Пример #1
0
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]);
		}
	}
}
Пример #2
0
	/**
	 * 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);
	}
Пример #3
0
/**
 * 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);
}
Пример #4
0
	/**
	 * 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);
	}
Пример #5
0
/**
 * 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;
}
Пример #6
0
	/**
	 * 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];
	}
Пример #7
0
	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;
	}
Пример #8
0
/** 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';
	}
}
Пример #9
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);
}
Пример #10
0
/**
 * 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;
}
Пример #11
0
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;
}
Пример #12
0
/**
 * 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;
	}
}
Пример #13
0
/**
 * 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);
}
Пример #14
0
/**
 * 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;
}
Пример #15
0
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;
}
Пример #16
0
/** 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());
}
Пример #17
0
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);
}