From 0324ddac50699ad21e390f67bbf457a6c7314fbd Mon Sep 17 00:00:00 2001
From: "Rob Swindell (on Windows)" <rob@synchro.net>
Date: Tue, 5 Sep 2023 16:58:50 -0700
Subject: [PATCH] Update File Options "paste" behavior to use insert-above
 instead of overwrite

To be more consistent with the paste key behavior elsewhere in SCFG,
make the file options (Viewable Files, Testable Files, Download Events,
Extractable Files, Compressible Files, and Transfer Protocols) menus handle
paste (Ctrl-V, F6) key by inserting the copied or cut item above the current
selection rather than overwriting the current selection.

Fixes issue #616
---
 src/sbbs3/scfg/scfg.c     | 17 ++++++++++++++++
 src/sbbs3/scfg/scfg.h     |  1 +
 src/sbbs3/scfg/scfgxfr1.c | 42 +++++++++++++++++++++++++++++++++------
 3 files changed, 54 insertions(+), 6 deletions(-)

diff --git a/src/sbbs3/scfg/scfg.c b/src/sbbs3/scfg/scfg.c
index 9e5d2e73d6..35408d0eec 100644
--- a/src/sbbs3/scfg/scfg.c
+++ b/src/sbbs3/scfg/scfg.c
@@ -2436,6 +2436,23 @@ int lprintf(int level, char *fmt, ...)
     return(0);
 }
 
