From 8aba642ed5bbad969b56bf5b72834ad04599d296 Mon Sep 17 00:00:00 2001 From: rubidium Date: Sat, 13 Nov 2010 12:09:30 +0000 Subject: [PATCH] (svn r21164) -Codechange: replace the hardcoded array of language metadata with a list --- src/language.h | 8 ++++++ src/settings_gui.cpp | 10 ++++---- src/strings.cpp | 60 +++++++++++++++++--------------------------- src/strings_func.h | 1 - src/strings_type.h | 9 ------- 5 files changed, 36 insertions(+), 52 deletions(-) diff --git a/src/language.h b/src/language.h index 84e9fa9b96..6a208ab929 100644 --- a/src/language.h +++ b/src/language.h @@ -12,6 +12,8 @@ #ifndef LANGUAGE_H #define LANGUAGE_H +#include "core/smallvec_type.hpp" + /** Header of a language file. */ struct LanguagePackHeader { static const uint32 IDENT = 0x474E414C; ///< Identifier for OpenTTD language files, big endian for "LANG" @@ -56,6 +58,12 @@ struct LanguageMetadata : public LanguagePackHeader { char file[MAX_PATH]; ///< Name of the file we read this data from. }; +/** Type for the list of language meta data. */ +typedef SmallVector LanguageList; + +/** The actual list of language meta data. */ +extern LanguageList _languages; + /** The currently loaded language. */ extern const LanguageMetadata *_current_language; diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 24f73bd715..6d68812344 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -316,9 +316,9 @@ struct GameOptionsWindow : Window { /* Sort language names */ LangList langs; - int current_lang; - for (int i = 0; i < _dynlang.num; i++) { - if (&_dynlang.ent[i] == _current_language) current_lang = i; + int current_lang = 0; + for (size_t i = 0; i < _languages.Length(); i++) { + if (&_languages[i] == _current_language) current_lang = i; langs[SPECSTR_LANGUAGE_START + i] = i; } @@ -418,7 +418,7 @@ struct GameOptionsWindow : Window { break; case GOW_LANG_DROPDOWN: // Change interface language - ReadLanguagePack(&_dynlang.ent[index]); + ReadLanguagePack(&_languages[index]); CheckForMissingGlyphsInLoadedLanguagePack(); UpdateAllVirtCoords(); ReInitAllWindows(); @@ -495,7 +495,7 @@ static const NWidgetPart _nested_game_options_widgets[] = { NWidget(WWT_DROPDOWN, COLOUR_GREY, GOW_TOWNNAME_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP), SetFill(1, 0), EndContainer(), NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_LANGUAGE, STR_NULL), - NWidget(WWT_DROPDOWN, COLOUR_GREY, GOW_LANG_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_LANGUAGE_TOOLTIP), SetFill(1, 0), + NWidget(WWT_DROPDOWN, COLOUR_GREY, GOW_LANG_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_LANGUAGE_TOOLTIP), SetFill(1, 0), EndContainer(), NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_SCREENSHOT_FORMAT, STR_NULL), NWidget(WWT_DROPDOWN, COLOUR_GREY, GOW_SCREENSHOT_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_SCREENSHOT_FORMAT_TOOLTIP), SetFill(1, 0), diff --git a/src/strings.cpp b/src/strings.cpp index 04d8e296eb..9bab8cb725 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -41,9 +41,9 @@ #include "table/control_codes.h" char _config_language_file[MAX_PATH]; ///< The file (name) stored in the configuration. +LanguageList _languages; ///< The actual list of language meta data. const LanguageMetadata *_current_language = NULL; ///< The currently loaded language. -DynamicLanguages _dynlang; ///< Language information of the program. TextDirection _current_text_dir; ///< Text direction of the currently selected language. uint64 _decode_parameters[20]; ///< Global array of string parameters. To access, use #SetDParam. @@ -1280,7 +1280,7 @@ static char *GetSpecialNameString(char *buff, int ind, int64 *argv, const char * if (IsInsideMM(ind, (SPECSTR_LANGUAGE_START - 0x70E4), (SPECSTR_LANGUAGE_END - 0x70E4) + 1)) { int i = ind - (SPECSTR_LANGUAGE_START - 0x70E4); return strecpy(buff, - &_dynlang.ent[i] == _current_language ? _current_language->own_name : _dynlang.ent[i].name, last); + &_languages[i] == _current_language ? _current_language->own_name : _languages[i].name, last); } /* resolution size? */ @@ -1442,16 +1442,13 @@ int CDECL StringIDSorter(const StringID *a, const StringID *b) /** * Checks whether the given language is already found. - * @param langs languages we've found so far - * @param max the length of the language list - * @param language name of the language to check - * @return true if and only if a language file with the same name has not been found + * @param newgrflangid NewGRF languages ID to check + * @return true if and only if a language file with the same language ID has not been found */ -static bool UniqueLanguageFile(const LanguageMetadata *langs, uint max, const char *language) +static bool UniqueLanguageFile(byte newgrflangid) { - for (uint i = 0; i < max; i++) { - const char *f_name = strrchr(langs[i].file, PATHSEPCHAR) + 1; - if (strcmp(f_name, language) == 0) return false; // duplicates + for (const LanguageMetadata *lang = _languages.Begin(); lang != _languages.End(); lang++) { + if (newgrflangid == lang->newgrflangid) return false; } return true; @@ -1480,42 +1477,34 @@ static bool GetLanguageFileHeader(const char *file, LanguagePackHeader *hdr) /** * Gets a list of languages from the given directory. - * @param langs the list to write to - * @param start the initial offset in the list - * @param max the length of the language list * @param path the base directory to search in - * @return the number of added languages */ -static int GetLanguageList(LanguageMetadata *langs, int start, int max, const char *path) +static void GetLanguageList(const char *path) { - int i = start; - DIR *dir = ttd_opendir(path); if (dir != NULL) { struct dirent *dirent; - while ((dirent = readdir(dir)) != NULL && i < max) { + while ((dirent = readdir(dir)) != NULL) { const char *d_name = FS2OTTD(dirent->d_name); const char *extension = strrchr(d_name, '.'); /* Not a language file */ if (extension == NULL || strcmp(extension, ".lng") != 0) continue; - /* Filter any duplicate language-files, first-come first-serve */ - if (!UniqueLanguageFile(langs, i, d_name)) continue; - - seprintf(langs[i].file, lastof(langs[i].file), "%s%s", path, d_name); + LanguageMetadata lmd; + seprintf(lmd.file, lastof(lmd.file), "%s%s", path, d_name); /* Check whether the file is of the correct version */ - if (!GetLanguageFileHeader(langs[i].file, &langs[i])) { - DEBUG(misc, 3, "%s is not a valid language file", langs[i].file); - continue; + if (!GetLanguageFileHeader(lmd.file, &lmd)) { + DEBUG(misc, 3, "%s is not a valid language file", lmd.file); + } else if (!UniqueLanguageFile(lmd.newgrflangid)) { + DEBUG(misc, 3, "%s's language ID is already known", lmd.file); + } else { + *_languages.Append() = lmd; } - - i++; } closedir(dir); } - return i - start; } /** @@ -1525,14 +1514,13 @@ static int GetLanguageList(LanguageMetadata *langs, int start, int max, const ch void InitializeLanguagePacks() { Searchpath sp; - uint language_count = 0; FOR_ALL_SEARCHPATHS(sp) { char path[MAX_PATH]; FioAppendDirectory(path, lengthof(path), sp, LANG_DIR); - language_count += GetLanguageList(_dynlang.ent, language_count, lengthof(_dynlang.ent), path); + GetLanguageList(path); } - if (language_count == 0) usererror("No available language packs (invalid versions?)"); + if (_languages.Length() == 0) usererror("No available language packs (invalid versions?)"); /* Acquire the locale of the current system */ const char *lang = GetCurrentLocale("LC_MESSAGES"); @@ -1540,16 +1528,14 @@ void InitializeLanguagePacks() const LanguageMetadata *chosen_language = NULL; ///< Matching the language in the configuartion file or the current locale const LanguageMetadata *language_fallback = NULL; ///< Using pt_PT for pt_BR locale when pt_BR is not available - const LanguageMetadata *en_GB_fallback = _dynlang.ent; ///< Fallback when no locale-matching language has been found + const LanguageMetadata *en_GB_fallback = _languages.Begin(); ///< Fallback when no locale-matching language has been found - _dynlang.num = language_count; - /* Fill the dynamic languages structures */ - for (uint i = 0; i < language_count; i++) { - const LanguageMetadata *lng = &_dynlang.ent[i]; + /* Find a proper language. */ + for (const LanguageMetadata *lng = _languages.Begin(); lng != _languages.End(); lng++) { /* We are trying to find a default language. The priority is by * configuration file, local environment and last, if nothing found, * english. */ - const char *lang_file = strrchr(lang, PATHSEPCHAR) + 1; + const char *lang_file = strrchr(lng->file, PATHSEPCHAR) + 1; if (strcmp(lang_file, _config_language_file) == 0) { chosen_language = lng; break; diff --git a/src/strings_func.h b/src/strings_func.h index 22c1f35d9d..706dbd1f07 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -95,7 +95,6 @@ static inline void CopyOutDParam(uint64 *dst, int offs, int num) memcpy(dst, _decode_parameters + offs, sizeof(uint64) * (num)); } -extern DynamicLanguages _dynlang; // defined in strings.cpp extern TextDirection _current_text_dir; ///< Text direction of the currently selected language void InitializeLanguagePacks(); diff --git a/src/strings_type.h b/src/strings_type.h index 326be62ec1..1dea474f91 100644 --- a/src/strings_type.h +++ b/src/strings_type.h @@ -12,8 +12,6 @@ #ifndef STRINGS_TYPE_H #define STRINGS_TYPE_H -#include "language.h" - /** * Numeric value that represents a string, independent of the selected language. */ @@ -28,13 +26,6 @@ enum TextDirection { TD_RTL, ///< Text is written right-to-left by default }; -/** Used for dynamic language support */ -struct DynamicLanguages { - int num; ///< Number of languages - char curr_file[MAX_PATH]; ///< Currently selected language file name without path (needed for saving the filename of the loaded language). - LanguageMetadata ent[MAX_LANG]; ///< Information about the languages -}; - /** Special string constants */ enum SpecialStrings {