mirror of
https://github.com/CTCaer/RetroArch.git
synced 2025-02-12 06:51:16 +00:00
Merge pull request #5552 from bparker06/win32_file_encoding
win32: support local multibyte encoding for file paths
This commit is contained in:
commit
e86e237ed7
@ -3701,15 +3701,15 @@ bool config_save_file(const char *path)
|
||||
if (settings->bools.ssh_enable)
|
||||
fclose(fopen(LAKKA_SSH_PATH, "w"));
|
||||
else
|
||||
remove(LAKKA_SSH_PATH);
|
||||
path_file_remove(LAKKA_SSH_PATH);
|
||||
if (settings->bools.samba_enable)
|
||||
fclose(fopen(LAKKA_SAMBA_PATH, "w"));
|
||||
else
|
||||
remove(LAKKA_SAMBA_PATH);
|
||||
path_file_remove(LAKKA_SAMBA_PATH);
|
||||
if (settings->bools.bluetooth_enable)
|
||||
fclose(fopen(LAKKA_BLUETOOTH_PATH, "w"));
|
||||
else
|
||||
remove(LAKKA_BLUETOOTH_PATH);
|
||||
path_file_remove(LAKKA_BLUETOOTH_PATH);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
|
@ -241,7 +241,7 @@ bool input_remapping_remove_file(const char *path)
|
||||
|
||||
fill_pathname_noext(remap_file, buf, ".rmp", path_size);
|
||||
|
||||
ret = remove(remap_file) == 0 ? true : false;;
|
||||
ret = path_file_remove(remap_file) == 0 ? true : false;;
|
||||
free(buf);
|
||||
free(remap_file);
|
||||
return ret;
|
||||
|
@ -20,6 +20,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
@ -31,6 +32,15 @@
|
||||
|
||||
#include <encodings/utf.h>
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
#include <windows.h>
|
||||
|
||||
/* Starting with Windows 8: MultiByteToWideChar is declared in stringapiset.h. Before Windows 8, it was declared in winnls.h (which windows.h includes for us). */
|
||||
#ifndef MultiByteToWideChar
|
||||
#include <stringapiset.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static INLINE unsigned leading_ones(uint8_t c)
|
||||
{
|
||||
unsigned ones = 0;
|
||||
@ -267,3 +277,81 @@ bool utf16_to_char_string(const uint16_t *in, char *s, size_t len)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
char *path_buf = NULL;
|
||||
wchar_t *path_buf_wide = NULL;
|
||||
int path_buf_len = 0;
|
||||
int path_buf_wide_len = 0;
|
||||
|
||||
if (!str || !*str)
|
||||
return NULL;
|
||||
|
||||
#if !defined(_WIN32) || defined(_XBOX)
|
||||
/* assume string needs no modification if not on Windows */
|
||||
return strdup(str);
|
||||
#else
|
||||
#ifdef UNICODE
|
||||
/* TODO/FIXME: Not implemented. */
|
||||
return strdup(str);
|
||||
#else
|
||||
|
||||
path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
|
||||
|
||||
if (path_buf_wide_len)
|
||||
{
|
||||
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)
|
||||
{
|
||||
path_buf_len = WideCharToMultiByte(cp_out, 0, path_buf_wide, -1, NULL, 0, NULL, NULL);
|
||||
|
||||
if (path_buf_len)
|
||||
{
|
||||
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;
|
||||
else
|
||||
{
|
||||
free(path_buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (path_buf_wide)
|
||||
free(path_buf_wide);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||
char* utf8_to_local_string_alloc(const char *str)
|
||||
{
|
||||
return mb_to_mb_string_alloc(str, CODEPAGE_UTF8, CODEPAGE_LOCAL);
|
||||
}
|
||||
|
||||
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||
char* local_to_utf8_string_alloc(const char *str)
|
||||
{
|
||||
return mb_to_mb_string_alloc(str, CODEPAGE_LOCAL, CODEPAGE_UTF8);
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#endif
|
||||
#include <compat/strcasestr.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <encodings/utf.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifdef _MSC_VER
|
||||
@ -115,9 +116,18 @@ static bool path_stat(const char *path, enum stat_mode mode, int32_t *size)
|
||||
return false;
|
||||
#elif defined(_WIN32)
|
||||
struct _stat buf;
|
||||
DWORD file_info = GetFileAttributes(path);
|
||||
|
||||
_stat(path, &buf);
|
||||
if (!path || !*path)
|
||||
return false;
|
||||
|
||||
char *path_local = utf8_to_local_string_alloc(path);
|
||||
|
||||
DWORD file_info = GetFileAttributes(path_local);
|
||||
|
||||
_stat(path_local, &buf);
|
||||
|
||||
if (path_local)
|
||||
free(path_local);
|
||||
|
||||
if (file_info == INVALID_FILE_ATTRIBUTES)
|
||||
return false;
|
||||
@ -365,8 +375,8 @@ bool path_is_compressed_file(const char* path)
|
||||
* Returns: true (1) if file already exists, otherwise false (0).
|
||||
*/
|
||||
bool path_file_exists(const char *path)
|
||||
{
|
||||
FILE *dummy;
|
||||
{
|
||||
FILE *dummy;
|
||||
|
||||
if (!path || !*path)
|
||||
return false;
|
||||
@ -884,3 +894,24 @@ void fill_short_pathname_representation_noext(char* out_rep,
|
||||
fill_short_pathname_representation(out_rep, in_path, size);
|
||||
path_remove_extension(out_rep);
|
||||
}
|
||||
|
||||
int path_file_remove(const char *path)
|
||||
{
|
||||
if (!path || !*path)
|
||||
return false;
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
char *path_local = utf8_to_local_string_alloc(path);
|
||||
|
||||
if (path_local)
|
||||
{
|
||||
bool ret = remove(path_local);
|
||||
free(path_local);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
return remove(path);
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -28,6 +28,8 @@
|
||||
|
||||
#include <boolean.h>
|
||||
#include <retro_dirent.h>
|
||||
#include <encodings/utf.h>
|
||||
#include <compat/strl.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
# ifdef _MSC_VER
|
||||
@ -89,6 +91,7 @@ struct RDIR *retro_opendir(const char *name)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
char path_buf[1024];
|
||||
char *path_local = NULL;
|
||||
#endif
|
||||
struct RDIR *rdir = (struct RDIR*)calloc(1, sizeof(*rdir));
|
||||
|
||||
@ -98,7 +101,11 @@ struct RDIR *retro_opendir(const char *name)
|
||||
#if defined(_WIN32)
|
||||
path_buf[0] = '\0';
|
||||
snprintf(path_buf, sizeof(path_buf), "%s\\*", name);
|
||||
rdir->directory = FindFirstFile(path_buf, &rdir->entry);
|
||||
path_local = utf8_to_local_string_alloc(path_buf);
|
||||
rdir->directory = FindFirstFile(path_local, &rdir->entry);
|
||||
|
||||
if (path_local)
|
||||
free(path_local);
|
||||
#elif defined(VITA) || defined(PSP)
|
||||
rdir->directory = sceIoDopen(name);
|
||||
#elif defined(_3DS)
|
||||
@ -149,6 +156,12 @@ int retro_readdir(struct RDIR *rdir)
|
||||
const char *retro_dirent_get_name(struct RDIR *rdir)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
char *name_local = local_to_utf8_string_alloc(rdir->entry.cFileName);
|
||||
memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
|
||||
strlcpy(rdir->entry.cFileName, name_local, sizeof(rdir->entry.cFileName));
|
||||
|
||||
if (name_local)
|
||||
free(name_local);
|
||||
return rdir->entry.cFileName;
|
||||
#elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__)
|
||||
return rdir->entry.d_name;
|
||||
|
@ -32,6 +32,12 @@
|
||||
|
||||
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);
|
||||
|
||||
@ -48,6 +54,10 @@ 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);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -466,6 +466,8 @@ bool path_is_valid(const char *path);
|
||||
|
||||
int32_t path_get_size(const char *path);
|
||||
|
||||
int path_file_remove(const char *path);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -65,6 +65,7 @@
|
||||
#include <string/stdstring.h>
|
||||
#include <memmap.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <encodings/utf.h>
|
||||
|
||||
struct RFILE
|
||||
{
|
||||
@ -140,6 +141,9 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len)
|
||||
const char *mode_str = NULL;
|
||||
#endif
|
||||
RFILE *stream = (RFILE*)calloc(1, sizeof(*stream));
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
char *path_local = NULL;
|
||||
#endif
|
||||
|
||||
if (!stream)
|
||||
return NULL;
|
||||
@ -228,7 +232,14 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len)
|
||||
#if defined(HAVE_BUFFERED_IO)
|
||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0 && mode_str)
|
||||
{
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
path_local = utf8_to_local_string_alloc(path);
|
||||
stream->fp = fopen(path_local, mode_str);
|
||||
if (path_local)
|
||||
free(path_local);
|
||||
#else
|
||||
stream->fp = fopen(path, mode_str);
|
||||
#endif
|
||||
if (!stream->fp)
|
||||
goto error;
|
||||
}
|
||||
@ -236,7 +247,14 @@ RFILE *filestream_open(const char *path, unsigned mode, ssize_t len)
|
||||
#endif
|
||||
{
|
||||
/* FIXME: HAVE_BUFFERED_IO is always 1, but if it is ever changed, open() needs to be changed to _wopen() for WIndows. */
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
path_local = utf8_to_local_string_alloc(path);
|
||||
stream->fd = open(path_local, flags, mode_int);
|
||||
if (path_local)
|
||||
free(path_local);
|
||||
#else
|
||||
stream->fd = open(path, flags, mode_int);
|
||||
#endif
|
||||
if (stream->fd == -1)
|
||||
goto error;
|
||||
#ifdef HAVE_MMAP
|
||||
|
@ -2643,7 +2643,7 @@ static void cb_decompressed(void *task_data, void *user_data, const char *err)
|
||||
if (dec)
|
||||
{
|
||||
if (path_file_exists(dec->source_file))
|
||||
remove(dec->source_file);
|
||||
path_file_remove(dec->source_file);
|
||||
|
||||
free(dec->source_file);
|
||||
free(dec);
|
||||
@ -4242,7 +4242,7 @@ static int action_ok_core_delete(const char *path,
|
||||
generic_action_ok_command(CMD_EVENT_UNLOAD_CORE);
|
||||
menu_entries_flush_stack(0, 0);
|
||||
|
||||
if (remove(core_path) != 0) { }
|
||||
if (path_file_remove(core_path) != 0) { }
|
||||
|
||||
free(core_path);
|
||||
|
||||
|
@ -1860,7 +1860,7 @@ static void systemd_service_toggle(const char *path, char *unit, bool enable)
|
||||
if (enable)
|
||||
fclose(fopen(path, "w"));
|
||||
else
|
||||
remove(path);
|
||||
path_file_remove(path);
|
||||
|
||||
if (pid == 0)
|
||||
execvp(args[0], args);
|
||||
|
@ -1717,7 +1717,7 @@ void content_deinit(void)
|
||||
|
||||
RARCH_LOG("%s: %s.\n",
|
||||
msg_hash_to_str(MSG_REMOVING_TEMPORARY_CONTENT_FILE), path);
|
||||
if (remove(path) < 0)
|
||||
if (path_file_remove(path) < 0)
|
||||
RARCH_ERR("%s: %s.\n",
|
||||
msg_hash_to_str(MSG_FAILED_TO_REMOVE_TEMPORARY_FILE),
|
||||
path);
|
||||
|
Loading…
x
Reference in New Issue
Block a user