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

/***********************************************************************
*                                                               
*   file idilocal1.c
*                                                                 
*   IDI  Device Dependent Routines                                 
*   (version for XWindows release 11)                               
*                                                                    
*
* V 1.00 880219  F.Pasian, P.Santin - Trieste Astronomical Observatory  
* V 2.00 890102  K. Banse  ESO - Garching                              
*
*  Xwstinit		: Connect to display + fill Xworkst structure;
*  wr_lut               : Write XWindows LUT;
*  rd_lut               : Read  XWindows LUT;
*  allo_mem             : Allocate memory for "Display Channel"
*  allo_zmem            : Allocate memory for "Display Channel"
*  get_hcopy            : Get hardcopy
*  smv                  : Set Memory Visibility : no scroll + zoom
*  int_enable           : Enable Interaction;
*  int_disable          : Disable Intaraction;
*  exit_trg_enable      : Enable Exit Trigger;
*  wait_int             : Wait for Interaction;
*  trigsta              : Test Trigger Status;

 090424		last modif
************************************************************************/

/*

*/

#include    <stdlib.h>
#include    <stdio.h>

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



static Bool  discard = True;

static int error_X;
static int  interact = 0;

static long int Def_Mask = (ExposureMask | StructureNotifyMask);

static float  rval;

static Window  mywindow;


/*
set up for "normal" case [*][0] and inverse byte order [*][1]
RGBord = 1: 0 R G B 	-> B G R 0   with inverse byte order
RGBord = 0: 0 B G R 	-> R G B 0   with inverse byte order  
(lowest byte is right)
*/

static int  shift24[3][2] =
        {
         {0, 24},               /* red/blue for RGBord 0/1 */
         {8, 16},               /* green */
         {16, 8},               /* blue/red for RGBord 0/1 */
        };

static int shift16[3] =
	{
         0,               /* red/blue for RGBord 0/1 */
         5,               /* green */
         11               /* blue/red for RGBord 0/1 */
	};
/*

*/

int myhandler(mydisp,myerr)

Display *mydisp;
XErrorEvent *myerr;

{
error_X = 1;		/* indicate an error */
return (0);
}
 
/*

*/
 
/* ---- Connect to Xserver + fill Xworkst stuff  ----------------------*/

int Xwstinit(flg,screen,no,fono,minlut)
int  flg;		/* IN: 0 = first call
			       1 = second call for image window
			       2 = second call for graphics window 
			       3 = ?  */
int  no, *fono, minlut;
char  *screen;		/* IN: name of display if flg=0
			       Pseudo or True if flg>0   */

