[net.micro.amiga] mand5.c

rj@amiga.UUCP (Robert J. Mical) (01/11/86)

/*****************************************************************************
 *                     MAND5.C - Color Window
 *             Mandelbrot Self-Squared Dragon Generator
 *                    For the Commodore Amiga
 *                         Version 2.01
 *
 *             Copyright (C) 1986, =Robert J. Mical=
 *                  Placed in the Public Domain
 *
 *  This program may be distributed free of charge as long as the above
 *  notice is retained.  You may extract any or all information contained
 *  in this file for use in your own programs
 *
 ****************************************************************************/

#include "mand.h"


extern struct Menu MainMenu[MENU_COUNT];
extern struct MenuItem OptionsItems[OPTIONS_COUNT];

extern int MathBase, MathTransBase;

extern SHORT Color0, Color1, Color2;
extern SHORT UserPalette[29];

/*----------------------*/
/* Graphics definitions */

extern struct   GfxBase       *GfxBase;
extern struct   IntuitionBase *IntuitionBase;
 
extern struct   RastPort      *rp,*rp2;
extern struct   ViewPort      *vp;
 
extern struct   Window        *w,*w2, *ColorWindow;
extern struct   Screen        *screen;
extern struct   IntuiMessage  *message;
 
extern long last_color;

extern BOOL SettingCenter, SettingBoxSize;

/*----------------------------------*/
/* Miscellaneous Global Definitions */

extern union kludge {
   float f;
   int i;
} start_r,end_r,start_i,end_i;  /* Block bounds for set */
extern int max_x,max_y,max_mem_y;  /* Graphics window size */
extern int max_count,color_inc,color_offset,color_set,color_mode,color_div;
extern int color_inset,func_num;

extern int v_starty,max_mem;
extern long v_offset;
extern UWORD *color_table,*v_mand_store;

extern int modified,want_read;

extern FILE *console,*v_fp,*redir_fp;
 
extern SHORT ZoomCenterX, ZoomCenterY, ZoomBoxSizeX, ZoomBoxSizeY;
extern SHORT ZoomBoxStartX, ZoomBoxStartY;



/*****************************************************************************
 *
 * Color initialization and routines
 *
 ****************************************************************************/

#define COPYCOLOR    1
#define RANGE_FIRST  2
#define RANGE_SECOND 3
USHORT ColorMode;

extern struct Gadget ColorTemplateGadgets[COLOR_GADGETS_COUNT];
extern struct Image ColorPropsImages[3];
extern struct PropInfo ColorPropsInfos[3];
extern struct IntuiText ColorClusterText[4];

USHORT SavePalette[32];
extern struct Image SuperColorImages[32];

#define COLOR_IDCMP_FLAGS (GADGETDOWN | GADGETUP | MOUSEBUTTONS \
        | MENUPICK | MOUSEMOVE | ACTIVEWINDOW | INACTIVEWINDOW)


struct NewWindow ColorNewWindow =
    {
    /*  SHORT LeftEdge, TopEdge;        /* screen dimensions of window */
    /*  SHORT Width, Height;            /* screen dimensions of window */
    DEFAULT_WINDOW_LEFT, DEFAULT_WINDOW_TOP,
    COLORWINDOW_WIDTH, COLORWINDOW_HEIGHT,

    /*  UBYTE DetailPen, BlockPen;      /* for bar/border/gadget rendering */
    -1, -1,

    /*  ULONG IDCMPFlags;               /* User-selected IDCMP flags */
    NULL,

    /*  ULONG Flags;                    /* see Window struct for defines */
    BORDERLESS | SMART_REFRESH | NOCAREREFRESH,

    /*  struct Gadget *FirstGadget;*/
    NULL,

    /*  struct Image *CheckMark;*/
    NULL,

    /*  UBYTE *Title;                     /* the title text for this window */
    NULL,
    
    /*  struct Screen *Screen;*/
    NULL,
    
    /*  struct BitMap *BitMap;*/
    NULL,

    /*  SHORT MinWidth, MinHeight;       /* minimums */
    0, 0,
    /*  SHORT MaxWidth, MaxHeight;       /* maximums */
    0, 0,

    /*  USHORT Type;*/
    CUSTOMSCREEN,
};

USHORT RangeFirst;      /* the first selection of the range-color pair */


/* ======================================================================== */
/* ======================================================================== */
/* ======================================================================== */

BOOL OpenColorWindow()
{
    SHORT i;

    if (ColorWindow) return(TRUE);

    ClearMenuStrip(w);
    ColorNewWindow.Screen = screen;
    ColorNewWindow.IDCMPFlags = NULL;
    ColorNewWindow.FirstGadget
            = &ColorTemplateGadgets[COLOR_GADGETS_COUNT - 1];
    SetColorProps();
    InitSuperColors();
    ColorMode = NULL;

    if ((ColorWindow = (struct Window *)OpenWindow(&ColorNewWindow)) == 0)
        {
        fputs("no memory!\n", console);
        return(FALSE);
        }
    ColorWindow->UserPort = w->UserPort;
    ModifyIDCMP(ColorWindow, COLOR_IDCMP_FLAGS);
    SetMenuStrip(w, &MainMenu[0]);

    for (i = 0; i < 32; i++) SavePalette[i] = GetRGB4(vp->ColorMap, i);
    DrawColorWindow();
    return(TRUE);
}


