summaryrefslogtreecommitdiff
path: root/src/os
diff options
context:
space:
mode:
authorMichael Lutz <michi@icosahedron.de>2018-04-29 00:34:01 +0200
committerMichael Lutz <michi@icosahedron.de>2018-06-06 21:37:09 +0200
commitf4394debdc092487d603f95716a026a5c8834f8c (patch)
treedb4865150cfd88422f279d6fa5213ab11e27beab /src/os
parent2b662b448cd020886c00ff7ec800d7bd7cb008fa (diff)
downloadopenttd-f4394debdc092487d603f95716a026a5c8834f8c.tar.xz
Add: [Win32] Native natural sort implementation.
Diffstat (limited to 'src/os')
-rw-r--r--src/os/windows/win32.cpp65
-rw-r--r--src/os/windows/win32.h3
2 files changed, 68 insertions, 0 deletions
diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp
index 8a90db4f7..2d853037f 100644
--- a/src/os/windows/win32.cpp
+++ b/src/os/windows/win32.cpp
@@ -28,6 +28,7 @@
#include "../../crashlog.h"
#include <errno.h>
#include <sys/stat.h>
+#include "../../language.h"
/* Due to TCHAR, strncat and strncpy have to remain (for a while). */
#include "../../safeguards.h"
@@ -739,6 +740,70 @@ uint GetCPUCoreCount()
return info.dwNumberOfProcessors;
}
+
+static WCHAR _cur_iso_locale[16] = L"";
+
+void Win32SetCurrentLocaleName(const char *iso_code)
+{
+ /* Convert the iso code into the format that windows expects. */
+ char iso[16];
+ if (strcmp(iso_code, "zh_TW") == 0) {
+ strecpy(iso, "zh-Hant", lastof(iso));
+ } else if (strcmp(iso_code, "zh_CN") == 0) {
+ strecpy(iso, "zh-Hans", lastof(iso));
+ } else {
+ /* Windows expects a '-' between language and country code, but we use a '_'. */
+ strecpy(iso, iso_code, lastof(iso));
+ for (char *c = iso; *c != '\0'; c++) {
+ if (*c == '_') *c = '-';
+ }
+ }
+
+ MultiByteToWideChar(CP_UTF8, 0, iso, -1, _cur_iso_locale, lengthof(_cur_iso_locale));
+}
+
+int OTTDStringCompare(const char *s1, const char *s2)
+{
+ typedef int (WINAPI *PFNCOMPARESTRINGEX)(LPCWSTR, DWORD, LPCWCH, int, LPCWCH, int, LPVOID, LPVOID, LPARAM);
+ static PFNCOMPARESTRINGEX _CompareStringEx = NULL;
+ static bool first_time = true;
+
+#ifndef SORT_DIGITSASNUMBERS
+# define SORT_DIGITSASNUMBERS 0x00000008 // use digits as numbers sort method
+#endif
+#ifndef LINGUISTIC_IGNORECASE
+# define LINGUISTIC_IGNORECASE 0x00000010 // linguistically appropriate 'ignore case'
+#endif
+
+ if (first_time) {
+ _CompareStringEx = (PFNCOMPARESTRINGEX)GetProcAddress(GetModuleHandle(_T("Kernel32")), "CompareStringEx");
+ first_time = false;
+ }
+
+ if (_CompareStringEx != NULL) {
+ /* CompareStringEx takes UTF-16 strings, even in ANSI-builds. */
+ int len_s1 = MultiByteToWideChar(CP_UTF8, 0, s1, -1, NULL, 0);
+ int len_s2 = MultiByteToWideChar(CP_UTF8, 0, s2, -1, NULL, 0);
+
+ if (len_s1 != 0 && len_s2 != 0) {
+ LPWSTR str_s1 = AllocaM(WCHAR, len_s1);
+ LPWSTR str_s2 = AllocaM(WCHAR, len_s2);
+
+ MultiByteToWideChar(CP_UTF8, 0, s1, -1, str_s1, len_s1);
+ MultiByteToWideChar(CP_UTF8, 0, s2, -1, str_s2, len_s2);
+
+ int result = _CompareStringEx(_cur_iso_locale, LINGUISTIC_IGNORECASE | SORT_DIGITSASNUMBERS, str_s1, -1, str_s2, -1, NULL, NULL, 0);
+ if (result != 0) return result;
+ }
+ }
+
+ TCHAR s1_buf[512], s2_buf[512];
+ convert_to_fs(s1, s1_buf, lengthof(s1_buf));
+ convert_to_fs(s2, s2_buf, lengthof(s2_buf));
+
+ return CompareString(MAKELCID(_current_language->winlangid, SORT_DEFAULT), NORM_IGNORECASE, s1_buf, -1, s2_buf, -1);
+}
+
#ifdef _MSC_VER
/* Code from MSDN: https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx */
const DWORD MS_VC_EXCEPTION = 0x406D1388;
diff --git a/src/os/windows/win32.h b/src/os/windows/win32.h
index 16632f6e9..4f813c4a6 100644
--- a/src/os/windows/win32.h
+++ b/src/os/windows/win32.h
@@ -45,4 +45,7 @@ void SetWin32ThreadName(DWORD dwThreadID, const char* threadName);
static inline void SetWin32ThreadName(DWORD dwThreadID, const char* threadName) {}
#endif
+void Win32SetCurrentLocaleName(const char *iso_code);
+int OTTDStringCompare(const char *s1, const char *s2);
+
#endif /* WIN32_H */