{
unsigned long int   plane_mask[1], pixels[256];
int    ii, jalloc, sys_colors, plot_colors;
int    isw, ddepth, tmpx, i, j, np, rgbset;
register int  k, nr;

unsigned char  tempa;
static char *plotcolors[9] = 
{ "black", "black", "white", "red", "green",
  "blue", "yellow", "magenta", "cyan" };



 

/*  -----------------  */
/* Connect to X server */
/*  -----------------  */


if (flg == 0)
   {
#ifdef vms
   if (no == 0)                 /* index 0 reserved for "default" display */
      mydisp[no] = XOpenDisplay("DECW$DISPLAY");
   else
#endif

   mydisp[no] = XOpenDisplay(screen);
   if (!mydisp[no]) return(XCONNERR);

   myscreen = DefaultScreen(mydisp[no]);
   rw[no] = XRootWindow(mydisp[no],myscreen);
   Xworkst[no].white = WhitePixel(mydisp[no],myscreen);
   Xworkst[no].black = BlackPixel(mydisp[no],myscreen);


/* build up full byte of black pixels */

   tempa = (unsigned char) Xworkst[no].black;
   Xworkst[no].blmask = tempa;
   for (i=0; i<8; i++)
      {
      Xworkst[no].blmask <<= 1;
      Xworkst[no].blmask += tempa;
      }

   Xworkst[no].width = DisplayWidth(mydisp[no],myscreen);
   Xworkst[no].height = DisplayHeight(mydisp[no],myscreen);
   Xworkst[no].depth = DefaultDepth(mydisp[no],myscreen);
   Xworkst[no].nobyt = -99;		/* indicate, that it's not set yet */
   Xworkst[no].lutsize = 0;
   Xworkst[no].lutlen = 0;
   Xworkst[no].auxcol = 0;
   Xworkst[no].RGBord = 0;

   return (II_SUCCESS);
   }


/*  -----------------                  */
/*  here for the 2. call of Xwstinit   */
/*  -----------------                  */

/*  get Fonts: first try given font no.s, 
    then fixed names, finally fixed names with wild card  */

if (flg != 3)
   {
   k = font_load(0,no,fono);			/* get Fonts */
   if (k < 0) return(NOFONTS);
   }

sys_colors = 0;
plot_colors = 0;

myvis[no] = XDefaultVisual(mydisp[no],myscreen);
rgbset = DoRed | DoGreen | DoBlue;

if (*screen == 'T')
   {
   isw = DirectColor;
   ddepth = 24;
   Xworkst[no].visual = 3;
   Xworkst[no].lutflag = -1;
   Xworkst[no].ownlut = -1;		/* only display of LUT is o.k. */
   Xworkst[no].nolut = 1;

   if (myvis[no]->class != isw)
      {                                 /* we cannot use default visual */
      k = XMatchVisualInfo(mydisp[no],myscreen,ddepth,isw,&vinfo);
      if (!k)
         {
         isw = TrueColor;
         if (myvis[no]->class != isw)
            {                           /* also this not the default visual */
            k = XMatchVisualInfo(mydisp[no],myscreen,ddepth,isw,&vinfo);
            if (!k) return (BADVISUAL);
         
            myvis[no] = vinfo.visual;
            Xworkst[no].depth = vinfo.depth;
            }
         }
      else
         {
         myvis[no] = vinfo.visual;
         Xworkst[no].depth = vinfo.depth;
         }
      }
   
   if (Xworkst[no].depth == 24 )
      nr = 0x00ff0000;
   else
      nr = 0xff000000;
   if (myvis[no]->red_mask == nr) Xworkst[no].RGBord = 1;
   }

else
   {
   Xworkst[no].lutflag = 0;
   Xworkst[no].ownlut = 1;

   if (*(screen+1) == 'S')		/* PseudoColor */
      {
      isw = PseudoColor;
      Xworkst[no].visual = 2;		/* visual = 2 for PseudoColor */
      ddepth = 8;
   
      if (myvis[no]->class != isw)
         {				/* we cannot use default visual */
         k = XMatchVisualInfo(mydisp[no],myscreen,ddepth,isw,&vinfo);
         if (!k) goto Pseudo_on_RGB;		/* no Pseudo visual there! */

         myvis[no] = vinfo.visual;
         Xworkst[no].depth = vinfo.depth;
         }
      goto after_visual;
      }

   else if (*(screen+1) == 'D')		/* PseudoColor on top of DirectColor */
      isw = DirectColor;

   else					/* PseudoColor on top of TrueColor */
      {
      isw = TrueColor;
      Xworkst[no].ownlut = 0;
      }

   if (myvis[no]->class != isw)
      {
      ddepth = 24;
      k = XMatchVisualInfo(mydisp[no],myscreen,ddepth,isw,&vinfo);
      if (!k) return (BADVISUAL);
         
      myvis[no] = vinfo.visual;
      Xworkst[no].depth = vinfo.depth;
      }
   goto setup_RGB;


   /* first try PseudoColor on top of DirectColor and then on TrueColor */

  Pseudo_on_RGB:
   isw = DirectColor;
   if (myvis[no]->class != isw)
      {
      ddepth = 24;
      k = XMatchVisualInfo(mydisp[no],myscreen,ddepth,isw,&vinfo);
      if (!k)
         {
         isw = TrueColor;
         Xworkst[no].ownlut = 0;
         if (myvis[no]->class != isw)
            { 
            k = XMatchVisualInfo(mydisp[no],myscreen,ddepth,isw,&vinfo);
            if (!k) return (BADVISUAL);
         
            myvis[no] = vinfo.visual;
            Xworkst[no].depth = vinfo.depth;
            }
         }
      else
         {
         myvis[no] = vinfo.visual;
         Xworkst[no].depth = vinfo.depth;
         }
      }

  setup_RGB:
   Xworkst[no].nolut = 1;
   Xworkst[no].visual = 4;
 
   /* A 16-bit truecolor emulation of pseudo should really be >= 256 cells */

   if (myvis[no]->class == TrueColor && Xworkst[no].depth == 16 
       && myvis[no]->map_entries <= 256) 
      {
      (void) printf("16 bit display: no. of cells = %d, will be set to 256\n",
                    myvis[no]->map_entries);
      myvis[no]->map_entries = 256;
      }

   Xworkst[no].lutsize = myvis[no]->map_entries;
   if (Xworkst[no].depth == 16 )
      nr = 0x00f800;
   else
      nr = 0x00ff0000;
   if (myvis[no]->red_mask == nr) Xworkst[no].RGBord = 1;
   }



/* we don't work with less than 8 bits/pixel anymore... (980112) */

after_visual:
if (Xworkst[no].depth < 8) return (BADXWTYPE);


for (nr=0; nr<256; nr++)
   {
   Xworkst[no].mapin[nr] = Xworkst[no].mapout[nr] = nr;
   }


if (myvis[no]->class != PseudoColor)
   {
   Xworkst[no].nobyt = 3;

   if (myvis[no]->class == DirectColor)
      {
      cmap[no][0] = XCreateColormap(mydisp[no],rw[no],myvis[no],AllocNone);

      if (Xworkst[no].visual == 3)
         {
         Xworkst[no].lutsize = 256;
         k = buildRGBLUT(no,Xworkst[no].lutsize,mycolr[no],pixels);
         if (k < 16) return (NOCOLALLO);
         Xworkst[no].lutsize = k;

         for (i=0; i<9; i++)
            {
            fixcolr[no][i].flags = rgbset;
            x11stat = XAllocNamedColor(mydisp[no],cmap[no][0],plotcolors[i],
                                       &exact,&fixcolr[no][i]);
            }
         }

      else				/* PseudoColor on DirectColor */
         {
         plot_colors = 9;
         for (ii=0; ii<plot_colors;ii++)
            {
            x11stat = XAllocNamedColor(mydisp[no],cmap[no][0],plotcolors[ii],
                                       &exact,&fixcolr[no][ii]);
            if (!x11stat)
               {
               (void) printf
                      ("could not allocate NamedColor %s\n",plotcolors[ii]);
               return(NOCOLALLO);
               }
            pixels[ii] = fixcolr[no][ii].pixel;
            }
         plane_mask[0] = 0;                     /* free the color cells */
         XFreeColors(mydisp[no],cmap[no][0],pixels,plot_colors,plane_mask[0]);

         ii = Xworkst[no].lutsize + plot_colors;
         k = buildRGBLUT(no,ii,mycolr[no],pixels);
         if (k < 16) return (NOCOLALLO);
         Xworkst[no].lutsize = k;

         for (nr=0,j=0; j<plot_colors; nr++,j++)
            {
            mycolr[no][nr].red = fixcolr[no][j].red;
            mycolr[no][nr].green = fixcolr[no][j].green;
            mycolr[no][nr].blue = fixcolr[no][j].blue;
            fixcolr[no][j].pixel = pixels[nr];
            }
         XStoreColors(mydisp[no],cmap[no][0],&mycolr[no][0],plot_colors);

         Xworkst[no].lutflag = 1;
         }
      }

   else				/* TrueColor - no change of colors possible */
      {
      cmap[no][0] = XCreateColormap(mydisp[0],rw[no],myvis[no],AllocNone);

      plot_colors = 9;
      for (ii=0; ii<plot_colors;ii++)
         {
         x11stat = XAllocNamedColor(mydisp[no],cmap[no][0],plotcolors[ii],
                                    &exact,&fixcolr[no][ii]);
         if (!x11stat)
            {
            (void) printf
                   ("could not allocate NamedColor %s\n",plotcolors[ii]);
            return(NOCOLALLO);
            }
         pixels[ii] = fixcolr[no][ii].pixel;
         }
      }


/*
   Xworkst[no].auxcol = plot_colors;
   Xworkst[no].lutlen = Xworkst[no].lutsize - Xworkst[no].auxcol;
*/
   Xworkst[no].lutlen = Xworkst[no].lutsize;
   goto after_colors;
   }

else
   {
   Xworkst[no].lutlen = 2 << (Xworkst[no].depth-1);
   if (Xworkst[no].depth > 8)
      Xworkst[no].nobyt = 2;
   else
      Xworkst[no].nobyt = 1;
   }


LUTretry:
Xworkst[no].auxcol = sys_colors + plot_colors;

np = 0;
 

if (Xworkst[no].lutflag == 0)
   {
   for (i=0; i<Xworkst[no].nolut; i++)
      {
      jalloc = Xworkst[no].lutsize;
      cmap[no][i] = DefaultColormap(mydisp[no],myscreen);
      
      if (Xworkst[no].ownlut == -1)		/* we only do it for i = 0 */
         {
         Xworkst[no].lutlen = Xworkst[no].lutsize;
         for (ii=0; ii<9;ii++)
            x11stat = XAllocNamedColor(mydisp[no],cmap[no][i],plotcolors[ii],
                                     &exact,&fixcolr[no][ii]);
         goto after_colors;
         }

      if (flg != 3)
         {
         for (ii=0; ii<9;ii++)
            x11stat = XAllocNamedColor(mydisp[no],cmap[no][i],plotcolors[ii],
                                     &exact,&fixcolr[no][ii]);
         Xworkst[no].lutlen = 9;
         }

      if (flg != 2)
         {
        color_loop:
         x11stat = XAllocColorCells(mydisp[no],cmap[no][i],0,plane_mask,
                                  0,pixels,jalloc);
         if (x11stat) 
            {
            Xworkst[no].lutsize = jalloc;
            tmpx = jalloc - 1;			/* index of last pixel */
            }
         else
            {
            jalloc --;
            if (jalloc < minlut)	/* not enough space in Colormap */
               {
               if (flg == 3)
		  {		/* we have already allocated plot colours */
                  for (ii=0; ii<9;ii++) pixels[ii] = fixcolr[no][ii].pixel;
                  plane_mask[0] = 0;
                  XFreeColors(mydisp[no],cmap[no][i],pixels,9,plane_mask[0]);
                  }
               flg = 2;			/* we do it only once */
               Xworkst[no].lutflag = 1;
               sys_colors = 16;
               plot_colors = 9;
               goto LUTretry;
               }
            else
               goto color_loop;
            } 
   
         k = np;
         if (pixels[0] > pixels[tmpx])
            {
            for (nr=0; nr<jalloc; nr++)
               {
               mycolr[no][k].pixel = Xworkst[no].mapin[k] = pixels[tmpx--];
               mycolr[no][k].flags = rgbset;
               k ++;
               }
            }
         else
            {
            for (nr=0; nr<jalloc; nr++)
               {
               mycolr[no][k].pixel = Xworkst[no].mapin[k] = pixels[nr];
               mycolr[no][k].flags = rgbset;
               k ++;
               }
            }
         for (nr=0; nr<jalloc; nr++)
            {
            k = Xworkst[no].mapin[nr];
            Xworkst[no].mapout[k] = nr;
            } 
               
         np += jalloc;

         Xworkst[no].lutlen = Xworkst[no].lutsize;
         }
      }
   }

else if (Xworkst[no].lutflag > 0)		/* private LUT */
   {

   int koff;

   if (Xworkst[no].ownlut == -1) 
      {
      Xworkst[no].lutlen = Xworkst[no].lutsize;
      goto after_colors;
      }

   jalloc = myvis[no]->map_entries;
   if (jalloc > Xworkst[no].lutsize) 
      {				/* copy as many current colors as possible */
      sys_colors = myvis[no]->map_entries - Xworkst[no].lutsize - plot_colors;
      Xworkst[no].auxcol = sys_colors + plot_colors;
      }


   if (Xworkst[no].white > 2)
      {					/* keep high end of LUT */
      koff = jalloc - Xworkst[no].auxcol;
      Xworkst[no].lutflag = 2;
      }
   else			
      {					/* keep low end of LUT */
      Xworkst[no].lutflag = 1;
      koff = sys_colors;
      }

   for (i=0; i<Xworkst[no].nolut; i++)
      {
      cmap[no][i] = XCreateColormap(mydisp[no],rw[no],myvis[no],AllocNone);


      /* get the color components for the Plot Colors and
         free the color cells again */

      if (i == 0)			/* do it only once */
         {
         for (ii=0; ii<9;ii++)
            {
            x11stat = XAllocNamedColor(mydisp[no],cmap[no][i],plotcolors[ii],
                                       &exact,&fixcolr[no][ii]);
            if (!x11stat) 
               {
               (void) printf
                      ("could not allocate NamedColor %s\n",plotcolors[ii]);
               return(NOCOLALLO);
               } 
            pixels[ii] = fixcolr[no][ii].pixel;
            }
         plane_mask[0] = 0;			/* free the color cells */
         XFreeColors(mydisp[no],cmap[no][i],pixels,9,plane_mask[0]);
         }
 

      /* now allocate all wanted color cells */

      x11stat = XAllocColorCells(mydisp[no],cmap[no][i],0,plane_mask,
                                 0,pixels,jalloc);

      if (!x11stat) 
         {
         (void) printf("could not allocate %d color cells...\n",jalloc);
         return(NOCOLALLO);
         } 

      k = np;
      for (nr=0; nr<jalloc; nr++)
         {
         mycolr[no][k].pixel = k;
         mycolr[no][k].flags = rgbset;
         k ++;
         }
      

      /*  copy all colors from the Default Color Map */

      XQueryColors(mydisp[no],DefaultColormap(mydisp[no],myscreen),
                   &mycolr[no][np],jalloc);

      k = np;
      for (nr=0; nr<jalloc; nr++)		/* reset pixels */
         {
         mycolr[no][k].pixel = pixels[nr];
         Xworkst[no].mapin[k] = pixels[nr] + Xworkst[no].auxcol;
         k++;
         }

      for (nr=0; nr<jalloc; nr++)
         {
         k = Xworkst[no].mapin[nr];
         Xworkst[no].mapout[k] = nr;
         }

      for (nr=koff,j=0; j<plot_colors; nr++,j++)
         {
         mycolr[no][nr].red = fixcolr[no][j].red;
         mycolr[no][nr].green = fixcolr[no][j].green;
         mycolr[no][nr].blue = fixcolr[no][j].blue;
         fixcolr[no][j].pixel = pixels[nr];
         }

      XStoreColors(mydisp[no],cmap[no][i],&mycolr[no][koff],plot_colors);

      np += jalloc;
      }

   Xworkst[no].lutsize = jalloc;
   Xworkst[no].lutlen = jalloc - Xworkst[no].auxcol;
   }


after_colors:
for (ii=0; ii<9; ii++)			/* save pixel value of fixed colours */
   Xworkst[no].fixpix[ii] = fixcolr[no][ii].pixel;

Xworkst[no].white = Xworkst[no].fixpix[2];
Xworkst[no].black = Xworkst[no].fixpix[1];

Xworkst[no].lutfct = XLUTFACT;
Xworkst[no].lutinv = 1.0 / Xworkst[no].lutfct;
   
return (II_SUCCESS);
}

