/*===========================================================================
  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: idiutil1.c                                                   *
*                                                                      *
*   X11 independent internal service routines                          *
*                                                                      *
************************************************************************
* V 1.1  871201: P. Santin  - Trieste Astronomical Observatory (X10)   *
* V 2.0  890102: K. Banse - ESO Garching  (X11)                        *
 
 090424		last modif
************************************************************************

* contains the following routines:
*
*   clmem                : Clear parameters of memory
*   wr_mem               : Write Main Memory Bitmap;
*   rd_mem               : Read Main Memory Bitmap;
*   show_pix8            : Read + Display location + pixel_value;
*   copy_mem             : Copy memory (or parts of);
*   zero_mem             : set memory to zero (+ constant)
*   
***********************************************************************/

/* 

*/

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

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



/* set up for "normal" [x][0] and byte swapped [x][1] case */

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

static unsigned int  outab[3][2] = 
	{
	 {0x00ffff00, 0x00ffff00},		/* red/blue */
	 {0x00ff00ff, 0xff00ff00},		/* green */
	 {0x0000ffff, 0xffff0000},		/* blue/red */
	};
/*

*/

/* ---- Clear Memory Parameters  ------------------------------------- */

void clmem(mem)

MEM_DATA  *mem;

{
register int  nr;

mem->xwoff = mem->ywoff = 0;
mem->xwdim = mem->xsize;
mem->ywdim = mem->ysize;
mem->load_dir = 0;
mem->lut_id = 0;
mem->xscroll = mem->yscroll = 0;
mem->zoom = 1;
mem->xscale = mem->yscale = 1;
mem->sspx = mem->sspy = 0;
mem->nsx = mem->nsy = 0;
mem->sfpx = mem->sfpy = 1;
mem->source = 0;
mem->frame[0] = ' ';
mem->frame[1] = '\0';		/* was: (void) strcpy(mem->frame," "); */
for (nr=0; nr<8; nr++) mem->rbuf[nr] = 0.0;
}

/* 

*/

/* ---- write main memory bitmap ------------------------------------- */

void wr_mem(dspno,RGBflag,mem,x0,y0,ix,iy,const_flg,data) 

MEM_DATA   *mem;
int        dspno, RGBflag, x0, y0, ix, iy, const_flg;
unsigned char *data;

