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