yterm

commit f7a46a8a6759937888bf3628821e7ec29bcb04bc

Author: mesyeti <mesyeti@mesyeti.uk>

some fixes

 source/app.c | 6 
 source/app.h | 1 
 source/backend.c | 8 
 source/backend.h | 4 
 source/backends/soft.c | 5 
 source/interpreter/vt100.c | 262 ++++++++++++++++++++++++++-------------


diff --git a/source/app.c b/source/app.c
index 380ae20bebd39230d6490ae5bb82e027a61355e6..0ea86677576d5b754e8003e7d23ea1de8f5dbfb7 100644
--- a/source/app.c
+++ b/source/app.c
@@ -32,6 +32,7 @@ 	app.bindNewTab  = Input_AddKeyBind(KEY_LCTRL, KEY_LSHIFT, 0, KEY_T);
 	app.bindPrevTab = Input_AddKeyBind(KEY_LCTRL, 0,          0, KEY_PAGE_UP);
 	app.bindNextTab = Input_AddKeyBind(KEY_LCTRL, 0,          0, KEY_PAGE_DOWN);
 	app.bindReport  = Input_AddKeyBind(KEY_LCTRL, KEY_LSHIFT, 0, KEY_R);
+	app.bindRedraw  = Input_AddKeyBind(KEY_LCTRL, KEY_LSHIFT, 0, KEY_D);
 }
 
 static Pane* GetSelectedPane(Pane* pane) {
@@ -77,6 +78,11 @@
 		Log("REPORT");
 		Log("======");
 		Log("Cursor: %d, %d\n", term->cursor.x, term->cursor.y);
+		return true;
+	}
+	if (Input_MatchBind(app.bindRedraw, e)) {
+		Backend_SetRedraw();
+		Log("Redrawing...");
 		return true;
 	}
 




diff --git a/source/app.h b/source/app.h
index 27dffed7b82e9fd32897c7d387e268ef7e26dcde..097ab29a262c993935df22a9965e0b5bd324aacf 100644
--- a/source/app.h
+++ b/source/app.h
@@ -21,6 +21,7 @@ 	Input_BindID bindNewTab;
 	Input_BindID bindPrevTab;
 	Input_BindID bindNextTab;
 	Input_BindID bindReport;
+	Input_BindID bindRedraw;
 } App;
 
 extern App app;




diff --git a/source/backend.c b/source/backend.c
index 1de9556c194b15ab4194f8493a671ec3c53cfe7b..50335cb4814335a4244893dbcee5f2f0a8d95abf 100644
--- a/source/backend.c
+++ b/source/backend.c
@@ -30,12 +30,8 @@ void Backend_OnWindowResize(void) {
 	backend.onWindowResize();
 }
 
-void Backend_OnScreenUpdate(void) {
-	backend.onScreenUpdate();
-}
-
-void Backend_OnCellChange(int x, int y) {
-	backend.onCellChange(x, y);
+void Backend_SetRedraw(void) {
+	backend.setRedraw();
 }
 
 void Backend_Render(void) {




diff --git a/source/backend.h b/source/backend.h
index 4dadee10dceace2eaaa7d001f520a7fc7cb60b33..9cf8b2bfb5008e40263674283e076d93e84cc6fd 100644
--- a/source/backend.h
+++ b/source/backend.h
@@ -26,8 +26,7 @@ 	Texture* (*loadTexture)(uint8_t* data, int w, int h, int aW, int aH, int ch);
 	void     (*freeTexture)(Texture* texture);
 	Vec2     (*getTextureSize)(Texture* texture);
 	void     (*onWindowResize)(void);
-	void     (*onScreenUpdate)(void);
-	void     (*onCellChange)(int x, int y);
+	void     (*setRedraw)(void);
 	void     (*render)(void);
 } Backend;
 
@@ -38,6 +37,7 @@ Texture* Backend_LoadTexture(uint8_t* data, int w, int h, int aW, int aH, int ch);
 void     Backend_FreeTexture(Texture* texture);
 Vec2     Backend_GetTextureSize(Texture* texture);
 void     Backend_OnWindowResize(void);
+void     Backend_SetRedraw(void);
 void     Backend_Render(void);
 
 #endif




diff --git a/source/backends/soft.c b/source/backends/soft.c
index 33bc739521d929772494125104b5e4e5ef5254d8..d1adf6856c4944f1d1bbee20d5308610d2b997b8 100644
--- a/source/backends/soft.c
+++ b/source/backends/soft.c
@@ -230,6 +230,10 @@ 	SDL_RenderCopy(state.renderer, state.texture, NULL, NULL);
 	SDL_RenderPresent(state.renderer);
 }
 
