/****************************************************************/
/*								*/
/* grfx.c:	hardware independent graphic stuff		*/
/*								*/
/*		Design: Walter Benzing 1994			*/
/*								*/
/*		NO RIGHTS RESERVED				*/
/****************************************************************/

/* standard includes */

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

/* my includes */

#include "xdim.h"

/* 
 * Initialize the graphic structure
 * this data is only used if no preference file is found
 */

void GR_InitColorInfo(XDColorInfo *XDC)
   {
    XDC->export = False;
    XDC->wwidth= 600;
    XDC->wheight = 400;
    XDC->pwidth = 800;
    XDC->pheight = 600;
    XDC->tNext = True;
    XDC->tInterval = 100;
    XDC->zoom = 1.2;
    XDC->dAngle = PI/16.0;
    XDC->delta = 25;
    XDC->rowNum = 4;
    XDC->DrawGrid = True;
    XDC->DrawAxisText = True;
    XDC->ticsX = 5;
    XDC->ticsY = 5;
    XDC->ticsZ = 5;
    XDC->back = 1;
    XDC->fore = 0;
    XDC->textFore = XDC->fore;
    XDC->axisFore = XDC->fore;
    XDC->axisBackX = 2;
    XDC->axisBackY = 3;
    XDC->axisBackZ = 4;
    XDC->gNum = 10;
    XDC->gStep = 1;
    XDC->interCol = True;
    XDC->GerNot = True;
    XDC->Repl = 0.0;
    XDC->jpgQuality = 85;
    (XDC->colors)[0] = 2;
    (XDC->colors)[1] = 4;
    (XDC->colors)[2] = 4;
    (XDC->colors)[3] = 4;
    XDC->wantedColors = 14;
    XDC->colS = 2;
    XDC->colE = XDC->wantedColors -1;
    (XDC->beginR)[0]= 0;
    (XDC->beginG)[0]= 0;
    (XDC->beginB)[0]= 0;
    (XDC->endR)[0]= USHRT_MAX;
    (XDC->endG)[0]= USHRT_MAX;
    (XDC->endB)[0]= USHRT_MAX;
    (XDC->beginR)[1]= (USHRT_MAX >> 1);
    (XDC->beginG)[1]= 0;
    (XDC->beginB)[1]= USHRT_MAX;
    (XDC->endR)[1]= 0;
    (XDC->endG)[1]= (0.75*USHRT_MAX);
    (XDC->endB)[1]= (0.25*USHRT_MAX);
    (XDC->beginR)[2]= 0;
    (XDC->beginG)[2]= USHRT_MAX;
    (XDC->beginB)[2]= 0;
    (XDC->endR)[2]= (0.85*USHRT_MAX);
    (XDC->endG)[2]= (0.85*USHRT_MAX);
    (XDC->endB)[2]= 0;
    (XDC->beginR)[3]= USHRT_MAX;
    (XDC->beginG)[3]= USHRT_MAX;
    (XDC->beginB)[3]= 0;
    (XDC->endR)[3]= USHRT_MAX;
    (XDC->endG)[3]= 0;
    (XDC->endB)[3]= 0;
    (XDC->pref)[0] = '\0';
   }

/*
 * Fill all the colours of wantedColours
 * with the best matches from availableColours
 */

void GR_FillUnusedColors(XDimInfo *XDim)
   {
    XDColorInfo *XDC;
    XDHardwareInfo *HWI;
    int i,j, red, green, blue, col, minS, minInd;
    int delR, delG, delB, delC;
    
    XDC = &(XDim->colors);
    HWI = &(XDim->hwInfo);
    for(i=0; i<XDC->wantedColors; i++)
       {
        if(!((HWI->colStat)[i]))
          {
           red = (int)((HWI->red)[i]);
           green = (int)((HWI->green)[i]);
           blue = (int)((HWI->blue)[i]);
           col = Mmax3(red, green, blue) - Mmin3(red, green, blue);
           minS = INT_MAX;
           minInd = 0;
           for(j=0;j<XDC->wantedColors;j++)
              {
               if((HWI->colStat)[j] == HW_COLORUSED)
                 {
        	  delR = (int)((HWI->red)[j]);
        	  delG = (int)((HWI->green)[j]);
        	  delB = (int)((HWI->blue)[j]);
        	  delC = Mmax3(delR, delG, delB) - Mmin3(delR, delG, delB);
		  delR -= red;
		  delG -= green;
		  delB -= blue;
		  delC -= col;
		  delR = delR*delR + delG*delG + delB*delB + delC*delC;
		  if(delR< minS)
		    {
		     minInd = j;
		     minS = delR;
		    }
		 }
              }
           (XDC->colTrans)[i] = (XDC->colTrans)[minInd];
          }
       }
   }

/*
 * Allocate colors for XDim
 * most of the work is done by hardware dependent (HW_) routines
 */

void GR_AllocateColors(XDimInfo *XDim)
   {
    XDColorInfo *XDC;
    XDHardwareInfo *HWI;
    int colStep, actStep, row, startRow, endRow, i;
    unsigned short red, green, blue;
    int br, bg, bb, er, eg, eb;
    double delta;
    
    XDC = &(XDim->colors);
    HWI = &(XDim->hwInfo);

    /* allocate first the colors that are probably available */
    /* availableColors > 0 or something went terribly wrong */
    /* all colors that can be overwritten must be marked HW_COLORCLAIMED */

    colStep = (XDC->wantedColors)/(HWI->availableColors);
    if(!colStep) colStep=1;
    row = 0;
    endRow = 0;
    actStep = 1;
    for(i=0; i<XDC->wantedColors; i+=actStep)
       {
        if(i>=endRow)
          {
           startRow = endRow;
           i= startRow;
           br= (int)((XDC->beginR)[row]);
           bg= (int)((XDC->beginG)[row]);
           bb= (int)((XDC->beginB)[row]);
           er= (int)((XDC->endR)[row])-br;
           eg= (int)((XDC->endG)[row])-bg;
           eb= (int)((XDC->endB)[row])-bb;
           if((XDC->colors)[row] > 1)
	      delta = 1.0/((XDC->colors)[row]-1);
           if(colStep >= (XDC->colors)[row])
             actStep = (XDC->colors)[row] -1;
           else
             actStep = colStep;
           if(actStep == 0)
             actStep = 1;
           endRow += (XDC->colors)[row++];
          }
        if((HWI->colStat)[i] != HW_COLORUSED)
          {
	   red = (unsigned short)(br + delta*((i-startRow)*er));
	   green = (unsigned short)(bg + delta*((i-startRow)*eg));
	   blue = (unsigned short)(bb + delta*((i-startRow)*eb));
	   HW_AllocateColor(i, red, green, blue, XDim);
          }
       }
    /* now try to get as much colors as possible */
    row = 0;
    endRow = 0;
    for(i=0; i<XDC->wantedColors; i++)
       {
        if(i>=endRow)
          {
           startRow = endRow;
           br= (int)((XDC->beginR)[row]);
           bg= (int)((XDC->beginG)[row]);
           bb= (int)((XDC->beginB)[row]);
           er= (int)((XDC->endR)[row])-br;
           eg= (int)((XDC->endG)[row])-bg;
           eb= (int)((XDC->endB)[row])-bb;
           if((XDC->colors)[row] > 1)
	      delta = 1.0/((XDC->colors)[row]-1);
           endRow += (XDC->colors)[row++];
          }
        if((HWI->colStat)[i] != HW_COLORUSED)
          {
	   red = (unsigned short)(br + delta*((i-startRow)*er));
	   green = (unsigned short)(bg + delta*((i-startRow)*eg));
	   blue = (unsigned short)(bb + delta*((i-startRow)*eb));
	   HW_AllocateColor(i, red, green, blue, XDim);
          }
       }
    /* fill the rest colors with best matches */
    GR_FillUnusedColors(XDim);
    /* clean up unused colors */
    HW_FreeUnusedColors(XDim);
   }

/* init import of a color map */

void GR_InitColorImport( int num_colors, XDColorInfo *XDC, XDHardwareInfo *HWI)
   {
    int i;
    
    for(i=0; i< XDC->wantedColors; i++)
       if((HWI->colStat)[i])
         (HWI->colStat)[i] = HW_COLORCLAIMED;
    XDC->wantedColors = num_colors;
    XDC->colS = 0;
    XDC->colE = num_colors -1;
    XDC->back = num_colors-1;
    XDC->fore = 0;
    XDC->axisFore = XDC->fore;
    XDC->axisBackX = ((int)num_colors*3)/4;
    XDC->axisBackY = num_colors/2;
    XDC->axisBackZ = num_colors/4;
   }

