pc-hack

PC HACK 3.61 source code (archival)
git clone http://frotz.net/git/pc-hack.git
Log | Files | Refs

pager.c (6175B)


      1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
      2 /* pager.c - version 1.0.3 */
      3 
      4 /* This file contains the command routine dowhatis() and a pager. */
      5 
      6 #include <stdio.h>
      7 #include "hack.h"
      8 extern int CO, LI;	/* usually COLNO and ROWNO+2 */
      9 extern char *CD;
     10 extern char quitchars[];
     11 extern char *getenv(), *getlogin();
     12 int done1();
     13 
     14 dowhatis()
     15 {
     16 	FILE *fp;
     17 	char bufr[BUFSZ+6];
     18 	register char *buf = &bufr[6], *ep, q;
     19 	extern char readchar();
     20 
     21 	if(!(fp = fopen("data","r")))
     22 		pline("Cannot open data file!");
     23 	else {
     24 		pline("Specify what? ");
     25 		q = readchar();
     26 #ifdef DGK
     27 		if (index(quitchars, q))
     28 			return(0);
     29 #endif
     30 		if(q != '\t')
     31 		while(fgets(buf,BUFSZ,fp))
     32 		    if(*buf == q) {
     33 			ep = index(buf, '\n');
     34 			if(ep) *ep = 0;
     35 			/* else: bad data file */
     36 			/* Expand tab 'by hand' */
     37 			if(buf[1] == '\t'){
     38 				buf = bufr;
     39 				buf[0] = q;
     40 				(void) strncpy(buf+1, "       ", 7);
     41 			}
     42 			pline(buf);
     43 			if(ep[-1] == ';') {
     44 				pline("More info? ");
     45 				if(readchar() == 'y') {
     46 					page_more(fp,1); /* does fclose() */
     47 					return(0);
     48 				}
     49 			}
     50 			(void) fclose(fp); 	/* kopper@psuvax1 */
     51 			return(0);
     52 		    }
     53 		pline("I've never heard of such things.");
     54 		(void) fclose(fp);
     55 	}
     56 	return(0);
     57 }
     58 
     59 /* simple pager, also used from dohelp() */
     60 page_more(fp,strip)
     61 FILE *fp;
     62 int strip;	/* nr of chars to be stripped from each line (0 or 1) */
     63 {
     64 	register char *bufr, *ep;
     65 #ifdef DGK
     66 	/* There seems to be a bug in ANSI.SYS  The first tab character
     67 	 * after a clear screen sequence is not expanded correctly.  Thus
     68 	 * expand the tabs by hand -dgk
     69 	 */
     70 	int tabstop = 8, spaces;
     71 	char buf[BUFSIZ], *bufp, *bufrp;
     72 
     73 	set_pager(0);
     74 	bufr = (char *) alloc((unsigned) CO);
     75 	while (fgets(buf, BUFSIZ, fp) && (!strip || *buf == '\t')){
     76 		bufp = buf;
     77 		bufrp = bufr;
     78 		while (*bufp && *bufp != '\n') {
     79 			if (*bufp == '\t') {
     80 				spaces = tabstop - (bufrp - bufr) % tabstop;
     81 				while (spaces--)
     82 					*bufrp++ = ' ';
     83 				bufp++;
     84 			} else
     85 				*bufrp++ = *bufp++;
     86 		}
     87 		*bufrp = '\0';
     88 #else
     89 	set_pager(0);
     90 	bufr = (char *) alloc((unsigned) CO);
     91 	bufr[CO-1] = 0;
     92 	while(fgets(bufr,CO-1,fp) && (!strip || *bufr == '\t')){
     93 		ep = index(bufr, '\n');
     94 		if(ep)
     95 			*ep = 0;
     96 #endif /* DGK /**/
     97 		if(page_line(bufr+strip)) {
     98 			set_pager(2);
     99 			goto ret;
    100 		}
    101 	}
    102 	set_pager(1);
    103 ret:
    104 	free(bufr);
    105 	(void) fclose(fp);
    106 }
    107 
    108 static boolean whole_screen = TRUE;
    109 #define	PAGMIN	12	/* minimum # of lines for page below level map */
    110 
    111 set_whole_screen() {	/* called in termcap as soon as LI is known */
    112 	whole_screen = (LI-ROWNO-2 <= PAGMIN || !CD);
    113 }
    114 
    115 set_pager(mode)
    116 register int mode;	/* 0: open  1: wait+close  2: close */
    117 {
    118 	static boolean so;
    119 	if(mode == 0) {
    120 		if(!whole_screen) {
    121 			/* clear topline */
    122 			clrlin();
    123 			/* use part of screen below level map */
    124 			curs(1, ROWNO+4);
    125 		} else {
    126 			cls();
    127 		}
    128 		so = flags.standout;
    129 		flags.standout = 1;
    130 	} else {
    131 		if(mode == 1) {
    132 			curs(1, LI);
    133 			more();
    134 		}
    135 		flags.standout = so;
    136 		if(whole_screen)
    137 			docrt();
    138 		else {
    139 			curs(1, ROWNO+4);
    140 			cl_eos();
    141 		}
    142 	}
    143 }
    144 
    145 page_line(s)		/* returns 1 if we should quit */
    146 register char *s;
    147 {
    148 	extern char morc;
    149 
    150 	if(cury == LI-1) {
    151 		if(!*s)
    152 			return(0);	/* suppress blank lines at top */
    153 		putchar('\n');
    154 		cury++;
    155 		cmore("q\033");
    156 		if(morc) {
    157 			morc = 0;
    158 			return(1);
    159 		}
    160 		if(whole_screen)
    161 			cls();
    162 		else {
    163 			curs(1, ROWNO+4);
    164 			cl_eos();
    165 		}
    166 	}
    167 	puts(s);
    168 	cury++;
    169 	return(0);
    170 }
    171 
    172 /*
    173  * Flexible pager: feed it with a number of lines and it will decide
    174  * whether these should be fed to the pager above, or displayed in a
    175  * corner.
    176  * Call:
    177  *	cornline(0, title or 0)	: initialize
    178  *	cornline(1, text)	: add text to the chain of texts
    179  *	cornline(2, morcs)	: output everything and cleanup
    180  *	cornline(3, 0)		: cleanup
    181  */
    182 
    183 cornline(mode, text)
    184 int mode;
    185 char *text;
    186 {
    187 	static struct line {
    188 		struct line *next_line;
    189 		char *line_text;
    190 	} *texthead, *texttail;
    191 	static int maxlen;
    192 	static int linect;
    193 	register struct line *tl;
    194 
    195 	if(mode == 0) {
    196 		texthead = 0;
    197 		maxlen = 0;
    198 		linect = 0;
    199 		if(text) {
    200 			cornline(1, text);	/* title */
    201 			cornline(1, "");	/* blank line */
    202 		}
    203 		return;
    204 	}
    205 
    206 	if(mode == 1) {
    207 	    register int len;
    208 
    209 	    if(!text) return;	/* superfluous, just to be sure */
    210 	    linect++;
    211 	    len = strlen(text);
    212 	    if(len > maxlen)
    213 		maxlen = len;
    214 	    tl = (struct line *)
    215 		alloc((unsigned)(len + sizeof(struct line) + 1));
    216 	    tl->next_line = 0;
    217 	    tl->line_text = (char *)(tl + 1);
    218 	    (void) strcpy(tl->line_text, text);
    219 	    if(!texthead)
    220 		texthead = tl;
    221 	    else
    222 		texttail->next_line = tl;
    223 	    texttail = tl;
    224 	    return;
    225 	}
    226 
    227 	/* --- now we really do it --- */
    228 	if(mode == 2 && linect == 1)			    /* topline only */
    229 		pline(texthead->line_text);
    230 	else
    231 	if(mode == 2) {
    232 	    register int curline, lth;
    233 
    234 	    if(flags.toplin == 1) more();	/* ab@unido */
    235 	    remember_topl();
    236 
    237 	    lth = CO - maxlen - 2;		   /* Use full screen width */
    238 	    if (linect < LI && lth >= 10) {		     /* in a corner */
    239 		home ();
    240 		cl_end ();
    241 		flags.toplin = 0;
    242 		curline = 1;
    243 		for (tl = texthead; tl; tl = tl->next_line) {
    244 		    curs (lth, curline);
    245 		    if(curline > 1)
    246 			cl_end ();
    247 		    putsym(' ');
    248 		    putstr (tl->line_text);
    249 		    curline++;
    250 		}
    251 		curs (lth, curline);
    252 		cl_end ();
    253 		cmore (text);
    254 		home ();
    255 		cl_end ();
    256 		docorner (lth, curline-1);
    257 	    } else {					/* feed to pager */
    258 		set_pager(0);
    259 		for (tl = texthead; tl; tl = tl->next_line) {
    260 		    if (page_line (tl->line_text)) {
    261 			set_pager(2);
    262 			goto cleanup;
    263 		    }
    264 		}
    265 		if(text) {
    266 			cgetret(text);
    267 			set_pager(2);
    268 		} else
    269 			set_pager(1);
    270 	    }
    271 	}
    272 
    273 cleanup:
    274 	while(tl = texthead) {
    275 		texthead = tl->next_line;
    276 		free((char *) tl);
    277 	}
    278 }
    279 
    280 dohelp()
    281 {
    282 	char c;
    283 
    284 	pline ("Long or short help? ");
    285 	while (((c = readchar ()) != 'l') && (c != 's') && !index(quitchars,c))
    286 		bell ();
    287 	if (!index(quitchars, c))
    288 		(void) page_file((c == 'l') ? HELP : SHELP, FALSE);
    289 	return(0);
    290 }
    291 
    292 page_file(fnam, silent)	/* return: 0 - cannot open fnam; 1 - otherwise */
    293 register char *fnam;
    294 boolean silent;
    295 {
    296 	FILE *f;			/* free after Robert Viduya */
    297 
    298 	if ((f = fopen (fnam, "r")) == (FILE *) 0) {
    299 		if(!silent)
    300 			pline ("Cannot open %s.", fnam);
    301 		return(0);
    302 	}
    303 	page_more(f, 0);
    304 	return(1);
    305 }