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

/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

.IDENTIFICATION
  function Ccursin			version 1.00	860217
  K. Banse				ESO - Garching

.KEYWORDS
  Image display , cursor positions

.PURPOSE
  pick up the image memory pixels of the two cursors on the screen

.ALGORITHM
  use IDI routines to bind cursors + read them
  write ima_mem_pixels to keyword CURSOR(1,..,4)

.VERSIONS

 090706		last modif
-------------------------------------------------------------------------- */

#include <midas_def.h>
#include <idinumd.h>
#include <proto_II.h>

static int  oldchan;

/*
 * first the local functions Rdcur and Rdwin
 */

/*++++++++++++++++++++++++++++

.IDENTIFICATION: 
  function Rdcur  
           Rdwin

.PURPOSE: 
  read screen coordinates at cursor position 
  and convert to image memory coordinates 

.ALGORITHM: 
  Get all relevant values from DAZMEMI + do it 


.VERSIONS
  1.10            write raw screen coords. of cursor into keyword CURSOR 
  1.20            take care of channels with no image loaded... 
  1.30            use SCTOCH (ScreenToChannel) instead of SCRLIM

------------------------------------------------------------------- */

#ifdef __STDC__
      static void Rdcur( int dsplay, int cursno, int *chan, int *xy, int *sxy )
#else
      static void Rdcur(dsplay,cursno,chan,xy,sxy)

      int  dsplay;		/* IN: display no. */
      int  cursno;		/* IN: cursor no. 0 or 1 */
      int  *chan;		/* OUT: image channel (memory) in use */
      int  *xy;			/* OUT: x,y coord of image memory */
      int  *sxy;		/* OUT: x,y screen coords */
#endif

{
int   stat = 0;


(void) IICRCP_C(dsplay,-1,cursno,xy,&xy[1],chan);
*sxy++ = xy[0];					/* pure screen coords. */
*sxy = xy[1];

if (oldchan != *chan)
   {
   oldchan = *chan;
   stat = DCGICH(oldchan);
   }

if (stat != 0)     
   xy[1] = QMSZY - QDSZY + xy[1];                /* xy[0] already o.k. */
else
   Sc2ch(1,xy,xy+1);

return;
}

/*

*/

#ifdef __STDC__
      static void Rdwin( int dsplay, int roiflg,
                         int *chan, int *xya, int *xyb, int *sxya, int *sxyb )
#else
      static void Rdwin(dsplay,roiflg,chan,xya,xyb,sxya,sxyb)

      int  dsplay;            /* IN: display no. */
      int  roiflg;            /* IN: rectangular (= 2) or circular ROI */
      int  *chan;             /* OUT: image channel (memory) in use */
      int  *xya;              /* OUT: x,y coord of image memory */
      int  *xyb;              /* OUT: x,y coord of image memory */
      int  *sxya;             /* OUT: x,y screen coords */
      int  *sxyb;             /* OUT: x,y screen coords */
#endif
{
int   stat = 0;


if (roiflg == 2)     
   (void) IIRRRI_C(dsplay,-1,0,xya,&xya[1],xyb,&xyb[1],chan);
else
   (void) IICRRI_C(dsplay,-1,0,xya,&xya[1],xyb,&xyb[1],&xyb[2],chan);

*sxya++ = xya[0];				/* pure screen coords. */
*sxya = xya[1];
*sxyb++ = xyb[0];
*sxyb = xyb[1];

if (oldchan != *chan)
   {
   oldchan = *chan;
   stat =  DCGICH(oldchan);
   }

if (stat != 0)     
   {
   xya[1] = QMSZY - QDSZY + xya[1];                   /* xya[0] already o.k. */
   if (roiflg == 2) xyb[1] = QMSZY - QDSZY + xyb[1];  /* xyb[0] already o.k. */
   }
else
   {
   Sc2ch(1,xya,xya+1);
   if (roiflg == 2) Sc2ch(1,xyb,xyb+1);
   }

return;
}

/*

*/

void Ccursin(dsplay,iact,nocurs,xya,isca,xyb,iscb)

int dsplay;		/* IN: display no.  */
int iact;		/* IN: action flag, 
                           -1 = as 0 but also enable arrow keys
                           0 = setup cursor binding, enable keyboard input
                           1 = get cursor position on ENTER only
                           2 = get cursor position each time we poll
                           in that case, ISCi = -1 if ENTER was pressed */
int nocurs;		/* IN: cursor no. = 0,1 for cursor #1 and #2,
                               2 for rectangle ROI,
                               3 for both cursors individually,
                               12 for circle  ROI  */

int *xya;		/* OUT: x,y position in image channel of cursor 0
			        + memory boards for cursor 0 
				+ x,y screen coordinates  (so 5 elements) */
int *isca;		/* OUT: status of cursor 0 (0/1 for off/on)
                                or = -9, if ISCB contains info about arrow key
                                     or keys 0, ..., 9 or special keys  */
int *xyb;		/* OUT: x,y position in image channel of cursor 1
			        + memory boards for cursor 1 
				+ x,y screen coordinates */
int *iscb;		/* OUT: status of cursor 1 (0/1 for off/on)
                                if ISCA = -9, holds info about key pressed */


