isplit into multiple files - iomenu - interactive terminal-based selection menu Err bitreich.org 70 hgit clone git://bitreich.org/iomenu git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/iomenu URL:git://bitreich.org/iomenu git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/iomenu bitreich.org 70 1Log /scm/iomenu/log.gph bitreich.org 70 1Files /scm/iomenu/files.gph bitreich.org 70 1Refs /scm/iomenu/refs.gph bitreich.org 70 1Tags /scm/iomenu/tag bitreich.org 70 1README /scm/iomenu/file/README.gph bitreich.org 70 1LICENSE /scm/iomenu/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 1commit 2743c784dbce7910cbec895c42a723f06fa7b620 /scm/iomenu/commit/2743c784dbce7910cbec895c42a723f06fa7b620.gph bitreich.org 70 1parent e24cea688e69bd009ef52ea40891a0a386b881ea /scm/iomenu/commit/e24cea688e69bd009ef52ea40891a0a386b881ea.gph bitreich.org 70 hAuthor: Josuah Demangeon URL:mailto:mail@josuah.net bitreich.org 70 iDate: Sun, 29 Oct 2017 22:05:58 +0100 Err bitreich.org 70 i Err bitreich.org 70 isplit into multiple files Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i M Makefile | 4 +++- Err bitreich.org 70 i A buffer.c | 93 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A buffer.h | 3 +++ Err bitreich.org 70 i A control.c | 169 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A control.h | 4 ++++ Err bitreich.org 70 i A display.c | 119 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A display.h | 2 ++ Err bitreich.org 70 i D iomenu.c | 543 ------------------------------- Err bitreich.org 70 i A iomenu.core | 0 Err bitreich.org 70 i A main.c | 123 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A main.h | 29 +++++++++++++++++++++++++++++ Err bitreich.org 70 i M utf8.c | 13 +++++-------- Err bitreich.org 70 i M utf8.h | 12 ++++++------ Err bitreich.org 70 i Err bitreich.org 70 i13 files changed, 556 insertions(+), 558 deletions(-) Err bitreich.org 70 i--- Err bitreich.org 70 1diff --git a/Makefile b/Makefile /scm/iomenu/file/Makefile.gph bitreich.org 70 i@@ -1,6 +1,6 @@ Err bitreich.org 70 i CFLAGS = -std=c89 -Wpedantic -Wall -Wextra -g -D_POSIX_C_SOURCE=200809L Err bitreich.org 70 i Err bitreich.org 70 i-OBJ = iomenu.o utf8.o Err bitreich.org 70 i+OBJ = buffer.o control.o display.o main.o utf8.o Err bitreich.org 70 i Err bitreich.org 70 i all: iomenu Err bitreich.org 70 i Err bitreich.org 70 i@@ -15,3 +15,5 @@ install: iomenu Err bitreich.org 70 i cp *.1 $(PREFIX)/share/man/man1 Err bitreich.org 70 i mkdir -p $(PREFIX)/bin Err bitreich.org 70 i cp iomenu $(PREFIX)/bin Err bitreich.org 70 i+ Err bitreich.org 70 i+.PHONY: all clean install Err bitreich.org 70 1diff --git a/buffer.c b/buffer.c /scm/iomenu/file/buffer.c.gph bitreich.org 70 i@@ -0,0 +1,93 @@ Err bitreich.org 70 i+#include "buffer.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+static char * Err bitreich.org 70 i+read_line(FILE *fp) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ char *line; Err bitreich.org 70 i+ size_t len; Err bitreich.org 70 i+ Err bitreich.org 70 i+ line = malloc(LINE_MAX + 1); Err bitreich.org 70 i+ if (!(fgets(line, LINE_MAX, fp))) { Err bitreich.org 70 i+ free(line); Err bitreich.org 70 i+ return NULL; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ len = strlen(line); Err bitreich.org 70 i+ if (len > 0 && line[len - 1] == '\n') Err bitreich.org 70 i+ line[len - 1] = '\0'; Err bitreich.org 70 i+ Err bitreich.org 70 i+ return (line); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static int Err bitreich.org 70 i+match_line(char *line, char **tokv, int tokc) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ if (opt['#'] && line[0] == '#') Err bitreich.org 70 i+ return 2; Err bitreich.org 70 i+ while (tokc-- > 0) Err bitreich.org 70 i+ if (strstr(line, tokv[tokc]) == NULL) Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+ Err bitreich.org 70 i+ return 1; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+free_lines(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ if (linev) { Err bitreich.org 70 i+ for (; linec > 0; linec--) Err bitreich.org 70 i+ free(linev[linec - 1]); Err bitreich.org 70 i+ free(linev); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ if (matchv) Err bitreich.org 70 i+ free(matchv); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+read_stdin(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int size = 0; Err bitreich.org 70 i+ Err bitreich.org 70 i+ while (1) { Err bitreich.org 70 i+ if (linec >= size) { Err bitreich.org 70 i+ size += BUFSIZ; Err bitreich.org 70 i+ linev = realloc(linev, sizeof (char **) * size); Err bitreich.org 70 i+ matchv = realloc(matchv, sizeof (char **) * size); Err bitreich.org 70 i+ if (!linev || !matchv) Err bitreich.org 70 i+ die("realloc"); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ if ((linev[linec] = read_line(stdin)) == NULL) Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ linec++; Err bitreich.org 70 i+ matchc++; Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+filter(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int tokc = 0; Err bitreich.org 70 i+ int n = 0; Err bitreich.org 70 i+ int i; Err bitreich.org 70 i+ char **tokv = NULL; Err bitreich.org 70 i+ char *s; Err bitreich.org 70 i+ char buffer[sizeof (input)]; Err bitreich.org 70 i+ Err bitreich.org 70 i+ current = offset = next = 0; Err bitreich.org 70 i+ strcpy(buffer, input); Err bitreich.org 70 i+ for (s = strtok(buffer, " "); s; s = strtok(NULL, " "), tokc++) { Err bitreich.org 70 i+ if (tokc >= n) { Err bitreich.org 70 i+ tokv = realloc(tokv, ++n * sizeof (*tokv)); Err bitreich.org 70 i+ if (tokv == NULL) Err bitreich.org 70 i+ die("realloc"); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ tokv[tokc] = s; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ matchc = 0; Err bitreich.org 70 i+ for (i = 0; i < linec; i++) Err bitreich.org 70 i+ if (match_line(linev[i], tokv, tokc)) Err bitreich.org 70 i+ matchv[matchc++] = linev[i]; Err bitreich.org 70 i+ free(tokv); Err bitreich.org 70 i+ if (opt['#'] && matchv[current][0] == '#') Err bitreich.org 70 i+ move(+1); Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/buffer.h b/buffer.h /scm/iomenu/file/buffer.h.gph bitreich.org 70 i@@ -0,0 +1,3 @@ Err bitreich.org 70 i+void free_lines (void); Err bitreich.org 70 i+void read_stdin (void); Err bitreich.org 70 i+void filter(void); Err bitreich.org 70 1diff --git a/control.c b/control.c /scm/iomenu/file/control.c.gph bitreich.org 70 i@@ -0,0 +1,169 @@ Err bitreich.org 70 i+#include "control.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+#define CTL(char) ((char) ^ 0x40) Err bitreich.org 70 i+#define ALT(char) ((char) + 0x80) Err bitreich.org 70 i+#define CSI(char) ((char) + 0x80 + 0x80) Err bitreich.org 70 i+ Err bitreich.org 70 i+static size_t Err bitreich.org 70 i+width(char *s) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int width = 0; Err bitreich.org 70 i+ Err bitreich.org 70 i+ while (*s) { Err bitreich.org 70 i+ if (*s++ == '\t') Err bitreich.org 70 i+ width += 8 - (width % 8); Err bitreich.org 70 i+ else Err bitreich.org 70 i+ width++; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ return width; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+prev_page(int pos) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int col, cols = ws.ws_col - MARGIN - 4; Err bitreich.org 70 i+ Err bitreich.org 70 i+ pos -= pos > 0 ? 1 : 0; Err bitreich.org 70 i+ for (col = 0; pos > 0; pos--) Err bitreich.org 70 i+ if ((col += width(matchv[pos]) + 2) > cols) Err bitreich.org 70 i+ return pos + 1; Err bitreich.org 70 i+ return pos; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+next_page(int pos) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int col, cols = ws.ws_col - MARGIN - 4; Err bitreich.org 70 i+ Err bitreich.org 70 i+ for (col = 0; pos < matchc; pos++) Err bitreich.org 70 i+ if ((col += width(matchv[pos]) + 2) > cols) Err bitreich.org 70 i+ return pos; Err bitreich.org 70 i+ return pos; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+move(signed int sign) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ for (i = current + sign; 0 <= i && i < matchc; i += sign) { Err bitreich.org 70 i+ if (!opt['#'] || matchv[i][0] != '#') { Err bitreich.org 70 i+ current = i; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+move_page(signed int sign) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (opt['l'] <= 0) { Err bitreich.org 70 i+ if (sign > 0) { Err bitreich.org 70 i+ offset = current = next; Err bitreich.org 70 i+ next = next_page(next); Err bitreich.org 70 i+ } else if (sign < 0) { Err bitreich.org 70 i+ next = offset; Err bitreich.org 70 i+ offset = current = prev_page(offset); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ i = current - current % rows + rows * sign; Err bitreich.org 70 i+ if (!(0 < i && i < matchc)) Err bitreich.org 70 i+ return; Err bitreich.org 70 i+ current = i - 1; Err bitreich.org 70 i+ move(+1); Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+remove_word() Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int len; Err bitreich.org 70 i+ int i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ len = strlen(input) - 1; Err bitreich.org 70 i+ for (i = len; i >= 0 && isspace(input[i]); i--) Err bitreich.org 70 i+ input[i] = '\0'; Err bitreich.org 70 i+ len = strlen(input) - 1; Err bitreich.org 70 i+ for (i = len; i >= 0 && !isspace(input[i]); i--) Err bitreich.org 70 i+ input[i] = '\0'; Err bitreich.org 70 i+ filter(); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+add_char(char c) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int len; Err bitreich.org 70 i+ Err bitreich.org 70 i+ len = strlen(input); Err bitreich.org 70 i+ if (isprint(c)) { Err bitreich.org 70 i+ input[len] = c; Err bitreich.org 70 i+ input[len + 1] = '\0'; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ filter(); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+key(int k) Err bitreich.org 70 i+{ Err bitreich.org 70 i+top: Err bitreich.org 70 i+ switch (k) { Err bitreich.org 70 i+ case CTL('C'): Err bitreich.org 70 i+ return EXIT_FAILURE; Err bitreich.org 70 i+ case CTL('U'): Err bitreich.org 70 i+ input[0] = '\0'; Err bitreich.org 70 i+ filter(); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case CTL('W'): Err bitreich.org 70 i+ remove_word(); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 127: Err bitreich.org 70 i+ case CTL('H'): /* backspace */ Err bitreich.org 70 i+ input[strlen(input) - 1] = '\0'; Err bitreich.org 70 i+ filter(); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case CSI('A'): /* up */ Err bitreich.org 70 i+ case CTL('P'): Err bitreich.org 70 i+ move(-1); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case CSI('B'): /* down */ Err bitreich.org 70 i+ case CTL('N'): Err bitreich.org 70 i+ move(+1); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case CSI('5'): /* page up */ Err bitreich.org 70 i+ if (fgetc(stdin) != '~') Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ /* fallthrough */ Err bitreich.org 70 i+ case ALT('v'): Err bitreich.org 70 i+ move_page(-1); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case CSI('6'): /* page down */ Err bitreich.org 70 i+ if (fgetc(stdin) != '~') Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ /* fallthrough */ Err bitreich.org 70 i+ case CTL('V'): Err bitreich.org 70 i+ move_page(+1); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case CTL('I'): /* tab */ Err bitreich.org 70 i+ if (linec > 0) Err bitreich.org 70 i+ strcpy(input, matchv[current]); Err bitreich.org 70 i+ filter(); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case CTL('J'): /* enter */ Err bitreich.org 70 i+ case CTL('M'): Err bitreich.org 70 i+ print_selection(); Err bitreich.org 70 i+ return EXIT_SUCCESS; Err bitreich.org 70 i+ case ALT('['): Err bitreich.org 70 i+ k = CSI(fgetc(stdin)); Err bitreich.org 70 i+ goto top; Err bitreich.org 70 i+ case 0x1b: /* escape / alt */ Err bitreich.org 70 i+ k = ALT(fgetc(stdin)); Err bitreich.org 70 i+ goto top; Err bitreich.org 70 i+ default: Err bitreich.org 70 i+ add_char((char) k); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ return CONTINUE; Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/control.h b/control.h /scm/iomenu/file/control.h.gph bitreich.org 70 i@@ -0,0 +1,4 @@ Err bitreich.org 70 i+int prev_page (int); Err bitreich.org 70 i+int next_page (int); Err bitreich.org 70 i+void move (signed int); Err bitreich.org 70 i+int key (int); Err bitreich.org 70 1diff --git a/display.c b/display.c /scm/iomenu/file/display.c.gph bitreich.org 70 i@@ -0,0 +1,119 @@ Err bitreich.org 70 i+#include "display.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+static char * Err bitreich.org 70 i+format(char *str, int cols) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int col = 0; Err bitreich.org 70 i+ long rune = 0; Err bitreich.org 70 i+ char *fmt = formatted; Err bitreich.org 70 i+ Err bitreich.org 70 i+ while (*str && col < cols) { Err bitreich.org 70 i+ if (*str == '\t') { Err bitreich.org 70 i+ int t = 8 - col % 8; Err bitreich.org 70 i+ while (t-- && col < cols) { Err bitreich.org 70 i+ *fmt++ = ' '; Err bitreich.org 70 i+ col++; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ str++; Err bitreich.org 70 i+ } else if (utf8_to_rune(&rune, str) && rune_is_print(rune)) { Err bitreich.org 70 i+ int i = utf8_len(str); Err bitreich.org 70 i+ while (i--) Err bitreich.org 70 i+ *fmt++ = *str++; Err bitreich.org 70 i+ col++; Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ *fmt++ = '?'; Err bitreich.org 70 i+ col++; Err bitreich.org 70 i+ str++; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ *fmt = '\0'; Err bitreich.org 70 i+ Err bitreich.org 70 i+ return formatted; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+print_lines(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int printed = 0, i = current - current % rows; Err bitreich.org 70 i+ Err bitreich.org 70 i+ for (; printed < rows && i < matchc; i++, printed++) { Err bitreich.org 70 i+ fprintf(stderr, Err bitreich.org 70 i+ opt['#'] && matchv[i][0] == '#' ? Err bitreich.org 70 i+ "\n\x1b[1m\x1b[K %s\x1b[m" : Err bitreich.org 70 i+ i == current ? Err bitreich.org 70 i+ "\n\x1b[47;30m\x1b[K %s\x1b[m" : Err bitreich.org 70 i+ "\n\x1b[K %s", Err bitreich.org 70 i+ format(matchv[i], ws.ws_col - 1) Err bitreich.org 70 i+ ); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ while (printed++ < rows) Err bitreich.org 70 i+ fputs("\n\x1b[K", stderr); Err bitreich.org 70 i+ fprintf(stderr, "\x1b[%dA\r\x1b[K", rows); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+print_segments(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (current < offset) { Err bitreich.org 70 i+ next = offset; Err bitreich.org 70 i+ offset = prev_page(offset); Err bitreich.org 70 i+ } else if (current >= next) { Err bitreich.org 70 i+ offset = next; Err bitreich.org 70 i+ next = next_page(offset); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ fprintf(stderr, "\r\x1b[K\x1b[%dC", MARGIN); Err bitreich.org 70 i+ fputs(offset > 0 ? "< " : " ", stderr); Err bitreich.org 70 i+ for (i = offset; i < next && i < matchc; i++) { Err bitreich.org 70 i+ fprintf(stderr, Err bitreich.org 70 i+ opt['#'] && matchv[i][0] == '#' ? "\x1b[1m %s \x1b[m" : Err bitreich.org 70 i+ i == current ? "\x1b[7m %s \x1b[m" : " %s ", Err bitreich.org 70 i+ format(matchv[i], ws.ws_col - 1) Err bitreich.org 70 i+ ); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ if (next < matchc) Err bitreich.org 70 i+ fprintf(stderr, "\x1b[%dC\b>", ws.ws_col - MARGIN); Err bitreich.org 70 i+ fputc('\r', stderr); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+print_screen(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int cols = ws.ws_col - 1; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (opt['l'] > 0) Err bitreich.org 70 i+ print_lines(); Err bitreich.org 70 i+ else Err bitreich.org 70 i+ print_segments(); Err bitreich.org 70 i+ if (*prompt) { Err bitreich.org 70 i+ format(prompt, cols - 2); Err bitreich.org 70 i+ fprintf(stderr, "\x1b[30;47m %s \x1b[m", formatted); Err bitreich.org 70 i+ cols -= strlen(formatted) + 2; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ fputc(' ', stderr); Err bitreich.org 70 i+ fputs(format(input, cols), stderr); Err bitreich.org 70 i+ fflush(stderr); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+print_selection(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ char **match; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (opt['#']) { Err bitreich.org 70 i+ match = matchv + current; Err bitreich.org 70 i+ while (--match >= matchv) { Err bitreich.org 70 i+ if ((*match)[0] == '#') { Err bitreich.org 70 i+ fputs(*match + 1, stdout); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+ putchar('\t'); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ if (matchc == 0 || (opt['#'] && matchv[current][0] == '#')) Err bitreich.org 70 i+ puts(input); Err bitreich.org 70 i+ else Err bitreich.org 70 i+ puts(matchv[current]); Err bitreich.org 70 i+ fputs("\r\x1b[K", stderr); Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/display.h b/display.h /scm/iomenu/file/display.h.gph bitreich.org 70 i@@ -0,0 +1,2 @@ Err bitreich.org 70 i+void print_screen (void); Err bitreich.org 70 i+void print_selection (void); Err bitreich.org 70 1diff --git a/iomenu.c b/iomenu.c /scm/iomenu/file/iomenu.c.gph bitreich.org 70 i@@ -1,543 +0,0 @@ Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i- Err bitreich.org 70 i-#include Err bitreich.org 70 i- Err bitreich.org 70 i-#include "utf8.h" Err bitreich.org 70 i- Err bitreich.org 70 i-#ifndef SIGWINCH Err bitreich.org 70 i-#define SIGWINCH 28 Err bitreich.org 70 i-#endif Err bitreich.org 70 i-#define CONTINUE 2 /* as opposed to EXIT_SUCCESS and EXIT_FAILURE */ Err bitreich.org 70 i-#define MARGIN 30 /* space for the input before the horizontal list */ Err bitreich.org 70 i- Err bitreich.org 70 i-#define CTL(char) (char ^ 0x40) Err bitreich.org 70 i-#define ALT(char) (char + 0x80) Err bitreich.org 70 i-#define CSI(char) (char + 0x80 + 0x80) Err bitreich.org 70 i-#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) Err bitreich.org 70 i- Err bitreich.org 70 i-static struct winsize ws; Err bitreich.org 70 i-static struct termios termios; Err bitreich.org 70 i-static int ttyfd; Err bitreich.org 70 i-static int current = 0, offset = 0, next = 0; Err bitreich.org 70 i-static int linec = 0, matchc = 0; Err bitreich.org 70 i-static char **linev = NULL, **matchv = NULL; Err bitreich.org 70 i-static char input[LINE_MAX], formatted[LINE_MAX * 8]; Err bitreich.org 70 i-static int opt[128], rows = 0; Err bitreich.org 70 i-static char *prompt = ""; Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-free_lines(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- if (linev) { Err bitreich.org 70 i- for (; linec > 0; linec--) Err bitreich.org 70 i- free(linev[linec - 1]); Err bitreich.org 70 i- free(linev); Err bitreich.org 70 i- } Err bitreich.org 70 i- if (matchv) Err bitreich.org 70 i- free(matchv); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-die(const char *s) Err bitreich.org 70 i-{ Err bitreich.org 70 i- tcsetattr(ttyfd, TCSANOW, &termios); Err bitreich.org 70 i- close(ttyfd); Err bitreich.org 70 i- free_lines(); Err bitreich.org 70 i- perror(s); Err bitreich.org 70 i- exit(EXIT_FAILURE); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static char * Err bitreich.org 70 i-read_line(FILE *fp) Err bitreich.org 70 i-{ Err bitreich.org 70 i- char *line; Err bitreich.org 70 i- size_t len; Err bitreich.org 70 i- Err bitreich.org 70 i- line = malloc(LINE_MAX + 1); Err bitreich.org 70 i- if (!(fgets(line, LINE_MAX, fp))) { Err bitreich.org 70 i- free(line); Err bitreich.org 70 i- return NULL; Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- len = strlen(line); Err bitreich.org 70 i- if (len > 0 && line[len - 1] == '\n') Err bitreich.org 70 i- line[len - 1] = '\0'; Err bitreich.org 70 i- Err bitreich.org 70 i- return (line); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-read_stdin(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int size = 0; Err bitreich.org 70 i- Err bitreich.org 70 i- while (1) { Err bitreich.org 70 i- if (linec >= size) { Err bitreich.org 70 i- size += BUFSIZ; Err bitreich.org 70 i- linev = realloc(linev, sizeof (char **) * size); Err bitreich.org 70 i- matchv = realloc(matchv, sizeof (char **) * size); Err bitreich.org 70 i- if (!linev || !matchv) Err bitreich.org 70 i- die("realloc"); Err bitreich.org 70 i- } Err bitreich.org 70 i- if ((linev[linec] = read_line(stdin)) == NULL) Err bitreich.org 70 i- break; Err bitreich.org 70 i- linec++; Err bitreich.org 70 i- matchc++; Err bitreich.org 70 i- } Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-set_terminal(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- struct termios new; Err bitreich.org 70 i- Err bitreich.org 70 i- /* save currentsor postition */ Err bitreich.org 70 i- fputs("\x1b[s", stderr); Err bitreich.org 70 i- Err bitreich.org 70 i- /* save attributes to `termios` */ Err bitreich.org 70 i- if (tcgetattr(ttyfd, &termios) < 0 || tcgetattr(ttyfd, &new) < 0) { Err bitreich.org 70 i- perror("tcgetattr"); Err bitreich.org 70 i- exit(EXIT_FAILURE); Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- /* change to raw mode */ Err bitreich.org 70 i- new.c_lflag &= ~(ICANON | ECHO | IGNBRK | IEXTEN | ISIG); Err bitreich.org 70 i- tcsetattr(ttyfd, TCSANOW, &new); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-reset_terminal(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int i; Err bitreich.org 70 i- Err bitreich.org 70 i- /* clear terminal */ Err bitreich.org 70 i- for (i = 0; i < rows + 1; i++) Err bitreich.org 70 i- fputs("\r\x1b[K\n", stderr); Err bitreich.org 70 i- Err bitreich.org 70 i- /* reset currentsor position */ Err bitreich.org 70 i- fputs("\x1b[u", stderr); Err bitreich.org 70 i- Err bitreich.org 70 i- tcsetattr(ttyfd, TCSANOW, &termios); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static size_t Err bitreich.org 70 i-width(char *s) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int width = 0; Err bitreich.org 70 i- Err bitreich.org 70 i- while (*s) { Err bitreich.org 70 i- if (*s++ == '\t') Err bitreich.org 70 i- width += 8 - (width % 8); Err bitreich.org 70 i- else Err bitreich.org 70 i- width++; Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- return width; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static int Err bitreich.org 70 i-prev_page(int pos) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int col, cols = ws.ws_col - MARGIN - 4; Err bitreich.org 70 i- Err bitreich.org 70 i- pos -= pos > 0 ? 1 : 0; Err bitreich.org 70 i- for (col = 0; pos > 0; pos--) Err bitreich.org 70 i- if ((col += width(matchv[pos]) + 2) > cols) Err bitreich.org 70 i- return pos + 1; Err bitreich.org 70 i- return pos; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static int Err bitreich.org 70 i-next_page(int pos) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int col, cols = ws.ws_col - MARGIN - 4; Err bitreich.org 70 i- Err bitreich.org 70 i- for (col = 0; pos < matchc; pos++) Err bitreich.org 70 i- if ((col += width(matchv[pos]) + 2) > cols) Err bitreich.org 70 i- return pos; Err bitreich.org 70 i- return pos; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-move(signed int sign) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int i; Err bitreich.org 70 i- Err bitreich.org 70 i- for (i = current + sign; 0 <= i && i < matchc; i += sign) { Err bitreich.org 70 i- if (!opt['#'] || matchv[i][0] != '#') { Err bitreich.org 70 i- current = i; Err bitreich.org 70 i- break; Err bitreich.org 70 i- } Err bitreich.org 70 i- } Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-move_page(signed int sign) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int i; Err bitreich.org 70 i- Err bitreich.org 70 i- if (opt['l'] <= 0) { Err bitreich.org 70 i- if (sign > 0) { Err bitreich.org 70 i- offset = current = next; Err bitreich.org 70 i- next = next_page(next); Err bitreich.org 70 i- } else if (sign < 0) { Err bitreich.org 70 i- next = offset; Err bitreich.org 70 i- offset = current = prev_page(offset); Err bitreich.org 70 i- } Err bitreich.org 70 i- } else { Err bitreich.org 70 i- i = current - current % rows + rows * sign; Err bitreich.org 70 i- if (!(0 < i && i < matchc)) Err bitreich.org 70 i- return; Err bitreich.org 70 i- current = i - 1; Err bitreich.org 70 i- move(+1); Err bitreich.org 70 i- } Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static char * Err bitreich.org 70 i-format(char *str, int cols) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int col = 0; Err bitreich.org 70 i- long rune = 0; Err bitreich.org 70 i- char *fmt = formatted; Err bitreich.org 70 i- Err bitreich.org 70 i- while (*str && col < cols) { Err bitreich.org 70 i- if (*str == '\t') { Err bitreich.org 70 i- int t = 8 - col % 8; Err bitreich.org 70 i- while (t-- && col < cols) { Err bitreich.org 70 i- *fmt++ = ' '; Err bitreich.org 70 i- col++; Err bitreich.org 70 i- } Err bitreich.org 70 i- str++; Err bitreich.org 70 i- } else if (utf8_to_rune(&rune, str) && rune_is_print(rune)) { Err bitreich.org 70 i- int i = utf8_len(str); Err bitreich.org 70 i- while (i--) Err bitreich.org 70 i- *fmt++ = *str++; Err bitreich.org 70 i- col++; Err bitreich.org 70 i- } else { Err bitreich.org 70 i- *fmt++ = '?'; Err bitreich.org 70 i- col++; Err bitreich.org 70 i- str++; Err bitreich.org 70 i- } Err bitreich.org 70 i- } Err bitreich.org 70 i- *fmt = '\0'; Err bitreich.org 70 i- Err bitreich.org 70 i- return formatted; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-print_lines(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int printed = 0, i = current - current % rows; Err bitreich.org 70 i- Err bitreich.org 70 i- for (; printed < rows && i < matchc; i++, printed++) { Err bitreich.org 70 i- fprintf(stderr, Err bitreich.org 70 i- opt['#'] && matchv[i][0] == '#' ? Err bitreich.org 70 i- "\n\x1b[1m\x1b[K %s\x1b[m" : Err bitreich.org 70 i- i == current ? Err bitreich.org 70 i- "\n\x1b[47;30m\x1b[K %s\x1b[m" : Err bitreich.org 70 i- "\n\x1b[K %s", Err bitreich.org 70 i- format(matchv[i], ws.ws_col - 1) Err bitreich.org 70 i- ); Err bitreich.org 70 i- } Err bitreich.org 70 i- while (printed++ < rows) Err bitreich.org 70 i- fputs("\n\x1b[K", stderr); Err bitreich.org 70 i- fprintf(stderr, "\x1b[%dA\r\x1b[K", rows); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-print_segments(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int i; Err bitreich.org 70 i- Err bitreich.org 70 i- if (current < offset) { Err bitreich.org 70 i- next = offset; Err bitreich.org 70 i- offset = prev_page(offset); Err bitreich.org 70 i- } else if (current >= next) { Err bitreich.org 70 i- offset = next; Err bitreich.org 70 i- next = next_page(offset); Err bitreich.org 70 i- } Err bitreich.org 70 i- fprintf(stderr, "\r\x1b[K\x1b[%dC", MARGIN); Err bitreich.org 70 i- fputs(offset > 0 ? "< " : " ", stderr); Err bitreich.org 70 i- for (i = offset; i < next && i < matchc; i++) { Err bitreich.org 70 i- fprintf(stderr, Err bitreich.org 70 i- opt['#'] && matchv[i][0] == '#' ? "\x1b[1m %s \x1b[m" : Err bitreich.org 70 i- i == current ? "\x1b[7m %s \x1b[m" : " %s ", Err bitreich.org 70 i- format(matchv[i], ws.ws_col - 1) Err bitreich.org 70 i- ); Err bitreich.org 70 i- } Err bitreich.org 70 i- if (next < matchc) Err bitreich.org 70 i- fprintf(stderr, "\x1b[%dC\b>", ws.ws_col - MARGIN); Err bitreich.org 70 i- fputc('\r', stderr); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-print_screen(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int cols = ws.ws_col - 1; Err bitreich.org 70 i- Err bitreich.org 70 i- if (opt['l'] > 0) Err bitreich.org 70 i- print_lines(); Err bitreich.org 70 i- else Err bitreich.org 70 i- print_segments(); Err bitreich.org 70 i- if (*prompt) { Err bitreich.org 70 i- format(prompt, cols - 2); Err bitreich.org 70 i- fprintf(stderr, "\x1b[30;47m %s \x1b[m", formatted); Err bitreich.org 70 i- cols -= strlen(formatted) + 2; Err bitreich.org 70 i- } Err bitreich.org 70 i- fputc(' ', stderr); Err bitreich.org 70 i- fputs(format(input, cols), stderr); Err bitreich.org 70 i- fflush(stderr); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static int Err bitreich.org 70 i-match_line(char *line, char **tokv, int tokc) Err bitreich.org 70 i-{ Err bitreich.org 70 i- if (opt['#'] && line[0] == '#') Err bitreich.org 70 i- return 2; Err bitreich.org 70 i- while (tokc-- > 0) Err bitreich.org 70 i- if (strstr(line, tokv[tokc]) == NULL) Err bitreich.org 70 i- return 0; Err bitreich.org 70 i- Err bitreich.org 70 i- return 1; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-filter(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int tokc = 0; Err bitreich.org 70 i- int n = 0; Err bitreich.org 70 i- int i; Err bitreich.org 70 i- char **tokv = NULL; Err bitreich.org 70 i- char *s; Err bitreich.org 70 i- char buffer[sizeof (input)]; Err bitreich.org 70 i- Err bitreich.org 70 i- current = offset = next = 0; Err bitreich.org 70 i- strcpy(buffer, input); Err bitreich.org 70 i- for (s = strtok(buffer, " "); s; s = strtok(NULL, " "), tokc++) { Err bitreich.org 70 i- if (tokc >= n) { Err bitreich.org 70 i- tokv = realloc(tokv, ++n * sizeof (*tokv)); Err bitreich.org 70 i- if (tokv == NULL) Err bitreich.org 70 i- die("realloc"); Err bitreich.org 70 i- } Err bitreich.org 70 i- tokv[tokc] = s; Err bitreich.org 70 i- } Err bitreich.org 70 i- matchc = 0; Err bitreich.org 70 i- for (i = 0; i < linec; i++) Err bitreich.org 70 i- if (match_line(linev[i], tokv, tokc)) Err bitreich.org 70 i- matchv[matchc++] = linev[i]; Err bitreich.org 70 i- free(tokv); Err bitreich.org 70 i- if (opt['#'] && matchv[current][0] == '#') Err bitreich.org 70 i- move(+1); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-remove_word() Err bitreich.org 70 i-{ Err bitreich.org 70 i- int len; Err bitreich.org 70 i- int i; Err bitreich.org 70 i- Err bitreich.org 70 i- len = strlen(input) - 1; Err bitreich.org 70 i- for (i = len; i >= 0 && isspace(input[i]); i--) Err bitreich.org 70 i- input[i] = '\0'; Err bitreich.org 70 i- len = strlen(input) - 1; Err bitreich.org 70 i- for (i = len; i >= 0 && !isspace(input[i]); i--) Err bitreich.org 70 i- input[i] = '\0'; Err bitreich.org 70 i- filter(); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-add_char(char key) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int len; Err bitreich.org 70 i- Err bitreich.org 70 i- len = strlen(input); Err bitreich.org 70 i- if (isprint(key)) { Err bitreich.org 70 i- input[len] = key; Err bitreich.org 70 i- input[len + 1] = '\0'; Err bitreich.org 70 i- } Err bitreich.org 70 i- filter(); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-print_selection(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- char **match; Err bitreich.org 70 i- Err bitreich.org 70 i- if (opt['#']) { Err bitreich.org 70 i- match = matchv + current; Err bitreich.org 70 i- while (--match >= matchv) { Err bitreich.org 70 i- if ((*match)[0] == '#') { Err bitreich.org 70 i- fputs(*match + 1, stdout); Err bitreich.org 70 i- break; Err bitreich.org 70 i- } Err bitreich.org 70 i- } Err bitreich.org 70 i- putchar('\t'); Err bitreich.org 70 i- } Err bitreich.org 70 i- if (matchc == 0 || (opt['#'] && matchv[current][0] == '#')) Err bitreich.org 70 i- puts(input); Err bitreich.org 70 i- else Err bitreich.org 70 i- puts(matchv[current]); Err bitreich.org 70 i- fputs("\r\x1b[K", stderr); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static int Err bitreich.org 70 i-key(int key) Err bitreich.org 70 i-{ Err bitreich.org 70 i-top: Err bitreich.org 70 i- switch (key) { Err bitreich.org 70 i- Err bitreich.org 70 i- case CTL('C'): Err bitreich.org 70 i- return EXIT_FAILURE; Err bitreich.org 70 i- Err bitreich.org 70 i- case CTL('U'): Err bitreich.org 70 i- input[0] = '\0'; Err bitreich.org 70 i- filter(); Err bitreich.org 70 i- break; Err bitreich.org 70 i- Err bitreich.org 70 i- case CTL('W'): Err bitreich.org 70 i- remove_word(); Err bitreich.org 70 i- break; Err bitreich.org 70 i- Err bitreich.org 70 i- case 127: Err bitreich.org 70 i- case CTL('H'): /* backspace */ Err bitreich.org 70 i- input[strlen(input) - 1] = '\0'; Err bitreich.org 70 i- filter(); Err bitreich.org 70 i- break; Err bitreich.org 70 i- Err bitreich.org 70 i- case CSI('A'): /* up */ Err bitreich.org 70 i- case CTL('P'): Err bitreich.org 70 i- move(-1); Err bitreich.org 70 i- break; Err bitreich.org 70 i- Err bitreich.org 70 i- case CSI('B'): /* down */ Err bitreich.org 70 i- case CTL('N'): Err bitreich.org 70 i- move(+1); Err bitreich.org 70 i- break; Err bitreich.org 70 i- Err bitreich.org 70 i- case CSI('5'): /* page up */ Err bitreich.org 70 i- if (fgetc(stdin) != '~') Err bitreich.org 70 i- break; Err bitreich.org 70 i- /* fallthrough */ Err bitreich.org 70 i- Err bitreich.org 70 i- case ALT('v'): Err bitreich.org 70 i- move_page(-1); Err bitreich.org 70 i- break; Err bitreich.org 70 i- Err bitreich.org 70 i- case CSI('6'): /* page down */ Err bitreich.org 70 i- if (fgetc(stdin) != '~') Err bitreich.org 70 i- break; Err bitreich.org 70 i- /* fallthrough */ Err bitreich.org 70 i- Err bitreich.org 70 i- case CTL('V'): Err bitreich.org 70 i- move_page(+1); Err bitreich.org 70 i- break; Err bitreich.org 70 i- Err bitreich.org 70 i- case CTL('I'): /* tab */ Err bitreich.org 70 i- if (linec > 0) Err bitreich.org 70 i- strcpy(input, matchv[current]); Err bitreich.org 70 i- filter(); Err bitreich.org 70 i- break; Err bitreich.org 70 i- Err bitreich.org 70 i- case CTL('J'): /* enter */ Err bitreich.org 70 i- case CTL('M'): Err bitreich.org 70 i- print_selection(); Err bitreich.org 70 i- return EXIT_SUCCESS; Err bitreich.org 70 i- Err bitreich.org 70 i- case ALT('['): Err bitreich.org 70 i- key = CSI(fgetc(stdin)); Err bitreich.org 70 i- goto top; Err bitreich.org 70 i- Err bitreich.org 70 i- case 0x1b: /* escape / alt */ Err bitreich.org 70 i- key = ALT(fgetc(stdin)); Err bitreich.org 70 i- goto top; Err bitreich.org 70 i- Err bitreich.org 70 i- default: Err bitreich.org 70 i- add_char((char) key); Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- return CONTINUE; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-sigwinch() Err bitreich.org 70 i-{ Err bitreich.org 70 i- if (ioctl(ttyfd, TIOCGWINSZ, &ws) < 0) Err bitreich.org 70 i- die("ioctl"); Err bitreich.org 70 i- rows = MIN(opt['l'], ws.ws_row - 1); Err bitreich.org 70 i- print_screen(); Err bitreich.org 70 i- signal(SIGWINCH, sigwinch); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-usage(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- fputs("iomenu [-#] [-l lines] [-p prompt]\n", stderr); Err bitreich.org 70 i- exit(EXIT_FAILURE); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-parse_opt(int argc, char *argv[]) Err bitreich.org 70 i-{ Err bitreich.org 70 i- memset(opt, 0, 128 * sizeof (int)); Err bitreich.org 70 i- opt['l'] = 255; Err bitreich.org 70 i- for (argv++, argc--; argc > 0; argv++, argc--) { Err bitreich.org 70 i- if (argv[0][0] != '-') Err bitreich.org 70 i- usage(); Err bitreich.org 70 i- switch ((*argv)[1]) { Err bitreich.org 70 i- case 'l': Err bitreich.org 70 i- if (!--argc || sscanf(*++argv, "%d", &opt['l']) <= 0) Err bitreich.org 70 i- usage(); Err bitreich.org 70 i- break; Err bitreich.org 70 i- case 'p': Err bitreich.org 70 i- if (!--argc) Err bitreich.org 70 i- usage(); Err bitreich.org 70 i- prompt = *++argv; Err bitreich.org 70 i- break; Err bitreich.org 70 i- case '#': Err bitreich.org 70 i- opt['#'] = 1; Err bitreich.org 70 i- break; Err bitreich.org 70 i- case 's': Err bitreich.org 70 i- if (!--argc) Err bitreich.org 70 i- usage(); Err bitreich.org 70 i- opt['s'] = (int) **++argv; Err bitreich.org 70 i- break; Err bitreich.org 70 i- default: Err bitreich.org 70 i- usage(); Err bitreich.org 70 i- } Err bitreich.org 70 i- } Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-int Err bitreich.org 70 i-main(int argc, char *argv[]) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int exit_code; Err bitreich.org 70 i- Err bitreich.org 70 i- parse_opt(argc, argv); Err bitreich.org 70 i- read_stdin(); Err bitreich.org 70 i- filter(); Err bitreich.org 70 i- if (!freopen("/dev/tty", "r", stdin)) Err bitreich.org 70 i- die("freopen /dev/tty"); Err bitreich.org 70 i- if (!freopen("/dev/tty", "w", stderr)) Err bitreich.org 70 i- die("freopen /dev/tty"); Err bitreich.org 70 i- ttyfd = open("/dev/tty", O_RDWR); Err bitreich.org 70 i- set_terminal(); Err bitreich.org 70 i- sigwinch(); Err bitreich.org 70 i- input[0] = '\0'; Err bitreich.org 70 i- while ((exit_code = key(fgetc(stdin))) == CONTINUE) Err bitreich.org 70 i- print_screen(); Err bitreich.org 70 i- print_screen(); Err bitreich.org 70 i- reset_terminal(); Err bitreich.org 70 i- close(ttyfd); Err bitreich.org 70 i- free_lines(); Err bitreich.org 70 i- Err bitreich.org 70 i- return exit_code; Err bitreich.org 70 i-} Err bitreich.org 70 1diff --git a/iomenu.core b/iomenu.core /scm/iomenu/file/iomenu.core.gph bitreich.org 70 iBinary files differ. Err bitreich.org 70 1diff --git a/main.c b/main.c /scm/iomenu/file/main.c.gph bitreich.org 70 i@@ -0,0 +1,123 @@ Err bitreich.org 70 i+#include "main.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct termios termios; Err bitreich.org 70 i+static int ttyfd; Err bitreich.org 70 i+ Err bitreich.org 70 i+void Err bitreich.org 70 i+die(const char *s) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ tcsetattr(ttyfd, TCSANOW, &termios); Err bitreich.org 70 i+ close(ttyfd); Err bitreich.org 70 i+ free_lines(); Err bitreich.org 70 i+ perror(s); Err bitreich.org 70 i+ exit(EXIT_FAILURE); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+set_terminal(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct termios new; Err bitreich.org 70 i+ Err bitreich.org 70 i+ /* save currentsor postition */ Err bitreich.org 70 i+ fputs("\x1b[s", stderr); Err bitreich.org 70 i+ Err bitreich.org 70 i+ /* save attributes to `termios` */ Err bitreich.org 70 i+ if (tcgetattr(ttyfd, &termios) < 0 || tcgetattr(ttyfd, &new) < 0) { Err bitreich.org 70 i+ perror("tcgetattr"); Err bitreich.org 70 i+ exit(EXIT_FAILURE); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ /* change to raw mode */ Err bitreich.org 70 i+ new.c_lflag &= ~(ICANON | ECHO | IGNBRK | IEXTEN | ISIG); Err bitreich.org 70 i+ tcsetattr(ttyfd, TCSANOW, &new); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+reset_terminal(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ /* clear terminal */ Err bitreich.org 70 i+ for (i = 0; i < rows + 1; i++) Err bitreich.org 70 i+ fputs("\r\x1b[K\n", stderr); Err bitreich.org 70 i+ Err bitreich.org 70 i+ /* reset currentsor position */ Err bitreich.org 70 i+ fputs("\x1b[u", stderr); Err bitreich.org 70 i+ Err bitreich.org 70 i+ tcsetattr(ttyfd, TCSANOW, &termios); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+sigwinch() Err bitreich.org 70 i+{ Err bitreich.org 70 i+ if (ioctl(ttyfd, TIOCGWINSZ, &ws) < 0) Err bitreich.org 70 i+ die("ioctl"); Err bitreich.org 70 i+ rows = MIN(opt['l'], ws.ws_row - 1); Err bitreich.org 70 i+ print_screen(); Err bitreich.org 70 i+ signal(SIGWINCH, sigwinch); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+usage(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ fputs("iomenu [-#] [-l lines] [-p prompt]\n", stderr); Err bitreich.org 70 i+ exit(EXIT_FAILURE); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+parse_opt(int argc, char *argv[]) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ memset(opt, 0, 128 * sizeof (int)); Err bitreich.org 70 i+ opt['l'] = 255; Err bitreich.org 70 i+ for (argv++, argc--; argc > 0; argv++, argc--) { Err bitreich.org 70 i+ if (argv[0][0] != '-') Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ switch ((*argv)[1]) { Err bitreich.org 70 i+ case 'l': Err bitreich.org 70 i+ if (!--argc || sscanf(*++argv, "%d", &opt['l']) <= 0) Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 'p': Err bitreich.org 70 i+ if (!--argc) Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ prompt = *++argv; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case '#': Err bitreich.org 70 i+ opt['#'] = 1; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 's': Err bitreich.org 70 i+ if (!--argc) Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ opt['s'] = (int) **++argv; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ default: Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+main(int argc, char *argv[]) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int exit_code; Err bitreich.org 70 i+ Err bitreich.org 70 i+ parse_opt(argc, argv); Err bitreich.org 70 i+ read_stdin(); Err bitreich.org 70 i+ filter(); Err bitreich.org 70 i+ if (!freopen("/dev/tty", "r", stdin)) Err bitreich.org 70 i+ die("freopen /dev/tty"); Err bitreich.org 70 i+ if (!freopen("/dev/tty", "w", stderr)) Err bitreich.org 70 i+ die("freopen /dev/tty"); Err bitreich.org 70 i+ ttyfd = open("/dev/tty", O_RDWR); Err bitreich.org 70 i+ set_terminal(); Err bitreich.org 70 i+ sigwinch(); Err bitreich.org 70 i+ input[0] = '\0'; Err bitreich.org 70 i+ while ((exit_code = key(fgetc(stdin))) == CONTINUE) Err bitreich.org 70 i+ print_screen(); Err bitreich.org 70 i+ print_screen(); Err bitreich.org 70 i+ reset_terminal(); Err bitreich.org 70 i+ close(ttyfd); Err bitreich.org 70 i+ free_lines(); Err bitreich.org 70 i+ Err bitreich.org 70 i+ return exit_code; Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/main.h b/main.h /scm/iomenu/file/main.h.gph bitreich.org 70 i@@ -0,0 +1,29 @@ Err bitreich.org 70 i+#ifndef SIGWINCH Err bitreich.org 70 i+#define SIGWINCH 28 Err bitreich.org 70 i+#endif Err bitreich.org 70 i+ Err bitreich.org 70 i+#define CONTINUE (EXIT_SUCCESS + EXIT_FAILURE + 1) Err bitreich.org 70 i+#define MARGIN 30 Err bitreich.org 70 i+ Err bitreich.org 70 i+#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) Err bitreich.org 70 i+ Err bitreich.org 70 i+winsize ws; Err bitreich.org 70 i+char **linev = NULL; Err bitreich.org 70 i+int linec = 0; Err bitreich.org 70 i+char **matchv = NULL; Err bitreich.org 70 i+int matchc = 0; Err bitreich.org 70 i+char *prompt = ""; Err bitreich.org 70 i+char input[LINE_MAX]; Err bitreich.org 70 i+char formatted[LINE_MAX * 8]; Err bitreich.org 70 i+int current = 0; Err bitreich.org 70 i+int offset = 0; Err bitreich.org 70 i+int next = 0; Err bitreich.org 70 i+int opt[128]; Err bitreich.org 70 i+int rows = 0; Err bitreich.org 70 i+ Err bitreich.org 70 i+size_t utf8_len (char *); Err bitreich.org 70 i+size_t rune_len (long); Err bitreich.org 70 i+size_t utf8_to_rune (long *, char *); Err bitreich.org 70 i+int utf8_is_unicode (long); Err bitreich.org 70 i+int utf8_check (char *); Err bitreich.org 70 i+int utf8_is_print (long); Err bitreich.org 70 1diff --git a/utf8.c b/utf8.c /scm/iomenu/file/utf8.c.gph bitreich.org 70 i@@ -1,3 +1,5 @@ Err bitreich.org 70 i+#include "utf8.h" Err bitreich.org 70 i+ Err bitreich.org 70 i /* Err bitreich.org 70 i * ASCII all have a leading '0' byte: Err bitreich.org 70 i * Err bitreich.org 70 i@@ -28,7 +30,6 @@ Err bitreich.org 70 i Err bitreich.org 70 i #include "utf8.h" Err bitreich.org 70 i Err bitreich.org 70 i- Err bitreich.org 70 i /* Err bitreich.org 70 i * Return the number of bytes in rune for the `n` next char in `s`, Err bitreich.org 70 i * or 0 if ti is misencoded. Err bitreich.org 70 i@@ -56,20 +57,18 @@ utf8_len(char *s) Err bitreich.org 70 i return len; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i- Err bitreich.org 70 i /* Err bitreich.org 70 i * Return the number of bytes required to encode `rune` into UTF-8, or Err bitreich.org 70 i * 0 if rune is too long. Err bitreich.org 70 i */ Err bitreich.org 70 i size_t Err bitreich.org 70 i-rune_len(long r) Err bitreich.org 70 i+utf8_rune_len(long r) Err bitreich.org 70 i { Err bitreich.org 70 i return (r <= 0x0000007f) ? 1 : (r <= 0x000007ff) ? 2 : Err bitreich.org 70 i (r <= 0x0000ffff) ? 3 : (r <= 0x001fffff) ? 4 : Err bitreich.org 70 i (r <= 0x03ffffff) ? 5 : (r <= 0x7fffffff) ? 6 : 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i- Err bitreich.org 70 i /* Err bitreich.org 70 i * Sets 'r' to a rune corresponding to the firsts 'n' bytes of 's'. Err bitreich.org 70 i * Err bitreich.org 70 i@@ -92,13 +91,12 @@ utf8_to_rune(long *r, char *s) Err bitreich.org 70 i *r = (*r << 6) | (*s++ & 0x3f); /* 10xxxxxx */ Err bitreich.org 70 i Err bitreich.org 70 i /* overlong sequences */ Err bitreich.org 70 i- if (rune_len(*r) != len) Err bitreich.org 70 i+ if (utf8_rune_len(*r) != len) Err bitreich.org 70 i return 0; Err bitreich.org 70 i Err bitreich.org 70 i return len; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i- Err bitreich.org 70 i /* Err bitreich.org 70 i * Returns 1 if the rune is a valid unicode code point and 0 if not. Err bitreich.org 70 i */ Err bitreich.org 70 i@@ -119,7 +117,6 @@ rune_is_unicode(long r) Err bitreich.org 70 i ); Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i- Err bitreich.org 70 i /* Err bitreich.org 70 i * Return 1 if '*s' is correctly encoded in UTF-8 with allowed Unicode Err bitreich.org 70 i * code points. Err bitreich.org 70 i@@ -146,7 +143,7 @@ utf8_check(char *s) Err bitreich.org 70 i * Return 1 if the rune is a printable character, and 0 otherwise. Err bitreich.org 70 i */ Err bitreich.org 70 i int Err bitreich.org 70 i-rune_is_print(long r) Err bitreich.org 70 i+utf8_is_print(long r) Err bitreich.org 70 i { Err bitreich.org 70 i return (0x1f < r && r != 0x7f && r < 0x80) || 0x9f < r; Err bitreich.org 70 i } Err bitreich.org 70 1diff --git a/utf8.h b/utf8.h /scm/iomenu/file/utf8.h.gph bitreich.org 70 i@@ -1,6 +1,6 @@ Err bitreich.org 70 i-size_t utf8_len(char *); Err bitreich.org 70 i-size_t rune_len(long); Err bitreich.org 70 i-size_t utf8_to_rune(long *, char *); Err bitreich.org 70 i-int utf8_is_unicode(long); Err bitreich.org 70 i-int utf8_check(char *); Err bitreich.org 70 i-int rune_is_print(long); Err bitreich.org 70 i+size_t utf8_len (char *); Err bitreich.org 70 i+size_t rune_len (long); Err bitreich.org 70 i+size_t utf8_to_rune (long *, char *); Err bitreich.org 70 i+int utf8_is_unicode (long); Err bitreich.org 70 i+int utf8_check (char *); Err bitreich.org 70 i+int utf8_is_print (long); Err bitreich.org 70 .