This is pager.c in view mode; [Download] [Up]
/* SCCS Id: @(#)pager.c 3.0 89/11/19 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ /* This file contains the command routine dowhatis() and a pager. */ /* Also readmail() and doshell(), and generally the things that contact the outside world. */ #define MONATTK_H /* comment line for pre-compiled headers */ /* block some unused #defines to avoid overloading some cpp's */ #include "hack.h" #include <ctype.h> #ifndef NO_SIGNAL #include <signal.h> #endif #if defined(BSD) || defined(ULTRIX) #include <sys/wait.h> #endif #ifdef MACOS extern WindowPtr HackWindow; extern short macflags; #endif #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef OVLB OSTATIC char hc; #else /* OVLB */ XSTATIC char hc = 0; #endif /* OVLB */ static void FDECL(page_more, (FILE *,int)); OSTATIC boolean FDECL(clear_help, (CHAR_P)); OSTATIC boolean FDECL(valid_help, (CHAR_P)); static boolean FDECL(pmatch,(const char *,const char *)); static boolean FDECL(outspec,(const char *,int)); static const char *FDECL(lookat,(int,int,UCHAR_P)); #ifdef WIZARD static void NDECL(wiz_help); #endif static void NDECL(help_menu); #ifdef OVLB /* * simple pattern matcher: '*' matches 0 or more characters * returns TRUE if strng matches patrn */ static boolean pmatch(patrn, strng) const char *patrn, *strng; { char s, p; s = *strng; p = *patrn; if (!p) { return (s == 0); } if (p == '*') { if (!patrn[1] || pmatch(patrn+1, strng)) { return TRUE; } return (s ? pmatch(patrn, strng+1) : FALSE); } return (p == s) ? pmatch(patrn+1, strng+1) : FALSE; } /* * print out another possibility for dowhatis. "new" is the possible new * string; "out_flag" indicates whether we really want output, and if * so what kind of output: 0 == no output, 1 == "(or %s)" output. * Returns TRUE if this new string wasn't the last string printed. */ static boolean outspec(new, out_flag) const char *new; int out_flag; { static char old[50]; if (!strcmp(old, new)) return FALSE; /* don't print the same thing twice */ if (out_flag) pline("(or %s)", an(new)); Strcpy(old, new); return 1; } /* * return the name of the character ch found at (x,y) */ static const char * lookat(x, y, ch) int x,y; uchar ch; { register struct monst *mtmp; register struct obj *otmp; struct trap *trap; static char answer[50]; register char *s, *t; uchar typ; answer[0] = 0; if(MON_AT(x,y)) { mtmp = m_at(x,y); if (!showmon(mtmp) || Hallucination) mtmp = (struct monst *)0; } else mtmp = (struct monst *) 0; typ = levl[x][y].typ; if (!Invisible #ifdef POLYSELF && !u.uundetected #endif && u.ux==x && u.uy==y) { Sprintf(answer, "%s named %s", #ifdef POLYSELF u.mtimedone ? mons[u.umonnum].mname : #endif pl_character, plname); } else if (mtmp && !mtmp->mimic) Sprintf(answer, "%s%s", mtmp->mtame ? "tame " : mtmp->mpeaceful ? "peaceful " : "", strncmp(lmonnam(mtmp), "the ", 4) ? lmonnam(mtmp) : lmonnam(mtmp)+4); else if (!levl[x][y].seen) Strcpy(answer,"dark part of a room"); else if (mtmp && mtmp->mimic) { if (mtmp->m_ap_type == M_AP_FURNITURE) { if (mtmp->mappearance == S_altar) Strcpy(answer, "neutral altar"); else Strcpy(answer, explainsyms[mtmp->mappearance]); } else if (mtmp->m_ap_type == M_AP_OBJECT) { if (mtmp->mappearance == STRANGE_OBJECT) Strcpy(answer, "strange object"); else { otmp = mksobj((int) mtmp->mappearance,FALSE ); Strcpy(answer, distant_name(otmp, xname)); free((genericptr_t) otmp); } } else if (mtmp->m_ap_type == M_AP_GOLD) Strcpy(answer, "pile of gold"); } else if (OBJ_AT(x, y)) { otmp = level.objects[x][y]; Strcpy(answer, distant_name(otmp, xname)); } else if (ch == GOLD_SYM) { Strcpy(answer, "pile of gold"); } #ifdef ALTARS else if (ch == ALTAR_SYM && IS_ALTAR(typ)) { int kind = levl[x][y].altarmask & ~A_SHRINE; Sprintf( answer, "%s altar", (kind == A_CHAOS) ? "chaotic" : (kind == A_NEUTRAL) ? "neutral" : "lawful" ); } #endif #ifdef STRONGHOLD else if ((ch == DB_VWALL_SYM || ch == DB_HWALL_SYM) && is_db_wall(x,y)) Strcpy(answer,"raised drawbridge"); #endif #ifdef THRONES else if ((ch == THRONE_SYM) && IS_THRONE(typ)) Strcpy(answer, "throne"); #endif else if ( (ch==H_OPEN_DOOR_SYM || ch==V_OPEN_DOOR_SYM || ch==CLOSED_DOOR_SYM || ch==NO_DOOR_SYM) && IS_DOOR(typ) ) { switch(levl[x][y].doormask & ~D_TRAPPED) { case D_NODOOR: Strcpy(answer,"doorway"); break; case D_BROKEN: Strcpy(answer,"broken door"); break; case D_ISOPEN: Strcpy(answer,"open door"); break; default: Strcpy(answer,"closed door"); break; /* locked or not */ } } #ifdef SINKS else if (ch == SINK_SYM && IS_SINK(levl[x][y].typ)) Strcpy(answer,"sink"); #endif else if ((ch == TRAP_SYM || ch == WEB_SYM) && (trap = t_at(x, y))) { if (trap->ttyp == WEB && ch == WEB_SYM) Strcpy(answer, "web"); else if (trap->ttyp != MONST_TRAP && ch == TRAP_SYM) { Strcpy(answer, traps[ Hallucination ? rn2(TRAPNUM-3)+3 : trap->ttyp]); /* strip leading garbage */ for (s = answer; *s && *s != ' '; s++) ; if (*s) ++s; for (t = answer; *t++ = *s++; ) ; } } else if (ch == UP_SYM && x == xupstair && y == yupstair) Strcpy(answer, "staircase up"); else if (ch == DN_SYM && x == xdnstair && y == ydnstair) Strcpy(answer, "staircase down"); #ifdef STRONGHOLD else if (ch == UPLADDER_SYM && x && x == xupladder && y == ydnladder) Strcpy(answer, "ladder up"); else if (ch == DNLADDER_SYM && x && x == xdnladder && y == ydnladder) Strcpy(answer, "ladder down"); #endif else if (IS_ROOM(typ)) { if (ch == ROOM_SYM) { if (levl[x][y].icedpool) Strcpy(answer,"iced pool"); else Strcpy(answer,"floor of a room"); } else if (ch == STONE_SYM || ch == ' ') Strcpy(answer,"dark part of a room"); } else if (ch == CORR_SYM && SPACE_POS(typ)) Strcpy(answer,"corridor"); else if (!ACCESSIBLE(typ)) { if (ch == STONE_SYM || ch == ' ') Strcpy(answer,"dark part of a room"); else Strcpy(answer,"wall"); } return answer; } int dowhatis() { FILE *fp; char buf[BUFSZ], inpbuf[BUFSZ]; register char *ep, *inp = inpbuf; char *alt = 0; /* alternate description */ #ifdef __GNULINT__ const char *firstmatch = 0; #else const char *firstmatch; #endif uchar q; register int i; coord cc; boolean oldverb = flags.verbose; boolean found_in_file = FALSE, need_to_print = FALSE; int found = 0; #ifdef OS2_CODEVIEW char tmp[PATHLEN]; Strcpy(tmp,hackdir); append_slash(tmp); Strcat(tmp,DATAFILE); fp = fopen(tmp,"r")); #else fp = fopen(DATAFILE, "r"); #endif if(!fp) { #ifdef MACOS fp = openFile(DATAFILE, "r"); } if (!fp) { #endif pline("Cannot open data file!"); return 0; } pline ("Specify unknown object by cursor? "); q = ynq(); if (q == 'q') { (void) fclose(fp); return 0; } else if (q == 'n') { cc.x = cc.y = -1; pline("Specify what? (type the word) "); getlin(inp); if (inp[0] == '\033' || !inp[0]) { (void)fclose(fp); return 0; } if (!inp[1]) q = inp[0]; else q = 0; } else { cc.x = u.ux; cc.y = u.uy; selobj: need_to_print = found_in_file = FALSE; found = 0; inp = inpbuf; alt = 0; (void) outspec("", 0); /* reset output */ if(flags.verbose) pline("Please move the cursor to an unknown object."); else pline("Pick an object."); getpos(&cc, FALSE, "an unknown object"); if (cc.x < 0) { (void) fclose(fp); /* sweet@scubed */ flags.verbose = oldverb; return 0; } flags.verbose = FALSE; q = levl[cc.x][cc.y].scrsym; if (!q || (!levl[cc.x][cc.y].seen && !MON_AT(cc.x,cc.y))) q = ' '; } if (!q) goto checkfile; /* user typed in a complete string */ if (q != ' ' && index(quitchars, (char)q)) { (void) fclose(fp); /* sweet@scubed */ flags.verbose = oldverb; return 0; } /* * if the user just typed one letter, or we're identifying from the * screen, then we have to check all the possibilities and print them * out for him/her */ /* Check for monsters */ for (i = 0; monsyms[i]; i++) { if (q == monsyms[i]) { need_to_print = TRUE; pline("%c %s",q,an(monexplain[i])); (void) outspec(firstmatch = monexplain[i], 0); found++; break; } } /* Now check for objects */ for (i = 0; objsyms[i]; i++) { if (q == objsyms[i]) { need_to_print = TRUE; if (!found) { pline("%c %s",q,an(objexplain[i])); (void)outspec(firstmatch = objexplain[i], 0); found++; } else if (outspec(objexplain[i], 1)) found++; } } /* Now check for graphics symbols */ for (i = 0; i < MAXPCHARS; i++) { if ( q == showsyms[i] && (*explainsyms[i])) { if (!found) { pline("%c %s",q,an(explainsyms[i])); (void)outspec(firstmatch = explainsyms[i], 0); found++; } else if (outspec(explainsyms[i], 1)) found++; if (i == S_altar || i == S_trap || i == S_web) need_to_print = TRUE; } } if (!found) pline("I've never heard of such things."); else if (cc.x != -1) { /* a specific object on screen */ if (found > 1 || need_to_print) { Strcpy(inp, lookat(cc.x, cc.y, q)); if (*inp) pline("(%s)", inp); } else { Strcpy(inp, firstmatch); } } else if (found == 1) { Strcpy(inp, firstmatch); } else found = FALSE; /* abort the 'More info?' stuff */ /* check the data file for information about this thing */ checkfile: if (!strncmp(inp, "a ", 2)) inp += 2; else if (!strncmp(inp, "an ", 3)) inp += 3; else if (!strncmp(inp, "the ", 4)) inp += 4; if (!strncmp(inp, "tame ", 5)) inp += 5; else if (!strncmp(inp, "peaceful ", 9)) inp += 9; if (!strncmp(inp, "invisible ", 10)) inp += 10; if ((!q || found) && *inp) { /* adjust the input to remove "named " and convert to lower case */ for (ep = inp; *ep; ) { if ((!strncmp(ep, " named ", 7) && (alt = ep + 7)) || !strncmp(ep, " called ", 8)) *ep = 0; else (*ep = tolower(*ep)), ep++; } /* * If the object is named, then the name is the alternate search string; * otherwise, the result of makesingular() applied to the name is. This * isn't strictly optimal, but named objects of interest to the user should * will usually be found under their name, rather than under their * object type, so looking for a singular form is pointless. */ if (!alt) alt = makesingular(inp); else for (ep = alt; *ep; ep++) *ep = tolower(*ep); while(fgets(buf,BUFSZ,fp)) { if(*buf != '\t') { ep = index(buf, '\n'); if(ep) *ep = 0; else impossible("bad data file"); if (pmatch(buf, inp)||(alt && pmatch(buf, alt))) { found_in_file = TRUE; break; } } } } if(found_in_file) { /* skip over other possible matches for the info */ for(;;) { if ( (i = getc(fp)) == '\t' ) { (void) ungetc(i, fp); break; } if (!fgets(buf, BUFSZ, fp)) { break; } } if (q) { pline("More info? "); if(yn() == 'y') { page_more(fp,1); /* does fclose() */ flags.verbose = oldverb; return 0; } } else { page_more(fp, 1); flags.verbose = oldverb; return 0; } } else if (!q) pline("I don't have any information on those things."); /* if specified by cursor, keep going */ if(cc.x != -1) { more(); rewind(fp); goto selobj; } (void) fclose(fp); /* kopper@psuvax1 */ flags.verbose = oldverb; return 0; } int dowhatdoes() { FILE *fp; char bufr[BUFSZ+6]; register char *buf = &bufr[6], *ep, q, ctrl, meta; #ifdef OS2_CODEVIEW char tmp[PATHLEN]; Strcpy(tmp,hackdir); append_slash(tmp); Strcat(tmp,CMDHELPFILE); if(!(fp = fopen(tmp,"r"))) { #else # ifdef MACOS if(!(fp = fopen(CMDHELPFILE, "r"))) fp = openFile(CMDHELPFILE, "r"); if (!fp) { # else if(!(fp = fopen(CMDHELPFILE, "r"))) { # endif #endif pline("Cannot open data file!"); return 0; } pline("What command? "); #if defined(UNIX) || defined(VMS) introff(); #endif q = readchar(); #if defined(UNIX) || defined(VMS) intron(); #endif ctrl = ((q <= '\033') ? (q - 1 + 'A') : 0); meta = ((0x80 & q) ? (0x7f & q) : 0); while(fgets(buf,BUFSZ,fp)) if ((ctrl && *buf=='^' && *(buf+1)==ctrl) || (meta && *buf=='M' && *(buf+1)=='-' && *(buf+2)==meta) || *buf==q) { ep = index(buf, '\n'); if(ep) *ep = 0; if (ctrl && buf[2] == '\t'){ buf = bufr + 1; (void) strncpy(buf, "^? ", 8); buf[1] = ctrl; } else if (meta && buf[3] == '\t'){ buf = bufr + 2; (void) strncpy(buf, "M-? ", 8); buf[2] = meta; } else if(buf[1] == '\t'){ buf = bufr; buf[0] = q; (void) strncpy(buf+1, " ", 7); } pline("%s", buf); (void) fclose(fp); return 0; } pline("I've never heard of such commands."); (void) fclose(fp); return 0; } /* make the paging of a file interruptible */ static int got_intrup; #if !defined(MSDOS) && !defined(TOS) && !defined(MACOS) static int intruph(){ (void) signal(SIGINT, (SIG_RET_TYPE) intruph); got_intrup++; return 0; } #endif /* simple pager, also used from dohelp() */ static void page_more(fp,strip) FILE *fp; int strip; /* nr of chars to be stripped from each line (0 or 1) */ { register char *bufr; #if !defined(MSDOS) && !defined(MINIMAL_TERM) register char *ep; #endif #if !defined(MSDOS) && !defined(TOS) && !defined(MACOS) int (*prevsig)() = (int (*)())signal(SIGINT, (SIG_RET_TYPE) intruph); #endif #ifdef MACOS short tmpflags; tmpflags = macflags; macflags &= ~fDoUpdate; if(!mac_more(fp, strip)) { macflags |= (tmpflags & fDoUpdate); return; } macflags |= (tmpflags & fDoUpdate); #else #if defined(MSDOS) || defined(MINIMAL_TERM) /* There seems to be a bug in ANSI.SYS The first tab character * after a clear screen sequence is not expanded correctly. Thus * expand the tabs by hand -dgk */ int tabstop = 8, spaces; char buf[BUFSIZ], *bufp, *bufrp; set_pager(0); bufr = (char *) alloc((unsigned) COLNO); while (fgets(buf, BUFSIZ, fp) && (!strip || *buf == '\t')){ bufp = buf; bufrp = bufr; while (*bufp && *bufp != '\n') { if (*bufp == '\t') { spaces = tabstop - (bufrp - bufr) % tabstop; while (spaces--) *bufrp++ = ' '; bufp++; } else *bufrp++ = *bufp++; } *bufrp = '\0'; #else /* MSDOS /**/ set_pager(0); bufr = (char *) alloc((unsigned) COLNO); bufr[COLNO-1] = 0; while(fgets(bufr,COLNO-1,fp) && (!strip || *bufr == '\t')){ ep = index(bufr, '\n'); if(ep) *ep = 0; #endif /* MSDOS /**/ if(got_intrup || page_line(bufr+strip)) { set_pager(2); goto ret; } } set_pager(1); ret: free((genericptr_t) bufr); (void) fclose(fp); #if !defined(MSDOS) && !defined(TOS) && !defined(MACOS) (void) signal(SIGINT, (SIG_RET_TYPE) prevsig); got_intrup = 0; #endif #endif } #endif /* OVLB */ #define PAGMIN 12 /* minimum # of lines for page below level map */ #ifndef OVLB OSTATIC boolean whole_screen; #else /* OVLB */ XSTATIC boolean whole_screen = TRUE; void set_whole_screen() { /* called in termcap as soon as LI is known */ whole_screen = (LI-ROWNO-2 <= PAGMIN || !CD); } #ifdef NEWS int readnews() { register int ret; whole_screen = TRUE; /* force a docrt(), our first */ ret = page_file(NEWS, TRUE); set_whole_screen(); return(ret); /* report whether we did docrt() */ } #endif void set_pager(mode) register int mode; /* 0: open 1: wait+close 2: close */ { #ifdef LINT /* lint may handle static decl poorly -- static boolean so; */ boolean so; #else static boolean so; #endif if(mode == 0) { if(!whole_screen) { /* clear topline */ clrlin(); /* use part of screen below level map */ curs(1, ROWNO+4); } else { cls(); } so = flags.standout; flags.standout = 1; } else { #ifdef MACOS macflags |= fFullScrKluge; #endif if(mode == 1) { #ifdef MACOS macflags |= fCornScrKluge; #endif curs(1, LI); more(); } flags.standout = so; if(whole_screen) docrt(); else { curs(1, ROWNO+4); cl_eos(); } #ifdef MACOS macflags &= ~fScreenKluges; #endif } } #endif /* OVLB */ #ifdef OVL0 int page_line(s) /* returns 1 if we should quit */ register const char *s; { if(cury == LI-1) { if(!*s) return(0); /* suppress blank lines at top */ (void) putchar('\n'); cury++; cmore("q\033"); if(morc) { morc = 0; return(1); } if(whole_screen) cls(); else { curs(1, ROWNO+4); cl_eos(); } } #ifdef TERMINFO xputs(s); xputc('\n'); #else (void) puts(s); # ifdef MACOS (void) putchar('\n'); # endif #endif cury++; return(0); } /* * Flexible pager: feed it with a number of lines and it will decide * whether these should be fed to the pager above, or displayed in a * corner. * Call: * cornline(0, title or 0) : initialize * cornline(1, text) : add text to the chain of texts * cornline(2, morcs) : output everything and cleanup * cornline(3, 0) : cleanup * cornline(-1,"") : special, for help menu mode only */ void cornline(mode, text) int mode; const char *text; { static struct line { struct line *next_line; char *line_text; } *texthead, *texttail; static int maxlen; static int linect; register struct line *tl; register boolean hmenu = FALSE; #ifdef NEXT WindowWindow(TRUE); #endif /* NEXT */ if(mode == -1) { /* help menu display only */ mode = 2; hmenu = TRUE; } if(mode == 0) { texthead = 0; maxlen = 0; linect = 0; if(text) { cornline(1, text); /* title */ cornline(1, ""); /* blank line */ } #ifdef NEXT WindowWindow(FALSE); #endif /* NEXT */ return; } if(mode == 1) { register int len; if(!text) return; /* superfluous, just to be sure */ linect++; len = strlen(text) + 1; /* allow for an extra leading space */ if(len > maxlen) maxlen = len; tl = (struct line *) alloc((unsigned)(len + sizeof(struct line) + 1)); tl->next_line = 0; tl->line_text = (char *)(tl + 1); tl->line_text[0] = ' '; tl->line_text[1] = '\0'; Strcat(tl->line_text, text); if(!texthead) texthead = tl; else texttail->next_line = tl; texttail = tl; #ifdef NEXT WindowWindow(FALSE); #endif /* NEXT */ return; } /* --- now we really do it --- */ if(mode == 2 && linect == 1) /* topline only */ pline("%s", texthead->line_text); else if(mode == 2) { register int curline, lth; #ifdef MACOS short tmpflags; extern struct line *mactexthead; extern int macmaxlen, maclinect; tmpflags = macflags; macflags |= fDoUpdate | fDisplayKluge; mactexthead = texthead; macmaxlen = maxlen; maclinect = linect; #endif if(flags.toplin == 1) more(); /* ab@unido */ remember_topl(); lth = CO - maxlen - 2; /* Use full screen width */ if (linect < LI && lth >= 10) { /* in a corner */ home (); cl_end (); flags.toplin = 0; curline = 1; for (tl = texthead; tl; tl = tl->next_line) { #if defined(MSDOS) && !defined(AMIGA) cmov (lth, curline); #else curs (lth, curline); #endif if(curline > 1) cl_end (); xputs(tl->line_text); curx = curx + strlen(tl->line_text); curline++; } if(hmenu) { /* help menu display */ do hc = lowc(readchar()); while (!valid_help(hc)); } #if defined(MSDOS) && !defined(AMIGA) cmov (lth, curline); #else curs (lth, curline); #endif cl_end (); if (!hmenu) { #ifdef MACOS macflags |= fCornScrKluge; #endif cmore (text); } if (!hmenu || clear_help(hc)) { home (); cl_end (); docorner (lth, curline-1); } #ifdef MACOS mactexthead = NULL; macflags |= (tmpflags & (fDoUpdate | fDisplayKluge)); #endif } else { /* feed to pager */ set_pager(0); for (tl = texthead; tl; tl = tl->next_line) { if (page_line (tl->line_text)) { set_pager(2); while(tl = texthead) { texthead = tl->next_line; free((genericptr_t) tl); } #ifdef NEXT WindowWindow(FALSE); #endif /* NEXT */ return; } } if(text) { cgetret(text); set_pager(2); } else set_pager(1); } } while(tl = texthead) { texthead = tl->next_line; free((genericptr_t) tl); } #ifdef NEXT WindowWindow(FALSE); #endif /* NEXT */ } #endif /* OVL0 */ #ifdef OVLB #ifdef WIZARD static void wiz_help() { cornline(0, "Wizard-Mode Quick Reference:"); cornline(1, "^E == detect secret doors and traps."); cornline(1, "^F == do magic mapping."); cornline(1, "^G == create monster."); cornline(1, "^I == identify items in pack."); cornline(1, "^O == tell locations of special levels."); cornline(1, "^T == do intra-level teleport."); cornline(1, "^V == do trans-level teleport."); cornline(1, "^W == make wish."); cornline(1, "^X == show intrinsic attributes."); cornline(1, ""); cornline(2, ""); } #endif static void help_menu() { cornline(0, "Information available:"); cornline(1, "a. Long description of the game and commands."); cornline(1, "b. List of game commands."); cornline(1, "c. Concise history of NetHack."); cornline(1, "d. Info on a character in the game display."); cornline(1, "e. Info on what a given key does."); cornline(1, "f. List of game options."); cornline(1, "g. Longer explanation of game options."); cornline(1, "h. List of extended commands."); cornline(1, "i. The NetHack license."); #ifdef MACOS cornline(1, "j. Macintosh primer."); #endif #ifdef WIZARD if (wizard) # ifdef MACOS cornline(1, "k. List of wizard-mode commands."); # else cornline(1, "j. List of wizard-mode commands."); # endif #endif cornline(1, ""); #ifdef WIZARD if (wizard) # ifdef MACOS cornline(1, "Select one of a,b,c,d,e,f,g,h,i,j,k or ESC: "); # else cornline(1, "Select one of a,b,c,d,e,f,g,h,i,j or ESC: "); # endif else #endif #ifdef MACOS cornline(1, "Select one of a,b,c,d,e,f,g,h,i,j or ESC: "); #else cornline(1, "Select one of a,b,c,d,e,f,g,h,i or ESC: "); #endif cornline(-1,""); } XSTATIC boolean clear_help(c) char c; { /* those valid_help characters which do not correspond to help routines * that redraw the whole screen on their own. if we always clear the * help menu, we end up restoring the part of the maze underneath the * help menu when the last page of a long help file is displayed with * an external pager. * * When whole_screen is FALSE and the internal pager is used, the * screen is big enough so that the maze is left in place during paging * and the paging occurs in the lower part of the screen. In this case * the pager clears out the part it wrote over when it exits but it * doesn't redraw the whole screen. So all characters require that * the help menu be cleared. * * When an external pager is used, the screen is always cleared. * However, the "f" and "h" help options always use the internal * pager even if DEF_PAGER is defined. * - Bob Wilber wilber@homxb.att.com 10/20/89 */ return(index(quitchars,c) || c == 'd' || c == 'e' #ifdef DEF_PAGER || (!whole_screen && (c == 'f' || c == 'h')) #else || !whole_screen #endif #ifdef WIZARD # ifdef MACOS || c == 'k' # else || c == 'j' # endif #endif ); } XSTATIC boolean valid_help(c) char c; { #ifdef WIZARD # ifdef MACOS return ((c >= 'a' && c <= (wizard ? 'k' : 'j')) || index(quitchars,c)); # else return ((c >= 'a' && c <= (wizard ? 'j' : 'i')) || index(quitchars,c)); # endif #else # ifdef MACOS return ((c >= 'a' && c <= 'j') || index(quitchars,c)); # else return ((c >= 'a' && c <= 'i') || index(quitchars,c)); # endif #endif } int dohelp() { #ifdef MACOS term_info *t; macflags &= ~fDoNonKeyEvt; t = (term_info *)GetWRefCon(HackWindow); SetVol((StringPtr)NULL, (t->auxFileVRefNum) ? t->auxFileVRefNum : t->recordVRefNum); #endif help_menu(); if (!index(quitchars, hc)) { switch(hc) { case 'a': (void) page_file(HELP, FALSE); break; case 'b': (void) page_file(SHELP, FALSE); break; case 'c': (void) dohistory(); break; case 'd': (void) dowhatis(); break; case 'e': (void) dowhatdoes(); break; case 'f': option_help(); break; case 'g': (void) page_file(OPTIONFILE, FALSE); break; case 'h': (void) doextlist(); break; case 'i': (void) page_file(LICENSE, FALSE); break; #ifdef WIZARD # ifdef MACOS case 'j': (void) page_file(MACHELP, FALSE); break; case 'k': wiz_help(); break; # else case 'j': wiz_help(); break; # endif #endif } } #ifdef MACOS SetVol((StringPtr)NULL, t->recordVRefNum); macflags |= fDoNonKeyEvt; #endif return 0; } int dohistory() { (void) page_file(HISTORY, FALSE); return 0; } int page_file(fnam, silent) /* return: 0 - cannot open fnam; 1 - otherwise */ register const char *fnam; boolean silent; { #ifdef DEF_PAGER /* this implies that UNIX is defined */ { /* use external pager; this may give security problems */ register int fd = open(fnam, 0); if(fd < 0) { if(!silent) pline("Cannot open %s.", fnam); return(0); } if(child(1)){ /* Now that child() does a setuid(getuid()) and a chdir(), we may not be able to open file fnam anymore, so make it stdin. */ (void) close(0); if(dup(fd)) { if(!silent) Printf("Cannot open %s as stdin.\n", fnam); } else { (void) execl(catmore, "page", NULL); if(!silent) Printf("Cannot exec %s.\n", catmore); } exit(1); } (void) close(fd); } #else { FILE *f; /* free after Robert Viduya */ #ifdef OS2_CODEVIEW char tmp[PATHLEN]; Strcpy(tmp,hackdir); append_slash(tmp); Strcat(tmp,fnam); if ((f = fopen (tmp, "r")) == (FILE *) 0) { #else # ifdef MACOS if ((f = fopen (fnam, "r")) == (FILE *) 0) f = openFile(fnam, "r"); if (!f) { # else if ((f = fopen (fnam, "r")) == (FILE *) 0) { # endif #endif if(!silent) { home(); perror (fnam); flags.toplin = 1; pline ("Cannot open %s.", fnam); } return(0); } page_more(f, 0); } #endif /* DEF_PAGER /**/ return(1); } #ifdef UNIX #ifdef SHELL int dosh(){ register char *str; if(child(0)) { if(str = getenv("SHELL")) (void) execl(str, str, NULL); else (void) execl("/bin/sh", "sh", NULL); pline("sh: cannot execute."); exit(1); } return 0; } #endif /* SHELL /**/ #if defined(SHELL) || defined(DEF_PAGER) || defined(DEF_MAILREADER) int child(wt) int wt; { register int f = fork(); if(f == 0){ /* child */ settty(NULL); /* also calls end_screen() */ (void) setgid(getgid()); (void) setuid(getuid()); #ifdef CHDIR (void) chdir(getenv("HOME")); #endif return(1); } if(f == -1) { /* cannot fork */ pline("Fork failed. Try again."); return(0); } /* fork succeeded; wait for child to exit */ (void) signal(SIGINT,SIG_IGN); (void) signal(SIGQUIT,SIG_IGN); (void) wait( #if defined(BSD) || defined(ULTRIX) (union wait *) #else (int *) #endif 0); gettty(); setftty(); (void) signal(SIGINT, (SIG_RET_TYPE) done1); #ifdef WIZARD if(wizard) (void) signal(SIGQUIT,SIG_DFL); #endif if(wt) { boolean so; cmov(1, LI); /* get prompt in reasonable place */ so = flags.standout; flags.standout = 1; more(); flags.standout = so; } docrt(); return(0); } #endif #endif /* UNIX /**/ #endif /* OVLB */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.