/*
 * M A N D E L B R O T	 C O N S T R U C T I O N   S E T
 *
 * (C) Copyright 1989 by Olaf Seibert.
 * Mandel may be freely distributed. See file 'doc/Notice' for details.
 *
 * GotMenu and some (many) related things.
 */

#include <exec/types.h>
#include <intuition/intuition.h>
#include "mandel.h"
#ifdef DEBUG
#   include <stdio.h>
#   undef STATIC
#   define STATIC   /* EMPTY */
#endif

extern double ReMouse, ImMouse;
extern UBYTE IPlotNr, EPlotNr;
extern void UpdateDrwCm();

TEXT FileName[FNAME_SIZE+1] = "Mandel.pic";
TEXT DirName[DNAME_SIZE+2]  = "";
UBYTE Buffer[5][20];

int (*DepthFuncArray[])() = {
    ZQuadMinC, ZC1MinZ, Z3PlusZCMin1MinC, UserProgFunc, I_ZQuadMinC
};

void (*IPlotFuncArray[])() = {
    None, PlotZ
};

void (*EPlotFuncArray[])() = {
    PlotIterationCount, PlotZ,
};

/* Forward declarations of static procedures */
STATIC void PrjNew();

void GotMenu(Code)
USHORT Code;
{
    static void (*MenuFunc[])()= {
	CprMenu, PrjMenu, OptMenu, DrwMenu, BatchMenu
    };
    while (Code != MENUNULL) {
	(*MenuFunc[MENUNUM(Code)]) (Code);
	Code = ItemAddress(MandelMenu, (long) Code)->NextSelect;
    }
}

void CprMenu(Code)
USHORT Code;
{
    extern long Revision;	/* From IncRev */
    ULONG OldIDCMP = MainWindow->IDCMPFlags;

#define DATE		    "16 April 1989 V1.3 ("
#define strlen_DATE	    20

    static UBYTE DateVersion[strlen_DATE+9] = DATE;

    static struct IntuiText Body[] =
    {
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
	    10, 15, NULL, (UBYTE *)"Mandelbrot Construction Set", &Body[1] },
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
	    10, 30, NULL, (UBYTE *)"By KosmoSoft Productions", &Body[2] },
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
	    10, 40, NULL, DateVersion, &Body[3] },
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
	    10, 55, NULL, (UBYTE *)"Ohh, please Copy-Me!", NULL }
    },
    ExitText =
    {	MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
	AUTOLEFTEDGE, AUTOTOPEDGE, NULL, (UBYTE *)" OK ", NULL };

    sprintf(&DateVersion[strlen_DATE], "%ld)", Revision);

    ModifyIDCMP(MainWindow, OldIDCMP &~ (MENUVERIFY | SIZEVERIFY | REQVERIFY));
    AutoRequest(MainWindow, &Body[0], NULL, &ExitText, NULL, NULL, 258L, 100L);
    ModifyIDCMP(MainWindow, OldIDCMP);
}

char *CatFileComponents(dest, dirname, filename)
char *dest;
char *dirname;
char *filename;
{
    strcpy(dest, dirname);
    if (dirname[0] && dirname[strlen(dirname) - 1] != ':')
	strcat(dest, "/");
    strcat(dest, FileName);

    return dest;
}


bool OpenAs(name)
char *name;
{
    struct Mand MandChunk;
    struct ILBM_info *ilbminfo, *win_read_iff();

    StopDrawing();
    MandChunk.MandID = 0;
    if (ilbminfo = win_read_iff(name, (short)FALSE,
	MainWindow, sizeof(MandChunk), &MandChunk)) {
	put_ea_cmap(&ilbminfo->cmap, NumColors, MandelScreen);
	InterpretMAND(&MandChunk, ilbminfo);
    }
    Saved = TRUE;
    NameValid = FALSE;

    return ilbminfo != NULL;
}

