#include "xmris.h"

/************************************************************************/
/*									*/
/* Emulate XCopyArea()							*/
/*									*/
/************************************************************************/

void MyXCopyArea(void *Src, void *Dst, UBYTE Minterm,
		 WORD SrcX, WORD SrcY,
		 WORD Width, WORD Height,
		 WORD DstX, WORD DstY)

{
  int Window;
  WORD SrcWidth, SrcHeight;
  WORD DstWidth, DstHeight;

  Window=FALSE;

  /* determine source type & size */
  if ((struct GS_Sprite *)Src>=&(Sprites->Sprites[0]) &&
      (struct GS_Sprite *)Src<&(Sprites->Sprites[Sprites->SpriteCount]))
    {
      int SrcSprite;

      SrcSprite=((char *)Src)-(char *)&Sprites->Sprites[0];
      SrcSprite=SrcSprite/sizeof(Sprites->Sprites[0]);
      Src=*(struct BitMap **)Src;
      assert(Src==Sprites->Sprites[SrcSprite].Image || Src==Sprites->Sprites[SrcSprite].Mask);
      SrcWidth=Sprites->Sprites[SrcSprite].Width;
      SrcHeight=Sprites->Sprites[SrcSprite].Height;
    }
  else
    {
      if (((Pixmap *)Src)->Layer==NULL)
	{
	  Src=((Pixmap *)Src)->BitMap;
	  SrcWidth=DIGIT_WIDTH*4;
	  SrcHeight=DIGIT_HEIGHT;
	}
      else
	{
	  assert(WINDOW_WIDTH==((Pixmap *)Src)->Layer->bounds.MaxX-((Pixmap *)Src)->Layer->bounds.MinX+1);
	  assert(WINDOW_HEIGHT==((Pixmap *)Src)->Layer->bounds.MaxY-((Pixmap *)Src)->Layer->bounds.MinY+1);
	  Src=((Pixmap *)Src)->Layer->rp->BitMap;
	  SrcWidth=WINDOW_WIDTH;
	  SrcHeight=WINDOW_HEIGHT;
	}
    }

  /* determine destination type & size */
  if ((struct GS_Sprite *)Dst>=&(Sprites->Sprites[0]) &&
      (struct GS_Sprite *)Dst<&(Sprites->Sprites[Sprites->SpriteCount]))
    {
      int DstSprite;

      DstSprite=((char *)Dst)-(char *)&Sprites->Sprites[0];
      DstSprite=DstSprite/sizeof(Sprites->Sprites[0]);
      Dst=*(struct BitMap **)Dst;
      assert(Dst==Sprites->Sprites[DstSprite].Image || Dst==Sprites->Sprites[DstSprite].Mask);
      DstWidth=Sprites->Sprites[DstSprite].Width;
      DstHeight=Sprites->Sprites[DstSprite].Height;
    }
  else if (Dst==&display.window)
    {
      Dst=display.window->RPort;
      Window=TRUE;
      DstWidth=WINDOW_WIDTH;
      DstHeight=WINDOW_HEIGHT;
    }
  else
    {
      if (((Pixmap *)Dst)->Layer==NULL)
	{
	  Dst=((Pixmap *)Dst)->BitMap;
	  DstWidth=DIGIT_WIDTH*4;
	  DstHeight=DIGIT_HEIGHT;
	}
      else
	{
	  assert(WINDOW_WIDTH==((Pixmap *)Dst)->Layer->bounds.MaxX-((Pixmap *)Dst)->Layer->bounds.MinX+1);
	  assert(WINDOW_HEIGHT==((Pixmap *)Dst)->Layer->bounds.MaxY-((Pixmap *)Dst)->Layer->bounds.MinY+1);
	  Dst=((Pixmap *)Dst)->Layer->rp->BitMap;
	  DstWidth=WINDOW_WIDTH;
	  DstHeight=WINDOW_HEIGHT;
	}
    }

  /* perform clipping */
  {
    if (SrcX<0)
      {
	Width+=SrcX;
	DstX-=SrcX;
	SrcX=0;
      }
    if (DstX<0)
      {
	Width+=DstX;
	SrcX-=DstX;
	DstX=0;
      }
    if (Width>SrcWidth-SrcX)
      {
	Width=SrcWidth-SrcX;
      }
    if (Width>DstWidth-DstX)
      {
	Width=DstWidth-DstX;
      }
    if (SrcX>SrcWidth || DstX>DstWidth)
      {
	Width=0;
      }

    if (SrcY<0)
      {
	Height+=SrcY;
	DstY-=SrcY;
	SrcY=0;
      }
    if (DstY<0)
      {
	Height+=DstY;
	SrcY-=DstY;
	DstY=0;
      }
    if (Height>SrcHeight-SrcY)
      {
	Height=SrcHeight-SrcY;
      }
    if (Height>DstHeight-DstY)
      {
	Height=DstHeight-DstY;
      }
    if (SrcY>SrcHeight || DstY>DstHeight)
      {
	Height=0;
      }
  }

  if (Width>0 && Height>0)
    {
      /* if blitting to window: offset coordinates */
      if (Window)
	{
	  DstX+=display.OriginX;
	  DstY+=display.OriginY;
	}

      if (Window)
	{
	  BltBitMapRastPort(Src,SrcX,SrcY,Dst,DstX,DstY,Width,Height,Minterm);
	}
      else
	{
	  BltBitMap(Src,SrcX,SrcY,Dst,DstX,DstY,Width,Height,Minterm,0xff,NULL);
	}
    }
}

