Merge branch 'master' into jgrpp

# Conflicts:
#	src/articulated_vehicles.cpp
#	src/articulated_vehicles.h
#	src/base_media_base.h
#	src/base_media_func.h
#	src/build_vehicle_gui.cpp
#	src/dock_gui.cpp
#	src/main_gui.cpp
#	src/music_gui.cpp
#	src/network/network_chat_gui.cpp
#	src/network/network_content.cpp
#	src/newgrf.cpp
#	src/newgrf_roadstop.cpp
#	src/os/windows/string_uniscribe.h
#	src/os/windows/win32.cpp
#	src/rail_gui.cpp
#	src/road.cpp
#	src/road_gui.cpp
#	src/settings.cpp
#	src/settings_gui.cpp
#	src/smallmap_gui.cpp
#	src/strings.cpp
#	src/terraform_gui.cpp
#	src/tests/test_script_admin.cpp
#	src/tests/test_window_desc.cpp
#	src/timer/timer_game_calendar.h
#	src/vehicle.cpp
#	src/vehicle_base.h
#	src/viewport.cpp
#	src/widget_type.h
#	src/window.cpp
#	src/window_gui.h
This commit is contained in:
Jonathan G Rennison
2023-11-29 20:32:54 +00:00
154 changed files with 1094 additions and 798 deletions

View File

