diff options
author | Jakob Kaivo <jkk@ung.org> | 2022-04-18 19:12:52 -0400 |
---|---|---|
committer | Jakob Kaivo <jkk@ung.org> | 2022-04-18 19:12:52 -0400 |
commit | 1fa82850d87a0f5526153655a2368c46ea447a90 (patch) | |
tree | 5ffd8c628a4a221b93cd68b36ec82b6e182bd314 | |
parent | 344424ffafe5e3b310b5595d897579544abdb90d (diff) |
switch to curses
-rw-r--r-- | Makefile | 11 | ||||
-rw-r--r-- | io.c | 12 | ||||
-rw-r--r-- | more.c | 107 | ||||
-rw-r--r-- | more.h | 6 | ||||
-rw-r--r-- | tty.c | 77 |
5 files changed, 78 insertions, 135 deletions
@@ -8,16 +8,20 @@ CC=c99 LD=$(CC) CFLAGS=-Wall -Wextra -Wpedantic -Werror -g LDFLAGS= -LDLIBS= +LDLIBS=-lcurses SRCDIR=. OBJDIR=. BINDIR=$(OBJDIR) +DESTDIR=/usr/local all: $(BINDIR)/more clean: rm -f $(BINDIR)/more $(OBJDIR)/*.o +install: $(BINDIR)/more + cp $(BINDIR)/more $(DESTDIR)/bin + $(BINDIR)/more: $(OBJDIR)/io.o $(OBJDIR)/io.o: $(SRCDIR)/more.h $(OBJDIR)/io.o: $(SRCDIR)/io.c @@ -28,10 +32,5 @@ $(OBJDIR)/more.o: $(SRCDIR)/more.h $(OBJDIR)/more.o: $(SRCDIR)/more.c $(CC) $(CFLAGS) -o $@ -c $(SRCDIR)/more.c -$(BINDIR)/more: $(OBJDIR)/tty.o -$(OBJDIR)/tty.o: $(SRCDIR)/more.h -$(OBJDIR)/tty.o: $(SRCDIR)/tty.c - $(CC) $(CFLAGS) -o $@ -c $(SRCDIR)/tty.c - $(BINDIR)/more: $(LD) $(LDFLAGS) -o $@ $(OBJDIR)/*.o $(LDLIBS) @@ -11,16 +11,16 @@ ssize_t more_getline(struct more_file *mf, size_t lineno) { if (mf->nlines <= lineno && mf->nlines != 0) { - fsetpos(mf->f, &(mf->lines[mf->nlines - 1])); + fsetpos(mf->f, &(mf->tlines[mf->nlines - 1])); getline(&(mf->buf), &(mf->nbuf), mf->f); } while (mf->nlines <= lineno) { mf->nlines++; - mf->lines = realloc(mf->lines, mf->nlines * sizeof(*mf->lines)); + mf->tlines = realloc(mf->tlines, mf->nlines * sizeof(*mf->tlines)); mf->bytepos = realloc(mf->bytepos, mf->nlines * sizeof(*mf->bytepos)); - fgetpos(mf->f, &(mf->lines[mf->nlines - 1])); + fgetpos(mf->f, &(mf->tlines[mf->nlines - 1])); getline(&(mf->buf), &(mf->nbuf), mf->f); if (mf->nlines > 1) { @@ -30,12 +30,12 @@ ssize_t more_getline(struct more_file *mf, size_t lineno) } if (mf->backing != mf->f) { - fgetpos(mf->backing, &(mf->lines[mf->nlines - 1])); + fgetpos(mf->backing, &(mf->tlines[mf->nlines - 1])); fputs(mf->buf, mf->backing); } } - fsetpos(mf->backing, &(mf->lines[lineno])); + fsetpos(mf->backing, &(mf->tlines[lineno])); return getline(&(mf->buf), &(mf->nbuf), mf->backing); } @@ -76,6 +76,6 @@ void more_close(struct more_file *mf) fclose(mf->f); } - free(mf->lines); + free(mf->tlines); free(mf->buf); } @@ -1,9 +1,11 @@ #define _XOPEN_SOURCE 700 +#include <curses.h> #include <ctype.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <term.h> #include <unistd.h> #include "more.h" @@ -19,22 +21,23 @@ enum { CTRL_U = 0x15, }; -void refresh(const struct more_tty *mt, struct more_file *mf) +void man_refresh(struct more_file *mf) { - for (size_t i = mf->topline; i < mf->topline + mt->lines; i++) { + for (size_t i = mf->topline; i < mf->topline + LINES - 1; i++) { /* FIXME: account for long lines */ if (more_getline(mf, i) == -1) { break; } - printf("%s", mf->buf); + printw("%s", mf->buf); } } -void scroll(const struct more_tty *mt, struct more_file *mf, int count, int multiple) +void man_scroll(struct more_file *mf, int count, int multiple) { int by = count ? count * multiple : multiple; + scrl(by); if (by < 0) { if ((size_t)(-by) > mf->topline) { @@ -42,36 +45,38 @@ void scroll(const struct more_tty *mt, struct more_file *mf, int count, int mult } else { mf->topline += by; } - refresh(mt, mf); + man_refresh(mf); } else while (by-- > 0) { /* FIXME: account for long lines here, too */ mf->topline++; - if (more_getline(mf, mf->topline + mt->lines + 1) < 0) { + if (more_getline(mf, mf->topline + LINES + 1) < 0) { break; } - printf("%s", mf->buf); + printw("%s", mf->buf); } + + refresh(); } -void mark(const struct more_tty *mt, struct more_file *mf) +void mark(struct more_file *mf) { - int c = fgetc(mt->tty); + int c = getch(); if (islower(c)) { mf->mark[c - 'a'] = mf->topline; } } -void jump(const struct more_tty *mt, struct more_file *mf) +void jump(struct more_file *mf) { - int c = fgetc(mt->tty); + int c = getch(); if (islower(c)) { mf->topline = mf->mark[c - 'a']; - refresh(mt, mf); + man_refresh(mf); } } -int more(const struct more_tty *mt, const char *path) +static int more(const char *path) { struct more_file mf = more_open(path); @@ -80,11 +85,11 @@ int more(const struct more_tty *mt, const char *path) return 1; } - refresh(mt, &mf); + man_refresh(&mf); int count = 0; while (mf.f) { - int c = fgetc(mt->tty); + int c = getch(); switch (c) { case EOF: @@ -93,50 +98,50 @@ int more(const struct more_tty *mt, const char *path) case 'h': //show_help(); - printf("Help!"); + printw("Help!"); break; case 'f': case CTRL_F: if (count == 0) { - count = mt->lines; + count = LINES; } - scroll(mt, &mf, count, 1); + man_scroll(&mf, count, 1); break; case 'b': case CTRL_B: if (count == 0) { - count = mt->lines; + count = LINES; } - scroll(mt, &mf, count, -1); + man_scroll(&mf, count, -1); break; case ' ': - count = count ? count : mt->lines; + count = count ? count : LINES; /* FALLTHRU */ case 'j': case '\n': - scroll(mt, &mf, count, 1); + man_scroll(&mf, count, 1); break; case 'k': - scroll(mt, &mf, count, -1); + man_scroll(&mf, count, -1); break; case 'd': case CTRL_D: - scroll(mt, &mf, count, mt->lines / 2); + man_scroll(&mf, count, LINES / 2); break; case 's': count = count ? count : 1; - scroll(mt, &mf, mt->lines + count, 1); + man_scroll(&mf, LINES + count, 1); break; case 'u': case CTRL_U: - scroll(mt, &mf, count, -mt->lines / 2); + man_scroll(&mf, count, -LINES / 2); break; case 'G': @@ -145,7 +150,7 @@ int more(const struct more_tty *mt, const char *path) } /* FALLTHRU */ case 'g': - scroll(mt, &mf, count - mf.topline, 1); + man_scroll(&mf, count - mf.topline, 1); break; case 'R': @@ -153,15 +158,15 @@ int more(const struct more_tty *mt, const char *path) /* FALLTHRU */ case 'r': case CTRL_L: - refresh(mt, &mf); + man_refresh(&mf); break; case 'm': - mark(mt, &mf); + mark(&mf); break; case '\'': - jump(mt, &mf); + jump(&mf); break; case '/': @@ -181,9 +186,13 @@ int more(const struct more_tty *mt, const char *path) break; case ':': { - fputc(c, mt->tty); - int c2 = fgetc(mt->tty); - fprintf(mt->tty, "\b \b"); + addch(c); + echo(); + int c2 = getch(); + noecho(); + + printw("\b \b"); + switch (c2) { case 'e': // examine(); @@ -215,11 +224,11 @@ int more(const struct more_tty *mt, const char *path) case '=': case CTRL_G: - printf("%s; File %d/%d; Line %zd; Byte %zd/%zd; %zd%%", path, 0, 0, mf.topline, mf.bytepos[mf.topline], mf.nbytes, 100 * mf.bytepos[mf.topline] / mf.nbytes); + printw("%s; File %d/%d; Line %zd; Byte %zd/%zd; %zd%%", path, 0, 0, mf.topline, mf.bytepos[mf.topline], mf.nbytes, 100 * mf.bytepos[mf.topline] / mf.nbytes); break; case 'Z': - if (fgetc(mt->tty) != 'Z') { + if (getch() != 'Z') { break; } /* FALLTHRU */ @@ -245,6 +254,8 @@ int more(const struct more_tty *mt, const char *path) if (!isdigit(c)) { count = 0; } + + refresh(); } more_close(&mf); @@ -332,6 +343,11 @@ static int more_cat(const char *path, void (*loop)(FILE *)) return 0; } +static void more_exit(void) +{ + endwin(); +} + int main(int argc, char *argv[]) { int c; @@ -341,7 +357,6 @@ int main(int argc, char *argv[]) int ignorecase = 0; int compressempty = 0; int backspace = 1; - int lines = 0; adjust_args(&argc, &argv); @@ -368,7 +383,7 @@ int main(int argc, char *argv[]) break; case 'n': - lines = atoi(optarg); + setenv("LINES", optarg, 1); break; case 'p': @@ -393,16 +408,25 @@ int main(int argc, char *argv[]) return ret; } - struct more_tty mt = more_open_tty(lines); - if (optind >= argc) { - more(&mt, "-"); + more("-"); + } + + initscr(); + cbreak(); + noecho(); + scrollok(stdscr, TRUE); + + atexit(more_exit); + + if (clear) { + clear(); } int min = optind; int max = argc - 1; while (optind < argc) { - int next = more(&mt, argv[optind]); + int next = more(argv[optind]); optind += next; if (optind < min) { optind = min; @@ -412,7 +436,6 @@ int main(int argc, char *argv[]) } } - (void)clear; (void)fastexit; (void)ignorecase; (void)backspace; @@ -3,15 +3,13 @@ struct more_tty { FILE *tty; - int lines; - int columns; }; struct more_file { FILE *f; FILE *backing; size_t topline; - fpos_t *lines; + fpos_t *tlines; size_t nlines; size_t mark[26]; size_t nbytes; @@ -20,7 +18,7 @@ struct more_file { size_t nbuf; }; -struct more_tty more_open_tty(int lines); +struct more_tty more_open_tty(int nlines); struct more_file more_open(const char *path); void more_close(struct more_file *mf); ssize_t more_getline(struct more_file *mf, size_t lineno); @@ -1,77 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <termios.h> - -#include "more.h" - -static FILE *resetty = NULL; -static struct termios resettings = { 0 }; - -static void resetterm(void) -{ - tcsetattr(fileno(resetty), TCSANOW, &resettings); -} - -static int query_term(const char *cap, const char *variable, int def) -{ - int n = 0; - char cmd[64]; - snprintf(cmd, sizeof(cmd), "tput %s", cap); - FILE *f = popen(cmd, "r"); - if (f) { - if (fscanf(f, "%d", &n) != 1) { - n = 0; - } - pclose(f); - if (n != 0) { - return n; - } - } - - char *value = getenv(variable); - if (value) { - n = atoi(value); - } - return n ? n : def; -} - -struct more_tty more_open_tty(int lines) -{ - struct more_tty mt = { - .tty = stderr, - .lines = query_term("lines", "LINES", 24), - .columns = query_term("cols", "COLUMNS", 80), - }; - - if (lines > 0) { - mt.lines = lines; - } - - /* leave room for prompts */ - lines--; - - /* FIXME: only open /dev/tty if stderr is not readable */ - // if (!(fcntl(fileno(mt.tty), F_GETFL) & (O_WRONLY | O_RDWR))) { - mt.tty = fopen("/dev/tty", "rb+"); - // } - if (mt.tty == NULL) { - perror("Couldn't open tty for reading"); - exit(1); - } - - setbuf(mt.tty, NULL); - - tcgetattr(fileno(mt.tty), &resettings); - struct termios term = resettings; - term.c_lflag &= ~(ECHO | ICANON); - term.c_cc[VMIN] = 1; - term.c_cc[VTIME] = 0; - tcsetattr(fileno(mt.tty), TCSANOW, &term); - - resetty = mt.tty; - atexit(resetterm); - - return mt; -} |