/*===========================================================================
  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
===========================================================================*/

/* ----------------------------------------------------------------- */
/* ---------  IIM -------------------------------------------------- */
/* ----------------------------------------------------------------- */

/*
***********************************************************************
*
*   IIMSTW_C:   Set Transfer Window;
*   IIMWMY_C:   Image Memory Write;
*   IIMRMY_C:   Image Memory Read;
*   IIMSMV_C:   Set Memory Visibility;
*   IIMCMY_C:   Clear memory;
*   IIMSLT_C:   Select Video Lookup Table;
*   IIMBLM_C:   Blink Memories;
*   IIMCPY_C:   Copy memory;
*   IIMCPV_C:   Copy memory + make it visible;
*
* V 1.1  871201: P. Santin - Trieste Astronomical Observatory         *
* V 2.0  881221: K. Banse - ESO  Garching                             *

 090120		last modif

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

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

# include    <stdio.h>


extern int  OSY_SLEEP();

static CONF_DATA  *conf;
static MEM_DATA   *mem, *dmem;

/*

*/

/************************************************************************
* IIMSTW_C routine : set image memory transfer window                   *
*                                                                       *
* synopsis   IIMSTW_C (display , memid , loaddir , xwdim , ywdim ,      *
*                      depth , xwoff , ywoff);                          *
*                                                                       *
*       int display;      input   display identifier                    *
*       int memid;        input   memory identifier                     *
*       int loaddir;      input   load direction                        *
                             not updated, if = -99
*       int xwdim;        input   X memory size                         *
*       int ywdim;        input   Y memory size                         *
*       int depth;        input   data depth (bits/pixel)               *
                             not updated currently
*       int xwoff;        input   X memory offset                       *
*       int ywoff;        input   Y memory offset                       *
************************************************************************/

int IIMSTW_C (display, memid, loaddir, xwdim, ywdim, depth, xwoff, 
          ywoff)

int display , memid , loaddir , xwdim , ywdim , depth , xwoff , ywoff;

{

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

conf = ididev [display].confptr;
if (conf->RGBmode == 1)
   {
   if (memid == 3)
      memid = conf->overlay;
   else
      memid = 0;		/* single memory for 3 channels */
   }
else
   {
   if ((memid < 0) || (memid >= conf->nmem)) return(ILLMEMID);
   }

/* check for transfer window size against memory size */

mem = conf->memory[memid];
if ((xwdim > mem->xsize) || (ywdim > mem->ysize)) return(TWTOOBIG);

/* store transfer window parameters */

mem->xwdim = xwdim;
mem->ywdim = ywdim;
mem->xwoff = xwoff;
mem->ywoff = ywoff;
if (loaddir != -99) mem->load_dir = loaddir;

return(II_SUCCESS);
}
/*

*/

/************************************************************************
* IIMWMY_C routine : writes image memory                                *
*                                                                       *
* synopsis   IIMWMY_C (display , memid , data , npixel , depth , packf ,*
*                      x0 , y0);                                        *
*                                                                       *
*       int display;      input   display identifier                    *
*       int memid;        input   memory identifier                     *
*       int data[];       input   image or graphic data                 *
*                                 single array -npix- long              *
*       int npixel;       input   data array length                     *
*       int depth;        input   data depth (bits/pixel)               *
*       int packf;        input   packing factor ( pixel/int >> 1..32 ) *
*       int x0;           input   X data origin                         *
*       int y0;           input   Y data origin                         *
************************************************************************/

int IIMWMY_C (display , memid , data , npixel , depth , packf , x0 , y0) 

int   display , memid , npixel , depth , packf , x0 , y0;
unsigned char *data;

