summaryrefslogtreecommitdiffstats
path: root/src/libvterm
diff options
context:
space:
mode:
Diffstat (limited to 'src/libvterm')
-rw-r--r--src/libvterm/.bzrignore13
-rw-r--r--src/libvterm/.gitignore18
-rw-r--r--src/libvterm/LICENSE23
-rw-r--r--src/libvterm/Makefile145
-rw-r--r--src/libvterm/README13
-rw-r--r--src/libvterm/bin/unterm.c287
-rw-r--r--src/libvterm/bin/vterm-ctrl.c362
-rw-r--r--src/libvterm/bin/vterm-dump.c231
-rw-r--r--src/libvterm/doc/URLs11
-rw-r--r--src/libvterm/doc/seqs.txt226
-rw-r--r--src/libvterm/include/vterm.h370
-rw-r--r--src/libvterm/include/vterm_keycodes.h58
-rw-r--r--src/libvterm/src/encoding.c232
-rw-r--r--src/libvterm/src/encoding/DECdrawing.tbl31
-rw-r--r--src/libvterm/src/encoding/uk.tbl1
-rw-r--r--src/libvterm/src/keyboard.c228
-rw-r--r--src/libvterm/src/mouse.c96
-rw-r--r--src/libvterm/src/parser.c346
-rw-r--r--src/libvterm/src/pen.c504
-rw-r--r--src/libvterm/src/rect.h56
-rw-r--r--src/libvterm/src/screen.c937
-rw-r--r--src/libvterm/src/state.c1851
-rw-r--r--src/libvterm/src/unicode.c331
-rw-r--r--src/libvterm/src/utf8.h47
-rw-r--r--src/libvterm/src/vterm.c385
-rw-r--r--src/libvterm/src/vterm_internal.h237
-rw-r--r--src/libvterm/t/02parser.test200
-rw-r--r--src/libvterm/t/03encoding_utf8.test122
-rw-r--r--src/libvterm/t/10state_putglyph.test55
-rw-r--r--src/libvterm/t/11state_movecursor.test224
-rw-r--r--src/libvterm/t/12state_scroll.test150
-rw-r--r--src/libvterm/t/13state_edit.test300
-rw-r--r--src/libvterm/t/14state_encoding.test105
-rw-r--r--src/libvterm/t/15state_mode.test86
-rw-r--r--src/libvterm/t/16state_resize.test48
-rw-r--r--src/libvterm/t/17state_mouse.test172
-rw-r--r--src/libvterm/t/18state_termprops.test36
-rw-r--r--src/libvterm/t/20state_wrapping.test69
-rw-r--r--src/libvterm/t/21state_tabstops.test60
-rw-r--r--src/libvterm/t/22state_save.test64
-rw-r--r--src/libvterm/t/25state_input.test132
-rw-r--r--src/libvterm/t/26state_query.test62
-rw-r--r--src/libvterm/t/27state_reset.test32
-rw-r--r--src/libvterm/t/28state_dbl_wh.test61
-rw-r--r--src/libvterm/t/29state_fallback.test19
-rw-r--r--src/libvterm/t/30pen.test106
-rw-r--r--src/libvterm/t/40screen_ascii.test69
-rw-r--r--src/libvterm/t/41screen_unicode.test47
-rw-r--r--src/libvterm/t/42screen_damage.test155
-rw-r--r--src/libvterm/t/43screen_resize.test90
-rw-r--r--src/libvterm/t/44screen_pen.test55
-rw-r--r--src/libvterm/t/45screen_protect.test16
-rw-r--r--src/libvterm/t/46screen_extent.test11
-rw-r--r--src/libvterm/t/47screen_dbl_wh.test32
-rw-r--r--src/libvterm/t/48screen_termprops.test17
-rw-r--r--src/libvterm/t/90vttest_01-movement-1.test87
-rw-r--r--src/libvterm/t/90vttest_01-movement-2.test40
-rw-r--r--src/libvterm/t/90vttest_01-movement-3.test21
-rw-r--r--src/libvterm/t/90vttest_01-movement-4.test36
-rw-r--r--src/libvterm/t/90vttest_02-screen-1.test18
-rw-r--r--src/libvterm/t/90vttest_02-screen-2.test29
-rw-r--r--src/libvterm/t/90vttest_02-screen-3.test16
-rw-r--r--src/libvterm/t/90vttest_02-screen-4.test17
-rw-r--r--src/libvterm/t/92lp1640917.test13
-rw-r--r--src/libvterm/t/harness.c929
-rw-r--r--src/libvterm/t/run-test.pl196
-rw-r--r--src/libvterm/tbl2inc_c.pl51
-rw-r--r--src/libvterm/vterm.pc.in9
68 files changed, 11096 insertions, 0 deletions
diff --git a/src/libvterm/.bzrignore b/src/libvterm/.bzrignore
new file mode 100644
index 0000000000..e58c036693
--- /dev/null
+++ b/src/libvterm/.bzrignore
@@ -0,0 +1,13 @@
+.libs
+*.lo
+*.la
+
+bin/*
+!bin/*.c
+
+pangoterm
+t/test
+t/suites.h
+t/externs.h
+t/harness
+src/encoding/*.inc
diff --git a/src/libvterm/.gitignore b/src/libvterm/.gitignore
new file mode 100644
index 0000000000..725c6f16f4
--- /dev/null
+++ b/src/libvterm/.gitignore
@@ -0,0 +1,18 @@
+*~
+*.swp
+
+tags
+src/*.o
+src/*.lo
+src/encoding/*.inc
+
+libvterm.la
+bin/unterm
+bin/vterm-ctrl
+bin/vterm-dump
+
+t/harness
+t/harness.lo
+t/harness.o
+
+.libs/
diff --git a/src/libvterm/LICENSE b/src/libvterm/LICENSE
new file mode 100644
index 0000000000..0d051634b2
--- /dev/null
+++ b/src/libvterm/LICENSE
@@ -0,0 +1,23 @@
+
+
+The MIT License
+
+Copyright (c) 2008 Paul Evans <leonerd@leonerd.org.uk>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/src/libvterm/Makefile b/src/libvterm/Makefile
new file mode 100644
index 0000000000..05f68dd605
--- /dev/null
+++ b/src/libvterm/Makefile
@@ -0,0 +1,145 @@
+ifeq ($(shell uname),Darwin)
+ LIBTOOL ?= glibtool
+else
+ LIBTOOL ?= libtool
+endif
+
+ifneq ($(VERBOSE),1)
+ LIBTOOL +=--quiet
+endif
+
+# override CFLAGS +=-Wall -Iinclude -std=c99 -DINLINE="static inline" -DUSE_INLINE
+override CFLAGS +=-Wall -Iinclude -std=c90 -Wpedantic -DINLINE=""
+
+ifeq ($(shell uname),SunOS)
+ override CFLAGS +=-D__EXTENSIONS__ -D_XPG6 -D__XOPEN_OR_POSIX
+endif
+
+ifeq ($(DEBUG),1)
+ override CFLAGS +=-ggdb -DDEBUG
+endif
+
+ifeq ($(PROFILE),1)
+ override CFLAGS +=-pg
+ override LDFLAGS+=-pg
+endif
+
+CFILES=$(sort $(wildcard src/*.c))
+HFILES=$(sort $(wildcard include/*.h))
+OBJECTS=$(CFILES:.c=.lo)
+LIBRARY=libvterm.la
+
+BINFILES_SRC=$(sort $(wildcard bin/*.c))
+BINFILES=$(BINFILES_SRC:.c=)
+
+TBLFILES=$(sort $(wildcard src/encoding/*.tbl))
+INCFILES=$(TBLFILES:.tbl=.inc)
+
+HFILES_INT=$(sort $(wildcard src/*.h)) $(HFILES)
+
+VERSION_MAJOR=0
+VERSION_MINOR=0
+
+VERSION_CURRENT=0
+VERSION_REVISION=0
+VERSION_AGE=0
+
+VERSION=0
+
+PREFIX=/usr/local
+BINDIR=$(PREFIX)/bin
+LIBDIR=$(PREFIX)/lib
+INCDIR=$(PREFIX)/include
+MANDIR=$(PREFIX)/share/man
+MAN3DIR=$(MANDIR)/man3
+
+all: $(LIBRARY) $(BINFILES)
+
+$(LIBRARY): $(OBJECTS)
+ @echo LINK $@
+ @$(LIBTOOL) --mode=link --tag=CC $(CC) -rpath $(LIBDIR) -version-info $(VERSION_CURRENT):$(VERSION_REVISION):$(VERSION_AGE) -o $@ $^ $(LDFLAGS)
+
+src/%.lo: src/%.c $(HFILES_INT)
+ @echo CC $<
+ @$(LIBTOOL) --mode=compile --tag=CC $(CC) $(CFLAGS) -o $@ -c $<
+
+src/encoding/%.inc: src/encoding/%.tbl
+ @echo TBL $<
+ @perl -CSD tbl2inc_c.pl $< >$@
+
+src/encoding.lo: $(INCFILES)
+
+bin/%: bin/%.c $(LIBRARY)
+ @echo CC $<
+ @$(LIBTOOL) --mode=link --tag=CC $(CC) $(CFLAGS) -o $@ $< -lvterm $(LDFLAGS)
+
+t/harness.lo: t/harness.c $(HFILES)
+ @echo CC $<
+ @$(LIBTOOL) --mode=compile --tag=CC $(CC) $(CFLAGS) -o $@ -c $<
+
+t/harness: t/harness.lo $(LIBRARY)
+ @echo LINK $@
+ @$(LIBTOOL) --mode=link --tag=CC $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+
+.PHONY: test
+test: $(LIBRARY) t/harness
+ for T in `ls t/[0-9]*.test`; do echo "** $$T **"; perl t/run-test.pl $$T $(if $(VALGRIND),--valgrind) || exit 1; done
+
+.PHONY: clean
+clean:
+ $(LIBTOOL) --mode=clean rm -f $(OBJECTS) $(INCFILES)
+ $(LIBTOOL) --mode=clean rm -f t/harness.lo t/harness
+ $(LIBTOOL) --mode=clean rm -f $(LIBRARY) $(BINFILES)
+
+.PHONY: install
+install: install-inc install-lib install-bin
+
+install-inc:
+ install -d $(DESTDIR)$(INCDIR)
+ install -m644 $(HFILES) $(DESTDIR)$(INCDIR)
+ install -d $(DESTDIR)$(LIBDIR)/pkgconfig
+ sed -e "s,@PREFIX@,$(PREFIX)," -e "s,@LIBDIR@,$(LIBDIR)," -e "s,@VERSION@,$(VERSION)," <vterm.pc.in >$(DESTDIR)$(LIBDIR)/pkgconfig/vterm.pc
+
+install-lib: $(LIBRARY)
+ install -d $(DESTDIR)$(LIBDIR)
+ $(LIBTOOL) --mode=install install $(LIBRARY) $(DESTDIR)$(LIBDIR)/$(LIBRARY)
+ $(LIBTOOL) --mode=finish $(DESTDIR)$(LIBDIR)
+
+install-bin: $(BINFILES)
+ install -d $(DESTDIR)$(BINDIR)
+ $(LIBTOOL) --mode=install install $(BINFILES) $(DESTDIR)$(BINDIR)/
+
+# DIST CUT
+
+VERSION=$(VERSION_MAJOR).$(VERSION_MINOR)
+
+DISTDIR=libvterm-$(VERSION)
+
+distdir: $(INCFILES)
+ mkdir __distdir
+ cp LICENSE __distdir
+ mkdir __distdir/src
+ cp src/*.c src/*.h __distdir/src
+ mkdir __distdir/src/encoding
+ cp src/encoding/*.inc __distdir/src/encoding
+ mkdir __distdir/include
+ cp include/*.h __distdir/include
+ mkdir __distdir/bin
+ cp bin/*.c __distdir/bin
+ mkdir __distdir/t
+ cp t/*.test t/harness.c t/run-test.pl __distdir/t
+ sed "s,@VERSION@,$(VERSION)," <vterm.pc.in >__distdir/vterm.pc.in
+ sed "/^# DIST CUT/Q" <Makefile >__distdir/Makefile
+ mv __distdir $(DISTDIR)
+
+TARBALL=$(DISTDIR).tar.gz
+
+dist: distdir
+ tar -czf $(TARBALL) $(DISTDIR)
+ rm -rf $(DISTDIR)
+
+dist+bzr:
+ $(MAKE) dist VERSION=$(VERSION)+bzr`bzr revno`
+
+distdir+bzr:
+ $(MAKE) distdir VERSION=$(VERSION)+bzr`bzr revno`
diff --git a/src/libvterm/README b/src/libvterm/README
new file mode 100644
index 0000000000..ef74b011aa
--- /dev/null
+++ b/src/libvterm/README
@@ -0,0 +1,13 @@
+This is a MODIFIED version of libvterm.
+
+The original can be found:
+On the original site (tar archive and Bazaar repository):
+ http://www.leonerd.org.uk/code/libvterm/
+Cloned on Github:
+ https://github.com/neovim/libvterm
+
+Modifications:
+- Add a .gitignore file.
+- Convert from C99 to C90.
+- Other changes to support embedding in Vim.
+-
diff --git a/src/libvterm/bin/unterm.c b/src/libvterm/bin/unterm.c
new file mode 100644
index 0000000000..acaf2d2d44
--- /dev/null
+++ b/src/libvterm/bin/unterm.c
@@ -0,0 +1,287 @@
+#include <stdio.h>
+#include <string.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include "vterm.h"
+
+#define DEFINE_INLINES
+#include "../src/utf8.h" /* fill_utf8 */
+
+#define streq(a,b) (!strcmp(a,b))
+
+static VTerm *vt;
+static VTermScreen *vts;
+
+static int cols;
+static int rows;
+
+static enum {
+ FORMAT_PLAIN,
+ FORMAT_SGR
+} format = FORMAT_PLAIN;
+
+static int col2index(VTermColor target)
+{
+ int index;
+
+ for(index = 0; index < 256; index++) {
+ VTermColor col;
+ vterm_state_get_palette_color(NULL, index, &col);
+ if(col.red == target.red && col.green == target.green && col.blue == target.blue)
+ return index;
+ }
+ return -1;
+}
+
+static void dump_cell(const VTermScreenCell *cell, const VTermScreenCell *prevcell)
+{
+ switch(format) {
+ case FORMAT_PLAIN:
+ break;
+ case FORMAT_SGR:
+ {
+ /* If all 7 attributes change, that means 7 SGRs max */
+ /* Each colour could consume up to 3 */
+ int sgr[7 + 2*3]; int sgri = 0;
+
+ if(!prevcell->attrs.bold && cell->attrs.bold)
+ sgr[sgri++] = 1;
+ if(prevcell->attrs.bold && !cell->attrs.bold)
+ sgr[sgri++] = 22;
+
+ if(!prevcell->attrs.underline && cell->attrs.underline)
+ sgr[sgri++] = 4;
+ if(prevcell->attrs.underline && !cell->attrs.underline)
+ sgr[sgri++] = 24;
+
+ if(!prevcell->attrs.italic && cell->attrs.italic)
+ sgr[sgri++] = 3;
+ if(prevcell->attrs.italic && !cell->attrs.italic)
+ sgr[sgri++] = 23;
+
+ if(!prevcell->attrs.blink && cell->attrs.blink)
+ sgr[sgri++] = 5;
+ if(prevcell->attrs.blink && !cell->attrs.blink)
+ sgr[sgri++] = 25;
+
+ if(!prevcell->attrs.reverse && cell->attrs.reverse)
+ sgr[sgri++] = 7;
+ if(prevcell->attrs.reverse && !cell->attrs.reverse)
+ sgr[sgri++] = 27;
+
+ if(!prevcell->attrs.strike && cell->attrs.strike)
+ sgr[sgri++] = 9;
+ if(prevcell->attrs.strike && !cell->attrs.strike)
+ sgr[sgri++] = 29;
+
+ if(!prevcell->attrs.font && cell->attrs.font)
+ sgr[sgri++] = 10 + cell->attrs.font;
+ if(prevcell->attrs.font && !cell->attrs.font)
+ sgr[sgri++] = 10;
+
+ if(prevcell->fg.red != cell->fg.red ||
+ prevcell->fg.green != cell->fg.green ||
+ prevcell->fg.blue != cell->fg.blue) {
+ int index = col2index(cell->fg);
+ if(index == -1)
+ sgr[sgri++] = 39;
+ else if(index < 8)
+ sgr[sgri++] = 30 + index;
+ else if(index < 16)
+ sgr[sgri++] = 90 + (index - 8);
+ else {
+ sgr[sgri++] = 38;
+ sgr[sgri++] = 5 | (1<<31);
+ sgr[sgri++] = index | (1<<31);
+ }
+ }
+
+ if(prevcell->bg.red != cell->bg.red ||
+ prevcell->bg.green != cell->bg.green ||
+ prevcell->bg.blue != cell->bg.blue) {
+ int index = col2index(cell->bg);
+ if(index == -1)
+ sgr[sgri++] = 49;
+ else if(index < 8)
+ sgr[sgri++] = 40 + index;
+ else if(index < 16)
+ sgr[sgri++] = 100 + (index - 8);
+ else {
+ sgr[sgri++] = 48;
+ sgr[sgri++] = 5 | (1<<31);
+ sgr[sgri++] = index | (1<<31);
+ }
+ }
+
+ if(!sgri)
+ break;
+
+ printf("\x1b[");
+ {
+ int i;
+ for(i = 0; i < sgri; i++)
+ printf(!i ? "%d" :
+ sgr[i] & (1<<31) ? ":%d" :
+ ";%d",
+ sgr[i] & ~(1<<31));
+ }
+ printf("m");
+ }
+ break;
+ }
+
+ {
+ int i;
+ for(i = 0; i < VTERM_MAX_CHARS_PER_CELL && cell->chars[i]; i++) {
+ char bytes[6];
+ bytes[fill_utf8(cell->chars[i], bytes)] = 0;
+ printf("%s", bytes);
+ }
+ }
+}
+
+static void dump_eol(const VTermScreenCell *prevcell)
+{
+ switch(format) {
+ case FORMAT_PLAIN:
+ break;
+ case FORMAT_SGR:
+ if(prevcell->attrs.bold || prevcell->attrs.underline || prevcell->attrs.italic ||
+ prevcell->attrs.blink || prevcell->attrs.reverse || prevcell->attrs.strike ||
+ prevcell->attrs.font)
+ printf("\x1b[m");
+ break;
+ }
+
+ printf("\n");
+}
+
+void dump_row(int row)
+{
+ VTermPos pos;
+ VTermScreenCell prevcell;
+ pos.row = row;
+ pos.col = 0;
+ memset(&prevcell, 0, sizeof(prevcell));
+ vterm_state_get_default_colors(vterm_obtain_state(vt), &prevcell.fg, &prevcell.bg);
+
+ while(pos.col < cols) {
+ VTermScreenCell cell;
+ vterm_screen_get_cell(vts, pos, &cell);
+
+ dump_cell(&cell, &prevcell);
+
+ pos.col += cell.width;
+ prevcell = cell;
+ }
+
+ dump_eol(&prevcell);
+}
+
+static int screen_sb_pushline(int cols, const VTermScreenCell *cells, void *user)
+{
+ VTermScreenCell prevcell;
+ int col;
+
+ memset(&prevcell, 0, sizeof(prevcell));
+ vterm_state_get_default_colors(vterm_obtain_state(vt), &prevcell.fg, &prevcell.bg);
+
+ for(col = 0; col < cols; col++) {
+ dump_cell(cells + col, &prevcell);
+ prevcell = cells[col];
+ }
+
+ dump_eol(&prevcell);
+
+ return 1;
+}
+
+static int screen_resize(int new_rows, int new_cols, void *user)
+{
+ rows = new_rows;
+ cols = new_cols;
+ return 1;
+}
+
+static VTermScreenCallbacks cb_screen = {
+ NULL, /* damage */
+ NULL, /* moverect */
+ NULL, /* movecursor */
+ NULL, /* settermprop */
+ NULL, /* bell */
+ &screen_resize, /* resize */
+ &screen_sb_pushline, /* sb_pushline */
+ NULL, /* popline */
+};
+
+int main(int argc, char *argv[])
+{
+ int opt;
+ const char *file;
+ int fd;
+ int len;
+ char buffer[1024];
+ int row;
+
+ rows = 25;
+ cols = 80;
+
+ while((opt = getopt(argc, argv, "f:l:c:")) != -1) {
+ switch(opt) {
+ case 'f':
+ if(streq(optarg, "plain"))
+ format = FORMAT_PLAIN;
+ else if(streq(optarg, "sgr"))
+ format = FORMAT_SGR;
+ else {
+ fprintf(stderr, "Unrecognised format '%s'\n", optarg);
+ exit(1);
+ }
+ break;
+
+ case 'l':
+ rows = atoi(optarg);
+ if(!rows)
+ rows = 25;
+ break;
+
+ case 'c':
+ cols = atoi(optarg);
+ if(!cols)
+ cols = 80;
+ break;
+ }
+ }
+
+ file = argv[optind++];
+ fd = open(file, O_RDONLY);
+ if(fd == -1) {
+ fprintf(stderr, "Cannot open %s - %s\n", file, strerror(errno));
+ exit(1);
+ }
+
+ vt = vterm_new(rows, cols);
+ vterm_set_utf8(vt, true);
+
+ vts = vterm_obtain_screen(vt);
+ vterm_screen_set_callbacks(vts, &cb_screen, NULL);
+
+ vterm_screen_reset(vts, 1);
+
+ while((len = read(fd, buffer, sizeof(buffer))) > 0) {
+ vterm_input_write(vt, buffer, len);
+ }
+
+ for(row = 0; row < rows; row++) {
+ dump_row(row);
+ }
+
+ close(fd);
+
+ vterm_free(vt);
+ return 0;
+}
diff --git a/src/libvterm/bin/vterm-ctrl.c b/src/libvterm/bin/vterm-ctrl.c
new file mode 100644
index 0000000000..14e35cda52
--- /dev/null
+++ b/src/libvterm/bin/vterm-ctrl.c
@@ -0,0 +1,362 @@
+#define _XOPEN_SOURCE 500 /* strdup */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define streq(a,b) (strcmp(a,b)==0)
+
+#include <termios.h>
+
+static char *getvalue(int *argip, int argc, char *argv[])
+{
+ if(*argip >= argc) {
+ fprintf(stderr, "Expected an option value\n");
+ exit(1);
+ }
+
+ return argv[(*argip)++];
+}
+
+static int getchoice(int *argip, int argc, char *argv[], const char *options[])
+{
+ const char *arg = getvalue(argip, argc, argv);
+
+ int value = -1;
+ while(options[++value])
+ if(streq(arg, options[value]))
+ return value;
+
+ fprintf(stderr, "Unrecognised option value %s\n", arg);
+ exit(1);
+}
+
+typedef enum {
+ OFF,
+ ON,
+ QUERY
+} BoolQuery;
+
+static BoolQuery getboolq(int *argip, int argc, char *argv[])
+{
+ const char *choices[] = {"off", "on", "query", NULL};
+ return getchoice(argip, argc, argv, choices);
+}
+
+static char *helptext[] = {
+ "reset",
+ "s8c1t [off|on]",
+ "keypad [app|num]",
+ "screen [off|on|query]",
+ "cursor [off|on|query]",
+ "curblink [off|on|query]",
+ "curshape [block|under|bar|query]",
+ "mouse [off|click|clickdrag|motion]",
+ "altscreen [off|on|query]",
+ "bracketpaste [off|on|query]",
+ "icontitle [STR]",
+ "icon [STR]",
+ "title [STR]",
+ NULL
+};
+
+static bool seticanon(bool icanon, bool echo)
+{
+ struct termios termios;
+
+ tcgetattr(0, &termios);
+
+ bool ret = (termios.c_lflag & ICANON);
+
+ if(icanon) termios.c_lflag |= ICANON;
+ else termios.c_lflag &= ~ICANON;
+
+ if(echo) termios.c_lflag |= ECHO;
+ else termios.c_lflag &= ~ECHO;
+
+ tcsetattr(0, TCSANOW, &termios);
+
+ return ret;
+}
+
+static void await_c1(int c1)
+{
+ int c;
+
+ /* await CSI - 8bit or 2byte 7bit form */
+ bool in_esc = false;
+ while((c = getchar())) {
+ if(c == c1)
+ break;
+ if(in_esc && c == (char)(c1 - 0x40))
+ break;
+ if(!in_esc && c == 0x1b)
+ in_esc = true;
+ else
+ in_esc = false;
+ }
+}
+
+static char *read_csi()
+{
+ unsigned char csi[32];
+ int i = 0;
+
+ await_c1(0x9B); /* CSI */
+
+ /* TODO: This really should be a more robust CSI parser
+ */
+ for(; i < sizeof(csi)-1; i++) {
+ int c = csi[i] = g