[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.3

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

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