strings.c
changeset 1316 6fba7f66c1f4
parent 1312 594340ca5b87
child 1317 3c90086ff34f
equal deleted inserted replaced
1315:183e30bdb5ec 1316:6fba7f66c1f4
    57 	STR_CURR_CUSTOM,
    57 	STR_CURR_CUSTOM,
    58 	INVALID_STRING_ID
    58 	INVALID_STRING_ID
    59 };
    59 };
    60 
    60 
    61 static const uint16 _cargo_string_list[NUM_LANDSCAPE][NUM_CARGO] = {
    61 static const uint16 _cargo_string_list[NUM_LANDSCAPE][NUM_CARGO] = {
    62 	/* LT_NORMAL */ {STR_PASSENGERS, STR_TONS, STR_BAGS, STR_LITERS, STR_ITEMS, STR_CRATES, STR_TONS, STR_TONS, STR_TONS, STR_TONS, STR_BAGS, STR_RES_OTHER},
    62 	{ /* LT_NORMAL */
    63 	/* LT_HILLY */  {STR_PASSENGERS, STR_TONS, STR_BAGS, STR_LITERS, STR_ITEMS, STR_CRATES, STR_TONS, STR_TONS, STR_RES_OTHER, STR_TONS, STR_BAGS, STR_TONS},
    63 		STR_PASSENGERS,
    64 	/* LT_DESERT */ {STR_PASSENGERS, STR_LITERS, STR_BAGS, STR_LITERS, STR_TONS, STR_CRATES, STR_TONS, STR_TONS, STR_TONS, STR_LITERS, STR_BAGS, STR_TONS},
    64 		STR_TONS,
    65 	/* LT_CANDY */  {STR_PASSENGERS, STR_TONS, STR_BAGS, STR_NOTHING, STR_NOTHING, STR_TONS, STR_TONS, STR_LITERS, STR_TONS, STR_NOTHING, STR_LITERS, STR_NOTHING}
    65 		STR_BAGS,
       
    66 		STR_LITERS,
       
    67 		STR_ITEMS,
       
    68 		STR_CRATES,
       
    69 		STR_TONS,
       
    70 		STR_TONS,
       
    71 		STR_TONS,
       
    72 		STR_TONS,
       
    73 		STR_BAGS,
       
    74 		STR_RES_OTHER
       
    75 	},
       
    76 
       
    77 	{ /* LT_HILLY */
       
    78 		STR_PASSENGERS,
       
    79 		STR_TONS,
       
    80 		STR_BAGS,
       
    81 		STR_LITERS,
       
    82 		STR_ITEMS,
       
    83 		STR_CRATES,
       
    84 		STR_TONS,
       
    85 		STR_TONS,
       
    86 		STR_RES_OTHER,
       
    87 		STR_TONS,
       
    88 		STR_BAGS,
       
    89 		STR_TONS
       
    90 	},
       
    91 
       
    92 	{ /* LT_DESERT */
       
    93 		STR_PASSENGERS,
       
    94 		STR_LITERS,
       
    95 		STR_BAGS,
       
    96 		STR_LITERS,
       
    97 		STR_TONS,
       
    98 		STR_CRATES,
       
    99 		STR_TONS,
       
   100 		STR_TONS,
       
   101 		STR_TONS,
       
   102 		STR_LITERS,
       
   103 		STR_BAGS,
       
   104 		STR_TONS
       
   105 	},
       
   106 
       
   107 	{ /* LT_CANDY */
       
   108 		STR_PASSENGERS,
       
   109 		STR_TONS,
       
   110 		STR_BAGS,
       
   111 		STR_NOTHING,
       
   112 		STR_NOTHING,
       
   113 		STR_TONS,
       
   114 		STR_TONS,
       
   115 		STR_LITERS,
       
   116 		STR_TONS,
       
   117 		STR_NOTHING,
       
   118 		STR_LITERS,
       
   119 		STR_NOTHING
       
   120 	}
    66 };
   121 };
    67 
   122 
    68 static char *str_cat(char *dst, const char *src)
   123 static char *str_cat(char *dst, const char *src)
    69 {
   124 {
    70 	while ( (*dst++ = *src++) != 0) {}
   125 	while ((*dst++ = *src++) != '\0') {}
    71 	return dst - 1;
   126 	return dst - 1;
    72 }
   127 }
    73 
   128 
    74 static char *GetStringPtr(uint16 string)
   129 static char *GetStringPtr(uint16 string)
    75 {
   130 {
    81 	uint index = string & 0x7FF;
   136 	uint index = string & 0x7FF;
    82 	uint tab = string >> 11;
   137 	uint tab = string >> 11;
    83 
   138 
    84 	if (string == 0) error("!invalid string id 0 in GetString");
   139 	if (string == 0) error("!invalid string id 0 in GetString");
    85 
   140 
    86 	if ( tab == 4 && index >= 0xC0)
   141 	if (tab == 4 && index >= 0xC0)
    87 		return GetSpecialTownNameString(buffr, index - 0xC0);
   142 		return GetSpecialTownNameString(buffr, index - 0xC0);
    88 
   143 
    89 	if ( tab == 6 && index == 0xD1)
   144 	if (tab == 6 && index == 0xD1)
    90 		return StationGetSpecialString(buffr);
   145 		return StationGetSpecialString(buffr);
    91 
   146 
    92 	if ( tab == 14 && index >= 0xE4)
   147 	if (tab == 14 && index >= 0xE4)
    93 		return GetSpecialPlayerNameString(buffr, index - 0xE4);
   148 		return GetSpecialPlayerNameString(buffr, index - 0xE4);
    94 
   149 
    95 	if ( tab == 15)
   150 	if (tab == 15)
    96 		return GetName(index, buffr);
   151 		return GetName(index, buffr);
    97 
   152 
    98 	// tab 31 is used for special or dynamic strings
   153 	// tab 31 is used for special or dynamic strings
    99 	if ( tab == 31) {
   154 	if (tab == 31) {
   100 		return DecodeString(buffr, index == (STR_SPEC_SCREENSHOT_NAME & 0x7FF) ? _screenshot_name : _userstring);
   155 		return DecodeString(buffr, index == (STR_SPEC_SCREENSHOT_NAME & 0x7FF) ? _screenshot_name : _userstring);
   101 	}
   156 	}
   102 
   157 
   103 	if (index >= _langtab_num[tab])
   158 	if (index >= _langtab_num[tab])
   104 		error("!String 0x%X is invalid. Probably because an old version of the .lng file.\n", string);
   159 		error("!String 0x%X is invalid. Probably because an old version of the .lng file.\n", string);
   175 	}
   230 	}
   176 
   231 
   177 	num = number;
   232 	num = number;
   178 
   233 
   179 	tot = 0;
   234 	tot = 0;
   180 	for(i=0; i!=10; i++) {
   235 	for (i = 0; i != 10; i++) {
   181 		divisor = _divisor_table[i];
   236 		divisor = _divisor_table[i];
   182 		quot = 0;
   237 		quot = 0;
   183 		if (num >= divisor) {
   238 		if (num >= divisor) {
   184 			quot = num / _divisor_table[i];
   239 			quot = num / _divisor_table[i];
   185 			num = num % _divisor_table[i];
   240 			num = num % _divisor_table[i];
   186 		}
   241 		}
   187 		if (tot|=quot || i==9) {
   242 		if (tot |= quot || i == 9) {
   188 			*buff++ = '0' + quot;
   243 			*buff++ = '0' + quot;
   189 			if (i==0 || i==3 || i==6) *buff++ = ',';
   244 			if (i == 0 || i == 3 || i == 6) *buff++ = ',';
   190 		}
   245 		}
   191 	}
   246 	}
   192 
   247 
   193 	*buff = 0;
   248 	*buff = '\0';
   194 
   249 
   195 	return buff;
   250 	return buff;
   196 }
   251 }
   197 
   252 
   198 static char *FormatNoCommaNumber(char *buff, int32 number)
   253 static char *FormatNoCommaNumber(char *buff, int32 number)
   208 	}
   263 	}
   209 
   264 
   210 	num = number;
   265 	num = number;
   211 
   266 
   212 	tot = 0;
   267 	tot = 0;
   213 	for(i=0; i!=10; i++) {
   268 	for (i = 0; i != 10; i++) {
   214 		divisor = _divisor_table[i];
   269 		divisor = _divisor_table[i];
   215 		quot = 0;
   270 		quot = 0;
   216 		if (num >= divisor) {
   271 		if (num >= divisor) {
   217 			quot = num / _divisor_table[i];
   272 			quot = num / _divisor_table[i];
   218 			num = num % _divisor_table[i];
   273 			num = num % _divisor_table[i];
   219 		}
   274 		}
   220 		if (tot|=quot || i==9) {
   275 		if (tot |= quot || i == 9) {
   221 			*buff++ = '0' + quot;
   276 			*buff++ = '0' + quot;
   222 		}
   277 		}
   223 	}
   278 	}
   224 
   279 
   225 	*buff = 0;
   280 	*buff = '\0';
   226 
   281 
   227 	return buff;
   282 	return buff;
   228 }
   283 }
   229 
   284 
   230 
   285 
   233 	const char *src;
   288 	const char *src;
   234 	YearMonthDay ymd;
   289 	YearMonthDay ymd;
   235 
   290 
   236 	ConvertDayToYMD(&ymd, number);
   291 	ConvertDayToYMD(&ymd, number);
   237 
   292 
   238 	for(src = GetStringPtr(ymd.day+STR_01AC_1ST-1); (*buff++=*src++) != 0;) {}
   293 	for (src = GetStringPtr(ymd.day + STR_01AC_1ST - 1); (*buff++ = *src++) != '\0';) {}
   239 
   294 
   240 	buff[-1] = ' ';
   295 	buff[-1] = ' ';
   241 	memcpy(buff, GetStringPtr(STR_0162_JAN + ymd.month), 4);
   296 	memcpy(buff, GetStringPtr(STR_0162_JAN + ymd.month), 4);
   242 	buff[3] = ' ';
   297 	buff[3] = ' ';
   243 
   298 
   249 	const char *src;
   304 	const char *src;
   250 	YearMonthDay ymd;
   305 	YearMonthDay ymd;
   251 
   306 
   252 	ConvertDayToYMD(&ymd, number);
   307 	ConvertDayToYMD(&ymd, number);
   253 
   308 
   254 	for(src = GetStringPtr(STR_MONTH_JAN + ymd.month); (*buff++=*src++) != 0;) {}
   309 	for (src = GetStringPtr(STR_MONTH_JAN + ymd.month); (*buff++ = *src++) != '\0';) {}
   255 	buff[-1] = ' ';
   310 	buff[-1] = ' ';
   256 
   311 
   257 	return FormatNoCommaNumber(buff, ymd.year + MAX_YEAR_BEGIN_REAL);
   312 	return FormatNoCommaNumber(buff, ymd.year + MAX_YEAR_BEGIN_REAL);
   258 }
   313 }
   259 
   314 
   267 	return buff;
   322 	return buff;
   268 }
   323 }
   269 
   324 
   270 uint GetCurrentCurrencyRate(void)
   325 uint GetCurrentCurrencyRate(void)
   271 {
   326 {
   272     return (&_currency_specs[_opt.currency])->rate;
   327 	return _currency_specs[_opt.currency].rate;
   273 }
   328 }
   274 
   329 
   275 static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, int64 number, bool compact)
   330 static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, int64 number, bool compact)
   276 {
   331 {
   277 	const char *s;
   332 	const char *s;
   281 
   336 
   282 	// multiply by exchange rate
   337 	// multiply by exchange rate
   283 	number *= spec->rate;
   338 	number *= spec->rate;
   284 
   339 
   285 	// convert from negative
   340 	// convert from negative
   286 	if (number < 0) { *buff++ = '-'; number = -number; }
   341 	if (number < 0) {
       
   342 		*buff++ = '-';
       
   343 		number = -number;
       
   344 	}
   287 
   345 
   288 	// add prefix part
   346 	// add prefix part
   289 	s = spec->prefix;
   347 	s = spec->prefix;
   290 	while (s != spec->prefix + lengthof(spec->prefix) && (c=*s++)) *buff++ = c;
   348 	while (s != spec->prefix + lengthof(spec->prefix) && (c = *s++) != '\0') *buff++ = c;
   291 
   349 
   292 	// for huge numbers, compact the number into k or M
   350 	// for huge numbers, compact the number into k or M
   293 	if (compact) {
   351 	if (compact) {
   294 		compact = 0;
   352 		compact = 0;
   295 		if (number >= 1000000000) {
   353 		if (number >= 1000000000) {
   303 
   361 
   304 	// convert to ascii number and add commas
   362 	// convert to ascii number and add commas
   305 	p = buf;
   363 	p = buf;
   306 	j = 4;
   364 	j = 4;
   307 	do {
   365 	do {
   308 		if (--j == 0) { *p++ = spec->separator; j = 3; }
   366 		if (--j == 0) {
       
   367 			*p++ = spec->separator;
       
   368 			j = 3;
       
   369 		}
   309 		*p++ = '0' + number % 10;
   370 		*p++ = '0' + number % 10;
   310 	} while (number /= 10);
   371 	} while (number /= 10);
   311 	do *buff++ = *--p; while (p != buf);
   372 	do *buff++ = *--p; while (p != buf);
   312 
   373 
   313 	if (compact) *buff++ = compact;
   374 	if (compact) *buff++ = compact;
   314 
   375 
   315 	// add suffix part
   376 	// add suffix part
   316 	s = spec->suffix;
   377 	s = spec->suffix;
   317 	while (s != spec->suffix + lengthof(spec->suffix) && (c=*s++)) *buff++ = c;
   378 	while (s != spec->suffix + lengthof(spec->suffix) && (c = *s++) != '\0') *buff++ = c;
   318 
   379 
   319 	return buff;
   380 	return buff;
   320 }
   381 }
   321 
   382 
   322 static char *DecodeString(char *buff, const char *str)
   383 static char *DecodeString(char *buff, const char *str)
   323 {
   384 {
   324 	byte b;
   385 	byte b;
   325 
   386 
   326 	while((b = *str++) != 0) {
   387 	while ((b = *str++) != '\0') {
   327 		switch(b) {
   388 		switch (b) {
   328 		case 0x1: // {SETX}
   389 		case 0x1: // {SETX}
   329 			*buff++ = b;
   390 			*buff++ = b;
   330 			*buff++ = *str++;
   391 			*buff++ = *str++;
   331 			break;
   392 			break;
   332 		case 0x2: // {SETXY}
   393 		case 0x2: // {SETXY}
   374 			break;
   435 			break;
   375 		}
   436 		}
   376 
   437 
   377 		// 0x85 is used as escape character..
   438 		// 0x85 is used as escape character..
   378 		case 0x85:
   439 		case 0x85:
   379 			switch(*str++) {
   440 			switch (*str++) {
   380 			case 0: /* {CURRCOMPACT} */
   441 			case 0: /* {CURRCOMPACT} */
   381 				buff = FormatGenericCurrency(buff, &_currency_specs[_opt.currency], GetParamInt32(), true);
   442 				buff = FormatGenericCurrency(buff, &_currency_specs[_opt.currency], GetParamInt32(), true);
   382 				break;
   443 				break;
   383 			case 1: /* {INT32} */
   444 			case 1: /* {INT32} */
   384 				buff = FormatNoCommaNumber(buff, GetParamInt32());
   445 				buff = FormatNoCommaNumber(buff, GetParamInt32());
   392 				// 16-bit = cargo count
   453 				// 16-bit = cargo count
   393 				char *s;
   454 				char *s;
   394 				uint16 cargo_str = _cargo_string_list[_opt.landscape][(byte)GetParamInt8()];
   455 				uint16 cargo_str = _cargo_string_list[_opt.landscape][(byte)GetParamInt8()];
   395 				uint16 multiplier = (cargo_str == STR_LITERS) ? 1000 : 1;
   456 				uint16 multiplier = (cargo_str == STR_LITERS) ? 1000 : 1;
   396 				// liquid type of cargo is multiplied by 100 to get correct amount
   457 				// liquid type of cargo is multiplied by 100 to get correct amount
   397 				buff = FormatCommaNumber(buff, GetParamInt16() * multiplier );
   458 				buff = FormatCommaNumber(buff, GetParamInt16() * multiplier);
   398 				s = GetStringPtr(cargo_str);
   459 				s = GetStringPtr(cargo_str);
   399 
   460 
   400 				memcpy(buff++, " ", 1);
   461 				memcpy(buff++, " ", 1);
   401 				while (*s) *buff++ = *s++;
   462 				while (*s) *buff++ = *s++;
   402 			}	break;
   463 			} break;
   403 			case 4: /* {CURRCOMPACT64} */
   464 			case 4: /* {CURRCOMPACT64} */
   404 				// 64 bit compact currency-unit
   465 				// 64 bit compact currency-unit
   405 				buff = FormatGenericCurrency(buff, &_currency_specs[_opt.currency], GetParamInt64(), true);
   466 				buff = FormatGenericCurrency(buff, &_currency_specs[_opt.currency], GetParamInt64(), true);
   406 				break;
   467 				break;
   407 
   468 
   440 
   501 
   441 		case 0x9A: { // {STATION}
   502 		case 0x9A: { // {STATION}
   442 			Station *st;
   503 			Station *st;
   443 			InjectDParam(1);
   504 			InjectDParam(1);
   444 			st = GetStation(GetDParam(1));
   505 			st = GetStation(GetDParam(1));
   445 			if (!st->xy) { // station doesn't exist anymore
   506 			if (st->xy == 0) { // station doesn't exist anymore
   446 				buff = GetString(buff, STR_UNKNOWN_DESTINATION);
   507 				buff = GetString(buff, STR_UNKNOWN_DESTINATION);
   447 				break;
   508 				break;
   448 			}
   509 			}
   449 			SetDParam(0, st->town->townnametype);
   510 			SetDParam(0, st->town->townnametype);
   450 			SetDParam(1, st->town->townnameparts);
   511 			SetDParam(1, st->town->townnameparts);
   498 		// 0x9E is the highest number that is available.
   559 		// 0x9E is the highest number that is available.
   499 		default:
   560 		default:
   500 			*buff++ = b;
   561 			*buff++ = b;
   501 		}
   562 		}
   502 	}
   563 	}
   503 	buff[0] = 0;
   564 	*buff = '\0';
   504 	return buff;
   565 	return buff;
   505 }
   566 }
   506 
   567 
   507 
   568 
   508 static char *StationGetSpecialString(char *buff)
   569 static char *StationGetSpecialString(char *buff)
   509 {
   570 {
   510 	int x = GetParamInt8();
   571 	int x = GetParamInt8();
   511 	if (x & 1) *buff++ = 0xB4;
   572 	if (x & 0x01) *buff++ = '\xB4';
   512 	if (x & 2) *buff++ = 0xB5;
   573 	if (x & 0x02) *buff++ = '\xB5';
   513 	if (x & 4) *buff++ = 0xB6;
   574 	if (x & 0x04) *buff++ = '\xB6';
   514 	if (x & 8) *buff++ = 0xB7;
   575 	if (x & 0x08) *buff++ = '\xB7';
   515 	if (x & 16) *buff++ = 0xB8;
   576 	if (x & 0x10) *buff++ = '\xB8';
   516 	*buff = 0;
   577 	*buff = '\0';
   517 	return buff;
   578 	return buff;
   518 }
   579 }
   519 
   580 
   520 static char *GetSpecialTownNameString(char *buff, int ind) {
   581 static char *GetSpecialTownNameString(char *buff, int ind)
       
   582 {
   521 	uint32 x = GetParamInt32();
   583 	uint32 x = GetParamInt32();
   522 
   584 
   523 	_town_name_generators[ind](buff, x);
   585 	_town_name_generators[ind](buff, x);
   524 
   586 
   525 	while (*buff != 0) buff++;
   587 	while (*buff != '\0') buff++;
   526 	return buff;
   588 	return buff;
   527 }
   589 }
   528 
   590 
   529 static const char * const _silly_company_names[] = {
   591 static const char * const _silly_company_names[] = {
   530 	"Bloggs Brothers",
   592 	"Bloggs Brothers",
   611 static char *GenPlayerName_4(char *buff)
   673 static char *GenPlayerName_4(char *buff)
   612 {
   674 {
   613 	uint32 x = GetParamInt32();
   675 	uint32 x = GetParamInt32();
   614 	uint i, base, num;
   676 	uint i, base, num;
   615 
   677 
   616 	buff[0] = _initial_name_letters[ (sizeof(_initial_name_letters) * (byte)x) >> 8];
   678 	buff[0] = _initial_name_letters[(sizeof(_initial_name_letters) * (byte)x) >> 8];
   617 	buff[1] = '.';
   679 	buff[1] = '.';
   618 	buff[2] = ' '; // Insert a space after initial and period "I. Firstname" instead of "I.Firstname"
   680 	buff[2] = ' '; // Insert a space after initial and period "I. Firstname" instead of "I.Firstname"
   619 	buff += 3;
   681 	buff += 3;
   620 
   682 
   621 	i = ((sizeof(_initial_name_letters) + 35) * (byte)(x >> 8)) >> 8;
   683 	i = ((sizeof(_initial_name_letters) + 35) * (byte)(x >> 8)) >> 8;
   663 	"Hard Drivin'"
   725 	"Hard Drivin'"
   664 };
   726 };
   665 
   727 
   666 static char *GetSpecialPlayerNameString(char *buff, int ind)
   728 static char *GetSpecialPlayerNameString(char *buff, int ind)
   667 {
   729 {
   668 	switch(ind) {
   730 	switch (ind) {
   669 
       
   670 	// not used
   731 	// not used
   671 	case 1: {
   732 	case 1: {
   672 		int i = GetParamInt32() & 0xFFFF;
   733 		int i = GetParamInt32() & 0xFFFF;
   673 		return str_cat(buff, _silly_company_names[i]);
   734 		return str_cat(buff, _silly_company_names[i]);
   674 	}
   735 	}
   685 		return str_cat(buff, song);
   746 		return str_cat(buff, song);
   686 	}
   747 	}
   687 	}
   748 	}
   688 
   749 
   689 	// town name?
   750 	// town name?
   690 	if (IS_INT_INSIDE(ind-6, 0, SPECSTR_TOWNNAME_LAST-SPECSTR_TOWNNAME_START+1)) {
   751 	if (IS_INT_INSIDE(ind - 6, 0, SPECSTR_TOWNNAME_LAST-SPECSTR_TOWNNAME_START + 1)) {
   691 		buff = GetSpecialTownNameString(buff, ind - 6);
   752 		buff = GetSpecialTownNameString(buff, ind - 6);
   692 		return str_cat(buff, " Transport");
   753 		return str_cat(buff, " Transport");
   693 	}
   754 	}
   694 
   755 
   695 	// language name?
   756 	// language name?
   707 	// screenshot format name?
   768 	// screenshot format name?
   708 	if (IS_INT_INSIDE(ind, (SPECSTR_SCREENSHOT_START - 0x70E4), (SPECSTR_SCREENSHOT_END - 0x70E4) + 1)) {
   769 	if (IS_INT_INSIDE(ind, (SPECSTR_SCREENSHOT_START - 0x70E4), (SPECSTR_SCREENSHOT_END - 0x70E4) + 1)) {
   709 		int i = ind - (SPECSTR_SCREENSHOT_START - 0x70E4);
   770 		int i = ind - (SPECSTR_SCREENSHOT_START - 0x70E4);
   710 		return str_cat(buff, GetScreenshotFormatDesc(i));
   771 		return str_cat(buff, GetScreenshotFormatDesc(i));
   711 	}
   772 	}
   712 
       
   713 
   773 
   714 	assert(0);
   774 	assert(0);
   715 	return NULL;
   775 	return NULL;
   716 }
   776 }
   717 
   777 
   727 	else if (IS_INT_INSIDE(s, 0x300F, 0x3030)) s = s - 0x300F + STR_SV_STNAME;
   787 	else if (IS_INT_INSIDE(s, 0x300F, 0x3030)) s = s - 0x300F + STR_SV_STNAME;
   728 	else if (s == 0x70E4 || s == 0x70E9) s = SPECSTR_PLAYERNAME_ENGLISH;
   788 	else if (s == 0x70E4 || s == 0x70E9) s = SPECSTR_PLAYERNAME_ENGLISH;
   729 	return s;
   789 	return s;
   730 }
   790 }
   731 
   791 
   732 bool ReadLanguagePack(int lang_index) {
   792 bool ReadLanguagePack(int lang_index)
       
   793 {
   733 	int tot_count, i;
   794 	int tot_count, i;
   734 	char *lang_pack;
   795 	char *lang_pack;
   735 	size_t len;
   796 	size_t len;
   736 	char **langpack_offs;
   797 	char **langpack_offs;
   737 	char *s;
   798 	char *s;
   750 		return false;
   811 		return false;
   751 	}
   812 	}
   752 #undef HDR
   813 #undef HDR
   753 
   814 
   754 #if defined(TTD_BIG_ENDIAN)
   815 #if defined(TTD_BIG_ENDIAN)
   755 	for(i=0; i!=32; i++) {
   816 	for (i = 0; i != 32; i++) {
   756 		((LanguagePackHeader*)lang_pack)->offsets[i] = READ_LE_UINT16(&((LanguagePackHeader*)lang_pack)->offsets[i]);
   817 		((LanguagePackHeader*)lang_pack)->offsets[i] = READ_LE_UINT16(&((LanguagePackHeader*)lang_pack)->offsets[i]);
   757 	}
   818 	}
   758 #endif
   819 #endif
   759 
   820 
   760 	tot_count = 0;
   821 	tot_count = 0;
   761 	for(i=0; i!=32; i++) {
   822 	for (i = 0; i != 32; i++) {
   762 		uint num = ((LanguagePackHeader*)lang_pack)->offsets[i];
   823 		uint num = ((LanguagePackHeader*)lang_pack)->offsets[i];
   763 		_langtab_start[i] = tot_count;
   824 		_langtab_start[i] = tot_count;
   764 		_langtab_num[i] = num;
   825 		_langtab_num[i] = num;
   765 		tot_count += num;
   826 		tot_count += num;
   766 	}
   827 	}
   768 	// Allocate offsets
   829 	// Allocate offsets
   769 	langpack_offs = malloc(tot_count * sizeof(*langpack_offs));
   830 	langpack_offs = malloc(tot_count * sizeof(*langpack_offs));
   770 
   831 
   771 	// Fill offsets
   832 	// Fill offsets
   772 	s = lang_pack + sizeof(LanguagePackHeader);
   833 	s = lang_pack + sizeof(LanguagePackHeader);
   773 	for(i=0; i!=tot_count; i++) {
   834 	for (i = 0; i != tot_count; i++) {
   774 		len = (byte)*s;
   835 		len = (byte)*s;
   775 		*s++ = 0; // zero terminate the string before.
   836 		*s++ = '\0'; // zero terminate the string before.
   776 		if (len >= 0xC0) { len = ((len & 0x3F) << 8) + (byte)*s++; }
   837 		if (len >= 0xC0) len = ((len & 0x3F) << 8) + (byte)*s++;
   777 		langpack_offs[i] = s;
   838 		langpack_offs[i] = s;
   778 		s += len;
   839 		s += len;
   779 	}
   840 	}
   780 
   841 
   781 	if (_langpack) free(_langpack);
   842 	if (_langpack) free(_langpack);
   803 	n = GetLanguageList(files, lengthof(files));
   864 	n = GetLanguageList(files, lengthof(files));
   804 
   865 
   805 	def = 0; // default language file
   866 	def = 0; // default language file
   806 
   867 
   807 	// go through the language files and make sure that they are valid.
   868 	// go through the language files and make sure that they are valid.
   808 	for(i=m=0; i!=n; i++) {
   869 	for (i = m = 0; i != n; i++) {
   809 		char *s = str_fmt("%s%s", _path.lang_dir, files[i]);
   870 		char *s = str_fmt("%s%s", _path.lang_dir, files[i]);
   810 		in = fopen(s, "rb");
   871 		in = fopen(s, "rb");
   811 		free(s);
   872 		free(s);
   812 		if (!in ||
   873 		if (in == NULL ||
   813 				(j = fread(&hdr, sizeof(hdr), 1, in), fclose(in), j) != 1 ||
   874 				(j = fread(&hdr, sizeof(hdr), 1, in), fclose(in), j) != 1 ||
   814 				hdr.ident != TO_LE32(LANGUAGE_PACK_IDENT) ||
   875 				hdr.ident != TO_LE32(LANGUAGE_PACK_IDENT) ||
   815 				hdr.version != TO_LE32(LANGUAGE_PACK_VERSION)) {
   876 				hdr.version != TO_LE32(LANGUAGE_PACK_VERSION)) {
   816 			free(files[i]);
   877 			free(files[i]);
   817 			continue;
   878 			continue;
   818 		}
   879 		}
   819 
   880 
   820 		dl->ent[m].file = files[i];
   881 		dl->ent[m].file = files[i];
   821 		dl->ent[m].name = strdup(hdr.name);
   882 		dl->ent[m].name = strdup(hdr.name);
   822 
   883 
   823 		if (!strcmp(hdr.name, "English")) def = m;
   884 		if (strcmp(hdr.name, "English") == 0) def = m;
   824 
   885 
   825 		m++;
   886 		m++;
   826 	}
   887 	}
   827 
   888 
   828 	if (m == 0)
   889 	if (m == 0)
   829 		error(n == 0 ? "No available language packs" : "Invalid version of language packs");
   890 		error(n == 0 ? "No available language packs" : "Invalid version of language packs");
   830 
   891 
   831 	dl->num = m;
   892 	dl->num = m;
   832 	for(i=0; i!=dl->num; i++)
   893 	for (i = 0; i != dl->num; i++)
   833 		dl->dropdown[i] = SPECSTR_LANGUAGE_START + i;
   894 		dl->dropdown[i] = SPECSTR_LANGUAGE_START + i;
   834 	dl->dropdown[i] = INVALID_STRING_ID;
   895 	dl->dropdown[i] = INVALID_STRING_ID;
   835 
   896 
   836 	for(i=0; i!=dl->num; i++)
   897 	for (i = 0; i != dl->num; i++)
   837 		if (!strcmp(dl->ent[i].file, dl->curr_file)) {
   898 		if (strcmp(dl->ent[i].file, dl->curr_file) == 0) {
   838 			def = i;
   899 			def = i;
   839 			break;
   900 			break;
   840 		}
   901 		}
   841 
   902 
   842 	if (!ReadLanguagePack(def))
   903 	if (!ReadLanguagePack(def))