/* @(#)twtest.c	19.1 (ES0-DMD) 02/25/03 14:12:56 */
/*===========================================================================
  Copyright (C) 1995 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.TYPE		Program
.NAME		TWtest
.LANGUAGE	C
.AUTHOR		Francois Ochsenbein [ESO-IPG]
.CATEGORY	Terminal Handling
.COMMENTS	Test of tw (window) and tx (TeX-like) routines
.ENVIRONMENT	TermWindows
.VERSION  2.1	(Version '2' of TermWindows)
.VERSION  2.2	02-Jul-1987: Merging with TermDisplay.
.VERSION  2.3	02-Dec-1987: Usage of WhileInput
------------------------------------------------------------*/

#define	PM_LEVEL	2

#define TWFAC_TeX	0

#include <stesodef.h>
#include <tw.h>
#include <atype.h>
#include <str.h>

#define STRETCH	0

char *gets();
WINDOW *specify();


#if TWFAC_TeX
#undef EOF
#undef NULL
#include <stdio.h>
static WD *wd = NULL_WD;
static FILE *IN;		/* Help File	*/

#define STOPPER 	"\\EndOfText"
#endif

#ifndef NULL
#define NULL	NULL_PTR(char)
#endif

#define LOGGING		{   if (state_log)				\
	{	TraceOff (LEVEL_TV);		/* Trace ZT lib	*/	\
		TraceOff (LEVEL_TW);		/* Trace ZU lib	*/	\
		TraceOff (LEVEL_TX);		/* Trace ZU lib	*/	\
	}	else							\
	{	   TraceOn (LEVEL_TV);		/* Trace ZT lib	*/	\
		   TraceOn (LEVEL_TW);		/* Trace ZU lib	*/	\
		TraceOn (LEVEL_TX);		/* Trace ZU lib	*/	\
	}	state_log ^= 1;						\
  }
static short int screen_size[2];


static char *menu_list[] = {
	"0 Show Windows",
	"1 Raise / Lower",
	"2 Cursor Movements",
	"3 Output with Scrolling ",
	"4 Attributes",
	"5 Move Window",
	"6 Delete Characters",
	"7 Insert a Text ",
	"8 Clear operations",
	"9 GetKey ",
	"A Applications",
	"G Gets   ",
	"T Set/Stop Tracing",
	"W Set/Stop Waiting",
 };

static char *wMa_list[] = {
	"0 GetsPassword",
	"1 GetsAnswer",
	"2 $ (Spawn)",
	"3 HitReturn",
	"4 Puts Text",
	"5 GetYes"
 };

static WINDOW *wM, *wT, *wS, *wF, *wD, *wR, *wMa;
static int choice;
static char state_log = 0;
static char state_wait = 0;
static char msg[161];
static short int tpos[2];
static int menu_pos, junk;
static char temp,string[5];
static char *char_type[8];

	int waiting_input();
	int run_automatic();


	MONITOR(TWtest);

