st 0.9 source code
This commit is contained in:
parent
d71cd9d4a7
commit
ce0cbe1aa8
3
FAQ
3
FAQ
|
@ -248,3 +248,6 @@ fonts:
|
|||
|
||||
Please don't bother reporting this bug to st, but notify the upstream Xft
|
||||
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
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT/X Consortium License
|
||||
|
||||
© 2014-2020 Hiltjo Posthuma <hiltjo at codemadness dot org>
|
||||
© 2014-2022 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>
|
||||
|
|
34
README
Normal file
34
README
Normal file
|
@ -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.
|
||||
|
|
@ -155,8 +155,8 @@ static Rune stcursor = 0x2603; /* snowman ("☃") */
|
|||
* Default columns and rows numbers
|
||||
*/
|
||||
|
||||
static unsigned int cols = 123;
|
||||
static unsigned int rows = 33;
|
||||
static unsigned int cols = 80;
|
||||
static unsigned int rows = 24;
|
||||
|
||||
/*
|
||||
* Default colour and shape of the mouse cursor
|
||||
|
|
4
config.h
4
config.h
|
@ -155,8 +155,8 @@ static Rune stcursor = 0x2603; /* snowman ("☃") */
|
|||
* Default columns and rows numbers
|
||||
*/
|
||||
|
||||
static unsigned int cols = 123;
|
||||
static unsigned int rows = 33;
|
||||
static unsigned int cols = 80;
|
||||
static unsigned int rows = 24;
|
||||
|
||||
/*
|
||||
* Default colour and shape of the mouse cursor
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# st version
|
||||
VERSION = 0.8.5
|
||||
VERSION = 0.9
|
||||
|
||||
# Customize below to fit your system
|
||||
|
||||
|
@ -30,6 +30,7 @@ STLDFLAGS = $(LIBS) $(LDFLAGS)
|
|||
#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \
|
||||
# `$(PKG_CONFIG) --libs fontconfig` \
|
||||
# `$(PKG_CONFIG) --libs freetype2`
|
||||
#MANPREFIX = ${PREFIX}/man
|
||||
|
||||
# compiler and linker
|
||||
# CC = c99
|
||||
|
|
118
st.c
118
st.c
|
@ -169,6 +169,7 @@ static void csidump(void);
|
|||
static void csihandle(void);
|
||||
static void csiparse(void);
|
||||
static void csireset(void);
|
||||
static void osc_color_response(int, int, int);
|
||||
static int eschandle(uchar);
|
||||
static void strdump(void);
|
||||
static void strhandle(void);
|
||||
|
@ -357,25 +358,10 @@ utf8validate(Rune *u, size_t 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
|
||||
base64dec_getc(const char **src)
|
||||
{
|
||||
while (**src && !isprint(**src))
|
||||
while (**src && !isprint((unsigned char)**src))
|
||||
(*src)++;
|
||||
return **src ? *((*src)++) : '='; /* emulate padding if string ends */
|
||||
}
|
||||
|
@ -385,6 +371,13 @@ base64dec(const char *src)
|
|||
{
|
||||
size_t in_len = strlen(src);
|
||||
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)
|
||||
in_len += 4 - (in_len % 4);
|
||||
|
@ -957,7 +950,7 @@ ttyresize(int tw, int th)
|
|||
}
|
||||
|
||||
void
|
||||
ttyhangup()
|
||||
ttyhangup(void)
|
||||
{
|
||||
/* Send SIGHUP to shell */
|
||||
kill(pid, SIGHUP);
|
||||
|
@ -1906,39 +1899,28 @@ csireset(void)
|
|||
}
|
||||
|
||||
void
|
||||
osc4_color_response(int num)
|
||||
osc_color_response(int num, int index, int is_osc4)
|
||||
{
|
||||
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);
|
||||
if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) {
|
||||
fprintf(stderr, "erresc: failed to fetch %s color %d\n",
|
||||
is_osc4 ? "osc4" : "osc",
|
||||
is_osc4 ? num : index);
|
||||
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]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007",
|
||||
is_osc4 ? "4;" : "", 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);
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -1946,6 +1928,11 @@ strhandle(void)
|
|||
{
|
||||
char *p = NULL, *dec;
|
||||
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);
|
||||
strparse();
|
||||
|
@ -1980,43 +1967,22 @@ 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();
|
||||
return;
|
||||
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:
|
||||
if (narg < 2)
|
||||
break;
|
||||
|
||||
p = strescseq.args[1];
|
||||
if ((j = par - 10) < 0 || j >= LEN(osc_table))
|
||||
break; /* shouldn't be possible */
|
||||
|
||||
if (!strcmp(p, "?"))
|
||||
osc_color_response(defaultcs, 12);
|
||||
else if (xsetcolorname(defaultcs, p))
|
||||
fprintf(stderr, "erresc: invalid cursor color: %s\n", p);
|
||||
else
|
||||
redraw();
|
||||
if (!strcmp(p, "?")) {
|
||||
osc_color_response(par, osc_table[j].idx, 0);
|
||||
} else if (xsetcolorname(osc_table[j].idx, p)) {
|
||||
fprintf(stderr, "erresc: invalid %s color: %s\n",
|
||||
osc_table[j].str, p);
|
||||
} else {
|
||||
tfulldirt();
|
||||
}
|
||||
return;
|
||||
case 4: /* color set */
|
||||
if (narg < 3)
|
||||
|
@ -2026,9 +1992,9 @@ strhandle(void)
|
|||
case 104: /* color reset */
|
||||
j = (narg > 1) ? atoi(strescseq.args[1]) : -1;
|
||||
|
||||
if (p && !strcmp(p, "?"))
|
||||
osc4_color_response(j);
|
||||
else if (xsetcolorname(j, p)) {
|
||||
if (p && !strcmp(p, "?")) {
|
||||
osc_color_response(j, 0, 1);
|
||||
} 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",
|
||||
|
@ -2038,7 +2004,7 @@ strhandle(void)
|
|||
* TODO if defaultbg color is changed, borders
|
||||
* are dirty
|
||||
*/
|
||||
redraw();
|
||||
tfulldirt();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
2
st.h
2
st.h
|
@ -115,8 +115,6 @@ 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;
|
||||
|
|
1
win.h
1
win.h
|
@ -30,6 +30,7 @@ void xdrawline(Line, int, int, int);
|
|||
void xfinishdraw(void);
|
||||
void xloadcols(void);
|
||||
int xsetcolorname(int, const char *);
|
||||
int xgetcolor(int, unsigned char *, unsigned char *, unsigned char *);
|
||||
void xseticontitle(char *);
|
||||
void xsettitle(char *);
|
||||
int xsetcursor(int);
|
||||
|
|
90
x.c
90
x.c
|
@ -253,7 +253,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 */
|
||||
static int cursorblinks = 0;
|
||||
|
||||
void
|
||||
|
@ -366,61 +366,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 & Mod1Mask ) ? 8 : 0) /* meta key: alt */
|
||||
+ ((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;
|
||||
}
|
||||
|
@ -463,9 +470,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;
|
||||
|
@ -474,7 +485,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.
|
||||
|
@ -688,6 +699,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;
|
||||
|
@ -695,7 +711,7 @@ brelease(XEvent *e)
|
|||
|
||||
if (mouseaction(e, 1))
|
||||
return;
|
||||
if (e->xbutton.button == Button1)
|
||||
if (btn == Button1)
|
||||
mousesel(e, 1);
|
||||
}
|
||||
|
||||
|
@ -1479,12 +1495,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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user