{
int   no, temp, kxsiz, ioff, indy;
register int loopk, loopi, koff, off, dval, *ptrlut;

register unsigned char  *cpntra, *cpntrb;




if (mem->load_dir == 0)			/* loading bottom up  */
   {
   temp = (mem->ysize -1 - mem->ywoff - y0) * mem->xsize;
   kxsiz = - mem->xsize;
   }
else					/* loading top down  */
   {
   temp = (mem->ywoff + y0) * mem->xsize;
   kxsiz = mem->xsize;
   } 

mem->source = mem->source | 1;		/* set last bit */

off = 0;
no = ididev[dspno].screen;
ioff = ididev[dspno].lutsect * Xworkst[no].lutsize;
ptrlut = Xworkst[no].mapin;


if (Xworkst[no].flag24[0] == 0)		/* write swap flag */
   indy = 0;
else
   indy = 1;				/* Yes, byte swapped */


if (Xworkst[no].visual == 2)                    /* PseudoColor */
   {
   if (Xworkst[no].nobyt == 1)			/* 8 bit memory  */
      {
      cpntra = (unsigned char*)( mem->mmbm + temp + (mem->xwoff + x0) );
 
      if (ioff == 0)
         {
         for (loopi=0; loopi<iy; loopi++)
            {
            cpntrb = cpntra;
            koff = off;
            for (loopk=0; loopk<ix; loopk++)
               {
               dval = (int)data[koff++];
               *cpntrb++ = (unsigned char) *(ptrlut+dval);
               }
       
            cpntra += kxsiz;
            off += ix;
            }
         }
      else
         {
         for (loopi=0; loopi<iy; loopi++)
            {
            cpntrb = cpntra;
            koff = off;
            for (loopk=0; loopk<ix; loopk++)
               {
               dval = (int)data[koff++] + ioff;
               *cpntrb++ = (unsigned char) *(ptrlut+dval);
               }
       
            cpntra += kxsiz;
            off += ix;
            }
         }
      }
   else if (Xworkst[no].nobyt == 2)		/* 16 bit memory  */
      {
      register short int  *jpntra, *jpntrb;

      jpntra = (short int *) mem->mmbm;
      jpntra += (temp + (mem->xwoff + x0));
 
      if (ioff == 0)
         {
         for (loopi=0; loopi<iy; loopi++)
            {
            jpntrb = jpntra;
            koff = off;
            for (loopk=0; loopk<ix; loopk++)
               {
               dval = (int)data[koff++];
               *jpntrb++ = (short int) *(ptrlut+dval);
               }
       
            jpntra += kxsiz;
            off += ix;
            }
         }
      else
         {
         for (loopi=0; loopi<iy; loopi++)
            {
            jpntrb = jpntra;
            koff = off;
            for (loopk=0; loopk<ix; loopk++)
               {
               dval = (int)data[koff++] + ioff;
               *jpntrb++ = (short int) *(ptrlut+dval);
               }
       
            jpntra += kxsiz;
            off += ix;
            }
         }
      }
   }

else if (Xworkst[no].visual == 3)	/* Direct/TrueColor (3 bytes/pixel) */
   {
   int  rgbpix, pixi, shiftmask, outmask;
   register int  *ipntra, *ipntrb;

   ipntra = (int *) mem->mmbm;
   ipntra += (temp + (mem->xwoff + x0));


   if (RGBflag == 0)			/* work on red color */
      {
      if (Xworkst[no].RGBord == 0)
         {
         shiftmask = shiftab[0][indy];                     /* red */
         outmask = outab[0][indy];
         }
      else
         {
         shiftmask = shiftab[2][indy];                     /* red */
         outmask = outab[2][indy];
         }
      }
   else if (RGBflag == 1)		/* work on green color */
      {
      shiftmask = shiftab[1][indy];                        /* green */
      outmask =  outab[1][indy];
      }
   else					/* work on blue color */
      {
      if (Xworkst[no].RGBord == 0)
         {
         shiftmask = shiftab[2][indy];                     /* blue */
         outmask = outab[2][indy];
         }
      else
         {
         shiftmask = shiftab[0][indy];                     /* blue */
         outmask = outab[0][indy];
         }
      }

   if (const_flg == 1)
      {
      dval = (int) *data;
      dval = dval << shiftmask;

      for (loopi=0; loopi<iy; loopi++)
         {
         ipntrb = ipntra;
         for (loopk=0; loopk<ix; loopk++)
            {
            rgbpix = (*ipntrb) & outmask;
            *ipntrb++ = (rgbpix | dval);
            }
         ipntra += kxsiz;
         }
      }

   else
      {
      for (loopi=0; loopi<iy; loopi++)
         {
         ipntrb = ipntra;
         koff = off;
         for (loopk=0; loopk<ix; loopk++)
            {
            dval = (int)data[koff++];
            dval &= 0xff;			/* cut out last byte */
            pixi = dval << shiftmask;
            rgbpix = (*ipntrb) & outmask;
            *ipntrb++ = (rgbpix | pixi);
            }
         ipntra += kxsiz;
         off += ix;
         }
      }
   }

else if (Xworkst[no].visual == 4)
   {
   register unsigned int  *ipntra, *ipntrb;

   ipntra = (unsigned int *) mem->mmbm;
   ipntra += (temp + (mem->xwoff + x0));

   if (const_flg == 1)
      {
      dval = (int) *data;
      dval += Xworkst[no].auxcol;
      dval =  Xworkst[no].mapin[dval];

      for (loopi=0; loopi<iy; loopi++)
         {
         ipntrb = ipntra;
         for (loopk=0; loopk<ix; loopk++) *ipntrb++ = dval;
         ipntra += kxsiz;
         }
      }

   else
      {
      for (loopi=0; loopi<iy; loopi++)
         {
         ipntrb = ipntra;
         koff = off;
         for (loopk=0; loopk<ix; loopk++)
            {
            dval = (int)data[koff++] + Xworkst[no].auxcol;
/*
            *ipntrb++ = *(ptrlut+dval);
            *ipntrb++ = Xworkst[no].mapin[dval];
*/
            *ipntrb++ = Xworkst[no].mapin[dval];
            }
         ipntra += kxsiz;
         off += ix;
         }
      }
   }
}

