/*===========================================================================
  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           tfcc.c
.TYPE		Module
.LANGUAGE       C
.CATEGORY       User interface, forms handling.
.ENVIRONMENT    TermWindows
.AUTHOR		Alan Richmond, Francois Ochsenbein
.VERSION  1.0	08-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 <cc.h>		/* for Ccode compilation*/


extern int cc_exec(), cc_ext(), cc_fct(), cc_glb(), cc_compile();

extern int eh_put1();



/*======================================================================*/
static int tfexec(form)
/*+++++++++++
.PURPOSE Routine called to derive Computed fields.
.RETURNS OK.
-------------*/
	TFORM	*form;		/* IN: The Form	*/
{
  return(cc_Execute(form->pgmno));
}

/*======================================================================*/
static int check(form, str, size)
/*+++++++++++
.PURPOSE Routine called to derive Computed fields.
.RETURNS OK.
-------------*/
	TFORM	*form;		/* IN: The Form	*/
	char	*str;		/* IN: Input String */
	int	size;		/* IN: Input String Size */
{
  return(cc_Execute(form->pgmcheck));
}

/*======================================================================*/
static int err(msg)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Error Function
.RETURNS NOK.
------------------------------------------------------------------------*/
	char	*msg;		/* IN: The Message	*/
{
  ERROR(msg);
  return(NOK);
}

/*======================================================================*/
static int isnull(addr)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Check if a Number is Null
.RETURNS 0 (false) / 1 (true)
------------------------------------------------------------------------*/
	long	addr[2];	/* IN: The Message	*/
{
	char	*x;
	int	result;

  result = 0;		/* FALSE = is NOT null	*/

  x = (char *)addr - sizeof(addr) - sizeof(short) - sizeof(char);
  if ((*x & 0xf) == _DTYPE_INT)	result = (addr[0] == addr[1]);

  return(result);
}

/*======================================================================*/
static int tonull(addr)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Set a number to NULL
.RETURNS 0 (bad) / 1 (done)
------------------------------------------------------------------------*/
	long	addr[2];	/* IN: The Message	*/
{
	char	*x;
	int	result;

  result = 0;		/* FALSE = is NOT null	*/

  x = (char *)addr - sizeof(addr) - sizeof(short) - sizeof(char);
  if ((*x & 0xf) == _DTYPE_INT)	
	addr[0] = addr[1],
  	result = 1;

  return(result);
}

/*======================================================================*/
static int ccbind(form)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Bind variables for Ccode
.RETURNS NOK.
------------------------------------------------------------------------*/
	TFORM	*form;			/* IN: The form Concerned	*/
{
	int	i;
	TFIELD	*field;

  cc_BindAddress("int $", &(form->avalue));
  cc_BindFunction("int ERROR",  1, err);
  cc_BindFunction("int isnull", 1, isnull);
  cc_BindFunction("int tonull", 1, tonull);

  for (i = form->nfields, field = form->fields; --i >=0; field++) 
  {	if (field->string_size == 0)	continue;
	switch(field->type & 7) 
	{
		case _DTYPE_INT:
	   		cc_BindInteger(field->name,field->value.integer);
	   		break;
		case _DTYPE_DOUBLE: case _DTYPE_FLOAT:
	   		cc_BindDouble(field->name,field->value.real);
	   		break;
	   	default:	/* Strings */
	   		cc_BindString(field->name, field->string);
	   		break;
	}		
  }

  return(OK);
}

/*======================================================================*/
int tf_cc(form, source, exe_hook)
/*+++++++++++
.PURPOSE Compile source code if any.
.RETURNS The program number (0 when error).
.REMARKS If other variables than those specified in the Form are necessary,
	use BEFORE the call to tf_cc the cc_BindInteger / cc_BindDouble /
	cc_BindString / cc_BindFunction (see cc.h)
-------------*/
	TFORM	*form;		/* MOD: The form Concerned	*/
	char	*source;	/* IN: Code to compile 		*/
	int	exe_hook;	/* IN: 0 for Compute / 1 for Check	*/
{
	int	ret;

  if(source)	ccbind(form),	/* Bind Variables 	*/
  		ret = cc_Compile(source);
  else		ret = 0;
	
  if(ret)	
  {	if (exe_hook)	form->check_fct   = check,  form->pgmcheck = ret;
  	else		form->compute_fct = tfexec, form->pgmno    = ret;
  }

  return(ret);
}

