From 9c52b38325662d66bc87b639d3043141c9305372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Sat, 7 Nov 2020 23:35:31 +0100 Subject: first commit --- Makefile | 7 ++ README | 1 + tea | Bin 0 -> 21072 bytes tea.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 232 insertions(+) create mode 100644 Makefile create mode 100644 README create mode 100755 tea create mode 100644 tea.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..59acc4f --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +all: tea + +%: %c + gcc -o $@ $< + +install: + install tea /usr/bin/tea diff --git a/README b/README new file mode 100644 index 0000000..b0beeee --- /dev/null +++ b/README @@ -0,0 +1 @@ +Troff Editor for ANSI terminals diff --git a/tea b/tea new file mode 100755 index 0000000..4e7612c Binary files /dev/null and b/tea differ diff --git a/tea.c b/tea.c new file mode 100644 index 0000000..d580493 --- /dev/null +++ b/tea.c @@ -0,0 +1,224 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ESC "\033" +#define CSI ESC "[" + +#define prn(...) dprintf(ttyfd, __VA_ARGS__) +#define rerr(...) do { raw(false); err(__VA_ARGS__); } while (0) + +char **lines; +int lines_c; +int lines_s; + +char *src; +int src_l; +int src_s; + +int x, y; /* current cursor position */ +int w, h; /* terminal width, height */ +int margin = 10; + +int current = -1; /* currently selected item */ +int xorig, yorig; /* original cursor position in cols, rows */ +int ttyfd; + +/* enable/disable "raw" mode */ +void raw(bool enable) { + int r; + static struct termios orig; + struct termios raw; + + if (enable) { + r = tcgetattr(ttyfd, &orig); + if (r == -1) err(1, "tcgetattr"); + + raw = orig; + raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + raw.c_oflag &= ~OPOST; + raw.c_cflag |= CS8; + raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + + r = tcsetattr(ttyfd, TCSAFLUSH, &raw); + if (r == -1) err(1, "tcsetattr"); + + } else + tcsetattr(ttyfd, TCSAFLUSH, &orig); +} + +/* cursor position report */ +int cpr(int *x, int *y) { + char c, xbuf[4], ybuf[4]; + int i; + + prn(CSI "6n"); + + /* get CSI */ + read(ttyfd, &c, 1); + if (c != '\033') return -1; + read(ttyfd, &c, 1); + if (c != '[') return -1; + + /* get x */ + i = 0; + while (read(ttyfd, &c, 1) && c != ';') { + if (i > 3 || !isdigit(c)) return -1; + ybuf[i++] = c; + } + if (i == 0) return -1; + ybuf[i] = '\0'; + + /* get y */ + i = 0; + while (read(ttyfd, &c, 1) && c != 'R') { + if (i > 3 || !isdigit(c)) return -1; + xbuf[i++] = c; + } + if (i == 0) return -1; + xbuf[i] = '\0'; + + *x = atoi(xbuf); + *y = atoi(ybuf); + + return 0; +} + +int up() { } +int down() { } +int right() {} +int left() {} + +void addc(char c) { + if (c != '\n' && x + 1 > w) { + prn("\r"); + addc('\n'); + x = margin + 1; + prn(CSI "%dC", margin - 1); + if (y == h) yorig--; + else y++; + } else + x++; + if (src_l + 2 > src_s) { + fprintf(stderr, "too big!\n"); + exit(1); + } + src[++src_l] = c; + src[src_l + 1] = '\0'; + prn("%c", c); +} + +int main() { + char c, *line, *p, *tmp; + int i, line_s, r; + struct winsize ws; + + src_s = 1000; + src = malloc((src_s + 1) * sizeof(char)); + if (src == NULL) err(1, "malloc"); + src_l = -1; + + ttyfd = open("/dev/tty", O_RDWR); + if (ttyfd == -1) rerr(1, "open"); + + /* read file */ + +/* + line_s = 100; + line = malloc((line_s + 1) * sizeof(char)); + if (line == NULL) err(1, "malloc"); + + lines_c = 0; + lines_s = 50; + lines = malloc(lines_s * sizeof(char *)); + if (lines == NULL) err(1, "malloc"); + + i = 0; + while (read(STDIN_FILENO, &c, 1) != 0) { + if (c == '\n') { + line[i] = '\0'; + lines[lines_c] = malloc((strlen(line) + 1) * sizeof(char)); + if (lines[lines_c] == NULL) err(1, "malloc"); + strcpy(lines[lines_c], line); + lines_c++; + i = 0; + } else { + if (i > line_s) { + line_s += 50; + tmp = realloc(line, (line_s + 1) * sizeof(char)); + if (tmp == NULL) err(1, "realloc"); + line = tmp; + } + line[i++] = c; + } + } +*/ + + raw(true); + + /* save original cursor position */ + r = cpr(&xorig, &yorig); + if (r == -1) { + fprintf(stderr, "could not retrieve cursor position"); + goto quit; + } + + /* print output */ + for (i = 0; i < lines_c; i++) + prn("%s\r\n", lines[i]); + + /* get height of terminal */ + r = ioctl(ttyfd, TIOCGWINSZ, &ws); + if (r == -1) rerr(1, "ioctl"); + w = ws.ws_col; + h = ws.ws_row; + + /* correct cursor position if original cursor was near bottom */ + r = y + lines_c - h; + if (r > 0) + y = y - r; + + /* restore original cursor position (CUP) */ + prn(CSI "%d;%dH", yorig, xorig + margin - 1); + x = xorig + margin - 1; + y = yorig; + + while (read(ttyfd, &c, 1) != 0) { + switch (c) { + case '\033': /* escape */ + read(ttyfd, &c, 1); + if (c != '[') break; + read(ttyfd, &c, 1); + if (c == 'A') up(); + if (c == 'B') down(); + if (c == 'C') right(); + if (c == 'D') left(); + break; + case 3: /* ctrl-c */ + goto quit; + break; + default: + if (iscntrl(c)) break; + addc(c); + break; + } + } +quit: + prn(CSI "%d;%dH", yorig, xorig); + prn(CSI "J"); /* delete from cursor to end of display (ED) */ + raw(false); + printf("%s", src); + return 0; +die: + raw(false); + puts("died"); + return 0; +} -- cgit v1.2.3