esfraga@water.UUCP (Eric S Fraga) (09/11/86)
# This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by water!esfraga on Sun Aug 3 17:22:02 EDT 1986 # Contents: README debug.c externs.c main.c screen.c tek.c window.c wterm.h # wterm.inp echo x - README sed 's/^@//' > "README" <<'@//E*O*F README//' WTerm-II Description This is a new version of WTerm (posted to the net several months ago). All the features in the old version have been retained (these included: Tek 4010 emulation, sysline support, add/delete line and char) with several new features added. The new version uses many more features of GEM. The menu bar is used for a cleaner user interface. This allows the use of any desk accessories that may be available. The terminal screen is now displayed inside a window which may be sized and moved. How to use This new program is a GEM application -- just double click on the particular icon and it will start up. The initial window is full size (77x20) but may be changed thereafter. The menu bar allows the user to select a new baud rate (although the default will be used) and the duplex. Any other line characteristics must be set elsewhere (I use the VT52 desk accessory for that). The approach taken with respect to the window is that the terminal screen takes up the whole window (nothing more; nothing less). That means that the window is not a 'window' into a virtual screen. As a result, whenever the window is resized, the host machine must be informed of this (if the host needs to know screen sizes as in Unix to use 'vi', 'emacs', etc.). The program has an option "New Termcap" which will send the termcap entry with the proper 'co' and 'li' entries to the host (note: this must only be done when the user is at the command level and that command level must be a 'csh' type because the command sent is of the form: setenv TERMCAP 'xx|window|window-s:hs:ts=\EN:fs=\EO:co#77:li#19...' ). The default termcap entry (which corresponds to the biggest window allowed = initial window) is: xx|window520st-s|window-s|window 520st vt52 emulation with sysline:\ :hs:ts=\EN:fs=\EO:\ :tc=window: xx|window520st|window|window 520st vt52 emulation:\ :co#77:li#20:nd=\EC:\ :am:bs:pt:xt:\ :cd=\EJ:ce=\EK:cl=\EE:\ :do=\EB:up=\EA:cm=\EY%+ %+ :\ :dl=\EM:al=\EL:\ :dc=\Em:ic=\El:im=:ei=:\ :ku=\EA:kl=\ED:kd=\EB:kr=\EC:kh=\EH:\ :kb=^H:\ :so=\Ep:se=\Eq: Known Bugs and Limitations There are several known bugs/limitations: - for some reason, the bottom row of pixels in a line is sometimes lost (this happens in 'vi' when scrolling up for example). I haven't been able to track this one down... - due to some interaction between the GEM and TOS levels on the ST, the first few characters typed in are ignored by the program. That is, the program does not get the first few characters (anywhere from 3 to 10). I have seen this bug elsewhere and has to do with using GEM event routines in conjunction with TOS console i/o routines... Just hold down some key until the program responds! - will not run very well at baud rates > 2400. The program should not lose characters but effective baud rate at 9600 comes out to approximately 2400. - tek mode plots are relative to the top left of the physical screen and are clipped to fit in the actual window. This means that if the actual plot uses parts of the edges of the screen, this information will not come out in the window. Yechh. I think that's it (whew). If anybody finds any more, please let me know (although due to the fact that my machine and I will be on separate continents for most of the next year, it is doubtful that I will do anything...). Eric S Fraga || esfraga@water.uucp Dept of Computer Science || esfraga@water.Waterloo.edu U of Waterloo || esfraga%water@waterloo.csnet @//E*O*F README// chmod u=rw,g=r,o=r README echo x - debug.c sed 's/^@//' > "debug.c" <<'@//E*O*F debug.c//' #include <osbind.h> Debug(s) char *s; { Cconout(27); Cconws( "Y " ); /* top left corner of screen */ Cconout(27); Cconout( 'K' ); /* clear to end of line */ Cconws(s); } char *digits = "0123456789"; DebugP(s,x) char *s; int x; { int d,i,len; char sign, buf[12]; buf[11] = '\0'; for( i=0; i<11; i++ ) buf[i] = ' '; len = 11; Debug(s); sign = ' '; if( x < 0 ) { sign = '-'; x = -x; } i = len - 1; do { d = x % 10; buf[i] = digits[d]; i--; x = x/10; } while( x != 0 ); buf[i] = sign; Cconws( &buf[i] ); Cconin(); Debug( "ok" ); } @//E*O*F debug.c// chmod u=rw,g=r,o=r debug.c echo x - externs.c sed 's/^@//' > "externs.c" <<'@//E*O*F externs.c//' #define EXTERN 1 #include "wterm.h" int Window; int Handle; int Ox, Oy, Ow, Oh; /* outer size of window */ int Ix, Iy, Iw, Ih; /* inner size of window */ int n_col = N_COL, n_row = N_ROW; /* number of rows and columns in window */ int max_col, max_row; /* maximum number allowed by physical screen */ long gaddr; /* used by the resource files */ int Xdesk, Ydesk, Wdesk, Hdesk; int CharW, CharH; /* character cell width and height */ int Baseline; /* Bottom line relative to baseline */ char Screen[N_ROW][1+N_COL]; /* image of whole screen */ int Scr_col, Scr_row; int Sysl_row, Sysl_col, Sysline; int command, comd_pos; /* used in screen.c mostly */ int Half; /* Half/full duplex */ int T_mode, T_draw, T_count; /* used in TEK 4010 emulation */ int T_x, T_y; /* current X and Y graphics pos */ int contrl[12]; int intin[128]; int ptsin[128]; int intout[128]; int ptsout[128]; @//E*O*F externs.c// chmod u=rw,g=r,o=r externs.c echo x - main.c sed 's/^@//' > "main.c" <<'@//E*O*F main.c//' /* * Terminal emulator using VDI routines * * Eric S Fraga * 1986 March 4 * Revision: 1986 July 10 -- converted to use a window and menu bar * * Based on a window demo: * ***************************************************** * Window demo * * by Jerome M. Lang 21 February 1986 * * PD * *****************************************************/ #include <obdefs.h> #include <gemdefs.h> #include <define.h> #include <osbind.h> #include "wterm.h" /* * main processing */ main() { #ifdef WINDOW /* * The window version of this program uses the menu bar. */ int MenuId; MenuId = -1; Window = NO_WINDOW; #endif appl_init(); #ifdef WINDOW /* * make sure the mouse is an arrow. */ graf_mouse( ARROW, 0L); #endif /* * Initialize very many things... amongst them, open the * window (if using windows), clear the screen, set up all * the appropriate flags, and possibly set up the menu. */ initMain(); /* * Init Screen stuff, then show the window. */ Init_Scr(); /* * Finally, call the actual terminal emulator (routine that * processes characters from the serial port and the * keyboard). */ term(); #ifdef WINDOW menu_bar( gaddr, 0 ); /* erase the menu bar */ rsrc_free(); /* free up the resources */ #endif v_clsvwk( Handle ); /* close the window */ appl_exit(); } initMain() { int attrib[10]; int distances[5],effects[3]; int workIn[11], workOut[57]; auto int dummy; int i; int ret; /* find size of desk */ #ifdef WINDOW wind_get( 0, WF_WORKXYWH, &Xdesk, &Ydesk, &Wdesk, &Hdesk ); #else /* * very kludgy: hard coded constants!!! (yechhh) */ Ix = 0; Iy = 0; Iw = 639; Ih = 399; #endif /* * Get a handle (no pun intended) on the screen. Set up all * the VDI shit... and finally open the workstation. */ Handle=graf_handle(&dummy,&dummy,&dummy,&dummy); for( i=0; i<10; i++) workIn[i]=1; workIn[10]=2; v_opnvwk(workIn, &Handle, workOut); /* * how big is character cell? */ vqt_attribute( Handle, attrib ); CharW = attrib[8]; CharH = attrib[9]; #ifdef WINDOW /* * Calculate the location and size of the maximum size window * that can be used. */ Ox = Xdesk; Oy = Ydesk; Ow = Wdesk; Oh = Hdesk; ret = wind_calc(1, W_KIND, Ox, Oy, Ow, Oh, &Ix, &Iy, &Iw, &Ih ); n_row = max_row = Ih / CharH - 1; n_col = max_col = Iw / CharW; if( n_row > N_ROW ) n_row = max_row = N_ROW; if( n_col > N_COL ) n_col = max_col = N_COL; Iw = n_col * CharW; Ih = (n_row+1) * CharH; ret = wind_calc( 0, W_KIND, Ix, Iy, Iw, Ih, &Ox, &Oy, &Ow, &Oh ); #endif vqt_fontinfo( Handle, &dummy, &dummy, distances, &dummy, effects); Baseline = distances[0]; /* * set fill pattern & color in order to clear window */ vsf_color( Handle, 0 ); /* * Initialize some other stuff */ #ifdef WINDOW Wopen(); /* open the window */ #endif Clear(); /* clear the window */ Clear_Sysl(); /* and the sysline line */ command = FALSE; /* no terminal command started yet */ comd_pos = 0; /* used by MOVE_CURSOR term command */ Half = FALSE; /* Full duplex is the default */ T_mode = ALPHA; /* text mode at start */ T_x = 0; /* TEK x coord = 0 */ T_y = 0; /* ditto for TEK y */ Sysline = FALSE; /* not in sysline mode yet */ #ifdef WINDOW /* * attempt to load in the resource file and then * set up the menu bar... */ ret = rsrc_load( RSC_FILE ); if( 0 == ret ) { Pterm0(); } /* * to set up the menu bar, must get the address of * the menu from the tree. */ ret = rsrc_gaddr( 0, TREE1, &gaddr ); if( 0 == ret ) { Pterm0(); } /* * now actually set up the menu */ ret = menu_bar( gaddr, 1 ); /* display the menu */ if( 0 == ret ) { Pterm0(); } #endif } /* * term * * This is the actual terminal emulator. Characters are read in * from the serial port, processed, and then displayed as necessary. * Likewise, characters from the keyboard are sent down the serial * line. * * In the window version, any time there has been no activity at * either the serial line or the keyboard, GEM is given control * for a little while (to allow user to use the mouse and desk * accessories). */ term() { long lx; int ret, done = FALSE; int flag = FALSE; register int x, Curscnt, n, Gemcount, mouse; register char c; Cursor(); Curscnt = CURSCNT; Gemcount = GEMCOUNT; graf_mouse( M_OFF, 0L ); mouse = FALSE; while(!done) { /* * Check keyboard for characters. Using event seems * to miss lots of chars unfortunately. */ flag = FALSE; x = Cconis(); /* check status */ if( 0 != x ) { /* some chars waiting */ if( TRUE == mouse ) { graf_mouse( M_OFF, 0L ); mouse = FALSE; } Gemcount = GEMCOUNT; flag = TRUE; lx = (long) Crawcin(); /* read from console */ c = (char) (lx & 0x7fL); /* actual character */ if( NIL == c ) done = special(lx); else { Cauxout(c); /* send to serial port */ if( TRUE == Half ) { if( Curscnt <= 0 ) Cursor(); /* Disable cursor */ proc( (char) c ); Curscnt = CURSCNT; /* reset count */ } } } /* * Finally, check the serial port for stuff. */ x = Cauxis(); if( -1 == x ) { /* there's something there */ if( TRUE == mouse ) { graf_mouse( M_OFF, 0L ); mouse = FALSE; } Gemcount = GEMCOUNT; flag = TRUE; if( Curscnt <= 0 ) Cursor(); /* Disable cursor */ n = 10; /* read up to 10 chars */ do { c = Cauxin(); c = c & 0x7f; /* get rid of parity */ proc( (char) c ); } while( n-->0 && (x=Cauxis()) == -1); Curscnt = CURSCNT; /* reset count */ } else if( Curscnt > 0 && ALPHA == T_mode ) { Curscnt--; if( Curscnt <= 0 ) Cursor(); /* Enable cursor */ } #ifdef WINDOW if( --Gemcount < 0 ) { /* * there was neither a character from the * keyboard nor the serial line in a long * time so let GEM get some control. */ if( FALSE == mouse ) { graf_mouse( M_ON, 0L ); mouse = TRUE; } done = Wproc(); Gemcount = 0; /* reset counter */ } #endif } } /* * Special key has been hit * (ie. function keys, arrow keys, HELP, UNDO, etc) */ special(x) long x; { register char c; c = (char) ( (x >> 16) & 0x7f ); switch( c ) { case HELP: do_help(); break; case UNDO: return( TRUE ); break; case HOME: Cauxout( ESC ); Cauxout( HO ); break; case UARROW: Cauxout( ESC ); Cauxout( UP ); break; case LARROW: Cauxout( ESC ); Cauxout( LE ); break; case DARROW: Cauxout( ESC ); Cauxout( DO ); break; case RARROW: Cauxout( ESC ); Cauxout( ND ); break; } return( FALSE ); } /* * do_help * * User hit HELP key. This key gives short description (ie. help) and * allows user to set some variables (like baud rate and such). */ do_help() { /* * don't this right now as it screws up the desktop... * (must do the baud rate and duplex stuff using menu * items which is better anyway) */ #ifndef WINDOW register char c; do { Cconout( ESC ); Cconout( CL ); Cconws( "WTerm -- UNDO to quit, HELP for help\r\n" ); Cconws( "(c) 1986 Eric S. Fraga\r\n\n" ); Cconws( "Hit:\r\n" ); Cconws( "\t1\t300 baud\r\n" ); Cconws( "\t2\t1200 baud\r\n" ); Cconws( "\t3\t2400 baud\r\n" ); Cconws( "\t4\t4800 baud\r\n" ); Cconws( "\t5\t9600 baud\r\n\n" ); Cconws( "\tf\tFull duplex\r\n" ); Cconws( "\th\tHalf duplex\r\n\n" ); Cconws( "\tspace\tto return\r\n\n" ); Cconws( "-->" ); /* * read in char from user */ c = Cconin(); switch( c ) { case 'q': case ' ': wshow( Ix, Iy, Iw, Ih ); break; case '1': Rsconf( B300, -1, -1, -1, -1, -1 ); break; case '2': Rsconf( B1200, -1, -1, -1, -1, -1 ); break; case '3': Rsconf( B2400, -1, -1, -1, -1, -1 ); break; case '4': Rsconf( B4800, -1, -1, -1, -1, -1 ); break; case '5': Rsconf( B9600, -1, -1, -1, -1, -1 ); break; case 'f': Half = FALSE; break; case 'h': Half = TRUE; break; default: Cconout(7); break; } } while( c != ' ' && c != 'q' ); #endif /* !WINDOW */ T_mode = ALPHA; /* just to have some way to reset for now */ } #ifdef MEGAMAX vqt_fontin(handle,minADE,maxADE,dist,maxw,effects) int handle,dist[5],effects[3]; int *minADE, *maxADE, *maxw; { vqt_font_info(handle,minADE,maxADE,dist,maxw,effects); } #endif /* MEGAMAX */ @//E*O*F main.c// chmod u=rw,g=r,o=r main.c echo x - screen.c sed 's/^@//' > "screen.c" <<'@//E*O*F screen.c//' #include <obdefs.h> #include <gemdefs.h> #include <define.h> #include <osbind.h> #include "wterm.h" /* * Init_Scr * * Initialize all the stuff associated with the screen: * * Clear the screen, reset row and column, etc. */ Init_Scr() { register int i, j; for( i=0; i<n_row; i++ ) { for( j=0; j<N_COL; j++ ) { Screen[i][j] = ' '; } Screen[i][n_col] = EOS; } Scr_col = 0; Scr_row = 0; } /* * Clear the sysline */ Init_Sysl() { register int i; for( i=0; i<n_col; i++ ) Screen[n_row][i] = ' '; Screen[n_row][n_col] = EOS; } /* * proc * * Process a character that is going out onto the screen. */ proc(c) char c; { if( command == TRUE ) { do_comd(c); return; } else if( comd_pos > 0 ) { do_pos(c); comd_pos--; return; } if( Sysline == TRUE && c != (char) 27 ) { show_char(c); Scr_col++; if( Scr_col >= n_col ) Scr_col = n_col - 1; return; } /* * There are two distinct modes: ALPHA and Graphics, the latter * emulating a Tektronix 4010 mode. */ if( GRAPH == T_mode ) { tek(c); /* process as if this were a TEK 4010 */ return; } switch( c ) { case '\r': Scr_col = 0; break; case '\n': Scr_row++; if( Scr_row >= n_row ) Scroll(); break; case 7: Cconout( 7 ); break; case 8: Scr_col--; if( Scr_col < 0 ) Scr_col = 0; break; case '\t': Scr_col = 8 * ( Scr_col/8 + 1 ); if( Scr_col >= n_col ) { Scr_col = 0; Scr_row++; if( Scr_row >= n_row ) Scroll(); } break; case 27: command = TRUE; break; case GS: T_mode = GRAPH; T_draw = FALSE; T_count = 0; break; case US: T_mode = ALPHA; break; default: if( c > (char)31 ) { Screen[Scr_row][Scr_col] = c; show_char(c); Scr_col++; if( Scr_col >= n_col ) { Scr_col = 0; Scr_row++; if( Scr_row >= n_row ) Scroll(); } } break; } } /* * do_comd * * a terminal command. */ do_comd(c) char c; { switch(c) { case 'A': Scr_row = (Scr_row > 0) ? --Scr_row : 0; break; case 'B': Scr_row = (Scr_row < n_row-1) ? ++Scr_row : n_row-1; break; case 'C': if( Scr_col < n_col-1 ) { Scr_col++; } else { Scr_col = 0; Scr_row++; if( Scr_row >= n_row ) Scroll(); } break; case 'D': Scr_col = (Scr_col > 0) ? --Scr_col : 0; break; case FF: /* for TEK mode ... */ case 'E': Clear(); break; case 'H': Scr_col = Scr_row = 0; break; case 'J': EOP_Clear(); break; case 'K': EOL_Clear(); break; case 'L': Ins_Line(); break; case 'M': Del_Line(); break; case 'N': Sysl_On(); break; case 'O': Sysl_Off(); break; case 'Y': comd_pos = 2; break; case 'l': Ins_Char(); break; case 'm': Del_Char(); break; case 'p': vst_effects(Handle,2); break; case 'q': vst_effects(Handle,0); break; default: break; } command = FALSE; } do_pos(c) register char c; { if( comd_pos == 2 ) { Scr_row = (int) (c - ' '); if( Scr_row >= n_row ) Scr_row = n_row-1; } else { Scr_col = (int) (c - ' '); if( Scr_col >= n_col ) Scr_col = n_col-1; } } /* * Scroll * * Scroll in a new line (do this the dumb way for now). */ Scroll() { register int i, j; int x,y,w,h; register char *from, *to; int wr_mode, pxy[8], src[10], des[10]; from = &Screen[1][0]; to = &Screen[0][0]; for( i=1; i<N_ROW; i++, to++, from++ ) for( j=0; j<N_COL; j++ ) *to++ = *from++; Scr_row = n_row - 1; for( j=0; j<n_col; j++ ) Screen[Scr_row][j] = ' '; /* * Try using a raster operation to scroll... ha ha */ #ifdef SMOOTH for( j=0; j<CharH; j++ ) { Raster( 3, Ix, Iy+1, Ix, Iy, n_col*CharW, n_row*CharH - 1 ); } eraseWindow( Handle, Ix, Iy+(n_row-1)*CharH, n_col*CharW, CharH ); #else Raster( 3, Ix, Iy+CharH, Ix, Iy, n_col*CharW, (n_row-1)*CharH ); eraseWindow( Handle, Ix, Iy+(n_row-1)*CharH, n_col*CharW, CharH ); #endif } Clear() { Init_Scr(); eraseWindow( Handle, Ix, Iy, Iw, Ih-CharH ); } EOP_Clear() { register int i, j; EOL_Clear(); i = Scr_row++; j = Scr_col; Scr_col = 0; for( ; Scr_row < n_row; Scr_row++ ) EOL_Clear(); Scr_row = i; Scr_col = j; } EOL_Clear() { register int i; for( i=Scr_col; i<n_col; i++ ) Screen[Scr_row][i] = ' '; eraseWindow( Handle, Ix+Scr_col*CharW, Iy+Scr_row*CharH, (n_col-Scr_col)*CharW, CharH ); } Ins_Line() { register int i, j; register char *p, *q; for( i=n_row-1; i>Scr_row; i-- ) { p = &Screen[i][0]; q = &Screen[i-1][0]; for( j=0; j<N_COL; j++ ) *p++ = *q++; } /* * Try using a raster operation to scroll... ha ha */ Raster( 3, Ix, Iy+Scr_row*CharH, Ix, Iy+(Scr_row+1)*CharH, n_col*CharW, (n_row-Scr_row-1)*CharH ); Scr_col = 0; EOL_Clear(); } Del_Line() { register int i, j; register char *p, *q; for( i=Scr_row; i<n_row; i++ ) { p = &Screen[i][0]; q = &Screen[i+1][0]; for( j=0; j<N_COL; j++ ) *p++ = *q++; } /* * Try using a raster operation to scroll... ha ha */ Raster( 3, Ix, Iy+(Scr_row+1)*CharH, Ix, Iy+Scr_row*CharH, n_col*CharW, (n_row-Scr_row-1)*CharH ); Scr_col = 0; i = Scr_row; Scr_row = n_row - 1; EOL_Clear(); Scr_row = i; } Del_Char() { register int i, j; register char *p, *q; p = &Screen[Scr_row][Scr_col]; q = &Screen[Scr_row][Scr_col+1]; for( i=Scr_col; i<n_col-1; i++ ) *p++ = *q++; /* Shift chars over */ Raster( 3, Ix+(Scr_col+1)*CharW, Iy+Scr_row*CharH, Ix+Scr_col*CharW, Iy+Scr_row*CharH, (n_col-Scr_col-1)*CharW, CharH ); /* Clear last byte */ Raster( 0, Ix+(n_col-1)*CharW, Iy+Scr_row*CharH, Ix+(n_col-1)*CharW, Iy+Scr_row*CharH, CharW, CharH ); } Ins_Char() { register int i, j; register char *p, *q; p = &Screen[Scr_row][Scr_col+1]; q = &Screen[Scr_row][Scr_col]; for( i=n_col-1; i>Scr_col; i-- ) *p++ = *q++; Raster( 3, Ix+Scr_col*CharW, Iy+Scr_row*CharH, Ix+(Scr_col+1)*CharW, Iy+Scr_row*CharH, (n_col-Scr_col-1)*CharW, CharH ); /* Clear current byte */ Raster( 0, Ix+Scr_col*CharW, Iy+Scr_row*CharH, Ix+Scr_col*CharW, Iy+Scr_row*CharH, CharW, CharH ); } Sysl_On() { Sysline = TRUE; Sysl_row = Scr_row; Sysl_col = Scr_col; Scr_row = n_row; /* Sysline is on bottom row */ Scr_col = 0; Init_Sysl(); /* clear the storage associated with the sysline */ Clear_Sysl(); /* clear the actual line on the screen */ vst_effects(Handle,2); } Sysl_Off() { vst_effects(Handle,0); Scr_row = Sysl_row; Scr_col = Sysl_col; Sysline = FALSE; } Clear_Sysl() { Raster( 0, 0, 0, Ix, Iy+n_row*CharH, n_col*CharW, CharH ); } @//E*O*F screen.c// chmod u=rw,g=r,o=r screen.c echo x - tek.c sed 's/^@//' > "tek.c" <<'@//E*O*F tek.c//' /* * tek * * This routine will attempt to emulate a Tektronix 4010 storage scope * terminal... */ #include "wterm.h" #define FALSE 0 #define TRUE 1 int Ly, Lx, Hy, Hx; tek(c) char c; { register int y, x; if( GS == c ) { T_mode = GRAPH; T_draw = FALSE; T_count = 0; } else if( US == c ) { T_mode = ALPHA; } else { switch( (int) (c & 0x60) ) { case 0x20: /* high order Y or X */ if( T_count > 0 ) { /* high order X */ Hx = c & 0x1f; } else { /* high order Y */ Hy = (int) (c & 0x1f); } break; case 0x60: /* low order Y */ Ly = (int) (c & 0x1f); T_count = 1; /* X next */ break; case 0x40: /* low X */ Lx = (int) (c & 0x1f); x = Lx | (int) (Hx << 5); y = Ly | (int) (Hy << 5); plot(x,y,T_draw); T_count = 0; T_draw = TRUE; break; default: /* * this really should not happen but we all * know better... */ break; /* just ignore (lazy, I guess) */ } } } plot(x,y,draw) { int pxy[8]; x = x / 2; y = 399 - (y/2); if( y < 0 ) y = 0; pxy[2] = x; pxy[3] = y; /* * if draw is TRUE then we are joining the previous point to * the current one. Otherwise, we just plot a point. */ if( TRUE == draw ) { pxy[0] = T_x; pxy[1] = T_y; } else { pxy[0] = x; pxy[1] = y; } v_pline( Handle, 2, pxy ); T_x = x; T_y = y; } @//E*O*F tek.c// chmod u=rw,g=r,o=r tek.c echo x - window.c sed 's/^@//' > "window.c" <<'@//E*O*F window.c//' #include <obdefs.h> #include <gemdefs.h> #include <define.h> #include <osbind.h> #include "wterm.h" #ifdef WINDOW /* * Wopen * * Open up a window */ Wopen() { int ret; Window = wind_create(W_KIND, Ox, Oy, Ow, Oh); if( 0 >= Window) { Window = NO_WINDOW; return ; } ret = wind_set(Window, WF_NAME, WINDNAME); ret = wind_open(Window, Ox, Oy, Ow, Oh); } /* Wclose - * close calculator display window */ Wclose() { if (Window != NO_WINDOW) { wind_close(Window); wind_delete(Window); Window = NO_WINDOW; } } /* * Wproc * * Process a message from GEM or wait for a millisecond... */ int Last_Baud = -1; /* for check mark on baud rate */ int Wproc() { int event, msgbuf[8], ret, done=FALSE; do { /* * Turn on the mouse so that the user can do things. Then * allow him to use the menu, size the window, etc. */ event = evnt_multi( MU_TIMER | MU_MESAG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, msgbuf, 1, 0, &ret, &ret, &ret, &ret, &ret, &ret); if( event & MU_MESAG ) { switch (msgbuf[0]) { #ifdef ACC case AC_OPEN: /* for future usage */ if (msgbuf[4] == MenuId) { closeWindow(); do_calc(); show_calc(); } break; case AC_CLOSE: /* for future usage */ if (msgbuf[3] == MenuId) Window = NO_WINDOW; break; #endif case WM_CLOSED: if (msgbuf[3] == Window) { Wclose(); done=TRUE; } break; case WM_MOVED: if (msgbuf[3] == Window) { Ox = msgbuf[4]; Oy = msgbuf[5]; Ow = msgbuf[6]; Oh = msgbuf[7]; wind_set( Window, WF_CURRXYWH, Ox, Oy, Ow, Oh); wind_calc(1, W_KIND, Ox, Oy, Ow, Oh, &Ix, &Iy, &Iw, &Ih); clip( Handle, Ix, Iy, Iw, Ih ); } break; case WM_SIZED: if (msgbuf[3] == Window) { Ox = msgbuf[4]; Oy = msgbuf[5]; Ow = msgbuf[6]; Oh = msgbuf[7]; /* * What does this mean in terms of * the inside area? */ wind_calc(1, W_KIND, Ox, Oy, Ow, Oh, &Ix, &Iy, &Iw, &Ih); n_row = Ih / CharH - 1; n_col = Iw / CharW; /* * If these dimensions are not acceptable, * reset them to a bare minimum. */ if( n_row < MIN_ROW ) n_row = MIN_ROW; else if( n_row > N_ROW ) n_row = N_ROW; if( n_col < MIN_COL ) n_col = MIN_COL; else if( n_col > N_COL ) n_col = N_COL; Ih = (n_row+1) * CharH; Iw = n_col * CharW; /* * Recalculate outer dimensions and define * the new window. */ wind_calc( 0, W_KIND, Ix, Iy, Iw, Ih, &Ox, &Oy, &Ow, &Oh ); wind_set( Window, WF_CURRXYWH, Ox, Oy, Ow, Oh); Init_Scr(); Init_Sysl(); clip( Handle, Ix, Iy, Iw, Ih ); eraseWindow( Handle, Ix, Iy, Iw, Ih ); Cursor(); } break; case WM_NEWTOP: case WM_TOPPED: if (msgbuf[3] == Window) wind_set( Window, WF_TOP, 0, 0, 0, 0); break; case WM_REDRAW: if (msgbuf[3] == Window) { wshow(msgbuf[4], msgbuf[5], msgbuf[6], msgbuf[7]); } break; case MN_SELECTED: switch( msgbuf[4] ) { case FILEQUIT: done = TRUE; break; case OPTFULL: Half = FALSE; menu_icheck( gaddr, OPTFULL, TRUE ); menu_icheck( gaddr, OPTHALF, FALSE ); break; case OPTHALF: Half = TRUE; menu_icheck( gaddr, OPTFULL, FALSE ); menu_icheck( gaddr, OPTHALF, TRUE ); break; case OPT300: Rsconf( B300, -1, -1, -1, -1, -1 ); goto Baud_Check; case OPT1200: Rsconf( B1200, -1, -1, -1, -1, -1 ); goto Baud_Check; case OPT2400: Rsconf( B2400, -1, -1, -1, -1, -1 ); goto Baud_Check; case OPT4800: Rsconf( B4800, -1, -1, -1, -1, -1 ); goto Baud_Check; case OPT9600: Rsconf( B9600, -1, -1, -1, -1, -1 ); goto Baud_Check; Baud_Check: if( -1 != Last_Baud ) menu_icheck( gaddr, Last_Baud, FALSE ); Last_Baud = msgbuf[4]; menu_icheck( gaddr, msgbuf[4], TRUE ); break; case OPTNTERM: ptermcap( n_row, n_col ); break; } menu_tnormal( gaddr, msgbuf[3], TRUE ); } } } while( !( event & MU_TIMER ) ); return( done ); } #endif clip( handle, x, y, w, h) int x,y,w,h; int handle; { int pxy[4]; pxy[0] = x; pxy[1] = y; pxy[2] = x+w-1; pxy[3] = y+h-1; vs_clip( handle, 1, pxy ); } eraseWindow( handle, x, y, w, h) int x,y,w,h; int handle; { int pxy[4]; pxy[0] = x; pxy[1] = y; pxy[2] = x+w-1; pxy[3] = y+h-1; graf_mouse( M_OFF, 0L ); v_bar( handle, pxy ); graf_mouse( M_ON, 0L ); } /* wshow - * actual display of the whole window */ wshow(x,y,w,h) int x,y,w,h; { register int i, yy; #ifdef WINDOW int cl_x, cl_y, cl_w, cl_h; graf_mouse(M_OFF, 0L); /* get rid of mouse for now */ /* * Must only do stuff in the rectangle list. That means * we must clip... */ wind_update( BEG_UPDATE ); /* start updating the window */ wind_get( Window, WF_FIRSTXYWH, &cl_x, &cl_y, &cl_w, &cl_h ); while( 0 != cl_w && 0 != cl_h ) { /* * limit changes to current rectangle by clipping */ clip( Handle, cl_x, cl_y, cl_w, cl_h ); #endif /* * Write from top to bottom */ yy = Iy - Baseline-1 + CharH; for( i = 0; i<=n_row; i++ ) { v_gtext( Handle, Ix, yy, &Screen[i][0] ); yy += CharH; } #ifdef WINDOW /* * get next rectangle in the list */ wind_get( Window, WF_NEXTXYWH, &cl_x, &cl_y, &cl_w, &cl_h ); } wind_update( END_UPDATE ); /* ve iss done! */ graf_mouse(M_ON, 0L); /* put mouse back there */ #endif Cursor(); } /* * show_char * * Update screen by showing the latest character that has come in. */ show_char(c) char c; { int x, y, w, h; char s[2]; /* * stuff char into string */ s[0] = c; s[1] = EOS; v_gtext(Handle, Ix + Scr_col*CharW, Iy - Baseline - 1 + (Scr_row+1)*CharH, s); } /* * Cursor * * Either show or hide (toggle) cursor (steady block). */ Cursor() { int wr_mode, pxy[8], src[10], des[10]; /* * Use raster operation to Invert pixels at current * location */ Raster( 12, Ix + Scr_col*CharW, Iy + Scr_row*CharH, Ix + Scr_col*CharW, Iy + Scr_row*CharH, CharW, CharH ); } Raster(wr_mode, xfrom, yfrom, xto, yto, w, h ) { register int i; int pxy[8], src[10], des[10]; pxy[0] = xfrom; pxy[1] = yfrom; pxy[2] = xfrom+w-1; pxy[3] = yfrom+h-1; pxy[4] = xto; pxy[5] = yto; pxy[6] = xto+w-1; pxy[7] = yto+h-1; for( i=0; i<10; i++ ) { src[i] = 0; des[i] = 0; } /* graf_mouse( M_OFF, 0L );*/ vro_cpyfm( Handle, wr_mode, pxy, src, des ); /* graf_mouse( M_ON, 0L );*/ } /* * ptermcap * * print out a new termcap entry... */ char Termcap[] = "setenv TERMCAP 'xx|window|window-s:hs:\ ts=\\EN:fs=\\EO:co#77:li#20:nd=\\EC:am:bs:pt:xt:cd=\\EJ:\ ce=\\EK:cl=\\EE:do=\\EB:up=\\EA:cm=\\EY%+\\040%+\\040:\ dl=\\EM:al=\\EL:dc=\\Em:ic=\\El:im=:ei=:ku=\\EA:kl=\\ED:\ kd=\\EB:kr=\\EC:kh=\\EH:kb=^H:so=\\Ep:se=\\Eq:'\n"; #define ROWPOS (61) #define COLPOS (55) ptermcap( row, col ) int row, col; { register char *p; register int ret; putnum( row, &Termcap[ROWPOS] ); putnum( col, &Termcap[COLPOS] ); p = Termcap; while( *p != '\0' ) { do { ret = Cauxos(); } while( ret == 0 ); Cauxout( *p++ ); } } /* * putnum * * convert an int to a two digit number in the string passed */ char Digits[] = "0123456789"; putnum( x, s ) int x; char *s; { register int t; t = x/10; *s++ = Digits[t]; t = x - t*10; *s = Digits[t]; } @//E*O*F window.c// chmod u=rw,g=r,o=r window.c echo x - wterm.h sed 's/^@//' > "wterm.h" <<'@//E*O*F wterm.h//' /* * the first few lines come from RSC... */ #define TREE1 0 /* TREE */ #define TREE2 1 /* TREE */ #define DESK 3 /* OBJECT in TREE #0 */ #define DESKINFO 8 /* OBJECT in TREE #0 */ #define FILE 4 /* OBJECT in TREE #0 */ #define FILEQUIT 17 /* OBJECT in TREE #0 */ #define OPTIONS 5 /* OBJECT in TREE #0 */ #define OPTFULL 19 /* OBJECT in TREE #0 */ #define OPTHALF 21 /* OBJECT in TREE #0 */ #define OPT300 22 /* OBJECT in TREE #0 */ #define OPT1200 23 /* OBJECT in TREE #0 */ #define OPT2400 24 /* OBJECT in TREE #0 */ #define OPT4800 25 /* OBJECT in TREE #0 */ #define OPT9600 26 /* OBJECT in TREE #0 */ #define OPTNTERM 28 /* OBJECT in TREE #0 */ #define RSC_FILE "wterm.rsc" /* for resources... */ #define WINDOW 1 #define NO_WINDOW (-1) #define W_KIND (NAME | CLOSER | MOVER | SIZER) #define WINDNAME "WTerm-II" #define N_COL 80 /* num of char to be displayed in window */ #define N_ROW 25 /* how many numbers in stack to display in window */ #define MIN_COL 20 /* minimum number of columns */ #define MIN_ROW 4 /* something reasonable? */ #define CURSCNT 2 /* how long to wait between displays of cursor */ /* has to be done because of slowness of some */ /* of the VDI/AES calls... damn. */ /* * since the minimum amount of time one can ask for when doing an * EVENT_MULTI call (to allow GEM to get control once in a while) is * 1 millisecond, we should only do this very infrequently. GEMCOUNT * describes how many noneventful iterations of the main loop in * TERM should be done before handing GEM control. */ #define GEMCOUNT 1000 /* * The following several defines are used by Tek 4010 mode. */ #define GRAPH 1 #define ALPHA 0 #define GS 0x1d #define US 0x1f #define ESC 0x1b /* Terminal Command initiator */ #define CE 'K' /* Clear to end of line */ #define CL 'E' /* Clear whole screen */ #define CM 'Y' /* Postion cursor -- followed by two chars */ #define DO 'B' /* cursor down */ #define HO 'H' /* Home cursor */ #define LE 'D' /* cursor left */ #define ND 'C' /* cursor right */ #define UP 'A' /* cursor up */ #define SC 'j' /* Save Cursor location */ #define RC 'k' /* Restore Cursor */ #define SO 'p' /* StandOut mode */ #define SE 'q' /* StandEnd mode */ #define TS 0x0e /* Control-N --> to status line */ #define FS 0x0f /* Control-O --> from Status line */ #define FF 0x0c /* Form Feed for TEK 4010 mode */ #define UNDO 0x61 #define HELP 0x62 #define HOME 0x47 #define UARROW 0x48 #define LARROW 0x4b #define DARROW 0x50 #define RARROW 0x4d #define B300 9 #define B1200 7 #define B2400 4 #define B4800 2 #define B9600 1 #ifndef EXTERN extern int gl_apid; extern int Window; extern int Handle; extern int Ox, Oy, Ow, Oh; /* outer dimensions of window */ extern int Ix, Iy, Iw, Ih; /* inner size of window */ extern int n_col, n_row; /* number of rows and columns in window */ extern int max_col, max_row; /* maximum allowed by screen */ extern long gaddr; /* used by the resource files */ extern int Xdesk, Ydesk, Wdesk, Hdesk; extern int CharW, CharH; /* character cell width and height */ extern int Baseline; /* Bottom line relative to baseline */ extern char Screen[N_ROW+1][1+N_COL]; /* image of whole screen */ extern int Scr_col, Scr_row; extern int Sysl_row, Sysl_col, Sysline; extern int command, comd_pos; extern int Half; /* for half/full duplex */ extern int T_mode, T_count, T_draw; extern int T_x, T_y; extern int contrl[12]; extern int intin[128]; extern int ptsin[128]; extern int intout[128]; extern int ptsout[128]; #endif @//E*O*F wterm.h// chmod u=rw,g=r,o=r wterm.h echo x - wterm.inp sed 's/^@//' > "wterm.inp" <<'@//E*O*F wterm.inp//' [u] wterm.68k=a:apstart,debug.o,externs.o,main.o,screen.o,tek.o,window.o,a:osbind,a:vdibind,a:aesbind @//E*O*F wterm.inp// chmod u=rw,g=r,o=r wterm.inp exit 0 -- Eric S Fraga || esfraga@water.uucp Dept of Computer Science || esfraga@water.Waterloo.edu U of Waterloo || esfraga%water@waterloo.csnet