/* 

*/

unsigned short int  XSWAP_SHORT(jnni)
unsigned short int  jnni;

{
unsigned short int  ja, jb, jn;

jb = jnni & 0xff;               /* input: ab */
ja = (jnni >> 8) & 0xff;

jb = jb << 8;
jn = jb | ja;                   /* output: ba */

return jn;
}



/* ---- read main memory bitmap -------------------------------------- */

void rd_mem(dspno,RGBflag,mem,hcopflg,inpntr,xoff,yoff,xsize,ix,iy,ittf,data) 

MEM_DATA   *mem;
int     dspno, RGBflag;
int	hcopflg;		/* IN: = 1, make a copy of display */
int	xoff, yoff, xsize, ix, iy, ittf;
char       *inpntr;
unsigned char *data;

{
register unsigned char   *cpntra, *cpntrb;
register int i, loopk, loopi, lutoff;
ITT_DATA    *itt;

int   ioff, no, offset, pix;
unsigned char  cpx;


lutoff = ididev[dspno].lutoff;
itt = mem->ittpntr;
no = ididev[dspno].screen;
ioff = ididev[dspno].lutsect * Xworkst[no].lutsize;


/*
printf("rd_memory: visual = %d, hcopflg = %d, RGBord = %d\n",
Xworkst[no].visual,Xworkst[no].RGBord,hcopflg);
*/


if (Xworkst[no].visual == 2)                    /* PseudoColor */
   {
   if (Xworkst[no].nobyt == 1) 		/*  8 bit memory  */
      {
      cpntra = (unsigned char*) (inpntr + yoff + xoff);
 
      if (ittf == 0) 
         {
         if (hcopflg == 0)
            {
            for (loopi=0; loopi<iy; loopi++)
               {
               cpntrb = cpntra;
               for (loopk=0; loopk<ix; loopk++)
                  {
                  pix = *cpntrb++;
                  *data++ = (unsigned char) Xworkst[no].mapout[ioff+pix];
                  }
               cpntra += xsize;
               }
            }
         else
            {				     /* highest colour + LUT offset */
            offset = Xworkst[no].lutlen;

            for (loopi=0; loopi<iy; loopi++)
               {
               cpntrb = cpntra;
               for (loopk=0; loopk<ix; loopk++)
                  {
                  pix = *cpntrb++;
                  for (i=0; i<9; i++)		/* test, if fixed colour */
                     {
                     if (pix == Xworkst[no].fixpix[i])
                        {
                        *data++ = (unsigned char) (offset + i);
                        goto nexta;
                        }
                     }
                  *data++ = (unsigned char) Xworkst[no].mapout[ioff+pix];
            nexta:
                  ;
                  }

               cpntra += xsize;
               }
            }
         }
      else
         {                                      /*  here we handle ITT data   */
         if (hcopflg == 0)
            {
            for (loopi=0; loopi<iy; loopi++)
               {
               cpntrb = cpntra;
               for (loopk=0; loopk<ix; loopk++)
                  {
                  pix = *cpntrb++;
                  cpx = (unsigned char) Xworkst[no].mapout[ioff+pix];
                  *data++ = (unsigned char) (itt->val[cpx]); 
                  }
               cpntra += xsize;
               }
            }
         else
            {				
            offset = Xworkst[no].lutlen;            /* highest colour only */
            for (loopi=0; loopi<iy; loopi++)
               {
               cpntrb = cpntra;
               for (loopk=0; loopk<ix; loopk++)
                  {
                  pix = *cpntrb++;
                  for (i=0; i<9; i++)              /* test, if fixed colour */
                     {
                     if (pix == Xworkst[no].fixpix[i])
                        {
                        *data++ = (unsigned char) (offset + i);
                        goto nextb;
                        }
                     }

                  cpx = (unsigned char) Xworkst[no].mapout[ioff+pix];
                  *data++ = (unsigned char) (itt->val[cpx]); 
            nextb:
                  ;
                  }
               cpntra += xsize;
               }
            }
         }
      }
   }

else if (Xworkst[no].visual == 3)
   {			/* DirectColor/TrueColor => 3 bytes per pixel */
   register int   *ipntra, *ipntrb;

   ipntra = (int *) inpntr;		/* no ITT here */
   ipntra += (yoff + xoff);
 
   if (hcopflg == 0)		/* no display snapshot */
      {
      int  rgbpix, shiftmask;

      /* Must account for RGB ordering when returning a particular plane */
      switch (RGBflag) 
	 {
	case 0: /* Red color */
	  if (Xworkst[no].RGBord == 0) shiftmask = 0; else shiftmask = 16;
	  break;
	case 1: /* Green color */
	  shiftmask = 8;
	  break;
	case 2: /* Blue color */
	  if (Xworkst[no].RGBord == 0) shiftmask = 16; else shiftmask = 0;
	  break;
	default:
          shiftmask = 0;
         }
      for (loopi=0; loopi<iy; loopi++)
         {
         ipntrb = ipntra;
         for (loopk=0; loopk<ix; loopk++)
            {
            rgbpix = *ipntrb++;
            *data++ = (unsigned char) (rgbpix >> shiftmask) & 0xff;
            }
         ipntra += xsize;
         }
      }

   else				/* hardcopy - work on all 3 color channels */
      {
      int  *idata;
      unsigned int word;


      idata = (int *) data;
      for (loopi=0; loopi<iy; loopi++)
         {
         ipntrb = ipntra;


         /* following section modified by CM */

	 if (Xworkst[no].RGBord == 0) 
            {
	    for (loopk=0; loopk<ix; loopk++) *idata++ = *ipntrb++;
            }
	 else 
            {
            for (loopk=0; loopk<ix; loopk++) 
	       {
	       word = *ipntrb++;
	       *idata++ = ((word & 0x00ff00) | ((word & 0xff0000) >> 16)
			      | ((word & 0x0000ff) << 16));
	       }
            }

         ipntra += xsize;
         }
      }
   }
   
else                    /* emulate PseudoColor on Direct/TrueColor */
   {
   register int   *ipntra, *ipntrb;

   ipntra = (int *) inpntr;             /* no ITT here */
   ipntra += (yoff + xoff);


   if (hcopflg == 0) 
      {
       unsigned long int mindist=0;
       unsigned int minind;

       for (loopi=0; loopi<iy; loopi++)
	 {
	   ipntrb = ipntra;
	   for (loopk=0; loopk<ix; loopk++)
	     {
	       /* It is possible to lose precision in the memory "read",
		  namely in the conversion from 16-bit to 32-bit pixels.
		  Thus, we loop through each color table entry to find a
		  closest match using the pythagorean theorem.  On small
		  enough images this is not a burden.  
		  
		  To get nice quality print output this step appears
		  necessary, so those using Pseudo emulation may just have
		  to wait.  
		  
		  I decided to put the ittf and hcopflg comparisons inside
		  the inner loop.  This doesn't cost much in comparison to
		  the color-table-lookup loop. */
	       
	       int i;
	       pix = *ipntrb++;
	       
	       /* Removed check for fixed colours - doesn't work well in
		  24-bit environments */

	       /* Search for the best fitting color index */
	       minind = -1;

               offset = Xworkst[no].lutlen;            /* highest colour only */

	       for (i=ioff; i<(offset+ioff); i++)
		 {
		   unsigned int lval;
		   unsigned long int dist;
		   int dr, dg, db;
		   
		   lval = Xworkst[no].mapin[i];
		   dr = ((lval & 0x0000ff) - (pix & 0x0000ff));
		   dg = ((lval & 0x00ff00) - (pix & 0x00ff00)) >> 8;
		   db = ((lval & 0xff0000) - (pix & 0xff0000)) >> 16;
		   /* Euclidean distance, squared */
		   dist = dr*dr + dg*dg + db*db;
		   if (minind == -1 || dist < mindist)
		     {
		       mindist = dist;
		       minind  = i;
		     }
		 }
	       /* Apply transfer function and global offset */
	       if (ittf == 0) 
		 *data++ = (unsigned char) (minind - lutoff);
	       else
		 {
		   int kval = (minind - lutoff);
		   if (kval < 0) kval = 0;
		   *data++ = (unsigned char) (itt->val[kval]);
		 }
	     }

	   ipntra += xsize;
	 }
      }
   else 			/* hardcopy - work on all 3 color channels */
      {
      int  *idata;
      unsigned int word;


      idata = (int *) data;

      /* The subsequent modules know about RGBord (= 0/1)
	 (1 = 0 R G B	0 = 0 B G R),
      	 with data shifted to the low 24 bytes - 
         thus for displays with RGBord = 1 we need 0 R G B as output 
	 (4 bytes, LSB to the right)
         and 0 B G R as output for displays with RGBord = 0      */

      if (Xworkst[no].RGBord == 0)	
         {
         if (Xworkst[no].flag24[1] == 0)	/* read swap flag */
            {					/* no byte swap */
            for (loopi=0; loopi<iy; loopi++)	/* in: 0 B G R  */
               {				/* same for 16/24/32 bits */
               ipntrb = ipntra;

               for (loopk=0; loopk<ix; loopk++) *idata++ = *ipntrb++;

	       ipntra += xsize;
               }
            }
         else				/* Yes, we have byte swap */
            {			
            if (Xworkst[no].depth == 16) 
               {				/* in: Rg gB 0 0 */
               unsigned short int jj, kk;

               for (loopi=0; loopi<iy; loopi++)
                  {
                  ipntrb = ipntra;

                  for (loopk=0; loopk<ix; loopk++) 
	             {
                     word = *ipntrb++;
                     kk = (unsigned short int) word;
                     jj = XSWAP_SHORT(kk);
		     *idata++ = (unsigned int) jj;
		     }				/* out: 0 0 gB Rg */
	          ipntra += xsize;
                  }
               }
            else			/* use 24 bits */
               {
               for (loopi=0; loopi<iy; loopi++)
                  {				/* in: R G B 0  */
                  ipntrb = ipntra;

                  for (loopk=0; loopk<ix; loopk++) 
	             {
                     word = *ipntrb++;
                     word = word >> 8;		/* out: 0 B G R */
		     *idata++ = ((word & 0x00ff00) | ((word & 0xff0000) >> 16)
                                 | ((word & 0x0000ff) << 16));
		     }
	          ipntra += xsize;
                  }
               }
            }
         }

      else				
         {
         if (Xworkst[no].flag24[1] == 0)	/* read swap flag */
            {					/* no byte swap */
            for (loopi=0; loopi<iy; loopi++)	/* in: 0 R G B */
               {
               ipntrb = ipntra;
            
               for (loopk=0; loopk<ix; loopk++) *idata++ = *ipntrb++;

	       ipntra += xsize;			/* same for 16/24/32 bits */
	       }
            }
         else				/* Yes, we have byte swap */	
            {
            if (Xworkst[no].depth == 16)
               {				/* in: Bg gR 0 0 */
               unsigned short int jj, kk;

               for (loopi=0; loopi<iy; loopi++)
                  {
                  ipntrb = ipntra;

                  for (loopk=0; loopk<ix; loopk++)
                     {
                     word = *ipntrb++;
                     kk = (unsigned short int) word;
                     jj = XSWAP_SHORT(kk);
                     *idata++ = (unsigned int) jj;
                     }				/* out: 0 0 gR Bg */
                  ipntra += xsize;
                  }
               }
            else				/* in: B G R 0 */
               {
               for (loopi=0; loopi<iy; loopi++)
                  {
                  ipntrb = ipntra;
            
                  for (loopk=0; loopk<ix; loopk++)
                     {
                     word = *ipntrb++;
   		     word = word >> 8;		/* out: 0 R G B */
                     *idata++ = ((word & 0x00ff00) | ((word & 0xff0000) >> 16)
                                 | ((word & 0x0000ff) << 16));
                     }
	    
                  ipntra += xsize;
	          }
	       }
	    }
	 }
      }
   }
}       

