/*
 *  FakeX, stubs for X11 calls, written in MetaGraphics
 *  (with annotations so you can translate them into whatever
 *   graphics package you like)
 *
 *   mid Nov '94  now translated to Windows
 */

#include "fakex.h"
#include "trippy.h"
/* #include <metawndo.h> */
#include <stdio.h>

extern int CX;
extern int CY;
extern char* progname;
extern POINT* Bezier(POINT*,int);
const short MaxX();
const short MaxY();
#ifdef WINDOWS
extern HWND FAR* window; /* eventually, this may become an array of HWNDs */
extern HPALETTE hPal;
#endif
extern foo options;

#ifdef WINDOWS
void
XDrawPoint(int display, int win,int color, int x, int y)
{
  HDC hdc;
  hdc = GetDC(win);
  SelectPalette(hdc,hPal,FALSE);
  SetPixel(hdc,x,y,RGB(0,0,0));
  SetPixel(hdc,x,y,PALETTEINDEX(color));
  ReleaseDC(win,hdc);
}
#endif

void
XDrawLine(int display,int win,int color,int x1 ,int y1 ,int x2 ,int y2)
{
/* sets the current color to 'color', moves to the first point, and
   draws a line to the second point */
#ifdef WINDOWS
  HDC hdc;
  HPEN hpen, hpenold;
  hdc= GetDC(win);
  SelectPalette(hdc,hPal,FALSE);
  hpen = CreatePen(PS_SOLID, 1, PALETTEINDEX(color));
  hpenold = SelectObject(hdc, hpen);

  MoveTo(hdc,x1,y1);
  LineTo(hdc,x2,y2);

  SelectObject(hdc, hpenold);
  DeleteObject(hpen);
  ReleaseDC(win,hdc);
#else
  PenColor(color); 
  MoveTo(x1,y1);
  LineTo(x2,y2);
#endif
/*  GrLine(x1,y1,x2,y2,color); */
}

void
XDrawLines(int display,int win,int color, XPoint *points,
           int npoints, int foo)
{
/* Set the Pen color to 'color', then draw a polyline connecting
   'points' */
#ifdef WINDOWS
  HDC hdc;
  HPEN hpen, hpenold;
  hdc= GetDC(win);
  SelectPalette(hdc,hPal,FALSE);
  hpen = CreatePen(PS_SOLID, 1, PALETTEINDEX(color));
  hpenold = SelectObject(hdc, hpen);

  Polyline(hdc,(POINT*)points,npoints);

  SelectObject(hdc, hpenold);
  DeleteObject(hpen);
  ReleaseDC(win,hdc);
#else
  int i;
  PenColor(color);
  PolyLine(npoints,(point *)points);

/* or, if you don't have a PolyLine, draw lines from point[x] to point[x+1] */
/*  for(i=0;i<npoints-1;i++) */
/*    GrLine(points[i].x,points[i].y,points[i+1].x,points[i+1].y,color); */
#endif
}

void
XDrawBez(int display,int win,int color, XPoint *points,
           int npoints, int foo)
{
#ifdef WINDOWS
  XDrawLines(display, win, color, (XPoint*)Bezier(points,npoints), 21, foo);
#else
  PenColor(color);
  PolyBezier((point *)points,npoints);
#endif
}

void
XDrawRectangle(int display, int win, int color, int x1, int y1,
               int width, int height)
{
/* Set Pen color to 'color', sets 'r' to the corners of the rectangle,
   and draws the rectangle */
#ifdef WINDOWS
  HDC hdc;
  HPEN hpen, hpenold;
  hdc= GetDC(win);
  SelectPalette(hdc,hPal,FALSE);
  hpen = CreatePen(PS_SOLID, 1, PALETTEINDEX(color));
  hpenold = SelectObject(hdc, hpen);

  MoveTo(hdc,x1,y1);
  LineTo(hdc,x1+width,y1);
  LineTo(hdc,x1+width,y1+height);
  LineTo(hdc,x1,y1+height);
  LineTo(hdc,x1,y1);
/*  Rectangle(hdc, x1, y1, x1+width, y1+height); */
  SelectObject(hdc, hpenold);
  DeleteObject(hpen);
  ReleaseDC(win,hdc);
#else
  rect r;
  SetRect(&r,x1,y1,x1+width,y1+height);
  PenColor(color);
  FrameRect(&r);
/*  GrBox(x1,y1,x1+width,y1+height,color); */
#endif
}

