From 28b4c822c5c0acec300fdf15c6e3ede9f5e2335d Mon Sep 17 00:00:00 2001 From: John Collis Date: Sun, 6 Sep 2020 17:53:41 +1200 Subject: [PATCH 01/18] ST: Add WM_ICON_NAME property support Also added _NET_WM_ICON_NAME. --- st.c | 9 +++++++++ win.h | 1 + x.c | 16 +++++++++++++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/st.c b/st.c index 76b7e0d..ae7fa63 100644 --- a/st.c +++ b/st.c @@ -1844,6 +1844,7 @@ strhandle(void) { char *p = NULL, *dec; int j, narg, par; + static int winname = 0; term.esc &= ~(ESC_STR_END|ESC_STR); strparse(); @@ -1853,7 +1854,15 @@ strhandle(void) case ']': /* OSC -- Operating System Command */ switch (par) { case 0: + if (narg > 1) { + xsettitle(strescseq.args[1]); + xseticontitle(strescseq.args[1]); + } + return; case 1: + if (narg > 1) + xseticontitle(strescseq.args[1]); + return; case 2: if (narg > 1) xsettitle(strescseq.args[1]); diff --git a/win.h b/win.h index a6ef1b9..e6e4369 100644 --- a/win.h +++ b/win.h @@ -30,6 +30,7 @@ void xdrawline(Line, int, int, int); void xfinishdraw(void); void xloadcols(void); int xsetcolorname(int, const char *); +void xseticontitle(char *); void xsettitle(char *); int xsetcursor(int); void xsetmode(int, unsigned int); diff --git a/x.c b/x.c index 210f184..120e495 100644 --- a/x.c +++ b/x.c @@ -93,7 +93,7 @@ typedef struct { Window win; Drawable buf; GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ - Atom xembed, wmdeletewin, netwmname, netwmpid; + Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; struct { XIM xim; XIC xic; @@ -1186,6 +1186,7 @@ xinit(int cols, int rows) xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); + xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); @@ -1579,6 +1580,19 @@ xsetenv(void) setenv("WINDOWID", buf, 1); } +void +xseticontitle(char *p) +{ + XTextProperty prop; + DEFAULT(p, opt_title); + + Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, + &prop); + XSetWMIconName(xw.dpy, xw.win, &prop); + XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname); + XFree(prop.value); +} + void xsettitle(char *p) { From 4ef0cbd8b9371f37f7d02ef37b5378b879e6b8bf Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 18 Oct 2020 11:18:03 +0200 Subject: [PATCH 02/18] remove unused variable from previous patch --- st.c | 1 - 1 file changed, 1 deletion(-) diff --git a/st.c b/st.c index ae7fa63..abbbe4b 100644 --- a/st.c +++ b/st.c @@ -1844,7 +1844,6 @@ strhandle(void) { char *p = NULL, *dec; int j, narg, par; - static int winname = 0; term.esc &= ~(ESC_STR_END|ESC_STR); strparse(); From 9e68fdbcdb06dfa3d23fe3a7a7f7b59e40e1ea2f Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 19 Mar 2021 11:54:36 +0100 Subject: [PATCH 03/18] fix: correctly encode mouse buttons >= 8 in X10 and SGR mode These are typically mapped in X11 to the side-buttons (backward/forwards) on the mouse. A comparison of the button numbers in SGR mode (first field): st old: 0 1 2 64 65 66 67 68 69 70 st new (it is the same as xterm now): 0 1 2 64 65 66 67 128 129 130 A script to test and reproduce it, first argument is "h" (on) or "l" (off): #!/bin/sh printf '\x1b[?1000%s\x1b[?1006%s' "$1" "$1" for n in 1 2 3 4 5 6 7 8 9 10; do printf 'button %d\n' "$n" xdotool click "$n" printf '\n\n' done --- x.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x.c b/x.c index 120e495..8bf998e 100644 --- a/x.c +++ b/x.c @@ -387,7 +387,9 @@ mousereport(XEvent *e) button = 3; } else { button -= Button1; - if (button >= 3) + if (button >= 7) + button += 128 - 7; + else if (button >= 3) button += 64 - 3; } if (e->xbutton.type == ButtonPress) { From 4536f46cfff50c66a115755def0155d8e246b02f Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Sun, 28 Mar 2021 21:16:59 +0200 Subject: [PATCH 04/18] Mild const-correctness improvements. Only touch a few things, the main focus is to improve code readability. --- st.c | 44 +++++++++++++++++++++++--------------------- st.h | 4 ++-- x.c | 6 +++--- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/st.c b/st.c index abbbe4b..ebdf360 100644 --- a/st.c +++ b/st.c @@ -186,18 +186,18 @@ static void tputc(Rune); static void treset(void); static void tscrollup(int, int); static void tscrolldown(int, int); -static void tsetattr(int *, int); -static void tsetchar(Rune, Glyph *, int, int); +static void tsetattr(const int *, int); +static void tsetchar(Rune, const Glyph *, int, int); static void tsetdirt(int, int); static void tsetscroll(int, int); static void tswapscreen(void); -static void tsetmode(int, int, int *, int); +static void tsetmode(int, int, const int *, int); static int twrite(const char *, int, int); static void tfulldirt(void); static void tcontrolcode(uchar ); static void tdectest(char ); static void tdefutf8(char); -static int32_t tdefcolor(int *, int *, int); +static int32_t tdefcolor(const int *, int *, int); static void tdeftran(char); static void tstrsequence(uchar); @@ -226,10 +226,10 @@ static int iofd = 1; static int cmdfd; static pid_t pid; -static uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; +static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; +static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; ssize_t xwrite(int fd, const char *s, size_t len) @@ -269,12 +269,14 @@ xrealloc(void *p, size_t len) } char * -xstrdup(char *s) +xstrdup(const char *s) { - if ((s = strdup(s)) == NULL) + char *p; + + if ((p = strdup(s)) == NULL) die("strdup: %s\n", strerror(errno)); - return s; + return p; } size_t @@ -518,7 +520,7 @@ selsnap(int *x, int *y, int direction) { int newx, newy, xt, yt; int delim, prevdelim; - Glyph *gp, *prevgp; + const Glyph *gp, *prevgp; switch (sel.snap) { case SNAP_WORD: @@ -591,7 +593,7 @@ getsel(void) { char *str, *ptr; int y, bufsize, lastx, linelen; - Glyph *gp, *last; + const Glyph *gp, *last; if (sel.ob.x == -1) return NULL; @@ -758,7 +760,7 @@ stty(char **args) } int -ttynew(char *line, char *cmd, char *out, char **args) +ttynew(const char *line, char *cmd, const char *out, char **args) { int m, s; @@ -1186,9 +1188,9 @@ tmoveto(int x, int y) } void -tsetchar(Rune u, Glyph *attr, int x, int y) +tsetchar(Rune u, const Glyph *attr, int x, int y) { - static char *vt100_0[62] = { /* 0x41 - 0x7e */ + static const char *vt100_0[62] = { /* 0x41 - 0x7e */ "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ @@ -1300,7 +1302,7 @@ tdeleteline(int n) } int32_t -tdefcolor(int *attr, int *npar, int l) +tdefcolor(const int *attr, int *npar, int l) { int32_t idx = -1; uint r, g, b; @@ -1350,7 +1352,7 @@ tdefcolor(int *attr, int *npar, int l) } void -tsetattr(int *attr, int l) +tsetattr(const int *attr, int l) { int i; int32_t idx; @@ -1468,9 +1470,9 @@ tsetscroll(int t, int b) } void -tsetmode(int priv, int set, int *args, int narg) +tsetmode(int priv, int set, const int *args, int narg) { - int alt, *lim; + int alt; const int *lim; for (lim = args + narg; args < lim; ++args) { if (priv) { @@ -2020,7 +2022,7 @@ void tdumpline(int n) { char buf[UTF_SIZ]; - Glyph *bp, *end; + const Glyph *bp, *end; bp = &term.line[n][0]; end = &bp[MIN(tlinelen(n), term.col) - 1]; diff --git a/st.h b/st.h index 3d351b6..fa2eddf 100644 --- a/st.h +++ b/st.h @@ -91,7 +91,7 @@ void tnew(int, int); void tresize(int, int); void tsetdirtattr(int); void ttyhangup(void); -int ttynew(char *, char *, char *, char **); +int ttynew(const char *, char *, const char *, char **); size_t ttyread(void); void ttyresize(int, int); void ttywrite(const char *, size_t, int); @@ -109,7 +109,7 @@ size_t utf8encode(Rune, char *); void *xmalloc(size_t); void *xrealloc(void *, size_t); -char *xstrdup(char *); +char *xstrdup(const char *); /* config.h globals */ extern char *utmp; diff --git a/x.c b/x.c index 8bf998e..7186040 100644 --- a/x.c +++ b/x.c @@ -156,7 +156,7 @@ static void xresize(int, int); static void xhints(void); static int xloadcolor(int, const char *, Color *); static int xloadfont(Font *, FcPattern *); -static void xloadfonts(char *, double); +static void xloadfonts(const char *, double); static void xunloadfont(Font *); static void xunloadfonts(void); static void xsetenv(void); @@ -952,7 +952,7 @@ xloadfont(Font *f, FcPattern *pattern) } void -xloadfonts(char *fontstr, double fontsize) +xloadfonts(const char *fontstr, double fontsize) { FcPattern *pattern; double fontval; @@ -960,7 +960,7 @@ xloadfonts(char *fontstr, double fontsize) if (fontstr[0] == '-') pattern = XftXlfdParse(fontstr, False, False); else - pattern = FcNameParse((FcChar8 *)fontstr); + pattern = FcNameParse((const FcChar8 *)fontstr); if (!pattern) die("can't open font %s\n", fontstr); From 2ec571a30c0c3b1a17f6b3631c80d573582f59a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petar=20Kapri=C5=A1?= Date: Sun, 18 Jul 2021 00:14:00 +0200 Subject: [PATCH 05/18] Add 14th bit to XK_SWITCH_MOD bitmask The bits of uint signal in an XKeyEvent which concern the key group (keyboard layout) are bits 13 and 14, as documented here: https://www.x.org/releases/X11R7.7/doc/libX11/XKB/xkblib.html#Groups_and_Shift_Levels In the older version, only bit 13 was marked as part of XK_SWITCH_MOD, this causes issues for users who have more than two keymaps. the 14th bit is not in ignoremod, key sequences are not caught by match(), if they switch to a third or fourth keyboard. --- x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x.c b/x.c index 7186040..248d505 100644 --- a/x.c +++ b/x.c @@ -48,7 +48,7 @@ typedef struct { /* X modifiers */ #define XK_ANY_MOD UINT_MAX #define XK_NO_MOD 0 -#define XK_SWITCH_MOD (1<<13) +#define XK_SWITCH_MOD (1<<13|1<<14) /* function definitions used in config.h */ static void clipcopy(const Arg *); From 1d3142da968da7f6f61f1c1708f39ca233eda150 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Tue, 24 Aug 2021 06:25:05 +0900 Subject: [PATCH 06/18] fix a problem that the standard streams are unexpectedly closed In the current implementation, the slave PTY (assigned to the variable `s') is always closed after duplicating it to file descriptors of standard streams (0, 1, and 2). However, when the allocated slave PTY `s' is already one of 0, 1, or 2, this causes unexpected closing of a standard stream. The same problem occurs when the file descriptor of the master PTY (the variable `m') is one of 0, 1, or 2. In this patch, the original master PTY (m) is closed before it would be overwritten by duplicated slave PTYs. The original slave PTY (s) is closed only when it is not one of the stanrad streams. --- st.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/st.c b/st.c index ebdf360..a9338e1 100644 --- a/st.c +++ b/st.c @@ -793,14 +793,15 @@ ttynew(const char *line, char *cmd, const char *out, char **args) break; case 0: close(iofd); + close(m); setsid(); /* create a new process group */ dup2(s, 0); dup2(s, 1); dup2(s, 2); if (ioctl(s, TIOCSCTTY, NULL) < 0) die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); - close(s); - close(m); + if (s > 2) + close(s); #ifdef __OpenBSD__ if (pledge("stdio getpw proc exec", NULL) == -1) die("pledge\n"); From 2f6e597ed871cff91c627850d03152cae5f45779 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Tue, 24 Aug 2021 13:44:35 +0200 Subject: [PATCH 07/18] fix possible rare crash when Xutf8TextPropertyToTextList fails from the XmbTextListToTextProperty(3) man page: "If insufficient memory is available for the new value string, the functions return XNoMemory. If the current locale is not supported, the functions return XLocaleNotSupported. In both of these error cases, the functions do not set text_prop_return." Reported by Steffen Nurpmeso , thanks! --- x.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/x.c b/x.c index 248d505..89786b8 100644 --- a/x.c +++ b/x.c @@ -1588,8 +1588,9 @@ xseticontitle(char *p) XTextProperty prop; DEFAULT(p, opt_title); - Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop); + if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, + &prop) != Success) + return; XSetWMIconName(xw.dpy, xw.win, &prop); XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname); XFree(prop.value); @@ -1601,8 +1602,9 @@ xsettitle(char *p) XTextProperty prop; DEFAULT(p, opt_title); - Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop); + if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, + &prop) != Success) + return; XSetWMName(xw.dpy, xw.win, &prop); XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); XFree(prop.value); From 8e310303903792c010d03c046ba75f8b18f7d3a7 Mon Sep 17 00:00:00 2001 From: Raheman Vaiya Date: Sun, 26 Dec 2021 18:57:04 +0100 Subject: [PATCH 08/18] Add support for OSC color sequences --- config.def.h | 8 ++++-- st.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++- st.h | 3 ++ x.c | 13 +++++++++ 4 files changed, 100 insertions(+), 4 deletions(-) diff --git a/config.def.h b/config.def.h index 6f05dce..91ab8ca 100644 --- a/config.def.h +++ b/config.def.h @@ -120,6 +120,8 @@ static const char *colorname[] = { /* more colors can be added after 255 to use with DefaultXX */ "#cccccc", "#555555", + "gray90", /* default foreground colour */ + "black", /* default background colour */ }; @@ -127,9 +129,9 @@ static const char *colorname[] = { * Default colors (colorname index) * foreground, background, cursor, reverse cursor */ -unsigned int defaultfg = 7; -unsigned int defaultbg = 0; -static unsigned int defaultcs = 256; +unsigned int defaultfg = 258; +unsigned int defaultbg = 259; +unsigned int defaultcs = 256; static unsigned int defaultrcs = 257; /* diff --git a/st.c b/st.c index a9338e1..781dbf2 100644 --- a/st.c +++ b/st.c @@ -1842,6 +1842,42 @@ csireset(void) memset(&csiescseq, 0, sizeof(csiescseq)); } +void +osc4_color_response(int num) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(num, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch osc4 color %d\n", num); + return; + } + + n = snprintf(buf, sizeof buf, "\033]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + num, r, r, g, g, b, b); + + ttywrite(buf, n, 1); +} + +void +osc_color_response(int index, int num) +{ + int n; + char buf[32]; + unsigned char r, g, b; + + if (xgetcolor(index, &r, &g, &b)) { + fprintf(stderr, "erresc: failed to fetch osc color %d\n", index); + return; + } + + n = snprintf(buf, sizeof buf, "\033]%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", + num, r, r, g, g, b, b); + + ttywrite(buf, n, 1); +} + void strhandle(void) { @@ -1880,6 +1916,45 @@ strhandle(void) } } return; + case 10: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultfg, 10); + else if (xsetcolorname(defaultfg, p)) + fprintf(stderr, "erresc: invalid foreground color: %s\n", p); + else + redraw(); + break; + case 11: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultbg, 11); + else if (xsetcolorname(defaultbg, p)) + fprintf(stderr, "erresc: invalid background color: %s\n", p); + else + redraw(); + break; + case 12: + if (narg < 2) + break; + + p = strescseq.args[1]; + + if (!strcmp(p, "?")) + osc_color_response(defaultcs, 12); + else if (xsetcolorname(defaultcs, p)) + fprintf(stderr, "erresc: invalid cursor color: %s\n", p); + else + redraw(); + break; case 4: /* color set */ if (narg < 3) break; @@ -1887,7 +1962,10 @@ strhandle(void) /* FALLTHROUGH */ case 104: /* color reset, here p = NULL */ j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - if (xsetcolorname(j, p)) { + + if (!strcmp(p, "?")) + osc4_color_response(j); + else if (xsetcolorname(j, p)) { if (par == 104 && narg <= 1) return; /* color reset without parameter */ fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", diff --git a/st.h b/st.h index fa2eddf..519b9bd 100644 --- a/st.h +++ b/st.h @@ -111,6 +111,8 @@ void *xmalloc(size_t); void *xrealloc(void *, size_t); char *xstrdup(const char *); +int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b); + /* config.h globals */ extern char *utmp; extern char *scroll; @@ -123,3 +125,4 @@ extern char *termname; extern unsigned int tabspaces; extern unsigned int defaultfg; extern unsigned int defaultbg; +extern unsigned int defaultcs; diff --git a/x.c b/x.c index 89786b8..8a16faa 100644 --- a/x.c +++ b/x.c @@ -799,6 +799,19 @@ xloadcols(void) loaded = 1; } +int +xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) +{ + if (!BETWEEN(x, 0, dc.collen)) + return 1; + + *r = dc.col[x].color.red >> 8; + *g = dc.col[x].color.green >> 8; + *b = dc.col[x].color.blue >> 8; + + return 0; +} + int xsetcolorname(int x, const char *name) { From 273db5ceaf392e68c2faf8f7dec14ea2e25e980d Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 26 Dec 2021 19:00:41 +0100 Subject: [PATCH 09/18] follow-up fix for OSC color sequences, return Otherwise the message "erresc: unknown str" is printed. --- st.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/st.c b/st.c index 781dbf2..6783c2b 100644 --- a/st.c +++ b/st.c @@ -1928,7 +1928,7 @@ strhandle(void) fprintf(stderr, "erresc: invalid foreground color: %s\n", p); else redraw(); - break; + return; case 11: if (narg < 2) break; @@ -1941,7 +1941,7 @@ strhandle(void) fprintf(stderr, "erresc: invalid background color: %s\n", p); else redraw(); - break; + return; case 12: if (narg < 2) break; @@ -1954,7 +1954,7 @@ strhandle(void) fprintf(stderr, "erresc: invalid cursor color: %s\n", p); else redraw(); - break; + return; case 4: /* color set */ if (narg < 3) break; From a0467c802d4f86ed162486e3453dd61181423902 Mon Sep 17 00:00:00 2001 From: Jochen Sprickerhof Date: Mon, 27 Dec 2021 11:41:42 +0100 Subject: [PATCH 10/18] Fix null pointer access in strhandle According to the spec the argument is optional for 104, so p can be NULL as can be tested with printf '\x1b]104\x07'. This is a regression of 8e31030. --- st.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/st.c b/st.c index 6783c2b..de2dd0e 100644 --- a/st.c +++ b/st.c @@ -1960,10 +1960,10 @@ strhandle(void) break; p = strescseq.args[2]; /* FALLTHROUGH */ - case 104: /* color reset, here p = NULL */ + case 104: /* color reset */ j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - if (!strcmp(p, "?")) + if (p && !strcmp(p, "?")) osc4_color_response(j); else if (xsetcolorname(j, p)) { if (par == 104 && narg <= 1) From 65f1dc428315ae9d7f362e10c668557c1379e7af Mon Sep 17 00:00:00 2001 From: jamin Date: Wed, 29 Dec 2021 09:07:17 -0800 Subject: [PATCH 11/18] Fix overtyping wide characters. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Overtyping the first half of a wide character with the second half of a wide character results in display garbage. This is because the trailing dummy is not cleaned up. i.e. ATTR_WIDE, ATTR_WDUMMY, ATTR_WDUMMY Here is a short script for demonstrating the behavior: #!/bin/sh alias printf=/usr/bin/printf printf こんにちは!; sleep 2 printf '\x1b[5D'; sleep 2 printf へ; sleep 2 printf ' '; sleep 2 echo --- st.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/st.c b/st.c index de2dd0e..51049ba 100644 --- a/st.c +++ b/st.c @@ -2507,6 +2507,10 @@ tputc(Rune u) if (width == 2) { gp->mode |= ATTR_WIDE; if (term.c.x+1 < term.col) { + if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) { + gp[2].u = ' '; + gp[2].mode &= ~ATTR_WDUMMY; + } gp[1].u = '\0'; gp[1].mode = ATTR_WDUMMY; } From 7e1c68f25d9f08687a94eeef8d7f8ffd0d14b911 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Sun, 2 Jan 2022 12:15:45 +0100 Subject: [PATCH 12/18] FAQ: fix a typo, patch -> path --- FAQ | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FAQ b/FAQ index 0f9609d..969b195 100644 --- a/FAQ +++ b/FAQ @@ -29,8 +29,8 @@ you can manually run `tic -sx st.info`. ## I would like to have utmp and/or scroll functionality by default -You can add the absolute patch of both programs in your config.h -file. You only have to modify the value of utmp and scroll variables. +You can add the absolute path of both programs in your config.h file. You only +have to modify the value of utmp and scroll variables. ## Why doesn't the Del key work in some programs? From 7fb0c0cc681f36be2ad12091ef93a41671f32738 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Fri, 7 Jan 2022 12:39:57 +0100 Subject: [PATCH 13/18] bump version to 0.8.5 --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index c070a4a..4c4c5d5 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # st version -VERSION = 0.8.4 +VERSION = 0.8.5 # Customize below to fit your system From ea7cd7b62fdfa6a1fbd882d1565d557577f2cf32 Mon Sep 17 00:00:00 2001 From: robert Date: Sat, 8 Jan 2022 11:40:34 -0800 Subject: [PATCH 14/18] Fix mousereport This patch replaces the previous one I sent. The following changes are made in this patch: - Fix tracking of pressed buttons. Previously, pressing two buttons and then releasing one would make st think no buttons are pressed, which in particular broke MODE_MOUSEMOTION. - Always send the lowest-numbered pressed button on motion events; when no button is pressed for a motion event in MODE_MOUSEMANY, then send a release. This matches the behaviour of xterm. (Previously, st sent the most recently pressed button in the motion report.) - Remove UB (?) access to potentially inactive struct member e->xbutton.button of XEvent union. - Fix (unlikely) possibility of overflow for large button numbers. The one discrepancy I found between st and xterm is that xterm sometimes encodes buttons with large numbers (>5) strangely. E.g., xterm reports presses of buttons 8 and 9 as releases, whereas st properly (?) encodes them as presses. --- x.c | 86 ++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/x.c b/x.c index 8a16faa..5f4ea73 100644 --- a/x.c +++ b/x.c @@ -252,7 +252,7 @@ static char *opt_line = NULL; static char *opt_name = NULL; static char *opt_title = NULL; -static int oldbutton = 3; /* button event on startup: 3 = release */ +static uint buttons; /* bit field of pressed buttons */ void clipcopy(const Arg *dummy) @@ -364,61 +364,68 @@ mousesel(XEvent *e, int done) void mousereport(XEvent *e) { - int len, x = evcol(e), y = evrow(e), - button = e->xbutton.button, state = e->xbutton.state; + int len, btn, code; + int x = evcol(e), y = evrow(e); + int state = e->xbutton.state; char buf[40]; static int ox, oy; - /* from urxvt */ - if (e->xbutton.type == MotionNotify) { + if (e->type == MotionNotify) { if (x == ox && y == oy) return; if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) return; - /* MOUSE_MOTION: no reporting if no button is pressed */ - if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3) + /* MODE_MOUSEMOTION: no reporting if no button is pressed */ + if (IS_SET(MODE_MOUSEMOTION) && buttons == 0) return; - - button = oldbutton + 32; - ox = x; - oy = y; + /* Set btn to lowest-numbered pressed button, or 12 if no + * buttons are pressed. */ + for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++) + ; + code = 32; } else { - if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) { - button = 3; - } else { - button -= Button1; - if (button >= 7) - button += 128 - 7; - else if (button >= 3) - button += 64 - 3; - } - if (e->xbutton.type == ButtonPress) { - oldbutton = button; - ox = x; - oy = y; - } else if (e->xbutton.type == ButtonRelease) { - oldbutton = 3; + btn = e->xbutton.button; + /* Only buttons 1 through 11 can be encoded */ + if (btn < 1 || btn > 11) + return; + if (e->type == ButtonRelease) { /* MODE_MOUSEX10: no button release reporting */ if (IS_SET(MODE_MOUSEX10)) return; - if (button == 64 || button == 65) + /* Don't send release events for the scroll wheel */ + if (btn == 4 || btn == 5) return; } + code = 0; } + ox = x; + oy = y; + + /* Encode btn into code. If no button is pressed for a motion event in + * MODE_MOUSEMANY, then encode it as a release. */ + if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12) + code += 3; + else if (btn >= 8) + code += 128 + btn - 8; + else if (btn >= 4) + code += 64 + btn - 4; + else + code += btn - 1; + if (!IS_SET(MODE_MOUSEX10)) { - button += ((state & ShiftMask ) ? 4 : 0) - + ((state & Mod4Mask ) ? 8 : 0) - + ((state & ControlMask) ? 16 : 0); + code += ((state & ShiftMask ) ? 4 : 0) + + ((state & Mod4Mask ) ? 8 : 0) + + ((state & ControlMask) ? 16 : 0); } if (IS_SET(MODE_MOUSESGR)) { len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", - button, x+1, y+1, - e->xbutton.type == ButtonRelease ? 'm' : 'M'); + code, x+1, y+1, + e->type == ButtonRelease ? 'm' : 'M'); } else if (x < 223 && y < 223) { len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", - 32+button, 32+x+1, 32+y+1); + 32+code, 32+x+1, 32+y+1); } else { return; } @@ -461,9 +468,13 @@ mouseaction(XEvent *e, uint release) void bpress(XEvent *e) { + int btn = e->xbutton.button; struct timespec now; int snap; + if (1 <= btn && btn <= 11) + buttons |= 1 << (btn-1); + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { mousereport(e); return; @@ -472,7 +483,7 @@ bpress(XEvent *e) if (mouseaction(e, 0)) return; - if (e->xbutton.button == Button1) { + if (btn == Button1) { /* * If the user clicks below predefined timeouts specific * snapping behaviour is exposed. @@ -686,6 +697,11 @@ xsetsel(char *str) void brelease(XEvent *e) { + int btn = e->xbutton.button; + + if (1 <= btn && btn <= 11) + buttons &= ~(1 << (btn-1)); + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { mousereport(e); return; @@ -693,7 +709,7 @@ brelease(XEvent *e) if (mouseaction(e, 1)) return; - if (e->xbutton.button == Button1) + if (btn == Button1) mousesel(e, 1); } From b1d97fec47b0d6633addb848131388ec40154ebc Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Mon, 10 Jan 2022 17:11:17 +0100 Subject: [PATCH 15/18] LICENSE: bump year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index d80eb47..3cbf420 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT/X Consortium License -© 2014-2020 Hiltjo Posthuma +© 2014-2022 Hiltjo Posthuma © 2018 Devin J. Pohly © 2014-2017 Quentin Rameau © 2009-2012 Aurélien APTEL From 2c5edf28ec851907305d73c6218ce75d39f1767f Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Wed, 12 Jan 2022 09:44:27 +0100 Subject: [PATCH 16/18] X10/SGR mouse: use alt as meta key instead of super/windows key --- x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x.c b/x.c index 5f4ea73..cd96575 100644 --- a/x.c +++ b/x.c @@ -415,7 +415,7 @@ mousereport(XEvent *e) if (!IS_SET(MODE_MOUSEX10)) { code += ((state & ShiftMask ) ? 4 : 0) - + ((state & Mod4Mask ) ? 8 : 0) + + ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */ + ((state & ControlMask) ? 16 : 0); } From e823e2308f2a99023032a3966ebb7036a31d305f Mon Sep 17 00:00:00 2001 From: Santtu Lakkala Date: Thu, 17 Feb 2022 16:00:47 +0200 Subject: [PATCH 17/18] Delay redrawals on palette changes Build on auto-sync and only mark window dirty on palette changes and let the event handler do the actual draw. --- st.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/st.c b/st.c index 51049ba..c71fa06 100644 --- a/st.c +++ b/st.c @@ -1927,7 +1927,7 @@ strhandle(void) else if (xsetcolorname(defaultfg, p)) fprintf(stderr, "erresc: invalid foreground color: %s\n", p); else - redraw(); + tfulldirt(); return; case 11: if (narg < 2) @@ -1940,7 +1940,7 @@ strhandle(void) else if (xsetcolorname(defaultbg, p)) fprintf(stderr, "erresc: invalid background color: %s\n", p); else - redraw(); + tfulldirt(); return; case 12: if (narg < 2) @@ -1953,7 +1953,7 @@ strhandle(void) else if (xsetcolorname(defaultcs, p)) fprintf(stderr, "erresc: invalid cursor color: %s\n", p); else - redraw(); + tfulldirt(); return; case 4: /* color set */ if (narg < 3) @@ -1975,7 +1975,7 @@ strhandle(void) * TODO if defaultbg color is changed, borders * are dirty */ - redraw(); + tfulldirt(); } return; } From 2aefa348baf4b702fdce98eb105bcba175d8283f Mon Sep 17 00:00:00 2001 From: Zacchary Dempsey-Plante Date: Sun, 13 Mar 2022 10:44:08 +0100 Subject: [PATCH 18/18] make underlines and strikethroughs respect `chscale` --- x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x.c b/x.c index cd96575..2a3bd38 100644 --- a/x.c +++ b/x.c @@ -1493,12 +1493,12 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i /* Render underline and strikethrough. */ if (base.mode & ATTR_UNDERLINE) { - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, + XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1, width, 1); } if (base.mode & ATTR_STRUCK) { - XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, + XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3, width, 1); }