home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d535 / fracblank.lha / FracBlank / FracBlank.c < prev    next >
C/C++ Source or Header  |  1991-08-26  |  26KB  |  1,298 lines

  1. /* $Revision Header * Header built automatically - do not edit! *************
  2.  *
  3.  *    (C) Copyright 1990 by Olaf Barthel & MXM
  4.  *
  5.  *    Name .....: FracBlank.c
  6.  *    Created ..: Friday 18-Jun-91 15:28
  7.  *    Revision .: 3
  8.  *
  9.  *    Date            Author          Comment
  10.  *    =========       ========        ====================
  11.  *    29-Jun-91    Olsen        Added VBlank interrupt server.
  12.  *    21-Jun-91    Olsen        Optimizations, cleanups.
  13.  *    18-Jun-91    Olsen        Created this file!
  14.  *
  15.  * $Revision Header ********************************************************/
  16.  
  17.     /* Include the specific math pragmas/header files here (is there
  18.      * any way to figure this out by taking a look at predefined
  19.      * compiler symbols?).
  20.      */
  21.  
  22. #ifdef MATH_FFP
  23. #include <clib/mathtrans_protos.h>
  24. #include <proto/mathtrans.h>
  25. #include <mffp.h>
  26. #else
  27. #include <m68881.h>
  28. #endif    /* MATH_FFP */
  29.  
  30. #include <math.h>
  31.  
  32.     /* sin -45° = cos -45° (saves precious calculation time). */
  33.  
  34. #define deg45    -0.707106781
  35.  
  36.     /* Hotkey IDs. */
  37.  
  38. enum    {    POP_WINDOW,BLANK_SCREEN };
  39.  
  40.     /* Gadget IDs. */
  41.  
  42. enum    {    GAD_SCREENTIMEOUT,GAD_PATTERNCHANGE,GAD_HOTKEY,
  43.         GAD_BLANKSCREEN,GAD_HIDE,GAD_QUIT };
  44.  
  45.     /* Dimensions of the control panel. */
  46.  
  47. #define WIDTH    308
  48. #define HEIGHT    87
  49.  
  50.     /* Sprite blanker interface data. */
  51.  
  52. struct BlankerInfo
  53. {
  54.     struct Task    *RingBack;
  55.     BYTE         Signal;
  56.     BYTE         Enabled;
  57. };
  58.  
  59.     /* Program revision tag. */
  60.  
  61. STATIC const UBYTE * const VersTag = "\0$VER: FracBlank 1.4 (23.7.91)";
  62.  
  63.     /* Shared library identifiers. */
  64.  
  65. extern struct ExecBase    *SysBase;
  66. struct IntuitionBase    *IntuitionBase;
  67. struct GfxBase        *GfxBase;
  68. struct Library        *CxBase,
  69.             *IconBase,
  70.             *GadToolsBase;
  71.  
  72.     /* Blanker data. */
  73.  
  74. struct Task        *BlankTask;
  75. struct Screen        *BlankScreen;
  76.  
  77.     /* Commodities interface data. */
  78.  
  79. struct MsgPort        *CxPort;
  80. CxObj            *Broker;
  81.  
  82.     /* Gfx and gadtools data. */
  83.  
  84. struct Screen        *DefaultScreen;
  85. APTR             VisualInfo;
  86. struct TextFont        *Topaz;
  87. struct Gadget        *GadgetList;
  88. struct Gadget        *GadgetArray[6];
  89. struct Window        *Window;
  90.  
  91.     /* Rainbow colour table. */
  92.  
  93. UWORD             Table[75];
  94.  
  95.     /* Key sequence buffers. */
  96.  
  97. UBYTE             HotkeyBuffer[256],BlankScreenBuffer[256];
  98.  
  99.     /* Screen and pattern change timeout. */
  100.  
  101. ULONG             ScreenCount = 0,PatternCount = 0,ScreenTimeout,PatternTimeout;
  102.  
  103.     /* The default font to be used by the control panel. */
  104.  
  105. struct TextAttr DefaultFont =
  106. {
  107.     (UBYTE *)"topaz.font",
  108.     8,
  109.     FS_NORMAL,
  110.     FPF_ROMFONT
  111. };
  112.  
  113.     /* A new broker definition, Commodities needs this. */
  114.  
  115. struct NewBroker NewBroker =
  116. {
  117.     NB_VERSION,
  118.     "FracBlanker",
  119.     "Fractal Blanker v1.3",
  120.     "Screen Blanker",
  121.     NBU_NOTIFY | NBU_UNIQUE,
  122.     0,0,NULL,0
  123. };
  124.  
  125.     /* Function prototypes. */
  126.  
  127. extern VOID __asm    Plot(register __a0 PLANEPTR Plane,register __d0 UWORD x,register __d1 UWORD y,register __d2 UWORD Modulo,register __d3 UWORD MaxX,register __d4 UWORD MaxY);
  128. LONG __saveds        ShowTime(struct Gadget *SomeGadget,WORD Level);
  129. struct Gadget *        CreateAllGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge);
  130. VOID            ShutdownWindow(VOID);
  131. BYTE            SetupWindow(VOID);
  132. LONG __saveds __asm    SpriteBlanker(register __a1 struct BlankerInfo *BlankerInfo);
  133. VOID            SpriteSwitch(BYTE Enabled);
  134. VOID __saveds        BlankerAction(CxMsg *CxMessage,CxObj *CxObject);
  135. VOID            ShutdownCx(VOID);
  136. BYTE            SetupCx(UBYTE **ToolTypes);
  137. VOID            HandleCxMsg(CxMsg *Message);
  138. ULONG            Random(ULONG MaxValue);
  139. VOID __saveds        Blanker(VOID);
  140. VOID            CloseAll(LONG ReturnCode);
  141. VOID            OpenAll(int argc,char **argv);
  142. VOID __stdargs        main(int argc,char **argv);
  143.  
  144.     /* ShowTime(struct Gadget *SomeGadget,WORD Level):
  145.      *
  146.      *    Gadtools support routine, displays the timeouts.
  147.      */
  148.  
  149. LONG __saveds
  150. ShowTime(struct Gadget *SomeGadget,WORD Level)
  151. {
  152.     STATIC UBYTE Buffer[30];
  153.  
  154.     if(Level)
  155.         SPrintf(Buffer,"%2ld.%02ld",Level / 60,Level % 60);
  156.     else
  157.         SPrintf(Buffer,"-Off-");
  158.  
  159.     return((LONG)Buffer);
  160. }
  161.  
  162.     /* CreateAllGadgets():
  163.      *
  164.      *    Gadtools support routine, creates all the gadgets
  165.      *    required by the control panel.
  166.      */
  167.  
  168. struct Gadget *
  169. CreateAllGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge)
  170. {
  171.     struct Gadget        *Gadget;
  172.     struct NewGadget     NewGadget;
  173.     UWORD             Counter = 0;
  174.  
  175.     if(Gadget = CreateContext(GadgetList))
  176.     {
  177.         NewGadget . ng_Width        = 104;
  178.         NewGadget . ng_Height        = 12;
  179.         NewGadget . ng_GadgetText    = "_Screen Timeout        ";
  180.         NewGadget . ng_TextAttr        = &DefaultFont;
  181.         NewGadget . ng_VisualInfo    = VisualInfo;
  182.         NewGadget . ng_GadgetID        = Counter;
  183.         NewGadget . ng_Flags        = 0;
  184.         NewGadget . ng_LeftEdge        = (strlen(NewGadget . ng_GadgetText) + 2 - 1) * 8 + 2;
  185.         NewGadget . ng_TopEdge        = 1 + TopEdge;
  186.  
  187.         GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget,
  188.             GT_Underscore,        '_',
  189.             GTSL_Min,        0,
  190.             GTSL_Max,        30 * 60,
  191.             GTSL_Level,        ScreenTimeout,
  192.             GTSL_DispFunc,        ShowTime,
  193.             GTSL_LevelFormat,    "%s",
  194.             GTSL_MaxLevelLen,    5,
  195.         TAG_DONE);
  196.  
  197.         NewGadget . ng_GadgetText    = "_Pattern Change       ";
  198.         NewGadget . ng_GadgetID        = Counter;
  199.         NewGadget . ng_TopEdge        = Gadget -> TopEdge + Gadget -> Height + 3;
  200.  
  201.         GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget,
  202.             GT_Underscore,        '_',
  203.             GTSL_Min,        0,
  204.             GTSL_Max,        30 * 60,
  205.             GTSL_Level,        PatternTimeout,
  206.             GTSL_DispFunc,        ShowTime,
  207.             GTSL_LevelFormat,    "%s",
  208.             GTSL_MaxLevelLen,    5,
  209.         TAG_DONE);
  210.  
  211.         NewGadget . ng_GadgetText    = "Hot _Key";
  212.         NewGadget . ng_GadgetID        = Counter;
  213.         NewGadget . ng_Height        = 14;
  214.         NewGadget . ng_TopEdge        = Gadget -> TopEdge + Gadget -> Height + 3;
  215.  
  216.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  217.             GT_Underscore,    '_',
  218.             GTST_MaxChars,    256,
  219.             GTST_String,    HotkeyBuffer,
  220.         TAG_DONE);
  221.  
  222.         NewGadget . ng_GadgetText    = "_Blank Screen";
  223.         NewGadget . ng_GadgetID        = Counter;
  224.         NewGadget . ng_Height        = 14;
  225.         NewGadget . ng_TopEdge        = Gadget -> TopEdge + Gadget -> Height + 4;
  226.  
  227.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  228.             GT_Underscore,    '_',
  229.             GTST_MaxChars,    256,
  230.             GTST_String,    BlankScreenBuffer,
  231.         TAG_DONE);
  232.  
  233.         NewGadget . ng_GadgetText    = "_Hide";
  234.         NewGadget . ng_GadgetID        = Counter;
  235.         NewGadget . ng_Flags        = 0;
  236.         NewGadget . ng_LeftEdge        = 10;
  237.         NewGadget . ng_TopEdge        = HEIGHT - 3 - NewGadget . ng_Height;
  238.  
  239.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  240.             GT_Underscore,    '_',
  241.         TAG_DONE);
  242.  
  243.         NewGadget . ng_GadgetText    = "_Quit";
  244.         NewGadget . ng_GadgetID        = Counter;
  245.         NewGadget . ng_LeftEdge        = WIDTH - 10 - NewGadget . ng_Width;
  246.  
  247.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  248.             GT_Underscore,    '_',
  249.         TAG_DONE);
  250.     }
  251.  
  252.     return(Gadget);
  253. }
  254.  
  255.     /* ShutdownWindow():
  256.      *
  257.      *    Closes the control panel.
  258.      */
  259.  
  260. VOID
  261. ShutdownWindow()
  262. {
  263.     if(Window)
  264.     {
  265.         CloseWindow(Window);
  266.  
  267.         Window = NULL;
  268.     }
  269.  
  270.     if(GadgetList)
  271.     {
  272.         FreeGadgets(GadgetList);
  273.  
  274.         GadgetList = NULL;
  275.     }
  276.  
  277.     if(VisualInfo)
  278.     {
  279.         FreeVisualInfo(VisualInfo);
  280.  
  281.         VisualInfo = NULL;
  282.     }
  283.  
  284.     if(DefaultScreen)
  285.     {
  286.         UnlockPubScreen(NULL,DefaultScreen);
  287.  
  288.         DefaultScreen = NULL;
  289.     }
  290.  
  291.     if(Topaz)
  292.     {
  293.         CloseFont(Topaz);
  294.  
  295.         Topaz = NULL;
  296.     }
  297. }
  298.  
  299.     /* SetupWindow():
  300.      *
  301.      *    Creates the control panel and disables the screen
  302.      *    blanker.
  303.      */
  304.  
  305. BYTE
  306. SetupWindow()
  307. {
  308.     if(BlankTask)
  309.     {
  310.         RemTask(BlankTask);
  311.  
  312.         BlankTask = NULL;
  313.     }
  314.  
  315.     if(BlankScreen)
  316.     {
  317.         ScreenToBack(BlankScreen);
  318.  
  319.         CloseScreen(BlankScreen);
  320.  
  321.         BlankScreen = NULL;
  322.  
  323.         SpriteSwitch(TRUE);
  324.     }
  325.  
  326.     if(Window)
  327.         return(TRUE);
  328.  
  329.     if(Topaz = (struct TextFont *)OpenFont(&DefaultFont))
  330.     {
  331.         if(DefaultScreen = (struct Screen *)LockPubScreen(NULL))
  332.         {
  333.             if(VisualInfo = GetVisualInfo(DefaultScreen,TAG_DONE))
  334.             {
  335.                 if(CreateAllGadgets(&GadgetArray[0],&GadgetList,VisualInfo,DefaultScreen -> WBorTop + DefaultScreen -> Font -> ta_YSize + 1))
  336.                 {
  337.                     if(Window = OpenWindowTags(NULL,
  338.                         WA_Width,    WIDTH,
  339.                         WA_Height,    HEIGHT + DefaultScreen -> Font -> ta_YSize - 8,
  340.  
  341.                         WA_Activate,    TRUE,
  342.                         WA_DragBar,    TRUE,
  343.                         WA_DepthGadget,    TRUE,
  344.                         WA_CloseGadget,    TRUE,
  345.                         WA_RMBTrap,    TRUE,
  346.  
  347.                         WA_IDCMP,    IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | SLIDERIDCMP | BUTTONIDCMP,
  348.  
  349.                         WA_Title,    "Fractal Blanker v1.3",
  350.                     TAG_DONE))
  351.                     {
  352.                         SetFont(Window -> RPort,Topaz);
  353.  
  354.                         AddGList(Window,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  355.                         RefreshGList(GadgetList,Window,NULL,(UWORD)-1);
  356.                         GT_RefreshWindow(Window,NULL);
  357.  
  358.                         return(TRUE);
  359.                     }
  360.                 }
  361.             }
  362.         }
  363.     }
  364.  
  365.     ShutdownWindow();
  366.  
  367.     return(FALSE);
  368. }
  369.  
  370.     /* SpriteBlanker():
  371.      *
  372.      *    VBlank interrupt server, turns on/off all sprite channels
  373.      *    at the top of the frame.
  374.      */
  375.  
  376. LONG __saveds __asm
  377. SpriteBlanker(register __a1 struct BlankerInfo *BlankerInfo)
  378. {
  379.         /* Are we still to run this piece of code? */
  380.  
  381.     if(BlankerInfo -> RingBack)
  382.     {
  383.             /* Enabled/disable the sprites. */
  384.  
  385.         if(BlankerInfo -> Enabled)
  386.             ON_SPRITE
  387.         else
  388.         {
  389.             UWORD i;
  390.  
  391.             OFF_SPRITE
  392.  
  393.             for(i = 0 ; i < 8 ; i++)
  394.             {
  395.                 custom . spr[i] . dataa = 0;
  396.                 custom . spr[i] . datab = 0;
  397.             }
  398.         }
  399.  
  400.             /* Signal father task to remove the server. */
  401.  
  402.         Signal(BlankerInfo -> RingBack,1 << BlankerInfo -> Signal);
  403.  
  404.             /* Sprites are to be turned on only once. */
  405.  
  406.         if(BlankerInfo -> Enabled)
  407.             BlankerInfo -> RingBack = NULL;
  408.     }
  409.  
  410.     return(0);
  411. }
  412.  
  413.     /* SpriteSwitch(BYTE Enabled):
  414.      *
  415.      *    Enable/disable sprite DMA by enabling a VBlank
  416.      *    interrupt server.
  417.      */
  418.  
  419. VOID
  420. SpriteSwitch(BYTE Enabled)
  421. {
  422.     struct BlankerInfo __aligned    BlankerInfo;
  423.     struct Interrupt __aligned    BlankInterrupt;
  424.  
  425.         /* Fill in the standard data. */
  426.  
  427.     BlankerInfo . RingBack    = SysBase -> ThisTask;
  428.     BlankerInfo . Signal    = AllocSignal(-1);
  429.     BlankerInfo . Enabled    = Enabled;
  430.  
  431.         /* Did we get the a signal? */
  432.  
  433.     if(BlankerInfo . Signal != -1)
  434.     {
  435.             /* Enable the interrupt server. */
  436.  
  437.         BlankInterrupt . is_Node . ln_Name    = "FracBlank.interrupt";
  438.         BlankInterrupt . is_Node . ln_Type    = NT_INTERRUPT;
  439.         BlankInterrupt . is_Node . ln_Pri    = 0;
  440.         BlankInterrupt . is_Code        = (APTR)SpriteBlanker;
  441.         BlankInterrupt . is_Data        = (APTR)&BlankerInfo;
  442.         
  443.         WaitTOF();
  444.         WaitTOF();
  445.  
  446.         AddIntServer(INTB_VERTB,&BlankInterrupt);
  447.  
  448.             /* Wait for ringback signal. */
  449.  
  450.         Wait(1 << BlankerInfo . Signal);
  451.  
  452.         if(!Enabled)
  453.         {
  454.                 /* Wait for another signal to make sure the
  455.                  * sprites are really off.
  456.                  */
  457.  
  458.             Wait(1 << BlankerInfo . Signal);
  459.         }
  460.  
  461.             /* Remove the server. */
  462.  
  463.         RemIntServer(INTB_VERTB,&BlankInterrupt);
  464.  
  465.             /* Free the signal. */
  466.  
  467.         FreeSignal(BlankerInfo . Signal);
  468.     }
  469. }
  470.  
  471.     /* BlankerAction(CxMsg *CxMessage,CxObj *CxObject):
  472.      *
  473.      *    Commodities support routine, handles the Commodities
  474.      *    custom actions (in this case: filter the InputEvents
  475.      *    coming in and enable/disable the screen blanker).
  476.      */
  477.  
  478. VOID __saveds
  479. BlankerAction(CxMsg *CxMessage,CxObj *CxObject)
  480. {
  481.     STATIC BYTE Count = 1;
  482.  
  483.     struct InputEvent *Event = (struct InputEvent *)CxMsgData(CxMessage);
  484.  
  485.         /* Push the blanker screen to the front if necessary. */
  486.  
  487.     if(BlankScreen)
  488.     {
  489.         if(BlankScreen -> TopEdge)
  490.             MoveScreen(BlankScreen,0,-BlankScreen -> TopEdge);
  491.  
  492.         if(IntuitionBase -> FirstScreen != BlankScreen)
  493.         {
  494.             ScreenToFront(BlankScreen);
  495.  
  496.             SpriteSwitch(FALSE);
  497.         }
  498.     }
  499.  
  500.         /* This looks like a timer event. */
  501.  
  502.     if(Event -> ie_Class == IECLASS_TIMER && !Window)
  503.     {
  504.             /* Screen blanker still inactive? */
  505.  
  506.         if(!BlankTask)
  507.         {
  508.                 /* Is there a timeout to take care of? */
  509.  
  510.             if(ScreenTimeout)
  511.             {
  512.                     /* Are we ready to create the
  513.                      * screenblanker?
  514.                      */
  515.  
  516.                 if(ScreenCount++ >= ScreenTimeout * 10)
  517.                 {
  518.                     if(BlankTask = (struct Task *)CreateTask("FracBlank.task",-20,Blanker,4000))
  519.                         PatternCount = 0;
  520.                 }
  521.             }
  522.         }
  523.         else
  524.         {
  525.                 /* Every 5/60 second we signal the blanker
  526.                  * task to rotate the palette.
  527.                  */
  528.  
  529.             if(Count++ == 2)
  530.             {
  531.                 Signal(BlankTask,SIGBREAKF_CTRL_E);
  532.  
  533.                 Count = 0;
  534.             }
  535.  
  536.                 /* Is it time to change the pattern? */
  537.  
  538.             if(PatternTimeout)
  539.             {
  540.                 if(PatternCount++ >= PatternTimeout * 10)
  541.                 {
  542.                     Signal(BlankTask,SIGBREAKF_CTRL_D);
  543.  
  544.                     PatternCount = 0;
  545.                 }
  546.             }
  547.         }
  548.     }
  549.     else
  550.     {
  551.             /* The following line determines whether
  552.              * the blanker is to be removed or to
  553.              * be left running.
  554.              */
  555.  
  556.         if((Event -> ie_Class == IECLASS_RAWKEY && !(Event -> ie_Code & IECODE_UP_PREFIX)) || Event -> ie_Class == IECLASS_RAWMOUSE)
  557.         {
  558.                 /* Remove the blanker task. */
  559.  
  560.             if(BlankTask)
  561.             {
  562.                 RemTask(BlankTask);
  563.  
  564.                 BlankTask = NULL;
  565.             }
  566.  
  567.                 /* Close the blanker screen. */
  568.  
  569.             if(BlankScreen)
  570.             {
  571.                 ScreenToBack(BlankScreen);
  572.  
  573.                 SpriteSwitch(TRUE);
  574.  
  575.                 CloseScreen(BlankScreen);
  576.  
  577.                 BlankScreen = NULL;
  578.             }
  579.         }
  580.  
  581.         ScreenCount = 0;
  582.     }
  583. }
  584.  
  585.     /* ShutdownCx():
  586.      *
  587.      *    Close the Commodities interface.
  588.      */
  589.  
  590. VOID
  591. ShutdownCx()
  592. {
  593.     if(CxPort)
  594.     {
  595.         struct Message *Message;
  596.  
  597.             /* Remove the broker. */
  598.  
  599.         if(Broker)
  600.             DeleteCxObjAll(Broker);
  601.  
  602.             /* Remove the MsgPort from the public list. */
  603.  
  604.         RemPort(CxPort);
  605.  
  606.             /* Remove all pending messages. */
  607.  
  608.         while(Message = GetMsg(CxPort))
  609.             ReplyMsg(Message);
  610.  
  611.             /* Delete the MsgPort. */
  612.  
  613.         DeleteMsgPort(CxPort);
  614.  
  615.         CxPort = NULL;
  616.         Broker = NULL;
  617.     }
  618. }
  619.  
  620.     /* SetupCx(UBYTE **ToolTypes):
  621.      *
  622.      *    Set up the Commodities interface.
  623.      */
  624.  
  625. BYTE
  626. SetupCx(UBYTE **ToolTypes)
  627. {
  628.         /* Cancel any previously made assignments. */
  629.  
  630.     ShutdownCx();
  631.  
  632.         /* Create a reply port. */
  633.  
  634.     if(CxPort = CreateMsgPort())
  635.     {
  636.             /* Fill in a unique name. */
  637.  
  638.         CxPort -> mp_Node . ln_Name = NewBroker . nb_Name;
  639.  
  640.             /* Add the reply port to the public list. */
  641.  
  642.         AddPort(CxPort);
  643.  
  644.             /* Set the Commodity priority if possible. */
  645.  
  646.         if(ToolTypes)
  647.         {
  648.             NewBroker . nb_Pri  = ArgInt(ToolTypes,"CX_PRIORITY",0);
  649.             NewBroker . nb_Port = CxPort;
  650.         }
  651.  
  652.             /* This Commodity features a control panel. */
  653.  
  654.         NewBroker . nb_Flags |= COF_SHOW_HIDE;
  655.  
  656.             /* Create the broker. */
  657.  
  658.         if(Broker = CxBroker(&NewBroker,NULL))
  659.         {
  660.             CxObj    *ObjectList;
  661.             UBYTE    *String;
  662.  
  663.                 /* Set the Commodity popup hotkey if possible. */
  664.  
  665.             if(ToolTypes)
  666.             {
  667.                 String = ArgString(ToolTypes,"CX_POPKEY","shift f1");
  668.  
  669.                 strcpy(HotkeyBuffer,String);
  670.             }
  671.  
  672.                 /* Link the hotkey. */
  673.  
  674.             AttachCxObj(Broker,HotKey(HotkeyBuffer,CxPort,POP_WINDOW));
  675.  
  676.                 /* Determine the screen blanker hotkey. */
  677.  
  678.             if(ToolTypes)
  679.             {
  680.                 String = ArgString(ToolTypes,"BLANKSCREEN","shift f2");
  681.  
  682.                 strcpy(BlankScreenBuffer,String);
  683.             }
  684.  
  685.                 /* Link another hotkey. */
  686.  
  687.             AttachCxObj(Broker,HotKey(BlankScreenBuffer,CxPort,BLANK_SCREEN));
  688.  
  689.                 /* Adjust the screen timeout if possible. */
  690.  
  691.             if(ToolTypes)
  692.                 ScreenTimeout = ArgInt(ToolTypes,"SCREENTIMEOUT",60);
  693.  
  694.                 /* Adjust the pattern change timeout if possible. */
  695.  
  696.             if(ToolTypes)
  697.                 PatternTimeout = ArgInt(ToolTypes,"PATTERNTIMEOUT",60);
  698.  
  699.                 /* Install the plain InputEvent handler. */
  700.  
  701.             ObjectList = CxCustom(BlankerAction,NULL);
  702.  
  703.                 /* Any accumulated errors? */
  704.  
  705.             if(!CxObjError(ObjectList))
  706.             {
  707.                     /* Add the custom object. */
  708.  
  709.                 AttachCxObj(Broker,ObjectList);
  710.  
  711.                     /* Any errors? */
  712.  
  713.                 if(!CxObjError(Broker))
  714.                 {
  715.                         /* Activate the broker. */
  716.  
  717.                     ActivateCxObj(Broker,TRUE);
  718.  
  719.                     return(TRUE);
  720.                 }
  721.             }
  722.         }
  723.     }
  724.  
  725.     ShutdownCx();
  726.  
  727.     return(FALSE);
  728. }
  729.  
  730.     /* HandleCxMsg(CxMsg *Message):
  731.      *
  732.      *    Handle incoming Commodities messages.
  733.      */
  734.  
  735. VOID
  736. HandleCxMsg(CxMsg *Message)
  737. {
  738.     ULONG MessageType = CxMsgID(Message),MessageID = CxMsgType(Message);
  739.  
  740.     ReplyMsg((struct Message *)Message);
  741.  
  742.         /* Take a look at the message type. */
  743.  
  744.     switch(MessageID)
  745.     {
  746.             /* It's a hotkey. */
  747.  
  748.         case CXM_IEVENT:    switch(MessageType)
  749.                     {
  750.                             /* Create the control panel. */
  751.  
  752.                         case POP_WINDOW:    SetupWindow();
  753.                                     break;
  754.  
  755.                             /* Blank the screen. */
  756.  
  757.                         case BLANK_SCREEN:    if(!BlankTask)
  758.                                     {
  759.                                             /* Blanker task isn't running yet,
  760.                                              * so let's create it.
  761.                                              */
  762.  
  763.                                         if(BlankTask = (struct Task *)CreateTask("FracBlank.task",-20,Blanker,4000))
  764.                                             PatternCount = 0;
  765.                                     }
  766.                                     else
  767.                                     {
  768.                                             /* Tell the blanker task to change the pattern. */
  769.  
  770.                                         Signal(BlankTask,SIGBREAKF_CTRL_D);
  771.  
  772.                                         PatternCount = 0;
  773.                                     }
  774.  
  775.                                     break;
  776.                     }
  777.  
  778.                     break;
  779.  
  780.             /* It's an internal Commodities command. */
  781.  
  782.         case CXM_COMMAND:    switch(MessageType)
  783.                     {
  784.                             /* Disable the Commodity. */
  785.  
  786.                         case CXCMD_DISABLE:    ActivateCxObj(Broker,FALSE);
  787.                                     break;
  788.  
  789.                             /* Enable the Commodity. */
  790.  
  791.                         case CXCMD_ENABLE:    ActivateCxObj(Broker,TRUE);
  792.                                     break;
  793.  
  794.                             /* Create the control panel. */
  795.  
  796.                         case CXCMD_APPEAR:
  797.                         case CXCMD_UNIQUE:    SetupWindow();
  798.                                     break;
  799.  
  800.                             /* Close the control panel. */
  801.  
  802.                         case CXCMD_DISAPPEAR:    ShutdownWindow();
  803.                                     break;
  804.  
  805.                             /* Remove this Commodity. */
  806.  
  807.                         case CXCMD_KILL:    CloseAll(RETURN_OK);
  808.                                     break;
  809.                     }
  810.  
  811.                     break;
  812.     }
  813. }
  814.  
  815.     /* Random(ULONG MaxValue):
  816.      *
  817.      *    Simple random number generation routine.
  818.      */
  819.  
  820. ULONG
  821. Random(ULONG MaxValue)
  822. {
  823.     STATIC ULONG RandomSeed = 0xDEAD0123;
  824.  
  825.     RandomSeed = RandomSeed * custom . vhposr + 0xE153766F;
  826.  
  827.     return(RandomSeed % MaxValue);
  828. }
  829.  
  830.     /* Blanker():
  831.      *
  832.      *    The screen blanker itself.
  833.      */
  834.  
  835. VOID __saveds
  836. Blanker()
  837. {
  838.         /* Open the screen. */
  839.  
  840.     if(BlankScreen = OpenScreenTags(NULL,
  841.         SA_Behind,    TRUE,
  842.         SA_Quiet,    TRUE,
  843.         SA_DisplayID,    HIRESLACE_KEY,
  844.         SA_Overscan,    OSCAN_STANDARD,
  845.         SA_Depth,    1,
  846.     TAG_DONE))
  847.     {
  848.         STATIC BYTE    Wheel = 0;
  849.  
  850.         UWORD        Modulo = BlankScreen -> RastPort . BitMap -> BytesPerRow,Colours[2],OffsetX = BlankScreen -> Width >> 1,OffsetY = BlankScreen -> Height >> 1;
  851.         PLANEPTR    Plane = BlankScreen -> RastPort . BitMap -> Planes[0];
  852.         float        x = 0,y = 0,yy,a,b,c,sx,sy,mag,save;
  853.  
  854.             /* Provide starting numbers for the fractal
  855.              * parameters.
  856.              */
  857.  
  858.         a = (float)Random(300) / 100;
  859.         b = (float)Random(100) / 100;
  860.         c = (float)Random( 50) / 100;
  861.  
  862.         mag = (float)(1 << (Random(4) + 5)) * deg45;
  863.  
  864.             /* Set up the screen colour table. */
  865.  
  866.         Colours[0] = 0;
  867.         Colours[1] = Table[Wheel];
  868.  
  869.         LoadRGB4(&BlankScreen -> ViewPort,Colours,2);
  870.  
  871.             /* Push the screen to the front. */
  872.  
  873.         ScreenToFront(BlankScreen);
  874.  
  875.             /* Turn off all sprite channels. */
  876.  
  877.         SpriteSwitch(FALSE);
  878.  
  879.             /* Go into fractal generation loop. */
  880.  
  881.         FOREVER
  882.         {
  883.                 /* The original formula looks like
  884.                  * this:
  885.                  *                                     ½
  886.                  *    x <- y - SIGN(x) * ABS(b * x - c)
  887.                  *    y <- a - x
  888.                  *
  889.                  * I have split the calculation into
  890.                  * several steps to save time and
  891.                  * variables.
  892.                  */
  893.  
  894.             yy = a - x;
  895.  
  896.             if((save = b * x - c) < 0)
  897.                 save = -save;
  898.  
  899.             if(x < 0)
  900.                 x = y + sqrt(save);
  901.             else
  902.                 x = y - sqrt(save);
  903.  
  904.             y = yy;
  905.  
  906.                 /* The resulting image appears to have
  907.                  * been rotated by 45°, so we'll
  908.                  * rotate the pixel coordinates by -45°
  909.                  *
  910.                  *    x <-  x * cos alpha + y * sin alpha
  911.                  *    y <- -x * sin alpha + y * cos alpha
  912.                  *
  913.                  * We also magnify the image (i.e. the
  914.                  * distribution of pixels) in the following
  915.                  * lines.
  916.                  */
  917.  
  918.             sx = mag * ( x + y);
  919.             sy = mag * (-x + y);
  920.  
  921.                 /* If the pixel happens to reside within
  922.                  * the boundaries of the screen, draw it.
  923.                  */
  924.  
  925.             Plot(Plane,(LONG)(sx) + OffsetX,(LONG)(sy) + OffsetY,Modulo,BlankScreen -> Width,BlankScreen -> Height);
  926.  
  927.                 /* ^D tells the blanker to change the pattern. */
  928.  
  929.             if(SetSignal(0,0) & SIGBREAKF_CTRL_D)
  930.             {
  931.                 SetSignal(0,SIGBREAKF_CTRL_D);
  932.  
  933.                 SetRast(&BlankScreen -> RastPort,0);
  934.  
  935.                 x = y = 0;
  936.  
  937.                 a = (float)Random(300) / 100;
  938.                 b = (float)Random(100) / 100;
  939.                 c = (float)Random( 50) / 100;
  940.  
  941.                 mag = (float)(1 << (Random(4) + 5)) * deg45;
  942.             }
  943.  
  944.                 /* ^E tells the blanker to rotate the
  945.                  * colours.
  946.                  */
  947.  
  948.             if(SetSignal(0,0) & SIGBREAKF_CTRL_E)
  949.             {
  950.                 SetSignal(0,SIGBREAKF_CTRL_E);
  951.  
  952.                 Wheel = (Wheel + 1) % 75;
  953.  
  954.                 Colours[1] = Table[Wheel];
  955.  
  956.                 LoadRGB4(&BlankScreen -> ViewPort,Colours,2);
  957.             }
  958.         }
  959.     }
  960.  
  961.         /* Quietly remove ourselves. */
  962.  
  963.     Forbid();
  964.  
  965.     BlankTask = NULL;
  966.  
  967.     RemTask(SysBase -> ThisTask);
  968. }
  969.  
  970.     /* CloseAll(LONG ReturnCode):
  971.      *
  972.      *    Free all resources and exit the program.
  973.      */
  974.  
  975. VOID
  976. CloseAll(LONG ReturnCode)
  977. {
  978.     if(CxBase && IconBase)
  979.     {
  980.         ShutdownCx();
  981.  
  982.         ArgArrayDone();
  983.     }
  984.  
  985.     if(BlankTask)
  986.         RemTask(BlankTask);
  987.  
  988.     if(BlankScreen)
  989.     {
  990.         SpriteSwitch(TRUE);
  991.  
  992.         ScreenToBack(BlankScreen);
  993.  
  994.         CloseScreen(BlankScreen);
  995.     }
  996.  
  997.     ShutdownWindow();
  998.  
  999.     if(IconBase)
  1000.         CloseLibrary(IconBase);
  1001.  
  1002.     if(CxBase)
  1003.         CloseLibrary(CxBase);
  1004.  
  1005.     if(GadToolsBase)
  1006.         CloseLibrary(GadToolsBase);
  1007.  
  1008.     if(GfxBase)
  1009.         CloseLibrary(GfxBase);
  1010.  
  1011.     if(IntuitionBase)
  1012.         CloseLibrary(IntuitionBase);
  1013.  
  1014.     exit(ReturnCode);
  1015. }
  1016.  
  1017.     /* OpenAll(int argc,char **argv):
  1018.      *
  1019.      *    Open all resources, initialize the colour table and
  1020.      *    create the Commodities interface.
  1021.      */
  1022.  
  1023. VOID
  1024. OpenAll(int argc,char **argv)
  1025. {
  1026.     UBYTE **ToolTypes,*String;
  1027.     SHORT i,c = 0,r = 15,g = 0,b = 0;
  1028.  
  1029.         /* Create a table of rainbow colours. */
  1030.  
  1031.     for(i = 0 ; i < 16 ; i++)
  1032.         Table[c++] = (r << 8) | ((g++) << 4) | b;
  1033.  
  1034.     g = 15;
  1035.     r--;
  1036.  
  1037.     for(i = 0 ; i < 15 ; i++)
  1038.         Table[c++] = ((r--) << 8) | (g << 4) | b;
  1039.  
  1040.     r = 0;
  1041.     g--;
  1042.     b++;
  1043.  
  1044.     for(i = 0 ; i < 15 ; i++)
  1045.         Table[c++] = (r << 8) | ((g--) << 4) | (b++);
  1046.  
  1047.     g = 0;
  1048.     b = 15;
  1049.     r++;
  1050.  
  1051.     for(i = 0 ; i < 15 ; i++)
  1052.         Table[c++] = ((r++) << 8) | (g << 4) | b;
  1053.  
  1054.     r = 15;
  1055.     b--;
  1056.  
  1057.     for(i = 0 ; i < 14 ; i++)
  1058.         Table[c++] = (r << 8) | (g << 4) | (b--);
  1059.  
  1060.         /* Open the libraries we need. */
  1061.  
  1062.     if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)))
  1063.         CloseAll(RETURN_FAIL + 0);
  1064.  
  1065.     if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)))
  1066.         CloseAll(RETURN_FAIL + 1);
  1067.  
  1068.     if(!(GadToolsBase = OpenLibrary("gadtools.library",37)))
  1069.         CloseAll(RETURN_FAIL + 2);
  1070.  
  1071.     if(!(CxBase = OpenLibrary("commodities.library",37)))
  1072.         CloseAll(RETURN_FAIL + 3);
  1073.  
  1074.     if(!(IconBase = OpenLibrary("icon.library",37)))
  1075.         CloseAll(RETURN_FAIL + 4);
  1076.  
  1077.         /* Parse the startup arguments. */
  1078.  
  1079.     ToolTypes = ArgArrayInit(argc,argv);
  1080.  
  1081.         /* Provide default values. */
  1082.  
  1083.     strcpy(HotkeyBuffer,        "shift f1");
  1084.     strcpy(BlankScreenBuffer,    "shift f2");
  1085.  
  1086.     ScreenTimeout    = 60;
  1087.     PatternTimeout    = 60;
  1088.  
  1089.         /* Create the commodities interface. */
  1090.  
  1091.     if(!SetupCx(ToolTypes))
  1092.         CloseAll(RETURN_FAIL + 5);
  1093.  
  1094.         /* Pop up the control panel if necessary. */
  1095.  
  1096.     if(ToolTypes)
  1097.     {
  1098.         String = ArgString(ToolTypes,"CX_POPUP","no");
  1099.  
  1100.         if(!strcmpi(String,"yes") || !strcmpi(String,"on"))
  1101.             SetupWindow();
  1102.     }
  1103. }
  1104.  
  1105.     /* main(int argc,char **argv):
  1106.      *
  1107.      *    That's where all the trouble starts.
  1108.      */
  1109.  
  1110. VOID __stdargs
  1111. main(int argc,char **argv)
  1112. {
  1113.     ULONG SignalSet;
  1114.  
  1115.         /* Open everything we need. */
  1116.  
  1117.     OpenAll(argc,argv);
  1118.  
  1119.         /* Go into loop waiting for messages. */
  1120.  
  1121.     FOREVER
  1122.     {
  1123.         SignalSet = (1 << CxPort -> mp_SigBit) | SIGBREAKF_CTRL_E;
  1124.  
  1125.             /* If the window is still open, wait for
  1126.              * some news.
  1127.              */
  1128.  
  1129.         if(Window)
  1130.             SignalSet |= (1 << Window -> UserPort -> mp_SigBit);
  1131.  
  1132.         SignalSet = Wait(SignalSet);
  1133.  
  1134.             /* There are messages pending at the
  1135.              * Commodities reply port.
  1136.              */
  1137.  
  1138.         if(SignalSet & (1 << CxPort -> mp_SigBit))
  1139.         {
  1140.             CxMsg *Message;
  1141.  
  1142.             while(Message = (CxMsg *)GetMsg(CxPort))
  1143.                 HandleCxMsg(Message);
  1144.         }
  1145.  
  1146.             /* ^E tells the program to quit. */
  1147.  
  1148.         if(SignalSet & SIGBREAKF_CTRL_E)
  1149.             CloseAll(RETURN_OK);
  1150.  
  1151.             /* If the control panel is still open,
  1152.              * check for new messages.
  1153.              */
  1154.  
  1155.         if(Window)
  1156.         {
  1157.             if(SignalSet & (1 << Window -> UserPort -> mp_SigBit))
  1158.             {
  1159.                 struct IntuiMessage    *Massage;
  1160.                 struct Gadget        *Gadget;
  1161.                 ULONG             Class,Code;
  1162.  
  1163.                 while(Massage = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort))
  1164.                 {
  1165.                     Class    = Massage -> Class;
  1166.                     Code    = Massage -> Code;
  1167.                     Gadget    = (struct Gadget *)Massage -> IAddress;
  1168.  
  1169.                     GT_ReplyIMsg(Massage);
  1170.  
  1171.                     switch(Class)
  1172.                     {
  1173.                             /* Close the window. */
  1174.  
  1175.                         case IDCMP_CLOSEWINDOW:    ShutdownWindow();
  1176.                                     break;
  1177.  
  1178.                             /* Set the slider values. */
  1179.  
  1180.                         case IDCMP_MOUSEMOVE:    switch(Gadget -> GadgetID)
  1181.                                     {
  1182.                                         case GAD_SCREENTIMEOUT:    ScreenCount = 0;
  1183.                                                     ScreenTimeout = Code;
  1184.                                                     break;
  1185.  
  1186.                                         case GAD_PATTERNCHANGE:    PatternCount = 0;
  1187.                                                     PatternTimeout = Code;
  1188.                                                     break;
  1189.                                     }
  1190.  
  1191.                                     break;
  1192.  
  1193.                             /* Handle the keyboard shortcuts. */
  1194.  
  1195.                         case IDCMP_VANILLAKEY:    switch(toupper(Code))
  1196.                                     {
  1197.                                         case 'S':    ScreenCount = 0;
  1198.  
  1199.                                                 if(Code == 's')
  1200.                                                 {
  1201.                                                     if(ScreenTimeout + 1 <= 30 * 60)
  1202.                                                         ScreenTimeout++;
  1203.                                                     else
  1204.                                                         ScreenTimeout = ScreenTimeout + 1 - 30 * 60;
  1205.                                                 }
  1206.                                                 else
  1207.                                                 {
  1208.                                                     if(ScreenTimeout + 10 <= 30 * 60)
  1209.                                                         ScreenTimeout += 10;
  1210.                                                     else
  1211.                                                         ScreenTimeout = ScreenTimeout + 10 - 30 * 60;
  1212.                                                 }
  1213.  
  1214.                                                 GT_SetGadgetAttrs(GadgetArray[GAD_SCREENTIMEOUT],Window,NULL,
  1215.                                                     GTSL_Level,ScreenTimeout,
  1216.                                                 TAG_DONE);
  1217.  
  1218.                                                 break;
  1219.  
  1220.                                         case 'P':    PatternCount = 0;
  1221.  
  1222.                                                 if(Code == 'p')
  1223.                                                 {
  1224.                                                     if(PatternTimeout + 1 <= 30 * 60)
  1225.                                                         PatternTimeout++;
  1226.                                                     else
  1227.                                                         PatternTimeout = PatternTimeout + 1 - 30 * 60;
  1228.                                                 }
  1229.                                                 else
  1230.                                                 {
  1231.                                                     if(PatternTimeout + 10 <= 30 * 60)
  1232.                                                         PatternTimeout += 10;
  1233.                                                     else
  1234.                                                         PatternTimeout = PatternTimeout + 10 - 30 * 60;
  1235.                                                 }
  1236.  
  1237.                                                 GT_SetGadgetAttrs(GadgetArray[GAD_PATTERNCHANGE],Window,NULL,
  1238.                                                     GTSL_Level,PatternTimeout,
  1239.                                                 TAG_DONE);
  1240.  
  1241.                                                 break;
  1242.  
  1243.                                         case 'K':    ActivateGadget(GadgetArray[GAD_HOTKEY],Window,NULL);
  1244.                                                 break;
  1245.  
  1246.                                         case 'B':    ActivateGadget(GadgetArray[GAD_BLANKSCREEN],Window,NULL);
  1247.                                                 break;
  1248.  
  1249.                                         case 'H':    ShutdownWindow();
  1250.                                                 break;
  1251.  
  1252.                                         case 'Q':    CloseAll(RETURN_OK);
  1253.  
  1254.                                         default:    break;
  1255.                                     }
  1256.  
  1257.                                     break;
  1258.  
  1259.                             /* Handle the gadgets themselves. */
  1260.  
  1261.                         case IDCMP_GADGETUP:    switch(Gadget -> GadgetID)
  1262.                                     {
  1263.                                         case GAD_HOTKEY:    strcpy(HotkeyBuffer,((struct StringInfo *)Gadget -> SpecialInfo) -> Buffer);
  1264.  
  1265.                                                     if(!SetupCx(NULL))
  1266.                                                         CloseAll(RETURN_FAIL + 5);
  1267.  
  1268.                                                     break;
  1269.  
  1270.                                         case GAD_BLANKSCREEN:    strcpy(BlankScreenBuffer,((struct StringInfo *)Gadget -> SpecialInfo) -> Buffer);
  1271.  
  1272.                                                     if(!SetupCx(NULL))
  1273.                                                         CloseAll(RETURN_FAIL + 5);
  1274.  
  1275.                                                     break;
  1276.  
  1277.                                         case GAD_HIDE:        ShutdownWindow();
  1278.                                                     break;
  1279.  
  1280.                                         case GAD_QUIT:        CloseAll(RETURN_OK);
  1281.                                     }
  1282.  
  1283.                                     break;
  1284.                     }
  1285.  
  1286.                         /* Window has been closed, do not
  1287.                          * continue requesting messages
  1288.                          * from the UserPort.
  1289.                          */
  1290.  
  1291.                     if(!Window)
  1292.                         break;
  1293.                 }
  1294.             }
  1295.         }
  1296.     }
  1297. }
  1298.