void
XFillRectangle(int display, int win, int color, int x1, int y1,
               int width, int height)
{
/* Set Pen color to 'color', sets 'r' to the corners of the rectangle,
   and fills in the rectangle */
#ifdef WINDOWS
  HDC hdc;
  RECT r;
  HBRUSH hbrush,hbrushold;
  HPEN hpen,hpenold;
  hdc= GetDC(win);
  SelectPalette(hdc,hPal,FALSE);

  if(width>0)
  {
    r.left = x1;
    r.right = x1+width;
  }
  else
  {
    r.left = x1+width;
    r.right = x1;
  }

  if(height>0)
  {
    r.top = y1;
    r.bottom = y1+height;
  }
  else
  {
    r.top = y1+height;
    r.bottom = y1;
  }
  hbrush = CreateSolidBrush(PALETTEINDEX(color));
  hbrushold = SelectObject(hdc, hbrush);
  hpen = CreatePen(PS_SOLID, 1, PALETTEINDEX(color));
  hpenold = SelectObject(hdc, hpen);
  Rectangle(hdc,r.left, r.top, r.right, r.bottom);
  SelectObject(hdc,hbrushold);
  SelectObject(hdc,hpenold);
  DeleteObject(hpen);
  DeleteObject(hbrush);
  ReleaseDC(win,hdc);
#else
  rect r;
  SetRect(&r,x1,y1,x1+width,y1+height);
  PenColor(color);
  FillRect(&r,1);
/*  GrFilledBox(x1,y1,x1+width,y1+height,color); */
#endif
}

void
XFillPolygon(int display, int win, int color, XPoint *pts,
             int nPts, int con, int mode)
{
/* sets the pen color to 'color', and Fills in the Polygon defined by
   'pts'. 'con' is the Convexity (I think they're all Convex), and 'mode'
   is the Coordinate mode, (In X, they're all CoordModeOrigin) 
 */
#ifdef WINDOWS
  HBRUSH hbrush,hbrushold;
  HPEN hpen,hpenold;
  HDC hdc;
  hdc= GetDC(win);
  SelectPalette(hdc,hPal,FALSE);
  hbrush = CreateSolidBrush(PALETTEINDEX(color));
  hbrushold = SelectObject(hdc,hbrush);
  hpen = CreatePen(PS_SOLID, 1, PALETTEINDEX(color));
  hpenold = SelectObject(hdc, hpen);
  SetPolyFillMode(hdc, WINDING);

  Polygon(hdc,(POINT*)pts,nPts);
  SelectObject(hdc,hbrushold);
  DeleteObject(hbrush);
  SelectObject(hdc,hpenold);
  DeleteObject(hpen);
  ReleaseDC(win,hdc);
#else
  PenColor(color);
  FillPolygon((point *)pts, nPts,mode, con);
#endif
}

int
WhitePixel()
{
#ifdef WINDOWS
  return RGB(255,255,255);
#else
  return -1;
#endif
/*  return GrWhite(); */
}

int
BlackPixel()
{
#ifdef WINDOWS
  return RGB(0,0,0);
#else
  return 0;
#endif
/*  return GrBlack(); */
}

int
XStoreColor(int display, int colmap, XColor *color)
{
  /* color->pixel is the index to the color table, color->[red,blue,green]
     are obvious... sets color->pixel to the RGB values in 'color' */
 #ifdef WINDOWS
  PALETTEENTRY palData;
  palData.peRed = color->red;
  palData.peGreen = color->green;
  palData.peBlue = color->blue;
  palData.peFlags = PC_RESERVED;
  AnimatePalette(hPal,color->pixel,1,(PALETTEENTRY FAR*)&palData);
 #else
  palData RGB[1];
  RGB[0].palRed=color->red;
  RGB[0].palGreen=color->green;
  RGB[0].palBlue=color->blue;
  WritePalette(0,color->pixel,color->pixel, RGB);
/*  GrSetColor(color->pixel,color->red,color->green,color->blue); */
  /*
    fprintf(stderr,"%d: (%d,%d,%d)\n",color->pixel,color->red,
    color->green,color->blue);
    */
 #endif
  return True;
}

