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

1.1       maekawa     1: #ifndef lint
1.1.1.2 ! maekawa     2: static char *RCSid = "$Id: term.c,v 1.19.2.3 1999/10/01 10:37:23 lhecking 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:
                    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:
1.1.1.2 ! maekawa   822: /* mainly useful for external code */
        !           823: GP_INLINE int
        !           824: term_count()
        !           825: {
        !           826:     return TERMCOUNT;
        !           827: }
        !           828:
1.1       maekawa   829: void list_terms()
                    830: {
                    831:     register int i;
                    832:     char line_buffer[BUFSIZ];
                    833:
                    834:     StartOutput();
                    835:     sprintf(line_buffer,"\nAvailable terminal types:\n");
                    836:     OutLine(line_buffer);
                    837:
                    838:     for (i = 0; i < TERMCOUNT; i++) {
                    839:        sprintf(line_buffer,"  %15s  %s\n",
                    840:                term_tbl[i].name, term_tbl[i].description);
                    841:        OutLine(line_buffer);
                    842:     }
                    843:
                    844:     EndOutput();
                    845: }
                    846:
                    847:
                    848: /* set_term: get terminal number from name on command line
                    849:  * will change 'term' variable if successful
                    850:  */
                    851: struct termentry *
                    852:  set_term(c_token_arg)
                    853: int c_token_arg;
                    854: {
                    855:     register struct termentry *t = NULL;
                    856:     char *input_name;
                    857:
                    858:     if (!token[c_token_arg].is_token)
                    859:        int_error("terminal name expected", c_token_arg);
                    860:     input_name = input_line + token[c_token_arg].start_index;
                    861:     t = change_term(input_name, token[c_token_arg].length);
                    862:     if (!t)
                    863:        int_error("unknown or ambiguous terminal type; type just 'set terminal' for a list",
                    864:                  c_token_arg);
                    865:
                    866:     /* otherwise the type was changed */
                    867:
                    868:     return (t);
                    869: }
                    870:
                    871: /* change_term: get terminal number from name and set terminal type
                    872:  *
                    873:  * returns NULL for unknown or ambiguous, otherwise is terminal
                    874:  * driver pointer
                    875:  */
                    876: struct termentry *
                    877:  change_term(name, length)
                    878: char *name;
                    879: int length;
                    880: {
                    881:     int i;
                    882:     struct termentry *t = NULL;
                    883:
                    884:     for (i = 0; i < TERMCOUNT; i++) {
                    885:        if (!strncmp(name, term_tbl[i].name, length)) {
                    886:            if (t)
                    887:                return (NULL);  /* ambiguous */
                    888:            t = term_tbl + i;
                    889:        }
                    890:     }
                    891:
                    892:     if (!t)                    /* unknown */
                    893:        return (NULL);
                    894:
                    895:     /* Success: set terminal type now */
                    896:
                    897:     term = t;
                    898:     term_initialised = FALSE;
                    899:     name = term->name;
                    900:
                    901:     if (term->scale != null_scale)
                    902:        fputs("Warning : scale interface is not null_scale - may not work with multiplot\n", stderr);
                    903:
                    904:     /* check that optional fields are initialised to something */
                    905:     if (term->text_angle == 0)
                    906:        term->text_angle = null_text_angle;
                    907:     if (term->justify_text == 0)
                    908:        term->justify_text = null_justify_text;
                    909:     if (term->point == 0)
                    910:        term->point = do_point;
                    911:     if (term->arrow == 0)
                    912:        term->arrow = do_arrow;
                    913:     if (term->set_font == 0)
                    914:        term->set_font = set_font_null;
                    915:     if (term->pointsize == 0)
                    916:        term->pointsize = do_pointsize;
                    917:     if (term->linewidth == 0)
                    918:        term->linewidth = null_linewidth;
                    919:
                    920:     /* Special handling for unixplot term type */
                    921:     if (!strncmp("unixplot", name, 8)) {
                    922:        UP_redirect(2);         /* Redirect actual stdout for unixplots */
                    923:     } else if (unixplot) {
                    924:        UP_redirect(3);         /* Put stdout back together again. */
                    925:     }
                    926:     if (interactive)
                    927:        fprintf(stderr, "Terminal type set to '%s'\n", name);
                    928:
                    929:     return (t);
                    930: }
                    931:
                    932: /*
                    933:  * Routine to detect what terminal is being used (or do anything else
                    934:  * that would be nice).  One anticipated (or allowed for) side effect
                    935:  * is that the global ``term'' may be set.
                    936:  * The environment variable GNUTERM is checked first; if that does
                    937:  * not exist, then the terminal hardware is checked, if possible,
                    938:  * and finally, we can check $TERM for some kinds of terminals.
                    939:  * A default can be set with -DDEFAULTTERM=myterm in the Makefile
                    940:  * or #define DEFAULTTERM myterm in term.h
                    941:  */
                    942: /* thanks to osupyr!alden (Dave Alden) for the original GNUTERM code */
                    943: void init_terminal()
                    944: {
                    945:     char *term_name = DEFAULTTERM;
                    946: #if (defined(__TURBOC__) && defined(MSDOS) && !defined(_Windows)) || defined(NEXT) || defined(SUN) || defined(X11)
                    947:     char *env_term = NULL;     /* from TERM environment var */
                    948: #endif
                    949: #ifdef X11
                    950:     char *display = NULL;
                    951: #endif
                    952:     char *gnuterm = NULL;
                    953:
                    954:     /* GNUTERM environment variable is primary */
                    955:     gnuterm = getenv("GNUTERM");
                    956:     if (gnuterm != (char *) NULL) {
                    957:        term_name = gnuterm;
                    958:     } else {
                    959:
                    960: #ifdef __ZTC__
                    961:        term_name = ztc_init();
                    962: #endif
                    963:
                    964: #ifdef VMS
                    965:        term_name = vms_init();
                    966: #endif /* VMS */
                    967:
                    968: #ifdef NEXT
                    969:        env_term = getenv("TERM");
                    970:        if (term_name == (char *) NULL
1.1.1.2 ! maekawa   971:            && env_term != (char *) NULL && strcmp(env_term, "next") == 0)
1.1       maekawa   972:            term_name = "next";
                    973: #endif /* NeXT */
                    974:
                    975: #ifdef SUN
                    976:        env_term = getenv("TERM");      /* try $TERM */
                    977:        if (term_name == (char *) NULL
                    978:            && env_term != (char *) NULL && strcmp(env_term, "sun") == 0)
                    979:            term_name = "sun";
                    980: #endif /* SUN */
                    981:
                    982: #ifdef _Windows
                    983:        term_name = "win";
                    984: #endif /* _Windows */
                    985:
                    986: #ifdef GPR
                    987:        /* find out whether stdout is a DM pad. See term/gpr.trm */
                    988:        if (gpr_isa_pad())
                    989:            term_name = "gpr";
                    990: #else
                    991: # ifdef APOLLO
                    992:        /* find out whether stdout is a DM pad. See term/apollo.trm */
                    993:        if (apollo_isa_pad())
                    994:            term_name = "apollo";
                    995: # endif                                /* APOLLO */
                    996: #endif /* GPR    */
                    997:
                    998: #ifdef X11
                    999:        env_term = getenv("TERM");      /* try $TERM */
                   1000:        if (term_name == (char *) NULL
                   1001:            && env_term != (char *) NULL && strcmp(env_term, "xterm") == 0)
                   1002:            term_name = "x11";
                   1003:        display = getenv("DISPLAY");
                   1004:        if (term_name == (char *) NULL && display != (char *) NULL)
                   1005:            term_name = "x11";
                   1006:        if (X11_Display)
                   1007:            term_name = "x11";
                   1008: #endif /* x11 */
                   1009:
                   1010: #ifdef AMIGA
                   1011:        term_name = "amiga";
                   1012: #endif
                   1013:
                   1014: #if defined(ATARI) || defined(MTOS)
                   1015:        term_name = "atari";
                   1016: #endif
                   1017:
                   1018: #ifdef UNIXPC
                   1019:        if (iswind() == 0) {
                   1020:            term_name = "unixpc";
                   1021:        }
                   1022: #endif /* unixpc */
                   1023:
                   1024: #ifdef CGI
                   1025:        if (getenv("CGIDISP") || getenv("CGIPRNT"))
                   1026:            term_name = "cgi";
                   1027: #endif /*CGI */
                   1028:
                   1029: #ifdef DJGPP
                   1030:        term_name = "svga";
                   1031: #endif
                   1032:
                   1033: #ifdef GRASS
                   1034:        term_name = "grass";
                   1035: #endif
                   1036:
                   1037: #ifdef OS2
                   1038: /*      if (_osmode==OS2_MODE) term_name = "pm" ; else term_name = "emxvga"; */
                   1039: # ifdef X11
                   1040: /* This catch is hopefully ok ... */
                   1041:        env_term = getenv("WINDOWID");
                   1042:        display = getenv("DISPLAY");
                   1043:        if ((env_term != (char *) NULL) && (display != (char *) NULL))
                   1044:            term_name = "x11";
                   1045:        else
                   1046: # endif                                /* X11 */
                   1047:            term_name = "pm";
                   1048: #endif /*OS2 */
                   1049:
                   1050: /* set linux terminal only if LINUX_setup was successfull, if we are on X11
                   1051:    LINUX_setup has failed, also if we are logged in by network */
                   1052: #ifdef LINUXVGA
                   1053:        if (LINUX_graphics_allowed)
                   1054:            term_name = "linux";
                   1055: #endif /* LINUXVGA */
                   1056:     }
                   1057:
                   1058:     /* We have a name, try to set term type */
                   1059:     if (term_name != NULL && *term_name != '\0') {
                   1060:        if (change_term(term_name, (int) strlen(term_name)))
                   1061:            return;
                   1062:        fprintf(stderr, "Unknown or ambiguous terminal name '%s'\n", term_name);
                   1063:     }
                   1064:     change_term("unknown", 7);
                   1065: }
                   1066:
                   1067:
                   1068: #ifdef __ZTC__
                   1069: char *ztc_init()
                   1070: {
                   1071:     int g_mode;
                   1072:     char *term_name = NULL;
                   1073:
                   1074:     g_mode = fg_init();
                   1075:
                   1076:     switch (g_mode) {
                   1077:     case FG_NULL:
                   1078:        fputs("Graphics card not detected or not supported.\n", stderr);
                   1079:        exit(1);
                   1080:     case FG_HERCFULL:
                   1081:        term_name = "hercules";
                   1082:        break;
                   1083:     case FG_EGAMONO:
                   1084:        term_name = "egamono";
                   1085:        break;
                   1086:     case FG_EGAECD:
                   1087:        term_name = "egalib";
                   1088:        break;
                   1089:     case FG_VGA11:
                   1090:        term_name = "vgamono";
                   1091:        break;
                   1092:     case FG_VGA12:
                   1093:        term_name = "vgalib";
                   1094:        break;
                   1095:     case FG_VESA6A:
                   1096:        term_name = "svgalib";
                   1097:        break;
                   1098:     case FG_VESA5:
                   1099:        term_name = "ssvgalib";
                   1100:        break;
                   1101:     }
                   1102:     fg_term();
                   1103:     return (term_name);
                   1104: }
                   1105: #endif /* __ZTC__ */
                   1106:
                   1107:
                   1108: /*
                   1109:    This is always defined so we don't have to have command.c know if it
                   1110:    is there or not.
                   1111:  */
                   1112: #if !(defined(UNIXPLOT) || defined(GNUGRAPH))
                   1113: void UP_redirect(caller)
                   1114: int caller;
                   1115: {
                   1116:     caller = caller;           /* to stop Turbo C complaining
                   1117:                                   * about caller not being used */
                   1118: }
                   1119:
                   1120: #else /* UNIXPLOT || GNUGRAPH */
                   1121: void UP_redirect(caller)
                   1122: int caller;
                   1123: /*
                   1124:    Unixplot can't really write to gpoutfile--it wants to write to stdout.
                   1125:    This is normally ok, but the original design of gnuplot gives us
                   1126:    little choice.  Originally users of unixplot had to anticipate
                   1127:    their needs and redirect all I/O to a file...  Not very gnuplot-like.
                   1128:
                   1129:    caller:  1 - called from SET OUTPUT "FOO.OUT"
                   1130:    2 - called from SET TERM UNIXPLOT
                   1131:    3 - called from SET TERM other
                   1132:    4 - called from SET OUTPUT
                   1133:  */
                   1134: {
                   1135:     switch (caller) {
                   1136:     case 1:
                   1137:        /* Don't save, just replace stdout w/gpoutfile (save was already done). */
                   1138:        if (unixplot)
                   1139:            *(stdout) = *(gpoutfile);   /* Copy FILE structure */
                   1140:        break;
                   1141:     case 2:
                   1142:        if (!unixplot) {
                   1143:            fflush(stdout);
                   1144:            save_stdout = *(stdout);
                   1145:            *(stdout) = *(gpoutfile);   /* Copy FILE structure */
                   1146:            unixplot = 1;
                   1147:        }
                   1148:        break;
                   1149:     case 3:
                   1150:        /* New terminal in use--put stdout back to original. */
                   1151: /* closepl(); *//* This is called by the term. */
                   1152:        fflush(stdout);
                   1153:        *(stdout) = save_stdout;        /* Copy FILE structure */
                   1154:        unixplot = 0;
                   1155:        break;
                   1156:     case 4:
                   1157:        /*  User really wants to go to normal output... */
                   1158:        if (unixplot) {
                   1159:            fflush(stdout);
                   1160:            *(stdout) = save_stdout;    /* Copy FILE structure */
                   1161:        }
                   1162:        break;
                   1163:     }
                   1164: }
                   1165: #endif /* UNIXPLOT || GNUGRAPH */
                   1166:
                   1167:
                   1168: /* test terminal by drawing border and text */
                   1169: /* called from command test */
                   1170: void test_term()
                   1171: {
                   1172:     register struct termentry *t = term;
                   1173:     char *str;
                   1174:     int x, y, xl, yl, i;
                   1175:     unsigned int xmax_t, ymax_t;
                   1176:     char label[MAX_ID_LEN];
                   1177:     int key_entry_height;
                   1178:     int p_width;
                   1179:
                   1180:     term_start_plot();
                   1181:     screen_ok = FALSE;
                   1182:     xmax_t = (unsigned int) (t->xmax * xsize);
                   1183:     ymax_t = (unsigned int) (t->ymax * ysize);
                   1184:
                   1185:     p_width = pointsize * (t->h_tic);
                   1186:     key_entry_height = pointsize * (t->v_tic) * 1.25;
                   1187:     if (key_entry_height < (t->v_char))
                   1188:        key_entry_height = (t->v_char);
                   1189:
                   1190:     /* border linetype */
1.1.1.2 ! maekawa  1191:     (*t->linewidth) (1.0);
1.1       maekawa  1192:     (*t->linetype) (-2);
                   1193:     (*t->move) (0, 0);
                   1194:     (*t->vector) (xmax_t - 1, 0);
                   1195:     (*t->vector) (xmax_t - 1, ymax_t - 1);
                   1196:     (*t->vector) (0, ymax_t - 1);
                   1197:     (*t->vector) (0, 0);
                   1198:     (void) (*t->justify_text) (LEFT);
                   1199:     (*t->put_text) (t->h_char * 5, ymax_t - t->v_char * 3, "Terminal Test");
                   1200:     /* axis linetype */
                   1201:     (*t->linetype) (-1);
                   1202:     (*t->move) (xmax_t / 2, 0);
                   1203:     (*t->vector) (xmax_t / 2, ymax_t - 1);
                   1204:     (*t->move) (0, ymax_t / 2);
                   1205:     (*t->vector) (xmax_t - 1, ymax_t / 2);
                   1206:     /* test width and height of characters */
                   1207:     (*t->linetype) (-2);
                   1208:     (*t->move) (xmax_t / 2 - t->h_char * 10, ymax_t / 2 + t->v_char / 2);
                   1209:     (*t->vector) (xmax_t / 2 + t->h_char * 10, ymax_t / 2 + t->v_char / 2);
                   1210:     (*t->vector) (xmax_t / 2 + t->h_char * 10, ymax_t / 2 - t->v_char / 2);
                   1211:     (*t->vector) (xmax_t / 2 - t->h_char * 10, ymax_t / 2 - t->v_char / 2);
                   1212:     (*t->vector) (xmax_t / 2 - t->h_char * 10, ymax_t / 2 + t->v_char / 2);
                   1213:     (*t->put_text) (xmax_t / 2 - t->h_char * 10, ymax_t / 2,
                   1214:                    "12345678901234567890");
                   1215:     /* test justification */
                   1216:     (void) (*t->justify_text) (LEFT);
                   1217:     (*t->put_text) (xmax_t / 2, ymax_t / 2 + t->v_char * 6, "left justified");
                   1218:     str = "centre+d text";
                   1219:     if ((*t->justify_text) (CENTRE))
                   1220:        (*t->put_text) (xmax_t / 2,
                   1221:                        ymax_t / 2 + t->v_char * 5, str);
                   1222:     else
                   1223:        (*t->put_text) (xmax_t / 2 - strlen(str) * t->h_char / 2,
                   1224:                        ymax_t / 2 + t->v_char * 5, str);
                   1225:     str = "right justified";
                   1226:     if ((*t->justify_text) (RIGHT))
                   1227:        (*t->put_text) (xmax_t / 2,
                   1228:                        ymax_t / 2 + t->v_char * 4, str);
                   1229:     else
                   1230:        (*t->put_text) (xmax_t / 2 - strlen(str) * t->h_char,
                   1231:                        ymax_t / 2 + t->v_char * 4, str);
                   1232:     /* test text angle */
                   1233:     str = "rotated ce+ntred text";
                   1234:     if ((*t->text_angle) (1)) {
                   1235:        if ((*t->justify_text) (CENTRE))
                   1236:            (*t->put_text) (t->v_char,
                   1237:                            ymax_t / 2, str);
                   1238:        else
                   1239:            (*t->put_text) (t->v_char,
                   1240:                            ymax_t / 2 - strlen(str) * t->h_char / 2, str);
                   1241:     } else {
                   1242:        (void) (*t->justify_text) (LEFT);
                   1243:        (*t->put_text) (t->h_char * 2, ymax_t / 2 - t->v_char * 2, "Can't rotate text");
                   1244:     }
                   1245:     (void) (*t->justify_text) (LEFT);
                   1246:     (void) (*t->text_angle) (0);
                   1247:     /* test tic size */
                   1248:     (*t->move) ((unsigned int) (xmax_t / 2 + t->h_tic * (1 + ticscale)), (unsigned) 0);
                   1249:     (*t->vector) ((unsigned int) (xmax_t / 2 + t->h_tic * (1 + ticscale)), (unsigned int)
                   1250:                  (ticscale * t->v_tic));
                   1251:     (*t->move) ((unsigned int) (xmax_t / 2), (unsigned int) (t->v_tic * (1 + ticscale)));
                   1252:     (*t->vector) ((unsigned int) (xmax_t / 2 + ticscale * t->h_tic), (unsigned int) (t->v_tic * (1
                   1253:                                                                                                 + ticscale)));
                   1254:     (*t->put_text) ((unsigned int) (xmax_t / 2 - 10 * t->h_char), (unsigned int) (t->v_tic * 2 +
                   1255:                                                                                  t->v_char / 2),
                   1256:                    "test tics");
                   1257:
                   1258:     /* test line and point types */
                   1259:     x = xmax_t - t->h_char * 6 - p_width;
                   1260:     y = ymax_t - key_entry_height;
                   1261:     (*t->pointsize) (pointsize);
                   1262:     for (i = -2; y > key_entry_height; i++) {
                   1263:        (*t->linetype) (i);
                   1264:        /*      (void) sprintf(label,"%d",i);  Jorgen Lippert
                   1265:           lippert@risoe.dk */
                   1266:        (void) sprintf(label, "%d", i + 1);
                   1267:        if ((*t->justify_text) (RIGHT))
                   1268:            (*t->put_text) (x, y, label);
                   1269:        else
                   1270:            (*t->put_text) (x - strlen(label) * t->h_char, y, label);
                   1271:        (*t->move) (x + t->h_char, y);
                   1272:        (*t->vector) (x + t->h_char * 4, y);
                   1273:        if (i >= -1)
                   1274:            (*t->point) (x + t->h_char * 5 + p_width / 2, y, i);
                   1275:        y -= key_entry_height;
                   1276:     }
                   1277:     /* test some arrows */
                   1278:     (*t->linewidth) (1.0);
                   1279:     (*t->linetype) (0);
                   1280:     x = xmax_t / 4;
                   1281:     y = ymax_t / 4;
                   1282:     xl = t->h_tic * 5;
                   1283:     yl = t->v_tic * 5;
                   1284:     (*t->arrow) (x, y, x + xl, y, TRUE);
                   1285:     (*t->arrow) (x, y, x + xl / 2, y + yl, TRUE);
                   1286:     (*t->arrow) (x, y, x, y + yl, TRUE);
                   1287:     (*t->arrow) (x, y, x - xl / 2, y + yl, FALSE);
                   1288:     (*t->arrow) (x, y, x - xl, y, TRUE);
                   1289:     (*t->arrow) (x, y, x - xl, y - yl, TRUE);
                   1290:     (*t->arrow) (x, y, x, y - yl, TRUE);
                   1291:     (*t->arrow) (x, y, x + xl, y - yl, TRUE);
                   1292:
                   1293:     term_end_plot();
                   1294: }
                   1295:
                   1296: #if 0
                   1297: # if defined(MSDOS)||defined(g)||defined(MTOS)||defined(OS2)||defined(_Windows)||defined(DOS386)
                   1298: /* output for some terminal types must be binary to stop non Unix computers
                   1299:    changing \n to \r\n.
                   1300:    If the output is not STDOUT, the following code reopens gpoutfile
                   1301:    with binary mode. */
                   1302: void reopen_binary()
                   1303: {
                   1304:     if (outstr) {
                   1305:        (void) fclose(gpoutfile);
                   1306: #  ifdef _Windows
                   1307:        if (!stricmp(outstr, "PRN")) {
                   1308:            /* use temp file for windows */
                   1309:            (void) strcpy(filename, win_prntmp);
                   1310:        }
                   1311: #  endif
                   1312:        if ((gpoutfile = fopen(filename, "wb")) == (FILE *) NULL) {
                   1313:            if ((gpoutfile = fopen(filename, "w")) == (FILE *) NULL) {
                   1314:                os_error("cannot reopen file with binary type; output unknown",
                   1315:                         NO_CARET);
                   1316:            } else {
                   1317:                os_error("cannot reopen file with binary type; output reset to ascii",
                   1318:                         NO_CARET);
                   1319:            }
                   1320:        }
                   1321: #  if defined(__TURBOC__) && defined(MSDOS)
                   1322: #   ifndef _Windows
                   1323:        if (!stricmp(outstr, "PRN")) {
                   1324:            /* Put the printer into binary mode. */
                   1325:            union REGS regs;
                   1326:            regs.h.ah = 0x44;   /* ioctl */
                   1327:            regs.h.al = 0;      /* get device info */
                   1328:            regs.x.bx = fileno(gpoutfile);
                   1329:            intdos(&regs, &regs);
                   1330:            regs.h.dl |= 0x20;  /* binary (no ^Z intervention) */
                   1331:            regs.h.dh = 0;
                   1332:            regs.h.ah = 0x44;   /* ioctl */
                   1333:            regs.h.al = 1;      /* set device info */
                   1334:            intdos(&regs, &regs);
                   1335:        }
                   1336: #   endif                      /* !_Windows */
                   1337: #  endif                       /* TURBOC && MSDOS */
                   1338:     }
                   1339: }
                   1340:
                   1341: # endif                                /* MSDOS || g || MTOS || ... */
                   1342: #endif /* 0 */
                   1343:
                   1344: #ifdef VMS
                   1345: /* these are needed to modify terminal characteristics */
                   1346: # ifndef VWS_XMAX
                   1347:    /* avoid duplicate warning; VWS includes these */
                   1348: #  include <descrip.h>
                   1349: #  include <ssdef.h>
                   1350: # endif /* !VWS_MAX */
                   1351: # include <iodef.h>
                   1352: # include <ttdef.h>
                   1353: # include <tt2def.h>
                   1354: # include <dcdef.h>
                   1355: # include <stat.h>
                   1356: # include <fab.h>
                   1357: /* If you use WATCOM C or a very strict ANSI compiler, you may have to
                   1358:  * delete or comment out the following 3 lines: */
                   1359: # ifndef TT2$M_DECCRT3         /* VT300 not defined as of VAXC v2.4 */
                   1360: #  define TT2$M_DECCRT3 0X80000000
                   1361: # endif
                   1362: static unsigned short chan;
                   1363: static int old_char_buf[3], cur_char_buf[3];
                   1364: $DESCRIPTOR(sysoutput_desc, "SYS$OUTPUT");
                   1365:
                   1366: char *vms_init()
                   1367: /*
                   1368:  *  Look first for decw$display (decterms do regis)
                   1369:  *  Determine if we have a regis terminal
                   1370:  * and save terminal characteristics
                   1371:  */
                   1372: {
                   1373:     /* Save terminal characteristics in old_char_buf and
                   1374:        initialise cur_char_buf to current settings. */
                   1375:     int i;
                   1376:     if (getenv("DECW$DISPLAY"))
                   1377:        return ("x11");
                   1378:     atexit(vms_reset);
                   1379:     sys$assign(&sysoutput_desc, &chan, 0, 0);
                   1380:     sys$qiow(0, chan, IO$_SENSEMODE, 0, 0, 0, old_char_buf, 12, 0, 0, 0, 0);
                   1381:     for (i = 0; i < 3; ++i)
                   1382:        cur_char_buf[i] = old_char_buf[i];
                   1383:     sys$dassgn(chan);
                   1384:
                   1385:     /* Test if terminal is regis */
                   1386:     if ((cur_char_buf[2] & TT2$M_REGIS) == TT2$M_REGIS)
                   1387:        return ("regis");
                   1388:     return (NULL);
                   1389: }
                   1390:
                   1391: void vms_reset()
                   1392: /* set terminal to original state */
                   1393: {
                   1394:     int i;
                   1395:     sys$assign(&sysoutput_desc, &chan, 0, 0);
                   1396:     sys$qiow(0, chan, IO$_SETMODE, 0, 0, 0, old_char_buf, 12, 0, 0, 0, 0);
                   1397:     for (i = 0; i < 3; ++i)
                   1398:        cur_char_buf[i] = old_char_buf[i];
                   1399:     sys$dassgn(chan);
                   1400: }
                   1401:
                   1402: void term_mode_tek()
                   1403: /* set terminal mode to tektronix */
                   1404: {
                   1405:     long status;
                   1406:     if (gpoutfile != stdout)
                   1407:        return;                 /* don't modify if not stdout */
                   1408:     sys$assign(&sysoutput_desc, &chan, 0, 0);
                   1409:     cur_char_buf[0] = 0x004A0000 | DC$_TERM | (TT$_TEK401X << 8);
                   1410:     cur_char_buf[1] = (cur_char_buf[1] & 0x00FFFFFF) | 0x18000000;
                   1411:
                   1412:     cur_char_buf[1] &= ~TT$M_CRFILL;
                   1413:     cur_char_buf[1] &= ~TT$M_ESCAPE;
                   1414:     cur_char_buf[1] &= ~TT$M_HALFDUP;
                   1415:     cur_char_buf[1] &= ~TT$M_LFFILL;
                   1416:     cur_char_buf[1] &= ~TT$M_MECHFORM;
                   1417:     cur_char_buf[1] &= ~TT$M_NOBRDCST;
                   1418:     cur_char_buf[1] &= ~TT$M_NOECHO;
                   1419:     cur_char_buf[1] &= ~TT$M_READSYNC;
                   1420:     cur_char_buf[1] &= ~TT$M_REMOTE;
                   1421:     cur_char_buf[1] |= TT$M_LOWER;
                   1422:     cur_char_buf[1] |= TT$M_TTSYNC;
                   1423:     cur_char_buf[1] |= TT$M_WRAP;
                   1424:     cur_char_buf[1] &= ~TT$M_EIGHTBIT;
                   1425:     cur_char_buf[1] &= ~TT$M_MECHTAB;
                   1426:     cur_char_buf[1] &= ~TT$M_SCOPE;
                   1427:     cur_char_buf[1] |= TT$M_HOSTSYNC;
                   1428:
                   1429:     cur_char_buf[2] &= ~TT2$M_APP_KEYPAD;
                   1430:     cur_char_buf[2] &= ~TT2$M_BLOCK;
                   1431:     cur_char_buf[2] &= ~TT2$M_DECCRT3;
                   1432:     cur_char_buf[2] &= ~TT2$M_LOCALECHO;
                   1433:     cur_char_buf[2] &= ~TT2$M_PASTHRU;
                   1434:     cur_char_buf[2] &= ~TT2$M_REGIS;
                   1435:     cur_char_buf[2] &= ~TT2$M_SIXEL;
                   1436:     cur_char_buf[2] |= TT2$M_BRDCSTMBX;
                   1437:     cur_char_buf[2] |= TT2$M_EDITING;
                   1438:     cur_char_buf[2] |= TT2$M_INSERT;
                   1439:     cur_char_buf[2] |= TT2$M_PRINTER;
                   1440:     cur_char_buf[2] &= ~TT2$M_ANSICRT;
                   1441:     cur_char_buf[2] &= ~TT2$M_AVO;
                   1442:     cur_char_buf[2] &= ~TT2$M_DECCRT;
                   1443:     cur_char_buf[2] &= ~TT2$M_DECCRT2;
                   1444:     cur_char_buf[2] &= ~TT2$M_DRCS;
                   1445:     cur_char_buf[2] &= ~TT2$M_EDIT;
                   1446:     cur_char_buf[2] |= TT2$M_FALLBACK;
                   1447:
                   1448:     status = sys$qiow(0, chan, IO$_SETMODE, 0, 0, 0, cur_char_buf, 12, 0, 0, 0, 0);
                   1449:     if (status == SS$_BADPARAM) {
                   1450:        /* terminal fallback utility not installed on system */
                   1451:        cur_char_buf[2] &= ~TT2$M_FALLBACK;
                   1452:        sys$qiow(0, chan, IO$_SETMODE, 0, 0, 0, cur_char_buf, 12, 0, 0, 0, 0);
                   1453:     } else {
                   1454:        if (status != SS$_NORMAL)
                   1455:            lib$signal(status, 0, 0);
                   1456:     }
                   1457:     sys$dassgn(chan);
                   1458: }
                   1459:
                   1460: void term_mode_native()
                   1461: /* set terminal mode back to native */
                   1462: {
                   1463:     int i;
                   1464:     if (gpoutfile != stdout)
                   1465:        return;                 /* don't modify if not stdout */
                   1466:     sys$assign(&sysoutput_desc, &chan, 0, 0);
                   1467:     sys$qiow(0, chan, IO$_SETMODE, 0, 0, 0, old_char_buf, 12, 0, 0, 0, 0);
                   1468:     for (i = 0; i < 3; ++i)
                   1469:        cur_char_buf[i] = old_char_buf[i];
                   1470:     sys$dassgn(chan);
                   1471: }
                   1472:
                   1473: void term_pasthru()
                   1474: /* set terminal mode pasthru */
                   1475: {
                   1476:     if (gpoutfile != stdout)
                   1477:        return;                 /* don't modify if not stdout */
                   1478:     sys$assign(&sysoutput_desc, &chan, 0, 0);
                   1479:     cur_char_buf[2] |= TT2$M_PASTHRU;
                   1480:     sys$qiow(0, chan, IO$_SETMODE, 0, 0, 0, cur_char_buf, 12, 0, 0, 0, 0);
                   1481:     sys$dassgn(chan);
                   1482: }
                   1483:
                   1484: void term_nopasthru()
                   1485: /* set terminal mode nopasthru */
                   1486: {
                   1487:     if (gpoutfile != stdout)
                   1488:        return;                 /* don't modify if not stdout */
                   1489:     sys$assign(&sysoutput_desc, &chan, 0, 0);
                   1490:     cur_char_buf[2] &= ~TT2$M_PASTHRU;
                   1491:     sys$qiow(0, chan, IO$_SETMODE, 0, 0, 0, cur_char_buf, 12, 0, 0, 0, 0);
                   1492:     sys$dassgn(chan);
                   1493: }
                   1494:
                   1495: void fflush_binary()
                   1496: {
                   1497:     typedef short int INT16;   /* signed 16-bit integers */
                   1498:     register INT16 k;          /* loop index */
                   1499:     if (gpoutfile != stdout) {
                   1500:        /* Stupid VMS fflush() raises error and loses last data block
                   1501:           unless it is full for a fixed-length record binary file.
                   1502:           Pad it here with NULL characters. */
                   1503:        for (k = (INT16) ((*gpoutfile)->_cnt); k > 0; --k)
                   1504:            putc('\0', gpoutfile);
                   1505:        fflush(gpoutfile);
                   1506:     }
                   1507: }
                   1508: #endif /* VMS */

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