/****************************************************************/
/*								*/
/* hwx11.c:	hardware depending stuff			*/
/*		X11 version					*/
/*								*/
/*		Design: Walter Benzing 1994			*/
/*								*/
/****************************************************************/

/* standard includes */

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

/* my includes */

#include "xdim.h"

/*
 * Open display and get information
 * about the X-server
 */

void HW_GetInfo(XDHardwareInfo *HWI)
    {
     XGCValues gcval;
     Pixmap xbm;
     int pad, test = 1, dum = 1, *list, i, count;
     char *bt;
     
     if(HWI->dpy== NULL)
       {                                            /*Unable to connect*/
        fprintf(stderr, "Couldn't connect to X-Server\n");
        XD_GoodBye(); 
       }
     else
       {
        /* XSynchronize(HWI->dpy, True);*/
	HWI->screen = DefaultScreen(HWI->dpy);
	HWI->vis = DefaultVisual(HWI->dpy, HWI->screen);
	HWI->screenWidth= DisplayWidth(HWI->dpy, HWI->screen);
	HWI->screenHeight= DisplayHeight(HWI->dpy, HWI->screen);
        HWI->cmap= DefaultColormap(HWI->dpy, HWI->screen);
        memset((HWI->colStat), HW_COLORFREE, MAX_COL_NUMBER);
	HWI->availableColors= 0;
        HWI->gc = XCreateGC(HWI->dpy, RootWindow(HWI->dpy,HWI->screen),
        	(unsigned long) 0, NULL);
        HWI->textGC = XCreateGC(HWI->dpy, RootWindow(HWI->dpy,HWI->screen),
        	(unsigned long) 0, NULL);
        pad = sizeof(myPixel) << CHAR2BITS;
        if(pad > 32)
          pad = 32;
        HWI->bits_per_pixel = 0;
        list = XListDepths(HWI->dpy, HWI->screen, &count);
        for(i=0; i< count; i++)
           {
            switch(list[i])
		{
		 case 1:
		 if(HWI->bits_per_pixel < 1)
		   HWI->bits_per_pixel = 1;
		 break;
		 case 2:
		 if(HWI->bits_per_pixel < 2)
		   HWI->bits_per_pixel = 2;
		 break;
		 case 4:
		 if(HWI->bits_per_pixel < 4)
		   HWI->bits_per_pixel = 4;
		 break;
		 case 8:
		 if(HWI->bits_per_pixel < 8)
		   HWI->bits_per_pixel = 8;
		 break;
		 case 16:
		 if(HWI->bits_per_pixel < 16)
		   HWI->bits_per_pixel = 16;
		 break;
		 case 24:
		 if(HWI->bits_per_pixel < 24)
		   HWI->bits_per_pixel = 24;
		 break;
		 case 32:
		 if(HWI->bits_per_pixel < 32)
		   HWI->bits_per_pixel = 32;
		 break;
		}
           }
        XFree(list);
	if(HWI->bits_per_pixel== 0 )
	  {
           fprintf(stderr, "Sorry, your display is troubling me\n");
           fprintf(stderr, "Only 1,2,4,8,16 and 32 bits per pixel allowed\n");
           XD_GoodBye(); 
	  }
	else
	  {
	   printf("Using %d bits internal and %d bits on your display\n",
		(sizeof(myPixel)<< CHAR2BITS), HWI->bits_per_pixel);
	   if(HWI->bits_per_pixel <= DefaultDepth(HWI->dpy, HWI->screen)/4)
	     {
	      printf("Sorry, can't process the default depth of the display\n");
	      printf("Only 1,2,4,8,16,24 and 32 bit displays recognized\n");
	      printf("The output is probably rubbish !\n");
	      printf("The internal image should be allright though\n");
	      printf("You can try to export the image\n");
	     }
	  }
	if(HWI->bits_per_pixel == 1)
          HWI->XIm= XCreateImage(HWI->dpy, HWI->vis, HWI->bits_per_pixel,
		XYBitmap, 0, NULL, 0, 0, pad, 0);
	else
	  HWI->XIm= XCreateImage(HWI->dpy, HWI->vis, HWI->bits_per_pixel,
		ZPixmap, 0, NULL, 0, 0, pad, 0);
	if(HWI->XIm== NULL )
	  {
           fprintf(stderr, "Couldn't allocate Image structure\n");
           XD_GoodBye(); 
	  }
	bt = (char *) &test;
	if(*bt == 1)
          (HWI->XIm)->byte_order = LSBFirst;
	else
	  (HWI->XIm)->byte_order = MSBFirst;
	/* this whole thing looks a bit strange to me */
	/* but the O'Reilly says it, so I do it */
	/* the x developers should really change their */
	/* attitude against colored images */
	/* this thing is a major mess */
	/* I have to take care of a lot of hardware dependent things */
	/* I cannot test ???? */
	xbm = XCreatePixmap(HWI->dpy, RootWindow(HWI->dpy,HWI->screen),
		8, 8, dum);
	if(xbm == 0)
	  {
	   fprintf(stderr, "Couldn't create bitmap => no text output\n");
	  }
	else
	  {
	   /* Create a text GC with depth one */
	   gcval.foreground = 1;
	   gcval.background = 0;
	   HWI->binGC = XCreateGC(HWI->dpy, xbm, GCForeground|GCBackground,
		&gcval);
	   gcval.foreground = 0;
	   gcval.background = 1;
	   HWI->clearBinGC = XCreateGC(HWI->dpy, xbm, GCForeground|GCBackground,
		&gcval);
	   /* Release the dummy */
	   XFreePixmap(HWI->dpy, xbm);
	  }
	_XInitImageFuncPtrs(HWI->XIm);
       }
    }