/*===========================================================================*/
main	()
/*+++++++
.PURPOSE Extensive Test Program for Window Facilities
	(including TeX)
.RETURNS 
--------*/
{
	int 	i;

	OpenLog	("twtest.log","Testing TW (windows) facilities"); 
	LogLevel	(-20); 

#if TRACING
  printf("Tracing ? "); gets(msg);
  if (msg[0] == 'Y' || msg[0] == 'y')
	LOGGING
#endif
  printf("Device name ? "); if (!gets(msg)) return;
  if (strlen(msg)) status = InitWindows(msg,NULL,-1);
	else status = InitWindows(NULL,NULL,-1);
  if (status != OK)
  {	printf("****%s\n", ERR_LOC());
	puts(msg);
	return;
  }

  ScreenSize(screen_size);

	char_type[0]	 	= " ???????    ";
	char_type[_STANDARD_] 	= " (ASCII)    ";
	char_type[_KEYPAD_] 	= " (Keypad)   ";
	char_type[_PF_] 	= " (PF key)   ";
	char_type[_ARROW_] 	= " (Arrow)    ";
	char_type[_FK_] 	= " (other key)";

  wT = OpenWindow("Title", 0,0, 4,0, _BOLD_,_GRAPHICS_,0);	
  	/* Title Window	*/
  ActiveWindow(wT);
  wS = OpenWindow("Small Window", 4, -30, screen_size[0]-7, 30,
  	0, _GRAPHICS_|_TITLE_|_SCROLL_,0);	/* Small Window	*/
  wD = OpenWindow("Dialog", -4, 0, 4, 0, 
  	0, _GRAPHICS_, 12);			/* Dialogue Window	*/
  wR = OpenWindow("Return", -3, -35, 3, 35,
  	0, _GRAPHICS_, 0);			/* Return Window	*/
  wF = OpenWindow("Full-Width Window", 3, 0, 0, 0,
  	_UNDERSCORE_, _SCROLL_|_TITLE_,0);	/* Full Window	*/

	/* Insert the Text in Menu Window */

  wM = OpenMenuWindow("Menu", 3, 0, menu_list, ITEMS(menu_list), _REVERSE_);
  wMa= OpenMenuWindow("Applications", 13, 3, wMa_list, ITEMS(wMa_list), 
  	_REVERSE_);

  menu_pos = GetPosition(wM);
  
  	/* Loop on Menu Display, Get a Choice, Execute Function */
  
  while(1)
  {	WhileInput(waiting_input);
	CursorHome(wM);
  	choice = GetMenuChoice(wM, _BOLD_);
	if (choice == EOF)	break;
	ospwait(1);
	switch(choice)
	{ default: 
		execute();		break;
	  case 10: /* Applications */
  		switch(GetMenuChoice(wMa, _BOLD_))
  		{ case 0:	GetsPassword(msg, 21, _DOWNLEFT_);
  				PutWindow(msg, _BOLD_,_DOWNLEFT_);
  				break;
  		  case 1:	GetsAnswer("Type below your Text", msg, 
  		  			sizeof(msg), _CENTER_);
  				PutWindow(msg, _BOLD_,_CENTER_);
  				break;
  		  case 2:	Execute (NULL_PTR(char), NULL_PTR(char));
  				break;
  		  case 3:	HitReturn(_REVERSE_, -1);  /* At cursor pos*/
  		  		break;
  		  case 4:	PutWindow("Text centered\n  in Window",
  		  			_BOLD_, _CENTER_);
  		  		break;
  		  case 5:	switch (GetYes ("Answer Y / N ")) {
				case OK:
  		  			PutWindow("Yes", _BOLD_, _CENTER_);
  		  			break;
				case NOK:
  		  			PutWindow("N O", _BOLD_, _CENTER_);
  		  			break;
				default:
  		  			PutWindow("EOF", _BOLD_, _CENTER_);
  		  			break;
  		  		}
  		  		break;
  		}
		RemoveWindow(wMa);	break;
	  case 11: /* Gets */
	  	Commands();		break;
	  case 12:	LOGGING;	break;
	  case 13: 	state_wait ^= 1;
		WaitTerm(state_wait ? 200 : 0);	
		break;
	}
  }

  ClearWindow(wR);
  SetAttr(wR,_BOLD_|_REVERSE_);
  Put(wR,"... Bye ...");
  RaiseWindow(wR);
  EndWindows();
  CloseLog();
  return;
}

/*=========================================================================*/
RemoveMenu()
{	
  	
  ChangeAttr(wM, wM->dim[1], _NORMAL_);
  RemoveWindow(wM);

  return(0);
}

