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

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

/* file iid2.c : contains the following routines
*
*   IIDCLO_C      : Close Display;
*   IIDRST_C      : Reset Display;
*   IIDDEL_C      : Delete Display;
*   IIDICO_C      : Move Display to Icon (or back);
*   IIDQDV_C      : Inquire Device Characteristics;
*   IIDQCI_C      : Inquire Capability Integer;
*   IIDQCR_C      : Inquire Capability Real;
*   IIDQDC_C      : Inquire Defined Configuration;
*   IIDSDP_C      : Select Display Path;
*   IIDSNP_C      : Get Snapshot;
*   IIDSSS_C      : Set Split Screen;
* 
*   IIDSEL_C      : Select Defined Configuration;	these routines
*   IIDUPD_C      : Update Display;			are not implemented
*   IIDIAG_C      : Get Diagnostic;			and already blocked
*   IIDERR_C      : Get Error;				on the client side...
* 
*************************************************************************
* V 1.1 871201: P. Santin - Trieste Astronomical Observatory            
* V 2.0 881130  Klaus Banse - ESO Garching                              

 070410		last modif

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

# include    <stdlib.h>             

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

/*

*/

/************************************************************************
* IIDCLO_C routine : closes an opened display                           *
*                                                                       *
* synopsis  IIDCLO_C (display);                                         *
*                                                                       *
*       int display;    input     display identifier                    *
************************************************************************/

int IIDCLO_C (display)
int display;

{
int   i, j;

CURS_DATA      *curs;
ROI_DATA       *roi;

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

/*  erase any visible cursor and ROI    */

j = 0;
for (i=0; i<ididev[display].ncurs; i++)
   {
   curs = ididev[display].cursor[i];
   if (curs->vis != 0)
      {
      curs->vis = 0;
      draw_curs(display,2,j,i,j,j,j,j);		/* 'j' just dummy - not used  */
      }
   }

roi = ididev[display].roi;
if ((roi->sh != -1) && (roi->vis != 0))
   {
   roi->vis = 0;
   if (roi->sh == 0)				/* rectangle */
      draw_rroi(display,2,j,j,j,j,j,j);
   else						/* circle */
      draw_croi(display,2,j,j,j,j,j,j,j);
   }

if (ididev[display].n_inter != 0)
   IIISTI_C(display);

sendX(display);				/* make sure all requests are flushed */
ididev[display].opened = 0;

return(II_SUCCESS);
}

/*

*/

/************************************************************************
* IIDRST_C routine : resets an opened display                           *
*                                                                       *
* synopsis  IIDRST_C (display);                                         *
*                                                                       *
*       int display;    input     display identifier                    *
************************************************************************/

int IIDRST_C (display)
int display;