/*

*/

/* ---- write XWindows LUT ------------------------------------------- */

/* load look up table                                           */

void wr_lut (dspno,lut,flag)
int  dspno;		/* IN: display no. */
int  flag;		/* IN: visibility flag, 0 = off, 1 = on */
LUT_DATA  *lut;		/* IN: pointer to LUT data */

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

int    no, memid, ioff;
int    np, j, k, i;
float  lutval, fval;
register int loop;



itt = (ITT_DATA *) 0;

no = ididev[dspno].screen;
np = ididev[dspno].lutsect;
j = np * Xworkst[no].lutsize;
ioff = j;
if (Xworkst[no].lutflag == 1) ioff += Xworkst[no].auxcol;

conf = ididev[dspno].confptr;
memid = conf->memid;
if (memid == conf->overlay)
   k = 0;			/* no ITT for overlay channel  */
else
   {
   mem = conf->memory[memid];
   itt = mem->ittpntr;
   k = itt->vis;
   }
i = 0;


if (Xworkst[no].ownlut == 1) goto no_pix_shift;

if (Xworkst[no].visual == 4)
   {					/* Pseudo on top of TrueColor */
   float  fr;
   int  ired, igreen, iblue;
   int  i0, shred, shblue, shgreen;	/* shift */
   INTBAR    *bar;




   /* handle 16bit LUT here */

   if ((Xworkst[no].depth == 16) && (myvis[no]->map_entries <= 256))
      {
      unsigned short int koko, jojo;
      unsigned int  modred, modblue, modgreen;	
      int  i1;
      unsigned char* bytptra=(unsigned char *) &koko;
      unsigned char* bytptrb=(unsigned char *) &jojo;

      if (Xworkst[no].flag24[0] == 0)	/* write swap flag */
         {				/* normal byte order */
         i0 = 0;			/* b[0] = a[0], b[1] = a[1] */
         i1 = 1;
         }
      else				/* low bytes swapped */
         {
         i0 = 1;			/* b[0] = a[1], b[1] = a[0] */
         i1 = 0;
         }


      if (Xworkst[no].RGBord != 1)
         {
         shred = shift16[0];
         shgreen = shift16[1];
         shblue = shift16[2];
         }
      else
         {
         shred = shift16[2];
         shgreen = shift16[1];
         shblue = shift16[0];
         }
      modred = 3;		/* red size = 5 bits */
      modgreen = 2;		/* green size = 6 bits */
      modblue = 3;		/* blue size = 5 bits */
      jojo = 0;
  
      if (flag > 0)
         {
         fr = (Xworkst[no].lutlen - 1.0)/Xworkst[no].lutfct;

         if (k == 1)
            {
            for (loop=ioff; loop<(Xworkst[no].lutlen+ioff); loop++)
               {
               k = itt->val[i++];
               ired   = (int) (fr * lut->lutr[k]);
               ired = ired >> modred;
               igreen = (int) (fr * lut->lutg[k]);
               igreen = igreen >> modgreen;
               iblue  = (int) (fr * lut->lutb[k]);
               iblue = iblue >> modblue;

               koko = (unsigned short int) ((ired << shred) | 
                       (igreen << shgreen) | (iblue << shblue));
               *bytptrb = *(bytptra+i0);
               *(bytptrb+1) = *(bytptra+i1);
               Xworkst[no].mapin[loop] = jojo;
               }
            }
         else
            {
            for (loop=ioff; loop<(Xworkst[no].lutlen+ioff); loop++)
               {
               ired   = (int) (fr * lut->lutr[i]);
               ired = ired >> modred;
               igreen = (int) (fr * lut->lutg[i]);
               igreen = igreen >> modgreen;
               iblue  = (int) (fr * lut->lutb[i++]);
               iblue = iblue >> modblue;

               koko = (unsigned short int) ((ired << shred) | 
                       (igreen << shgreen) | (iblue << shblue));
               *bytptrb = *(bytptra+i0);
               *(bytptrb+1) = *(bytptra+i1);
               Xworkst[no].mapin[loop] = jojo;
               }
            }
         }
      else
         {
         fr = Xworkst[no].lutlen - 1.0;
         rval = 1.0 / fr;

         if (k == 1)
            {
            for (loop=ioff; loop<(Xworkst[no].lutlen+ioff); loop++)
               {
               igreen = iblue = ired = itt->val[i++];   /* in [0,LUTsize-1] */
               ired = ired >> modred;
               igreen = igreen >> modgreen;
               iblue = iblue >> modblue;

               koko = (unsigned short int) ((ired << shred) | 
                       (igreen << shgreen) | (iblue << shblue));
               *bytptrb = *(bytptra+i0);
               *(bytptrb+1) = *(bytptra+i1);
               Xworkst[no].mapin[loop] = jojo;
               }
            }
         else
            {
            fval = 0.0;
            for (loop=ioff; loop<(Xworkst[no].lutlen+ioff); loop++)
               {
               igreen = iblue = ired = (int) (fval * fr);
               ired = ired >> modred;
               igreen = igreen >> modgreen;
               iblue = iblue >> modblue;

               koko = (unsigned short int) ((ired << shred) | 
                       (igreen << shgreen) | (iblue << shblue));
               *bytptrb = *(bytptra+i0);
               *(bytptrb+1) = *(bytptra+i1);
               Xworkst[no].mapin[loop] = jojo;

               fval += rval;
               }
            }
         }
      }


   /* handle 24bit LUT here */

   else
      {
      if (Xworkst[no].flag24[0] == 0)		/* write swap flag */
         i0 = 0;				/* normal byte order */
      else
         i0 = 1;

      if (Xworkst[no].RGBord != 1)
         {
         shred = shift24[0][i0];
         shgreen = shift24[1][i0];
         shblue = shift24[2][i0];
         }
      else
         {
         shred = shift24[2][i0];
         shgreen = shift24[1][i0];
         shblue = shift24[0][i0];
         }

      if (flag > 0)
         {
         fr = (Xworkst[no].lutlen - 1.0)/Xworkst[no].lutfct;

         if (k == 1)
            {
            for (loop=ioff; loop<(Xworkst[no].lutlen+ioff); loop++)
               {
               k = itt->val[i++];
               ired   = (int) (fr * lut->lutr[k]);
               igreen = (int) (fr * lut->lutg[k]);
               iblue  = (int) (fr * lut->lutb[k]);
               ired   = ired << shred;
               igreen = igreen << shgreen;
               iblue = iblue << shblue;
               Xworkst[no].mapin[loop] = ired | igreen | iblue;
               }
            }
         else
            {
            for (loop=ioff; loop<(Xworkst[no].lutlen+ioff); loop++)
               {
               ired   = (int) (fr * lut->lutr[i]);
               igreen = (int) (fr * lut->lutg[i]);
               iblue  = (int) (fr * lut->lutb[i++]);
               ired   = ired << shred;
               igreen = igreen << shgreen;
               iblue = iblue << shblue;
               Xworkst[no].mapin[loop] = ired | igreen | iblue;
               }
            }
         }
      else
         {
         fr = Xworkst[no].lutlen - 1.0;
         rval = 1.0 / fr;

         if (k == 1)
            {
            for (loop=ioff; loop<(Xworkst[no].lutlen+ioff); loop++)
               {
               igreen = iblue = ired = itt->val[i++];	/* in [0,LUTsize-1] */
               ired   = ired << shred;
               igreen = igreen << shgreen;
               iblue = iblue << shblue;
               Xworkst[no].mapin[loop] = ired | igreen | iblue;
               }
            }
         else
            {
            fval = 0.0;
            for (loop=ioff; loop<(Xworkst[no].lutlen+ioff); loop++)
               {
               igreen = iblue = ired = (int) (fval * fr);
               ired   = ired << shred;
               igreen = igreen << shgreen;
               iblue = iblue << shblue;
               Xworkst[no].mapin[loop] = ired | igreen | iblue;
               fval += rval;
               }
            }
         }
      }

   if (ididev[dspno].bar != 0)
      {
      bar = ididev[dspno].bar;
      if (bar->vis == 1) updalutbar(dspno,bar);
      }
   }
