st-undercurl-0.8.4.diff (6335B)
1 diff --git a/st.c b/st.c 2 index 76b7e0d..542ab3a 100644 3 --- a/st.c 4 +++ b/st.c 5 @@ -33,6 +33,7 @@ 6 #define UTF_SIZ 4 7 #define ESC_BUF_SIZ (128*UTF_SIZ) 8 #define ESC_ARG_SIZ 16 9 +#define CAR_PER_ARG 4 10 #define STR_BUF_SIZ ESC_BUF_SIZ 11 #define STR_ARG_SIZ ESC_ARG_SIZ 12 13 @@ -139,6 +140,7 @@ typedef struct { 14 int arg[ESC_ARG_SIZ]; 15 int narg; /* nb of args */ 16 char mode[2]; 17 + int carg[ESC_ARG_SIZ][CAR_PER_ARG]; /* colon args */ 18 } CSIEscape; 19 20 /* STR Escape sequence structs */ 21 @@ -159,6 +161,7 @@ static void ttywriteraw(const char *, size_t); 22 23 static void csidump(void); 24 static void csihandle(void); 25 +static void readcolonargs(char **, int, int[][CAR_PER_ARG]); 26 static void csiparse(void); 27 static void csireset(void); 28 static int eschandle(uchar); 29 @@ -1131,6 +1134,28 @@ tnewline(int first_col) 30 tmoveto(first_col ? 0 : term.c.x, y); 31 } 32 33 +void 34 +readcolonargs(char **p, int cursor, int params[][CAR_PER_ARG]) 35 +{ 36 + int i = 0; 37 + for (; i < CAR_PER_ARG; i++) 38 + params[cursor][i] = -1; 39 + 40 + if (**p != ':') 41 + return; 42 + 43 + char *np = NULL; 44 + i = 0; 45 + 46 + while (**p == ':' && i < CAR_PER_ARG) { 47 + while (**p == ':') 48 + (*p)++; 49 + params[cursor][i] = strtol(*p, &np, 10); 50 + *p = np; 51 + i++; 52 + } 53 +} 54 + 55 void 56 csiparse(void) 57 { 58 @@ -1153,6 +1178,7 @@ csiparse(void) 59 v = -1; 60 csiescseq.arg[csiescseq.narg++] = v; 61 p = np; 62 + readcolonargs(&p, csiescseq.narg-1, csiescseq.carg); 63 if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) 64 break; 65 p++; 66 @@ -1369,6 +1395,10 @@ tsetattr(int *attr, int l) 67 ATTR_STRUCK ); 68 term.c.attr.fg = defaultfg; 69 term.c.attr.bg = defaultbg; 70 + term.c.attr.ustyle = -1; 71 + term.c.attr.ucolor[0] = -1; 72 + term.c.attr.ucolor[1] = -1; 73 + term.c.attr.ucolor[2] = -1; 74 break; 75 case 1: 76 term.c.attr.mode |= ATTR_BOLD; 77 @@ -1380,7 +1410,14 @@ tsetattr(int *attr, int l) 78 term.c.attr.mode |= ATTR_ITALIC; 79 break; 80 case 4: 81 - term.c.attr.mode |= ATTR_UNDERLINE; 82 + term.c.attr.ustyle = csiescseq.carg[i][0]; 83 + 84 + if (term.c.attr.ustyle != 0) 85 + term.c.attr.mode |= ATTR_UNDERLINE; 86 + else 87 + term.c.attr.mode &= ~ATTR_UNDERLINE; 88 + 89 + term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; 90 break; 91 case 5: /* slow blink */ 92 /* FALLTHROUGH */ 93 @@ -1431,6 +1468,18 @@ tsetattr(int *attr, int l) 94 case 49: 95 term.c.attr.bg = defaultbg; 96 break; 97 + case 58: 98 + term.c.attr.ucolor[0] = csiescseq.carg[i][1]; 99 + term.c.attr.ucolor[1] = csiescseq.carg[i][2]; 100 + term.c.attr.ucolor[2] = csiescseq.carg[i][3]; 101 + term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; 102 + break; 103 + case 59: 104 + term.c.attr.ucolor[0] = -1; 105 + term.c.attr.ucolor[1] = -1; 106 + term.c.attr.ucolor[2] = -1; 107 + term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; 108 + break; 109 default: 110 if (BETWEEN(attr[i], 30, 37)) { 111 term.c.attr.fg = attr[i] - 30; 112 diff --git a/st.h b/st.h 113 index 3d351b6..2cfac88 100644 114 --- a/st.h 115 +++ b/st.h 116 @@ -34,6 +34,7 @@ enum glyph_attribute { 117 ATTR_WIDE = 1 << 9, 118 ATTR_WDUMMY = 1 << 10, 119 ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, 120 + ATTR_DIRTYUNDERLINE = 1 << 15, 121 }; 122 123 enum selection_mode { 124 @@ -65,6 +66,8 @@ typedef struct { 125 ushort mode; /* attribute flags */ 126 uint32_t fg; /* foreground */ 127 uint32_t bg; /* background */ 128 + int ustyle; /* underline style */ 129 + int ucolor[3]; /* underline color */ 130 } Glyph; 131 132 typedef Glyph *Line; 133 diff --git a/st.info b/st.info 134 index 8201ad6..659878c 100644 135 --- a/st.info 136 +++ b/st.info 137 @@ -1,4 +1,5 @@ 138 st-mono| simpleterm monocolor, 139 + Su, 140 acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, 141 am, 142 bce, 143 diff --git a/x.c b/x.c 144 index 210f184..9a6a2bd 100644 145 --- a/x.c 146 +++ b/x.c 147 @@ -1461,8 +1461,95 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i 148 149 /* Render underline and strikethrough. */ 150 if (base.mode & ATTR_UNDERLINE) { 151 - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, 152 - width, 1); 153 + // Underline Color 154 + int wlw = 1; // Wave Line Width 155 + int linecolor; 156 + if ((base.ucolor[0] >= 0) && 157 + !(base.mode & ATTR_BLINK && win.mode & MODE_BLINK) && 158 + !(base.mode & ATTR_INVISIBLE) 159 + ) { 160 + // Special color for underline 161 + // Index 162 + if (base.ucolor[1] < 0) { 163 + linecolor = dc.col[base.ucolor[0]].pixel; 164 + } 165 + // RGB 166 + else { 167 + XColor lcolor; 168 + lcolor.red = base.ucolor[0] * 257; 169 + lcolor.green = base.ucolor[1] * 257; 170 + lcolor.blue = base.ucolor[2] * 257; 171 + lcolor.flags = DoRed | DoGreen | DoBlue; 172 + XAllocColor(xw.dpy, xw.cmap, &lcolor); 173 + linecolor = lcolor.pixel; 174 + } 175 + } else { 176 + // Foreground color for underline 177 + linecolor = fg->pixel; 178 + } 179 + 180 + XGCValues ugcv = { 181 + .foreground = linecolor, 182 + .line_width = wlw, 183 + .line_style = LineSolid, 184 + .cap_style = CapNotLast 185 + }; 186 + 187 + GC ugc = XCreateGC(xw.dpy, XftDrawDrawable(xw.draw), 188 + GCForeground | GCLineWidth | GCLineStyle | GCCapStyle, 189 + &ugcv); 190 + 191 + // Underline Style 192 + if (base.ustyle != 3) { 193 + //XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, width, 1); 194 + XFillRectangle(xw.dpy, XftDrawDrawable(xw.draw), ugc, winx, 195 + winy + dc.font.ascent + 1, width, wlw); 196 + } else if (base.ustyle == 3) { 197 + int ww = win.cw;//width; 198 + int wh = dc.font.descent - wlw/2 - 1;//r.height/7; 199 + int wx = winx; 200 + int wy = winy + win.ch - dc.font.descent; 201 + 202 + // Draw waves 203 + int narcs = charlen * 2 + 1; 204 + XArc *arcs = xmalloc(sizeof(XArc) * narcs); 205 + 206 + int i = 0; 207 + for (i = 0; i < charlen-1; i++) { 208 + arcs[i*2] = (XArc) { 209 + .x = wx + win.cw * i + ww / 4, 210 + .y = wy, 211 + .width = win.cw / 2, 212 + .height = wh, 213 + .angle1 = 0, 214 + .angle2 = 180 * 64 215 + }; 216 + arcs[i*2+1] = (XArc) { 217 + .x = wx + win.cw * i + ww * 0.75, 218 + .y = wy, 219 + .width = win.cw/2, 220 + .height = wh, 221 + .angle1 = 180 * 64, 222 + .angle2 = 180 * 64 223 + }; 224 + } 225 + // Last wave 226 + arcs[i*2] = (XArc) {wx + ww * i + ww / 4, wy, ww / 2, wh, 227 + 0, 180 * 64 }; 228 + // Last wave tail 229 + arcs[i*2+1] = (XArc) {wx + ww * i + ww * 0.75, wy, ceil(ww / 2.), 230 + wh, 180 * 64, 90 * 64}; 231 + // First wave tail 232 + i++; 233 + arcs[i*2] = (XArc) {wx - ww/4 - 1, wy, ceil(ww / 2.), wh, 270 * 64, 234 + 90 * 64 }; 235 + 236 + XDrawArcs(xw.dpy, XftDrawDrawable(xw.draw), ugc, arcs, narcs); 237 + 238 + free(arcs); 239 + } 240 + 241 + XFreeGC(xw.dpy, ugc); 242 } 243 244 if (base.mode & ATTR_STRUCK) {