|
|
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 - metrics - 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*/
}