{
int    j, k, m;
int    x0, y0;

ITT_DATA   *itt;
CURS_DATA  *curs;
ROI_DATA   *roi;
CONF_DATA  *conf;
MEM_DATA   *mem;
ALPH_DATA  *alph;

/* check if ididev has been opened */

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

ididev[display].inter_mask = 0;
IIISTI_C(display);			     /* reset pending interactions */

x0 = ididev[display].xsize / 2;
y0 = ididev[display].ysize / 2;

m = 0;		/* dummy place holder */
for (j=0; j<ididev [display].ncurs; j++)     /* disable cursors */
   {
   curs = ididev [display].cursor[j];
   curs->sh = -1;
   curs->col = 0;
   curs->xpos = x0;
   curs->ypos = y0;
   if (curs->vis != 0)
      {
      curs->vis = 0;
      draw_curs(display,2,m,j,m,m,m,m);	    /* 'm' just dummy par ...  */
      }
   }


roi = ididev[display].roi;		     /* disable ROIs */
roi->sh = -1;                    
roi->col = 0;
roi->xmin = x0 - 20;
roi->ymin = y0 - 20;
roi->xmax = x0 + 20;
roi->ymax = y0 + 20;
roi->radiusi = 20;
roi->radiusm = 0;
roi->radiuso = 0;

if (roi->vis != 0)
   {
   roi->vis = 0;
   if (roi->sh == 0)                            /* rectangle */
      draw_rroi(display,2,m,m,m,m,m,m);
   else                                         /* circle */
      draw_croi(display,2,m,m,m,m,m,m,m);
   }

conf = ididev [display].confptr;       /* reset config + mem structure */
if (conf->RGBmode == 1)
   {
   mem = conf->memory[0];
   clgraph(mem);
   clmem(mem);

   if (mem->mmbm != (char *) 0)
      {
      k = 0;
      m = IIMCMY_C(display,&k,1,0);	     /* clear channel  */
      if (ididev[display].alpno >= 90)
         {
         alph = conf->alpmem[0];
         for (k=0; k<10; k++) alph->savx[k] = -1;
         if (mem->visibility == 1) clalph(display,0,0,0,0);
         }
      }
   }

else
   {
   for (k=0; k<conf->nmem; k++)
      {
      mem = conf->memory[k];
      if (mem->mmbm != (char *) 0)
         m = IIMCMY_C(display,&k,1,0);	     /* clear channel  */
      itt = mem->ittpntr;
      if (itt != (ITT_DATA *)0) itt->vis = 0;	/* avoid it for overlay chan */
      }

   /*  clear also alpha numerics if it's main window */

   if (ididev[display].alpno >= 90) 
      m = IIMCMY_C(display,&ididev[display].alpno,1,0);
   }


loc_zero(display);				/* reset locators  */
initgra(display);				/* reset graphics functions */

return(m);
}

/*

*/

void waste_disp(dspno)
int dspno;

{
int     j, k;

INTBAR         *bar;
CONF_DATA      *conf;
MEM_DATA       *mem;
GLIST          *gr;


/*
printf("wasting display %d, links = %d,%d\n",
dspno,ididev[dspno].link[0],ididev[dspno].link[1]);
*/



if (ididev[dspno].hcopy != (char *) 0)          /*  see if we had a hardcopy  */
   destroy(dspno,"hcopy");

if (ididev[dspno].alpno >= 90)          /*  see if we have alpha memory  */
   destroy(dspno,"alpha");

bar = ididev[dspno].bar;
if (bar != 0)
   {
   if (bar->wp == 1)                /* check if we already created the rest */
      destroy(dspno,"lutbar");
   free(ididev[dspno].bar);
   }

if (ididev[dspno].lookup != 0)  /* free LUT data structure */
   free(ididev[dspno].lookup);

for (j=0; j<ididev[dspno].ncurs; j++)           /* kill cursor structs  */
   free(ididev[dspno].cursor[j]);

free(ididev[dspno].roi);                        /* kill ROI struct  */

if (ididev[dspno].devtyp != 'c')
   {
   for (j=0; j<MAX_INTER; j++)
      free(ididev[dspno].inter[j]);

   for (j=0; j<intdevtable[dspno].nloc; j++)
      free(intdevtable[dspno].loc[j]);


   for (j=0; j<intdevtable[dspno].ntrig; j++)
      free(intdevtable[dspno].trig[j]);
   }
else
   {
   j = -ididev[dspno].curswin;
   ididev[j].curswin = -1;              /* reset also main window */
   }


conf = ididev[dspno].confptr;
destroy(dspno,"memory");                /* kill XImages of all memories */

for (k=0; k<conf->nmem; k++)
   {
   mem = conf->memory[k];
   if (mem->ittpntr != (ITT_DATA *)0) free((char *)mem->ittpntr);

   if ( (ididev[dspno].alpno >= 90) && (conf->overlay != k) )
      free((char *)conf->alpmem[k]);

   if (mem->gpntr != (GLIST *)0)
      {
      gr = mem->gpntr;
      free((char *)gr->x);
      free((char *)mem->gpntr);
      }
   if (mem->tpntr != (TLIST *)0) free((char *)mem->tpntr);

   free(mem);                   /* finally kill memory itself  */
   }
free(conf);                     /* and configuration structure */


/*  now get rid of the window */

destroy(dspno,"display");
sendX(dspno);                           /* Flush out  */


/*  finally free this entry in structure ididev  */

ididev[dspno].devname[0] = '\0';
ididev[dspno].link[0] = 0;
ididev[dspno].link[1] = -1;
ididev[dspno].opened = 0;
}

