/* Reticolo.c - versione tradotta da A. Prandi */

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

#include <functions.h>

#ifdef ORIGINALCODE
#define printf  kprintf
#endif

struct  Remember    *rememberkey = NULL;
struct  Window      *getNewWind();

struct  IntuitionBase   *IntuitionBase;
struct  GfxBase         *GfxBase;

ULONG   flg = ACTIVATE | WINDOWCLOSE | NOCAREREFRESH | WINDOWDRAG
       | WINDOWDEPTH | SIMPLE_REFRESH;

ULONG   iflg = CLOSEWINDOW | INTUITICKS ;

#define FANCYVERSION 1
#if FANCYVERSION
#define VISUALTICKS   30
#define CYCLETICKS   3
#endif

main()
{
    struct  IntuiMessage    *msg;
    struct Window   *window = NULL;
    WORD    exitval = 0;

    /* hold data from *msg  */
    ULONG   class;

    /* specifico per questo test  */
    struct Screen *wbscreen;
    struct RasInfo *rinfo2 = NULL;
    struct BitMap  *bmap2 = NULL;
    struct RastPort *rport2 = NULL;
    int      it_is_done = 0;
    int      counter = 0;

    if (!(IntuitionBase = (struct IntuitionBase *)
   OpenLibrary("intuition.library", 0L)))
    {
   printf("NO INTUITION LIBRARY\n");
   exitval = 1;
   goto EXITING;
    }

    if (!(GfxBase = (struct GfxBase *)
   OpenLibrary("graphics.library", 0L)))
    {
   printf("NO GRAPHICS LIBRARY\n");
   exitval = 2;
   goto EXITING;
    }

    /* get a window on the workbench   */
    window = getNewWind(320, 20, 300, 50, flg, iflg);
    if (window == NULL)
    {
   printf("test: can't get window.\n");
   exitval = 1;
   goto EXITING;
    }


    /* ------ Aggiunge un secondo playfield per il Workbench ------------ */

    wbscreen = window->WScreen;      /* lo trova   */

    /* colloca le rasinfo del secondo playfield, bitmap, e bitplane   */

    if (!(rinfo2 = (struct RasInfo *)
   AllocMem((LONG) sizeof(struct RasInfo), (LONG) MEMF_PUBLIC|MEMF_CLEAR)))
    {
   printf("alloc rasinfo failed\n");
   goto EXITING;
    }

    if (!(bmap2 = (struct BitMap *)
   AllocMem((LONG) sizeof(struct BitMap), (LONG) MEMF_PUBLIC|MEMF_CLEAR)))
    {
   printf("alloc bitmap failed\n");
   goto EXITING;
    }

    InitBitMap(bmap2, 1L, (LONG) wbscreen->Width, (LONG) wbscreen->Height);

    /* useremo 1 plane. */
    if (!(bmap2->Planes[0] =
   (UBYTE *) AllocRaster((LONG) wbscreen->Width, (LONG) wbscreen->Height)))
    {
   printf("alloc raster failed\n");
   goto EXITING;
    }

    if (!(rport2 = (struct RastPort *)
   AllocMem((LONG) sizeof (struct RastPort), (LONG) MEMF_PUBLIC)))
    {
   printf("alloc rastport failed\n");
   goto EXITING;
    }
    InitRastPort(rport2);
    rport2->BitMap = bmap2;

    SetRast(rport2, 0L);

    Forbid();

    rinfo2->BitMap = bmap2;   /* installa la mia bitmap nelle mie rasinfo  */

    wbscreen->ViewPort.RasInfo->Next = rinfo2;

    wbscreen->ViewPort.Modes |= DUALPF;
    it_is_done = 1;

    Permit();

    /* setta il colore di primo piano */
    SetRGB4(&wbscreen->ViewPort, 9L, 0L, (LONG) 0xF, 0L);

    MakeScreen(wbscreen);
    RethinkDisplay();

    drawSomething(rport2);

    FOREVER
    {
   if ((msg = (struct IntuiMessage *)GetMsg(window->UserPort)) == NULL)
   {
       Wait((ULONG) 1<<window->UserPort->mp_SigBit);
       continue;
   }

   class   = msg->Class;
   ReplyMsg(msg);

   switch (class)
   {
   case INTUITICKS:
#if FANCYVERSION
       setPrimary(&wbscreen->ViewPort);   /* colori dei cicli */
       if (counter++ > VISUALTICKS)
       {
      counter = 0;
      SetRast(rport2, 0L);
      drawSomething(rport2);
       }
#endif
       break;

   case CLOSEWINDOW:
       goto EXITING;
   default:
       printf("unknown event: class %lx\n", class);
   }
    }

EXITING:
    if (it_is_done)
    {
   Forbid();
   wbscreen->ViewPort.RasInfo->Next = NULL;
   wbscreen->ViewPort.Modes &= ~DUALPF;
   Permit();
   MakeScreen(wbscreen);
   RethinkDisplay();
    }

    if (rport2) FreeMem(rport2, (LONG) sizeof (struct RastPort));
    if (bmap2) 
    {
   if (bmap2->Planes[0])
   {
       FreeRaster(bmap2->Planes[0],
          (LONG) wbscreen->Width, (LONG) wbscreen->Height);
   }
   FreeMem(bmap2, (LONG) sizeof (struct BitMap));
    }
    if (rinfo2) FreeMem(rinfo2, (LONG) sizeof (struct RasInfo));

    if (window) CloseWindow(window);
    if (GfxBase) CloseLibrary(GfxBase);
    if (IntuitionBase) CloseLibrary(IntuitionBase);

    exit (exitval);
}