/************************************************************************/
/*									*/
/* Emulate XFillRectangle()						*/
/*									*/
/************************************************************************/

void MyXFillRectangle(void *Dst, UBYTE Minterm, WORD X1, WORD Y1, WORD X2, WORD Y2)

{
  assert(Minterm==GC_CLEAR || Minterm==GC_COPY);

  if (X1>X2)
    {
      WORD t;

      t=X1;
      X1=X2;
      X2=t;
    }
  if (Y1>Y2)
    {
      WORD t;

      t=Y1;
      Y1=Y2;
      Y2=t;
    }

  /* determine destination type & size */
  if ((struct GS_Sprite *)Dst>=&(Sprites->Sprites[0]) &&
      (struct GS_Sprite *)Dst<&(Sprites->Sprites[Sprites->SpriteCount]))
    {
      /* destination is a sprite -> BitMap */
      int DstSprite;
      WORD DstWidth, DstHeight;

      DstSprite=((char *)Dst)-(char *)&Sprites->Sprites[0];
      DstSprite=DstSprite/sizeof(Sprites->Sprites[0]);
      Dst=*(struct BitMap **)Dst;
      assert(Dst==Sprites->Sprites[DstSprite].Image || Dst==Sprites->Sprites[DstSprite].Mask);
      DstWidth=Sprites->Sprites[DstSprite].Width;
      DstHeight=Sprites->Sprites[DstSprite].Height;
      if (X1<0)
	{
	  X1=0;
	}
      else if (X1>=DstWidth)
	{
	  X1=DstWidth-1;
	}
      if (X2<0)
	{
	  X2=0;
	}
      else if (X2>=DstWidth)
	{
	  X2=DstWidth-1;
	}
    DoBitMap:
      if (X1!=X2 && Y1!=Y2)
	{
	  struct RastPort RastPort;

	  InitRastPort(&RastPort);
	  RastPort.BitMap=Dst;
	  if (Minterm==GC_CLEAR)
	    {
	      SetABPenDrMd(&RastPort,display.white,0,JAM1);
	    }
	  else
	    {
	      SetABPenDrMd(&RastPort,(1<<display.DrawInfo->dri_Depth)-1,0,JAM1);
	    }
	  RectFill(&RastPort,X1,Y1,X2,Y2);
	}
    }
  else if (((Pixmap *)Dst)->Layer==NULL)
    {
      Dst=((Pixmap *)Dst)->BitMap;
      goto DoBitMap;
    }
  else if (X1!=X2 && Y1!=Y2)
    {
      struct RastPort *RastPort;

      assert(Dst!=&display.window);
      RastPort=((Pixmap *)Dst)->Layer->rp;
      if (Minterm==GC_CLEAR)
	{
	  SetABPenDrMd(RastPort,display.white,0,JAM1);
	}
      else
	{
	  assert(Minterm==GC_COPY);
	  SetABPenDrMd(RastPort,(1<<display.DrawInfo->dri_Depth)-1,0,JAM1);
	}
      RectFill(RastPort,X1,Y1,X2,Y2);
    }
}

