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 >
C/C++ Source or Header  |  1992-06-26  |  62KB  |  3,047 lines

  1. /*
  2. **    FracBlank - AmigaDOS 2.04 commodities utility screenblanker
  3. **
  4. **    Copyright © 1991-1992 by Olaf `Olsen' Barthel
  5. **        All Rights Reserved
  6. **
  7. **    Cosmic flame fractal code derived from xlock source code
  8. **
  9. **    Copyright © 1988-1991 by Patrick J. Naughton.
  10. */
  11.  
  12.     /* Include the specific math pragmas/header files here (is there
  13.      * any way to figure this out by taking a look at undocumented
  14.      * predefined compiler symbols?).
  15.      */
  16.  
  17. #ifdef MATH_FFP
  18. #include <clib/mathtrans_protos.h>
  19. #include <proto/mathtrans.h>
  20. #include <mffp.h>
  21. #else
  22. #include <m68881.h>
  23. #endif    /* MATH_FFP */
  24.  
  25. #include <math.h>
  26.  
  27.     /* sin -45° = cos -45° (saves precious calculation time). */
  28.  
  29. #define deg45    (-0.707106781)
  30.  
  31.     /* Use a simple address trick instead of the predefined
  32.      * address in amiga.lib.
  33.      */
  34.  
  35. #ifndef custom
  36. #define custom (*(struct Custom *)0xDFF000)
  37. #endif    /* custom */
  38.  
  39.     /* A couple of handy gadget control macros. */
  40.  
  41. #define GT_CHECKED(G)    ((((struct Gadget *)(G)) -> Flags & GFLG_SELECTED) ? TRUE : FALSE)
  42. #define GT_STRING(G)    (((struct StringInfo *)(((struct Gadget *)(G)) -> SpecialInfo)) -> Buffer)
  43.  
  44.     /* Hotkey IDs. */
  45.  
  46. enum    {    POP_WINDOW,BLANK_SCREEN };
  47.  
  48.     /* Gadget IDs. */
  49.  
  50. enum    {    GAD_SCREENTIMEOUT,GAD_MOUSETIMEOUT,GAD_PATTERNCHANGE,GAD_HOTKEY,
  51.         GAD_BLANKSCREEN,GAD_KEYBLANK,GAD_FRACTAL,GAD_COLOUR,GAD_HIDE,GAD_QUIT };
  52.  
  53.     /* Some useful signals. */
  54.  
  55. #define SIG_BREAK    SIGBREAKF_CTRL_C
  56. #define SIG_CHANGE    SIGBREAKF_CTRL_D
  57. #define SIG_CYCLE    SIGBREAKF_CTRL_E
  58. #define SIG_START    SIGBREAKF_CTRL_F
  59. #define SIG_REFRESH    SIGBREAKF_CTRL_E
  60. #define SIG_WAKEUP    SIGBREAKF_CTRL_F
  61. #define SIG_CX        (1 << CxPort -> mp_SigBit)
  62. #define SIG_WINDOW    (Window ? (1 << Window -> UserPort -> mp_SigBit) : NULL)
  63.  
  64.     /* Private mouse blanker signals. */
  65.  
  66. #define SIG_NOTICE    SIGBREAKF_CTRL_D
  67. #define SIG_ON        SIGBREAKF_CTRL_E
  68. #define SIG_OFF        SIGBREAKF_CTRL_F
  69.  
  70.     /* Number of patches to install. */
  71.  
  72. #define NUM_PATCHES    (sizeof(PatchTable) / sizeof(struct PatchInfo))
  73.  
  74.     /* Cosmic flame fractal parameters. */
  75.  
  76. #define MAXFLAMELEVEL    20
  77. #define MAXTOTALPOINTS    20000
  78.  
  79.     /* Fractal types. */
  80.  
  81. enum    {    FRACTAL_REAL_PLANE,FRACTAL_COSMIC_FLAME,FRACTAL_RANDOM };
  82.  
  83.     /* Colour modes. */
  84.  
  85. enum    {    COLOUR_CYCLE,COLOUR_STATIC,COLOUR_MONO };
  86.  
  87.     /* A system library patch definition. */
  88.  
  89. struct PatchInfo
  90. {
  91.     APTR         NewRoutine;
  92.     LONG         Offset;
  93.     ULONG        *Destination;
  94. };
  95.  
  96.     /* A window identification node, also contains information
  97.      * on the currently selected pointer sprite.
  98.      */
  99.  
  100. struct WindowNode
  101. {
  102.     struct MinNode     Node;
  103.  
  104.     struct Window    *Window;
  105.  
  106.     UWORD        *Pointer;
  107.     BYTE         Height,
  108.              Width;
  109.     BYTE         XOffset,
  110.              YOffset;
  111.     BYTE         Off;
  112. };
  113.  
  114.     /* The offsets of the system library routines we will patch. */
  115.  
  116. extern ULONG __far     LVOClearPointer,
  117.              LVOSetPointer,
  118.              LVOOpenWindow,
  119.              LVOOpenWindowTagList,
  120.              LVOCloseWindow;
  121.  
  122.     /* Program revision tag. */
  123.  
  124. STATIC const UBYTE VersTag[] = "\0$VER: FracBlank 2.2 (4.4.92)";
  125.  
  126.     /* Shared library identifiers. */
  127.  
  128. extern struct ExecBase    *SysBase;
  129.  
  130. struct IntuitionBase    *IntuitionBase;
  131. struct GfxBase        *GfxBase;
  132. struct Library        *CxBase,
  133.             *IconBase,
  134.             *GadToolsBase,
  135.             *UtilityBase;
  136.  
  137.     /* The main program. */
  138.  
  139. struct Process        *MainProcess;
  140.  
  141.     /* Blanker data. */
  142.  
  143. struct Task        *BlankTask;
  144. struct Screen        *BlankScreen;
  145.  
  146.     /* BlankerControl data. */
  147.  
  148. struct Task        *BlankerControlTask;
  149.  
  150.     /* Mouse blanker data. */
  151.  
  152. struct Task        *MouseBlankerTask;
  153.  
  154.     /* Commodities interface data. */
  155.  
  156. struct MsgPort        *CxPort;
  157. CxObj            *Broker;
  158.  
  159.     /* Gfx and gadtools data. */
  160.  
  161. struct Screen        *DefaultScreen;
  162. APTR             VisualInfo;
  163. struct TextFont        *LocalFont;
  164. struct Gadget        *GadgetList;
  165. struct Gadget        *GadgetArray[GAD_QUIT + 1];
  166. struct Window        *Window;
  167.  
  168.     /* Window zoom data. */
  169.  
  170. struct IBox         ZoomData = { -1,-1,-1,-1 };
  171.  
  172.     /* Window dimensions. */
  173.  
  174. WORD             WindowWidth    = 284,
  175.              WindowHeight    = 113;
  176.  
  177.     /* Rainbow colour table. */
  178.  
  179. UWORD             Table[75];
  180.  
  181.     /* No colours at all. */
  182.  
  183. UWORD             Black[32];
  184.  
  185.     /* Declarations for cosmic flame blanker code. */
  186.  
  187. float             Flame[2][3][2];
  188. WORD             FlameLevel,
  189.              FlameAlternateForm,
  190.              FlameModulo;
  191. UWORD             FlameColourTable[32];
  192. BYTE             FlameWheel,
  193.              FlameColour;
  194. PLANEPTR         FlamePlane;
  195. ULONG             FlamePoints;
  196.  
  197.     /* Key sequence buffers. */
  198.  
  199. UBYTE             HotkeyBuffer[256],
  200.              BlankScreenBuffer[256];
  201.  
  202.     /* Screen and pattern change timeout. */
  203.  
  204. ULONG             ScreenCount    = 0,
  205.              PatternCount    = 0,
  206.              ScreenTimeout    = 60,
  207.              MouseTimeout    = 5,
  208.              PatternTimeout    = 60;
  209.  
  210.     /* A flag which tells us whether to blank the mouse pointer
  211.      * on a keypress or not.
  212.      */
  213.  
  214. BYTE             KeyBlank    = TRUE;
  215.  
  216.     /* Some kind of a semaphore to tell the blank task to stop drawing. */
  217.  
  218. BYTE             StopDrawing    = FALSE;
  219.  
  220.     /* The default font to be used by the control panel. */
  221.  
  222. struct TextAttr         DefaultFont;
  223. UBYTE             DefaultFontName[256];
  224. UWORD             DefaultFontWidth;
  225.  
  226.     /* The colours of a rainbow (well, with a bit of imagination, just
  227.      * 32 colours in this rainbow for now).
  228.      */
  229.  
  230. UWORD Rainbow[32] =
  231. {
  232.     0x0000,0x0F00,0x0F30,0x0F50,
  233.     0x0F70,0x0F90,0x0FB0,0x0FD0,
  234.     0x0FF0,0x0DF0,0x0BF0,0x09F0,
  235.     0x07F0,0x05F0,0x03F0,0x00F0,
  236.     0x00D1,0x00B3,0x0095,0x0077,
  237.     0x0059,0x003B,0x001D,0x000F,
  238.     0x010F,0x030F,0x050F,0x070F,
  239.     0x090F,0x0B0F,0x0D0F,0x0F0F
  240. };
  241.  
  242.     /* A new broker definition, Commodities needs this. */
  243.  
  244. struct NewBroker NewBroker =
  245. {
  246.     NB_VERSION,
  247.     "FracBlanker",
  248.     "Fractal Blanker v2.2",
  249.     "Screen Blanker",
  250.     NBU_NOTIFY | NBU_UNIQUE,
  251.     COF_SHOW_HIDE,
  252.     0,NULL,0
  253. };
  254.  
  255.     /* The fractal mode names. */
  256.  
  257. STRPTR FractalModes[] =
  258. {
  259.     "Real Plane",
  260.     "Cosmic Flame",
  261.     "Random",
  262.     NULL
  263. };
  264.  
  265.     /* The current fractal type. */
  266.  
  267. UBYTE    FractalType = FRACTAL_RANDOM;
  268.  
  269.     /* The colour mode names. */
  270.  
  271. STRPTR ColourModes[] =
  272. {
  273.     "Cycling Colours",
  274.     "Static Colours",
  275.     "Monochrome",
  276.     NULL
  277. };
  278.  
  279.     /* The current colour mode. */
  280.  
  281. UBYTE    ColourMode = COLOUR_CYCLE;
  282.  
  283.     /* Patch data. */
  284.  
  285. extern VOID __stdargs         StackOldSetPointer(struct Window *Window,UWORD *Pointer,WORD Height,WORD Width,WORD XOffset,WORD YOffset);
  286. extern VOID              NewSetPointer(VOID);
  287.  
  288. APTR                 OldSetPointer;
  289.  
  290. VOID            (* __asm OldClearPointer)(register __a0 struct Window *,register __a6 struct IntuitionBase *);
  291. struct Window *        (* __asm OldOpenWindowTagList)(register __a0 struct NewWindow *,register __a1 struct TagItem *,register __a6 struct IntuitionBase *);
  292. struct Window *        (* __asm OldOpenWindow)(register __a0 struct NewWindow *,register __a6 struct IntuitionBase *);
  293. VOID            (* __asm OldCloseWindow)(register __a0 struct Window *,register __a6 struct IntuitionBase *);
  294.  
  295.     /* Mouse blanker function prototypes. */
  296.  
  297. VOID __stdargs __saveds         StackNewSetPointer(struct Window *Window,UWORD *Pointer,WORD Height,WORD Width,WORD XOffset,WORD YOffset);
  298.  
  299. VOID __asm __saveds         NewClearPointer(register __a0 struct Window *Window);
  300. struct Window * __asm __saveds     NewOpenWindowTagList(register __a0 struct NewWindow *NewWindow,register __a1 struct TagItem *TagList);
  301. struct Window * __asm __saveds     NewOpenWindow(register __a0 struct NewWindow *NewWindow);
  302. VOID __asm __saveds         NewCloseWindow(register __a0 struct Window *Window);
  303.  
  304. VOID __saveds             MouseBlanker(VOID);
  305.  
  306. VOID __regargs             UpdateNode(struct WindowNode *Node,struct Window *Window);
  307. struct WindowNode * __regargs     NewNode(struct Window *Window);
  308.  
  309. VOID                 TurnOff(VOID);
  310. VOID                 TurnOn(VOID);
  311.  
  312.     /* The window and mouse pointer access list. */
  313.  
  314. struct SignalSemaphore     WindowSemaphore;
  315. struct List         WindowList;
  316.  
  317.     /* Miscellaneous mouse blanker counters and flags. */
  318.  
  319. ULONG             KeyBlankUseCnt    = 0,
  320.              KeyBlankCount    = 0;
  321. BYTE             AllSpritesOff    = FALSE,
  322.              KeyBlankStop    = FALSE;
  323.  
  324.     /* The table of patches to install. */
  325.  
  326. struct PatchInfo PatchTable[] =
  327. {
  328.     NewClearPointer,    (LONG)&LVOClearPointer,        (ULONG *)&OldClearPointer,
  329.     NewSetPointer,        (LONG)&LVOSetPointer,        (ULONG *)&OldSetPointer,
  330.     NewOpenWindowTagList,    (LONG)&LVOOpenWindowTagList,    (ULONG *)&OldOpenWindowTagList,
  331.     NewOpenWindow,        (LONG)&LVOOpenWindow,        (ULONG *)&OldOpenWindow,
  332.     NewCloseWindow,        (LONG)&LVOCloseWindow,        (ULONG *)&OldCloseWindow
  333. };
  334.  
  335.     /* An entirely transparent sprite. */
  336.  
  337. UWORD __chip BlankSprite[(2 + 1) * 2] =
  338. {
  339.     0x0000,0x0000,
  340.  
  341.     0x0000,0x0000,
  342.  
  343.     0x0000,0x0000
  344. };
  345.  
  346.     /* Function prototypes. */
  347.  
  348. 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);
  349. extern VOID __asm    MultiPlot(register __a0 struct Screen *,register __d0 WORD X,register __d1 WORD Y,register __d2 WORD Colour);
  350.  
  351. extern __stdargs    SPrintf(STRPTR Mem,STRPTR Args,...);
  352. extern LONG __asm    Atol(register __a0 STRPTR String);
  353.  
  354. VOID __saveds        BlankerControl(VOID);
  355. ULONG __regargs        Random(ULONG MaxValue);
  356. VOID            RealPlane(VOID);
  357. VOID            CosmicFlame(VOID);
  358. BYTE            RecurseMono(float x,float y,WORD Level);
  359. BYTE            RecurseColour(float x,float y,WORD Level);
  360. VOID __saveds        Blanker(VOID);
  361. VOID __saveds __stdargs    BlankerAction(CxMsg *CxMessage,CxObj *CxObject);
  362. VOID            ShutdownCx(VOID);
  363. BYTE __regargs        SetupCx(STRPTR *ToolTypes);
  364. VOID __regargs        HandleCxMsg(CxMsg *Message);
  365. LONG __saveds __stdargs    ShowTime(struct Gadget *SomeGadget,WORD Level);
  366. struct Gadget *        CreateAllGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge);
  367. VOID            ShutdownWindow(VOID);
  368. VOID __regargs        CentreWindow(struct Screen *Screen,WORD *LeftEdge,WORD *TopEdge);
  369. BYTE            SetupWindow(VOID);
  370. VOID __regargs        CloseAll(LONG ReturnCode);
  371. VOID __regargs        OpenAll(int argc,char **argv);
  372. VOID __stdargs        main(int argc,char **argv);
  373.  
  374.     /* MouseBlanker():
  375.      *
  376.      *    The mouse pointer blanker task, patches a few system library functions
  377.      *    and turns the mouse pointer on and off.
  378.      */
  379.  
  380. VOID __saveds
  381. MouseBlanker()
  382. {
  383.     struct Wedge *WedgeTable;
  384.  
  385.         /* Create the wedge table, note: this memory will never be
  386.          * freed!
  387.          */
  388.  
  389.     if(WedgeTable = (struct Wedge *)AllocMem(sizeof(struct Wedge) * NUM_PATCHES,MEMF_PUBLIC | MEMF_CLEAR))
  390.     {
  391.         struct WindowNode    *Node,
  392.                     *Next;
  393.         ULONG             IntuiLock,
  394.                      SignalSet;
  395.         struct Screen        *Screen;
  396.         struct Window        *Window;
  397.         BYTE             Terminated = FALSE;
  398.         WORD             i;
  399.  
  400.             /* Set up the window list data. */
  401.  
  402.         InitSemaphore(&WindowSemaphore);
  403.  
  404.         NewList(&WindowList);
  405.  
  406.             /* Put all windows into the list. */
  407.  
  408.         IntuiLock = LockIBase(NULL);
  409.  
  410.         Screen = IntuitionBase -> FirstScreen;
  411.  
  412.         while(Screen)
  413.         {
  414.             Window = Screen -> FirstWindow;
  415.  
  416.             while(Window)
  417.             {
  418.                 NewNode(Window);
  419.  
  420.                 Window = Window -> NextWindow;
  421.             }
  422.  
  423.             Screen = Screen -> NextScreen;
  424.         }
  425.  
  426.         Forbid();
  427.  
  428.         UnlockIBase(IntuiLock);
  429.  
  430.             /* Install the patches. */
  431.  
  432.         for(i = 0 ; i < NUM_PATCHES ; i++)
  433.         {
  434.             WedgeTable[i] . Command    = JMP_ABS;
  435.             WedgeTable[i] . Address    = PatchTable[i] . NewRoutine;
  436.  
  437.             *PatchTable[i] . Destination = (ULONG)SetFunction((struct Library *)IntuitionBase,PatchTable[i] . Offset,(APTR)&WedgeTable[i]);
  438.         }
  439.  
  440.         CacheClearU();
  441.  
  442.             /* Ring back. */
  443.  
  444.         Signal(MainProcess,SIG_WAKEUP);
  445.  
  446.         Permit();
  447.  
  448.             /* Loop until terminated. */
  449.  
  450.         while(!Terminated)
  451.         {
  452.                 /* Wait for a signal. */
  453.  
  454.             SignalSet = Wait(SIG_BREAK | SIG_ON | SIG_OFF);
  455.  
  456.                 /* Are we to quit? */
  457.  
  458.             if(SignalSet & SIG_BREAK)
  459.                 Terminated = TRUE;
  460.  
  461.                 /* Are we to turn the mouse pointer sprite back on? */
  462.  
  463.             if(SignalSet & SIG_ON)
  464.                 TurnOn();
  465.  
  466.                 /* Are we to turn all mouse pointer sprites off? */
  467.  
  468.             if(SignalSet & SIG_OFF)
  469.                 TurnOff();
  470.         }
  471.  
  472.         Forbid();
  473.  
  474.             /* Clear the notification signal. */
  475.  
  476.         SetSignal(0,SIG_NOTICE);
  477.  
  478.             /* Do not continue adding new nodes to the list. */
  479.  
  480.         KeyBlankStop = TRUE;
  481.  
  482.         Permit();
  483.  
  484.             /* Turn all sprites back on. */
  485.  
  486.         TurnOn();
  487.  
  488.             /* Remove the patches. */
  489.  
  490.         Forbid();
  491.  
  492.         for(i = 0 ; i < NUM_PATCHES ; i++)
  493.             WedgeTable[i] . Address    = (APTR)*PatchTable[i] . Destination;
  494.  
  495.         CacheClearU();
  496.  
  497.         Permit();
  498.  
  499.             /* Loop until all patched routines are clear. */
  500.  
  501.         while(KeyBlankUseCnt > 0)
  502.             Wait(SIG_NOTICE);
  503.  
  504.             /* Remove all windows from the list. */
  505.  
  506.         Node = (struct WindowNode *)WindowList . lh_Head;
  507.  
  508.         while(Next = (struct WindowNode *)Node -> Node . mln_Succ)
  509.         {
  510.             Remove((struct Node *)Node);
  511.  
  512.             FreeVec(Node);
  513.  
  514.             Node = Next;
  515.         }
  516.     }
  517.  
  518.         /* We're done now. */
  519.  
  520.     Forbid();
  521.  
  522.     Signal(MainProcess,SIG_WAKEUP);
  523. }
  524.  
  525.     /* UpdateNode(struct WindowNode *Node,struct Window *Window):
  526.      *
  527.      *    Update a window node with the new pointer data.
  528.      */
  529.  
  530. VOID __regargs
  531. UpdateNode(struct WindowNode *Node,struct Window *Window)
  532. {
  533.     Node -> Pointer    = Window -> Pointer;
  534.     Node -> Height    = Window -> PtrHeight;
  535.     Node -> Width    = Window -> PtrWidth;
  536.     Node -> XOffset    = Window -> XOffset;
  537.     Node -> YOffset    = Window -> YOffset;
  538. }
  539.  
  540.     /* NewNode(struct Window *Window):
  541.      *
  542.      *    Create a new window node and link it into the window list.
  543.      */
  544.  
  545. struct WindowNode * __regargs
  546. NewNode(struct Window *Window)
  547. {
  548.     struct WindowNode *Node;
  549.  
  550.     if(Node = (struct WindowNode *)AllocVec(sizeof(struct WindowNode),MEMF_PUBLIC | MEMF_CLEAR))
  551.     {
  552.         Node -> Window = Window;
  553.  
  554.         UpdateNode(Node,Window);
  555.  
  556.         AddTail(&WindowList,(struct Node *)Node);
  557.     }
  558.  
  559.     return(Node);
  560. }
  561.  
  562.     /* FindWindow(struct Window *Window):
  563.      *
  564.      *    Find a window within the window list.
  565.      */
  566.  
  567. struct WindowNode * __regargs
  568. FindWindow(struct Window *Window)
  569. {
  570.     struct WindowNode    *Node,
  571.                 *Next;
  572.  
  573.     Node = (struct WindowNode *)WindowList . lh_Head;
  574.  
  575.     while(Next = (struct WindowNode *)Node -> Node . mln_Succ)
  576.     {
  577.         if(Window == Node -> Window)
  578.             return(Node);
  579.  
  580.         Node = Next;
  581.     }
  582.  
  583.     return(NULL);
  584. }
  585.  
  586.     /* TurnOff():
  587.      *
  588.      *    Turn all mouse pointer sprites in all windows off.
  589.      */
  590.  
  591. VOID
  592. TurnOff()
  593. {
  594.         /* Gain access to the window semaphore. */
  595.  
  596.     ObtainSemaphore(&WindowSemaphore);
  597.  
  598.         /* Are all sprites still turned off? */
  599.  
  600.     if(!AllSpritesOff)
  601.     {
  602.         struct WindowNode    *Node,
  603.                     *Next;
  604.  
  605.             /* Walk through the window list... */
  606.  
  607.         Node = (struct WindowNode *)WindowList . lh_Head;
  608.  
  609.         while(Next = (struct WindowNode *)Node -> Node . mln_Succ)
  610.         {
  611.                 /* Is this mouse pointer still active? */
  612.  
  613.             if(!Node -> Off)
  614.             {
  615.                     /* Update the node entry. */
  616.  
  617.                 UpdateNode(Node,Node -> Window);
  618.  
  619.                     /* Change the pointer. */
  620.  
  621.                 StackOldSetPointer(Node -> Window,BlankSprite,1,16,0,0);
  622.  
  623.                 Node -> Off = TRUE;
  624.             }
  625.  
  626.             Node = Next;
  627.         }
  628.  
  629.         AllSpritesOff = TRUE;
  630.     }
  631.  
  632.     ReleaseSemaphore(&WindowSemaphore);
  633. }
  634.  
  635.     /* TurnOn():
  636.      *
  637.      *    Turn all mouse pointer sprites in all windows back on.
  638.      */
  639.  
  640. VOID
  641. TurnOn()
  642. {
  643.     struct WindowNode    *Node,
  644.                 *Next;
  645.  
  646.     ObtainSemaphore(&WindowSemaphore);
  647.  
  648.     AllSpritesOff = FALSE;
  649.  
  650.     KeyBlankCount = 0;
  651.  
  652.     Node = (struct WindowNode *)WindowList . lh_Head;
  653.  
  654.     while(Next = (struct WindowNode *)Node -> Node . mln_Succ)
  655.     {
  656.         if(Node -> Off)
  657.         {
  658.             if(Node -> Pointer)
  659.                 StackOldSetPointer(Node -> Window,Node -> Pointer,Node -> Height,Node -> Width,Node -> XOffset,Node -> YOffset);
  660.             else
  661.                 OldClearPointer(Node -> Window,IntuitionBase);
  662.  
  663.             Node -> Off = FALSE;
  664.         }
  665.  
  666.         Node = Next;
  667.     }
  668.  
  669.     ReleaseSemaphore(&WindowSemaphore);
  670. }
  671.  
  672.     /* NewClearPointer(register __a0 struct Window *Window):
  673.      *
  674.      *    Patch: resets the mouse pointer of a window
  675.      *    back to its default shape.
  676.      */
  677.  
  678. VOID __asm __saveds
  679. NewClearPointer(register __a0 struct Window *Window)
  680. {
  681.     if(KeyBlankStop)
  682.         OldClearPointer(Window,IntuitionBase);
  683.     else
  684.     {
  685.         struct WindowNode *Node;
  686.  
  687.         ObtainSemaphore(&WindowSemaphore);
  688.  
  689.         KeyBlankUseCnt++;
  690.  
  691.         if(Node = FindWindow(Window))
  692.         {
  693.             if(!AllSpritesOff)
  694.             {
  695.                 OldClearPointer(Window,IntuitionBase);
  696.  
  697.                 Node -> Off = FALSE;
  698.             }
  699.             else
  700.                 Node -> Off = TRUE;
  701.  
  702.             Node -> Pointer = NULL;
  703.         }
  704.         else
  705.             OldClearPointer(Window,IntuitionBase);
  706.  
  707.         KeyBlankUseCnt--;
  708.  
  709.         Signal(MouseBlankerTask,SIG_NOTICE);
  710.  
  711.         ReleaseSemaphore(&WindowSemaphore);
  712.     }
  713. }
  714.  
  715.     /* StackNewSetPointer():
  716.      *
  717.      *    Patch: attach a new mouse pointer sprite to a window.
  718.      */
  719.  
  720. VOID __stdargs __saveds
  721. StackNewSetPointer(struct Window *Window,UWORD *Pointer,WORD Height,WORD Width,WORD XOffset,WORD YOffset)
  722. {
  723.     if(KeyBlankStop)
  724.         StackOldSetPointer(Window,Pointer,Height,Width,XOffset,YOffset);
  725.     else
  726.     {
  727.         struct WindowNode *Node;
  728.  
  729.         ObtainSemaphore(&WindowSemaphore);
  730.  
  731.         KeyBlankUseCnt++;
  732.  
  733.         if(Node = FindWindow(Window))
  734.         {
  735.             if(!AllSpritesOff)
  736.             {
  737.                 StackOldSetPointer(Window,Pointer,Height,Width,XOffset,YOffset);
  738.  
  739.                 Node -> Off = FALSE;
  740.             }
  741.             else
  742.                 Node -> Off = TRUE;
  743.  
  744.             Node -> Pointer    = Pointer;
  745.             Node -> Height    = Height;
  746.             Node -> Width    = Width;
  747.             Node -> XOffset    = XOffset;
  748.             Node -> YOffset    = YOffset;
  749.         }
  750.         else
  751.             StackOldSetPointer(Window,Pointer,Height,Width,XOffset,YOffset);
  752.  
  753.         KeyBlankUseCnt--;
  754.  
  755.         Signal(MouseBlankerTask,SIG_NOTICE);
  756.  
  757.         ReleaseSemaphore(&WindowSemaphore);
  758.     }
  759. }
  760.  
  761.     /* NewOpenWindowTagList():
  762.      *
  763.      *    Patch: open a new window.
  764.      */
  765.  
  766. struct Window * __asm __saveds
  767. NewOpenWindowTagList(register __a0 struct NewWindow *NewWindow,register __a1 struct TagItem *TagList)
  768. {
  769.     struct NewWindow OtherWindow;
  770.  
  771.     if(NewWindow)
  772.     {
  773.         if((NewWindow -> Type & SCREENTYPE) == CUSTOMSCREEN && NewWindow -> Screen == BlankScreen)
  774.         {
  775.             CopyMem(NewWindow,&OtherWindow,sizeof(struct NewWindow));
  776.  
  777.             NewWindow = &OtherWindow;
  778.  
  779.             NewWindow -> Type        = (NewWindow -> Type & ~SCREENTYPE) | WBENCHSCREEN;
  780.             NewWindow -> Screen        = NULL;
  781.  
  782.             Signal(MouseBlankerTask,    SIG_ON);
  783.             Signal(BlankerControlTask,    SIG_BREAK);
  784.         }
  785.     }
  786.  
  787.     if(KeyBlankStop)
  788.         return(OldOpenWindowTagList(NewWindow,TagList,IntuitionBase));
  789.     else
  790.     {
  791.         struct Window    *Window;
  792.         ULONG         Signals;
  793.  
  794.         ObtainSemaphore(&WindowSemaphore);
  795.  
  796.         KeyBlankUseCnt++;
  797.  
  798.         if(Window = OldOpenWindowTagList(NewWindow,TagList,IntuitionBase))
  799.         {
  800.             NewNode(Window);
  801.  
  802.             Signals = SIG_NOTICE | SIG_ON;
  803.         }
  804.         else
  805.             Signals = SIG_NOTICE;
  806.  
  807.         KeyBlankUseCnt--;
  808.  
  809.         Signal(MouseBlankerTask,Signals);
  810.  
  811.         ReleaseSemaphore(&WindowSemaphore);
  812.  
  813.         return(Window);
  814.     }
  815. }
  816.  
  817.     /* NewOpenWindow():
  818.      *
  819.      *    Patch: open a new window.
  820.      */
  821.  
  822. struct Window * __asm __saveds
  823. NewOpenWindow(register __a0 struct NewWindow *NewWindow)
  824. {
  825.     struct NewWindow OtherWindow;
  826.  
  827.     if(NewWindow)
  828.     {
  829.         if((NewWindow -> Type & SCREENTYPE) == CUSTOMSCREEN && NewWindow -> Screen == BlankScreen)
  830.         {
  831.             CopyMem(NewWindow,&OtherWindow,sizeof(struct NewWindow));
  832.  
  833.             NewWindow = &OtherWindow;
  834.  
  835.             NewWindow -> Type        = (NewWindow -> Type & ~SCREENTYPE) | WBENCHSCREEN;
  836.             NewWindow -> Screen        = NULL;
  837.  
  838.             Signal(MouseBlankerTask,    SIG_ON);
  839.             Signal(BlankerControlTask,    SIG_BREAK);
  840.         }
  841.     }
  842.  
  843.     if(KeyBlankStop)
  844.         return(OldOpenWindow(NewWindow,IntuitionBase));
  845.     else
  846.     {
  847.         struct Window    *Window;
  848.         ULONG         Signals;
  849.  
  850.         ObtainSemaphore(&WindowSemaphore);
  851.  
  852.         KeyBlankUseCnt++;
  853.  
  854.         if(Window = OldOpenWindow(NewWindow,IntuitionBase))
  855.         {
  856.             NewNode(Window);
  857.  
  858.             Signals = SIG_NOTICE | SIG_ON;
  859.         }
  860.         else
  861.             Signals = SIG_NOTICE;
  862.  
  863.         KeyBlankUseCnt--;
  864.  
  865.         Signal(MouseBlankerTask,Signals);
  866.  
  867.         ReleaseSemaphore(&WindowSemaphore);
  868.  
  869.         return(Window);
  870.     }
  871. }
  872.  
  873.     /* NewCloseWindow():
  874.      *
  875.      *    Patch: close a window.
  876.      */
  877.  
  878. VOID __asm __saveds
  879. NewCloseWindow(register __a0 struct Window *Window)
  880. {
  881.     struct WindowNode *Node;
  882.  
  883.     ObtainSemaphore(&WindowSemaphore);
  884.  
  885.     KeyBlankUseCnt++;
  886.  
  887.     if(Node = FindWindow(Window))
  888.     {
  889.         Remove((struct Node *)Node);
  890.  
  891.         FreeVec(Node);
  892.     }
  893.  
  894.     OldCloseWindow(Window,IntuitionBase);
  895.  
  896.     KeyBlankUseCnt--;
  897.  
  898.     Signal(MouseBlankerTask,SIG_NOTICE);
  899.  
  900.     ReleaseSemaphore(&WindowSemaphore);
  901. }
  902.  
  903.     /* BlankerControl():
  904.      *
  905.      *    The screen blanker control task.
  906.      */
  907.  
  908. VOID __saveds
  909. BlankerControl()
  910. {
  911.     ULONG SignalSet;
  912.  
  913.     Forbid();
  914.  
  915.     FOREVER
  916.     {
  917.         SignalSet = Wait(SIG_BREAK | SIG_START | SIG_CHANGE | SIG_REFRESH);
  918.  
  919.             /* Remove both the screen and the blanker task? */
  920.  
  921.         if(SignalSet & SIG_BREAK)
  922.         {
  923.             if(BlankScreen)
  924.                 ScreenToBack(BlankScreen);
  925.  
  926.                 /* Remove the blanker task. */
  927.  
  928.             if(BlankTask)
  929.             {
  930.                 struct Task *Task = BlankTask;
  931.  
  932.                     /* Remember the old address and clear it. */
  933.  
  934.                 BlankTask = NULL;
  935.  
  936.                     /* Make sure that the break signal is
  937.                      * not set when we are waiting for a
  938.                      * handshake.
  939.                      */
  940.  
  941.                 SetSignal(0,SIG_BREAK);
  942.  
  943.                     /* Tell the blanker task to shut down. */
  944.  
  945.                 Signal(Task,SIG_BREAK);
  946.  
  947.                     /* Move the blanker task priority up. */
  948.  
  949.                 SetTaskPri(Task,80);
  950.  
  951.                     /* Wait for handshake signal... */
  952.  
  953.                 Wait(SIG_BREAK);
  954.             }
  955.  
  956.                 /* Close the blanker screen. */
  957.  
  958.             if(BlankScreen)
  959.             {
  960.                 struct Screen *Screen = BlankScreen;
  961.  
  962.                 BlankScreen = NULL;
  963.  
  964. #ifdef USE_COP_LIST
  965.                 FreeVPortCopLists(&Screen -> ViewPort);
  966.  
  967.                 RethinkDisplay();
  968. #endif    /* USE_COP_LIST */
  969.                 CloseScreen(Screen);
  970.             }
  971.  
  972.             continue;
  973.         }
  974.  
  975.             /* Start the screen blanker? */
  976.  
  977.         if(SignalSet & SIG_START)
  978.         {
  979.             if(!BlankScreen)
  980.             {
  981.                 struct Screen    *Screen,
  982.                         *FirstScreen;
  983.                 ULONG         DisplayID,
  984.                          Mode,
  985.                          IntuiLock;
  986.  
  987.                     /* Gain access to IntuitionBase. */
  988.  
  989.                 IntuiLock = LockIBase(NULL);
  990.  
  991.                     /* Determine the first screen. */
  992.  
  993.                 FirstScreen = IntuitionBase -> FirstScreen;
  994.  
  995.                     /* Inquire the display mode the first
  996.                      * screen is in.
  997.                      */
  998.  
  999.                 DisplayID = GetVPModeID(&FirstScreen -> ViewPort);
  1000.  
  1001.                     /* Surrender the lock. */
  1002.  
  1003.                 UnlockIBase(IntuiLock);
  1004.  
  1005.                     /* Set the approriate display mode. */
  1006.  
  1007.                 if(ColourMode == COLOUR_MONO)
  1008.                     Mode = HIRESLACE_KEY;
  1009.                 else
  1010.                     Mode = EXTRAHALFBRITELACE_KEY;
  1011.  
  1012.                     /* This feature has been added for users
  1013.                      * of old Multiscan monitors which take
  1014.                      * ages to synchronize with different
  1015.                      * display modes. The programm will try
  1016.                      * to open the blanker screen in the same
  1017.                      * display mode as the first screen is in.
  1018.                      * Note that this trick will fail to work
  1019.                      * in ECS screen modes (productivity,
  1020.                      * superhires, etc.).
  1021.                      */
  1022.  
  1023.                 switch(DisplayID & MONITOR_ID_MASK)
  1024.                 {
  1025.                     case NTSC_MONITOR_ID:    Mode |= NTSC_MONITOR_ID;
  1026.                                 break;
  1027.  
  1028.                     case PAL_MONITOR_ID:    Mode |= PAL_MONITOR_ID;
  1029.                                 break;
  1030.  
  1031.                     default:        Mode |= DEFAULT_MONITOR_ID;
  1032.                                 break;
  1033.                 }
  1034.  
  1035.                 if(Screen = OpenScreenTags(NULL,
  1036.                     SA_Behind,    TRUE,
  1037.                     SA_Quiet,    TRUE,
  1038.                     SA_DisplayID,    Mode,
  1039.                     SA_Overscan,    OSCAN_MAX,
  1040.                     SA_Depth,    ColourMode == COLOUR_MONO ? 1 : 6,
  1041.                 TAG_DONE))
  1042.                 {
  1043. #ifdef USE_COP_LIST
  1044.                     struct UCopList    *UserCopperList;
  1045.  
  1046.                         /* I had a lot of problems trying to shut down
  1047.                          * the sprite display hardware completely.
  1048.                          * The mouse pointer would pop up again after
  1049.                          * a certain time interval, no matter what I
  1050.                          * did.
  1051.                          *
  1052.                          * Now, Amy, you had your chance, hadn't you?
  1053.                          *
  1054.                          * This is the big one: a user copper list will
  1055.                          * shut down the sprite hardware. Full stop.
  1056.                          */
  1057.  
  1058.                     if(UserCopperList = (struct UCopList *)AllocMem(sizeof(struct UCopList),MEMF_PUBLIC|MEMF_CLEAR))
  1059.                     {
  1060.                             /* Set up for 3 instructions. */
  1061.  
  1062.                         if(UCopperListInit(UserCopperList,3))
  1063.                         {
  1064.                                 /* Wait for first line. */
  1065.  
  1066.                             CWAIT(UserCopperList,0,0);
  1067.  
  1068.                                 /* Disable sprite DMA. */
  1069.  
  1070.                             CMOVE(UserCopperList,custom . dmacon,BITCLR|DMAF_SPRITE);
  1071.  
  1072.                                 /* Terminate copper instruction list. */
  1073.  
  1074.                             CEND(UserCopperList);
  1075.  
  1076.                                 /* Install the copper list. */
  1077.  
  1078.                             Screen -> ViewPort . UCopIns = UserCopperList;
  1079.  
  1080.                                 /* Link it into the screen copper list. */
  1081.  
  1082.                             RethinkDisplay();
  1083.  
  1084.                                 /* Set the colours to black. */
  1085. #endif    /* USE_COP_LIST */
  1086.                             LoadRGB4(&Screen -> ViewPort,Black,32);
  1087.  
  1088.                                 /* Display the screen. */
  1089.  
  1090.                             ScreenToFront(Screen);
  1091.  
  1092.                             BlankScreen = Screen;
  1093. #ifdef USE_COP_LIST
  1094.                         }
  1095.                         else
  1096.                         {
  1097.                             CloseScreen(Screen);
  1098.  
  1099.                             FreeMem(UserCopperList,sizeof(struct UCopList));
  1100.                         }
  1101.                     }
  1102.                     else
  1103.                         CloseScreen(Screen);
  1104. #endif    /* USE_COP_LIST */
  1105.                 }
  1106.             }
  1107.  
  1108.             if(BlankScreen)
  1109.             {
  1110.                 PatternCount = 0;
  1111.  
  1112.                 if(!BlankTask)
  1113.                     BlankTask = (struct Task *)CreateTask("FracBlank Blanker Task",-20,Blanker,1024 * MAXFLAMELEVEL);
  1114.             }
  1115.  
  1116.             continue;
  1117.         }
  1118.  
  1119.             /* Bring the screen to the front? */
  1120.  
  1121.         if(SignalSet & SIG_REFRESH)
  1122.         {
  1123.             if(BlankScreen)
  1124.             {
  1125.                     /* Push the blanker screen to the front if necessary. */
  1126.  
  1127.                 if(BlankScreen -> TopEdge > 0)
  1128.                     MoveScreen(BlankScreen,0,-BlankScreen -> TopEdge);
  1129.  
  1130.                 if(IntuitionBase -> FirstScreen != BlankScreen)
  1131.                     ScreenToFront(BlankScreen);
  1132.             }
  1133.         }
  1134.  
  1135.             /* Change the patterns? */
  1136.  
  1137.         if(SignalSet & SIG_CHANGE)
  1138.         {
  1139.                 /* Stop drawing patterns. */
  1140.  
  1141.             StopDrawing = TRUE;
  1142.  
  1143.             if(BlankScreen && BlankTask)
  1144.             {
  1145.                     /* Clear the screen. */
  1146.  
  1147.                 LoadRGB4(&BlankScreen -> ViewPort,Black,32);
  1148.  
  1149.                     /* Then tell the blanker to restart. */
  1150.  
  1151.                 Signal(BlankTask,SIG_CHANGE);
  1152.             }
  1153.         }
  1154.     }
  1155. }
  1156.  
  1157.     /* Random(ULONG MaxValue):
  1158.      *
  1159.      *    Simple random number generation routine.
  1160.      */
  1161.  
  1162. ULONG __regargs
  1163. Random(ULONG MaxValue)
  1164. {
  1165.     STATIC ULONG RandomSeed = 0xDEAD0123;
  1166.  
  1167.     RandomSeed = RandomSeed * custom . vhposr + 0xE153766F;
  1168.  
  1169.     return(RandomSeed % MaxValue);
  1170. }
  1171.  
  1172.     /* RealPlane():
  1173.      *
  1174.      *    Draw real plane fractals.
  1175.      */
  1176.  
  1177. VOID
  1178. RealPlane()
  1179. {
  1180.     STATIC BYTE Wheel = 0;
  1181.  
  1182.     UWORD    Colours[32],OffsetX = BlankScreen -> Width >> 1,OffsetY = BlankScreen -> Height >> 1;
  1183.     float    x = 0,y = 0,yy,a,b,c,sx,sy,mag;
  1184.  
  1185.         /* Are we running in monochrome mode? */
  1186.  
  1187.     if(ColourMode == COLOUR_MONO)
  1188.     {
  1189.         UWORD        Modulo    = BlankScreen -> RastPort . BitMap -> BytesPerRow;
  1190.         PLANEPTR    Plane    = BlankScreen -> RastPort . BitMap -> Planes[0];
  1191.  
  1192.             /* Provide starting numbers for the fractal
  1193.              * parameters.
  1194.              */
  1195.  
  1196.         a = (float)(Random(700) + 5) / 100;
  1197.         b = (float)(Random(190) + 5) / 100;
  1198.         c = (float)(Random( 90) + 5) / 100;
  1199.  
  1200.         mag = (float)(1 << (Random(6) + 2)) * deg45;
  1201.  
  1202.             /* Set up the screen colour table. */
  1203.  
  1204.         Colours[0] = 0;
  1205.         Colours[1] = Table[Wheel];
  1206.  
  1207.         LoadRGB4(&BlankScreen -> ViewPort,Colours,2);
  1208.  
  1209.             /* Go into fractal generation loop. */
  1210.  
  1211.         FOREVER
  1212.         {
  1213.                 /* Are we to shut down? */
  1214.  
  1215.             if(SetSignal(0,0) & SIG_BREAK)
  1216.             {
  1217.                 Forbid();
  1218.  
  1219.                 Signal(BlankerControlTask,SIG_BREAK);
  1220.  
  1221.                 RemTask(SysBase -> ThisTask);
  1222.             }
  1223.  
  1224.                 /* The original formula looks like
  1225.                  * this:
  1226.                  *                                    ½
  1227.                  *    x = y - SIGN(x) × ABS(b × x - c)
  1228.                  *    y = a - x
  1229.                  *
  1230.                  * I have split the calculation into
  1231.                  * several steps to save time and
  1232.                  * variables.
  1233.                  */
  1234.  
  1235.             yy = a - x;
  1236.  
  1237.             if(x < 0)
  1238.                 x = y + sqrt(fabs(b * x - c));
  1239.             else
  1240.                 x = y - sqrt(fabs(b * x - c));
  1241.  
  1242.             y = yy;
  1243.  
  1244.                 /* The resulting image appears to have
  1245.                  * been rotated by 45°, so we'll
  1246.                  * rotate the pixel coordinates by -45°
  1247.                  *
  1248.                  *    x =  x × cos(alpha) + y × sin(alpha)
  1249.                  *    y = -x × sin(alpha) + y × cos(alpha)
  1250.                  *
  1251.                  * We also magnify the image (i.e. the
  1252.                  * distribution of pixels) in the following
  1253.                  * lines.
  1254.                  */
  1255.  
  1256.             sx = mag * ( x + y);
  1257.             sy = mag * (-x + y);
  1258.  
  1259.                 /* If the pixel happens to reside within
  1260.                  * the boundaries of the screen, draw it.
  1261.                  */
  1262.  
  1263.             MonoPlot(Plane,(WORD)(sx) + OffsetX,(WORD)(sy) + OffsetY,Modulo,BlankScreen -> Width,BlankScreen -> Height);
  1264.  
  1265.                 /* ^E tells the blanker to rotate the
  1266.                  * colours.
  1267.                  */
  1268.  
  1269.             if(SetSignal(0,0) & SIG_CYCLE)
  1270.             {
  1271.                 SetSignal(0,SIG_CYCLE);
  1272.  
  1273.                 Colours[1] = Table[Wheel];
  1274.  
  1275.                 LoadRGB4(&BlankScreen -> ViewPort,Colours,2);
  1276.  
  1277.                 Wheel = (Wheel + 1) % 75;
  1278.             }
  1279.  
  1280.                 /* Change the pattern? */
  1281.  
  1282.             if(SetSignal(0,0) & SIG_CHANGE)
  1283.             {
  1284.                 SetSignal(0,SIG_CHANGE);
  1285.  
  1286.                 SetRast(&BlankScreen -> RastPort,0);
  1287.  
  1288.                 LoadRGB4(&BlankScreen -> ViewPort,Colours,2);
  1289.  
  1290.                 StopDrawing = FALSE;
  1291.  
  1292.                 x = y = 0;
  1293.  
  1294.                 a = (float)(Random(700) + 5) / 100;
  1295.                 b = (float)(Random(190) + 5) / 100;
  1296.                 c = (float)(Random( 90) + 5) / 100;
  1297.  
  1298.                 mag = (float)(1 << (Random(6) + 2)) * deg45;
  1299.             }
  1300.         }
  1301.     }
  1302.     else
  1303.     {
  1304.         struct RastPort    *RPort;
  1305.         UWORD         Count = 0;
  1306.         WORD         i,NewBit = 0;
  1307.         BYTE         Colour = 1,Plus = 1;
  1308.  
  1309.         a = (float)(Random(700) + 5) / 100;
  1310.         b = (float)(Random(190) + 5) / 100;
  1311.         c = (float)(Random( 90) + 5) / 100;
  1312.  
  1313.         mag = (float)(1 << (Random(6) + 2)) * deg45;
  1314.  
  1315.         Colours[0] = 0x000;
  1316.  
  1317.         for(i = 1 ; i < 32 ; i++)
  1318.             Colours[i] = Table[(Wheel + i) % 75];
  1319.  
  1320.         if(ColourMode == COLOUR_CYCLE)
  1321.             LoadRGB4(&BlankScreen -> ViewPort,Colours,32);
  1322.         else
  1323.             LoadRGB4(&BlankScreen -> ViewPort,Rainbow,32);
  1324.  
  1325.         Wheel = (Wheel + 1) % 75;
  1326.  
  1327.         RPort = &BlankScreen -> RastPort;
  1328.  
  1329.         FOREVER
  1330.         {
  1331.                 /* Are we to shut down? */
  1332.  
  1333.             if(SetSignal(0,0) & SIG_BREAK)
  1334.             {
  1335.                 Forbid();
  1336.  
  1337.                 Signal(BlankerControlTask,SIG_BREAK);
  1338.  
  1339.                 RemTask(SysBase -> ThisTask);
  1340.             }
  1341.  
  1342.             yy = a - x;
  1343.  
  1344.             if(x < 0)
  1345.                 x = y + sqrt(fabs(b * x - c));
  1346.             else
  1347.                 x = y - sqrt(fabs(b * x - c));
  1348.  
  1349.             y = yy;
  1350.  
  1351.             sx = mag *       ( x + y);
  1352.             sy = mag * 2.0 * (-x + y);
  1353.  
  1354.             MultiPlot(BlankScreen,(WORD)(sx) + OffsetX,(WORD)(sy) + OffsetY,Colour | NewBit);
  1355.  
  1356.                 /* Oh well, it's not that easy to
  1357.                  * produce decent colour values for
  1358.                  * the pixels to be rendered.
  1359.                  *
  1360.                  * The following statement will change
  1361.                  * the current drawing pen after exactly
  1362.                  * 1200 pixels have been rendered and will
  1363.                  * pick a new colour between 1 and 31.
  1364.                  */
  1365.  
  1366.             if(Count++ >= 1200)
  1367.             {
  1368.                 Count = 0;
  1369.  
  1370.                 if(NewBit)
  1371.                 {
  1372.                     NewBit = 0;
  1373.  
  1374.                     Colour += Plus;
  1375.  
  1376.                     if(!Colour)
  1377.                     {
  1378.                         Plus    = 1;
  1379.                         Colour    = 2;
  1380.                     }
  1381.                     else
  1382.                     {
  1383.                         if(Colour == 32)
  1384.                         {
  1385.                             Plus    = -1;
  1386.                             Colour    = 30;
  1387.                         }
  1388.                     }
  1389.                 }
  1390.                 else
  1391.                     NewBit = 0x20;
  1392.             }
  1393.  
  1394.             if(SetSignal(0,0) & SIG_CYCLE)
  1395.             {
  1396.                 SetSignal(0,SIG_CYCLE);
  1397.  
  1398.                 for(i = 1 ; i < 32 ; i++)
  1399.                     Colours[i] = Table[(Wheel + i) % 75];
  1400.  
  1401.                 if(ColourMode == COLOUR_CYCLE)
  1402.                     LoadRGB4(&BlankScreen -> ViewPort,Colours,32);
  1403.  
  1404.                 Wheel = (Wheel + 1) % 75;
  1405.             }
  1406.  
  1407.             if(SetSignal(0,0) & SIG_CHANGE)
  1408.             {
  1409.                 SetSignal(0,SIG_CHANGE);
  1410.  
  1411.                 SetRast(RPort,0);
  1412.  
  1413.                 StopDrawing = FALSE;
  1414.  
  1415.                 if(ColourMode == COLOUR_CYCLE)
  1416.                     LoadRGB4(&BlankScreen -> ViewPort,Colours,32);
  1417.                 else
  1418.                     LoadRGB4(&BlankScreen -> ViewPort,Rainbow,32);
  1419.  
  1420.                 x = y = 0;
  1421.  
  1422.                 a = (float)(Random(700) + 5) / 100;
  1423.                 b = (float)(Random(190) + 5) / 100;
  1424.                 c = (float)(Random( 90) + 5) / 100;
  1425.  
  1426.                 mag = (float)(1 << (Random(6) + 2)) * deg45;
  1427.             }
  1428.         }
  1429.     }
  1430. }
  1431.  
  1432.     /* RecurseMono(float x,float y,WORD Level):
  1433.      *
  1434.      *    Cosmic flame calculation routine (monochrome).
  1435.      */
  1436.  
  1437. BYTE
  1438. RecurseMono(float x,float y,WORD Level)
  1439. {
  1440.         /* Are we to shut down? */
  1441.  
  1442.     if(SetSignal(0,0) & SIG_BREAK)
  1443.     {
  1444.         Forbid();
  1445.  
  1446.         Signal(BlankerControlTask,SIG_BREAK);
  1447.  
  1448.         RemTask(SysBase -> ThisTask);
  1449.     }
  1450.  
  1451.     if(StopDrawing)
  1452.     {
  1453.         FlameLevel    = 0;
  1454.         StopDrawing    = FALSE;
  1455.  
  1456.         return(FALSE);
  1457.     }
  1458.  
  1459.         /* Change the pattern? */
  1460.  
  1461.     if(SetSignal(0,0) & SIG_CHANGE)
  1462.     {
  1463.         SetSignal(0,SIG_CHANGE);
  1464.  
  1465.         FlameLevel    = 0;
  1466.         StopDrawing    = FALSE;
  1467.  
  1468.         return(FALSE);
  1469.     }
  1470.  
  1471.         /* ^E tells the blanker to rotate the
  1472.          * colours.
  1473.          */
  1474.  
  1475.     if(SetSignal(0,0) & SIG_CYCLE)
  1476.     {
  1477.         SetSignal(0,SIG_CYCLE);
  1478.  
  1479.         FlameColourTable[1] = Table[FlameWheel];
  1480.  
  1481.         LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,2);
  1482.  
  1483.         FlameWheel = (FlameWheel + 1) % 75;
  1484.     }
  1485.  
  1486.     if(Level >= MAXFLAMELEVEL)
  1487.     {
  1488.         if((FlamePoints++) > MAXTOTALPOINTS)
  1489.             return(FALSE);
  1490.         else
  1491.             MonoPlot(FlamePlane,(WORD)((BlankScreen -> Width >> 1) * (x + 1.0)),(WORD)((BlankScreen -> Height >> 1) * (y + 1.0)),FlameModulo,BlankScreen -> Width,BlankScreen -> Height);
  1492.     }
  1493.     else
  1494.     {
  1495.         float    nx,ny;
  1496.         WORD    i;
  1497.  
  1498.         for(i = 0 ; i < 2 ; i++)
  1499.         {
  1500.             nx = Flame[0][0][i] * x + Flame[0][1][i] * y + Flame[0][2][i];
  1501.             ny = Flame[1][0][i] * x + Flame[1][1][i] * y + Flame[1][2][i];
  1502.  
  1503.             if(i < FlameAlternateForm)
  1504.             {
  1505.                 nx = sin(nx);
  1506.                 ny = sin(ny);
  1507.             }
  1508.  
  1509.             if(!StopDrawing)
  1510.             {
  1511.                 if(!RecurseMono(nx,ny,Level + 1))
  1512.                     return(FALSE);
  1513.             }
  1514.             else
  1515.                 return(FALSE);
  1516.         }
  1517.     }
  1518.  
  1519.     return(TRUE);
  1520. }
  1521.  
  1522.     /* RecurseColour(float x,float y,WORD Level):
  1523.      *
  1524.      *    Cosmic flame calculation routine (colour).
  1525.      */
  1526.  
  1527. BYTE
  1528. RecurseColour(float x,float y,WORD Level)
  1529. {
  1530.         /* Are we to shut down? */
  1531.  
  1532.     if(SetSignal(0,0) & SIG_BREAK)
  1533.     {
  1534.         Forbid();
  1535.  
  1536.         Signal(BlankerControlTask,SIG_BREAK);
  1537.  
  1538.         RemTask(SysBase -> ThisTask);
  1539.     }
  1540.  
  1541.     if(StopDrawing)
  1542.     {
  1543.         FlameLevel    = 0;
  1544.         StopDrawing    = FALSE;
  1545.  
  1546.         return(FALSE);
  1547.     }
  1548.  
  1549.         /* Change the pattern? */
  1550.  
  1551.     if(SetSignal(0,0) & SIG_CHANGE)
  1552.     {
  1553.         SetSignal(0,SIG_CHANGE);
  1554.  
  1555.         FlameLevel    = 0;
  1556.         StopDrawing    = FALSE;
  1557.  
  1558.         return(FALSE);
  1559.     }
  1560.  
  1561.         /* ^E tells the blanker to rotate the
  1562.          * colours.
  1563.          */
  1564.  
  1565.     if(SetSignal(0,0) & SIG_CYCLE)
  1566.     {
  1567.         SetSignal(0,SIG_CYCLE);
  1568.  
  1569.         if(ColourMode == COLOUR_CYCLE)
  1570.         {
  1571.             WORD i;
  1572.  
  1573.             for(i = 1 ; i < 32 ; i++)
  1574.                 FlameColourTable[i] = Table[(FlameWheel + i) % 75];
  1575.  
  1576.             LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,32);
  1577.  
  1578.             FlameWheel = (FlameWheel + 1) % 75;
  1579.         }
  1580.     }
  1581.  
  1582.     if(Level >= MAXFLAMELEVEL)
  1583.     {
  1584.         if((FlamePoints++) > MAXTOTALPOINTS)
  1585.             return(FALSE);
  1586.         else
  1587.             MultiPlot(BlankScreen,(WORD)((BlankScreen -> Width >> 1) * (x + 1.0)),(WORD)((BlankScreen -> Height >> 1) * (y + 1.0)),FlameColour + 1);
  1588.     }
  1589.     else
  1590.     {
  1591.         float    nx,ny;
  1592.         WORD    i;
  1593.  
  1594.         for(i = 0 ; i < 2 ; i++)
  1595.         {
  1596.             nx = Flame[0][0][i] * x + Flame[0][1][i] * y + Flame[0][2][i];
  1597.             ny = Flame[1][0][i] * x + Flame[1][1][i] * y + Flame[1][2][i];
  1598.  
  1599.             if(i < FlameAlternateForm)
  1600.             {
  1601.                 nx = sin(nx);
  1602.                 ny = sin(ny);
  1603.             }
  1604.  
  1605.             if(!StopDrawing)
  1606.             {
  1607.                 if(!RecurseColour(nx,ny,Level + 1))
  1608.                     return(FALSE);
  1609.             }
  1610.             else
  1611.                 return(FALSE);
  1612.         }
  1613.     }
  1614.  
  1615.     return(TRUE);
  1616. }
  1617.  
  1618.     /* CosmicFlame():
  1619.      *
  1620.      *    The cosmic flame screen blanker.
  1621.      *
  1622.      *    xlock.c - X11 client to lock a display and show a screen saver.
  1623.      *
  1624.      *    Copyright (c) 1988-91 by Patrick J. Naughton.
  1625.      *
  1626.      *    Permission to use, copy, modify, and distribute this software and its
  1627.      *    documentation for any purpose and without fee is hereby granted,
  1628.      *    provided that the above copyright notice appear in all copies and that
  1629.      *    both that copyright notice and this permission notice appear in
  1630.      *    supporting documentation.
  1631.      */
  1632.  
  1633. VOID
  1634. CosmicFlame()
  1635. {
  1636.     WORD i,j,k;
  1637.  
  1638.         /* Monochrome mode? */
  1639.  
  1640.     if(ColourMode == COLOUR_MONO)
  1641.     {
  1642.         BYTE Alternate = FALSE;
  1643.  
  1644.             /* Initialize defaults. */
  1645.  
  1646.         FlameModulo    = BlankScreen -> RastPort . BitMap -> BytesPerRow;
  1647.         FlamePlane    = BlankScreen -> RastPort . BitMap -> Planes[0];
  1648.  
  1649.         FlameWheel    = 0;
  1650.  
  1651.             /* Set up the screen colour table. */
  1652.  
  1653.         FlameColourTable[0] = 0;
  1654.         FlameColourTable[1] = Table[FlameWheel];
  1655.  
  1656.         LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,2);
  1657.  
  1658.         FlameLevel    = 0;
  1659.  
  1660.             /* Go into fractal generation loop. */
  1661.  
  1662.         FOREVER
  1663.         {
  1664.             if(!((FlameLevel++) % 20))
  1665.             {
  1666.                 LoadRGB4(&BlankScreen -> ViewPort,Black,2);
  1667.  
  1668.                 SetRast(&BlankScreen -> RastPort,0);
  1669.  
  1670.                 LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,2);
  1671.  
  1672.                 Alternate = !Alternate;
  1673.             }
  1674.  
  1675.             if(Alternate)
  1676.                 FlameAlternateForm = 0;
  1677.             else
  1678.                 FlameAlternateForm = Random(2) + 2;
  1679.  
  1680.             for(k = 0 ; k < 2 ; k++)
  1681.             {
  1682.                 for(i = 0 ; i < 2 ; i++)
  1683.                 {
  1684.                     for(j = 0; j < 3; j++)
  1685.                         Flame[i][j][k] = ((float)Random(1024)) / 512.0 - 1.0;
  1686.                 }
  1687.             }
  1688.  
  1689.             FlamePoints = 0;
  1690.  
  1691.             RecurseMono(0.0,0.0,0);
  1692.         }
  1693.     }
  1694.     else
  1695.     {
  1696.         BYTE Alternate = FALSE,Plus;
  1697.  
  1698.         FlameWheel = Random(75);
  1699.  
  1700.         FlameColourTable[0] = 0x000;
  1701.  
  1702.         for(i = 1 ; i < 32 ; i++)
  1703.             FlameColourTable[i] = Table[(FlameWheel + i) % 75];
  1704.  
  1705.         if(ColourMode == COLOUR_CYCLE)
  1706.             LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,32);
  1707.         else
  1708.             LoadRGB4(&BlankScreen -> ViewPort,Rainbow,32);
  1709.  
  1710.         FlameWheel    = (FlameWheel + 1) % 75;
  1711.  
  1712.         FlameColour    = Random(63);
  1713.         Plus        = 1;
  1714.  
  1715.         FlameLevel    = 0;
  1716.  
  1717.             /* Go into fractal generation loop. */
  1718.  
  1719.         FOREVER
  1720.         {
  1721.             if(!((FlameLevel++) % 20))
  1722.             {
  1723.                 LoadRGB4(&BlankScreen -> ViewPort,Black,32);
  1724.  
  1725.                 SetRast(&BlankScreen -> RastPort,0);
  1726.  
  1727.                 if(ColourMode == COLOUR_CYCLE)
  1728.                     LoadRGB4(&BlankScreen -> ViewPort,FlameColourTable,32);
  1729.                 else
  1730.                     LoadRGB4(&BlankScreen -> ViewPort,Rainbow,32);
  1731.  
  1732.                 Alternate = !Alternate;
  1733.             }
  1734.             else
  1735.             {
  1736.                 if(FlameColour == 62)
  1737.                     Plus = -1;
  1738.  
  1739.                 if(FlameColour == 0)
  1740.                     Plus = 1;
  1741.  
  1742.                 FlameColour += Plus;
  1743.             }
  1744.  
  1745.             if(Alternate)
  1746.                 FlameAlternateForm = 0;
  1747.             else
  1748.                 FlameAlternateForm = Random(2) + 2;
  1749.  
  1750.             for(k = 0 ; k < 2 ; k++)
  1751.             {
  1752.                 for(i = 0 ; i < 2 ; i++)
  1753.                 {
  1754.                     for(j = 0; j < 3; j++)
  1755.                         Flame[i][j][k] = ((float)Random(1024)) / 512.0 - 1.0;
  1756.                 }
  1757.             }
  1758.  
  1759.             FlamePoints = 0;
  1760.  
  1761.             RecurseColour(0.0,0.0,0);
  1762.         }
  1763.     }
  1764. }
  1765.  
  1766.     /* Blanker():
  1767.      *
  1768.      *    The screen blanker itself.
  1769.      */
  1770.  
  1771. VOID __saveds
  1772. Blanker()
  1773. {
  1774.         /* Determine fractal type. */
  1775.  
  1776.     if(FractalType == FRACTAL_COSMIC_FLAME)
  1777.         CosmicFlame();
  1778.     else
  1779.     {
  1780.         if(FractalType == FRACTAL_REAL_PLANE)
  1781.             RealPlane();
  1782.         else
  1783.         {
  1784.             if(Random(42) >= 21)
  1785.                 CosmicFlame();
  1786.             else
  1787.                 RealPlane();
  1788.         }
  1789.     }
  1790.  
  1791.         /* Quietly remove ourselves. */
  1792.  
  1793.     Forbid();
  1794.  
  1795.     BlankTask = NULL;
  1796. }
  1797.  
  1798.     /* BlankerAction(CxMsg *CxMessage,CxObj *CxObject):
  1799.      *
  1800.      *    Commodities support routine, handles the Commodities
  1801.      *    custom actions (in this case: filter the InputEvents
  1802.      *    coming in and enable/disable the screen blanker).
  1803.      */
  1804.  
  1805. VOID __saveds __stdargs
  1806. BlankerAction(CxMsg *CxMessage,CxObj *CxObject)
  1807. {
  1808.     STATIC BYTE Count = 0;
  1809.  
  1810.     struct InputEvent *Event = (struct InputEvent *)CxMsgData(CxMessage);
  1811.  
  1812.         /* Push the blanker screen to the front if necessary. */
  1813.  
  1814.     if(BlankScreen)
  1815.         Signal(BlankerControlTask,SIG_REFRESH);
  1816.  
  1817.         /* This looks like a timer event. */
  1818.  
  1819.     if(Event -> ie_Class == IECLASS_TIMER)
  1820.     {
  1821.         if(KeyBlankCount++ >= MouseTimeout * 10)
  1822.         {
  1823.             KeyBlankCount = 0;
  1824.  
  1825.             if(MouseTimeout)
  1826.                 Signal(MouseBlankerTask,SIG_OFF);
  1827.         }
  1828.  
  1829.         if(!Window)
  1830.         {
  1831.                 /* Screen blanker still inactive? */
  1832.  
  1833.             if(!BlankTask)
  1834.             {
  1835.                     /* Is there a timeout to take care of? */
  1836.  
  1837.                 if(ScreenTimeout)
  1838.                 {
  1839.                         /* Are we ready to create the
  1840.                          * screenblanker?
  1841.                          */
  1842.  
  1843.                     if(ScreenCount++ >= ScreenTimeout * 10)
  1844.                         Signal(BlankerControlTask,SIG_START);
  1845.                 }
  1846.             }
  1847.             else
  1848.             {
  1849.                     /* Every 5/60 second we signal the blanker
  1850.                      * task to rotate the palette.
  1851.                      */
  1852.  
  1853.                 if(Count++ >= 2)
  1854.                 {
  1855.                     Signal(BlankTask,SIG_CYCLE);
  1856.  
  1857.                     Count = 0;
  1858.                 }
  1859.  
  1860.                     /* Is it time to change the pattern? */
  1861.  
  1862.                 if(PatternTimeout)
  1863.                 {
  1864.                     if(PatternCount++ >= PatternTimeout * 10)
  1865.                     {
  1866.                         Signal(BlankerControlTask,SIG_CHANGE);
  1867.  
  1868.                         PatternCount = 0;
  1869.                     }
  1870.                 }
  1871.             }
  1872.         }
  1873.     }
  1874.     else
  1875.     {
  1876.             /* The following lines determine whether
  1877.              * the blanker is to be removed or to
  1878.              * be left running.
  1879.              */
  1880.  
  1881.         switch(Event -> ie_Class)
  1882.         {
  1883.             case IECLASS_RAWKEY:    if(!(Event -> ie_Code & IECODE_UP_PREFIX) && !(Event -> ie_Qualifier & IEQUALIFIER_REPEAT))
  1884.                         {
  1885.                             if(KeyBlank)
  1886.                                 Signal(MouseBlankerTask,SIG_OFF);
  1887.  
  1888.                             Signal(BlankerControlTask,SIG_BREAK);
  1889.                         }
  1890.  
  1891.                         break;
  1892.  
  1893.             case IECLASS_NEWPOINTERPOS:
  1894.             case IECLASS_POINTERPOS:
  1895.             case IECLASS_RAWMOUSE:    Signal(MouseBlankerTask,SIG_ON);
  1896.  
  1897.                         Signal(BlankerControlTask,SIG_BREAK);
  1898.  
  1899.                         break;
  1900.  
  1901.             default:        break;
  1902.         }
  1903.  
  1904.         ScreenCount = 0;
  1905.     }
  1906. }
  1907.  
  1908.     /* ShutdownCx():
  1909.      *
  1910.      *    Close the Commodities interface.
  1911.      */
  1912.  
  1913. VOID
  1914. ShutdownCx()
  1915. {
  1916.     if(CxPort)
  1917.     {
  1918.         struct Message *Message;
  1919.  
  1920.             /* Remove the broker. */
  1921.  
  1922.         if(Broker)
  1923.             DeleteCxObjAll(Broker);
  1924.  
  1925.             /* Remove the MsgPort from the public list. */
  1926.  
  1927.         RemPort(CxPort);
  1928.  
  1929.             /* Remove all pending messages. */
  1930.  
  1931.         while(Message = GetMsg(CxPort))
  1932.             ReplyMsg(Message);
  1933.  
  1934.             /* Delete the MsgPort. */
  1935.  
  1936.         DeleteMsgPort(CxPort);
  1937.  
  1938.         CxPort = NULL;
  1939.         Broker = NULL;
  1940.     }
  1941. }
  1942.  
  1943.     /* GetSeconds(STRPTR String):
  1944.      *
  1945.      *    Calculates the number of seconds corresponding to
  1946.      *    expressions such as `11:25' or `10'.
  1947.      */
  1948.  
  1949. WORD
  1950. GetSeconds(STRPTR String)
  1951. {
  1952.     WORD i,Seconds;
  1953.  
  1954.     for(i = strlen(String) - 1 ; i >= 0 ; i--)
  1955.     {
  1956.         if(String[i] == ':')
  1957.         {
  1958.             Seconds = Atol(&String[i + 1]);
  1959.  
  1960.             String[i] = 0;
  1961.  
  1962.             Seconds += 60 * Atol(String);
  1963.  
  1964.             if(Seconds > 30 * 60)
  1965.                 Seconds = 30 * 60;
  1966.  
  1967.             return(Seconds);
  1968.         }
  1969.     }
  1970.  
  1971.     if((Seconds = Atol(String)) > 30 * 60)
  1972.         Seconds = 30 * 60;
  1973.  
  1974.     return(Seconds);
  1975. }
  1976.  
  1977.     /* SetupCx(STRPTR *ToolTypes):
  1978.      *
  1979.      *    Set up the Commodities interface.
  1980.      */
  1981.  
  1982. BYTE __regargs
  1983. SetupCx(STRPTR *ToolTypes)
  1984. {
  1985.         /* Cancel any previously made assignments. */
  1986.  
  1987.     ShutdownCx();
  1988.  
  1989.         /* Create a reply port. */
  1990.  
  1991.     if(CxPort = CreateMsgPort())
  1992.     {
  1993.             /* Fill in a unique name. */
  1994.  
  1995.         CxPort -> mp_Node . ln_Name = NewBroker . nb_Name;
  1996.  
  1997.             /* Add the reply port to the public list. */
  1998.  
  1999.         AddPort(CxPort);
  2000.  
  2001.             /* Install the replyport. */
  2002.  
  2003.         NewBroker . nb_Port = CxPort;
  2004.  
  2005.             /* Set the Commodity priority if possible. */
  2006.  
  2007.         if(ToolTypes)
  2008.             NewBroker . nb_Pri  = ArgInt(ToolTypes,"CX_PRIORITY",0);
  2009.  
  2010.             /* Create the broker. */
  2011.  
  2012.         if(Broker = CxBroker(&NewBroker,NULL))
  2013.         {
  2014.             CxObj    *ObjectList;
  2015.             UBYTE    *String,Buffer[256];
  2016.  
  2017.             if(ToolTypes)
  2018.             {
  2019.                     /* Set the Commodity popup hotkey if possible. */
  2020.  
  2021.                 String = ArgString(ToolTypes,"CX_POPKEY","shift f1");
  2022.  
  2023.                 strcpy(HotkeyBuffer,String);
  2024.  
  2025.                     /* Determine the screen blanker hotkey. */
  2026.  
  2027.                 String = ArgString(ToolTypes,"BLANKSCREEN","shift f2");
  2028.  
  2029.                 strcpy(BlankScreenBuffer,String);
  2030.  
  2031.                     /* Which fractal type? */
  2032.  
  2033.                 String = ArgString(ToolTypes,"FRACTAL","RANDOM");
  2034.  
  2035.                 if(!Stricmp(String,"REALPLANE") || !Stricmp(String,"REAL"))
  2036.                     FractalType = FRACTAL_REAL_PLANE;
  2037.                 else
  2038.                 {
  2039.                     if(!Stricmp(String,"COSMICFLAME") || !Stricmp(String,"FLAME"))
  2040.                         FractalType = FRACTAL_COSMIC_FLAME;
  2041.                     else
  2042.                         FractalType = FRACTAL_RANDOM;
  2043.                 }
  2044.  
  2045.                     /* Which colour mode? */
  2046.  
  2047.                 String = ArgString(ToolTypes,"COLOUR","CYCLE");
  2048.  
  2049.                 if(!Stricmp(String,"STATIC"))
  2050.                     ColourMode = COLOUR_STATIC;
  2051.                 else
  2052.                 {
  2053.                     if(!Stricmp(String,"MONO"))
  2054.                         ColourMode = COLOUR_MONO;
  2055.                     else
  2056.                         ColourMode = COLOUR_CYCLE;
  2057.                 }
  2058.  
  2059.                     /* Adjust the screen timeout if possible. */
  2060.  
  2061.                 strcpy(Buffer,ArgString(ToolTypes,"SCREENTIMEOUT","1:00"));
  2062.  
  2063.                 ScreenTimeout = GetSeconds(Buffer);
  2064.  
  2065.                     /* Adjust the pattern change timeout if possible. */
  2066.  
  2067.                 strcpy(Buffer,ArgString(ToolTypes,"PATTERNTIMEOUT","1:00"));
  2068.  
  2069.                 PatternTimeout = GetSeconds(Buffer);
  2070.  
  2071.                     /* Adjust the mouse timeout if possible. */
  2072.  
  2073.                 strcpy(Buffer,ArgString(ToolTypes,"MOUSETIMEOUT","0:05"));
  2074.  
  2075.                 MouseTimeout = GetSeconds(Buffer);
  2076.  
  2077.                     /* Determine whether to enable the keypress
  2078.                      * mouse blanker or not.
  2079.                      */
  2080.  
  2081.                 String = ArgString(ToolTypes,"KEYBLANK","Yes");
  2082.  
  2083.                 if(!Stricmp(String,"No") || !Stricmp(String,"Off"))
  2084.                     KeyBlank = FALSE;
  2085.                 else
  2086.                     KeyBlank = TRUE;
  2087.             }
  2088.  
  2089.                 /* Link the hotkey. */
  2090.  
  2091.             AttachCxObj(Broker,HotKey(HotkeyBuffer,CxPort,POP_WINDOW));
  2092.  
  2093.                 /* Link another hotkey. */
  2094.  
  2095.             AttachCxObj(Broker,HotKey(BlankScreenBuffer,CxPort,BLANK_SCREEN));
  2096.  
  2097.                 /* Install the plain InputEvent handler. */
  2098.  
  2099.             ObjectList = CxCustom(BlankerAction,NULL);
  2100.  
  2101.                 /* Any accumulated errors? */
  2102.  
  2103.             if(!CxObjError(ObjectList))
  2104.             {
  2105.                     /* Add the custom object. */
  2106.  
  2107.                 AttachCxObj(Broker,ObjectList);
  2108.  
  2109.                     /* Any errors? */
  2110.  
  2111.                 if(!CxObjError(Broker))
  2112.                 {
  2113.                         /* Activate the broker. */
  2114.  
  2115.                     ActivateCxObj(Broker,TRUE);
  2116.  
  2117.                     return(TRUE);
  2118.                 }
  2119.             }
  2120.         }
  2121.     }
  2122.  
  2123.     ShutdownCx();
  2124.  
  2125.     return(FALSE);
  2126. }
  2127.  
  2128.     /* HandleCxMsg(CxMsg *Message):
  2129.      *
  2130.      *    Handle incoming Commodities messages.
  2131.      */
  2132.  
  2133. VOID __regargs
  2134. HandleCxMsg(CxMsg *Message)
  2135. {
  2136.     ULONG MessageID = CxMsgID(Message),MessageType = CxMsgType(Message);
  2137.  
  2138.     ReplyMsg((struct Message *)Message);
  2139.  
  2140.         /* Take a look at the message type. */
  2141.  
  2142.     switch(MessageType)
  2143.     {
  2144.             /* It's a hotkey. */
  2145.  
  2146.         case CXM_IEVENT:    switch(MessageID)
  2147.                     {
  2148.                             /* Create the control panel. */
  2149.  
  2150.                         case POP_WINDOW:    SetupWindow();
  2151.                                     break;
  2152.  
  2153.                             /* Blank the screen. */
  2154.  
  2155.                         case BLANK_SCREEN:    if(!BlankTask)
  2156.                                         Signal(BlankerControlTask,SIG_START);
  2157.                                     else
  2158.                                     {
  2159.                                         Signal(BlankerControlTask,SIG_CHANGE);
  2160.  
  2161.                                         PatternCount = 0;
  2162.                                     }
  2163.  
  2164.                                     break;
  2165.                     }
  2166.  
  2167.                     break;
  2168.  
  2169.             /* It's an internal Commodities command. */
  2170.  
  2171.         case CXM_COMMAND:    switch(MessageID)
  2172.                     {
  2173.                             /* Disable the Commodity. */
  2174.  
  2175.                         case CXCMD_DISABLE:    ActivateCxObj(Broker,FALSE);
  2176.                                     break;
  2177.  
  2178.                             /* Enable the Commodity. */
  2179.  
  2180.                         case CXCMD_ENABLE:    ActivateCxObj(Broker,TRUE);
  2181.                                     break;
  2182.  
  2183.                             /* Create the control panel. */
  2184.  
  2185.                         case CXCMD_APPEAR:
  2186.                         case CXCMD_UNIQUE:    SetupWindow();
  2187.                                     break;
  2188.  
  2189.                             /* Close the control panel. */
  2190.  
  2191.                         case CXCMD_DISAPPEAR:    ShutdownWindow();
  2192.                                     break;
  2193.  
  2194.                             /* Remove this Commodity. */
  2195.  
  2196.                         case CXCMD_KILL:    CloseAll(RETURN_OK);
  2197.                                     break;
  2198.                     }
  2199.  
  2200.                     break;
  2201.     }
  2202. }
  2203.  
  2204.     /* ShowTime(struct Gadget *SomeGadget,WORD Level):
  2205.      *
  2206.      *    Gadtools support routine, displays the timeouts.
  2207.      */
  2208.  
  2209. LONG __saveds __stdargs
  2210. ShowTime(struct Gadget *SomeGadget,WORD Level)
  2211. {
  2212.     STATIC UBYTE Buffer[30];
  2213.  
  2214.     if(Level)
  2215.         SPrintf(Buffer,"%2ld.%02ld",Level / 60,Level % 60);
  2216.     else
  2217.         SPrintf(Buffer,"-Off-");
  2218.  
  2219.     return((LONG)Buffer);
  2220. }
  2221.  
  2222.     /* CreateAllGadgets():
  2223.      *
  2224.      *    Gadtools support routine, creates all the gadgets
  2225.      *    required by the control panel.
  2226.      */
  2227.  
  2228. struct Gadget *
  2229. CreateAllGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge)
  2230. {
  2231.     struct Gadget        *Gadget;
  2232.     struct NewGadget     NewGadget;
  2233.     UWORD             Counter = 0;
  2234.  
  2235.     WindowWidth    = 42 * DefaultFontWidth + 20;
  2236.     WindowHeight    = TopEdge + 10 + 9 * (DefaultFont . ta_YSize + 6 + INTERHEIGHT) + 4;
  2237.  
  2238.     if(Gadget = CreateContext(GadgetList))
  2239.     {
  2240.         NewGadget . ng_Width        = DefaultFontWidth * 20;
  2241.         NewGadget . ng_Height        = DefaultFont . ta_YSize + 6;
  2242.         NewGadget . ng_GadgetText    = "_Screen Timeout      ";
  2243.         NewGadget . ng_TextAttr        = &DefaultFont;
  2244.         NewGadget . ng_VisualInfo    = VisualInfo;
  2245.         NewGadget . ng_GadgetID        = Counter;
  2246.         NewGadget . ng_Flags        = 0;
  2247.         NewGadget . ng_LeftEdge        = DefaultFontWidth * 22 + 10;
  2248.         NewGadget . ng_TopEdge        = TopEdge + 6;
  2249.  
  2250.         GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget,
  2251.             GT_Underscore,        '_',
  2252.             GTSL_Min,        0,
  2253.             GTSL_Max,        30 * 60,
  2254.             GTSL_Level,        ScreenTimeout,
  2255.             GTSL_DispFunc,        ShowTime,
  2256.             GTSL_LevelFormat,    "%s",
  2257.             GTSL_MaxLevelLen,    5,
  2258.         TAG_DONE);
  2259.  
  2260.         NewGadget . ng_GadgetText     = "_Mouse Timeout      ";
  2261.         NewGadget . ng_GadgetID         = Counter;
  2262.         NewGadget . ng_TopEdge        += NewGadget . ng_Height + INTERHEIGHT;
  2263.  
  2264.         GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget,
  2265.             GT_Underscore,        '_',
  2266.             GTSL_Min,        0,
  2267.             GTSL_Max,        30 * 60,
  2268.             GTSL_Level,        MouseTimeout,
  2269.             GTSL_DispFunc,        ShowTime,
  2270.             GTSL_LevelFormat,    "%s",
  2271.             GTSL_MaxLevelLen,    5,
  2272.         TAG_DONE);
  2273.  
  2274.         NewGadget . ng_GadgetText     = "_Pattern Change      ";
  2275.         NewGadget . ng_GadgetID         = Counter;
  2276.         NewGadget . ng_TopEdge        += NewGadget . ng_Height + INTERHEIGHT;
  2277.  
  2278.         GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget,
  2279.             GT_Underscore,        '_',
  2280.             GTSL_Min,        0,
  2281.             GTSL_Max,        30 * 60,
  2282.             GTSL_Level,        PatternTimeout,
  2283.             GTSL_DispFunc,        ShowTime,
  2284.             GTSL_LevelFormat,    "%s",
  2285.             GTSL_MaxLevelLen,    5,
  2286.         TAG_DONE);
  2287.  
  2288.         NewGadget . ng_GadgetText     = "Hot _Key";
  2289.         NewGadget . ng_GadgetID         = Counter;
  2290.         NewGadget . ng_TopEdge        += NewGadget . ng_Height + INTERHEIGHT;
  2291.  
  2292.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  2293.             GT_Underscore,    '_',
  2294.             GTST_MaxChars,    255,
  2295.             GTST_String,    HotkeyBuffer,
  2296.         TAG_DONE);
  2297.  
  2298.         NewGadget . ng_GadgetText     = "_Blank Screen";
  2299.         NewGadget . ng_GadgetID         = Counter;
  2300.         NewGadget . ng_TopEdge        += NewGadget . ng_Height + INTERHEIGHT;
  2301.  
  2302.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  2303.             GT_Underscore,    '_',
  2304.             GTST_MaxChars,    255,
  2305.             GTST_String,    BlankScreenBuffer,
  2306.         TAG_DONE);
  2307.  
  2308.         NewGadget . ng_GadgetText     = "Ke_ypress blanks mouse";
  2309.         NewGadget . ng_Width         = 26;
  2310.         NewGadget . ng_GadgetID         = Counter;
  2311.         NewGadget . ng_TopEdge        += NewGadget . ng_Height + INTERHEIGHT;
  2312.  
  2313.         GadgetArray[Counter++] = Gadget = CreateGadget(CHECKBOX_KIND,Gadget,&NewGadget,
  2314.             GT_Underscore,        '_',
  2315.             GTCB_Checked,        KeyBlank,
  2316.         TAG_DONE);
  2317.  
  2318.         NewGadget . ng_GadgetText     = "_Fractal Type";
  2319.         NewGadget . ng_Width         = DefaultFontWidth * 20;
  2320.         NewGadget . ng_GadgetID         = Counter;
  2321.         NewGadget . ng_TopEdge        += NewGadget . ng_Height + INTERHEIGHT;
  2322.  
  2323.         GadgetArray[Counter++] = Gadget = CreateGadget(CYCLE_KIND,Gadget,&NewGadget,
  2324.             GT_Underscore,    '_',
  2325.             GTCY_Labels,    FractalModes,
  2326.             GTCY_Active,    FractalType,
  2327.         TAG_DONE);
  2328.  
  2329.         NewGadget . ng_GadgetText     = "_Colour Mode";
  2330.         NewGadget . ng_GadgetID         = Counter;
  2331.         NewGadget . ng_TopEdge        += NewGadget . ng_Height + INTERHEIGHT;
  2332.  
  2333.         GadgetArray[Counter++] = Gadget = CreateGadget(CYCLE_KIND,Gadget,&NewGadget,
  2334.             GT_Underscore,    '_',
  2335.             GTCY_Labels,    ColourModes,
  2336.             GTCY_Active,    ColourMode,
  2337.         TAG_DONE);
  2338.  
  2339.         NewGadget . ng_GadgetText     = "_Hide";
  2340.         NewGadget . ng_GadgetID         = Counter;
  2341.         NewGadget . ng_Flags         = 0;
  2342.         NewGadget . ng_LeftEdge         = 10;
  2343.         NewGadget . ng_TopEdge        += NewGadget . ng_Height + 4 + INTERHEIGHT;
  2344.  
  2345.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  2346.             GT_Underscore,    '_',
  2347.         TAG_DONE);
  2348.  
  2349.         NewGadget . ng_GadgetText     = "_Quit";
  2350.         NewGadget . ng_GadgetID         = Counter;
  2351.         NewGadget . ng_LeftEdge         = WindowWidth - 10 - NewGadget . ng_Width;
  2352.  
  2353.         GadgetArray[Counter] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  2354.             GT_Underscore,    '_',
  2355.         TAG_DONE);
  2356.     }
  2357.  
  2358.     return(Gadget);
  2359. }
  2360.  
  2361.     /* ShutdownWindow():
  2362.      *
  2363.      *    Closes the control panel.
  2364.      */
  2365.  
  2366. VOID
  2367. ShutdownWindow()
  2368. {
  2369.     if(Window)
  2370.     {
  2371.         CloseWindow(Window);
  2372.  
  2373.         ZoomData . Left = -1;
  2374.  
  2375.         Window = NULL;
  2376.     }
  2377.  
  2378.     if(GadgetList)
  2379.     {
  2380.         FreeGadgets(GadgetList);
  2381.  
  2382.         GadgetList = NULL;
  2383.     }
  2384.  
  2385.     if(VisualInfo)
  2386.     {
  2387.         FreeVisualInfo(VisualInfo);
  2388.  
  2389.         VisualInfo = NULL;
  2390.     }
  2391.  
  2392.     if(DefaultScreen)
  2393.     {
  2394.         UnlockPubScreen(NULL,DefaultScreen);
  2395.  
  2396.         DefaultScreen = NULL;
  2397.     }
  2398.  
  2399.     if(LocalFont)
  2400.     {
  2401.         CloseFont(LocalFont);
  2402.  
  2403.         LocalFont = NULL;
  2404.     }
  2405. }
  2406.  
  2407.     /* CentreWindow():
  2408.      *
  2409.      *    Adjust left/top coordinates of window to be opened to
  2410.      *    become visible right below the mouse pointer.
  2411.      */
  2412.  
  2413. VOID __regargs
  2414. CentreWindow(struct Screen *Screen,WORD *LeftEdge,WORD *TopEdge)
  2415. {
  2416.     (*LeftEdge)    = Screen -> MouseX - (WindowWidth >> 1);
  2417.     (*TopEdge)    = Screen -> MouseY - (WindowHeight >> 1);
  2418.  
  2419.     while((*LeftEdge) + WindowWidth > Screen -> Width)
  2420.         (*LeftEdge)--;
  2421.  
  2422.     while((*LeftEdge) < 0)
  2423.         (*LeftEdge)++;
  2424.  
  2425.     while((*TopEdge) + WindowHeight > Screen -> Height)
  2426.         (*TopEdge)--;
  2427.  
  2428.     while((*TopEdge) < 0)
  2429.         (*TopEdge)++;
  2430. }
  2431.  
  2432.     /* SetupWindow():
  2433.      *
  2434.      *    Creates the control panel and disables the screen
  2435.      *    blanker.
  2436.      */
  2437.  
  2438. BYTE
  2439. SetupWindow()
  2440. {
  2441.     if(BlankTask)
  2442.     {
  2443.         struct Task *Task = BlankTask;
  2444.  
  2445.         BlankTask = NULL;
  2446.  
  2447.         RemTask(Task);
  2448.     }
  2449.  
  2450.     if(BlankScreen)
  2451.     {
  2452.         struct Screen *Screen = BlankScreen;
  2453.  
  2454.         BlankScreen = NULL;
  2455.  
  2456.         ScreenToBack(Screen);
  2457.  
  2458.         FreeVPortCopLists(&Screen -> ViewPort);
  2459.  
  2460.         RethinkDisplay();
  2461.  
  2462.         CloseScreen(Screen);
  2463.     }
  2464.  
  2465.     if(Window)
  2466.     {
  2467.         struct Window    *ActiveWindow;
  2468.         struct Screen    *FirstScreen;
  2469.         ULONG         IntuiLock;
  2470.         BYTE         ZipIt;
  2471.  
  2472.         IntuiLock = LockIBase(NULL);
  2473.  
  2474.         FirstScreen    = IntuitionBase -> FirstScreen;
  2475.         ActiveWindow    = IntuitionBase -> ActiveWindow;
  2476.  
  2477.         UnlockIBase(IntuiLock);
  2478.  
  2479.         if(Window -> WScreen -> TopEdge > 0)
  2480.         {
  2481.             MoveScreen(Window -> WScreen,0,-Window -> WScreen -> TopEdge);
  2482.  
  2483.             ZipIt = FALSE;
  2484.         }
  2485.         else
  2486.             ZipIt = TRUE;
  2487.  
  2488.         if(FirstScreen != Window -> WScreen)
  2489.         {
  2490.             ScreenToFront(Window -> WScreen);
  2491.  
  2492.             ZipIt = FALSE;
  2493.         }
  2494.         else
  2495.             ZipIt = TRUE;
  2496.  
  2497.         if(ActiveWindow != Window)
  2498.         {
  2499.             ActivateWindow(Window);
  2500.  
  2501.             ZipIt = FALSE;
  2502.         }
  2503.         else
  2504.             ZipIt = TRUE;
  2505.  
  2506.         if(Window -> Height != WindowHeight)
  2507.             ZipIt = TRUE;
  2508.  
  2509.         WindowToFront(Window);
  2510.  
  2511.         if(ZipIt)
  2512.             ZipWindow(Window);
  2513.  
  2514.         return(TRUE);
  2515.     }
  2516.     else
  2517.     {
  2518.         Forbid();
  2519.  
  2520.         strcpy(DefaultFontName,GfxBase -> DefaultFont -> tf_Message . mn_Node . ln_Name);
  2521.  
  2522.         DefaultFont . ta_Name    = DefaultFontName;
  2523.         DefaultFont . ta_YSize    = GfxBase -> DefaultFont -> tf_YSize;
  2524.         DefaultFont . ta_Style    = GfxBase -> DefaultFont -> tf_Style;
  2525.         DefaultFont . ta_Flags    = GfxBase -> DefaultFont -> tf_Flags & ~FPF_REMOVED;
  2526.  
  2527.         DefaultFontWidth = GfxBase -> DefaultFont -> tf_XSize;
  2528.  
  2529.         Permit();
  2530.  
  2531.         if(LocalFont = (struct TextFont *)OpenFont(&DefaultFont))
  2532.         {
  2533.             if(DefaultScreen = (struct Screen *)LockPubScreen(NULL))
  2534.             {
  2535.                 if(VisualInfo = GetVisualInfo(DefaultScreen,TAG_DONE))
  2536.                 {
  2537.                     if(CreateAllGadgets(&GadgetArray[0],&GadgetList,VisualInfo,DefaultScreen -> WBorTop + DefaultScreen -> Font -> ta_YSize + 1))
  2538.                     {
  2539.                         WORD Left,Top;
  2540.  
  2541.                         CentreWindow(DefaultScreen,&Left,&Top);
  2542.  
  2543.                         if(ZoomData . Left == -1)
  2544.                         {
  2545.                             ZoomData . Left        = 0;
  2546.                             ZoomData . Top        = 0;
  2547.                             ZoomData . Width    = WindowWidth >> 1;
  2548.                             ZoomData . Height    = DefaultScreen -> WBorTop + DefaultScreen -> Font -> ta_YSize + 1;
  2549.                         }
  2550.  
  2551.                         if(Window = OpenWindowTags(NULL,
  2552.                             WA_CustomScreen,    DefaultScreen,
  2553.  
  2554.                             WA_Left,        Left,
  2555.                             WA_Top,            Top,
  2556.  
  2557.                             WA_Width,        WindowWidth,
  2558.                             WA_Height,        WindowHeight,
  2559.  
  2560.                             WA_Activate,        TRUE,
  2561.                             WA_DragBar,        TRUE,
  2562.                             WA_DepthGadget,        TRUE,
  2563.                             WA_CloseGadget,        TRUE,
  2564.                             WA_RMBTrap,        TRUE,
  2565.                             WA_Zoom,        &ZoomData,
  2566.                             WA_NoCareRefresh,    TRUE,
  2567.  
  2568.                             WA_IDCMP,        IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | IDCMP_REFRESHWINDOW | IDCMP_NEWSIZE | SLIDERIDCMP | BUTTONIDCMP,
  2569.  
  2570.                             WA_Title,        "Fractal Blanker v2.2",
  2571.                         TAG_DONE))
  2572.                         {
  2573.                             SetFont(Window -> RPort,LocalFont);
  2574.  
  2575.                             AddGList(Window,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  2576.                             RefreshGList(GadgetList,Window,NULL,(UWORD)-1);
  2577.                             GT_RefreshWindow(Window,NULL);
  2578.  
  2579.                             if(Window -> WScreen -> TopEdge > 0)
  2580.                                 MoveScreen(Window -> WScreen,0,-Window -> WScreen -> TopEdge);
  2581.  
  2582.                             ScreenToFront(Window -> WScreen);
  2583.  
  2584.                             UnlockPubScreen(NULL,DefaultScreen);
  2585.  
  2586.                             DefaultScreen = NULL;
  2587.  
  2588.                             return(TRUE);
  2589.                         }
  2590.                     }
  2591.                 }
  2592.             }
  2593.         }
  2594.  
  2595.         ShutdownWindow();
  2596.  
  2597.         return(FALSE);
  2598.     }
  2599. }
  2600.  
  2601.     /* CloseAll(LONG ReturnCode):
  2602.      *
  2603.      *    Free all resources and exit the program.
  2604.      */
  2605.  
  2606. VOID __regargs
  2607. CloseAll(LONG ReturnCode)
  2608. {
  2609.     if(CxBase && IconBase)
  2610.     {
  2611.         ShutdownCx();
  2612.  
  2613.         ArgArrayDone();
  2614.     }
  2615.  
  2616.     if(MouseBlankerTask)
  2617.     {
  2618.         Signal(MouseBlankerTask,SIG_BREAK);
  2619.  
  2620.         Wait(SIG_WAKEUP);
  2621.     }
  2622.  
  2623.     if(BlankerControlTask)
  2624.         RemTask(BlankerControlTask);
  2625.  
  2626.     if(BlankTask)
  2627.         RemTask(BlankTask);
  2628.  
  2629.     if(BlankScreen)
  2630.     {
  2631.         ScreenToBack(BlankScreen);
  2632.  
  2633.         FreeVPortCopLists(&BlankScreen -> ViewPort);
  2634.  
  2635.         RethinkDisplay();
  2636.  
  2637.         CloseScreen(BlankScreen);
  2638.  
  2639.         BlankScreen = NULL;
  2640.     }
  2641.  
  2642.     ShutdownWindow();
  2643.  
  2644.     if(IconBase)
  2645.         CloseLibrary(IconBase);
  2646.  
  2647.     if(UtilityBase)
  2648.         CloseLibrary(UtilityBase);
  2649.  
  2650.     if(CxBase)
  2651.         CloseLibrary(CxBase);
  2652.  
  2653.     if(GadToolsBase)
  2654.         CloseLibrary(GadToolsBase);
  2655.  
  2656.     if(GfxBase)
  2657.         CloseLibrary(GfxBase);
  2658.  
  2659.     if(IntuitionBase)
  2660.         CloseLibrary(IntuitionBase);
  2661.  
  2662.     exit(ReturnCode);
  2663. }
  2664.  
  2665.     /* OpenAll(int argc,char **argv):
  2666.      *
  2667.      *    Open all resources, initialize the colour table and
  2668.      *    create the Commodities interface.
  2669.      */
  2670.  
  2671. VOID __regargs
  2672. OpenAll(int argc,char **argv)
  2673. {
  2674.     UBYTE    **ToolTypes,*String;
  2675.     WORD    i,c = 0,r = 15,g = 0,b = 0;
  2676.  
  2677.         /* Set up the pointer to our process structure. */
  2678.  
  2679.     MainProcess = (struct Process *)SysBase -> ThisTask;
  2680.  
  2681.         /* Create a table of rainbow colours. */
  2682.  
  2683.     for(i = 0 ; i < 16 ; i++)
  2684.         Table[c++] = (r << 8) | ((g++) << 4) | b;
  2685.  
  2686.     g = 15;
  2687.     r--;
  2688.  
  2689.     for(i = 0 ; i < 15 ; i++)
  2690.         Table[c++] = ((r--) << 8) | (g << 4) | b;
  2691.  
  2692.     r = 0;
  2693.     g--;
  2694.     b++;
  2695.  
  2696.     for(i = 0 ; i < 15 ; i++)
  2697.         Table[c++] = (r << 8) | ((g--) << 4) | (b++);
  2698.  
  2699.     g = 0;
  2700.     b = 15;
  2701.     r++;
  2702.  
  2703.     for(i = 0 ; i < 15 ; i++)
  2704.         Table[c++] = ((r++) << 8) | (g << 4) | b;
  2705.  
  2706.     r = 15;
  2707.     b--;
  2708.  
  2709.     for(i = 0 ; i < 14 ; i++)
  2710.         Table[c++] = (r << 8) | (g << 4) | (b--);
  2711.  
  2712.         /* Open the libraries we need. */
  2713.  
  2714.     if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)))
  2715.         CloseAll(RETURN_FAIL + 0);
  2716.  
  2717.     if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)))
  2718.         CloseAll(RETURN_FAIL + 1);
  2719.  
  2720.     if(!(GadToolsBase = OpenLibrary("gadtools.library",37)))
  2721.         CloseAll(RETURN_FAIL + 2);
  2722.  
  2723.     if(!(CxBase = OpenLibrary("commodities.library",37)))
  2724.         CloseAll(RETURN_FAIL + 3);
  2725.  
  2726.     if(!(UtilityBase = OpenLibrary("utility.library",37)))
  2727.         CloseAll(RETURN_FAIL + 4);
  2728.  
  2729.     if(!(IconBase = OpenLibrary("icon.library",37)))
  2730.         CloseAll(RETURN_FAIL + 5);
  2731.  
  2732.     if(!(BlankerControlTask = (struct Task *)CreateTask("FracBlank Control Task",100,BlankerControl,8192)))
  2733.         CloseAll(RETURN_FAIL + 6);
  2734.  
  2735.     if(!(MouseBlankerTask = (struct Task *)CreateTask("FracBlank Mouse Blanker Task",100,MouseBlanker,8192)))
  2736.         CloseAll(RETURN_FAIL + 7);
  2737.  
  2738.         /* Wait for handshake signal. */
  2739.  
  2740.     Wait(SIG_WAKEUP);
  2741.  
  2742.         /* Is the blanker still running? */
  2743.  
  2744.     if(!MouseBlankerTask)
  2745.         CloseAll(RETURN_FAIL + 8);
  2746.  
  2747.         /* Parse the startup arguments. */
  2748.  
  2749.     ToolTypes = ArgArrayInit(argc,argv);
  2750.  
  2751.         /* Provide default values. */
  2752.  
  2753.     strcpy(HotkeyBuffer,        "shift f1");
  2754.     strcpy(BlankScreenBuffer,    "shift f2");
  2755.  
  2756.         /* Create the commodities interface. */
  2757.  
  2758.     if(!SetupCx(ToolTypes))
  2759.         CloseAll(RETURN_FAIL + 9);
  2760.  
  2761.         /* Pop up the control panel if necessary. */
  2762.  
  2763.     if(ToolTypes)
  2764.     {
  2765.         String = ArgString(ToolTypes,"CX_POPUP","no");
  2766.  
  2767.         if(!Stricmp(String,"yes"))
  2768.             SetupWindow();
  2769.     }
  2770. }
  2771.  
  2772.     /* main(int argc,char **argv):
  2773.      *
  2774.      *    That's where all the trouble starts.
  2775.      */
  2776.  
  2777. VOID __stdargs
  2778. main(int argc,char **argv)
  2779. {
  2780.     ULONG SignalSet;
  2781.  
  2782.         /* Open everything we need. */
  2783.  
  2784.     OpenAll(argc,argv);
  2785.  
  2786.         /* Go into loop waiting for messages. */
  2787.  
  2788.     FOREVER
  2789.     {
  2790.             /* Wait for a signal... */
  2791.  
  2792.         SignalSet = Wait(SIG_CX | SIG_BREAK | SIG_WAKEUP | SIG_WINDOW);
  2793.  
  2794.             /* Check the commodities toolkit reply port. */
  2795.  
  2796.         if(SignalSet & SIG_CX)
  2797.         {
  2798.             CxMsg *Message;
  2799.  
  2800.             while(Message = (CxMsg *)GetMsg(CxPort))
  2801.                 HandleCxMsg(Message);
  2802.         }
  2803.  
  2804.             /* ^C tells the program to quit. */
  2805.  
  2806.         if(SignalSet & SIG_BREAK)
  2807.             CloseAll(RETURN_OK);
  2808.  
  2809.             /* ^F tells the program to open its control panel. */
  2810.  
  2811.         if(SignalSet & SIG_WAKEUP)
  2812.             SetupWindow();
  2813.  
  2814.             /* If the control panel is still open,
  2815.              * check for new messages.
  2816.              */
  2817.  
  2818.         if(SignalSet & SIG_WINDOW)
  2819.         {
  2820.             struct IntuiMessage    *Massage;
  2821.             struct Gadget        *Gadget;
  2822.             ULONG             Class,Code;
  2823.  
  2824.             while(Massage = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort))
  2825.             {
  2826.                 Class    = Massage -> Class;
  2827.                 Code    = Massage -> Code;
  2828.                 Gadget    = (struct Gadget *)Massage -> IAddress;
  2829.  
  2830.                 GT_ReplyIMsg(Massage);
  2831.  
  2832.                 switch(Class)
  2833.                 {
  2834.                         /* Close the window. */
  2835.  
  2836.                     case IDCMP_CLOSEWINDOW:    ShutdownWindow();
  2837.                                 break;
  2838.  
  2839.                         /* Gadtools does not seem to handle
  2840.                          * it yet: refresh the window
  2841.                          * contents.
  2842.                          */
  2843.  
  2844.                     case IDCMP_NEWSIZE:    GT_RefreshWindow(Window,NULL);
  2845.                                 break;
  2846.  
  2847.                         /* Set the slider values. */
  2848.  
  2849.                     case IDCMP_MOUSEMOVE:    switch(Gadget -> GadgetID)
  2850.                                 {
  2851.                                     case GAD_SCREENTIMEOUT:    ScreenCount    = 0;
  2852.                                                 ScreenTimeout    = Code;
  2853.                                                 break;
  2854.  
  2855.                                     case GAD_MOUSETIMEOUT:    MouseTimeout    = Code;
  2856.                                                 break;
  2857.  
  2858.                                     case GAD_PATTERNCHANGE:    PatternCount    = 0;
  2859.                                                 PatternTimeout    = Code;
  2860.                                                 break;
  2861.                                 }
  2862.  
  2863.                                 break;
  2864.  
  2865.                         /* Handle the keyboard shortcuts. */
  2866.  
  2867.                     case IDCMP_VANILLAKEY:    switch(Code)
  2868.                                 {
  2869.                                     case 's':    ScreenCount = 0;
  2870.  
  2871.                                             if(ScreenTimeout + 1 <= 30 * 60)
  2872.                                                 ScreenTimeout++;
  2873.  
  2874.                                             GT_SetGadgetAttrs(GadgetArray[GAD_SCREENTIMEOUT],Window,NULL,
  2875.                                                 GTSL_Level,ScreenTimeout,
  2876.                                             TAG_DONE);
  2877.  
  2878.                                             break;
  2879.  
  2880.                                     case 'S':    ScreenCount = 0;
  2881.  
  2882.                                             if(ScreenTimeout > 0)
  2883.                                                 ScreenTimeout--;
  2884.  
  2885.                                             GT_SetGadgetAttrs(GadgetArray[GAD_SCREENTIMEOUT],Window,NULL,
  2886.                                                 GTSL_Level,ScreenTimeout,
  2887.                                             TAG_DONE);
  2888.  
  2889.                                             break;
  2890.  
  2891.                                     case 'm':    if(MouseTimeout + 1 <= 30 * 60)
  2892.                                                 MouseTimeout++;
  2893.  
  2894.                                             GT_SetGadgetAttrs(GadgetArray[GAD_MOUSETIMEOUT],Window,NULL,
  2895.                                                 GTSL_Level,MouseTimeout,
  2896.                                             TAG_DONE);
  2897.  
  2898.                                             break;
  2899.  
  2900.                                     case 'M':    if(MouseTimeout > 0)
  2901.                                                 MouseTimeout--;
  2902.  
  2903.                                             GT_SetGadgetAttrs(GadgetArray[GAD_MOUSETIMEOUT],Window,NULL,
  2904.                                                 GTSL_Level,MouseTimeout,
  2905.                                             TAG_DONE);
  2906.  
  2907.                                             break;
  2908.  
  2909.                                     case 'p':    PatternCount = 0;
  2910.  
  2911.                                             if(PatternTimeout + 1 <= 30 * 60)
  2912.                                                 PatternTimeout++;
  2913.  
  2914.                                             GT_SetGadgetAttrs(GadgetArray[GAD_PATTERNCHANGE],Window,NULL,
  2915.                                                 GTSL_Level,PatternTimeout,
  2916.                                             TAG_DONE);
  2917.  
  2918.                                             break;
  2919.  
  2920.                                     case 'P':    PatternCount = 0;
  2921.  
  2922.                                             if(PatternTimeout > 0)
  2923.                                                 PatternTimeout--;
  2924.  
  2925.                                             GT_SetGadgetAttrs(GadgetArray[GAD_PATTERNCHANGE],Window,NULL,
  2926.                                                 GTSL_Level,PatternTimeout,
  2927.                                             TAG_DONE);
  2928.  
  2929.                                             break;
  2930.  
  2931.                                     case 'k':
  2932.                                     case 'K':    ActivateGadget(GadgetArray[GAD_HOTKEY],Window,NULL);
  2933.                                             break;
  2934.  
  2935.                                     case 'b':
  2936.                                     case 'B':    ActivateGadget(GadgetArray[GAD_BLANKSCREEN],Window,NULL);
  2937.                                             break;
  2938.  
  2939.                                     case 'y':
  2940.                                     case 'Y':    KeyBlank ^= TRUE;
  2941.  
  2942.                                             GT_SetGadgetAttrs(GadgetArray[GAD_KEYBLANK],Window,NULL,
  2943.                                                 GTCB_Checked,KeyBlank,
  2944.                                             TAG_DONE);
  2945.  
  2946.                                             break;
  2947.  
  2948.                                     case 'f':    FractalType = (FractalType + 1) % 3;
  2949.  
  2950.                                             GT_SetGadgetAttrs(GadgetArray[GAD_FRACTAL],Window,NULL,
  2951.                                                 GTCY_Active,FractalType,
  2952.                                             TAG_DONE);
  2953.  
  2954.                                             break;
  2955.  
  2956.                                     case 'F':    if(FractalType)
  2957.                                                 FractalType--;
  2958.                                             else
  2959.                                                 FractalType = FRACTAL_RANDOM;
  2960.  
  2961.                                             GT_SetGadgetAttrs(GadgetArray[GAD_FRACTAL],Window,NULL,
  2962.                                                 GTCY_Active,FractalType,
  2963.                                             TAG_DONE);
  2964.  
  2965.                                             break;
  2966.  
  2967.                                     case 'c':    ColourMode = (ColourMode + 1) % 3;
  2968.  
  2969.                                             GT_SetGadgetAttrs(GadgetArray[GAD_COLOUR],Window,NULL,
  2970.                                                 GTCY_Active,ColourMode,
  2971.                                             TAG_DONE);
  2972.  
  2973.                                             break;
  2974.  
  2975.                                     case 'C':    if(ColourMode)
  2976.                                                 ColourMode--;
  2977.                                             else
  2978.                                                 ColourMode = COLOUR_MONO;
  2979.  
  2980.                                             GT_SetGadgetAttrs(GadgetArray[GAD_COLOUR],Window,NULL,
  2981.                                                 GTCY_Active,ColourMode,
  2982.                                             TAG_DONE);
  2983.  
  2984.                                             break;
  2985.  
  2986.                                     case '\033':
  2987.                                     case 'h':
  2988.                                     case 'H':    ShutdownWindow();
  2989.                                             break;
  2990.  
  2991.                                     case 3:
  2992.                                     case 'q':
  2993.                                     case 'Q':    CloseAll(RETURN_OK);
  2994.  
  2995.                                     default:    break;
  2996.                                 }
  2997.  
  2998.                                 break;
  2999.  
  3000.                         /* Handle the gadgets themselves. */
  3001.  
  3002.                     case IDCMP_GADGETUP:    switch(Gadget -> GadgetID)
  3003.                                 {
  3004.                                     case GAD_HOTKEY:    strcpy(HotkeyBuffer,GT_STRING(Gadget));
  3005.  
  3006.                                                 if(!SetupCx(NULL))
  3007.                                                     CloseAll(RETURN_FAIL + 5);
  3008.  
  3009.                                                 break;
  3010.  
  3011.                                     case GAD_BLANKSCREEN:    strcpy(BlankScreenBuffer,GT_STRING(Gadget));
  3012.  
  3013.                                                 if(!SetupCx(NULL))
  3014.                                                     CloseAll(RETURN_FAIL + 5);
  3015.  
  3016.                                                 break;
  3017.  
  3018.                                     case GAD_KEYBLANK:    KeyBlank = GT_CHECKED(Gadget);
  3019.                                                 break;
  3020.  
  3021.                                     case GAD_FRACTAL:    FractalType = Code;
  3022.                                                 break;
  3023.  
  3024.                                     case GAD_COLOUR:    ColourMode = Code;
  3025.                                                 break;
  3026.  
  3027.                                     case GAD_HIDE:        ShutdownWindow();
  3028.                                                 break;
  3029.  
  3030.                                     case GAD_QUIT:        CloseAll(RETURN_OK);
  3031.                                 }
  3032.  
  3033.                                 break;
  3034.                 }
  3035.  
  3036.                     /* Window has been closed, do not
  3037.                      * continue requesting messages
  3038.                      * from the UserPort.
  3039.                      */
  3040.  
  3041.                 if(!Window)
  3042.                     break;
  3043.             }
  3044.         }
  3045.     }
  3046. }
  3047.