{
      
int iav;
int intaty, intaid, intaop, objty, objid;
int mca, mcb, trgsta[10];

char cbuf[4];

static int  enttrg = 1;     /* trigger no 1 for enter trigger  */
static int  exetrg = 2;     /* trigger no 2 for execute trigger  */
static int  exttrg = 0;     /* trigger no 0 for exit trigger  */

static char nokeys[] = {"0123456789"};
 


*isca = 0;
*iscb = 0;
if (iact > 0) goto sect_1000;


/*  ********************************************* */

/*  IACT = -1 or 0,  bind cursor movement to EXIT trigger */

/*  ********************************************* */
 
oldchan = -1;

intaty = 0;                          /* interactor type = 0 for locator */
intaid = 0;                          /* id = 0 of locator */
intaop = 1;                          /* interactive operation = 1 for move */
if (nocurs < 2)      
   {
   objty = 1;                        /* object type = cursor */
   objid = nocurs;
   (void) IIIENI_C(dsplay,intaty,intaid,objty,objid,intaop,exttrg);
   }


/*  bind locator 0, id 0 to movements of ROI */

else if ((nocurs == 2) || (nocurs == 12))     
   {
   objty = 4;                        /* object type = roi */
   objid = 0;
   (void) IIIENI_C(dsplay,intaty,intaid,objty,objid,intaop,exttrg);

/*  and bind locator 0, id 1 to modifications of size of ROI */

   intaid = 1;                       /* use id = 1 of locator */
   intaop = 7;                       /* int. operation = 7 for modify */
   (void) IIIENI_C(dsplay,intaty,intaid,objty,objid,intaop,exttrg);
   }


/*  bind cursor 0 and 1 independently */

else
   {
   objty = 1;                        /* object type = cursor */
   objid = 0;
   (void) IIIENI_C(dsplay,intaty,intaid,objty,objid,intaop,exttrg);
   intaid = 1;
   objid = 1;
   (void) IIIENI_C(dsplay,intaty,intaid,objty,objid,intaop,exttrg);
   }


/*  bind ENTER button (trigger) to EXIT trigger as well */

intaty = 5;                       /* interactor type = 5 for trigger */
intaid = enttrg;                  /* id = 1, for trigger 1 (enter button) */
intaop = 0;                       /* inter. operation = 0 for applic spec. */
objid = 0;
objty = 0;                           /* object type = 0, no visible effect */
(void) IIIENI_C(dsplay,intaty,intaid,objty,objid,intaop,exttrg);


/*  also bind EXECUTE trigger to EXIT trigger as well */

intaid = exetrg;                  /* id = 2, for trigger 2 (execute button) */
(void) IIIENI_C(dsplay,intaty,intaid,objty,objid,intaop,exttrg);


/*  if IACT = -1, bind triggers for arrow keys (L,R,D,U)  */
 
if (iact < 0)     
   {
   for (intaid=4; intaid<8; intaid++)
      {
      (void) IIIENI_C(dsplay,intaty,intaid,objty,objid,intaop, exttrg) ;
      }

/*  finally bind trigger for special keys h, z, x, c, b, m */

   intaty = 4;                       /* interactor type = 4 for char. eval. */
   intaid = 8;
   (void) IIIENI_C(dsplay,intaty,intaid,objty,objid,intaop, exttrg);
   }

return;

/*  ********************************************* */

/*  here for IACT = 1,2 */

/*  ********************************************* */
 
sect_1000:
(void) IIIEIW_C(dsplay,trgsta);

 
/*  if EXIT trigger fired - we terminate the interaction + return  */

if (trgsta[0] == 1)     
   {
   (void) IIISTI_C(dsplay);
   return;                               /* exit trigger 0 is in trgsta[1] */
   }


/*  look for arrow keys */

for (iav=4; iav<8; iav++)
   {
   if (trgsta[iav] == 1)     
      {
      *isca = -8;
      *iscb = iav - 8;                    /* map to -4, -3, -2, -1 */
      return;
      }
   }

if (trgsta[8] == 1)     
   {
   (void) IIIGCE_C(dsplay,0,cbuf);      /* get character */
   if ((cbuf[0] >= 'a') && (cbuf[0] <= 'z'))
      {					/* return lower case chars directly */
      *isca = -9;
      *iscb = (int) cbuf[0];
      return;              
      }

   for (iav=0; iav<10; iav++)
      {
      if (cbuf[0] == nokeys[iav])     
         {
         *isca = -8;
         *iscb = iav + 1;                 /* map 0,1,2,...,9 */
         return;                         /* to  1,2,3,...,10 */
         }
      }
   }

if (iact == 1)                           /* loop, if no enter pushed */
   {
   if ( (trgsta[1] == 0) && (trgsta[2] == 0) ) goto sect_1000 ;
   }
 

/*  get channel involved and image pixels at cursor location */

if (nocurs == 0)     
   {
   *isca = 1;
   (void) Rdcur(dsplay,0,&mca,xya,&xya[3]);
   xya[2] = mca;
   }
else if (nocurs == 1)     
   {
   *iscb = 1;
   (void) Rdcur(dsplay,1,&mcb,xyb,&xyb[3]);
   xyb[2] = mcb;
   }
else if (nocurs == 2)     
   {
   *isca = 1;
   *iscb = 1;
   (void) Rdwin(dsplay,nocurs,&mca,xya,xyb,&xya[3],&xyb[3]);
   xya[2] = mca;
   xyb[2] = mca;
   }
else if (nocurs == 12)     
   {
   *isca = 1;
   *iscb = 1;
   (void) Rdwin(dsplay,nocurs,&mca,xya,xyb,&xya[3],&xyb[3]);
   xya[2] = mca;
   }
else
   {
   *isca = 1;
   *iscb = 1;
   (void) Rdcur(dsplay,0,&mca,xya,&xya[3]);
   (void) Rdcur(dsplay,1,&mcb,xyb,&xyb[3]);
   xya[2] = mca;
   xyb[2] = mcb;
   }

if (trgsta[2] == 1)                     /* show, that execute pushed */
   {
   *isca = -2;
   *iscb = -2;
   }

if (trgsta[1] == 1)                     /* show, that enter pushed */
   {
   *isca = -1;
   *iscb = -1;
   }
 
}