/************************************************************************/
/*									*/
/* Emulate XDrawLine()							*/
/*									*/
/************************************************************************/

void MyXDrawLine(void *Dst, UBYTE Minterm, WORD FromX, WORD FromY, WORD ToX, WORD ToY)

{
  struct RastPort *RastPort;

  if (Dst==&display.window)
    {
      RastPort=display.window->RPort;
      FromX+=display.OriginX;
      FromY+=display.OriginY;
      ToX+=display.OriginX;
      ToY+=display.OriginY;
    }
  else
    {
      assert(((Pixmap *)Dst)->Layer!=NULL);
      RastPort=((Pixmap *)Dst)->Layer->rp;
    }
  if (Minterm==GC_LOAD)
    {
      assert(FromY==ToY);
      BltBitMapRastPort(&display.xorBitmap,0,0,RastPort,FromX,FromY,(WORD)(ToX-FromX+1),1,0x60);
    }
  else
    {
      assert(Minterm==GC_BORDER);
      SetABPenDrMd(RastPort,display.border,display.border,JAM1);
      Move(RastPort,FromX,FromY);
      Draw(RastPort,ToX,ToY);
    }
}

/************************************************************************/
/*									*/
/* Emulate XDrawRectangle()						*/
/*									*/
/************************************************************************/

void MyXDrawRectangle(Pixmap *Dst, UBYTE Minterm, WORD X, WORD Y, WORD Width, WORD Height)

{
  struct RastPort *RastPort;

  assert(Minterm==GC_SET);
  RastPort=Dst->Layer->rp;
  SetABPenDrMd(RastPort,display.black,0,JAM1);
  Move(RastPort,X,Y);
  Draw(RastPort,X+Width-1,Y);
  Draw(RastPort,X+Width-1,Y+Height-1);
  Draw(RastPort,X,Y+Height-1);
  Draw(RastPort,X,Y);
}

/************************************************************************/
/*									*/
/*									*/
/************************************************************************/

void FillBack(unsigned Fill, unsigned Back, WORD X, WORD Y, WORD Width, WORD Height)

{
  const struct BitMap *FillPattern;
  struct RastPort *RastPort;

  RastPort=display.back.Layer->rp;
  if (display.dynamic)
    {
      SetABPenDrMd(RastPort,display.DynamicColor2,display.DynamicColor1,JAM2);
    }
  else
    {
      SetABPenDrMd(RastPort,backgrounds[Back][1],backgrounds[Back][0],JAM2);
    }
  FillPattern=sprites[SPRITE_FILLS+Fill].image;
  while (Height>0)
    {
      WORD SizeY;
      WORD x, width;

      SizeY=(Height>16) ? 16 : Height;
      width=Width;
      x=X;
      while (width>0)
	{
	  WORD SizeX;

	  SizeX=(width>32) ? 32 : width;
	  BltTemplate((PLANEPTR)FillPattern->Planes[0],0,FillPattern->BytesPerRow,RastPort,x,Y,SizeX,SizeY);
	  x+=SizeX;
	  width-=SizeX;
	}
      Height-=SizeY;
      Y+=SizeY;
    }
}
