aboutsummaryrefslogtreecommitdiffstats
path: root/common/win_main_utf8.h
diff options
context:
space:
mode:
Diffstat (limited to 'common/win_main_utf8.h')
-rw-r--r--common/win_main_utf8.h97
1 files changed, 97 insertions, 0 deletions
diff --git a/common/win_main_utf8.h b/common/win_main_utf8.h
new file mode 100644
index 00000000..faddc257
--- /dev/null
+++ b/common/win_main_utf8.h
@@ -0,0 +1,97 @@
+#ifndef WIN_MAIN_UTF8_H
+#define WIN_MAIN_UTF8_H
+
+/* For Windows systems this provides a way to get UTF-8 encoded argv strings,
+ * 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>
+#include <shellapi.h>
+
+static FILE *my_fopen(const char *fname, const char *mode)
+{
+ WCHAR *wname=NULL, *wmode=NULL;
+ int namelen, modelen;
+ FILE *file = NULL;
+ errno_t err;
+
+ namelen = MultiByteToWideChar(CP_UTF8, 0, fname, -1, NULL, 0);
+ modelen = MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
+
+ if(namelen <= 0 || modelen <= 0)
+ {
+ fprintf(stderr, "Failed to convert UTF-8 fname \"%s\", mode \"%s\"\n", fname, mode);
+ return NULL;
+ }
+
+ wname = calloc(sizeof(WCHAR), namelen+modelen);
+ wmode = wname + namelen;
+ MultiByteToWideChar(CP_UTF8, 0, fname, -1, wname, namelen);
+ MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, modelen);
+
+ err = _wfopen_s(&file, wname, wmode);
+ if(err)
+ {
+ errno = err;
+ file = NULL;
+ }
+
+ free(wname);
+
+ return file;
+}
+#define fopen my_fopen
+
+
+static char **arglist;
+static void cleanup_arglist(void)
+{
+ free(arglist);
+}
+
+static void GetUnicodeArgs(int *argc, char ***argv)
+{
+ size_t total;
+ wchar_t **args;
+ int nargs, i;
+
+ args = CommandLineToArgvW(GetCommandLineW(), &nargs);
+ if(!args)
+ {
+ fprintf(stderr, "Failed to get command line args: %ld\n", GetLastError());
+ exit(EXIT_FAILURE);
+ }
+
+ total = sizeof(**argv) * nargs;
+ for(i = 0;i < nargs;i++)
+ total += WideCharToMultiByte(CP_UTF8, 0, args[i], -1, NULL, 0, NULL, NULL);
+
+ atexit(cleanup_arglist);
+ arglist = *argv = calloc(1, total);
+ (*argv)[0] = (char*)(*argv + nargs);
+ for(i = 0;i < nargs-1;i++)
+ {
+ int len = WideCharToMultiByte(CP_UTF8, 0, args[i], -1, (*argv)[i], 65535, NULL, NULL);
+ (*argv)[i+1] = (*argv)[i] + len;
+ }
+ WideCharToMultiByte(CP_UTF8, 0, args[i], -1, (*argv)[i], 65535, NULL, NULL);
+ *argc = nargs;
+
+ LocalFree(args);
+}
+#define GET_UNICODE_ARGS(argc, argv) GetUnicodeArgs(argc, argv)
+
+#else
+
+/* Do nothing. */
+#define GET_UNICODE_ARGS(argc, argv)
+
+#endif
+
+#endif /* WIN_MAIN_UTF8_H */