Changeset - r16434:88fcbcadb08e
[Not reviewed]
master
1 8 1
rubidium - 14 years ago 2010-11-13 11:11:02
rubidium@openttd.org
(svn r21160) -Codechange: reuse the strgen LanguageHeader to store some metadata about a language, and keep the language metadata in memory instead of loading it several times from disk
10 files changed with 91 insertions and 106 deletions:
0 comments (0 inline, 0 general)
projects/openttd_vs100.vcxproj
Show inline comments
 
@@ -453,6 +453,7 @@
 
    <ClInclude Include="..\src\ini_type.h" />
 
    <ClInclude Include="..\src\landscape.h" />
 
    <ClInclude Include="..\src\landscape_type.h" />
 
    <ClInclude Include="..\src\language.h" />
 
    <ClInclude Include="..\src\livery.h" />
 
    <ClInclude Include="..\src\map_func.h" />
 
    <ClInclude Include="..\src\map_type.h" />
 
@@ -551,7 +552,6 @@
 
    <ClInclude Include="..\src\station_type.h" />
 
    <ClInclude Include="..\src\statusbar_gui.h" />
 
    <ClInclude Include="..\src\stdafx.h" />
 
    <ClInclude Include="..\src\strgen\strgen.h" />
 
    <ClInclude Include="..\src\string_func.h" />
 
    <ClInclude Include="..\src\string_type.h" />
 
    <ClInclude Include="..\src\strings_func.h" />
projects/openttd_vs100.vcxproj.filters
Show inline comments
 
@@ -579,6 +579,9 @@
 
    <ClInclude Include="..\src\landscape_type.h">
 
      <Filter>Header Files</Filter>
 
    </ClInclude>
 
    <ClInclude Include="..\src\language.h">
 
      <Filter>Header Files</Filter>
 
    </ClInclude>
 
    <ClInclude Include="..\src\livery.h">
 
      <Filter>Header Files</Filter>
 
    </ClInclude>
 
@@ -873,9 +876,6 @@
 
    <ClInclude Include="..\src\stdafx.h">
 
      <Filter>Header Files</Filter>
 
    </ClInclude>
 
    <ClInclude Include="..\src\strgen\strgen.h">
 
      <Filter>Header Files</Filter>
 
    </ClInclude>
 
    <ClInclude Include="..\src\string_func.h">
 
      <Filter>Header Files</Filter>
 
    </ClInclude>
projects/openttd_vs80.vcproj
Show inline comments
 
@@ -1087,6 +1087,10 @@
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\language.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\livery.h"
 
				>
 
			</File>
 
@@ -1479,10 +1483,6 @@
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\strgen\strgen.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\string_func.h"
 
				>
 
			</File>
projects/openttd_vs90.vcproj
Show inline comments
 
@@ -1084,6 +1084,10 @@
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\language.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\livery.h"
 
				>
 
			</File>
 
@@ -1476,10 +1480,6 @@
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\strgen\strgen.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\string_func.h"
 
				>
 
			</File>
source.list
Show inline comments
 
@@ -186,6 +186,7 @@ industrytype.h
 
ini_type.h
 
landscape.h
 
landscape_type.h
 
language.h
 
livery.h
 
map_func.h
 
map_type.h
 
@@ -284,7 +285,6 @@ station_gui.h
 
station_type.h
 
statusbar_gui.h
 
stdafx.h
 
strgen/strgen.h
 
string_func.h
 
string_type.h
 
strings_func.h
src/language.h
Show inline comments
 
new file 100644
 
/* $Id$ */
 

	
 
/*
 
 * 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 <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file language.h Information about languages and their files. */
 

	
 
#ifndef LANGUAGE_H
 
#define LANGUAGE_H
 

	
 
/** Header of a language file. */
 
struct LanguagePackHeader {
 
	static const uint32 IDENT = 0x474E414C; ///< Identifier for OpenTTD language files, big endian for "LANG"
 

	
 
	uint32 ident;       ///< 32-bits identifier
 
	uint32 version;     ///< 32-bits of auto generated version info which is basically a hash of strings.h
 
	char name[32];      ///< the international name of this language
 
	char own_name[32];  ///< the localized name of this language
 
	char isocode[16];   ///< the ISO code for the language (not country code)
 
	uint16 offsets[32]; ///< the offsets
 

	
 
	/** Thousand separator used for anything not currencies */
 
	char digit_group_separator[8];
 
	/** Thousand separator used for currencies */
 
	char digit_group_separator_currency[8];
 