return;


no_pix_shift:
if (flag > 0)
   {
   if (k == 1) 
      {
      for (loop=ioff; loop<(Xworkst[no].lutlen+ioff); loop++)
         {
         k = itt->val[i++];
         mycolr[no][loop].red   = (unsigned short) lut->lutr[k];
         mycolr[no][loop].green = (unsigned short) lut->lutg[k];
         mycolr[no][loop].blue  = (unsigned short) lut->lutb[k];
         }
      }
   else
      {
      for (loop=ioff; loop<(Xworkst[no].lutlen+ioff); loop++)
         {
         mycolr[no][loop].red   = (unsigned short) lut->lutr[i];
         mycolr[no][loop].green = (unsigned short) lut->lutg[i];
         mycolr[no][loop].blue  = (unsigned short) lut->lutb[i++];
         }
      }
   }

else
   {
   rval = 1.0 / (Xworkst[no].lutlen - 1.0);
   if (k == 1) 
      {
      for (loop=ioff; loop<(Xworkst[no].lutlen+ioff); loop++)
         {
         fval = (float) itt->val[i++];			/* in [0,LUTsize-1]  */
         fval *= rval;					/* now in [0.,1.]    */
         lutval = fval * Xworkst[no].lutfct;
         mycolr[no][loop].red   = (unsigned short) lutval;
         mycolr[no][loop].green = (unsigned short) lutval;
         mycolr[no][loop].blue  = (unsigned short) lutval;
         }
      }
   else
      {
      fval = 0.0;
      for (loop=ioff; loop<(Xworkst[no].lutlen+ioff); loop++)
         {
         lutval = fval * Xworkst[no].lutfct;
         mycolr[no][loop].red   = (unsigned short) lutval;
         mycolr[no][loop].green = (unsigned short) lutval;
         mycolr[no][loop].blue  = (unsigned short) lutval;
         fval += rval;
         }
      }
   }


