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

1.1       maekawa     1: #ifndef lint
1.1.1.2 ! maekawa     2: static char *RCSid = "$Id: help.c,v 1.8.2.2 1999/10/11 21:24:20 lhecking 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: #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:                }
1.1.1.2 ! maekawa   565:                if (pos >= PER_LINE) {
1.1       maekawa   566:                    (void) strcat(line, "\n");
                    567:                    OutLine(line);
                    568:                    *line = NUL;
                    569:                    pos = 0;
                    570:                }
1.1.1.2 ! maekawa   571: #define FIRSTCOL       4
        !           572: #define COLLENGTH      18
        !           573:
1.1       maekawa   574:                /* adapted by DvdSchaaf */
1.1.1.2 ! maekawa   575:                if (pos == 0)
        !           576:                    spacelen = FIRSTCOL;
        !           577:                for (ispacelen = 0; ispacelen < spacelen; ispacelen++)
        !           578:                    (void) strcat(line, " ");
        !           579:                (void) strncat(line, start, sublen);
        !           580:                spacelen = COLLENGTH - sublen;
        !           581:
        !           582:                while (spacelen <= 0) {
        !           583:                    spacelen += COLLENGTH;
        !           584:                        pos++;
1.1       maekawa   585:                }
1.1.1.2 ! maekawa   586:
1.1       maekawa   587:                pos++;
                    588:                prev = start;
                    589:            }
                    590:        } else {
                    591:            /* new topic */
                    592:            break;
                    593:        }
                    594:     }
                    595:
                    596:     /* put out the last line */
                    597:     if (subt > 0 && pos > 0) {
                    598:        (void) strcat(line, "\n");
                    599:        OutLine(line);
                    600:     }
                    601: /*
                    602:    if (subt == 0) {
                    603:    OutLine("\n");
                    604:    OutLine("No subtopics available\n");
                    605:    }
                    606:  */
                    607:
                    608:     if (subtopics)
                    609:        *subtopics = (subt != 0);
                    610: }
                    611:
                    612:
                    613: /* StartOutput:
                    614:  * Open a file pointer to a pipe to user's $PAGER, if there is one,
                    615:  * otherwise use our own pager.
                    616:  */
                    617: void StartOutput()
                    618: {
                    619: #if defined(PIPES)
                    620:     char *pager_name = getenv("PAGER");
                    621:
                    622:     if (pager_name != NULL && *pager_name != NUL)
                    623:        if ((outfile = popen(pager_name, "w")) != (FILE *) NULL)
                    624:            return;             /* success */
                    625:     outfile = stderr;
                    626:     /* fall through to built-in pager */
                    627: #endif
                    628:
                    629:     /* built-in pager */
                    630:     pagelines = 0;
                    631: }
                    632:
                    633: #if defined(ATARI) || defined(MTOS)
                    634: # ifndef READLINE
                    635: #  error cannot compile atari versions without -DREADLINE
                    636: # endif
                    637: #endif
                    638:
                    639: /* write a line of help output  */
                    640: /* line should contain only one \n, at the end */
                    641: void OutLine(line)
                    642: char *line;
                    643: {
                    644:     int c;                     /* dummy input char */
                    645: #if defined(PIPES)
                    646:     if (outfile != stderr) {
                    647:        fputs(line, outfile);
                    648:        return;
                    649:     }
                    650: #endif
                    651:
                    652:     /* built-in dumb pager */
                    653:     /* leave room for prompt line */
                    654:     if (pagelines >= SCREENSIZE - 2) {
                    655:        fputs("Press return for more: ", stderr);
                    656: #if defined(ATARI) || defined(MTOS)
                    657:        do
                    658:            c = tos_getch();
                    659:        while (c != '\x04' && c != '\r' && c != '\n');
                    660: #else
                    661:        do
                    662:            c = getchar();
                    663:        while (c != EOF && c != '\n');
                    664: #endif
                    665:        pagelines = 0;
                    666:     }
                    667:     fputs(line, stderr);
                    668:     pagelines++;
                    669: }
                    670:
                    671: void EndOutput()
                    672: {
                    673: #if defined(PIPES)
                    674:     if (outfile != stderr)
                    675:        (void) pclose(outfile);
                    676: #endif
                    677: }

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