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

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENTIFIER  module drawinput
.LANGUAGE    C
.AUTHOR      K. Banse			IPG-ESO Garching
.KEYWORDS    
.COMMENTS    holds routines: FIXP_INP, KEYW_INP, CURS_INP & TABL_INP

.ENVIRONment MIDAS
             #include <midas_def.h>   Prototypes for MIDAS interfaces
             #include <idinumd.h>     Global variables for DISPLAY interfaces
 
.VERSIONS    1.00       940712  from DRAW.FOR    R.M. van Hees

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

/* Define _POSIX_SOURCE to indicate that this is a POSIX program */

#define  _POSIX_SOURCE 1

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

#ifndef TRUE
#define TRUE            1
#define FALSE           0
#endif

#define MAXDIM		4

int XConvcoo();



/*

*/

/*++++++++++++++++++++++++++++++
.IDENTIFIER  FIXP_INP
.PURPOSE     handle fixed position
.INPUT/OUTPUT
  input:
             char *shape   :		shape, e.g. 'CI'
             char *ref     :		'S'creen or 'F'rame coordinates
             char *coord   :		coordinate string (*ref == 'S')
             char *frame   :            input frame       (*ref == 'F')
             int  ncurs    :		number of cursors
  output:
             float cpos[4] :            position in screen coordinates

.RETURNS     nothing
------------------------------*/

#ifdef __STDC__
      void FIXP_INP(char *shape, char *ref, char *coord, char *frame,
                    int ncurs, float *cpos)
#else
      void FIXP_INP(shape, ref, coord, frame, ncurs, cpos)
      char  *shape, *ref, *coord, *frame;
      int   ncurs;
      float *cpos;
#endif

