summary refs log tree commit diff
path: root/bin/shotty.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2019-07-12 18:41:04 -0400
committerJune McEnroe <june@causal.agency>2019-07-12 18:41:04 -0400
commitac9f4093c4b0638ee522c9dda410ca221231857d (patch)
tree4aeba0ac009ecca80e3e4b2bc36b31917509a799 /bin/shotty.c
parentDon't do carriage return on line feed (diff)
downloadsrc-ac9f4093c4b0638ee522c9dda410ca221231857d.tar.gz
src-ac9f4093c4b0638ee522c9dda410ca221231857d.zip
Support insert mode in shotty
This is how curses puts characters into the bottom-right cell of the
terminal.
Diffstat (limited to 'bin/shotty.c')
-rw-r--r--bin/shotty.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/bin/shotty.c b/bin/shotty.c
index 66651af8..d7814a91 100644
--- a/bin/shotty.c
+++ b/bin/shotty.c
@@ -51,6 +51,7 @@ static struct Style def = { .fg = 7 };
 static uint rows, cols;
 
 static uint y, x;
+static bool insert;
 static struct Style style;
 static struct Cell *cells;
 
@@ -65,6 +66,10 @@ static void clear(struct Cell *a, struct Cell *b) {
 	}
 }
 
+static void move(struct Cell *dst, struct Cell *src, uint len) {
+	memmove(dst, src, sizeof(*dst) * len);
+}
+
 static char updateNUL(wchar_t ch) {
 	switch (ch) {
 		case BS: if (x) x--; return NUL;
@@ -82,7 +87,14 @@ static char updateNUL(wchar_t ch) {
 		warnx("unhandled \\u%X", ch);
 		return NUL;
 	}
+	if (x + width > cols) {
+		warnx("cannot fit '%lc'", ch);
+		return NUL;
+	}
 
+	if (insert) {
+		move(cell(y, x + width), cell(y, x), cols - x - width);
+	}
 	cell(y, x)->style = style;
 	cell(y, x)->ch = ch;
 
@@ -177,8 +189,20 @@ static char updateCSI(wchar_t ch) {
 			clear(a, b);
 		}
 
-		break; case SM: // ignore
-		break; case RM: // ignore
+		break; case SM: {
+			if (dec) break;
+			switch (ps[0]) {
+				break; case 4: insert = true;
+				break; default: warnx("unhandled SM %u", ps[0]);
+			}
+		}
+		break; case RM: {
+			if (dec) break;
+			switch (ps[0]) {
+				break; case 4: insert = false;
+				break; default: warnx("unhandled RM %u", ps[0]);
+			}
+		}
 
 		break; case SGR: {
 			if (ps[0] == 38 && ps[1] == 5) {