]> git.rm.cloudns.org Git - xonotic/darkplaces.git/commitdiff
fix can't load data on windows if data is in non-ascii path (introduced by 1f4743e9...
authorNaitLee <naitli@foxmail.com>
Sat, 6 Jul 2024 19:00:14 +0000 (03:00 +0800)
committerNaitLee <naitli@foxmail.com>
Sat, 6 Jul 2024 19:00:14 +0000 (03:00 +0800)
fs.c
utf8lib.c
utf8lib.h

diff --git a/fs.c b/fs.c
index 6e4259717b0c3ffbd733557a995f23d0ece5e296..c5cf5d66896a0cce691d85e3dff75f00d75322a1 100644 (file)
--- a/fs.c
+++ b/fs.c
@@ -49,9 +49,7 @@
 #include "fs.h"
 #include "wad.h"
 
-#ifdef WIN32
 #include "utf8lib.h"
-#endif
 
 // Win32 requires us to add O_BINARY, but the other OSes don't have it
 #ifndef O_BINARY
@@ -65,7 +63,7 @@
 
 // largefile support for Win32
 #ifdef WIN32
-#undef lseek
+# undef lseek
 # define lseek _lseeki64
 #endif
 
 # define dup _dup
 #endif
 
+// windows wchar helpers
+#ifdef WIN32
+# define MAX_OSWPATH (MAX_OSPATH * sizeof(wchar))
+# define WPATHDEF(var) wchar var[MAX_OSWPATH]
+#else
+# define WPATHDEF(var) ;
+#endif // WIN32
+
 #if USE_RWOPS
 # include <SDL.h>
 typedef SDL_RWops *filedesc_t;
@@ -990,32 +996,19 @@ static packfile_t* FS_AddFileToPack (const char* name, pack_t* pack,
        return pfile;
 }
 
-#if WIN32
-#define WSTRBUF 4096
-static inline int wstrlen(wchar *wstr)
-{
-       int len = 0;
-       while (wstr[len] != 0 && len < WSTRBUF)
-               ++len;
-       return len;
-}
-#define widen(str, wstr) fromwtf8(str, strlen(str), wstr, WSTRBUF)
-#define narrow(wstr, str) towtf8(wstr, wstrlen(wstr), str, WSTRBUF)
-#endif
-
 static void FS_mkdir (const char *path)
 {
-#if WIN32
-       wchar pathw[WSTRBUF] = {0};
-#endif
+       WPATHDEF(pathw);
+
        if(Sys_CheckParm("-readonly"))
                return;
 
-#if WIN32
-       widen(path, pathw);
-       if (_wmkdir (pathw) == -1)
+       WIDE(path, pathw);
+
+#ifdef WIN32
+       if (_wmkdir(pathw) == -1)
 #else
-       if (mkdir (path, 0777) == -1)
+       if (mkdir(path, 0777) == -1)
 #endif
        {
                // No logging for this. The only caller is FS_CreatePath (which
@@ -1963,15 +1956,15 @@ static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t use
        return -1;
 
 #elif defined(WIN32)
-       char homedir[WSTRBUF];
+       char homedir[MAX_OSWPATH];
        wchar *homedirw;
 #if _MSC_VER >= 1400
        size_t homedirwlen;
 #endif
-       wchar_t mydocsdirw[WSTRBUF];
-       char mydocsdir[WSTRBUF];
-       wchar_t *savedgamesdirw;
-       char savedgamesdir[WSTRBUF] = {0};
+       char mydocsdir[MAX_OSWPATH];
+       wchar mydocsdirw[MAX_OSWPATH];
+       char savedgamesdir[MAX_OSWPATH];
+       wchar *savedgamesdirw;
        int fd;
        char vabuf[1024];
 
@@ -1989,13 +1982,13 @@ static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t use
                mydocsdir[0] = 0;
                if (qSHGetFolderPath && qSHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, mydocsdirw) == S_OK)
                {
-                       narrow(mydocsdirw, mydocsdir);
+                       NARROW(mydocsdirw, mydocsdir);
                        dpsnprintf(userdir, userdirsize, "%s/My Games/%s/", mydocsdir, gameuserdirname);
                        break;
                }
 #if _MSC_VER >= 1400
                _wdupenv_s(&homedirw, &homedirwlen, L"USERPROFILE");
-               narrow(homedirw, homedir);
+               NARROW(homedirw, homedir);
                if(homedir[0])
                {
                        dpsnprintf(userdir, userdirsize, "%s/.%s/", homedir, gameuserdirname);
@@ -2004,7 +1997,7 @@ static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t use
                }
 #else
                homedirw = _wgetenv(L"USERPROFILE");
-               narrow(homedirw, homedir);
+               NARROW(homedirw, homedir);
                if(homedir[0])
                {
                        dpsnprintf(userdir, userdirsize, "%s/.%s/", homedir, gameuserdirname);
@@ -2030,7 +2023,7 @@ static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t use
 */
                        if (qSHGetKnownFolderPath(&qFOLDERID_SavedGames, qKF_FLAG_CREATE | qKF_FLAG_NO_ALIAS, NULL, &savedgamesdirw) == S_OK)
                        {
-                               narrow(savedgamesdirw, savedgamesdir);
+                               NARROW(savedgamesdirw, savedgamesdir);
                                qCoTaskMemFree(savedgamesdirw);
                        }
                        qCoUninitialize();
@@ -2141,6 +2134,7 @@ static void FS_Init_Dir (void)
        int i;
        int numgamedirs;
        const char *cmdline_gamedirs[MAX_GAMEDIRS];
+       WPATHDEF(fs_basedirw);
 
        *fs_basedir = 0;
        *fs_userdir = 0;
@@ -2194,8 +2188,13 @@ static void FS_Init_Dir (void)
                        }
                }
 #else
