home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 616.lha / ASwarmII_v1.1 / ASwarm.c < prev    next >
C/C++ Source or Header  |  1992-02-05  |  33KB  |  1,301 lines

  1. /*
  2.  
  3.       ASwarm II V1.1
  4.  
  5.    Written by Markus "Ill" Illenseer and Matthias "Tron" Scheler
  6.    Based upon Jeff Buterworths XSwarm
  7.  
  8. */
  9.  
  10. #include <hardware/custom.h>
  11. #include <hardware/dmabits.h>
  12. #include <exec/memory.h>
  13. #include <exec/ports.h>
  14. #include <exec/execbase.h>
  15. #include <graphics/displayinfo.h>
  16. #include <graphics/gfxbase.h>
  17. #include <graphics/gfxmacros.h>
  18. #include <intuition/intuitionbase.h>
  19. #include <libraries/commodities.h>
  20. #include <libraries/gadtools.h>
  21. #include <dos/dosextens.h>
  22. #include <dos/dostags.h>
  23. #include <utility/tagitem.h>
  24.  
  25. #include <clib/alib_protos.h>
  26. #include <clib/alib_stdio_protos.h>
  27. #include <clib/commodities_protos.h>
  28. #include <clib/dos_protos.h>
  29. #include <clib/exec_protos.h>
  30. #include <clib/gadtools_protos.h>
  31. #include <clib/graphics_protos.h>
  32. #include <clib/intuition_protos.h>
  33. #include <clib/macros.h>
  34.  
  35. #include <string.h>
  36. #include <stdlib.h>
  37.  
  38. #ifdef LATTICE /* some stuff for SAS-C */
  39.  
  40. #include <pragmas/commodities_pragmas.h>
  41. #include <pragmas/dos_pragmas.h>
  42. #include <pragmas/exec_pragmas.h>
  43. #include <pragmas/gadtools_pragmas.h>
  44. #include <pragmas/graphics_pragmas.h>
  45. #include <pragmas/intuition_pragmas.h>
  46.  
  47. #define VOID_INTERRUPT void __interrupt __saveds
  48. #define REGARGS        __regargs
  49. #define VOID_STDARGS   void __stdargs
  50.  
  51. UBYTE *VersionString = "$VER: ASwarm II V1.1 (compiled with SAS/C)";
  52.  
  53. void chkabort(void)
  54.  
  55. {}
  56.  
  57. #else /* some stuff for Dice especially for -mR */
  58.  
  59. #include <workbench/startup.h>
  60.  
  61. #define VOID_INTERRUPT __stkargs __geta4 void
  62. #define REGARGS
  63. #define VOID_STDARGS   __stkargs void
  64.  
  65. #undef HotKey
  66. #undef ArgArrayInit
  67. #undef ArgInt
  68. #undef ArgString
  69.  
  70. __stkargs CxObj *HotKey(UBYTE *,struct MsgPort *,long);
  71. __stkargs UBYTE **ArgArrayInit(long arg1,UBYTE **arg2 );
  72. __stkargs LONG ArgInt(UBYTE **arg1,UBYTE *arg2,long arg3 );
  73. __stkargs UBYTE *ArgString(UBYTE **arg1,UBYTE *arg2,UBYTE *arg3);
  74.  
  75. UBYTE *VersionString = "$VER: ASwarm II V1.1 (compiled with DICE)";
  76.  
  77. void main(LONG,UBYTE **);
  78.  
  79. void wbmain(struct WBStartup *WBS)
  80.  
  81. {
  82.  if (WBS->sm_NumArgs) (void)CurrentDir(WBS->sm_ArgList->wa_Lock);
  83.  
  84.  main(0L,(UBYTE **)WBS);
  85. }
  86.  
  87. #endif
  88.  
  89. /*
  90.  
  91.    Common Definitions
  92.  
  93. */
  94.  
  95. #define custom (*((struct Custom *)0xDFF000L))
  96.  
  97. extern struct ExecBase *SysBase;
  98. extern struct DosLibrary *DOSBase;
  99.  
  100. #define FINDPROCPORT (&((struct Process *)SysBase->ThisTask)->pr_MsgPort)
  101.  
  102. struct IntuitionBase *IntuitionBase;
  103. struct GfxBase *GfxBase;
  104.  
  105. struct Library *CxBase,*GadToolsBase,*IconBase;
  106.  
  107. /*
  108.  
  109.    Definitions for our Commodity
  110.  
  111. */
  112.  
  113. struct NewBroker NewBroker =
  114.  {NB_VERSION,"ASwarm II","Amiga Swarm II V1.1","Screen Blanker based on XSwarm",
  115.   NBU_NOTIFY|NBU_UNIQUE,COF_SHOW_HIDE,0,NULL,0};
  116. struct MsgPort *CxPort;
  117.  
  118. UBYTE *PopKey;
  119.  
  120. #define EVENT_OPEN_WINDOW 1L
  121.  
  122. #define DEF_CX_PRI 0L
  123. #define DEF_POPKEY "alt s"
  124.  
  125. LONG TimeOut,ClientTimeOut;
  126.  
  127. #define MAX_TIMEOUT        3600L
  128. #define MAX_CLIENT_TIMEOUT 60L
  129.  
  130. #define DEF_TIMEOUT        60L
  131. #define DEF_CLIENT_TIMEOUT 5L
  132.  
  133. #define SERVER_PRI 5L
  134. #define CLIENT_PRI -40L
  135.  
  136. /*
  137.  
  138.    Definitions for our Blanker Screen
  139.  
  140. */
  141.  
  142. struct NewScreen NewBlankerScreen =
  143.  {0,0,STDSCREENWIDTH,STDSCREENHEIGHT,2,-1,-1,0L,CUSTOMSCREEN|SCREENQUIET,NULL,NULL,NULL,NULL};
  144.  
  145. struct ModeNode
  146.  {
  147.   struct Node mn_Node;
  148.   UWORD mn_Index;
  149.   ULONG mn_DisplayID;
  150.   char mn_Name[DISPLAYNAMELEN];
  151.  };
  152.  
  153. struct List *ModeList;
  154. struct ModeNode *DisplayMode;
  155.  
  156. #define FindMode(l,n) ((struct ModeNode *)FindName(l,n))
  157.  
  158. #define DEF_MODE      HIRES
  159. #define DEF_MODE_NAME "Hires"
  160.  
  161. /*
  162.  
  163.    Definitions for our Configuration Window
  164.  
  165. */
  166.  
  167. struct NewWindow NewBlankerWindow =
  168.  {20,16,480,160,0,1,IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW|IDCMP_GADGETDOWN|IDCMP_GADGETUP|
  169.   IDCMP_VANILLAKEY,WINDOWCLOSE|WINDOWDRAG|WINDOWDEPTH|SIMPLE_REFRESH,NULL,NULL,NULL,NULL,NULL,
  170.   0,0,0,0,WBENCHSCREEN};
  171. struct Window *BlankerWindow;
  172.  
  173. #define GID_HIDE     1
  174. #define GID_BLANK    2
  175. #define GID_QUIT     3
  176. #define GID_MODE     4
  177. #define GID_TIMEOUT  5
  178. #define GID_CLIENT   6
  179. #define GID_SPEED    7
  180. #define GID_WASPS    8
  181. #define GID_BEES     9
  182. #define GID_CYCLE   10
  183. #define GID_AIM     11
  184.  
  185. #define NUM_GADS 11
  186.  
  187. struct VisualInfo *BlankerVisualInfo;
  188. struct Gadgets *BlankerGadgets;
  189. struct TextAttr BlankerAttr={"topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT};
  190. struct NewGadget NewBlankerGadgets[NUM_GADS] =
  191.  {16,144,48,12,"_Hide",&BlankerAttr,GID_HIDE,PLACETEXT_IN,NULL,NULL,
  192.   80,144,48,12,"_Blank",&BlankerAttr,GID_BLANK,PLACETEXT_IN,NULL,NULL,
  193.   144,144,48,12,"_Quit",&BlankerAttr,GID_QUIT,PLACETEXT_IN,NULL,NULL,
  194.   208,28,248,128,"Display Mode",&BlankerAttr,GID_MODE,PLACETEXT_ABOVE,NULL,NULL,
  195.   136,28,56,12,"Timeout",&BlankerAttr,GID_TIMEOUT,PLACETEXT_LEFT,NULL,NULL,
  196.   136,42,56,12,"Client Timeout",&BlankerAttr,GID_CLIENT,PLACETEXT_LEFT,NULL,NULL,
  197.   136,67,56,12,"Speed",&BlankerAttr,GID_SPEED,PLACETEXT_LEFT,NULL,NULL,
  198.   136,81,56,12,"Wasps",&BlankerAttr,GID_WASPS,PLACETEXT_LEFT,NULL,NULL,
  199.   136,95,56,12,"Bees",&BlankerAttr,GID_BEES,PLACETEXT_LEFT,NULL,NULL,
  200.   152,110,16,12,"Color Cycling",&BlankerAttr,GID_CYCLE,PLACETEXT_LEFT,NULL,NULL,
  201.   152,124,16,12,"Aim Mode",&BlankerAttr,GID_AIM,PLACETEXT_LEFT,NULL,NULL};
  202.  
  203. UBYTE BlankerGadgetKinds[NUM_GADS] =
  204.  {BUTTON_KIND,BUTTON_KIND,BUTTON_KIND,LISTVIEW_KIND,
  205.   INTEGER_KIND,INTEGER_KIND,INTEGER_KIND,INTEGER_KIND,INTEGER_KIND,
  206.   CHECKBOX_KIND,CHECKBOX_KIND};
  207. struct TagItem BlankerGadgetTags[] =
  208.  {GT_Underscore,(ULONG)'_',TAG_DONE,0L,
  209.   GTLV_Labels,0L,GTLV_Selected,0L,GTLV_ShowSelected,NULL,TAG_DONE,0L,
  210.   GTIN_Number,0L,GTIN_MaxChars,4L,TAG_DONE,0L,
  211.   GTIN_Number,0L,GTIN_MaxChars,2L,TAG_DONE,0L,
  212.   GTIN_Number,0L,GTIN_MaxChars,2L,TAG_DONE,0L,
  213.   GTIN_Number,0L,GTIN_MaxChars,2L,TAG_DONE,0L,
  214.   GTIN_Number,0L,GTIN_MaxChars,3L,TAG_DONE,0L,
  215.   GTCB_Checked,0L,TAG_DONE,0L,
  216.   GTCB_Checked,0L,TAG_DONE,0L};
  217. UBYTE BlankerTagsIndex[NUM_GADS] = {0,0,0,2,6,9,12,15,18,21,23};
  218.  
  219. /*
  220.  
  221.     Definitions for Server/Client Communication
  222.  
  223. */
  224.  
  225. BYTE bsp_TimerSig,bsp_InputSig,bsp_ClientSig;
  226. struct Task *BlankerServerProcess;
  227.  
  228. #define MASK(n) (1L<<(n))
  229.  
  230. struct BlankerClientMsg
  231.  {
  232.   struct Message bcm_Message;
  233.   struct Screen *bcm_Screen;
  234.   LONG bcm_Status;
  235.   ULONG bcm_SigMask;
  236.   LONG bcm_Wasps,bcm_Bees,bcm_Speed,bcm_Cycle,bcm_Aim;
  237.  };
  238.  
  239. /*
  240.  
  241.    Definitions or Swarm Movement
  242.  
  243. */
  244.  
  245. #define BEEACC  3
  246. #define BEEVEL  9
  247. #define WASPACC 5
  248. #define WASPVEL 13
  249. #define BORDER  5
  250.  
  251. #define BEE_COL_NUM 32
  252.  
  253. UWORD BeeColors[BEE_COL_NUM] =
  254.  {0x000F,0x004F,0x008F,0x00BF,0x00FF,0x00FB,0x00F7,0x00F3,0x00F0,0x04F0,0x08F0,
  255.   0x09F0,0x0AF0,0x0BF0,0x0CF0,0x0DF0,0x0EF0,0x0FF0,0x0FE0,0x0FD0,0x0FC0,0x0FB0,
  256.   0x0F90,0x0F80,0x0F70,0x0F60,0x0F50,0x0F40,0x0F30,0x0F20,0x0F10,0x0F00};
  257.  
  258. #define RAND(m) (Random(m)-(m)/2)
  259.  
  260. UWORD SwarmColors[4] = {0x0000,0x0FFF,0x0000,0x0FFF};
  261. LONG NumWasps,NumBees;
  262. LONG Speed,Cycle,Aim;
  263.  
  264. struct SwarmStruct /* structure for a swarm, including the wasp */
  265.  {
  266.   WORD ss_Width;
  267.   WORD ss_Height;
  268.   WORD ss_NumWasps;
  269.   WORD *ss_WX[4];  /* the wasps  */
  270.   WORD *ss_WY[4];
  271.   WORD ss_NumBees;
  272.   WORD *ss_X[4];   /* the NumBees */
  273.   WORD *ss_Y[4];
  274.   WORD *ss_MW;     /* My next Wasp */
  275.  };
  276.  
  277. /* Ill's strange Macros for easy access to the above structure */
  278.  
  279. #define BXVel(I)   (SP->ss_X[3][I])
  280. #define BYVel(I)   (SP->ss_Y[3][I])
  281. #define BeeX(P,I)  (SP->ss_X[P][I])
  282. #define BeeY(P,I)  (SP->ss_Y[P][I])
  283. #define MyWasp(I)  (SP->ss_MW[I])
  284.  
  285. #define WaXVel(I)  (SP->ss_WX[3][I])
  286. #define WaYVel(I)  (SP->ss_WY[3][I])
  287. #define WaspX(P,I) (SP->ss_WX[P][I])
  288. #define WaspY(P,I) (SP->ss_WY[P][I])
  289.  
  290. /* Mini and Maximum definitions for possible parameters */
  291.  
  292. #define MAX_SPEED 4L
  293. #define MAX_WASPS 10L
  294. #define MAX_BEES  500L
  295.  
  296. #define DEF_SPEED 4L
  297. #define DEF_WASPS 2L
  298. #define DEF_BEES  25L
  299.  
  300. /*
  301.  
  302.     The following functions are taken from my resource tracker library for SAS/C.
  303.     I normally use to link the programs with this library, but to make it possible
  304.     for other people to compile ASwarm I included the required source codes.
  305.  
  306. */
  307.  
  308. struct ToolNode
  309.  {
  310.   struct ToolNode *Next;
  311.   void *Tool;
  312.   void (*RemProc)(void *,LONG); /* requires stack arguments !!! */
  313.   LONG Size;
  314.  } *ToolList;
  315.  
  316. void REGARGS RemTool(void *Tool)
  317.  
  318. {
  319.  struct ToolNode **Ptr,*ToolNode;
  320.  
  321.  Ptr=&ToolList;
  322.  while (*Ptr)
  323.   if ((*Ptr)->Tool==Tool)
  324.    {
  325.     ToolNode=*Ptr;
  326.     *Ptr=(*Ptr)->Next;
  327.     ToolNode->RemProc(ToolNode->Tool,ToolNode->Size);
  328.     FreeMem (ToolNode,sizeof(struct ToolNode));
  329.    }
  330.   else Ptr=&(*Ptr)->Next;
  331. }
  332.  
  333. void REGARGS Quit(int ReturnCode)
  334.  
  335. {
  336.  while (ToolList) RemTool (ToolList->Tool);
  337.  
  338.  exit (ReturnCode);
  339. }
  340.  
  341. void REGARGS AddTool(void *NewTool,void *ProcPtr,LONG NewSize)
  342.  
  343. {
  344.  struct ToolNode *Ptr;
  345.  void (*NewRemProc)(void *,LONG);
  346.  
  347.  NewRemProc=ProcPtr;
  348.  if (NewTool==NULL) Quit (10);
  349.  
  350.  if ((Ptr=AllocMem(sizeof(struct ToolNode),0L))==NULL)
  351.   {
  352.    NewRemProc (NewTool,NewSize);
  353.    Quit (20);
  354.   }
  355.  Ptr->Next=ToolList;
  356.  Ptr->Tool=NewTool;
  357.  Ptr->RemProc=NewRemProc;
  358.  Ptr->Size=NewSize;
  359.  ToolList=Ptr;
  360. }
  361.  
  362. /*
  363.  
  364.    Some useful functions
  365.  
  366. */
  367.  
  368. VOID_STDARGS DeleteMsgPortSafely(struct MsgPort *AnyPort)
  369.  
  370. {
  371.  struct Message *AnyMsg;
  372.  
  373.  while (AnyMsg=GetMsg(AnyPort)) ReplyMsg (AnyMsg);
  374.  DeleteMsgPort (AnyPort);
  375. }
  376.  
  377. LONG REGARGS ArgIntMax(char **ToolTypes,char *ID,LONG Default,LONG Max)
  378.  
  379. {
  380.  LONG Val;
  381.  
  382.  Val=ArgInt(ToolTypes,ID,Default);
  383.  if ((Val<1L)||(Val>Max)) return Default;
  384.  else return Val;
  385. }
  386.  
  387. LONG REGARGS ArgBoolean(char **ToolTypes,char *ID,LONG Default)
  388.  
  389. {
  390.  if (Default) return (stricmp(ArgString(ToolTypes,ID,""),"NO")!=0L);
  391.  else return (stricmp(ArgString(ToolTypes,ID,""),"YES")==0L);
  392. }
  393.  
  394. /*
  395.  
  396.    Our "InputHandler"
  397.  
  398. */
  399.  
  400. VOID_INTERRUPT BlankerAction(CxMsg *CxMsg,CxObj *CO)
  401.  
  402. {
  403.  struct InputEvent *IE;
  404.  
  405.  IE=(struct InputEvent *)CxMsgData(CxMsg);
  406.  if (IE->ie_Class==IECLASS_TIMER) Signal (BlankerServerProcess,1L<<bsp_TimerSig);
  407.  else Signal (BlankerServerProcess,1L<<bsp_InputSig);
  408. }
  409.  
  410. /*
  411.  
  412.    Functions for Handling the List of the avaible Graphics Modes
  413.  
  414. */
  415.  
  416. VOID_STDARGS DeleteModeList(struct List *ModeList)
  417.  
  418. {
  419.  struct ModeNode *ModeNode;
  420.  
  421.  while (ModeList->lh_Head->ln_Succ)
  422.   {
  423.    ModeNode=(struct ModeNode *)ModeList->lh_Head;
  424.    RemHead (ModeList);
  425.    FreeMem (ModeNode,sizeof(struct ModeNode));
  426.   }
  427.  FreeMem (ModeList,sizeof(struct List));
  428. }
  429.  
  430. struct List *CreateModeList(void)
  431.  
  432. {
  433.  struct List *ModeList;
  434.  UWORD Num;
  435.  ULONG DisplayID;
  436.  struct DimensionInfo DimInfo;
  437.  struct NameInfo NameInfo;
  438.  struct ModeNode *ModeNode;
  439.  
  440.  if (ModeList=AllocMem(sizeof(struct List),MEMF_PUBLIC)) NewList (ModeList);
  441.  else return NULL;
  442.  
  443.  Num=0;
  444.  DisplayID=INVALID_ID;
  445.  while ((DisplayID=NextDisplayInfo(DisplayID))!=INVALID_ID)
  446.   if ((DisplayID&MONITOR_ID_MASK)&&(ModeNotAvailable(DisplayID)==0L))
  447.    if (GetDisplayInfoData(NULL,(UBYTE *)&DimInfo,sizeof(struct DimensionInfo),DTAG_DIMS,DisplayID))
  448.     if (DimInfo.MaxDepth>1)
  449.      if (GetDisplayInfoData(NULL,(UBYTE *)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,DisplayID))
  450.       if (ModeNode=AllocMem(sizeof(struct ModeNode),MEMF_PUBLIC))
  451.        {
  452.         (void)strcpy(ModeNode->mn_Node.ln_Name=ModeNode->mn_Name,NameInfo.Name);
  453.         ModeNode->mn_Index=Num++;
  454.         ModeNode->mn_DisplayID=DisplayID;
  455.         AddTail (ModeList,&ModeNode->mn_Node);
  456.        }
  457.  
  458.  if (ModeList->lh_Head->ln_Succ==NULL)
  459.   if (ModeNode=AllocMem(sizeof(struct ModeNode),MEMF_PUBLIC))
  460.    {
  461.     (void)strcpy(ModeNode->mn_Node.ln_Name=ModeNode->mn_Name,DEF_MODE_NAME);
  462.     ModeNode->mn_Index=Num;
  463.     ModeNode->mn_DisplayID=DEF_MODE;
  464.     AddTail (ModeList,&ModeNode->mn_Node);
  465.    }
  466.   else
  467.    {
  468.     FreeMem (ModeList,sizeof(struct List));
  469.     return NULL;
  470.    }
  471.  
  472.  return ModeList;
  473. }
  474.  
  475. struct ModeNode *GetDefaultMode(struct List *ModeList)
  476.  
  477. {
  478.  struct NameInfo NameInfo;
  479.  struct ModeNode *ModeNode;
  480.  
  481.  if (GetDisplayInfoData(NULL,(UBYTE *)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,DEF_MODE))
  482.   if (ModeNode=FindMode(ModeList,NameInfo.Name)) return ModeNode;
  483.  
  484.  return (struct ModeNode *)ModeList->lh_Head;
  485. }
  486.  
  487. struct ModeNode *GetIndexMode(struct List *ModeList,UWORD Index)
  488.  
  489. {
  490.  struct ModeNode *ModeNode;
  491.  
  492.  ModeNode=(struct ModeNode *)ModeList->lh_Head;
  493.  while (ModeNode->mn_Node.ln_Succ)
  494.   if (ModeNode->mn_Index==Index) return ModeNode;
  495.   else ModeNode=(struct ModeNode *)ModeNode->mn_Node.ln_Succ;
  496.  
  497.  return (struct ModeNode *)ModeList->lh_Head;
  498. }
  499.  
  500. /*
  501.  
  502.    Functions for Handling the Configuration Window
  503.  
  504. */
  505.  
  506. LONG GetNum(struct Gadget *Gadget,LONG *Data,LONG Max)
  507.  
  508. {
  509.  LONG NewData;
  510.  
  511.  NewData=((struct StringInfo *)Gadget->SpecialInfo)->LongInt;
  512.  if ((NewData<1L)||(NewData>Max))
  513.   {
  514.    GT_SetGadgetAttrs (Gadget,BlankerWindow,NULL,GTIN_Number,(ULONG)*Data,TAG_DONE);
  515.    return FALSE;
  516.   }
  517.  else
  518.   {
  519.    *Data=NewData;
  520.    return TRUE;
  521.   }
  522. }
  523.  
  524. void CloseBlankerWindow(void)
  525.  
  526. {
  527.  if (BlankerWindow)
  528.   {
  529.    NewBlankerWindow.LeftEdge=BlankerWindow->LeftEdge;
  530.    NewBlankerWindow.TopEdge=BlankerWindow->TopEdge;
  531.  
  532.    RemTool (BlankerGadgets);
  533.    RemTool (BlankerVisualInfo);
  534.    RemTool (BlankerWindow);
  535.    BlankerWindow=NULL;
  536.   }
  537. }
  538.  
  539. void OpenBlankerWindow(void)
  540.  
  541. {
  542.  struct Gadget *Ptr;
  543.  UWORD Index;
  544.  static char Title[80];
  545.  struct TagItem WindowTags[3];
  546.  
  547.  if (BlankerWindow==NULL)
  548.   {
  549.    WindowTags[0].ti_Tag=WA_Title;
  550.    WindowTags[1].ti_Tag=WA_AutoAdjust;
  551.    WindowTags[1].ti_Data=TRUE;
  552.    WindowTags[2].ti_Tag=TAG_DONE;
  553.  
  554.    (void)strcpy(Title,"ASwarm II by Illenseer/Scheler: HotKey=");
  555.    WindowTags[0].ti_Data=(ULONG)strcat(Title,PopKey);
  556.  
  557.    if (BlankerWindow=OpenWindowTagList(&NewBlankerWindow,WindowTags))
  558.     {
  559.      AddTool (BlankerWindow,CloseWindow,NULL);
  560.  
  561.      if ((BlankerVisualInfo=GetVisualInfo(BlankerWindow->WScreen,TAG_DONE))==NULL)
  562.       {
  563.        RemTool (BlankerWindow);
  564.        return;
  565.       }
  566.      AddTool (BlankerVisualInfo,FreeVisualInfo,0L);
  567.  
  568.      BlankerGadgets=NULL;
  569.      if ((Ptr=CreateContext(&BlankerGadgets))==NULL)
  570.       {
  571.        RemTool (BlankerVisualInfo);
  572.        RemTool (BlankerWindow);
  573.        return;
  574.       }
  575.      AddTool (Ptr,FreeGadgets,0L);
  576.  
  577.      BlankerGadgetTags[2].ti_Data=(ULONG)ModeList;
  578.      BlankerGadgetTags[3].ti_Data=(ULONG)DisplayMode->mn_Index;
  579.      BlankerGadgetTags[6].ti_Data=(ULONG)TimeOut;
  580.      BlankerGadgetTags[9].ti_Data=(ULONG)ClientTimeOut;
  581.      BlankerGadgetTags[12].ti_Data=(ULONG)Speed;
  582.      BlankerGadgetTags[15].ti_Data=(ULONG)NumWasps;
  583.      BlankerGadgetTags[18].ti_Data=(ULONG)NumBees;
  584.      BlankerGadgetTags[21].ti_Data=(ULONG)Cycle;
  585.      BlankerGadgetTags[23].ti_Data=(ULONG)Aim;
  586.      for (Index=0L; Index<NUM_GADS; Index++)
  587.       {
  588.        NewBlankerGadgets[Index].ng_VisualInfo=BlankerVisualInfo;
  589.        Ptr=CreateGadgetA((ULONG)BlankerGadgetKinds[Index],Ptr,&NewBlankerGadgets[Index],
  590.                          &BlankerGadgetTags[BlankerTagsIndex[Index]]);
  591.        if (Ptr==NULL)
  592.         {
  593.          CloseBlankerWindow();
  594.          return;
  595.         }
  596.       }
  597.  
  598.      AddGList (BlankerWindow,BlankerGadgets,0L,-1L,NULL);
  599.      RefreshGadgets (BlankerGadgets,BlankerWindow,NULL);
  600.      GT_RefreshWindow (BlankerWindow,NULL);
  601.     }
  602.   }
  603.  
  604.  ScreenToFront (BlankerWindow->WScreen);
  605.  WindowToFront (BlankerWindow);
  606.  ActivateWindow (BlankerWindow);
  607. }
  608.  
  609. /*
  610.  
  611.    Function to handle the Commodity Stuff
  612.  
  613. */
  614.  
  615. void REGARGS HandleCxMsg(CxObj *Broker,CxMsg *CxMsg)
  616.  
  617. {
  618.  ULONG MsgType,MsgID;
  619.  
  620.  MsgType=CxMsgType(CxMsg);
  621.  MsgID=CxMsgID(CxMsg);
  622.  ReplyMsg ((struct Message *)CxMsg);
  623.  
  624.  switch (MsgType)
  625.   {
  626.    case CXM_IEVENT: /* HotKey was pressed */
  627.     OpenBlankerWindow();
  628.     break;
  629.    case CXM_COMMAND:
  630.     switch (MsgID)
  631.      {
  632.       case CXCMD_DISABLE: /* Message created by Exchange (except CXCMD_UNIQUE) */
  633.        (void)ActivateCxObj(Broker,FALSE);
  634.        break;
  635.       case CXCMD_ENABLE:
  636.        (void)ActivateCxObj(Broker,TRUE);
  637.        break;
  638.       case CXCMD_UNIQUE:
  639.       case CXCMD_APPEAR:
  640.        OpenBlankerWindow();
  641.        break;
  642.       case CXCMD_DISAPPEAR:
  643.        CloseBlankerWindow();
  644.        break;
  645.       case CXCMD_KILL:
  646.        Quit (0);
  647.      }
  648.    }
  649. }
  650.  
  651. /*
  652.  
  653.    Open a Screen with the supplied DisplayID
  654.  
  655. */
  656.  
  657. void SpritesOff(void)
  658.  
  659. {
  660.  ULONG Index;
  661.  
  662.  OFF_SPRITE /* switch sprites off */
  663.  for (Index=0L; Index<8L; Index++) custom.spr[Index].ctl=0;
  664. }
  665.  
  666. struct Screen *CreateScreen(struct List *ModeList,struct ModeNode *ModeNode)
  667.  
  668. {
  669.  struct TagItem ScreenTags[2];
  670.  struct Screen *Screen;
  671.  
  672.  ScreenTags[0].ti_Tag=SA_DisplayID;
  673.  ScreenTags[0].ti_Data=ModeNode->mn_DisplayID;
  674.  ScreenTags[1].ti_Tag=TAG_DONE;
  675.  if (Screen=OpenScreenTagList(&NewBlankerScreen,ScreenTags))
  676.   {
  677.    SetRGB4 (&Screen->ViewPort,0,0,0,0);
  678.    SetRast (&Screen->RastPort,0);
  679.  
  680.    SpritesOff();
  681.   }
  682.  return Screen;
  683. }
  684.  
  685. /*
  686.  
  687.    Functions fore Creating/Deleting the Client Process
  688.  
  689. */
  690.  
  691. VOID_STDARGS DeleteBlankerClient(struct MsgPort *BlankerClientPort)
  692.  
  693. {
  694.  struct BlankerClientMsg BlankerClientMsg;
  695.  
  696.  BlankerClientMsg.bcm_Message.mn_ReplyPort=FINDPROCPORT;
  697.  PutMsg (BlankerClientPort,(struct Message *)&BlankerClientMsg);
  698.  
  699.  (void)SetTaskPri(BlankerClientPort->mp_SigTask,SERVER_PRI+1L);
  700.  
  701.  (void)WaitPort(BlankerClientMsg.bcm_Message.mn_ReplyPort);
  702.  (void)GetMsg(BlankerClientMsg.bcm_Message.mn_ReplyPort);
  703. }
  704.  
  705. struct MsgPort *REGARGS CreateBlankerClient(void *CodePtr,struct BlankerClientMsg *BlankerClientMsg)
  706.  
  707. {
  708.  struct TagItem ProcTags[3];
  709.  struct Process *BlankerClientProcess;
  710.  
  711.  ProcTags[0].ti_Tag=NP_Entry;
  712.  ProcTags[0].ti_Data=(ULONG)CodePtr;
  713.  ProcTags[1].ti_Tag=NP_Name;
  714.  ProcTags[1].ti_Data=(ULONG)"BlankerClient";
  715.  ProcTags[2].ti_Tag=TAG_DONE;
  716.  
  717.  if (BlankerClientProcess=CreateNewProc(ProcTags))
  718.   {
  719.    BlankerClientMsg->bcm_Message.mn_ReplyPort=FINDPROCPORT;
  720.    PutMsg (&BlankerClientProcess->pr_MsgPort,(struct Message *)BlankerClientMsg);
  721.  
  722.    (void)WaitPort(BlankerClientMsg->bcm_Message.mn_ReplyPort);
  723.    (void)GetMsg(BlankerClientMsg->bcm_Message.mn_ReplyPort);
  724.  
  725.    (void)SetTaskPri((struct Task *)BlankerClientProcess,CLIENT_PRI);
  726.  
  727.    if (BlankerClientMsg->bcm_Status) return &BlankerClientProcess->pr_MsgPort;
  728.   }
  729.  return NULL;
  730. }
  731.  
  732. /*
  733.  
  734.    Functions for Creating/Drawing/Removing the Swarms
  735.  
  736. */
  737.  
  738. /* Ill's strange and genius Random Function :-) */
  739.  
  740. WORD REGARGS Random(WORD Max)
  741.  
  742. {
  743.  static ULONG Num=0L; /* So the last random-number is still stored ! */
  744.  ULONG Sec,Mic;
  745.  
  746.  CurrentTime((LONG *)&Sec,(LONG *)&Mic);
  747.  
  748.  Num*=Sec;
  749.  Num+=Mic;
  750.  
  751.  while (Num>32767L) Num=Num>>1;
  752.  
  753.  return (WORD)Num%Max;
  754. }
  755.  
  756. ULONG SwarmSize(LONG NumWaps,LONG NumBees)
  757.  
  758. {
  759.  return sizeof(struct SwarmStruct)+sizeof(WORD)*((ULONG)NumWaps*8L+(ULONG)NumBees*9L);
  760. }
  761.  
  762. struct SwarmStruct *REGARGS CreateSwarms(struct Screen *SwarmScreen,LONG NumWasps,LONG NumBees)
  763.  
  764. /* allocate Memory and initialize the Swarm(s) */
  765.  
  766. {
  767.  LONG Index;
  768.  struct SwarmStruct *SP;
  769.  WORD *Ptr;
  770.  
  771.  if ((SP=AllocMem(SwarmSize(NumWasps,NumBees),0L))==NULL) return NULL;
  772.  
  773.  SP->ss_NumWasps=NumWasps;
  774.  SP->ss_NumBees=NumBees;
  775.  SP->ss_Width=SwarmScreen->Width;
  776.  SP->ss_Height=SwarmScreen->Height;
  777.  
  778.  Ptr=(WORD *)&SP[1];
  779.  for (Index=0L; Index<4L; Index++)
  780.   {
  781.    SP->ss_WX[Index]=Ptr;
  782.    Ptr+=NumWasps;
  783.    SP->ss_WY[Index]=Ptr;
  784.    Ptr+=NumWasps;
  785.    SP->ss_X[Index]=Ptr;
  786.    Ptr+=NumBees;
  787.    SP->ss_Y[Index]=Ptr;
  788.    Ptr+=NumBees;
  789.   }
  790.  SP->ss_MW=Ptr;
  791.  
  792.  /* Wasps */
  793.  for (Index=0L; Index<NumWasps; Index++)
  794.   {
  795.    WaspX(1,Index)=WaspX(0,Index)=BORDER+Random(SP->ss_Width-2*BORDER);
  796.    WaspY(1,Index)=WaspY(0,Index)=BORDER+Random(SP->ss_Height-2*BORDER);
  797.    WaXVel(Index)=RAND(WASPACC);
  798.    WaYVel(Index)=RAND(WASPACC);
  799.   }
  800.  
  801.  /* Bees */
  802.  for (Index=0L; Index<SP->ss_NumBees; Index++)
  803.   {
  804.    BeeX(1,Index)=BeeX(0,Index)=BORDER+Random(SP->ss_Width-2*BORDER);
  805.    BeeY(1,Index)=BeeY(0,Index)=BORDER+Random(SP->ss_Height-2*BORDER);
  806.    BXVel(Index)=RAND(BEEACC);
  807.    BYVel(Index)=RAND(BEEACC);
  808.    MyWasp(Index)=Index%SP->ss_NumWasps;
  809.   }
  810.  
  811.  return SP;
  812. }
  813.  
  814. /* move Swarms and redraw it */
  815.  
  816. void REGARGS DrawSwarms(struct SwarmStruct *SP,LONG Aim,
  817.                         struct RastPort *WaspRP,struct RastPort *BeeRP)
  818.  
  819. {
  820.  LONG Index;
  821.  
  822.  /* Wasps */
  823.  
  824.  for (Index=0L; Index<SP->ss_NumWasps; Index++)
  825.   {
  826.    WaspX(2,Index)=WaspX(1,Index);
  827.    WaspX(1,Index)=WaspX(0,Index);
  828.    WaspY(2,Index)=WaspY(1,Index);
  829.    WaspY(1,Index)=WaspY(0,Index);
  830.  
  831.    WaXVel(Index)+=RAND(WASPACC);
  832.    WaYVel(Index)+=RAND(WASPACC);
  833.  
  834.    if (WaXVel(Index)>WASPVEL) WaXVel(Index)=WASPVEL;
  835.    if (WaXVel(Index)<-WASPVEL) WaXVel(Index)=-WASPVEL;
  836.    if (WaYVel(Index)>WASPVEL) WaYVel(Index)=WASPVEL;
  837.    if (WaYVel(Index)<-WASPVEL) WaYVel(Index)=-WASPVEL;
  838.  
  839.    WaspX(0,Index)=WaspX(1,Index)+WaXVel(Index);
  840.    WaspY(0,Index)=WaspY(1,Index)+WaYVel(Index);
  841.  
  842.    /* Bounce check */
  843.  
  844.    if ((WaspX(0,Index)<BORDER)||(WaspX(0,Index)>SP->ss_Width-BORDER-1))
  845.     {
  846.      WaXVel(Index)=-WaXVel(Index);
  847.      if (WaspX(0,Index)<BORDER) WaspX(0,Index)=BORDER;
  848.      else WaspX(0,Index)=SP->ss_Width-BORDER-1;
  849.     }
  850.    if ((WaspY(0,Index)<BORDER)||(WaspY(0,Index)>SP->ss_Height-BORDER-1))
  851.     {
  852.      WaYVel(Index)=-WaYVel(Index);
  853.      if (WaspY(0,Index)<BORDER) WaspY(0,Index)=BORDER;
  854.      else WaspY(0,Index)=SP->ss_Height-BORDER-1;
  855.     }
  856.   }
  857.  
  858.  /* just a little more random Movements */
  859.  
  860.  BXVel(Random(SP->ss_NumBees))+=RAND(BEEACC);
  861.  BYVel(Random(SP->ss_NumBees))+=RAND(BEEACC);
  862.  
  863.  /* Bees */
  864.  
  865.  for (Index=0L; Index<SP->ss_NumBees; Index++)
  866.   {
  867.    WORD Distance,DX,DY,Min;
  868.    LONG WaspIndex;
  869.  
  870.    BeeX(2,Index)=BeeX(1,Index);
  871.    BeeX(1,Index)=BeeX(0,Index);
  872.    BeeY(2,Index)=BeeY(1,Index);
  873.    BeeY(1,Index)=BeeY(0,Index);
  874.  
  875.    if (Aim) /* Look out for the nearest wasp if Aim-Mode is on */
  876.     for(WaspIndex=0L, Min=32767; WaspIndex<=SP->ss_NumWasps; WaspIndex++)
  877.      {
  878.       DX=WaspX(1,WaspIndex)-BeeX(1,Index);
  879.       DY=WaspY(1,WaspIndex)-BeeY(1,Index);
  880.       Distance=(ABS(DX)+ABS(DY))/2;        /* Easy Distance check */
  881.       if (Min>Distance)
  882.        {
  883.         Min=Distance;
  884.         MyWasp(Index)=WaspIndex;           /* Mark a nearer Wasp */
  885.        }
  886.      }
  887.  
  888.    DX=WaspX(1,MyWasp(Index))-BeeX(1,Index);
  889.    DY=WaspY(1,MyWasp(Index))-BeeY(1,Index);
  890.    Distance=(ABS(DX)+ABS(DY))/2;
  891.    if (Distance==0) Distance=1;
  892.  
  893.    BXVel(Index)+=(DX*BEEACC)/Distance;
  894.    BYVel(Index)+=(DY*BEEACC)/Distance;
  895.  
  896.    if (BXVel(Index)>BEEVEL)  BXVel(Index)=BEEVEL;
  897.    if (BXVel(Index)<-BEEVEL) BXVel(Index)=-BEEVEL;
  898.    if (BYVel(Index)>BEEVEL)  BYVel(Index)=BEEVEL;
  899.    if (BYVel(Index)<-BEEVEL) BYVel(Index)=-BEEVEL;
  900.  
  901.    BeeX(0,Index)=BeeX(1,Index)+BXVel(Index);
  902.    BeeY(0,Index)=BeeY(1,Index)+BYVel(Index);
  903.  
  904.    /* Bounce check */
  905.  
  906.    if ((BeeX(0,Index)<BORDER)||(BeeX(0,Index)>(SP->ss_Width-BORDER-1)))
  907.     {
  908.      BXVel(Index)=-BXVel(Index);
  909.      BeeX(0,Index)=BeeX(1,Index)+BXVel(Index);
  910.     }
  911.    if ((BeeY(0,Index)<BORDER)||(BeeY(0,Index)>(SP->ss_Height-BORDER-1)))
  912.     {
  913.      BYVel(Index)=-BYVel(Index);
  914.      BeeY(0,Index)=BeeY(1,Index)+BYVel(Index);
  915.     }
  916.   }
  917.  
  918.  /* Move our insects */
  919.  
  920.  for(Index=0L; Index<SP->ss_NumWasps; Index++)    /* Wasps */
  921.   {
  922.    SetAPen (WaspRP,0);
  923.    Move (WaspRP,WaspX(2,Index),WaspY(2,Index));
  924.    Draw (WaspRP,WaspX(1,Index),WaspY(1,Index));
  925.    SetAPen (WaspRP,1);
  926.    Draw (WaspRP,WaspX(0,Index),WaspY(0,Index));
  927.   }
  928.  
  929.  for (Index=0L; Index<SP->ss_NumBees; Index++)   /* Bees  */
  930.   {
  931.    SetAPen (BeeRP,0);
  932.    Move (BeeRP,BeeX(2,Index),BeeY(2,Index));
  933.    Draw (BeeRP,BeeX(1,Index),BeeY(1,Index));
  934.    SetAPen (BeeRP,1);
  935.    Draw (BeeRP,BeeX(0,Index),BeeY(0,Index));
  936.   }
  937. }
  938.  
  939. /*
  940.  
  941.    This is the Client Process's Main Loop
  942.  
  943. */
  944.  
  945. VOID_INTERRUPT ASwarmClientProcess(void)
  946.  
  947. {
  948.  struct BlankerClientMsg *BlankerClientMsg;
  949.  struct MsgPort *BlankerClientPort;
  950.  struct Task *BlankerServerTask;
  951.  ULONG BlankerServerSigMask;
  952.  struct Screen *SwarmScreen;
  953.  LONG Index,NumWasps,NumBees,Speed,Cycle,Aim,Count;
  954.  struct SwarmStruct *Swarms;
  955.  WORD Color,DColor;
  956.  static struct RastPort RastPorts[2];
  957.  static struct BitMap BitMaps[2];
  958.  
  959.  /* wait for Server's initial Message */
  960.  
  961.  BlankerClientPort=FINDPROCPORT;
  962.  (void)WaitPort(BlankerClientPort);
  963.  BlankerClientMsg=(struct BlankerClientMsg *)GetMsg(BlankerClientPort);
  964.  
  965.  BlankerServerTask=BlankerClientMsg->bcm_Message.mn_ReplyPort->mp_SigTask;
  966.  BlankerServerSigMask=BlankerClientMsg->bcm_SigMask;
  967.  
  968.  NumWasps=BlankerClientMsg->bcm_Wasps;
  969.  NumBees=BlankerClientMsg->bcm_Bees;
  970.  SwarmScreen=BlankerClientMsg->bcm_Screen;
  971.  Speed=BlankerClientMsg->bcm_Speed;
  972.  Cycle=BlankerClientMsg->bcm_Cycle;
  973.  Aim=BlankerClientMsg->bcm_Aim;
  974.  
  975.  /* initialize requested Number of Swarms */
  976.  
  977.  if ((Swarms=CreateSwarms(SwarmScreen,NumWasps,NumBees))==NULL)
  978.   {
  979.    BlankerClientMsg->bcm_Status=FALSE;
  980.    Forbid();
  981.    ReplyMsg ((struct Message *)BlankerClientMsg);
  982.    return;
  983.   }
  984.  BlankerClientMsg->bcm_Status=TRUE;
  985.  ReplyMsg ((struct Message *)BlankerClientMsg);
  986.  
  987.  /* Here we do a little trick:
  988.     We create two RastPorts - one for the Wasp(s), one for the Bees - with one
  989.     BitPlane. So we have only to draw in one BitPlane and are able to do it faster. */
  990.  
  991.  for (Index=0L; Index<2L; Index++)
  992.   {
  993.    InitRastPort (&RastPorts[Index]);
  994.    RastPorts[Index].BitMap=&BitMaps[Index];
  995.    SetDrMd (&RastPorts[Index],JAM1);
  996.    InitBitMap (&BitMaps[Index],1L,SwarmScreen->Width,SwarmScreen->Height);
  997.    BitMaps[Index].Planes[0]=SwarmScreen->BitMap.Planes[Index];
  998.   }
  999.  
  1000.  Color=BEE_COL_NUM-1;
  1001.  DColor=Cycle?1:0;
  1002.  Count=Speed;
  1003.  
  1004.  while ((BlankerClientMsg=(struct BlankerClientMsg *)GetMsg(BlankerClientPort))==NULL)
  1005.   {
  1006.    /* Color Cycling */
  1007.  
  1008.    SwarmColors[2]=BeeColors[Color];
  1009.    LoadRGB4 (&SwarmScreen->ViewPort,SwarmColors,4);
  1010.    Color+=DColor;
  1011.    if ((Color==-1)||(Color==BEE_COL_NUM))
  1012.     {
  1013.      DColor=-DColor;
  1014.      Color+=2*DColor;
  1015.     }
  1016.  
  1017.    /* Synchronisation */
  1018.  
  1019.    WaitTOF();
  1020.    if (Count<MAX_SPEED)
  1021.     {
  1022.      Count++;
  1023.      continue;
  1024.     }
  1025.    Count=Speed;
  1026.  
  1027.    /* Move the Swarm(s) */
  1028.  
  1029.    DrawSwarms (Swarms,Aim,&RastPorts[0],&RastPorts[1]);
  1030.    Signal (BlankerServerTask,BlankerServerSigMask);
  1031.   }
  1032.  FreeMem (Swarms,SwarmSize(NumWasps,NumBees));
  1033.  
  1034.  /* We are requested to finish, so we do. */
  1035.  
  1036.  ReplyMsg ((struct Message *)BlankerClientMsg);
  1037. }
  1038.  
  1039. /*
  1040.  
  1041.    The Main Loop
  1042.  
  1043. */
  1044.  
  1045. void main(LONG argc,UBYTE **argv)
  1046.  
  1047. {
  1048.  char **ToolTypes;
  1049.  CxObj *Broker,*ObjectList,*Filter;
  1050.  struct IntuiMessage *IntMsg;
  1051.  CxMsg *BlankerCxMsg;
  1052.  LONG ThisTimeOut,TimeUntilBlank,TimeUntilBlack;
  1053.  struct Screen *BlankerScreen=NULL;
  1054.  struct BlankerClientPort *BlankerClientPort=NULL;
  1055.  
  1056.  /* open our Libraries */
  1057.  
  1058.  AddTool (GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L),
  1059.           CloseLibrary,0L);
  1060.  AddTool (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37L),
  1061.           CloseLibrary,0L);
  1062.  AddTool (IconBase=OpenLibrary("icon.library",37L),CloseLibrary,0L);
  1063.  AddTool (CxBase=OpenLibrary("commodities.library",37L),CloseLibrary,0L);
  1064.  AddTool (GadToolsBase=OpenLibrary("gadtools.library",37L),CloseLibrary,0L);
  1065.  
  1066.  /* create List of Graphics Modes */
  1067.  
  1068.  AddTool (ModeList=CreateModeList(),DeleteModeList,0L);
  1069.  
  1070.  /* get our Arguments */
  1071.  
  1072.  if (ToolTypes=ArgArrayInit(argc,argv)) AddTool (ToolTypes,ArgArrayDone,0L);
  1073.  
  1074.  /* get some Signals */
  1075.  
  1076.  BlankerServerProcess=SysBase->ThisTask;
  1077.  if ((bsp_TimerSig=AllocSignal(-1L))==-1) Quit (10);
  1078.  AddTool ((void *)bsp_TimerSig,FreeSignal,0L);
  1079.  if ((bsp_InputSig=AllocSignal(-1L))==-1) Quit (10);
  1080.  AddTool ((void *)bsp_InputSig,FreeSignal,0L);
  1081.  if ((bsp_ClientSig=AllocSignal(-1L))==-1) Quit (10);
  1082.  AddTool ((void *)bsp_ClientSig,FreeSignal,0L);
  1083.  
  1084.  /* initialize our Broker=install us as a Commodity */
  1085.  
  1086.  AddTool (CxPort=CreateMsgPort(),DeleteMsgPortSafely,0L);
  1087.  
  1088.  NewBroker.nb_Pri=ArgInt(ToolTypes,"CX_PRIORITY",DEF_CX_PRI);
  1089.  NewBroker.nb_Port=CxPort;
  1090.  AddTool (Broker=CxBroker(&NewBroker,NULL),DeleteCxObjAll,0L);
  1091.  
  1092.  /* get Time Out, Client Time Out and Display mode */
  1093.  
  1094.  TimeOut=ArgIntMax(ToolTypes,"TIMEOUT",DEF_TIMEOUT,MAX_TIMEOUT);
  1095.  ClientTimeOut=ArgIntMax(ToolTypes,"CLIENTTIMEOUT",DEF_CLIENT_TIMEOUT,MAX_CLIENT_TIMEOUT);
  1096.  if ((DisplayMode=FindMode(ModeList,ArgString(ToolTypes,"DISPLAY","")))==NULL)
  1097.   DisplayMode=GetDefaultMode(ModeList);
  1098.  
  1099.  /* gete some Global Flags */
  1100.  
  1101.  Cycle=ArgBoolean(ToolTypes,"CYCLE",TRUE);
  1102.  Aim=ArgBoolean(ToolTypes,"AIM",FALSE);
  1103.  
  1104.  /* get Parameters for Swarm Movement */
  1105.  
  1106.  NumWasps=ArgIntMax(ToolTypes,"WASPS",DEF_WASPS,MAX_WASPS);
  1107.  NumBees=ArgIntMax(ToolTypes,"BEES",DEF_BEES,MAX_BEES);
  1108.  Speed=ArgIntMax(ToolTypes,"SPEED",DEF_SPEED,MAX_SPEED);
  1109.  
  1110.  /* install our Hot Key */
  1111.  
  1112.  PopKey=ArgString(ToolTypes,"CX_POPKEY",DEF_POPKEY);
  1113.  if (Filter=HotKey(PopKey,CxPort,EVENT_OPEN_WINDOW))
  1114.   if (CxObjError(Filter)==0L) AttachCxObj(Broker,Filter);
  1115.   else
  1116.    {
  1117.     DeleteCxObj (Filter);
  1118.     Filter=NULL;
  1119.    }
  1120.  if (Filter==NULL) PopKey="<NONE>";
  1121.  
  1122.  /* install our "InputHandler" */
  1123.  
  1124.  ObjectList=CxCustom(BlankerAction,0L);
  1125.  AttachCxObj (Broker,ObjectList);
  1126.  if (CxObjError(ObjectList)) Quit (10);
  1127.  
  1128.  (void)ActivateCxObj(Broker,TRUE);
  1129.  AddTool (Broker,ActivateCxObj,FALSE);
  1130.  
  1131.  /* open Window on startup if not forbidden */
  1132.  
  1133.  if (ArgBoolean(ToolTypes,"CX_POPUP",TRUE)) OpenBlankerWindow();
  1134.  
  1135.  /* increase our Priority */
  1136.  
  1137.  AddTool (FindTask(NULL),SetTaskPri,(LONG)SetTaskPri(FindTask(NULL),SERVER_PRI));
  1138.  
  1139.  /* start the Loop */
  1140.  
  1141.  TimeUntilBlank=ThisTimeOut=10L*TimeOut;
  1142.  TimeUntilBlack=10L*ClientTimeOut;
  1143.  FOREVER
  1144.   {
  1145.    ULONG Mask;
  1146.  
  1147.    if (BlankerWindow)
  1148.     Mask=Wait(MASK(bsp_TimerSig)|MASK(bsp_InputSig)|MASK(bsp_ClientSig)|
  1149.               MASK(CxPort->mp_SigBit)|MASK(BlankerWindow->UserPort->mp_SigBit)|
  1150.               SIGBREAKF_CTRL_C);
  1151.    else
  1152.     Mask=Wait(MASK(bsp_TimerSig)|MASK(bsp_InputSig)|MASK(bsp_ClientSig)|
  1153.               MASK(CxPort->mp_SigBit)|SIGBREAKF_CTRL_C);
  1154.  
  1155.    /* process Window Events */
  1156.  
  1157.    while ((BlankerWindow!=NULL)&&(IntMsg=GT_GetIMsg(BlankerWindow->UserPort)))
  1158.     switch (IntMsg->Class)
  1159.      {
  1160.       struct Gadget *Clicked;
  1161.       UWORD Code;
  1162.  
  1163.       case IDCMP_CLOSEWINDOW:
  1164.        GT_ReplyIMsg (IntMsg);
  1165.        CloseBlankerWindow();
  1166.        break;
  1167.       case IDCMP_REFRESHWINDOW:
  1168.        GT_BeginRefresh (BlankerWindow);
  1169.        GT_EndRefresh (BlankerWindow,TRUE);
  1170.        break;
  1171.       case IDCMP_GADGETUP:
  1172.        Code=IntMsg->Code;
  1173.        Clicked=(struct Gadget *)IntMsg->IAddress;
  1174.        GT_ReplyIMsg (IntMsg);
  1175.        switch (Clicked->GadgetID)
  1176.         {
  1177.          case GID_HIDE:
  1178.           CloseBlankerWindow();
  1179.           break;
  1180.          case GID_QUIT:
  1181.           Quit (0);
  1182.          case GID_BLANK:
  1183.           if (TimeUntilBlank) TimeUntilBlank=ThisTimeOut=2L;
  1184.           break;
  1185.          case GID_MODE:
  1186.           DisplayMode=GetIndexMode(ModeList,Code);
  1187.           break;
  1188.          case GID_TIMEOUT:
  1189.           if (GetNum(Clicked,&TimeOut,MAX_TIMEOUT)) TimeUntilBlank=ThisTimeOut=10L*TimeOut;
  1190.           break;
  1191.          case GID_CLIENT:
  1192.           if (GetNum(Clicked,&ClientTimeOut,MAX_CLIENT_TIMEOUT)) TimeUntilBlack=10L*ClientTimeOut;
  1193.           break;
  1194.          case GID_SPEED:
  1195.           (void)GetNum(Clicked,&Speed,MAX_SPEED);
  1196.           break;
  1197.          case GID_WASPS:
  1198.           (void)GetNum(Clicked,&NumWasps,MAX_WASPS);
  1199.           break;
  1200.          case GID_BEES:
  1201.           (void)GetNum(Clicked,&NumBees,MAX_BEES);
  1202.           break;
  1203.          case GID_CYCLE:
  1204.           Cycle=!Cycle;
  1205.           break;
  1206.          case GID_AIM:
  1207.           Aim=!Aim;
  1208.         }
  1209.        break;
  1210.       case IDCMP_VANILLAKEY:
  1211.        Code=IntMsg->Code;
  1212.        GT_ReplyIMsg (IntMsg);
  1213.        switch ((char)Code)
  1214.         {
  1215.          case 'H':
  1216.          case 'h':
  1217.           CloseBlankerWindow();
  1218.           break;
  1219.          case 'Q':
  1220.          case 'q':
  1221.           Quit (0);
  1222.          case 'B':
  1223.          case 'b':
  1224.           if (TimeUntilBlank) TimeUntilBlank=ThisTimeOut=2L;
  1225.         }
  1226.        break;
  1227.       default:
  1228.        GT_ReplyIMsg (IntMsg);
  1229.      }
  1230.  
  1231.    /* process Commodity Messages */
  1232.  
  1233.    while (BlankerCxMsg=(CxMsg *)GetMsg(CxPort)) HandleCxMsg (Broker,BlankerCxMsg);
  1234.  
  1235.    /* check for <CTRL>-C */
  1236.  
  1237.    if (Mask&SIGBREAKF_CTRL_C) Quit (0);
  1238.  
  1239.    /* Input detected, unblank if necessary */
  1240.  
  1241.    if (Mask&MASK(bsp_InputSig))
  1242.     {
  1243.      if (TimeUntilBlank==0L)
  1244.       {
  1245.        ON_SPRITE
  1246.        if (BlankerClientPort) RemTool (BlankerClientPort);
  1247.        RemTool (BlankerScreen);
  1248.        ThisTimeOut=10L*TimeOut;
  1249.       }
  1250.      TimeUntilBlank=ThisTimeOut;
  1251.     }
  1252.  
  1253.    /* client has confirmed that it is still alive */
  1254.  
  1255.    if (Mask&MASK(bsp_ClientSig))
  1256.     {
  1257.      ON_DISPLAY
  1258.      TimeUntilBlack=10L*ClientTimeOut;
  1259.     }
  1260.  
  1261.    /* 1/10 sec is over */
  1262.  
  1263.    if (Mask&MASK(bsp_TimerSig))
  1264.     if (TimeUntilBlank)
  1265.      {
  1266.       TimeUntilBlank--;
  1267.       if (TimeUntilBlank==0L) /* Time Out reached, blank the screen */
  1268.        {
  1269.         struct BlankerClientMsg BlankerClientMsg;
  1270.  
  1271.         AddTool (BlankerScreen=CreateScreen(ModeList,DisplayMode),CloseScreen,0L);
  1272.         BlankerClientMsg.bcm_Screen=BlankerScreen;
  1273.         BlankerClientMsg.bcm_SigMask=1L<<bsp_ClientSig;
  1274.         BlankerClientMsg.bcm_Wasps=NumWasps;
  1275.         BlankerClientMsg.bcm_Bees=NumBees;
  1276.         BlankerClientMsg.bcm_Speed=Speed;
  1277.         BlankerClientMsg.bcm_Cycle=Cycle;
  1278.         BlankerClientMsg.bcm_Aim=Aim;
  1279.         if (BlankerClientPort=CreateBlankerClient(ASwarmClientProcess,&BlankerClientMsg))
  1280.          {
  1281.           TimeUntilBlack=10L*ClientTimeOut; /* try to start Client */
  1282.           AddTool (BlankerClientPort,DeleteBlankerClient,0L);
  1283.          }
  1284.        }
  1285.      }
  1286.     else
  1287.      {
  1288.       if (IntuitionBase->FirstScreen!=BlankerScreen)
  1289.        {
  1290.         ScreenToFront (BlankerScreen);
  1291.         SpritesOff();
  1292.        }
  1293.       if (TimeUntilBlack)
  1294.        {
  1295.         TimeUntilBlack--;
  1296.         if (TimeUntilBlack==0L) OFF_DISPLAY /* Client Time Out reached, turn entire screen black */
  1297.        }
  1298.      }
  1299.   }
  1300. }
  1301.