/* init viewport data values */

void GR_InitViewports(XDimInfo *XDim)
   {
    int i;
    ViewportInfo *view;

    XDim->port = -1;
    for(i=0; i<MAX_VIEWPORT_NUMBER; i++)
       {
        view = &((XDim->Views)[i]);
        view->pict = NULL;
        view->dataType = 0;
        view->charData = NULL;
        view->actData = NULL;
        view->Data = NULL;
        *(view->dfile) = '\0';
        *(view->fileName) = '\0';
       }
   }

/* Initialize all structures for graphic's */

void GR_InitGraphics(XDimInfo *XDim)
   {
    XDColorInfo *XDC;
    XDHardwareInfo *HWI;
    
    XDC = &(XDim->colors);
    HWI = &(XDim->hwInfo);
    XDim->link2Window = False;
    XDim->createLast = False;
    XDim->useLinks = True;
    XDim->math = False;
    XDim->RecSave = False;
    WD_SetFastRedraw(NULL, (funcCast)XT_RedrawHidden, NULL);
    WD_SetNormalRedraw(NULL, (funcCast)XT_RedrawHFilled, NULL);
    HW_GetInfo(HWI);
    GR_InitColorInfo(XDC);
    if((HWI->XIm)->bits_per_pixel > (sizeof(myPixel))<<CHAR2BITS)
      XDC->transCol = True;
    else
      XDC->transCol = False;
    HW_AvailableColors(XDim);
    GR_AllocateColors(XDim);
    GR_InitViewports(XDim);
   }

/*
 * resize the backup image of a viewport
 */

int GR_ResizeViewport(ViewportInfo *VWI, XDimInfo *XDim)
   {
    size_t size;
    void *new;
    
    size = ((VWI->pwidth *VWI->pheight*sizeof(myPixel))
          /sizeof(unsigned long int) +1)*sizeof(unsigned long int);
    if(new= malloc(size))
      {
       if(VWI->pict)
	 free(VWI->pict);
       VWI->pict = new;
       VWI->changed |= CHANGED;
       return(OK);
      }
    else
      {
       sprintf(XDim->error, "Couldn't allocate %d bytes of memory", (int)size);
       return(ERROR);
      }
   }

/*
 * Create a standard decoding vector for a viewport
 */

void GR_InitDeco(myPixel *deco, myPixel colS, myPixel colE)
   {
    register int i,delta,Sum;
    
    delta = (int)(colE-colS)+1;
    Sum = 0;
    for(i=0; i<MAX_DECO_NUMBER; i++)
       {
        deco[i] = (myPixel)colS;
        Sum += delta;
        if(Sum >= MAX_DECO_NUMBER)
          {
           colS++;
           Sum -= MAX_DECO_NUMBER;
          }
       }
   }

/*
 * Create pixel translation table from decoding vector
 */

void GR_Trans(ViewportInfo *view, Pixel *colTrans, Boolean transCol, int export)
   {
    int i;
    myPixel *deco, *trans;

    trans = view->trans;
    deco = view->deco;
    if(transCol || export )
      {
       for(i=0; i< MAX_DECO_NUMBER; i++)
	  *trans++ = *deco++;
      }
    else
      {
       /* data fits into myPixel */
       for(i=0; i< MAX_DECO_NUMBER; i++)
	  *trans++ = (myPixel) colTrans[*deco++];
      }
    if(!export)
      view->changed &= ~TRANS_CHANGED;
   }

/*
 * Reset the deco and trans of all viewports
 */

void GR_ResetAllDecoding(XDimInfo *XDim)
   {
    ViewportInfo *VWI; 
    XDColorInfo *XDC;
    int i;
    
    XDC = &(XDim->colors);
    VWI = XDim->Views;
    for(i=0; i<MAX_VIEWPORT_NUMBER; i++)
       {
        if((VWI[i]).pict)
          {
           (VWI[i]).colS = XDC->colS;
           (VWI[i]).colE = XDC->colE;
           GR_InitDeco((VWI[i]).deco, (VWI[i]).colS, (VWI[i]).colE);
	   (VWI[i]).changed |= TRANS_AND_CHANGE;
          }
       }
   }

/*
 * Read the pixel at x,y
 */

int GR_ReadPixel(int x, int y)
  {
   int val;
   extern XDimInfo XDim;
   ViewportInfo *view;
   
   view = &((XDim.Views)[XDim.port]);
   val = (int) *(view->pict+y*view->pwidth+x);
   return(val);
  }


/*
 * Hidden line algorithm
 * all coordinates are between -CO_ONE and + CO_ONE;
 */

void GR_myHiddenLine(myPixel Col, int x0, int y0,
	int x1, int y1, myCoor *HMin, myCoor *HMax,
	int pwidth, int pheight, myPixel *pict)
   {
    int yStep, maxY;
    int delX, delY, Sum, Min, Max;
    myPixel *dp;
    
    delX = x1-x0;
    delY = y1-y0;
#ifndef PICUP
    dp = pict+(pheight-1-y0)*pwidth+x0;
    yStep= -pwidth;
#else
    dp = pict+y0*pwidth+x0;
    yStep= pwidth;
#endif /* PICUP */
    HMin += x0;
    HMax += x0;
    maxY = CO_ONE;
    if(delX >= delY && delY >=0)
      {
       Sum = delX >> 1;
       while(x0<pwidth)
         {
          if(x0 >=0)
            {
             if(y0 > *HMax)
               {
                if(y0 >= 0 && y0 < pheight)
        	  *dp = Col;
        	*HMax = y0;
        	if(y0 < *HMin)
        	  *HMin = y0;
               }
             else if(y0 < *HMin)
               {
                if(y0 >= 0 && y0 < pheight)
        	  *dp = Col;
        	*HMin = y0;
               }
            }
          Sum += delY;
          if(Sum >= delX)
            {
             dp += yStep;
             y0++;
             Sum -= delX;
            }
	  x0++;
	  if(x0>=x1)
	     break;
	  dp++;
	  HMax++;
	  HMin++;
         }
      }
    else if(delY > delX && delX >= 0)
      {
       Sum = delY >> 1;
       Max = *HMax;
       Min = *HMin;
       while(x0<pwidth)
         {
          if(x0 >=0)
            {
             if(y0 > *HMax)
               {
                if(y0 >= 0 && y0 < pheight)
        	  *dp = Col;
        	Max = y0;
        	if(y0 < *HMin)
        	  Min = y0;
               }
             else if(y0 < *HMin)
               {
                if(y0 >= 0 && y0 < pheight)
        	  *dp = Col;
        	Min = y0;
               }
            }
          y0++;
	  if(y0>=y1)
	    {
	     break;
	    }
	  dp += yStep;
          Sum += delX;
          if(Sum >= delY)
            {
             Sum -= delY;
	     if(x0!=x1)
	       {
		*HMax = Max;
		*HMin = Min;
	       }
             x0++;
             dp++;
	     HMax++;
	     HMin++;
	     Max = *HMax;
	     Min = *HMin;
            }
         }
      }
    else if(delX < 0 && delY >=0)
      {
       delX = -delX;
       if(delX >= delY)
         {
	  Sum = delX >> 1;
	  while(x0>=0)
            {
             if(x0 < pwidth)
               {
        	if(y0 > *HMax)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	   *HMax = y0;
        	   if(y0 < *HMin)
        	     *HMin = y0;
        	  }
        	else if(y0 < *HMin)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	   *HMin = y0;
        	  }
               }
             Sum += delY;
             if(Sum >= delX)
               {
                y0++;
        	dp += yStep;
        	Sum -= delX;
               }
	     --x0;
	     if(x0<=x1)
		break;
	     --dp;
	     --HMax;
	     --HMin;
            }
	 }
       else
	 {
	  Sum = delY >> 1;
	  Min = *HMin;
	  Max = *HMax;
	  while(x0>=0)
            {
             if(x0 < pwidth)
               {
        	if(y0 > *HMax)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	   Max = y0;
        	   if(y0 < *HMin)
        	     Min = y0;
        	  }
        	else if(y0 < *HMin)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	   Min = y0;
        	  }
               }
             Sum += delX;
             y0++;
	     if(y0>=y1)
	       {
		break;
	       }
	     dp += yStep;
             if(Sum >= delY)
               {
        	Sum -= delY;
		if(x0!=x1)
		  {
		   *HMax = Max;
		   *HMin = Min;
		  }
        	--x0;
        	--dp;
		--HMax;
		--HMin;
		Max = *HMax;
		Min = *HMin;
               }
            }
         }
      }
    else if(delX < 0 && delY <0)
      {
       delX = -delX;
       delY = -delY;
       if(delX >= delY)
         {
	  Sum = delX >> 1;
	  while(x0>=0)
            {
             if(x0 < pwidth)
               {
        	if(y0 > *HMax)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	   *HMax = y0;
        	   if(y0 < *HMin)
        	     *HMin = y0;
        	  }
        	else if(y0 < *HMin)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	   *HMin = y0;
        	  }
               }
             Sum += delY;
             if(Sum >= delX)
               {
                --y0;
        	dp -= yStep;
        	Sum -= delX;
               }
	     --x0;
	     if(x0<=x1)
		break;
	     --dp;
	     --HMax;
	     --HMin;
            }
	 }
       else
	 {
	  Sum = delY >> 1;
	  Min = *HMin;
	  Max = *HMax;
	  while(x0>=0)
            {
             if(x0 < pwidth)
               {
        	if(y0 > *HMax)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	   Max = y0;
        	   if(y0 < *HMin)
        	     Min = y0;
        	  }
        	else if(y0 < *HMin)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	   Min = y0;
        	  }
               }
             y0--;
	     if(y0<=y1)
	       {
		break;
	       }
	     dp -= yStep;
             Sum += delX;
             if(Sum >= delY)
               {
        	Sum -= delY;
		if(x0!=x1)
		  {
		   *HMax = Max;
		   *HMin = Min;
		  }
		--HMax;
		--HMin;
        	--x0;
        	--dp;
		Max = *HMax;
		Min = *HMin;
               }
            }
         }
      }
    else if(delX >= 0 && delY <0)
      {
       delY = -delY;
       if(delX >= delY)
         {
	  Sum = delX >> 1;
	  while(x0<pwidth)
            {
             if(x0>=0)
               {
        	if(y0 > *HMax)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	   *HMax = y0;
        	   if(y0 < *HMin)
        	     *HMin = y0;
        	  }
        	else if(y0 < *HMin)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	   *HMin = y0;
        	  }
               }
             Sum += delY;
             if(Sum >= delX)
               {
                --y0;
        	dp -= yStep;
        	Sum -= delX;
               }
	     x0++;
	     if(x0>=x1)
		break;
	     dp++;
	     HMax++;
	     HMin++;
            }
	 }
       else
	 {
	  Sum = delY >> 1;
	  Min = *HMin;
	  Max = *HMax;
	  while(x0< pwidth)
            {
             if(x0>=0)
               {
        	if(y0 > *HMax)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	   Max = y0;
        	   if(y0 < *HMin)
        	     Min = y0;
        	  }
        	else if(y0 < *HMin)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	   Min = y0;
        	  }
               }
             y0--;
	     if(y0<=y1)
	       {
		break;
	       }
	     dp -= yStep;
             Sum += delX;
             if(Sum >= delY)
               {
        	Sum -= delY;
		if(x0!=x1)
		  {
		   *HMax = Max;
		   *HMin = Min;
		  }
        	x0++;
        	dp++;
		HMax++;
		HMin++;
		Max = *HMax;
		Min = *HMin;
               }
            }
         }
      }
   }