XStoreColors (mydisp[no],cmap[no][np],&mycolr[no][j],Xworkst[no].lutsize);

}
/*

*/

/* ---- read XWindows LUT ------------------------------------------- */

/* read look up table                                           */

void rd_lut (dspno,lut)
int dspno;
LUT_DATA  *lut;

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

int    np, j, k, no, memid, ioff;
register int loop;


no = ididev[dspno].screen;
if (Xworkst[no].ownlut != 1) return;            /* no LUT used ... */

np = ididev[dspno].lutsect;
j = np * Xworkst[no].lutsize;
ioff = j;
if (Xworkst[no].lutflag == 1)
   ioff += Xworkst[no].auxcol;

conf = ididev[dspno].confptr;
memid = conf->memid;
if (memid == conf->overlay)
   k = 0;			/* no ITT for overlay channel  */
else
   {
   mem = conf->memory[memid];
   itt = mem->ittpntr;
   k = itt->vis;
   }

/* we only read via X11 if ITT is not set */

if (k == 0) 
   {
   XQueryColors (mydisp[no],cmap[no][np],&mycolr[no][j],Xworkst[no].lutlen);

   for (loop=0; loop<Xworkst[no].lutlen; loop++)
      {
      lut->lutr[loop] = mycolr[no][loop+ioff].red;
      lut->lutg[loop] = mycolr[no][loop+ioff].green;
      lut->lutb[loop] = mycolr[no][loop+ioff].blue;
      }
   } 
}

