/*===========================================================================
  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 tvindel.c
.AUTHOR    	Francois Ochsenbein [ESO-IPG]
.LANGUAGE  	C
.KEYWORDS	Terminal Independant i/o Package.
.ENVIRONMENT 	TermWindows
.COMMENTS	This module includes functions to insert or delete lines
		and characters.
		In the Minimal Implementation, these routines are not used.
\begin{TeX}
Used Capabilities:
$$\begin{tabular}{|lp{30em}|}	\hline
{\tt al}	& Add a new (blank) line, pushing all lines below it down.\\
{\tt dl}	& Delete the current line, moving all lines below it up	\\
{\tt dc}	& Delete the current char, moving all chars to the left \\
{\tt ei}	& Exit Insert Mode.					\\
{\tt ic}	& Insert one blank, moving all chars to the right	\\
{\tt im}	& Enter Insert Mode.					\\
\hline
\end{tabular}$$
\end{TeX}
.VERSION  1.0	12-Aug-1986:	Creation 
.VERSION  2.0	03-Dec-1986	New terminal-independant graphic characters
			with output buffering version.
.VERSION  2.1	11-Jun-1987	Version '2' of TermWindows.
.VERSION  2.2	23-Jun-1987	Adapted to UNIX and Minimal Implementation.
.VERSION 3.0	20-Mar-1988	Version '3' of TermWindows.

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

#define DEBUG		0		/* Debugging only	*/

#define PM_LEVEL 	LEVEL_TV

#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>

MID_EXTERN TERM	*terms;		

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

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

#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)

#if DEBUG
	static  char ch=EOS;
	static int type=0;
#endif

		/* 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 (ZTINDEL); */

/*======================================================================
 *			tv_dc
 *======================================================================*/
int tv_dc(nchars)
/*+++
.PURPOSE Delete n chars, starting at the cursor position, and moving
	characters to the left.
.RETURNS OK / NOK (impossible)
.REMARKS A negative number of times asks to delete chars at the left of
	the cursor. Returns always NOK in the Minimal Implementation.
---*/
	int nchars;	/* IN: Number of chars to delete		*/
{
#if (TW_LEVEL < 2)
  return(NOK);
#else
	int 	n;
	char 	*p;

  ENTER_TV("tv_dc");

  status = OK;

  if (nchars == 0) 	FINISH;

  p = SearchCap("dc");
  if (!p)
  {	status = NOK;
	FINISH;
  }

  if (nchars < 0) 	tv_goto(curl, curc+nchars);
  n = ABSOLUTE(nchars);  

  status = tv_send(p,n);

  EXIT_TV(status);
#endif
}

/*==========================================================================
 *			tv_dl
 *==========================================================================*/
int	tv_dl(lines)
/*+++++++++
.PURPOSE Delete lines (moving up lines below), inluding the running
	line.
.RETURNS OK, or NOK (capability does not exist)
.REMARKS On return, the cursor is at the beginning of the line.
	If lines<0, lines on top of the current are deleted.
	Returns always NOK in the Minimal Implementation.
-----------*/
	int lines;		/* IN: Number of lines to delete	*/
{	
#if (TW_LEVEL < 2)
  return(NOK);
#else
	short int old_pos[2];
	char 	*p;
	int 	n;

  ENTER_TV("tv_dl");

  status = OK;

  if (lines < 0) 
  {	tv_goto(curl+lines, 0);
	n = -lines;
  }
  else 	
  {	tv_goto(curl, 0);
	n = lines;
  }

  if (lines == 0) 	FINISH;

  p = SearchCap("dl");
  if (p)
  {	status = tv_send(p,n);
	FINISH;
  }

	/* Delete Line does not exist ---
	 * Try to use the scrolling		*/

  status = tv_sr(curl,  diml-1) ;
  if (status == OK)
  {	tv_where(old_pos);
	tv_goto(diml-1,0);
	curl -= n;		/* In fact, the cursor did not move	*/
	tv_mvc(_DOWN_,n);
	tv_sr(0, diml-1);
  }

  status = tv_goto(oldl, 0);	

  EXIT_TV(status);
#endif
}

/*======================================================================
 *			tv_ic
 *======================================================================*/
