/*===========================================================================
  Copyright (C) 1987-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 tvout.c
.AUTHOR    	Francois Ochsenbein [ESO-IPG]
.LANGUAGE  	C
.KEYWORDS	Terminal Independant Window Package.
.ENVIRONMENT 	TermWindows
.COMMENTS	This module groups direct output to terminal (interfaces
		to ost), without checks on the validity of the
		output or cursor positionning. 
\begin{TeX}
Used Capabilities:
$$\begin{tabular}{|lp{30em}|}\hline
{\tt pc=}	& Padding char (for delays)			\\
{\tt G0{\rm...}G4=}	& Corners			\\
{\tt Gu,Gd,Gl,Gr=}	& Tees			\\
{\tt Gg=}	& ``Rubbish'' character			\\
\hline
\end{tabular}$$
\end{TeX}
.VERSION 2.1	11-Jun-1987	Version '2' of TermWindows.
			Extracted from previous ZTOUT.
.VERSION 3.0	20-Mar-1988	Version '3' of TermWindows.

 090901		last modif
----------------------------------------------------------------------------*/

#define DEBUG		0		/* 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>

#define  ms_to_pad(ms)		((terms->baud/100) * ms)/100

extern int tv_wms(), tv_out();

extern int pm_ed_tr2(), pm_enter(), pm_iexit(), pm_tr2();
extern int eh_put1();




MID_EXTERN  TERM	*terms ;		
MID_STATIC  char	delay_flag = EOS;

#if DEBUG
#define ENTER_DEBUG(x)	ENTER(x)
#define EXIT_DEBUG(x)	EXIT(x)
#else
#define ENTER_DEBUG(x)	
#define EXIT_DEBUG(x)	return(x)
#endif

#define	TERMTEST	

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

		/* Macros just to improve readibility	*/

#define		BUFW			(terms->bufw)
#define		BUFS			(terms->bufs)

	MONITOR (TVOUT);


/*==========================================================================
 *			tv_feed
 *==========================================================================*/
static int tv_feed()
/*+++
.PURPOSE Write the current buffer to the terminal, and reset buffer. 
.RETURNS OK / NOK
.REMARKS 
-------*/
{
	register int s;

  ENTER_DEBUG("tv_feed");
  TRACE_STR2(BUFW, terms->iw);

  s = OK;
  if (terms->iw)	/* Only if there is something in the buffer	*/
  {	if (terms->flags & TERM_NOWRITE) ;
	else	
	{
#if (TW_LEVEL == 0)		/* Minimal Implementation	*/
		s = ostwrite(BUFW, terms->iw);
#else
		if (terms->term_type)		/* No terminal		*/
			s = osdwrite(1, BUFW, terms->iw); 
		else
		{	s = ostwrite(BUFW, terms->iw);
			if (terms->msw)		tv_wms(terms->msw);
		}
	}
  }
#endif
  if (s < 0)	ERROR(osmsg()), s = NOK;
  else		s = OK;
  terms->iw = 0;
  EXIT_DEBUG(s);
}

/*==========================================================================
 *			tv_buffer
 *==========================================================================*/
int tv_buffer (buffered)
/*+++
.PURPOSE Start (buffered!=0) or Stop (buffered==0) terminal buffering
.RETURNS The previous state, i.e. 0 if terminal was unbuffered, not-zero
	if terminal was buffered.
.REMARKS If unbuffering is asked for, the contents of the buffer is
	sent to the terminal. NOT TRACED.
---*/
	int	buffered;	/* IN: 1 to start, 0 to stop buffering	*/
{
	register int returned;

  returned = (terms->flags) & (TERM_buffered);

  if(buffered)	terms->flags |=   TERM_buffered;
  else		
  {	if (terms->iw)		/* If there is something in the buffer	*/
		tv_feed();	/* Send the buffer contents 		*/
	terms->flags &= ~(TERM_buffered);
  }

  return(returned);
}

/*==========================================================================
 *			compute_delay
 *==========================================================================*/
static int	compute_delay(str)
/*
.PURPOSE Compute the delay required by a sequence.
.RETURNS The delay converted into a number of padding chars.
.REMARKS Not Traced.
-----------------------------------------------------------------------*/
	char *str;		/* IN: The capability string 	*/
{
	register int delay;

  delay 	= 0;
  delay_flag 	= *(str+3);

  if (delay_flag != '=')			/* A delay is required	*/
  {	delay = (unsigned char)*(str+4+ *(unsigned char *)str);	
  						/* Delay in ms		*/
	delay = (int)ms_to_pad(delay);  /* Delay in number of padding chars	*/
  }

  return(delay);
}

