home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_progs
/
fract
/
fracblnk.lha
/
FracBlank.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-26
|
62KB
|
3,047 lines
/*
** FracBlank - AmigaDOS 2.04 commodities utility screenblanker
**
** Copyright © 1991-1992 by Olaf `Olsen' Barthel
** All Rights Reserved
**
** Cosmic flame fractal code derived from xlock source code
**
** Copyright © 1988-1991 by Patrick J. Naughton.
*/
/* Include the specific math pragmas/header files here (is there
* any way to figure this out by taking a look at undocumented
* 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)
/* Use a simple address trick instead of the predefined
* address in amiga.lib.
*/
#ifndef custom
#define custom (*(struct Custom *)0xDFF000)
#endif /* custom */
/* A couple of handy gadget control macros. */
#define GT_CHECKED(G) ((((struct Gadget *)(G)) -> Flags & GFLG_SELECTED) ? TRUE : FALSE)
#define GT_STRING(G) (((struct StringInfo *)(((struct Gadget *)(G)) -> SpecialInfo)) -> Buffer)
/* Hotkey IDs. */
enum { POP_WINDOW,BLANK_SCREEN };
/* Gadget IDs. */
enum { GAD_SCREENTIMEOUT,GAD_MOUSETIMEOUT,GAD_PATTERNCHANGE,GAD_HOTKEY,
GAD_BLANKSCREEN,GAD_KEYBLANK,GAD_FRACTAL,GAD_COLOUR,GAD_HIDE,GAD_QUIT };
/* Some useful signals. */
#define SIG_BREAK SIGBREAKF_CTRL_C
#define SIG_CHANGE SIGBREAKF_CTRL_D
#define SIG_CYCLE SIGBREAKF_CTRL_E
#define SIG_START SIGBREAKF_CTRL_F
#define SIG_REFRESH SIGBREAKF_CTRL_E
#define SIG_WAKEUP SIGBREAKF_CTRL_F
#define SIG_CX (1 << CxPort -> mp_SigBit)
#define SIG_WINDOW (Window ? (1 << Window -> UserPort -> mp_SigBit) : NULL)
/* Private mouse blanker signals. */
#define SIG_NOTICE SIGBREAKF_CTRL_D
#define SIG_ON SIGBREAKF_CTRL_E
#define SIG_OFF SIGBREAKF_CTRL_F
/* Number of patches to install. */
#define NUM_PATCHES (sizeof(PatchTable) / sizeof(struct PatchInfo))
/* Cosmic flame fractal parameters. */
#define MAXFLAMELEVEL 20
#define MAXTOTALPOINTS 20000
/* Fractal types. */
enum { FRACTAL_REAL_PLANE,FRACTAL_COSMIC_FLAME,FRACTAL_RANDOM };
/* Colour modes. */
enum { COLOUR_CYCLE,COLOUR_STATIC,COLOUR_MONO };
/* A system library patch definition. */
struct PatchInfo
{
APTR NewRoutine;
LONG Offset;
ULONG *Destination;
};
/* A window identification node, also contains information
* on the currently selected pointer sprite.
*/
struct WindowNode
{
struct MinNode Node;
struct Window *Window;
UWORD *Pointer;
BYTE Height,
Width;
BYTE XOffset,
YOffset;
BYTE Off;
};
/* The offsets of the system library routines we will patch. */
extern ULONG __far LVOClearPointer,
LVOSetPointer,
LVOOpenWindow,
LVOOpenWindowTagList,
LVOCloseWindow;
/* Program revision tag. */
STATIC const UBYTE VersTag[] = "\0$VER: FracBlank 2.2 (4.4.92)";
/* Shared library identifiers. */
extern struct ExecBase *SysBase;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *CxBase,
*IconBase,
*GadToolsBase,
*UtilityBase;
/* The main program. */
struct Process *MainProcess;
/* Blanker data. */
struct Task *BlankTask;
struct Screen *BlankScreen;
/* BlankerControl data. */
struct Task *BlankerControlTask;
/* Mouse blanker data. */
struct Task *MouseBlankerTask;
/* Commodities interface data. */
struct MsgPort *CxPort;
CxObj *Broker;
/* Gfx and gadtools data. */
struct Screen *DefaultScreen;
APTR VisualInfo;
struct TextFont *LocalFont;
struct Gadget *GadgetList;
struct Gadget *GadgetArray[GAD_QUIT + 1];
struct Window *Window;
/* Window zoom data. */
struct IBox ZoomData = { -1,-1,-1,-1 };
/* Window dimensions. */
WORD WindowWidth = 284,
WindowHeight = 113;
/* Rainbow colour table. */
UWORD Table[75];
/* No colours at all. */
UWORD Black[32];
/* Declarations for cosmic flame blanker code. */
float Flame[2][3][2];
WORD FlameLevel,
FlameAlternateForm,
FlameModulo;
UWORD FlameColourTable[32];
BYTE FlameWheel,
FlameColour;
PLANEPTR FlamePlane;
ULONG FlamePoints;
/* Key sequence buffers. */
UBYTE HotkeyBuffer[256],
BlankScreenBuffer[256];
/* Screen and pattern change timeout. */
ULONG ScreenCount = 0,
PatternCount = 0,
ScreenTimeout = 60,
MouseTimeout = 5,
PatternTimeout = 60;
/* A flag which tells us whether to blank the mouse pointer
* on a keypress or not.
*/
BYTE KeyBlank = TRUE;
/* Some kind of a semaphore to tell the blank task to stop drawing. */
BYTE StopDrawing = FALSE;
/* The default font to be used by the control panel. */
struct TextAttr DefaultFont;
UBYTE DefaultFontName[256];
UWORD DefaultFontWidth;
/* The colours of a rainbow (well, with a bit of imagination, just
* 32 colours in this rainbow for now).
*/
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
};
/* A new broker definition, Commodities needs this. */
struct NewBroker NewBroker =
{
NB_VERSION,
"FracBlanker",
"Fractal Blanker v2.2",
"Screen Blanker",
NBU_NOTIFY | NBU_UNIQUE,
COF_SHOW_HIDE,
0,NULL,0
};
/* The fractal mode names. */
STRPTR FractalModes[] =
{
"Real Plane",
"Cosmic Flame",
"Random",
NULL
};
/* The current fractal type. */
UBYTE FractalType = FRACTAL_RANDOM;
/* The colour mode names. */
STRPTR ColourModes[] =
{
"Cycling Colours",
"Static Colours",
"Monochrome",
NULL
};
/* The current colour mode. */
UBYTE ColourMode = COLOUR_CYCLE;
/* Patch data. */
extern VOID __stdargs StackOldSetPointer(struct Window *Window,UWORD *Pointer,WORD Height,WORD Width,WORD XOffset,WORD YOffset);
extern VOID NewSetPointer(VOID);
APTR OldSetPointer;
VOID (* __asm OldClearPointer)(register __a0 struct Window *,register __a6 struct IntuitionBase *);
struct Window * (* __asm OldOpenWindowTagList)(register __a0 struct NewWindow *,register __a1 struct TagItem *,register __a6 struct IntuitionBase *);
struct Window * (* __asm OldOpenWindow)(register __a0 struct NewWindow *,register __a6 struct IntuitionBase *);
VOID (* __asm OldCloseWindow)(register __a0 struct Window *,register __a6 struct IntuitionBase *);
/* Mouse blanker function prototypes. */
VOID __stdargs __saveds StackNewSetPointer(struct Window *Window,UWORD *Pointer,WORD Height,WORD Width,WORD XOffset,WORD YOffset);
VOID __asm __saveds NewClearPointer(register __a0 struct Window *Window);
struct Window * __asm __saveds NewOpenWindowTagList(register __a0 struct NewWindow *NewWindow,register __a1 struct TagItem *TagList);
struct Window * __asm __saveds NewOpenWindow(register __a0 struct NewWindow *NewWindow);
VOID __asm __saveds NewCloseWindow(register __a0 struct Window *Window);
VOID __saveds MouseBlanker(VOID);
VOID __regargs UpdateNode(struct WindowNode *Node,struct Window *Window);
struct WindowNode * __regargs NewNode(struct Window *Window);
VOID TurnOff(VOID);
VOID TurnOn(VOID);
/* The window and mouse pointer access list. */
struct SignalSemaphore WindowSemaphore;
struct List WindowList;
/* Miscellaneous mouse blanker counters and flags. */
ULONG KeyBlankUseCnt = 0,
KeyBlankCount = 0;
BYTE AllSpritesOff = FALSE,
KeyBlankStop = FALSE;
/* The table of patches to install. */
struct PatchInfo PatchTable[] =
{
NewClearPointer, (LONG)&LVOClearPointer, (ULONG *)&OldClearPointer,
NewSetPointer, (LONG)&LVOSetPointer, (ULONG *)&OldSetPointer,
NewOpenWindowTagList, (LONG)&LVOOpenWindowTagList, (ULONG *)&OldOpenWindowTagList,
NewOpenWindow, (LONG)&LVOOpenWindow, (ULONG *)&OldOpenWindow,
NewCloseWindow, (LONG)&LVOCloseWindow, (ULONG *)&OldCloseWindow
};
/* An entirely transparent sprite. */
UWORD __chip BlankSprite[(2 + 1) * 2] =
{
0x0000,0x0000,
0x0000,0x0000,
0x0000,0x0000
};
/* 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);
extern __stdargs SPrintf(STRPTR Mem,STRPTR Args,...);
extern LONG __asm Atol(register __a0 STRPTR String);
VOID __saveds BlankerControl(VOID);
ULONG __regargs Random(ULONG MaxValue);
VOID RealPlane(VOID);
VOID CosmicFlame(VOID);
BYTE RecurseMono(float x,float y,WORD Level);
BYTE RecurseColour(float x,float y,WORD Level);
VOID __saveds Blanker(VOID);
VOID __saveds __stdargs BlankerAction(CxMsg *CxMessage,CxObj *CxObject);
VOID ShutdownCx(VOID);
BYTE __regargs SetupCx(STRPTR *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);
/* MouseBlanker():
*
* The mouse pointer blanker task, patches a few system library functions
* and turns the mouse pointer on and off.
*/
VOID __saveds
MouseBlanker()
{
struct Wedge *WedgeTable;
/* Create the wedge table, note: this memory will never be
* freed!
*/
if(WedgeTable = (struct Wedge *)AllocMem(sizeof(struct Wedge) * NUM_PATCHES,MEMF_PUBLIC | MEMF_CLEAR))
{
struct WindowNode *Node,
*Next;
ULONG IntuiLock,
SignalSet;
struct Screen *Screen;
struct Window *Window;
BYTE Terminated = FALSE;
WORD i;
/* Set up the window list data. */
InitSemaphore(&WindowSemaphore);
NewList(&WindowList);
/* Put all windows into the list. */
IntuiLock = LockIBase(NULL);
Screen = IntuitionBase -> FirstScreen;
while(Screen)
{
Window = Screen -> FirstWindow;
while(Window)
{
NewNode(Window);
Window = Window -> NextWindow;
}
Screen = Screen -> NextScreen;
}
Forbid();
UnlockIBase(IntuiLock);
/* Install the patches. */
for(i = 0 ; i < NUM_PATCHES ; i++)
{
WedgeTable[i] . Command = JMP_ABS;
WedgeTable[i] . Address = PatchTable[i] . NewRoutine;
*PatchTable[i] . Destination = (ULONG)SetFunction((struct Library *)IntuitionBase,PatchTable[i] . Offset,(APTR)&WedgeTable[i]);
}
CacheClearU();
/* Ring back. */
Signal(MainProcess,SIG_WAKEUP);
Permit();
/* Loop until terminated. */
while(!Terminated)
{
/* Wait for a signal. */
SignalSet = Wait(SIG_BREAK | SIG_ON | SIG_OFF);
/* Are we to quit? */
if(SignalSet & SIG_BREAK)
Terminated = TRUE;
/* Are we to turn the mouse pointer sprite back on? */
if(SignalSet & SIG_ON)
TurnOn();
/* Are we to turn all mouse pointer sprites off? */
if(SignalSet & SIG_OFF)
TurnOff();
}
Forbid();
/* Clear the notification signal. */
SetSignal(0,SIG_NOTICE);
/* Do not continue adding new nodes to the list. */
KeyBlankStop = TRUE;
Permit();
/* Turn all sprites back on. */
TurnOn();
/* Remove the patches. */
Forbid();
for(i = 0 ; i < NUM_PATCHES ; i++)
WedgeTable[i] . Address = (APTR)*PatchTable[i] . Destination;
CacheClearU();
Permit();
/* Loop until all patched routines are clear. */
while(KeyBlankUseCnt > 0)
Wait(SIG_NOTICE);
/* Remove all windows from the list. */
Node = (struct WindowNode *)WindowList . lh_Head;
while(Next = (struct WindowNode *)Node -> Node . mln_Succ)
{
Remove((struct Node *)Node);
FreeVec(Node);
Node = Next;
}
}
/* We're done now. */
Forbid();
Signal(MainProcess,SIG_WAKEUP);
}
/* UpdateNode(struct WindowNode *Node,struct Window *Window):
*
* Update a window node with the new pointer data.
*/
VOID __regargs
UpdateNode(struct WindowNode *Node,struct Window *Window)
{
Node -> Pointer = Window -> Pointer;
Node -> Height = Window -> PtrHeight;
Node -> Width = Window -> PtrWidth;
Node -> XOffset = Window -> XOffset;
Node -> YOffset = Window -> YOffset;
}
/* NewNode(struct Window *Window):
*
* Create a new window node and link it into the window list.
*/
struct WindowNode * __regargs
NewNode(struct Window *Window)
{
struct WindowNode *Node;
if(Node = (struct WindowNode *)AllocVec(sizeof(struct WindowNode),MEMF_PUBLIC | MEMF_CLEAR))
{
Node -> Window = Window;
UpdateNode(Node,Window);
AddTail(&WindowList,(struct Node *)Node);
}
return(Node);
}
/* FindWindow(struct Window *Window):
*
* Find a window within the window list.
*/
struct WindowNode * __regargs
FindWindow(struct Window *Window)
{
struct WindowNode *Node,
*Next;
Node = (struct WindowNode *)WindowList . lh_Head;
while(Next = (struct WindowNode *)Node -> Node . mln_Succ)
{
if(Window == Node -> Window)
return(Node);
Node = Next;
}
return(NULL);
}
/* TurnOff():
*
* Turn all mouse pointer sprites in all windows off.
*/
VOID
TurnOff()
{
/* Gain access to the window semaphore. */
ObtainSemaphore(&WindowSemaphore);
/* Are all sprites still turned off? */
if(!AllSpritesOff)
{
struct WindowNode *Node,
*Next;
/* Walk through the window list... */
Node = (struct WindowNode *)WindowList . lh_Head;
while(Next = (struct WindowNode *)Node -> Node . mln_Succ)
{
/* Is this mouse pointer still active? */
if(!Node -> Off)
{
/* Update the node entry. */
UpdateNode(Node,Node -> Window);
/* Change the pointer. */
StackOldSetPointer(Node -> Window,BlankSprite,1,16,0,0);
Node -> Off = TRUE;
}
Node = Next;
}
AllSpritesOff = TRUE;
}
ReleaseSemaphore(&WindowSemaphore);
}
/* TurnOn():
*
* Turn all mouse pointer sprites in all windows back on.
*/
VOID
TurnOn()
{
struct WindowNode *Node,
*Next;
ObtainSemaphore(&WindowSemaphore);
AllSpritesOff = FALSE;
KeyBlankCount = 0;
Node = (struct WindowNode *)WindowList . lh_Head;
while(Next = (struct WindowNode *)Node -> Node . mln_Succ)
{
if(Node -> Off)
{
if(Node -> Pointer)
StackOldSetPointer(Node -> Window,Node -> Pointer,Node -> Height,Node -> Width,Node -> XOffset,Node -> YOffset);
else
OldClearPointer(Node -> Window,IntuitionBase);
Node -> Off = FALSE;
}
Node = Next;
}
ReleaseSemaphore(&WindowSemaphore);
}
/* NewClearPointer(register __a0 struct Window *Window):
*
* Patch: resets the mouse pointer of a window
* back to its default shape.
*/
VOID __asm __saveds
NewClearPointer(register __a0 struct Window *Window)
{
if(KeyBlankStop)
OldClearPointer(Window,IntuitionBase);
else
{
struct WindowNode *Node;
ObtainSemaphore(&WindowSemaphore);
KeyBlankUseCnt++;
if(Node = FindWindow(Window))
{
if(!AllSpritesOff)
{
OldClearPointer(Window,IntuitionBase);
Node -> Off = FALSE;
}
else
Node -> Off = TRUE;
Node -> Pointer = NULL;
}
else
OldClearPointer(Window,IntuitionBase);
KeyBlankUseCnt--;
Signal(MouseBlankerTask,SIG_NOTICE);
ReleaseSemaphore(&WindowSemaphore);
}
}
/* StackNewSetPointer():
*
* Patch: attach a new mouse pointer sprite to a window.
*/
VOID __stdargs __saveds
StackNewSetPointer(struct Window *Window,UWORD *Pointer,WORD Height,WORD Width,WORD XOffset,WORD YOffset)
{
if(KeyBlankStop)
StackOldSetPointer(Window,Pointer,Height,Width,XOffset,YOffset);
else
{
struct WindowNode *Node;
ObtainSemaphore(&WindowSemaphore);
KeyBlankUseCnt++;
if(Node = FindWindow(Window))
{
if(!AllSpritesOff)
{
StackOldSetPointer(Window,Pointer,Height,Width,XOffset,YOffset);
Node -> Off = FALSE;
}
else
Node -> Off = TRUE;
Node -> Pointer = Pointer;
Node -> Height = Height;
Node -> Width = Width;
Node -> XOffset = XOffset;
Node -> YOffset = YOffset;
}
else
StackOldSetPointer(Window,Pointer,Height,Width,XOffset,YOffset);
KeyBlankUseCnt--;
Signal(MouseBlankerTask,SIG_NOTICE);
ReleaseSemaphore(&WindowSemaphore);
}
}
/* NewOpenWindowTagList():
*
* Patch: open a new window.
*/
struct Window * __asm __saveds
NewOpenWindowTagList(register __a0 struct NewWindow *NewWindow,register __a1 struct TagItem *TagList)
{
struct NewWindow OtherWindow;
if(NewWindow)
{
if((NewWindow -> Type & SCREENTYPE) == CUSTOMSCREEN && NewWindow -> Screen == BlankScreen)
{
CopyMem(NewWindow,&OtherWindow,sizeof(struct NewWindow));
NewWindow = &OtherWindow;
NewWindow -> Type = (NewWindow -> Type & ~SCREENTYPE) | WBENCHSCREEN;
NewWindow -> Screen = NULL;
Signal(MouseBlankerTask, SIG_ON);
Signal(BlankerControlTask, SIG_BREAK);
}
}
if(KeyBlankStop)
return(OldOpenWindowTagList(NewWindow,TagList,IntuitionBase));
else
{
struct Window *Window;
ULONG Signals;
ObtainSemaphore(&WindowSemaphore);
KeyBlankUseCnt++;
if(Window = OldOpenWindowTagList(NewWindow,TagList,IntuitionBase))
{
NewNode(Window);
Signals = SIG_NOTICE | SIG_ON;
}
else
Signals = SIG_NOTICE;
KeyBlankUseCnt--;
Signal(MouseBlankerTask,Signals);
ReleaseSemaphore(&WindowSemaphore);
return(Window);
}
}
/* NewOpenWindow():
*
* Patch: open a new window.
*/
struct Window * __asm __saveds
NewOpenWindow(register __a0 struct NewWindow *NewWindow)
{
struct NewWindow OtherWindow;
if(NewWindow)
{
if((NewWindow -> Type & SCREENTYPE) == CUSTOMSCREEN && NewWindow -> Screen == BlankScreen)
{
CopyMem(NewWindow,&OtherWindow,sizeof(struct NewWindow));
NewWindow = &OtherWindow;
NewWindow -> Type = (NewWindow -> Type & ~SCREENTYPE) | WBENCHSCREEN;
NewWindow -> Screen = NULL;
Signal(MouseBlankerTask, SIG_ON);
Signal(BlankerControlTask, SIG_BREAK);
}
}
if(KeyBlankStop)
return(OldOpenWindow(NewWindow,IntuitionBase));
else
{
struct Window *Window;
ULONG Signals;
ObtainSemaphore(&WindowSemaphore);
KeyBlankUseCnt++;
if(Window = OldOpenWindow(NewWindow,IntuitionBase))
{
NewNode(Window);
Signals = SIG_NOTICE | SIG_ON;
}
else
Signals = SIG_NOTICE;
KeyBlankUseCnt--;
Signal(MouseBlankerTask,Signals);
ReleaseSemaphore(&WindowSemaphore);
return(Window);
}
}
/* NewCloseWindow():
*
* Patch: close a window.
*/
VOID __asm __saveds
NewCloseWindow(register __a0 struct Window *Window)
{
struct WindowNode *Node;
ObtainSemaphore(&WindowSemaphore);
KeyBlankUseCnt++;
if(Node = FindWindow(Window))
{
Remove((struct Node *)Node);
FreeVec(Node);
}
OldCloseWindow(Window,IntuitionBase);
KeyBlankUseCnt--;
Signal(MouseBlankerTask,SIG_NOTICE);
ReleaseSemaphore(&WindowSemaphore);
}
/* BlankerControl():
*
* The screen blanker control task.
*/
VOID __saveds
BlankerControl()
{
ULONG SignalSet;
Forbid();
FOREVER
{
SignalSet = Wait(SIG_BREAK | SIG_START | SIG_CHANGE | SIG_REFRESH);
/* Remove both the screen and the blanker task? */
if(SignalSet & SIG_BREAK)
{
if(BlankScreen)
ScreenToBack(BlankScreen);
/* Remove the blanker task. */
if(BlankTask)
{
struct Task *Task = BlankTask;
/* Remember the old address and clear it. */
BlankTask = NULL;
/* Make sure that the break signal is
* not set when we are waiting for a
* handshake.
*/
SetSignal(0,SIG_BREAK);
/* Tell the blanker task to shut down. */
Signal(Task,SIG_BREAK);
/* Move the blanker task priority up. */
SetTaskPri(Task,80);
/* Wait for handshake signal... */
Wait(SIG_BREAK);
}
/* Close the blanker screen. */
if(BlankScreen)
{
struct Screen *Screen = BlankScreen;
BlankScreen = NULL;
#ifdef USE_COP_LIST
FreeVPortCopLists(&Screen -> ViewPort);
RethinkDisplay();
#endif /* USE_COP_LIST */
CloseScreen(Screen);
}
continue;
}
/* Start the screen blanker? */
if(SignalSet & SIG_START)
{
if(!BlankScreen)
{
struct Screen *Screen,
*FirstScreen;
ULONG DisplayID,
Mode,
IntuiLock;
/* Gain access to IntuitionBase. */
IntuiLock = LockIBase(NULL);
/* Determine the first screen. */
FirstScreen = IntuitionBase -> FirstScreen;
/* Inquire the display mode the first
* screen is in.
*/
DisplayID = GetVPModeID(&FirstScreen -> ViewPort);
/* Surrender the lock. */
UnlockIBase(IntuiLock);
/* Set the approriate display mode. */
if(ColourMode == COLOUR_MONO)
Mode = HIRESLACE_KEY;
else
Mode = EXTRAHALFBRITELACE_KEY;
/* This feature has been added for users
* of old Multiscan monitors which take
* ages to synchronize with different
* display modes. The programm will try
* to open the blanker screen in the same
* display mode as the first screen is in.
* Note that this trick will fail to work
* in ECS screen modes (productivity,
* superhires, etc.).
*/
switch(DisplayID & MONITOR_ID_MASK)
{
case NTSC_MONITOR_ID: Mode |= NTSC_MONITOR_ID;
break;
case PAL_MONITOR_ID: Mode |= PAL_MONITOR_ID;
break;
default: Mode |= DEFAULT_MONITOR_ID;
break;
}
if(Screen = OpenScreenTags(NULL,
SA_Behind, TRUE,
SA_Quiet, TRUE,
SA_DisplayID, Mode,
SA_Overscan, OSCAN_MAX,
SA_Depth, ColourMode == COLOUR_MONO ? 1 : 6,
TAG_DONE))
{
#ifdef USE_COP_LIST
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 instructions. */
if(UCopperListInit(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 colours to black. */
#endif /* USE_COP_LIST */
LoadRGB4(&Screen -> ViewPort,Black,32);
/* Display the screen. */
ScreenToFront(Screen);
BlankScreen = Screen;
#ifdef USE_COP_LIST
}
else
{
CloseScreen(Screen);
FreeMem(UserCopperList,sizeof(struct UCopList));
}
}
else
CloseScreen(Screen);
#endif /* USE_COP_LIST */
}
}
if(BlankScreen)
{
PatternCount = 0;
if(!BlankTask)
BlankTask = (struct Task *)CreateTask("FracBlank Blanker Task",-20,Blanker,1024 * MAXFLAMELEVEL);
}
continue;
}
/* Bring the screen to the front? */
if(SignalSet & SIG_REFRESH)
{
if(BlankScreen)
{
/* Push the blanker screen to the front if necessary. */
if(BlankScreen -> TopEdge > 0)
MoveScreen(BlankScreen,0,-BlankScreen -> TopEdge);
if(IntuitionBase -> FirstScreen != BlankScreen)
ScreenToFront(BlankScreen);
}
}
/* Change the patterns? */
if(SignalSet & SIG_CHANGE)
{
/* Stop drawing patterns. */
StopDrawing = TRUE;
if(BlankScreen && BlankTask)
{
/* Clear the screen. */
LoadRGB4(&BlankScreen -> ViewPort,Black,32);
/* Then tell the blanker to restart. */
Signal(BlankTask,SIG_CHANGE);
}
}
}
}
/* 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);
}
/* RealPlane():
*
* Draw real plane fractals.
*/
VOID
RealPlane()
{
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;
/* Are we running in monochrome mode? */
if(ColourMode == COLOUR_MONO)
{
UWORD Modulo = BlankScreen -> RastPort . BitMap -> BytesPerRow;
PLANEPTR Plane = BlankScreen -> RastPort . BitMap -> Planes[0];
/* Provide starting numbers for the fractal
* parameters.
*/
a = (float)(Random(700) + 5) / 100;
b = (float)(Random(190) + 5) / 100;
c = (float)(Random( 90) + 5) / 100;
mag = (float)(1 << (Random(6) + 2)) * 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
{
/* Are we to shut down? */
if(SetSignal(0,0) & SIG_BREAK)
{
Forbid();
Signal(BlankerControlTask,SIG_BREAK);
RemTask(SysBase -> ThisTask);
}
/* 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(x < 0)
x = y + sqrt(fabs(b * x - c));
else
x = y - sqrt(fabs(b * x - c));
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);
/* ^E tells the blanker to rotate the
* colours.
*/
if(SetSignal(0,0) & SIG_CYCLE)
{
SetSignal(0,SIG_CYCLE);
Colours[1] = Table[Wheel];
LoadRGB4(&BlankScreen -> ViewPort,Colours,2);
Wheel = (Wheel + 1) % 75;
}
/* Change the pattern? */
if(SetSignal(0,0) & SIG_CHANGE)
{
SetSignal(0,SIG_CHANGE);
SetRast(&BlankScreen -> RastPort,0);
LoadRGB4(&BlankScreen -> ViewPort,Colours,2);
StopDrawing = FALSE;
x = y = 0;
a = (float)(Random(700) + 5) / 100;
b = (float)(Random(190) + 5) / 100;
c = (float)(Random( 90) + 5) / 100;
mag = (float)(1 << (Random(6) + 2)) * deg45;
}
}
}
else
{
struct RastPort *RPort;
UWORD Count = 0;
WORD i,NewBit = 0;
BYTE Colour = 1,Plus = 1;
a = (float)(Random(700) + 5) / 100;
b = (float)(Random(190) + 5) / 100;
c = (float)(Random( 90) + 5) / 100;
mag = (float)(1 << (Random(6) + 2)) * deg45;
Colours[0] = 0x000;
for(i = 1 ; i < 32 ; i++)
Colours[i] = Table[(Wheel + i) % 75];
if(ColourMode == COLOUR_CYCLE)
LoadRGB4(&BlankScreen -> ViewPort,Colours,32);
else
LoadRGB4(&BlankScreen -> ViewPort,Rainbow,32);
Wheel = (Wheel + 1) % 75;
RPort = &BlankScreen -> RastPort;
FOREVER
{
/* Are we to shut down? */
if(SetSignal(0,0) & SIG_BREAK)
{
Forbid();
Signal(BlankerControlTask,SIG_BREAK);
RemTask(SysBase -> ThisTask);
}
yy = a - x;
if(x < 0)
x = y + sqrt(fabs(b * x - c));
else
x = y - sqrt(fabs(b * x - c));
y = yy;
sx = mag * ( x + y);
sy = mag * 2.0 * (-x + y);
MultiPlot(BlankScreen,(WORD)(sx) + OffsetX,(WORD)(sy) + OffsetY,Colour | NewBit);
/* 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
* 1200 pixels have been rendered and will
* pick a new colour between 1 and 31.
*/
if(Count++ >= 1200)
{
Count = 0;
if(NewBit)
{
NewBit = 0;
Colour += Plus;
if(!Colour)
{
Plus = 1;
Colour = 2;
}
else
{
if(Colour == 32)
{
Plus = -1;
Colour = 30;
}
}
}
else
NewBit = 0x20;
}
if(SetSignal(0,0) & SIG_CYCLE)
{
SetSignal(0,SIG_CYCLE);
for(i = 1 ; i < 32 ; i++)
Colours[i] = Table[(Wheel + i) % 75];
if(ColourMode == COLOUR_CYCLE)
LoadRGB4(&BlankScreen -> ViewPort,Colours,32);
Wheel = (Wheel + 1) % 75;
}
if(SetSignal(0,0) & SIG_CHANGE)
{
SetSignal(0,SIG_CHANGE);
SetRast(RPort,0);
StopDrawing = FALSE;
if(ColourMode == COLOUR_CYCLE)
LoadRGB4(&BlankScreen -> ViewPort,Colours,32);
else
LoadRGB4(&BlankScreen -> ViewPort,Rainbow,32);
x = y = 0;
a = (float)(Random(700) + 5) / 100;
b = (float)(Random(190) + 5) / 100;
c = (float)(Random( 90) + 5) / 100;
mag = (float)(1 << (Random(6) + 2)) * deg45;
}
}
}
}
/* RecurseMono(float x,float y,WORD Level):
*
* Cosmic flame calculation routine (monochrome).
*/
BYTE
RecurseMono(float x,float y,WORD Level)
{
/* Are we to shut down? */
if(SetSignal(0,0) & SIG_BREAK)
{
Forbid();
Signal(BlankerControlTask,SIG_BREAK);
RemTask(SysBase -> ThisTask);
}
if(StopDrawing)
{
FlameLevel = 0;
StopDrawing = FALSE;
return(FALSE);
}
/* Change the pattern? */
if(SetSignal(0,0) & SIG_CHANGE)
{
SetSignal(0,SIG_CHANGE);
FlameLevel = 0;
StopDrawing = FALSE;
return(FALSE);
}
/* ^E tells the blanker to rotate the
* colours.
*/
if(SetSignal(0,0) & SIG_CYCLE)
{
SetSignal(0,SIG_CYCLE);
FlameColourTable[1] = Table[FlameWheel];
LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,2);
FlameWheel = (FlameWheel + 1) % 75;
}
if(Level >= MAXFLAMELEVEL)
{
if((FlamePoints++) > MAXTOTALPOINTS)
return(FALSE);
else
MonoPlot(FlamePlane,(WORD)((BlankScreen -> Width >> 1) * (x + 1.0)),(WORD)((BlankScreen -> Height >> 1) * (y + 1.0)),FlameModulo,BlankScreen -> Width,BlankScreen -> Height);
}
else
{
float nx,ny;
WORD i;
for(i = 0 ; i < 2 ; i++)
{
nx = Flame[0][0][i] * x + Flame[0][1][i] * y + Flame[0][2][i];
ny = Flame[1][0][i] * x + Flame[1][1][i] * y + Flame[1][2][i];
if(i < FlameAlternateForm)
{
nx = sin(nx);
ny = sin(ny);
}
if(!StopDrawing)
{
if(!RecurseMono(nx,ny,Level + 1))
return(FALSE);
}
else
return(FALSE);
}
}
return(TRUE);
}
/* RecurseColour(float x,float y,WORD Level):
*
* Cosmic flame calculation routine (colour).
*/
BYTE
RecurseColour(float x,float y,WORD Level)
{
/* Are we to shut down? */
if(SetSignal(0,0) & SIG_BREAK)
{
Forbid();
Signal(BlankerControlTask,SIG_BREAK);
RemTask(SysBase -> ThisTask);
}
if(StopDrawing)
{
FlameLevel = 0;
StopDrawing = FALSE;
return(FALSE);
}
/* Change the pattern? */
if(SetSignal(0,0) & SIG_CHANGE)
{
SetSignal(0,SIG_CHANGE);
FlameLevel = 0;
StopDrawing = FALSE;
return(FALSE);
}
/* ^E tells the blanker to rotate the
* colours.
*/
if(SetSignal(0,0) & SIG_CYCLE)
{
SetSignal(0,SIG_CYCLE);
if(ColourMode == COLOUR_CYCLE)
{
WORD i;
for(i = 1 ; i < 32 ; i++)
FlameColourTable[i] = Table[(FlameWheel + i) % 75];
LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,32);
FlameWheel = (FlameWheel + 1) % 75;
}
}
if(Level >= MAXFLAMELEVEL)
{
if((FlamePoints++) > MAXTOTALPOINTS)
return(FALSE);
else
MultiPlot(BlankScreen,(WORD)((BlankScreen -> Width >> 1) * (x + 1.0)),(WORD)((BlankScreen -> Height >> 1) * (y + 1.0)),FlameColour + 1);
}
else
{
float nx,ny;
WORD i;
for(i = 0 ; i < 2 ; i++)
{
nx = Flame[0][0][i] * x + Flame[0][1][i] * y + Flame[0][2][i];
ny = Flame[1][0][i] * x + Flame[1][1][i] * y + Flame[1][2][i];
if(i < FlameAlternateForm)
{
nx = sin(nx);
ny = sin(ny);
}
if(!StopDrawing)
{
if(!RecurseColour(nx,ny,Level + 1))
return(FALSE);
}
else
return(FALSE);
}
}
return(TRUE);
}
/* CosmicFlame():
*
* The cosmic flame screen blanker.
*
* xlock.c - X11 client to lock a display and show a screen saver.
*
* Copyright (c) 1988-91 by Patrick J. Naughton.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*/
VOID
CosmicFlame()
{
WORD i,j,k;
/* Monochrome mode? */
if(ColourMode == COLOUR_MONO)
{
BYTE Alternate = FALSE;
/* Initialize defaults. */
FlameModulo = BlankScreen -> RastPort . BitMap -> BytesPerRow;
FlamePlane = BlankScreen -> RastPort . BitMap -> Planes[0];
FlameWheel = 0;
/* Set up the screen colour table. */
FlameColourTable[0] = 0;
FlameColourTable[1] = Table[FlameWheel];
LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,2);
FlameLevel = 0;
/* Go into fractal generation loop. */
FOREVER
{
if(!((FlameLevel++) % 20))
{
LoadRGB4(&BlankScreen -> ViewPort,Black,2);
SetRast(&BlankScreen -> RastPort,0);
LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,2);
Alternate = !Alternate;
}
if(Alternate)
FlameAlternateForm = 0;
else
FlameAlternateForm = Random(2) + 2;
for(k = 0 ; k < 2 ; k++)
{
for(i = 0 ; i < 2 ; i++)
{
for(j = 0; j < 3; j++)
Flame[i][j][k] = ((float)Random(1024)) / 512.0 - 1.0;
}
}
FlamePoints = 0;
RecurseMono(0.0,0.0,0);
}
}
else
{
BYTE Alternate = FALSE,Plus;
FlameWheel = Random(75);
FlameColourTable[0] = 0x000;
for(i = 1 ; i < 32 ; i++)
FlameColourTable[i] = Table[(FlameWheel + i) % 75];
if(ColourMode == COLOUR_CYCLE)
LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,32);
else
LoadRGB4(&BlankScreen -> ViewPort,Rainbow,32);
FlameWheel = (FlameWheel + 1) % 75;
FlameColour = Random(63);
Plus = 1;
FlameLevel = 0;
/* Go into fractal generation loop. */
FOREVER
{
if(!((FlameLevel++) % 20))
{
LoadRGB4(&BlankScreen -> ViewPort,Black,32);
SetRast(&BlankScreen -> RastPort,0);
if(ColourMode == COLOUR_CYCLE)
LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,32);
else
LoadRGB4(&BlankScreen -> ViewPort,Rainbow,32);
Alternate = !Alternate;
}
else
{
if(FlameColour == 62)
Plus = -1;
if(FlameColour == 0)
Plus = 1;
FlameColour += Plus;
}
if(Alternate)
FlameAlternateForm = 0;
else
FlameAlternateForm = Random(2) + 2;
for(k = 0 ; k < 2 ; k++)
{
for(i = 0 ; i < 2 ; i++)
{
for(j = 0; j < 3; j++)
Flame[i][j][k] = ((float)Random(1024)) / 512.0 - 1.0;
}
}
FlamePoints = 0;
RecurseColour(0.0,0.0,0);
}
}
}
/* Blanker():
*
* The screen blanker itself.
*/
VOID __saveds
Blanker()
{
/* Determine fractal type. */
if(FractalType == FRACTAL_COSMIC_FLAME)
CosmicFlame();
else
{
if(FractalType == FRACTAL_REAL_PLANE)
RealPlane();
else
{
if(Random(42) >= 21)
CosmicFlame();
else
RealPlane();
}
}
/* Quietly remove ourselves. */
Forbid();
BlankTask = NULL;
}
/* 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 = 0;
struct InputEvent *Event = (struct InputEvent *)CxMsgData(CxMessage);
/* Push the blanker screen to the front if necessary. */
if(BlankScreen)
Signal(BlankerControlTask,SIG_REFRESH);
/* This looks like a timer event. */
if(Event -> ie_Class == IECLASS_TIMER)
{
if(KeyBlankCount++ >= MouseTimeout * 10)
{
KeyBlankCount = 0;
if(MouseTimeout)
Signal(MouseBlankerTask,SIG_OFF);
}
if(!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)
Signal(BlankerControlTask,SIG_START);
}
}
else
{
/* Every 5/60 second we signal the blanker
* task to rotate the palette.
*/
if(Count++ >= 2)
{
Signal(BlankTask,SIG_CYCLE);
Count = 0;
}
/* Is it time to change the pattern? */
if(PatternTimeout)
{
if(PatternCount++ >= PatternTimeout * 10)
{
Signal(BlankerControlTask,SIG_CHANGE);
PatternCount = 0;
}
}
}
}
}
else
{
/* The following lines determine whether
* the blanker is to be removed or to
* be left running.
*/
switch(Event -> ie_Class)
{
case IECLASS_RAWKEY: if(!(Event -> ie_Code & IECODE_UP_PREFIX) && !(Event -> ie_Qualifier & IEQUALIFIER_REPEAT))
{
if(KeyBlank)
Signal(MouseBlankerTask,SIG_OFF);
Signal(BlankerControlTask,SIG_BREAK);
}
break;
case IECLASS_NEWPOINTERPOS:
case IECLASS_POINTERPOS:
case IECLASS_RAWMOUSE: Signal(MouseBlankerTask,SIG_ON);
Signal(BlankerControlTask,SIG_BREAK);
break;
default: break;
}
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(STRPTR String):
*
* Calculates the number of seconds corresponding to
* expressions such as `11:25' or `10'.
*/
WORD
GetSeconds(STRPTR 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(STRPTR *ToolTypes):
*
* Set up the Commodities interface.
*/
BYTE __regargs
SetupCx(STRPTR *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);
/* Which fractal type? */
String = ArgString(ToolTypes,"FRACTAL","RANDOM");
if(!Stricmp(String,"REALPLANE") || !Stricmp(String,"REAL"))
FractalType = FRACTAL_REAL_PLANE;
else
{
if(!Stricmp(String,"COSMICFLAME") || !Stricmp(String,"FLAME"))
FractalType = FRACTAL_COSMIC_FLAME;
else
FractalType = FRACTAL_RANDOM;
}
/* Which colour mode? */
String = ArgString(ToolTypes,"COLOUR","CYCLE");
if(!Stricmp(String,"STATIC"))
ColourMode = COLOUR_STATIC;
else
{
if(!Stricmp(String,"MONO"))
ColourMode = COLOUR_MONO;
else
ColourMode = COLOUR_CYCLE;
}
/* 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);
/* Adjust the mouse timeout if possible. */
strcpy(Buffer,ArgString(ToolTypes,"MOUSETIMEOUT","0:05"));
MouseTimeout = GetSeconds(Buffer);
/* Determine whether to enable the keypress
* mouse blanker or not.
*/
String = ArgString(ToolTypes,"KEYBLANK","Yes");
if(!Stricmp(String,"No") || !Stricmp(String,"Off"))
KeyBlank = FALSE;
else
KeyBlank = TRUE;
}
/* 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)
Signal(BlankerControlTask,SIG_START);
else
{
Signal(BlankerControlTask,SIG_CHANGE);
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;
WindowWidth = 42 * DefaultFontWidth + 20;
WindowHeight = TopEdge + 10 + 9 * (DefaultFont . ta_YSize + 6 + INTERHEIGHT) + 4;
if(Gadget = CreateContext(GadgetList))
{
NewGadget . ng_Width = DefaultFontWidth * 20;
NewGadget . ng_Height = DefaultFont . ta_YSize + 6;
NewGadget . ng_GadgetText = "_Screen Timeout ";
NewGadget . ng_TextAttr = &DefaultFont;
NewGadget . ng_VisualInfo = VisualInfo;
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_Flags = 0;
NewGadget . ng_LeftEdge = DefaultFontWidth * 22 + 10;
NewGadget . ng_TopEdge = TopEdge + 6;
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 = "_Mouse Timeout ";
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_TopEdge += NewGadget . ng_Height + INTERHEIGHT;
GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
GTSL_Min, 0,
GTSL_Max, 30 * 60,
GTSL_Level, MouseTimeout,
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 + INTERHEIGHT;
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 + INTERHEIGHT;
GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
GTST_MaxChars, 255,
GTST_String, HotkeyBuffer,
TAG_DONE);
NewGadget . ng_GadgetText = "_Blank Screen";
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_TopEdge += NewGadget . ng_Height + INTERHEIGHT;
GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
GTST_MaxChars, 255,
GTST_String, BlankScreenBuffer,
TAG_DONE);
NewGadget . ng_GadgetText = "Ke_ypress blanks mouse";
NewGadget . ng_Width = 26;
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_TopEdge += NewGadget . ng_Height + INTERHEIGHT;
GadgetArray[Counter++] = Gadget = CreateGadget(CHECKBOX_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
GTCB_Checked, KeyBlank,
TAG_DONE);
NewGadget . ng_GadgetText = "_Fractal Type";
NewGadget . ng_Width = DefaultFontWidth * 20;
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_TopEdge += NewGadget . ng_Height + INTERHEIGHT;
GadgetArray[Counter++] = Gadget = CreateGadget(CYCLE_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
GTCY_Labels, FractalModes,
GTCY_Active, FractalType,
TAG_DONE);
NewGadget . ng_GadgetText = "_Colour Mode";
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_TopEdge += NewGadget . ng_Height + INTERHEIGHT;
GadgetArray[Counter++] = Gadget = CreateGadget(CYCLE_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
GTCY_Labels, ColourModes,
GTCY_Active, ColourMode,
TAG_DONE);
NewGadget . ng_GadgetText = "_Hide";
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_Flags = 0;
NewGadget . ng_LeftEdge = 10;
NewGadget . ng_TopEdge += NewGadget . ng_Height + 4 + INTERHEIGHT;
GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
GT_Underscore, '_',
TAG_DONE);
NewGadget . ng_GadgetText = "_Quit";
NewGadget . ng_GadgetID = Counter;
NewGadget . ng_LeftEdge = WindowWidth - 10 - 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);
ZoomData . Left = -1;
Window = NULL;
}
if(GadgetList)
{
FreeGadgets(GadgetList);
GadgetList = NULL;
}
if(VisualInfo)
{
FreeVisualInfo(VisualInfo);
VisualInfo = NULL;
}
if(DefaultScreen)
{
UnlockPubScreen(NULL,DefaultScreen);
DefaultScreen = NULL;
}
if(LocalFont)
{
CloseFont(LocalFont);
LocalFont = 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 - (WindowWidth >> 1);
(*TopEdge) = Screen -> MouseY - (WindowHeight >> 1);
while((*LeftEdge) + WindowWidth > Screen -> Width)
(*LeftEdge)--;
while((*LeftEdge) < 0)
(*LeftEdge)++;
while((*TopEdge) + WindowHeight > 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);
RethinkDisplay();
CloseScreen(Screen);
}
if(Window)
{
struct Window *ActiveWindow;
struct Screen *FirstScreen;
ULONG IntuiLock;
BYTE ZipIt;
IntuiLock = LockIBase(NULL);
FirstScreen = IntuitionBase -> FirstScreen;
ActiveWindow = IntuitionBase -> ActiveWindow;
UnlockIBase(IntuiLock);
if(Window -> WScreen -> TopEdge > 0)
{
MoveScreen(Window -> WScreen,0,-Window -> WScreen -> TopEdge);
ZipIt = FALSE;
}
else
ZipIt = TRUE;
if(FirstScreen != Window -> WScreen)
{
ScreenToFront(Window -> WScreen);
ZipIt = FALSE;
}
else
ZipIt = TRUE;
if(ActiveWindow != Window)
{
ActivateWindow(Window);
ZipIt = FALSE;
}
else
ZipIt = TRUE;
if(Window -> Height != WindowHeight)
ZipIt = TRUE;
WindowToFront(Window);
if(ZipIt)
ZipWindow(Window);
return(TRUE);
}
else
{
Forbid();
strcpy(DefaultFontName,GfxBase -> DefaultFont -> tf_Message . mn_Node . ln_Name);
DefaultFont . ta_Name = DefaultFontName;
DefaultFont . ta_YSize = GfxBase -> DefaultFont -> tf_YSize;
DefaultFont . ta_Style = GfxBase -> DefaultFont -> tf_Style;
DefaultFont . ta_Flags = GfxBase -> DefaultFont -> tf_Flags & ~FPF_REMOVED;
DefaultFontWidth = GfxBase -> DefaultFont -> tf_XSize;
Permit();
if(LocalFont = (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 . Left == -1)
{
ZoomData . Left = 0;
ZoomData . Top = 0;
ZoomData . Width = WindowWidth >> 1;
ZoomData . Height = DefaultScreen -> WBorTop + DefaultScreen -> Font -> ta_YSize + 1;
}
if(Window = OpenWindowTags(NULL,
WA_CustomScreen, DefaultScreen,
WA_Left, Left,
WA_Top, Top,
WA_Width, WindowWidth,
WA_Height, WindowHeight,
WA_Activate, TRUE,
WA_DragBar, TRUE,
WA_DepthGadget, TRUE,
WA_CloseGadget, TRUE,
WA_RMBTrap, TRUE,
WA_Zoom, &ZoomData,
WA_NoCareRefresh, TRUE,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | IDCMP_REFRESHWINDOW | IDCMP_NEWSIZE | SLIDERIDCMP | BUTTONIDCMP,
WA_Title, "Fractal Blanker v2.2",
TAG_DONE))
{
SetFont(Window -> RPort,LocalFont);
AddGList(Window,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
RefreshGList(GadgetList,Window,NULL,(UWORD)-1);
GT_RefreshWindow(Window,NULL);
if(Window -> WScreen -> TopEdge > 0)
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(MouseBlankerTask)
{
Signal(MouseBlankerTask,SIG_BREAK);
Wait(SIG_WAKEUP);
}
if(BlankerControlTask)
RemTask(BlankerControlTask);
if(BlankTask)
RemTask(BlankTask);
if(BlankScreen)
{
ScreenToBack(BlankScreen);
FreeVPortCopLists(&BlankScreen -> ViewPort);
RethinkDisplay();
CloseScreen(BlankScreen);
BlankScreen = NULL;
}
ShutdownWindow();
if(IconBase)
CloseLibrary(IconBase);
if(UtilityBase)
CloseLibrary(UtilityBase);
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;
/* Set up the pointer to our process structure. */
MainProcess = (struct Process *)SysBase -> ThisTask;
/* 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(!(UtilityBase = OpenLibrary("utility.library",37)))
CloseAll(RETURN_FAIL + 4);
if(!(IconBase = OpenLibrary("icon.library",37)))
CloseAll(RETURN_FAIL + 5);
if(!(BlankerControlTask = (struct Task *)CreateTask("FracBlank Control Task",100,BlankerControl,8192)))
CloseAll(RETURN_FAIL + 6);
if(!(MouseBlankerTask = (struct Task *)CreateTask("FracBlank Mouse Blanker Task",100,MouseBlanker,8192)))
CloseAll(RETURN_FAIL + 7);
/* Wait for handshake signal. */
Wait(SIG_WAKEUP);
/* Is the blanker still running? */
if(!MouseBlankerTask)
CloseAll(RETURN_FAIL + 8);
/* 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 + 9);
/* Pop up the control panel if necessary. */
if(ToolTypes)
{
String = ArgString(ToolTypes,"CX_POPUP","no");
if(!Stricmp(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
{
/* Wait for a signal... */
SignalSet = Wait(SIG_CX | SIG_BREAK | SIG_WAKEUP | SIG_WINDOW);
/* Check the commodities toolkit reply port. */
if(SignalSet & SIG_CX)
{
CxMsg *Message;
while(Message = (CxMsg *)GetMsg(CxPort))
HandleCxMsg(Message);
}
/* ^C tells the program to quit. */
if(SignalSet & SIG_BREAK)
CloseAll(RETURN_OK);
/* ^F tells the program to open its control panel. */
if(SignalSet & SIG_WAKEUP)
SetupWindow();
/* If the control panel is still open,
* check for new messages.
*/
if(SignalSet & SIG_WINDOW)
{
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;
/* Gadtools does not seem to handle
* it yet: refresh the window
* contents.
*/
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_MOUSETIMEOUT: MouseTimeout = Code;
break;
case GAD_PATTERNCHANGE: PatternCount = 0;
PatternTimeout = Code;
break;
}
break;
/* Handle the keyboard shortcuts. */
case IDCMP_VANILLAKEY: switch(Code)
{
case 's': ScreenCount = 0;
if(ScreenTimeout + 1 <= 30 * 60)
ScreenTimeout++;
GT_SetGadgetAttrs(GadgetArray[GAD_SCREENTIMEOUT],Window,NULL,
GTSL_Level,ScreenTimeout,
TAG_DONE);
break;
case 'S': ScreenCount = 0;
if(ScreenTimeout > 0)
ScreenTimeout--;
GT_SetGadgetAttrs(GadgetArray[GAD_SCREENTIMEOUT],Window,NULL,
GTSL_Level,ScreenTimeout,
TAG_DONE);
break;
case 'm': if(MouseTimeout + 1 <= 30 * 60)
MouseTimeout++;
GT_SetGadgetAttrs(GadgetArray[GAD_MOUSETIMEOUT],Window,NULL,
GTSL_Level,MouseTimeout,
TAG_DONE);
break;
case 'M': if(MouseTimeout > 0)
MouseTimeout--;
GT_SetGadgetAttrs(GadgetArray[GAD_MOUSETIMEOUT],Window,NULL,
GTSL_Level,MouseTimeout,
TAG_DONE);
break;
case 'p': PatternCount = 0;
if(PatternTimeout + 1 <= 30 * 60)
PatternTimeout++;
GT_SetGadgetAttrs(GadgetArray[GAD_PATTERNCHANGE],Window,NULL,
GTSL_Level,PatternTimeout,
TAG_DONE);
break;
case 'P': PatternCount = 0;
if(PatternTimeout > 0)
PatternTimeout--;
GT_SetGadgetAttrs(GadgetArray[GAD_PATTERNCHANGE],Window,NULL,
GTSL_Level,PatternTimeout,
TAG_DONE);
break;
case 'k':
case 'K': ActivateGadget(GadgetArray[GAD_HOTKEY],Window,NULL);
break;
case 'b':
case 'B': ActivateGadget(GadgetArray[GAD_BLANKSCREEN],Window,NULL);
break;
case 'y':
case 'Y': KeyBlank ^= TRUE;
GT_SetGadgetAttrs(GadgetArray[GAD_KEYBLANK],Window,NULL,
GTCB_Checked,KeyBlank,
TAG_DONE);
break;
case 'f': FractalType = (FractalType + 1) % 3;
GT_SetGadgetAttrs(GadgetArray[GAD_FRACTAL],Window,NULL,
GTCY_Active,FractalType,
TAG_DONE);
break;
case 'F': if(FractalType)
FractalType--;
else
FractalType = FRACTAL_RANDOM;
GT_SetGadgetAttrs(GadgetArray[GAD_FRACTAL],Window,NULL,
GTCY_Active,FractalType,
TAG_DONE);
break;
case 'c': ColourMode = (ColourMode + 1) % 3;
GT_SetGadgetAttrs(GadgetArray[GAD_COLOUR],Window,NULL,
GTCY_Active,ColourMode,
TAG_DONE);
break;
case 'C': if(ColourMode)
ColourMode--;
else
ColourMode = COLOUR_MONO;
GT_SetGadgetAttrs(GadgetArray[GAD_COLOUR],Window,NULL,
GTCY_Active,ColourMode,
TAG_DONE);
break;
case '\033':
case 'h':
case 'H': ShutdownWindow();
break;
case 3:
case 'q':
case 'Q': CloseAll(RETURN_OK);
default: break;
}
break;
/* Handle the gadgets themselves. */
case IDCMP_GADGETUP: switch(Gadget -> GadgetID)
{
case GAD_HOTKEY: strcpy(HotkeyBuffer,GT_STRING(Gadget));
if(!SetupCx(NULL))
CloseAll(RETURN_FAIL + 5);
break;
case GAD_BLANKSCREEN: strcpy(BlankScreenBuffer,GT_STRING(Gadget));
if(!SetupCx(NULL))
CloseAll(RETURN_FAIL + 5);
break;
case GAD_KEYBLANK: KeyBlank = GT_CHECKED(Gadget);
break;
case GAD_FRACTAL: FractalType = Code;
break;
case GAD_COLOUR: ColourMode = Code;
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;
}
}
}
}