Changeset - r4912:d420151de4c6
[Not reviewed]
master
0 33 0
Darkvater - 18 years ago 2006-10-21 23:31:34
darkvater@openttd.org
(svn r6884) -Codechange: Add strict bounds checking in string formatting system.
The last parameter should point to the end of the buffer (eg lastof(buf))
Courtesy of Tron.
33 files changed with 248 insertions and 239 deletions:
0 comments (0 inline, 0 general)
build_vehicle_gui.c
Show inline comments
 
@@ -96,18 +96,18 @@ static int CDECL EngineNameSorter(const 
 
	const EngineID va = *(const EngineID*)a;
 
	const EngineID vb = *(const EngineID*)b;
 
	int r;
 

	
 
	if (va != last_engine[0]) {
 
		last_engine[0] = va;
 
		GetString(last_name[0], GetCustomEngineName(va));
 
		GetString(last_name[0], GetCustomEngineName(va), lastof(last_name[0]));
 
	}
 

	
 
	if (vb != last_engine[1]) {
 
		last_engine[1] = vb;
 
		GetString(last_name[1], GetCustomEngineName(vb));
 
		GetString(last_name[1], GetCustomEngineName(vb), lastof(last_name[1]));
 
	}
 

	
 
	r = strcmp(last_name[0], last_name[1]); // sort by name
 

	
 
	if (r == 0) {
 
		/* Use EngineID to sort instead since we want consistent sorting */
console_cmds.c
Show inline comments
 
@@ -1214,13 +1214,13 @@ DEF_CONSOLE_CMD(ConPlayers)
 

	
 
	FOR_ALL_PLAYERS(p) {
 
		char buffer[512];
 

	
 
		if (!p->is_active) continue;
 

	
 
		GetString(buffer, STR_00D1_DARK_BLUE + _player_colors[p->index]);
 
		GetString(buffer, STR_00D1_DARK_BLUE + _player_colors[p->index], lastof(buffer));
 
		IConsolePrintF(8, "#:%d(%s) Company Name: '%s'  Year Founded: %d  Money: %d  Loan: %d  Value: %" OTTD_PRINTF64 "d  (T:%d, R:%d, P:%d, S:%d)",
 
			p->index + 1, buffer, _network_player_info[p->index].company_name, p->inaugurated_year, p->player_money, p->current_loan, CalculateCompanyValue(p),
 
			/* trains      */ _network_player_info[p->index].num_vehicle[0],
 
			/* lorry + bus */ _network_player_info[p->index].num_vehicle[1] + _network_player_info[p->index].num_vehicle[2],
 
			/* planes      */ _network_player_info[p->index].num_vehicle[3],
 
			/* ships       */ _network_player_info[p->index].num_vehicle[4]);
functions.h
Show inline comments
 
@@ -137,13 +137,13 @@ void PlaceTreesRandomly(void);
 

	
 
void InitializeLandscapeVariables(bool only_constants);
 

	
 
/* misc.c */
 
bool IsCustomName(StringID id);
 
void DeleteName(StringID id);
 
char *GetName(int id, char *buff);
 
char *GetName(char *buff, StringID id, const char* last);
 

	
 
// AllocateNameUnique also tests if the name used is not used anywere else
 
//  and if it is used, it returns an error.
 
#define AllocateNameUnique(name, skip) RealAllocateName(name, skip, true)
 
#define AllocateName(name, skip) RealAllocateName(name, skip, false)
 
StringID RealAllocateName(const char *name, byte skip, bool check_double);
genworld_gui.c
Show inline comments
 
@@ -281,13 +281,13 @@ void GenerateLandscapeWndProc(Window *w,
 
				SetDParam(0, _heightmap_y);
 
				SetDParam(1, _heightmap_x);
 
			} else {
 
				SetDParam(0, _heightmap_x);
 
				SetDParam(1, _heightmap_y);
 
			}
 
			GetString(buffer, STR_HEIGHTMAP_SIZE);
 
			GetString(buffer, STR_HEIGHTMAP_SIZE, lastof(buffer));
 
			DrawStringRightAligned(326, 91, STR_HEIGHTMAP_SIZE, 0x10);
 

	
 
			DrawString( 12,  91, STR_HEIGHTMAP_NAME, 0x10);
 
			SetDParam(0, _heightmap_str);
 
			DrawStringTruncated(114,  91, STR_ORANGE, 0x10, 326 - 114 - GetStringBoundingBox(buffer).width - 5);
 

	
gfx.c
Show inline comments
 
@@ -326,52 +326,52 @@ static int TruncateString(char *str, int
 
		}
 
	}
 

	
 
	return w;
 
}
 

	
 
static inline int TruncateStringID(StringID src, char *dest, int maxw)
 
static inline int TruncateStringID(StringID src, char *dest, int maxw, const char* last)
 
{
 
	GetString(dest, src);
 
	GetString(dest, src, last);
 
	return TruncateString(dest, maxw);
 
}
 

	
 
/* returns right coordinate */
 
int DrawString(int x, int y, StringID str, uint16 color)
 
{
 
	char buffer[512];
 

	
 
	GetString(buffer, str);
 
	GetString(buffer, str, lastof(buffer));
 
	return DoDrawString(buffer, x, y, color);
 
}
 

	
 
int DrawStringTruncated(int x, int y, StringID str, uint16 color, uint maxw)
 
{
 
	char buffer[512];
 
	TruncateStringID(str, buffer, maxw);
 
	TruncateStringID(str, buffer, maxw, lastof(buffer));
 
	return DoDrawString(buffer, x, y, color);
 
}
 

	
 

	
 
int DrawStringRightAligned(int x, int y, StringID str, uint16 color)
 
{
 
	char buffer[512];
 
	int w;
 

	
 
	GetString(buffer, str);
 
	GetString(buffer, str, lastof(buffer));
 
	w = GetStringBoundingBox(buffer).width;
 
	DoDrawString(buffer, x - w, y, color);
 

	
 
	return w;
 
}
 

	
 
void DrawStringRightAlignedTruncated(int x, int y, StringID str, uint16 color, uint maxw)
 
{
 
	char buffer[512];
 

	
 
	TruncateStringID(str, buffer, maxw);
 
	TruncateStringID(str, buffer, maxw, lastof(buffer));
 
	DoDrawString(buffer, x - GetStringBoundingBox(buffer).width, y, color);
 
}
 

	
 
void DrawStringRightAlignedUnderline(int x, int y, StringID str, uint16 color)
 
{
 
	int w = DrawStringRightAligned(x, y, str, color);
 
@@ -381,24 +381,24 @@ void DrawStringRightAlignedUnderline(int
 

	
 
int DrawStringCentered(int x, int y, StringID str, uint16 color)
 
{
 
	char buffer[512];
 
	int w;
 

	
 
	GetString(buffer, str);
 
	GetString(buffer, str, lastof(buffer));
 

	
 
	w = GetStringBoundingBox(buffer).width;
 
	DoDrawString(buffer, x - w / 2, y, color);
 

	
 
	return w;
 
}
 

	
 
int DrawStringCenteredTruncated(int xl, int xr, int y, StringID str, uint16 color)
 
{
 
	char buffer[512];
 
	int w = TruncateStringID(str, buffer, xr - xl);
 
	int w = TruncateStringID(str, buffer, xr - xl, lastof(buffer));
 
	return DoDrawString(buffer, (xl + xr - w) / 2, y, color);
 
}
 

	
 
int DoDrawStringCentered(int x, int y, const char *str, uint16 color)
 
{
 
	int w = GetStringBoundingBox(str).width;
 
@@ -463,13 +463,13 @@ void DrawStringMultiCenter(int x, int y,
 
	char buffer[512];
 
	uint32 tmp;
 
	int num, w, mt;
 
	const char *src;
 
	byte c;
 

	
 
	GetString(buffer, str);
 
	GetString(buffer, str, lastof(buffer));
 

	
 
	tmp = FormatStringLinebreaks(buffer, maxw);
 
	num = GB(tmp, 0, 16);
 

	
 
	mt = GetCharacterHeight(GB(tmp, 16, 16));
 

	
 
@@ -505,13 +505,13 @@ void DrawStringMultiLine(int x, int y, S
 
	char buffer[512];
 
	uint32 tmp;
 
	int num, mt;
 
	const char *src;
 
	byte c;
 

	
 
	GetString(buffer, str);
 
	GetString(buffer, str, lastof(buffer));
 

	
 
	tmp = FormatStringLinebreaks(buffer, maxw);
 
	num = GB(tmp, 0, 16);
 

	
 
	mt = GetCharacterHeight(GB(tmp, 16, 16));
 

	
graph_gui.c
Show inline comments
 
@@ -1132,17 +1132,17 @@ static const Sign *_last_sign;
 
static int CDECL SignNameSorter(const void *a, const void *b)
 
{
 
	const Sign *sign0 = *(const Sign**)a;
 
	const Sign *sign1 = *(const Sign**)b;
 
	char buf1[64];
 

	
 
	GetString(buf1, sign0->str);
 
	GetString(buf1, sign0->str, lastof(buf1));
 

	
 
	if (sign1 != _last_sign) {
 
		_last_sign = sign1;
 
		GetString(_bufcache, sign1->str);
 
		GetString(_bufcache, sign1->str, lastof(_bufcache));
 
	}
 

	
 
	return strcmp(buf1, _bufcache); // sort by name
 
}
 

	
 
static void GlobalSortSignList(void)
industry_gui.c
Show inline comments
 
@@ -533,18 +533,18 @@ static int CDECL GeneralIndustrySorter(c
 

	
 
	// default to string sorting if they are otherwise equal
 
	if (r == 0) {
 
		char buf1[96];
 

	
 
		SetDParam(0, i->town->index);
 
		GetString(buf1, STR_TOWN);
 
		GetString(buf1, STR_TOWN, lastof(buf1));
 

	
 
		if (j != _last_industry) {
 
			_last_industry = j;
 
			SetDParam(0, j->town->index);
 
			GetString(_bufcache, STR_TOWN);
 
			GetString(_bufcache, STR_TOWN, lastof(_bufcache));
 
		}
 
		r = strcmp(buf1, _bufcache);
 
	}
 

	
 
	if (_industry_sort_order & 1) r = -r;
 
	return r;
main_gui.c
Show inline comments
 
@@ -655,13 +655,13 @@ static int GetStringListMaxWidth(StringI
 
	char buffer[512];
 
	int width, max_width;
 
	byte i;
 

	
 
	max_width = 0;
 
	for (i = 0; i != count; i++) {
 
		GetString(buffer, base_string + i);
 
		GetString(buffer, base_string + i, lastof(buffer));
 
		width = GetStringBoundingBox(buffer).width;
 
		if (width > max_width) max_width = width;
 
	}
 

	
 
	return max_width;
 
}
 
@@ -2105,13 +2105,13 @@ static bool DrawScrollingStatusText(cons
 
		str = _get_news_string_callback[ni->callback](ni);
 
	} else {
 
		COPY_IN_DPARAM(0, ni->params, lengthof(ni->params));
 
		str = ni->string_id;
 
	}
 

	
 
	GetString(buf, str);
 
	GetString(buf, str, lastof(buf));
 

	
 
	s = buf;
 
	d = buffer;
 

	
 
	for (;; s++) {
 
		if (*s == '\0') {
misc.c
Show inline comments
 
@@ -159,15 +159,15 @@ void DeleteName(StringID id)
 
{
 
	if (IsCustomName(id)) {
 
		memset(_name_array[id & 0x1FF], 0, sizeof(_name_array[id & 0x1FF]));
 
	}
 
}
 

	
 
char *GetName(int id, char *buff)
 
char *GetName(char *buff, StringID id, const char* last)
 
{
 
	return strecpy(buff, _name_array[id & ~0x600], NULL);
 
	return strecpy(buff, _name_array[id & ~0x600], last);
 
}
 

	
 

	
 
static void InitializeCheats(void)
 
{
 
	memset(&_cheats, 0, sizeof(Cheats));
misc_gui.c
Show inline comments
 
@@ -89,13 +89,13 @@ static void LandInfoWndProc(Window *w, W
 
			SetDParam(1, lid->town->index);
 
		}
 
		DrawStringCentered(140,60, STR_01A8_LOCAL_AUTHORITY, 0);
 

	
 
		{
 
			char buf[512];
 
			char *p = GetString(buf, STR_01CE_CARGO_ACCEPTED);
 
			char *p = GetString(buf, STR_01CE_CARGO_ACCEPTED, lastof(buf));
 
			bool found = false;
 

	
 
			for (i = 0; i < NUM_CARGO; ++i) {
 
				if (lid->ac[i] > 0) {
 
					// Add a comma between each item.
 
					if (found) {
 
@@ -105,15 +105,15 @@ static void LandInfoWndProc(Window *w, W
 
					found = true;
 

	
 
					// If the accepted value is less than 8, show it in 1/8:ths
 
					if (lid->ac[i] < 8) {
 
						SetDParam(0, lid->ac[i]);
 
						SetDParam(1, _cargoc.names_s[i]);
 
						p = GetString(p, STR_01D1_8);
 
						p = GetString(p, STR_01D1_8, lastof(buf));
 
					} else {
 
						p = GetString(p, _cargoc.names_s[i]);
 
						p = GetString(p, _cargoc.names_s[i], lastof(buf));
 
					}
 
				}
 
			}
 

	
 
			if (found) DrawStringMultiCenter(140, 76, BindCString(buf), 276);
 
		}
 
@@ -676,13 +676,13 @@ void GuiShowTooltipsWithArgs(StringID st
 
	DeleteWindowById(WC_TOOLTIPS, 0);
 

	
 
	/* We only show measurement tooltips with patch setting on */
 
	if (str == STR_NULL || (paramcount != 0 && !_patches.measure_tooltip)) return;
 

	
 
	for (i = 0; i != paramcount; i++) SetDParam(i, params[i]);
 
	GetString(buffer, str);
 
	GetString(buffer, str, lastof(buffer));
 

	
 
	br = GetStringBoundingBox(buffer);
 
	br.width += 6; br.height += 4; // increase slightly to have some space around the box
 

	
 
	/* Cut tooltip length to 200 pixels max, wrap to new line if longer */
 
	if (br.width > 200) {
 
@@ -1073,13 +1073,13 @@ void ShowQueryString(StringID str, Strin
 

	
 
	DeleteWindowById(WC_QUERY_STRING, 0);
 
	DeleteWindowById(WC_SAVELOAD, 0);
 

	
 
	w = AllocateWindowDesc(&_query_string_desc);
 

	
 
	GetString(_edit_str_buf, str);
 
	GetString(_edit_str_buf, str, lastof(_edit_str_buf));
 
	_edit_str_buf[realmaxlen-1] = '\0';
 

	
 
	if (maxlen & 0x1000) {
 
		WP(w, querystr_d).orig = NULL;
 
	} else {
 
		strcpy(_orig_str_buf, _edit_str_buf);
 
@@ -1308,13 +1308,13 @@ static void GenerateFileName(void)
 
	    Let's use the name of player #0 for now. */
 
	const Player *p = GetPlayer(IsValidPlayer(_local_player) ? _local_player : 0);
 

	
 
	SetDParam(0, p->name_1);
 
	SetDParam(1, p->name_2);
 
	SetDParam(2, _date);
 
	GetString(_edit_str_buf, STR_4004);
 
	GetString(_edit_str_buf, STR_4004, lastof(_edit_str_buf));
 
}
 

	
 
extern void StartupEngines(void);
 

	
 
static void SaveLoadDlgWndProc(Window *w, WindowEvent *e)
 
{
 
@@ -1774,13 +1774,13 @@ static void CheatsWndProc(Window *w, Win
 
				switch (ce->str) {
 
				/* Display date for change date cheat */
 
				case STR_CHEAT_CHANGE_DATE: SetDParam(0, _date); break;
 
				/* Draw colored flag for change player cheat */
 
				case STR_CHEAT_CHANGE_PLAYER:
 
					SetDParam(0, val);
 
					GetString(buf, STR_CHEAT_CHANGE_PLAYER);
 
					GetString(buf, STR_CHEAT_CHANGE_PLAYER, lastof(buf));
 
					DrawPlayerIcon(_current_player, 60 + GetStringBoundingBox(buf).width, y + 2);
 
					break;
 
				/* Set correct string for switch climate cheat */
 
				case STR_CHEAT_SWITCH_CLIMATE: val += STR_TEMPERATE_LANDSCAPE;
 
				/* Fallthrough */
 
				default: SetDParam(0, val);
network.c
Show inline comments
 
@@ -128,60 +128,60 @@ void CDECL NetworkTextMessage(NetworkAct
 
	va_start(va, str);
 
	vsnprintf(buf, lengthof(buf), str, va);
 
	va_end(va);
 

	
 
	switch (action) {
 
		case NETWORK_ACTION_JOIN:
 
			GetString(temp, STR_NETWORK_CLIENT_JOINED);
 
			GetString(temp, STR_NETWORK_CLIENT_JOINED, lastof(temp));
 
			snprintf(message, sizeof(message), "*** %s %s", name, temp);
 
			break;
 
		case NETWORK_ACTION_LEAVE:
 
			GetString(temp, STR_NETWORK_ERR_LEFT);
 
			GetString(temp, STR_NETWORK_ERR_LEFT, lastof(temp));
 
			snprintf(message, sizeof(message), "*** %s %s (%s)", name, temp, buf);
 
			break;
 
		case NETWORK_ACTION_GIVE_MONEY:
 
			if (self_send) {
 
				SetDParamStr(0, name);
 
				SetDParam(1, atoi(buf));
 
				GetString(temp, STR_NETWORK_GAVE_MONEY_AWAY);
 
				GetString(temp, STR_NETWORK_GAVE_MONEY_AWAY, lastof(temp));
 
				snprintf(message, sizeof(message), "*** %s", temp);
 
			} else {
 
				SetDParam(0, atoi(buf));
 
				GetString(temp, STR_NETWORK_GIVE_MONEY);
 
				GetString(temp, STR_NETWORK_GIVE_MONEY, lastof(temp));
 
				snprintf(message, sizeof(message), "*** %s %s", name, temp);
 
			}
 
			break;
 
		case NETWORK_ACTION_CHAT_COMPANY:
 
			if (self_send) {
 
				SetDParamStr(0, name);
 
				GetString(temp, STR_NETWORK_CHAT_TO_COMPANY);
 
				GetString(temp, STR_NETWORK_CHAT_TO_COMPANY, lastof(temp));
 
				snprintf(message, sizeof(message), "%s %s", temp, buf);
 
			} else {
 
				SetDParamStr(0, name);
 
				GetString(temp, STR_NETWORK_CHAT_COMPANY);
 
				GetString(temp, STR_NETWORK_CHAT_COMPANY, lastof(temp));
 
				snprintf(message, sizeof(message), "%s %s", temp, buf);
 
			}
 
			break;
 
		case NETWORK_ACTION_CHAT_CLIENT:
 
			if (self_send) {
 
				SetDParamStr(0, name);
 
				GetString(temp, STR_NETWORK_CHAT_TO_CLIENT);
 
				GetString(temp, STR_NETWORK_CHAT_TO_CLIENT, lastof(temp));
 
				snprintf(message, sizeof(message), "%s %s", temp, buf);
 
			} else {
 
				SetDParamStr(0, name);
 
				GetString(temp, STR_NETWORK_CHAT_CLIENT);
 
				GetString(temp, STR_NETWORK_CHAT_CLIENT, lastof(temp));
 
				snprintf(message, sizeof(message), "%s %s", temp, buf);
 
			}
 
			break;
 
		case NETWORK_ACTION_NAME_CHANGE:
 
			GetString(temp, STR_NETWORK_NAME_CHANGE);
 
			GetString(temp, STR_NETWORK_NAME_CHANGE, lastof(temp));
 
			snprintf(message, sizeof(message), "*** %s %s %s", name, temp, buf);
 
			break;
 
		default:
 
			SetDParamStr(0, name);
 
			GetString(temp, STR_NETWORK_CHAT_ALL);
 
			GetString(temp, STR_NETWORK_CHAT_ALL, lastof(temp));
 
			snprintf(message, sizeof(message), "%s %s", temp, buf);
 
			break;
 
	}
 

	
 
	IConsolePrintF(color, "%s", message);
 
	AddTextMessage(color, duration, "%s", message);
 
@@ -257,13 +257,13 @@ static void NetworkClientError(NetworkRe
 
}
 

	
 
/** Retrieve a string representation of an internal error number
 
 * @param buf buffer where the error message will be stored
 
 * @param err NetworkErrorCode
 
 * @return returns a pointer to the error message (buf) */
 
char *GetNetworkErrorMsg(char *buf, NetworkErrorCode err)
 
char* GetNetworkErrorMsg(char* buf, NetworkErrorCode err, const char* last)
 
{
 
	/* List of possible network errors, used by
 
	 * PACKET_SERVER_ERROR and PACKET_CLIENT_ERROR */
 
	static const StringID network_error_strings[] = {
 
		STR_NETWORK_ERR_CLIENT_GENERAL,
 
		STR_NETWORK_ERR_CLIENT_DESYNC,
 
@@ -280,13 +280,13 @@ char *GetNetworkErrorMsg(char *buf, Netw
 
		STR_NETWORK_ERR_CLIENT_CHEATER,
 
		STR_NETWORK_ERR_CLIENT_SERVER_FULL
 
	};
 

	
 
	if (err >= lengthof(network_error_strings)) err = 0;
 

	
 
	return GetString(buf, network_error_strings[err]);
 
	return GetString(buf, network_error_strings[err], last);
 
}
 

	
 
/* Count the number of active clients connected */
 
static uint NetworkCountPlayers(void)
 
{
 
	const NetworkClientState *cs;
 
@@ -596,13 +596,13 @@ void NetworkCloseClient(NetworkClientSta
 
		char str[100];
 
		char client_name[NETWORK_CLIENT_NAME_LENGTH];
 
		NetworkClientState *new_cs;
 

	
 
		NetworkGetClientName(client_name, sizeof(client_name), cs);
 

	
 
		GetNetworkErrorMsg(str, errorno);
 
		GetNetworkErrorMsg(str, errorno, lastof(str));
 

	
 
		NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
 

	
 
		// Inform other clients of this... strange leaving ;)
 
		FOR_ALL_CLIENTS(new_cs) {
 
			if (new_cs->status > STATUS_AUTH && cs != new_cs) {
network_client.c
Show inline comments
 
@@ -625,13 +625,13 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 
				break;
 
			case NETWORK_ACTION_CHAT_COMPANY:
 
			case NETWORK_ACTION_GIVE_MONEY:
 
				/* For speaking to player or give money, we need the player-name */
 
				if (!IsValidPlayer(ci_to->client_playas)) return NETWORK_RECV_STATUS_OKAY; // This should never happen
 

	
 
				GetString(name, GetPlayer(ci_to->client_playas)->name_1);
 
				GetString(name, GetPlayer(ci_to->client_playas)->name_1, lastof(name));
 
				ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
 
				break;
 
			default:
 
				/* This should never happen */
 
				NOT_REACHED();
 
				break;
 
@@ -651,13 +651,13 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 
{
 
	char str[100];
 
	uint16 index;
 
	NetworkClientInfo *ci;
 

	
 
	index = NetworkRecv_uint16(MY_CLIENT, p);
 
	GetNetworkErrorMsg(str, NetworkRecv_uint8(MY_CLIENT, p));
 
	GetNetworkErrorMsg(str, NetworkRecv_uint8(MY_CLIENT, p), lastof(str));
 

	
 
	ci = NetworkFindClientInfoFromIndex(index);
 
	if (ci != NULL) {
 
		NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, ci->client_name, "%s", str);
 

	
 
		// The client is gone, give the NetworkClientInfo free
network_data.h
Show inline comments
 
@@ -227,11 +227,11 @@ void NetworkGetClientName(char *clientna
 
uint NetworkCalculateLag(const NetworkClientState *cs);
 
byte NetworkGetCurrentLanguageIndex(void);
 
NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index);
 
NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip);
 
NetworkClientState *NetworkFindClientStateFromIndex(uint16 client_index);
 
unsigned long NetworkResolveHost(const char *hostname);
 
char *GetNetworkErrorMsg(char *buf, NetworkErrorCode err);
 
char* GetNetworkErrorMsg(char* buf, NetworkErrorCode err, const char* last);
 

	
 
#endif /* ENABLE_NETWORK */
 

	
 
#endif /* NETWORK_DATA_H */
network_gui.c
Show inline comments
 
@@ -1178,42 +1178,42 @@ static Window *PopupClientList(Window *w
 

	
 
	ci = NetworkFindClientInfo(client_no);
 
	if (ci == NULL) return NULL;
 

	
 
	i = 0;
 
	if (_network_own_client_index != ci->client_index) {
 
		GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT);
 
		GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, lastof(_clientlist_action[i]));
 
		_clientlist_proc[i++] = &ClientList_SpeakToClient;
 
	}
 

	
 
	if (IsValidPlayer(ci->client_playas)) {
 
		GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY);
 
		GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, lastof(_clientlist_action[i]));
 
		_clientlist_proc[i++] = &ClientList_SpeakToCompany;
 
	}
 
	GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL);
 
	GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, lastof(_clientlist_action[i]));
 
	_clientlist_proc[i++] = &ClientList_SpeakToAll;
 

	
 
	if (_network_own_client_index != ci->client_index) {
 
		/* We are no spectator and the player we want to give money to is no spectator */
 
		if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas)) {
 
			GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY);
 
			GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY, lastof(_clientlist_action[i]));
 
			_clientlist_proc[i++] = &ClientList_GiveMoney;
 
		}
 
	}
 

	
 
	// A server can kick clients (but not himself)
 
	if (_network_server && _network_own_client_index != ci->client_index) {
 
		GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_KICK);
 
		GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_KICK, lastof(_clientlist_action[i]));
 
		_clientlist_proc[i++] = &ClientList_Kick;
 

	
 
		sprintf(_clientlist_action[i],"Ban");
 
		sprintf(_clientlist_action[i],"Ban"); // XXX GetString?
 
		_clientlist_proc[i++] = &ClientList_Ban;
 
	}
 

	
 
	if (i == 0) {
 
		GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_NONE);
 
		GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_NONE, lastof(_clientlist_action[i]));
 
		_clientlist_proc[i++] = &ClientList_None;
 
	}
 

	
 
	/* Calculate the height */
 
	h = ClientListPopupHeigth();
 

	
 
@@ -1508,13 +1508,13 @@ static const char *ChatTabCompletionNext
 
	if (*item < (uint)MAX_CLIENT_INFO + GetTownArraySize()) {
 
		const Town *t;
 

	
 
		FOR_ALL_TOWNS_FROM(t, *item - MAX_CLIENT_INFO) {
 
			/* Get the town-name via the string-system */
 
			SetDParam(0, t->townnameparts);
 
			GetString(chat_tab_temp_buffer, t->townnametype);
 
			GetString(chat_tab_temp_buffer, t->townnametype, lastof(chat_tab_temp_buffer));
 
			return &chat_tab_temp_buffer[0];
 
		}
 
	}
 

	
 
	return NULL;
 
}
network_server.c
Show inline comments
 
/* $Id$ */
 

	
 
#ifdef ENABLE_NETWORK
 

	
 
#include "stdafx.h"
 
#include "openttd.h" // XXX StringID
 
#include "debug.h"
 
#include "string.h"
 
#include "strings.h"
 
#include "network_data.h"
 
#include "train.h"
 
#include "date.h"
 
@@ -141,13 +142,13 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SER
 
	char str[100];
 
	Packet *p = NetworkSend_Init(PACKET_SERVER_ERROR);
 

	
 
	NetworkSend_uint8(p, error);
 
	NetworkSend_Packet(p, cs);
 

	
 
	GetNetworkErrorMsg(str, error);
 
	GetNetworkErrorMsg(str, error, lastof(str));
 

	
 
	// Only send when the current client was in game
 
	if (cs->status > STATUS_AUTH) {
 
		NetworkClientState *new_cs;
 
		char client_name[NETWORK_CLIENT_NAME_LENGTH];
 

	
 
@@ -896,13 +897,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT
 
		cs->has_quit = true;
 
		return;
 
	}
 

	
 
	NetworkGetClientName(client_name, sizeof(client_name), cs);
 

	
 
	GetNetworkErrorMsg(str, errorno);
 
	GetNetworkErrorMsg(str, errorno, lastof(str));
 

	
 
	DEBUG(net, 2)("[NET] %s reported an error and is closing his connection (%s)", client_name, str);
 

	
 
	NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
 

	
 
	FOR_ALL_CLIENTS(new_cs) {
 
@@ -1040,13 +1041,13 @@ void NetworkServer_HandleChat(NetworkAct
 
		if (ci_to == NULL) break;
 

	
 
		// Display the message locally (so you know you have sent it)
 
		if (ci != NULL && show_local) {
 
			if (from_index == NETWORK_SERVER_INDEX) {
 
				char name[NETWORK_NAME_LENGTH];
 
				GetString(name, GetPlayer(ci_to->client_playas)->name_1);
 
				GetString(name, GetPlayer(ci_to->client_playas)->name_1, lastof(name));
 
				NetworkTextMessage(action, GetDrawStringPlayerColor(ci_own->client_playas), true, name, "%s", msg);
 
			} else {
 
				FOR_ALL_CLIENTS(cs) {
 
					if (cs->index == from_index) {
 
						SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, ci_to->client_index, true, msg);
 
					}
 
@@ -1208,13 +1209,13 @@ void NetworkPopulateCompanyInfo(void)
 
		_network_player_info[p->index].months_empty = months_empty;
 
		ttd_strlcpy(_network_player_info[p->index].password, password, sizeof(_network_player_info[p->index].password));
 

	
 
		// Grap the company name
 
		SetDParam(0, p->name_1);
 
		SetDParam(1, p->name_2);
 
		GetString(_network_player_info[p->index].company_name, STR_JUST_STRING);
 
		GetString(_network_player_info[p->index].company_name, STR_JUST_STRING, lastof(_network_player_info[p->index].company_name));
 

	
 
		// Check the income
 
		if (_cur_year - 1 == p->inaugurated_year) {
 
			// The player is here just 1 year, so display [2], else display[1]
 
			for (i = 0; i < lengthof(p->yearly_expenses[2]); i++) {
 
				_network_player_info[p->index].income -= p->yearly_expenses[2][i];
newgrf_text.c
Show inline comments
 
@@ -289,13 +289,13 @@ StringID GetGRFStringID(uint32 grfid, ui
 
	}
 

	
 
	return STR_UNDEFINED;
 
}
 

	
 

	
 
char *GetGRFString(char *buff, uint16 stringid)
 
char *GetGRFString(char *buff, uint16 stringid, const char* last)
 
{
 
	const GRFText *default_text = NULL;
 
	const GRFText *search_text;
 

	
 
	assert(_grf_text[stringid].grfid != 0);
 

	
 
@@ -316,13 +316,13 @@ char *GetGRFString(char *buff, uint16 st
 
	}
 

	
 
	/* If there is a fallback string, return that */
 
	if (default_text != NULL) return strecpy(buff, default_text->text, NULL);
 

	
 
	/* Use the default string ID if the fallback string isn't available */
 
	return GetString(buff, _grf_text[stringid].def_string);
 
	return GetString(buff, _grf_text[stringid].def_string, last);
 
}
 

	
 
/**
 
 * Equivalence Setter function between game and newgrf langID.
 
 * This function will adjust _currentLangID as to what is the LangID
 
 * of the current language set by the user.
newgrf_text.h
Show inline comments
 
@@ -5,11 +5,11 @@
 
/** @file
 
 * Header of Action 04 "universal holder" structure and functions
 
 */
 

	
 
StringID AddGRFString(uint32 grfid, uint16 stringid, byte langid, bool new_scheme, const char *text_to_add, StringID def_string);
 
StringID GetGRFStringID(uint32 grfid, uint16 stringid);
 
char *GetGRFString(char *buff, uint16 stringid);
 
char *GetGRFString(char *buff, uint16 stringid, const char* last);
 
void CleanUpStrings(void);
 
void SetCurrentGrfLangID(const char *iso_name);
 

	
 
#endif /* NEWGRF_TEXT_H */
news_gui.c
Show inline comments
 
@@ -576,13 +576,13 @@ static void DrawNewsString(int x, int y,
 
		str = _get_news_string_callback[ni->callback](ni);
 
	} else {
 
		COPY_IN_DPARAM(0, ni->params, lengthof(ni->params));
 
		str = ni->string_id;
 
	}
 

	
 
	GetString(buffer, str);
 
	GetString(buffer, str, lastof(buffer));
 
	/* Copy the just gotten string to another buffer to remove any formatting
 
	 * from it such as big fonts, etc. */
 
	for (ptr = buffer, dest = buffer2; *ptr != '\0'; ptr++) {
 
		if (*ptr == '\r') {
 
			dest[0] = dest[1] = dest[2] = dest[3] = ' ';
 
			dest += 4;
openttd.c
Show inline comments
 
@@ -14,12 +14,13 @@
 
#define VARDEF
 
#include "openttd.h"
 
#include "bridge_map.h"
 
#include "functions.h"
 
#include "mixer.h"
 
#include "spritecache.h"
 
#include "strings.h"
 
#include "gfx.h"
 
#include "gfxinit.h"
 
#include "gui.h"
 
#include "station.h"
 
#include "station_map.h"
 
#include "town_map.h"
 
@@ -875,22 +876,23 @@ void StateGameLoop(void)
 
static void DoAutosave(void)
 
{
 
	char buf[200];
 

	
 
	if (_patches.keep_all_autosave && _local_player != PLAYER_SPECTATOR) {
 
		const Player *p = GetPlayer(_local_player);
 
		char *s;
 
		sprintf(buf, "%s%s", _path.autosave_dir, PATHSEP);
 
		char* s = buf;
 

	
 
		s += snprintf(buf, lengthof(buf), "%s%s", _path.autosave_dir, PATHSEP);
 

	
 
		SetDParam(0, p->name_1);
 
		SetDParam(1, p->name_2);
 
		SetDParam(2, _date);
 
		s = GetString(buf + strlen(_path.autosave_dir) + strlen(PATHSEP), STR_4004);
 
		strcpy(s, ".sav");
 
		s = GetString(s, STR_4004, lastof(buf));
 
		strecpy(s, ".sav", lastof(buf));
 
	} else { /* generate a savegame name and number according to _patches.max_num_autosaves */
 
		sprintf(buf, "%s%sautosave%d.sav", _path.autosave_dir, PATHSEP, _autosave_ctr);
 
		snprintf(buf, lengthof(buf), "%s%sautosave%d.sav", _path.autosave_dir, PATHSEP, _autosave_ctr);
 

	
 
		_autosave_ctr++;
 
		if (_autosave_ctr >= _patches.max_num_autosaves) {
 
			// we reached the limit for numbers of autosaves. We will start over
 
			_autosave_ctr = 0;
 
		}
order_cmd.c
Show inline comments
 
@@ -823,13 +823,13 @@ void BackupVehicleOrders(const Vehicle *
 
	bak->service_interval = v->service_interval;
 

	
 
	/* Safe custom string, if any */
 
	if (!IsCustomName(v->string_id)) {
 
		bak->name[0] = '\0';
 
	} else {
 
		GetName(v->string_id & 0x7FF, bak->name);
 
		GetName(bak->name, v->string_id & 0x7FF, lastof(bak->name));
 
	}
 

	
 
	/* If we have shared orders, store it on a special way */
 
	if (IsOrderListShared(v)) {
 
		const Vehicle *u = (v->next_shared) ? v->next_shared : v->prev_shared;
 

	
players.c
Show inline comments
 
@@ -328,13 +328,13 @@ static void GenerateCompanyName(Player *
 
verify_name:;
 
		// No player must have this name already
 
		FOR_ALL_PLAYERS(pp) {
 
			if (pp->name_1 == str && pp->name_2 == strp) goto bad_town_name;
 
		}
 

	
 
		GetString(buffer, str);
 
		GetString(buffer, str, lastof(buffer));
 
		if (strlen(buffer) >= 32 || GetStringBoundingBox(buffer).width >= 150)
 
			goto bad_town_name;
 

	
 
set_name:;
 
		p->name_1 = str;
 
		p->name_2 = strp;
 
@@ -435,20 +435,20 @@ static void GeneratePresidentName(Player
 
restart:;
 

	
 
		p->president_name_2 = Random();
 
		p->president_name_1 = SPECSTR_PRESIDENT_NAME;
 

	
 
		SetDParam(0, p->president_name_2);
 
		GetString(buffer, p->president_name_1);
 
		GetString(buffer, p->president_name_1, lastof(buffer));
 
		if (strlen(buffer) >= 32 || GetStringBoundingBox(buffer).width >= 94)
 
			continue;
 

	
 
		FOR_ALL_PLAYERS(pp) {
 
			if (pp->is_active && p != pp) {
 
				SetDParam(0, pp->president_name_2);
 
				GetString(buffer2, pp->president_name_1);
 
				GetString(buffer2, pp->president_name_1, lastof(buffer));
 
				if (strcmp(buffer2, buffer) == 0)
 
					goto restart;
 
			}
 
		}
 
		return;
 
	}
 
@@ -995,13 +995,13 @@ int8 SaveHighScoreValue(const Player *p)
 
			// move all elements one down starting from the replaced one
 
			memmove(&hs[i + 1], &hs[i], sizeof(HighScore) * (lengthof(_highscore_table[0]) - i - 1));
 
			SetDParam(0, p->president_name_1);
 
			SetDParam(1, p->president_name_2);
 
			SetDParam(2, p->name_1);
 
			SetDParam(3, p->name_2);
 
			GetString(hs[i].company, STR_HIGHSCORE_NAME); // get manager/company name string
 
			GetString(hs[i].company, STR_HIGHSCORE_NAME, lastof(hs[i].company)); // get manager/company name string
 
			hs[i].score = score;
 
			hs[i].title = EndGameGetPerformanceTitleFromValue(score);
 
			return i;
 
		}
 
	}
 

	
 
@@ -1040,13 +1040,13 @@ int8 SaveHighScoreValueNetwork(void)
 
			HighScore* hs = &_highscore_table[LAST_HS_ITEM][i];
 

	
 
			SetDParam(0, pl[i]->president_name_1);
 
			SetDParam(1, pl[i]->president_name_2);
 
			SetDParam(2, pl[i]->name_1);
 
			SetDParam(3, pl[i]->name_2);
 
			GetString(hs->company, STR_HIGHSCORE_NAME); // get manager/company name string
 
			GetString(hs->company, STR_HIGHSCORE_NAME, lastof(hs->company)); // get manager/company name string
 
			hs->score = pl[i]->old_economy[0].performance_history;
 
			hs->title = EndGameGetPerformanceTitleFromValue(hs->score);
 

	
 
			// get the ranking of the local player
 
			if (pl[i]->index == _local_player) player = i;
 
		}
screenshot.c
Show inline comments
 
@@ -501,13 +501,13 @@ static char *MakeScreenshotName(const ch
 
		sprintf(_screenshot_name, "screenshot");
 
	} else {
 
		const Player* p = GetPlayer(_local_player);
 
		SetDParam(0, p->name_1);
 
		SetDParam(1, p->name_2);
 
		SetDParam(2, _date);
 
		GetString(_screenshot_name, STR_4004);
 
		GetString(_screenshot_name, STR_4004, lastof(_screenshot_name));
 
	}
 

	
 
	base = strchr(_screenshot_name, 0);
 
	base[0] = '.'; strcpy(base + 1, ext);
 

	
 
	serial = 0;
station_gui.c
Show inline comments
 
@@ -78,18 +78,18 @@ static int CDECL StationNameSorter(const
 
	const Station* st1 = *(const Station**)a;
 
	const Station* st2 = *(const Station**)b;
 
	char buf1[64];
 
	int r;
 

	
 
	SetDParam(0, st1->index);
 
	GetString(buf1, STR_STATION);
 
	GetString(buf1, STR_STATION, lastof(buf1));
 

	
 
	if (st2 != _last_station) {
 
		_last_station = st2;
 
		SetDParam(0, st2->index);
 
		GetString(_bufcache, STR_STATION);
 
		GetString(_bufcache, STR_STATION, lastof(_bufcache));
 
	}
 

	
 
	r =  strcmp(buf1, _bufcache); // sort by name
 
	return (_internal_sort_order & 1) ? -r : r;
 
}
 

	
string.c
Show inline comments
 
/* $Id$ */
 

	
 
#include "stdafx.h"
 
#include "openttd.h"
 
#include "functions.h"
 
#include "string.h"
 

	
 
#include <stdarg.h>
 
#include <ctype.h> // required for tolower()
 

	
 
void ttd_strlcat(char *dst, const char *src, size_t size)
 
@@ -23,26 +25,31 @@ void ttd_strlcpy(char *dst, const char *
 
	*dst = '\0';
 
}
 

	
 

	
 
char* strecat(char* dst, const char* src, const char* last)
 
{
 
	assert(last == NULL || dst <= last);
 
	assert(dst <= last);
 
	for (; *dst != '\0'; ++dst)
 
		if (dst == last) return dst;
 
	for (; *src != '\0' && dst != last; ++dst, ++src) *dst = *src;
 
	*dst = '\0';
 
	return strecpy(dst, src, last);
 
}
 

	
 

	
 
char* strecpy(char* dst, const char* src, const char* last)
 
{
 
	assert(last == NULL || dst <= last);
 
	assert(dst <= last);
 
	for (; *src != '\0' && dst != last; ++dst, ++src) *dst = *src;
 
	*dst = '\0';
 
#if 0
 
	if (dst == last && *src != '\0') {
 
		error("String too long for destination buffer");
 
	}
 
#endif
 
	return dst;
 
}
 

	
 

	
 
char* CDECL str_fmt(const char* str, ...)
 
{
strings.c
Show inline comments
 
@@ -28,17 +28,17 @@
 
# include <sys/types.h>
 
# include <dirent.h>
 
#endif /* WIN32 */
 

	
 
char _userstring[128];
 

	
 
static char *StationGetSpecialString(char *buff, int x);
 
static char *GetSpecialTownNameString(char *buff, int ind, uint32 seed);
 
static char *GetSpecialPlayerNameString(char *buff, int ind, const int32 *argv);
 
static char *StationGetSpecialString(char *buff, int x, const char* last);
 
static char *GetSpecialTownNameString(char *buff, int ind, uint32 seed, const char* last);
 
static char *GetSpecialPlayerNameString(char *buff, int ind, const int32 *argv, const char* last);
 

	
 
static char *FormatString(char *buff, const char *str, const int32 *argv, uint casei);
 
static char *FormatString(char *buff, const char *str, const int32 *argv, uint casei, const char* last);
 

	
 
typedef struct LanguagePack {
 
	uint32 ident;
 
	uint32 version;     // 32-bits of auto generated version info which is basically a hash of strings.h
 
	char name[32];      // the international name of this language
 
	char own_name[32];  // the localized name of this language
 
@@ -163,78 +163,78 @@ static const char *GetStringPtr(StringID
 
}
 

	
 
// The highest 8 bits of string contain the "case index".
 
// These 8 bits will only be set when FormatString wants to print
 
// the string in a different case. No one else except FormatString
 
// should set those bits, therefore string CANNOT be StringID, but uint32.
 
static char *GetStringWithArgs(char *buffr, uint string, const int32 *argv)
 
static char *GetStringWithArgs(char *buffr, uint string, const int32 *argv, const char* last)
 
{
 
	uint index = GB(string,  0, 11);
 
	uint tab   = GB(string, 11,  5);
 
	char buff[512];
 

	
 
	if (GB(string, 0, 16) == 0) error("!invalid string id 0 in GetString");
 

	
 
	switch (tab) {
 
		case 4:
 
			if (index >= 0xC0)
 
				return GetSpecialTownNameString(buffr, index - 0xC0, GetInt32(&argv));
 
				return GetSpecialTownNameString(buffr, index - 0xC0, GetInt32(&argv), last);
 
			break;
 

	
 
		case 14:
 
			if (index >= 0xE4)
 
				return GetSpecialPlayerNameString(buffr, index - 0xE4, argv);
 
				return GetSpecialPlayerNameString(buffr, index - 0xE4, argv, last);
 
			break;
 

	
 
		// User defined name
 
		case 15:
 
			return GetName(index, buffr);
 
			return GetName(buffr, index, last);
 

	
 
		case 26:
 
			/* Include string within newgrf text (format code 81) */
 
			if (HASBIT(index, 10)) {
 
				StringID string = GetGRFStringID(0, 0xD000 + GB(index, 0, 10));
 
				return GetStringWithArgs(buffr, string, argv);
 
				return GetStringWithArgs(buffr, string, argv, last);
 
			}
 
			break;
 

	
 
		case 28:
 
			GetGRFString(buff, index);
 
			return FormatString(buffr, buff, argv, 0);
 
			GetGRFString(buff, index, last);
 
			return FormatString(buffr, buff, argv, 0, last);
 

	
 
		case 29:
 
			GetGRFString(buff, index + 0x800);
 
			return FormatString(buffr, buff, argv, 0);
 
			GetGRFString(buff, index + 0x800, last);
 
			return FormatString(buffr, buff, argv, 0, last);
 

	
 
		case 30:
 
			GetGRFString(buff, index + 0x1000);
 
			return FormatString(buffr, buff, argv, 0);
 
			GetGRFString(buff, index + 0x1000, last);
 
			return FormatString(buffr, buff, argv, 0, last);
 

	
 
		case 31:
 
			// dynamic strings. These are NOT to be passed through the formatter,
 
			// but passed through verbatim.
 
			if (index < (STR_SPEC_USERSTRING & 0x7FF)) {
 
				return strecpy(buffr, _bound_strings[index], NULL);
 
				return strecpy(buffr, _bound_strings[index], last);
 
			}
 

	
 
			return FormatString(buffr, _userstring, NULL, 0);
 
			return FormatString(buffr, _userstring, NULL, 0, last);
 
	}
 

	
 
	if (index >= _langtab_num[tab]) {
 
		error(
 
			"!String 0x%X is invalid. "
 
			"Probably because an old version of the .lng file.\n", string
 
		);
 
	}
 

	
 
	return FormatString(buffr, GetStringPtr(GB(string, 0, 16)), argv, GB(string, 24, 8));
 
	return FormatString(buffr, GetStringPtr(GB(string, 0, 16)), argv, GB(string, 24, 8), last);
 
}
 

	
 
char *GetString(char *buffr, StringID string)
 
char *GetString(char *buffr, StringID string, const char* last)
 
{
 
	return GetStringWithArgs(buffr, string, (int32*)_decode_parameters);
 
	return GetStringWithArgs(buffr, string, (int32*)_decode_parameters, last);
 
}
 

	
 

	
 
// This function takes a C-string and allocates a temporary string ID.
 
// The duration of the bound string is valid only until the next GetString,
 
// so be careful.
 
@@ -267,13 +267,14 @@ static const uint32 _divisor_table[] = {
 
	1000,
 
	100,
 
	10,
 
	1
 
};
 

	
 
static char *FormatCommaNumber(char *buff, int32 number)
 
// TODO
 
static char *FormatCommaNumber(char *buff, int32 number, const char* last)
 
{
 
	uint32 quot,divisor;
 
	int i;
 
	uint32 tot;
 
	uint32 num;
 

	
 
@@ -300,21 +301,22 @@ static char *FormatCommaNumber(char *buf
 

	
 
	*buff = '\0';
 

	
 
	return buff;
 
}
 

	
 
static char *FormatNoCommaNumber(char *buff, int32 number)
 
// TODO
 
static char *FormatNoCommaNumber(char *buff, int32 number, const char* last)
 
{
 
	uint32 quot,divisor;
 
	int i;
 
	uint32 tot;
 
	uint32 num;
 

	
 
	if (number < 0) {
 
		*buff++ = '-';
 
		buff = strecpy(buff, "-", last);
 
		number = -number;
 
	}
 

	
 
	num = number;
 

	
 
	tot = 0;
 
@@ -333,108 +335,102 @@ static char *FormatNoCommaNumber(char *b
 
	*buff = '\0';
 

	
 
	return buff;
 
}
 

	
 

	
 
static char *FormatYmdString(char *buff, Date date)
 
static char *FormatYmdString(char *buff, Date date, const char* last)
 
{
 
	const char *src;
 
	YearMonthDay ymd;
 

	
 
	ConvertDateToYMD(date, &ymd);
 

	
 
	buff = strecpy(buff, GetStringPtr(ymd.day + STR_01AC_1ST - 1), last);
 
	buff = strecpy(buff, " ", last);
 
	buff = strecpy(buff, GetStringPtr(STR_0162_JAN + ymd.month), last);
 
	buff = strecpy(buff, " ", last);
 

	
 
	return FormatNoCommaNumber(buff, ymd.year, last);
 
}
 

	
 
static char *FormatMonthAndYear(char *buff, Date date, const char* last)
 
{
 
	YearMonthDay ymd;
 

	
 
	ConvertDateToYMD(date, &ymd);
 

	
 
	for (src = GetStringPtr(ymd.day + STR_01AC_1ST - 1); (*buff++ = *src++) != '\0';) {}
 
	buff[-1] = ' ';
 
	buff = strecpy(buff, GetStringPtr(STR_MONTH_JAN + ymd.month), last);
 
	buff = strecpy(buff, " ", last);
 

	
 
	for (src = GetStringPtr(STR_0162_JAN + ymd.month); (*buff++ = *src++) != '\0';) {}
 
	buff[-1] = ' ';
 

	
 
	return FormatNoCommaNumber(buff, ymd.year);
 
	return FormatNoCommaNumber(buff, ymd.year, last);
 
}
 

	
 
static char *FormatMonthAndYear(char *buff, Date date)
 
{
 
	const char *src;
 
	YearMonthDay ymd;
 

	
 
	ConvertDateToYMD(date, &ymd);
 

	
 
	for (src = GetStringPtr(STR_MONTH_JAN + ymd.month); (*buff++ = *src++) != '\0';) {}
 
	buff[-1] = ' ';
 

	
 
	return FormatNoCommaNumber(buff, ymd.year);
 
}
 

	
 
static char *FormatTinyDate(char *buff, Date date)
 
static char *FormatTinyDate(char *buff, Date date, const char* last)
 
{
 
	YearMonthDay ymd;
 

	
 
	ConvertDateToYMD(date, &ymd);
 
	buff += sprintf(buff, " %02i-%02i-%04i", ymd.day, ymd.month + 1, ymd.year);
 
	buff += snprintf(
 
		buff, last - buff + 1,
 
		" %02i-%02i-%04i", ymd.day, ymd.month + 1, ymd.year
 
	);
 

	
 
	return buff;
 
}
 

	
 
static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, int64 number, bool compact)
 
static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, int64 number, bool compact, const char* last)
 
{
 
	const char *s;
 
	char c;
 
	char buf[40], *p;
 
	const char* multiplier = "";
 
	char buf[40];
 
	char* p;
 
	int j;
 

	
 
	// multiply by exchange rate
 
	number *= spec->rate;
 

	
 
	// convert from negative
 
	if (number < 0) {
 
		*buff++ = '-';
 
		buff = strecpy(buff, "-", last);
 
		number = -number;
 
	}
 

	
 
	/* Add prefix part, folowing symbol_pos specification.
 
	 * Here, it can can be either 0 (prefix) or 2 (both prefix anf suffix).
 
	 * The only remaining value is 1 (suffix), so everything that is not 1 */
 
	if (spec->symbol_pos != 1){
 
		s = spec->prefix;
 
		while (s != spec->prefix + lengthof(spec->prefix) && (c = *(s++)) != '\0') *(buff)++ = c;
 
	}
 
	if (spec->symbol_pos != 1) buff = strecpy(buff, spec->prefix, last);
 

	
 
	// for huge numbers, compact the number into k or M
 
	if (compact) {
 
		compact = 0;
 
		if (number >= 1000000000) {
 
			number = (number + 500000) / 1000000;
 
			compact = 'M';
 
			multiplier = "M";
 
		} else if (number >= 1000000) {
 
			number = (number + 500) / 1000;
 
			compact = 'k';
 
			multiplier = "k";
 
		}
 
	}
 

	
 
	// convert to ascii number and add commas
 
	p = buf;
 
	p = endof(buf);
 
	*--p = '\0';
 
	j = 4;
 
	do {
 
		if (--j == 0) {
 
			*p++ = spec->separator;
 
			*--p = spec->separator;
 
			j = 3;
 
		}
 
		*p++ = '0' + number % 10;
 
	} while (number /= 10);
 
	do *buff++ = *--p; while (p != buf);
 
		*--p = '0' + number % 10;
 
	} while ((number /= 10) != 0);
 
	buff = strecpy(buff, p, last);
 

	
 
	if (compact) *buff++ = compact;
 
	buff = strecpy(buff, multiplier, last);
 

	
 
	/* Add suffix part, folowing symbol_pos specification.
 
	 * Here, it can can be either 1 (suffix) or 2 (both prefix anf suffix).
 
	 * The only remaining value is 1 (prefix), so everything that is not 0 */
 
	if (spec->symbol_pos != 0) {
 
		s = spec->suffix;
 
		while (s != spec->suffix + lengthof(spec->suffix) && (c = *(s++)) != '\0') *(buff++) = c;
 
	}
 
	if (spec->symbol_pos != 0) buff = strecpy(buff, spec->suffix, last);
 

	
 
	return buff;
 
}
 

	
 
static int DeterminePluralForm(int32 n)
 
{
 
@@ -561,132 +557,136 @@ static const Units units[] = {
 
		1000,  0, STR_UNITS_WEIGHT_SHORT_SI, STR_UNITS_WEIGHT_LONG_SI,
 
		   1,  0, STR_UNITS_VOLUME_SHORT_SI, STR_UNITS_VOLUME_LONG_SI,
 
		   1,  0, STR_UNITS_FORCE_SI,
 
	},
 
};
 

	
 
static char *FormatString(char *buff, const char *str, const int32 *argv, uint casei)
 
static char* FormatString(char* buff, const char* str, const int32* argv, uint casei, const char* last)
 
{
 
	extern const char _openttd_revision[];
 
	byte b;
 
	const int32 *argv_orig = argv;
 
	uint modifier = 0;
 

	
 
	while ((b = *str++) != '\0') {
 
		switch (b) {
 
		case 0x1: // {SETX}
 
			*buff++ = b;
 
			*buff++ = *str++;
 
			if (buff != last && buff + 1 != last) {
 
				*buff++ = b;
 
				*buff++ = *str++;
 
			}
 
			break;
 
		case 0x2: // {SETXY}
 
			*buff++ = b;
 
			*buff++ = *str++;
 
			*buff++ = *str++;
 
			if (buff != last && buff + 1 != last && buff + 2 != last) {
 
				*buff++ = b;
 
				*buff++ = *str++;
 
				*buff++ = *str++;
 
			}
 
			break;
 

	
 
		case 0x81: // {STRINL}
 
			buff = GetStringWithArgs(buff, ReadLE16Unaligned(str), argv);
 
			buff = GetStringWithArgs(buff, ReadLE16Unaligned(str), argv, last);
 
			str += 2;
 
			break;
 
		case 0x82: // {DATE_LONG}
 
			buff = FormatYmdString(buff, GetInt32(&argv));
 
			buff = FormatYmdString(buff, GetInt32(&argv), last);
 
			break;
 
		case 0x83: // {DATE_SHORT}
 
			buff = FormatMonthAndYear(buff, GetInt32(&argv));
 
			buff = FormatMonthAndYear(buff, GetInt32(&argv), last);
 
			break;
 
		case 0x84: {// {VELOCITY}
 
			int32 args[1];
 
			assert(_opt_ptr->units < lengthof(units));
 
			args[0] = GetInt32(&argv) * units[_opt_ptr->units].s_m >> units[_opt_ptr->units].s_s;
 
			buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].velocity), args, modifier >> 24);
 
			buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].velocity), args, modifier >> 24, last);
 
			modifier = 0;
 
			break;
 
		}
 
		// 0x85 is used as escape character..
 
		case 0x85:
 
			switch (*str++) {
 
			case 0: /* {CURRCOMPACT} */
 
				buff = FormatGenericCurrency(buff, _currency, GetInt32(&argv), true);
 
				buff = FormatGenericCurrency(buff, _currency, GetInt32(&argv), true, last);
 
				break;
 
			case 2: /* {REV} */
 
				buff = strecpy(buff, _openttd_revision, NULL);
 
				buff = strecpy(buff, _openttd_revision, last);
 
				break;
 
			case 3: { /* {SHORTCARGO} */
 
				// Short description of cargotypes. Layout:
 
				// 8-bit = cargo type
 
				// 16-bit = cargo count
 
				StringID cargo_str = _cargo_types_base_values[_opt_ptr->landscape].units_volume[GetInt32(&argv)];
 
				switch (cargo_str) {
 
					case STR_TONS: {
 
						int32 args[1];
 
						assert(_opt_ptr->units < lengthof(units));
 
						args[0] = GetInt32(&argv) * units[_opt_ptr->units].w_m >> units[_opt_ptr->units].w_s;
 
						buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_weight), args, modifier >> 24);
 
						buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_weight), args, modifier >> 24, last);
 
						modifier = 0;
 
						break;
 
					}
 

	
 
					case STR_LITERS: {
 
						int32 args[1];
 
						assert(_opt_ptr->units < lengthof(units));
 
						args[0] = GetInt32(&argv) * units[_opt_ptr->units].v_m >> units[_opt_ptr->units].v_s;
 
						buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_volume), args, modifier >> 24);
 
						buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_volume), args, modifier >> 24, last);
 
						modifier = 0;
 
						break;
 
					}
 

	
 
					default:
 
						buff = FormatCommaNumber(buff, GetInt32(&argv));
 
						buff = strecpy(buff, " ", NULL);
 
						buff = strecpy(buff, GetStringPtr(cargo_str), NULL);
 
						buff = FormatCommaNumber(buff, GetInt32(&argv), last);
 
						buff = strecpy(buff, " ", last);
 
						buff = strecpy(buff, GetStringPtr(cargo_str), last);
 
						break;
 
				}
 
			} break;
 
			case 4: {/* {CURRCOMPACT64} */
 
				// 64 bit compact currency-unit
 
				buff = FormatGenericCurrency(buff, _currency, GetInt64(&argv), true);
 
				buff = FormatGenericCurrency(buff, _currency, GetInt64(&argv), true, last);
 
				break;
 
			}
 
			case 5: { /* {STRING1} */
 
				// String that consumes ONE argument
 
				uint str = modifier + GetInt32(&argv);
 
				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 1));
 
				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 1), last);
 
				modifier = 0;
 
				break;
 
			}
 
			case 6: { /* {STRING2} */
 
				// String that consumes TWO arguments
 
				uint str = modifier + GetInt32(&argv);
 
				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 2));
 
				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 2), last);
 
				modifier = 0;
 
				break;
 
			}
 
			case 7: { /* {STRING3} */
 
				// String that consumes THREE arguments
 
				uint str = modifier + GetInt32(&argv);
 
				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 3));
 
				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 3), last);
 
				modifier = 0;
 
				break;
 
			}
 
			case 8: { /* {STRING4} */
 
				// String that consumes FOUR arguments
 
				uint str = modifier + GetInt32(&argv);
 
				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 4));
 
				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 4), last);
 
				modifier = 0;
 
				break;
 
			}
 
			case 9: { /* {STRING5} */
 
				// String that consumes FIVE arguments
 
				uint str = modifier + GetInt32(&argv);
 
				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 5));
 
				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 5), last);
 
				modifier = 0;
 
				break;
 
			}
 

	
 
			case 10: { /* {STATIONFEATURES} */
 
				buff = StationGetSpecialString(buff, GetInt32(&argv));
 
				buff = StationGetSpecialString(buff, GetInt32(&argv), last);
 
				break;
 
			}
 

	
 
			case 11: { /* {INDUSTRY} */
 
				const Industry* i = GetIndustry(GetInt32(&argv));
 
				int32 args[2];
 
@@ -695,22 +695,22 @@ static char *FormatString(char *buff, co
 
				if (!IsValidIndustry(i)) break;
 

	
 
				// First print the town name and the industry type name
 
				// The string STR_INDUSTRY_PATTERN controls the formatting
 
				args[0] = i->town->index;
 
				args[1] = i->type + STR_4802_COAL_MINE;
 
				buff = FormatString(buff, GetStringPtr(STR_INDUSTRY_FORMAT), args, modifier >> 24);
 
				buff = FormatString(buff, GetStringPtr(STR_INDUSTRY_FORMAT), args, modifier >> 24, last);
 
				modifier = 0;
 
				break;
 
			}
 

	
 
			case 12: { // {VOLUME}
 
				int32 args[1];
 
				assert(_opt_ptr->units < lengthof(units));
 
				args[0] = GetInt32(&argv) * units[_opt_ptr->units].v_m >> units[_opt_ptr->units].v_s;
 
				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_volume), args, modifier >> 24);
 
				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_volume), args, modifier >> 24, last);
 
				modifier = 0;
 
				break;
 
			}
 

	
 
			case 13: { // {G 0 Der Die Das}
 
				const byte* s = (const byte*)GetStringPtr(argv_orig[(byte)*str++]); // contains the string that determines gender.
 
@@ -720,67 +720,67 @@ static char *FormatString(char *buff, co
 
				str = ParseStringChoice(str, gender, buff, &len);
 
				buff += len;
 
				break;
 
			}
 

	
 
			case 14: { // {DATE_TINY}
 
				buff = FormatTinyDate(buff, GetInt32(&argv));
 
				buff = FormatTinyDate(buff, GetInt32(&argv), last);
 
				break;
 
			}
 

	
 
			case 15: { // {CARGO}
 
				// Layout now is:
 
				//   8bit   - cargo type
 
				//   16-bit - cargo count
 
				CargoID cargo = GetInt32(&argv);
 
				StringID cargo_str = (cargo == CT_INVALID) ? STR_8838_N_A : _cargoc.names_long[cargo];
 
				buff = GetStringWithArgs(buff, cargo_str, argv++);
 
				buff = GetStringWithArgs(buff, cargo_str, argv++, last);
 
				break;
 
			}
 

	
 
			case 16: { // {POWER}
 
				int32 args[1];
 
				assert(_opt_ptr->units < lengthof(units));
 
				args[0] = GetInt32(&argv) * units[_opt_ptr->units].p_m >> units[_opt_ptr->units].p_s;
 
				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].power), args, modifier >> 24);
 
				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].power), args, modifier >> 24, last);
 
				modifier = 0;
 
				break;
 
			}
 

	
 
			case 17: { // {VOLUME_S}
 
				int32 args[1];
 
				assert(_opt_ptr->units < lengthof(units));
 
				args[0] = GetInt32(&argv) * units[_opt_ptr->units].v_m >> units[_opt_ptr->units].v_s;
 
				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].s_volume), args, modifier >> 24);
 
				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].s_volume), args, modifier >> 24, last);
 
				modifier = 0;
 
				break;
 
			}
 

	
 
			case 18: { // {WEIGHT}
 
				int32 args[1];
 
				assert(_opt_ptr->units < lengthof(units));
 
				args[0] = GetInt32(&argv) * units[_opt_ptr->units].w_m >> units[_opt_ptr->units].w_s;
 
				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_weight), args, modifier >> 24);
 
				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_weight), args, modifier >> 24, last);
 
				modifier = 0;
 
				break;
 
			}
 

	
 
			case 19: { // {WEIGHT_S}
 
				int32 args[1];
 
				assert(_opt_ptr->units < lengthof(units));
 
				args[0] = GetInt32(&argv) * units[_opt_ptr->units].w_m >> units[_opt_ptr->units].w_s;
 
				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].s_weight), args, modifier >> 24);
 
				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].s_weight), args, modifier >> 24, last);
 
				modifier = 0;
 
				break;
 
			}
 

	
 
			case 20: { // {FORCE}
 
				int32 args[1];
 
				assert(_opt_ptr->units < lengthof(units));
 
				args[0] = GetInt32(&argv) * units[_opt_ptr->units].f_m >> units[_opt_ptr->units].f_s;
 
				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].force), args, modifier >> 24);
 
				buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].force), args, modifier >> 24, last);
 
				modifier = 0;
 
				break;
 
			}
 

	
 
			default:
 
				error("!invalid escape sequence in string");
 