void HW_AvailableColors(XDimInfo *XDim)
   {
    XDColorInfo *XDC;
    XDHardwareInfo *HWI;
    unsigned long plane_masks;
    int numColors;
    XColor TestCol;
    
    XDC = &(XDim->colors);
    HWI = &(XDim->hwInfo);
    /* THE COLOR PROCESSING POLITIC UNDER X11 is a TOTAL MESS */
    /* SO THE CODE ENDS UP BEING STRANGE */
    /* WHY X11 ITSELF DOESEN'T USE A COLOR TRANSLATION TABLE */
    /* TO SUPPORT THE DIFFERENT VISUAL's ??????????????????? */
    /* I don't have acces to different visuals so this is a try */
    /* nothing more */
    if(HWI->availableColors != 0)
      {
       XFreeColors(HWI->dpy, HWI->cmap, (XDC->colTrans), (HWI->availableColors),
	       (unsigned long) 0);
       HWI->availableColors = 0;
      }
    /* 1. straight forward */
    if(XAllocColorCells(HWI->dpy, HWI->cmap, False, &plane_masks, 0,
           (XDC->colTrans), (XDC->wantedColors))) 
      {
       /* This seems to be OK */
       
       HWI->ReadWrite = True;
       HWI->availableColors = XDC->wantedColors;
       for(numColors = 0; numColors < XDC->wantedColors; numColors++)
          (HWI->colStat)[numColors] = HW_COLORCLAIMED;
      }
    /* 2. now comes the funny part */
    else
      {
       /* allocate a dummy color map */
       
       HWI->ReadWrite = False;
       for(numColors=0; numColors<XDC->wantedColors; numColors++)
          {
	   TestCol.red = (unsigned short) (numColors<<Short2Char);
	   TestCol.green = (unsigned short) (numColors<<Short2Char);
	   TestCol.blue = USHRT_MAX - (unsigned short) (numColors<<Short2Char);
           if(!XAllocColor(HWI->dpy, HWI->cmap, &TestCol))
              break;
           else
             {
              (HWI->colStat)[numColors] = HW_COLORCLAIMED;
              (XDC->colTrans)[numColors] = TestCol.pixel;
             }
          }
       /* availableColors may change so be carefull, take it as a first guess */
       HWI->availableColors = numColors;
      }
    if(HWI->availableColors == 0)
      {
        fprintf(stderr, "Couldn't allocate any colors\n");
        XD_GoodBye(); 
      }
   }

/*
 * Strange color processing part II
 * now I try to actually store some RGB values in the colormap
 * (X11 was obviously developed by black n' white purists)
 */

void HW_AllocateColor(int Index, unsigned short wantedRed,
	unsigned short wantedGreen, unsigned short wantedBlue, XDimInfo *XDim)
   {
    XDColorInfo *XDC;
    XDHardwareInfo *HWI;
    unsigned long plane_masks;
    static XColor SetCol = { 0, 0, 0, 0, DoRed|DoGreen|DoBlue};
    int freeIndex;
    
    XDC = &(XDim->colors);
    HWI = &(XDim->hwInfo);
    SetCol.red = wantedRed;
    SetCol.green = wantedGreen;
    SetCol.blue = wantedBlue;
    if(HWI->ReadWrite)
      {
       /* Juuupppiiieee !!! */
       if(!((HWI->colStat)[Index]))
         {
	  if(XAllocColorCells(HWI->dpy, HWI->cmap, False, &plane_masks, 0,
        	 &((XDC->colTrans)[Index]), 1)) 
	    {
	     (HWI->colStat)[Index] = HW_COLORCLAIMED;
	     (HWI->availableColors)++;
	    }
         }
       if((HWI->colStat)[Index])
         {
          SetCol.pixel = (XDC->colTrans)[Index];
	  XStoreColor(HWI->dpy, HWI->cmap, &SetCol);
	  (HWI->colStat)[Index] = HW_COLORUSED;
	 }
      }
    else
      {
       /* Buuuuuhhh */
       for(freeIndex = 0; freeIndex<Index; freeIndex++)
          if((HWI->colStat)[freeIndex]==HW_COLORCLAIMED) break; 
       if((HWI->colStat)[freeIndex])
         {
          /* at least there was a color allocated before */
          XFreeColors(HWI->dpy, HWI->cmap, &((XDC->colTrans)[freeIndex]),
			1, (unsigned long)0);
	  (HWI->colStat)[freeIndex] = HW_COLORFREE;
	  if(XAllocColor(HWI->dpy, HWI->cmap, &SetCol))
	    {
	     /* ok we got it back */
	     (HWI->colStat)[Index] = HW_COLORUSED;
	     (XDC->colTrans)[Index] = SetCol.pixel;
	    }
	  else
	    {
	     /* now there is another one lost */
	     (HWI->availableColors)--;
	     if(HWI->availableColors <= 0)
	       {
        	fprintf(stderr, "There is no colorcell left to allocate\n");
        	XD_GoodBye(); 
	       }
	     (HWI->colStat)[Index] = HW_COLORFREE;
	    }
         }
       else
         {
          /* may be we can get a color this time */
	  if(XAllocColor(HWI->dpy, HWI->cmap, &SetCol))
	    {
	     /* ok, there is another one */
	     (HWI->availableColors)++;
	     (HWI->colStat)[Index] = HW_COLORUSED;
	     (XDC->colTrans)[Index] = SetCol.pixel;
	    }
	  else
	    {
	     /* no luck again */
	     (HWI->colStat)[Index] = HW_COLORFREE;
	    }
         }
      }
/* the wanted color is always stored */
    (HWI->red)[Index] = (unsigned char)(wantedRed >> Short2Char);
    (HWI->green)[Index] = (unsigned char)(wantedGreen >> Short2Char);
    (HWI->blue)[Index] = (unsigned char)(wantedBlue >> Short2Char);
   }

