13 #include <windows.h> /* for WideCharToMultiByte and MultiByteToWideChar */
15 #include "share/compat.h"
16 #include "share/win_utf8_io.h"
17 #include "share/compat.h"
19 static UINT win_utf8_io_codepage
= CP_ACP
;
21 /* convert WCHAR stored Unicode string to UTF-8. Caller is responsible for freeing memory */
23 char *utf8_from_wchar(const wchar_t *wstr
)
28 if (!wstr
) return NULL
;
29 if ((len
= WideCharToMultiByte(CP_UTF8
, 0, wstr
, -1, NULL
, 0, NULL
, NULL
)) == 0) return NULL
;
30 if ((utf8str
= (char *)malloc(++len
)) == NULL
) return NULL
;
31 if (WideCharToMultiByte(CP_UTF8
, 0, wstr
, -1, utf8str
, len
, NULL
, NULL
) == 0) {
39 /* convert UTF-8 back to WCHAR. Caller is responsible for freeing memory */
41 wchar_t *wchar_from_utf8(const char *str
)
46 if (!str
) return NULL
;
47 len
=(int)strlen(str
)+1;
48 if ((widestr
= (wchar_t *)malloc(len
*sizeof(wchar_t))) != NULL
) {
49 if (MultiByteToWideChar(win_utf8_io_codepage
, 0, str
, len
, widestr
, len
) == 0) {
50 if (MultiByteToWideChar(CP_ACP
, 0, str
, len
, widestr
, len
) == 0) { /* try conversion from Ansi in case the initial UTF-8 conversion had failed */
60 /* retrieve WCHAR commandline, expand wildcards and convert everything to UTF-8 */
61 int get_utf8_argv(int *argc
, char ***argv
)
63 typedef int (__cdecl
*__wgetmainargs_
)(int*, wchar_t***, wchar_t***, int, int*);
64 __wgetmainargs_ __wgetmainargs
;
72 if ((handle
= LoadLibrary("msvcrt.dll")) == NULL
) return 1;
73 if ((__wgetmainargs
= (__wgetmainargs_
)GetProcAddress(handle
, "__wgetmainargs")) == NULL
) return 1;
75 if (__wgetmainargs(&wargc
, &wargv
, &wenv
, 1, &i
) != 0) return 1;
76 if ((utf8argv
= (char **)malloc(wargc
*sizeof(char*))) == NULL
) return 1;
79 for (i
=0; i
<wargc
; i
++) {
80 if ((utf8argv
[i
] = utf8_from_wchar(wargv
[i
])) == NULL
) {
90 win_utf8_io_codepage
= CP_UTF8
;
100 /* return number of characters in the UTF-8 string */
101 size_t strlen_utf8(const char *str
)
104 if ((len
= MultiByteToWideChar(win_utf8_io_codepage
, 0, str
, -1, NULL
, 0)) == 0)
109 /* get the console width in characters */
110 int win_get_console_width(void)
113 CONSOLE_SCREEN_BUFFER_INFO csbi
;
114 HANDLE hOut
= GetStdHandle(STD_OUTPUT_HANDLE
);
115 if (GetConsoleScreenBufferInfo(hOut
, &csbi
) != 0) width
= csbi
.dwSize
.X
;
119 /* print functions */
121 int print_console(FILE *stream
, const wchar_t *text
, uint32_t len
)
126 hOut
= GetStdHandle(STD_OUTPUT_HANDLE
);
127 hErr
= GetStdHandle(STD_ERROR_HANDLE
);
128 if (stream
== stdout
&& hOut
!= INVALID_HANDLE_VALUE
&& GetFileType(hOut
) == FILE_TYPE_CHAR
) {
129 if (WriteConsoleW(hOut
, text
, len
, &out
, NULL
) == 0) return -1;
131 } else if (stream
== stderr
&& hErr
!= INVALID_HANDLE_VALUE
&& GetFileType(hErr
) == FILE_TYPE_CHAR
) {
132 if (WriteConsoleW(hErr
, text
, len
, &out
, NULL
) == 0) return -1;
135 int ret
= fwprintf(stream
, L
"%s", text
);
136 if (ret
< 0) return ret
;
141 int printf_utf8(const char *format
, ...)
144 wchar_t *wout
= NULL
;
149 if (!(utmp
= (char *)malloc(32768*sizeof(char)))) break;
150 va_start(argptr
, format
);
151 ret
= vsprintf(utmp
, format
, argptr
);
154 if (!(wout
= wchar_from_utf8(utmp
))) {
158 ret
= print_console(stdout
, wout
, wcslen(wout
));
161 if (utmp
) free(utmp
);
162 if (wout
) free(wout
);
167 int fprintf_utf8(FILE *stream
, const char *format
, ...)
170 wchar_t *wout
= NULL
;
175 if (!(utmp
= (char *)malloc(32768*sizeof(char)))) break;
176 va_start(argptr
, format
);
177 ret
= vsprintf(utmp
, format
, argptr
);
180 if (!(wout
= wchar_from_utf8(utmp
))) {
184 ret
= print_console(stream
, wout
, wcslen(wout
));
187 if (utmp
) free(utmp
);
188 if (wout
) free(wout
);
193 int vfprintf_utf8(FILE *stream
, const char *format
, va_list argptr
)
196 wchar_t *wout
= NULL
;
200 if (!(utmp
= (char *)malloc(32768*sizeof(char)))) break;
201 if ((ret
= vsprintf(utmp
, format
, argptr
)) < 0) break;
202 if (!(wout
= wchar_from_utf8(utmp
))) {
206 ret
= print_console(stream
, wout
, wcslen(wout
));
209 if (utmp
) free(utmp
);
210 if (wout
) free(wout
);
217 FILE *fopen_utf8(const char *filename
, const char *mode
)
219 wchar_t *wname
= NULL
;
220 wchar_t *wmode
= NULL
;
224 if (!(wname
= wchar_from_utf8(filename
))) break;
225 if (!(wmode
= wchar_from_utf8(mode
))) break;
226 f
= _wfopen(wname
, wmode
);
229 if (wname
) free(wname
);
230 if (wmode
) free(wmode
);
235 int _stat64_utf8(const char *path
, struct __stat64
*buffer
)
240 if (!(wpath
= wchar_from_utf8(path
))) return -1;
241 ret
= _wstat64(wpath
, buffer
);
247 int chmod_utf8(const char *filename
, int pmode
)
252 if (!(wname
= wchar_from_utf8(filename
))) return -1;
253 ret
= _wchmod(wname
, pmode
);
259 int utime_utf8(const char *filename
, struct utimbuf
*times
)
265 if (!(wname
= wchar_from_utf8(filename
))) return -1;
266 ret
= _wutime(wname
, &ut
);
270 if (sizeof(*times
) == sizeof(ut
)) {
271 memcpy(times
, &ut
, sizeof(ut
));
273 times
->actime
= ut
.actime
;
274 times
->modtime
= ut
.modtime
;
281 int unlink_utf8(const char *filename
)
286 if (!(wname
= wchar_from_utf8(filename
))) return -1;
287 ret
= _wunlink(wname
);
293 int rename_utf8(const char *oldname
, const char *newname
)
295 wchar_t *wold
= NULL
;
296 wchar_t *wnew
= NULL
;
300 if (!(wold
= wchar_from_utf8(oldname
))) break;
301 if (!(wnew
= wchar_from_utf8(newname
))) break;
302 ret
= _wrename(wold
, wnew
);
305 if (wold
) free(wold
);
306 if (wnew
) free(wnew
);