commit c719485
uint
·
2026-05-14 16:58:44 +0000 UTC
parent 0018ec7
add alternate screen, cursor restore .
3 files changed,
+71,
-4
+1,
-0
1@@ -58,6 +58,7 @@ static Term term = {
2 static void cleanup(void)
3 {
4 free(term.runes);
5+ free(term.alt);
6 font_free(&font);
7
8 if (surf)
+2,
-0
1@@ -31,6 +31,7 @@ typedef struct {
2
3 typedef struct {
4 Rune* runes;
5+ Rune* alt;
6 uint32_t fg;
7 uint32_t bg;
8
9@@ -43,6 +44,7 @@ typedef struct {
10 enum TState state;
11 int csi_params[CSI_PARAMS_MAX];
12 int csi_idx;
13+ Caret saved;
14 char utf8[4];
15 size_t utf8_len;
16 } Term;
+68,
-4
1@@ -8,6 +8,7 @@
2 #include "utils.h"
3
4 static int csi_arg(Term* t, int i, int fallback);
5+static void alt_screen(Term* t, Caret* c, bool on);
6 static void csi_dispatch(Term* t, Caret* c, unsigned char ch);
7 static void csi_reset(Term* t);
8 static void erase_display(Term* t, Caret* c);
9@@ -36,6 +37,32 @@ static int csi_arg(Term* t, int i, int fallback)
10 return t->csi_params[i];
11 }
12
13+/** TODO
14+ */
15+static void alt_screen(Term* t, Caret* c, bool on)
16+{
17+ Rune* tmp;
18+
19+ if (on) {
20+ if (t->alt)
21+ return;
22+ tmp = calloc(t->cols*t->rows, sizeof(*tmp));
23+ if (!tmp)
24+ return;
25+ t->alt = t->runes;
26+ t->runes = tmp;
27+ term_clear(t, c);
28+ return;
29+ }
30+
31+ if (!t->alt)
32+ return;
33+ free(t->runes);
34+ t->runes = t->alt;
35+ t->alt = NULL;
36+ term_damage_all(t);
37+}
38+
39 /** TODO
40 */
41 static void csi_dispatch(Term* t, Caret* c, unsigned char ch)
42@@ -128,13 +155,31 @@ static void csi_dispatch(Term* t, Caret* c, unsigned char ch)
43 break;
44 }
45
46- /* TODO? unsupported */
47 case 'h': /* set mode */
48- case 'l': /* reset mode */
49+ case 'l': { /* reset mode */
50+ bool on = ch == 'h';
51+ for (int i = 0; i <= t->csi_idx; i++) {
52+ int p = t->csi_params[i];
53+ if (p == 1048) {
54+ if (on)
55+ t->saved = *c;
56+ else
57+ *c = t->saved;
58+ }
59+ if (p == 47 || p == 1047 || p == 1049) {
60+ if (on && p == 1049)
61+ t->saved = *c;
62+ alt_screen(t, c, on);
63+ if (!on && p == 1049)
64+ *c = t->saved;
65+ }
66+ }
67+ break;
68+ }
69 case 'r': /* scrolling region */
70- case 's': /* save cursor */
71- case 'u': /* restore cursor */
72 break;
73+ case 's': t->saved = *c; break; /* save cursor */
74+ case 'u': *c = t->saved; break; /* restore cursor */
75
76 default: /* Unsupported CSI */
77 break;
78@@ -371,6 +416,13 @@ int term_resize(Term* t, Caret* c, int cols, int rows)
79 int ocols = t->cols;
80 int orows = t->rows;
81
82+ if (t->alt) {
83+ free(t->runes);
84+ t->runes = t->alt;
85+ t->alt = NULL;
86+ or = t->runes;
87+ }
88+
89 if (cols < 1)
90 cols = 1;
91 if (rows < 1)
92@@ -422,6 +474,10 @@ int term_resize(Term* t, Caret* c, int cols, int rows)
93 c->x = 0;
94 if (c->y < 0)
95 c->y = 0;
96+ if (t->saved.x >= cols)
97+ t->saved.x = cols - 1;
98+ if (t->saved.y >= rows)
99+ t->saved.y = rows - 1;
100
101 return 0;
102 }
103@@ -469,6 +525,14 @@ bool term_write(Term* t, Caret* c, const char* s, size_t n)
104 csi_reset(t);
105 t->state = TSTATE_CSI;
106 }
107+ else if (ch == '7') {
108+ t->saved = *c;
109+ t->state = TSTATE_NORMAL;
110+ }
111+ else if (ch == '8') {
112+ *c = t->saved;
113+ t->state = TSTATE_NORMAL;
114+ }
115 else {
116 t->state = TSTATE_NORMAL;
117 }