/* 

*/

/* ---- read + display cursor location(s) + pixel value ------------- */

void show_pix8(dspno,cursno,x0,y0,x1,y1,data) 

int    dspno, cursno, x0, y0, x1, y1;
unsigned char *data;

{
int   i, temp, pix, no, xs, ys, xoff, yoff;
int   *ipntra;
short int *jpntra;
register int lutoff;

char  text[28];
static char  bltext[18] = "                 ";

unsigned char  *cpntra;

MEM_DATA   *mem;
CONF_DATA  *conf;
ALPH_DATA  *alph;

if (ididev[dspno].alpno < 90) return;


/*   first we get currently active memory + the data values     */

no = ididev[dspno].screen;
lutoff = ididev[dspno].lutoff;
conf = ididev[dspno].confptr;
i = conf->memid;
mem = conf->memory[i];
alph = conf->alpmem[i];

ys = 3;  yoff = y0;  xoff = x0;


loop:
temp = mem->ysize - 1 - mem->yscroll - yoff;

if (Xworkst[no].visual == 2)                    /* PseudoColor */
   {
   if (Xworkst[no].nobyt == 1)			/*  8bit memory  */
      {
      cpntra = (unsigned char*)( mem->mmbm + (temp*mem->xsize) + 
               (mem->xscroll + xoff) );
      pix = *cpntra;
      *data = (unsigned char) (pix - lutoff); 
      }
   else if (Xworkst[no].nobyt == 2)
      {
      jpntra = (short int *) mem->mmbm;
      jpntra += (temp + (mem->xscroll + x0));
      pix = *jpntra;
      *data = (unsigned char) (pix - lutoff); 
      }
   }

else                    /* DirectColor/TrueColor => 3 (in 4) bytes per pixel */
   {
   ipntra = (int *) mem->mmbm;
   ipntra += (temp*mem->xsize + (mem->xscroll + xoff));
   pix = (*ipntra) & 0xff;			/* use only red part */
   if (Xworkst[no].visual == 4) 
      {
      pix -= lutoff;
      if (pix < 0) pix = 0;
      }
   *data = (unsigned char) pix;
   }

            /*   now we display the stuff     */

if ((cursno == 1) || (cursno == 3)) 
   xs = (ididev[dspno].xsize/16) + 13;		/* 13 = 5 + 8  */
else
   xs = 8;

(void) sprintf(text,"%d, %d, %d",xoff,yoff,*data);	/* convert to ASCII  */
alptext(1,dspno,alph,bltext,xs,ys);		/* force display */
alptext(1,dspno,alph,text,xs,ys);


/*  if cursno .eq. 2, handle second coordinate pair  */

if (cursno == 2)
   {
   data ++;
   yoff = y1;
   xoff = x1;
   cursno = 3;
   goto loop;
   }

}

