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: diff --git a/cmake/CompileFlags.cmake b/cmake/CompileFlags.cmake index cc4b5baef6..f55ddd751b 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. diff --git a/src/debug.cpp b/src/debug.cpp index bdd15e74e1..f1b3924813 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -183,8 +183,8 @@ static void debug_print(const char *dbg, const char *buf) #if defined(_WIN32) if (strcmp(dbg, "desync") != 0) { wchar_t system_buf[512]; - convert_to_fs(buffer, system_buf, lengthof(system_buf), true); - _fputts(system_buf, stderr); + convert_to_fs(buffer, system_buf, lengthof(system_buf)); + fputws(system_buf, stderr); } #else fputs(buffer, stderr); diff --git a/src/disaster_vehicle.cpp b/src/disaster_vehicle.cpp index f5315c7bd8..3c234e499e 100644 --- a/src/disaster_vehicle.cpp +++ b/src/disaster_vehicle.cpp @@ -479,7 +479,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) { diff --git a/src/fileio.cpp b/src/fileio.cpp index 94e578234c..a78a1476af 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); @@ -512,11 +512,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 } @@ -1321,7 +1321,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; @@ -1331,7 +1331,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 4ee01b342e..540b654760 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 4e4fce82b9..aaee937afa 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..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.c_str())); + std::ofstream os(OTTD2FS(file_new).c_str()); 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/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index c06fe44540..3a26248974 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -1140,6 +1140,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} @@ -1148,6 +1149,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: @@ -2533,7 +2536,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/catalan.txt b/src/lang/catalan.txt index d7ed8cfbd1..2dc547f2fe 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -1140,6 +1140,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} @@ -1148,6 +1149,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/english_US.txt b/src/lang/english_US.txt index 25f59382eb..c7fd0022cd 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -1139,6 +1139,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} @@ -1147,6 +1148,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/finnish.txt b/src/lang/finnish.txt index c4997f4c3a..848212c5ac 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -1139,6 +1139,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} @@ -1147,6 +1148,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/french.txt b/src/lang/french.txt index 6dc837f833..99e51254ac 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -1140,6 +1140,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} @@ -1148,6 +1149,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}: @@ -2533,7 +2536,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/german.txt b/src/lang/german.txt index 6295ee191a..3c5826dbeb 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -1151,6 +1151,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} @@ -1159,6 +1160,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/korean.txt b/src/lang/korean.txt index ff8ce34890..8ad3f19c28 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -966,7 +966,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 @@ -1154,6 +1154,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} @@ -1162,6 +1163,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}종류: @@ -3851,7 +3854,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}) @@ -3887,7 +3890,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/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index 5a1f828796..fef91ec16c 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -1141,6 +1141,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} @@ -1149,6 +1150,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/portuguese.txt b/src/lang/portuguese.txt index 5daeb51f9f..97d1eab83b 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -1140,6 +1140,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} @@ -1148,6 +1149,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: @@ -1905,11 +1908,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) @@ -1918,8 +1921,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/romanian.txt b/src/lang/romanian.txt index 624c4a5e93..7f3f5f740b 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 . @@ -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 @@ -1010,7 +991,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ă @@ -1019,7 +999,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 @@ -1192,7 +1171,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} @@ -1293,16 +1271,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ă @@ -1495,7 +1469,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 @@ -1560,7 +1533,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 @@ -1610,7 +1582,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} @@ -1639,9 +1610,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 @@ -1793,8 +1762,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 @@ -1983,13 +1950,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ă: @@ -2076,7 +2040,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 @@ -3019,7 +2982,6 @@ STR_INVALID_VEHICLE :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 @@ -572,6 +571,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 @@ -845,7 +848,7 @@ struct TooltipsWindow : public Window 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) this->delete_next_mouse_loop = true; + if (w == nullptr || IsPtInWindowViewport(w, _cursor.pos.x, _cursor.pos.y) == nullptr) delete this; break; } } 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 98c2e437f5..fd85469199 100644 --- a/src/music/dmusic.cpp +++ b/src/music/dmusic.cpp @@ -433,7 +433,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; @@ -884,7 +884,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/music/fluidsynth.cpp b/src/music/fluidsynth.cpp index 61686a441e..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 */ @@ -77,12 +85,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 { diff --git a/src/music_gui.cpp b/src/music_gui.cpp index 7e2aaac1d6..28cb6ce4e1 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,19 +786,11 @@ 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(); + SetWindowClassesDirty(WC_GAME_OPTIONS); } if (click_count > 0) this->mouse_capture_widget = widget; diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index 1f9db029a9..97c84d94e6 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -244,7 +244,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/newgrf_gui.cpp b/src/newgrf_gui.cpp index bf731f5e55..b8ab749622 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -1264,7 +1264,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, diff --git a/src/os/os2/os2.cpp b/src/os/os2/os2.cpp index 3507520273..5d35eca451 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 d3254c5fd3..2479c6fe8c 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 a98d8eb543..0fa36d3a4a 100644 --- a/src/os/windows/crashlog_win.cpp +++ b/src/os/windows/crashlog_win.cpp @@ -231,7 +231,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, @@ -579,7 +579,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; @@ -810,7 +810,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; @@ -825,19 +826,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))) + 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); - _snwprintf(text, len, _crash_desc, OTTD2FS(CrashLogWindows::current->crashlog_filename)); - if (_settings_client.gui.developer > 0 && 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))); + 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 (_settings_client.gui.developer > 0 && convert_to_fs(CrashLogWindows::current->crashdump_filename, filenamebuf, lengthof(filenamebuf))[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))[0] != L'\0') { + wcscat(text, L"\n"); + wcscat(text, filenamebuf); } SetDlgItemText(wnd, 10, text); @@ -853,11 +858,13 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA case 13: // Emergency save _savegame_DBGL_data = CrashLogWindows::current->crashlog; _save_DBGC_data = true; + wchar_t filenamebuf[MAX_PATH * 2]; char filename[MAX_PATH]; if (CrashLogWindows::current->WriteSavegame(filename, lastof(filename), CrashLogWindows::current->name_buffer)) { - size_t len = wcslen(_save_succeeded) + wcslen(OTTD2FS(filename)) + 1; + 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, 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); @@ -866,7 +873,7 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA _save_DBGC_data = false; 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 0f61219c4d..fac366f8bf 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() @@ -440,7 +441,7 @@ void Win32FontCache::SetFontSize(FontSize fs, int pixels) font_height_cache[this->fs] = this->GetHeight(); - 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); } /** @@ -499,7 +500,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) { @@ -543,10 +544,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 }; @@ -607,12 +608,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)); } } @@ -650,7 +651,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/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 3746dd4f33..9c553fa757 100644 --- a/src/os/windows/win32.cpp +++ b/src/os/windows/win32.cpp @@ -63,7 +63,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 (;;) { @@ -83,12 +83,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 @@ -147,14 +147,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 @@ -252,7 +252,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 @@ -422,7 +422,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(); @@ -560,34 +560,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) { - static TCHAR 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)); } @@ -601,10 +607,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; @@ -621,7 +625,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'; @@ -632,9 +636,12 @@ wchar_t *convert_to_fs(const char *name, wchar_t *system_buf, size_t buflen, boo /** 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; } diff --git a/src/os/windows/win32.h b/src/os/windows/win32.h index 542e308a82..3c9c16d4d4 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__) && !(_WIN32_IE >= 0x0500) #define SHGFP_TYPE_CURRENT 0 diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index fda811aeb1..1e8ab4f35e 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1674,7 +1674,7 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE); AddTrackToSignalBuffer(tile, track, _current_company); YapfNotifyTrackLayoutChange(tile, track); - if (v != nullptr) { + if (v != nullptr && v->track != TRACK_BIT_DEPOT) { ReReserveTrainPath(v); } } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index ab55be6810..16182ca902 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" @@ -36,6 +37,7 @@ #include "fontcache.h" #include "zoom_func.h" #include "video/video_driver.hpp" +#include "music/music_driver.hpp" #include #include @@ -338,6 +340,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; } } @@ -390,6 +400,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); @@ -444,6 +464,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); @@ -651,9 +684,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), @@ -664,9 +698,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/stdafx.h b/src/stdafx.h index ee4f1bf3e1..a6384320da 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) @@ -248,25 +249,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); +# 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 0c3dd5f379..cb9be4721d 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -674,6 +674,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; } } @@ -2253,14 +2259,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/table/settings.ini b/src/table/settings.ini index caab744427..7762bac612 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -5583,7 +5583,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 @@ -5593,7 +5593,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 diff --git a/src/table/strgen_tables.h b/src/table/strgen_tables.h index 569f9b03f1..de3b96c114 100644 --- a/src/table/strgen_tables.h +++ b/src/table/strgen_tables.h @@ -190,6 +190,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: diff --git a/src/video/opengl.cpp b/src/video/opengl.cpp index 75bb0a6d82..c1c1afaaec 100644 --- a/src/video/opengl.cpp +++ b/src/video/opengl.cpp @@ -1074,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; diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 62167b1f35..17eead90b9 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -215,7 +215,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); } @@ -332,7 +332,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); @@ -553,14 +553,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? */ @@ -569,21 +561,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 diff --git a/src/viewport.cpp b/src/viewport.cpp index 69d00396bd..49c2dee67b 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -4619,7 +4619,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/widget_type.h b/src/widget_type.h index a17811511c..89dd9f93a0 100644 --- a/src/widget_type.h +++ b/src/widget_type.h @@ -170,6 +170,16 @@ public: virtual void FillDirtyWidgets(std::vector &dirty_widgets) = 0; virtual void SetDirty(Window *w); + 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. WidgetBaseFlags base_flags; ///< Widget base flags uint fill_x; ///< Horizontal fill stepsize (from initial size, \c 0 means not resizable). diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt index 0d4a85de33..5fe8ffa44a 100644 --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -46,6 +46,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/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. 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 */ diff --git a/src/window.cpp b/src/window.cpp index 6f8c0523de..186b13dd47 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1185,8 +1185,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; } }