#include "gbos.h" /* more [file]: page a file (or stdin) one screenful at a time. * * The terminal is 40x18, so anything longer than a screen scrolls off before * you can read it (try `ls` on a full disk, or `cat` on a wget dump). This * prints 17 lines, then paints a --More-- bar and waits for a keypress: * SELECT opens the on-screen keyboard, any key pages forward, 'q' quits. * * Keys come from pollin()/pollcon(), NOT stdin - so `cat file | more` still * has a keyboard even though its stdin is the pipe. (pollcon also means the * host can drive it over the link with tools/gbtype.) */ #define PAGE 17 /* TROWS - 1: leave a row for the bar */ #define TCOLS 40 static void sgr(unsigned char n) { /* emit ESC [ n m */ putc(27); putc('['); putu(n); putc('m'); } /* show the bar, block until a key arrives; 0 = the user asked to quit */ static unsigned char waitkey(void) { unsigned char c; sgr(44); sgr(37); /* white on blue */ puts("--More--"); sgr(0); for (;;) { c = pollin(); /* on-screen keyboard */ if (!c) c = pollcon(); /* link-injected console bytes */ if (c) break; yield(); /* cooperative: let other procs run */ } puts("\r \r"); /* wipe the bar, stay on the same row */ return (c == 'q' || c == 'Q') ? 0 : 1; } void main(void) { char *argv[4]; unsigned char argc = argv_parse(argv, 4); unsigned char fd = NOFD, rows = 0, col = 0; int ch; if (argc > 0 && argv[0][0] != '-') { fd = open(argv[0], O_READ); if (fd == EISDIR) { puts("more: is a directory"); nl(); sexit(2); } if (fd == NOFD) { puts("more: no such file"); nl(); sexit(2); } } for (;;) { if (fd == NOFD) { char c = readc(); ch = (c == EOF) ? -1 : c; } else ch = fgetc(fd); if (ch < 0) break; putc((char)ch); /* count screen rows, not input lines: a 100-char line wraps to three */ if (ch == '\n') { rows++; col = 0; } else if (ch != '\r' && ++col == TCOLS) { rows++; col = 0; } if (rows >= PAGE) { if (!waitkey()) break; rows = 0; } } if (fd != NOFD) close(fd); }