commit c80ff623dc2b8052d5edf1a7af272d87c66e1f3c
parent 7fddff3e66001954bf3c829a384b0d7cc368d1d0
Author: Iskustvo <iskustvo@yahoo.com>
Date:   Sat,  7 Jan 2023 02:02:39 +0100
[st][patch][glyph wide support] patch update
Add new patch which fixes the issue where wide glyphs were not being properly
redrawn during editing.
For more information, see https://github.com/LukeSmithxyz/st/pull/349
Diffstat:
2 files changed, 256 insertions(+), 0 deletions(-)
diff --git a/st.suckless.org/patches/glyph_wide_support/index.md b/st.suckless.org/patches/glyph_wide_support/index.md
@@ -10,6 +10,10 @@ Download
 --------
 * [st-glyph-wide-support-20220411-ef05519.diff](st-glyph-wide-support-20220411-ef05519.diff)
 
+Use this patch if wide glyph characters are still being chopped during editing.
+For all informations about how this looks, why it might and might not happen, look [here](https://github.com/LukeSmithxyz/st/pull/349).
+* [st-glyph-wide-support-20230701-5770f2f.diff](st-glyph-wide-support-20230701-5770f2f.diff)
+
 Use this patch if you are using boxdraw.
 * [st-glyph-wide-support-boxdraw-20220411-ef05519.diff](st-glyph-wide-support-boxdraw-20220411-ef05519.diff)
 
@@ -17,3 +21,4 @@ Authors
 -------
 * Dreomite - Creating the original commit
 * wael - 40663@protonmail.com
+* Iskustvo - Fixing the solution for chopping during editing
diff --git a/st.suckless.org/patches/glyph_wide_support/st-glyph-wide-support-20230701-5770f2f.diff b/st.suckless.org/patches/glyph_wide_support/st-glyph-wide-support-20230701-5770f2f.diff
@@ -0,0 +1,251 @@
+From 5770f2fc02afca341c275fc340bbc5003ecc3df8 Mon Sep 17 00:00:00 2001
+From: Iskustvo <iskustvo@yahoo.com>
+Date: Sat, 7 Jan 2023 01:23:37 +0100
+Subject: [PATCH] [PATCH] add glyph wide support patch
+
+---
+ st.c  |   3 +-
+ st.h  |   6 +++
+ win.h |   2 +-
+ x.c   | 141 ++++++++++++++++++++++++++++++----------------------------
+ 4 files changed, 81 insertions(+), 71 deletions(-)
+
+diff --git a/st.c b/st.c
+index 62def59..cc6c78e 100644
+--- a/st.c
++++ b/st.c
+@@ -2640,7 +2640,8 @@ draw(void)
+ 
+ 	drawregion(0, 0, term.col, term.row);
+ 	xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
+-			term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
++		term.ocx, term.ocy, term.line[term.ocy][term.ocx],
++		term.line[term.ocy], term.col);
+ 	term.ocx = cx;
+ 	term.ocy = term.c.y;
+ 	xfinishdraw();
+diff --git a/st.h b/st.h
+index fd3b0d8..0053050 100644
+--- a/st.h
++++ b/st.h
+@@ -36,6 +36,12 @@ enum glyph_attribute {
+ 	ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
+ };
+ 
++enum drawing_mode {
++    DRAW_NONE = 0,
++    DRAW_BG = 1 << 0,
++    DRAW_FG = 1 << 1,
++};
++
+ enum selection_mode {
+ 	SEL_IDLE = 0,
+ 	SEL_EMPTY = 1,
+diff --git a/win.h b/win.h
+index 6de960d..94679e4 100644
+--- a/win.h
++++ b/win.h
+@@ -25,7 +25,7 @@ enum win_mode {
+ 
+ void xbell(void);
+ void xclipcopy(void);
+-void xdrawcursor(int, int, Glyph, int, int, Glyph);
++void xdrawcursor(int, int, Glyph, int, int, Glyph, Line, int);
+ void xdrawline(Line, int, int, int);
+ void xfinishdraw(void);
+ void xloadcols(void);
+diff --git a/x.c b/x.c
+index aa09997..85deee6 100644
+--- a/x.c
++++ b/x.c
+@@ -142,7 +142,7 @@ typedef struct {
+ 
+ static inline ushort sixd_to_16bit(int);
+ static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int);
+-static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
++static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int);
+ static void xdrawglyph(Glyph, int, int);
+ static void xclear(int, int, int, int);
+ static int xgeommasktogravity(int);
+@@ -1372,7 +1372,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
+ }
+ 
+ void
+-xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
++xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode)
+ {
+ 	int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
+ 	int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch,
+@@ -1463,47 +1463,40 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
+ 	if (base.mode & ATTR_INVISIBLE)
+ 		fg = bg;
+ 
+-	/* Intelligent cleaning up of the borders. */
+-	if (x == 0) {
+-		xclear(0, (y == 0)? 0 : winy, borderpx,
+-			winy + win.ch +
+-			((winy + win.ch >= borderpx + win.th)? win.h : 0));
+-	}
+-	if (winx + width >= borderpx + win.tw) {
+-		xclear(winx + width, (y == 0)? 0 : winy, win.w,
+-			((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
+-	}
+-	if (y == 0)
+-		xclear(winx, 0, winx + width, borderpx);
+-	if (winy + win.ch >= borderpx + win.th)
+-		xclear(winx, winy + win.ch, winx + width, win.h);
+-
+-	/* Clean up the region we want to draw to. */
+-	XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
+-
+-	/* Set the clip region because Xft is sometimes dirty. */
+-	r.x = 0;
+-	r.y = 0;
+-	r.height = win.ch;
+-	r.width = width;
+-	XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1);
+-
+-	/* Render the glyphs. */
+-	XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
+-
+-	/* Render underline and strikethrough. */
+-	if (base.mode & ATTR_UNDERLINE) {
+-		XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1,
+-				width, 1);
+-	}
+-
+-	if (base.mode & ATTR_STRUCK) {
+-		XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3,
+-				width, 1);
+-	}
+-
+-	/* Reset clip to none. */
+-	XftDrawSetClip(xw.draw, 0);
++    if (dmode & DRAW_BG) {
++        /* Intelligent cleaning up of the borders. */
++        if (x == 0) {
++            xclear(0, (y == 0)? 0 : winy, borderpx,
++                   winy + win.ch +
++                   ((winy + win.ch >= borderpx + win.th)? win.h : 0));
++        }
++        if (winx + width >= borderpx + win.tw) {
++            xclear(winx + width, (y == 0)? 0 : winy, win.w,
++                   ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch)));
++        }
++        if (y == 0)
++            xclear(winx, 0, winx + width, borderpx);
++        if (winy + win.ch >= borderpx + win.th)
++            xclear(winx, winy + win.ch, winx + width, win.h);
++        /* Fill the background */
++        XftDrawRect(xw.draw, bg, winx, winy, width, win.ch);
++    }
++
++    if (dmode & DRAW_FG) {
++        /* Render the glyphs. */
++        XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
++
++        /* Render underline and strikethrough. */
++        if (base.mode & ATTR_UNDERLINE) {
++            XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1,
++                        width, 1);
++        }
++
++        if (base.mode & ATTR_STRUCK) {
++            XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3,
++                        width, 1);
++        }
++    }
+ }
+ 
+ void
+@@ -1513,18 +1506,21 @@ xdrawglyph(Glyph g, int x, int y)
+ 	XftGlyphFontSpec spec;
+ 
+ 	numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
+-	xdrawglyphfontspecs(&spec, g, numspecs, x, y);
++	xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG);
+ }
+ 
+ void
+-xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
++xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int len)
+ {
+ 	Color drawcol;
+ 
+ 	/* remove the old cursor */
+ 	if (selected(ox, oy))
+ 		og.mode ^= ATTR_REVERSE;
+-	xdrawglyph(og, ox, oy);
++
++	/* Redraw the line where cursor was previously.
++	 * It will restore wide glyphs and ligatures broken by the cursor. */
++	xdrawline(line, 0, oy, len);
+ 
+ 	if (IS_SET(MODE_HIDE))
+ 		return;
+@@ -1648,32 +1644,39 @@ xstartdraw(void)
+ void
+ xdrawline(Line line, int x1, int y1, int x2)
+ {
+-	int i, x, ox, numspecs;
++	int i, x, ox, numspecs, numspecs_cached;
+ 	Glyph base, new;
+-	XftGlyphFontSpec *specs = xw.specbuf;
+-
+-	numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1);
+-	i = ox = 0;
+-	for (x = x1; x < x2 && i < numspecs; x++) {
+-		new = line[x];
+-		if (new.mode == ATTR_WDUMMY)
+-			continue;
+-		if (selected(x, y1))
+-			new.mode ^= ATTR_REVERSE;
+-		if (i > 0 && ATTRCMP(base, new)) {
+-			xdrawglyphfontspecs(specs, base, i, ox, y1);
+-			specs += i;
+-			numspecs -= i;
+-			i = 0;
+-		}
+-		if (i == 0) {
+-			ox = x;
+-			base = new;
++	XftGlyphFontSpec *specs;
++
++	numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1);
++
++	/* Draw line in 2 passes: background and foreground. This way wide glyphs
++       won't get truncated (#223) */
++	for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) {
++		specs = xw.specbuf;
++		numspecs = numspecs_cached;
++		i = ox = 0;
++		for (x = x1; x < x2 && i < numspecs; x++) {
++			new = line[x];
++			if (new.mode == ATTR_WDUMMY)
++				continue;
++			if (selected(x, y1))
++				new.mode ^= ATTR_REVERSE;
++			if (i > 0 && ATTRCMP(base, new)) {
++				xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
++				specs += i;
++				numspecs -= i;
++				i = 0;
++			}
++			if (i == 0) {
++				ox = x;
++				base = new;
++			}
++			i++;
+ 		}
+-		i++;
++		if (i > 0)
++			xdrawglyphfontspecs(specs, base, i, ox, y1, dmode);
+ 	}
+-	if (i > 0)
+-		xdrawglyphfontspecs(specs, base, i, ox, y1);
+ }
+ 
+ void
+-- 
+2.39.0
+