int tv_ic(nchars)
/*+++
.PURPOSE Insert n blanks at the cursor position, moving existing characters
	to the right.
.RETURNS OK / NOK (impossible)
.REMARKS A negative number of times asks to insert chars at the left of
	the cursor.
	Returns always NOK in the Minimal Implementation.
---*/
	int nchars;	/* IN: Number of blanks to insert	*/
{
#if (TW_LEVEL < 2)
  return(NOK);
#else
	int 	n;
	char 	*p;

  ENTER_TV("tv_ic");

  status = OK;

  if (nchars == 0) 	FINISH;

  if (nchars < 0) 	status = tv_goto(curl, curc+nchars);
  n = ABSOLUTE(nchars);  
  n = MIN(n, terms->buf_size);

  p = SearchCap("ic");
  if (!p) 	
  {	status = tv_imode(1);	/* Try to use Insert Mode */
	if (status == NOK) 	FINISH;
	oscfill(BUFS,n,' ');
	tv_write(BUFS,n);
	status = tv_imode(0);
  }

  if (status == OK)	status = tv_send(p,n);

  EXIT_TV(status);
#endif
}

/*==========================================================================
 *			tv_il
 *==========================================================================*/
int	tv_il(lines)
/*++++++++++++++
.PURPOSE Insert blank lines (moving down lines below) from the
	cursor position inclusive.
.RETURNS OK, or NOK (capability does not exist)
.REMARKS On return, the cursor is at the beginning of the current (blank) line.
	If lines<0, lines are inserted on top of the current line.
	Returns always NOK in the Minimal Implementation.
---------------*/
	int lines;		/* IN: Number of blank lines to insert	*/
{
#if (TW_LEVEL < 2)
  return(NOK);
#else
	short int old_pos[2];
	char 	*p;
	int 	n;

  ENTER_TV("tv_il");

  status = OK;

  if (lines < 0) 
  {	tv_goto(curl+lines, 0);
	n = -lines;
  }
  else 	
  {	tv_goto(curl, 0);
	n = lines;
  }

  if (lines == 0) 	FINISH;

  p = SearchCap("al");
  if (p) 	
  {	status = tv_send(p,n);
	FINISH;
  }

	/* Insert Line does not exist ---
	 * Try to use the scrolling		*/

#if DEBUG
	tv_getc(&ch,&type);
#endif
  status = tv_sr(curl,  diml-1) ;
  if (status == OK)
  {	tv_where(old_pos);	/* The cursor is at top of subscreen 	*/
#if DEBUG
	tv_getc(&ch,&type);
#endif
	if ((status = tv_mvc(_UP_, n)) != OK)	FINISH;
#if DEBUG
	tv_getc(&ch,&type);
#endif
	status = tv_sr(0, diml-1);
  }

  if (status == OK)	status = tv_goto(oldl,0);	

  EXIT_TV(status);
#endif
}

/*======================================================================
 *			tv_imode
 *======================================================================*/
int tv_imode(k)
/*+++
.PURPOSE Enter/Exit Insert Mode (displayed chars will push existing chars to
	the right of the cursor)
.RETURNS OK / NOK (impossible)
.REMARKS Displaying a new line will stop the Insert Mode.
	(see tv_nl).
	Returns always NOK in the Minimal Implementation.
---*/
	int k;		/* IN: 0 to exit, non-zero to enter	*/
{
#if (TW_LEVEL < 2)
  return(NOK);
#else
	register char *p;

  ENTER_TV("tv_imode");

  status = OK;

  if (k)		/* Trying to enable ... 	*/
  { 	if (terms->flags & TERM_IMODE)		FINISH;
	p = SearchCap("im");
	if (p)	terms->flags |= TERM_IMODE;
  }
  else
  { 	if (!(terms->flags & TERM_IMODE))	FINISH;
	p = SearchCap("ei");
	if (p) 	terms->flags &= (~TERM_IMODE);
  }

  if (!p)		status = NOK;
  if (status == OK)	status = tv_send(p,1);

  EXIT_TV(status);
#endif
}

/*======================================================================
 *			tv_iwrite
 *======================================================================*/
int tv_iwrite(str,len)
/*+++
.PURPOSE Insert a text at the cursor position, pushing 
	existing chars to the right.
.RETURNS OK / NOK (impossible)
.REMARKS Displaying a new line will stop the Insert Mode.
	(see tv_nl).
	Returns always NOK in the Minimal Implementation.
---*/
	char *str;	/* IN: Text to display		*/
	int len;	/* IN: Length of text		*/
{
#if (TW_LEVEL < 2)
  return(NOK);
#else
	register char *p;

  ENTER_TV("tv_imode");

  status = OK;

  if (!(terms->flags & TERM_IMODE))	/* Enter Insert Mode	*/
  {	if ( (status = tv_imode(1)) == NOK)	FINISH;
  }
  
  status = tv_write(str,len);

  tv_imode(0);

  EXIT_TV(status);
#endif
}  
