diff --git a/dosbox_pure_libretro.cpp b/dosbox_pure_libretro.cpp index 9b71a1e65..98db3dbe1 100644 --- a/dosbox_pure_libretro.cpp +++ b/dosbox_pure_libretro.cpp @@ -4180,44 +4180,94 @@ bool retro_load_game_special(unsigned type, const struct retro_game_info *info, void retro_deinit(void) { } // UTF8 fopen -#include "libretro-common/include/compat/fopen_utf8.h" -FILE *fopen_wrap(const char *path, const char *mode) +#include + +#ifdef WIN32 +wchar_t* AllocUTF8ToUTF16(const char *str) +{ + if (!str || !*str) return NULL; + wchar_t* res; + if (int len8 = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0)) + { + if (!(res = (wchar_t*)malloc(len8 * sizeof(wchar_t)))) return NULL; + if ((MultiByteToWideChar(CP_UTF8, 0, str, -1, res, len8)) < 0) { free(res); return NULL; } + } + if (int lena = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0)) // Fall back to ANSI codepage instead + { + if (!(res = (wchar_t*)malloc(lena * sizeof(wchar_t)))) return NULL; + if ((MultiByteToWideChar(CP_ACP, 0, str, -1, res, lena)) < 0) { free(res); return NULL; } + } + return res; +} +#ifndef S_ISDIR +#define S_ISDIR(m) (((m)&S_IFMT)==S_IFDIR) +#endif +#endif + +FILE* fopen_wrap(const char* path, const char* mode) { #ifdef WIN32 - for (const unsigned char* p = (unsigned char*)path; *p; p++) - if (*p >= 0x80) - return (FILE*)fopen_utf8(path, mode); + for (const char* p = path; *p; p++) { if ((Bit8u)*p > 0x7F) goto needw; } #endif return fopen(path, mode); + #ifdef WIN32 + needw: + wchar_t *wpath = AllocUTF8ToUTF16(path), wmode[20], *pwmode = wmode; + if (!wpath) return NULL; + for (const char* p = mode, *pEnd = p + 19; *p && p != pEnd; p++) *(pwmode++) = *p; + *pwmode = '\0'; + FILE* f = _wfopen(wpath, wmode); + free(wpath); + return f; + #endif +} + +static bool exists_utf8(const char* path, bool* out_is_dir) +{ + #ifdef WIN32 + for (const char* p = path; *p; p++) { if ((Bit8u)*p > 0x7F) goto needw; } + #endif + struct stat test; + if (stat(path, &test)) return false; + if (out_is_dir) *out_is_dir = !!S_ISDIR(test.st_mode); + return true; + #ifdef WIN32 + needw: + wchar_t *wpath = AllocUTF8ToUTF16(path); + if (!wpath) return NULL; + struct _stat64i32 wtest; + bool retval = !_wstat64i32(wpath, &wtest); + free(wpath); + if (out_is_dir && retval) *out_is_dir = !!S_ISDIR(wtest.st_mode); + return true; + #endif } + #ifndef STATIC_LINKING -#include "libretro-common/compat/fopen_utf8.c" -#include "libretro-common/compat/compat_strl.c" -#include "libretro-common/encodings/encoding_utf.c" #include "libretro-common/features/features_cpu.c" #endif -bool fpath_nocase(char* path) +bool fpath_nocase(std::string& pathstr, bool* out_is_dir) { - if (!path || !*path) return false; - struct stat test; - if (stat(path, &test) == 0) return true; // exists as is + if (pathstr.empty()) return false; + char* path = (char*)pathstr.c_str(); + if (exists_utf8(path, out_is_dir)) return true; // exists as is #ifdef WIN32 - // If stat could handle utf8 strings, we just return false here because paths are not case senstive on Windows - size_t rootlen = ((path[1] == ':' && (path[2] == '/' || path[2] == '\\')) ? 3 : 0); + // For absolute paths we just return false here because paths are not case sensitive on Windows + if ((path[1] == ':' && (path[2] == '/' || path[2] == '\\')) || (path[0] == '\\' && path[1] == '\\')) return false; #else size_t rootlen = ((path[0] == '/' || path[0] == '\\') ? 1 : 0); - #endif - if (!path[rootlen]) return false; + if (!path[rootlen]) { if (out_is_dir) *out_is_dir = true; return true; } // querying root directory std::string subdir; - const char* base_dir = (rootlen ? subdir.append(path, rootlen).c_str() : NULL); + const char* base_dir = (rootlen ? subdir.assign(path, rootlen).c_str() : NULL); path += rootlen; struct retro_vfs_interface_info vfs = { 3, NULL }; if (!environ_cb || !environ_cb(RETRO_ENVIRONMENT_GET_VFS_INTERFACE, &vfs) || vfs.required_interface_version < 3 || !vfs.iface) return false; + bool relative_to_content = false; for (char* psubdir;; *psubdir = CROSS_FILESPLIT, path = psubdir + 1) { char *next_slash = strchr(path, '/'), *next_bslash = strchr(path, '\\'); @@ -4226,6 +4276,7 @@ bool fpath_nocase(char* path) if (psubdir) *psubdir = '\0'; // On Android opendir fails for directories the user/app doesn't have access so just assume it exists as is + bool confirmed = false; if (struct retro_vfs_dir_handle *dir = (base_dir ? vfs.iface->opendir(base_dir, true) : NULL)) { while (dir && vfs.iface->readdir(dir)) @@ -4233,15 +4284,40 @@ bool fpath_nocase(char* path) const char* entry_name = vfs.iface->dirent_get_name(dir); if (strcasecmp(entry_name, path)) continue; strcpy(path, entry_name); + confirmed = true; + if (!psubdir && out_is_dir) *out_is_dir = vfs.iface->dirent_is_dir(dir); break; } vfs.iface->closedir(dir); } - if (!psubdir) return true; - if (subdir.empty() && base_dir) subdir = base_dir; - if (!subdir.empty() && subdir.back() != '/' && subdir.back() != '\\') subdir += CROSS_FILESPLIT; - base_dir = subdir.append(path).c_str(); + if (psubdir) + { + if (subdir.empty() && base_dir) subdir = base_dir; + if (!subdir.empty() && subdir.back() != '/' && subdir.back() != '\\') subdir += CROSS_FILESPLIT; + base_dir = subdir.append(path).c_str(); + continue; + } + + if (confirmed || rootlen) return true; + if (relative_to_content) return false; + #endif + + const char *content = dbp_content_path.c_str(), *content_fs = strrchr(content, '/'), *content_bs = strrchr(content, '\\'); + const char* content_dir_end = ((content_fs || content_bs) ? (content_fs > content_bs ? content_fs : content_bs) + 1 : content + dbp_content_path.length()); + if (content_dir_end == content) return false; + + pathstr.insert(0, content, (content_dir_end - content)); + if (!content_fs && !content_bs) pathstr.insert(((content_dir_end++) - content), 1, CROSS_FILESPLIT); + if (exists_utf8(pathstr.c_str(), out_is_dir)) return true; // exists relative to content as is + + #ifdef WIN32 + return false; + #else + base_dir = subdir.assign(pathstr.c_str(), content_dir_end - 1 - content).c_str(); + psubdir = (char*)pathstr.c_str() + subdir.length(); + relative_to_content = true; } + #endif } MYGL_FOR_EACH_PROC(MYGL_MAKEFUNCPTR) diff --git a/include/cross.h b/include/cross.h index 7bd9b36b9..99f8aa277 100644 --- a/include/cross.h +++ b/include/cross.h @@ -156,7 +156,7 @@ FILE *fopen_wrap(const char *path, const char *mode); #ifdef C_DBP_HAVE_FPATH_NOCASE // Check if path exists, will fix case in path // Returns true if file exists, otherwise path can be partially modified -bool fpath_nocase(char* path); +bool fpath_nocase(std::string& path, bool* out_is_dir = NULL); #endif //DBP: Use 64-bit fseek and ftell (based on libretro-common/vfs/vfs_implementation.c) diff --git a/libretro-common/compat/compat_strl.c b/libretro-common/compat/compat_strl.c deleted file mode 100644 index 5c8b0468a..000000000 --- a/libretro-common/compat/compat_strl.c +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright (C) 2010-2020 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (compat_strl.c). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include - -#include "../include/compat/strl.h" - -/* Implementation of strlcpy()/strlcat() based on OpenBSD. */ - -#ifndef __MACH__ - -size_t strlcpy(char *dest, const char *source, size_t size) -{ - size_t src_size = 0; - size_t n = size; - - if (n) - while (--n && (*dest++ = *source++)) src_size++; - - if (!n) - { - if (size) *dest = '\0'; - while (*source++) src_size++; - } - - return src_size; -} - -size_t strlcat(char *dest, const char *source, size_t size) -{ - size_t len = strlen(dest); - - dest += len; - - if (len > size) - size = 0; - else - size -= len; - - return len + strlcpy(dest, source, size); -} -#endif - -char *strldup(const char *s, size_t n) -{ - char *dst = (char*)malloc(sizeof(char) * (n + 1)); - strlcpy(dst, s, n); - return dst; -} diff --git a/libretro-common/compat/fopen_utf8.c b/libretro-common/compat/fopen_utf8.c deleted file mode 100644 index 337ddc27c..000000000 --- a/libretro-common/compat/fopen_utf8.c +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (C) 2010-2020 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (fopen_utf8.c). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "../include/compat/fopen_utf8.h" -#include "../include/encodings/utf.h" -#include -#include - -#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 || defined(_XBOX) -#ifndef LEGACY_WIN32 -#define LEGACY_WIN32 -#endif -#endif - -#ifdef _WIN32 -#undef fopen - -void *fopen_utf8(const char * filename, const char * mode) -{ -#if defined(LEGACY_WIN32) - FILE *ret = NULL; - char * filename_local = utf8_to_local_string_alloc(filename); - - if (!filename_local) - return NULL; - ret = fopen(filename_local, mode); - if (filename_local) - free(filename_local); - return ret; -#else - wchar_t * filename_w = utf8_to_utf16_string_alloc(filename); - wchar_t * mode_w = utf8_to_utf16_string_alloc(mode); - FILE* ret = NULL; - - if (filename_w && mode_w) - ret = _wfopen(filename_w, mode_w); - if (filename_w) - free(filename_w); - if (mode_w) - free(mode_w); - return ret; -#endif -} -#endif diff --git a/libretro-common/encodings/encoding_utf.c b/libretro-common/encodings/encoding_utf.c deleted file mode 100644 index b0bd1a223..000000000 --- a/libretro-common/encodings/encoding_utf.c +++ /dev/null @@ -1,512 +0,0 @@ -/* Copyright (C) 2010-2020 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (encoding_utf.c). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include -#include - -#include "../include/boolean.h" -#include "../include/compat/strl.h" -#include "../include/retro_inline.h" - -#include "../include/encodings/utf.h" - -#if defined(_WIN32) && !defined(_XBOX) -#include -#elif defined(_XBOX) -#include -#endif - -#define UTF8_WALKBYTE(string) (*((*(string))++)) - -static unsigned leading_ones(uint8_t c) -{ - unsigned ones = 0; - while (c & 0x80) - { - ones++; - c <<= 1; - } - - return ones; -} - -/* Simple implementation. Assumes the sequence is - * properly synchronized and terminated. */ - -size_t utf8_conv_utf32(uint32_t *out, size_t out_chars, - const char *in, size_t in_size) -{ - unsigned i; - size_t ret = 0; - while (in_size && out_chars) - { - unsigned extra, shift; - uint32_t c; - uint8_t first = *in++; - unsigned ones = leading_ones(first); - - if (ones > 6 || ones == 1) /* Invalid or desync. */ - break; - - extra = ones ? ones - 1 : ones; - if (1 + extra > in_size) /* Overflow. */ - break; - - shift = (extra - 1) * 6; - c = (first & ((1 << (7 - ones)) - 1)) << (6 * extra); - - for (i = 0; i < extra; i++, in++, shift -= 6) - c |= (*in & 0x3f) << shift; - - *out++ = c; - in_size -= 1 + extra; - out_chars--; - ret++; - } - - return ret; -} - -bool utf16_conv_utf8(uint8_t *out, size_t *out_chars, - const uint16_t *in, size_t in_size) -{ - size_t out_pos = 0; - size_t in_pos = 0; - static const - uint8_t utf8_limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - for (;;) - { - unsigned num_adds; - uint32_t value; - - if (in_pos == in_size) - { - *out_chars = out_pos; - return true; - } - value = in[in_pos++]; - if (value < 0x80) - { - if (out) - out[out_pos] = (char)value; - out_pos++; - continue; - } - - if (value >= 0xD800 && value < 0xE000) - { - uint32_t c2; - - if (value >= 0xDC00 || in_pos == in_size) - break; - c2 = in[in_pos++]; - if (c2 < 0xDC00 || c2 >= 0xE000) - break; - value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; - } - - for (num_adds = 1; num_adds < 5; num_adds++) - if (value < (((uint32_t)1) << (num_adds * 5 + 6))) - break; - if (out) - out[out_pos] = (char)(utf8_limits[num_adds - 1] - + (value >> (6 * num_adds))); - out_pos++; - do - { - num_adds--; - if (out) - out[out_pos] = (char)(0x80 - + ((value >> (6 * num_adds)) & 0x3F)); - out_pos++; - }while (num_adds != 0); - } - - *out_chars = out_pos; - return false; -} - -/* Acts mostly like strlcpy. - * - * Copies the given number of UTF-8 characters, - * but at most d_len bytes. - * - * Always NULL terminates. - * Does not copy half a character. - * - * Returns number of bytes. 's' is assumed valid UTF-8. - * Use only if 'chars' is considerably less than 'd_len'. */ -size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars) -{ - const uint8_t *sb = (const uint8_t*)s; - const uint8_t *sb_org = sb; - - if (!s) - return 0; - - while (*sb && chars-- > 0) - { - sb++; - while ((*sb & 0xC0) == 0x80) - sb++; - } - - if ((size_t)(sb - sb_org) > d_len-1 /* NUL */) - { - sb = sb_org + d_len-1; - while ((*sb & 0xC0) == 0x80) - sb--; - } - - memcpy(d, sb_org, sb-sb_org); - d[sb-sb_org] = '\0'; - - return sb-sb_org; -} - -const char *utf8skip(const char *str, size_t chars) -{ - const uint8_t *strb = (const uint8_t*)str; - - if (!chars) - return str; - - do - { - strb++; - while ((*strb & 0xC0)==0x80) - strb++; - chars--; - }while (chars); - - return (const char*)strb; -} - -size_t utf8len(const char *string) -{ - size_t ret = 0; - - if (!string) - return 0; - - while (*string) - { - if ((*string & 0xC0) != 0x80) - ret++; - string++; - } - return ret; -} - -/* Does not validate the input, returns garbage if it's not UTF-8. */ -uint32_t utf8_walk(const char **string) -{ - uint8_t first = UTF8_WALKBYTE(string); - uint32_t ret = 0; - - if (first < 128) - return first; - - ret = (ret << 6) | (UTF8_WALKBYTE(string) & 0x3F); - if (first >= 0xE0) - { - ret = (ret << 6) | (UTF8_WALKBYTE(string) & 0x3F); - if (first >= 0xF0) - { - ret = (ret << 6) | (UTF8_WALKBYTE(string) & 0x3F); - return ret | (first & 7) << 18; - } - return ret | (first & 15) << 12; - } - - return ret | (first & 31) << 6; -} - -static bool utf16_to_char(uint8_t **utf_data, - size_t *dest_len, const uint16_t *in) -{ - unsigned len = 0; - - while (in[len] != '\0') - len++; - - utf16_conv_utf8(NULL, dest_len, in, len); - *dest_len += 1; - *utf_data = (uint8_t*)malloc(*dest_len); - if (*utf_data == 0) - return false; - - return utf16_conv_utf8(*utf_data, dest_len, in, len); -} - -bool utf16_to_char_string(const uint16_t *in, char *s, size_t len) -{ - size_t dest_len = 0; - uint8_t *utf16_data = NULL; - bool ret = utf16_to_char(&utf16_data, &dest_len, in); - - if (ret) - { - utf16_data[dest_len] = 0; - strlcpy(s, (const char*)utf16_data, len); - } - - free(utf16_data); - utf16_data = NULL; - - return ret; -} - -#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE) -/* Returned pointer MUST be freed by the caller if non-NULL. */ -static char *mb_to_mb_string_alloc(const char *str, - enum CodePage cp_in, enum CodePage cp_out) -{ - wchar_t *path_buf_wide = NULL; - int path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0); - - /* Windows 95 will return 0 from these functions with - * a UTF8 codepage set without MSLU. - * - * From an unknown MSDN version (others omit this info): - * - CP_UTF8 Windows 98/Me, Windows NT 4.0 and later: - * Translate using UTF-8. When this is set, dwFlags must be zero. - * - Windows 95: Under the Microsoft Layer for Unicode, - * MultiByteToWideChar also supports CP_UTF7 and CP_UTF8. - */ - - if (!path_buf_wide_len) - return strdup(str); - - path_buf_wide = (wchar_t*) - calloc(path_buf_wide_len + sizeof(wchar_t), sizeof(wchar_t)); - - if (path_buf_wide) - { - MultiByteToWideChar(cp_in, 0, - str, -1, path_buf_wide, path_buf_wide_len); - - if (*path_buf_wide) - { - int path_buf_len = WideCharToMultiByte(cp_out, 0, - path_buf_wide, -1, NULL, 0, NULL, NULL); - - if (path_buf_len) - { - char *path_buf = (char*) - calloc(path_buf_len + sizeof(char), sizeof(char)); - - if (path_buf) - { - WideCharToMultiByte(cp_out, 0, - path_buf_wide, -1, path_buf, - path_buf_len, NULL, NULL); - - free(path_buf_wide); - - if (*path_buf) - return path_buf; - - free(path_buf); - return NULL; - } - } - else - { - free(path_buf_wide); - return strdup(str); - } - } - - free(path_buf_wide); - } - - return NULL; -} -#endif - -/* Returned pointer MUST be freed by the caller if non-NULL. */ -char* utf8_to_local_string_alloc(const char *str) -{ - if (str && *str) - { -#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE) - return mb_to_mb_string_alloc(str, CODEPAGE_UTF8, CODEPAGE_LOCAL); -#else - /* assume string needs no modification if not on Windows */ - return strdup(str); -#endif - } - return NULL; -} - -/* Returned pointer MUST be freed by the caller if non-NULL. */ -char* local_to_utf8_string_alloc(const char *str) -{ - if (str && *str) - { -#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE) - return mb_to_mb_string_alloc(str, CODEPAGE_LOCAL, CODEPAGE_UTF8); -#else - /* assume string needs no modification if not on Windows */ - return strdup(str); -#endif - } - return NULL; -} - -/* Returned pointer MUST be freed by the caller if non-NULL. */ -wchar_t* utf8_to_utf16_string_alloc(const char *str) -{ -#ifdef _WIN32 - int len = 0; - int out_len = 0; -#else - size_t len = 0; - size_t out_len = 0; -#endif - wchar_t *buf = NULL; - - if (!str || !*str) - return NULL; - -#ifdef _WIN32 - len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); - - if (len) - { - buf = (wchar_t*)calloc(len, sizeof(wchar_t)); - - if (!buf) - return NULL; - - out_len = MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, len); - } - else - { - /* fallback to ANSI codepage instead */ - len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); - - if (len) - { - buf = (wchar_t*)calloc(len, sizeof(wchar_t)); - - if (!buf) - return NULL; - - out_len = MultiByteToWideChar(CP_ACP, 0, str, -1, buf, len); - } - } - - if (out_len < 0) - { - free(buf); - return NULL; - } -#else - /* NOTE: For now, assume non-Windows platforms' locale is already UTF-8. */ - len = mbstowcs(NULL, str, 0) + 1; - - if (len) - { - buf = (wchar_t*)calloc(len, sizeof(wchar_t)); - - if (!buf) - return NULL; - - out_len = mbstowcs(buf, str, len); - } - - if (out_len == (size_t)-1) - { - free(buf); - return NULL; - } -#endif - - return buf; -} - -/* Returned pointer MUST be freed by the caller if non-NULL. */ -char* utf16_to_utf8_string_alloc(const wchar_t *str) -{ -#ifdef _WIN32 - int len = 0; -#else - size_t len = 0; -#endif - char *buf = NULL; - - if (!str || !*str) - return NULL; - -#ifdef _WIN32 - { - UINT code_page = CP_UTF8; - len = WideCharToMultiByte(code_page, - 0, str, -1, NULL, 0, NULL, NULL); - - /* fallback to ANSI codepage instead */ - if (!len) - { - code_page = CP_ACP; - len = WideCharToMultiByte(code_page, - 0, str, -1, NULL, 0, NULL, NULL); - } - - buf = (char*)calloc(len, sizeof(char)); - - if (!buf) - return NULL; - - if (WideCharToMultiByte(code_page, - 0, str, -1, buf, len, NULL, NULL) < 0) - { - free(buf); - return NULL; - } - } -#else - /* NOTE: For now, assume non-Windows platforms' - * locale is already UTF-8. */ - len = wcstombs(NULL, str, 0) + 1; - - if (len) - { - buf = (char*)calloc(len, sizeof(char)); - - if (!buf) - return NULL; - - if (wcstombs(buf, str, len) == (size_t)-1) - { - free(buf); - return NULL; - } - } -#endif - - return buf; -} diff --git a/libretro-common/features/features_cpu.c b/libretro-common/features/features_cpu.c index 6fdca9af1..dc0e13645 100644 --- a/libretro-common/features/features_cpu.c +++ b/libretro-common/features/features_cpu.c @@ -29,7 +29,6 @@ #include #endif -#include "../include/compat/strl.h" #include "../include/libretro.h" #include "../include/retro_timers.h" diff --git a/libretro-common/include/boolean.h b/libretro-common/include/boolean.h deleted file mode 100644 index 9d0d7c129..000000000 --- a/libretro-common/include/boolean.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (C) 2010-2020 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (boolean.h). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __LIBRETRO_SDK_BOOLEAN_H -#define __LIBRETRO_SDK_BOOLEAN_H - -#ifndef __cplusplus - -#if defined(_MSC_VER) && _MSC_VER < 1800 && !defined(SN_TARGET_PS3) -/* Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. */ -#define bool unsigned char -#define true 1 -#define false 0 -#else -#include -#endif - -#endif - -#endif diff --git a/libretro-common/include/compat/fopen_utf8.h b/libretro-common/include/compat/fopen_utf8.h deleted file mode 100644 index 97d4404e2..000000000 --- a/libretro-common/include/compat/fopen_utf8.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 2010-2020 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (fopen_utf8.h). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __LIBRETRO_SDK_COMPAT_FOPEN_UTF8_H -#define __LIBRETRO_SDK_COMPAT_FOPEN_UTF8_H - -#ifdef _WIN32 -/* Defined to error rather than fopen_utf8, to make it clear to everyone reading the code that not worrying about utf16 is fine */ -/* TODO: enable */ -/* #define fopen (use fopen_utf8 instead) */ -void *fopen_utf8(const char * filename, const char * mode); -#else -#define fopen_utf8 fopen -#endif -#endif diff --git a/libretro-common/include/compat/strl.h b/libretro-common/include/compat/strl.h deleted file mode 100644 index a0b7227eb..000000000 --- a/libretro-common/include/compat/strl.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (C) 2010-2020 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (strl.h). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __LIBRETRO_SDK_COMPAT_STRL_H -#define __LIBRETRO_SDK_COMPAT_STRL_H - -#include -#include - -#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H) -#include "../../../config.h" -#endif - -#include "../retro_common_api.h" - -RETRO_BEGIN_DECLS - -#ifdef __MACH__ -#ifndef HAVE_STRL -#define HAVE_STRL -#endif -#endif - -#ifndef HAVE_STRL -/* Avoid possible naming collisions during link since - * we prefer to use the actual name. */ -#define strlcpy(dst, src, size) strlcpy_retro__(dst, src, size) - -#define strlcat(dst, src, size) strlcat_retro__(dst, src, size) - -size_t strlcpy(char *dest, const char *source, size_t size); -size_t strlcat(char *dest, const char *source, size_t size); - -#endif - -char *strldup(const char *s, size_t n); - -RETRO_END_DECLS - -#endif diff --git a/libretro-common/include/encodings/utf.h b/libretro-common/include/encodings/utf.h deleted file mode 100644 index 27033fffe..000000000 --- a/libretro-common/include/encodings/utf.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (C) 2010-2020 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (utf.h). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _LIBRETRO_ENCODINGS_UTF_H -#define _LIBRETRO_ENCODINGS_UTF_H - -#include -#include - -#include "../boolean.h" - -#include "../retro_common_api.h" - -RETRO_BEGIN_DECLS - -enum CodePage -{ - CODEPAGE_LOCAL = 0, /* CP_ACP */ - CODEPAGE_UTF8 = 65001 /* CP_UTF8 */ -}; - -size_t utf8_conv_utf32(uint32_t *out, size_t out_chars, - const char *in, size_t in_size); - -bool utf16_conv_utf8(uint8_t *out, size_t *out_chars, - const uint16_t *in, size_t in_size); - -size_t utf8len(const char *string); - -size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars); - -const char *utf8skip(const char *str, size_t chars); - -uint32_t utf8_walk(const char **string); - -bool utf16_to_char_string(const uint16_t *in, char *s, size_t len); - -char* utf8_to_local_string_alloc(const char *str); - -char* local_to_utf8_string_alloc(const char *str); - -wchar_t* utf8_to_utf16_string_alloc(const char *str); - -char* utf16_to_utf8_string_alloc(const wchar_t *str); - -RETRO_END_DECLS - -#endif diff --git a/libretro-common/include/retro_common_api.h b/libretro-common/include/retro_common_api.h deleted file mode 100644 index 0f68b7d98..000000000 --- a/libretro-common/include/retro_common_api.h +++ /dev/null @@ -1,119 +0,0 @@ -/* Copyright (C) 2010-2020 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (retro_common_api.h). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _LIBRETRO_COMMON_RETRO_COMMON_API_H -#define _LIBRETRO_COMMON_RETRO_COMMON_API_H - -/* -This file is designed to normalize the libretro-common compiling environment -for public API headers. This should be leaner than a normal compiling environment, -since it gets #included into other project's sources. -*/ - -/* ------------------------------------ */ - -/* -Ordinarily we want to put #ifdef __cplusplus extern "C" in C library -headers to enable them to get used by c++ sources. -However, we want to support building this library as C++ as well, so a -special technique is called for. -*/ - -#define RETRO_BEGIN_DECLS -#define RETRO_END_DECLS - -#ifdef __cplusplus - -#ifdef CXX_BUILD -/* build wants everything to be built as c++, so no extern "C" */ -#else -#undef RETRO_BEGIN_DECLS -#undef RETRO_END_DECLS -#define RETRO_BEGIN_DECLS extern "C" { -#define RETRO_END_DECLS } -#endif - -#else - -/* header is included by a C source file, so no extern "C" */ - -#endif - -/* -IMO, this non-standard ssize_t should not be used. -However, it's a good example of how to handle something like this. -*/ -#ifdef _MSC_VER -#ifndef HAVE_SSIZE_T -#define HAVE_SSIZE_T -#if defined(_WIN64) -typedef __int64 ssize_t; -#elif defined(_WIN32) -typedef int ssize_t; -#endif -#endif -#elif defined(__MACH__) -#include -#endif - -#ifdef _MSC_VER -#if _MSC_VER >= 1800 -#include -#else -#ifndef PRId64 -#define PRId64 "I64d" -#define PRIu64 "I64u" -#define PRIuPTR "Iu" -#endif -#endif -#else -/* C++11 says this one isn't needed, but apparently (some versions of) mingw require it anyways */ -/* https://stackoverflow.com/questions/8132399/how-to-printf-uint64-t-fails-with-spurious-trailing-in-format */ -/* https://github.com/libretro/RetroArch/issues/6009 */ -#ifndef __STDC_FORMAT_MACROS -#define __STDC_FORMAT_MACROS 1 -#endif -#include -#endif -#ifndef PRId64 -#error "inttypes.h is being screwy" -#endif -#define STRING_REP_INT64 "%" PRId64 -#define STRING_REP_UINT64 "%" PRIu64 -#define STRING_REP_USIZE "%" PRIuPTR - -/* -I would like to see retro_inline.h moved in here; possibly boolean too. - -rationale: these are used in public APIs, and it is easier to find problems -and write code that works the first time portably when theyre included uniformly -than to do the analysis from scratch each time you think you need it, for each feature. - -Moreover it helps force you to make hard decisions: if you EVER bring in boolean.h, -then you should pay the price everywhere, so you can see how much grief it will cause. - -Of course, another school of thought is that you should do as little damage as possible -in as few places as possible... -*/ - -/* _LIBRETRO_COMMON_RETRO_COMMON_API_H */ -#endif diff --git a/libretro-common/include/retro_inline.h b/libretro-common/include/retro_inline.h deleted file mode 100644 index b27d6dd6d..000000000 --- a/libretro-common/include/retro_inline.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (C) 2010-2020 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (retro_inline.h). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __LIBRETRO_SDK_INLINE_H -#define __LIBRETRO_SDK_INLINE_H - -#ifndef INLINE - -#if defined(_WIN32) || defined(__INTEL_COMPILER) -#define INLINE __inline -#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L -#define INLINE inline -#elif defined(__GNUC__) -#define INLINE __inline__ -#else -#define INLINE -#endif - -#endif -#endif diff --git a/src/dos/cdrom_image.cpp b/src/dos/cdrom_image.cpp index 138bb3795..e8dc78909 100644 --- a/src/dos/cdrom_image.cpp +++ b/src/dos/cdrom_image.cpp @@ -1022,11 +1022,11 @@ bool CDROM_Interface_Image::GetRealFileName(string &filename, string &pathname) return true; } #else - if (fpath_nocase(filename.c_str())) return true; + if (fpath_nocase(filename)) return true; // check if file with path relative to cue file exists string tmpstr(pathname + "/" + filename); - if (fpath_nocase(tmpstr.c_str())) { + if (fpath_nocase(tmpstr)) { filename = tmpstr; return true; } diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index abdfd5fb2..190ef4d6c 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -314,6 +314,7 @@ class MOUNT : public Program { if (lastconfigdir.length()) temp_line = lastconfigdir + CROSS_FILESPLIT + temp_line; } #endif +#ifndef C_DBP_HAVE_FPATH_NOCASE struct stat test; //Win32 : strip tailing backslashes //os2: some special drive check @@ -377,6 +378,12 @@ class MOUNT : public Program { return; #endif } +#else + Cross::ResolveHomedir(temp_line); + bool path_is_dir; + if (!fpath_nocase(temp_line, &path_is_dir)) { WriteOut(MSG_Get("PROGRAM_MOUNT_ERROR_1"),temp_line.c_str()); return; } + if (!path_is_dir) { WriteOut(MSG_Get("PROGRAM_MOUNT_ERROR_2"),temp_line.c_str()); return; } +#endif if (temp_line[temp_line.size()-1]!=CROSS_FILESPLIT) temp_line+=CROSS_FILESPLIT; Bit8u bit8size=(Bit8u) sizes[1]; diff --git a/src/dos/drives.cpp b/src/dos/drives.cpp index d15a46dca..8d344546a 100644 --- a/src/dos/drives.cpp +++ b/src/dos/drives.cpp @@ -516,7 +516,7 @@ DOS_File *FindAndOpenDosFile(char const* filename, Bit32u *bsize, bool* writable std::string filename_s(filename); Cross::ResolveHomedir(filename_s); #ifdef C_DBP_HAVE_FPATH_NOCASE - if (!fpath_nocase(&filename_s[0])) return NULL; + if (!fpath_nocase(filename_s)) return NULL; #endif FILE* raw_file_h; if (writable && (raw_file_h = fopen_wrap(filename_s.c_str(), "rb+")) != NULL) {