(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.
This commit is contained in:
		| @@ -99,12 +99,12 @@ static int CDECL EngineNameSorter(const void *a, const void *b) | |||||||
|  |  | ||||||
| 	if (va != last_engine[0]) { | 	if (va != last_engine[0]) { | ||||||
| 		last_engine[0] = va; | 		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]) { | 	if (vb != last_engine[1]) { | ||||||
| 		last_engine[1] = vb; | 		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 | 	r = strcmp(last_name[0], last_name[1]); // sort by name | ||||||
|   | |||||||
| @@ -1217,7 +1217,7 @@ DEF_CONSOLE_CMD(ConPlayers) | |||||||
|  |  | ||||||
| 		if (!p->is_active) continue; | 		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)", | 		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), | 			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], | 			/* trains      */ _network_player_info[p->index].num_vehicle[0], | ||||||
|   | |||||||
| @@ -140,7 +140,7 @@ void InitializeLandscapeVariables(bool only_constants); | |||||||
| /* misc.c */ | /* misc.c */ | ||||||
| bool IsCustomName(StringID id); | bool IsCustomName(StringID id); | ||||||
| void DeleteName(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 | // AllocateNameUnique also tests if the name used is not used anywere else | ||||||
| //  and if it is used, it returns an error. | //  and if it is used, it returns an error. | ||||||
|   | |||||||
| @@ -284,7 +284,7 @@ void GenerateLandscapeWndProc(Window *w, WindowEvent *e) | |||||||
| 				SetDParam(0, _heightmap_x); | 				SetDParam(0, _heightmap_x); | ||||||
| 				SetDParam(1, _heightmap_y); | 				SetDParam(1, _heightmap_y); | ||||||
| 			} | 			} | ||||||
| 			GetString(buffer, STR_HEIGHTMAP_SIZE); | 			GetString(buffer, STR_HEIGHTMAP_SIZE, lastof(buffer)); | ||||||
| 			DrawStringRightAligned(326, 91, STR_HEIGHTMAP_SIZE, 0x10); | 			DrawStringRightAligned(326, 91, STR_HEIGHTMAP_SIZE, 0x10); | ||||||
|  |  | ||||||
| 			DrawString( 12,  91, STR_HEIGHTMAP_NAME, 0x10); | 			DrawString( 12,  91, STR_HEIGHTMAP_NAME, 0x10); | ||||||
|   | |||||||
							
								
								
									
										20
									
								
								gfx.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								gfx.c
									
									
									
									
									
								
							| @@ -329,9 +329,9 @@ static int TruncateString(char *str, int maxw) | |||||||
| 	return w; | 	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); | 	return TruncateString(dest, maxw); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -340,14 +340,14 @@ int DrawString(int x, int y, StringID str, uint16 color) | |||||||
| { | { | ||||||
| 	char buffer[512]; | 	char buffer[512]; | ||||||
|  |  | ||||||
| 	GetString(buffer, str); | 	GetString(buffer, str, lastof(buffer)); | ||||||
| 	return DoDrawString(buffer, x, y, color); | 	return DoDrawString(buffer, x, y, color); | ||||||
| } | } | ||||||
|  |  | ||||||
| int DrawStringTruncated(int x, int y, StringID str, uint16 color, uint maxw) | int DrawStringTruncated(int x, int y, StringID str, uint16 color, uint maxw) | ||||||
| { | { | ||||||
| 	char buffer[512]; | 	char buffer[512]; | ||||||
| 	TruncateStringID(str, buffer, maxw); | 	TruncateStringID(str, buffer, maxw, lastof(buffer)); | ||||||
| 	return DoDrawString(buffer, x, y, color); | 	return DoDrawString(buffer, x, y, color); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -357,7 +357,7 @@ int DrawStringRightAligned(int x, int y, StringID str, uint16 color) | |||||||
| 	char buffer[512]; | 	char buffer[512]; | ||||||
| 	int w; | 	int w; | ||||||
|  |  | ||||||
| 	GetString(buffer, str); | 	GetString(buffer, str, lastof(buffer)); | ||||||
| 	w = GetStringBoundingBox(buffer).width; | 	w = GetStringBoundingBox(buffer).width; | ||||||
| 	DoDrawString(buffer, x - w, y, color); | 	DoDrawString(buffer, x - w, y, color); | ||||||
|  |  | ||||||
| @@ -368,7 +368,7 @@ void DrawStringRightAlignedTruncated(int x, int y, StringID str, uint16 color, u | |||||||
| { | { | ||||||
| 	char buffer[512]; | 	char buffer[512]; | ||||||
|  |  | ||||||
| 	TruncateStringID(str, buffer, maxw); | 	TruncateStringID(str, buffer, maxw, lastof(buffer)); | ||||||
| 	DoDrawString(buffer, x - GetStringBoundingBox(buffer).width, y, color); | 	DoDrawString(buffer, x - GetStringBoundingBox(buffer).width, y, color); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -384,7 +384,7 @@ int DrawStringCentered(int x, int y, StringID str, uint16 color) | |||||||
| 	char buffer[512]; | 	char buffer[512]; | ||||||
| 	int w; | 	int w; | ||||||
|  |  | ||||||
| 	GetString(buffer, str); | 	GetString(buffer, str, lastof(buffer)); | ||||||
|  |  | ||||||
| 	w = GetStringBoundingBox(buffer).width; | 	w = GetStringBoundingBox(buffer).width; | ||||||
| 	DoDrawString(buffer, x - w / 2, y, color); | 	DoDrawString(buffer, x - w / 2, y, color); | ||||||
| @@ -395,7 +395,7 @@ int DrawStringCentered(int x, int y, StringID str, uint16 color) | |||||||
| int DrawStringCenteredTruncated(int xl, int xr, int y, StringID str, uint16 color) | int DrawStringCenteredTruncated(int xl, int xr, int y, StringID str, uint16 color) | ||||||
| { | { | ||||||
| 	char buffer[512]; | 	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); | 	return DoDrawString(buffer, (xl + xr - w) / 2, y, color); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -466,7 +466,7 @@ void DrawStringMultiCenter(int x, int y, StringID str, int maxw) | |||||||
| 	const char *src; | 	const char *src; | ||||||
| 	byte c; | 	byte c; | ||||||
|  |  | ||||||
| 	GetString(buffer, str); | 	GetString(buffer, str, lastof(buffer)); | ||||||
|  |  | ||||||
| 	tmp = FormatStringLinebreaks(buffer, maxw); | 	tmp = FormatStringLinebreaks(buffer, maxw); | ||||||
| 	num = GB(tmp, 0, 16); | 	num = GB(tmp, 0, 16); | ||||||
| @@ -508,7 +508,7 @@ void DrawStringMultiLine(int x, int y, StringID str, int maxw) | |||||||
| 	const char *src; | 	const char *src; | ||||||
| 	byte c; | 	byte c; | ||||||
|  |  | ||||||
| 	GetString(buffer, str); | 	GetString(buffer, str, lastof(buffer)); | ||||||
|  |  | ||||||
| 	tmp = FormatStringLinebreaks(buffer, maxw); | 	tmp = FormatStringLinebreaks(buffer, maxw); | ||||||
| 	num = GB(tmp, 0, 16); | 	num = GB(tmp, 0, 16); | ||||||
|   | |||||||
| @@ -1135,11 +1135,11 @@ static int CDECL SignNameSorter(const void *a, const void *b) | |||||||
| 	const Sign *sign1 = *(const Sign**)b; | 	const Sign *sign1 = *(const Sign**)b; | ||||||
| 	char buf1[64]; | 	char buf1[64]; | ||||||
|  |  | ||||||
| 	GetString(buf1, sign0->str); | 	GetString(buf1, sign0->str, lastof(buf1)); | ||||||
|  |  | ||||||
| 	if (sign1 != _last_sign) { | 	if (sign1 != _last_sign) { | ||||||
| 		_last_sign = sign1; | 		_last_sign = sign1; | ||||||
| 		GetString(_bufcache, sign1->str); | 		GetString(_bufcache, sign1->str, lastof(_bufcache)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return strcmp(buf1, _bufcache); // sort by name | 	return strcmp(buf1, _bufcache); // sort by name | ||||||
|   | |||||||
| @@ -536,12 +536,12 @@ static int CDECL GeneralIndustrySorter(const void *a, const void *b) | |||||||
| 		char buf1[96]; | 		char buf1[96]; | ||||||
|  |  | ||||||
| 		SetDParam(0, i->town->index); | 		SetDParam(0, i->town->index); | ||||||
| 		GetString(buf1, STR_TOWN); | 		GetString(buf1, STR_TOWN, lastof(buf1)); | ||||||
|  |  | ||||||
| 		if (j != _last_industry) { | 		if (j != _last_industry) { | ||||||
| 			_last_industry = j; | 			_last_industry = j; | ||||||
| 			SetDParam(0, j->town->index); | 			SetDParam(0, j->town->index); | ||||||
| 			GetString(_bufcache, STR_TOWN); | 			GetString(_bufcache, STR_TOWN, lastof(_bufcache)); | ||||||
| 		} | 		} | ||||||
| 		r = strcmp(buf1, _bufcache); | 		r = strcmp(buf1, _bufcache); | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -658,7 +658,7 @@ static int GetStringListMaxWidth(StringID base_string, byte count) | |||||||
|  |  | ||||||
| 	max_width = 0; | 	max_width = 0; | ||||||
| 	for (i = 0; i != count; i++) { | 	for (i = 0; i != count; i++) { | ||||||
| 		GetString(buffer, base_string + i); | 		GetString(buffer, base_string + i, lastof(buffer)); | ||||||
| 		width = GetStringBoundingBox(buffer).width; | 		width = GetStringBoundingBox(buffer).width; | ||||||
| 		if (width > max_width) max_width = width; | 		if (width > max_width) max_width = width; | ||||||
| 	} | 	} | ||||||
| @@ -2108,7 +2108,7 @@ static bool DrawScrollingStatusText(const NewsItem *ni, int pos) | |||||||
| 		str = ni->string_id; | 		str = ni->string_id; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	GetString(buf, str); | 	GetString(buf, str, lastof(buf)); | ||||||
|  |  | ||||||
| 	s = buf; | 	s = buf; | ||||||
| 	d = buffer; | 	d = buffer; | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								misc.c
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								misc.c
									
									
									
									
									
								
							| @@ -162,9 +162,9 @@ void DeleteName(StringID id) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| 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); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								misc_gui.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								misc_gui.c
									
									
									
									
									
								
							| @@ -92,7 +92,7 @@ static void LandInfoWndProc(Window *w, WindowEvent *e) | |||||||
|  |  | ||||||
| 		{ | 		{ | ||||||
| 			char buf[512]; | 			char buf[512]; | ||||||
| 			char *p = GetString(buf, STR_01CE_CARGO_ACCEPTED); | 			char *p = GetString(buf, STR_01CE_CARGO_ACCEPTED, lastof(buf)); | ||||||
| 			bool found = false; | 			bool found = false; | ||||||
|  |  | ||||||
| 			for (i = 0; i < NUM_CARGO; ++i) { | 			for (i = 0; i < NUM_CARGO; ++i) { | ||||||
| @@ -108,9 +108,9 @@ static void LandInfoWndProc(Window *w, WindowEvent *e) | |||||||
| 					if (lid->ac[i] < 8) { | 					if (lid->ac[i] < 8) { | ||||||
| 						SetDParam(0, lid->ac[i]); | 						SetDParam(0, lid->ac[i]); | ||||||
| 						SetDParam(1, _cargoc.names_s[i]); | 						SetDParam(1, _cargoc.names_s[i]); | ||||||
| 						p = GetString(p, STR_01D1_8); | 						p = GetString(p, STR_01D1_8, lastof(buf)); | ||||||
| 					} else { | 					} else { | ||||||
| 						p = GetString(p, _cargoc.names_s[i]); | 						p = GetString(p, _cargoc.names_s[i], lastof(buf)); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @@ -679,7 +679,7 @@ void GuiShowTooltipsWithArgs(StringID str, uint paramcount, const uint32 params[ | |||||||
| 	if (str == STR_NULL || (paramcount != 0 && !_patches.measure_tooltip)) return; | 	if (str == STR_NULL || (paramcount != 0 && !_patches.measure_tooltip)) return; | ||||||
|  |  | ||||||
| 	for (i = 0; i != paramcount; i++) SetDParam(i, params[i]); | 	for (i = 0; i != paramcount; i++) SetDParam(i, params[i]); | ||||||
| 	GetString(buffer, str); | 	GetString(buffer, str, lastof(buffer)); | ||||||
|  |  | ||||||
| 	br = GetStringBoundingBox(buffer); | 	br = GetStringBoundingBox(buffer); | ||||||
| 	br.width += 6; br.height += 4; // increase slightly to have some space around the box | 	br.width += 6; br.height += 4; // increase slightly to have some space around the box | ||||||
| @@ -1076,7 +1076,7 @@ void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth, | |||||||
|  |  | ||||||
| 	w = AllocateWindowDesc(&_query_string_desc); | 	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'; | 	_edit_str_buf[realmaxlen-1] = '\0'; | ||||||
|  |  | ||||||
| 	if (maxlen & 0x1000) { | 	if (maxlen & 0x1000) { | ||||||
| @@ -1311,7 +1311,7 @@ static void GenerateFileName(void) | |||||||
| 	SetDParam(0, p->name_1); | 	SetDParam(0, p->name_1); | ||||||
| 	SetDParam(1, p->name_2); | 	SetDParam(1, p->name_2); | ||||||
| 	SetDParam(2, _date); | 	SetDParam(2, _date); | ||||||
| 	GetString(_edit_str_buf, STR_4004); | 	GetString(_edit_str_buf, STR_4004, lastof(_edit_str_buf)); | ||||||
| } | } | ||||||
|  |  | ||||||
| extern void StartupEngines(void); | extern void StartupEngines(void); | ||||||
| @@ -1777,7 +1777,7 @@ static void CheatsWndProc(Window *w, WindowEvent *e) | |||||||
| 				/* Draw colored flag for change player cheat */ | 				/* Draw colored flag for change player cheat */ | ||||||
| 				case STR_CHEAT_CHANGE_PLAYER: | 				case STR_CHEAT_CHANGE_PLAYER: | ||||||
| 					SetDParam(0, val); | 					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); | 					DrawPlayerIcon(_current_player, 60 + GetStringBoundingBox(buf).width, y + 2); | ||||||
| 					break; | 					break; | ||||||
| 				/* Set correct string for switch climate cheat */ | 				/* Set correct string for switch climate cheat */ | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								network.c
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								network.c
									
									
									
									
									
								
							| @@ -131,54 +131,54 @@ void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send | |||||||
|  |  | ||||||
| 	switch (action) { | 	switch (action) { | ||||||
| 		case NETWORK_ACTION_JOIN: | 		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); | 			snprintf(message, sizeof(message), "*** %s %s", name, temp); | ||||||
| 			break; | 			break; | ||||||
| 		case NETWORK_ACTION_LEAVE: | 		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); | 			snprintf(message, sizeof(message), "*** %s %s (%s)", name, temp, buf); | ||||||
| 			break; | 			break; | ||||||
| 		case NETWORK_ACTION_GIVE_MONEY: | 		case NETWORK_ACTION_GIVE_MONEY: | ||||||
| 			if (self_send) { | 			if (self_send) { | ||||||
| 				SetDParamStr(0, name); | 				SetDParamStr(0, name); | ||||||
| 				SetDParam(1, atoi(buf)); | 				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); | 				snprintf(message, sizeof(message), "*** %s", temp); | ||||||
| 			} else { | 			} else { | ||||||
| 				SetDParam(0, atoi(buf)); | 				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); | 				snprintf(message, sizeof(message), "*** %s %s", name, temp); | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| 		case NETWORK_ACTION_CHAT_COMPANY: | 		case NETWORK_ACTION_CHAT_COMPANY: | ||||||
| 			if (self_send) { | 			if (self_send) { | ||||||
| 				SetDParamStr(0, name); | 				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); | 				snprintf(message, sizeof(message), "%s %s", temp, buf); | ||||||
| 			} else { | 			} else { | ||||||
| 				SetDParamStr(0, name); | 				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); | 				snprintf(message, sizeof(message), "%s %s", temp, buf); | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| 		case NETWORK_ACTION_CHAT_CLIENT: | 		case NETWORK_ACTION_CHAT_CLIENT: | ||||||
| 			if (self_send) { | 			if (self_send) { | ||||||
| 				SetDParamStr(0, name); | 				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); | 				snprintf(message, sizeof(message), "%s %s", temp, buf); | ||||||
| 			} else { | 			} else { | ||||||
| 				SetDParamStr(0, name); | 				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); | 				snprintf(message, sizeof(message), "%s %s", temp, buf); | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| 		case NETWORK_ACTION_NAME_CHANGE: | 		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); | 			snprintf(message, sizeof(message), "*** %s %s %s", name, temp, buf); | ||||||
| 			break; | 			break; | ||||||
| 		default: | 		default: | ||||||
| 			SetDParamStr(0, name); | 			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); | 			snprintf(message, sizeof(message), "%s %s", temp, buf); | ||||||
| 			break; | 			break; | ||||||
| 	} | 	} | ||||||
| @@ -260,7 +260,7 @@ static void NetworkClientError(NetworkRecvStatus res, NetworkClientState* cs) | |||||||
|  * @param buf buffer where the error message will be stored |  * @param buf buffer where the error message will be stored | ||||||
|  * @param err NetworkErrorCode |  * @param err NetworkErrorCode | ||||||
|  * @return returns a pointer to the error message (buf) */ |  * @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 | 	/* List of possible network errors, used by | ||||||
| 	 * PACKET_SERVER_ERROR and PACKET_CLIENT_ERROR */ | 	 * PACKET_SERVER_ERROR and PACKET_CLIENT_ERROR */ | ||||||
| @@ -283,7 +283,7 @@ char *GetNetworkErrorMsg(char *buf, NetworkErrorCode err) | |||||||
|  |  | ||||||
| 	if (err >= lengthof(network_error_strings)) err = 0; | 	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 */ | /* Count the number of active clients connected */ | ||||||
| @@ -599,7 +599,7 @@ void NetworkCloseClient(NetworkClientState *cs) | |||||||
|  |  | ||||||
| 		NetworkGetClientName(client_name, sizeof(client_name), 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); | 		NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -628,7 +628,7 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CHAT) | |||||||
| 				/* For speaking to player or give money, we need the player-name */ | 				/* 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 | 				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); | 				ci = NetworkFindClientInfoFromIndex(_network_own_client_index); | ||||||
| 				break; | 				break; | ||||||
| 			default: | 			default: | ||||||
| @@ -654,7 +654,7 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT) | |||||||
| 	NetworkClientInfo *ci; | 	NetworkClientInfo *ci; | ||||||
|  |  | ||||||
| 	index = NetworkRecv_uint16(MY_CLIENT, p); | 	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); | 	ci = NetworkFindClientInfoFromIndex(index); | ||||||
| 	if (ci != NULL) { | 	if (ci != NULL) { | ||||||
|   | |||||||
| @@ -230,7 +230,7 @@ NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index); | |||||||
| NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip); | NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip); | ||||||
| NetworkClientState *NetworkFindClientStateFromIndex(uint16 client_index); | NetworkClientState *NetworkFindClientStateFromIndex(uint16 client_index); | ||||||
| unsigned long NetworkResolveHost(const char *hostname); | 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 /* ENABLE_NETWORK */ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1181,36 +1181,36 @@ static Window *PopupClientList(Window *w, int client_no, int x, int y) | |||||||
|  |  | ||||||
| 	i = 0; | 	i = 0; | ||||||
| 	if (_network_own_client_index != ci->client_index) { | 	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; | 		_clientlist_proc[i++] = &ClientList_SpeakToClient; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (IsValidPlayer(ci->client_playas)) { | 	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; | 		_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; | 	_clientlist_proc[i++] = &ClientList_SpeakToAll; | ||||||
|  |  | ||||||
| 	if (_network_own_client_index != ci->client_index) { | 	if (_network_own_client_index != ci->client_index) { | ||||||
| 		/* We are no spectator and the player we want to give money to is no spectator */ | 		/* We are no spectator and the player we want to give money to is no spectator */ | ||||||
| 		if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas)) { | 		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; | 			_clientlist_proc[i++] = &ClientList_GiveMoney; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// A server can kick clients (but not himself) | 	// A server can kick clients (but not himself) | ||||||
| 	if (_network_server && _network_own_client_index != ci->client_index) { | 	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; | 		_clientlist_proc[i++] = &ClientList_Kick; | ||||||
|  |  | ||||||
| 		sprintf(_clientlist_action[i],"Ban"); | 		sprintf(_clientlist_action[i],"Ban"); // XXX GetString? | ||||||
| 		_clientlist_proc[i++] = &ClientList_Ban; | 		_clientlist_proc[i++] = &ClientList_Ban; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (i == 0) { | 	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; | 		_clientlist_proc[i++] = &ClientList_None; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -1511,7 +1511,7 @@ static const char *ChatTabCompletionNextItem(uint *item) | |||||||
| 		FOR_ALL_TOWNS_FROM(t, *item - MAX_CLIENT_INFO) { | 		FOR_ALL_TOWNS_FROM(t, *item - MAX_CLIENT_INFO) { | ||||||
| 			/* Get the town-name via the string-system */ | 			/* Get the town-name via the string-system */ | ||||||
| 			SetDParam(0, t->townnameparts); | 			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 &chat_tab_temp_buffer[0]; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ | |||||||
| #ifdef ENABLE_NETWORK | #ifdef ENABLE_NETWORK | ||||||
|  |  | ||||||
| #include "stdafx.h" | #include "stdafx.h" | ||||||
|  | #include "openttd.h" // XXX StringID | ||||||
| #include "debug.h" | #include "debug.h" | ||||||
| #include "string.h" | #include "string.h" | ||||||
| #include "strings.h" | #include "strings.h" | ||||||
| @@ -144,7 +145,7 @@ DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientState *cs, Netwo | |||||||
| 	NetworkSend_uint8(p, error); | 	NetworkSend_uint8(p, error); | ||||||
| 	NetworkSend_Packet(p, cs); | 	NetworkSend_Packet(p, cs); | ||||||
|  |  | ||||||
| 	GetNetworkErrorMsg(str, error); | 	GetNetworkErrorMsg(str, error, lastof(str)); | ||||||
|  |  | ||||||
| 	// Only send when the current client was in game | 	// Only send when the current client was in game | ||||||
| 	if (cs->status > STATUS_AUTH) { | 	if (cs->status > STATUS_AUTH) { | ||||||
| @@ -899,7 +900,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ERROR) | |||||||
|  |  | ||||||
| 	NetworkGetClientName(client_name, sizeof(client_name), cs); | 	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); | 	DEBUG(net, 2)("[NET] %s reported an error and is closing his connection (%s)", client_name, str); | ||||||
|  |  | ||||||
| @@ -1043,7 +1044,7 @@ void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest, | |||||||
| 		if (ci != NULL && show_local) { | 		if (ci != NULL && show_local) { | ||||||
| 			if (from_index == NETWORK_SERVER_INDEX) { | 			if (from_index == NETWORK_SERVER_INDEX) { | ||||||
| 				char name[NETWORK_NAME_LENGTH]; | 				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); | 				NetworkTextMessage(action, GetDrawStringPlayerColor(ci_own->client_playas), true, name, "%s", msg); | ||||||
| 			} else { | 			} else { | ||||||
| 				FOR_ALL_CLIENTS(cs) { | 				FOR_ALL_CLIENTS(cs) { | ||||||
| @@ -1211,7 +1212,7 @@ void NetworkPopulateCompanyInfo(void) | |||||||
| 		// Grap the company name | 		// Grap the company name | ||||||
| 		SetDParam(0, p->name_1); | 		SetDParam(0, p->name_1); | ||||||
| 		SetDParam(1, p->name_2); | 		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 | 		// Check the income | ||||||
| 		if (_cur_year - 1 == p->inaugurated_year) { | 		if (_cur_year - 1 == p->inaugurated_year) { | ||||||
|   | |||||||
| @@ -292,7 +292,7 @@ StringID GetGRFStringID(uint32 grfid, uint16 stringid) | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| char *GetGRFString(char *buff, uint16 stringid) | char *GetGRFString(char *buff, uint16 stringid, const char* last) | ||||||
| { | { | ||||||
| 	const GRFText *default_text = NULL; | 	const GRFText *default_text = NULL; | ||||||
| 	const GRFText *search_text; | 	const GRFText *search_text; | ||||||
| @@ -319,7 +319,7 @@ char *GetGRFString(char *buff, uint16 stringid) | |||||||
| 	if (default_text != NULL) return strecpy(buff, default_text->text, NULL); | 	if (default_text != NULL) return strecpy(buff, default_text->text, NULL); | ||||||
|  |  | ||||||
| 	/* Use the default string ID if the fallback string isn't available */ | 	/* 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); | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ | |||||||
|  |  | ||||||
| StringID AddGRFString(uint32 grfid, uint16 stringid, byte langid, bool new_scheme, const char *text_to_add, StringID def_string); | 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); | 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 CleanUpStrings(void); | ||||||
| void SetCurrentGrfLangID(const char *iso_name); | void SetCurrentGrfLangID(const char *iso_name); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -579,7 +579,7 @@ static void DrawNewsString(int x, int y, uint16 color, const NewsItem *ni, uint | |||||||
| 		str = ni->string_id; | 		str = ni->string_id; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	GetString(buffer, str); | 	GetString(buffer, str, lastof(buffer)); | ||||||
| 	/* Copy the just gotten string to another buffer to remove any formatting | 	/* Copy the just gotten string to another buffer to remove any formatting | ||||||
| 	 * from it such as big fonts, etc. */ | 	 * from it such as big fonts, etc. */ | ||||||
| 	for (ptr = buffer, dest = buffer2; *ptr != '\0'; ptr++) { | 	for (ptr = buffer, dest = buffer2; *ptr != '\0'; ptr++) { | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								openttd.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								openttd.c
									
									
									
									
									
								
							| @@ -17,6 +17,7 @@ | |||||||
| #include "functions.h" | #include "functions.h" | ||||||
| #include "mixer.h" | #include "mixer.h" | ||||||
| #include "spritecache.h" | #include "spritecache.h" | ||||||
|  | #include "strings.h" | ||||||
| #include "gfx.h" | #include "gfx.h" | ||||||
| #include "gfxinit.h" | #include "gfxinit.h" | ||||||
| #include "gui.h" | #include "gui.h" | ||||||
| @@ -878,16 +879,17 @@ static void DoAutosave(void) | |||||||
|  |  | ||||||
| 	if (_patches.keep_all_autosave && _local_player != PLAYER_SPECTATOR) { | 	if (_patches.keep_all_autosave && _local_player != PLAYER_SPECTATOR) { | ||||||
| 		const Player *p = GetPlayer(_local_player); | 		const Player *p = GetPlayer(_local_player); | ||||||
| 		char *s; | 		char* s = buf; | ||||||
| 		sprintf(buf, "%s%s", _path.autosave_dir, PATHSEP); |  | ||||||
|  | 		s += snprintf(buf, lengthof(buf), "%s%s", _path.autosave_dir, PATHSEP); | ||||||
|  |  | ||||||
| 		SetDParam(0, p->name_1); | 		SetDParam(0, p->name_1); | ||||||
| 		SetDParam(1, p->name_2); | 		SetDParam(1, p->name_2); | ||||||
| 		SetDParam(2, _date); | 		SetDParam(2, _date); | ||||||
| 		s = GetString(buf + strlen(_path.autosave_dir) + strlen(PATHSEP), STR_4004); | 		s = GetString(s, STR_4004, lastof(buf)); | ||||||
| 		strcpy(s, ".sav"); | 		strecpy(s, ".sav", lastof(buf)); | ||||||
| 	} else { /* generate a savegame name and number according to _patches.max_num_autosaves */ | 	} 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++; | 		_autosave_ctr++; | ||||||
| 		if (_autosave_ctr >= _patches.max_num_autosaves) { | 		if (_autosave_ctr >= _patches.max_num_autosaves) { | ||||||
|   | |||||||
| @@ -826,7 +826,7 @@ void BackupVehicleOrders(const Vehicle *v, BackuppedOrders *bak) | |||||||
| 	if (!IsCustomName(v->string_id)) { | 	if (!IsCustomName(v->string_id)) { | ||||||
| 		bak->name[0] = '\0'; | 		bak->name[0] = '\0'; | ||||||
| 	} else { | 	} 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 we have shared orders, store it on a special way */ | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								players.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								players.c
									
									
									
									
									
								
							| @@ -331,7 +331,7 @@ verify_name:; | |||||||
| 			if (pp->name_1 == str && pp->name_2 == strp) goto bad_town_name; | 			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) | 		if (strlen(buffer) >= 32 || GetStringBoundingBox(buffer).width >= 150) | ||||||
| 			goto bad_town_name; | 			goto bad_town_name; | ||||||
|  |  | ||||||
| @@ -438,14 +438,14 @@ restart:; | |||||||
| 		p->president_name_1 = SPECSTR_PRESIDENT_NAME; | 		p->president_name_1 = SPECSTR_PRESIDENT_NAME; | ||||||
|  |  | ||||||
| 		SetDParam(0, p->president_name_2); | 		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) | 		if (strlen(buffer) >= 32 || GetStringBoundingBox(buffer).width >= 94) | ||||||
| 			continue; | 			continue; | ||||||
|  |  | ||||||
| 		FOR_ALL_PLAYERS(pp) { | 		FOR_ALL_PLAYERS(pp) { | ||||||
| 			if (pp->is_active && p != pp) { | 			if (pp->is_active && p != pp) { | ||||||
| 				SetDParam(0, pp->president_name_2); | 				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) | 				if (strcmp(buffer2, buffer) == 0) | ||||||
| 					goto restart; | 					goto restart; | ||||||
| 			} | 			} | ||||||
| @@ -998,7 +998,7 @@ int8 SaveHighScoreValue(const Player *p) | |||||||
| 			SetDParam(1, p->president_name_2); | 			SetDParam(1, p->president_name_2); | ||||||
| 			SetDParam(2, p->name_1); | 			SetDParam(2, p->name_1); | ||||||
| 			SetDParam(3, p->name_2); | 			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].score = score; | ||||||
| 			hs[i].title = EndGameGetPerformanceTitleFromValue(score); | 			hs[i].title = EndGameGetPerformanceTitleFromValue(score); | ||||||
| 			return i; | 			return i; | ||||||
| @@ -1043,7 +1043,7 @@ int8 SaveHighScoreValueNetwork(void) | |||||||
| 			SetDParam(1, pl[i]->president_name_2); | 			SetDParam(1, pl[i]->president_name_2); | ||||||
| 			SetDParam(2, pl[i]->name_1); | 			SetDParam(2, pl[i]->name_1); | ||||||
| 			SetDParam(3, pl[i]->name_2); | 			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->score = pl[i]->old_economy[0].performance_history; | ||||||
| 			hs->title = EndGameGetPerformanceTitleFromValue(hs->score); | 			hs->title = EndGameGetPerformanceTitleFromValue(hs->score); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -504,7 +504,7 @@ static char *MakeScreenshotName(const char *ext) | |||||||
| 		SetDParam(0, p->name_1); | 		SetDParam(0, p->name_1); | ||||||
| 		SetDParam(1, p->name_2); | 		SetDParam(1, p->name_2); | ||||||
| 		SetDParam(2, _date); | 		SetDParam(2, _date); | ||||||
| 		GetString(_screenshot_name, STR_4004); | 		GetString(_screenshot_name, STR_4004, lastof(_screenshot_name)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	base = strchr(_screenshot_name, 0); | 	base = strchr(_screenshot_name, 0); | ||||||
|   | |||||||
| @@ -81,12 +81,12 @@ static int CDECL StationNameSorter(const void *a, const void *b) | |||||||
| 	int r; | 	int r; | ||||||
|  |  | ||||||
| 	SetDParam(0, st1->index); | 	SetDParam(0, st1->index); | ||||||
| 	GetString(buf1, STR_STATION); | 	GetString(buf1, STR_STATION, lastof(buf1)); | ||||||
|  |  | ||||||
| 	if (st2 != _last_station) { | 	if (st2 != _last_station) { | ||||||
| 		_last_station = st2; | 		_last_station = st2; | ||||||
| 		SetDParam(0, st2->index); | 		SetDParam(0, st2->index); | ||||||
| 		GetString(_bufcache, STR_STATION); | 		GetString(_bufcache, STR_STATION, lastof(_bufcache)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	r =  strcmp(buf1, _bufcache); // sort by name | 	r =  strcmp(buf1, _bufcache); // sort by name | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								string.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								string.c
									
									
									
									
									
								
							| @@ -1,6 +1,8 @@ | |||||||
| /* $Id$ */ | /* $Id$ */ | ||||||
|  |  | ||||||
| #include "stdafx.h" | #include "stdafx.h" | ||||||
|  | #include "openttd.h" | ||||||
|  | #include "functions.h" | ||||||
| #include "string.h" | #include "string.h" | ||||||
|  |  | ||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
| @@ -26,7 +28,7 @@ void ttd_strlcpy(char *dst, const char *src, size_t size) | |||||||
|  |  | ||||||
| char* strecat(char* dst, const char* src, const char* last) | char* strecat(char* dst, const char* src, const char* last) | ||||||
| { | { | ||||||
| 	assert(last == NULL || dst <= last); | 	assert(dst <= last); | ||||||
| 	for (; *dst != '\0'; ++dst) | 	for (; *dst != '\0'; ++dst) | ||||||
| 		if (dst == last) return dst; | 		if (dst == last) return dst; | ||||||
| 	for (; *src != '\0' && dst != last; ++dst, ++src) *dst = *src; | 	for (; *src != '\0' && dst != last; ++dst, ++src) *dst = *src; | ||||||
| @@ -37,9 +39,14 @@ char* strecat(char* dst, const char* src, const char* last) | |||||||
|  |  | ||||||
| char* strecpy(char* dst, const char* src, const char* 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; | 	for (; *src != '\0' && dst != last; ++dst, ++src) *dst = *src; | ||||||
| 	*dst = '\0'; | 	*dst = '\0'; | ||||||
|  | #if 0 | ||||||
|  | 	if (dst == last && *src != '\0') { | ||||||
|  | 		error("String too long for destination buffer"); | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
| 	return dst; | 	return dst; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										269
									
								
								strings.c
									
									
									
									
									
								
							
							
						
						
									
										269
									
								
								strings.c
									
									
									
									
									
								
							| @@ -31,11 +31,11 @@ | |||||||
|  |  | ||||||
| char _userstring[128]; | char _userstring[128]; | ||||||
|  |  | ||||||
| static char *StationGetSpecialString(char *buff, int x); | static char *StationGetSpecialString(char *buff, int x, const char* last); | ||||||
| static char *GetSpecialTownNameString(char *buff, int ind, uint32 seed); | static char *GetSpecialTownNameString(char *buff, int ind, uint32 seed, const char* last); | ||||||
| static char *GetSpecialPlayerNameString(char *buff, int ind, const int32 *argv); | 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 { | typedef struct LanguagePack { | ||||||
| 	uint32 ident; | 	uint32 ident; | ||||||
| @@ -166,7 +166,7 @@ static const char *GetStringPtr(StringID string) | |||||||
| // These 8 bits will only be set when FormatString wants to print | // These 8 bits will only be set when FormatString wants to print | ||||||
| // the string in a different case. No one else except FormatString | // the string in a different case. No one else except FormatString | ||||||
| // should set those bits, therefore string CANNOT be StringID, but uint32. | // 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 index = GB(string,  0, 11); | ||||||
| 	uint tab   = GB(string, 11,  5); | 	uint tab   = GB(string, 11,  5); | ||||||
| @@ -177,46 +177,46 @@ static char *GetStringWithArgs(char *buffr, uint string, const int32 *argv) | |||||||
| 	switch (tab) { | 	switch (tab) { | ||||||
| 		case 4: | 		case 4: | ||||||
| 			if (index >= 0xC0) | 			if (index >= 0xC0) | ||||||
| 				return GetSpecialTownNameString(buffr, index - 0xC0, GetInt32(&argv)); | 				return GetSpecialTownNameString(buffr, index - 0xC0, GetInt32(&argv), last); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case 14: | 		case 14: | ||||||
| 			if (index >= 0xE4) | 			if (index >= 0xE4) | ||||||
| 				return GetSpecialPlayerNameString(buffr, index - 0xE4, argv); | 				return GetSpecialPlayerNameString(buffr, index - 0xE4, argv, last); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		// User defined name | 		// User defined name | ||||||
| 		case 15: | 		case 15: | ||||||
| 			return GetName(index, buffr); | 			return GetName(buffr, index, last); | ||||||
|  |  | ||||||
| 		case 26: | 		case 26: | ||||||
| 			/* Include string within newgrf text (format code 81) */ | 			/* Include string within newgrf text (format code 81) */ | ||||||
| 			if (HASBIT(index, 10)) { | 			if (HASBIT(index, 10)) { | ||||||
| 				StringID string = GetGRFStringID(0, 0xD000 + GB(index, 0, 10)); | 				StringID string = GetGRFStringID(0, 0xD000 + GB(index, 0, 10)); | ||||||
| 				return GetStringWithArgs(buffr, string, argv); | 				return GetStringWithArgs(buffr, string, argv, last); | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case 28: | 		case 28: | ||||||
| 			GetGRFString(buff, index); | 			GetGRFString(buff, index, last); | ||||||
| 			return FormatString(buffr, buff, argv, 0); | 			return FormatString(buffr, buff, argv, 0, last); | ||||||
|  |  | ||||||
| 		case 29: | 		case 29: | ||||||
| 			GetGRFString(buff, index + 0x800); | 			GetGRFString(buff, index + 0x800, last); | ||||||
| 			return FormatString(buffr, buff, argv, 0); | 			return FormatString(buffr, buff, argv, 0, last); | ||||||
|  |  | ||||||
| 		case 30: | 		case 30: | ||||||
| 			GetGRFString(buff, index + 0x1000); | 			GetGRFString(buff, index + 0x1000, last); | ||||||
| 			return FormatString(buffr, buff, argv, 0); | 			return FormatString(buffr, buff, argv, 0, last); | ||||||
|  |  | ||||||
| 		case 31: | 		case 31: | ||||||
| 			// dynamic strings. These are NOT to be passed through the formatter, | 			// dynamic strings. These are NOT to be passed through the formatter, | ||||||
| 			// but passed through verbatim. | 			// but passed through verbatim. | ||||||
| 			if (index < (STR_SPEC_USERSTRING & 0x7FF)) { | 			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]) { | 	if (index >= _langtab_num[tab]) { | ||||||
| @@ -226,12 +226,12 @@ static char *GetStringWithArgs(char *buffr, uint string, const int32 *argv) | |||||||
| 		); | 		); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	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); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -270,7 +270,8 @@ static const uint32 _divisor_table[] = { | |||||||
| 	1 | 	1 | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static char *FormatCommaNumber(char *buff, int32 number) | // TODO | ||||||
|  | static char *FormatCommaNumber(char *buff, int32 number, const char* last) | ||||||
| { | { | ||||||
| 	uint32 quot,divisor; | 	uint32 quot,divisor; | ||||||
| 	int i; | 	int i; | ||||||
| @@ -303,7 +304,8 @@ static char *FormatCommaNumber(char *buff, int32 number) | |||||||
| 	return buff; | 	return buff; | ||||||
| } | } | ||||||
|  |  | ||||||
| static char *FormatNoCommaNumber(char *buff, int32 number) | // TODO | ||||||
|  | static char *FormatNoCommaNumber(char *buff, int32 number, const char* last) | ||||||
| { | { | ||||||
| 	uint32 quot,divisor; | 	uint32 quot,divisor; | ||||||
| 	int i; | 	int i; | ||||||
| @@ -311,7 +313,7 @@ static char *FormatNoCommaNumber(char *buff, int32 number) | |||||||
| 	uint32 num; | 	uint32 num; | ||||||
|  |  | ||||||
| 	if (number < 0) { | 	if (number < 0) { | ||||||
| 		*buff++ = '-'; | 		buff = strecpy(buff, "-", last); | ||||||
| 		number = -number; | 		number = -number; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -336,50 +338,50 @@ static char *FormatNoCommaNumber(char *buff, int32 number) | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| static char *FormatYmdString(char *buff, Date date) | static char *FormatYmdString(char *buff, Date date, const char* last) | ||||||
| { | { | ||||||
| 	const char *src; |  | ||||||
| 	YearMonthDay ymd; | 	YearMonthDay ymd; | ||||||
|  |  | ||||||
| 	ConvertDateToYMD(date, &ymd); | 	ConvertDateToYMD(date, &ymd); | ||||||
|  |  | ||||||
| 	for (src = GetStringPtr(ymd.day + STR_01AC_1ST - 1); (*buff++ = *src++) != '\0';) {} | 	buff = strecpy(buff, GetStringPtr(ymd.day + STR_01AC_1ST - 1), last); | ||||||
| 	buff[-1] = ' '; | 	buff = strecpy(buff, " ", last); | ||||||
|  | 	buff = strecpy(buff, GetStringPtr(STR_0162_JAN + ymd.month), last); | ||||||
|  | 	buff = strecpy(buff, " ", last); | ||||||
|  |  | ||||||
| 	for (src = GetStringPtr(STR_0162_JAN + ymd.month); (*buff++ = *src++) != '\0';) {} | 	return FormatNoCommaNumber(buff, ymd.year, last); | ||||||
| 	buff[-1] = ' '; |  | ||||||
|  |  | ||||||
| 	return FormatNoCommaNumber(buff, ymd.year); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static char *FormatMonthAndYear(char *buff, Date date) | static char *FormatMonthAndYear(char *buff, Date date, const char* last) | ||||||
| { | { | ||||||
| 	const char *src; |  | ||||||
| 	YearMonthDay ymd; | 	YearMonthDay ymd; | ||||||
|  |  | ||||||
| 	ConvertDateToYMD(date, &ymd); | 	ConvertDateToYMD(date, &ymd); | ||||||
|  |  | ||||||
| 	for (src = GetStringPtr(STR_MONTH_JAN + ymd.month); (*buff++ = *src++) != '\0';) {} | 	buff = strecpy(buff, GetStringPtr(STR_MONTH_JAN + ymd.month), last); | ||||||
| 	buff[-1] = ' '; | 	buff = strecpy(buff, " ", last); | ||||||
|  |  | ||||||
| 	return FormatNoCommaNumber(buff, ymd.year); | 	return FormatNoCommaNumber(buff, ymd.year, last); | ||||||
| } | } | ||||||
|  |  | ||||||
| static char *FormatTinyDate(char *buff, Date date) | static char *FormatTinyDate(char *buff, Date date, const char* last) | ||||||
| { | { | ||||||
| 	YearMonthDay ymd; | 	YearMonthDay ymd; | ||||||
|  |  | ||||||
| 	ConvertDateToYMD(date, &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; | 	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; | 	const char* multiplier = ""; | ||||||
| 	char c; | 	char buf[40]; | ||||||
| 	char buf[40], *p; | 	char* p; | ||||||
| 	int j; | 	int j; | ||||||
|  |  | ||||||
| 	// multiply by exchange rate | 	// multiply by exchange rate | ||||||
| @@ -387,51 +389,45 @@ static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, int64 n | |||||||
|  |  | ||||||
| 	// convert from negative | 	// convert from negative | ||||||
| 	if (number < 0) { | 	if (number < 0) { | ||||||
| 		*buff++ = '-'; | 		buff = strecpy(buff, "-", last); | ||||||
| 		number = -number; | 		number = -number; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Add prefix part, folowing symbol_pos specification. | 	/* Add prefix part, folowing symbol_pos specification. | ||||||
| 	 * Here, it can can be either 0 (prefix) or 2 (both prefix anf suffix). | 	 * 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 */ | 	 * The only remaining value is 1 (suffix), so everything that is not 1 */ | ||||||
| 	if (spec->symbol_pos != 1){ | 	if (spec->symbol_pos != 1) buff = strecpy(buff, spec->prefix, last); | ||||||
| 		s = spec->prefix; |  | ||||||
| 		while (s != spec->prefix + lengthof(spec->prefix) && (c = *(s++)) != '\0') *(buff)++ = c; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// for huge numbers, compact the number into k or M | 	// for huge numbers, compact the number into k or M | ||||||
| 	if (compact) { | 	if (compact) { | ||||||
| 		compact = 0; |  | ||||||
| 		if (number >= 1000000000) { | 		if (number >= 1000000000) { | ||||||
| 			number = (number + 500000) / 1000000; | 			number = (number + 500000) / 1000000; | ||||||
| 			compact = 'M'; | 			multiplier = "M"; | ||||||
| 		} else if (number >= 1000000) { | 		} else if (number >= 1000000) { | ||||||
| 			number = (number + 500) / 1000; | 			number = (number + 500) / 1000; | ||||||
| 			compact = 'k'; | 			multiplier = "k"; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// convert to ascii number and add commas | 	// convert to ascii number and add commas | ||||||
| 	p = buf; | 	p = endof(buf); | ||||||
|  | 	*--p = '\0'; | ||||||
| 	j = 4; | 	j = 4; | ||||||
| 	do { | 	do { | ||||||
| 		if (--j == 0) { | 		if (--j == 0) { | ||||||
| 			*p++ = spec->separator; | 			*--p = spec->separator; | ||||||
| 			j = 3; | 			j = 3; | ||||||
| 		} | 		} | ||||||
| 		*p++ = '0' + number % 10; | 		*--p = '0' + number % 10; | ||||||
| 	} while (number /= 10); | 	} while ((number /= 10) != 0); | ||||||
| 	do *buff++ = *--p; while (p != buf); | 	buff = strecpy(buff, p, last); | ||||||
|  |  | ||||||
| 	if (compact) *buff++ = compact; | 	buff = strecpy(buff, multiplier, last); | ||||||
|  |  | ||||||
| 	/* Add suffix part, folowing symbol_pos specification. | 	/* Add suffix part, folowing symbol_pos specification. | ||||||
| 	 * Here, it can can be either 1 (suffix) or 2 (both prefix anf suffix). | 	 * 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 */ | 	 * The only remaining value is 1 (prefix), so everything that is not 0 */ | ||||||
| 	if (spec->symbol_pos != 0) { | 	if (spec->symbol_pos != 0) buff = strecpy(buff, spec->suffix, last); | ||||||
| 		s = spec->suffix; |  | ||||||
| 		while (s != spec->suffix + lengthof(spec->suffix) && (c = *(s++)) != '\0') *(buff++) = c; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return buff; | 	return buff; | ||||||
| } | } | ||||||
| @@ -564,7 +560,7 @@ static const Units units[] = { | |||||||
| 	}, | 	}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| 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[]; | 	extern const char _openttd_revision[]; | ||||||
| 	byte b; | 	byte b; | ||||||
| @@ -574,30 +570,34 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 	while ((b = *str++) != '\0') { | 	while ((b = *str++) != '\0') { | ||||||
| 		switch (b) { | 		switch (b) { | ||||||
| 		case 0x1: // {SETX} | 		case 0x1: // {SETX} | ||||||
|  | 			if (buff != last && buff + 1 != last) { | ||||||
| 				*buff++ = b; | 				*buff++ = b; | ||||||
| 				*buff++ = *str++; | 				*buff++ = *str++; | ||||||
|  | 			} | ||||||
| 			break; | 			break; | ||||||
| 		case 0x2: // {SETXY} | 		case 0x2: // {SETXY} | ||||||
|  | 			if (buff != last && buff + 1 != last && buff + 2 != last) { | ||||||
| 				*buff++ = b; | 				*buff++ = b; | ||||||
| 				*buff++ = *str++; | 				*buff++ = *str++; | ||||||
| 				*buff++ = *str++; | 				*buff++ = *str++; | ||||||
|  | 			} | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case 0x81: // {STRINL} | 		case 0x81: // {STRINL} | ||||||
| 			buff = GetStringWithArgs(buff, ReadLE16Unaligned(str), argv); | 			buff = GetStringWithArgs(buff, ReadLE16Unaligned(str), argv, last); | ||||||
| 			str += 2; | 			str += 2; | ||||||
| 			break; | 			break; | ||||||
| 		case 0x82: // {DATE_LONG} | 		case 0x82: // {DATE_LONG} | ||||||
| 			buff = FormatYmdString(buff, GetInt32(&argv)); | 			buff = FormatYmdString(buff, GetInt32(&argv), last); | ||||||
| 			break; | 			break; | ||||||
| 		case 0x83: // {DATE_SHORT} | 		case 0x83: // {DATE_SHORT} | ||||||
| 			buff = FormatMonthAndYear(buff, GetInt32(&argv)); | 			buff = FormatMonthAndYear(buff, GetInt32(&argv), last); | ||||||
| 			break; | 			break; | ||||||
| 		case 0x84: {// {VELOCITY} | 		case 0x84: {// {VELOCITY} | ||||||
| 			int32 args[1]; | 			int32 args[1]; | ||||||
| 			assert(_opt_ptr->units < lengthof(units)); | 			assert(_opt_ptr->units < lengthof(units)); | ||||||
| 			args[0] = GetInt32(&argv) * units[_opt_ptr->units].s_m >> units[_opt_ptr->units].s_s; | 			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; | 			modifier = 0; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @@ -605,10 +605,10 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 		case 0x85: | 		case 0x85: | ||||||
| 			switch (*str++) { | 			switch (*str++) { | ||||||
| 			case 0: /* {CURRCOMPACT} */ | 			case 0: /* {CURRCOMPACT} */ | ||||||
| 				buff = FormatGenericCurrency(buff, _currency, GetInt32(&argv), true); | 				buff = FormatGenericCurrency(buff, _currency, GetInt32(&argv), true, last); | ||||||
| 				break; | 				break; | ||||||
| 			case 2: /* {REV} */ | 			case 2: /* {REV} */ | ||||||
| 				buff = strecpy(buff, _openttd_revision, NULL); | 				buff = strecpy(buff, _openttd_revision, last); | ||||||
| 				break; | 				break; | ||||||
| 			case 3: { /* {SHORTCARGO} */ | 			case 3: { /* {SHORTCARGO} */ | ||||||
| 				// Short description of cargotypes. Layout: | 				// Short description of cargotypes. Layout: | ||||||
| @@ -620,7 +620,7 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 						int32 args[1]; | 						int32 args[1]; | ||||||
| 						assert(_opt_ptr->units < lengthof(units)); | 						assert(_opt_ptr->units < lengthof(units)); | ||||||
| 						args[0] = GetInt32(&argv) * units[_opt_ptr->units].w_m >> units[_opt_ptr->units].w_s; | 						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; | 						modifier = 0; | ||||||
| 						break; | 						break; | ||||||
| 					} | 					} | ||||||
| @@ -629,61 +629,61 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 						int32 args[1]; | 						int32 args[1]; | ||||||
| 						assert(_opt_ptr->units < lengthof(units)); | 						assert(_opt_ptr->units < lengthof(units)); | ||||||
| 						args[0] = GetInt32(&argv) * units[_opt_ptr->units].v_m >> units[_opt_ptr->units].v_s; | 						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; | 						modifier = 0; | ||||||
| 						break; | 						break; | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 					default: | 					default: | ||||||
| 						buff = FormatCommaNumber(buff, GetInt32(&argv)); | 						buff = FormatCommaNumber(buff, GetInt32(&argv), last); | ||||||
| 						buff = strecpy(buff, " ", NULL); | 						buff = strecpy(buff, " ", last); | ||||||
| 						buff = strecpy(buff, GetStringPtr(cargo_str), NULL); | 						buff = strecpy(buff, GetStringPtr(cargo_str), last); | ||||||
| 						break; | 						break; | ||||||
| 				} | 				} | ||||||
| 			} break; | 			} break; | ||||||
| 			case 4: {/* {CURRCOMPACT64} */ | 			case 4: {/* {CURRCOMPACT64} */ | ||||||
| 				// 64 bit compact currency-unit | 				// 64 bit compact currency-unit | ||||||
| 				buff = FormatGenericCurrency(buff, _currency, GetInt64(&argv), true); | 				buff = FormatGenericCurrency(buff, _currency, GetInt64(&argv), true, last); | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 			case 5: { /* {STRING1} */ | 			case 5: { /* {STRING1} */ | ||||||
| 				// String that consumes ONE argument | 				// String that consumes ONE argument | ||||||
| 				uint str = modifier + GetInt32(&argv); | 				uint str = modifier + GetInt32(&argv); | ||||||
| 				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 1)); | 				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 1), last); | ||||||
| 				modifier = 0; | 				modifier = 0; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 			case 6: { /* {STRING2} */ | 			case 6: { /* {STRING2} */ | ||||||
| 				// String that consumes TWO arguments | 				// String that consumes TWO arguments | ||||||
| 				uint str = modifier + GetInt32(&argv); | 				uint str = modifier + GetInt32(&argv); | ||||||
| 				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 2)); | 				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 2), last); | ||||||
| 				modifier = 0; | 				modifier = 0; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 			case 7: { /* {STRING3} */ | 			case 7: { /* {STRING3} */ | ||||||
| 				// String that consumes THREE arguments | 				// String that consumes THREE arguments | ||||||
| 				uint str = modifier + GetInt32(&argv); | 				uint str = modifier + GetInt32(&argv); | ||||||
| 				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 3)); | 				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 3), last); | ||||||
| 				modifier = 0; | 				modifier = 0; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 			case 8: { /* {STRING4} */ | 			case 8: { /* {STRING4} */ | ||||||
| 				// String that consumes FOUR arguments | 				// String that consumes FOUR arguments | ||||||
| 				uint str = modifier + GetInt32(&argv); | 				uint str = modifier + GetInt32(&argv); | ||||||
| 				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 4)); | 				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 4), last); | ||||||
| 				modifier = 0; | 				modifier = 0; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 			case 9: { /* {STRING5} */ | 			case 9: { /* {STRING5} */ | ||||||
| 				// String that consumes FIVE arguments | 				// String that consumes FIVE arguments | ||||||
| 				uint str = modifier + GetInt32(&argv); | 				uint str = modifier + GetInt32(&argv); | ||||||
| 				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 5)); | 				buff = GetStringWithArgs(buff, str, GetArgvPtr(&argv, 5), last); | ||||||
| 				modifier = 0; | 				modifier = 0; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			case 10: { /* {STATIONFEATURES} */ | 			case 10: { /* {STATIONFEATURES} */ | ||||||
| 				buff = StationGetSpecialString(buff, GetInt32(&argv)); | 				buff = StationGetSpecialString(buff, GetInt32(&argv), last); | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| @@ -698,7 +698,7 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 				// The string STR_INDUSTRY_PATTERN controls the formatting | 				// The string STR_INDUSTRY_PATTERN controls the formatting | ||||||
| 				args[0] = i->town->index; | 				args[0] = i->town->index; | ||||||
| 				args[1] = i->type + STR_4802_COAL_MINE; | 				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; | 				modifier = 0; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| @@ -707,7 +707,7 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 				int32 args[1]; | 				int32 args[1]; | ||||||
| 				assert(_opt_ptr->units < lengthof(units)); | 				assert(_opt_ptr->units < lengthof(units)); | ||||||
| 				args[0] = GetInt32(&argv) * units[_opt_ptr->units].v_m >> units[_opt_ptr->units].v_s; | 				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; | 				modifier = 0; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| @@ -723,7 +723,7 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			case 14: { // {DATE_TINY} | 			case 14: { // {DATE_TINY} | ||||||
| 				buff = FormatTinyDate(buff, GetInt32(&argv)); | 				buff = FormatTinyDate(buff, GetInt32(&argv), last); | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| @@ -733,7 +733,7 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 				//   16-bit - cargo count | 				//   16-bit - cargo count | ||||||
| 				CargoID cargo = GetInt32(&argv); | 				CargoID cargo = GetInt32(&argv); | ||||||
| 				StringID cargo_str = (cargo == CT_INVALID) ? STR_8838_N_A : _cargoc.names_long[cargo]; | 				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; | 				break; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| @@ -741,7 +741,7 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 				int32 args[1]; | 				int32 args[1]; | ||||||
| 				assert(_opt_ptr->units < lengthof(units)); | 				assert(_opt_ptr->units < lengthof(units)); | ||||||
| 				args[0] = GetInt32(&argv) * units[_opt_ptr->units].p_m >> units[_opt_ptr->units].p_s; | 				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; | 				modifier = 0; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| @@ -750,7 +750,7 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 				int32 args[1]; | 				int32 args[1]; | ||||||
| 				assert(_opt_ptr->units < lengthof(units)); | 				assert(_opt_ptr->units < lengthof(units)); | ||||||
| 				args[0] = GetInt32(&argv) * units[_opt_ptr->units].v_m >> units[_opt_ptr->units].v_s; | 				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; | 				modifier = 0; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| @@ -759,7 +759,7 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 				int32 args[1]; | 				int32 args[1]; | ||||||
| 				assert(_opt_ptr->units < lengthof(units)); | 				assert(_opt_ptr->units < lengthof(units)); | ||||||
| 				args[0] = GetInt32(&argv) * units[_opt_ptr->units].w_m >> units[_opt_ptr->units].w_s; | 				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; | 				modifier = 0; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| @@ -768,7 +768,7 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 				int32 args[1]; | 				int32 args[1]; | ||||||
| 				assert(_opt_ptr->units < lengthof(units)); | 				assert(_opt_ptr->units < lengthof(units)); | ||||||
| 				args[0] = GetInt32(&argv) * units[_opt_ptr->units].w_m >> units[_opt_ptr->units].w_s; | 				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; | 				modifier = 0; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| @@ -777,7 +777,7 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 				int32 args[1]; | 				int32 args[1]; | ||||||
| 				assert(_opt_ptr->units < lengthof(units)); | 				assert(_opt_ptr->units < lengthof(units)); | ||||||
| 				args[0] = GetInt32(&argv) * units[_opt_ptr->units].f_m >> units[_opt_ptr->units].f_s; | 				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; | 				modifier = 0; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| @@ -802,13 +802,13 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 			// WARNING. It's prohibited for the included string to consume any arguments. | 			// WARNING. It's prohibited for the included string to consume any arguments. | ||||||
| 			// For included strings that consume argument, you should use STRING1, STRING2 etc. | 			// 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 | 			// 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; | 			modifier = 0; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		case 0x8B: // {COMMA} | 		case 0x8B: // {COMMA} | ||||||
| 			buff = FormatCommaNumber(buff, GetInt32(&argv)); | 			buff = FormatCommaNumber(buff, GetInt32(&argv), last); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case 0x8C: // Move argument pointer | 		case 0x8C: // Move argument pointer | ||||||
| @@ -824,11 +824,11 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		case 0x8E: // {NUM} | 		case 0x8E: // {NUM} | ||||||
| 			buff = FormatNoCommaNumber(buff, GetInt32(&argv)); | 			buff = FormatNoCommaNumber(buff, GetInt32(&argv), last); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case 0x8F: // {CURRENCY} | 		case 0x8F: // {CURRENCY} | ||||||
| 			buff = FormatGenericCurrency(buff, _currency, GetInt32(&argv), false); | 			buff = FormatGenericCurrency(buff, _currency, GetInt32(&argv), false, last); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case 0x99: { // {WAYPOINT} | 		case 0x99: { // {WAYPOINT} | ||||||
| @@ -842,20 +842,20 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 				temp[1] = wp->town_cn + 1; | 				temp[1] = wp->town_cn + 1; | ||||||
| 				str = wp->town_cn == 0 ? STR_WAYPOINTNAME_CITY : STR_WAYPOINTNAME_CITY_SERIAL; | 				str = wp->town_cn == 0 ? STR_WAYPOINTNAME_CITY : STR_WAYPOINTNAME_CITY_SERIAL; | ||||||
| 			} | 			} | ||||||
| 			buff = GetStringWithArgs(buff, str, temp); | 			buff = GetStringWithArgs(buff, str, temp, last); | ||||||
| 		} break; | 		} break; | ||||||
|  |  | ||||||
| 		case 0x9A: { // {STATION} | 		case 0x9A: { // {STATION} | ||||||
| 			const Station* st = GetStation(GetInt32(&argv)); | 			const Station* st = GetStation(GetInt32(&argv)); | ||||||
| 			int32 temp[2]; |  | ||||||
|  |  | ||||||
| 			if (!IsValidStation(st)) { // station doesn't exist anymore | 			if (!IsValidStation(st)) { // station doesn't exist anymore | ||||||
| 				buff = GetStringWithArgs(buff, STR_UNKNOWN_DESTINATION, NULL); | 				buff = GetStringWithArgs(buff, STR_UNKNOWN_DESTINATION, NULL, last); | ||||||
| 				break; | 			} else { | ||||||
| 			} | 				int32 temp[2]; | ||||||
| 				temp[0] = st->town->townnametype; | 				temp[0] = st->town->townnametype; | ||||||
| 				temp[1] = st->town->townnameparts; | 				temp[1] = st->town->townnameparts; | ||||||
| 			buff = GetStringWithArgs(buff, st->string_id, temp); | 				buff = GetStringWithArgs(buff, st->string_id, temp, last); | ||||||
|  | 			} | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		case 0x9B: { // {TOWN} | 		case 0x9B: { // {TOWN} | ||||||
| @@ -865,12 +865,12 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 			assert(IsValidTown(t)); | 			assert(IsValidTown(t)); | ||||||
|  |  | ||||||
| 			temp[0] = t->townnameparts; | 			temp[0] = t->townnameparts; | ||||||
| 			buff = GetStringWithArgs(buff, t->townnametype, temp); | 			buff = GetStringWithArgs(buff, t->townnametype, temp, last); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		case 0x9C: { // {CURRENCY64} | 		case 0x9C: { // {CURRENCY64} | ||||||
| 			buff = FormatGenericCurrency(buff, _currency, GetInt64(&argv), false); | 			buff = FormatGenericCurrency(buff, _currency, GetInt64(&argv), false, last); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -899,7 +899,7 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		default: | 		default: | ||||||
| 			*buff++ = b; | 			if (buff != last) *buff++ = b; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	*buff = '\0'; | 	*buff = '\0'; | ||||||
| @@ -907,23 +907,22 @@ static char *FormatString(char *buff, const char *str, const int32 *argv, uint c | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| static char *StationGetSpecialString(char *buff, int x) | static char *StationGetSpecialString(char *buff, int x, const char* last) | ||||||
| { | { | ||||||
| 	if (x & 0x01) *buff++ = '\x94'; | 	if (x & 0x01) buff = strecpy(buff, "\x94", last); | ||||||
| 	if (x & 0x02) *buff++ = '\x95'; | 	if (x & 0x02) buff = strecpy(buff, "\x95", last); | ||||||
| 	if (x & 0x04) *buff++ = '\x96'; | 	if (x & 0x04) buff = strecpy(buff, "\x96", last); | ||||||
| 	if (x & 0x08) *buff++ = '\x97'; | 	if (x & 0x08) buff = strecpy(buff, "\x97", last); | ||||||
| 	if (x & 0x10) *buff++ = '\x98'; | 	if (x & 0x10) buff = strecpy(buff, "\x98", last); | ||||||
| 	*buff = '\0'; |  | ||||||
| 	return buff; | 	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++; | 	_town_name_generators[ind](name, seed); // TODO | ||||||
| 	return buff; | 	return strecpy(buff, name, last); | ||||||
| } | } | ||||||
|  |  | ||||||
| static const char* const _silly_company_names[] = { | static const char* const _silly_company_names[] = { | ||||||
| @@ -994,7 +993,7 @@ static const char _initial_name_letters[] = { | |||||||
| 	'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W', | 	'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; | 	const char* const* base; | ||||||
| 	uint num; | 	uint num; | ||||||
| @@ -1007,29 +1006,26 @@ static char *GenAndCoName(char *buff, uint32 arg) | |||||||
| 		num  = lengthof(_surname_list); | 		num  = lengthof(_surname_list); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	buff = strecpy(buff, base[num * GB(arg, 16, 8) >> 8], NULL); | 	buff = strecpy(buff, base[num * GB(arg, 16, 8) >> 8], last); | ||||||
| 	buff = strecpy(buff, " & Co.", NULL); | 	buff = strecpy(buff, " & Co.", last); | ||||||
|  |  | ||||||
| 	return buff; | 	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; | 	const char* const* base; | ||||||
| 	uint num; | 	uint num; | ||||||
| 	uint i; | 	uint i; | ||||||
|  |  | ||||||
| 	buff[0] = _initial_name_letters[sizeof(_initial_name_letters) * GB(x, 0, 8) >> 8]; | 	initial[0] = _initial_name_letters[sizeof(_initial_name_letters) * GB(x, 0, 8) >> 8]; | ||||||
| 	buff[1] = '.'; | 	buff = strecpy(buff, initial, last); | ||||||
| 	buff[2] = ' '; // Insert a space after initial and period "I. Firstname" instead of "I.Firstname" |  | ||||||
| 	buff += 3; |  | ||||||
|  |  | ||||||
| 	i = (sizeof(_initial_name_letters) + 35) * GB(x, 8, 8) >> 8; | 	i = (sizeof(_initial_name_letters) + 35) * GB(x, 8, 8) >> 8; | ||||||
| 	if (i < sizeof(_initial_name_letters)) { | 	if (i < sizeof(_initial_name_letters)) { | ||||||
| 		buff[0] = _initial_name_letters[i]; | 		initial[0] = _initial_name_letters[i]; | ||||||
| 		buff[1] = '.'; | 		buff = strecpy(buff, initial, last); | ||||||
| 		buff[2] = ' '; // Insert a space after initial and period "I. J. Firstname" instead of "I.J.Firstname" |  | ||||||
| 		buff += 3; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (_opt_ptr->landscape == LT_CANDY) { | 	if (_opt_ptr->landscape == LT_CANDY) { | ||||||
| @@ -1040,50 +1036,53 @@ static char *GenPresidentName(char *buff, uint32 x) | |||||||
| 		num  = lengthof(_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; | 	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) { | 	switch (ind) { | ||||||
| 		case 1: // not used | 		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 | 		case 2: // used for Foobar & Co company names | ||||||
| 			return GenAndCoName(buff, GetInt32(&argv)); | 			return GenAndCoName(buff, GetInt32(&argv), last); | ||||||
|  |  | ||||||
| 		case 3: // President name | 		case 3: // President name | ||||||
| 			return GenPresidentName(buff, GetInt32(&argv)); | 			return GenPresidentName(buff, GetInt32(&argv), last); | ||||||
|  |  | ||||||
| 		case 4: // song names | 		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? | 	// town name? | ||||||
| 	if (IS_INT_INSIDE(ind - 6, 0, SPECSTR_TOWNNAME_LAST-SPECSTR_TOWNNAME_START + 1)) { | 	if (IS_INT_INSIDE(ind - 6, 0, SPECSTR_TOWNNAME_LAST-SPECSTR_TOWNNAME_START + 1)) { | ||||||
| 		buff = GetSpecialTownNameString(buff, ind - 6, GetInt32(&argv)); | 		buff = GetSpecialTownNameString(buff, ind - 6, GetInt32(&argv), last); | ||||||
| 		return strecpy(buff, " Transport", NULL); | 		return strecpy(buff, " Transport", last); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// language name? | 	// language name? | ||||||
| 	if (IS_INT_INSIDE(ind, (SPECSTR_LANGUAGE_START - 0x70E4), (SPECSTR_LANGUAGE_END - 0x70E4) + 1)) { | 	if (IS_INT_INSIDE(ind, (SPECSTR_LANGUAGE_START - 0x70E4), (SPECSTR_LANGUAGE_END - 0x70E4) + 1)) { | ||||||
| 		int i = ind - (SPECSTR_LANGUAGE_START - 0x70E4); | 		int i = ind - (SPECSTR_LANGUAGE_START - 0x70E4); | ||||||
| 		return strecpy(buff, | 		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? | 	// resolution size? | ||||||
| 	if (IS_INT_INSIDE(ind, (SPECSTR_RESOLUTION_START - 0x70E4), (SPECSTR_RESOLUTION_END - 0x70E4) + 1)) { | 	if (IS_INT_INSIDE(ind, (SPECSTR_RESOLUTION_START - 0x70E4), (SPECSTR_RESOLUTION_END - 0x70E4) + 1)) { | ||||||
| 		int i = ind - (SPECSTR_RESOLUTION_START - 0x70E4); | 		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? | 	// screenshot format name? | ||||||
| 	if (IS_INT_INSIDE(ind, (SPECSTR_SCREENSHOT_START - 0x70E4), (SPECSTR_SCREENSHOT_END - 0x70E4) + 1)) { | 	if (IS_INT_INSIDE(ind, (SPECSTR_SCREENSHOT_START - 0x70E4), (SPECSTR_SCREENSHOT_END - 0x70E4) + 1)) { | ||||||
| 		int i = ind - (SPECSTR_SCREENSHOT_START - 0x70E4); | 		int i = ind - (SPECSTR_SCREENSHOT_START - 0x70E4); | ||||||
| 		return strecpy(buff, GetScreenshotFormatDesc(i), NULL); | 		return strecpy(buff, GetScreenshotFormatDesc(i), last); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	assert(0); | 	assert(0); | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ static inline char* InlineString(char* buf, uint16 string) | |||||||
| 	return buf; | 	return buf; | ||||||
| } | } | ||||||
|  |  | ||||||
| char *GetString(char *buffr, uint16 string); | char *GetString(char *buffr, uint16 string, const char* last); | ||||||
|  |  | ||||||
| extern char _userstring[128]; | extern char _userstring[128]; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -246,7 +246,7 @@ void AddTextEffect(StringID msg, int x, int y, uint16 duration) | |||||||
| 	te->params_1 = GetDParam(0); | 	te->params_1 = GetDParam(0); | ||||||
| 	te->params_2 = GetDParam(4); | 	te->params_2 = GetDParam(4); | ||||||
|  |  | ||||||
| 	GetString(buffer, msg); | 	GetString(buffer, msg, lastof(buffer)); | ||||||
| 	w = GetStringBoundingBox(buffer).width; | 	w = GetStringBoundingBox(buffer).width; | ||||||
|  |  | ||||||
| 	te->x = x - (w >> 1); | 	te->x = x - (w >> 1); | ||||||
|   | |||||||
| @@ -886,7 +886,7 @@ restart: | |||||||
| 		r = Random(); | 		r = Random(); | ||||||
|  |  | ||||||
| 		SetDParam(0, r); | 		SetDParam(0, r); | ||||||
| 		GetString(buf1, townnametype); | 		GetString(buf1, townnametype, lastof(buf1)); | ||||||
|  |  | ||||||
| 		// Check size and width | 		// Check size and width | ||||||
| 		if (strlen(buf1) >= 31 || GetStringBoundingBox(buf1).width > 130) continue; | 		if (strlen(buf1) >= 31 || GetStringBoundingBox(buf1).width > 130) continue; | ||||||
| @@ -895,7 +895,7 @@ restart: | |||||||
| 			// We can't just compare the numbers since | 			// We can't just compare the numbers since | ||||||
| 			// several numbers may map to a single name. | 			// several numbers may map to a single name. | ||||||
| 			SetDParam(0, t2->index); | 			SetDParam(0, t2->index); | ||||||
| 			GetString(buf2, STR_TOWN); | 			GetString(buf2, STR_TOWN, lastof(buf2)); | ||||||
| 			if (strcmp(buf1, buf2) == 0) { | 			if (strcmp(buf1, buf2) == 0) { | ||||||
| 				if (tries-- < 0) return false; | 				if (tries-- < 0) return false; | ||||||
| 				goto restart; | 				goto restart; | ||||||
|   | |||||||
| @@ -378,7 +378,7 @@ static int CDECL TownNameSorter(const void *a, const void *b) | |||||||
| 	int r; | 	int r; | ||||||
|  |  | ||||||
| 	SetDParam(0, ta->index); | 	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 | 	/* 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 | 	 *  We do this to speed stuff up ('b' is called with the same value a lot of | ||||||
| @@ -386,7 +386,7 @@ static int CDECL TownNameSorter(const void *a, const void *b) | |||||||
| 	if (tb != _last_town) { | 	if (tb != _last_town) { | ||||||
| 		_last_town = tb; | 		_last_town = tb; | ||||||
| 		SetDParam(0, tb->index); | 		SetDParam(0, tb->index); | ||||||
| 		GetString(_bufcache, STR_TOWN); | 		GetString(_bufcache, STR_TOWN, lastof(_bufcache)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	r = strcmp(buf1, _bufcache); | 	r = strcmp(buf1, _bufcache); | ||||||
|   | |||||||
| @@ -135,13 +135,13 @@ static int CDECL TrainEngineNameSorter(const void *a, const void *b) | |||||||
| 	char buf1[64]; | 	char buf1[64]; | ||||||
| 	int r; | 	int r; | ||||||
|  |  | ||||||
| 	GetString(buf1, GetCustomEngineName(va)); | 	GetString(buf1, GetCustomEngineName(va), lastof(buf1)); | ||||||
|  |  | ||||||
| 	if (vb != _last_engine) { | 	if (vb != _last_engine) { | ||||||
| 		_last_engine = vb; | 		_last_engine = vb; | ||||||
| 		_bufcache[0] = '\0'; | 		_bufcache[0] = '\0'; | ||||||
|  |  | ||||||
| 		GetString(_bufcache, GetCustomEngineName(vb)); | 		GetString(_bufcache, GetCustomEngineName(vb), lastof(_bufcache)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	r =  strcasecmp(buf1, _bufcache); // sort by name | 	r =  strcasecmp(buf1, _bufcache); // sort by name | ||||||
|   | |||||||
| @@ -2076,7 +2076,7 @@ static int32 ReplaceVehicle(Vehicle **w, byte flags, int32 total_cost) | |||||||
| 		if (!IsCustomName(old_v->string_id)) { | 		if (!IsCustomName(old_v->string_id)) { | ||||||
| 			vehicle_name[0] = '\0'; | 			vehicle_name[0] = '\0'; | ||||||
| 		} else { | 		} 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 | 	} else { // flags & DC_EXEC not set | ||||||
| 		/* Ensure that the player will not end up having negative money while autoreplacing | 		/* Ensure that the player will not end up having negative money while autoreplacing | ||||||
|   | |||||||
| @@ -516,7 +516,7 @@ static int CDECL VehicleNameSorter(const void *a, const void *b) | |||||||
| 	if (va != last_vehicle[0]) { | 	if (va != last_vehicle[0]) { | ||||||
| 		last_vehicle[0] = va; | 		last_vehicle[0] = va; | ||||||
| 		if (IsCustomName(va->string_id)) { | 		if (IsCustomName(va->string_id)) { | ||||||
| 			GetString(last_name[0], va->string_id); | 			GetString(last_name[0], va->string_id, lastof(last_name[0])); | ||||||
| 		} else { | 		} else { | ||||||
| 			last_name[0][0] = '\0'; | 			last_name[0][0] = '\0'; | ||||||
| 		} | 		} | ||||||
| @@ -525,7 +525,7 @@ static int CDECL VehicleNameSorter(const void *a, const void *b) | |||||||
| 	if (vb != last_vehicle[1]) { | 	if (vb != last_vehicle[1]) { | ||||||
| 		last_vehicle[1] = vb; | 		last_vehicle[1] = vb; | ||||||
| 		if (IsCustomName(vb->string_id)) { | 		if (IsCustomName(vb->string_id)) { | ||||||
| 			GetString(last_name[1], vb->string_id); | 			GetString(last_name[1], vb->string_id, lastof(last_name[1])); | ||||||
| 		} else { | 		} else { | ||||||
| 			last_name[1][0] = '\0'; | 			last_name[1][0] = '\0'; | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -1017,7 +1017,7 @@ void UpdateViewportSignPos(ViewportSign *sign, int left, int top, StringID str) | |||||||
|  |  | ||||||
| 	sign->top = top; | 	sign->top = top; | ||||||
|  |  | ||||||
| 	GetString(buffer, str); | 	GetString(buffer, str, lastof(buffer)); | ||||||
| 	w = GetStringBoundingBox(buffer).width + 3; | 	w = GetStringBoundingBox(buffer).width + 3; | ||||||
| 	sign->width_1 = w; | 	sign->width_1 = w; | ||||||
| 	sign->left = left - w / 2; | 	sign->left = left - w / 2; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Darkvater
					Darkvater