/*===========================================================================
  Copyright (C) 1986-2009 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		Module
.IDENTIFICATION tvclear.c
.AUTHOR    	Francois Ochsenbein [ESO-IPG]
.LANGUAGE  	C
.KEYWORDS	Terminal Independant i/o Package.
.ENVIRONMENT 	TermWindows
.COMMENTS	This module includes clear functions.
\begin{TeX}
Used Capabilities:
$$\begin{tabular}{|lp{30em}|} \hline
{\tt cl=}	& Clear whole screen (and cursor to home position)	\\
{\tt cu=}	& Clear Up (from top of screen to cursor inclusive)	\\
{\tt cd=}	& Clear Down (from cursor inclusive to bottom of screen)\\
{\tt ce=}	& Clear from cursor to end of line			\\
{\tt cs=}	& Clear from start of line to cursor inclusive	\\
\hline
\end{tabular}$$
\end{TeX}
.VERSION 1.0	07-Jul-1986:	Creation
.VERSION 1.1 	12-Aug-1986: 	Clearing lines or screen also means stop insert mode.

.VERSION 1.2 	23-Oct-1986: 	Take care of possible existing scrolling region

.VERSION 2.0 	03-Dec-1986	New terminal-independant graphic characters
			with output buffering version.
.VERSION 2.1 	11-Jun-1987	Modify a bit for hard_copy terminals:
			Useless to clear characters!!!
.VERSION 2.2	23-Jun-1987	Adapted to UNIX
.VERSION 3.0	20-Mar-1988	Version '3' of TermWindows.

 090831		last modif
----------------------------------------------------------------------------*/

#define DEBUG		0	/* Only for debugging	*/

#define PM_LEVEL 	LEVEL_TV

#include <midas_def.h>


#define	TW_MACROS	0		/* Don't use TermWindows Macros */
#define	TW_import	0	
#define TW_STRUCT	0	/* Do not use window Structures		*/
#include <twset.h>


extern int tv_buffer(), tv_send(), tv_goto(), tv_out();
extern int tv_line(), tv_where(), tv_open(), tv_attr();
extern int tv_nl(), tv_sr0(), tv_home();

extern int pm_ed_i(), pm_iexit(), pm_enter();


MID_RSTATIC  char	clear_cap[] = "cucdcbce";
MID_STATIC   short int	old_pos[2] = {0,0};

#if 	DEBUG
#	define	TERMTEST	if(!terms->version) tv_gopen();\
				tv_ed(terms)
#else
#	define	TERMTEST	if(!terms->version) tv_gopen()
#endif

#define FIN_CURSOR	goto RESET_CURSOR

#define	ENTER_TV(x)	static int 	state_buffer;			\
			ENTER(x);	TERMTEST;			\
			state_buffer  =	tv_buffer(TRUE);	
#define	EXIT_TV(f)	FIN:						\
			tv_buffer(state_buffer);			\
			EXIT(f)

MID_EXTERN  TERM	*terms ;		

#define		SEND(p)		tv_send(p,1)

		/* Macros just to improve readibility	*/

#define		oldl			old_pos[0]
#define		oldc			old_pos[1]
#define		curl			(terms->pos[0])
#define		curc			(terms->pos[1])
#define		diml			(terms->dim[0])
#define		dimc			(terms->dim[1])
#define		BUFS			(terms->bufs)


	MONITOR (ZTCLEAR);

/*==========================================================================
 *			clear_h()
 *==========================================================================*/
static int clear_h(dir)
/*++++++++++++++++++++++++
.DES Clear at left / right of cursor (inclusive)
.RET OK / NOK
.REM Not traced. Never called for hard-copy terminals. Cursor moves
	if blanks are sent.
-----------------------*/
	int dir;	/* IN: Direction (left or right)	*/
{
	register char *p;
	register int i, s;

 			/* Use TermCapabilities when possible	*/
  p = SearchCap(&clear_cap[dir*2]);
  if (p) 	return(SEND(p));

  s = OK;
  if (dir == _LEFT_)
  {	tv_out("\r",1); 
	i = curc + 1;
	curc = 0;
  }
  else	i = dimc - curc;

  if (i > 0)
  {	oscfill(BUFS,i,' ');
	s = tv_line(BUFS, i);
  }
  
  return(s);
}

/*==========================================================================
 *			tv_cc
 *==========================================================================*/
int	tv_cc(nchar)
/*+++++++++++
.DES Clear n chars from the cursor inclusive.
.RET OK
.REM The cursor position remains unchanged. Simply write blanks ---
      	or do nothing for hard_copy terminals!
	If nchar<0, clear chars at the left of the cursor.
----------*/
	int nchar;		/* IN: Number of chars to clear	*/
{
	register int n;
	unsigned char old_attr;

  ENTER_TV("tv_cc");

  TRACE_ED_I("Clearing chars: ", nchar);

  status = OK;
  if (nchar == 0) 			FINISH;
  if (terms->flags & TERM_hard)		FINISH;

  tv_where(old_pos);
  old_attr = terms->attr;
  tv_attr(terms->attr_init);

  n = 0;			/* Number of blanks to issue	*/
  if (nchar < 0)
  { 	if (oldc + nchar < 0)			/* Optimize	*/
		status = clear_h(_LEFT_);
	else	tv_goto(oldl, oldc + nchar +1), n = -nchar;
  }
  else
  {	if (oldc + n >= dimc)			/* Optimize	*/	
		status = clear_h(_RIGHT_);
	else	n = nchar;
  }

	/* Can't clear with optimized TermCapabilities;
	 * issue blanks.				*/

  if (n)
  {	oscfill(BUFS,n,' ');
	status = tv_line(BUFS, n);
  }

  tv_goto(oldl,oldc);
  tv_attr(old_attr);

  EXIT_TV(status);
}