/*

*/

/* ---- allocate memory + create XImage structure -------------------- */

int allo_mem(dspno,mem,memid)
int  dspno, memid;
MEM_DATA  *mem;

{
int      total, np, no, x, y;
int      myhandler();
unsigned int w, h, bw, d;


CONF_DATA  *conf;


/* check, if it's id of overlay channel  */

conf = ididev[dspno].confptr;
if (memid == conf->overlay) return (II_SUCCESS);     /* Yes. So we leave.. */

no = ididev[dspno].screen;
if (Xworkst[no].depth > 8)
   np = 32;
else
   np = 8;

mxpix[dspno][memid] = 
XCreatePixmap(mydisp[no],mwndw[dspno],mem->xsize,mem->ysize,Xworkst[no].depth);


/* we may not have enough memory for the Pixmaps, so we have to check it */

error_X = 0;
XSetErrorHandler(myhandler);		/* use our Error handler */
x11stat = XGetGeometry(mydisp[no],mxpix[dspno][memid],&mywindow,
                       &x,&y,&w,&h,&bw,&d);
XSetErrorHandler(None);			/* use default Error handler */

myima = XCreateImage(mydisp[no],myvis[no],Xworkst[no].depth,ZPixmap,
                     0,0,mem->xsize,mem->ysize,np,np*mem->xsize/8);

total = myima->bytes_per_line * mem->ysize;
myima->data = malloc((size_t)total);
if (myima->data == 0) return (MEMALLERR);



/* clear the allocated memory + copy to Pixmap  */

mxima[dspno][memid] = myima;
mem->mmbm = myima->data;
zero_mem(dspno,mem,0,0);

if (error_X != 0)
   mem->pixmap = 0;
else
   {
   mem->pixmap = 1;
   idi_putimage(mydisp[no],mxpix[dspno][memid],gcima[dspno],
             myima,0,0,0,0,mem->xsize,mem->ysize);
   }

return (II_SUCCESS);
}
/*

*/

/* ---- allocate zoom memory + create XImage structure -------------------- */

int allo_zmem(dspno,mem,memid)
int  dspno, memid;
MEM_DATA  *mem;

{
int      total, np, no;
int  myhandler();

CONF_DATA  *conf;


/* check, if it's id of overlay channel  */

conf = ididev[dspno].confptr;
if (memid == conf->overlay) return (II_SUCCESS);     /* Yes. So we leave.. */

no = ididev[dspno].screen;
if (Xworkst[no].depth > 8)
   np = 32;
else
   np = 8;

myima = XCreateImage(mydisp[no],myvis[no],Xworkst[no].depth,ZPixmap,
                     0,0,mem->xsize,mem->ysize,np,np*mem->xsize/8);

total = myima->bytes_per_line * mem->ysize;
myima->data = malloc((size_t)total);
if (myima->data == 0) return (MEMALLERR);

mzima[dspno][memid] = myima;
mem->zmbm = myima->data;
zero_mem(dspno,mem,1,0);

return (II_SUCCESS); 
}

/*

*/

/* ---- create XImage structure for hardcopy and fill it   -------- */

int get_hcopy(dspno,mem,memid)
int  dspno, memid;
MEM_DATA    *mem;

{
int   total, tmpx, tmpy, np, no;


no = ididev[dspno].screen;
tmpx = ididev[dspno].xsize;  tmpy = ididev[dspno].ysize;

if (ididev[dspno].hcopy == (char *) 0) 
   {
   if (Xworkst[no].depth > 8)
      np = 32;
   else
      np = 8;


   /* here we create the structure + allocate memory  */

   myima = XCreateImage(mydisp[no],myvis[no],Xworkst[no].depth,ZPixmap,
                        0,0,tmpx,tmpy,np,np*tmpx/8);

   total = myima->bytes_per_line * tmpy;
   myima->data = malloc((size_t)total);
   if (myima->data == (char *) 0) return (MEMALLERR);

   hcopy[dspno] = myima;
   ididev[dspno].hcopy = myima->data;
   }


/* here we make the screen dump  */

np = -1;
xdrawable = mwndw[dspno];
if (mem->pixmap == 1) 
   {
   XGetWindowAttributes(mydisp[no],mwndw[dspno],&attributes);
   if (attributes.map_state != IsViewable)
      {
      xdrawable = mxpix[dspno][memid];
      copy_over(dspno,memid,1);		/* put graphics into Pixmap */
      }
   }

hcopy[dspno] = idi_getsubimage(mydisp[no],xdrawable,0,0,tmpx,tmpy,
                            np,ZPixmap,hcopy[dspno],no);
XFlush(mydisp[no]);

return (II_SUCCESS);
}
/*

*/

