/*===========================================================================
  Copyright (C) 1995-2005 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 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence 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
===========================================================================*/

/* ----------------------------------------------------------------- */
/* ---------  III -------------------------------------------------- */
/* ----------------------------------------------------------------- */

/* file III.C : contains the following routines
*
*   IIIENI_C      : Enable Interaction;
*   IIISTI_C      : Stop Interaction;
*   IIIEIW_C      : Execute Interaction & Wait;
*   IIIGLD_C      : get Locator Displacement;
*   IIIGLE_C      : get Logical Evaluator;
*   IIIGSE_C      : get String Evaluator;
*   IIIGCE_C      : get (single) Character Evaluator ;
*                   - this is an extension of the IDIs !!
*
* 
*   version 2.2  890612    KB
  
 051012		last modif

*/

# include    <idi.h>             
# include    <idistruct.h>
# include    <proto_idi.h>

# include    <stdio.h>


extern int osawrite();

static char evchar[12];

static INTER_DATA  *intdata;
static LOCATOR     *loca;

/*

*/

/************************************************************************
* IIIENI_C routine : enable interaction                                 *
*                                                                       *
* synopsis   IIIENI_C (display , intype , intid , objtype , objid ,     *
*                      oper , trigger);                                 *
*                                                                       *
*       int   display;      input   display identifier                  *
*       int   intype;       input   interactor type                     *
*       int   intid;        input   interactor id                       *
*       int   objtype;      input   object type                         *
*       int   objid;        input   object id                           *
*       int   oper;         input   interactive operation               *
*       int   trigger;      input   exit trigger                        *
************************************************************************/

int IIIENI_C (display, intype, intid, objtype, objid, oper, trigger)

int  intype , objtype , oper;
int  display , intid , objid , trigger;

{
int  noint;


if (ididev[display].opened == 0) return(DEVNOTOP);
noint = ididev[display].n_inter;


/* check exit trigger with  previous enabled interactions           */

if ((noint > 0) && (trigger != ididev[display].trigger))
   return(ILLTRIGGER);


/* check max number of enabled interactions */

if (noint == MAX_INTER)
   {
   (void) printf("max_inter = MAX_INTER, n_inter = %d\n",noint);
   return(MAXNOINT);
   }

intdata = ididev[display].inter[noint];
intdata->inttype = intype;
intdata->intid = intid;

switch (intype)
   {
   case II_LOC:
      if ((intid>= 0) && (intid < intdevtable[display].nloc))
         intdata->interactor = intdevtable[display].loc[intid]->interactor;
      else
         return(ILLINTTYPE);
      break;
   
   case II_TRG:
      if ((intid>= 0) && (intid < intdevtable[display].ntrig))
         {
         intdata->interactor = intdevtable[display].trig[intid]->interactor;
         intdevtable[display].trig[intid]->def = II_TRG;
         }
      else
         return(ILLINTTYPE);
      break;
   
   case II_EVLC:
      if ((intid>= 0) && (intid < intdevtable[display].ntrig))
         {
         intdata->interactor = intdevtable[display].trig[intid]->interactor;
         intdevtable[display].trig[intid]->def = II_EVLC;
         }
      else
         return(ILLINTTYPE);
      break;

   default:
      return(ILLINTTYPE);
   }


intdata->objtype =  objtype;
intdata->objid = objid;

switch (objtype)
   {
   case II_NULL:
   case II_CURSOR:
   case II_ROI:
      break;
  
   default:
      return(ILLINTOBJ);
   }

switch (oper)
   {
   case II_USER:
   case II_MOVE:
   case II_MODIFY:
      intdata->oper = oper;
      break;
  
    default:
      return(ILLINTOPER);
   }

ididev[display].trigger  = trigger;
ididev[display].n_inter ++;

return(II_SUCCESS);
}

/*

*/

/************************************************************************
* IIISTI_C routine : stop interaction                                   *
*                                                                       *
* synopsis   IIISTI_C (display);                                        *
*                                                                       *
*       int   display;      input   display identifier                  *
************************************************************************/

int IIISTI_C (display)

int  display;

{
if (ididev[display].opened == 0) return(DEVNOTOP);

ididev[display].n_inter = 0;
int_disable (display);
                
return(II_SUCCESS);
}

/*

*/

/************************************************************************
* IIIEIW_C routine : execute interaction & wait                         *
*                                                                       *
* synopsis   IIIEIW_C (display , trgstatus);                            *
*                                                                       *
*       int   display;      input   display identifier                  *
*       int   trgstatus[];  output  output trigger status               *
************************************************************************/

int IIIEIW_C (display , trgstatus)
int display , trgstatus[MAX_TRG];