bool SaveAs(name)
char *name;
{
    struct Mand MandChunk;
    unsigned char ea_colormap[3*MAXCOL];

    get_ea_cmap(ea_colormap, NumColors, MandelScreen);
    MakeMAND(&MandChunk);
    SuspendDrawing();
    NameValid = Saved = write_iff(name, ea_colormap, MainWindow,
	    (short) 0, (short) 0, (short) TRUE, sizeof(MandChunk),
	    &MandChunk);
    ResumeDrawing();

    return Saved;
}

STATIC void PrjMenu(Code)
USHORT Code;
{
    int SubNum = SUBNUM(Code);
    int ItemNum = ITEMNUM(Code);

    struct Mand MandChunk;
    char Name[DNAME_SIZE + FNAME_SIZE + 3];

    switch (ItemNum) {
    case PRJNEW:
	PrjNew(SubNum);
	break;
    case PRJOPN:
	if ( get_fname(MainWindow, "Select a filename to OPEN",
		FileName, DirName) == NULL )
	    break;
	CatFileComponents(Name, DirName, FileName);
	OpenAs(Name);
	break;
    case PRJSVE:    /* Save */
	if (NameValid) skipto prjsve;
	/* Fall Through */
    case PRJSVA:    /* Save As */
	if ( get_fname(MainWindow, "Select a filename to SAVE",
		FileName, DirName) == NULL )
	    break;
prjsve:
	CatFileComponents(Name, DirName, FileName);
	SaveAs(Name);
	break;
    case PRJSTP:
	StopDrawing();
	break;
    case PRJQUI:
	finished = TRUE;
    }
}

STATIC void OptMenu(Code)
USHORT Code;
{
    int SubNum = SUBNUM(Code);
    int ItemNum = ITEMNUM(Code);

    switch (ItemNum) {
    case OPTCOL:
	switch (SubNum) {
	case OCSEL:
	    PenTableMode = SELECT;
	    Select();
	    break;
	case OCMOD:
	    PenTableMode = MODULO;
	    break;
	case OCRAN:
	    PenTableMode = RANGES;
	    break;
	case OCPAL:
	    OpenColorWindow(MainWindow);
	} /* End Switch SUBNUM */
	InitPenTable();
	break;
    case OPTRES:
	switch (SubNum) {
	case ORNRM:
	    PixelStep = 1;
	    break;
	case OR12:
	    PixelStep = 2;
	    break;
	case OR13:
	    PixelStep = 3;
	    break;
	case OR14:
	    PixelStep = 4;
	    break;
	case ORFIL: /* Fill in */
	    DrawPicture((bool)TRUE);
	    break;
	case ORHI:
	case ORILC:
	case OREHB:
	    {
		USHORT newmode = MandelNScreen.ViewModes & ~(HIRES | LACE | EXTRA_HALFBRITE);

		if (ItemAddress(MandelMenu, MENU(OPTMENU, OPTRES, ORHI))
		    -> Flags & CHECKED)
			newmode |= HIRES;
		if (ItemAddress(MandelMenu, MENU(OPTMENU, OPTRES, ORILC))
		    -> Flags & CHECKED)
			newmode |= LACE;
		if (ItemAddress(MandelMenu, MENU(OPTMENU, OPTRES, OREHB))
		    -> Flags & CHECKED)
			newmode |= EXTRA_HALFBRITE;
		if (newmode != MandelNScreen.ViewModes) {
		    MandelNScreen.ViewModes = newmode;
		    if (Sure())
			ReInitDisplay();
		    else
			UpdateOptViewResCm();
		}
	    }
	    break;
	case ORBCK:
	    if (ItemAddress(MandelMenu, MENU(OPTMENU,OPTRES,ORBCK))->Flags & CHECKED)
		DoBorderless(MainWindow, &borderinfo);
	    else
		UndoBorderless(MainWindow, &borderinfo);
	} /* End Switch SUBNUM */
	break;
    case OPTPAR:
	Parameters();
	break;
    case OPTPRI:
	switch (SubNum) {
	case OPNOR:
	    SetDrawPri(0);
	    break;
	case OPLOW:
	    SetDrawPri(-5);
	    break;
	}
	break;
    } /* End Switch ITEMNUM */
}

