mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-06 14:27:16 +00:00
(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:
parent
1a046ff4c6
commit
3e62457107
@ -422,7 +422,7 @@ void RunTileLoop(void)
|
||||
_cur_tileloop_tile = tile;
|
||||
}
|
||||
|
||||
void InitializeLandscape()
|
||||
void InitializeLandscape(void)
|
||||
{
|
||||
uint map_size;
|
||||
uint i;
|
||||
|
25
network.c
25
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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
36
strings.c
36
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));
|
||||
|
10
variables.h
10
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))
|
||||
|
Loading…
Reference in New Issue
Block a user