/*

*/

/************************************************************************
* IIDDEL_C routine : delete display device structures
*                                        
* synopsis   IIDDEL (display,nodels,imindx,grindx) 
*                                       
*       char[] display;   input    device name  
*       int *nodels;      output   no. of open display windows destroyed
*       int *imindx;      output   dspno of image display still left,
*				   else -1 is returned
*       int *grindx;      output   dspno of graphics display still left,
*				   else -1 is returned
************************************************************************/

int  IIDDEL_C (display,nodels,imindx,grindx)
char display[];
int *nodels, *imindx, *grindx;

{
char   ct, cbuf[12];

int     i, j, k, m, l, indx;
int     delcnt, imix, grix, shadow[MAX_DEV], allflg;
int     parent_window, devs[MAX_DEV];



*nodels = 0, shadow[0] = -1;
allflg = 0; delcnt = 0; imix = -1;  grix = -1;
parent_window = -1, indx = MAX_DEV-1;

for (i=0; i<MAX_DEV; i++) devs[i] = -1;		/* init to no destroy */


/* if not wildcard, search for device with that name */

if (display[0] != '*')
   {
   for (i=0; i<MAX_DEV; i++)
      {
      if (strcmp(ididev[i].devname,display) == 0) 
         {
         devs[indx--] = i;			/* enter indx in destr. list */
         for (j=0; j<MAX_DEV; j++)
            {
            k = ididev[i].shadow[j];		/* also all `shadows' */
            if (k != -1) devs[indx--] = k;
            }
         goto entry_found;
         }
      }
   return(DEVNAMERR);			/* no device to delete... */


  entry_found:
   if (ididev[i].link[0] == 1)		/* are we parent window? */
      {					/* Yes. look for subwindows */
      float rdum;

      do_misc(i,1,-1,cbuf,&k,&rdum);		/* we have to reset rootw */
      parent_window = i;

      for (i=0; i<MAX_DEV; i++)
         {
         if (ididev[i].devname[0] != '\0')
            {
            k = ididev[i].link[1];
            if (k == parent_window)
               devs[indx--] = i;
            else if (k > -1)
               {	
               m = ididev[k].link[1];
               if (m == parent_window) 
                  devs[indx--] = i;
               else if (m > -1)
                  {			/* we only follow max 3 links */
                  j = ididev[m].link[1];
                  if (j == parent_window) devs[indx--] = i;
                  }
               }
            }
         }
      }
   }

else
   {
   indx = 0;
   for (i=0; i<MAX_DEV; i++)
      {
      /*
      printf("ididev[%d].devtyp = %c, devname = %s\n",
             i,ididev[i].devtyp,ididev[i].devname);
      */

      if ((ididev[i].devtyp == display[1]) &&
          (ididev[i].devname[0] != '\0'))
         devs[indx++] = i;
      }
   }



/* now get rid of all structures for ididev[i]  */

for (i=0; i<MAX_DEV; i++)
   {
   if (devs[i] > -1)			/* index of window to get rid of? */
      {
      k = devs[i];
      allflg++;
      (void) strcpy(cbuf,ididev[k].devname);		/* save name */
      waste_disp(k);
      delcnt++;

      (void) strcat(cbuf,"z");		 /* zoom window exists for display? */
      for (j=0; j<MAX_DEV; j++)
         {
         if (strcmp(ididev[j].devname,cbuf) == 0) 
            {
            waste_disp(j);		/* also this one out */
            delcnt++;
            devs[j] = -1;
            break;			/* single zoom window only */
            }
         }
      }
   }

if (allflg == 0) return(DEVNAMERR);	/* no device to delete... */



/*  find out what is left, so we can assign it as display/graphics w. */

m = 0; l = 0;

for (i=0; i<MAX_DEV; i++)
   {
   ct = ididev[i].devname[5]; 			/* get display no */
   if (ididev[i].devname[0] != '\0') 
      {
      if ((ididev[i].devtyp == 'i') && (m == 0))
         {
         if ((ct >= '0') && (ct <= '9'))
            imix = ct - 48;			/* return image no. */
         else
            imix = 0;
         m = 1;
         }
      else if ((ididev[i].devtyp == 'g') && (l == 0))
         {
         if ((ct >= '0') && (ct <= '9'))
            grix = ct - 48;			/* return graphics no. */
         else
            grix = 0;
         l = 1;
         }
      }
   }


*imindx = imix;
*grindx = grix;
*nodels = delcnt;


return(II_SUCCESS);
}