@@ -799,19 +799,19 @@ static char *FormatString(char *buff, co
 

	
 
		case 0x88: {// {STRING}
 
			uint str = modifier + GetInt32(&argv);
 
			// WARNING. It's prohibited for the included string to consume any arguments.
 
			// For included strings that consume argument, you should use STRING1, STRING2 etc.
 
			// To debug stuff you can set argv to NULL and it will tell you
 
			buff = GetStringWithArgs(buff, str, argv);
 
			buff = GetStringWithArgs(buff, str, argv, last);
 
			modifier = 0;
 
			break;
 
		}
 

	
 
		case 0x8B: // {COMMA}
 
			buff = FormatCommaNumber(buff, GetInt32(&argv));
 
			buff = FormatCommaNumber(buff, GetInt32(&argv), last);
 
			break;
 

	
 
		case 0x8C: // Move argument pointer
 
			argv = argv_orig + (byte)*str++;
 
			break;
 

	
 
@@ -821,17 +821,17 @@ static char *FormatString(char *buff, co
 
			str = ParseStringChoice(str, DeterminePluralForm(v), buff, &len);
 
			buff += len;
 
			break;
 
		}
 

	
 
		case 0x8E: // {NUM}
 
			buff = FormatNoCommaNumber(buff, GetInt32(&argv));
 
			buff = FormatNoCommaNumber(buff, GetInt32(&argv), last);
 
			break;
 

	
 
		case 0x8F: // {CURRENCY}
 
			buff = FormatGenericCurrency(buff, _currency, GetInt32(&argv), false);
 
			buff = FormatGenericCurrency(buff, _currency, GetInt32(&argv), false, last);
 
			break;
 

	
 
		case 0x99: { // {WAYPOINT}
 
			int32 temp[2];
 
			Waypoint *wp = GetWaypoint(GetInt32(&argv));
 
			StringID str;
 
@@ -839,41 +839,41 @@ static char *FormatString(char *buff, co
 
				str = wp->string;
 
			} else {
 
				temp[0] = wp->town_index;
 
				temp[1] = wp->town_cn + 1;
 
				str = wp->town_cn == 0 ? STR_WAYPOINTNAME_CITY : STR_WAYPOINTNAME_CITY_SERIAL;
 
			}
 
			buff = GetStringWithArgs(buff, str, temp);
 
			buff = GetStringWithArgs(buff, str, temp, last);
 
		} break;
 

	
 
		case 0x9A: { // {STATION}
 
			const Station* st = GetStation(GetInt32(&argv));
 
			int32 temp[2];
 

	
 
			if (!IsValidStation(st)) { // station doesn't exist anymore
 
				buff = GetStringWithArgs(buff, STR_UNKNOWN_DESTINATION, NULL);
 
				break;
 
				buff = GetStringWithArgs(buff, STR_UNKNOWN_DESTINATION, NULL, last);
 
			} else {
 
				int32 temp[2];
 
				temp[0] = st->town->townnametype;
 
				temp[1] = st->town->townnameparts;
 
				buff = GetStringWithArgs(buff, st->string_id, temp, last);
 
			}
 
			temp[0] = st->town->townnametype;
 
			temp[1] = st->town->townnameparts;
 
			buff = GetStringWithArgs(buff, st->string_id, temp);
 
			break;
 
		}
 
		case 0x9B: { // {TOWN}
 
			const Town* t = GetTown(GetInt32(&argv));
 
			int32 temp[1];
 

	
 
			assert(IsValidTown(t));
 

	
 
			temp[0] = t->townnameparts;
 
			buff = GetStringWithArgs(buff, t->townnametype, temp);
 
			buff = GetStringWithArgs(buff, t->townnametype, temp, last);
 
			break;
 
		}
 

	
 
		case 0x9C: { // {CURRENCY64}
 
			buff = FormatGenericCurrency(buff, _currency, GetInt64(&argv), false);
 
			buff = FormatGenericCurrency(buff, _currency, GetInt64(&argv), false, last);
 
			break;
 
		}
 

	
 
		case 0x9D: { // {SETCASE}
 
			// This is a pseudo command, it's outputted when someone does {STRING.ack}
 
			// The modifier is added to all subsequent GetStringWithArgs that accept the modifier.
 
@@ -896,37 +896,36 @@ static char *FormatString(char *buff, co
 
				num--;
 
			}
 
			break;
 
		}
 

	
 
		default:
 
			*buff++ = b;
 
			if (buff != last) *buff++ = b;
 
		}
 
	}
 
	*buff = '\0';
 
	return buff;
 
}
 

	
 

	
 
