#include <exec/types.h>
#include <exec/lists.h>
#include <exec/libraries.h>
#include <utility/tagitem.h>
#include <dos/dos.h>
#include <graphics/displayinfo.h>
#include <intuition/screens.h>
#include <vilintuisup/vilintuisup_protos.h>
#include <vilintuisup/screenmode.h>
#include <vilintuisup.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>

#include <string.h>

/*
 *  TagItems to open a double buffer screen
 */

struct TagItem openscreentags[] = {
    {  TAVIS_SCREEN_MODEID, 0 },
    {  TAVIS_DOUBLE_BUFFER, TRUE },
    {  TAVIS_OPEN_BEHIND, FALSE },
    {  TAG_DONE, 0 }
};

/*
 *  TagItems for the VillageModeRequest call
 */

struct TagItem requesttags[] = {
    {  TAVIS_MINDEPTH, 8 },
    {  TAVIS_MAXDEPTH, 8 },
    {  TAVIS_MAXHEIGHT, 900 },
    {  TAG_DONE, 0 }
};

/*
 *  Library bases we need ...
 */

struct Library *VilIntuiBase;
struct IntuitionBase *IntuitionBase;

/*
 *  Fill a region in all color modes
 */

void FillVillageRegion(struct Screen *s, int xpos,  int ypos,
					 int width, int height, ULONG color)
{
   int screendepth;                /* how much bits per pixel ?         */
   int bpP;                        /* Bytes per Pixel                   */
   UBYTE *memstart;                /* where the screen starts in memory */
   struct VilFillRecord vilfill;   /* always needed by this function    */

   memstart    = LockVillageScreen(s);

   screendepth = VillageScreenData(s,TAVIS_SD_SCREEN_DEPTH);
   bpP         = (screendepth + 7) >> 3;

   /*
    *  fill up the structure
    */

   vilfill.DestAdr   = (APTR)(memstart + (xpos*bpP + (ypos * (s->Width*bpP))));
   vilfill.DestPitch = s->Width;
   vilfill.Width     = width;
   vilfill.Height    = height;
   vilfill.Color     = color;

   /*
    *  fill up the region
    */

   VillageRectFill(s,&vilfill); /* does it's own WaitVillageBlit() inside */

   /*
    * donn't forget this
    */

   UnLockVillageScreen(s);
}


/*
 *  the main program
 */

int main(int argc, char *argv[])
{
   struct Screen *s = 0;
   UBYTE *boardmem;
   UBYTE *firstbuffer, *secondbuffer;
   int switchcounter = 10;

   /*
    * first open all required libraries, notice the 2 behind "vilintuisup.l..."
    * VillageModeRequest was not available in version 1.x !!!
    */

   if (VilIntuiBase = OpenLibrary("vilintuisup.library",2))
   {  if (IntuitionBase = (struct IntuitionBase *)
			  OpenLibrary("intuition.library",37))
      {
	 /*
	  * let the user choose the display mode
	  * remember: every time check against INVALID_ID, not NULL!!
	  */

	 if ((openscreentags[0].ti_Data = VillageModeRequest(requesttags))
	     != INVALID_ID)
	 {
	    /*
	     * The user clicked on "O.K."
	     */

	    if (s = OpenVillageScreenTagList(openscreentags))
	    {
	       /*
		* OK, the screen is open, let's have a look at the height
		* The height is doubled!
		*/

	       Printf("Screen Height %4ld, Width %4ld\n",s->Height, s->Width);

	       /*
		* Before doing anything lock the screen first
		*/

	       boardmem = LockVillageScreen(s);

	       /*
		* Too set colors in 8Bit modes use SetRGB4 as usual
		*/

	       SetRGB4(&(s->ViewPort),0,0,0,0);       /* color 0 = black     */
	       SetRGB4(&(s->ViewPort),1,100,100,100); /* color 1 = dark gray */
	       SetRGB4(&(s->ViewPort),2,255,  0,  0); /* color 2 = red       */
	       SetRGB4(&(s->ViewPort),3,  0,255,  0); /* color 3 = green     */
	       SetRGB4(&(s->ViewPort),4,  0,  0,255); /* color 4 = blue      */

	       /*
		* Now get the pointer to the two buffer
		*/

	       firstbuffer  = VillageGetBufAddr(s,0);
	       secondbuffer = VillageGetBufAddr(s,1);

	       /*
		* fill the buffer with "color"
		* this is the slow method, using VillageRectFill is better
		*/

	       memset(firstbuffer, '\x00',s->Height/2*s->Width);
	       memset(secondbuffer,'\x01',s->Height/2*s->Width);

	       /*
		* now switch some times
		*/

	       do
	       {
		  /*
		   * fills a region with a color out of (red, green, blue)
		   */

		  FillVillageRegion(s,100,100+s->Height/2,s->Width-200,
				      (s->Height/2)-200,(switchcounter % 3)+2);
		  /*
		   * this slows down significantly, but has to be called
		   */

		  WaitVillageBlit();

		  /*
		   * switch to the second buffer
		   */

		  VillageSetDisplayBuf(s,1);

		  /*
		   * fills a region with a color out of (red, green, blue)
		   */

		  FillVillageRegion(s,100,100,s->Width-200,(s->Height/2)-200,
				      4-(switchcounter % 3));
		  /*
		   * this slows down significantly, but has to be called
		   */

		  WaitVillageBlit();

		  /*
		   * switch to the first buffer
		   */
		  VillageSetDisplayBuf(s,0);

	       } while (--switchcounter);

	       /*
		* there might be some more useful thing to do left
		*/

	       /*
		* don't forget to UnLock the screen
		*/

	       UnLockVillageScreen(s);

	       /*
		* only close with CloseVillageScreen(), never use CloseScreen()!!
		*/

	       CloseVillageScreen(s);

	    }  /* if (OpenVIllageScreenTagList(openscreentags)) */

	 }  /* the User clicked on "O.K." */

	 CloseLibrary((struct Library *)IntuitionBase);
      }
      CloseLibrary(VilIntuiBase);
   }

   /*
    * if the screen was not open (s == 0) return RETURN_FAIL
    */

   return s ? RETURN_OK : RETURN_FAIL;
}

