home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 607.lha / ASwarmII_v1.0 / ASwarm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-05  |  29.1 KB  |  1,205 lines

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