/*
 * Free the unused color cells
 */

void HW_FreeUnusedColors(XDimInfo *XDim)
   {
    XDColorInfo *XDC;
    XDHardwareInfo *HWI;
    int i;
    
    XDC = &(XDim->colors);
    HWI = &(XDim->hwInfo);
    for(i=0; i<MAX_COL_NUMBER; i++)
       {
        if((HWI->colStat)[i] == HW_COLORCLAIMED && HWI->availableColors > 1)
          {
           (HWI->colStat)[i] = HW_COLORFREE;
           XFreeColors(HWI->dpy, HWI->cmap, &((XDC->colTrans)[i]),
			1, (unsigned long)0);
	   (HWI->availableColors)--;
          }
       }
   }

/*
 * Draw a filled Box
 */

void HW_FillBox(int x0, int y0, int x1, int y1, Pixel col,
		Window w, XDimInfo *XDim)
   {
    XDHardwareInfo *HWI;
    int dx,dy,dummy;
    
    HWI = &(XDim->hwInfo);
    dx= x1-x0;
    if(dx<0)
      {
       dummy= x0;
       x0= x1;
       x1= dummy;
       dx= -dx;
      }
    dy= y1-y0;
    if(dy<0)
      {
       dummy= y0;
       y0= y1;
       y1= dummy;
       dy= -dy;
      }
    XSetForeground(HWI->dpy, HWI->gc, col);
    XFillRectangle(HWI->dpy, w, HWI->gc, x0, y0, (unsigned int) dx, (unsigned int) dy);
   }

/*
 * Draw a Line, x11 draws top down with y >=0
 */

void HW_DrawLine(int x0, int y0, int x1, int y1,
		Window w, XDHardwareInfo *HWI)
   {
    XDrawLine(HWI->dpy, w, HWI->gc, x0, y0, x1, y1);
   }

/*
 * Put a line into an Image, allthough this is hardware independent
 * it was put into this file, beacause reasonable OS have this function
 * build in.
 */

void HW_PutLine(myPixel fg, int x0,int y0, int x1, int y1, int Dx, int Dy, 
	myPixel *Image, XDHardwareInfo *HWI)
   {
    int dy, ystep, Sum, dum, delx, dely;
    myPixel *dp;
    
    if(x1<x0)
      {
       dum = x0;
       x0 = x1;
       x1 = dum;
       dum = y0;
       y0 = y1;
       y1 = dum;
      }
    /* line inside ? */
    if(x0 >= Dx)
      return;
#ifndef PICUP
    dp = Image+(Dy-1-y0)*Dx+x0;
    ystep= -Dx;
#else
    dp = Image+y0*Dx+x0;
    ystep= Dx;
#endif /* PICUP */
    delx = x1-x0;
    dely = y1-y0;
    if(dely < 0)
      {
       dely = -dely;
       ystep = -ystep;
       dy = -1;
      }
    else
      dy = 1;
    if(delx > dely)
      {
       Sum = delx >> 1;
       for(;x0<=x1;x0++)
         {
          Sum += dely;
          if(Sum>=delx)
            {
             Sum -= delx;
             y0 += dy;
             dp += ystep;
            }
          if(x0 >= Dx)
            break;
          if(x0 >=0 && y0 >=0 && y0 < Dy)
            *dp++ = fg;
          else
            dp++;
         }
      }
    else
      {
       y1 +=dy;
       Sum = dely >> 1;
       for(;y0!=y1;y0+=dy)
         {
          Sum += delx;
          if(Sum>=dely)
            {
             Sum -= dely;
             x0++;
             dp++;
             if(x0 >= Dx)
               break;
            }
          if(x0 >=0 && y0 >=0 && y0 < Dy)
            *dp = fg;
          dp += ystep;
         }
      }
   }

