From a9ef3e58f686ab95c49787616a4500e17304871d Mon Sep 17 00:00:00 2001
From: "Rob Swindell (on Windows 11)" <rob@synchro.net>
Date: Sun, 21 Jan 2024 15:01:23 -0800
Subject: [PATCH] Allow override of parameters to console.editfile()

For Nightfox and his newsgroup reader thing: The strings that end up in the editor drop file (e.g. MSGINF) can now be passed as optional arguments to consol.editfile() and the underlying C++ API.

Allow maxlines (default:10000) to be overridden with an optional consol.editfile() argument too.
---
 src/sbbs3/js_console.cpp | 72 +++++++++++++++++++++++++++++++---------
 src/sbbs3/sbbs.h         |  4 +--
 src/sbbs3/writemsg.cpp   | 21 ++++++++----
 3 files changed, 73 insertions(+), 24 deletions(-)

diff --git a/src/sbbs3/js_console.cpp b/src/sbbs3/js_console.cpp
index e6bc146c2d..e225cc8793 100644
--- a/src/sbbs3/js_console.cpp
+++ b/src/sbbs3/js_console.cpp
@@ -1608,27 +1608,69 @@ static JSBool
 js_editfile(JSContext *cx, uintN argc, jsval *arglist)
 {
 	jsval *argv=JS_ARGV(cx, arglist);
-    JSString*	str;
+    JSString*	js_str;
 	sbbs_t*		sbbs;
-	char*		cstr;
+	char*		path{nullptr};
+	char*		to{nullptr};
+	char*		from{nullptr};
+	char*		subj{nullptr};
+	char*		msgarea{nullptr};
+	int32		maxlines = 10000;
 	jsrefcount	rc;
+	JSBool		result = JS_TRUE;
 
 	if((sbbs=(sbbs_t*)js_GetClassPrivate(cx, JS_THIS_OBJECT(cx, arglist), &js_console_class))==NULL)
 		return(JS_FALSE);
 
-	JS_SET_RVAL(cx, arglist, JSVAL_VOID);
+	JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
 
-	if((str=JS_ValueToString(cx, argv[0]))==NULL)
-		return(JS_FALSE);
+	for (uintN i = 0; i < argc; ++i) {
+		if(JSVAL_IS_NUMBER(argv[i])) {
+			if(!JS_ValueToInt32(cx, argv[i], &maxlines))
+				return JS_FALSE;
+			continue;
+		}
+		if(JSVAL_IS_STRING(argv[i])) {
+			if((js_str = JS_ValueToString(cx, argv[i])) == NULL)
+				continue;
+			char* cstr;
+			JSSTRING_TO_MSTRING(cx, js_str, cstr, NULL);
+			if(cstr == nullptr)
+				continue;
+			if(path == nullptr)
+				path = cstr;
+			else if(to == nullptr)
+				to = cstr;
+			else if(from == nullptr)
+				from = cstr;
+			else if(subj == nullptr)
+				subj = cstr;
+			else if(msgarea == nullptr)
+				msgarea = cstr;
+			else {
+				JS_ReportError(cx, "Unsupported argument");
+				free(cstr);
+				result = JS_FALSE;
+			}
+			continue;
+		}
+	}
 
-	JSSTRING_TO_MSTRING(cx, str, cstr, NULL);
-	if(cstr==NULL)
-		return JS_FALSE;
-	rc=JS_SUSPENDREQUEST(cx);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->editfile(cstr)));
-	free(cstr);
-	JS_RESUMEREQUEST(cx, rc);
-    return(JS_TRUE);
+	if(path == nullptr) {
+		JS_ReportError(cx, "No filename specified");
+		result = JS_FALSE;
+	}
+	if (result == JS_TRUE) {
+		rc=JS_SUSPENDREQUEST(cx);
+		JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(sbbs->editfile(path, maxlines, to, from, subj, msgarea)));
+		JS_RESUMEREQUEST(cx, rc);
+	}
+	free(path);
+	free(to);
+	free(from);
+	free(subj);
+	free(msgarea);
+    return result;
 }
 
 
@@ -2599,8 +2641,8 @@ static jsSyncMethodSpec js_console_functions[] = {
 	,JSDOCSTR("Print the last <i>n</i> lines of file with optional print mode, original column width, and scope.")
 	,310
 	},
