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