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