+void** new_item(void* list[], size_t size, int index, int* total)
+{
+	void** p;
+	void* item;
+
+	if((item = calloc(size, 1)) == NULL)
+		return NULL;
+	if((p = realloc(list, size * ((*total) + 1))) == NULL)
+		return NULL;
+	list = p;
+	for(int i = *total; i > index; --i)
+		list[i] = list[i - 1];
+	list[index] = item;
+	++(*total);
+	return list;
+}
+
 void bail(int code)
 {
     if(code) {
diff --git a/src/sbbs3/scfg/scfg.h b/src/sbbs3/scfg/scfg.h
index 65683b35d2..60bedcc07d 100644
--- a/src/sbbs3/scfg/scfg.h
+++ b/src/sbbs3/scfg/scfg.h
@@ -163,6 +163,7 @@ void reencrypt_keys(const char* old_pass, const char* new_pass);
 int code_ok(char *str);
 int  bits(long l);
 void getar(char *desc, char *ar);
+void** new_item(void* list[], size_t size, int index, int* total);
 bool new_sub(int new_subnum, int group_num, sub_t* pasted_sub, long misc);
 bool new_qhub_sub(qhub_t*, int qsubnum, sub_t*, unsigned confnum);
 void remove_sub(scfg_t*, int subnum, bool cut);
diff --git a/src/sbbs3/scfg/scfgxfr1.c b/src/sbbs3/scfg/scfgxfr1.c
index 1812cc9b6b..6aef937571 100644
--- a/src/sbbs3/scfg/scfgxfr1.c
+++ b/src/sbbs3/scfg/scfgxfr1.c
@@ -338,7 +338,7 @@ void xfer_opts()
 					if(cfg.total_fviews)
 						i|=WIN_DEL|WIN_COPY|WIN_CUT;
 					if(savfview.cmd[0])
-						i|=WIN_PASTE;
+						i|=WIN_PASTE | WIN_PASTEXTR;
 					uifc.helpbuf=
 						"`Viewable File Types:`\n"
 						"\n"
@@ -409,6 +409,11 @@ void xfer_opts()
 						continue;
 					}
 					if(msk == MSK_PASTE) {
+						if((cfg.fview = (fview_t**)new_item(cfg.fview, sizeof(fview_t), i, &cfg.total_fviews)) == NULL) {
+							errormsg(WHERE, ERR_ALLOC, "fviews", sizeof(fview_t) * (cfg.total_fviews + 1));
+							cfg.total_fviews = 0;
+							bail(1);
+						}
 						*cfg.fview[i]=savfview;
 						uifc.changes=1;
 						continue;
@@ -474,7 +479,7 @@ void xfer_opts()
 					if(cfg.total_ftests)
 						i|=WIN_DEL|WIN_COPY|WIN_CUT;
 					if(savftest.cmd[0])
-						i|=WIN_PASTE;
+						i|=WIN_PASTE | WIN_PASTEXTR;
 					uifc.helpbuf = testable_files_help;
 					i=uifc.list(i,0,0,50,&ftest_dflt,&ftest_bar,"Testable File Types",opt);
 					if(i==-1)
@@ -536,6 +541,11 @@ void xfer_opts()
 						continue;
 					}
 					if(msk == MSK_PASTE) {
+						if((cfg.ftest = (ftest_t**)new_item(cfg.ftest, sizeof(ftest_t), i, &cfg.total_ftests)) == NULL) {
+							errormsg(WHERE, ERR_ALLOC, "ftests", sizeof(ftest_t) * (cfg.total_ftests + 1));
+							cfg.total_ftests = 0;
+							bail(1);
+						}
 						*cfg.ftest[i]=savftest;
 						uifc.changes=1;
 						continue;
@@ -608,7 +618,7 @@ void xfer_opts()
 					if(cfg.total_dlevents)
 						i|=WIN_DEL|WIN_COPY|WIN_CUT;
 					if(savdlevent.cmd[0])
-						i|=WIN_PASTE;
+						i|=WIN_PASTE | WIN_PASTEXTR;
 					uifc.helpbuf=
 						"`Download Events:`\n"
 						"\n"
@@ -685,6 +695,11 @@ void xfer_opts()
 						continue;
 					}
 					if(msk == MSK_PASTE) {
+						if((cfg.dlevent = (dlevent_t**)new_item(cfg.dlevent, sizeof(dlevent_t), i, &cfg.total_dlevents)) == NULL) {
+							errormsg(WHERE, ERR_ALLOC, "dlevents", sizeof(dlevent_t) * (cfg.total_dlevents + 1));
+							cfg.total_dlevents = 0;
+							bail(1);
+						}
 						*cfg.dlevent[i]=savdlevent;
 						uifc.changes=1;
 						continue;
@@ -757,7 +772,7 @@ void xfer_opts()
 					if(cfg.total_fextrs)
 						i|=WIN_DEL|WIN_COPY|WIN_CUT;
 					if(savfextr.cmd[0])
-						i|=WIN_PASTE;
+						i|=WIN_PASTE | WIN_PASTEXTR;
 					uifc.helpbuf=
 						"`Extractable File Types:`\n"
 						"\n"
@@ -826,6 +841,11 @@ void xfer_opts()
 						continue;
 					}
 					if(msk == MSK_PASTE) {
+						if((cfg.fextr = (fextr_t**)new_item(cfg.fextr, sizeof(fextr_t), i, &cfg.total_fextrs)) == NULL) {
+							errormsg(WHERE, ERR_ALLOC, "fextrs", sizeof(fextr_t) * (cfg.total_fextrs + 1));
+							cfg.total_fextrs = 0;
+							bail(1);
+						}
 						*cfg.fextr[i]=savfextr;
 						uifc.changes=1;
 						continue;
@@ -891,7 +911,7 @@ void xfer_opts()
 					if(cfg.total_fcomps)
 						i|=WIN_DEL|WIN_COPY|WIN_CUT;
 					if(savfcomp.cmd[0])
-						i|=WIN_PASTE;
+						i|=WIN_PASTE | WIN_PASTEXTR;
 					uifc.helpbuf=
 						"`Compressible File Types:`\n"
 						"\n"
@@ -959,6 +979,11 @@ void xfer_opts()
 						continue;
 					}
 					if(msk == MSK_PASTE) {
+						if((cfg.fcomp = (fcomp_t**)new_item(cfg.fcomp, sizeof(fcomp_t), i, &cfg.total_fcomps)) == NULL) {
+							errormsg(WHERE, ERR_ALLOC, "fcomps", sizeof(fcomp_t) * (cfg.total_fcomps + 1));
+							cfg.total_fcomps = 0;
+							bail(1);
+						}
 						*cfg.fcomp[i]=savfcomp;
 						uifc.changes=1;
 						continue;
@@ -1025,7 +1050,7 @@ void xfer_opts()
 					if(cfg.total_prots)
 						wmode |= WIN_DEL|WIN_COPY|WIN_CUT;
 					if(savprot.mnemonic)
-						wmode |= WIN_PASTE;
+						wmode |= WIN_PASTE | WIN_PASTEXTR;
 					uifc.helpbuf=
 						"`File Transfer Protocols:`\n"
 						"\n"
@@ -1096,6 +1121,11 @@ void xfer_opts()
 						continue;
 					}
 					if(msk == MSK_PASTE) {
+						if((cfg.prot = (prot_t**)new_item(cfg.prot, sizeof(prot_t), i, &cfg.total_prots)) == NULL) {
+							errormsg(WHERE, ERR_ALLOC, "prots", sizeof(prot_t) * (cfg.total_prots + 1));
+							cfg.total_prots=0;
+							bail(1);
+						}
 						*cfg.prot[i]=savprot;
 						uifc.changes=1;
 						continue;
-- 
GitLab