{
int    idum;

double  ddum;




/* take care of screen (easy) or frame (tough) coordinates */

if (*ref == 'S')     			/* we use screen coords/pixels */
   {
   int    isw, iv[2], kk, n, lstart, ncoord, lc;
   float  rbuf[4], rval;
   char   mybuf[44];


   /* number of coordinates needed */

   iv[0] = QDSZX - 1;
   iv[1] = QDSZY - 1;
   isw = 0;
   ncoord = ncurs + 2;
   lstart = 0;
   lc = (int)strlen(coord);


   for (n=0; n<ncoord; n++)
      {
      if (CGN_EXTRSS(coord,lc,',',&lstart,mybuf,40) < 1)
         {
         if ((shape[0] == 'C') && (shape[1] == 'I') && 
             (ncoord == 4) && (n == 3))
            {
            shape[3] = '3';
            if (cpos[2] < 1.0) cpos[2] = 1.0;	/* radius at least 1 pixel */
            return;
            }
         else
            SCETER(2,"FIXP_INP: not enough coordinates for shape...");
         }

      if (CGN_CNVT(mybuf,2,1,&idum,&rval,&ddum) <= 0)
         SCETER(1,"FIXP_INP: invalid syntax in screen coord. string...");

      kk = CGN_INDEXC(mybuf,'.');
      if (kk > -1)			/* float value */
         rbuf[n] = rval*iv[isw];
      else
         rbuf[n] = rval;

      cpos[n] = rbuf[n];
      isw = 1 - isw;
      } 

   if (ncurs != 2)     				/* single cursor */
      {
      cpos[2] = cpos[0];
      cpos[3] = cpos[1];
      }
   }

else                                                    /* get frame coords. */
   {
   int   actvals, indx, mm, knul, unit, imno, stat;
   int   npix[MAXDIM];

   char  cbuff[80], cbufff[32], output[84];

   float rdum, sublo[MAXDIM], subhi[MAXDIM];

   double  dd1[MAXDIM], dd2[MAXDIM], dd3[MAXDIM];


   (void) sprintf(output, "frame %s used for reference", frame );
   SCTPUT(output);
   imno = -1;
   (void) SCFOPN(frame,D_R4_FORMAT,0,1,&imno );
   (void) SCDRDI(imno,"NPIX",1,MAXDIM,&actvals,npix,&unit,&knul);
   if (Pixconv("INIT",imno,dd1,dd2,dd3) > 0)       /* init wc conversion */
      SCETER(69,"initialization of world coord. conversion failed ...");

   indx = 0;
   if (CGN_EXTRSS(coord,60,',',&indx,cbuff,30) <= 0)
      SCETER( 5, "FIXP_INP: not enough coordinates for shape..." );
   if (CGN_EXTRSS(coord,60,',',&indx,cbufff,30) <= 0)
      SCETER( 6, "FIXP_INP: not enough coordinates for shape..." );

   (void) strcat(cbuff,",");
   (void) strcat(cbuff,cbufff);
   stat = XConvcoo(0,imno,cbuff,2,&mm,sublo,subhi);
   if (stat != 0)
      SCETER(9,"FIXP_INP: invalid coordinates for shape..." );
   dd1[0] = (double) (sublo[0]+1);	/* Pixconv expects Fortran indices */
   dd1[1] = (double) (sublo[1]+1);
   dd1[2] = ZPLANE;


   /* convert cursor1 to screen pixels */

   if ( Pixconv("_RS",0,dd1,dd2,dd3) != 0 ) 
      SCETER(7,"FIXP_INP: error in pixel conversion - first coords.");
   else
      {
      cpos[0] = (float) dd3[0];
      cpos[1] = (float) dd3[1];
      }

   if ( ncurs != 2 )     
      {
      dd1[0] = (double) (npix[0] / 2);	   /* default to center of image */
      dd1[1] = (double) (npix[1] / 2);
      }

   else
      {
      if (CGN_EXTRSS(coord,60,',',&indx,cbuff,30) <= 0)
         SCETER(7,"FIXP_INP: not enough coordinates for shape...");

      if (CGN_EXTRSS(coord,60,',',&indx,cbufff,30) <= 0)
         {
         if ((shape[0] == 'C') && (shape[1] == 'I'))
            {
            shape[3] = '3';
            if (CGN_CNVT(cbuff,2,1,&idum,&rdum,&ddum)  <= 0)
               SCETER(5,"FIXP_INP: invalid radius spec...");

            cpos[2] = rdum;
            if (cpos[2] < 1.0) cpos[2] = 1.0;      /* radius at least 1 pixel */
            return;
            }

         SCETER(8,"FIXP_INP: not enough coordinates for shape...");
         }

      (void) strcat(cbuff,",");
      (void) strcat(cbuff,cbufff);
      if (XConvcoo(0,imno,cbuff,2,&mm,sublo,subhi) != 0)
         SCETER(9,"FIXP_INP: invalid coordinates for shape..." );

      dd1[0] = (double) (sublo[0]+1);	/* Pixconv expects Fortran indices */
      dd1[1] = (double) (sublo[1]+1);
      }


   /* convert cursor2 to screen pixels */

   if (Pixconv("_RS",0,dd1,dd2,dd3) != 0) 
      SCETER(8,"FIXP_INP: error in pixel conversion - second coords.");
   else
      {
      cpos[2] = (float) dd3[0];
      cpos[3] = (float) dd3[1];
      }
   }
}

/*

*/
      
/*++++++++++++++++++++++++++++++
.IDENTIFIER  KEYW_INP
.PURPOSE     use keyword input to retrive screen coordinates
.INPUT/OUTPUT
  input:
             char *keynm   :            name of keyword
             int  ncurs    :		number of cursors
  output:
             float cpos[4] :            position in screen coordinates

.RETURNS     status 0: there are more coordinates
                    1: finished
------------------------------*/

#ifdef __STDC__
      int KEYW_INP( char *keynm, int ncurs, float *cpos )
#else
      int KEYW_INP( keynm, ncurs, cpos )
      char  *keynm;
      int   ncurs;
      float *cpos;
#endif