/*==========================================================================
 *			tv_cl
 *==========================================================================*/
int	tv_cl()
/*+++++++++++++
.DES Clear the complete line; the cursor is moved to the left margin.
.RET OK
.REM 
--------------*/
{
	unsigned char old_attr;

  ENTER_TV("tv_cl");

#if (TW_LEVEL > 0)
  status = OK;

	/* For hard-copy terminals, issue a new line	*/

  if (terms->flags & TERM_hard)	
  {	tv_nl();
	curl--;		/* ... but line unchanged	*/
	FINISH;
  }
#endif

	/* Simply go to line beginning, and clear it	*/

  old_attr = terms->attr;
  tv_attr(terms->attr_init);
  tv_out("\r", 1);	curc = 0;
  status = clear_h(_RIGHT_);
  tv_goto(curl,0);
  tv_attr(old_attr);

  EXIT_TV(status);
}

/*==========================================================================
 *			tv_clear
 *==========================================================================*/
int tv_clear(direction)
/*+++++++++++++++++
.DES Clear the terminal, according to the specified direction:
\begin{TeX}
\begin{itemize}
\item \_UP\_ : from the top of the screen, to the cursor (inclusive).
		The cursor does not move.
\item \_DOWN\_ : from the cursor (inclusive) to the end of the screen.
		The cursor does not move.
\item \_LEFT\_ : from the left margin of the current line
		to the cursor (inclusive) .
		The cursor does not move.
\item \_RIGHT\_ : from the cursor (inclusive) to the end of the line.
		The cursor does not move.
\item \_WHOLE\_ : the complete screen (the cursor goes to home, \ie [0,0]
			position.
\end{itemize}
\end{TeX}
.RET OK/NOK
.REM Insert Mode turned off. For hard-copy terminals, only _WHOLE_
	has some signification.
-------------------*/
	int	direction; /* IN: Clearing direction _WHOLE_, _UP_, _DOWN_, etc */
{
	register char *p;
	unsigned char old_attr;

  ENTER_TV("tv_clear");

  status = OK;
  terms->flags &= (~TERM_IMODE);

  tv_where(old_pos);		/* Save present position	*/
  curc = oldc;			/* For wrap (cursor passed right margin) */
  old_attr = terms->attr;
  tv_attr(terms->attr_init);

  if ( (direction < 0) || (direction > 3) )
  { 					/* Whole screen is the default	*/
			/* Reset the scrolling region to whole screen	*/
	tv_sr0();

	/* Look if "cl" cap exists (already stored in TERM)
		otherwise, simply put a new line	*/

	p = terms->tt_clear;
	if (p) 	
		status = SEND(p);
	else	status = tv_nl();	/* No cap: Simply go to newline ... */

	oldc = 0; oldl = 0;		/* New cursor position	*/
	FIN_CURSOR;
  }

  if (terms->flags & TERM_hard)	FINISH;


	/* Change the direction for optimisation		*/

  switch(direction)
  { case _UP_	:
	if (curl != 0) 			break;
    case _LEFT_	:				/* Cont. _UP_	*/
	status = clear_h(_LEFT_);	FIN_CURSOR;
    case _DOWN_	:
	if (curl != diml-1) 		break;
    case _RIGHT_:				/* Cont. _DOWN_	*/
	status = clear_h(_RIGHT_);	FIN_CURSOR;
  }

	/* Here only in case of _UP_/_DOWN_ clearing		*/

	/* Test if a scrolling region exists --- Use tv_sr0	*/

  if ( (terms->scregion[0] != 0) || (terms->scregion[1] < diml-1) )
  {	tv_sr0();
	tv_goto(oldl, oldc);
  }

 			/* Use TermCapabilities when possible	*/
  p = SearchCap(&clear_cap[direction*2]);
  if (p) 	{ status = SEND(p); FIN_CURSOR;}

			/* Simulate Clearing with blanks	*/
  switch(direction)
  { case _UP_:			/* Clear from top left corner	*/
	tv_home(); 	/* ... Cursor position is updated	*/
	while (curl < oldl)
	{	clear_h(_RIGHT_);
		tv_nl();
	}			/* We are on original line...	*/
	tv_goto(oldl, oldc);	/* ... and continue with _LEFT_	*/
	status = clear_h(_LEFT_);
	break;

    case _DOWN_: 	/* `cd' capability doesn't exist	*/
	status = clear_h(_RIGHT_);	/* clear current line...*/
	while (curl < diml-1)
		tv_nl(), clear_h(_RIGHT_);
  }

  RESET_CURSOR:
  tv_goto(oldl,oldc);
  tv_attr(old_attr);

  EXIT_TV(status);
}