#if FANCYVERSION
setPrimary(vp)
struct ViewPort *vp;
{
    static int current = 0;

    if (!(current++ % CYCLETICKS)) return;

    switch ((current/CYCLETICKS)%3)
    {
    case 0:
   SetRGB4(vp, 9L, 0xFL, 0L, 0L);
   break;
    case 1:
   SetRGB4(vp, 9L, 0L, 0xFL, 0L);
   break;
    case 2:
   SetRGB4(vp, 9L, 0L, 0L, 0xFL);
   break;
    }
}

struct pt_st {
    ULONG x;
    ULONG y;
    };

typedef struct pt_st Pt;

drawSomething(rp)
struct RastPort *rp;
{
    int width, height;
    LONG   RangeRand();
    int i;

    Pt start, vertex, end;
    Pt p0, p1;

    width = rp->BitMap->BytesPerRow * 8;
    height = rp->BitMap->Rows;

    /* setta due linee di riferimento random */
    start.x = RangeRand((LONG) width);
    vertex.x   = RangeRand((LONG) width);
    end.x   = RangeRand((LONG) width);

    start.y = RangeRand((LONG) height);
    vertex.y = RangeRand((LONG) height);
    end.y   = RangeRand((LONG) height);

    SetAPen(rp, 1L);

    /* disegna linee che collegano punti intermedi */
    for (i = 0; i <= 0x100; i += 0x10)
    {
   /* punto tra l'inizio e il vertice */
   p0.x = (start.x * (0xFF - i) + vertex.x  * i) >> 8;
   p0.y = (start.y * (0xFF - i)  + vertex.y * i) >> 8;

   /* punto tra il vertice e la fine   */
   p1.x = (vertex.x * (0xFF - i) + end.x * i) >> 8;
   p1.y = (vertex.y * (0xFF - i) + end.y * i) >> 8;

   Move(rp, p0.x, p0.y);
   Draw(rp, p1.x, p1.y);
    }

}

#else

drawSomething(rp)
struct RastPort *rp;
{
    int width, height;
    int r, c;

    width = rp->BitMap->BytesPerRow * 8;
    height = rp->BitMap->Rows;

    SetAPen(rp, 1L);

    for (r = 0; r < height; r += 40)
   for (c = 0; c < width; c += 40)
   {
       Move(rp, 0L, (LONG) r);
       Draw(rp, (LONG) c, 0L);
   }
}

#endif

struct  Window * getNewWind(left, top, width, height, flg, iflg)
SHORT   left, top, width, height;
ULONG   flg, iflg;
{
    struct  Window  *OpenWindow();
    struct  NewWindow   nw;

    nw.LeftEdge =   (SHORT) left;
    nw.TopEdge  =   (SHORT) top;
    nw.Width    =   (SHORT) width;
    nw.Height   =   (SHORT) height;
    nw.DetailPen    =   (UBYTE) -1;
    nw.BlockPen =   (UBYTE) -1;
    nw.IDCMPFlags   =   (ULONG) iflg;

    nw.Flags    =   (ULONG) flg;

    nw.FirstGadget  =   (struct Gadget *)   NULL;
    nw.CheckMark    =   (struct Image *)    NULL;
    nw.Title    =   (UBYTE *)   " Doppio Reticolo ";
    nw.Screen   =   (struct Screen *)   NULL;
    nw.BitMap   =   (struct BitMap *)   NULL;
    nw.MinWidth =   (SHORT) 50;
    nw.MinHeight=   (SHORT) 30;
    /* work around bug  */
    nw.MaxWidth =   (SHORT) nw.Width;
    nw.MaxHeight    =   (SHORT) nw.Height;
    nw.Type     =   (USHORT) WBENCHSCREEN;

    return ((struct Window *) OpenWindow(&nw));
}
