foxygit / doom Log in
commit 8c723c09234bbfdda47b12e65ca8dfbd58e18673
Author:     Roman Fomin <rfomin@gmail.com>
AuthorDate: Mon Aug 15 13:15:58 2022 +0700
Commit:     GitHub <noreply@github.com>
CommitDate: Mon Aug 15 08:15:58 2022 +0200

    Implement M_getenv() wrapper to support non-Latin paths on Windows (#1486)

    * implement M_getenv wrapper for non-Latin paths support on Windows

    * update HACKING.md
---
 HACKING.md          |  1 +
 src/d_iwad.c        |  4 ++--
 src/m_misc.c        | 64 +++++++++++++++++++++++++++++++++++++++++++++++++----
 src/m_misc.h        |  3 ++-
 src/setup/execute.c |  2 +-
 5 files changed, 66 insertions(+), 8 deletions(-)

diff --git a/HACKING.md b/HACKING.md
index 57818478..792136e8 100644
--- a/HACKING.md
+++ b/HACKING.md
@@ -227,6 +227,7 @@ C library function |   Wrapper
 `rename()`         |  `M_rename()`
 `stat()`           |  `M_stat()`
 `mkdir()`          |  `M_MakeDirectory()`
+`getenv()`         |  `M_getenv()`

 ## GNU GPL and licensing

diff --git a/src/d_iwad.c b/src/d_iwad.c
index 6b4380a4..e6e5ffe3 100644
--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@ -744,14 +744,14 @@ static void BuildIWADDirList(void)
     AddIWADDir(M_DirName(myargv[0]));

     // Add DOOMWADDIR if it is in the environment
-    env = getenv("DOOMWADDIR");
+    env = M_getenv("DOOMWADDIR");
     if (env != NULL)
     {
         AddIWADDir(env);
     }

     // Add dirs from DOOMWADPATH:
-    env = getenv("DOOMWADPATH");
+    env = M_getenv("DOOMWADPATH");
     if (env != NULL)
     {
         AddIWADPath(env, "");
diff --git a/src/m_misc.c b/src/m_misc.c
index 5b8f22b3..9ede5581 100644
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -28,6 +28,7 @@
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #include <io.h>
+#include "SDL_stdinc.h" // SDL_iconv_string
 #ifdef _MSC_VER
 #include <direct.h>
 #endif
@@ -58,7 +59,7 @@ wchar_t *M_ConvertUtf8ToWide(const char *str)
     if (!wlen)
     {
         errno = EINVAL;
-        printf("Warning: Failed to convert path to UTF8\n");
+        printf("M_ConvertUtf8ToWide: Failed to convert path from UTF8\n");
         return NULL;
     }

@@ -73,7 +74,7 @@ wchar_t *M_ConvertUtf8ToWide(const char *str)
     if (MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, wlen) == 0)
     {
         errno = EINVAL;
-        printf("Warning: Failed to convert path to UTF8\n");
+        printf("M_ConvertUtf8ToWide: Failed to convert path from UTF8\n");
         free(wstr);
         return NULL;
     }
@@ -82,7 +83,7 @@ wchar_t *M_ConvertUtf8ToWide(const char *str)
 }
 #endif

-FILE* M_fopen(const char *filename, const char *mode)
+FILE *M_fopen(const char *filename, const char *mode)
 {
 #ifdef _WIN32
     FILE *file;
@@ -200,6 +201,61 @@ int M_stat(const char *path, struct stat *buf)
 #endif
 }

+#ifdef _WIN32
+typedef struct {
+    char *var;
+    const char *name;
+} env_var_t;
+
+static env_var_t *env_vars;
+static int num_vars;
+#endif
+
+char *M_getenv(const char *name)
+{
+#ifdef _WIN32
+    int i;
+    wchar_t *wenv = NULL, *wname = NULL;
+    char *env = NULL;
+
+    for (i = 0; i < num_vars; ++i)
+    {
+        if (!strcasecmp(name, env_vars[i].name))
+           return env_vars[i].var;
+    }
+
+    wname = M_ConvertUtf8ToWide(name);
+
+    if (!wname)
+    {
+        return NULL;
+    }
+
+    wenv = _wgetenv(wname);
+
+    free(wname);
+
+    if (wenv)
+    {
+        env = SDL_iconv_string("UTF-8", "UTF-16LE", (const char *)wenv,
+                               (wcslen(wenv) + 1) * sizeof(wchar_t));
+    }
+    else
+    {
+        env = NULL;
+    }
+
+    env_vars = I_Realloc(env_vars, (num_vars + 1) * sizeof(*env_vars));
+    env_vars[num_vars].var = env;
+    env_vars[num_vars].name = M_StringDuplicate(name);
+    ++num_vars;
+
+    return env;
+#else
+    return getenv(name);
+#endif
+}
+
 //
 // Create a directory
 //
@@ -405,7 +461,7 @@ char *M_TempFile(const char *s)

     // Check the TEMP environment variable to find the location.

-    tempdir = getenv("TEMP");
+    tempdir = M_getenv("TEMP");

     if (tempdir == NULL)
     {
diff --git a/src/m_misc.h b/src/m_misc.h
index f9a6beff..c04e050e 100644
--- a/src/m_misc.h
+++ b/src/m_misc.h
@@ -30,10 +30,11 @@
 wchar_t *M_ConvertUtf8ToWide(const char *str);
 #endif

-FILE* M_fopen(const char *filename, const char *mode);
+FILE *M_fopen(const char *filename, const char *mode);
 int M_remove(const char *path);
 int M_rename(const char *oldname, const char *newname);
 int M_stat(const char *path, struct stat *buf);
+char *M_getenv(const char *name);
 boolean M_WriteFile(const char *name, const void *source, int length);
 int M_ReadFile(const char *name, byte **buffer);
 void M_MakeDirectory(const char *dir);
diff --git a/src/setup/execute.c b/src/setup/execute.c
index e297f40e..0a86dd7b 100644
--- a/src/setup/execute.c
+++ b/src/setup/execute.c
@@ -61,7 +61,7 @@ static char *TempFile(const char *s)
 #ifdef _WIN32
     // Check the TEMP environment variable to find the location.

-    tempdir = getenv("TEMP");
+    tempdir = M_getenv("TEMP");

     if (tempdir == NULL)
     {