Patch 9.0.1577
Problem: MS-Windows: context menu translations may be wrong.
Solution: Set the encoding before using gettext(). (Ken Takata,
closes #12441, closes #12431)
Files: src/GvimExt/Make_ming.mak, src/GvimExt/Make_mvc.mak,
src/GvimExt/gvimext.cpp, src/GvimExt/gvimext.h
*** ../vim-9.0.1576/src/GvimExt/Make_ming.mak 2022-11-02 13:30:37.526314510
+0000
--- src/GvimExt/Make_ming.mak 2023-05-25 16:39:16.898728119 +0100
***************
*** 43,51 ****
DEL = del
endif
endif
! # Set the default $(WINVER) to make it work with WinXP.
ifndef WINVER
! WINVER = 0x0501
endif
CXX := $(CROSS_COMPILE)g++
WINDRES := $(CROSS_COMPILE)windres
--- 43,51 ----
DEL = del
endif
endif
! # Set the default $(WINVER) to make it work with Windows 7.
ifndef WINVER
! WINVER = 0x0601
endif
CXX := $(CROSS_COMPILE)g++
WINDRES := $(CROSS_COMPILE)windres
*** ../vim-9.0.1576/src/GvimExt/Make_mvc.mak 2022-09-09 10:51:14.415772399
+0100
--- src/GvimExt/Make_mvc.mak 2023-05-25 16:39:16.898728119 +0100
***************
*** 8,17 ****
TARGETOS = WINNT
!ifndef APPVER
! APPVER = 5.01
!endif
!ifndef WINVER
! WINVER = 0x0501
!endif
!if "$(DEBUG)" != "yes"
--- 8,18 ----
TARGETOS = WINNT
!ifndef APPVER
! APPVER = 6.01
!endif
+ # Set the default $(WINVER) to make it work with Windows 7.
!ifndef WINVER
! WINVER = 0x0601
!endif
!if "$(DEBUG)" != "yes"
***************
*** 40,48 ****
!endif
!ifdef SDK_INCLUDE_DIR
! !include $(SDK_INCLUDE_DIR)\Win32.mak
!elseif "$(USE_WIN32MAK)"=="yes"
! !include <Win32.mak>
!else
cc = cl
link = link
--- 41,49 ----
!endif
!ifdef SDK_INCLUDE_DIR
! ! include $(SDK_INCLUDE_DIR)\Win32.mak
!elseif "$(USE_WIN32MAK)"=="yes"
! ! include <Win32.mak>
!else
cc = cl
link = link
*** ../vim-9.0.1576/src/GvimExt/gvimext.cpp 2021-12-22 15:12:38.000000000
+0000
--- src/GvimExt/gvimext.cpp 2023-05-25 16:39:16.898728119 +0100
***************
*** 130,162 ****
}
}
! HBITMAP IconToBitmap(HICON hIcon, HBRUSH hBackground, int width, int height)
{
! HDC hDC = GetDC(NULL);
! HDC hMemDC = CreateCompatibleDC(hDC);
! HBITMAP hMemBmp = CreateCompatibleBitmap(hDC, width, height);
! HBITMAP hResultBmp = NULL;
! HGDIOBJ hOrgBMP = SelectObject(hMemDC, hMemBmp);
!
! DrawIconEx(hMemDC, 0, 0, hIcon, width, height, 0, hBackground,
DI_NORMAL);
!
! hResultBmp = hMemBmp;
! hMemBmp = NULL;
!
! SelectObject(hMemDC, hOrgBMP);
! DeleteDC(hMemDC);
! ReleaseDC(NULL, hDC);
! DestroyIcon(hIcon);
! return hResultBmp;
}
//
// GETTEXT: translated messages and menu entries
//
#ifndef FEAT_GETTEXT
! # define _(x) x
#else
! # define _(x) (*dyn_libintl_gettext)(x)
# define VIMPACKAGE "vim"
# ifndef GETTEXT_DLL
# define GETTEXT_DLL "libintl.dll"
--- 130,177 ----
}
}
! WCHAR *
! utf8_to_utf16(const char *s)
{
! int size = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0);
! WCHAR *buf = (WCHAR *)malloc(size * sizeof(WCHAR));
! MultiByteToWideChar(CP_UTF8, 0, s, -1, buf, size);
! return buf;
! }
!
! HBITMAP
! IconToBitmap(HICON hIcon, HBRUSH hBackground, int width, int height)
! {
! HDC hDC = GetDC(NULL);
! HDC hMemDC = CreateCompatibleDC(hDC);
! HBITMAP hMemBmp = CreateCompatibleBitmap(hDC, width, height);
! HBITMAP hResultBmp = NULL;
! HGDIOBJ hOrgBMP = SelectObject(hMemDC, hMemBmp);
!
! DrawIconEx(hMemDC, 0, 0, hIcon, width, height, 0, hBackground, DI_NORMAL);
!
! hResultBmp = hMemBmp;
! hMemBmp = NULL;
!
! SelectObject(hMemDC, hOrgBMP);
! DeleteDC(hMemDC);
! ReleaseDC(NULL, hDC);
! DestroyIcon(hIcon);
! return hResultBmp;
}
//
// GETTEXT: translated messages and menu entries
//
#ifndef FEAT_GETTEXT
! # define _(x) x
! # define W_impl(x) _wcsdup(L##x)
! # define W(x) W_impl(x)
! # define set_gettext_codeset() NULL
! # define restore_gettext_codeset(x)
#else
! # define _(x) (*dyn_libintl_gettext)(x)
! # define W(x) utf8_to_utf16(x)
# define VIMPACKAGE "vim"
# ifndef GETTEXT_DLL
# define GETTEXT_DLL "libintl.dll"
***************
*** 167,172 ****
--- 182,188 ----
static char *null_libintl_gettext(const char *);
static char *null_libintl_textdomain(const char *);
static char *null_libintl_bindtextdomain(const char *, const char *);
+ static char *null_libintl_bind_textdomain_codeset(const char *, const char *);
static int dyn_libintl_init(char *dir);
static void dyn_libintl_end(void);
***************
*** 175,180 ****
--- 191,198 ----
static char *(*dyn_libintl_textdomain)(const char *) =
null_libintl_textdomain;
static char *(*dyn_libintl_bindtextdomain)(const char *, const char *)
= null_libintl_bindtextdomain;
+ static char *(*dyn_libintl_bind_textdomain_codeset)(const char *, const char
*)
+ = null_libintl_bind_textdomain_codeset;
//
// Attempt to load libintl.dll. If it doesn't work, use dummy functions.
***************
*** 194,199 ****
--- 212,218 ----
{(char *)"gettext", (FARPROC*)&dyn_libintl_gettext},
{(char *)"textdomain", (FARPROC*)&dyn_libintl_textdomain},
{(char *)"bindtextdomain", (FARPROC*)&dyn_libintl_bindtextdomain},
+ {(char *)"bind_textdomain_codeset",
(FARPROC*)&dyn_libintl_bind_textdomain_codeset},
{NULL, NULL}
};
DWORD len, len2;
***************
*** 254,259 ****
--- 273,279 ----
dyn_libintl_gettext = null_libintl_gettext;
dyn_libintl_textdomain = null_libintl_textdomain;
dyn_libintl_bindtextdomain = null_libintl_bindtextdomain;
+ dyn_libintl_bind_textdomain_codeset =
null_libintl_bind_textdomain_codeset;
}
static char *
***************
*** 263,275 ****
}
static char *
null_libintl_bindtextdomain(const char * /* domainname */, const char * /*
dirname */)
{
return NULL;
}
static char *
! null_libintl_textdomain(const char* /* domainname */)
{
return NULL;
}
--- 283,301 ----
}
static char *
+ null_libintl_textdomain(const char * /* domainname */)
+ {
+ return NULL;
+ }
+
+ static char *
null_libintl_bindtextdomain(const char * /* domainname */, const char * /*
dirname */)
{
return NULL;
}
static char *
! null_libintl_bind_textdomain_codeset(const char * /* domainname */, const
char * /* codeset */)
{
return NULL;
}
***************
*** 304,309 ****
--- 330,358 ----
{
dyn_libintl_end();
}
+
+ //
+ // Use UTF-8 for gettext. Returns previous codeset.
+ //
+ static char *
+ set_gettext_codeset(void)
+ {
+ char *prev = dyn_libintl_bind_textdomain_codeset(VIMPACKAGE, NULL);
+ prev = _strdup((prev != NULL) ? prev : "char");
+ dyn_libintl_bind_textdomain_codeset(VIMPACKAGE, "utf-8");
+
+ return prev;
+ }
+
+ //
+ // Restore previous codeset for gettext.
+ //
+ static void
+ restore_gettext_codeset(char *prev)
+ {
+ dyn_libintl_bind_textdomain_codeset(VIMPACKAGE, prev);
+ free(prev);
+ }
#endif // FEAT_GETTEXT
//
***************
*** 583,589 ****
hres = m_pDataObj->GetData(&fmte, &medium);
if (medium.hGlobal)
! cbFiles = DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, 0, 0);
// InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL);
--- 632,638 ----
hres = m_pDataObj->GetData(&fmte, &medium);
if (medium.hGlobal)
! cbFiles = DragQueryFileW((HDROP)medium.hGlobal, (UINT)-1, 0, 0);
// InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL);
***************
*** 607,617 ****
RegCloseKey(keyhandle);
}
// Retrieve all the vim instances, unless disabled.
if (showExisting)
EnumWindows(EnumWindowsProc, (LPARAM)this);
! MENUITEMINFO mii = { sizeof(MENUITEMINFO) };
mii.fMask = MIIM_STRING | MIIM_ID;
if (showIcons)
{
--- 656,669 ----
RegCloseKey(keyhandle);
}
+ // Use UTF-8 for gettext.
+ char *prev = set_gettext_codeset();
+
// Retrieve all the vim instances, unless disabled.
if (showExisting)
EnumWindows(EnumWindowsProc, (LPARAM)this);
! MENUITEMINFOW mii = { sizeof(MENUITEMINFOW) };
mii.fMask = MIIM_STRING | MIIM_ID;
if (showIcons)
{
***************
*** 622,643 ****
if (cbFiles > 1)
{
mii.wID = idCmd++;
! mii.dwTypeData = _("Edit with Vim using &tabpages");
! mii.cch = lstrlen(mii.dwTypeData);
! InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
mii.wID = idCmd++;
! mii.dwTypeData = _("Edit with single &Vim");
! mii.cch = lstrlen(mii.dwTypeData);
! InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
if (cbFiles <= 4)
{
// Can edit up to 4 files in diff mode
mii.wID = idCmd++;
! mii.dwTypeData = _("Diff with Vim");
! mii.cch = lstrlen(mii.dwTypeData);
! InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
m_edit_existing_off = 3;
}
else
--- 674,698 ----
if (cbFiles > 1)
{
mii.wID = idCmd++;
! mii.dwTypeData = W(_("Edit with Vim using &tabpages"));
! mii.cch = wcslen(mii.dwTypeData);
! InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii);
! free(mii.dwTypeData);
mii.wID = idCmd++;
! mii.dwTypeData = W(_("Edit with single &Vim"));
! mii.cch = wcslen(mii.dwTypeData);
! InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii);
! free(mii.dwTypeData);
if (cbFiles <= 4)
{
// Can edit up to 4 files in diff mode
mii.wID = idCmd++;
! mii.dwTypeData = W(_("Diff with Vim"));
! mii.cch = wcslen(mii.dwTypeData);
! InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii);
! free(mii.dwTypeData);
m_edit_existing_off = 3;
}
else
***************
*** 647,655 ****
else
{
mii.wID = idCmd++;
! mii.dwTypeData = _("Edit with &Vim");
! mii.cch = lstrlen(mii.dwTypeData);
! InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
m_edit_existing_off = 1;
}
--- 702,711 ----
else
{
mii.wID = idCmd++;
! mii.dwTypeData = W(_("Edit with &Vim"));
! mii.cch = wcslen(mii.dwTypeData);
! InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii);
! free(mii.dwTypeData);
m_edit_existing_off = 1;
}
***************
*** 659,704 ****
hSubMenu = CreatePopupMenu();
mii.fMask |= MIIM_SUBMENU;
mii.wID = idCmd;
! mii.dwTypeData = _("Edit with existing Vim");
! mii.cch = lstrlen(mii.dwTypeData);
mii.hSubMenu = hSubMenu;
! InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
mii.fMask = mii.fMask & ~MIIM_SUBMENU;
mii.hSubMenu = NULL;
}
// Now display all the vim instances
for (int i = 0; i < m_cntOfHWnd; i++)
{
! char title[BUFSIZE];
! char temp[BUFSIZE];
int index;
HMENU hmenu;
// Obtain window title, continue if can not
! if (GetWindowText(m_hWnd[i], title, BUFSIZE - 1) == 0)
continue;
// Truncate the title before the path, keep the file name
! char *pos = strchr(title, '(');
if (pos != NULL)
{
! if (pos > title && pos[-1] == ' ')
--pos;
*pos = 0;
}
// Now concatenate
if (m_cntOfHWnd > 1)
! temp[0] = '\0';
else
{
! strncpy(temp, _("Edit with existing Vim - "), BUFSIZE - 1);
! temp[BUFSIZE - 1] = '\0';
}
! strncat(temp, title, BUFSIZE - 1 - strlen(temp));
! temp[BUFSIZE - 1] = '\0';
mii.wID = idCmd++;
mii.dwTypeData = temp;
! mii.cch = lstrlen(mii.dwTypeData);
if (m_cntOfHWnd > 1)
{
hmenu = hSubMenu;
--- 715,763 ----
hSubMenu = CreatePopupMenu();
mii.fMask |= MIIM_SUBMENU;
mii.wID = idCmd;
! mii.dwTypeData = W(_("Edit with existing Vim"));
! mii.cch = wcslen(mii.dwTypeData);
mii.hSubMenu = hSubMenu;
! InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii);
! free(mii.dwTypeData);
mii.fMask = mii.fMask & ~MIIM_SUBMENU;
mii.hSubMenu = NULL;
}
// Now display all the vim instances
for (int i = 0; i < m_cntOfHWnd; i++)
{
! WCHAR title[BUFSIZE];
! WCHAR temp[BUFSIZE];
int index;
HMENU hmenu;
// Obtain window title, continue if can not
! if (GetWindowTextW(m_hWnd[i], title, BUFSIZE - 1) == 0)
continue;
// Truncate the title before the path, keep the file name
! WCHAR *pos = wcschr(title, L'(');
if (pos != NULL)
{
! if (pos > title && pos[-1] == L' ')
--pos;
*pos = 0;
}
// Now concatenate
if (m_cntOfHWnd > 1)
! temp[0] = L'\0';
else
{
! WCHAR *s = W(_("Edit with existing Vim - "));
! wcsncpy(temp, s, BUFSIZE - 1);
! temp[BUFSIZE - 1] = L'\0';
! free(s);
}
! wcsncat(temp, title, BUFSIZE - 1 - wcslen(temp));
! temp[BUFSIZE - 1] = L'\0';
mii.wID = idCmd++;
mii.dwTypeData = temp;
! mii.cch = wcslen(mii.dwTypeData);
if (m_cntOfHWnd > 1)
{
hmenu = hSubMenu;
***************
*** 709,718 ****
hmenu = hMenu;
index = indexMenu++;
}
! InsertMenuItem(hmenu, index, TRUE, &mii);
}
// InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL);
// Must return number of menu items we added.
return ResultFromShort(idCmd-idCmdFirst);
}
--- 768,780 ----
hmenu = hMenu;
index = indexMenu++;
}
! InsertMenuItemW(hmenu, index, TRUE, &mii);
}
// InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL);
+ // Restore previous codeset.
+ restore_gettext_codeset(prev);
+
// Must return number of menu items we added.
return ResultFromShort(idCmd-idCmdFirst);
}
***************
*** 819,826 ****
LPSTR pszName,
UINT cchMax)
{
! if (uFlags == GCS_HELPTEXT && cchMax > 35)
! lstrcpy(pszName, _("Edits the selected file(s) with Vim"));
return NOERROR;
}
--- 881,896 ----
LPSTR pszName,
UINT cchMax)
{
! // Use UTF-8 for gettext.
! char *prev = set_gettext_codeset();
!
! WCHAR *s = W(_("Edits the selected file(s) with Vim"));
! if (uFlags == GCS_HELPTEXTW && cchMax > wcslen(s))
! wcscpy((WCHAR *)pszName, s);
! free(s);
!
! // Restore previous codeset.
! restore_gettext_codeset(prev);
return NOERROR;
}
***************
*** 831,837 ****
// First do a bunch of check
// No invisible window
! if (!IsWindowVisible(hWnd)) return TRUE;
// No child window ???
// if (GetParent(hWnd)) return TRUE;
// Class name should be Vim, if failed to get class name, return
--- 901,908 ----
// First do a bunch of check
// No invisible window
! if (!IsWindowVisible(hWnd))
! return TRUE;
// No child window ???
// if (GetParent(hWnd)) return TRUE;
// Class name should be Vim, if failed to get class name, return
***************
*** 842,848 ****
return TRUE;
// First check if the number of vim instance exceeds MAX_HWND
CShellExt *cs = (CShellExt*) lParam;
! if (cs->m_cntOfHWnd >= MAX_HWND) return TRUE;
// Now we get the vim window, put it into some kind of array
cs->m_hWnd[cs->m_cntOfHWnd] = hWnd;
cs->m_cntOfHWnd ++;
--- 913,920 ----
return TRUE;
// First check if the number of vim instance exceeds MAX_HWND
CShellExt *cs = (CShellExt*) lParam;
! if (cs->m_cntOfHWnd >= MAX_HWND)
! return FALSE; // stop enumeration
// Now we get the vim window, put it into some kind of array
cs->m_hWnd[cs->m_cntOfHWnd] = hWnd;
cs->m_cntOfHWnd ++;
***************
*** 852,869 ****
BOOL CShellExt::LoadMenuIcon()
{
! char vimExeFile[BUFSIZE];
! getGvimName(vimExeFile, 1);
! if (vimExeFile[0] == '\0')
! return FALSE;
! HICON hVimIcon;
! if (ExtractIconEx(vimExeFile, 0, NULL, &hVimIcon, 1) == 0)
! return FALSE;
! m_hVimIconBitmap = IconToBitmap(hVimIcon,
! GetSysColorBrush(COLOR_MENU),
! GetSystemMetrics(SM_CXSMICON),
! GetSystemMetrics(SM_CYSMICON));
! return TRUE;
}
static char *
--- 924,941 ----
BOOL CShellExt::LoadMenuIcon()
{
! char vimExeFile[BUFSIZE];
! getGvimName(vimExeFile, 1);
! if (vimExeFile[0] == '\0')
! return FALSE;
! HICON hVimIcon;
! if (ExtractIconEx(vimExeFile, 0, NULL, &hVimIcon, 1) == 0)
! return FALSE;
! m_hVimIconBitmap = IconToBitmap(hVimIcon,
! GetSysColorBrush(COLOR_MENU),
! GetSystemMetrics(SM_CXSMICON),
! GetSystemMetrics(SM_CYSMICON));
! return TRUE;
}
static char *
***************
*** 948,963 ****
FALSE, // Set handle inheritance to FALSE.
0, // No creation flags.
NULL, // Use parent's environment block.
! workingDir, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi) // Pointer to PROCESS_INFORMATION structure.
)
{
! MessageBox(
! hParent,
! _("Error creating process: Check if gvim is in your path!"),
! _("gvimext.dll error"),
! MB_OK);
}
else
{
--- 1020,1043 ----
FALSE, // Set handle inheritance to FALSE.
0, // No creation flags.
NULL, // Use parent's environment block.
! workingDir, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi) // Pointer to PROCESS_INFORMATION structure.
)
{
! // Use UTF-8 for gettext.
! char *prev = set_gettext_codeset();
!
! WCHAR *msg = W(_("Error creating process: Check if gvim is in your
path!"));
! WCHAR *title = W(_("gvimext.dll error"));
!
! MessageBoxW(hParent, msg, title, MB_OK);
!
! free(msg);
! free(title);
!
! // Restore previous codeset.
! restore_gettext_codeset(prev);
}
else
{
*** ../vim-9.0.1576/src/GvimExt/gvimext.h 2022-01-24 11:12:27.000000000
+0000
--- src/GvimExt/gvimext.h 2023-05-25 16:39:16.898728119 +0100
***************
*** 81,101 ****
class CShellExtClassFactory : public IClassFactory
{
protected:
! ULONG m_cRef;
public:
! CShellExtClassFactory();
! ~CShellExtClassFactory();
! //IUnknown members
! STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *);
! STDMETHODIMP_(ULONG) AddRef();
! STDMETHODIMP_(ULONG) Release();
!
! //IClassFactory members
! STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR *);
! STDMETHODIMP LockServer(BOOL);
};
typedef CShellExtClassFactory *LPCSHELLEXTCLASSFACTORY;
#define MAX_HWND 100
--- 81,100 ----
class CShellExtClassFactory : public IClassFactory
{
protected:
! ULONG m_cRef;
public:
! CShellExtClassFactory();
! ~CShellExtClassFactory();
! //IUnknown members
! STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *);
! STDMETHODIMP_(ULONG) AddRef();
! STDMETHODIMP_(ULONG) Release();
+ //IClassFactory members
+ STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR *);
+ STDMETHODIMP LockServer(BOOL);
};
typedef CShellExtClassFactory *LPCSHELLEXTCLASSFACTORY;
#define MAX_HWND 100
*** ../vim-9.0.1576/src/version.c 2023-05-24 21:02:20.489162125 +0100
--- src/version.c 2023-05-25 16:41:22.770738804 +0100
***************
*** 697,698 ****
--- 697,700 ----
{ /* Add new patch number below this line */
+ /**/
+ 1577,
/**/
--
hundred-and-one symptoms of being an internet addict:
75. You start wondering whether you could actually upgrade your brain
with a Pentium Pro microprocessor 80. The upgrade works just fine.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/20230525154352.7F3FB1C091C%40moolenaar.net.