From f1bbf2e48aaa6d0bc2688cb21443f93e3246b1c7 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 27 Aug 2017 06:01:31 -0700 Subject: Use a common header for Unicode-awareness on Windows --- common/win_main_utf8.h | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 common/win_main_utf8.h (limited to 'common') 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 */ -- cgit v1.2.3