VOID CloseColorWindow(accept)
BOOL accept;
{
    SHORT i;

    if (ColorWindow == NULL) return;

    ClearMenuStrip(ColorWindow);
    ColorWindow->UserPort = NULL;
    CloseWindow(ColorWindow);
    ColorWindow = NULL;

    if (NOT accept) LoadRGB4(vp, &SavePalette[0], 32);
    else
        {
        color_set = 2;
        Color0 = GetRGB4(vp->ColorMap, 0);
        Color1 = GetRGB4(vp->ColorMap, 1);
        Color2 = GetRGB4(vp->ColorMap, 2);
        for (i = 2; i <= 31; i++)
            {
            if (i == 2) *(color_table) = GetRGB4(vp->ColorMap, 2);
            else *(color_table + color_offset + (i - 2) * color_inc) 
                    = GetRGB4(vp->ColorMap, i);
            }
        }
}


VOID ColorRange(first, last)
SHORT first, last;
{
    SHORT i;
    LONG whole, redfraction, greenfraction, bluefraction;
    USHORT rgb;
    SHORT firstred, firstgreen, firstblue;
    SHORT lastred, lastgreen, lastblue;
    SHORT workred, workgreen, workblue;

    if (first > last)
        {
        i = first;
        first = last;
        last = i;
        }

    /* I need to see a spread of at least two, where there's at least one
     * spot between the endpoints, else there's no work to do so I
     * might as well just return now.
     */
    if (first >= last - 1) return;

    rgb = GetRGB4(vp->ColorMap, first);
    firstred = (rgb >> 8) & 0xF;
    firstgreen = (rgb >> 4) & 0xF;
    firstblue = (rgb >> 0) & 0xF;

    rgb = GetRGB4(vp->ColorMap, last);
    lastred = (rgb >> 8) & 0xF;
    lastgreen = (rgb >> 4) & 0xF;
    lastblue = (rgb >> 0) & 0xF;

    whole = (lastred - firstred) << 16;
    redfraction = whole / (last - first);
    whole = (lastgreen - firstgreen) << 16;
    greenfraction = whole / (last - first);
    whole = (lastblue - firstblue) << 16;
    bluefraction = whole / (last - first);

    for (i = first + 1; i < last; i++)
        {
        lastred = (redfraction * (i - first) + 0x8000) >> 16;
        workred = firstred + lastred;
        lastgreen = (greenfraction * (i - first) + 0x8000) >> 16;
        workgreen = firstgreen + lastgreen;
        lastblue = (bluefraction * (i - first) + 0x8000) >> 16;
        workblue = firstblue + lastblue;
        SetRGB4(vp, i, workred, workgreen, workblue);
        }
}


BOOL ColorGadgetGotten(gadget)
struct Gadget *gadget;
{
    USHORT rgb, pen;
    struct RastPort *RPort;
    SHORT greenpos, redpos, bluepos;

    RPort = ColorWindow->RPort;

    /* Have we got a color specifier? */
    if (gadget->GadgetID < 32)
        {
        /* Yes, it's a color gadget.  Set this pen number */
        pen = gadget->GadgetID;
        /* first, were we in COPY COLOR mode? */
        if (ColorMode == COPYCOLOR)
            {
            /* ok, copy old color here first! */
            rgb = GetRGB4(vp->ColorMap, rp->FgPen);
            SetRGB4(vp, pen, rgb >> 8, rgb >> 4, rgb);
            ColorMode = NULL;
            }
        if (ColorMode == RANGE_FIRST)
            {
            ColorMode = RANGE_SECOND;
            RangeFirst = pen;
            }
        else if (ColorMode == RANGE_SECOND)
            {
            ColorMode = NULL;
            ColorRange(RangeFirst, pen);
            }
        SetAPen(rp, pen);
        rgb = GetRGB4(vp->ColorMap, pen);
        ColorRectFill(RPort, pen);

        redpos = RemoveGadget(ColorWindow,
                &ColorTemplateGadgets[COLOR_RED]);
        greenpos = RemoveGadget(ColorWindow,
                &ColorTemplateGadgets[COLOR_GREEN]);
        bluepos = RemoveGadget(ColorWindow,
                &ColorTemplateGadgets[COLOR_BLUE]);
        SetColorProps();
        AddGadget(ColorWindow, &ColorTemplateGadgets[COLOR_BLUE], bluepos);
        AddGadget(ColorWindow, &ColorTemplateGadgets[COLOR_GREEN], greenpos);
        AddGadget(ColorWindow, &ColorTemplateGadgets[COLOR_RED], redpos);
        RefreshGadgets(&ColorTemplateGadgets[COLOR_GADGETS_COUNT - 1], 
                ColorWindow);
        }