int
XStoreColors(int display, int colmap, XColor *color,int numColors)
{
  /* color->pixel is the index to the color table, color->[red,blue,green]
     are obvious... sets color->pixel to the RGB values in 'color' */
#ifdef WINDOWS
  AnimatePalette(hPal,color[0].pixel,numColors,(PALETTEENTRY*)color);
#else
  WritePalette(0,color[0].pixel,numColors,(palData*)color);
/*  GrSetColor(color->pixel,color->red,color->green,color->blue); */
  /*
    fprintf(stderr,"%d: (%d,%d,%d)\n",color->pixel,color->red,
    color->green,color->blue);
    */
#endif
  return True;
}

void
XMapWindow(HWND win, int display)
{
#ifdef WINDOWS
  ShowWindow(win,SW_SHOWNORMAL);
#endif
  return;
}

#ifdef WINDOWS
HWND
#else
int
#endif
MakeWindow(int o_argc,char **o_argv, HINSTANCE hInst)
{
/* Does the Window setup thing... under DOS, this just sets CX and CY to be
   the maxX and maxY values.. Under X, this calls XCreateSimpleWindow, and
   XMapWindow , et al. */
#ifdef WINDOWS
  HWND temp;
  RECT rc;
  temp= CreateWindow("WinTacy","Wheeee",
                                  WS_OVERLAPPEDWINDOW|CS_BYTEALIGNWINDOW,
                                  0,0,200,200,
                                  NULL,NULL,hInst,NULL);
  ShowWindow(temp,1);
  UpdateWindow(temp);
  return temp;
#else
  CX=MaxX();
  CY=MaxY();
  return 1;
#endif
}

const short MaxX(int win)
{
#ifdef WINDOWS
  RECT rc;
  GetClientRect(win,&rc);
  return rc.right;
#else
/* Meta doesn't have a function to return the MaxX and MaxY, so I wrote 'em..
   it grabs the info from the Bitmap. */

  grafPort *screenPort;
  GetPort(&screenPort);
  return screenPort->portMap->pixWidth;
#endif
}

const short MaxY(int win)
{
#ifdef WINDOWS
  RECT rc;
  GetClientRect(win,&rc);
  return rc.bottom;

#else
  grafPort *screenPort;
  GetPort(&screenPort);
  return screenPort->portMap->pixHeight;
#endif
}

void XClearWindow(int disp, int win)
{
#ifdef WINDOWS
  RECT rc;
  HDC hdc;
  HBRUSH hbr,hbrold;
  hdc=GetDC(win);
  GetClientRect(win,&rc);
  hbr = CreateSolidBrush(PALETTEINDEX(0));
  hbrold = SelectObject(hdc,hbr);
  FillRect(hdc,&rc,hbr);
  SelectObject(hdc,hbrold);
  DeleteObject(hbr);
  ReleaseDC(win,hdc);
#else
/* Meta also doesn't have a ClearScreen function, so this erases the whole
   screen */
  grafPort *screenPort;
  GetPort(&screenPort);
  EraseRect( &screenPort->portRect);
#endif
}

int
DisplayCells(int foo, int bar)
{
#ifdef WINDOWS
  HDC hdc = GetDC(window[0]);
  int dc = GetDeviceCaps(hdc,COLORRES) ;
  ReleaseDC(window[0],hdc);
  return dc;
#else
  return log(QueryColors()+1)/log(2);
#endif
}

int
XAllocColorCells(int disp,int cm,int bool,int *foob,int huh,
                 unsigned long *pixels,int num)
{
#ifdef WINDOWS
  HDC hdc = GetDC(window[0]);
  int nc = GetDeviceCaps(hdc,SIZEPALETTE)-GetDeviceCaps(hdc,NUMRESERVED);
  ReleaseDC(window[0],hdc);
#else
  int nc=QueryColors()+1;
#endif
  if(nc<num)
  {
    return 0;
    fprintf(stderr,"Can't alloc %d\n",num);
  }
  else
  {
    int a;
    for(a=0;a<num;a++)
    {
      pixels[a]=a;  //      GrAllocCell();
    }
    return 1;
  }
}

void
XFreeColors()
{
  if(options.tryfor>0)
    DeleteObject(hPal);
}
