vf_uspp: drop this filter
[mplayer.git] / osdep / io.c
blobfc0da617860f2405cb3b3922bfe4071ed7cd4281
1 /*
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/>.
21 #ifdef _WIN32
23 #include <windows.h>
24 #include <wchar.h>
25 #include <stdio.h>
26 #include <stddef.h>
28 #include "osdep/io.h"
29 #include "talloc.h"
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);
37 if (count <= 0)
38 abort();
39 wchar_t *ret = talloc_array(talloc_ctx, wchar_t, count);
40 MultiByteToWideChar(CP_UTF8, 0, s, -1, ret, count);
41 return ret;
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);
47 if (count <= 0)
48 abort();
49 char *ret = talloc_array(talloc_ctx, char, count);
50 WideCharToMultiByte(CP_UTF8, 0, s, -1, ret, count, NULL, NULL);
51 return ret;
54 #endif // _WIN32
56 #ifdef __MINGW32__
58 #include <io.h>
59 #include <fcntl.h>
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) {
69 win32_argc = 0;
70 wchar_t **argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc);
71 if (win32_argc <= 0 || !argv_w)
72 return;
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]);
80 LocalFree(argv_w);
83 *argc = win32_argc;
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 = _wstati64(wpath, buf);
91 talloc_free(wpath);
92 return res;
95 int mp_fprintf(FILE *stream, const char *format, ...)
97 va_list args;
98 int done = 0;
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)))
113 int isConsole;
114 filetype &= ~(FILE_TYPE_REMOTE);
115 if (filetype == FILE_TYPE_CHAR)
117 DWORD ConsoleMode;
118 int ret = GetConsoleMode(wstream, &ConsoleMode);
119 if (!ret && (GetLastError() == ERROR_INVALID_HANDLE))
120 isConsole = 0;
121 else
122 isConsole = 1;
124 else
125 isConsole = 0;
127 if (isConsole)
129 int nchars = vsnprintf(NULL, 0, format, args) + 1;
130 char *buf = talloc_array(NULL, char, nchars);
131 if (buf)
133 vsnprintf(buf, nchars, format, args);
134 wchar_t *out = mp_from_utf8(NULL, buf);
135 size_t nchars = wcslen(out);
136 talloc_free(buf);
137 done = WriteConsoleW(wstream, out, nchars, NULL, NULL);
138 talloc_free(out);
141 else
142 done = vfprintf(stream, format, args);
146 else
147 done = vfprintf(stream, format, args);
149 va_end(args);
151 return done;
154 int mp_open(const char *filename, int oflag, ...)
156 int mode = 0;
157 if (oflag & _O_CREAT) {
158 va_list va;
159 va_start(va, oflag);
160 mode = va_arg(va, int);
161 va_end(va);
163 wchar_t *wpath = mp_from_utf8(NULL, filename);
164 int res = _wopen(wpath, oflag, mode);
165 talloc_free(wpath);
166 return res;
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);
179 talloc_free(wpath);
180 return res;
183 struct mp_dir {
184 DIR crap; // must be first member
185 _WDIR *wdir;
186 union {
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);
201 talloc_free(wpath);
202 if (!wdir)
203 return NULL;
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));
208 mpdir->wdir = wdir;
209 return (DIR*)mpdir;
212 struct dirent* mp_readdir(DIR *dir)
214 struct mp_dir *mpdir = (struct mp_dir*)dir;
215 struct _wdirent *wdirent = _wreaddir(mpdir->wdir);
216 if (!wdirent)
217 return NULL;
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);
231 talloc_free(mpdir);
232 return res;
235 int mp_mkdir(const char *path, int mode)
237 wchar_t *wpath = mp_from_utf8(NULL, path);
238 int res = _wmkdir(wpath);
239 talloc_free(wpath);
240 return res;
243 #endif // __MINGW32__