@@ -340,6 +340,31 @@ int MacOSStringCompare(std::string_view s1, std::string_view s2)
return (int)CFStringCompareWithOptionsAndLocale(cf1.get(), cf2.get(), CFRangeMake(0, CFStringGetLength(cf1.get())), flags, _osx_locale.get()) + 2;
}
/**
* Search if a string is contained in another string using the current locale.
*
* @param str String to search in.
* @param value String to search for.
* @param case_insensitive Search case-insensitive.
* @return 1 if value was found, 0 if it was not found, or -1 if not supported by the OS.
*/
int MacOSStringContains(const std::string_view str, const std::string_view value, bool case_insensitive)
{
static bool supported = MacOSVersionIsAtLeast(10, 5, 0);
if (!supported) return -1;
CFStringCompareFlags flags = kCFCompareLocalized | kCFCompareWidthInsensitive;
if (case_insensitive) flags |= kCFCompareCaseInsensitive;
CFAutoRelease<CFStringRef> cf_str(CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)str.data(), str.size(), kCFStringEncodingUTF8, false));
CFAutoRelease<CFStringRef> cf_value(CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)value.data(), value.size(), kCFStringEncodingUTF8, false));
/* If any CFString could not be created (e.g., due to UTF8 invalid chars), return OS unsupported functionality */
if (cf_str == nullptr || cf_value == nullptr) return -1;
return CFStringFindWithOptionsAndLocale(cf_str.get(), cf_value.get(), CFRangeMake(0, CFStringGetLength(cf_str.get())), flags, _osx_locale.get(), nullptr) ? 1 : 0;
}
/* virtual */ void OSXStringIterator::SetString(const char *s)
{

View File

@@ -85,6 +85,7 @@ public:
void MacOSResetScriptCache(FontSize size);
void MacOSSetCurrentLocaleName(const char *iso_code);
int MacOSStringCompare(std::string_view s1, std::string_view s2);
int MacOSStringContains(const std::string_view str, const std::string_view value, bool case_insensitive);
void MacOSRegisterExternalFont(const char *file_path);

View File

@@ -79,8 +79,8 @@ FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
if (!font_style.empty() && !StrEqualsIgnoreCase(font_style, (char *)style)) continue;
/* Font config takes the best shot, which, if the family name is spelled
* wrongly a 'random' font, so check whether the family name is the
* same as the supplied name */
* wrongly a 'random' font, so check whether the family name is the
* same as the supplied name */
if (StrEqualsIgnoreCase(font_family, (char *)family)) {
err = FT_New_Face(_library, (char *)file, index, face);
}

View File

@@ -866,7 +866,7 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA
/* Convert unix -> dos newlines because the edit box only supports that properly :( */
const char *unix_nl = CrashLogWindows::current->crashlog;
char *p = dos_nl;
WChar c;
char32_t c;
while ((c = Utf8Consume(&unix_nl)) && p < (dos_nl + dos_nl_length - 1) - 4) { // 4 is max number of bytes per character
if (c == '\n') p += Utf8Encode(p, '\r');
p += Utf8Encode(p, c);

View File

@@ -276,7 +276,7 @@ void Win32FontCache::ClearFontCache()
return new_glyph.sprite;
}
/* virtual */ GlyphID Win32FontCache::MapCharToGlyph(WChar key)
/* virtual */ GlyphID Win32FontCache::MapCharToGlyph(char32_t key)
{
assert(IsPrintable(key));

View File

@@ -33,7 +33,7 @@ public:
Win32FontCache(FontSize fs, const LOGFONT &logfont, int pixels);
~Win32FontCache();
void ClearFontCache() override;
GlyphID MapCharToGlyph(WChar key) override;
GlyphID MapCharToGlyph(char32_t key) override;
std::string GetFontName() override { return this->fontname; }
const void *GetOSHandle() override { return &this->logfont; }
};

View File

@@ -111,7 +111,7 @@ public:
int CountRuns() const override { return (uint)this->size(); }
const VisualRun &GetVisualRun(int run) const override { return this->at(run); }
int GetInternalCharLength(WChar c) const override
int GetInternalCharLength(char32_t c) const override
{
/* Uniscribe uses UTF-16 internally which means we need to account for surrogate pairs. */
return c >= 0x010000U ? 2 : 1;
@@ -537,7 +537,7 @@ const int *UniscribeParagraphLayout::UniscribeVisualRun::GetGlyphToCharMap() con
while (*s != '\0') {
size_t idx = s - string_base;
WChar c = Utf8Consume(&s);
char32_t c = Utf8Consume(&s);
if (c < 0x10000) {
utf16_str.push_back((wchar_t)c);
} else {

View File

@@ -29,22 +29,22 @@ public:
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.
*/
* 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)
* 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, char32_t c)
{
assert(buff < buffer_last);
if (c >= 0x010000U) {

View File

@@ -19,6 +19,7 @@
#define NO_SHOBJIDL_SORTDIRECTION // Avoid multiple definition of SORT_ASCENDING
#include <shlobj.h> /* SHGetFolderPath */
#include <shellapi.h>
#include <winnls.h>
#include "win32.h"
#include "../../fios.h"
#include "../../core/alloc_func.hpp"
@@ -715,6 +716,43 @@ int OTTDStringCompare(std::string_view s1, std::string_view s2)
return CompareString(MAKELCID(_current_language->winlangid, SORT_DEFAULT), NORM_IGNORECASE, s1_buf, -1, s2_buf, -1);
}
/**
* Search if a string is contained in another string using the current locale.
*
* @param str String to search in.
* @param value String to search for.
* @param case_insensitive Search case-insensitive.
* @return 1 if value was found, 0 if it was not found, or -1 if not supported by the OS.
*/
int Win32StringContains(const std::string_view str, const std::string_view value, bool case_insensitive)
{
typedef int (WINAPI *PFNFINDNLSSTRINGEX)(LPCWSTR, DWORD, LPCWSTR, int, LPCWSTR, int, LPINT, LPNLSVERSIONINFO, LPVOID, LPARAM);
static PFNFINDNLSSTRINGEX _FindNLSStringEx = nullptr;
static bool first_time = true;
if (first_time) {
_FindNLSStringEx = GetProcAddressT<PFNFINDNLSSTRINGEX>(GetModuleHandle(L"Kernel32"), "FindNLSStringEx");
first_time = false;
}
if (_FindNLSStringEx != nullptr) {
int len_str = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0);
int len_value = MultiByteToWideChar(CP_UTF8, 0, value.data(), (int)value.size(), nullptr, 0);
if (len_str != 0 && len_value != 0) {
std::wstring str_str(len_str, L'\0'); // len includes terminating null
std::wstring str_value(len_value, L'\0');
MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), str_str.data(), len_str);
MultiByteToWideChar(CP_UTF8, 0, value.data(), (int)value.size(), str_value.data(), len_value);
return _FindNLSStringEx(_cur_iso_locale, FIND_FROMSTART | (case_insensitive ? LINGUISTIC_IGNORECASE : 0), str_str.data(), -1, str_value.data(), -1, nullptr, nullptr, nullptr, 0) >= 0 ? 1 : 0;
}
}
return -1; // Failure indication.
}
static DWORD main_thread_id;
static DWORD game_thread_id;

View File

@@ -25,6 +25,7 @@ wchar_t *convert_to_fs(const std::string_view name, wchar_t *utf16_buf, size_t b
void Win32SetCurrentLocaleName(const char *iso_code);
int OTTDStringCompare(std::string_view s1, std::string_view s2);
int Win32StringContains(const std::string_view str, const std::string_view value, bool case_insensitive);
#ifdef __MINGW32__
/* GCC doesn't understand the expected usage of GetProcAddress(). */