WINDOW *specify()		/* Routine to get the Window */
{  
	static   char *list[] = {
		"T  Top Window",
		"F  Full-Size  Window",
		"S  Small-Size Window",
		"D  Dialogue   Window"
	};
	static 	WINDOW *ww = NULL_WINDOW;
	register WINDOW *w;
	char ch;
	int	i;

  if (ww == NULL_WINDOW)
  	ww = OpenMenuWindow("Windows Choice", 10, 10, list, ITEMS(list), 0);

  WhileInput(run_automatic);

  switch(i = GetMenuChoice(ww, _BOLD_))
  { case 0: w = wT; break;
    case 1: w = wF; break;
    case 2: w = wS; break;
    case 3: w = wD; break;
    case -1: w = NULL_WINDOW;	break;
  }
  if (w)
  {	ospwait(1);
	ChangeAttr(ww, ww->dim[1], _NORMAL_);
  }
  RemoveWindow(ww);

  RemoveMenu();
  if (w)	ActiveWindow(w);
  return(w);
}

/*==========================================================================*/
Commands()
/*++++++++++++
.PURPOSE Loop on Get / Display Commands
.RETURNS 0
--------------*/
{ 	int 	i;
	char	ch;

#if STRETCH
  WINDOW *wD;
  
  wD = wT;
#endif

  RemoveMenu();
  Title("Getting and displaying commands - Help is Control-G");
  Put(wT, "\n                                  End is Control-Z");
  DeactiveWindow(wS);
  ClearWindow(wS);
  RaiseWindow(wS), DeactiveWindow(wS);
  RaiseWindow(wD), ActiveWindow(wD);
  ActiveStacking(wD);
  i = 0;		/* The first time, use a template	*/
  WhileInput(waiting_input); 	/* Function used while waiting for input */

  while(1)
  {
#if !STRETCH
  	ClearWindow(wD);
#endif
	CursorHome(wD);
	Put(wD,"Command=>");
	SetAttr(wD,_REVERSE_);
	if (i == 0)				/* First test	*/
		strcpy(msg,"Template command ===> Try to edit it !");
	else	msg[0] = 0;
#if STRETCH
	status = Mods(wD, msg, -sizeof(msg));
#else
	status = Mods(wD, msg, sizeof(msg));
#endif
	SetAttr(wD,_NORMAL_);
	if (status == 0) 	status = GetChar(&ch);	
				/* Special character stopped input */
	if (status < 0) break;

#if !STRETCH
	if (i)	NewLine(wS);
	i++;
	SetAttr(wS,_REVERSE_);
	Puts(wS,char_type[status]);
	SetAttr(wS,_NORMAL_);
	EditNumberedCommand(wD, wS);
	TouchWindow(wS);
#endif
  }
#if !STRETCH
  ClearWindow(wD);
#endif

  WhileInput(run_automatic); 	/* Function used while waiting for input */
  ClearWindow(wF);
  RaiseWindow(wF), ActiveWindow(wF);
  SetAttr(wF,_UNDERSCORE_|_BOLD_);
  PutCentered(wF,"List of stored commands");
  SetAttr(wF,_NORMAL_);
  ListNumberedCommands(wD, wF);
  WaitCR();
  return(0);
}

