From 3eded06669b09db2abf610efc4feecf32c4c8d0b Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 14 Sep 2018 17:34:33 -0700 Subject: [PATCH] fix #H7156 - perm_invent Bug report #H7156 listed three items, all relating to perm_invent: 1) it shouldn't persist across save/restore since restore might be on a system which doesn't have enough room to display it (report actually complained that config file setting was ignored when restoring old games, which is an expected side-effect for options that persist across save/restore); 2) permanent inventory wasn't updated when using scroll of charging; 3) attempts to update permanent inventory during restore could lead to crash if it tries to access shop cost for unpaid items. Items (2) and (3) have already been fixed. This fixes (1). Replace 'flags.perm_invent' with a dummy flag, preserving save files while removing it from flags. Add 'iflags.perm_invent' to hold the value of the perm_invent option. The win32 files that are updated here haven't been tested. Whichever branch contains the curses interface needs to be updated; ditto for any other pending/potential interfaces which support perm_invent. --- doc/Guidebook.mn | 1 - doc/Guidebook.tex | 1 - doc/fixes36.2 | 2 ++ include/flag.h | 3 ++- src/end.c | 2 +- src/invent.c | 6 +++--- src/options.c | 3 ++- src/restore.c | 12 ++++++++---- win/X11/winmenu.c | 2 +- win/win32/mhmain.c | 4 ++-- win/win32/mhmenu.c | 6 +++--- win/win32/mswproc.c | 6 +++--- 12 files changed, 27 insertions(+), 21 deletions(-) diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index e1db1cd85..151b25f5a 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -3004,7 +3004,6 @@ such as ``paranoid_confirmation:attack pray Remove''. .lp perm_invent If true, always display your current inventory in a window. This only makes sense for windowing system interfaces that implement this feature. -Persistent. .lp pettype Specify the type of your initial pet, if you are playing a character class that uses multiple types of pets; or choose to have no initial pet at all. diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 7cc9b7de6..4d3352d84 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -3501,7 +3501,6 @@ such as ``{\it par\-a\-noid\verb+_+con\-fir\-ma\-tion:attack~pray~Remove}''. \item[\ib{perm\verb+_+invent}] If true, always display your current inventory in a window. This only makes sense for windowing system interfaces that implement this feature. -Persistent. %.lp \item[\ib{pettype}] Specify the type of your initial pet, if you are playing a character class diff --git a/doc/fixes36.2 b/doc/fixes36.2 index a8202713e..3454dda9e 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -136,6 +136,8 @@ tty: ensure that current status fields are always copied to prior status Platform- and/or Interface-Specific Fixes ----------------------------------------- +move 'perm_invent' value from flags to iflags to keep it out of save files; + affects X11, win32, and curses windows-gui: In nethackw, there could be conflicts between menu accelerators and an extra choice accelerator to fix H7132. windows-gui: recognize new BL_RESET in status_update; no change in behavior yet diff --git a/include/flag.h b/include/flag.h index 8d386decf..f2339f6c0 100644 --- a/include/flag.h +++ b/include/flag.h @@ -40,7 +40,7 @@ struct flag { boolean lit_corridor; /* show a dark corr as lit if it is in sight */ boolean nap; /* `timed_delay' option for display effects */ boolean null; /* OK to send nulls to the terminal */ - boolean perm_invent; /* keep full inventories up until dismissed */ + boolean p__obsolete; /* [3.6.2: perm_invent moved to iflags] */ boolean pickup; /* whether you pickup or move and look */ boolean pickup_thrown; /* auto-pickup items you threw */ boolean pushweapon; /* When wielding, push old weapon into second slot */ @@ -292,6 +292,7 @@ struct instance_flags { boolean menu_tab_sep; /* Use tabs to separate option menu fields */ boolean news; /* print news */ boolean num_pad; /* use numbers for movement commands */ + boolean perm_invent; /* keep full inventories up until dismissed */ boolean renameallowed; /* can change hero name during role selection */ boolean renameinprogress; /* we are changing hero name */ boolean status_updates; /* allow updates to bottom status lines; diff --git a/src/end.c b/src/end.c index 4d176323b..fd5d73db9 100644 --- a/src/end.c +++ b/src/end.c @@ -1280,7 +1280,7 @@ int how; if (WIN_INVEN != WIN_ERR) { destroy_nhwindow(WIN_INVEN), WIN_INVEN = WIN_ERR; /* precaution in case any late update_inventory() calls occur */ - flags.perm_invent = 0; + iflags.perm_invent = 0; } display_nhwindow(WIN_MESSAGE, TRUE); destroy_nhwindow(WIN_MAP), WIN_MAP = WIN_ERR; diff --git a/src/invent.c b/src/invent.c index 25280839b..4262a5153 100644 --- a/src/invent.c +++ b/src/invent.c @@ -2511,7 +2511,7 @@ long *out_cnt; if (lets && !*lets) lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */ - if (flags.perm_invent && (lets || xtra_choice)) { + if (iflags.perm_invent && (lets || xtra_choice)) { /* partial inventory in perm_invent setting; don't operate on full inventory window, use an alternate one instead; create the first time needed and keep it for re-use as needed later */ @@ -2536,7 +2536,7 @@ long *out_cnt; * more than 1; for the last one, we don't need a precise number. * For perm_invent update we force 'more than 1'. */ - n = (flags.perm_invent && !lets && !want_reply) ? 2 + n = (iflags.perm_invent && !lets && !want_reply) ? 2 : lets ? (int) strlen(lets) : !invent ? 0 : !invent->nobj ? 1 : 2; /* for xtra_choice, there's another 'item' not included in initial 'n'; @@ -2670,7 +2670,7 @@ nextclass: nothing has been listed (because there isn't anyhing to list; recognized via any.a_char still being zero; the n==0 case above gets skipped for perm_invent), put something into the menu */ - if (flags.perm_invent && !lets && !any.a_char) { + if (iflags.perm_invent && !lets && !any.a_char) { any = zeroany; add_menu(win, NO_GLYPH, &any, 0, 0, 0, not_carrying_anything, MENU_UNSELECTED); diff --git a/src/options.c b/src/options.c index a283f4283..490d68a0a 100644 --- a/src/options.c +++ b/src/options.c @@ -173,7 +173,8 @@ static struct Bool_Opt { #else { "page_wait", (boolean *) 0, FALSE, SET_IN_FILE }, #endif - { "perm_invent", &flags.perm_invent, FALSE, SET_IN_GAME }, + /* 3.6.2: move perm_invent from flags to inflags and out of save file */ + { "perm_invent", &iflags.perm_invent, FALSE, SET_IN_GAME }, { "pickup_thrown", &flags.pickup_thrown, TRUE, SET_IN_GAME }, { "popup_dialog", &iflags.wc_popup_dialog, FALSE, SET_IN_GAME }, /*WC*/ { "preload_tiles", &iflags.wc_preload_tiles, TRUE, DISP_IN_GAME }, /*WC*/ diff --git a/src/restore.c b/src/restore.c index f7e92da76..f638875b8 100644 --- a/src/restore.c +++ b/src/restore.c @@ -543,9 +543,12 @@ unsigned int *stuckid, *steedid; /* avoid keeping permanent inventory window up to date during restore (setworn() calls update_inventory); attempting to include the cost of unpaid items before shopkeeper's bill is available is a no-no; - named fruit names aren't accessible yet either */ - defer_perm_invent = flags.perm_invent; - flags.perm_invent = FALSE; + named fruit names aren't accessible yet either + [3.6.2: moved perm_invent from flags to iflags to keep it out of + save files; retaining the override here is simpler than trying to + to figure out where it really belongs now] */ + defer_perm_invent = iflags.perm_invent; + iflags.perm_invent = FALSE; /* wizard and discover are actually flags.debug and flags.explore; player might be overriding the save file values for them; in the discover case, we don't want to set that for a normal @@ -595,6 +598,7 @@ unsigned int *stuckid, *steedid; u.uz.dlevel = 1; /* revert to pre-restore option settings */ iflags.deferred_X = FALSE; + iflags.perm_invent = defer_perm_invent; flags = newgameflags; #ifdef SYSFLAGS sysflags = newgamesysflags; @@ -672,7 +676,7 @@ unsigned int *stuckid, *steedid; relink_timers(FALSE); relink_light_sources(FALSE); /* inventory display is now viable */ - flags.perm_invent = defer_perm_invent; + iflags.perm_invent = defer_perm_invent; return TRUE; } diff --git a/win/X11/winmenu.c b/win/X11/winmenu.c index 75c99b57a..a3287737c 100644 --- a/win/X11/winmenu.c +++ b/win/X11/winmenu.c @@ -826,7 +826,7 @@ menu_item **menu_list; * each time. */ if (menu_info->valid_widgets - && (window != WIN_INVEN || !flags.perm_invent)) { + && (window != WIN_INVEN || !iflags.perm_invent)) { XtDestroyWidget(wp->popup); menu_info->valid_widgets = FALSE; menu_info->is_up = FALSE; diff --git a/win/win32/mhmain.c b/win/win32/mhmain.c index 6c6bfea7d..41e7733fa 100644 --- a/win/win32/mhmain.c +++ b/win/win32/mhmain.c @@ -700,7 +700,7 @@ mswin_layout_main_window(HWND changed_child) GetNHApp()->rtInvenWindow.bottom = GetNHApp()->rtMenuWindow.bottom; /* adjust map window size only if perm_invent is set */ - if (flags.perm_invent) + if (iflags.perm_invent) GetNHApp()->rtMapWindow.right = GetNHApp()->rtMenuWindow.left; } @@ -712,7 +712,7 @@ mswin_layout_main_window(HWND changed_child) /* kludge - inventory window should have its own type (same as menu-text as a matter of fact) */ - if (flags.perm_invent && i == WIN_INVEN) { + if (iflags.perm_invent && i == WIN_INVEN) { mswin_get_window_placement(NHW_INVEN, &rt); } else { mswin_get_window_placement(GetNHApp()->windowlist[i].type, diff --git a/win/win32/mhmenu.c b/win/win32/mhmenu.c index c8d71b4e6..6b0b4fda2 100644 --- a/win/win32/mhmenu.c +++ b/win/win32/mhmenu.c @@ -251,7 +251,7 @@ mswin_menu_window_select_menu(HWND hWnd, int how, MENU_ITEM_P **_selected, /* If we just used the permanent inventory window to pick something, * set the menu back to its display inventory state. */ - if (flags.perm_invent && mswin_winid_from_handle(hWnd) == WIN_INVEN + if (iflags.perm_invent && mswin_winid_from_handle(hWnd) == WIN_INVEN && how != PICK_NONE) { data->menu.prompt[0] = '\0'; SetMenuListType(hWnd, PICK_NONE); @@ -322,7 +322,7 @@ MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) GetWindowRect(hWnd, &rt); ScreenToClient(GetNHApp()->hMainWnd, (LPPOINT) &rt); ScreenToClient(GetNHApp()->hMainWnd, ((LPPOINT) &rt) + 1); - if (flags.perm_invent && mswin_winid_from_handle(hWnd) == WIN_INVEN) + if (iflags.perm_invent && mswin_winid_from_handle(hWnd) == WIN_INVEN) mswin_update_window_placement(NHW_INVEN, &rt); else mswin_update_window_placement(NHW_MENU, &rt); @@ -334,7 +334,7 @@ MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) GetWindowRect(hWnd, &rt); ScreenToClient(GetNHApp()->hMainWnd, (LPPOINT) &rt); ScreenToClient(GetNHApp()->hMainWnd, ((LPPOINT) &rt) + 1); - if (flags.perm_invent && mswin_winid_from_handle(hWnd) == WIN_INVEN) + if (iflags.perm_invent && mswin_winid_from_handle(hWnd) == WIN_INVEN) mswin_update_window_placement(NHW_INVEN, &rt); else mswin_update_window_placement(NHW_MENU, &rt); diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index feabf49b2..ce9b14d5f 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -1194,7 +1194,7 @@ mswin_select_menu(winid wid, int how, MENU_ITEM_P **selected) ShowWindow(GetNHApp()->windowlist[wid].win, SW_SHOW); nReturned = mswin_menu_window_select_menu( GetNHApp()->windowlist[wid].win, how, selected, - !(flags.perm_invent && wid == WIN_INVEN + !(iflags.perm_invent && wid == WIN_INVEN && how == PICK_NONE) /* don't activate inventory window if perm_invent is on */ ); @@ -1211,7 +1211,7 @@ void mswin_update_inventory() { logDebug("mswin_update_inventory()\n"); - if (flags.perm_invent && program_state.something_worth_saving + if (iflags.perm_invent && program_state.something_worth_saving && iflags.window_inited && WIN_INVEN != WIN_ERR) display_inventory(NULL, FALSE); } @@ -2243,7 +2243,7 @@ mswin_popup_destroy(HWND hWnd) DrawMenuBar(GetNHApp()->hMainWnd); /* Don't hide the permanent inventory window ... leave it showing */ - if (!flags.perm_invent || mswin_winid_from_handle(hWnd) != WIN_INVEN) + if (!iflags.perm_invent || mswin_winid_from_handle(hWnd) != WIN_INVEN) ShowWindow(hWnd, SW_HIDE); GetNHApp()->hPopupWnd = NULL;