{
register int nn;
int actvals, knul, unit;
static int nmal, nmax, ibuff[40], init=1;


if (init == 1)
   {
   (void) SCKRDI(keynm,1,40,&actvals,ibuff,&unit,&knul);

   nn = 0;
   while ((nn<actvals) && (ibuff[nn]>=0)) nn++;

   if ( (nmax = nn/(ncurs + 2)) < 1 )
      SCETER(1,"KEYW_INP: not enough coordinates for shape...");

   nmal = 0;
   init = 0;
   }


/* here is the loop */

if ( nmax-- <= 0 ) return (1);				/* we're finished */

cpos[0] = ibuff[nmal++];
cpos[1] = ibuff[nmal++];
if (ncurs == 2)     
   { 
   cpos[2] = ibuff[nmal++];
   cpos[3] = ibuff[nmal++];
   }
else
   {
   cpos[2] = cpos[0];
   cpos[3] = cpos[1];
   }

return (0);
}

/*

*/

/*++++++++++++++++++++++++++++++
.IDENTIFIER  CURS_INP
.PURPOSE     handle cursor input, return screen coordinates
.INPUT/OUTPUT
  input:
             char *shape   :		cursor shape
  in/output:
             int  *ncurs   :		number of cursors
  output:
             float cpos[4] :            position in screen coordinates

.RETURNS     status 0: we're not finished yet
                    1: finished
------------------------------*/

#ifdef __STDC__
      int CURS_INP( char *shape, int *ncurs, float *cpos )
#else
      int CURS_INP( shape, ncurs, cpos )
      char  *shape;
      int   *ncurs;
      float *cpos;
#endif

{
register int nn;
int  statA, statB, xyA[5], xyB[5];

char cbuff[82];

static int  cform, color, nmal, mx_curs, coord[5], 
            init = TRUE, give_info =  TRUE;
static char *info_usr = "switch cursor(s) on - next time we exit...";



if (init)
   {
   int actvals, knul, unit, dazhld[2];

   init = FALSE;
   if ( IDINUM >= 11 )
      {
      coord[0] = 100;
      coord[1] = 100;
      coord[2] = 200;
      coord[3] = 200;
      coord[4] = 0;
      }
   else
      for ( nn = 0; nn < 5; nn++ ) coord[nn] = -1;

   nmal = 0;
   (void) SCKRDI("CURSOR",1,2,&actvals,dazhld,&unit,&knul);
   mx_curs = dazhld[0];
   if (dazhld[1] < 2)
      *ncurs = 0;
   else
      *ncurs = 2;
   color = 2;				/* white */

   if ( *ncurs == 2 )
      {
      cform = 1;
      if ((shape[0] == 'C') && (shape[1] == 'I') && (IDINUM > 10))     
         {
         cform = 2;                         /* for X11 use real circle */
         coord[2] = 10;             /* default to radius of 10 pixels */
         coord[3] = 0;                           /* only inner circle */
         }
      }
   else
      {
      (void) SCKRDI("DAZHOLD",1,2,&actvals,dazhld,&unit,&knul);
      if ((dazhld[1] != -1) && (dazhld[0] == 0))
         cform = dazhld[1];
      else
         cform = 3;
      }


   /* set up cursor shape */

   SETCUR_C(QDSPNO,*ncurs,cform,color,coord); 
   Ccursin(QDSPNO,0,*ncurs,xyA,&statA,xyB,&statB);
   }



/* input cursor positions and check status */

if (++nmal > mx_curs) return (1);			/* we're finished */

(void) sprintf(cbuff," Ready for cursor input: %d                  ", nmal);
(void) SCTDIS(cbuff,99);		/* move cursor back to beginning */


C_loop:
Ccursin(QDSPNO,1,*ncurs,xyA,&statA,xyB,&statB);
if ( *ncurs < 2 ) statB = 0;

if ((statA == 0) && (statB == 0))     
   {
   if ((nmal == 1) && (give_info))
      {
      SCTPUT( info_usr );
      give_info = FALSE;
      Ccursin(QDSPNO,0,*ncurs,xyA,&statA,xyB,&statB);
      goto C_loop;
      }
   else
      {
      nmal--;
      return (1);                                   /* return EXIT */
      }
   }
 
cpos[0] = xyA[0];                       /* lower left corner... */
cpos[1] = xyA[1];
if ( *ncurs > 1 )
   {
   cpos[2] = xyB[0];                 /* upper right corner... */
   cpos[3] = xyB[1];
   }
else
   {
   cpos[2] = 0.0;
   cpos[3] = 0.0;
   }
   
return (0);
}

