From dd7c20c848cbee5a1e71446536e9ea65b3f22655 Mon Sep 17 00:00:00 2001 From: lethosor Date: Tue, 28 Jul 2015 18:34:29 -0400 Subject: [PATCH] Add safer helpers to get STRING_X keys from interface_key sets A few plugins were using input->rbegin() previously, which crashes if input is empty and isn't strictly guaranteed to return a STRING_X key. --- NEWS | 1 + plugins/buildingplan.cpp | 2 +- plugins/search.cpp | 14 +++----------- plugins/uicommon.h | 22 ++++++++++++++++++---- plugins/zone.cpp | 9 ++------- 5 files changed, 25 insertions(+), 23 deletions(-) diff --git a/NEWS b/NEWS index 406b2c6a3..0588784b9 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,7 @@ DFHack Future gui/hack-wish now properly assigns quality to items. gui/gm-editor handles lua tables properly search: fixed crash in unit list after cancelling a job + stocks: fixed a crash when right-clicking steam-engine: - fixed a crash on arena load - number keys (e.g. 2/8) take priority over cursor keys when applicable diff --git a/plugins/buildingplan.cpp b/plugins/buildingplan.cpp index d3cdef923..ddc804897 100644 --- a/plugins/buildingplan.cpp +++ b/plugins/buildingplan.cpp @@ -189,7 +189,7 @@ struct buildingplan_hook : public df::viewscreen_dwarfmodest else if (isInNobleRoomQueryMode()) { auto np = getNoblePositionOfSelectedBuildingOwner(); - df::interface_key last_token = *input->rbegin(); + df::interface_key last_token = get_string_key(input); if (last_token >= interface_key::STRING_A048 && last_token <= interface_key::STRING_A058) { int selection = last_token - interface_key::STRING_A048; diff --git a/plugins/search.cpp b/plugins/search.cpp index 4c0773906..7877bc207 100644 --- a/plugins/search.cpp +++ b/plugins/search.cpp @@ -5,6 +5,8 @@ #include +#include "uicommon.h" + #include "df/ui_look_list.h" #include "df/viewscreen_announcelistst.h" #include "df/viewscreen_petst.h" @@ -65,12 +67,6 @@ to use. */ -void OutputString(int8_t color, int &x, int y, const std::string &text) -{ - Screen::paintString(Screen::Pen(' ', color, 0), x, y, text); - x += text.length(); -} - void make_text_dim(int x1, int x2, int y) { for (int x = x1; x <= x2; x++) @@ -225,11 +221,7 @@ public: { // Query typing mode - if (input->empty()) - { - return false; - } - df::interface_key last_token = *input->rbegin(); + df::interface_key last_token = get_string_key(input); int charcode = Screen::keyToChar(last_token); if (charcode >= 32 && charcode <= 126) { diff --git a/plugins/uicommon.h b/plugins/uicommon.h index 56519c260..5f5414b72 100644 --- a/plugins/uicommon.h +++ b/plugins/uicommon.h @@ -206,6 +206,20 @@ static string pad_string(string text, const int size, const bool front = true, c } } +static df::interface_key get_string_key(const std::set *input) +{ + for (auto it = input->begin(); it != input->end(); ++it) + { + if (DFHack::Screen::keyToChar(*it) >= 0) + return *it; + } + return df::interface_key::NONE; +} + +static char get_string_input(const std::set *input) +{ + return DFHack::Screen::keyToChar(get_string_key(input)); +} /* * Utility Functions @@ -370,7 +384,7 @@ protected: y2 = sp->room.y + sp->room.height; } -private: +protected: int x1, x2, y1, y2, z; }; @@ -414,7 +428,7 @@ public: DFHack::World::DeletePersistentData(config); } -private: +protected: PersistentDataItem config; string persistence_key; }; @@ -799,7 +813,7 @@ public: else if (allow_search) { // Search query typing mode always on - df::interface_key last_token = *input->rbegin(); + df::interface_key last_token = get_string_key(input); int charcode = Screen::keyToChar(last_token); if ((charcode >= 96 && charcode <= 123) || charcode == 32) { @@ -873,7 +887,7 @@ public: return display_list.size(); } -private: +protected: static void clear_fn(ListEntry &e) { e.selected = false; } static bool sort_fn(ListEntry const& a, ListEntry const& b) { return a.text.compare(b.text) < 0; } diff --git a/plugins/zone.cpp b/plugins/zone.cpp index 10ffcd3c8..b9044b6fd 100644 --- a/plugins/zone.cpp +++ b/plugins/zone.cpp @@ -41,6 +41,7 @@ using namespace std; #include "Export.h" #include "PluginManager.h" #include "MiscUtils.h" +#include "uicommon.h" #include "LuaTools.h" #include "DataFuncs.h" @@ -3705,12 +3706,6 @@ DFHACK_PLUGIN_LUA_COMMANDS { //START zone filters -void OutputString(int8_t color, int &x, int y, const std::string &text) -{ - Screen::paintString(Screen::Pen(' ', color, 0), x, y, text); - x += text.length(); -} - class zone_filter { public: @@ -3856,7 +3851,7 @@ public: return false; } - df::interface_key last_token = *input->rbegin(); + df::interface_key last_token = get_string_key(input); int charcode = Screen::keyToChar(last_token); if (charcode >= 32 && charcode <= 126) {