To: vim-dev@vim.org Subject: Patch 6.3a.013 (extra) Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ Patch 6.3a.013 (extra) Problem: Win32: Characters in the menu that are not in the active codepage are garbled. Solution: Convert menu strings from 'encoding' to the active codepage. Files: src/gui_w32.c, src/gui_w48.c *** ../vim-6.3a.012/src/gui_w32.c Tue May 11 22:32:13 2004 --- src/gui_w32.c Wed May 12 15:42:30 2004 *************** *** 2020,2037 **** } else { ! MENUITEMINFO info; ! info.cbSize = sizeof(info); ! info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID | MIIM_SUBMENU; ! info.dwItemData = (DWORD)menu; ! info.wID = menu->id; ! info.fType = MFT_STRING; ! info.dwTypeData = (LPTSTR)menu->name; ! info.cch = (UINT)STRLEN(menu->name); ! info.hSubMenu = menu->submenu_id; ! InsertMenuItem((parent == NULL) ? s_menuBar : parent->submenu_id, ! (UINT)pos, TRUE, &info); } } --- 2020,2074 ---- } else { ! #ifdef FEAT_MBYTE ! WCHAR *wn = NULL; ! int n; ! ! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) ! { ! /* 'encoding' differs from active codepage: convert menu name ! * and use wide function */ ! wn = enc_to_ucs2(menu->name, NULL); ! if (wn != NULL) ! { ! MENUITEMINFOW infow; ! ! infow.cbSize = sizeof(infow); ! infow.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID ! | MIIM_SUBMENU; ! infow.dwItemData = (DWORD)menu; ! infow.wID = menu->id; ! infow.fType = MFT_STRING; ! infow.dwTypeData = wn; ! infow.cch = wcslen(wn); ! infow.hSubMenu = menu->submenu_id; ! n = InsertMenuItemW((parent == NULL) ! ? s_menuBar : parent->submenu_id, ! (UINT)pos, TRUE, &infow); ! vim_free(wn); ! if (n == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) ! /* Failed, try using non-wide function. */ ! wn = NULL; ! } ! } ! ! if (wn == NULL) ! #endif ! { ! MENUITEMINFO info; ! info.cbSize = sizeof(info); ! info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_ID | MIIM_SUBMENU; ! info.dwItemData = (DWORD)menu; ! info.wID = menu->id; ! info.fType = MFT_STRING; ! info.dwTypeData = (LPTSTR)menu->name; ! info.cch = (UINT)STRLEN(menu->name); ! info.hSubMenu = menu->submenu_id; ! InsertMenuItem((parent == NULL) ! ? s_menuBar : parent->submenu_id, ! (UINT)pos, TRUE, &info); ! } } } *************** *** 2137,2143 **** else #endif { ! InsertMenu(parent->submenu_id, (UINT)idx, (menu_is_separator(menu->name) ? MF_SEPARATOR : MF_STRING) | MF_BYPOSITION, (UINT)menu->id, (LPCTSTR)menu->name); --- 2174,2203 ---- else #endif { ! #ifdef FEAT_MBYTE ! WCHAR *wn = NULL; ! int n; ! ! if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) ! { ! /* 'encoding' differs from active codepage: convert menu item name ! * and use wide function */ ! wn = enc_to_ucs2(menu->name, NULL); ! if (wn != NULL) ! { ! n = InsertMenuW(parent->submenu_id, (UINT)idx, ! (menu_is_separator(menu->name) ! ? MF_SEPARATOR : MF_STRING) | MF_BYPOSITION, ! (UINT)menu->id, wn); ! vim_free(wn); ! if (n == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) ! /* Failed, try using non-wide function. */ ! wn = NULL; ! } ! } ! if (wn == NULL) ! #endif ! InsertMenu(parent->submenu_id, (UINT)idx, (menu_is_separator(menu->name) ? MF_SEPARATOR : MF_STRING) | MF_BYPOSITION, (UINT)menu->id, (LPCTSTR)menu->name); *************** *** 2875,2891 **** LPWORD lpWCStr, LPSTR lpAnsiIn) { ! int nChar = 0; ! #ifdef FEAT_MBYTE ! int len = lstrlen(lpAnsiIn) + 1; /* include NUL character */ ! int i; ! ! nChar = MultiByteToWideChar( ! CP_ACP, ! MB_PRECOMPOSED, ! lpAnsiIn, len, ! lpWCStr, len); for (i = 0; i < nChar; ++i) if (lpWCStr[i] == (WORD)'\t') /* replace tabs with spaces */ lpWCStr[i] = (WORD)' '; --- 2935,2964 ---- LPWORD lpWCStr, LPSTR lpAnsiIn) { ! int nChar = 0; #ifdef FEAT_MBYTE ! int len = lstrlen(lpAnsiIn) + 1; /* include NUL character */ ! int i; ! WCHAR *wn; ! ! if (enc_codepage == 0 && (int)GetACP() != enc_codepage) ! { ! /* Not a codepage, use our own conversion function. */ ! wn = enc_to_ucs2(lpAnsiIn, NULL); ! if (wn != NULL) ! { ! wcscpy(lpWCStr, wn); ! nChar = wcslen(wn) + 1; ! vim_free(wn); ! } ! } ! if (nChar == 0) ! /* Use Win32 conversion function. */ ! nChar = MultiByteToWideChar( ! enc_codepage > 0 ? enc_codepage : CP_ACP, ! MB_PRECOMPOSED, ! lpAnsiIn, len, ! lpWCStr, len); for (i = 0; i < nChar; ++i) if (lpWCStr[i] == (WORD)'\t') /* replace tabs with spaces */ lpWCStr[i] = (WORD)' '; *************** *** 3128,3134 **** text = (col == 0) ? pmenu->dname : pmenu->actext; if (text != NULL && *text != NUL) { ! textWidth = GetTextWidth(hdc, text, (int)STRLEN(text)); if (textWidth > columnWidths[col]) columnWidths[col] = textWidth; } --- 3201,3207 ---- text = (col == 0) ? pmenu->dname : pmenu->actext; if (text != NULL && *text != NUL) { ! textWidth = GetTextWidthEnc(hdc, text, (int)STRLEN(text)); if (textWidth > columnWidths[col]) columnWidths[col] = textWidth; } *************** *** 3161,3167 **** (int)STRLEN(TEAROFF_SUBMENU_LABEL)); textWidth += submenuWidth; } ! dlgwidth = GetTextWidth(hdc, title, (int)STRLEN(title)); if (textWidth > dlgwidth) dlgwidth = textWidth; dlgwidth += 2 * TEAROFF_PADDING_X + TEAROFF_BUTTON_PAD_X; --- 3234,3240 ---- (int)STRLEN(TEAROFF_SUBMENU_LABEL)); textWidth += submenuWidth; } ! dlgwidth = GetTextWidthEnc(hdc, title, (int)STRLEN(title)); if (textWidth > dlgwidth) dlgwidth = textWidth; dlgwidth += 2 * TEAROFF_PADDING_X + TEAROFF_BUTTON_PAD_X; *************** *** 3265,3271 **** * actual text, "dname" for estimating the displayed size. "name" * has "&a" for mnemonic and includes the accelerator. */ len = nameLen = (int)STRLEN(menu->name); ! padding0 = (columnWidths[0] - GetTextWidth(hdc, menu->dname, (int)STRLEN(menu->dname))) / spaceWidth; len += padding0; --- 3338,3344 ---- * actual text, "dname" for estimating the displayed size. "name" * has "&a" for mnemonic and includes the accelerator. */ len = nameLen = (int)STRLEN(menu->name); ! padding0 = (columnWidths[0] - GetTextWidthEnc(hdc, menu->dname, (int)STRLEN(menu->dname))) / spaceWidth; len += padding0; *************** *** 3273,3279 **** { acLen = (int)STRLEN(menu->actext); len += acLen; ! textWidth = GetTextWidth(hdc, menu->actext, acLen); } else textWidth = 0; --- 3346,3352 ---- { acLen = (int)STRLEN(menu->actext); len += acLen; ! textWidth = GetTextWidthEnc(hdc, menu->actext, acLen); } else textWidth = 0; *** ../vim-6.3a.012/src/gui_w48.c Tue May 11 22:32:13 2004 --- src/gui_w48.c Wed May 12 15:56:09 2004 *************** *** 1959,1964 **** --- 1959,1997 ---- return size.cx; } + #ifdef FEAT_MBYTE + /* + * Return the width in pixels of the given text in the given DC, taking care + * of 'encoding' to active codepage conversion. + */ + static int + GetTextWidthEnc(HDC hdc, char_u *str, int len) + { + SIZE size; + WCHAR *wstr; + int n; + int wlen = len; + + if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) + { + /* 'encoding' differs from active codepage: convert text and use wide + * function */ + wstr = enc_to_ucs2(str, &wlen); + if (wstr != NULL) + { + n = GetTextExtentPointW(hdc, wstr, wlen, &size); + vim_free(wstr); + if (n) + return size.cx; + } + } + + return GetTextWidth(hdc, str, len); + } + #else + # define GetTextWidthEnc(h, s, l) GetTextWidth((h), (s), (l)) + #endif + /* * A quick little routine that will center one window over another, handy for * dialog boxes. Taken from the Win32SDK samples. *** ../vim-6.3a.012/src/version.c Wed May 12 14:16:11 2004 --- src/version.c Wed May 12 16:55:44 2004 *************** *** 643,644 **** --- 643,646 ---- { /* Add new patch number below this line */ + /**/ + 13, /**/ -- hundred-and-one symptoms of being an internet addict: 269. You wonder how you can make your dustbin produce Sesame Street's Oscar's the Garbage Monster song when you empty it. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// Sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ Project leader for A-A-P -- http://www.A-A-P.org /// \\\ Buy at Amazon and help AIDS victims -- http://ICCF.nl/click1.html ///