(svn r21164) -Codechange: replace the hardcoded array of language metadata with a list

This commit is contained in:
rubidium 2010-11-13 12:09:30 +00:00
parent 68b94e61e0
commit 8aba642ed5
5 changed files with 36 additions and 52 deletions

View File

@ -12,6 +12,8 @@
#ifndef LANGUAGE_H #ifndef LANGUAGE_H
#define LANGUAGE_H #define LANGUAGE_H
#include "core/smallvec_type.hpp"
/** Header of a language file. */ /** Header of a language file. */
struct LanguagePackHeader { struct LanguagePackHeader {
static const uint32 IDENT = 0x474E414C; ///< Identifier for OpenTTD language files, big endian for "LANG" 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. char file[MAX_PATH]; ///< Name of the file we read this data from.
}; };
/** Type for the list of language meta data. */
typedef SmallVector<LanguageMetadata, 4> LanguageList;
/** The actual list of language meta data. */
extern LanguageList _languages;
/** The currently loaded language. */ /** The currently loaded language. */
extern const LanguageMetadata *_current_language; extern const LanguageMetadata *_current_language;

View File

@ -316,9 +316,9 @@ struct GameOptionsWindow : Window {
/* Sort language names */ /* Sort language names */
LangList langs; LangList langs;
int current_lang; int current_lang = 0;
for (int i = 0; i < _dynlang.num; i++) { for (size_t i = 0; i < _languages.Length(); i++) {
if (&_dynlang.ent[i] == _current_language) current_lang = i; if (&_languages[i] == _current_language) current_lang = i;
langs[SPECSTR_LANGUAGE_START + i] = i; langs[SPECSTR_LANGUAGE_START + i] = i;
} }
@ -418,7 +418,7 @@ struct GameOptionsWindow : Window {
break; break;
case GOW_LANG_DROPDOWN: // Change interface language case GOW_LANG_DROPDOWN: // Change interface language
ReadLanguagePack(&_dynlang.ent[index]); ReadLanguagePack(&_languages[index]);
CheckForMissingGlyphsInLoadedLanguagePack(); CheckForMissingGlyphsInLoadedLanguagePack();
UpdateAllVirtCoords(); UpdateAllVirtCoords();
ReInitAllWindows(); 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), 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(), EndContainer(),
NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_LANGUAGE, STR_NULL), 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(), EndContainer(),
NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_SCREENSHOT_FORMAT, STR_NULL), 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), NWidget(WWT_DROPDOWN, COLOUR_GREY, GOW_SCREENSHOT_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_SCREENSHOT_FORMAT_TOOLTIP), SetFill(1, 0),

View File