/*

*/

/************************************************************************
* IIDQDV_C routine : inquire ididev characteristics                     *
*                                                                       *
* synopsis   IIDQDV_C (display , nconf , xdev , ydev , depthdev ,       *
*                      maxlutn , maxittn , maxcurn);                    *
*                                                                       *
*       int display;      input    display identifier                   *
*       int *nconf;       output   no. of configurations                *
*       int *xdev;        output   ididev X dimensions                  *
*       int *ydev;        output   ididev Y dimensions                  *
*       int *depthdev;    output   ididev depth                         *
*       int *maxlutn;     output   max no. of LUTs                      *
*       int *mmaxittn;    output   max no. of ITTs                      *
*       int *maxcurn;     output   max no. of cursors                   *
************************************************************************/

int IIDQDV_C (display, nconf, xdev, ydev, depthdev, maxlutn, maxittn,
              maxcurn)
int  display , *nconf , *xdev , *ydev , *depthdev;
int  *maxlutn , *maxittn , *maxcurn;

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

*nconf = 1;

*xdev = ididev[display].xsize;
*ydev = ididev[display].ysize;
*depthdev = ididev[display].depth;

*maxlutn = 1;
*maxittn = 1;
*maxcurn = ididev[display].ncurs;

return(II_SUCCESS);
}

/*

*/

/************************************************************************
* IIDQCI_C routine : inquire ididev capabilities integer                *
*                                                                       *
* synopsis   IIDQCI_C (display , devcap , size , capdata , ncap)        *
*                                                                       *
*                                                                       *
*       int display;      input    display identifier                   *
*       int devcap;       input    ididev capability integer code       *
*       int size;         input    capability array size                *
*       int capdata[];    output   ididev capabilities array            *
*       int *ncap;        output   ididev capabilities array size       *
************************************************************************/

int IIDQCI_C (display , devcap , size , capdata , ncap)
int  display , devcap , size , capdata[] , *ncap;

{
int   no;

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

no = ididev[display].screen;
if (devcap == 15)
   {
   capdata[0] = Xworkst[no].nolut;
   *ncap = 1;
   }

else if (devcap == 17)
   {
   capdata[0] = 1;
   capdata[1] = MAX_ZOOM;
   *ncap = 2;
   }

else if (devcap == 18)
   {
   capdata[0] = Xworkst[no].nolut;
   capdata[1] = Xworkst[no].lutlen;
   capdata[2] = ididev[display].lutoff;
   capdata[3] = Xworkst[no].lutflag;
   if ((Xworkst[no].visual == 4) && (Xworkst[no].ownlut == 0))
      capdata[4] = 5;			/* Pseudo on TrueColor */
   else
      capdata[4] = Xworkst[no].visual;	/* 2, 3 or 4 */
   capdata[5] = Xworkst[no].width;
   capdata[6] = Xworkst[no].height;
   *ncap = 7;
   }

return(II_SUCCESS);

}

