[BACK]Return to help.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot

Annotation of OpenXM_contrib/gnuplot/help.c, Revision 1.1

1.1     ! maekawa     1: #ifndef lint
        !             2: static char *RCSid = "$Id: help.c,v 1.29 1998/04/14 00:15:36 drd Exp $";
        !             3: #endif
        !             4:
        !             5: /* GNUPLOT - help.c */
        !             6:
        !             7: /*[
        !             8:  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
        !             9:  *
        !            10:  * Permission to use, copy, and distribute this software and its
        !            11:  * documentation for any purpose with or without fee is hereby granted,
        !            12:  * provided that the above copyright notice appear in all copies and
        !            13:  * that both that copyright notice and this permission notice appear
        !            14:  * in supporting documentation.
        !            15:  *
        !            16:  * Permission to modify the software is granted, but not the right to
        !            17:  * distribute the complete modified source code.  Modifications are to
        !            18:  * be distributed as patches to the released version.  Permission to
        !            19:  * distribute binaries produced by compiling modified sources is granted,
        !            20:  * provided you
        !            21:  *   1. distribute the corresponding source modifications from the
        !            22:  *    released version in the form of a patch file along with the binaries,
        !            23:  *   2. add special version identification to distinguish your version
        !            24:  *    in addition to the base release version number,
        !            25:  *   3. provide your name and address as the primary contact for the
        !            26:  *    support of your modified version, and
        !            27:  *   4. retain our contact information in regard to use of the base
        !            28:  *    software.
        !            29:  * Permission to distribute the released version of the source code along
        !            30:  * with corresponding source modifications in the form of a patch file is
        !            31:  * granted with same provisions 2 through 4 for binary distributions.
        !            32:  *
        !            33:  * This software is provided "as is" without express or implied warranty
        !            34:  * to the extent permitted by applicable law.
        !            35: ]*/
        !            36:
        !            37: #include "plot.h"
        !            38:
        !            39: #define        SAME    0               /* for strcmp() */
        !            40:
        !            41: #include "help.h"              /* values passed back */
        !            42:
        !            43: void int_error __PROTO((char str[], int t_num));
        !            44:
        !            45: #if defined(__EMX__) || defined(DJGPP) || defined(DOS386)
        !            46: /* we have plenty of memory under __EMX__ or DJGPP */
        !            47: # ifdef MSDOS
        !            48: #  undef MSDOS
        !            49: # endif
        !            50: #endif
        !            51:
        !            52: /*
        !            53:  ** help -- help subsystem that understands defined keywords
        !            54:  **
        !            55:  ** Looks for the desired keyword in the help file at runtime, so you
        !            56:  ** can give extra help or supply local customizations by merely editing
        !            57:  ** the help file.
        !            58:  **
        !            59:  ** The original (single-file) idea and algorithm is by John D. Johnson,
        !            60:  ** Hewlett-Packard Company.  Thanx and a tip of the Hatlo hat!
        !            61:  **
        !            62:  ** Much extension by David Kotz for use in gnutex, and then in gnuplot.
        !            63:  ** Added output paging support, both unix and builtin. Rewrote completely
        !            64:  ** to read helpfile into memory, avoiding reread of help file. 12/89.
        !            65:  **
        !            66:  ** Modified by Russell Lang to avoid reading completely into memory
        !            67:  ** if MSDOS defined.  This uses much less memory.  6/91
        !            68:  **
        !            69:  ** The help file looks like this (the question marks are really in column 1):
        !            70:  **
        !            71:  **   ?topic
        !            72:  **   This line is printed when the user wants help on "topic".
        !            73:  **   ?keyword
        !            74:  **   ?Keyword
        !            75:  **   ?KEYWORD
        !            76:  **   These lines will be printed on the screen if the user wanted
        !            77:  **   help on "keyword", "Keyword", or "KEYWORD".  No casefolding is
        !            78:  **   done on the keywords.
        !            79:  **   ?subject
        !            80:  **   ?alias
        !            81:  **   This line is printed for help on "subject" and "alias".
        !            82:  **   ?
        !            83:  **   ??
        !            84:  **   Since there is a null keyword for this line, this section
        !            85:  **   is printed when the user wants general help (when a help
        !            86:  **   keyword isn't given).  A command summary is usually here.
        !            87:  **   Notice that the null keyword is equivalent to a "?" keyword
        !            88:  **   here, because of the '?' and '??' topic lines above.
        !            89:  **   If multiple keywords are given, the first is considered the
        !            90:  **   'primary' keyword. This affects a listing of available topics.
        !            91:  **   ?last-subject
        !            92:  **   Note that help sections are terminated by the start of the next
        !            93:  **   '?' entry or by EOF.  So you can't have a leading '?' on a line
        !            94:  **   of any help section.  You can re-define the magic character to
        !            95:  **   recognize in column 1, though, if '?' is too useful.  (Try ^A.)
        !            96:  */
        !            97:
        !            98: #define        KEYFLAG '?'             /* leading char in help file topic lines */
        !            99:
        !           100: /*
        !           101:  ** Calling sequence:
        !           102:  **   int result;             # 0 == success
        !           103:  **   char *keyword;          # topic to give help on
        !           104:  **   char *pathname;         # path of help file
        !           105:  **   int subtopics;          # set to TRUE if only subtopics to be listed
        !           106:  **                           # returns TRUE if subtopics were found
        !           107:  **   result = help(keyword, pathname, &subtopics);
        !           108:  ** Sample:
        !           109:  **   cmd = "search\n";
        !           110:  **   helpfile = "/usr/local/lib/program/program.help";
        !           111:  **   subtopics = FALSE;
        !           112:  **   if (help(cmd, helpfile, &subtopics) != H_FOUND)
        !           113:  **           printf("Sorry, no help for %s", cmd);
        !           114:  **
        !           115:  **
        !           116:  ** Speed this up by replacing the stdio calls with open/close/read/write.
        !           117:  */
        !           118: #ifdef WDLEN
        !           119: # define PATHSIZE WDLEN
        !           120: #else
        !           121: # define PATHSIZE BUFSIZ
        !           122: #endif
        !           123:
        !           124: typedef struct line_s LINEBUF;
        !           125: struct line_s {
        !           126:     char *line;                        /* the text of this line */
        !           127:     LINEBUF *next;             /* the next line */
        !           128: };
        !           129:
        !           130: typedef struct linkey_s LINKEY;
        !           131: struct linkey_s {
        !           132:     char *key;                 /* the name of this key */
        !           133:     long pos;                  /* ftell position */
        !           134:     LINEBUF *text;             /* the text for this key */
        !           135:     TBOOLEAN primary;          /* TRUE -> is a primary name for a text block */
        !           136:     LINKEY *next;              /* the next key in linked list */
        !           137: };
        !           138:
        !           139: typedef struct key_s KEY;
        !           140: struct key_s {
        !           141:     char *key;                 /* the name of this key */
        !           142:     long pos;                  /* ftell position */
        !           143:     LINEBUF *text;             /* the text for this key */
        !           144:     TBOOLEAN primary;          /* TRUE -> is a primary name for a text block */
        !           145: };
        !           146: static LINKEY *keylist = NULL; /* linked list of keys */
        !           147: static KEY *keys = NULL;       /* array of keys */
        !           148: static int keycount = 0;       /* number of keys */
        !           149: static FILE *helpfp = NULL;
        !           150:
        !           151: static int LoadHelp __PROTO((char *path));
        !           152: static void sortkeys __PROTO((void));
        !           153: static int keycomp __PROTO((struct key_s * a, struct key_s * b));
        !           154: static LINEBUF *storeline __PROTO((char *text));
        !           155: static LINKEY *storekey __PROTO((char *key));
        !           156: static KEY *FindHelp __PROTO((char *keyword));
        !           157: static TBOOLEAN Ambiguous __PROTO((struct key_s * key, int len));
        !           158:
        !           159: /* Help output */
        !           160: static void PrintHelp __PROTO((struct key_s * key, int *subtopics));
        !           161: static void ShowSubtopics __PROTO((struct key_s * key, int *subtopics));
        !           162:
        !           163: #if defined(PIPES)
        !           164: static FILE *outfile;          /* for unix pager, if any */
        !           165: #endif
        !           166: static int pagelines;          /* count for builtin pager */
        !           167: #define SCREENSIZE 24          /* lines on screen (most have at least 24) */
        !           168:
        !           169: /* help:
        !           170:  * print a help message
        !           171:  * also print available subtopics, if subtopics is TRUE
        !           172:  */
        !           173: int help(keyword, path, subtopics)
        !           174: char *keyword;                 /* on this topic */
        !           175: char *path;                    /* from this file */
        !           176: TBOOLEAN *subtopics;           /* (in) - subtopics only? */
        !           177:                                /* (out) - are there subtopics? */
        !           178: {
        !           179:     static char oldpath[PATHSIZE] = "";                /* previous help file */
        !           180:     int status;                        /* result of LoadHelp */
        !           181:     KEY *key;                  /* key that matches keyword */
        !           182:
        !           183:     /*
        !           184:      ** Load the help file if necessary (say, first time we enter this routine,
        !           185:      ** or if the help file changes from the last time we were called).
        !           186:      ** Also may occur if in-memory copy was freed.
        !           187:      ** Calling routine may access errno to determine cause of H_ERROR.
        !           188:      */
        !           189:     errno = 0;
        !           190:     if (strncmp(oldpath, path, PATHSIZE) != SAME)
        !           191:        FreeHelp();
        !           192:     if (keys == NULL) {
        !           193:        status = LoadHelp(path);
        !           194:        if (status == H_ERROR)
        !           195:            return (status);
        !           196:
        !           197:        /* save the new path in oldpath */
        !           198:        safe_strncpy(oldpath, path, PATHSIZE);
        !           199:     }
        !           200:     /* look for the keyword in the help file */
        !           201:     key = FindHelp(keyword);
        !           202:     if (key != NULL) {
        !           203:        /* found the keyword: print help and return */
        !           204:        PrintHelp(key, subtopics);
        !           205:        status = H_FOUND;
        !           206:     } else {
        !           207:        status = H_NOTFOUND;
        !           208:     }
        !           209:
        !           210:     return (status);
        !           211: }
        !           212:
        !           213: /* we only read the file once, into memory
        !           214:  * except for MSDOS when we don't read all the file -
        !           215:  * just the keys and location of the text
        !           216:  */
        !           217: static int LoadHelp(path)
        !           218: char *path;
        !           219: {
        !           220:     LINKEY *key;               /* this key */
        !           221:     long pos = 0;              /* ftell location within help file */
        !           222:     char buf[BUFSIZ];          /* line from help file */
        !           223:     LINEBUF *head;             /* head of text list  */
        !           224:     LINEBUF *firsthead = NULL;
        !           225:     TBOOLEAN primary;          /* first ? line of a set is primary */
        !           226:     TBOOLEAN flag;
        !           227:
        !           228:     if ((helpfp = fopen(path, "r")) == NULL) {
        !           229:        /* can't open help file, so error exit */
        !           230:        return (H_ERROR);
        !           231:     }
        !           232:     /*
        !           233:      ** The help file is open.  Look in there for the keyword.
        !           234:      */
        !           235:     if (!fgets(buf, BUFSIZ - 1, helpfp) || *buf != KEYFLAG)
        !           236:        return (H_ERROR);       /* it is probably not the .gih file */
        !           237:
        !           238:     while (!feof(helpfp)) {
        !           239:        /*
        !           240:         ** Make an entry for each synonym keyword
        !           241:         */
        !           242:        primary = TRUE;
        !           243:        while (buf[0] == KEYFLAG) {
        !           244:            key = storekey(buf + 1);    /* store this key */
        !           245:            key->primary = primary;
        !           246:            key->text = NULL;   /* fill in with real value later */
        !           247:            key->pos = 0;       /* fill in with real value later */
        !           248:            primary = FALSE;
        !           249:            pos = ftell(helpfp);
        !           250:            if (fgets(buf, BUFSIZ - 1, helpfp) == (char *) NULL)
        !           251:                break;
        !           252:        }
        !           253:        /*
        !           254:         ** Now store the text for this entry.
        !           255:         ** buf already contains the first line of text.
        !           256:         */
        !           257: #ifndef MSDOS
        !           258:        firsthead = storeline(buf);
        !           259:        head = firsthead;
        !           260: #endif
        !           261:        while ((fgets(buf, BUFSIZ - 1, helpfp) != (char *) NULL)
        !           262:               && (buf[0] != KEYFLAG)) {
        !           263: #ifndef MSDOS
        !           264:            /* save text line */
        !           265:            head->next = storeline(buf);
        !           266:            head = head->next;
        !           267: #endif
        !           268:        }
        !           269:        /* make each synonym key point to the same text */
        !           270:        do {
        !           271:            key->pos = pos;
        !           272:            key->text = firsthead;
        !           273:            flag = key->primary;
        !           274:            key = key->next;
        !           275:        } while (flag != TRUE && key != NULL);
        !           276:     }
        !           277: #ifndef MSDOS
        !           278:     (void) fclose(helpfp);
        !           279: #endif
        !           280:
        !           281:     /* we sort the keys so we can use binary search later */
        !           282:     sortkeys();
        !           283:     return (H_FOUND);          /* ok */
        !           284: }
        !           285:
        !           286: /* make a new line buffer and save this string there */
        !           287: static LINEBUF *
        !           288:  storeline(text)
        !           289: char *text;
        !           290: {
        !           291:     LINEBUF *new;
        !           292:
        !           293:     new = (LINEBUF *) malloc(sizeof(LINEBUF));
        !           294:     if (new == NULL)
        !           295:        int_error("not enough memory to store help file", -1);
        !           296:     if (text != NULL) {
        !           297:        new->line = (char *) malloc((unsigned int) (strlen(text) + 1));
        !           298:        if (new->line == NULL)
        !           299:            int_error("not enough memory to store help file", -1);
        !           300:        (void) strcpy(new->line, text);
        !           301:     } else
        !           302:        new->line = NULL;
        !           303:
        !           304:     new->next = NULL;
        !           305:
        !           306:     return (new);
        !           307: }
        !           308:
        !           309: /* Add this keyword to the keys list, with the given text */
        !           310: static LINKEY *
        !           311:  storekey(key)
        !           312: char *key;
        !           313: {
        !           314:     LINKEY *new;
        !           315:
        !           316:     key[strlen(key) - 1] = NUL;        /* cut off \n  */
        !           317:
        !           318:     new = (LINKEY *) malloc(sizeof(LINKEY));
        !           319:     if (new == NULL)
        !           320:        int_error("not enough memory to store help file", -1);
        !           321:     new->key = (char *) malloc((unsigned int) (strlen(key) + 1));
        !           322:     if (new->key == NULL)
        !           323:        int_error("not enough memory to store help file", -1);
        !           324:     (void) strcpy(new->key, key);
        !           325:
        !           326:     /* add to front of list */
        !           327:     new->next = keylist;
        !           328:     keylist = new;
        !           329:     keycount++;
        !           330:     return (new);
        !           331: }
        !           332:
        !           333: /* we sort the keys so we can use binary search later */
        !           334: /* We have a linked list of keys and the number.
        !           335:  * to sort them we need an array, so we reform them into an array,
        !           336:  * and then throw away the list.
        !           337:  */
        !           338: static void sortkeys()
        !           339: {
        !           340:     LINKEY *p, *n;             /* pointers to linked list */
        !           341:     int i;                     /* index into key array */
        !           342:
        !           343:     /* allocate the array */
        !           344:     keys = (KEY *) malloc((unsigned int) ((keycount + 1) * sizeof(KEY)));
        !           345:     if (keys == NULL)
        !           346:        int_error("not enough memory to store help file", -1);
        !           347:
        !           348:     /* copy info from list to array, freeing list */
        !           349:     for (p = keylist, i = 0; p != NULL; p = n, i++) {
        !           350:        keys[i].key = p->key;
        !           351:        keys[i].pos = p->pos;
        !           352:        keys[i].text = p->text;
        !           353:        keys[i].primary = p->primary;
        !           354:        n = p->next;
        !           355:        free((char *) p);
        !           356:     }
        !           357:
        !           358:     /* a null entry to terminate subtopic searches */
        !           359:     keys[keycount].key = NULL;
        !           360:     keys[keycount].pos = 0;
        !           361:     keys[keycount].text = NULL;
        !           362:
        !           363:     /* sort the array */
        !           364:     /* note that it only moves objects of size (two pointers + long + int) */
        !           365:     /* it moves no strings */
        !           366:     qsort((char *) keys, keycount, sizeof(KEY), (sortfunc) keycomp);
        !           367: }
        !           368:
        !           369: static int keycomp(a, b)
        !           370: KEY *a, *b;
        !           371: {
        !           372:     return (strcmp(a->key, b->key));
        !           373: }
        !           374:
        !           375: /* Free the help file from memory. */
        !           376: /* May be called externally if space is needed */
        !           377: void FreeHelp()
        !           378: {
        !           379:     int i;                     /* index into keys[] */
        !           380:     LINEBUF *t, *next;
        !           381:
        !           382:     if (keys == NULL)
        !           383:        return;
        !           384:
        !           385:     for (i = 0; i < keycount; i++) {
        !           386:        free((char *) keys[i].key);
        !           387:        if (keys[i].primary)    /* only try to release text once! */
        !           388:            for (t = keys[i].text; t != NULL; t = next) {
        !           389:                free((char *) t->line);
        !           390:                next = t->next;
        !           391:                free((char *) t);
        !           392:            }
        !           393:     }
        !           394:     free((char *) keys);
        !           395:     keys = NULL;
        !           396:     keycount = 0;
        !           397: #ifdef MSDOS
        !           398:     (void) fclose(helpfp);
        !           399: #endif
        !           400: }
        !           401:
        !           402: /* FindHelp:
        !           403:  *  Find the key that matches the keyword.
        !           404:  *  The keys[] array is sorted by key.
        !           405:  *  We could use a binary search, but a linear search will aid our
        !           406:  *  attempt to allow abbreviations. We search for the first thing that
        !           407:  *  matches all the text we're given. If not an exact match, then
        !           408:  *  it is an abbreviated match, and there must be no other abbreviated
        !           409:  *  matches -- for if there are, the abbreviation is ambiguous.
        !           410:  *  We print the ambiguous matches in that case, and return not found.
        !           411:  */
        !           412: static KEY *                   /* NULL if not found */
        !           413:  FindHelp(keyword)
        !           414: char *keyword;                 /* string we look for */
        !           415: {
        !           416:     KEY *key;
        !           417:     int len = strlen(keyword);
        !           418:     int compare;
        !           419:
        !           420:     for (key = keys, compare = 1; key->key != NULL && compare > 0; key++) {
        !           421:        compare = strncmp(keyword, key->key, len);
        !           422:        if (compare == 0)       /* we have a match! */
        !           423:            if (!Ambiguous(key, len)) {
        !           424:                /* non-ambiguous abbreviation */
        !           425:                (void) strcpy(keyword, key->key);       /* give back the full spelling */
        !           426:                return (key);   /* found!! */
        !           427:            }
        !           428:     }
        !           429:
        !           430:     /* not found, or ambiguous */
        !           431:     return (NULL);
        !           432: }
        !           433:
        !           434: /* Ambiguous:
        !           435:  * Check the key for ambiguity up to the given length.
        !           436:  * It is ambiguous if it is not a complete string and there are other
        !           437:  * keys following it with the same leading substring.
        !           438:  */
        !           439: static TBOOLEAN
        !           440:  Ambiguous(key, len)
        !           441: KEY *key;
        !           442: int len;
        !           443: {
        !           444:     char *first;
        !           445:     char *prev;
        !           446:     TBOOLEAN status = FALSE;   /* assume not ambiguous */
        !           447:     int compare;
        !           448:     int sublen;
        !           449:
        !           450:     if (key->key[len] == NUL)
        !           451:        return (FALSE);
        !           452:
        !           453:     for (prev = first = key->key, compare = 0, key++;
        !           454:         key->key != NULL && compare == 0; key++) {
        !           455:        compare = strncmp(first, key->key, len);
        !           456:        if (compare == 0) {
        !           457:            /* So this key matches the first one, up to len.
        !           458:             * But is it different enough from the previous one
        !           459:             * to bother printing it as a separate choice?
        !           460:             */
        !           461:            sublen = instring(prev + len, ' ');
        !           462:            if (strncmp(key->key, prev, len + sublen) != 0) {
        !           463:                /* yup, this is different up to the next space */
        !           464:                if (!status) {
        !           465:                    /* first one we have printed is special */
        !           466:                    fprintf(stderr,
        !           467:                         "Ambiguous request '%.*s'; possible matches:\n",
        !           468:                            len, first);
        !           469:                    fprintf(stderr, "\t%s\n", prev);
        !           470:                    status = TRUE;
        !           471:                }
        !           472:                fprintf(stderr, "\t%s\n", key->key);
        !           473:                prev = key->key;
        !           474:            }
        !           475:        }
        !           476:     }
        !           477:
        !           478:     return (status);
        !           479: }
        !           480:
        !           481: /* PrintHelp:
        !           482:  * print the text for key
        !           483:  */
        !           484: static void PrintHelp(key, subtopics)
        !           485: KEY *key;
        !           486: TBOOLEAN *subtopics;           /* (in) - subtopics only? */
        !           487:                                /* (out) - are there subtopics? */
        !           488: {
        !           489:     LINEBUF *t;
        !           490: #ifdef MSDOS
        !           491:     char buf[BUFSIZ];          /* line from help file */
        !           492: #endif
        !           493:
        !           494:     StartOutput();
        !           495:
        !           496:     if (subtopics == NULL || !*subtopics) {
        !           497: #ifdef MSDOS
        !           498:        fseek(helpfp, key->pos, 0);
        !           499:        while ((fgets(buf, BUFSIZ - 1, helpfp) != (char *) NULL)
        !           500:               && (buf[0] != KEYFLAG)) {
        !           501:            OutLine(buf);
        !           502:        }
        !           503: #else
        !           504:        for (t = key->text; t != NULL; t = t->next)
        !           505:            OutLine(t->line);   /* print text line */
        !           506: #endif
        !           507:     }
        !           508:     ShowSubtopics(key, subtopics);
        !           509:     OutLine("\n");
        !           510:
        !           511:     EndOutput();
        !           512: }
        !           513:
        !           514:
        !           515: /* ShowSubtopics:
        !           516:  *  Print a list of subtopic names
        !           517:  */
        !           518: #define PER_LINE 4
        !           519:
        !           520: static void ShowSubtopics(key, subtopics)
        !           521: KEY *key;                      /* the topic */
        !           522: TBOOLEAN *subtopics;           /* (out) are there any subtopics */
        !           523: {
        !           524:     int subt = 0;              /* printed any subtopics yet? */
        !           525:     KEY *subkey;               /* subtopic key */
        !           526:     int len;                   /* length of key name */
        !           527:     char line[BUFSIZ];         /* subtopic output line */
        !           528:     char *start;               /* position of subname in key name */
        !           529:     int sublen;                        /* length of subname */
        !           530:     int pos = 0;
        !           531:     int spacelen = 0;          /* Moved from inside for() loop */
        !           532:     char *prev = NULL;         /* the last thing we put on the list */
        !           533:
        !           534:     *line = NUL;
        !           535:     len = strlen(key->key);
        !           536:
        !           537:     for (subkey = key + 1; subkey->key != NULL; subkey++) {
        !           538:        int ispacelen = 0;
        !           539:        if (strncmp(subkey->key, key->key, len) == 0) {
        !           540:            /* find this subtopic name */
        !           541:            start = subkey->key + len;
        !           542:            if (len > 0) {
        !           543:                if (*start == ' ')
        !           544:                    start++;    /* skip space */
        !           545:                else
        !           546:                    break;      /* not the same topic after all  */
        !           547:            } else {
        !           548:                /* here we are looking for main topics */
        !           549:                if (!subkey->primary)
        !           550:                    continue;   /* not a main topic */
        !           551:            }
        !           552:            sublen = instring(start, ' ');
        !           553:            if (prev == NULL || strncmp(start, prev, sublen) != 0) {
        !           554:                if (subt == 0) {
        !           555:                    subt++;
        !           556:                    if (len)
        !           557:                        (void) sprintf(line, "\nSubtopics available for %s:\n",
        !           558:                                       key->key);
        !           559:                    else
        !           560:                        (void) sprintf(line, "\nHelp topics available:\n");
        !           561:                    OutLine(line);
        !           562:                    *line = NUL;
        !           563:                    pos = 0;
        !           564:                }
        !           565:                if (pos == PER_LINE) {
        !           566:                    (void) strcat(line, "\n");
        !           567:                    OutLine(line);
        !           568:                    *line = NUL;
        !           569:                    pos = 0;
        !           570:                }
        !           571:                /* adapted by DvdSchaaf */
        !           572:                {
        !           573: #define FIRSTCOL       6
        !           574: #define COLLENGTH      15
        !           575:
        !           576:                    if (pos == 0)
        !           577:                        spacelen = FIRSTCOL;
        !           578:                    for (ispacelen = 0;
        !           579:                         ispacelen < spacelen; ispacelen++)
        !           580:                        (void) strcat(line, " ");
        !           581:                    /* commented out *
        !           582:                       (void) strcat(line, "\t");
        !           583:                     */
        !           584:                    (void) strncat(line, start, sublen);
        !           585:                    spacelen = COLLENGTH - sublen;
        !           586:                    if (spacelen <= 0)
        !           587:                        spacelen = 1;
        !           588:                }
        !           589:                pos++;
        !           590:                prev = start;
        !           591:            }
        !           592:        } else {
        !           593:            /* new topic */
        !           594:            break;
        !           595:        }
        !           596:     }
        !           597:
        !           598:     /* put out the last line */
        !           599:     if (subt > 0 && pos > 0) {
        !           600:        (void) strcat(line, "\n");
        !           601:        OutLine(line);
        !           602:     }
        !           603: /*
        !           604:    if (subt == 0) {
        !           605:    OutLine("\n");
        !           606:    OutLine("No subtopics available\n");
        !           607:    }
        !           608:  */
        !           609:
        !           610:     if (subtopics)
        !           611:        *subtopics = (subt != 0);
        !           612: }
        !           613:
        !           614:
        !           615: /* StartOutput:
        !           616:  * Open a file pointer to a pipe to user's $PAGER, if there is one,
        !           617:  * otherwise use our own pager.
        !           618:  */
        !           619: void StartOutput()
        !           620: {
        !           621: #if defined(PIPES)
        !           622:     char *pager_name = getenv("PAGER");
        !           623:
        !           624:     if (pager_name != NULL && *pager_name != NUL)
        !           625:        if ((outfile = popen(pager_name, "w")) != (FILE *) NULL)
        !           626:            return;             /* success */
        !           627:     outfile = stderr;
        !           628:     /* fall through to built-in pager */
        !           629: #endif
        !           630:
        !           631:     /* built-in pager */
        !           632:     pagelines = 0;
        !           633: }
        !           634:
        !           635: #if defined(ATARI) || defined(MTOS)
        !           636: # ifndef READLINE
        !           637: #  error cannot compile atari versions without -DREADLINE
        !           638: # endif
        !           639: #endif
        !           640:
        !           641: /* write a line of help output  */
        !           642: /* line should contain only one \n, at the end */
        !           643: void OutLine(line)
        !           644: char *line;
        !           645: {
        !           646:     int c;                     /* dummy input char */
        !           647: #if defined(PIPES)
        !           648:     if (outfile != stderr) {
        !           649:        fputs(line, outfile);
        !           650:        return;
        !           651:     }
        !           652: #endif
        !           653:
        !           654:     /* built-in dumb pager */
        !           655:     /* leave room for prompt line */
        !           656:     if (pagelines >= SCREENSIZE - 2) {
        !           657:        fputs("Press return for more: ", stderr);
        !           658: #if defined(ATARI) || defined(MTOS)
        !           659:        do
        !           660:            c = tos_getch();
        !           661:        while (c != '\x04' && c != '\r' && c != '\n');
        !           662: #else
        !           663:        do
        !           664:            c = getchar();
        !           665:        while (c != EOF && c != '\n');
        !           666: #endif
        !           667:        pagelines = 0;
        !           668:     }
        !           669:     fputs(line, stderr);
        !           670:     pagelines++;
        !           671: }
        !           672:
        !           673: void EndOutput()
        !           674: {
        !           675: #if defined(PIPES)
        !           676:     if (outfile != stderr)
        !           677:        (void) pclose(outfile);
        !           678: #endif
        !           679: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>