/*
 * Hidden line algorithm, without storing values back (axis)
 * all coordinates are between -CO_ONE and + CO_ONE;
 */

void GR_HideLine(myPixel Col, int x0, int y0,
	int x1, int y1, myCoor *HMin, myCoor *HMax,
	int pwidth, int pheight, myPixel *pict)
   {
    int yStep, maxY;
    int delX, delY, Sum, Min, Max;
    myPixel *dp;
    
    delX = x1-x0;
    delY = y1-y0;
#ifndef PICUP
    dp = pict+(pheight-1-y0)*pwidth+x0;
    yStep= -pwidth;
#else
    dp = pict+y0*pwidth+x0;
    yStep= pwidth;
#endif /* PICUP */
    HMin += x0;
    HMax += x0;
    maxY = CO_ONE;
    if(delX >= delY && delY >=0)
      {
       Sum = delX >> 1;
       while(x0<pwidth)
         {
          if(x0 >=0)
            {
             if(y0 > *HMax)
               {
                if(y0 >= 0 && y0 < pheight)
        	  *dp = Col;
               }
             else if(y0 < *HMin)
               {
                if(y0 >= 0 && y0 < pheight)
        	  *dp = Col;
               }
            }
          Sum += delY;
          if(Sum >= delX)
            {
             dp += yStep;
             y0++;
             Sum -= delX;
            }
	  x0++;
	  if(x0>=x1)
	     break;
	  dp++;
	  HMax++;
	  HMin++;
         }
      }
    else if(delY > delX && delX >= 0)
      {
       Sum = delY >> 1;
       Min = *HMin;
       Max = *HMax;
       while(x0<pwidth)
         {
          if(x0 >=0)
            {
             if(y0 > Max)
               {
                if(y0 >= 0 && y0 < pheight)
        	  *dp = Col;
               }
             else if(y0 < Min)
               {
                if(y0 >= 0 && y0 < pheight)
        	  *dp = Col;
               }
            }
          y0++;
	  if(y0>=y1)
	     break;
	  dp += yStep;
          Sum += delX;
          if(Sum >= delY)
            {
             Sum -= delY;
             x0++;
             dp++;
             if(x0!=x1)
               {
		Max = *(++HMax);
		Min = *(++HMin);
	       }
            }
         }
      }
    else if(delX < 0 && delY >=0)
      {
       delX = -delX;
       if(delX >= delY)
         {
	  Sum = delX >> 1;
	  while(x0>=0)
            {
             if(x0 < pwidth)
               {
        	if(y0 > *HMax)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	  }
        	else if(y0 < *HMin)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	  }
               }
             Sum += delY;
             if(Sum >= delX)
               {
                y0++;
        	dp += yStep;
        	Sum -= delX;
               }
	     --x0;
	     if(x0<=x1)
		break;
	     --dp;
	     --HMax;
	     --HMin;
            }
	 }
       else
	 {
	  Sum = delY >> 1;
	  Min = *HMin;
	  Max = *HMax;
	  while(x0>=0)
            {
             if(x0 < pwidth)
               {
        	if(y0 > Max)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	  }
        	else if(y0 < Min)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	  }
               }
             Sum += delX;
             y0++;
	     if(y0>=y1)
		break;
	     dp += yStep;
             if(Sum >= delY)
               {
        	Sum -= delY;
        	--x0;
        	--dp;
        	if(x0!=x1)
        	  {
		   Max = *(--HMax);
		   Min = *(--HMin);
		  }
               }
            }
         }
      }
    else if(delX < 0 && delY <0)
      {
       delX = -delX;
       delY = -delY;
       if(delX >= delY)
         {
	  Sum = delX >> 1;
	  while(x0>=0)
            {
             if(x0 < pwidth)
               {
        	if(y0 > *HMax)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	  }
        	else if(y0 < *HMin)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	  }
               }
             Sum += delY;
             if(Sum >= delX)
               {
                --y0;
        	dp -= yStep;
        	Sum -= delX;
               }
	     --x0;
	     if(x0<=x1)
		break;
	     --dp;
	     --HMax;
	     --HMin;
            }
	 }
       else
	 {
	  Sum = delY >> 1;
	  Min = *HMin;
	  Max = *HMax;
	  while(x0>=0)
            {
             if(x0 < pwidth)
               {
        	if(y0 > Max)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	  }
        	else if(y0 < Min)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	  }
               }
             y0--;
	     if(y0<=y1)
		break;
	     dp -= yStep;
             Sum += delX;
             if(Sum >= delY)
               {
        	Sum -= delY;
        	--x0;
        	--dp;
        	if(x0!=x1)
        	  {
		   Max = *(--HMax);
		   Min = *(--HMin);
		  }
               }
            }
         }
      }
    else if(delX >= 0 && delY <0)
      {
       delY = -delY;
       if(delX >= delY)
         {
	  Sum = delX >> 1;
	  while(x0<pwidth)
            {
             if(x0>=0)
               {
        	if(y0 > *HMax)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	  }
        	else if(y0 < *HMin)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	  }
               }
             Sum += delY;
             if(Sum >= delX)
               {
                --y0;
        	dp -= yStep;
        	Sum -= delX;
               }
	     x0++;
	     if(x0>=x1)
		break;
	     dp++;
	     HMax++;
	     HMin++;
            }
	 }
       else
	 {
	  Sum = delY >> 1;
	  Min = *HMin;
	  Max = *HMax;
	  while(x0< pwidth)
            {
             if(x0>=0)
               {
        	if(y0 > Max)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	  }
        	else if(y0 < Min)
        	  {
                   if(y0 >= 0 && y0 < pheight)
        	     *dp = Col;
        	  }
               }
             y0--;
	     if(y0<=y1)
		break;
	     dp -= yStep;
             Sum += delX;
             if(Sum >= delY)
               {
        	Sum -= delY;
        	x0++;
        	dp++;
        	if(x0!=x1)
        	  {
		   Max = *(++HMax);
		   Min = *(++HMin);
		  }
               }
            }
         }
      }
   }

