diff options
author | John Ankarström <john@ankarstrom.se> | 2020-11-06 18:42:26 +0100 |
---|---|---|
committer | John Ankarström <john@ankarstrom.se> | 2020-11-06 18:42:26 +0100 |
commit | e169dbe7c20ed4b4b1acf80c8e03e9aa58a60836 (patch) | |
tree | 3f45098e6691dd3530ce278641970f46f90c002e | |
download | lst-e169dbe7c20ed4b4b1acf80c8e03e9aa58a60836.tar.gz |
add cpr function, basic setup
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | l.c | 137 |
2 files changed, 141 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..62f142f --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +all: l + +%: %c + gcc -o $@ $< @@ -0,0 +1,137 @@ +#include <ctype.h> +#include <err.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/ttydefaults.h> +#include <termios.h> +#include <unistd.h> + +#define ESC "\033" +#define CSI ESC "[" + +int ttyfd; + +/* enable/disable "raw" mode */ +void raw(bool enable) { + int r; + static struct termios orig; + struct termios raw; + + if (enable) { + r = tcgetattr(0, &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(0, TCSAFLUSH, &raw); + if (r == -1) err(1, "tcsetattr"); + + } else + tcsetattr(0, TCSAFLUSH, &orig); +} + +/* cursor position report */ +int cpr(int *x, int *y) { + char c, xbuf[4], ybuf[4]; + int i; + + write (1, CSI "6n", 2+2); + + /* get CSI */ + read(1, &c, 1); + if (c != '\033') return -1; + read(1, &c, 1); + if (c != '[') return -1; + + /* get x */ + i = 0; + while (read(1, &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(1, &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; +} + +void up() {} +void down() {} +void right() {} +void left() {} + +int main() { + char c, *p; + char *ex = "file1 file2 file3\r\nfile4 file5 file6\r\nfile7"; + int i, r, x, x2, y, y2; + struct winsize w; + + ttyfd = open("/dev/tty", O_RDWR); + if (ttyfd == -1) err(1, "open"); + + raw(true); + + /* save original cursor position */ + r = cpr(&x, &y); + if (r == -1) goto quit; + + /* print output */ + dprintf(ttyfd, "%s", ex); + + /* get height of output */ + p = ex - 1; + i = 0; + while (*(++p) != '\0') + if (*p == '\n') i++; + + /* get height of terminal */ + r = ioctl(ttyfd, TIOCGWINSZ, &w); + if (r == -1) err(1, "ioctl"); + + /* correct cursor position if original cursor was near bottom */ + r = y + i - w.ws_row; + if (r > 0) + y = y - r; + + /* restore original cursor position */ + dprintf(ttyfd, "%s%d;%dH", CSI, y, x); /* restore cursor position (CUP) */ + + while (read(0, &c, 1) != 0) { + switch (c) { + case 'q': + goto quit; + break; + case '\033': + read(0, &c, 1); + if (c != '[') break; + read(0, &c, 1); + if (c == 'A') up(); + if (c == 'B') down(); + if (c == 'C') right(); + if (c == 'D') left(); + break; + } + } + +quit: + raw(false); +} |