diff options
| author | LM-LCL <hello@exaltedelite.club> | 2024-08-31 21:28:41 +0200 |
|---|---|---|
| committer | LM-LCL <hello@exaltedelite.club> | 2024-08-31 21:28:41 +0200 |
| commit | 6eece88391d6dc3bfe54176249991cdc6cb8dd46 (patch) | |
| tree | 078be96373ebc098b838e16f912679327a09cb13 | |
| parent | ab3144f7dd3ee40d99328b51f8bc1d2f8ddc548e (diff) | |
st-0.9.2
| -rw-r--r-- | Makefile | 10 | ||||
| -rw-r--r-- | config.def.h | 4 | ||||
| -rw-r--r-- | config.h | 23 | ||||
| -rw-r--r-- | config.mk | 2 | ||||
| -rw-r--r-- | patches/st-externalpipe-0.8.5.diff (renamed from patches/st-externalpipe-0.8.4.diff) | 20 | ||||
| -rw-r--r-- | patches/st-scrollback-0.9.2.diff (renamed from patches/st-scrollback-0.8.5.diff) | 55 | ||||
| -rw-r--r-- | st.c | 43 | ||||
| -rw-r--r-- | st.info | 4 | ||||
| -rw-r--r-- | x.c | 19 |
9 files changed, 113 insertions, 67 deletions
@@ -7,13 +7,7 @@ include config.mk SRC = st.c x.c boxdraw.c OBJ = $(SRC:.c=.o) -all: options st - -options: - @echo st build options: - @echo "CFLAGS = $(STCFLAGS)" - @echo "LDFLAGS = $(STLDFLAGS)" - @echo "CC = $(CC)" +all: st config.h: cp config.def.h config.h @@ -55,4 +49,4 @@ uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/st rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 -.PHONY: all options clean dist install uninstall +.PHONY: all clean dist install uninstall diff --git a/config.def.h b/config.def.h index a94fb88..26a1779 100644 --- a/config.def.h +++ b/config.def.h @@ -59,7 +59,7 @@ int allowwindowops = 0; * 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 minlatency = 2; static double maxlatency = 33; /* @@ -220,7 +220,7 @@ static Shortcut shortcuts[] = { { ShiftMask, XK_Insert, selpaste, {.i = 0} }, { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, - { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, }; /* @@ -5,8 +5,14 @@ * * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = "Liberation Mono:pixelsize=14:antialias=true:autohint=true"; -static char *font2[] = { "Noto Color Emoji:pixelsize=10:antialias=true:autohint=true" }; +static char *font = "Liberation Mono:pixelsize=16:antialias=true:autohint=true"; +/* Spare fonts */ +static char *font2[] = { +/* "Inconsolata for Powerline:pixelsize=12:antialias=true:autohint=true", */ +/* "Hack Nerd Font Mono:pixelsize=11:antialias=true:autohint=true", */ + "Noto Color Emoji:pixelsize=12:antialias=true:autohint=true" +}; + static int borderpx = 2; /* @@ -54,7 +60,7 @@ int allowwindowops = 0; * 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 minlatency = 2; static double maxlatency = 33; /* @@ -189,11 +195,11 @@ static uint forcemousemod = ShiftMask; */ static MouseShortcut mshortcuts[] = { /* mask button function argument release */ - { XK_NO_MOD, Button4, kscrollup, {.i = 2} }, - { XK_NO_MOD, Button5, kscrolldown, {.i = 2} }, + { XK_NO_MOD, Button4, kscrollup, {.i = 2} }, + { XK_NO_MOD, Button5, kscrolldown, {.i = 2} }, { ControlMask, Button4, zoom, {.f = +1} }, { ControlMask, Button5, zoom, {.f = -1} }, - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, + { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, @@ -209,6 +215,7 @@ static char *copyoutput[] = { "/bin/sh", "-c", "st-copyout", "externalpipe", NUL static Shortcut shortcuts[] = { /* mask keysym function argument */ + { ShiftMask, XK_Insert, selpaste, {.i = 0} }, { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, { TERMMOD, XK_C, clipcopy, {.i = 0} }, @@ -224,8 +231,8 @@ static Shortcut shortcuts[] = { { TERMMOD, XK_Left, zoom, {.f = -1} }, { TERMMOD, XK_L, zoom, {.f = +1} }, { TERMMOD, XK_H, zoom, {.f = -1} }, - { MODKEY, XK_o, externalpipe, {.v = copyoutput } }, - { MODKEY, XK_p, externalpipe, {.v = copyurlcmd } }, + { MODKEY, XK_o, externalpipe, {.v = copyoutput} }, + { MODKEY, XK_p, externalpipe, {.v = copyurlcmd} }, }; /* @@ -1,5 +1,5 @@ # st version -VERSION = 0.9 +VERSION = 0.9.2 # Customize below to fit your system diff --git a/patches/st-externalpipe-0.8.4.diff b/patches/st-externalpipe-0.8.5.diff index 297d746..daf91d3 100644 --- a/patches/st-externalpipe-0.8.4.diff +++ b/patches/st-externalpipe-0.8.5.diff @@ -1,8 +1,8 @@ diff --git a/st.c b/st.c -index 76b7e0d..0e9a614 100644 +index 034954d..98f2589 100644 --- a/st.c +++ b/st.c -@@ -723,8 +723,14 @@ sigchld(int a) +@@ -718,8 +718,14 @@ sigchld(int a) if ((p = waitpid(pid, &stat, WNOHANG)) < 0) die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); @@ -18,7 +18,16 @@ index 76b7e0d..0e9a614 100644 if (WIFEXITED(stat) && WEXITSTATUS(stat)) die("child exited with status %d\n", WEXITSTATUS(stat)); -@@ -1926,6 +1932,59 @@ strparse(void) +@@ -803,7 +809,7 @@ ttynew(const char *line, char *cmd, const char *out, char **args) + break; + default: + #ifdef __OpenBSD__ +- if (pledge("stdio rpath tty proc", NULL) == -1) ++ if (pledge("stdio rpath tty proc exec", NULL) == -1) + die("pledge\n"); + #endif + close(s); +@@ -1991,6 +1997,59 @@ strparse(void) } } @@ -79,7 +88,7 @@ index 76b7e0d..0e9a614 100644 strdump(void) { diff --git a/st.h b/st.h -index 3d351b6..392b64e 100644 +index fd3b0d8..754cd08 100644 --- a/st.h +++ b/st.h @@ -81,6 +81,7 @@ void die(const char *, ...); @@ -90,3 +99,6 @@ index 3d351b6..392b64e 100644 void printscreen(const Arg *); void printsel(const Arg *); void sendbreak(const Arg *); +-- +2.42.0 + diff --git a/patches/st-scrollback-0.8.5.diff b/patches/st-scrollback-0.9.2.diff index 750111d..f9782e8 100644 --- a/patches/st-scrollback-0.8.5.diff +++ b/patches/st-scrollback-0.9.2.diff @@ -1,5 +1,5 @@ diff --git a/config.def.h b/config.def.h -index 91ab8ca..e3b469b 100644 +index 2cd740a..40b7d93 100644 --- a/config.def.h +++ b/config.def.h @@ -201,6 +201,8 @@ static Shortcut shortcuts[] = { @@ -7,12 +7,12 @@ index 91ab8ca..e3b469b 100644 { ShiftMask, XK_Insert, selpaste, {.i = 0} }, { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, + { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, -+ { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, ++ { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, }; /* diff --git a/st.c b/st.c -index 51049ba..cd750f2 100644 +index b9f66e7..2478942 100644 --- a/st.c +++ b/st.c @@ -35,6 +35,7 @@ @@ -28,8 +28,8 @@ index 51049ba..cd750f2 100644 #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) #define ISDELIM(u) (u && wcschr(worddelimiters, u)) +#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ -+ term.scr + HISTSIZE + 1) % HISTSIZE] : \ -+ term.line[(y) - term.scr]) ++ term.scr + HISTSIZE + 1) % HISTSIZE] : \ ++ term.line[(y) - term.scr]) enum term_mode { MODE_WRAP = 1 << 0, @@ -43,7 +43,7 @@ index 51049ba..cd750f2 100644 int *dirty; /* dirtyness of lines */ TCursor c; /* cursor */ int ocx; /* old cursor col */ -@@ -184,8 +191,8 @@ static void tnewline(int); +@@ -185,8 +192,8 @@ static void tnewline(int); static void tputtab(int); static void tputc(Rune); static void treset(void); @@ -54,7 +54,7 @@ index 51049ba..cd750f2 100644 static void tsetattr(const int *, int); static void tsetchar(Rune, const Glyph *, int, int); static void tsetdirt(int, int); -@@ -416,10 +423,10 @@ tlinelen(int y) +@@ -409,10 +416,10 @@ tlinelen(int y) { int i = term.col; @@ -67,7 +67,7 @@ index 51049ba..cd750f2 100644 --i; return i; -@@ -528,7 +535,7 @@ selsnap(int *x, int *y, int direction) +@@ -521,7 +528,7 @@ selsnap(int *x, int *y, int direction) * Snap around if the word wraps around at the end or * beginning of a line. */ @@ -76,7 +76,7 @@ index 51049ba..cd750f2 100644 prevdelim = ISDELIM(prevgp->u); for (;;) { newx = *x + direction; -@@ -543,14 +550,14 @@ selsnap(int *x, int *y, int direction) +@@ -536,14 +543,14 @@ selsnap(int *x, int *y, int direction) yt = *y, xt = *x; else yt = newy, xt = newx; @@ -93,7 +93,7 @@ index 51049ba..cd750f2 100644 delim = ISDELIM(gp->u); if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim || (delim && gp->u != prevgp->u))) -@@ -571,14 +578,14 @@ selsnap(int *x, int *y, int direction) +@@ -564,14 +571,14 @@ selsnap(int *x, int *y, int direction) *x = (direction < 0) ? 0 : term.col - 1; if (direction < 0) { for (; *y > 0; *y += direction) { @@ -110,7 +110,7 @@ index 51049ba..cd750f2 100644 & ATTR_WRAP)) { break; } -@@ -609,13 +616,13 @@ getsel(void) +@@ -602,13 +609,13 @@ getsel(void) } if (sel.type == SEL_RECTANGULAR) { @@ -127,7 +127,7 @@ index 51049ba..cd750f2 100644 while (last >= gp && last->u == ' ') --last; -@@ -851,6 +858,9 @@ void +@@ -844,6 +851,9 @@ void ttywrite(const char *s, size_t n, int may_echo) { const char *next; @@ -137,7 +137,7 @@ index 51049ba..cd750f2 100644 if (may_echo && IS_SET(MODE_ECHO)) twrite(s, n, 1); -@@ -1062,12 +1072,52 @@ tswapscreen(void) +@@ -1055,13 +1065,53 @@ tswapscreen(void) } void @@ -181,6 +181,7 @@ index 51049ba..cd750f2 100644 Line temp; LIMIT(n, 0, term.bot-orig+1); + + if (copyhist) { + term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; + temp = term.hist[term.histi]; @@ -188,10 +189,10 @@ index 51049ba..cd750f2 100644 + term.line[term.bot] = temp; + } + - tsetdirt(orig, term.bot-n); tclearregion(0, term.bot-n+1, term.col-1, term.bot); -@@ -1078,17 +1128,28 @@ tscrolldown(int orig, int n) + +@@ -1071,17 +1121,28 @@ tscrolldown(int orig, int n) term.line[i-n] = temp; } @@ -222,7 +223,7 @@ index 51049ba..cd750f2 100644 tclearregion(0, orig, term.col-1, orig+n-1); tsetdirt(orig+n, term.bot); -@@ -1098,7 +1159,8 @@ tscrollup(int orig, int n) +@@ -1091,7 +1152,8 @@ tscrollup(int orig, int n) term.line[i+n] = temp; } @@ -232,7 +233,7 @@ index 51049ba..cd750f2 100644 } void -@@ -1127,7 +1189,7 @@ tnewline(int first_col) +@@ -1120,7 +1182,7 @@ tnewline(int first_col) int y = term.c.y; if (y == term.bot) { @@ -241,7 +242,7 @@ index 51049ba..cd750f2 100644 } else { y++; } -@@ -1292,14 +1354,14 @@ void +@@ -1285,14 +1347,14 @@ void tinsertblankline(int n) { if (BETWEEN(term.c.y, term.top, term.bot)) @@ -258,9 +259,9 @@ index 51049ba..cd750f2 100644 } int32_t -@@ -1736,11 +1798,11 @@ csihandle(void) - break; +@@ -1730,11 +1792,11 @@ csihandle(void) case 'S': /* SU -- Scroll <n> line up */ + if (csiescseq.priv) break; DEFAULT(csiescseq.arg[0], 1); - tscrollup(term.top, csiescseq.arg[0]); + tscrollup(term.top, csiescseq.arg[0], 0); @@ -272,7 +273,7 @@ index 51049ba..cd750f2 100644 break; case 'L': /* IL -- Insert <n> blank lines */ DEFAULT(csiescseq.arg[0], 1); -@@ -2330,7 +2392,7 @@ eschandle(uchar ascii) +@@ -2306,7 +2368,7 @@ eschandle(uchar ascii) return 0; case 'D': /* IND -- Linefeed */ if (term.c.y == term.bot) { @@ -281,7 +282,7 @@ index 51049ba..cd750f2 100644 } else { tmoveto(term.c.x, term.c.y+1); } -@@ -2343,7 +2405,7 @@ eschandle(uchar ascii) +@@ -2319,7 +2381,7 @@ eschandle(uchar ascii) break; case 'M': /* RI -- Reverse index */ if (term.c.y == term.top) { @@ -290,7 +291,7 @@ index 51049ba..cd750f2 100644 } else { tmoveto(term.c.x, term.c.y-1); } -@@ -2557,7 +2619,7 @@ twrite(const char *buf, int buflen, int show_ctrl) +@@ -2542,7 +2604,7 @@ twrite(const char *buf, int buflen, int show_ctrl) void tresize(int col, int row) { @@ -299,7 +300,7 @@ index 51049ba..cd750f2 100644 int minrow = MIN(row, term.row); int mincol = MIN(col, term.col); int *bp; -@@ -2594,6 +2656,14 @@ tresize(int col, int row) +@@ -2579,6 +2641,14 @@ tresize(int col, int row) term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); @@ -314,7 +315,7 @@ index 51049ba..cd750f2 100644 /* resize each row to new width, zero-pad if needed */ for (i = 0; i < minrow; i++) { term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); -@@ -2652,7 +2722,7 @@ drawregion(int x1, int y1, int x2, int y2) +@@ -2637,7 +2707,7 @@ drawregion(int x1, int y1, int x2, int y2) continue; term.dirty[y] = 0; @@ -323,7 +324,7 @@ index 51049ba..cd750f2 100644 } } -@@ -2673,8 +2743,9 @@ draw(void) +@@ -2658,8 +2728,9 @@ draw(void) cx--; drawregion(0, 0, term.col, term.row); @@ -336,7 +337,7 @@ index 51049ba..cd750f2 100644 term.ocy = term.c.y; xfinishdraw(); diff --git a/st.h b/st.h -index 519b9bd..da36b34 100644 +index fd3b0d8..818a6f8 100644 --- a/st.h +++ b/st.h @@ -81,6 +81,8 @@ void die(const char *, ...); @@ -44,8 +44,8 @@ #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) #define ISDELIM(u) (u && wcschr(worddelimiters, u)) #define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - \ - term.scr + HISTSIZE + 1) % HISTSIZE] : \ - term.line[(y) - term.scr]) + term.scr + HISTSIZE + 1) % HISTSIZE] : \ + term.line[(y) - term.scr]) #define TLINE_HIST(y) ((y) <= HISTSIZE-term.row+2 ? term.hist[(y)] : term.line[(y-HISTSIZE+term.row-3)]) enum term_mode { @@ -831,7 +831,7 @@ ttynew(const char *line, char *cmd, const char *out, char **args) break; default: #ifdef __OpenBSD__ - if (pledge("stdio rpath tty proc", NULL) == -1) + if (pledge("stdio rpath tty proc exec", NULL) == -1) die("pledge\n"); #endif close(s); @@ -1125,6 +1125,7 @@ tscrolldown(int orig, int n, int copyhist) Line temp; LIMIT(n, 0, term.bot-orig+1); + if (copyhist) { term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; temp = term.hist[term.histi]; @@ -1132,7 +1133,6 @@ tscrolldown(int orig, int n, int copyhist) term.line[term.bot] = temp; } - tsetdirt(orig, term.bot-n); tclearregion(0, term.bot-n+1, term.col-1, term.bot); @@ -1180,7 +1180,7 @@ tscrollup(int orig, int n, int copyhist) void selscroll(int orig, int n) { - if (sel.ob.x == -1) + if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) return; if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig, term.bot)) { @@ -1729,7 +1729,7 @@ csihandle(void) ttywrite(vtiden, strlen(vtiden), 0); break; case 'b': /* REP -- if last char is printable print it <n> more times */ - DEFAULT(csiescseq.arg[0], 1); + LIMIT(csiescseq.arg[0], 1, 65535); if (term.lastc) while (csiescseq.arg[0]-- > 0) tputc(term.lastc); @@ -1814,6 +1814,7 @@ csihandle(void) } break; case 'S': /* SU -- Scroll <n> line up */ + if (csiescseq.priv) break; DEFAULT(csiescseq.arg[0], 1); tscrollup(term.top, csiescseq.arg[0], 0); break; @@ -1855,11 +1856,18 @@ csihandle(void) case 'm': /* SGR -- Terminal attribute (color) */ tsetattr(csiescseq.arg, csiescseq.narg); break; - case 'n': /* DSR – Device Status Report (cursor position) */ - if (csiescseq.arg[0] == 6) { + case 'n': /* DSR -- Device Status Report */ + switch (csiescseq.arg[0]) { + case 5: /* Status Report "OK" `0n` */ + ttywrite("\033[0n", sizeof("\033[0n") - 1, 0); + break; + case 6: /* Report Cursor Position (CPR) "<row>;<column>R" */ len = snprintf(buf, sizeof(buf), "\033[%i;%iR", - term.c.y+1, term.c.x+1); + term.c.y+1, term.c.x+1); ttywrite(buf, len, 0); + break; + default: + goto unknown; } break; case 'r': /* DECSTBM -- Set Scrolling Region */ @@ -2018,8 +2026,10 @@ strhandle(void) if (p && !strcmp(p, "?")) { osc_color_response(j, 0, 1); } else if (xsetcolorname(j, p)) { - if (par == 104 && narg <= 1) + if (par == 104 && narg <= 1) { + xloadcols(); return; /* color reset without parameter */ + } fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", j, p ? p : "(null)"); } else { @@ -2462,6 +2472,7 @@ eschandle(uchar ascii) treset(); resettitle(); xloadcols(); + xsetmode(0, MODE_HIDE); break; case '=': /* DECPAM -- Application keypad */ xsetmode(1, MODE_APPKEYPAD); @@ -2554,6 +2565,9 @@ check_control_code: * they must not cause conflicts with sequences. */ if (control) { + /* in UTF-8 mode ignore handling C1 control characters */ + if (IS_SET(MODE_UTF8) && ISCONTROLC1(u)) + return; tcontrolcode(u); /* * control codes are not shown ever @@ -2600,11 +2614,16 @@ check_control_code: gp = &term.line[term.c.y][term.c.x]; } - if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) + if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) { memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); + gp->mode &= ~ATTR_WIDE; + } if (term.c.x+width > term.col) { - tnewline(1); + if (IS_SET(MODE_WRAP)) + tnewline(1); + else + tmoveto(term.col - width, term.c.y); gp = &term.line[term.c.y][term.c.x]; } @@ -184,6 +184,10 @@ st-mono| simpleterm monocolor, # XTerm extensions rmxx=\E[29m, smxx=\E[9m, + BE=\E[?2004h, + BD=\E[?2004l, + PS=\E[200~, + PE=\E[201~, # disabled rep for now: causes some issues with older ncurses versions. # rep=%p1%c\E[%p2%{1}%-%db, # tmux extensions, see TERMINFO EXTENSIONS in tmux(1) @@ -821,7 +821,7 @@ xloadcols(void) int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) { - if (!BETWEEN(x, 0, dc.collen)) + if (!BETWEEN(x, 0, dc.collen - 1)) return 1; *r = dc.col[x].color.red >> 8; @@ -836,7 +836,7 @@ xsetcolorname(int x, const char *name) { Color ncolor; - if (!BETWEEN(x, 0, dc.collen)) + if (!BETWEEN(x, 0, dc.collen - 1)) return 1; if (!xloadcolor(x, name, &ncolor)) @@ -1729,6 +1729,9 @@ xseticontitle(char *p) XTextProperty prop; DEFAULT(p, opt_title); + if (p[0] == '\0') + p = opt_title; + if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, &prop) != Success) return; @@ -1743,6 +1746,9 @@ xsettitle(char *p) XTextProperty prop; DEFAULT(p, opt_title); + if (p[0] == '\0') + p = opt_title; + if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, &prop) != Success) return; @@ -1945,7 +1951,7 @@ void kpress(XEvent *ev) { XKeyEvent *e = &ev->xkey; - KeySym ksym; + KeySym ksym = NoSymbol; char buf[64], *customkey; int len; Rune c; @@ -1955,10 +1961,13 @@ kpress(XEvent *ev) if (IS_SET(MODE_KBDLOCK)) return; - if (xw.ime.xic) + if (xw.ime.xic) { len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); - else + if (status == XBufferOverflow) + return; + } else { len = XLookupString(e, buf, sizeof buf, &ksym, NULL); + } /* 1. shortcuts */ for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { if (ksym == bp->keysym && match(bp->mod, e->state)) { |
