geoff@utcsstat.UUCP (Geoff Collyer) (08/14/84)
This article is a follow-on to my article in January which contained a kernel tty pager for v7. This is the long-awaited 4.2 version. The utcs (4.2bsd) kernel has a *simple* paginator in the kernel tty driver, originally written by Ron Gomes (sftig!rrg). This paginator is selectable by ioctl and the screen length is settable. It consists of a very small set of kernel changes and adds two new ioctl codes (one to get and one to set the paging parameters). This paginator makes *very* few decisions of its own and will be extended slightly to make fewer decisions by making more of its behavior selectable. To forestall flames, I will mail a /vmunix to any one who mails me a flame. I am not willing to debate this topic; the pager works, works well and I will never go back to using more(1). To those who are working on a terminal driver standard, I strongly recommend that a paginator similar to this one be included in any proposed standard. With the kind permission of Ron Gomes and as a public service I offer here the changes needed to add a simple kernel paginator to the 4.2bsd terminal driver. This code contains no Bell nor AT&T code and is hereby declared public domain. ---only code and documentation follow this line--- Here are the diffs to tty.4: ----- 124c124 < Output processing is done. --- > Output processing is done, except for paging. 619c619 < all processing is done except the input editing: --- > all processing is done except the input editing and paging: This is a new section: 743a744,781 > .Ul "Paging" > .PP > The terminal interface can be put into a ``paging mode'' > in which output will halt when a full ``page'' > has been displayed; > output resumes when any character, > other than the start and stop characters, > is typed. > Usually this will be a newline, which is absorbed; > any other character will also restart output but in addition > it will be transmitted to the program reading from the terminal. > The structure referenced in the \fIioctl\fR call is defined in > .I <sgtty.h> > as follows: > .PP > .nf > .ft 3 > struct tpage { > unsigned short t_pagsiz; /* Page size for automatic paging */ > char t_pgparm[4]; /* Reserved for future bells and whistles */ > }; > .fi > .ft R > .PP > The > .I t_pagsiz > value is the number of lines which will be printed before output > stops to wait for a character to be typed; > if this is zero the paging feature is turned off. > The calls are: > .TP > TIOCSPAG > Set the paging parameters for the terminal according to the > pointed-to structure. > .TP > TIOCGPAG > Fetch the paging parameters and store them in the pointed-to structure. > .LP 830a869,870 > .SH HISTORY > The paging feature was implemented at BNR by Ron Gomes. This goes in the BUGS section: 832a873,876 > .PP > The paging feature should really take account of a terminal's > line length, to allow for extra newlines caused by wraparound > on over-long lines. ----- Here are the /sys/h/tty.h diffs: --- Add these struct members to the end of struct tty: 80a81,84 > struct tpage tpg; /* Paging parameters */ > /* unsigned short t_xstate; /* Extra state bits */ > #define t_xstate t_state /* save space */ > unsigned short t_plc; /* Line count for paging */ 122a127,128 > /* extra internal state bits (encoded in t_xstate) */ > #define TS_PAGEFULL 0x80000000 /* screen full, wait 'til something is typed */ --- Here are the /sys/h/ttychars.h diffs: --- 25a26,30 > struct tpage { > unsigned short t_pagsiz; /* Page size for automatic paging */ > char t_pgparm[4]; /* Reserved for future bells and whistles */ > }; > --- Here are the diffs for /sys/h/ioctl.h: --- 127a128,129 > #define TIOCSPAG _IOW(t, 64, struct tpage) > #define TIOCGPAG _IOR(t, 65, struct tpage) --- Here are the /sys/sys/tty.c diffs: --- Add these cases to the giant ioctl switch in ttioctl(): 475a476,484 > case TIOCGPAG: > bcopy((caddr_t)&tp->tpg, data, sizeof (struct tpage)); > break; > > case TIOCSPAG: > bcopy(data, (caddr_t)&tp->tpg, sizeof (struct tpage)); > break; > > Add this at the end of ttyclose(): 571a581,583 > tp->t_xstate = 0; > tp->tpg.t_pagsiz = 0; > tp->t_plc = 0; Add this to ttyoutput(), after if (c == tp->t_startc) goto restartoutput; 701a714,721 > tp->t_plc = 0; > if (tp->t_xstate&TS_PAGEFULL) { > tp->t_xstate &= ~TS_PAGEFULL; > wakeup((caddr_t)&tp->t_plc); > if (c == '\n' || (c == '\r' && t_flags&CRMOD)) > return; > } > Add this after ``If we're mapping lower case or kludging tildes,'': 1228a1249 > * or paging output, 1232c1253,1254 < if (tp->t_flags & (LCASE|TILDE)) { --- > if (tp->tpg.t_pagsiz > 0 && (tp->t_flags&(RAW|CBREAK)) == 0 || > tp->t_flags & (LCASE|TILDE)) { 1236c1258,1260 < while ((c = ttyoutput(c, tp)) >= 0) { --- > for (ttstoppg(tp, c); > (c = ttyoutput(c, tp)) >= 0; > ttstoppg(tp, c)) { This is an unrelated bug fix; add it after ``if (tp->t_state&TS_NBIO) {'': 1324a1349 > splx(s); 1332a1358,1384 > } > > /* > * If screen is full, sleep until something is typed. > * If paging is on and c is the last newline on a screen, > * write a return, mark the terminal as screen-full, > * sleep until something is typed. > */ > static > ttstoppg(tp, c) > register struct tty *tp; > register int c; > { > register int s; > > while (tp->t_xstate & TS_PAGEFULL) > sleep((caddr_t)&tp->t_plc, TTOPRI); > s = spl5(); > if (tp->tpg.t_pagsiz > 0 && (tp->t_flags&(RAW|CBREAK)) == 0 && > c == '\n' && ++(tp->t_plc) >= tp->tpg.t_pagsiz) { > ttyoutput('\r', tp); /* distinctive pause */ > ttstart(tp); > tp->t_xstate |= TS_PAGEFULL; > while (tp->t_xstate & TS_PAGEFULL) > sleep((caddr_t)&tp->t_plc, TTOPRI); > } > splx(s); --- Here are the changes to stty.1: ----- These paragraphs should be added after the description of brk: --- .br .ns .TP .BI page \ n turn on paging mode and set the page size to .I n (a number). (In paging mode output at the terminal is frozen when .I n lines have been printed without anything having been typed at the keyboard; output is started again when a new-line is typed.) If .I n is omitted a page size of 22 is assumed; setting the page size to 0 turns paging mode off. .br .ns .TP .B -page same as `page 0'. .br --- Add this section: --- .SH HISTORY Modified by Ron Gomes to turn paging mode (a local addition) on and off. ----- Here are the diffs for stty.c: --- 8a6 > #include <ctype.h> 129a128 > struct tpage tpg; Add this after the first TIOCGETP ioctl: 168a168 > ioctl(1, TIOCGPAG, &tpg); Add this after if (eq("gspeed")): 258a259,268 > if (eq("page")) > if (argv[1] && isascii(argv[1][0]) && > isdigit(argv[1][0])) { > tpg.t_pagsiz = atoi(*++argv); > argc--; > } > else > tpg.t_pagsiz = 22; > if (eq("-page")) > tpg.t_pagsiz = 0; Add this after the TIOCSETN ioctl: 291a302 > ioctl(1, TIOCSPAG, &tpg); Add this after the fprintf containing ``all==2'': 330a342,343 > if(tpg.t_pagsiz) > fprintf(stderr, "page = %d; ", tpg.t_pagsiz); --- Geoff Collyer, U. of Toronto