From 98df700c84d4fb639527b9139b8f33d2669b938f Mon Sep 17 00:00:00 2001
From: Rob Swindell <rob@synchro.net>
Date: Sun, 1 Nov 2020 13:20:03 -0800
Subject: [PATCH] Add strip_ansi() function, expose as JS method

A function/method to strip all ANSI terminal control sequences from a string.
---
 src/sbbs3/js_global.c | 35 +++++++++++++++++++++++++++++++++++
 src/sbbs3/sbbs.h      |  1 +
 src/sbbs3/str_util.c  | 19 +++++++++++++++++++
 3 files changed, 55 insertions(+)

diff --git a/src/sbbs3/js_global.c b/src/sbbs3/js_global.c
index 2ee6631ea1..d98f931606 100644
--- a/src/sbbs3/js_global.c
+++ b/src/sbbs3/js_global.c
@@ -1115,6 +1115,37 @@ js_strip_ctrl(JSContext *cx, uintN argc, jsval *arglist)
 	return(JS_TRUE);
 }
 
+static JSBool
+js_strip_ansi(JSContext *cx, uintN argc, jsval *arglist)
+{
+	jsval *argv=JS_ARGV(cx, arglist);
+	char*		buf = NULL;
+	JSString*	js_str;
+	jsrefcount	rc;
+
+	JS_SET_RVAL(cx, arglist, JSVAL_VOID);
+
+	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+		return JS_TRUE;
+
+	JSVALUE_TO_MSTRING(cx, argv[0], buf, NULL)
+	HANDLE_PENDING(cx, buf);
+	if(buf==NULL) 
+		return JS_TRUE;
+
+	rc=JS_SUSPENDREQUEST(cx);
+	strip_ansi(buf);
+	JS_RESUMEREQUEST(cx, rc);
+
+	js_str = JS_NewStringCopyZ(cx, buf);
+	free(buf);
+	if(js_str==NULL)
+		return JS_FALSE;
+
+	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	return JS_TRUE;
+}
+
 static JSBool
 js_strip_exascii(JSContext *cx, uintN argc, jsval *arglist)
 {
@@ -4574,6 +4605,10 @@ static jsSyncMethodSpec js_global_functions[] = {
 	,JSDOCSTR("strip control characters from string, returns modified string")
 	,310
 	},		
+	{"strip_ansi",		js_strip_ansi,		1,	JSTYPE_STRING,	JSDOCSTR("text")
+	,JSDOCSTR("strip all ANSI terminal control sequences from string, returns modified string")
+	,31802
+	},		
 	{"strip_exascii",	js_strip_exascii,	1,	JSTYPE_STRING,	JSDOCSTR("text")
 	,JSDOCSTR("strip all extended-ASCII characters from string, returns modified string")
 	,310
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index c46e5cb6b1..db1111c679 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -1221,6 +1221,7 @@ extern "C" {
 	DLLEXPORT BOOL		trashcan(scfg_t* cfg, const char *insearch, const char *name);
 	DLLEXPORT char *	trashcan_fname(scfg_t* cfg, const char *name, char* fname, size_t);
 	DLLEXPORT str_list_t trashcan_list(scfg_t* cfg, const char* name);
+	DLLEXPORT char *	strip_ansi(char* str);
 	DLLEXPORT char *	strip_exascii(const char *str, char* dest);
 	DLLEXPORT char *	strip_space(const char *str, char* dest);
 	DLLEXPORT char *	prep_file_desc(const char *str, char* dest);
diff --git a/src/sbbs3/str_util.c b/src/sbbs3/str_util.c
index 61b5095507..8b170bdd65 100644
--- a/src/sbbs3/str_util.c
+++ b/src/sbbs3/str_util.c
@@ -89,6 +89,25 @@ char* strip_ctrl(const char *str, char* dest)
 	return dest;
 }
 
+char* strip_ansi(char* str)
+{
+	char* s = str;
+	char* d = str;
+	while(*s != '\0') {
+		if(*s == ESC && *(s + 1) == '[') {
+			s += 2;
+			while(*s != '\0' && (*s < '@' || *s > '~'))
+				s++;
+			if(*s != '\0') // Skip "final byte""
+				s++;
+		} else {
+			*(d++) = *(s++);
+		}
+	}
+	*d = '\0';
+	return str;
+}
+
 char* strip_exascii(const char *str, char* dest)
 {
 	int	i,j;
-- 
GitLab