/**************************************************************
 *                                                            *
 *           Order From Chaos: A Fractal Sampler              *
 *                                                            *
 *          Written by Eric Giguere for AMIGA Plus            *
 *                                                            *
 *------------------------------------------------------------*
 *                                                            *
 * File: fractal.c                                            *
 *                                                            *
 * Contains the functions common to all the fractal routines  *
 * and the mainline that activates the fractal display        *
 * function.  It must be linked to one of the other files     *
 * before execution.                                          *
 *                                                            *
 * This file compiles under Manx C 3.6a using either the      *
 * 16-bit or 32-bit (+L option) libraries.  The only compiler *
 * dependency is the random-number generator, ran(), which    *
 * returns a random number from 0.0 to 1.0 --- Lattice users  *
 * will have to use an equivalent function to modify the      *
 * GetRand() function below.                                  *
 *                                                            *
 **************************************************************/


#include <stdio.h>
#include "exec/types.h"
#include "intuition/intuition.h"
#define DEPTH   5
#define WIDTH   320
#define HEIGHT  200
#define MODES   0


/*
 * Define our custom screen & window
 */

static struct NewScreen CSDefn =
  {
    0, 0, WIDTH, HEIGHT,
    DEPTH, 0, 3, MODES,
    CUSTOMSCREEN,
    NULL, NULL, NULL, NULL
  };

static struct NewWindow CWDefn =
  {
    0, 0, WIDTH,HEIGHT,
    -1, -1,
    CLOSEWINDOW,
    WINDOWCLOSE | GIMMEZEROZERO | SMART_REFRESH |
    ACTIVATE | RMBTRAP,
    NULL, NULL, NULL, NULL, NULL,
    0, 0, 0, 0,
    CUSTOMSCREEN
  };

/*
 * Define the colour table we'll use
 */

static UWORD ColourTable[] =
  {
    0x0000, 0x0e30, 0x0ed0, 0x069f,
    0x0b40, 0x0fb0, 0x0bf0, 0x05d0,
    0x07df, 0x0c0e, 0x0f2e, 0x0feb,
    0x0c98, 0x0F00, 0x0f0f, 0x000f,
    0x0811, 0x0833, 0x0855, 0x0877,
    0x0899, 0x08bb, 0x08dd, 0x0CDD,
    0x0CBB, 0x0C99, 0x0C77, 0x0C55,
    0x0C33, 0x0C11, 0x0C28, 0x0C2F
  };      /* Good colors would help...*/

/*
 * Variables needed to use graphics
 */

struct IntuitionBase *IntuitionBase;  /* Intuition library */
struct GfxBase       *GfxBase;        /* Graphics library */
struct Screen        *FScreen;        /* The custom screen */
struct Window        *FWindow;        /* The graphics window */
struct RastPort      *FRPort;         /* The window raster port */

/*
 * Window title -- must be defined in
 * the other module ..
 * along with these other Screen parameters
 */

extern UBYTE *FTitle;
extern UBYTE SDepth,SWidth, SHeight;
extern USHORT SViewModes;
/*
 * Library functions
 */

extern struct Library      *OpenLibrary();
extern struct Screen       *OpenScreen();
extern struct Window       *OpenWindow();
extern struct IntuiMessage *GetMsg();
extern void                 CloseWindow();
extern void                 CloseScreen();
extern void                 CloseLibrary();

/*
 * Random number generator --- Manx-dependent
 */

#ifdef AZTEC_C
    extern double ran();
#endif

/*
 * The fractal routine
 */

extern void RunFractals();

/*
 * Forward references
 */

int  Initialize();
void Finish();

/*
 * Mainline -- Set up screen & window and then call the
 *             fractal routine.  Cleanup when done.
 */

int main()
  {
    if( Initialize() )
        RunFractals();
    else if( FTitle != NULL )
        printf( "Could not create `%s'\n", FTitle );
    else
        puts( "Fractal experiment failed." );

    Finish();
  }

/*
 * Initialize libraries, open screen & window.
 * Returns FALSE if unsuccessful.
 */

int Initialize()
  {
    /* Open the libraries */

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

    if( IntuitionBase == NULL )
        return( FALSE );

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

    if( GfxBase == NULL )
        return( FALSE );

    /* Open the custom screen */
/*   CSDefn.Depth= SDepth;              */
/*   CSDefn.Width =SWidth;            */
/*   CSDefn.Height= SHeight;        */
/*   CSDefn.ViewModes= SViewModes;*/

    FScreen = OpenScreen( &CSDefn );

    if( FScreen == NULL )
        return( FALSE );

    /* Load the 2^DEPTH colours from our colour table */

    LoadRGB4( &FScreen->ViewPort, ColourTable, (long) 1L<<DEPTH );

    /* Open the display window */

    CWDefn.Screen = FScreen;
    CWDefn.Title  = FTitle;

    FWindow = OpenWindow( &CWDefn );

    if( FWindow == NULL )
        return( FALSE );

    FRPort = FWindow->RPort;

    return( TRUE ); /* Initialization was successful */
  }

/*
 * Cleanup any open windows, screens or libraries.
 */

void Finish()
  {
    if( FWindow != NULL )
        CloseWindow( FWindow );

    if( FScreen != NULL )
        CloseScreen( FScreen );

    if( GfxBase != NULL )
        CloseLibrary( GfxBase );

    if( IntuitionBase != NULL )
        CloseLibrary( IntuitionBase );
  }

/*
 * Check to see if the CLOSEWINDOW gadget on the
 * fractal window was chosen.  Returns TRUE if it was.
 */

int Done()
  {
    struct IntuiMessage *msg;

    while( ( msg = GetMsg( FWindow->UserPort ) ) != NULL )
        if( msg->Class == CLOSEWINDOW )
            return( TRUE );

    return( FALSE );
  }

/*
 * Return a random integer from 0 .. ceiling-1
 *
 * NOTE:  This function depends on the Manx ran() function.
 *        Lattice users will have to find an equivalent way
 *        to generate a random number from 0 to ceiling-1.
 */

long GetRand( ceiling )
  long ceiling;
  {
    #ifdef AZTEC_C
        return( (long) ( ran() * (double) ceiling ) % ceiling );
    #else
        return( 0L ); /* replace with your generator */
    #endif
  }

/*
 * Draw a point in the given colour at the given location.
 */

void DrawPoint( colour, x, y )
  long colour, x, y;
  {
    SetAPen( FRPort, colour );
    Move( FRPort, x, y );
    Draw( FRPort, x, y );
  }