/* 

*/

/* ---- Copy parts of memory planes  ----------------------------------*/

void copy_zmem(dspno,mema)

int    dspno;
MEM_DATA   *mema;

{
int    offseta[2], xysize[2];
int    offa, offb, inca;

void cp_zmem8();


offseta[0] = mema->xscroll;
offseta[1] = mema->ysize - (ididev[dspno].ysize + mema->yscroll);

xysize[0] = (mema->xsize - offseta[0]);		/* no of pixels per line */
xysize[1] = (mema->ysize - offseta[1]);		/* no of lines */


if (mema->load_dir == 0)                      /* loading bottom up  */
   {
   offa = (offseta[1] * mema->xsize) + offseta[0];	/* contrary to */
   offb = 0;						/* normal copy... ! */
   inca = mema->xsize;
   }
else
   {
   offa = (((mema->ysize-1) - offseta[1]) * mema->xsize) + offseta[0];
   offb = (mema->ysize - 1) * mema->xsize;
   inca = -mema->xsize;
   }

if (Xworkst[ididev[dspno].screen].nobyt == 1)
   cp_zmem8(mema,offa,inca,offb,xysize);

}

/* 

*/

void cp_zmem8(mema,offa,xsiza,offb,xysize)

int    offa, xsiza, offb, *xysize;
MEM_DATA   *mema;