/*
 *  This function sets the drawing function, numbered from 0.
 */

void SetDrawingFunction(number)
int number;
{
    if (number >= 0 && number <= DF5) {
	FunctionNr = number;
	DepthFunc = DepthFuncArray[FunctionNr];
    }
}

/*
 *  This function sets the i plotting function, numbered from 0.
 */

void SetIPlotFunction(number)
int number;
{
    if (number >= 0 && number <= DIZ) {
	IPlotNr = number;
	IPlotFunc = IPlotFuncArray[IPlotNr];
    }
}

/*
 *  This function sets the e plotting function, numbered from 0.
 */

void SetEPlotFunction(number)
int number;
{
    if (number >= 0 && number <= DEZ) {
	EPlotNr = number;
	EPlotFunc = EPlotFuncArray[EPlotNr];
    }
}

void DrwMenu(Code)
USHORT Code;
{
    int ItemNum = ITEMNUM(Code);
    int SubNum = SUBNUM(Code);

    switch (ItemNum) {
    case DRWFUN:
	SetDrawingFunction(SubNum + DF1);
	break;
    case DRWIPL:
	SetIPlotFunction(SubNum + DINONE);
	break;
    case DRWEPL:
	SetEPlotFunction(SubNum + DEDEPTH);
	break;
    }
}

void UnImpl()
{
    static char alert[] = "\
\0\144\25Mandelbrot Construction Set -- By KosmoSoft Productions\0a\
\0\170\40Sorry, this function has not been implemented yet!\0";
    DisplayAlert(RECOVERY_ALERT, alert, 50L);
}

STATIC USHORT OldMinWidth, OldMinHeight, OldMaxWidth, OldMaxHeight;

/* Do not nest calls to DisableSizing: the original values will be lost. */

void DisableSizing()
{
    OldMinWidth = MainWindow->MinWidth;
    OldMaxWidth = MainWindow->MaxWidth;
    OldMinHeight = MainWindow->MinHeight;
    OldMaxHeight = MainWindow->MaxHeight;
    WindowLimits(MainWindow, (long) MainWindow->Width, (long) MainWindow->Height,
		    (long) MainWindow->Width, (long) MainWindow->Height);
}

void EnableSizing()
{
    WindowLimits(MainWindow, (long) OldMinWidth, (long) OldMinHeight,
		    (long) OldMaxWidth, (long) OldMaxHeight);
}