/*
 * Fill a Triangle with color
 */

void GR_Triangle(myPixel *trans, myCoor x0, myCoor y0,
	myCoor x1, myCoor y1, myCoor x2, myCoor y2, myCoor z0,
	int pwidth, int pheight, myPixel *pict)
   {
    int yStep,x1Step,x2Step,zStep,z1Step,z2Step;
    myCoor delX1, delY1, delX2, delY2, SumX1, SumX2;
    myCoor x, x01, x02, FactXZ, delX;
    myPixel *dp, col, *dp1;
    
    if(y0 > y1)
      {
       if(y1 < y2)
         {
          delX2 = x1;
          x1 = x0;
          x0 = delX2;
          delX2 = y1;
          y1 = y0;
          y0 = delX2;
         }
       else
         {
          delX2 = x2;
          x2 = x0;
          x0 = delX2;
          delX2 = y2;
          y2 = y0;
          y0 = delX2;
         }
      }
    else if(y0 > y2)
      {
       delX2 = x2;
       x2 = x0;
       x0 = delX2;
       delX2 = y2;
       y2 = y0;
       y0 = delX2;
      }
    delX1 = x1-x0;
    delX2 = x2-x0;
    delY1 = y1-y0;
    delY2 = y2-y0;
    if(delX1*delY2 > delX2*delY1)
      {
       delX1 = x2;
       x2 = x1;
       x1 = delX1;
       delX1 = y2;
       y2 = y1;
       y1 = delX1;
       delX1 = delX2;
       delX2 = x2-x0;
       delY1 = delY2;
       delY2 = y2-y0;
      }
    if(y1 <0 && y2 <0) goto StopIt;
    if(y0 >= pheight) goto StopIt;
    if(x2 < 0 && x0 <0) goto StopIt;
    if(x1 > pwidth && x0 > pwidth) goto StopIt;
#ifndef PICUP
    dp = pict+(pheight-1-y0)*pwidth+x0;
    yStep= -pwidth;
#else
    dp = pict+y0*pwidth+x0;
    yStep= pwidth;
#endif /* PICUP */
    col = *(trans + z0);
    CO_getStep(delX1,x1Step);
    CO_getStep(delX2,x2Step);
    SumX1 = delX1>>1;
    SumX2 = delX2>>1;
    x01= x0;
    x02= x0;
    if(y1 < y2)
      {
       while(y0<=y1 && y0<pheight)
         {
          while(SumX1>=delY1)
            {
             if(x01==x1) break;
             x01 += x1Step;
             dp += x1Step;
             SumX1 -= delY1;
            }
          while(SumX2>=delY2)
            {
             if(x02==x2) break;
             x02 += x2Step;
             SumX2 -= delY2;
            }
          if(y0 >=0)
            {
             dp1 = dp;
             for(x=x01; x<=x02;x++)
                {
                 if(x>=pwidth) break;
                 if(x>=0)
                   *dp1++ = col;
                 else
                   dp1++;
                }
            }
          SumX1 += delX1;
          SumX2 += delX2;
          dp += yStep;
          y0++;
         }
       if(y0 < pheight)
         {
	  delY1 = y2-y1;
	  delX1 = x2-x1;
	  CO_getStep(delX1,x1Step);
	  SumX1 = delX1;
         }
       while(y0<=y2 && y0 < pheight)
         {
          while(SumX1>=delY1)
            {
             if(x01==x2) break;
             x01 += x1Step;
             dp += x1Step;
             SumX1 -= delY1;
            }
          while(SumX2>=delY2)
            {
             if(x02 == x2) break;
             x02 += x2Step;
             SumX2 -= delY2;
            }
          if(y0 >=0)
            {
             dp1 = dp;
             for(x=x01; x<=x02;x++)
                {
                 if(x>=pwidth) break;
                 if(x>=0)
                    *dp1++ = col;
                 else
                   dp1++;
                }
            }
          SumX1 += delX1;
          SumX2 += delX2;
          dp += yStep;
          y0++;
         }
      }
    else
      {
       while(y0<=y2 && y0 < pheight)
         {
          while(SumX1>=delY1)
            {
             if(x01==x1) break;
             x01 += x1Step;
             dp += x1Step;
             SumX1 -= delY1;
            }
          while(SumX2>=delY2)
            {
             if(x02==x2) break;
             x02 += x2Step;
             SumX2 -= delY2;
            }
          if(y0 >=0)
            {
             dp1 = dp;
             for(x=x01; x<=x02;x++)
                {
                 if(x>=pwidth) break;
                 if(x>=0)
                    *dp1++ = col;
                 else
                   dp1++;
                }
            }
          SumX1 += delX1;
          SumX2 += delX2;
          dp += yStep;
          y0++;
         }
       if(y0 < pheight)
         {
	  delY2 = y1-y2;
	  delX2 = x1-x2;
	  CO_getStep(delX2,x2Step);
	  SumX2 = delX2;
         }
       while(y0<=y1 && y0 < pheight)
         {
          while(SumX1>=delY1)
            {
             if(x01==x1) break;
             x01 += x1Step;
             dp += x1Step;
             SumX1 -= delY1;
            }
          while(SumX2>=delY2)
            {
             if(x02 == x1) break;
             x02 += x2Step;
             SumX2 -= delY2;
            }
          if(y0 >=0 && x01 <pwidth && x02 >=0)
            {
             dp1 = dp;
             for(x=x01; x<=x02;x++)
                {
                 if(x>=pwidth) break;
                 if(x>=0)
                    *dp1++ = col;
                 else
                   dp1++;
                }
            }
          SumX1 += delX1;
          SumX2 += delX2;
          dp += yStep;
          y0++;
         }
      }
StopIt:;
   }

/*
 * Fill a Triangle with interpolated colors
 */