/*==========================================================================
 *			tv_delay
 *==========================================================================*/
int	tv_delay(str)
/*++++++++++
.PURPOSE Send the delay (only) of a sequence, in principle made of NUL 
	characters.
.RETURNS OK / NOK
.REMARKS 
-----------------------------------------------------------------------*/
	char *str;		/* IN: The capability string 	*/
{
	register int delay;

  ENTER_DEBUG("tv_delay");

  status = OK;

  delay = compute_delay(str);	/* Delay in number of padding chars	*/

  if(delay)
  {	if (delay > terms->buf_size)	delay = terms->buf_size;
	oscfill(BUFS,delay,terms->pad_char);
	status = tv_out(BUFS,delay);
  }

  EXIT_DEBUG(status);
}

/*==========================================================================
 *			tv_out
 *==========================================================================*/
int	tv_out(str,len)
/*++++++++++++
.PURPOSE Write any string of characters to the terminal, with buffering. 
	No care taken about control characters, cursor position, etc.
.RETURNS OK / NOK
.REMARKS The buffer is only filled, and sent to terminal when full.
	Use tv_feed to output the buffer.
--------------*/
	char *str;		/* IN: String to display on the terminal */
	int  len;		/* IN: Length of String			*/
{
	register int i, l;
	char *p, *q;
 	

  ENTER_DEBUG("tv_out");

  status = OK;

  TRACE_ED_STR2("tv_out of: ", str, len);

  for (l = len, p = str; (l > 0) && (status); l -= i, p += i)
  {	i = terms->buf_size - terms->iw;
  	i = MIN(l, i);
	q = BUFW + terms->iw;
	terms->iw += oscopy(q, p, i);
	if (terms->iw >= terms->buf_size)  status = tv_feed();
  }

  EXIT_DEBUG(status);
}

/*==========================================================================
 *			tv_send
 *==========================================================================*/
int	tv_send(str, times)
/*++++++++++
.PURPOSE Send a sequence n times. This sequence has the encoded form
	of a capability (see tu_encode)
.RETURNS OK / NOK
.REMARKS The delay is made by sending additional padding chars.
----------*/
	char *str;	/* IN: The string to send	*/
	int  times;	/* IN: Number of times to send the string	*/
{
	int ls, n;
	int delay;

  ENTER_TV("tv_send");

#if DEBUG
	TRACE_ED_I("Sending sequence times: ", times);
#endif

  status = OK;
  if(times <= 0)   	FINISH;		/* Nothing to send ...	*/
  if(!str)		FINISH;

  ls = *str;
  if(ls == 0)    	FINISH;


  delay = compute_delay(str);	/* Delay in number of padding chars	*/

	/* Output the text in a loop	*/

  if (delay)					/* A delay is required	*/
  {	if (delay > terms->buf_size)	delay = terms->buf_size;
	oscfill(BUFS, delay, terms->pad_char);
  }
  for (n=times; --n>=0; )
  {	if (!(status = tv_out(str+4,ls)))	FINISH;
	if(delay_flag == 'D')	
		if (!(status = tv_out(BUFS,delay)))	FINISH;
  }
  if (delay_flag == 'd')
	status = tv_out(BUFS,delay);

  EXIT_TV(status);
}

/*==========================================================================
 *			tv_wms(ms)
 *==========================================================================*/
int	tv_wms(ms)
/*++++++
.PURPOSE Simulate a waiting time (by sending padding chars)
.RETURNS OK 
.REMARKS Send directly the padding chars to terminal (no buffering)
------------*/
	short unsigned int  ms;	/* IN: Number of ms waiting time to simulate */
{
	register int delay, n;

  ENTER("tv_wms");

  if (terms->term_type)		FINISH;		/* No terminal		*/

  delay = (int)ms_to_pad(ms);

  oscfill(BUFS, MIN(delay, terms->buf_size), terms->pad_char);

  status = 0;
  while ( (delay > 0) && (status >= 0) )
  {	n = MIN(delay, terms->buf_size);
	status = ostwrite(BUFS, n);
	delay -= n;
  }
  if (status < 0)	ERROR(osmsg());

  FIN:
  EXIT(OK);
}
