strings.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * 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.
00007  * 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/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "currency.h"
00014 #include "station_base.h"
00015 #include "town.h"
00016 #include "screenshot.h"
00017 #include "waypoint_base.h"
00018 #include "depot_base.h"
00019 #include "industry.h"
00020 #include "newgrf_text.h"
00021 #include "fileio_func.h"
00022 #include "signs_base.h"
00023 #include "fontcache.h"
00024 #include "error.h"
00025 #include "strings_func.h"
00026 #include "rev.h"
00027 #include "core/endian_func.hpp"
00028 #include "date_func.h"
00029 #include "vehicle_base.h"
00030 #include "engine_base.h"
00031 #include "language.h"
00032 #include "townname_func.h"
00033 #include "string_func.h"
00034 #include "company_base.h"
00035 #include "smallmap_gui.h"
00036 #include "window_func.h"
00037 #include "debug.h"
00038 #include "game/game_text.hpp"
00039 #include <stack>
00040 
00041 #include "table/strings.h"
00042 #include "table/control_codes.h"
00043 
00044 char _config_language_file[MAX_PATH];             
00045 LanguageList _languages;                          
00046 const LanguageMetadata *_current_language = NULL; 
00047 
00048 TextDirection _current_text_dir; 
00049 
00050 #ifdef WITH_ICU
00051 Collator *_current_collator = NULL;               
00052 #endif /* WITH_ICU */
00053 
00054 static uint64 _global_string_params_data[20];     
00055 static WChar _global_string_params_type[20];      
00056 StringParameters _global_string_params(_global_string_params_data, 20, _global_string_params_type);
00057 
00059 void StringParameters::ClearTypeInformation()
00060 {
00061   assert(this->type != NULL);
00062   MemSetT(this->type, 0, this->num_param);
00063 }
00064 
00065 
00070 int64 StringParameters::GetInt64(WChar type)
00071 {
00072   if (this->offset >= this->num_param) {
00073     DEBUG(misc, 0, "Trying to read invalid string parameter");
00074     return 0;
00075   }
00076   if (this->type != NULL) {
00077     assert(this->type[this->offset] == 0 || this->type[this->offset] == type);
00078     this->type[this->offset] = type;
00079   }
00080   return this->data[this->offset++];
00081 }
00082 
00087 void StringParameters::ShiftParameters(uint amount)
00088 {
00089   assert(amount <= this->num_param);
00090   MemMoveT(this->data + amount, this->data, this->num_param - amount);
00091 }
00092 
00099 void CopyInDParam(int offs, const uint64 *src, int num)
00100 {
00101   MemCpyT(_global_string_params.GetPointerToOffset(offs), src, num);
00102 }
00103 
00110 void CopyOutDParam(uint64 *dst, int offs, int num)
00111 {
00112   MemCpyT(dst, _global_string_params.GetPointerToOffset(offs), num);
00113 }
00114 
00123 void CopyOutDParam(uint64 *dst, const char **strings, StringID string, int num)
00124 {
00125   char buf[DRAW_STRING_BUFFER];
00126   GetString(buf, string, lastof(buf));
00127 
00128   MemCpyT(dst, _global_string_params.GetPointerToOffset(0), num);
00129   for (int i = 0; i < num; i++) {
00130     if (_global_string_params.HasTypeInformation() && _global_string_params.GetTypeAtOffset(i) == SCC_RAW_STRING_POINTER) {
00131       strings[i] = strdup((const char *)(size_t)_global_string_params.GetParam(i));
00132       dst[i] = (size_t)strings[i];
00133     } else {
00134       strings[i] = NULL;
00135     }
00136   }
00137 }
00138 
00139 static char *StationGetSpecialString(char *buff, int x, const char *last);
00140 static char *GetSpecialTownNameString(char *buff, int ind, uint32 seed, const char *last);
00141 static char *GetSpecialNameString(char *buff, int ind, StringParameters *args, const char *last);
00142 
00143 static char *FormatString(char *buff, const char *str, StringParameters *args, const char *last, uint case_index = 0, bool game_script = false, bool dry_run = false);
00144 
00145 struct LanguagePack : public LanguagePackHeader {
00146   char data[]; // list of strings
00147 };
00148 
00149 static char **_langpack_offs;
00150 static LanguagePack *_langpack;
00151 static uint _langtab_num[TAB_COUNT];   
00152 static uint _langtab_start[TAB_COUNT]; 
00153 static bool _scan_for_gender_data = false;  
00154 
00155 
00156 const char *GetStringPtr(StringID string)
00157 {
00158   switch (GB(string, TAB_COUNT_OFFSET, TAB_COUNT_BITS)) {
00159     case GAME_TEXT_TAB: return GetGameStringPtr(GB(string, TAB_SIZE_OFFSET, TAB_SIZE_BITS));
00160     /* GetGRFStringPtr doesn't handle 0xD4xx ids, we need to convert those to 0xD0xx. */
00161     case 26: return GetStringPtr(GetGRFStringID(0, 0xD000 + GB(string, TAB_SIZE_OFFSET, 10)));
00162     case 28: return GetGRFStringPtr(GB(string, TAB_SIZE_OFFSET, TAB_SIZE_BITS));
00163     case 29: return GetGRFStringPtr(GB(string, TAB_SIZE_OFFSET, TAB_SIZE_BITS) + 0x0800);
00164     case 30: return GetGRFStringPtr(GB(string, TAB_SIZE_OFFSET, TAB_SIZE_BITS) + 0x1000);
00165     default: return _langpack_offs[_langtab_start[GB(string, TAB_COUNT_OFFSET, TAB_COUNT_BITS)] + GB(string, TAB_SIZE_OFFSET, TAB_SIZE_BITS)];
00166   }
00167 }
00168 
00179 char *GetStringWithArgs(char *buffr, StringID string, StringParameters *args, const char *last, uint case_index, bool game_script)
00180 {
00181   if (string == 0) return GetStringWithArgs(buffr, STR_UNDEFINED, args, last);
00182 
00183   uint index = GB(string, TAB_SIZE_OFFSET,  TAB_SIZE_BITS);
00184   uint tab   = GB(string, TAB_COUNT_OFFSET, TAB_COUNT_BITS);
00185 
00186   switch (tab) {
00187     case 4:
00188       if (index >= 0xC0 && !game_script) {
00189         return GetSpecialTownNameString(buffr, index - 0xC0, args->GetInt32(), last);
00190       }
00191       break;
00192 
00193     case 14:
00194       if (index >= 0xE4 && !game_script) {
00195         return GetSpecialNameString(buffr, index - 0xE4, args, last);
00196       }
00197       break;
00198 
00199     case 15:
00200       /* Old table for custom names. This is no longer used */
00201       error("Incorrect conversion of custom name string.");
00202 
00203     case GAME_TEXT_TAB:
00204       return FormatString(buffr, GetGameStringPtr(index), args, last, case_index, true);
00205 
00206     case 26:
00207       /* Include string within newgrf text (format code 81) */
00208       if (HasBit(index, 10)) {
00209         StringID string = GetGRFStringID(0, 0xD000 + GB(index, 0, 10));
00210         return GetStringWithArgs(buffr, string, args, last, case_index);
00211       }
00212       break;
00213 
00214     case 28:
00215       return FormatString(buffr, GetGRFStringPtr(index), args, last, case_index);
00216 
00217     case 29:
00218       return FormatString(buffr, GetGRFStringPtr(index + 0x0800), args, last, case_index);
00219 
00220     case 30:
00221       return FormatString(buffr, GetGRFStringPtr(index + 0x1000), args, last, case_index);
00222 
00223     case 31:
00224       NOT_REACHED();
00225   }
00226 
00227   if (index >= _langtab_num[tab]) {
00228     if (game_script) {
00229       return GetStringWithArgs(buffr, STR_UNDEFINED, args, last);
00230     }
00231     error("String 0x%X is invalid. You are probably using an old version of the .lng file.\n", string);
00232   }
00233 
00234   return FormatString(buffr, GetStringPtr(string), args, last, case_index);
00235 }
00236 
00237 char *GetString(char *buffr, StringID string, const char *last)
00238 {
00239   _global_string_params.ClearTypeInformation();
00240   _global_string_params.offset = 0;
00241   return GetStringWithArgs(buffr, string, &_global_string_params, last);
00242 }
00243 
00244 
00245 char *InlineString(char *buf, StringID string)
00246 {
00247   buf += Utf8Encode(buf, SCC_STRING_ID);
00248   buf += Utf8Encode(buf, string);
00249   return buf;
00250 }
00251 
00252 
00258 void SetDParamStr(uint n, const char *str)
00259 {
00260   SetDParam(n, (uint64)(size_t)str);
00261 }
00262 
00267 void InjectDParam(uint amount)
00268 {
00269   _global_string_params.ShiftParameters(amount);
00270 }
00271 
00283 static char *FormatNumber(char *buff, int64 number, const char *last, const char *separator, int zerofill = 1, int fractional_digits = 0)
00284 {
00285   static const int max_digits = 20;
00286   uint64 divisor = 10000000000000000000ULL;
00287   zerofill += fractional_digits;
00288   int thousands_offset = (max_digits - fractional_digits - 1) % 3;
00289 
00290   if (number < 0) {
00291     buff += seprintf(buff, last, "-");
00292     number = -number;
00293   }
00294 
00295   uint64 num = number;
00296   uint64 tot = 0;
00297   for (int i = 0; i < max_digits; i++) {
00298     if (i == max_digits - fractional_digits) {
00299       const char *decimal_separator = _settings_game.locale.digit_decimal_separator;
00300       if (decimal_separator == NULL) decimal_separator = _langpack->digit_decimal_separator;
00301       buff += seprintf(buff, last, "%s", decimal_separator);
00302     }
00303 
00304     uint64 quot = 0;
00305     if (num >= divisor) {
00306       quot = num / divisor;
00307       num = num % divisor;
00308     }
00309     if ((tot |= quot) || i >= max_digits - zerofill) {
00310       buff += seprintf(buff, last, "%i", (int)quot);
00311       if ((i % 3) == thousands_offset && i < max_digits - 1 - fractional_digits) buff = strecpy(buff, separator, last);
00312     }
00313 
00314     divisor /= 10;
00315   }
00316 
00317   *buff = '\0';
00318 
00319   return buff;
00320 }
00321 
00322 static char *FormatCommaNumber(char *buff, int64 number, const char *last, int fractional_digits = 0)
00323 {
00324   const char *separator = _settings_game.locale.digit_group_separator;
00325   if (separator == NULL) separator = _langpack->digit_group_separator;
00326   return FormatNumber(buff, number, last, separator, 1, fractional_digits);
00327 }
00328 
00329 static char *FormatNoCommaNumber(char *buff, int64 number, const char *last)
00330 {
00331   return FormatNumber(buff, number, last, "");
00332 }
00333 
00334 static char *FormatZerofillNumber(char *buff, int64 number, int64 count, const char *last)
00335 {
00336   return FormatNumber(buff, number, last, "", count);
00337 }
00338 
00339 static char *FormatHexNumber(char *buff, uint64 number, const char *last)
00340 {
00341   return buff + seprintf(buff, last, "0x" OTTD_PRINTFHEX64, number);
00342 }
00343 
00351 static char *FormatBytes(char *buff, int64 number, const char *last)
00352 {
00353   assert(number >= 0);
00354 
00355   /*                                   1   2^10  2^20  2^30  2^40  2^50  2^60 */
00356   const char * const iec_prefixes[] = {"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei"};
00357   uint id = 1;
00358   while (number >= 1024 * 1024) {
00359     number /= 1024;
00360     id++;
00361   }
00362 
00363   const char *decimal_separator = _settings_game.locale.digit_decimal_separator;
00364   if (decimal_separator == NULL) decimal_separator = _langpack->digit_decimal_separator;
00365 
00366   if (number < 1024) {
00367     id = 0;
00368     buff += seprintf(buff, last, "%i", (int)number);
00369   } else if (number < 1024 * 10) {
00370     buff += seprintf(buff, last, "%i%s%02i", (int)number / 1024, decimal_separator, (int)(number % 1024) * 100 / 1024);
00371   } else if (number < 1024 * 100) {
00372     buff += seprintf(buff, last, "%i%s%01i", (int)number / 1024, decimal_separator, (int)(number % 1024) * 10 / 1024);
00373   } else {
00374     assert(number < 1024 * 1024);
00375     buff += seprintf(buff, last, "%i", (int)number / 1024);
00376   }
00377 
00378   assert(id < lengthof(iec_prefixes));
00379   buff += seprintf(buff, last, " %sB", iec_prefixes[id]);
00380 
00381   return buff;
00382 }
00383 
00384 static char *FormatYmdString(char *buff, Date date, const char *last, uint case_index)
00385 {
00386   YearMonthDay ymd;
00387   ConvertDateToYMD(date, &ymd);
00388 
00389   int64 args[] = {ymd.day + STR_ORDINAL_NUMBER_1ST - 1, STR_MONTH_ABBREV_JAN + ymd.month, ymd.year};
00390   StringParameters tmp_params(args);
00391   return FormatString(buff, GetStringPtr(STR_FORMAT_DATE_LONG), &tmp_params, last, case_index);
00392 }
00393 
00394 static char *FormatMonthAndYear(char *buff, Date date, const char *last, uint case_index)
00395 {
00396   YearMonthDay ymd;
00397   ConvertDateToYMD(date, &ymd);
00398 
00399   int64 args[] = {STR_MONTH_JAN + ymd.month, ymd.year};
00400   StringParameters tmp_params(args);
00401   return FormatString(buff, GetStringPtr(STR_FORMAT_DATE_SHORT), &tmp_params, last, case_index);
00402 }
00403 
00404 static char *FormatTinyOrISODate(char *buff, Date date, StringID str, const char *last)
00405 {
00406   YearMonthDay ymd;
00407   ConvertDateToYMD(date, &ymd);
00408 
00409   char day[3];
00410   char month[3];
00411   /* We want to zero-pad the days and months */
00412   snprintf(day,   lengthof(day),   "%02i", ymd.day);
00413   snprintf(month, lengthof(month), "%02i", ymd.month + 1);
00414 
00415   int64 args[] = {(int64)(size_t)day, (int64)(size_t)month, ymd.year};
00416   StringParameters tmp_params(args);
00417   return FormatString(buff, GetStringPtr(str), &tmp_params, last);
00418 }
00419 
00420 static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, Money number, bool compact, const char *last)
00421 {
00422   /* We are going to make number absolute for printing, so
00423    * keep this piece of data as we need it later on */
00424   bool negative = number < 0;
00425   const char *multiplier = "";
00426 
00427   number *= spec->rate;
00428 
00429   /* convert from negative */
00430   if (number < 0) {
00431     if (buff + Utf8CharLen(SCC_RED) > last) return buff;
00432     buff += Utf8Encode(buff, SCC_RED);
00433     buff = strecpy(buff, "-", last);
00434     number = -number;
00435   }
00436 
00437   /* Add prefix part, following symbol_pos specification.
00438    * Here, it can can be either 0 (prefix) or 2 (both prefix and suffix).
00439    * The only remaining value is 1 (suffix), so everything that is not 1 */
00440   if (spec->symbol_pos != 1) buff = strecpy(buff, spec->prefix, last);
00441 
00442   /* for huge numbers, compact the number into k or M */
00443   if (compact) {
00444     /* Take care of the 'k' rounding. Having 1 000 000 k
00445      * and 1 000 M is inconsistent, so always use 1 000 M. */
00446     if (number >= 1000000000 - 500) {
00447       number = (number + 500000) / 1000000;
00448       multiplier = "M";
00449     } else if (number >= 1000000) {
00450       number = (number + 500) / 1000;
00451       multiplier = "k";
00452     }
00453   }
00454 
00455   const char *separator = _settings_game.locale.digit_group_separator_currency;
00456   if (separator == NULL && !StrEmpty(_currency->separator)) separator = _currency->separator;
00457   if (separator == NULL) separator = _langpack->digit_group_separator_currency;
00458   buff = FormatNumber(buff, number, last, separator);
00459   buff = strecpy(buff, multiplier, last);
00460 
00461   /* Add suffix part, following symbol_pos specification.
00462    * Here, it can can be either 1 (suffix) or 2 (both prefix and suffix).
00463    * The only remaining value is 1 (prefix), so everything that is not 0 */
00464   if (spec->symbol_pos != 0) buff = strecpy(buff, spec->suffix, last);
00465 
00466   if (negative) {
00467     if (buff + Utf8CharLen(SCC_PREVIOUS_COLOUR) > last) return buff;
00468     buff += Utf8Encode(buff, SCC_PREVIOUS_COLOUR);
00469     *buff = '\0';
00470   }
00471 
00472   return buff;
00473 }
00474 
00481 static int DeterminePluralForm(int64 count, int plural_form)
00482 {
00483   /* The absolute value determines plurality */
00484   uint64 n = abs(count);
00485 
00486   switch (plural_form) {
00487     default:
00488       NOT_REACHED();
00489 
00490     /* Two forms: singular used for one only.
00491      * Used in:
00492      *   Danish, Dutch, English, German, Norwegian, Swedish, Estonian, Finnish,
00493      *   Greek, Hebrew, Italian, Portuguese, Spanish, Esperanto */
00494     case 0:
00495       return n != 1;
00496 
00497     /* Only one form.
00498      * Used in:
00499      *   Hungarian, Japanese, Korean, Turkish */
00500     case 1:
00501       return 0;
00502 
00503     /* Two forms: singular used for 0 and 1.
00504      * Used in:
00505      *   French, Brazilian Portuguese */
00506     case 2:
00507       return n > 1;
00508 
00509     /* Three forms: special cases for 0, and numbers ending in 1 except when ending in 11.
00510      * Used in:
00511      *   Latvian */
00512     case 3:
00513       return n % 10 == 1 && n % 100 != 11 ? 0 : n != 0 ? 1 : 2;
00514 
00515     /* Five forms: special cases for 1, 2, 3 to 6, and 7 to 10.
00516      * Used in:
00517      *   Gaelige (Irish) */
00518     case 4:
00519       return n == 1 ? 0 : n == 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4;
00520 
00521     /* Three forms: special cases for numbers ending in 1 except when ending in 11, and 2 to 9 except when ending in 12 to 19.
00522      * Used in:
00523      *   Lithuanian */
00524     case 5:
00525       return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
00526 
00527     /* Three forms: special cases for numbers ending in 1 except wehn ending in 11, and 2 to 4 except when ending in 12 to 14.
00528      * Used in:
00529      *   Croatian, Russian, Ukrainian */
00530     case 6:
00531       return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
00532 
00533     /* Three forms: special cases for 1, and numbers ending in 2 to 4 except when ending in 12 to 14.
00534      * Used in:
00535      *   Polish */
00536     case 7:
00537       return n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
00538 
00539     /* Four forms: special cases for numbers ending in 01, 02, and 03 to 04.
00540      * Used in:
00541      *   Slovenian */
00542     case 8:
00543       return n % 100 == 1 ? 0 : n % 100 == 2 ? 1 : n % 100 == 3 || n % 100 == 4 ? 2 : 3;
00544 
00545     /* Two forms: singular used for numbers ending in 1 except when ending in 11.
00546      * Used in:
00547      *   Icelandic */
00548     case 9:
00549       return n % 10 == 1 && n % 100 != 11 ? 0 : 1;
00550 
00551     /* Three forms: special cases for 1, and 2 to 4
00552      * Used in:
00553      *   Czech, Slovak */
00554     case 10:
00555       return n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2;
00556 
00557     /* Two forms: cases for numbers ending with a consonant, and with a vowel.
00558      * Korean doesn't have the concept of plural, but depending on how a
00559      * number is pronounced it needs another version of a particle.
00560      * As such the plural system is misused to give this distinction.
00561      */
00562     case 11:
00563       switch (n % 10) {
00564         case 0: // yeong
00565         case 1: // il
00566         case 3: // sam
00567         case 6: // yuk
00568         case 7: // chil
00569         case 8: // pal
00570           return 0;
00571 
00572         case 2: // i
00573         case 4: // sa
00574         case 5: // o
00575         case 9: // gu
00576           return 1;
00577 
00578         default:
00579           NOT_REACHED();
00580       }
00581 
00582     /* Four forms: special cases for 1, 0 and numbers ending in 02 to 10, and numbers ending in 11 to 19.
00583      * Used in:
00584      *  Maltese */
00585     case 12:
00586       return (n == 1 ? 0 : n == 0 || (n % 100 > 1 && n % 100 < 11) ? 1 : (n % 100 > 10 && n % 100 < 20) ? 2 : 3);
00587   }
00588 }
00589 
00590 static const char *ParseStringChoice(const char *b, uint form, char **dst, const char *last)
00591 {
00592   /* <NUM> {Length of each string} {each string} */
00593   uint n = (byte)*b++;
00594   uint pos, i, mypos = 0;
00595 
00596   for (i = pos = 0; i != n; i++) {
00597     uint len = (byte)*b++;
00598     if (i == form) mypos = pos;
00599     pos += len;
00600   }
00601 
00602   *dst += seprintf(*dst, last, "%s", b + mypos);
00603   return b + pos;
00604 }
00605 
00607 struct UnitConversion {
00608   int multiplier; 
00609   int shift;      
00610 
00617   int64 ToDisplay(int64 input, bool round = true) const
00618   {
00619     return ((input * this->multiplier) + (round && this->shift != 0 ? 1 << (this->shift - 1) : 0)) >> this->shift;
00620   }
00621 
00629   int64 FromDisplay(int64 input, bool round = true, int64 divider = 1) const
00630   {
00631     return ((input << this->shift) + (round ? (this->multiplier * divider) - 1 : 0)) / (this->multiplier * divider);
00632   }
00633 };
00634 
00635 struct Units {
00636   UnitConversion c_velocity; 
00637   StringID velocity;         
00638   UnitConversion c_power;    
00639   StringID power;            
00640   UnitConversion c_weight;   
00641   StringID s_weight;         
00642   StringID l_weight;         
00643   UnitConversion c_volume;   
00644   StringID s_volume;         
00645   StringID l_volume;         
00646   UnitConversion c_force;    
00647   StringID force;            
00648   UnitConversion c_height;   
00649   StringID height;           
00650 };
00651 
00652 /* Unit conversions */
00653 static const Units _units[] = {
00654   { // Imperial (Original, mph, hp, metric ton, litre, kN, ft)
00655     {   1,  0}, STR_UNITS_VELOCITY_IMPERIAL,
00656     {   1,  0}, STR_UNITS_POWER_IMPERIAL,
00657     {   1,  0}, STR_UNITS_WEIGHT_SHORT_METRIC, STR_UNITS_WEIGHT_LONG_METRIC,
00658     {1000,  0}, STR_UNITS_VOLUME_SHORT_METRIC, STR_UNITS_VOLUME_LONG_METRIC,
00659     {   1,  0}, STR_UNITS_FORCE_SI,
00660     {   3,  0}, STR_UNITS_HEIGHT_IMPERIAL, // "Wrong" conversion factor for more nicer GUI values
00661   },
00662   { // Metric (km/h, hp, metric ton, litre, kN, metre)
00663     { 103,  6}, STR_UNITS_VELOCITY_METRIC,
00664     {4153, 12}, STR_UNITS_POWER_METRIC,
00665     {   1,  0}, STR_UNITS_WEIGHT_SHORT_METRIC, STR_UNITS_WEIGHT_LONG_METRIC,
00666     {1000,  0}, STR_UNITS_VOLUME_SHORT_METRIC, STR_UNITS_VOLUME_LONG_METRIC,
00667     {   1,  0}, STR_UNITS_FORCE_SI,
00668     {   1,  0}, STR_UNITS_HEIGHT_SI,
00669   },
00670   { // SI (m/s, kilowatt, kilogram, cubic metre, kilonewton, metre)
00671     {1831, 12}, STR_UNITS_VELOCITY_SI,
00672     {6109, 13}, STR_UNITS_POWER_SI,
00673     {1000,  0}, STR_UNITS_WEIGHT_SHORT_SI, STR_UNITS_WEIGHT_LONG_SI,
00674     {   1,  0}, STR_UNITS_VOLUME_SHORT_SI, STR_UNITS_VOLUME_LONG_SI,
00675     {   1,  0}, STR_UNITS_FORCE_SI,
00676     {   1,  0}, STR_UNITS_HEIGHT_SI,
00677   },
00678 };
00679 
00685 uint ConvertSpeedToDisplaySpeed(uint speed)
00686 {
00687   /* For historical reasons we don't want to mess with the
00688    * conversion for speed. So, don't round it and keep the
00689    * original conversion factors instead of the real ones. */
00690   return _units[_settings_game.locale.units].c_velocity.ToDisplay(speed, false);
00691 }
00692 
00698 uint ConvertDisplaySpeedToSpeed(uint speed)
00699 {
00700   return _units[_settings_game.locale.units].c_velocity.FromDisplay(speed);
00701 }
00702 
00708 uint ConvertKmhishSpeedToDisplaySpeed(uint speed)
00709 {
00710   return _units[_settings_game.locale.units].c_velocity.ToDisplay(speed * 10, false) / 16;
00711 }
00712 
00718 uint ConvertDisplaySpeedToKmhishSpeed(uint speed)
00719 {
00720   return _units[_settings_game.locale.units].c_velocity.FromDisplay(speed * 16, true, 10);
00721 }
00731 static char *FormatString(char *buff, const char *str_arg, StringParameters *args, const char *last, uint case_index, bool game_script, bool dry_run)
00732 {
00733   uint orig_offset = args->offset;
00734 
00735   /* When there is no array with types there is no need to do a dry run. */
00736   if (args->HasTypeInformation() && !dry_run) {
00737     if (UsingNewGRFTextStack()) {
00738       /* Values from the NewGRF text stack are only copied to the normal
00739        * argv array at the time they are encountered. That means that if
00740        * another string command references a value later in the string it
00741        * would fail. We solve that by running FormatString twice. The first
00742        * pass makes sure the argv array is correctly filled and the second
00743        * pass can reference later values without problems. */
00744       struct TextRefStack *backup = CreateTextRefStackBackup();
00745       FormatString(buff, str_arg, args, last, case_index, game_script, true);
00746       RestoreTextRefStackBackup(backup);
00747     } else {
00748       FormatString(buff, str_arg, args, last, case_index, game_script, true);
00749     }
00750     /* We have to restore the original offset here to to read the correct values. */
00751     args->offset = orig_offset;
00752   }
00753   WChar b;
00754   uint next_substr_case_index = 0;
00755   char *buf_start = buff;
00756   std::stack<const char *> str_stack;
00757   str_stack.push(str_arg);
00758 
00759   for (;;) {
00760     while (!str_stack.empty() && (b = Utf8Consume(&str_stack.top())) == '\0') {
00761       str_stack.pop();
00762     }
00763     if (str_stack.empty()) break;
00764     const char *&str = str_stack.top();
00765 
00766     if (SCC_NEWGRF_FIRST <= b && b <= SCC_NEWGRF_LAST) {
00767       /* We need to pass some stuff as it might be modified; oh boy. */
00768       //todo: should argve be passed here too?
00769       b = RemapNewGRFStringControlCode(b, buf_start, &buff, &str, (int64 *)args->GetDataPointer(), dry_run);
00770       if (b == 0) continue;
00771     }
00772 
00773     switch (b) {
00774       case SCC_ENCODED: {
00775         uint64 sub_args_data[20];
00776         WChar sub_args_type[20];
00777         bool sub_args_need_free[20];
00778         StringParameters sub_args(sub_args_data, 20, sub_args_type);
00779 
00780         sub_args.ClearTypeInformation();
00781         memset(sub_args_need_free, 0, sizeof(sub_args_need_free));
00782 
00783         uint16 stringid;
00784         const char *s = str;
00785         char *p;
00786         stringid = strtol(str, &p, 16);
00787         if (*p != ':' && *p != '\0') {
00788           while (*p != '\0') p++;
00789           str = p;
00790           buff = strecat(buff, "(invalid SCC_ENCODED)", last);
00791           break;
00792         }
00793         if (stringid >= TAB_SIZE) {
00794           while (*p != '\0') p++;
00795           str = p;
00796           buff = strecat(buff, "(invalid StringID)", last);
00797           break;
00798         }
00799 
00800         int i = 0;
00801         while (*p != '\0' && i < 20) {
00802           uint64 param;
00803           s = ++p;
00804 
00805           /* Find the next value */
00806           bool instring = false;
00807           bool escape = false;
00808           for (;; p++) {
00809             if (*p == '\\') {
00810               escape = true;
00811               continue;
00812             }
00813             if (*p == '"' && escape) {
00814               escape = false;
00815               continue;
00816             }
00817             escape = false;
00818 
00819             if (*p == '"') {
00820               instring = !instring;
00821               continue;
00822             }
00823             if (instring) {
00824               continue;
00825             }
00826 
00827             if (*p == ':') break;
00828             if (*p == '\0') break;
00829           }
00830 
00831           if (*s != '"') {
00832             /* Check if we want to look up another string */
00833             WChar l;
00834             size_t len = Utf8Decode(&l, s);
00835             bool lookup = (l == SCC_ENCODED);
00836             if (lookup) s += len;
00837 
00838             param = strtol(s, &p, 16);
00839 
00840             if (lookup) {
00841               if (param >= TAB_SIZE) {
00842                 while (*p != '\0') p++;
00843                 str = p;
00844                 buff = strecat(buff, "(invalid sub-StringID)", last);
00845                 break;
00846               }
00847               param = (GAME_TEXT_TAB << TAB_COUNT_OFFSET) + param;
00848             }
00849 
00850             sub_args.SetParam(i++, param);
00851           } else {
00852             char *g = strdup(s);
00853             g[p - s] = '\0';
00854 
00855             sub_args_need_free[i] = true;
00856             sub_args.SetParam(i++, (uint64)(size_t)g);
00857           }
00858         }
00859         /* We error'd out in the while, to error out in themain too */
00860         if (*str == '\0') break;
00861 
00862         str = p;
00863         buff = GetStringWithArgs(buff, (GAME_TEXT_TAB << TAB_COUNT_OFFSET) + stringid, &sub_args, last, true);
00864 
00865         for (int i = 0; i < 20; i++) {
00866           if (sub_args_need_free[i]) free((void *)sub_args.GetParam(i));
00867         }
00868         break;
00869       }
00870 
00871       case SCC_NEWGRF_STRINL: {
00872         StringID substr = Utf8Consume(&str);
00873         str_stack.push(GetStringPtr(substr));
00874         break;
00875       }
00876 
00877       case SCC_NEWGRF_PRINT_WORD_STRING_ID: {
00878         StringID substr = args->GetInt32(SCC_NEWGRF_PRINT_WORD_STRING_ID);
00879         str_stack.push(GetStringPtr(substr));
00880         case_index = next_substr_case_index;
00881         next_substr_case_index = 0;
00882         break;
00883       }
00884 
00885 
00886       case SCC_GENDER_LIST: { // {G 0 Der Die Das}
00887         /* First read the meta data from the language file. */
00888         uint offset = orig_offset + (byte)*str++;
00889         int gender = 0;
00890         if (!dry_run && args->GetTypeAtOffset(offset) != 0) {
00891           /* Now we need to figure out what text to resolve, i.e.
00892            * what do we need to draw? So get the actual raw string
00893            * first using the control code to get said string. */
00894           char input[4 + 1];
00895           char *p = input + Utf8Encode(input, args->GetTypeAtOffset(offset));
00896           *p = '\0';
00897 
00898           /* Now do the string formatting. */
00899           char buf[256];
00900           bool old_sgd = _scan_for_gender_data;
00901           _scan_for_gender_data = true;
00902           StringParameters tmp_params(args->GetPointerToOffset(offset), args->num_param - offset, NULL);
00903           p = FormatString(buf, input, &tmp_params, lastof(buf));
00904           _scan_for_gender_data = old_sgd;
00905           *p = '\0';
00906 
00907           /* And determine the string. */
00908           const char *s = buf;
00909           WChar c = Utf8Consume(&s);
00910           /* Does this string have a gender, if so, set it */
00911           if (c == SCC_GENDER_INDEX) gender = (byte)s[0];
00912         }
00913         str = ParseStringChoice(str, gender, &buff, last);
00914         break;
00915       }
00916 
00917       /* This sets up the gender for the string.
00918        * We just ignore this one. It's used in {G 0 Der Die Das} to determine the case. */
00919       case SCC_GENDER_INDEX: // {GENDER 0}
00920         if (_scan_for_gender_data) {
00921           buff += Utf8Encode(buff, SCC_GENDER_INDEX);
00922           *buff++ = *str++;
00923         } else {
00924           str++;
00925         }
00926         break;
00927 
00928       case SCC_PLURAL_LIST: { // {P}
00929         int plural_form = *str++;          // contains the plural form for this string
00930         uint offset = orig_offset + (byte)*str++;
00931         int64 v = *args->GetPointerToOffset(offset); // contains the number that determines plural
00932         str = ParseStringChoice(str, DeterminePluralForm(v, plural_form), &buff, last);
00933         break;
00934       }
00935 
00936       case SCC_ARG_INDEX: { // Move argument pointer
00937         args->offset = orig_offset + (byte)*str++;
00938         break;
00939       }
00940 
00941       case SCC_SET_CASE: { // {SET_CASE}
00942         /* This is a pseudo command, it's outputted when someone does {STRING.ack}
00943          * The modifier is added to all subsequent GetStringWithArgs that accept the modifier. */
00944         next_substr_case_index = (byte)*str++;
00945         break;
00946       }
00947 
00948       case SCC_SWITCH_CASE: { // {Used to implement case switching}
00949         /* <0x9E> <NUM CASES> <CASE1> <LEN1> <STRING1> <CASE2> <LEN2> <STRING2> <CASE3> <LEN3> <STRING3> <STRINGDEFAULT>
00950          * Each LEN is printed using 2 bytes in big endian order. */
00951         uint num = (byte)*str++;
00952         while (num) {
00953           if ((byte)str[0] == case_index) {
00954             /* Found the case, adjust str pointer and continue */
00955             str += 3;
00956             break;
00957           }
00958           /* Otherwise skip to the next case */
00959           str += 3 + (str[1] << 8) + str[2];
00960           num--;
00961         }
00962         break;
00963       }
00964 
00965       case SCC_SETX: // {SETX}
00966         if (buff + Utf8CharLen(SCC_SETX) + 1 < last) {
00967           buff += Utf8Encode(buff, SCC_SETX);
00968           *buff++ = *str++;
00969         }
00970         break;
00971 
00972       case SCC_SETXY: // {SETXY}
00973         if (buff + Utf8CharLen(SCC_SETXY) + 2 < last) {
00974           buff += Utf8Encode(buff, SCC_SETXY);
00975           *buff++ = *str++;
00976           *buff++ = *str++;
00977         }
00978         break;
00979 
00980       case SCC_REVISION: // {REV}
00981         buff = strecpy(buff, _openttd_revision, last);
00982         break;
00983 
00984       case SCC_STRING_ID: // {STRINL}
00985         if (game_script) break;
00986         buff = GetStringWithArgs(buff, Utf8Consume(&str), args, last);
00987         break;
00988 
00989       case SCC_RAW_STRING_POINTER: { // {RAW_STRING}
00990         if (game_script) break;
00991         const char *str = (const char *)(size_t)args->GetInt64(SCC_RAW_STRING_POINTER);
00992         buff = FormatString(buff, str, args, last);
00993         break;
00994       }
00995 
00996       case SCC_STRING: {// {STRING}
00997         StringID str = args->GetInt32(SCC_STRING);
00998         if (game_script && GB(str, TAB_COUNT_OFFSET, TAB_COUNT_BITS) != GAME_TEXT_TAB) break;
00999         /* WARNING. It's prohibited for the included string to consume any arguments.
01000          * For included strings that consume argument, you should use STRING1, STRING2 etc.
01001          * To debug stuff you can set argv to NULL and it will tell you */
01002         StringParameters tmp_params(args->GetDataPointer(), args->num_param - args->offset, NULL);
01003         buff = GetStringWithArgs(buff, str, &tmp_params, last, next_substr_case_index, game_script);
01004         next_substr_case_index = 0;
01005         break;
01006       }
01007 
01008       case SCC_STRING1:
01009       case SCC_STRING2:
01010       case SCC_STRING3:
01011       case SCC_STRING4:
01012       case SCC_STRING5:
01013       case SCC_STRING6:
01014       case SCC_STRING7: { // {STRING1..7}
01015         /* Strings that consume arguments */
01016         StringID str = args->GetInt32(b);
01017         if (game_script && GB(str, TAB_COUNT_OFFSET, TAB_COUNT_BITS) != GAME_TEXT_TAB) break;
01018         StringParameters sub_args(*args, b - SCC_STRING1 + 1);
01019         buff = GetStringWithArgs(buff, str, &sub_args, last, next_substr_case_index, game_script);
01020         next_substr_case_index = 0;
01021         break;
01022       }
01023 
01024       case SCC_COMMA: // {COMMA}
01025         buff = FormatCommaNumber(buff, args->GetInt64(SCC_COMMA), last);
01026         break;
01027 
01028       case SCC_DECIMAL: {// {DECIMAL}
01029         int64 number = args->GetInt64(SCC_DECIMAL);
01030         int digits = args->GetInt32(SCC_DECIMAL);
01031         buff = FormatCommaNumber(buff, number, last, digits);
01032         break;
01033       }
01034 
01035       case SCC_NUM: // {NUM}
01036         buff = FormatNoCommaNumber(buff, args->GetInt64(SCC_NUM), last);
01037         break;
01038 
01039       case SCC_ZEROFILL_NUM: { // {ZEROFILL_NUM}
01040         int64 num = args->GetInt64();
01041         buff = FormatZerofillNumber(buff, num, args->GetInt64(), last);
01042         break;
01043       }
01044 
01045       case SCC_HEX: // {HEX}
01046         buff = FormatHexNumber(buff, (uint64)args->GetInt64(SCC_HEX), last);
01047         break;
01048 
01049       case SCC_BYTES: // {BYTES}
01050         buff = FormatBytes(buff, args->GetInt64(), last);
01051         break;
01052 
01053       case SCC_CARGO_TINY: { // {CARGO_TINY}
01054         /* Tiny description of cargotypes. Layout:
01055          * param 1: cargo type
01056          * param 2: cargo count */
01057         CargoID cargo = args->GetInt32(SCC_CARGO_TINY);
01058         if (cargo >= CargoSpec::GetArraySize()) break;
01059 
01060         StringID cargo_str = CargoSpec::Get(cargo)->units_volume;
01061         int64 amount = 0;
01062         switch (cargo_str) {
01063           case STR_TONS:
01064             amount = _units[_settings_game.locale.units].c_weight.ToDisplay(args->GetInt64());
01065             break;
01066 
01067           case STR_LITERS:
01068             amount = _units[_settings_game.locale.units].c_volume.ToDisplay(args->GetInt64());
01069             break;
01070 
01071           default: {
01072             amount = args->GetInt64();
01073             break;
01074           }
01075         }
01076 
01077         buff = FormatCommaNumber(buff, amount, last);
01078         break;
01079       }
01080 
01081       case SCC_CARGO_SHORT: { // {CARGO_SHORT}
01082         /* Short description of cargotypes. Layout:
01083          * param 1: cargo type
01084          * param 2: cargo count */
01085         CargoID cargo = args->GetInt32(SCC_CARGO_SHORT);
01086         if (cargo >= CargoSpec::GetArraySize()) break;
01087 
01088         StringID cargo_str = CargoSpec::Get(cargo)->units_volume;
01089         switch (cargo_str) {
01090           case STR_TONS: {
01091             assert(_settings_game.locale.units < lengthof(_units));
01092             int64 args_array[] = {_units[_settings_game.locale.units].c_weight.ToDisplay(args->GetInt64())};
01093             StringParameters tmp_params(args_array);
01094             buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].l_weight), &tmp_params, last);
01095             break;
01096           }
01097 
01098           case STR_LITERS: {
01099             assert(_settings_game.locale.units < lengthof(_units));
01100             int64 args_array[] = {_units[_settings_game.locale.units].c_volume.ToDisplay(args->GetInt64())};
01101             StringParameters tmp_params(args_array);
01102             buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].l_volume), &tmp_params, last);
01103             break;
01104           }
01105 
01106           default: {
01107             StringParameters tmp_params(*args, 1);
01108             buff = GetStringWithArgs(buff, cargo_str, &tmp_params, last);
01109             break;
01110           }
01111         }
01112         break;
01113       }
01114 
01115       case SCC_CARGO_LONG: { // {CARGO_LONG}
01116         /* First parameter is cargo type, second parameter is cargo count */
01117         CargoID cargo = args->GetInt32(SCC_CARGO_LONG);
01118         if (cargo != CT_INVALID && cargo >= CargoSpec::GetArraySize()) break;
01119 
01120         StringID cargo_str = (cargo == CT_INVALID) ? STR_QUANTITY_N_A : CargoSpec::Get(cargo)->quantifier;
01121         StringParameters tmp_args(*args, 1);
01122         buff = GetStringWithArgs(buff, cargo_str, &tmp_args, last);
01123         break;
01124       }
01125 
01126       case SCC_CARGO_LIST: { // {CARGO_LIST}
01127         uint32 cmask = args->GetInt32(SCC_CARGO_LIST);
01128         bool first = true;
01129 
01130         const CargoSpec *cs;
01131         FOR_ALL_SORTED_CARGOSPECS(cs) {
01132           if (!HasBit(cmask, cs->Index())) continue;
01133 
01134           if (buff >= last - 2) break; // ',' and ' '
01135 
01136           if (first) {
01137             first = false;
01138           } else {
01139             /* Add a comma if this is not the first item */
01140             *buff++ = ',';
01141             *buff++ = ' ';
01142           }
01143 
01144           buff = GetStringWithArgs(buff, cs->name, args, last, next_substr_case_index, game_script);
01145         }
01146 
01147         /* If first is still true then no cargo is accepted */
01148         if (first) buff = GetStringWithArgs(buff, STR_JUST_NOTHING, args, last, next_substr_case_index, game_script);
01149 
01150         *buff = '\0';
01151         next_substr_case_index = 0;
01152 
01153         /* Make sure we detect any buffer overflow */
01154         assert(buff < last);
01155         break;
01156       }
01157 
01158       case SCC_CURRENCY_SHORT: // {CURRENCY_SHORT}
01159         buff = FormatGenericCurrency(buff, _currency, args->GetInt64(), true, last);
01160         break;
01161 
01162       case SCC_CURRENCY_LONG: // {CURRENCY_LONG}
01163         buff = FormatGenericCurrency(buff, _currency, args->GetInt64(SCC_CURRENCY_LONG), false, last);
01164         break;
01165 
01166       case SCC_DATE_TINY: // {DATE_TINY}
01167         buff = FormatTinyOrISODate(buff, args->GetInt32(SCC_DATE_TINY), STR_FORMAT_DATE_TINY, last);
01168         break;
01169 
01170       case SCC_DATE_SHORT: // {DATE_SHORT}
01171         buff = FormatMonthAndYear(buff, args->GetInt32(SCC_DATE_SHORT), last, next_substr_case_index);
01172         next_substr_case_index = 0;
01173         break;
01174 
01175       case SCC_DATE_LONG: // {DATE_LONG}
01176         buff = FormatYmdString(buff, args->GetInt32(SCC_DATE_LONG), last, next_substr_case_index);
01177         next_substr_case_index = 0;
01178         break;
01179 
01180       case SCC_DATE_ISO: // {DATE_ISO}
01181         buff = FormatTinyOrISODate(buff, args->GetInt32(), STR_FORMAT_DATE_ISO, last);
01182         break;
01183 
01184       case SCC_FORCE: { // {FORCE}
01185         assert(_settings_game.locale.units < lengthof(_units));
01186         int64 args_array[1] = {_units[_settings_game.locale.units].c_force.ToDisplay(args->GetInt64())};
01187         StringParameters tmp_params(args_array);
01188         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].force), &tmp_params, last);
01189         break;
01190       }
01191 
01192       case SCC_HEIGHT: { // {HEIGHT}
01193         int64 args_array[] = {_units[_settings_game.locale.units].c_height.ToDisplay(args->GetInt64())};
01194         StringParameters tmp_params(args_array);
01195         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].height), &tmp_params, last);
01196         break;
01197       }
01198 
01199       case SCC_POWER: { // {POWER}
01200         assert(_settings_game.locale.units < lengthof(_units));
01201         int64 args_array[1] = {_units[_settings_game.locale.units].c_power.ToDisplay(args->GetInt64())};
01202         StringParameters tmp_params(args_array);
01203         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].power), &tmp_params, last);
01204         break;
01205       }
01206 
01207       case SCC_VELOCITY: { // {VELOCITY}
01208         assert(_settings_game.locale.units < lengthof(_units));
01209         int64 args_array[] = {ConvertKmhishSpeedToDisplaySpeed(args->GetInt64(SCC_VELOCITY))};
01210         StringParameters tmp_params(args_array);
01211         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].velocity), &tmp_params, last);
01212         break;
01213       }
01214 
01215       case SCC_VOLUME_SHORT: { // {VOLUME_SHORT}
01216         assert(_settings_game.locale.units < lengthof(_units));
01217         int64 args_array[1] = {_units[_settings_game.locale.units].c_volume.ToDisplay(args->GetInt64())};
01218         StringParameters tmp_params(args_array);
01219         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].s_volume), &tmp_params, last);
01220         break;
01221       }
01222 
01223       case SCC_VOLUME_LONG: { // {VOLUME_LONG}
01224         assert(_settings_game.locale.units < lengthof(_units));
01225         int64 args_array[1] = {_units[_settings_game.locale.units].c_volume.ToDisplay(args->GetInt64(SCC_VOLUME_LONG))};
01226         StringParameters tmp_params(args_array);
01227         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].l_volume), &tmp_params, last);
01228         break;
01229       }
01230 
01231       case SCC_WEIGHT_SHORT: { // {WEIGHT_SHORT}
01232         assert(_settings_game.locale.units < lengthof(_units));
01233         int64 args_array[1] = {_units[_settings_game.locale.units].c_weight.ToDisplay(args->GetInt64())};
01234         StringParameters tmp_params(args_array);
01235         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].s_weight), &tmp_params, last);
01236         break;
01237       }
01238 
01239       case SCC_WEIGHT_LONG: { // {WEIGHT_LONG}
01240         assert(_settings_game.locale.units < lengthof(_units));
01241         int64 args_array[1] = {_units[_settings_game.locale.units].c_weight.ToDisplay(args->GetInt64(SCC_WEIGHT_LONG))};
01242         StringParameters tmp_params(args_array);
01243         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].l_weight), &tmp_params, last);
01244         break;
01245       }
01246 
01247       case SCC_COMPANY_NAME: { // {COMPANY}
01248         const Company *c = Company::GetIfValid(args->GetInt32());
01249         if (c == NULL) break;
01250 
01251         if (c->name != NULL) {
01252           int64 args_array[] = {(uint64)(size_t)c->name};
01253           StringParameters tmp_params(args_array);
01254           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01255         } else {
01256           int64 args_array[] = {c->name_2};
01257           StringParameters tmp_params(args_array);
01258           buff = GetStringWithArgs(buff, c->name_1, &tmp_params, last);
01259         }
01260         break;
01261       }
01262 
01263       case SCC_COMPANY_NUM: { // {COMPANY_NUM}
01264         CompanyID company = (CompanyID)args->GetInt32();
01265 
01266         /* Nothing is added for AI or inactive companies */
01267         if (Company::IsValidHumanID(company)) {
01268           int64 args_array[] = {company + 1};
01269           StringParameters tmp_params(args_array);
01270           buff = GetStringWithArgs(buff, STR_FORMAT_COMPANY_NUM, &tmp_params, last);
01271         }
01272         break;
01273       }
01274 
01275       case SCC_DEPOT_NAME: { // {DEPOT}
01276         VehicleType vt = (VehicleType)args->GetInt32(SCC_DEPOT_NAME);
01277         if (vt == VEH_AIRCRAFT) {
01278           uint64 args_array[] = {args->GetInt32()};
01279           WChar types_array[] = {SCC_STATION_NAME};
01280           StringParameters tmp_params(args_array, 1, types_array);
01281           buff = GetStringWithArgs(buff, STR_FORMAT_DEPOT_NAME_AIRCRAFT, &tmp_params, last);
01282           break;
01283         }
01284 
01285         const Depot *d = Depot::Get(args->GetInt32());
01286         if (d->name != NULL) {
01287           int64 args_array[] = {(uint64)(size_t)d->name};
01288           StringParameters tmp_params(args_array);
01289           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01290         } else {
01291           int64 args_array[] = {d->town->index, d->town_cn + 1};
01292           StringParameters tmp_params(args_array);
01293           buff = GetStringWithArgs(buff, STR_FORMAT_DEPOT_NAME_TRAIN + 2 * vt + (d->town_cn == 0 ? 0 : 1), &tmp_params, last);
01294         }
01295         break;
01296       }
01297 
01298       case SCC_ENGINE_NAME: { // {ENGINE}
01299         const Engine *e = Engine::GetIfValid(args->GetInt32(SCC_ENGINE_NAME));
01300         if (e == NULL) break;
01301 
01302         if (e->name != NULL && e->IsEnabled()) {
01303           int64 args_array[] = {(uint64)(size_t)e->name};
01304           StringParameters tmp_params(args_array);
01305           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01306         } else {
01307           StringParameters tmp_params(NULL, 0, NULL);
01308           buff = GetStringWithArgs(buff, e->info.string_id, &tmp_params, last);
01309         }
01310         break;
01311       }
01312 
01313       case SCC_GROUP_NAME: { // {GROUP}
01314         const Group *g = Group::GetIfValid(args->GetInt32());
01315         if (g == NULL) break;
01316 
01317         if (g->name != NULL) {
01318           int64 args_array[] = {(uint64)(size_t)g->name};
01319           StringParameters tmp_params(args_array);
01320           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01321         } else {
01322           int64 args_array[] = {g->index};
01323           StringParameters tmp_params(args_array);
01324 
01325           buff = GetStringWithArgs(buff, STR_FORMAT_GROUP_NAME, &tmp_params, last);
01326         }
01327         break;
01328       }
01329 
01330       case SCC_INDUSTRY_NAME: { // {INDUSTRY}
01331         const Industry *i = Industry::GetIfValid(args->GetInt32(SCC_INDUSTRY_NAME));
01332         if (i == NULL) break;
01333 
01334         if (_scan_for_gender_data) {
01335           /* Gender is defined by the industry type.
01336            * STR_FORMAT_INDUSTRY_NAME may have the town first, so it would result in the gender of the town name */
01337           StringParameters tmp_params(NULL, 0, NULL);
01338           buff = FormatString(buff, GetStringPtr(GetIndustrySpec(i->type)->name), &tmp_params, last, next_substr_case_index);
01339         } else {
01340           /* First print the town name and the industry type name. */
01341           int64 args_array[2] = {i->town->index, GetIndustrySpec(i->type)->name};
01342           StringParameters tmp_params(args_array);
01343 
01344           buff = FormatString(buff, GetStringPtr(STR_FORMAT_INDUSTRY_NAME), &tmp_params, last, next_substr_case_index);
01345         }
01346         next_substr_case_index = 0;
01347         break;
01348       }
01349 
01350       case SCC_PRESIDENT_NAME: { // {PRESIDENT_NAME}
01351         const Company *c = Company::GetIfValid(args->GetInt32(SCC_PRESIDENT_NAME));
01352         if (c == NULL) break;
01353 
01354         if (c->president_name != NULL) {
01355           int64 args_array[] = {(uint64)(size_t)c->president_name};
01356           StringParameters tmp_params(args_array);
01357           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01358         } else {
01359           int64 args_array[] = {c->president_name_2};
01360           StringParameters tmp_params(args_array);
01361           buff = GetStringWithArgs(buff, c->president_name_1, &tmp_params, last);
01362         }
01363         break;
01364       }
01365 
01366       case SCC_STATION_NAME: { // {STATION}
01367         StationID sid = args->GetInt32(SCC_STATION_NAME);
01368         const Station *st = Station::GetIfValid(sid);
01369 
01370         if (st == NULL) {
01371           /* The station doesn't exist anymore. The only place where we might
01372            * be "drawing" an invalid station is in the case of cargo that is
01373            * in transit. */
01374           StringParameters tmp_params(NULL, 0, NULL);
01375           buff = GetStringWithArgs(buff, STR_UNKNOWN_STATION, &tmp_params, last);
01376           break;
01377         }
01378 
01379         if (st->name != NULL) {
01380           int64 args_array[] = {(uint64)(size_t)st->name};
01381           StringParameters tmp_params(args_array);
01382           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01383         } else {
01384           StringID str = st->string_id;
01385           if (st->indtype != IT_INVALID) {
01386             /* Special case where the industry provides the name for the station */
01387             const IndustrySpec *indsp = GetIndustrySpec(st->indtype);
01388 
01389             /* Industry GRFs can change which might remove the station name and
01390              * thus cause very strange things. Here we check for that before we
01391              * actually set the station name. */
01392             if (indsp->station_name != STR_NULL && indsp->station_name != STR_UNDEFINED) {
01393               str = indsp->station_name;
01394             }
01395           }
01396 
01397           int64 args_array[] = {STR_TOWN_NAME, st->town->index, st->index};
01398           StringParameters tmp_params(args_array);
01399           buff = GetStringWithArgs(buff, str, &tmp_params, last);
01400         }
01401         break;
01402       }
01403 
01404       case SCC_TOWN_NAME: { // {TOWN}
01405         const Town *t = Town::GetIfValid(args->GetInt32(SCC_TOWN_NAME));
01406         if (t == NULL) break;
01407 
01408         if (t->name != NULL) {
01409           int64 args_array[] = {(uint64)(size_t)t->name};
01410           StringParameters tmp_params(args_array);
01411           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01412         } else {
01413           buff = GetTownName(buff, t, last);
01414         }
01415         break;
01416       }
01417 
01418       case SCC_WAYPOINT_NAME: { // {WAYPOINT}
01419         Waypoint *wp = Waypoint::GetIfValid(args->GetInt32(SCC_WAYPOINT_NAME));
01420         if (wp == NULL) break;
01421 
01422         if (wp->name != NULL) {
01423           int64 args_array[] = {(uint64)(size_t)wp->name};
01424           StringParameters tmp_params(args_array);
01425           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01426         } else {
01427           int64 args_array[] = {wp->town->index, wp->town_cn + 1};
01428           StringParameters tmp_params(args_array);
01429           StringID str = ((wp->string_id == STR_SV_STNAME_BUOY) ? STR_FORMAT_BUOY_NAME : STR_FORMAT_WAYPOINT_NAME);
01430           if (wp->town_cn != 0) str++;
01431           buff = GetStringWithArgs(buff, str, &tmp_params, last);
01432         }
01433         break;
01434       }
01435 
01436       case SCC_VEHICLE_NAME: { // {VEHICLE}
01437         const Vehicle *v = Vehicle::GetIfValid(args->GetInt32(SCC_VEHICLE_NAME));
01438         if (v == NULL) break;
01439 
01440         if (v->name != NULL) {
01441           int64 args_array[] = {(uint64)(size_t)v->name};
01442           StringParameters tmp_params(args_array);
01443           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01444         } else {
01445           int64 args_array[] = {v->unitnumber};
01446           StringParameters tmp_params(args_array);
01447 
01448           StringID str;
01449           switch (v->type) {
01450             default: NOT_REACHED();
01451             case VEH_TRAIN:    str = STR_SV_TRAIN_NAME; break;
01452             case VEH_ROAD:     str = STR_SV_ROAD_VEHICLE_NAME; break;
01453             case VEH_SHIP:     str = STR_SV_SHIP_NAME; break;
01454             case VEH_AIRCRAFT: str = STR_SV_AIRCRAFT_NAME; break;
01455           }
01456 
01457           buff = GetStringWithArgs(buff, str, &tmp_params, last);
01458         }
01459         break;
01460       }
01461 
01462       case SCC_SIGN_NAME: { // {SIGN}
01463         const Sign *si = Sign::GetIfValid(args->GetInt32());
01464         if (si == NULL) break;
01465 
01466         if (si->name != NULL) {
01467           int64 args_array[] = {(uint64)(size_t)si->name};
01468           StringParameters tmp_params(args_array);
01469           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01470         } else {
01471           StringParameters tmp_params(NULL, 0, NULL);
01472           buff = GetStringWithArgs(buff, STR_DEFAULT_SIGN_NAME, &tmp_params, last);
01473         }
01474         break;
01475       }
01476 
01477       case SCC_STATION_FEATURES: { // {STATIONFEATURES}
01478         buff = StationGetSpecialString(buff, args->GetInt32(SCC_STATION_FEATURES), last);
01479         break;
01480       }
01481 
01482       default:
01483         if (buff + Utf8CharLen(b) < last) buff += Utf8Encode(buff, b);
01484         break;
01485     }
01486   }
01487   *buff = '\0';
01488   return buff;
01489 }
01490 
01491 
01492 static char *StationGetSpecialString(char *buff, int x, const char *last)
01493 {
01494   if ((x & FACIL_TRAIN)      && (buff + Utf8CharLen(SCC_TRAIN) < last)) buff += Utf8Encode(buff, SCC_TRAIN);
01495   if ((x & FACIL_TRUCK_STOP) && (buff + Utf8CharLen(SCC_LORRY) < last)) buff += Utf8Encode(buff, SCC_LORRY);
01496   if ((x & FACIL_BUS_STOP)   && (buff + Utf8CharLen(SCC_BUS)   < last)) buff += Utf8Encode(buff, SCC_BUS);
01497   if ((x & FACIL_DOCK)       && (buff + Utf8CharLen(SCC_SHIP)  < last)) buff += Utf8Encode(buff, SCC_SHIP);
01498   if ((x & FACIL_AIRPORT)    && (buff + Utf8CharLen(SCC_PLANE) < last)) buff += Utf8Encode(buff, SCC_PLANE);
01499   *buff = '\0';
01500   return buff;
01501 }
01502 
01503 static char *GetSpecialTownNameString(char *buff, int ind, uint32 seed, const char *last)
01504 {
01505   return GenerateTownNameString(buff, last, ind, seed);
01506 }
01507 
01508 static const char * const _silly_company_names[] = {
01509   "Bloggs Brothers",
01510   "Tiny Transport Ltd.",
01511   "Express Travel",
01512   "Comfy-Coach & Co.",
01513   "Crush & Bump Ltd.",
01514   "Broken & Late Ltd.",
01515   "Sam Speedy & Son",
01516   "Supersonic Travel",
01517   "Mike's Motors",
01518   "Lightning International",
01519   "Pannik & Loozit Ltd.",
01520   "Inter-City Transport",
01521   "Getout & Pushit Ltd."
01522 };
01523 
01524 static const char * const _surname_list[] = {
01525   "Adams",
01526   "Allan",
01527   "Baker",
01528   "Bigwig",
01529   "Black",
01530   "Bloggs",
01531   "Brown",
01532   "Campbell",
01533   "Gordon",
01534   "Hamilton",
01535   "Hawthorn",
01536   "Higgins",
01537   "Green",
01538   "Gribble",
01539   "Jones",
01540   "McAlpine",
01541   "MacDonald",
01542   "McIntosh",
01543   "Muir",
01544   "Murphy",
01545   "Nelson",
01546   "O'Donnell",
01547   "Parker",
01548   "Phillips",
01549   "Pilkington",
01550   "Quigley",
01551   "Sharkey",
01552   "Thomson",
01553   "Watkins"
01554 };
01555 
01556 static const char * const _silly_surname_list[] = {
01557   "Grumpy",
01558   "Dozy",
01559   "Speedy",
01560   "Nosey",
01561   "Dribble",
01562   "Mushroom",
01563   "Cabbage",
01564   "Sniffle",
01565   "Fishy",
01566   "Swindle",
01567   "Sneaky",
01568   "Nutkins"
01569 };
01570 
01571 static const char _initial_name_letters[] = {
01572   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
01573   'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W',
01574 };
01575 
01576 static char *GenAndCoName(char *buff, uint32 arg, const char *last)
01577 {
01578   const char * const *base;
01579   uint num;
01580 
01581   if (_settings_game.game_creation.landscape == LT_TOYLAND) {
01582     base = _silly_surname_list;
01583     num  = lengthof(_silly_surname_list);
01584   } else {
01585     base = _surname_list;
01586     num  = lengthof(_surname_list);
01587   }
01588 
01589   buff = strecpy(buff, base[num * GB(arg, 16, 8) >> 8], last);
01590   buff = strecpy(buff, " & Co.", last);
01591 
01592   return buff;
01593 }
01594 
01595 static char *GenPresidentName(char *buff, uint32 x, const char *last)
01596 {
01597   char initial[] = "?. ";
01598   const char * const *base;
01599   uint num;
01600   uint i;
01601 
01602   initial[0] = _initial_name_letters[sizeof(_initial_name_letters) * GB(x, 0, 8) >> 8];
01603   buff = strecpy(buff, initial, last);
01604 
01605   i = (sizeof(_initial_name_letters) + 35) * GB(x, 8, 8) >> 8;
01606   if (i < sizeof(_initial_name_letters)) {
01607     initial[0] = _initial_name_letters[i];
01608     buff = strecpy(buff, initial, last);
01609   }
01610 
01611   if (_settings_game.game_creation.landscape == LT_TOYLAND) {
01612     base = _silly_surname_list;
01613     num  = lengthof(_silly_surname_list);
01614   } else {
01615     base = _surname_list;
01616     num  = lengthof(_surname_list);
01617   }
01618 
01619   buff = strecpy(buff, base[num * GB(x, 16, 8) >> 8], last);
01620 
01621   return buff;
01622 }
01623 
01624 static char *GetSpecialNameString(char *buff, int ind, StringParameters *args, const char *last)
01625 {
01626   switch (ind) {
01627     case 1: // not used
01628       return strecpy(buff, _silly_company_names[min(args->GetInt32() & 0xFFFF, lengthof(_silly_company_names) - 1)], last);
01629 
01630     case 2: // used for Foobar & Co company names
01631       return GenAndCoName(buff, args->GetInt32(), last);
01632 
01633     case 3: // President name
01634       return GenPresidentName(buff, args->GetInt32(), last);
01635   }
01636 
01637   /* town name? */
01638   if (IsInsideMM(ind - 6, 0, SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1)) {
01639     buff = GetSpecialTownNameString(buff, ind - 6, args->GetInt32(), last);
01640     return strecpy(buff, " Transport", last);
01641   }
01642 
01643   /* language name? */
01644   if (IsInsideMM(ind, (SPECSTR_LANGUAGE_START - 0x70E4), (SPECSTR_LANGUAGE_END - 0x70E4) + 1)) {
01645     int i = ind - (SPECSTR_LANGUAGE_START - 0x70E4);
01646     return strecpy(buff,
01647       &_languages[i] == _current_language ? _current_language->own_name : _languages[i].name, last);
01648   }
01649 
01650   /* resolution size? */
01651   if (IsInsideMM(ind, (SPECSTR_RESOLUTION_START - 0x70E4), (SPECSTR_RESOLUTION_END - 0x70E4) + 1)) {
01652     int i = ind - (SPECSTR_RESOLUTION_START - 0x70E4);
01653     buff += seprintf(
01654       buff, last, "%ux%u", _resolutions[i].width, _resolutions[i].height
01655     );
01656     return buff;
01657   }
01658 
01659   /* screenshot format name? */
01660   if (IsInsideMM(ind, (SPECSTR_SCREENSHOT_START - 0x70E4), (SPECSTR_SCREENSHOT_END - 0x70E4) + 1)) {
01661     int i = ind - (SPECSTR_SCREENSHOT_START - 0x70E4);
01662     return strecpy(buff, GetScreenshotFormatDesc(i), last);
01663   }
01664 
01665   NOT_REACHED();
01666 }
01667 
01668 #ifdef ENABLE_NETWORK
01669 extern void SortNetworkLanguages();
01670 #else /* ENABLE_NETWORK */
01671 static inline void SortNetworkLanguages() {}
01672 #endif /* ENABLE_NETWORK */
01673 
01678 bool LanguagePackHeader::IsValid() const
01679 {
01680   return this->ident        == TO_LE32(LanguagePackHeader::IDENT) &&
01681          this->version      == TO_LE32(LANGUAGE_PACK_VERSION) &&
01682          this->plural_form  <  LANGUAGE_MAX_PLURAL &&
01683          this->text_dir     <= 1 &&
01684          this->newgrflangid < MAX_LANG &&
01685          this->num_genders  < MAX_NUM_GENDERS &&
01686          this->num_cases    < MAX_NUM_CASES &&
01687          StrValid(this->name,                           lastof(this->name)) &&
01688          StrValid(this->own_name,                       lastof(this->own_name)) &&
01689          StrValid(this->isocode,                        lastof(this->isocode)) &&
01690          StrValid(this->digit_group_separator,          lastof(this->digit_group_separator)) &&
01691          StrValid(this->digit_group_separator_currency, lastof(this->digit_group_separator_currency)) &&
01692          StrValid(this->digit_decimal_separator,        lastof(this->digit_decimal_separator));
01693 }
01694 
01700 bool ReadLanguagePack(const LanguageMetadata *lang)
01701 {
01702   /* Current language pack */
01703   size_t len;
01704   LanguagePack *lang_pack = (LanguagePack *)ReadFileToMem(lang->file, &len, 1U << 20);
01705   if (lang_pack == NULL) return false;
01706 
01707   /* End of read data (+ terminating zero added in ReadFileToMem()) */
01708   const char *end = (char *)lang_pack + len + 1;
01709 
01710   /* We need at least one byte of lang_pack->data */
01711   if (end <= lang_pack->data || !lang_pack->IsValid()) {
01712     free(lang_pack);
01713     return false;
01714   }
01715 
01716 #if TTD_ENDIAN == TTD_BIG_ENDIAN
01717   for (uint i = 0; i < TAB_COUNT; i++) {
01718     lang_pack->offsets[i] = ReadLE16Aligned(&lang_pack->offsets[i]);
01719   }
01720 #endif /* TTD_ENDIAN == TTD_BIG_ENDIAN */
01721 
01722   uint count = 0;
01723   for (uint i = 0; i < TAB_COUNT; i++) {
01724     uint num = lang_pack->offsets[i];
01725     _langtab_start[i] = count;
01726     _langtab_num[i] = num;
01727     count += num;
01728   }
01729 
01730   /* Allocate offsets */
01731   char **langpack_offs = MallocT<char *>(count);
01732 
01733   /* Fill offsets */
01734   char *s = lang_pack->data;
01735   len = (byte)*s++;
01736   for (uint i = 0; i < count; i++) {
01737     if (s + len >= end) {
01738       free(lang_pack);
01739       free(langpack_offs);
01740       return false;
01741     }
01742     if (len >= 0xC0) {
01743       len = ((len & 0x3F) << 8) + (byte)*s++;
01744       if (s + len >= end) {
01745         free(lang_pack);
01746         free(langpack_offs);
01747         return false;
01748       }
01749     }
01750     langpack_offs[i] = s;
01751     s += len;
01752     len = (byte)*s;
01753     *s++ = '\0'; // zero terminate the string
01754   }
01755 
01756   free(_langpack);
01757   _langpack = lang_pack;
01758 
01759   free(_langpack_offs);
01760   _langpack_offs = langpack_offs;
01761 
01762   _current_language = lang;
01763   _current_text_dir = (TextDirection)_current_language->text_dir;
01764   const char *c_file = strrchr(_current_language->file, PATHSEPCHAR) + 1;
01765   strecpy(_config_language_file, c_file, lastof(_config_language_file));
01766   SetCurrentGrfLangID(_current_language->newgrflangid);
01767 
01768 #ifdef WITH_ICU
01769   /* Delete previous collator. */
01770   if (_current_collator != NULL) {
01771     delete _current_collator;
01772     _current_collator = NULL;
01773   }
01774 
01775   /* Create a collator instance for our current locale. */
01776   UErrorCode status = U_ZERO_ERROR;
01777   _current_collator = Collator::createInstance(Locale(_current_language->isocode), status);
01778   /* Sort number substrings by their numerical value. */
01779   if (_current_collator != NULL) _current_collator->setAttribute(UCOL_NUMERIC_COLLATION, UCOL_ON, status);
01780   /* Avoid using the collator if it is not correctly set. */
01781   if (U_FAILURE(status)) {
01782     delete _current_collator;
01783     _current_collator = NULL;
01784   }
01785 #endif /* WITH_ICU */
01786 
01787   /* Some lists need to be sorted again after a language change. */
01788   ReconsiderGameScriptLanguage();
01789   InitializeSortedCargoSpecs();
01790   SortIndustryTypes();
01791   BuildIndustriesLegend();
01792   SortNetworkLanguages();
01793   InvalidateWindowClassesData(WC_BUILD_VEHICLE);      // Build vehicle window.
01794   InvalidateWindowClassesData(WC_TRAINS_LIST);        // Train group window.
01795   InvalidateWindowClassesData(WC_ROADVEH_LIST);       // Road vehicle group window.
01796   InvalidateWindowClassesData(WC_SHIPS_LIST);         // Ship group window.
01797   InvalidateWindowClassesData(WC_AIRCRAFT_LIST);      // Aircraft group window.
01798   InvalidateWindowClassesData(WC_INDUSTRY_DIRECTORY); // Industry directory window.
01799   InvalidateWindowClassesData(WC_STATION_LIST);       // Station list window.
01800 
01801   return true;
01802 }
01803 
01804 /* Win32 implementation in win32.cpp.
01805  * OS X implementation in os/macosx/macos.mm. */
01806 #if !(defined(WIN32) || defined(__APPLE__))
01807 
01815 const char *GetCurrentLocale(const char *param)
01816 {
01817   const char *env;
01818 
01819   env = getenv("LANGUAGE");
01820   if (env != NULL) return env;
01821 
01822   env = getenv("LC_ALL");
01823   if (env != NULL) return env;
01824 
01825   if (param != NULL) {
01826     env = getenv(param);
01827     if (env != NULL) return env;
01828   }
01829 
01830   return getenv("LANG");
01831 }
01832 #else
01833 const char *GetCurrentLocale(const char *param);
01834 #endif /* !(defined(WIN32) || defined(__APPLE__)) */
01835 
01836 int CDECL StringIDSorter(const StringID *a, const StringID *b)
01837 {
01838   char stra[512];
01839   char strb[512];
01840   GetString(stra, *a, lastof(stra));
01841   GetString(strb, *b, lastof(strb));
01842 
01843   return strcmp(stra, strb);
01844 }
01845 
01851 const LanguageMetadata *GetLanguage(byte newgrflangid)
01852 {
01853   for (const LanguageMetadata *lang = _languages.Begin(); lang != _languages.End(); lang++) {
01854     if (newgrflangid == lang->newgrflangid) return lang;
01855   }
01856 
01857   return NULL;
01858 }
01859 
01866 static bool GetLanguageFileHeader(const char *file, LanguagePackHeader *hdr)
01867 {
01868   FILE *f = fopen(file, "rb");
01869   if (f == NULL) return false;
01870 
01871   size_t read = fread(hdr, sizeof(*hdr), 1, f);
01872   fclose(f);
01873 
01874   bool ret = read == 1 && hdr->IsValid();
01875 
01876   /* Convert endianness for the windows language ID */
01877   if (ret) {
01878     hdr->missing = FROM_LE16(hdr->missing);
01879     hdr->winlangid = FROM_LE16(hdr->winlangid);
01880   }
01881   return ret;
01882 }
01883 
01888 static void GetLanguageList(const char *path)
01889 {
01890   DIR *dir = ttd_opendir(path);
01891   if (dir != NULL) {
01892     struct dirent *dirent;
01893     while ((dirent = readdir(dir)) != NULL) {
01894       const char *d_name    = FS2OTTD(dirent->d_name);
01895       const char *extension = strrchr(d_name, '.');
01896 
01897       /* Not a language file */
01898       if (extension == NULL || strcmp(extension, ".lng") != 0) continue;
01899 
01900       LanguageMetadata lmd;
01901       seprintf(lmd.file, lastof(lmd.file), "%s%s", path, d_name);
01902 
01903       /* Check whether the file is of the correct version */
01904       if (!GetLanguageFileHeader(lmd.file, &lmd)) {
01905         DEBUG(misc, 3, "%s is not a valid language file", lmd.file);
01906       } else if (GetLanguage(lmd.newgrflangid) != NULL) {
01907         DEBUG(misc, 3, "%s's language ID is already known", lmd.file);
01908       } else {
01909         *_languages.Append() = lmd;
01910       }
01911     }
01912     closedir(dir);
01913   }
01914 }
01915 
01920 void InitializeLanguagePacks()
01921 {
01922   Searchpath sp;
01923 
01924   FOR_ALL_SEARCHPATHS(sp) {
01925     char path[MAX_PATH];
01926     FioAppendDirectory(path, lengthof(path), sp, LANG_DIR);
01927     GetLanguageList(path);
01928   }
01929   if (_languages.Length() == 0) usererror("No available language packs (invalid versions?)");
01930 
01931   /* Acquire the locale of the current system */
01932   const char *lang = GetCurrentLocale("LC_MESSAGES");
01933   if (lang == NULL) lang = "en_GB";
01934 
01935   const LanguageMetadata *chosen_language   = NULL; 
01936   const LanguageMetadata *language_fallback = NULL; 
01937   const LanguageMetadata *en_GB_fallback    = _languages.Begin(); 
01938 
01939   /* Find a proper language. */
01940   for (const LanguageMetadata *lng = _languages.Begin(); lng != _languages.End(); lng++) {
01941     /* We are trying to find a default language. The priority is by
01942      * configuration file, local environment and last, if nothing found,
01943      * English. */
01944     const char *lang_file = strrchr(lng->file, PATHSEPCHAR) + 1;
01945     if (strcmp(lang_file, _config_language_file) == 0) {
01946       chosen_language = lng;
01947       break;
01948     }
01949 
01950     if (strcmp (lng->isocode, "en_GB") == 0) en_GB_fallback    = lng;
01951     if (strncmp(lng->isocode, lang, 5) == 0) chosen_language   = lng;
01952     if (strncmp(lng->isocode, lang, 2) == 0) language_fallback = lng;
01953   }
01954 
01955   /* We haven't found the language in the config nor the one in the locale.
01956    * Now we set it to one of the fallback languages */
01957   if (chosen_language == NULL) {
01958     chosen_language = (language_fallback != NULL) ? language_fallback : en_GB_fallback;
01959   }
01960 
01961   if (!ReadLanguagePack(chosen_language)) usererror("Can't read language pack '%s'", chosen_language->file);
01962 }
01963 
01968 const char *GetCurrentLanguageIsoCode()
01969 {
01970   return _langpack->isocode;
01971 }
01972 
01979 bool MissingGlyphSearcher::FindMissingGlyphs(const char **str)
01980 {
01981   InitFreeType(this->Monospace());
01982   const Sprite *question_mark[FS_END];
01983 
01984   for (FontSize size = this->Monospace() ? FS_MONO : FS_BEGIN; size < (this->Monospace() ? FS_END : FS_MONO); size++) {
01985     question_mark[size] = GetGlyph(size, '?');
01986   }
01987 
01988   this->Reset();
01989   for (const char *text = this->NextString(); text != NULL; text = this->NextString()) {
01990     FontSize size = this->DefaultSize();
01991     if (str != NULL) *str = text;
01992     for (WChar c = Utf8Consume(&text); c != '\0'; c = Utf8Consume(&text)) {
01993       if (c == SCC_SETX) {
01994         /* SetX is, together with SetXY as special character that
01995           * uses the next (two) characters as data points. We have
01996           * to skip those, otherwise the UTF8 reading will go haywire. */
01997         text++;
01998       } else if (c == SCC_SETXY) {
01999         text += 2;
02000       } else if (c == SCC_TINYFONT) {
02001         size = FS_SMALL;
02002       } else if (c == SCC_BIGFONT) {
02003         size = FS_LARGE;
02004       } else if (!IsInsideMM(c, SCC_SPRITE_START, SCC_SPRITE_END) && IsPrintable(c) && !IsTextDirectionChar(c) && c != '?' && GetGlyph(size, c) == question_mark[size]) {
02005         /* The character is printable, but not in the normal font. This is the case we were testing for. */
02006         return true;
02007       }
02008     }
02009   }
02010   return false;
02011 }
02012 
02014 class LanguagePackGlyphSearcher : public MissingGlyphSearcher {
02015   uint i; 
02016   uint j; 
02017 
02018   /* virtual */ void Reset()
02019   {
02020     this->i = 0;
02021     this->j = 0;
02022   }
02023 
02024   /* virtual */ FontSize DefaultSize()
02025   {
02026     return FS_NORMAL;
02027   }
02028 
02029   /* virtual */ const char *NextString()
02030   {
02031     if (this->i >= TAB_COUNT) return NULL;
02032 
02033     const char *ret = _langpack_offs[_langtab_start[i] + j];
02034 
02035     this->j++;
02036     while (this->j >= _langtab_num[this->i] && this->i < TAB_COUNT) {
02037       i++;
02038       j = 0;
02039     }
02040 
02041     return ret;
02042   }
02043 
02044   /* virtual */ bool Monospace()
02045   {
02046     return false;
02047   }
02048 
02049   /* virtual */ void SetFontNames(FreeTypeSettings *settings, const char *font_name)
02050   {
02051 #ifdef WITH_FREETYPE
02052     strecpy(settings->small_font,  font_name, lastof(settings->small_font));
02053     strecpy(settings->medium_font, font_name, lastof(settings->medium_font));
02054     strecpy(settings->large_font,  font_name, lastof(settings->large_font));
02055 #endif /* WITH_FREETYPE */
02056   }
02057 };
02058 
02072 void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher)
02073 {
02074   static LanguagePackGlyphSearcher pack_searcher;
02075   if (searcher == NULL) searcher = &pack_searcher;
02076   bool bad_font = !base_font || searcher->FindMissingGlyphs(NULL);
02077 #ifdef WITH_FREETYPE
02078   if (bad_font) {
02079     /* We found an unprintable character... lets try whether we can find
02080      * a fallback font that can print the characters in the current language. */
02081     FreeTypeSettings backup;
02082     memcpy(&backup, &_freetype, sizeof(backup));
02083 
02084     bad_font = !SetFallbackFont(&_freetype, _langpack->isocode, _langpack->winlangid, searcher);
02085 
02086     memcpy(&_freetype, &backup, sizeof(backup));
02087 
02088     if (bad_font && base_font) {
02089       /* Our fallback font does miss characters too, so keep the
02090        * user chosen font as that is more likely to be any good than
02091        * the wild guess we made */
02092       InitFreeType(searcher->Monospace());
02093     }
02094   }
02095 #endif
02096 
02097   if (bad_font) {
02098     /* All attempts have failed. Display an error. As we do not want the string to be translated by
02099      * the translators, we 'force' it into the binary and 'load' it via a BindCString. To do this
02100      * properly we have to set the colour of the string, otherwise we end up with a lot of artefacts.
02101      * The colour 'character' might change in the future, so for safety we just Utf8 Encode it into
02102      * the string, which takes exactly three characters, so it replaces the "XXX" with the colour marker. */
02103     static char *err_str = strdup("XXXThe current font is missing some of the characters used in the texts for this language. Read the readme to see how to solve this.");
02104     Utf8Encode(err_str, SCC_YELLOW);
02105     SetDParamStr(0, err_str);
02106     ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_WARNING);
02107 
02108     /* Reset the font width */
02109     LoadStringWidthTable(searcher->Monospace());
02110     return;
02111   }
02112 
02113   /* Update the font with cache */
02114   LoadStringWidthTable(searcher->Monospace());
02115 
02116 #if !defined(WITH_ICU)
02117   /*
02118    * For right-to-left languages we need the ICU library. If
02119    * we do not have support for that library we warn the user
02120    * about it with a message. As we do not want the string to
02121    * be translated by the translators, we 'force' it into the
02122    * binary and 'load' it via a BindCString. To do this
02123    * properly we have to set the colour of the string,
02124    * otherwise we end up with a lot of artefacts. The colour
02125    * 'character' might change in the future, so for safety
02126    * we just Utf8 Encode it into the string, which takes
02127    * exactly three characters, so it replaces the "XXX" with
02128    * the colour marker.
02129    */
02130   if (_current_text_dir != TD_LTR) {
02131     static char *err_str = strdup("XXXThis version of OpenTTD does not support right-to-left languages. Recompile with icu enabled.");
02132     Utf8Encode(err_str, SCC_YELLOW);
02133     SetDParamStr(0, err_str);
02134     ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
02135   }
02136 #endif
02137 }