aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2020-11-07 23:35:31 +0100
committerJohn Ankarström <john@ankarstrom.se>2020-11-07 23:35:31 +0100
commit9c52b38325662d66bc87b639d3043141c9305372 (patch)
tree601bdec663b34e96e42ccb00d608adbbc397678e
downloadtea-9c52b38325662d66bc87b639d3043141c9305372.tar.gz
first commit
-rw-r--r--Makefile7
-rw-r--r--README1
-rwxr-xr-xteabin0 -> 21072 bytes
-rw-r--r--tea.c224
4 files changed, 232 insertions, 0 deletions
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
--- /dev/null
+++ b/tea
Binary files 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 <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/ttydefaults.h>
+#include <termios.h>
+#include <unistd.h>
+
+#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;
+}