# HG changeset patch # User Ryan C. Gordon # Date 1254988117 0 # Node ID 261ad7b40a31fded459b6d87aa7badb4134d4308 # Parent cd511a8560b75dc3b658cd3c53867279db9180f8 Allow Unicode filenames in RWOPS on Windows. Fixes Bugzilla #733. diff -r cd511a8560b7 -r 261ad7b40a31 src/file/SDL_rwops.c --- a/src/file/SDL_rwops.c Thu Oct 08 07:45:55 2009 +0000 +++ b/src/file/SDL_rwops.c Thu Oct 08 07:48:37 2009 +0000 @@ -102,14 +102,74 @@ SDL_stack_free(filenameW); } #else - /* Do not open a dialog box if failure */ - old_error_mode = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); + { + + /* handle Unicode filenames. We do some tapdancing here to make sure this + works on Win9x, which doesn't support anything but 1-byte codepages. */ + const size_t size = SDL_strlen(filename)+1; + static int unicode_support = -1; + + if (unicode_support == -1) { + OSVERSIONINFO osVerInfo; /* Information about the OS */ + osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo); + if (!GetVersionEx(&osVerInfo)) { + unicode_support = 0; + } else if (osVerInfo.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) { + unicode_support = 1; /* Not Win95/98/ME. */ + } else { + unicode_support = 0; + } + } + + if (unicode_support) { /* everything but Win95/98/ME. */ + wchar_t *filenameW = SDL_stack_alloc(wchar_t, size); + if ( MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, size) == 0 ) { + SDL_stack_free(filenameW); + SDL_free(context->hidden.win32io.buffer.data); + context->hidden.win32io.buffer.data = NULL; + SDL_SetError("Unable to convert filename to Unicode"); + return -1; + } - h = CreateFile(filename, (w_right|r_right), (w_right)? 0 : FILE_SHARE_READ, - NULL, (must_exist|truncate|a_mode), FILE_ATTRIBUTE_NORMAL,NULL); + /* Do not open a dialog box if failure */ + old_error_mode = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); + h = CreateFileW(filenameW, (w_right|r_right), (w_right)? 0 : FILE_SHARE_READ, + NULL, (must_exist|truncate|a_mode), FILE_ATTRIBUTE_NORMAL,NULL); + /* restore old behaviour */ + SetErrorMode(old_error_mode); + + SDL_stack_free(filenameW); + } else { + /* CP_UTF8 might not be supported (Win95), so use SDL_iconv to get wchars. */ + /* Use UCS2: no UTF-16 support here. Try again in SDL 1.3. :) */ + char *utf16 = SDL_iconv_string("UCS2", "UTF8", filename, SDL_strlen(filename) + 1); + char *filenameA = SDL_stack_alloc(char, size * 6); /* 6, just in case. */ + BOOL bDefCharUsed = FALSE; - /* restore old behaviour */ - SetErrorMode(old_error_mode); + /* Dither down to a codepage and hope for the best. */ + if (!utf16 || + !WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)utf16, -1, filenameA, size*6, 0, &bDefCharUsed) || + bDefCharUsed) { + SDL_stack_free(filenameA); + SDL_free(utf16); + SDL_free(context->hidden.win32io.buffer.data); + context->hidden.win32io.buffer.data = NULL; + SDL_SetError("Unable to convert filename to Unicode"); + return -1; + } + + /* Do not open a dialog box if failure */ + old_error_mode = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); + h = CreateFile(filenameA, (w_right|r_right), (w_right)? 0 : FILE_SHARE_READ, + NULL, (must_exist|truncate|a_mode), FILE_ATTRIBUTE_NORMAL,NULL); + /* restore old behaviour */ + SetErrorMode(old_error_mode); + + SDL_stack_free(filenameA); + SDL_free(utf16); + } + + } #endif /* _WIN32_WCE */ if (h==INVALID_HANDLE_VALUE) {