From 3e62457107457c8295076370425e9a1df44fa58c Mon Sep 17 00:00:00 2001 From: ludde Date: Thu, 14 Jul 2005 09:43:59 +0000 Subject: [PATCH] (svn r2564) Fix: Fixed conceptual issue in network_gui.c. AllocateName is not meant to be used by GUI-code, because it modifies the "game-state". Added a way to bind a C-string to an openttd string which doesn't modify the game state. --- landscape.c | 2 +- network.c | 25 ++++++------------------ network_gui.c | 53 ++++++++++---------------------------------------- openttd.c | 2 +- openttd.h | 5 +++-- player_gui.c | 6 ++---- settings_gui.c | 7 +++---- strings.c | 36 ++++++++++++++++++++++++++++++---- variables.h | 10 ++++++++++ 9 files changed, 68 insertions(+), 78 deletions(-) diff --git a/landscape.c b/landscape.c index 31f134e93e..bd708aea45 100644 --- a/landscape.c +++ b/landscape.c @@ -422,7 +422,7 @@ void RunTileLoop(void) _cur_tileloop_tile = tile; } -void InitializeLandscape() +void InitializeLandscape(void) { uint map_size; uint i; diff --git a/network.c b/network.c index 3dcff1b305..e422c5e20a 100644 --- a/network.c +++ b/network.c @@ -93,7 +93,6 @@ void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send const int duration = 10; // Game days the messages stay visible char message[1024]; char temp[1024]; - StringID TempStr = STR_NULL; va_start(va, str); vsprintf(buf, str, va); @@ -110,11 +109,9 @@ void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send break; case NETWORK_ACTION_GIVE_MONEY: if (self_send) { - TempStr = AllocateName(name, 0); - SetDParam(0, TempStr); + SetDParamStr(0, name); SetDParam(1, atoi(buf)); GetString(temp, STR_NETWORK_GAVE_MONEY_AWAY); - DeleteName(TempStr); snprintf(message, sizeof(message), "*** %s", temp); } else { SetDParam(0, atoi(buf)); @@ -124,31 +121,23 @@ void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send break; case NETWORK_ACTION_CHAT_PLAYER: if (self_send) { - TempStr = AllocateName(name, 0); - SetDParam(0, TempStr); + SetDParamStr(0, name); GetString(temp, STR_NETWORK_CHAT_TO_COMPANY); - DeleteName(TempStr); snprintf(message, sizeof(message), "%s %s", temp, buf); } else { - TempStr = AllocateName(name, 0); - SetDParam(0, TempStr); + SetDParamStr(0, name); GetString(temp, STR_NETWORK_CHAT_COMPANY); - DeleteName(TempStr); snprintf(message, sizeof(message), "%s %s", temp, buf); } break; case NETWORK_ACTION_CHAT_CLIENT: if (self_send) { - TempStr = AllocateName(name, 0); - SetDParam(0, TempStr); + SetDParamStr(0, name); GetString(temp, STR_NETWORK_CHAT_TO_CLIENT); - DeleteName(TempStr); snprintf(message, sizeof(message), "%s %s", temp, buf); } else { - TempStr = AllocateName(name, 0); - SetDParam(0, TempStr); + SetDParamStr(0, name); GetString(temp, STR_NETWORK_CHAT_CLIENT); - DeleteName(TempStr); snprintf(message, sizeof(message), "%s %s", temp, buf); } break; @@ -157,10 +146,8 @@ void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send snprintf(message, sizeof(message), "*** %s %s %s", name, temp, buf); break; default: - TempStr = AllocateName(name, 0); - SetDParam(0, TempStr); + SetDParamStr(0, name); GetString(temp, STR_NETWORK_CHAT_ALL); - DeleteName(TempStr); snprintf(message, sizeof(message), "%s %s", temp, buf); break; } diff --git a/network_gui.c b/network_gui.c index 95911fa8ac..0f33962d29 100644 --- a/network_gui.c +++ b/network_gui.c @@ -190,10 +190,11 @@ static void NetworkGameWindowWndProc(Window *w, WindowEvent *e) DrawStringMultiCenter(365, 30, STR_NETWORK_GAME_INFO, 0); - SetDParam(0, _str_game_name); + + SetDParamStr(0, _selected_item->info.server_name); DrawStringMultiCenter(365, 42, STR_ORANGE, 2); // game name - SetDParam(0, _str_map_name); + SetDParamStr(0, _selected_item->info.map_name); DrawStringMultiCenter(365, 54, STR_02BD, 2); // map name SetDParam(0, _selected_item->info.clients_on); @@ -214,11 +215,11 @@ static void NetworkGameWindowWndProc(Window *w, WindowEvent *e) DrawString(260, y, STR_NETWORK_MAP_SIZE, 2); // map size y+=10; - SetDParam(0, _str_server_version); + SetDParamStr(0, _selected_item->info.server_revision); DrawString(260, y, STR_NETWORK_SERVER_VERSION, 2); // server version y+=10; - SetDParam(0, _str_server_address); + SetDParamStr(0, _selected_item->info.hostname); SetDParam(1, _selected_item->port); DrawString(260, y, STR_NETWORK_SERVER_ADDRESS, 2); // server address y+=10; @@ -273,30 +274,6 @@ static void NetworkGameWindowWndProc(Window *w, WindowEvent *e) return; } _selected_item = cur_item; - - DeleteName(_str_game_name); - DeleteName(_str_map_name); - DeleteName(_str_server_version); - DeleteName(_str_server_address); - if (_selected_item->info.server_name[0] != '\0') - _str_game_name = AllocateName(_selected_item->info.server_name, 0); - else - _str_game_name = STR_EMPTY; - - if (_selected_item->info.map_name[0] != '\0') - _str_map_name = AllocateName(_selected_item->info.map_name, 0); - else - _str_map_name = STR_EMPTY; - - if (_selected_item->info.server_revision[0] != '\0') - _str_server_version = AllocateName(_selected_item->info.server_revision, 0); - else - _str_server_version = STR_EMPTY; - - if (_selected_item->info.hostname[0] != '\0') - _str_server_address = AllocateName(_selected_item->info.hostname, 0); - else - _str_server_address = STR_EMPTY; } SetWindowDirty(w); } break; @@ -307,16 +284,13 @@ static void NetworkGameWindowWndProc(Window *w, WindowEvent *e) } break; case 12: { // Add a server - StringID str = AllocateName(_network_default_ip, 0); - ShowQueryString( - str, + BindCString(_network_default_ip), STR_NETWORK_ENTER_IP, 31 | 0x1000, // maximum number of characters OR 250, // characters up to this width pixels, whichever is satisfied first w->window_class, w->window_number); - DeleteName(str); } break; case 13: /* Start server */ ShowNetworkStartServerWindow(); @@ -536,10 +510,8 @@ static void NetworkStartServerWindowWndProc(Window *w, WindowEvent *e) ShowNetworkGameWindow(); break; case 4: { /* Set password button */ - StringID str; - str = AllocateName(_network_server_password, 0); - ShowQueryString(str, STR_NETWORK_SET_PASSWORD, 20, 250, w->window_class, w->window_number); - DeleteName(str); + ShowQueryString(BindCString(_network_server_password), + STR_NETWORK_SET_PASSWORD, 20, 250, w->window_class, w->window_number); } break; case 5: { /* Select map */ int y = (e->click.pt.y - NSSWND_START) / NSSWND_ROWSIZE; @@ -697,7 +669,6 @@ static void NetworkLobbyWindowWndProc(Window *w, WindowEvent *e) switch(e->event) { case WE_PAINT: { int y = NET_PRC__OFFSET_TOP_WIDGET_COMPANY, pos; - StringID str; w->disabled_state = (_selected_company_item == -1) ? 1 << 7 : 0; @@ -745,10 +716,8 @@ static void NetworkLobbyWindowWndProc(Window *w, WindowEvent *e) uint xm; y = 65; - str = AllocateName(_network_player_info[_selected_company_item].company_name, 0); - SetDParam(0, str); + SetDParamStr(0, _network_player_info[_selected_company_item].company_name); DrawString(x, y, STR_NETWORK_COMPANY_NAME, 2); - DeleteName(str); y += 10; SetDParam(0, _network_player_info[_selected_company_item].inaugurated_year + MAX_YEAR_BEGIN_REAL); @@ -787,10 +756,8 @@ static void NetworkLobbyWindowWndProc(Window *w, WindowEvent *e) DrawString(x, y, STR_NETWORK_STATIONS, 2); // stations y += 10; - str = AllocateName(_network_player_info[_selected_company_item].players, 0); - SetDParam(0, str); + SetDParamStr(0, _network_player_info[_selected_company_item].players); xm = DrawString(x, y, STR_NETWORK_PLAYERS, 2); // players - DeleteName(str); y += 10; } } break; diff --git a/openttd.c b/openttd.c index 9abf6e78a9..26057a5175 100644 --- a/openttd.c +++ b/openttd.c @@ -738,7 +738,7 @@ int ttd_main(int argc, char* argv[]) static void ShowScreenshotResult(bool b) { if (b) { - SetDParam(0, STR_SPEC_SCREENSHOT_NAME); + SetDParamStr(0, _screenshot_name); ShowErrorMessage(INVALID_STRING_ID, STR_031B_SCREENSHOT_SUCCESSFULLY, 0, 0); } else { ShowErrorMessage(INVALID_STRING_ID, STR_031C_SCREENSHOT_FAILED, 0, 0); diff --git a/openttd.h b/openttd.h index a44ccdc955..317acd03f3 100644 --- a/openttd.h +++ b/openttd.h @@ -517,8 +517,9 @@ enum SpecialStrings { SPECSTR_SCREENSHOT_START = 0x7140, SPECSTR_SCREENSHOT_END = 0x715F, - STR_SPEC_SCREENSHOT_NAME = 0xF800, - STR_SPEC_USERSTRING = 0xF801, + // Used to implement SetDParamStr + STR_SPEC_DYNSTRING = 0xF800, + STR_SPEC_USERSTRING = 0xF808, }; typedef void PlaceProc(TileIndex tile); diff --git a/player_gui.c b/player_gui.c index 6359d97e60..d58eb0360c 100644 --- a/player_gui.c +++ b/player_gui.c @@ -614,11 +614,9 @@ static void PlayerCompanyWndProc(Window *w, WindowEvent *e) case 11: { /* Password protect company */ #ifdef ENABLE_NETWORK if (!IsWindowOfPrototype(w, _other_player_company_widgets)) { - StringID str; WP(w,def_d).byte_1 = 2; - str = AllocateName(_network_player_info[_local_player].password, 0); - ShowQueryString(str, STR_SET_COMPANY_PASSWORD, sizeof(_network_player_info[_local_player].password), 250, w->window_class, w->window_number); - DeleteName(str); + ShowQueryString(BindCString(_network_player_info[_local_player].password), + STR_SET_COMPANY_PASSWORD, sizeof(_network_player_info[_local_player].password), 250, w->window_class, w->window_number); } #endif } break; diff --git a/settings_gui.c b/settings_gui.c index b9a0e00372..c2e7944ae2 100644 --- a/settings_gui.c +++ b/settings_gui.c @@ -1384,21 +1384,21 @@ static void CustCurrencyWndProc(Window *w, WindowEvent *e) case 1: // separator if ( IS_INT_INSIDE(x, 10, 30) ) // clicked button WP(w,def_d).data_1 = (1 << (line * 2 + 1)); - str = AllocateName(_str_separator, 0); + str = BindCString(_str_separator); len = 1; edittext = true; break; case 2: // prefix if ( IS_INT_INSIDE(x, 10, 30) ) // clicked button WP(w,def_d).data_1 = (1 << (line * 2 + 1)); - str = AllocateName(_currency_specs[23].prefix, 0); + str = BindCString(_currency_specs[23].prefix); len = 12; edittext = true; break; case 3: // suffix if ( IS_INT_INSIDE(x, 10, 30) ) // clicked button WP(w,def_d).data_1 = (1 << (line * 2 + 1)); - str = AllocateName(_currency_specs[23].suffix, 0); + str = BindCString(_currency_specs[23].suffix); len = 12; edittext = true; break; @@ -1432,7 +1432,6 @@ static void CustCurrencyWndProc(Window *w, WindowEvent *e) 250, // characters up to this width pixels, whichever is satisfied first w->window_class, w->window_number); - if (str != STR_CONFIG_PATCHES_INT32) DeleteName(str); } w->flags4 |= 5 << WF_TIMEOUT_SHL; diff --git a/strings.c b/strings.c index c509333216..f91d17e1a6 100644 --- a/strings.c +++ b/strings.c @@ -125,6 +125,17 @@ static const StringID _cargo_string_list[NUM_LANDSCAPE][NUM_CARGO] = { }; +#define NUM_BOUND_STRINGS 8 + +// Array to hold the bound strings. +static const char *_bound_strings[NUM_BOUND_STRINGS]; + +// This index is used to implement a "round-robin" allocating of +// slots for BindCString. NUM_BOUND_STRINGS slots are reserved. +// Which means that after NUM_BOUND_STRINGS calls to BindCString, +// the indices will be reused. +static int _bind_index; + static const char *GetStringPtr(StringID string) { return _langpack_offs[_langtab_start[string >> 11] + (string & 0x7FF)]; @@ -142,9 +153,6 @@ char *GetString(char *buffr, StringID string) case 0x30D1: return StationGetSpecialString(buffr); - - case STR_SPEC_SCREENSHOT_NAME: - return DecodeString(buffr, _screenshot_name); } switch (tab) { @@ -160,7 +168,11 @@ char *GetString(char *buffr, StringID string) return GetName(index, buffr); case 31: // special or dynamic strings - return DecodeString(buffr, _userstring); + if (index < (STR_SPEC_USERSTRING & 0x7FF)) { + return DecodeString(buffr, _bound_strings[index]); + } else { + return DecodeString(buffr, _userstring); + } default: break; @@ -175,6 +187,22 @@ char *GetString(char *buffr, StringID string) return DecodeString(buffr, GetStringPtr(string)); } +// 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. +StringID BindCString(const char *str) +{ + int idx = (++_bind_index) & (NUM_BOUND_STRINGS - 1); + _bound_strings[idx] = str; + return idx + STR_SPEC_DYNSTRING; +} + +// This function is used to "bind" a C string to a OpenTTD dparam slot. +void SetDParamStr(uint n, const char *str) +{ + SetDParam(n, BindCString(str)); +} + void InjectDParam(int amount) { memmove(_decode_parameters + amount, _decode_parameters, sizeof(_decode_parameters) - amount * sizeof(uint32)); diff --git a/variables.h b/variables.h index 3514ad54fc..985390095f 100644 --- a/variables.h +++ b/variables.h @@ -424,6 +424,16 @@ static inline uint32 GetDParam(uint n) return _decode_parameters[n]; } +// Used to bind a C string name to a dparam number. +// NOTE: This has a short lifetime. You can't +// use this string much later or it will be gone. +void SetDParamStr(uint n, const char *str); + +// This function takes a C-string and allocates a temporary string ID. +// The duration of the bound string is valid only until the next acll to GetString, +// so be careful. +StringID BindCString(const char *str); + #define COPY_IN_DPARAM(offs,src,num) memcpy(_decode_parameters + offs, src, sizeof(uint32) * (num)) #define COPY_OUT_DPARAM(dst,offs,num) memcpy(dst,_decode_parameters + offs, sizeof(uint32) * (num))