	/** Decimal separator */
 
	char digit_decimal_separator[8];
 
	byte plural_form;   ///< plural form index
 
	byte text_dir;      ///< default direction of the text
 
	/**
 
	 * Windows language ID:
 
	 * Windows cannot and will not convert isocodes to something it can use to
 
	 * determine whether a font can be used for the language or not. As a result
 
	 * of that we need to pass the language id via strgen to OpenTTD to tell
 
	 * what language it is in "Windows". The ID is the 'locale identifier' on:
 
	 *   http://msdn.microsoft.com/en-us/library/ms776294.aspx
 
	 */
 
	uint16 winlangid;   ///< windows language id
 
	uint8 newgrflangid; ///< newgrf language id
 
	byte pad[3];        ///< pad header to be a multiple of 4
 

	
 
	/**
 
	 * Check whether the header is a valid header for OpenTTD.
 
	 * @return true iff the header is deemed valid.
 
	 */
 
	bool IsValid() const;
 
};
 
assert_compile(sizeof(LanguagePackHeader) % 4 == 0);
 

	
 
/** Metadata about a single language. */
 
struct LanguageMetadata : public LanguagePackHeader {
 
	char file[MAX_PATH]; ///< Name of the file we read this data from.
 
};
 

	
 
#endif /* LANGUAGE_H */
src/strgen/strgen.cpp
Show inline comments
 
@@ -16,7 +16,7 @@
 
#include "../core/mem_func.hpp"
 
#include "../string_func.h"
 
#include "../strings_type.h"
 
#include "strgen.h"
 
#include "../language.h"
 
#include "../table/control_codes.h"
 

	
 
#include <stdarg.h>
src/strgen/strgen.h
Show inline comments
 
deleted file
src/strings.cpp
Show inline comments
 
@@ -30,7 +30,7 @@
 
#include "date_func.h"
 
#include "vehicle_base.h"
 
#include "engine_base.h"
 
#include "strgen/strgen.h"
 
#include "language.h"
 
#include "townname_func.h"
 
#include "string_func.h"
 
#include "company_base.h"
 
