From b0b7ab792bc1f45963f4b84b94faaf05054e1613 Mon Sep 17 00:00:00 2001
From: Ron Yorston <rmy@pobox.com>
Date: Wed, 8 Jan 2020 09:42:49 +0000
Subject: winansi: code shrink

Rework the ANSI emulation code to reduce its size.

- Fetch console attributes when required rather than caching them.
  The init() function is no longer required; the only remaining
  initialisation is now performed in is_console().

- Turning off inverse video (ESC[27m) didn't work properly.  This has
  been improved though it still doesn't work in some unlikely cases
  (ESC[7;27m).

These changes save 180 bytes.
---
 win32/winansi.c | 68 ++++++++++++++++++++++++++-------------------------------
 1 file changed, 31 insertions(+), 37 deletions(-)

diff --git a/win32/winansi.c b/win32/winansi.c
index 0d8cf662a..41ca3ccca 100644
--- a/win32/winansi.c
+++ b/win32/winansi.c
@@ -21,41 +21,35 @@
 #undef read
 #undef getc
 
-static WORD plain_attr;
-static WORD attr;
-static int negative;
+#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
+#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
+
+static WORD plain_attr = 0;
 
 static HANDLE get_console(void)
 {
 	return GetStdHandle(STD_OUTPUT_HANDLE);
 }
 
-static void init(void)
+static WORD get_console_attr(void)
 {
-	static int initialised = FALSE;
-	HANDLE console;
 	CONSOLE_SCREEN_BUFFER_INFO sbi;
 
-	if (initialised)
-		return;
-	initialised = TRUE;
+	if (GetConsoleScreenBufferInfo(get_console(), &sbi))
+		return sbi.wAttributes;
 
-	console = get_console();
-	if (GetConsoleScreenBufferInfo(console, &sbi)) {
-		attr = plain_attr = sbi.wAttributes;
-		negative = 0;
-	}
+	return FOREGROUND_ALL;
 }
 
 static int is_console(int fd)
 {
-	init();
+	if (!plain_attr)
+		plain_attr = get_console_attr();
 	return isatty(fd) && get_console() != INVALID_HANDLE_VALUE;
 }
 
 static int is_console_in(int fd)
 {
-	init();
 	return isatty(fd) && GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE;
 }
 
@@ -91,11 +85,8 @@ static HANDLE dup_handle(HANDLE h)
 static void use_alt_buffer(int flag)
 {
 	static HANDLE console_orig = INVALID_HANDLE_VALUE;
-	CONSOLE_SCREEN_BUFFER_INFO sbi;
 	HANDLE console, h;
 
-	init();
-
 	console = get_console();
 	console_orig = dup_handle(console);
 	if (console_orig == INVALID_HANDLE_VALUE)
@@ -103,6 +94,7 @@ static void use_alt_buffer(int flag)
 
 	if (flag) {
 		SECURITY_ATTRIBUTES sa;
+		CONSOLE_SCREEN_BUFFER_INFO sbi;
 
 		// handle should be inheritable
 		memset(&sa, 0, sizeof(sa));
@@ -134,31 +126,28 @@ static void use_alt_buffer(int flag)
 	_open_osfhandle((intptr_t)console, O_RDWR|O_BINARY);
 }
 
-#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
-#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
-
-static void set_console_attr(void)
+static void set_console_attr(WORD attributes, int invert)
 {
 	HANDLE console = get_console();
-	WORD attributes = attr;
-	if (negative) {
+	if (invert) {
+		WORD save = attributes;
 		attributes &= ~FOREGROUND_ALL;
 		attributes &= ~BACKGROUND_ALL;
 
 		/* This could probably use a bitmask
 		   instead of a series of ifs */
-		if (attr & FOREGROUND_RED)
+		if (save & FOREGROUND_RED)
 			attributes |= BACKGROUND_RED;
-		if (attr & FOREGROUND_GREEN)
+		if (save & FOREGROUND_GREEN)
 			attributes |= BACKGROUND_GREEN;
-		if (attr & FOREGROUND_BLUE)
+		if (save & FOREGROUND_BLUE)
 			attributes |= BACKGROUND_BLUE;
 
-		if (attr & BACKGROUND_RED)
+		if (save & BACKGROUND_RED)
 			attributes |= FOREGROUND_RED;
-		if (attr & BACKGROUND_GREEN)
+		if (save & BACKGROUND_GREEN)
 			attributes |= FOREGROUND_GREEN;
-		if (attr & BACKGROUND_BLUE)
+		if (save & BACKGROUND_BLUE)
 			attributes |= FOREGROUND_BLUE;
 	}
 	SetConsoleTextAttribute(console, attributes);
@@ -252,6 +241,9 @@ static char *process_escape(char *pos)
 	const char *str, *func;
 	char *bel;
 	size_t len;
+	WORD attr = get_console_attr();
+	int invert = FALSE;
+	static int inverse = 0;
 
 	switch (pos[1]) {
 	case '[':
@@ -281,7 +273,7 @@ static char *process_escape(char *pos)
 			switch (val) {
 			case 0: /* reset */
 				attr = plain_attr;
-				negative = 0;
+				inverse = 0;
 				break;
 			case 1: /* bold */
 				attr |= FOREGROUND_INTENSITY;
@@ -311,11 +303,13 @@ static char *process_escape(char *pos)
 			case 25: /* no blink */
 				attr &= ~BACKGROUND_INTENSITY;
 				break;
-			case 7:  /* negative */
-				negative = 1;
+			case 7:  /* inverse on */
+				invert = !inverse;
+				inverse = 1;
 				break;
-			case 27: /* positive */
-				negative = 0;
+			case 27: /* inverse off */
+				invert = inverse;
+				inverse = 0;
 				break;
 			case 8:  /* conceal */
 			case 28: /* reveal */
@@ -404,7 +398,7 @@ static char *process_escape(char *pos)
 			str++;
 		} while (*(str-1) == ';');
 
-		set_console_attr();
+		set_console_attr(attr, invert);
 		break;
 	case 'A': /* up */
 		move_cursor_row(-strtol(str, (char **)&str, 10));
-- 
cgit v1.2.3-55-g6feb