    else switch (gadget->GadgetID)
        {
        case COLOR_OK:
            CloseColorWindow(TRUE);
            return(FALSE);
            break;
        case COLOR_CANCEL:
            CloseColorWindow(FALSE);
            return(FALSE);
            break;
        case COLOR_COPY:
            ColorMode = COPYCOLOR;
            break;
        case COLOR_RANGE:
            ColorMode = RANGE_FIRST;
            break;
        }
    return(TRUE);
}


ModifyColors()
{
    USHORT pen, newred, newgreen, newblue;

    pen = w->RPort->FgPen;

    newred = ((struct PropInfo *)
            ColorTemplateGadgets[COLOR_RED].SpecialInfo)->HorizPot >> 12;
    newgreen = ((struct PropInfo *)
            ColorTemplateGadgets[COLOR_GREEN].SpecialInfo)->HorizPot >> 12;
    newblue = ((struct PropInfo *)
            ColorTemplateGadgets[COLOR_BLUE].SpecialInfo)->HorizPot >> 12;

    SetRGB4(vp, pen, newred, newgreen, newblue);
}



DrawColorWindow()
{
    struct RastPort *RPort;

    RPort = ColorWindow->RPort;

    ColorRectFill(RPort, rp->FgPen);
    SetAPen(RPort, 1);
    DrawBox(RPort, 1, 1, COLORWINDOW_WIDTH - 2, COLORWINDOW_HEIGHT - 2);
    DrawBox(RPort, COLOR_BOX_LEFT - 2, COLOR_BOX_TOP - 2, 
        COLOR_BOX_RIGHT + 2, COLOR_BOX_BOTTOM + 2);
    DrawBox(RPort, COLOR_BOX_LEFT - 2, COLOR_COLOR_TOP - 2, 
        COLOR_BOX_LEFT + (8 * 15) + 1, COLOR_COLOR_TOP + (4 * 10) + 1);
}



SetColorProps()
{
    USHORT rgb, red, green, blue;

    rgb = GetRGB4(vp->ColorMap, rp->FgPen);
    red = (rgb >> 8) & 0xF;
    green = (rgb >> 4) & 0xF;
    blue = (rgb >> 0) & 0xF;

    ((struct PropInfo *)ColorTemplateGadgets[COLOR_RED]
            .SpecialInfo)->HorizPot
            = (red << 12) | (red << 8) | (red << 4) | red;
    ((struct PropInfo *)ColorTemplateGadgets[COLOR_GREEN]
            .SpecialInfo)->HorizPot
            = (green << 12) | (green << 8) | (green << 4) | green;
    ((struct PropInfo *)ColorTemplateGadgets[COLOR_BLUE]
            .SpecialInfo)->HorizPot
            = (blue << 12) | (blue << 8) | (blue << 4) | blue;
}


ColorRectFill(RPort, pen)
struct RastPort *RPort;
SHORT pen;
{
    SetAPen(RPort, pen);
    SetDrMd(RPort, JAM2);
    WaitBOVP(vp);
    RectFill(RPort, COLOR_BOX_LEFT, COLOR_BOX_TOP, 
        COLOR_BOX_RIGHT, COLOR_BOX_BOTTOM);
}


VOID DoColorWindow()
{
    struct IntuiMessage *message;
    ULONG class;
    struct Gadget *gadget;

    if (NOT OpenColorWindow()) return;

    FOREVER
        {
        Wait((1 << ColorWindow->UserPort->mp_SigBit));
        while (message = (struct IntuiMessage *)GetMsg(ColorWindow->UserPort))
            {
            class = message->Class;
            gadget = (struct Gadget *)(message->IAddress);
            ReplyMsg(message);

            switch (class)
                {
                case GADGETDOWN:
                case GADGETUP:
                    if (ColorGadgetGotten(gadget) == FALSE) return;
                    break;
                case MOUSEMOVE:
                    ModifyColors();
                    break;
                }
            }
        }
}


InitSuperColors()
{
    SHORT i;

    /* OK, initialize those Super Color Gadgets! */
    for (i = 0; i < 32; i++)
        {
        SuperColorImages[i].LeftEdge = 0;
        SuperColorImages[i].TopEdge = 0;
        SuperColorImages[i].Width = 15;
        SuperColorImages[i].Height = 10;
        SuperColorImages[i].Depth = 0;
        SuperColorImages[i].ImageData = NULL;
        SuperColorImages[i].PlanePick = 0;
        SuperColorImages[i].PlaneOnOff = i;
        SuperColorImages[i].NextImage = NULL;
        }
}