{
int    ix, iy, nb;
int    colchan;



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

conf = ididev[display].confptr;
if (conf->RGBmode == 1)
   {
   colchan = memid;
   memid = 0;			/* single memory for 3 channels */
   }
else
   {
   if ((memid < 0) || (memid >= conf->nmem)) return(ILLMEMID);
   colchan = -1;
   }


mem = conf->memory[memid];
if (mem->mmbm == (char *) 0)
   nb = allo_mem(display,mem,memid);		/* allocate primary memory  */

iy = ((npixel-1) / mem->xwdim) + 1;         /* no. of rows to write */
ix = npixel / iy;
if (y0 +iy > mem->ysize) return(IMGTOOBIG);

wr_mem(display,colchan,mem,x0,y0,ix,iy,0,data); 


return(II_SUCCESS);
}
/*

*/

/************************************************************************
* IIMRMY_C routine : read image memory                                  *
*                                                                       *
* synopsis   IIMRMY_C (display , memid , npixel , x0 , y0 , depth ,     *
*                      packf , ittf , data);                            *
*                                                                       *
*       int display;      input   display identifier                    *
*       int memid;        input   memory identifier                     *
*                                 single array -npix- long              *
*       int npixel;       input   data array length                     *
*       int x0;           input   X data origin                         *
*       int y0;           input   Y data origin                         *
*       int depth;        input   data depth (bits/pixel)               *
*       int packf;        input   packing factor ( pixel/int >> 1..32 ) *
*       int ittf;         input   ITT flag                              *
*       int data[];       output  image or graphic data                 *
************************************************************************/

int IIMRMY_C (display,memid,npixel,x0,y0,depth,packf,ittf,data)

int   display,memid,npixel,depth,packf,x0,y0,ittf;
unsigned char *data;

{
int    ix, iy;
int    colchan, xoff, yoff, xsize;


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

conf = ididev [display].confptr;
if (conf->RGBmode == 1)
   {
   colchan = memid;
   memid = 0;                   /* single memory for 3 channels */
   }
else
   {
   if ((memid < 0) || (memid >= conf->nmem)) return(ILLMEMID);
   colchan = -1;
   }

mem = conf->memory[memid];
if (mem->mmbm == (char *) 0)
   ix = allo_mem(display,mem,memid);		/* allocate primary memory  */

iy = ((npixel-1) / mem->xwdim) + 1;         /* no. of rows to write */
ix = npixel / iy;
if (y0 +iy > mem->ysize) return(IMGTOOBIG);

xoff = mem->xwoff + x0;
yoff = (mem->ysize - 1 - mem->ywoff - y0) * mem->xsize;
xsize = - mem->xsize;

rd_mem(display,colchan,mem,0,mem->mmbm,xoff,yoff,xsize,ix,iy,ittf,data); 

return(II_SUCCESS);
}
/*

*/

/************************************************************************
* IIMSMV_C routine : set memory visibility                              *
*                                                                       *
* synopsis   IIMSMV_C (display , memlist , nmem , vis);                 *
*                                                                       *
*       int display;      input   display identifier                    *
*       int memlist[];    input   memory list                           *
*       int nmem;         input   number of memories                    *
*       int vis;          input   visibility (1/0)                      *
************************************************************************/

int IIMSMV_C(display,memlist,nmem,vis)

int   display,nmem,vis;
int   memlist[];

