Compare commits

...

13 Commits

Author SHA1 Message Date
Ryan 5eb745581e
cleanup config.def.h
Few small tweaks to variable naming and such.
2024-12-03 11:11:04 -05:00
Ryan fec6ec3257
make the zoomrate configurable
This commit makes the rate that st zooms configurable.
2024-12-03 11:11:04 -05:00
Ryan 057ec62950
apply external-pipe-eternal patch
Makes it work with scrollback.
2024-12-03 11:11:04 -05:00
Ryan ed7be6b51b
apply externalpipe patch 2024-12-03 11:11:04 -05:00
Ryan bd6d10b904
apply blinking_cursor patch
Tweak the Xresources loading to use the new variable.
2024-12-03 11:11:04 -05:00
Ryan c5eb9851a9
apply xclearwin patch 2024-12-03 11:11:04 -05:00
Ryan c0bdced263
apply scrollback-mouse-increment patch
Tweak the config to be a bit better organized.
2024-12-03 11:11:04 -05:00
Ryan 2cd815077c
apply scrollback-mouse-altscreen patch
This makes the mouse wheel work for both normal scrolling and
altscreens such as less or vim.
2024-12-03 11:11:04 -05:00
Ryan 04f516b05e
apply scrollback-mouse patch
Just updates the config, kinda unnecessary.
2024-12-03 11:11:04 -05:00
Ryan 660100a961
apply scrollback-reflow patch
This patch makes text reflow like a real terminal.
2024-12-03 11:11:00 -05:00
Ryan 33885fc9d1
apply scrollback patch 2024-12-03 11:09:21 -05:00
Ryan 04e9641e17
apply dynamic-cursor-color patch
Makes the cursor match the underlying text. Very pretty.
2024-12-03 11:09:21 -05:00
Ryan 0a8ec7d442
apply anysize patch
This patch causes the terminal to fill its window manager slot versus
snapping to a multiple of the character width/height.
2024-12-03 11:09:21 -05:00
5 changed files with 893 additions and 318 deletions

View File

