Apply wide glyph support patch - st - personal variant of st
 (HTM) git clone https://git.drkhsh.at/st.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 69e757d755bc187b51512bc58beebb8d48570207
 (DIR) parent bc2834356ed1bbf2cdfb7bb3cf307568e6235539
 (HTM) Author: drkhsh <me@drkhsh.at>
       Date:   Wed, 10 Jan 2024 10:11:12 +0100
       
       Apply wide glyph support patch
       
       This patch fixes wide glyphs truncation. Based on
       https://github.com/LukeSmithxyz/st/commit/e3b821dcb3511d60341dec35ee05a4a0abfef7f2
       
       https://st.suckless.org/patches/glyph_wide_support/
       
       Diffstat:
         M st.h                                |       6 ++++++
         M x.c                                 |     134 ++++++++++++++++----------------
       
       2 files changed, 73 insertions(+), 67 deletions(-)
       ---
 (DIR) diff --git 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,
 (DIR) diff --git 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);
       @@ -1373,7 +1373,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,
       @@ -1464,47 +1464,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
       @@ -1514,7 +1507,7 @@ 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
       @@ -1649,32 +1642,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