diff --git a/_suckless/st/patches/10-fix-wide-glyphs.diff b/_suckless/st/patches/10-fix-wide-glyphs.diff new file mode 100644 index 0000000..ffd2720 --- /dev/null +++ b/_suckless/st/patches/10-fix-wide-glyphs.diff @@ -0,0 +1,204 @@ +diff --git a/st.h b/st.h +index a25605c..96b285c 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/x.c b/x.c +index 12008ef..b668c83 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); +@@ -1457,14 +1457,13 @@ 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, + width = charlen * win.cw; + Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; + XRenderColor colfg, colbg; +- XRectangle r; + + /* Fallback on color display for attributes not supported by the font */ + if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { +@@ -1548,47 +1547,47 @@ 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 + 1, +- width, 1); +- } ++ 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); + +- if (base.mode & ATTR_STRUCK) { +- XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, +- width, 1); ++ /* Fill the background */ ++ XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); + } + +- /* Reset clip to none. */ +- XftDrawSetClip(xw.draw, 0); ++ if (dmode & DRAW_FG) { ++/* ++ if (base.mode & ATTR_BOXDRAW) { ++ drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len); ++ } else { ++*/ ++ /* 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 +@@ -1598,7 +1597,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 +1734,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