{
int  xm, ym, zoomf;
register int  i, k, loopk, loopi;

register unsigned char  *p1, *p2, *r1, *r2;


p1 = (unsigned char *) mema->mmbm;
p1 += offa;

p2 = (unsigned char *) mema->zmbm;
p2 += offb;

zoomf = mema->zoom;
xm = mema->xsize/zoomf;			/* max. no. of pixels */
if (xm > *xysize) xm = *xysize;
ym = mema->ysize/zoomf;			/* max. no. of lines */
if (ym > xysize[1]) ym = xysize[1];

for (loopi=0; loopi<ym; loopi++)
   {
   for (i=0; i<zoomf; i++)
      {
      r1 = p1;
      r2 = p2;
      for (loopk=0; loopk<xm; loopk++)
         {
         for (k=0; k<zoomf; k++)
            *r2++ = *r1;
         r1 ++;
         }
      p2 += xsiza;
      }

   p1 += xsiza;
   }
}

/* 

*/

/* ---- Copy parts of memory planes  ----------------------------------*/

void copy_mem(dspno,mema,offseta,memb,offsetb,xysize,zoomf)

int    dspno, *offseta, *offsetb, *xysize, zoomf;
MEM_DATA   *mema, *memb;

{
int    no, offa, offb, inca, incb;

void  cp_mem8(), cp_mem16(), cp_mem32();


if (mema->load_dir == 0)                      /* loading bottom up  */
   {
   offa = (((mema->ysize-1) - offseta[1]) * mema->xsize) + offseta[0];
   offb = (((memb->ysize-1) - offsetb[1]) * memb->xsize) + offsetb[0];
   inca = -mema->xsize;
   incb = -memb->xsize;
   }
else
   {
   offa = (offseta[1] * mema->xsize) + offseta[0];
   offb = (offsetb[1] * memb->xsize) + offsetb[0];
   inca = mema->xsize;
   incb = memb->xsize;
   }
memb->source = memb->source | 2;

no = ididev[dspno].screen;

if (Xworkst[no].visual == 2)                    /* PseudoColor */
   {
   if (Xworkst[no].nobyt == 1)
      cp_mem8(mema,offa,inca,memb,offb,incb,xysize,zoomf);
   else if (Xworkst[no].nobyt == 2)
      cp_mem16(mema,offa,inca,memb,offb,incb,xysize,zoomf);
   }
else                    /* DirectColor/TrueColor => 3 bytes per pixel */
   cp_mem32(mema,offa,inca,memb,offb,incb,xysize,zoomf);
}