-	{"editfile",		js_editfile,		1, JSTYPE_BOOLEAN,		JSDOCSTR("filename")
-	,JSDOCSTR("Edit/create a text file using the user's preferred message editor")
+	{"editfile",		js_editfile,		1, JSTYPE_BOOLEAN,		JSDOCSTR("filename [,<i>number</i> maxlines=10000] [,<i>string</i> to] [,<i>string</i> from] [,<i>string</i> subject] [,<i>string</i> msg_area]")
+	,JSDOCSTR("Edit/create a text file using the user's preferred message editor with optional override values for the drop file created to communicate metadata to an external editor")
 	,310
 	},
 	{"uselect",			js_uselect,			0, JSTYPE_NUMBER,	JSDOCSTR("[<i>number</i> index, title, item] [,ars]")
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 2d20a8fec4..b954735288 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -798,12 +798,12 @@ public:
 	bool	forwardmsg(smb_t*, smbmsg_t*, const char* to, const char* subject = NULL, const char* comment = NULL);
 	void	removeline(char *str, char *str2, char num, char skip);
 	uint	msgeditor(char *buf, const char *top, char *title, uint max_lines, uint max_line_len);
-	bool	editfile(char *path, uint max_lines = 10000);
+	bool	editfile(char *path, uint max_lines = 10000, const char* to = NULL, const char* from = NULL, const char* subj = NULL, const char* msgarea = NULL);
 	ushort	chmsgattr(const smbmsg_t*);
 	bool	quotemsg(smb_t*, smbmsg_t*, bool tails = false);
 	bool	editmsg(smb_t*, smbmsg_t*);
 	void	editor_inf(int xeditnum, const char *to, const char* from, const char *subj, int mode
-				,int subnum, const char* tagfile);
+				,const char* msgarea, const char* tagfile = NULL);
 	bool	copyfattach(uint to, uint from, const char* subj);
 	bool	movemsg(smbmsg_t* msg, int subnum);
 	int		process_edited_text(char* buf, FILE* stream, int mode, unsigned* lines, unsigned maxlines);
diff --git a/src/sbbs3/writemsg.cpp b/src/sbbs3/writemsg.cpp
index 5fbe9cafbc..e9e35f11cb 100644
--- a/src/sbbs3/writemsg.cpp
+++ b/src/sbbs3/writemsg.cpp
@@ -589,7 +589,7 @@ bool sbbs_t::writemsg(const char *fname, const char *top, char *subj, int mode,
 				}
 			}
 		}
-		editor_inf(useron_xedit,to,from,subj,mode,subnum,tagfile);
+		editor_inf(useron_xedit,to,from,subj,mode,subnum==INVALID_SUB ? nulstr : cfg.sub[subnum]->sname, tagfile);
 		if(cfg.xedit[useron_xedit-1]->type) {
 			gettimeleft();
 			xtrndat(mode&WM_ANON ? text[Anonymous]:from,cfg.node_dir,cfg.xedit[useron_xedit-1]->type
@@ -822,7 +822,7 @@ void quotestr(char *str)
 /****************************************************************************/
 /****************************************************************************/
 void sbbs_t::editor_inf(int xeditnum, const char *to, const char* from, const char *subj, int mode
-	,int subnum, const char* tagfile)
+	,const char* msgarea, const char* tagfile)
 {
 	char	path[MAX_PATH+1];
 	FILE*	fp;
@@ -841,9 +841,7 @@ void sbbs_t::editor_inf(int xeditnum, const char *to, const char* from, const ch
 		fprintf(fp,"%s\r\n%s\r\n%s\r\n%u\r\n%s\r\n%s\r\n"
 			,mode&WM_ANON ? text[Anonymous]:from,to,subj,1
 			,mode&WM_NETMAIL ? "NetMail"
-				:mode&WM_EMAIL ? "Electronic Mail"
-					:subnum==INVALID_SUB ? nulstr
-						:cfg.sub[subnum]->sname
+				:mode&WM_EMAIL ? "Electronic Mail" : msgarea
 			,mode&WM_PRIVATE ? "YES":"NO");
 		/* the 7th line (the tag-line file) is a Synchronet extension, for SlyEdit */
 		if((mode&WM_EXTDESC)==0 && tagfile!=NULL)
@@ -1240,7 +1238,7 @@ uint sbbs_t::msgeditor(char *buf, const char *top, char *title, uint maxlines, u
 /****************************************************************************/
 /* Edits an existing file or creates a new one in MSG format                */
 /****************************************************************************/
-bool sbbs_t::editfile(char *fname, uint maxlines)
+bool sbbs_t::editfile(char *fname, uint maxlines, const char* to, const char* from, const char* subj, const char* msgarea)
 {
 	char *buf,path[MAX_PATH+1];
 	char msgtmp[MAX_PATH+1];
@@ -1262,6 +1260,15 @@ bool sbbs_t::editfile(char *fname, uint maxlines)
 	quotes_fname(useron_xedit, path, sizeof(path));
 	(void)removecase(path);
 
+	if(to == NULL)
+		to = fname;
+	if(from == NULL)
+		from = nulstr;
+	if(subj == NULL)
+		subj = nulstr;
+	if(msgarea == NULL)
+		msgarea = nulstr;
+
 	if(useron_xedit) {
 
 		SAFECOPY(path,fname);
@@ -1273,7 +1280,7 @@ bool sbbs_t::editfile(char *fname, uint maxlines)
 				CopyFile(path, msgtmp, /* failIfExists: */FALSE);
 		}
 
-		editor_inf(useron_xedit,/* to: */fname,/* from: */nulstr,/* subj: */nulstr,/* mode: */0,INVALID_SUB,/* tagfile: */NULL);
+		editor_inf(useron_xedit, to, from, subj, /* mode: */0, msgarea);
 		if(cfg.xedit[useron_xedit-1]->misc&XTRN_NATIVE)
 			mode|=EX_NATIVE;
 		if(cfg.xedit[useron_xedit-1]->misc&XTRN_SH)
-- 
GitLab