rewrite the emulator to use UTF-8 internally

This commit is contained in:
David Hrdlička
2021-03-14 20:35:01 +01:00
parent 56d62de4fe
commit dfbbe08a07
146 changed files with 1507 additions and 1457 deletions

View File

@@ -31,6 +31,7 @@
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <direct.h>
#include <wchar.h>
#include <io.h>
#define HAVE_STDARG_H
@@ -66,6 +67,7 @@ HINSTANCE hinstance; /* application instance */
HANDLE ghMutex;
LCID lang_id; /* current language ID used */
DWORD dwSubLangID;
int acp_utf8; /* Windows supports UTF-8 codepage */
/* Local data. */
@@ -81,7 +83,7 @@ static rc_str_t *lpRCstr2048,
*lpRCstr6144,
*lpRCstr7168;
static int vid_api_inited = 0;
static wchar_t *argbuf;
static char *argbuf;
static int first_use = 1;
static LARGE_INTEGER StartingTime;
static LARGE_INTEGER Frequency;
@@ -181,6 +183,36 @@ LoadCommonStrings(void)
}
size_t mbstoc16s(uint16_t dst[], const char src[], int len)
{
if (src == NULL) return 0;
if (len < 0) return 0;
size_t ret = MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, dst == NULL ? 0 : len);
if (!ret) {
return -1;
}
return ret;
}
size_t c16stombs(char dst[], const uint16_t src[], int len)
{
if (src == NULL) return 0;
if (len < 0) return 0;
size_t ret = WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, dst == NULL ? 0 : len, NULL, NULL);
if (!ret) {
return -1;
}
return ret;
}
/* Set (or re-set) the language for the application. */
void
set_language(int id)
@@ -302,21 +334,25 @@ CloseConsole(void)
/* Process the commandline, and create standard argc/argv array. */
static int
ProcessCommandLine(wchar_t ***argw)
ProcessCommandLine(char ***argv)
{
WCHAR *cmdline;
wchar_t **args;
char **args;
int argc_max;
int i, q, argc;
cmdline = GetCommandLine();
i = wcslen(cmdline) + 1;
argbuf = (wchar_t *)malloc(sizeof(wchar_t)*i);
wcscpy(argbuf, cmdline);
if (acp_utf8) {
i = strlen(GetCommandLineA()) + 1;
argbuf = (char *)malloc(i);
strcpy(argbuf, GetCommandLineA());
} else {
i = c16stombs(NULL, GetCommandLineW(), 0) + 1;
argbuf = (char *)malloc(i);
c16stombs(argbuf, GetCommandLineW(), i);
}
argc = 0;
argc_max = 64;
args = (wchar_t **)malloc(sizeof(wchar_t *) * argc_max);
args = (char **)malloc(sizeof(char *) * argc_max);
if (args == NULL) {
free(argbuf);
return(0);
@@ -325,11 +361,11 @@ ProcessCommandLine(wchar_t ***argw)
/* parse commandline into argc/argv format */
i = 0;
while (argbuf[i]) {
while (argbuf[i] == L' ')
while (argbuf[i] == ' ')
i++;
if (argbuf[i]) {
if ((argbuf[i] == L'\'') || (argbuf[i] == L'"')) {
if ((argbuf[i] == '\'') || (argbuf[i] == '"')) {
q = argbuf[i++];
if (!argbuf[i])
break;
@@ -340,7 +376,7 @@ ProcessCommandLine(wchar_t ***argw)
if (argc >= argc_max) {
argc_max += 64;
args = realloc(args, sizeof(wchar_t *)*argc_max);
args = realloc(args, sizeof(char *)*argc_max);
if (args == NULL) {
free(argbuf);
return(0);
@@ -348,7 +384,7 @@ ProcessCommandLine(wchar_t ***argw)
}
while ((argbuf[i]) && ((q)
? (argbuf[i]!=q) : (argbuf[i]!=L' '))) i++;
? (argbuf[i]!=q) : (argbuf[i]!=' '))) i++;
if (argbuf[i]) {
argbuf[i] = 0;
@@ -358,7 +394,7 @@ ProcessCommandLine(wchar_t ***argw)
}
args[argc] = NULL;
*argw = args;
*argv = args;
return(argc);
}
@@ -368,12 +404,18 @@ ProcessCommandLine(wchar_t ***argw)
int WINAPI
WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow)
{
wchar_t **argw = NULL;
char **argv = NULL;
int argc, i;
wchar_t * AppID = L"86Box.86Box\0";
SetCurrentProcessExplicitAppUserModelID(AppID);
/* Check if Windows supports UTF-8 */
if (GetACP() == CP_UTF8)
acp_utf8 = 1;
else
acp_utf8 = 0;
/* Set this to the default value (windowed mode). */
video_fullscreen = 0;
@@ -387,10 +429,10 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow)
set_language(0x0409);
/* Process the command line for options. */
argc = ProcessCommandLine(&argw);
argc = ProcessCommandLine(&argv);
/* Pre-initialize the system, this loads the config file. */
if (! pc_init(argc, argw)) {
if (! pc_init(argc, argv)) {
/* Detach from console. */
if (force_debug)
CreateConsole(0);
@@ -399,7 +441,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow)
PostMessage((HWND) (uintptr_t) source_hwnd, WM_HAS_SHUTDOWN, (WPARAM) 0, (LPARAM) hwndMain);
free(argbuf);
free(argw);
free(argv);
return(1);
}
@@ -417,7 +459,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow)
i = ui_init(nCmdShow);
free(argbuf);
free(argw);
free(argv);
return(i);
}
@@ -507,87 +549,152 @@ do_stop(void)
void
plat_get_exe_name(wchar_t *s, int size)
plat_get_exe_name(char *s, int size)
{
GetModuleFileName(hinstance, s, size);
wchar_t *temp;
if (acp_utf8)
GetModuleFileNameA(hinstance, s, size);
else {
temp = malloc(size * sizeof(wchar_t));
GetModuleFileNameW(hinstance, temp, size);
c16stombs(s, temp, size);
free(temp);
}
}
void
plat_tempfile(wchar_t *bufp, wchar_t *prefix, wchar_t *suffix)
plat_tempfile(char *bufp, char *prefix, char *suffix)
{
SYSTEMTIME SystemTime;
char temp[1024];
if (prefix != NULL)
sprintf(temp, "%ls-", prefix);
sprintf(bufp, "%s-", prefix);
else
strcpy(temp, "");
strcpy(bufp, "");
GetSystemTime(&SystemTime);
sprintf(&temp[strlen(temp)], "%d%02d%02d-%02d%02d%02d-%03d%ls",
sprintf(&bufp[strlen(bufp)], "%d%02d%02d-%02d%02d%02d-%03d%s",
SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay,
SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond,
SystemTime.wMilliseconds,
suffix);
mbstowcs(bufp, temp, strlen(temp)+1);
}
int
plat_getcwd(wchar_t *bufp, int max)
plat_getcwd(char *bufp, int max)
{
(void)_wgetcwd(bufp, max);
wchar_t *temp;
if (acp_utf8)
(void)_getcwd(bufp, max);
else {
temp = malloc(max * sizeof(wchar_t));
(void)_wgetcwd(temp, max);
c16stombs(bufp, temp, max);
free(temp);
}
return(0);
}
int
plat_chdir(wchar_t *path)
plat_chdir(char *path)
{
return(_wchdir(path));
wchar_t *temp;
int len, ret;
if (acp_utf8)
return(_chdir(path));
else {
len = mbstoc16s(NULL, path, 0) + 1;
temp = malloc(len * sizeof(wchar_t));
mbstoc16s(temp, path, len);
ret = _wchdir(temp);
free(temp);
return ret;
}
}
FILE *
plat_fopen(wchar_t *path, wchar_t *mode)
plat_fopen(const char *path, const char *mode)
{
return(_wfopen(path, mode));
wchar_t *pathw, *modew;
int len;
FILE *fp;
if (acp_utf8)
return fopen(path, mode);
else {
len = mbstoc16s(NULL, path, 0) + 1;
pathw = malloc(sizeof(wchar_t) * len);
mbstoc16s(pathw, path, len);
len = mbstoc16s(NULL, mode, 0) + 1;
modew = malloc(sizeof(wchar_t) * len);
mbstoc16s(modew, mode, len);
fp = _wfopen(pathw, modew);
free(pathw);
free(modew);
return fp;
}
}
/* Open a file, using Unicode pathname, with 64bit pointers. */
FILE *
plat_fopen64(const wchar_t *path, const wchar_t *mode)
plat_fopen64(const char *path, const char *mode)
{
return(_wfopen(path, mode));
return plat_fopen(path, mode);
}
void
plat_remove(wchar_t *path)
plat_remove(char *path)
{
_wremove(path);
wchar_t *temp;
int len;
if (acp_utf8)
remove(path);
else {
len = mbstoc16s(NULL, path, 0) + 1;
temp = malloc(len * sizeof(wchar_t));
mbstoc16s(temp, path, len);
_wremove(temp);
free(temp);
}
}
/* Make sure a path ends with a trailing (back)slash. */
void
plat_path_slash(wchar_t *path)
plat_path_slash(char *path)
{
if ((path[wcslen(path)-1] != L'\\') &&
(path[wcslen(path)-1] != L'/')) {
wcscat(path, L"\\");
if ((path[strlen(path)-1] != '\\') &&
(path[strlen(path)-1] != '/')) {
strcat(path, "\\");
}
}
/* Check if the given path is absolute or not. */
int
plat_path_abs(wchar_t *path)
plat_path_abs(char *path)
{
if ((path[1] == L':') || (path[0] == L'\\') || (path[0] == L'/'))
if ((path[1] == ':') || (path[0] == '\\') || (path[0] == '/'))
return(1);
return(0);
@@ -595,33 +702,33 @@ plat_path_abs(wchar_t *path)
/* Return the last element of a pathname. */
wchar_t *
plat_get_basename(const wchar_t *path)
char *
plat_get_basename(const char *path)
{
int c = (int)wcslen(path);
int c = (int)strlen(path);
while (c > 0) {
if (path[c] == L'/' || path[c] == L'\\')
return((wchar_t *)&path[c]);
if (path[c] == '/' || path[c] == '\\')
return((char *)&path[c]);
c--;
}
return((wchar_t *)path);
return((char *)path);
}
/* Return the 'directory' element of a pathname. */
void
plat_get_dirname(wchar_t *dest, const wchar_t *path)
plat_get_dirname(char *dest, const char *path)
{
int c = (int)wcslen(path);
wchar_t *ptr;
int c = (int)strlen(path);
char *ptr;
ptr = (wchar_t *)path;
ptr = (char *)path;
while (c > 0) {
if (path[c] == L'/' || path[c] == L'\\') {
ptr = (wchar_t *)&path[c];
if (path[c] == '/' || path[c] == '\\') {
ptr = (char *)&path[c];
break;
}
c--;
@@ -630,17 +737,17 @@ plat_get_dirname(wchar_t *dest, const wchar_t *path)
/* Copy to destination. */
while (path < ptr)
*dest++ = *path++;
*dest = L'\0';
*dest = '\0';
}
wchar_t *
plat_get_filename(wchar_t *s)
char *
plat_get_filename(char *s)
{
int c = wcslen(s) - 1;
int c = strlen(s) - 1;
while (c > 0) {
if (s[c] == L'/' || s[c] == L'\\')
if (s[c] == '/' || s[c] == '\\')
return(&s[c+1]);
c--;
}
@@ -649,47 +756,61 @@ plat_get_filename(wchar_t *s)
}
wchar_t *
plat_get_extension(wchar_t *s)
char *
plat_get_extension(char *s)
{
int c = wcslen(s) - 1;
int c = strlen(s) - 1;
if (c <= 0)
return(s);
while (c && s[c] != L'.')
while (c && s[c] != '.')
c--;
if (!c)
return(&s[wcslen(s)]);
return(&s[strlen(s)]);
return(&s[c+1]);
}
void
plat_append_filename(wchar_t *dest, wchar_t *s1, wchar_t *s2)
plat_append_filename(char *dest, char *s1, char *s2)
{
wcscat(dest, s1);
strcpy(dest, s1);
plat_path_slash(dest);
wcscat(dest, s2);
strcat(dest, s2);
}
void
plat_put_backslash(wchar_t *s)
plat_put_backslash(char *s)
{
int c = wcslen(s) - 1;
int c = strlen(s) - 1;
if (s[c] != L'/' && s[c] != L'\\')
s[c] = L'/';
if (s[c] != '/' && s[c] != '\\')
s[c] = '/';
}
int
plat_dir_check(wchar_t *path)
plat_dir_check(char *path)
{
DWORD dwAttrib = GetFileAttributes(path);
DWORD dwAttrib;
int len;
wchar_t *temp;
if (acp_utf8)
dwAttrib = GetFileAttributesA(path);
else {
len = mbstoc16s(NULL, path, 0) + 1;
temp = malloc(len * sizeof(wchar_t));
mbstoc16s(temp, path, len);
dwAttrib = GetFileAttributesW(temp);
free(temp);
}
return(((dwAttrib != INVALID_FILE_ATTRIBUTES &&
(dwAttrib & FILE_ATTRIBUTE_DIRECTORY))) ? 1 : 0);
@@ -697,9 +818,24 @@ plat_dir_check(wchar_t *path)
int
plat_dir_create(wchar_t *path)
plat_dir_create(char *path)
{
return((int)SHCreateDirectory(hwndMain, path));
int ret, len;
wchar_t *temp;
if (acp_utf8)
return (int)SHCreateDirectoryExA(NULL, path, NULL);
else {
len = mbstoc16s(NULL, path, 0) + 1;
temp = malloc(len * sizeof(wchar_t));
mbstoc16s(temp, path, len);
ret = (int)SHCreateDirectoryExW(NULL, temp, NULL);
free(temp);
return ret;
}
}