STATIC void PrjNew(SubNum)
USHORT SubNum;
{
    struct Window *window;
    int ID;
    static double HShift = 0.0,
		  VShift = 0.0;
    static double Factor = 3.0;
    double Width = RightEdge - LeftEdge,
	   Height = TopEdge - BottomEdge,
	   NewLeftEdge = LeftEdge,
	   NewTopEdge = TopEdge,
	   NewRightEdge = RightEdge,
	   NewBottomEdge = BottomEdge;

    /* Stuff for the ABSOLUTE requester */

    static struct IntuiText RatioText = {
	MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 90, NULL,
	(UBYTE *) "Ratio:                    ", NULL    };
    static struct IntuiText AbsText = {
	MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 10, NULL,
	(UBYTE *) "Select an absolute position", &RatioText };
    static struct IntuiText LRTBText[] = {
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
	    (UBYTE *) "Left", NULL  },
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
	    (UBYTE *) "Right", NULL },
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
	    (UBYTE *) "Top", NULL   },
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
	    (UBYTE *) "Bottom", NULL    }
    };
    static struct StringInfo LRTBinfo[] = {
	{   &Buffer[0][0], &Buffer[4][0], 0, 20, 0  },
	{   &Buffer[1][0], &Buffer[4][0], 0, 20, 0  },
	{   &Buffer[2][0], &Buffer[4][0], 0, 20, 0  },
	{   &Buffer[3][0], &Buffer[4][0], 0, 20, 0  }
    };
    static struct Gadget LRTBGadget[] = {
	{   &LRTBGadget[1], 66, 30, 160, 10,		/* next, LTWH */
	    GADGHCOMP,					/* Flags */
	    RELVERIFY,					/* Activation */
	    STRGADGET | REQGADGET,			/* GadgetType */
	    (APTR) NULL, NULL,                          /* rendering */
	    &LRTBText[0], 0, (APTR) &LRTBinfo[0],       /* "Left" */
	    NEGGADGETID+1, NULL },
	{   &LRTBGadget[2], 66, 45, 160, 10,		/* next, LTWH */
	    GADGHCOMP,
	    RELVERIFY,
	    STRGADGET | REQGADGET,
	    (APTR) NULL, NULL,
	    &LRTBText[1], 0, (APTR) &LRTBinfo[1],       /* Right */
	    NEGGADGETID+1, NULL },
	{   &LRTBGadget[3], 66, 60, 160, 10,		/* next, LTWH */
	    GADGHCOMP,
	    RELVERIFY,
	    STRGADGET | REQGADGET,
	    (APTR) NULL, NULL,
	    &LRTBText[2], 0, (APTR) &LRTBinfo[2],       /* Top */
	    NEGGADGETID+1, NULL },
	{   NULL, 66, 75, 160, 10,			/* next, LTWH */
	    GADGHCOMP,
	    RELVERIFY,
	    STRGADGET | REQGADGET,
	    (APTR) NULL, NULL,
	    &LRTBText[3], 0, (APTR) &LRTBinfo[3],       /* Bottom */
	    NEGGADGETID+1, NULL }
    };
    static struct Requester AbsRequest = {
	NULL, 25, 40, 260, 130, 0,0, &PositiveGadget, NULL,
	&AbsText, 0, 1	};

    /* Stuff for the SHIFT requester */

    static struct IntuiText ShiftText = {
	MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 10, NULL,
	(UBYTE *) "Select a window shift amount", NULL  };
    static struct IntuiText RDText[] = {
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
	    (UBYTE *) "Right", NULL },
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
	    (UBYTE *) "Down", NULL  }
    };
    static struct Gadget RDGadget[] = {
	{   &RDGadget[1], 66, 45, 160, 10,	    /* next, LTWH */
	    GADGHCOMP,
	    0,
	    STRGADGET | REQGADGET,
	    (APTR) NULL, NULL,
	    &RDText[0], 0, (APTR) &LRTBinfo[0],     /* Right */
	    0, NULL },
	{   NULL, 66, 60, 160, 10,		    /* next, LTWH */
	    GADGHCOMP,
	    0,
	    STRGADGET | REQGADGET,
	    (APTR) NULL, NULL,
	    &RDText[1], 0, (APTR) &LRTBinfo[1],     /* Down */
	    0, NULL }
    };
    static struct Requester ShiftRequest = {
	NULL, 25, 40, 260, 130, 0,0, &PositiveGadget, NULL,
	&ShiftText, 0, 1    };

    /* Stuff for the ZOOM requester */

    static struct IntuiText ZoomText = {
	MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 10, NULL,
	(UBYTE *) "Select a zoom center", NULL  };
    static struct IntuiText RIFText[] = {
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
	    (UBYTE *) "X:Real", NULL },
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
	    (UBYTE *) "Y:Imag", NULL  },
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -56, 0, NULL,
	    (UBYTE *) "Factor", NULL  }
    };
    static struct Gadget RIFGadget[] = {
	{   &RIFGadget[1], 66, 30, 160, 10,	     /* next, LTWH */
	    GADGHCOMP,
	    0,
	    STRGADGET | REQGADGET,
	    (APTR) NULL, NULL,
	    &RIFText[0], 0, (APTR) &LRTBinfo[0],    /* Re */
	    0, NULL },
	{   &RIFGadget[2], 66, 45, 160, 10,	    /* next, LTWH */
	    GADGHCOMP,
	    0,
	    STRGADGET | REQGADGET,
	    (APTR) NULL, NULL,
	    &RIFText[1], 0, (APTR) &LRTBinfo[1],    /* Im */
	    0, NULL },
	{   NULL, 66, 60, 160, 10,		    /* next, LTWH */
	    GADGHCOMP,
	    0,
	    STRGADGET | REQGADGET,
	    (APTR) NULL, NULL,
	    &RIFText[2], 0, (APTR) &LRTBinfo[2],    /* Factor */
	    0, NULL }
    };
    static struct Requester ZoomRequest = {
	NULL, 25, 40, 260, 130, 0,0, &PositiveGadget, NULL,
	&ZoomText, 0, 1    };

    switch (SubNum) {
    case PNRED:
	if (MouseStatus != FLASHING) return;
	else {
	    register SHORT w = MainWindow -> GZZWidth,
			   h = MainWindow -> GZZHeight;
	    register SHORT X1, Y1, X2, Y2;

	    /* If you cast less, Aztec seems to do it wrong... */
	    X1 = (-(long)FrameX1 * w) / ((long)FrameX2 - (long)FrameX1);
	    Y1 = (-(long)FrameY1 * h) / ((long)FrameY2 - (long)FrameY1);
	    X2 = ((long)(w-1-FrameX1) * w) / ((long)FrameX2 - (long)FrameX1)
		- 1;
	    Y2 = ((long)(h-1-FrameY1) * h) / ((long)FrameY2 - (long)FrameY1)
		- 1;

	    NewLeftEdge   = LeftEdge + X1 * CXStep;
	    NewRightEdge  = LeftEdge + X2 * CXStep;
	    NewTopEdge	  =  TopEdge - Y1 * CYStep;
	    NewBottomEdge =  TopEdge - Y2 * CYStep;

	    skipto pnabs;
	}
    case PNENL:
	if (MouseStatus != FLASHING) return;

	NewLeftEdge   = LeftEdge + FrameX1 * CXStep;
	NewRightEdge  = LeftEdge + FrameX2 * CXStep;
	NewTopEdge    =  TopEdge - FrameY1 * CYStep;
	NewBottomEdge =  TopEdge - FrameY2 * CYStep;
	skipto pnabs;
    case PNSHF:
	NegativeGadget.NextGadget = &RDGadget[0];
	do {
	    sprintf(Buffer[0], "%1.6g",HShift);
	    sprintf(Buffer[1], "%1.6g",VShift);

	    window = MyRequest(&ShiftRequest, MainWindow);
	    ID = WaitMyRequest(window);
	    EndMyRequest(&ShiftRequest, window, MainWindow);
	    if (ID == NEGGADGETID) return;

	} while (sscanf(Buffer[0], "%lf", &HShift)+
		sscanf(Buffer[1], "%lf", &VShift) != 2);

	NewLeftEdge   = LeftEdge + HShift * Width;
	NewRightEdge  = RightEdge + HShift * Width;
	NewTopEdge    = TopEdge - VShift * Height;
	NewBottomEdge = BottomEdge - VShift * Height;

	skipto pnabs;
    case PNZI:
    case PNZO: {
	double ReMid, ImMid;

	if (MouseStatus == NOTFRAMING) {
	    ReMid = (RightEdge + LeftEdge) / 2.0;
	    ImMid = (TopEdge + BottomEdge) / 2.0;
	} else {
	    ReMid = ReMouse;
	    ImMid = ImMouse;
	}

	NegativeGadget.NextGadget = &RIFGadget[0];
	do {
	    sprintf(Buffer[0], "%1.6g",ReMid);
	    sprintf(Buffer[1], "%1.6g",ImMid);
	    sprintf(Buffer[2], "%1.6g",Factor);

	    window = MyRequest(&ZoomRequest, MainWindow);
	    ID = WaitMyRequest(window);
	    EndMyRequest(&ZoomRequest, window, MainWindow);
	    if (ID == NEGGADGETID) return;

	} while (sscanf(Buffer[0], "%lf", &ReMid)+
		 sscanf(Buffer[1], "%lf", &ImMid)+
		 sscanf(Buffer[2], "%lf", &Factor) != 3);
	if (SubNum == PNZI) {
	    if (Factor == 0.0) {
		Factor = 1.0;
	    }
	    Width /= Factor;
	    Height /= Factor;
	} else {
	    Width *= Factor;
	    Height *= Factor;
	}
	NewLeftEdge   = ReMid - Width / 2.0;
	NewTopEdge    = ImMid + Height / 2.0;
	NewRightEdge  = NewLeftEdge + Width;
	NewBottomEdge = NewTopEdge - Height;
	skipto pnabs;
	}
    case PNABS:
	NewLeftEdge = LeftEdge;
	NewRightEdge = RightEdge;
	NewTopEdge = TopEdge;
	NewBottomEdge = BottomEdge;

pnabs:
	NegativeGadget.NextGadget = &LRTBGadget[0];
	sprintf(Buffer[0], "%1.10g", NewLeftEdge);
	sprintf(Buffer[1], "%1.10g", NewRightEdge);
	sprintf(Buffer[2], "%1.10g", NewTopEdge);
	sprintf(Buffer[3], "%1.10g", NewBottomEdge);
	sprintf(RatioText.IText+7, "%1.4f     ", Ratio(NewLeftEdge,
		NewRightEdge, NewTopEdge, NewBottomEdge, MainWindow));

	do {
	    window = MyRequest(&AbsRequest, MainWindow);

	    while ( (ID = WaitMyRequest(window) ) > NEGGADGETID) {
		sscanf(Buffer[0], "%lf", &NewLeftEdge);
		sscanf(Buffer[1], "%lf", &NewRightEdge);
		sscanf(Buffer[2], "%lf", &NewTopEdge);
		sscanf(Buffer[3], "%lf", &NewBottomEdge);
		sprintf(RatioText.IText+7, "%1.4f     ",
		    Ratio(NewLeftEdge, NewRightEdge, NewTopEdge,
		    NewBottomEdge, MainWindow));

		PrintIText(AbsRequest.ReqLayer->rp, &RatioText, 0L, 0L);
	    }

	    EndMyRequest(&AbsRequest, window, MainWindow);

	} while (sscanf(Buffer[0], "%lf", &NewLeftEdge)+
		 sscanf(Buffer[1], "%lf", &NewRightEdge)+
		 sscanf(Buffer[2], "%lf", &NewTopEdge)+
		 sscanf(Buffer[3], "%lf", &NewBottomEdge) < 4);

	if (ID != POSGADGETID) return;

	LeftEdge = NewLeftEdge;
	RightEdge = NewRightEdge;
	TopEdge = NewTopEdge;
	BottomEdge = NewBottomEdge;

	StopFraming();
	StopDrawing();

	break;
    }
    DrawPicture((bool)FALSE);   /* Don't fill in */
}

