diff options
| author | jack <[email protected]> | 2023-11-21 16:45:29 -0700 | 
|---|---|---|
| committer | jack <[email protected]> | 2023-11-21 16:45:29 -0700 | 
| commit | cf34fd0adf148540a79ed6fe6444e1fc3260d2ea (patch) | |
| tree | 928d1071a0bee4da1caf137769e2153ae578f6f9 | |
| parent | 7185766961d183f550abbdc1c832bdd6233355d3 (diff) | |
| download | st-cf34fd0adf148540a79ed6fe6444e1fc3260d2ea.tar.gz st-cf34fd0adf148540a79ed6fe6444e1fc3260d2ea.zip | |
fix unicode glyphs
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | patches/st-clipboard-20180309-c5ba9c0.diff | 13 | ||||
| -rw-r--r-- | patches/st-glyph-wide-support-20220411-ef05519.diff | 206 | ||||
| -rw-r--r-- | st.h | 6 | ||||
| -rw-r--r-- | x.c | 136 | 
5 files changed, 295 insertions, 67 deletions
| @@ -1,3 +1,4 @@  st  *.o  *.orig +*.rej diff --git a/patches/st-clipboard-20180309-c5ba9c0.diff b/patches/st-clipboard-20180309-c5ba9c0.diff new file mode 100644 index 0000000..4a14e2b --- /dev/null +++ b/patches/st-clipboard-20180309-c5ba9c0.diff @@ -0,0 +1,13 @@ +diff --git a/x.c b/x.c +index 13fa9f4..88fd341 100644 +--- a/x.c ++++ b/x.c +@@ -624,6 +624,8 @@ setsel(char *str, Time t) + 	XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); + 	if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) + 		selclear(); ++ ++	xclipcopy(); + } +  + void diff --git a/patches/st-glyph-wide-support-20220411-ef05519.diff b/patches/st-glyph-wide-support-20220411-ef05519.diff new file mode 100644 index 0000000..f88c5ee --- /dev/null +++ b/patches/st-glyph-wide-support-20220411-ef05519.diff @@ -0,0 +1,206 @@ +From 68de38fadd04f2f454bceccea0fccc8276b635cb Mon Sep 17 00:00:00 2001 +From: wael <[email protected]> +Date: Mon, 11 Apr 2022 16:45:49 +0300 +Subject: [PATCH] add glyph wide support patch + +--- + st.h |   6 +++ + x.c  | 134 +++++++++++++++++++++++++++++------------------------------ + 2 files changed, 73 insertions(+), 67 deletions(-) + +diff --git a/st.h b/st.h +index 519b9bd..4f74621 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 2a3bd38..d60df52 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,7 +1506,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 +@@ -1648,32 +1641,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.35.1 + @@ -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, @@ -144,7 +144,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); @@ -688,6 +688,8 @@ setsel(char *str, Time t)  	XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t);  	if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win)  		selclear(); + +	xclipcopy();  }  void @@ -1374,7 +1376,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, @@ -1465,47 +1467,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 @@ -1515,7 +1510,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 @@ -1650,32 +1645,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 | 
