diff --git a/config.lib b/config.lib
index 536d58b940..2ccd3c6ce3 100644
--- a/config.lib
+++ b/config.lib
@@ -88,6 +88,7 @@ set_default() {
with_icu_layout="1"
with_icu_sort="1"
static_icu="0"
+ with_uniscribe="1"
with_threads="1"
with_distcc="1"
with_ccache="1"
@@ -167,6 +168,7 @@ set_default() {
with_icu_layout
with_icu_sort
static_icu
+ with_uniscribe
with_threads
with_distcc
with_ccache
@@ -407,6 +409,10 @@ detect_params() {
--static-libicu) static_icu="1";;
--static-libicu=*) static_icu="$optarg";;
+ --with-uniscribe) with_uniscribe="2";;
+ --without-uniscribe) with_uniscribe="0";;
+ --with-uniscribe=*) with_uniscribe="$optarg";;
+
--disable-builtin-depend) enable_builtin_depend="0";;
--enable-builtin-depend) enable_builtin_depend="2";;
--enable-builtin-depend=*) enable_builtin_depend="$optarg";;
@@ -879,6 +885,28 @@ check_params() {
fi
fi
+ if [ "$with_uniscribe" != "0" ]; then
+ if [ "$os" != "MINGW" ]; then
+ if [ "$with_uniscribe" != "1" ]; then
+ log 1 "configure: error: Uniscribe is only supported on native Win32 targets"
+ exit 1
+ fi
+ with_uniscribe="0"
+
+ log 1 "checking Uniscribe text layout... not Windows, skipping"
+ else
+ log 1 "checking Uniscribe text layout... found"
+
+ # Don't use ICU unless forced.
+ if [ "$with_icu_layout" = "1" ]; then
+ with_icu_layout="0"
+ fi
+ if [ "$with_icu_sort" = "1" ]; then
+ with_icu_sort="0"
+ fi
+ fi
+ fi
+
detect_xdg_basedir
detect_png
detect_freetype
@@ -2083,6 +2111,10 @@ EOL
fi
fi
+ if [ "$with_uniscribe" != "0" ]; then
+ CFLAGS="$CFLAGS -DWITH_UNISCRIBE"
+ LIBS="$LIBS -lusp10"
+ fi
if [ "$with_direct_music" != "0" ]; then
CFLAGS="$CFLAGS -DWIN32_ENABLE_DIRECTMUSIC_SUPPORT"
diff --git a/projects/openttd_vs100.vcxproj b/projects/openttd_vs100.vcxproj
index fed445249a..5a291d83b0 100644
--- a/projects/openttd_vs100.vcxproj
+++ b/projects/openttd_vs100.vcxproj
@@ -102,7 +102,7 @@
Size
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions)
true
Sync
MultiThreaded
@@ -131,7 +131,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
%(IgnoreSpecificDefaultLibraries)
true
@@ -162,7 +162,7 @@
/MP %(AdditionalOptions)
Disabled
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions)
EnableFastChecks
MultiThreadedDebug
@@ -182,7 +182,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)
true
@@ -216,7 +216,7 @@
Size
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions)
true
Sync
MultiThreaded
@@ -245,7 +245,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
%(IgnoreSpecificDefaultLibraries)
true
@@ -274,7 +274,7 @@
/MP %(AdditionalOptions)
Disabled
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions)
EnableFastChecks
MultiThreadedDebug
@@ -298,7 +298,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)
true
@@ -660,6 +660,7 @@
+
@@ -1357,6 +1358,7 @@
+
diff --git a/projects/openttd_vs100.vcxproj.filters b/projects/openttd_vs100.vcxproj.filters
index 3b82a1b2ac..e7b33ed305 100644
--- a/projects/openttd_vs100.vcxproj.filters
+++ b/projects/openttd_vs100.vcxproj.filters
@@ -1140,6 +1140,9 @@
Header Files
+
+ Header Files
+
Header Files
@@ -3231,6 +3234,9 @@
Windows files
+
+ Windows files
+
Windows files
diff --git a/projects/openttd_vs100.vcxproj.in b/projects/openttd_vs100.vcxproj.in
index aab1340756..b2eb33d316 100644
--- a/projects/openttd_vs100.vcxproj.in
+++ b/projects/openttd_vs100.vcxproj.in
@@ -102,7 +102,7 @@
Size
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions)
true
Sync
MultiThreaded
@@ -131,7 +131,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
%(IgnoreSpecificDefaultLibraries)
true
@@ -162,7 +162,7 @@
/MP %(AdditionalOptions)
Disabled
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions)
EnableFastChecks
MultiThreadedDebug
@@ -182,7 +182,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)
true
@@ -216,7 +216,7 @@
Size
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions)
true
Sync
MultiThreaded
@@ -245,7 +245,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
%(IgnoreSpecificDefaultLibraries)
true
@@ -274,7 +274,7 @@
/MP %(AdditionalOptions)
Disabled
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions)
EnableFastChecks
MultiThreadedDebug
@@ -298,7 +298,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)
true
diff --git a/projects/openttd_vs140.vcxproj b/projects/openttd_vs140.vcxproj
index 863a5a1f82..4a13d06b94 100644
--- a/projects/openttd_vs140.vcxproj
+++ b/projects/openttd_vs140.vcxproj
@@ -105,7 +105,7 @@
Size
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions)
true
Sync
MultiThreaded
@@ -136,7 +136,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
%(IgnoreSpecificDefaultLibraries)
true
@@ -170,7 +170,7 @@
Disabled
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions)
EnableFastChecks
MultiThreadedDebug
@@ -192,7 +192,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)
true
@@ -228,7 +228,7 @@
Size
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions)
true
Sync
MultiThreaded
@@ -259,7 +259,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
%(IgnoreSpecificDefaultLibraries)
true
@@ -291,7 +291,7 @@
Disabled
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions)
EnableFastChecks
MultiThreadedDebug
@@ -317,7 +317,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)
true
@@ -681,6 +681,7 @@
+
@@ -1378,6 +1379,7 @@
+
diff --git a/projects/openttd_vs140.vcxproj.filters b/projects/openttd_vs140.vcxproj.filters
index 3b82a1b2ac..e7b33ed305 100644
--- a/projects/openttd_vs140.vcxproj.filters
+++ b/projects/openttd_vs140.vcxproj.filters
@@ -1140,6 +1140,9 @@
Header Files
+
+ Header Files
+
Header Files
@@ -3231,6 +3234,9 @@
Windows files
+
+ Windows files
+
Windows files
diff --git a/projects/openttd_vs140.vcxproj.in b/projects/openttd_vs140.vcxproj.in
index 1dd1e35219..d6ba126b5f 100644
--- a/projects/openttd_vs140.vcxproj.in
+++ b/projects/openttd_vs140.vcxproj.in
@@ -105,7 +105,7 @@
Size
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions)
true
Sync
MultiThreaded
@@ -136,7 +136,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
%(IgnoreSpecificDefaultLibraries)
true
@@ -170,7 +170,7 @@
Disabled
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions)
EnableFastChecks
MultiThreadedDebug
@@ -192,7 +192,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)
true
@@ -228,7 +228,7 @@
Size
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions)
true
Sync
MultiThreaded
@@ -259,7 +259,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
%(IgnoreSpecificDefaultLibraries)
true
@@ -291,7 +291,7 @@
Disabled
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions)
EnableFastChecks
MultiThreadedDebug
@@ -317,7 +317,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)
true
diff --git a/projects/openttd_vs141.vcxproj b/projects/openttd_vs141.vcxproj
index c81f175140..aafaa2429b 100644
--- a/projects/openttd_vs141.vcxproj
+++ b/projects/openttd_vs141.vcxproj
@@ -105,7 +105,7 @@
Size
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions)
true
Sync
MultiThreaded
@@ -136,7 +136,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
%(IgnoreSpecificDefaultLibraries)
true
@@ -170,7 +170,7 @@
Disabled
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions)
EnableFastChecks
MultiThreadedDebug
@@ -192,7 +192,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)
true
@@ -228,7 +228,7 @@
Size
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions)
true
Sync
MultiThreaded
@@ -259,7 +259,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
%(IgnoreSpecificDefaultLibraries)
true
@@ -291,7 +291,7 @@
Disabled
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions)
EnableFastChecks
MultiThreadedDebug
@@ -317,7 +317,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)
true
@@ -681,6 +681,7 @@
+
@@ -1378,6 +1379,7 @@
+
diff --git a/projects/openttd_vs141.vcxproj.filters b/projects/openttd_vs141.vcxproj.filters
index 3b82a1b2ac..e7b33ed305 100644
--- a/projects/openttd_vs141.vcxproj.filters
+++ b/projects/openttd_vs141.vcxproj.filters
@@ -1140,6 +1140,9 @@
Header Files
+
+ Header Files
+
Header Files
@@ -3231,6 +3234,9 @@
Windows files
+
+ Windows files
+
Windows files
diff --git a/projects/openttd_vs141.vcxproj.in b/projects/openttd_vs141.vcxproj.in
index c470ffcdde..f231c6264d 100644
--- a/projects/openttd_vs141.vcxproj.in
+++ b/projects/openttd_vs141.vcxproj.in
@@ -105,7 +105,7 @@
Size
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";WITH_ASSERT;%(PreprocessorDefinitions)
true
Sync
MultiThreaded
@@ -136,7 +136,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
%(IgnoreSpecificDefaultLibraries)
true
@@ -170,7 +170,7 @@
Disabled
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";%(PreprocessorDefinitions)
EnableFastChecks
MultiThreadedDebug
@@ -192,7 +192,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)
true
@@ -228,7 +228,7 @@
Size
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;WITH_ASSERT;%(PreprocessorDefinitions)
true
Sync
MultiThreaded
@@ -259,7 +259,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
%(IgnoreSpecificDefaultLibraries)
true
@@ -291,7 +291,7 @@
Disabled
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_XAUDIO2;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR="OpenTTD";_SQ64;%(PreprocessorDefinitions)
EnableFastChecks
MultiThreadedDebug
@@ -317,7 +317,7 @@
0x0809
- winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;icuuc.lib;icuin.lib;icudt.lib;icule.lib;iculx.lib;%(AdditionalDependencies)
+ winmm.lib;ws2_32.lib;imm32.lib;libpng.lib;zlibstat.lib;lzo2.lib;liblzma.lib;libfreetype2.lib;%(AdditionalDependencies)
true
LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)
true
diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj
index 6c8b19a9fc..401c4819fe 100644
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -52,7 +52,7 @@
FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR=\"OpenTTD\";WITH_ASSERT"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR=\"OpenTTD\";WITH_ASSERT"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
@@ -87,7 +87,7 @@
/>
+
+
@@ -4734,6 +4738,10 @@
RelativePath=".\..\src\os\windows\ottdres.rc"
>
+
+
diff --git a/projects/openttd_vs80.vcproj.in b/projects/openttd_vs80.vcproj.in
index 8b187ad857..3363d0d019 100644
--- a/projects/openttd_vs80.vcproj.in
+++ b/projects/openttd_vs80.vcproj.in
@@ -52,7 +52,7 @@
FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR=\"OpenTTD\";WITH_ASSERT"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR=\"OpenTTD\";WITH_ASSERT"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
@@ -87,7 +87,7 @@
/>
+
+
@@ -4731,6 +4735,10 @@
RelativePath=".\..\src\os\windows\ottdres.rc"
>
+
+
diff --git a/projects/openttd_vs90.vcproj.in b/projects/openttd_vs90.vcproj.in
index 39be14875f..b2d3fdeb9c 100644
--- a/projects/openttd_vs90.vcproj.in
+++ b/projects/openttd_vs90.vcproj.in
@@ -53,7 +53,7 @@
FavorSizeOrSpeed="2"
OmitFramePointers="true"
AdditionalIncludeDirectories="..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include"
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_ICU_SORT;WITH_ICU_LAYOUT;U_STATIC_IMPLEMENTATION;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR=\"OpenTTD\";WITH_ASSERT"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_ENABLE_DIRECTMUSIC_SUPPORT;WITH_SSE;WITH_ZLIB;WITH_LZO;WITH_LZMA;LZMA_API_STATIC;WITH_PNG;WITH_FREETYPE;WITH_UNISCRIBE;ENABLE_NETWORK;WITH_PERSONAL_DIR;PERSONAL_DIR=\"OpenTTD\";WITH_ASSERT"
StringPooling="true"
ExceptionHandling="1"
RuntimeLibrary="0"
@@ -88,7 +88,7 @@
/>
family_name; }
+ virtual bool IsBuiltInFont() { return false; }
};
FT_Library _library = NULL;
diff --git a/src/fontcache.h b/src/fontcache.h
index c5a165e929..dbef8e81a7 100644
--- a/src/fontcache.h
+++ b/src/fontcache.h
@@ -147,6 +147,11 @@ public:
{
return this->parent != NULL;
}
+
+ /**
+ * Is this a built-in sprite font?
+ */
+ virtual bool IsBuiltInFont() = 0;
};
/** Get the SpriteID mapped to the given font size and key */
diff --git a/src/gfx_layout.cpp b/src/gfx_layout.cpp
index 3290aea653..1d9fc7c313 100644
--- a/src/gfx_layout.cpp
+++ b/src/gfx_layout.cpp
@@ -21,6 +21,10 @@
#include
#endif /* WITH_ICU_LAYOUT */
+#ifdef WITH_UNISCRIBE
+#include "os/windows/string_uniscribe.h"
+#endif /* WITH_UNISCRIBE */
+
#include "safeguards.h"
@@ -113,26 +117,12 @@ le_bool Font::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &poin
return FALSE;
}
-static size_t AppendToBuffer(UChar *buff, const UChar *buffer_last, WChar c)
-{
- /* Transform from UTF-32 to internal ICU format of UTF-16. */
- int32 length = 0;
- UErrorCode err = U_ZERO_ERROR;
- u_strFromUTF32(buff, buffer_last - buff, &length, (UChar32*)&c, 1, &err);
- return length;
-}
-
/**
* Wrapper for doing layouts with ICU.
*/
class ICUParagraphLayout : public AutoDeleteSmallVector, public ParagraphLayouter {
ParagraphLayout *p; ///< The actual ICU paragraph layout.
public:
- /** Helper for GetLayouter, to get the right type. */
- typedef UChar CharType;
- /** Helper for GetLayouter, to get whether the layouter supports RTL. */
- static const bool SUPPORTS_RTL = true;
-
/** Visual run contains data about the bit of text with the same font. */
class ICUVisualRun : public ParagraphLayouter::VisualRun {
const ParagraphLayout::VisualRun *vr; ///< The actual ICU vr.
@@ -184,35 +174,54 @@ public:
}
};
-static ParagraphLayouter *GetParagraphLayout(UChar *buff, UChar *buff_end, FontMap &fontMapping)
-{
- int32 length = buff_end - buff;
+/**
+ * Helper class to construct a new #ICUParagraphLayout.
+ */
+class ICUParagraphLayoutFactory {
+public:
+ /** Helper for GetLayouter, to get the right type. */
+ typedef UChar CharType;
+ /** Helper for GetLayouter, to get whether the layouter supports RTL. */
+ static const bool SUPPORTS_RTL = true;
- if (length == 0) {
- /* ICU's ParagraphLayout cannot handle empty strings, so fake one. */
- buff[0] = ' ';
- length = 1;
- fontMapping.End()[-1].first++;
+ static ParagraphLayouter *GetParagraphLayout(UChar *buff, UChar *buff_end, FontMap &fontMapping)
+ {
+ int32 length = buff_end - buff;
+
+ if (length == 0) {
+ /* ICU's ParagraphLayout cannot handle empty strings, so fake one. */
+ buff[0] = ' ';
+ length = 1;
+ fontMapping.End()[-1].first++;
+ }
+
+ /* Fill ICU's FontRuns with the right data. */
+ FontRuns runs(fontMapping.Length());
+ for (FontMap::iterator iter = fontMapping.Begin(); iter != fontMapping.End(); iter++) {
+ runs.add(iter->second, iter->first);
+ }
+
+ LEErrorCode status = LE_NO_ERROR;
+ /* ParagraphLayout does not copy "buff", so it must stay valid.
+ * "runs" is copied according to the ICU source, but the documentation does not specify anything, so this might break somewhen. */
+ ParagraphLayout *p = new ParagraphLayout(buff, length, &runs, NULL, NULL, NULL, _current_text_dir == TD_RTL ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR, false, status);
+ if (status != LE_NO_ERROR) {
+ delete p;
+ return NULL;
+ }
+
+ return new ICUParagraphLayout(p);
}
- /* Fill ICU's FontRuns with the right data. */
- FontRuns runs(fontMapping.Length());
- for (FontMap::iterator iter = fontMapping.Begin(); iter != fontMapping.End(); iter++) {
- runs.add(iter->second, iter->first);
+ static size_t AppendToBuffer(UChar *buff, const UChar *buffer_last, WChar c)
+ {
+ /* Transform from UTF-32 to internal ICU format of UTF-16. */
+ int32 length = 0;
+ UErrorCode err = U_ZERO_ERROR;
+ u_strFromUTF32(buff, buffer_last - buff, &length, (UChar32*)&c, 1, &err);
+ return length;
}
-
- LEErrorCode status = LE_NO_ERROR;
- /* ParagraphLayout does not copy "buff", so it must stay valid.
- * "runs" is copied according to the ICU source, but the documentation does not specify anything, so this might break somewhen. */
- ParagraphLayout *p = new ParagraphLayout(buff, length, &runs, NULL, NULL, NULL, _current_text_dir == TD_RTL ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR, false, status);
- if (status != LE_NO_ERROR) {
- delete p;
- return NULL;
- }
-
- return new ICUParagraphLayout(p);
-}
-
+};
#endif /* WITH_ICU_LAYOUT */
/*** Paragraph layout ***/
@@ -236,11 +245,6 @@ static ParagraphLayouter *GetParagraphLayout(UChar *buff, UChar *buff_end, FontM
*/
class FallbackParagraphLayout : public ParagraphLayouter {
public:
- /** Helper for GetLayouter, to get the right type. */
- typedef WChar CharType;
- /** Helper for GetLayouter, to get whether the layouter supports RTL. */
- static const bool SUPPORTS_RTL = false;
-
/** Visual run contains data about the bit of text with the same font. */
class FallbackVisualRun : public ParagraphLayouter::VisualRun {
Font *font; ///< The font used to layout these.
@@ -280,6 +284,42 @@ public:
const ParagraphLayouter::Line *NextLine(int max_width);
};
+/**
+ * Helper class to construct a new #FallbackParagraphLayout.
+ */
+class FallbackParagraphLayoutFactory {
+public:
+ /** Helper for GetLayouter, to get the right type. */
+ typedef WChar CharType;
+ /** Helper for GetLayouter, to get whether the layouter supports RTL. */
+ static const bool SUPPORTS_RTL = false;
+
+ /**
+ * Get the actual ParagraphLayout for the given buffer.
+ * @param buff The begin of the buffer.
+ * @param buff_end The location after the last element in the buffer.
+ * @param fontMapping THe mapping of the fonts.
+ * @return The ParagraphLayout instance.
+ */
+ static ParagraphLayouter *GetParagraphLayout(WChar *buff, WChar *buff_end, FontMap &fontMapping)
+ {
+ return new FallbackParagraphLayout(buff, buff_end - buff, fontMapping);
+ }
+
+ /**
+ * Append a wide character to the internal buffer.
+ * @param buff The buffer to append to.
+ * @param buffer_last The end of the buffer.
+ * @param c The character to add.
+ * @return The number of buffer spaces that were used.
+ */
+ static size_t AppendToBuffer(WChar *buff, const WChar *buffer_last, WChar c)
+ {
+ *buff = c;
+ return 1;
+ }
+};
+
/**
* Create the visual run.
* @param font The font to use for this run.
@@ -536,31 +576,6 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width)
return l;
}
-/**
- * Appand a wide character to the internal buffer.
- * @param buff The buffer to append to.
- * @param buffer_last The end of the buffer.
- * @param c The character to add.
- * @return The number of buffer spaces that were used.
- */
-static size_t AppendToBuffer(WChar *buff, const WChar *buffer_last, WChar c)
-{
- *buff = c;
- return 1;
-}
-
-/**
- * Get the actual ParagraphLayout for the given buffer.
- * @param buff The begin of the buffer.
- * @param buff_end The location after the last element in the buffer.
- * @param fontMapping THe mapping of the fonts.
- * @return The ParagraphLayout instance.
- */
-static FallbackParagraphLayout *GetParagraphLayout(WChar *buff, WChar *buff_end, FontMap &fontMapping)
-{
- return new FallbackParagraphLayout(buff, buff_end - buff, fontMapping);
-}
-
/**
* Helper for getting a ParagraphLayouter of the given type.
*
@@ -605,7 +620,7 @@ static inline void GetLayouter(Layouter::LineCacheItem &line, const char *&str,
* will not be handled in the fallback non ICU case because they are
* mostly needed for RTL languages which need more ICU support. */
if (!T::SUPPORTS_RTL && IsTextDirectionChar(c)) continue;
- buff += AppendToBuffer(buff, buffer_last, c);
+ buff += T::AppendToBuffer(buff, buffer_last, c);
continue;
}
@@ -621,7 +636,7 @@ static inline void GetLayouter(Layouter::LineCacheItem &line, const char *&str,
if (!fontMapping.Contains(buff - buff_begin)) {
fontMapping.Insert(buff - buff_begin, f);
}
- line.layout = GetParagraphLayout(buff_begin, buff, fontMapping);
+ line.layout = T::GetParagraphLayout(buff_begin, buff, fontMapping);
line.state_after = state;
}
@@ -654,11 +669,11 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi
line.layout->Reflow();
} else {
/* Line is new, layout it */
-#ifdef WITH_ICU_LAYOUT
FontState old_state = state;
const char *old_str = str;
- GetLayouter(line, str, state);
+#ifdef WITH_ICU_LAYOUT
+ GetLayouter(line, str, state);
if (line.layout == NULL) {
static bool warned = false;
if (!warned) {
@@ -668,11 +683,22 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi
state = old_state;
str = old_str;
- GetLayouter(line, str, state);
}
-#else
- GetLayouter(line, str, state);
#endif
+
+#ifdef WITH_UNISCRIBE
+ if (line.layout == NULL) {
+ GetLayouter(line, str, state);
+ if (line.layout == NULL) {
+ state = old_state;
+ str = old_str;
+ }
+ }
+#endif
+
+ if (line.layout == NULL) {
+ GetLayouter(line, str, state);
+ }
}
/* Copy all lines into a local cache so we can reuse them later on more easily. */
@@ -809,6 +835,10 @@ void Layouter::ResetFontCache(FontSize size)
/* We must reset the linecache since it references the just freed fonts */
ResetLineCache();
+
+#if defined(WITH_UNISCRIBE)
+ UniscribeResetScriptCache(size);
+#endif
}
/**
diff --git a/src/os/windows/string_uniscribe.cpp b/src/os/windows/string_uniscribe.cpp
new file mode 100644
index 0000000000..ea8b8c0224
--- /dev/null
+++ b/src/os/windows/string_uniscribe.cpp
@@ -0,0 +1,610 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see .
+ */
+
+/** @file string_uniscribe.cpp Functions related to laying out text on Win32. */
+
+#if defined(WITH_UNISCRIBE)
+
+#include "../../stdafx.h"
+#include "../../debug.h"
+#include "string_uniscribe.h"
+#include "../../language.h"
+#include "../../strings_func.h"
+#include "../../string_func.h"
+#include "../../table/control_codes.h"
+#include "win32.h"
+#include
+
+#include
+#include
+
+#include "../../safeguards.h"
+
+#ifdef _MSC_VER
+# pragma comment(lib, "usp10")
+#endif
+
+
+/** Uniscribe cache for internal font information, cleared when OTTD changes fonts. */
+static SCRIPT_CACHE _script_cache[FS_END];
+
+/**
+ * Contains all information about a run of characters. A run are consecutive
+ * characters that share a single font and language.
+ */
+struct UniscribeRun {
+ int pos;
+ int len;
+ Font *font;
+
+ std::vector ft_glyphs;
+
+ SCRIPT_ANALYSIS sa;
+ std::vector char_to_glyph;
+
+ std::vector vis_attribs;
+ std::vector glyphs;
+ std::vector advances;
+ std::vector offsets;
+ int total_advance;
+
+ UniscribeRun(int pos, int len, Font *font, SCRIPT_ANALYSIS &sa) : pos(pos), len(len), font(font), sa(sa) {}
+};
+
+/** Break a string into language formatting ranges. */
+static std::vector UniscribeItemizeString(UniscribeParagraphLayoutFactory::CharType *buff, int32 length);
+/** Generate and place glyphs for a run of characters. */
+static bool UniscribeShapeRun(const UniscribeParagraphLayoutFactory::CharType *buff, UniscribeRun &range);
+
+/**
+ * Wrapper for doing layouts with Uniscribe.
+ */
+class UniscribeParagraphLayout : public ParagraphLayouter {
+private:
+ const UniscribeParagraphLayoutFactory::CharType *text_buffer;
+
+ std::vector ranges; ///< All runs of the text.
+ std::vector::iterator cur_range; ///< The next run to be output.
+ int cur_range_offset = 0; ///< Offset from the start of the current run from where to output.
+
+public:
+ /** Visual run contains data about the bit of text with the same font. */
+ class UniscribeVisualRun : public ParagraphLayouter::VisualRun {
+ private:
+ std::vector glyphs;
+ std::vector positions;
+ std::vector char_to_glyph;
+
+ int start_pos;
+ int total_advance;
+ int num_glyphs;
+ Font *font;
+
+ mutable int *glyph_to_char = NULL;
+
+ public:
+ UniscribeVisualRun(const UniscribeRun &range, int x);
+ virtual ~UniscribeVisualRun()
+ {
+ free(this->glyph_to_char);
+ }
+
+ virtual const GlyphID *GetGlyphs() const { return &this->glyphs[0]; }
+ virtual const float *GetPositions() const { return &this->positions[0]; }
+ virtual const int *GetGlyphToCharMap() const;
+
+ virtual const Font *GetFont() const { return this->font; }
+ virtual int GetLeading() const { return this->font->fc->GetHeight(); }
+ virtual int GetGlyphCount() const { return this->num_glyphs; }
+ int GetAdvance() const { return this->total_advance; }
+ };
+
+ /** A single line worth of VisualRuns. */
+ class UniscribeLine : public AutoDeleteSmallVector, public ParagraphLayouter::Line {
+ public:
+ virtual int GetLeading() const;
+ virtual int GetWidth() const;
+ virtual int CountRuns() const { return this->Length(); }
+ virtual const VisualRun *GetVisualRun(int run) const { return *this->Get(run); }
+
+ int GetInternalCharLength(WChar c) const
+ {
+ /* Uniscribe uses UTF-16 internally which means we need to account for surrogate pairs. */
+ return c >= 0x010000U ? 2 : 1;
+ }
+ };
+
+ UniscribeParagraphLayout(std::vector &ranges, const UniscribeParagraphLayoutFactory::CharType *buffer) : text_buffer(buffer), ranges(ranges)
+ {
+ this->Reflow();
+ }
+
+ virtual ~UniscribeParagraphLayout() {}
+
+ virtual void Reflow()
+ {
+ this->cur_range = this->ranges.begin();
+ this->cur_range_offset = 0;
+ }
+
+ virtual const Line *NextLine(int max_width);
+};
+
+void UniscribeResetScriptCache(FontSize size)
+{
+ if (_script_cache[size] != NULL) {
+ ScriptFreeCache(&_script_cache[size]);
+ _script_cache[size] = NULL;
+ }
+}
+
+/** Load the matching native Windows font. */
+static HFONT HFontFromFont(Font *font)
+{
+ LOGFONT logfont;
+ ZeroMemory(&logfont, sizeof(LOGFONT));
+ logfont.lfHeight = font->fc->GetHeight();
+ logfont.lfWeight = FW_NORMAL;
+ logfont.lfCharSet = DEFAULT_CHARSET;
+ convert_to_fs(font->fc->GetFontName(), logfont.lfFaceName, lengthof(logfont.lfFaceName));
+
+ return CreateFontIndirect(&logfont);
+}
+
+/** Determine the glyph positions for a run. */
+static bool UniscribeShapeRun(const UniscribeParagraphLayoutFactory::CharType *buff, UniscribeRun &range)
+{
+ /* Initial size guess for the number of glyphs recommended by Uniscribe. */
+ range.glyphs.resize(range.len * 3 / 2 + 16);
+ range.vis_attribs.resize(range.glyphs.size());
+
+ /* The char-to-glyph array is the same size as the input. */
+ range.char_to_glyph.resize(range.len);
+
+ HDC temp_dc = NULL;
+ HFONT old_font = NULL;
+ HFONT cur_font = NULL;
+
+ while (true) {
+ /* Shape the text run by determining the glyphs needed for display. */
+ int glyphs_used = 0;
+ HRESULT hr = ScriptShape(temp_dc, &_script_cache[range.font->fc->GetSize()], buff + range.pos, range.len, (int)range.glyphs.size(), &range.sa, &range.glyphs[0], &range.char_to_glyph[0], &range.vis_attribs[0], &glyphs_used);
+
+ if (SUCCEEDED(hr)) {
+ range.glyphs.resize(glyphs_used);
+ range.vis_attribs.resize(glyphs_used);
+
+ /* Calculate the glyph positions. */
+ ABC abc;
+ range.advances.resize(range.glyphs.size());
+ range.offsets.resize(range.glyphs.size());
+ hr = ScriptPlace(temp_dc, &_script_cache[range.font->fc->GetSize()], &range.glyphs[0], (int)range.glyphs.size(), &range.vis_attribs[0], &range.sa, &range.advances[0], &range.offsets[0], &abc);
+ if (SUCCEEDED(hr)) {
+ /* We map our special sprite chars to values that don't fit into a WORD. Copy the glyphs
+ * into a new vector and query the real glyph to use for these special chars. */
+ range.ft_glyphs.resize(range.glyphs.size());
+ for (size_t g_id = 0; g_id < range.glyphs.size(); g_id++) {
+ range.ft_glyphs[g_id] = range.glyphs[g_id];
+ }
+ for (int i = 0; i < range.len; i++) {
+ if (buff[range.pos + i] >= SCC_SPRITE_START && buff[range.pos + i] <= SCC_SPRITE_END) {
+ range.ft_glyphs[range.char_to_glyph[i]] = range.font->fc->MapCharToGlyph(buff[range.pos + i]);
+ }
+ }
+
+ /* FreeType and GDI/Uniscribe seems to occasionally disagree over the width of a glyph. */
+ range.total_advance = 0;
+ for (size_t i = 0; i < range.advances.size(); i++) {
+ if (range.advances[i] > 0 && range.ft_glyphs[i] != 0xFFFF) range.advances[i] = range.font->fc->GetGlyphWidth(range.ft_glyphs[i]);
+ range.total_advance += range.advances[i];
+ }
+ break;
+ }
+ }
+
+ if (hr == E_OUTOFMEMORY) {
+ /* The glyph buffer needs to be larger. Just double it every time. */
+ range.glyphs.resize(range.glyphs.size() * 2);
+ range.vis_attribs.resize(range.vis_attribs.size() * 2);
+ } else if (hr == E_PENDING) {
+ /* Glyph data is not in cache, load native font. */
+ cur_font = HFontFromFont(range.font);
+ if (cur_font == NULL) return false; // Sorry, no dice.
+
+ temp_dc = CreateCompatibleDC(NULL);
+ SetMapMode(temp_dc, MM_TEXT);
+ old_font = (HFONT)SelectObject(temp_dc, cur_font);
+ } else if (hr == USP_E_SCRIPT_NOT_IN_FONT && range.sa.eScript != SCRIPT_UNDEFINED) {
+ /* Try again with the generic shaping engine. */
+ range.sa.eScript = SCRIPT_UNDEFINED;
+ } else {
+ /* Some unknown other error. */
+ if (temp_dc != NULL) {
+ SelectObject(temp_dc, old_font);
+ DeleteObject(cur_font);
+ ReleaseDC(NULL, temp_dc);
+ }
+ return false;
+ }
+ }
+
+ if (temp_dc != NULL) {
+ SelectObject(temp_dc, old_font);
+ DeleteObject(cur_font);
+ ReleaseDC(NULL, temp_dc);
+ }
+
+ return true;
+}
+
+static std::vector UniscribeItemizeString(UniscribeParagraphLayoutFactory::CharType *buff, int32 length)
+{
+ /* Itemize text. */
+ SCRIPT_CONTROL control;
+ ZeroMemory(&control, sizeof(SCRIPT_CONTROL));
+ control.uDefaultLanguage = _current_language->winlangid;
+
+ SCRIPT_STATE state;
+ ZeroMemory(&state, sizeof(SCRIPT_STATE));
+ state.uBidiLevel = _current_text_dir == TD_RTL ? 1 : 0;
+
+ std::vector items(16);
+ while (true) {
+ /* We subtract one from max_items to work around a buffer overflow on some older versions of Windows. */
+ int generated = 0;
+ HRESULT hr = ScriptItemize(buff, length, (int)items.size() - 1, &control, &state, &items[0], &generated);
+
+ if (SUCCEEDED(hr)) {
+ /* Resize the item buffer. Note that Uniscribe will always add an additional end sentinel item. */
+ items.resize(generated + 1);
+ break;
+ }
+ /* Some kind of error except item buffer too small. */
+ if (hr != E_OUTOFMEMORY) return std::vector();
+
+ items.resize(items.size() * 2);
+ }
+
+ return items;
+}
+
+/* static */ ParagraphLayouter *UniscribeParagraphLayoutFactory::GetParagraphLayout(CharType *buff, CharType *buff_end, FontMap &fontMapping)
+{
+ int32 length = buff_end - buff;
+ /* Can't layout an empty string. */
+ if (length == 0) return NULL;
+
+ /* Can't layout our in-built sprite fonts. */
+ for (FontMap::const_iterator i = fontMapping.Begin(); i != fontMapping.End(); i++) {
+ if (i->second->fc->IsBuiltInFont()) return NULL;
+ }
+
+ /* Itemize text. */
+ std::vector items = UniscribeItemizeString(buff, length);
+ if (items.size() == 0) return NULL;
+
+ /* Build ranges from the items and the font map. A range is a run of text
+ * that is part of a single item and formatted using a single font style. */
+ std::vector ranges;
+
+ int cur_pos = 0;
+ std::vector::iterator cur_item = items.begin();
+ for (FontMap::const_iterator i = fontMapping.Begin(); i != fontMapping.End(); i++) {
+ while (cur_pos < i->first && cur_item != items.end() - 1) {
+ /* Add a range that spans the intersection of the remaining item and font run. */
+ int stop_pos = min(i->first, (cur_item + 1)->iCharPos);
+ assert(stop_pos - cur_pos > 0);
+ ranges.push_back(UniscribeRun(cur_pos, stop_pos - cur_pos, i->second, cur_item->a));
+
+ /* Shape the range. */
+ if (!UniscribeShapeRun(buff, ranges.back())) {
+ return NULL;
+ }
+
+ /* If we are at the end of the current item, advance to the next item. */
+ if (stop_pos == (cur_item + 1)->iCharPos) cur_item++;
+ cur_pos = stop_pos;
+ }
+ }
+
+ return new UniscribeParagraphLayout(ranges, buff);
+}
+
+/* virtual */ const ParagraphLayouter::Line *UniscribeParagraphLayout::NextLine(int max_width)
+{
+ std::vector::iterator start_run = this->cur_range;
+ std::vector::iterator last_run = this->cur_range;
+
+ if (start_run == this->ranges.end()) return NULL;
+
+ /* Add remaining width of the first run if it is a broken run. */
+ int cur_width = 0;
+ if (this->cur_range_offset != 0) {
+ std::vector dx(start_run->len);
+ ScriptGetLogicalWidths(&start_run->sa, start_run->len, (int)start_run->glyphs.size(), &start_run->advances[0], &start_run->char_to_glyph[0], &start_run->vis_attribs[0], &dx[0]);
+
+ for (std::vector::const_iterator c = dx.begin() + this->cur_range_offset; c != dx.end(); c++) {
+ cur_width += *c;
+ }
+ ++last_run;
+ }
+
+ /* Gather runs until the line is full. */
+ while (last_run != this->ranges.end() && cur_width < max_width) {
+ cur_width += last_run->total_advance;
+ ++last_run;
+ }
+
+ /* If the text does not fit into the available width, find a suitable breaking point. */
+ int remaing_offset = (last_run - 1)->len;
+ if (cur_width > max_width) {
+ std::vector log_attribs;
+
+ /* Get word break information. */
+ int width_avail = max_width;
+ int num_chars = this->cur_range_offset;
+ int start_offs = this->cur_range_offset;
+ int last_cluster = this->cur_range_offset + 1;
+ for (std::vector::iterator r = start_run; r != last_run; r++) {
+ log_attribs.resize(r->pos - start_run->pos + r->len);
+ if (FAILED(ScriptBreak(this->text_buffer + r->pos + start_offs, r->len - start_offs, &r->sa, &log_attribs[r->pos - start_run->pos + start_offs]))) return NULL;
+
+ std::vector dx(r->len);
+ ScriptGetLogicalWidths(&r->sa, r->len, (int)r->glyphs.size(), &r->advances[0], &r->char_to_glyph[0], &r->vis_attribs[0], &dx[0]);
+
+ /* Count absolute max character count on the line. */
+ for (int c = start_offs; c < r->len && width_avail > 0; c++, num_chars++) {
+ if (c > start_offs && log_attribs[num_chars].fCharStop) last_cluster = num_chars;
+ width_avail -= dx[c];
+ }
+
+ start_offs = 0;
+ }
+
+ /* Walk backwards to find the last suitable breaking point. */
+ while (--num_chars > this->cur_range_offset && !log_attribs[num_chars].fSoftBreak && !log_attribs[num_chars].fWhiteSpace) {}
+
+ if (num_chars == this->cur_range_offset) {
+ /* Didn't find any suitable word break point, just break on the last cluster boundary. */
+ num_chars = last_cluster;
+ }
+
+ /* Include whitespace characters after the breaking point. */
+ while (num_chars < (int)log_attribs.size() && log_attribs[num_chars].fWhiteSpace) {
+ num_chars++;
+ }
+
+ /* Get last run that corresponds to the number of characters to show. */
+ for (std::vector::iterator run = start_run; run != last_run; run++) {
+ num_chars -= run->len;
+
+ if (num_chars <= 0) {
+ remaing_offset = num_chars + run->len + 1;
+ last_run = run + 1;
+ assert(remaing_offset - 1 > 0);
+ break;
+ }
+ }
+ }
+
+ /* Build display order from the runs. */
+ std::vector bidi_level;
+ for (std::vector::iterator r = start_run; r != last_run; r++) {
+ bidi_level.push_back(r->sa.s.uBidiLevel);
+ }
+ std::vector vis_to_log(bidi_level.size());
+ if (FAILED(ScriptLayout((int)bidi_level.size(), &bidi_level[0], &vis_to_log[0], NULL))) return NULL;
+
+ /* Create line. */
+ UniscribeLine *line = new UniscribeLine();
+
+ int cur_pos = 0;
+ for (std::vector::iterator l = vis_to_log.begin(); l != vis_to_log.end(); l++) {
+ std::vector::iterator i_run = start_run + *l;
+ UniscribeRun run = *i_run;
+
+ /* Partial run after line break (either start or end)? Reshape run to get the first/last glyphs right. */
+ if (i_run == last_run - 1 && remaing_offset < (last_run - 1)->len) {
+ run.len = remaing_offset - 1;
+
+ if (!UniscribeShapeRun(this->text_buffer, run)) return NULL;
+ }
+ if (i_run == start_run && this->cur_range_offset > 0) {
+ assert(run.len - this->cur_range_offset > 0);
+ run.pos += this->cur_range_offset;
+ run.len -= this->cur_range_offset;
+
+ if (!UniscribeShapeRun(this->text_buffer, run)) return NULL;
+ }
+
+ *line->Append() = new UniscribeVisualRun(run, cur_pos);
+ cur_pos += run.total_advance;
+ }
+
+ if (remaing_offset < (last_run - 1)->len) {
+ /* We didn't use up all of the last run, store remainder for the next line. */
+ this->cur_range_offset = remaing_offset - 1;
+ this->cur_range = last_run - 1;
+ assert(this->cur_range->len > this->cur_range_offset);
+ } else {
+ this->cur_range_offset = 0;
+ this->cur_range = last_run;
+ }
+
+ return line;
+}
+
+/**
+ * Get the height of the line.
+ * @return The maximum height of the line.
+ */
+int UniscribeParagraphLayout::UniscribeLine::GetLeading() const
+{
+ int leading = 0;
+ for (const UniscribeVisualRun * const *run = this->Begin(); run != this->End(); run++) {
+ leading = max(leading, (*run)->GetLeading());
+ }
+
+ return leading;
+}
+
+/**
+ * Get the width of this line.
+ * @return The width of the line.
+ */
+int UniscribeParagraphLayout::UniscribeLine::GetWidth() const
+{
+ int length = 0;
+ for (const UniscribeVisualRun * const *run = this->Begin(); run != this->End(); run++) {
+ length += (*run)->GetAdvance();
+ }
+
+ return length;
+}
+
+UniscribeParagraphLayout::UniscribeVisualRun::UniscribeVisualRun(const UniscribeRun &range, int x) : glyphs(range.ft_glyphs), char_to_glyph(range.char_to_glyph), start_pos(range.pos), total_advance(range.total_advance), font(range.font)
+{
+ this->num_glyphs = (int)glyphs.size();
+ this->positions.resize(this->num_glyphs * 2 + 2);
+
+ int advance = 0;
+ for (int i = 0; i < this->num_glyphs; i++) {
+ this->positions[i * 2 + 0] = range.offsets[i].du + advance + x;
+ this->positions[i * 2 + 1] = range.offsets[i].dv;
+
+ advance += range.advances[i];
+ }
+ this->positions[this->num_glyphs * 2] = advance + x;
+}
+
+const int *UniscribeParagraphLayout::UniscribeVisualRun::GetGlyphToCharMap() const
+{
+ if (this->glyph_to_char == NULL) {
+ this->glyph_to_char = CallocT(this->GetGlyphCount());
+
+ /* The char to glyph array contains the first glyph index of the cluster that is associated
+ * with each character. It is possible for a cluster to be formed of several chars. */
+ for (int c = 0; c < (int)this->char_to_glyph.size(); c++) {
+ /* If multiple chars map to one glyph, only refer back to the first character. */
+ if (this->glyph_to_char[this->char_to_glyph[c]] == 0) this->glyph_to_char[this->char_to_glyph[c]] = c + this->start_pos;
+ }
+
+ /* We only marked the first glyph of each cluster in the loop above. Fill the gaps. */
+ int last_char = this->glyph_to_char[0];
+ for (int g = 0; g < this->GetGlyphCount(); g++) {
+ if (this->glyph_to_char[g] != 0) last_char = this->glyph_to_char[g];
+ this->glyph_to_char[g] = last_char;
+ }
+ }
+
+ return this->glyph_to_char;
+}
+
+
+/* virtual */ void UniscribeStringIterator::SetString(const char *s)
+{
+ const char *string_base = s;
+
+ this->utf16_to_utf8.clear();
+ this->str_info.clear();
+ this->cur_pos = 0;
+
+ /* Uniscribe operates on UTF-16, thus we have to convert the input string.
+ * To be able to return proper offsets, we have to create a mapping at the same time. */
+ std::vector utf16_str; ///< UTF-16 copy of the string.
+ while (*s != '\0') {
+ size_t idx = s - string_base;
+
+ WChar c = Utf8Consume(&s);
+ if (c < 0x10000) {
+ utf16_str.push_back((wchar_t)c);
+ } else {
+ /* Make a surrogate pair. */
+ utf16_str.push_back((wchar_t)(0xD800 + ((c - 0x10000) >> 10)));
+ utf16_str.push_back((wchar_t)(0xDC00 + ((c - 0x10000) & 0x3FF)));
+ this->utf16_to_utf8.push_back(idx);
+ }
+ this->utf16_to_utf8.push_back(idx);
+ }
+ this->utf16_to_utf8.push_back(s - string_base);
+
+ /* Query Uniscribe for word and cluster break information. */
+ this->str_info.resize(utf16_to_utf8.size());
+
+ if (utf16_str.size() > 0) {
+ /* Itemize string into language runs. */
+ std::vector runs = UniscribeItemizeString(&utf16_str[0], (int32)utf16_str.size());
+
+ for (std::vector::const_iterator run = runs.begin(); runs.size() > 0 && run != runs.end() - 1; run++) {
+ /* Get information on valid word and character break.s */
+ int len = (run + 1)->iCharPos - run->iCharPos;
+ std::vector attr(len);
+ ScriptBreak(&utf16_str[run->iCharPos], len, &run->a, &attr[0]);
+
+ /* Extract the information we're interested in. */
+ for (size_t c = 0; c < attr.size(); c++) {
+ /* First character of a run is always a valid word break. */
+ this->str_info[c + run->iCharPos].word_stop = attr[c].fWordStop || c == 0;
+ this->str_info[c + run->iCharPos].char_stop = attr[c].fCharStop;
+ }
+ }
+ }
+
+ /* End-of-string is always a valid stopping point. */
+ this->str_info.back().char_stop = true;
+ this->str_info.back().word_stop = true;
+}
+
+/* virtual */ size_t UniscribeStringIterator::SetCurPosition(size_t pos)
+{
+ /* Convert incoming position to an UTF-16 string index. */
+ size_t utf16_pos = 0;
+ for (size_t i = 0; i < this->utf16_to_utf8.size(); i++) {
+ if (this->utf16_to_utf8[i] == pos) {
+ utf16_pos = i;
+ break;
+ }
+ }
+
+ /* Sanitize in case we get a position inside a grapheme cluster. */
+ while (utf16_pos > 0 && !this->str_info[utf16_pos].char_stop) utf16_pos--;
+ this->cur_pos = utf16_pos;
+
+ return this->utf16_to_utf8[this->cur_pos];
+}
+
+/* virtual */ size_t UniscribeStringIterator::Next(IterType what)
+{
+ assert(this->cur_pos <= this->utf16_to_utf8.size());
+ assert(what == StringIterator::ITER_CHARACTER || what == StringIterator::ITER_WORD);
+
+ if (this->cur_pos == this->utf16_to_utf8.size()) return END;
+
+ do {
+ this->cur_pos++;
+ } while (this->cur_pos < this->utf16_to_utf8.size() && (what == ITER_WORD ? !this->str_info[this->cur_pos].word_stop : !this->str_info[this->cur_pos].char_stop));
+
+ return this->cur_pos == this->utf16_to_utf8.size() ? END : this->utf16_to_utf8[this->cur_pos];
+}
+
+/*virtual */ size_t UniscribeStringIterator::Prev(IterType what)
+{
+ assert(this->cur_pos <= this->utf16_to_utf8.size());
+ assert(what == StringIterator::ITER_CHARACTER || what == StringIterator::ITER_WORD);
+
+ if (this->cur_pos == 0) return END;
+
+ do {
+ this->cur_pos--;
+ } while (this->cur_pos > 0 && (what == ITER_WORD ? !this->str_info[this->cur_pos].word_stop : !this->str_info[this->cur_pos].char_stop));
+
+ return this->utf16_to_utf8[this->cur_pos];
+}
+
+#endif /* defined(WITH_UNISCRIBE) */
diff --git a/src/os/windows/string_uniscribe.h b/src/os/windows/string_uniscribe.h
new file mode 100644
index 0000000000..6af858a88f
--- /dev/null
+++ b/src/os/windows/string_uniscribe.h
@@ -0,0 +1,92 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see .
+ */
+
+/** @file string_uniscribe.h Functions related to laying out text on Win32. */
+
+#ifndef STRING_UNISCRIBE_H
+#define STRING_UNISCRIBE_H
+
+#if defined(WITH_UNISCRIBE)
+
+#include "../../gfx_layout.h"
+#include "../../string_base.h"
+#include
+
+
+void UniscribeResetScriptCache(FontSize size);
+
+
+/**
+ * Helper class to construct a new #UniscribeParagraphLayout.
+ */
+class UniscribeParagraphLayoutFactory {
+public:
+ /** Helper for GetLayouter, to get the right type. */
+ typedef wchar_t CharType;
+ /** Helper for GetLayouter, to get whether the layouter supports RTL. */
+ static const bool SUPPORTS_RTL = true;
+
+ /**
+ * Get the actual ParagraphLayout for the given buffer.
+ * @param buff The begin of the buffer.
+ * @param buff_end The location after the last element in the buffer.
+ * @param fontMapping THe mapping of the fonts.
+ * @return The ParagraphLayout instance.
+ */
+ static ParagraphLayouter *GetParagraphLayout(CharType *buff, CharType *buff_end, FontMap &fontMapping);
+
+ /**
+ * Append a wide character to the internal buffer.
+ * @param buff The buffer to append to.
+ * @param buffer_last The end of the buffer.
+ * @param c The character to add.
+ * @return The number of buffer spaces that were used.
+ */
+ static size_t AppendToBuffer(CharType *buff, const CharType *buffer_last, WChar c)
+ {
+ if (c >= 0x010000U) {
+ /* Character is encoded using surrogates in UTF-16. */
+ if (buff + 1 <= buffer_last) {
+ buff[0] = (CharType)(((c - 0x010000U) >> 10) + 0xD800);
+ buff[1] = (CharType)(((c - 0x010000U) & 0x3FF) + 0xDC00);
+ } else {
+ /* Not enough space in buffer. */
+ *buff = 0;
+ }
+ return 2;
+ } else {
+ *buff = (CharType)(c & 0xFFFF);
+ return 1;
+ }
+ }
+};
+
+/** String iterator using Uniscribe as a backend. */
+class UniscribeStringIterator : public StringIterator {
+ /** */
+ struct CharInfo {
+ bool word_stop : 1; ///< Code point is suitable as a word break.
+ bool char_stop : 1; ///< Code point is the start of a grapheme cluster, i.e. a "character".
+ };
+
+ std::vector str_info; ///< Break information for each code point.
+ std::vector utf16_to_utf8; ///< Mapping from UTF-16 code point position to index in the UTF-8 source string.
+
+ size_t cur_pos; ///< Current iteration position.
+
+public:
+ virtual void SetString(const char *s);
+ virtual size_t SetCurPosition(size_t pos);
+ virtual size_t Next(IterType what);
+ virtual size_t Prev(IterType what);
+};
+
+#endif /* defined(WITH_UNISCRIBE) */
+
+#endif /* STRING_UNISCRIBE_H */
diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp
index 1c22f1af68..37d399eb35 100644
--- a/src/os/windows/win32.cpp
+++ b/src/os/windows/win32.cpp
@@ -28,6 +28,7 @@
#include "../../crashlog.h"
#include
#include
+#include "../../language.h"
/* Due to TCHAR, strncat and strncpy have to remain (for a while). */
#include "../../safeguards.h"
@@ -742,6 +743,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 16632f6e9a..4f813c4a6f 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 */
diff --git a/src/string.cpp b/src/string.cpp
index b68f38d6ce..2afe86776a 100644
--- a/src/string.cpp
+++ b/src/string.cpp
@@ -25,6 +25,14 @@
#include // required by vsnprintf implementation for MSVC
#endif
+#ifdef WIN32
+#include "os/windows/win32.h"
+#endif
+
+#ifdef WITH_UNISCRIBE
+#include "os/windows/string_uniscribe.h"
+#endif
+
#ifdef WITH_ICU_SORT
/* Required by strnatcmp. */
#include
@@ -658,20 +666,32 @@ int strnatcmp(const char *s1, const char *s2, bool ignore_garbage_at_front)
s1 = SkipGarbage(s1);
s2 = SkipGarbage(s2);
}
+
#ifdef WITH_ICU_SORT
if (_current_collator != NULL) {
UErrorCode status = U_ZERO_ERROR;
int result = _current_collator->compareUTF8(s1, s2, status);
if (U_SUCCESS(status)) return result;
}
-
#endif /* WITH_ICU_SORT */
+#if defined(WIN32) && !defined(STRGEN) && !defined(SETTINGSGEN)
+ int res = OTTDStringCompare(s1, s2);
+ if (res != 0) return res - 2; // Convert to normal C return values.
+#endif
+
/* Do a manual natural sort comparison if ICU is missing or if we cannot create a collator. */
return _strnatcmpIntl(s1, s2);
}
-#ifdef WITH_ICU_SORT
+#ifdef WITH_UNISCRIBE
+
+/* static */ StringIterator *StringIterator::Create()
+{
+ return new UniscribeStringIterator();
+}
+
+#elif defined(WITH_ICU_SORT)
#include
#include
diff --git a/src/strings.cpp b/src/strings.cpp
index 79063439ef..5ab89b8ab2 100644
--- a/src/strings.cpp
+++ b/src/strings.cpp
@@ -2048,6 +2048,11 @@ bool ReadLanguagePack(const LanguageMetadata *lang)
strecpy(_config_language_file, c_file, lastof(_config_language_file));
SetCurrentGrfLangID(_current_language->newgrflangid);
+#ifdef WIN32
+ extern void Win32SetCurrentLocaleName(const char *iso_code);
+ Win32SetCurrentLocaleName(_current_language->isocode);
+#endif
+
#ifdef WITH_ICU_SORT
/* Delete previous collator. */
if (_current_collator != NULL) {
@@ -2390,7 +2395,7 @@ void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher)
/* Update the font with cache */
LoadStringWidthTable(searcher->Monospace());
-#if !defined(WITH_ICU_LAYOUT)
+#if !defined(WITH_ICU_LAYOUT) && !defined(WITH_UNISCRIBE)
/*
* For right-to-left languages we need the ICU library. If
* we do not have support for that library we warn the user