
/***********************  MANDELW.CPP  ***********************************
*                                                                        *
*               Simple Mandelbrodt program                               *
*                         using                                          *
*              the  C M A T H  part of OptiVec                           *
*          with Borland C++ 4.x, 5.x, C++ Builder,                       *
*           or Microsoft Visual C++ 5.0 or higher                        *
*                                                                        *
*   Copyright 1996-2008 by OptiCode - Dr. Martin Sander Software Dev.    *
*                                                                        *
*                                                                        *
*       This sample program is meant to demonstrate how to use           *
*       CMATH within your Windows programs. No efforts are made          *
*       to provide a comfortable user interface etc.                     *
*       Appearance could be considerably improved by refinement          *
*       of color definition.                                             *
*                                                                        *
**************************************************************************/
/*

Microsoft Visual C++:
    Either open the workspace  VDEMO.DSW, in which the MANDEL project is
    included, or follow this way:

    1. Create a new empty project as a "Win32 application".
    2. In the project settings, C/C++, Code Generation,
       verify that multi-thread debug is chosen.
    3. Add \OptiVec\include to the include-file search path.
    4.a) Single-processor systems:
         Add the files MANDELW.CPP, OVVC4D.LIB and OVVCMTD.LIB to your project.
      b) Multi-processor systems (AMD64 x2, Intel Core2Duo or higher):
         Add the files MANDELW.CPP, OVVC7M.LIB and OVVCMTD.LIB to your project.
    5. Disable the use of precompiled headers
       (Project Settings /  C/C++   /  Preprocessor  /  Precompiled Headers)
    6. Compile and run.



Borland (CodeGear) Developer Studio and Borland C++ Builder 6+:
Don't use this file, but open the project MANDELB6.BPR.

BC++ Builder 4+:  Don't use this file, but open the project MANDELB.BPR.


Borland C++, Command-line:
    1. Go to your OptiVec directory.
    2. Be sure, your Borland C++ BIN directory is contained in the
       environment variable PATH and that you have a BCC32.CFG file
       pointing to your BC++ version's include and library paths.
    3. a) 32-bit, single-processor systems: type
               BCC32 -W -Iinclude mandelw.cpp lib\vcf4d.lib  lib\vcfs.lib
       b) 32-bit, multi-processor systems (AMD64 x2, Intel Core2Duo +): type
               BCC32 -W -Iinclude -tWM mandelw.cpp lib\vcf7m.lib  lib\vcfs.lib
       c) 16-bit: type
               BCC -ml -W -Iinclude mandelw.cpp lib\vcl4w.lib
    4. Run the program by typing:  mandelw

Borland C++, IDE (not for C++ Builder):
    1. Open the new-project menu with  Project/New.
    2. Create a project MANDELW in the OptiVec directory,
       e.g., c:\optivec.
    3.a) 32-bit: Choose Application[EXE] for Win32 GUI, static linking,
                 multi-thread.
    3.b) 16-bit: Choose Application[EXE] for Windows3.x, memory model LARGE.
    4. Hit OK.
    5. In the Project window that will now be on the screen, delete the
       nodes MANDELW.DEF and MANDELW.RC.
    6.a) 32-bit, single-processor systems:
         Add the nodes VCF4D.LIB and VCFS.LIB.
      b) 32-bit, multi-processor systems (AMD64 x2, Intel Core2Duo or higher):
         Add the nodes VCF7M.LIB and VCFS.LIB.
      c) 16-bit: Add the node VCL3W.LIB.
    7. In Options/Project, be sure the include-file search path and the
       library search path both include the respective  OPTIVEC directories,
       e.g.: c:\optivec\include and c:\optivec\lib, resprectively
    8. Compile and run.

*/

#include <windows.h>                    /* Compiler's include files */
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <winbase.h>

#include <newcplx.h>                      /* CMath include file */
HWND     hWndMain;

   /* Mandelbrodt parameters: */
fComplex  Offset(-0.5f,0), Asymmetry(-0.2f, +0.2f);
float     zoom = 1.0f;
unsigned  maxit = 120;
    // play around with these values!

LONG FAR PASCAL MainMessageHandler (HWND, UINT, WPARAM, LPARAM);


