st-undercurl-0.8.4-20210822.diff - sites - public wiki contents of suckless.org | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
st-undercurl-0.8.4-20210822.diff (16126B) | |
--- | |
1 diff --git a/config.def.h b/config.def.h | |
2 index 6f05dce..7ae1b92 100644 | |
3 --- a/config.def.h | |
4 +++ b/config.def.h | |
5 @@ -470,3 +470,27 @@ static char ascii_printable[] = | |
6 " !\"#$%&'()*+,-./0123456789:;<=>?" | |
7 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" | |
8 "`abcdefghijklmnopqrstuvwxyz{|}~"; | |
9 + | |
10 +/** | |
11 + * Undercurl style. Set UNDERCURL_STYLE to one of the available styles. | |
12 + * | |
13 + * Curly: Dunno how to draw it *shrug* | |
14 + * _ _ _ _ | |
15 + * ( ) ( ) ( ) ( ) | |
16 + * (_) (_) (_) (_) | |
17 + * | |
18 + * Spiky: | |
19 + * /\ /\ /\ /\ | |
20 + * \/ \/ \/ | |
21 + * | |
22 + * Capped: | |
23 + * _ _ _ | |
24 + * / \ / \ / \ | |
25 + * \_/ \_/ | |
26 + */ | |
27 +// Available styles | |
28 +#define UNDERCURL_CURLY 0 | |
29 +#define UNDERCURL_SPIKY 1 | |
30 +#define UNDERCURL_CAPPED 2 | |
31 +// Active style | |
32 +#define UNDERCURL_STYLE UNDERCURL_SPIKY | |
33 diff --git a/st.c b/st.c | |
34 index 76b7e0d..542ab3a 100644 | |
35 --- a/st.c | |
36 +++ b/st.c | |
37 @@ -33,6 +33,7 @@ | |
38 #define UTF_SIZ 4 | |
39 #define ESC_BUF_SIZ (128*UTF_SIZ) | |
40 #define ESC_ARG_SIZ 16 | |
41 +#define CAR_PER_ARG 4 | |
42 #define STR_BUF_SIZ ESC_BUF_SIZ | |
43 #define STR_ARG_SIZ ESC_ARG_SIZ | |
44 | |
45 @@ -139,6 +140,7 @@ typedef struct { | |
46 int arg[ESC_ARG_SIZ]; | |
47 int narg; /* nb of args */ | |
48 char mode[2]; | |
49 + int carg[ESC_ARG_SIZ][CAR_PER_ARG]; /* colon args */ | |
50 } CSIEscape; | |
51 | |
52 /* STR Escape sequence structs */ | |
53 @@ -159,6 +161,7 @@ static void ttywriteraw(const char *, size_t); | |
54 | |
55 static void csidump(void); | |
56 static void csihandle(void); | |
57 +static void readcolonargs(char **, int, int[][CAR_PER_ARG]); | |
58 static void csiparse(void); | |
59 static void csireset(void); | |
60 static int eschandle(uchar); | |
61 @@ -1131,6 +1134,28 @@ tnewline(int first_col) | |
62 tmoveto(first_col ? 0 : term.c.x, y); | |
63 } | |
64 | |
65 +void | |
66 +readcolonargs(char **p, int cursor, int params[][CAR_PER_ARG]) | |
67 +{ | |
68 + int i = 0; | |
69 + for (; i < CAR_PER_ARG; i++) | |
70 + params[cursor][i] = -1; | |
71 + | |
72 + if (**p != ':') | |
73 + return; | |
74 + | |
75 + char *np = NULL; | |
76 + i = 0; | |
77 + | |
78 + while (**p == ':' && i < CAR_PER_ARG) { | |
79 + while (**p == ':') | |
80 + (*p)++; | |
81 + params[cursor][i] = strtol(*p, &np, 10); | |
82 + *p = np; | |
83 + i++; | |
84 + } | |
85 +} | |
86 + | |
87 void | |
88 csiparse(void) | |
89 { | |
90 @@ -1153,6 +1178,7 @@ csiparse(void) | |
91 v = -1; | |
92 csiescseq.arg[csiescseq.narg++] = v; | |
93 p = np; | |
94 + readcolonargs(&p, csiescseq.narg-1, csiescseq.carg); | |
95 if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ) | |
96 break; | |
97 p++; | |
98 @@ -1369,6 +1395,10 @@ tsetattr(int *attr, int l) | |
99 ATTR_STRUCK ); | |
100 term.c.attr.fg = defaultfg; | |
101 term.c.attr.bg = defaultbg; | |
102 + term.c.attr.ustyle = -1; | |
103 + term.c.attr.ucolor[0] = -1; | |
104 + term.c.attr.ucolor[1] = -1; | |
105 + term.c.attr.ucolor[2] = -1; | |
106 break; | |
107 case 1: | |
108 term.c.attr.mode |= ATTR_BOLD; | |
109 @@ -1380,7 +1410,14 @@ tsetattr(int *attr, int l) | |
110 term.c.attr.mode |= ATTR_ITALIC; | |
111 break; | |
112 case 4: | |
113 - term.c.attr.mode |= ATTR_UNDERLINE; | |
114 + term.c.attr.ustyle = csiescseq.carg[i][0]; | |
115 + | |
116 + if (term.c.attr.ustyle != 0) | |
117 + term.c.attr.mode |= ATTR_UNDERLINE; | |
118 + else | |
119 + term.c.attr.mode &= ~ATTR_UNDERLINE; | |
120 + | |
121 + term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; | |
122 break; | |
123 case 5: /* slow blink */ | |
124 /* FALLTHROUGH */ | |
125 @@ -1431,6 +1468,18 @@ tsetattr(int *attr, int l) | |
126 case 49: | |
127 term.c.attr.bg = defaultbg; | |
128 break; | |
129 + case 58: | |
130 + term.c.attr.ucolor[0] = csiescseq.carg[i][1]; | |
131 + term.c.attr.ucolor[1] = csiescseq.carg[i][2]; | |
132 + term.c.attr.ucolor[2] = csiescseq.carg[i][3]; | |
133 + term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; | |
134 + break; | |
135 + case 59: | |
136 + term.c.attr.ucolor[0] = -1; | |
137 + term.c.attr.ucolor[1] = -1; | |
138 + term.c.attr.ucolor[2] = -1; | |
139 + term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; | |
140 + break; | |
141 default: | |
142 if (BETWEEN(attr[i], 30, 37)) { | |
143 term.c.attr.fg = attr[i] - 30; | |
144 diff --git a/st.h b/st.h | |
145 index 3d351b6..95bdcbd 100644 | |
146 --- a/st.h | |
147 +++ b/st.h | |
148 @@ -34,6 +34,7 @@ enum glyph_attribute { | |
149 ATTR_WIDE = 1 << 9, | |
150 ATTR_WDUMMY = 1 << 10, | |
151 ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, | |
152 + ATTR_DIRTYUNDERLINE = 1 << 15, | |
153 }; | |
154 | |
155 enum selection_mode { | |
156 @@ -65,6 +66,8 @@ typedef struct { | |
157 ushort mode; /* attribute flags */ | |
158 uint32_t fg; /* foreground */ | |
159 uint32_t bg; /* background */ | |
160 + int ustyle; /* underline style */ | |
161 + int ucolor[3]; /* underline color */ | |
162 } Glyph; | |
163 | |
164 typedef Glyph *Line; | |
165 diff --git a/st.info b/st.info | |
166 index 8201ad6..659878c 100644 | |
167 --- a/st.info | |
168 +++ b/st.info | |
169 @@ -1,4 +1,5 @@ | |
170 st-mono| simpleterm monocolor, | |
171 + Su, | |
172 acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{… | |
173 am, | |
174 bce, | |
175 diff --git a/x.c b/x.c | |
176 index 210f184..3a0e79e 100644 | |
177 --- a/x.c | |
178 +++ b/x.c | |
179 @@ -45,6 +45,14 @@ typedef struct { | |
180 signed char appcursor; /* application cursor */ | |
181 } Key; | |
182 | |
183 +/* Undercurl slope types */ | |
184 +enum undercurl_slope_type { | |
185 + UNDERCURL_SLOPE_ASCENDING = 0, | |
186 + UNDERCURL_SLOPE_TOP_CAP = 1, | |
187 + UNDERCURL_SLOPE_DESCENDING = 2, | |
188 + UNDERCURL_SLOPE_BOTTOM_CAP = 3 | |
189 +}; | |
190 + | |
191 /* X modifiers */ | |
192 #define XK_ANY_MOD UINT_MAX | |
193 #define XK_NO_MOD 0 | |
194 @@ -1339,6 +1347,51 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, cons… | |
195 return numspecs; | |
196 } | |
197 | |
198 +static int isSlopeRising (int x, int iPoint, int waveWidth) | |
199 +{ | |
200 + // . . . . | |
201 + // / \ / \ / \ / \ | |
202 + // / \ / \ / \ / \ | |
203 + // . . . . . | |
204 + | |
205 + // Find absolute `x` of point | |
206 + x += iPoint * (waveWidth/2); | |
207 + | |
208 + // Find index of absolute wave | |
209 + int absSlope = x / ((float)waveWidth/2); | |
210 + | |
211 + return (absSlope % 2); | |
212 +} | |
213 + | |
214 +static int getSlope (int x, int iPoint, int waveWidth) | |
215 +{ | |
216 + // Sizes: Caps are half width of slopes | |
217 + // 1_2 1_2 1_2 1_2 | |
218 + // / \ / \ / \ / \ | |
219 + // / \ / \ / \ / \ | |
220 + // 0 3_0 3_0 3_0 3_ | |
221 + // <2-> <1> <---6----> | |
222 + | |
223 + // Find type of first point | |
224 + int firstType; | |
225 + x -= (x / waveWidth) * waveWidth; | |
226 + if (x < (waveWidth * (2.f/6.f))) | |
227 + firstType = UNDERCURL_SLOPE_ASCENDING; | |
228 + else if (x < (waveWidth * (3.f/6.f))) | |
229 + firstType = UNDERCURL_SLOPE_TOP_CAP; | |
230 + else if (x < (waveWidth * (5.f/6.f))) | |
231 + firstType = UNDERCURL_SLOPE_DESCENDING; | |
232 + else | |
233 + firstType = UNDERCURL_SLOPE_BOTTOM_CAP; | |
234 + | |
235 + // Find type of given point | |
236 + int pointType = (iPoint % 4); | |
237 + pointType += firstType; | |
238 + pointType %= 4; | |
239 + | |
240 + return pointType; | |
241 +} | |
242 + | |
243 void | |
244 xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len,… | |
245 { | |
246 @@ -1461,8 +1514,357 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *spec… | |
247 | |
248 /* Render underline and strikethrough. */ | |
249 if (base.mode & ATTR_UNDERLINE) { | |
250 - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + … | |
251 - width, 1); | |
252 + // Underline Color | |
253 + const int widthThreshold = 28; // +1 width every width… | |
254 + int wlw = (win.ch / widthThreshold) + 1; // Wave Line W… | |
255 + int linecolor; | |
256 + if ((base.ucolor[0] >= 0) && | |
257 + !(base.mode & ATTR_BLINK && win.mode & MODE_BLI… | |
258 + !(base.mode & ATTR_INVISIBLE) | |
259 + ) { | |
260 + // Special color for underline | |
261 + // Index | |
262 + if (base.ucolor[1] < 0) { | |
263 + linecolor = dc.col[base.ucolor[0]].pixe… | |
264 + } | |
265 + // RGB | |
266 + else { | |
267 + XColor lcolor; | |
268 + lcolor.red = base.ucolor[0] * 257; | |
269 + lcolor.green = base.ucolor[1] * 257; | |
270 + lcolor.blue = base.ucolor[2] * 257; | |
271 + lcolor.flags = DoRed | DoGreen | DoBlue; | |
272 + XAllocColor(xw.dpy, xw.cmap, &lcolor); | |
273 + linecolor = lcolor.pixel; | |
274 + } | |
275 + } else { | |
276 + // Foreground color for underline | |
277 + linecolor = fg->pixel; | |
278 + } | |
279 + | |
280 + XGCValues ugcv = { | |
281 + .foreground = linecolor, | |
282 + .line_width = wlw, | |
283 + .line_style = LineSolid, | |
284 + .cap_style = CapNotLast | |
285 + }; | |
286 + | |
287 + GC ugc = XCreateGC(xw.dpy, XftDrawDrawable(xw.draw), | |
288 + GCForeground | GCLineWidth | GCLineStyle | GCCa… | |
289 + &ugcv); | |
290 + | |
291 + // Underline Style | |
292 + if (base.ustyle != 3) { | |
293 + //XftDrawRect(xw.draw, fg, winx, winy + dc.font… | |
294 + XFillRectangle(xw.dpy, XftDrawDrawable(xw.draw)… | |
295 + winy + dc.font.ascent + 1, width, wlw); | |
296 + } else if (base.ustyle == 3) { | |
297 + int ww = win.cw;//width; | |
298 + int wh = dc.font.descent - wlw/2 - 1;//r.height… | |
299 + int wx = winx; | |
300 + int wy = winy + win.ch - dc.font.descent; | |
301 + | |
302 +#if UNDERCURL_STYLE == UNDERCURL_CURLY | |
303 + // Draw waves | |
304 + int narcs = charlen * 2 + 1; | |
305 + XArc *arcs = xmalloc(sizeof(XArc) * narcs); | |
306 + | |
307 + int i = 0; | |
308 + for (i = 0; i < charlen-1; i++) { | |
309 + arcs[i*2] = (XArc) { | |
310 + .x = wx + win.cw * i + ww / 4, | |
311 + .y = wy, | |
312 + .width = win.cw / 2, | |
313 + .height = wh, | |
314 + .angle1 = 0, | |
315 + .angle2 = 180 * 64 | |
316 + }; | |
317 + arcs[i*2+1] = (XArc) { | |
318 + .x = wx + win.cw * i + ww * 0.7… | |
319 + .y = wy, | |
320 + .width = win.cw/2, | |
321 + .height = wh, | |
322 + .angle1 = 180 * 64, | |
323 + .angle2 = 180 * 64 | |
324 + }; | |
325 + } | |
326 + // Last wave | |
327 + arcs[i*2] = (XArc) {wx + ww * i + ww / 4, wy, w… | |
328 + 0, 180 * 64 }; | |
329 + // Last wave tail | |
330 + arcs[i*2+1] = (XArc) {wx + ww * i + ww * 0.75, … | |
331 + wh, 180 * 64, 90 * 64}; | |
332 + // First wave tail | |
333 + i++; | |
334 + arcs[i*2] = (XArc) {wx - ww/4 - 1, wy, ceil(ww … | |
335 + 90 * 64 }; | |
336 + | |
337 + XDrawArcs(xw.dpy, XftDrawDrawable(xw.draw), ugc… | |
338 + | |
339 + free(arcs); | |
340 +#elif UNDERCURL_STYLE == UNDERCURL_SPIKY | |
341 + // Make the underline corridor larger | |
342 + /* | |
343 + wy -= wh; | |
344 + */ | |
345 + wh *= 2; | |
346 + | |
347 + // Set the angle of the slope to 45° | |
348 + ww = wh; | |
349 + | |
350 + // Position of wave is independent of word, it'… | |
351 + wx = (wx / (ww/2)) * (ww/2); | |
352 + | |
353 + int marginStart = winx - wx; | |
354 + | |
355 + // Calculate number of points with floating pre… | |
356 + float n = width; … | |
357 + n = (n / ww) * 2; … | |
358 + n += 2; … | |
359 + int npoints = n; … | |
360 + | |
361 + // Total length of underline | |
362 + float waveLength = 0; | |
363 + | |
364 + if (npoints >= 3) { | |
365 + // We add an aditional slot in case we … | |
366 + XPoint *points = xmalloc(sizeof(XPoint)… | |
367 + | |
368 + // First point (Starts with the word bo… | |
369 + points[0] = (XPoint) { | |
370 + .x = wx + marginStart, | |
371 + .y = (isSlopeRising(wx, 0, ww)) | |
372 + ? (wy - marginStart + w… | |
373 + : (wy + marginStart) | |
374 + }; | |
375 + | |
376 + // Second point (Goes back to the absol… | |
377 + points[1] = (XPoint) { | |
378 + .x = (ww/2.f) - marginStart, | |
379 + .y = (isSlopeRising(wx, 1, ww)) | |
380 + ? (ww/2.f - marginStart) | |
381 + : (-ww/2.f + marginStar… | |
382 + }; | |
383 + waveLength += (ww/2.f) - marginStart; | |
384 + | |
385 + // The rest of the points | |
386 + for (int i = 2; i < npoints-1; i++) { | |
387 + points[i] = (XPoint) { | |
388 + .x = ww/2, | |
389 + .y = (isSlopeRising(wx,… | |
390 + ? wh/2 | |
391 + : -wh/2 | |
392 + }; | |
393 + waveLength += ww/2; | |
394 + } | |
395 + | |
396 + // Last point | |
397 + points[npoints-1] = (XPoint) { | |
398 + .x = ww/2, | |
399 + .y = (isSlopeRising(wx, npoints… | |
400 + ? wh/2 | |
401 + : -wh/2 | |
402 + }; | |
403 + waveLength += ww/2; | |
404 + | |
405 + // End | |
406 + if (waveLength < width) { // Add a bonu… | |
407 + int marginEnd = width - waveLen… | |
408 + points[npoints] = (XPoint) { | |
409 + .x = marginEnd, | |
410 + .y = (isSlopeRising(wx,… | |
411 + ? (marginEnd) | |
412 + : (-marginEnd) | |
413 + }; | |
414 + | |
415 + npoints++; | |
416 + } else if (waveLength > width) { // Is … | |
417 + int marginEnd = waveLength - wi… | |
418 + points[npoints-1].x -= marginEn… | |
419 + if (isSlopeRising(wx, npoints-1… | |
420 + points[npoints-1].y -= … | |
421 + else | |
422 + points[npoints-1].y += … | |
423 + } | |
424 + | |
425 + // Draw the lines | |
426 + XDrawLines(xw.dpy, XftDrawDrawable(xw.d… | |
427 + CoordModePrevious); | |
428 + | |
429 + // Draw a second underline with an offs… | |
430 + if ( ((win.ch / (widthThreshold/2)) % 2… | |
431 + points[0].x++; | |
432 + | |
433 + XDrawLines(xw.dpy, XftDrawDrawa… | |
434 + npoints, CoordM… | |
435 + } | |
436 + | |
437 + // Free resources | |
438 + free(points); | |
439 + } | |
440 +#else // UNDERCURL_CAPPED | |
441 + // Cap is half of wave width | |
442 + float capRatio = 0.5f; | |
443 + | |
444 + // Make the underline corridor larger | |
445 + wh *= 2; | |
446 + | |
447 + // Set the angle of the slope to 45° | |
448 + ww = wh; | |
449 + ww *= 1 + capRatio; // Add a bit of width for t… | |
450 + | |
451 + // Position of wave is independent of word, it'… | |
452 + wx = (wx / ww) * ww; | |
453 + | |
454 + float marginStart; | |
455 + switch(getSlope(winx, 0, ww)) { | |
456 + case UNDERCURL_SLOPE_ASCENDING: | |
457 + marginStart = winx - wx; | |
458 + break; | |
459 + case UNDERCURL_SLOPE_TOP_CAP: | |
460 + marginStart = winx - (wx + (ww … | |
461 + break; | |
462 + case UNDERCURL_SLOPE_DESCENDING: | |
463 + marginStart = winx - (wx + (ww … | |
464 + break; | |
465 + case UNDERCURL_SLOPE_BOTTOM_CAP: | |
466 + marginStart = winx - (wx + (ww … | |
467 + break; | |
468 + } | |
469 + | |
470 + // Calculate number of points with floating pre… | |
471 + float n = width; … | |
472 + … | |
473 + n = (n / ww) * 4; … | |
474 + n += 2; … | |
475 + int npoints = n; … | |
476 + | |
477 + // Position of the pen to draw the lines | |
478 + float penX = 0; | |
479 + float penY = 0; | |
480 + | |
481 + if (npoints >= 3) { | |
482 + XPoint *points = xmalloc(sizeof(XPoint)… | |
483 + | |
484 + // First point (Starts with the word bo… | |
485 + penX = winx; | |
486 + switch (getSlope(winx, 0, ww)) { | |
487 + case UNDERCURL_SLOPE_ASCENDING: | |
488 + penY = wy + wh/2.f - ma… | |
489 + break; | |
490 + case UNDERCURL_SLOPE_TOP_CAP: | |
491 + penY = wy; | |
492 + break; | |
493 + case UNDERCURL_SLOPE_DESCENDING: | |
494 + penY = wy + marginStart; | |
495 + break; | |
496 + case UNDERCURL_SLOPE_BOTTOM_CAP: | |
497 + penY = wy + wh/2.f; | |
498 + break; | |
499 + } | |
500 + points[0].x = penX; | |
501 + points[0].y = penY; | |
502 + | |
503 + // Second point (Goes back to the absol… | |
504 + switch (getSlope(winx, 1, ww)) { | |
505 + case UNDERCURL_SLOPE_ASCENDING: | |
506 + penX += ww * (1.f/6.f) … | |
507 + penY += 0; | |
508 + break; | |
509 + case UNDERCURL_SLOPE_TOP_CAP: | |
510 + penX += ww * (2.f/6.f) … | |
511 + penY += -wh/2.f + margi… | |
512 + break; | |
513 + case UNDERCURL_SLOPE_DESCENDING: | |
514 + penX += ww * (1.f/6.f) … | |
515 + penY += 0; | |
516 + break; | |
517 + case UNDERCURL_SLOPE_BOTTOM_CAP: | |
518 + penX += ww * (2.f/6.f) … | |
519 + penY += -marginStart + … | |
520 + break; | |
521 + } | |
522 + points[1].x = penX; | |
523 + points[1].y = penY; | |
524 + | |
525 + // The rest of the points | |
526 + for (int i = 2; i < npoints; i++) { | |
527 + switch (getSlope(winx, i, ww)) { | |
528 + case UNDERCURL_SLOPE_AS… | |
529 + case UNDERCURL_SLOPE_DE… | |
530 + penX += ww * (1… | |
531 + penY += 0; | |
532 + break; | |
533 + case UNDERCURL_SLOPE_TO… | |
534 + penX += ww * (2… | |
535 + penY += -wh / 2… | |
536 + break; | |
537 + case UNDERCURL_SLOPE_BO… | |
538 + penX += ww * (2… | |
539 + penY += wh / 2.… | |
540 + break; | |
541 + } | |
542 + points[i].x = penX; | |
543 + points[i].y = penY; | |
544 + } | |
545 + | |
546 + // End | |
547 + float waveLength = penX - winx; | |
548 + if (waveLength < width) { // Add a bonu… | |
549 + int marginEnd = width - waveLen… | |
550 + penX += marginEnd; | |
551 + switch(getSlope(winx, npoints, … | |
552 + case UNDERCURL_SLOPE_AS… | |
553 + case UNDERCURL_SLOPE_DE… | |
554 + //penY += 0; | |
555 + break; | |
556 + case UNDERCURL_SLOPE_TO… | |
557 + penY += -margin… | |
558 + break; | |
559 + case UNDERCURL_SLOPE_BO… | |
560 + penY += marginE… | |
561 + break; | |
562 + } | |
563 + | |
564 + points[npoints].x = penX; | |
565 + points[npoints].y = penY; | |
566 + | |
567 + npoints++; | |
568 + } else if (waveLength > width) { // Is … | |
569 + int marginEnd = waveLength - wi… | |
570 + points[npoints-1].x -= marginEn… | |
571 + switch(getSlope(winx, npoints-1… | |
572 + case UNDERCURL_SLOPE_TO… | |
573 + points[npoints-… | |
574 + break; | |
575 + case UNDERCURL_SLOPE_BO… | |
576 + points[npoints-… | |
577 + break; | |
578 + default: | |
579 + break; | |
580 + } | |
581 + } | |
582 + | |
583 + // Draw the lines | |
584 + XDrawLines(xw.dpy, XftDrawDrawable(xw.d… | |
585 + CoordModeOrigin); | |
586 + | |
587 + // Draw a second underline with an offs… | |
588 + if ( ((win.ch / (widthThreshold/2)) % 2… | |
589 + for (int i = 0; i < npoints; i+… | |
590 + points[i].x++; | |
591 + | |
592 + XDrawLines(xw.dpy, XftDrawDrawa… | |
593 + npoints, CoordM… | |
594 + } | |
595 + | |
596 + // Free resources | |
597 + free(points); | |
598 + } | |
599 +#endif | |
600 + } | |
601 + | |
602 + XFreeGC(xw.dpy, ugc); | |
603 } | |
604 | |
605 if (base.mode & ATTR_STRUCK) { |