static char *StationGetSpecialString(char *buff, int x)
 
static char *StationGetSpecialString(char *buff, int x, const char* last)
 
{
 
	if (x & 0x01) *buff++ = '\x94';
 
	if (x & 0x02) *buff++ = '\x95';
 
	if (x & 0x04) *buff++ = '\x96';
 
	if (x & 0x08) *buff++ = '\x97';
 
	if (x & 0x10) *buff++ = '\x98';
 
	*buff = '\0';
 
	if (x & 0x01) buff = strecpy(buff, "\x94", last);
 
	if (x & 0x02) buff = strecpy(buff, "\x95", last);
 
	if (x & 0x04) buff = strecpy(buff, "\x96", last);
 
	if (x & 0x08) buff = strecpy(buff, "\x97", last);
 
	if (x & 0x10) buff = strecpy(buff, "\x98", last);
 
	return buff;
 
}
 

	
 
static char *GetSpecialTownNameString(char *buff, int ind, uint32 seed)
 
static char *GetSpecialTownNameString(char *buff, int ind, uint32 seed, const char* last)
 
{
 
	_town_name_generators[ind](buff, seed);
 
	char name[512];
 

	
 
	while (*buff != '\0') buff++;
 
	return buff;
 
	_town_name_generators[ind](name, seed); // TODO
 
	return strecpy(buff, name, last);
 
}
 

	
 
