From 1c85a913ca99a8897a164f7d1158f4f5157fd7a6 Mon Sep 17 00:00:00 2001
From: "Rob Swindell (on Debian Linux)" <rob@synchro.net>
Date: Fri, 21 Jun 2024 00:10:23 -0700
Subject: [PATCH] Introduce a restore() uifc_api method for restoring a saved
 window buffer

This allows for menu options on an "active" list (with both WIN_SAVE and
WIN_ACT mode flags) to close the window and restore the most recently saved
window.

Also, for the range check on the save buffer count in ulist(), if we've
hit the bounds, don't *just* beep (though, that was useful), but turn off the
WIN_SAV mode flag so we don't overflow the sav[] array and corrupt the heap!
---
 src/uifc/uifc.h   | 10 +++++---
 src/uifc/uifc32.c | 62 +++++++++++++++++++----------------------------
 2 files changed, 31 insertions(+), 41 deletions(-)

diff --git a/src/uifc/uifc.h b/src/uifc/uifc.h
index cba55f346d..4e048f1f0e 100644
--- a/src/uifc/uifc.h
+++ b/src/uifc/uifc.h
@@ -355,10 +355,6 @@ typedef struct {
 /****************************************************************************/
     uint    savnum;
 /****************************************************************************/
-/* The current overlapped-window save buffer depth.							*/
-/****************************************************************************/
-    uint    savdepth;
-/****************************************************************************/
 /* Screen length															*/
 /****************************************************************************/
     uint    scrn_len;
@@ -458,6 +454,12 @@ typedef struct {
     int     (*list) (uifc_winmode_t, int left, int top, int width, int* dflt
                         ,int* bar, const char *title, char** option);
 /****************************************************************************/
+/* Restore last saved window buffer (using WIN_SAV mode)					*/
+/* Decrements save_num if non-zero.											*/
+/* Can be used to return from a nested-list (with WIN_SAV) without ESC key.	*/
+/****************************************************************************/
+	BOOL	(*restore)(void);
+/****************************************************************************/
 /* Windowed string input routine.											*/
 /* mode contains WIN_* flags to control display and functionality.			*/
 /* left and top specify desired screen location.							*/
diff --git a/src/uifc/uifc32.c b/src/uifc/uifc32.c
index 9dedd4a0d7..459b0d3e68 100644
--- a/src/uifc/uifc32.c
+++ b/src/uifc/uifc32.c
@@ -75,6 +75,7 @@ static void upop(const char *str);
 static void sethelp(int line, char* file);
 static void showbuf(uifc_winmode_t, int left, int top, int width, int height, const char *title
 	, const char *hbuf, int *curp, int *barp);
+static BOOL restore(void);
 
 /* Dynamic menu support */
 static int *last_menu_cur=NULL;
@@ -229,6 +230,7 @@ int uifcini32(uifcapi_t* uifcapi)
 	api->deny=deny;
     api->pop=upop;
     api->list=ulist;
+	api->restore=restore;
     api->input=uinput;
     api->sethelp=sethelp;
     api->showhelp=help;
@@ -370,6 +372,20 @@ int uifcini32(uifcapi_t* uifcapi)
     return(0);
 }
 
+static BOOL restore(void)
+{
+	if(api->savnum < 1)
+		return FALSE;
+	if(sav[api->savnum - 1].buf == NULL)
+		return FALSE;
+	--api->savnum;
+	vmem_puttext(sav[api->savnum].left,sav[api->savnum].top
+		,sav[api->savnum].right,sav[api->savnum].bot
+		,sav[api->savnum].buf);
+	FREE_AND_NULL(sav[api->savnum].buf);
+	return TRUE;
+}
+
 void docopy(void)
 {
 	int	key;
@@ -698,8 +714,10 @@ int ulist(uifc_winmode_t mode, int left, int top, int width, int *cur, int *bar
 		opts++;
 
 	/* Sanity-check the savnum */
-	if(mode&WIN_SAV && api->savnum>=MAX_BUFS-1)
+	if(mode&WIN_SAV && api->savnum>=MAX_BUFS-1) {
 		putch(7);
+		mode &= ~WIN_SAV;
+	}
 
 	api->help_available = (api->helpbuf!=NULL || api->helpixbfile[0]!=0);
 
@@ -1154,16 +1172,11 @@ int ulist(uifc_winmode_t mode, int left, int top, int width, int *cur, int *bar
 								uifc_mouse_enable();
 						}
 						else if(mode&WIN_SAV) {
-							api->savnum--;
 							if(!(api->mode&UIFC_NHM))
 								uifc_mouse_disable();
-							if(sav[api->savnum].buf != NULL)
-								vmem_puttext(sav[api->savnum].left,sav[api->savnum].top
-									,sav[api->savnum].right,sav[api->savnum].bot
-									,sav[api->savnum].buf);
+							restore();
 							if(!(api->mode&UIFC_NHM))
 								uifc_mouse_enable();
-							FREE_AND_NULL(sav[api->savnum].buf);
 						}
 						if(mode&WIN_XTR && (*cur)==opts-1)
 							return(MSK_INS|*cur);
@@ -1578,12 +1591,7 @@ int ulist(uifc_winmode_t mode, int left, int top, int width, int *cur, int *bar
 							if(mode&WIN_ACT)
 								inactive_win(tmp_buffer, s_left+left, s_top+top, s_left+left+width-1, s_top+top+height-1, y, hbrdrsize, cclr, lclr, hclr, top);
 							else if(mode&WIN_SAV) {
-								api->savnum--;
-								if(sav[api->savnum].buf != NULL)
-									vmem_puttext(sav[api->savnum].left,sav[api->savnum].top
-										,sav[api->savnum].right,sav[api->savnum].bot
-										,sav[api->savnum].buf);
-								FREE_AND_NULL(sav[api->savnum].buf);
+								restore();
 							}
 							return((*cur)|MSK_EDIT);
 						}
@@ -1609,12 +1617,7 @@ int ulist(uifc_winmode_t mode, int left, int top, int width, int *cur, int *bar
 							if(mode&WIN_INSACT)
 								inactive_win(tmp_buffer, s_left+left,s_top+top,s_left+left+width-1,s_top+top+height-1,y, hbrdrsize, cclr, lclr, hclr, top);
 							else if(mode&WIN_SAV) {
-								api->savnum--;
-								if(sav[api->savnum].buf != NULL)
-									vmem_puttext(sav[api->savnum].left,sav[api->savnum].top
-										,sav[api->savnum].right,sav[api->savnum].bot
-										,sav[api->savnum].buf);
-								FREE_AND_NULL(sav[api->savnum].buf);
+								restore();
 							}
 							if(!opts) {
 								return(MSK_INS);
@@ -1631,12 +1634,7 @@ int ulist(uifc_winmode_t mode, int left, int top, int width, int *cur, int *bar
 							if(mode&WIN_DELACT)
 								inactive_win(tmp_buffer, s_left+left, s_top+top, s_left+left+width-1, s_top+top+height-1, y, hbrdrsize, cclr, lclr, hclr, top);
 							else if(mode&WIN_SAV) {
-								api->savnum--;
-								if (sav[api->savnum].buf != NULL)
-									vmem_puttext(sav[api->savnum].left,sav[api->savnum].top
-										,sav[api->savnum].right,sav[api->savnum].bot
-										,sav[api->savnum].buf);
-								FREE_AND_NULL(sav[api->savnum].buf);
+								restore();
 							}
 							return((*cur)|MSK_DEL);
 						}
@@ -1758,12 +1756,7 @@ int ulist(uifc_winmode_t mode, int left, int top, int width, int *cur, int *bar
 							if(mode&WIN_ACT)
 								inactive_win(tmp_buffer, s_left+left, s_top+top, s_left+left+width-1, s_top+top+height-1, y, hbrdrsize, cclr, lclr, hclr, top);
 							else if(mode&WIN_SAV) {
-								api->savnum--;
-								if (sav[api->savnum].buf != NULL)
-									vmem_puttext(sav[api->savnum].left,sav[api->savnum].top
-										,sav[api->savnum].right,sav[api->savnum].bot
-										,sav[api->savnum].buf);
-								FREE_AND_NULL(sav[api->savnum].buf);
+								restore();
 							}
 							if(mode&WIN_XTR && (*cur)==opts-1)
 								return(MSK_INS|*cur);
@@ -1781,12 +1774,7 @@ int ulist(uifc_winmode_t mode, int left, int top, int width, int *cur, int *bar
 									+left+width-1,s_top+top+height-1,tmp_buffer);
 							}
 							else if(mode&WIN_SAV) {
-								api->savnum--;
-								if (sav[api->savnum].buf != NULL)
-									vmem_puttext(sav[api->savnum].left,sav[api->savnum].top
-										,sav[api->savnum].right,sav[api->savnum].bot
-										,sav[api->savnum].buf);
-								FREE_AND_NULL(sav[api->savnum].buf);
+								restore();
 							}
 							return(-1);
 						case CTRL_F:			/* find */
-- 
GitLab