Introduction
Introduction Statistics Contact Development Disclaimer Help
st-ligatures-scrollback-20240105-0.9.diff - sites - public wiki contents of suc…
git clone git://git.suckless.org/sites
Log
Files
Refs
---
st-ligatures-scrollback-20240105-0.9.diff (18754B)
---
1 diff --git a/Makefile b/Makefile
2 index 470ac86..38240da 100644
3 --- a/Makefile
4 +++ b/Makefile
5 @@ -4,7 +4,7 @@
6
7 include config.mk
8
9 -SRC = st.c x.c
10 +SRC = st.c x.c hb.c
11 OBJ = $(SRC:.c=.o)
12
13 all: options st
14 @@ -22,7 +22,8 @@ config.h:
15 $(CC) $(STCFLAGS) -c $<
16
17 st.o: config.h st.h win.h
18 -x.o: arg.h config.h st.h win.h
19 +x.o: arg.h config.h st.h win.h hb.h
20 +hb.o: st.h
21
22 $(OBJ): config.h config.mk
23
24 diff --git a/config.mk b/config.mk
25 index 1e306f8..3e13e53 100644
26 --- a/config.mk
27 +++ b/config.mk
28 @@ -15,10 +15,12 @@ PKG_CONFIG = pkg-config
29 # includes and libs
30 INCS = -I$(X11INC) \
31 `$(PKG_CONFIG) --cflags fontconfig` \
32 - `$(PKG_CONFIG) --cflags freetype2`
33 + `$(PKG_CONFIG) --cflags freetype2` \
34 + `$(PKG_CONFIG) --cflags harfbuzz`
35 LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \
36 `$(PKG_CONFIG) --libs fontconfig` \
37 - `$(PKG_CONFIG) --libs freetype2`
38 + `$(PKG_CONFIG) --libs freetype2` \
39 + `$(PKG_CONFIG) --libs harfbuzz`
40
41 # flags
42 STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
43 diff --git a/hb.c b/hb.c
44 new file mode 100644
45 index 0000000..99412c8
46 --- /dev/null
47 +++ b/hb.c
48 @@ -0,0 +1,125 @@
49 +#include <stdlib.h>
50 +#include <stdio.h>
51 +#include <math.h>
52 +#include <X11/Xft/Xft.h>
53 +#include <X11/cursorfont.h>
54 +#include <hb.h>
55 +#include <hb-ft.h>
56 +
57 +#include "st.h"
58 +#include "hb.h"
59 +
60 +#define FEATURE(c1,c2,c3,c4) { .tag = HB_TAG(c1,c2,c3,c4), .value = 1, …
61 +#define BUFFER_STEP 256
62 +
63 +hb_font_t *hbfindfont(XftFont *match);
64 +
65 +typedef struct {
66 + XftFont *match;
67 + hb_font_t *font;
68 +} HbFontMatch;
69 +
70 +typedef struct {
71 + size_t capacity;
72 + HbFontMatch *fonts;
73 +} HbFontCache;
74 +
75 +static HbFontCache hbfontcache = { 0, NULL };
76 +
77 +typedef struct {
78 + size_t capacity;
79 + Rune *runes;
80 +} RuneBuffer;
81 +
82 +static RuneBuffer hbrunebuffer = { 0, NULL };
83 +
84 +/*
85 + * Poplulate the array with a list of font features, wrapped in FEATURE…
86 + * e. g.
87 + * FEATURE('c', 'a', 'l', 't'), FEATURE('d', 'l', 'i', 'g')
88 + */
89 +hb_feature_t features[] = { };
90 +
91 +void
92 +hbunloadfonts()
93 +{
94 + for (int i = 0; i < hbfontcache.capacity; i++) {
95 + hb_font_destroy(hbfontcache.fonts[i].font);
96 + XftUnlockFace(hbfontcache.fonts[i].match);
97 + }
98 +
99 + if (hbfontcache.fonts != NULL) {
100 + free(hbfontcache.fonts);
101 + hbfontcache.fonts = NULL;
102 + }
103 + hbfontcache.capacity = 0;
104 +}
105 +
106 +hb_font_t *
107 +hbfindfont(XftFont *match)
108 +{
109 + for (int i = 0; i < hbfontcache.capacity; i++) {
110 + if (hbfontcache.fonts[i].match == match)
111 + return hbfontcache.fonts[i].font;
112 + }
113 +
114 + /* Font not found in cache, caching it now. */
115 + hbfontcache.fonts = realloc(hbfontcache.fonts, sizeof(HbFontMat…
116 + FT_Face face = XftLockFace(match);
117 + hb_font_t *font = hb_ft_font_create(face, NULL);
118 + if (font == NULL)
119 + die("Failed to load Harfbuzz font.");
120 +
121 + hbfontcache.fonts[hbfontcache.capacity].match = match;
122 + hbfontcache.fonts[hbfontcache.capacity].font = font;
123 + hbfontcache.capacity += 1;
124 +
125 + return font;
126 +}
127 +
128 +void hbtransform(HbTransformData *data, XftFont *xfont, const Glyph *gl…
129 + ushort mode = USHRT_MAX;
130 + unsigned int glyph_count;
131 + int rune_idx, glyph_idx, end = start + length;
132 +
133 + hb_font_t *font = hbfindfont(xfont);
134 + if (font == NULL)
135 + return;
136 +
137 + hb_buffer_t *buffer = hb_buffer_create();
138 + hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
139 + hb_buffer_set_cluster_level(buffer, HB_BUFFER_CLUSTER_LEVEL_MON…
140 +
141 + /* Resize the buffer if required length is larger. */
142 + if (hbrunebuffer.capacity < length) {
143 + hbrunebuffer.capacity = (length / BUFFER_STEP + 1) * BU…
144 + hbrunebuffer.runes = realloc(hbrunebuffer.runes, hbrune…
145 + }
146 +
147 + /* Fill buffer with codepoints. */
148 + for (rune_idx = 0, glyph_idx = start; glyph_idx < end; glyph_id…
149 + hbrunebuffer.runes[rune_idx] = glyphs[glyph_idx].u;
150 + mode = glyphs[glyph_idx].mode;
151 + if (mode & ATTR_WDUMMY)
152 + hbrunebuffer.runes[rune_idx] = 0x0020;
153 + }
154 + hb_buffer_add_codepoints(buffer, hbrunebuffer.runes, length, 0,…
155 +
156 + /* Shape the segment. */
157 + hb_shape(font, buffer, features, sizeof(features)/sizeof(hb_fea…
158 +
159 + /* Get new glyph info. */
160 + hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, &glyp…
161 + hb_glyph_position_t *pos = hb_buffer_get_glyph_positions(buffer…
162 +
163 + /* Fill the output. */
164 + data->buffer = buffer;
165 + data->glyphs = info;
166 + data->positions = pos;
167 + data->count = glyph_count;
168 +}
169 +
170 +void hbcleanup(HbTransformData *data) {
171 + hb_buffer_destroy(data->buffer);
172 + memset(data, 0, sizeof(HbTransformData));
173 +}
174 diff --git a/hb.h b/hb.h
175 new file mode 100644
176 index 0000000..3b0ef44
177 --- /dev/null
178 +++ b/hb.h
179 @@ -0,0 +1,14 @@
180 +#include <X11/Xft/Xft.h>
181 +#include <hb.h>
182 +#include <hb-ft.h>
183 +
184 +typedef struct {
185 + hb_buffer_t *buffer;
186 + hb_glyph_info_t *glyphs;
187 + hb_glyph_position_t *positions;
188 + unsigned int count;
189 +} HbTransformData;
190 +
191 +void hbunloadfonts();
192 +void hbtransform(HbTransformData *, XftFont *, const Glyph *, int, int);
193 +void hbcleanup(HbTransformData *);
194 diff --git a/st.c b/st.c
195 index 79ee9ba..7675db6 100644
196 --- a/st.c
197 +++ b/st.c
198 @@ -2711,7 +2711,8 @@ draw(void)
199 drawregion(0, 0, term.col, term.row);
200 if (term.scr == 0)
201 xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
202 - term.ocx, term.ocy, term.line[term.ocy]…
203 + term.ocx, term.ocy, term.line[term.ocy]…
204 + term.line[term.ocy], term.col);
205 term.ocx = cx;
206 term.ocy = term.c.y;
207 xfinishdraw();
208 diff --git a/st.h b/st.h
209 index 818a6f8..4e584b6 100644
210 --- a/st.h
211 +++ b/st.h
212 @@ -11,7 +11,8 @@
213 #define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d))
214 #define DEFAULT(a, b) (a) = (a) ? (a) : (b)
215 #define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b)…
216 -#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg !=…
217 +#define ATTRCMP(a, b) (((a).mode & (~ATTR_WRAP)) != ((b)…
218 + (a).fg != (b).fg || \
219 (a).bg != (b).bg)
220 #define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \
221 (t1.tv_nsec-t2.tv_nsec)/1E6)
222 diff --git a/win.h b/win.h
223 index 6de960d..94679e4 100644
224 --- a/win.h
225 +++ b/win.h
226 @@ -25,7 +25,7 @@ enum win_mode {
227
228 void xbell(void);
229 void xclipcopy(void);
230 -void xdrawcursor(int, int, Glyph, int, int, Glyph);
231 +void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int);
232 void xdrawline(Line, int, int, int);
233 void xfinishdraw(void);
234 void xloadcols(void);
235 diff --git a/x.c b/x.c
236 index 2a3bd38..0bb51ff 100644
237 --- a/x.c
238 +++ b/x.c
239 @@ -19,6 +19,7 @@ char *argv0;
240 #include "arg.h"
241 #include "st.h"
242 #include "win.h"
243 +#include "hb.h"
244
245 /* types used in config.h */
246 typedef struct {
247 @@ -141,8 +142,9 @@ typedef struct {
248 } DC;
249
250 static inline ushort sixd_to_16bit(int);
251 +static void xresetfontsettings(ushort mode, Font **font, int *frcflags);
252 static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, …
253 -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, i…
254 +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, i…
255 static void xdrawglyph(Glyph, int, int);
256 static void xclear(int, int, int, int);
257 static int xgeommasktogravity(int);
258 @@ -757,7 +759,7 @@ xresize(int col, int row)
259 xclear(0, 0, win.w, win.h);
260
261 /* resize to new width */
262 - xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec));
263 + xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec) *…
264 }
265
266 ushort
267 @@ -1062,6 +1064,9 @@ xunloadfont(Font *f)
268 void
269 xunloadfonts(void)
270 {
271 + /* Clear Harfbuzz font cache. */
272 + hbunloadfonts();
273 +
274 /* Free the loaded fonts in the font cache. */
275 while (frclen > 0)
276 XftFontClose(xw.dpy, frc[--frclen].font);
277 @@ -1185,7 +1190,7 @@ xinit(int cols, int rows)
278 XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h);
279
280 /* font spec buffer */
281 - xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec));
282 + xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec) * 4);
283
284 /* Xft rendering context */
285 xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap);
286 @@ -1239,6 +1244,22 @@ xinit(int cols, int rows)
287 xsel.xtarget = XA_STRING;
288 }
289
290 +void
291 +xresetfontsettings(ushort mode, Font **font, int *frcflags)
292 +{
293 + *font = &dc.font;
294 + if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) {
295 + *font = &dc.ibfont;
296 + *frcflags = FRC_ITALICBOLD;
297 + } else if (mode & ATTR_ITALIC) {
298 + *font = &dc.ifont;
299 + *frcflags = FRC_ITALIC;
300 + } else if (mode & ATTR_BOLD) {
301 + *font = &dc.bfont;
302 + *frcflags = FRC_BOLD;
303 + }
304 +}
305 +
306 int
307 xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int l…
308 {
309 @@ -1253,128 +1274,157 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, c…
310 FcPattern *fcpattern, *fontpattern;
311 FcFontSet *fcsets[] = { NULL };
312 FcCharSet *fccharset;
313 - int i, f, numspecs = 0;
314 + int i, f, length = 0, start = 0, numspecs = 0;
315 + float cluster_xp = xp, cluster_yp = yp;
316 + HbTransformData shaped = { 0 };
317 +
318 + /* Initial values. */
319 + mode = prevmode = glyphs[0].mode & ~ATTR_WRAP;
320 + xresetfontsettings(mode, &font, &frcflags);
321
322 for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) {
323 - /* Fetch rune and mode for current glyph. */
324 - rune = glyphs[i].u;
325 - mode = glyphs[i].mode;
326 + mode = glyphs[i].mode & ~ATTR_WRAP;
327
328 /* Skip dummy wide-character spacing. */
329 - if (mode == ATTR_WDUMMY)
330 + if (mode & ATTR_WDUMMY && i < (len - 1))
331 continue;
332
333 - /* Determine font for glyph if different from previous …
334 - if (prevmode != mode) {
335 - prevmode = mode;
336 - font = &dc.font;
337 - frcflags = FRC_NORMAL;
338 - runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f…
339 - if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD))…
340 - font = &dc.ibfont;
341 - frcflags = FRC_ITALICBOLD;
342 - } else if (mode & ATTR_ITALIC) {
343 - font = &dc.ifont;
344 - frcflags = FRC_ITALIC;
345 - } else if (mode & ATTR_BOLD) {
346 - font = &dc.bfont;
347 - frcflags = FRC_BOLD;
348 + if (
349 + prevmode != mode
350 + || ATTRCMP(glyphs[start], glyphs[i])
351 + || selected(x + i, y) != selected(x + start, y)
352 + || i == (len - 1)
353 + ) {
354 + /* Handle 1-character wide segments and end of …
355 + length = i - start;
356 + if (i == start) {
357 + length = 1;
358 + } else if (i == (len - 1)) {
359 + length = (i - start + 1);
360 }
361 - yp = winy + font->ascent;
362 - }
363
364 - /* Lookup character index with default font. */
365 - glyphidx = XftCharIndex(xw.dpy, font->match, rune);
366 - if (glyphidx) {
367 - specs[numspecs].font = font->match;
368 - specs[numspecs].glyph = glyphidx;
369 - specs[numspecs].x = (short)xp;
370 - specs[numspecs].y = (short)yp;
371 - xp += runewidth;
372 - numspecs++;
373 - continue;
374 - }
375 -
376 - /* Fallback on font cache, search the font cache for ma…
377 - for (f = 0; f < frclen; f++) {
378 - glyphidx = XftCharIndex(xw.dpy, frc[f].font, ru…
379 - /* Everything correct. */
380 - if (glyphidx && frc[f].flags == frcflags)
381 - break;
382 - /* We got a default font for a not found glyph.…
383 - if (!glyphidx && frc[f].flags == frcflags
384 - && frc[f].unicodep == rune) {
385 - break;
386 + /* Shape the segment. */
387 + hbtransform(&shaped, font->match, glyphs, start…
388 + runewidth = win.cw * ((glyphs[start].mode & ATT…
389 + cluster_xp = xp; cluster_yp = yp;
390 + for (int code_idx = 0; code_idx < shaped.count;…
391 + int idx = shaped.glyphs[code_idx].clust…
392 +
393 + if (glyphs[start + idx].mode & ATTR_WDU…
394 + continue;
395 +
396 + /* Advance the drawing cursor if we've …
397 + if (code_idx > 0 && idx != shaped.glyph…
398 + xp += runewidth;
399 + cluster_xp = xp;
400 + cluster_yp = yp;
401 + runewidth = win.cw * ((glyphs[s…
402 + }
403 +
404 + if (shaped.glyphs[code_idx].codepoint !…
405 + /* If symbol is found, put it i…
406 + specs[numspecs].font = font->ma…
407 + specs[numspecs].glyph = shaped.…
408 + specs[numspecs].x = cluster_xp …
409 + specs[numspecs].y = cluster_yp …
410 + cluster_xp += shaped.positions[…
411 + cluster_yp += shaped.positions[…
412 + numspecs++;
413 + } else {
414 + /* If it's not found, try to fe…
415 + rune = glyphs[start + idx].u;
416 + for (f = 0; f < frclen; f++) {
417 + glyphidx = XftCharIndex…
418 + /* Everything correct. …
419 + if (glyphidx && frc[f].…
420 + break;
421 + /* We got a default fon…
422 + if (!glyphidx && frc[f]…
423 + && frc[…
424 + break;
425 + }
426 + }
427 +
428 + /* Nothing was found. Use fontc…
429 + if (f >= frclen) {
430 + if (!font->set)
431 + font->set = FcF…
432 + …
433 + fcsets[0] = font->set;
434 +
435 + /*
436 + * Nothing was found in…
437 + * some dozen of Fontco…
438 + * font for one single …
439 + *
440 + * Xft and fontconfig a…
441 + */
442 + fcpattern = FcPatternDu…
443 + fccharset = FcCharSetCr…
444 +
445 + FcCharSetAddChar(fcchar…
446 + FcPatternAddCharSet(fcp…
447 + fcchars…
448 + FcPatternAddBool(fcpatt…
449 +
450 + FcConfigSubstitute(0, f…
451 + FcMatch…
452 + FcDefaultSubstitute(fcp…
453 +
454 + fontpattern = FcFontSet…
455 + fcpatte…
456 +
457 + /* Allocate memory for …
458 + if (frclen >= frccap) {
459 + frccap += 16;
460 + frc = xrealloc(…
461 + }
462 +
463 + frc[frclen].font = XftF…
464 + fontpat…
465 + if (!frc[frclen].font)
466 + die("XftFontOpe…
467 + strerro…
468 + frc[frclen].flags = frc…
469 + frc[frclen].unicodep = …
470 +
471 + glyphidx = XftCharIndex…
472 +
473 + f = frclen;
474 + frclen++;
475 +
476 + FcPatternDestroy(fcpatt…
477 + FcCharSetDestroy(fcchar…
478 + }
479 +
480 + specs[numspecs].font = frc[f].f…
481 + specs[numspecs].glyph = glyphid…
482 + specs[numspecs].x = (short)xp;
483 + specs[numspecs].y = (short)yp;
484 + numspecs++;
485 + }
486 }
487 - }
488
489 - /* Nothing was found. Use fontconfig to find matching f…
490 - if (f >= frclen) {
491 - if (!font->set)
492 - font->set = FcFontSort(0, font->pattern,
493 - 1, 0, &fcres);
494 - fcsets[0] = font->set;
495 + /* Cleanup and get ready for next segment. */
496 + hbcleanup(&shaped);
497 + start = i;
498
499 - /*
500 - * Nothing was found in the cache. Now use
501 - * some dozen of Fontconfig calls to get the
502 - * font for one single character.
503 - *
504 - * Xft and fontconfig are design failures.
505 - */
506 - fcpattern = FcPatternDuplicate(font->pattern);
507 - fccharset = FcCharSetCreate();
508 -
509 - FcCharSetAddChar(fccharset, rune);
510 - FcPatternAddCharSet(fcpattern, FC_CHARSET,
511 - fccharset);
512 - FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
513 -
514 - FcConfigSubstitute(0, fcpattern,
515 - FcMatchPattern);
516 - FcDefaultSubstitute(fcpattern);
517 -
518 - fontpattern = FcFontSetMatch(0, fcsets, 1,
519 - fcpattern, &fcres);
520 -
521 - /* Allocate memory for the new cache entry. */
522 - if (frclen >= frccap) {
523 - frccap += 16;
524 - frc = xrealloc(frc, frccap * sizeof(Fon…
525 + /* Determine font for glyph if different from p…
526 + if (prevmode != mode) {
527 + prevmode = mode;
528 + xresetfontsettings(mode, &font, &frcfla…
529 + yp = winy + font->ascent;
530 }
531 -
532 - frc[frclen].font = XftFontOpenPattern(xw.dpy,
533 - fontpattern);
534 - if (!frc[frclen].font)
535 - die("XftFontOpenPattern failed seeking …
536 - strerror(errno));
537 - frc[frclen].flags = frcflags;
538 - frc[frclen].unicodep = rune;
539 -
540 - glyphidx = XftCharIndex(xw.dpy, frc[frclen].fon…
541 -
542 - f = frclen;
543 - frclen++;
544 -
545 - FcPatternDestroy(fcpattern);
546 - FcCharSetDestroy(fccharset);
547 }
548 -
549 - specs[numspecs].font = frc[f].font;
550 - specs[numspecs].glyph = glyphidx;
551 - specs[numspecs].x = (short)xp;
552 - specs[numspecs].y = (short)yp;
553 - xp += runewidth;
554 - numspecs++;
555 }
556
557 + hbcleanup(&shaped);
558 return numspecs;
559 }
560
561 void
562 -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len,…
563 +xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len,…
564 {
565 - int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
566 int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
567 width = charlen * win.cw;
568 Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
569 @@ -1510,21 +1560,24 @@ void
570 xdrawglyph(Glyph g, int x, int y)
571 {
572 int numspecs;
573 - XftGlyphFontSpec spec;
574 + XftGlyphFontSpec *specs = xw.specbuf;
575
576 - numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
577 - xdrawglyphfontspecs(&spec, g, numspecs, x, y);
578 + numspecs = xmakeglyphfontspecs(specs, &g, 1, x, y);
579 + xdrawglyphfontspecs(specs, g, numspecs, x, y, (g.mode & ATTR_WI…
580 }
581
582 void
583 -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
584 +xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line lin…
585 {
586 Color drawcol;
587
588 /* remove the old cursor */
589 if (selected(ox, oy))
590 og.mode ^= ATTR_REVERSE;
591 - xdrawglyph(og, ox, oy);
592 +
593 + /* Redraw the line where cursor was previously.
594 + * It will restore the ligatures broken by the cursor. */
595 + xdrawline(line, 0, oy, len);
596
597 if (IS_SET(MODE_HIDE))
598 return;
599 @@ -1652,18 +1705,16 @@ xdrawline(Line line, int x1, int y1, int x2)
600 Glyph base, new;
601 XftGlyphFontSpec *specs = xw.specbuf;
602
603 - numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y…
604 i = ox = 0;
605 - for (x = x1; x < x2 && i < numspecs; x++) {
606 + for (x = x1; x < x2; x++) {
607 new = line[x];
608 if (new.mode == ATTR_WDUMMY)
609 continue;
610 if (selected(x, y1))
611 new.mode ^= ATTR_REVERSE;
612 - if (i > 0 && ATTRCMP(base, new)) {
613 - xdrawglyphfontspecs(specs, base, i, ox, y1);
614 - specs += i;
615 - numspecs -= i;
616 + if ((i > 0) && ATTRCMP(base, new)) {
617 + numspecs = xmakeglyphfontspecs(specs, &line[ox]…
618 + xdrawglyphfontspecs(specs, base, numspecs, ox, …
619 i = 0;
620 }
621 if (i == 0) {
622 @@ -1672,8 +1723,10 @@ xdrawline(Line line, int x1, int y1, int x2)
623 }
624 i++;
625 }
626 - if (i > 0)
627 - xdrawglyphfontspecs(specs, base, i, ox, y1);
628 + if (i > 0) {
629 + numspecs = xmakeglyphfontspecs(specs, &line[ox], x2 - o…
630 + xdrawglyphfontspecs(specs, base, numspecs, ox, y1, x2 -…
631 + }
632 }
633
634 void
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.