void GR_myTriangle(myPixel *trans, myCoor x0, myCoor y0, myCoor z0,
	myCoor x1, myCoor y1, myCoor z1, myCoor x2, myCoor y2, myCoor z2,
	int pwidth, int pheight, myPixel *pict)
   {
    int yStep,x1Step,x2Step,zStep,z1Step,z2Step;
    myCoor delZ, delX1, delY1, delZ1, delX2, delY2, delZ2, SumX1, SumX2;
    myCoor x01,z01,x02,z02, SumZ1, FactXZ, SumZ2, SumZ, delX;
    myCoor x, z;
    myPixel *dp, *cp, *dp1, *cp1;
    
    if(y0 > y1)
      {
       if(y1 < y2)
         {
          delX2 = x1;
          x1 = x0;
          x0 = delX2;
          delX2 = y1;
          y1 = y0;
          y0 = delX2;
          delX2 = z1;
          z1 = z0;
          z0 = delX2;
         }
       else
         {
          delX2 = x2;
          x2 = x0;
          x0 = delX2;
          delX2 = y2;
          y2 = y0;
          y0 = delX2;
          delX2 = z2;
          z2 = z0;
          z0 = delX2;
         }
      }
    else if(y0 > y2)
      {
       delX2 = x2;
       x2 = x0;
       x0 = delX2;
       delX2 = y2;
       y2 = y0;
       y0 = delX2;
       delX2 = z2;
       z2 = z0;
       z0 = delX2;
      }
    delX1 = x1-x0;
    delX2 = x2-x0;
    delY1 = y1-y0;
    delY2 = y2-y0;
    if(delX1*delY2 > delX2*delY1)
      {
       delZ2 = x2;
       x2 = x1;
       x1 = delZ2;
       delZ2 = y2;
       y2 = y1;
       y1 = delZ2;
       delZ2 = z2;
       z2 = z1;
       z1 = delZ2;
       delX1 = delX2;
       delX2 = x2-x0;
       delY1 = delY2;
       delY2 = y2-y0;
      }
    if(y1 <0 && y2 <0) goto StopIt;
    if(y0 >= pheight) goto StopIt;
    if(x2 < 0 && x0 <0) goto StopIt;
    if(x1 > pwidth && x0 > pwidth) goto StopIt;
#ifndef PICUP
    dp = pict+(pheight-1-y0)*pwidth+x0;
    yStep= -pwidth;
#else
    dp = pict+y0*pwidth+x0;
    yStep= pwidth;
#endif /* PICUP */
    cp = trans + z0;
    delZ1 = z1-z0;
    delZ2 = z2-z0;
#ifdef MULTZ
    FactXZ = delY1*delX2-delY2*delX1;
    if(FactXZ!=0)
       FactXZ = (myCoor)(((double)(delY1*delZ2-delY2*delZ1)*(CO_ONE-2))/(double)FactXZ);
    else
      FactXZ = 1;
#endif /* MULTZ */
    CO_getStep(delX1,x1Step);
    CO_getStep(delX2,x2Step);
    CO_getStep(delZ1,z1Step);
    CO_getStep(delZ2,z2Step);
    SumX1 = delX1>>1;
    SumX2 = delX2>>1;
    x01= x0;
    x02= x0;
    SumZ1 = delZ1>>1;
    z01= z0;
#ifndef MULTZ
    SumZ2 = delZ2>>1;
    z02= z0;
#endif /* MULTZ */
    if(y1 < y2)
      {
       while(y0<=y1 && y0<pheight)
         {
          while(SumX1>=delY1)
            {
             if(x01==x1) break;
             x01 += x1Step;
             dp += x1Step;
             SumX1 -= delY1;
            }
          while(SumX2>=delY2)
            {
             if(x02==x2) break;
             x02 += x2Step;
             SumX2 -= delY2;
            }
          while(SumZ1>=delY1)
            {
             if(z01 == z1) break;
             z01 += z1Step;
             cp += z1Step;
             SumZ1 -= delY1;
            }
#ifndef MULTZ
          while(SumZ2>=delY2)
            {
             if(z02==z2) break;
             z02 += z2Step;
             SumZ2 -= delY2;
            }
#endif /* MULTZ*/
          if(y0 >=0)
            {
#ifndef MULTZ
             delX = x02-x01;
             delZ = z02-z01;
             CO_getStep(delZ,zStep);
             SumZ = delZ >> 1;
             cp1 = cp;
             z= z01;
#else
	     SumZ = 0;
#endif /*MULTZ*/
             dp1 = dp;
             for(x=x01; x<=x02;x++)
                {
                 if(x>=pwidth) break;
#ifndef MULTZ
                 SumZ += delZ;
                 while(SumZ >= delX)
                   {
                    if(z==z02) break;
        	    cp1 += zStep;
                    z+= zStep;
        	    SumZ -= delX;
        	   }
#else
                 z = (SumZ>>CO_ONESHIFT)+z01;
                 if(z>=CO_ONE)
                    z=CO_ONE-1;
                 else if(z<0)
                    z=0;
		 cp1 = trans + z;
                 SumZ += FactXZ;
#endif /*MULTZ*/
                 if(x>=0)
                   *dp1++ = *cp1;
                 else
                   dp1++;
                }
            }
          SumX1 += delX1;
          SumX2 += delX2;
          SumZ1 += delZ1;
#ifndef MULTZ
          SumZ2 += delZ2;
#endif /*MULTZ*/
          dp += yStep;
          y0++;
         }
       if(y0 < pheight)
         {
	  delY1 = y2-y1;
	  delX1 = x2-x1;
	  CO_getStep(delX1,x1Step);
	  SumX1 = delX1;
	  delZ1 = z2-z1;
	  CO_getStep(delZ1,z1Step);
	  SumZ1 = delZ1;
         }
       while(y0<=y2 && y0 < pheight)
         {
          while(SumX1>=delY1)
            {
             if(x01==x2) break;
             x01 += x1Step;
             dp += x1Step;
             SumX1 -= delY1;
            }
          while(SumX2>=delY2)
            {
             if(x02 == x2) break;
             x02 += x2Step;
             SumX2 -= delY2;
            }
          while(SumZ1>=delY1)
            {
             if(z01==z2) break;
             z01 += z1Step;
             cp += z1Step;
             SumZ1 -= delY1;
            }
#ifndef MULTZ
          while(SumZ2>=delY2)
            {
             if(z02 == z2) break;
             z02 += z2Step;
             SumZ2 -= delY2;
            }
#endif /*MULTZ*/
          if(y0 >=0)
            {
#ifndef MULTZ
             delX = x02-x01;
             delZ = z02-z01;
             CO_getStep(delZ,zStep);
             SumZ = delZ >> 1;
             z= z01;
             cp1 = cp;
#else
	     SumZ = 0;
#endif /*MULTZ*/
             dp1 = dp;
             for(x=x01; x<=x02;x++)
                {
                 if(x>=pwidth) break;
#ifndef MULTZ
                 SumZ += delZ;
                 while(SumZ >= delX)
                   {
                    if(z== z02) break;
                    z += zStep;
        	    cp1 += zStep;
        	    SumZ -= delX;
        	   }
#else
                 z = (SumZ>>CO_ONESHIFT)+z01;
                 if(z>=CO_ONE)
                   z= CO_ONE-1;
                 else if(z<0)
                   z=0;
		 cp1 = trans + z;
                 SumZ += FactXZ;
#endif /*MULTZ*/
                 if(x>=0)
                    *dp1++ = *cp1;
                 else
                   dp1++;
                }
            }
          SumX1 += delX1;
          SumX2 += delX2;
          SumZ1 += delZ1;
#ifndef MULTZ
          SumZ2 += delZ2;
#endif /*MULTZ*/
          dp += yStep;
          y0++;
         }
      }
    else
      {
       while(y0<=y2 && y0 < pheight)
         {
          while(SumX1>=delY1)
            {
             if(x01==x1) break;
             x01 += x1Step;
             dp += x1Step;
             SumX1 -= delY1;
            }
          while(SumX2>=delY2)
            {
             if(x02==x2) break;
             x02 += x2Step;
             SumX2 -= delY2;
            }
          while(SumZ1>=delY1)
            {
             if(z01 == z1) break;
             z01 += z1Step;
             cp += z1Step;
             SumZ1 -= delY1;
            }
#ifndef MULTZ
          while(SumZ2>=delY2)
            {
             if(z02==z2) break;
             z02 += z2Step;
             SumZ2 -= delY2;
            }
#endif /* MULTZ */
          if(y0 >=0)
            {
#ifndef MULTZ
             delX = x02-x01;
             delZ = z02-z01;
             CO_getStep(delZ,zStep);
             SumZ = delZ >> 1;
             cp1 = cp;
             z= z01;
#else
	     SumZ = 0;
#endif
             dp1 = dp;
             for(x=x01; x<=x02;x++)
                {
                 if(x>=pwidth) break;
#ifndef MULTZ
                 SumZ += delZ;
                 while(SumZ >= delX)
                   {
                    if(z==z02) break;
                    z+= zStep;
        	    cp1 += zStep;
        	    SumZ -= delX;
        	   }
#else
                 z = (SumZ>>CO_ONESHIFT)+z01;
                 if(z>=CO_ONE)
                   z= CO_ONE-1;
                 else if(z<0)
                   z=0;
		 cp1 = trans + z;
                 SumZ += FactXZ;
#endif /*MULTZ*/
                 if(x>=0)
                    *dp1++ = *cp1;
                 else
                   dp1++;
                }
            }
          SumX1 += delX1;
          SumX2 += delX2;
          SumZ1 += delZ1;
#ifndef MULTZ
          SumZ2 += delZ2;
#endif /*MULTZ*/
          dp += yStep;
          y0++;
         }
       if(y0 < pheight)
         {
	  delY2 = y1-y2;
	  delX2 = x1-x2;
	  CO_getStep(delX2,x2Step);
	  SumX2 = delX2;
	  delZ2 = z1-z2;
	  CO_getStep(delZ2,z2Step);
	  SumZ2 = delZ2;
         }
       while(y0<=y1 && y0 < pheight)
         {
          while(SumX1>=delY1)
            {
             if(x01==x1) break;
             x01 += x1Step;
             dp += x1Step;
             SumX1 -= delY1;
            }
          while(SumX2>=delY2)
            {
             if(x02 == x1) break;
             x02 += x2Step;
             SumX2 -= delY2;
            }
          while(SumZ1>=delY1)
            {
             if(z01==z1) break;
             z01 += z1Step;
             cp += z1Step;
             SumZ1 -= delY1;
            }
#ifndef MULTZ
          while(SumZ2>=delY2)
            {
             if(z02 == z1) break;
             z02 += z2Step;
             SumZ2 -= delY2;
            }
#endif /*MULTZ*/
          if(y0 >=0 && x01 <pwidth && x02 >=0)
            {
#ifndef MULTZ
             delX = x02-x01;
             delZ = z02-z01;
             CO_getStep(delZ,zStep);
             SumZ = delZ >> 1;
             cp1 = cp;
             z= z01;
#else
	     SumZ = 0;
#endif /* MULTZ */
             dp1 = dp;
             for(x=x01; x<=x02;x++)
                {
                 if(x>=pwidth) break;
#ifndef MULTZ
                 SumZ += delZ;
                 while(SumZ >= delX)
                   {
                    if(z== z02) break;
                    z += zStep;
        	    cp1 += zStep;
        	    SumZ -= delX;
        	   }
#else
                 z = (SumZ>>CO_ONESHIFT)+z01;
                 if(z>=CO_ONE)
                   z= CO_ONE-1;
                 else if(z<0)
                   z=0;
		 cp1 = trans + z;
                 SumZ += FactXZ;
#endif /*MULTZ*/
                 if(x>=0)
                    *dp1++ = *cp1;
                 else
                   dp1++;
                }
            }
          SumX1 += delX1;
          SumX2 += delX2;
          SumZ1 += delZ1;
#ifndef MULTZ
          SumZ2 += delZ2;
#endif /*MULTZ*/
          dp += yStep;
          y0++;
         }
      }
StopIt:;
   }

