summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2019-08-01 15:27:17 -0400
committerJune McEnroe <june@causal.agency>2019-08-01 15:27:17 -0400
commit4a8d717ca12917cb1c3432cf9eb2d15e23a712c2 (patch)
treebf6c6e4bd013eec0513567888db947deaab510b2
parentAdd poll timeout to ingest (diff)
downloadstream-4a8d717ca12917cb1c3432cf9eb2d15e23a712c2.tar.gz
stream-4a8d717ca12917cb1c3432cf9eb2d15e23a712c2.zip
Factor out SGR handling
-rw-r--r--term.c165
1 files changed, 95 insertions, 70 deletions
diff --git a/term.c b/term.c
index c0395f9..6fb07da 100644
--- a/term.c
+++ b/term.c
@@ -44,8 +44,6 @@ struct Cell {
 	wchar_t ch;
 };
 
-static const struct Style Default = { .bg = -1, .fg = -1 };
-
 static uint rows, cols;
 static uint y, x;
 
@@ -54,7 +52,7 @@ static struct {
 	uint top, bot;
 } scroll;
 
-static struct Style style;
+static struct Style style = { .bg = -1, .fg = -1 };
 static struct Cell *cells;
 
 static struct Cell *cell(uint y, uint x) {
@@ -124,33 +122,10 @@ static char updateNUL(wchar_t ch) {
 	return NUL;
 }
 
-#define ENUM_CHARS \
-	X('?', DEC) \
-	X('A', CUU) \
-	X('B', CUD) \
-	X('C', CUF) \
-	X('D', CUB) \
-	X('E', CNL) \
-	X('F', CPL) \
-	X('G', CHA) \
-	X('H', CUP) \
-	X('J', ED)  \
-	X('K', EL)  \
-	X('M', DL)  \
-	X('P', DCH) \
-	X('[', CSI) \
-	X('\\', ST) \
-	X(']', OSC) \
-	X('d', VPA) \
-	X('h', SM)  \
-	X('l', RM)  \
-	X('m', SGR) \
-	X('r', DECSTBM)
-
 enum {
-#define X(ch, name) name = ch,
-	ENUM_CHARS
-#undef X
+	CSI = '[',
+	OSC = ']',
+	ST  = '\\',
 };
 
 static char updateESC(wchar_t ch) {
@@ -170,6 +145,96 @@ static char updateESC(wchar_t ch) {
 	}
 }
 
+enum {
+	Default,
+	Bold,
+	Italic = 3,
+	Underline,
+	Reverse = 7,
+	NotBold = 22,
+	NotItalic,
+	NotUnderline,
+	NotReverse,
+	Fg0 = 30,
+	Fg7 = 37,
+	Fg,
+	FgDefault,
+	Bg0,
+	Bg7 = 47,
+	Bg,
+	BgDefault,
+	Fg8 = 90,
+	Fg15 = 97,
+	Bg8 = 100,
+	Bg15 = 107,
+	Color256 = 5,
+};
+
+static void updateSGR(uint ps[], uint n) {
+	for (uint i = 0; i < n; ++i) {
+		switch (ps[i]) {
+			break; case Default: style = (struct Style) { .bg = -1, .fg = -1 };
+
+			break; case Bold:      style.bold = true;
+			break; case Italic:    style.italic = true;
+			break; case Underline: style.underline = true;
+			break; case Reverse:   style.reverse = true;
+
+			break; case NotBold:      style.bold = false;
+			break; case NotItalic:    style.italic = false;
+			break; case NotUnderline: style.underline = false;
+			break; case NotReverse:   style.reverse = false;
+
+			break; case Fg: {
+				if (++i < n && ps[i] == Color256) {
+					if (++i < n) style.fg = ps[i];
+				}
+			}
+			break; case Bg: {
+				if (++i < n && ps[i] == Color256) {
+					if (++i < n) style.bg = ps[i];
+				}
+			}
+
+			break; case FgDefault: style.fg = -1;
+			break; case BgDefault: style.bg = -1;
+
+			break; default: {
+				if (ps[i] >= Fg0 && ps[i] <= Fg7) {
+					style.fg = ps[i] - Fg0;
+				} else if (ps[i] >= Bg0 && ps[i] <= Bg7) {
+					style.bg = ps[i] - Bg0;
+				} else if (ps[i] >= Fg8 && ps[i] <= Fg15) {
+					style.fg = 8 + ps[i] - Fg8;
+				} else if (ps[i] >= Bg8 && ps[i] <= Bg15) {
+					style.bg = 8 + ps[i] - Bg8;
+				}
+			}
+		}
+	}
+}
+
+enum {
+	DEC = '?',
+	CUU = 'A',
+	CUD,
+	CUF,
+	CUB,
+	CNL,
+	CPL,
+	CHA,
+	CUP,
+	ED  = 'J',
+	EL,
+	DL  = 'M',
+	DCH = 'P',
+	VPA = 'd',
+	SM  = 'h',
+	RM  = 'l',
+	SGR,
+	DECSTBM = 'r',
+};
+
 static char updateCSI(wchar_t ch) {
 	static bool dec;
 	if (ch == DEC) {
@@ -247,46 +312,7 @@ static char updateCSI(wchar_t ch) {
 			}
 		}
 
-		break; case SGR: {
-			if (ps[0] == 38 && ps[1] == 5) {
-				style.fg = ps[2];
-				break;
-			}
-			if (ps[0] == 48 && ps[1] == 5) {
-				style.bg = ps[2];
-				break;
-			}
-			for (uint i = 0; i < p + 1; ++i) {
-				switch (ps[i]) {
-					break; case 0: style = Default;
-					break; case 1: style.bold = true;
-					break; case 3: style.italic = true;
-					break; case 4: style.underline = true;
-					break; case 7: style.reverse = true;
-					break; case 21: style.bold = false;
-					break; case 22: style.bold = false;
-					break; case 23: style.italic = false;
-					break; case 24: style.underline = false;
-					break; case 27: style.reverse = false;
-					break; case 39: style.fg = -1;
-					break; case 49: style.bg = -1;
-					break; default: {
-						if (ps[i] >= 30 && ps[i] <= 37) {
-							style.fg = ps[i] - 30;
-						} else if (ps[i] >= 40 && ps[i] <= 47) {
-							style.bg = ps[i] - 40;
-						} else if (ps[i] >= 90 && ps[i] <= 97) {
-							style.fg = 8 + ps[i] - 90;
-						} else if (ps[i] >= 100 && ps[i] <= 107) {
-							style.bg = 8 + ps[i] - 100;
-						} else {
-							// FIXME: Nowhere for this warning to go.
-							warnx("unhandled SGR %u", ps[i]);
-						}
-					}
-				}
-			}
-		}
+		break; case SGR: updateSGR(ps, p + 1);
 
 		break; case DECSTBM: {
 			scroll.top = (n > 0 ? ps[0] - 1 : 0);
@@ -333,7 +359,6 @@ void termInit(uint _rows, uint _cols) {
 	cells = calloc(rows * cols, sizeof(*cells));
 	if (!cells) err(EX_OSERR, "calloc");
 
-	style = Default;
 	clear(cell(0, 0), cell(rows - 1, cols - 1));
 	scroll.bot = rows - 1;
 }