/*===========================================================================
  Copyright (C) 1989-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
===========================================================================*/

/*++++++++++++++
.NAME		tform.c
.TYPE           Module
.LANGUAGE       C
.KEYWORDS	Forms
.ENVIRONMENT    TermWindows
.AUTHOR		Alan Richmond, Francois Ochsenbein 
.COMMENTS
	This module contains the basic operations on Forms:
	creation, destruction, retrieval, remove.
.VERSION 1.0 	07-Jun-1989: Extracted from Proteus.

 090902         last modif
------------------*/

#define	PM_LEVEL	LEVEL_TF

#define  PASCAL_DEF	0	/* Don't include Pascalisation 	*/

#include <stesodef.h>	/* Standard definitions	*/
#include <tform.h>	/* for form values	*/
#include <str.h>	/* String utilities	*/


extern int pm_enter(), pm_iexit(), pm_tr2(), pm_ed_i();
extern int pm_trace(), pm_ed_trace();

extern int tw_fill(), tw_attr(), tw_uattr(), tw_r(), tw_goto(), tw_rule();
extern int tw_st(), tw_uflag(), tw_chars(), tw_copw(), tw_flags();
extern int tw_uw(), tw_write(), tw_il(), tw_clear(), tw_dc();
extern int tw_nl(), tw_upw(), tw_uc(), tw_mvc(), tw_copy();
extern int tw_mrule(), tw_cus(), tw_gc2(), tw_close(), tw_cur();
extern int tw_home(), tw_tra(), tw_wa(), tw_agoto(), tw_mods();
extern int tw_cline(), tw_stopin(), tw_ms2(), tw_wf(), tw_awhere();
extern int tw_getc(), tw_helps(), tw_where(), tw_tr();

extern int mm_free();


static TFORM	*last_form = NULL_PTR(TFORM);	/* Start of Form Chain	*/

#define FINISH	goto FIN

/*=====================================================================*/

TFORM *tf_new(name, mfields, fw)
/*++++++++
.PURPOSE Create a new form
.REMARKS A new `standard' window is created if none was supplied.
.RETURNS The form pointer / NULL
----------*/
	char	*name;		/* IN: Form name		*/
	int	mfields;	/* IN: Max number of Fields 	*/
	WINDOW	*fw;		/* IN: The window to use	*/
{
	TFORM	*form;
	int	i;
	WINDOW	*w;

	ENTER("*tf_new");

	/* Allocate a New Window if Necessary	*/

  if_not(w = fw)
  	w = OpenWindow(name, 0, 0, 0, 0, _NORMAL_, _TITLE_, 0);

	/* Allocate a new FORM	*/
	
  i = strlen(name)  + 1;
	
  form = (TFORM *)(MEM_GET(char, sizeof(TFORM)+i));
	
  if(form)	/* Allocation is successful. Fill the FORM */
  {
	i = mfields;
  	form->name	= (char *)(form+1);
	form->mfields 	= i;	/* maximal number of available fields	*/
	form->nfields 	= 0;	/* how many fields in this form		*/
	form->ifield 	= 0;	/* index of the current field		*/
	form->options	= _FORM_TOSCREEN;
  	form->fields 	= MEM_GET(TFIELD, i);
	form->window  	= w;
	form->prev	= last_form;
	form->avalue  	= NULL_PTR(int);
	form->pgmno	= 0;		/* Parameter for compute_fct	*/
	form->pgmcheck	= 0;		/* Parameter for check_fct	*/
	form->compute_fct = NULL_FCT(int);
	form->check_fct = NULL_FCT(int);
	form->afileno	= -1;	/* File Number for ASCII file		*/
	form->bfileno	= -1;	/* File Number for ASCII file		*/
	form->acount	= 0;	/* Records written onto ASCII file	*/
	form->bcount	= 0;	/* Records written onto ASCII file	*/

  	strcopy(form->name, name);
	last_form = form;		/* Chain of FORM structures	*/
  }
  EnableArrows(w);			/* Allow Arrows to Stop		*/

  EXIT_PTR(TFORM, form);
}

/*=====================================================================*/
int tf_free(form)
/*+++++++
.PURPOSE Free a Form (free allocated memory)
.REMARKS The window is NOT removed, neither destroyed.
.RETURNS OK / NOK
---------*/
	TFORM	*form;	/* IN: The form to destroy	*/
{
	TFORM	**pp;
	TFIELD	*f;
	int	i;
	
  ENTER("tf_free");

	/* Free allocated strings in fields	*/

  if(!form)	FINISH;		/* Form is NULL	*/

  TRACE_ED_STRING("Free Form: ", form->name);

  for (f = form->fields, i = form->nfields; --i >=0; f++)
  	MEM_FREE(f->string), 
  	MEM_FREE(f->note);
  
	/* Free now the TFIELD array	*/

  MEM_FREE(form->fields);

	/* Modify the links between forms: retrieve it first in chain	*/

  for (pp = &last_form; (*pp) && (*pp != form); pp = &((*pp)->prev)) ;
  if (*pp == form)	*pp = form->prev;
  
  	/* Finally free form itself	*/
  	
  MEM_FREE(form);
  
  FIN:
  EXIT(OK);
}