/*
 * set foreground color
 */

void HW_SetFore(Pixel col, XDHardwareInfo *HWI)
   {
    XSetForeground(HWI->dpy, HWI->gc, col);
   }

/*
 * set text foreground color
 */

void HW_SetTextFore(Pixel col, XDHardwareInfo *HWI)
   {
    XSetForeground(HWI->dpy, HWI->textGC, col);
   }

/*
 * set background color
 */

void HW_SetBack(Pixel col, XDHardwareInfo *HWI)
   {
    XSetBackground(HWI->dpy, HWI->gc, col);
   }

void HW_SetWindowBack(Pixel col, Window win, XDHardwareInfo *HWI)
   {
    XSetWindowBackground(HWI->dpy, win, col);
   }

/*
 * clear window
 */

void HW_ClearWindow(Window win, ViewportInfo *view, XDimInfo *XDim)
   {
    XDHardwareInfo *HWI;

    HWI = &(XDim->hwInfo);
    HW_SetBack( ((XDim->colors).colTrans)[view->back], HWI);   
    XClearWindow(HWI->dpy, win);
   }

/*
 * Clear a picture
 */

void HW_ClearPict(Window win, ViewportInfo *view, XDimInfo *XDim)
   {
    unsigned long int val, *cp;
    int num, shift, i, size;
    myPixel Col;

    if((XDim->colors).transCol || (XDim->colors).export)
       Col = view->back;
    else
       Col = (myPixel)(((XDim->colors).colTrans)[view->back]);
    cp = (unsigned long int*) view->pict;
    num = sizeof(unsigned long int)/sizeof(myPixel);
    shift = sizeof(myPixel)<<CHAR2BITS;
    val = 0;
    for(i=0; i<num; i++)
       {
        val <<= shift;
        val |= Col;
       }
    size = (view->pwidth * view->pheight *sizeof(myPixel))
	/sizeof(unsigned long int) +1;
    for(i=0; i<size; i++)
       *cp++ = val;
   }

/*
 * put the image onto the screen
 */

