commit 79278e3d3262645ef538c3b837644a601ccf6c24
parent ce05a34de1bafca41aad5ca0458efaf91615bf6e
Author: bakkeby <bakkeby@gmail.com>
Date: Sat, 8 May 2021 10:53:46 +0200
Adding undercurl patch ref. #20
Diffstat:
| M | README.md | | | 5 | ++++- |
| M | patches.def.h | | | 14 | ++++++++++++++ |
| M | st.c | | | 67 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | st.h | | | 7 | +++++++ |
| M | st.info | | | 1 | + |
| M | x.c | | | 95 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
6 files changed, 187 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
@@ -15,7 +15,7 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the
### Changelog:
-2021-05-08 - Added blinking cursor patch
+2021-05-08 - Added blinking cursor and undercurl patches
2021-05-07 - Added xresources reload patch
@@ -169,6 +169,9 @@ Refer to [https://st.suckless.org/](https://st.suckless.org/) for details on the
- [themed-cursor](https://st.suckless.org/patches/themed_cursor/)
- instead of a default X cursor, use the xterm cursor from your cursor theme
+ - [undercurl](https://st.suckless.org/patches/undercurl/)
+ - adds support for special underlines, e.g. curly / wavy underlines
+
- [vertcenter](https://st.suckless.org/patches/vertcenter/)
- vertically center lines in the space available if you have set a larger chscale in config.h
diff --git a/patches.def.h b/patches.def.h
@@ -258,6 +258,20 @@
*/
#define THEMED_CURSOR_PATCH 0
+/* Adds support for special underlines.
+ *
+ * Example test command:
+ * $ echo -e "\e[4:3m\e[58:5:10munderline\e[0m"
+ * ^ ^ ^ ^ ^- sets terminal color 10
+ * | | | \- indicates that terminal colors should be used
+ * | | \- indicates that underline color is being set
+ * | \- sets underline style to curvy
+ * \- set underline
+ *
+ * https://st.suckless.org/patches/undercurl/
+ */
+#define UNDERCURL_PATCH 0
+
/* Vertically center lines in the space available if you have set a larger chscale in config.h
* https://st.suckless.org/patches/vertcenter/
*/
diff --git a/st.c b/st.c
@@ -42,6 +42,9 @@
#define UTF_SIZ 4
#define ESC_BUF_SIZ (128*UTF_SIZ)
#define ESC_ARG_SIZ 16
+#if UNDERCURL_PATCH
+#define CAR_PER_ARG 4
+#endif // UNDERCURL_PATCH
#define STR_BUF_SIZ ESC_BUF_SIZ
#define STR_ARG_SIZ ESC_ARG_SIZ
@@ -126,6 +129,9 @@ typedef struct {
int arg[ESC_ARG_SIZ];
int narg; /* nb of args */
char mode[2];
+ #if UNDERCURL_PATCH
+ int carg[ESC_ARG_SIZ][CAR_PER_ARG]; /* colon args */
+ #endif // UNDERCURL_PATCH
} CSIEscape;
/* STR Escape sequence structs */
@@ -146,6 +152,9 @@ static void ttywriteraw(const char *, size_t);
static void csidump(void);
static void csihandle(void);
+#if UNDERCURL_PATCH
+static void readcolonargs(char **, int, int[][CAR_PER_ARG]);
+#endif // UNDERCURL_PATCH
static void csiparse(void);
static void csireset(void);
static int eschandle(uchar);
@@ -1286,6 +1295,30 @@ tnewline(int first_col)
tmoveto(first_col ? 0 : term.c.x, y);
}
+#if UNDERCURL_PATCH
+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++;
+ }
+}
+#endif // UNDERCURL_PATCH
+
void
csiparse(void)
{
@@ -1308,6 +1341,9 @@ csiparse(void)
v = -1;
csiescseq.arg[csiescseq.narg++] = v;
p = np;
+ #if UNDERCURL_PATCH
+ readcolonargs(&p, csiescseq.narg-1, csiescseq.carg);
+ #endif // UNDERCURL_PATCH
if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ)
break;
p++;
@@ -1537,6 +1573,12 @@ tsetattr(int *attr, int l)
ATTR_STRUCK );
term.c.attr.fg = defaultfg;
term.c.attr.bg = defaultbg;
+ #if UNDERCURL_PATCH
+ term.c.attr.ustyle = -1;
+ term.c.attr.ucolor[0] = -1;
+ term.c.attr.ucolor[1] = -1;
+ term.c.attr.ucolor[2] = -1;
+ #endif // UNDERCURL_PATCH
break;
case 1:
term.c.attr.mode |= ATTR_BOLD;
@@ -1548,7 +1590,18 @@ tsetattr(int *attr, int l)
term.c.attr.mode |= ATTR_ITALIC;
break;
case 4:
+ #if UNDERCURL_PATCH
+ 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;
+ #else
term.c.attr.mode |= ATTR_UNDERLINE;
+ #endif // UNDERCURL_PATCH
break;
case 5: /* slow blink */
/* FALLTHROUGH */
@@ -1607,6 +1660,20 @@ tsetattr(int *attr, int l)
case 49:
term.c.attr.bg = defaultbg;
break;
+ #if UNDERCURL_PATCH
+ 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;
+ #endif // UNDERCURL_PATCH
default:
if (BETWEEN(attr[i], 30, 37)) {
#if MONOCHROME_PATCH
diff --git a/st.h b/st.h
@@ -59,6 +59,9 @@ enum glyph_attribute {
ATTR_SIXEL = 1 << 13,
#endif // SIXEL_PATCH
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
+ #if UNDERCURL_PATCH
+ ATTR_DIRTYUNDERLINE = 1 << 15,
+ #endif // UNDERCURL_PATCH
};
#if SIXEL_PATCH
@@ -115,6 +118,10 @@ typedef struct {
ushort mode; /* attribute flags */
uint32_t fg; /* foreground */
uint32_t bg; /* background */
+ #if UNDERCURL_PATCH
+ int ustyle; /* underline style */
+ int ucolor[3]; /* underline color */
+ #endif // UNDERCURL_PATCH
} Glyph;
typedef Glyph *Line;
diff --git a/st.info b/st.info
@@ -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
@@ -1713,7 +1713,100 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
/* Render underline and strikethrough. */
if (base.mode & ATTR_UNDERLINE) {
- #if VERTCENTER_PATCH
+ #if UNDERCURL_PATCH
+ // 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;
+ #if VERTCENTER_PATCH
+ wy += win.cyo;
+ #endif // VERTCENTER_PATCH
+
+ // 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);
+ #elif VERTCENTER_PATCH
XftDrawRect(xw.draw, fg, winx, winy + win.cyo + dc.font.ascent + 1,
width, 1);
#else