-               // use the working directory
+       // use the working directory
+       #ifdef WIN32
+               _wgetcwd(fs_basedirw, sizeof(fs_basedirw));
+               NARROW(fs_basedirw, fs_basedir);
+       #else
                getcwd(fs_basedir, sizeof(fs_basedir));
+       #endif
 #endif
        }
 
@@ -2380,9 +2379,7 @@ static filedesc_t FS_SysOpenFiledesc(const char *filepath, const char *mode, qbo
        int mod, opt;
        unsigned int ind;
        qbool dolock = false;
-       #ifdef WIN32
-       wchar filepathw[WSTRBUF] = {0};
-       #endif
+       WPATHDEF(filepathw);
 
        // Parse the mode string
        switch (mode[0])
@@ -2434,14 +2431,14 @@ static filedesc_t FS_SysOpenFiledesc(const char *filepath, const char *mode, qbo
        handle = SDL_RWFromFile(filepath, mode);
 #else
 # ifdef WIN32
-       widen(filepath, filepathw);
+       WIDE(filepath, filepathw);
 #  if _MSC_VER >= 1400
        _wsopen_s(&handle, filepathw, mod | opt, (dolock ? ((mod == O_RDONLY) ? _SH_DENYRD : _SH_DENYRW) : _SH_DENYNO), _S_IREAD | _S_IWRITE);
 #  else
-       handle = _wsopen (filepathw, mod | opt, (dolock ? ((mod == O_RDONLY) ? _SH_DENYRD : _SH_DENYRW) : _SH_DENYNO), _S_IREAD | _S_IWRITE);
+       handle = _wsopen(filepathw, mod | opt, (dolock ? ((mod == O_RDONLY) ? _SH_DENYRD : _SH_DENYRW) : _SH_DENYNO), _S_IREAD | _S_IWRITE);
 #  endif
 # else
-       handle = open (filepath, mod | opt, 0666);
+       handle = open(filepath, mod | opt, 0666);
        if(handle >= 0 && dolock)
        {
                struct flock l;
@@ -3703,14 +3700,15 @@ Look for a file in the filesystem only
 */
 int FS_SysFileType (const char *path)
 {
-#if WIN32
-// Sajt - some older sdks are missing this define
+#ifdef WIN32
+       // Sajt - some older sdks are missing this define
 # ifndef INVALID_FILE_ATTRIBUTES
 #  define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
 # endif
-       wchar pathw[WSTRBUF] = {0};
+       WPATHDEF(pathw);
        DWORD result;
-       widen(path, pathw);
+
+       WIDE(path, pathw);
        result = GetFileAttributesW(pathw);
 
        if(result == INVALID_FILE_ATTRIBUTES)
index 1e34e707c978413cb8ef999db36a6e5dd24ecb8b..620601325bd8dd51c346539692f6249accb1ceb7 100644 (file)
--- a/utf8lib.c
+++ b/utf8lib.c
@@ -912,7 +912,7 @@ size_t u8_strpad_colorcodes(char *out, size_t outsize, const char *in, qbool lef
 /**
  * Convert Windows "wide" characters to WTF-8 for internal manipulation
  */
-int towtf8(const wchar *wstr, int wlen, char *cstr, int maxclen)
+int towtf8(const wchar *wstr, int wlen, char *str, int maxlen)
 {
        int p = 0;
        int i;
@@ -921,24 +921,24 @@ int towtf8(const wchar *wstr, int wlen, char *cstr, int maxclen)
                wchar point = wstr[i];
                if (point < 0x80)
                {
-                       if (p + 1 >= maxclen) break;
-                       cstr[p++] = point;
+                       if (p + 1 > maxlen) break;
+                       str[p++] = point;
                }
                else if (point < 0x800)
                {
-                       if (p + 2 >= maxclen) break;
-                       cstr[p++] = (0xc0 | ((point >>  6) & 0x1f));
-                       cstr[p++] = (0x80 | ((point >>  0) & 0x3f));
+                       if (p + 2 > maxlen) break;
+                       str[p++] = (0xc0 | ((point >>  6) & 0x1f));
+                       str[p++] = (0x80 | ((point >>  0) & 0x3f));
                }
                else
                #if WTF8U32
                if (point < 0x10000)
                #endif
                {
-                       if (p + 3 >= maxclen) break;
-                       cstr[p++] = (0xe0 | ((point >> 12) & 0x0f));
-                       cstr[p++] = (0x80 | ((point >>  6) & 0x3f));
-                       cstr[p++] = (0x80 | ((point >>  0) & 0x3f));
+                       if (p + 3 > maxlen) break;
+                       str[p++] = (0xe0 | ((point >> 12) & 0x0f));
+                       str[p++] = (0x80 | ((point >>  6) & 0x3f));
+                       str[p++] = (0x80 | ((point >>  0) & 0x3f));
                }
                #if WTF8U32
                else
@@ -946,31 +946,31 @@ int towtf8(const wchar *wstr, int wlen, char *cstr, int maxclen)
                if (point < 0x110000)
                #endif
                {
-                       if (p + 4 >= maxclen) break;
-                       cstr[p++] = (0xf0 | ((point >> 18) & 0x07));
-                       cstr[p++] = (0x80 | ((point >> 12) & 0x3f));
-                       cstr[p++] = (0x80 | ((point >>  6) & 0x3f));
-                       cstr[p++] = (0x80 | ((point >>  0) & 0x3f));
+                       if (p + 4 > maxlen) break;
+                       str[p++] = (0xf0 | ((point >> 18) & 0x07));
+                       str[p++] = (0x80 | ((point >> 12) & 0x3f));
+                       str[p++] = (0x80 | ((point >>  6) & 0x3f));
+                       str[p++] = (0x80 | ((point >>  0) & 0x3f));
                }
                #endif
        }
-       cstr[p] = 0x00;
+       str[p] = 0x00;
        return p;
 }
 
 /**
  * Convert WTF-8 string to "wide" characters used by Windows
  */
-int fromwtf8(const char *cstr, int clen, wchar *wstr, int maxwlen)
+int fromwtf8(const char *str, int len, wchar *wstr, int maxwlen)
 {
        int p = 0;
        int i;
-       for (i = 0; i < clen;)
+       for (i = 0; i < len;)
        {
-               char byte = cstr[i++];
+               char byte = str[i++];
                wchar point = byte;
                int length = 1;
-               if (p + 1 >= maxwlen) break;
+               if (p + 1 > maxwlen) break;
                #if WTF8CHECKS
                if ((byte & 0xf8) == 0xf8)
                        return -1;
@@ -1001,7 +1001,7 @@ int fromwtf8(const char *cstr, int clen, wchar *wstr, int maxwlen)
                #endif
                while (--length)
                {
-                       byte = cstr[i++];
+                       byte = str[i++];
                        #if WTF8CHECKS
                        if (byte == -1) return -1;
                        else if ((byte & 0xc0) != 0x80) return -1;
@@ -1014,6 +1014,14 @@ int fromwtf8(const char *cstr, int clen, wchar *wstr, int maxwlen)
        return p;
 }
 
+int wstrlen(const wchar *wstr)
+{
+       int i;
+       for (i = 0; wstr[i] != 0; ++i)
+               ;
+       return i;
+}
+
 #endif // WIN32
 
 
index b50a20655c8ce3ce1790dd6a1f81b9dec85b0a3f..fb75018d4725006dba16b9f4ff36f3bf644f1407 100644 (file)
--- a/utf8lib.h
+++ b/utf8lib.h
@@ -82,12 +82,29 @@ Uchar u8_tolower(Uchar ch);
 
 // WTF-8 encoding to circumvent Windows encodings, be it UTF-16 or random codepages
 // https://simonsapin.github.io/wtf-8/
-#define WTF8U32 0     // whether to regard wchar as utf-32
-#define WTF8CHECKS 1  // check for extra sanity in conversion steps
+
 typedef wchar_t wchar;
 
-int towtf8(const wchar* wstr, int wlen, char* cstr, int maxclen);
-int fromwtf8(const char* cstr, int clen, wchar* wstr, int maxwlen);
+// whether to regard wchar as utf-32
+// sizeof(wchar_t) is 2 for win32, we don't have sizeof in macros
+#define WTF8U32 0
+// check for extra sanity in conversion steps
+#define WTF8CHECKS 1
+
+int towtf8(const wchar* wstr, int wlen, char* str, int maxlen);
+int fromwtf8(const char* str, int len, wchar* wstr, int maxwlen);
+int wstrlen(const wchar* wstr);
+
+// helpers for wchar code
+/* convert given wtf-8 encoded char *str to wchar *wstr, only on win32 */
+#define WIDE(str, wstr) fromwtf8(str, strlen(str), wstr, strlen(str))
+/* convert given wchar *wstr to wtf-8 encoded char *str, only on win32 */
+#define NARROW(wstr, str) towtf8(wstr, wstrlen(wstr), str, wstrlen(wstr) * (WTF8U32 ? 4 : 3))
+
+#else
+
+#define WIDE(str, wstr) ;
+#define NARROW(wstr, str) ;
 
 #endif // WIN32