+static void SetRedraw(void) {
+	state.redraw = true;
+}
+
 Backend Backend_Soft(void) {
 	return (Backend) {
 		.name           = "soft",
@@ -239,6 +243,7 @@ 		.loadTexture    = &LoadTexture,
 		.freeTexture    = &FreeTexture,
 		.getTextureSize = &GetTextureSize,
 		.onWindowResize = &OnWindowResize,
+		.setRedraw      = &SetRedraw,
 		.render         = &Render
 	};
 }




diff --git a/source/interpreter/vt100.c b/source/interpreter/vt100.c
index 62c82943b77502c5325461757f40124275be8f2d..f57285cb711475632abc07c8b53777d15b4b4e79 100644
--- a/source/interpreter/vt100.c
+++ b/source/interpreter/vt100.c
@@ -9,9 +9,11 @@
 enum {
 	MODE_READY = 0,
 	MODE_ESCAPE,
-	MODE_CSI,  // \e[
-	MODE_OSC,  // \e]
-	MODE_CHSET // \e(
+	MODE_CSI,     // \e[
+	MODE_OSC,     // \e]
+	MODE_CHSET,   // \e(
+	MODE_CHSET_P, // \e%
+	MODE_HASHTAG  // \e#
 };
 
 enum {
@@ -27,6 +29,7 @@
 	// terminal settings
 	bool bracketedPaste;
 	int  mouseMode;
+	Vec2 savedCursor;
 } Vt100;
 
 static char* KeyToSequence(Key key) {
@@ -168,6 +171,93 @@ 		terminal->cursor.y -= by;
 	}
 }
 
