#include "xheaders.h"

#include XGraphicObject_i
#include XGraphicDevice_i
#include XLine_i
#include XColor_i
#include XRect_i
#include XFont_i
#include XText_i
#include XBox_i
#include XMarker_i
#include XBitmap_i
#include XFile_i
#include XResource_i
#include XResourceLibrary_i
#include XBitmapShadow_i

#include "stdlib.h"
#include "string.h"
#include XUserButton_i

XGraphicObject :: XGraphicObject( XGraphicDevice * d, XPoint * point )
{
  next = NULL;
  dev = d;
  p.p = point->p;
  dev->AddObject( this);
}

XGraphicObject :: XGraphicObject()
{
   next = NULL;
}


/*
void XGraphicObject :: GetPos( XPoint * point)
{
  point->p = p.p;
}


void XGraphicObject :: Move (XPoint * point)
{
  p.p.x = x;
  p.p.y = y;
}
*/

void XGraphicObject :: Show( BOOL show )
{
   if( show)
      {
         if( settings & GO_HIDE)
            settings ^= GO_HIDE;
      }
   else
      settings|= GO_HIDE;

  Draw();
}


/*
void XGraphicObject :: GetColor( XColor * c )
{
  memcpy( &c->color, &color, 4);
}
*/

void XGraphicObject :: SetupDevice( void )
{
  LONG c = color.GetColor();

  if( dev->aktColor != c)
     {
         dev->aktColor = c;
         GpiSetColor( dev->hps, c);
     }
}

/*
void XGraphicObject :: SetColor( XColor * c )
{
  memcpy( &color, &c->color, 4);
}
*/

XGraphicObject :: ~XGraphicObject()
{
  if(dev)
     dev->RemoveObject( this, FALSE);
}


/*
XMarker :: XMarker ( XGraphicDevice *d, XPoint * point, SHORT t):XGraphicObject(d, point )
{
  type = t;
}
*/

void XMarker :: Draw( XRect * r)
{
   if( dev->markerType != type)
     {
        dev->markerType = type;
        GpiSetMarker( dev->hps, type);
     }

   GpiMove( dev->hps, &p.p);
   GpiMarker( dev->hps, &p.p);
}

/*
void XLine :: SetLineWidth( char width )
{
   lineWidth = width;
}


void XLine :: SetLineEnd( char end )
{
   lineEnd = end;
}


void XLine :: SetLineJoin( char join )
{
   lineJoin = join;
}
*/

void XLine :: SetupDevice( void )
{
  XGraphicObject :: SetupDevice();

  if( lineJoin != dev->aktLineJoining)
     dev->SetLineJoin( lineJoin);
  if( lineEnd != dev->aktLineEnding)
     dev->SetLineEnd( lineEnd );
  if( lineWidth != dev->aktLineWidth)
     dev->SetLineWidth( lineWidth);
}


void XLine :: Draw( XRect * r )
{
  if( !(settings & GO_HIDE))
    {
       SetupDevice( );
       GpiBeginPath( dev->hps, 1);
       GpiMove( dev->hps, &p.p);
       POINTL ptl = p.p;
       ptl.x += p2.p.x;
       ptl.y += p2.p.y;
       GpiLine( dev->hps, &ptl);
       GpiEndPath( dev->hps);
       GpiStrokePath( dev->hps, 1, 0);
    }
}

/*
void XLine :: SetWight( LONG x)
{
  p2.p.x = p.p.x + x;
}


void XLine :: SetHight( LONG y)
{
  p2.p.y = p.p.y + y;
}


LONG XLine :: GetWight( void )
{
   return p2.p.x - p.p.x;
}


LONG XLine :: GetHight( void )
{
   return p2.p.y - p.p.y;
}
*/

XLine :: XLine ( XGraphicDevice * d, XPoint * pp1, XPoint * pp2):XGraphicObject( d, pp1)
{
  p2.p.x = pp2->p.x - p.p.x;
  p2.p.y = pp2->p.y - p.p.y;
}


XFont :: XFont( XGraphicDevice * dev, char * fontName, SHORT size)
{
  dev->fontId+=1;
  fontId = dev->fontId;
  fontSize = size;
  FATTRS fat;
  memset(&fat, 0, sizeof(fat));
  fat.usRecordLength = sizeof(fat);
  strcpy(fat.szFacename, fontName);
  fat.usCodePage = 850;
  fat.lMaxBaselineExt = size;
  fat.lAveCharWidth = size;
  fat.fsFontUse = FATTR_FONTUSE_NOMIX;

  GpiCreateLogFont( dev->hps, NULL, fontId, &fat);
}


