diff options
Diffstat (limited to 'src/libvterm')
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 |