@@ -1439,12 +1439,12 @@ int CDECL StringIDSorter(const StringID 
 

	
 
/**
 
 * Checks whether the given language is already found.
 
 * @param langs    languages we've found so fa
 
 * @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
 
 */
 
static bool UniqueLanguageFile(const Language *langs, uint max, const char *language)
 
static bool UniqueLanguageFile(const LanguageMetadata *langs, uint max, const char *language)
 
{
 
	for (uint i = 0; i < max; i++) {
 
		const char *f_name = strrchr(langs[i].file, PATHSEPCHAR) + 1;
 
@@ -1460,7 +1460,7 @@ static bool UniqueLanguageFile(const Lan
 
 * @param hdr  the place to write the header information to
 
 * @return true if and only if the language file is of a compatible version
 
 */
 
static bool GetLanguageFileHeader(const char *file, LanguagePack *hdr)
 
static bool GetLanguageFileHeader(const char *file, LanguagePackHeader *hdr)
 
{
 
	FILE *f = fopen(file, "rb");
 
	if (f == NULL) return false;
 
@@ -1483,7 +1483,7 @@ static bool GetLanguageFileHeader(const 
 
 * @param path  the base directory to search in
 
 * @return the number of added languages
 
 */
 
static int GetLanguageList(Language *langs, int start, int max, const char *path)
 
static int GetLanguageList(LanguageMetadata *langs, int start, int max, const char *path)
 
{
 
	int i = start;
 

	
 
@@ -1500,13 +1500,11 @@ static int GetLanguageList(Language *lan
 
			/* Filter any duplicate language-files, first-come first-serve */
 
			if (!UniqueLanguageFile(langs, i, d_name)) continue;
 

	
 
			langs[i].file = str_fmt("%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 */
 
			LanguagePack hdr;
 
			if (!GetLanguageFileHeader(langs[i].file, &hdr)) {
 
			if (!GetLanguageFileHeader(langs[i].file, &langs[i])) {
 
				DEBUG(misc, 3, "%s is not a valid language file", langs[i].file);
 
				free(langs[i].file);
 
				continue;
 
			}
 

	
 
@@ -1524,13 +1522,12 @@ static int GetLanguageList(Language *lan
 
void InitializeLanguagePacks()
 
{
 
	Searchpath sp;
 
	Language files[MAX_LANG];
 
	uint language_count = 0;
 

	
 
	FOR_ALL_SEARCHPATHS(sp) {
 
		char path[MAX_PATH];
 
		FioAppendDirectory(path, lengthof(path), sp, LANG_DIR);
 
		language_count += GetLanguageList(files, language_count, lengthof(files), path);
 
		language_count += GetLanguageList(_dynlang.ent, language_count, lengthof(_dynlang.ent), path);
 
	}
 
	if (language_count == 0) usererror("No available language packs (invalid versions?)");
 

	
 
@@ -1542,41 +1539,29 @@ void InitializeLanguagePacks()
 
	int language_fallback = -1; ///< Using pt_PT for pt_BR locale when pt_BR is not available
 
	int en_GB_fallback    =  0; ///< Fallback when no locale-matching language has been found
 

	
 
	DynamicLanguages *dl = &_dynlang;
 
	dl->num = 0;
 
	_dynlang.num = language_count;
 
	/* Fill the dynamic languages structures */
 
	for (uint i = 0; i < language_count; i++) {
 
		/* File read the language header */
 
		LanguagePack hdr;
 
		if (!GetLanguageFileHeader(files[i].file, &hdr)) continue;
 

	
 
		dl->ent[dl->num].file = files[i].file;
 
		dl->ent[dl->num].name = strdup(hdr.name);
 

	
 
		/* We are trying to find a default language. The priority is by
 
		 * configuration file, local environment and last, if nothing found,
 
		 * english. If def equals -1, we have not picked a default language */
 
		const char *lang_file = strrchr(dl->ent[dl->num].file, PATHSEPCHAR) + 1;
 
		if (strcmp(lang_file, dl->curr_file) == 0) chosen_language = dl->num;
 
		const char *lang_file = strrchr(_dynlang.ent[i].file, PATHSEPCHAR) + 1;
 
		if (strcmp(lang_file, _dynlang.curr_file) == 0) chosen_language = i;
 

	
 
		if (chosen_language == -1) {
 
			if (strcmp (hdr.isocode, "en_GB") == 0) en_GB_fallback    = dl->num;
 
			if (strncmp(hdr.isocode, lang, 5) == 0) chosen_language   = dl->num;
 
			if (strncmp(hdr.isocode, lang, 2) == 0) language_fallback = dl->num;
 
			if (strcmp (_dynlang.ent[i].isocode, "en_GB") == 0) en_GB_fallback    = i;
 
			if (strncmp(_dynlang.ent[i].isocode, lang, 5) == 0) chosen_language   = i;
 
			if (strncmp(_dynlang.ent[i].isocode, lang, 2) == 0) language_fallback = i;
 
		}
 

	
 
		dl->num++;
 
	}
 

	
 
	if (dl->num == 0) usererror("Invalid version of language packs");
 

	
 
	/* We haven't found the language in the config nor the one in the locale.
 
	 * Now we set it to one of the fallback languages */
 
	if (chosen_language == -1) {
 
		chosen_language = (language_fallback != -1) ? language_fallback : en_GB_fallback;
 
	}
 

	
 
	if (!ReadLanguagePack(chosen_language)) usererror("Can't read language pack '%s'", dl->ent[chosen_language].file);
 
	if (!ReadLanguagePack(chosen_language)) usererror("Can't read language pack '%s'", _dynlang.ent[chosen_language].file);
 
}
 

	
 
/**
src/strings_type.h
Show inline comments
 
@@ -12,6 +12,8 @@
 
#ifndef STRINGS_TYPE_H
 
#define STRINGS_TYPE_H
 

	
 
#include "language.h"
 

	
 
/**
 
 * Numeric value that represents a string, independent of the selected language.
 
 */
 
@@ -26,18 +28,12 @@ enum TextDirection {
 
	TD_RTL, ///< Text is written right-to-left by default
 
};
 

	
 
/** Information about a language */
 
struct Language {
 
	char *name; ///< The internal name of the language
 
	char *file; ///< The name of the language as it appears on disk
 
};
 

	
 
/** Used for dynamic language support */
 
struct DynamicLanguages {
 
	int num;                  ///< Number of languages
 
	int curr;                 ///< Currently selected language index
 
	char curr_file[MAX_PATH]; ///< Currently selected language file name without path (needed for saving the filename of the loaded language).
 
	Language ent[MAX_LANG];   ///< Information about the languages
 
	LanguageMetadata ent[MAX_LANG]; ///< Information about the languages
 
};
 

	
 
/** Special string constants */
0 comments (0 inline, 0 general)