diff options
author | Chris Robinson <[email protected]> | 2017-08-27 06:01:31 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2017-08-27 06:01:31 -0700 |
commit | f1bbf2e48aaa6d0bc2688cb21443f93e3246b1c7 (patch) | |
tree | 7cd296c240cb1a253a7003bdb5d185257d4f1ffd /common | |
parent | bfcde9ae8ac4cd3ecdb128397eec2913ba90142d (diff) |
Use a common header for Unicode-awareness on Windows
Diffstat (limited to 'common')
-rw-r--r-- | common/win_main_utf8.h | 92 |
1 files changed, 92 insertions, 0 deletions
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 <windows.h> + +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 */ |