/*

*/
/************************************************************************
* IIDQCR_C routine : inquire ididev capabilities real                   *
*                                                                       *
* synopsis   IIDQCR_C (display , devcap , size , capdata , ncap)        *
*                                                                       *
*       int   display;      input    display identifier                 *
*       int   devcap;       input    ididev capability integer code     *
*       int   size;         input    capability array size              *
*       float capdata[];    output   ididev capabilities array          *
*       int   *ncap;        output   ididev capabilities number         *
************************************************************************/

int IIDQCR_C (display , devcap , size , capdata , ncap)
int   display , devcap , size , *ncap;
float capdata[];

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

return(II_SUCCESS);
}

/*

*/

/************************************************************************
* IIDQDC_C routine : inquire defined configuration                      *
*                                                                       *
* synopsis   IIDQDC_C (display , confn , memtyp , maxmem , confmode ,   *
*                      mlist, mxsize , mysize , mdepth , ittdepth ,     *
*                      nmem);                                           *
*                                                                       *
*                                                                       *
*       int display;      input   display identifier                    *
*       int confn;        input   configuration number                  *
*       int memtyp;       input   memory type                           *
*                                 available types IMAGE = 1             *
*                                                 TEXT  = 2             *
*                                                 GRAPH = 4             *
*       int maxmem;       input   max memory number                     *
*       int *confmode     output  configuration mode                    *
*                                 [1=mono - 2=pseudocolor - 3=RGB]      *
*       int mlist[];      output  memories id list                      *
*       int mxsize[];     output  memories x size                       *
*       int mysize[];     output  memories y size                       *
*       int mdepth[];     output  memories depth                        *
*       int ittlen[];     output  associated ITTs length                *
*       int *nmem;        output  no. of memories in configuration      *
************************************************************************/

int IIDQDC_C (display , confn , memtyp , maxmem , confmode ,
          mlist, mxsize , mysize , mdepth , ittlen , nmem)
int display, confn , memtyp , maxmem , *confmode , *nmem;
int mlist[] , mxsize[] , mysize[] , mdepth[] , ittlen[];

{
CONF_DATA      *conf;
MEM_DATA       *mem;

int      m, no;


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

conf = ididev[display].confptr;		/* `confn' is ignored... */
if (memtyp == 4)  		/* graphics memory type  */
   m = conf->overlay;
else if (memtyp == 1)
   m = conf->memid;
else
   return (BADINPUT);    

*confmode = 2;
mem = conf->memory[m];
mlist[0] = m;
mxsize[0] = mem->xsize;
mysize[0] = mem->ysize;
mdepth[0] = mem->depth;
no = ididev[display].screen;
ittlen[0] = Xworkst[no].lutlen;
*nmem = 1;

return(II_SUCCESS);
}

/*

*/

/************************************************************************
* IIDSDP_C routine : select display path                                *
*                                                                       *
* synopsis   IIDSDP_C (display , memlist , nmem , lutflag , ittflag)    *
*                                                                       *
*       int display;      input   display identifier                    *
*       int memlist[];    input   memory list                           *
*       int nmem;         input   no. of memories                       *
*       int lutflag[];    input   LUT flags                             *
*       int ittflag[];    input   ITT flags                             *
************************************************************************/

int IIDSDP_C (display , memlist , nmem , lutflag , ittflag)
int display , nmem;
int memlist[] , lutflag[] , ittflag[];

