mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
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)
This commit is contained in:
43
src/mbyte.c
43
src/mbyte.c
@@ -4583,47 +4583,6 @@ static HINSTANCE hMsvcrtDLL = 0;
|
||||
# define DYNAMIC_MSVCRT_DLL "msvcrt.dll"
|
||||
# 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.
|
||||
*/
|
||||
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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 char *, const char *, unsigned long n);
|
||||
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)(const char *, const char *)
|
||||
= 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 *domainname)
|
||||
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++ */
|
||||
|
@@ -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);
|
||||
|
@@ -764,6 +764,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
175,
|
||||
/**/
|
||||
174,
|
||||
/**/
|
||||
|
@@ -574,6 +574,7 @@ extern char *(*dyn_libintl_ngettext)(const char *msgid, const char *msgid_plural
|
||||
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)(const char *domainname);
|
||||
# define HAVE_BIND_TEXTDOMAIN_CODESET 1
|
||||
# endif
|
||||
# define textdomain(domain) (*dyn_libintl_textdomain)(domain)
|
||||
# define libintl_putenv(envstring) (*dyn_libintl_putenv)(envstring)
|
||||
# else
|
||||
# include <libintl.h>
|
||||
# define _(x) gettext((char *)(x))
|
||||
|
Reference in New Issue
Block a user