int HW_Image(int x0,int y0,int Dx, int Dy, myPixel *Image,
	Window win, Pixel *colTrans, XDHardwareInfo *HWI)
   {
    XImage *XIm;
    int depth, wdepth, NumShift, Shift, ShiftC, i,j, k, c24;
    size_t size;
    unsigned long int *NewImage,*np, dat, dat1, dat2;
    unsigned myINT32 *np24, dat24, dat224;
    myPixel *mp, *mp24, *mp24l;
    
    XIm = HWI->XIm;
    XIm->width = Dx;
    XIm->height = Dy;
    if(XIm->bits_per_pixel!= (sizeof(myPixel) << CHAR2BITS))
      {
       if(XIm->bits_per_pixel != 24)
         {
	  depth = sizeof(unsigned long int)<<CHAR2BITS;
	  size = ((Dx*XIm->bits_per_pixel+depth-1)/depth)
		   *sizeof(unsigned long int);
	  XIm->bytes_per_line = size;
	  size *= Dy;
	  NewImage = malloc(size);
	  if(!NewImage)
            return(ERROR);
	  Shift = XIm->bits_per_pixel;
	  np = NewImage;
	  mp = Image;
	  if(XIm->bits_per_pixel <= ((sizeof(myPixel)) << CHAR2BITS))
            {
            /* all data fits into myPixel */
	     if(XIm->byte_order == MSBFirst)
               {
        	NumShift = (depth/Shift)-1;
        	for(i=0;i<Dy;i++)
        	  {
        	   k=0;
        	   for(j=0;j<Dx;j++)
        	      {
		       if(!k)
	        	 dat = (unsigned long int)*mp++;
		       else
			 {
			  dat <<= Shift;
	        	  dat |= (unsigned long int)*mp++;
	        	 }
        	       if(k==NumShift)
                	 {
                	  k=0;
			  *np++ = dat;
			 }
		       else
	        	 k++;
        	      }
        	   if(k)
        	     {
        	      while(k<=NumShift)
        		dat <<= Shift;
        	      *np++ = dat;
        	     }
        	  }
               }
	     else
               {
        	NumShift = depth-Shift;
        	for(i=0;i<Dy;i++)
        	  {
        	   ShiftC = 0;
        	   for(j=0;j<Dx;j++)
        	      {
		       if(!ShiftC)
	        	 dat = (unsigned long int)*mp++;
		       else
	        	  dat |= (((unsigned long int)*mp++)<<ShiftC);
        	       if(ShiftC==NumShift)
                	 {
                	  ShiftC=0;
			  *np++ = dat;
			 }
		       else
	        	 ShiftC += Shift;
        	      }
        	   if(ShiftC)
        	      *np++ = dat;
        	  }
               }
            }
	  else
	    {
	     /* myPixel too small to hold data => use Pixel */
	     if(XIm->byte_order == MSBFirst)
               {
        	NumShift = (depth/Shift)-1;
        	for(i=0;i<Dy;i++)
        	  {
        	   k=0;
        	   for(j=0;j<Dx;j++)
        	      {
		       if(!k)
	        	 dat = (unsigned long int)(colTrans[*mp++]);
		       else
			 {
			  dat <<= Shift;
	        	  dat |= (unsigned long int)(colTrans[*mp++]);
	        	 }
        	       if(k==NumShift)
                	 {
                	  k=0;
			  *np++ = dat;
			 }
		       else
	        	 k++;
        	      }
        	   if(k)
        	     {
        	      while(k<=NumShift)
        		dat <<= Shift;
        	      *np++ = dat;
        	     }
        	  }
               }
	     else
               {
        	NumShift = depth-Shift;
        	for(i=0;i<Dy;i++)
        	  {
        	   ShiftC = 0;
        	   for(j=0;j<Dx;j++)
        	      {
		       if(!ShiftC)
	        	 dat = (unsigned long int)(colTrans[*mp++]);
		       else
	        	  dat |= (((unsigned long int)(colTrans[*mp++]))<<ShiftC);
        	       if(ShiftC==NumShift)
                	 {
                	  ShiftC=0;
			  *np++ = dat;
			 }
		       else
	        	 ShiftC += Shift;
        	      }
        	   if(ShiftC)
        	      *np++ = dat;
        	  }
               }
            }
         }
      else	/* 24 Bits*/
         {
          /* Here it is ! someone actually used 24 bits for 24 bit images */
          /* #!??? ## ##++##!!!??? (CENSORED) */
          /* this will work ONLY if bits_per_pixel == 24 */
          /* and if your system is not too picky about memory access */
          /* beacuse a of read memory access up to 8 byte below the picture */
          /* but these extra bytes are discarded anyway and a if > Dx, da= 0 */
          /* qould be correct but too time consuming */
	  depth = sizeof(unsigned long int)<<CHAR2BITS;
	  wdepth = 3*depth;
	  size = ((Dx*XIm->bits_per_pixel+wdepth-1)/wdepth)
		   *3*sizeof(unsigned long int);
	  XIm->bytes_per_line = size;
	  size *= Dy;
	  NewImage = malloc(size);
	  if(!NewImage)
            return(ERROR);
	  Shift = XIm->bits_per_pixel;
	  np24 = (unsigned myINT32*)NewImage;
	  mp24l = Image;
	  k = (Dx+3)/4;
	  if(XIm->bits_per_pixel <= ((sizeof(myPixel)) << CHAR2BITS))
            {
            /* all data fits into myPixel */
	     if(XIm->byte_order == MSBFirst)
               {
        	for(i=0;i<Dy;i++)
        	  {
        	   mp24 = mp24l;
        	   mp24l += Dx;
        	   for(j=0;j<k;j++)
        	      {
        	       dat24 = (unsigned myINT32) *mp24++;
        	       dat24 <<= 8; 
        	       dat224 = (unsigned myINT32) *mp24++;
        	       dat24 |= (unsigned myINT8) (dat224 >> 16);
        	       *np24++ = dat24;
        	       dat224 <<= 16;
        	       dat24 = (unsigned myINT32) *mp24++;
        	       dat224 |= (unsigned myINT16) (dat24 >> 8);
        	       *np24++ = dat224;
        	       dat24 = (dat24 << 24) | (unsigned myINT32) *mp24++;
        	       *np24++ = dat24;
        	      }
        	  }
               }
            else	/* LSB first */
               {
                /* I hope I get this right ? */
        	for(i=0;i<Dy;i++)
        	  {
        	   mp24 = mp24l;
        	   mp24l += Dx;
        	   for(j=0;j<k;j++)
        	      {
        	       dat24 = (unsigned myINT32) *mp24++;
        	       dat224 = (unsigned myINT32) *mp24++;
        	       dat24 |= (dat224 & 0x0000FF) << 24;
        	       *np24++ = dat24;
        	       dat224 >>= 8;
        	       dat24 = (unsigned myINT32) *mp24++;
        	       dat224 |= (dat24 & 0x00FFFF) << 16;
        	       *np24++ = dat224;
        	       dat24 >>= 16;
        	       dat224 = (unsigned myINT32) *mp24++;
        	       dat24 |= dat224 << 8;
        	       *np24++ = dat24;
        	      }
        	  }
               }
            }
         else	/* 24 Bit only */
	    {
            /* data doesn't fit into myPixel */
	     if(XIm->byte_order == MSBFirst)
               {
        	for(i=0;i<Dy;i++)
        	  {
        	   mp24 = mp24l;
        	   mp24l += Dx;
        	   for(j=0;j<k;j++)
        	      {
        	       dat24 = (unsigned myINT32) (colTrans[*mp24++]);
        	       dat24 <<= 8; 
        	       dat224 = (unsigned myINT32) (colTrans[*mp24++]);
        	       dat24 |= (unsigned myINT8) (dat224 >> 16);
        	       *np24++ = dat24;
        	       dat224 <<= 16;
        	       dat24 = (unsigned myINT32) (colTrans[*mp24++]);
        	       dat224 |= (unsigned myINT16) (dat24 >> 8);
        	       *np24++ = dat224;
        	       dat24 = (dat24 << 24) |
				(unsigned myINT32) (colTrans[*mp24++]);
        	       *np24++ = dat24;
        	      }
        	  }
               }
            else	/* LSB first */
               {
                /* I hope I get this right ? */
        	for(i=0;i<Dy;i++)
        	  {
        	   mp24 = mp24l;
        	   mp24l += Dx;
        	   for(j=0;j<k;j++)
        	      {
        	       dat24 = (unsigned myINT32) (colTrans[*mp24++]);
        	       dat224 = (unsigned myINT32) (colTrans[*mp24++]);
        	       dat24 |= (dat224 & 0x0000FF) << 24;
        	       *np24++ = dat24;
        	       dat224 >>= 8;
        	       dat24 = (unsigned myINT32) (colTrans[*mp24++]);
        	       dat224 |= (dat24 & 0x00FFFF) << 16;
        	       *np24++ = dat224;
        	       dat24 >>= 16;
        	       dat224 = (unsigned myINT32) (colTrans[*mp24++]);
        	       dat24 |= (dat224 & 0xFFFFFF) << 8;
        	       *np24++ = dat24;
        	      }
        	  }
               }
            }         }
       XIm->data = (char*)NewImage;
       XPutImage(HWI->dpy, win, HWI->gc, XIm, 0, 0, x0, y0, Dx, Dy);
       free(NewImage);
      }
    else
      {
       XIm->data = (char*)Image;
       XIm->bytes_per_line = Dx*sizeof(myPixel);
       XPutImage(HWI->dpy, win, HWI->gc, XIm, 0, 0, x0, y0, Dx, Dy);
      }
    return(OK);
   }

