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
<keywords> = 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 <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
X
//**** MS-DOS ****
#ifdef MSDOS
X	#include <conio.h>
X	#include <dos.h>
#else
X	#include <unistd.h>	//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 <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
X
//**** MS-DOS ****
X
#ifdef MSDOS
X
X	#include <conio.h>
X	#include <dos.h>
X	#include <asynch_2.h>
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 <stddef.h>
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
//**** MS-DOS ****
#ifdef MSDOS
X	#include <asynch_2.h>
#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 <assert.h>
#include <string.h>
#include <ctype.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
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




