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 }