@ -41,9 +41,9 @@
#include "table/control_codes.h" #include "table/control_codes.h"
char _config_language_file[MAX_PATH]; ///< The file (name) stored in the configuration. 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. 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. TextDirection _current_text_dir; ///< Text direction of the currently selected language.
uint64 _decode_parameters[20]; ///< Global array of string parameters. To access, use #SetDParam. 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)) { if (IsInsideMM(ind, (SPECSTR_LANGUAGE_START - 0x70E4), (SPECSTR_LANGUAGE_END - 0x70E4) + 1)) {
int i = ind - (SPECSTR_LANGUAGE_START - 0x70E4); int i = ind - (SPECSTR_LANGUAGE_START - 0x70E4);
return strecpy(buff, 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? */ /* resolution size? */
@ -1442,16 +1442,13 @@ int CDECL StringIDSorter(const StringID *a, const StringID *b)
/** /**
* Checks whether the given language is already found. * Checks whether the given language is already found.
* @param langs languages we've found so far * @param newgrflangid NewGRF languages ID to check
* @param max the length of the language list * @return true if and only if a language file with the same language ID has not been found
* @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
*/ */
static bool UniqueLanguageFile(const LanguageMetadata *langs, uint max, const char *language) static bool UniqueLanguageFile(byte newgrflangid)
{ {
for (uint i = 0; i < max; i++) { for (const LanguageMetadata *lang = _languages.Begin(); lang != _languages.End(); lang++) {
const char *f_name = strrchr(langs[i].file, PATHSEPCHAR) + 1; if (newgrflangid == lang->newgrflangid) return false;
if (strcmp(f_name, language) == 0) return false; // duplicates
} }
return true; return true;
@ -1480,42 +1477,34 @@ static bool GetLanguageFileHeader(const char *file, LanguagePackHeader *hdr)
/** /**
* Gets a list of languages from the given directory. * 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 * @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); DIR *dir = ttd_opendir(path);
if (dir != NULL) { if (dir != NULL) {
struct dirent *dirent; 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 *d_name = FS2OTTD(dirent->d_name);
const char *extension = strrchr(d_name, '.'); const char *extension = strrchr(d_name, '.');
/* Not a language file */ /* Not a language file */
if (extension == NULL || strcmp(extension, ".lng") != 0) continue; if (extension == NULL || strcmp(extension, ".lng") != 0) continue;
/* Filter any duplicate language-files, first-come first-serve */ LanguageMetadata lmd;
if (!UniqueLanguageFile(langs, i, d_name)) continue; seprintf(lmd.file, lastof(lmd.file), "%s%s", path, d_name);
seprintf(langs[i].file, lastof(langs[i].file), "%s%s", path, d_name);
/* Check whether the file is of the correct version */ /* Check whether the file is of the correct version */
if (!GetLanguageFileHeader(langs[i].file, &langs[i])) { if (!GetLanguageFileHeader(lmd.file, &lmd)) {
DEBUG(misc, 3, "%s is not a valid language file", langs[i].file); DEBUG(misc, 3, "%s is not a valid language file", lmd.file);
continue; } else if (!UniqueLanguageFile(lmd.newgrflangid)) {
DEBUG(misc, 3, "%s's language ID is already known", lmd.file);
} else {
*_languages.Append() = lmd;
} }
i++;
} }
closedir(dir); closedir(dir);
} }
return i - start;
} }
/** /**
@ -1525,14 +1514,13 @@ static int GetLanguageList(LanguageMetadata *langs, int start, int max, const ch
void InitializeLanguagePacks() void InitializeLanguagePacks()
{ {
Searchpath sp; Searchpath sp;
uint language_count = 0;
FOR_ALL_SEARCHPATHS(sp) { FOR_ALL_SEARCHPATHS(sp) {
char path[MAX_PATH]; char path[MAX_PATH];
FioAppendDirectory(path, lengthof(path), sp, LANG_DIR); 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 */ /* Acquire the locale of the current system */
const char *lang = GetCurrentLocale("LC_MESSAGES"); 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 *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 *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; /* Find a proper language. */
/* Fill the dynamic languages structures */ for (const LanguageMetadata *lng = _languages.Begin(); lng != _languages.End(); lng++) {
for (uint i = 0; i < language_count; i++) {
const LanguageMetadata *lng = &_dynlang.ent[i];
/* We are trying to find a default language. The priority is by /* We are trying to find a default language. The priority is by
* configuration file, local environment and last, if nothing found, * configuration file, local environment and last, if nothing found,
* english. */ * 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) { if (strcmp(lang_file, _config_language_file) == 0) {
chosen_language = lng; chosen_language = lng;
break; break;

View File

@ -95,7 +95,6 @@ static inline void CopyOutDParam(uint64 *dst, int offs, int num)
memcpy(dst, _decode_parameters + offs, sizeof(uint64) * (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 extern TextDirection _current_text_dir; ///< Text direction of the currently selected language
void InitializeLanguagePacks(); void InitializeLanguagePacks();

View File

@ -12,8 +12,6 @@
#ifndef STRINGS_TYPE_H #ifndef STRINGS_TYPE_H
#define STRINGS_TYPE_H #define STRINGS_TYPE_H
#include "language.h"
/** /**
* Numeric value that represents a string, independent of the selected language. * 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 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 */ /** Special string constants */
enum SpecialStrings { enum SpecialStrings {