-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Unofficial patch: https://lists.suckless.org/wiki/2301/4571.html For more information, read: LukeSmithxyz/st#349
- Loading branch information
Showing
1 changed file
with
252 additions
and
0 deletions.
There are no files selected for viewing
252 changes: 252 additions & 0 deletions
252
patches/8-glyph_wide_support/1-st-glyph-wide-support-20230701-5770f2f.diff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,252 @@ | ||
From 37567786b543aacd172c7cd095ce862568ca46f0 Mon Sep 17 00:00:00 2001 | ||
From: Iskustvo <[email protected]> | ||
Date: Sat, 7 Jan 2023 03:37:22 +0100 | ||
Subject: [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 d756be1..e6ea1a0 100644 | ||
--- a/st.c | ||
+++ b/st.c | ||
@@ -2801,7 +2801,8 @@ draw(void) | ||
drawregion(0, 0, term.col, term.row); | ||
if (TSCREEN.off == 0) | ||
xdrawcursor(cx, term.c.y, TLINE(term.c.y)[cx], | ||
- term.ocx, term.ocy, TLINE(term.ocy)[term.ocx]); | ||
+ term.ocx, term.ocy, TLINE(term.ocy)[term.ocx], | ||
+ TLINE(term.ocy), term.col); | ||
term.ocx = cx; | ||
term.ocy = term.c.y; | ||
xfinishdraw(); | ||
diff --git a/st.h b/st.h | ||
index 8471441..2c71ec8 100644 | ||
--- a/st.h | ||
+++ b/st.h | ||
@@ -37,6 +37,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 cd4bd94..b8c4d93 100644 | ||
--- 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); | ||
@@ -1375,7 +1375,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, | ||
@@ -1462,47 +1462,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 | ||
@@ -1512,11 +1505,11 @@ 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; | ||
XRenderColor colbg; | ||
@@ -1524,7 +1517,10 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) | ||
/* 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; | ||
@@ -1662,32 +1658,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 | ||
|