static const char* const _silly_company_names[] = {
 
	"Bloggs Brothers",
 
	"Tiny Transport Ltd.",
 
	"Express Travel",
 
@@ -991,102 +990,102 @@ static const char* const _silly_surname_
 

	
 
static const char _initial_name_letters[] = {
 
	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
 
	'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W',
 
};
 

	
 
static char *GenAndCoName(char *buff, uint32 arg)
 
static char *GenAndCoName(char *buff, uint32 arg, const char* last)
 
{
 
	const char* const* base;
 
	uint num;
 

	
 
	if (_opt_ptr->landscape == LT_CANDY) {
 
		base = _silly_surname_list;
 
		num  = lengthof(_silly_surname_list);
 
	} else {
 
		base = _surname_list;
 
		num  = lengthof(_surname_list);
 
	}
 

	
 
	buff = strecpy(buff, base[num * GB(arg, 16, 8) >> 8], NULL);
 
	buff = strecpy(buff, " & Co.", NULL);
 
	buff = strecpy(buff, base[num * GB(arg, 16, 8) >> 8], last);
 
	buff = strecpy(buff, " & Co.", last);
 

	
 
	return buff;
 
}
 

	
 
static char *GenPresidentName(char *buff, uint32 x)
 
static char *GenPresidentName(char *buff, uint32 x, const char* last)
 
{
 
	char initial[] = "?. ";
 
	const char* const* base;
 
	uint num;
 
	uint i;
 

	
 
	buff[0] = _initial_name_letters[sizeof(_initial_name_letters) * GB(x, 0, 8) >> 8];
 
	buff[1] = '.';
 
	buff[2] = ' '; // Insert a space after initial and period "I. Firstname" instead of "I.Firstname"
 
	buff += 3;
 
	initial[0] = _initial_name_letters[sizeof(_initial_name_letters) * GB(x, 0, 8) >> 8];
 
	buff = strecpy(buff, initial, last);
 

	
 
	i = (sizeof(_initial_name_letters) + 35) * GB(x, 8, 8) >> 8;
 
	if (i < sizeof(_initial_name_letters)) {
 
		buff[0] = _initial_name_letters[i];
 
		buff[1] = '.';
 
		buff[2] = ' '; // Insert a space after initial and period "I. J. Firstname" instead of "I.J.Firstname"
 
		buff += 3;
 
		initial[0] = _initial_name_letters[i];
 
		buff = strecpy(buff, initial, last);
 
	}
 

	
 
	if (_opt_ptr->landscape == LT_CANDY) {
 
		base = _silly_surname_list;
 
		num  = lengthof(_silly_surname_list);
 
	} else {
 
		base = _surname_list;
 
		num  = lengthof(_surname_list);
 
	}
 

	
 
	buff = strecpy(buff, base[num * GB(x, 16, 8) >> 8], NULL);
 
	buff = strecpy(buff, base[num * GB(x, 16, 8) >> 8], last);
 

	
 
	return buff;
 
}
 

	
 
static char *GetSpecialPlayerNameString(char *buff, int ind, const int32 *argv)
 
static char *GetSpecialPlayerNameString(char *buff, int ind, const int32 *argv, const char* last)
 
{
 
	switch (ind) {
 
		case 1: // not used
 
			return strecpy(buff, _silly_company_names[GetInt32(&argv) & 0xFFFF], NULL);
 
			return strecpy(buff, _silly_company_names[GetInt32(&argv) & 0xFFFF], last);
 

	
 
		case 2: // used for Foobar & Co company names
 
			return GenAndCoName(buff, GetInt32(&argv));
 
			return GenAndCoName(buff, GetInt32(&argv), last);
 

	
 
		case 3: // President name
 
			return GenPresidentName(buff, GetInt32(&argv));
 
			return GenPresidentName(buff, GetInt32(&argv), last);
 

	
 
		case 4: // song names
 
			return strecpy(buff, origin_songs_specs[GetInt32(&argv) - 1].song_name, NULL);
 
			return strecpy(buff, origin_songs_specs[GetInt32(&argv) - 1].song_name, last);
 
	}
 

	
 
	// town name?
 
	if (IS_INT_INSIDE(ind - 6, 0, SPECSTR_TOWNNAME_LAST-SPECSTR_TOWNNAME_START + 1)) {
 
		buff = GetSpecialTownNameString(buff, ind - 6, GetInt32(&argv));
 
		return strecpy(buff, " Transport", NULL);
 
		buff = GetSpecialTownNameString(buff, ind - 6, GetInt32(&argv), last);
 
		return strecpy(buff, " Transport", last);
 
	}
 

	
 
	// language name?
 
	if (IS_INT_INSIDE(ind, (SPECSTR_LANGUAGE_START - 0x70E4), (SPECSTR_LANGUAGE_END - 0x70E4) + 1)) {
 
		int i = ind - (SPECSTR_LANGUAGE_START - 0x70E4);
 
		return strecpy(buff,
 
			i == _dynlang.curr ? _langpack->own_name : _dynlang.ent[i].name, NULL);
 
			i == _dynlang.curr ? _langpack->own_name : _dynlang.ent[i].name, last);
 
	}
 

	
 
	// resolution size?
 
	if (IS_INT_INSIDE(ind, (SPECSTR_RESOLUTION_START - 0x70E4), (SPECSTR_RESOLUTION_END - 0x70E4) + 1)) {
 
		int i = ind - (SPECSTR_RESOLUTION_START - 0x70E4);
 
		return buff + sprintf(buff, "%dx%d", _resolutions[i][0], _resolutions[i][1]);
 
		buff += snprintf(
 
			buff, last - buff + 1, "%dx%d", _resolutions[i][0], _resolutions[i][1]
 
		);
 
		return buff;
 
	}
 

	
 
	// screenshot format name?
 
	if (IS_INT_INSIDE(ind, (SPECSTR_SCREENSHOT_START - 0x70E4), (SPECSTR_SCREENSHOT_END - 0x70E4) + 1)) {
 
		int i = ind - (SPECSTR_SCREENSHOT_START - 0x70E4);
 
		return strecpy(buff, GetScreenshotFormatDesc(i), NULL);
 
		return strecpy(buff, GetScreenshotFormatDesc(i), last);
 
	}
 

	
 
	assert(0);
 
	return NULL;
 
}
 

	
strings.h
Show inline comments
 
