changeset 16448:a94bb23bd67b draft

(svn r21164) -Codechange: replace the hardcoded array of language metadata with a list
author rubidium <rubidium@openttd.org>
date Sat, 13 Nov 2010 12:09:30 +0000
parents f8144bcc795c
children 27dc2b916134
files src/language.h src/settings_gui.cpp src/strings.cpp src/strings_func.h src/strings_type.h
diffstat 5 files changed, 36 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- 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 @@
 	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. */
 extern const LanguageMetadata *_current_language;
 
--- a/src/settings_gui.cpp
+++ b/src/settings_gui.cpp
@@ -316,9 +316,9 @@
 
 				/* 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 @@
 				break;
 
 			case GOW_LANG_DROPDOWN: // Change interface language
-				ReadLanguagePack(&_dynlang.ent[index]);
+				ReadLanguagePack(&_languages[index]);
 				CheckForMissingGlyphsInLoadedLanguagePack();
 				UpdateAllVirtCoords();
 				ReInitAllWindows();
@@ -495,7 +495,7 @@
 					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),
--- 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 @@
 	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 @@
 
 /**
  * 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 @@
 
 /**
  * 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 @@
 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 @@
 
 	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;
--- a/src/strings_func.h
+++ b/src/strings_func.h
@@ -95,7 +95,6 @@
 	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();
--- 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 @@
 	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 {