Changeset - r18941:8b8e5486e2f8
[Not reviewed]
master
0 4 0
frosch - 13 years ago 2012-01-15 15:49:01
frosch@openttd.org
(svn r23805) -Add: {STRING6} and {STRING7}.
4 files changed with 17 insertions and 44 deletions:
0 comments (0 inline, 0 general)
src/strgen/strgen_base.cpp
Show inline comments
 
@@ -582,96 +582,98 @@ StringReader::StringReader(StringData &d
 
StringReader::~StringReader()
 
{
 
	free(file);
 
}
 

	
 
static void ExtractCommandString(ParsedCommandStruct *p, const char *s, bool warnings)
 
{
 
	char param[MAX_COMMAND_PARAM_SIZE];
 
	int argno;
 
	int argidx = 0;
 
	int casei;
 

	
 
	memset(p, 0, sizeof(*p));
 

	
 
	for (;;) {
 
		/* read until next command from a. */
 
		const CmdStruct *ar = ParseCommandString(&s, param, &argno, &casei);
 

	
 
		if (ar == NULL) break;
 

	
 
		/* Sanity checking */
 
		if (argno != -1 && ar->consumes == 0) strgen_fatal("Non consumer param can't have a paramindex");
 

	
 
		if (ar->consumes) {
 
			if (argno != -1) argidx = argno;
 
			if (argidx < 0 || (uint)argidx >= lengthof(p->cmd)) strgen_fatal("invalid param idx %d", argidx);
 
			if (p->cmd[argidx] != NULL && p->cmd[argidx] != ar) strgen_fatal("duplicate param idx %d", argidx);
 

	
 
			p->cmd[argidx++] = ar;
 
		} else if (!(ar->flags & C_DONTCOUNT)) { // Ignore some of them
 
			if (p->np >= lengthof(p->pairs)) strgen_fatal("too many commands in string, max " PRINTF_SIZE, lengthof(p->pairs));
 
			p->pairs[p->np].a = ar;
 
			p->pairs[p->np].v = param[0] != '\0' ? strdup(param) : "";
 
			p->np++;
 
		}
 
	}
 
}
 

	
 

	
 
static const CmdStruct *TranslateCmdForCompare(const CmdStruct *a)
 
{
 
	if (a == NULL) return NULL;
 

	
 
	if (strcmp(a->cmd, "STRING1") == 0 ||
 
			strcmp(a->cmd, "STRING2") == 0 ||
 
			strcmp(a->cmd, "STRING3") == 0 ||
 
			strcmp(a->cmd, "STRING4") == 0 ||
 
			strcmp(a->cmd, "STRING5") == 0 ||
 
			strcmp(a->cmd, "STRING6") == 0 ||
 
			strcmp(a->cmd, "STRING7") == 0 ||
 
			strcmp(a->cmd, "RAW_STRING") == 0) {
 
		return FindCmd("STRING", 6);
 
	}
 

	
 
	return a;
 
}
 

	
 

	
 
static bool CheckCommandsMatch(char *a, char *b, const char *name)
 
{
 
	/* If we're not translating, i.e. we're compiling the base language,
 
	 * it is pointless to do all these checks as it'll always be correct.
 
	 * After all, all checks are based on the base language.
 
	 */
 
	if (!_translation) return true;
 

	
 
	ParsedCommandStruct templ;
 
	ParsedCommandStruct lang;
 
	bool result = true;
 

	
 
	ExtractCommandString(&templ, b, true);
 
	ExtractCommandString(&lang, a, true);
 

	
 
	/* For each string in templ, see if we find it in lang */
 
	if (templ.np != lang.np) {
 
		strgen_warning("%s: template string and language string have a different # of commands", name);
 
		result = false;
 
	}
 

	
 
	for (uint i = 0; i < templ.np; i++) {
 
		/* see if we find it in lang, and zero it out */
 
		bool found = false;
 
		for (uint j = 0; j < lang.np; j++) {
 
			if (templ.pairs[i].a == lang.pairs[j].a &&
 
					strcmp(templ.pairs[i].v, lang.pairs[j].v) == 0) {
 
				/* it was found in both. zero it out from lang so we don't find it again */
 
				lang.pairs[j].a = NULL;
 
				found = true;
 
				break;
 
			}
 
		}
 

	
 
		if (!found) {
 
			strgen_warning("%s: command '%s' exists in template file but not in language file", name, templ.pairs[i].a->cmd);
 
			result = false;
 
		}
 
	}
 

	
src/strings.cpp
Show inline comments
 
@@ -923,141 +923,107 @@ static char *FormatString(char *buff, co
 
					num--;
 
				}
 
				break;
 
			}
 

	
 
			case SCC_SETX: // {SETX}
 
				if (buff + Utf8CharLen(SCC_SETX) + 1 < last) {
 
					buff += Utf8Encode(buff, SCC_SETX);
 
					*buff++ = *str++;
 
				}
 
				break;
 

	
 
			case SCC_SETXY: // {SETXY}
 
				if (buff + Utf8CharLen(SCC_SETXY) + 2 < last) {
 
					buff += Utf8Encode(buff, SCC_SETXY);
 
					*buff++ = *str++;
 
					*buff++ = *str++;
 
				}
 
				break;
 

	
 
			case SCC_REVISION: // {REV}
 
				buff = strecpy(buff, _openttd_revision, last);
 
				break;
 

	
 
			case SCC_STRING_ID: // {STRINL}
 
				if (game_script) break;
 
				buff = GetStringWithArgs(buff, Utf8Consume(&str), args, last);
 
				break;
 

	
 
			case SCC_RAW_STRING_POINTER: { // {RAW_STRING}
 
				if (game_script) break;
 
				const char *str = (const char *)(size_t)args->GetInt64(SCC_RAW_STRING_POINTER);
 
				buff = FormatString(buff, str, args, last);
 
				break;
 
			}
 

	
 
			case SCC_STRING: {// {STRING}
 
				StringID str = args->GetInt32(SCC_STRING);
 
				if (game_script && GB(str, TAB_COUNT_OFFSET, TAB_COUNT_BITS) != GAME_TEXT_TAB) break;
 
				/* WARNING. It's prohibited for the included string to consume any arguments.
 
				 * For included strings that consume argument, you should use STRING1, STRING2 etc.
 
				 * To debug stuff you can set argv to NULL and it will tell you */
 
				StringParameters tmp_params(args->GetDataPointer(), args->num_param - args->offset, NULL);
 
				buff = GetStringWithArgs(buff, str, &tmp_params, last, next_substr_case_index, game_script);
 
				next_substr_case_index = 0;
 
				break;
 
			}
 

	
 
			case SCC_STRING1: { // {STRING1}
 
				/* String that consumes ONE argument */
 
				StringID str = args->GetInt32(SCC_STRING1);
 
				if (game_script && GB(str, TAB_COUNT_OFFSET, TAB_COUNT_BITS) != GAME_TEXT_TAB) break;
 
				StringParameters sub_args(*args, 1);
 
				buff = GetStringWithArgs(buff, str, &sub_args, last, next_substr_case_index, game_script);
 
				next_substr_case_index = 0;
 
				break;
 
			}
 

	
 
			case SCC_STRING2: { // {STRING2}
 
				/* String that consumes TWO arguments */
 
				StringID str = args->GetInt32(SCC_STRING2);
 
			case SCC_STRING1:
 
			case SCC_STRING2:
 
			case SCC_STRING3:
 
			case SCC_STRING4:
 
			case SCC_STRING5:
 
			case SCC_STRING6:
 
			case SCC_STRING7: { // {STRING1..7}
 
				/* Strings that consume arguments */
 
				StringID str = args->GetInt32(b);
 
				if (game_script && GB(str, TAB_COUNT_OFFSET, TAB_COUNT_BITS) != GAME_TEXT_TAB) break;
 
				StringParameters sub_args(*args, 2);
 
				buff = GetStringWithArgs(buff, str, &sub_args, last, next_substr_case_index, game_script);
 
				next_substr_case_index = 0;
 
				break;
 
			}
 

	
 
			case SCC_STRING3: { // {STRING3}
 
				/* String that consumes THREE arguments */
 
				StringID str = args->GetInt32(SCC_STRING3);
 
				if (game_script && GB(str, TAB_COUNT_OFFSET, TAB_COUNT_BITS) != GAME_TEXT_TAB) break;
 
				StringParameters sub_args(*args, 3);
 
				buff = GetStringWithArgs(buff, str, &sub_args, last, next_substr_case_index, game_script);
 
				next_substr_case_index = 0;
 
				break;
 
			}
 

	
 
			case SCC_STRING4: { // {STRING4}
 
				/* String that consumes FOUR arguments */
 
				StringID str = args->GetInt32(SCC_STRING4);
 
				if (game_script && GB(str, TAB_COUNT_OFFSET, TAB_COUNT_BITS) != GAME_TEXT_TAB) break;
 
				StringParameters sub_args(*args, 4);
 
				buff = GetStringWithArgs(buff, str, &sub_args, last, next_substr_case_index, game_script);
 
				next_substr_case_index = 0;
 
				break;
 
			}
 

	
 
			case SCC_STRING5: { // {STRING5}
 
				/* String that consumes FIVE arguments */
 
				StringID str = args->GetInt32(SCC_STRING5);
 
				if (game_script && GB(str, TAB_COUNT_OFFSET, TAB_COUNT_BITS) != GAME_TEXT_TAB) break;
 
				StringParameters sub_args(*args, 5);
 
				StringParameters sub_args(*args, b - SCC_STRING1 + 1);
 
				buff = GetStringWithArgs(buff, str, &sub_args, last, next_substr_case_index, game_script);
 
				next_substr_case_index = 0;
 
				break;
 
			}
 

	
 
			case SCC_COMMA: // {COMMA}
 
				buff = FormatCommaNumber(buff, args->GetInt64(SCC_COMMA), last);
 
				break;
 

	
 
			case SCC_DECIMAL: {// {DECIMAL}
 
				int64 number = args->GetInt64(SCC_DECIMAL);
 
				int digits = args->GetInt32(SCC_DECIMAL);
 
				buff = FormatCommaNumber(buff, number, last, digits);
 
				break;
 
			}
 

	
 
			case SCC_NUM: // {NUM}
 
				buff = FormatNoCommaNumber(buff, args->GetInt64(SCC_NUM), last);
 
				break;
 

	
 
			case SCC_ZEROFILL_NUM: { // {ZEROFILL_NUM}
 
				int64 num = args->GetInt64();
 
				buff = FormatZerofillNumber(buff, num, args->GetInt64(), last);
 
				break;
 
			}
 

	
 
			case SCC_HEX: // {HEX}
 
				buff = FormatHexNumber(buff, (uint64)args->GetInt64(SCC_HEX), last);
 
				break;
 

	
 
			case SCC_BYTES: // {BYTES}
 
				buff = FormatBytes(buff, args->GetInt64(), last);
 
				break;
 

	
 
			case SCC_CARGO_TINY: { // {CARGO_TINY}
 
				/* Tiny description of cargotypes. Layout:
 
				 * param 1: cargo type
 
				 * param 2: cargo count */
 
				CargoID cargo = args->GetInt32(SCC_CARGO_TINY);
 
				if (cargo >= CargoSpec::GetArraySize()) break;
 

	
 
				StringID cargo_str = CargoSpec::Get(cargo)->units_volume;
 
				int64 amount = 0;
 
				switch (cargo_str) {
 
					case STR_TONS:
 
						amount = _units[_settings_game.locale.units].c_weight.ToDisplay(args->GetInt64());
 
						break;
 

	
src/table/control_codes.h
Show inline comments
 
@@ -20,101 +20,104 @@ enum StringControlCode {
 
	SCC_CONTROL_START = 0xE000,
 
	SCC_CONTROL_END   = 0xE1FF,
 

	
 
	SCC_SPRITE_START  = 0xE200,
 
	SCC_SPRITE_END    = SCC_SPRITE_START + 0xFF,
 

	
 
	/* Display control codes */
 
	SCC_SETX = SCC_CONTROL_START,
 
	SCC_SETXY,
 
	SCC_TINYFONT,  ///< Switch to small font
 
	SCC_BIGFONT,   ///< Switch to large font
 

	
 
	/* Formatting control codes */
 
	SCC_REVISION,
 
	SCC_COMPANY_NUM,
 
	SCC_STATION_FEATURES,
 
	SCC_INDUSTRY_NAME,
 
	SCC_WAYPOINT_NAME,
 
	SCC_STATION_NAME,
 
	SCC_DEPOT_NAME,
 
	SCC_TOWN_NAME,
 
	SCC_GROUP_NAME,
 
	SCC_VEHICLE_NAME,
 
	SCC_SIGN_NAME,
 
	SCC_COMPANY_NAME,
 
	SCC_PRESIDENT_NAME,
 
	SCC_ENGINE_NAME,
 

	
 
	SCC_CURRENCY_SHORT,
 
	SCC_CURRENCY_LONG,
 

	
 
	SCC_CARGO_LONG,
 
	SCC_CARGO_SHORT,
 
	SCC_CARGO_TINY,
 
	SCC_POWER,
 
	SCC_VOLUME_LONG,
 
	SCC_VOLUME_SHORT,
 
	SCC_WEIGHT_LONG,
 
	SCC_WEIGHT_SHORT,
 
	SCC_FORCE,
 
	SCC_VELOCITY,
 
	SCC_HEIGHT,
 

	
 
	SCC_DATE_TINY,
 
	SCC_DATE_SHORT,
 
	SCC_DATE_LONG,
 
	SCC_DATE_ISO,
 

	
 
	/* Must be consecutive */
 
	SCC_STRING1,
 
	SCC_STRING2,
 
	SCC_STRING3,
 
	SCC_STRING4,
 
	SCC_STRING5,
 
	SCC_STRING6,
 
	SCC_STRING7,
 

	
 
	SCC_ENCODED,
 

	
 
	SCC_STRING,
 
	SCC_COMMA,
 
	SCC_DECIMAL,
 
	SCC_NUM,
 
	SCC_ZEROFILL_NUM,
 
	SCC_HEX,
 
	SCC_BYTES,
 

	
 
	SCC_STRING_ID,
 
	SCC_RAW_STRING_POINTER,
 
	SCC_PLURAL_LIST,
 
	SCC_GENDER_LIST,
 
	SCC_GENDER_INDEX,
 
	SCC_ARG_INDEX,
 
	SCC_SET_CASE,
 
	SCC_SWITCH_CASE,
 

	
 
	/* Colour codes */
 
	SCC_BLUE,
 
	SCC_SILVER,
 
	SCC_GOLD,
 
	SCC_RED,
 
	SCC_PURPLE,
 
	SCC_LTBROWN,
 
	SCC_ORANGE,
 
	SCC_GREEN,
 
	SCC_YELLOW,
 
	SCC_DKGREEN,
 
	SCC_CREAM,
 
	SCC_BROWN,
 
	SCC_WHITE,
 
	SCC_LTBLUE,
 
	SCC_GRAY,
 
	SCC_DKBLUE,
 
	SCC_BLACK,
 
	SCC_PREVIOUS_COLOUR,
 

	
 
	/**
 
	 * The next variables are part of a NewGRF subsystem for creating text strings.
 
	 * It uses a "stack" of bytes and reads from there.
 
	 */
 
	SCC_NEWGRF_FIRST,
 
	SCC_NEWGRF_PRINT_DWORD_SIGNED = SCC_NEWGRF_FIRST, ///< Read 4 bytes from the stack
 
	SCC_NEWGRF_PRINT_WORD_SIGNED,                     ///< Read 2 bytes from the stack as signed value
 
	SCC_NEWGRF_PRINT_BYTE_SIGNED,                     ///< Read 1 byte from the stack as signed value
src/table/strgen_tables.h
Show inline comments
 
@@ -20,96 +20,98 @@ enum CmdFlags {
 
DECLARE_ENUM_AS_BIT_SET(CmdFlags)
 

	
 
struct Buffer;
 
typedef void (*ParseCmdProc)(Buffer *buffer, char *buf, int value);
 

	
 
struct CmdStruct {
 
	const char *cmd;
 
	ParseCmdProc proc;
 
	long value;
 
	uint8 consumes;
 
	CmdFlags flags;
 
};
 

	
 
extern void EmitSingleChar(Buffer *buffer, char *buf, int value);
 
extern void EmitPlural(Buffer *buffer, char *buf, int value);
 
extern void EmitGender(Buffer *buffer, char *buf, int value);
 

	
 
static const CmdStruct _cmd_structs[] = {
 
	/* Font size */
 
	{"TINY_FONT",         EmitSingleChar, SCC_TINYFONT,           0, C_NONE},
 
	{"BIG_FONT",          EmitSingleChar, SCC_BIGFONT,            0, C_NONE},
 

	
 
	/* Colours */
 
	{"BLUE",              EmitSingleChar, SCC_BLUE,               0, C_NONE},
 
	{"SILVER",            EmitSingleChar, SCC_SILVER,             0, C_NONE},
 
	{"GOLD",              EmitSingleChar, SCC_GOLD,               0, C_NONE},
 
	{"RED",               EmitSingleChar, SCC_RED,                0, C_NONE},
 
	{"PURPLE",            EmitSingleChar, SCC_PURPLE,             0, C_NONE},
 
	{"LTBROWN",           EmitSingleChar, SCC_LTBROWN,            0, C_NONE},
 
	{"ORANGE",            EmitSingleChar, SCC_ORANGE,             0, C_NONE},
 
	{"GREEN",             EmitSingleChar, SCC_GREEN,              0, C_NONE},
 
	{"YELLOW",            EmitSingleChar, SCC_YELLOW,             0, C_NONE},
 
	{"DKGREEN",           EmitSingleChar, SCC_DKGREEN,            0, C_NONE},
 
	{"CREAM",             EmitSingleChar, SCC_CREAM,              0, C_NONE},
 
	{"BROWN",             EmitSingleChar, SCC_BROWN,              0, C_NONE},
 
	{"WHITE",             EmitSingleChar, SCC_WHITE,              0, C_NONE},
 
	{"LTBLUE",            EmitSingleChar, SCC_LTBLUE,             0, C_NONE},
 
	{"GRAY",              EmitSingleChar, SCC_GRAY,               0, C_NONE},
 
	{"DKBLUE",            EmitSingleChar, SCC_DKBLUE,             0, C_NONE},
 
	{"BLACK",             EmitSingleChar, SCC_BLACK,              0, C_NONE},
 

	
 
	{"REV",               EmitSingleChar, SCC_REVISION,           0, C_NONE}, // openttd revision string
 

	
 
	{"STRING1",           EmitSingleChar, SCC_STRING1,            2, C_CASE | C_GENDER}, // included string that consumes the string id and ONE argument
 
	{"STRING2",           EmitSingleChar, SCC_STRING2,            3, C_CASE | C_GENDER}, // included string that consumes the string id and TWO arguments
 
	{"STRING3",           EmitSingleChar, SCC_STRING3,            4, C_CASE | C_GENDER}, // included string that consumes the string id and THREE arguments
 
	{"STRING4",           EmitSingleChar, SCC_STRING4,            5, C_CASE | C_GENDER}, // included string that consumes the string id and FOUR arguments
 
	{"STRING5",           EmitSingleChar, SCC_STRING5,            6, C_CASE | C_GENDER}, // included string that consumes the string id and FIVE arguments
 
	{"STRING6",           EmitSingleChar, SCC_STRING6,            7, C_CASE | C_GENDER}, // included string that consumes the string id and SIX arguments
 
	{"STRING7",           EmitSingleChar, SCC_STRING7,            8, C_CASE | C_GENDER}, // included string that consumes the string id and SEVEN arguments
 

	
 
	{"STATION_FEATURES",  EmitSingleChar, SCC_STATION_FEATURES,   1, C_NONE}, // station features string, icons of the features
 
	{"INDUSTRY",          EmitSingleChar, SCC_INDUSTRY_NAME,      1, C_CASE | C_GENDER}, // industry, takes an industry #, can have cases
 
	{"CARGO_LONG",        EmitSingleChar, SCC_CARGO_LONG,         2, C_NONE | C_GENDER},
 
	{"CARGO_SHORT",       EmitSingleChar, SCC_CARGO_SHORT,        2, C_NONE}, // short cargo description, only ### tons, or ### litres
 
	{"CARGO_TINY",        EmitSingleChar, SCC_CARGO_TINY,         2, C_NONE}, // tiny cargo description with only the amount, not a specifier for the amount or the actual cargo name
 
	{"POWER",             EmitSingleChar, SCC_POWER,              1, C_NONE},
 
	{"VOLUME_LONG",       EmitSingleChar, SCC_VOLUME_LONG,        1, C_NONE},
 
	{"VOLUME_SHORT",      EmitSingleChar, SCC_VOLUME_SHORT,       1, C_NONE},
 
	{"WEIGHT_LONG",       EmitSingleChar, SCC_WEIGHT_LONG,        1, C_NONE},
 
	{"WEIGHT_SHORT",      EmitSingleChar, SCC_WEIGHT_SHORT,       1, C_NONE},
 
	{"FORCE",             EmitSingleChar, SCC_FORCE,              1, C_NONE},
 
	{"VELOCITY",          EmitSingleChar, SCC_VELOCITY,           1, C_NONE},
 
	{"HEIGHT",            EmitSingleChar, SCC_HEIGHT,             1, C_NONE},
 

	
 
	{"P",                 EmitPlural,     0,                      0, C_DONTCOUNT}, // plural specifier
 
	{"G",                 EmitGender,     0,                      0, C_DONTCOUNT}, // gender specifier
 

	
 
	{"DATE_TINY",         EmitSingleChar, SCC_DATE_TINY,          1, C_NONE},
 
	{"DATE_SHORT",        EmitSingleChar, SCC_DATE_SHORT,         1, C_CASE},
 
	{"DATE_LONG",         EmitSingleChar, SCC_DATE_LONG,          1, C_CASE},
 
	{"DATE_ISO",          EmitSingleChar, SCC_DATE_ISO,           1, C_NONE},
 

	
 
	{"STRING",            EmitSingleChar, SCC_STRING,             1, C_CASE | C_GENDER},
 
	{"RAW_STRING",        EmitSingleChar, SCC_RAW_STRING_POINTER, 1, C_NONE | C_GENDER},
 

	
 
	/* Numbers */
 
	{"COMMA",             EmitSingleChar, SCC_COMMA,              1, C_NONE}, // Number with comma
 
	{"DECIMAL",           EmitSingleChar, SCC_DECIMAL,            2, C_NONE}, // Number with comma and fractional part. Second parameter is number of fractional digits, first parameter is number times 10**(second parameter).
 
	{"NUM",               EmitSingleChar, SCC_NUM,                1, C_NONE}, // Signed number
 
	{"ZEROFILL_NUM",      EmitSingleChar, SCC_ZEROFILL_NUM,       2, C_NONE}, // Unsigned number with zero fill, e.g. "02". First parameter is number, second minimum length
 
	{"BYTES",             EmitSingleChar, SCC_BYTES,              1, C_NONE}, // Unsigned number with "bytes", i.e. "1.02 MiB or 123 KiB"
 
	{"HEX",               EmitSingleChar, SCC_HEX,                1, C_NONE}, // Hexadecimally printed number
 

	
 
	{"CURRENCY_LONG",     EmitSingleChar, SCC_CURRENCY_LONG,      1, C_NONE},
 
	{"CURRENCY_SHORT",    EmitSingleChar, SCC_CURRENCY_SHORT,     1, C_NONE}, // compact currency
 

	
 
	{"WAYPOINT",          EmitSingleChar, SCC_WAYPOINT_NAME,      1, C_NONE | C_GENDER}, // waypoint name
 
	{"STATION",           EmitSingleChar, SCC_STATION_NAME,       1, C_NONE | C_GENDER},
 
	{"DEPOT",             EmitSingleChar, SCC_DEPOT_NAME,         2, C_NONE | C_GENDER},
 
	{"TOWN",              EmitSingleChar, SCC_TOWN_NAME,          1, C_NONE | C_GENDER},
 
	{"GROUP",             EmitSingleChar, SCC_GROUP_NAME,         1, C_NONE | C_GENDER},
 
	{"SIGN",              EmitSingleChar, SCC_SIGN_NAME,          1, C_NONE | C_GENDER},
 
	{"ENGINE",            EmitSingleChar, SCC_ENGINE_NAME,        1, C_NONE | C_GENDER},
 
	{"VEHICLE",           EmitSingleChar, SCC_VEHICLE_NAME,       1, C_NONE | C_GENDER},
 
	{"COMPANY",           EmitSingleChar, SCC_COMPANY_NAME,       1, C_NONE | C_GENDER},
 
	{"COMPANY_NUM",       EmitSingleChar, SCC_COMPANY_NUM,        1, C_NONE},
 
	{"PRESIDENT_NAME",    EmitSingleChar, SCC_PRESIDENT_NAME,     1, C_NONE | C_GENDER},
0 comments (0 inline, 0 general)