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

Annotation of OpenXM_contrib/gnuplot/term.c, Revision 1.1.1.1

1.1       maekawa     1: #ifndef lint
                      2: static char *RCSid = "$Id: term.c,v 1.104 1998/06/18 14:55:19 ddenholm Exp $";
                      3: #endif
                      4:
                      5: /* GNUPLOT - term.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:
                     38:  /* This module is responsible for looking after the terminal
                     39:   * drivers at the lowest level. Only this module (should)
                     40:   * know about all the various rules about interpreting
                     41:   * the terminal capabilities exported by the terminal
                     42:   * drivers in the table.
                     43:   *
                     44:   * Note that, as far as this module is concerned, a
                     45:   * terminal session lasts only until _either_ terminal
                     46:   * or output file changes. Before either is changed,
                     47:   * the terminal is shut down.
                     48:   *
                     49:   * Entry points : (see also term/README)
                     50:   *
                     51:   * term_set_output() : called when  set output  invoked
                     52:   *
                     53:   * term_init()  : optional. Prepare the terminal for first
                     54:   *                use. It protects itself against subsequent calls.
                     55:   *
                     56:   * term_start_plot() : called at start of graph output. Calls term_init
                     57:   *                     if necessary
                     58:   *
                     59:   * term_apply_lp_properties() : apply linewidth settings
                     60:   *
                     61:   * term_end_plot() : called at the end of a plot
                     62:   *
                     63:   * term_reset() : called during int_error handling, to shut
                     64:   *                terminal down cleanly
                     65:   *
                     66:   * term_start_multiplot() : called by   set multiplot
                     67:   *
                     68:   * term_end_multiplot() : called by  set nomultiplot
                     69:   *
                     70:   * term_check_multiplot_okay() : called just before an interactive
                     71:   *                        prompt is issued while in multiplot mode,
                     72:   *                        to allow terminal to suspend if necessary,
                     73:   *                        Raises an error if interactive multiplot
                     74:   *                       is not supported.
                     75:   */
                     76:
                     77: #include "plot.h"
                     78: #include "bitmap.h"
                     79: #include "setshow.h"
                     80: #include "driver.h"
                     81:
                     82: #ifdef _Windows
                     83: FILE *open_printer __PROTO((void));    /* in wprinter.c */
                     84: void close_printer __PROTO((FILE * outfile));
                     85: # ifdef __MSC__
                     86: #  include <malloc.h>
                     87: # else
                     88: #  include <alloc.h>
                     89: # endif                                /* MSC */
                     90: #endif /* _Windows */
                     91:
                     92:
                     93: /* true if terminal has been initialized */
                     94: static TBOOLEAN term_initialised;
                     95:
                     96: /* true if terminal is in graphics mode */
                     97: static TBOOLEAN term_graphics = FALSE;
                     98:
                     99: /* we have suspended the driver, in multiplot mode */
                    100: static TBOOLEAN term_suspended = FALSE;
                    101:
                    102: /* true if? */
                    103: static TBOOLEAN opened_binary = FALSE;
                    104:
                    105: /* true if require terminal to be initialized */
                    106: static TBOOLEAN term_force_init = FALSE;
                    107:
                    108: extern FILE *gpoutfile;
                    109: extern char *outstr;
                    110: extern float xsize, ysize;
                    111:
                    112: /* internal pointsize for do_point */
                    113: static double term_pointsize;
                    114:
                    115: static void term_suspend __PROTO((void));
                    116: static void term_close_output __PROTO((void));
                    117: static void null_linewidth __PROTO((double));
                    118:
                    119: void do_point __PROTO((unsigned int x, unsigned int y, int number));
                    120: void do_pointsize __PROTO((double size));
                    121: void line_and_point __PROTO((unsigned int x, unsigned int y, int number));
                    122: void do_arrow __PROTO((unsigned int sx, unsigned int sy, unsigned int ex, unsigned int ey, int head));
                    123:
                    124:
                    125: #ifdef __ZTC__
                    126: char *ztc_init();
                    127: /* #undef TGIF */
                    128: #endif
                    129:
                    130: #ifdef VMS
                    131: char *vms_init();
                    132: void vms_reset();
                    133: void term_mode_tek();
                    134: void term_mode_native();
                    135: void term_pasthru();
                    136: void term_nopasthru();
                    137: void fflush_binary();
                    138: # define FOPEN_BINARY(file) fopen(file, "wb", "rfm=fix", "bls=512", "mrs=512")
                    139: #else /* !VMS */
                    140: # define FOPEN_BINARY(file) fopen(file, "wb")
                    141: #endif /* !VMS */
                    142:
                    143:
                    144: /* This is needed because the unixplot library only writes to stdout. */
                    145: #if defined(UNIXPLOT) || defined(GNUGRAPH)
                    146: static FILE save_stdout;
                    147: #endif
                    148: static int unixplot = 0;
                    149:
                    150: #if defined(MTOS) || defined(ATARI)
                    151: int aesid = -1;
                    152: #endif
                    153:
                    154: #define NICE_LINE              0
                    155: #define POINT_TYPES            6
                    156:
                    157: #ifndef DEFAULTTERM
                    158: # define DEFAULTTERM NULL
                    159: #endif
                    160:
                    161: /* interface to the rest of gnuplot - the rules are getting
                    162:  * too complex for the rest of gnuplot to be allowed in
                    163:  */
                    164:
                    165: #if defined(PIPES)
                    166: static TBOOLEAN pipe_open = FALSE;
                    167: #endif /* PIPES */
                    168:
                    169: static void term_close_output()
                    170: {
                    171:     FPRINTF((stderr, "term_close_output\n"));
                    172:
                    173:     opened_binary = FALSE;
                    174:
                    175:     if (!outstr)               /* ie using stdout */
                    176:        return;
                    177:
                    178: #if defined(PIPES)
                    179:     if (pipe_open) {
                    180:        (void) pclose(gpoutfile);
                    181:        pipe_open = FALSE;
                    182:     } else
                    183: #endif /* PIPES */
                    184: #ifdef _Windows
                    185:     if (stricmp(outstr, "PRN") == 0)
                    186:        close_printer(gpoutfile);
                    187:     else
                    188: #endif
                    189:        (void) fclose(gpoutfile);
                    190:
                    191:     gpoutfile = stdout;                /* Don't dup... */
                    192:     free(outstr);
                    193:     outstr = NULL;
                    194: }
                    195:
                    196: #ifdef OS2
                    197: # define POPEN_MODE ("wb")
                    198: #else
                    199: # define POPEN_MODE ("w")
                    200: #endif
                    201:
                    202: /* assigns dest to outstr, so it must be allocated or NULL
                    203:  * and it must not be outstr itself !
                    204:  */
                    205: void term_set_output(dest)
                    206: char *dest;
                    207: {
                    208:     FILE *f;
                    209:
                    210:     FPRINTF((stderr, "term_set_output\n"));
                    211:     assert(dest == NULL || dest != outstr);
                    212:
                    213:     if (multiplot) {
                    214:        fputs("In multiplotmode you can't change the output\n", stderr);
                    215:        return;
                    216:     }
                    217:     if (term && term_initialised) {
                    218:        (*term->reset) ();
                    219:        term_initialised = FALSE;
                    220:     }
                    221:     if (dest == NULL) {                /* stdout */
                    222:        UP_redirect(4);
                    223:        term_close_output();
                    224:     } else {
                    225:
                    226: #if defined(PIPES)
                    227:        if (*dest == '|') {
                    228:            if ((f = popen(dest + 1, POPEN_MODE)) == (FILE *) NULL)
                    229:                    os_error("cannot create pipe; output not changed", c_token);
                    230:                else
                    231:                    pipe_open = TRUE;
                    232:        } else
                    233: #endif /* PIPES */
                    234:
                    235: #ifdef _Windows
                    236:        if (outstr && stricmp(outstr, "PRN") == 0) {
                    237:            /* we can't call open_printer() while printer is open, so */
                    238:            close_printer(gpoutfile);   /* close printer immediately if open */
                    239:            gpoutfile = stdout; /* and reset output to stdout */
                    240:            free(outstr);
                    241:            outstr = NULL;
                    242:        }
                    243:        if (stricmp(dest, "PRN") == 0) {
                    244:            if ((f = open_printer()) == (FILE *) NULL)
                    245:                os_error("cannot open printer temporary file; output may have changed", c_token);
                    246:        } else
                    247: #endif
                    248:
                    249:        {
                    250:            if (term && (term->flags & TERM_BINARY)) {
                    251:                f = FOPEN_BINARY(dest);
                    252:            } else
                    253:                f = fopen(dest, "w");
                    254:
                    255:            if (f == (FILE *) NULL)
                    256:                os_error("cannot open file; output not changed", c_token);
                    257:        }
                    258:        term_close_output();
                    259:        gpoutfile = f;
                    260:        outstr = dest;
                    261:        opened_binary = (term && (term->flags & TERM_BINARY));
                    262:        UP_redirect(1);
                    263:     }
                    264: }
                    265:
                    266: void term_init()
                    267: {
                    268:     FPRINTF((stderr, "term_init()\n"));
                    269:
                    270:     if (!term)
                    271:        int_error("No terminal defined", NO_CARET);
                    272:
                    273:     /* check if we have opened the output file in the wrong mode
                    274:      * (text/binary), if set term comes after set output
                    275:      * This was originally done in change_term, but that
                    276:      * resulted in output files being truncated
                    277:      */
                    278:
                    279:     if (outstr &&
                    280:        (((term->flags & TERM_BINARY) && !opened_binary) ||
                    281:         ((!(term->flags & TERM_BINARY) && opened_binary)))) {
                    282:        /* this is nasty - we cannot just term_set_output(outstr)
                    283:         * since term_set_output will first free outstr and we
                    284:         * end up with an invalid pointer. I think I would
                    285:         * prefer to defer opening output file until first plot.
                    286:         */
                    287:        char *temp = gp_alloc(strlen(outstr) + 1, "temp file string");
                    288:        if (temp) {
                    289:            FPRINTF((stderr, "term_init : reopening \"%s\" as %s\n",
                    290:                     outstr, term->flags & TERM_BINARY ? "binary" : "text"));
                    291:            strcpy(temp, outstr);
                    292:            term_set_output(temp);      /* will free outstr */
                    293:        } else
                    294:            fputs("Cannot reopen output file in binary", stderr);
                    295:        /* and carry on, hoping for the best ! */
                    296:     }
                    297: #ifdef OS2
                    298:     else if (!outstr && !interactive && (term->flags & TERM_BINARY)) {
                    299:        /* binary (eg gif) to stdout in a non-interactive session */
                    300:        fflush(stdout);         // _fsetmode requires an empty buffer
                    301:
                    302:        _fsetmode(stdout, "b");
                    303:     }
                    304: #endif
                    305:
                    306:
                    307:     if (!term_initialised || term_force_init) {
                    308:        FPRINTF((stderr, "- calling term->init()\n"));
                    309:        (*term->init) ();
                    310:        term_initialised = TRUE;
                    311:     }
                    312: }
                    313:
                    314:
                    315: void term_start_plot()
                    316: {
                    317:     FPRINTF((stderr, "term_start_plot()\n"));
                    318:
                    319:     if (!term_initialised)
                    320:        term_init();
                    321:
                    322:     if (!term_graphics) {
                    323:        FPRINTF((stderr, "- calling term->graphics()\n"));
                    324:        (*term->graphics) ();
                    325:        term_graphics = TRUE;
                    326:     } else if (multiplot && term_suspended) {
                    327:        if (term->resume) {
                    328:            FPRINTF((stderr, "- calling term->resume()\n"));
                    329:            (*term->resume) ();
                    330:        }
                    331:        term_suspended = FALSE;
                    332:     }
                    333: }
                    334:
                    335: void term_end_plot()
                    336: {
                    337:     FPRINTF((stderr, "term_end_plot()\n"));
                    338:
                    339:     if (!term_initialised)
                    340:        return;
                    341:
                    342:     if (!multiplot) {
                    343:        FPRINTF((stderr, "- calling term->text()\n"));
                    344:        (*term->text) ();
                    345:        term_graphics = FALSE;
                    346:     }
                    347: #ifdef VMS
                    348:     if (opened_binary)
                    349:        fflush_binary();
                    350:     else
                    351: #endif /* VMS */
                    352:
                    353:        (void) fflush(gpoutfile);
                    354: }
                    355:
                    356: void term_start_multiplot()
                    357: {
                    358:     FPRINTF((stderr, "term_start_multiplot()\n"));
                    359:     if (multiplot)
                    360:        term_end_multiplot();
                    361:
                    362:     multiplot = TRUE;
                    363:     term_start_plot();
                    364: }
                    365:
                    366: void term_end_multiplot()
                    367: {
                    368:     FPRINTF((stderr, "term_end_multiplot()\n"));
                    369:     if (!multiplot)
                    370:        return;
                    371:
                    372:     if (term_suspended) {
                    373:        if (term->resume)
                    374:            (*term->resume) ();
                    375:        term_suspended = FALSE;
                    376:     }
                    377:     multiplot = FALSE;
                    378:
                    379:     term_end_plot();
                    380: }
                    381:
                    382:
                    383:
                    384: static void term_suspend()
                    385: {
                    386:     FPRINTF((stderr, "term_suspend()\n"));
                    387:     if (term_initialised && !term_suspended && term->suspend) {
                    388:        FPRINTF((stderr, "- calling term->suspend()\n"));
                    389:        (*term->suspend) ();
                    390:        term_suspended = TRUE;
                    391:     }
                    392: }
                    393:
                    394: void term_reset()
                    395: {
                    396:     FPRINTF((stderr, "term_reset()\n"));
                    397:
                    398:     if (!term_initialised)
                    399:        return;
                    400:
                    401:     if (term_suspended) {
                    402:        if (term->resume) {
                    403:            FPRINTF((stderr, "- calling term->resume()\n"));
                    404:            (*term->resume) ();
                    405:        }
                    406:        term_suspended = FALSE;
                    407:     }
                    408:     if (term_graphics) {
                    409:        (*term->text) ();
                    410:        term_graphics = FALSE;
                    411:     }
                    412:     if (term_initialised) {
                    413:        (*term->reset) ();
                    414:        term_initialised = FALSE;
                    415:     }
                    416: }
                    417:
                    418: void term_apply_lp_properties(lp)
                    419: struct lp_style_type *lp;
                    420: {
                    421:     /*  This function passes all the line and point properties to the
                    422:      *  terminal driver and issues the corresponding commands.
                    423:      *
                    424:      *  Alas, sometimes it might be necessary to give some help to
                    425:      *  this function by explicitly issuing additional '(*term)(...)'
                    426:      *  commands.
                    427:      */
                    428:
                    429:     if (lp->pointflag) {
                    430:        /* change points, too
                    431:         * Currently, there is no 'pointtype' function.  For points
                    432:         * there is a special function also dealing with (x,y) co-
                    433:         * ordinates.
                    434:         */
                    435:        (*term->pointsize) (lp->p_size);
                    436:     }
                    437:     /*  _first_ set the line width, _then_ set the line type !
                    438:
                    439:      *  The linetype might depend on the linewidth in some terminals.
                    440:      */
                    441:     (*term->linewidth) (lp->l_width);
                    442:     (*term->linetype) (lp->l_type);
                    443: }
                    444:
                    445:
                    446:
                    447: void term_check_multiplot_okay(f_interactive)
                    448: TBOOLEAN f_interactive;
                    449: {
                    450:     FPRINTF((stderr, "term_multiplot_okay(%d)\n", f_interactive));
                    451:
                    452:     if (!term_initialised)
                    453:        return;                 /* they've not started yet */
                    454:
                    455:     /* make sure that it is safe to issue an interactive prompt
                    456:      * it is safe if
                    457:      *   it is not an interactive read, or
                    458:      *   the terminal supports interactive multiplot, or
                    459:      *   we are not writing to stdout and terminal doesn't
                    460:      *     refuse multiplot outright
                    461:      */
                    462:     if (!f_interactive || (term->flags & TERM_CAN_MULTIPLOT) ||
                    463:        ((gpoutfile != stdout) && !(term->flags & TERM_CANNOT_MULTIPLOT))
                    464:        ) {
                    465:        /* it's okay to use multiplot here, but suspend first */
                    466:        term_suspend();
                    467:        return;
                    468:     }
                    469:     /* uh oh : they're not allowed to be in multiplot here */
                    470:
                    471:     term_end_multiplot();
                    472:
                    473:     /* at this point we know that it is interactive and that the
                    474:      * terminal can either only do multiplot when writing to
                    475:      * to a file, or it does not do multiplot at all
                    476:      */
                    477:
                    478:     if (term->flags & TERM_CANNOT_MULTIPLOT)
                    479:        int_error("This terminal does not support multiplot", NO_CARET);
                    480:     else
                    481:        int_error("Must set output to a file or put all multiplot commands on one input line", NO_CARET);
                    482: }
                    483:
                    484: void do_point(x, y, number)
                    485: unsigned int x, y;
                    486: int number;
                    487: {
                    488:     register int htic, vtic;
                    489:     register struct termentry *t = term;
                    490:
                    491:     if (number < 0) {          /* do dot */
                    492:        (*t->move) (x, y);
                    493:        (*t->vector) (x, y);
                    494:        return;
                    495:     }
                    496:     number %= POINT_TYPES;
                    497:     /* should be in term_tbl[] in later version */
                    498:     htic = (term_pointsize * t->h_tic / 2);
                    499:     vtic = (term_pointsize * t->v_tic / 2);
                    500:
                    501:     switch (number) {
                    502:     case 0:                    /* do diamond */
                    503:        (*t->move) (x - htic, y);
                    504:        (*t->vector) (x, y - vtic);
                    505:        (*t->vector) (x + htic, y);
                    506:        (*t->vector) (x, y + vtic);
                    507:        (*t->vector) (x - htic, y);
                    508:        (*t->move) (x, y);
                    509:        (*t->vector) (x, y);
                    510:        break;
                    511:     case 1:                    /* do plus */
                    512:        (*t->move) (x - htic, y);
                    513:        (*t->vector) (x - htic, y);
                    514:        (*t->vector) (x + htic, y);
                    515:        (*t->move) (x, y - vtic);
                    516:        (*t->vector) (x, y - vtic);
                    517:        (*t->vector) (x, y + vtic);
                    518:        break;
                    519:     case 2:                    /* do box */
                    520:        (*t->move) (x - htic, y - vtic);
                    521:        (*t->vector) (x - htic, y - vtic);
                    522:        (*t->vector) (x + htic, y - vtic);
                    523:        (*t->vector) (x + htic, y + vtic);
                    524:        (*t->vector) (x - htic, y + vtic);
                    525:        (*t->vector) (x - htic, y - vtic);
                    526:        (*t->move) (x, y);
                    527:        (*t->vector) (x, y);
                    528:        break;
                    529:     case 3:                    /* do X */
                    530:        (*t->move) (x - htic, y - vtic);
                    531:        (*t->vector) (x - htic, y - vtic);
                    532:        (*t->vector) (x + htic, y + vtic);
                    533:        (*t->move) (x - htic, y + vtic);
                    534:        (*t->vector) (x - htic, y + vtic);
                    535:        (*t->vector) (x + htic, y - vtic);
                    536:        break;
                    537:     case 4:                    /* do triangle */
                    538:        (*t->move) (x, y + (4 * vtic / 3));
                    539:        (*t->vector) (x - (4 * htic / 3), y - (2 * vtic / 3));
                    540:        (*t->vector) (x + (4 * htic / 3), y - (2 * vtic / 3));
                    541:        (*t->vector) (x, y + (4 * vtic / 3));
                    542:        (*t->move) (x, y);
                    543:        (*t->vector) (x, y);
                    544:        break;
                    545:     case 5:                    /* do star */
                    546:        (*t->move) (x - htic, y);
                    547:        (*t->vector) (x - htic, y);
                    548:        (*t->vector) (x + htic, y);
                    549:        (*t->move) (x, y - vtic);
                    550:        (*t->vector) (x, y - vtic);
                    551:        (*t->vector) (x, y + vtic);
                    552:        (*t->move) (x - htic, y - vtic);
                    553:        (*t->vector) (x - htic, y - vtic);
                    554:        (*t->vector) (x + htic, y + vtic);
                    555:        (*t->move) (x - htic, y + vtic);
                    556:        (*t->vector) (x - htic, y + vtic);
                    557:        (*t->vector) (x + htic, y - vtic);
                    558:        break;
                    559:     }
                    560: }
                    561:
                    562: void do_pointsize(size)
                    563: double size;
                    564: {
                    565:     term_pointsize = (size >= 0 ? size : 1);
                    566: }
                    567:
                    568:
                    569: /*
                    570:  * general point routine
                    571:  */
                    572: void line_and_point(x, y, number)
                    573: unsigned int x, y;
                    574: int number;
                    575: {
                    576:     /* temporary(?) kludge to allow terminals with bad linetypes
                    577:        to make nice marks */
                    578:
                    579:     (*term->linetype) (NICE_LINE);
                    580:     do_point(x, y, number);
                    581: }
                    582:
                    583: /*
                    584:  * general arrow routine
                    585:  *
                    586:  * I set the angle between the arrowhead and the line 15 degree.
                    587:  * The length of arrowhead varies depending on the line length
                    588:  * within the the range [0.3*(the-tic-length), 2*(the-tic-length)].
                    589:  * No head is printed if the arrow length is zero.
                    590:  *
                    591:  *            Yasu-hiro Yamazaki(hiro@rainbow.physics.utoronto.ca)
                    592:  *            Jul 1, 1993
                    593:  */
                    594:
                    595: #define COS15 (0.96593)                /* cos of 15 degree */
                    596: #define SIN15 (0.25882)                /* sin of 15 degree */
                    597:
                    598: #define HEAD_LONG_LIMIT  (2.0) /* long  limit of arrowhead length */
                    599: #define HEAD_SHORT_LIMIT (0.3) /* short limit of arrowhead length */
                    600:                                /* their units are the "tic" length */
                    601:
                    602: #define HEAD_COEFF  (0.3)      /* default value of head/line length ratio */
                    603:
                    604: void do_arrow(sx, sy, ex, ey, head)
                    605: unsigned int sx, sy;           /* start point */
                    606: unsigned int ex, ey;           /* end point (point of arrowhead) */
                    607: TBOOLEAN head;
                    608: {
                    609:     register struct termentry *t = term;
                    610:     float len_tic = ((double) (t->h_tic + t->v_tic)) / 2.0;
                    611:     /* average of tic sizes */
                    612:     /* (dx,dy) : vector from end to start */
                    613:     double dx = (double) sx - (double) ex;
                    614:     double dy = (double) sy - (double) ey;
                    615:     double len_arrow = sqrt(dx * dx + dy * dy);
                    616:
                    617:     /* draw the line for the arrow. That's easy. */
                    618:     (*t->move) (sx, sy);
                    619:     (*t->vector) (ex, ey);
                    620:
                    621:     /* no head for arrows whih length = 0
                    622:      * or, to be more specific, length < DBL_EPSILON,
                    623:      * because len_arrow will almost always be != 0
                    624:      */
                    625:     if (head && fabs(len_arrow) >= DBL_EPSILON) {
                    626:        /* now calc the head_coeff */
                    627:        double coeff_shortest = len_tic * HEAD_SHORT_LIMIT / len_arrow;
                    628:        double coeff_longest = len_tic * HEAD_LONG_LIMIT / len_arrow;
                    629:        double head_coeff = GPMAX(coeff_shortest,
                    630:                                  GPMIN(HEAD_COEFF, coeff_longest));
                    631:        /* now draw the arrow head. */
                    632:        /* we put the arrowhead marks at 15 degrees to line */
                    633:        int x, y;               /* one endpoint */
                    634:
                    635:        x = (int) (ex + (COS15 * dx - SIN15 * dy) * head_coeff);
                    636:        y = (int) (ey + (SIN15 * dx + COS15 * dy) * head_coeff);
                    637:        (*t->move) (x, y);
                    638:        (*t->vector) (ex, ey);
                    639:
                    640:        x = (int) (ex + (COS15 * dx + SIN15 * dy) * head_coeff);
                    641:        y = (int) (ey + (-SIN15 * dx + COS15 * dy) * head_coeff);
                    642:        (*t->vector) (x, y);
                    643:     }
                    644: }
                    645:
                    646: #if 0                          /* oiginal routine */
                    647: #define ROOT2 (1.41421)                /* sqrt of 2 */
                    648:
                    649: void org_do_arrow(sx, sy, ex, ey, head)
                    650: int sx, sy;                    /* start point */
                    651: int ex, ey;                    /* end point (point of arrowhead) */
                    652: TBOOLEAN head;
                    653: {
                    654:     register struct termentry *t = term;
                    655:     int len = (t->h_tic + t->v_tic) / 2;       /* arrowhead size = avg of tic sizes */
                    656:
                    657:     /* draw the line for the arrow. That's easy. */
                    658:     (*t->move) (sx, sy);
                    659:     (*t->vector) (ex, ey);
                    660:
                    661:     if (head) {
                    662:        /* now draw the arrow head. */
                    663:        /* we put the arrowhead marks at 45 degrees to line */
                    664:        if (sx == ex) {
                    665:            /* vertical line, special case */
                    666:            int delta = ((float) len / ROOT2 + 0.5);
                    667:            if (sy < ey)
                    668:                delta = -delta; /* up arrow goes the other way */
                    669:            (*t->move) (ex - delta, ey + delta);
                    670:            (*t->vector) (ex, ey);
                    671:            (*t->vector) (ex + delta, ey + delta);
                    672:        } else {
                    673:            int dx = sx - ex;
                    674:            int dy = sy - ey;
                    675:            double coeff = len / sqrt(2.0 * ((double) dx * (double) dx
                    676:                                             + (double) dy * (double) dy));
                    677:            int x, y;           /* one endpoint */
                    678:
                    679:            x = (int) (ex + (dx + dy) * coeff);
                    680:            y = (int) (ey + (dy - dx) * coeff);
                    681:            (*t->move) (x, y);
                    682:            (*t->vector) (ex, ey);
                    683:
                    684:            x = (int) (ex + (dx - dy) * coeff);
                    685:            y = (int) (ey + (dy + dx) * coeff);
                    686:            (*t->vector) (x, y);
                    687:        }
                    688:     }
                    689: }
                    690:
                    691: #endif /* original routine */
                    692:
                    693:
                    694: #define TERM_PROTO
                    695: #define TERM_BODY
                    696: #define TERM_PUBLIC static
                    697:
                    698: #include "term.h"
                    699:
                    700: #undef TERM_PROTO
                    701: #undef TERM_BODY
                    702: #undef TERM_PUBLIC
                    703:
                    704:
                    705: /* Dummy functions for unavailable features */
                    706: /* return success if they asked for default - this simplifies code
                    707:  * where param is passed as a param. Client can first pass it here,
                    708:  * and only if it fails do they have to see what was trying to be done
                    709:  */
                    710:
                    711: /* change angle of text.  0 is horizontal left to right.
                    712:    * 1 is vertical bottom to top (90 deg rotate)
                    713:  */
                    714: int null_text_angle(ang)
                    715: int ang;
                    716: {
                    717:     return (ang == 0);
                    718: }
                    719:
                    720: /* change justification of text.
                    721:  * modes are LEFT (flush left), CENTRE (centred), RIGHT (flush right)
                    722:  */
                    723: int null_justify_text(just)
                    724: enum JUSTIFY just;
                    725: {
                    726:     return (just == LEFT);
                    727: }
                    728:
                    729:
                    730: /* Change scale of plot.
                    731:  * Parameters are x,y scaling factors for this plot.
                    732:  * Some terminals (eg latex) need to do scaling themselves.
                    733:  */
                    734: int null_scale(x, y)
                    735: double x;
                    736: double y;
                    737: {
                    738:     return FALSE;              /* can't be done */
                    739: }
                    740:
                    741: int do_scale(x, y)
                    742: double x;
                    743: double y;
                    744: {
                    745:     return TRUE;               /* can be done */
                    746: }
                    747:
                    748: void options_null()
                    749: {
                    750:     term_options[0] = '\0';    /* we have no options */
                    751: }
                    752:
                    753: void UNKNOWN_null()
                    754: {
                    755: }
                    756:
                    757: void MOVE_null(x, y)
                    758: unsigned int x, y;
                    759: {
                    760: }
                    761:
                    762: void LINETYPE_null(t)
                    763: int t;
                    764: {
                    765: }
                    766:
                    767: void PUTTEXT_null(x, y, s)
                    768: unsigned int x, y;
                    769: char *s;
                    770: {
                    771: }
                    772:
                    773:
                    774: int set_font_null(s)
                    775: char *s;
                    776: {
                    777:     return FALSE;
                    778: }
                    779:
                    780: static void null_linewidth(s)
                    781: double s;
                    782: {
                    783: }
                    784:
                    785:
                    786: /* cast to get rid of useless warnings about UNKNOWN_null */
                    787: typedef void (*void_fp) __PROTO((void));
                    788:
                    789:
                    790: /* setup the magic macros to compile in the right parts of the
                    791:  * terminal drivers included by term.h
                    792:  */
                    793:
                    794: #define TERM_TABLE
                    795: #define TERM_TABLE_START(x) ,{
                    796: #define TERM_TABLE_END(x)   }
                    797:
                    798:
                    799: /*
                    800:  * term_tbl[] contains an entry for each terminal.  "unknown" must be the
                    801:  *   first, since term is initialized to 0.
                    802:  */
                    803: struct termentry term_tbl[] =
                    804: {
                    805:     {"unknown", "Unknown terminal type - not a plotting device",
                    806:      100, 100, 1, 1,
                    807:      1, 1, options_null, UNKNOWN_null, UNKNOWN_null,
                    808:      UNKNOWN_null, null_scale, UNKNOWN_null, MOVE_null, MOVE_null,
                    809:      LINETYPE_null, PUTTEXT_null}
                    810:     ,
                    811:     {"table", "Dump ASCII table of X Y [Z] values to output",
                    812:      100, 100, 1, 1,
                    813:      1, 1, options_null, UNKNOWN_null, UNKNOWN_null,
                    814:      UNKNOWN_null, null_scale, UNKNOWN_null, MOVE_null, MOVE_null,
                    815:      LINETYPE_null, PUTTEXT_null}
                    816: #include "term.h"
                    817:
                    818: };
                    819:
                    820: #define TERMCOUNT (sizeof(term_tbl)/sizeof(struct termentry))
                    821:
                    822: void list_terms()
                    823: {
                    824:     register int i;
                    825:     char line_buffer[BUFSIZ];
                    826:
                    827:     StartOutput();
                    828:     sprintf(line_buffer,"\nAvailable terminal types:\n");
                    829:     OutLine(line_buffer);
                    830:
                    831:     for (i = 0; i < TERMCOUNT; i++) {
                    832:        sprintf(line_buffer,"  %15s  %s\n",
                    833:                term_tbl[i].name, term_tbl[i].description);
                    834:        OutLine(line_buffer);
                    835:     }
                    836:
                    837:     EndOutput();
                    838: }
                    839:
                    840:
                    841: /* set_term: get terminal number from name on command line
                    842:  * will change 'term' variable if successful
                    843:  */
                    844: struct termentry *
                    845:  set_term(c_token_arg)
                    846: int c_token_arg;
                    847: {
                    848:     register struct termentry *t = NULL;
                    849:     char *input_name;
                    850:
                    851:     if (!token[c_token_arg].is_token)
                    852:        int_error("terminal name expected", c_token_arg);
                    853:     input_name = input_line + token[c_token_arg].start_index;
                    854:     t = change_term(input_name, token[c_token_arg].length);
                    855:     if (!t)
                    856:        int_error("unknown or ambiguous terminal type; type just 'set terminal' for a list",
                    857:                  c_token_arg);
                    858:
                    859:     /* otherwise the type was changed */
                    860:
                    861:     return (t);
                    862: }
                    863:
                    864: /* change_term: get terminal number from name and set terminal type
                    865:  *
                    866:  * returns NULL for unknown or ambiguous, otherwise is terminal
                    867:  * driver pointer
                    868:  */
                    869: struct termentry *
                    870:  change_term(name, length)
                    871: char *name;
                    872: int length;
                    873: {
                    874:     int i;
                    875:     struct termentry *t = NULL;
                    876:
                    877:     for (i = 0; i < TERMCOUNT; i++) {
                    878:        if (!strncmp(name, term_tbl[i].name, length)) {
                    879:            if (t)
                    880:                return (NULL);  /* ambiguous */
                    881:            t = term_tbl + i;
                    882:        }
                    883:     }
                    884:
                    885:     if (!t)                    /* unknown */
                    886:        return (NULL);
                    887:
                    888:     /* Success: set terminal type now */
                    889:
                    890:     term = t;
                    891:     term_initialised = FALSE;
                    892:     name = term->name;
                    893:
                    894:     if (term->scale != null_scale)
                    895:        fputs("Warning : scale interface is not null_scale - may not work with multiplot\n", stderr);
                    896:
                    897:     /* check that optional fields are initialised to something */
                    898:     if (term->text_angle == 0)
                    899:        term->text_angle = null_text_angle;
                    900:     if (term->justify_text == 0)
                    901:        term->justify_text = null_justify_text;
                    902:     if (term->point == 0)
                    903:        term->point = do_point;
                    904:     if (term->arrow == 0)
                    905:        term->arrow = do_arrow;
                    906:     if (term->set_font == 0)
                    907:        term->set_font = set_font_null;
                    908:     if (term->pointsize == 0)
                    909:        term->pointsize = do_pointsize;
                    910:     if (term->linewidth == 0)
                    911:        term->linewidth = null_linewidth;
                    912:
                    913:     /* Special handling for unixplot term type */
                    914:     if (!strncmp("unixplot", name, 8)) {
                    915:        UP_redirect(2);         /* Redirect actual stdout for unixplots */
                    916:     } else if (unixplot) {
                    917:        UP_redirect(3);         /* Put stdout back together again. */
                    918:     }
                    919:     if (interactive)
                    920:        fprintf(stderr, "Terminal type set to '%s'\n", name);
                    921:
                    922:     return (t);
                    923: }
                    924:
                    925: /*
                    926:  * Routine to detect what terminal is being used (or do anything else
                    927:  * that would be nice).  One anticipated (or allowed for) side effect
                    928:  * is that the global ``term'' may be set.
                    929:  * The environment variable GNUTERM is checked first; if that does
                    930:  * not exist, then the terminal hardware is checked, if possible,
                    931:  * and finally, we can check $TERM for some kinds of terminals.
                    932:  * A default can be set with -DDEFAULTTERM=myterm in the Makefile
                    933:  * or #define DEFAULTTERM myterm in term.h
                    934:  */
                    935: /* thanks to osupyr!alden (Dave Alden) for the original GNUTERM code */
                    936: void init_terminal()
                    937: {
                    938:     char *term_name = DEFAULTTERM;
                    939: #if (defined(__TURBOC__) && defined(MSDOS) && !defined(_Windows)) || defined(NEXT) || defined(SUN) || defined(X11)
                    940:     char *env_term = NULL;     /* from TERM environment var */
                    941: #endif
                    942: #ifdef X11
                    943:     char *display = NULL;
                    944: #endif
                    945:     char *gnuterm = NULL;
                    946:
                    947:     /* GNUTERM environment variable is primary */
                    948:     gnuterm = getenv("GNUTERM");
                    949:     if (gnuterm != (char *) NULL) {
                    950:        term_name = gnuterm;
                    951:     } else {
                    952:
                    953: #ifdef __ZTC__
                    954:        term_name = ztc_init();
                    955: #endif
                    956:
                    957: #ifdef VMS
                    958:        term_name = vms_init();
                    959: #endif /* VMS */
                    960:
                    961: #ifdef NEXT
                    962:        env_term = getenv("TERM");
                    963:        if (term_name == (char *) NULL
                    964:            && env_term != (char *) NULL && strcmp(term, "next") == 0)
                    965:            term_name = "next";
                    966: #endif /* NeXT */
                    967:
                    968: #ifdef SUN
                    969:        env_term = getenv("TERM");      /* try $TERM */
                    970:        if (term_name == (char *) NULL
                    971:            && env_term != (char *) NULL && strcmp(env_term, "sun") == 0)
                    972:            term_name = "sun";
                    973: #endif /* SUN */
                    974:
                    975: #ifdef _Windows
                    976:        term_name = "win";
                    977: #endif /* _Windows */
                    978:
                    979: #ifdef GPR
                    980:        /* find out whether stdout is a DM pad. See term/gpr.trm */
                    981:        if (gpr_isa_pad())
                    982:            term_name = "gpr";
                    983: #else
                    984: # ifdef APOLLO
                    985:        /* find out whether stdout is a DM pad. See term/apollo.trm */
                    986:        if (apollo_isa_pad())
                    987:            term_name = "apollo";
                    988: # endif                                /* APOLLO */
                    989: #endif /* GPR    */
                    990:
                    991: #ifdef X11
                    992:        env_term = getenv("TERM");      /* try $TERM */
                    993:        if (term_name == (char *) NULL
                    994:            && env_term != (char *) NULL && strcmp(env_term, "xterm") == 0)
                    995:            term_name = "x11";
                    996:        display = getenv("DISPLAY");
                    997:        if (term_name == (char *) NULL && display != (char *) NULL)
                    998:            term_name = "x11";
                    999:        if (X11_Display)
                   1000:            term_name = "x11";
                   1001: #endif /* x11 */
                   1002:
                   1003: #ifdef AMIGA
                   1004:        term_name = "amiga";
                   1005: #endif
                   1006:
                   1007: #if defined(ATARI) || defined(MTOS)
                   1008:        term_name = "atari";
                   1009: #endif
                   1010:
                   1011: #ifdef UNIXPC
                   1012:        if (iswind() == 0) {
                   1013:            term_name = "unixpc";
                   1014:        }
                   1015: #endif /* unixpc */
                   1016:
                   1017: #ifdef CGI
                   1018:        if (getenv("CGIDISP") || getenv("CGIPRNT"))
                   1019:            term_name = "cgi";
                   1020: #endif /*CGI */
                   1021:
                   1022: #ifdef DJGPP
                   1023:        term_name = "svga";
                   1024: #endif
                   1025:
                   1026: #ifdef GRASS
                   1027:        term_name = "grass";
                   1028: #endif
                   1029:
                   1030: #ifdef OS2
                   1031: /*      if (_osmode==OS2_MODE) term_name = "pm" ; else term_name = "emxvga"; */
                   1032: # ifdef X11
                   1033: /* This catch is hopefully ok ... */
                   1034:        env_term = getenv("WINDOWID");
                   1035:        display = getenv("DISPLAY");
                   1036:        if ((env_term != (char *) NULL) && (display != (char *) NULL))
                   1037:            term_name = "x11";
                   1038:        else
                   1039: # endif                                /* X11 */
                   1040:            term_name = "pm";
                   1041: #endif /*OS2 */
                   1042:
                   1043: /* set linux terminal only if LINUX_setup was successfull, if we are on X11
                   1044:    LINUX_setup has failed, also if we are logged in by network */
                   1045: #ifdef LINUXVGA
                   1046:        if (LINUX_graphics_allowed)
                   1047:            term_name = "linux";
                   1048: #endif /* LINUXVGA */
                   1049:     }
                   1050:
                   1051:     /* We have a name, try to set term type */
                   1052:     if (term_name != NULL && *term_name != '\0') {
                   1053:        if (change_term(term_name, (int) strlen(term_name)))
                   1054:            return;
                   1055:        fprintf(stderr, "Unknown or ambiguous terminal name '%s'\n", term_name);
                   1056:     }
                   1057:     change_term("unknown", 7);
                   1058: }
                   1059:
                   1060:
                   1061: #ifdef __ZTC__
                   1062: char *ztc_init()
                   1063: {
                   1064:     int g_mode;
                   1065:     char *term_name = NULL;
                   1066:
                   1067:     g_mode = fg_init();
                   1068:
                   1069:     switch (g_mode) {
                   1070:     case FG_NULL:
                   1071:        fputs("Graphics card not detected or not supported.\n", stderr);
                   1072:        exit(1);
                   1073:     case FG_HERCFULL:
                   1074:        term_name = "hercules";
                   1075:        break;
                   1076:     case FG_EGAMONO:
                   1077:        term_name = "egamono";
                   1078:        break;
                   1079:     case FG_EGAECD:
                   1080:        term_name = "egalib";
                   1081:        break;
                   1082:     case FG_VGA11:
                   1083:        term_name = "vgamono";
                   1084:        break;
                   1085:     case FG_VGA12:
                   1086:        term_name = "vgalib";
                   1087:        break;
                   1088:     case FG_VESA6A:
                   1089:        term_name = "svgalib";
                   1090:        break;
                   1091:     case FG_VESA5:
                   1092:        term_name = "ssvgalib";
                   1093:        break;
                   1094:     }
                   1095:     fg_term();
                   1096:     return (term_name);
                   1097: }
                   1098: #endif /* __ZTC__ */
                   1099:
                   1100:
                   1101: /*
                   1102:    This is always defined so we don't have to have command.c know if it
                   1103:    is there or not.
                   1104:  */
                   1105: #if !(defined(UNIXPLOT) || defined(GNUGRAPH))
                   1106: void UP_redirect(caller)
                   1107: int caller;
                   1108: {
                   1109:     caller = caller;           /* to stop Turbo C complaining
                   1110:                                   * about caller not being used */
                   1111: }
                   1112:
                   1113: #else /* UNIXPLOT || GNUGRAPH */
                   1114: void UP_redirect(caller)
                   1115: int caller;
                   1116: /*
                   1117:    Unixplot can't really write to gpoutfile--it wants to write to stdout.
                   1118:    This is normally ok, but the original design of gnuplot gives us
                   1119:    little choice.  Originally users of unixplot had to anticipate
                   1120:    their needs and redirect all I/O to a file...  Not very gnuplot-like.
                   1121:
                   1122:    caller:  1 - called from SET OUTPUT "FOO.OUT"
                   1123:    2 - called from SET TERM UNIXPLOT
                   1124:    3 - called from SET TERM other
                   1125:    4 - called from SET OUTPUT
                   1126:  */
                   1127: {
                   1128:     switch (caller) {
                   1129:     case 1:
                   1130:        /* Don't save, just replace stdout w/gpoutfile (save was already done). */
                   1131:        if (unixplot)
                   1132:            *(stdout) = *(gpoutfile);   /* Copy FILE structure */
                   1133:        break;
                   1134:     case 2:
                   1135:        if (!unixplot) {
                   1136:            fflush(stdout);
                   1137:            save_stdout = *(stdout);
                   1138:            *(stdout) = *(gpoutfile);   /* Copy FILE structure */
                   1139:            unixplot = 1;
                   1140:        }
                   1141:        break;
                   1142:     case 3:
                   1143:        /* New terminal in use--put stdout back to original. */
                   1144: /* closepl(); *//* This is called by the term. */
                   1145:        fflush(stdout);
                   1146:        *(stdout) = save_stdout;        /* Copy FILE structure */
                   1147:        unixplot = 0;
                   1148:        break;
                   1149:     case 4:
                   1150:        /*  User really wants to go to normal output... */
                   1151:        if (unixplot) {
                   1152:            fflush(stdout);
                   1153:            *(stdout) = save_stdout;    /* Copy FILE structure */
                   1154:        }
                   1155:        break;
                   1156:     }
                   1157: }
                   1158: #endif /* UNIXPLOT || GNUGRAPH */
                   1159:
                   1160:
                   1161: /* test terminal by drawing border and text */
                   1162: /* called from command test */
                   1163: void test_term()
                   1164: {
                   1165:     register struct termentry *t = term;
                   1166:     char *str;
                   1167:     int x, y, xl, yl, i;
                   1168:     unsigned int xmax_t, ymax_t;
                   1169:     char label[MAX_ID_LEN];
                   1170:     int key_entry_height;
                   1171:     int p_width;
                   1172:
                   1173:     term_start_plot();
                   1174:     screen_ok = FALSE;
                   1175:     xmax_t = (unsigned int) (t->xmax * xsize);
                   1176:     ymax_t = (unsigned int) (t->ymax * ysize);
                   1177:
                   1178:     p_width = pointsize * (t->h_tic);
                   1179:     key_entry_height = pointsize * (t->v_tic) * 1.25;
                   1180:     if (key_entry_height < (t->v_char))
                   1181:        key_entry_height = (t->v_char);
                   1182:
                   1183:     /* border linetype */
                   1184:     (*t->linetype) (-2);
                   1185:     (*t->move) (0, 0);
                   1186:     (*t->vector) (xmax_t - 1, 0);
                   1187:     (*t->vector) (xmax_t - 1, ymax_t - 1);
                   1188:     (*t->vector) (0, ymax_t - 1);
                   1189:     (*t->vector) (0, 0);
                   1190:     (void) (*t->justify_text) (LEFT);
                   1191:     (*t->put_text) (t->h_char * 5, ymax_t - t->v_char * 3, "Terminal Test");
                   1192:     /* axis linetype */
                   1193:     (*t->linetype) (-1);
                   1194:     (*t->move) (xmax_t / 2, 0);
                   1195:     (*t->vector) (xmax_t / 2, ymax_t - 1);
                   1196:     (*t->move) (0, ymax_t / 2);
                   1197:     (*t->vector) (xmax_t - 1, ymax_t / 2);
                   1198:     /* test width and height of characters */
                   1199:     (*t->linetype) (-2);
                   1200:     (*t->move) (xmax_t / 2 - t->h_char * 10, ymax_t / 2 + t->v_char / 2);
                   1201:     (*t->vector) (xmax_t / 2 + t->h_char * 10, ymax_t / 2 + t->v_char / 2);
                   1202:     (*t->vector) (xmax_t / 2 + t->h_char * 10, ymax_t / 2 - t->v_char / 2);
                   1203:     (*t->vector) (xmax_t / 2 - t->h_char * 10, ymax_t / 2 - t->v_char / 2);
                   1204:     (*t->vector) (xmax_t / 2 - t->h_char * 10, ymax_t / 2 + t->v_char / 2);
                   1205:     (*t->put_text) (xmax_t / 2 - t->h_char * 10, ymax_t / 2,
                   1206:                    "12345678901234567890");
                   1207:     /* test justification */
                   1208:     (void) (*t->justify_text) (LEFT);
                   1209:     (*t->put_text) (xmax_t / 2, ymax_t / 2 + t->v_char * 6, "left justified");
                   1210:     str = "centre+d text";
                   1211:     if ((*t->justify_text) (CENTRE))
                   1212:        (*t->put_text) (xmax_t / 2,
                   1213:                        ymax_t / 2 + t->v_char * 5, str);
                   1214:     else
                   1215:        (*t->put_text) (xmax_t / 2 - strlen(str) * t->h_char / 2,
                   1216:                        ymax_t / 2 + t->v_char * 5, str);
                   1217:     str = "right justified";
                   1218:     if ((*t->justify_text) (RIGHT))
                   1219:        (*t->put_text) (xmax_t / 2,
                   1220:                        ymax_t / 2 + t->v_char * 4, str);
                   1221:     else
                   1222:        (*t->put_text) (xmax_t / 2 - strlen(str) * t->h_char,
                   1223:                        ymax_t / 2 + t->v_char * 4, str);
                   1224:     /* test text angle */
                   1225:     str = "rotated ce+ntred text";
                   1226:     if ((*t->text_angle) (1)) {
                   1227:        if ((*t->justify_text) (CENTRE))
                   1228:            (*t->put_text) (t->v_char,
                   1229:                            ymax_t / 2, str);
                   1230:        else
                   1231:            (*t->put_text) (t->v_char,
                   1232:                            ymax_t / 2 - strlen(str) * t->h_char / 2, str);
                   1233:     } else {
                   1234:        (void) (*t->justify_text) (LEFT);
                   1235:        (*t->put_text) (t->h_char * 2, ymax_t / 2 - t->v_char * 2, "Can't rotate text");
                   1236:     }
                   1237:     (void) (*t->justify_text) (LEFT);
                   1238:     (void) (*t->text_angle) (0);
                   1239:     /* test tic size */
                   1240:     (*t->move) ((unsigned int) (xmax_t / 2 + t->h_tic * (1 + ticscale)), (unsigned) 0);
                   1241:     (*t->vector) ((unsigned int) (xmax_t / 2 + t->h_tic * (1 + ticscale)), (unsigned int)
                   1242:                  (ticscale * t->v_tic));
                   1243:     (*t->move) ((unsigned int) (xmax_t / 2), (unsigned int) (t->v_tic * (1 + ticscale)));
                   1244:     (*t->vector) ((unsigned int) (xmax_t / 2 + ticscale * t->h_tic), (unsigned int) (t->v_tic * (1
                   1245:                                                                                                 + ticscale)));
                   1246:     (*t->put_text) ((unsigned int) (xmax_t / 2 - 10 * t->h_char), (unsigned int) (t->v_tic * 2 +
                   1247:                                                                                  t->v_char / 2),
                   1248:                    "test tics");
                   1249:
                   1250:     /* test line and point types */
                   1251:     x = xmax_t - t->h_char * 6 - p_width;
                   1252:     y = ymax_t - key_entry_height;
                   1253:     (*t->pointsize) (pointsize);
                   1254:     for (i = -2; y > key_entry_height; i++) {
                   1255:        (*t->linetype) (i);
                   1256:        /*      (void) sprintf(label,"%d",i);  Jorgen Lippert
                   1257:           lippert@risoe.dk */
                   1258:        (void) sprintf(label, "%d", i + 1);
                   1259:        if ((*t->justify_text) (RIGHT))
                   1260:            (*t->put_text) (x, y, label);
                   1261:        else
                   1262:            (*t->put_text) (x - strlen(label) * t->h_char, y, label);
                   1263:        (*t->move) (x + t->h_char, y);
                   1264:        (*t->vector) (x + t->h_char * 4, y);
                   1265:        if (i >= -1)
                   1266:            (*t->point) (x + t->h_char * 5 + p_width / 2, y, i);
                   1267:        y -= key_entry_height;
                   1268:     }
                   1269:     /* test some arrows */
                   1270:     (*t->linewidth) (1.0);
                   1271:     (*t->linetype) (0);
                   1272:     x = xmax_t / 4;
                   1273:     y = ymax_t / 4;
                   1274:     xl = t->h_tic * 5;
                   1275:     yl = t->v_tic * 5;
                   1276:     (*t->arrow) (x, y, x + xl, y, TRUE);
                   1277:     (*t->arrow) (x, y, x + xl / 2, y + yl, TRUE);
                   1278:     (*t->arrow) (x, y, x, y + yl, TRUE);
                   1279:     (*t->arrow) (x, y, x - xl / 2, y + yl, FALSE);
                   1280:     (*t->arrow) (x, y, x - xl, y, TRUE);
                   1281:     (*t->arrow) (x, y, x - xl, y - yl, TRUE);
                   1282:     (*t->arrow) (x, y, x, y - yl, TRUE);
                   1283:     (*t->arrow) (x, y, x + xl, y - yl, TRUE);
                   1284:
                   1285:     term_end_plot();
                   1286: }
                   1287:
                   1288: #if 0
                   1289: # if defined(MSDOS)||defined(g)||defined(MTOS)||defined(OS2)||defined(_Windows)||defined(DOS386)
                   1290: /* output for some terminal types must be binary to stop non Unix computers
                   1291:    changing \n to \r\n.
                   1292:    If the output is not STDOUT, the following code reopens gpoutfile
                   1293:    with binary mode. */
                   1294: void reopen_binary()
                   1295: {
                   1296:     if (outstr) {
                   1297:        (void) fclose(gpoutfile);
                   1298: #  ifdef _Windows
                   1299:        if (!stricmp(outstr, "PRN")) {
                   1300:            /* use temp file for windows */
                   1301:            (void) strcpy(filename, win_prntmp);
                   1302:        }
                   1303: #  endif
                   1304:        if ((gpoutfile = fopen(filename, "wb")) == (FILE *) NULL) {
                   1305:            if ((gpoutfile = fopen(filename, "w")) == (FILE *) NULL) {
                   1306:                os_error("cannot reopen file with binary type; output unknown",
                   1307:                         NO_CARET);
                   1308:            } else {
                   1309:                os_error("cannot reopen file with binary type; output reset to ascii",
                   1310:                         NO_CARET);
                   1311:            }
                   1312:        }
                   1313: #  if defined(__TURBOC__) && defined(MSDOS)
                   1314: #   ifndef _Windows
                   1315:        if (!stricmp(outstr, "PRN")) {
                   1316:            /* Put the printer into binary mode. */
                   1317:            union REGS regs;
                   1318:            regs.h.ah = 0x44;   /* ioctl */
                   1319:            regs.h.al = 0;      /* get device info */
                   1320:            regs.x.bx = fileno(gpoutfile);
                   1321:            intdos(&regs, &regs);
                   1322:            regs.h.dl |= 0x20;  /* binary (no ^Z intervention) */
                   1323:            regs.h.dh = 0;
                   1324:            regs.h.ah = 0x44;   /* ioctl */
                   1325:            regs.h.al = 1;      /* set device info */
                   1326:            intdos(&regs, &regs);
                   1327:        }
                   1328: #   endif                      /* !_Windows */
                   1329: #  endif                       /* TURBOC && MSDOS */
                   1330:     }
                   1331: }
                   1332:
                   1333: # endif                                /* MSDOS || g || MTOS || ... */
                   1334: #endif /* 0 */
                   1335:
                   1336: #ifdef VMS
                   1337: /* these are needed to modify terminal characteristics */
                   1338: # ifndef VWS_XMAX
                   1339:    /* avoid duplicate warning; VWS includes these */
                   1340: #  include <descrip.h>
                   1341: #  include <ssdef.h>
                   1342: # endif /* !VWS_MAX */
                   1343: # include <iodef.h>
                   1344: # include <ttdef.h>
                   1345: # include <tt2def.h>
                   1346: # include <dcdef.h>
                   1347: # include <stat.h>
                   1348: # include <fab.h>
                   1349: /* If you use WATCOM C or a very strict ANSI compiler, you may have to
                   1350:  * delete or comment out the following 3 lines: */
                   1351: # ifndef TT2$M_DECCRT3         /* VT300 not defined as of VAXC v2.4 */
                   1352: #  define TT2$M_DECCRT3 0X80000000
                   1353: # endif
                   1354: static unsigned short chan;
                   1355: static int old_char_buf[3], cur_char_buf[3];
                   1356: $DESCRIPTOR(sysoutput_desc, "SYS$OUTPUT");
                   1357:
                   1358: char *vms_init()
                   1359: /*
                   1360:  *  Look first for decw$display (decterms do regis)
                   1361:  *  Determine if we have a regis terminal
                   1362:  * and save terminal characteristics
                   1363:  */
                   1364: {
                   1365:     /* Save terminal characteristics in old_char_buf and
                   1366:        initialise cur_char_buf to current settings. */
                   1367:     int i;
                   1368:     if (getenv("DECW$DISPLAY"))
                   1369:        return ("x11");
                   1370:     atexit(vms_reset);
                   1371:     sys$assign(&sysoutput_desc, &chan, 0, 0);
                   1372:     sys$qiow(0, chan, IO$_SENSEMODE, 0, 0, 0, old_char_buf, 12, 0, 0, 0, 0);
                   1373:     for (i = 0; i < 3; ++i)
                   1374:        cur_char_buf[i] = old_char_buf[i];
                   1375:     sys$dassgn(chan);
                   1376:
                   1377:     /* Test if terminal is regis */
                   1378:     if ((cur_char_buf[2] & TT2$M_REGIS) == TT2$M_REGIS)
                   1379:        return ("regis");
                   1380:     return (NULL);
                   1381: }
                   1382:
                   1383: void vms_reset()
                   1384: /* set terminal to original state */
                   1385: {
                   1386:     int i;
                   1387:     sys$assign(&sysoutput_desc, &chan, 0, 0);
                   1388:     sys$qiow(0, chan, IO$_SETMODE, 0, 0, 0, old_char_buf, 12, 0, 0, 0, 0);
                   1389:     for (i = 0; i < 3; ++i)
                   1390:        cur_char_buf[i] = old_char_buf[i];
                   1391:     sys$dassgn(chan);
                   1392: }
                   1393:
                   1394: void term_mode_tek()
                   1395: /* set terminal mode to tektronix */
                   1396: {
                   1397:     long status;
                   1398:     if (gpoutfile != stdout)
                   1399:        return;                 /* don't modify if not stdout */
                   1400:     sys$assign(&sysoutput_desc, &chan, 0, 0);
                   1401:     cur_char_buf[0] = 0x004A0000 | DC$_TERM | (TT$_TEK401X << 8);
                   1402:     cur_char_buf[1] = (cur_char_buf[1] & 0x00FFFFFF) | 0x18000000;
                   1403:
                   1404:     cur_char_buf[1] &= ~TT$M_CRFILL;
                   1405:     cur_char_buf[1] &= ~TT$M_ESCAPE;
                   1406:     cur_char_buf[1] &= ~TT$M_HALFDUP;
                   1407:     cur_char_buf[1] &= ~TT$M_LFFILL;
                   1408:     cur_char_buf[1] &= ~TT$M_MECHFORM;
                   1409:     cur_char_buf[1] &= ~TT$M_NOBRDCST;
                   1410:     cur_char_buf[1] &= ~TT$M_NOECHO;
                   1411:     cur_char_buf[1] &= ~TT$M_READSYNC;
                   1412:     cur_char_buf[1] &= ~TT$M_REMOTE;
                   1413:     cur_char_buf[1] |= TT$M_LOWER;
                   1414:     cur_char_buf[1] |= TT$M_TTSYNC;
                   1415:     cur_char_buf[1] |= TT$M_WRAP;
                   1416:     cur_char_buf[1] &= ~TT$M_EIGHTBIT;
                   1417:     cur_char_buf[1] &= ~TT$M_MECHTAB;
                   1418:     cur_char_buf[1] &= ~TT$M_SCOPE;
                   1419:     cur_char_buf[1] |= TT$M_HOSTSYNC;
                   1420:
                   1421:     cur_char_buf[2] &= ~TT2$M_APP_KEYPAD;
                   1422:     cur_char_buf[2] &= ~TT2$M_BLOCK;
                   1423:     cur_char_buf[2] &= ~TT2$M_DECCRT3;
                   1424:     cur_char_buf[2] &= ~TT2$M_LOCALECHO;
                   1425:     cur_char_buf[2] &= ~TT2$M_PASTHRU;
                   1426:     cur_char_buf[2] &= ~TT2$M_REGIS;
                   1427:     cur_char_buf[2] &= ~TT2$M_SIXEL;
                   1428:     cur_char_buf[2] |= TT2$M_BRDCSTMBX;
                   1429:     cur_char_buf[2] |= TT2$M_EDITING;
                   1430:     cur_char_buf[2] |= TT2$M_INSERT;
                   1431:     cur_char_buf[2] |= TT2$M_PRINTER;
                   1432:     cur_char_buf[2] &= ~TT2$M_ANSICRT;
                   1433:     cur_char_buf[2] &= ~TT2$M_AVO;
                   1434:     cur_char_buf[2] &= ~TT2$M_DECCRT;
                   1435:     cur_char_buf[2] &= ~TT2$M_DECCRT2;
                   1436:     cur_char_buf[2] &= ~TT2$M_DRCS;
                   1437:     cur_char_buf[2] &= ~TT2$M_EDIT;
                   1438:     cur_char_buf[2] |= TT2$M_FALLBACK;
                   1439:
                   1440:     status = sys$qiow(0, chan, IO$_SETMODE, 0, 0, 0, cur_char_buf, 12, 0, 0, 0, 0);
                   1441:     if (status == SS$_BADPARAM) {
                   1442:        /* terminal fallback utility not installed on system */
                   1443:        cur_char_buf[2] &= ~TT2$M_FALLBACK;
                   1444:        sys$qiow(0, chan, IO$_SETMODE, 0, 0, 0, cur_char_buf, 12, 0, 0, 0, 0);
                   1445:     } else {
                   1446:        if (status != SS$_NORMAL)
                   1447:            lib$signal(status, 0, 0);
                   1448:     }
                   1449:     sys$dassgn(chan);
                   1450: }
                   1451:
                   1452: void term_mode_native()
                   1453: /* set terminal mode back to native */
                   1454: {
                   1455:     int i;
                   1456:     if (gpoutfile != stdout)
                   1457:        return;                 /* don't modify if not stdout */
                   1458:     sys$assign(&sysoutput_desc, &chan, 0, 0);
                   1459:     sys$qiow(0, chan, IO$_SETMODE, 0, 0, 0, old_char_buf, 12, 0, 0, 0, 0);
                   1460:     for (i = 0; i < 3; ++i)
                   1461:        cur_char_buf[i] = old_char_buf[i];
                   1462:     sys$dassgn(chan);
                   1463: }
                   1464:
                   1465: void term_pasthru()
                   1466: /* set terminal mode pasthru */
                   1467: {
                   1468:     if (gpoutfile != stdout)
                   1469:        return;                 /* don't modify if not stdout */
                   1470:     sys$assign(&sysoutput_desc, &chan, 0, 0);
                   1471:     cur_char_buf[2] |= TT2$M_PASTHRU;
                   1472:     sys$qiow(0, chan, IO$_SETMODE, 0, 0, 0, cur_char_buf, 12, 0, 0, 0, 0);
                   1473:     sys$dassgn(chan);
                   1474: }
                   1475:
                   1476: void term_nopasthru()
                   1477: /* set terminal mode nopasthru */
                   1478: {
                   1479:     if (gpoutfile != stdout)
                   1480:        return;                 /* don't modify if not stdout */
                   1481:     sys$assign(&sysoutput_desc, &chan, 0, 0);
                   1482:     cur_char_buf[2] &= ~TT2$M_PASTHRU;
                   1483:     sys$qiow(0, chan, IO$_SETMODE, 0, 0, 0, cur_char_buf, 12, 0, 0, 0, 0);
                   1484:     sys$dassgn(chan);
                   1485: }
                   1486:
                   1487: void fflush_binary()
                   1488: {
                   1489:     typedef short int INT16;   /* signed 16-bit integers */
                   1490:     register INT16 k;          /* loop index */
                   1491:     if (gpoutfile != stdout) {
                   1492:        /* Stupid VMS fflush() raises error and loses last data block
                   1493:           unless it is full for a fixed-length record binary file.
                   1494:           Pad it here with NULL characters. */
                   1495:        for (k = (INT16) ((*gpoutfile)->_cnt); k > 0; --k)
                   1496:            putc('\0', gpoutfile);
                   1497:        fflush(gpoutfile);
                   1498:     }
                   1499: }
                   1500: #endif /* VMS */

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