/*=====================================================================*/
TFORM *tf_find(name)
/*+++++++
.PURPOSE Retrieve a named form
.RETURNS The found form (NULL if not found)
.REMARKS The window is NOT removed, neither destroyed.
---------*/
	char	*name;	/* IN: The form name to retrieve */
{
	TFORM	*form;
	
  ENTER("*tf_find");

  form = NULL_PTR(TFORM);
  if(!name)	FINISH;		/* No name...	*/

  TRACE_ED_STRING("Find Form: ", name);


  for (form = last_form; form; form = form->prev) 
  	if (strcomp(name, form->name) == 0)	break;
  
  FIN:
  EXIT_PTR(TFORM, form);
}

/*=====================================================================*/
TFORM *tf_next(form)
/*+++++++
.PURPOSE Retrieve the next form 
.RETURNS The following FORM.
.REMARKS The chain of forms is REVERSE, i.e. from most recently created to
	oldest.
---------*/
	TFORM	*form;	/* IN: The current form */
{
  return (form ? form->prev : last_form);
}

/*=====================================================================*/
int tf_raise(form)
/*+++++++
.PURPOSE Raise the Form to screen
.RETURNS OK / NOK
.REMARKS 
---------*/
	TFORM	*form;	/* IN: The form to raise */
{
  return(RaiseWindow(form->window));
}

/*=====================================================================*/
int tf_active(form, what_to_do)
/*+++++++
.PURPOSE Raise the Form to screen
.RETURNS The previous Form active status.
.REMARKS 
---------*/
	TFORM	*form;		/* IN: The form to raise */
	int	what_to_do;	/* IN: Zero to Deactive, 1 to Active */
{
	int	old_flag;

  old_flag = tw_st(form->window, Echo, what_to_do);
  if (what_to_do)	TouchWindow(form->window);

  return(old_flag);
}

/*=====================================================================*/
int tf_remove(form)
/*+++++++
.PURPOSE Remove the Form from screen
.RETURNS OK / NOK
.REMARKS 
---------*/
	TFORM	*form;	/* IN: The form to remove */
{
  return(RemoveWindow(form->window));
}

/*=====================================================================*/
int tf_oclear(form, mask)
/*++++++++++++
.PURPOSE Clear options in form
.RETURNS Number of fields.
------------------------------------------------------------------------*/
	TFORM	*form;	/* IN: The form concerned	*/
	int	mask;	/* IN: The mask	*/
{
	int	i;
	TFIELD	*field;

  for (i = form->nfields, field = form->fields; --i >= 0; field++)
	field->options &= ~mask;

  return (form->nfields);
}

/*=====================================================================*/
int tf_opwd(form, mask)
/*++++++++++++
.PURPOSE Clear options in form for non-echo (Password) Fields
.RETURNS Number of non-echo fields.
------------------------------------------------------------------------*/
	TFORM	*form;	/* IN: The form concerned	*/
	int	mask;	/* IN: The mask	*/
{
	int	i, count;
	TFIELD	*field;

  for (count = 0, i = form->nfields, field = form->fields; --i >= 0; field++)
  {
  	if(field->options & _FIELD_NOECHO)  
  		count++, field->options &= ~mask;
  }

  return (count);
}

/*=====================================================================*/
int tf_oset(form, mask)
/*++++++++++++
.PURPOSE Set options in form
.RETURNS Number of fields.
.REMARKS 
------------------------------------------------------------------------*/
	TFORM	*form;	/* IN: The form concerned	*/
	int	mask;	/* IN: The mask	*/
{
	int	i;
	TFIELD	*field;

  for (i = form->nfields, field = form->fields; --i >= 0; field++)
  	field->options |= mask;

  return (form->nfields);
}

/*=====================================================================*/
TF_FCT tf_fset(form, fct)
/*++++++++++++
.PURPOSE Implement the Compute function.
.RETURNS Previous Compute function.
------------------------------------------------------------------------*/
	TFORM	*form;	/* IN: The form concerned	*/
	TF_FCT fct;	/* IN: The new compute function	*/
{
	TF_FCT old;

  old = form->compute_fct;
  form->compute_fct = fct;
  
  return (old);
}

/*=====================================================================*/
TF_CHECK tf_cfset(form, fct)
/*++++++++++++
.PURPOSE Implement the Check function.
.RETURNS Previous Compute function.
.REMARK  The check function has arguments w, str, size.
------------------------------------------------------------------------*/
	TFORM	*form;		/* IN: The form concerned	*/
	TF_CHECK fct;		/* IN: The new compute function	*/
{
	TF_CHECK old;

  old = form->check_fct;
  form->check_fct = fct;
  
  return (old);
}

