aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-08-27 06:01:31 -0700
committerChris Robinson <[email protected]>2017-08-27 06:01:31 -0700
commitf1bbf2e48aaa6d0bc2688cb21443f93e3246b1c7 (patch)
tree7cd296c240cb1a253a7003bdb5d185257d4f1ffd /common
parentbfcde9ae8ac4cd3ecdb128397eec2913ba90142d (diff)
Use a common header for Unicode-awareness on Windows
Diffstat (limited to 'common')
-rw-r--r--common/win_main_utf8.h92
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 */