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 			}