diff --git a/common/main/newmenu.h b/common/main/newmenu.h index 16fe0260b..ce202e135 100644 --- a/common/main/newmenu.h +++ b/common/main/newmenu.h @@ -59,6 +59,20 @@ struct listbox; class newmenu_item { + struct input_common_type + { + int text_len; + /* Only used by imenu, but placing it in imenu_specific_type + * makes newmenu_item non-POD. Some users expect newmenu_item + * to be POD. Placing group here does not increase overall size + * since number_slider_common_type also has two int members. + */ + int group; + }; + struct input_specific_type : input_common_type + { + static constexpr std::integral_constant nm_type{}; + }; struct radio_specific_type { static constexpr std::integral_constant nm_type{}; @@ -73,10 +87,9 @@ class newmenu_item { static constexpr std::integral_constant nm_type{}; }; - struct imenu_specific_type + struct imenu_specific_type : input_common_type { static constexpr std::integral_constant nm_type{}; - int group; }; struct slider_specific_type : number_slider_common_type { @@ -97,11 +110,15 @@ public: int type; // What kind of item this is, see NM_TYPE_????? defines int value; // For checkboxes and radio buttons, this is 1 if marked initially, else 0 union { + input_specific_type nm_private_input; radio_specific_type nm_private_radio; number_specific_type nm_private_number; imenu_specific_type nm_private_imenu; slider_specific_type nm_private_slider; }; + input_specific_type &input() { + return get_union_member(nm_private_input); + } radio_specific_type &radio() { return get_union_member(nm_private_radio); } @@ -119,7 +136,11 @@ public: ? &nm_private_number : nullptr; } - int text_len; // The maximum length of characters that can be entered by this inputboxes + input_common_type *input_or_menu() { + return (type == nm_private_input.nm_type || type == nm_private_imenu.nm_type) + ? &nm_private_input + : nullptr; + } char *text; // The text associated with this item. // The rest of these are used internally by by the menu system, so don't set 'em!! short x, y; @@ -350,7 +371,7 @@ static inline void nm_set_item_input(newmenu_item &ni, unsigned len, char *text) { ni.type = NM_TYPE_INPUT; ni.text = text; - ni.text_len = len-1; + ni.input().text_len = len - 1; } template diff --git a/similar/main/newmenu.cpp b/similar/main/newmenu.cpp index 2c75f1f67..3d0644c28 100644 --- a/similar/main/newmenu.cpp +++ b/similar/main/newmenu.cpp @@ -1080,7 +1080,7 @@ static window_event_result newmenu_key_command(window *, const d_event &event, n rval = window_event_result::handled; } else { auto ascii = key_ascii(); - if ((ascii < 255 ) && (citem.value < citem.text_len )) + if (ascii < 255 && citem.value < citem.input_or_menu()->text_len) { if (citem.value == -1) { citem.value = 0; @@ -1282,10 +1282,11 @@ static void newmenu_create_structure( newmenu *menu ) i.right_offset = w1; } - if (i.type == NM_TYPE_INPUT || i.type == NM_TYPE_INPUT_MENU) + if (const auto input_or_menu = i.input_or_menu()) { i.saved_text.copy_if(i.text); - string_width = i.text_len * fspacx(8) + i.text_len; + const auto text_len = input_or_menu->text_len; + string_width = text_len * fspacx(8) + text_len; if (i.type == NM_TYPE_INPUT && string_width > MAX_TEXT_WIDTH) string_width = MAX_TEXT_WIDTH; diff --git a/similar/main/state.cpp b/similar/main/state.cpp index fe4ea3e02..83701723f 100644 --- a/similar/main/state.cpp +++ b/similar/main/state.cpp @@ -697,9 +697,10 @@ static int state_get_savegame_filename(char * fname, char * dsc, const char * ca if (dsc == NULL) m[i+1].type = NM_TYPE_TEXT; } if (dsc != NULL) { + auto &mi = m[i + 1]; m[i+1].type = NM_TYPE_INPUT_MENU; + mi.imenu().text_len = DESC_LENGTH - 1; } - m[i+1].text_len = DESC_LENGTH-1; m[i+1].text = desc[i]; }