allbery@ncoast.UUCP (04/12/87)
The following program is a "more"-like pager for Minix. It doesn't presume to use termcap as yet (that is to come eventually, I'm putting the real work into an 8250 serial port driver so this was basically a hack). It works given filenames or on standard input in the same fashion as the real "more", and supports the following subset of commands: space Display the next screenful of text newline Display the next line of text ' Skip back to the beginning of the file n Skip to the next file (this is normally ":n") q Quit; typing your interrupt character will also work Enjoy! ++Brando ----------------- cut here ----------------- NOT a shar file ----------------- /* * I like "more", and think "mined" used as a pager is a bit dumb (never * understood "view" as a link to "vi", either). So, here's a simple pager * which acts like the BSD "more" in some limited ways. Commands are any * of: SPACE, RETURN, or q. Del acts as q but works at any time. * * (Actually, I like "pg -n -s" better, and can understand "view" on large * files when I'm only interested in a small section that can't be pulled * with "grep". Someday.) * * No copyright. Copy, use under Minix, Unix, Xenix, etc. Be warned that * there are hardcoded dependencies on the PC Minix console driver. * * ++Brando */ #define reverse() write(1, "\033z\160", 3) /* reverse video */ #define normal() write(1, "\033z\7", 3) /* undo reverse() */ #define clearln() write(1, "\r\033~0", 4) /* clear line */ #define LINES 23 /* lines/screen (- 1 to retain last line) */ #define COLS 80 /* columns/line */ #define TABSTOP 8 /* tabstop expansion */ #include <sgtty.h> #include <signal.h> extern int byebye(); extern char *index(); int line = 0; /* current terminal line */ int col = 0; /* current terminal column */ int fd = -1; /* terminal file descriptor (/dev/tty) */ struct sgttyb ttymode; /* and the terminal modes */ char ibuf[1024]; /* input buffer */ char obuf[1024]; /* output buffer */ int ibl = 0; /* chars in input buffer */ int ibc = 0; /* position in input buffer */ int obc = 0; /* position in output buffer (== chars in) */ int isrewind = 0; /* flag: ' command -- next input() rewind */ int isdone = 0; /* flag: return EOF next read even if not */ main(argc, argv) char **argv; { char ch; int fd, arg; signal(SIGINT, byebye); cbreak(); if (argc < 2) while ((ch = input(fd)) != 0) output(ch); else for (arg = 1; argv[arg] != (char *) 0; arg++) { if ((fd = open(argv[arg], 0)) == -1) { write(1, "more: cannot open ", 18); write(1, argv[arg], strlen(argv[arg])); write(1, "\n", 1); nocbreak(); exit(1); } while ((ch = input(fd)) != 0) output(ch); close(fd); if (argv[arg + 1] != (char *) 0) { oflush(); if (isdone) { /* 'n' command */ reverse(); write(1, "*** Skipping to next file ***\n", 30); normal(); isdone = 0; } reverse(); write(1, "--More-- (Next file: ", 21); write(1, argv[arg + 1], strlen(argv[arg + 1])); write(1, ")", 1); normal(); switch (wtch()) { case ' ': case '\'': case 'n': case 'N': line = 0; break; case '\r': case '\n': line = LINES - 1; break; case 'q': case 'Q': clearln(); byebye(); } clearln(); } } oflush(); byebye(); } input(fd) { if (isdone) { ibl = 0; ibc = 0; return 0; } if (isrewind) { lseek(fd, 0L, 0); ibl = 0; ibc = 0; isrewind = 0; } if (ibc == ibl) { if ((ibl = read(fd, ibuf, sizeof ibuf)) <= 0) return 0; ibc = 0; } return ibuf[ibc++]; } output(c) char c; { if (obc == sizeof obuf) { lwrite(1, obuf, sizeof obuf); obc = 0; } obuf[obc++] = c; } oflush() { if (isdone) obc = 0; else lwrite(1, obuf, obc); } lwrite(fd, buf, len) char *buf; unsigned len; { unsigned here, start; char cmd; start = 0; here = 0; while (here != len) { cmd = '\0'; switch (buf[here++]) { case '\n': col = 0; if (++line == LINES) { write(fd, buf + start, here - start); reverse(); write(1, "--More--", 8); normal(); cmd = wtch(); clearln(); line = 0; start = here; } break; case '\r': col = 0; break; case '\b': if (col != 0) col--; else { line--; col = COLS - 1; } break; case '\t': do { col++; } while (col % TABSTOP != 0); break; default: if (++col == COLS) { col = 0; if (++line == LINES) { write(fd, buf + start, here - start); reverse(); write(1, "--More--", 8); normal(); cmd = wtch(); clearln(); line = 0; start = here; } } } switch (cmd) { case '\0': break; case ' ': line = 0; break; case '\r': case '\n': line = LINES - 1; break; case 'q': case 'Q': byebye(); case '\'': isrewind = 1; reverse(); write(1, "*** Back ***\n", 13); normal(); return; case 'n': case 'N': isdone = 1; return; default: break; } } if (here != start) write(fd, buf + start, here - start); } wtch() { char ch; do { read(fd, &ch, 1); } while (index(" \r\nqQ'nN", ch) == (char *) 0); return ch; } cbreak() { if (fd != -1) return; if ((fd = open("/dev/tty", 0)) == -1) { write(2, "OOPS -- can't open /dev/tty\n", 28); exit(1); } ioctl(fd, TIOCGETP, &ttymode); ttymode.sg_flags |= CBREAK; ttymode.sg_flags &= ~ECHO; ioctl(fd, TIOCSETP, &ttymode); /* NB: add TIOCSETN! */ } nocbreak() { if (fd == -1) return; ttymode.sg_flags &= ~CBREAK; ttymode.sg_flags |= ECHO; ioctl(fd, TIOCSETP, &ttymode); close(fd); fd = -1; } byebye() { nocbreak(); exit(0); } ----------------------------------- finis ------------------------------------ -- Brandon S. Allbery cbatt!cwruecmp!ncoast!allbery +-------------+ aXcess Company ncoast!allbery%case.CSNET@relay.cs.net | panic: | 6615 Center St. #A1-105 MCIMail: BALLBERY | screw loose | Mentor, OH 44060-4101 +01 216 974 9210 +-------------+