home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 634.lha / ASwarm_III / ASwarm3.c < prev    next >
C/C++ Source or Header  |  1992-03-03  |  34KB  |  1,344 lines

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