float Ratio(l, r, t, b, window)
double l, r, t, b;
struct Window *window;
{
    float PixelRatio;
    float ReImRatio;

    if (t == b) t = b+1;    /* You never know... */

    PixelRatio = (float) window->GZZWidth / window->GZZHeight;

    if (window->WScreen->ViewPort.Modes & HIRES) PixelRatio /= 2;
    if (window->WScreen->ViewPort.Modes & LACE) PixelRatio *= 2;
    ReImRatio = (r - l)/(t - b);

    return ReImRatio / PixelRatio;
}

void Parameters()
{
    struct Window *window;
    int ID;
    int NewMaxDepth, NewRangeWidth, NewWBwidth, NewWBheight;

    static struct IntuiText ParamText = {
	MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, 10, 10, NULL,
	(UBYTE *) "Select these parameters", NULL   };
    static struct IntuiText ParmText[] = {
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -120, 0, NULL,
	    (UBYTE *) "Max depth", NULL },
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -120, 0, NULL,
	    (UBYTE *) "Range width", NULL   },
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -120, 0, NULL,
	    (UBYTE *) "Screen width", NULL  },
	{   MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE, -120, 0, NULL,
	    (UBYTE *) "Screen height", NULL  }
    };
    static struct StringInfo Parminfo[] = {
	{   &Buffer[0][0], &Buffer[4][0], 0, 20, 0  },
	{   &Buffer[1][0], &Buffer[4][0], 0, 20, 0  },
	{   &Buffer[2][0], &Buffer[4][0], 0, 20, 0  },
	{   &Buffer[3][0], &Buffer[4][0], 0, 20, 0  }
    };
    static struct Gadget ParmGadget[] = {
	{   &ParmGadget[1], 130, 30, 96, 10,		/* next, LTWH */
	    GADGHCOMP,					/* Flags */
	    RELVERIFY | LONGINT,			/* Activation */
	    STRGADGET | REQGADGET,			/* GadgetType */
	    (APTR) NULL, NULL,                          /* rendering */
	    &ParmText[0], 0, (APTR) &Parminfo[0],       /* "MaxDepth" */
	    0, NULL },
	{   &ParmGadget[2], 130, 45, 96, 10,		/* next, LTWH */
	    GADGHCOMP,
	    RELVERIFY | LONGINT,
	    STRGADGET | REQGADGET,
	    (APTR) NULL, NULL,
	    &ParmText[1], 0, (APTR) &Parminfo[1],       /* "RangeWidth" */
	    0, NULL },
	{   &ParmGadget[3], 130, 60, 96, 10,		/* next, LTWH */
	    GADGHCOMP,
	    RELVERIFY | LONGINT,
	    STRGADGET | REQGADGET,
	    (APTR) NULL, NULL,
	    &ParmText[2], 0, (APTR) &Parminfo[2],       /* "Screen width" */
	    0, NULL },
	{   NULL, 130, 75, 96, 10,			/* next, LTWH */
	    GADGHCOMP,
	    RELVERIFY | LONGINT,
	    STRGADGET | REQGADGET,
	    (APTR) NULL, NULL,
	    &ParmText[3], 0, (APTR) &Parminfo[3],       /* "Screen height" */
	    0, NULL }
    };
    static struct Requester ParmRequest = {
	NULL, 25, 40, 260, 130, 0,0, &PositiveGadget, NULL,
	&ParamText, 0, 1    };

    /* Stuff for the PARAMETERS requester */
    NegativeGadget.NextGadget = &ParmGadget[0];
    Parminfo[0].LongInt = MaxDepth;
    Parminfo[1].LongInt = RangeWidth;
    Parminfo[2].LongInt = WBWidth;
    Parminfo[3].LongInt = WBHeight;
    do {
	sprintf(Buffer[0], "%ld", Parminfo[0].LongInt);
	sprintf(Buffer[1], "%ld", Parminfo[1].LongInt);
	sprintf(Buffer[2], "%ld", Parminfo[2].LongInt);
	sprintf(Buffer[3], "%ld", Parminfo[3].LongInt);

	window = MyRequest(&ParmRequest, MainWindow);
	ID = WaitMyRequest(window);
	EndMyRequest(&ParmRequest, window, MainWindow);
	if (ID == NEGGADGETID) return;

	NewMaxDepth   = Parminfo[0].LongInt;
	NewRangeWidth = Parminfo[1].LongInt;
	NewWBwidth    = Parminfo[2].LongInt;
	NewWBheight   = Parminfo[3].LongInt;
    } while ( NewMaxDepth < 0 || NewMaxDepth > MAXDEPTH ||
	      NewRangeWidth < 0 || NewRangeWidth > MAXDEPTH );

    if (NewRangeWidth != RangeWidth)    InitPenTable();
    MaxDepth = NewMaxDepth;
    RangeWidth = NewRangeWidth;

    if ((NewWBwidth != WBWidth || NewWBheight != WBHeight) && Sure()) {
	 WBWidth = NewWBwidth;
	 WBHeight = NewWBheight;
	 ReInitDisplay();
    }
}