/* 

*/

void cp_mem8(mema,offa,xsiza,memb,offb,xsizb,xysize,zoomf)

int   xsiza, offa, xsizb, offb, *xysize, zoomf;
MEM_DATA   *mema, *memb;

{
int  xm, ym;
register int  i, k, loopk, loopi;

register unsigned char  *p1, *p2, *r1, *r2;


p1 = (unsigned char *) mema->mmbm;
p1 += offa;

p2 = (unsigned char *) memb->mmbm;
p2 += offb;

xm = memb->xsize / zoomf;   
if (xm > xysize[0]) xm = xysize[0];  		/* no of pixels per line */

ym = memb->ysize / zoomf;   
if (ym > xysize[1]) ym = xysize[1];  		/* no of lines */

for (loopi=0; loopi<ym; loopi++)
   {
   for (i=0; i<zoomf; i++)
      {
      r1 = p1;
      r2 = p2;
      for (loopk=0; loopk<xm; loopk++)
         {
         for (k=0; k<zoomf; k++)
            *r2++ = *r1;
         r1 ++;
         }
      p2 += xsizb;
      }
   p1 += xsiza;
   }
}

/* 

*/

void cp_mem16(mema,offa,xsiza,memb,offb,xsizb,xysize,zoomf)

int   xsiza, offa, xsizb, offb, *xysize, zoomf;
MEM_DATA   *mema, *memb;

