# HG changeset patch # User Christian Brabandt # Date 1484253904 -3600 # Node ID b726d3ea70bc23cbeb62442f4520b4f559c8da6b # Parent 33f9dbbfb7e5319f43357c5e2486fd07d83edb10 patch 8.0.0175: setting language on MS-Windows does not always work commit https://github.com/vim/vim/commit/972c3b8f1b50e2f887a397c324af99eb354aad0b Author: Bram Moolenaar Date: Thu Jan 12 21:44:49 2017 +0100 patch 8.0.0175: setting language on MS-Windows does not always work Problem: Setting language in gvim on MS-Windows does not work when libintl.dll is dynamically linked with msvcrt.dll. Solution: Use putenv() from libintl as well. (Ken Takata, closes #1082) diff --git a/src/mbyte.c b/src/mbyte.c --- a/src/mbyte.c +++ b/src/mbyte.c @@ -4584,47 +4584,6 @@ static HINSTANCE hMsvcrtDLL = 0; # endif /* - * Get the address of 'funcname' which is imported by 'hInst' DLL. - */ - static void * -get_iconv_import_func(HINSTANCE hInst, const char *funcname) -{ - PBYTE pImage = (PBYTE)hInst; - PIMAGE_DOS_HEADER pDOS = (PIMAGE_DOS_HEADER)hInst; - PIMAGE_NT_HEADERS pPE; - PIMAGE_IMPORT_DESCRIPTOR pImpDesc; - PIMAGE_THUNK_DATA pIAT; /* Import Address Table */ - PIMAGE_THUNK_DATA pINT; /* Import Name Table */ - PIMAGE_IMPORT_BY_NAME pImpName; - - if (pDOS->e_magic != IMAGE_DOS_SIGNATURE) - return NULL; - pPE = (PIMAGE_NT_HEADERS)(pImage + pDOS->e_lfanew); - if (pPE->Signature != IMAGE_NT_SIGNATURE) - return NULL; - pImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pImage - + pPE->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] - .VirtualAddress); - for (; pImpDesc->FirstThunk; ++pImpDesc) - { - if (!pImpDesc->OriginalFirstThunk) - continue; - pIAT = (PIMAGE_THUNK_DATA)(pImage + pImpDesc->FirstThunk); - pINT = (PIMAGE_THUNK_DATA)(pImage + pImpDesc->OriginalFirstThunk); - for (; pIAT->u1.Function; ++pIAT, ++pINT) - { - if (IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal)) - continue; - pImpName = (PIMAGE_IMPORT_BY_NAME)(pImage - + (UINT_PTR)(pINT->u1.AddressOfData)); - if (strcmp((char *)pImpName->Name, funcname) == 0) - return (void *)pIAT->u1.Function; - } - } - return NULL; -} - -/* * Try opening the iconv.dll and return TRUE if iconv() can be used. */ int @@ -4671,7 +4630,7 @@ iconv_enabled(int verbose) iconv_open = (void *)GetProcAddress(hIconvDLL, "libiconv_open"); iconv_close = (void *)GetProcAddress(hIconvDLL, "libiconv_close"); iconvctl = (void *)GetProcAddress(hIconvDLL, "libiconvctl"); - iconv_errno = get_iconv_import_func(hIconvDLL, "_errno"); + iconv_errno = get_dll_import_func(hIconvDLL, "_errno"); if (iconv_errno == NULL) iconv_errno = (void *)GetProcAddress(hMsvcrtDLL, "_errno"); if (iconv == NULL || iconv_open == NULL || iconv_close == NULL diff --git a/src/misc1.c b/src/misc1.c --- a/src/misc1.c +++ b/src/misc1.c @@ -4455,6 +4455,9 @@ vim_setenv(char_u *name, char_u *val) { sprintf((char *)envbuf, "%s=%s", name, val); putenv((char *)envbuf); +# ifdef libintl_putenv + libintl_putenv((char *)envbuf); +# endif } #endif #ifdef FEAT_GETTEXT diff --git a/src/os_win32.c b/src/os_win32.c --- a/src/os_win32.c +++ b/src/os_win32.c @@ -425,6 +425,84 @@ vimLoadLib(char *name) return dll; } +#if defined(DYNAMIC_ICONV) || defined(DYNAMIC_GETTEXT) || defined(PROTO) +/* + * Get related information about 'funcname' which is imported by 'hInst'. + * If 'info' is 0, return the function address. + * If 'info' is 1, return the module name which the function is imported from. + */ + static void * +get_imported_func_info(HINSTANCE hInst, const char *funcname, int info) +{ + PBYTE pImage = (PBYTE)hInst; + PIMAGE_DOS_HEADER pDOS = (PIMAGE_DOS_HEADER)hInst; + PIMAGE_NT_HEADERS pPE; + PIMAGE_IMPORT_DESCRIPTOR pImpDesc; + PIMAGE_THUNK_DATA pIAT; /* Import Address Table */ + PIMAGE_THUNK_DATA pINT; /* Import Name Table */ + PIMAGE_IMPORT_BY_NAME pImpName; + + if (pDOS->e_magic != IMAGE_DOS_SIGNATURE) + return NULL; + pPE = (PIMAGE_NT_HEADERS)(pImage + pDOS->e_lfanew); + if (pPE->Signature != IMAGE_NT_SIGNATURE) + return NULL; + pImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pImage + + pPE->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] + .VirtualAddress); + for (; pImpDesc->FirstThunk; ++pImpDesc) + { + if (!pImpDesc->OriginalFirstThunk) + continue; + pIAT = (PIMAGE_THUNK_DATA)(pImage + pImpDesc->FirstThunk); + pINT = (PIMAGE_THUNK_DATA)(pImage + pImpDesc->OriginalFirstThunk); + for (; pIAT->u1.Function; ++pIAT, ++pINT) + { + if (IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal)) + continue; + pImpName = (PIMAGE_IMPORT_BY_NAME)(pImage + + (UINT_PTR)(pINT->u1.AddressOfData)); + if (strcmp((char *)pImpName->Name, funcname) == 0) + { + switch (info) + { + case 0: + return (void *)pIAT->u1.Function; + case 1: + return (void *)(pImage + pImpDesc->Name); + default: + return NULL; + } + } + } + } + return NULL; +} + +/* + * Get the module handle which 'funcname' in 'hInst' is imported from. + */ + HINSTANCE +find_imported_module_by_funcname(HINSTANCE hInst, const char *funcname) +{ + char *modulename; + + modulename = (char *)get_imported_func_info(hInst, funcname, 1); + if (modulename != NULL) + return GetModuleHandleA(modulename); + return NULL; +} + +/* + * Get the address of 'funcname' which is imported by 'hInst' DLL. + */ + void * +get_dll_import_func(HINSTANCE hInst, const char *funcname) +{ + return get_imported_func_info(hInst, funcname, 0); +} +#endif + #if defined(DYNAMIC_GETTEXT) || defined(PROTO) # ifndef GETTEXT_DLL # define GETTEXT_DLL "libintl.dll" @@ -436,6 +514,7 @@ static char *null_libintl_ngettext(const 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 null_libintl_putenv(const char *); static HINSTANCE hLibintlDLL = NULL; char *(*dyn_libintl_gettext)(const char *) = null_libintl_gettext; @@ -446,6 +525,7 @@ char *(*dyn_libintl_bindtextdomain)(cons = null_libintl_bindtextdomain; char *(*dyn_libintl_bind_textdomain_codeset)(const char *, const char *) = null_libintl_bind_textdomain_codeset; +int (*dyn_libintl_putenv)(const char *) = null_libintl_putenv; int dyn_libintl_init(void) @@ -463,6 +543,7 @@ dyn_libintl_init(void) {"bindtextdomain", (FARPROC*)&dyn_libintl_bindtextdomain}, {NULL, NULL} }; + HINSTANCE hmsvcrt; /* No need to initialize twice. */ if (hLibintlDLL) @@ -507,6 +588,13 @@ dyn_libintl_init(void) dyn_libintl_bind_textdomain_codeset = null_libintl_bind_textdomain_codeset; + /* _putenv() function for the libintl.dll is optional. */ + hmsvcrt = find_imported_module_by_funcname(hLibintlDLL, "getenv"); + if (hmsvcrt != NULL) + dyn_libintl_putenv = (void *)GetProcAddress(hmsvcrt, "_putenv"); + if (dyn_libintl_putenv == NULL || dyn_libintl_putenv == putenv) + dyn_libintl_putenv = null_libintl_putenv; + return 1; } @@ -521,6 +609,7 @@ dyn_libintl_end(void) dyn_libintl_textdomain = null_libintl_textdomain; dyn_libintl_bindtextdomain = null_libintl_bindtextdomain; dyn_libintl_bind_textdomain_codeset = null_libintl_bind_textdomain_codeset; + dyn_libintl_putenv = null_libintl_putenv; } /*ARGSUSED*/ @@ -562,6 +651,13 @@ null_libintl_textdomain(const char *doma return NULL; } +/*ARGSUSED*/ + int +null_libintl_putenv(const char *envstring) +{ + return 0; +} + #endif /* DYNAMIC_GETTEXT */ /* This symbol is not defined in older versions of the SDK or Visual C++ */ @@ -4781,32 +4877,32 @@ mch_call_shell( #if defined(FEAT_JOB_CHANNEL) || defined(PROTO) static HANDLE job_io_file_open( - char_u *fname, - DWORD dwDesiredAccess, - DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreationDisposition, - DWORD dwFlagsAndAttributes) + char_u *fname, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes) { HANDLE h; # ifdef FEAT_MBYTE WCHAR *wn = NULL; if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) { - wn = enc_to_utf16(fname, NULL); - if (wn != NULL) - { - h = CreateFileW(wn, dwDesiredAccess, dwShareMode, - lpSecurityAttributes, dwCreationDisposition, - dwFlagsAndAttributes, NULL); - vim_free(wn); - } + wn = enc_to_utf16(fname, NULL); + if (wn != NULL) + { + h = CreateFileW(wn, dwDesiredAccess, dwShareMode, + lpSecurityAttributes, dwCreationDisposition, + dwFlagsAndAttributes, NULL); + vim_free(wn); + } } if (wn == NULL) # endif - h = CreateFile((LPCSTR)fname, dwDesiredAccess, dwShareMode, - lpSecurityAttributes, dwCreationDisposition, - dwFlagsAndAttributes, NULL); + h = CreateFile((LPCSTR)fname, dwDesiredAccess, dwShareMode, + lpSecurityAttributes, dwCreationDisposition, + dwFlagsAndAttributes, NULL); return h; } diff --git a/src/proto/os_win32.pro b/src/proto/os_win32.pro --- a/src/proto/os_win32.pro +++ b/src/proto/os_win32.pro @@ -1,5 +1,7 @@ /* os_win32.c */ HINSTANCE vimLoadLib(char *name); +HINSTANCE find_imported_module_by_funcname(HINSTANCE hInst, const char *funcname); +void *get_dll_import_func(HINSTANCE hInst, const char *funcname); int dyn_libintl_init(void); void dyn_libintl_end(void); void PlatformId(void); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -765,6 +765,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 175, +/**/ 174, /**/ 173, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -574,6 +574,7 @@ extern char *(*dyn_libintl_ngettext)(con extern char *(*dyn_libintl_bindtextdomain)(const char *domainname, const char *dirname); extern char *(*dyn_libintl_bind_textdomain_codeset)(const char *domainname, const char *codeset); extern char *(*dyn_libintl_textdomain)(const char *domainname); +extern int (*dyn_libintl_putenv)(const char *envstring); #endif @@ -592,6 +593,7 @@ extern char *(*dyn_libintl_textdomain)(c # define HAVE_BIND_TEXTDOMAIN_CODESET 1 # endif # define textdomain(domain) (*dyn_libintl_textdomain)(domain) +# define libintl_putenv(envstring) (*dyn_libintl_putenv)(envstring) # else # include # define _(x) gettext((char *)(x))