To: [email protected]
Subject: Patch 6.3a.013 (extra)
Fcc: outbox
From: Bram Moolenaar <[email protected]>
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 -- [email protected] -- 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 ///