commit b01bc68e43b7e6e4e20700ddcdee55b41652f58d
Author: HexOctal <hex0octal_AT_gmail.com>
Date:   Mon Apr 26 10:56:12 2021 +0100
    [st][patch][st-undercurl] Introduced new patch.
    
    This patch adds support for special underlines for st, which includes
    curly/wavy underlines, as well as a color different than the foreground
    color.
diff --git a/st.suckless.org/patches/undercurl/index.md b/st.suckless.org/patches/undercurl/index.md
new file mode 100644
index 00000000..a4e64fe0
--- /dev/null
+++ b/st.suckless.org/patches/undercurl/index.md
_AT_@ -0,0 +1,26 @@
+undercurl
+=========
+
+
+
+Description
+-----------
+This patch adds support for special underlines. It allows the use of the
+following [SGR](
https://en.wikipedia.org/wiki/ANSI_escape_code#SGR) parameters:
+* 4:x - Where x can be 0 (No underline), 1-2 (Straight), 3 (Curly/Wavy)
+* 58:5:x - Where x is the index of one of the terminal colors, up to 255, that the underline will be drawn with.
+* 58:2:r:g:b - Where r, g and b are the red, green and blue color values of the underline respectively.
+* 59 - Resets the underline color to the foreground color.
+
+Notes
+-----
+These escape codes aren't standard, but they are supported by most other
+terminal emulators, as well as many terminal programs (Such as Vim).
+
+Download
+--------
+* [st-undercurl-0.8.4.diff](st-undercurl-0.8.4.diff)
+
+Authors
+-------
+* HexOctal - ([github.com/hexoctal](github.com/hexoctal)) <hex0octal_AT_gmail.com>
diff --git a/st.suckless.org/patches/undercurl/st-undercurl-0.8.4.diff b/st.suckless.org/patches/undercurl/st-undercurl-0.8.4.diff
new file mode 100644
index 00000000..a91b6074
--- /dev/null
+++ b/st.suckless.org/patches/undercurl/st-undercurl-0.8.4.diff
_AT_@ -0,0 +1,244 @@
+diff --git a/st.c b/st.c
+index 76b7e0d..542ab3a 100644
+--- a/st.c
++++ b/st.c
+_AT_@ -33,6 +33,7 @@
+ #define UTF_SIZ       4
+ #define ESC_BUF_SIZ   (128*UTF_SIZ)
+ #define ESC_ARG_SIZ   16
++#define CAR_PER_ARG   4
+ #define STR_BUF_SIZ   ESC_BUF_SIZ
+ #define STR_ARG_SIZ   ESC_ARG_SIZ
+ 
+_AT_@ -139,6 +140,7 @@ typedef struct {
+ 	int arg[ESC_ARG_SIZ];
+ 	int narg;              /* nb of args */
+ 	char mode[2];
++	int carg[ESC_ARG_SIZ][CAR_PER_ARG]; /* colon args */
+ } CSIEscape;
+ 
+ /* STR Escape sequence structs */
+_AT_@ -159,6 +161,7 @@ static void ttywriteraw(const char *, size_t);
+ 
+ static void csidump(void);
+ static void csihandle(void);
++static void readcolonargs(char **, int, int[][CAR_PER_ARG]);
+ static void csiparse(void);
+ static void csireset(void);
+ static int eschandle(uchar);
+_AT_@ -1131,6 +1134,28 @@ tnewline(int first_col)
+ 	tmoveto(first_col ? 0 : term.c.x, y);
+ }
+ 
++void
++readcolonargs(char **p, int cursor, int params[][CAR_PER_ARG])
++{
++	int i = 0;
++	for (; i < CAR_PER_ARG; i++)
++		params[cursor][i] = -1;
++
++	if (**p != ':')
++		return;
++
++	char *np = NULL;
++	i = 0;
++
++	while (**p == ':' && i < CAR_PER_ARG) {
++		while (**p == ':')
++			(*p)++;
++		params[cursor][i] = strtol(*p, &np, 10);
++		*p = np;
++		i++;
++	}
++}
++
+ void
+ csiparse(void)
+ {
+_AT_@ -1153,6 +1178,7 @@ csiparse(void)
+ 			v = -1;
+ 		csiescseq.arg[csiescseq.narg++] = v;
+ 		p = np;
++		readcolonargs(&p, csiescseq.narg-1, csiescseq.carg);
+ 		if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ)
+ 			break;
+ 		p++;
+_AT_@ -1369,6 +1395,10 @@ tsetattr(int *attr, int l)
+ 				ATTR_STRUCK     );
+ 			term.c.attr.fg = defaultfg;
+ 			term.c.attr.bg = defaultbg;
++			term.c.attr.ustyle = -1;
++			term.c.attr.ucolor[0] = -1;
++			term.c.attr.ucolor[1] = -1;
++			term.c.attr.ucolor[2] = -1;
+ 			break;
+ 		case 1:
+ 			term.c.attr.mode |= ATTR_BOLD;
+_AT_@ -1380,7 +1410,14 @@ tsetattr(int *attr, int l)
+ 			term.c.attr.mode |= ATTR_ITALIC;
+ 			break;
+ 		case 4:
+-			term.c.attr.mode |= ATTR_UNDERLINE;
++			term.c.attr.ustyle = csiescseq.carg[i][0];
++
++			if (term.c.attr.ustyle != 0)
++				term.c.attr.mode |= ATTR_UNDERLINE;
++			else
++				term.c.attr.mode &= ~ATTR_UNDERLINE;
++
++			term.c.attr.mode ^= ATTR_DIRTYUNDERLINE;
+ 			break;
+ 		case 5: /* slow blink */
+ 			/* FALLTHROUGH */
+_AT_@ -1431,6 +1468,18 @@ tsetattr(int *attr, int l)
+ 		case 49:
+ 			term.c.attr.bg = defaultbg;
+ 			break;
++		case 58:
++			term.c.attr.ucolor[0] = csiescseq.carg[i][1];
++			term.c.attr.ucolor[1] = csiescseq.carg[i][2];
++			term.c.attr.ucolor[2] = csiescseq.carg[i][3];
++			term.c.attr.mode ^= ATTR_DIRTYUNDERLINE;
++			break;
++		case 59:
++			term.c.attr.ucolor[0] = -1;
++			term.c.attr.ucolor[1] = -1;
++			term.c.attr.ucolor[2] = -1;
++			term.c.attr.mode ^= ATTR_DIRTYUNDERLINE;
++			break;
+ 		default:
+ 			if (BETWEEN(attr[i], 30, 37)) {
+ 				term.c.attr.fg = attr[i] - 30;
+diff --git a/st.h b/st.h
+index 3d351b6..2cfac88 100644
+--- a/st.h
++++ b/st.h
+_AT_@ -34,6 +34,7 @@ enum glyph_attribute {
+ 	ATTR_WIDE       = 1 << 9,
+ 	ATTR_WDUMMY     = 1 << 10,
+ 	ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
++	ATTR_DIRTYUNDERLINE = 1 << 15,
+ };
+ 
+ enum selection_mode {
+_AT_@ -65,6 +66,8 @@ typedef struct {
+ 	ushort mode;      /* attribute flags */
+ 	uint32_t fg;      /* foreground  */
+ 	uint32_t bg;      /* background  */
++	int ustyle;	  /* underline style */
++	int ucolor[3];    /* underline color */
+ } Glyph;
+ 
+ typedef Glyph *Line;
+diff --git a/st.info b/st.info
+index 8201ad6..659878c 100644
+--- a/st.info
++++ b/st.info
+_AT_@ -1,4 +1,5 @@
+ st-mono| simpleterm monocolor,
++	Su,
+ 	acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
+ 	am,
+ 	bce,
+diff --git a/x.c b/x.c
+index 210f184..9a6a2bd 100644
+--- a/x.c
++++ b/x.c
+_AT_@ -1461,8 +1461,95 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
+ 
+ 	/* Render underline and strikethrough. */
+ 	if (base.mode & ATTR_UNDERLINE) {
+-		XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1,
+-				width, 1);
++		// Underline Color
++		int wlw = 1; // Wave Line Width
++		int linecolor;
++		if ((base.ucolor[0] >= 0) &&
++			!(base.mode & ATTR_BLINK && win.mode & MODE_BLINK) &&
++			!(base.mode & ATTR_INVISIBLE)
++		) {
++			// Special color for underline
++			// Index
++			if (base.ucolor[1] < 0) {
++				linecolor = dc.col[base.ucolor[0]].pixel;
++			}
++			// RGB
++			else {
++				XColor lcolor;
++				lcolor.red = base.ucolor[0] * 257;
++				lcolor.green = base.ucolor[1] * 257;
++				lcolor.blue = base.ucolor[2] * 257;
++				lcolor.flags = DoRed | DoGreen | DoBlue;
++				XAllocColor(xw.dpy, xw.cmap, &lcolor);
++				linecolor = lcolor.pixel;
++			}
++		} else {
++			// Foreground color for underline
++			linecolor = fg->pixel;
++		}
++
++		XGCValues ugcv = {
++			.foreground = linecolor,
++			.line_width = wlw,
++			.line_style = LineSolid,
++			.cap_style = CapNotLast
++		};
++
++		GC ugc = XCreateGC(xw.dpy, XftDrawDrawable(xw.draw),
++			GCForeground | GCLineWidth | GCLineStyle | GCCapStyle,
++			&ugcv);
++
++		// Underline Style
++		if (base.ustyle != 3) {
++			//XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, width, 1);
++			XFillRectangle(xw.dpy, XftDrawDrawable(xw.draw), ugc, winx,
++				winy + dc.font.ascent + 1, width, wlw);
++		} else if (base.ustyle == 3) {
++			int ww = win.cw;//width;
++			int wh = dc.font.descent - wlw/2 - 1;//r.height/7;
++			int wx = winx;
++			int wy = winy + win.ch - dc.font.descent;
++
++			// Draw waves
++			int narcs = charlen * 2 + 1;
++			XArc *arcs = xmalloc(sizeof(XArc) * narcs);
++
++			int i = 0;
++			for (i = 0; i < charlen-1; i++) {
++				arcs[i*2] = (XArc) {
++					.x = wx + win.cw * i + ww / 4,
++					.y = wy,
++					.width = win.cw / 2,
++					.height = wh,
++					.angle1 = 0,
++					.angle2 = 180 * 64
++				};
++				arcs[i*2+1] = (XArc) {
++					.x = wx + win.cw * i + ww * 0.75,
++					.y = wy,
++					.width = win.cw/2,
++					.height = wh,
++					.angle1 = 180 * 64,
++					.angle2 = 180 * 64
++				};
++			}
++			// Last wave
++			arcs[i*2] = (XArc) {wx + ww * i + ww / 4, wy, ww / 2, wh,
++			0, 180 * 64 };
++			// Last wave tail
++			arcs[i*2+1] = (XArc) {wx + ww * i + ww * 0.75, wy, ceil(ww / 2.),
++			wh, 180 * 64, 90 * 64};
++			// First wave tail
++			i++;
++			arcs[i*2] = (XArc) {wx - ww/4 - 1, wy, ceil(ww / 2.), wh, 270 * 64,
++			90 * 64 };
++
++			XDrawArcs(xw.dpy, XftDrawDrawable(xw.draw), ugc, arcs, narcs);
++
++			free(arcs);
++		}
++
++		XFreeGC(xw.dpy, ugc);
+ 	}
+ 
+ 	if (base.mode & ATTR_STRUCK) {
diff --git a/st.suckless.org/patches/undercurl/undercurl.png b/st.suckless.org/patches/undercurl/undercurl.png
new file mode 100644
index 00000000..dce372e9
Binary files /dev/null and b/st.suckless.org/patches/undercurl/undercurl.png differ
Received on Mon Apr 26 2021 - 12:05:55 CEST