From 2e944449a7b944d3a8ddf33bfa56568ca7253573 Mon Sep 17 00:00:00 2001
From: Rob Swindell <rob@synchro.net>
Date: Sun, 27 Mar 2022 03:04:15 -0700
Subject: [PATCH] Support scrolling ANSI messages in preview and view modes

Supports mixed Ctrl-A and ANSI messages.

ANSIs of any length should display correctly.

ANSIs wider than 79 columns will be truncated (not horizontally scrollable).

Animated ANSIs will not render with their animation sequences in tact. :-(
---
 exec/msglist.js | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/exec/msglist.js b/exec/msglist.js
index 16912aa49f..7b9b53ed05 100644
--- a/exec/msglist.js
+++ b/exec/msglist.js
@@ -71,6 +71,8 @@ require('sbbsdefs.js', 'LEN_ALIAS');
 require("utf8_cp437.js", 'utf8_cp437');
 require("file_size.js", 'file_size_str');
 require("html2asc.js", 'html2asc');
+require("graphic.js", 'Graphic');
+var ansiterm = require("ansiterm_lib.js", 'expand_ctrl_a');
 load('822header.js');
 var hexdump = load('hexdump_lib.js');
 var mimehdr = load('mimehdr.js');
@@ -572,6 +574,7 @@ function get_msg_lines(msgbase, msg, hdr, source, hex, wrap, chop)
 	msg.source = (source===true && !hex);
 	msg.wrapped = false;
 	msg.html = false;
+	msg.ansi = false;
 	var text;
 	if(!hdr) {
 		console.print(format(preparing_fmt, options.reading_message_text || "\x01[Reading message text ..."));
@@ -611,12 +614,21 @@ function get_msg_lines(msgbase, msg, hdr, source, hex, wrap, chop)
 			}
 		}
 		text = text.replace(/\xff/g, ' ');	// Use a regular old space for nbsp
-		if(msg.wrapped) {
-			console.print(format(preparing_fmt, options.wrapping_lines || "\x01[Wrapping lines ..."));
-			text = word_wrap(text, console.screen_columns - 1, (msg.columns || 80) - 1).split('\n');
+		msg.ansi = text.indexOf("\x1b[") >= 0;
+		if(msg.ansi) {
+			var graphic = new Graphic(console.screen_columns, 10);
+			graphic.auto_extend = true;
+			graphic.ANSI = ansiterm.expand_ctrl_a(text);
+			graphic.width = console.screen_columns - 1;
+			text = graphic.MSG.split('\n');
 		} else {
-			console.print(format(preparing_fmt, options.splitting_lines || "\x01[Splitting lines ..."));
-			text = line_split(text, chop);
+			if(msg.wrapped) {
+				console.print(format(preparing_fmt, options.wrapping_lines || "\x01[Wrapping lines ..."));
+				text = word_wrap(text, console.screen_columns - 1, (msg.columns || 80) - 1).split('\n');
+			} else {
+				console.print(format(preparing_fmt, options.splitting_lines || "\x01[Splitting lines ..."));
+				text = line_split(text, chop);
+			}
 		}
 		while(text.length && !text[0].trim().length)
 			text.shift(); // Remove initial blank lines
@@ -715,6 +727,8 @@ function content_description(msg)
 		desc.push('header');
 	else if(msg.hex)
 		desc.push('hex-dumpped');
+	else if(msg.ansi)
+			desc.push('ANSI');
 	else {
 		if(msg.wrapped)
 			desc.push('wrapped');
-- 
GitLab