/* ---- set memory visibility -------------------------------------- */

void smv (flag,dspno,mem,memid,srcx,srcy,xdim,ydim,dstx,dsty)
int       flag, dspno, memid, srcx, srcy, dstx, dsty;
MEM_DATA  *mem;
unsigned int  xdim, ydim;

{
int  no;


no = ididev[dspno].screen;

if (mem->zoom > 1) 
   {
   if (mem->pixmap != 1)        /* we have no Pixmaps (not enough memory) */

      /* load image zoom mem. into the Window */

      idi_putimage(mydisp[no],mwndw[dspno],gcima[dspno],mzima[dspno][memid],
                0,0,0,0,xdim,ydim);

   else
      {                         /* we have Pixmaps */
   
      /* first (if flag > 1), load full image mem. into Pixmap */

      if (flag > 1)
         idi_putimage(mydisp[no],mxpix[dspno][memid],gcima[dspno],
                   mzima[dspno][memid],0,0,0,0,mem->xsize,mem->ysize);
   
   
      /* then (if flag = 0, 1, or 2) copy the Pixmap to the Window */
     
      if (flag < 3)
      XCopyArea(mydisp[no],mxpix[dspno][memid],mwndw[dspno],gcima[dspno],
                0,0,xdim,ydim,0,0);
      }
   }

else
   {
   if (flag > 10)		/* do not clear for rectangles */
      flag -= 10;
   else
      {
      if (dstx != 0) 			/* because of scrolling */
         XClearArea(mydisp[no],mwndw[dspno],0,0,dstx,1024,False);
      if (dsty != 0)
         XClearArea(mydisp[no],mwndw[dspno],0,0,1024,dsty,False);
      }

   if (mem->pixmap != 1)	/* we have no Pixmaps (not enough memory) */

      /* load subwindow from image mem. into the Window
         at corner (dstx,dsty)  */

      idi_putimage(mydisp[no],mwndw[dspno],gcima[dspno],mxima[dspno][memid],
                srcx,srcy,dstx,dsty,xdim,ydim);

   else
      {				/* we have Pixmaps */
   
      /* first (if flag > 1), load full image mem. into Pixmap */

      if (flag > 1)
         idi_putimage(mydisp[no],mxpix[dspno][memid],gcima[dspno],
                   mxima[dspno][memid],0,0,0,0,mem->xsize,mem->ysize);
   
   
      /* then (if flag = 0, 1, or 2) copy the Pixmap to the Window */
      
      if (flag < 3)
      XCopyArea(mydisp[no],mxpix[dspno][memid],mwndw[dspno],gcima[dspno],
                srcx,srcy,xdim,ydim,dstx,dsty);
      }
   }
}

/*

*/

/* ---- interaction enable ------------------------------------------- */

void int_enable (dspno)
int    dspno;

{
int   i, no;

INTER_DATA     *intdata;



interact = 1;				/* set flag */

no = ididev[dspno].screen;
XSync (mydisp[no],discard);

for (i=0; i<ididev[dspno].n_inter; i++)
   {
   intdata = ididev[dspno].inter[i];

   if (intdata->inttype == II_LOC)		/* II_LOC  */
      {
      if (intdata->interactor == II_MOUSE)
         ididev[dspno].inter_mask |= PointerMotionMask;
      else if (intdata->interactor == II_KEYB)
         ididev[dspno].inter_mask |= KeyPressMask;
      else
         goto end_of_loop;
      }

   else 					/* II_TRG or II_EVLC  */
      {           
      if (intdata->interactor == II_MOUSE)
         ididev[dspno].inter_mask |= ButtonPressMask;
      else if (intdata->interactor == II_KEYB)
         ididev[dspno].inter_mask |= KeyPressMask;
      else
         goto end_of_loop;
      }

   ididev[dspno].inter_mask |= Def_Mask;
   XSelectInput (mydisp[no],mwndw[dspno],ididev[dspno].inter_mask);

end_of_loop:
   ;
   }

set_wcur(dspno,0);

}

/*

*/

/* ---- interaction disable ------------------------------------------ */

void int_disable (dspno)
int   dspno;

{
int  no;


if (interact == 0) return;		/* nothing to do */

interact = 0;
no = ididev[dspno].screen;
XSync (mydisp[no],discard);

ididev[dspno].inter_mask = Def_Mask;
XSelectInput (mydisp[no],mwndw[dspno],ididev[dspno].inter_mask); 

}



/* ---- exit trigger enable ------------------------------------------ */

void exit_trg_enable (dspno)
int    dspno;

{
int   trg0, no, interactor_id;

trg0 = ididev[dspno].trigger;
interactor_id = intdevtable[dspno].trig[trg0]->interactor;
no = ididev[dspno].screen;
 
if (interactor_id == II_MOUSE)
   ididev[dspno].inter_mask |= ButtonPressMask;
else if (interactor_id == II_KEYB)
   ididev[dspno].inter_mask |= KeyPressMask;

ididev[dspno].inter_mask |= Def_Mask;
XSelectInput (mydisp[no],mwndw[dspno],ididev[dspno].inter_mask);
}

/*

*/

/* ---- wait for interaction ----------------------------------------- */
/* synchronous interaction routine                                     */

/* type : internally defined interactor (locator , locator-buttons ,   */
/*                                       keyboard ...                  */
/* data : interactor dependent (mouse-button , key )                   */
/* position : cursor position                                          */

