summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarkvater <darkvater@openttd.org>2007-03-07 18:58:28 +0000
committerDarkvater <darkvater@openttd.org>2007-03-07 18:58:28 +0000
commit2536a14abd95098fa752835dce90db679a557721 (patch)
treeba99aff4f6b2c185df22ce8dd28562996f0a5441
parent5e1351b377bbb44238880a22b74dcc7793c89691 (diff)
downloadopenttd-2536a14abd95098fa752835dce90db679a557721.tar.xz
(svn r9055) -Codechange: Change windows unicode handling and allow a pure non-unicode build to function. Win9x binaries will be possible with mingw/nightly system.
-rw-r--r--src/fios.cpp5
-rw-r--r--src/fios.h6
-rw-r--r--src/stdafx.h14
-rw-r--r--src/video/win32_v.cpp17
-rw-r--r--src/win32.cpp155
-rw-r--r--src/win32.h1
6 files changed, 135 insertions, 63 deletions
diff --git a/src/fios.cpp b/src/fios.cpp
index 7f2f04548..3ba326dfc 100644
--- a/src/fios.cpp
+++ b/src/fios.cpp
@@ -18,6 +18,7 @@
#include <sys/stat.h>
#ifdef WIN32
+# include <tchar.h>
# include <io.h>
#else
# include <unistd.h>
@@ -171,8 +172,8 @@ void FiosMakeSavegameName(char *buf, const char *name, size_t size)
snprintf(buf, size, "%s" PATHSEP "%s%s", _fios_path, name, extension);
}
-#if defined(WIN32) || defined(WIN64)
-# define unlink _wunlink
+#if defined(WIN32)
+# define unlink _tunlink
#endif
bool FiosDelete(const char *name)
diff --git a/src/fios.h b/src/fios.h
index bb119cc88..b1d923090 100644
--- a/src/fios.h
+++ b/src/fios.h
@@ -59,7 +59,7 @@ int CDECL compare_FiosItems(const void *a, const void *b);
struct DIR;
struct dirent { // XXX - only d_name implemented
- wchar_t *d_name; // name of found file
+ TCHAR *d_name; // name of found file
/* little hack which will point to parent DIR struct which will
* save us a call to GetFileAttributes if we want information
* about the file (for example in function fio_bla) */
@@ -72,14 +72,14 @@ struct DIR {
* note: having only one global instance is not possible because
* multiple independent opendir/readdir sequences must be supported. */
dirent ent;
- WIN32_FIND_DATAW fd;
+ WIN32_FIND_DATA fd;
/* since opendir calls FindFirstFile, we need a means of telling the
* first call to readdir that we already have a file.
* that's the case iff this is true */
bool at_first_entry;
};
-DIR *opendir(const wchar_t *path);
+DIR *opendir(const TCHAR *path);
struct dirent *readdir(DIR *d);
int closedir(DIR *d);
#else
diff --git a/src/stdafx.h b/src/stdafx.h
index 022ca61e5..3c9419f84 100644
--- a/src/stdafx.h
+++ b/src/stdafx.h
@@ -198,14 +198,16 @@
* call to the same function and is not thread- or reentrancy-safe */
#if !defined(STRGEN)
# if defined(WIN32) || defined(WIN64)
-# if defined(WINCE)
+# include <tchar.h>
/* XXX - WinCE without MSVCRT doesn't support wfopen, so it seems */
-# else
-# define fopen(file, mode) _wfopen(OTTD2FS(file), L ## mode)
-# endif
- const char *FS2OTTD(const wchar_t *name);
- const wchar_t *OTTD2FS(const char *name);
+# if !defined(WINCE)
+# define fopen(file, mode) _tfopen(OTTD2FS(file), _T(mode))
+# endif /* WINCE */
+
+ const char *FS2OTTD(const TCHAR *name);
+ const TCHAR *OTTD2FS(const char *name);
# else
+
# define fopen(file, mode) fopen(OTTD2FS(file), mode)
const char *FS2OTTD(const char *name);
const char *OTTD2FS(const char *name);
diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp
index 4e9f43236..aecfbd226 100644
--- a/src/video/win32_v.cpp
+++ b/src/video/win32_v.cpp
@@ -36,6 +36,9 @@ bool _window_maximize;
uint _display_hz;
uint _fullscreen_bpp;
static uint16 _bck_resolution[2];
+#if !defined(UNICODE)
+uint _codepage;
+#endif
static void MakePalette()
{
@@ -211,6 +214,9 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
switch (msg) {
case WM_CREATE:
SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, (TIMERPROC)TrackMouseTimerProc);
+#if !defined(UNICODE)
+ _codepage = GetACP(); // get system codepage as some kind of a default
+#endif /* UNICODE */
break;
case WM_PAINT: {
@@ -347,6 +353,17 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
return 0;
}
+#if !defined(UNICODE)
+ case WM_INPUTLANGCHANGE: {
+ TCHAR locale[6];
+ LCID lcid = GB(lParam, 0, 16);
+
+ int len = GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, locale, lengthof(locale));
+ if (len != 0) _codepage = _ttoi(locale);
+ return 1;
+ }
+#endif /* UNICODE */
+
case WM_KEYDOWN: {
// this is the rewritten ascii input function
// it disables windows deadkey handling --> more linux like :D
diff --git a/src/win32.cpp b/src/win32.cpp
index 63f1b26ae..33e5fd964 100644
--- a/src/win32.cpp
+++ b/src/win32.cpp
@@ -658,23 +658,23 @@ static inline void dir_free(DIR *d)
}
}
-DIR *opendir(const wchar_t *path)
+DIR *opendir(const TCHAR *path)
{
DIR *d;
UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS); // disable 'no-disk' message box
- DWORD fa = GetFileAttributesW(path);
+ DWORD fa = GetFileAttributes(path);
if ((fa != INVALID_FILE_ATTRIBUTES) && (fa & FILE_ATTRIBUTE_DIRECTORY)) {
d = dir_calloc();
if (d != NULL) {
- wchar_t search_path[MAX_PATH];
- bool slash = path[wcslen(path) - 1] == L'\\';
+ TCHAR search_path[MAX_PATH];
+ bool slash = path[_tcslen(path) - 1] == '\\';
/* build search path for FindFirstFile, try not to append additional slashes
* as it throws Win9x off its groove for root directories */
- _snwprintf(search_path, lengthof(search_path), L"%s%s*", path, slash ? L"" : L"\\");
+ _sntprintf(search_path, lengthof(search_path), _T("%s%s*"), path, slash ? _T("") : _T("\\"));
*lastof(search_path) = '\0';
- d->hFind = FindFirstFileW(search_path, &d->fd);
+ d->hFind = FindFirstFile(search_path, &d->fd);
if (d->hFind != INVALID_HANDLE_VALUE ||
GetLastError() == ERROR_NO_MORE_FILES) { // the directory is empty
@@ -705,7 +705,7 @@ struct dirent *readdir(DIR *d)
/* the directory was empty when opened */
if (d->hFind == INVALID_HANDLE_VALUE) return NULL;
d->at_first_entry = false;
- } else if (!FindNextFileW(d->hFind, &d->fd)) { // determine cause and bail
+ } else if (!FindNextFile(d->hFind, &d->fd)) { // determine cause and bail
if (GetLastError() == ERROR_NO_MORE_FILES) SetLastError(prev_err);
return NULL;
}
@@ -748,7 +748,7 @@ bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb
{
// hectonanoseconds between Windows and POSIX epoch
static const int64 posix_epoch_hns = 0x019DB1DED53E8000LL;
- const WIN32_FIND_DATAW *fd = &ent->dir->fd;
+ const WIN32_FIND_DATA *fd = &ent->dir->fd;
sb->st_size = ((uint64) fd->nFileSizeHigh << 32) + fd->nFileSizeLow;
/* UTC FILETIME to seconds-since-1970 UTC
@@ -878,13 +878,7 @@ void ShowInfo(const char *str)
int _set_error_mode(int);
#endif
-#if defined(WINCE) && !defined(_tWinMain)
-/* GCC crosscompiler for WINCE doesn't support wide version */
-# define _tWinMain WinMain
-#endif /* WINCE */
-
-int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
- LPTSTR lpCmdLine, int nCmdShow)
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
int argc;
char *argv[64]; // max 64 command line arguments
@@ -947,11 +941,15 @@ void GetCurrentDirectoryW(int length, wchar_t *path)
void DeterminePaths()
{
char *s, *cfg;
- wchar_t path[MAX_PATH];
_paths.personal_dir = _paths.game_data_dir = cfg = (char*)malloc(MAX_PATH);
- GetCurrentDirectoryW(MAX_PATH - 1, path);
+#if defined(UNICODE)
+ TCHAR path[MAX_PATH];
+ GetCurrentDirectory(MAX_PATH - 1, path);
convert_from_fs(path, cfg, MAX_PATH);
+#else
+ GetCurrentDirectory(MAX_PATH - 1, cfg);
+#endif
cfg[0] = toupper(cfg[0]);
s = strchr(cfg, '\0');
@@ -972,10 +970,10 @@ void DeterminePaths()
_log_file = str_fmt("%sopenttd.log", _paths.personal_dir);
// make (auto)save and scenario folder
- CreateDirectoryW(OTTD2FS(_paths.save_dir), NULL);
- CreateDirectoryW(OTTD2FS(_paths.autosave_dir), NULL);
- CreateDirectoryW(OTTD2FS(_paths.scenario_dir), NULL);
- CreateDirectoryW(OTTD2FS(_paths.heightmap_dir), NULL);
+ CreateDirectory(OTTD2FS(_paths.save_dir), NULL);
+ CreateDirectory(OTTD2FS(_paths.autosave_dir), NULL);
+ CreateDirectory(OTTD2FS(_paths.scenario_dir), NULL);
+ CreateDirectory(OTTD2FS(_paths.heightmap_dir), NULL);
}
/**
@@ -1069,39 +1067,85 @@ int64 GetTS()
return (__int64)(value * freq);
}
-/** Convert from OpenTTD's encoding to that of the local environment in
- * UNICODE. OpenTTD encoding is UTF8, local is wide-char
- * @param name pointer to a valid string that will be converted
- * @param utf16_buf pointer to a valid wide-char buffer that will receive the
- * converted string
- * @param buflen length in wide characters of the receiving buffer
- * @return pointer to utf16_buf. If conversion fails the string is of zero-length */
-wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen)
+
+/**
+ * Convert to OpenTTD's encoding from that of the local environment.
+ * When the project is built in UNICODE, the system codepage is irrelevant and
+ * the input string is wide. In ANSI mode, the string is in the
+ * local codepage which we'll convert to wide-char, and then to UTF-8.
+ * OpenTTD internal encoding is UTF8.
+ * The returned value's contents can only be guaranteed until the next call to
+ * this function. So if the value is needed for anything else, use convert_from_fs
+ * @param name pointer to a valid string that will be converted (local, or wide)
+ * @return pointer to the converted string; if failed string is of zero-length
+ * @see the current code-page comes from video\win32_v.cpp, event-notification
+ * WM_INPUTLANGCHANGE */
+const char *FS2OTTD(const TCHAR *name)
{
- int len = MultiByteToWideChar(CP_UTF8, 0, name, -1, utf16_buf, buflen);
- if (len == 0) {
- DEBUG(misc, 0, "[utf8] error converting '%s'. Errno %d", name, GetLastError());
- utf16_buf[0] = '\0';
+ static char utf8_buf[512];
+#if defined(UNICODE)
+ return convert_from_fs(name, utf8_buf, lengthof(utf8_buf));
+#else
+ char *s = utf8_buf;
+
+ for (; *name != '\0'; name++) {
+ wchar_t w;
+ int len = MultiByteToWideChar(_codepage, 0, name, 1, &w, 1);
+ if (len != 1) {
+ DEBUG(misc, 0, "[utf8] M2W error converting '%c'. Errno %d", *name, GetLastError());
+ continue;
+ }
+
+ if (s + Utf8CharLen(w) >= lastof(utf8_buf)) break;
+ s += Utf8Encode(s, w);
}
- return utf16_buf;
+ *s = '\0';
+ return utf8_buf;
+#endif /* UNICODE */
}
-/** Convert from OpenTTD's encoding to that of the local environment in
- * UNICODE. OpenTTD encoding is UTF8, local is wide-char.
+/**
+ * Convert from OpenTTD's encoding to that of the local environment.
+ * When the project is built in UNICODE the system codepage is irrelevant and
+ * the converted string is wide. In ANSI mode, the UTF8 string is converted
+ * to multi-byte.
+ * OpenTTD internal encoding is UTF8.
* The returned value's contents can only be guaranteed until the next call to
* this function. So if the value is needed for anything else, use convert_from_fs
- * @param name pointer to a valid string that will be converted
- * @return pointer to the converted string; if failed string is of zero-length */
-const wchar_t *OTTD2FS(const char *name)
+ * @param name pointer to a valid string that will be converted (UTF8)
+ * @return pointer to the converted string; if failed string is of zero-length
+ * @see the current code-page comes from video\win32_v.cpp, event-notification
+ * WM_INPUTLANGCHANGE */
+const TCHAR *OTTD2FS(const char *name)
{
- static wchar_t utf16_buf[512];
- return convert_to_fs(name, utf16_buf, lengthof(utf16_buf));
+ static TCHAR system_buf[512];
+#if defined(UNICODE)
+ return convert_to_fs(name, system_buf, lengthof(system_buf));
+#else
+ char *s = system_buf;
+
+ for (WChar c; (c = Utf8Consume(&name)) != '\0';) {
+ if (s >= lastof(system_buf)) break;
+
+ char mb;
+ int len = WideCharToMultiByte(_codepage, 0, (wchar_t*)&c, 1, &mb, 1, NULL, NULL);
+ if (len != 1) {
+ DEBUG(misc, 0, "[utf8] W2M error converting '0x%X'. Errno %d", c, GetLastError());
+ continue;
+ }
+
+ *s++ = mb;
+ }
+
+ *s = '\0';
+ return system_buf;
+#endif /* UNICODE */
}
-/** Convert to OpenTTD's encoding from that of the local environment in
- * UNICODE. OpenTTD encoding is UTF8, local is wide-char
+/** Convert to OpenTTD's encoding from that of the environment in
+ * UNICODE. OpenTTD encoding is UTF8, local is wide
* @param name pointer to a valid string that will be converted
* @param utf8_buf pointer to a valid buffer that will receive the converted string
* @param buflen length in characters of the receiving buffer
@@ -1110,23 +1154,30 @@ char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen)
{
int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, utf8_buf, buflen, NULL, NULL);
if (len == 0) {
- DEBUG(misc, 0, "[utf8] error converting wide-string. Errno %d", GetLastError());
+ DEBUG(misc, 0, "[utf8] W2M error converting wide-string. Errno %d", GetLastError());
utf8_buf[0] = '\0';
}
return utf8_buf;
}
-/** Convert to OpenTTD's encoding from that of the local environment in
- * UNICODE. OpenTTD encoding is UTF8, local is wide-char.
- * The returned value's contents can only be guaranteed until the next call to
- * this function. So if the value is needed for anything else, use convert_from_fs
+
+/** Convert from OpenTTD's encoding to that of the environment in
+ * UNICODE. OpenTTD encoding is UTF8, local is wide
* @param name pointer to a valid string that will be converted
- * @return pointer to the converted string; if failed string is of zero-length */
-const char *FS2OTTD(const wchar_t *name)
+ * @param utf16_buf pointer to a valid wide-char buffer that will receive the
+ * converted string
+ * @param buflen length in wide characters of the receiving buffer
+ * @return pointer to utf16_buf. If conversion fails the string is of zero-length */
+wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen)
{
- static char utf8_buf[512];
- return convert_from_fs(name, utf8_buf, lengthof(utf8_buf));
+ int len = MultiByteToWideChar(CP_UTF8, 0, name, -1, utf16_buf, buflen);
+ if (len == 0) {
+ DEBUG(misc, 0, "[utf8] M2W error converting '%s'. Errno %d", name, GetLastError());
+ utf16_buf[0] = '\0';
+ }
+
+ return utf16_buf;
}
/** Our very own SHGetFolderPath function for support of windows operating
diff --git a/src/win32.h b/src/win32.h
index 4938c3a2a..f91eaf3c5 100644
--- a/src/win32.h
+++ b/src/win32.h
@@ -26,6 +26,7 @@ wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen);
# define WIDE_TO_MB(str) FS2OTTD(str)
# define WIDE_TO_MB_BUFFER(str, buffer, buflen) convert_from_fs(str, buffer, buflen)
#else
+extern uint _codepage; // local code-page in the system @see win32_v.cpp:WM_INPUTLANGCHANGE
# define MB_TO_WIDE(str) (str)
# define MB_TO_WIDE_BUFFER(str, buffer, buflen) (str)
# define WIDE_TO_MB(str) (str)