/*************************************************************
 *  Do square area fills without using Blitter
 *   by Tom Krotchko for Jumpdisk
 *   - box and line algorithms from the book
 *      Advanced TURBO C by Herbert Schildt
 *      Borland-Osborne/McGraw-Hill
 ************************************************************/

#include <exec/types.h>
#include <intuition/intuition.h>
#include <dos.h>

void fill_box(), line();

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase; 
struct IntuiMessage *message;

#define INTUITION_REV 0
#define GRAPHICS_REV  0

struct Screen *Screen;
struct Window *Window;

static struct NewScreen NewScreenStructure = {
	0,0,	/* screen XY origin relative to View */
	320,200,	/* screen width and height */
	5,	/* screen depth (number of bitplanes) */
	0,1,	/* detail and block pens */
	NULL,	/* display modes for this screen */
	CUSTOMSCREEN,	/* screen type */
	NULL,	/* pointer to default screen font */
	"Area Fill Without Blitter",	/* screen title */
	NULL,	/* first in list of custom screen gadgets */
	NULL	/* pointer to custom BitMap structure */
};

#define NEWSCREENSTRUCTURE NewScreenStructure

static struct NewWindow NewWindowStructure1 = {
	0,11,	/* window XY origin relative to TopLeft of screen */
	320,189,	/* window width and height */
	0,1,	/* detail and block pens */
	CLOSEWINDOW,	/* IDCMP flags */
	WINDOWCLOSE+SIMPLE_REFRESH+ACTIVATE+NOCAREREFRESH, /* other window flags */
	NULL,	/* first gadget in gadget list */
	NULL,	/* custom CHECKMARK imagery */
	NULL,	/* window title */
	NULL,	/* custom screen pointer */
	NULL,	/* custom bitmap */
	5,5,	/* minimum width and height */
	-1,-1,	/* maximum width and height */
	CUSTOMSCREEN	/* destination screen type */
};

void main()
{
int startx=160,starty=106,endx=161,endy=107,color_code=0;

IntuitionBase=(struct IntuitionBase *) 
  OpenLibrary("intuition.library",INTUITION_REV);


GfxBase=(struct GfxBase *)
  OpenLibrary("graphics.library",GRAPHICS_REV);

if ((Screen=(struct Screen *)OpenScreen(&NEWSCREENSTRUCTURE))==NULL)
   {
   printf("Bad OpenScreen. \n");
   exit(FALSE);
   }

NewWindowStructure1.Screen = Screen;

if ((Window=(struct Window *) OpenWindow(&NewWindowStructure1)) == NULL)
    {
    printf("Bad OpenWindow. Closing Screen. \n");
    CloseScreen(Screen);
    exit(FALSE);
    }

 for (;;)
 {
     /* for-ever loop to do processing */
     /* don't waste cycles if nothing's happening */
  
     while(message = (struct IntuiMessage *)GetMsg(Window->UserPort))  
     {
          /* Always check for closewindow event! */
          if (message->Class == CLOSEWINDOW)
          {
             CloseWindow(Window);
             CloseScreen(Screen);
             CloseLibrary(GfxBase);
             CloseLibrary(IntuitionBase);
             exit(TRUE);
          } /* end if */
          ReplyMsg(message);

     } /* end while */

     color_code++;
     color_code++;        
     if(color_code>255) color_code=0;
     SetAPen(Window->RPort,color_code);
     startx--;
     starty--;
     endx++;
     endy++;
     if(startx<2)  startx=160;
     if(starty<12) starty=106;
     if(endx>319)  endx  =161;
     if(endy>199)  endy  =107;

     if(startx>endx) endx=startx+1;
     if(starty>endy) endy=starty+1;

     SetAPen(Window->RPort,color_code);
     fill_box(startx,starty,endx,endy);
 } /* end for */
}  /* End of main procedure */

void fill_box(startx, starty, endx, endy)
int startx, starty, endx, endy;
{
  register int i, begin, end;
  begin = startx<endx ? startx : endx;
  end = startx>endx ? startx : endx;

  for(i=begin; i<=end;i++)
     line(i,starty,i,endy);
} /* fill_box */

/* Fast, non-blitter line drawing using Bresenham's integer based algorithms */
void line(startx, starty, endx, endy)
int startx, starty, endx, endy;
{
  register int t, distance;
  int xerr=0, yerr=0, delta_x, delta_y;
  int incx, incy;
  
  delta_x=endx-startx;
  delta_y=endy-starty;

  if(delta_x>0) incx=1;
  else if(delta_x == 0) incx=0;
       else incx=-1;

  if(delta_y>0) incy=1;
  else if(delta_y == 0) incy=0;
       else incy=-1;

  delta_x=abs(delta_x);
  delta_y=abs(delta_y);

  if(delta_x>delta_y) distance=delta_x;
  else distance=delta_y;

  for(t=0;t<=distance+1;t++) {
     WritePixel(Window->RPort,startx,starty);

     xerr+=delta_x;
     yerr+=delta_y;

     if(xerr>distance) {
       xerr-=distance;
       startx+=incx;
     }

     if(yerr>distance) {
       yerr-=distance;
       starty+=incy;
     }

  } /* for */
} /* fill_box */