/*==========================================================================*/
execute()
/*++++++++++++
.PURPOSE Execute the menu
.RETURNS 0
--------------*/
{
	int i;
	WINDOW *w;
	
  switch(choice)
  { case 0:		/* Show the Windows */
	RemoveMenu();
	Title("TEST 0 - Clear Windows and output text");
	WaitandSee();
	ClearWindow(wT);
	PutCentered(wT,"Title Window - BOLD, no scrolling");
	RaiseWindow(wT);
	ActiveWindow(wT);
	WaitandSee();

	ClearWindow(wF);
	PutCentered(wF,"Full-Width Window: UNDERSCORE, scrolling");
	RaiseWindow(wF);
	WaitandSee();

	ClearWindow(wS);
	PutCentered(wS,"Small-width scrolling Window");
	RaiseWindow(wS);
	WaitandSee();

	ClearWindow(wD);
	PutCentered(wD,"The Dialogue Window");
	RaiseWindow(wD);
	break;

    case 1:	/* Raise Windows	*/
	Title("TEST 1 - Raise / Lower a Window at your Choice");
	w = specify();
	if (w)	RaiseWindow(w);
	w = specify();
	if (w)	LowerWindow(w);
	break;

    case 2:	/* Cursor Movements	*/
	RemoveMenu();
	Title("TEST 2A - Cursor positioning on Full-Width Window");
	SetAttr(wF,_BOLD_|_UNDERSCORE_);
	CursorTo(wF,14,25);
	Put(wF,"This should be on line 15");
	CursorTo(wF,4,25);
	Put(wF,"This should be on line 5");
	SetAttr(wF,_NORMAL_);
 
	Title("TEST 2B - Move Cursor on Small Window");
	ActiveWindow(wS);
	RaiseWindow(wS);
	WaitandSee();
	CursorTo(wS,2,0);
	Put(wS,"A");
	CursorRight(wS,5);
	Put(wS,"G");
	CursorLeft(wS,6);
	Put(wS,"B");
	CursorRight(wS,3);
	Put(wS,"F");
	CursorLeft(wS,4);
	Put(wS,"C");
	CursorRight(wS,1);
	Put(wS,"E");
	CursorLeft(wS,2);
	Put(wS,"D");
	CursorLeft(wS,7);
	CursorDown(wS,2);
	Puts(wS,"The above should read:\nABCDEFG");
	WaitandSee();

	CursorDown(wS,4);
	Puts(wS,"`down four'");
	CursorUp(wS,2);
	Put(wS,"Above `down four'... OK?");
	break;

    case 3: 
	Title("TEST 3 - Output with Line Wrap and Scrolling");
	if_not(w = specify())	break;
	ActiveWindow(w);
	Puts(w," This should cause a line wrap..................\
.................................OKAY?");
	Puts(w,"This should appear\non two lines...");
	WaitandSee();
	Puts(w,"\nOn this window,\nif a long long story\nis displayed,");
	Puts(w,"made of many many words,\nit could happen that,");
	Puts(w,"after some time,\nthe scrolling is enabled,");
	Puts(w,"to ensure that you do not\nloose any word of this");
	Put(w,"(interesting but awful)\nlong story...");
	break;
    
    case 4:	/* Attributes */
	Title("TEST 4 - Character attributes ");
	if_not(w = specify())	break;
	DeactiveWindow(w);
	ClearWindow(w);
	NewLine(w);
	SetAttr(w,_NORMAL_);
	Puts(w,"\n NORMAL");
	SetAttr(w,_BOLD_);
	Puts(w," BOLD");
	SetAttr(w,_BLINK_);
	Puts(w," BLINK");
	SetAttr(w,_UNDERSCORE_);
	Puts(w," UNDERSCORE");
	SetAttr(w,_REVERSE_);
	Puts(w," REVERSE");
	SetAttr(w,_BLINK_|_BOLD_|_REVERSE_);
	Puts(w," BLINK+BOLD+REVERSE");

	SetAttr(w,_UNDERSCORE_);
	Puts(w,"\n Graphic chars");
	SetAttr(w,_GRAPHICS_);
	Puts(w,"abcdefghijklmnopqrstuvwxyz");
	ActiveWindow(w);
	Put(wT,"  Trace a box around window ...");
	WaitandSee();
	DrawBox(w,0,22, 2,4); 
	DrawBox(w,1,0, 8,20); 
	DrawBox(w,0,0,0,0); 
	SetAttr(w,_NORMAL_);
	break;

    case 5: 	/* Move Window	*/
	Title ("TEST 5 - Move Window to Top or Bottom");
	if_not(w = specify())	break;
	GetHomePosition(w, tpos);
	WaitandSee();
	MoveWindow(w, (w == wT ? -1 : 0), tpos[1]);
	ClearLine(wT);
	Put(wT,"\n                      ... and put it back ");
	WaitandSee();
	MoveWindow(w, tpos[0], tpos[1]);
	break;

    case 6:
	Title ("TEST 6 - Delete Characters");
	if_not(w = specify())	break;
	CursorTo(w,1,1);
	SetAttr(w,_BOLD_);
	Put(w,"ABCDEFGHIJKLMNOPQ");
	SetAttr(w,_NORMAL_);
	CursorTo(w,1,2);
	RaiseWindow(w);
	ActiveWindow(w);
	CursorTo(wT,0,40);
	Put(wT,"Will delete BCD");
	WaitandSee();
	CursorTo(w,1,2);
	DeleteChars(w,3);
	break;

    case 7:
	Title("TEST 7 - Terminal type displayed in Insert Mode on Title Window");
	RaiseWindow(wT); RemoveMenu();
	SetAttr(wT,_BOLD_);
	Put(wT,"The tests were performed on a ");
	GetCursor(wT,tpos);
	Put(wT, " terminal.");
	SetAttr(wT,_NORMAL_);
	CursorTo(wT,tpos[0],tpos[1]);
	WaitandSee();
	EnterImode(wT);
	sprintf(msg,"%s with %d lines and %d columns",GetTerm(), 
		screen_size[0], screen_size[1]);
	Put(wT,msg);
	ExitImode(wT);
  	break;

    case 8:	/* Clear */
	tpos[0] = 1; tpos[1] = 0;
	Title("TEST 8C - Clear Characters M-Q (inclusive)");
	if_not(w = specify())	break;
	CursorTo(w, tpos[0], tpos[1]);
	SetAttr(w,_REVERSE_);
	Puts(w,"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
	Puts(w,"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
	Puts(w,"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
	SetAttr(w,_NORMAL_);
	WaitandSee();
	CursorTo(w,tpos[0],tpos[1]+'M'-'A');
	ClearChars(w,5);

	Title1("TEST 8E - Clear to end of line from X");
	WaitandSee();
	CursorTo(w,tpos[0],tpos[1] + 'X' - 'A');
	ClearRight(w);

	Title1("TEST 8B - Clear from beginning of line until F");
	WaitandSee();
	CursorTo(w,tpos[0],tpos[1] + 'F' - 'A');
	ClearLeft(w);

	Title1("TEST 8U - Clear from beginning of Window to J");
	WaitandSee();
	CursorTo(w,tpos[0],tpos[1] + 'J' - 'A');
	ClearUp(w);

	Title1("TEST 8D - Clear to end of Window from U");
	WaitandSee();
	CursorTo(w,tpos[0],tpos[1] + 'U' - 'A');
	ClearDown(w);

	Title1("TEST 8L - Clear line 2");
	WaitandSee();
	CursorTo(w,tpos[0],tpos[1]);
	ClearLine(w);
 
	break;
 
    case 9:
	Title("TEST 9 - Single key input displayed on Small Window");
	RemoveMenu();
	Put(wT,"Use Control_G for Help");
	ClearWindow(wS);
	RaiseWindow(wS);
	ActiveWindow(wS);
	DeactiveWindow(wR);
	CursorHome(wR);
	ClearWindow(wR);
	SetStopping(wR,_STANDARD_,"*-RG\\");	/* All controls except ^R ^G */
						/* Return for these Controls */
	SetStopping(wR,_ARROW_,"*");		/* Return if arrow */
	SetStopping(wR,_FK_,"*");		/* Return if Function Keys */
	EnableKeypad(wR);			/* Return if Keypad */
	Put(wR,"Type a key");
	RaiseWindow(wR);
	GetCursor(wR,tpos);
	for( i=0; (junk = GetKey(wR, &temp)) >= 0; i++, TouchWindow(wR))
	{	if(junk == NOK)
		{ 	SetAttr(wS,_REVERSE_|_BLINK_);
			if (i++)	NewLine(wS);
			Put(wS,"TERMCAP can't understand!");
			SetAttr(wS,_NORMAL_);
			continue;
		}
		if (iscntrl(temp))
		{	string[1] = temp + '@';
			string[0] = '^';
			string[2] = ' ';
			if (temp > ' ')		/* Delete Key */
				string[0]='D', string[1]='e', string[2]='l';
	   	} 
		else	string[1] = temp, string[2] = '\'', string[0] = '\'';
		if (i)	NewLine(wS);
		Write(wS,string,3);
		Put(wS," ");
		Put(wS,char_type[junk]);
	}
	break;
 }
 WaitCR();
 return(0);
}

WaitandSee()
/*++++++++++++
.PURPOSE Just wait the CR to perform the test
.RETURNS 0
--------------*/
{
	char ch;
	int run_automatic();

  ENTER("WaitandSee");

  WhileInput(run_automatic);
  ClearWindow(wR);
  CursorTo(wR,0,1);
  SetAttr(wR,_BLINK_|_REVERSE_);
  Put(wR, "Hit <Return> to perform test");
  SetAttr(wR,_NORMAL_);
  RaiseWindow(wR);

  GetKey(wR, &ch);
  RemoveWindow(wR);

  EXIT(0);
}

WaitCR()
/*++++++++++++
.PURPOSE Just wait the CR to go blck to Menu
.RETURNS 0
--------------*/
{
	char ch;

  ENTER("WaitCR");

  WhileInput(run_automatic);
  ClearWindow(wR);
  CursorTo(wR,0,1);
  SetAttr(wR,_BOLD_);
  Put(wR, "Hit <Return> to go back to Menu");
  SetAttr(wR,_NORMAL_);
  RaiseWindow(wR);

  GetKey(wR, &ch);
  RemoveWindow(wR);

  EXIT(0);
}

/*==========================================================================*/
int waiting_input(tick)		/* Routine excuted while waiting for input */
	int tick;		/* IN: Counter 	*/
{  
	static WINDOW *w_w;
	MID_RSTATIC char text[]=" Are you sleeping ?? ";

  ENTER("waiting_input");
  if (w_w == NULL_WINDOW)
  {	w_w = OpenWindow("Waiting", 0, -1-sizeof(text), 3, sizeof(text)+1,
  	_REVERSE_|_BLINK_|_BOLD_,  _DISPLAY_|_GRAPHICS_, 0);
	Put(w_w,text); CursorLeft(w_w,1);
  }
	
  if (tick > 30)		EXIT(30);
  if (tick == 2) 
  {	Bell();
	RaiseWindow(w_w);
	ospwait(2);			/* Wait 2	*/
  	Bell();
	RemoveWindow(w_w);
  	EXIT(999);
  }
  EXIT(--tick);
}

int run_automatic(tick)		/* Routine excuted while waiting for input */
	int tick;		/* IN: Counter 	*/
{  
	static WINDOW *w_w;
	MID_RSTATIC char text[]=" Let's continue... ";

  ENTER("run_automatic");
  if (w_w == NULL_WINDOW)
  {	w_w = OpenWindow("Automatic", 0, -1-sizeof(text), 3, sizeof(text)+1,
		_REVERSE_|_BLINK_|_BOLD_, _DISPLAY_|_GRAPHICS_, 0);
	Put(w_w,text);
  }
	
  if (tick > 30)		EXIT(30);
  if (tick == 2) 
  {	Bell();
	SupplyInputs("\r");
	RaiseWindow(w_w);
	ospwait(2);			/* Wait 2s	*/
	RemoveWindow(w_w);
  	Bell();
	EXIT(0);
  }
  EXIT(--tick);
}

Title(text)
	char *text;
{
  LOG(text);
  ClearWindow(wT);
  Puts(wT,text);
  return (0);
}

Title1(text)
	char *text;
{
  LOG(text);
  CursorHome(wT);
  ClearLine(wT);
  CursorHome(wT);
  Put(wT,text);
  return (0);
}
