Browse Source

Fix bugs in terminal

Björn Åström 1 year ago
parent
commit
b51700fe1c
2 changed files with 54 additions and 11 deletions
  1. 53 11
      term.c
  2. 1 0
      term.h

+ 53 - 11
term.c

@@ -76,9 +76,12 @@ static void term_line_feed(struct term *t)
 {
 	if (t->cursor.y == t->num_rows - 1) {
 		for (int i = 1; i < t->num_rows; i++) {
-			memcpy(t->rows[i-1].cells, t->rows[i].cells, t->num_cols);
+			memcpy(t->rows[i-1].cells, t->rows[i].cells, t->num_cols * sizeof(struct cell));
+		}
+
+		for (int i = 0; i < t->num_cols; i++) {
+			t->rows[t->cursor.y].cells[i].c = ' ';
 		}
-		memset(t->rows[t->cursor.y].cells, ' ', t->num_cols);
 	} else {
 		t->cursor.y++;
 	}
@@ -92,7 +95,7 @@ static void term_print(struct term *t, char c) {
 	cur_cell->sgra = t->sgra;
 
 	if (t->cursor.x >= t->num_cols - 1) {
-		term_cursor_move_down(t, 1);
+		term_line_feed(t);
 		t->cursor.x = 0;
 	} else {
 		t->cursor.x++;
@@ -139,7 +142,6 @@ static void term_execute(struct term *t, char c) {
 
 		case '\r': t->cursor.x = 0; break;
 
-
 		case '\t':
 			term_print(t, ' ');
 			term_print(t, ' ');
@@ -234,7 +236,6 @@ static void term_csi_sgr(struct term *t) {
 			t->sgra.normal = 0;
 			switch (p) {
 				case 1: t->sgra.bold = 1; break;
-
 				case 30 ... 37: t->sgra.fg = p - 30; break;
 				case 40 ... 47: t->sgra.bg = p - 40; break;
 			}
@@ -247,13 +248,13 @@ static void term_csi_dispatch(struct term *t, char c) {
 	int p1 = t->params[1];
 
 	switch (c) {
-		case 'A': term_cursor_move_up(t, p0); break;
+		case 'A': term_cursor_move_up(t, p0 == 0 ? 1 : p0); break;
 		
-		case 'B': term_cursor_move_down(t, p0); break;
+		case 'B': term_cursor_move_down(t, p0 == 0 ? 1 : p0); break;
 		
-		case 'C': term_cursor_move_right(t, p0); break;
+		case 'C': term_cursor_move_right(t, p0 == 0 ? 1 : p0); break;
 		
-		case 'D': term_cursor_move_left(t, p0); break;
+		case 'D': term_cursor_move_left(t, p0 == 0 ? 1 : p0); break;
 
 		case 'E': t->cursor.x = 0; term_cursor_move_down(t, p0 == 0 ? 1 : p0); break;
 		
@@ -271,6 +272,14 @@ static void term_csi_dispatch(struct term *t, char c) {
 	}
 }
 
+static void term_esc_dispatch(struct term *t, char c) {
+	switch (c) {
+		case 'D': term_line_feed(t); break;
+
+		case 'E': t->cursor.x = 0; term_line_feed(t); break;
+	}
+}
+
 void term_putc(struct term *t, char c)
 {
 	// Loosely based on a very (very) limited subset of the state machine at https://vt100.net/emu/dec_ansi_parser
@@ -298,9 +307,29 @@ void term_putc(struct term *t, char c)
 				case 0x19:
 				case 0x1c ... 0x1f: term_execute(t, c); break;
 
+				case 0x20 ... 0x2f: term_collect(t, c); t->state = TERM_STATE_ESC_INTERMEDIATE; break;
+
+				case 0x30 ... 0x4f:
+				case 0x51 ... 0x57:
+				case 0x59:
+				case 0x5a:
+				case 0x5c:
+				case 0x60 ... 0x7e: term_esc_dispatch(t, c); t->state = TERM_STATE_GROUND; break;
+
 				case 0x5b: t->state = TERM_STATE_CSI_ENTRY; break;
+			} break;
+
+		case TERM_STATE_ESC_INTERMEDIATE:
+			switch (c) {
+				case 0x00 ... 0x17:
+				case 0x19:
+				case 0x1c ... 0x1f: term_execute(t, c); break;
 
-				default: t->state = TERM_STATE_GROUND; break;
+				case 0x1b: t->state = TERM_STATE_ESC; break;
+
+				case 0x20 ... 0x2f: term_collect(t, c); break;
+
+				case 0x30 ... 0x7e: term_esc_dispatch(t, c); t->state = TERM_STATE_GROUND; break;
 			} break;
 
 		case TERM_STATE_CSI_ENTRY:
@@ -313,11 +342,13 @@ void term_putc(struct term *t, char c)
 				case 0x19:
 				case 0x1c ... 0x1f: term_execute(t, c); break;
 
+				case 0x1b: t->state = TERM_STATE_ESC; break;
+
 				case 0x20 ... 0x2f: term_collect(t, c); t->state = TERM_STATE_CSI_INTERMEDIATE; break;
 
 				case 0x3a: t->state = TERM_STATE_CSI_IGNORE; break;
 
-				case 0x3c ... 0x3f: /* Ignore privates??? */ break;
+				case 0x3c ... 0x3f: term_collect(t, c); break;
 
 				case 0x30 ... 0x39:
 				case 0x3b:
@@ -333,6 +364,8 @@ void term_putc(struct term *t, char c)
 				case 0x19:
 				case 0x1c ... 0x1f: term_execute(t, c); break;
 
+				case 0x1b: t->state = TERM_STATE_ESC; break;
+
 				case 0x20 ... 0x2f: term_collect(t, c); t->state = TERM_STATE_CSI_INTERMEDIATE; break;
 
 				case 0x30 ... 0x39:
@@ -348,6 +381,12 @@ void term_putc(struct term *t, char c)
 		case TERM_STATE_CSI_INTERMEDIATE:
 			// events
 			switch (c) {
+				case 0x00 ... 0x17:
+				case 0x19:
+				case 0x1c ... 0x1f: term_execute(t, c); break;
+
+				case 0x1b: t->state = TERM_STATE_ESC; break;
+
 				case 0x20 ... 0x2f: term_collect(t, c); break;
 
 				case 0x30 ... 0x3f: t->state = TERM_STATE_CSI_IGNORE; break;
@@ -362,6 +401,8 @@ void term_putc(struct term *t, char c)
 				case 0x19:
 				case 0x1c ... 0x1f: term_execute(t, c); break;
 
+				case 0x1b: t->state = TERM_STATE_ESC; break;
+
 				case 0x40 ... 0x7e: t->state = TERM_STATE_GROUND; break;
 			} break;
 
@@ -397,6 +438,7 @@ static char *xml_entity(char *str, char c) {
 
 char *term_to_string(struct term *t)
 {
+	// TODO: Allocate once
 	// TODO: don't allocate too much if pango is not used.
 	int str_size = t->num_rows * t->num_cols * 128 + t->num_rows;
 	char *ret = calloc(str_size, sizeof(char));

+ 1 - 0
term.h

@@ -8,6 +8,7 @@
 enum term_state {
 	TERM_STATE_GROUND,
 	TERM_STATE_ESC,
+	TERM_STATE_ESC_INTERMEDIATE,
 	TERM_STATE_CSI_ENTRY,
 	TERM_STATE_CSI_PARAM,
 	TERM_STATE_CSI_INTERMEDIATE,