HTTPS
https://git.nageyqma.icu/nageyqma/st.git
SSH
git@git.nageyqma.icu:nageyqma/st.git
HTTPS 链接可直接 git clone;推送代码请使用 SSH。
仅展示默认分支 main 最近 100 条提交。
remove stupid llm config查看变更.gitignore | 2 ++ 1 file changed, 2 insertions(+) @@ -4,3 +4,5 @@ st *-protocol.c *-protocol.h +.qoder/ +AGENT.md |
tried to fix wired boarder查看变更wl.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) @@ -1240,7 +1240,7 @@ drawglyphspecs(const GlyphSpec *specs, Glyph base, int len, int x, int y) int winy = win.vborderpx + y * win.ch; int width = charlen * win.cw; uint32_t fg, bg, temp; - int by1, by2, i; + int i; /* Fallback on color display for attributes not supported by the font */ if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { @@ -1287,26 +1287,15 @@ drawglyphspecs(const GlyphSpec *specs, Glyph base, int len, int x, int y) if (base.mode & ATTR_INVISIBLE) fg = bg; - /* Intelligent cleaning up of the borders. */ - if (x == 0) { - by1 = y ? winy : 0; - by2 = winy + win.ch; - if (winy + win.ch >= win.vborderpx + win.th) - by2 = win.h; - clearrect(0, by1, win.hborderpx, by2 - by1, bg); - } - if (winx + width >= win.hborderpx + win.tw) { - by1 = y ? winy : 0; - by2 = winy + win.ch >= win.vborderpx + win.th ? - win.h : winy + win.ch; - clearrect(winx + width, by1, win.w - (winx + width), - by2 - by1, bg); - } - if (y == 0) - clearrect(winx, 0, width, win.vborderpx, bg); - if (winy + win.ch >= win.vborderpx + win.th) - clearrect(winx, winy + win.ch, width, - win.h - (winy + win.ch), bg); + /* Intelligent cleaning up of the borders, horizontally only: the top and + * the bottom padding always belong to the default background, see + * startdraw(), so that a coloured block on the first or the last row does + * not bleed out of its own row. */ + if (x == 0) + clearrect(0, winy, win.hborderpx, win.ch, bg); + if (winx + width >= win.hborderpx + win.tw) + clearrect(winx + width, winy, win.w - (winx + width), + win.ch, bg); /* Clean up the region we want to draw to. */ clearrect(winx, winy, width, win.ch, bg); @@ -1461,6 +1450,8 @@ drawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int startdraw(void) { + uint32_t padcol; + if (!fb.data[0] || !IS_SET(MODE_VISIBLE)) return 0; @@ -1475,6 +1466,14 @@ startdraw(void) fb.drawn = 0; draw_pending = 0; resetclip(); + + /* The padding the character grid does not fill keeps the default + * background, even under reverse video. Rows must not paint into it, + * a coloured first or last row would otherwise look too tall. */ + padcol = dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg]; + clearrect(0, 0, win.w, win.vborderpx, padcol); + clearrect(0, win.vborderpx + win.th, win.w, + win.h - (win.vborderpx + win.th), padcol); tfulldirt(); return 1; } |
cjk font查看变更README | 4 ++++ st.1 | 2 ++ wl.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------- 3 files changed, 85 insertions(+), 59 deletions(-) @@ -63,6 +63,10 @@ Notes complete frame. This is required because some compositors (KWin) keep the current buffer alive until it is replaced and therefore never send wl_buffer.release for a single-buffer scheme. +- Font fallback: a glyph the configured font does not carry (CJK, for + instance) is drawn with the first fontconfig candidate whose face really + contains it. The family in config.h stays the primary font; fallback only + fills the gaps. Credits ------- @@ -65,6 +65,8 @@ defines the application id (default $TERM). defines the .I font to use when st is run (a fontconfig pattern). +Characters it has no glyph for are taken from the first installed font that +does cover them. .TP .BI \-g " geometry" sets the initial size of the terminal in columns and rows. @@ -108,7 +108,6 @@ typedef struct { typedef struct { FT_Face face; FcPattern *pattern; - FcFontSet *set; int height, width; int ascent, descent; int badslant, badweight; @@ -286,6 +285,7 @@ static int sixd_to_16bit(int); static void setclip(int, int, int, int); static void resetclip(void); static void drawglyphbitmap(FT_Face, uint32_t, int, int, uint32_t); +static FT_Face loadfallbackface(Font *, Rune, FT_UInt *); static int makeglyphspecs(GlyphSpec *, const Glyph *, int, int, int); static void drawglyphspecs(const GlyphSpec *, Glyph, int, int, int); static void drawglyph(Glyph, int, int); @@ -789,7 +789,6 @@ loadfont(Font *f, FcPattern *pattern, double px) f->face = face; f->pattern = configured; - f->set = NULL; FcPatternDestroy(match); return 0; @@ -864,8 +863,6 @@ unloadfont(Font *f) FT_Done_Face(f->face); if (f->pattern) FcPatternDestroy(f->pattern); - if (f->set) - FcFontSetDestroy(f->set); memset(f, 0, sizeof(*f)); } @@ -1062,6 +1059,66 @@ enum { FRC_ITALICBOLD }; +/* Face for a rune the configured font does not carry, or NULL when nothing on + * the system does. *glyphidx is its index for that face (0 when not found). + * + * fontconfig's cached charsets over-report: the best match it offers may have + * no cmap entry at all for the rune, which is how CJK came out blank. Only + * FreeType knows what a loaded face really contains, so walk the sorted + * candidates and ask it. Capped because the set is the whole font cache and a + * rune nobody covers must not turn a redraw into a file scan. */ +static FT_Face +loadfallbackface(Font *f, Rune rune, FT_UInt *glyphidx) +{ + FcPattern *pattern; + FcCharSet *charset; + FcFontSet *set; + FcResult result; + FcChar8 *file; + FT_Face face = NULL; + int i, index; + + charset = FcCharSetCreate(); + pattern = FcPatternDuplicate(f->pattern); + if (!charset || !pattern) + die("out of memory looking up a fallback font\n"); + + FcCharSetAddChar(charset, rune); + FcPatternAddCharSet(pattern, FC_CHARSET, charset); + FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); + FcConfigSubstitute(NULL, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); + + *glyphidx = 0; + set = FcFontSort(NULL, pattern, FcTrue, NULL, &result); + for (i = 0; set && i < set->nfont && i < 32; i++) { + if (FcPatternGetString(set->fonts[i], FC_FILE, 0, &file) != + FcResultMatch || + FcPatternGetInteger(set->fonts[i], FC_INDEX, 0, &index) != + FcResultMatch) + continue; + if (FT_New_Face(ftlib, (const char *)file, index, &face)) + continue; + + FT_Select_Charmap(face, FT_ENCODING_UNICODE); + FT_Set_Char_Size(face, 0, (FT_F26Dot6)(f->pxsize * 64 + 0.5), + 72, 72); + *glyphidx = FT_Get_Char_Index(face, rune); + if (*glyphidx) + break; + FT_Done_Face(face); + } + + if (set) + FcFontSetDestroy(set); + FcPatternDestroy(pattern); + FcCharSetDestroy(charset); + + if (!*glyphidx) + return NULL; + return face; +} + /* Turn a run of glyphs into font specs. Exactly one spec is appended per * non-dummy glyph so that hbtransform() can stay index-aligned. */ static int @@ -1075,13 +1132,8 @@ makeglyphspecs(GlyphSpec *specs, const Glyph *glyphs, int len, int x, int y) double runewidth = win.cw; Rune rune; FT_UInt glyphidx; - FcResult fcres; - FcPattern *fcpattern, *fontpattern; - FcFontSet *fcsets[] = { NULL }; - FcCharSet *fccharset; - FcChar8 *file; FT_Face face; - int f, index, numspecs = 0, i; + int f, numspecs = 0, i; for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { rune = glyphs[i].u; @@ -1126,9 +1178,11 @@ makeglyphspecs(GlyphSpec *specs, const Glyph *glyphs, int len, int x, int y) continue; } - /* Fallback on font cache, search the font cache for match. */ + /* Fallback on font cache, search the font cache for match. A NULL + * face is a rune nothing on the system covers, see below. */ for (f = 0; f < frclen; f++) { - glyphidx = FT_Get_Char_Index(frc[f].face, rune); + glyphidx = frc[f].face ? + FT_Get_Char_Index(frc[f].face, rune) : 0; /* Everything correct. */ if (glyphidx && frc[f].flags == frcflags) break; @@ -1138,57 +1192,23 @@ makeglyphspecs(GlyphSpec *specs, const Glyph *glyphs, int len, int x, int y) break; } - /* Nothing was found. Use fontconfig to find a matching font. */ + /* Nothing was found. Ask fontconfig for a face carrying the rune + * and cache the answer either way, so a rune is looked up once and + * an uncovered one does not rescan the fonts on every redraw. */ if (f >= frclen) { - fcpattern = FcPatternDuplicate(font->pattern); - fccharset = FcCharSetCreate(); - if (!fcpattern || !fccharset) - die("out of memory looking up a fallback font\n"); - - FcCharSetAddChar(fccharset, rune); - FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, 1); - FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); - FcDefaultSubstitute(fcpattern); - - if (!font->set) - font->set = FcFontSort(NULL, font->pattern, 1, - NULL, &fcres); - fcsets[0] = font->set; - fontpattern = FcFontSetMatch(NULL, fcsets, 1, fcpattern, - &fcres); - - f = -1; - glyphidx = 0; - face = font->face; - if (fontpattern && - FcPatternGetString(fontpattern, FC_FILE, 0, &file) == - FcResultMatch && - FcPatternGetInteger(fontpattern, FC_INDEX, 0, - &index) == FcResultMatch && - !FT_New_Face(ftlib, (const char *)file, index, &face)) { - FT_Select_Charmap(face, FT_ENCODING_UNICODE); - FT_Set_Char_Size(face, 0, - (FT_F26Dot6)(font->pxsize * 64 + 0.5), - 72, 72); - glyphidx = FT_Get_Char_Index(face, rune); - - if (frclen >= frccap) { - frccap += 16; - frc = xrealloc(frc, - frccap * sizeof(Fontcache)); - } - frc[frclen].face = face; - frc[frclen].flags = frcflags; - frc[frclen].unicodep = rune; - f = frclen++; - } + face = loadfallbackface(font, rune, &glyphidx); - FcPatternDestroy(fcpattern); - FcCharSetDestroy(fccharset); + if (frclen >= frccap) { + frccap += 16; + frc = xrealloc(frc, frccap * sizeof(Fontcache)); + } + frc[frclen].face = face; + frc[frclen].flags = frcflags; + frc[frclen].unicodep = rune; + f = frclen++; } - specs[numspecs].font = f >= 0 ? frc[f].face : face; + specs[numspecs].font = frc[f].face ? frc[f].face : font->face; specs[numspecs].glyph = glyphidx; specs[numspecs].x = (short)xp; specs[numspecs].y = (short)yp; |
early wayland support查看变更.gitignore | 2 + Makefile | 83 ++- README | 41 +- boxdraw.c | 94 ++-- config.h | 472 +++++++++--------- config.mk | 46 +- hb.c | 125 +++-- hb.h | 9 +- render.h | 28 ++ st.1 | 91 ++-- st.c | 150 +++--- st.h | 19 +- win.h | 76 ++- wl.c | 3848 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ x.c | 2146 ------------------------------------------------------------------------------ 15 files changed, 4557 insertions(+), 2673 deletions(-) @@ -2,3 +2,5 @@ *.rej *.o st +*-protocol.c +*-protocol.h @@ -4,11 +4,36 @@ include config.mk -SRC = st.c x.c boxdraw.c hb.c +PROTOHDR = xdg-shell-client-protocol.h \ + fractional-scale-client-protocol.h \ + viewporter-client-protocol.h \ + cursor-shape-client-protocol.h \ + system-bell-client-protocol.h \ + primary-selection-client-protocol.h \ + text-input-client-protocol.h \ + tablet-v2-client-protocol.h +PROTOC = xdg-shell-protocol.c \ + fractional-scale-protocol.c \ + viewporter-protocol.c \ + cursor-shape-protocol.c \ + system-bell-protocol.c \ + primary-selection-protocol.c \ + text-input-protocol.c \ + tablet-v2-protocol.c +SRC = st.c wl.c boxdraw.c hb.c $(PROTOC) OBJ = $(SRC:.c=.o) all: options st +# wayland-protocols is only needed to (re)generate the protocol bindings, so +# clean and dist keep working without it; anything else fails with a hint +# instead of make looking for /stable/xdg-shell/xdg-shell.xml. +ifeq ($(WLPROTO),) +ifeq ($(filter clean dist uninstall,$(MAKECMDGOALS)),) +$(error wayland-protocols not found: install it or run make WLPROTO=/path/to/wayland-protocols) +endif +endif + options: @echo st build options: @echo "CFLAGS = $(STCFLAGS)" @@ -22,23 +47,65 @@ config.h: $(CC) $(STCFLAGS) -c $< st.o: config.h st.h win.h -x.o: arg.h config.h st.h win.h hb.h -hb.o: st.h -boxdraw.o: config.h st.h boxdraw_data.h +wl.o: arg.h config.h st.h win.h render.h hb.h $(PROTOHDR) +hb.o: st.h render.h hb.h +boxdraw.o: config.h st.h render.h boxdraw_data.h +$(PROTOC:.c=.o): $(PROTOHDR) $(OBJ): config.h config.mk st: $(OBJ) $(CC) -o $@ $(OBJ) $(STLDFLAGS) +# Wayland protocol bindings (generated, not committed) +xdg-shell-client-protocol.h: $(XDG_SHELL_XML) + $(WAYLAND_SCANNER) client-header $< $@ +xdg-shell-protocol.c: $(XDG_SHELL_XML) + $(WAYLAND_SCANNER) private-code $< $@ + +fractional-scale-client-protocol.h: $(FRACTIONAL_XML) + $(WAYLAND_SCANNER) client-header $< $@ +fractional-scale-protocol.c: $(FRACTIONAL_XML) + $(WAYLAND_SCANNER) private-code $< $@ + +viewporter-client-protocol.h: $(VIEWPORTER_XML) + $(WAYLAND_SCANNER) client-header $< $@ +viewporter-protocol.c: $(VIEWPORTER_XML) + $(WAYLAND_SCANNER) private-code $< $@ + +cursor-shape-client-protocol.h: $(CURSOR_SHAPE_XML) + $(WAYLAND_SCANNER) client-header $< $@ +cursor-shape-protocol.c: $(CURSOR_SHAPE_XML) + $(WAYLAND_SCANNER) private-code $< $@ + +system-bell-client-protocol.h: $(SYSTEM_BELL_XML) + $(WAYLAND_SCANNER) client-header $< $@ +system-bell-protocol.c: $(SYSTEM_BELL_XML) + $(WAYLAND_SCANNER) private-code $< $@ + +primary-selection-client-protocol.h: $(PRIMARY_XML) + $(WAYLAND_SCANNER) client-header $< $@ +primary-selection-protocol.c: $(PRIMARY_XML) + $(WAYLAND_SCANNER) private-code $< $@ + +text-input-client-protocol.h: $(TEXT_INPUT_XML) + $(WAYLAND_SCANNER) client-header $< $@ +text-input-protocol.c: $(TEXT_INPUT_XML) + $(WAYLAND_SCANNER) private-code $< $@ + +tablet-v2-client-protocol.h: $(TABLET_XML) + $(WAYLAND_SCANNER) client-header $< $@ +tablet-v2-protocol.c: $(TABLET_XML) + $(WAYLAND_SCANNER) private-code $< $@ + clean: - rm -f st $(OBJ) st-$(VERSION).tar.gz + rm -f st $(OBJ) $(PROTOC) $(PROTOHDR) st-$(VERSION).tar.gz dist: clean mkdir -p st-$(VERSION) - cp -R FAQ LEGACY TODO LICENSE Makefile README config.mk\ - config.def.h st.info st.1 arg.h st.h win.h $(SRC)\ - st-$(VERSION) + cp -R AGENT.md LEGACY LICENSE Makefile README config.mk config.h\ + st.info st.1 arg.h st.h wl.c hb.h hb.c boxdraw.c boxdraw_data.h\ + render.h st.c st-$(VERSION) tar -cf - st-$(VERSION) | gzip > st-$(VERSION).tar.gz rm -rf st-$(VERSION) @@ -1,11 +1,28 @@ st - simple terminal -------------------- -st is a simple terminal emulator for X which sucks less. +st is a simple terminal emulator for Wayland which sucks less. + +It is a port of suckless st: the terminal core (st.c) is unchanged, the +old X11 backend has been replaced by a small Wayland backend (wl.c) that +draws an ARGB8888 wl_shm buffer. There is no X11 code path and no +XWayland fallback. Requirements ------------ -In order to build st you need the Xlib header files. +In order to build st you need: + + - wayland-client and wayland-protocols (wayland-scanner) + - xkbcommon + - fontconfig and freetype2 + - harfbuzz + +The protocol bindings are generated at build time and are not committed. +The XMLs are found through pkg-config, then under $XDG_DATA_HOME (or +~/.local/share), /usr/local/share and /usr/share. If wayland-protocols +lives somewhere else, point WLPROTO at it: + + make WLPROTO=/opt/wayland-protocols Installation @@ -21,6 +38,12 @@ necessary as root): Running st ---------- +st runs on any Wayland compositor that implements xdg-shell and wl_shm. +The following protocols are used when the compositor provides them and +silently skipped otherwise: fractional-scale/viewporter for crisp +fractional scaling, text-input-v3 for input methods, primary-selection, +cursor-shape and xdg-system-bell. + If you did not install st with make clean install, you must compile the st terminfo entry with the following command: @@ -28,7 +51,19 @@ the st terminfo entry with the following command: See the man page for additional details. +Notes +----- +- Wayland does not let clients place their windows. -g only selects the + initial number of columns and rows; offsets are ignored with a warning. +- -n and -w are gone: X11 instance names and XEmbed do not exist here. +- Scaling: the surface is rendered at the compositor's preferred scale and + mapped through wp_viewport, so 1.5x and other fractional scales stay + crisp. +- The window is drawn with two rotating buffers; every commit contains the + complete frame. This is required because some compositors (KWin) keep + the current buffer alive until it is replaced and therefore never send + wl_buffer.release for a single-buffer scheme. + Credits ------- Based on Aurélien APTEL <aurelien dot aptel at gmail dot com> bt source code. - @@ -3,29 +3,18 @@ * MIT/X Consortium License */ -#include <X11/Xft/Xft.h> #include "st.h" +#include "render.h" #include "boxdraw_data.h" /* Rounded non-negative integers division of n / d */ #define DIV(n, d) (((n) + (d) / 2) / (d)) -static Display *xdpy; -static Colormap xcmap; -static XftDraw *xd; -static Visual *xvis; - -static void drawbox(int, int, int, int, XftColor *, XftColor *, ushort); -static void drawboxlines(int, int, int, int, XftColor *, ushort); +static void drawbox(int, int, int, int, uint32_t, uint32_t, ushort); +static void drawboxlines(int, int, int, int, uint32_t, ushort); /* public API */ -void -boxdraw_xinit(Display *dpy, Colormap cmap, XftDraw *draw, Visual *vis) -{ - xdpy = dpy; xcmap = cmap; xd = draw, xvis = vis; -} - int isboxdraw(Rune u) { @@ -46,8 +35,8 @@ boxdrawindex(const Glyph *g) } void -drawboxes(int x, int y, int cw, int ch, XftColor *fg, XftColor *bg, - const XftGlyphFontSpec *specs, int len) +drawboxes(int x, int y, int cw, int ch, uint32_t fg, uint32_t bg, + const GlyphSpec *specs, int len) { for ( ; len-- > 0; x += cw, specs++) drawbox(x, y, cw, ch, fg, bg, (ushort)specs->glyph); @@ -56,7 +45,7 @@ drawboxes(int x, int y, int cw, int ch, XftColor *fg, XftColor *bg, /* implementation */ void -drawbox(int x, int y, int w, int h, XftColor *fg, XftColor *bg, ushort bd) +drawbox(int x, int y, int w, int h, uint32_t fg, uint32_t bg, ushort bd) { ushort cat = bd & ~(BDB | 0xff); /* mask out bold and data */ if (bd & (BDL | BDA)) { @@ -66,66 +55,61 @@ drawbox(int x, int y, int w, int h, XftColor *fg, XftColor *bg, ushort bd) } else if (cat == BBD) { /* lower (8-X)/8 block */ int d = DIV((uint8_t)bd * h, 8); - XftDrawRect(xd, fg, x, y + d, w, h - d); + blendrect(x, y + d, w, h - d, fg); } else if (cat == BBU) { /* upper X/8 block */ - XftDrawRect(xd, fg, x, y, w, DIV((uint8_t)bd * h, 8)); + blendrect(x, y, w, DIV((uint8_t)bd * h, 8), fg); } else if (cat == BBL) { /* left X/8 block */ - XftDrawRect(xd, fg, x, y, DIV((uint8_t)bd * w, 8), h); + blendrect(x, y, DIV((uint8_t)bd * w, 8), h, fg); } else if (cat == BBR) { /* right (8-X)/8 block */ int d = DIV((uint8_t)bd * w, 8); - XftDrawRect(xd, fg, x + d, y, w - d, h); + blendrect(x + d, y, w - d, h, fg); } else if (cat == BBQ) { /* Quadrants */ int w2 = DIV(w, 2), h2 = DIV(h, 2); if (bd & TL) - XftDrawRect(xd, fg, x, y, w2, h2); + blendrect(x, y, w2, h2, fg); if (bd & TR) - XftDrawRect(xd, fg, x + w2, y, w - w2, h2); + blendrect(x + w2, y, w - w2, h2, fg); if (bd & BL) - XftDrawRect(xd, fg, x, y + h2, w2, h - h2); + blendrect(x, y + h2, w2, h - h2, fg); if (bd & BR) - XftDrawRect(xd, fg, x + w2, y + h2, w - w2, h - h2); + blendrect(x + w2, y + h2, w - w2, h - h2, fg); } else if (bd & BBS) { /* Shades - data is 1/2/3 for 25%/50%/75% alpha, respectively */ int d = (uint8_t)bd; - XftColor xfc; - XRenderColor xrc = { .alpha = 0xffff }; - - xrc.red = DIV(fg->color.red * d + bg->color.red * (4 - d), 4); - xrc.green = DIV(fg->color.green * d + bg->color.green * (4 - d), 4); - xrc.blue = DIV(fg->color.blue * d + bg->color.blue * (4 - d), 4); + uint32_t r = DIV(((fg >> 16) & 0xff) * d + ((bg >> 16) & 0xff) * (4 - d), 4); + uint32_t g = DIV(((fg >> 8) & 0xff) * d + ((bg >> 8) & 0xff) * (4 - d), 4); + uint32_t b = DIV((fg & 0xff) * d + (bg & 0xff) * (4 - d), 4); - XftColorAllocValue(xdpy, xvis, xcmap, &xrc, &xfc); - XftDrawRect(xd, &xfc, x, y, w, h); - XftColorFree(xdpy, xvis, xcmap, &xfc); + blendrect(x, y, w, h, 0xff000000 | r << 16 | g << 8 | b); } else if (cat == BRL) { /* braille, each data bit corresponds to one dot at 2x4 grid */ int w1 = DIV(w, 2); int h1 = DIV(h, 4), h2 = DIV(h, 2), h3 = DIV(3 * h, 4); - if (bd & 1) XftDrawRect(xd, fg, x, y, w1, h1); - if (bd & 2) XftDrawRect(xd, fg, x, y + h1, w1, h2 - h1); - if (bd & 4) XftDrawRect(xd, fg, x, y + h2, w1, h3 - h2); - if (bd & 8) XftDrawRect(xd, fg, x + w1, y, w - w1, h1); - if (bd & 16) XftDrawRect(xd, fg, x + w1, y + h1, w - w1, h2 - h1); - if (bd & 32) XftDrawRect(xd, fg, x + w1, y + h2, w - w1, h3 - h2); - if (bd & 64) XftDrawRect(xd, fg, x, y + h3, w1, h - h3); - if (bd & 128) XftDrawRect(xd, fg, x + w1, y + h3, w - w1, h - h3); + if (bd & 1) blendrect(x, y, w1, h1, fg); + if (bd & 2) blendrect(x, y + h1, w1, h2 - h1, fg); + if (bd & 4) blendrect(x, y + h2, w1, h3 - h2, fg); + if (bd & 8) blendrect(x + w1, y, w - w1, h1, fg); + if (bd & 16) blendrect(x + w1, y + h1, w - w1, h2 - h1, fg); + if (bd & 32) blendrect(x + w1, y + h2, w - w1, h3 - h2, fg); + if (bd & 64) blendrect(x, y + h3, w1, h - h3, fg); + if (bd & 128) blendrect(x + w1, y + h3, w - w1, h - h3, fg); } } void -drawboxlines(int x, int y, int w, int h, XftColor *fg, ushort bd) +drawboxlines(int x, int y, int w, int h, uint32_t fg, ushort bd) { /* s: stem thickness. width/8 roughly matches underscore thickness. */ /* We draw bold as 1.5 * normal-stem and at least 1px thicker. */ @@ -151,13 +135,13 @@ drawboxlines(int x, int y, int w, int h, XftColor *fg, ushort bd) int d = arc || (multi_double && !multi_light) ? -s : 0; if (bd & LL) - XftDrawRect(xd, fg, x, y + h2, w2 + s + d, s); + blendrect(x, y + h2, w2 + s + d, s, fg); if (bd & LU) - XftDrawRect(xd, fg, x + w2, y, s, h2 + s + d); + blendrect(x + w2, y, s, h2 + s + d, fg); if (bd & LR) - XftDrawRect(xd, fg, x + w2 - d, y + h2, w - w2 + d, s); + blendrect(x + w2 - d, y + h2, w - w2 + d, s, fg); if (bd & LD) - XftDrawRect(xd, fg, x + w2, y + h2 - d, s, h - h2 + d); + blendrect(x + w2, y + h2 - d, s, h - h2 + d, fg); } /* double lines - also align with light to form heavy when combined */ @@ -172,23 +156,23 @@ drawboxlines(int x, int y, int w, int h, XftColor *fg, ushort bd) int dl = bd & DL, du = bd & DU, dr = bd & DR, dd = bd & DD; if (dl) { int p = dd ? -s : 0, n = du ? -s : dd ? s : 0; - XftDrawRect(xd, fg, x, y + h2 + s, w2 + s + p, s); - XftDrawRect(xd, fg, x, y + h2 - s, w2 + s + n, s); + blendrect(x, y + h2 + s, w2 + s + p, s, fg); + blendrect(x, y + h2 - s, w2 + s + n, s, fg); } if (du) { int p = dl ? -s : 0, n = dr ? -s : dl ? s : 0; - XftDrawRect(xd, fg, x + w2 - s, y, s, h2 + s + p); - XftDrawRect(xd, fg, x + w2 + s, y, s, h2 + s + n); + blendrect(x + w2 - s, y, s, h2 + s + p, fg); + blendrect(x + w2 + s, y, s, h2 + s + n, fg); } if (dr) { int p = du ? -s : 0, n = dd ? -s : du ? s : 0; - XftDrawRect(xd, fg, x + w2 - p, y + h2 - s, w - w2 + p, s); - XftDrawRect(xd, fg, x + w2 - n, y + h2 + s, w - w2 + n, s); + blendrect(x + w2 - p, y + h2 - s, w - w2 + p, s, fg); + blendrect(x + w2 - n, y + h2 + s, w - w2 + n, s, fg); } if (dd) { int p = dr ? -s : 0, n = dl ? -s : dr ? s : 0; - XftDrawRect(xd, fg, x + w2 + s, y + h2 - p, s, h - h2 + p); - XftDrawRect(xd, fg, x + w2 - s, y + h2 - n, s, h - h2 + n); + blendrect(x + w2 + s, y + h2 - p, s, h - h2 + p, fg); + blendrect(x + w2 - s, y + h2 - n, s, h - h2 + n, fg); } } } @@ -7,7 +7,7 @@ */ //static char *font = "JetBrainsMono Nerd Font Mono:pixelsize=26:antialias=true:autohint=true"; //static char *font = "SauceCodePro Nerd Font Mono:pixelsize=26:antialias=true:autohint=true"; -static char *font = "SauceCodePro Nerd Font Mono:pixelsize=20:antialias=true:autohint=true"; +static char *font = "SauceCodePro Nerd Font Mono:pixelsize=26:antialias=true:autohint=true"; //static char *font = "Source Code Pro:pixelsize=26:antialias=true:autohint=true"; static int borderpx = 1; @@ -171,11 +171,11 @@ static unsigned int cols = 80; static unsigned int rows = 24; /* - * Default colour and shape of the mouse cursor + * Default shape of the mouse cursor. Wayland compositors own the cursor + * theme, so this is a cursor name ("text", "default", "pointer", ...). + * The XC_* aliases in win.h cover the common X cursor names. */ -static unsigned int mouseshape = XC_xterm; -static unsigned int mousefg = 7; -static unsigned int mousebg = 0; +static char *mouseshape = XC_xterm; /* * Color used to display font attributes when fontconfig selected a font which @@ -200,36 +200,36 @@ static uint forcemousemod = ShiftMask; */ static MouseShortcut mshortcuts[] = { /* mask button function argument release */ - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { XK_NO_MOD, Button4, kscrollup, {.i = 1} }, - { XK_NO_MOD, Button5, kscrolldown, {.i = 1} }, + { MOD_ANY, Button2, selpaste, {.i = 0}, 1 }, + { MOD_NONE, Button4, kscrollup, {.i = 1} }, + { MOD_NONE, Button5, kscrolldown, {.i = 1} }, { ControlMask, Button4, kscrollup, {.i = -1} }, { ControlMask, Button5, kscrolldown, {.i = -1} }, }; static Shortcut shortcuts[] = { /* mask keysym function argument */ - { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, - { ControlMask, XK_Print, toggleprinter, {.i = 0} }, - { ShiftMask, XK_Print, printscreen, {.i = 0} }, - { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { ControlMask, XK_equal, zoom, {.f = +1} }, - { ControlMask, XK_minus, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, - { TERMMOD, XK_C, clipcopy, {.i = 0} }, - { TERMMOD, XK_V, clippaste, {.i = 0} }, - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { TERMMOD, XK_S, keyboard_select,{.i = 0} }, + { MOD_ANY, XKB_KEY_Break, sendbreak, {.i = 0} }, + { ControlMask, XKB_KEY_Print, toggleprinter, {.i = 0} }, + { ShiftMask, XKB_KEY_Print, printscreen, {.i = 0} }, + { MOD_ANY, XKB_KEY_Print, printsel, {.i = 0} }, + { ControlMask, XKB_KEY_equal, zoom, {.f = +1} }, + { ControlMask, XKB_KEY_minus, zoom, {.f = -1} }, + { TERMMOD, XKB_KEY_Home, zoomreset, {.f = 0} }, + { TERMMOD, XKB_KEY_C, clipcopy, {.i = 0} }, + { TERMMOD, XKB_KEY_V, clippaste, {.i = 0} }, + { TERMMOD, XKB_KEY_Y, selpaste, {.i = 0} }, + { ShiftMask, XKB_KEY_Insert, selpaste, {.i = 0} }, + { TERMMOD, XKB_KEY_Num_Lock, numlock, {.i = 0} }, + { TERMMOD, XKB_KEY_S, keyboard_select,{.i = 0} }, }; /* * Special keys (change & recompile st.info accordingly) * * Mask value: - * * Use XK_ANY_MOD to match the key no matter modifiers state - * * Use XK_NO_MOD to match the key alone (no modifiers) + * * Use MOD_ANY to match the key no matter modifiers state + * * Use MOD_NONE to match the key alone (no modifiers) * appkey value: * * 0: no value * * > 0: keypad application mode enabled @@ -241,21 +241,21 @@ static Shortcut shortcuts[] = { * * < 0: cursor application mode disabled * * Be careful with the order of the definitions because st searches in - * this table sequentially, so any XK_ANY_MOD must be in the last + * this table sequentially, so any MOD_ANY must be in the last * position for a key. */ /* - * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * If you want keys other than the function keys (0xFD00 - 0xFFFF) * to be mapped below, add them to this array. */ static KeySym mappedkeys[] = { -1 }; /* * State bits to ignore when matching key or button events. By default, - * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + * numlock (Mod2Mask) and keyboard layout (MOD_SWITCH) are ignored. */ -static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; +static uint ignoremod = Mod2Mask|MOD_SWITCH; /* * This is the huge key array which defines all compatibility to the Linux @@ -263,215 +263,215 @@ static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; */ static Key key[] = { /* keysym mask string appkey appcursor */ - { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, - { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, - { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, - { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, - { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, - { XK_KP_End, ControlMask, "\033[J", -1, 0}, - { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_KP_End, ShiftMask, "\033[K", -1, 0}, - { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, - { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, - { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, - { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, - { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, - { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, - { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, - { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, - { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, - { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, - { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, - { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, - { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, - { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, - { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, - { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, - { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, - { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, - { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, - { XK_Up, ControlMask, "\033[1;5A", 0, 0}, - { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, - { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, - { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, - { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, - { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, - { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, - { XK_Down, ControlMask, "\033[1;5B", 0, 0}, - { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, - { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, - { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, - { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, - { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, - { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, - { XK_Left, ControlMask, "\033[1;5D", 0, 0}, - { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, - { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, - { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, - { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, - { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, - { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, - { XK_Right, ControlMask, "\033[1;5C", 0, 0}, - { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, - { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, - { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, - { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, - { XK_Return, Mod1Mask, "\033\r", 0, 0}, - { XK_Return, XK_ANY_MOD, "\r", 0, 0}, - { XK_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_Insert, ControlMask, "\033[L", -1, 0}, - { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_Delete, ControlMask, "\033[M", -1, 0}, - { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, - { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, - { XK_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_End, ControlMask, "\033[J", -1, 0}, - { XK_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_End, ShiftMask, "\033[K", -1, 0}, - { XK_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, - { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_Next, ControlMask, "\033[6;5~", 0, 0}, - { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, - { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, - { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, - { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, - { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, - { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, - { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, - { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, - { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, - { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, - { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, - { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, - { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, - { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, - { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, - { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, - { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, - { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, - { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, - { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, - { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, - { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, - { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, - { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, - { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, - { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, - { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, - { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, - { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, - { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, - { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, - { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, - { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, - { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, - { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, - { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, - { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, - { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, - { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, - { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, - { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, - { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, - { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, - { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, - { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, - { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, - { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, - { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, - { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, - { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, - { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, - { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, - { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, - { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, - { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, - { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, - { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, - { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, - { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, - { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, - { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, - { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, - { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, - { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, - { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, - { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, - { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, - { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, - { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, - { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, - { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, - { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, - { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, - { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, - { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, - { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, - { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, - { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, - { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, - { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, - { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, - { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, - { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, - { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, - { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, - { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, + { XKB_KEY_KP_Home, ShiftMask, "\033[2J", 0, -1}, + { XKB_KEY_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XKB_KEY_KP_Home, MOD_ANY, "\033[H", 0, -1}, + { XKB_KEY_KP_Home, MOD_ANY, "\033[1~", 0, +1}, + { XKB_KEY_KP_Up, MOD_ANY, "\033Ox", +1, 0}, + { XKB_KEY_KP_Up, MOD_ANY, "\033[A", 0, -1}, + { XKB_KEY_KP_Up, MOD_ANY, "\033OA", 0, +1}, + { XKB_KEY_KP_Down, MOD_ANY, "\033Or", +1, 0}, + { XKB_KEY_KP_Down, MOD_ANY, "\033[B", 0, -1}, + { XKB_KEY_KP_Down, MOD_ANY, "\033OB", 0, +1}, + { XKB_KEY_KP_Left, MOD_ANY, "\033Ot", +1, 0}, + { XKB_KEY_KP_Left, MOD_ANY, "\033[D", 0, -1}, + { XKB_KEY_KP_Left, MOD_ANY, "\033OD", 0, +1}, + { XKB_KEY_KP_Right, MOD_ANY, "\033Ov", +1, 0}, + { XKB_KEY_KP_Right, MOD_ANY, "\033[C", 0, -1}, + { XKB_KEY_KP_Right, MOD_ANY, "\033OC", 0, +1}, + { XKB_KEY_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XKB_KEY_KP_Prior, MOD_ANY, "\033[5~", 0, 0}, + { XKB_KEY_KP_Begin, MOD_ANY, "\033[E", 0, 0}, + { XKB_KEY_KP_End, ControlMask, "\033[J", -1, 0}, + { XKB_KEY_KP_End, ControlMask, "\033[1;5F", +1, 0}, + { XKB_KEY_KP_End, ShiftMask, "\033[K", -1, 0}, + { XKB_KEY_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + { XKB_KEY_KP_End, MOD_ANY, "\033[4~", 0, 0}, + { XKB_KEY_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XKB_KEY_KP_Next, MOD_ANY, "\033[6~", 0, 0}, + { XKB_KEY_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XKB_KEY_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + { XKB_KEY_KP_Insert, ControlMask, "\033[L", -1, 0}, + { XKB_KEY_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XKB_KEY_KP_Insert, MOD_ANY, "\033[4h", -1, 0}, + { XKB_KEY_KP_Insert, MOD_ANY, "\033[2~", +1, 0}, + { XKB_KEY_KP_Delete, ControlMask, "\033[M", -1, 0}, + { XKB_KEY_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XKB_KEY_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + { XKB_KEY_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XKB_KEY_KP_Delete, MOD_ANY, "\033[P", -1, 0}, + { XKB_KEY_KP_Delete, MOD_ANY, "\033[3~", +1, 0}, + { XKB_KEY_KP_Multiply, MOD_ANY, "\033Oj", +2, 0}, + { XKB_KEY_KP_Add, MOD_ANY, "\033Ok", +2, 0}, + { XKB_KEY_KP_Enter, MOD_ANY, "\033OM", +2, 0}, + { XKB_KEY_KP_Enter, MOD_ANY, "\r", -1, 0}, + { XKB_KEY_KP_Subtract, MOD_ANY, "\033Om", +2, 0}, + { XKB_KEY_KP_Decimal, MOD_ANY, "\033On", +2, 0}, + { XKB_KEY_KP_Divide, MOD_ANY, "\033Oo", +2, 0}, + { XKB_KEY_KP_0, MOD_ANY, "\033Op", +2, 0}, + { XKB_KEY_KP_1, MOD_ANY, "\033Oq", +2, 0}, + { XKB_KEY_KP_2, MOD_ANY, "\033Or", +2, 0}, + { XKB_KEY_KP_3, MOD_ANY, "\033Os", +2, 0}, + { XKB_KEY_KP_4, MOD_ANY, "\033Ot", +2, 0}, + { XKB_KEY_KP_5, MOD_ANY, "\033Ou", +2, 0}, + { XKB_KEY_KP_6, MOD_ANY, "\033Ov", +2, 0}, + { XKB_KEY_KP_7, MOD_ANY, "\033Ow", +2, 0}, + { XKB_KEY_KP_8, MOD_ANY, "\033Ox", +2, 0}, + { XKB_KEY_KP_9, MOD_ANY, "\033Oy", +2, 0}, + { XKB_KEY_Up, ShiftMask, "\033[1;2A", 0, 0}, + { XKB_KEY_Up, Mod1Mask, "\033[1;3A", 0, 0}, + { XKB_KEY_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, + { XKB_KEY_Up, ControlMask, "\033[1;5A", 0, 0}, + { XKB_KEY_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, + { XKB_KEY_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, + { XKB_KEY_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, + { XKB_KEY_Up, MOD_ANY, "\033[A", 0, -1}, + { XKB_KEY_Up, MOD_ANY, "\033OA", 0, +1}, + { XKB_KEY_Down, ShiftMask, "\033[1;2B", 0, 0}, + { XKB_KEY_Down, Mod1Mask, "\033[1;3B", 0, 0}, + { XKB_KEY_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, + { XKB_KEY_Down, ControlMask, "\033[1;5B", 0, 0}, + { XKB_KEY_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, + { XKB_KEY_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, + { XKB_KEY_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, + { XKB_KEY_Down, MOD_ANY, "\033[B", 0, -1}, + { XKB_KEY_Down, MOD_ANY, "\033OB", 0, +1}, + { XKB_KEY_Left, ShiftMask, "\033[1;2D", 0, 0}, + { XKB_KEY_Left, Mod1Mask, "\033[1;3D", 0, 0}, + { XKB_KEY_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, + { XKB_KEY_Left, ControlMask, "\033[1;5D", 0, 0}, + { XKB_KEY_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, + { XKB_KEY_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, + { XKB_KEY_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, + { XKB_KEY_Left, MOD_ANY, "\033[D", 0, -1}, + { XKB_KEY_Left, MOD_ANY, "\033OD", 0, +1}, + { XKB_KEY_Right, ShiftMask, "\033[1;2C", 0, 0}, + { XKB_KEY_Right, Mod1Mask, "\033[1;3C", 0, 0}, + { XKB_KEY_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, + { XKB_KEY_Right, ControlMask, "\033[1;5C", 0, 0}, + { XKB_KEY_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, + { XKB_KEY_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, + { XKB_KEY_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, + { XKB_KEY_Right, MOD_ANY, "\033[C", 0, -1}, + { XKB_KEY_Right, MOD_ANY, "\033OC", 0, +1}, + { XKB_KEY_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + { XKB_KEY_Return, Mod1Mask, "\033\r", 0, 0}, + { XKB_KEY_Return, MOD_ANY, "\r", 0, 0}, + { XKB_KEY_Insert, ShiftMask, "\033[4l", -1, 0}, + { XKB_KEY_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XKB_KEY_Insert, ControlMask, "\033[L", -1, 0}, + { XKB_KEY_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XKB_KEY_Insert, MOD_ANY, "\033[4h", -1, 0}, + { XKB_KEY_Insert, MOD_ANY, "\033[2~", +1, 0}, + { XKB_KEY_Delete, ControlMask, "\033[M", -1, 0}, + { XKB_KEY_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XKB_KEY_Delete, ShiftMask, "\033[2K", -1, 0}, + { XKB_KEY_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XKB_KEY_Delete, MOD_ANY, "\033[P", -1, 0}, + { XKB_KEY_Delete, MOD_ANY, "\033[3~", +1, 0}, + { XKB_KEY_BackSpace, MOD_NONE, "\177", 0, 0}, + { XKB_KEY_BackSpace, Mod1Mask, "\033\177", 0, 0}, + { XKB_KEY_Home, ShiftMask, "\033[2J", 0, -1}, + { XKB_KEY_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XKB_KEY_Home, MOD_ANY, "\033[H", 0, -1}, + { XKB_KEY_Home, MOD_ANY, "\033[1~", 0, +1}, + { XKB_KEY_End, ControlMask, "\033[J", -1, 0}, + { XKB_KEY_End, ControlMask, "\033[1;5F", +1, 0}, + { XKB_KEY_End, ShiftMask, "\033[K", -1, 0}, + { XKB_KEY_End, ShiftMask, "\033[1;2F", +1, 0}, + { XKB_KEY_End, MOD_ANY, "\033[4~", 0, 0}, + { XKB_KEY_Prior, ControlMask, "\033[5;5~", 0, 0}, + { XKB_KEY_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XKB_KEY_Prior, MOD_ANY, "\033[5~", 0, 0}, + { XKB_KEY_Next, ControlMask, "\033[6;5~", 0, 0}, + { XKB_KEY_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XKB_KEY_Next, MOD_ANY, "\033[6~", 0, 0}, + { XKB_KEY_F1, MOD_NONE, "\033OP" , 0, 0}, + { XKB_KEY_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + { XKB_KEY_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + { XKB_KEY_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + { XKB_KEY_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + { XKB_KEY_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + { XKB_KEY_F2, MOD_NONE, "\033OQ" , 0, 0}, + { XKB_KEY_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + { XKB_KEY_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + { XKB_KEY_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + { XKB_KEY_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + { XKB_KEY_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + { XKB_KEY_F3, MOD_NONE, "\033OR" , 0, 0}, + { XKB_KEY_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + { XKB_KEY_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + { XKB_KEY_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + { XKB_KEY_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + { XKB_KEY_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + { XKB_KEY_F4, MOD_NONE, "\033OS" , 0, 0}, + { XKB_KEY_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + { XKB_KEY_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + { XKB_KEY_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + { XKB_KEY_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + { XKB_KEY_F5, MOD_NONE, "\033[15~", 0, 0}, + { XKB_KEY_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + { XKB_KEY_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + { XKB_KEY_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + { XKB_KEY_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + { XKB_KEY_F6, MOD_NONE, "\033[17~", 0, 0}, + { XKB_KEY_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + { XKB_KEY_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + { XKB_KEY_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + { XKB_KEY_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + { XKB_KEY_F7, MOD_NONE, "\033[18~", 0, 0}, + { XKB_KEY_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + { XKB_KEY_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + { XKB_KEY_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + { XKB_KEY_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + { XKB_KEY_F8, MOD_NONE, "\033[19~", 0, 0}, + { XKB_KEY_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + { XKB_KEY_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + { XKB_KEY_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + { XKB_KEY_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + { XKB_KEY_F9, MOD_NONE, "\033[20~", 0, 0}, + { XKB_KEY_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + { XKB_KEY_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + { XKB_KEY_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + { XKB_KEY_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + { XKB_KEY_F10, MOD_NONE, "\033[21~", 0, 0}, + { XKB_KEY_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + { XKB_KEY_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + { XKB_KEY_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + { XKB_KEY_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + { XKB_KEY_F11, MOD_NONE, "\033[23~", 0, 0}, + { XKB_KEY_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + { XKB_KEY_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + { XKB_KEY_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + { XKB_KEY_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + { XKB_KEY_F12, MOD_NONE, "\033[24~", 0, 0}, + { XKB_KEY_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + { XKB_KEY_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + { XKB_KEY_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + { XKB_KEY_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + { XKB_KEY_F13, MOD_NONE, "\033[1;2P", 0, 0}, + { XKB_KEY_F14, MOD_NONE, "\033[1;2Q", 0, 0}, + { XKB_KEY_F15, MOD_NONE, "\033[1;2R", 0, 0}, + { XKB_KEY_F16, MOD_NONE, "\033[1;2S", 0, 0}, + { XKB_KEY_F17, MOD_NONE, "\033[15;2~", 0, 0}, + { XKB_KEY_F18, MOD_NONE, "\033[17;2~", 0, 0}, + { XKB_KEY_F19, MOD_NONE, "\033[18;2~", 0, 0}, + { XKB_KEY_F20, MOD_NONE, "\033[19;2~", 0, 0}, + { XKB_KEY_F21, MOD_NONE, "\033[20;2~", 0, 0}, + { XKB_KEY_F22, MOD_NONE, "\033[21;2~", 0, 0}, + { XKB_KEY_F23, MOD_NONE, "\033[23;2~", 0, 0}, + { XKB_KEY_F24, MOD_NONE, "\033[24;2~", 0, 0}, + { XKB_KEY_F25, MOD_NONE, "\033[1;5P", 0, 0}, + { XKB_KEY_F26, MOD_NONE, "\033[1;5Q", 0, 0}, + { XKB_KEY_F27, MOD_NONE, "\033[1;5R", 0, 0}, + { XKB_KEY_F28, MOD_NONE, "\033[1;5S", 0, 0}, + { XKB_KEY_F29, MOD_NONE, "\033[15;5~", 0, 0}, + { XKB_KEY_F30, MOD_NONE, "\033[17;5~", 0, 0}, + { XKB_KEY_F31, MOD_NONE, "\033[18;5~", 0, 0}, + { XKB_KEY_F32, MOD_NONE, "\033[19;5~", 0, 0}, + { XKB_KEY_F33, MOD_NONE, "\033[20;5~", 0, 0}, + { XKB_KEY_F34, MOD_NONE, "\033[21;5~", 0, 0}, + { XKB_KEY_F35, MOD_NONE, "\033[23;5~", 0, 0}, }; /* @@ -7,35 +7,39 @@ VERSION = 0.9.0.1 PREFIX = /usr/local MANPREFIX = $(PREFIX)/share/man -X11INC = /usr/X11R6/include -X11LIB = /usr/X11R6/lib - PKG_CONFIG = pkg-config +WAYLAND_SCANNER = wayland-scanner + +# Wayland protocol XMLs (wayland-protocols). pkg-config only reports a +# system-wide install, so also look in the usual data dirs (per user and +# under /usr/local). Override with: make WLPROTO=/path/to/wayland-protocols +WLPROTO_PC = $(shell $(PKG_CONFIG) --variable=pkgdatadir wayland-protocols 2>/dev/null) +WLPROTO_USER = $(or $(XDG_DATA_HOME),$(HOME)/.local/share)/wayland-protocols +WLPROTO_DIRS = $(WLPROTO_PC) $(WLPROTO_USER) +WLPROTO_DIRS += /usr/local/share/wayland-protocols +WLPROTO_DIRS += /usr/share/wayland-protocols +WLPROTO ?= $(firstword $(foreach d,$(WLPROTO_DIRS),$(if $(wildcard $(d)/stable/xdg-shell/xdg-shell.xml),$(d)))) +XDG_SHELL_XML = $(WLPROTO)/stable/xdg-shell/xdg-shell.xml +VIEWPORTER_XML = $(WLPROTO)/stable/viewporter/viewporter.xml +FRACTIONAL_XML = $(WLPROTO)/staging/fractional-scale/fractional-scale-v1.xml +CURSOR_SHAPE_XML = $(WLPROTO)/staging/cursor-shape/cursor-shape-v1.xml +SYSTEM_BELL_XML = $(WLPROTO)/staging/xdg-system-bell/xdg-system-bell-v1.xml +PRIMARY_XML = $(WLPROTO)/unstable/primary-selection/primary-selection-unstable-v1.xml +TEXT_INPUT_XML = $(WLPROTO)/unstable/text-input/text-input-unstable-v3.xml +# cursor-shape-v1 references zwp_tablet_tool_v2, so its interface must exist +TABLET_XML = $(WLPROTO)/stable/tablet/tablet-v2.xml # includes and libs -INCS = -I$(X11INC) \ - `$(PKG_CONFIG) --cflags fontconfig` \ - `$(PKG_CONFIG) --cflags freetype2` \ - `$(PKG_CONFIG) --cflags harfbuzz` -LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ - `$(PKG_CONFIG) --libs fontconfig` \ - `$(PKG_CONFIG) --libs freetype2` \ - `$(PKG_CONFIG) --libs harfbuzz` +INCS = `$(PKG_CONFIG) --cflags wayland-client xkbcommon fontconfig freetype2 harfbuzz` +LIBS = -lm -lrt -lutil \ + `$(PKG_CONFIG) --libs wayland-client xkbcommon fontconfig freetype2 harfbuzz` # flags -#CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L ${XINERAMAFLAGS} -CPUFLAGS = -march=native -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations ${CPUFLAGS} -Ofast --lto ${INCS} ${CPPFLAGS} +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -D_GNU_SOURCE +CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -O2 STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) STLDFLAGS = $(LIBS) $(LDFLAGS) -# OpenBSD: -#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ -# `$(PKG_CONFIG) --libs fontconfig` \ -# `$(PKG_CONFIG) --libs freetype2` - # compiler and linker # CC = c99 @@ -1,17 +1,19 @@ +/* See LICENSE for license details. */ + #include <stdlib.h> #include <stdio.h> -#include <math.h> -#include <X11/Xft/Xft.h> #include <hb.h> #include <hb-ft.h> #include "st.h" +#include "render.h" +#include "hb.h" -void hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoints, int start, int length); -hb_font_t *hbfindfont(XftFont *match); +void hbtransformsegment(FT_Face, const Glyph *, hb_codepoint_t *, int, int); +hb_font_t *hbfindfont(FT_Face); typedef struct { - XftFont *match; + FT_Face face; hb_font_t *font; } HbFontMatch; @@ -19,105 +21,120 @@ static int hbfontslen = 0; static HbFontMatch *hbfontcache = NULL; void -hbunloadfonts() +hbunloadfonts(void) { - for (int i = 0; i < hbfontslen; i++) { + int i; + + for (i = 0; i < hbfontslen; i++) hb_font_destroy(hbfontcache[i].font); - XftUnlockFace(hbfontcache[i].match); - } - if (hbfontcache != NULL) { - free(hbfontcache); - hbfontcache = NULL; - } + free(hbfontcache); + hbfontcache = NULL; hbfontslen = 0; } hb_font_t * -hbfindfont(XftFont *match) +hbfindfont(FT_Face face) { - for (int i = 0; i < hbfontslen; i++) { - if (hbfontcache[i].match == match) + int i; + hb_font_t *font; + + for (i = 0; i < hbfontslen; i++) + if (hbfontcache[i].face == face) return hbfontcache[i].font; - } - /* Font not found in cache, caching it now. */ - hbfontcache = realloc(hbfontcache, sizeof(HbFontMatch) * (hbfontslen + 1)); - FT_Face face = XftLockFace(match); - hb_font_t *font = hb_ft_font_create(face, NULL); - if (font == NULL) - die("Failed to load Harfbuzz font."); + hbfontcache = realloc(hbfontcache, + sizeof(HbFontMatch) * (hbfontslen + 1)); + if (!hbfontcache) + die("realloc: failed to grow HarfBuzz font cache\n"); + + font = hb_ft_font_create(face, NULL); + if (!font) + die("Failed to load Harfbuzz font.\n"); - hbfontcache[hbfontslen].match = match; + hbfontcache[hbfontslen].face = face; hbfontcache[hbfontslen].font = font; - hbfontslen += 1; + hbfontslen++; return font; } void -hbtransform(XftGlyphFontSpec *specs, const Glyph *glyphs, size_t len, int x, int y) +hbtransform(GlyphSpec *specs, const Glyph *glyphs, size_t len, int x, int y) { int start = 0, length = 1, gstart = 0; - hb_codepoint_t *codepoints = calloc(len, sizeof(hb_codepoint_t)); + hb_codepoint_t *codepoints; + int idx, specidx; - for (int idx = 1, specidx = 1; idx < len; idx++) { + codepoints = calloc(len, sizeof(hb_codepoint_t)); + if (!codepoints) + die("calloc: failed to allocate HarfBuzz buffer\n"); + + for (idx = 1, specidx = 1; idx < (int)len; idx++) { if (glyphs[idx].mode & ATTR_WDUMMY) { - length += 1; + length++; continue; } - if (specs[specidx].font != specs[start].font || ATTRCMP(glyphs[gstart], glyphs[idx]) || selected(x + idx, y) != selected(x + gstart, y)) { - hbtransformsegment(specs[start].font, glyphs, codepoints, gstart, length); + if (specs[specidx].font != specs[start].font || + ATTRCMP(glyphs[gstart], glyphs[idx]) || + selected(x + idx, y) != selected(x + gstart, y)) { + hbtransformsegment((FT_Face)specs[start].font, glyphs, + codepoints, gstart, length); - /* Reset the sequence. */ length = 1; start = specidx; gstart = idx; } else { - length += 1; + length++; } specidx++; } /* EOL. */ - hbtransformsegment(specs[start].font, glyphs, codepoints, gstart, length); + hbtransformsegment((FT_Face)specs[start].font, glyphs, codepoints, + gstart, length); /* Apply the transformation to glyph specs. */ - for (int i = 0, specidx = 0; i < len; i++) { - if (glyphs[i].mode & ATTR_WDUMMY) + for (idx = 0, specidx = 0; idx < (int)len; idx++) { + if (glyphs[idx].mode & ATTR_WDUMMY) continue; - if (glyphs[i].mode & ATTR_BOXDRAW) { + if (glyphs[idx].mode & ATTR_BOXDRAW) { specidx++; continue; } - if (codepoints[i] != specs[specidx].glyph) - ((Glyph *)glyphs)[i].mode |= ATTR_LIGA; + if (codepoints[idx] != specs[specidx].glyph) + ((Glyph *)glyphs)[idx].mode |= ATTR_LIGA; - specs[specidx++].glyph = codepoints[i]; + specs[specidx++].glyph = codepoints[idx]; } free(codepoints); } void -hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoints, int start, int length) +hbtransformsegment(FT_Face face, const Glyph *string, + hb_codepoint_t *codepoints, int start, int length) { - hb_font_t *font = hbfindfont(xfont); + hb_font_t *font = hbfindfont(face); + hb_buffer_t *buffer; + hb_glyph_info_t *info; + unsigned int count, i; + Rune rune; + ushort mode; + if (font == NULL) return; - Rune rune; - ushort mode = USHRT_MAX; - hb_buffer_t *buffer = hb_buffer_create(); + buffer = hb_buffer_create(); hb_buffer_set_direction(buffer, HB_DIRECTION_LTR); /* Fill buffer with codepoints. */ - for (int i = start; i < (start+length); i++) { - rune = string[i].u; - mode = string[i].mode; + for (i = 0; i < (unsigned)length; i++) { + rune = string[start + i].u; + mode = string[start + i].mode; if (mode & ATTR_WDUMMY) rune = 0x0020; hb_buffer_add_codepoints(buffer, &rune, 1, 0, 1); @@ -127,14 +144,12 @@ hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoin hb_shape(font, buffer, NULL, 0); /* Get new glyph info. */ - hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, NULL); + info = hb_buffer_get_glyph_infos(buffer, &count); - /* Write new codepoints. */ - for (int i = 0; i < length; i++) { - hb_codepoint_t gid = info[i].codepoint; - codepoints[start+i] = gid; - } + /* Write new codepoints. A ligature can collapse several cells into + * one glyph; leave the remaining cells with glyph 0, which wl.c skips. */ + for (i = 0; i < (unsigned)length; i++) + codepoints[start + i] = i < count ? info[i].codepoint : 0; - /* Cleanup. */ hb_buffer_destroy(buffer); } @@ -1,7 +1,4 @@ -#include <X11/Xft/Xft.h> -#include <hb.h> -#include <hb-ft.h> - -void hbunloadfonts(); -void hbtransform(XftGlyphFontSpec *, const Glyph *, size_t, int, int); +#include "render.h" +void hbunloadfonts(void); +void hbtransform(GlyphSpec *, const Glyph *, size_t, int, int); @@ -0,0 +1,28 @@ +/* See LICENSE for license details. */ + +#ifndef RENDER_H +#define RENDER_H + +#include <stdint.h> +#include "st.h" + +/* A glyph ready to be rasterized. font is an FT_Face owned by wl.c. */ +typedef struct { + void *font; + uint32_t glyph; + short x; /* buffer pixel, left edge of the cell run */ + short y; /* buffer pixel, baseline */ +} GlyphSpec; + +/* Replace a rectangle (used for backgrounds; alpha is preserved). */ +void clearrect(int, int, int, int, uint32_t); + +/* Alpha-blend a rectangle (text decorations, box drawing, cursor). */ +void blendrect(int, int, int, int, uint32_t); + +int isboxdraw(Rune); +ushort boxdrawindex(const Glyph *); +void drawboxes(int, int, int, int, uint32_t, uint32_t, + const GlyphSpec *, int); + +#endif @@ -4,14 +4,14 @@ st \- simple terminal .SH SYNOPSIS .B st .RB [ \-aiv ] +.RB [ \-A +.IR alpha ] .RB [ \-c .IR class ] .RB [ \-f .IR font ] .RB [ \-g .IR geometry ] -.RB [ \-n -.IR name ] .RB [ \-o .IR iofile ] .RB [ \-T @@ -20,65 +20,69 @@ st \- simple terminal .IR title ] .RB [ \-l .IR line ] -.RB [ \-w -.IR windowid ] .RB [[ \-e ] .IR command .RI [ arguments ...]] .PP .B st .RB [ \-aiv ] +.RB [ \-A +.IR alpha ] .RB [ \-c .IR class ] .RB [ \-f .IR font ] .RB [ \-g .IR geometry ] -.RB [ \-n -.IR name ] .RB [ \-o .IR iofile ] .RB [ \-T .IR title ] .RB [ \-t .IR title ] -.RB [ \-w -.IR windowid ] .RB \-l .IR line .RI [ stty_args ...] .SH DESCRIPTION .B st -is a simple terminal emulator. +is a simple terminal emulator for Wayland. +It uses xdg-shell and wl_shm directly; there is no X11 backend. .SH OPTIONS .TP .B \-a disable alternate screens in terminal .TP +.BI \-A " alpha" +set the opacity of the terminal background (0.0 to 1.0). +This overrides the +.I alpha +value from config.h. +.TP .BI \-c " class" -defines the window class (default $TERM). +defines the application id (default $TERM). .TP .BI \-f " font" defines the .I font -to use when st is run. +to use when st is run (a fontconfig pattern). .TP .BI \-g " geometry" -defines the X11 geometry string. -The form is [=][<cols>{xX}<rows>][{+-}<xoffset>{+-}<yoffset>]. See -.BR XParseGeometry (3) -for further details. +sets the initial size of the terminal in columns and rows. +The form is [<cols>][x<rows>]. +Wayland does not allow clients to position their windows, so any +.I xoffset +or +.I yoffset +is ignored with a warning. .TP .B \-i -will fixate the position given with the -g option. -.TP -.BI \-n " name" -defines the window instance name (default $TERM). +fix the window to its initial size (the compositor is asked to keep the +minimum and maximum size equal). .TP .BI \-o " iofile" writes all the I/O to -.I iofile. -This feature is useful when recording st sessions. A value of "-" means +.IR iofile . +This feature is useful when recording st sessions. A value of "-" means standard output. .TP .BI \-T " title" @@ -87,10 +91,6 @@ defines the window title (default 'st'). .BI \-t " title" defines the window title (default 'st'). .TP -.BI \-w " windowid" -embeds st within the window identified by -.I windowid -.TP .BI \-l " line" use a tty .I line @@ -100,16 +100,12 @@ should be a (pseudo-)serial device (e.g. /dev/ttyS0 on Linux for serial port 0). When this flag is given remaining arguments are used as flags for -.BR stty(1). +.BR stty (1). By default st initializes the serial line to 8 bits, no parity, 1 stop bit -and a 38400 baud rate. The speed is set by appending it as last argument -(e.g. 'st -l /dev/ttyS0 115200'). Arguments before the last one are -.BR stty(1) -flags. If you want to set odd parity on 115200 baud use for example 'st -l -/dev/ttyS0 parenb parodd 115200'. Set the number of bits by using for -example 'st -l /dev/ttyS0 cs7 115200'. See -.BR stty(1) -for more arguments and cases. +and a 38400 baud rate. The speed is set by appending it as last argument +(e.g. 'st -l /dev/ttyS0 115200'). Arguments before the last one are +.BR stty (1) +flags. .TP .B \-v prints version information to stderr, then exits. @@ -127,8 +123,6 @@ even without it. .TP .B Break Send a break in the serial line. -Break key is obtained in PC keyboards -pressing at the same time control and pause. .TP .B Ctrl-Print Screen Toggle if st should print to the @@ -142,36 +136,39 @@ Print the full screen to the Print the selection to the .I iofile. .TP -.B Ctrl-Shift-Page Up +.B Ctrl-= Increase font size. .TP -.B Ctrl-Shift-Page Down +.B Ctrl-Minus Decrease font size. .TP .B Ctrl-Shift-Home -Reset to default font size. -.TP -.B Ctrl-Shift-y -Paste from primary selection (middle mouse button). +Reset to the default font size. .TP .B Ctrl-Shift-c Copy the selected text to the clipboard selection. .TP .B Ctrl-Shift-v Paste from the clipboard selection. +.TP +.B Ctrl-Shift-y +Paste from the primary selection (middle mouse button). +.TP +.B Shift-Insert +Paste from the primary selection. +.TP +.B Ctrl-Shift-s +Toggle keyboard selection mode. .SH CUSTOMIZATION .B st -can be customized by creating a custom config.h and (re)compiling the source -code. This keeps it fast, secure and simple. +is customized by editing config.h and recompiling the source code. +This keeps it fast, secure and simple. .SH AUTHORS See the LICENSE file for the authors. .SH LICENSE See the LICENSE file for the terms of redistribution. .SH SEE ALSO -.BR tabbed (1), -.BR utmp (1), .BR stty (1), .BR scroll (1) .SH BUGS See the TODO file in the distribution. - @@ -16,8 +16,6 @@ #include <termios.h> #include <unistd.h> #include <wchar.h> -#include <X11/keysym.h> -#include <X11/X.h> #include "st.h" #include "win.h" @@ -202,7 +200,7 @@ static void tsetscroll(int, int); static void tswapscreen(void); static void tsetmode(int, int, int *, int); static int twrite(const char *, int, int); -static void tfulldirt(void); +void tfulldirt(void); static void tcontrolcode(uchar ); static void tdectest(char ); static void tdefutf8(char); @@ -1541,10 +1539,10 @@ tsetmode(int priv, int set, int *args, int narg) if (priv) { switch (*args) { case 1: /* DECCKM -- Cursor key */ - xsetmode(set, MODE_APPCURSOR); + setmode(set, MODE_APPCURSOR); break; case 5: /* DECSCNM -- Reverse video */ - xsetmode(set, MODE_REVERSE); + setmode(set, MODE_REVERSE); break; case 6: /* DECOM -- Origin */ MODBIT(term.c.state, set, CURSOR_ORIGIN); @@ -1564,36 +1562,36 @@ tsetmode(int priv, int set, int *args, int narg) case 12: /* att610 -- Start blinking cursor (IGNORED) */ break; case 25: /* DECTCEM -- Text Cursor Enable Mode */ - xsetmode(!set, MODE_HIDE); + setmode(!set, MODE_HIDE); break; case 9: /* X10 mouse compatibility mode */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEX10); + setpointermotion(0); + setmode(0, MODE_MOUSE); + setmode(set, MODE_MOUSEX10); break; case 1000: /* 1000: report button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEBTN); + setpointermotion(0); + setmode(0, MODE_MOUSE); + setmode(set, MODE_MOUSEBTN); break; case 1002: /* 1002: report motion on button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMOTION); + setpointermotion(0); + setmode(0, MODE_MOUSE); + setmode(set, MODE_MOUSEMOTION); break; case 1003: /* 1003: enable all mouse motions */ - xsetpointermotion(set); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMANY); + setpointermotion(set); + setmode(0, MODE_MOUSE); + setmode(set, MODE_MOUSEMANY); break; case 1004: /* 1004: send focus events to tty */ - xsetmode(set, MODE_FOCUS); + setmode(set, MODE_FOCUS); break; case 1006: /* 1006: extended reporting mode */ - xsetmode(set, MODE_MOUSESGR); + setmode(set, MODE_MOUSESGR); break; case 1034: - xsetmode(set, MODE_8BIT); + setmode(set, MODE_8BIT); break; case 10 …… diff 过长已截断 …… |
some old changes i made 2023查看变更config.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) @@ -6,7 +6,8 @@ * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ //static char *font = "JetBrainsMono Nerd Font Mono:pixelsize=26:antialias=true:autohint=true"; -static char *font = "SauceCodePro Nerd Font Mono:pixelsize=26:antialias=true:autohint=true"; +//static char *font = "SauceCodePro Nerd Font Mono:pixelsize=26:antialias=true:autohint=true"; +static char *font = "SauceCodePro Nerd Font Mono:pixelsize=20:antialias=true:autohint=true"; //static char *font = "Source Code Pro:pixelsize=26:antialias=true:autohint=true"; static int borderpx = 1; @@ -82,8 +83,9 @@ const int boxdraw_bold = 1; const int boxdraw_braille = 1; /* bg opacity */ -//float alpha = 0.60; -float alpha = 0.55; +float alpha = 0.75; +//float alpha = 0.55; + //float alpha = 0.45; //float alpha = 0.0; |
w3m support查看变更config.h | 8 +++++--- config.mk | 3 +-- patches/st-w3m-0.8.3.diff | 42 ++++++++++++++++++++++++++++++++++++++++++ x.c | 2 ++ 4 files changed, 50 insertions(+), 5 deletions(-) @@ -82,8 +82,9 @@ const int boxdraw_bold = 1; const int boxdraw_braille = 1; /* bg opacity */ -//float alpha = 0.65; -float alpha = 0.45; +//float alpha = 0.60; +float alpha = 0.55; +//float alpha = 0.45; //float alpha = 0.0; /* @@ -138,7 +139,8 @@ static const char *colorname[] = { //[256] = "#222D31", /* background */ [256] = "#282a36", /* background */ //[256] = "#000000", /* background */ - [257] = "#B5B5B5", /* foreground */ +// [257] = "#B5B5B5", /* foreground */ + [257] = "#BD93F9", /* foreground */ }; /* @@ -24,10 +24,9 @@ LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ # flags #CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L ${XINERAMAFLAGS} -#CPUFLAGS = -march=x86-64-v3 CPUFLAGS = -march=native CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations ${CPUFLAGS} -O3 --lto ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations ${CPUFLAGS} -Ofast --lto ${INCS} ${CPPFLAGS} STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) STLDFLAGS = $(LIBS) $(LDFLAGS) @@ -0,0 +1,42 @@ +From 69cffc587b54b0a9cd81adb87abad8e526d5b25b Mon Sep 17 00:00:00 2001 +From: "Avi Halachmi (:avih)" <avihpit@yahoo.com> +Date: Thu, 4 Jun 2020 17:35:08 +0300 +Subject: [PATCH] support w3m images + +w3m images are a hack which renders on top of the terminal's drawable, +which didn't work in st because when using double buffering, the front +buffer (on which w3m draws its images) is ignored, and st draws only +on the back buffer, which is then copied to the front buffer. + +There's a patch to make it work at the FAQ already, but that patch +canceles double-buffering, which can have negative side effects on +some cases such as flickering. + +This patch achieves the same goal but instead of canceling the double +buffer it first copies the front buffer to the back buffer. + +This has the same issues as the FAQ patch in that the cursor line is +deleted at the image (because st renders always full lines), but +otherwise it's simpler and does keeps double buffering. +--- + x.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/x.c b/x.c +index e5f1737..b6ae162 100644 +--- a/x.c ++++ b/x.c +@@ -1594,6 +1594,8 @@ xsettitle(char *p) + int + xstartdraw(void) + { ++ if (IS_SET(MODE_VISIBLE)) ++ XCopyArea(xw.dpy, xw.win, xw.buf, dc.gc, 0, 0, win.w, win.h, 0, 0); + return IS_SET(MODE_VISIBLE); + } + + +base-commit: 43a395ae91f7d67ce694e65edeaa7bbc720dd027 +-- +2.17.1 + @@ -1665,6 +1665,8 @@ xsettitle(char *p) int xstartdraw(void) { + if (IS_SET(MODE_VISIBLE)) + XCopyArea(xw.dpy, xw.win, xw.buf, dc.gc, 0, 0, win.w, win.h, 0, 0); return IS_SET(MODE_VISIBLE); } |
nerd font support查看变更config.h | 10 ++++++---- config.mk | 5 +++-- patches/st-dynamic-cursor-color-0.9.diff | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ x.c | 17 ++++++++++++++--- 4 files changed, 73 insertions(+), 9 deletions(-) @@ -6,8 +6,8 @@ * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ //static char *font = "JetBrainsMono Nerd Font Mono:pixelsize=26:antialias=true:autohint=true"; -//static char *font = "SauceCodePro Nerd Font Mono:pixelsize=26:antialias=true:autohint=true"; -static char *font = "Source Code Pro:pixelsize=26:antialias=true:autohint=true"; +static char *font = "SauceCodePro Nerd Font Mono:pixelsize=26:antialias=true:autohint=true"; +//static char *font = "Source Code Pro:pixelsize=26:antialias=true:autohint=true"; static int borderpx = 1; /* @@ -82,8 +82,9 @@ const int boxdraw_bold = 1; const int boxdraw_braille = 1; /* bg opacity */ -float alpha = 0.65; -//float alpha = 0.5; //better visual if u r using a dark wallpaper +//float alpha = 0.65; +float alpha = 0.45; +//float alpha = 0.0; /* * bell volume. It must be a value between -100 and 100. Use 0 for disabling @@ -136,6 +137,7 @@ static const char *colorname[] = { /* special colors */ //[256] = "#222D31", /* background */ [256] = "#282a36", /* background */ +//[256] = "#000000", /* background */ [257] = "#B5B5B5", /* foreground */ }; @@ -24,9 +24,10 @@ LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ # flags #CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L ${XINERAMAFLAGS} -CPUFLAGS = -march=x86-64-v3 +#CPUFLAGS = -march=x86-64-v3 +CPUFLAGS = -march=native CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations ${CPUFLAGS} -O3 ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations ${CPUFLAGS} -O3 --lto ${INCS} ${CPPFLAGS} STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) STLDFLAGS = $(LIBS) $(LDFLAGS) @@ -0,0 +1,50 @@ +From 215ec30d6b5fe3319f88f1c9d16a37b6e14e5a53 Mon Sep 17 00:00:00 2001 +From: Bakkeby <bakkeby@gmail.com> +Date: Mon, 19 Dec 2022 10:20:47 +0100 +Subject: [PATCH] dynamic cursor color: cursor color taken from current + character + +--- + x.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/x.c b/x.c +index 2a3bd38..21aadce 100644 +--- a/x.c ++++ b/x.c +@@ -1520,6 +1520,7 @@ void + xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) + { + Color drawcol; ++ XRenderColor colbg; + + /* remove the old cursor */ + if (selected(ox, oy)) +@@ -1548,11 +1549,21 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) + if (selected(cx, cy)) { + g.fg = defaultfg; + g.bg = defaultrcs; ++ } else if (!(og.mode & ATTR_REVERSE)) { ++ unsigned long col = g.bg; ++ g.bg = g.fg; ++ g.fg = col; ++ } ++ ++ if (IS_TRUECOL(g.bg)) { ++ colbg.alpha = 0xffff; ++ colbg.red = TRUERED(g.bg); ++ colbg.green = TRUEGREEN(g.bg); ++ colbg.blue = TRUEBLUE(g.bg); ++ XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &drawcol); + } else { +- g.fg = defaultbg; +- g.bg = defaultcs; ++ drawcol = dc.col[g.bg]; + } +- drawcol = dc.col[g.bg]; + } + + /* draw the new one */ +-- +2.38.1 + @@ -1544,6 +1544,7 @@ void xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int len) { Color drawcol; + XRenderColor colbg; /* remove the old cursor */ if (selected(ox, oy)) @@ -1575,11 +1576,21 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int le if (selected(cx, cy)) { g.fg = defaultfg; g.bg = defaultrcs; + } else if (!(og.mode & ATTR_REVERSE)) { + unsigned long col = g.bg; + g.bg = g.fg; + g.fg = col; + } + + if (IS_TRUECOL(g.bg)) { + colbg.alpha = 0xffff; + colbg.red = TRUERED(g.bg); + colbg.green = TRUEGREEN(g.bg); + colbg.blue = TRUEBLUE(g.bg); + XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &drawcol); } else { - g.fg = defaultbg; - g.bg = defaultcs; + drawcol = dc.col[g.bg]; } - drawcol = dc.col[g.bg]; } /* draw the new one */ |
cpu flags added查看变更config.mk | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) @@ -1,5 +1,5 @@ # st version -VERSION = 0.8.4 +VERSION = 0.9.0.1 # Customize below to fit your system @@ -23,6 +23,10 @@ LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ `$(PKG_CONFIG) --libs harfbuzz` # flags +#CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L ${XINERAMAFLAGS} +CPUFLAGS = -march=x86-64-v3 +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L +CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations ${CPUFLAGS} -O3 ${INCS} ${CPPFLAGS} STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) STLDFLAGS = $(LIBS) $(LDFLAGS) |
remap zoom查看变更config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) @@ -207,8 +207,8 @@ static Shortcut shortcuts[] = { { ControlMask, XK_Print, toggleprinter, {.i = 0} }, { ShiftMask, XK_Print, printscreen, {.i = 0} }, { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { TERMMOD, XK_Prior, zoom, {.f = +1} }, - { TERMMOD, XK_Next, zoom, {.f = -1} }, + { ControlMask, XK_equal, zoom, {.f = +1} }, + { ControlMask, XK_minus, zoom, {.f = -1} }, { TERMMOD, XK_Home, zoomreset, {.f = 0} }, { TERMMOD, XK_C, clipcopy, {.i = 0} }, { TERMMOD, XK_V, clippaste, {.i = 0} }, |
rebuild查看变更.gitignore | 4 + LEGACY | 17 + LICENSE | 34 ++ Makefile | 59 +++ README | 34 ++ arg.h | 50 ++ boxdraw.c | 194 +++++++ boxdraw_data.h | 214 ++++++++ config.h | 489 ++++++++++++++++++ config.mk | 37 ++ hb.c | 140 +++++ hb.h | 7 + patches/st-alpha-0.8.2.diff | 163 ++++++ patches/st-anysize-0.8.1.diff | 152 ++++++ patches/st-boxdraw_v2-0.8.3.diff | 600 +++++++++++++++++++++ patches/st-copyout | 12 + patches/st-hidecursor-0.8.1.diff | 88 ++++ patches/st-keyboard_select-20200617-9ba7ecf.diff | 319 ++++++++++++ patches/st-ligatures-boxdraw-20200430-0.8.3.diff | 311 +++++++++++ patches/st-scrollback-20190331-21367a0.diff | 335 ++++++++++++ st.1 | 177 +++++++ st.c | 2891 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ st.h | 141 +++++ st.info | 239 +++++++++ win.h | 42 ++ x.c | 2133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 26 files changed, 8882 insertions(+) @@ -0,0 +1,4 @@ +*.orig +*.rej +*.o +st @@ -0,0 +1,17 @@ +A STATEMENT ON LEGACY SUPPORT + +In the terminal world there is much cruft that comes from old and unsup‐ +ported terminals that inherit incompatible modes and escape sequences +which noone is able to know, except when he/she comes from that time and +developed a graphical vt100 emulator at that time. + +One goal of st is to only support what is really needed. When you en‐ +counter a sequence which you really need, implement it. But while you +are at it, do not add the other cruft you might encounter while sneek‐ +ing at other terminal emulators. History has bloated them and there is +no real evidence that most of the sequences are used today. + + +Christoph Lohmann <20h@r-36.net> +2012-09-13T07:00:36.081271045+02:00 + @@ -0,0 +1,34 @@ +MIT/X Consortium License + +© 2014-2020 Hiltjo Posthuma <hiltjo at codemadness dot org> +© 2018 Devin J. Pohly <djpohly at gmail dot com> +© 2014-2017 Quentin Rameau <quinq at fifth dot space> +© 2009-2012 Aurélien APTEL <aurelien dot aptel at gmail dot com> +© 2008-2017 Anselm R Garbe <garbeam at gmail dot com> +© 2012-2017 Roberto E. Vargas Caballero <k0ga at shike2 dot com> +© 2012-2016 Christoph Lohmann <20h at r-36 dot net> +© 2013 Eon S. Jeon <esjeon at hyunmu dot am> +© 2013 Alexander Sedov <alex0player at gmail dot com> +© 2013 Mark Edgar <medgar123 at gmail dot com> +© 2013-2014 Eric Pruitt <eric.pruitt at gmail dot com> +© 2013 Michael Forney <mforney at mforney dot org> +© 2013-2014 Markus Teich <markus dot teich at stusta dot mhn dot de> +© 2014-2015 Laslo Hunhold <dev at frign dot de> + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. @@ -0,0 +1,59 @@ +# st - simple terminal +# See LICENSE file for copyright and license details. +.POSIX: + +include config.mk + +SRC = st.c x.c boxdraw.c hb.c +OBJ = $(SRC:.c=.o) + +all: options st + +options: + @echo st build options: + @echo "CFLAGS = $(STCFLAGS)" + @echo "LDFLAGS = $(STLDFLAGS)" + @echo "CC = $(CC)" + +config.h: + cp config.def.h config.h + +.c.o: + $(CC) $(STCFLAGS) -c $< + +st.o: config.h st.h win.h +x.o: arg.h config.h st.h win.h hb.h +hb.o: st.h +boxdraw.o: config.h st.h boxdraw_data.h + +$(OBJ): config.h config.mk + +st: $(OBJ) + $(CC) -o $@ $(OBJ) $(STLDFLAGS) + +clean: + rm -f st $(OBJ) st-$(VERSION).tar.gz + +dist: clean + mkdir -p st-$(VERSION) + cp -R FAQ LEGACY TODO LICENSE Makefile README config.mk\ + config.def.h st.info st.1 arg.h st.h win.h $(SRC)\ + st-$(VERSION) + tar -cf - st-$(VERSION) | gzip > st-$(VERSION).tar.gz + rm -rf st-$(VERSION) + +install: st + mkdir -p $(DESTDIR)$(PREFIX)/bin + cp -f st $(DESTDIR)$(PREFIX)/bin + chmod 755 $(DESTDIR)$(PREFIX)/bin/st + mkdir -p $(DESTDIR)$(MANPREFIX)/man1 + sed "s/VERSION/$(VERSION)/g" < st.1 > $(DESTDIR)$(MANPREFIX)/man1/st.1 + chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 + tic -sx st.info + @echo Please see the README file regarding the terminfo entry of st. + +uninstall: + rm -f $(DESTDIR)$(PREFIX)/bin/st + rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 + +.PHONY: all options clean dist install uninstall @@ -0,0 +1,34 @@ +st - simple terminal +-------------------- +st is a simple terminal emulator for X which sucks less. + + +Requirements +------------ +In order to build st you need the Xlib header files. + + +Installation +------------ +Edit config.mk to match your local setup (st is installed into +the /usr/local namespace by default). + +Afterwards enter the following command to build and install st (if +necessary as root): + + make clean install + + +Running st +---------- +If you did not install st with make clean install, you must compile +the st terminfo entry with the following command: + + tic -sx st.info + +See the man page for additional details. + +Credits +------- +Based on Aurélien APTEL <aurelien dot aptel at gmail dot com> bt source code. + @@ -0,0 +1,50 @@ +/* + * Copy me if you can. + * by 20h + */ + +#ifndef ARG_H__ +#define ARG_H__ + +extern char *argv0; + +/* use main(int argc, char *argv[]) */ +#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ + argv[0] && argv[0][0] == '-'\ + && argv[0][1];\ + argc--, argv++) {\ + char argc_;\ + char **argv_;\ + int brk_;\ + if (argv[0][1] == '-' && argv[0][2] == '\0') {\ + argv++;\ + argc--;\ + break;\ + }\ + int i_;\ + for (i_ = 1, brk_ = 0, argv_ = argv;\ + argv[0][i_] && !brk_;\ + i_++) {\ + if (argv_ != argv)\ + break;\ + argc_ = argv[0][i_];\ + switch (argc_) + +#define ARGEND }\ + } + +#define ARGC() argc_ + +#define EARGF(x) ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ + ((x), abort(), (char *)0) :\ + (brk_ = 1, (argv[0][i_+1] != '\0')?\ + (&argv[0][i_+1]) :\ + (argc--, argv++, argv[0]))) + +#define ARGF() ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ + (char *)0 :\ + (brk_ = 1, (argv[0][i_+1] != '\0')?\ + (&argv[0][i_+1]) :\ + (argc--, argv++, argv[0]))) + +#endif @@ -0,0 +1,194 @@ +/* + * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih + * MIT/X Consortium License + */ + +#include <X11/Xft/Xft.h> +#include "st.h" +#include "boxdraw_data.h" + +/* Rounded non-negative integers division of n / d */ +#define DIV(n, d) (((n) + (d) / 2) / (d)) + +static Display *xdpy; +static Colormap xcmap; +static XftDraw *xd; +static Visual *xvis; + +static void drawbox(int, int, int, int, XftColor *, XftColor *, ushort); +static void drawboxlines(int, int, int, int, XftColor *, ushort); + +/* public API */ + +void +boxdraw_xinit(Display *dpy, Colormap cmap, XftDraw *draw, Visual *vis) +{ + xdpy = dpy; xcmap = cmap; xd = draw, xvis = vis; +} + +int +isboxdraw(Rune u) +{ + Rune block = u & ~0xff; + return (boxdraw && block == 0x2500 && boxdata[(uint8_t)u]) || + (boxdraw_braille && block == 0x2800); +} + +/* the "index" is actually the entire shape data encoded as ushort */ +ushort +boxdrawindex(const Glyph *g) +{ + if (boxdraw_braille && (g->u & ~0xff) == 0x2800) + return BRL | (uint8_t)g->u; + if (boxdraw_bold && (g->mode & ATTR_BOLD)) + return BDB | boxdata[(uint8_t)g->u]; + return boxdata[(uint8_t)g->u]; +} + +void +drawboxes(int x, int y, int cw, int ch, XftColor *fg, XftColor *bg, + const XftGlyphFontSpec *specs, int len) +{ + for ( ; len-- > 0; x += cw, specs++) + drawbox(x, y, cw, ch, fg, bg, (ushort)specs->glyph); +} + +/* implementation */ + +void +drawbox(int x, int y, int w, int h, XftColor *fg, XftColor *bg, ushort bd) +{ + ushort cat = bd & ~(BDB | 0xff); /* mask out bold and data */ + if (bd & (BDL | BDA)) { + /* lines (light/double/heavy/arcs) */ + drawboxlines(x, y, w, h, fg, bd); + + } else if (cat == BBD) { + /* lower (8-X)/8 block */ + int d = DIV((uint8_t)bd * h, 8); + XftDrawRect(xd, fg, x, y + d, w, h - d); + + } else if (cat == BBU) { + /* upper X/8 block */ + XftDrawRect(xd, fg, x, y, w, DIV((uint8_t)bd * h, 8)); + + } else if (cat == BBL) { + /* left X/8 block */ + XftDrawRect(xd, fg, x, y, DIV((uint8_t)bd * w, 8), h); + + } else if (cat == BBR) { + /* right (8-X)/8 block */ + int d = DIV((uint8_t)bd * w, 8); + XftDrawRect(xd, fg, x + d, y, w - d, h); + + } else if (cat == BBQ) { + /* Quadrants */ + int w2 = DIV(w, 2), h2 = DIV(h, 2); + if (bd & TL) + XftDrawRect(xd, fg, x, y, w2, h2); + if (bd & TR) + XftDrawRect(xd, fg, x + w2, y, w - w2, h2); + if (bd & BL) + XftDrawRect(xd, fg, x, y + h2, w2, h - h2); + if (bd & BR) + XftDrawRect(xd, fg, x + w2, y + h2, w - w2, h - h2); + + } else if (bd & BBS) { + /* Shades - data is 1/2/3 for 25%/50%/75% alpha, respectively */ + int d = (uint8_t)bd; + XftColor xfc; + XRenderColor xrc = { .alpha = 0xffff }; + + xrc.red = DIV(fg->color.red * d + bg->color.red * (4 - d), 4); + xrc.green = DIV(fg->color.green * d + bg->color.green * (4 - d), 4); + xrc.blue = DIV(fg->color.blue * d + bg->color.blue * (4 - d), 4); + + XftColorAllocValue(xdpy, xvis, xcmap, &xrc, &xfc); + XftDrawRect(xd, &xfc, x, y, w, h); + XftColorFree(xdpy, xvis, xcmap, &xfc); + + } else if (cat == BRL) { + /* braille, each data bit corresponds to one dot at 2x4 grid */ + int w1 = DIV(w, 2); + int h1 = DIV(h, 4), h2 = DIV(h, 2), h3 = DIV(3 * h, 4); + + if (bd & 1) XftDrawRect(xd, fg, x, y, w1, h1); + if (bd & 2) XftDrawRect(xd, fg, x, y + h1, w1, h2 - h1); + if (bd & 4) XftDrawRect(xd, fg, x, y + h2, w1, h3 - h2); + if (bd & 8) XftDrawRect(xd, fg, x + w1, y, w - w1, h1); + if (bd & 16) XftDrawRect(xd, fg, x + w1, y + h1, w - w1, h2 - h1); + if (bd & 32) XftDrawRect(xd, fg, x + w1, y + h2, w - w1, h3 - h2); + if (bd & 64) XftDrawRect(xd, fg, x, y + h3, w1, h - h3); + if (bd & 128) XftDrawRect(xd, fg, x + w1, y + h3, w - w1, h - h3); + + } +} + +void +drawboxlines(int x, int y, int w, int h, XftColor *fg, ushort bd) +{ + /* s: stem thickness. width/8 roughly matches underscore thickness. */ + /* We draw bold as 1.5 * normal-stem and at least 1px thicker. */ + /* doubles draw at least 3px, even when w or h < 3. bold needs 6px. */ + int mwh = MIN(w, h); + int base_s = MAX(1, DIV(mwh, 8)); + int bold = (bd & BDB) && mwh >= 6; /* possibly ignore boldness */ + int s = bold ? MAX(base_s + 1, DIV(3 * base_s, 2)) : base_s; + int w2 = DIV(w - s, 2), h2 = DIV(h - s, 2); + /* the s-by-s square (x + w2, y + h2, s, s) is the center texel. */ + /* The base length (per direction till edge) includes this square. */ + + int light = bd & (LL | LU | LR | LD); + int double_ = bd & (DL | DU | DR | DD); + + if (light) { + /* d: additional (negative) length to not-draw the center */ + /* texel - at arcs and avoid drawing inside (some) doubles */ + int arc = bd & BDA; + int multi_light = light & (light - 1); + int multi_double = double_ & (double_ - 1); + /* light crosses double only at DH+LV, DV+LH (ref. shapes) */ + int d = arc || (multi_double && !multi_light) ? -s : 0; + + if (bd & LL) + XftDrawRect(xd, fg, x, y + h2, w2 + s + d, s); + if (bd & LU) + XftDrawRect(xd, fg, x + w2, y, s, h2 + s + d); + if (bd & LR) + XftDrawRect(xd, fg, x + w2 - d, y + h2, w - w2 + d, s); + if (bd & LD) + XftDrawRect(xd, fg, x + w2, y + h2 - d, s, h - h2 + d); + } + + /* double lines - also align with light to form heavy when combined */ + if (double_) { + /* + * going clockwise, for each double-ray: p is additional length + * to the single-ray nearer to the previous direction, and n to + * the next. p and n adjust from the base length to lengths + * which consider other doubles - shorter to avoid intersections + * (p, n), or longer to draw the far-corner texel (n). + */ + int dl = bd & DL, du = bd & DU, dr = bd & DR, dd = bd & DD; + if (dl) { + int p = dd ? -s : 0, n = du ? -s : dd ? s : 0; + XftDrawRect(xd, fg, x, y + h2 + s, w2 + s + p, s); + XftDrawRect(xd, fg, x, y + h2 - s, w2 + s + n, s); + } + if (du) { + int p = dl ? -s : 0, n = dr ? -s : dl ? s : 0; + XftDrawRect(xd, fg, x + w2 - s, y, s, h2 + s + p); + XftDrawRect(xd, fg, x + w2 + s, y, s, h2 + s + n); + } + if (dr) { + int p = du ? -s : 0, n = dd ? -s : du ? s : 0; + XftDrawRect(xd, fg, x + w2 - p, y + h2 - s, w - w2 + p, s); + XftDrawRect(xd, fg, x + w2 - n, y + h2 + s, w - w2 + n, s); + } + if (dd) { + int p = dr ? -s : 0, n = dl ? -s : dr ? s : 0; + XftDrawRect(xd, fg, x + w2 + s, y + h2 - p, s, h - h2 + p); + XftDrawRect(xd, fg, x + w2 - s, y + h2 - n, s, h - h2 + n); + } + } +} @@ -0,0 +1,214 @@ +/* + * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih + * MIT/X Consortium License + */ + +/* + * U+25XX codepoints data + * + * References: + * http://www.unicode.org/charts/PDF/U2500.pdf + * http://www.unicode.org/charts/PDF/U2580.pdf + * + * Test page: + * https://github.com/GNOME/vte/blob/master/doc/boxes.txt + */ + +/* Each shape is encoded as 16-bits. Higher bits are category, lower are data */ +/* Categories (mutually exclusive except BDB): */ +/* For convenience, BDL/BDA/BBS/BDB are 1 bit each, the rest are enums */ +#define BDL (1<<8) /* Box Draw Lines (light/double/heavy) */ +#define BDA (1<<9) /* Box Draw Arc (light) */ + +#define BBD (1<<10) /* Box Block Down (lower) X/8 */ +#define BBL (2<<10) /* Box Block Left X/8 */ +#define BBU (3<<10) /* Box Block Upper X/8 */ +#define BBR (4<<10) /* Box Block Right X/8 */ +#define BBQ (5<<10) /* Box Block Quadrants */ +#define BRL (6<<10) /* Box Braille (data is lower byte of U28XX) */ + +#define BBS (1<<14) /* Box Block Shades */ +#define BDB (1<<15) /* Box Draw is Bold */ + +/* (BDL/BDA) Light/Double/Heavy x Left/Up/Right/Down/Horizontal/Vertical */ +/* Heavy is light+double (literally drawing light+double align to form heavy) */ +#define LL (1<<0) +#define LU (1<<1) +#define LR (1<<2) +#define LD (1<<3) +#define LH (LL+LR) +#define LV (LU+LD) + +#define DL (1<<4) +#define DU (1<<5) +#define DR (1<<6) +#define DD (1<<7) +#define DH (DL+DR) +#define DV (DU+DD) + +#define HL (LL+DL) +#define HU (LU+DU) +#define HR (LR+DR) +#define HD (LD+DD) +#define HH (HL+HR) +#define HV (HU+HD) + +/* (BBQ) Quadrants Top/Bottom x Left/Right */ +#define TL (1<<0) +#define TR (1<<1) +#define BL (1<<2) +#define BR (1<<3) + +/* Data for U+2500 - U+259F except dashes/diagonals */ +static const unsigned short boxdata[256] = { + /* light lines */ + [0x00] = BDL + LH, /* light horizontal */ + [0x02] = BDL + LV, /* light vertical */ + [0x0c] = BDL + LD + LR, /* light down and right */ + [0x10] = BDL + LD + LL, /* light down and left */ + [0x14] = BDL + LU + LR, /* light up and right */ + [0x18] = BDL + LU + LL, /* light up and left */ + [0x1c] = BDL + LV + LR, /* light vertical and right */ + [0x24] = BDL + LV + LL, /* light vertical and left */ + [0x2c] = BDL + LH + LD, /* light horizontal and down */ + [0x34] = BDL + LH + LU, /* light horizontal and up */ + [0x3c] = BDL + LV + LH, /* light vertical and horizontal */ + [0x74] = BDL + LL, /* light left */ + [0x75] = BDL + LU, /* light up */ + [0x76] = BDL + LR, /* light right */ + [0x77] = BDL + LD, /* light down */ + + /* heavy [+light] lines */ + [0x01] = BDL + HH, + [0x03] = BDL + HV, + [0x0d] = BDL + HR + LD, + [0x0e] = BDL + HD + LR, + [0x0f] = BDL + HD + HR, + [0x11] = BDL + HL + LD, + [0x12] = BDL + HD + LL, + [0x13] = BDL + HD + HL, + [0x15] = BDL + HR + LU, + [0x16] = BDL + HU + LR, + [0x17] = BDL + HU + HR, + [0x19] = BDL + HL + LU, + [0x1a] = BDL + HU + LL, + [0x1b] = BDL + HU + HL, + [0x1d] = BDL + HR + LV, + [0x1e] = BDL + HU + LD + LR, + [0x1f] = BDL + HD + LR + LU, + [0x20] = BDL + HV + LR, + [0x21] = BDL + HU + HR + LD, + [0x22] = BDL + HD + HR + LU, + [0x23] = BDL + HV + HR, + [0x25] = BDL + HL + LV, + [0x26] = BDL + HU + LD + LL, + [0x27] = BDL + HD + LU + LL, + [0x28] = BDL + HV + LL, + [0x29] = BDL + HU + HL + LD, + [0x2a] = BDL + HD + HL + LU, + [0x2b] = BDL + HV + HL, + [0x2d] = BDL + HL + LD + LR, + [0x2e] = BDL + HR + LL + LD, + [0x2f] = BDL + HH + LD, + [0x30] = BDL + HD + LH, + [0x31] = BDL + HD + HL + LR, + [0x32] = BDL + HR + HD + LL, + [0x33] = BDL + HH + HD, + [0x35] = BDL + HL + LU + LR, + [0x36] = BDL + HR + LU + LL, + [0x37] = BDL + HH + LU, + [0x38] = BDL + HU + LH, + [0x39] = BDL + HU + HL + LR, + [0x3a] = BDL + HU + HR + LL, + [0x3b] = BDL + HH + HU, + [0x3d] = BDL + HL + LV + LR, + [0x3e] = BDL + HR + LV + LL, + [0x3f] = BDL + HH + LV, + [0x40] = BDL + HU + LH + LD, + [0x41] = BDL + HD + LH + LU, + [0x42] = BDL + HV + LH, + [0x43] = BDL + HU + HL + LD + LR, + [0x44] = BDL + HU + HR + LD + LL, + [0x45] = BDL + HD + HL + LU + LR, + [0x46] = BDL + HD + HR + LU + LL, + [0x47] = BDL + HH + HU + LD, + [0x48] = BDL + HH + HD + LU, + [0x49] = BDL + HV + HL + LR, + [0x4a] = BDL + HV + HR + LL, + [0x4b] = BDL + HV + HH, + [0x78] = BDL + HL, + [0x79] = BDL + HU, + [0x7a] = BDL + HR, + [0x7b] = BDL + HD, + [0x7c] = BDL + HR + LL, + [0x7d] = BDL + HD + LU, + [0x7e] = BDL + HL + LR, + [0x7f] = BDL + HU + LD, + + /* double [+light] lines */ + [0x50] = BDL + DH, + [0x51] = BDL + DV, + [0x52] = BDL + DR + LD, + [0x53] = BDL + DD + LR, + [0x54] = BDL + DR + DD, + [0x55] = BDL + DL + LD, + [0x56] = BDL + DD + LL, + [0x57] = BDL + DL + DD, + [0x58] = BDL + DR + LU, + [0x59] = BDL + DU + LR, + [0x5a] = BDL + DU + DR, + [0x5b] = BDL + DL + LU, + [0x5c] = BDL + DU + LL, + [0x5d] = BDL + DL + DU, + [0x5e] = BDL + DR + LV, + [0x5f] = BDL + DV + LR, + [0x60] = BDL + DV + DR, + [0x61] = BDL + DL + LV, + [0x62] = BDL + DV + LL, + [0x63] = BDL + DV + DL, + [0x64] = BDL + DH + LD, + [0x65] = BDL + DD + LH, + [0x66] = BDL + DD + DH, + [0x67] = BDL + DH + LU, + [0x68] = BDL + DU + LH, + [0x69] = BDL + DH + DU, + [0x6a] = BDL + DH + LV, + [0x6b] = BDL + DV + LH, + [0x6c] = BDL + DH + DV, + + /* (light) arcs */ + [0x6d] = BDA + LD + LR, + [0x6e] = BDA + LD + LL, + [0x6f] = BDA + LU + LL, + [0x70] = BDA + LU + LR, + + /* Lower (Down) X/8 block (data is 8 - X) */ + [0x81] = BBD + 7, [0x82] = BBD + 6, [0x83] = BBD + 5, [0x84] = BBD + 4, + [0x85] = BBD + 3, [0x86] = BBD + 2, [0x87] = BBD + 1, [0x88] = BBD + 0, + + /* Left X/8 block (data is X) */ + [0x89] = BBL + 7, [0x8a] = BBL + 6, [0x8b] = BBL + 5, [0x8c] = BBL + 4, + [0x8d] = BBL + 3, [0x8e] = BBL + 2, [0x8f] = BBL + 1, + + /* upper 1/2 (4/8), 1/8 block (X), right 1/2, 1/8 block (8-X) */ + [0x80] = BBU + 4, [0x94] = BBU + 1, + [0x90] = BBR + 4, [0x95] = BBR + 7, + + /* Quadrants */ + [0x96] = BBQ + BL, + [0x97] = BBQ + BR, + [0x98] = BBQ + TL, + [0x99] = BBQ + TL + BL + BR, + [0x9a] = BBQ + TL + BR, + [0x9b] = BBQ + TL + TR + BL, + [0x9c] = BBQ + TL + TR + BR, + [0x9d] = BBQ + TR, + [0x9e] = BBQ + BL + TR, + [0x9f] = BBQ + BL + TR + BR, + + /* Shades, data is an alpha value in 25% units (1/4, 1/2, 3/4) */ + [0x91] = BBS + 1, [0x92] = BBS + 2, [0x93] = BBS + 3, + + /* U+2504 - U+250B, U+254C - U+254F: unsupported (dashes) */ + /* U+2571 - U+2573: unsupported (diagonals) */ +}; @@ -0,0 +1,489 @@ +/* See LICENSE file for copyright and license details. */ + +/* + * appearance + * + * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + */ +//static char *font = "JetBrainsMono Nerd Font Mono:pixelsize=26:antialias=true:autohint=true"; +//static char *font = "SauceCodePro Nerd Font Mono:pixelsize=26:antialias=true:autohint=true"; +static char *font = "Source Code Pro:pixelsize=26:antialias=true:autohint=true"; +static int borderpx = 1; + +/* + * What program is execed by st depends of these precedence rules: + * 1: program passed with -e + * 2: scroll and/or utmp + * 3: SHELL environment variable + * 4: value of shell in /etc/passwd + * 5: value of shell in config.h + */ +static char *shell = "/bin/sh"; +char *utmp = NULL; +/* scroll program: to enable use a string like "scroll" */ +char *scroll = NULL; +char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; + +/* identification sequence returned in DA and DECID */ +char *vtiden = "\033[?6c"; + +/* Kerning / character bounding-box multipliers */ +static float cwscale = 1.0; +static float chscale = 0.9; + +/* + * word delimiter string + * + * More advanced example: L" `'\"()[]{}" + */ +wchar_t *worddelimiters = L" "; + +/* selection timeouts (in milliseconds) */ +static unsigned int doubleclicktimeout = 300; +static unsigned int tripleclicktimeout = 600; + +/* alt screens */ +int allowaltscreen = 1; + +/* allow certain non-interactive (insecure) window operations such as: + setting the clipboard text */ +int allowwindowops = 0; + +/* + * draw latency range in ms - from new content/keypress/etc until drawing. + * within this range, st draws when content stops arriving (idle). mostly it's + * near minlatency, but it waits longer for slow updates to avoid partial draw. + * low minlatency will tear/flicker more, as it can "detect" idle too early. + */ +static double minlatency = 8; +static double maxlatency = 33; + +/* + * blinking timeout (set to 0 to disable blinking) for the terminal blinking + * attribute. + */ +static unsigned int blinktimeout = 800; + +/* + * thickness of underline and bar cursors + */ +static unsigned int cursorthickness = 2; + +/* + * 1: render most of the lines/blocks characters without using the font for + * perfect alignment between cells (U2500 - U259F except dashes/diagonals). + * Bold affects lines thickness if boxdraw_bold is not 0. Italic is ignored. + * 0: disable (render all U25XX glyphs normally from the font). + */ +const int boxdraw = 1; +const int boxdraw_bold = 1; + +/* braille (U28XX): 1: render as adjacent "pixels", 0: use font */ +const int boxdraw_braille = 1; + +/* bg opacity */ +float alpha = 0.65; +//float alpha = 0.5; //better visual if u r using a dark wallpaper + +/* + * bell volume. It must be a value between -100 and 100. Use 0 for disabling + * it + */ +static int bellvolume = 0; + +/* default TERM value */ +char *termname = "st-256color"; + +/* + * spaces per tab + * + * When you are changing this value, don't forget to adapt the »it« value in + * the st.info and appropriately install the st.info in the environment where + * you use this st version. + * + * it#$tabspaces, + * + * Secondly make sure your kernel is not expanding tabs. When running `stty + * -a` »tab0« should appear. You can tell the terminal to not expand tabs by + * running following command: + * + * stty tabs + */ +unsigned int tabspaces = 8; + +/* Terminal colors (16 first used in escape sequence) */ +static const char *colorname[] = { + /* 8 normal colors */ + [0] = "#000000", /* black */ + [1] = "#ff5555", /* red */ + [2] = "#50fa7b", /* green */ + [3] = "#f1fa8c", /* yellow */ + [4] = "#bd93f9", /* blue */ + [5] = "#ff79c6", /* magenta */ + [6] = "#8be9fd", /* cyan */ + [7] = "#bbbbbb", /* white */ + + /* 8 bright colors */ + [8] = "#696969", /* black */ + [9] = "#ff5555", /* red */ + [10] = "#50fa7b", /* green */ + [11] = "#f1fa8c", /* yellow */ + [12] = "#bd93f9", /* blue */ + [13] = "#ff79c6", /* magenta */ + [14] = "#8be9fd", /* cyan */ + [15] = "#dddddd", /* white */ + + /* special colors */ +//[256] = "#222D31", /* background */ + [256] = "#282a36", /* background */ + [257] = "#B5B5B5", /* foreground */ +}; + +/* + * Default colors (colorname index) + * foreground, background, cursor, reverse cursor + */ +unsigned int defaultfg = 257; +unsigned int defaultbg = 256; +static unsigned int defaultcs = 257; +static unsigned int defaultrcs = 257; + +/* + * Default shape of cursor + * 2: Block ("█") + * 4: Underline ("_") + * 6: Bar ("|") + * 7: Snowman ("☃") + */ +static unsigned int cursorshape = 2; + +/* + * Default columns and rows numbers + */ + +static unsigned int cols = 80; +static unsigned int rows = 24; + +/* + * Default colour and shape of the mouse cursor + */ +static unsigned int mouseshape = XC_xterm; +static unsigned int mousefg = 7; +static unsigned int mousebg = 0; + +/* + * Color used to display font attributes when fontconfig selected a font which + * doesn't match the ones requested. + */ +static unsigned int defaultattr = 11; + +/* + * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). + * Note that if you want to use ShiftMask with selmasks, set this to an other + * modifier, set to 0 to not use it. + */ +static uint forcemousemod = ShiftMask; + +/* Internal keyboard shortcuts. */ +#define MODKEY Mod1Mask +#define TERMMOD (ControlMask|ShiftMask) + +/* + * Internal mouse shortcuts. + * Beware that overloading Button1 will disable the selection. + */ +static MouseShortcut mshortcuts[] = { + /* mask button function argument release */ + { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, + { XK_NO_MOD, Button4, kscrollup, {.i = 1} }, + { XK_NO_MOD, Button5, kscrolldown, {.i = 1} }, + { ControlMask, Button4, kscrollup, {.i = -1} }, + { ControlMask, Button5, kscrolldown, {.i = -1} }, +}; + +static Shortcut shortcuts[] = { + /* mask keysym function argument */ + { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, + { ControlMask, XK_Print, toggleprinter, {.i = 0} }, + { ShiftMask, XK_Print, printscreen, {.i = 0} }, + { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, + { TERMMOD, XK_Prior, zoom, {.f = +1} }, + { TERMMOD, XK_Next, zoom, {.f = -1} }, + { TERMMOD, XK_Home, zoomreset, {.f = 0} }, + { TERMMOD, XK_C, clipcopy, {.i = 0} }, + { TERMMOD, XK_V, clippaste, {.i = 0} }, + { TERMMOD, XK_Y, selpaste, {.i = 0} }, + { ShiftMask, XK_Insert, selpaste, {.i = 0} }, + { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, + { TERMMOD, XK_S, keyboard_select,{.i = 0} }, +}; + +/* + * Special keys (change & recompile st.info accordingly) + * + * Mask value: + * * Use XK_ANY_MOD to match the key no matter modifiers state + * * Use XK_NO_MOD to match the key alone (no modifiers) + * appkey value: + * * 0: no value + * * > 0: keypad application mode enabled + * * = 2: term.numlock = 1 + * * < 0: keypad application mode disabled + * appcursor value: + * * 0: no value + * * > 0: cursor application mode enabled + * * < 0: cursor application mode disabled + * + * Be careful with the order of the definitions because st searches in + * this table sequentially, so any XK_ANY_MOD must be in the last + * position for a key. + */ + +/* + * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) + * to be mapped below, add them to this array. + */ +static KeySym mappedkeys[] = { -1 }; + +/* + * State bits to ignore when matching key or button events. By default, + * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. + */ +static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; + +/* + * This is the huge key array which defines all compatibility to the Linux + * world. Please decide about changes wisely. + */ +static Key key[] = { + /* keysym mask string appkey appcursor */ + { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, + { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, + { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, + { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, + { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, + { XK_KP_End, ControlMask, "\033[J", -1, 0}, + { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_KP_End, ShiftMask, "\033[K", -1, 0}, + { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, + { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, + { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, + { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, + { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, + { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, + { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, + { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, + { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, + { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, + { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, + { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, + { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, + { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, + { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, + { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, + { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, + { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, + { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, + { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, + { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, + { XK_Up, ControlMask, "\033[1;5A", 0, 0}, + { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, + { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, + { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, + { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, + { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, + { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, + { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, + { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, + { XK_Down, ControlMask, "\033[1;5B", 0, 0}, + { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, + { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, + { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, + { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, + { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, + { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, + { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, + { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, + { XK_Left, ControlMask, "\033[1;5D", 0, 0}, + { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, + { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, + { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, + { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, + { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, + { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, + { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, + { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, + { XK_Right, ControlMask, "\033[1;5C", 0, 0}, + { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, + { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, + { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, + { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, + { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, + { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, + { XK_Return, Mod1Mask, "\033\r", 0, 0}, + { XK_Return, XK_ANY_MOD, "\r", 0, 0}, + { XK_Insert, ShiftMask, "\033[4l", -1, 0}, + { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, + { XK_Insert, ControlMask, "\033[L", -1, 0}, + { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, + { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, + { XK_Delete, ControlMask, "\033[M", -1, 0}, + { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, + { XK_Delete, ShiftMask, "\033[2K", -1, 0}, + { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, + { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, + { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, + { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, + { XK_Home, ShiftMask, "\033[2J", 0, -1}, + { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, + { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, + { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, + { XK_End, ControlMask, "\033[J", -1, 0}, + { XK_End, ControlMask, "\033[1;5F", +1, 0}, + { XK_End, ShiftMask, "\033[K", -1, 0}, + { XK_End, ShiftMask, "\033[1;2F", +1, 0}, + { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, + { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, + { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, + { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, + { XK_Next, ControlMask, "\033[6;5~", 0, 0}, + { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, + { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, + { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, + { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, + { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, + { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, + { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, + { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, + { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, + { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, + { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, + { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, + { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, + { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, + { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, + { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, + { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, + { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, + { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, + { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, + { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, + { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, + { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, + { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, + { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, + { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, + { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, + { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, + { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, + { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, + { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, + { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, + { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, + { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, + { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, + { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, + { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, + { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, + { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, + { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, + { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, + { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, + { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, + { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, + { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, + { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, + { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, + { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, + { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, + { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, + { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, + { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, + { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, + { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, + { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, + { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, + { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, + { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, + { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, + { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, + { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, + { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, + { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, + { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, + { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, + { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, + { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, + { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, + { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, + { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, + { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, + { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, + { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, + { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, + { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, + { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, + { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, + { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, + { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, + { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, + { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, + { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, + { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, + { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, + { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, + { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, + { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, + { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, +}; + +/* + * Selection types' masks. + * Use the same masks as usual. + * Button1Mask is always unset, to make masks match between ButtonPress. + * ButtonRelease and MotionNotify. + * If no match is found, regular selection is used. + */ +static uint selmasks[] = { + [SEL_RECTANGULAR] = Mod1Mask, +}; + +/* + * Printable characters in ASCII, used to estimate the advance width + * of single wide characters. + */ +static char ascii_printable[] = + " !\"#$%&'()*+,-./0123456789:;<=>?" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" + "`abcdefghijklmnopqrstuvwxyz{|}~"; @@ -0,0 +1,37 @@ +# st version +VERSION = 0.8.4 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = $(PREFIX)/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +PKG_CONFIG = pkg-config + +# includes and libs +INCS = -I$(X11INC) \ + `$(PKG_CONFIG) --cflags fontconfig` \ + `$(PKG_CONFIG) --cflags freetype2` \ + `$(PKG_CONFIG) --cflags harfbuzz` +LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ + `$(PKG_CONFIG) --libs fontconfig` \ + `$(PKG_CONFIG) --libs freetype2` \ + `$(PKG_CONFIG) --libs harfbuzz` + +# flags +STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 +STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) +STLDFLAGS = $(LIBS) $(LDFLAGS) + +# OpenBSD: +#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE +#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ +# `$(PKG_CONFIG) --libs fontconfig` \ +# `$(PKG_CONFIG) --libs freetype2` + +# compiler and linker +# CC = c99 @@ -0,0 +1,140 @@ +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <X11/Xft/Xft.h> +#include <hb.h> +#include <hb-ft.h> + +#include "st.h" + +void hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoints, int start, int length); +hb_font_t *hbfindfont(XftFont *match); + +typedef struct { + XftFont *match; + hb_font_t *font; +} HbFontMatch; + +static int hbfontslen = 0; +static HbFontMatch *hbfontcache = NULL; + +void +hbunloadfonts() +{ + for (int i = 0; i < hbfontslen; i++) { + hb_font_destroy(hbfontcache[i].font); + XftUnlockFace(hbfontcache[i].match); + } + + if (hbfontcache != NULL) { + free(hbfontcache); + hbfontcache = NULL; + } + hbfontslen = 0; +} + +hb_font_t * +hbfindfont(XftFont *match) +{ + for (int i = 0; i < hbfontslen; i++) { + if (hbfontcache[i].match == match) + return hbfontcache[i].font; + } + + /* Font not found in cache, caching it now. */ + hbfontcache = realloc(hbfontcache, sizeof(HbFontMatch) * (hbfontslen + 1)); + FT_Face face = XftLockFace(match); + hb_font_t *font = hb_ft_font_create(face, NULL); + if (font == NULL) + die("Failed to load Harfbuzz font."); + + hbfontcache[hbfontslen].match = match; + hbfontcache[hbfontslen].font = font; + hbfontslen += 1; + + return font; +} + +void +hbtransform(XftGlyphFontSpec *specs, const Glyph *glyphs, size_t len, int x, int y) +{ + int start = 0, length = 1, gstart = 0; + hb_codepoint_t *codepoints = calloc(len, sizeof(hb_codepoint_t)); + + for (int idx = 1, specidx = 1; idx < len; idx++) { + if (glyphs[idx].mode & ATTR_WDUMMY) { + length += 1; + continue; + } + + if (specs[specidx].font != specs[start].font || ATTRCMP(glyphs[gstart], glyphs[idx]) || selected(x + idx, y) != selected(x + gstart, y)) { + hbtransformsegment(specs[start].font, glyphs, codepoints, gstart, length); + + /* Reset the sequence. */ + length = 1; + start = specidx; + gstart = idx; + } else { + length += 1; + } + + specidx++; + } + + /* EOL. */ + hbtransformsegment(specs[start].font, glyphs, codepoints, gstart, length); + + /* Apply the transformation to glyph specs. */ + for (int i = 0, specidx = 0; i < len; i++) { + if (glyphs[i].mode & ATTR_WDUMMY) + continue; + if (glyphs[i].mode & ATTR_BOXDRAW) { + specidx++; + continue; + } + + if (codepoints[i] != specs[specidx].glyph) + ((Glyph *)glyphs)[i].mode |= ATTR_LIGA; + + specs[specidx++].glyph = codepoints[i]; + } + + free(codepoints); +} + +void +hbtransformsegment(XftFont *xfont, const Glyph *string, hb_codepoint_t *codepoints, int start, int length) +{ + hb_font_t *font = hbfindfont(xfont); + if (font == NULL) + return; + + Rune rune; + ushort mode = USHRT_MAX; + hb_buffer_t *buffer = hb_buffer_create(); + hb_buffer_set_direction(buffer, HB_DIRECTION_LTR); + + /* Fill buffer with codepoints. */ + for (int i = start; i < (start+length); i++) { + rune = string[i].u; + mode = string[i].mode; + if (mode & ATTR_WDUMMY) + rune = 0x0020; + hb_buffer_add_codepoints(buffer, &rune, 1, 0, 1); + } + + /* Shape the segment. */ + hb_shape(font, buffer, NULL, 0); + + /* Get new glyph info. */ + hb_glyph_info_t *info = hb_buffer_get_glyph_infos(buffer, NULL); + + /* Write new codepoints. */ + for (int i = 0; i < length; i++) { + hb_codepoint_t gid = info[i].codepoint; + codepoints[start+i] = gid; + } + + /* Cleanup. */ + hb_buffer_destroy(buffer); +} @@ -0,0 +1,7 @@ +#include <X11/Xft/Xft.h> +#include <hb.h> +#include <hb-ft.h> + +void hbunloadfonts(); +void hbtransform(XftGlyphFontSpec *, const Glyph *, size_t, int, int); + @@ -0,0 +1,163 @@ +diff --git a/config.def.h b/config.def.h +index 0e01717..e116631 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -82,6 +82,9 @@ char *termname = "st-256color"; + */ + unsigned int tabspaces = 8; + ++/* bg opacity */ ++float alpha = 0.8; ++ + /* Terminal colors (16 first used in escape sequence) */ + static const char *colorname[] = { + /* 8 normal colors */ +@@ -109,6 +112,7 @@ static const char *colorname[] = { + /* more colors can be added after 255 to use with DefaultXX */ + "#cccccc", + "#555555", ++ "black", + }; + + +@@ -117,7 +121,7 @@ static const char *colorname[] = { + * foreground, background, cursor, reverse cursor + */ + unsigned int defaultfg = 7; +-unsigned int defaultbg = 0; ++unsigned int defaultbg = 258; + static unsigned int defaultcs = 256; + static unsigned int defaultrcs = 257; + +diff --git a/config.mk b/config.mk +index 0cbb002..1d2f0e2 100644 +--- a/config.mk ++++ b/config.mk +@@ -16,7 +16,7 @@ PKG_CONFIG = pkg-config + INCS = -I$(X11INC) \ + `$(PKG_CONFIG) --cflags fontconfig` \ + `$(PKG_CONFIG) --cflags freetype2` +-LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ ++LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lXrender\ + `$(PKG_CONFIG) --libs fontconfig` \ + `$(PKG_CONFIG) --libs freetype2` + +diff --git a/st.h b/st.h +index 38c61c4..b7634ab 100644 +--- a/st.h ++++ b/st.h +@@ -120,3 +120,4 @@ extern char *termname; + extern unsigned int tabspaces; + extern unsigned int defaultfg; + extern unsigned int defaultbg; ++extern float alpha; +diff --git a/x.c b/x.c +index 0422421..588dec3 100644 +--- a/x.c ++++ b/x.c +@@ -98,6 +98,7 @@ typedef struct { + XSetWindowAttributes attrs; + int scr; + int isfixed; /* is fixed geometry? */ ++ int depth; /* bit depth */ + int l, t; /* left and top offset */ + int gm; /* geometry mask */ + } XWindow; +@@ -229,6 +230,7 @@ static char *usedfont = NULL; + static double usedfontsize = 0; + static double defaultfontsize = 0; + ++static char *opt_alpha = NULL; + static char *opt_class = NULL; + static char **opt_cmd = NULL; + static char *opt_embed = NULL; +@@ -688,7 +690,7 @@ xresize(int col, int row) + + XFreePixmap(xw.dpy, xw.buf); + xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, +- DefaultDepth(xw.dpy, xw.scr)); ++ xw.depth); + XftDrawChange(xw.draw, xw.buf); + xclear(0, 0, win.w, win.h); + +@@ -748,6 +750,13 @@ xloadcols(void) + else + die("could not allocate color %d\n", i); + } ++ ++ /* set alpha value of bg color */ ++ if (opt_alpha) ++ alpha = strtof(opt_alpha, NULL); ++ dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); ++ dc.col[defaultbg].pixel &= 0x00FFFFFF; ++ dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; + loaded = 1; + } + +@@ -1004,11 +1013,23 @@ xinit(int cols, int rows) + Window parent; + pid_t thispid = getpid(); + XColor xmousefg, xmousebg; ++ XWindowAttributes attr; ++ XVisualInfo vis; + + if (!(xw.dpy = XOpenDisplay(NULL))) + die("can't open display\n"); + xw.scr = XDefaultScreen(xw.dpy); +- xw.vis = XDefaultVisual(xw.dpy, xw.scr); ++ ++ if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) { ++ parent = XRootWindow(xw.dpy, xw.scr); ++ xw.depth = 32; ++ } else { ++ XGetWindowAttributes(xw.dpy, parent, &attr); ++ xw.depth = attr.depth; ++ } ++ ++ XMatchVisualInfo(xw.dpy, xw.scr, xw.depth, TrueColor, &vis); ++ xw.vis = vis.visual; + + /* font */ + if (!FcInit()) +@@ -1018,7 +1039,7 @@ xinit(int cols, int rows) + xloadfonts(usedfont, 0); + + /* colors */ +- xw.cmap = XDefaultColormap(xw.dpy, xw.scr); ++ xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None); + xloadcols(); + + /* adjust fixed window geometry */ +@@ -1038,19 +1059,15 @@ xinit(int cols, int rows) + | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; + xw.attrs.colormap = xw.cmap; + +- if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) +- parent = XRootWindow(xw.dpy, xw.scr); + xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t, +- win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, ++ win.w, win.h, 0, xw.depth, InputOutput, + xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity + | CWEventMask | CWColormap, &xw.attrs); + + memset(&gcvalues, 0, sizeof(gcvalues)); + gcvalues.graphics_exposures = False; +- dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, +- &gcvalues); +- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, +- DefaultDepth(xw.dpy, xw.scr)); ++ xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, xw.depth); ++ dc.gc = XCreateGC(xw.dpy, xw.buf, GCGraphicsExposures, &gcvalues); + XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); + XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); + +@@ -1894,6 +1911,9 @@ main(int argc, char *argv[]) + case 'a': + allowaltscreen = 0; + break; ++ case 'A': ++ opt_alpha = EARGF(usage()); ++ break; + case 'c': + opt_class = EARGF(usage()); + break; @@ -0,0 +1,152 @@ +diff --git a/x.c b/x.c +index 00cb6b1..8f87c0f 100644 +--- a/x.c ++++ b/x.c +@@ -78,6 +78,7 @@ typedef XftGlyphFontSpec GlyphFontSpec; + typedef struct { + int tw, th; /* tty width and height */ + int w, h; /* window width and height */ ++ int hborderpx, vborderpx; + int ch; /* char height */ + int cw; /* char width */ + int mode; /* window state/mode flags */ +@@ -311,7 +312,7 @@ zoomreset(const Arg *arg) + int + evcol(XEvent *e) + { +- int x = e->xbutton.x - borderpx; ++ int x = e->xbutton.x - win.hborderpx; + LIMIT(x, 0, win.tw - 1); + return x / win.cw; + } +@@ -319,7 +320,7 @@ evcol(XEvent *e) + int + evrow(XEvent *e) + { +- int y = e->xbutton.y - borderpx; ++ int y = e->xbutton.y - win.vborderpx; + LIMIT(y, 0, win.th - 1); + return y / win.ch; + } +@@ -675,6 +676,9 @@ cresize(int width, int height) + col = MAX(1, col); + row = MAX(1, row); + ++ win.hborderpx = (win.w - col * win.cw) / 2; ++ win.vborderpx = (win.h - row * win.ch) / 2; ++ + tresize(col, row); + xresize(col, row); + ttyresize(win.tw, win.th); +@@ -793,8 +797,8 @@ xhints(void) + sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; + sizeh->height = win.h; + sizeh->width = win.w; +- sizeh->height_inc = win.ch; +- sizeh->width_inc = win.cw; ++ sizeh->height_inc = 1; ++ sizeh->width_inc = 1; + sizeh->base_height = 2 * borderpx; + sizeh->base_width = 2 * borderpx; + sizeh->min_height = win.ch + 2 * borderpx; +@@ -1022,8 +1026,8 @@ xinit(int cols, int rows) + xloadcols(); + + /* adjust fixed window geometry */ +- win.w = 2 * borderpx + cols * win.cw; +- win.h = 2 * borderpx + rows * win.ch; ++ win.w = 2 * win.hborderpx + cols * win.cw; ++ win.h = 2 * win.vborderpx + rows * win.ch; + if (xw.gm & XNegative) + xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; + if (xw.gm & YNegative) +@@ -1123,7 +1127,7 @@ xinit(int cols, int rows) + int + xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) + { +- float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; ++ float winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, xp, yp; + ushort mode, prevmode = USHRT_MAX; + Font *font = &dc.font; + int frcflags = FRC_NORMAL; +@@ -1259,7 +1263,7 @@ void + xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) + { + int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); +- int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, ++ int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, + width = charlen * win.cw; + Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; + XRenderColor colfg, colbg; +@@ -1349,17 +1353,17 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i + + /* Intelligent cleaning up of the borders. */ + if (x == 0) { +- xclear(0, (y == 0)? 0 : winy, borderpx, ++ xclear(0, (y == 0)? 0 : winy, win.vborderpx, + winy + win.ch + +- ((winy + win.ch >= borderpx + win.th)? win.h : 0)); ++ ((winy + win.ch >= win.vborderpx + win.th)? win.h : 0)); + } +- if (winx + width >= borderpx + win.tw) { ++ if (winx + width >= win.hborderpx + win.tw) { + xclear(winx + width, (y == 0)? 0 : winy, win.w, +- ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); ++ ((winy + win.ch >= win.vborderpx + 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, 0, winx + width, win.hborderpx); ++ if (winy + win.ch >= win.vborderpx + win.th) + xclear(winx, winy + win.ch, winx + width, win.h); + + /* Clean up the region we want to draw to. */ +@@ -1452,35 +1456,35 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) + case 3: /* Blinking Underline */ + case 4: /* Steady Underline */ + XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + (cy + 1) * win.ch - \ ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + (cy + 1) * win.ch - \ + cursorthickness, + win.cw, cursorthickness); + break; + case 5: /* Blinking bar */ + case 6: /* Steady bar */ + XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + cy * win.ch, ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + cy * win.ch, + cursorthickness, win.ch); + break; + } + } else { + XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + cy * win.ch, ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + cy * win.ch, + win.cw - 1, 1); + XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + cy * win.ch, ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, +- borderpx + (cx + 1) * win.cw - 1, +- borderpx + cy * win.ch, ++ win.hborderpx + (cx + 1) * win.cw - 1, ++ win.vborderpx + cy * win.ch, + 1, win.ch - 1); + XftDrawRect(xw.draw, &drawcol, +- borderpx + cx * win.cw, +- borderpx + (cy + 1) * win.ch - 1, ++ win.hborderpx + cx * win.cw, ++ win.vborderpx + (cy + 1) * win.ch - 1, + win.cw, 1); + } + } @@ -0,0 +1,600 @@ +From 3f3b80b9966c60086f4ed80ce4de0cbf03468d36 Mon Sep 17 00:00:00 2001 +From: "Avi Halachmi (:avih)" <avihpit@yahoo.com> +Date: Wed, 26 Dec 2018 14:51:45 +0200 +Subject: [PATCH] boxdraw_v2: custom render lines/blocks/braille for perfect + alignment + +It seems impossible to ensure that blocks and line drawing glyphs +align without visible gaps for all combinations of arbitrary font, +size and width/height scale factor. + +This commit adds options to render most of the lines/blocks and +braille codepoints without using the font such that they align +perfectly regardless of font, size or other configuration values. + +Supported codepoints are U+2500 - U+259F except dashes/diagonals, +and U28XX. + +The lines/blocks data is stored as 16-bit values at boxdraw_data.h + +boxdraw/braille are independent, disabled by default at config[.def].h +--- + Makefile | 3 +- + boxdraw.c | 194 ++++++++++++++++++++++++++++++++++++++++++++ + boxdraw_data.h | 214 +++++++++++++++++++++++++++++++++++++++++++++++++ + config.def.h | 12 +++ + st.c | 3 + + st.h | 10 +++ + x.c | 21 +++-- + 7 files changed, 451 insertions(+), 6 deletions(-) + create mode 100644 boxdraw.c + create mode 100644 boxdraw_data.h + +diff --git a/Makefile b/Makefile +index 470ac86..6dfa212 100644 +--- a/Makefile ++++ b/Makefile +@@ -4,7 +4,7 @@ + + include config.mk + +-SRC = st.c x.c ++SRC = st.c x.c boxdraw.c + OBJ = $(SRC:.c=.o) + + all: options st +@@ -23,6 +23,7 @@ config.h: + + st.o: config.h st.h win.h + x.o: arg.h config.h st.h win.h ++boxdraw.o: config.h st.h boxdraw_data.h + + $(OBJ): config.h config.mk + +diff --git a/boxdraw.c b/boxdraw.c +new file mode 100644 +index 0000000..28a92d0 +--- /dev/null ++++ b/boxdraw.c +@@ -0,0 +1,194 @@ ++/* ++ * Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih ++ * MIT/X Consortium License ++ */ ++ ++#include <X11/Xft/Xft.h> ++#include "st.h" ++#include "boxdraw_data.h" ++ ++/* Rounded non-negative integers division of n / d */ ++#define DIV(n, d) (((n) + (d) / 2) / (d)) ++ ++static Display *xdpy; ++static Colormap xcmap; ++static XftDraw *xd; ++static Visual *xvis; ++ ++static void drawbox(int, int, int, int, XftColor *, XftColor *, ushort); ++static void drawboxlines(int, int, int, int, XftColor *, ushort); ++ ++/* public API */ ++ ++void ++boxdraw_xinit(Display *dpy, Colormap cmap, XftDraw *draw, Visual *vis) ++{ ++ xdpy = dpy; xcmap = cmap; xd = draw, xvis = vis; ++} ++ ++int ++isboxdraw(Rune u) ++{ ++ Rune block = u & ~0xff; ++ return (boxdraw && block == 0x2500 && boxdata[(uint8_t)u]) || ++ (boxdraw_braille && block == 0x2800); ++} ++ ++/* the "index" is actually the entire shape data encoded as ushort */ ++ushort ++boxdrawindex(const Glyph *g) ++{ ++ if (boxdraw_braille && (g->u & ~0xff) == 0x2800) ++ return BRL | (uint8_t)g->u; ++ if (boxdraw_bold && (g->mode & ATTR_BOLD)) ++ return BDB | boxdata[(uint8_t)g->u]; ++ return boxdata[(uint8_t)g->u]; ++} ++ ++void ++drawboxes(int x, int y, int cw, int ch, XftColor *fg, XftColor *bg, ++ const XftGlyphFontSpec *specs, int len) ++{ ++ for ( ; len-- > 0; x += cw, specs++) ++ drawbox(x, y, cw, ch, fg, bg, (ushort)specs->glyph); ++} ++ ++/* implementation */ ++ ++void ++drawbox(int x, int y, int w, int h, XftColor *fg, XftColor *bg, ushort bd) ++{ ++ ushort cat = bd & ~(BDB | 0xff); /* mask out bold and data */ ++ if (bd & (BDL | BDA)) { ++ /* lines (light/double/heavy/arcs) */ ++ drawboxlines(x, y, w, h, fg, bd); ++ ++ } else if (cat == BBD) { ++ /* lower (8-X)/8 block */ ++ int d = DIV((uint8_t)bd * h, 8); ++ XftDrawRect(xd, fg, x, y + d, w, h - d); ++ ++ } else if (cat == BBU) { ++ /* upper X/8 block */ ++ XftDrawRect(xd, fg, x, y, w, DIV((uint8_t)bd * h, 8)); ++ ++ } else if (cat == BBL) { ++ /* left X/8 block */ ++ XftDrawRect(xd, fg, x, y, DIV((uint8_t)bd * w, 8), h); ++ ++ } else if (cat == BBR) { ++ /* right (8-X)/8 block */ ++ int d = DIV((uint8_t)bd * w, 8); ++ XftDrawRect(xd, fg, x + d, y, w - d, h); ++ ++ } else if (cat == BBQ) { ++ /* Quadrants */ ++ int w2 = DIV(w, 2), h2 = DIV(h, 2); ++ if (bd & TL) ++ XftDrawRect(xd, fg, x, y, w2, h2); ++ if (bd & TR) ++ XftDrawRect(xd, fg, x + w2, y, w - w2, h2); ++ if (bd & BL) ++ XftDrawRect(xd, fg, x, y + h2, w2, h - h2); ++ if (bd & BR) ++ XftDrawRect(xd, fg, x + w2, y + h2, w - w2, h - h2); ++ ++ } else if (bd & BBS) { ++ /* Shades - data is 1/2/3 for 25%/50%/75% alpha, respectively */ ++ int d = (uint8_t)bd; ++ XftColor xfc; ++ XRenderColor xrc = { .alpha = 0xffff }; ++ ++ xrc.red = DIV(fg->color.red * d + bg->color.red * (4 - d), 4); ++ xrc.green = DIV(fg->color.green * d + bg->color.green * (4 - d), 4); ++ xrc.blue = DIV(fg->color.blue * d + bg->color.blue * (4 - d), 4); ++ ++ XftColorAllocValue(xdpy, xvis, xcmap, &xrc, &xfc); ++ XftDrawRect(xd, &xfc, x, y, w, h); ++ XftColorFree(xdpy, xvis, xcmap, &xfc); ++ ++ } else if (cat == BRL) { ++ /* braille, each data bit corresponds to one dot at 2x4 grid */ ++ int w1 = DIV(w, 2); ++ int h1 = DIV(h, 4), h2 = DIV(h, 2), h3 = DIV(3 * h, 4); ++ ++ if (bd & 1) XftDrawRect(xd, fg, x, y, w1, h1); ++ if (bd & 2) XftDrawRect(xd, fg, x, y + h1, w1, h2 - h1); ++ if (bd & 4) XftDrawRect(xd, fg, x, y + h2, w1, h3 - h2); ++ if (bd & 8) XftDrawRect(xd, fg, x + w1, y, w - w1, h1); ++ if (bd & 16) XftDrawRect(xd, fg, x + w1, y + h1, w - w1, h2 - h1); ++ if (bd & 32) XftDrawRect(xd, fg, x + w1, y + h2, w - w1, h3 - h2); ++ if (bd & 64) XftDrawRect(xd, fg, x, y + h3, w1, h - h3); ++ if (bd & 128) XftDrawRect(xd, fg, x + w1, y + h3, w - w1, h - h3); ++ ++ } ++} ++ ++void ++drawboxlines(int x, int y, int w, int h, XftColor *fg, ushort bd) ++{ ++ /* s: stem thickness. width/8 roughly matches unders …… diff 过长已截断 …… |