diff --git a/src/error.h b/src/error.h index 366bcd3ade..206bb67fbd 100644 --- a/src/error.h +++ b/src/error.h @@ -24,5 +24,7 @@ enum WarningLevel { void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x = 0, int y = 0, uint textref_stack_size = 0, const uint32 *textref_stack = NULL); void ClearErrorMessages(); +void ShowFirstError(); +void UnshowCriticalError(); #endif /* ERROR_H */ diff --git a/src/error_gui.cpp b/src/error_gui.cpp index ee2d5325a1..72e051281c 100644 --- a/src/error_gui.cpp +++ b/src/error_gui.cpp @@ -127,6 +127,8 @@ public: typedef std::list ErrorList; /** The actual queue with errors. */ ErrorList _errors; +/** Whether the window system is initialized or not. */ +bool _window_system_initialized = false; /** Window class for displaying an error message window. */ struct ErrmsgWindow : public Window, ErrorMessageData { @@ -261,11 +263,7 @@ public: ~ErrmsgWindow() { SetRedErrorSquare(INVALID_TILE); - - if (!_errors.empty()) { - new ErrmsgWindow(_errors.front()); - _errors.pop_front(); - } + if (_window_system_initialized) ShowFirstError(); } virtual EventState OnKeyPress(uint16 key, uint16 keycode) @@ -293,6 +291,30 @@ void ClearErrorMessages() _errors.clear(); } +/** Show the first error of the queue. */ +void ShowFirstError() +{ + _window_system_initialized = true; + if (!_errors.empty()) { + new ErrmsgWindow(_errors.front()); + _errors.pop_front(); + } +} + +/** + * Unshow the critical error. This has to happen when a critical + * error is shown and we uninitialise the window system, i.e. + * remove all the windows. + */ +void UnshowCriticalError() +{ + ErrmsgWindow *w = (ErrmsgWindow*)FindWindowById(WC_ERRMSG, 0); + if (w != NULL) { + if (w->IsCritical()) _errors.push_front(*w); + _window_system_initialized = false; + } +} + /** * Display an error message in a window. * @param summary_msg General error message showed in first line. Must be valid. diff --git a/src/network/core/tcp_game.cpp b/src/network/core/tcp_game.cpp index 4f0202c602..64b7ba97a8 100644 --- a/src/network/core/tcp_game.cpp +++ b/src/network/core/tcp_game.cpp @@ -18,6 +18,7 @@ #include "../network.h" #include "../network_internal.h" #include "../../debug.h" +#include "../../error.h" #include "table/strings.h" @@ -46,8 +47,7 @@ NetworkRecvStatus NetworkGameSocketHandler::CloseConnection(bool error) if (!_network_server && _networking) { _switch_mode = SM_MENU; _networking = false; - extern StringID _switch_mode_errorstr; - _switch_mode_errorstr = STR_NETWORK_ERROR_LOSTCONNECTION; + ShowErrorMessage(STR_NETWORK_ERROR_LOSTCONNECTION, INVALID_STRING_ID, WL_CRITICAL); return NETWORK_RECV_STATUS_CONN_LOST; } diff --git a/src/network/network.cpp b/src/network/network.cpp index 0b6e9c35a8..dd47be1729 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -36,6 +36,7 @@ #include "../rev.h" #include "../core/pool_func.hpp" #include "../gfx_func.h" +#include "../error.h" #include "table/strings.h" #ifdef DEBUG_DUMP_COMMANDS @@ -287,8 +288,7 @@ uint NetworkCalculateLag(const NetworkClientSocket *cs) void NetworkError(StringID error_string) { _switch_mode = SM_MENU; - extern StringID _switch_mode_errorstr; - _switch_mode_errorstr = error_string; + ShowErrorMessage(error_string, INVALID_STRING_ID, WL_CRITICAL); } /** diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index c982536489..fd133dc548 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -526,12 +526,11 @@ bool ClientNetworkGameSocketHandler::IsConnected() ************/ extern bool SafeLoad(const char *filename, int mode, GameMode newgm, Subdirectory subdir, struct LoadFilter *lf = NULL); -extern StringID _switch_mode_errorstr; NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_FULL(Packet *p) { /* We try to join a server which is full */ - _switch_mode_errorstr = STR_NETWORK_ERROR_SERVER_FULL; + ShowErrorMessage(STR_NETWORK_ERROR_SERVER_FULL, INVALID_STRING_ID, WL_CRITICAL); DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0); return NETWORK_RECV_STATUS_SERVER_FULL; @@ -540,7 +539,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_FULL(Packet *p) NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_BANNED(Packet *p) { /* We try to join a server where we are banned */ - _switch_mode_errorstr = STR_NETWORK_ERROR_SERVER_BANNED; + ShowErrorMessage(STR_NETWORK_ERROR_SERVER_BANNED, INVALID_STRING_ID, WL_CRITICAL); DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0); return NETWORK_RECV_STATUS_SERVER_BANNED; @@ -652,28 +651,28 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p case NETWORK_ERROR_NOT_AUTHORIZED: case NETWORK_ERROR_NOT_EXPECTED: case NETWORK_ERROR_COMPANY_MISMATCH: - _switch_mode_errorstr = STR_NETWORK_ERROR_SERVER_ERROR; + ShowErrorMessage(STR_NETWORK_ERROR_SERVER_ERROR, INVALID_STRING_ID, WL_CRITICAL); break; case NETWORK_ERROR_FULL: - _switch_mode_errorstr = STR_NETWORK_ERROR_SERVER_FULL; + ShowErrorMessage(STR_NETWORK_ERROR_SERVER_FULL, INVALID_STRING_ID, WL_CRITICAL); break; case NETWORK_ERROR_WRONG_REVISION: - _switch_mode_errorstr = STR_NETWORK_ERROR_WRONG_REVISION; + ShowErrorMessage(STR_NETWORK_ERROR_WRONG_REVISION, INVALID_STRING_ID, WL_CRITICAL); break; case NETWORK_ERROR_WRONG_PASSWORD: - _switch_mode_errorstr = STR_NETWORK_ERROR_WRONG_PASSWORD; + ShowErrorMessage(STR_NETWORK_ERROR_WRONG_PASSWORD, INVALID_STRING_ID, WL_CRITICAL); break; case NETWORK_ERROR_KICKED: - _switch_mode_errorstr = STR_NETWORK_ERROR_KICKED; + ShowErrorMessage(STR_NETWORK_ERROR_KICKED, INVALID_STRING_ID, WL_CRITICAL); break; case NETWORK_ERROR_CHEATER: - _switch_mode_errorstr = STR_NETWORK_ERROR_CHEATER; + ShowErrorMessage(STR_NETWORK_ERROR_CHEATER, INVALID_STRING_ID, WL_CRITICAL); break; case NETWORK_ERROR_TOO_MANY_COMMANDS: - _switch_mode_errorstr = STR_NETWORK_ERROR_TOO_MANY_COMMANDS; + ShowErrorMessage(STR_NETWORK_ERROR_TOO_MANY_COMMANDS, INVALID_STRING_ID, WL_CRITICAL); break; default: - _switch_mode_errorstr = STR_NETWORK_ERROR_LOSTCONNECTION; + ShowErrorMessage(STR_NETWORK_ERROR_LOSTCONNECTION, INVALID_STRING_ID, WL_CRITICAL); } DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0); @@ -710,7 +709,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(P } /* NewGRF mismatch, bail out */ - _switch_mode_errorstr = STR_NETWORK_ERROR_NEWGRF_MISMATCH; + ShowErrorMessage(STR_NETWORK_ERROR_NEWGRF_MISMATCH, INVALID_STRING_ID, WL_CRITICAL); return ret; } @@ -849,7 +848,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet if (!load_success) { DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0); - _switch_mode_errorstr = STR_NETWORK_ERROR_SAVEGAMEERROR; + ShowErrorMessage(STR_NETWORK_ERROR_SAVEGAMEERROR, INVALID_STRING_ID, WL_CRITICAL); return NETWORK_RECV_STATUS_SAVEGAME; } /* If the savegame has successfully loaded, ALL windows have been removed, @@ -1053,7 +1052,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_SHUTDOWN(Packet /* Only when we're trying to join we really * care about the server shutting down. */ if (this->status >= STATUS_JOIN) { - _switch_mode_errorstr = STR_NETWORK_MESSAGE_SERVER_SHUTDOWN; + ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_SHUTDOWN, INVALID_STRING_ID, WL_CRITICAL); } return NETWORK_RECV_STATUS_SERVER_ERROR; @@ -1068,7 +1067,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEWGAME(Packet * Client ID modulo 16. This way reconnects should be spread * out a bit. */ _network_reconnect = _network_own_client_id % 16; - _switch_mode_errorstr = STR_NETWORK_MESSAGE_SERVER_REBOOT; + ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_REBOOT, INVALID_STRING_ID, WL_CRITICAL); } return NETWORK_RECV_STATUS_SERVER_ERROR; @@ -1157,7 +1156,7 @@ void ClientNetworkGameSocketHandler::CheckConnection() * the server will forcefully disconnect you. */ if (lag > 20) { this->NetworkGameSocketHandler::CloseConnection(); - _switch_mode_errorstr = STR_NETWORK_ERROR_LOSTCONNECTION; + ShowErrorMessage(STR_NETWORK_ERROR_LOSTCONNECTION, INVALID_STRING_ID, WL_CRITICAL); return; } diff --git a/src/openttd.cpp b/src/openttd.cpp index 464330581a..a902d197d6 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -71,9 +71,6 @@ #include "table/strings.h" -/** Error message to show when switching modes. */ -StringID _switch_mode_errorstr; - void CallLandscapeTick(); void IncreaseDate(); void DoPaletteAnimations(); @@ -524,7 +521,6 @@ int ttd_main(int argc, char *argv[]) _game_mode = GM_MENU; _switch_mode = SM_MENU; - _switch_mode_errorstr = INVALID_STRING_ID; _config_file = NULL; GetOptData mgo(argc - 1, argv + 1, _options); @@ -1103,11 +1099,6 @@ void SwitchToMode(SwitchMode new_mode) default: NOT_REACHED(); } - - if (_switch_mode_errorstr != INVALID_STRING_ID) { - ShowErrorMessage(_switch_mode_errorstr, INVALID_STRING_ID, WL_CRITICAL); - _switch_mode_errorstr = INVALID_STRING_ID; - } } diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 3873b5d6ed..85a1ace1da 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -53,6 +53,7 @@ #include "../smallmap_gui.h" #include "../news_func.h" #include "../group.h" +#include "../error.h" #include "table/strings.h" @@ -60,7 +61,6 @@ #include -extern StringID _switch_mode_errorstr; extern Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY); /** @@ -622,8 +622,8 @@ bool AfterLoadGame() } switch (gcf_res) { - case GLC_COMPATIBLE: _switch_mode_errorstr = STR_NEWGRF_COMPATIBLE_LOAD_WARNING; break; - case GLC_NOT_FOUND: _switch_mode_errorstr = STR_NEWGRF_DISABLED_WARNING; _pause_mode = PM_PAUSED_ERROR; break; + case GLC_COMPATIBLE: ShowErrorMessage(STR_NEWGRF_COMPATIBLE_LOAD_WARNING, INVALID_STRING_ID, WL_CRITICAL); break; + case GLC_NOT_FOUND: ShowErrorMessage(STR_NEWGRF_DISABLED_WARNING, INVALID_STRING_ID, WL_CRITICAL); _pause_mode = PM_PAUSED_ERROR; break; default: break; } @@ -1756,9 +1756,7 @@ bool AfterLoadGame() RoadVehicle *v; FOR_ALL_ROADVEHICLES(v) { if (v->First() == v && HasBit(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM)) { - if (_switch_mode_errorstr == INVALID_STRING_ID || _switch_mode_errorstr == STR_NEWGRF_COMPATIBLE_LOAD_WARNING) { - _switch_mode_errorstr = STR_WARNING_LOADGAME_REMOVED_TRAMS; - } + ShowErrorMessage(STR_WARNING_LOADGAME_REMOVED_TRAMS, INVALID_STRING_ID, WL_CRITICAL); delete v; } } diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 4413092d3f..407a837d19 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -1896,8 +1896,7 @@ bool GenerateTowns(TownLayout layout) /* If there are no towns at all and we are generating new game, bail out */ if (Town::GetNumItems() == 0 && _game_mode != GM_EDITOR) { - extern StringID _switch_mode_errorstr; - _switch_mode_errorstr = STR_ERROR_COULD_NOT_CREATE_TOWN; + ShowErrorMessage(STR_ERROR_COULD_NOT_CREATE_TOWN, INVALID_STRING_ID, WL_CRITICAL); } return false; // we are still without a town? we failed, simply diff --git a/src/window.cpp b/src/window.cpp index 9241f6c84e..33b48916af 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -32,6 +32,7 @@ #include "hotkeys.h" #include "toolbar_gui.h" #include "statusbar_gui.h" +#include "error.h" static Point _drag_delta; ///< delta between mouse cursor and upper left corner of dragged window @@ -1448,6 +1449,8 @@ void InitWindowSystem() NWidgetLeaf::InvalidateDimensionCache(); // Reset cached sizes of several widgets. NWidgetScrollbar::InvalidateDimensionCache(); + + ShowFirstError(); } /** @@ -1455,6 +1458,8 @@ void InitWindowSystem() */ void UnInitWindowSystem() { + UnshowCriticalError(); + Window *w; FOR_ALL_WINDOWS_FROM_FRONT(w) delete w;