void UpdateCheckmarks()
{
    UpdateOptColorCm();
    UpdateOptDrawResCm();
    UpdateOptViewResCm();
    UpdateOptPriCm();
    UpdateDrwCm();
}

void UpdateOptColorCm()
{
    SelectMenu(MENU(OPTMENU, OPTCOL, OCSEL), (bool)(PenTableMode == SELECT));
    SelectMenu(MENU(OPTMENU, OPTCOL, OCMOD), (bool)(PenTableMode == MODULO));
    SelectMenu(MENU(OPTMENU, OPTCOL, OCRAN), (bool)(PenTableMode == RANGES));
}

void UpdateOptDrawResCm()
{
    SelectMenu(MENU(OPTMENU, OPTRES, ORNRM), (bool)(PixelStep == 1));
    SelectMenu(MENU(OPTMENU, OPTRES, OR12 ), (bool)(PixelStep == 2));
    SelectMenu(MENU(OPTMENU, OPTRES, OR13 ), (bool)(PixelStep == 3));
    SelectMenu(MENU(OPTMENU, OPTRES, OR14 ), (bool)(PixelStep == 4));
}

void UpdateOptViewResCm()
{
    SelectMenu(MENU(OPTMENU, OPTRES, ORHI ),
	       (bool)((MandelNScreen.ViewModes & HIRES) != 0));
    SelectMenu(MENU(OPTMENU, OPTRES, ORILC),
	       (bool)((MandelNScreen.ViewModes & LACE) != 0));
    SelectMenu(MENU(OPTMENU, OPTRES, OREHB),
	       (bool)((MandelNScreen.ViewModes & EXTRA_HALFBRITE) != 0));
    SelectMenu(MENU(OPTMENU, OPTRES, ORBCK),
	       (bool)((MainWindow->Flags & BORDERLESS) != 0));
}

