Article 6040 of alt.sources: Path: jac.zko.dec.com!nntpd.lkg.dec.com!pa.dec.com!decwrl!hookup!news.mathworks.com!gatech!news.sprintlink.net!cs.utexas.edu!not-for-mail From: nygren@ctr.nawcad.navy.mil Newsgroups: alt.sources Subject: Tscreen+Tstring shar file: C++ terminal control Date: 26 Jun 1995 15:01:12 -0500 Organization: UTexas Mail-to-News Gateway Lines: 1482 Sender: nobody@cs.utexas.edu Message-ID: <9506262003.AA00923@worf.ctr.nawcad.navy.mil> NNTP-Posting-Host: news.cs.utexas.edu Archive-name:Tscreen+Tstring (shell archive) Submitted-by:nygren@tecnet1.jcte.jcs.mil (Dan Nygren) ---- #!/bin/sh # This is a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # made 06/11/1995 18:03 UTC by jc6s@sunipc-1.unixlab.Virginia.EDU # Source directory /tmp_mnt/net/csissun13.ee.Virginia.EDU/dsk4.2/users/jc6s/dan # # existing files will NOT be overwritten unless -c is specified # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 670 -rw-rw-rw- README # 2496 -rw-rw-rw- ansi.cc # 1053 -rw-rw-rw- makansi # 269 -rw-rw-rw- makeunix # 1198 -rw-rw-rw- maktouch # 9624 -rw-rw-rw- touch_sc.cc # 11204 -rw-rw-rw- tscreen.cc # 3500 -rw-rw-rw- tscreen.hpp # 3739 -rw-rw-rw- tstring.cc # 3234 -rw-rw-rw- tstring.hpp # # ============= README ============== if test -f 'README' -a X"$1" != X"-c"; then echo 'x - skipping README (File already exists)' else echo 'x - extracting README (Text)' sed 's/^X//' << 'SHAR_EOF' > 'README' && These files are example programs for the article entitled "Controlling Terminals Sanely Using C++" in the July 1995 issue of "Embedded Systems Programming" magazine. X = terminals, string, screen, C++ X Manifest -------- tstring.cc, tstring.hpp - A minimal "terminal" string class tscreen.cc, tscreen.hpp - A terminal screen class touch_sc.cc - A demo program for a FPA570 touch screen ansi.cc - A demo program for an ANSI terminal X or a PC with the ANSI.SYS driver mak* - Makefiles for UNIX and Turbo C++ readme - This file X Dan Nygren 333 Carrsbrook Drive Charlottesville, VA 22901 nygren@tecnet1.jcte.jcs.mil nygren@ctr.nawcad.navy.mil X X SHAR_EOF chmod 0666 README || echo 'restore of README failed' Wc_c="`wc -c < 'README'`" test 670 -eq "$Wc_c" || echo 'README: original size 670, current size' "$Wc_c" fi # ============= ansi.cc ============== if test -f 'ansi.cc' -a X"$1" != X"-c"; then echo 'x - skipping ansi.cc (File already exists)' else echo 'x - extracting ansi.cc (Text)' sed 's/^X//' << 'SHAR_EOF' > 'ansi.cc' && //ANSI.CC - A demo that runs on a PC with ANSI.SYS in CONFIG.SYS file //or on other machines with an ANSI terminal attached X //"MSDOS" directive should be defined if compiling for a PC X //Copyright 1995 by Daniel C. Nygren //Current e-mail: nygren@tecnet1.jcte.jcs.mil X // Permission to use and modify this software for any purpose is // hereby granted without fee. Permission to copy and distribute this software // is also granted without fee, provided that the above copyright notice // and this entire permission notice appear in all copies, and any supporting // documentation. The author makes no representations about the suitability of // this software for any purpose. It is provided "as is" without express or // implied warranty. X //**** INCLUDES **** #include #include #include #include X //**** MS-DOS **** #ifdef MSDOS X #include X #include #else X #include //Needed instead on my UNIX system #endif //**** END MS-DOS **** X #include "tstring.hpp" #include "tscreen.hpp" X void main(void) { X //**** Function prototypes**** X X void set_up_screen(Tscreen &); X X //**** End Function Prototypes **** X X Tscreen PC_Screen; X #ifdef MSDOS X //Clear the PC's screen using MSDOS, not an ANSI control sequence X clrscr(); #endif X X //Print to the PC's screen using MSDOS, not an ANSI control sequence X printf("C++ Tscreen and Tstring class demo - PCs Needs ANSI.SYS\n"); X X sleep(3); X X set_up_screen(PC_Screen);//Call set_up_screen function X X PC_Screen.move(8,6).text("This text started at location x=8, y=6").show(); X X PC_Screen.move(20,20).blink().text("This is blinking text").normal().show(); X X PC_Screen.move(1,15).inverse().text("Inverse Video Text").normal().show(); X X PC_Screen.move(11,24).bold().text("Bold Text").normal().show(); X X sleep(5); } X /***************************************************************************/ /* set_up_screen /* /* This routine sets up the touch screen at the start of the program by /* performing the following functions: /* /* 1) Kick display into 8-bit mode (if EIGHT_BIT defined) /* 2) Clears and homes the screen /* /***************************************************************************/ void set_up_screen(Tscreen & RTouch_Screen) { X #ifdef EIGHT_BIT X RTouch_Screen.vt300_8bit().show();//Compile and execute this only if we have a 8 bit terminal X sleep(2);//Must delay while terminal is changing modes #endif X X RTouch_Screen.clear_screen().home().show();//Tidy everything up X } X SHAR_EOF chmod 0666 ansi.cc || echo 'restore of ansi.cc failed' Wc_c="`wc -c < 'ansi.cc'`" test 2496 -eq "$Wc_c" || echo 'ansi.cc: original size 2496, current size' "$Wc_c" fi # ============= makansi ============== if test -f 'makansi' -a X"$1" != X"-c"; then echo 'x - skipping makansi (File already exists)' else echo 'x - extracting makansi (Text)' sed 's/^X//' << 'SHAR_EOF' > 'makansi' && # Turbo C++ Makefile for ANSI.CC .AUTODEPEND X # *Translator Definitions* CC = tcc +ANSI.CFG -Pcc TASM = TASM TLIB = tlib TLINK = tlink LIBPATH = D:\TC\LIB;D:\TC\CAM\BORLANDC\LIB INCLUDEPATH = D:\TC\INCLUDE;D:\TC\CAM\INCLUDE DIRECTIVES = MSDOS X X # *Implicit Rules* .c.obj: X $(CC) -c {$< } X .cc.obj: X $(CC) -c {$< } X # *List Macros* X X EXE_dependencies = \ X ansi.obj \ X tscreen.obj \ X tstring.obj X # *Explicit Rules* ansi.exe: ansi.cfg $(EXE_dependencies) X $(TLINK) /v/x/c/L$(LIBPATH) @&&| c0s.obj+ ansi.obj+ tscreen.obj+ tstring.obj ansi X # no map file fp87.lib+ maths.lib+ cs.lib | X X # *Individual File Dependencies* ansi.obj: ansi.cfg ansi.cc X tscreen.obj: ansi.cfg tscreen.cc tstring.hpp X tstring.obj: ansi.cfg tstring.cc tstring.hpp X # *Compiler Configuration File* ansi.cfg: makefile X copy &&| -2 -f287 -v -vi- -w-ret -w-nci -w-inl -wpin -wamb -wamp -w-par -wasm -wcln -w-cpt -wdef -w-dup -w-pia -wsig -wnod -w-ill -w-sus -wstv -wucp -wuse -w-ext -w-ias -w-ibc -w-pre -w-nst -I$(INCLUDEPATH) -L$(LIBPATH) -D$(DIRECTIVES) | ansi.cfg X X X SHAR_EOF chmod 0666 makansi || echo 'restore of makansi failed' Wc_c="`wc -c < 'makansi'`" test 1053 -eq "$Wc_c" || echo 'makansi: original size 1053, current size' "$Wc_c" fi # ============= makeunix ============== if test -f 'makeunix' -a X"$1" != X"-c"; then echo 'x - skipping makeunix (File already exists)' else echo 'x - extracting makeunix (Text)' sed 's/^X//' << 'SHAR_EOF' > 'makeunix' && # Makefile for ansi.cc on a UNIX systen X ansi : ansi.o X CC +w -o ansi ansi.o tscreen.o tstring.o X ansi.o : ansi.cc tscreen.o X CC +w -c ansi.cc X tscreen.o : tscreen.cc tscreen.hpp tstring.o X CC +w -c tscreen.cc X tstring.o : tstring.cc tstring.hpp X CC +w -c tstring.cc X SHAR_EOF chmod 0666 makeunix || echo 'restore of makeunix failed' Wc_c="`wc -c < 'makeunix'`" test 269 -eq "$Wc_c" || echo 'makeunix: original size 269, current size' "$Wc_c" fi # ============= maktouch ============== if test -f 'maktouch' -a X"$1" != X"-c"; then echo 'x - skipping maktouch (File already exists)' else echo 'x - extracting maktouch (Text)' sed 's/^X//' << 'SHAR_EOF' > 'maktouch' && # Turbo C++ Makefile for TOUCH_SC.CC .AUTODEPEND X # *Translator Definitions* CC = tcc +TOUCH_SC.CFG -Pcc TASM = TASM TLIB = tlib TLINK = tlink LIBPATH = D:\TC\LIB;D:\TC\CAM\BORLANDC\LIB INCLUDEPATH = D:\TC\INCLUDE;D:\TC\CAM\INCLUDE DIRECTIVES = MSDOS;EIGHT_BIT;BLAISE X # *Implicit Rules* .c.obj: X $(CC) -c {$< } X .cc.obj: X $(CC) -c {$< } X # *List Macros* X X EXE_dependencies = \ X touch_sc.obj \ X tscreen.obj \ X tstring.obj \ X {$(LIBPATH)}cambors.lib X # *Explicit Rules* touch_sc.exe: touch_sc.cfg $(EXE_dependencies) X $(TLINK) /v/x/c/L$(LIBPATH) @&&| c0s.obj+ touch_sc.obj+ tscreen.obj+ tstring.obj touch_sc X # no map file cambors.lib+ fp87.lib+ maths.lib+ cs.lib | X X # *Individual File Dependencies* touch_sc.obj: touch_sc.cfg touch_sc.cc tstring.hpp tscreen.hpp X tscreen.obj: touch_sc.cfg tscreen.cc tscreen.hpp tstring.hpp X tstring.obj: touch_sc.cfg tstring.cc tstring.hpp X # *Compiler Configuration File* touch_sc.cfg: makefile X copy &&| -2 -f287 -v -vi- -w-ret -w-nci -w-inl -wpin -wamb -wamp -w-par -wasm -wcln -w-cpt -wdef -w-dup -w-pia -wsig -wnod -w-ill -w-sus -wstv -wucp -wuse -w-ext -w-ias -w-ibc -w-pre -w-nst -I$(INCLUDEPATH) -L$(LIBPATH) -D$(DIRECTIVES) | touch_sc.cfg X X X SHAR_EOF chmod 0666 maktouch || echo 'restore of maktouch failed' Wc_c="`wc -c < 'maktouch'`" test 1198 -eq "$Wc_c" || echo 'maktouch: original size 1198, current size' "$Wc_c" fi # ============= touch_sc.cc ============== if test -f 'touch_sc.cc' -a X"$1" != X"-c"; then echo 'x - skipping touch_sc.cc (File already exists)' else echo 'x - extracting touch_sc.cc (Text)' sed 's/^X//' << 'SHAR_EOF' > 'touch_sc.cc' && //TOUCH_SC.CC - Demo program to control a FPA570 touch screen X //Copyright 1995 by Daniel C. Nygren //Current e-mail: nygren@tecnet1.jcte.jcs.mil X // Permission to use and modify this software for any purpose is // hereby granted without fee. Permission to copy and distribute this software // is also granted without fee, provided that the above copyright notice // and this entire permission notice appear in all copies, and any supporting // documentation. The author makes no representations about the suitability of // this software for any purpose. It is provided "as is" without express or // implied warranty. X //**** DEFINES **** //This part should be in a makefile (i.e -DMSDOS;EIGHT_BIT //#define MSDOS //Define this if using Blaise Computing's C Async Manager //#define EIGHT_BIT //Define this if terminal can support 8 bit control chars X X //Use "const int" instead of "define" in C++ because symbol //is then available to a symbolic debugger //(i.e not "#define BUF_SIZE 64" but "const int BUF_SIZE=64") const int BUF_SIZE=1024; const int ON=0; //Used to activate touch points const int OFF=1;//Used to deactivate touch points const int IS_MACRO=1;//Used by load_touch_point() to determine if touch point const int NOT_MACRO=0;//is to be part of a macro or not X //**** INCLUDES **** #include #include #include #include X //**** MS-DOS **** X #ifdef MSDOS X X #include X #include X #include X #endif //From C Asynch Manager p.54, Used as param for functions that set //and return transmission options. This struct is in one of the //include files, it is presented here for reference //typedef struct //{ // int baud_rate; // int parity; // int data_bits; // int stop_bits; // int remote_flow_ctrl; // int local_flow_ctrl; // int bit_trimming; // int bit_forcing; // int require_cts; // int break_time; //} POPT; X //**** END MS-DOS **** X #include "tstring.hpp" #include "tscreen.hpp" X int main(void) { X //**** Function prototypes**** X X void set_up_touch_screen(Tscreen &); X void set_up_macro1(void); X void set_up_macro2(void); X X //**** End Function Prototypes **** X X Tscreen Touch_Screen; X X int error; X X POPT com2set; X X clrscr();//Clear the PC's screen X X printf(" EMERALD FPS570 TOUCH SCREEN TESTER - VERSION 1.0\n"); X X if(error=(open_a2(COM2,BUF_SIZE,BUF_SIZE,0,0)))//Open COM2 with BUF_SIZE byte input and output buffers X { X printf("Error opening COM1, error code=%d\n",error);//If open_a2 returns a non zero number, trouble X exit(1);//Exit and tell DOS something's wrong X } X X if(error=(retop_a2(COM2,&com2set)))//Open COM2 with a BUF_SIZE byte input buffer X { X printf("Error reading COM2 settings, error code=%d\n",error);//If open_a2 returns a non zero number, trouble X exit(1);//Exit and tell DOS something's wrong X } X X com2set.baud_rate=9600; X com2set.parity=0; //0=no parity X com2set.data_bits=8; X com2set.stop_bits=1; X com2set.remote_flow_ctrl=0; X com2set.local_flow_ctrl=0; X com2set.bit_trimming=0; X com2set.bit_forcing=0; X com2set.require_cts=0; X com2set.break_time=50; X X X if(error=(setop_a2(COM2,&com2set)))//Set COM2 to 96008N1 X { X printf("Error setting up COM2, error code=%d\n",error);//If setop_a2 returns a non-zero number, trouble X exit(1);//Exit and tell DOS something's wrong X } X X X // if(error=(rdtrm_a2(COM2,5,START,in_buf,FOREVER,0,term_char,num_read,dummy2,port_status2)))//Read in the next 5 bytes X // { X // printf("Error reading message, error code=%d\n",error);//If a non-zero error code is returned, trouble X // } X // error=0;//Clear error flag X X set_up_touch_screen(Touch_Screen); X X set_up_macro1(); X X set_up_macro2(); X X Touch_Screen.macro_execute(1).show(); X X Touch_Screen.cursor_off().show(); X X sleep(15); X X Touch_Screen.ctrl_touch_group(1,OFF);//Turn macro #1's buttons off X X Touch_Screen.macro_execute(2).show(); X X Touch_Screen.cursor_off().show(); X X sleep(2); X X close_a2(COM2);//Close COM port to keep everything tidy X X return(0);//Tell MSDOS everything is OK X } X /***************************************************************************/ /* set_up_touch_screen /* /* This routine sets up the touch screen at the start of the program by /* performing the following functions: /* /* 1) Reset /* 2) Kick dispaly into 8-bit mode /* 3) Set up touch point terminal modes /* 4) Clears all macros /* 5) Clears and homes the screen /* /***************************************************************************/ void set_up_touch_screen(Tscreen & RTouch_Screen) { X X RTouch_Screen.reset().show(); X sleep(2);//Must delay while terminal is resetting X #ifdef EIGHT_BIT X X RTouch_Screen.vt320_8bit().show();//Compile and execute this only if we have a 8 bit terminal X sleep(2);//Must delay while terminal is changing modes X #endif X X RTouch_Screen.move(4,6).double_high_n_wide("Use only one finger to hit screen!").cursor_off().show(); X X sleep(5); X X RTouch_Screen.text("\x1b[=2;3;7;8h").show(); //Set touch point terminal modes X // 2 - Allow touch reporting X // 3 - Report touch upon exit X // 7 - Outline touch point when valid touch X // 8 - Flash touch point when valid touch X RTouch_Screen.text("\x1b[=5;6;10l").show(); // 5 - Load an inactive status X // 6 - No click when valid X // 10 - Ignore errors X X RTouch_Screen.clear_screen().clear_macros().home().show();//Tidy everything up } X /***************************************************************************/ /* MACROS /* /* Always start a macro with a clear screen to get rid of previous legends /* immediately followed by an absolute movement command (i.e. move(x,y) or /* home() etc.) because you don't know where the cursor is currently located /* at. In the same manner, the macro should end with a home() command, because /* the Tscreen object has no way of knowing the last position of the cursor /* when the macro is executed. Of course the macro_execute(int) command should /* also place the row and column of the cursor as if it were homed. /* /***************************************************************************/ X /***************************************************************************/ /* set_up_macro1 /* /* This function sets up a macro to generate a basic nine button screen /* /***************************************************************************/ void set_up_macro1(void) { X X Tscreen MTouch_Screen; X X const int NUMBER_OF_LEGENDS=10; X X int button, x=104, y=66, group=1, buttons_per_line=3; X X char button_string[4];//Need to convert button # to a string X //Must have enough room to hold 3 digit numbers X //so char x[4] three digits plus '\0' X X X char * title[NUMBER_OF_LEGENDS]={ X "Main Menu", //top of screen legend X "\b\b\bButton 1", X "\b\b\bButton 2", X "\b\b\bButton 3", X "\b\b\bButton 4", //cursor is placed at center of button X "\b\b\bButton 5", //so backspace '\b' is used to center X "\b\b\bButton 6", //entire button title X "\b\b\bButton 7", X "\b\b\bButton 8", X "\b\b\bButton 9" X }; X X X //Put legend up at top of screen X MTouch_Screen.clear_screen().move(16,1).wide().text(title[0]); X X //Draw nine buttons X for(button=1; button<=(NUMBER_OF_LEGENDS-1); ++button) X { X itoa(button,button_string,10);//Need to convert button to a string X //Must have enough room to hold 3 digit numbers X //so char button[4] three digits plus '\0' X X X MTouch_Screen.move_pixel(x,y).text(title[button]).load_touch_point_size(button,x,y,150,100,group,"",button_string,IS_MACRO).ctrl_touch_point(button,ON); X X x=x+208;//Move horizontally to next button X X if(!(button%buttons_per_line)) X { X //Everytime we have a remainder of zero, 3 buttons X //have been drawn, so start on next line X x=104; X y=y+132; X } X X } X X MTouch_Screen.home().macroize(1).show();//Turn command string into a macro X //Last command must be a home(); X } X /***************************************************************************/ /* set_up_macro2 /* /* This function sets up a macro to generate a calculator touch pad /* /***************************************************************************/ void set_up_macro2(void) { X X Tscreen MTouch_Screen; X X const int NUMBER_OF_LEGENDS=21; X X int button, x=52, y=33, group=2, buttons_per_line=3; X X char button_string[4];//Need to convert button # to a string X //Must have enough room to hold 3 digit numbers X //so char x[4] three digits plus '\0' X X X char * title[NUMBER_OF_LEGENDS]={ X "Calculator", //top of screen legend X "D", X "E", X "F", X "A", //cursor is placed at center of button X "B", //so backspace '\b' is used to center X "C", //entire button title X "7", X "8", X "9", X "4", X "5", X "6", X "1", X "2", X "3", X "-", X "0", X ".", X "CLR", X "\bENTER" X }; X X X //Put legend up at top of screen X MTouch_Screen.clear_screen().move(26,1).wide().text(title[0]); X X //Draw buttons X for(button=1; button<=(NUMBER_OF_LEGENDS-1); ++button) X { X itoa(button,button_string,10);//Need to convert button to a string X //Must have enough room to hold 3 digit numbers X //so char button[4] three digits plus '\0' X X X MTouch_Screen.move_pixel(x,y).text(title[button]).load_touch_point_size(button,x,y,90,60,group,"",button_string,IS_MACRO).ctrl_touch_point(button,ON); X X x=x+104;//Move horizontally to next button X X if(button>12)//After the first four lines of 3 buttons per line, make it four buttons per line X buttons_per_line=4; X X if(!(button%buttons_per_line)) X { X //Everytime we have a remainder of zero, 3 buttons X //have been drawn, so start on next line X x=52; X y=y+66; X } X X } X X MTouch_Screen.home().macroize(2).show();//Turn command string into a macro X //Last command must be a home(); X } X SHAR_EOF chmod 0666 touch_sc.cc || echo 'restore of touch_sc.cc failed' Wc_c="`wc -c < 'touch_sc.cc'`" test 9624 -eq "$Wc_c" || echo 'touch_sc.cc: original size 9624, current size' "$Wc_c" fi # ============= tscreen.cc ============== if test -f 'tscreen.cc' -a X"$1" != X"-c"; then echo 'x - skipping tscreen.cc (File already exists)' else echo 'x - extracting tscreen.cc (Text)' sed 's/^X//' << 'SHAR_EOF' > 'tscreen.cc' && //tscreen.cc, Terminal Screen member functions X // Some of this file is specific to a FPA570 touch screen, but it should not // be too hard to adapt it to the terminal of your choice. X //Copyright 1995 by Daniel C. Nygren //Current e-mail: nygren@tecnet1.jcte.jcs.mil X // Permission to use and modify this software for any purpose is // hereby granted without fee. Permission to copy and distribute this software // is also granted without fee, provided that the above copyright notice // and this entire permission notice appear in all copies, and any supporting // documentation. The author makes no representations about the suitability of // this software for any purpose. It is provided "as is" without express or // implied warranty. X #include "tscreen.hpp" X // String constants (NOT String classes!) placed next to each other automatically // concatenate, so things like ESC"[=C" and CSI"2J" are legal since ESC and CSI // have been defined as strings. (i.e. "a" "b" is same as "ab" in ANSI C and C++) X /****************************************************************************/ // // reset() Causes the display to perform a power on reset // /****************************************************************************/ Tscreen& Tscreen::reset(void) { X Cmd=Cmd+ESC"c"; X return *this; } X /*%%%%%%%%%%%%%%%%%%%%%%%%%%% Setting Operating Level %%%%%%%%%%%%%%%%%%%%%%*/ X // When selecting an operating level for a terminal, (i.e. setting it to // VT52, VT100, VT200, VT300 or VT400 modes), use the 7-bit representations // of the control characters because the terminal may initially be in the // 7-bit mode and not will recognize 8-bit control characters. X /****************************************************************************/ // // vt100_7bit() Set operating level of terminal to 7-bit VT100 mode // /****************************************************************************/ Tscreen& Tscreen::vt100_7bit(void) { X Cmd=Cmd+"\x1B[61\"p";//Must explicitly use 7-bit CSI character sequence X return *this; //because display may be in 7-bit mode } X /****************************************************************************/ // // vt320_8bit() Set operating level of terminal to 8-bit VT320 mode // /****************************************************************************/ Tscreen& Tscreen::vt320_8bit(void) { X Cmd=Cmd+"\x1B[62\"p"; //Must explicitly use 7-bit CSI character sequence X return *this; //because display may be in 7-bit mode } X /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ X /****************************************************************************/ // // clear_macros() Clears macros and touch points // /****************************************************************************/ Tscreen& Tscreen::clear_macros(void) { X Cmd=Cmd+ESC"[=C"; X return *this; } X Tscreen& Tscreen::clear_screen(void) { X Cmd=Cmd+CSI"2J"; X return *this; } X Tscreen& Tscreen::cursor_on(void) { X Cmd=Cmd+CSI"?25h"; X return *this; } X Tscreen& Tscreen::cursor_off(void) { X Cmd=Cmd+CSI"?25l"; X return *this; } X Tscreen& Tscreen::home(void) { X Cmd=Cmd+CSI"H"; X return *this; } X /*%%%%%%%%%%%%%%%%%%%%%%%%%%% Video Attributes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ X /****************************************************************************/ // // Set Video Attributes: // // The following commands apply the specfied video attributes to each // character following the command. The attributes are cumulative and // stay in effect until turned off. // /****************************************************************************/ X Tscreen& Tscreen::normal(void) { X Cmd=Cmd+CSI"m"; X return *this; } X Tscreen& Tscreen::bold(void) { X Cmd=Cmd+CSI"1m"; X return *this; } X Tscreen& Tscreen::underline(void) { X Cmd=Cmd+CSI"4m"; X return *this; } X Tscreen& Tscreen::blink(void) { X Cmd=Cmd+CSI"5m"; X return *this; } X Tscreen& Tscreen::inverse(void) { X Cmd=Cmd+CSI"7m"; X return *this; } /*%%%%%%%%%%%%%%%%%%%%%%%%%%% End Video Attributes %%%%%%%%%%%%%%%%%%%%%%%%%*/ X X /****************************************************************************/ // // wide() Makes the current line of text double wide, single high, // until changed // /****************************************************************************/ Tscreen& Tscreen::wide(void) { X Cmd=Cmd+ESC"#6"; X return *this; } X /****************************************************************************/ // // double_high_n_wide( string to be displayed on the screen) // // Makes the only text argument double wide, double high // // !!! Make sure all the text fits on one line !!! // /****************************************************************************/ Tscreen& Tscreen::double_high_n_wide(const char *p) { X int p_len=strlen(p); //Find out how long the current argument is X //We need to know this so we can print double X //height and width characters. In order to X //print double high and wide, basically we must X //print the top half double wide and high, move X //back the number of charaters there is in the X //string, move down one character, then print X //lower half double high and wide, then finish X //moving back up one character. X X Cmd=Cmd+ESC"#3"+p+CSI+p_len+"D"+CSI+"B"+ESC"#4"+p+CSI+"A"; X X return *this; } X X /****************************************************************************/ // // move( x distance in chars, y distance chars ) // /****************************************************************************/ Tscreen& Tscreen::move(short x, short y) { X Cmd=Cmd+CSI+y+";"+x+"H"; X return *this; } X /****************************************************************************/ // // move_pixel( x distance in pixels, y distance in pixels ) // // move_pixel just converts pixels position to character position // by the following formula: // // 640 x 400 pixels/screen, 80 x 24 chars/screen // 640/80 = 8 pixels/char horizontal (x) // 400/24 = 16.667 pixels/char vertical (y) // /****************************************************************************/ Tscreen& Tscreen::move_pixel(short x, short y) { X return this->move( short(x/8), short(y/16.667) ); } X /****************************************************************************/ // // text( string to be displayed on screen ) // /****************************************************************************/ Tscreen& Tscreen::text(const char *p) { X Cmd=Cmd+p; X return *this; } X Tscreen& Tscreen::pixel(short x, short y) { X Cmd=Cmd+ESC"^"+y+";"+x+"A"; X return *this; } X Tscreen& Tscreen::pixel_erase(short x, short y) { X Cmd=Cmd+ESC"^"+y+";"+x+"B"; X return *this; } X Tscreen& Tscreen::line(short x1, short y1, short x2, short y2) { X Cmd=Cmd+ESC"^"+y1+";"+x1+";"+y2+";"+x2+"I"; X return *this; } X Tscreen& Tscreen::line_erase(short x1, short y1, short x2, short y2) { X Cmd=Cmd+ESC"^"+y1+";"+x1+";"+y2+";"+x2+"J"; X return *this; } X Tscreen& Tscreen::rectangle(short x1, short y1, short x2, short y2) { X Cmd=Cmd+ESC"^"+y1+";"+x1+";"+y2+";"+x2+"M"; X return *this; } X Tscreen& Tscreen::rectangle_size(short cx, short cy, short sx, short sy) { X return this->rectangle((cx+sx/2), (cy+sy/2), (cx-sx/2), (cy-sy/2)); } X /* Tscreen& Tscreen::rectangle_size(short cx, short cy, short sx, short sy) { X return this->rectangle( (cx*8+(sx*8)/2), (cy*16.667+(sy*16.667)/2), (cx*8-(sx*8)/2), (cy*16.667-(sy*16.667)/2)); } */ X Tscreen& Tscreen::rectangle_erase(short x1, short y1, short x2, short y2) { X Cmd=Cmd+ESC"^"+y1+";"+x1+";"+y2+";"+x2+"N"; X return *this; } X Tscreen& Tscreen::rectangle_erase_size(short cx, short cy, short sx, short sy) { X return this->rectangle_erase((cx+sx/2), (cy+sy/2), (cx-sx/2), (cy-sy/2)); } X /****************************************************************************/ // // load_touch_point(touch point # (1-127), x1, y1, x2, y2, // touch group # (0-99), string displayed on screen, // string that is sent back on the RS-232 port, // is_macro=0 if touch point not a macro, =1 if it is) // // load_touch_point automatically draws a rectangle the same dimensions // as the touch point // /****************************************************************************/ Tscreen& Tscreen::load_touch_point(short num, short x1, short y1, short x2, short y2, short gr, char * scr_str, char * com_str, short is_macro) { X if(is_macro)//If touch point is to be part of a macro X Cmd=Cmd+ESC+"P"+num+";"+y1+";"+x1+";"+y2+";"+x2+";"+gr+"T"+scr_str+ESC+"X"+"\""+com_str+"\""+"\x7F";//End with 0x7F if its to be a macro X else X Cmd=Cmd+ESC+"P"+num+";"+y1+";"+x1+";"+y2+";"+x2+";"+gr+"T"+scr_str+ESC+"X"+"\""+com_str+"\""+ESC"\\";// else end with a ESC\ X X return *this; X } X /****************************************************************************/ // // load_touch_point_size( touch point # (1-127), center x, center y, // size x, size y, touch group # (0-99), // string displayed on screen, string that is // sent back on the RS-232 port, is_macro ) // /****************************************************************************/ /*Tscreen& Tscreen::load_touch_point_size(short num, short cx, short cy, short sx, short sy, short gr, char * scr_str, char * com_str, short is_macro) { X return this->load_touch_point(num, (cx*8+(sx*8)/2), (cy*16.667+(sy*16.667)/2), (cx*8-(sx*8)/2), (cy*16.667-(sy*16.667)/2), gr, scr_str, com_str, is_macro); } */ Tscreen& Tscreen::load_touch_point_size(short num, short cx, short cy, short sx, short sy, short gr, char * scr_str, char * com_str, short is_macro) { X return this->load_touch_point(num, (cx-sx/2), (cy-sy/2), (cx+sx/2), (cy+sy/2), gr, scr_str, com_str, is_macro); } X X Tscreen& Tscreen::ctrl_touch_point(short num, short param) { X Cmd=Cmd+CSI"="+num+";"+param+"p"; X return *this; } X Tscreen& Tscreen::ctrl_touch_group(short gr, short param) { X Cmd=Cmd+CSI"="+gr+";"+param+"g"; X return *this; } X /****************************************************************************/ // // macroize( macro # (1-127) ) // // Turn the current Tscreen command string into a macro // /****************************************************************************/ Tscreen& Tscreen::macroize(short macro_num) { X Tstring Header;//A null String object used so "String operator + (String &, String &)" will work X Cmd=Header+ESC"P"+macro_num+"M"+Cmd+ESC"\\";//command strings that end with ESC\ won't work! X X return *this;//spit out the macro } X /****************************************************************************/ // // macro_execute( macro # (1-127) ) // // Execute a predefined macro // /****************************************************************************/ Tscreen& Tscreen::macro_execute(short macro_num) { X Cmd=Cmd+CSI"="+macro_num+"M"; X X //put here the command to place cursor position at (1,1) X X return *this; } X void Tscreen::show(void) { X #ifdef BLAISE //MSDOS specific routine from Blaise Computing's "C Async Manager" library //Basically it spits bytes out the COM2 port. I used this because I thought //Turbo C++'s bios.h com port routines were too slow. X X int error, num_written; X X if(error=(wrtst_a1(COM2,Cmd.length(),Cmd.string(),&num_written))) X { X printf("Error writting characters, error code=%d\n",error); X } X #else X puts(Cmd.string()); #endif X X Cmd="";//clear out commands for next time X } X SHAR_EOF chmod 0666 tscreen.cc || echo 'restore of tscreen.cc failed' Wc_c="`wc -c < 'tscreen.cc'`" test 11204 -eq "$Wc_c" || echo 'tscreen.cc: original size 11204, current size' "$Wc_c" fi # ============= tscreen.hpp ============== if test -f 'tscreen.hpp' -a X"$1" != X"-c"; then echo 'x - skipping tscreen.hpp (File already exists)' else echo 'x - extracting tscreen.hpp (Text)' sed 's/^X//' << 'SHAR_EOF' > 'tscreen.hpp' && //tscreen.hpp, Terminal Screen Class Definition X //Copyright 1995 by Daniel C. Nygren //Current e-mail: nygren@tecnet1.jcte.jcs.mil X // Permission to use and modify this software for any purpose is // hereby granted without fee. Permission to copy and distribute this software // is also granted without fee, provided that the above copyright notice // and this entire permission notice appear in all copies, and any supporting // documentation. The author makes no representations about the suitability of // this software for any purpose. It is provided "as is" without express or // implied warranty. X #ifndef tscreen_hpp //If we haven't been in this file before, compile it #define tscreen_hpp //Define the token so we don't compile this again X X //**** DEFINES **** #define ESC "\x1B" X #ifdef EIGHT_BIT //Adjacent string literals are concatenated in ANSI C //and C++, so we can use the following expansions X #define CSI "\x9B" //8 bit Control Sequence Introducer (Saves sending a byte when used) X #define DSC "\x90" //8 bit Device Control String (Saves sending a byte when used) X #define ST "\x9C" //8 bit String Terminator (Saves sending a byte when used) #else //One can express any 8-bit C1 control character as two 7-bit charaters by the following formula //8-bit control character = ESC + (8-bit control character - \x40 ) X #define CSI "\x1B[" //7 bit Control Sequence Introducer (i.e "ESC[" ) X #define DSC "\x1BP" //7 bit Device Control String (i.e "ESCP" ) X #define ST "\x1B\" //7 bit String Terminator (i.e "ESC\" ) #endif X //**** INCLUDES **** #include #include #include #include #include //**** MS-DOS **** #ifdef MSDOS X #include #endif //**** END MS-DOS X #include "tstring.hpp" X class Tscreen { X X public: X // Constructors and Destructor X Tscreen(){cols=80; rows=40; pixel_cols=640; pixel_rows=400;} X ~Tscreen() {} X X /*****************************************************/ X /* Member fuctions are fully commented in tscreen.cpp */ X /*****************************************************/ X X /**** Member Functions ****/ X Tscreen& reset(void); X Tscreen& vt100_7bit(void);//Kick screen into VT100 7-bit mode X Tscreen& vt320_8bit(void);//Kick screen into VT320 8-bit mode X Tscreen& clear_screen(void); X Tscreen& clear_macros(void); X Tscreen& cursor_on(void); X Tscreen& cursor_off(void); X Tscreen& home(void); X Tscreen& normal(void); X Tscreen& bold(void); X Tscreen& underline(void); X Tscreen& blink(void); X Tscreen& inverse(void); X Tscreen& move(short,short); X Tscreen& move_pixel(short,short); X Tscreen& text(const char *); X Tscreen& wide(void); X Tscreen& double_high_n_wide(const char *); X Tscreen& pixel(short,short); X Tscreen& pixel_erase(short,short); X Tscreen& line(short,short, short,short); X Tscreen& line_erase(short,short, short,short); X Tscreen& rectangle(short,short, short,short); X Tscreen& rectangle_size(short,short, short,short); X Tscreen& rectangle_erase(short,short, short,short); X Tscreen& rectangle_erase_size(short,short, short,short); X Tscreen& load_touch_point(short, short,short, short,short, short, char *, char *, short); X Tscreen& load_touch_point_size(short, short,short, short,short, short, char *, char *, short); X Tscreen& ctrl_touch_point(short,short); X Tscreen& ctrl_touch_group(short,short); X Tscreen& macro_execute(short); X Tscreen& macroize(short); X void show(void); X X private: X X short rows, cols, pixel_rows, pixel_cols; X X Tstring Cmd; }; X #endif X SHAR_EOF chmod 0666 tscreen.hpp || echo 'restore of tscreen.hpp failed' Wc_c="`wc -c < 'tscreen.hpp'`" test 3500 -eq "$Wc_c" || echo 'tscreen.hpp: original size 3500, current size' "$Wc_c" fi # ============= tstring.cc ============== if test -f 'tstring.cc' -a X"$1" != X"-c"; then echo 'x - skipping tstring.cc (File already exists)' else echo 'x - extracting tstring.cc (Text)' sed 's/^X//' << 'SHAR_EOF' > 'tstring.cc' && //tstring.cc, Terminal String Class Member Functions X //Copyright 1995 by Daniel C. Nygren //Current e-mail: nygren@tecnet1.jcte.jcs.mil X // Permission to use and modify this software for any purpose is // hereby granted without fee. Permission to copy and distribute this software // is also granted without fee, provided that the above copyright notice // and this entire permission notice appear in all copies, and any supporting // documentation. The author makes no representations about the suitability of // this software for any purpose. It is provided "as is" without express or // implied warranty. X #include "tstring.hpp" X /***************************************************************/ /* Tstring Constructors */ /***************************************************************/ Tstring :: Tstring() { X str = new char[1]; //Create a null string X assert(str != NULL); //Abort if new fails X str[0]='\0'; //A null char must be at end X len = 0; //Length of a null string is zero } X Tstring :: Tstring(const char *s) { X len = strlen(s); //len = the length of the string X str = new char[len+1]; //Leave room for null char at end of string X assert(str != NULL); //Abort if new fails X strcpy(str,s); //Copy string s into string str } X Tstring :: Tstring(const Tstring& S) { X len = S.len; //Memberwise Initialization X str = new char[len+1]; //Get enough memory for string and null char X assert(str != NULL); //Abort if new fails X strcpy(str,S.str); //Copy string S.str into string str } X Tstring :: Tstring(const long l) { X char l_string[MAX_LDIGITS+2]; X //Need to convert l to a string, l_string X //must have enough room to hold max return X //value from an "ltoa" function. X //So char l_string[] is MAX_LDIGITS plus 2 for X // "-" sign and terminating '\0'. X X sprintf(l_string,"%ld",l); X //Not all compilers have a long to ASCII X //function (Example: ltoa(l,l_string,10);) X X len = strlen(l_string); //length field = length of l_string X str = new char[len+1]; //Leave room for null char at end of string X assert(str != NULL); //Abort if new fails X strcpy(str,l_string); //Copy string l_string into string str } X /***************************************************************/ /* Assignment Operator */ /***************************************************************/ Tstring& Tstring::operator=(const Tstring& S) { X if (this == &S) //Take care of case where Tstring is X { //assigned to itself (e.g. Ts1=Ts1;) X return *this; //If they are the same, return the original X } X else X { X len = S.len; //The new length is the length of Tstring S X delete [] str; //Delete the original array of characters X str = new char[len+1]; //Allocate memory for the new string X assert(str != NULL); //Abort if new fails X strcpy(str,S.str); //Copy the new string over X return *this; //Return the Tstring so we can say X } //things like Ts1=Ts2=Ts3 } X /***************************************************************/ /* Pseudo-Conversion Operator */ /***************************************************************/ X //The conversion operator "operator char*()" gives the following error //"Ambiguity between operator + (Tstring &, Tstring &) and operator char*()" //so I worked around the problem with the string function defined below X char * Tstring::string(void) //Conversion operator should return a copy { //copy of str, not the original. This way X char *s; //nobody can mess with the private data. X s = new char[len+1]; //Leave room for null char at end of string X assert(s != NULL); //Abort if new fails X strcpy(s, str); //Copy string str into string s X return s; //Return the copy of str } X SHAR_EOF chmod 0666 tstring.cc || echo 'restore of tstring.cc failed' Wc_c="`wc -c < 'tstring.cc'`" test 3739 -eq "$Wc_c" || echo 'tstring.cc: original size 3739, current size' "$Wc_c" fi # ============= tstring.hpp ============== if test -f 'tstring.hpp' -a X"$1" != X"-c"; then echo 'x - skipping tstring.hpp (File already exists)' else echo 'x - extracting tstring.hpp (Text)' sed 's/^X//' << 'SHAR_EOF' > 'tstring.hpp' && //tstring.hpp, Terminal String Class Definition X //Copyright 1995 by Daniel C. Nygren //Current e-mail: nygren@tecnet1.jcte.jcs.mil X // Permission to use and modify this software for any purpose is // hereby granted without fee. Permission to copy and distribute this software // is also granted without fee, provided that the above copyright notice // and this entire permission notice appear in all copies, and any supporting // documentation. The author makes no representations about the suitability of // this software for any purpose. It is provided "as is" without express or // implied warranty. X #ifndef tstring_hpp //If we haven't been in this file before, include it #define tstring_hpp //Define the token so we don't include this again X /******************************************************/ /* Member fuctions are fully commented in tstring.cpp */ /******************************************************/ X #include #include #include #include #include #include X const int MAX_LDIGITS=32; //Maximum digits in a long integer X class Tstring { X /*********************************************************************/ /* FRIENDS /* /* A member function requires that its left hand operand be an object /* of its class. If the operator requires a left operand of another /* type, then it *must* be made a non-member function. If it needs to /* access non-public members of the class, then it must be made a /* friend. /*********************************************************************/ X /*********************************************************************/ /* friend Tstring operator + (const Tstring &, const Tstring &) /* /* I made this a non-member function so I could say "stuff" + Tstring /* as well as Tstring + Tstring and Tstring + "stuff". Also I didn't /* want to have a huge number of Tstring::operator + (class, type) /* member functions of every permutation. Instead, I have conversions /* for the built in types so thet are converted to strings. /*********************************************************************/ X friend Tstring operator + (const Tstring & S1, const Tstring & S2)//Note no Tstring:: needed X { X Tstring Temp; //Make a new string that can hold the others X Temp.len = S1.len + S2.len; X Temp.str=new char[Temp.len + 1]; //Leave room for null char at end of string X assert(Temp.str != NULL); //Abort if string is NULL X strcpy(Temp.str,S1.str); //Copy 1st string to Temp string X strcat(Temp.str,S2.str); //Concatenate 2nd string to Temp string X X return Temp; X } X X X public: X // Constructors and Destructor X Tstring(); X Tstring(const Tstring& S); X Tstring(const char * s); X Tstring(const long l); X ~Tstring() { delete [] str;} X X /**** Member Functions ****/ X X Tstring& operator = (const Tstring &); X X unsigned long length() { return len;} X X //The conversion operator "operator char*()" gives the following error X //"Ambiguity between operator + (Tstring &, Tstring &) and operator char*()" X //so I worked around the problem with the string function defined below X X char * string(void);//Psuedo-conversion operator X X private: X char * str; X unsigned long len; X }; X #endif X SHAR_EOF chmod 0666 tstring.hpp || echo 'restore of tstring.hpp failed' Wc_c="`wc -c < 'tstring.hpp'`" test 3234 -eq "$Wc_c" || echo 'tstring.hpp: original size 3234, current size' "$Wc_c" fi exit 0