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

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

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