{
int    memid, i;
int    szflag;

if (ididev[display].opened == 0) return(DEVNOTOP);
if (nmem > 1)
   {
   (void) printf
          ("IIMSMV: memory list with more than 1 memory not supported...\n");
   return(FNCNOTIMPL);
   }

szflag = 0;
memid = memlist[0];

conf = ididev[display].confptr;
if (conf->RGBmode == 1)
   {
   if (memid == 3)
      memid = conf->overlay;
   else
      memid = 0;		/* single memory for 3 channels */
   }
else
   {
   if ((memid < 0) || (memid >= conf->nmem)) return(ILLMEMID);
   }


mem = conf->memory[memid];
mem->visibility = vis;

if (vis == 1) 
   {
   if (memid == conf->overlay) 
      {
      if (mem->gpntr != 0) polyrefr(display,mem,0,0);
      if (mem->tpntr != (TLIST *)0) txtrefr(display,mem,0,0);
      return(II_SUCCESS);
      }

   if (conf->RGBmode != 1)
      {
      for (i=0; i<conf->nmem; i++)     /* turn off visibility for all others */
         {
         if ((i != memid) && (i != conf->overlay))
            {
            dmem = conf->memory[i];
            dmem->visibility = 0;
            }
         }
      }
   
   allrefr(display,mem,memid,2);		/* also updates graphics */
   

   /*  if needed, repaint overlay graphics   */

   i = conf->overlay;
   dmem = conf->memory[i];
   if (dmem->visibility == 1)
      {
      if (dmem->gpntr != 0) polyrefr(display,dmem,0,0);
      if (dmem->tpntr != (TLIST *)0) txtrefr(display,dmem,0,0);
      }
   }


/* with visibility off, we only have work if it's the overlay channel */ 

else
   {
   if (memid == conf->overlay) 
      {
      if (conf->RGBmode != 1)
         {			/* no RGB mode */
         for (i=0; i<conf->nmem; i++)
            {
            if (i != memid)
               {
               dmem = conf->memory[i];
               if (dmem->visibility == 1)	/* use 1st chanl with vis on */
                  {
                  allrefr(display,dmem,i,1);
                  return(II_SUCCESS);
                  }
               }
            }
         }
      else			/* in RGB mode */
         {
         dmem = conf->memory[0];
         if (dmem->visibility == 1)		/* use red chanl */
            {
            allrefr(display,dmem,0,1);
            return(II_SUCCESS);
            }
         }
      return(II_SUCCESS);
      }
   }

conf->memid = memid;		/* update active memory-id in config */
return(II_SUCCESS);
}
/*

*/

/************************************************************************
* IIMCMY_C routine : clear memory                                       *
*                                                                       *
* synopsis   IIMCMY_C (display , memlist , nmem , bck);                 *
*                                                                       *
*       int display;      input   display identifier                    *
*       int memlist[];    input   memory list                           *
*       int nmem;         input   number of memories                    *
*       int bck;          input   background value                      *
************************************************************************/

int IIMCMY_C (display, memlist, nmem, bck)

int   display, nmem, bck;
int   memlist[];

{
int    i, n, curmem;

ALPH_DATA  *alph;



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

conf = ididev[display].confptr;

for (i=0; i<nmem; i++)
   {
   curmem = memlist[i];

   if (curmem >= 90)		/* handle alpha memory in a special way... */
      {
      if (ididev[display].alpno < 90)
         return (NOALPHA);
      else
         {
         alph = conf->alpmem[conf->memid];
         for (n=0; n<10; n++)
            alph->savx[n] = -1;
         clalph(display,0,0,0,0);
         return(II_SUCCESS);
         }
      }

   if (conf->RGBmode == 1)		/* true RGB mode */
      {
      if (curmem == 3)
         {
         curmem = conf->overlay;
         mem = conf->memory[curmem];
         }
      else
         {
         if ((curmem < 0) || (curmem > 2)) return(ILLMEMID);
         mem = conf->memory[0];
         }
      clgraph(mem);			/* clear any graphics + text */
      }

   else 
      {
      if ((curmem < 0) || (curmem >= conf->nmem)) return(ILLMEMID);
      mem = conf->memory[curmem];
      clgraph(mem);			/* clear any graphics + text */
      clmem(mem);		/* reset parameters of normal" channel  */
      }


   
   if ((mem->type & II_IMAGE) > 0)
      {
      if (mem->mmbm == (char *) 0)
         n = allo_mem(display,mem,curmem);
      else
         {
         if (ididev[display].devtyp == 'g')
            cl_win(display,bck);
         else
            {
            int  trumem;

            if (conf->RGBmode == 1)
               {
               unsigned char  zero=0;

               wr_mem(display,curmem,mem,0,0,mem->xsize,mem->ysize,
                      1,&zero);			/* curmem => RGBflag */
               clmem(mem);	
               trumem = 0;
               }
            else
               {
               zero_mem(display,mem,0,bck);
               trumem = curmem;
               }

            if (mem->visibility == 1)
               smv(2,display,mem,trumem,0,0,mem->xsize,mem->ysize,0,0);

            if (ididev[display].alpno >= 90)
               {
               alph = conf->alpmem[trumem];
               for (n=0; n<10; n++) alph->savx[n] = -1;
               if (mem->visibility == 1) clalph(display,0,0,0,0);
               }
            }
         }
      }
   else
      {
      if (conf->RGBmode == 1)		/* was  if (conf->RGBmode > 0)	 */
         {
         if (mem->mmbm == (char *) 0)
            cl_win(display,bck);
         else
            zero_mem(display,mem,0,bck); 
         clgraph(mem);
         }
      else
         {
         if (ididev[display].devtyp == 'g')
            cl_win(display,bck);
         else
            zero_mem(display,mem,0,bck); 
         }
      }
   }

if (curmem == conf->overlay)
   {
   for (i=0; i<conf->nmem; i++)
      {
      if (i != curmem)
         {
         dmem = conf->memory[i];
         if (dmem->visibility == 1)	/* use first channel with vis on  */
            {
            allrefr(display,dmem,i,1);
            return(II_SUCCESS);
            }
         }
      }
   }

return(II_SUCCESS);
}
/*

*/

