home *** CD-ROM | disk | FTP | other *** search
- #include "help.h"
- #define MAXMATCHES 24
-
- /* ************************************************************
- * H E L P !!
- * =========================
- *
- * This program emulates the VMS help facility in the UNIX
- * environment. The main routine HELP1 looks up help and
- * subtopics for help. The help texts for various topix
- * are tree-structured. A directory is defined as a "help"
- * directory, it has four types of files in it:
- * main help text: .HLP
- * manual page name: .MANUAL
- * subtopic texts: <topicname>.HLP
- * subtopic directories: <topicname>
- * subtopic cross-refs: <topicname>.XREF
- *
- * Subtopic names must start with an alphanumeric
- * character. Preferably all subtopics will start with
- * lowercase letters.
- *
- * The routine help1 is recursive, it descends the tree
- * structure.
- */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int i,j,k;
- int longlen;
- char yesno[10];
- char *opts;
-
- strcpy(progname,argv[0]);
- helpdir = NULL;
- getwd(olddir);
- dumb_flag = 0;
- list_flag = 0;
- frst_flag = 1;
- col_flag = 1;
-
- argc--;
- if (*(*++argv) == '-') { /* must be options */
- for (opts = *argv; *opts != '\0'; opts++) {
- switch(*opts) {
- case '-' :
- break;
-
- case 'd' :
- if (argc > 1) {
- helpdir = *++argv;
- argc--;
- }
- break;
-
- case 'l' :
- list_flag = 1;
- col_flag = 0;
- break;
-
- case 'q' :
- dumb_flag = 1;
- break;
-
- case 'C' :
- col_flag = 1;
- break;
-
- case 'n' :
- col_flag = 0;
-
- default:
- fprintf(stderr,"%s: %c: bad option.\n",
- progname,*opts);
- break;
- }
- }
- argc--; argv++;
- }
-
- if (helpdir == NULL) helpdir = HELPDIR;
-
- if (chdir(helpdir) < 0) {
- fprintf(stderr,"%s: %s: help directory not found.\n",
- progname,helpdir);
- exit(1);
- }
-
- #ifdef BSD
- init_funky();
- #endif
- if (argc >= 1) { /* treat vector as a help path */
- #ifdef DEBUG
- fprintf(stderr," help path vector, argc=%d, *argv=%s.\n",
- argc,*argv);
- #endif
- help1( "", argv, 0, 0, 0);
-
- }
- else help1( "", NULL, 0, 0, 0);
-
- exit(0);
- }
-
-
-
-
- /* **************************************************************
- * printhelp: given a string, pop .HLP on the end and do more(1).
- *
- * This routine sends a help file to more(1). A string
- * is passed in, which is the name of a help. If the string
- * is nil, then just use the name HLP.
- * The return value is -1 if no help file is accessible,
- * 0 if the more(1) command was called okay with fkoff();
- */
-
- printhelp(hs, path)
- char *hs;
- {
- char filename[MAXNAMELEN], comm[MAXNAMELEN + 20];
-
- if (hs == NULL) strcpy(filename,HELPEX);
- else if (strlen(hs) < 1) strcpy(filename, HELPEX);
- else {
- strcpy(filename, hs);
- strcat(filename,HELPEX);
- }
-
- if ( access(filename, R_OK) < 0 ) {
- printf("\n Sorry, no help text for %s.\n",
- (hs==NULL)?"this topic":hs );
- return(-1);
- }
-
- if (path != NULL) printf("\n HELP: %s\n",path);
-
- fkoff(VIEWPROGRAM,VIEWPROGOPTS1,VIEWPROGOPTS2,filename,NULL);
-
- return(0);
- }
-
-
-
- /* *************************************************************
- * printtopix: print the topics available in this directory
- * in a nice format.
- *
- * This routine does a directory of help options,
- * and prints them out in a manner similar to that of ls(1).
- * All filenames which start with anything other than numbers
- * or letters are not kept. Extensions are stripped off.
- *
- * The number of subtopics found is returned, along with
- * a pointer to a null-terminated vector of string pointers.
- * If the mode is non-zero, it means just use the strings stored
- * in topix. If mode==0, then re-allocate space and re-check
- * the directory. If mode
- */
-
- printtopix( topix, mode, supress)
- char *topix[];
- int mode, supress;
- {
- int i,j,k,l,xrefs = 0;
- int namewidth, totalnames;
- char *malloc(), *nbuf;
- char *thisname, *index();
- char *s1, *s2, **nxtname, *nxcnt;
- struct direct *readdir(), *filedat;
- DIR *dirp, *opendir();
-
- if ( mode ) {
- for(nxtname=topix, i=0; *nxtname++ != NULL; i++ );
- totalnames = i;
- goto inputtopix;
- }
-
- /* if mode is zero, then allocate space and search the directory */
- nbuf = malloc( MAXNAMES * MAXNAMELEN );
- nxcnt=nbuf;
- dirp = opendir(".");
- if (dirp == NULL) {
- fprintf(stderr,"%s: Cannot open help directory.\n",progname);
- return(-1);
- }
-
- for(nxtname=topix, i=0; i < (MAXNAMES-1) ; ) {
- filedat = readdir(dirp);
- if (filedat == NULL) break;
- thisname = filedat->d_name;
- if ( !(isalnum(*thisname)) ) /* if not in [0-9A-Za-z] */
- continue; /* do the next one. */
- *nxcnt = '\0';
- if ( (s1 = index(thisname,'.')) != NULL) {
- if (strcmp(s1, HELPEX) == 0) *s1 = '\0';
- else if ( strcmp(s1, MANEX) == 0) continue;
- else if ( strcmp(s1, XREFEX) == 0) {
- /* mark xref with at sign in first char */
- strcpy(nxcnt,"@");
- }
- }
- if (strlen(thisname) >= MAXNAMELEN - 1)
- *(thisname+MAXNAMELEN-1) = '\0';
- /* copy in data from this loop */
- if (*nxcnt == '\0') strcpy(nxcnt,thisname);
- else strcat(nxcnt,thisname);
- *nxtname++ = nxcnt;
- /* update pointers for next loop */
- nxcnt += strlen(thisname) + ((*nxcnt=='@')?(2):(1));
- i++;
- }
- *nxtname++ = NULL;
- totalnames = i;
- closedir(dirp);
-
- if (totalnames == 0) return(0);
-
- /* sort the names in ascending order with exchange algorithm */
- for(i=0; i < totalnames-1; i++)
- for(j=i+1; j <totalnames; j++)
- if (strcmp(topix[i],topix[j]) > 0) {
- thisname = topix[i];
- topix[i] = topix[j];
- topix[j] = thisname;
- }
-
-
- inputtopix:
- if (supress) return(totalnames);
- else {
- if (col_flag) printf("\n Subtopics:\n");
- printlist(topix, totalnames);
- return(totalnames);
- }
-
- }
-
-
-
- /* ****************************************************************
- * help1: descend recursive help tree and provide some
- * user services.
- *
- * This routine is the heart of the new UNIX help facility.
- * It climbs recursively around an n-tree of documentation files
- * and directories. The routine printhelp() outputs a file of
- * help text, the routine printtopix prints out all subtopics.
- *
- * This routine can operate in interactive mode, or not. The
- * basic cycle of operation is:
- * if (not list-only-mode) print help.
- * if (not quiet-mode) print list.
- * if (not interactive) return.
- * print prompt and do commands.
- * return.
- *
- * There are a number of commands available in the
- * interactive mode, they are:
- *
- * blank line: up recursive level.
- * subtopic name: recurse to subtopic.
- * ?: list topics again.
- * *: get list of commands
- * $: get info on topix
- * ^D: quit help program.
- * .: man page (if any).
- * # list topics again
- *
- */
-
- help1(ppt,svec,skip,xref,comp_flag)
- char *ppt;
- char *svec[];
- short skip;
- short xref; /* non-zero if doing xref */
- short comp_flag; /* non-zero if doing completions */
- { /* this routine is too big, eh? */
- int i,j,k, err;
- int no_subs;
- char answer[MAXLINELEN];
- char fullpath[MAXNAMELEN + 29];
- char yesno[10];
- char *topix[MAXNAMES], *mx[MAXMATCHES];
- int matchv();
- char *index(), *getenv();
- char *s1, *s2, *s3, *rest;
- char *wvec[MAXMATCHES];
- char cmdbuf[90];
-
-
- if (comp_flag) {
- printtopix( topix, 0, 1);
- if ( (k = matchv( *svec, topix, mx)) == 0) return(-1);
- /* if there is more than one match, and we are not at end, flub */
- if ( svec[1] != NULL && k > 1 ) return(-1);
- /* if we are not at end, go down one level */
- if ( svec[1] != NULL ) {
- if ( chdir( mx[0] ) < 0) return(-1);
- else {
- k = help1(ppt, svec+1, 0, 0, comp_flag);
- chdir("..");
- return(k);
- }
- }
- /* if we are at end, then do appropriate action on comp_flag */
- else {
- strcpy(gbl_match, mx[0]);
- if ( comp_flag == CTRLD_COMP ) {
- fputs("\n",stdout);
- printlist(mx,k);
- }
- }
- return(0);
- }
-
- if ( svec != NULL && *svec != NULL) {
- printtopix( topix, 0, 1);
- if ( (k = matchv(*svec, topix, mx)) == 0) {
- printf(" sorry, no direct help path to %s %s\n",ppt,*svec);
- if ( (k = xref_matchv(*svec, topix, mx)) == 0) {
- printf(" no cross-references, either.\n\n");
- if (strlen(ppt) == 0) help1(ppt,NULL,1,0, 0);
- return(-1);
- }
- else {
- do_xref(ppt,*svec,mx);
- if (strlen(ppt) == 0) help1(ppt,NULL,1,0, 0);
- return(-1);
- }
- }
-
- for(i = 0, j = 0, err = -1; mx[i] != NULL; ) {
- if (i > 0)
- j = takeit(" Next help path: %s %s\nTry it?",ppt,mx[i]);
- if (j == 1) { i++; continue; }
- if (j < 0) break;
- strcpy(fullpath,ppt);
- strcat(fullpath," ");
- strcat(fullpath,mx[i]);
-
- if ( chdir(mx[i]) < 0) {
- if ( *(svec + 1) != NULL ) {
- i++;
- continue;
- }
- if (list_flag)
- return(-1);
- else
- printhelp( mx[i],fullpath);
- printf("\n");
- if (!dumb_flag) help1(ppt,NULL,1,0, 0);
- err = 0;
- }
- else {
- if ( help1(fullpath,(svec+1),0,0, 0) >= 0) {
- err = 0;
- chdir("..");
- printf("\n");
- if (!dumb_flag) help1(ppt,NULL,1,xref, 0);
- }
- else chdir("..");
- }
- i++;
- }
- return(err);
- }
-
- if ( !list_flag && !skip)
- if (printhelp(NULL, ppt) < 0) {
- return(-1);
- }
-
- if ( !list_flag && !dumb_flag && ( access(MANEX, R_OK) >= 0) && !skip)
- printf("\n Manual page IS available.\n");
-
- if ( !dumb_flag ) {
- if ( printtopix( topix, 0, skip) <= 0 ) {
- no_subs = 1;
- }
- else no_subs= 0;
- }
-
- if ( dumb_flag || list_flag ) return(0);
-
- while (xref == 0) {
- if (frst_flag) {
- printf(" (type '*' for commands)\n");
- frst_flag = 0;
- }
-
-
- /* now, prompt and wait for user response */
-
- if ( strlen(ppt) < 1 ) sprintf(gbl_ppt," Help %s",PROMPT);
- else sprintf(gbl_ppt," %s %s",ppt,SUBPROMPT);
- fputs(gbl_ppt,stdout);
- #ifndef BSD
- if ( fgets(answer, MAXLINELEN-1, stdin) == NULL ) {
- printf("\nbye...\n");
- exit(1);
- }
- #else
- if (read_gets(stdin->_file, answer, MAXLINELEN - 1, 1) < 0) {
- printf("\nbye...\n");
- exit(1);
- }
- #endif
-
- /* first remove any leading blanks or tabs */
- for(s1=answer; *s1 == ' ' || *s1 == ' '; s1++);
-
- /* chop off all of answer after first word. */
- s2 = index(s1,' ');
- if (s2 == NULL) s2 = index(s1,' ');
- if (s2 == NULL) s2 = index(s1,'\n');
- if (s2)
- { *s2 = '\0'; rest = ++s2; }
- else {
- rest = s2 = s1 + strlen(s1);
- }
- makewvec(rest,wvec,MAXMATCHES);
-
- if ( strlen(s1) == 0 ) /* on blank line, */
- break; /* pop up one level*/
-
- switch (*s1) {
- case '?': /* ?: print stuff again */
- printhelp(NULL, ppt);
- if ( access(MANEX, R_OK) >= 0 )
- printf("\n Manual page IS available.\n");
- if (!no_subs) printtopix(topix, 1,0);
- else printf("\n Sorry, no subtopics.\n\n");
- break;
-
- case '#':
- if (!no_subs) printtopix( topix, 1,0);
- else printf("\n Sorry, no subtopics.\n\n");
- break;
-
- case '*': /* *: list commands */
- printf("\n");
- for(i=0; helpcmds[i] != NULL; i++) {
- printf(" %s\n",helpcmds[i]);
- }
- printf("\n");
- break;
-
- case '$': /* $: find out about files */
- s2 = s1 + 1;
- if (no_subs) {
- printf("\n Sorry, no subtopics.\n\n");
- break;
- }
- strcpy(cmdbuf, INFOHEAD);
- strcat(cmdbuf,s2);
- strcat(cmdbuf,"* ");
- strcat(cmdbuf, INFOTAIL);
- printf("\n File information: \n");
- system(cmdbuf);
- printf("\n");
- break;
-
-
- case '.': /* .: do manpage if any */
- s2 = s1 + 1;
- if (no_subs) {
- printf("\n Sorry, no subtopics.\n\n");
- break;
- }
- if ( *s2 == '\0' ) {
- mx[0] = ""; mx[1] = NULL; k = 1;
- }
- else if ( (k = matchv( s2, topix, mx)) == 0 ) {
- printf("\n Sorry, no topics match %s\n",s2);
- printf(" (list cmnds with '*', topix with '#')\n");
- }
- for( i=0; i < k; i++ ) {
- strcpy(cmdbuf,mx[i]);
- strcat(cmdbuf,MANEX);
- if (access(cmdbuf, R_OK|X_OK ) < 0) {
- strcpy(cmdbuf,mx[i]);
- strcat(cmdbuf,MAN_SUBEX);
- if (access(cmdbuf,R_OK|X_OK) < 0) {
- printf("\n Sorry, %s for %s.\n\n",
- "No manual reference available",
- (strlen(s2)==0)?ppt:mx[i]);
- continue;
- }
- }
- if (i > 0) {
- k=
- takeit(" Next man page: %s.\n Take it? ",
- mx[i]);
- if (k == 1) continue;
- if (k == -1) break;
- }
- printf(" ...doing %s\n\n",cmdbuf);
- fkoff(SHELLPROG,SHELLOPTS,cmdbuf,NULL);
- /* source contents of .MANUAL file */
- }
- break;
-
-
- default: /* must be a topic spec */
- if ( no_subs ) {
- printf("\n Sorry, no subtopics.\n\n");
- break;
- }
- if ( (k = matchv( s1, topix, mx)) == 0 ) {
- printf("\n Sorry, no direct help for %s\n",s1);
- if ( (k = xref_matchv(s1,topix,mx)) == 0) {
- printf(" no cross-references to %s\n",s1);
- printf(
- " (list cmnds with '*', topics with '#')\n");
- break; /* leave switch */
- }
- else {
- do_xref(ppt,s1,mx);
- break; /* leave switch */
- }
- }
-
- /* step thru sub-topics that match src */
- for(i=0; i < k; i++) {
- s3 = mx[i];
-
- if (i > 0) {
- j=takeit("\nNext %s subtopic: %s\nTake it?",
- ppt,s3);
- if (j == 1) continue;
- if (j == -1) break;
- }
-
- if ( chdir(s3) >= 0 ) { /* directory subtopic */
- strcpy(fullpath,ppt);
- strcat(fullpath," ");
- strcat(fullpath,s3);
- help1(fullpath,wvec,0,0, 0); /* recurse */
- if ( strcmp(getwd(newdir),helpdir) )
- chdir("..");
- } /* else text subtopic */
- else {
- strcpy(fullpath, ppt);
- strcat(fullpath, " ");
- strcat(fullpath, s3);
- printhelp(s3, fullpath);
- }
- }
-
- } /* end of switch */
-
- } /* end of while(1) */
-
- if (!no_subs && (*topix != NULL) ) free( *topix );
-
- return(0);
-
- } /* end of help1 */
-
-
- /* ****************************************************************
- * takeit: ask user whether to take next topic, return t or f
- *
- * This routine takes a message, with format, and asks the
- * user whether he wants to do the action, not do the action,
- * or quit the cycle of actions.
- * y - return 0
- * n - return 1
- * q - return -1
- * ? - tell what y, n, and q do.
- * * - tell what y, n, and q do.
- * <CR> - carriage return
- *
- * Naturally, case is insignificant.
- */
-
- takeit(fmt,m1,m2,m3)
- char *fmt, *m1, *m2, *m3;
- {
-
- char ans[40];
- int done, ret;
- char *fgets();
-
- for(done = 0; !done; ) {
- if (fmt != NULL) printf(fmt, m1, m2, m3);
- printf(" [ynq] ");
- if (fgets(ans, 39, stdin) == NULL) exit(1); /* abort */
- isupper(*ans)?(*ans=tolower(*ans)):0;
- if (*ans == 'n') {
- done = 1;
- ret = 1;
- }
- else if (*ans == 'y' || *ans == '\n') {
- done = 1;
- ret = 0;
- }
- else if (*ans == 'q') {
- done = 1;
- ret = -1;
- }
- else printf(" Answer y to get next subtopic, n to skip, q to quit.\n");
- }
- return(ret);
- }
-
-
- /* ***************************************************************
- * matchv: return all matches of a string in a vector.
- *
- * This routine accepts a string and a vector of strings.
- * The string is supposed to be an abbreviation of one or more
- * strings in the vector. The full versions of the strings are
- * placed in a another vector (which is in a static area) and
- * a pointer to that vector returned. Note that the input
- * vector of pointers must have NULL as its terminating element.
- * The output vector will also terminate with NULL.
- * NOTE: The vector returned contains pointers into the input
- * vector. Do not, therefore, mess with the contents of the output
- * vector.
- *
- * If NULL is returned, nothing matched, or there was some other
- * error.
- */
-
- matchv( src, vec, mx)
- char *src;
- char *vec[];
- char *mx[];
- {
- char *m[MAXMATCHES];
- char *s1, *s2;
- int i,j, slen;
-
- if ( (slen = strlen(src)) == 0 ) return(NULL);
-
- for(i=0, j=0; vec[i] != NULL && j < MAXMATCHES; i++) {
- if ( strcmp(src,vec[i]) == 0 ) { /* exact match! */
- m[0] = vec[i]; j = 1;
- break;
- }
- else if ( strncmp(src,vec[i],slen) == 0 &&
- strlen(vec[i]) >= slen )
- m[j++] = vec[i];
- }
- m[j] = NULL;
- for(i=0; i <= j; mx[i] = m[i], i++);
- return(j);
- }
-
- /* *****************************************************************
- * fkoff: fork a process and return the exit status of the process.
- *
- * This routine takes a command line separated into words, and
- * uses vfork(2) and execve(2) to quickly run the program.
- *
- * This is a simplified version of the fkoff() routine from dcon(8).
- * Here, a program name and up to four arguments may be passed in.
- * If one of them is null, FINE, but the fifth
- *
- */
-
- fkoff(prg,arg1,arg2,arg3,arg4)
- char *prg, *arg1, *arg2, *arg3, *arg4;
-
- {
- char *command, *malloc(), *argvec[6];
- int pid, stat, i;
-
- for(i=0; i < 6; argvec[i++] = NULL);
- argvec[0] = prg;
- argvec[1] = arg1;
- argvec[2] = arg2;
- argvec[3] = arg3;
- argvec[4] = arg4;
- if (argvec[0] == NULL) return(-1);
- command = malloc( strlen(argvec[0]) + 1);
- strcpy(command,argvec[0]);
-
- Set_Tc_Init( (stdin->_file) ) ;
- #ifdef USG
- pid = fork();
- #else
- pid = vfork(); /* fork 2 copies of us */
- #endif
- if (pid < 0 ) {
- fflush(stdout);
- perror("help: fork");
- Set_Tc_Here( (stdin->_file) ) ;
- return(0);
- }
- else if (pid == 0) { /* we are child, execve the program. */
- pid = execve(command,argvec,environ);
- _exit(1);
- }
- else { /* we are parent, wait for child */
- pid = wait(&stat);
- Set_Tc_Here( (stdin->_file) ) ;
- if (pid == -1) return(pid);
- stat = stat / 0400; /* get hi byte of status */
- return(stat);
- }
- }
-
- /* **************************************************************
- * makewvec: make a vector of words, up to N of them
- *
- * This routine uses index to simply parse a string
- * made up of (possibly) several blank-separated words.
- * The words are stored into the slots of a vector, as pointers
- * into the original string. Therefore, the original string
- * is destroyed.
- */
- makewvec(sstr, rvec, veccnt)
- char *sstr;
- char *rvec[];
- int veccnt;
- {
- int mcnt = 0;
- int done = 0;
- int i,j;
- char *s1, *s2, *index();
-
- if (strlen(sstr) == 0) {
- rvec[0] = NULL;
- }
- else {
- /* skip leading whitespace */
- for(s1=sstr; iswhite(*s1); s1++);
- for(mcnt = 0, done = 0; !done; mcnt++) {
- s2 = index(s1,' ');
- if (s2 == NULL) s2 = index(s1,' ');
- if (s2 == NULL) s2 = index(s1,'\n');
- if (s2 != NULL) *s2 = '\0';
- rvec[mcnt] = s1;
- if (mcnt + 1 >= veccnt) break;
- if (s2 == NULL) done = 1;
- else {
- /* skip more white space */
- for(s1 = s2+1; iswhite(*s1); s1++);
- if (*s1 == '\0') done = 1;
- }
- }
- rvec[mcnt] = NULL;
- }
-
- return(mcnt);
- }
-
-
- /* ***************************************************************
- * xref_matchv: return all cross-ref matches for a topic
- *
- * This routine accepts a string and a vector of strings.
- * The string is supposed to be a referal to one or more
- * cross-reference file names in the vector. The matches are
- * placed in a another vector (which is in a static area) and
- * a pointer to that vector returned. Note that the input
- * vector of pointers must have NULL as its terminating element.
- * The output vector will also terminate with NULL.
- * NOTE: The vector returned contains pointers into the input
- * vector. Do not, therefore, mess with the contents of the output
- * vector.
- * NOTE: cross-ref file names in the topix vector begin with
- * the flag char '@' and still have their extension of .XREF.
- *
- * If 0 is returned, nothing matched, or there was some other error.
- */
-
- xref_matchv( src, vec, mx)
- char *src;
- char *vec[];
- char *mx[];
- {
- char *m[MAXMATCHES];
- char *s1, *s2;
- char one_ref[MAXNAMELEN];
- int i,j, slen;
-
- if ( (slen = strlen(src)) == 0 ) return(NULL);
-
- for(i=0, j=0; vec[i] != NULL && j < MAXMATCHES; i++) {
- if ( *vec[i] != '@' ) break;
- for(s1 = vec[i], s2 = one_ref;
- *s1 != '\0' && *s1 != '.';
- *s2++ = *s1++);
- *s2 = '\0';
- if ( strcmp(src,one_ref) == 0) { /* exact match! */
- m[0] = vec[i]; j = 1;
- break;
- }
- else if
- (strncmp(src,(vec[i] + 1),slen) == 0 && strlen(vec[i]) >= slen)
- m[j++] = vec[i];
- }
- m[j] = NULL;
- for(i=0; i <= j; mx[i] = m[i], i++);
- return(j);
- }
-
-
- /* **************************************************************
- * do_xref: given a vector of cross-reference filenames, do them
- *
- * This routine follows a set of cross references.
- * Technically, there are two kinds of cross-reference files,
- * distinguished by the first character of their contents.
- * If the first character is an at sign (@) the file is a
- * ``direct'' cross-reference and the rest of the line starting
- * with the @ sign is a vector of words that give an ABSOLUTE
- * help path. If the first char is not @ then the file is an
- * ``apologetic'' cross-reference, and the text in it is a
- * lame-brained excuse for why the topic in question is not
- * documented in help.
- *
- * For each filename in the vector, the following actions
- * are performed.
- *
- * 1. check that the file exists and is readable, by
- * opening it for reading.
- * 2. If this is not the first xref, ask the user if
- * he wants to look at this one, if so, proceed to
- * 3. Read the first line of the file and check it.
- * a. if first char is not '@', do a more(1)
- * on the file with fkoff.
- * b. otherwise, read the first line, and
- * use makewvec to parse it into words.
- * pass these words to a new invokation
- * of help1. Make the ppt for help1
- * be something that denotes a cross-ref.
- */
- do_xref(ppt,src,mx)
- char *ppt, *src;
- char *mx[];
- {
- int i,j,k;
- char one_ref[MAXNAMELEN];
- char *s1, *index();
-
- for(i=0; mx[i] != NULL; i++) {
- strcpy(one_ref,mx[i]+1);
- if (i > 0) {
- j = takeit("\nNext %s %s cross-reference: %s\nTake it?",
- ppt,src,one_ref);
- if (j == 1) continue;
- if (j == -1) break;
- }
- do_one_xref(one_ref,src,ppt);
- }
-
- putchar('\n');
- return(0);
- }
-
-
- /* **************************************************************
- * do_one_xref: evaluate and do a single cross-reference
- *
- * This routine accepts a single file name and src name
- * for a single cross-reference. It then checks the file
- * for type, and performs the appropriate action.
- *
- * If the file is not accessible, an error message is
- * printed.
- */
- do_one_xref(xref_file,src,ppt)
- char *xref_file, *src, *ppt;
- {
- int i,j;
- FILE *xr_fp, *fopen();
- char *wvec[MAXMATCHES];
- char *index(), *s1, lbuf[MAXLINELEN], xbuf[MAXNAMELEN+15];
-
- if ( (xr_fp = fopen(xref_file,"r")) == NULL) {
- printf(" Sorry, %s cross-reference file inaccessible.\n",xref_file);
- return(-1);
- }
-
- if (fgets(lbuf,MAXLINELEN,xr_fp) != NULL) {
- if ( *lbuf != '@' ) {
- s1 = index(xref_file,'.');
- if (s1 != NULL) *s1 = '\0';
- printf(" Cross reference text called \"%s\" is available\n",
- xref_file);
- if (ppt != NULL)
- printf("\n HELP: %s <<%s>>\n",ppt,xref_file);
- if (s1 != NULL) *s1 = '.';
- fclose(xr_fp);
- fkoff(VIEWPROGRAM,VIEWPROGOPTS1,VIEWPROGOPTS2,xref_file,NULL);
- }
- else {
- char pptbuf[MAXNAMELEN+13], pathbuf[256];
- makewvec(lbuf+1,wvec,MAXMATCHES);
- printf("\n following cross-reference `help");
- for(i=0; wvec[i] != NULL; i++) printf(" %s",wvec[i]);
- s1 = index(xref_file,'.');
- if (s1 != NULL) *s1 = '\0';
- printf("' to find help for %s\n\n",xref_file);
- sprintf(pptbuf,"<<%s>> ",xref_file);
- if (s1 != NULL) *s1 = '.';
- getwd(pathbuf);
- chdir(helpdir);
- help1(pptbuf,wvec,1,1, 0);
- chdir(pathbuf);
- putchar('\n');
- }
- }
- else {
- printf(" Sorry, cross-ref file %s seems to be empty!\n\n",xref_file);
- }
- return(0);
- }
-
-
- /* **************************************************************
- * printlist - print a list of strings in columnar or list form
- *
- * This routine takes a list of names in a vector and prints
- * the list according to the current help mode. This code
- * used to be in printtopix() but I decided to move it here
- * so it could be used for other things.
- */
- printlist(vec,namecnt)
- char *vec[];
- int namecnt;
- {
- int i,j,k;
- int longlen, namewidth, rowcnt, colcnt, xrefs;
- char *s1, *s2;
- static char row[TERMWID+1];
-
- longlen = xrefs = 0;
- for(i=0; i < namecnt; i++ ) {
- if (*vec[i] == '@') xrefs++;
- else
- longlen = ((k=strlen(vec[i]))>longlen)?k:longlen;
- }
-
- /* here print the names out in nice columns */
- namewidth = longlen + COLUMNSPACE;
- rowcnt = TERMWID / namewidth;
- colcnt = (namecnt + (rowcnt-1)) / rowcnt ;
- if (colcnt <= 0) colcnt = 1;
-
- if (col_flag && rowcnt >= 1) {
- printf("\n");
- for(i=0; i < colcnt ; i++ ) {
- for(k=0; k < TERMWID; row[k++] = ' ');
- row[k] = '\0';
- for(j=0, s1 = row;
- (i+j+xrefs) < namecnt;
- j += colcnt) {
- row[strlen(row)] = ' ';
- strcpy(s1,vec[i+j+xrefs]);
- s1 = s1 + namewidth;
- }
- printf(" %s\n",row);
- }
- printf("\n");
- }
- else {
- for(i=xrefs; i < namecnt; i++)
- printf("%s\n",vec[i]);
- }
-
- }
-
- #ifdef BSD
-
- /* **************** funky keyboard stuff below here ************* */
-
- /* **************************************************************
- * pushback - push a string back onto the tty input queue
- *
- * This routine accepts a string and pushes it onto the tty
- * input queue, as if the user had typed it.
- * The input is a file descriptor that points to a tty, and
- * a pointer to the string.
- */
- pushback(fd, str)
- int fd;
- char *str;
- {
- char *s1;
-
- for(s1=str; *s1; ioctl( fd, TIOCSTI, s1++));
- }
-
-
- /* **************************************************************
- * getpending - get pending chars from tty, then push them back
- *
- * This routine grabs chars pending on a specified file
- * descriptor, puts them into the specified buffer, and pushes
- * them back onto the tty input queue.
- * The buffer passed by the caller had BETTER be long enough,
- * or everything gets munched.
- * If the parameter no_pushback is non-zero, the characters are
- * not pushed back.
- * The number of characters obtained is returned.
- */
- getpending(fd, buf, buflen, no_pushback)
- int fd;
- char *buf;
- int buflen, no_pushback;
- {
- int i,j;
- char x = '\n';
-
- ioctl(fd, FIONREAD, &i);
- if (i <= 0) return(0);
- j = read(fd, buf, buflen);
- buf[j-1] = '\0';
- for(i = j-2; buf[i] > '\030' ; buf[i--] = '\0' );
- if (i <= 0) return(0);
- if ( !no_pushback) pushback(fd, buf);
- return(i);
- }
-
-
- /* **************************************************************
- * init_funky - initialize funky stuff, and save startup values
- *
- * This routine starts up breaking for ESC, and
- * saves the initial tchars structure.
- */
- init_funky()
- {
- char *malloc();
-
- if ( isatty(0) ) {
- is_tty = 1;
- init_tchars = (struct tchars *) malloc( sizeof(struct tchars));
- here_tchars = (struct tchars *) malloc( sizeof(struct tchars));
- ioctl(0,TIOCGETC,init_tchars);
- ioctl(0,TIOCGETC,here_tchars);
- here_tchars->t_brkc = '\033';
- ioctl(0,TIOCSETC,here_tchars);
- }
-
- return;
- }
-
-
- /* **************************************************************
- * read_gets: do a gets by read(2)ing a line
- *
- * Read a string into a buffer, from the given file
- * descriptor. There are four arguments:
- *
- * fd file descriptor (usually 0)
- * buf char * to buffer
- * blen buffer length in bytes
- * spec do special ^[ and ^D processing
- *
- * If the special processing is enabled, ESC invokes helpname
- * completion, and ^D invokes possible completion listing.
- * When the user finally inputs a line that does not require
- * special processing, it is returned as a string to caller.
- * If anything goes wrong, or a true EOF is given, -1 is
- * returned.
- * When special processing is not enabled, the input line is
- * simply returned to the caller as a string.
- */
- read_gets(fd, buf, blen, do_special)
- int fd, blen, do_special;
- char *buf;
- {
- char *s1, *s2, endc;
- static char bufcopy[MAXLINELEN];
- static char *wvec[MAXMATCHES];
- int i,j,k;
-
-
- for(endc = '\0'; endc != LF ; ) {
- fflush(stdout);
- i = read(fd, buf, blen);
-
- /* now, having read data, analyze it for special stuff */
- if (i <= 0) return(-1);
- else {
- s1 = buf + (i - 1);
- if (*s1 == ESC || *s1 == LF || *s1 == RET) {
- endc = (*s1 == ESC)?(*s1):(LF);
- *s1 = '\0';
- }
- else {
- *++s1 = '\0';
- endc = *s1;
- }
- for(s1 = buf + (strlen(buf) - 1);
- *s1 == ' ' || *s1 == ' ';
- *s1-- = '\0');
- for(s1 = buf; *s1 == ' ' || *s1 == ' '; s1++);
-
- if (endc == LF || endc == RET || do_special == 0) return(i-1);
- else {
- *gbl_match = '\0';
-
- /* if this is a non-topic command, just beep */
- if ( index( SPEC_CHARS, *s1) ) {
- fputs(" ",stdout);
- for(s1 = buf; *s1; s1++) fputs("",stdout);
- fflush(stdout);
- pushback(stdin->_file,buf);
- continue;
- }
- else
- /* do special stuff here */
- if (endc == ESC) {
- strcpy(bufcopy,buf);
- i = makewvec(bufcopy, wvec, MAXMATCHES);
- help1("", wvec, 0, 0, ESC_COMP);
- fputs(" ",stdout);
- for(s1 = buf; *s1; s1++) fputs("",stdout);
- fflush(stdout);
- pushback(stdin->_file,buf);
- if ( *gbl_match ) {
- pushback(stdin->_file,(gbl_match + strlen(wvec[i-1])));
- }
- else fputs("",stdout);
- fflush(stdout);
- }
- else
- if (endc == '\0') { /* must have been eof */
- strcpy(bufcopy,buf);
- i = makewvec(bufcopy, wvec, MAXMATCHES);
- help1("" , wvec, 0, 0, CTRLD_COMP);
- printf("\n%s ",gbl_ppt);
- if (*gbl_match == '\0') fputs("", stdout);
- fflush(stdout);
- pushback(stdin->_file,buf);
-
- }
- }
- }
- }
- }
-
-
-
- #endif
-