URI: 
       glyph wide support - st - simple terminal
  HTML git clone https://git.parazyd.org/st
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit cc6999c8b6eaa714222eecd519d8212781190ce7
   DIR parent 97988681134630a84c9824d83027d0f429d427e8
  HTML Author: parazyd <parazyd@dyne.org>
       Date:   Tue, 26 Apr 2022 20:48:13 +0200
       
       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
       @@ -145,7 +145,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);
       @@ -1444,7 +1444,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,
       @@ -1547,47 +1547,40 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
                        bg = &revbg;
                }
        
       -        /* 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
       @@ -1597,7 +1590,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
       @@ -1735,32 +1728,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