Introduction
Introduction Statistics Contact Development Disclaimer Help
st-scrollback-reflow-0.9.diff - sites - public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log
Files
Refs
---
st-scrollback-reflow-0.9.diff (37402B)
---
1 diff --git a/st.c b/st.c
2 index 79ee9ba..5170cd4 100644
3 --- a/st.c
4 +++ b/st.c
5 @@ -36,6 +36,7 @@
6 #define STR_BUF_SIZ ESC_BUF_SIZ
7 #define STR_ARG_SIZ ESC_ARG_SIZ
8 #define HISTSIZE 2000
9 +#define RESIZEBUFFER 1000
10
11 /* macros */
12 #define IS_SET(flag) ((term.mode & (flag)) != 0)
13 @@ -43,9 +44,22 @@
14 #define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f))
15 #define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c))
16 #define ISDELIM(u) (u && wcschr(worddelimiters, u))
17 -#define TLINE(y) ((y) < term.scr ? term.hist[((y) + term…
18 - term.scr + HISTSIZE + 1) % HISTSIZE] : \
19 - term.line[(y) - term.scr])
20 +
21 +#define TLINE(y) ( \
22 + (y) < term.scr ? term.hist[(term.histi + (y) - term.scr + 1 + H…
23 + : term.line[(y) - term.scr] \
24 +)
25 +
26 +#define TLINEABS(y) ( \
27 + (y) < 0 ? term.hist[(term.histi + (y) + 1 + HISTSIZE) % HISTSIZ…
28 +)
29 +
30 +#define UPDATEWRAPNEXT(alt, col) do { \
31 + if ((term.c.state & CURSOR_WRAPNEXT) && term.c.x + term.wrapcwi…
32 + term.c.x += term.wrapcwidth[alt]; \
33 + term.c.state &= ~CURSOR_WRAPNEXT; \
34 + } \
35 +} while (0);
36
37 enum term_mode {
38 MODE_WRAP = 1 << 0,
39 @@ -57,6 +71,12 @@ enum term_mode {
40 MODE_UTF8 = 1 << 6,
41 };
42
43 +enum scroll_mode {
44 + SCROLL_RESIZE = -1,
45 + SCROLL_NOSAVEHIST = 0,
46 + SCROLL_SAVEHIST = 1
47 +};
48 +
49 enum cursor_movement {
50 CURSOR_SAVE,
51 CURSOR_LOAD
52 @@ -118,10 +138,11 @@ typedef struct {
53 int row; /* nb row */
54 int col; /* nb col */
55 Line *line; /* screen */
56 - Line *alt; /* alternate screen */
57 Line hist[HISTSIZE]; /* history buffer */
58 - int histi; /* history index */
59 - int scr; /* scroll back */
60 + int histi; /* history index */
61 + int histf; /* nb history available */
62 + int scr; /* scroll back */
63 + int wrapcwidth[2]; /* used in updating WRAPNEXT when resizing…
64 int *dirty; /* dirtyness of lines */
65 TCursor c; /* cursor */
66 int ocx; /* old cursor col */
67 @@ -179,26 +200,37 @@ static void tprinter(char *, size_t);
68 static void tdumpsel(void);
69 static void tdumpline(int);
70 static void tdump(void);
71 -static void tclearregion(int, int, int, int);
72 +static void tclearregion(int, int, int, int, int);
73 static void tcursor(int);
74 +static void tclearglyph(Glyph *, int);
75 +static void tresetcursor(void);
76 static void tdeletechar(int);
77 static void tdeleteline(int);
78 static void tinsertblank(int);
79 static void tinsertblankline(int);
80 -static int tlinelen(int);
81 +static int tlinelen(Line len);
82 +static int tiswrapped(Line line);
83 +static char *tgetglyphs(char *, const Glyph *, const Glyph *);
84 +static size_t tgetline(char *, const Glyph *);
85 static void tmoveto(int, int);
86 static void tmoveato(int, int);
87 static void tnewline(int);
88 static void tputtab(int);
89 static void tputc(Rune);
90 static void treset(void);
91 -static void tscrollup(int, int, int);
92 -static void tscrolldown(int, int, int);
93 +static void tscrollup(int, int, int, int);
94 +static void tscrolldown(int, int);
95 +static void treflow(int, int);
96 +static void rscrolldown(int);
97 +static void tresizedef(int, int);
98 +static void tresizealt(int, int);
99 static void tsetattr(const int *, int);
100 static void tsetchar(Rune, const Glyph *, int, int);
101 static void tsetdirt(int, int);
102 static void tsetscroll(int, int);
103 static void tswapscreen(void);
104 +static void tloaddefscreen(int, int);
105 +static void tloadaltscreen(int, int);
106 static void tsetmode(int, int, const int *, int);
107 static int twrite(const char *, int, int);
108 static void tfulldirt(void);
109 @@ -212,7 +244,10 @@ static void tstrsequence(uchar);
110 static void drawregion(int, int, int, int);
111
112 static void selnormalize(void);
113 -static void selscroll(int, int);
114 +static void selscroll(int, int, int);
115 +static void selmove(int);
116 +static void selremove(void);
117 +static int regionselected(int, int, int, int);
118 static void selsnap(int *, int *, int);
119
120 static size_t utf8decode(const char *, Rune *, size_t);
121 @@ -412,17 +447,46 @@ selinit(void)
122 }
123
124 int
125 -tlinelen(int y)
126 +tlinelen(Line line)
127 {
128 - int i = term.col;
129 + int i = term.col - 1;
130 +
131 + for (; i >= 0 && !(line[i].mode & (ATTR_SET | ATTR_WRAP)); i--);
132 + return i + 1;
133 +}
134
135 - if (TLINE(y)[i - 1].mode & ATTR_WRAP)
136 - return i;
137 +int
138 +tiswrapped(Line line)
139 +{
140 + int len = tlinelen(line);
141
142 - while (i > 0 && TLINE(y)[i - 1].u == ' ')
143 - --i;
144 + return len > 0 && (line[len - 1].mode & ATTR_WRAP);
145 +}
146
147 - return i;
148 +char *
149 +tgetglyphs(char *buf, const Glyph *gp, const Glyph *lgp)
150 +{
151 + while (gp <= lgp)
152 + if (gp->mode & ATTR_WDUMMY) {
153 + gp++;
154 + } else {
155 + buf += utf8encode((gp++)->u, buf);
156 + }
157 + return buf;
158 +}
159 +
160 +size_t
161 +tgetline(char *buf, const Glyph *fgp)
162 +{
163 + char *ptr;
164 + const Glyph *lgp = &fgp[term.col - 1];
165 +
166 + while (lgp > fgp && !(lgp->mode & (ATTR_SET | ATTR_WRAP)))
167 + lgp--;
168 + ptr = tgetglyphs(buf, fgp, lgp);
169 + if (!(lgp->mode & ATTR_WRAP))
170 + *(ptr++) = '\n';
171 + return ptr - buf;
172 }
173
174 void
175 @@ -462,10 +526,11 @@ selextend(int col, int row, int type, int done)
176
177 sel.oe.x = col;
178 sel.oe.y = row;
179 - selnormalize();
180 sel.type = type;
181 + selnormalize();
182
183 - if (oldey != sel.oe.y || oldex != sel.oe.x || oldtype != sel.ty…
184 + if (oldey != sel.oe.y || oldex != sel.oe.x ||
185 + oldtype != sel.type || sel.mode == SEL_EMPTY)
186 tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey));
187
188 sel.mode = done ? SEL_IDLE : SEL_READY;
189 @@ -492,36 +557,43 @@ selnormalize(void)
190 /* expand selection over line breaks */
191 if (sel.type == SEL_RECTANGULAR)
192 return;
193 - i = tlinelen(sel.nb.y);
194 - if (i < sel.nb.x)
195 +
196 + i = tlinelen(TLINE(sel.nb.y));
197 + if (sel.nb.x > i)
198 sel.nb.x = i;
199 - if (tlinelen(sel.ne.y) <= sel.ne.x)
200 - sel.ne.x = term.col - 1;
201 + if (sel.ne.x >= tlinelen(TLINE(sel.ne.y)))
202 + sel.ne.x = term.col - 1;
203 }
204
205 int
206 -selected(int x, int y)
207 +regionselected(int x1, int y1, int x2, int y2)
208 {
209 - if (sel.mode == SEL_EMPTY || sel.ob.x == -1 ||
210 - sel.alt != IS_SET(MODE_ALTSCREEN))
211 + if (sel.ob.x == -1 || sel.mode == SEL_EMPTY ||
212 + sel.alt != IS_SET(MODE_ALTSCREEN) || sel.nb.y > y2 || sel.n…
213 return 0;
214
215 - if (sel.type == SEL_RECTANGULAR)
216 - return BETWEEN(y, sel.nb.y, sel.ne.y)
217 - && BETWEEN(x, sel.nb.x, sel.ne.x);
218 + return (sel.type == SEL_RECTANGULAR) ? sel.nb.x <= x2 && sel.ne…
219 + : (sel.nb.y != y2 || sel.nb.x <= x2) &&
220 + (sel.ne.y != y1 || sel.ne.x >= x1);
221 +}
222
223 - return BETWEEN(y, sel.nb.y, sel.ne.y)
224 - && (y != sel.nb.y || x >= sel.nb.x)
225 - && (y != sel.ne.y || x <= sel.ne.x);
226 +int
227 +selected(int x, int y)
228 +{
229 + return regionselected(x, y, x, y);
230 }
231
232 void
233 selsnap(int *x, int *y, int direction)
234 {
235 int newx, newy, xt, yt;
236 + int rtop = 0, rbot = term.row - 1;
237 int delim, prevdelim;
238 const Glyph *gp, *prevgp;
239
240 + if (!IS_SET(MODE_ALTSCREEN))
241 + rtop += -term.histf + term.scr, rbot += term.scr;
242 +
243 switch (sel.snap) {
244 case SNAP_WORD:
245 /*
246 @@ -536,7 +608,7 @@ selsnap(int *x, int *y, int direction)
247 if (!BETWEEN(newx, 0, term.col - 1)) {
248 newy += direction;
249 newx = (newx + term.col) % term.col;
250 - if (!BETWEEN(newy, 0, term.row - 1))
251 + if (!BETWEEN(newy, rtop, rbot))
252 break;
253
254 if (direction > 0)
255 @@ -547,13 +619,13 @@ selsnap(int *x, int *y, int direction)
256 break;
257 }
258
259 - if (newx >= tlinelen(newy))
260 + if (newx >= tlinelen(TLINE(newy)))
261 break;
262
263 gp = &TLINE(newy)[newx];
264 delim = ISDELIM(gp->u);
265 - if (!(gp->mode & ATTR_WDUMMY) && (delim != prev…
266 - || (delim && gp->u != prevgp->u…
267 + if (!(gp->mode & ATTR_WDUMMY) && (delim != prev…
268 + (delim && !(gp->u == ' ' && prevgp->u == ' …
269 break;
270
271 *x = newx;
272 @@ -570,18 +642,14 @@ selsnap(int *x, int *y, int direction)
273 */
274 *x = (direction < 0) ? 0 : term.col - 1;
275 if (direction < 0) {
276 - for (; *y > 0; *y += direction) {
277 - if (!(TLINE(*y-1)[term.col-1].mode
278 - & ATTR_WRAP)) {
279 + for (; *y > rtop; *y -= 1) {
280 + if (!tiswrapped(TLINE(*y-1)))
281 break;
282 - }
283 }
284 } else if (direction > 0) {
285 - for (; *y < term.row-1; *y += direction) {
286 - if (!(TLINE(*y)[term.col-1].mode
287 - & ATTR_WRAP)) {
288 + for (; *y < rbot; *y += 1) {
289 + if (!tiswrapped(TLINE(*y)))
290 break;
291 - }
292 }
293 }
294 break;
295 @@ -592,40 +660,34 @@ char *
296 getsel(void)
297 {
298 char *str, *ptr;
299 - int y, bufsize, lastx, linelen;
300 - const Glyph *gp, *last;
301 + int y, lastx, linelen;
302 + const Glyph *gp, *lgp;
303
304 - if (sel.ob.x == -1)
305 + if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN))
306 return NULL;
307
308 - bufsize = (term.col+1) * (sel.ne.y-sel.nb.y+1) * UTF_SIZ;
309 - ptr = str = xmalloc(bufsize);
310 + str = xmalloc((term.col + 1) * (sel.ne.y - sel.nb.y + 1) * UTF_…
311 + ptr = str;
312
313 /* append every set & selected glyph to the selection */
314 for (y = sel.nb.y; y <= sel.ne.y; y++) {
315 - if ((linelen = tlinelen(y)) == 0) {
316 + Line line = TLINE(y);
317 +
318 + if ((linelen = tlinelen(line)) == 0) {
319 *ptr++ = '\n';
320 continue;
321 }
322
323 if (sel.type == SEL_RECTANGULAR) {
324 - gp = &TLINE(y)[sel.nb.x];
325 + gp = &line[sel.nb.x];
326 lastx = sel.ne.x;
327 } else {
328 - gp = &TLINE(y)[sel.nb.y == y ? sel.nb.x : 0];
329 + gp = &line[sel.nb.y == y ? sel.nb.x : 0];
330 lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1;
331 }
332 - last = &TLINE(y)[MIN(lastx, linelen-1)];
333 - while (last >= gp && last->u == ' ')
334 - --last;
335 -
336 - for ( ; gp <= last; ++gp) {
337 - if (gp->mode & ATTR_WDUMMY)
338 - continue;
339 -
340 - ptr += utf8encode(gp->u, ptr);
341 - }
342 + lgp = &line[MIN(lastx, linelen-1)];
343
344 + ptr = tgetglyphs(ptr, gp, lgp);
345 /*
346 * Copy and pasting of line endings is inconsistent
347 * in the inconsistent terminal and GUI world.
348 @@ -636,10 +698,10 @@ getsel(void)
349 * FIXME: Fix the computer world.
350 */
351 if ((y < sel.ne.y || lastx >= linelen) &&
352 - (!(last->mode & ATTR_WRAP) || sel.type == SEL_RECTA…
353 + (!(lgp->mode & ATTR_WRAP) || sel.type == SEL_RECTAN…
354 *ptr++ = '\n';
355 }
356 - *ptr = 0;
357 + *ptr = '\0';
358 return str;
359 }
360
361 @@ -648,9 +710,15 @@ selclear(void)
362 {
363 if (sel.ob.x == -1)
364 return;
365 + selremove();
366 + tsetdirt(sel.nb.y, sel.ne.y);
367 +}
368 +
369 +void
370 +selremove(void)
371 +{
372 sel.mode = SEL_IDLE;
373 sel.ob.x = -1;
374 - tsetdirt(sel.nb.y, sel.ne.y);
375 }
376
377 void
378 @@ -851,10 +919,8 @@ void
379 ttywrite(const char *s, size_t n, int may_echo)
380 {
381 const char *next;
382 - Arg arg = (Arg) { .i = term.scr };
383 -
384 - kscrolldown(&arg);
385
386 + kscrolldown(&((Arg){ .i = term.scr }));
387 if (may_echo && IS_SET(MODE_ECHO))
388 twrite(s, n, 1);
389
390 @@ -990,7 +1056,7 @@ tsetdirtattr(int attr)
391 for (i = 0; i < term.row-1; i++) {
392 for (j = 0; j < term.col-1; j++) {
393 if (term.line[i][j].mode & attr) {
394 - tsetdirt(i, i);
395 + term.dirty[i] = 1;
396 break;
397 }
398 }
399 @@ -1000,7 +1066,8 @@ tsetdirtattr(int attr)
400 void
401 tfulldirt(void)
402 {
403 - tsetdirt(0, term.row-1);
404 + for (int i = 0; i < term.row; i++)
405 + term.dirty[i] = 1;
406 }
407
408 void
409 @@ -1017,51 +1084,116 @@ tcursor(int mode)
410 }
411 }
412
413 +void
414 +tresetcursor(void)
415 +{
416 + term.c = (TCursor){ { .mode = ATTR_NULL, .fg = defaultfg, .bg =…
417 + .x = 0, .y = 0, .state = CURSOR_DEFAULT };
418 +}
419 +
420 void
421 treset(void)
422 {
423 uint i;
424 + int x, y;
425
426 - term.c = (TCursor){{
427 - .mode = ATTR_NULL,
428 - .fg = defaultfg,
429 - .bg = defaultbg
430 - }, .x = 0, .y = 0, .state = CURSOR_DEFAULT};
431 + tresetcursor();
432
433 memset(term.tabs, 0, term.col * sizeof(*term.tabs));
434 for (i = tabspaces; i < term.col; i += tabspaces)
435 term.tabs[i] = 1;
436 term.top = 0;
437 + term.histf = 0;
438 + term.scr = 0;
439 term.bot = term.row - 1;
440 term.mode = MODE_WRAP|MODE_UTF8;
441 memset(term.trantbl, CS_USA, sizeof(term.trantbl));
442 term.charset = 0;
443
444 + selremove();
445 for (i = 0; i < 2; i++) {
446 - tmoveto(0, 0);
447 - tcursor(CURSOR_SAVE);
448 - tclearregion(0, 0, term.col-1, term.row-1);
449 + tcursor(CURSOR_SAVE); /* reset saved cursor */
450 + for (y = 0; y < term.row; y++)
451 + for (x = 0; x < term.col; x++)
452 + tclearglyph(&term.line[y][x], 0);
453 tswapscreen();
454 }
455 + tfulldirt();
456 }
457
458 void
459 tnew(int col, int row)
460 {
461 - term = (Term){ .c = { .attr = { .fg = defaultfg, .bg = defaultb…
462 - tresize(col, row);
463 - treset();
464 + int i, j;
465 +
466 + for (i = 0; i < 2; i++) {
467 + term.line = xmalloc(row * sizeof(Line));
468 + for (j = 0; j < row; j++)
469 + term.line[j] = xmalloc(col * sizeof(Glyph));
470 + term.col = col, term.row = row;
471 + tswapscreen();
472 + }
473 + term.dirty = xmalloc(row * sizeof(*term.dirty));
474 + term.tabs = xmalloc(col * sizeof(*term.tabs));
475 + for (i = 0; i < HISTSIZE; i++)
476 + term.hist[i] = xmalloc(col * sizeof(Glyph));
477 + treset();
478 }
479
480 +/* handle it with care */
481 void
482 tswapscreen(void)
483 {
484 - Line *tmp = term.line;
485 + static Line *altline;
486 + static int altcol, altrow;
487 + Line *tmpline = term.line;
488 + int tmpcol = term.col, tmprow = term.row;
489
490 - term.line = term.alt;
491 - term.alt = tmp;
492 + term.line = altline;
493 + term.col = altcol, term.row = altrow;
494 + altline = tmpline;
495 + altcol = tmpcol, altrow = tmprow;
496 term.mode ^= MODE_ALTSCREEN;
497 - tfulldirt();
498 +}
499 +
500 +void
501 +tloaddefscreen(int clear, int loadcursor)
502 +{
503 + int col, row, alt = IS_SET(MODE_ALTSCREEN);
504 +
505 + if (alt) {
506 + if (clear)
507 + tclearregion(0, 0, term.col-1, term.row-1, 1);
508 + col = term.col, row = term.row;
509 + tswapscreen();
510 + }
511 + if (loadcursor)
512 + tcursor(CURSOR_LOAD);
513 + if (alt)
514 + tresizedef(col, row);
515 +}
516 +
517 +void
518 +tloadaltscreen(int clear, int savecursor)
519 +{
520 + int col, row, def = !IS_SET(MODE_ALTSCREEN);
521 +
522 + if (savecursor)
523 + tcursor(CURSOR_SAVE);
524 + if (def) {
525 + col = term.col, row = term.row;
526 + tswapscreen();
527 + term.scr = 0;
528 + tresizealt(col, row);
529 + }
530 + if (clear)
531 + tclearregion(0, 0, term.col-1, term.row-1, 1);
532 +}
533 +
534 +int
535 +tisaltscreen(void)
536 +{
537 + return IS_SET(MODE_ALTSCREEN);
538 }
539
540 void
541 @@ -1069,17 +1201,22 @@ kscrolldown(const Arg* a)
542 {
543 int n = a->i;
544
545 - if (n < 0)
546 - n = term.row + n;
547 + if (!term.scr || IS_SET(MODE_ALTSCREEN))
548 + return;
549
550 - if (n > term.scr)
551 - n = term.scr;
552 + if (n < 0)
553 + n = MAX(term.row / -n, 1);
554
555 - if (term.scr > 0) {
556 + if (n <= term.scr) {
557 term.scr -= n;
558 - selscroll(0, -n);
559 - tfulldirt();
560 + } else {
561 + n = term.scr;
562 + term.scr = 0;
563 }
564 +
565 + if (sel.ob.x != -1 && !sel.alt)
566 + selmove(-n); /* negate change in term.scr */
567 + tfulldirt();
568 }
569
570 void
571 @@ -1087,92 +1224,118 @@ kscrollup(const Arg* a)
572 {
573 int n = a->i;
574
575 + if (!term.histf || IS_SET(MODE_ALTSCREEN))
576 + return;
577 +
578 if (n < 0)
579 - n = term.row + n;
580 + n = MAX(term.row / -n, 1);
581
582 - if (term.scr <= HISTSIZE-n) {
583 + if (term.scr + n <= term.histf) {
584 term.scr += n;
585 - selscroll(0, n);
586 - tfulldirt();
587 + } else {
588 + n = term.histf - term.scr;
589 + term.scr = term.histf;
590 }
591 +
592 + if (sel.ob.x != -1 && !sel.alt)
593 + selmove(n); /* negate change in term.scr */
594 + tfulldirt();
595 }
596
597 void
598 -tscrolldown(int orig, int n, int copyhist)
599 +tscrolldown(int top, int n)
600 {
601 - int i;
602 + int i, bot = term.bot;
603 Line temp;
604
605 - LIMIT(n, 0, term.bot-orig+1);
606 - if (copyhist) {
607 - term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE;
608 - temp = term.hist[term.histi];
609 - term.hist[term.histi] = term.line[term.bot];
610 - term.line[term.bot] = temp;
611 - }
612 -
613 + if (n <= 0)
614 + return;
615 + n = MIN(n, bot-top+1);
616
617 - tsetdirt(orig, term.bot-n);
618 - tclearregion(0, term.bot-n+1, term.col-1, term.bot);
619 + tsetdirt(top, bot-n);
620 + tclearregion(0, bot-n+1, term.col-1, bot, 1);
621
622 - for (i = term.bot; i >= orig+n; i--) {
623 + for (i = bot; i >= top+n; i--) {
624 temp = term.line[i];
625 term.line[i] = term.line[i-n];
626 term.line[i-n] = temp;
627 }
628
629 - if (term.scr == 0)
630 - selscroll(orig, n);
631 + if (sel.ob.x != -1 && sel.alt == IS_SET(MODE_ALTSCREEN))
632 + selscroll(top, bot, n);
633 }
634
635 void
636 -tscrollup(int orig, int n, int copyhist)
637 +tscrollup(int top, int bot, int n, int mode)
638 {
639 - int i;
640 + int i, j, s;
641 + int alt = IS_SET(MODE_ALTSCREEN);
642 + int savehist = !alt && top == 0 && mode != SCROLL_NOSAVEHIST;
643 Line temp;
644
645 - LIMIT(n, 0, term.bot-orig+1);
646 -
647 - if (copyhist) {
648 - term.histi = (term.histi + 1) % HISTSIZE;
649 - temp = term.hist[term.histi];
650 - term.hist[term.histi] = term.line[orig];
651 - term.line[orig] = temp;
652 + if (n <= 0)
653 + return;
654 + n = MIN(n, bot-top+1);
655 +
656 + if (savehist) {
657 + for (i = 0; i < n; i++) {
658 + term.histi = (term.histi + 1) % HISTSIZE;
659 + temp = term.hist[term.histi];
660 + for (j = 0; j < term.col; j++)
661 + tclearglyph(&temp[j], 1);
662 + term.hist[term.histi] = term.line[i];
663 + term.line[i] = temp;
664 + }
665 + term.histf = MIN(term.histf + n, HISTSIZE);
666 + s = n;
667 + if (term.scr) {
668 + j = term.scr;
669 + term.scr = MIN(j + n, HISTSIZE);
670 + s = j + n - term.scr;
671 + }
672 + if (mode != SCROLL_RESIZE)
673 + tfulldirt();
674 + } else {
675 + tclearregion(0, top, term.col-1, top+n-1, 1);
676 + tsetdirt(top+n, bot);
677 }
678
679 - if (term.scr > 0 && term.scr < HISTSIZE)
680 - term.scr = MIN(term.scr + n, HISTSIZE-1);
681 -
682 - tclearregion(0, orig, term.col-1, orig+n-1);
683 - tsetdirt(orig+n, term.bot);
684 -
685 - for (i = orig; i <= term.bot-n; i++) {
686 + for (i = top; i <= bot-n; i++) {
687 temp = term.line[i];
688 term.line[i] = term.line[i+n];
689 term.line[i+n] = temp;
690 }
691
692 - if (term.scr == 0)
693 - selscroll(orig, -n);
694 + if (sel.ob.x != -1 && sel.alt == alt) {
695 + if (!savehist) {
696 + selscroll(top, bot, -n);
697 + } else if (s > 0) {
698 + selmove(-s);
699 + if (-term.scr + sel.nb.y < -term.histf)
700 + selremove();
701 + }
702 + }
703 }
704
705 void
706 -selscroll(int orig, int n)
707 +selmove(int n)
708 {
709 - if (sel.ob.x == -1)
710 - return;
711 + sel.ob.y += n, sel.nb.y += n;
712 + sel.oe.y += n, sel.ne.y += n;
713 +}
714 +
715 +void
716 +selscroll(int top, int bot, int n)
717 +{
718 + /* turn absolute coordinates into relative */
719 + top += term.scr, bot += term.scr;
720
721 - if (BETWEEN(sel.nb.y, orig, term.bot) != BETWEEN(sel.ne.y, orig…
722 + if (BETWEEN(sel.nb.y, top, bot) != BETWEEN(sel.ne.y, top, bot))…
723 selclear();
724 - } else if (BETWEEN(sel.nb.y, orig, term.bot)) {
725 - sel.ob.y += n;
726 - sel.oe.y += n;
727 - if (sel.ob.y < term.top || sel.ob.y > term.bot ||
728 - sel.oe.y < term.top || sel.oe.y > term.bot) {
729 + } else if (BETWEEN(sel.nb.y, top, bot)) {
730 + selmove(n);
731 + if (sel.nb.y < top || sel.ne.y > bot)
732 selclear();
733 - } else {
734 - selnormalize();
735 - }
736 }
737 }
738
739 @@ -1182,7 +1345,7 @@ tnewline(int first_col)
740 int y = term.c.y;
741
742 if (y == term.bot) {
743 - tscrollup(term.top, 1, 1);
744 + tscrollup(term.top, term.bot, 1, SCROLL_SAVEHIST);
745 } else {
746 y++;
747 }
748 @@ -1272,89 +1435,93 @@ tsetchar(Rune u, const Glyph *attr, int x, int y)
749 } else if (term.line[y][x].mode & ATTR_WDUMMY) {
750 term.line[y][x-1].u = ' ';
751 term.line[y][x-1].mode &= ~ATTR_WIDE;
752 - }
753 + }
754
755 term.dirty[y] = 1;
756 term.line[y][x] = *attr;
757 term.line[y][x].u = u;
758 + term.line[y][x].mode |= ATTR_SET;
759 }
760
761 void
762 -tclearregion(int x1, int y1, int x2, int y2)
763 +tclearglyph(Glyph *gp, int usecurattr)
764 {
765 - int x, y, temp;
766 - Glyph *gp;
767 + if (usecurattr) {
768 + gp->fg = term.c.attr.fg;
769 + gp->bg = term.c.attr.bg;
770 + } else {
771 + gp->fg = defaultfg;
772 + gp->bg = defaultbg;
773 + }
774 + gp->mode = ATTR_NULL;
775 + gp->u = ' ';
776 +}
777
778 - if (x1 > x2)
779 - temp = x1, x1 = x2, x2 = temp;
780 - if (y1 > y2)
781 - temp = y1, y1 = y2, y2 = temp;
782 +void
783 +tclearregion(int x1, int y1, int x2, int y2, int usecurattr)
784 +{
785 + int x, y;
786
787 - LIMIT(x1, 0, term.col-1);
788 - LIMIT(x2, 0, term.col-1);
789 - LIMIT(y1, 0, term.row-1);
790 - LIMIT(y2, 0, term.row-1);
791 + /* regionselected() takes relative coordinates */
792 + if (regionselected(x1+term.scr, y1+term.scr, x2+term.scr, y2+te…
793 + selremove();
794
795 for (y = y1; y <= y2; y++) {
796 term.dirty[y] = 1;
797 - for (x = x1; x <= x2; x++) {
798 - gp = &term.line[y][x];
799 - if (selected(x, y))
800 - selclear();
801 - gp->fg = term.c.attr.fg;
802 - gp->bg = term.c.attr.bg;
803 - gp->mode = 0;
804 - gp->u = ' ';
805 - }
806 + for (x = x1; x <= x2; x++)
807 + tclearglyph(&term.line[y][x], usecurattr);
808 }
809 }
810
811 void
812 tdeletechar(int n)
813 {
814 - int dst, src, size;
815 - Glyph *line;
816 -
817 - LIMIT(n, 0, term.col - term.c.x);
818 + int src, dst, size;
819 + Line line;
820
821 + if (n <= 0)
822 + return;
823 dst = term.c.x;
824 - src = term.c.x + n;
825 + src = MIN(term.c.x + n, term.col);
826 size = term.col - src;
827 - line = term.line[term.c.y];
828 -
829 - memmove(&line[dst], &line[src], size * sizeof(Glyph));
830 - tclearregion(term.col-n, term.c.y, term.col-1, term.c.y);
831 + if (size > 0) { /* otherwise src would point beyond the array
832 + https://stackoverflow.com/questions/29844298…
833 + line = term.line[term.c.y];
834 + memmove(&line[dst], &line[src], size * sizeof(Glyph));
835 + }
836 + tclearregion(dst + size, term.c.y, term.col - 1, term.c.y, 1);
837 }
838
839 void
840 tinsertblank(int n)
841 {
842 - int dst, src, size;
843 - Glyph *line;
844 -
845 - LIMIT(n, 0, term.col - term.c.x);
846 + int src, dst, size;
847 + Line line;
848
849 - dst = term.c.x + n;
850 + if (n <= 0)
851 + return;
852 + dst = MIN(term.c.x + n, term.col);
853 src = term.c.x;
854 size = term.col - dst;
855 - line = term.line[term.c.y];
856 -
857 - memmove(&line[dst], &line[src], size * sizeof(Glyph));
858 - tclearregion(src, term.c.y, dst - 1, term.c.y);
859 + if (size > 0) { /* otherwise dst would point beyond the array */
860 + line = term.line[term.c.y];
861 + memmove(&line[dst], &line[src], size * sizeof(Glyph));
862 + }
863 + tclearregion(src, term.c.y, dst - 1, term.c.y, 1);
864 }
865
866 void
867 tinsertblankline(int n)
868 {
869 if (BETWEEN(term.c.y, term.top, term.bot))
870 - tscrolldown(term.c.y, n, 0);
871 + tscrolldown(term.c.y, n);
872 }
873
874 void
875 tdeleteline(int n)
876 {
877 if (BETWEEN(term.c.y, term.top, term.bot))
878 - tscrollup(term.c.y, n, 0);
879 + tscrollup(term.c.y, term.bot, n, SCROLL_NOSAVEHIST);
880 }
881
882 int32_t
883 @@ -1528,7 +1695,7 @@ tsetscroll(int t, int b)
884 void
885 tsetmode(int priv, int set, const int *args, int narg)
886 {
887 - int alt; const int *lim;
888 + const int *lim;
889
890 for (lim = args + narg; args < lim; ++args) {
891 if (priv) {
892 @@ -1589,25 +1756,18 @@ tsetmode(int priv, int set, const int *args, int…
893 xsetmode(set, MODE_8BIT);
894 break;
895 case 1049: /* swap screen & set/restore cursor …
896 - if (!allowaltscreen)
897 - break;
898 - tcursor((set) ? CURSOR_SAVE : CURSOR_LO…
899 - /* FALLTHROUGH */
900 case 47: /* swap screen */
901 - case 1047:
902 + case 1047: /* swap screen, clearing alternate s…
903 if (!allowaltscreen)
904 break;
905 - alt = IS_SET(MODE_ALTSCREEN);
906 - if (alt) {
907 - tclearregion(0, 0, term.col-1,
908 - term.row-1);
909 - }
910 - if (set ^ alt) /* set is always 1 or 0 …
911 - tswapscreen();
912 - if (*args != 1049)
913 - break;
914 - /* FALLTHROUGH */
915 + if (set)
916 + tloadaltscreen(*args == 1049, *…
917 + else
918 + tloaddefscreen(*args == 1047, *…
919 + break;
920 case 1048:
921 + if (!allowaltscreen)
922 + break;
923 tcursor((set) ? CURSOR_SAVE : CURSOR_LO…
924 break;
925 case 2004: /* 2004: bracketed paste mode */
926 @@ -1659,7 +1819,7 @@ void
927 csihandle(void)
928 {
929 char buf[40];
930 - int len;
931 + int n, x;
932
933 switch (csiescseq.mode[0]) {
934 default:
935 @@ -1757,20 +1917,30 @@ csihandle(void)
936 case 'J': /* ED -- Clear screen */
937 switch (csiescseq.arg[0]) {
938 case 0: /* below */
939 - tclearregion(term.c.x, term.c.y, term.col-1, te…
940 + tclearregion(term.c.x, term.c.y, term.col-1, te…
941 if (term.c.y < term.row-1) {
942 - tclearregion(0, term.c.y+1, term.col-1,
943 - term.row-1);
944 + tclearregion(0, term.c.y+1, term.col-1,…
945 }
946 break;
947 case 1: /* above */
948 - if (term.c.y > 1)
949 - tclearregion(0, 0, term.col-1, term.c.y…
950 - tclearregion(0, term.c.y, term.c.x, term.c.y);
951 + if (term.c.y >= 1)
952 + tclearregion(0, 0, term.col-1, term.c.y…
953 + tclearregion(0, term.c.y, term.c.x, term.c.y, 1…
954 break;
955 case 2: /* all */
956 - tclearregion(0, 0, term.col-1, term.row-1);
957 - break;
958 + if (IS_SET(MODE_ALTSCREEN)) {
959 + tclearregion(0, 0, term.col-1, term.row-1, 1);
960 + break;
961 + }
962 + /* vte does this:
963 + tscrollup(0, term.row-1, term.row, SCROLL_SAVEH…
964 +
965 + /* alacritty does this: */
966 + for (n = term.row-1; n >= 0 && tlinelen(term.li…
967 + if (n >= 0)
968 + tscrollup(0, term.row-1, n+1, SCROLL_SA…
969 + tscrollup(0, term.row-1, term.row-n-1, SCROLL_N…
970 + break;
971 default:
972 goto unknown;
973 }
974 @@ -1778,24 +1948,24 @@ csihandle(void)
975 case 'K': /* EL -- Clear line */
976 switch (csiescseq.arg[0]) {
977 case 0: /* right */
978 - tclearregion(term.c.x, term.c.y, term.col-1,
979 - term.c.y);
980 + tclearregion(term.c.x, term.c.y, term.col-1, te…
981 break;
982 case 1: /* left */
983 - tclearregion(0, term.c.y, term.c.x, term.c.y);
984 + tclearregion(0, term.c.y, term.c.x, term.c.y, 1…
985 break;
986 case 2: /* all */
987 - tclearregion(0, term.c.y, term.col-1, term.c.y);
988 + tclearregion(0, term.c.y, term.col-1, term.c.y,…
989 break;
990 }
991 break;
992 case 'S': /* SU -- Scroll <n> line up */
993 DEFAULT(csiescseq.arg[0], 1);
994 - tscrollup(term.top, csiescseq.arg[0], 0);
995 + /* xterm, urxvt, alacritty save this in history */
996 + tscrollup(term.top, term.bot, csiescseq.arg[0], SCROLL_…
997 break;
998 case 'T': /* SD -- Scroll <n> line down */
999 DEFAULT(csiescseq.arg[0], 1);
1000 - tscrolldown(term.top, csiescseq.arg[0], 0);
1001 + tscrolldown(term.top, csiescseq.arg[0]);
1002 break;
1003 case 'L': /* IL -- Insert <n> blank lines */
1004 DEFAULT(csiescseq.arg[0], 1);
1005 @@ -1809,9 +1979,11 @@ csihandle(void)
1006 tdeleteline(csiescseq.arg[0]);
1007 break;
1008 case 'X': /* ECH -- Erase <n> char */
1009 + if (csiescseq.arg[0] < 0)
1010 + return;
1011 DEFAULT(csiescseq.arg[0], 1);
1012 - tclearregion(term.c.x, term.c.y,
1013 - term.c.x + csiescseq.arg[0] - 1, term.c…
1014 + x = MIN(term.c.x + csiescseq.arg[0], term.col) - 1;
1015 + tclearregion(term.c.x, term.c.y, x, term.c.y, 1);
1016 break;
1017 case 'P': /* DCH -- Delete <n> char */
1018 DEFAULT(csiescseq.arg[0], 1);
1019 @@ -1833,9 +2005,9 @@ csihandle(void)
1020 break;
1021 case 'n': /* DSR – Device Status Report (cursor position) */
1022 if (csiescseq.arg[0] == 6) {
1023 - len = snprintf(buf, sizeof(buf), "\033[%i;%iR",
1024 + n = snprintf(buf, sizeof(buf), "\033[%i;%iR",
1025 term.c.y+1, term.c.x+1);
1026 - ttywrite(buf, len, 0);
1027 + ttywrite(buf, n, 0);
1028 }
1029 break;
1030 case 'r': /* DECSTBM -- Set Scrolling Region */
1031 @@ -2128,16 +2300,8 @@ tdumpsel(void)
1032 void
1033 tdumpline(int n)
1034 {
1035 - char buf[UTF_SIZ];
1036 - const Glyph *bp, *end;
1037 -
1038 - bp = &term.line[n][0];
1039 - end = &bp[MIN(tlinelen(n), term.col) - 1];
1040 - if (bp != end || bp->u != ' ') {
1041 - for ( ; bp <= end; ++bp)
1042 - tprinter(buf, utf8encode(bp->u, buf));
1043 - }
1044 - tprinter("\n", 1);
1045 + char str[(term.col + 1) * UTF_SIZ];
1046 + tprinter(str, tgetline(str, &term.line[n][0]));
1047 }
1048
1049 void
1050 @@ -2358,7 +2522,7 @@ eschandle(uchar ascii)
1051 return 0;
1052 case 'D': /* IND -- Linefeed */
1053 if (term.c.y == term.bot) {
1054 - tscrollup(term.top, 1, 1);
1055 + tscrollup(term.top, term.bot, 1, SCROLL_SAVEHIS…
1056 } else {
1057 tmoveto(term.c.x, term.c.y+1);
1058 }
1059 @@ -2371,7 +2535,7 @@ eschandle(uchar ascii)
1060 break;
1061 case 'M': /* RI -- Reverse index */
1062 if (term.c.y == term.top) {
1063 - tscrolldown(term.top, 1, 1);
1064 + tscrolldown(term.top, 1);
1065 } else {
1066 tmoveto(term.c.x, term.c.y-1);
1067 }
1068 @@ -2511,7 +2675,8 @@ check_control_code:
1069 */
1070 return;
1071 }
1072 - if (selected(term.c.x, term.c.y))
1073 + /* selected() takes relative coordinates */
1074 + if (selected(term.c.x + term.scr, term.c.y + term.scr))
1075 selclear();
1076
1077 gp = &term.line[term.c.y][term.c.x];
1078 @@ -2546,6 +2711,7 @@ check_control_code:
1079 if (term.c.x+width < term.col) {
1080 tmoveto(term.c.x+width, term.c.y);
1081 } else {
1082 + term.wrapcwidth[IS_SET(MODE_ALTSCREEN)] = width;
1083 term.c.state |= CURSOR_WRAPNEXT;
1084 }
1085 }
1086 @@ -2583,93 +2749,275 @@ twrite(const char *buf, int buflen, int show_ct…
1087 }
1088
1089 void
1090 -tresize(int col, int row)
1091 +treflow(int col, int row)
1092 {
1093 int i, j;
1094 - int minrow = MIN(row, term.row);
1095 - int mincol = MIN(col, term.col);
1096 - int *bp;
1097 - TCursor c;
1098 -
1099 - if (col < 1 || row < 1) {
1100 - fprintf(stderr,
1101 - "tresize: error resizing to %dx%d\n", col, row);
1102 - return;
1103 + int oce, nce, bot, scr;
1104 + int ox = 0, oy = -term.histf, nx = 0, ny = -1, len;
1105 + int cy = -1; /* proxy for new y coordinate of cursor */
1106 + int nlines;
1107 + Line *buf, line;
1108 +
1109 + /* y coordinate of cursor line end */
1110 + for (oce = term.c.y; oce < term.row - 1 &&
1111 + tiswrapped(term.line[oce]); oce++);
1112 +
1113 + nlines = term.histf + oce + 1;
1114 + if (col < term.col) {
1115 + /* each line can take this many lines after reflow */
1116 + j = (term.col + col - 1) / col;
1117 + nlines = j * nlines;
1118 + if (nlines > HISTSIZE + RESIZEBUFFER + row) {
1119 + nlines = HISTSIZE + RESIZEBUFFER + row;
1120 + oy = -(nlines / j - oce - 1);
1121 + }
1122 }
1123 + buf = xmalloc(nlines * sizeof(Line));
1124 + do {
1125 + if (!nx)
1126 + buf[++ny] = xmalloc(col * sizeof(Glyph));
1127 + if (!ox) {
1128 + line = TLINEABS(oy);
1129 + len = tlinelen(line);
1130 + }
1131 + if (oy == term.c.y) {
1132 + if (!ox)
1133 + len = MAX(len, term.c.x + 1);
1134 + /* update cursor */
1135 + if (cy < 0 && term.c.x - ox < col - nx) {
1136 + term.c.x = nx + term.c.x - ox, cy = ny;
1137 + UPDATEWRAPNEXT(0, col);
1138 + }
1139 + }
1140 + /* get reflowed lines in buf */
1141 + if (col - nx > len - ox) {
1142 + memcpy(&buf[ny][nx], &line[ox], (len-ox) * size…
1143 + nx += len - ox;
1144 + if (len == 0 || !(line[len - 1].mode & ATTR_WRA…
1145 + for (j = nx; j < col; j++)
1146 + tclearglyph(&buf[ny][j], 0);
1147 + nx = 0;
1148 + } else if (nx > 0) {
1149 + buf[ny][nx - 1].mode &= ~ATTR_WRAP;
1150 + }
1151 + ox = 0, oy++;
1152 + } else if (col - nx == len - ox) {
1153 + memcpy(&buf[ny][nx], &line[ox], (col-nx) * size…
1154 + ox = 0, oy++, nx = 0;
1155 + } else/* if (col - nx < len - ox) */ {
1156 + memcpy(&buf[ny][nx], &line[ox], (col-nx) * size…
1157 + ox += col - nx;
1158 + buf[ny][col - 1].mode |= ATTR_WRAP;
1159 + nx = 0;
1160 + }
1161 + } while (oy <= oce);
1162 + if (nx)
1163 + for (j = nx; j < col; j++)
1164 + tclearglyph(&buf[ny][j], 0);
1165
1166 - /*
1167 - * slide screen to keep cursor where we expect it -
1168 - * tscrollup would work here, but we can optimize to
1169 - * memmove because we're freeing the earlier lines
1170 - */
1171 - for (i = 0; i <= term.c.y - row; i++) {
1172 + /* free extra lines */
1173 + for (i = row; i < term.row; i++)
1174 free(term.line[i]);
1175 - free(term.alt[i]);
1176 + /* resize to new height */
1177 + term.line = xrealloc(term.line, row * sizeof(Line));
1178 +
1179 + bot = MIN(ny, row - 1);
1180 + scr = MAX(row - term.row, 0);
1181 + /* update y coordinate of cursor line end */
1182 + nce = MIN(oce + scr, bot);
1183 + /* update cursor y coordinate */
1184 + term.c.y = nce - (ny - cy);
1185 + if (term.c.y < 0) {
1186 + j = nce, nce = MIN(nce + -term.c.y, bot);
1187 + term.c.y += nce - j;
1188 + while (term.c.y < 0) {
1189 + free(buf[ny--]);
1190 + term.c.y++;
1191 + }
1192 }
1193 - /* ensure that both src and dst are not NULL */
1194 - if (i > 0) {
1195 - memmove(term.line, term.line + i, row * sizeof(Line));
1196 - memmove(term.alt, term.alt + i, row * sizeof(Line));
1197 + /* allocate new rows */
1198 + for (i = row - 1; i > nce; i--) {
1199 + term.line[i] = xmalloc(col * sizeof(Glyph));
1200 + for (j = 0; j < col; j++)
1201 + tclearglyph(&term.line[i][j], 0);
1202 }
1203 - for (i += row; i < term.row; i++) {
1204 + /* fill visible area */
1205 + for (/*i = nce */; i >= term.row; i--, ny--)
1206 + term.line[i] = buf[ny];
1207 + for (/*i = term.row - 1 */; i >= 0; i--, ny--) {
1208 free(term.line[i]);
1209 - free(term.alt[i]);
1210 + term.line[i] = buf[ny];
1211 + }
1212 + /* fill lines in history buffer and update term.histf */
1213 + for (/*i = -1 */; ny >= 0 && i >= -HISTSIZE; i--, ny--) {
1214 + j = (term.histi + i + 1 + HISTSIZE) % HISTSIZE;
1215 + free(term.hist[j]);
1216 + term.hist[j] = buf[ny];
1217 + }
1218 + term.histf = -i - 1;
1219 + term.scr = MIN(term.scr, term.histf);
1220 + /* resize rest of the history lines */
1221 + for (/*i = -term.histf - 1 */; i >= -HISTSIZE; i--) {
1222 + j = (term.histi + i + 1 + HISTSIZE) % HISTSIZE;
1223 + term.hist[j] = xrealloc(term.hist[j], col * sizeof(Glyp…
1224 }
1225 + free(buf);
1226 +}
1227
1228 - /* resize to new height */
1229 - term.line = xrealloc(term.line, row * sizeof(Line));
1230 - term.alt = xrealloc(term.alt, row * sizeof(Line));
1231 - term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
1232 - term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
1233 +void
1234 +rscrolldown(int n)
1235 +{
1236 + int i;
1237 + Line temp;
1238
1239 - for (i = 0; i < HISTSIZE; i++) {
1240 - term.hist[i] = xrealloc(term.hist[i], col * sizeof(Glyp…
1241 - for (j = mincol; j < col; j++) {
1242 - term.hist[i][j] = term.c.attr;
1243 - term.hist[i][j].u = ' ';
1244 - }
1245 - }
1246 + /* can never be true as of now
1247 + if (IS_SET(MODE_ALTSCREEN))
1248 + return; */
1249
1250 - /* resize each row to new width, zero-pad if needed */
1251 - for (i = 0; i < minrow; i++) {
1252 - term.line[i] = xrealloc(term.line[i], col * sizeof(Glyp…
1253 - term.alt[i] = xrealloc(term.alt[i], col * sizeof(Glyp…
1254 - }
1255 + if ((n = MIN(n, term.histf)) <= 0)
1256 + return;
1257
1258 - /* allocate any new rows */
1259 - for (/* i = minrow */; i < row; i++) {
1260 - term.line[i] = xmalloc(col * sizeof(Glyph));
1261 - term.alt[i] = xmalloc(col * sizeof(Glyph));
1262 + for (i = term.c.y + n; i >= n; i--) {
1263 + temp = term.line[i];
1264 + term.line[i] = term.line[i-n];
1265 + term.line[i-n] = temp;
1266 }
1267 + for (/*i = n - 1 */; i >= 0; i--) {
1268 + temp = term.line[i];
1269 + term.line[i] = term.hist[term.histi];
1270 + term.hist[term.histi] = temp;
1271 + term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE;
1272 + }
1273 + term.c.y += n;
1274 + term.histf -= n;
1275 + if ((i = term.scr - n) >= 0) {
1276 + term.scr = i;
1277 + } else {
1278 + term.scr = 0;
1279 + if (sel.ob.x != -1 && !sel.alt)
1280 + selmove(-i);
1281 + }
1282 +}
1283 +
1284 +void
1285 +tresize(int col, int row)
1286 +{
1287 + int *bp;
1288 +
1289 + /* col and row are always MAX(_, 1)
1290 + if (col < 1 || row < 1) {
1291 + fprintf(stderr, "tresize: error resizing to %dx%d\n", c…
1292 + return;
1293 + } */
1294 +
1295 + term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty));
1296 + term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs));
1297 if (col > term.col) {
1298 bp = term.tabs + term.col;
1299 -
1300 memset(bp, 0, sizeof(*term.tabs) * (col - term.col));
1301 while (--bp > term.tabs && !*bp)
1302 /* nothing */ ;
1303 for (bp += tabspaces; bp < term.tabs + col; bp += tabsp…
1304 *bp = 1;
1305 }
1306 - /* update terminal size */
1307 - term.col = col;
1308 - term.row = row;
1309 - /* reset scrolling region */
1310 - tsetscroll(0, row-1);
1311 - /* make use of the LIMIT in tmoveto */
1312 - tmoveto(term.c.x, term.c.y);
1313 - /* Clearing both screens (it makes dirty all lines) */
1314 - c = term.c;
1315 - for (i = 0; i < 2; i++) {
1316 - if (mincol < col && 0 < minrow) {
1317 - tclearregion(mincol, 0, col - 1, minrow - 1);
1318 +
1319 + if (IS_SET(MODE_ALTSCREEN))
1320 + tresizealt(col, row);
1321 + else
1322 + tresizedef(col, row);
1323 +}
1324 +
1325 +void
1326 +tresizedef(int col, int row)
1327 +{
1328 + int i, j;
1329 +
1330 + /* return if dimensions haven't changed */
1331 + if (term.col == col && term.row == row) {
1332 + tfulldirt();
1333 + return;
1334 + }
1335 + if (col != term.col) {
1336 + if (!sel.alt)
1337 + selremove();
1338 + treflow(col, row);
1339 + } else {
1340 + /* slide screen up if otherwise cursor would get out of…
1341 + if (term.c.y >= row) {
1342 + tscrollup(0, term.row - 1, term.c.y - row + 1, …
1343 + term.c.y = row - 1;
1344 }
1345 - if (0 < col && minrow < row) {
1346 - tclearregion(0, minrow, col - 1, row - 1);
1347 + for (i = row; i < term.row; i++)
1348 + free(term.line[i]);
1349 +
1350 + /* resize to new height */
1351 + term.line = xrealloc(term.line, row * sizeof(Line));
1352 + /* allocate any new rows */
1353 + for (i = term.row; i < row; i++) {
1354 + term.line[i] = xmalloc(col * sizeof(Glyph));
1355 + for (j = 0; j < col; j++)
1356 + tclearglyph(&term.line[i][j], 0);
1357 }
1358 - tswapscreen();
1359 - tcursor(CURSOR_LOAD);
1360 + /* scroll down as much as height has increased */
1361 + rscrolldown(row - term.row);
1362 + }
1363 + /* update terminal size */
1364 + term.col = col, term.row = row;
1365 + /* reset scrolling region */
1366 + term.top = 0, term.bot = row - 1;
1367 + /* dirty all lines */
1368 + tfulldirt();
1369 +}
1370 +
1371 +void
1372 +tresizealt(int col, int row)
1373 +{
1374 + int i, j;
1375 +
1376 + /* return if dimensions haven't changed */
1377 + if (term.col == col && term.row == row) {
1378 + tfulldirt();
1379 + return;
1380 }
1381 - term.c = c;
1382 + if (sel.alt)
1383 + selremove();
1384 + /* slide screen up if otherwise cursor would get out of the scr…
1385 + for (i = 0; i <= term.c.y - row; i++)
1386 + free(term.line[i]);
1387 + if (i > 0) {
1388 + /* ensure that both src and dst are not NULL */
1389 + memmove(term.line, term.line + i, row * sizeof(Line));
1390 + term.c.y = row - 1;
1391 + }
1392 + for (i += row; i < term.row; i++)
1393 + free(term.line[i]);
1394 + /* resize to new height */
1395 + term.line = xrealloc(term.line, row * sizeof(Line));
1396 + /* resize to new width */
1397 + for (i = 0; i < MIN(row, term.row); i++) {
1398 + term.line[i] = xrealloc(term.line[i], col * sizeof(Glyp…
1399 + for (j = term.col; j < col; j++)
1400 + tclearglyph(&term.line[i][j], 0);
1401 + }
1402 + /* allocate any new rows */
1403 + for (/*i = MIN(row, term.row) */; i < row; i++) {
1404 + term.line[i] = xmalloc(col * sizeof(Glyph));
1405 + for (j = 0; j < col; j++)
1406 + tclearglyph(&term.line[i][j], 0);
1407 + }
1408 + /* update cursor */
1409 + if (term.c.x >= col) {
1410 + term.c.state &= ~CURSOR_WRAPNEXT;
1411 + term.c.x = col - 1;
1412 + } else {
1413 + UPDATEWRAPNEXT(1, col);
1414 + }
1415 + /* update terminal size */
1416 + term.col = col, term.row = row;
1417 + /* reset scrolling region */
1418 + term.top = 0, term.bot = row - 1;
1419 + /* dirty all lines */
1420 + tfulldirt();
1421 }
1422
1423 void
1424 diff --git a/st.h b/st.h
1425 index 818a6f8..514ec08 100644
1426 --- a/st.h
1427 +++ b/st.h
1428 @@ -22,17 +22,19 @@
1429
1430 enum glyph_attribute {
1431 ATTR_NULL = 0,
1432 - ATTR_BOLD = 1 << 0,
1433 - ATTR_FAINT = 1 << 1,
1434 - ATTR_ITALIC = 1 << 2,
1435 - ATTR_UNDERLINE = 1 << 3,
1436 - ATTR_BLINK = 1 << 4,
1437 - ATTR_REVERSE = 1 << 5,
1438 - ATTR_INVISIBLE = 1 << 6,
1439 - ATTR_STRUCK = 1 << 7,
1440 - ATTR_WRAP = 1 << 8,
1441 - ATTR_WIDE = 1 << 9,
1442 - ATTR_WDUMMY = 1 << 10,
1443 + ATTR_SET = 1 << 0,
1444 + ATTR_BOLD = 1 << 1,
1445 + ATTR_FAINT = 1 << 2,
1446 + ATTR_ITALIC = 1 << 3,
1447 + ATTR_UNDERLINE = 1 << 4,
1448 + ATTR_BLINK = 1 << 5,
1449 + ATTR_REVERSE = 1 << 6,
1450 + ATTR_INVISIBLE = 1 << 7,
1451 + ATTR_STRUCK = 1 << 8,
1452 + ATTR_WRAP = 1 << 9,
1453 + ATTR_WIDE = 1 << 10,
1454 + ATTR_WDUMMY = 1 << 11,
1455 + ATTR_SELECTED = 1 << 12,
1456 ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
1457 };
1458
1459 @@ -90,6 +92,7 @@ void toggleprinter(const Arg *);
1460
1461 int tattrset(int);
1462 void tnew(int, int);
1463 +int tisaltscreen(void);
1464 void tresize(int, int);
1465 void tsetdirtattr(int);
1466 void ttyhangup(void);
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.