/*
 * Draw a Series of connected Lines
 */

void HW_DrawLines(Window win, XPoint *points, int Num, XDHardwareInfo *HWI)
  {
   XDrawLines(HWI->dpy, win, HWI->gc, points, Num, CoordModeOrigin);
  }


/*
 * calculate Text Extension
 */

void HW_TextExtent(char *text, int *dx, int *dy, XDHardwareInfo *HWI)
  {
   int len, ascent, descent, direc;
   XCharStruct total;
   
   len = strlen(text);
   XTextExtents(HWI->font, text, len, &direc, &ascent, &descent,
		&total);
   *dy = total.ascent+total.descent;
   *dx = total.width;   
  }

/*
 * draw text to the screen (using X11)
 */

void HW_DrawText(char *text, int x0,int y0, int Align,
	Window win, XDHardwareInfo *HWI)
  {
   int direc, ascent, descent, len, height;
   XCharStruct total;

   len = strlen(text);
   XTextExtents(HWI->font, text, len, &direc, &ascent, &descent,
		&total);
   height = total.ascent+total.descent;
   if(Align & ALIGN_CENTER_X)
      x0 -= (total.width >>1);
   else if(Align & ALIGN_RIGHT)
      x0 -= total.width;
   if(Align & ALIGN_CENTER_Y)
      y0 += height >>1;
   else if(Align & ALIGN_TOP)
      y0 += height +2;
   XDrawString(HWI->dpy, win, HWI->textGC, x0, y0-total.descent, text, len);
  }

/*
 * Put Text on the screen
 * Despite the danger of repeating myself
 * there is practically no help for using images in X11
 * therefore a pretty silly way of putting text onto the
 * screen is neccessary
 */