void UpdateOptPriCm()
{
    SelectMenu(MENU(OPTMENU, OPTPRI, OPNOR), (bool)(DrawPri == 0));
    SelectMenu(MENU(OPTMENU, OPTPRI, OPLOW), (bool)(DrawPri <  0));
}

void UpdateFunCm()
{
    SelectMenu(MENU(DRWMENU, DRWFUN, DF1), (bool)(FunctionNr == DF1-DF1));
    SelectMenu(MENU(DRWMENU, DRWFUN, DF2), (bool)(FunctionNr == DF2-DF1));
    SelectMenu(MENU(DRWMENU, DRWFUN, DF3), (bool)(FunctionNr == DF3-DF1));
    SelectMenu(MENU(DRWMENU, DRWFUN, DFUPF), (bool)(FunctionNr == DFUPF-DF1));
    SelectMenu(MENU(DRWMENU, DRWFUN, DF5), (bool)(FunctionNr == DF5-DF1));
}

void UpdateIPlotCm()
{
    SelectMenu(MENU(DRWMENU, DRWIPL, DINONE), (bool)(IPlotNr == DINONE-DINONE));
    SelectMenu(MENU(DRWMENU, DRWIPL, DIZ)   , (bool)(IPlotNr == DIZ-DINONE));
}

void UpdateEPlotCm()
{
    SelectMenu(MENU(DRWMENU, DRWEPL, DEDEPTH), (bool)(EPlotNr == DEDEPTH-DEDEPTH));
    SelectMenu(MENU(DRWMENU, DRWEPL, DEZ)    , (bool)(EPlotNr == DEZ-DEDEPTH));
}

void UpdateDrwCm()
{
    UpdateFunCm();
    UpdateIPlotCm();
    UpdateEPlotCm();
}