@@ -8,13 +8,13 @@ static inline char* InlineString(char* b
 
	*buf++ = '\x81';
 
	*buf++ = string & 0xFF;
 
	*buf++ = string >> 8;
 
	return buf;
 
}
 

	
 
char *GetString(char *buffr, uint16 string);
 
char *GetString(char *buffr, uint16 string, const char* last);
 

	
 
extern char _userstring[128];
 

	
 
void InjectDParam(int amount);
 
int32 GetParamInt32(void);
 

	
texteff.c
Show inline comments
 
@@ -243,13 +243,13 @@ void AddTextEffect(StringID msg, int x, 
 
	te->duration = duration;
 
	te->y = y - 5;
 
	te->bottom = y + 5;
 
	te->params_1 = GetDParam(0);
 
	te->params_2 = GetDParam(4);
 

	
 
	GetString(buffer, msg);
 
	GetString(buffer, msg, lastof(buffer));
 
	w = GetStringBoundingBox(buffer).width;
 

	
 
	te->x = x - (w >> 1);
 
	te->right = x + (w >> 1) - 1;
 
	MarkTextEffectAreaDirty(te);
 
}
town_cmd.c
Show inline comments
 
@@ -883,22 +883,22 @@ static bool CreateTownName(uint32 *townn
 

	
 
	for (;;) {
 
restart:
 
		r = Random();
 

	
 
		SetDParam(0, r);
 
		GetString(buf1, townnametype);
 
		GetString(buf1, townnametype, lastof(buf1));
 

	
 
		// Check size and width
 
		if (strlen(buf1) >= 31 || GetStringBoundingBox(buf1).width > 130) continue;
 

	
 
		FOR_ALL_TOWNS(t2) {
 
			// We can't just compare the numbers since
 
			// several numbers may map to a single name.
 
			SetDParam(0, t2->index);
 
			GetString(buf2, STR_TOWN);
 
			GetString(buf2, STR_TOWN, lastof(buf2));
 
			if (strcmp(buf1, buf2) == 0) {
 
				if (tries-- < 0) return false;
 
				goto restart;
 
			}
 
		}
 
		*townnameparts = r;
town_gui.c
Show inline comments
 
@@ -375,21 +375,21 @@ static int CDECL TownNameSorter(const vo
 
	const Town* ta = *(const Town**)a;
 
	const Town* tb = *(const Town**)b;
 
	char buf1[64];
 
	int r;
 

	
 
	SetDParam(0, ta->index);
 
	GetString(buf1, STR_TOWN);
 
	GetString(buf1, STR_TOWN, lastof(buf1));
 

	
 
	/* If 'b' is the same town as in the last round, use the cached value
 
	 *  We do this to speed stuff up ('b' is called with the same value a lot of
 
	 *  times after eachother) */
 
	if (tb != _last_town) {
 
		_last_town = tb;
 
		SetDParam(0, tb->index);
 
		GetString(_bufcache, STR_TOWN);
 
		GetString(_bufcache, STR_TOWN, lastof(_bufcache));
 
	}
 

	
 
	r = strcmp(buf1, _bufcache);
 
	if (_town_sort_order & 1) r = -r;
 
	return r;
 
}
train_gui.c
Show inline comments
 
@@ -132,19 +132,19 @@ static int CDECL TrainEngineNameSorter(c
 
{
 
	const EngineID va = *(const EngineID*)a;
 
	const EngineID vb = *(const EngineID*)b;
 
	char buf1[64];
 
	int r;
 

	
 
	GetString(buf1, GetCustomEngineName(va));
 
	GetString(buf1, GetCustomEngineName(va), lastof(buf1));
 

	
 
	if (vb != _last_engine) {
 
		_last_engine = vb;
 
		_bufcache[0] = '\0';
 

	
 
		GetString(_bufcache, GetCustomEngineName(vb));
 
		GetString(_bufcache, GetCustomEngineName(vb), lastof(_bufcache));
 
	}
 

	
 
	r =  strcasecmp(buf1, _bufcache); // sort by name
 

	
 
	if (r == 0) {
 
		/* Use EngineID to sort instead since we want consistent sorting */
vehicle.c
Show inline comments
 
@@ -2073,13 +2073,13 @@ static int32 ReplaceVehicle(Vehicle **w,
 
		MoveVehicleCargo(new_v->type == VEH_Train ? GetFirstVehicleInChain(new_v) : new_v, old_v);
 

	
 
		// Get the name of the old vehicle if it has a custom name.
 
		if (!IsCustomName(old_v->string_id)) {
 
			vehicle_name[0] = '\0';
 
		} else {
 
			GetName(old_v->string_id & 0x7FF, vehicle_name);
 
			GetName(vehicle_name, old_v->string_id & 0x7FF, lastof(vehicle_name));
 
		}
 
	} else { // flags & DC_EXEC not set
 
		/* Ensure that the player will not end up having negative money while autoreplacing
 
		 * This is needed because the only other check is done after the income from selling the old vehicle is substracted from the cost */
 
		if (p->money64 < (cost + total_cost)) {
 
			SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
vehicle_gui.c
Show inline comments
 
@@ -513,22 +513,22 @@ static int CDECL VehicleNameSorter(const
 
	const Vehicle* vb = *(const Vehicle**)b;
 
	int r;
 

	
 
	if (va != last_vehicle[0]) {
 
		last_vehicle[0] = va;
 
		if (IsCustomName(va->string_id)) {
 
			GetString(last_name[0], va->string_id);
 
			GetString(last_name[0], va->string_id, lastof(last_name[0]));
 
		} else {
 
			last_name[0][0] = '\0';
 
		}
 
	}
 

	
 
	if (vb != last_vehicle[1]) {
 
		last_vehicle[1] = vb;
 
		if (IsCustomName(vb->string_id)) {
 
			GetString(last_name[1], vb->string_id);
 
			GetString(last_name[1], vb->string_id, lastof(last_name[1]));
 
		} else {
 
			last_name[1][0] = '\0';
 
		}
 
	}
 

	
 
	r = strcmp(last_name[0], last_name[1]); // sort by name
viewport.c
Show inline comments
 
@@ -1014,13 +1014,13 @@ void UpdateViewportSignPos(ViewportSign 
 
{
 
	char buffer[128];
 
	uint w;
 

	
 
	sign->top = top;
 

	
 
	GetString(buffer, str);
 
	GetString(buffer, str, lastof(buffer));
 
	w = GetStringBoundingBox(buffer).width + 3;
 
	sign->width_1 = w;
 
	sign->left = left - w / 2;
 

	
 
	/* zoomed out version */
 
	_cur_fontsize = FS_SMALL;
0 comments (0 inline, 0 general)