(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.
This commit is contained in:
ludde 2005-07-14 09:43:59 +00:00
parent 1a046ff4c6
commit 3e62457107
9 changed files with 68 additions and 78 deletions

View File

@ -422,7 +422,7 @@ void RunTileLoop(void)
_cur_tileloop_tile = tile;
}
void InitializeLandscape()
void InitializeLandscape(void)
{
uint map_size;
uint i;

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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));

View File

@ -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))