• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

tek.c

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

Generated on Wed Oct 12 2011 20:42:23 for PLplot by  doxygen 1.7.1