st horizontal scrollback feature

This commit is contained in:
2025-09-20 18:50:59 +02:00
parent 57a4b03eab
commit 09aba35516
3 changed files with 90 additions and 4 deletions

View File

@@ -275,6 +275,10 @@ static Shortcut shortcuts[] = {
{ MODKEY, XK_Down, kscrolldown, {.i = 1} },
{ MODKEY, XK_u, kscrollup, {.i = -1} },
{ MODKEY, XK_d, kscrolldown, {.i = -1} },
{ MODKEY|ShiftMask, XK_h, hscrollright, {.i = 1} },
{ MODKEY|ShiftMask, XK_l, hscrollleft, {.i = 1} },
{ MODKEY|ShiftMask, XK_Left, hscrollright, {.i = 1} },
{ MODKEY|ShiftMask, XK_Right, hscrollleft, {.i = 1} },
{ MODKEY, XK_s, changealpha, {.f = -0.05} },
{ MODKEY, XK_a, changealpha, {.f = +0.05} },
{ TERMMOD, XK_Up, zoom, {.f = +1} },

88
st.c
View File

@@ -126,6 +126,9 @@ typedef struct {
Line hist[HISTSIZE]; /* history buffer */
int histi; /* history index */
int scr; /* scroll back */
int hscr; /* horizontal scroll offset */
int *linelen; /* actual length of each line */
int *histlen; /* actual length of each history line */
int *dirty; /* dirtyness of lines */
TCursor c; /* cursor */
int ocx; /* old cursor col */
@@ -1288,6 +1291,52 @@ kscrollup(const Arg* a)
}
}
void
hscrollleft(const Arg* a)
{
int n = a->i;
int maxscroll = 0;
int i;
if (n < 0)
n = term.col + n;
/* find maximum horizontal scroll based on line lengths */
if (term.scr == 0) {
/* scrolling current screen */
for (i = 0; i < term.row; i++) {
if (term.linelen[i] > maxscroll)
maxscroll = term.linelen[i];
}
} else {
/* scrolling history */
for (i = 0; i < HISTSIZE; i++) {
if (term.histlen[i] > maxscroll)
maxscroll = term.histlen[i];
}
}
maxscroll = MAX(0, maxscroll - term.col);
if (term.hscr < maxscroll) {
term.hscr = MIN(term.hscr + n, maxscroll);
tfulldirt();
}
}
void
hscrollright(const Arg* a)
{
int n = a->i;
if (n < 0)
n = term.col + n;
if (term.hscr > 0) {
term.hscr = MAX(0, term.hscr - n);
tfulldirt();
}
}
void
tscrolldown(int orig, int n, int copyhist)
{
@@ -1469,6 +1518,10 @@ tsetchar(Rune u, const Glyph *attr, int x, int y)
term.line[y][x] = *attr;
term.line[y][x].u = u;
/* update line length tracking */
if (x + 1 > term.linelen[y])
term.linelen[y] = x + 1;
if (isboxdraw(u))
term.line[y][x].mode |= ATTR_BOXDRAW;
}
@@ -2882,18 +2935,25 @@ tresize(int col, int row)
term.alt = xrealloc(term.alt, row * sizeof(Line));
term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
term.linelen = xrealloc(term.linelen, row * sizeof(*term.linelen));
term.histlen = xrealloc(term.histlen, HISTSIZE * sizeof(*term.histlen));
/* preserve history line lengths and resize history buffer */
for (i = 0; i < HISTSIZE; i++) {
term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph));
if (!term.histlen[i])
term.histlen[i] = term.maxcol;
term.hist[i] = xrealloc(term.hist[i], MAX(col, term.histlen[i]) * sizeof(Glyph));
for (j = mincol; j < col; j++) {
term.hist[i][j] = term.c.attr;
term.hist[i][j].u = ' ';
}
}
/* resize each row to new width, zero-pad if needed */
/* resize each row to new width, preserve line lengths */
for (i = 0; i < minrow; i++) {
term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph));
if (!term.linelen[i])
term.linelen[i] = term.maxcol;
term.line[i] = xrealloc(term.line[i], MAX(col, term.linelen[i]) * sizeof(Glyph));
term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyph));
}
@@ -2901,6 +2961,7 @@ tresize(int col, int row)
for (/* i = minrow */; i < row; i++) {
term.line[i] = xmalloc(col * sizeof(Glyph));
term.alt[i] = xmalloc(col * sizeof(Glyph));
term.linelen[i] = col;
}
if (col > term.maxcol) {
bp = term.tabs + term.maxcol;
@@ -2944,13 +3005,32 @@ void
drawregion(int x1, int y1, int x2, int y2)
{
int y;
Line line;
int hx1, hx2, linelen;
for (y = y1; y < y2; y++) {
if (!term.dirty[y])
continue;
term.dirty[y] = 0;
xdrawline(TLINE(y), x1, y, x2);
line = TLINE(y);
/* get line length based on whether we're in history or current screen */
if (y < term.scr) {
/* history line */
int histidx = ((y + term.histi - term.scr + HISTSIZE + 1) % HISTSIZE);
linelen = term.histlen[histidx];
} else {
/* current screen line */
linelen = term.linelen[y - term.scr];
}
/* apply horizontal scroll offset */
if (term.hscr >= linelen)
continue;
/* draw from horizontally scrolled position */
xdrawline(&line[term.hscr], x1, y, MIN(x2, linelen - term.hscr));
}
}

2
st.h
View File

@@ -88,6 +88,8 @@ void draw(void);
void externalpipe(const Arg *);
void kscrolldown(const Arg *);
void kscrollup(const Arg *);
void hscrollleft(const Arg *);
void hscrollright(const Arg *);
void newterm(const Arg *);
void printscreen(const Arg *);