33 #include "table/strings.h" 
   47   GRFLB_AMERICAN    = 0x01,
 
   55 enum GRFExtendedLanguages {
 
   56   GRFLX_AMERICAN    = 0x00,
 
   61   GRFLX_UNSPECIFIED = 0x7F,
 
  101   void *
operator new(
size_t size)
 
  110   void operator delete(
void *p)
 
  126     memcpy(this->
text, text_, 
len);
 
  135   void *
operator new(
size_t size, 
size_t extra)
 
  137     return MallocT<byte>(size + extra);
 
  161 static uint _num_grf_texts = 0;
 
  175     if (m->newgrf_id == newgrf_id) 
return m->openttd_id;
 
  190     if (m->openttd_id == openttd_id) 
return m->newgrf_id;
 
  212     type(type), old_d(old_d), offset(offset)
 
  233       grfmsg(1, 
"choice list misses default value");
 
  242       size_t len = strlen(this->
strings[0]);
 
  243       memcpy(d, this->
strings[0], len);
 
  249     if (this->
type == SCC_SWITCH_CASE) {
 
  268         char *str = this->
strings[idx];
 
  274         size_t len = strlen(str) + 1;
 
  275         *d++ = 
GB(len, 8, 8);
 
  276         *d++ = 
GB(len, 0, 8);
 
  284       size_t len = strlen(this->
strings[0]) + 1;
 
  285       memcpy(d, this->
strings[0], len);
 
  288       if (this->
type == SCC_PLURAL_LIST) {
 
  298       *d++ = this->
offset - 0x80;
 
  305       for (
int i = 0; i < count; i++) {
 
  308         size_t len = strlen(str) + 1;
 
  309         if (len > 0xFF) 
grfmsg(1, 
"choice list string is too long");
 
  310         *d++ = 
GB(len, 0, 8);
 
  314       for (
int i = 0; i < count; i++) {
 
  319         size_t len = min<size_t>(0xFE, strlen(str));
 
  341   char *tmp = MallocT<char>(strlen(str) * 10 + 1); 
 
  343   bool unicode = 
false;
 
  357       c = Utf8Consume(&str);
 
  359       if (
GB(c, 8, 8) == 0xE0) {
 
  361       } 
else if (c >= 0x20) {
 
  369     if (c == 
'\0') 
break;
 
  373         if (str[0] == 
'\0') 
goto string_end;
 
  379         if (allow_newlines) {
 
  382           grfmsg(1, 
"Detected newline in string that does not allow one");
 
  388         if (str[0] == 
'\0' || str[1] == 
'\0') 
goto string_end;
 
  399         if (str[0] == 
'\0' || str[1] == 
'\0') 
goto string_end;
 
  401         string  = ((uint8)*str++);
 
  402         string |= ((uint8)*str++) << 8;
 
  413       case 0x88: d += 
Utf8Encode(d, SCC_BLUE);    
break;
 
  414       case 0x89: d += 
Utf8Encode(d, SCC_SILVER);  
break;
 
  415       case 0x8A: d += 
Utf8Encode(d, SCC_GOLD);    
break;
 
  416       case 0x8B: d += 
Utf8Encode(d, SCC_RED);     
break;
 
  417       case 0x8C: d += 
Utf8Encode(d, SCC_PURPLE);  
break;
 
  418       case 0x8D: d += 
Utf8Encode(d, SCC_LTBROWN); 
break;
 
  419       case 0x8E: d += 
Utf8Encode(d, SCC_ORANGE);  
break;
 
  420       case 0x8F: d += 
Utf8Encode(d, SCC_GREEN);   
break;
 
  421       case 0x90: d += 
Utf8Encode(d, SCC_YELLOW);  
break;
 
  422       case 0x91: d += 
Utf8Encode(d, SCC_DKGREEN); 
break;
 
  423       case 0x92: d += 
Utf8Encode(d, SCC_CREAM);   
break;
 
  424       case 0x93: d += 
Utf8Encode(d, SCC_BROWN);   
break;
 
  425       case 0x94: d += 
Utf8Encode(d, SCC_WHITE);   
break;
 
  426       case 0x95: d += 
Utf8Encode(d, SCC_LTBLUE);  
break;
 
  427       case 0x96: d += 
Utf8Encode(d, SCC_GRAY);    
break;
 
  428       case 0x97: d += 
Utf8Encode(d, SCC_DKBLUE);  
break;
 
  429       case 0x98: d += 
Utf8Encode(d, SCC_BLACK);   
break;
 
  433           case 0x00: 
goto string_end;
 
  443             if (str[0] == 
'\0' || str[1] == 
'\0') 
goto string_end;
 
  444             uint16 tmp  = ((uint8)*str++);
 
  445             tmp        |= ((uint8)*str++) << 8;
 
  451             if (str[0] == 
'\0') 
goto string_end;
 
  464             if (str[0] == 
'\0') 
goto string_end;
 
  467             int mapped = lm != NULL ? lm->
GetMapping(index, code == 0x0E) : -1;
 
  469               d += 
Utf8Encode(d, code == 0x0E ? SCC_GENDER_INDEX : SCC_SET_CASE);
 
  470               d += 
Utf8Encode(d, code == 0x0E ? mapped : mapped + 1);
 
  477             if (str[0] == 
'\0') 
goto string_end;
 
  478             if (mapping == NULL) {
 
  479               if (code == 0x10) str++; 
 
  480               grfmsg(1, 
"choice list %s marker found when not expected", code == 0x10 ? 
"next" : 
"default");
 
  485               int index = (code == 0x10 ? *str++ : 0);
 
  487                 grfmsg(1, 
"duplicate choice list string, ignoring");
 
  490                 d = mapping->
strings[index] = MallocT<char>(strlen(str) * 10 + 1);
 
  496             if (mapping == NULL) {
 
  497               grfmsg(1, 
"choice list end marker found when not expected");
 
  512             if (str[0] == 
'\0') 
goto string_end;
 
  513             if (mapping != NULL) {
 
  514               grfmsg(1, 
"choice lists can't be stacked, it's going to get messy now...");
 
  515               if (code != 0x14) str++;
 
  517               static const StringControlCode mp[] = { SCC_GENDER_LIST, SCC_SWITCH_CASE, SCC_PLURAL_LIST };
 
  535             grfmsg(1, 
"missing handler for extended format code");
 
  543       case 0xA0: d += 
Utf8Encode(d, SCC_UP_ARROW);         
break;
 
  544       case 0xAA: d += 
Utf8Encode(d, SCC_DOWN_ARROW);       
break;
 
  545       case 0xAC: d += 
Utf8Encode(d, SCC_CHECKMARK);        
break;
 
  546       case 0xAD: d += 
Utf8Encode(d, SCC_CROSS);            
break;
 
  547       case 0xAF: d += 
Utf8Encode(d, SCC_RIGHT_ARROW);      
break;
 
  548       case 0xB4: d += 
Utf8Encode(d, SCC_TRAIN);            
break;
 
  549       case 0xB5: d += 
Utf8Encode(d, SCC_LORRY);            
break;
 
  550       case 0xB6: d += 
Utf8Encode(d, SCC_BUS);              
break;
 
  551       case 0xB7: d += 
Utf8Encode(d, SCC_PLANE);            
break;
 
  552       case 0xB8: d += 
Utf8Encode(d, SCC_SHIP);             
break;
 
  553       case 0xB9: d += 
Utf8Encode(d, SCC_SUPERSCRIPT_M1);   
break;
 
  554       case 0xBC: d += 
Utf8Encode(d, SCC_SMALL_UP_ARROW);   
break;
 
  555       case 0xBD: d += 
Utf8Encode(d, SCC_SMALL_DOWN_ARROW); 
break;
 
  565   if (mapping != NULL) {
 
  566     grfmsg(1, 
"choice list was incomplete, the whole list is ignored");
 
  571   if (olen != NULL) *olen = d - tmp + 1;
 
  586   for (ptext = list; (text = *ptext) != NULL; ptext = &text->
next) {
 
  589       *ptext = text_to_add;
 
  596   *ptext = text_to_add;
 
  613   free(translatedtext);
 
  638   for (; orig != NULL; orig = orig->
next) {
 
  640     ptext = &(*ptext)->
next;
 
  648 StringID AddGRFString(uint32 grfid, uint16 stringid, byte langid_to_add, 
bool new_scheme, 
bool allow_newlines, 
const char *text_to_add, 
StringID def_string)
 
  650   char *translatedtext;
 
  660     if (langid_to_add & (GRFLB_AMERICAN | GRFLB_ENGLISH)) {
 
  661       langid_to_add = GRFLX_ENGLISH;
 
  664       if (langid_to_add & GRFLB_GERMAN)  ret = 
AddGRFString(grfid, stringid, GRFLX_GERMAN,  
true, allow_newlines, text_to_add, def_string);
 
  665       if (langid_to_add & GRFLB_FRENCH)  ret = 
AddGRFString(grfid, stringid, GRFLX_FRENCH,  
true, allow_newlines, text_to_add, def_string);
 
  666       if (langid_to_add & GRFLB_SPANISH) ret = 
AddGRFString(grfid, stringid, GRFLX_SPANISH, 
true, allow_newlines, text_to_add, def_string);
 
  671   for (
id = 0; 
id < _num_grf_texts; 
id++) {
 
  672     if (_grf_text[
id].grfid == grfid && _grf_text[
id].stringid == stringid) {
 
  678   if (
id == 
lengthof(_grf_text)) 
return STR_EMPTY;
 
  685   free(translatedtext);
 
  688   if (
id == _num_grf_texts) _num_grf_texts++;
 
  690   if (_grf_text[
id].textholder == NULL) {
 
  691     _grf_text[id].grfid      = grfid;
 
  692     _grf_text[id].stringid   = stringid;
 
  693     _grf_text[id].def_string = def_string;
 
  697   grfmsg(3, 
"Added 0x%X: grfid %08X string 0x%X lang 0x%X string '%s'", 
id, grfid, stringid, newtext->
langid, newtext->
text);
 
  699   return (GRFTAB << TABSIZE) + id;
 
  707   for (uint 
id = 0; 
id < _num_grf_texts; 
id++) {
 
  708     if (_grf_text[
id].grfid == grfid && _grf_text[
id].stringid == stringid) {
 
  709       return (GRFTAB << TABSIZE) + id;
 
  713   return STR_UNDEFINED;
 
  726   const char *default_text = NULL;
 
  729   for (; text != NULL; text = text->
next) {
 
  734     if (text->
langid == GRFLX_UNSPECIFIED || (default_text == NULL && (text->
langid == GRFLX_ENGLISH || text->
langid == GRFLX_AMERICAN))) {
 
  735       default_text = text->
text;
 
  747   assert(_grf_text[stringid].grfid != 0);
 
  750   if (str != NULL) 
return str;
 
  753   return GetStringPtr(_grf_text[stringid].def_string);
 
  769 bool CheckGrfLangID(byte lang_id, byte grf_version)
 
  771   if (grf_version < 7) {
 
  773       case GRFLX_GERMAN:  
return (lang_id & GRFLB_GERMAN)  != 0;
 
  774       case GRFLX_FRENCH:  
return (lang_id & GRFLB_FRENCH)  != 0;
 
  775       case GRFLX_SPANISH: 
return (lang_id & GRFLB_SPANISH) != 0;
 
  776       default:            
return (lang_id & (GRFLB_ENGLISH | GRFLB_AMERICAN)) != 0;
 
  780   return (lang_id == 
_currentLangID || lang_id == GRFLX_UNSPECIFIED);
 
  789   while (grftext != NULL) {
 
  804   for (
id = 0; 
id < _num_grf_texts; 
id++) {
 
  806     _grf_text[id].grfid      = 0;
 
  807     _grf_text[id].stringid   = 0;
 
  808     _grf_text[id].textholder = NULL;
 
  820   TextRefStack() : position(0), grffile(NULL), used(
false) {}
 
  823     position(stack.position),
 
  824     grffile(stack.grffile),
 
  827     memcpy(this->stack, stack.stack, 
sizeof(this->stack));
 
  830   uint8  PopUnsignedByte()  { assert(this->position < 
lengthof(this->stack)); 
return this->stack[this->position++]; }
 
  831   int8   PopSignedByte()    { 
return (int8)this->PopUnsignedByte(); }
 
  833   uint16 PopUnsignedWord()
 
  835     uint16 val = this->PopUnsignedByte();
 
  836     return val | (this->PopUnsignedByte() << 8);
 
  838   int16  PopSignedWord()    { 
return (int32)this->PopUnsignedWord(); }
 
  840   uint32 PopUnsignedDWord()
 
  842     uint32 val = this->PopUnsignedWord();
 
  843     return val | (this->PopUnsignedWord() << 16);
 
  845   int32  PopSignedDWord()   { 
return (int32)this->PopUnsignedDWord(); }
 
  847   uint64 PopUnsignedQWord()
 
  849     uint64 val = this->PopUnsignedDWord();
 
  850     return val | (((uint64)this->PopUnsignedDWord()) << 32);
 
  852   int64  PopSignedQWord()   { 
return (int64)this->PopUnsignedQWord(); }
 
  858     for (
int i = 0; i  < 2; i++) tmp[i] = this->stack[this->position + i + 6];
 
  859     for (
int i = 5; i >= 0; i--) this->stack[this->position + i + 2] = this->stack[this->position + i];
 
  860     for (
int i = 0; i  < 2; i++) this->stack[this->position + i] = tmp[i];
 
  863   void PushWord(uint16 word)
 
  865     if (this->position >= 2) {
 
  868       for (
int i = 
lengthof(stack) - 1; i >= this->position + 2; i--) {
 
  869         this->stack[i] = this->stack[i - 2];
 
  872     this->stack[this->position]     = 
GB(word, 0, 8);
 
  873     this->stack[this->position + 1] = 
GB(word, 8, 8);
 
  876   void ResetStack(
const GRFFile *grffile)
 
  878     assert(grffile != NULL);
 
  880     this->grffile = grffile;
 
  884   void RewindStack() { this->position = 0; }
 
  896   return _newgrf_textrefstack.used;
 
  914   _newgrf_textrefstack = *backup;
 
  940   _newgrf_textrefstack.ResetStack(grffile);
 
  942   byte *p = _newgrf_textrefstack.stack;
 
  943   for (uint i = 0; i < numEntries; i++) {
 
  944     uint32 value = values != NULL ? values[i] : _temp_store.
GetValue(0x100 + i);
 
  945     for (uint j = 0; j < 32; j += 8) {
 
  946       *p = 
GB(value, j, 8);
 
  955   _newgrf_textrefstack.used = 
false;
 
  958 void RewindTextRefStack()
 
  960   _newgrf_textrefstack.RewindStack();
 
 1001       if (argv_size < 1) {
 
 1002         DEBUG(misc, 0, 
"Too many NewGRF string parameters.");
 
 1010       if (argv_size < 2) {
 
 1011         DEBUG(misc, 0, 
"Too many NewGRF string parameters.");
 
 1017   if (_newgrf_textrefstack.used && modify_argv) {
 
 1019       default: NOT_REACHED();
 
 1057         argv[0] = 
GetCargoTranslation(_newgrf_textrefstack.PopUnsignedWord(), _newgrf_textrefstack.grffile);
 
 1058         argv[1] = _newgrf_textrefstack.PopUnsignedWord();
 
 1062         *argv = 
MapGRFStringID(_newgrf_textrefstack.grffile->grfid, _newgrf_textrefstack.PopUnsignedWord());
 
 1067         *argv = cargo < 
NUM_CARGO ? 1 << cargo : 0;
 
 1084     default: NOT_REACHED();
 
 1099       return SCC_CURRENCY_LONG;
 
 1106       return SCC_DATE_LONG;
 
 1110       return SCC_DATE_SHORT;
 
 1113       return SCC_VELOCITY;
 
 1116       return SCC_VOLUME_LONG;
 
 1119       return SCC_VOLUME_SHORT;
 
 1122       return SCC_WEIGHT_LONG;
 
 1125       return SCC_WEIGHT_SHORT;
 
 1131       return SCC_CARGO_LONG;
 
 1134       return SCC_CARGO_SHORT;
 
 1137       return SCC_CARGO_TINY;
 
 1140       return SCC_CARGO_LIST;
 
 1143       return SCC_STATION_NAME;