#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
// 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;
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
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];
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);
}
#else
homedirw = _wgetenv(L"USERPROFILE");
- narrow(homedirw, homedir);
+ NARROW(homedirw, homedir);
if(homedir[0])
{
dpsnprintf(userdir, userdirsize, "%s/.%s/", homedir, gameuserdirname);
*/
if (qSHGetKnownFolderPath(&qFOLDERID_SavedGames, qKF_FLAG_CREATE | qKF_FLAG_NO_ALIAS, NULL, &savedgamesdirw) == S_OK)
{
- narrow(savedgamesdirw, savedgamesdir);
+ NARROW(savedgamesdirw, savedgamesdir);
qCoTaskMemFree(savedgamesdirw);
}
qCoUninitialize();
int i;
int numgamedirs;
const char *cmdline_gamedirs[MAX_GAMEDIRS];
+ WPATHDEF(fs_basedirw);
*fs_basedir = 0;
*fs_userdir = 0;
}
}
#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
}
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])
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;
*/
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)
/**
* 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;
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
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;
#endif
while (--length)
{
- byte = cstr[i++];
+ byte = str[i++];
#if WTF8CHECKS
if (byte == -1) return -1;
else if ((byte & 0xc0) != 0x80) return -1;
return p;
}
+int wstrlen(const wchar *wstr)
+{
+ int i;
+ for (i = 0; wstr[i] != 0; ++i)
+ ;
+ return i;
+}
+
#endif // WIN32
// 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