/*===========================================================================
  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  SUBMEM_C
.LANGUAGE    C
.AUTHOR      K. Banse			IPG-ESO Garching
.KEYWORDS    ImageDisplay, memory control regs.
.PURPOSE     manipulate the memory control registers of a given channel
.ALGORITHM   use IDIs to do the job
.INPUT/OUTPUT
  The following keywords are used:

  DAZIN/I/1/2          LUT/ITT section no., flag for graphics memory
  or for ACTION = B:
  INPUTI/I/1/5	       channel1, channel2, ..., -1, delay in 10th of seconds

  call as    SUBMEM_C( action, dazhld )

  input:
          char *action :	action flag:
			  B, for blinking between two image channels
               		  C, for clearing the memory channel
                    	  D, display in a user friendly format
                  	     all image channel related info (SHOW/CHANNEL)
                  	  I, for setting ITT section
			  L, for setting LUT section
			  M, for loading an image/graphics memory into FCR's
                  	  R, for displaying the refscale/intensity_bar
                    	  S, startup afresh = initialize the ima_display
          int  *dazhld:

.RETURNS     nothing
.ENVIRONment MIDAS
             #include <midas_def.h>   Prototypes for MIDAS interfaces
             #include <idinumd.h>     Global variables for DISPLAY interfaces

.VERSIONS    1.00       940630  converted from IDAUXZ.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>
#include <proto_II.h>

#define  MAXCHN  40

/*

*/

void SUBMEM_C(action,dazhld)
char *action;
int  *dazhld;