XText :: ~XText( )
{
   free( text );
}


XText :: XText( XGraphicDevice * d, XFont * f, XRect * rect, char * s, SHORT sty):XGraphicObject( d, rect->x, rect->y)
{
   font = f;
   style = sty;
   text = (char*) malloc( strlen(s) + 1);
   strcpy( text, s);
   p2.p.x = rect->cx + p.p.x;
   p2.p.y = rect->cy + p.p.y;
}


void XText :: Draw( XRect * r)
{
   RECTL rc;

   rc.yBottom = p.p.y + dev->yOffset;
   rc.yTop = p2.p.y + dev->yOffset;
   rc.xLeft = p.p.x + dev->xOffset;
   rc.xRight = p2.p.x + dev->xOffset;

   if( dev->aktFont != font->fontId)
      dev->SetFont( font );

   WinDrawText( dev->hps, -1, (PSZ) text, &rc, color.GetColor(), CLR_BLACK, style);
}

/*
void XText :: SetWight( LONG w)
{
   p2.p.x = p.p.x + w;
}


void XText :: SetHight( LONG h)
{
   p2.p.y = p.p.y + h;
}
*/

void XText :: SetText( char * t, LONG textLen )
{
   LONG l;
   if( textLen > -1)
      l = textLen;
   else
      l = strlen( t );
   text = (char*) realloc(text, l + 1);
   memcpy( text, t, l);
   text[l] = 0;
}



XBox :: XBox ( XGraphicDevice * d, XPoint * pp1, XPoint * pp2, BOOL f):XLine( d, pp1, pp2)
{
   settings = 0;
   fill = f;
}


void XBox :: Draw( XRect * r)
{
  if(!(settings & GO_HIDE))
    {
       XLine :: SetupDevice( );
       POINTL ptl[5];
       ptl[0] = ptl[4] = p.p;
       ptl[1].x = p.p.x;
       ptl[1].y = ptl[2].y = p2.p.y + p.p.y;
       ptl[3].x = ptl[2].x = p2.p.x + p.p.x;
       ptl[3].y = p.p.y;
       GpiBeginPath( dev->hps, 1);
       GpiMove( dev->hps, &p.p);
       GpiPolyLine( dev->hps, 5, ptl);
       GpiEndPath( dev->hps);
       if( fill )
         GpiFillPath( dev->hps, 1, FPATH_ALTERNATE);
       else
         GpiStrokePath( dev->hps, 1, 0);
    }
}

char * pszdata[8] = {"Display", NULL, NULL, NULL, NULL, NULL, NULL};
SIZEL g = {0,0};


XBitmap :: XBitmap( XGraphicDevice * d, XPoint * pp1):XGraphicObject( d, pp1)
{
   owner = NULL;
   data = NULL;
   hdc = DevOpenDC( dev->hab, OD_MEMORY, (PSZ) "*", 4, (PDEVOPENDATA) pszdata, 0L);
   hps = GpiCreatePS( dev->hab, hdc, &g, PU_PELS | GPIA_ASSOC|GPIT_MICRO);
   XColor x(COL_PALEGRAY);

   LONG l;
   GpiCreateLogColorTable( hps, LCOL_RESET, LCOLF_RGB, 0, 1, &l);

   GpiSetBackColor( hps, 0);
   GpiSetBackMix( hps, BM_SRCTRANSPARENT );
}


XBitmap :: XBitmap(XUserButton * bt)
{
   data = NULL;
   hbm = hps = 0;
   owner = bt;
//   hdc = DevOpenDC( WinQueryAnchorBlock(bt->winhandle), OD_MEMORY, (PSZ) "*", 4, (PDEVOPENDATA) pszdata, 0L);
//   hps = GpiCreatePS( WinQueryAnchorBlock(bt->winhandle), hdc, &g, PU_PELS | GPIA_ASSOC|GPIT_MICRO);
   bt->bmp = this;
}


void XBitmap :: Draw( XRect * r)
{
    POINTL aptl[4];
    aptl[0].x = p.GetX() - dev->xOffset;
    aptl[0].y = p.GetY() - dev->yOffset;
    aptl[1].x = dev->wight;
    aptl[1].y = dev->hight;
    aptl[2].x = aptl[2].y = 0;
    LONG m = 3;

    GpiBitBlt( dev->hps, hps, m, aptl, ROP_SRCCOPY, BBO_IGNORE );
}


