strings.cpp

Go to the documentation of this file.
00001 /* $Id: strings.cpp 24607 2012-10-17 19:15:23Z rubidium $ */
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 zero and one
00504      * Used in:
00505      *   French, Brazilian Portuguese */
00506     case 2:
00507       return n > 1;
00508 
00509     /* Three forms, special case for 0 and ending in 1, except those 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 case for one, two, 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 case for numbers ending in 1[2-9]
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 and 2, 3, 4, except those ending in 1[1-4]
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 case for one and some numbers ending in 2, 3, or 4
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 case for one and all numbers ending in 02, 03, or 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 everything ending in 1 but not 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 one and 2, 3, or 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, special 'hack' for Korean; singular for numbers ending
00558      *   in a consonant and plural for numbers ending in a vowel.
00559      * Korean doesn't have the concept of plural, but depending on how a
00560      * number is pronounced it needs another version of a particle.
00561      * As such the plural system is misused to give this distinction.
00562      */
00563     case 11:
00564       switch (n % 10) {
00565         case 0: // yeong
00566         case 1: // il
00567         case 3: // sam
00568         case 6: // yuk
00569         case 7: // chil
00570         case 8: // pal
00571           return 0;
00572 
00573         case 2: // i
00574         case 4: // sa
00575         case 5: // o
00576         case 9: // gu
00577           return 1;
00578 
00579         default:
00580           NOT_REACHED();
00581       }
00582 
00583     /* Four forms: one, 0 and everything ending in 02..10, everything ending in 11..19.
00584      * Used in:
00585      *  Maltese */
00586     case 12:
00587       return (n == 1 ? 0 : n == 0 || (n % 100 > 1 && n % 100 < 11) ? 1 : (n % 100 > 10 && n % 100 < 20) ? 2 : 3);
00588   }
00589 }
00590 
00591 static const char *ParseStringChoice(const char *b, uint form, char **dst, const char *last)
00592 {
00593   /* <NUM> {Length of each string} {each string} */
00594   uint n = (byte)*b++;
00595   uint pos, i, mypos = 0;
00596 
00597   for (i = pos = 0; i != n; i++) {
00598     uint len = (byte)*b++;
00599     if (i == form) mypos = pos;
00600     pos += len;
00601   }
00602 
00603   *dst += seprintf(*dst, last, "%s", b + mypos);
00604   return b + pos;
00605 }
00606 
00608 struct UnitConversion {
00609   int multiplier; 
00610   int shift;      
00611 
00618   int64 ToDisplay(int64 input, bool round = true) const
00619   {
00620     return ((input * this->multiplier) + (round && this->shift != 0 ? 1 << (this->shift - 1) : 0)) >> this->shift;
00621   }
00622 
00630   int64 FromDisplay(int64 input, bool round = true, int64 divider = 1) const
00631   {
00632     return ((input << this->shift) + (round ? (this->multiplier * divider) - 1 : 0)) / (this->multiplier * divider);
00633   }
00634 };
00635 
00636 struct Units {
00637   UnitConversion c_velocity; 
00638   StringID velocity;         
00639   UnitConversion c_power;    
00640   StringID power;            
00641   UnitConversion c_weight;   
00642   StringID s_weight;         
00643   StringID l_weight;         
00644   UnitConversion c_volume;   
00645   StringID s_volume;         
00646   StringID l_volume;         
00647   UnitConversion c_force;    
00648   StringID force;            
00649   UnitConversion c_height;   
00650   StringID height;           
00651 };
00652 
00653 /* Unit conversions */
00654 static const Units _units[] = {
00655   { // Imperial (Original, mph, hp, metric ton, litre, kN, ft)
00656     {   1,  0}, STR_UNITS_VELOCITY_IMPERIAL,
00657     {   1,  0}, STR_UNITS_POWER_IMPERIAL,
00658     {   1,  0}, STR_UNITS_WEIGHT_SHORT_METRIC, STR_UNITS_WEIGHT_LONG_METRIC,
00659     {1000,  0}, STR_UNITS_VOLUME_SHORT_METRIC, STR_UNITS_VOLUME_LONG_METRIC,
00660     {   1,  0}, STR_UNITS_FORCE_SI,
00661     {   3,  0}, STR_UNITS_HEIGHT_IMPERIAL, // "Wrong" conversion factor for more nicer GUI values
00662   },
00663   { // Metric (km/h, hp, metric ton, litre, kN, metre)
00664     { 103,  6}, STR_UNITS_VELOCITY_METRIC,
00665     {4153, 12}, STR_UNITS_POWER_METRIC,
00666     {   1,  0}, STR_UNITS_WEIGHT_SHORT_METRIC, STR_UNITS_WEIGHT_LONG_METRIC,
00667     {1000,  0}, STR_UNITS_VOLUME_SHORT_METRIC, STR_UNITS_VOLUME_LONG_METRIC,
00668     {   1,  0}, STR_UNITS_FORCE_SI,
00669     {   1,  0}, STR_UNITS_HEIGHT_SI,
00670   },
00671   { // SI (m/s, kilowatt, kilogram, cubic metre, kilonewton, metre)
00672     {1831, 12}, STR_UNITS_VELOCITY_SI,
00673     {6109, 13}, STR_UNITS_POWER_SI,
00674     {1000,  0}, STR_UNITS_WEIGHT_SHORT_SI, STR_UNITS_WEIGHT_LONG_SI,
00675     {   1,  0}, STR_UNITS_VOLUME_SHORT_SI, STR_UNITS_VOLUME_LONG_SI,
00676     {   1,  0}, STR_UNITS_FORCE_SI,
00677     {   1,  0}, STR_UNITS_HEIGHT_SI,
00678   },
00679 };
00680 
00686 uint ConvertSpeedToDisplaySpeed(uint speed)
00687 {
00688   /* For historical reasons we don't want to mess with the
00689    * conversion for speed. So, don't round it and keep the
00690    * original conversion factors instead of the real ones. */
00691   return _units[_settings_game.locale.units].c_velocity.ToDisplay(speed, false);
00692 }
00693 
00699 uint ConvertDisplaySpeedToSpeed(uint speed)
00700 {
00701   return _units[_settings_game.locale.units].c_velocity.FromDisplay(speed);
00702 }
00703 
00709 uint ConvertKmhishSpeedToDisplaySpeed(uint speed)
00710 {
00711   return _units[_settings_game.locale.units].c_velocity.ToDisplay(speed * 10, false) / 16;
00712 }
00713 
00719 uint ConvertDisplaySpeedToKmhishSpeed(uint speed)
00720 {
00721   return _units[_settings_game.locale.units].c_velocity.FromDisplay(speed * 16, true, 10);
00722 }
00732 static char *FormatString(char *buff, const char *str_arg, StringParameters *args, const char *last, uint case_index, bool game_script, bool dry_run)
00733 {
00734   uint orig_offset = args->offset;
00735 
00736   /* When there is no array with types there is no need to do a dry run. */
00737   if (args->HasTypeInformation() && !dry_run) {
00738     if (UsingNewGRFTextStack()) {
00739       /* Values from the NewGRF text stack are only copied to the normal
00740        * argv array at the time they are encountered. That means that if
00741        * another string command references a value later in the string it
00742        * would fail. We solve that by running FormatString twice. The first
00743        * pass makes sure the argv array is correctly filled and the second
00744        * pass can reference later values without problems. */
00745       struct TextRefStack *backup = CreateTextRefStackBackup();
00746       FormatString(buff, str_arg, args, last, case_index, game_script, true);
00747       RestoreTextRefStackBackup(backup);
00748     } else {
00749       FormatString(buff, str_arg, args, last, case_index, game_script, true);
00750     }
00751     /* We have to restore the original offset here to to read the correct values. */
00752     args->offset = orig_offset;
00753   }
00754   WChar b;
00755   uint next_substr_case_index = 0;
00756   char *buf_start = buff;
00757   std::stack<const char *> str_stack;
00758   str_stack.push(str_arg);
00759 
00760   for (;;) {
00761     while (!str_stack.empty() && (b = Utf8Consume(&str_stack.top())) == '\0') {
00762       str_stack.pop();
00763     }
00764     if (str_stack.empty()) break;
00765     const char *&str = str_stack.top();
00766 
00767     if (SCC_NEWGRF_FIRST <= b && b <= SCC_NEWGRF_LAST) {
00768       /* We need to pass some stuff as it might be modified; oh boy. */
00769       //todo: should argve be passed here too?
00770       b = RemapNewGRFStringControlCode(b, buf_start, &buff, &str, (int64 *)args->GetDataPointer(), dry_run);
00771       if (b == 0) continue;
00772     }
00773 
00774     switch (b) {
00775       case SCC_ENCODED: {
00776         uint64 sub_args_data[20];
00777         WChar sub_args_type[20];
00778         bool sub_args_need_free[20];
00779         StringParameters sub_args(sub_args_data, 20, sub_args_type);
00780 
00781         sub_args.ClearTypeInformation();
00782         memset(sub_args_need_free, 0, sizeof(sub_args_need_free));
00783 
00784         uint16 stringid;
00785         const char *s = str;
00786         char *p;
00787         stringid = strtol(str, &p, 16);
00788         if (*p != ':' && *p != '\0') {
00789           while (*p != '\0') p++;
00790           str = p;
00791           buff = strecat(buff, "(invalid SCC_ENCODED)", last);
00792           break;
00793         }
00794         if (stringid >= TAB_SIZE) {
00795           while (*p != '\0') p++;
00796           str = p;
00797           buff = strecat(buff, "(invalid StringID)", last);
00798           break;
00799         }
00800 
00801         int i = 0;
00802         while (*p != '\0' && i < 20) {
00803           uint64 param;
00804           s = ++p;
00805 
00806           /* Find the next value */
00807           bool instring = false;
00808           bool escape = false;
00809           for (;; p++) {
00810             if (*p == '\\') {
00811               escape = true;
00812               continue;
00813             }
00814             if (*p == '"' && escape) {
00815               escape = false;
00816               continue;
00817             }
00818             escape = false;
00819 
00820             if (*p == '"') {
00821               instring = !instring;
00822               continue;
00823             }
00824             if (instring) {
00825               continue;
00826             }
00827 
00828             if (*p == ':') break;
00829             if (*p == '\0') break;
00830           }
00831 
00832           if (*s != '"') {
00833             /* Check if we want to look up another string */
00834             WChar l;
00835             size_t len = Utf8Decode(&l, s);
00836             bool lookup = (l == SCC_ENCODED);
00837             if (lookup) s += len;
00838 
00839             param = strtol(s, &p, 16);
00840 
00841             if (lookup) {
00842               if (param >= TAB_SIZE) {
00843                 while (*p != '\0') p++;
00844                 str = p;
00845                 buff = strecat(buff, "(invalid sub-StringID)", last);
00846                 break;
00847               }
00848               param = (GAME_TEXT_TAB << TAB_COUNT_OFFSET) + param;
00849             }
00850 
00851             sub_args.SetParam(i++, param);
00852           } else {
00853             char *g = strdup(s);
00854             g[p - s] = '\0';
00855 
00856             sub_args_need_free[i] = true;
00857             sub_args.SetParam(i++, (uint64)(size_t)g);
00858           }
00859         }
00860         /* We error'd out in the while, to error out in themain too */
00861         if (*str == '\0') break;
00862 
00863         str = p;
00864         buff = GetStringWithArgs(buff, (GAME_TEXT_TAB << TAB_COUNT_OFFSET) + stringid, &sub_args, last, true);
00865 
00866         for (int i = 0; i < 20; i++) {
00867           if (sub_args_need_free[i]) free((void *)sub_args.GetParam(i));
00868         }
00869         break;
00870       }
00871 
00872       case SCC_NEWGRF_STRINL: {
00873         StringID substr = Utf8Consume(&str);
00874         str_stack.push(GetStringPtr(substr));
00875         break;
00876       }
00877 
00878       case SCC_NEWGRF_PRINT_WORD_STRING_ID: {
00879         StringID substr = args->GetInt32(SCC_NEWGRF_PRINT_WORD_STRING_ID);
00880         str_stack.push(GetStringPtr(substr));
00881         case_index = next_substr_case_index;
00882         next_substr_case_index = 0;
00883         break;
00884       }
00885 
00886 
00887       case SCC_GENDER_LIST: { // {G 0 Der Die Das}
00888         /* First read the meta data from the language file. */
00889         uint offset = orig_offset + (byte)*str++;
00890         int gender = 0;
00891         if (!dry_run && args->GetTypeAtOffset(offset) != 0) {
00892           /* Now we need to figure out what text to resolve, i.e.
00893            * what do we need to draw? So get the actual raw string
00894            * first using the control code to get said string. */
00895           char input[4 + 1];
00896           char *p = input + Utf8Encode(input, args->GetTypeAtOffset(offset));
00897           *p = '\0';
00898 
00899           /* Now do the string formatting. */
00900           char buf[256];
00901           bool old_sgd = _scan_for_gender_data;
00902           _scan_for_gender_data = true;
00903           StringParameters tmp_params(args->GetPointerToOffset(offset), args->num_param - offset, NULL);
00904           p = FormatString(buf, input, &tmp_params, lastof(buf));
00905           _scan_for_gender_data = old_sgd;
00906           *p = '\0';
00907 
00908           /* And determine the string. */
00909           const char *s = buf;
00910           WChar c = Utf8Consume(&s);
00911           /* Does this string have a gender, if so, set it */
00912           if (c == SCC_GENDER_INDEX) gender = (byte)s[0];
00913         }
00914         str = ParseStringChoice(str, gender, &buff, last);
00915         break;
00916       }
00917 
00918       /* This sets up the gender for the string.
00919        * We just ignore this one. It's used in {G 0 Der Die Das} to determine the case. */
00920       case SCC_GENDER_INDEX: // {GENDER 0}
00921         if (_scan_for_gender_data) {
00922           buff += Utf8Encode(buff, SCC_GENDER_INDEX);
00923           *buff++ = *str++;
00924         } else {
00925           str++;
00926         }
00927         break;
00928 
00929       case SCC_PLURAL_LIST: { // {P}
00930         int plural_form = *str++;          // contains the plural form for this string
00931         uint offset = orig_offset + (byte)*str++;
00932         int64 v = *args->GetPointerToOffset(offset); // contains the number that determines plural
00933         str = ParseStringChoice(str, DeterminePluralForm(v, plural_form), &buff, last);
00934         break;
00935       }
00936 
00937       case SCC_ARG_INDEX: { // Move argument pointer
00938         args->offset = orig_offset + (byte)*str++;
00939         break;
00940       }
00941 
00942       case SCC_SET_CASE: { // {SET_CASE}
00943         /* This is a pseudo command, it's outputted when someone does {STRING.ack}
00944          * The modifier is added to all subsequent GetStringWithArgs that accept the modifier. */
00945         next_substr_case_index = (byte)*str++;
00946         break;
00947       }
00948 
00949       case SCC_SWITCH_CASE: { // {Used to implement case switching}
00950         /* <0x9E> <NUM CASES> <CASE1> <LEN1> <STRING1> <CASE2> <LEN2> <STRING2> <CASE3> <LEN3> <STRING3> <STRINGDEFAULT>
00951          * Each LEN is printed using 2 bytes in big endian order. */
00952         uint num = (byte)*str++;
00953         while (num) {
00954           if ((byte)str[0] == case_index) {
00955             /* Found the case, adjust str pointer and continue */
00956             str += 3;
00957             break;
00958           }
00959           /* Otherwise skip to the next case */
00960           str += 3 + (str[1] << 8) + str[2];
00961           num--;
00962         }
00963         break;
00964       }
00965 
00966       case SCC_SETX: // {SETX}
00967         if (buff + Utf8CharLen(SCC_SETX) + 1 < last) {
00968           buff += Utf8Encode(buff, SCC_SETX);
00969           *buff++ = *str++;
00970         }
00971         break;
00972 
00973       case SCC_SETXY: // {SETXY}
00974         if (buff + Utf8CharLen(SCC_SETXY) + 2 < last) {
00975           buff += Utf8Encode(buff, SCC_SETXY);
00976           *buff++ = *str++;
00977           *buff++ = *str++;
00978         }
00979         break;
00980 
00981       case SCC_REVISION: // {REV}
00982         buff = strecpy(buff, _openttd_revision, last);
00983         break;
00984 
00985       case SCC_STRING_ID: // {STRINL}
00986         if (game_script) break;
00987         buff = GetStringWithArgs(buff, Utf8Consume(&str), args, last);
00988         break;
00989 
00990       case SCC_RAW_STRING_POINTER: { // {RAW_STRING}
00991         if (game_script) break;
00992         const char *str = (const char *)(size_t)args->GetInt64(SCC_RAW_STRING_POINTER);
00993         buff = FormatString(buff, str, args, last);
00994         break;
00995       }
00996 
00997       case SCC_STRING: {// {STRING}
00998         StringID str = args->GetInt32(SCC_STRING);
00999         if (game_script && GB(str, TAB_COUNT_OFFSET, TAB_COUNT_BITS) != GAME_TEXT_TAB) break;
01000         /* WARNING. It's prohibited for the included string to consume any arguments.
01001          * For included strings that consume argument, you should use STRING1, STRING2 etc.
01002          * To debug stuff you can set argv to NULL and it will tell you */
01003         StringParameters tmp_params(args->GetDataPointer(), args->num_param - args->offset, NULL);
01004         buff = GetStringWithArgs(buff, str, &tmp_params, last, next_substr_case_index, game_script);
01005         next_substr_case_index = 0;
01006         break;
01007       }
01008 
01009       case SCC_STRING1:
01010       case SCC_STRING2:
01011       case SCC_STRING3:
01012       case SCC_STRING4:
01013       case SCC_STRING5:
01014       case SCC_STRING6:
01015       case SCC_STRING7: { // {STRING1..7}
01016         /* Strings that consume arguments */
01017         StringID str = args->GetInt32(b);
01018         if (game_script && GB(str, TAB_COUNT_OFFSET, TAB_COUNT_BITS) != GAME_TEXT_TAB) break;
01019         StringParameters sub_args(*args, b - SCC_STRING1 + 1);
01020         buff = GetStringWithArgs(buff, str, &sub_args, last, next_substr_case_index, game_script);
01021         next_substr_case_index = 0;
01022         break;
01023       }
01024 
01025       case SCC_COMMA: // {COMMA}
01026         buff = FormatCommaNumber(buff, args->GetInt64(SCC_COMMA), last);
01027         break;
01028 
01029       case SCC_DECIMAL: {// {DECIMAL}
01030         int64 number = args->GetInt64(SCC_DECIMAL);
01031         int digits = args->GetInt32(SCC_DECIMAL);
01032         buff = FormatCommaNumber(buff, number, last, digits);
01033         break;
01034       }
01035 
01036       case SCC_NUM: // {NUM}
01037         buff = FormatNoCommaNumber(buff, args->GetInt64(SCC_NUM), last);
01038         break;
01039 
01040       case SCC_ZEROFILL_NUM: { // {ZEROFILL_NUM}
01041         int64 num = args->GetInt64();
01042         buff = FormatZerofillNumber(buff, num, args->GetInt64(), last);
01043         break;
01044       }
01045 
01046       case SCC_HEX: // {HEX}
01047         buff = FormatHexNumber(buff, (uint64)args->GetInt64(SCC_HEX), last);
01048         break;
01049 
01050       case SCC_BYTES: // {BYTES}
01051         buff = FormatBytes(buff, args->GetInt64(), last);
01052         break;
01053 
01054       case SCC_CARGO_TINY: { // {CARGO_TINY}
01055         /* Tiny description of cargotypes. Layout:
01056          * param 1: cargo type
01057          * param 2: cargo count */
01058         CargoID cargo = args->GetInt32(SCC_CARGO_TINY);
01059         if (cargo >= CargoSpec::GetArraySize()) break;
01060 
01061         StringID cargo_str = CargoSpec::Get(cargo)->units_volume;
01062         int64 amount = 0;
01063         switch (cargo_str) {
01064           case STR_TONS:
01065             amount = _units[_settings_game.locale.units].c_weight.ToDisplay(args->GetInt64());
01066             break;
01067 
01068           case STR_LITERS:
01069             amount = _units[_settings_game.locale.units].c_volume.ToDisplay(args->GetInt64());
01070             break;
01071 
01072           default: {
01073             amount = args->GetInt64();
01074             break;
01075           }
01076         }
01077 
01078         buff = FormatCommaNumber(buff, amount, last);
01079         break;
01080       }
01081 
01082       case SCC_CARGO_SHORT: { // {CARGO_SHORT}
01083         /* Short description of cargotypes. Layout:
01084          * param 1: cargo type
01085          * param 2: cargo count */
01086         CargoID cargo = args->GetInt32(SCC_CARGO_SHORT);
01087         if (cargo >= CargoSpec::GetArraySize()) break;
01088 
01089         StringID cargo_str = CargoSpec::Get(cargo)->units_volume;
01090         switch (cargo_str) {
01091           case STR_TONS: {
01092             assert(_settings_game.locale.units < lengthof(_units));
01093             int64 args_array[] = {_units[_settings_game.locale.units].c_weight.ToDisplay(args->GetInt64())};
01094             StringParameters tmp_params(args_array);
01095             buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].l_weight), &tmp_params, last);
01096             break;
01097           }
01098 
01099           case STR_LITERS: {
01100             assert(_settings_game.locale.units < lengthof(_units));
01101             int64 args_array[] = {_units[_settings_game.locale.units].c_volume.ToDisplay(args->GetInt64())};
01102             StringParameters tmp_params(args_array);
01103             buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].l_volume), &tmp_params, last);
01104             break;
01105           }
01106 
01107           default: {
01108             StringParameters tmp_params(*args, 1);
01109             buff = GetStringWithArgs(buff, cargo_str, &tmp_params, last);
01110             break;
01111           }
01112         }
01113         break;
01114       }
01115 
01116       case SCC_CARGO_LONG: { // {CARGO_LONG}
01117         /* First parameter is cargo type, second parameter is cargo count */
01118         CargoID cargo = args->GetInt32(SCC_CARGO_LONG);
01119         if (cargo != CT_INVALID && cargo >= CargoSpec::GetArraySize()) break;
01120 
01121         StringID cargo_str = (cargo == CT_INVALID) ? STR_QUANTITY_N_A : CargoSpec::Get(cargo)->quantifier;
01122         StringParameters tmp_args(*args, 1);
01123         buff = GetStringWithArgs(buff, cargo_str, &tmp_args, last);
01124         break;
01125       }
01126 
01127       case SCC_CARGO_LIST: { // {CARGO_LIST}
01128         uint32 cmask = args->GetInt32(SCC_CARGO_LIST);
01129         bool first = true;
01130 
01131         const CargoSpec *cs;
01132         FOR_ALL_SORTED_CARGOSPECS(cs) {
01133           if (!HasBit(cmask, cs->Index())) continue;
01134 
01135           if (buff >= last - 2) break; // ',' and ' '
01136 
01137           if (first) {
01138             first = false;
01139           } else {
01140             /* Add a comma if this is not the first item */
01141             *buff++ = ',';
01142             *buff++ = ' ';
01143           }
01144 
01145           buff = GetStringWithArgs(buff, cs->name, args, last, next_substr_case_index, game_script);
01146         }
01147 
01148         /* If first is still true then no cargo is accepted */
01149         if (first) buff = GetStringWithArgs(buff, STR_JUST_NOTHING, args, last, next_substr_case_index, game_script);
01150 
01151         *buff = '\0';
01152         next_substr_case_index = 0;
01153 
01154         /* Make sure we detect any buffer overflow */
01155         assert(buff < last);
01156         break;
01157       }
01158 
01159       case SCC_CURRENCY_SHORT: // {CURRENCY_SHORT}
01160         buff = FormatGenericCurrency(buff, _currency, args->GetInt64(), true, last);
01161         break;
01162 
01163       case SCC_CURRENCY_LONG: // {CURRENCY_LONG}
01164         buff = FormatGenericCurrency(buff, _currency, args->GetInt64(SCC_CURRENCY_LONG), false, last);
01165         break;
01166 
01167       case SCC_DATE_TINY: // {DATE_TINY}
01168         buff = FormatTinyOrISODate(buff, args->GetInt32(SCC_DATE_TINY), STR_FORMAT_DATE_TINY, last);
01169         break;
01170 
01171       case SCC_DATE_SHORT: // {DATE_SHORT}
01172         buff = FormatMonthAndYear(buff, args->GetInt32(SCC_DATE_SHORT), last, next_substr_case_index);
01173         next_substr_case_index = 0;
01174         break;
01175 
01176       case SCC_DATE_LONG: // {DATE_LONG}
01177         buff = FormatYmdString(buff, args->GetInt32(SCC_DATE_LONG), last, next_substr_case_index);
01178         next_substr_case_index = 0;
01179         break;
01180 
01181       case SCC_DATE_ISO: // {DATE_ISO}
01182         buff = FormatTinyOrISODate(buff, args->GetInt32(), STR_FORMAT_DATE_ISO, last);
01183         break;
01184 
01185       case SCC_FORCE: { // {FORCE}
01186         assert(_settings_game.locale.units < lengthof(_units));
01187         int64 args_array[1] = {_units[_settings_game.locale.units].c_force.ToDisplay(args->GetInt64())};
01188         StringParameters tmp_params(args_array);
01189         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].force), &tmp_params, last);
01190         break;
01191       }
01192 
01193       case SCC_HEIGHT: { // {HEIGHT}
01194         int64 args_array[] = {_units[_settings_game.locale.units].c_height.ToDisplay(args->GetInt64())};
01195         StringParameters tmp_params(args_array);
01196         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].height), &tmp_params, last);
01197         break;
01198       }
01199 
01200       case SCC_POWER: { // {POWER}
01201         assert(_settings_game.locale.units < lengthof(_units));
01202         int64 args_array[1] = {_units[_settings_game.locale.units].c_power.ToDisplay(args->GetInt64())};
01203         StringParameters tmp_params(args_array);
01204         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].power), &tmp_params, last);
01205         break;
01206       }
01207 
01208       case SCC_VELOCITY: { // {VELOCITY}
01209         assert(_settings_game.locale.units < lengthof(_units));
01210         int64 args_array[] = {ConvertKmhishSpeedToDisplaySpeed(args->GetInt64(SCC_VELOCITY))};
01211         StringParameters tmp_params(args_array);
01212         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].velocity), &tmp_params, last);
01213         break;
01214       }
01215 
01216       case SCC_VOLUME_SHORT: { // {VOLUME_SHORT}
01217         assert(_settings_game.locale.units < lengthof(_units));
01218         int64 args_array[1] = {_units[_settings_game.locale.units].c_volume.ToDisplay(args->GetInt64())};
01219         StringParameters tmp_params(args_array);
01220         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].s_volume), &tmp_params, last);
01221         break;
01222       }
01223 
01224       case SCC_VOLUME_LONG: { // {VOLUME_LONG}
01225         assert(_settings_game.locale.units < lengthof(_units));
01226         int64 args_array[1] = {_units[_settings_game.locale.units].c_volume.ToDisplay(args->GetInt64(SCC_VOLUME_LONG))};
01227         StringParameters tmp_params(args_array);
01228         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].l_volume), &tmp_params, last);
01229         break;
01230       }
01231 
01232       case SCC_WEIGHT_SHORT: { // {WEIGHT_SHORT}
01233         assert(_settings_game.locale.units < lengthof(_units));
01234         int64 args_array[1] = {_units[_settings_game.locale.units].c_weight.ToDisplay(args->GetInt64())};
01235         StringParameters tmp_params(args_array);
01236         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].s_weight), &tmp_params, last);
01237         break;
01238       }
01239 
01240       case SCC_WEIGHT_LONG: { // {WEIGHT_LONG}
01241         assert(_settings_game.locale.units < lengthof(_units));
01242         int64 args_array[1] = {_units[_settings_game.locale.units].c_weight.ToDisplay(args->GetInt64(SCC_WEIGHT_LONG))};
01243         StringParameters tmp_params(args_array);
01244         buff = FormatString(buff, GetStringPtr(_units[_settings_game.locale.units].l_weight), &tmp_params, last);
01245         break;
01246       }
01247 
01248       case SCC_COMPANY_NAME: { // {COMPANY}
01249         const Company *c = Company::GetIfValid(args->GetInt32());
01250         if (c == NULL) break;
01251 
01252         if (c->name != NULL) {
01253           int64 args_array[] = {(uint64)(size_t)c->name};
01254           StringParameters tmp_params(args_array);
01255           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01256         } else {
01257           int64 args_array[] = {c->name_2};
01258           StringParameters tmp_params(args_array);
01259           buff = GetStringWithArgs(buff, c->name_1, &tmp_params, last);
01260         }
01261         break;
01262       }
01263 
01264       case SCC_COMPANY_NUM: { // {COMPANY_NUM}
01265         CompanyID company = (CompanyID)args->GetInt32();
01266 
01267         /* Nothing is added for AI or inactive companies */
01268         if (Company::IsValidHumanID(company)) {
01269           int64 args_array[] = {company + 1};
01270           StringParameters tmp_params(args_array);
01271           buff = GetStringWithArgs(buff, STR_FORMAT_COMPANY_NUM, &tmp_params, last);
01272         }
01273         break;
01274       }
01275 
01276       case SCC_DEPOT_NAME: { // {DEPOT}
01277         VehicleType vt = (VehicleType)args->GetInt32(SCC_DEPOT_NAME);
01278         if (vt == VEH_AIRCRAFT) {
01279           uint64 args_array[] = {args->GetInt32()};
01280           WChar types_array[] = {SCC_STATION_NAME};
01281           StringParameters tmp_params(args_array, 1, types_array);
01282           buff = GetStringWithArgs(buff, STR_FORMAT_DEPOT_NAME_AIRCRAFT, &tmp_params, last);
01283           break;
01284         }
01285 
01286         const Depot *d = Depot::Get(args->GetInt32());
01287         if (d->name != NULL) {
01288           int64 args_array[] = {(uint64)(size_t)d->name};
01289           StringParameters tmp_params(args_array);
01290           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01291         } else {
01292           int64 args_array[] = {d->town->index, d->town_cn + 1};
01293           StringParameters tmp_params(args_array);
01294           buff = GetStringWithArgs(buff, STR_FORMAT_DEPOT_NAME_TRAIN + 2 * vt + (d->town_cn == 0 ? 0 : 1), &tmp_params, last);
01295         }
01296         break;
01297       }
01298 
01299       case SCC_ENGINE_NAME: { // {ENGINE}
01300         const Engine *e = Engine::GetIfValid(args->GetInt32(SCC_ENGINE_NAME));
01301         if (e == NULL) break;
01302 
01303         if (e->name != NULL && e->IsEnabled()) {
01304           int64 args_array[] = {(uint64)(size_t)e->name};
01305           StringParameters tmp_params(args_array);
01306           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01307         } else {
01308           StringParameters tmp_params(NULL, 0, NULL);
01309           buff = GetStringWithArgs(buff, e->info.string_id, &tmp_params, last);
01310         }
01311         break;
01312       }
01313 
01314       case SCC_GROUP_NAME: { // {GROUP}
01315         const Group *g = Group::GetIfValid(args->GetInt32());
01316         if (g == NULL) break;
01317 
01318         if (g->name != NULL) {
01319           int64 args_array[] = {(uint64)(size_t)g->name};
01320           StringParameters tmp_params(args_array);
01321           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01322         } else {
01323           int64 args_array[] = {g->index};
01324           StringParameters tmp_params(args_array);
01325 
01326           buff = GetStringWithArgs(buff, STR_FORMAT_GROUP_NAME, &tmp_params, last);
01327         }
01328         break;
01329       }
01330 
01331       case SCC_INDUSTRY_NAME: { // {INDUSTRY}
01332         const Industry *i = Industry::GetIfValid(args->GetInt32(SCC_INDUSTRY_NAME));
01333         if (i == NULL) break;
01334 
01335         if (_scan_for_gender_data) {
01336           /* Gender is defined by the industry type.
01337            * STR_FORMAT_INDUSTRY_NAME may have the town first, so it would result in the gender of the town name */
01338           StringParameters tmp_params(NULL, 0, NULL);
01339           buff = FormatString(buff, GetStringPtr(GetIndustrySpec(i->type)->name), &tmp_params, last, next_substr_case_index);
01340         } else {
01341           /* First print the town name and the industry type name. */
01342           int64 args_array[2] = {i->town->index, GetIndustrySpec(i->type)->name};
01343           StringParameters tmp_params(args_array);
01344 
01345           buff = FormatString(buff, GetStringPtr(STR_FORMAT_INDUSTRY_NAME), &tmp_params, last, next_substr_case_index);
01346         }
01347         next_substr_case_index = 0;
01348         break;
01349       }
01350 
01351       case SCC_PRESIDENT_NAME: { // {PRESIDENT_NAME}
01352         const Company *c = Company::GetIfValid(args->GetInt32(SCC_PRESIDENT_NAME));
01353         if (c == NULL) break;
01354 
01355         if (c->president_name != NULL) {
01356           int64 args_array[] = {(uint64)(size_t)c->president_name};
01357           StringParameters tmp_params(args_array);
01358           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01359         } else {
01360           int64 args_array[] = {c->president_name_2};
01361           StringParameters tmp_params(args_array);
01362           buff = GetStringWithArgs(buff, c->president_name_1, &tmp_params, last);
01363         }
01364         break;
01365       }
01366 
01367       case SCC_STATION_NAME: { // {STATION}
01368         StationID sid = args->GetInt32(SCC_STATION_NAME);
01369         const Station *st = Station::GetIfValid(sid);
01370 
01371         if (st == NULL) {
01372           /* The station doesn't exist anymore. The only place where we might
01373            * be "drawing" an invalid station is in the case of cargo that is
01374            * in transit. */
01375           StringParameters tmp_params(NULL, 0, NULL);
01376           buff = GetStringWithArgs(buff, STR_UNKNOWN_STATION, &tmp_params, last);
01377           break;
01378         }
01379 
01380         if (st->name != NULL) {
01381           int64 args_array[] = {(uint64)(size_t)st->name};
01382           StringParameters tmp_params(args_array);
01383           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01384         } else {
01385           StringID str = st->string_id;
01386           if (st->indtype != IT_INVALID) {
01387             /* Special case where the industry provides the name for the station */
01388             const IndustrySpec *indsp = GetIndustrySpec(st->indtype);
01389 
01390             /* Industry GRFs can change which might remove the station name and
01391              * thus cause very strange things. Here we check for that before we
01392              * actually set the station name. */
01393             if (indsp->station_name != STR_NULL && indsp->station_name != STR_UNDEFINED) {
01394               str = indsp->station_name;
01395             }
01396           }
01397 
01398           int64 args_array[] = {STR_TOWN_NAME, st->town->index, st->index};
01399           StringParameters tmp_params(args_array);
01400           buff = GetStringWithArgs(buff, str, &tmp_params, last);
01401         }
01402         break;
01403       }
01404 
01405       case SCC_TOWN_NAME: { // {TOWN}
01406         const Town *t = Town::GetIfValid(args->GetInt32(SCC_TOWN_NAME));
01407         if (t == NULL) break;
01408 
01409         if (t->name != NULL) {
01410           int64 args_array[] = {(uint64)(size_t)t->name};
01411           StringParameters tmp_params(args_array);
01412           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01413         } else {
01414           buff = GetTownName(buff, t, last);
01415         }
01416         break;
01417       }
01418 
01419       case SCC_WAYPOINT_NAME: { // {WAYPOINT}
01420         Waypoint *wp = Waypoint::GetIfValid(args->GetInt32(SCC_WAYPOINT_NAME));
01421         if (wp == NULL) break;
01422 
01423         if (wp->name != NULL) {
01424           int64 args_array[] = {(uint64)(size_t)wp->name};
01425           StringParameters tmp_params(args_array);
01426           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01427         } else {
01428           int64 args_array[] = {wp->town->index, wp->town_cn + 1};
01429           StringParameters tmp_params(args_array);
01430           StringID str = ((wp->string_id == STR_SV_STNAME_BUOY) ? STR_FORMAT_BUOY_NAME : STR_FORMAT_WAYPOINT_NAME);
01431           if (wp->town_cn != 0) str++;
01432           buff = GetStringWithArgs(buff, str, &tmp_params, last);
01433         }
01434         break;
01435       }
01436 
01437       case SCC_VEHICLE_NAME: { // {VEHICLE}
01438         const Vehicle *v = Vehicle::GetIfValid(args->GetInt32(SCC_VEHICLE_NAME));
01439         if (v == NULL) break;
01440 
01441         if (v->name != NULL) {
01442           int64 args_array[] = {(uint64)(size_t)v->name};
01443           StringParameters tmp_params(args_array);
01444           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01445         } else {
01446           int64 args_array[] = {v->unitnumber};
01447           StringParameters tmp_params(args_array);
01448 
01449           StringID str;
01450           switch (v->type) {
01451             default: NOT_REACHED();
01452             case VEH_TRAIN:    str = STR_SV_TRAIN_NAME; break;
01453             case VEH_ROAD:     str = STR_SV_ROAD_VEHICLE_NAME; break;
01454             case VEH_SHIP:     str = STR_SV_SHIP_NAME; break;
01455             case VEH_AIRCRAFT: str = STR_SV_AIRCRAFT_NAME; break;
01456           }
01457 
01458           buff = GetStringWithArgs(buff, str, &tmp_params, last);
01459         }
01460         break;
01461       }
01462 
01463       case SCC_SIGN_NAME: { // {SIGN}
01464         const Sign *si = Sign::GetIfValid(args->GetInt32());
01465         if (si == NULL) break;
01466 
01467         if (si->name != NULL) {
01468           int64 args_array[] = {(uint64)(size_t)si->name};
01469           StringParameters tmp_params(args_array);
01470           buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last);
01471         } else {
01472           StringParameters tmp_params(NULL, 0, NULL);
01473           buff = GetStringWithArgs(buff, STR_DEFAULT_SIGN_NAME, &tmp_params, last);
01474         }
01475         break;
01476       }
01477 
01478       case SCC_STATION_FEATURES: { // {STATIONFEATURES}
01479         buff = StationGetSpecialString(buff, args->GetInt32(SCC_STATION_FEATURES), last);
01480         break;
01481       }
01482 
01483       default:
01484         if (buff + Utf8CharLen(b) < last) buff += Utf8Encode(buff, b);
01485         break;
01486     }
01487   }
01488   *buff = '\0';
01489   return buff;
01490 }
01491 
01492 
01493 static char *StationGetSpecialString(char *buff, int x, const char *last)
01494 {
01495   if ((x & FACIL_TRAIN)      && (buff + Utf8CharLen(SCC_TRAIN) < last)) buff += Utf8Encode(buff, SCC_TRAIN);
01496   if ((x & FACIL_TRUCK_STOP) && (buff + Utf8CharLen(SCC_LORRY) < last)) buff += Utf8Encode(buff, SCC_LORRY);
01497   if ((x & FACIL_BUS_STOP)   && (buff + Utf8CharLen(SCC_BUS)   < last)) buff += Utf8Encode(buff, SCC_BUS);
01498   if ((x & FACIL_DOCK)       && (buff + Utf8CharLen(SCC_SHIP)  < last)) buff += Utf8Encode(buff, SCC_SHIP);
01499   if ((x & FACIL_AIRPORT)    && (buff + Utf8CharLen(SCC_PLANE) < last)) buff += Utf8Encode(buff, SCC_PLANE);
01500   *buff = '\0';
01501   return buff;
01502 }
01503 
01504 static char *GetSpecialTownNameString(char *buff, int ind, uint32 seed, const char *last)
01505 {
01506   return GenerateTownNameString(buff, last, ind, seed);
01507 }
01508 
01509 static const char * const _silly_company_names[] = {
01510   "Bloggs Brothers",
01511   "Tiny Transport Ltd.",
01512   "Express Travel",
01513   "Comfy-Coach & Co.",
01514   "Crush & Bump Ltd.",
01515   "Broken & Late Ltd.",
01516   "Sam Speedy & Son",
01517   "Supersonic Travel",
01518   "Mike's Motors",
01519   "Lightning International",
01520   "Pannik & Loozit Ltd.",
01521   "Inter-City Transport",
01522   "Getout & Pushit Ltd."
01523 };
01524 
01525 static const char * const _surname_list[] = {
01526   "Adams",
01527   "Allan",
01528   "Baker",
01529   "Bigwig",
01530   "Black",
01531   "Bloggs",
01532   "Brown",
01533   "Campbell",
01534   "Gordon",
01535   "Hamilton",
01536   "Hawthorn",
01537   "Higgins",
01538   "Green",
01539   "Gribble",
01540   "Jones",
01541   "McAlpine",
01542   "MacDonald",
01543   "McIntosh",
01544   "Muir",
01545   "Murphy",
01546   "Nelson",
01547   "O'Donnell",
01548   "Parker",
01549   "Phillips",
01550   "Pilkington",
01551   "Quigley",
01552   "Sharkey",
01553   "Thomson",
01554   "Watkins"
01555 };
01556 
01557 static const char * const _silly_surname_list[] = {
01558   "Grumpy",
01559   "Dozy",
01560   "Speedy",
01561   "Nosey",
01562   "Dribble",
01563   "Mushroom",
01564   "Cabbage",
01565   "Sniffle",
01566   "Fishy",
01567   "Swindle",
01568   "Sneaky",
01569   "Nutkins"
01570 };
01571 
01572 static const char _initial_name_letters[] = {
01573   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
01574   'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W',
01575 };
01576 
01577 static char *GenAndCoName(char *buff, uint32 arg, const char *last)
01578 {
01579   const char * const *base;
01580   uint num;
01581 
01582   if (_settings_game.game_creation.landscape == LT_TOYLAND) {
01583     base = _silly_surname_list;
01584     num  = lengthof(_silly_surname_list);
01585   } else {
01586     base = _surname_list;
01587     num  = lengthof(_surname_list);
01588   }
01589 
01590   buff = strecpy(buff, base[num * GB(arg, 16, 8) >> 8], last);
01591   buff = strecpy(buff, " & Co.", last);
01592 
01593   return buff;
01594 }
01595 
01596 static char *GenPresidentName(char *buff, uint32 x, const char *last)
01597 {
01598   char initial[] = "?. ";
01599   const char * const *base;
01600   uint num;
01601   uint i;
01602 
01603   initial[0] = _initial_name_letters[sizeof(_initial_name_letters) * GB(x, 0, 8) >> 8];
01604   buff = strecpy(buff, initial, last);
01605 
01606   i = (sizeof(_initial_name_letters) + 35) * GB(x, 8, 8) >> 8;
01607   if (i < sizeof(_initial_name_letters)) {
01608     initial[0] = _initial_name_letters[i];
01609     buff = strecpy(buff, initial, last);
01610   }
01611 
01612   if (_settings_game.game_creation.landscape == LT_TOYLAND) {
01613     base = _silly_surname_list;
01614     num  = lengthof(_silly_surname_list);
01615   } else {
01616     base = _surname_list;
01617     num  = lengthof(_surname_list);
01618   }
01619 
01620   buff = strecpy(buff, base[num * GB(x, 16, 8) >> 8], last);
01621 
01622   return buff;
01623 }
01624 
01625 static char *GetSpecialNameString(char *buff, int ind, StringParameters *args, const char *last)
01626 {
01627   switch (ind) {
01628     case 1: // not used
01629       return strecpy(buff, _silly_company_names[min(args->GetInt32() & 0xFFFF, lengthof(_silly_company_names) - 1)], last);
01630 
01631     case 2: // used for Foobar & Co company names
01632       return GenAndCoName(buff, args->GetInt32(), last);
01633 
01634     case 3: // President name
01635       return GenPresidentName(buff, args->GetInt32(), last);
01636   }
01637 
01638   /* town name? */
01639   if (IsInsideMM(ind - 6, 0, SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1)) {
01640     buff = GetSpecialTownNameString(buff, ind - 6, args->GetInt32(), last);
01641     return strecpy(buff, " Transport", last);
01642   }
01643 
01644   /* language name? */
01645   if (IsInsideMM(ind, (SPECSTR_LANGUAGE_START - 0x70E4), (SPECSTR_LANGUAGE_END - 0x70E4) + 1)) {
01646     int i = ind - (SPECSTR_LANGUAGE_START - 0x70E4);
01647     return strecpy(buff,
01648       &_languages[i] == _current_language ? _current_language->own_name : _languages[i].name, last);
01649   }
01650 
01651   /* resolution size? */
01652   if (IsInsideMM(ind, (SPECSTR_RESOLUTION_START - 0x70E4), (SPECSTR_RESOLUTION_END - 0x70E4) + 1)) {
01653     int i = ind - (SPECSTR_RESOLUTION_START - 0x70E4);
01654     buff += seprintf(
01655       buff, last, "%ux%u", _resolutions[i].width, _resolutions[i].height
01656     );
01657     return buff;
01658   }
01659 
01660   /* screenshot format name? */
01661   if (IsInsideMM(ind, (SPECSTR_SCREENSHOT_START - 0x70E4), (SPECSTR_SCREENSHOT_END - 0x70E4) + 1)) {
01662     int i = ind - (SPECSTR_SCREENSHOT_START - 0x70E4);
01663     return strecpy(buff, GetScreenshotFormatDesc(i), last);
01664   }
01665 
01666   NOT_REACHED();
01667 }
01668 
01669 #ifdef ENABLE_NETWORK
01670 extern void SortNetworkLanguages();
01671 #else /* ENABLE_NETWORK */
01672 static inline void SortNetworkLanguages() {}
01673 #endif /* ENABLE_NETWORK */
01674 
01679 bool LanguagePackHeader::IsValid() const
01680 {
01681   return this->ident        == TO_LE32(LanguagePackHeader::IDENT) &&
01682          this->version      == TO_LE32(LANGUAGE_PACK_VERSION) &&
01683          this->plural_form  <  LANGUAGE_MAX_PLURAL &&
01684          this->text_dir     <= 1 &&
01685          this->newgrflangid < MAX_LANG &&
01686          this->num_genders  < MAX_NUM_GENDERS &&
01687          this->num_cases    < MAX_NUM_CASES &&
01688          StrValid(this->name,                           lastof(this->name)) &&
01689          StrValid(this->own_name,                       lastof(this->own_name)) &&
01690          StrValid(this->isocode,                        lastof(this->isocode)) &&
01691          StrValid(this->digit_group_separator,          lastof(this->digit_group_separator)) &&
01692          StrValid(this->digit_group_separator_currency, lastof(this->digit_group_separator_currency)) &&
01693          StrValid(this->digit_decimal_separator,        lastof(this->digit_decimal_separator));
01694 }
01695 
01701 bool ReadLanguagePack(const LanguageMetadata *lang)
01702 {
01703   /* Current language pack */
01704   size_t len;
01705   LanguagePack *lang_pack = (LanguagePack *)ReadFileToMem(lang->file, &len, 1U << 20);
01706   if (lang_pack == NULL) return false;
01707 
01708   /* End of read data (+ terminating zero added in ReadFileToMem()) */
01709   const char *end = (char *)lang_pack + len + 1;
01710 
01711   /* We need at least one byte of lang_pack->data */
01712   if (end <= lang_pack->data || !lang_pack->IsValid()) {
01713     free(lang_pack);
01714     return false;
01715   }
01716 
01717 #if TTD_ENDIAN == TTD_BIG_ENDIAN
01718   for (uint i = 0; i < TAB_COUNT; i++) {
01719     lang_pack->offsets[i] = ReadLE16Aligned(&lang_pack->offsets[i]);
01720   }
01721 #endif /* TTD_ENDIAN == TTD_BIG_ENDIAN */
01722 
01723   uint count = 0;
01724   for (uint i = 0; i < TAB_COUNT; i++) {
01725     uint num = lang_pack->offsets[i];
01726     _langtab_start[i] = count;
01727     _langtab_num[i] = num;
01728     count += num;
01729   }
01730 
01731   /* Allocate offsets */
01732   char **langpack_offs = MallocT<char *>(count);
01733 
01734   /* Fill offsets */
01735   char *s = lang_pack->data;
01736   len = (byte)*s++;
01737   for (uint i = 0; i < count; i++) {
01738     if (s + len >= end) {
01739       free(lang_pack);
01740       free(langpack_offs);
01741       return false;
01742     }
01743     if (len >= 0xC0) {
01744       len = ((len & 0x3F) << 8) + (byte)*s++;
01745       if (s + len >= end) {
01746         free(lang_pack);
01747         free(langpack_offs);
01748         return false;
01749       }
01750     }
01751     langpack_offs[i] = s;
01752     s += len;
01753     len = (byte)*s;
01754     *s++ = '\0'; // zero terminate the string
01755   }
01756 
01757   free(_langpack);
01758   _langpack = lang_pack;
01759 
01760   free(_langpack_offs);
01761   _langpack_offs = langpack_offs;
01762 
01763   _current_language = lang;
01764   _current_text_dir = (TextDirection)_current_language->text_dir;
01765   const char *c_file = strrchr(_current_language->file, PATHSEPCHAR) + 1;
01766   strecpy(_config_language_file, c_file, lastof(_config_language_file));
01767   SetCurrentGrfLangID(_current_language->newgrflangid);
01768 
01769 #ifdef WITH_ICU
01770   /* Delete previous collator. */
01771   if (_current_collator != NULL) {
01772     delete _current_collator;
01773     _current_collator = NULL;
01774   }
01775 
01776   /* Create a collator instance for our current locale. */
01777   UErrorCode status = U_ZERO_ERROR;
01778   _current_collator = Collator::createInstance(Locale(_current_language->isocode), status);
01779   /* Sort number substrings by their numerical value. */
01780   if (_current_collator != NULL) _current_collator->setAttribute(UCOL_NUMERIC_COLLATION, UCOL_ON, status);
01781   /* Avoid using the collator if it is not correctly set. */
01782   if (U_FAILURE(status)) {
01783     delete _current_collator;
01784     _current_collator = NULL;
01785   }
01786 #endif /* WITH_ICU */
01787 
01788   /* Some lists need to be sorted again after a language change. */
01789   ReconsiderGameScriptLanguage();
01790   InitializeSortedCargoSpecs();
01791   SortIndustryTypes();
01792   BuildIndustriesLegend();
01793   SortNetworkLanguages();
01794   InvalidateWindowClassesData(WC_BUILD_VEHICLE);      // Build vehicle window.
01795   InvalidateWindowClassesData(WC_TRAINS_LIST);        // Train group window.
01796   InvalidateWindowClassesData(WC_ROADVEH_LIST);       // Road vehicle group window.
01797   InvalidateWindowClassesData(WC_SHIPS_LIST);         // Ship group window.
01798   InvalidateWindowClassesData(WC_AIRCRAFT_LIST);      // Aircraft group window.
01799   InvalidateWindowClassesData(WC_INDUSTRY_DIRECTORY); // Industry directory window.
01800   InvalidateWindowClassesData(WC_STATION_LIST);       // Station list window.
01801 
01802   return true;
01803 }
01804 
01805 /* Win32 implementation in win32.cpp.
01806  * OS X implementation in os/macosx/macos.mm. */
01807 #if !(defined(WIN32) || defined(__APPLE__))
01808 
01816 const char *GetCurrentLocale(const char *param)
01817 {
01818   const char *env;
01819 
01820   env = getenv("LANGUAGE");
01821   if (env != NULL) return env;
01822 
01823   env = getenv("LC_ALL");
01824   if (env != NULL) return env;
01825 
01826   if (param != NULL) {
01827     env = getenv(param);
01828     if (env != NULL) return env;
01829   }
01830 
01831   return getenv("LANG");
01832 }
01833 #else
01834 const char *GetCurrentLocale(const char *param);
01835 #endif /* !(defined(WIN32) || defined(__APPLE__)) */
01836 
01837 int CDECL StringIDSorter(const StringID *a, const StringID *b)
01838 {
01839   char stra[512];
01840   char strb[512];
01841   GetString(stra, *a, lastof(stra));
01842   GetString(strb, *b, lastof(strb));
01843 
01844   return strcmp(stra, strb);
01845 }
01846 
01852 const LanguageMetadata *GetLanguage(byte newgrflangid)
01853 {
01854   for (const LanguageMetadata *lang = _languages.Begin(); lang != _languages.End(); lang++) {
01855     if (newgrflangid == lang->newgrflangid) return lang;
01856   }
01857 
01858   return NULL;
01859 }
01860 
01867 static bool GetLanguageFileHeader(const char *file, LanguagePackHeader *hdr)
01868 {
01869   FILE *f = fopen(file, "rb");
01870   if (f == NULL) return false;
01871 
01872   size_t read = fread(hdr, sizeof(*hdr), 1, f);
01873   fclose(f);
01874 
01875   bool ret = read == 1 && hdr->IsValid();
01876 
01877   /* Convert endianness for the windows language ID */
01878   if (ret) {
01879     hdr->missing = FROM_LE16(hdr->missing);
01880     hdr->winlangid = FROM_LE16(hdr->winlangid);
01881   }
01882   return ret;
01883 }
01884 
01889 static void GetLanguageList(const char *path)
01890 {
01891   DIR *dir = ttd_opendir(path);
01892   if (dir != NULL) {
01893     struct dirent *dirent;
01894     while ((dirent = readdir(dir)) != NULL) {
01895       const char *d_name    = FS2OTTD(dirent->d_name);
01896       const char *extension = strrchr(d_name, '.');
01897 
01898       /* Not a language file */
01899       if (extension == NULL || strcmp(extension, ".lng") != 0) continue;
01900 
01901       LanguageMetadata lmd;
01902       seprintf(lmd.file, lastof(lmd.file), "%s%s", path, d_name);
01903 
01904       /* Check whether the file is of the correct version */
01905       if (!GetLanguageFileHeader(lmd.file, &lmd)) {
01906         DEBUG(misc, 3, "%s is not a valid language file", lmd.file);
01907       } else if (GetLanguage(lmd.newgrflangid) != NULL) {
01908         DEBUG(misc, 3, "%s's language ID is already known", lmd.file);
01909       } else {
01910         *_languages.Append() = lmd;
01911       }
01912     }
01913     closedir(dir);
01914   }
01915 }
01916 
01921 void InitializeLanguagePacks()
01922 {
01923   Searchpath sp;
01924 
01925   FOR_ALL_SEARCHPATHS(sp) {
01926     char path[MAX_PATH];
01927     FioAppendDirectory(path, lengthof(path), sp, LANG_DIR);
01928     GetLanguageList(path);
01929   }
01930   if (_languages.Length() == 0) usererror("No available language packs (invalid versions?)");
01931 
01932   /* Acquire the locale of the current system */
01933   const char *lang = GetCurrentLocale("LC_MESSAGES");
01934   if (lang == NULL) lang = "en_GB";
01935 
01936   const LanguageMetadata *chosen_language   = NULL; 
01937   const LanguageMetadata *language_fallback = NULL; 
01938   const LanguageMetadata *en_GB_fallback    = _languages.Begin(); 
01939 
01940   /* Find a proper language. */
01941   for (const LanguageMetadata *lng = _languages.Begin(); lng != _languages.End(); lng++) {
01942     /* We are trying to find a default language. The priority is by
01943      * configuration file, local environment and last, if nothing found,
01944      * English. */
01945     const char *lang_file = strrchr(lng->file, PATHSEPCHAR) + 1;
01946     if (strcmp(lang_file, _config_language_file) == 0) {
01947       chosen_language = lng;
01948       break;
01949     }
01950 
01951     if (strcmp (lng->isocode, "en_GB") == 0) en_GB_fallback    = lng;
01952     if (strncmp(lng->isocode, lang, 5) == 0) chosen_language   = lng;
01953     if (strncmp(lng->isocode, lang, 2) == 0) language_fallback = lng;
01954   }
01955 
01956   /* We haven't found the language in the config nor the one in the locale.
01957    * Now we set it to one of the fallback languages */
01958   if (chosen_language == NULL) {
01959     chosen_language = (language_fallback != NULL) ? language_fallback : en_GB_fallback;
01960   }
01961 
01962   if (!ReadLanguagePack(chosen_language)) usererror("Can't read language pack '%s'", chosen_language->file);
01963 }
01964 
01969 const char *GetCurrentLanguageIsoCode()
01970 {
01971   return _langpack->isocode;
01972 }
01973 
01980 bool MissingGlyphSearcher::FindMissingGlyphs(const char **str)
01981 {
01982   InitFreeType(this->Monospace());
01983   const Sprite *question_mark[FS_END];
01984 
01985   for (FontSize size = this->Monospace() ? FS_MONO : FS_BEGIN; size < (this->Monospace() ? FS_END : FS_MONO); size++) {
01986     question_mark[size] = GetGlyph(size, '?');
01987   }
01988 
01989   this->Reset();
01990   for (const char *text = this->NextString(); text != NULL; text = this->NextString()) {
01991     FontSize size = this->DefaultSize();
01992     if (str != NULL) *str = text;
01993     for (WChar c = Utf8Consume(&text); c != '\0'; c = Utf8Consume(&text)) {
01994       if (c == SCC_SETX) {
01995         /* SetX is, together with SetXY as special character that
01996           * uses the next (two) characters as data points. We have
01997           * to skip those, otherwise the UTF8 reading will go haywire. */
01998         text++;
01999       } else if (c == SCC_SETXY) {
02000         text += 2;
02001       } else if (c == SCC_TINYFONT) {
02002         size = FS_SMALL;
02003       } else if (c == SCC_BIGFONT) {
02004         size = FS_LARGE;
02005       } else if (!IsInsideMM(c, SCC_SPRITE_START, SCC_SPRITE_END) && IsPrintable(c) && !IsTextDirectionChar(c) && c != '?' && GetGlyph(size, c) == question_mark[size]) {
02006         /* The character is printable, but not in the normal font. This is the case we were testing for. */
02007         return true;
02008       }
02009     }
02010   }
02011   return false;
02012 }
02013 
02015 class LanguagePackGlyphSearcher : public MissingGlyphSearcher {
02016   uint i; 
02017   uint j; 
02018 
02019   /* virtual */ void Reset()
02020   {
02021     this->i = 0;
02022     this->j = 0;
02023   }
02024 
02025   /* virtual */ FontSize DefaultSize()
02026   {
02027     return FS_NORMAL;
02028   }
02029 
02030   /* virtual */ const char *NextString()
02031   {
02032     if (this->i >= TAB_COUNT) return NULL;
02033 
02034     const char *ret = _langpack_offs[_langtab_start[i] + j];
02035 
02036     this->j++;
02037     while (this->j >= _langtab_num[this->i] && this->i < TAB_COUNT) {
02038       i++;
02039       j = 0;
02040     }
02041 
02042     return ret;
02043   }
02044 
02045   /* virtual */ bool Monospace()
02046   {
02047     return false;
02048   }
02049 
02050   /* virtual */ void SetFontNames(FreeTypeSettings *settings, const char *font_name)
02051   {
02052 #ifdef WITH_FREETYPE
02053     strecpy(settings->small_font,  font_name, lastof(settings->small_font));
02054     strecpy(settings->medium_font, font_name, lastof(settings->medium_font));
02055     strecpy(settings->large_font,  font_name, lastof(settings->large_font));
02056 #endif /* WITH_FREETYPE */
02057   }
02058 };
02059 
02073 void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher)
02074 {
02075   static LanguagePackGlyphSearcher pack_searcher;
02076   if (searcher == NULL) searcher = &pack_searcher;
02077   bool bad_font = !base_font || searcher->FindMissingGlyphs(NULL);
02078 #ifdef WITH_FREETYPE
02079   if (bad_font) {
02080     /* We found an unprintable character... lets try whether we can find
02081      * a fallback font that can print the characters in the current language. */
02082     FreeTypeSettings backup;
02083     memcpy(&backup, &_freetype, sizeof(backup));
02084 
02085     bad_font = !SetFallbackFont(&_freetype, _langpack->isocode, _langpack->winlangid, searcher);
02086 
02087     memcpy(&_freetype, &backup, sizeof(backup));
02088 
02089     if (bad_font && base_font) {
02090       /* Our fallback font does miss characters too, so keep the
02091        * user chosen font as that is more likely to be any good than
02092        * the wild guess we made */
02093       InitFreeType(searcher->Monospace());
02094     }
02095   }
02096 #endif
02097 
02098   if (bad_font) {
02099     /* All attempts have failed. Display an error. As we do not want the string to be translated by
02100      * the translators, we 'force' it into the binary and 'load' it via a BindCString. To do this
02101      * properly we have to set the colour of the string, otherwise we end up with a lot of artefacts.
02102      * The colour 'character' might change in the future, so for safety we just Utf8 Encode it into
02103      * the string, which takes exactly three characters, so it replaces the "XXX" with the colour marker. */
02104     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.");
02105     Utf8Encode(err_str, SCC_YELLOW);
02106     SetDParamStr(0, err_str);
02107     ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_WARNING);
02108 
02109     /* Reset the font width */
02110     LoadStringWidthTable(searcher->Monospace());
02111     return;
02112   }
02113 
02114   /* Update the font with cache */
02115   LoadStringWidthTable(searcher->Monospace());
02116 
02117 #if !defined(WITH_ICU)
02118   /*
02119    * For right-to-left languages we need the ICU library. If
02120    * we do not have support for that library we warn the user
02121    * about it with a message. As we do not want the string to
02122    * be translated by the translators, we 'force' it into the
02123    * binary and 'load' it via a BindCString. To do this
02124    * properly we have to set the colour of the string,
02125    * otherwise we end up with a lot of artefacts. The colour
02126    * 'character' might change in the future, so for safety
02127    * we just Utf8 Encode it into the string, which takes
02128    * exactly three characters, so it replaces the "XXX" with
02129    * the colour marker.
02130    */
02131   if (_current_text_dir != TD_LTR) {
02132     static char *err_str = strdup("XXXThis version of OpenTTD does not support right-to-left languages. Recompile with icu enabled.");
02133     Utf8Encode(err_str, SCC_YELLOW);
02134     SetDParamStr(0, err_str);
02135     ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_ERROR);
02136   }
02137 #endif
02138 }