int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR /* lpCmdLine */, int /* nCmdShow */)
{
    MSG       msg;                      /* MSG structure to pass to windows proc */
    WNDCLASS  wc;
    char      *AppName;                 /* Name for the window */

    AppName = "MandelW";                 /* The name of this application */
    if(!hPrevInstance)
    {
        wc.style      = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc= MainMessageHandler;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance  = hInstance;
        wc.hIcon      = LoadIcon (hInstance, AppName);
        wc.hCursor    = LoadCursor (NULL, IDC_ARROW);
        wc.hbrBackground  = (HBRUSH) GetStockObject (WHITE_BRUSH);
        wc.lpszMenuName   = AppName;
        wc.lpszClassName  = AppName;
        RegisterClass (&wc);
    }
    
                             /* create application's Main window:  */
    hWndMain = CreateWindow (AppName,
                             "CMATH Demo: Madelbrodt",
                             WS_OVERLAPPEDWINDOW,
                             CW_USEDEFAULT,     /* Use default X, Y, and width  */
                             CW_USEDEFAULT,
                             CW_USEDEFAULT,
                             CW_USEDEFAULT,
                             NULL,              /* Parent window's handle      */
                             NULL,              /* Default to Class Menu       */
                             hInstance,         /* Instance of window          */
                             NULL);             /* Create struct for WM_CREATE */


    if (hWndMain == NULL)
    {
        MessageBox(NULL, "Could not create window in WinMain", NULL, MB_ICONEXCLAMATION);
        return (1);
    }

    ShowWindow(hWndMain, SW_SHOWMAXIMIZED);     /* Display main window      */
    UpdateWindow(hWndMain);

    while(GetMessage(&msg, NULL, 0, 0)) /* Main message loop */
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    UnregisterClass (AppName, hInstance);
    return (msg.wParam);
}

LONG FAR PASCAL
MainMessageHandler(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    HDC         vDC;
    RECT        mrect;
    PAINTSTRUCT ps;
    HPEN        Pens[16];

        // set the Mandelbrodt parameters at the top of this file
        // (below the #include directives)! 
        // A more advanced user interface would have to allow for live
        // input of these parameters. For our purposes, setting them in
        // in the source code has to be enough.
    unsigned  i, j, kk;
    float     scal;
    int       ii, jj;
    unsigned  width, width_2, height, height_2;
    fComplex  CM, ZM;

    switch (Message)                    /* Windows Message Loop           */
    {
        case WM_CREATE:
            break;

        case WM_PAINT:
            vDC = BeginPaint(hWndMain, &ps);
            GetClientRect( hWnd, &mrect );
            Pens[0]   = CreatePen( PS_SOLID, 1, 0x00000000 );  // Black
            Pens[1]   = CreatePen( PS_SOLID, 1, 0x00800000 );  // Dark Blue
            Pens[2]   = CreatePen( PS_SOLID, 1, 0x00008000 );  // Dark Green
            Pens[3]   = CreatePen( PS_SOLID, 1, 0x00000080 );  // Brown
            Pens[4]   = CreatePen( PS_SOLID, 1, 0x000000A0 );  // Dark Red
            Pens[5]   = CreatePen( PS_SOLID, 1, 0x00808000 );  // Cyan
            Pens[6]   = CreatePen( PS_SOLID, 1, 0x00800080 );  // Magenta
            Pens[7]   = CreatePen( PS_SOLID, 1, 0x00808080 );  // Dark Grey
            Pens[8]   = CreatePen( PS_SOLID, 1, 0x00B0B0B0 );  // Light Grey
            Pens[9]   = CreatePen( PS_SOLID, 1, 0x00FF0000 );  // Light Blue
            Pens[10]  = CreatePen( PS_SOLID, 1, 0x0000FF00 );  // Light Green
            Pens[11]  = CreatePen( PS_SOLID, 1, 0x000000FF );  // Light Red
            Pens[12]  = CreatePen( PS_SOLID, 1, 0x00FFFF00 );  // Light Cyan
            Pens[13]  = CreatePen( PS_SOLID, 1, 0x00FF00FF );  // Light Magenta
            Pens[14]  = CreatePen( PS_SOLID, 1, 0x0000FFFF );  // Yellow
            Pens[15]  = CreatePen( PS_SOLID, 1, 0x00FFFFFF );  // White
            width_2  = (width  = mrect.right - mrect.left) / 2;
            height_2 = (height = mrect.bottom - mrect.top) / 2;
            scal     = 1.5f / zoom / height_2;
            for (i = 0; i < width ; i++)
            {
                ii = i - width_2;
                for (j = 0; j < height; j++)
                {
                    jj = j - height_2;
                    ZM = fComplex((float)ii, (float)jj) * scal + Offset;
                    CM = ZM + Asymmetry;
                    for (kk = 0; kk < maxit; kk++)
                    {     // iterate until |Z| > 2, or a maximum of maxit times
                          // iterative Mandelbrodt formula
                        ZM = (ZM*ZM) + CM;
                        if( abs(ZM) > 2.0 ) break;
                    }  // kk now can be mapped to the plotting color
                       // for more details, use some nonlinear mapping function, like:
                    SelectObject( vDC, Pens[(int)(16.*fabs(sin( kk )))] );
                    MoveToEx( vDC, i, j, NULL ); LineTo( vDC, i+1, j+1 );
                }
            }
            for( i=0; i<16; i++ ) DeleteObject( Pens[i] );
            EndPaint(hWndMain, &ps);
            break;

        case WM_CLOSE:
            DestroyWindow(hWnd);
            if (hWnd == hWndMain)
                PostQuitMessage(0);
            break;

        default:
            return (DefWindowProc(hWnd, Message, wParam, lParam));
    }  // end of switch( message )
    return (0);
}

