static void Load_GLOG_common(LoggedAction *&gamelog_action, uint &gamelog_actions) { assert(gamelog_action == NULL); assert(gamelog_actions == 0); GamelogActionType at; while ((at = (GamelogActionType)SlReadByte()) != GLAT_NONE) { gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1); LoggedAction *la = &gamelog_action[gamelog_actions++]; la->at = at; SlObject(la, _glog_action_desc); // has to be saved after 'DATE'! la->change = NULL; la->changes = 0; GamelogChangeType ct; while ((ct = (GamelogChangeType)SlReadByte()) != GLCT_NONE) { la->change = ReallocT(la->change, la->changes + 1); LoggedChange *lc = &la->change[la->changes++]; /* for SLE_STR, pointer has to be valid! so make it NULL */ memset(lc, 0, sizeof(*lc)); lc->ct = ct; assert((uint)ct < GLCT_END); SlObject(lc, _glog_desc[ct]); } } }
/** * Compact the matrix down to the smallest possible size. */ inline void Compact() { uint capacity = this->height * this->width; if (capacity >= this->capacity) return; this->capacity = capacity; this->data = ReallocT(this->data, this->capacity); }
/** * Deallocate a StationSpec from a Station. Called when removing a single station tile. * @param st Station to work with. * @param specindex Index of the custom station within the Station's spec list. * @return Indicates whether the StationSpec was deallocated. */ void DeallocateSpecFromStation(BaseStation *st, byte specindex) { /* specindex of 0 (default) is never freeable */ if (specindex == 0) return; ETileArea area = ETileArea(st, INVALID_TILE, TA_WHOLE); /* Check all tiles over the station to check if the specindex is still in use */ TILE_AREA_LOOP(tile, area) { if (st->TileBelongsToRailStation(tile) && GetCustomStationSpecIndex(tile) == specindex) { return; } } /* This specindex is no longer in use, so deallocate it */ st->speclist[specindex].spec = NULL; st->speclist[specindex].grfid = 0; st->speclist[specindex].localidx = 0; /* If this was the highest spec index, reallocate */ if (specindex == st->num_specs - 1) { for (; st->speclist[st->num_specs - 1].grfid == 0 && st->num_specs > 1; st->num_specs--) {} if (st->num_specs > 1) { st->speclist = ReallocT(st->speclist, st->num_specs); } else { free(st->speclist); st->num_specs = 0; st->speclist = NULL; st->cached_anim_triggers = 0; return; } } StationUpdateAnimTriggers(st); }
/** * Compact the list down to the smallest block size boundary. */ FORCEINLINE void Compact() { uint capacity = Align(this->items, S); if (capacity >= this->capacity) return; this->capacity = capacity; this->data = ReallocT(this->data, this->capacity); }
/** * Resizes the pool so 'index' can be addressed * @param index index we will allocate later * @pre index >= this->size * @pre index < Tmax_size */ DEFINE_POOL_METHOD(inline void)::ResizeFor(size_t index) { assert(index >= this->size); assert(index < Tmax_size); size_t new_size = ::min(Tmax_size, Align(index + 1, Tgrowth_step)); this->data = ReallocT(this->data, new_size); MemSetT(this->data + this->size, 0, new_size - this->size); this->size = new_size; }
/** * Append an item and return it. * @param to_add the number of items to append * @return pointer to newly allocated item */ FORCEINLINE T *Append(uint to_add = 1) { uint begin = this->items; this->items += to_add; if (this->items > this->capacity) { this->capacity = Align(this->items, S); this->data = ReallocT(this->data, this->capacity); } return &this->data[begin]; }
bool Add(const TCHAR *font) { for (uint i = 0; i < this->items; i++) { if (_tcscmp(this->fonts[i], font) == 0) return false; } if (this->items == this->capacity) { this->capacity += 10; this->fonts = ReallocT(this->fonts, this->capacity); } this->fonts[this->items++] = _tcsdup(font); return true; }
/** Initialize all buffers of the chat visualisation. */ void NetworkInitChatMessage() { MAX_CHAT_MESSAGES = _settings_client.gui.network_chat_box_height; _chatmsg_list = ReallocT(_chatmsg_list, _settings_client.gui.network_chat_box_height); _chatmsg_box.x = 10; _chatmsg_box.width = _settings_client.gui.network_chat_box_width; NetworkReInitChatBoxSize(); _chatmessage_visible = false; for (uint i = 0; i < MAX_CHAT_MESSAGES; i++) { _chatmsg_list[i].message[0] = '\0'; } }
static SpriteCache *AllocateSpriteCache(uint index) { if (index >= _spritecache_items) { /* Add another 1024 items to the 'pool' */ uint items = Align(index + 1, 1024); DEBUG(sprite, 4, "Increasing sprite cache to %u items (" PRINTF_SIZE " bytes)", items, items * sizeof(*_spritecache)); _spritecache = ReallocT(_spritecache, items); /* Reset the new items and update the count */ memset(_spritecache + _spritecache_items, 0, (items - _spritecache_items) * sizeof(*_spritecache)); _spritecache_items = items; } return GetSpriteCache(index); }
/** * Allocate a StationSpec to a Station. This is called once per build operation. * @param statspec StationSpec to allocate. * @param st Station to allocate it to. * @param exec Whether to actually allocate the spec. * @return Index within the Station's spec list, or -1 if the allocation failed. */ int AllocateSpecToStation(const StationSpec *statspec, BaseStation *st, bool exec) { uint i; if (statspec == NULL || st == NULL) return 0; for (i = 1; i < st->num_specs && i < NUM_STATIONSSPECS_PER_STATION; i++) { if (st->speclist[i].spec == NULL && st->speclist[i].grfid == 0) break; } if (i == NUM_STATIONSSPECS_PER_STATION) { /* As final effort when the spec list is already full... * try to find the same spec and return that one. This might * result in slightly "wrong" (as per specs) looking stations, * but it's fairly unlikely that one reaches the limit anyways. */ for (i = 1; i < st->num_specs && i < NUM_STATIONSSPECS_PER_STATION; i++) { if (st->speclist[i].spec == statspec) return i; } return -1; } if (exec) { if (i >= st->num_specs) { st->num_specs = i + 1; st->speclist = ReallocT(st->speclist, st->num_specs); if (st->num_specs == 2) { /* Initial allocation */ st->speclist[0].spec = NULL; st->speclist[0].grfid = 0; st->speclist[0].localidx = 0; } } st->speclist[i].spec = statspec; st->speclist[i].grfid = statspec->grf_prop.grffile->grfid; st->speclist[i].localidx = statspec->grf_prop.local_id; StationUpdateCachedTriggers(st); } return i; }
SQInteger SquirrelStd::require(HSQUIRRELVM vm) { SQInteger top = sq_gettop(vm); const SQChar *filename; SQChar *real_filename; sq_getstring(vm, 2, &filename); /* Get the script-name of the current file, so we can work relative from it */ SQStackInfos si; sq_stackinfos(vm, 1, &si); if (si.source == NULL) { DEBUG(misc, 0, "[squirrel] Couldn't detect the script-name of the 'require'-caller; this should never happen!"); return SQ_ERROR; } real_filename = scstrdup(si.source); /* Keep the dir, remove the rest */ SQChar *s = scstrrchr(real_filename, PATHSEPCHAR); if (s != NULL) { /* Keep the PATHSEPCHAR there, remove the rest */ s++; *s = '\0'; } /* And now we concat, so we are relative from the current script * First, we have to make sure we have enough space for the full path */ real_filename = ReallocT(real_filename, scstrlen(real_filename) + scstrlen(filename) + 1); scstrcat(real_filename, filename); /* Tars dislike opening files with '/' on Windows.. so convert it to '\\' ;) */ char *filen = strdup(SQ2OTTD(real_filename)); #if (PATHSEPCHAR != '/') for (char *n = filen; *n != '\0'; n++) if (*n == '/') *n = PATHSEPCHAR; #endif bool ret = Squirrel::LoadScript(vm, filen); /* Reset the top, so the stack stays correct */ sq_settop(vm, top); free(real_filename); free(filen); return ret ? 0 : SQ_ERROR; }
/** * This function puts the packet in the send-queue and it is send as * soon as possible. This is the next tick, or maybe one tick later * if the OS-network-buffer is full) * @param packet the packet to send */ void NetworkTCPSocketHandler::SendPacket(Packet *packet) { Packet *p; assert(packet != NULL); packet->PrepareToSend(); /* Reallocate the packet as in 99+% of the times we send at most 25 bytes and * keeping the other 1400+ bytes wastes memory, especially when someone tries * to do a denial of service attack! */ packet->buffer = ReallocT(packet->buffer, packet->size); /* Locate last packet buffered for the client */ p = this->packet_queue; if (p == NULL) { /* No packets yet */ this->packet_queue = packet; } else { /* Skip to the last packet */ while (p->next != NULL) p = p->next; p->next = packet; } }
/** * Load the Ini file's data from the disk. * @param filename the file to load. * @param subdir the sub directory to load the file from. * @pre nothing has been loaded yet. */ void IniLoadFile::LoadFromDisk(const char *filename, Subdirectory subdir) { assert(this->last_group == &this->group); char buffer[1024]; IniGroup *group = nullptr; char *comment = nullptr; uint comment_size = 0; uint comment_alloc = 0; size_t end; FILE *in = this->OpenFile(filename, subdir, &end); if (in == nullptr) return; end += ftell(in); /* for each line in the file */ while ((size_t)ftell(in) < end && fgets(buffer, sizeof(buffer), in)) { char c, *s; /* trim whitespace from the left side */ for (s = buffer; *s == ' ' || *s == '\t'; s++) {} /* trim whitespace from right side. */ char *e = s + strlen(s); while (e > s && ((c = e[-1]) == '\n' || c == '\r' || c == ' ' || c == '\t')) e--; *e = '\0'; /* Skip comments and empty lines outside IGT_SEQUENCE groups. */ if ((group == nullptr || group->type != IGT_SEQUENCE) && (*s == '#' || *s == ';' || *s == '\0')) { uint ns = comment_size + (e - s + 1); uint a = comment_alloc; /* add to comment */ if (ns > a) { a = max(a, 128U); do a *= 2; while (a < ns); comment = ReallocT(comment, comment_alloc = a); } uint pos = comment_size; comment_size += (e - s + 1); comment[pos + e - s] = '\n'; // comment newline memcpy(comment + pos, s, e - s); // copy comment contents continue; } /* it's a group? */ if (s[0] == '[') { if (e[-1] != ']') { this->ReportFileError("ini: invalid group name '", buffer, "'"); } else { e--; } s++; // skip [ group = new IniGroup(this, s, e - 1); if (comment_size != 0) { group->comment = stredup(comment, comment + comment_size - 1); comment_size = 0; } } else if (group != nullptr) { if (group->type == IGT_SEQUENCE) { /* A sequence group, use the line as item name without further interpretation. */ IniItem *item = new IniItem(group, buffer, e - 1); if (comment_size) { item->comment = stredup(comment, comment + comment_size - 1); comment_size = 0; } continue; } char *t; /* find end of keyname */ if (*s == '\"') { s++; for (t = s; *t != '\0' && *t != '\"'; t++) {} if (*t == '\"') *t = ' '; } else { for (t = s; *t != '\0' && *t != '=' && *t != '\t' && *t != ' '; t++) {} } /* it's an item in an existing group */ IniItem *item = new IniItem(group, s, t - 1); if (comment_size != 0) { item->comment = stredup(comment, comment + comment_size - 1); comment_size = 0; } /* find start of parameter */ while (*t == '=' || *t == ' ' || *t == '\t') t++; bool quoted = (*t == '\"'); /* remove starting quotation marks */ if (*t == '\"') t++; /* remove ending quotation marks */ e = t + strlen(t); if (e > t && e[-1] == '\"') e--; *e = '\0'; /* If the value was not quoted and empty, it must be nullptr */ item->value = (!quoted && e == t) ? nullptr : stredup(t); if (item->value != nullptr) str_validate(item->value, item->value + strlen(item->value)); } else { /* it's an orphan item */ this->ReportFileError("ini: '", buffer, "' outside of group"); } } if (comment_size > 0) { this->comment = stredup(comment, comment + comment_size - 1); comment_size = 0; } free(comment); fclose(in); }
/** * Translate TTDPatch string codes into something OpenTTD can handle (better). * @param grfid The (NewGRF) ID associated with this string * @param language_id The (NewGRF) language ID associated with this string. * @param allow_newlines Whether newlines are allowed in the string or not. * @param str The string to translate. * @param [out] olen The length of the final string. * @param byte80 The control code to use as replacement for the 0x80-value. * @return The translated string. */ char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, bool allow_newlines, const char *str, int *olen, StringControlCode byte80) { char *tmp = MallocT<char>(strlen(str) * 10 + 1); // Allocate space to allow for expansion char *d = tmp; bool unicode = false; WChar c; size_t len = Utf8Decode(&c, str); /* Helper variable for a possible (string) mapping. */ UnmappedChoiceList *mapping = NULL; if (c == NFO_UTF8_IDENTIFIER) { unicode = true; str += len; } for (;;) { if (unicode && Utf8EncodedCharLen(*str) != 0) { c = Utf8Consume(&str); /* 'Magic' range of control codes. */ if (GB(c, 8, 8) == 0xE0) { c = GB(c, 0, 8); } else if (c >= 0x20) { if (!IsValidChar(c, CS_ALPHANUMERAL)) c = '?'; d += Utf8Encode(d, c); continue; } } else { c = (byte)*str++; } if (c == '\0') break; switch (c) { case 0x01: if (str[0] == '\0') goto string_end; d += Utf8Encode(d, ' '); str++; break; case 0x0A: break; case 0x0D: if (allow_newlines) { *d++ = 0x0A; } else { grfmsg(1, "Detected newline in string that does not allow one"); } break; case 0x0E: d += Utf8Encode(d, SCC_TINYFONT); break; case 0x0F: d += Utf8Encode(d, SCC_BIGFONT); break; case 0x1F: if (str[0] == '\0' || str[1] == '\0') goto string_end; d += Utf8Encode(d, ' '); str += 2; break; case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F: d += Utf8Encode(d, SCC_NEWGRF_PRINT_DWORD_SIGNED + c - 0x7B); break; case 0x80: d += Utf8Encode(d, byte80); break; case 0x81: { if (str[0] == '\0' || str[1] == '\0') goto string_end; StringID string; string = ((uint8)*str++); string |= ((uint8)*str++) << 8; d += Utf8Encode(d, SCC_NEWGRF_STRINL); d += Utf8Encode(d, MapGRFStringID(grfid, string)); break; } case 0x82: case 0x83: case 0x84: d += Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_DATE_LONG + c - 0x82); break; case 0x85: d += Utf8Encode(d, SCC_NEWGRF_DISCARD_WORD); break; case 0x86: d += Utf8Encode(d, SCC_NEWGRF_ROTATE_TOP_4_WORDS); break; case 0x87: d += Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_VOLUME_LONG); break; case 0x88: d += Utf8Encode(d, SCC_BLUE); break; case 0x89: d += Utf8Encode(d, SCC_SILVER); break; case 0x8A: d += Utf8Encode(d, SCC_GOLD); break; case 0x8B: d += Utf8Encode(d, SCC_RED); break; case 0x8C: d += Utf8Encode(d, SCC_PURPLE); break; case 0x8D: d += Utf8Encode(d, SCC_LTBROWN); break; case 0x8E: d += Utf8Encode(d, SCC_ORANGE); break; case 0x8F: d += Utf8Encode(d, SCC_GREEN); break; case 0x90: d += Utf8Encode(d, SCC_YELLOW); break; case 0x91: d += Utf8Encode(d, SCC_DKGREEN); break; case 0x92: d += Utf8Encode(d, SCC_CREAM); break; case 0x93: d += Utf8Encode(d, SCC_BROWN); break; case 0x94: d += Utf8Encode(d, SCC_WHITE); break; case 0x95: d += Utf8Encode(d, SCC_LTBLUE); break; case 0x96: d += Utf8Encode(d, SCC_GRAY); break; case 0x97: d += Utf8Encode(d, SCC_DKBLUE); break; case 0x98: d += Utf8Encode(d, SCC_BLACK); break; case 0x9A: { int code = *str++; switch (code) { case 0x00: goto string_end; case 0x01: d += Utf8Encode(d, SCC_NEWGRF_PRINT_QWORD_CURRENCY); break; /* 0x02: ignore next colour byte is not supported. It works on the final * string and as such hooks into the string drawing routine. At that * point many things already happened, such as splitting up of strings * when drawn over multiple lines or right-to-left translations, which * make the behaviour peculiar, e.g. only happening at specific width * of windows. Or we need to add another pass over the string to just * support this. As such it is not implemented in OpenTTD. */ case 0x03: { if (str[0] == '\0' || str[1] == '\0') goto string_end; uint16 tmp = ((uint8)*str++); tmp |= ((uint8)*str++) << 8; d += Utf8Encode(d, SCC_NEWGRF_PUSH_WORD); d += Utf8Encode(d, tmp); break; } case 0x04: if (str[0] == '\0') goto string_end; d += Utf8Encode(d, SCC_NEWGRF_UNPRINT); d += Utf8Encode(d, *str++); break; case 0x06: d += Utf8Encode(d, SCC_NEWGRF_PRINT_BYTE_HEX); break; case 0x07: d += Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_HEX); break; case 0x08: d += Utf8Encode(d, SCC_NEWGRF_PRINT_DWORD_HEX); break; /* 0x09, 0x0A are TTDPatch internal use only string codes. */ case 0x0B: d += Utf8Encode(d, SCC_NEWGRF_PRINT_QWORD_HEX); break; case 0x0C: d += Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_STATION_NAME); break; case 0x0D: d += Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_WEIGHT_LONG); break; case 0x0E: case 0x0F: { if (str[0] == '\0') goto string_end; const LanguageMap *lm = LanguageMap::GetLanguageMap(grfid, language_id); int index = *str++; int mapped = lm != NULL ? lm->GetMapping(index, code == 0x0E) : -1; if (mapped >= 0) { d += Utf8Encode(d, code == 0x0E ? SCC_GENDER_INDEX : SCC_SET_CASE); d += Utf8Encode(d, code == 0x0E ? mapped : mapped + 1); } break; } case 0x10: case 0x11: if (str[0] == '\0') goto string_end; if (mapping == NULL) { if (code == 0x10) str++; // Skip the index grfmsg(1, "choice list %s marker found when not expected", code == 0x10 ? "next" : "default"); break; } else { /* Terminate the previous string. */ *d = '\0'; int index = (code == 0x10 ? *str++ : 0); if (mapping->strings.Contains(index)) { grfmsg(1, "duplicate choice list string, ignoring"); d++; } else { d = mapping->strings[index] = MallocT<char>(strlen(str) * 10 + 1); } } break; case 0x12: if (mapping == NULL) { grfmsg(1, "choice list end marker found when not expected"); } else { /* Terminate the previous string. */ *d = '\0'; /* Now we can start flushing everything and clean everything up. */ d = mapping->Flush(LanguageMap::GetLanguageMap(grfid, language_id)); delete mapping; mapping = NULL; } break; case 0x13: case 0x14: case 0x15: if (str[0] == '\0') goto string_end; if (mapping != NULL) { grfmsg(1, "choice lists can't be stacked, it's going to get messy now..."); if (code != 0x14) str++; } else { static const StringControlCode mp[] = { SCC_GENDER_LIST, SCC_SWITCH_CASE, SCC_PLURAL_LIST }; mapping = new UnmappedChoiceList(mp[code - 0x13], d, code == 0x14 ? 0 : *str++); } break; case 0x16: case 0x17: case 0x18: case 0x19: case 0x1A: d += Utf8Encode(d, SCC_NEWGRF_PRINT_DWORD_DATE_LONG + code - 0x16); break; default: grfmsg(1, "missing handler for extended format code"); break; } break; } case 0x9E: d += Utf8Encode(d, 0x20AC); break; // Euro case 0x9F: d += Utf8Encode(d, 0x0178); break; // Y with diaeresis case 0xA0: d += Utf8Encode(d, SCC_UP_ARROW); break; case 0xAA: d += Utf8Encode(d, SCC_DOWN_ARROW); break; case 0xAC: d += Utf8Encode(d, SCC_CHECKMARK); break; case 0xAD: d += Utf8Encode(d, SCC_CROSS); break; case 0xAF: d += Utf8Encode(d, SCC_RIGHT_ARROW); break; case 0xB4: d += Utf8Encode(d, SCC_TRAIN); break; case 0xB5: d += Utf8Encode(d, SCC_LORRY); break; case 0xB6: d += Utf8Encode(d, SCC_BUS); break; case 0xB7: d += Utf8Encode(d, SCC_PLANE); break; case 0xB8: d += Utf8Encode(d, SCC_SHIP); break; case 0xB9: d += Utf8Encode(d, SCC_SUPERSCRIPT_M1); break; case 0xBC: d += Utf8Encode(d, SCC_SMALL_UP_ARROW); break; case 0xBD: d += Utf8Encode(d, SCC_SMALL_DOWN_ARROW); break; default: /* Validate any unhandled character */ if (!IsValidChar(c, CS_ALPHANUMERAL)) c = '?'; d += Utf8Encode(d, c); break; } } string_end: if (mapping != NULL) { grfmsg(1, "choice list was incomplete, the whole list is ignored"); delete mapping; } *d = '\0'; if (olen != NULL) *olen = d - tmp + 1; tmp = ReallocT(tmp, d - tmp + 1); return tmp; }
char *TranslateTTDPatchCodes(uint32 grfid, const char *str) { char *tmp = MallocT<char>(strlen(str) * 10 + 1); // Allocate space to allow for expansion char *d = tmp; bool unicode = false; WChar c; size_t len = Utf8Decode(&c, str); if (c == 0x00DE) { /* The thorn ('þ') indicates a unicode string to TTDPatch */ unicode = true; str += len; } for (;;) { if (unicode && Utf8EncodedCharLen(*str) != 0) { c = Utf8Consume(&str); /* 'Magic' range of control codes. */ if (GB(c, 8, 8) == 0xE0) { c = GB(c, 0, 8); } else if (c >= 0x20) { if (!IsValidChar(c, CS_ALPHANUMERAL)) c = '?'; d += Utf8Encode(d, c); continue; } } else { c = (byte)*str++; } if (c == 0) break; switch (c) { case 0x01: d += Utf8Encode(d, SCC_SETX); *d++ = *str++; break; case 0x0A: break; case 0x0D: *d++ = 0x0A; break; case 0x0E: d += Utf8Encode(d, SCC_TINYFONT); break; case 0x0F: d += Utf8Encode(d, SCC_BIGFONT); break; case 0x1F: d += Utf8Encode(d, SCC_SETXY); *d++ = *str++; *d++ = *str++; break; case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F: case 0x80: d += Utf8Encode(d, SCC_NEWGRF_PRINT_DWORD + c - 0x7B); break; case 0x81: { StringID string; string = ((uint8)*str++); string |= ((uint8)*str++) << 8; d += Utf8Encode(d, SCC_STRING_ID); d += Utf8Encode(d, MapGRFStringID(grfid, string)); break; } case 0x82: case 0x83: case 0x84: d += Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_SPEED + c - 0x82); break; case 0x85: d += Utf8Encode(d, SCC_NEWGRF_DISCARD_WORD); break; case 0x86: d += Utf8Encode(d, SCC_NEWGRF_ROTATE_TOP_4_WORDS); break; case 0x87: d += Utf8Encode(d, SCC_NEWGRF_PRINT_WORD_LITRES); break; case 0x88: d += Utf8Encode(d, SCC_BLUE); break; case 0x89: d += Utf8Encode(d, SCC_SILVER); break; case 0x8A: d += Utf8Encode(d, SCC_GOLD); break; case 0x8B: d += Utf8Encode(d, SCC_RED); break; case 0x8C: d += Utf8Encode(d, SCC_PURPLE); break; case 0x8D: d += Utf8Encode(d, SCC_LTBROWN); break; case 0x8E: d += Utf8Encode(d, SCC_ORANGE); break; case 0x8F: d += Utf8Encode(d, SCC_GREEN); break; case 0x90: d += Utf8Encode(d, SCC_YELLOW); break; case 0x91: d += Utf8Encode(d, SCC_DKGREEN); break; case 0x92: d += Utf8Encode(d, SCC_CREAM); break; case 0x93: d += Utf8Encode(d, SCC_BROWN); break; case 0x94: d += Utf8Encode(d, SCC_WHITE); break; case 0x95: d += Utf8Encode(d, SCC_LTBLUE); break; case 0x96: d += Utf8Encode(d, SCC_GRAY); break; case 0x97: d += Utf8Encode(d, SCC_DKBLUE); break; case 0x98: d += Utf8Encode(d, SCC_BLACK); break; case 0x9A: switch (*str++) { case 0: // FALL THROUGH case 1: d += Utf8Encode(d, SCC_NEWGRF_PRINT_QWORD_CURRENCY); break; case 3: { uint16 tmp = ((uint8)*str++); tmp |= ((uint8)*str++) << 8; d += Utf8Encode(d, SCC_NEWGRF_PUSH_WORD); d += Utf8Encode(d, tmp); } break; case 4: d += Utf8Encode(d, SCC_NEWGRF_UNPRINT); d += Utf8Encode(d, *str++); break; case 6: d += Utf8Encode(d, SCC_NEWGRF_PRINT_HEX_BYTE); break; case 7: d += Utf8Encode(d, SCC_NEWGRF_PRINT_HEX_WORD); break; case 8: d += Utf8Encode(d, SCC_NEWGRF_PRINT_HEX_DWORD); break; case 0x0B: d += Utf8Encode(d, SCC_NEWGRF_PRINT_HEX_QWORD); break; default: grfmsg(1, "missing handler for extended format code"); break; } break; case 0x9E: d += Utf8Encode(d, 0x20AC); break; // Euro case 0x9F: d += Utf8Encode(d, 0x0178); break; // Y with diaeresis case 0xA0: d += Utf8Encode(d, SCC_UPARROW); break; case 0xAA: d += Utf8Encode(d, SCC_DOWNARROW); break; case 0xAC: d += Utf8Encode(d, SCC_CHECKMARK); break; case 0xAD: d += Utf8Encode(d, SCC_CROSS); break; case 0xAF: d += Utf8Encode(d, SCC_RIGHTARROW); break; case 0xB4: d += Utf8Encode(d, SCC_TRAIN); break; case 0xB5: d += Utf8Encode(d, SCC_LORRY); break; case 0xB6: d += Utf8Encode(d, SCC_BUS); break; case 0xB7: d += Utf8Encode(d, SCC_PLANE); break; case 0xB8: d += Utf8Encode(d, SCC_SHIP); break; case 0xB9: d += Utf8Encode(d, SCC_SUPERSCRIPT_M1); break; case 0xBC: d += Utf8Encode(d, SCC_SMALLUPARROW); break; case 0xBD: d += Utf8Encode(d, SCC_SMALLDOWNARROW); break; default: /* Validate any unhandled character */ if (!IsValidChar(c, CS_ALPHANUMERAL)) c = '?'; d += Utf8Encode(d, c); break; } } *d = '\0'; tmp = ReallocT(tmp, strlen(tmp) + 1); return tmp; }
/** Initialize all font-dependent chat box sizes. */ void NetworkReInitChatBoxSize() { _chatmsg_box.y = 3 * FONT_HEIGHT_NORMAL; _chatmsg_box.height = MAX_CHAT_MESSAGES * (FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING) + 2; _chatmessage_backup = ReallocT(_chatmessage_backup, _chatmsg_box.width * _chatmsg_box.height * BlitterFactory::GetCurrentBlitter()->GetBytesPerPixel()); }
void IniFile::LoadFromDisk(const char *filename) { assert(this->last_group == &this->group); char buffer[1024]; IniGroup *group = NULL; char *comment = NULL; uint comment_size = 0; uint comment_alloc = 0; size_t end; /* * Now we are going to open a file that contains no more than simple * plain text. That would raise the question: "why open the file as * if it is a binary file?". That's simple... Microsoft, in all * their greatness and wisdom decided it would be useful if ftell * is aware of '\r\n' and "sees" that as a single character. The * easiest way to test for that situation is by searching for '\n' * and decrease the value every time you encounter a '\n'. This will * thus also make ftell "see" the '\r' when it is not there, so the * result of ftell will be highly unreliable. So to work around this * marvel of wisdom we have to open in as a binary file. */ FILE *in = FioFOpenFile(filename, "rb", DATA_DIR, &end); if (in == NULL) return; end += ftell(in); /* for each line in the file */ while ((size_t)ftell(in) < end && fgets(buffer, sizeof(buffer), in)) { char c, *s; /* trim whitespace from the left side */ for (s = buffer; *s == ' ' || *s == '\t'; s++) {} /* trim whitespace from right side. */ char *e = s + strlen(s); while (e > s && ((c = e[-1]) == '\n' || c == '\r' || c == ' ' || c == '\t')) e--; *e = '\0'; /* skip comments and empty lines */ if (*s == '#' || *s == ';' || *s == '\0') { uint ns = comment_size + (e - s + 1); uint a = comment_alloc; /* add to comment */ if (ns > a) { a = max(a, 128U); do a *= 2; while (a < ns); comment = ReallocT(comment, comment_alloc = a); } uint pos = comment_size; comment_size += (e - s + 1); comment[pos + e - s] = '\n'; // comment newline memcpy(comment + pos, s, e - s); // copy comment contents continue; } /* it's a group? */ if (s[0] == '[') { if (e[-1] != ']') { ShowInfoF("ini: invalid group name '%s'", buffer); } else { e--; } s++; // skip [ group = new IniGroup(this, s, e - s); if (comment_size) { group->comment = strndup(comment, comment_size); comment_size = 0; } } else if (group) { char *t; /* find end of keyname */ if (*s == '\"') { s++; for (t = s; *t != '\0' && *t != '\"'; t++) {} if (*t == '\"') *t = ' '; } else { for (t = s; *t != '\0' && *t != '=' && *t != '\t' && *t != ' '; t++) {} } /* it's an item in an existing group */ IniItem *item = new IniItem(group, s, t - s); if (comment_size) { item->comment = strndup(comment, comment_size); comment_size = 0; } /* find start of parameter */ while (*t == '=' || *t == ' ' || *t == '\t') t++; bool quoted = (*t == '\"'); /* remove starting quotation marks */ if (*t == '\"') t++; /* remove ending quotation marks */ e = t + strlen(t); if (e > t && e[-1] == '\"') e--; *e = '\0'; /* If the value was not quoted and empty, it must be NULL */ item->value = (!quoted && e == t) ? NULL : strndup(t, e - t); } else { /* it's an orphan item */ ShowInfoF("ini: '%s' outside of group", buffer); } } if (comment_size > 0) { this->comment = strndup(comment, comment_size); comment_size = 0; } free(comment); fclose(in); }