Compare commits

..

No commits in common. "master" and "v0.8.5" have entirely different histories.

11 changed files with 123 additions and 123 deletions

3
FAQ
View File

@ -248,6 +248,3 @@ fonts:
Please don't bother reporting this bug to st, but notify the upstream Xft Please don't bother reporting this bug to st, but notify the upstream Xft
developers about fixing this bug. developers about fixing this bug.
As of 2022-09-05 this now seems to be finally fixed in libXft 2.3.5:
https://gitlab.freedesktop.org/xorg/lib/libxft/-/blob/libXft-2.3.5/NEWS

View File

@ -1,6 +1,6 @@
MIT/X Consortium License MIT/X Consortium License
© 2014-2022 Hiltjo Posthuma <hiltjo at codemadness dot org> © 2014-2020 Hiltjo Posthuma <hiltjo at codemadness dot org>
© 2018 Devin J. Pohly <djpohly at gmail dot com> © 2018 Devin J. Pohly <djpohly at gmail dot com>
© 2014-2017 Quentin Rameau <quinq at fifth dot space> © 2014-2017 Quentin Rameau <quinq at fifth dot space>
© 2009-2012 Aurélien APTEL <aurelien dot aptel at gmail dot com> © 2009-2012 Aurélien APTEL <aurelien dot aptel at gmail dot com>

View File

@ -14,28 +14,23 @@ st-config - My configuration of st suckless simple terminal
* `Support for scroll with Alt+j and Alt+k` * `Support for scroll with Alt+j and Alt+k`
* `Support for scroll with Alt+Up and Alt+Down` * `Support for scroll with Alt+Up and Alt+Down`
* `Support for scroll block with Alt+PageUp and Alt+PageDown` * `Support for scroll block with Alt+PageUp and Alt+PageDown`
* `Set font size with -z parameter`
* `Increase/Decrease/Reset zoom with Ctrl+9/8/0`
* `Increase/Decrease zoom with Ctrl+Plus/Minus`
* `Patch autocomplete applied` * `Patch autocomplete applied`
* `Includes shortcut installation` * `Includes shortcut installation`
<img src="https://git.q3aql.dev/q3aql/st-config/raw/branch/master/examples/st.png" /> <img src="examples/st.png" />
### Dependencies: ### Dependencies:
* **Arch Linux:** * **Arch Linux:**
```shell ```shell
$ sudo pacman -S gcc git make coreutils freetype2 libxinerama fontconfig libx11 \ $ sudo pacman -S gcc make coreutils freetype2 libxinerama fontconfig libx11 libxrender
libxrender libxft --noconfirm
```` ````
* **Debian/Ubuntu:** * **Debian/Ubuntu:**
```shell ```shell
$ sudo apt install gcc git make coreutils libfreetype-dev libxinerama-dev libxft-dev \ $ sudo apt install gcc make coreutils libfreetype-dev libxinerama-dev libfreetype6-dev libfontconfig1-dev libxrender-dev
libfreetype6-dev libfontconfig1-dev libxrender-dev -y
```` ````
### Build and install: ### Build and install:
@ -43,7 +38,7 @@ st-config - My configuration of st suckless simple terminal
* Open terminal and run the following commands: * Open terminal and run the following commands:
```shell ```shell
$ git clone https://git.q3aql.dev/q3aql/st-config $ git clone https://github.com/q3aql/st-config
$ cd st-config $ cd st-config
$ sudo make install clean $ sudo make install clean
```` ````

View File