+static void PrintCSI(char** parts, size_t num, UChar ch) {
+	printf("CSI ");
+
+	for (size_t i = 0; i < num; ++ i) {
+		printf("%s ", parts[i]);
+	}
+
+	printf("%c\n", (char) ch);
+}
+
+static void ColourSeq(int part, Terminal* terminal) {
+	switch (part) {
+		case 0: {
+			terminal->attr.fgMode = BUF_DEFAULT;
+			terminal->attr.bgMode = BUF_DEFAULT;
+			terminal->attr.invert = false;
+			break;
+		}
+		case 1: break; // TODO: bold
+		case 4: break; // TODO: underline
+		case 5: break; // TODO: blink
+		case 7: {
+			terminal->attr.invert = true;
+			break;
+		}
+		case 8: break; // TODO: hidden
+		case 22: break; // TODO: normal
+		case 24: break; // TODO: not underlined
+		case 25: break; // TODO: steady - not blinking
+		case 27: {
+			terminal->attr.invert = false;
+			break;
+		}
+		case 28: break; // TODO: visible - not hidden
+		default: {
+			if (((part >= 30) && (part <= 39)) || ((part >= 90) && (part <= 97))) {
+				terminal->attr.fgMode = BUF_16COL;
+
+				switch (part) {
+					case 30: terminal->attr.fg.idx = 0x0; break; // black
+					case 31: terminal->attr.fg.idx = 0x1; break; // red
+					case 32: terminal->attr.fg.idx = 0x2; break; // green
+					case 33: terminal->attr.fg.idx = 0x3; break; // yellow
+					case 34: terminal->attr.fg.idx = 0x4; break; // blue
+					case 35: terminal->attr.fg.idx = 0x5; break; // magenta
+					case 36: terminal->attr.fg.idx = 0x6; break; // cyan
+					case 37: terminal->attr.fg.idx = 0x7; break; // white
+					case 39: terminal->attr.fgMode = BUF_DEFAULT; break;
+					case 90: terminal->attr.fg.idx = 0x8; break; // grey/bright black
+					case 91: terminal->attr.fg.idx = 0x9; break; // bright red
+					case 92: terminal->attr.fg.idx = 0xA; break; // bright green
+					case 93: terminal->attr.fg.idx = 0xB; break; // bright yellow
+					case 94: terminal->attr.fg.idx = 0xC; break; // bright blue
+					case 95: terminal->attr.fg.idx = 0xD; break; // bright magenta
+					case 96: terminal->attr.fg.idx = 0xE; break; // bright cyan
+					case 97: terminal->attr.fg.idx = 0xF; break; // bright white
+					default: break;
+				}
+			}
+			else if (((part >= 40) && (part <= 49)) || ((part >= 100) && (part <= 107))) {
+				terminal->attr.bgMode = BUF_16COL;
+
+				switch (part) {
+					case 40:  terminal->attr.bg.idx = 0x0; break; // black
+					case 41:  terminal->attr.bg.idx = 0x1; break; // red
+					case 42:  terminal->attr.bg.idx = 0x2; break; // green
+					case 43:  terminal->attr.bg.idx = 0x3; break; // yellow
+					case 44:  terminal->attr.bg.idx = 0x4; break; // blue
+					case 45:  terminal->attr.bg.idx = 0x5; break; // magenta
+					case 46:  terminal->attr.bg.idx = 0x6; break; // cyan
+					case 47:  terminal->attr.bg.idx = 0x7; break; // white
+					case 49:  terminal->attr.bgMode = BUF_DEFAULT; break;
+					case 100: terminal->attr.bg.idx = 0x8; break; // grey/bright black
+					case 101: terminal->attr.bg.idx = 0x9; break; // bright red
+					case 102: terminal->attr.bg.idx = 0xA; break; // bright green
+					case 103: terminal->attr.bg.idx = 0xB; break; // bright yellow
+					case 104: terminal->attr.bg.idx = 0xC; break; // bright blue
+					case 105: terminal->attr.bg.idx = 0xD; break; // bright magenta
+					case 106: terminal->attr.bg.idx = 0xE; break; // bright cyan
+					case 107: terminal->attr.bg.idx = 0xF; break; // bright white
+					default: break;
+				}
+			}
+		}
+	}
+}
+
 static void HandleCSI(Vt100* this, Terminal* terminal, UChar ch) {
 	// parse sequences
 	const char* str = this->reading;
@@ -180,6 +270,8 @@ 	}
 
 	size_t num;
 	char** parts = Split(str, &num, ';');
