/*
 *
 * ApfelC.c  by Holger Gzella
 *
 * for use with Lattice C v5.04 ...
 *
 */

/* C-Includes; entsprechen im weitesten */
/* Sinne den Modula-Definitionsmodules. */

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

/* Function-Prototypes; sie erlauben bei Lattice-C */
/* ab Version 4.00 das direkte Anspringen der Li-  */
/* brary-Offsets, was in Modula automatisch ge-    */
/* schieht. Ohne Verwendung der Prototypes steigt  */
/* die Länge und Ausführungszeit eines Programms   */
/* beträchtlich, da so erst Zwischencode vor den   */
/* eigentlichen Library-Aufruf gesetzt werden muß. */

#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>

/* Screen- und Window definieren ... */

struct NewScreen screenDaten = {
   0,0,320,256,6,2,1,EXTRA_HALFBRITE,
   CUSTOMSCREEN,NULL,NULL,NULL,NULL,
};

struct NewWindow windowDaten = {
   0,0,320,256,0,1,MOUSEBUTTONS,BORDERLESS,
   NULL,NULL,NULL,0,NULL,0,0,0,0,CUSTOMSCREEN,
};

/* Die Farben ... */

UWORD colors[] = {
   0x000,0x00F,0x02F,0x04F,0x06F,0x08F,0x0AF,0x0BF,
   0x0CF,0x0DF,0x0FF,0xFF0,0xFC0,0xFA0,0xF80,0xF60,
   0xF40,0xF20,0xF00,0xF02,0xF04,0xF06,0xF08,0xF0A,
   0xF0C,0xF0F,0xF20,0xF40,0xF60,0xF80,0xFA0,0xFC0,
};

/* Globale Definitionen ... */

struct GfxBase       *GfxBase;
struct IntuitionBase *IntuitionBase;

struct Screen *screen;
struct Window *window;
struct RastPort *rastPort;
struct IntuiMessage *nachricht;

long class;

/* Function-Prototypes innerhalb des */
/* Programms; "sauberes" ANSI-C!     */

void DrawApfel(double,double,double,double,int,int,int,int);

/* Das Hauptprogramm ... */

void main(void)
{

   /* Intuition und Graphics dürften IMMER  */
   /* zu öffnen sein, daher fangen wir hier */
   /* keinen Fehler ab.                     */

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

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

   if ((screen = (struct Screen *)
                  OpenScreen(&screenDaten)) != NULL) {

         windowDaten.Screen = screen;

         if ((window = (struct Window *)
                        OpenWindow(&windowDaten)) != NULL) {

            rastPort = window->RPort;
            LoadRGB4(&screen->ViewPort,(UWORD *)&colors,32);

            DrawApfel((double)-1.25,(double)1.25,
                      (double)-2.0,(double)0.5,320,256,64,64);

            /* Über IDCMP auf's Drücken der */
            /* linken Maustaste warten ...  */

            for (;;) {
               WaitPort(window->UserPort);
               nachricht = (struct IntuiMessage *)
               GetMsg(window->UserPort);

               class = nachricht->Class;
               ReplyMsg((struct Message *)nachricht);
               if (class == MOUSEBUTTONS) break;
            }

            CloseWindow(window);
         }

      CloseScreen(screen);
   }

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

/* Hier ist die Routine, die das Zeichnen */
/* eines Apfelmännchens übernimmt. Sie    */
/* benötigt diese Parameter:              */
/*                                        */
/* imin: minimaler Imaginärwert.          */
/* imax: maximaler Imaginärwert.          */
/* rmin: minimaler Realwert.              */
/* rmax: maximaler Realwert.              */
/* xmax: Breite der Grafik.               */
/* ymax: Höhe der Grafik.                 */
/* nmax: Iterationszahl.                  */
/* ncol: maximale Anzahl Farben.          */

void DrawApfel(double imin,
               double imax,
               double rmin,
               double rmax,
               int xmax,
               int ymax,
               int nmax,
               int ncol)
{
   double rst,ist,a,b,bet,x,y,real,imag;
   int h,v,col,n;

   rst = (rmax-rmin)/xmax;
   ist = (imax-imin)/ymax;

   for (h = 0; h<xmax; h++) {

      a = rmin+h*rst;

      for (v = 0; v<ymax; v++) {

         nachricht = (struct IntuiMessage *)GetMsg(window->UserPort);

         while (nachricht) {
            class = nachricht->Class;
            ReplyMsg((struct Message *)nachricht);
            if (class == MOUSEBUTTONS) {
               h = xmax;
               v = ymax;
            }
            nachricht = (struct IntuiMessage *)GetMsg(window->UserPort);
         }

         b = imin+v*ist;
         n = 0;
         x = (double)0;
         y = (double)0;

         for(;;) {
            real = x*x-y*y+a;
            imag = 2*x*y+b;

            x = real;
            y = imag;

            bet = x*x+y*y;

            if ((bet >= 4) || (n == nmax)) break;

            n++;
         }

         col = n%(ncol-2)+1;
         if (n == nmax) col = 0;

         SetAPen(rastPort,(long)col);
         (void)WritePixel(rastPort,(long)h,(long)v);
      }
   }
}

