PLplot
5.10.0
|
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) || ...