// Maurice LeBrun // IFS, University of Texas // Feb 15, 1995 // // Test program for illustrating possible Tek GIN anomalies. In // particular, for problems with GIN reports encountered in VLT (Tek // 4107 emulator for the Amiga). May not work right with other Tek // emulators. // // To compile: "$CC foo.c -o foo", where $CC is an ANSI-C compiler. // // Usage: // // % foo [x0 [y0]] // // To reproduce problem: // Run program, then turn on graphic crosshair with XY and position over // the intersection of the drawn lines. Experiment with different // crosshair locations, entered via the command line. Invariably, // the reported position is systematically <= than the drawn one, // sometimes by as much as 2 pixels. // // Note: this anomaly has important consequences when doing graphic // input, because the reported world coordinates are then // systematically off. // #include <stdio.h> #include <stdlib.h> #include <ctype.h> // Static function prototypes void plD_init_vlt( void ); void plD_line_tek( short, short, short, short ); void plD_eop_tek( void ); void plD_bop_tek( void ); void plD_tidy_tek( void ); static void WaitForPage( void ); static void tek_text( void ); static void tek_graph( void ); static void encode_int( char *c, int i ); static void encode_vector( char *c, int x, int y ); static void tek_vector( int x, int y ); // Graphics control characters. #define RING_BELL "\007" // ^G = 7 #define CLEAR_VIEW "\033\f" // clear the view = ESC FF #define ALPHA_MODE "\037" // Enter Alpha mode: US #define VECTOR_MODE "\035" // Enter Vector mode: GS #define GIN_MODE "\033\032" // Enter GIN mode: ESC SUB #define BYPASS_MODE "\033\030" // Enter Bypass mode: ESC CAN #define XTERM_VTMODE "\033\003" // End xterm-Tek mode: ESC ETX #define CANCEL "\033KC" // Cancel //-------------------------------------------------------------------------- // main // // Generates simple test case. //-------------------------------------------------------------------------- int main( int argc, char *argv[] ) { short x0 = 300, y0 = 300, l = 100; short x1, x2, y1, y2; // Optional x0, y0 specification by the command line if ( argc > 1 ) x0 = atoi( argv[1] ); if ( argc > 2 ) y0 = atoi( argv[2] ); plD_init_vlt(); // Draw boundary plD_line_tek( 0, 0, 1023, 0 ); plD_line_tek( 1023, 0, 1023, 779 ); plD_line_tek( 1023, 779, 0, 779 ); plD_line_tek( 0, 779, 0, 0 ); // Draw crosshairs centered around (x0, y0) of length 2l x1 = x0 - l, x2 = x0 + l; y1 = y0 - l, y2 = y0 + l; plD_line_tek( x1, y0, x2, y0 ); plD_line_tek( x0, y1, x0, y2 ); plD_eop_tek(); plD_tidy_tek(); exit( 0 ); } //-------------------------------------------------------------------------- // plD_init_vlt() VLT emulator (Amiga) //-------------------------------------------------------------------------- void plD_init_vlt( void ) { tek_graph(); fprintf( stdout, VECTOR_MODE ); // Enter vector mode fprintf( stdout, CLEAR_VIEW ); // erase and home } //-------------------------------------------------------------------------- // plD_line_tek() // // Draw a line from (x1,y1) to (x2,y2). //-------------------------------------------------------------------------- void plD_line_tek( short x1, short y1, short x2, short y2 ) { fprintf( stdout, VECTOR_MODE ); tek_vector( x1, y1 ); tek_vector( x2, y2 ); } //-------------------------------------------------------------------------- // plD_eop_tek() // // End of page. User must hit a <CR> to continue (terminal output). //-------------------------------------------------------------------------- void plD_eop_tek( void ) { WaitForPage(); fprintf( stdout, CLEAR_VIEW ); // erase and home } //-------------------------------------------------------------------------- // plD_tidy_tek() // // Close graphics file or otherwise clean up. //-------------------------------------------------------------------------- void plD_tidy_tek( void ) { tek_text(); } //-------------------------------------------------------------------------- // tek_text() //-------------------------------------------------------------------------- static void tek_text( void ) { printf( "\033[?38l" ); // vt100 screen } //-------------------------------------------------------------------------- // tek_graph() //-------------------------------------------------------------------------- static void tek_graph( void ) { printf( "\033[?38h" ); // switch to tek screen } //-------------------------------------------------------------------------- // encode_int() // // Encodes a single int into standard tek integer format, storing into a // NULL-terminated character string (must be length 4 or greater). This // scheme does not work for negative integers less than 15. //-------------------------------------------------------------------------- static void encode_int( char *c, int i ) { int negative = 0; if ( i > 0 ) { if ( i & 0x7C00 ) // are any of bits 10-14 set? *c++ = ( ( i >> 10 ) & 0x1F ) | 0x40; if ( i & 0x03F0 ) // are any of bits 4-9 set? *c++ = ( ( i >> 4 ) & 0x3F ) | 0x40; } else { i = -i; negative = 1; } if ( i & 0x000F ) // are any of bits 0-3 set? *c = ( i & 0x0F ) | 0x20; else // if not, put in a space *c = 0x20; if ( !negative ) // if positive, set sign bit *c |= 0x10; c++; *c = '\0'; // NULL-terminate return; } //-------------------------------------------------------------------------- // encode_vector() // // Encodes an xy vector (2 ints) into standard tek vector format, storing // into a NULL-terminated character string of length 5. Note that the y // coordinate always comes first. //-------------------------------------------------------------------------- static void encode_vector( char *c, int x, int y ) { c[0] = ( y >> 5 ) + 0x20; // hy c[1] = ( y & 0x1f ) + 0x60; // ly c[2] = ( x >> 5 ) + 0x20; // hx c[3] = ( x & 0x1f ) + 0x40; // lx c[4] = '\0'; // NULL } //-------------------------------------------------------------------------- // tek_vector() // // Issues a vector draw command, assuming we are in vector plot mode. XY // coordinates are encoded according to the standard xy encoding scheme. //-------------------------------------------------------------------------- static void tek_vector( int x, int y ) { char c[5]; c[0] = ( y >> 5 ) + 0x20; // hy c[1] = ( y & 0x1f ) + 0x60; // ly c[2] = ( x >> 5 ) + 0x20; // hx c[3] = ( x & 0x1f ) + 0x40; // lx c[4] = '\0'; // NULL fprintf( stdout, "%s", c ); } //-------------------------------------------------------------------------- // WaitForPage() // // This routine waits for the user to advance the plot, while handling // all other events. //-------------------------------------------------------------------------- static void WaitForPage( void ) { printf( ALPHA_MODE ); // Switch to alpha mode (necessary) printf( RING_BELL ); // and ring bell printf( VECTOR_MODE ); // Switch out of alpha mode fflush( stdout ); while ( !getchar() ) ; }