From e0561dbded57f195e7842cf69764e3ee2c3a71da Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Sun, 21 Feb 2021 17:03:19 +0100 Subject: [PATCH 01/31] Fix #8713: Change OTTD2FS and FS2OTTD to return string objects instead of static buffers --- src/debug.cpp | 2 +- src/fileio.cpp | 14 ++++---- src/fileio_func.h | 2 +- src/fios.cpp | 4 +-- src/ini.cpp | 6 ++-- src/music/cocoa_m.cpp | 4 +-- src/music/dmusic.cpp | 4 +-- src/network/core/address.cpp | 2 +- src/os/os2/os2.cpp | 3 -- src/os/unix/unix.cpp | 21 +++++------- src/os/windows/crashlog_win.cpp | 37 +++++++++++--------- src/os/windows/font_win32.cpp | 11 +++--- src/os/windows/font_win32.h | 3 +- src/os/windows/win32.cpp | 60 ++++++++++++++++++--------------- src/stdafx.h | 26 +++++++------- src/strings.cpp | 6 ++-- src/video/win32_v.cpp | 4 +-- 17 files changed, 109 insertions(+), 100 deletions(-) diff --git a/src/debug.cpp b/src/debug.cpp index 034af755fd..eb8dc5d4fa 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -134,7 +134,7 @@ static void debug_print(const char *dbg, const char *buf) #if defined(_WIN32) wchar_t system_buf[512]; convert_to_fs(buffer, system_buf, lengthof(system_buf), true); - _fputts(system_buf, stderr); + fputws(system_buf, stderr); #else fputs(buffer, stderr); #endif diff --git a/src/fileio.cpp b/src/fileio.cpp index 6b33f8aa24..f2a2b14f3a 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -279,7 +279,7 @@ bool FioCheckFileExists(const std::string &filename, Subdirectory subdir) */ bool FileExists(const std::string &filename) { - return access(OTTD2FS(filename.c_str()), 0) == 0; + return access(OTTD2FS(filename).c_str(), 0) == 0; } /** @@ -358,7 +358,7 @@ static FILE *FioFOpenFileSp(const std::string &filename, const char *mode, Searc } #if defined(_WIN32) - if (mode[0] == 'r' && GetFileAttributes(OTTD2FS(buf.c_str())) == INVALID_FILE_ATTRIBUTES) return nullptr; + if (mode[0] == 'r' && GetFileAttributes(OTTD2FS(buf).c_str()) == INVALID_FILE_ATTRIBUTES) return nullptr; #endif f = fopen(buf.c_str(), mode); @@ -506,11 +506,11 @@ void FioCreateDirectory(const std::string &name) /* Ignore directory creation errors; they'll surface later on, and most * of the time they are 'directory already exists' errors anyhow. */ #if defined(_WIN32) - CreateDirectory(OTTD2FS(name.c_str()), nullptr); + CreateDirectory(OTTD2FS(name).c_str(), nullptr); #elif defined(OS2) && !defined(__INNOTEK_LIBC__) - mkdir(OTTD2FS(name.c_str())); + mkdir(OTTD2FS(name).c_str()); #else - mkdir(OTTD2FS(name.c_str()), 0755); + mkdir(OTTD2FS(name).c_str(), 0755); #endif } @@ -1315,7 +1315,7 @@ static uint ScanPath(FileScanner *fs, const char *extension, const char *path, s if (path == nullptr || (dir = ttd_opendir(path)) == nullptr) return 0; while ((dirent = readdir(dir)) != nullptr) { - const char *d_name = FS2OTTD(dirent->d_name); + std::string d_name = FS2OTTD(dirent->d_name); if (!FiosIsValidFile(path, dirent, &sb)) continue; @@ -1325,7 +1325,7 @@ static uint ScanPath(FileScanner *fs, const char *extension, const char *path, s if (S_ISDIR(sb.st_mode)) { /* Directory */ if (!recursive) continue; - if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue; + if (d_name == "." || d_name == "..") continue; AppendPathSeparator(filename); num += ScanPath(fs, extension, filename.c_str(), basepath_length, recursive); } else if (S_ISREG(sb.st_mode)) { diff --git a/src/fileio_func.h b/src/fileio_func.h index 6dbaea8970..1428356506 100644 --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -132,7 +132,7 @@ int closedir(DIR *d); */ static inline DIR *ttd_opendir(const char *path) { - return opendir(OTTD2FS(path)); + return opendir(OTTD2FS(path).c_str()); } diff --git a/src/fios.cpp b/src/fios.cpp index b48bc21089..b68da08f80 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -309,7 +309,7 @@ bool FiosFileScanner::AddFile(const std::string &filename, size_t basepath_lengt FiosItem *fios = file_list.Append(); #ifdef _WIN32 // Retrieve the file modified date using GetFileTime rather than stat to work around an obscure MSVC bug that affects Windows XP - HANDLE fh = CreateFile(OTTD2FS(filename.c_str()), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); + HANDLE fh = CreateFile(OTTD2FS(filename).c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); if (fh != INVALID_HANDLE_VALUE) { FILETIME ft; @@ -384,7 +384,7 @@ static void FiosGetFileList(SaveLoadOperation fop, fios_getlist_callback_proc *c /* Show subdirectories */ if ((dir = ttd_opendir(_fios_path->c_str())) != nullptr) { while ((dirent = readdir(dir)) != nullptr) { - strecpy(d_name, FS2OTTD(dirent->d_name), lastof(d_name)); + strecpy(d_name, FS2OTTD(dirent->d_name).c_str(), lastof(d_name)); /* found file must be directory, but not '.' or '..' */ if (FiosIsValidFile(_fios_path->c_str(), dirent, &sb) && S_ISDIR(sb.st_mode) && diff --git a/src/ini.cpp b/src/ini.cpp index 4988c778ee..a5045b7151 100644 --- a/src/ini.cpp +++ b/src/ini.cpp @@ -53,7 +53,7 @@ bool IniFile::SaveToDisk(const std::string &filename) std::string file_new{ filename }; file_new.append(".new"); - std::ofstream os(OTTD2FS(file_new.c_str())); + std::ofstream os(OTTD2FS(file_new)); if (os.fail()) return false; for (const IniGroup *group = this->group; group != nullptr; group = group->next) { @@ -94,8 +94,8 @@ bool IniFile::SaveToDisk(const std::string &filename) #if defined(_WIN32) /* Allocate space for one more \0 character. */ wchar_t tfilename[MAX_PATH + 1], tfile_new[MAX_PATH + 1]; - wcsncpy(tfilename, OTTD2FS(filename.c_str()), MAX_PATH); - wcsncpy(tfile_new, OTTD2FS(file_new.c_str()), MAX_PATH); + wcsncpy(tfilename, OTTD2FS(filename).c_str(), MAX_PATH); + wcsncpy(tfile_new, OTTD2FS(file_new).c_str(), MAX_PATH); /* SHFileOperation wants a double '\0' terminated string. */ tfilename[MAX_PATH - 1] = '\0'; tfile_new[MAX_PATH - 1] = '\0'; diff --git a/src/music/cocoa_m.cpp b/src/music/cocoa_m.cpp index a989cfe769..279e0b38ae 100644 --- a/src/music/cocoa_m.cpp +++ b/src/music/cocoa_m.cpp @@ -134,8 +134,8 @@ void MusicDriver_Cocoa::PlaySong(const MusicSongInfo &song) return; } - const char *os_file = OTTD2FS(filename.c_str()); - CFAutoRelease url(CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)os_file, strlen(os_file), false)); + std::string os_file = OTTD2FS(filename); + CFAutoRelease url(CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)os_file.c_str(), os_file.length(), false)); if (MusicSequenceFileLoad(_sequence, url.get(), kMusicSequenceFile_AnyType, 0) != noErr) { DEBUG(driver, 0, "cocoa_m: Failed to load MIDI file"); diff --git a/src/music/dmusic.cpp b/src/music/dmusic.cpp index c9447206af..619a20d8bf 100644 --- a/src/music/dmusic.cpp +++ b/src/music/dmusic.cpp @@ -430,7 +430,7 @@ bool DLSFile::ReadDLSWaveList(FILE *f, DWORD list_length) bool DLSFile::LoadFile(const wchar_t *file) { - DEBUG(driver, 2, "DMusic: Try to load DLS file %s", FS2OTTD(file)); + DEBUG(driver, 2, "DMusic: Try to load DLS file %s", FS2OTTD(file).c_str()); FILE *f = _wfopen(file, L"rb"); if (f == nullptr) return false; @@ -881,7 +881,7 @@ static const char *LoadDefaultDLSFile(const char *user_dls) if (!dls_file.LoadFile(path)) return "Can't load GM DLS collection"; } } else { - if (!dls_file.LoadFile(OTTD2FS(user_dls))) return "Can't load GM DLS collection"; + if (!dls_file.LoadFile(OTTD2FS(user_dls).c_str())) return "Can't load GM DLS collection"; } /* Get download port and allocate download IDs. */ diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index 2e00b5b193..a45bd49142 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -246,7 +246,7 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, SocketList * if (e != 0) { if (func != ResolveLoopProc) { DEBUG(net, 0, "getaddrinfo for hostname \"%s\", port %s, address family %s and socket type %s failed: %s", - this->hostname, port_name, AddressFamilyAsString(family), SocketTypeAsString(socktype), FS2OTTD(gai_strerror(e))); + this->hostname, port_name, AddressFamilyAsString(family), SocketTypeAsString(socktype), FS2OTTD(gai_strerror(e)).c_str()); } return INVALID_SOCKET; } diff --git a/src/os/os2/os2.cpp b/src/os/os2/os2.cpp index f1128b0c61..009a3e0ede 100644 --- a/src/os/os2/os2.cpp +++ b/src/os/os2/os2.cpp @@ -203,9 +203,6 @@ bool GetClipboardContents(char *buffer, const char *last) } -const char *FS2OTTD(const char *name) {return name;} -const char *OTTD2FS(const char *name) {return name;} - void OSOpenBrowser(const char *url) { // stub only diff --git a/src/os/unix/unix.cpp b/src/os/unix/unix.cpp index 9ef2bc386d..57edf1d38e 100644 --- a/src/os/unix/unix.cpp +++ b/src/os/unix/unix.cpp @@ -146,9 +146,8 @@ static const char *GetLocalCode() * Convert between locales, which from and which to is set in the calling * functions OTTD2FS() and FS2OTTD(). */ -static const char *convert_tofrom_fs(iconv_t convd, const char *name) +static const char *convert_tofrom_fs(iconv_t convd, const char *name, char *outbuf, size_t outlen) { - static char buf[1024]; /* There are different implementations of iconv. The older ones, * e.g. SUSv2, pass a const pointer, whereas the newer ones, e.g. * IEEE 1003.1 (2004), pass a non-const pointer. */ @@ -158,9 +157,8 @@ static const char *convert_tofrom_fs(iconv_t convd, const char *name) const char *inbuf = name; #endif - char *outbuf = buf; - size_t outlen = sizeof(buf) - 1; size_t inlen = strlen(name); + char *buf = outbuf; strecpy(outbuf, name, outbuf + outlen); @@ -179,9 +177,10 @@ static const char *convert_tofrom_fs(iconv_t convd, const char *name) * @param name pointer to a valid string that will be converted * @return pointer to a new stringbuffer that contains the converted string */ -const char *OTTD2FS(const char *name) +std::string OTTD2FS(const std::string &name) { static iconv_t convd = (iconv_t)(-1); + char buf[1024] = {}; if (convd == (iconv_t)(-1)) { const char *env = GetLocalCode(); @@ -192,17 +191,18 @@ const char *OTTD2FS(const char *name) } } - return convert_tofrom_fs(convd, name); + return convert_tofrom_fs(convd, name.c_str(), buf, lengthof(buf)); } /** * Convert to OpenTTD's encoding from that of the local environment - * @param name pointer to a valid string that will be converted + * @param name valid string that will be converted * @return pointer to a new stringbuffer that contains the converted string */ -const char *FS2OTTD(const char *name) +std::string FS2OTTD(const std::string &name) { static iconv_t convd = (iconv_t)(-1); + char buf[1024] = {}; if (convd == (iconv_t)(-1)) { const char *env = GetLocalCode(); @@ -213,12 +213,9 @@ const char *FS2OTTD(const char *name) } } - return convert_tofrom_fs(convd, name); + return convert_tofrom_fs(convd, name.c_str(), buf, lengthof(buf)); } -#else -const char *FS2OTTD(const char *name) {return name;} -const char *OTTD2FS(const char *name) {return name;} #endif /* WITH_ICONV */ void ShowInfo(const char *str) diff --git a/src/os/windows/crashlog_win.cpp b/src/os/windows/crashlog_win.cpp index 76a05eaa9e..9768bcc82e 100644 --- a/src/os/windows/crashlog_win.cpp +++ b/src/os/windows/crashlog_win.cpp @@ -189,7 +189,7 @@ static char *PrintModuleInfo(char *output, const char *last, HMODULE mod) GetModuleFileName(mod, buffer, MAX_PATH); GetFileInfo(&dfi, buffer); output += seprintf(output, last, " %-20s handle: %p size: %d crc: %.8X date: %d-%.2d-%.2d %.2d:%.2d:%.2d\n", - FS2OTTD(buffer), + FS2OTTD(buffer).c_str(), mod, dfi.size, dfi.crc32, @@ -501,7 +501,7 @@ char *CrashLogWindows::AppendDecodedStacktrace(char *buffer, const char *last) c MiniDumpWriteDump_t funcMiniDumpWriteDump = (MiniDumpWriteDump_t)GetProcAddress(dbghelp, "MiniDumpWriteDump"); if (funcMiniDumpWriteDump != nullptr) { seprintf(filename, filename_last, "%scrash.dmp", _personal_dir.c_str()); - HANDLE file = CreateFile(OTTD2FS(filename), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, 0); + HANDLE file = CreateFile(OTTD2FS(filename).c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, 0); HANDLE proc = GetCurrentProcess(); DWORD procid = GetCurrentProcessId(); MINIDUMP_EXCEPTION_INFORMATION mdei; @@ -689,7 +689,8 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA switch (msg) { case WM_INITDIALOG: { /* We need to put the crash-log in a separate buffer because the default - * buffer in OTTD2FS is not large enough (512 chars) */ + * buffer in MB_TO_WIDE is not large enough (512 chars) */ + wchar_t filenamebuf[MAX_PATH * 2]; wchar_t crash_msgW[lengthof(CrashLogWindows::current->crashlog)]; /* Convert unix -> dos newlines because the edit box only supports that properly :( */ const char *unix_nl = CrashLogWindows::current->crashlog; @@ -704,19 +705,23 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA /* Add path to crash.log and crash.dmp (if any) to the crash window text */ size_t len = wcslen(_crash_desc) + 2; - len += wcslen(OTTD2FS(CrashLogWindows::current->crashlog_filename)) + 2; - len += wcslen(OTTD2FS(CrashLogWindows::current->crashdump_filename)) + 2; - len += wcslen(OTTD2FS(CrashLogWindows::current->screenshot_filename)) + 1; + len += wcslen(convert_to_fs(CrashLogWindows::current->crashlog_filename, filenamebuf, lengthof(filenamebuf), false)) + 2; + len += wcslen(convert_to_fs(CrashLogWindows::current->crashdump_filename, filenamebuf, lengthof(filenamebuf), false)) + 2; + len += wcslen(convert_to_fs(CrashLogWindows::current->screenshot_filename, filenamebuf, lengthof(filenamebuf), false)) + 1; wchar_t *text = AllocaM(wchar_t, len); - _snwprintf(text, len, _crash_desc, OTTD2FS(CrashLogWindows::current->crashlog_filename)); - if (OTTD2FS(CrashLogWindows::current->crashdump_filename)[0] != L'\0') { - wcscat(text, L"\n"); - wcscat(text, OTTD2FS(CrashLogWindows::current->crashdump_filename)); + int printed = _snwprintf(text, len, _crash_desc, convert_to_fs(CrashLogWindows::current->crashlog_filename, filenamebuf, lengthof(filenamebuf), false)); + if (printed < 0 || (size_t)printed > len) { + MessageBox(wnd, L"Catastrophic failure trying to display crash message. Could not perform text formatting.", L"OpenTTD", MB_ICONERROR); + return FALSE; } - if (OTTD2FS(CrashLogWindows::current->screenshot_filename)[0] != L'\0') { + if (convert_to_fs(CrashLogWindows::current->crashdump_filename, filenamebuf, lengthof(filenamebuf), false)[0] != L'\0') { wcscat(text, L"\n"); - wcscat(text, OTTD2FS(CrashLogWindows::current->screenshot_filename)); + wcscat(text, filenamebuf); + } + if (convert_to_fs(CrashLogWindows::current->screenshot_filename, filenamebuf, lengthof(filenamebuf), false)[0] != L'\0') { + wcscat(text, L"\n"); + wcscat(text, filenamebuf); } SetDlgItemText(wnd, 10, text); @@ -730,18 +735,20 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA CrashLog::AfterCrashLogCleanup(); ExitProcess(2); case 13: // Emergency save + wchar_t filenamebuf[MAX_PATH * 2]; char filename[MAX_PATH]; if (CrashLogWindows::current->WriteSavegame(filename, lastof(filename))) { - size_t len = wcslen(_save_succeeded) + wcslen(OTTD2FS(filename)) + 1; + convert_to_fs(filename, filenamebuf, lengthof(filenamebuf), false); + size_t len = lengthof(_save_succeeded) + wcslen(filenamebuf) + 1; wchar_t *text = AllocaM(wchar_t, len); - _snwprintf(text, len, _save_succeeded, OTTD2FS(filename)); + _snwprintf(text, len, _save_succeeded, filenamebuf); MessageBox(wnd, text, L"Save successful", MB_ICONINFORMATION); } else { MessageBox(wnd, L"Save failed", L"Save failed", MB_ICONINFORMATION); } break; case 15: // Expand window to show crash-message - _expanded ^= 1; + _expanded = !_expanded; SetWndSize(wnd, _expanded); break; } diff --git a/src/os/windows/font_win32.cpp b/src/os/windows/font_win32.cpp index 9a9dba2f2e..1d923ddb21 100644 --- a/src/os/windows/font_win32.cpp +++ b/src/os/windows/font_win32.cpp @@ -83,7 +83,7 @@ FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) } /* Convert font name to file system encoding. */ - wchar_t *font_namep = wcsdup(OTTD2FS(font_name)); + wchar_t *font_namep = wcsdup(OTTD2FS(font_name).c_str()); for (index = 0;; index++) { wchar_t *s; @@ -377,6 +377,7 @@ Win32FontCache::Win32FontCache(FontSize fs, const LOGFONT &logfont, int pixels) { this->dc = CreateCompatibleDC(nullptr); this->SetFontSize(fs, pixels); + this->fontname = FS2OTTD(this->logfont.lfFaceName); } Win32FontCache::~Win32FontCache() @@ -438,7 +439,7 @@ void Win32FontCache::SetFontSize(FontSize fs, int pixels) this->glyph_size.cx = otm->otmTextMetrics.tmMaxCharWidth; this->glyph_size.cy = otm->otmTextMetrics.tmHeight; - DEBUG(freetype, 2, "Loaded font '%s' with size %d", FS2OTTD((LPTSTR)((BYTE *)otm + (ptrdiff_t)otm->otmpFullName)), pixels); + DEBUG(freetype, 2, "Loaded font '%s' with size %d", FS2OTTD((LPWSTR)((BYTE *)otm + (ptrdiff_t)otm->otmpFullName)).c_str(), pixels); } /** @@ -541,10 +542,10 @@ void Win32FontCache::ClearFontCache() /* Convert characters outside of the BMP into surrogate pairs. */ WCHAR chars[2]; if (key >= 0x010000U) { - chars[0] = (WCHAR)(((key - 0x010000U) >> 10) + 0xD800); - chars[1] = (WCHAR)(((key - 0x010000U) & 0x3FF) + 0xDC00); + chars[0] = (wchar_t)(((key - 0x010000U) >> 10) + 0xD800); + chars[1] = (wchar_t)(((key - 0x010000U) & 0x3FF) + 0xDC00); } else { - chars[0] = (WCHAR)(key & 0xFFFF); + chars[0] = (wchar_t)(key & 0xFFFF); } WORD glyphs[2] = { 0, 0 }; diff --git a/src/os/windows/font_win32.h b/src/os/windows/font_win32.h index ba413fae5e..6ab304c89c 100644 --- a/src/os/windows/font_win32.h +++ b/src/os/windows/font_win32.h @@ -21,6 +21,7 @@ private: HDC dc = nullptr; ///< Cached GDI device context. HGDIOBJ old_font; ///< Old font selected into the GDI context. SIZE glyph_size; ///< Maximum size of regular glyphs. + std::string fontname; ///< Cached copy of this->logfont.lfFaceName void SetFontSize(FontSize fs, int pixels); @@ -33,7 +34,7 @@ public: ~Win32FontCache(); void ClearFontCache() override; GlyphID MapCharToGlyph(WChar key) override; - const char *GetFontName() override { return FS2OTTD(this->logfont.lfFaceName); } + const char *GetFontName() override { return this->fontname.c_str(); } const void *GetOSHandle() override { return &this->logfont; } }; diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index cfe7d42d95..568876ab1e 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -57,7 +57,7 @@ bool LoadLibraryList(Function proc[], const char *dll) { while (*dll != '\0') { HMODULE lib; - lib = LoadLibrary(OTTD2FS(dll)); + lib = LoadLibrary(OTTD2FS(dll).c_str()); if (lib == nullptr) return false; for (;;) { @@ -77,12 +77,12 @@ bool LoadLibraryList(Function proc[], const char *dll) void ShowOSErrorBox(const char *buf, bool system) { MyShowCursor(true); - MessageBox(GetActiveWindow(), OTTD2FS(buf), L"Error!", MB_ICONSTOP | MB_TASKMODAL); + MessageBox(GetActiveWindow(), OTTD2FS(buf).c_str(), L"Error!", MB_ICONSTOP | MB_TASKMODAL); } void OSOpenBrowser(const char *url) { - ShellExecute(GetActiveWindow(), L"open", OTTD2FS(url), nullptr, nullptr, SW_SHOWNORMAL); + ShellExecute(GetActiveWindow(), L"open", OTTD2FS(url).c_str(), nullptr, nullptr, SW_SHOWNORMAL); } /* Code below for windows version of opendir/readdir/closedir copied and @@ -141,14 +141,14 @@ DIR *opendir(const wchar_t *path) if ((fa != INVALID_FILE_ATTRIBUTES) && (fa & FILE_ATTRIBUTE_DIRECTORY)) { d = dir_calloc(); if (d != nullptr) { - wchar_t search_path[MAX_PATH]; + std::wstring search_path = path; bool slash = path[wcslen(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"\\"); - *lastof(search_path) = '\0'; - d->hFind = FindFirstFile(search_path, &d->fd); + if (!slash) search_path += L"\\"; + search_path += L"*"; + d->hFind = FindFirstFile(search_path.c_str(), &d->fd); if (d->hFind != INVALID_HANDLE_VALUE || GetLastError() == ERROR_NO_MORE_FILES) { // the directory is empty @@ -246,7 +246,7 @@ bool FiosGetDiskFreeSpace(const char *path, uint64 *tot) UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS); // disable 'no-disk' message box ULARGE_INTEGER bytes_free; - bool retval = GetDiskFreeSpaceEx(OTTD2FS(path), &bytes_free, nullptr, nullptr); + bool retval = GetDiskFreeSpaceEx(OTTD2FS(path).c_str(), &bytes_free, nullptr, nullptr); if (retval) *tot = bytes_free.QuadPart; SetErrorMode(sem); // reset previous setting @@ -415,7 +415,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi /* Convert the command line to UTF-8. We need a dedicated buffer * for this because argv[] points into this buffer and this needs to * be available between subsequent calls to FS2OTTD(). */ - char *cmdline = stredup(FS2OTTD(GetCommandLine())); + char *cmdline = stredup(FS2OTTD(GetCommandLine()).c_str()); #if defined(_DEBUG) CreateConsole(); @@ -553,34 +553,40 @@ bool GetClipboardContents(char *buffer, const char *last) /** - * Convert to OpenTTD's encoding from wide characters. + * Convert to OpenTTD's encoding from a wide string. * 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 + * @param name valid string that will be converted (local, or wide) + * @return 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 wchar_t *name) +std::string FS2OTTD(const std::wstring &name) { - static char utf8_buf[512]; - return convert_from_fs(name, utf8_buf, lengthof(utf8_buf)); + int name_len = (name.length() >= INT_MAX) ? INT_MAX : (int)name.length(); + int len = WideCharToMultiByte(CP_UTF8, 0, name.c_str(), name_len, nullptr, 0, nullptr, nullptr); + if (len <= 0) return std::string(); + char *utf8_buf = AllocaM(char, len + 1); + utf8_buf[len] = '\0'; + WideCharToMultiByte(CP_UTF8, 0, name.c_str(), name_len, utf8_buf, len, nullptr, nullptr); + return std::string(utf8_buf, static_cast(len)); } /** - * Convert from OpenTTD's encoding to wide characters. + * Convert from OpenTTD's encoding to a wide string. * 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 (UTF8) + * @param name valid string that will be converted (UTF8) * @param console_cp convert to the console encoding instead of the normal system encoding. - * @return pointer to the converted string; if failed string is of zero-length + * @return converted string; if failed string is of zero-length */ -const wchar_t *OTTD2FS(const char *name, bool console_cp) +std::wstring OTTD2FS(const std::string &name, bool console_cp) { - static wchar_t system_buf[512]; - return convert_to_fs(name, system_buf, lengthof(system_buf), console_cp); + int name_len = (name.length() >= INT_MAX) ? INT_MAX : (int)name.length(); + int len = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), name_len, nullptr, 0); + if (len <= 0) return std::wstring(); + wchar_t *system_buf = AllocaM(wchar_t, len + 1); + system_buf[len] = L'\0'; + MultiByteToWideChar(CP_UTF8, 0, name.c_str(), name_len, system_buf, len); + return std::wstring(system_buf, static_cast(len)); } @@ -594,10 +600,8 @@ const wchar_t *OTTD2FS(const char *name, bool console_cp) */ char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen) { - const wchar_t *wide_buf = name; - /* Convert UTF-16 string to UTF-8. */ - int len = WideCharToMultiByte(CP_UTF8, 0, wide_buf, -1, utf8_buf, (int)buflen, nullptr, nullptr); + int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, utf8_buf, (int)buflen, nullptr, nullptr); if (len == 0) utf8_buf[0] = '\0'; return utf8_buf; diff --git a/src/stdafx.h b/src/stdafx.h index 42a6106e8a..06860f1045 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -93,6 +93,7 @@ #include #include #include +#include #ifndef SIZE_MAX # define SIZE_MAX ((size_t)-1) @@ -252,25 +253,26 @@ #endif /* defined(_MSC_VER) */ -/* NOTE: the string returned by these functions is only valid until the next - * call to the same function and is not thread- or reentrancy-safe */ #if !defined(STRGEN) && !defined(SETTINGSGEN) # if defined(_WIN32) char *getcwd(char *buf, size_t size); -# include # include +# include - namespace std { using ::_wfopen; } -# define fopen(file, mode) _wfopen(OTTD2FS(file), _T(mode)) -# define unlink(file) _wunlink(OTTD2FS(file)) +# define fopen(file, mode) _wfopen(OTTD2FS(file).c_str(), _T(mode)) +# define unlink(file) _wunlink(OTTD2FS(file).c_str()) - const char *FS2OTTD(const wchar_t *name); - const wchar_t *OTTD2FS(const char *name, bool console_cp = false); + std::string FS2OTTD(const std::wstring &name); + std::wstring OTTD2FS(const std::string &name, bool console_cp = false); +# elif defined(WITH_ICONV) +# define fopen(file, mode) fopen(OTTD2FS(file).c_str(), mode) + std::string FS2OTTD(const std::string &name); + std::string OTTD2FS(const std::string &name); # else -# define fopen(file, mode) fopen(OTTD2FS(file), mode) - const char *FS2OTTD(const char *name); - const char *OTTD2FS(const char *name); -# endif /* _WIN32 */ + // no override of fopen() since no transformation is required of the filename + template std::string FS2OTTD(T name) { return name; } + template std::string OTTD2FS(T name) { return name; } +# endif /* _WIN32 or WITH_ICONV */ #endif /* STRGEN || SETTINGSGEN */ #if defined(_WIN32) || defined(__OS2__) && !defined(__INNOTEK_LIBC__) diff --git a/src/strings.cpp b/src/strings.cpp index 08e826141c..7cbdc3cb09 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -1910,14 +1910,14 @@ static void GetLanguageList(const char *path) if (dir != nullptr) { struct dirent *dirent; while ((dirent = readdir(dir)) != nullptr) { - const char *d_name = FS2OTTD(dirent->d_name); - const char *extension = strrchr(d_name, '.'); + std::string d_name = FS2OTTD(dirent->d_name); + const char *extension = strrchr(d_name.c_str(), '.'); /* Not a language file */ if (extension == nullptr || strcmp(extension, ".lng") != 0) continue; LanguageMetadata lmd; - seprintf(lmd.file, lastof(lmd.file), "%s%s", path, d_name); + seprintf(lmd.file, lastof(lmd.file), "%s%s", path, d_name.c_str()); /* Check whether the file is of the correct version */ if (!GetLanguageFileHeader(lmd.file, &lmd)) { diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 1d9cd3e2bf..1b3476dab9 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -214,7 +214,7 @@ bool VideoDriver_Win32Base::MakeWindow(bool full_screen, bool resize) char window_title[64]; seprintf(window_title, lastof(window_title), "OpenTTD %s", _openttd_revision); - this->main_wnd = CreateWindow(L"OTTD", OTTD2FS(window_title), style, x, y, w, h, 0, 0, GetModuleHandle(nullptr), this); + this->main_wnd = CreateWindow(L"OTTD", OTTD2FS(window_title).c_str(), style, x, y, w, h, 0, 0, GetModuleHandle(nullptr), this); if (this->main_wnd == nullptr) usererror("CreateWindow failed"); ShowWindow(this->main_wnd, showstyle); } @@ -331,7 +331,7 @@ static LRESULT HandleIMEComposition(HWND hwnd, WPARAM wParam, LPARAM lParam) /* Transmit text to windowing system. */ if (len > 0) { HandleTextInput(nullptr, true); // Clear marked string. - HandleTextInput(FS2OTTD(str)); + HandleTextInput(FS2OTTD(str).c_str()); } SetCompositionPos(hwnd); From 746f1ca11a18af97e4fed06e5ac1af622bf21d35 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Fri, 2 Apr 2021 18:35:00 +0200 Subject: [PATCH 02/31] Codechange: Remove the now meaningless console_cp parameter from OTTD2FS --- src/debug.cpp | 2 +- src/os/windows/crashlog_win.cpp | 14 +++++++------- src/os/windows/font_win32.cpp | 6 +++--- src/os/windows/win32.cpp | 4 ++-- src/os/windows/win32.h | 2 +- src/stdafx.h | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/debug.cpp b/src/debug.cpp index eb8dc5d4fa..25a0f1a82f 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -133,7 +133,7 @@ static void debug_print(const char *dbg, const char *buf) seprintf(buffer, lastof(buffer), "%sdbg: [%s] %s\n", GetLogPrefix(), dbg, buf); #if defined(_WIN32) wchar_t system_buf[512]; - convert_to_fs(buffer, system_buf, lengthof(system_buf), true); + convert_to_fs(buffer, system_buf, lengthof(system_buf)); fputws(system_buf, stderr); #else fputs(buffer, stderr); diff --git a/src/os/windows/crashlog_win.cpp b/src/os/windows/crashlog_win.cpp index 9768bcc82e..a7ff8e4110 100644 --- a/src/os/windows/crashlog_win.cpp +++ b/src/os/windows/crashlog_win.cpp @@ -705,21 +705,21 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA /* Add path to crash.log and crash.dmp (if any) to the crash window text */ size_t len = wcslen(_crash_desc) + 2; - len += wcslen(convert_to_fs(CrashLogWindows::current->crashlog_filename, filenamebuf, lengthof(filenamebuf), false)) + 2; - len += wcslen(convert_to_fs(CrashLogWindows::current->crashdump_filename, filenamebuf, lengthof(filenamebuf), false)) + 2; - len += wcslen(convert_to_fs(CrashLogWindows::current->screenshot_filename, filenamebuf, lengthof(filenamebuf), false)) + 1; + len += wcslen(convert_to_fs(CrashLogWindows::current->crashlog_filename, filenamebuf, lengthof(filenamebuf))) + 2; + len += wcslen(convert_to_fs(CrashLogWindows::current->crashdump_filename, filenamebuf, lengthof(filenamebuf))) + 2; + len += wcslen(convert_to_fs(CrashLogWindows::current->screenshot_filename, filenamebuf, lengthof(filenamebuf))) + 1; wchar_t *text = AllocaM(wchar_t, len); - int printed = _snwprintf(text, len, _crash_desc, convert_to_fs(CrashLogWindows::current->crashlog_filename, filenamebuf, lengthof(filenamebuf), false)); + int printed = _snwprintf(text, len, _crash_desc, convert_to_fs(CrashLogWindows::current->crashlog_filename, filenamebuf, lengthof(filenamebuf))); if (printed < 0 || (size_t)printed > len) { MessageBox(wnd, L"Catastrophic failure trying to display crash message. Could not perform text formatting.", L"OpenTTD", MB_ICONERROR); return FALSE; } - if (convert_to_fs(CrashLogWindows::current->crashdump_filename, filenamebuf, lengthof(filenamebuf), false)[0] != L'\0') { + if (convert_to_fs(CrashLogWindows::current->crashdump_filename, filenamebuf, lengthof(filenamebuf))[0] != L'\0') { wcscat(text, L"\n"); wcscat(text, filenamebuf); } - if (convert_to_fs(CrashLogWindows::current->screenshot_filename, filenamebuf, lengthof(filenamebuf), false)[0] != L'\0') { + if (convert_to_fs(CrashLogWindows::current->screenshot_filename, filenamebuf, lengthof(filenamebuf))[0] != L'\0') { wcscat(text, L"\n"); wcscat(text, filenamebuf); } @@ -738,7 +738,7 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA wchar_t filenamebuf[MAX_PATH * 2]; char filename[MAX_PATH]; if (CrashLogWindows::current->WriteSavegame(filename, lastof(filename))) { - convert_to_fs(filename, filenamebuf, lengthof(filenamebuf), false); + convert_to_fs(filename, filenamebuf, lengthof(filenamebuf)); size_t len = lengthof(_save_succeeded) + wcslen(filenamebuf) + 1; wchar_t *text = AllocaM(wchar_t, len); _snwprintf(text, len, _save_succeeded, filenamebuf); diff --git a/src/os/windows/font_win32.cpp b/src/os/windows/font_win32.cpp index 1d923ddb21..59d5e0ad85 100644 --- a/src/os/windows/font_win32.cpp +++ b/src/os/windows/font_win32.cpp @@ -606,12 +606,12 @@ void LoadWin32Font(FontSize fs) /* See if this is an absolute path. */ if (FileExists(settings->font)) { - convert_to_fs(settings->font, fontPath, lengthof(fontPath), false); + convert_to_fs(settings->font, fontPath, lengthof(fontPath)); } else { /* Scan the search-paths to see if it can be found. */ std::string full_font = FioFindFullPath(BASE_DIR, settings->font); if (!full_font.empty()) { - convert_to_fs(full_font.c_str(), fontPath, lengthof(fontPath), false); + convert_to_fs(full_font.c_str(), fontPath, lengthof(fontPath)); } } @@ -649,7 +649,7 @@ void LoadWin32Font(FontSize fs) if (logfont.lfFaceName[0] == 0) { logfont.lfWeight = strcasestr(settings->font, " bold") != nullptr ? FW_BOLD : FW_NORMAL; // Poor man's way to allow selecting bold fonts. - convert_to_fs(settings->font, logfont.lfFaceName, lengthof(logfont.lfFaceName), false); + convert_to_fs(settings->font, logfont.lfFaceName, lengthof(logfont.lfFaceName)); } HFONT font = CreateFontIndirect(&logfont); diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index 568876ab1e..3f72d1e723 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -578,7 +578,7 @@ std::string FS2OTTD(const std::wstring &name) * @param console_cp convert to the console encoding instead of the normal system encoding. * @return converted string; if failed string is of zero-length */ -std::wstring OTTD2FS(const std::string &name, bool console_cp) +std::wstring OTTD2FS(const std::string &name) { int name_len = (name.length() >= INT_MAX) ? INT_MAX : (int)name.length(); int len = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), name_len, nullptr, 0); @@ -618,7 +618,7 @@ char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen) * @param console_cp convert to the console encoding instead of the normal system encoding. * @return pointer to system_buf. If conversion fails the string is of zero-length */ -wchar_t *convert_to_fs(const char *name, wchar_t *system_buf, size_t buflen, bool console_cp) +wchar_t *convert_to_fs(const char *name, wchar_t *system_buf, size_t buflen) { int len = MultiByteToWideChar(CP_UTF8, 0, name, -1, system_buf, (int)buflen); if (len == 0) system_buf[0] = '\0'; diff --git a/src/os/windows/win32.h b/src/os/windows/win32.h index 60cbed6e97..095181c46c 100644 --- a/src/os/windows/win32.h +++ b/src/os/windows/win32.h @@ -17,7 +17,7 @@ typedef void (*Function)(int); bool LoadLibraryList(Function proc[], const char *dll); char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen); -wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen, bool console_cp = false); +wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen); #if defined(__MINGW32__) && !defined(__MINGW64__) #define SHGFP_TYPE_CURRENT 0 diff --git a/src/stdafx.h b/src/stdafx.h index 06860f1045..f13104a5b2 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -263,7 +263,7 @@ # define unlink(file) _wunlink(OTTD2FS(file).c_str()) std::string FS2OTTD(const std::wstring &name); - std::wstring OTTD2FS(const std::string &name, bool console_cp = false); + std::wstring OTTD2FS(const std::string &name); # elif defined(WITH_ICONV) # define fopen(file, mode) fopen(OTTD2FS(file).c_str(), mode) std::string FS2OTTD(const std::string &name); From 9725bd8dd057b499e6e79990be4e23ed31517c3c Mon Sep 17 00:00:00 2001 From: Ghislain Antony Vaillant Date: Mon, 5 Apr 2021 17:26:41 +0200 Subject: [PATCH 03/31] Fix: Use FluidSynth default soundfont --- src/music/fluidsynth.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/music/fluidsynth.cpp b/src/music/fluidsynth.cpp index 61686a441e..acbc4a47ea 100644 --- a/src/music/fluidsynth.cpp +++ b/src/music/fluidsynth.cpp @@ -77,12 +77,22 @@ const char *MusicDriver_FluidSynth::Start(const StringList ¶m) /* Load a SoundFont and reset presets (so that new instruments * get used from the SoundFont) */ if (!sfont_name) { - int i; sfont_id = FLUID_FAILED; - for (i = 0; default_sf[i]; i++) { - if (!fluid_is_soundfont(default_sf[i])) continue; - sfont_id = fluid_synth_sfload(_midi.synth, default_sf[i], 1); - if (sfont_id != FLUID_FAILED) break; + + /* Try loading the default soundfont registered with FluidSynth. */ + char *default_soundfont; + fluid_settings_dupstr(_midi.settings, "synth.default-soundfont", &default_soundfont); + if (fluid_is_soundfont(default_soundfont)) { + sfont_id = fluid_synth_sfload(_midi.synth, default_soundfont, 1); + } + + /* If no default soundfont found, try our own list. */ + if (sfont_id == FLUID_FAILED) { + for (int i = 0; default_sf[i]; i++) { + if (!fluid_is_soundfont(default_sf[i])) continue; + sfont_id = fluid_synth_sfload(_midi.synth, default_sf[i], 1); + if (sfont_id != FLUID_FAILED) break; + } } if (sfont_id == FLUID_FAILED) return "Could not open any sound font"; } else { From e7cf589868480022599f6935997ef45963fc3f5a Mon Sep 17 00:00:00 2001 From: Ghislain Antony Vaillant Date: Sun, 4 Apr 2021 21:07:10 +0200 Subject: [PATCH 04/31] Fix: Honor default soundfont for FluidSynth Debian now provides a default soundfont for FluidSynth via its alternatives system. In short, FluidSynth is configured to look for `/usr/share/sounds/sf3/default-GM.sf3` as its default soundfont, and each soundfront package (FluidR3, OPL-3, MuseScore...) may provide or override this symlink. By default, FluidSynth is installed on Debian with the `TimGM6mb` soundfont by default due to its limited size. See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=929185 for further details. --- src/music/fluidsynth.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/music/fluidsynth.cpp b/src/music/fluidsynth.cpp index acbc4a47ea..000432e1da 100644 --- a/src/music/fluidsynth.cpp +++ b/src/music/fluidsynth.cpp @@ -29,7 +29,15 @@ static FMusicDriver_FluidSynth iFMusicDriver_FluidSynth; /** List of sound fonts to try by default. */ static const char *default_sf[] = { - /* Debian/Ubuntu/OpenSUSE preferred */ + /* FluidSynth preferred */ + /* See: https://www.fluidsynth.org/api/settings_synth.html#settings_synth_default-soundfont */ + "/usr/share/soundfonts/default.sf2", + + /* Debian/Ubuntu preferred */ + /* See: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=929185 */ + "/usr/share/sounds/sf3/default-GM.sf3", + + /* OpenSUSE preferred */ "/usr/share/sounds/sf2/FluidR3_GM.sf2", /* RedHat/Fedora/Arch preferred */ From f306d65ea3985de4701d4a552b653757d0cb4858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Wed, 7 Apr 2021 12:43:17 +0200 Subject: [PATCH 05/31] Fix: [CMake] Use the right run-time library depending on vcpkg triplet (#8964) --- cmake/CompileFlags.cmake | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/cmake/CompileFlags.cmake b/cmake/CompileFlags.cmake index f4047b8396..86d336b595 100644 --- a/cmake/CompileFlags.cmake +++ b/cmake/CompileFlags.cmake @@ -4,20 +4,22 @@ # macro(compile_flags) if(MSVC) - # Switch to MT (static) instead of MD (dynamic) binary + if(VCPKG_TARGET_TRIPLET MATCHES "-static" AND NOT VCPKG_TARGET_TRIPLET MATCHES "-md") + # Switch to MT (static) instead of MD (dynamic) binary - # For MSVC two generators are available - # - a command line generator (Ninja) using CMAKE_BUILD_TYPE to specify the - # configuration of the build tree - # - an IDE generator (Visual Studio) using CMAKE_CONFIGURATION_TYPES to - # specify all configurations that will be available in the generated solution - list(APPEND MSVC_CONFIGS "${CMAKE_BUILD_TYPE}" "${CMAKE_CONFIGURATION_TYPES}") + # For MSVC two generators are available + # - a command line generator (Ninja) using CMAKE_BUILD_TYPE to specify the + # configuration of the build tree + # - an IDE generator (Visual Studio) using CMAKE_CONFIGURATION_TYPES to + # specify all configurations that will be available in the generated solution + list(APPEND MSVC_CONFIGS "${CMAKE_BUILD_TYPE}" "${CMAKE_CONFIGURATION_TYPES}") - # Set usage of static runtime for all configurations - foreach(MSVC_CONFIG ${MSVC_CONFIGS}) - string(TOUPPER "CMAKE_CXX_FLAGS_${MSVC_CONFIG}" MSVC_FLAGS) - string(REPLACE "/MD" "/MT" ${MSVC_FLAGS} "${${MSVC_FLAGS}}") - endforeach() + # Set usage of static runtime for all configurations + foreach(MSVC_CONFIG ${MSVC_CONFIGS}) + string(TOUPPER "CMAKE_CXX_FLAGS_${MSVC_CONFIG}" MSVC_FLAGS) + string(REPLACE "/MD" "/MT" ${MSVC_FLAGS} "${${MSVC_FLAGS}}") + endforeach() + endif() # "If /Zc:rvalueCast is specified, the compiler follows section 5.4 of the # C++11 standard". We need C++11 for the way we use threads. From 152940358469f060d0af68ecefb88293ac604aa0 Mon Sep 17 00:00:00 2001 From: translators Date: Wed, 7 Apr 2021 17:53:18 +0000 Subject: [PATCH 06/31] Update: Translations from eints norwegian (bokmal): 3 changes by Anolitt spanish (mexican): 3 changes by absay vietnamese: 3 changes by KhoiCanDev german: 3 changes by danidoedel finnish: 3 changes by hpiirai catalan: 3 changes by J0anJosep spanish: 3 changes by JohnBoyFan --- src/lang/catalan.txt | 3 +++ src/lang/finnish.txt | 3 +++ src/lang/german.txt | 3 +++ src/lang/norwegian_bokmal.txt | 3 +++ src/lang/spanish.txt | 3 +++ src/lang/spanish_MX.txt | 3 +++ src/lang/vietnamese.txt | 3 +++ 7 files changed, 21 insertions(+) diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index bd9166e6ea..f4d8021e19 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -1139,6 +1139,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Configur STR_CONFIG_SETTING_FILTER_TITLE :{G=Femenin}{BLACK}Cadena de filtrat: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Desplega-ho tot STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Plega-ho tot +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Restableix tots els valors STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(cap explicació disponible) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Valor per defecte: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Tipus de paràmetre: {ORANGE}{STRING} @@ -1147,6 +1148,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Paràmetre de l STR_CONFIG_SETTING_TYPE_GAME_INGAME :Paràmetre de la partida (emmagatzemat a la partida actual; només afecta la partida actual) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Paràmetre de la companyia (emmagatzemat a les partides; només afectarà les partides noves) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Paràmetre de la companyia (emmagatzemat a la partida actual; només afecta la companyia actual) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Avís! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Aquesta acció restablirà la configuració de la partida als seus valors per defecte.{}Esteu segur que voleu fer-ho? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Categoria: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Tipus: diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index dd239bce20..e457ea9fe8 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -1138,6 +1138,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Asetukse STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Suodatinteksti: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Avaa kaikki STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Sulje kaikki +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Palauta oletukset STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(selitystä ei saatavilla) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Oletusarvo: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Asetuksen tyyppi: {ORANGE}{STRING} @@ -1146,6 +1147,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Pelin asetus (t STR_CONFIG_SETTING_TYPE_GAME_INGAME :Pelin asetus (tallennetaan tallenteeseen; vaikuttaa vain nykyiseen peliin) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Yhtiön asetus (tallennetaan tallenteisiin; vaikuttaa vain uusiin peleihin) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Yhtiön asetus (tallennetaan tallennukseen; vaikuttaa vain nykyiseen yhtiöön) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Varoitus! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Tämä toiminto palauttaa pelin kaikki asetukset oletusarvoihinsa.{}Haluatko varmasti jatkaa? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Kategoria: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Tyyppi: diff --git a/src/lang/german.txt b/src/lang/german.txt index b7df032f08..ea971e99ee 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -1139,6 +1139,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Einstell STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Suchtext: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Alles ausklappen STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Alles einklappen +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Alle Werte zurücksetzen STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(keine Erklärung verfügbar) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Standardwert: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Art der Einstellung: {ORANGE}{STRING} @@ -1147,6 +1148,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Karten-Einstell STR_CONFIG_SETTING_TYPE_GAME_INGAME :Karten-Einstellung (im Spielstand gespeichert; beeinflusst nur aktuelles Spiel) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Firmen-Einstellung (in Spielständen gespeichert; beeinflusst nur neue Spiele) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Firmen-Einstellung (im Spielstand gespeichert; beeinflusst nur aktuelle Firma) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Achtung! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Diese Aktion setzt alle Spieleinstellungen auf ihre Standardwerte zurück.{}Sind Sie sicher, dass Sie fortfahren möchten? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Kategorie: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Art: diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index 1e1e00695e..93333cc2e5 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -1140,6 +1140,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Innstill STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Filtrer streng: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Vis alle STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Skjul alle +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Tilbakestill alle verdier STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(ingen forklaring tilgjengelig) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Standard verdi: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Instillings type: {ORANGE}{STRING} @@ -1148,6 +1149,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Selskapet innst STR_CONFIG_SETTING_TYPE_GAME_INGAME :Selskapet innstilling (lagret i lagringsfilen, påvirker bare gjeldende spill) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Selskapet innstilling (lagret i lagringsfilen, påvirker bare nye spill) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Selskapet innstilling (lagret i lagringsfilen, påvirker bare gjeldende selskap) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Advarsel! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Denne handlingen vil tilbakestille alle spillinnstillingene til standard verdier.{}Er du sikker på at du vil fortsette? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Kategori: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Type: diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index 6b77d1f2a1..e4c02a2ef0 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -1139,6 +1139,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Configur STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Patrón de filtrado: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Expandir todos STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Colapsar todos +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Restablecer valores STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(no hay explicación disponible) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Valor por defecto: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Tipo de opción: {ORANGE}{STRING} @@ -1147,6 +1148,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Opción de part STR_CONFIG_SETTING_TYPE_GAME_INGAME :Opción de partida (almacenada en la partida guardada, afecta solamente a la partida actual) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Opción de empresa (se almacena en las partidas guardadas, afecta solamente a las nuevas partidas) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Opción de empresa (almacenada en la partida guardada, afecta solamente a la empresa actual) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :¡Advertencia! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Esta acción restablecerá todos los ajustes del juego a sus valores por defecto.{}¿Deseas proceder? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Categoría: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Tipo: diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index b2be26e6be..b3cada6dbd 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -1139,6 +1139,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Configur STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Filtrar texto: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Desplegar todo STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Plegar todo +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Restablecer todos los ajustes STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(sin explicación disponible) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Valor por defecto: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Tipo de opción: {ORANGE}{STRING} @@ -1147,6 +1148,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Opción de part STR_CONFIG_SETTING_TYPE_GAME_INGAME :Opción de partida (almacenada en la partida guardada, afecta solamente la partida actual) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Opción de empresa (se almacena en las partidas guardadas, afecta solamente las partidas nuevas) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Opción de empresa (almacenada en la partida guardada, afecta solamente la empresa actual) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}¡Advertencia! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Esta acción restablecerá todos los ajustes del juego a sus valores originales.{}¿Deseas proceder? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Categoría: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Tipo: diff --git a/src/lang/vietnamese.txt b/src/lang/vietnamese.txt index 6fd16d0cb7..4b51cb67a9 100644 --- a/src/lang/vietnamese.txt +++ b/src/lang/vietnamese.txt @@ -1138,6 +1138,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Thiết STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Lọc chuỗi: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Mở xuống tất cả STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Đóng lại tất cả +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Thiết lập lại tất cả STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(hiện không có giải thích nào) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Giá trị mặc định: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Kiểu thiết lập: {ORANGE}{STRING} @@ -1146,6 +1147,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Thiết lập t STR_CONFIG_SETTING_TYPE_GAME_INGAME :Thiết lập trò chơi (chứa trong save; chỉ tác động tới ván chơi hiện tại) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Thiết lập công ty (chứa trong save; chỉ tác động tới các ván chơi mới) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Thiết lập công ty (chứa trong save; chỉ tác động tới công ty hiện tại) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Chú Ý! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Hành động này sẽ thiết lập lại tất cả các thông số về ban đầu.{}Bạn có muốn tiến hành? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Phân loại: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Kiểu: From ae94b2d29695d46813e93d26e05abb436f2bf396 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 5 Apr 2021 12:13:56 +0100 Subject: [PATCH 07/31] Fix: Viewport drag tooltip flickering when dragging outside window --- src/misc_gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 9d0259b3be..65f98b3653 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -782,7 +782,7 @@ void GuiShowTooltips(Window *parent, StringID str, uint paramcount, const uint64 { DeleteWindowById(WC_TOOLTIPS, 0); - if (str == STR_NULL) return; + if (str == STR_NULL || !_cursor.in_window) return; new TooltipsWindow(parent, str, paramcount, params, close_tooltip); } From 3ede756d23b09f52a8099736d9a78abc966448b8 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 5 Apr 2021 12:30:58 +0100 Subject: [PATCH 08/31] Fix: Viewport drag tooltips not being removed when dragging over other windows --- src/misc_gui.cpp | 6 ++++++ src/viewport.cpp | 2 +- src/window_gui.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 65f98b3653..2f538f2af9 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -766,6 +766,12 @@ struct TooltipsWindow : public Window case TCC_RIGHT_CLICK: if (!_right_button_down) delete this; break; case TCC_HOVER: if (!_mouse_hovering) delete this; break; case TCC_NONE: break; + + case TCC_EXIT_VIEWPORT: { + Window *w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y); + if (w == nullptr || IsPtInWindowViewport(w, _cursor.pos.x, _cursor.pos.y) == nullptr) delete this; + break; + } } } }; diff --git a/src/viewport.cpp b/src/viewport.cpp index 2a3f9b32de..aae659d53d 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -2637,7 +2637,7 @@ void UpdateTileSelection() * @param params (optional) up to 5 pieces of additional information that may be added to a tooltip * @param close_cond Condition for closing this tooltip. */ -static inline void ShowMeasurementTooltips(StringID str, uint paramcount, const uint64 params[], TooltipCloseCondition close_cond = TCC_NONE) +static inline void ShowMeasurementTooltips(StringID str, uint paramcount, const uint64 params[], TooltipCloseCondition close_cond = TCC_EXIT_VIEWPORT) { if (!_settings_client.gui.measure_tooltip) return; GuiShowTooltips(_thd.GetCallbackWnd(), str, paramcount, params, close_cond); diff --git a/src/window_gui.h b/src/window_gui.h index c792a6b28c..aca7f4486c 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -268,6 +268,7 @@ enum TooltipCloseCondition { TCC_RIGHT_CLICK, TCC_HOVER, TCC_NONE, + TCC_EXIT_VIEWPORT, }; /** From 2b86d42ddc9bfd6aef2856ec953cb03eefe6cd12 Mon Sep 17 00:00:00 2001 From: translators Date: Thu, 8 Apr 2021 17:53:09 +0000 Subject: [PATCH 09/31] Update: Translations from eints english (us): 3 changes by 2TallTyler korean: 3 changes by telk5093 russian: 32 changes by Ln-Wolf spanish: 1 change by JohnBoyFan french: 4 changes by arikover portuguese: 10 changes by azulcosta --- src/lang/english_US.txt | 3 +++ src/lang/french.txt | 5 ++++- src/lang/korean.txt | 3 +++ src/lang/portuguese.txt | 17 ++++++++++------- src/lang/russian.txt | 35 ++++++++++++++++++++++++++++++++--- src/lang/spanish.txt | 2 +- 6 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index 33c67d54e2..4a3eb6abb8 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -1138,6 +1138,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Settings STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Filter string: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Expand all STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Collapse all +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Reset all values STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(no explanation available) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Default value: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Setting type: {ORANGE}{STRING} @@ -1146,6 +1147,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Game setting (s STR_CONFIG_SETTING_TYPE_GAME_INGAME :Game setting (stored in save; affects only current game) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Company setting (stored in saves; affects only new games) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Company setting (stored in save; affects only current company) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Caution! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}This action will reset all game settings to their default values.{}Are you sure you want to proceed? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Category: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Type: diff --git a/src/lang/french.txt b/src/lang/french.txt index 20e1104d81..09a7f38e55 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -1139,6 +1139,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Paramèt STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Filtre{NBSP}: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Tout développer STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Tout réduire +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Réinitialiser tous les réglages STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(pas d'explication disponible) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Valeur par défaut{NBSP}: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Type de paramètre{NBSP}: {ORANGE}{STRING} @@ -1147,6 +1148,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Paramètre de j STR_CONFIG_SETTING_TYPE_GAME_INGAME :Paramètre de jeu (enregistré dans la sauvegarde{NBSP}; affecte uniquement la partie actuelle) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Paramètre de compagnie (enregistré dans les sauvegardes{NBSP}; affecte uniquement les nouvelles parties) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Paramètre de compagnie (enregistré dans la sauvegarde{NBSP}; affecte uniquement la compagnie actuelle) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Attention{NBSP}! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Par cette action, toues les réglages seront réinitialisés aux valeurs par défaut.{}Êtes-vous sûr de vouloir continuer{NBSP}? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Catégorie{NBSP}: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Type{NBSP}: @@ -2532,7 +2535,7 @@ STR_WATERWAYS_TOOLBAR_BUILD_DOCK_TOOLTIP :{BLACK}Construi STR_WATERWAYS_TOOLBAR_BUOY_TOOLTIP :{BLACK}Placer une bouée pouvant servir de guide aux navires.{}Shift pour afficher seulement le coût estimé. STR_WATERWAYS_TOOLBAR_BUILD_AQUEDUCT_TOOLTIP :{BLACK}Construire un aqueduc.{}Shift pour afficher seulement le coût estimé. STR_WATERWAYS_TOOLBAR_CREATE_LAKE_TOOLTIP :{BLACK}Définir une zone d'eau.{}Construire un canal, sauf si Ctrl est enfoncé au niveau de la mer{NBSP}: dans ce cas, le voisinage sera inondé. -STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Placer des rivières +STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Placer des rivières. Presser Ctrl pour sélectionner en diagonale # Ship depot construction window STR_DEPOT_BUILD_SHIP_CAPTION :{WHITE}Orientation du dépôt diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 798f2fbb52..47ccfc9028 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -1139,6 +1139,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}설정 STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}검색할 문자열: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}모두 펼치기 STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}모두 접기 +STR_CONFIG_SETTING_RESET_ALL :{BLACK}모든 설정 초기화 STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(설명이 존재하지 않습니다) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}기본값: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}설정 종류: {ORANGE}{STRING} @@ -1147,6 +1148,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :게임 설정 ( STR_CONFIG_SETTING_TYPE_GAME_INGAME :게임 설정 (게임 저장 파일에 저장됨; 현재 게임에만 적용됨) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :회사 설정 (게임 저장 파일에 저장됨; 새 게임에만 적용됨) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :회사 설정 (게임 저장 파일에 저장됨; 현재 회사에만 적용됨) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}경고! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}게임의 모든 설정을 기본값으로 되돌립니다.{}정말 모든 설정을 초기화하시겠습니까? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}분류: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}종류: diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 203cd9327d..f98ef16211 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -1139,6 +1139,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Definiç STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Filtrar frase: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Expandir todas STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Colapsar todas +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Repor todos os valores STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(sem explicação disponível) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Valor por omissão: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Tipo de configuração: {ORANGE}{STRING} @@ -1147,6 +1148,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Configuração STR_CONFIG_SETTING_TYPE_GAME_INGAME :Configuração de jogo (guardado; afeta apenas o jogo atual) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Configurações de empresa (guardado; afeta apenas novos jogos) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Configurações de empresa (guardado; afeta apenas a empresa atual) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Cuidado! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Esta ação vai repor todas as configurações do jogo para os seus valores padrão.{}Tem a certeza que deseja continuar? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Categoria: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Tipo: @@ -1904,11 +1907,11 @@ STR_LIVERY_SECONDARY_TOOLTIP :{BLACK}Seleccio STR_LIVERY_PANEL_TOOLTIP :{BLACK}Seleccione o esquema de cores a alterar, ou esquemas múltiplos utilizando a tecla Ctrl com o botão esquerdo do rato. Marque a caixa para comutar a utilização do esquema de cores STR_LIVERY_DEFAULT :Estampagem Padrão -STR_LIVERY_STEAM :Motor a Vapor -STR_LIVERY_DIESEL :Motor Diesel -STR_LIVERY_ELECTRIC :Motor Eléctrico -STR_LIVERY_MONORAIL :Motor Monocarril -STR_LIVERY_MAGLEV :Motor Maglev (Levitação Magnética) +STR_LIVERY_STEAM :Locomotivas a Vapor +STR_LIVERY_DIESEL :Locomotivas Diesel +STR_LIVERY_ELECTRIC :Locomotivas Eléctricas +STR_LIVERY_MONORAIL :Motoras Monocarril +STR_LIVERY_MAGLEV :Motoras Maglev (Levitação Magnética) STR_LIVERY_DMU :DMU STR_LIVERY_EMU :EMU STR_LIVERY_PASSENGER_WAGON_STEAM :Carruagem de Passageiros (Vapor) @@ -1917,8 +1920,8 @@ STR_LIVERY_PASSENGER_WAGON_ELECTRIC :Carruagem de Pa STR_LIVERY_PASSENGER_WAGON_MONORAIL :Carruagem de Passageiros (Monocarril) STR_LIVERY_PASSENGER_WAGON_MAGLEV :Carruagem de Passageiros (Maglev) STR_LIVERY_FREIGHT_WAGON :Vagão de Carga -STR_LIVERY_BUS :Autocarro -STR_LIVERY_TRUCK :Veículo de Mercadorias +STR_LIVERY_BUS :Autocarros +STR_LIVERY_TRUCK :Camiões STR_LIVERY_PASSENGER_SHIP :Navio de passageiros STR_LIVERY_FREIGHT_SHIP :Navio cargueiro STR_LIVERY_HELICOPTER :Helicóptero diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 5d5f88da6a..1a67358636 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -1263,7 +1263,7 @@ STR_DISASTER_NONE :нет STR_DISASTER_REDUCED :сниженная STR_DISASTER_NORMAL :обычная -STR_SUBSIDY_X1_5 :x1.5 +STR_SUBSIDY_X1_5 :x1,5 STR_SUBSIDY_X2 :x2 STR_SUBSIDY_X3 :x3 STR_SUBSIDY_X4 :x4 @@ -1273,6 +1273,8 @@ STR_TERRAIN_TYPE_FLAT :Равнинн STR_TERRAIN_TYPE_HILLY :Холмистый STR_TERRAIN_TYPE_MOUNTAINOUS :Преимущественно горный STR_TERRAIN_TYPE_ALPINIST :Исключительно горный +STR_TERRAIN_TYPE_CUSTOM :Установить высоту вручную +STR_TERRAIN_TYPE_CUSTOM_VALUE :Установленная высота ({NUM}) STR_CITY_APPROVAL_PERMISSIVE :дозволяющее STR_CITY_APPROVAL_TOLERANT :терпимое @@ -1285,6 +1287,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Расш STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Фильтр: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Развернуть всё STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Свернуть всё +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Сбросить все значения STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(нет описания) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Значение по умолчанию: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Тип настроек: {ORANGE}{STRING} @@ -1293,6 +1296,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Настрой STR_CONFIG_SETTING_TYPE_GAME_INGAME :Настройки игры (содержатся в файлах сохранений; действительны только для текущей игры) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Настройки компании (содержатся в файлах сохранений; действительны только для новых игр) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Настройки компании (содержатся в файлах сохранений; действительны только для текущей игры) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Внимание! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Вы уверены, что хотите сбросить все настройки игры к значениям по умолчанию? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Категория: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Тип: @@ -1356,6 +1361,10 @@ STR_CONFIG_SETTING_DISASTERS_HELPTEXT :Включен STR_CONFIG_SETTING_CITY_APPROVAL :Отношение городского совета к реструктуризации окрестностей: {STRING} STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :Выберите уровень влияния шума и загрязнения окружающей среды компаниями на их рейтинг в городах и возможность дальнейшего строительства около городов +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT :Максимальная высота объектов на карте: {STRING} +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_HELPTEXT :Установить максимальное значение высоты гор на карте. «(Автовыбор)» подберёт приемлемое значение после создания ландшафта. +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_VALUE :{NUM} +STR_CONFIG_SETTING_MAP_HEIGHT_LIMIT_AUTO :(автовыбор) STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}Невозможно изменить максимальную высоту. На карте есть горы выше этого значения. STR_CONFIG_SETTING_AUTOSLOPE :Разрешить изм. ландшафта под зданиями, дорогами и т. д. (автоспуски): {STRING} STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :Разрешить изменение ландшафта под домами и дорогами, не требуя их сноса @@ -1500,8 +1509,13 @@ STR_CONFIG_SETTING_INDUSTRY_DENSITY_HELPTEXT :Выберит STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Макс. расстояние от края карты до предприятий нефтяной индустрии: {STRING} STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Эта настройка ограничивает расстояние от края карты до нефтяных платформ и нефтеперерабатывающих заводов. Таким образом, на краях карты, оканчивающихся водой, они будут строиться у берега. На картах размером более 256 это значение будет соответственно увеличено. STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Высота снеговой линии: {STRING} -STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Укажите, на какой высоте в субарктическом климате устанавливается снеговой покров. Наличие снега влияет на расстановку предприятий и на условия роста городов. +STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Это значение определяет, на какой высоте в субарктическом климате устанавливается снеговой покров. Наличие снега влияет на расстановку предприятий и на условия роста городов.{}Значение может быть установлено только в редакторе сценариев; иначе оно рассчитывается в зависимости от значения «снежного покрытия». +STR_CONFIG_SETTING_SNOW_COVERAGE :Снежное покрытие: {STRING} +STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :Это значение определяет примерную относительную площадь суши, покрытой снегом в субарктическом климате.Наличие снега влияет на расстановку предприятий и на условия роста городов.{}Используется только при создании карты. Земля чуть выше уровня моря никогда не покрывается снегом. +STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}% +STR_CONFIG_SETTING_DESERT_COVERAGE :Песчаное покрытие: {STRING} STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :Укажите приблизительное количество пустыни на тропическом ландшафте. Пустыня также влияет на промышленное производство. Используется только во время создания карты +STR_CONFIG_SETTING_DESERT_COVERAGE_VALUE :{NUM}% STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :Грубость ландшафта: {STRING} STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(Только для TerraGenesis){}Выберите количество гор и холмов на карте. На гладком ландшафте холмов немного и они более пологие. На грубом - много гор, и ландшафт может показаться слишком однообразным. STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :Очень гладкий @@ -2691,7 +2705,7 @@ STR_WATERWAYS_TOOLBAR_BUILD_DOCK_TOOLTIP :{BLACK}Стро STR_WATERWAYS_TOOLBAR_BUOY_TOOLTIP :{BLACK}Буи помогают в навигации на больших расстояниях; используйте их как маршрутные точки. При нажатом Shift - оценка стоимости строительства. STR_WATERWAYS_TOOLBAR_BUILD_AQUEDUCT_TOOLTIP :{BLACK}Строительство акведуков. При нажатом Shift - оценка стоимости строительства. STR_WATERWAYS_TOOLBAR_CREATE_LAKE_TOOLTIP :{BLACK}Создать канал.{}При зажатом Ctrl клетка на уровне моря наполняется водой. -STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Разместить реки. +STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Создание рек на карте. При нажатом Ctrl они создаются по диагонали. # Ship depot construction window STR_DEPOT_BUILD_SHIP_CAPTION :{WHITE}Направление дока @@ -3066,6 +3080,17 @@ STR_MAPGEN_BY :{BLACK}× STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}Количество городов: STR_MAPGEN_DATE :{BLACK}Дата: STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}Кол-во предпр.: +STR_MAPGEN_HEIGHTMAP_HEIGHT :{BLACK}Высочайшая вершина: +STR_MAPGEN_HEIGHTMAP_HEIGHT_UP :{BLACK}Увеличить максимальную высоту гор на карте на 1 +STR_MAPGEN_HEIGHTMAP_HEIGHT_DOWN :{BLACK}Уменьшить максимальную высоту гор на карте на 1 +STR_MAPGEN_SNOW_COVERAGE :{BLACK}Снежное покрытие: +STR_MAPGEN_SNOW_COVERAGE_UP :{BLACK}Увеличить площадь снежного покрытия на 10% +STR_MAPGEN_SNOW_COVERAGE_DOWN :{BLACK}Уменьшить площадь снежного покрытия на 10% +STR_MAPGEN_SNOW_COVERAGE_TEXT :{BLACK}{NUM}% +STR_MAPGEN_DESERT_COVERAGE :{BLACK}Песчаное покрытие: +STR_MAPGEN_DESERT_COVERAGE_UP :{BLACK}Увеличить площадь песчаного покрытия на 10% +STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}Уменьшить площадь песчаного покрытия на 10% +STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}{NUM}% STR_MAPGEN_LAND_GENERATOR :{BLACK}Генератор ландшафта: STR_MAPGEN_TERRAIN_TYPE :{BLACK}Тип ландшафта: STR_MAPGEN_QUANTITY_OF_SEA_LAKES :{BLACK}Количество морей и озёр: @@ -3091,7 +3116,10 @@ STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Назв STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Размер: STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} × {NUM} +STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}Максимальная высота STR_MAPGEN_HEIGHTMAP_HEIGHT_QUERY_CAPT :{WHITE}Cамая высокая вершина +STR_MAPGEN_SNOW_COVERAGE_QUERY_CAPT :{WHITE}Снежное покрытие (в %) +STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT :{WHITE}Песчаное покрытие (в %) STR_MAPGEN_START_DATE_QUERY_CAPT :{WHITE}Изменить год начала игры # SE Map generation @@ -4520,6 +4548,7 @@ STR_WARNING_FALLBACK_SOUNDSET :{WHITE}Теку STR_WARNING_SCREENSHOT_SIZE_CAPTION :{WHITE}Огромный снимок экрана STR_WARNING_SCREENSHOT_SIZE_MESSAGE :{YELLOW}Снимок экрана будет иметь размер {COMMA}{NBSP}х{NBSP}{COMMA}{NBSP}пиксел{P ь я ей}. Его создание займёт некоторое время. Продолжить? +STR_MESSAGE_HEIGHTMAP_SUCCESSFULLY :{WHITE}Карта высот успешно сохранена под именем «{STRING}». Максимальная высота - {NUM}. STR_MESSAGE_SCREENSHOT_SUCCESSFULLY :{WHITE}Снимок экрана сохранён под именем «{STRING}» STR_ERROR_SCREENSHOT_FAILED :{WHITE}Не удалось сделать снимок экрана diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index e4c02a2ef0..b7dc758c3c 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -1148,7 +1148,7 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Opción de part STR_CONFIG_SETTING_TYPE_GAME_INGAME :Opción de partida (almacenada en la partida guardada, afecta solamente a la partida actual) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Opción de empresa (se almacena en las partidas guardadas, afecta solamente a las nuevas partidas) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Opción de empresa (almacenada en la partida guardada, afecta solamente a la empresa actual) -STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :¡Advertencia! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}¡Advertencia! STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Esta acción restablecerá todos los ajustes del juego a sus valores por defecto.{}¿Deseas proceder? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Categoría: From 5233fd275146ced3a0338d1740cef024be4063f5 Mon Sep 17 00:00:00 2001 From: Wim Leflere Date: Fri, 9 Apr 2021 11:22:03 +0200 Subject: [PATCH 10/31] Change: [win32] Use user UI language for initial language selection (#8973) (#8974) --- src/os/windows/win32.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp index 3f72d1e723..073f70b98c 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -629,9 +629,12 @@ wchar_t *convert_to_fs(const char *name, wchar_t *system_buf, size_t buflen) /** Determine the current user's locale. */ const char *GetCurrentLocale(const char *) { + const LANGID userUiLang = GetUserDefaultUILanguage(); + const LCID userUiLocale = MAKELCID(userUiLang, SORT_DEFAULT); + char lang[9], country[9]; - if (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, lang, lengthof(lang)) == 0 || - GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, country, lengthof(country)) == 0) { + if (GetLocaleInfoA(userUiLocale, LOCALE_SISO639LANGNAME, lang, lengthof(lang)) == 0 || + GetLocaleInfoA(userUiLocale, LOCALE_SISO3166CTRYNAME, country, lengthof(country)) == 0) { /* Unable to retrieve the locale. */ return nullptr; } From 49d370185bf2a5fe8c34a4087ee8e9763c2821c9 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Sun, 4 Apr 2021 09:51:48 +0200 Subject: [PATCH 11/31] Change: Default music and sound effects volume to be lower --- src/table/settings.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/table/settings.ini b/src/table/settings.ini index c4a6aeafc9..efbb3e0c78 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -3522,7 +3522,7 @@ cat = SC_BASIC var = music.music_vol type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -def = 127 +def = 50 min = 0 max = 127 interval = 1 @@ -3532,7 +3532,7 @@ cat = SC_BASIC var = music.effect_vol type = SLE_UINT8 flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC -def = 127 +def = 100 min = 0 max = 127 interval = 1 From 64c9af09914472c6a9eeb495cd790f7c325b194c Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Sun, 4 Apr 2021 10:34:37 +0200 Subject: [PATCH 12/31] Add: NWidgetBase::GetCurrentRect function --- src/widget_type.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/widget_type.h b/src/widget_type.h index c5083c6c5a..1692ef2266 100644 --- a/src/widget_type.h +++ b/src/widget_type.h @@ -158,6 +158,16 @@ public: virtual void Draw(const Window *w) = 0; virtual void SetDirty(const Window *w) const; + Rect GetCurrentRect() const + { + Rect r; + r.left = this->pos_x; + r.top = this->pos_y; + r.right = this->pos_x + this->current_x; + r.bottom = this->pos_y + this->current_y; + return r; + } + WidgetType type; ///< Type of the widget / nested widget. uint fill_x; ///< Horizontal fill stepsize (from initial size, \c 0 means not resizable). uint fill_y; ///< Vertical fill stepsize (from initial size, \c 0 means not resizable). From 88c92f7b7c51295f5a9cc8d1b837fbca03be37fb Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Sun, 4 Apr 2021 10:04:06 +0200 Subject: [PATCH 13/31] Codechange: Move volume control slider logic to separate functions --- src/music_gui.cpp | 44 ++++++------------------ src/settings_gui.cpp | 1 + src/widgets/CMakeLists.txt | 2 ++ src/widgets/slider.cpp | 70 ++++++++++++++++++++++++++++++++++++++ src/widgets/slider_func.h | 21 ++++++++++++ 5 files changed, 104 insertions(+), 34 deletions(-) create mode 100644 src/widgets/slider.cpp create mode 100644 src/widgets/slider_func.h diff --git a/src/music_gui.cpp b/src/music_gui.cpp index 7e2aaac1d6..469066706e 100644 --- a/src/music_gui.cpp +++ b/src/music_gui.cpp @@ -26,6 +26,7 @@ #include "settings_gui.h" #include "widgets/dropdown_func.h" #include "widgets/dropdown_type.h" +#include "widgets/slider_func.h" #include "widgets/music_widget.h" @@ -643,8 +644,6 @@ static void ShowMusicTrackSelection() } struct MusicWindow : public Window { - static const int slider_width = 3; - MusicWindow(WindowDesc *desc, WindowNumber number) : Window(desc) { this->InitNested(number); @@ -740,27 +739,13 @@ struct MusicWindow : public Window { break; } - case WID_M_MUSIC_VOL: case WID_M_EFFECT_VOL: { - /* Draw a wedge indicating low to high volume level. */ - const int ha = (r.bottom - r.top) / 5; - int wx1 = r.left, wx2 = r.right; - if (_current_text_dir == TD_RTL) std::swap(wx1, wx2); - const uint shadow = _colour_gradient[COLOUR_GREY][3]; - const uint fill = _colour_gradient[COLOUR_GREY][6]; - const uint light = _colour_gradient[COLOUR_GREY][7]; - const std::vector wedge{ Point{wx1, r.bottom - ha}, Point{wx2, r.top + ha}, Point{wx2, r.bottom - ha} }; - GfxFillPolygon(wedge, fill); - GfxDrawLine(wedge[0].x, wedge[0].y, wedge[2].x, wedge[2].y, light); - GfxDrawLine(wedge[1].x, wedge[1].y, wedge[2].x, wedge[2].y, _current_text_dir == TD_RTL ? shadow : light); - GfxDrawLine(wedge[0].x, wedge[0].y, wedge[1].x, wedge[1].y, shadow); - /* Draw a slider handle indicating current volume level. */ - const int sw = ScaleGUITrad(slider_width); - byte volume = (widget == WID_M_MUSIC_VOL) ? _settings_client.music.music_vol : _settings_client.music.effect_vol; - if (_current_text_dir == TD_RTL) volume = 127 - volume; - const int x = r.left + (volume * (r.right - r.left - sw) / 127); - DrawFrameRect(x, r.top, x + sw, r.bottom, COLOUR_GREY, FR_NONE); + case WID_M_MUSIC_VOL: + DrawVolumeSliderWidget(r, _settings_client.music.music_vol); + break; + + case WID_M_EFFECT_VOL: + DrawVolumeSliderWidget(r, _settings_client.music.effect_vol); break; - } } } @@ -801,18 +786,9 @@ struct MusicWindow : public Window { break; case WID_M_MUSIC_VOL: case WID_M_EFFECT_VOL: { // volume sliders - int x = pt.x - this->GetWidget(widget)->pos_x; - - byte *vol = (widget == WID_M_MUSIC_VOL) ? &_settings_client.music.music_vol : &_settings_client.music.effect_vol; - - byte new_vol = Clamp(x * 127 / (int)this->GetWidget(widget)->current_x, 0, 127); - if (_current_text_dir == TD_RTL) new_vol = 127 - new_vol; - /* Clamp to make sure min and max are properly settable */ - if (new_vol > 124) new_vol = 127; - if (new_vol < 3) new_vol = 0; - if (new_vol != *vol) { - *vol = new_vol; - if (widget == WID_M_MUSIC_VOL) MusicDriver::GetInstance()->SetVolume(new_vol); + byte &vol = (widget == WID_M_MUSIC_VOL) ? _settings_client.music.music_vol : _settings_client.music.effect_vol; + if (ClickVolumeSliderWidget(this->GetWidget(widget)->GetCurrentRect(), pt, vol)) { + if (widget == WID_M_MUSIC_VOL) MusicDriver::GetInstance()->SetVolume(vol); this->SetDirty(); } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 68587c46a7..513a3ef8f3 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -21,6 +21,7 @@ #include "string_func.h" #include "widgets/dropdown_type.h" #include "widgets/dropdown_func.h" +#include "widgets/slider_func.h" #include "highscore.h" #include "base_media_base.h" #include "company_base.h" diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt index 18ecd529e8..5586870a3a 100644 --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -44,6 +44,8 @@ add_files( screenshot_widget.h settings_widget.h sign_widget.h + slider.cpp + slider_func.h smallmap_widget.h station_widget.h statusbar_widget.h diff --git a/src/widgets/slider.cpp b/src/widgets/slider.cpp new file mode 100644 index 0000000000..6d6d732884 --- /dev/null +++ b/src/widgets/slider.cpp @@ -0,0 +1,70 @@ +/* + * 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 slider.cpp Implementation of the horizontal slider widget. */ + +#include "../stdafx.h" +#include "../window_gui.h" +#include "../window_func.h" +#include "../strings_func.h" +#include "../zoom_func.h" +#include "slider_func.h" + +#include "../safeguards.h" + + +/** + * Draw a volume slider widget with know at given value + * @param r Rectangle to draw the widget in + * @param value Value to put the slider at + */ +void DrawVolumeSliderWidget(Rect r, byte value) +{ + static const int slider_width = 3; + + /* Draw a wedge indicating low to high volume level. */ + const int ha = (r.bottom - r.top) / 5; + int wx1 = r.left, wx2 = r.right; + if (_current_text_dir == TD_RTL) std::swap(wx1, wx2); + const uint shadow = _colour_gradient[COLOUR_GREY][3]; + const uint fill = _colour_gradient[COLOUR_GREY][6]; + const uint light = _colour_gradient[COLOUR_GREY][7]; + const std::vector wedge{ Point{wx1, r.bottom - ha}, Point{wx2, r.top + ha}, Point{wx2, r.bottom - ha} }; + GfxFillPolygon(wedge, fill); + GfxDrawLine(wedge[0].x, wedge[0].y, wedge[2].x, wedge[2].y, light); + GfxDrawLine(wedge[1].x, wedge[1].y, wedge[2].x, wedge[2].y, _current_text_dir == TD_RTL ? shadow : light); + GfxDrawLine(wedge[0].x, wedge[0].y, wedge[1].x, wedge[1].y, shadow); + + /* Draw a slider handle indicating current volume level. */ + const int sw = ScaleGUITrad(slider_width); + if (_current_text_dir == TD_RTL) value = 127 - value; + const int x = r.left + (value * (r.right - r.left - sw) / 127); + DrawFrameRect(x, r.top, x + sw, r.bottom, COLOUR_GREY, FR_NONE); +} + +/** + * Handle click on a volume slider widget to change the value + * @param r Rectangle of the widget + * @param pt Clicked point + * @param value[in,out] Volume value to modify + * @return True if the volume setting was modified + */ +bool ClickVolumeSliderWidget(Rect r, Point pt, byte &value) +{ + byte new_vol = Clamp((pt.x - r.left) * 127 / (r.right - r.left), 0, 127); + if (_current_text_dir == TD_RTL) new_vol = 127 - new_vol; + + /* Clamp to make sure min and max are properly settable */ + if (new_vol > 124) new_vol = 127; + if (new_vol < 3) new_vol = 0; + if (new_vol != value) { + value = new_vol; + return true; + } + + return false; +} diff --git a/src/widgets/slider_func.h b/src/widgets/slider_func.h new file mode 100644 index 0000000000..1aa1fa10c6 --- /dev/null +++ b/src/widgets/slider_func.h @@ -0,0 +1,21 @@ +/* + * 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 slider_type.h Types related to the horizontal slider widget. */ + +#ifndef WIDGETS_SLIDER_TYPE_H +#define WIDGETS_SLIDER_TYPE_H + +#include "../window_type.h" +#include "../gfx_func.h" + + +void DrawVolumeSliderWidget(Rect r, byte value); +bool ClickVolumeSliderWidget(Rect r, Point pt, byte &value); + + +#endif /* WIDGETS_SLIDER_TYPE_H */ From 785e42a6f9d5d36b2bb98d2b941839ffc6de1fc5 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Sun, 4 Apr 2021 11:22:13 +0200 Subject: [PATCH 14/31] Feature: Volume sliders in Game Options window --- src/music_gui.cpp | 1 + src/settings_gui.cpp | 40 ++++++++++++++++++++++++++++++++--- src/widgets/settings_widget.h | 2 ++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/music_gui.cpp b/src/music_gui.cpp index 469066706e..28cb6ce4e1 100644 --- a/src/music_gui.cpp +++ b/src/music_gui.cpp @@ -790,6 +790,7 @@ struct MusicWindow : public Window { if (ClickVolumeSliderWidget(this->GetWidget(widget)->GetCurrentRect(), pt, vol)) { if (widget == WID_M_MUSIC_VOL) MusicDriver::GetInstance()->SetVolume(vol); this->SetDirty(); + SetWindowClassesDirty(WC_GAME_OPTIONS); } if (click_count > 0) this->mouse_capture_widget = widget; diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 513a3ef8f3..6788d1ae39 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -37,6 +37,7 @@ #include "fontcache.h" #include "zoom_func.h" #include "video/video_driver.hpp" +#include "music/music_driver.hpp" #include #include @@ -336,6 +337,14 @@ struct GameOptionsWindow : Window { SetDParamStr(0, BaseMusic::GetUsedSet()->GetDescription(GetCurrentLanguageIsoCode())); DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING); break; + + case WID_GO_BASE_SFX_VOLUME: + DrawVolumeSliderWidget(r, _settings_client.music.effect_vol); + break; + + case WID_GO_BASE_MUSIC_VOLUME: + DrawVolumeSliderWidget(r, _settings_client.music.music_vol); + break; } } @@ -388,6 +397,16 @@ struct GameOptionsWindow : Window { } break; + case WID_GO_BASE_SFX_VOLUME: + case WID_GO_BASE_MUSIC_VOLUME: + size->width = ScaleGUITrad(67); + size->height = ScaleGUITrad(12); + resize->width = 0; + resize->height = 0; + fill->width = 0; + fill->height = 0; + break; + default: { int selected; DropDownList list = this->BuildDropDownList(widget, &selected); @@ -442,6 +461,19 @@ struct GameOptionsWindow : Window { this->SetDirty(); break; + case WID_GO_BASE_SFX_VOLUME: + case WID_GO_BASE_MUSIC_VOLUME: { + byte &vol = (widget == WID_GO_BASE_MUSIC_VOLUME) ? _settings_client.music.music_vol : _settings_client.music.effect_vol; + if (ClickVolumeSliderWidget(this->GetWidget(widget)->GetCurrentRect(), pt, vol)) { + if (widget == WID_GO_BASE_MUSIC_VOLUME) MusicDriver::GetInstance()->SetVolume(vol); + this->SetDirty(); + SetWindowClassesDirty(WC_MUSIC_WINDOW); + } + + if (click_count > 0) this->mouse_capture_widget = widget; + break; + } + default: { int selected; DropDownList list = this->BuildDropDownList(widget, &selected); @@ -646,9 +678,10 @@ static const NWidgetPart _nested_game_options_widgets[] = { EndContainer(), NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_SFX, STR_NULL), SetPadding(0, 10, 0, 10), - NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0), + NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 7), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_SFX_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_SFX_TOOLTIP), - NWidget(NWID_SPACER), SetFill(1, 0), + NWidget(NWID_SPACER), SetMinimalSize(150, 12), SetFill(1, 0), + NWidget(WWT_EMPTY, COLOUR_GREY, WID_GO_BASE_SFX_VOLUME), SetMinimalSize(67, 12), SetMinimalTextLines(1, 0), SetDataTip(0x0, STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC), EndContainer(), NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_SFX_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 6, 0), NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7), @@ -659,9 +692,10 @@ static const NWidgetPart _nested_game_options_widgets[] = { EndContainer(), NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_MUSIC, STR_NULL), SetPadding(0, 10, 0, 10), - NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0), + NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 7), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_MUSIC_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP), NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0), + NWidget(WWT_EMPTY, COLOUR_GREY, WID_GO_BASE_MUSIC_VOLUME), SetMinimalSize(67, 12), SetMinimalTextLines(1, 0), SetDataTip(0x0, STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC), EndContainer(), NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 6, 0), NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(7, 0, 7), diff --git a/src/widgets/settings_widget.h b/src/widgets/settings_widget.h index 6cb2d7e949..ae9c22c1a8 100644 --- a/src/widgets/settings_widget.h +++ b/src/widgets/settings_widget.h @@ -25,9 +25,11 @@ enum GameOptionsWidgets { WID_GO_BASE_GRF_TEXTFILE, ///< Open base GRF readme, changelog (+1) or license (+2). WID_GO_BASE_GRF_DESCRIPTION = WID_GO_BASE_GRF_TEXTFILE + TFT_END, ///< Description of selected base GRF. WID_GO_BASE_SFX_DROPDOWN, ///< Use to select a base SFX. + WID_GO_BASE_SFX_VOLUME, ///< Change sound effects volume. WID_GO_BASE_SFX_TEXTFILE, ///< Open base SFX readme, changelog (+1) or license (+2). WID_GO_BASE_SFX_DESCRIPTION = WID_GO_BASE_SFX_TEXTFILE + TFT_END, ///< Description of selected base SFX. WID_GO_BASE_MUSIC_DROPDOWN, ///< Use to select a base music set. + WID_GO_BASE_MUSIC_VOLUME, ///< Change music volume. WID_GO_BASE_MUSIC_STATUS, ///< Info about corrupted files etc. WID_GO_BASE_MUSIC_TEXTFILE, ///< Open base music readme, changelog (+1) or license (+2). WID_GO_BASE_MUSIC_DESCRIPTION = WID_GO_BASE_MUSIC_TEXTFILE + TFT_END, ///< Description of selected base music set. From 96d33ab46a9244f8302a33e827c1b4ea1f3909e5 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Thu, 8 Apr 2021 23:16:43 +0200 Subject: [PATCH 15/31] Fix #8930: [Win32] Don't handle printable keys on keydown if an edit box is in focus. Handle printable input only when the matching WM_CHAR message is incoming. Without an edit box, do the handling in keydown as usual to support hotkeys. --- src/video/win32_v.cpp | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 1b3476dab9..b4d3946ea0 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -552,14 +552,6 @@ LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) uint scancode = GB(lParam, 16, 8); keycode = scancode == 41 ? (uint)WKC_BACKQUOTE : MapWindowsKey(wParam); - /* Silently drop all messages handled by WM_CHAR. */ - MSG msg; - if (PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE)) { - if ((msg.message == WM_CHAR || msg.message == WM_DEADCHAR) && GB(lParam, 16, 8) == GB(msg.lParam, 16, 8)) { - return 0; - } - } - uint charcode = MapVirtualKey(wParam, MAPVK_VK_TO_CHAR); /* No character translation? */ @@ -568,21 +560,26 @@ LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) return 0; } - /* Is the console key a dead key? If yes, ignore the first key down event. */ - if (HasBit(charcode, 31) && !console) { - if (scancode == 41) { - console = true; - return 0; + /* If an edit box is in focus, wait for the corresponding WM_CHAR message. */ + if (!EditBoxInGlobalFocus()) { + /* Is the console key a dead key? If yes, ignore the first key down event. */ + if (HasBit(charcode, 31) && !console) { + if (scancode == 41) { + console = true; + return 0; + } } + console = false; + + /* IMEs and other input methods sometimes send a WM_CHAR without a WM_KEYDOWN, + * clear the keycode so a previous WM_KEYDOWN doesn't become 'stuck'. */ + uint cur_keycode = keycode; + keycode = 0; + + return HandleCharMsg(cur_keycode, LOWORD(charcode)); } - console = false; - /* IMEs and other input methods sometimes send a WM_CHAR without a WM_KEYDOWN, - * clear the keycode so a previous WM_KEYDOWN doesn't become 'stuck'. */ - uint cur_keycode = keycode; - keycode = 0; - - return HandleCharMsg(cur_keycode, LOWORD(charcode)); + return 0; } case WM_SYSKEYDOWN: // user presses F10 or Alt, both activating the title-menu From e98aed8b485caa63145ae1d8f48b177da3b54006 Mon Sep 17 00:00:00 2001 From: translators Date: Fri, 9 Apr 2021 17:46:40 +0000 Subject: [PATCH 16/31] Update: Translations from eints swedish: 3 changes by DonaldDuck313 korean: 2 changes by telk5093 portuguese (brazilian): 4 changes by brunodelara-cloudcrm --- src/lang/brazilian_portuguese.txt | 5 ++++- src/lang/korean.txt | 4 ++-- src/lang/swedish.txt | 3 +++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index e13a883070..09fd14b100 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -1139,6 +1139,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Configur STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Filtro: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Maximizar tudo STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Minimizar tudo +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Redefinir todos os parâmetros STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(não há explicação disponível) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Valor padrão: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Tipo de config.: {ORANGE}{STRING} @@ -1147,6 +1148,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Config. do jogo STR_CONFIG_SETTING_TYPE_GAME_INGAME :Config. do jogo (guardado no savegame; afeta apenas jogo atual) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Config. da companhia (guardado no savegame; afeta apenas novos jogos) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Config. da companhia (guardado no savegame; afeta apenas a comp. atual) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Cuidado! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Essa ação irá restaurar todas as configurações para os valores padrão.{}Tem certeza que deseja continuar? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Categoria: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Tipo: @@ -2532,7 +2535,7 @@ STR_WATERWAYS_TOOLBAR_BUILD_DOCK_TOOLTIP :{BLACK}Construi STR_WATERWAYS_TOOLBAR_BUOY_TOOLTIP :{BLACK}Posicione a bóia, que pode ser usada como ponto de rota. Shift altera construção/preço estimado STR_WATERWAYS_TOOLBAR_BUILD_AQUEDUCT_TOOLTIP :{BLACK}Construir aqueduto. Shift altera construção/preço estimado STR_WATERWAYS_TOOLBAR_CREATE_LAKE_TOOLTIP :{BLACK}Define área com água.{}Faz um canal, a menos se CTRL for pressionado ao nível do mar, neste caso inundará ao redor -STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Criar rios +STR_WATERWAYS_TOOLBAR_CREATE_RIVER_TOOLTIP :{BLACK}Criar rios. Ctrl seleciona a área na diagonal # Ship depot construction window STR_DEPOT_BUILD_SHIP_CAPTION :{WHITE}Orientação do Depósito Naval diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 47ccfc9028..31149fa9c7 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -3093,7 +3093,7 @@ STR_NEWGRF_ERROR_LOAD_BEFORE :{1:STRING}{G 1 STR_NEWGRF_ERROR_LOAD_AFTER :{1:STRING}{G 1 "은" "는"} 반드시 {STRING} 뒤에 불러와야 합니다 STR_NEWGRF_ERROR_OTTD_VERSION_NUMBER :{1:STRING}{G 1 "은" "는"} OpenTTD {STRING} 버전이나 그 이상이 필요합니다 STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE :GRF 파일이 번역을 위해 만들어졌습니다 -STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED :NewGRF이 너무 많습니다 +STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED :NewGRF가 너무 많습니다 STR_NEWGRF_ERROR_STATIC_GRF_CAUSES_DESYNC :{2:STRING}{G 2 "을" "를"} 포함한 정적 NewGRF {1:STRING}{G 1 "을" "를"} 불러오는 것은 비동기화를 일으킬 수 있습니다 STR_NEWGRF_ERROR_UNEXPECTED_SPRITE :예기치 않은 스프라이트 (스프라이트 {3:NUM}) STR_NEWGRF_ERROR_UNKNOWN_PROPERTY :알려지지 않은 액션 0 속성 {4:HEX} (스프라이트 {3:NUM}) @@ -3127,7 +3127,7 @@ STR_NEWGRF_LIST_COMPATIBLE :{YELLOW}호환 STR_NEWGRF_LIST_MISSING :{RED}파일 없음 # NewGRF 'it's broken' warnings -STR_NEWGRF_BROKEN :{WHITE}'{0:STRING}' NewGRF이 적용되는 과정에서 비동기화나 충돌이 일어날 수 있습니다 +STR_NEWGRF_BROKEN :{WHITE}'{0:STRING}' NewGRF가 적용되는 과정에서 비동기화나 충돌이 일어날 수 있습니다 STR_NEWGRF_BROKEN_POWERED_WAGON :{WHITE}차고지 안에 있지 않은 '{1:ENGINE}'에 대한 동력 차량 상태가 바뀌었습니다 STR_NEWGRF_BROKEN_VEHICLE_LENGTH :{WHITE}'{1:ENGINE}'{G 1 "이" "가"} 차고지 안에 있지 않으면 차량 길이가 바뀝니다 STR_NEWGRF_BROKEN_CAPACITY :{WHITE}차량이 기지 안에 있지 않거나 개조가 불가능한 상태에서 '{1:ENGINE}'의 수송량이 변경되었습니다 diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index 2a7ef7de9a..4e2c8487de 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -1138,6 +1138,7 @@ STR_CONFIG_SETTING_TREE_CAPTION :{WHITE}Inställ STR_CONFIG_SETTING_FILTER_TITLE :{BLACK}Sökfilter: STR_CONFIG_SETTING_EXPAND_ALL :{BLACK}Utöka alla STR_CONFIG_SETTING_COLLAPSE_ALL :{BLACK}Stäng alla +STR_CONFIG_SETTING_RESET_ALL :{BLACK}Återställ alla värden STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT :(ingen förklaring tillgänglig) STR_CONFIG_SETTING_DEFAULT_VALUE :{LTBLUE}Standardvärde: {ORANGE}{STRING} STR_CONFIG_SETTING_TYPE :{LTBLUE}Typ av inställning: {ORANGE}{STRING} @@ -1146,6 +1147,8 @@ STR_CONFIG_SETTING_TYPE_GAME_MENU :Spelinställnin STR_CONFIG_SETTING_TYPE_GAME_INGAME :Spelinställning (sparad i spel-fil och påverkar enbart nuvarande spel) STR_CONFIG_SETTING_TYPE_COMPANY_MENU :Företagsinställning (sparad i spel-fil och påverkar enbart nya spel) STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :Företagsinställning (sparad i spel-fil och påverkar enbart nuvarande företag) +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION :{WHITE}Varning! +STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT :{WHITE}Detta kommer att återställa alla spelinställningar till deras standardvärden.{}Är du säker på att du vill fortsätta? STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}Kategori: STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}Typ: From ff6924f1222ade72feab10a9e9137e50fad9ea89 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 10 Apr 2021 11:14:55 +0200 Subject: [PATCH 17/31] Fix 70bc55cfd6e: snow line height was set while calculating desert line (#8989) Seems I liked copy/pasting just a tiny bit too much. --- src/landscape.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/landscape.cpp b/src/landscape.cpp index 9c524bf6c1..6ea3af75b6 100644 --- a/src/landscape.cpp +++ b/src/landscape.cpp @@ -1400,7 +1400,7 @@ static void CalculateSnowLine() static uint8 CalculateDesertLine() { /* CalculateCoverageLine() runs from top to bottom, so we need to invert the coverage. */ - return _settings_game.game_creation.snow_line_height = CalculateCoverageLine(100 - _settings_game.game_creation.desert_coverage, 4); + return CalculateCoverageLine(100 - _settings_game.game_creation.desert_coverage, 4); } void GenerateLandscape(byte mode) From c64b0946e882ca6ff199834853696e3e0c239b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Sat, 10 Apr 2021 11:15:47 +0200 Subject: [PATCH 18/31] Fix e0561dbde: [MinGW] use ofstring(wchar_t*) as ofstring(wstring) doesn't exist (#8985) --- src/ini.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ini.cpp b/src/ini.cpp index a5045b7151..017f5f9030 100644 --- a/src/ini.cpp +++ b/src/ini.cpp @@ -53,7 +53,7 @@ bool IniFile::SaveToDisk(const std::string &filename) std::string file_new{ filename }; file_new.append(".new"); - std::ofstream os(OTTD2FS(file_new)); + std::ofstream os(OTTD2FS(file_new).c_str()); if (os.fail()) return false; for (const IniGroup *group = this->group; group != nullptr; group = group->next) { From 0cb99c55233e8e29ba33ae49002f9453d55d600c Mon Sep 17 00:00:00 2001 From: Didac Perez Parera Date: Sat, 10 Apr 2021 02:19:14 -0700 Subject: [PATCH 19/31] Codechange: nullptr deletion in DeleteWindowById (#8941) --- src/window.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/window.cpp b/src/window.cpp index e164d0d4a6..2216fb2418 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1165,8 +1165,7 @@ Window *FindWindowByClass(WindowClass cls) void DeleteWindowById(WindowClass cls, WindowNumber number, bool force) { Window *w = FindWindowById(cls, number); - if (force || w == nullptr || - (w->flags & WF_STICKY) == 0) { + if (w != nullptr && (force || (w->flags & WF_STICKY) == 0)) { delete w; } } From c800dcaff8b72a1e9997f39b2fd701fa6378799a Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Sat, 10 Apr 2021 11:17:53 +0200 Subject: [PATCH 20/31] Fix: [Win32] Font glyphs of certain widths broke Font glyphs between 33 and 39 pixels wide, in the Win32 font system, used wrong alignment and caused glyphs to appear broken. When in the 33 to 39 pixel range, glyphs without AA were rounded down to 32 pixel pitch, instead of up to 64 pixel pitch. --- src/os/windows/font_win32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/os/windows/font_win32.cpp b/src/os/windows/font_win32.cpp index 59d5e0ad85..55d4193e89 100644 --- a/src/os/windows/font_win32.cpp +++ b/src/os/windows/font_win32.cpp @@ -498,7 +498,7 @@ void Win32FontCache::ClearFontCache() * For anti-aliased rendering, GDI uses the strange value range of 0 to 64, * inclusively. To map this to 0 to 255, we shift left by two and then * subtract one. */ - uint pitch = Align(aa ? gm.gmBlackBoxX : std::max(gm.gmBlackBoxX / 8u, 1u), 4); + uint pitch = Align(aa ? gm.gmBlackBoxX : std::max((gm.gmBlackBoxX + 7u) / 8u, 1u), 4); /* Draw shadow for medium size. */ if (this->fs == FS_NORMAL && !aa) { From 8a944c88c9b10642641f2f44ae2937cf36b481a4 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 10 Apr 2021 11:47:17 +0200 Subject: [PATCH 21/31] Change: [DorpsGek] also announce Discussion creation/comments from GitHub (#8991) --- .dorpsgek.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.dorpsgek.yml b/.dorpsgek.yml index 363d8b0b42..7ce84af72f 100644 --- a/.dorpsgek.yml +++ b/.dorpsgek.yml @@ -10,6 +10,7 @@ notifications: only-by: - DorpsGek commit-comment: + discussion: pull-request: issue: tag-created: From 47c04033200c58671f31b1df0ad474f37bfb1864 Mon Sep 17 00:00:00 2001 From: Didac Perez Parera Date: Sat, 10 Apr 2021 03:55:49 -0700 Subject: [PATCH 22/31] Change: do not disable NewGRF window apply button if dev tools are enabled (#8975) enabled --- src/newgrf_gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index ad37b35425..50e402ffb9 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -1255,7 +1255,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { this->BuildAvailables(); - this->SetWidgetDisabledState(WID_NS_APPLY_CHANGES, !this->editable || !this->modified); + this->SetWidgetDisabledState(WID_NS_APPLY_CHANGES, !((this->editable && this->modified) || _settings_client.gui.newgrf_developer_tools)); this->SetWidgetsDisabledState(!this->editable, WID_NS_PRESET_LIST, WID_NS_TOGGLE_PALETTE, From c50626319765e85efeb2e327cb401c807d5a26f3 Mon Sep 17 00:00:00 2001 From: Charles Pigott Date: Sat, 10 Apr 2021 13:44:17 +0100 Subject: [PATCH 23/31] Fix #8956: Industry disaster news messages showed the wrong location (#8992) --- src/disaster_vehicle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/disaster_vehicle.cpp b/src/disaster_vehicle.cpp index c5d76877cc..cc245b38fe 100644 --- a/src/disaster_vehicle.cpp +++ b/src/disaster_vehicle.cpp @@ -456,7 +456,7 @@ static bool DisasterTick_Aircraft(DisasterVehicle *v, uint16 image_override, boo DestructIndustry(i); SetDParam(0, i->town->index); - AddTileNewsItem(news_message, NT_ACCIDENT, v->dest_tile); + AddIndustryNewsItem(news_message, NT_ACCIDENT, i->index); if (_settings_client.sound.disaster) SndPlayTileFx(SND_12_EXPLOSION, i->location.tile); } } else if (v->current_order.GetDestination() == 0) { From 5a14bf3a6ccf08c26b63b4f68d1cdae66f732770 Mon Sep 17 00:00:00 2001 From: translators Date: Sat, 10 Apr 2021 15:24:45 +0000 Subject: [PATCH 24/31] Update: Translations from eints korean: 1 change by telk5093 spanish: 1 change by MontyMontana --- src/lang/korean.txt | 2 +- src/lang/spanish.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 31149fa9c7..c5e44fa35a 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -954,7 +954,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :말레이시아 STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :좌측통행 STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT :우측통행 -STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}도시 이름 +STR_GAME_OPTIONS_TOWN_NAMES_FRAME :{BLACK}도시 이름: STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP :{BLACK}도시 이름 스타일을 선택하세요 ############ start of townname region diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index b7dc758c3c..855546f875 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -119,7 +119,7 @@ STR_QUANTITY_SUGAR :{WEIGHT_LONG} d STR_QUANTITY_TOYS :{COMMA}{NBSP}juguete{P "" s} STR_QUANTITY_SWEETS :{COMMA}{NBSP}bolsa{P "" s} de caramelos STR_QUANTITY_COLA :{VOLUME_LONG} de cola -STR_QUANTITY_CANDYFLOSS :{WEIGHT_LONG} de algodón dulce +STR_QUANTITY_CANDYFLOSS :{WEIGHT_LONG} de algodón de azúcar STR_QUANTITY_BUBBLES :{COMMA} burbuja{P "" s} STR_QUANTITY_TOFFEE :{WEIGHT_LONG} de tofe{P "" s} STR_QUANTITY_BATTERIES :{COMMA} pila{P "" s} From d4c3d01d07980708e86c3532422b4bf437aabb64 Mon Sep 17 00:00:00 2001 From: Nicolae Crefelean Date: Sat, 10 Apr 2021 17:33:27 +0200 Subject: [PATCH 25/31] Add: new plural form for Romanian translation (#8936) --- src/lang/romanian.txt | 2 +- src/strings.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt index 889268e22e..42ec4d24b3 100644 --- a/src/lang/romanian.txt +++ b/src/lang/romanian.txt @@ -1,7 +1,7 @@ ##name Romanian ##ownname Românӑ ##isocode ro_RO -##plural 0 +##plural 14 ##textdir ltr ##digitsep . ##digitsepcur . diff --git a/src/strings.cpp b/src/strings.cpp index 7cbdc3cb09..1f288d308e 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -628,6 +628,12 @@ static int DeterminePluralForm(int64 count, int plural_form) * Scottish Gaelic */ case 13: return ((n == 1 || n == 11) ? 0 : (n == 2 || n == 12) ? 1 : ((n > 2 && n < 11) || (n > 12 && n < 20)) ? 2 : 3); + + /* Three forms: special cases for 1, 0 and numbers ending in 01 to 19. + * Used in: + * Romanian */ + case 14: + return n == 1 ? 0 : (n == 0 || (n % 100 > 0 && n % 100 < 20)) ? 1 : 2; } } From 0e01a7a43122a17d8537c455e6a068f75f61b809 Mon Sep 17 00:00:00 2001 From: translators Date: Sat, 10 Apr 2021 15:48:34 +0000 Subject: [PATCH 26/31] Update: Translations from eints --- src/lang/romanian.txt | 55 ------------------------------------------- 1 file changed, 55 deletions(-) diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt index 42ec4d24b3..88113eac2d 100644 --- a/src/lang/romanian.txt +++ b/src/lang/romanian.txt @@ -93,37 +93,25 @@ STR_CARGO_SINGULAR_FIZZY_DRINK :Suc acidulat # Quantity of cargo STR_QUANTITY_NOTHING : -STR_QUANTITY_PASSENGERS :{COMMA} călător{P "" i} STR_QUANTITY_COAL :{WEIGHT_LONG} de cărbune -STR_QUANTITY_MAIL :{COMMA} sac{P "" i} cu colete poștale STR_QUANTITY_OIL :{VOLUME_LONG} de petrol -STR_QUANTITY_LIVESTOCK :{COMMA} animal{P "" e} -STR_QUANTITY_GOODS :{COMMA} pachet{P "" e} de bunuri STR_QUANTITY_GRAIN :{WEIGHT_LONG} de cereale STR_QUANTITY_WOOD :{WEIGHT_LONG} de lemne STR_QUANTITY_IRON_ORE :{WEIGHT_LONG} de minereu de fier STR_QUANTITY_STEEL :{WEIGHT_LONG} de oțel -STR_QUANTITY_VALUABLES :{COMMA} cuti{P e i} de valori STR_QUANTITY_COPPER_ORE :{WEIGHT_LONG} de minereu de cupru STR_QUANTITY_MAIZE :{WEIGHT_LONG} de porumb STR_QUANTITY_FRUIT :{WEIGHT_LONG} de fructe -STR_QUANTITY_DIAMONDS :{COMMA} sac{P "" i} cu diamante STR_QUANTITY_FOOD :{WEIGHT_LONG} de alimente STR_QUANTITY_PAPER :{WEIGHT_LONG} de hârtie -STR_QUANTITY_GOLD :{COMMA} sac{P "" i} cu aur STR_QUANTITY_WATER :{VOLUME_LONG} de apă STR_QUANTITY_WHEAT :{WEIGHT_LONG} de grâu STR_QUANTITY_RUBBER :{VOLUME_LONG} de cauciuc STR_QUANTITY_SUGAR :{WEIGHT_LONG} de zahăr -STR_QUANTITY_TOYS :{COMMA} sac{P "" i} cu jucării -STR_QUANTITY_SWEETS :{COMMA} sac{P "" i} cu bomboane STR_QUANTITY_COLA :{VOLUME_LONG} de cola STR_QUANTITY_CANDYFLOSS :{WEIGHT_LONG} de vată de zahăr -STR_QUANTITY_BUBBLES :{COMMA} balonaș{P "" e} STR_QUANTITY_TOFFEE :{WEIGHT_LONG} de caramel -STR_QUANTITY_BATTERIES :{COMMA} bateri{P e i} STR_QUANTITY_PLASTIC :{VOLUME_LONG} de plastic -STR_QUANTITY_FIZZY_DRINKS :{COMMA} bido{P n ane} cu suc STR_QUANTITY_N_A :N/A # Two letter abbreviation of cargo name @@ -163,12 +151,9 @@ STR_ABBREV_NONE :{TINY_FONT}NU STR_ABBREV_ALL :{TINY_FONT}TOT # 'Mode' of transport for cargoes -STR_PASSENGERS :{COMMA} călător{P "" i} -STR_BAGS :{COMMA}{NBSP}sac{P "" i} STR_TONS :{COMMA} tone STR_LITERS :{COMMA} litri STR_ITEMS :{COMMA} bucăți -STR_CRATES :{COMMA} pachet{P "" e} # Colours, do not shuffle STR_COLOUR_DARK_BLUE :Albastru închis @@ -203,16 +188,12 @@ STR_UNITS_WEIGHT_SHORT_IMPERIAL :{COMMA}t STR_UNITS_WEIGHT_SHORT_METRIC :{COMMA}t STR_UNITS_WEIGHT_SHORT_SI :{COMMA}kg -STR_UNITS_WEIGHT_LONG_IMPERIAL :{COMMA} ton{P ă e} -STR_UNITS_WEIGHT_LONG_METRIC :{COMMA} ton{P ă e} STR_UNITS_WEIGHT_LONG_SI :{COMMA} kg STR_UNITS_VOLUME_SHORT_IMPERIAL :{COMMA}gal STR_UNITS_VOLUME_SHORT_METRIC :{COMMA}l STR_UNITS_VOLUME_SHORT_SI :{COMMA}m³ -STR_UNITS_VOLUME_LONG_IMPERIAL :{COMMA} galo{P n ane} -STR_UNITS_VOLUME_LONG_METRIC :{COMMA} litr{P u i} STR_UNITS_VOLUME_LONG_SI :{COMMA} m³ STR_UNITS_FORCE_IMPERIAL :{COMMA} lbf @@ -1009,7 +990,6 @@ STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP :{BLACK}Alegeți STR_GAME_OPTIONS_BASE_GRF :{BLACK}Set grafic de bază STR_GAME_OPTIONS_BASE_GRF_TOOLTIP :{BLACK}Selectează setul grafic de bază utilizat în joc -STR_GAME_OPTIONS_BASE_GRF_STATUS :{RED}{NUM} fişier{P "" "e"} lipsă/corupt{P "" e} STR_GAME_OPTIONS_BASE_GRF_DESCRIPTION_TOOLTIP :{BLACK}Informaţii adiţionale despre setul grafic de bază STR_GAME_OPTIONS_BASE_SFX :{BLACK}Set sunete de bază @@ -1018,7 +998,6 @@ STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP :{BLACK}Informa STR_GAME_OPTIONS_BASE_MUSIC :{BLACK}Setul de muzică de bază STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP :{BLACK}Selectaţi setul de muzică de bază -STR_GAME_OPTIONS_BASE_MUSIC_STATUS :{RED}{NUM} fişier{P "" e} corupt{P "" e} STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP :{BLACK}Informaţii adiţionale despre setul de muzică de bază STR_ERROR_RESOLUTION_LIST_FAILED :{WHITE}Nu s-a putut obține lista de rezoluții suportate @@ -1191,7 +1170,6 @@ STR_CONFIG_SETTING_EXTRADYNAMITE :Permite demolar STR_CONFIG_SETTING_EXTRADYNAMITE_HELPTEXT :Facilitează eliminarea de clădiri şi infrastructură deţinute de oraş STR_CONFIG_SETTING_TRAIN_LENGTH :Lungimea maximă a trenurilor: {STRING} STR_CONFIG_SETTING_TRAIN_LENGTH_HELPTEXT :Configurează lungimea maximă a trenurilor -STR_CONFIG_SETTING_TILE_LENGTH :{COMMA} pătrăţel{P 0 "" e} STR_CONFIG_SETTING_SMOKE_AMOUNT :Cantitatea de fum/ scântei ale vehiculului: {STRING} STR_CONFIG_SETTING_SMOKE_AMOUNT_HELPTEXT :Configurează cât de mult fum sau cât de multe scântei sunt emise de vehicule STR_CONFIG_SETTING_TRAIN_ACCELERATION_MODEL :Modelul de acceleraţie al trenurilor: {STRING} @@ -1292,16 +1270,12 @@ STR_CONFIG_SETTING_AUTORENEW_VEHICLE :Înnoire automa STR_CONFIG_SETTING_AUTORENEW_VEHICLE_HELPTEXT :După activare, orice vehicul care este învechit va fi reînnoit automat când condițiile de înlocuire automată sunt îndeplinite STR_CONFIG_SETTING_AUTORENEW_MONTHS :Autoreînnoire când vehiculul {STRING} vârsta maximă STR_CONFIG_SETTING_AUTORENEW_MONTHS_HELPTEXT :Vârsta aproximativă când un vehicul ar trebui autoreînnoit -STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_BEFORE :mai are {COMMA} lun{P 0 ă i} până la -STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_AFTER :a depășit cu {COMMA} lun{P 0 ă i} STR_CONFIG_SETTING_AUTORENEW_MONEY :Fonduri minime pentru înnoire automată: {STRING} STR_CONFIG_SETTING_AUTORENEW_MONEY_HELPTEXT :Suma minimă care trebuie să rămână disponibilă atunci când se face autoreînnoirea STR_CONFIG_SETTING_ERRMSG_DURATION :Durata de afișare a mesajelor de eroare: {STRING} STR_CONFIG_SETTING_ERRMSG_DURATION_HELPTEXT :Durata afișării mesajelor de eroare în fereastra roșie. Unele mesaje de eroare (cele critice) nu sunt închise automat după trecerea acestei perioade, și trebuie închise manual. -STR_CONFIG_SETTING_ERRMSG_DURATION_VALUE :{COMMA} secund{P 0 ă e} STR_CONFIG_SETTING_HOVER_DELAY :Afișează texte informative: {STRING} STR_CONFIG_SETTING_HOVER_DELAY_HELPTEXT :Durata dinaintea afișării sfaturilor când se ține mausul pe un element al interfeței. Alternativ, afișarea sfaturilor poate fi setată pentru clic-dreapta -STR_CONFIG_SETTING_HOVER_DELAY_VALUE :Plutește {COMMA} milisecund{P 0 ă e} STR_CONFIG_SETTING_HOVER_DELAY_DISABLED :Click dreapta STR_CONFIG_SETTING_POPULATION_IN_LABEL :Afişează populaţia unui oras lângă nume: {STRING} STR_CONFIG_SETTING_POPULATION_IN_LABEL_HELPTEXT :Afișează populația orașelor în numele afișate pe hartă @@ -1494,7 +1468,6 @@ STR_CONFIG_SETTING_SERVINT_ISPERCENT :Intervaluri de STR_CONFIG_SETTING_SERVINT_ISPERCENT_HELPTEXT :Alege dacă întreținerea vehiculelor este activată de trecerea unei anumite perioade de timp, sau scăzând un anumit procent din gradul de rezistență al vehiculului STR_CONFIG_SETTING_SERVINT_TRAINS :Intervalul de întreținere implicit al trenurilor: {STRING} STR_CONFIG_SETTING_SERVINT_TRAINS_HELPTEXT :Alege perioada de întreținere implicită pentru noi vehicule feroviare, dacă nu există un interval de întreținere stabilit pentru vehicul -STR_CONFIG_SETTING_SERVINT_VALUE :{COMMA} zi{P 0 "" le}/% STR_CONFIG_SETTING_SERVINT_DISABLED :Dezactivat STR_CONFIG_SETTING_SERVINT_ROAD_VEHICLES :Intervalul de întreținere implicit al vehiculelor rutiere: {STRING} STR_CONFIG_SETTING_SERVINT_ROAD_VEHICLES_HELPTEXT :Alege perioada de întreținere implicită pentru noi vehicule rutiere, dacă nu există un interval de întreținere stabilit pentru vehicul @@ -1559,7 +1532,6 @@ STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE :Procentul din p STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT :Procentul din câştig care este oferit legăturilor intermediare pentru alimentare, oferind mai mult control asupra încasărilor STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY :Când se trage cu mouse-ul, plasează semnale la fiecare: {STRING} STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY_HELPTEXT :Configurează distanţa la care se vor construi semnale pe şină până la următorul obstacol (semnal, intersecţie), dacâ se trage cu mouse-ul -STR_CONFIG_SETTING_DRAG_SIGNALS_DENSITY_VALUE :{COMMA} pătrăţel{P 0 "" e} STR_CONFIG_SETTING_DRAG_SIGNALS_FIXED_DISTANCE :La plasarea mai multor semale, păstrează distanţa fixă între acestea: {STRING} STR_CONFIG_SETTING_SEMAPHORE_BUILD_BEFORE_DATE :Construieşte automat semafoare înainte de: {STRING} STR_CONFIG_SETTING_SEMAPHORE_BUILD_BEFORE_DATE_HELPTEXT :Alege anul din care se vor folosi semnale electrice pe calea feroviară. Înainte de acest an, se vor folosi semnale non-electrice care au aceeasi funcționalitate dar arată diferit @@ -1609,7 +1581,6 @@ STR_CONFIG_SETTING_TOOLBAR_POS_HELPTEXT :Poziţia orizon STR_CONFIG_SETTING_STATUSBAR_POS :Poziţia barei de stare: {STRING} STR_CONFIG_SETTING_STATUSBAR_POS_HELPTEXT :Poziţia orizontală a barei principale în partea de jos a ecranului STR_CONFIG_SETTING_SNAP_RADIUS :Raza "magnetică" a ferestrelor: {STRING} -STR_CONFIG_SETTING_SNAP_RADIUS_VALUE :{COMMA} pixel{P 0 "" i} STR_CONFIG_SETTING_SNAP_RADIUS_DISABLED :Dezactivat STR_CONFIG_SETTING_SOFT_LIMIT :Numărul maxim de ferestre nefixate: {STRING} STR_CONFIG_SETTING_SOFT_LIMIT_VALUE :{COMMA} @@ -1638,9 +1609,7 @@ STR_CONFIG_SETTING_LARGER_TOWNS_DISABLED :deloc STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER :Multiplicator iniţial dimensiune oraş: {STRING} STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :Dimensiunea medie a oraşelor mari relativ la oraşele normale, la începutul jocului -STR_CONFIG_SETTING_LINKGRAPH_INTERVAL :Actualizează graficul de distribuţie la fiecare {STRING} zi{P 0:2 "" le} STR_CONFIG_SETTING_LINKGRAPH_INTERVAL_HELPTEXT :Interval de timp între recalculările graficului de conexiuni. Fiecare recalculare calculează planurile unei componente ale graficului. Asta înseamnă că o valoare X pentru această setare nu va duce la actualizarea întregului grafic la fiecare X zile, ci doar o componentă va fi actualizată. Cu cât e mai mică valoarea, cu atât mai timp CPU va fi necesar pentru calcule. Cu cât e mai mare valoarea, cu atât va dura mai mult până va începe distribuția mărfii pe rute noi. -STR_CONFIG_SETTING_LINKGRAPH_TIME :Acordă {STRING} zi{P 0:2 "" le} pentru recalcularea graficului de distribuţie STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :manual STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC :asimetric STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC :simetric @@ -1792,8 +1761,6 @@ STR_INTRO_TOOLTIP_ONLINE_CONTENT :{BLACK}Verific STR_INTRO_TOOLTIP_SCRIPT_SETTINGS :{BLACK}Afişează setările pentru Inteligența Artificială şi pentru Scripturi Joc STR_INTRO_TOOLTIP_QUIT :{BLACK}Ieşi din 'OpenTTD' -STR_INTRO_BASESET :{BLACK}Setul grafic actual are lipsă {NUM} sprite{P "" s}. Verificați actualizările pentru setul de bază. -STR_INTRO_TRANSLATION :{BLACK}Acestei traduceri îi lipse{P 0 "şte" "sc"} {NUM} text{P "" e}. Te rugăm să ajuti la îmbunătățirea OpenTTD înrolându-te ca traducător. Citește fișierul readme.txt pentru detalii. # Quit window STR_QUIT_CAPTION :{WHITE}Ieşire din joc @@ -1982,13 +1949,10 @@ STR_NETWORK_START_SERVER_ADVERTISED_LABEL :{BLACK}Publicat STR_NETWORK_START_SERVER_ADVERTISED_TOOLTIP :{BLACK}Alege între un joc publicat (prin Internet) și unul privat (reț) game STR_NETWORK_START_SERVER_UNADVERTISED :Nu STR_NETWORK_START_SERVER_ADVERTISED :Da -STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} clien{P t ţi} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Număr maxim de clienţi: STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS_TOOLTIP :{BLACK}Alege un număr maxim de clienţi. Nu trebuie ocupate toate locurile. -STR_NETWORK_START_SERVER_COMPANIES_SELECT :{BLACK}{NUM} compan{P ie ii} STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES :{BLACK}Companii maxim: STR_NETWORK_START_SERVER_NUMBER_OF_COMPANIES_TOOLTIP :{BLACK}Limitează serverul la un anumit număr de companii -STR_NETWORK_START_SERVER_SPECTATORS_SELECT :{BLACK}{NUM} spectator{P "" i} STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS :{BLACK}Spectatori maxim: STR_NETWORK_START_SERVER_NUMBER_OF_SPECTATORS_TOOLTIP :{BLACK}Limitează serverul la un anumit număr de spectatori STR_NETWORK_START_SERVER_LANGUAGE_SPOKEN :{BLACK}Limba vorbită: @@ -2075,7 +2039,6 @@ STR_NETWORK_CONNECTING_6 :{BLACK}(6/6) Î STR_NETWORK_CONNECTING_SPECIAL_1 :{BLACK}Preluare informaţii joc... STR_NETWORK_CONNECTING_SPECIAL_2 :{BLACK}Preluare informaţii companie... ############ End of leave-in-this-order -STR_NETWORK_CONNECTING_WAITING :{BLACK}{NUM} clien{P t ţi} înaintea noastră STR_NETWORK_CONNECTING_DOWNLOADING_1 :{BLACK}{BYTES} descărcat până acum STR_NETWORK_CONNECTING_DOWNLOADING_2 :{BLACK}{BYTES} / {BYTES} descărcaţi până acum @@ -3014,7 +2977,6 @@ STR_INVALID_VEHICLE : Date: Sat, 10 Apr 2021 18:09:04 +0200 Subject: [PATCH 27/31] Fix d4c3d01d: add plural form 14 to strgen. (#8999) --- src/table/strgen_tables.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/table/strgen_tables.h b/src/table/strgen_tables.h index 1c565089ad..ecdafb3ee7 100644 --- a/src/table/strgen_tables.h +++ b/src/table/strgen_tables.h @@ -176,6 +176,7 @@ static const PluralForm _plural_forms[] = { { 2, "Two forms: cases for numbers ending with a consonant, and with a vowel.", "\"yeong,il,sam,yuk,chil,pal\" \"i,sa,o,gu\"" }, { 4, "Four forms: special cases for 1, 0 and numbers ending in 02 to 10, and numbers ending in 11 to 19.", "\"1\" \"0,2..10,102..110,202..210,...\" \"11..19,111..119,211..219,...\" \"other\"" }, { 4, "Four forms: special cases for 1 and 11, 2 and 12, 3..10 and 13..19.", "\"1,11\" \"2,12\" \"3..10,13..19\" \"other\"" }, + { 3, "Three forms: special cases for 1, 0 and numbers ending in 01 to 19.", "\"1\" \"0,2..19,101..119,201..219,...\" \"other\"" }, }; /* Flags: From fbd0a2e65a5563e8f8059aae1adb0f375f2d3348 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 5 Apr 2021 21:32:48 +0100 Subject: [PATCH 28/31] Fix: Thread unsafe use of sprite cache in OpenGLBackend::DrawMouseCursor See also: #8870 See also: #8977 --- src/video/opengl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/opengl.cpp b/src/video/opengl.cpp index e74ab7b5bc..c346fd1528 100644 --- a/src/video/opengl.cpp +++ b/src/video/opengl.cpp @@ -1060,9 +1060,9 @@ void OpenGLBackend::DrawMouseCursor() /* Sprites are cached by PopulateCursorCache(). */ if (this->cursor_cache.Contains(sprite)) { - const Sprite *spr = GetSprite(sprite, ST_NORMAL); + Sprite *spr = this->cursor_cache.Get(sprite); - this->RenderOglSprite((OpenGLSprite *)this->cursor_cache.Get(sprite)->data, _cursor.sprite_seq[i].pal, + this->RenderOglSprite((OpenGLSprite *)spr->data, _cursor.sprite_seq[i].pal, _cursor.pos.x + _cursor.sprite_pos[i].x + UnScaleByZoom(spr->x_offs, ZOOM_LVL_GUI), _cursor.pos.y + _cursor.sprite_pos[i].y + UnScaleByZoom(spr->y_offs, ZOOM_LVL_GUI), ZOOM_LVL_GUI); From 39b7ef31f8754a7e9d535d3b061a2e167ccd1338 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 5 Apr 2021 23:22:55 +0100 Subject: [PATCH 29/31] Fix: Data races on cursor state in OpenGL backends --- src/video/cocoa/cocoa_ogl.mm | 2 +- src/video/opengl.cpp | 21 ++++++++++++++++----- src/video/opengl.h | 6 ++++++ src/video/sdl2_opengl_v.cpp | 2 +- src/video/win32_v.cpp | 2 +- 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/video/cocoa/cocoa_ogl.mm b/src/video/cocoa/cocoa_ogl.mm index 8d02428e0c..f8c2e97e0d 100644 --- a/src/video/cocoa/cocoa_ogl.mm +++ b/src/video/cocoa/cocoa_ogl.mm @@ -134,7 +134,7 @@ static bool _allowSoftware; CGLSetCurrentContext(ctx); OpenGLBackend::Get()->Paint(); - if (_cursor.in_window) OpenGLBackend::Get()->DrawMouseCursor(); + OpenGLBackend::Get()->DrawMouseCursor(); [ super drawInCGLContext:ctx pixelFormat:pf forLayerTime:t displayTime:ts ]; } diff --git a/src/video/opengl.cpp b/src/video/opengl.cpp index c346fd1528..c1c1afaaec 100644 --- a/src/video/opengl.cpp +++ b/src/video/opengl.cpp @@ -1053,18 +1053,20 @@ void OpenGLBackend::Paint() */ void OpenGLBackend::DrawMouseCursor() { + if (!this->cursor_in_window) return; + /* Draw cursor on screen */ _cur_dpi = &_screen; - for (uint i = 0; i < _cursor.sprite_count; ++i) { - SpriteID sprite = _cursor.sprite_seq[i].sprite; + for (uint i = 0; i < this->cursor_sprite_count; ++i) { + SpriteID sprite = this->cursor_sprite_seq[i].sprite; /* Sprites are cached by PopulateCursorCache(). */ if (this->cursor_cache.Contains(sprite)) { Sprite *spr = this->cursor_cache.Get(sprite); - this->RenderOglSprite((OpenGLSprite *)spr->data, _cursor.sprite_seq[i].pal, - _cursor.pos.x + _cursor.sprite_pos[i].x + UnScaleByZoom(spr->x_offs, ZOOM_LVL_GUI), - _cursor.pos.y + _cursor.sprite_pos[i].y + UnScaleByZoom(spr->y_offs, ZOOM_LVL_GUI), + this->RenderOglSprite((OpenGLSprite *)spr->data, this->cursor_sprite_seq[i].pal, + this->cursor_pos.x + this->cursor_sprite_pos[i].x + UnScaleByZoom(spr->x_offs, ZOOM_LVL_GUI), + this->cursor_pos.y + this->cursor_sprite_pos[i].y + UnScaleByZoom(spr->y_offs, ZOOM_LVL_GUI), ZOOM_LVL_GUI); } } @@ -1072,6 +1074,9 @@ void OpenGLBackend::DrawMouseCursor() void OpenGLBackend::PopulateCursorCache() { + static_assert(lengthof(_cursor.sprite_seq) == lengthof(this->cursor_sprite_seq)); + static_assert(lengthof(_cursor.sprite_pos) == lengthof(this->cursor_sprite_pos)); + if (this->clear_cursor_cache) { /* We have a pending cursor cache clear to do first. */ this->clear_cursor_cache = false; @@ -1085,7 +1090,13 @@ void OpenGLBackend::PopulateCursorCache() } } + this->cursor_pos = _cursor.pos; + this->cursor_sprite_count = _cursor.sprite_count; + this->cursor_in_window = _cursor.in_window; + for (uint i = 0; i < _cursor.sprite_count; ++i) { + this->cursor_sprite_seq[i] = _cursor.sprite_seq[i]; + this->cursor_sprite_pos[i] = _cursor.sprite_pos[i]; SpriteID sprite = _cursor.sprite_seq[i].sprite; if (!this->cursor_cache.Contains(sprite)) { diff --git a/src/video/opengl.h b/src/video/opengl.h index c17a8536d9..7e42b20bed 100644 --- a/src/video/opengl.h +++ b/src/video/opengl.h @@ -65,6 +65,12 @@ private: PaletteID last_sprite_pal = (PaletteID)-1; ///< Last uploaded remap palette. bool clear_cursor_cache = false; ///< A clear of the cursor cache is pending. + Point cursor_pos; ///< Cursor position + bool cursor_in_window; ///< Cursor inside this window + PalSpriteID cursor_sprite_seq[16]; ///< Current image of cursor + Point cursor_sprite_pos[16]; ///< Relative position of individual cursor sprites + uint cursor_sprite_count; ///< Number of cursor sprites to draw + OpenGLBackend(); ~OpenGLBackend(); diff --git a/src/video/sdl2_opengl_v.cpp b/src/video/sdl2_opengl_v.cpp index 86dc104dd2..5df2837513 100644 --- a/src/video/sdl2_opengl_v.cpp +++ b/src/video/sdl2_opengl_v.cpp @@ -174,7 +174,7 @@ void VideoDriver_SDL_OpenGL::Paint() } OpenGLBackend::Get()->Paint(); - if (_cursor.in_window) OpenGLBackend::Get()->DrawMouseCursor(); + OpenGLBackend::Get()->DrawMouseCursor(); SDL_GL_SwapWindow(this->sdl_window); } diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index b4d3946ea0..426d74c0aa 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -1454,7 +1454,7 @@ void VideoDriver_Win32OpenGL::Paint() } OpenGLBackend::Get()->Paint(); - if (_cursor.in_window) OpenGLBackend::Get()->DrawMouseCursor(); + OpenGLBackend::Get()->DrawMouseCursor(); SwapBuffers(this->dc); } From 59b6e46bcee466532e7dae3a272079ecdafa0ae1 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sat, 10 Apr 2021 12:40:56 +0100 Subject: [PATCH 30/31] Fix: Adjust scrolling interval of credits to account for text line height --- src/misc_gui.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 2f538f2af9..8ca94b2c3e 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -497,7 +497,7 @@ struct AboutWindow : public Window { int line_height; ///< The height of a single line static const int num_visible_lines = 19; ///< The number of lines visible simultaneously - static const uint TIMER_INTERVAL = 150; ///< Scrolling interval in ms + static const uint TIMER_INTERVAL = 2100; ///< Scrolling interval, scaled by line text line height. This value chosen to maintain parity: 2100 / FONT_HEIGHT_NORMAL = 150ms GUITimer timer; AboutWindow() : Window(&_about_desc) @@ -505,7 +505,6 @@ struct AboutWindow : public Window { this->InitNested(WN_GAME_OPTIONS_ABOUT); this->text_position = this->GetWidget(WID_A_SCROLLING_TEXT)->pos_y + this->GetWidget(WID_A_SCROLLING_TEXT)->current_y; - this->timer.SetInterval(TIMER_INTERVAL); } void SetStringParameters(int widget) const override @@ -528,6 +527,10 @@ struct AboutWindow : public Window { d.width = std::max(d.width, GetStringBoundingBox(_credits[i]).width); } *size = maxdim(*size, d); + + /* Set scroll interval based on required speed. To keep scrolling smooth, + * the interval is adjusted rather than the distance moved. */ + this->timer.SetInterval(TIMER_INTERVAL / FONT_HEIGHT_NORMAL); } void DrawWidget(const Rect &r, int widget) const override From f9460c0c8b4f9f994aadc396579590d26fbac32b Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sat, 10 Apr 2021 18:29:21 +0100 Subject: [PATCH 31/31] Fix #8981: Don't attempt to re-reserve path if already entering/entered depot. --- src/rail_cmd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index a5e985c022..888b98e943 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1197,7 +1197,7 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, MarkTileDirtyByTile(tile); AddTrackToSignalBuffer(tile, track, _current_company); YapfNotifyTrackLayoutChange(tile, track); - if (v != nullptr) { + if (v != nullptr && v->track != TRACK_BIT_DEPOT) { /* Extend the train's path if it's not stopped or loading, or not at a safe position. */ if (!(((v->vehstatus & VS_STOPPED) && v->cur_speed == 0) || v->current_order.IsType(OT_LOADING)) || !IsSafeWaitingPosition(v, v->tile, v->GetVehicleTrackdir(), true, _settings_game.pf.forbid_90_deg)) {