{
int  actvals, inputi, itt, knul, lutno, lutvis, refsc;
int  actcha, splmod, unit, dazzin[2], jarea;
register int ii;

char output[84], frame[16];
char *info_usr = "switch cursor(s) on - next time we exit...",
     *str_chpi = "start channel pixels:     %8d%8d",
     *str_used = "channel pixels used:      %8d%8d",
     *str_frpi = "start frame pixels:       %8d%8d",
     *str_scal = "scaling factors:          %8d%8d",
     *str_scro = "scroll values:            %8d%8d",
     *str_zoom = "zoom factors:             %8d%8d",
     *str_chsz = "channel size:             %8d%8d",
     *war_lutno = "Invalid lut section - forced to section 0 ...";

void CONCHA_C();




splmod = dazhld[2];			/* initialisation */
refsc  = dazhld[7];
lutno  = dazhld[9];
jarea = 0;

(void) SCKRDI("DAZIN",1,2,&actvals,dazzin,&unit,&knul);
inputi = *dazzin;


if (*action != 'S')			/* not for CLEAR/DISPLAY */
   {
   if ((*action == 'L') && (inputi >= 0))		/* enable LUT */
      (void) SCKGETC("P2",1,10,&actvals,output);
   else
      (void) SCKGETC("P1",1,10,&actvals,output);

   (void) CGN_UPCOPY(frame,output,8);
   if (frame[0] == '+')
      actcha = QIMCH;
   else if (frame[0] == 'O')
      actcha = QOVCH;
   else
      {
      double  ddum;
      int     stat;
      float   rdum;

      stat = CGN_CNVT(frame,1,1,&actcha,&rdum,&ddum);
      if ((stat != 1) || (actcha < 0) || (actcha > QLSTCH))
         {
         char  cdum[64];

         (void)sprintf(cdum,"invalid image channel (= %s) ...",output);
         SCETER(5,cdum);
         }
      }
   }


/* branch to desired action */

if (*action == 'B')                              /* blink between channels */
   {
   int   ink[MAXCHN], maxchan, mm, dummy[4];
   float delay[MAXCHN], dt; 

   (void) SCKRDI("DAZDEVR",20,1,&actvals,&maxchan,&unit,&knul);	 /* max chans */
   if (maxchan > MAXCHN) 
      SCETER(11,"Max. no. of channels out of sync with DAZDEVR(20)!");

   (void) SCKRDI("CHANLS",1,maxchan,&actvals,ink,&unit,&knul);
   mm = maxchan;
   for (ii=0; ii<maxchan; ii++)
      {
      if (ink[ii] == -1) 
         {
         mm = ii;
         break;
         }
      }
   if (mm < 2) (void) SCETER(11,"Bad (or not enough) channels entered...");
   QIMCH = ink[0];
   DCGICH(QIMCH);	
   (void) Cdazvis(QDSPNO,QIMCH,2,1);


   (void) SCKRDR("INPUTR",1,1,&actvals,&dt,&unit,&knul);
   for (ii=0; ii<mm; ii++) delay[ii] = dt;	/* DELAY is in seconds */


   /* check, what option for blinking area we have */

   (void) SCKGETC("P3",1,60,&actvals,output);
   if (output[0] == '+')
      jarea = 0;
   else
      {
      CGN_UPSTR(output);
      if (strcmp(output,"CURSOR") == 0)
         jarea = 1;
      }

   if (jarea == 1)
      {
      int   give_info, cooco, coords[4];
      int   worky, statA, statB, xwdim, ywdim, xwoff, ywoff;
      int   xya[5], xyb[5];
      void  Ccursin();

      for (ii=0; ii<4; ii++) coords[ii] = -1;

      CONCHA_C(QDSPNO,QOVCH,1,0);	/* Clear ov_chan if necessary */
      (void) SETCUR_C(QDSPNO,2,1,0,coords);	/* setup cursor rectange */


      /* read cursor position(s) */

      cooco = 0;			/* counter for cursor reading */
      give_info = 0;
      worky = 1;
      Ccursin(QDSPNO,0,2,xya,&statA,xyb,&statB);

   Cursor_loop:
      Ccursin(QDSPNO,1,2,xya,&statA,xyb,&statB);

      if ((statA == 0) && (statB == 0))
         {
         if ((give_info == 0) && (cooco == 0))		/* EXIT (1) */
            {
            SCTDIS(output,-9);
            SCTDIS(info_usr,80);
            give_info = 1;
            Ccursin(QDSPNO,0,2,xya,&statA,xyb,&statB);
            goto Cursor_loop;
            }
         SCTDIS(" ",0);
         }
      else
         {
         if (cooco == 0)
            cooco = 1;
         else
            CONCHA_C(QDSPNO,QOVCH,1,0); 
         (void) IIISTI_C(QDSPNO);

         xwdim = xyb[0] - xya[0] + 1;
         ywdim = xyb[1] - xya[1] + 1;
         xwoff = xya[0];		/* rectangle offset in memory */
         ywoff = xya[1];


         /* 1. chanl -> full view, all other chanls -> rectangle only */

         (void) IIMSTW_C(QDSPNO,ink[0],-99,QMSZX,QMSZY,-99,0,0);
         for (ii=1; ii<mm; ii++)
            (void) IIMSTW_C(QDSPNO,ink[ii],-99,xwdim,ywdim,-99,xwoff,ywoff);

         (void) IIMBLM_C(QDSPNO,ink,mm,delay);
         DCGICH(QIMCH);	
         (void) Cdazvis(QDSPNO,QIMCH,2,1);
             
         SCTDIS(" Move to next rectangle, or push EXIT button",80);
         Ccursin(QDSPNO,0,2,xya,&statA,xyb,&statB);
         goto Cursor_loop;
         }
      }

   else
      {		/* do it via IIMBLM, we get out of there via Exit button */
      for (ii=0; ii<mm; ii++)
         (void) IIMSTW_C(QDSPNO,ink[ii],-99,QMSZX,QMSZY,-99,0,0);

      (void) IIMBLM_C(QDSPNO,ink,mm,delay);

      /*  get currently displayed channel */

      (void) IIDQDC_C(QDSPNO,0,1,1,dummy,ink,dummy,dummy,dummy,dummy,&mm);
      QIMCH = ink[0];
      DCGICH(QIMCH);			/* update memory info */
      }
   }

else if (*action == 'C')             /* handle CLEAR/CHANNEL business here */
   { 
   CONCHA_C(QDSPNO,actcha,0,*dazzin);
   (void) strcpy(dzmemc,"   ");		/* prepare data for cleaned channel */
   LOADDR = 0;
   SSPX = SSPY = 0;
   NSX = QMSZX;                       /* nopix in image memory */
   NSY = QMSZY;
   SFPX  = SFPY  = 1;
   SCALX = SCALY = 1;
   SCROLX = 0;                   /* pixel 0 -> left edge of display screen */
   SCROLY = QMSZY - 1;          /* last chan line -> top line of display */
   ZOOMX = ZOOMY = 1;
   SOURCE = 0;
   ITTYES = 0;
   DZDRAW = 0;
   ZPLANE = 0;

   DCPICH(actcha);		/* store new setup of channel */
   }

else if (*action == 'D')                       /* handle SHOW/CHANNEL here */
   {
   char  mybuf[84];

   if ((actcha == QOVCH) && (IDINUM == 11))
      {
      (void) sprintf(mybuf,
      "Overlay channel (%d) is emulated by software for X11",actcha);
      SCTPUT(mybuf);
      }
   else
      {
      (void) DCGICH(actcha);		/* get info from IDI display */

      if (QRGBFL != 1)
         {
         if (actcha != QOVCH)                  /* display usage of channel */
            (void) sprintf(mybuf,"Image channel %d:",actcha);
         else
            (void) sprintf(mybuf,"Overlay channel %d:",actcha);

         if (SOURCE > 0)                              /* from LOAD/IMAGE */
            (void) sprintf(output,"%s   frame %s loaded",mybuf,dzmemc);
         else
            (void) sprintf(output,"%s   unused... ",mybuf);
         SCTPUT(output);

         if (ZPLANE > 0)
            {
            (void) sprintf(output,"plane_no. loaded:              %d",ZPLANE);
            SCTPUT(output);
            }
         }
      else				/* RGB mode */
         {
         (void) sprintf(mybuf,"Image channel 0:");
         if (SOURCE > 0)                              /* from LOAD/IMAGE */
            (void) sprintf(output,"%s   frame %s loaded",mybuf,dzmemc);
         else
            (void) sprintf(output,"%s   unused... ",mybuf);
         SCTPUT(output);

         if (actcha == 0)
            SCTPUT("channel 0 used for red color");
         else if (actcha == 1)
            SCTPUT("channel 1 used for green color");
         else
            SCTPUT("channel 2 used for blue color");
         }  


      /* display channel size; */

      (void) sprintf( output, str_chsz, QMSZX, QMSZY );
      SCTPUT(output);


      /* display start screen pixels */

      (void) sprintf( output, str_chpi, SSPX, SSPY );
      SCTPUT(output);


      /* display no. of ima_mempixels */

      (void) sprintf( output, str_used, NSX, NSY );
      SCTPUT(output);


      /* display start frame pixels */

      (void) sprintf( output, str_frpi, SFPX, SFPY );
      SCTPUT(output);


      /* display scaling factors */

      if ( SCALX == 1 )
         *dazzin = SCALX;
      else
         *dazzin = -SCALX;

      if ( SCALY == 1 )
         dazzin[1] = SCALY;
      else
         dazzin[1] = -SCALY;
      (void) sprintf(output,str_scal,*dazzin,dazzin[1]);
      SCTPUT(output);


      /* display scroll values */

      (void) sprintf( output, str_scro, SCROLX, SCROLY );
      SCTPUT(output);


      /* display zoom factors */

      (void) sprintf( output, str_zoom,  ZOOMX, ZOOMY );
      SCTPUT(output);

      if (ITTYES == 1)
         {
         char cbuff[24];

         (void) SCKGETC("HCITTLUT",1,42,&actvals,output);
         (void) strncpy(cbuff, output, 20 );
         cbuff[20] = '\0';
         (void) sprintf(output,"current ITT = %s",cbuff);
         }
      else
         (void) strcpy(output,"no ITT used");
      SCTPUT(output);

      if ( DZDRAW == 0 )     
         (void) strcpy(output,"no graphics in channel ");
      else
         (void) strcpy(output,"graphics in channel ");
      SCTPUT(output);
      }
   }


else if (*action == 'I')                      /* handle ITT business here */
   {
   int ittno, ittvis;

   DCGICH(actcha);

   if ( inputi < 0 )				/* clear ITT */ 
      ITTYES = 0; 
   else
      ITTYES = 1;                               /* set to visible */

   DCPICH(actcha);
   ittno = 0;					/* ITT section always = 0 */
   ittvis = ITTYES;


   /* Get last referenced LUT section no.
     LUTNO in [0,3] (enabled LUT_sect) or in [100,103] (disabled LUT_sect) */

   if ( lutno > 99 ) lutno -= 100;


   /* select desired ITT and same LUT + en/disable visibility */

   if (ittvis > 0) (void) IIMSLT_C(QDSPNO,actcha,lutno,ittno);


   /* leave lut visibility as it is */

   lutvis = -1;
   (void) IIDSDP_C(QDSPNO,&actcha,1,&lutvis,&ittvis);
   if (actcha == QIMCH)
      (void) Cdazvis(QDSPNO,QIMCH,2,1);
   }

else if (*action == 'L')                                 /* en/disable LUT */
   {
   if (inputi < 0)     
      {
      lutvis = 0;
      if (lutno < 100) lutno += 100;       /* force to 100,101,102,103 */
      }
   else
      {
      lutvis = 7;
      if (inputi == 99)                 /* if 99, use last lut_section */
         {
         if (lutno >= 100) lutno -= 100;           /* force to 0,1,2,3 */
         }
      else
         {
         if ( (inputi >= 0) && (inputi <= 3) )     
            lutno = inputi;
         else
            {
            (void) SCTDIS(war_lutno,0);
            lutno = 0;                       /* default to section 0 */
            }
         }
      inputi = lutno;
      }
   (void) SCKWRI("DAZHOLD",&lutno,10,1,&unit);


   /* select LUT + ITT section */

   itt = 0;
   (void) IIMSLT_C(QDSPNO,actcha,inputi,itt);


   /* set LUT + ITT visibility */

   (void) IIDSDP_C(QDSPNO,&actcha,1,&lutvis,&itt);
   if (actcha == QIMCH)
      (void) Cdazvis( QDSPNO,QIMCH,2,1);               /* display channel */
   }

else if ( *action == 'M' )                   /* load image memory into FCR's */
   {
   QIMCH = actcha;

   if (QIMCH == QOVCH)			/* only for non-X11 */
      {
      if (IDINUM == 11) 
         (void)SCETER(5,"invalid image channel (= overlay channel) ...");
      else
         {
         (void) Cdazvis(QDSPNO,QIMCH,2,1);
         if (QRGBFL != 1) Alphamem(QIMCH);
         }
      return;
      }

   (void) DCGICH(QIMCH);


   /* handle pseudo-colour + RGB mode differently ...! */

   if (QRGBFL != 1)		/* here in non-RGB (3 channels) mode */
      {
      if (lutno < 100)     
         {
         lutvis = 7;				/* use LUT... */
         if ( inputi >= 0  && inputi <= 3 )     
            {
            lutno = inputi;
            (void) SCKWRI("DAZHOLD",&lutno,10,1,&unit);
            }
         else
            inputi = lutno;
         }
      else
         {
         inputi = lutno;
         lutvis = 0;				/* bypass LUT... */
         }


      /* select LUT + ITT section */

      itt = 0;
      (void) IIMSLT_C(QDSPNO,QIMCH,inputi,itt);


      /* display channel on screen + use given LUT section */

      (void) Cdazvis(QDSPNO,QIMCH,2,1);
      Alphamem( QIMCH );
      itt = ITTYES;
      (void) IIDSDP_C(QDSPNO,&QIMCH,1,&lutvis,&itt);
      }

   else                   /* RGB mode: only handle the alpha part */
      Alphamem(QIMCH);
   }

else if (*action == 'R')               /* handle DISPLAY/LUT business here */
   { 
   (void) Cdazvis(QDSPNO,QIMCH,1,refsc);


   /* draw outer rectangle and bars, if graphics channel exists */

   if ((QOVCH != -1) && (IDINUM != 11))
      {
      int   color, posx, posy, lrecx[18], lrecy[18];
      float factx, facty;
      static char *str[5] = { "50", "100", "150", "200", "250" };


      color = dazzin[1];
      factx = QDSZX / 512.;             /* these numbers were calculated */
      facty = QDSZY / 512.;             /* for 512*512 display initially */

      lrecx[0] = lrecx[1] = 0;
      lrecx[2] = CGN_NINT( 87 * factx );
      lrecy[0] = 0;
      lrecy[1] = lrecy[2] = CGN_NINT( 19 * facty );
      (void) IIGPLY_C(QDSPNO,QOVCH,lrecx,lrecy,3,color,1);

      lrecx[0] = CGN_NINT( 110 * factx );
      lrecx[1] = CGN_NINT( 183 * factx );
      (void) IIGPLY_C(QDSPNO,QOVCH,lrecx,lrecy+1,2, color,1);

      lrecx[0] = CGN_NINT( 216 * factx );
      lrecx[1] = CGN_NINT( 283 * factx );
      (void) IIGPLY_C( QDSPNO, QOVCH, lrecx, lrecy + 1, 2, color, 1 );

      lrecx[0] = CGN_NINT( 316 * factx );
      lrecx[1] = CGN_NINT( 383 * factx );
      (void) IIGPLY_C( QDSPNO, QOVCH, lrecx, lrecy + 1, 2, color, 1 );

      lrecx[0] = CGN_NINT( 416 * factx );
      lrecx[1] = CGN_NINT( 483 * factx );
      (void) IIGPLY_C( QDSPNO, QOVCH, lrecx, lrecy + 1, 2, color, 1 );

      lrecx[0]  = lrecx[1]  = CGN_NINT( 511 * factx );
      lrecx[2]  = lrecx[3]  = lrecx[4]  = CGN_NINT( 500 * factx );
      lrecx[5]  = lrecx[6]  = lrecx[7]  = CGN_NINT( 400 * factx );
      lrecx[8]  = lrecx[9]  = lrecx[10] = CGN_NINT( 300 * factx );
      lrecx[11] = lrecx[12] = lrecx[13] = CGN_NINT( 200 * factx );
      lrecx[14] = lrecx[15] = lrecx[16] = CGN_NINT( 100 * factx );
      lrecx[17] = 0;
      for ( ii = 0; ii < 18; ii++ ) lrecy[ii] = 0;
      lrecy[0] = CGN_NINT( 19 * facty );
      for ( ii = 3; ii < 18; ii += 3 ) lrecy[ii] = CGN_NINT( 8 * facty );
      (void) IIGPLY_C( QDSPNO, QOVCH, lrecx, lrecy , 18, color, 1 );


      /* draw numbers */

      posx = CGN_NINT( 94 * factx );
      posy = CGN_NINT( 12 * facty );
      (void) IIGTXT_C( QDSPNO, QOVCH, str[0], posx, posy, 0, 0, color, 0 );

      posx = CGN_NINT( 190 * factx );
      (void) IIGTXT_C( QDSPNO, QOVCH, str[1], posx, posy, 0, 0, color, 0 );

      posx = CGN_NINT( 290 * factx );
      (void) IIGTXT_C( QDSPNO, QOVCH, str[2], posx, posy, 0, 0, color, 0 );

      posx = CGN_NINT( 390 * factx );
      (void) IIGTXT_C( QDSPNO, QOVCH, str[3], posx, posy, 0, 0, color, 0 );

      posx = CGN_NINT( 490 * factx );
      (void) IIGTXT_C( QDSPNO, QOVCH, str[4], posx, posy, 0, 0, color, 0 );
      }
   }

else if (*action == 'S')                      /* handle CLEAR/DISPLAY here */
   { 
   QOVCH = QLSTCH;                  /* use last channel as overlay channel */
   QIMCH = 0;                        /* start with channel 0 for images... */


   /* Now use IIDSEL to do the default configuration */ 

   (void) IIDRST_C(QDSPNO);      /* this call needed on other devices... */
   (void) IIDSEL_C(QDSPNO,1);


   /* Initialize data for cleaned channels */
   
   (void) strcpy(dzmemc,"   ");
   LOADDR = 0;
   SSPX = SSPY = 0;
   NSX = QMSZX;                                   /* nopix in image memory */
   NSY = QMSZY;
   SFPX = SFPY = 1;
   SCALX = SCALY = 1;
   SCROLX = 0;                   /* pixel 0 -> left edge of display screen */
   SCROLY = QMSZY - 1;          /* last chan line -> top line of display */
   ZOOMX = ZOOMY = 1;
   SOURCE = 0;
   ITTYES = 0;
   DZDRAW = 0;
   ZPLANE = 0;

   for (ii=0; ii<=QLSTCH; ii++) DCPICH(ii);


   /* Set up values for key DAZHOLD */

   dazhld[0] = 0;                  /* cursor no. */
   dazhld[1] = -1;                 /* cursor form (-1 = disabled) */
   dazhld[2] = 0;                  /* user split mode (0 = off, 1 = on) */
   dazhld[3] = (QDSZX - 1) / 2;    /* split addresses in x,y */
   dazhld[4] = (QDSZY - 1) / 2;    /* set to center of display */
   dazhld[5] = 1;                  /* zoom factors in x,y */
   dazhld[6] = 1;
   dazhld[7] = 0;                  /* refscale flag */
   dazhld[8] = 1;                  /* overlay_set flag */
   dazhld[9] = 0;                  /* last referenced lut section */
   dazhld[10] = 1;                 /* no. of memory boards per channel */
   (void) SCKWRI( "DAZHOLD", dazhld, 1, 11, &unit );

   /* finally clear + enable also the overlay */

   (void) IIMCMY_C(QDSPNO,&QOVCH,1,0);
   (void) Cdazvis(QDSPNO,QOVCH,2,1);
   }

else
   SCETER(1,"SUBMEM: unknown option");

}

