1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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 */
|