{
(void) printf("memory copy not implemented for 16 bit pixels...\n");
return;
}

void cp_mem32(mema,offa,xsiza,memb,offb,xsizb,xysize,zoomf)

int   xsiza, offa, xsizb, offb, *xysize, zoomf;
MEM_DATA   *mema, *memb;

{
int  xm, ym;
register int i, k, loopi, loopk;
register int *ip1, *ip2, *ir1, *ir2;


ip1 = (int *) mema->mmbm;
ip1 += offa;

ip2 = (int *) memb->mmbm;
ip2 += offb;

xm = memb->xsize / zoomf;   
if (xm > xysize[0]) xm = xysize[0];  		/* no of pixels per line */

ym = memb->ysize / zoomf;   
if (ym > xysize[1]) ym = xysize[1];  		/* no of lines */

for (loopi=0; loopi<ym; loopi++)
   {
   for (i=0; i<zoomf; i++)
      {
      ir1 = ip1;
      ir2 = ip2;
      for (loopk=0; loopk<xm; loopk++)
         {
         for (k=0; k<zoomf; k++)
            *ir2++ = *ir1;
         ir1 ++;
         }
      ip2 += xsizb;
      }
   ip1 += xsiza;
   }
}

/* 

*/

/* ---- Zero Memory             ------------------------------------- */

void zero_mem(dspno,mem,zflag,bck)

int     dspno, zflag, bck;
MEM_DATA  *mem;

{
int       no, temp;
register int loopi, lutoff;

unsigned char  bval;
unsigned char  *cpntra;


if (mem->source > 1)
   mem->source--;
else
   mem->source = 0;

temp = mem->xsize * mem->ysize; 
no = ididev[dspno].screen;
lutoff = ididev[dspno].lutoff;

if (Xworkst[no].visual == 2)                    /* `true' PseudoColor */
   {
   if (Xworkst[no].nobyt == 1)
      {
      if (zflag == 0)
         cpntra = (unsigned char *) mem->mmbm;
      else
         cpntra = (unsigned char *) mem->zmbm;
      /* bval = (unsigned char) (lutoff + bck); */
      bval = (unsigned char) (ididev[dspno].backpix);

      for (loopi=0; loopi<temp; loopi++)
          *cpntra++ = bval;
      }
   else if (Xworkst[no].nobyt == 2)
      {
      register short int   *jpntra, jbval;

      if (zflag == 0)
         jpntra = (short int*) mem->mmbm;
      else
         jpntra = (short int*) mem->zmbm;
      jbval = (short int) (ididev[dspno].backpix);

      for (loopi=0; loopi<temp; loopi++)
          *jpntra++ = jbval;
      }
   }

else if (Xworkst[no].visual == 3)		/* RGB mode with 24 (32) bits */
   {
   register int  *ipntra, ibval;

   if (zflag == 0)
      ipntra = (int *) mem->mmbm;
   else
      ipntra = (int *) mem->zmbm;

   /* ibval = (int) bck; */
   ibval = (int) (ididev[dspno].backpix);
   for (loopi=0; loopi<temp; loopi++) *ipntra++ = ibval;
   }

else if (Xworkst[no].visual == 4)		/* PseudoColor on RGB */
   {
   register int  *ipntra, ibval;

   if (zflag == 0)
      ipntra = (int *) mem->mmbm;
   else
      ipntra = (int *) mem->zmbm;

   /* 
   ibval = (int) bck;
   ibval += Xworkst[no].auxcol;
   ibval =  Xworkst[no].mapin[ibval];
   */

   ibval = (int) (ididev[dspno].backpix);
   for (loopi=0; loopi<temp; loopi++) *ipntra++ = ibval;
   }
}
 