{
CONF_DATA      *conf;
MEM_DATA       *mem;
LUT_DATA       *lut;
ITT_DATA       *itt;

int    m, no;


if (ididev[display].opened == 0) return(DEVNOTOP);
if (nmem > 1) return (FNCNOTIMPL);

no = ididev[display].screen;
if (Xworkst[no].ownlut != 1) return(II_SUCCESS);

conf = ididev[display].confptr;
m = memlist[0];
if (m != conf->overlay) conf->memid = m;	/* update current memid  */

mem = conf->memory[m];
itt = mem->ittpntr;

lut = ididev[display].lookup;
if (lutflag[0] != -1) lut->vis = lutflag[0];
if (ittflag[0] != -1) itt->vis = ittflag[0];
wr_lut(display,lut,lut->vis);

return(II_SUCCESS);
}

/************************************************************************
* IIDSSS_C routine : set split screen                                   *
* synopsis   IIDSSS_C (display,memid,xoff,yoff,splitf,splitx,splity)    *
*       int display;      input   display identifier                    *
*       int memid[];      input   memory id list                        *
*       int xoff[];       input   X offsets                             *
*       int yoff[];       input   Y offsets                             *
*       int splitf;       input   split flag                            *
*       int splitx;       input   X split location                      *
*       int splity;       input   Y split location                      *
************************************************************************/

int IIDSSS_C (display, memid, xoff, yoff, splitf, splitx, splity) 
int display , splitf , splitx , splity;
int *memid, *xoff, *yoff;

{
return(FNCNOTIMPL);		/*  currently not implemented  */
}

/*

*/

/***********************************************************************
* IIDSNP_C routine : create snapshot                                   *
*                                                                      *
* synopsis   IIDSNP_C (display , colmode , npixel , xoff , yoff ,      *
*                      depth , packf , data);                          *
*                                                                      *
*       int display      input   display identifier                    *
*       int colmode      input   color mode                            *
*       int npixel       input   no. of data pixel                     *
*       int xoff         input   X offset                              *
*       int yoff         input   Y offset                              *
*       int depth        input   data depth                            *
*       int packf        input   packing factor                        *
*       unsigned char data[]   output  out data                        *
************************************************************************/

int IIDSNP_C (display , colmode , npixel , xoff , yoff , depth , packf ,
              data)
int display , colmode , npixel , xoff , yoff , depth , packf;
unsigned char *data;

{
MEM_DATA   *mem;
ITT_DATA   *itt;
CONF_DATA  *conf;

int    j, xsize, ix, iy, dx, dy;

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

conf = ididev[display].confptr;
if (ididev[display].devtyp != 'g')
   {
   if (conf->memid == conf->overlay) return(ILLMEMID);
   }

dx = ididev[display].xsize;
dy = ididev[display].ysize;
iy = ((npixel-1) / dx) + 1;         /* no. of rows to write */
ix = npixel / iy;
if ((yoff + iy) > dy) return(IMGTOOBIG);

yoff = (dy - 1 - yoff) * dx;
xsize = -dx;
mem = conf->memory[conf->memid];


/*  get the hardcopy of the active window  */

get_hcopy(display,mem,conf->memid);


/* and now pull it over  */

j = 0;
if (conf->RGBmode == 0)				/* plain Pseudocolor mode */
   {
   itt = mem->ittpntr;
   if (itt != (ITT_DATA *)0) j = itt->vis;
   rd_mem(display,0,mem,1,ididev[display].hcopy,xoff,yoff,xsize,ix,iy,j,data); 
   }
else						/* all other need 3 planes */
   rd_mem(display,1,mem,1,ididev[display].hcopy,xoff,yoff,xsize,ix,iy,j,data); 

return(II_SUCCESS);
}

/*

*/

/************************************************************************
* IIDICO_C routine : moves an opened display to an icon (or back)                           *
*                                                                       *
* synopsis  IIDICO_C (display,flag);                                         *
*                                                                       *
*       int display;    input     display identifier                    *
*       int flag;       input     1 = window -> icon
				  0 = icon -> window
************************************************************************/

int IIDICO_C (display,flag)
int  display, flag;

{

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

iconify(display,flag);

return 0;
}
