From dc83e43aad7b8070911e8210b58cc36bdc4214d5 Mon Sep 17 00:00:00 2001
From: Santtu Lakkala <inz@inz.fi>
Date: Wed, 23 Feb 2022 11:55:19 +0200
Subject: [PATCH 1/2] Allow CSI SGR in status bar

---
 config.def.h |  19 ++++++
 dwm.c        | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 198 insertions(+), 3 deletions(-)

diff --git a/config.def.h b/config.def.h
index a2ac963..3dc34bd 100644
--- a/config.def.h
+++ b/config.def.h
@@ -18,6 +18,25 @@ static const char *colors[][3]      = {
 	[SchemeSel]  = { col_gray4, col_cyan,  col_cyan  },
 };
 
+static const char *barcolors[] = {
+	"#000000",
+	"#7f0000",
+	"#007f00",
+	"#7f7f00",
+	"#00007f",
+	"#7f007f",
+	"#007f7f",
+	"#cccccc",
+	"#333333",
+	"#ff0000",
+	"#00ff00",
+	"#ffff00",
+	"#0000ff",
+	"#ff00ff",
+	"#00ffff",
+	"#ffffff",
+};
+
 /* tagging */
 static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
 
diff --git a/dwm.c b/dwm.c
index a96f33c..cb9484a 100644
--- a/dwm.c
+++ b/dwm.c
@@ -237,7 +237,7 @@ static void zoom(const Arg *arg);
 
 /* variables */
 static const char broken[] = "broken";
-static char stext[256];
+static char stext[512];
 static int screen;
 static int sw, sh;           /* X display screen geometry width, height */
 static int bh, blw = 0;      /* bar geometry */
@@ -264,6 +264,7 @@ static Atom wmatom[WMLast], netatom[NetLast];
 static int running = 1;
 static Cur *cursor[CurLast];
 static Clr **scheme;
+static Clr *barclrs;
 static Display *dpy;
 static Drw *drw;
 static Monitor *mons, *selmon;
@@ -693,6 +694,25 @@ dirtomon(int dir)
 	return m;
 }
 