+
+	PrintCSI(parts, num, ch);
 
 	switch (ch) {
 		case 'A': { // move cursor up # lines
@@ -231,10 +323,15 @@ 			break;
 		}
 		case 'H':
 		case 'f': {
-			if (num < 2) return;
+			int y = 0;
+			int x = 0;
 
-			int y = atoi(parts[0]) - 1;
-			int x = atoi(parts[1]) - 1;
+			if (num >= 1) {
+				y = atoi(parts[0]) - 1;
+			}
+			if (num >= 2) {
+				x = atoi(parts[1]) - 1;
+			}
 
 			if (x < 0) x = 0;
 			if (y < 0) y = 0;
@@ -327,85 +424,15 @@ 			}
 			break;
 		}
 		case 'm': {
+			if (num == 0) {
+				ColourSeq(0, terminal);
+				break;
+			}
+
 			for (size_t i = 0; i < num; ++ i) {
 				int part = atoi(parts[i]);
 
-				// printf("CSI %d m\n", part);
-
-				switch (part) {
-					case 0: {
-						terminal->attr.fgMode = BUF_DEFAULT;
-						terminal->attr.bgMode = BUF_DEFAULT;
-						terminal->attr.invert = false;
-						break;
-					}
-					case 1: break; // TODO: bold
-					case 4: break; // TODO: underline
-					case 5: break; // TODO: blink
-					case 7: {
-						terminal->attr.invert = true;
-						break;
-					}
-					case 8: break; // TODO: hidden
-					case 22: break; // TODO: normal
-					case 24: break; // TODO: not underlined
-					case 25: break; // TODO: steady - not blinking
-					case 27: {
-						terminal->attr.invert = false;
-						break;
-					}
-					case 28: break; // TODO: visible - not hidden
-					default: {
-						if (((part >= 30) && (part <= 39)) || ((part >= 90) && (part <= 97))) {
-							terminal->attr.fgMode = BUF_16COL;
-
-							switch (part) {
-								case 30: terminal->attr.fg.idx = 0x0; break; // black
-								case 31: terminal->attr.fg.idx = 0x1; break; // red
-								case 32: terminal->attr.fg.idx = 0x2; break; // green
-								case 33: terminal->attr.fg.idx = 0x3; break; // yellow
-								case 34: terminal->attr.fg.idx = 0x4; break; // blue
-								case 35: terminal->attr.fg.idx = 0x5; break; // magenta
-								case 36: terminal->attr.fg.idx = 0x6; break; // cyan
-								case 37: terminal->attr.fg.idx = 0x7; break; // white
-								case 39: terminal->attr.fgMode = BUF_DEFAULT; break;
-								case 90: terminal->attr.fg.idx = 0x8; break; // grey/bright black
-								case 91: terminal->attr.fg.idx = 0x9; break; // bright red
-								case 92: terminal->attr.fg.idx = 0xA; break; // bright green
-								case 93: terminal->attr.fg.idx = 0xB; break; // bright yellow
-								case 94: terminal->attr.fg.idx = 0xC; break; // bright blue
-								case 95: terminal->attr.fg.idx = 0xD; break; // bright magenta
-								case 96: terminal->attr.fg.idx = 0xE; break; // bright cyan
-								case 97: terminal->attr.fg.idx = 0xF; break; // bright white
-								default: break;
-							}
-						}
-						else if (((part >= 40) && (part <= 49)) || ((part >= 100) && (part <= 107))) {
-							terminal->attr.bgMode = BUF_16COL;
-
-							switch (part) {
-								case 40:  terminal->attr.bg.idx = 0x0; break; // black
-								case 41:  terminal->attr.bg.idx = 0x1; break; // red
-								case 42:  terminal->attr.bg.idx = 0x2; break; // green
-								case 43:  terminal->attr.bg.idx = 0x3; break; // yellow
-								case 44:  terminal->attr.bg.idx = 0x4; break; // blue
-								case 45:  terminal->attr.bg.idx = 0x5; break; // magenta
-								case 46:  terminal->attr.bg.idx = 0x6; break; // cyan
-								case 47:  terminal->attr.bg.idx = 0x7; break; // white
-								case 49:  terminal->attr.bgMode = BUF_DEFAULT; break;
-								case 100: terminal->attr.bg.idx = 0x8; break; // grey/bright black
-								case 101: terminal->attr.bg.idx = 0x9; break; // bright red
-								case 102: terminal->attr.bg.idx = 0xA; break; // bright green
-								case 103: terminal->attr.bg.idx = 0xB; break; // bright yellow
-								case 104: terminal->attr.bg.idx = 0xC; break; // bright blue
-								case 105: terminal->attr.bg.idx = 0xD; break; // bright magenta
-								case 106: terminal->attr.bg.idx = 0xE; break; // bright cyan
-								case 107: terminal->attr.bg.idx = 0xF; break; // bright white
-								default: break;
-							}
-						}
-					}
-				}
+				ColourSeq(part, terminal);
 			}
 
 			break;
@@ -425,8 +452,15 @@ 				case 1000: this->mouseMode = MOUSE_BOTH; break;
 				case 1001: break; // TODO: use hilite motion mouse tracking
 				case 1002: break; // TODO: use cell motion mouse tracking
 				case 1003: break; // TODO: use all motion mouse tracking
-				case 1048: break; // TODO: save cursor
-				case 1049: break; // TODO: save cursor & use alternate screen buffer
+				case 1048: {
+					this->savedCursor = terminal->cursor;
+					break;
+				}
+				case 1049: {
+					this->savedCursor = terminal->cursor;
+					break;
+					// TODO: switch to alternate screen buffer
+				}
 				case 2004: break; // TODO: bracketed paste mode
 				default: printf("Unsupported: %dh\n", param);
 			}
