]> granicus.if.org Git - vim/commitdiff
patch 8.0.0280: problem setting multi-byte environment var on MS-Windows v8.0.0280
authorBram Moolenaar <Bram@vim.org>
Wed, 1 Feb 2017 12:14:16 +0000 (13:14 +0100)
committerBram Moolenaar <Bram@vim.org>
Wed, 1 Feb 2017 12:14:16 +0000 (13:14 +0100)
Problem:    On MS-Windows setting an environment variable with multi-byte
            strings does not work well.
Solution:   Use wputenv when possible. (Taro Muraoka, Ken Takata)

src/misc1.c
src/os_win32.c
src/os_win32.h
src/proto/os_win32.pro
src/version.c
src/vim.h

index cc5d5e60f6707e3bb52d2b777dfdf3d6f0990191..f95c3fe477da1d38b16b06e58a4e4bf7b08cf949 100644 (file)
@@ -4453,9 +4453,6 @@ 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
index 9b86478d3e384203712a236ffeecdffc0c76f082..030b4b0da75a1c7d76d7cb97b3eb88cad3b745f6 100644 (file)
@@ -515,6 +515,7 @@ 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 int null_libintl_wputenv(const wchar_t *);
 
 static HINSTANCE hLibintlDLL = NULL;
 char *(*dyn_libintl_gettext)(const char *) = null_libintl_gettext;
@@ -526,6 +527,7 @@ char *(*dyn_libintl_bindtextdomain)(const char *, const char *)
 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_wputenv)(const wchar_t *) = null_libintl_wputenv;
 
     int
 dyn_libintl_init(void)
@@ -591,9 +593,14 @@ dyn_libintl_init(void)
     /* _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_wputenv = (void *)GetProcAddress(hmsvcrt, "_wputenv");
+    }
+    if (dyn_libintl_putenv == NULL || dyn_libintl_putenv == _putenv)
        dyn_libintl_putenv = null_libintl_putenv;
+    if (dyn_libintl_wputenv == NULL || dyn_libintl_wputenv == _wputenv)
+       dyn_libintl_wputenv = null_libintl_wputenv;
 
     return 1;
 }
@@ -610,6 +617,7 @@ dyn_libintl_end(void)
     dyn_libintl_bindtextdomain = null_libintl_bindtextdomain;
     dyn_libintl_bind_textdomain_codeset = null_libintl_bind_textdomain_codeset;
     dyn_libintl_putenv         = null_libintl_putenv;
+    dyn_libintl_wputenv                = null_libintl_wputenv;
 }
 
 /*ARGSUSED*/
@@ -658,6 +666,13 @@ null_libintl_putenv(const char *envstring)
     return 0;
 }
 
+/*ARGSUSED*/
+    int
+null_libintl_wputenv(const wchar_t *envstring)
+{
+    return 0;
+}
+
 #endif /* DYNAMIC_GETTEXT */
 
 /* This symbol is not defined in older versions of the SDK or Visual C++ */
@@ -6985,3 +7000,43 @@ fix_arg_enc(void)
     set_alist_count();
 }
 #endif
+
+    int
+mch_setenv(char *var, char *value, int x)
+{
+    char_u     *envbuf;
+
+    envbuf = alloc((unsigned)(STRLEN(var) + STRLEN(value) + 2));
+    if (envbuf == NULL)
+       return -1;
+
+    sprintf((char *)envbuf, "%s=%s", var, value);
+
+#ifdef FEAT_MBYTE
+    if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+    {
+       WCHAR       *p = enc_to_utf16(envbuf, NULL);
+
+       vim_free(envbuf);
+       if (p == NULL)
+           return -1;
+       _wputenv(p);
+# ifdef libintl_wputenv
+       libintl_wputenv(p);
+# endif
+       /* Unlike Un*x systems, we can free the string for _wputenv(). */
+       vim_free(p);
+    }
+    else
+#endif
+    {
+       _putenv((char *)envbuf);
+# ifdef libintl_putenv
+       libintl_putenv((char *)envbuf);
+# endif
+       /* Unlike Un*x systems, we can free the string for _putenv(). */
+       vim_free(envbuf);
+    }
+
+    return 0;
+}
index f620d742e827c13b2f7e0581a62b698fd40f4c58..5017f532eff3bc7c62887be89c04818796a4b9c2 100644 (file)
@@ -202,7 +202,9 @@ Trace(char *pszFormat, ...);
 #define ASSERT_NULL_OR_POINTER(p, type) \
     ASSERT(((p) == NULL)  ||  IsValidAddress((p), sizeof(type), FALSE))
 
-#define mch_setenv(name, val, x) setenv(name, val, x)
+#ifndef HAVE_SETENV
+# define HAVE_SETENV
+#endif
 #define mch_getenv(x) (char_u *)getenv((char *)(x))
 #ifdef __BORLANDC__
 # define vim_mkdir(x, y) mkdir(x)
index a64c863bbc6b7388fc5d3c0a122eb1860b88d292..ca671464b99b87b7348001e6b40151637afbaf33 100644 (file)
@@ -65,4 +65,5 @@ void free_cmd_argsW(void);
 void used_file_arg(char *name, int literal, int full_path, int diff_mode);
 void set_alist_count(void);
 void fix_arg_enc(void);
+int mch_setenv(char *var, char *value, int x);
 /* vim: set ft=c : */
index 82ee6d4e65312cb8f83e9e373dc177a393a0cb8e..08e32cf90b135092a77756184c4726da4e00ea6d 100644 (file)
@@ -764,6 +764,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    280,
 /**/
     279,
 /**/
index abee386cb3335e1cdac1a856ee488195bcf18860..f3e87fef5cbcbe1cfb5b0dc7283818293448ec77 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -594,6 +594,7 @@ extern int (*dyn_libintl_putenv)(const char *envstring);
 #  endif
 #  define textdomain(domain) (*dyn_libintl_textdomain)(domain)
 #  define libintl_putenv(envstring) (*dyn_libintl_putenv)(envstring)
+#  define libintl_wputenv(envstring) (*dyn_libintl_wputenv)(envstring)
 # else
 #  include <libintl.h>
 #  define _(x) gettext((char *)(x))