void wait_int (dspno,type,data,cdata,position)
int   dspno, *type, *data, *position;
char  *cdata;

{
int    i, no;


no = ididev[dspno].screen;

we_wait:
XWindowEvent (mydisp[no],mwndw[dspno],ididev[dspno].inter_mask,&myevent);

if (myevent.type == Expose)
   {
   exposed(no,dspno);		/* handle that in `exposed' */
   goto we_wait;
   }


*type = myevent.type;

if (myevent.type == KeyPress)
   {
   position[0] = myevent.xkey.x;
   position[1] = myevent.xkey.y;

   if (myevent.xkey.send_event)		/* from AutoCursor mode */
      {
      *data = myevent.xkey.keycode - 100;	/* keycode is UNSIGNED int */
      *cdata = '\0';
      }

   else					/* real interactive input */
      {
      i = XLookupString(&myevent.xkey,cdata,10,&mykey,&xcstat);

      cdata[i] = '\0';
      switch(mykey)
         {
         case XK_Up:
           *data = -1;
           break;
         case XK_Down:
           *data = -2;
           break;
         case XK_Right:
           *data = -3;
           break;
         case  XK_Left:
           *data = -4;
           break;
         case XK_Return:
           *data = -5;
           break;
         case  XK_F1:
           *data = -11;
           break;
         case  XK_F2:
           *data = -12;
           break;
         case  XK_F3:
           *data = -13;
           break;
         case  XK_F4:
           *data = -14;
           break;
         case  XK_0:
           *data = 0;
           break;
         case  XK_1:
           *data = 1;
           break;
         case  XK_2:
           *data = 2;
           break;
         case  XK_3:
           *data = 3;
           break;
         case  XK_4:
           *data = 4;
           break;
         case  XK_5:
           *data = 5;
           break;
         case  XK_6:
           *data = 6;
           break;
         case  XK_7:
           *data = 7;
           break;
         case  XK_8:
           *data = 8;
           break;
         case  XK_9:
           *data = 9;
           break;
         default:
           *data = -99;
         }
      }
   }

else
   {
   position[0] = myevent.xbutton.x;
   position[1] = myevent.xbutton.y;
   if (myevent.type == ButtonPress)
      *data = myevent.xbutton.button;
   else
      *data = 0;
   *cdata = '\0';
   }
}
 
/*

*/

/* ---- test trigger status ------------------------------------------ */
 
int trigsta(dspno,trgno,event,data,cbuf)
int   dspno, trgno, event, data;
char  *cbuf;

{
int  k, flag, interactor_id, interactor_def;


flag = 0;
interactor_id = intdevtable[dspno].trig[trgno]->interactor;


switch(interactor_id)
   {
   case II_MOUSE:
   if (event == ButtonPress)
      {
      if (trgno == 0)			/* EXIT trigger */
         {
         if (data != 1) flag = 1;
         }
      else if (trgno == 1)
         {
         if (data == 1)
            {
            flag = 1;
            set_wcur(dspno,3);
            }
         }
      }
   break;

   case II_KEYB:
   interactor_def = intdevtable[dspno].trig[trgno]->def;
   
   if (interactor_def == II_TRG)
      {
      if (trgno == 2)			/* EXECUTE trigger */
         {
         if (data == -5) 
            {
            flag = 1;
            set_wcur(dspno,3);
            }
         }
      else if ((trgno > 3) && (trgno < 8))     /* triggers for arrow keys */
         {
         k = trgno - 8;			/* trgno 4 => -4  etc.  */
         if (data == k)
            flag = 1;
         }
      }
   else if (interactor_def == II_EVLC)
      {
      if (*cbuf != '\0') flag = 1;
      }
   break;

   default:
   (void) printf("trigsta: interactor_id = %d\n",interactor_id);
   }

return (flag);
}

/*

*/

int buildRGBLUT(num,lutlen,xcolo,pxls)
int num, lutlen;
unsigned long int *pxls;
XColor  xcolo[];


{
int    j, ifact, isw, rgbset;
register int nr;
unsigned long int   plane_mask[1];



/* here for DirectColor (we build a linear LUT) */

j = myvis[num]->map_entries;
if (lutlen > j) lutlen = j;

ifact = 0xffff / (lutlen - 1);
rgbset =  DoRed | DoGreen | DoBlue;
j = 0;
isw = 0;

if (Xworkst[num].visual == 3)
   {
   XColor  colo;

   colo.flags =rgbset;

   for (nr=0; nr<lutlen; nr++)
      {
      colo.red = colo.green = colo.blue = j;
      j += ifact;

      if (XAllocColor(mydisp[num],cmap[num][0],&colo)) isw++;
      }

   if (isw == 0)
      {
      (void) printf("No entries in LUT!\n");
      return(-1);
      }
   }

else				/* Xworkst[num].visual = 4 */
   {
   plane_mask[0] = 0;
   x11stat = XAllocColorCells(mydisp[num],cmap[num][0],0,plane_mask,
                              0,pxls,lutlen);

   if (x11stat)
      {
      isw = lutlen;

      for (nr=0; nr<lutlen; nr++)
         {
         xcolo[nr].flags = rgbset;
         xcolo[nr].red = xcolo[nr].green = xcolo[nr].blue = j;
         j += ifact;

         Xworkst[num].mapin[nr] = xcolo[nr].pixel = pxls[nr];
         }
      }
   else
      {
      (void) printf("could not allocate %d color cells for LUT!\n",lutlen);
      return(-1);
      }
   }

return (isw);

}

/*

*/

void LUTinstall(dspno)
int dspno;


{
int  no, np;


no = ididev[dspno].screen;
if ((Xworkst[no].ownlut == 1) && (Xworkst[no].lutflag > 0))
   {
   np = ididev[dspno].lutsect;
   XInstallColormap(mydisp[no],cmap[no][np]);
   }
}
