strings.c
changeset 1321 938ec22ae6f7
parent 1319 cd302ee91e27
child 1376 425781645fba
equal deleted inserted replaced
1320:bf9623526d71 1321:938ec22ae6f7
    30 static char **_langpack_offs;
    30 static char **_langpack_offs;
    31 static LanguagePack *_langpack;
    31 static LanguagePack *_langpack;
    32 static uint _langtab_num[32]; // Offset into langpack offs
    32 static uint _langtab_num[32]; // Offset into langpack offs
    33 static uint _langtab_start[32]; // Offset into langpack offs
    33 static uint _langtab_start[32]; // Offset into langpack offs
    34 
    34 
    35 const uint16 _currency_string_list[] = {
    35 const StringID _currency_string_list[] = {
    36 	STR_CURR_GBP,
    36 	STR_CURR_GBP,
    37 	STR_CURR_USD,
    37 	STR_CURR_USD,
    38 	STR_CURR_EUR,
    38 	STR_CURR_EUR,
    39 	STR_CURR_YEN,
    39 	STR_CURR_YEN,
    40 	STR_CURR_ATS,
    40 	STR_CURR_ATS,
    58 	STR_CURR_SEK,
    58 	STR_CURR_SEK,
    59 	STR_CURR_CUSTOM,
    59 	STR_CURR_CUSTOM,
    60 	INVALID_STRING_ID
    60 	INVALID_STRING_ID
    61 };
    61 };
    62 
    62 
    63 static const uint16 _cargo_string_list[NUM_LANDSCAPE][NUM_CARGO] = {
    63 static const StringID _cargo_string_list[NUM_LANDSCAPE][NUM_CARGO] = {
    64 	{ /* LT_NORMAL */
    64 	{ /* LT_NORMAL */
    65 		STR_PASSENGERS,
    65 		STR_PASSENGERS,
    66 		STR_TONS,
    66 		STR_TONS,
    67 		STR_BAGS,
    67 		STR_BAGS,
    68 		STR_LITERS,
    68 		STR_LITERS,
   126 {
   126 {
   127 	while ((*dst++ = *src++) != '\0') {}
   127 	while ((*dst++ = *src++) != '\0') {}
   128 	return dst - 1;
   128 	return dst - 1;
   129 }
   129 }
   130 
   130 
   131 static const char *GetStringPtr(uint16 string)
   131 static const char *GetStringPtr(StringID string)
   132 {
   132 {
   133 	return _langpack_offs[_langtab_start[string >> 11] + (string & 0x7FF)];
   133 	return _langpack_offs[_langtab_start[string >> 11] + (string & 0x7FF)];
   134 }
   134 }
   135 
   135 
   136 char *GetString(char *buffr, uint16 string)
   136 char *GetString(char *buffr, StringID string)
   137 {
   137 {
   138 	uint index = string & 0x7FF;
   138 	uint index = string & 0x7FF;
   139 	uint tab = string >> 11;
   139 	uint tab = string >> 11;
   140 
   140 
   141 	if (string == 0) error("!invalid string id 0 in GetString");
   141 	switch (string) {
   142 
   142 		case 0:
   143 	if (tab == 4 && index >= 0xC0)
   143 			error("!invalid string id 0 in GetString");
   144 		return GetSpecialTownNameString(buffr, index - 0xC0);
   144 			break;
   145 
   145 
   146 	if (tab == 6 && index == 0xD1)
   146 		case 0x30D1:
   147 		return StationGetSpecialString(buffr);
   147 			return StationGetSpecialString(buffr);
   148 
   148 
   149 	if (tab == 14 && index >= 0xE4)
   149 		case STR_SPEC_SCREENSHOT_NAME:
   150 		return GetSpecialPlayerNameString(buffr, index - 0xE4);
   150 			return DecodeString(buffr, _screenshot_name);
   151 
   151 	}
   152 	if (tab == 15)
   152 
   153 		return GetName(index, buffr);
   153 	switch (tab) {
   154 
   154 		case 4:
   155 	// tab 31 is used for special or dynamic strings
   155 			if (index >= 0xC0) return GetSpecialTownNameString(buffr, index - 0xC0);
   156 	if (tab == 31) {
   156 			break;
   157 		return DecodeString(buffr, index == (STR_SPEC_SCREENSHOT_NAME & 0x7FF) ? _screenshot_name : _userstring);
   157 
       
   158 		case 14:
       
   159 			if (index >= 0xE4) return GetSpecialPlayerNameString(buffr, index - 0xE4);
       
   160 			break;
       
   161 
       
   162 		case 15:
       
   163 			return GetName(index, buffr);
       
   164 
       
   165 		case 31: // special or dynamic strings
       
   166 			return DecodeString(buffr, _userstring);
       
   167 
       
   168 		default:
       
   169 			break;
   158 	}
   170 	}
   159 
   171 
   160 	if (index >= _langtab_num[tab])
   172 	if (index >= _langtab_num[tab])
   161 		error("!String 0x%X is invalid. Probably because an old version of the .lng file.\n", string);
   173 		error(
       
   174 			"!String 0x%X is invalid. "
       
   175 			"Probably because an old version of the .lng file.\n", string
       
   176 		);
   162 
   177 
   163 	return DecodeString(buffr, GetStringPtr(string));
   178 	return DecodeString(buffr, GetStringPtr(string));
   164 }
   179 }
   165 
   180 
   166 void InjectDParam(int amount)
   181 void InjectDParam(int amount)
   452 			case 3: { /* {SHORTCARGO} */
   467 			case 3: { /* {SHORTCARGO} */
   453 				// Short description of cargotypes. Layout:
   468 				// Short description of cargotypes. Layout:
   454 				// 8-bit = cargo type
   469 				// 8-bit = cargo type
   455 				// 16-bit = cargo count
   470 				// 16-bit = cargo count
   456 				const char *s;
   471 				const char *s;
   457 				uint16 cargo_str = _cargo_string_list[_opt.landscape][(byte)GetParamInt8()];
   472 				StringID cargo_str = _cargo_string_list[_opt.landscape][(byte)GetParamInt8()];
   458 				uint16 multiplier = (cargo_str == STR_LITERS) ? 1000 : 1;
   473 				uint16 multiplier = (cargo_str == STR_LITERS) ? 1000 : 1;
   459 				// liquid type of cargo is multiplied by 100 to get correct amount
   474 				// liquid type of cargo is multiplied by 100 to get correct amount
   460 				buff = FormatCommaNumber(buff, GetParamInt16() * multiplier);
   475 				buff = FormatCommaNumber(buff, GetParamInt16() * multiplier);
   461 				s = GetStringPtr(cargo_str);
   476 				s = GetStringPtr(cargo_str);
   462 
   477 
   649 	"Sneaky",
   664 	"Sneaky",
   650 	"Nutkins",
   665 	"Nutkins",
   651 };
   666 };
   652 
   667 
   653 static const char _initial_name_letters[] = {
   668 static const char _initial_name_letters[] = {
   654 	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W',
   669 	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
       
   670 	'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W',
   655 };
   671 };
   656 
   672 
   657 static char *GenAndCoName(char *buff)
   673 static char *GenAndCoName(char *buff)
   658 {
   674 {
   659 	uint32 x = GetParamInt32();
   675 	uint32 x = GetParamInt32();
   728 };
   744 };
   729 
   745 
   730 static char *GetSpecialPlayerNameString(char *buff, int ind)
   746 static char *GetSpecialPlayerNameString(char *buff, int ind)
   731 {
   747 {
   732 	switch (ind) {
   748 	switch (ind) {
   733 	// not used
   749 		case 1: // not used
   734 	case 1: {
   750 			return str_cat(buff, _silly_company_names[GetParamInt32() & 0xFFFF]);
   735 		int i = GetParamInt32() & 0xFFFF;
   751 
   736 		return str_cat(buff, _silly_company_names[i]);
   752 		case 2: // used for Foobar & Co company names
   737 	}
   753 			return GenAndCoName(buff);
   738 
   754 
   739 	case 2: // used for Foobar & Co company names
   755 		case 3: // President name
   740 		return GenAndCoName(buff);
   756 			return GenPlayerName_4(buff);
   741 
   757 
   742 	case 3: // President name
   758 		case 4: // song names
   743 		return GenPlayerName_4(buff);
   759 			return str_cat(buff, _song_names[GetParamUint16() - 1]);
   744 
       
   745 	// song names
       
   746 	case 4: {
       
   747 		const char *song = _song_names[GetParamUint16() - 1];
       
   748 		return str_cat(buff, song);
       
   749 	}
       
   750 	}
   760 	}
   751 
   761 
   752 	// town name?
   762 	// town name?
   753 	if (IS_INT_INSIDE(ind - 6, 0, SPECSTR_TOWNNAME_LAST-SPECSTR_TOWNNAME_START + 1)) {
   763 	if (IS_INT_INSIDE(ind - 6, 0, SPECSTR_TOWNNAME_LAST-SPECSTR_TOWNNAME_START + 1)) {
   754 		buff = GetSpecialTownNameString(buff, ind - 6);
   764 		buff = GetSpecialTownNameString(buff, ind - 6);
   778 }
   788 }
   779 
   789 
   780 // remap a string ID from the old format to the new format
   790 // remap a string ID from the old format to the new format
   781 StringID RemapOldStringID(StringID s)
   791 StringID RemapOldStringID(StringID s)
   782 {
   792 {
   783 	if (s == 0x7000) s = STR_SV_UNNAMED;
   793 	switch (s) {
   784 	else if (s == 0x0006) s = STR_SV_EMPTY;
   794 		case 0x0006: return STR_SV_EMPTY;
   785 	else if (s == 0x8864) s = STR_SV_TRAIN_NAME;
   795 		case 0x7000: return STR_SV_UNNAMED;
   786 	else if (s == 0x902B) s = STR_SV_ROADVEH_NAME;
   796 		case 0x70E4: return SPECSTR_PLAYERNAME_ENGLISH;
   787 	else if (s == 0x9830) s = STR_SV_SHIP_NAME;
   797 		case 0x70E9: return SPECSTR_PLAYERNAME_ENGLISH;
   788 	else if (s == 0xA02F) s = STR_SV_AIRCRAFT_NAME;
   798 		case 0x8864: return STR_SV_TRAIN_NAME;
   789 	else if (IS_INT_INSIDE(s, 0x300F, 0x3030)) s = s - 0x300F + STR_SV_STNAME;
   799 		case 0x902B: return STR_SV_ROADVEH_NAME;
   790 	else if (s == 0x70E4 || s == 0x70E9) s = SPECSTR_PLAYERNAME_ENGLISH;
   800 		case 0x9830: return STR_SV_SHIP_NAME;
   791 	return s;
   801 		case 0xA02F: return STR_SV_AIRCRAFT_NAME;
       
   802 
       
   803 		default:
       
   804 			if (IS_INT_INSIDE(s, 0x300F, 0x3030))
       
   805 				return s - 0x300F + STR_SV_STNAME;
       
   806 			else
       
   807 				return s;
       
   808 	}
   792 }
   809 }
   793 
   810 
   794 bool ReadLanguagePack(int lang_index)
   811 bool ReadLanguagePack(int lang_index)
   795 {
   812 {
   796 	int tot_count, i;
   813 	int tot_count, i;
   837 		if (len >= 0xC0) len = ((len & 0x3F) << 8) + (byte)*s++;
   854 		if (len >= 0xC0) len = ((len & 0x3F) << 8) + (byte)*s++;
   838 		langpack_offs[i] = s;
   855 		langpack_offs[i] = s;
   839 		s += len;
   856 		s += len;
   840 	}
   857 	}
   841 
   858 
   842 	if (_langpack) free(_langpack);
   859 	free(_langpack);
   843 	_langpack = lang_pack;
   860 	_langpack = lang_pack;
   844 
   861 
   845 	if (_langpack_offs) free(_langpack_offs);
   862 	free(_langpack_offs);
   846 	_langpack_offs = langpack_offs;
   863 	_langpack_offs = langpack_offs;
   847 
   864 
   848 	ttd_strlcpy(_dynlang.curr_file, _dynlang.ent[lang_index].file, sizeof(_dynlang.curr_file));
   865 	ttd_strlcpy(_dynlang.curr_file, _dynlang.ent[lang_index].file, sizeof(_dynlang.curr_file));
   849 
   866 
   850 
   867 
   854 
   871 
   855 // make a list of the available language packs. put the data in _dynlang struct.
   872 // make a list of the available language packs. put the data in _dynlang struct.
   856 void InitializeLanguagePacks(void)
   873 void InitializeLanguagePacks(void)
   857 {
   874 {
   858 	DynamicLanguages *dl = &_dynlang;
   875 	DynamicLanguages *dl = &_dynlang;
   859 	int i, j, n, m,def;
   876 	int i;
       
   877 	int n;
       
   878 	int m;
       
   879 	int def;
   860 	LanguagePack hdr;
   880 	LanguagePack hdr;
   861 	FILE *in;
   881 	FILE *in;
   862 	char *files[32];
   882 	char *files[32];
   863 
   883 
   864 	n = GetLanguageList(files, lengthof(files));
   884 	n = GetLanguageList(files, lengthof(files));
   865 
   885 
   866 	def = 0; // default language file
   886 	def = 0; // default language file
   867 
   887 
   868 	// go through the language files and make sure that they are valid.
   888 	// go through the language files and make sure that they are valid.
   869 	for (i = m = 0; i != n; i++) {
   889 	for (i = m = 0; i != n; i++) {
       
   890 		int j;
       
   891 
   870 		char *s = str_fmt("%s%s", _path.lang_dir, files[i]);
   892 		char *s = str_fmt("%s%s", _path.lang_dir, files[i]);
   871 		in = fopen(s, "rb");
   893 		in = fopen(s, "rb");
   872 		free(s);
   894 		free(s);
   873 		if (in == NULL ||
   895 		if (in == NULL ||
   874 				(j = fread(&hdr, sizeof(hdr), 1, in), fclose(in), j) != 1 ||
   896 				(j = fread(&hdr, sizeof(hdr), 1, in), fclose(in), j) != 1 ||