@ -208,13 +208,8 @@ static Shortcut shortcuts[] = {
{ ShiftMask, XK_Print, printscreen, {.i = 0} }, { ShiftMask, XK_Print, printscreen, {.i = 0} },
{ XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, { XK_ANY_MOD, XK_Print, printsel, {.i = 0} },
{ TERMMOD, XK_Prior, zoom, {.f = +1} }, { TERMMOD, XK_Prior, zoom, {.f = +1} },
{ ControlMask, XK_9, zoom, {.f = +1} },
{ ControlMask, XK_plus, zoom, {.f = +1} },
{ TERMMOD, XK_Next, zoom, {.f = -1} }, { TERMMOD, XK_Next, zoom, {.f = -1} },
{ ControlMask, XK_8, zoom, {.f = -1} },
{ ControlMask, XK_minus, zoom, {.f = -1} },
{ TERMMOD, XK_Home, zoomreset, {.f = 0} }, { TERMMOD, XK_Home, zoomreset, {.f = 0} },
{ ControlMask, XK_0, zoomreset, {.f = 0} },
{ TERMMOD, XK_C, clipcopy, {.i = 0} }, { TERMMOD, XK_C, clipcopy, {.i = 0} },
{ TERMMOD, XK_V, clippaste, {.i = 0} }, { TERMMOD, XK_V, clippaste, {.i = 0} },
{ TERMMOD, XK_Y, selpaste, {.i = 0} }, { TERMMOD, XK_Y, selpaste, {.i = 0} },

View File

@ -208,13 +208,8 @@ static Shortcut shortcuts[] = {
{ ShiftMask, XK_Print, printscreen, {.i = 0} }, { ShiftMask, XK_Print, printscreen, {.i = 0} },
{ XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, { XK_ANY_MOD, XK_Print, printsel, {.i = 0} },
{ TERMMOD, XK_Prior, zoom, {.f = +1} }, { TERMMOD, XK_Prior, zoom, {.f = +1} },
{ ControlMask, XK_9, zoom, {.f = +1} },
{ ControlMask, XK_plus, zoom, {.f = +1} },
{ TERMMOD, XK_Next, zoom, {.f = -1} }, { TERMMOD, XK_Next, zoom, {.f = -1} },
{ ControlMask, XK_8, zoom, {.f = -1} },
{ ControlMask, XK_minus, zoom, {.f = -1} },
{ TERMMOD, XK_Home, zoomreset, {.f = 0} }, { TERMMOD, XK_Home, zoomreset, {.f = 0} },
{ ControlMask, XK_0, zoomreset, {.f = 0} },
{ TERMMOD, XK_C, clipcopy, {.i = 0} }, { TERMMOD, XK_C, clipcopy, {.i = 0} },
{ TERMMOD, XK_V, clippaste, {.i = 0} }, { TERMMOD, XK_V, clippaste, {.i = 0} },
{ TERMMOD, XK_Y, selpaste, {.i = 0} }, { TERMMOD, XK_Y, selpaste, {.i = 0} },

View File

@ -1,5 +1,5 @@
# st version # st version
VERSION = 0.9 VERSION = 0.8.5
# Customize below to fit your system # Customize below to fit your system
@ -30,7 +30,6 @@ STLDFLAGS = $(LIBS) $(LDFLAGS)
#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ #LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \
# `$(PKG_CONFIG) --libs fontconfig` \ # `$(PKG_CONFIG) --libs fontconfig` \
# `$(PKG_CONFIG) --libs freetype2` # `$(PKG_CONFIG) --libs freetype2`
#MANPREFIX = ${PREFIX}/man
# compiler and linker # compiler and linker
# CC = c99 # CC = c99

118
st.c
View File

@ -169,7 +169,6 @@ static void csidump(void);
static void csihandle(void); static void csihandle(void);
static void csiparse(void); static void csiparse(void);
static void csireset(void); static void csireset(void);
static void osc_color_response(int, int, int);
static int eschandle(uchar); static int eschandle(uchar);
static void strdump(void); static void strdump(void);
static void strhandle(void); static void strhandle(void);
@ -358,10 +357,25 @@ utf8validate(Rune *u, size_t i)
return i; return i;
} }
static const char base64_digits[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0,
63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, -1, 0, 0, 0, 0, 1,
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
char char
base64dec_getc(const char **src) base64dec_getc(const char **src)
{ {
while (**src && !isprint((unsigned char)**src)) while (**src && !isprint(**src))
(*src)++; (*src)++;
return **src ? *((*src)++) : '='; /* emulate padding if string ends */ return **src ? *((*src)++) : '='; /* emulate padding if string ends */
} }
@ -371,13 +385,6 @@ base64dec(const char *src)
{ {
size_t in_len = strlen(src); size_t in_len = strlen(src);
char *result, *dst; char *result, *dst;
static const char base64_digits[256] = {
[43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0,
0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
};
if (in_len % 4) if (in_len % 4)
in_len += 4 - (in_len % 4); in_len += 4 - (in_len % 4);
@ -950,7 +957,7 @@ ttyresize(int tw, int th)
} }
void void
ttyhangup(void) ttyhangup()
{ {
/* Send SIGHUP to shell */ /* Send SIGHUP to shell */
kill(pid, SIGHUP); kill(pid, SIGHUP);
@ -1899,28 +1906,39 @@ csireset(void)
} }
void void
osc_color_response(int num, int index, int is_osc4) osc4_color_response(int num)
{ {
int n; int n;
char buf[32]; char buf[32];
unsigned char r, g, b; unsigned char r, g, b;
if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) { if (xgetcolor(num, &r, &g, &b)) {
fprintf(stderr, "erresc: failed to fetch %s color %d\n", fprintf(stderr, "erresc: failed to fetch osc4 color %d\n", num);
is_osc4 ? "osc4" : "osc",
is_osc4 ? num : index);
return; return;
} }
n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", n = snprintf(buf, sizeof buf, "\033]4;%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
is_osc4 ? "4;" : "", num, r, r, g, g, b, b); num, r, r, g, g, b, b);
if (n < 0 || n >= sizeof(buf)) {
fprintf(stderr, "error: %s while printing %s response\n",
n < 0 ? "snprintf failed" : "truncation occurred",
is_osc4 ? "osc4" : "osc");
} else {
ttywrite(buf, n, 1); 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 void
@ -1928,11 +1946,6 @@ strhandle(void)
{ {
char *p = NULL, *dec; char *p = NULL, *dec;
int j, narg, par; int j, narg, par;
const struct { int idx; char *str; } osc_table[] = {
{ defaultfg, "foreground" },
{ defaultbg, "background" },
{ defaultcs, "cursor" }
};
term.esc &= ~(ESC_STR_END|ESC_STR); term.esc &= ~(ESC_STR_END|ESC_STR);
strparse(); strparse();
@ -1967,22 +1980,43 @@ strhandle(void)
} }
return; return;
case 10: 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();
return;
case 11: 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();
return;
case 12: case 12:
if (narg < 2) if (narg < 2)
break; break;
p = strescseq.args[1];
if ((j = par - 10) < 0 || j >= LEN(osc_table))
break; /* shouldn't be possible */
if (!strcmp(p, "?")) { p = strescseq.args[1];
osc_color_response(par, osc_table[j].idx, 0);
} else if (xsetcolorname(osc_table[j].idx, p)) { if (!strcmp(p, "?"))
fprintf(stderr, "erresc: invalid %s color: %s\n", osc_color_response(defaultcs, 12);
osc_table[j].str, p); else if (xsetcolorname(defaultcs, p))
} else { fprintf(stderr, "erresc: invalid cursor color: %s\n", p);
tfulldirt(); else
} redraw();
return; return;
case 4: /* color set */ case 4: /* color set */
if (narg < 3) if (narg < 3)
@ -1992,9 +2026,9 @@ strhandle(void)
case 104: /* color reset */ case 104: /* color reset */
j = (narg > 1) ? atoi(strescseq.args[1]) : -1; j = (narg > 1) ? atoi(strescseq.args[1]) : -1;
if (p && !strcmp(p, "?")) { if (p && !strcmp(p, "?"))
osc_color_response(j, 0, 1); osc4_color_response(j);
} else if (xsetcolorname(j, p)) { else if (xsetcolorname(j, p)) {
if (par == 104 && narg <= 1) if (par == 104 && narg <= 1)
return; /* color reset without parameter */ return; /* color reset without parameter */
fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", fprintf(stderr, "erresc: invalid color j=%d, p=%s\n",
@ -2004,7 +2038,7 @@ strhandle(void)
* TODO if defaultbg color is changed, borders * TODO if defaultbg color is changed, borders
* are dirty * are dirty
*/ */
tfulldirt(); redraw();
} }
return; return;
} }

View File

@ -5,7 +5,7 @@ TryExec=st
Icon=utilities-terminal Icon=utilities-terminal
Terminal=false Terminal=false
Categories=System;TerminalEmulator; Categories=System;TerminalEmulator;
Name=st Simple Terminal (Suckless) Name=st
GenericName=Terminal GenericName=Terminal
Comment=st is a simple terminal implementation for X Comment=st is a simple terminal implementation for X
StartupWMClass=st-256color StartupWMClass=st-256color

2
st.h
View File

@ -115,6 +115,8 @@ void *xmalloc(size_t);
void *xrealloc(void *, size_t); void *xrealloc(void *, size_t);
char *xstrdup(const char *); char *xstrdup(const char *);
int xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b);
/* config.h globals */ /* config.h globals */
extern char *utmp; extern char *utmp;
extern char *scroll; extern char *scroll;

