Introduction
Introduction Statistics Contact Development Disclaimer Help
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) {
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.