{
int  i, trgflg, exitflg, trgno, userstatus;
int  evdata, evtype, evpos[2];




if (ididev[display].opened == 0) return(DEVNOTOP);


/* check if any interaction has been enabled */

if (ididev[display].n_inter == 0) return(INTNOEN);

int_enable (display);			 /* enable interactive ididevs */
exit_trg_enable (display);		 /* Exit trigger enable */

userstatus = 0;
exitflg = 0;

set_wcur(display,0);	
for (i = 0; i < MAX_TRG; i++)		 /* zero trigger status array */
   trgstatus[i] = 0;


/* loop on enabled interactions 
   wait until exit trigger is fired  or some USER interaction is verified    */

waiting_loop:
if (auto_cursor_fid > 0)
   send_event(display);			/* if AUTO_CURSOR => an event */
wait_int (display,&evtype,&evdata,evchar,evpos);


/* loop on multiple enabled interactions */

for (i=0; i<ididev[display].n_inter; i++)
   { 
   intdata = ididev[display].inter[i];
   if (intdata->inttype == II_LOC)
      {
      if (intdata->objtype == II_CURSOR)
         {
         if (intdata->oper == II_MOVE)
            curmove(display,intdata->objid,intdata->intid,evdata,evpos);
         }
      
      else if (intdata->objtype == II_ROI)
         {
         if (intdata->oper == II_MOVE)
            roimove(display,intdata->intid,evpos);
         else if (intdata->oper == II_MODIFY)
            {
            loc_mod(display,intdata->intid,evdata);
            roimodify(display,intdata->intid);
            }
         }
      
      else 
         loc_mod(display,intdata->intid,evdata);
      }

   else if ((intdata->inttype == II_TRG) || (intdata->inttype == II_EVLC))
      {
      trgno = intdata->intid;
      trgflg = trigsta(display,trgno,evtype,evdata,evchar);
      if (trgflg == 1) trgstatus[trgno] = 1;
      }
  
   if (intdata->oper == II_USER) 		  /* look for user option  */
      userstatus = 1;
   }
   

/* check, if we are in record_cursor mode */

if (record_cursor_fid > 0)              /* record all cursor/key input */
   {
   int  do_store, fpos[2];
   char  cbuf[40];

   do_store = 0;
   if ((evtype == 4) && (evdata == 1))		/* mouse button event */
      {
      do_store = 1;
      fpos[0] = evpos[0] + 2;			/* because of epsi2 ... */
      fpos[1] = ididev[display].ysize - evpos[1] + 1;
      (void) sprintf(cbuf,"1,%d,%d",fpos[0],fpos[1]);
      }

   else if (evtype == 2)			/* keyboard event */
      {
      do_store = 1;
      if (evdata == -5)			/* check for RETURN key */
         {
         fpos[0] = evpos[0] + 2;
         fpos[1] = ididev[display].ysize - evpos[1] + 1;
         (void) sprintf(cbuf,"1,%d,%d",fpos[0],fpos[1]);
         }
      else
         (void) sprintf(cbuf,"2,%d",evdata);
      }

   if (do_store == 1)
      (void) osawrite(record_cursor_fid,cbuf,(int)strlen(cbuf));
   }

   
/*  test the exit trigger  */
  
trgno = ididev[display].trigger;
trgflg = trigsta(display,trgno,evtype,evdata,evchar);
if (trgflg == 1) 
   {
   trgstatus[trgno] = 1;
   exitflg = 1;
   set_wcur(display,1);			/* let window cursor show the end  */
  
   if (record_cursor_fid > 0)		/* record also exit button */
      (void) osawrite(record_cursor_fid,"0",1);
   }

if ((userstatus != 1) && (exitflg != 1))
   goto waiting_loop;

return(II_SUCCESS);
}

/*

*/

/************************************************************************
* IIIGLE_C routine : Get logical Evaluator
*                                                                       *
* synopsis   IIIGLE (display, evalno, cbuf)
*                                                                       *
*       int   display;      input   display identifier                  *
*       int   evalno;       input   evaluator no.                       *
*             < 0, wait for char. from keyboard,                        *
*             = 0, use character from interrupt before                  *
*       int  *cbuf;        output  logical				*
************************************************************************/

int IIIGLE_C (display,evalno,cbuf)
int   display, evalno;
int  *cbuf;

{
if (ididev[display].opened == 0) return(DEVNOTOP);

/*  just a dummy stub routine for now  */


return(II_SUCCESS);
}



/************************************************************************
* IIIGCE_C routine : Get character Evaluator
*                                                                       *
* synopsis   IIICSE (display, evalno, cbuf)
*                                                                       *
*       int   display;      input   display identifier                  *
*       int   evalno;       input   evaluator no.                       *
*             < 0, wait for char. from keyboard,                        *
*             = 0, use character from interrupt before                  *
*       char  *cbuf;        output  character                           *
************************************************************************/

int IIIGCE_C (display,evalno,cbuf)
int   display, evalno;
char  *cbuf;

{
if (ididev[display].opened == 0) return(DEVNOTOP);

if (evalno < 0)
   get_char(display,cbuf);
else
   *cbuf = evchar[0];

return(II_SUCCESS);
}

/*

*/

/************************************************************************
* IIIGSE_C routine : Get String Evaluator
*                                                                       *
* synopsis   IIIGSE (display, evalno, cbuf, lcbuf)
*                                                                       *
*       int   display;      input   display identifier                  *
*       int   evalno;       input   evaluator no. (not used...)         *
*       char  *cbuf;        output  character string                    *
*       int   *lcbuf;       output  length of above                     *
************************************************************************/

int IIIGSE_C (display, evalno, cbuf, lcbuf)
int   display, evalno, *lcbuf;
char  *cbuf;

{
if (ididev[display].opened == 0)
   return(DEVNOTOP);
else
   {
   get_string(display,cbuf,lcbuf);
   return(II_SUCCESS);
   }
}


/************************************************************************
* IIIGLD_C routine : Get Locator Displacement                           *
*                                                                       *
* synopsis   IIIGLD_C (display , locn , xdis , ydis);                   *
*                                                                       *
*       int   display;      input   display identifier                  *
*       int   locn;         input   locator number                      *
*       int   *xdis;        output  X displacement                      *
*       int   *ydis;        output  Y displacement                      *
************************************************************************/

int IIIGLD_C(display,locn,xdis,ydis)
int   display , locn , *xdis , *ydis;

{
if (ididev[display].opened == 0) return(DEVNOTOP);
   
loca = intdevtable[display].loc[locn];

*xdis = loca->xdif * 3;
*ydis = loca->ydif * 3;
 
loca->xdif = 0;
loca->ydif = 0;

return(II_SUCCESS);
}
