/* WorkBench256 - ein Programm, das den Hintergrund der Workbench in 256 Farben
   darstellt. Diese Aufgabe übernimmt der COPPER. Tim Pietzcker 18.12.88 

   Dieses Programm muß mit der +l - Option compiliert und gelinkt werden.
   Ich lege zwar großen Wert auf Vermeiden dieser Option, aber ich habe
   mit allen Versuchen, ohne +l auszukommen, nur Gurus erzeugt.             */

#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/gfx.h>
#include <graphics/gfxmacros.h>
#include <graphics/copper.h>
#include <hardware/custom.h>
#include <exec/memory.h>

#define LEFT_OFFSET 30l   /* der sichtbare Bereich des Bildschirms beginnt da */
#define RECT_WIDTH  12l   /* so breit (12*8 Pixel) wird ein Rechteck */

UWORD farben[6][2] = { /* bestimmt, welche Color-Register wie gecycled werden */
  { 1  ,16 },  /* blau,grün */
  { 256,16 },  /* rot ,grün */
  { 256, 1 },  /* rot ,blau */
  { 272, 1 },  /* rot & grün, blau */
  { 256,17 },  /* rot, grün & blau */
  { 257,16 }   /* rot & blau, grün */
};

struct IntuitionBase *IntuitionBase;
struct GfxBase       *GfxBase;
struct Library       *OpenLibrary();
struct ViewPort      *vp,*ViewPortAddress();
void                 *AllocMem();
struct Window        *MyWindow,*OpenWindow();
struct UCopList      *MyCL;
struct IntuiMessage  *msg,*GetMsg();

struct NewWindow TheWindow =
{
   0,0,
   640,20,
   2,1,
   CLOSEWINDOW|MOUSEBUTTONS,
   WINDOWDRAG|WINDOWCLOSE|SMART_REFRESH,
   NULL,NULL,
   (UBYTE *)"WorkBench256 © 18.12.88 by Tim Pietzcker -- click below for more",
   NULL,NULL,
   0,0,0,0,
   WBENCHSCREEN
};

change_CList(colors)    /* erstellt die neue Copperliste */
UWORD colors;           /* bestimmt, welche Farben zum Zug kommen */
{
   UWORD rows,cols,i;
   for(rows=0;rows<16;++rows)
      for(i=rows;i<=rows+16l;++i)
         for(cols=0;cols<16;++cols)
         {
            CWAIT(MyCL,rows*16l+i,LEFT_OFFSET+cols*RECT_WIDTH);
            CMOVE(MyCL,custom.color[0],
                  rows*farben[colors][0] + cols*farben[colors][1]);
         }
   CEND(MyCL);
   WaitTOF();  /* warten, bis Rasterstrahl auf Pos. 0 angelangt ist */
}

main()
{
   UWORD fn=0; int FirstClick;
   void *dspins,*sprins,*clrins;  /* Zeiger in der ViewPort-Struktur */

   GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",NULL);
   IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",NULL);

   MyWindow=OpenWindow(&TheWindow);
   vp=ViewPortAddress(MyWindow);    /* der ViewPort der Workbench */
   msg=GetMsg(MyWindow->UserPort);  /* evtl. Message abfangen */

   do
   { 
      if (msg) ReplyMsg(msg); 
      MyCL=(struct UCopList *)
            AllocMem(sizeof(struct UCopList),MEMF_CHIP|MEMF_CLEAR);
      change_CList(fn);
      dspins=vp->DspIns; sprins=vp->SprIns; clrins=vp->ClrIns;
      Forbid();   /* Multitasking aus */
      vp->DspIns=vp->SprIns=vp->ClrIns=NULL; /* vp-Register löschen */
      FreeVPortCopLists(vp);                 /* alte Copperliste löschen */
      vp->DspIns=dspins; vp->SprIns=sprins; vp->ClrIns=clrins;
      vp->UCopIns=MyCL;                      /* neue Copperliste einsetzen */
      Permit();   /* Multitasking wieder an */
      RethinkDisplay(); /* und die neue Copperliste darstellen */
      fn=(fn+1)%6;      /* neue Farbtabelle */
      do {
         Wait(1l<<MyWindow->UserPort->mp_SigBit); /* Warten auf Event */
         msg=GetMsg(MyWindow->UserPort); /* und dieses abrufen */
	 if (msg->Code==SELECTDOWN) ReplyMsg(msg),FirstClick=1; 
            else FirstClick=0;
      } while (FirstClick); /* die letzten drei Zeilen sind nötig, da ich für
                               jeden Mausklick zwei Messages bekomme */
   } while (msg->Class != CLOSEWINDOW);  /* wenn nicht CloseGadget, von vorne */
   FreeVPortCopLists(vp);  /* alte Copperliste löschen */
   RemakeDisplay();        /* Original-Workbench wiederherstellen */
   ReplyMsg(msg);	   /* letzte Message der Form halber Replyen */
   CloseWindow(MyWindow);  /* und aufräumen */
   CloseLibrary(IntuitionBase);
   CloseLibrary(GfxBase);
}
