home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / maths / plplot / plplot_2 / drivers / tek.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-26  |  23.2 KB  |  960 lines

  1. /* $Id: tek.c,v 1.32 1994/08/26 19:21:55 mjl Exp $
  2.  * $Log: tek.c,v $
  3.  * Revision 1.32  1994/08/26  19:21:55  mjl
  4.  * Added support for the Conex vt320 Tek4010/4014/4105 terminal emulator (DOS).
  5.  * Much cleaning up and optimizations.  Contributed by Mark Olesen.
  6.  *
  7.  * Revision 1.31  1994/07/23  04:44:27  mjl
  8.  * Added conditional compilation of atexit() code based on STDC_HEADERS.
  9.  *
  10.  * Revision 1.30  1994/07/22  22:21:28  mjl
  11.  * Eliminated a gcc -Wall warning.
  12.  *
  13.  * Revision 1.29  1994/07/19  22:30:29  mjl
  14.  * All device drivers: enabling macro renamed to PLD_<driver>, where <driver>
  15.  * is xwin, ps, etc.  See plDevs.h for more detail.
  16.  *
  17.  * Revision 1.28  1994/06/30  17:52:35  mjl
  18.  * Made another pass to eliminate warnings when using gcc -Wall, especially
  19.  * those created by changing a PLINT from a long to an int.
  20.  *
  21.  * Revision 1.27  1994/06/24  04:38:35  mjl
  22.  * Greatly reworked the POSIX_TTY code that puts the terminal into cbreak
  23.  * mode.  Now, initially both the original and modified terminal states are
  24.  * saved.  When the terminal goes into graphics mode, it is also put into
  25.  * cbreak mode.  This ensures that the program gets character-at-a-time
  26.  * input, which is good for quitting <Q> PLplot or for paging in plrender.
  27.  * When the terminal goes into text mode, the original terminal state
  28.  * (canonical input, typically) is restored, which is good for reading user
  29.  * input or command interpreters.  Just make sure you use plgra() and
  30.  * pltext() for switching; if you switch the terminal locally it may get
  31.  * confused until the next plgra() or pltext().
  32.  *
  33.  * Revision 1.26  1994/06/23  22:32:07  mjl
  34.  * Now ensures that device is in graphics mode before issuing any graphics
  35.  * instruction.
  36. */
  37.  
  38. /*    tek.c
  39.  
  40.     PLPLOT tektronix device & emulators driver.
  41. */
  42. #include "plDevs.h"
  43.  
  44. #if defined(PLD_xterm) ||        /* xterm */ \
  45.     defined(PLD_tek4010) ||        /* TEK 4010 */ \
  46.     defined(PLD_tek4107) ||        /* TEK 4107 */ \
  47.     defined(PLD_mskermit) ||        /* MS-kermit emulator */ \
  48.     defined(PLD_versaterm) ||        /* Versaterm emulator */ \
  49.     defined(PLD_vlt) ||            /* VLT emulator */ \
  50.     defined(PLD_conex)            /* conex emulator 4010/4014/4105 */
  51.  
  52. #include "plplotP.h"
  53. #include "drivers.h"
  54. #include "plevent.h"
  55.  
  56. #include <ctype.h>
  57.  
  58. /* Static function prototypes */
  59.  
  60. static void    WaitForPage    (PLStream *pls);
  61. static void    EventHandler    (PLStream *pls, int input_char);
  62. static void    tek_init    (PLStream *pls);
  63. static void    tek_text    (PLStream *pls);
  64. static void    tek_graph    (PLStream *pls);
  65. static void    fill_polygon    (PLStream *pls);
  66. static void    encode_int    (char *c, int i);
  67. static void    encode_vector    (char *c, int x, int y);
  68. static void    tek_vector    (PLStream *pls, int x, int y);
  69. static void    scolor        (int icol, int r, int g, int b);
  70. static void    setcmap        (PLStream *pls);
  71.  
  72. /* Stuff for handling tty cbreak mode */
  73.  
  74. #ifdef POSIX_TTY
  75.  
  76. #include <termios.h>
  77. #include <unistd.h>
  78.  
  79. static struct termios    termios_cbreak, termios_reset;
  80. static enum { RESET, CBREAK } ttystate = RESET;
  81.  
  82. static void tty_atexit    (void);
  83. static void tty_setup    (void);
  84. static int  tty_cbreak    (void);
  85. static int  tty_reset    (void);
  86. #endif
  87.  
  88. /* Pixel settings */
  89.  
  90. #define TEKX   1023
  91. #define TEKY    779
  92.  
  93. /* Graphics control characters. */
  94.  
  95. #define BEL_CHAR    '\007'        /* BEL char = ^G = 7 */
  96. #define CLEAR_VIEW    "\033\f"    /* clear the view = ESC FF */
  97.  
  98. #define ALPHA_MODE    "\037"        /* Enter Alpha mode = US */
  99. #define VECTOR_MODE    "\035"        /* Enter Vector mode = GS */
  100. #define GIN_MODE    "\033\032"    /* Enter GIN mode = ESC SUB */
  101. #define XTERM_VTMODE    "\033\003"    /* End Tek mode (xterm) = ESC ETX */
  102.  
  103. /* Static vars */
  104.  
  105. enum {tek4010, tek4105, tek4107, xterm, mskermit, vlt, versaterm};
  106.  
  107. static exit_eventloop = 0;
  108. static int curcolor;
  109.  
  110. /* color for MS-DOS Kermit v2.31 (and up) tektronix emulator 
  111.  *    0 = normal, 1 = bright 
  112.  *    foreground color (30-37) = 30 + colors
  113.  *        where colors are   1=red, 2=green, 4=blue 
  114.  */
  115. #ifdef PLD_mskermit
  116. static char *kermit_color[15]= {
  117.    "0;30","0;37",
  118.    "0;32","0;36","0;31","0;35",
  119.    "1;34","1;33","1;31","1;37",
  120.    "1;35","1;32","1;36","0;34",
  121.    "0;33"};
  122. #endif
  123. /*----------------------------------------------------------------------*\
  124.  * plD_init_xterm()    xterm 
  125.  * plD_init_tekt()    Tek 4010 terminal
  126.  * plD_init_tekf()    Tek 4010 file
  127.  * plD_init_tek4107t()    Tek 4105/4107 terminal
  128.  * plD_init_tek4107f()    Tek 4105/4107 file
  129.  * plD_init_mskermit()    MS-Kermit emulator (DOS)
  130.  * plD_init_vlt()    VLT emulator (Amiga)
  131.  * plD_init_versaterm()    VersaTerm emulator (Mac)
  132.  * plD_init_conex()    Conex vt320/Tek 4105 emulator (DOS)
  133.  *
  134.  * Initialize device.  These just set attributes for the particular
  135.  * tektronix device, then call tek_init().  The following attributes can
  136.  * be set:
  137.  *
  138.  * pls->termin        if a terminal device
  139.  * pls->color        if color (1), if only fixed colors (2)
  140.  * pls->dev_fill0    if can handle solid area fill
  141.  * pls->dev_fill1    if can handle pattern area fill
  142.  *
  143. \*----------------------------------------------------------------------*/
  144.  
  145. #ifdef PLD_xterm
  146. void 
  147. plD_init_xterm(PLStream *pls)
  148. {
  149.     pls->dev_minor = xterm;
  150.     pls->termin = 1;
  151.     tek_init(pls);
  152. }
  153. #endif    /* xterm */
  154.  
  155. #if defined (PLD_tek4010)
  156. void
  157. plD_init_tekt(PLStream *pls)
  158. {
  159.     pls->termin = 1;
  160.     plD_init_tekf(pls);
  161. }
  162.  
  163. void
  164. plD_init_tekf(PLStream *pls)
  165. {
  166.     pls->dev_minor = tek4010;
  167.     tek_init(pls);
  168. }
  169. #endif    /* PLD_tek4010 (term & file) */
  170.  
  171.  
  172. #if defined (PLD_tek4107)
  173. void
  174. plD_init_tek4107t(PLStream *pls)
  175. {
  176.     pls->termin = 1;
  177.     plD_init_tek4107f(pls);
  178. }
  179.  
  180. void
  181. plD_init_tek4107f(PLStream *pls)
  182. {
  183.     pls->dev_minor = tek4107;
  184.     pls->color = 1;
  185.     pls->dev_fill0 = 1;
  186.     tek_init(pls);
  187. }
  188. #endif    /* PLD_tek4107 (term & file) */
  189.  
  190. #ifdef PLD_mskermit
  191. void
  192. plD_init_mskermit(PLStream *pls)
  193. {
  194.     pls->dev_minor = mskermit;
  195.     pls->termin = 1;
  196.     pls->color = 1;
  197.     pls->dev_fill0 = 1;
  198.     tek_init(pls);
  199. }
  200. #endif    /* PLD_mskermit */
  201.  
  202. #ifdef PLD_vlt
  203. void
  204. plD_init_vlt(PLStream *pls)
  205. {
  206.     pls->dev_minor = vlt;
  207.     pls->termin = 1;
  208.     pls->color = 1;
  209.     pls->dev_fill0 = 1;
  210.     tek_init(pls);
  211. }
  212. #endif    /* PLD_vlt */
  213.  
  214. #ifdef PLD_versaterm
  215. void
  216. plD_init_versaterm(PLStream *pls)
  217. {
  218.     pls->dev_minor = versaterm;
  219.     pls->termin = 1;
  220.     pls->color = 1;
  221.     pls->dev_fill0 = 1;
  222.     tek_init(pls);
  223. }
  224. #endif    /* PLD_versaterm */
  225.  
  226. #ifdef PLD_conex
  227. void
  228. plD_init_conex(PLStream *pls)
  229. {
  230.     pls->dev_minor = xterm;        /* responds to xterm escape codes */
  231.     pls->termin = 1;
  232.     pls->color = 2;            /* only fixed colours */
  233.     tek_init(pls);
  234. }
  235. #endif    /* PLD_conex */
  236.  
  237. /*----------------------------------------------------------------------*\
  238.  * tek_init()
  239.  *
  240.  * Generic tektronix device initialization.
  241. \*----------------------------------------------------------------------*/
  242.  
  243. static void
  244. tek_init(PLStream *pls)
  245. {
  246.     PLDev *dev;
  247.  
  248.     pls->icol0 = 1;
  249.     pls->width = 1;
  250.     pls->bytecnt = 0;
  251.     pls->page = 0;
  252.     pls->graphx = TEXT_MODE;
  253.     curcolor = 1;
  254.  
  255. /* Allocate and initialize device-specific data */
  256.  
  257.     dev = plAllocDev(pls);
  258.  
  259.     dev->xold = UNDEFINED;
  260.     dev->yold = UNDEFINED;
  261.     dev->xmin = 0;
  262.     dev->ymin = 0;
  263.     dev->xmax = TEKX * 16;
  264.     dev->ymax = TEKY * 16;
  265.     dev->pxlx = 4.771 * 16;
  266.     dev->pxly = 4.653 * 16;
  267.  
  268.     plP_setpxl(dev->pxlx, dev->pxly);
  269.     plP_setphy(dev->xmin, dev->xmax, dev->ymin, dev->ymax);
  270.  
  271. /* Terminal/file initialization */
  272.  
  273.     if (pls->termin) {
  274.     pls->OutFile = stdout;
  275. #ifdef POSIX_TTY
  276.     tty_setup();
  277. #endif
  278.     }
  279.     else {
  280.     plFamInit(pls);
  281.     plOpenFile(pls);
  282.     }
  283.  
  284.     switch (pls->dev_minor) {
  285. #ifdef PLD_tek4107
  286.     case tek4107:
  287.     pls->graphx = GRAPHICS_MODE;
  288.     fprintf(pls->OutFile, "\033%%!0");    /* set tek mode */
  289.     fprintf(pls->OutFile, "\033KN1");    /* clear the view */
  290.     fprintf(pls->OutFile, "\033LZ");    /* clear dialog buffer */
  291.     fprintf(pls->OutFile, "\033ML1");    /* set default color */
  292.     break;
  293. #endif    /* PLD_tek4107 */
  294.  
  295. /* A sneaky hack: VLT sometimes has leftover panel information, causing 
  296.  * garbage at the beginning of a sequence of color fills.  Since 
  297.  * there is no clear panel command, instead I set the fill color to the
  298.  * same as background and issue an end panel command.
  299.  */
  300. #ifdef PLD_vlt
  301.     case vlt:{
  302.     char fillcol[4];
  303.     tek_graph(pls);
  304.     encode_int(fillcol, 0);
  305.     fprintf(pls->OutFile, "\033MP%s\033LE", fillcol);
  306.     break;
  307.     }
  308. #endif    /* PLD_vlt */
  309.  
  310.     default:
  311.     tek_graph(pls);
  312.     }
  313.  
  314. /* Initialize palette */
  315.  
  316.    if ( pls->color & 0x01 ) {
  317.        printf("\033TM111");    /* Switch to RGB colors */
  318.        setcmap(pls);
  319.    }
  320.  
  321. /* Finish initialization */
  322.  
  323.     fprintf(pls->OutFile, VECTOR_MODE);    /* Enter vector mode */
  324.     if (pls->termin)
  325.     fprintf(pls->OutFile, CLEAR_VIEW);/* erase and home */
  326.  
  327.     fflush(pls->OutFile);
  328. }
  329.  
  330. /*----------------------------------------------------------------------*\
  331.  * plD_line_tek()
  332.  *
  333.  * Draw a line from (x1,y1) to (x2,y2).
  334. \*----------------------------------------------------------------------*/
  335.  
  336. void
  337. plD_line_tek(PLStream *pls, short x1a, short y1a, short x2a, short y2a)
  338. {
  339.    PLDev *dev = (PLDev *) pls->dev;
  340.    short x1 = x1a >> 4, 
  341.         y1 = y1a >> 4, 
  342.          x2 = x2a >> 4,
  343.          y2 = y2a >> 4;
  344.  
  345.    tek_graph(pls);
  346.  
  347. /* If continuation of previous line just send new point */
  348.  
  349.    if (x1 != dev->xold || y1 != dev->yold) {
  350.        fprintf(pls->OutFile, VECTOR_MODE);
  351.        pls->bytecnt++;
  352.        tek_vector(pls, x1, y1);
  353.    }
  354.    tek_vector(pls, x2, y2);
  355.  
  356.    dev->xold = x2;
  357.    dev->yold = y2;
  358. }
  359.  
  360. /*----------------------------------------------------------------------*\
  361.  * plD_polyline_tek()
  362.  *
  363.  * Draw a polyline in the current color.
  364. \*----------------------------------------------------------------------*/
  365.  
  366. void
  367. plD_polyline_tek(PLStream *pls, short *xa, short *ya, PLINT npts)
  368. {
  369.    PLINT i;
  370.    PLDev *dev = (PLDev *) pls->dev;
  371.    short x = xa[0] >> 4, y = ya[0] >> 4;
  372.  
  373.    tek_graph(pls);
  374.  
  375. /* If continuation of previous line just send new point */
  376.  
  377.    if ( x != dev->xold || y != dev->yold ) {
  378.        fprintf(pls->OutFile, VECTOR_MODE);
  379.        pls->bytecnt++;
  380.        tek_vector(pls, x, y);
  381.    }
  382.    for (i = 1; i < npts; i++) {
  383.        tek_vector(pls, xa[i] >> 4, ya[i] >> 4 );
  384.    }
  385.    
  386.    dev->xold = xa[npts -1] >> 4;
  387.    dev->yold = ya[npts -1] >> 4;
  388. }
  389.  
  390. /*----------------------------------------------------------------------*\
  391.  * plD_eop_tek()
  392.  *
  393.  * End of page.  User must hit a <CR> to continue (terminal output).
  394. \*----------------------------------------------------------------------*/
  395.  
  396. void
  397. plD_eop_tek(PLStream *pls)
  398. {
  399.     tek_graph(pls);
  400.  
  401.     if (pls->termin) {
  402.     if ( ! pls->nopause) 
  403.         WaitForPage(pls);
  404.     }
  405.     fprintf(pls->OutFile, CLEAR_VIEW);    /* erase and home */
  406. }
  407.  
  408. /*----------------------------------------------------------------------*\
  409.  * plD_bop_tek()
  410.  *
  411.  * Set up for the next page.  Advance to next family file if necessary
  412.  * (file output).  Devices that share graphics/alpha screens need a page
  413.  * clear.
  414. \*----------------------------------------------------------------------*/
  415.  
  416. void
  417. plD_bop_tek(PLStream *pls)
  418. {
  419.    PLDev *dev = (PLDev *) pls->dev;
  420.  
  421.    dev->xold = UNDEFINED;
  422.    dev->yold = UNDEFINED;
  423.  
  424.    if (pls->termin) {
  425.        switch (pls->dev_minor) {
  426.        case mskermit:
  427.        fprintf(pls->OutFile, CLEAR_VIEW);    /* erase and home */
  428.        break;
  429.        }
  430.    } else {
  431.        plGetFam(pls);
  432.    }
  433.    pls->page++;
  434.  
  435. /* Initialize palette */
  436.  
  437.    if ( pls->color & 0x01 )
  438.        setcmap(pls);
  439. }
  440.  
  441. /*----------------------------------------------------------------------*\
  442.  * plD_tidy_tek()
  443.  *
  444.  * Close graphics file or otherwise clean up.
  445. \*----------------------------------------------------------------------*/
  446.  
  447. void
  448. plD_tidy_tek(PLStream *pls)
  449. {
  450.     if ( ! pls->termin) {
  451.     fclose(pls->OutFile);
  452.     } else {
  453.     tek_text(pls);
  454.     fflush(pls->OutFile);
  455.     }
  456. }
  457.  
  458. /*----------------------------------------------------------------------*\
  459.  * plD_state_tek()
  460.  *
  461.  * Handle change in PLStream state (color, pen width, fill attribute,
  462.  * etc).
  463. \*----------------------------------------------------------------------*/
  464.  
  465. void 
  466. plD_state_tek(PLStream *pls, PLINT op)
  467. {
  468.     switch (op) {
  469.  
  470.     case PLSTATE_WIDTH:
  471.     break;
  472.  
  473.     case PLSTATE_COLOR0:
  474.     if (pls->color) {
  475.         int icol0 = pls->icol0;
  476.         tek_graph(pls);
  477.         if (icol0 != PL_RGB_COLOR) {
  478.         curcolor = icol0;
  479.         switch (pls->dev_minor) {
  480. #ifdef PLD_mskermit
  481.         case mskermit:
  482.             fprintf(pls->OutFile, "\033[%sm",
  483.                 kermit_color[icol0 % 14] );
  484.             break;
  485. #endif    /* PLD_mskermit */
  486.  
  487.         default:
  488.             fprintf(pls->OutFile, "\033ML%c", icol0 + '0');
  489.         }
  490.         }
  491.     }
  492.     break;
  493.  
  494.     case PLSTATE_COLOR1:
  495.     if (pls->color) {
  496.         int icol1, ncol1;
  497.         tek_graph(pls);
  498.         if ((ncol1 = MIN(16 - pls->ncol0, pls->ncol1)) < 1)
  499.         break;
  500.  
  501.         icol1 = pls->ncol0 + (pls->icol1 * (ncol1-1)) / (pls->ncol1-1);
  502.         curcolor = icol1;
  503.         fprintf(pls->OutFile, "\033ML%c", icol1 + '0');
  504.     }
  505.     break;
  506.  
  507.     case PLSTATE_CMAP0:
  508.     case PLSTATE_CMAP1:
  509.     if ( pls->color & 0x01 )
  510.         setcmap(pls);    
  511.  
  512.     break;
  513.     }
  514. }
  515.  
  516. /*----------------------------------------------------------------------*\
  517.  * plD_esc_tek()
  518.  *
  519.  * Escape function.
  520. \*----------------------------------------------------------------------*/
  521.  
  522. void 
  523. plD_esc_tek(PLStream *pls, PLINT op, void *ptr)
  524. {
  525.     switch (op) {
  526.  
  527.     case PLESC_TEXT:
  528.     tek_text(pls);
  529.     break;
  530.  
  531.     case PLESC_GRAPH:
  532.     tek_graph(pls);
  533.     break;
  534.  
  535.     case PLESC_FILL:
  536.     fill_polygon(pls);
  537.     break;
  538.     }
  539. }
  540.  
  541. /*----------------------------------------------------------------------*\
  542.  * fill_polygon()
  543.  *
  544.  * Fill polygon described in points pls->dev_x[] and pls->dev_y[].
  545. \*----------------------------------------------------------------------*/
  546.  
  547. static void
  548. fill_polygon(PLStream *pls)
  549. {
  550.     int i;
  551.     char fillcol[4], firstpoint[5];
  552.  
  553.     if (pls->dev_npts < 1)
  554.     return;
  555.  
  556.     tek_graph(pls);
  557.  
  558.     encode_int(fillcol, -curcolor);
  559.     encode_vector(firstpoint, pls->dev_x[0]>>4, pls->dev_y[0]>>4);
  560.  
  561. /* Select the fill pattern */
  562.  
  563.     fprintf(pls->OutFile, "\033MP%s", fillcol);
  564.  
  565. /* Begin panel boundary */
  566. /* Change %s0 to %s1 to see the boundary of each fill box -- cool! */
  567.  
  568.     fprintf(pls->OutFile, "\033LP%s0", firstpoint);
  569.  
  570. /* Specify boundary (use vector mode) */
  571.  
  572.     fprintf(pls->OutFile, VECTOR_MODE);
  573.     pls->bytecnt++;
  574.     for (i = 1; i < pls->dev_npts; i++) {
  575.     tek_vector(pls, pls->dev_x[i]>>4, pls->dev_y[i]>>4);
  576.     }
  577.  
  578. /* End panel */
  579.  
  580.     fprintf(pls->OutFile, "\033LE");
  581. }
  582.  
  583. /*----------------------------------------------------------------------*\
  584.  * tek_text()
  585.  *
  586.  * Switch to text screen (or alpha mode, for vanilla tek's).  Restore
  587.  * terminal to its original state, to better handle user input if
  588.  * necessary.
  589.  *
  590.  * Note: xterm behaves strangely in the following circumstance: switch to
  591.  * the text screen, print a string, and switch to the graphics screen, all
  592.  * done in quick succession.  The first character of the printed string
  593.  * usually comes out blank -- but only apparently so, because if you force
  594.  * a refresh of the screen in this area it will reappear.  This is a
  595.  * reproducible bug on the HP 720 under X11R5.  If you insert a sleep(1)
  596.  * after the switch to text screen or before the switch to graphics
  597.  * screen, the string is printed correctly.  I've been unable to find a
  598.  * workaround for this problem (and I've tried, you can believe eet man).
  599. \*----------------------------------------------------------------------*/
  600.  
  601. static void 
  602. tek_text(PLStream *pls)
  603. {
  604.     if (pls->termin && (pls->graphx == GRAPHICS_MODE)) {
  605. #ifdef POSIX_TTY
  606.     tty_reset();
  607. #endif
  608.     pls->graphx = TEXT_MODE;
  609.     switch (pls->dev_minor) {
  610.     case xterm:
  611.         printf("\033\003");        /* vt100 mode (xterm) = ESC ETX */
  612.         break;
  613.  
  614.     case mskermit:
  615.     case vlt:
  616.         printf("\033[?38l");    /* vt100 screen */
  617.         break;
  618.  
  619.     case versaterm:
  620.         printf("\033%%!2");        /* vt100 screen */
  621.         break;
  622.  
  623.     case tek4107:
  624.         printf("\033LV1");        /* set dialog visible */
  625.         printf("\033%%!1");        /* set ansi mode */
  626.         break;
  627.  
  628.     default:
  629.         printf(ALPHA_MODE);        /* enter alpha mode */
  630.     }
  631.     }
  632. }
  633.  
  634. /*----------------------------------------------------------------------*\
  635.  * tek_graph()
  636.  *
  637.  * Switch to graphics screen (or vector mode, for vanilla tek's).  Also
  638.  * switch terminal to cbreak mode, to allow single keystrokes to govern
  639.  * actions at end of page.
  640. \*----------------------------------------------------------------------*/
  641.  
  642. static void 
  643. tek_graph(PLStream *pls)
  644. {
  645.     if (pls->termin && (pls->graphx == TEXT_MODE)) {
  646. #ifdef POSIX_TTY
  647.     tty_cbreak();
  648. #endif
  649.     pls->graphx = GRAPHICS_MODE;
  650.     switch (pls->dev_minor) {
  651.     case xterm:
  652.     case mskermit:
  653.     case vlt:
  654.         printf("\033[?38h");    /* switch to tek screen */
  655.         break;
  656.  
  657.     case versaterm:
  658.         printf("\033%%!0");        /* switch to tek4107 screen */
  659.         break;
  660.  
  661.     case tek4107:
  662.         printf("\033%%!0");        /* set tek mode */
  663.            printf(CLEAR_VIEW);        /* clear screen */
  664.         printf("\033LV0");        /* set dialog invisible */
  665.         break;
  666.  
  667.     default:
  668.         printf(VECTOR_MODE);    /* enter vector mode */
  669.     }
  670.     }
  671. }
  672.  
  673. /*----------------------------------------------------------------------*\
  674.  * encode_int()
  675.  *
  676.  * Encodes a single int into standard tek integer format, storing into a
  677.  * NULL-terminated character string (must be length 4 or greater).  This
  678.  * scheme does not work for negative integers less than 15.
  679. \*----------------------------------------------------------------------*/
  680.  
  681. static void
  682. encode_int(char *c, int i)
  683. {
  684.     int negative = 0;
  685.  
  686.     if (i > 0) {
  687.     if (i & 0x7C00)                /* are any of bits 10-14 set?*/
  688.         *c++ = ((i >> 10) & 0x1F) | 0x40;
  689.     if (i & 0x03F0)                /* are any of bits 4-9 set? */
  690.         *c++ = ((i >> 4) & 0x3F) | 0x40;
  691.     } else {
  692.     i = -i;
  693.     negative = 1;
  694.     }
  695.  
  696.     if (i & 0x000F)                /* are any of bits 0-3 set? */
  697.     *c = (i & 0x0F) | 0x20;
  698.     else                    /* if not, put in a space */
  699.     *c = 0x20;
  700.     
  701.     if ( ! negative)                /* if positive, set sign bit */
  702.     *c |= 0x10;
  703.  
  704.     c++; *c = '\0';                /* NULL-terminate */
  705.     return;
  706. }
  707.  
  708. /*----------------------------------------------------------------------*\
  709.  * encode_vector()
  710.  *
  711.  * Encodes an xy vector (2 ints) into standard tek vector format, storing
  712.  * into a NULL-terminated character string of length 5.  Note that the y
  713.  * coordinate always comes first.
  714. \*----------------------------------------------------------------------*/
  715.  
  716. static void
  717. encode_vector(char *c, int x, int y)
  718. {
  719.     c[0] = (y >> 5)   + 0x20;        /* hy */
  720.     c[1] = (y & 0x1f) + 0x60;        /* ly */
  721.     c[2] = (x >> 5)   + 0x20;        /* hx */
  722.     c[3] = (x & 0x1f) + 0x40;        /* lx */
  723.     c[4] = '\0';            /* NULL */
  724. }
  725.  
  726. /*----------------------------------------------------------------------*\
  727.  * tek_vector()
  728.  *
  729.  * Issues a vector draw command, assuming we are in vector plot mode.  XY
  730.  * coordinates are encoded according to the standard xy encoding scheme.
  731. \*----------------------------------------------------------------------*/
  732.  
  733. static void
  734. tek_vector(PLStream *pls, int x, int y)
  735. {
  736.    char c[5];
  737.    c[0] = (y >> 5)   + 0x20;        /* hy */
  738.    c[1] = (y & 0x1f) + 0x60;        /* ly */
  739.    c[2] = (x >> 5)   + 0x20;        /* hx */
  740.    c[3] = (x & 0x1f) + 0x40;        /* lx */
  741.    c[4] = '\0';                /* NULL */
  742.  
  743.    fprintf( pls->OutFile, "%s", c );
  744.    pls->bytecnt += 4;
  745. }
  746.  
  747. /*----------------------------------------------------------------------*\
  748.  * scolor()
  749.  *
  750.  * Sets a color by tek-encoded RGB values.  Need to convert PLPLOT RGB
  751.  * color range (0 to 255) to Tek RGB color range (0 to 100).
  752. \*----------------------------------------------------------------------*/
  753.  
  754. static void
  755. scolor(int icol, int r, int g, int b)
  756. {
  757.     char tek_col[4], tek_r[4], tek_g[4], tek_b[4];
  758.  
  759.     encode_int(tek_col, icol);
  760.     encode_int(tek_r, (100*r)/255);
  761.     encode_int(tek_g, (100*g)/255);
  762.     encode_int(tek_b, (100*b)/255);
  763.  
  764.     printf("\033TG14%s%s%s%s", tek_col, tek_r, tek_g, tek_b);
  765. }
  766.  
  767. /*----------------------------------------------------------------------*\
  768.  * setcmap()
  769.  *
  770.  * Sets up color palette.
  771. \*----------------------------------------------------------------------*/
  772.  
  773. static void
  774. setcmap(PLStream *pls)
  775. {
  776.     int i, ncol1 = MIN(16 - pls->ncol0, pls->ncol1);
  777.     PLColor cmap1col;
  778.  
  779.     tek_graph(pls);
  780.  
  781. /* Initialize cmap 0 colors */
  782.  
  783.     for (i = 0; i < pls->ncol0; i++) 
  784.     scolor(i, pls->cmap0[i].r, pls->cmap0[i].g, pls->cmap0[i].b);
  785.  
  786. /* Initialize any remaining slots for cmap1 */
  787.  
  788.     for (i = 0; i < ncol1; i++) {
  789.     plcol_interp(pls, &cmap1col, i, ncol1);
  790.     scolor(i + pls->ncol0, cmap1col.r, cmap1col.g, cmap1col.b);
  791.     }
  792. }
  793.  
  794. /*----------------------------------------------------------------------*\
  795.  * WaitForPage()
  796.  *
  797.  * This routine waits for the user to advance the plot, while handling
  798.  * all other events.
  799. \*----------------------------------------------------------------------*/
  800.  
  801. static void
  802. WaitForPage(PLStream *pls)
  803. {
  804.     int input_char;
  805.  
  806.     putchar(BEL_CHAR);
  807.     fflush(stdout);
  808.  
  809.     while ( ! exit_eventloop) {
  810.     input_char = getchar();
  811.     EventHandler(pls, input_char);
  812.     }
  813.     exit_eventloop = FALSE;
  814. }
  815.  
  816. /*----------------------------------------------------------------------*\
  817.  * EventHandler()
  818.  *
  819.  * Event handler routine for xterm.  Just reacts to keyboard input.
  820. \*----------------------------------------------------------------------*/
  821.  
  822. static void
  823. EventHandler(PLStream *pls, int input_char)
  824. {
  825.     PLKey key;
  826.  
  827.     key.code = 0;
  828.     key.string[0] = '\0';
  829.  
  830. /* Translate keystroke into a PLKey */
  831.  
  832.     if ( ! isprint(input_char)) {
  833.     switch (input_char) {
  834.     case 0x0A:
  835.         key.code = PLK_Linefeed;
  836.         break;
  837.  
  838.     case 0x0D:
  839.         key.code = PLK_Return;
  840.         break;
  841.  
  842.     case 0x08:
  843.         key.code = PLK_BackSpace;
  844.         break;
  845.  
  846.     case 0x7F:
  847.         key.code = PLK_Delete;
  848.         break;
  849.     }
  850.     } else {
  851.     key.string[0] = input_char;
  852.     key.string[1] = '\0';
  853.     }
  854.  
  855. #ifdef DEBUG
  856.     pltext();
  857.     fprintf(stderr, "Input char %x, Keycode %x, string: %s\n",
  858.         input_char, key.code, key.string);
  859.     plgra();
  860. #endif
  861.  
  862. /* Call user event handler.
  863.  * Since this is called first, the user can disable all plplot internal
  864.  * event handling by setting key.code to 0 and key.string to '\0'.
  865.  */
  866.  
  867.     if (pls->KeyEH != NULL)
  868.     (*pls->KeyEH) (&key, pls->KeyEH_data, &exit_eventloop);
  869.  
  870. /* Handle internal events */
  871.  
  872. /* Advance to next page (i.e. terminate event loop) on a <eol> */
  873.  
  874.     if (key.code == PLK_Linefeed)
  875.     exit_eventloop = TRUE;
  876.  
  877. /* Terminate on a 'Q' (not 'q', since it's too easy to hit by mistake) */
  878.  
  879.     if (key.string[0] == 'Q') {
  880.     pls->nopause = TRUE;
  881.     plexit("");
  882.     }
  883.  
  884. /* Some test code, don't rely on it. */
  885.  
  886.     if (key.string[0] == 't') {
  887.     fprintf(stderr, "Entering GIN mode..\n");
  888.  
  889.     printf(GIN_MODE);            /* Enter GIN mode */
  890.     fflush(stdout);
  891.     }
  892. }
  893.  
  894. /*----------------------------------------------------------------------*\
  895.  * tty cbreak-mode handlers
  896.  *
  897.  * Taken from "Advanced Programming in the UNIX(R) Environment", 
  898.  * by W. Richard Stevens.
  899. \*----------------------------------------------------------------------*/
  900.  
  901. #ifdef POSIX_TTY
  902.  
  903. static void
  904. tty_setup(void)                /* setup for terminal operations */
  905. {
  906.     if (tcgetattr(STDIN_FILENO, &termios_reset) < 0) {
  907.     fprintf(stderr, "Unable to set up cbreak mode.\n");
  908.     return;
  909.     }
  910.  
  911.     termios_cbreak = termios_reset;        /* structure copy */
  912.  
  913.     termios_cbreak.c_lflag &= ~(ICANON);    /* canonical mode off */
  914.     termios_cbreak.c_cc[VMIN] = 1;        /* 1 byte at a time */
  915.     termios_cbreak.c_cc[VTIME] = 0;        /* no timer */
  916.  
  917. #ifdef STDC_HEADERS
  918.     if (atexit(tty_atexit))
  919.     fprintf(stderr, "Unable to set up atexit handler.\n");
  920. #endif
  921.     return;
  922. }
  923.  
  924. static int
  925. tty_cbreak(void)            /* put terminal into a cbreak mode */
  926. {
  927.     if (ttystate != CBREAK) {
  928.     if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios_cbreak) < 0)
  929.         return -1;
  930.  
  931.     ttystate = CBREAK;
  932.     }
  933.     return 0;
  934. }
  935.  
  936. static int
  937. tty_reset(void)                /* restore terminal's mode */
  938. {
  939.     if (ttystate != RESET) {
  940.     if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios_reset) < 0)
  941.         return -1;
  942.  
  943.     ttystate = RESET;
  944.     }
  945.     return 0;
  946. }
  947.  
  948. static void
  949. tty_atexit(void)            /* exit handler */
  950. {
  951.     tty_reset();
  952. }
  953.  
  954. #endif            /* POSIX_TTY */
  955.  
  956. #else
  957. int pldummy_tek() {return 0;}
  958.  
  959. #endif    /*  defined(PLD_xterm) || ... */
  960.