XBitmap :: ~XBitmap()
{
   GpiDestroyPS( hps );
   DevCloseDC( hdc );
   GpiDeleteBitmap( hbm );
   if(data)
     free( data );
}


LONG XBitmap :: SetBitmap( HBITMAP hbm )
{
   HBITMAP old;
   if( (old = GpiSetBitmap( hps, hbm)) == HBM_ERROR)
      return -4;
   else
      {
         GpiDeleteBitmap( hbm );
         return 0;
      }
}


void XBitmap :: QueryDimensions( LONG& x, LONG& y)
{
   BITMAPINFOHEADER phd;
   GpiQueryBitmapParameters( hbm, &phd);
   x = phd.cx;
   y = phd.cy;
}


LONG XBitmap :: LoadBitmap( XResource * r)
{
   hbm = GpiLoadBitmap( hps, r->library->moduleHandle, r->id, 0, 0);
   if( SetBitmap( hbm ) != 0)
      return -4;
   return 0;
}


LONG XBitmap :: LoadBitmap( char * f)
{
   PBITMAPFILEHEADER p;
   XFile file;
   if( file.Open( f, 0, XFILE_FAIL_IF_NEW | XFILE_OPEN_EXISTING, XFILE_SHARE_DENYNONE | XFILE_READONLY ) == 0)
     {
         file.Seek( 0, XFILE_END);
         LONG size = file.QueryPointerPos()+1;
         file.Seek( 0, XFILE_BEGIN);
         p = (PBITMAPFILEHEADER) malloc(size);
         file.Read(p, size-1);
         file.Close();
     }
   else
      return -1;

   if(owner )
      {
         hps = WinGetPS(owner->GetHandle());
         hbm = GpiCreateBitmap( hps, (PBITMAPINFOHEADER2) &p->bmp, CBM_INIT,(PBYTE) p + p->offBits, (PBITMAPINFO2) &p->bmp);
         cx = p->bmp.cx;
         cy = p->bmp.cy;
      }
   else
      SetData( (BITMAPINFOHEADER2*) &p->bmp, p->offBits);

   free( p );

   if(hbm == GPI_ERROR)
      return -3;

   return 0;
}


LONG XBitmap :: SetData( BITMAPINFOHEADER2 * p, LONG offset)
{
   if(data)
      free(data );

   LONG size = ((( p->cBitCount * p->cx) + 31) / 32) * 4 * p->cPlanes * p->cy;

   data = (PBITMAPINFOHEADER2) malloc( size );
   memcpy( data, p, size);
   if(data->cbFix == sizeof(BITMAPINFOHEADER))
      cScans = (ULONG) ((PBITMAPINFOHEADER)data)->cy;
   else
      cScans = data->cy;

   if(hbm != 0) GpiDeleteBitmap(hbm);
   hbm = GpiCreateBitmap( hps, data, 0, NULL, NULL);

   if(hbm == GPI_ERROR)
      return -3;

   if( SetBitmap( hbm) != 0)
      return -4;

   if(GpiSetBitmapBits( hps, 0L, cScans, (PBYTE)p + offset, (PBITMAPINFO2) data) != cScans)
      return -5;
   free(data);
   data = NULL;

   return 0;
}


void XBitmapShadow :: Draw( XRect * r)
{
    POINTL aptl[4];
    aptl[0].x = p.GetX() - dev->xOffset;
    aptl[0].y = p.GetY() - dev->yOffset;
    aptl[1].x = dev->wight;
    aptl[1].y = dev->hight;
    aptl[2].x = aptl[2].y = 0;
    LONG m = 3;

    GpiBitBlt( dev->hps, bmp->hps, m, aptl, ROP_SRCCOPY, BBO_IGNORE );
}


XBitmapShadow :: XBitmapShadow( XBitmap * b, XPoint * p):XGraphicObject(b->dev, p)
{
   bmp = b;
}


BOOL XBitmap :: HitTest( LONG x, LONG y)
{
   LONG x1, y1;
   QueryDimensions(x1, y1);
   if( x > p.GetX() && x < p.GetX() + x1 && y > p.GetY() && y < p.GetY() + y1)
     return TRUE;
  else
     return FALSE;
}


BOOL XBitmapShadow :: HitTest( LONG x, LONG y)
{
   LONG x1, y1;
   bmp->QueryDimensions(x1,y1);
   if( x > p.GetX() && x < p.GetX() + x1 && y > p.GetY() && y < p.GetY() + y1)
     return TRUE;
  else
     return FALSE;
}
