|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T p ┃
Length: 5903 (0x170f) Types: TextFile Names: »pager.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/news/misc/undig/pager.c«
#include "undig.h" #include <sgtty.h> #include <signal.h> /* Screen dimensions. */ int lines= 24; int cols= 80; /* Pager parameters */ bool pageclear= NO; bool messclear= NO; int pagesize= 23; /* Normal paging amount */ int halfsize= 11; /* Half paging amount */ int startsize= 7; /* Paging amount for message start */ int left= 23; /* Number of lines left on current page. */ bool needclear= NO; /* Should clear screen before next output line. */ char clearhomestr[100]; /* How to clear the screen */ /* Read screen size and clear/home sequence from termcap and ioctl. */ bool preset() { char tcbuf[1024]; char *term= getenv("TERM"); char *cp; int i; if (term == NULL || term[0] == EOS) return NO; if (tgetent(tcbuf, term) != 1) return NO; cp= clearhomestr; (void) tgetstr("cl", &cp); i= tgetnum("li"); if (i > 0) lines= i; i= tgetnum("co"); if (i > 0) cols= i; #ifdef TIOCGWINSZ { struct winsize w; if (ioctl(fileno(stdout), TIOCGWINSZ, &w) == 0) { if (w.ws_row > 0) lines= w.ws_row; if (w.ws_col > 0) cols= w.ws_col; } } #endif pagesize= lines-1; if (pagesize < 1) pagesize= 1; halfsize= pagesize/2; if (halfsize < 1) halfsize= 1; startsize= pagesize/3; if (startsize < 7) startsize= halfsize; return YES; } /* TTY and signal handling. */ struct sgttyb ttyold, ttynew; bool cbreak= NO; handler(sig) int sig; { ttyreset(); signal(sig, SIG_DFL); /* So the kill takes effect immediately */ kill(getpid(), sig); /* Pretend we died of the signal after all */ exit(1); /* If the kill doesn't work */ } ttyset() { if (cbreak) return; signal(SIGINT, handler); signal(SIGTERM, handler); signal(SIGPIPE, handler); gtty(fileno(stdin), &ttyold); ttynew= ttyold; ttynew.sg_flags &= ~ECHO; ttynew.sg_flags |= CBREAK; cbreak= YES; stty(fileno(stdin), &ttynew); } ttyreset() { if (cbreak) stty(fileno(stdin), &ttyold); cbreak= NO; } clearhome() { fputs(clearhomestr, stdout); needclear= NO; } /* Input a line, echoing characters. Return YES if ok, NO if backspaced beyond begin of line. */ bool ttygets(line, len) char *line; int len; { int i= 0; bool ok= YES; int c; for (;;) { c= getc(stdin); switch (c) { case '\r': case '\n': case EOF: putchar('\n'); line[i]= EOS; break; default: if (c == ttynew.sg_erase) { if (--i < 0) { ok= NO; break; } printf("\b \b"); } else if (c == ttynew.sg_kill) { putchar('\n'); i= 0; } else if (i < len-1) { putchar(c); line[i++]= c; } else putchar(CTL('G')); continue; } break; } return ok; } /* Output a line, filtered through the pager. Return YES if output OK, NO if pager wants to stop. */ bool pageline(p) struct line *p; { int need; need= needlines(p); if (left < need) { if (!pagecmd()) return NO; } if (needclear) clearhome(); left -= need; putline(p, stdout); if (p->text != NULL && index(p->text, '\014') != NULL) left= 0; /* Force pager prompt after ^L in a line. */ return YES; } /* Output a text line to a file. */ putline(p, fp) struct line *p; FILE *fp; { int i; for (i= p->indent % cols; i >= TABSTOP; i -= TABSTOP) putc('\t', fp); while (--i >= 0) putc(' ', fp); if (p->text != NULL) fputs(p->text, fp); putc('\n', fp); } /* Count the number of screen lines needed for a struct line. */ int needlines(p) struct line *p; { char *cp; int i; if (p == NULL) return 0; i= p->indent % cols; cp= p->text; if (cp != NULL) { for (; *cp != NULL; ++cp) { if (*cp == '\t') i= (i/TABSTOP + 1)*TABSTOP; else if (*cp == '\b') { if (i > 0) --i; } else ++i; } } return i/cols + 1; } /* Pager command input. Returns YES if ok to output next line. */ int lastcmd= ' '; /* Passes char typed by user to higher levels. */ char cmdarg[256]; /* Parameter for cmds like 'w', '!' */ bool pagecmd() { bool ok= YES; ttyset(); for (;;) { printf("\r:"); lastcmd= getc(stdin); switch (lastcmd) { case '/': case '?': case 's': case 'w': case '|': case '!': putchar(lastcmd); if (!ttygets(cmdarg, sizeof cmdarg)) { printf("\b \b"); continue; } if (lastcmd == '!') { shell(cmdarg); continue; } /* Fall through (twice!) */ case 'r': case 'R': case 'f': case 'F': case EOF: case 'q': case 'n': case 'N': case CTL('N'): case CTL('R'): case CTL('L'): case 'v': case 'p': case 'P': case CTL('P'): case '-': case 'b': case CTL('B'): case '^': ok= NO; /* Fall through */ case ' ': left= pagesize; if (pageclear) needclear= YES; break; case '\n': case '\r': left= 1; break; case 'd': case CTL('D'): left= halfsize; break; case 'h': help(); continue; default: putchar(CTL('G')); continue; } break; } printf("\r \r"); fflush(stdout); return ok; } help() { printf("\r...help for Undigestify...\n"); printf("Paging commands:\n"); printf("h\thelp\n"); printf("SP\tdisplay next page\n"); printf("d\tdisplay next half page\n"); printf("CR\tdisplay next line\n"); printf("!\tshell escape\n"); printf("Message commands:\n"); printf("n\tdisplay next unseen message\n"); printf("N\tdisplay next message\n"); printf("p\tdisplay previous message\n"); printf("^R\tredisplay current message\n"); printf("-\ttoggle between current and previously displayed message\n"); printf("^\tdisplay first message\n"); printf("/,?\tsearch forward, backward for string\n"); printf("s,w,|\tsave, write to file, pipe to command\n"); printf("r\treply by mail to current message\n"); printf("q\tquit\n"); printf("...end help...\n"); } /* Shell escape. */ shell(command) char *command; { ttyreset(); system(command); ttyset(); } /* Exit from the program. */ bye(status) int status; { ttyreset(); exit(status); /*NOTREACHED*/ }