+void
+resetfntlist(Fnt *orighead, Fnt *curhead)
+{
+	if (orighead != curhead) {
+		Fnt *f;
+		for (f = orighead; f->next; f = f->next);
+		f->next = curhead;
+		for (f = f->next; f->next != orighead; f = f->next);
+		f->next = NULL;
+	}
+}
+
+enum SgrFlags {
+	REVERSE = 1 << 0,
+	UNDERLINE = 1 << 1,
+	STRIKETHROUGH = 1 << 2,
+	OVERLINE = 1 << 3
+};
+
 void
 drawbar(Monitor *m)
 {
@@ -707,9 +727,160 @@ drawbar(Monitor *m)
 
 	/* draw status first so it can be overdrawn by tags later */
 	if (m == selmon) { /* status is only drawn on selected monitor */
+		char buffer[sizeof(stext)];
+		Clr scm[3];
+		int wr, rd;
+		int pw;
+		int fg = 7;
+		int bg = 0;
+		int fmt = 0;
+		int lp = lrpad / 2 - 2;
+		Fnt *fset = drw->fonts;
+
+		memcpy(scm, scheme[SchemeNorm], sizeof(scm));
+
+		drw_setscheme(drw, scm);
+
+		for (tw = 0, wr = 0, rd = 0; stext[rd]; rd++) {
+			if (stext[rd] == '' && stext[rd + 1] == '[') {
+				size_t alen = strspn(stext + rd + 2,
+						     "0123456789;");
+				if (stext[rd + alen + 2] == 'm') {
+					buffer[wr] = '\0';
+					tw += TEXTW(buffer) - lrpad;
+					wr = 0;
+
+					char *ep = stext + rd + 1;
+					while (*ep != 'm') {
+						unsigned v = strtoul(ep + 1, &ep, 10);
+						if (v == 0 || (v >= 10 && v <= 19)) {
+							int fi = v % 10;
+							Fnt *f;
+							Fnt *p;
+							resetfntlist(fset, drw->fonts);
+							for (p = NULL, f = fset; f && fi--; p = f, f = f->next);
+							if (f) {
+								if (p) {
+									p->next = NULL;
+									for (p = f; p->next; p = p->next);
+									p->next = fset;
+								}
+								drw_setfontset(drw, f);
+							} else {
+								drw_setfontset(drw, fset);
+							}
+						}
+					}
+
+					rd += alen + 2;
+					continue;
+				}
+			}
+			buffer[wr++] = stext[rd];
+		}
+		buffer[wr] = '\0';
+
+		tw += TEXTW(buffer) - lrpad / 2 + 2;
+		x = m->ww - tw;
+
+		resetfntlist(fset, drw->fonts);
+		drw_setfontset(drw, fset);
+
+		for (wr = 0, rd = 0; stext[rd]; rd++) {
+			if (stext[rd] == '' && stext[rd + 1] == '[') {
+				size_t alen = strspn(stext + rd + 2,
+						     "0123456789;");
+				if (stext[rd + alen + 2] == 'm') {
+					buffer[wr] = '\0';
+					pw = TEXTW(buffer) - lrpad;
+					drw_text(drw, x, 0, pw + lp, bh, lp, buffer, fmt & REVERSE);
+					if (fmt & UNDERLINE)
+						drw_rect(drw, x, (bh + drw->fonts->h) / 2, pw, 1, 1, fmt & REVERSE); 
+					if (fmt & STRIKETHROUGH)
+						drw_rect(drw, x, bh / 2, pw, 1, 1, fmt & REVERSE); 
+					if (fmt & OVERLINE)
+						drw_rect(drw, x, (bh - drw->fonts->h) / 2, pw, 1, 1, fmt & REVERSE); 
+					x += pw + lp;
+					lp = 0;
+
+					char *ep = stext + rd + 1;
+					while (*ep != 'm') {
+						unsigned v = strtoul(ep + 1, &ep, 10);
+						if (v == 0) {
+							memcpy(scm, scheme[SchemeNorm], sizeof(scm));
+							fg = 7;
+							bg = 0;
+							fmt = 0;
+							resetfntlist(fset, drw->fonts);
+							drw_setfontset(drw, fset);
+						} else if (v == 1) {
+							fg |= 8;
+							scm[0] = barclrs[fg];
+						} else if (v == 4) {
+							fmt |= UNDERLINE;
+						} else if (v == 7) {
+							fmt |= REVERSE;
+						} else if (v == 9) {
+							fmt |= STRIKETHROUGH;
+						} else if (v >= 10 && v <= 19) {
+							int fi = v % 10;
+							Fnt *f;
+							Fnt *p;
+							resetfntlist(fset, drw->fonts);
+							for (p = NULL, f = fset; f && fi--; p = f, f = f->next);
+							if (f) {
+								if (p) {
+									p->next = NULL;
+									for (p = f; p->next; p = p->next);
+									p->next = fset;
+								}
+								drw_setfontset(drw, f);
+							} else {
+								drw_setfontset(drw, fset);
+							}
+						} else if (v == 22) {
+							fg &= ~8;
+							scm[0] = barclrs[fg];
+						} else if (v == 24) {
+							fmt &= ~UNDERLINE;
+						} else if (v == 27) {
+							fmt &= ~REVERSE;
+						} else if (v == 29) {
+							fmt &= ~STRIKETHROUGH;
+						} else if (v >= 30 && v <= 37) {
+							fg = v % 10 | (fg & 8);
+							scm[0] = barclrs[fg];
+						} else if (v >= 40 && v <= 47) {
+							bg = v % 10;
+							scm[1] = barclrs[bg];
+						} else if (v == 53) {
+							fmt |= OVERLINE;
+						} else if (v == 55) {
+							fmt &= ~OVERLINE;
+						}
+					}
+
+					rd += alen + 2;
+					wr = 0;
+
+					drw_setscheme(drw, scm);
+					continue;
+				}
+			}
+			buffer[wr++] = stext[rd];
+		}
+
+		buffer[wr] = '\0';
+		pw = TEXTW(buffer) - lrpad;
+		drw_text(drw, x, 0, pw + lp, bh, lp, buffer, fmt & REVERSE);
+		if (fmt & UNDERLINE)
+			drw_rect(drw, x, (bh + drw->fonts->h) / 2, pw, 1, 1, fmt & REVERSE); 
+		if (fmt & STRIKETHROUGH)
+			drw_rect(drw, x, bh / 2, pw, 1, 1, fmt & REVERSE); 
+		if (fmt & OVERLINE)
+			drw_rect(drw, x, (bh - drw->fonts->h) / 2, pw, 1, 1, fmt & REVERSE); 
+
 		drw_setscheme(drw, scheme[SchemeNorm]);
-		tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
-		drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
 	}
 
 	for (c = m->clients; c; c = c->next) {
@@ -1574,6 +1745,11 @@ setup(void)
 	scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
 	for (i = 0; i < LENGTH(colors); i++)
 		scheme[i] = drw_scm_create(drw, colors[i], 3);
+
+	barclrs = ecalloc(LENGTH(barcolors), sizeof(Clr));
+	for (i = 0; i < LENGTH(barcolors); i++)
+		drw_clr_create(drw, &barclrs[i], barcolors[i]);
+
 	/* init bars */
 	updatebars();
 	updatestatus();
-- 
2.32.0