st-scrollback-0.9.2.diff - sites - public wiki contents of suckless.org | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
st-scrollback-0.9.2.diff (8955B) | |
--- | |
1 diff --git a/config.def.h b/config.def.h | |
2 index 2cd740a..40b7d93 100644 | |
3 --- a/config.def.h | |
4 +++ b/config.def.h | |
5 @@ -201,6 +201,8 @@ static Shortcut shortcuts[] = { | |
6 { TERMMOD, XK_Y, selpaste, {.i = … | |
7 { ShiftMask, XK_Insert, selpaste, {.i = … | |
8 { TERMMOD, XK_Num_Lock, numlock, {.i = … | |
9 + { ShiftMask, XK_Page_Up, kscrollup, {.i = -… | |
10 + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, | |
11 }; | |
12 | |
13 /* | |
14 diff --git a/st.c b/st.c | |
15 index b9f66e7..2478942 100644 | |
16 --- a/st.c | |
17 +++ b/st.c | |
18 @@ -35,6 +35,7 @@ | |
19 #define ESC_ARG_SIZ 16 | |
20 #define STR_BUF_SIZ ESC_BUF_SIZ | |
21 #define STR_ARG_SIZ ESC_ARG_SIZ | |
22 +#define HISTSIZE 2000 | |
23 | |
24 /* macros */ | |
25 #define IS_SET(flag) ((term.mode & (flag)) != 0) | |
26 @@ -42,6 +43,9 @@ | |
27 #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) | |
28 #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) | |
29 #define ISDELIM(u) (u && wcschr(worddelimiters, u)) | |
30 +#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term… | |
31 + term.scr + HISTSIZE + 1) % HISTSIZE] : \ | |
32 + term.line[(y) - term.scr]) | |
33 | |
34 enum term_mode { | |
35 MODE_WRAP = 1 << 0, | |
36 @@ -115,6 +119,9 @@ typedef struct { | |
37 int col; /* nb col */ | |
38 Line *line; /* screen */ | |
39 Line *alt; /* alternate screen */ | |
40 + Line hist[HISTSIZE]; /* history buffer */ | |
41 + int histi; /* history index */ | |
42 + int scr; /* scroll back */ | |
43 int *dirty; /* dirtyness of lines */ | |
44 TCursor c; /* cursor */ | |
45 int ocx; /* old cursor col */ | |
46 @@ -185,8 +192,8 @@ static void tnewline(int); | |
47 static void tputtab(int); | |
48 static void tputc(Rune); | |
49 static void treset(void); | |
50 -static void tscrollup(int, int); | |
51 -static void tscrolldown(int, int); | |
52 +static void tscrollup(int, int, int); | |
53 +static void tscrolldown(int, int, int); | |
54 static void tsetattr(const int *, int); | |
55 static void tsetchar(Rune, const Glyph *, int, int); | |
56 static void tsetdirt(int, int); | |
57 @@ -409,10 +416,10 @@ tlinelen(int y) | |
58 { | |
59 int i = term.col; | |
60 | |
61 - if (term.line[y][i - 1].mode & ATTR_WRAP) | |
62 + if (TLINE(y)[i - 1].mode & ATTR_WRAP) | |
63 return i; | |
64 | |
65 - while (i > 0 && term.line[y][i - 1].u == ' ') | |
66 + while (i > 0 && TLINE(y)[i - 1].u == ' ') | |
67 --i; | |
68 | |
69 return i; | |
70 @@ -521,7 +528,7 @@ selsnap(int *x, int *y, int direction) | |
71 * Snap around if the word wraps around at the end or | |
72 * beginning of a line. | |
73 */ | |
74 - prevgp = &term.line[*y][*x]; | |
75 + prevgp = &TLINE(*y)[*x]; | |
76 prevdelim = ISDELIM(prevgp->u); | |
77 for (;;) { | |
78 newx = *x + direction; | |
79 @@ -536,14 +543,14 @@ selsnap(int *x, int *y, int direction) | |
80 yt = *y, xt = *x; | |
81 else | |
82 yt = newy, xt = newx; | |
83 - if (!(term.line[yt][xt].mode & ATTR_WRA… | |
84 + if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) | |
85 break; | |
86 } | |
87 | |
88 if (newx >= tlinelen(newy)) | |
89 break; | |
90 | |
91 - gp = &term.line[newy][newx]; | |
92 + gp = &TLINE(newy)[newx]; | |
93 delim = ISDELIM(gp->u); | |
94 if (!(gp->mode & ATTR_WDUMMY) && (delim != prev… | |
95 || (delim && gp->u != prevgp->u… | |
96 @@ -564,14 +571,14 @@ selsnap(int *x, int *y, int direction) | |
97 *x = (direction < 0) ? 0 : term.col - 1; | |
98 if (direction < 0) { | |
99 for (; *y > 0; *y += direction) { | |
100 - if (!(term.line[*y-1][term.col-1].mode | |
101 + if (!(TLINE(*y-1)[term.col-1].mode | |
102 & ATTR_WRAP)) { | |
103 break; | |
104 } | |
105 } | |
106 } else if (direction > 0) { | |
107 for (; *y < term.row-1; *y += direction) { | |
108 - if (!(term.line[*y][term.col-1].mode | |
109 + if (!(TLINE(*y)[term.col-1].mode | |
110 & ATTR_WRAP)) { | |
111 break; | |
112 } | |
113 @@ -602,13 +609,13 @@ getsel(void) | |
114 } | |
115 | |
116 if (sel.type == SEL_RECTANGULAR) { | |
117 - gp = &term.line[y][sel.nb.x]; | |
118 + gp = &TLINE(y)[sel.nb.x]; | |
119 lastx = sel.ne.x; | |
120 } else { | |
121 - gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0… | |
122 + gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0]; | |
123 lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; | |
124 } | |
125 - last = &term.line[y][MIN(lastx, linelen-1)]; | |
126 + last = &TLINE(y)[MIN(lastx, linelen-1)]; | |
127 while (last >= gp && last->u == ' ') | |
128 --last; | |
129 | |
130 @@ -844,6 +851,9 @@ void | |
131 ttywrite(const char *s, size_t n, int may_echo) | |
132 { | |
133 const char *next; | |
134 + Arg arg = (Arg) { .i = term.scr }; | |
135 + | |
136 + kscrolldown(&arg); | |
137 | |
138 if (may_echo && IS_SET(MODE_ECHO)) | |
139 twrite(s, n, 1); | |
140 @@ -1055,13 +1065,53 @@ tswapscreen(void) | |
141 } | |
142 | |
143 void | |
144 -tscrolldown(int orig, int n) | |
145 +kscrolldown(const Arg* a) | |
146 +{ | |
147 + int n = a->i; | |
148 + | |
149 + if (n < 0) | |
150 + n = term.row + n; | |
151 + | |
152 + if (n > term.scr) | |
153 + n = term.scr; | |
154 + | |
155 + if (term.scr > 0) { | |
156 + term.scr -= n; | |
157 + selscroll(0, -n); | |
158 + tfulldirt(); | |
159 + } | |
160 +} | |
161 + | |
162 +void | |
163 +kscrollup(const Arg* a) | |
164 +{ | |
165 + int n = a->i; | |
166 + | |
167 + if (n < 0) | |
168 + n = term.row + n; | |
169 + | |
170 + if (term.scr <= HISTSIZE-n) { | |
171 + term.scr += n; | |
172 + selscroll(0, n); | |
173 + tfulldirt(); | |
174 + } | |
175 +} | |
176 + | |
177 +void | |
178 +tscrolldown(int orig, int n, int copyhist) | |
179 { | |
180 int i; | |
181 Line temp; | |
182 | |
183 LIMIT(n, 0, term.bot-orig+1); | |
184 | |
185 + if (copyhist) { | |
186 + term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; | |
187 + temp = term.hist[term.histi]; | |
188 + term.hist[term.histi] = term.line[term.bot]; | |
189 + term.line[term.bot] = temp; | |
190 + } | |
191 + | |
192 tsetdirt(orig, term.bot-n); | |
193 tclearregion(0, term.bot-n+1, term.col-1, term.bot); | |
194 | |
195 @@ -1071,17 +1121,28 @@ tscrolldown(int orig, int n) | |
196 term.line[i-n] = temp; | |
197 } | |
198 | |
199 - selscroll(orig, n); | |
200 + if (term.scr == 0) | |
201 + selscroll(orig, n); | |
202 } | |
203 | |
204 void | |
205 -tscrollup(int orig, int n) | |
206 +tscrollup(int orig, int n, int copyhist) | |
207 { | |
208 int i; | |
209 Line temp; | |
210 | |
211 LIMIT(n, 0, term.bot-orig+1); | |
212 | |
213 + if (copyhist) { | |
214 + term.histi = (term.histi + 1) % HISTSIZE; | |
215 + temp = term.hist[term.histi]; | |
216 + term.hist[term.histi] = term.line[orig]; | |
217 + term.line[orig] = temp; | |
218 + } | |
219 + | |
220 + if (term.scr > 0 && term.scr < HISTSIZE) | |
221 + term.scr = MIN(term.scr + n, HISTSIZE-1); | |
222 + | |
223 tclearregion(0, orig, term.col-1, orig+n-1); | |
224 tsetdirt(orig+n, term.bot); | |
225 | |
226 @@ -1091,7 +1152,8 @@ tscrollup(int orig, int n) | |
227 term.line[i+n] = temp; | |
228 } | |
229 | |
230 - selscroll(orig, -n); | |
231 + if (term.scr == 0) | |
232 + selscroll(orig, -n); | |
233 } | |
234 | |
235 void | |
236 @@ -1120,7 +1182,7 @@ tnewline(int first_col) | |
237 int y = term.c.y; | |
238 | |
239 if (y == term.bot) { | |
240 - tscrollup(term.top, 1); | |
241 + tscrollup(term.top, 1, 1); | |
242 } else { | |
243 y++; | |
244 } | |
245 @@ -1285,14 +1347,14 @@ void | |
246 tinsertblankline(int n) | |
247 { | |
248 if (BETWEEN(term.c.y, term.top, term.bot)) | |
249 - tscrolldown(term.c.y, n); | |
250 + tscrolldown(term.c.y, n, 0); | |
251 } | |
252 | |
253 void | |
254 tdeleteline(int n) | |
255 { | |
256 if (BETWEEN(term.c.y, term.top, term.bot)) | |
257 - tscrollup(term.c.y, n); | |
258 + tscrollup(term.c.y, n, 0); | |
259 } | |
260 | |
261 int32_t | |
262 @@ -1730,11 +1792,11 @@ csihandle(void) | |
263 case 'S': /* SU -- Scroll <n> line up */ | |
264 if (csiescseq.priv) break; | |
265 DEFAULT(csiescseq.arg[0], 1); | |
266 - tscrollup(term.top, csiescseq.arg[0]); | |
267 + tscrollup(term.top, csiescseq.arg[0], 0); | |
268 break; | |
269 case 'T': /* SD -- Scroll <n> line down */ | |
270 DEFAULT(csiescseq.arg[0], 1); | |
271 - tscrolldown(term.top, csiescseq.arg[0]); | |
272 + tscrolldown(term.top, csiescseq.arg[0], 0); | |
273 break; | |
274 case 'L': /* IL -- Insert <n> blank lines */ | |
275 DEFAULT(csiescseq.arg[0], 1); | |
276 @@ -2306,7 +2368,7 @@ eschandle(uchar ascii) | |
277 return 0; | |
278 case 'D': /* IND -- Linefeed */ | |
279 if (term.c.y == term.bot) { | |
280 - tscrollup(term.top, 1); | |
281 + tscrollup(term.top, 1, 1); | |
282 } else { | |
283 tmoveto(term.c.x, term.c.y+1); | |
284 } | |
285 @@ -2319,7 +2381,7 @@ eschandle(uchar ascii) | |
286 break; | |
287 case 'M': /* RI -- Reverse index */ | |
288 if (term.c.y == term.top) { | |
289 - tscrolldown(term.top, 1); | |
290 + tscrolldown(term.top, 1, 1); | |
291 } else { | |
292 tmoveto(term.c.x, term.c.y-1); | |
293 } | |
294 @@ -2542,7 +2604,7 @@ twrite(const char *buf, int buflen, int show_ctrl) | |
295 void | |
296 tresize(int col, int row) | |
297 { | |
298 - int i; | |
299 + int i, j; | |
300 int minrow = MIN(row, term.row); | |
301 int mincol = MIN(col, term.col); | |
302 int *bp; | |
303 @@ -2579,6 +2641,14 @@ tresize(int col, int row) | |
304 term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); | |
305 term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); | |
306 | |
307 + for (i = 0; i < HISTSIZE; i++) { | |
308 + term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyp… | |
309 + for (j = mincol; j < col; j++) { | |
310 + term.hist[i][j] = term.c.attr; | |
311 + term.hist[i][j].u = ' '; | |
312 + } | |
313 + } | |
314 + | |
315 /* resize each row to new width, zero-pad if needed */ | |
316 for (i = 0; i < minrow; i++) { | |
317 term.line[i] = xrealloc(term.line[i], col * sizeof(Glyp… | |
318 @@ -2637,7 +2707,7 @@ drawregion(int x1, int y1, int x2, int y2) | |
319 continue; | |
320 | |
321 term.dirty[y] = 0; | |
322 - xdrawline(term.line[y], x1, y, x2); | |
323 + xdrawline(TLINE(y), x1, y, x2); | |
324 } | |
325 } | |
326 | |
327 @@ -2658,8 +2728,9 @@ draw(void) | |
328 cx--; | |
329 | |
330 drawregion(0, 0, term.col, term.row); | |
331 - xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], | |
332 - term.ocx, term.ocy, term.line[term.ocy][term.oc… | |
333 + if (term.scr == 0) | |
334 + xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], | |
335 + term.ocx, term.ocy, term.line[term.ocy]… | |
336 term.ocx = cx; | |
337 term.ocy = term.c.y; | |
338 xfinishdraw(); | |
339 diff --git a/st.h b/st.h | |
340 index fd3b0d8..818a6f8 100644 | |
341 --- a/st.h | |
342 +++ b/st.h | |
343 @@ -81,6 +81,8 @@ void die(const char *, ...); | |
344 void redraw(void); | |
345 void draw(void); | |
346 | |
347 +void kscrolldown(const Arg *); | |
348 +void kscrollup(const Arg *); | |
349 void printscreen(const Arg *); | |
350 void printsel(const Arg *); | |
351 void sendbreak(const Arg *); |