/*------------------------------------------------*
  $Id: crawl.c,v 1.4 92/11/03 17:14:49 tf Exp $
  Crawling frames and some other EOR tricks
  written by Tobias Ferber, 1992
 *------------------------------------------------*/

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>

static char rcs_id[] = "$Id: crawl.c,v 1.4 92/11/03 17:14:49 tf Exp $";

extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;
static struct RastPort CrawlPort;

static UWORD fptrn= 0xF0F0;        /* $F0F0 == %1111000011110000 */

static UWORD gptrn[]= { 0x8888,    /* $8888 == %1000100010001000 */
                        0x2222,    /* $2222 == %0010001000100010 */
                        0xAAAA,    /* $AAAA == %1010101010101010 */
                        0x5555,    /* $5555 == %0101010101010101 */
                        0xCCCC,    /* $CCCC == %1100110011001100 */
                        0x3333     /* $3333 == %0011001100110011 */
                      };

static struct frame { USHORT x1,y1;
                      USHORT x2,y2;
                    } fbox;

#define erase_frame() draw_frame() /* draw mode complement => EOR frame away */

void draw_frame()
{ Move(&CrawlPort, fbox.x1,fbox.y1);  Draw(&CrawlPort, fbox.x2,fbox.y1);
  Move(&CrawlPort, fbox.x2,fbox.y1);  Draw(&CrawlPort, fbox.x2,fbox.y2);
  Move(&CrawlPort, fbox.x2,fbox.y2);  Draw(&CrawlPort, fbox.x1,fbox.y2);
  Move(&CrawlPort, fbox.x1,fbox.y2);  Draw(&CrawlPort, fbox.x1,fbox.y1);
}

void crawl_frame(int dir)
{ UWORD temp= fptrn;
  if(dir)
    fptrn= ((fptrn << 1) & 0xFFFE) | ((fptrn & 0x8000) >> 15);
  else
    fptrn= ((fptrn >> 1) & 0x7FFF) | ((fptrn & 0x001L) << 15);

  temp ^= fptrn;
  SetDrPt(&CrawlPort, temp);
  WaitTOF();
  draw_frame();
  SetDrPt(&CrawlPort, fptrn);
}

void init_frame(rp, x1,y1, x2,y2)
struct RastPort *rp;
USHORT x1,y1, x2,y2;
{ CopyMem(rp, &CrawlPort, sizeof(struct RastPort)); /* make a copy ! */
  SetAPen(&CrawlPort, 1L);
  SetDrMd(&CrawlPort, COMPLEMENT);
  SetDrPt(&CrawlPort, fptrn);
  fbox.x1= x1;  fbox.y1= y1;
  fbox.x2= x2;  fbox.y2= y2;
  draw_frame();
}

void resize_frame(x1,y1, x2,y2)
USHORT x1,y1, x2,y2;
{ WaitTOF();
  erase_frame();  /* EOR frame away */
  fbox.x1= x1; fbox.y1= y1;
  fbox.x2= x2; fbox.y2= y2;
  WaitTOF();
  draw_frame();   /* draw new frame */
}

void grid_frame(frame,pen)
struct frame *frame;
UBYTE pen;
{ USHORT x1,y1, x2,y2;

  /*
   * RectFill() expects the following relations to be true:
   *
   *               (x1 <= x2) and (y1 <= y2)
   */

  if(frame->x1 <= frame->x2) { x1= frame->x1; x2= frame->x2; }
  else { x1= frame->x2; x2= frame->x1; }
  if(frame->y1 <= frame->y2) { y1= frame->y1; y2= frame->y2; }
  else { y1= frame->y2; y2= frame->y1; }

  SetAPen(&CrawlPort,pen);
  SetAfPt(&CrawlPort,&gptrn[0],1L);
  RectFill(&CrawlPort,x1,y1,x2,y2);
}
