home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
500-599
/
ff588.lza
/
FracBlank
/
FracBlank.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-04
|
32KB
|
1,548 lines
/* $Revision Header * Header built automatically - do not edit! *************
*
* (C) Copyright 1991 by Olaf Barthel & MXM
*
* Name .....: FracBlank.c
* Created ..: Friday 18-Jun-91 15:28
* Revision .: 8
*
* Date Author Comment
* ========= ======== ====================
* 09-Sep-91 Olsen Numerous bug fixes.
* 17-Aug-91 Olsen Rewrote sprite blanker code.
* 17-Aug-91 Olsen Added cycle gadget.
* 12-Aug-91 Olsen Added multicolour/monochrome mode.
* 30-Jun-91 Olsen VBlank code revised.
* 29-Jun-91 Olsen Added VBlank interrupt server.
* 21-Jun-91 Olsen Optimizations, cleanups.
* 18-Jun-91 Olsen Created this file!
*
* $Revision Header ********************************************************/
/* Include the specific math pragmas/header files here (is there
* any way to figure this out by taking a look at predefined
* compiler symbols?).
*/
#ifdef MATH_FFP
#include <clib/mathtrans_protos.h>
#include <proto/mathtrans.h>
#include <mffp.h>
#else
#include <m68881.h>
#endif /* MATH_FFP */
#include <math.h>
/* sin -45° = cos -45° (saves precious calculation time). */
#define deg45 (-0.707106781)
/* Hotkey IDs. */
enum { POP_WINDOW,BLANK_SCREEN };
/* Gadget IDs. */
enum { GAD_SCREENTIMEOUT,GAD_PATTERNCHANGE,GAD_HOTKEY,
GAD_BLANKSCREEN,GAD_MONO,GAD_CYCLE,GAD_HIDE,GAD_QUIT };
/* Dimensions of the control panel. */
#define WIDTH 284
#define HEIGHT 113
/* Program revision tag. */
STATIC const UBYTE * const VersTag = "\0$VER: FracBlank 1.8 (9.9.91)";
/* Shared library identifiers. */
extern struct ExecBase *SysBase;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *CxBase,
*IconBase,
*GadToolsBase;
/* Blanker data. */
struct Task *BlankTask;
struct Screen *BlankScreen;
/* Commodities interface data. */
struct MsgPort *CxPort;
CxObj *Broker;
/* Gfx and gadtools data. */
struct Screen *DefaultScreen;
APTR VisualInfo;
struct TextFont *Topaz;
struct Gadget *GadgetList;
struct Gadget *GadgetArray[8];
struct Window *Window;
/* Window zoom data. */
WORD ZoomData[4] = { -1,-1,-1,-1 };
/* Rainbow colour table. */
UWORD Table[75];
/* Key sequence buffers. */
UBYTE HotkeyBuffer[256],BlankScreenBuffer[256];
/* Screen and pattern change timeout. */
ULONG ScreenCount = 0,PatternCount = 0,ScreenTimeout = 60,PatternTimeout = 60;
/* Display mode: monochrome / multicolor. */
BYTE Mono = FALSE,Cycle = TRUE;
/* The default font to be used by the control panel. */
struct TextAttr DefaultFont =
{
(UBYTE *)"topaz.font",
8,
FS_NORMAL,
FPF_ROMFONT
};
/* A new broker definition, Commodities needs this. */
struct NewBroker NewBroker =
{
NB_VERSION,
"FracBlanker",
"Fractal Blanker v1.8",
"Screen Blanker",
NBU_NOTIFY | NBU_UNIQUE,
COF_SHOW_HIDE,
0,NULL,0
};
/* Function prototypes. */
extern VOID __asm MonoPlot(register __a0 PLANEPTR Plane,register __d0 WORD x,register __d1 WORD y,register __d2 UWORD Modulo,register __d3 WORD MaxX,register __d4 WORD MaxY);
extern VOID __asm MultiPlot(register __a0 struct Screen *,register __d0 WORD X,register __d1 WORD Y,register __d2 WORD Colour);
VOID StartBlanker(VOID);
ULONG __regargs Random(ULONG MaxValue);
VOID __saveds Blanker(VOID);
VOID __saveds __stdargs BlankerAction(CxMsg *CxMessage,CxObj *CxObject);
VOID ShutdownCx(VOID);
BYTE __regargs SetupCx(UBYTE **ToolTypes);
VOID __regargs HandleCxMsg(CxMsg *Message);
LONG __saveds __stdargs ShowTime(struct Gadget *SomeGadget,WORD Level);
struct Gadget * CreateAllGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge);
VOID ShutdownWindow(VOID);
VOID __regargs CentreWindow(struct Screen *Screen,WORD *LeftEdge,WORD *TopEdge);
BYTE SetupWindow(VOID);
VOID __regargs CloseAll(LONG ReturnCode);
VOID __regargs OpenAll(int argc,char **argv);
VOID __stdargs main(int argc,char **argv);
/* StartBlanker():
*
* Open the display screen and create the blanker task.
*/
VOID
StartBlanker()
{
if(!BlankScreen)
{
struct Screen *Screen;
if(Screen = OpenScreenTags(NULL,
SA_Behind, TRUE,
SA_Quiet, TRUE,
SA_DisplayID, Mono ? HIRESLACE_KEY : LORES_KEY,
SA_Overscan, OSCAN_MAX,
SA_Depth, Mono ? 1 : 5,
TAG_DONE))
{
struct UCopList *UserCopperList;
/* I had a lot of problems trying to shut down
* the sprite display hardware completely.
* The mouse pointer would pop up again after
* a certain time interval, no matter what I
* did.
*
* Now, Amy, you had your chance, hadn't you?
*
* This is the big one: a user copper list will
* shut down the sprite hardware. Full stop.
*/
if(UserCopperList = (struct UCopList *)AllocMem(sizeof(struct UCopList),MEMF_PUBLIC|MEMF_CLEAR))
{
/* Set up for 3 instruction. */
CINIT(UserCopperList,3);
/* Wait for first line. */
CWAIT(UserCopperList,0,0);
/* Disable sprite DMA. */
CMOVE(UserCopperList,custom . dmacon,BITCLR|DMAF_SPRITE);
/* Terminate copper instruction list. */
CEND(UserCopperList);
/* Install the copper list. */
Screen -> ViewPort . UCopIns = UserCopperList;
/* Link it into the screen copper list. */
RethinkDisplay();
/* Set the background colour to black. */
SetRGB4(&Screen -> ViewPort,0,0x0,0x0,0x0);
/* Display the screen. */
ScreenToFront(Screen);
BlankScreen = Screen;
}
else
CloseScreen(Screen);
}
}
if(BlankScreen)
{
PatternCount = 0;
BlankTask = (struct Task *)CreateTask("FracBlank.task",-20,Blanker,4000);
}
}
/* Random(ULONG MaxValue):
*
* Simple random number generation routine.
*/
ULONG __regargs
Random(ULONG MaxValue)
{
STATIC ULONG RandomSeed = 0xDEAD0123;
RandomSeed = RandomSeed * custom . vhposr + 0xE153766F;
return(RandomSeed % MaxValue);
}
/* Blanker():
*
* The screen blanker itself.
*/
VOID __saveds
Blanker()
{
STATIC BYTE Wheel = 0;
UWORD Colours[32],OffsetX = BlankScreen -> Width >> 1,OffsetY = BlankScreen -> Height >> 1;
float x = 0,y = 0,yy,a,b,c,sx,sy,mag,save;
SetSignal(0,SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E);
/* Are we running in monochrome mode? */
if(Mono)
{
UWORD Modulo = BlankScreen -> RastPort . BitMap -> BytesPerRow;
PLANEPTR Plane = BlankScreen -> RastPort . BitMap -> Planes[0];
/* Provide starting numbers for the fractal
* parameters.
*/
a = (float)Random(300) / 100;
b = (float)Random(100) / 100;
c = (float)Random( 50) / 100;
mag = (float)(1 << (Random(4) + 5)) * deg45;
/* Set up the screen colour table. */
Colours[0] = 0;
Colours[1] = Table[Wheel];
LoadRGB4(&BlankScreen -> ViewPort,Colours,2);
/* Go into fractal generation loop. */
FOREVER
{
/* The original formula looks like
* this:
* ½
* x <- y - SIGN(x) * ABS(b * x - c)
* y <- a - x
*
* I have split the calculation into
* several steps to save time and
* variables.
*/
yy = a - x;
if((save = b * x - c) < 0)
save = -save;
if(x < 0)
x = y + sqrt(save);
else
x = y - sqrt(save);
y = yy;
/* The resulting image appears to have
* been rotated by 45°, so we'll
* rotate the pixel coordinates by -45°
*
* x <- x * cos alpha + y * sin alpha
* y <- -x * sin alpha + y * cos alpha
*
* We also magnify the image (i.e. the
* distribution of pixels) in the following
* lines.
*/
sx = mag * ( x + y);
sy = mag * (-x + y);
/* If the pixel happens to reside within
* the boundaries of the screen, draw it.
*/
MonoPlot(Plane,(WORD)(sx) + OffsetX,(WORD)(sy) + OffsetY,Modulo,BlankScreen -> Width,BlankScreen -> Height);
/* ^D tells the blanker to change the pattern. */
if(SetSignal(0,0) & SIGBREAKF_CTRL_D)
{
SetSignal(0,SIGBREAKF_CTRL_D);
SetRast(&BlankScreen -> RastPort,0);
x = y = 0;
a = (float)Random(300) / 100;
b = (float)Random(100) / 100;
c = (float)Random( 50) / 100;
mag = (float)(1 << (Random(4) + 5)) * deg45;
}
/* ^E tells the blanker to rotate the
* colours.
*/
if(SetSignal(0,0) & SIGBREAKF_CTRL_E)
{
SetSignal(0,SIGBREAKF_CTRL_E);
Colours[1] = Table[Wheel];
LoadRGB4(&BlankScreen -> ViewPort,Colours,2);
Wheel = (Wheel + 1) % 75;
}
}
}
else
{
STATIC UWORD Rainbow[32] =
{
0x0000,0x0F00,0x0F30,0x0F50,
0x0F70,0x0F90,0x0FB0,0x0FD0,
0x0FF0,0x0DF0,0x0BF0,0x09F0,
0x07F0,0x05F0,0x03F0,0x00F0,
0x00D1,0x00B3,0x0095,0x0077,
0x0059,0x003B,0x001D,0x000F,
0x010F,0x030F,0x050F,0x070F,
0x090F,0x0B0F,0x0D0F,0x0F0F
};
UWORD Count = 0;
WORD i;
BYTE Colour = 1,Plus = 1;
struct RastPort *RPort;
a = (float)Random(300) / 100;
b = (float)Random(100) / 100;
c = (float)Random( 50) / 100;
mag = (float)(1 << (Random(4) + 2)) * deg45;
Colours[0] = 0x000;
for(i = 1 ; i < 32 ; i++)
Colours[i] = Table[(Wheel + i) % 75];
if(Cycle)
LoadRGB4(&BlankScreen -> ViewPort,Colours,32);
else
LoadRGB4(&BlankScreen -> ViewPort,Rainbow,32);
Wheel = (Wheel + 1) % 75;
RPort = &BlankScreen -> RastPort;
FOREVER
{
yy = a - x;
if((save = b * x - c) < 0)
save = -save;
if(x < 0)
x = y + sqrt(save);
else
x = y - sqrt(save);
y = yy;
sx = mag * ( x + y);
sy = mag * (-x + y);
MultiPlot(BlankScreen,(WORD)(sx) + OffsetX,(WORD)(sy) + OffsetY,Colour);
/* Oh well, it's not that easy to
* produce decent colour values for
* the pixels to be rendered.
*
* The following statement will change
* the current drawing pen after exactly
* 900 pixels have been rendered and will
* pick a new colour between 1 and 31.
*/
if(Count++ >= 900)
{
Count = 0;
Colour += Plus;
if(!Colour)
{
Plus = 1;
Colour = 2;
}
else
{
if(Colour == 32)
{
Plus = -1;
Colour = 30;
}
}
}
if(SetSignal(0,0) & SIGBREAKF_CTRL_D)
{
SetSignal(0,SIGBREAKF_CTRL_D);
SetRast(RPort,0);
x = y = 0;
a = (float)Random(300) / 100;
b = (float)Random(100) / 100;
c = (float)Random( 50) / 100;
mag = (float)(1 << (Random(4) + 2)) * deg45;
}
if(SetSignal(0,0) & SIGBREAKF_CTRL_E)
{
SetSignal(0,SIGBREAKF_CTRL_E);
for(i = 1 ; i < 32 ; i++)
Colours[i] = Table[(Wheel + i) % 75];
if(Cycle)
LoadRGB4(&BlankScreen -> ViewPort,Colours,32);
Wheel = (Wheel + 1) % 75;
}
}
}
/* Quietly remove ourselves. */
Forbid();
BlankTask = NULL;
RemTask(SysBase -> ThisTask);
}
/* BlankerAction(CxMsg *CxMessage,CxObj *CxObject):
*
* Commodities support routine, handles the Commodities
* custom actions (in this case: filter the InputEvents
* coming in and enable/disable the screen blanker).
*/
VOID __saveds __stdargs
BlankerAction(CxMsg *CxMessage,CxObj *CxObject)
{
STATIC BYTE Count = 1;
struct InputEvent *Event = (struct InputEvent *)CxMsgData(CxMessage);
/* Push the blanker screen to the front if necessary. */
if(BlankScreen)
{
if(BlankScreen -> TopEdge)
MoveScreen(BlankScreen,0,-BlankScreen -> TopEdge);
if(IntuitionBase -> FirstScreen != BlankScreen)
ScreenToFront(BlankScreen);
}
/* This looks like a timer event. */
if(Event -> ie_Class == IECLASS_TIMER && !Window)
{
/* Screen blanker still inactive? */
if(!BlankTask)
{
/* Is there a timeout to take care of? */
if(ScreenTimeout)
{
/* Are we ready to create the
* screenblanker?
*/
if(ScreenCount++ >= ScreenTimeout * 10)
{
if(!BlankTask)
StartBlanker();
}
}
}
else
{
if(Count < 0)
Count = 0;
/* Every 5/60 second we signal the blanker
* task to rotate the palette.
*/
if(Count++ >= 2)
{
Signal(BlankTask,SIGBREAKF_CTRL_E);
Count = 0;
}
/* Is it time to change the pattern? */
if(PatternTimeout)
{
if(PatternCount++ >= PatternTimeout * 10)
{
Signal(BlankTask,SIGBREAKF_CTRL_D);
PatternCount = 0;
}
}
}
}
else
{
/* The following line determines whether
* the blanker is to be removed or to
* be left running.
*/
if((Event -> ie_Class == IECLASS_RAWKEY && !(Event -> ie_Code & IECODE_UP_PREFIX) && !(Event -> ie_Qualifier & IEQUALIFIER_REPEAT)) || Event -> ie_Class == IECLASS_RAWMOUSE)
{
/* Remove the blanker task. */
if(BlankTask)
{
struct Task *Task = BlankTask;
BlankTask = NULL;
RemTask(Task);
}
/* Close the blanker screen. */
if(BlankScreen)
{
struct Screen *Screen = BlankScreen;
BlankScreen = NULL;
ScreenToBack(Screen);
FreeVPortCopLists(&Screen -> ViewPort);
RemakeDisplay();
CloseScreen(Screen);
}
}
ScreenCount = 0;
}
}
/* ShutdownCx():
*
* Close the Commodities interface.
*/
VOID
ShutdownCx()
{
if(CxPort)
{
struct Message *Message;
/* Remove the broker. */
if(Broker)
DeleteCxObjAll(Broker);
/* Remove the MsgPort from the public list. */
RemPort(CxPort);
/* Remove all pending messages. */
while(Message = GetMsg(CxPort))
ReplyMsg(Message);
/* Delete the MsgPort. */
DeleteMsgPort(CxPort);
CxPort = NULL;
Broker = NULL;
}
}
/* GetSeconds(UBYTE *String):
*
* Calculates the number of seconds corresponding to
* expressions such as `11:25' or `10'.
*/
WORD
GetSeconds(UBYTE *String)
{
WORD i,Seconds;
for(i = strlen(String) - 1 ; i >= 0 ; i--)
{
if(String[i] == ':')
{
Seconds = atol(&String[i + 1]);
String[i] = 0;
Seconds += 60 * atol(String);
if(Seconds > 30 * 60)
Seconds = 30 * 60;
return(Seconds);
}
}
if((Seconds = atol(String)) > 30 * 60)
Seconds = 30 * 60;
return(Seconds);
}
/* SetupCx(UBYTE **ToolTypes):
*
* Set up the Commodities interface.
*/
BYTE __regargs
SetupCx(UBYTE **ToolTypes)
{
/* Cancel any previously made assignments. */
ShutdownCx();
/* Create a reply port. */
if(CxPort = CreateMsgPort())
{
/* Fill in a unique name. */
CxPort -> mp_Node . ln_Name = NewBroker . nb_Name;
/* Add the reply port to the public list. */
AddPort(CxPort);
/* Install the replyport. */
NewBroker . nb_Port = CxPort;
/* Set the Commodity priority if possible. */
if(ToolTypes)
NewBroker . nb_Pri = ArgInt(ToolTypes,"CX_PRIORITY",0);
/* Create the broker. */
if(Broker = CxBroker(&NewBroker,NULL))
{
CxObj *ObjectList;
UBYTE *String,Buffer[256];
if(ToolTypes)
{
/* Set the Commodity popup hotkey if possible. */
String = ArgString(ToolTypes,"CX_POPKEY","shift f1");
strcpy(HotkeyBuffer,String);
/* Determine the screen blanker hotkey. */
String = ArgString(ToolTypes,"BLANKSCREEN","shift f2");
strcpy(BlankScreenBuffer,String);
/* Cycle the multicolour palette? */
String = ArgString(ToolTypes,"CYCLE","yes");
if(!strcmpi(String,"yes"))
Cycle = TRUE;
else
Cycle = FALSE;
/* Run in monochrome mode? */
String = ArgString(ToolTypes,"MONO","no");
if(!strcmpi(String,"yes"))
Mono = TRUE;
else
Mono = FALSE;
/* Adjust the screen timeout if possible. */
strcpy(Buffer,ArgString(ToolTypes,"SCREENTIMEOUT","1:00"));
ScreenTimeout = GetSeconds(Buffer);
/* Adjust the pattern change timeout if possible. */
strcpy(Buffer,ArgString(ToolTypes,"PATTERNTIMEOUT","1:00"));
PatternTimeout = GetSeconds(Buffer);
}
/* Link the hotkey. */
AttachCxObj(Broker,HotKey(HotkeyBuffer,CxPort,POP_WINDOW));
/* Link another hotkey. */
AttachCxObj(Broker,HotKey(BlankScreenBuffer,CxPort,BLANK_SCREEN));
/* Install the plain InputEvent handler. */
ObjectList = CxCustom(BlankerAction,NULL);
/* Any accumulated errors? */
if(!CxObjError(ObjectList))
{
/* Add the custom object. */
AttachCxObj(Broker,ObjectList);
/* Any errors? */
if(!CxObjError(Broker))
{
/* Activate the broker. */
ActivateCxObj(Broker,TRUE);
return(TRUE);
}
}
}
}
ShutdownCx();
return(FALSE);
}
/* HandleCxMsg(CxMsg *Message):
*
* Handle incoming Commodities messages.
*/
VOID __regargs
HandleCxMsg(CxMsg *Message)
{
ULONG MessageID = CxMsgID(Message),MessageType = CxMsgType(Message);
ReplyMsg((struct Message *)Message);
/* Take a look at the message type. */
switch(MessageType)
{
/* It's a hotkey. */
case CXM_IEVENT: switch(MessageID)
{
/* Create the control panel. */
case POP_WINDOW: SetupWindow();
break;
/* Blank the screen. */
case BLANK_SCREEN: if(!BlankTask)
StartBlanker();
else
{
/* Tell the blanker task to change the pattern. */
Signal(BlankTask,SIGBREAKF_CTRL_D);
PatternCount = 0;
}
break;
}
break;
/* It's an internal Commodities command. */
case CXM_COMMAND: switch(MessageID)
{
/* Disable the Commodity. */
case CXCMD_DISABLE: ActivateCxObj(Broker,FALSE);
break;
/* Enable the Commodity. */
case CXCMD_ENABLE: ActivateCxObj(Broker,TRUE);
break;
/* Create the control panel. */
case CXCMD_APPEAR:
case CXCMD_UNIQUE: SetupWindow();
break;
/* Close the control panel. */
case CXCMD_DISAPPEAR: ShutdownWindow();
break;
/* Remove this Commodity. */
case CXCMD_KILL: CloseAll(RETURN_OK);
break;
}
break;
}
}
/* ShowTime(struct Gadget *SomeGadget,WORD Level):
*
* Gadtools support routine, displays the timeouts.
*/
LONG __saveds __stdargs
ShowTime(struct Gadget *SomeGadget,WORD Level)
{
STATIC UBYTE Buffer[30];
if(Level)
SPrintf(Buffer,"%2ld.%02ld",Level / 60,Level % 60);
else
SPrintf(Buffer,"-Off-");
return((LONG)Buffer);
}
/* CreateAllGadgets():
*
* Gadtools support routine, creates all the gadgets
* required by the control panel.
*/
struct Gadget *
CreateAllGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge)
{
struct Gadget *Gadget;
struct NewGadget NewGadget;
UWORD Counter = 0;
if(Gadget = CreateContext(GadgetList))
{
NewGadget . ng_Width = 104;
NewGadget . ng_Height = 12;
NewGadget . ng_GadgetText = "_Screen Timeout ";
NewGadget . ng_TextAttr = &DefaultFont;
NewGadget . ng_VisualInfo = VisualInfo;
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_Flags = 0;
NewGadget . ng_LeftEdge = (strlen(NewGadget . ng_GadgetText) + 2 - 1) * 8 - 2;
NewGadget . ng_TopEdge = 1 + TopEdge;
GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
GTSL_Min, 0,
GTSL_Max, 30 * 60,
GTSL_Level, ScreenTimeout,
GTSL_DispFunc, ShowTime,
GTSL_LevelFormat, "%s",
GTSL_MaxLevelLen, 5,
TAG_DONE);
NewGadget . ng_GadgetText = "_Pattern Change ";
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_TopEdge += NewGadget . ng_Height + 1;
GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
GTSL_Min, 0,
GTSL_Max, 30 * 60,
GTSL_Level, PatternTimeout,
GTSL_DispFunc, ShowTime,
GTSL_LevelFormat, "%s",
GTSL_MaxLevelLen, 5,
TAG_DONE);
NewGadget . ng_GadgetText = "Hot _Key";
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_TopEdge += NewGadget . ng_Height + 2;
NewGadget . ng_Height = 14;
GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
GTST_MaxChars, 256,
GTST_String, HotkeyBuffer,
TAG_DONE);
NewGadget . ng_GadgetText = "_Blank Screen";
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_TopEdge += NewGadget . ng_Height + 1;
NewGadget . ng_Height = 14;
GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
GTST_MaxChars, 256,
GTST_String, BlankScreenBuffer,
TAG_DONE);
NewGadget . ng_GadgetText = "_Monochrome";
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_TopEdge += NewGadget . ng_Height + 2;
NewGadget . ng_Height = 12;
GadgetArray[Counter++] = Gadget = CreateGadget(CHECKBOX_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
GTCB_Checked, Mono,
TAG_DONE);
NewGadget . ng_GadgetText = "_Cycle";
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_TopEdge += NewGadget . ng_Height + 1;
GadgetArray[Counter++] = Gadget = CreateGadget(CHECKBOX_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
GTCB_Checked, Cycle,
TAG_DONE);
NewGadget . ng_GadgetText = "_Hide";
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_Flags = 0;
NewGadget . ng_LeftEdge = 6;
NewGadget . ng_TopEdge = HEIGHT - 3 - NewGadget . ng_Height;
GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
TAG_DONE);
NewGadget . ng_GadgetText = "_Quit";
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_LeftEdge = WIDTH - 6 - NewGadget . ng_Width;
GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
TAG_DONE);
}
return(Gadget);
}
/* ShutdownWindow():
*
* Closes the control panel.
*/
VOID
ShutdownWindow()
{
if(Window)
{
CloseWindow(Window);
Window = NULL;
}
if(GadgetList)
{
FreeGadgets(GadgetList);
GadgetList = NULL;
}
if(VisualInfo)
{
FreeVisualInfo(VisualInfo);
VisualInfo = NULL;
}
if(DefaultScreen)
{
UnlockPubScreen(NULL,DefaultScreen);
DefaultScreen = NULL;
}
if(Topaz)
{
CloseFont(Topaz);
Topaz = NULL;
}
}
/* CentreWindow():
*
* Adjust left/top coordinates of window to be opened to
* become visible right below the mouse pointer.
*/
VOID __regargs
CentreWindow(struct Screen *Screen,WORD *LeftEdge,WORD *TopEdge)
{
(*LeftEdge) = Screen -> MouseX - (WIDTH >> 1);
(*TopEdge) = Screen -> MouseY - (HEIGHT >> 1);
while((*LeftEdge) + WIDTH > Screen -> Width)
(*LeftEdge)--;
while((*LeftEdge) < 0)
(*LeftEdge)++;
while((*TopEdge) + HEIGHT > Screen -> Height)
(*TopEdge)--;
while((*TopEdge) < 0)
(*TopEdge)++;
}
/* SetupWindow():
*
* Creates the control panel and disables the screen
* blanker.
*/
BYTE
SetupWindow()
{
if(BlankTask)
{
struct Task *Task = BlankTask;
BlankTask = NULL;
RemTask(Task);
}
if(BlankScreen)
{
struct Screen *Screen = BlankScreen;
BlankScreen = NULL;
ScreenToBack(Screen);
FreeVPortCopLists(&Screen -> ViewPort);
RemakeDisplay();
CloseScreen(Screen);
}
if(Window)
return(TRUE);
if(Topaz = (struct TextFont *)OpenFont(&DefaultFont))
{
if(DefaultScreen = (struct Screen *)LockPubScreen(NULL))
{
if(VisualInfo = GetVisualInfo(DefaultScreen,TAG_DONE))
{
if(CreateAllGadgets(&GadgetArray[0],&GadgetList,VisualInfo,DefaultScreen -> WBorTop + DefaultScreen -> Font -> ta_YSize + 1))
{
WORD Left,Top;
CentreWindow(DefaultScreen,&Left,&Top);
if(ZoomData[0] == -1)
{
ZoomData[0] = 0;
ZoomData[1] = 0;
ZoomData[2] = WIDTH;
ZoomData[3] = DefaultScreen -> WBorTop + DefaultScreen -> Font -> ta_YSize + 1;
}
if(Window = OpenWindowTags(NULL,
WA_Left, Left,
WA_Top, Top,
WA_Width, WIDTH,
WA_Height, HEIGHT + DefaultScreen -> Font -> ta_YSize - 8,
WA_Activate, TRUE,
WA_DragBar, TRUE,
WA_DepthGadget, TRUE,
WA_CloseGadget, TRUE,
WA_RMBTrap, TRUE,
WA_Zoom, ZoomData,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | IDCMP_NEWSIZE | SLIDERIDCMP | BUTTONIDCMP,
WA_Title, "Fractal Blanker v1.8",
TAG_DONE))
{
SetFont(Window -> RPort,Topaz);
AddGList(Window,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
RefreshGList(GadgetList,Window,NULL,(UWORD)-1);
GT_RefreshWindow(Window,NULL);
MoveScreen(Window -> WScreen,0,-Window -> WScreen -> TopEdge);
ScreenToFront(Window -> WScreen);
UnlockPubScreen(NULL,DefaultScreen);
DefaultScreen = NULL;
return(TRUE);
}
}
}
}
}
ShutdownWindow();
return(FALSE);
}
/* CloseAll(LONG ReturnCode):
*
* Free all resources and exit the program.
*/
VOID __regargs
CloseAll(LONG ReturnCode)
{
if(CxBase && IconBase)
{
ShutdownCx();
ArgArrayDone();
}
if(BlankTask)
RemTask(BlankTask);
if(BlankScreen)
{
ScreenToBack(BlankScreen);
FreeVPortCopLists(&BlankScreen -> ViewPort);
RemakeDisplay();
CloseScreen(BlankScreen);
BlankScreen = NULL;
}
ShutdownWindow();
if(IconBase)
CloseLibrary(IconBase);
if(CxBase)
CloseLibrary(CxBase);
if(GadToolsBase)
CloseLibrary(GadToolsBase);
if(GfxBase)
CloseLibrary(GfxBase);
if(IntuitionBase)
CloseLibrary(IntuitionBase);
exit(ReturnCode);
}
/* OpenAll(int argc,char **argv):
*
* Open all resources, initialize the colour table and
* create the Commodities interface.
*/
VOID __regargs
OpenAll(int argc,char **argv)
{
UBYTE **ToolTypes,*String;
WORD i,c = 0,r = 15,g = 0,b = 0;
/* Create a table of rainbow colours. */
for(i = 0 ; i < 16 ; i++)
Table[c++] = (r << 8) | ((g++) << 4) | b;
g = 15;
r--;
for(i = 0 ; i < 15 ; i++)
Table[c++] = ((r--) << 8) | (g << 4) | b;
r = 0;
g--;
b++;
for(i = 0 ; i < 15 ; i++)
Table[c++] = (r << 8) | ((g--) << 4) | (b++);
g = 0;
b = 15;
r++;
for(i = 0 ; i < 15 ; i++)
Table[c++] = ((r++) << 8) | (g << 4) | b;
r = 15;
b--;
for(i = 0 ; i < 14 ; i++)
Table[c++] = (r << 8) | (g << 4) | (b--);
/* Open the libraries we need. */
if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)))
CloseAll(RETURN_FAIL + 0);
if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)))
CloseAll(RETURN_FAIL + 1);
if(!(GadToolsBase = OpenLibrary("gadtools.library",37)))
CloseAll(RETURN_FAIL + 2);
if(!(CxBase = OpenLibrary("commodities.library",37)))
CloseAll(RETURN_FAIL + 3);
if(!(IconBase = OpenLibrary("icon.library",37)))
CloseAll(RETURN_FAIL + 4);
/* Parse the startup arguments. */
ToolTypes = ArgArrayInit(argc,argv);
/* Provide default values. */
strcpy(HotkeyBuffer, "shift f1");
strcpy(BlankScreenBuffer, "shift f2");
/* Create the commodities interface. */
if(!SetupCx(ToolTypes))
CloseAll(RETURN_FAIL + 5);
/* Pop up the control panel if necessary. */
if(ToolTypes)
{
String = ArgString(ToolTypes,"CX_POPUP","no");
if(!strcmpi(String,"yes"))
SetupWindow();
}
}
/* main(int argc,char **argv):
*
* That's where all the trouble starts.
*/
VOID __stdargs
main(int argc,char **argv)
{
ULONG SignalSet;
/* Open everything we need. */
OpenAll(argc,argv);
/* Go into loop waiting for messages. */
FOREVER
{
SignalSet = (1 << CxPort -> mp_SigBit) | SIGBREAKF_CTRL_C;
/* If the window is still open, wait for
* some news.
*/
if(Window)
SignalSet |= (1 << Window -> UserPort -> mp_SigBit);
SignalSet = Wait(SignalSet);
/* There are messages pending at the
* Commodities reply port.
*/
if(SignalSet & (1 << CxPort -> mp_SigBit))
{
CxMsg *Message;
while(Message = (CxMsg *)GetMsg(CxPort))
HandleCxMsg(Message);
}
/* ^E tells the program to quit. */
if(SignalSet & SIGBREAKF_CTRL_C)
CloseAll(RETURN_OK);
/* If the control panel is still open,
* check for new messages.
*/
if(Window)
{
if(SignalSet & (1 << Window -> UserPort -> mp_SigBit))
{
struct IntuiMessage *Massage;
struct Gadget *Gadget;
ULONG Class,Code;
while(Massage = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort))
{
Class = Massage -> Class;
Code = Massage -> Code;
Gadget = (struct Gadget *)Massage -> IAddress;
GT_ReplyIMsg(Massage);
switch(Class)
{
/* Close the window. */
case IDCMP_CLOSEWINDOW: ShutdownWindow();
break;
case IDCMP_NEWSIZE: GT_RefreshWindow(Window,NULL);
break;
/* Set the slider values. */
case IDCMP_MOUSEMOVE: switch(Gadget -> GadgetID)
{
case GAD_SCREENTIMEOUT: ScreenCount = 0;
ScreenTimeout = Code;
break;
case GAD_PATTERNCHANGE: PatternCount = 0;
PatternTimeout = Code;
break;
}
break;
/* Handle the keyboard shortcuts. */
case IDCMP_VANILLAKEY: switch(toupper(Code))
{
case 'S': ScreenCount = 0;
if(Code == 's')
{
if(ScreenTimeout + 1 <= 30 * 60)
ScreenTimeout++;
else
ScreenTimeout = ScreenTimeout + 1 - 30 * 60;
}
else
{
if(ScreenTimeout > 0)
ScreenTimeout--;
else
ScreenTimeout = 30 * 60;
}
GT_SetGadgetAttrs(GadgetArray[GAD_SCREENTIMEOUT],Window,NULL,
GTSL_Level,ScreenTimeout,
TAG_DONE);
break;
case 'P': PatternCount = 0;
if(Code == 'p')
{
if(PatternTimeout + 1 <= 30 * 60)
PatternTimeout++;
else
PatternTimeout = PatternTimeout + 1 - 30 * 60;
}
else
{
if(PatternTimeout > 0)
PatternTimeout--;
else
PatternTimeout = 30 * 60;
}
GT_SetGadgetAttrs(GadgetArray[GAD_PATTERNCHANGE],Window,NULL,
GTSL_Level,PatternTimeout,
TAG_DONE);
break;
case 'K': ActivateGadget(GadgetArray[GAD_HOTKEY],Window,NULL);
break;
case 'B': ActivateGadget(GadgetArray[GAD_BLANKSCREEN],Window,NULL);
break;
case 'M': Mono ^= TRUE;
GT_SetGadgetAttrs(GadgetArray[GAD_MONO],Window,NULL,
GTCB_Checked,Mono,
TAG_DONE);
break;
case 'C': Cycle ^= TRUE;
GT_SetGadgetAttrs(GadgetArray[GAD_CYCLE],Window,NULL,
GTCB_Checked,Cycle,
TAG_DONE);
break;
case 'H': ShutdownWindow();
break;
case 'Q': CloseAll(RETURN_OK);
default: break;
}
break;
/* Handle the gadgets themselves. */
case IDCMP_GADGETUP: switch(Gadget -> GadgetID)
{
case GAD_HOTKEY: strcpy(HotkeyBuffer,((struct StringInfo *)Gadget -> SpecialInfo) -> Buffer);
if(!SetupCx(NULL))
CloseAll(RETURN_FAIL + 5);
break;
case GAD_BLANKSCREEN: strcpy(BlankScreenBuffer,((struct StringInfo *)Gadget -> SpecialInfo) -> Buffer);
if(!SetupCx(NULL))
CloseAll(RETURN_FAIL + 5);
break;
case GAD_MONO: if(Gadget -> Flags & GFLG_SELECTED)
Mono = TRUE;
else
Mono = FALSE;
break;
case GAD_CYCLE: if(Gadget -> Flags & GFLG_SELECTED)
Cycle = TRUE;
else
Cycle = FALSE;
break;
case GAD_HIDE: ShutdownWindow();
break;
case GAD_QUIT: CloseAll(RETURN_OK);
}
break;
}
/* Window has been closed, do not
* continue requesting messages
* from the UserPort.
*/
if(!Window)
break;
}
}
}
}
}