/*

*/

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.COPYRIGHT   (c) 1994 European Southern Observatory
.IDENTIFIER  CONCHA_C
.LANGUAGE    C
.AUTHOR      K. Banse				IPG-ESO Garching
.KEYWORDS    Image Display , memory board
.PURPOSE     fill the channel with a constant value
.ALGORITHM   use IDI interfaces

.INPUT/OUTPUT
  call as    CONCHA_C(display,chan,aux_flag,value)

  input:
         int  display		device id
         int  chan		memory channel no.
         int  aux_flag		if set to 1, check keyword AUX_MODE(9) first,
				if we should update the channel;
				AUX_MODE(9) = 1, yes do it
				AUX_MODE(9) = 0, no don't do it
         int  value		constant to write into memory channel

.RETURNS     nothing

.VERSIONS    1.00       940325  F2C, taken from LOADWN.FOR   RvH
	     1.10       960522  change meaning of parameter #3, KB
------------------------------------------------------------*/


void CONCHA_C(display,chan,aux_flag,value)
int display, chan, aux_flag, value;

{
if (aux_flag == 1)		/* check AUX_MODE(9) first ... */
   {
   int iav, knul, unit, doit;

   (void) SCKRDI("AUX_MODE",9,1,&iav,&doit,&unit,&knul);
   if (doit != 1) return;
   }


(void) IIMCMY_C(display,&chan,1,value);
}