@ -135,13 +135,20 @@ unsigned int defaultcs = 256;
static unsigned int defaultrcs = 257;
/*
* Default shape of cursor
* 2: Block ("")
* 4: Underline ("_")
* 6: Bar ("|")
* 7: Snowman ("")
* https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Functions-using-CSI-_-ordered-by-the-final-character-lparen-s-rparen:CSI-Ps-SP-q.1D81
* Default style of cursor
* 0: blinking block
* 1: blinking block (default)
* 2: steady block ("")
* 3: blinking underline
* 4: steady underline ("_")
* 5: blinking bar
* 6: steady bar ("|")
* 7: blinking st cursor
* 8: steady st cursor
*/
static unsigned int cursorshape = 2;
static unsigned int cursorstyle = 1;
static Rune stcursor = 0x2603; /* snowman ("☃") */
/*
* Default columns and rows numbers
@ -170,12 +177,24 @@ static unsigned int defaultattr = 11;
*/
static uint forcemousemod = ShiftMask;
/*
* The number of lines to scroll by.
*/
const unsigned int scrollrate = 1;
/*
* The rate to zoom in (adjust the font size).
*/
const unsigned int zoomrate = 1;
/*
* Internal mouse shortcuts.
* Beware that overloading Button1 will disable the selection.
*/
static MouseShortcut mshortcuts[] = {
/* mask button function argument release */
{ XK_ANY_MOD, Button4, kscrollup, {.i = scrollrate}, 0, /* !alt */ -1 },
{ XK_ANY_MOD, Button5, kscrolldown, {.i = scrollrate}, 0, /* !alt */ -1 },
{ XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 },
{ ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} },
{ XK_ANY_MOD, Button4, ttysend, {.s = "\031"} },
@ -193,14 +212,16 @@ 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} },
{ TERMMOD, XK_Prior, zoom, {.f = +1 * zoomrate} },
{ TERMMOD, XK_Next, zoom, {.f = -1 * zoomrate} },
{ 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} },
{ ShiftMask, XK_Page_Up, kscrollup, {.i = -1 * scrollrate} },
{ ShiftMask, XK_Page_Down, kscrolldown, {.i = -1 * scrollrate} },
};
/*

1014
st.c

File diff suppressed because it is too large Load Diff

29
st.h
View File

@ -22,17 +22,19 @@
enum glyph_attribute {
ATTR_NULL = 0,
ATTR_BOLD = 1 << 0,
ATTR_FAINT = 1 << 1,
ATTR_ITALIC = 1 << 2,
ATTR_UNDERLINE = 1 << 3,
ATTR_BLINK = 1 << 4,
ATTR_REVERSE = 1 << 5,
ATTR_INVISIBLE = 1 << 6,
ATTR_STRUCK = 1 << 7,
ATTR_WRAP = 1 << 8,
ATTR_WIDE = 1 << 9,
ATTR_WDUMMY = 1 << 10,
ATTR_SET = 1 << 0,
ATTR_BOLD = 1 << 1,
ATTR_FAINT = 1 << 2,
ATTR_ITALIC = 1 << 3,
ATTR_UNDERLINE = 1 << 4,
ATTR_BLINK = 1 << 5,
ATTR_REVERSE = 1 << 6,
ATTR_INVISIBLE = 1 << 7,
ATTR_STRUCK = 1 << 8,
ATTR_WRAP = 1 << 9,
ATTR_WIDE = 1 << 10,
ATTR_WDUMMY = 1 << 11,
ATTR_SELECTED = 1 << 12,
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
};
@ -81,13 +83,18 @@ void die(const char *, ...);
void redraw(void);
void draw(void);
void kscrolldown(const Arg *);
void kscrollup(const Arg *);
void externalpipe(const Arg *);
void printscreen(const Arg *);
void printsel(const Arg *);
void sendbreak(const Arg *);
void toggleprinter(const Arg *);
int tattrset(int);
int tisaltscr(void);
void tnew(int, int);
int tisaltscreen(void);
void tresize(int, int);
void tsetdirtattr(int);
void ttyhangup(void);

1
win.h
View File

@ -39,3 +39,4 @@ void xsetpointermotion(int);
void xsetsel(char *);
int xstartdraw(void);
void xximspot(int, int);
void xclearwin(void);

130
x.c
View File

@ -34,6 +34,7 @@ typedef struct {
void (*func)(const Arg *);
const Arg arg;
uint release;
int altscrn; /* 0: don't care, -1: not alt screen, 1: alt screen */
} MouseShortcut;
typedef struct {
@ -81,6 +82,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 */
@ -253,6 +255,7 @@ static char *opt_name = NULL;
static char *opt_title = NULL;
static uint buttons; /* bit field of pressed buttons */
static int cursorblinks = 0;
void
clipcopy(const Arg *dummy)
@ -331,7 +334,7 @@ ttysend(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;
}
@ -339,7 +342,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;
}
@ -455,6 +458,7 @@ mouseaction(XEvent *e, uint release)
for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) {
if (ms->release == release &&
ms->button == e->xbutton.button &&
(!ms->altscrn || (ms->altscrn == (tisaltscr() ? 1 : -1))) &&
(match(ms->mod, state) || /* exact or forced */
match(ms->mod, state & ~forcemousemod))) {
ms->func(&(ms->arg));
@ -739,6 +743,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);
@ -856,6 +863,12 @@ xclear(int x1, int y1, int x2, int y2)
x1, y1, x2-x1, y2-y1);
}
void
xclearwin(void)
{
xclear(0, 0, win.w, win.h);
}
void
xhints(void)
{
@ -869,8 +882,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;
@ -1152,8 +1165,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 + 2 * borderpx + cols * win.cw;
win.h = 2 * win.vborderpx + 2 * borderpx + rows * win.ch;
if (xw.gm & XNegative)
xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2;
if (xw.gm & YNegative)
@ -1245,7 +1258,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;
@ -1378,7 +1391,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;
@ -1468,17 +1481,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.hborderpx,
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.vborderpx);
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. */
@ -1523,6 +1536,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))
@ -1551,56 +1565,81 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og)
if (selected(cx, cy)) {
g.fg = defaultfg;
g.bg = defaultrcs;
} else {
g.fg = defaultbg;
g.bg = defaultcs;
} 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 {
drawcol = dc.col[g.bg];
}
drawcol = dc.col[g.bg];
}
/* draw the new one */
if (IS_SET(MODE_FOCUSED)) {
switch (win.cursor) {
case 7: /* st extension */
g.u = 0x2603; /* snowman (U+2603) */
default:
case 0: /* blinking block */
case 1: /* blinking block (default) */
if (IS_SET(MODE_BLINK))
break;
/* FALLTHROUGH */
case 0: /* Blinking Block */
case 1: /* Blinking Block (Default) */
case 2: /* Steady Block */
case 2: /* steady block */
xdrawglyph(g, cx, cy);
break;
case 3: /* Blinking Underline */
case 4: /* Steady Underline */
case 3: /* blinking underline */
if (IS_SET(MODE_BLINK))
break;
/* FALLTHROUGH */
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 */
case 5: /* blinking bar */
if (IS_SET(MODE_BLINK))
break;
/* FALLTHROUGH */
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;
case 7: /* blinking st cursor */
if (IS_SET(MODE_BLINK))
break;
/* FALLTHROUGH */
case 8: /* steady st cursor */
g.u = stcursor;
xdrawglyph(g, cx, cy);
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);
}
}
@ -1746,9 +1785,12 @@ xsetmode(int set, unsigned int flags)
int
xsetcursor(int cursor)
{
if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */
if (!BETWEEN(cursor, 0, 8)) /* 7-8: st extensions */
return 1;
win.cursor = cursor;
cursorblinks = win.cursor == 0 || win.cursor == 1 ||
win.cursor == 3 || win.cursor == 5 ||
win.cursor == 7;
return 0;
}
@ -1995,6 +2037,10 @@ run(void)
if (FD_ISSET(ttyfd, &rfd) || xev) {
if (!drawing) {
trigger = now;
if (IS_SET(MODE_BLINK)) {
win.mode ^= MODE_BLINK;
}
lastblink = now;
drawing = 1;
}
timeout = (maxlatency - TIMEDIFF(now, trigger)) \
@ -2005,7 +2051,7 @@ run(void)
/* idle detected or maxlatency exhausted -> draw */
timeout = -1;
if (blinktimeout && tattrset(ATTR_BLINK)) {
if (blinktimeout && (cursorblinks || tattrset(ATTR_BLINK))) {
timeout = blinktimeout - TIMEDIFF(now, lastblink);
if (timeout <= 0) {
if (-timeout > blinktimeout) /* start visible */
@ -2041,7 +2087,7 @@ main(int argc, char *argv[])
{
xw.l = xw.t = 0;
xw.isfixed = False;
xsetcursor(cursorshape);
xsetcursor(cursorstyle);
ARGBEGIN {
case 'a':