/*

*/

/*++++++++++++++++++++++++++++++
.IDENTIFIER  TABL_INP
.PURPOSE     handle table defined input, return screen coordinates
.INPUT/OUTPUT
  input:

.RETURNS     status 0: we still haven't read the whole table
                    1: finished
                   -1: error in pixel conversion
------------------------------*/

#ifdef __STDC__
int TABL_INP(char *table, char *frame, char *ref,
             char *shape, int *aux_flag, float *cpos, float *aux)
#else
int TABL_INP(table,frame,ref,shape,aux_flag,cpos,aux)
char *table;		/* IN: input table */
char *frame;		/* IN: input frame */
char *ref;		/* IN: 'S'creen or 'F'rame world coordinates 
				or 'P' for frame pixels */
char *shape;		/* IN: shape of drawing object */
int  *aux_flag;		/* OUT: > 0, if also auxiliary data  returned,
                                3 digits xyz, with z=0/1 if :color column, 
                                y=0/1 if :rotang column, x=0 (not used yet) */
float *cpos;		/* OUT: 4 positions in screen coordinates
				or 2 positions + radius for `CI' */
float *aux;		/* OUT: auxiliary data if *aux_flag = 1 */
#endif

{
int    null[4], selflg;
register int nn;
static int  nmal, ncol, nrow, tid, tbcol[8], init=TRUE;
static int  myaux = 0;
static int  prflag;

double  dd1[MAXDIM], dd2[MAXDIM], dd3[MAXDIM];

char   cbuff[84];
static char   pxc[4];
static char   *outlab[2][4] = { {"X_coord","Y_coord","Radius1"," "},
                                {"Xstart","Ystart","Xend","Yend"} };

static char   *outlap[2][4] = { {"X_coordpix","Y_coordpix","Radius1"," "},
                                {"Xstartpix","Ystartpix","Xendpix","Yendpix"} };



if (init)
   {
   int indx, nsort, allcol, allrow;

   init = FALSE;
   prflag = 0;
   (void) SCKRDI("MID$INFO",8,1,&allcol,&prflag,&indx,&nsort);

   tid = -1;
   (void) TCTOPN(table,F_I_MODE,&tid);

					/* get total no. of rows and column */
   (void) TCIGET(tid,&ncol,&nrow,&nsort,&allcol,&allrow);

   if ((shape[0] == 'C') && (shape[1] == 'R'))
      {
      ncol = 2;
      indx = 0;
      }
   else
      {
      ncol = 4;
      indx = 1;
      }
   for (nn=0; nn<ncol; nn++)
      {
      if (*ref == 'P')
         (void) TCLSER(tid,outlap[indx][nn],tbcol+nn);
      else
         (void) TCLSER(tid,outlab[indx][nn],tbcol+nn);
      if (tbcol[nn] == -1) 
         {
         if ((shape[0] == 'C') && (shape[1] == 'I'))
            goto try_again;
         else
            {
            if (*ref == 'P')
               (void) sprintf(cbuff,"Column with label %s not found... ",
                              outlap[indx][nn]);
            else
               (void) sprintf(cbuff,"Column with label %s not found... ",
                              outlab[indx][nn]);
            SCETER(5,cbuff);
            }
         }
      }
   if ((shape[0] == 'C') && (shape[1] == 'I')) shape[3] = '4';
   goto now_ok;


  try_again:
   ncol = 3;
   indx = 0;
   for (nn=0; nn<ncol; nn++)
      {
      if (*ref == 'P')
         (void) TCLSER(tid,outlap[indx][nn],tbcol+nn);
      else
         (void) TCLSER(tid,outlab[indx][nn],tbcol+nn);
      if ( tbcol[nn] == -1 )              /* check, if column exists... */
         {
         if (*ref == 'P')
            (void) sprintf(cbuff,"Column with label %s not found... ",
                           outlap[indx][nn]);
         else
            (void) sprintf(cbuff,"Column with label %s not found... ",
                           outlab[indx][nn]);
         SCETER(5,cbuff);
         }
      }
   shape[3] = '3';


  now_ok:
   (void) TCLSER(tid,"Color",tbcol+4);
   if ( tbcol[4] != -1 ) myaux = 1;		/* search for :COLOR */

   (void) TCLSER(tid,"Rotang",tbcol+5);
   if ( tbcol[5] != -1 ) myaux += 10;		/* search for :ROTANG */

   if (*ref != 'S')
      {
      int  imno;
      char output[81];

      (void) sprintf(output,"frame %s used for reference",frame);
      SCTPUT(output);
      imno = -1;
      (void) SCFOPN(frame,D_R4_FORMAT,0,1,&imno);
      if (*ref != 'S')
         {				/* init wc conversion */
         if (Pixconv("INIT",imno,dd1,dd2,dd3) > 0)
            SCETER(69,"initialization of world coord. conversion failed ...");
         if (*ref == 'F')
            (void) strcpy(pxc,"WRS");
         else
            (void) strcpy(pxc,"_RS");
         }
      }

   nmal = 0;
   }


/* Did we read all the lines in the table? */

check_limit:
if ( ++nmal > nrow )
   {
   (void) TCTCLO( tid );
   *aux_flag = myaux;
   return (1);					/* finished */
   }


/* If not, read next line (no. `nmal') */

(void) TCSGET(tid,nmal,&selflg);	/* test, if that row is selected */
if (!selflg) goto check_limit;

cpos[3] = 0.0;
(void) TCRRDR(tid,nmal,ncol,tbcol,cpos,null);	/* world coords. */
if (*ref != 'S')
   {
   dd1[0] = (double) cpos[0];
   dd1[1] = (double) cpos[1];
   if ( Pixconv(pxc,0,dd1,dd2,dd3) != 0)
      {
      if (prflag == 99)
         {
         (void) sprintf(cbuff,
             "row no: %d, error in pixel conversion - we skip...",nmal);
         SCTPUT(cbuff);
         }
      return (-1);
      }
   cpos[0] = (float) dd3[0];
   cpos[1] = (float) dd3[1];

   if (ncol == 4)
      {
      dd1[0] = (double) cpos[2];
      dd1[1] = (double) cpos[3];
      if ( Pixconv(pxc,0,dd1,dd2,dd3) != 0)
         {
         if (prflag == 99)
            {
            (void) sprintf(cbuff,
                "row no: %d, error in pixel conversion - we skip...",nmal);
            SCTPUT(cbuff);
            }
         return (-1);
         }
      cpos[2] = (float) dd3[0];
      cpos[3] = (float) dd3[1];
      }
   }

if (myaux > 0)
   {					/* also get auxiliary data */
   if (myaux == 11)
      (void) TCRRDR(tid,nmal,2,tbcol+4,aux,null);
   else if (myaux == 10)
      {
      aux[0] = 0.0;
      (void) TCRRDR(tid,nmal,1,tbcol+5,aux+1,null);
      }
   else 
      {
      aux[1] = 0.0;
      (void) TCRRDR(tid,nmal,1,tbcol+4,aux,null);
      }
   }

*aux_flag = myaux;
return (0);
}