/************************************************************************
* IIMSLT_C routine : select video lookup table                          *
*                                                                       *
* synopsis   IIMSLT_C (display , memid , lutn , ittn);                  *
*                                                                       *
*       int display;      input   display identifier                    *
*       int memid;        input   memory identifier                     *
*       int lutn;         input   LUT number                            *
*       int ittn;         input   ITT number                            *
************************************************************************/

int IIMSLT_C (display , memid , lutn , ittn)

int   display , memid , lutn , ittn;

{

return(II_SUCCESS);

}

/************************************************************************
* IIMBLM_C routine : blink memories                                     *
*                                                                       *
* synopsis   IIMBLM_C (display , memlst , nmem , period);               *
*       int   display;      input   display identifier                  *
*       int   memlst[];     input   memory list                         *
*       int   nmem;         input   no. of memories                     *
*       float period[];     input   blink periods                       *
************************************************************************/
                           
int IIMBLM_C (display , memlst ,nmem , period)

int   display , memlst[] ,nmem;
float period[];

{
int    memid, Recta;
register int nr;
unsigned int  time;




if (ididev[display].opened == 0) return(DEVNOTOP);
conf = ididev[display].confptr;
if (conf->RGBmode == 1)
   {
   (void) printf("IIMBLM: blinking not supported for TrueColor mode ...\n");
   return(FNCNOTIMPL);
   }

for (nr=0; nr<nmem; nr++)
   {
   memid = memlst[nr];
   if ((memid < 0) || (memid >= conf->nmem)) return(ILLMEMID);
   }

memid = memlst[1];			/* test 2. channel for rectangle */
mem = conf->memory[memid];
if ((mem->xwdim < mem->xsize) || (mem->ywdim < mem->ysize))
   Recta = 1;
else
   Recta = 0;

for (nr=0; nr<nmem; nr++)
   {
   memid = memlst[nr];
   mem = conf->memory[memid];
   smv(3,display,mem,memid,0,0,mem->xsize,mem->ysize,0,0);
   }

if (memlst[0] != conf->memid)		/* 1. blink-chanl is not current one */
   {
   mem = conf->memory[conf->memid];
   mem->visibility = 0;
   }


/* enable EXIT trigger */

(void) IIIENI_C(display,5,0,0,0,0,0);
exit_trg_enable(display);


/* only period[0] is used for all channels... */

if (period[0] > 0.01)
   {					/* OSY_SLEEP <- millisecs */
   time = (unsigned int) (period[0]*1000);  
   }
else
   {
   time = 0;
   }


blink_loop:
for (nr=0; nr<nmem; nr++)
   {
   memid = memlst[nr];
   conf->memid = memid;		/* update active mem id in config  */
   mem = conf->memory[memid];
   mem->visibility = 1;
   
   if (Recta == 1)
      rectrefr(display,mem,memid);	/* refresh rectangle of memory */
   else
      allrefr(display,mem,memid,1);	/* refresh contents of memory */

   sendX(display);			/* force display now!! */

   mem->visibility = 0;			/* now vis. for this mem. off */


   /* do we have overlay stuff? */

   mem = conf->memory[conf->overlay];
   if (mem->visibility == 1)
      {
      if (mem->gpntr != 0) polyrefr(display,mem,0,0);
      if (mem->tpntr != (TLIST *)0) txtrefr(display,mem,0,0);
      }

   if (stopped(display) == 1) goto blink_stop;	/* Exit button pressed? */

   if (time > 0) OSY_SLEEP(time,1);	/* use high resolution wait... */
   if (stopped(display) == 1) goto blink_stop;	/* Exit button pressed? */
   }

goto blink_loop;


/* leave last displayed memory visible  */

blink_stop:
ididev[display].n_inter = 0;
int_disable(display);


mem = conf->memory[memid];		/* set mem back from overlay */

mem->visibility = 1;

return(II_SUCCESS);

}
/*

*/

