DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T p

⟦2d83412b9⟧ TextFile

    Length: 5903 (0x170f)
    Types: TextFile
    Names: »pager.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/news/misc/undig/pager.c« 

TextFile

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