@@ -447,15 +481,22 @@ 				case 1000: this->mouseMode = MOUSE_OFF; break;
 				case 1001: break; // TODO: do not use hilite motion mouse tracking
 				case 1002: break; // TODO: do not use cell motion mouse tracking
 				case 1003: break; // TODO: do not use all motion mouse tracking
-				case 1048: break; // TODO: restore cursor
-				case 1049: break; // TODO: restore cursor & use normal screen buffer
+				case 1048: {
+					terminal->cursor = this->savedCursor;
+					break;
+				}
+				case 1049: {
+					terminal->cursor = this->savedCursor;
+					break;
+					// TODO: switch to normal screen buffer
+				}
 				case 2004: break; // TODO: bracketed paste mode
 				default: printf("Unsupported: %dl\n", param);
 			}
 			break;
 		}
 		default: {
-			printf("Unsupported: %s %c\n", this->reading, (char) ch);
+			printf("Unsupported: %s %s %c\n", this->reading, q? "?" : "", (char) ch);
 			break; // Unsupported
 		}
 	}
@@ -514,6 +555,16 @@ 				case '\x1b': {
 					this->mode = MODE_ESCAPE;
 					break;
 				}
+				case 0x08: {
+					-- terminal->cursor.x;
+					if (terminal->cursor.x < 0) {
+						terminal->cursor.x = 0;
+					}
+					break;
+				}
+				case 0x07: { // bell
+					break;
+				}
 				default: {
 					BufCell cell;
 					cell.ch   = (UChar) ch;
@@ -527,11 +578,32 @@ 			break;
 		}
 		case MODE_ESCAPE: {
 			switch (ch) {
-				case '[': this->mode = MODE_CSI; break;
-				case ']': this->mode = MODE_OSC; break;
-				case '(': this->mode = MODE_CHSET; break;
+				case '[': this->mode = MODE_CSI;     break;
+				case ']': this->mode = MODE_OSC;     break;
+				case '(': this->mode = MODE_CHSET;   break;
+				case '%': this->mode = MODE_CHSET_P; break;
+				case '#': this->mode = MODE_HASHTAG; break;
+				case 'E': { // next line
+					++ terminal->cursor.y;
+					terminal->cursor.x = 0;
+					ShouldScroll(terminal);
+					break;
+				}
+				case 'D': { // index: move down one line
+					++ terminal->cursor.y;
+					ShouldScroll(terminal);
+					break;
+				}
+				case 'M': { // reverse index: move up one line
+					-- terminal->cursor.y;
+					if (terminal->cursor.y < TermTop(terminal)) {
+						terminal->cursor.y = TermTop(terminal);
+					}
+
+					break;
+				}
 				default: {
-					printf("Unimplemented: ESC '%c'\n", ch);
+					printf("Unimplemented: ESC (%d) '%c'\n", ch, ch);
 					this->mode = MODE_READY; // invalid
 				}
 			}
@@ -576,6 +648,14 @@ 			}
 			break;
 		}
 		case MODE_CHSET: {
+			this->mode = MODE_READY;
+			break;
+		}
+		case MODE_CHSET_P: {
+			this->mode = MODE_READY;
+			break;
+		}
+		case MODE_HASHTAG: {
 			this->mode = MODE_READY;
 			break;
 		}