1
win.h
View File

@ -30,7 +30,6 @@ void xdrawline(Line, int, int, int);
void xfinishdraw(void); void xfinishdraw(void);
void xloadcols(void); void xloadcols(void);
int xsetcolorname(int, const char *); int xsetcolorname(int, const char *);
int xgetcolor(int, unsigned char *, unsigned char *, unsigned char *);
void xseticontitle(char *); void xseticontitle(char *);
void xsettitle(char *); void xsettitle(char *);
int xsetcursor(int); int xsetcursor(int);

88
x.c
View File

@ -253,7 +253,7 @@ static char *opt_line = NULL;
static char *opt_name = NULL; static char *opt_name = NULL;
static char *opt_title = NULL; static char *opt_title = NULL;
static uint buttons; /* bit field of pressed buttons */ static int oldbutton = 3; /* button event on startup: 3 = release */
static int cursorblinks = 0; static int cursorblinks = 0;
void void
@ -366,68 +366,61 @@ mousesel(XEvent *e, int done)
void void
mousereport(XEvent *e) mousereport(XEvent *e)
{ {
int len, btn, code; int len, x = evcol(e), y = evrow(e),
int x = evcol(e), y = evrow(e); button = e->xbutton.button, state = e->xbutton.state;
int state = e->xbutton.state;
char buf[40]; char buf[40];
static int ox, oy; static int ox, oy;
if (e->type == MotionNotify) { /* from urxvt */
if (e->xbutton.type == MotionNotify) {
if (x == ox && y == oy) if (x == ox && y == oy)
return; return;
if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY))
return; return;
/* MODE_MOUSEMOTION: no reporting if no button is pressed */ /* MOUSE_MOTION: no reporting if no button is pressed */
if (IS_SET(MODE_MOUSEMOTION) && buttons == 0) if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3)
return; return;
/* Set btn to lowest-numbered pressed button, or 12 if no
* buttons are pressed. */ button = oldbutton + 32;
for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++) ox = x;
; oy = y;
code = 32;
} else { } else {
btn = e->xbutton.button; if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) {
/* Only buttons 1 through 11 can be encoded */ button = 3;
if (btn < 1 || btn > 11) } else {
return; button -= Button1;
if (e->type == ButtonRelease) { 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;
/* MODE_MOUSEX10: no button release reporting */ /* MODE_MOUSEX10: no button release reporting */
if (IS_SET(MODE_MOUSEX10)) if (IS_SET(MODE_MOUSEX10))
return; return;
/* Don't send release events for the scroll wheel */ if (button == 64 || button == 65)
if (btn == 4 || btn == 5)
return; 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)) { if (!IS_SET(MODE_MOUSEX10)) {
code += ((state & ShiftMask ) ? 4 : 0) button += ((state & ShiftMask ) ? 4 : 0)
+ ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */ + ((state & Mod4Mask ) ? 8 : 0)
+ ((state & ControlMask) ? 16 : 0); + ((state & ControlMask) ? 16 : 0);
} }
if (IS_SET(MODE_MOUSESGR)) { if (IS_SET(MODE_MOUSESGR)) {
len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c",
code, x+1, y+1, button, x+1, y+1,
e->type == ButtonRelease ? 'm' : 'M'); e->xbutton.type == ButtonRelease ? 'm' : 'M');
} else if (x < 223 && y < 223) { } else if (x < 223 && y < 223) {
len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", len = snprintf(buf, sizeof(buf), "\033[M%c%c%c",
32+code, 32+x+1, 32+y+1); 32+button, 32+x+1, 32+y+1);
} else { } else {
return; return;
} }
@ -470,13 +463,9 @@ mouseaction(XEvent *e, uint release)
void void
bpress(XEvent *e) bpress(XEvent *e)
{ {
int btn = e->xbutton.button;
struct timespec now; struct timespec now;
int snap; int snap;
if (1 <= btn && btn <= 11)
buttons |= 1 << (btn-1);
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
mousereport(e); mousereport(e);
return; return;
@ -485,7 +474,7 @@ bpress(XEvent *e)
if (mouseaction(e, 0)) if (mouseaction(e, 0))
return; return;
if (btn == Button1) { if (e->xbutton.button == Button1) {
/* /*
* If the user clicks below predefined timeouts specific * If the user clicks below predefined timeouts specific
* snapping behaviour is exposed. * snapping behaviour is exposed.
@ -699,11 +688,6 @@ xsetsel(char *str)
void void
brelease(XEvent *e) 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)) { if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
mousereport(e); mousereport(e);
return; return;
@ -711,7 +695,7 @@ brelease(XEvent *e)
if (mouseaction(e, 1)) if (mouseaction(e, 1))
return; return;
if (btn == Button1) if (e->xbutton.button == Button1)
mousesel(e, 1); mousesel(e, 1);
} }
@ -1495,12 +1479,12 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
/* Render underline and strikethrough. */ /* Render underline and strikethrough. */
if (base.mode & ATTR_UNDERLINE) { if (base.mode & ATTR_UNDERLINE) {
XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1, XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1,
width, 1); width, 1);
} }
if (base.mode & ATTR_STRUCK) { if (base.mode & ATTR_STRUCK) {
XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3, XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3,
width, 1); width, 1);
} }