From 192dea0e154b1f2d6f7ba2ffcf20a2fa2aeffc46 Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Fri, 8 May 2020 19:18:15 +0000
Subject: [PATCH] A more convenient method of creating mouse hot spots in a
 display (e.g. menu) file: New "HOT:<attr>" @-code allows you to define a
 specific combination of attributes (colors) that will be used to exclusively
 create clickable command keys or words in a file. Every set of charcters in
 the display file that uses that specific combination of attributes will
 become an automatic mouse hot spot. The <attr> is specified using a set of
 attribte mnemonics (e.g. "YH" for high-intensity yellow), the same set used
 in attr.cfg and other places in sbbs.

This allows more WYSIWYG style menu editing (e.g. use PabloDraw), you just need to be careful with your choice of colors. You cannot send white-space or control characters with this method and the clickable text is the exact text that will be put in the keyboard buffer.
---
 src/sbbs3/atcodes.cpp |  5 +++++
 src/sbbs3/main.cpp    |  1 +
 src/sbbs3/putmsg.cpp  | 14 ++++++++++++++
 src/sbbs3/sbbs.h      |  1 +
 4 files changed, 21 insertions(+)

diff --git a/src/sbbs3/atcodes.cpp b/src/sbbs3/atcodes.cpp
index 193490e7fc..bd28d88ce8 100644
--- a/src/sbbs3/atcodes.cpp
+++ b/src/sbbs3/atcodes.cpp
@@ -253,6 +253,11 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode, bool
 		return sp;
 	}
 
+	if(strncmp(sp, "HOT:", 4) == 0) {	// Auto-mouse hot-spot attribute
+		hot_attr = attrstr(sp + 4);
+		return nulstr;
+	}
+
 	if(strncmp(sp, "U+", 2) == 0) {	// UNICODE
 		enum unicode_codepoint codepoint = (enum unicode_codepoint)strtoul(sp + 2, &tp, 16);
 		if(tp == NULL || *tp == 0)
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index c9f6950952..6e5b6a7fb1 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -3400,6 +3400,7 @@ sbbs_t::sbbs_t(ushort node_num, union xp_sockaddr *addr, size_t addr_len, const
 	tabstop=8;
 	lastlinelen=0;
 	curatr=LIGHTGRAY;
+	hot_attr = 0;
 	attr_sp=0;	/* attribute stack pointer */
 	errorlevel=0;
 	logcol=1;
diff --git a/src/sbbs3/putmsg.cpp b/src/sbbs3/putmsg.cpp
index 6db3365137..7b17626ce3 100644
--- a/src/sbbs3/putmsg.cpp
+++ b/src/sbbs3/putmsg.cpp
@@ -61,7 +61,9 @@ char sbbs_t::putmsg(const char *buf, long mode, long org_cols, JSObject* obj)
 	ulong	l=0,sys_status_sav=sys_status;
 	uint	lines_printed = 0;
 	enum output_rate output_rate = cur_output_rate;
+	struct mouse_hotspot hot_spot = {0};
 
+	hot_attr = 0;
 	attr_sp=0;	/* clear any saved attributes */
 	tmpatr=curatr;	/* was lclatr(-1) */
 	if(!(mode&P_SAVEATR))
@@ -375,6 +377,18 @@ char sbbs_t::putmsg(const char *buf, long mode, long org_cols, JSObject* obj)
 			}
 			if(mode&P_CPM_EOF && str[l]==CTRL_Z)
 				break;
+			if(hot_attr) {
+				if(curatr == hot_attr && str[l] > ' ') {
+					hot_spot.y = row;
+					if(!hot_spot.minx)
+						hot_spot.minx = column;
+					hot_spot.maxx = column;
+					hot_spot.cmd[strlen(hot_spot.cmd)] = str[l];
+				} else if(hot_spot.cmd[0]) {
+					add_hotspot(&hot_spot);
+					memset(&hot_spot, 0, sizeof(hot_spot));
+				}
+			}
 			size_t skip = sizeof(char);
 			if(mode&P_PETSCII) {
 				if(term&PETSCII)
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 9b385a77cb..8b3059e76a 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -464,6 +464,7 @@ public:
 	time_t 	timeout;		/* User inactivity timeout reference */
 	ulong 	timeleft_warn;	/* low timeleft warning flag */
 	uint	curatr; 		/* Current Text Attributes Always */
+	uint	hot_attr;		/* Auto-Mouse hot-spot attribute (when non-zero) */
 	uint	attr_stack[64];	/* Saved attributes (stack) */
 	int 	attr_sp;		/* Attribute stack pointer */
 	long 	lncntr; 		/* Line Counter - for PAUSE */
-- 
GitLab