PLplot  5.10.0
tek.c
Go to the documentation of this file.
00001 //      PLplot tektronix device & emulators driver.
00002 //
00003 #include "plDevs.h"
00004 
00005 #if defined ( PLD_xterm ) ||               /* xterm */              \
00006     defined ( PLD_tek4010 ) ||             /* TEK 4010 */           \
00007     defined ( PLD_tek4010f ) ||            /* ditto, file */        \
00008     defined ( PLD_tek4107 ) ||             /* TEK 4107 */           \
00009     defined ( PLD_tek4107f ) ||            /* ditto, file */        \
00010     defined ( PLD_mskermit ) ||            /* MS-kermit emulator */ \
00011     defined ( PLD_versaterm ) ||           /* Versaterm emulator */ \
00012     defined ( PLD_vlt ) ||                 /* VLT emulator */       \
00013     defined ( PLD_conex )                  // conex emulator 4010/4014/4105
00014 
00015 #define NEED_PLDEBUG
00016 #include "plplotP.h"
00017 #include "drivers.h"
00018 #include "plevent.h"
00019 
00020 #include <ctype.h>
00021 
00022 // Device info
00023 
00024 PLDLLIMPEXP_DRIVER const char* plD_DEVICE_INFO_tek =
00025 #if defined ( PLD_conex )
00026     "conex:Conex vt320/tek emulator:1:tek:24:conex\n"
00027 #endif
00028 #if defined ( PLD_mskermit )
00029     "mskermit:MS-Kermit emulator:1:tek:21:mskermit\n"
00030 #endif
00031 #if defined ( PLD_tek4107t )
00032     "tek4107t:Tektronix Terminal (4105/4107):1:tek:20:tek4107t\n"
00033 #endif
00034 #if defined ( PLD_tek4107f )
00035     "tek4107f:Tektronix File (4105/4107):0:tek:28:tek4107f\n"
00036 #endif
00037 #if defined ( PLD_tekt )
00038     "tekt:Tektronix Terminal (4010):1:tek:19:tekt\n"
00039 #endif
00040 #if defined ( PLD_tekf )
00041     "tekf:Tektronix File (4010):0:tek:27:tekf\n"
00042 #endif
00043 #if defined ( PLD_versaterm )
00044     "versaterm:Versaterm vt100/tek emulator:1:tek:22:versaterm\n"
00045 #endif
00046 #if defined ( PLD_vlt )
00047     "vlt:VLT vt100/tek emulator:1:tek:23:vlt\n"
00048 #endif
00049 #if defined ( PLD_xterm )
00050     "xterm:Xterm Window:1:tek:18:xterm\n"
00051 #endif
00052 ;
00053 
00054 // Prototype the driver entry points that will be used to initialize the
00055 // dispatch table entries.
00056 
00057 void plD_init_xterm( PLStream * );
00058 void plD_init_tekt( PLStream * );
00059 void plD_init_tekf( PLStream * );
00060 void plD_init_tek4107t( PLStream * );
00061 void plD_init_tek4107f( PLStream * );
00062 void plD_init_mskermit( PLStream * );
00063 void plD_init_versaterm( PLStream * );
00064 void plD_init_vlt( PLStream * );
00065 void plD_init_conex( PLStream * );
00066 
00067 // External generic entry points
00068 
00069 void plD_line_tek( PLStream *, short, short, short, short );
00070 void plD_polyline_tek( PLStream *, short *, short *, PLINT );
00071 void plD_eop_tek( PLStream * );
00072 void plD_bop_tek( PLStream * );
00073 void plD_tidy_tek( PLStream * );
00074 void plD_state_tek( PLStream *, PLINT );
00075 void plD_esc_tek( PLStream *, PLINT, void * );
00076 
00077 // Static function prototypes
00078 
00079 static void  WaitForPage( PLStream *pls );
00080 static void  tek_init( PLStream *pls );
00081 static void  tek_text( PLStream *pls );
00082 static void  tek_graph( PLStream *pls );
00083 static void  fill_polygon( PLStream *pls );
00084 static void  GetCursor( PLStream *pls, PLGraphicsIn *ptr );
00085 static void  encode_int( char *c, int i );
00086 static void  encode_vector( char *c, int x, int y );
00087 static void  decode_gin( char *c, PLGraphicsIn *gin );
00088 static void  tek_vector( PLStream *pls, int x, int y );
00089 static void  scolor( PLStream *pls, int icol, int r, int g, int b );
00090 static void  setcmap( PLStream *pls );
00091 
00092 static void  LookupEvent( PLStream *pls );
00093 static void  InputEH( PLStream *pls );
00094 static void  LocateEH( PLStream *pls );
00095 
00096 // Stuff for handling tty cbreak mode
00097 
00098 #ifdef HAVE_TERMIOS_H
00099 #include <termios.h>
00100 #include <unistd.h>
00101 static struct termios         termios_cbreak, termios_reset;
00102 static enum { RESET, CBREAK } ttystate = RESET;
00103 static void tty_setup( void );
00104 static int  tty_cbreak( void );
00105 static int  tty_reset( void );
00106 static void tty_atexit( void );
00107 #else
00108 static void tty_setup( void )
00109 {
00110 }
00111 static int  tty_cbreak( void )
00112 {
00113     return 0;
00114 }
00115 static int  tty_reset( void )
00116 {
00117     return 0;
00118 }
00119 static void tty_atexit( void )
00120 {
00121 }
00122 #endif
00123 
00124 // Pixel settings
00125 
00126 #define TEKX    1023
00127 #define TEKY    779
00128 
00129 // Graphics control characters.
00130 
00131 #define RING_BELL       "\007"          // ^G = 7
00132 #define CLEAR_VIEW      "\033\f"        // clear the view = ESC FF
00133 
00134 #define ALPHA_MODE      "\037"          // Enter Alpha  mode:  US
00135 #define VECTOR_MODE     "\035"          // Enter Vector mode:  GS
00136 #define GIN_MODE        "\033\032"      // Enter GIN    mode:  ESC SUB
00137 #define BYPASS_MODE     "\033\030"      // Enter Bypass mode:  ESC CAN
00138 #define XTERM_VTMODE    "\033\003"      // End xterm-Tek mode: ESC ETX
00139 #define CANCEL          "\033KC"        // Cancel
00140 
00141 // Static vars
00142 
00143 enum { tek4010, tek4105, tek4107, xterm, mskermit, vlt, versaterm };
00144 
00145 // One of these holds the tek driver state information
00146 
00147 typedef struct
00148 {
00149     PLINT        xold, yold;     // Coordinates of last point plotted
00150     int          exit_eventloop; // Break out of event loop
00151     int          locate_mode;    // Set while in locate (pick) mode
00152     int          curcolor;       // Current color index
00153     PLGraphicsIn gin;            // Graphics input structure
00154 } TekDev;
00155 
00156 // color for MS-DOS Kermit v2.31 (and up) tektronix emulator
00157 //      0 = normal, 1 = bright
00158 //      foreground color (30-37) = 30 + colors
00159 //              where colors are   1=red, 2=green, 4=blue
00160 //
00161 #ifdef PLD_mskermit
00162 static char *kermit_color[15] = {
00163     "0;30", "0;37",
00164     "0;32", "0;36","0;31",  "0;35",
00165     "1;34", "1;33","1;31",  "1;37",
00166     "1;35", "1;32","1;36",  "0;34",
00167     "0;33"
00168 };
00169 #endif
00170 
00171 static void tek_dispatch_init_helper( PLDispatchTable *pdt,
00172                                       char *menustr, char *devnam,
00173                                       int type, int seq, plD_init_fp init )
00174 {
00175 #ifndef ENABLE_DYNDRIVERS
00176     pdt->pl_MenuStr = menustr;
00177     pdt->pl_DevName = devnam;
00178 #endif
00179     pdt->pl_type     = type;
00180     pdt->pl_seq      = seq;
00181     pdt->pl_init     = init;
00182     pdt->pl_line     = (plD_line_fp) plD_line_tek;
00183     pdt->pl_polyline = (plD_polyline_fp) plD_polyline_tek;
00184     pdt->pl_eop      = (plD_eop_fp) plD_eop_tek;
00185     pdt->pl_bop      = (plD_bop_fp) plD_bop_tek;
00186     pdt->pl_tidy     = (plD_tidy_fp) plD_tidy_tek;
00187     pdt->pl_state    = (plD_state_fp) plD_state_tek;
00188     pdt->pl_esc      = (plD_esc_fp) plD_esc_tek;
00189 }
00190 
00191 void plD_dispatch_init_xterm( PLDispatchTable *pdt )
00192 {
00193     tek_dispatch_init_helper( pdt,
00194         "Xterm Window", "xterm",
00195         plDevType_Interactive, 18,
00196         (plD_init_fp) plD_init_xterm );
00197 }
00198 
00199 void plD_dispatch_init_tekt( PLDispatchTable *pdt )
00200 {
00201     tek_dispatch_init_helper( pdt,
00202         "Tektronix Terminal (4010)", "tekt",
00203         plDevType_Interactive, 19,
00204         (plD_init_fp) plD_init_tekt );
00205 }
00206 
00207 void plD_dispatch_init_tek4107t( PLDispatchTable *pdt )
00208 {
00209     tek_dispatch_init_helper( pdt,
00210         "Tektronix Terminal (4105/4107)", "tek4107t",
00211         plDevType_Interactive, 20,
00212         (plD_init_fp) plD_init_tek4107t );
00213 }
00214 
00215 void plD_dispatch_init_mskermit( PLDispatchTable *pdt )
00216 {
00217     tek_dispatch_init_helper( pdt,
00218         "MS-Kermit emulator", "mskermit",
00219         plDevType_Interactive, 21,
00220         (plD_init_fp) plD_init_mskermit );
00221 }
00222 
00223 void plD_dispatch_init_versaterm( PLDispatchTable *pdt )
00224 {
00225     tek_dispatch_init_helper( pdt,
00226         "Versaterm vt100/tek emulator", "versaterm",
00227         plDevType_Interactive, 22,
00228         (plD_init_fp) plD_init_versaterm );
00229 }
00230 
00231 void plD_dispatch_init_vlt( PLDispatchTable *pdt )
00232 {
00233     tek_dispatch_init_helper( pdt,
00234         "VLT vt100/tek emulator", "vlt",
00235         plDevType_Interactive, 23,
00236         (plD_init_fp) plD_init_vlt );
00237 }
00238 
00239 void plD_dispatch_init_conex( PLDispatchTable *pdt )
00240 {
00241     tek_dispatch_init_helper( pdt,
00242         "Conex vt320/tek emulator", "conex",
00243         plDevType_Interactive, 24,
00244         (plD_init_fp) plD_init_conex );
00245 }
00246 
00247 void plD_dispatch_init_tekf( PLDispatchTable *pdt )
00248 {
00249     tek_dispatch_init_helper( pdt,
00250         "Tektronix File (4010)", "tekf",
00251         plDevType_FileOriented, 27,
00252         (plD_init_fp) plD_init_tekf );
00253 }
00254 
00255 void plD_dispatch_init_tek4107f( PLDispatchTable *pdt )
00256 {
00257     tek_dispatch_init_helper( pdt,
00258         "Tektronix File (4105/4107)", "tek4107f",
00259         plDevType_FileOriented, 28,
00260         (plD_init_fp) plD_init_tek4107f );
00261 }
00262 
00263 //--------------------------------------------------------------------------
00264 // plD_init_xterm()     xterm
00265 // plD_init_tekt()      Tek 4010 terminal
00266 // plD_init_tekf()      Tek 4010 file
00267 // plD_init_tek4107t()  Tek 4105/4107 terminal
00268 // plD_init_tek4107f()  Tek 4105/4107 file
00269 // plD_init_mskermit()  MS-Kermit emulator (DOS)
00270 // plD_init_vlt()       VLT emulator (Amiga)
00271 // plD_init_versaterm() VersaTerm emulator (Mac)
00272 // plD_init_conex()     Conex vt320/Tek 4105 emulator (DOS)
00273 //
00274 // These just set attributes for the particular tektronix device, then call
00275 // tek_init().  The following attributes can be set:
00276 //
00277 // pls->termin          if a terminal device
00278 // pls->color           if color (1), if only fixed colors (2)
00279 // pls->dev_fill0       if can handle solid area fill
00280 // pls->dev_fill1       if can handle pattern area fill
00281 //--------------------------------------------------------------------------
00282 
00283 void
00284 plD_init_xterm( PLStream *pls )
00285 {
00286     pls->dev_minor = xterm;
00287     pls->termin    = 1;
00288     tek_init( pls );
00289 }
00290 
00291 void
00292 plD_init_tekt( PLStream *pls )
00293 {
00294     pls->termin = 1;
00295     plD_init_tekf( pls );
00296 }
00297 
00298 void
00299 plD_init_tekf( PLStream *pls )
00300 {
00301     pls->dev_minor = tek4010;
00302     tek_init( pls );
00303 }
00304 
00305 void
00306 plD_init_tek4107t( PLStream *pls )
00307 {
00308     pls->termin = 1;
00309     plD_init_tek4107f( pls );
00310 }
00311 
00312 void
00313 plD_init_tek4107f( PLStream *pls )
00314 {
00315     pls->dev_minor = tek4107;
00316     pls->color     = 1;
00317     pls->dev_fill0 = 1;
00318     tek_init( pls );
00319 }
00320 
00321 void
00322 plD_init_mskermit( PLStream *pls )
00323 {
00324     pls->dev_minor = mskermit;
00325     pls->termin    = 1;
00326     pls->color     = 1;
00327     pls->dev_fill0 = 1;
00328     tek_init( pls );
00329 }
00330 
00331 void
00332 plD_init_vlt( PLStream *pls )
00333 {
00334     pls->dev_minor = vlt;
00335     pls->termin    = 1;
00336     pls->color     = 1;
00337     pls->dev_fill0 = 1;
00338     tek_init( pls );
00339 }
00340 
00341 void
00342 plD_init_versaterm( PLStream *pls )
00343 {
00344     pls->dev_minor = versaterm;
00345     pls->termin    = 1;
00346     pls->color     = 1;
00347     pls->dev_fill0 = 1;
00348     tek_init( pls );
00349 }
00350 
00351 void
00352 plD_init_conex( PLStream *pls )
00353 {
00354     pls->dev_minor = xterm;             // responds to xterm escape codes
00355     pls->termin    = 1;
00356     pls->color     = 2;                 // only fixed colours
00357     tek_init( pls );
00358 }
00359 
00360 //--------------------------------------------------------------------------
00361 // tek_init()
00362 //
00363 // Generic tektronix device initialization.
00364 //--------------------------------------------------------------------------
00365 
00366 static void
00367 tek_init( PLStream *pls )
00368 {
00369     TekDev *dev;
00370     int    xmin = 0;
00371     int    xmax = TEKX;
00372     int    ymin = 0;
00373     int    ymax = TEKY;
00374 
00375     PLFLT  pxlx = 4.771;
00376     PLFLT  pxly = 4.653;
00377 
00378     pls->graphx = TEXT_MODE;
00379 
00380 // Allocate and initialize device-specific data
00381 
00382     pls->dev = calloc( 1, (size_t) sizeof ( TekDev ) );
00383     if ( pls->dev == NULL )
00384         plexit( "tek_init: Out of memory." );
00385 
00386     dev = (TekDev *) pls->dev;
00387 
00388     dev->curcolor = 1;
00389     dev->xold     = PL_UNDEFINED;
00390     dev->yold     = PL_UNDEFINED;
00391 
00392     plP_setpxl( pxlx, pxly );
00393     plP_setphy( xmin, xmax, ymin, ymax );
00394 
00395 // Terminal/file initialization
00396 
00397     if ( pls->termin )
00398     {
00399         pls->OutFile = stdout;
00400         tty_setup();
00401     }
00402     else
00403     {
00404         plFamInit( pls );
00405         plOpenFile( pls );
00406     }
00407 
00408     switch ( pls->dev_minor )
00409     {
00410 #ifdef PLD_tek4107
00411     case tek4107:
00412         pls->graphx = GRAPHICS_MODE;
00413         fprintf( pls->OutFile, "\033%%!0" );      // set tek mode
00414         fprintf( pls->OutFile, "\033KN1" );       // clear the view
00415         fprintf( pls->OutFile, "\033LZ" );        // clear dialog buffer
00416         fprintf( pls->OutFile, "\033ML1" );       // set default color
00417         break;
00418 #endif  // PLD_tek4107
00419 
00420 // A sneaky hack: VLT sometimes has leftover panel information, causing
00421 // garbage at the beginning of a sequence of color fills.  Since
00422 // there is no clear panel command, instead I set the fill color to the
00423 // same as background and issue an end panel command.
00424 //
00425 #ifdef PLD_vlt
00426     case vlt: {
00427         char fillcol[4];
00428         tek_graph( pls );
00429         encode_int( fillcol, 0 );
00430         fprintf( pls->OutFile, "\033MP%s\033LE", fillcol );
00431         break;
00432     }
00433 #endif  // PLD_vlt
00434 
00435     default:
00436         tek_graph( pls );
00437     }
00438 
00439 // Initialize palette
00440 
00441     if ( pls->color & 0x01 )
00442     {
00443         printf( "\033TM111" );  // Switch to RGB colors
00444         setcmap( pls );
00445     }
00446 
00447 // Finish initialization
00448 
00449     fprintf( pls->OutFile, VECTOR_MODE );    // Enter vector mode
00450     if ( pls->termin )
00451         fprintf( pls->OutFile, CLEAR_VIEW ); // erase and home
00452 
00453     fflush( pls->OutFile );
00454 }
00455 
00456 //--------------------------------------------------------------------------
00457 // plD_line_tek()
00458 //
00459 // Draw a line from (x1,y1) to (x2,y2).
00460 //--------------------------------------------------------------------------
00461 
00462 void
00463 plD_line_tek( PLStream *pls, short x1, short y1, short x2, short y2 )
00464 {
00465     TekDev *dev = (TekDev *) pls->dev;
00466 
00467     tek_graph( pls );
00468 
00469 // If not continuation of previous line, begin a new one
00470 
00471     if ( x1 != dev->xold || y1 != dev->yold )
00472     {
00473         pls->bytecnt += fprintf( pls->OutFile, VECTOR_MODE );
00474         tek_vector( pls, x1, y1 );
00475     }
00476 
00477 // Now send following point to complete line draw
00478 
00479     tek_vector( pls, x2, y2 );
00480 
00481     dev->xold = x2;
00482     dev->yold = y2;
00483 }
00484 
00485 //--------------------------------------------------------------------------
00486 // plD_polyline_tek()
00487 //
00488 // Draw a polyline in the current color.
00489 //--------------------------------------------------------------------------
00490 
00491 void
00492 plD_polyline_tek( PLStream *pls, short *xa, short *ya, PLINT npts )
00493 {
00494     PLINT  i;
00495     TekDev *dev = (TekDev *) pls->dev;
00496     short  x    = xa[0], y = ya[0];
00497 
00498     tek_graph( pls );
00499 
00500 // If not continuation of previous line, begin a new one
00501 
00502     if ( x != dev->xold || y != dev->yold )
00503     {
00504         pls->bytecnt += fprintf( pls->OutFile, VECTOR_MODE );
00505         tek_vector( pls, x, y );
00506     }
00507 
00508 // Now send following points to complete polyline draw
00509 
00510     for ( i = 1; i < npts; i++ )
00511         tek_vector( pls, xa[i], ya[i] );
00512 
00513     dev->xold = xa[npts - 1];
00514     dev->yold = ya[npts - 1];
00515 }
00516 
00517 //--------------------------------------------------------------------------
00518 // plD_eop_tek()
00519 //
00520 // End of page.  User must hit a <CR> to continue (terminal output).
00521 //--------------------------------------------------------------------------
00522 
00523 void
00524 plD_eop_tek( PLStream *pls )
00525 {
00526     tek_graph( pls );
00527 
00528     if ( pls->termin )
00529     {
00530         if ( !pls->nopause )
00531             WaitForPage( pls );
00532     }
00533     fprintf( pls->OutFile, CLEAR_VIEW );          // erase and home
00534 }
00535 
00536 //--------------------------------------------------------------------------
00537 // plD_bop_tek()
00538 //
00539 // Set up for the next page.  Advance to next family file if necessary
00540 // (file output).  Devices that share graphics/alpha screens need a page
00541 // clear.
00542 //--------------------------------------------------------------------------
00543 
00544 void
00545 plD_bop_tek( PLStream *pls )
00546 {
00547     TekDev *dev = (TekDev *) pls->dev;
00548 
00549     dev->xold = PL_UNDEFINED;
00550     dev->yold = PL_UNDEFINED;
00551 
00552     if ( pls->termin )
00553     {
00554         switch ( pls->dev_minor )
00555         {
00556         case mskermit:
00557             fprintf( pls->OutFile, CLEAR_VIEW ); // erase and home
00558             break;
00559         }
00560     }
00561     else
00562     {
00563         plGetFam( pls );
00564     }
00565     pls->page++;
00566 
00567 // Initialize palette
00568 
00569     if ( pls->color & 0x01 )
00570         setcmap( pls );
00571 }
00572 
00573 //--------------------------------------------------------------------------
00574 // plD_tidy_tek()
00575 //
00576 // Close graphics file or otherwise clean up.
00577 //--------------------------------------------------------------------------
00578 
00579 void
00580 plD_tidy_tek( PLStream *pls )
00581 {
00582     if ( !pls->termin )
00583     {
00584         plCloseFile( pls );
00585     }
00586     else
00587     {
00588         tek_text( pls );
00589         fflush( pls->OutFile );
00590     }
00591 }
00592 
00593 //--------------------------------------------------------------------------
00594 // tek_color()
00595 //
00596 // Change to specified color index.
00597 //--------------------------------------------------------------------------
00598 
00599 static void
00600 tek_color( PLStream *pls, int icol )
00601 {
00602     switch ( pls->dev_minor )
00603     {
00604 #ifdef PLD_mskermit                     // Is this really necessary?
00605     case mskermit:
00606         printf( "\033[%sm", kermit_color[icol % 14] );
00607         break;
00608 #endif
00609     default:
00610         pls->bytecnt += fprintf( pls->OutFile, "\033ML%c", icol + '0' );
00611     }
00612 }
00613 
00614 //--------------------------------------------------------------------------
00615 // plD_state_tek()
00616 //
00617 // Handle change in PLStream state (color, pen width, fill attribute,
00618 // etc).
00619 //--------------------------------------------------------------------------
00620 
00621 void
00622 plD_state_tek( PLStream *pls, PLINT op )
00623 {
00624     TekDev *dev = (TekDev *) pls->dev;
00625 
00626     switch ( op )
00627     {
00628     case PLSTATE_WIDTH:
00629         break;
00630 
00631     case PLSTATE_COLOR0:
00632         if ( pls->color )
00633         {
00634             int icol0 = pls->icol0;
00635             tek_graph( pls );
00636             if ( icol0 != PL_RGB_COLOR )
00637             {
00638                 dev->curcolor = icol0;
00639                 tek_color( pls, icol0 );
00640             }
00641         }
00642         break;
00643 
00644     case PLSTATE_COLOR1:
00645         if ( pls->color )
00646         {
00647             int icol1, ncol1;
00648             tek_graph( pls );
00649             if ( ( ncol1 = MIN( 16 - pls->ncol0, pls->ncol1 ) ) < 1 )
00650                 break;
00651 
00652             icol1         = pls->ncol0 + ( pls->icol1 * ( ncol1 - 1 ) ) / ( pls->ncol1 - 1 );
00653             dev->curcolor = icol1;
00654             tek_color( pls, icol1 );
00655         }
00656         break;
00657 
00658     case PLSTATE_CMAP0:
00659     case PLSTATE_CMAP1:
00660         if ( pls->color & 0x01 )
00661             setcmap( pls );
00662 
00663         break;
00664     }
00665 }
00666 
00667 //--------------------------------------------------------------------------
00668 // plD_esc_tek()
00669 //
00670 // Escape function.
00671 //--------------------------------------------------------------------------
00672 
00673 void
00674 plD_esc_tek( PLStream *pls, PLINT op, void *ptr )
00675 {
00676     switch ( op )
00677     {
00678     case PLESC_TEXT:
00679         tek_text( pls );
00680         break;
00681 
00682     case PLESC_GRAPH:
00683         tek_graph( pls );
00684         break;
00685 
00686     case PLESC_FILL:
00687         fill_polygon( pls );
00688         break;
00689 
00690     case PLESC_GETC:
00691         GetCursor( pls, (PLGraphicsIn *) ptr );
00692         break;
00693     }
00694 }
00695 
00696 //--------------------------------------------------------------------------
00697 // GetCursor()
00698 //
00699 // Waits for a left button mouse event and returns coordinates.
00700 // xterm doesn't handle GIN. I think all the rest do.
00701 //--------------------------------------------------------------------------
00702 
00703 static void
00704 GetCursor( PLStream *pls, PLGraphicsIn *ptr )
00705 {
00706 #define MAX_GIN    10
00707     char input_string[MAX_GIN];
00708     int  i = 0;
00709 
00710     plGinInit( ptr );
00711 
00712     if ( pls->termin && pls->dev_minor != xterm )
00713     {
00714         tek_graph( pls );
00715 
00716         // Enter GIN mode
00717 
00718         printf( GIN_MODE );
00719         fflush( stdout );
00720 
00721         // Read & decode report
00722 
00723         while ( ++i < MAX_GIN && ( input_string[i - 1] = getchar() ) != '\n' )
00724             ;
00725 
00726         input_string[i - 1] = '\0';
00727         ptr->keysym         = input_string[0];
00728         decode_gin( &input_string[1], ptr );
00729 
00730         // Switch out of GIN mode
00731 
00732         printf( VECTOR_MODE );
00733     }
00734 }
00735 
00736 //--------------------------------------------------------------------------
00737 // fill_polygon()
00738 //
00739 // Fill polygon described in points pls->dev_x[] and pls->dev_y[].
00740 //--------------------------------------------------------------------------
00741 
00742 static void
00743 fill_polygon( PLStream *pls )
00744 {
00745     TekDev *dev = (TekDev *) pls->dev;
00746     int    i;
00747     char   fillcol[4], firstpoint[5];
00748 
00749     if ( pls->dev_npts < 1 )
00750         return;
00751 
00752     tek_graph( pls );
00753 
00754     encode_int( fillcol, -dev->curcolor );
00755     encode_vector( firstpoint, pls->dev_x[0], pls->dev_y[0] );
00756 
00757 // Select the fill pattern
00758 
00759     pls->bytecnt += fprintf( pls->OutFile, "\033MP%s", fillcol );
00760 
00761 // Begin panel boundary
00762 // Set pls->debug to see the boundary of each fill box -- cool!
00763 
00764     if ( pls->debug )
00765         pls->bytecnt += fprintf( pls->OutFile, "\033LP%s1", firstpoint );
00766     else
00767         pls->bytecnt += fprintf( pls->OutFile, "\033LP%s0", firstpoint );
00768 
00769 // Specify boundary (in vector mode)
00770 
00771     pls->bytecnt += fprintf( pls->OutFile, VECTOR_MODE );
00772     for ( i = 1; i < pls->dev_npts; i++ )
00773         tek_vector( pls, pls->dev_x[i], pls->dev_y[i] );
00774 
00775 // End panel
00776 
00777     pls->bytecnt += fprintf( pls->OutFile, "\033LE" );
00778 }
00779 
00780 //--------------------------------------------------------------------------
00781 // tek_text()
00782 //
00783 // Switch to text screen (or alpha mode, for vanilla tek's).  Restore
00784 // terminal to its original state, to better handle user input if
00785 // necessary.
00786 //
00787 // Note: xterm behaves strangely in the following circumstance: switch to
00788 // the text screen, print a string, and switch to the graphics screen, all
00789 // done in quick succession.  The first character of the printed string
00790 // usually comes out blank -- but only apparently so, because if you force
00791 // a refresh of the screen in this area it will reappear.  This is a
00792 // reproducible bug on the HP 720 under X11R5.  If you insert a sleep(1)
00793 // after the switch to text screen or before the switch to graphics
00794 // screen, the string is printed correctly.  I've been unable to find a
00795 // workaround for this problem (and I've tried, you can believe eet man).
00796 //--------------------------------------------------------------------------
00797 
00798 static void
00799 tek_text( PLStream *pls )
00800 {
00801     if ( pls->termin && ( pls->graphx == GRAPHICS_MODE ) )
00802     {
00803         tty_reset();
00804         pls->graphx = TEXT_MODE;
00805         switch ( pls->dev_minor )
00806         {
00807         case xterm:
00808             printf( "\033\003" );         // vt100 mode (xterm) = ESC ETX
00809             break;
00810 
00811         case mskermit:
00812         case vlt:
00813             printf( "\033[?38l" );        // vt100 screen
00814             break;
00815 
00816         case versaterm:
00817             printf( "\033%%!2" );         // vt100 screen
00818             break;
00819 
00820         case tek4107:
00821             printf( "\033LV1" );          // set dialog visible
00822             printf( "\033%%!1" );         // set ansi mode
00823             break;
00824 
00825         default:
00826             printf( ALPHA_MODE );         // enter alpha mode
00827         }
00828         fflush( stdout );
00829     }
00830 }
00831 
00832 //--------------------------------------------------------------------------
00833 // tek_graph()
00834 //
00835 // Switch to graphics screen.  Also switch terminal to cbreak mode, to allow
00836 // single keystrokes to govern actions at end of page.
00837 //--------------------------------------------------------------------------
00838 
00839 static void
00840 tek_graph( PLStream *pls )
00841 {
00842     if ( pls->termin && ( pls->graphx == TEXT_MODE ) )
00843     {
00844         tty_cbreak();
00845         pls->graphx = GRAPHICS_MODE;
00846         switch ( pls->dev_minor )
00847         {
00848         case xterm:
00849         case mskermit:
00850         case vlt:
00851             printf( "\033[?38h" );        // switch to tek screen
00852             break;
00853 
00854         case versaterm:
00855             printf( "\033%%!0" );         // switch to tek4107 screen
00856             break;
00857 
00858         case tek4107:
00859             printf( "\033%%!0" );         // set tek mode
00860             printf( CLEAR_VIEW );         // clear screen
00861             printf( "\033LV0" );          // set dialog invisible
00862             break;
00863         }
00864     }
00865 }
00866 
00867 //--------------------------------------------------------------------------
00868 // encode_int()
00869 //
00870 // Encodes a single int into standard tek integer format, storing into a
00871 // NULL-terminated character string (must be length 4 or greater).  This
00872 // scheme does not work for negative integers less than 15.
00873 //--------------------------------------------------------------------------
00874 
00875 static void
00876 encode_int( char *c, int i )
00877 {
00878     int negative = 0;
00879 
00880     if ( i > 0 )
00881     {
00882         if ( i & 0x7C00 )                       // are any of bits 10-14 set?
00883             *c++ = ( ( i >> 10 ) & 0x1F ) | 0x40;
00884         if ( i & 0x03F0 )                       // are any of bits 4-9 set?
00885             *c++ = ( ( i >> 4 ) & 0x3F ) | 0x40;
00886     }
00887     else
00888     {
00889         i        = -i;
00890         negative = 1;
00891     }
00892 
00893     if ( i & 0x000F )                           // are any of bits 0-3 set?
00894         *c = ( i & 0x0F ) | 0x20;
00895     else                                        // if not, put in a space
00896         *c = 0x20;
00897 
00898     if ( !negative )                            // if positive, set sign bit
00899         *c |= 0x10;
00900 
00901     c++; *c = '\0';                             // NULL-terminate
00902     return;
00903 }
00904 
00905 //--------------------------------------------------------------------------
00906 // decode_gin()
00907 //
00908 // Decodes a GIN tek vector string into an xy pair of relative device
00909 // coordinates.  It's best to not use absolute device coordinates since the
00910 // coordinate bounds are different depending on the report encoding used.
00911 //
00912 // Standard:    <HiX><LoX><HiY><LoY>
00913 // Extended:    <HiY><Extra><LoY><HiX><LoX>
00914 //
00915 // where <Extra> holds the two low order bits for each coordinate.
00916 //--------------------------------------------------------------------------
00917 
00918 static void
00919 decode_gin( char *c, PLGraphicsIn *gin )
00920 {
00921     int x, y, lc = strlen( c );
00922 
00923     if ( lc == 4 )
00924     {
00925         x = ( ( c[0] & 0x1f ) << 5 ) +
00926             ( ( c[1] & 0x1f ) );
00927 
00928         y = ( ( c[2] & 0x1f ) << 5 ) +
00929             ( ( c[3] & 0x1f ) );
00930 
00931         gin->pX = x;
00932         gin->pY = y;
00933         gin->dX = x / (double) TEKX;
00934         gin->dY = y / (double) TEKY;
00935     }
00936     else if ( lc == 5 )
00937     {
00938         y = ( ( c[0] & 0x1f ) << 7 ) +
00939             ( ( c[2] & 0x1f ) << 2 ) +
00940             ( ( c[1] & 0x06 ) >> 2 );
00941 
00942         x = ( ( c[3] & 0x1f ) << 7 ) +
00943             ( ( c[4] & 0x1f ) << 2 ) +
00944             ( ( c[1] & 0x03 ) );
00945 
00946         gin->pX = x;
00947         gin->pY = y;
00948         gin->dX = x / (double) ( TEKX << 2 );
00949         gin->dY = y / (double) ( TEKY << 2 );
00950     }
00951     else                        // Illegal encoding
00952     {
00953         gin->pX = 0;
00954         gin->pY = 0;
00955         gin->dY = 0;
00956         gin->dX = 0;
00957     }
00958 }
00959 
00960 //--------------------------------------------------------------------------
00961 // encode_vector()
00962 //
00963 // Encodes an xy vector (2 ints) into standard tek vector format, storing
00964 // into a NULL-terminated character string of length 5.  Note that the y
00965 // coordinate always comes first.
00966 //--------------------------------------------------------------------------
00967 
00968 static void
00969 encode_vector( char *c, int x, int y )
00970 {
00971     c[0] = ( y >> 5 ) + 0x20;             // hy
00972     c[1] = ( y & 0x1f ) + 0x60;           // ly
00973     c[2] = ( x >> 5 ) + 0x20;             // hx
00974     c[3] = ( x & 0x1f ) + 0x40;           // lx
00975     c[4] = '\0';                          // NULL
00976 }
00977 
00978 //--------------------------------------------------------------------------
00979 // tek_vector()
00980 //
00981 // Issues a vector draw command, assuming we are in vector plot mode.  XY
00982 // coordinates are encoded according to the standard xy encoding scheme.
00983 //--------------------------------------------------------------------------
00984 
00985 static void
00986 tek_vector( PLStream *pls, int x, int y )
00987 {
00988     char c[5];
00989 
00990     encode_vector( c, x, y );
00991     pls->bytecnt += fprintf( pls->OutFile, "%s", c );
00992 }
00993 
00994 //--------------------------------------------------------------------------
00995 // scolor()
00996 //
00997 // Sets a color by tek-encoded RGB values.  Need to convert PLplot RGB
00998 // color range (0 to 255) to Tek RGB color range (0 to 100).
00999 //--------------------------------------------------------------------------
01000 
01001 static void
01002 scolor( PLStream *pls, int icol, int r, int g, int b )
01003 {
01004     char tek_col[4], tek_r[4], tek_g[4], tek_b[4];
01005 
01006     encode_int( tek_col, icol );
01007     encode_int( tek_r, ( 100 * r ) / 255 );
01008     encode_int( tek_g, ( 100 * g ) / 255 );
01009     encode_int( tek_b, ( 100 * b ) / 255 );
01010 
01011     pls->bytecnt += fprintf( pls->OutFile, "\033TG14%s%s%s%s",
01012         tek_col, tek_r, tek_g, tek_b );
01013 }
01014 
01015 //--------------------------------------------------------------------------
01016 // setcmap()
01017 //
01018 // Sets up color palette.
01019 //--------------------------------------------------------------------------
01020 
01021 static void
01022 setcmap( PLStream *pls )
01023 {
01024     int     i, ncol1 = MIN( 16 - pls->ncol0, pls->ncol1 );
01025     PLColor cmap1col;
01026 
01027     tek_graph( pls );
01028 
01029 // Initialize cmap 0 colors
01030 
01031     for ( i = 0; i < pls->ncol0; i++ )
01032         scolor( pls, i, pls->cmap0[i].r, pls->cmap0[i].g, pls->cmap0[i].b );
01033 
01034 // Initialize any remaining slots for cmap1
01035 
01036     for ( i = 0; i < ncol1; i++ )
01037     {
01038         plcol_interp( pls, &cmap1col, i, ncol1 );
01039         scolor( pls, i + pls->ncol0, cmap1col.r, cmap1col.g, cmap1col.b );
01040     }
01041 }
01042 
01043 //--------------------------------------------------------------------------
01044 // WaitForPage()
01045 //
01046 // This routine waits for the user to advance the plot, while handling
01047 // all other events.
01048 //--------------------------------------------------------------------------
01049 
01050 static void
01051 WaitForPage( PLStream *pls )
01052 {
01053     TekDev *dev = (TekDev *) pls->dev;
01054 
01055     printf( ALPHA_MODE );         // Switch to alpha mode (necessary)
01056     printf( RING_BELL );          // and ring bell
01057     printf( VECTOR_MODE );        // Switch out of alpha mode
01058     fflush( stdout );
01059 
01060     while ( !dev->exit_eventloop )
01061     {
01062         LookupEvent( pls );
01063         if ( dev->locate_mode )
01064             LocateEH( pls );
01065         else
01066             InputEH( pls );
01067     }
01068     dev->exit_eventloop = FALSE;
01069 }
01070 
01071 //--------------------------------------------------------------------------
01072 // LookupEvent()
01073 //
01074 // Fills in the PLGraphicsIn from an input event.
01075 //--------------------------------------------------------------------------
01076 
01077 static void
01078 LookupEvent( PLStream *pls )
01079 {
01080     TekDev       *dev = (TekDev *) pls->dev;
01081     PLGraphicsIn *gin = &( dev->gin );
01082 
01083     if ( dev->locate_mode )
01084     {
01085         GetCursor( pls, gin );
01086     }
01087     else
01088     {
01089         plGinInit( gin );
01090         gin->keysym = getchar();
01091     }
01092 
01093     if ( isprint( gin->keysym ) )
01094     {
01095         gin->string[0] = gin->keysym;
01096         gin->string[1] = '\0';
01097     }
01098     else
01099     {
01100         gin->string[0] = '\0';
01101     }
01102 
01103     pldebug( "LookupEvent",
01104         "Keycode %x, string: %s\n", gin->keysym, gin->string );
01105 }
01106 
01107 //--------------------------------------------------------------------------
01108 // LocateEH()
01109 //
01110 // Handles locate mode events.
01111 //
01112 // In locate mode: move cursor to desired location and select by pressing a
01113 // key or by clicking on the mouse (if available).  Typically the world
01114 // coordinates of the selected point are reported.
01115 //
01116 // There are two ways to enter Locate mode -- via the API, or via a driver
01117 // command.  The API entry point is the call plGetCursor(), which initiates
01118 // locate mode and does not return until input has been obtained.  The
01119 // driver entry point is by entering a 'L' while the driver is waiting for
01120 // events.
01121 //
01122 // Locate mode input is reported in one of three ways:
01123 // 1. Through a returned PLGraphicsIn structure, when user has specified a
01124 //    locate handler via (*pls->LocateEH).
01125 // 2. Through a returned PLGraphicsIn structure, when locate mode is invoked
01126 //    by a plGetCursor() call.
01127 // 3. Through writes to stdout, when locate mode is invoked by a driver
01128 //    command and the user has not supplied a locate handler.
01129 //
01130 // Hitting <Escape> will at all times end locate mode.  Other keys will
01131 // typically be interpreted as locator input.  Selecting a point out of
01132 // bounds will end locate mode unless the user overrides with a supplied
01133 // Locate handler.
01134 //--------------------------------------------------------------------------
01135 
01136 static void
01137 LocateEH( PLStream *pls )
01138 {
01139     TekDev       *dev = (TekDev *) pls->dev;
01140     PLGraphicsIn *gin = &( dev->gin );
01141 
01142 // End locate mode on <Escape>
01143 
01144     if ( gin->keysym == PLK_Escape )
01145     {
01146         dev->locate_mode = 0;
01147         return;
01148     }
01149 
01150 // Call user locate mode handler if provided
01151 
01152     if ( pls->LocateEH != NULL )
01153         ( *pls->LocateEH )( gin, pls->LocateEH_data, &dev->locate_mode );
01154 
01155 // Use default procedure
01156 
01157     else
01158     {
01159         // Try to locate cursor
01160 
01161         if ( plTranslateCursor( gin ) )
01162         {
01163             // Successful, so send report to stdout
01164 
01165             pltext();
01166             if ( isprint( gin->keysym ) )
01167                 printf( "%f %f %c\n", gin->wX, gin->wY, gin->keysym );
01168             else
01169                 printf( "%f %f\n", gin->wX, gin->wY );
01170 
01171             plgra();
01172         }
01173         else
01174         {
01175             // Selected point is out of bounds, so end locate mode
01176 
01177             dev->locate_mode = 0;
01178         }
01179     }
01180 }
01181 
01182 //--------------------------------------------------------------------------
01183 // InputEH()
01184 //
01185 // Event handler routine for xterm.  Just reacts to keyboard input.
01186 //
01187 // In locate mode: move cursor to desired location and select by pressing a
01188 // key or by clicking on the mouse (if available).  The world coordinates of
01189 // the selected point are output on the text screen.  Terminate by picking a
01190 // point out of bounds, hitting page advance, or the escape key.  If you
01191 // want to customize this, write an event handler to do it.
01192 //--------------------------------------------------------------------------
01193 
01194 static void
01195 InputEH( PLStream *pls )
01196 {
01197     TekDev       *dev = (TekDev *) pls->dev;
01198     PLGraphicsIn *gin = &( dev->gin );
01199 
01200 // Call user event handler.
01201 // Since this is called first, the user can disable all PLplot internal
01202 // event handling by setting gin->keysym to 0 and gin->string to '\0'.
01203 //
01204     if ( pls->KeyEH != NULL )
01205         ( *pls->KeyEH )( gin, pls->KeyEH_data, &dev->exit_eventloop );
01206 
01207 // Remaining internal event handling
01208 
01209     switch ( gin->keysym )
01210     {
01211     case PLK_Linefeed:
01212         // Advance to next page (i.e. terminate event loop) on a <eol>
01213         dev->exit_eventloop = TRUE;
01214         break;
01215 
01216     case 'Q':
01217         // Terminate on a 'Q' (not 'q', since it's too easy to hit by mistake)
01218         pls->nopause = TRUE;
01219         plexit( "" );
01220         break;
01221 
01222     case 'L':
01223         // Begin locate mode
01224         dev->locate_mode = 1;
01225         break;
01226     }
01227 }
01228 
01229 //--------------------------------------------------------------------------
01230 // tty cbreak-mode handlers
01231 //
01232 // Taken from "Advanced Programming in the UNIX(R) Environment",
01233 // by W. Richard Stevens.
01234 //--------------------------------------------------------------------------
01235 
01236 #ifdef HAVE_TERMIOS_H
01237 
01238 static void
01239 tty_setup( void )                         // setup for terminal operations
01240 {
01241     if ( tcgetattr( STDIN_FILENO, &termios_reset ) < 0 )
01242     {
01243         fprintf( stderr, "Unable to set up cbreak mode.\n" );
01244         return;
01245     }
01246 
01247     termios_cbreak = termios_reset;             // structure copy
01248 
01249     termios_cbreak.c_lflag    &= ~( ICANON );   // canonical mode off
01250     termios_cbreak.c_cc[VMIN]  = 1;             // 1 byte at a time
01251     termios_cbreak.c_cc[VTIME] = 0;             // no timer
01252 
01253 #ifdef STDC_HEADERS
01254     if ( atexit( tty_atexit ) )
01255         fprintf( stderr, "Unable to set up atexit handler.\n" );
01256 #endif
01257     return;
01258 }
01259 
01260 static int
01261 tty_cbreak( void )                        // put terminal into a cbreak mode
01262 {
01263     if ( ttystate != CBREAK )
01264     {
01265         if ( tcsetattr( STDIN_FILENO, TCSAFLUSH, &termios_cbreak ) < 0 )
01266             return -1;
01267 
01268         ttystate = CBREAK;
01269     }
01270     return 0;
01271 }
01272 
01273 static int
01274 tty_reset( void )                         // restore terminal's mode
01275 {
01276     if ( ttystate != RESET )
01277     {
01278         if ( tcsetattr( STDIN_FILENO, TCSAFLUSH, &termios_reset ) < 0 )
01279             return -1;
01280 
01281         ttystate = RESET;
01282     }
01283     return 0;
01284 }
01285 
01286 static void
01287 tty_atexit( void )                        // exit handler
01288 {
01289     tty_reset();
01290 }
01291 
01292 #endif                  // HAVE_TERMIOS_H
01293 
01294 #else
01295 int pldummy_tek()
01296 {
01297     return 0;
01298 }
01299 
01300 #endif  //  defined(PLD_xterm) || ...
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines