]> git.immae.eu Git - perso/Immae/Config/AUR.git/blob - scrollback.patch
746b83b10a0272ea8063a416c390fe2645bb395f
[perso/Immae/Config/AUR.git] / scrollback.patch
1 diff --git a/config.def.h b/config.def.h
2 index bb5596e..2df4cbc 100644
3 --- a/config.def.h
4 +++ b/config.def.h
5 @@ -7,6 +7,7 @@
6 */
7 static char font[] = "Liberation Mono:pixelsize=12:antialias=false:autohint=false";
8 static int borderpx = 2;
9 +static int histsize = 2000;
10 static char shell[] = "/bin/sh";
11 static char *utmp = NULL;
12 static char stty_args[] = "stty raw -echo -iexten echonl";
13 @@ -128,6 +129,8 @@ static Shortcut shortcuts[] = {
14 { MODKEY|ShiftMask, XK_C, clipcopy, {.i = 0} },
15 { MODKEY|ShiftMask, XK_V, clippaste, {.i = 0} },
16 { MODKEY, XK_Num_Lock, numlock, {.i = 0} },
17 + { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} },
18 + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} },
19 };
20
21 /*
22 diff --git a/st.c b/st.c
23 index 0c6b9c3..ab56435 100644
24 --- a/st.c
25 +++ b/st.c
26 @@ -83,6 +83,8 @@ char *argv0;
27 #define TRUERED(x) (((x) & 0xff0000) >> 8)
28 #define TRUEGREEN(x) (((x) & 0xff00))
29 #define TRUEBLUE(x) (((x) & 0xff) << 8)
30 +#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term.histi - term.scr \
31 + + histsize + 1) % histsize] : term.line[(y) - term.scr])
32
33
34 enum glyph_attribute {
35 @@ -231,6 +233,9 @@ typedef struct {
36 int col; /* nb col */
37 Line *line; /* screen */
38 Line *alt; /* alternate screen */
39 + Line *hist; /* history buffer */
40 + int histi; /* history index */
41 + int scr; /* scroll back */
42 bool *dirty; /* dirtyness of lines */
43 XftGlyphFontSpec *specbuf; /* font spec buffer used for rendering */
44 TCursor c; /* cursor */
45 @@ -324,6 +329,8 @@ typedef struct {
46 /* function definitions used in config.h */
47 static void clipcopy(const Arg *);
48 static void clippaste(const Arg *);
49 +static void kscrolldown(const Arg *);
50 +static void kscrollup(const Arg *);
51 static void numlock(const Arg *);
52 static void selpaste(const Arg *);
53 static void xzoom(const Arg *);
54 @@ -395,8 +402,8 @@ static void tputtab(int);
55 static void tputc(Rune);
56 static void treset(void);
57 static void tresize(int, int);
58 -static void tscrollup(int, int);
59 -static void tscrolldown(int, int);
60 +static void tscrollup(int, int, bool);
61 +static void tscrolldown(int, int, bool);
62 static void tsetattr(int *, int);
63 static void tsetchar(Rune, Glyph *, int, int);
64 static void tsetscroll(int, int);
65 @@ -682,10 +689,10 @@ int
66 tlinelen(int y) {
67 int i = term.col;
68
69 - if(term.line[y][i - 1].mode & ATTR_WRAP)
70 + if(TLINE(y)[i - 1].mode & ATTR_WRAP)
71 return i;
72
73 - while(i > 0 && term.line[y][i - 1].u == ' ')
74 + while(i > 0 && TLINE(y)[i - 1].u == ' ')
75 --i;
76
77 return i;
78 @@ -744,7 +751,7 @@ selsnap(int *x, int *y, int direction) {
79 * Snap around if the word wraps around at the end or
80 * beginning of a line.
81 */
82 - prevgp = &term.line[*y][*x];
83 + prevgp = &TLINE(*y)[*x];
84 prevdelim = ISDELIM(prevgp->u);
85 for(;;) {
86 newx = *x + direction;
87 @@ -759,14 +766,14 @@ selsnap(int *x, int *y, int direction) {
88 yt = *y, xt = *x;
89 else
90 yt = newy, xt = newx;
91 - if(!(term.line[yt][xt].mode & ATTR_WRAP))
92 + if(!(TLINE(yt)[xt].mode & ATTR_WRAP))
93 break;
94 }
95
96 if (newx >= tlinelen(newy))
97 break;
98
99 - gp = &term.line[newy][newx];
100 + gp = &TLINE(newy)[newx];
101 delim = ISDELIM(gp->u);
102 if(!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim
103 || (delim && gp->u != prevgp->u)))
104 @@ -787,14 +794,14 @@ selsnap(int *x, int *y, int direction) {
105 *x = (direction < 0) ? 0 : term.col - 1;
106 if(direction < 0) {
107 for(; *y > 0; *y += direction) {
108 - if(!(term.line[*y-1][term.col-1].mode
109 + if(!(TLINE(*y-1)[term.col-1].mode
110 & ATTR_WRAP)) {
111 break;
112 }
113 }
114 } else if(direction > 0) {
115 for(; *y < term.row-1; *y += direction) {
116 - if(!(term.line[*y][term.col-1].mode
117 + if(!(TLINE(*y)[term.col-1].mode
118 & ATTR_WRAP)) {
119 break;
120 }
121 @@ -953,13 +960,13 @@ getsel(void) {
122 linelen = tlinelen(y);
123
124 if(sel.type == SEL_RECTANGULAR) {
125 - gp = &term.line[y][sel.nb.x];
126 + gp = &TLINE(y)[sel.nb.x];
127 lastx = sel.ne.x;
128 } else {
129 - gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0];
130 + gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0];
131 lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
132 }
133 - last = &term.line[y][MIN(lastx, linelen-1)];
134 + last = &TLINE(y)[MIN(lastx, linelen-1)];
135 while(last >= gp && last->u == ' ')
136 --last;
137
138 @@ -1362,10 +1369,16 @@ ttyread(void) {
139
140 /* keep any uncomplete utf8 char for the next call */
141 memmove(buf, ptr, buflen);
142 + if(term.scr > 0 && term.scr < histsize-1)
143 + term.scr++;
144 }
145
146 void
147 ttywrite(const char *s, size_t n) {
148 + Arg arg = (Arg){ .i = term.scr };
149 +
150 + kscrolldown(&arg);
151 +
152 if(xwrite(cmdfd, s, n) == -1)
153 die("write error on tty: %s\n", strerror(errno));
154 }
155 @@ -1500,13 +1513,52 @@ tswapscreen(void) {
156 }
157
158 void
159 -tscrolldown(int orig, int n) {
160 +kscrolldown(const Arg* a) {
161 + int n = a->i;
162 +
163 + if(n < 0)
164 + n = term.row + n;
165 +
166 + if(n > term.scr)
167 + n = term.scr;
168 +
169 + if(term.scr > 0) {
170 + term.scr -= n;
171 + selscroll(0, -n);
172 + tfulldirt();
173 + }
174 +}
175 +
176 +void
177 +kscrollup(const Arg* a) {
178 + int n = a->i;
179 +
180 + if(n < 0)
181 + n = term.row + n;
182 +
183 + if(term.scr <= histsize - n) {
184 + term.scr += n;
185 + selscroll(0, n);
186 + tfulldirt();
187 + }
188 +}
189 +
190 +void
191 +tscrolldown(int orig, int n, bool copyhist) {
192 int i;
193 Line temp;
194
195 LIMIT(n, 0, term.bot-orig+1);
196
197 + if(copyhist) {
198 + term.histi = (term.histi - 1 + histsize) % histsize;
199 + temp = term.hist[term.histi];
200 + term.hist[term.histi] = term.line[term.bot];
201 + term.line[term.bot] = temp;
202 + }
203 +
204 tsetdirt(orig, term.bot-n);
205 +
206 tclearregion(0, term.bot-n+1, term.col-1, term.bot);
207
208 for(i = term.bot; i >= orig+n; i--) {
209 @@ -1519,12 +1571,19 @@ tscrolldown(int orig, int n) {
210 }
211
212 void
213 -tscrollup(int orig, int n) {
214 +tscrollup(int orig, int n, bool copyhist) {
215 int i;
216 Line temp;
217
218 LIMIT(n, 0, term.bot-orig+1);
219
220 + if(copyhist) {
221 + term.histi = (term.histi + 1) % histsize;
222 + temp = term.hist[term.histi];
223 + term.hist[term.histi] = term.line[orig];
224 + term.line[orig] = temp;
225 + }
226 +
227 tclearregion(0, orig, term.col-1, orig+n-1);
228 tsetdirt(orig+n, term.bot);
229
230 @@ -1571,7 +1630,7 @@ tnewline(int first_col) {
231 int y = term.c.y;
232
233 if(y == term.bot) {
234 - tscrollup(term.top, 1);
235 + tscrollup(term.top, 1, true);
236 } else {
237 y++;
238 }
239 @@ -1728,13 +1787,13 @@ tinsertblank(int n) {
240 void
241 tinsertblankline(int n) {
242 if(BETWEEN(term.c.y, term.top, term.bot))
243 - tscrolldown(term.c.y, n);
244 + tscrolldown(term.c.y, n, false);
245 }
246
247 void
248 tdeleteline(int n) {
249 if(BETWEEN(term.c.y, term.top, term.bot))
250 - tscrollup(term.c.y, n);
251 + tscrollup(term.c.y, n, false);
252 }
253
254 int32_t
255 @@ -2163,11 +2222,11 @@ csihandle(void) {
256 break;
257 case 'S': /* SU -- Scroll <n> line up */
258 DEFAULT(csiescseq.arg[0], 1);
259 - tscrollup(term.top, csiescseq.arg[0]);
260 + tscrollup(term.top, csiescseq.arg[0], false);
261 break;
262 case 'T': /* SD -- Scroll <n> line down */
263 DEFAULT(csiescseq.arg[0], 1);
264 - tscrolldown(term.top, csiescseq.arg[0]);
265 + tscrolldown(term.top, csiescseq.arg[0], false);
266 break;
267 case 'L': /* IL -- Insert <n> blank lines */
268 DEFAULT(csiescseq.arg[0], 1);
269 @@ -2617,7 +2676,7 @@ eschandle(uchar ascii) {
270 return 0;
271 case 'D': /* IND -- Linefeed */
272 if(term.c.y == term.bot) {
273 - tscrollup(term.top, 1);
274 + tscrollup(term.top, 1, true);
275 } else {
276 tmoveto(term.c.x, term.c.y+1);
277 }
278 @@ -2630,7 +2689,7 @@ eschandle(uchar ascii) {
279 break;
280 case 'M': /* RI -- Reverse index */
281 if(term.c.y == term.top) {
282 - tscrolldown(term.top, 1);
283 + tscrolldown(term.top, 1, true);
284 } else {
285 tmoveto(term.c.x, term.c.y-1);
286 }
287 @@ -2791,7 +2850,7 @@ tputc(Rune u) {
288
289 void
290 tresize(int col, int row) {
291 - int i;
292 + int i, j;
293 int minrow = MIN(row, term.row);
294 int mincol = MIN(col, term.col);
295 bool *bp;
296 @@ -2828,9 +2887,18 @@ tresize(int col, int row) {
297 /* resize to new height */
298 term.line = xrealloc(term.line, row * sizeof(Line));
299 term.alt = xrealloc(term.alt, row * sizeof(Line));
300 + term.hist = xrealloc(term.hist, histsize * sizeof(Line));
301 term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
302 term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
303
304 + for(i = 0; i < histsize; i++) {
305 + term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyph));
306 + for(j = mincol; j < col; j++) {
307 + term.hist[i][j] = term.c.attr;
308 + term.hist[i][j].u = ' ';
309 + }
310 + }
311 +
312 /* resize each row to new width, zero-pad if needed */
313 for(i = 0; i < minrow; i++) {
314 term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph));
315 @@ -3664,11 +3732,11 @@ drawregion(int x1, int y1, int x2, int y2) {
316 term.dirty[y] = 0;
317
318 specs = term.specbuf;
319 - numspecs = xmakeglyphfontspecs(specs, &term.line[y][x1], x2 - x1, x1, y);
320 + numspecs = xmakeglyphfontspecs(specs, &TLINE(y)[x1], x2 - x1, x1, y);
321
322 i = ox = 0;
323 for(x = x1; x < x2 && i < numspecs; x++) {
324 - new = term.line[y][x];
325 + new = TLINE(y)[x];
326 if(new.mode == ATTR_WDUMMY)
327 continue;
328 if(ena_sel && selected(x, y))
329 @@ -3688,7 +3756,8 @@ drawregion(int x1, int y1, int x2, int y2) {
330 if(i > 0)
331 xdrawglyphfontspecs(specs, base, i, ox, y);
332 }
333 - xdrawcursor();
334 + if(term.scr == 0)
335 + xdrawcursor();
336 }
337
338 void