From f1bbf2e48aaa6d0bc2688cb21443f93e3246b1c7 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 27 Aug 2017 06:01:31 -0700 Subject: [PATCH] Use a common header for Unicode-awareness on Windows --- common/win_main_utf8.h | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++ utils/bsincgen.c | 80 +------------------------------------------ utils/makehrtf.c | 82 ++------------------------------------------ 3 files changed, 95 insertions(+), 159 deletions(-) create mode 100644 common/win_main_utf8.h diff --git a/common/win_main_utf8.h b/common/win_main_utf8.h new file mode 100644 index 00000000..d83aa610 --- /dev/null +++ b/common/win_main_utf8.h @@ -0,0 +1,92 @@ +#ifndef WIN_MAIN_UTF8_H +#define WIN_MAIN_UTF8_H + +/* For Windows systems this overrides main() so that the argv strings are UTF-8 + * encoded, and also overrides fopen to accept UTF-8 filenames. Working with + * wmain directly complicates cross-platform compatibility, while normal main() + * in Windows uses the current codepage (which has limited availability of + * characters). + * + * For MinGW, you must link with -municode + */ +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include + +static char *ToUTF8(const wchar_t *from) +{ + char *out = NULL; + int len; + if((len=WideCharToMultiByte(CP_UTF8, 0, from, -1, NULL, 0, NULL, NULL)) > 0) + { + out = calloc(sizeof(*out), len); + WideCharToMultiByte(CP_UTF8, 0, from, -1, out, len, NULL, NULL); + out[len-1] = 0; + } + return out; +} + +static WCHAR *FromUTF8(const char *str) +{ + WCHAR *out = NULL; + int len; + + if((len=MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0)) > 0) + { + out = calloc(sizeof(WCHAR), len); + MultiByteToWideChar(CP_UTF8, 0, str, -1, out, len); + out[len-1] = 0; + } + return out; +} + + +static FILE *my_fopen(const char *fname, const char *mode) +{ + WCHAR *wname=NULL, *wmode=NULL; + FILE *file = NULL; + + wname = FromUTF8(fname); + wmode = FromUTF8(mode); + if(!wname) + fprintf(stderr, "Failed to convert UTF-8 filename: \"%s\"\n", fname); + else if(!wmode) + fprintf(stderr, "Failed to convert UTF-8 mode: \"%s\"\n", mode); + else + file = _wfopen(wname, wmode); + + free(wname); + free(wmode); + + return file; +} +#define fopen my_fopen + + +#define main my_main +int main(int argc, char *argv[]); + +static char **arglist; +static void cleanup_arglist(void) +{ + int i; + for(i = 0;arglist[i];i++) + free(arglist[i]); + free(arglist); +} + +int wmain(int argc, const wchar_t *wargv[]) +{ + int i; + + atexit(cleanup_arglist); + arglist = calloc(sizeof(*arglist), argc+1); + for(i = 0;i < argc;i++) + arglist[i] = ToUTF8(wargv[i]); + + return main(argc, arglist); +} + +#endif + +#endif /* WIN_MAIN_UTF8_H */ diff --git a/utils/bsincgen.c b/utils/bsincgen.c index ba0116cb..40e487ba 100644 --- a/utils/bsincgen.c +++ b/utils/bsincgen.c @@ -39,59 +39,7 @@ #include #include -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include - -static char *ToUTF8(const wchar_t *from) -{ - char *out = NULL; - int len; - if((len=WideCharToMultiByte(CP_UTF8, 0, from, -1, NULL, 0, NULL, NULL)) > 0) - { - out = calloc(sizeof(*out), len); - WideCharToMultiByte(CP_UTF8, 0, from, -1, out, len, NULL, NULL); - out[len-1] = 0; - } - return out; -} - -static WCHAR *FromUTF8(const char *str) -{ - WCHAR *out = NULL; - int len; - - if((len=MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0)) > 0) - { - out = calloc(sizeof(WCHAR), len); - MultiByteToWideChar(CP_UTF8, 0, str, -1, out, len); - out[len-1] = 0; - } - return out; -} - - -static FILE *my_fopen(const char *fname, const char *mode) -{ - WCHAR *wname=NULL, *wmode=NULL; - FILE *file = NULL; - - wname = FromUTF8(fname); - wmode = FromUTF8(mode); - if(!wname) - fprintf(stderr, "Failed to convert UTF-8 filename: \"%s\"\n", fname); - else if(!wmode) - fprintf(stderr, "Failed to convert UTF-8 mode: \"%s\"\n", mode); - else - file = _wfopen(wname, wmode); - - free(wname); - free(wmode); - - return file; -} -#define fopen my_fopen -#endif +#include "win_main_utf8.h" #ifndef M_PI @@ -409,32 +357,6 @@ static void Sinc4GenerateTables(FILE *output, const double rejection) } -#ifdef _WIN32 -#define main my_main -int main(int argc, char *argv[]); - -static char **arglist; -static void cleanup_arglist(void) -{ - int i; - for(i = 0;arglist[i];i++) - free(arglist[i]); - free(arglist); -} - -int wmain(int argc, const wchar_t *wargv[]) -{ - int i; - - atexit(cleanup_arglist); - arglist = calloc(sizeof(*arglist), argc+1); - for(i = 0;i < argc;i++) - arglist[i] = ToUTF8(wargv[i]); - - return main(argc, arglist); -} -#endif - int main(int argc, char *argv[]) { FILE *output; diff --git a/utils/makehrtf.c b/utils/makehrtf.c index a4286ee3..3e848dde 100644 --- a/utils/makehrtf.c +++ b/utils/makehrtf.c @@ -77,6 +77,8 @@ #include "getopt.h" #endif +#include "win_main_utf8.h" + // Rely (if naively) on OpenAL's header for the types used for serialization. #include "AL/al.h" #include "AL/alext.h" @@ -90,60 +92,6 @@ #endif -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include - -static char *ToUTF8(const wchar_t *from) -{ - char *out = NULL; - int len; - if((len=WideCharToMultiByte(CP_UTF8, 0, from, -1, NULL, 0, NULL, NULL)) > 0) - { - out = calloc(sizeof(*out), len); - WideCharToMultiByte(CP_UTF8, 0, from, -1, out, len, NULL, NULL); - out[len-1] = 0; - } - return out; -} - -static WCHAR *FromUTF8(const char *str) -{ - WCHAR *out = NULL; - int len; - - if((len=MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0)) > 0) - { - out = calloc(sizeof(WCHAR), len); - MultiByteToWideChar(CP_UTF8, 0, str, -1, out, len); - out[len-1] = 0; - } - return out; -} - - -static FILE *my_fopen(const char *fname, const char *mode) -{ - WCHAR *wname=NULL, *wmode=NULL; - FILE *file = NULL; - - wname = FromUTF8(fname); - wmode = FromUTF8(mode); - if(!wname) - fprintf(stderr, "Failed to convert UTF-8 filename: \"%s\"\n", fname); - else if(!wmode) - fprintf(stderr, "Failed to convert UTF-8 mode: \"%s\"\n", mode); - else - file = _wfopen(wname, wmode); - - free(wname); - free(wmode); - - return file; -} -#define fopen my_fopen -#endif - // The epsilon used to maintain signal stability. #define EPSILON (1e-9) @@ -2913,32 +2861,6 @@ static void PrintHelp(const char *argv0, FILE *ofile) fprintf(ofile, " Use of '%%r' will be substituted with the data set sample rate.\n"); } -#ifdef _WIN32 -#define main my_main -int main(int argc, char *argv[]); - -static char **arglist; -static void cleanup_arglist(void) -{ - int i; - for(i = 0;arglist[i];i++) - free(arglist[i]); - free(arglist); -} - -int wmain(int argc, const wchar_t *wargv[]) -{ - int i; - - atexit(cleanup_arglist); - arglist = calloc(sizeof(*arglist), argc+1); - for(i = 0;i < argc;i++) - arglist[i] = ToUTF8(wargv[i]); - - return main(argc, arglist); -} -#endif - // Standard command line dispatch. int main(int argc, char *argv[]) { -- 2.11.4.GIT