forked from aniani/vim
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"
|
# define DYNAMIC_MSVCRT_DLL "msvcrt.dll"
|
||||||
# endif
|
# 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.
|
* 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_open = (void *)GetProcAddress(hIconvDLL, "libiconv_open");
|
||||||
iconv_close = (void *)GetProcAddress(hIconvDLL, "libiconv_close");
|
iconv_close = (void *)GetProcAddress(hIconvDLL, "libiconv_close");
|
||||||
iconvctl = (void *)GetProcAddress(hIconvDLL, "libiconvctl");
|
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)
|
if (iconv_errno == NULL)
|
||||||
iconv_errno = (void *)GetProcAddress(hMsvcrtDLL, "_errno");
|
iconv_errno = (void *)GetProcAddress(hMsvcrtDLL, "_errno");
|
||||||
if (iconv == NULL || iconv_open == NULL || iconv_close == NULL
|
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);
|
sprintf((char *)envbuf, "%s=%s", name, val);
|
||||||
putenv((char *)envbuf);
|
putenv((char *)envbuf);
|
||||||
|
# ifdef libintl_putenv
|
||||||
|
libintl_putenv((char *)envbuf);
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_GETTEXT
|
#ifdef FEAT_GETTEXT
|
||||||
|
130
src/os_win32.c
130
src/os_win32.c
@@ -425,6 +425,84 @@ vimLoadLib(char *name)
|
|||||||
return dll;
|
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)
|
#if defined(DYNAMIC_GETTEXT) || defined(PROTO)
|
||||||
# ifndef GETTEXT_DLL
|
# ifndef GETTEXT_DLL
|
||||||
# define GETTEXT_DLL "libintl.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_textdomain(const char *);
|
||||||
static char *null_libintl_bindtextdomain(const char *, const char *);
|
static char *null_libintl_bindtextdomain(const char *, const char *);
|
||||||
static char *null_libintl_bind_textdomain_codeset(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;
|
static HINSTANCE hLibintlDLL = NULL;
|
||||||
char *(*dyn_libintl_gettext)(const char *) = null_libintl_gettext;
|
char *(*dyn_libintl_gettext)(const char *) = null_libintl_gettext;
|
||||||
@@ -446,6 +525,7 @@ char *(*dyn_libintl_bindtextdomain)(const char *, const char *)
|
|||||||
= null_libintl_bindtextdomain;
|
= null_libintl_bindtextdomain;
|
||||||
char *(*dyn_libintl_bind_textdomain_codeset)(const char *, const char *)
|
char *(*dyn_libintl_bind_textdomain_codeset)(const char *, const char *)
|
||||||
= null_libintl_bind_textdomain_codeset;
|
= null_libintl_bind_textdomain_codeset;
|
||||||
|
int (*dyn_libintl_putenv)(const char *) = null_libintl_putenv;
|
||||||
|
|
||||||
int
|
int
|
||||||
dyn_libintl_init(void)
|
dyn_libintl_init(void)
|
||||||
@@ -463,6 +543,7 @@ dyn_libintl_init(void)
|
|||||||
{"bindtextdomain", (FARPROC*)&dyn_libintl_bindtextdomain},
|
{"bindtextdomain", (FARPROC*)&dyn_libintl_bindtextdomain},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
HINSTANCE hmsvcrt;
|
||||||
|
|
||||||
/* No need to initialize twice. */
|
/* No need to initialize twice. */
|
||||||
if (hLibintlDLL)
|
if (hLibintlDLL)
|
||||||
@@ -507,6 +588,13 @@ dyn_libintl_init(void)
|
|||||||
dyn_libintl_bind_textdomain_codeset =
|
dyn_libintl_bind_textdomain_codeset =
|
||||||
null_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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,6 +609,7 @@ dyn_libintl_end(void)
|
|||||||
dyn_libintl_textdomain = null_libintl_textdomain;
|
dyn_libintl_textdomain = null_libintl_textdomain;
|
||||||
dyn_libintl_bindtextdomain = null_libintl_bindtextdomain;
|
dyn_libintl_bindtextdomain = null_libintl_bindtextdomain;
|
||||||
dyn_libintl_bind_textdomain_codeset = null_libintl_bind_textdomain_codeset;
|
dyn_libintl_bind_textdomain_codeset = null_libintl_bind_textdomain_codeset;
|
||||||
|
dyn_libintl_putenv = null_libintl_putenv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
@@ -562,6 +651,13 @@ null_libintl_textdomain(const char *domainname)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
null_libintl_putenv(const char *envstring)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* DYNAMIC_GETTEXT */
|
#endif /* DYNAMIC_GETTEXT */
|
||||||
|
|
||||||
/* This symbol is not defined in older versions of the SDK or Visual C++ */
|
/* 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)
|
#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
|
||||||
static HANDLE
|
static HANDLE
|
||||||
job_io_file_open(
|
job_io_file_open(
|
||||||
char_u *fname,
|
char_u *fname,
|
||||||
DWORD dwDesiredAccess,
|
DWORD dwDesiredAccess,
|
||||||
DWORD dwShareMode,
|
DWORD dwShareMode,
|
||||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||||
DWORD dwCreationDisposition,
|
DWORD dwCreationDisposition,
|
||||||
DWORD dwFlagsAndAttributes)
|
DWORD dwFlagsAndAttributes)
|
||||||
{
|
{
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
# ifdef FEAT_MBYTE
|
# ifdef FEAT_MBYTE
|
||||||
WCHAR *wn = NULL;
|
WCHAR *wn = NULL;
|
||||||
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
|
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
|
||||||
{
|
{
|
||||||
wn = enc_to_utf16(fname, NULL);
|
wn = enc_to_utf16(fname, NULL);
|
||||||
if (wn != NULL)
|
if (wn != NULL)
|
||||||
{
|
{
|
||||||
h = CreateFileW(wn, dwDesiredAccess, dwShareMode,
|
h = CreateFileW(wn, dwDesiredAccess, dwShareMode,
|
||||||
lpSecurityAttributes, dwCreationDisposition,
|
lpSecurityAttributes, dwCreationDisposition,
|
||||||
dwFlagsAndAttributes, NULL);
|
dwFlagsAndAttributes, NULL);
|
||||||
vim_free(wn);
|
vim_free(wn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (wn == NULL)
|
if (wn == NULL)
|
||||||
# endif
|
# endif
|
||||||
h = CreateFile((LPCSTR)fname, dwDesiredAccess, dwShareMode,
|
h = CreateFile((LPCSTR)fname, dwDesiredAccess, dwShareMode,
|
||||||
lpSecurityAttributes, dwCreationDisposition,
|
lpSecurityAttributes, dwCreationDisposition,
|
||||||
dwFlagsAndAttributes, NULL);
|
dwFlagsAndAttributes, NULL);
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
/* os_win32.c */
|
/* os_win32.c */
|
||||||
HINSTANCE vimLoadLib(char *name);
|
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);
|
int dyn_libintl_init(void);
|
||||||
void dyn_libintl_end(void);
|
void dyn_libintl_end(void);
|
||||||
void PlatformId(void);
|
void PlatformId(void);
|
||||||
|
@@ -764,6 +764,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
175,
|
||||||
/**/
|
/**/
|
||||||
174,
|
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_bindtextdomain)(const char *domainname, const char *dirname);
|
||||||
extern char *(*dyn_libintl_bind_textdomain_codeset)(const char *domainname, const char *codeset);
|
extern char *(*dyn_libintl_bind_textdomain_codeset)(const char *domainname, const char *codeset);
|
||||||
extern char *(*dyn_libintl_textdomain)(const char *domainname);
|
extern char *(*dyn_libintl_textdomain)(const char *domainname);
|
||||||
|
extern int (*dyn_libintl_putenv)(const char *envstring);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -592,6 +593,7 @@ extern char *(*dyn_libintl_textdomain)(const char *domainname);
|
|||||||
# define HAVE_BIND_TEXTDOMAIN_CODESET 1
|
# define HAVE_BIND_TEXTDOMAIN_CODESET 1
|
||||||
# endif
|
# endif
|
||||||
# define textdomain(domain) (*dyn_libintl_textdomain)(domain)
|
# define textdomain(domain) (*dyn_libintl_textdomain)(domain)
|
||||||
|
# define libintl_putenv(envstring) (*dyn_libintl_putenv)(envstring)
|
||||||
# else
|
# else
|
||||||
# include <libintl.h>
|
# include <libintl.h>
|
||||||
# define _(x) gettext((char *)(x))
|
# define _(x) gettext((char *)(x))
|
||||||
|
Reference in New Issue
Block a user