2 * unicode/utf-8 I/O helpers and wrappers for Windows
4 * This file is part of mplayer2.
5 * Contains parts based on libav code (http://libav.org).
7 * mplayer2 is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * mplayer2 is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with mplayer2. If not, see <http://www.gnu.org/licenses/>.
31 //copied and modified from libav
32 //http://git.libav.org/?p=libav.git;a=blob;f=libavformat/os_support.c;h=a0fcd6c9ba2be4b0dbcc476f6c53587345cc1152;hb=HEADl30
34 wchar_t *mp_from_utf8(void *talloc_ctx
, const char *s
)
36 int count
= MultiByteToWideChar(CP_UTF8
, 0, s
, -1, NULL
, 0);
39 wchar_t *ret
= talloc_array(talloc_ctx
, wchar_t, count
);
40 MultiByteToWideChar(CP_UTF8
, 0, s
, -1, ret
, count
);
44 char *mp_to_utf8(void *talloc_ctx
, const wchar_t *s
)
46 int count
= WideCharToMultiByte(CP_UTF8
, 0, s
, -1, NULL
, 0, NULL
, NULL
);
49 char *ret
= talloc_array(talloc_ctx
, char, count
);
50 WideCharToMultiByte(CP_UTF8
, 0, s
, -1, ret
, count
, NULL
, NULL
);
61 //http://git.libav.org/?p=libav.git;a=blob;f=cmdutils.c;h=ade3f10ce2fc030e32e375a85fbd06c26d43a433#l161
63 static char** win32_argv_utf8
;
64 static int win32_argc
;
66 void mp_get_converted_argv(int *argc
, char ***argv
)
68 if (!win32_argv_utf8
) {
70 wchar_t **argv_w
= CommandLineToArgvW(GetCommandLineW(), &win32_argc
);
71 if (win32_argc
<= 0 || !argv_w
)
74 win32_argv_utf8
= talloc_zero_array(NULL
, char*, win32_argc
+ 1);
76 for (int i
= 0; i
< win32_argc
; i
++) {
77 win32_argv_utf8
[i
] = mp_to_utf8(NULL
, argv_w
[i
]);
84 *argv
= win32_argv_utf8
;
87 int mp_stat(const char *path
, struct stat
*buf
)
89 wchar_t *wpath
= mp_from_utf8(NULL
, path
);
90 int res
= _wstat64(wpath
, buf
);
95 int mp_fprintf(FILE *stream
, const char *format
, ...)
100 va_start(args
, format
);
102 if (stream
== stdout
|| stream
== stderr
)
104 HANDLE
*wstream
= GetStdHandle(stream
== stdout
?
105 STD_OUTPUT_HANDLE
: STD_ERROR_HANDLE
);
106 if (wstream
!= INVALID_HANDLE_VALUE
)
108 // figure out whether we're writing to a console
109 unsigned int filetype
= GetFileType(wstream
);
110 if (!((filetype
== FILE_TYPE_UNKNOWN
) &&
111 (GetLastError() != ERROR_SUCCESS
)))
114 filetype
&= ~(FILE_TYPE_REMOTE
);
115 if (filetype
== FILE_TYPE_CHAR
)
118 int ret
= GetConsoleMode(wstream
, &ConsoleMode
);
119 if (!ret
&& (GetLastError() == ERROR_INVALID_HANDLE
))
129 int nchars
= vsnprintf(NULL
, 0, format
, args
) + 1;
130 char *buf
= talloc_array(NULL
, char, nchars
);
133 vsnprintf(buf
, nchars
, format
, args
);
134 wchar_t *out
= mp_from_utf8(NULL
, buf
);
135 size_t nchars
= wcslen(out
);
137 done
= WriteConsoleW(wstream
, out
, nchars
, NULL
, NULL
);
142 done
= vfprintf(stream
, format
, args
);
147 done
= vfprintf(stream
, format
, args
);
154 int mp_open(const char *filename
, int oflag
, ...)
157 if (oflag
& _O_CREAT
) {
160 mode
= va_arg(va
, int);
163 wchar_t *wpath
= mp_from_utf8(NULL
, filename
);
164 int res
= _wopen(wpath
, oflag
, mode
);
169 int mp_creat(const char *filename
, int mode
)
171 return open(filename
, O_CREAT
|O_WRONLY
|O_TRUNC
, mode
);
174 FILE *mp_fopen(const char *filename
, const char *mode
)
176 wchar_t *wpath
= mp_from_utf8(NULL
, filename
);
177 wchar_t *wmode
= mp_from_utf8(wpath
, mode
);
178 FILE *res
= _wfopen(wpath
, wmode
);
184 DIR crap
; // must be first member
187 struct dirent dirent
;
188 // dirent has space only for FILENAME_MAX bytes. _wdirent has space for
189 // FILENAME_MAX wchar_t, which might end up bigger as UTF-8 in some
190 // cases. Guarantee we can always hold _wdirent.d_name converted to
191 // UTF-8 (see MP_PATH_MAX).
192 // This works because dirent.d_name is the last member of dirent.
193 char space
[MP_PATH_MAX
];
197 DIR* mp_opendir(const char *path
)
199 wchar_t *wpath
= mp_from_utf8(NULL
, path
);
200 _WDIR
*wdir
= _wopendir(wpath
);
204 struct mp_dir
*mpdir
= talloc(NULL
, struct mp_dir
);
205 // DIR is supposed to be opaque, but unfortunately the MinGW headers still
206 // define it. Make sure nobody tries to use it.
207 memset(&mpdir
->crap
, 0xCD, sizeof(mpdir
->crap
));
212 struct dirent
* mp_readdir(DIR *dir
)
214 struct mp_dir
*mpdir
= (struct mp_dir
*)dir
;
215 struct _wdirent
*wdirent
= _wreaddir(mpdir
->wdir
);
218 size_t buffersize
= sizeof(mpdir
->space
) - offsetof(struct dirent
, d_name
);
219 WideCharToMultiByte(CP_UTF8
, 0, wdirent
->d_name
, -1, mpdir
->dirent
.d_name
,
220 buffersize
, NULL
, NULL
);
221 mpdir
->dirent
.d_ino
= 0;
222 mpdir
->dirent
.d_reclen
= 0;
223 mpdir
->dirent
.d_namlen
= strlen(mpdir
->dirent
.d_name
);
224 return &mpdir
->dirent
;
227 int mp_closedir(DIR *dir
)
229 struct mp_dir
*mpdir
= (struct mp_dir
*)dir
;
230 int res
= _wclosedir(mpdir
->wdir
);
235 int mp_mkdir(const char *path
, int mode
)
237 wchar_t *wpath
= mp_from_utf8(NULL
, path
);
238 int res
= _wmkdir(wpath
);
243 #endif // __MINGW32__