void HW_PutText(char *text, int x0,int y0,int Dx, int Dy, myPixel fg, int Align,
	myPixel *Image, XDHardwareInfo *HWI)
  {
   XImage *XIm;
   Pixmap xbm;
   int xs, ystep, direc, ascent, descent, len, width, height, bo, i, j, k;
   XCharStruct total;
   unsigned myINT32 data, *dp, mask;
   myPixel *ip, *ip0;
   unsigned myINT8 ch0, ch1, ch2, ch3;

   len = strlen(text);
   XTextExtents(HWI->font, text, len, &direc, &ascent, &descent,
		&total);
   width = ((total.width + 31) >> 5)<<5;
   height = total.ascent+total.descent;
   if(Align & ALIGN_CENTER_X)
      x0 -= (total.width >>1);
   else if(Align & ALIGN_RIGHT)
      x0 -= total.width;
   if(Align & ALIGN_CENTER_Y)
      y0 += height >>1;
   else if(Align & ALIGN_BOTTOM)
      y0 += height;
   else if(Align & ALIGN_TOP)
      y0 -= 2;
   xbm = XCreatePixmap(HWI->dpy, RootWindow(HWI->dpy,HWI->screen),
		width, height, 1);
   XFillRectangle(HWI->dpy, xbm, HWI->clearBinGC, 0, 0, width, height);
   XDrawString(HWI->dpy, xbm, HWI->binGC, 0, total.ascent, text, len);
   XIm = XGetImage(HWI->dpy, xbm, 0, 0, width, height, AllPlanes, ZPixmap);
   XFreePixmap(HWI->dpy, xbm);
   dp = (unsigned myINT32 *)XIm->data;
   width >>= 5;
   xs = x0;
   if(XIm->byte_order != HWI->XIm->byte_order)
     bo = 1;
   else
     bo = 0;
#ifndef PICUP
   ip0 = Image+(Dy-y0-1)*Dx+x0;
   ystep = -1;
#else
   ip0 = Image+y0*Dx+x0;
   ystep = 1;
#endif /* PICUP */
   if(XIm->bitmap_bit_order == LSBFirst)
     {
      mask = 1;
      if(XIm->bitmap_unit == 16 && XIm->byte_order == MSBFirst)
        {
         if(HWI->XIm->byte_order == LSBFirst)
           {
	    for(i=0; i< height; i++)
               {
        	ip = ip0;
        	x0 = xs;
        	for(j=0; j<width; j++)
        	   {
        	    data = *dp++;
        	    if(y0>=0 && y0 < Dy)
        	      {
        	       /* swap data */
        	       ch3 = (unsigned char) data;
        	       data >>= 8;
        	       ch2 = (unsigned char) data;
        	       data >>= 8;
        	       ch1 = (unsigned char) data;
        	       data >>= 8;
        	       ch0 = (unsigned char) data;
        	       data = (unsigned myINT32) ch1;
        	       data |= ((unsigned myINT32) ch0)<<8;
        	       data |= ((unsigned myINT32) ch3)<<16;
        	       data |= ((unsigned myINT32) ch2)<<24;
		       for(k=0; k<32; k++)
			  {
			   if(mask & data && x0 >=0 && x0 < Dx)
			     {
		              /* fg ausgeben */
		              *ip++ = fg;
			     }
			   else
			     ip++;
			   data >>=1;
			   x0++;
			  }
		      }
        	   }
		y0 += ystep;
		ip0 += Dx;
               }
           }
         else
	   {
	    for(i=0; i< height; i++)
               {
        	ip = ip0;
        	x0 = xs;
        	for(j=0; j<width; j++)
        	   {
        	    data = *dp++;
        	    if(y0>=0 && y0 < Dy)
        	      {
        	       /* swap data */
        	       ch3 = (unsigned char) data;
        	       data >>= 8;
        	       ch2 = (unsigned char) data;
        	       data >>= 8;
        	       ch1 = (unsigned char) data;
        	       data >>= 8;
        	       ch0 = (unsigned char) data;
        	       data = (unsigned myINT32) ch2;
        	       data |= ((unsigned myINT32) ch3)<<8;
        	       data |= ((unsigned myINT32) ch0)<<16;
        	       data |= ((unsigned myINT32) ch1)<<24;
		       for(k=0; k<32; k++)
			  {
			   if(mask & data && x0 >=0 && x0 < Dx)
			     {
		              /* fg ausgeben */
		              *ip++ = fg;
			     }
			   else
			     ip++;
			   data >>=1;
			   x0++;
			  }
		      }
        	   }
		y0 += ystep;
		ip0 += Dx;
               }
           }
        }
      else if((XIm->bitmap_unit == 8 && HWI->XIm->byte_order == LSBFirst) ||
              (XIm->bitmap_unit == 16 && !bo) ||
              (XIm->bitmap_unit == 32 && !bo))
        {
	 for(i=0; i< height; i++)
            {
             ip = ip0;
             x0 = xs;
             for(j=0; j<width; j++)
        	{
        	 data = *dp++;
        	 if(y0>=0 && y0 < Dy)
        	   {
		    for(k=0; k<32; k++)
		       {
			if(mask & data && x0 >=0 && x0 < Dx)
			  {
		           /* fg ausgeben */
		           *ip++ = fg;
			  }
			else
			  ip++;
			data >>=1;
			x0++;
		       }
		   }
        	}
	     y0 += ystep;
	     ip0 += Dx;
            }
        }
      else
        {
	 for(i=0; i< height; i++)
            {
             ip = ip0;
             x0 = xs;
             for(j=0; j<width; j++)
        	{
        	 data = *dp++;
        	 if(y0>=0 && y0 < Dy)
        	   {
        	    /* swap data */
        	    ch3 = (unsigned char) data;
        	    data >>= 8;
        	    ch2 = (unsigned char) data;
        	    data >>= 8;
        	    ch1 = (unsigned char) data;
        	    data >>= 8;
        	    ch0 = (unsigned char) data;
        	    data = (unsigned myINT32) ch0;
        	    data |= ((unsigned myINT32) ch1)<<8;
        	    data |= ((unsigned myINT32) ch2)<<16;
        	    data |= ((unsigned myINT32) ch3)<<24;
		    for(k=0; k<32; k++)
		       {
			if(mask & data && x0 >=0 && x0 < Dx)
			  {
		           /* fg ausgeben */
		           *ip++ = fg;
			  }
			else
			  ip++;
			data >>=1;
			x0++;
		       }
		   }
        	}
	     y0 += ystep;
	     ip0 += Dx;
            }
        }
     }
   else
     {
      mask = 1<<31;
      if(XIm->bitmap_unit == 16 && XIm->byte_order == LSBFirst)
        {
         if(HWI->XIm->byte_order == LSBFirst)
           {
	    for(i=0; i< height; i++)
               {
        	ip = ip0;
        	x0 = xs;
        	for(j=0; j<width; j++)
        	   {
        	    data = *dp++;
        	    if(y0>=0 && y0 < Dy)
        	      {
        	       /* swap data */
        	       ch0 = (unsigned char) data;
        	       data >>= 8;
        	       ch1 = (unsigned char) data;
        	       data >>= 8;
        	       ch2 = (unsigned char) data;
        	       data >>= 8;
        	       ch3 = (unsigned char) data;
        	       data = (unsigned myINT32) ch2;
        	       data |= ((unsigned myINT32) ch3)<<8;
        	       data |= ((unsigned myINT32) ch0)<<16;
        	       data |= ((unsigned myINT32) ch1)<<24;
		       for(k=0; k<32; k++)
			  {
			   if(mask & data && x0 >=0 && x0 < Dx)
			     {
		              /* fg ausgeben */
		              *ip++ = fg;
			     }
			   else
			     ip++;
			   data <<=1;
			   x0++;
			  }
		      }
        	   }
		y0 += ystep;
		ip0 += Dx;
               }
           }
         else
	   {
	    for(i=0; i< height; i++)
               {
        	ip = ip0;
        	x0 = xs;
        	for(j=0; j<width; j++)
        	   {
        	    data = *dp++;
        	    if(y0>=0 && y0 < Dy)
        	      {
        	       /* swap data */
        	       ch0 = (unsigned char) data;
        	       data >>= 8;
        	       ch1 = (unsigned char) data;
        	       data >>= 8;
        	       ch2 = (unsigned char) data;
        	       data >>= 8;
        	       ch3 = (unsigned char) data;
        	       data = (unsigned myINT32) ch1;
        	       data |= ((unsigned myINT32) ch0)<<8;
        	       data |= ((unsigned myINT32) ch3)<<16;
        	       data |= ((unsigned myINT32) ch2)<<24;
		       for(k=0; k<32; k++)
			  {
			   if(mask & data && x0 >=0 && x0 < Dx)
			     {
		              /* fg ausgeben */
		              *ip++ = fg;
			     }
			   else
			     ip++;
			   data <<=1;
			   x0++;
			  }
		      }
        	   }
		y0 += ystep;
		ip0 += Dx;
               }
           }
        }
      else if((XIm->bitmap_unit == 8 && HWI->XIm->byte_order == MSBFirst) ||
	      (XIm->bitmap_unit == 16 && !bo) ||
	      (XIm->bitmap_unit == 32 && !bo))
        {
	 for(i=0; i< height; i++)
            {
             ip = ip0;
             x0 = xs;
             for(j=0; j<width; j++)
        	{
        	 data = *dp++;
        	 if(y0>=0 && y0 < Dy)
        	   {
		    for(k=0; k<32; k++)
		       {
			if((mask & data) && x0 >=0 && x0 < Dx)
			  {
		           /* fg ausgeben */
		           *ip++ = fg;
			  }
			else
			  ip++;
			data <<=1;
			x0++;
		       }
		   }
        	}
	     y0 += ystep;
	     ip0 += Dx;
            }
        }
      else
        {
	 for(i=0; i< height; i++)
            {
             ip = ip0;
             x0 = xs;
             for(j=0; j<width; j++)
        	{
        	 data = *dp++;
        	 if(y0>=0 && y0 < Dy)
        	   {
        	    /* swap data */
        	    ch3 = (unsigned char) data;
        	    data >>= 8;
        	    ch2 = (unsigned char) data;
        	    data >>= 8;
        	    ch1 = (unsigned char) data;
        	    data >>= 8;
        	    ch0 = (unsigned char) data;
        	    data = (unsigned myINT32) ch0;
        	    data |= ((unsigned myINT32) ch1)<<8;
        	    data |= ((unsigned myINT32) ch2)<<16;
        	    data |= ((unsigned myINT32) ch3)<<24;
		    for(k=0; k<32; k++)
		       {
			if((mask & data) && x0 >=0 && x0 < Dx)
			  {
		           /* fg ausgeben */
		           *ip++ = fg;
			  }
			else
			  ip++;
			data <<=1;
			x0++;
		       }
		   }
        	}
	     y0 += ystep;
	     ip0 += Dx;
            }
        }
     }
   XDestroyImage(XIm);
  }
