1 #ifndef WIN_MAIN_UTF8_H
2 #define WIN_MAIN_UTF8_H
4 /* For Windows systems this provides a way to get UTF-8 encoded argv strings,
5 * and also overrides fopen to accept UTF-8 filenames. Working with wmain
6 * directly complicates cross-platform compatibility, while normal main() in
7 * Windows uses the current codepage (which has limited availability of
10 * For MinGW, you must link with -municode
13 #define WIN32_LEAN_AND_MEAN
21 #define STATIC_CAST(...) static_cast<__VA_ARGS__>
22 #define REINTERPRET_CAST(...) reinterpret_cast<__VA_ARGS__>
26 #define STATIC_CAST(...) (__VA_ARGS__)
27 #define REINTERPRET_CAST(...) (__VA_ARGS__)
30 static FILE *my_fopen(const char *fname, const char *mode)
32 wchar_t *wname=NULL, *wmode=NULL;
37 namelen = MultiByteToWideChar(CP_UTF8, 0, fname, -1, NULL, 0);
38 modelen = MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
40 if(namelen <= 0 || modelen <= 0)
42 fprintf(stderr, "Failed to convert UTF-8 fname \"%s\", mode \"%s\"\n", fname, mode);
47 auto strbuf = std::make_unique<wchar_t[]>(static_cast<size_t>(namelen)+modelen);
50 wname = (wchar_t*)calloc(sizeof(wchar_t), (size_t)namelen + modelen);
52 wmode = wname + namelen;
53 MultiByteToWideChar(CP_UTF8, 0, fname, -1, wname, namelen);
54 MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, modelen);
56 err = _wfopen_s(&file, wname, wmode);
68 #define fopen my_fopen
71 /* SDL overrides main and provides UTF-8 args for us. */
72 #if !defined(SDL_MAIN_NEEDED) && !defined(SDL_MAIN_AVAILABLE)
73 int my_main(int, char**);
79 int wmain(int argc, wchar_t **wargv)
85 total = sizeof(*argv) * STATIC_CAST(size_t)(argc);
86 for(i = 0;i < argc;i++)
87 total += STATIC_CAST(size_t)(WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, NULL, 0, NULL,
91 auto argbuf = std::make_unique<char[]>(total);
92 argv = reinterpret_cast<char**>(argbuf.get());
94 argv = (char**)calloc(1, total);
96 argv[0] = REINTERPRET_CAST(char*)(argv + argc);
97 for(i = 0;i < argc-1;i++)
99 int len = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i], 65535, NULL, NULL);
100 argv[i+1] = argv[i] + len;
102 WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i], 65535, NULL, NULL);
105 return main(argc, argv);
107 i = main(argc, argv);
113 #endif /* !defined(SDL_MAIN_NEEDED) && !defined(SDL_MAIN_AVAILABLE) */
117 #endif /* WIN_MAIN_UTF8_H */