/* CircleSquared from Sept. '86 Scientific American "Computer Recreations" column produces wildly colorful but mathematically precise patterns on your Amiga display. There is also a treatment of this topic in the Oct. '86 issue of Computer Language in their "Theory & Practice" column. It doesn't take nearly as long as the generation of a Mandelbrot either. The program is controlled thru standard intuition menus, gadgets, and requesters. Most of the important operating parameters, i.e. corna, cornb, side, and modval, are modifiable thru these gadgets, requesters, menues and such. corna - the X coordinate of the upper left hand corner of the window cornb - the Y coordinate of the upper left hand corner of the window side - the length of the side of the square modval - the modulus value that determines the color of the pixel at the point(i, j) The following calculations are made for each point plotted on the display. Note that this routine, PlotPoints(), was written using the Motorola Fast Floating Point library. x = corna + side * i/linesize y = cornb + side * j/linesize z = x * x + y * y c = z MOD modval The point at coordinates (i,j) is colored with color "c". Note that the palette of colors is also modifiable thru another requester containing sixteen color selection gadgets. Three proportional gadgets allow the modification the Red, Green, and Blue components of the selected color. The CLOSEWINDOW gadget causes the program to exit. Also note that there is a Hi-Res mode of operation. Instead of invoking the program (from the CLI) as "CSquared" include a runtime parameter of "-h" such that the new invocation becomes "CSquared -h". Lo-Res is the default mode of operation. I freely admit that this program is a hack and was strictly done for my own personal entertainment. I am new to C so if you see any wretched code perhaps you will be understanding. (I'm also new to the Amiga.) I am placing this program into the public domain although if you make use of major portions of the code please give credit where credit is due. (I'd like to see my name up in lights, too.) Have fun! This program compiles cleanly under Lattice C version 3.03. No other external routines are required except for some of those found in Lattice's LC.LIB and, of course, AMIGA.LIB. The standard c.o startup code is also used as well. Author: Bill DuPree (with many thanks to Rob Peck) Date: 09/23/86 Address BIX mail to bdupree. Address written correspondence to: Bill DuPree 434 W. Wellington #505 Chicago, IL. 60657 */ /* DEFINES ********************************************************** */ /* Gadget ID's - Note ID's 1 - 16 are used by color gadgets in palette */ #define RCONTROL 17 #define GCONTROL 18 #define BCONTROL 19 #define NEWMOD 20 #define NEWSIDE 21 #define NEWCORNA 22 #define NEWCORNB 23 #define RESUME 24 /* Screen and Window parameters */ #define XMIN 2 #define YMIN 10 #define DEPTH 4 #define INTUITION_MESSAGE (1< 0", /* IText */ &NCATxt /* NextText */ }; struct IntuiText NSTxt = { 0, 1, /* FrontPen, BackPen */ JAM2, /* DrawMode */ 8, 26, /* LeftEdge, TopEdge */ NULL, /* ITextFont */ "Enter a new side value", /* IText */ &NSRange /* NextText */ }; struct IntuiText ModRange = { 2, 1, /* FrontPen, BackPen */ JAM2, /* DrawMode */ 56, 16, /* LeftEdge, TopEdge */ NULL, /* ITextFont */ "(2 <= modulus <= 16)", /* IText */ &NSTxt /* NextText */ }; struct IntuiText ModPrompt = { 0, 1, /* FrontPen, BackPen */ JAM2, /* DrawMode */ 8, 6, /* LeftEdge, TopEdge */ NULL, /* ITextFont */ "Enter a new modulus value", /* IText */ &ModRange /* NextText */ }; SHORT NumCoords[10] = { 0,0, 217,0, 217,97, 0,97, 0,0 }; struct Border NumReqBord = { 1, 1, /* LeftEdge, TopEdge */ 0, 1, JAM1, /* FrontPen, BackPen, DrawMode */ 5, /* Count */ &NumCoords[0], /* XY */ NULL /* NextBorder */ }; struct Requester NumericParms = { NULL, /* OlderRequest */ 2, 12, /* LeftEdge, TopEdge */ 220, 100, /* Width, Height */ 0, 0, /* RelLeft, RelTop */ &NewModulus, /* ReqGadget */ &NumReqBord, /* ReqBorder */ &ModPrompt, /* ReqText */ 0, /* Flags */ 1, /* BackFill */ NULL, /* ReqLayer */ {NULL}, /* Pad */ NULL, /* ImageBmap */ NULL, /* RWindow (system) */ {NULL} /* Pad */ }; SHORT RCoord2[10] = { 0,0, 247,0, 247,47, 0,47, 0,0 }; struct Border ReqBord2 = { 1, 1, /* LeftEdge, TopEdge */ 0, 1, JAM1, /* FrontPen, BackPen, DrawMode */ 5, /* Count */ &RCoord2[0], /* XY */ NULL /* NextBorder */ }; struct IntuiText BadValMsg2 = { 0, 1, /* FrontPen, BackPen */ JAM2, /* DrawMode */ 6, 14, /* LeftEdge, TopEdge */ NULL, /* ITextFont */ "Value was not changed", /* IText */ NULL /* NextText */ }; UBYTE ValMsg[32]; struct IntuiText BadValMsg = { 0, 1, /* FrontPen, BackPen */ JAM2, /* DrawMode */ 6, 4, /* LeftEdge, TopEdge */ NULL, /* ITextFont */ &ValMsg[0], /* IText */ &BadValMsg2 /* NextText */ }; struct Requester BadNum = { NULL, /* OlderRequest */ 35, 20, /* LeftEdge, TopEdge */ 250, 50, /* Width, Height */ 0, 0, /* RelLeft, RelTop */ &Resume, /* ReqGadget */ &ReqBord2, /* ReqBorder */ &BadValMsg, /* ReqText */ 0, /* Flags */ 1, /* BackFill */ NULL, /* ReqLayer */ {NULL}, /* Pad */ NULL, /* ImageBmap */ NULL, /* RWindow (system) */ {NULL} /* Pad */ }; struct IntuiText PaletteText = { 0, 1, /* FrontPen, BackPen */ JAM2, /* DrawMode */ 0, 0, /* LeftEdge, TopEdge */ NULL, /* ITextFont */ "Palette ", /* IText */ NULL /* NextText */ }; struct IntuiText NumericText = { 0, 1, /* FrontPen, BackPen */ JAM2, /* DrawMode */ 0, 0, /* LeftEdge, TopEdge */ NULL, /* ITextFont */ "Numeric ", /* IText */ NULL /* NextText */ }; struct IntuiText ParmText = { 0, 1, /* FrontPen, BackPen */ JAM2, /* DrawMode */ 0, 0, /* LeftEdge, TopEdge */ NULL, /* ITextFont */ "Parameters", /* IText */ NULL /* NextText */ }; struct IntuiText NewText = { 0, 1, /* FrontPen, BackPen */ JAM2, /* DrawMode */ 0, 0, /* LeftEdge, TopEdge */ NULL, /* ITextFont */ "New ", /* IText */ NULL /* NextText */ }; struct IntuiText StopText = { 0, 1, /* FrontPen, BackPen */ JAM2, /* DrawMode */ 0, 0, /* LeftEdge, TopEdge */ NULL, /* ITextFont */ "Stop ", /* IText */ NULL /* NextText */ }; struct IntuiText StartText = { 0, 1, /* FrontPen, BackPen */ JAM2, /* DrawMode */ 0, 0, /* LeftEdge, TopEdge */ NULL, /* ITextFont */ "Start ", /* IText */ NULL /* NextText */ }; struct MenuItem PaletteItem = { NULL, /* NextItem */ 79, 12, 80, 8, /* LeftEdge, TopEdge, Width, Height */ ITEMTEXT | ITEMENABLED | HIGHCOMP, /* Flags */ 0, /* MutualExclude */ (APTR) &PaletteText, /* ItemFill */ NULL, /* SelectFill */ 0, /* Command */ NULL, /* SubItem */ 0 /* NextSelect */ }; struct MenuItem NumItem = { &PaletteItem, /* NextItem */ 79, 2, 80, 8, /* LeftEdge, TopEdge, Width, Height */ ITEMTEXT | ITEMENABLED | HIGHCOMP, /* Flags */ 0, /* MutualExclude */ (APTR) &NumericText, /* ItemFill */ NULL, /* SelectFill */ 0, /* Command */ NULL, /* SubItem */ 0 /* NextSelect */ }; struct MenuItem ParmItem = { NULL, /* NextItem */ 0, 30, 80, 8, /* LeftEdge, TopEdge, Width, Height */ ITEMTEXT | ITEMENABLED | HIGHCOMP, /* Flags */ 0, /* MutualExclude */ (APTR) &ParmText, /* ItemFill */ NULL, /* SelectFill */ 0, /* Command */ &NumItem, /* SubItem */ 0 /* NextSelect */ }; struct MenuItem NewItem = { &ParmItem, /* NextItem */ 0, 20, 80, 8, /* LeftEdge, TopEdge, Width, Height */ ITEMTEXT | ITEMENABLED | HIGHCOMP, /* Flags */ 0, /* MutualExclude */ (APTR) &NewText, /* ItemFill */ NULL, /* SelectFill */ 0, /* Command */ NULL, /* SubItem */ 0 /* NextSelect */ }; struct MenuItem StopItem = { &NewItem, /* NextItem */ 0, 10, 80, 8, /* LeftEdge, TopEdge, Width, Height */ ITEMTEXT | ITEMENABLED | HIGHCOMP, /* Flags */ 0, /* MutualExclude */ (APTR) &StopText, /* ItemFill */ NULL, /* SelectFill */ 0, /* Command */ NULL, /* SubItem */ 0 /* NextSelect */ }; struct MenuItem StartItem = { &StopItem, /* NextItem */ 0, 0, 80, 8, /* LeftEdge, TopEdge, Width, Height */ ITEMTEXT | HIGHCOMP, /* Flags */ 0, /* MutualExclude */ (APTR) &StartText, /* ItemFill */ NULL, /* SelectFill */ 0, /* Command */ NULL, /* SubItem */ 0 /* NextSelect */ }; struct Menu CCMenu = { NULL, /* NextMenu */ 16, 0, 56, 0, /* LeftEdge, TopEdge, Width, Height */ MENUENABLED, /* Flags */ "Options", /* MenuName */ &StartItem /* FirstItem */ }; struct NewWindow nwGraphics = { 0, 0, /* start position */ 0, 0, /* width, height are filled in later */ 0, 1, /* detail pen, block pen */ MENUPICK | GADGETUP | CLOSEWINDOW, /* IDCMP flags */ WINDOWCLOSE | SMART_REFRESH | NOCAREREFRESH | ACTIVATE, /* window flags */ NULL, /* pointer to first user gadget */ NULL, /* pointer to user checkmark */ "", /* window title */ NULL, /* pointer to screen (later) */ NULL, /* pointer to superbitmap */ 50,40,0,0, /* sizing limits min and max */ CUSTOMSCREEN /* type of screen in which to open */ }; struct NewScreen Any_Res_Screen = { 0, 0, /* LeftEdge, TopEdge */ 0, 0, /* Width, Height are filled in later */ DEPTH, /* Depth */ 0, 1, /* DetailPen, BlockPen */ 0, /* ViewModes */ CUSTOMSCREEN, /* Type */ NULL, /* Font */ "", /* DefaultTitle */ NULL, /* Gadgets */ NULL /* CustomBitMap */ }; struct RastPort *rpG; /* rastport at which to render */ struct IntuiMessage *message; /* the message the IDCMP sends us */ struct Screen *sG; struct Window *wG; UWORD colortable[] = { 0x000, 0xfff, /* black, white */ 0xf00, 0xf70, /* ruby, orange */ 0xff0, 0x7f0, /* yellow, lime */ 0x0f0, 0x0f7, /* green, aqua */ 0x0ff, 0x07f, /* turquoise, blue-green */ 0x00f, 0x70f, /* blue, maroon */ 0xf0f, 0x707, /* purple, deep purple */ 0xa84, 0x888 }; /* brown, gray */ main(argc, argv) int argc; char *argv[]; { int problem; struct ColorMap *oldcmap; /* Let's initialize some stuff first */ PlanePtr = /* get some chip RAM for gadget image data */ (struct MyImageData *) AllocMem(16 * sizeof(struct MyImageData), MEMF_CHIP | MEMF_CLEAR); if (PlanePtr == 0) { printf("Memory allocation error\n"); exit(20); } strcpy(NSString,"160"); /* set initial side value */ strcpy(NCAString,"-15"); /* set initial corner values */ strcpy(NCBString,"-20"); strcpy(NMString,"2"); /* set initial modulus value */ InitGadgetList(); /* Put together palette gadgets */ if ((argc == 2) && ((strcmp(argv[1],"-h") == 0) || (strcmp(argv[1],"-H") == 0))) { MaxHeight = 400; MaxWidth = 640; Any_Res_Screen.ViewModes = LACE | HIRES; } else { MaxHeight = 200; MaxWidth = 320; } /* Initialize any dynamic screen and window parameters */ Any_Res_Screen.Width = MaxWidth; Any_Res_Screen.Height = MaxHeight; nwGraphics.Width = MaxWidth; nwGraphics.Height = MaxHeight; nwGraphics.MaxWidth = MaxWidth; nwGraphics.MaxHeight = MaxHeight; /* Open all necessary libraries */ if ((MathBase = OpenLibrary("mathffp.library",0)) < 1) { printf("mathffp library open failed\n"); problem = 100; goto cleanup0; } if ((MathTransBase = OpenLibrary("mathtrans.library",0)) < 1) { printf("mathtrans library open failed\n"); problem = 200; goto cleanup0; } GfxBase = OpenLibrary("graphics.library", 0); if (GfxBase == NULL) { printf("graphics library open failed\n"); problem = 1; goto cleanup1; } IntuitionBase = OpenLibrary("intuition.library", 0); if (IntuitionBase == NULL) { printf("intuition library open failed\n"); problem = 2; goto cleanup1; } /* We need a custom screen for this stuff */ sG = OpenScreen(&Any_Res_Screen); if ( sG == NULL) { printf("open screen failed\n"); problem = 3; goto cleanup1a; } /* Let's substitute our own color map */ oldcmap = sG->ViewPort.ColorMap; sG->ViewPort.ColorMap = (struct ColorMap *) GetColorMap(16); LoadRGB4(&(sG->ViewPort), colortable, 16); nwGraphics.Screen = sG; wG = OpenWindow(&nwGraphics); /* open a window for graphics*/ if ( wG == NULL ) { printf ("open window failed\n"); problem = 4; goto cleanup2; } rpG = wG->RPort; /* set a rastport pointer */ SetNumericValues(); /* Set window title, initialize values */ SetMenuStrip(wG, &CCMenu); /* Attach a menu to the window */ /* find out which signals to wait for.... Intuition allocates a signal bit for an IDCMP */ intuitionMsgBit = wG->UserPort->mp_SigBit; /* This code assumes that the only events we expect to wake up for are messages from intuition arriving at the IDCMP */ TimeToStop = FALSE; NotDone = TRUE; do { message = NULL; /* no messages yet */ if ((TimeToStop) || (NotDone = PlotPoints())) { /* display graphics rendition */ ClearMenuStrip(wG); /* Enable start MenuItem */ StartItem.Flags |= ITEMENABLED; StopItem.Flags &= ~ITEMENABLED; SetMenuStrip(wG, &CCMenu); wakeupmask = Wait(INTUITION_MESSAGE); /* Clear signal */ if (message == NULL) message = (struct IntuiMessage *) GetMsg(wG->UserPort); do { /* empty the port then try to handle the event */ class = message->Class; code = message->Code; qualifier = message->Qualifier; address = message->IAddress; ReplyMsg(message); if ((NotDone = HandleEvent()) == FALSE) break; } while( (message = (struct IntuiMessage *) GetMsg(wG->UserPort) ) != NULL); } } while (NotDone); /* keep going until done */ problem = 0; cleanup3: ClearMenuStrip(wG); CloseWindow(wG); cleanup2: FreeColorMap(sG->ViewPort.ColorMap); sG->ViewPort.ColorMap = oldcmap; CloseScreen(sG); cleanup1a: if (GfxBase != NULL) CloseLibrary(GfxBase); cleanup1: if (IntuitionBase != NULL) CloseLibrary(IntuitionBase); cleanup0: if (MathTransBase != NULL) { RemLibrary(MathTransBase); /* allow library to be expunged */ CloseLibrary(MathTransBase); } if (MathBase != NULL) { CloseLibrary(MathBase); } FreeMem(PlanePtr, 16 * sizeof(struct MyImageData)); if(problem > 0) exit(problem+1000); else return(0); } /* This routine does the actual plotting of the points */ int PlotPoints() { int c, ExitFlag; register int i, j; union kludge x, y, z, point5, linesize; /* Initialize some parameters. */ point5.num = 0.5; point5.i = SPFieee(point5.i); /* used for rounding */ linesize.i = MaxHeight - 3 - YMIN; linesize.i = SPFlt(linesize.i); for (i = XMIN; i <= MaxWidth-3; i++) { /* one iteration per vert. line */ for (j = YMIN; j <= MaxHeight-3; j++) { /* one iteration per pixel */ /* Compute: x = corna + side * i/linesize y = cornb + side * j/linesize z = x * x + y * y c = z MOD modval */ x.i = SPAdd(corna.i, SPMul(side.i, SPDiv(linesize.i, SPFlt(i)))); y.i = SPAdd(cornb.i, SPMul(side.i, SPDiv(linesize.i, SPFlt(j)))); z.i = SPAdd(SPMul(x.i, x.i), SPMul(y.i, y.i)); c = SPFix(SPAdd(z.i, point5.i)); c %= modval; SetAPen(rpG, c); /* Set new color for rendering pixel */ WritePixel(rpG, i, j); } /* we poll?!!! for a message at the end of each vertical line */ /* It is okay to poll in this case since we have plenty of work */ /* to do if no message is available */ if ((message = (struct IntuiMessage *) GetMsg(wG->UserPort)) != NULL) if (!(ExitFlag = CheckEvent())) return(ExitFlag); else if (TimeToStop) break; } TimeToStop = TRUE; return(TRUE); } /* This routine returns FALSE to PlotPoints() is a CLOSEWINDOW event */ /* is detected. Other events are handled thru an event handler. */ int CheckEvent() { int bugout; /* Note that the following call to Wait() will not put us to sleep because there is already a message in the port awaiting Reply(). The only reason that we call Wait() is to clear the signal. */ wakeupmask = Wait(INTUITION_MESSAGE); /* Clear signal */ do { /* empty the port then try to handle the event */ class = message->Class; code = message->Code; qualifier = message->Qualifier; address = message->IAddress; ReplyMsg(message); if ((bugout = HandleEvent()) == FALSE) break; } while((message = (struct IntuiMessage *) GetMsg(wG->UserPort)) != NULL); return(bugout); } int HandleEvent() /* Process events */ { switch(class) { case CLOSEWINDOW: return(FALSE); break; case MENUPICK: MenuEvent(); /* process menu events */ break; } class = 0; code = 0; qualifier = 0; address = 0; return(TRUE); } #define OPTIONS 0 #define START 0 #define STOP 1 #define NEW 2 #define PARAMETERS 3 #define NUMERIC 0 #define PALETTE 1 /* All menu events are funneled into this routine and processed here */ MenuEvent() { USHORT MenuNumber, fnMenu, fnItem, fnSubItem; struct MenuItem *ItemAddress(), *Item; MenuNumber = code; while (MenuNumber != MENUNULL) { Item = ItemAddress(&CCMenu, MenuNumber); fnMenu = MENUNUM(MenuNumber); fnItem = ITEMNUM(MenuNumber); fnSubItem = SUBNUM(MenuNumber); switch(fnMenu) { case OPTIONS: switch(fnItem) { case START: /* Start PlotPoints() plotting */ ClearMenuStrip(wG); StartItem.Flags &= ~ITEMENABLED; StopItem.Flags |= ITEMENABLED; SetMenuStrip(wG, &CCMenu); TimeToStop = FALSE; break; case STOP: /* stop plotting */ TimeToStop = TRUE; break; case NEW: /* Clear screen and stop plotting */ TimeToStop = TRUE; SetAPen(rpG, 0); SetOPen(rpG, 0); RectFill(rpG, XMIN, YMIN, MaxWidth-2, MaxHeight-2); break; case PARAMETERS: /* process parameter subitems */ switch(fnSubItem) { case NUMERIC: /* modify numeric parms */ ParmReq(&NumericParms); SetNumericValues(); break; case PALETTE: /* modify palette */ ParmReq(&ColorParms); break; } break; } break; } MenuNumber = Item->NextSelect; } } /* This routine clones the 16 color gadgets for the palette requester */ InitGadgetList() { SHORT i, j, k; struct Gadget *CGadg; struct Image *CImage, *AImage; struct MyImageData *PPtr; CGadg = ColorGadg; CImage = ColorImage; AImage = AltImage; PPtr = PlanePtr; for(i = 0; i <= 15; i++) { /* Initialize each color selection gadget */ CGadg->NextGadget = CGadg + 1; /* chain them together */ CGadg->LeftEdge = i * 12 + 14; CGadg->TopEdge = 56; CGadg->Width = 10; CGadg->Height = 8; CGadg->Flags = GADGIMAGE | GADGHIMAGE; CGadg->Activation = RELVERIFY | TOGGLESELECT; CGadg->GadgetType = BOOLGADGET | REQGADGET; CGadg->GadgetRender = (APTR) &ColorImage[i]; CGadg->SelectRender = (APTR) &AltImage[i]; CGadg->GadgetText = NULL; CGadg->MutualExclude = 0; CGadg->SpecialInfo = NULL; CGadg->GadgetID = (USHORT) i + 1; CGadg->UserData = NULL; /* Images for unselected gadgets are colored rectangles */ CImage->LeftEdge = 0; CImage->TopEdge = 0; CImage->Width = 10; CImage->Height = 8; CImage->Depth = 0; CImage->ImageData = NULL; CImage->PlanePick = 0; CImage->PlaneOnOff = (UBYTE) i; CImage->NextImage = NULL; /* Alternate (selected) images are bordered colored rectangles */ AImage->LeftEdge = 0; AImage->TopEdge = 0; AImage->Width = 10; AImage->Height = 8; AImage->Depth = 4; AImage->ImageData = (SHORT *) PPtr; AImage->PlanePick = 0xf; AImage->PlaneOnOff = 0; AImage->NextImage = NULL; /* Construct image data area in CHIP RAM for each gadget */ for (k = 1, j = 0; j <= 3; j++) { if ((k & i) != 0) PPtr->Plane[j] = SelectedOne; else PPtr->Plane[j] = NullOne; k <<= 1; } CGadg++; /* bump pointers */ CImage++; AImage++; PPtr++; } CGadg--; /* tidy up first and last gadgets in the chain */ CGadg->NextGadget = &Resume; ColorGadg[0].Flags |= SELECTED; CurrentColor = 0; SetRGBGadgets(CurrentColor); } /* This routine handles the requester processing. Note that the */ /* requester is passed as a parameter. */ ParmReq(ReqPtr) struct Requester *ReqPtr; { Request(ReqPtr, wG); do { wakeupmask = Wait(INTUITION_MESSAGE); while((message = (struct IntuiMessage *) GetMsg(wG->UserPort)) != NULL) { /* empty the port then try to handle the event */ class = message->Class; code = message->Code; qualifier = message->Qualifier; address = message->IAddress; ReplyMsg(message); /* we do not need to go to the standard event handler since */ /* while the requester is up all we will receive are gadget */ /* events from the IDCMP. Therefore we go to a special */ /* gadget event handler. */ if (GadgetEvent() == TRUE) return(0); } } while (1); } /* This routine handles the requester gadgets and their events */ GadgetEvent() { USHORT GadgID; GadgID = ((struct Gadget *) address)->GadgetID; switch(class) { case GADGETUP: switch(GadgID) { case RESUME: return(TRUE); break; case NEWMOD: break; case RCONTROL: case GCONTROL: case BCONTROL: SetColorRegs(CurrentColor); break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: /* (I'm sure there are better ways of doing this) */ case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: CurrentColor = GadgID - 1; SetRGBGadgets(CurrentColor); ClearColorSel(); ColorGadg[CurrentColor].Flags |= SELECTED; RefreshGadgets(&RGadget, wG, &ColorParms); break; } break; } class = 0; code = 0; qualifier = 0; address = 0; return(FALSE); } /* This routine manages all three proportional gadgets and sets them */ /* up to reflect the currently selected color. */ SetRGBGadgets(Color) USHORT Color; { int rval, gval, bval; struct PropInfo *PIPtr; /* Isolate component values of selected color */ rval = (colortable[Color] >> 8) & 0x000f; gval = (colortable[Color] >> 4) & 0x000f; bval = colortable[Color] & 0x000f; /* Initialize proportional gadgets to reflect the color values */ PIPtr = (struct PropInfo *) RGadget.SpecialInfo; PIPtr->HorizPot = PIPtr->VertPot = (USHORT) rval * 0x0fff; PIPtr = (struct PropInfo *) GGadget.SpecialInfo; PIPtr->HorizPot = PIPtr->VertPot = (USHORT) gval * 0x0fff; PIPtr = (struct PropInfo *) BGadget.SpecialInfo; PIPtr->HorizPot = PIPtr->VertPot = (USHORT) bval * 0x0fff; } /* Routine clears selection flag from all color gadgets. */ /* This is used before re-rendering gadgets. */ ClearColorSel() { int i; struct Gadget *CGadg; CGadg = ColorGadg; for (i = 0; i <= 15; i++) { CGadg->Flags &= ~SELECTED; CGadg++; } } /* This routine reads the values off of the proportional gadgets and */ /* sets that value into the selected color register. The modified */ /* color table is then loaded. */ SetColorRegs(Color) USHORT Color; { LONG rval, gval, bval; struct PropInfo *PIPtr; PIPtr = (struct PropInfo *) RGadget.SpecialInfo; rval = (((PIPtr->HorizPot + 1) * 15) + 0x8000) >> 16; PIPtr = (struct PropInfo *) GGadget.SpecialInfo; gval = (((PIPtr->HorizPot + 1) * 15) + 0x8000) >> 16; PIPtr = (struct PropInfo *) BGadget.SpecialInfo; bval = (((PIPtr->HorizPot + 1) * 15) + 0x8000) >> 16; colortable[Color] = (UWORD) ((rval << 8) | (gval << 4) | bval); LoadRGB4(&(sG->ViewPort), colortable, 16); } /* Routine provides initialization and edit checking for the numeric */ /* parameters. It also constructs the and sets the window title. */ SetNumericValues() { int newmod, newside, SPFlt(); char cvt[10]; stcd_i(NSString, &newside); /* convert parameters to integers */ stcd_i(NCAString, &corna.i); /* or perhaps FFP FLOATs */ strcpy(NCAUndo, NCAString); corna.i = SPFlt(corna.i); stcd_i(NCBString, &cornb.i); strcpy(NCBUndo, NCBString); cornb.i = SPFlt(cornb.i); stcd_i(NMString, &newmod); /* now let's do a little judicious editting */ if ((newmod >= 2) && (newmod <= 16)) { strcpy(NMUndo, NMString); modval = newmod; strcpy(Title, "CircleSquared - Modulus: "); strcat(Title, NMString); SetWindowTitles(wG, Title, -1); } else { /* whoops! - modulus value is out of range */ stci_d(cvt, modval, 10); strcpy(NMString, cvt); strcpy(NMUndo, NMString); strcpy(ValMsg, "Modulus value was out of range"); Request(&BadNum, wG); wakeupmask = Wait(INTUITION_MESSAGE); while((message = (struct IntuiMessage *) GetMsg(wG->UserPort)) != NULL) ReplyMsg(message); } if (newside <= 0) { /* make sure that side value is positive */ stci_d(cvt, sideval, 10); strcpy(NSString, cvt); strcpy(NSUndo, NMString); strcpy(ValMsg, "Side value was out of range"); Request(&BadNum, wG); wakeupmask = Wait(INTUITION_MESSAGE); while((message = (struct IntuiMessage *) GetMsg(wG->UserPort)) != NULL) ReplyMsg(message); } else { strcpy(NSUndo, NSString); sideval = newside; side.i = SPFlt(sideval); } }