/************************************************************************
* IIMCPY_C routine : copy memory                                        *
*                                                                       *
* synopsis                                                              *
* IIMCPY_C(displaya,memida,offseta,displayb,memidb,offsetb,xysize,zoom) *
*                                                                       *
*       int displaya;     input   display id of source 
*       int memida;       input   memid of source
*       int offseta[];    input   x,y offset in source
*       int memidb;       input   memid of destination
*       int offsetb[];    input   x,y offset in destination
*       int xysize[];     input   x,ysize for copying
*       int zoom;         input   zoom factor (>= 1)
************************************************************************/

int IIMCPY_C(displaya,memida,offseta,displayb,memidb,offsetb,xysize,zoom) 

int   displaya, displayb, memida, memidb;
int   *offseta, *offsetb, *xysize, zoom;

{
CONF_DATA  *confb;


if ((ididev[displaya].opened == 0) ||
    (ididev[displayb].opened == 0)) return(DEVNOTOP);

conf = ididev [displaya].confptr;
mem = conf->memory[memida];

confb = ididev [displayb].confptr;
dmem = confb->memory[memidb];

copy_mem(displaya,mem,offseta,dmem,offsetb,xysize,zoom);

return(II_SUCCESS);
}
/*

*/

/************************************************************************
* IIMCPV_C routine : copy memory + make it visible                      *
*                                                                       *
* synopsis                                                              *
* IIMCPV_C(displaya,memida,offseta,displayb,memidb,offsetb,xysize,zoom) *
*                                                                       *
*       int displaya;     input   display id of source 
*       int memida;       input   memid of source
*       int offseta[];    input   x,y offset in source
*       int memidb;       input   memid of destination
*       int offsetb[];    input   x,y offset in destination
*       int xysize[];     input   x,ysize for copying
*       int zoom;         input   zoom factor (>= 1)
************************************************************************/

int IIMCPV_C(displaya,memida,offseta,displayb,memidb,offsetb,xysize,zoom) 

int   displaya, displayb, memida, memidb;
int   *offseta, *offsetb, *xysize, zoom;

{
int  i;

CONF_DATA  *confb;

if ((ididev[displaya].opened == 0) ||
    (ididev[displayb].opened == 0)) return(DEVNOTOP);

conf = ididev [displaya].confptr;
mem = conf->memory[memida];

confb = ididev [displayb].confptr;
dmem = confb->memory[memidb];

copy_mem(displaya,mem,offseta,dmem,offsetb,xysize,zoom);

dmem->visibility = 1;
for (i=0; i<confb->nmem; i++)         /* turn off visibility for all others */
   {
   if ((i != memidb) && (i != confb->overlay))
      {
      mem = confb->memory[i];
      mem->visibility = 0;
      }
   }

allrefr(displayb,dmem,memidb,2);                /* also updates graphics */
confb->memid = memidb;          /* update active memory id in configuration  */

return(II_SUCCESS);
}

