commit efaab74

uint  ·  2026-05-14 18:12:13 +0000 UTC
parent 500c495
add terminal delayed autowrapping
2 files changed,  +31, -4
+1, -0
1@@ -45,6 +45,7 @@ typedef struct {
2 	pid_t          ptypid;
3 
4 	enum TState    state;
5+	bool           wrapnext;
6 	int            csi_params[CSI_PARAMS_MAX];
7 	int            csi_idx;
8 	char           utf8[4];
+30, -4
  1@@ -72,6 +72,7 @@ static void csi_dispatch(Term* t, Caret* c, unsigned char ch)
  2 	switch (ch) {
  3 	case 'H': /* CUP - Cursor Position - ESC[row;colH */
  4 	case 'f': { /* HVP - Horizontal and Vertical Postion - ESC[row;colf */
  5+		t->wrapnext = false;
  6 		int row = csi_arg(t, 0, 1) - 1;
  7 		int col = csi_arg(t, 1, 1) - 1;
  8 
  9@@ -109,6 +110,7 @@ static void csi_dispatch(Term* t, Caret* c, unsigned char ch)
 10 		break;
 11 
 12 	case 'A': { /* CUU - cursor up */
 13+		t->wrapnext = false;
 14 		int n = csi_arg(t, 0, 1);
 15 		c->y -= n;
 16 		if (c->y < 0)
 17@@ -117,6 +119,7 @@ static void csi_dispatch(Term* t, Caret* c, unsigned char ch)
 18 	}
 19 
 20 	case 'B': { /* CUD - cursor down */
 21+		t->wrapnext = false;
 22 		int n = csi_arg(t, 0, 1);
 23 		c->y += n;
 24 		if (c->y >= t->rows)
 25@@ -125,6 +128,7 @@ static void csi_dispatch(Term* t, Caret* c, unsigned char ch)
 26 	}
 27 
 28 	case 'C': { /* CUF - cursor forward */
 29+		t->wrapnext = false;
 30 		int n = csi_arg(t, 0, 1);
 31 		c->x += n;
 32 		if (c->x >= t->cols)
 33@@ -133,6 +137,7 @@ static void csi_dispatch(Term* t, Caret* c, unsigned char ch)
 34 	}
 35 
 36 	case 'D': { /* CUB - cursor back */
 37+			  t->wrapnext = false;
 38 			  int n = csi_arg(t, 0, 1);
 39 			  c->x -= n;
 40 			  if (c->x < 0)
 41@@ -141,6 +146,7 @@ static void csi_dispatch(Term* t, Caret* c, unsigned char ch)
 42 	}
 43 
 44 	case 'G': { /* CHA - cursor horizontal absolute */
 45+			  t->wrapnext = false;
 46 			  int col = csi_arg(t, 0, 1) - 1;
 47 
 48 			  if (col < 0)
 49@@ -153,6 +159,7 @@ static void csi_dispatch(Term* t, Caret* c, unsigned char ch)
 50 	}
 51 
 52 	case 'd': { /* VPA - vertical position absolute */
 53+			  t->wrapnext = false;
 54 			  int row = csi_arg(t, 0, 1) - 1;
 55 
 56 			  if (row < 0)
 57@@ -165,20 +172,24 @@ static void csi_dispatch(Term* t, Caret* c, unsigned char ch)
 58 	}
 59 
 60 	case 'L': /* IL - Insert Line */
 61+		t->wrapnext = false;
 62 		if (c->y >= t->scroll_top && c->y <= t->scroll_bot)
 63 			scroll_down(t, c->y, t->scroll_bot, csi_arg(t, 0, 1));
 64 		break;
 65 
 66 	case 'M': /* DL - Delete Line */
 67+		t->wrapnext = false;
 68 		if (c->y >= t->scroll_top && c->y <= t->scroll_bot)
 69 			scroll_up(t, c->y, t->scroll_bot, csi_arg(t, 0, 1));
 70 		break;
 71 
 72 	case 'S': /* SU - Scroll Up */
 73+		t->wrapnext = false;
 74 		scroll_up(t, t->scroll_top, t->scroll_bot, csi_arg(t, 0, 1));
 75 		break;
 76 
 77 	case 'T': /* SD - Scroll Down */
 78+		t->wrapnext = false;
 79 		scroll_down(t, t->scroll_top, t->scroll_bot, csi_arg(t, 0, 1));
 80 		break;
 81 
 82@@ -204,6 +215,7 @@ static void csi_dispatch(Term* t, Caret* c, unsigned char ch)
 83 		break;
 84 	}
 85 	case 'r': { /* DECSTBM - scrolling region */
 86+		t->wrapnext = false;
 87 		int top = csi_arg(t, 0, 1) - 1;
 88 		int bot = csi_arg(t, 1, t->rows) - 1;
 89 		if (top < 0)
 90@@ -219,7 +231,7 @@ static void csi_dispatch(Term* t, Caret* c, unsigned char ch)
 91 		break;
 92 	}
 93 	case 's': t->saved = *c; break; /* save cursor */
 94-	case 'u': *c = t->saved; break; /* restore cursor */
 95+	case 'u': t->wrapnext = false; *c = t->saved; break; /* restore cursor */
 96 
 97 	default: /* Unsupported CSI */
 98 		break;
 99@@ -433,6 +445,7 @@ void term_clear(Term* t, Caret* c)
100 
101 	c->x = 0;
102 	c->y = 0;
103+	t->wrapnext = false;
104 }
105 
106 void term_damage_all(Term* t)
107@@ -455,9 +468,11 @@ void term_putc(Term* t, Caret* c, uint32_t cp)
108 	switch (cp) {
109 	case '\r':
110 		c->x = 0;
111+		t->wrapnext = false;
112 		break;
113 	case '\n':
114 		c->x = 0;
115+		t->wrapnext = false;
116 		if (c->y == t->scroll_bot) {
117 			term_scroll(t);
118 		}
119@@ -465,10 +480,12 @@ void term_putc(Term* t, Caret* c, uint32_t cp)
120 			c->y++;
121 		break;
122 	case '\b':
123+		t->wrapnext = false;
124 		if (c->x > 0)
125 			c->x--;
126 		break;
127 	case '\t':
128+		t->wrapnext = false;
129 		/* move cursor to next tabstop */
130 		c->x = (c->x+8) & ~0x7;
131 		if (c->x >= t->cols)
132@@ -478,6 +495,11 @@ void term_putc(Term* t, Caret* c, uint32_t cp)
133 		if (cp < 32)
134 			break;
135 
136+		if (t->wrapnext) {
137+			term_putc(t, c, '\n');
138+			t->wrapnext = false;
139+		}
140+
141 		Rune* r = &RUNE(t, c->x, c->y);
142 		if (r->cp != cp || r->fg != t->fg || r->bg != t->bg) {
143 			r->cp = cp;
144@@ -485,9 +507,10 @@ void term_putc(Term* t, Caret* c, uint32_t cp)
145 			r->bg = t->bg;
146 			r->dmg = true;
147 		}
148-		c->x++;
149-		if (c->x >= t->cols)
150-			term_putc(t, c, '\n');
151+		if (c->x == t->cols - 1)
152+			t->wrapnext = true;
153+		else
154+			c->x++;
155 
156 		break;
157 	}
158@@ -560,6 +583,7 @@ int term_resize(Term* t, Caret* c, int cols, int rows)
159 		c->x = 0;
160 	if (c->y < 0)
161 		c->y = 0;
162+	t->wrapnext = false;
163 	if (t->saved.x >= cols)
164 		t->saved.x = cols - 1;
165 	if (t->saved.y >= rows)
166@@ -606,6 +630,7 @@ bool term_write(Term* t, Caret* c, const char* s, size_t n)
167 				t->state = TSTATE_NORMAL;
168 			}
169 			else if (ch == 'M') {
170+				t->wrapnext = false;
171 				if (c->y == t->scroll_top)
172 					scroll_down(t, t->scroll_top, t->scroll_bot, 1);
173 				else if (c->y > 0)
174@@ -613,6 +638,7 @@ bool term_write(Term* t, Caret* c, const char* s, size_t n)
175 				t->state = TSTATE_NORMAL;
176 			}
177 			else if (ch == 'D' || ch == 'E') {
178+				t->wrapnext = false;
179 				if (ch == 'E')
180 					c->x = 0;
181 				if (c->y == t->scroll_bot)