Introduction
Introduction Statistics Contact Development Disclaimer Help
st-scrollback-ringbuffer-0.8.5.diff - sites - public wiki contents of suckless.…
git clone git://git.suckless.org/sites
Log
Files
Refs
---
st-scrollback-ringbuffer-0.8.5.diff (19546B)
---
1 commit 0663bdf11a409961da5b1120741a69814da8ce65
2 Author: Timo Röhling <[email protected]>
3 Date: Tue Nov 23 19:45:33 2021 +0100
4
5 Terminal scrollback with ring buffer
6
7 This patch adds a ring buffer for scrollback to the terminal. The
8 advantage of using a ring buffer is that the common case, scrolling …
9 no static screen content, can be achieved very efficiently by
10 incrementing and decrementing the starting line (modulo buffer size).
11
12 The scrollback buffer is limited to HISTSIZE lines in order to bound
13 memory usage. As the lines are allocated on demand, it is possible to
14 implement unlimited scrollback with few changes. If the terminal is
15 reset, the scroll back buffer is reset, too.
16
17 diff --git a/config.def.h b/config.def.h
18 index 91ab8ca..e3b469b 100644
19 --- a/config.def.h
20 +++ b/config.def.h
21 @@ -201,6 +201,8 @@ static Shortcut shortcuts[] = {
22 { TERMMOD, XK_Y, selpaste, {.i = …
23 { ShiftMask, XK_Insert, selpaste, {.i = …
24 { TERMMOD, XK_Num_Lock, numlock, {.i = …
25 + { ShiftMask, XK_Page_Up, kscrollup, {.i = -…
26 + { ShiftMask, XK_Page_Down, kscrolldown, {.i = -…
27 };
28
29 /*
30 diff --git a/st.c b/st.c
31 index 51049ba..f9e24ba 100644
32 --- a/st.c
33 +++ b/st.c
34 @@ -43,6 +43,10 @@
35 #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c))
36 #define ISDELIM(u) (u && wcschr(worddelimiters, u))
37
38 +#define TSCREEN term.screen[IS_SET(MODE_ALTSCREEN)]
39 +#define TLINEOFFSET(y) (((y) + TSCREEN.cur - TSCREEN.off + TSCREEN.size…
40 +#define TLINE(y) (TSCREEN.buffer[TLINEOFFSET(y)])
41 +
42 enum term_mode {
43 MODE_WRAP = 1 << 0,
44 MODE_INSERT = 1 << 1,
45 @@ -109,12 +113,21 @@ typedef struct {
46 int alt;
47 } Selection;
48
49 +/* Screen lines */
50 +typedef struct {
51 + Line* buffer; /* ring buffer */
52 + int size; /* size of buffer */
53 + int cur; /* start of active screen */
54 + int off; /* scrollback line offset */
55 + TCursor sc; /* saved cursor */
56 +} LineBuffer;
57 +
58 /* Internal representation of the screen */
59 typedef struct {
60 int row; /* nb row */
61 int col; /* nb col */
62 - Line *line; /* screen */
63 - Line *alt; /* alternate screen */
64 + LineBuffer screen[2]; /* screen and alternate screen */
65 + int linelen; /* allocated line length */
66 int *dirty; /* dirtyness of lines */
67 TCursor c; /* cursor */
68 int ocx; /* old cursor col */
69 @@ -202,6 +215,8 @@ static void tdeftran(char);
70 static void tstrsequence(uchar);
71
72 static void drawregion(int, int, int, int);
73 +static void clearline(Line, Glyph, int, int);
74 +static Line ensureline(Line);
75
76 static void selnormalize(void);
77 static void selscroll(int, int);
78 @@ -415,11 +430,12 @@ int
79 tlinelen(int y)
80 {
81 int i = term.col;
82 + Line line = TLINE(y);
83
84 - if (term.line[y][i - 1].mode & ATTR_WRAP)
85 + if (line[i - 1].mode & ATTR_WRAP)
86 return i;
87
88 - while (i > 0 && term.line[y][i - 1].u == ' ')
89 + while (i > 0 && line[i - 1].u == ' ')
90 --i;
91
92 return i;
93 @@ -528,7 +544,7 @@ selsnap(int *x, int *y, int direction)
94 * Snap around if the word wraps around at the end or
95 * beginning of a line.
96 */
97 - prevgp = &term.line[*y][*x];
98 + prevgp = &TLINE(*y)[*x];
99 prevdelim = ISDELIM(prevgp->u);
100 for (;;) {
101 newx = *x + direction;
102 @@ -543,14 +559,14 @@ selsnap(int *x, int *y, int direction)
103 yt = *y, xt = *x;
104 else
105 yt = newy, xt = newx;
106 - if (!(term.line[yt][xt].mode & ATTR_WRA…
107 + if (!(TLINE(yt)[xt].mode & ATTR_WRAP))
108 break;
109 }
110
111 if (newx >= tlinelen(newy))
112 break;
113
114 - gp = &term.line[newy][newx];
115 + gp = &TLINE(newy)[newx];
116 delim = ISDELIM(gp->u);
117 if (!(gp->mode & ATTR_WDUMMY) && (delim != prev…
118 || (delim && gp->u != prevgp->u…
119 @@ -571,14 +587,14 @@ selsnap(int *x, int *y, int direction)
120 *x = (direction < 0) ? 0 : term.col - 1;
121 if (direction < 0) {
122 for (; *y > 0; *y += direction) {
123 - if (!(term.line[*y-1][term.col-1].mode
124 + if (!(TLINE(*y-1)[term.col-1].mode
125 & ATTR_WRAP)) {
126 break;
127 }
128 }
129 } else if (direction > 0) {
130 for (; *y < term.row-1; *y += direction) {
131 - if (!(term.line[*y][term.col-1].mode
132 + if (!(TLINE(*y)[term.col-1].mode
133 & ATTR_WRAP)) {
134 break;
135 }
136 @@ -609,13 +625,13 @@ getsel(void)
137 }
138
139 if (sel.type == SEL_RECTANGULAR) {
140 - gp = &term.line[y][sel.nb.x];
141 + gp = &TLINE(y)[sel.nb.x];
142 lastx = sel.ne.x;
143 } else {
144 - gp = &term.line[y][sel.nb.y == y ? sel.nb.x : 0…
145 + gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0];
146 lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
147 }
148 - last = &term.line[y][MIN(lastx, linelen-1)];
149 + last = &TLINE(y)[MIN(lastx, linelen-1)];
150 while (last >= gp && last->u == ' ')
151 --last;
152
153 @@ -956,12 +972,15 @@ int
154 tattrset(int attr)
155 {
156 int i, j;
157 + int y = TLINEOFFSET(0);
158
159 for (i = 0; i < term.row-1; i++) {
160 + Line line = TSCREEN.buffer[y];
161 for (j = 0; j < term.col-1; j++) {
162 - if (term.line[i][j].mode & attr)
163 + if (line[j].mode & attr)
164 return 1;
165 }
166 + y = (y+1) % TSCREEN.size;
167 }
168
169 return 0;
170 @@ -983,14 +1002,17 @@ void
171 tsetdirtattr(int attr)
172 {
173 int i, j;
174 + int y = TLINEOFFSET(0);
175
176 for (i = 0; i < term.row-1; i++) {
177 + Line line = TSCREEN.buffer[y];
178 for (j = 0; j < term.col-1; j++) {
179 - if (term.line[i][j].mode & attr) {
180 + if (line[j].mode & attr) {
181 tsetdirt(i, i);
182 break;
183 }
184 }
185 + y = (y+1) % TSCREEN.size;
186 }
187 }
188
189 @@ -1003,27 +1025,19 @@ tfulldirt(void)
190 void
191 tcursor(int mode)
192 {
193 - static TCursor c[2];
194 - int alt = IS_SET(MODE_ALTSCREEN);
195 -
196 if (mode == CURSOR_SAVE) {
197 - c[alt] = term.c;
198 + TSCREEN.sc = term.c;
199 } else if (mode == CURSOR_LOAD) {
200 - term.c = c[alt];
201 - tmoveto(c[alt].x, c[alt].y);
202 + term.c = TSCREEN.sc;
203 + tmoveto(term.c.x, term.c.y);
204 }
205 }
206
207 void
208 treset(void)
209 {
210 - uint i;
211 -
212 - term.c = (TCursor){{
213 - .mode = ATTR_NULL,
214 - .fg = defaultfg,
215 - .bg = defaultbg
216 - }, .x = 0, .y = 0, .state = CURSOR_DEFAULT};
217 + int i, j;
218 + Glyph g = (Glyph){ .fg = defaultfg, .bg = defaultbg};
219
220 memset(term.tabs, 0, term.col * sizeof(*term.tabs));
221 for (i = tabspaces; i < term.col; i += tabspaces)
222 @@ -1035,17 +1049,37 @@ treset(void)
223 term.charset = 0;
224
225 for (i = 0; i < 2; i++) {
226 - tmoveto(0, 0);
227 - tcursor(CURSOR_SAVE);
228 - tclearregion(0, 0, term.col-1, term.row-1);
229 - tswapscreen();
230 + term.screen[i].sc = (TCursor){{
231 + .fg = defaultfg,
232 + .bg = defaultbg
233 + }};
234 + term.screen[i].cur = 0;
235 + term.screen[i].off = 0;
236 + for (j = 0; j < term.row; ++j) {
237 + if (term.col != term.linelen)
238 + term.screen[i].buffer[j] = xrealloc(ter…
239 + clearline(term.screen[i].buffer[j], g, 0, term.…
240 + }
241 + for (j = term.row; j < term.screen[i].size; ++j) {
242 + free(term.screen[i].buffer[j]);
243 + term.screen[i].buffer[j] = NULL;
244 + }
245 }
246 + tcursor(CURSOR_LOAD);
247 + term.linelen = term.col;
248 + tfulldirt();
249 }
250
251 void
252 tnew(int col, int row)
253 {
254 - term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultb…
255 + int i;
256 + term = (Term){};
257 + term.screen[0].buffer = xmalloc(HISTSIZE * sizeof(Line));
258 + term.screen[0].size = HISTSIZE;
259 + term.screen[1].buffer = NULL;
260 + for (i = 0; i < HISTSIZE; ++i) term.screen[0].buffer[i] = NULL;
261 +
262 tresize(col, row);
263 treset();
264 }
265 @@ -1053,14 +1087,42 @@ tnew(int col, int row)
266 void
267 tswapscreen(void)
268 {
269 - Line *tmp = term.line;
270 -
271 - term.line = term.alt;
272 - term.alt = tmp;
273 term.mode ^= MODE_ALTSCREEN;
274 tfulldirt();
275 }
276
277 +void
278 +kscrollup(const Arg *a)
279 +{
280 + int n = a->i;
281 +
282 + if (IS_SET(MODE_ALTSCREEN))
283 + return;
284 +
285 + if (n < 0) n = (-n) * term.row;
286 + if (n > TSCREEN.size - term.row - TSCREEN.off) n = TSCREEN.size…
287 + while (!TLINE(-n)) --n;
288 + TSCREEN.off += n;
289 + selscroll(0, n);
290 + tfulldirt();
291 +}
292 +
293 +void
294 +kscrolldown(const Arg *a)
295 +{
296 +
297 + int n = a->i;
298 +
299 + if (IS_SET(MODE_ALTSCREEN))
300 + return;
301 +
302 + if (n < 0) n = (-n) * term.row;
303 + if (n > TSCREEN.off) n = TSCREEN.off;
304 + TSCREEN.off -= n;
305 + selscroll(0, -n);
306 + tfulldirt();
307 +}
308 +
309 void
310 tscrolldown(int orig, int n)
311 {
312 @@ -1069,15 +1131,29 @@ tscrolldown(int orig, int n)
313
314 LIMIT(n, 0, term.bot-orig+1);
315
316 - tsetdirt(orig, term.bot-n);
317 - tclearregion(0, term.bot-n+1, term.col-1, term.bot);
318 + /* Ensure that lines are allocated */
319 + for (i = -n; i < 0; i++) {
320 + TLINE(i) = ensureline(TLINE(i));
321 + }
322
323 - for (i = term.bot; i >= orig+n; i--) {
324 - temp = term.line[i];
325 - term.line[i] = term.line[i-n];
326 - term.line[i-n] = temp;
327 + /* Shift non-scrolling areas in ring buffer */
328 + for (i = term.bot+1; i < term.row; i++) {
329 + temp = TLINE(i);
330 + TLINE(i) = TLINE(i-n);
331 + TLINE(i-n) = temp;
332 + }
333 + for (i = 0; i < orig; i++) {
334 + temp = TLINE(i);
335 + TLINE(i) = TLINE(i-n);
336 + TLINE(i-n) = temp;
337 }
338
339 + /* Scroll buffer */
340 + TSCREEN.cur = (TSCREEN.cur + TSCREEN.size - n) % TSCREEN.size;
341 + /* Clear lines that have entered the view */
342 + tclearregion(0, orig, term.linelen-1, orig+n-1);
343 + /* Redraw portion of the screen that has scrolled */
344 + tsetdirt(orig+n-1, term.bot);
345 selscroll(orig, n);
346 }
347
348 @@ -1089,15 +1165,29 @@ tscrollup(int orig, int n)
349
350 LIMIT(n, 0, term.bot-orig+1);
351
352 - tclearregion(0, orig, term.col-1, orig+n-1);
353 - tsetdirt(orig+n, term.bot);
354 + /* Ensure that lines are allocated */
355 + for (i = term.row; i < term.row + n; i++) {
356 + TLINE(i) = ensureline(TLINE(i));
357 + }
358
359 - for (i = orig; i <= term.bot-n; i++) {
360 - temp = term.line[i];
361 - term.line[i] = term.line[i+n];
362 - term.line[i+n] = temp;
363 + /* Shift non-scrolling areas in ring buffer */
364 + for (i = orig-1; i >= 0; i--) {
365 + temp = TLINE(i);
366 + TLINE(i) = TLINE(i+n);
367 + TLINE(i+n) = temp;
368 + }
369 + for (i = term.row-1; i >term.bot; i--) {
370 + temp = TLINE(i);
371 + TLINE(i) = TLINE(i+n);
372 + TLINE(i+n) = temp;
373 }
374
375 + /* Scroll buffer */
376 + TSCREEN.cur = (TSCREEN.cur + n) % TSCREEN.size;
377 + /* Clear lines that have entered the view */
378 + tclearregion(0, term.bot-n+1, term.linelen-1, term.bot);
379 + /* Redraw portion of the screen that has scrolled */
380 + tsetdirt(orig, term.bot-n+1);
381 selscroll(orig, -n);
382 }
383
384 @@ -1201,6 +1291,7 @@ tsetchar(Rune u, const Glyph *attr, int x, int y)
385 "⎻", "─", "⎼", "⎽", "├", "┤", "â”´", "┬",…
386 "│", "≤", "≥", "Ï€", "≠", "£", "·", /* x - ~ …
387 };
388 + Line line = TLINE(y);
389
390 /*
391 * The table is proudly stolen from rxvt.
392 @@ -1209,25 +1300,25 @@ tsetchar(Rune u, const Glyph *attr, int x, int y)
393 BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41])
394 utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ);
395
396 - if (term.line[y][x].mode & ATTR_WIDE) {
397 + if (line[x].mode & ATTR_WIDE) {
398 if (x+1 < term.col) {
399 - term.line[y][x+1].u = ' ';
400 - term.line[y][x+1].mode &= ~ATTR_WDUMMY;
401 + line[x+1].u = ' ';
402 + line[x+1].mode &= ~ATTR_WDUMMY;
403 }
404 - } else if (term.line[y][x].mode & ATTR_WDUMMY) {
405 - term.line[y][x-1].u = ' ';
406 - term.line[y][x-1].mode &= ~ATTR_WIDE;
407 + } else if (line[x].mode & ATTR_WDUMMY) {
408 + line[x-1].u = ' ';
409 + line[x-1].mode &= ~ATTR_WIDE;
410 }
411
412 term.dirty[y] = 1;
413 - term.line[y][x] = *attr;
414 - term.line[y][x].u = u;
415 + line[x] = *attr;
416 + line[x].u = u;
417 }
418
419 void
420 tclearregion(int x1, int y1, int x2, int y2)
421 {
422 - int x, y, temp;
423 + int x, y, L, S, temp;
424 Glyph *gp;
425
426 if (x1 > x2)
427 @@ -1235,15 +1326,16 @@ tclearregion(int x1, int y1, int x2, int y2)
428 if (y1 > y2)
429 temp = y1, y1 = y2, y2 = temp;
430
431 - LIMIT(x1, 0, term.col-1);
432 - LIMIT(x2, 0, term.col-1);
433 + LIMIT(x1, 0, term.linelen-1);
434 + LIMIT(x2, 0, term.linelen-1);
435 LIMIT(y1, 0, term.row-1);
436 LIMIT(y2, 0, term.row-1);
437
438 + L = TLINEOFFSET(y1);
439 for (y = y1; y <= y2; y++) {
440 term.dirty[y] = 1;
441 for (x = x1; x <= x2; x++) {
442 - gp = &term.line[y][x];
443 + gp = &TSCREEN.buffer[L][x];
444 if (selected(x, y))
445 selclear();
446 gp->fg = term.c.attr.fg;
447 @@ -1251,6 +1343,7 @@ tclearregion(int x1, int y1, int x2, int y2)
448 gp->mode = 0;
449 gp->u = ' ';
450 }
451 + L = (L + 1) % TSCREEN.size;
452 }
453 }
454
455 @@ -1265,7 +1358,7 @@ tdeletechar(int n)
456 dst = term.c.x;
457 src = term.c.x + n;
458 size = term.col - src;
459 - line = term.line[term.c.y];
460 + line = TLINE(term.c.y);
461
462 memmove(&line[dst], &line[src], size * sizeof(Glyph));
463 tclearregion(term.col-n, term.c.y, term.col-1, term.c.y);
464 @@ -1282,7 +1375,7 @@ tinsertblank(int n)
465 dst = term.c.x + n;
466 src = term.c.x;
467 size = term.col - dst;
468 - line = term.line[term.c.y];
469 + line = TLINE(term.c.y);
470
471 memmove(&line[dst], &line[src], size * sizeof(Glyph));
472 tclearregion(src, term.c.y, dst - 1, term.c.y);
473 @@ -2103,7 +2196,7 @@ tdumpline(int n)
474 char buf[UTF_SIZ];
475 const Glyph *bp, *end;
476
477 - bp = &term.line[n][0];
478 + bp = &TLINE(n)[0];
479 end = &bp[MIN(tlinelen(n), term.col) - 1];
480 if (bp != end || bp->u != ' ') {
481 for ( ; bp <= end; ++bp)
482 @@ -2486,11 +2579,11 @@ check_control_code:
483 if (selected(term.c.x, term.c.y))
484 selclear();
485
486 - gp = &term.line[term.c.y][term.c.x];
487 + gp = &TLINE(term.c.y)[term.c.x];
488 if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) {
489 gp->mode |= ATTR_WRAP;
490 tnewline(1);
491 - gp = &term.line[term.c.y][term.c.x];
492 + gp = &TLINE(term.c.y)[term.c.x];
493 }
494
495 if (IS_SET(MODE_INSERT) && term.c.x+width < term.col)
496 @@ -2498,7 +2591,7 @@ check_control_code:
497
498 if (term.c.x+width > term.col) {
499 tnewline(1);
500 - gp = &term.line[term.c.y][term.c.x];
501 + gp = &TLINE(term.c.y)[term.c.x];
502 }
503
504 tsetchar(u, &term.c.attr, term.c.x, term.c.y);
505 @@ -2529,6 +2622,11 @@ twrite(const char *buf, int buflen, int show_ctrl)
506 Rune u;
507 int n;
508
509 + if (TSCREEN.off) {
510 + TSCREEN.off = 0;
511 + tfulldirt();
512 + }
513 +
514 for (n = 0; n < buflen; n += charsize) {
515 if (IS_SET(MODE_UTF8)) {
516 /* process a complete utf8 char */
517 @@ -2555,56 +2653,85 @@ twrite(const char *buf, int buflen, int show_ctr…
518 }
519
520 void
521 -tresize(int col, int row)
522 +clearline(Line line, Glyph g, int x, int xend)
523 {
524 int i;
525 + g.mode = 0;
526 + g.u = ' ';
527 + for (i = x; i < xend; ++i) {
528 + line[i] = g;
529 + }
530 +}
531 +
532 +Line
533 +ensureline(Line line)
534 +{
535 + if (!line) {
536 + line = xmalloc(term.linelen * sizeof(Glyph));
537 + }
538 + return line;
539 +}
540 +
541 +void
542 +tresize(int col, int row)
543 +{
544 + int i, j;
545 int minrow = MIN(row, term.row);
546 int mincol = MIN(col, term.col);
547 + int linelen = MAX(col, term.linelen);
548 int *bp;
549 - TCursor c;
550
551 - if (col < 1 || row < 1) {
552 + if (col < 1 || row < 1 || row > HISTSIZE) {
553 fprintf(stderr,
554 "tresize: error resizing to %dx%d\n", col, row);
555 return;
556 }
557
558 - /*
559 - * slide screen to keep cursor where we expect it -
560 - * tscrollup would work here, but we can optimize to
561 - * memmove because we're freeing the earlier lines
562 - */
563 - for (i = 0; i <= term.c.y - row; i++) {
564 - free(term.line[i]);
565 - free(term.alt[i]);
566 + /* Shift buffer to keep the cursor where we expect it */
567 + if (row <= term.c.y) {
568 + term.screen[0].cur = (term.screen[0].cur - row + term.c…
569 + }
570 +
571 + /* Resize and clear line buffers as needed */
572 + if (linelen > term.linelen) {
573 + for (i = 0; i < term.screen[0].size; ++i) {
574 + if (term.screen[0].buffer[i]) {
575 + term.screen[0].buffer[i] = xrealloc(ter…
576 + clearline(term.screen[0].buffer[i], ter…
577 + }
578 + }
579 + for (i = 0; i < minrow; ++i) {
580 + term.screen[1].buffer[i] = xrealloc(term.screen…
581 + clearline(term.screen[1].buffer[i], term.c.attr…
582 + }
583 }
584 - /* ensure that both src and dst are not NULL */
585 - if (i > 0) {
586 - memmove(term.line, term.line + i, row * sizeof(Line));
587 - memmove(term.alt, term.alt + i, row * sizeof(Line));
588 + /* Allocate all visible lines for regular line buffer */
589 + for (j = term.screen[0].cur, i = 0; i < row; ++i, j = (j + 1) %…
590 + {
591 + if (!term.screen[0].buffer[j]) {
592 + term.screen[0].buffer[j] = xmalloc(linelen * si…
593 + }
594 + if (i >= term.row) {
595 + clearline(term.screen[0].buffer[j], term.c.attr…
596 + }
597 }
598 - for (i += row; i < term.row; i++) {
599 - free(term.line[i]);
600 - free(term.alt[i]);
601 + /* Resize alt screen */
602 + term.screen[1].cur = 0;
603 + term.screen[1].size = row;
604 + for (i = row; i < term.row; ++i) {
605 + free(term.screen[1].buffer[i]);
606 + }
607 + term.screen[1].buffer = xrealloc(term.screen[1].buffer, row * s…
608 + for (i = term.row; i < row; ++i) {
609 + term.screen[1].buffer[i] = xmalloc(linelen * sizeof(Gly…
610 + clearline(term.screen[1].buffer[i], term.c.attr, 0, lin…
611 }
612
613 /* resize to new height */
614 - term.line = xrealloc(term.line, row * sizeof(Line));
615 - term.alt = xrealloc(term.alt, row * sizeof(Line));
616 term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
617 term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
618
619 - /* resize each row to new width, zero-pad if needed */
620 - for (i = 0; i < minrow; i++) {
621 - term.line[i] = xrealloc(term.line[i], col * sizeof(Glyp…
622 - term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyp…
623 - }
624 -
625 - /* allocate any new rows */
626 - for (/* i = minrow */; i < row; i++) {
627 - term.line[i] = xmalloc(col * sizeof(Glyph));
628 - term.alt[i] = xmalloc(col * sizeof(Glyph));
629 - }
630 + /* fix tabstops */
631 if (col > term.col) {
632 bp = term.tabs + term.col;
633
634 @@ -2614,26 +2741,16 @@ tresize(int col, int row)
635 for (bp += tabspaces; bp < term.tabs + col; bp += tabsp…
636 *bp = 1;
637 }
638 +
639 /* update terminal size */
640 term.col = col;
641 term.row = row;
642 + term.linelen = linelen;
643 /* reset scrolling region */
644 tsetscroll(0, row-1);
645 /* make use of the LIMIT in tmoveto */
646 tmoveto(term.c.x, term.c.y);
647 - /* Clearing both screens (it makes dirty all lines) */
648 - c = term.c;
649 - for (i = 0; i < 2; i++) {
650 - if (mincol < col && 0 < minrow) {
651 - tclearregion(mincol, 0, col - 1, minrow - 1);
652 - }
653 - if (0 < col && minrow < row) {
654 - tclearregion(0, minrow, col - 1, row - 1);
655 - }
656 - tswapscreen();
657 - tcursor(CURSOR_LOAD);
658 - }
659 - term.c = c;
660 + tfulldirt();
661 }
662
663 void
664 @@ -2645,14 +2762,15 @@ resettitle(void)
665 void
666 drawregion(int x1, int y1, int x2, int y2)
667 {
668 - int y;
669 + int y, L;
670
671 + L = TLINEOFFSET(y1);
672 for (y = y1; y < y2; y++) {
673 - if (!term.dirty[y])
674 - continue;
675 -
676 - term.dirty[y] = 0;
677 - xdrawline(term.line[y], x1, y, x2);
678 + if (term.dirty[y]) {
679 + term.dirty[y] = 0;
680 + xdrawline(TSCREEN.buffer[L], x1, y, x2);
681 + }
682 + L = (L + 1) % TSCREEN.size;
683 }
684 }
685
686 @@ -2667,14 +2785,15 @@ draw(void)
687 /* adjust cursor position */
688 LIMIT(term.ocx, 0, term.col-1);
689 LIMIT(term.ocy, 0, term.row-1);
690 - if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY)
691 + if (TLINE(term.ocy)[term.ocx].mode & ATTR_WDUMMY)
692 term.ocx--;
693 - if (term.line[term.c.y][cx].mode & ATTR_WDUMMY)
694 + if (TLINE(term.c.y)[cx].mode & ATTR_WDUMMY)
695 cx--;
696
697 drawregion(0, 0, term.col, term.row);
698 - xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
699 - term.ocx, term.ocy, term.line[term.ocy][term.oc…
700 + if (TSCREEN.off == 0)
701 + xdrawcursor(cx, term.c.y, TLINE(term.c.y)[cx],
702 + term.ocx, term.ocy, TLINE(term.ocy)[ter…
703 term.ocx = cx;
704 term.ocy = term.c.y;
705 xfinishdraw();
706 diff --git a/st.h b/st.h
707 index 519b9bd..b48e810 100644
708 --- a/st.h
709 +++ b/st.h
710 @@ -19,6 +19,7 @@
711
712 #define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b))
713 #define IS_TRUECOL(x) (1 << 24 & (x))
714 +#define HISTSIZE 2000
715
716 enum glyph_attribute {
717 ATTR_NULL = 0,
718 diff --git a/x.c b/x.c
719 index 8a16faa..1bb5853 100644
720 --- a/x.c
721 +++ b/x.c
722 @@ -59,6 +59,8 @@ static void zoom(const Arg *);
723 static void zoomabs(const Arg *);
724 static void zoomreset(const Arg *);
725 static void ttysend(const Arg *);
726 +void kscrollup(const Arg *);
727 +void kscrolldown(const Arg *);
728
729 /* config.h for applying patches and the configuration. */
730 #include "config.h"
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.