diff options
author | Chris Robinson <[email protected]> | 2014-03-28 00:37:42 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2014-03-28 00:37:42 -0700 |
commit | 20886059fd88724f724da8601a82e04fc3f03a53 (patch) | |
tree | 0f8c147ad311226ea9983d73e9ca18faade84e8f | |
parent | 18620ab5e00fb4cba97f3aa2bfbc677dfe8376ef (diff) |
Wrap fopen calls under Windows
The idea is that all filenames we deal with are encoded as UTF-8, but the
Windows functions that take a char string interpret it using the ANSI codepage.
So instead, we convert the UTF-8 string to a wchar string, and then use the
wchar functions for proper extended character filename support.
-rw-r--r-- | Alc/ALc.c | 2 | ||||
-rw-r--r-- | Alc/alcConfig.c | 18 | ||||
-rw-r--r-- | Alc/backends/wave.c | 2 | ||||
-rw-r--r-- | Alc/compat.h | 5 | ||||
-rw-r--r-- | Alc/helpers.c | 41 |
5 files changed, 52 insertions, 16 deletions
@@ -893,7 +893,7 @@ static void alc_initconfig(void) str = getenv("ALSOFT_LOGFILE"); if(str && str[0]) { - FILE *logfile = fopen(str, "wt"); + FILE *logfile = al_fopen(str, "wt"); if(logfile) LogFile = logfile; else ERR("Failed to open log file '%s'\n", str); } diff --git a/Alc/alcConfig.c b/Alc/alcConfig.c index 740d0f86..41416a18 100644 --- a/Alc/alcConfig.c +++ b/Alc/alcConfig.c @@ -32,13 +32,13 @@ #include <stdio.h> #include <ctype.h> #include <string.h> - -#include "alMain.h" - #ifdef _WIN32_IE #include <shlobj.h> #endif +#include "alMain.h" +#include "compat.h" + typedef struct ConfigEntry { char *key; @@ -304,7 +304,7 @@ void ReadALConfig(void) snprintf(buffer+p, sizeof(buffer)-p, "\\alsoft.ini"); TRACE("Loading config %s...\n", buffer); - f = fopen(buffer, "rt"); + f = al_fopen(buffer, "rt"); if(f) { LoadConfigFromFile(f); @@ -315,7 +315,7 @@ void ReadALConfig(void) str = "/etc/openal/alsoft.conf"; TRACE("Loading config %s...\n", str); - f = fopen(str, "r"); + f = al_fopen(str, "r"); if(f) { LoadConfigFromFile(f); @@ -346,7 +346,7 @@ void ReadALConfig(void) buffer[sizeof(buffer)-1] = 0; TRACE("Loading config %s...\n", next); - f = fopen(next, "r"); + f = al_fopen(next, "r"); if(f) { LoadConfigFromFile(f); @@ -362,7 +362,7 @@ void ReadALConfig(void) snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", str); TRACE("Loading config %s...\n", buffer); - f = fopen(buffer, "r"); + f = al_fopen(buffer, "r"); if(f) { LoadConfigFromFile(f); @@ -381,7 +381,7 @@ void ReadALConfig(void) if(buffer[0] != 0) { TRACE("Loading config %s...\n", buffer); - f = fopen(buffer, "r"); + f = al_fopen(buffer, "r"); if(f) { LoadConfigFromFile(f); @@ -393,7 +393,7 @@ void ReadALConfig(void) if((str=getenv("ALSOFT_CONF")) != NULL && *str) { TRACE("Loading config %s...\n", str); - f = fopen(str, "r"); + f = al_fopen(str, "r"); if(f) { LoadConfigFromFile(f); diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c index 2fafc4b9..2209c798 100644 --- a/Alc/backends/wave.c +++ b/Alc/backends/wave.c @@ -183,7 +183,7 @@ static ALCenum wave_open_playback(ALCdevice *device, const ALCchar *deviceName) data = (wave_data*)calloc(1, sizeof(wave_data)); - data->f = fopen(fname, "wb"); + data->f = al_fopen(fname, "wb"); if(!data->f) { free(data); diff --git a/Alc/compat.h b/Alc/compat.h index 1c80e7c5..426dad9d 100644 --- a/Alc/compat.h +++ b/Alc/compat.h @@ -23,6 +23,9 @@ inline int alsched_yield(void) WCHAR *strdupW(const WCHAR *str); +/* Opens a file with standard I/O. The filename is expected to be UTF-8. */ +FILE *al_fopen(const char *fname, const char *mode); + #define HAVE_DYNLOAD 1 #else @@ -50,6 +53,8 @@ void Sleep(ALuint t); #define alsched_yield sched_yield +#define al_fopen(_n, _m) fopen((_n), (_m)) + #if defined(HAVE_DLFCN_H) && !defined(IN_IDE_PARSER) #define HAVE_DYNLOAD 1 #endif diff --git a/Alc/helpers.c b/Alc/helpers.c index 59eb359e..1246e92b 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -375,6 +375,37 @@ WCHAR *strdupW(const WCHAR *str) return ret; } + +FILE *al_fopen(const char *fname, const char *mode) +{ + WCHAR *wname=NULL, *wmode=NULL; + FILE *file = NULL; + int len; + + if((len=MultiByteToWideChar(CP_UTF8, 0, fname, -1, NULL, 0)) > 0) + { + wname = calloc(sizeof(WCHAR), len); + MultiByteToWideChar(CP_UTF8, 0, fname, -1, wname, len); + } + if((len=MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0)) > 0) + { + wmode = calloc(sizeof(WCHAR), len); + MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, len); + } + + if(!wname) + ERR("Failed to convert UTF-8 filename: \"%s\"\n", fname); + else if(!wmode) + ERR("Failed to convert UTF-8 mode: \"%s\"\n", mode); + else + file = _wfopen(wname, wmode); + + free(wname); + free(wmode); + + return file; +} + #else #include <pthread.h> @@ -526,7 +557,7 @@ FILE *OpenDataFile(const char *fname, const char *subdir) /* If the path is absolute, open it directly. */ if(fname[0] != '\0' && fname[1] == ':' && (fname[2] == '\\' || fname[2] == '/')) { - if((f=fopen(fname, "rb")) != NULL) + if((f=al_fopen(fname, "rb")) != NULL) { TRACE("Opened %s\n", fname); return f; @@ -554,7 +585,7 @@ FILE *OpenDataFile(const char *fname, const char *subdir) buffer[len] = '\\'; } - if((f=fopen(buffer, "rb")) != NULL) + if((f=al_fopen(buffer, "rb")) != NULL) { TRACE("Opened %s\n", buffer); return f; @@ -566,7 +597,7 @@ FILE *OpenDataFile(const char *fname, const char *subdir) if(fname[0] == '/') { - if((f=fopen(fname, "rb")) != NULL) + if((f=al_fopen(fname, "rb")) != NULL) { TRACE("Opened %s\n", fname); return f; @@ -581,7 +612,7 @@ FILE *OpenDataFile(const char *fname, const char *subdir) snprintf(buffer, sizeof(buffer), "%s/.local/share/%s/%s", str, subdir, fname); if(buffer[0]) { - if((f=fopen(buffer, "rb")) != NULL) + if((f=al_fopen(buffer, "rb")) != NULL) { TRACE("Opened %s\n", buffer); return f; @@ -612,7 +643,7 @@ FILE *OpenDataFile(const char *fname, const char *subdir) buffer[len] = '\0'; snprintf(buffer+len, sizeof(buffer)-len, "/%s/%s", subdir, fname); - if((f=fopen(buffer, "rb")) != NULL) + if((f=al_fopen(buffer, "rb")) != NULL) { TRACE("Opened %s\n", buffer); return f; |