/* draw axis in hidden line mode */

void GR_HiddenGridImage(myCoor x0, myCoor y0, myCoor Min, myCoor Max,
    int xys, ViewportInfo *view,
    XDimInfo *XDim)
   {
    XDHardwareInfo *HWI;
    XDColorInfo *XDC;
    myPixel Col, textCol, *pict;
    int Dx, Dy, i, modeX, xa, ya, xb, yb, xc, yc, xd, yd, ticsX, ticsY, ticsZ;
    int Sum, mode, modeY, smod, xt, yt, dx, dy, delx, dely;
    myCoor *HMin, *HMax, sinXY, cosXY, sinZ, cosZ, moveX, moveY, k;
    myCoor zoomX, zoomY, zoomZ, z0, zz, xi, yi, zi;
    myCoor coMaxX, coMaxY;
    char text[MAX_DIM_LENGTH+16];
    double val, sum, fact;
    
    HWI = &(XDim->hwInfo);
    XDC = &(XDim->colors);
    if(XDC->transCol || XDC->export)
      {
       Col = view->axisFore;
       textCol = XDC->textFore;
      }
    else
      {
       Col = (myPixel)((XDC->colTrans)[view->axisFore]);
       textCol = (myPixel)((XDC->colTrans)[XDC->textFore]);
      }
    sinXY = view->sinXY;
    cosXY = view->cosXY;
    sinZ = view->sinZ;
    cosZ = view->cosZ;
    moveX = view->moveX;
    moveY = view->moveY;
    zoomX = view->zoomX;
    zoomY = view->zoomY;
    zoomZ = view->zoomZ;
    k = view->k;
    pict = view->pict;
    Dx = view->pwidth;
    Dy = view->pheight;
    HMin = view->HMin;
    HMax = view->HMax;
    ticsX = view->Width-1;
    ticsY = view->Height-1;
    coMaxX = x0 <<1;
    if(x0 < 0)
      coMaxX = -coMaxX;
    coMaxY = y0 <<1;
    if(y0 < 0)
      coMaxY = -coMaxY;    
    if(view->ticsX > 1)
      ticsX = view->ticsX -1;
    else
      ticsX = 1;
    if(view->ticsY > 1)
      ticsY = view->ticsY -1;
    else
      ticsY = 1;
    if(view->ticsZ > 1)
      ticsZ = view->ticsZ -1;
    else
      ticsZ = 1;
    if(view->rotZ < PI/2.0)
      {
       smod = ALIGN_BOTTOM;
       z0 = Min;
       zz = Max;
      }
    else
      {
       z0 = Max;
       zz = Min;
       smod = ALIGN_TOP;
      }
   if(x0 > 0)
     ticsX = -ticsX;
   if(y0 > 0)
     ticsY = -ticsY;

/* Draw x Background */

    Sum = 0;
    for(i=0; i < view->ticsX; i++)
       {
        xi = Sum/ticsX+x0;
        Sum += coMaxX;
	CO_TransformXY(xa,ya,xt,yt,xi,y0,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
	CO_TransformXY(xb,yb,xt,yt,xi,y0,zz,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
        GR_HideLine(Col, xa, ya, xb, yb, HMin, HMax, Dx, Dy, pict);
       }
    if(view->baseZ == 0.0)
      fact = 1.0;
    else
      fact = 1.0/view->baseZ;
    if(z0 > 0)
      {
       ticsZ = -ticsZ;
       sum = view->Max*fact;
      }
    else
      sum = view->Min*fact;
    val = (view->Max-view->Min)*fact/ticsZ;

/* z Lines for x and y */

    CO_TransformXY(xa,ya,xt,yt,-x0,y0,z0,sinXY,cosXY,sinZ,cosZ,
	 zoomX,zoomY,zoomZ,moveX,moveY,k);
    CO_TransformXY(xb,yb,xt,yt,x0,y0,z0,sinXY,cosXY,sinZ,cosZ,
	 zoomX,zoomY,zoomZ,moveX,moveY,k);
    CO_TransformXY(xc,yc,xt,yt,x0,-y0,z0,sinXY,cosXY,sinZ,cosZ,
	 zoomX,zoomY,zoomZ,moveX,moveY,k);
    if(xc < xa)
      {
       modeX = ALIGN_RIGHT;
       modeY = ALIGN_LEFT;
      }
    else
      {
       modeX = ALIGN_LEFT;
       modeY = ALIGN_RIGHT;
      }
    for(i=1; i <= view->ticsZ; i++)
       {
        GR_HideLine(Col, xa, ya, xb, yb, HMin, HMax, Dx, Dy, pict);
        GR_HideLine(Col, xb, yb, xc, yc, HMin, HMax, Dx, Dy, pict);
        sprintf(text,"%1.2f",sum);
	dx = (xc-xb) >> 6;
	dy = (yc-yb) >> 6;
        HW_PutText(text, xc+dx, yc+dy, Dx, Dy, textCol,
		smod | modeX, pict, HWI);  
	dx = (xa-xb) >> 6;
	dy = (ya-yb) >> 6;
        HW_PutText(text, xa+dx, ya+dy, Dx, Dy, textCol,
		smod | modeY, pict, HWI);  
        sum += val;
        zi = (i<<CO_ONESHIFT)/ticsZ+z0;
	CO_TransformXY(xa,ya,xt,yt,-x0,y0,zi,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
	CO_TransformXY(xb,yb,xt,yt,x0,y0,zi,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
	CO_TransformXY(xc,yc,xt,yt,x0,-y0,zi,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
       }

/* Draw y Background */

    Sum = 0;
    for(i=0; i < view->ticsY; i++)
       {
        yi = Sum/ticsY+y0;
        Sum += coMaxY;
	CO_TransformXY(xa,ya,xt,yt,x0,yi,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
	CO_TransformXY(xb,yb,xt,yt,x0,yi,zz,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
        GR_HideLine(Col, xa, ya, xb, yb, HMin, HMax, Dx, Dy, pict);
       }

/* z-Axis Text */

    if(view->DrawAxisText)
      {
       HW_TextExtent(text, &delx, &dely, HWI);
       if(view->baseZ == 1.0)
         sprintf(text, "z: [%s]", view->DimZ);
       else if(view->baseZ > 0.01 && view->baseZ < 100.0)
         sprintf(text, "z: [%1.2f %s]", view->baseZ, view->DimZ);
       else
         sprintf(text, "z: [%1.2e %s]", view->baseZ, view->DimZ);
       if(dx < 0)
         {
          xi = -x0;
          yi = y0;
          delx = 1.5*delx-dx;
         }
       else
         {
          delx = 1.5*delx+dx;
          xi = x0;
          yi = -y0;
	 }
       if(dy < 0)
          dely = 1.5*dely-dy;
       else
          dely = 1.5*dely+dy;
       zi = (3*zz+z0)>>2;
       CO_TransformXY(xa,ya,xd,yd,xi,yi,zi,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
       HW_PutText(text, xa-delx, ya-dely, Dx, Dy, textCol,
		ALIGN_CENTER_Y|ALIGN_RIGHT, pict, HWI);  
      }


/* Draw z Background */

    if(view->rotZ < PI/2.0)
       smod = ALIGN_TOP;
    else
       smod = ALIGN_BOTTOM;
    if(view->baseX == 0.0)
      fact = 1.0;
    else
      fact = 1.0/view->baseX;
    val = (view->Width-1)*view->FactX*fact;
    sum = view->OffX*fact;
    if(xys & POS_TOP_X)
       sum += val;
    val /= ticsX;
    mode = smod | modeX;
    Sum = 0;
    for(i=0; i < view->ticsX; i++)
       {
        xi = Sum/ticsX+x0;
        Sum += coMaxX;
	CO_TransformXY(xa,ya,xt,yt,xi,y0,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
	CO_TransformXY(xb,yb,xt,yt,xi,-y0,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
        GR_HideLine(Col, xa, ya, xb, yb, HMin, HMax, Dx, Dy, pict);
	delx = (xb-xa) >> 6;
	dely = (yb-ya) >> 6;
        sprintf(text,"%1.2f",sum);
        HW_PutText(text, xb+delx, yb+dely, Dx, Dy, textCol,
		mode, pict, HWI);  
        sum += val;
       }

/* x-Axis Text */

    if(view->DrawAxisText)
      {
       HW_TextExtent(text, &dx, &dy, HWI);
       if(view->baseX == 1.0)
         sprintf(text, "x: [%s]", view->DimX);
       else if(view->baseX > 0.01 && view->baseX < 100.0)
         sprintf(text, "x: [%1.2f %s]", view->baseX, view->DimX);
       else
         sprintf(text, "x: [%1.2e %s]", view->baseX, view->DimX);
       CO_TransformXY(xa,ya,xt,yt,0,-y0,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
       if(delx > 0)
         delx += 1.5*dx;
       else
         delx -= 1.5*dx;
       if(dely >0)
         dely += 1.5*dy;
       else
         dely -= 1.5*dy;
       HW_PutText(text, xa+delx, ya+dely, Dx, Dy, textCol,
		mode, pict, HWI);  
      }

    if(view->baseY == 0.0)
      fact = 1.0;
    else
      fact = 1.0/view->baseY;
    val = (view->Height-1)*view->FactY*fact;
    sum = view->OffY*fact;
    if(xys & POS_TOP_Y)
       sum += val;
    val /= ticsY;
    mode = smod | modeY;
    Sum = 0;
    for(i=0; i < view->ticsY; i++)
       {
        yi = Sum/ticsY+y0;
        Sum += coMaxY;
	CO_TransformXY(xa,ya,xt,yt,x0,yi,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
	CO_TransformXY(xb,yb,xt,yt,-x0,yi,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
        GR_HideLine(Col, xa, ya, xb, yb, HMin, HMax, Dx, Dy, pict);
	delx = (xb-xa) >> 6;
	dely = (yb-ya) >> 6;
        sprintf(text,"%1.2f",sum);
        HW_PutText(text, xb+delx, yb+dely, Dx, Dy, textCol,
		mode, pict, HWI);  
        sum += val;
       }

/* y-Axis Text */

    if(view->DrawAxisText)
      {
       HW_TextExtent(text, &dx, &dy, HWI);
       if(view->baseY == 1.0)
         sprintf(text, "y: [%s]", view->DimY);
       else if(view->baseY > 0.01 && view->baseY < 100.0)
         sprintf(text, "y: [%1.2f %s]", view->baseY, view->DimY);
       else
         sprintf(text, "y: [%1.2e %s]", view->baseY, view->DimY);
       CO_TransformXY(xa,ya,xt,yt,-x0,0,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
       if(delx > 0)
         delx += 1.5*dx;
       else
         delx -= 1.5*dx;
       if(dely >0)
         dely += 1.5*dy;
       else
         dely -= 1.5*dy;
       HW_PutText(text, xa+delx, ya+dely, Dx, Dy, textCol,
		mode, pict, HWI);  
      }
   }


/* draw axis in colored mode */

void GR_ColoredGridImage(myCoor x0, myCoor y0, myCoor Min, myCoor Max,
    int xys, ViewportInfo *view,
    XDimInfo *XDim)
   {
    XDHardwareInfo *HWI;
    XDColorInfo *XDC;
    myPixel Col, textCol, bx, by, bz, *trans, *pict;
    int Dx, Dy, i, modeX, xa, ya, xb, yb, xc, yc, xd, yd, ticsX, ticsY, ticsZ;
    int Sum, mode, modeY, smod, xt, yt, dx, dy, delx, dely;
    myCoor *HMin, *HMax, sinXY, cosXY, sinZ, cosZ, moveX, moveY, k;
    myCoor zoomX, zoomY, zoomZ, z0, zz, xi, yi, zi;
    myCoor coMaxX, coMaxY;
    char text[MAX_DIM_LENGTH+16];
    double val, sum, fact;
    
    HWI = &(XDim->hwInfo);
    XDC = &(XDim->colors);
    if(XDC->transCol || XDC->export)
      {
       Col = view->axisFore;
       bx = view->axisBackX;
       by = view->axisBackY;
       bz = view->axisBackZ;
       textCol = XDC->textFore;
      }
    else
      {
       Col = (myPixel)((XDC->colTrans)[view->axisFore]);
       bx = (myPixel)((XDC->colTrans)[view->axisBackX]);
       by = (myPixel)((XDC->colTrans)[view->axisBackY]);
       bz = (myPixel)((XDC->colTrans)[view->axisBackZ]);
       textCol = (myPixel)((XDC->colTrans)[XDC->textFore]);
      }
    trans = view->trans;
    sinXY = view->sinXY;
    cosXY = view->cosXY;
    sinZ = view->sinZ;
    cosZ = view->cosZ;
    moveX = view->moveX;
    moveY = view->moveY;
    zoomX = view->zoomX;
    zoomY = view->zoomY;
    zoomZ = view->zoomZ;
    k = view->k;
    pict = view->pict;
    Dx = view->pwidth;
    Dy = view->pheight;
    HMin = view->HMin;
    HMax = view->HMax;
    ticsX = view->Width-1;
    ticsY = view->Height-1;
    coMaxX = x0 <<1;
    if(x0 < 0)
      coMaxX = -coMaxX;
    coMaxY = y0 <<1;
    if(y0 < 0)
      coMaxY = -coMaxY;    
    if(view->ticsX > 1)
      ticsX = view->ticsX -1;
    else
      ticsX = 1;
    if(view->ticsY > 1)
      ticsY = view->ticsY -1;
    else
      ticsY = 1;
    if(view->ticsZ > 1)
      ticsZ = view->ticsZ -1;
    else
      ticsZ = 1;
    if(view->rotZ < PI/2.0)
      {
       smod = ALIGN_BOTTOM;
       z0 = Min;
       zz = Max;
      }
    else
      {
       z0 = Max;
       zz = Min;
       smod = ALIGN_TOP;
      }
   if(x0 > 0)
     ticsX = -ticsX;
   if(y0 > 0)
     ticsY = -ticsY;

/* Draw colored backgrounds */

    CO_TransformXY(xa,ya,xt,yt,x0,y0,z0,sinXY,cosXY,sinZ,cosZ,
	 zoomX,zoomY,zoomZ,moveX,moveY,k);
    CO_TransformXY(xb,yb,xt,yt,-x0,y0,z0,sinXY,cosXY,sinZ,cosZ,
	 zoomX,zoomY,zoomZ,moveX,moveY,k);
    CO_TransformXY(xc,yc,xt,yt,x0,-y0,z0,sinXY,cosXY,sinZ,cosZ,
	 zoomX,zoomY,zoomZ,moveX,moveY,k);
    CO_TransformXY(xd,yd,xt,yt,-x0,-y0,z0,sinXY,cosXY,sinZ,cosZ,
	 zoomX,zoomY,zoomZ,moveX,moveY,k);
/* z */

    GR_Triangle(&bz, xa, ya, xc, yc, xb, yb, 0, Dx, Dy, pict);
    GR_Triangle(&bz, xd, yd, xb, yb, xc, yc, 0, Dx, Dy, pict);

/* xy */
    CO_TransformXY(xd,yd,xt,yt,x0,y0,zz,sinXY,cosXY,sinZ,cosZ,
	 zoomX,zoomY,zoomZ,moveX,moveY,k);
    GR_Triangle(&bx, xb, yb, xd, yd, xa, ya, 0, Dx, Dy, pict);
    GR_Triangle(&by, xc, yc, xa, ya, xd, yd, 0, Dx, Dy, pict);
    CO_TransformXY(xa,ya,xt,yt,-x0,y0,zz,sinXY,cosXY,sinZ,cosZ,
	 zoomX,zoomY,zoomZ,moveX,moveY,k);
    GR_Triangle(&bx, xb, yb, xd, yd, xa, ya, 0, Dx, Dy, pict);
    CO_TransformXY(xa,ya,xt,yt,x0,-y0,zz,sinXY,cosXY,sinZ,cosZ,
	 zoomX,zoomY,zoomZ,moveX,moveY,k);
    GR_Triangle(&by, xc, yc, xa, ya, xd, yd, 0, Dx, Dy, pict);

/* Draw x Background */

    Sum = 0;
    for(i=0; i < view->ticsX; i++)
       {
        xi = Sum/ticsX+x0;
        Sum += coMaxX;
	CO_TransformXY(xa,ya,xt,yt,xi,y0,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
	CO_TransformXY(xb,yb,xt,yt,xi,y0,zz,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
        HW_PutLine(Col, xa, ya, xb, yb, Dx, Dy, pict, HWI);
       }
    if(view->baseZ == 0.0)
      fact = 1.0;
    else
      fact = 1.0/view->baseZ;
    if(z0 > 0)
      {
       ticsZ = -ticsZ;
       sum = view->Max*fact;
      }
    else
      sum = view->Min*fact;
    val = (view->Max-view->Min)*fact/ticsZ;

/* z Lines for x and y */

    CO_TransformXY(xa,ya,xt,yt,-x0,y0,z0,sinXY,cosXY,sinZ,cosZ,
	 zoomX,zoomY,zoomZ,moveX,moveY,k);
    CO_TransformXY(xb,yb,xt,yt,x0,y0,z0,sinXY,cosXY,sinZ,cosZ,
	 zoomX,zoomY,zoomZ,moveX,moveY,k);
    CO_TransformXY(xc,yc,xt,yt,x0,-y0,z0,sinXY,cosXY,sinZ,cosZ,
	 zoomX,zoomY,zoomZ,moveX,moveY,k);
    if(xc < xa)
      {
       modeX = ALIGN_RIGHT;
       modeY = ALIGN_LEFT;
      }
    else
      {
       modeX = ALIGN_LEFT;
       modeY = ALIGN_RIGHT;
      }
    for(i=1; i <= view->ticsZ; i++)
       {
        HW_PutLine(Col, xa, ya, xb, yb, Dx, Dy, pict, HWI);
        HW_PutLine(Col, xb, yb, xc, yc, Dx, Dy, pict, HWI);
        sprintf(text,"%1.2f",sum);
	dx = (xc-xb) >> 6;
	dy = (yc-yb) >> 6;
        HW_PutText(text, xc+dx, yc+dy, Dx, Dy, textCol,
		smod | modeX, pict, HWI);  
	dx = (xa-xb) >> 6;
	dy = (ya-yb) >> 6;
        HW_PutText(text, xa+dx, ya+dy, Dx, Dy, textCol,
		smod | modeY, pict, HWI);  
        sum += val;
        zi = (i<<CO_ONESHIFT)/ticsZ+z0;
	CO_TransformXY(xa,ya,xt,yt,-x0,y0,zi,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
	CO_TransformXY(xb,yb,xt,yt,x0,y0,zi,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
	CO_TransformXY(xc,yc,xt,yt,x0,-y0,zi,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
       }

/* Draw y Background */

    Sum = 0;
    for(i=0; i < view->ticsY; i++)
       {
        yi = Sum/ticsY+y0;
        Sum += coMaxY;
	CO_TransformXY(xa,ya,xt,yt,x0,yi,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
	CO_TransformXY(xb,yb,xt,yt,x0,yi,zz,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
        HW_PutLine(Col, xa, ya, xb, yb, Dx, Dy, pict, HWI);
       }

/* z-Axis Text */

    if(view->DrawAxisText)
      {
       HW_TextExtent(text, &delx, &dely, HWI);
       if(view->baseZ == 1.0)
         sprintf(text, "z: [%s]", view->DimZ);
       else if(view->baseZ > 0.01 && view->baseZ < 100.0)
         sprintf(text, "z: [%1.2f %s]", view->baseZ, view->DimZ);
       else
         sprintf(text, "z: [%1.2e %s]", view->baseZ, view->DimZ);
       if(dx < 0)
         {
          xi = -x0;
          yi = y0;
          delx = 1.5*delx-dx;
         }
       else
         {
          delx = 1.5*delx+dx;
          xi = x0;
          yi = -y0;
	 }
       if(dy < 0)
          dely = 1.5*dely-dy;
       else
          dely = 1.5*dely+dy;
       zi = (3*zz+z0)>>2;
       CO_TransformXY(xa,ya,xd,yd,xi,yi,zi,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
       HW_PutText(text, xa-delx, ya-dely, Dx, Dy, textCol,
		ALIGN_CENTER_Y|ALIGN_RIGHT, pict, HWI);  
      }


/* Draw z Background */

    if(view->rotZ < PI/2.0)
       smod = ALIGN_TOP;
    else
       smod = ALIGN_BOTTOM;
    if(view->baseX == 0.0)
      fact = 1.0;
    else
      fact = 1.0/view->baseX;
    val = (view->Width-1)*view->FactX*fact;
    sum = view->OffX*fact;
    if(xys & POS_TOP_X)
       sum += val;
    val /= ticsX;
    mode = smod | modeX;
    Sum = 0;
    for(i=0; i < view->ticsX; i++)
       {
        xi = Sum/ticsX+x0;
        Sum += coMaxX;
	CO_TransformXY(xa,ya,xt,yt,xi,y0,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
	CO_TransformXY(xb,yb,xt,yt,xi,-y0,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
        HW_PutLine(Col, xa, ya, xb, yb, Dx, Dy, pict, HWI);
	delx = (xb-xa) >> 6;
	dely = (yb-ya) >> 6;
        sprintf(text,"%1.2f",sum);
        HW_PutText(text, xb+delx, yb+dely, Dx, Dy, textCol,
		mode, pict, HWI);  
        sum += val;
       }

/* x-Axis Text */

    if(view->DrawAxisText)
      {
       HW_TextExtent(text, &dx, &dy, HWI);
       if(view->baseX == 1.0)
         sprintf(text, "x: [%s]", view->DimX);
       else if(view->baseX > 0.01 && view->baseX < 100.0)
         sprintf(text, "x: [%1.2f %s]", view->baseX, view->DimX);
       else
         sprintf(text, "x: [%1.2e %s]", view->baseX, view->DimX);
       CO_TransformXY(xa,ya,xt,yt,0,-y0,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
       if(delx > 0)
         delx += 1.5*dx;
       else
         delx -= 1.5*dx;
       if(dely >0)
         dely += 1.5*dy;
       else
         dely -= 1.5*dy;
       HW_PutText(text, xa+delx, ya+dely, Dx, Dy, textCol,
		mode, pict, HWI);  
      }

    if(view->baseY == 0.0)
      fact = 1.0;
    else
      fact = 1.0/view->baseY;
    val = (view->Height-1)*view->FactY*fact;
    sum = view->OffY*fact;
    if(xys & POS_TOP_Y)
       sum += val;
    val /= ticsY;
    mode = smod | modeY;
    Sum = 0;
    for(i=0; i < view->ticsY; i++)
       {
        yi = Sum/ticsY+y0;
        Sum += coMaxY;
	CO_TransformXY(xa,ya,xt,yt,x0,yi,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
	CO_TransformXY(xb,yb,xt,yt,-x0,yi,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
        HW_PutLine(Col, xa, ya, xb, yb, Dx, Dy, pict, HWI);
	delx = (xb-xa) >> 6;
	dely = (yb-ya) >> 6;
        sprintf(text,"%1.2f",sum);
        HW_PutText(text, xb+delx, yb+dely, Dx, Dy, textCol,
		mode, pict, HWI);  
        sum += val;
       }

/* y-Axis Text */

    if(view->DrawAxisText)
      {
       HW_TextExtent(text, &dx, &dy, HWI);
       if(view->baseY == 1.0)
         sprintf(text, "y: [%s]", view->DimY);
       else if(view->baseY > 0.01 && view->baseY < 100.0)
         sprintf(text, "y: [%1.2f %s]", view->baseY, view->DimY);
       else
         sprintf(text, "y: [%1.2e %s]", view->baseY, view->DimY);
       CO_TransformXY(xa,ya,xt,yt,-x0,0,z0,sinXY,cosXY,sinZ,cosZ,
	     zoomX,zoomY,zoomZ,moveX,moveY,k);
       if(delx > 0)
         delx += 1.5*dx;
       else
         delx -= 1.5*dx;
       if(dely >0)
         dely += 1.5*dy;
       else
         dely -= 1.5*dy;
       HW_PutText(text, xa+delx, ya+dely, Dx, Dy, textCol,
		mode, pict, HWI);  
      }
   }

