home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 510.lha / NewPop_v4.0 / NewPop.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-07  |  36.5 KB  |  1,411 lines

  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  2. /* |_o_o|\\ Copyright (c) 1986 The Software Distillery.  All Rights Reserved */
  3. /* |. o.| || This program may not be distributed without the permission of   */
  4. /* | .  | || the authors.                                                    */
  5. /* | o  | ||    Dave Baker     Ed Burnette  Stan Chow    Jay Denebeim        */
  6. /* |  . |//     Gordon Keener  Jack Rouse   John Toebes  Doug Walker         */
  7. /* ======          BBS:(919)-471-6436      VOICE:(919)-469-4210              */
  8. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  9.  
  10. /*
  11.  * VERY loosely based on the input.device example by Rob Peck, 12/1/85
  12.  *
  13.  *
  14.  * Additions and modifications Copyright (c) 1989, 1990, 1991 Loren J. Rittle
  15.  * Modifications Copyright (c) 1990 Ed A. Hutchins and Loren J. Rittle
  16.  *
  17.  * As stated in the original POPCLI documentation file:
  18.  *
  19.  * Permission is hereby granted to distribute this program provided
  20.  * both the documentation accompanies the executable and that no
  21.  * charge is made for its distribution.
  22.  * I assume that this statement includes the right to modify the source
  23.  * and futher distribute the modified work under this same agreement. - LJR
  24.  * (Actually, at this point, 'diff newpop.c popcli3.c | wc'
  25.  * > 'wc -c newpop.c' + 'wc -c popcli3.c'. :-)
  26.  *
  27.  *
  28.  *    Note:    Some code to do the Q*X pattern lifted (and modified) from:
  29.  *         Line drawing demo for the Commodore/Amiga
  30.  *         Written by John Riley, Lattice, Inc.
  31.  *
  32.  *    Note:   The spawning of a lower priority task to do graphics
  33.  *        was inspired by Mackie to some degree (and by
  34.  *        one person who claimed that NewPop slowed down
  35.  *        HST modem transfers! I think that they were
  36.  *        on a non-A3000 class machine :-)  Later, I got
  37.  *        a report that it also happened on an A3000! :-(
  38.  *        See NICENEWPOP in `[s:].newpoprc'.
  39.  *
  40.  *    UpfrontLayer is used instead of WindowToFront() because of
  41.  *    a WorkBench/INTUITION bug. From dmouse.doc:
  42.  *
  43.  *    WORKBENCH USERS!!!!!!!!!! There appears to be a bug in
  44.  *    intuition's WindowToFront() call, which can lock up
  45.  *     intuition when workbench icons are active.  Under the
  46.  *    defaults, this will occur whenever you depress the left
  47.  *     mouse button over an icon.
  48.  *
  49.  *     Thanks to Matt Dillon for showing the work around
  50.  *     in DMouse's source code.
  51.  *
  52.  *    See ChangeLog for the record of changes.
  53.  *
  54.  *    Loren J. Rittle
  55.  *    l-rittle@uiuc.edu
  56.  */
  57.  
  58.  
  59. /* * * * * * * * * * * INCLUDES * * * * * * * * * * * * */
  60. #include <exec/exec.h>
  61. #include <dos/dos.h>
  62. #include <dos/dostags.h>
  63. #include <devices/timer.h>
  64. #include <devices/input.h>
  65. #include <devices/inputevent.h>
  66. #include <intuition/intuitionbase.h>
  67. #include <graphics/gfxmacros.h>
  68. #include <graphics/layers.h>
  69. #include <graphics/gfxbase.h>
  70. #include <graphics/text.h>
  71. // Kludge! There is no prototype for GetString in reqbase.h!
  72. int GetString (char *, char *, struct Window *, int, int);
  73. #include <proto/req.h>
  74. // Kludge! There is no pramga for System!
  75. #define System xxxxxx
  76. #include <proto/dos.h>
  77. #undef System
  78. LONG __stdargs System( UBYTE *command, struct TagItem *tags );
  79. // end Kludge!
  80. #include <proto/exec.h>
  81. #include <proto/layers.h>
  82. #include <proto/intuition.h>
  83. #include <proto/graphics.h>
  84. #include <proto/diskfont.h>
  85. #include <string.h>
  86. #include <time.h>
  87. #include <math.h>
  88. #include <stdio.h>
  89.  
  90.  
  91. /* * * * * * * * * * * CONSTANTS * * * * * * * * * * * * */
  92. #define PORTNAME     "NewPop.port"
  93.  /* The name of our well known *PRIVATE* message port */
  94.  
  95. #define MAXCMD        200
  96. #define MAXTASKNAME    32
  97. #define MAXFONTNAME    32
  98. #define MAXPASSWORD    32
  99.  /* Maximum string size of various things */
  100.  
  101. #define BANNER \
  102. "\x9B" "0;33mNewPop\x9B" \
  103. "0m v4.0 by Loren J. Rittle - Copyright \xA9 1989 - 1991 Based upon:\n" \
  104. "\x9B" "0;33mPOPCLI III\x9B" \
  105. "0m by John Toebes - Copyright \xA9 1987 The Software Distillery\n"
  106.  /* The hello banner */
  107.  
  108. #define ALREADYHEREMESSAGE \
  109. "NewPop is already running, you should use `break [cli number of NewPop]'\n" \
  110. "to kill it before starting another.\n"
  111.  /* The already here message :-) */
  112.  
  113.  
  114. /* * * * * * * * * * * * * * * * TYPES * * * * * * * * * * * * * */
  115. struct color
  116. {
  117.   int red, green, blue;
  118. };
  119.  
  120. enum OptionTypes
  121. {
  122.   boolean, integer, string
  123. };
  124.  
  125. struct NewPopOption
  126. {
  127.   char *name;
  128.   enum OptionTypes type;
  129.   union
  130.   {
  131.     int ivalue;
  132.     char *svalue;
  133.   } value;
  134.   int min, max;
  135. };
  136.  
  137.  
  138. /* * * * * * * * * * * EXTERNALS AND GLOBAL DATA * * * * * * * * */
  139. char FontName[MAXFONTNAME] = "Helvetica.font";
  140. char TaskName[MAXTASKNAME] = "gvpscsi.device";
  141. #ifndef LJR_FAVORITE
  142. char Cmd[MAXCMD] = "NEWCLI >NIL:";
  143. #else
  144. char Cmd[MAXCMD] = "NewWSH <nil: >nil: cnn:0/11/640/189/WShell/c";
  145. #endif
  146. char PassWord[MAXPASSWORD] = "Amiga";
  147.  
  148. /*
  149.  *  See .newpoprc for the meanings of these options!
  150.  */
  151. struct NewPopOption NewPopOptions[] =
  152. {
  153. #define NICENEWPOP (NewPopOptions[0].value.ivalue)
  154.   {"NICENEWPOP", boolean, 1, 0, 1},
  155. #define NEWPOPLITE (NewPopOptions[1].value.ivalue)
  156.   {"NEWPOPLITE", boolean, 0, 0, 1},
  157. #define WEWANTWINDOWDRAG (NewPopOptions[2].value.ivalue)
  158.   {"WEWANTWINDOWDRAG", boolean, 0, 0, 1},
  159. #define SCSITASKNAME (NewPopOptions[3].value.svalue)
  160.   {"SCSITASKNAME", string, (int) TaskName, 0, MAXTASKNAME},
  161. #define FONTNAME (NewPopOptions[4].value.svalue)
  162.   {"FONTNAME", string, (int) FontName, 0, MAXFONTNAME},
  163. #define COMMAND (NewPopOptions[5].value.svalue)
  164.   {"COMMAND", string, (int) Cmd, 0, MAXCMD},
  165. #define MAXSCSIUSAGE (NewPopOptions[6].value.ivalue)
  166.   {"MAXSCSIUSAGE", integer, 55, 20, 255},
  167. #define SCSIIOMONWIDTH (NewPopOptions[7].value.ivalue)
  168.   {"SCSIIOMONWIDTH", integer, 100, 0, 1024},
  169. #define CPULOADMONWIDTH (NewPopOptions[8].value.ivalue)
  170.   {"CPULOADMONWIDTH", integer, 100, 0, 1024},
  171. #define GAPBETWEEN2 (NewPopOptions[9].value.ivalue)
  172.   {"GAPBETWEEN2", integer, 16, 0, 256},
  173. #define GAPBETWEEN (NewPopOptions[10].value.ivalue)
  174.   {"GAPBETWEEN", integer, 16, 0, 256},
  175. #define FONTSIZE (NewPopOptions[11].value.ivalue)
  176.   {"FONTSIZE", integer, 9, 4, 56},
  177. #define STARTYOFFSET (NewPopOptions[12].value.ivalue)
  178.   {"STARTYOFFSET", integer, 7, 2, 60},
  179. #define MAXTEXTWIDTH (NewPopOptions[13].value.ivalue)
  180.   {"MAXTEXTWIDTH", integer, 107, 10, 1024},
  181. #define STARTXOFFSET (NewPopOptions[14].value.ivalue)
  182.   {"STARTXOFFSET", integer, 56, 10, 200},
  183. #define WINDOWHEIGHT (NewPopOptions[15].value.ivalue)
  184.   {"WINDOWHEIGHT", integer, 8, 4, 56},
  185. #define TIMEOUT (NewPopOptions[16].value.ivalue)
  186.   {"TIMEOUT", integer, 180, 0, 0x00ffffff},
  187. #define POPKEY (NewPopOptions[17].value.ivalue)
  188.   {"POPKEY", integer, 69, 0, 255},
  189. #define BLANKERPRIORITY (NewPopOptions[18].value.ivalue)
  190.   {"BLANKERPRIORITY", integer, -20, -20, 10},
  191. #define ULC (NewPopOptions[19].value.ivalue)
  192.   {"ULC", integer, 0, 0, 2},
  193. #define URC (NewPopOptions[20].value.ivalue)
  194.   {"URC", integer, 1, 0, 2},
  195. #define LLC (NewPopOptions[21].value.ivalue)
  196.   {"LLC", integer, 0, 0, 2},
  197. #define LRC (NewPopOptions[22].value.ivalue)
  198.   {"LRC", integer, 2, 0, 2},
  199. #define INSTANTKEY (NewPopOptions[23].value.ivalue)
  200.   {"INSTANTKEY", integer, 0, 0, 255},
  201. #define DEFEATKEY (NewPopOptions[24].value.ivalue)
  202.   {"DEFEATKEY", integer, 0, 0, 255},
  203. #define LOCK (NewPopOptions[25].value.ivalue)
  204.   {"LOCK", boolean, 0, 0, 1},
  205. #define PASSWORD (NewPopOptions[26].value.svalue)
  206.   {"PASSWORD", string, (int) PassWord, 0, MAXPASSWORD},
  207. #define MEMORYMONWIDTH (NewPopOptions[27].value.ivalue)
  208.   {"MEMORYMONWIDTH", integer, 0, 0, 1024},
  209. #define GAPBETWEEN3 (NewPopOptions[28].value.ivalue)
  210.   {"GAPBETWEEN3", integer, 0, 0, 256},
  211. #define BACKDROPWINDOW (NewPopOptions[29].value.ivalue)
  212.   {"BACKDROPWINDOW", boolean, 1, 0, 1},
  213. #define WIMPYCLOCK (NewPopOptions[30].value.ivalue)
  214.   {"WIMPYCLOCK", boolean, 0, 0, 1},
  215. /* Add new enties before this line! */
  216.   {NULL, boolean, 0, 0, 0}
  217. };
  218.  
  219. struct IntuitionBase *IntuitionBase;
  220. struct LayersBase *LayersBase;
  221. struct GfxBase *GfxBase;
  222. struct DiskfontBase *DiskfontBase;
  223. struct DosLibrary *DosBase;
  224. struct ExecBase *ExecBase;
  225. struct ReqLib *ReqBase;
  226.  
  227. struct NewScreen NewScreen =
  228. {0, 0, 640, 400, 1, 0, 1, HIRES | LACE, SCREENBEHIND | SCREENQUIET | CUSTOMSCREEN, NULL, NULL, NULL, NULL};
  229.  
  230. struct NewWindow NewBlankerWindow =
  231. {0, 0, 640, 400, -1, -1, 0, RMBTRAP | BORDERLESS | BACKDROP | SIMPLE_REFRESH | ACTIVATE, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, CUSTOMSCREEN};
  232.  
  233. int WindowWidth, WindowHeight;
  234.  
  235. struct Gadget WDragGadget =
  236. {NULL, 0, 0, 0, 0, GADGHNONE, NULL, WDRAGGING, NULL, NULL, NULL, NULL, NULL, 0, 0};
  237.  
  238. struct NewWindow NewWindow =
  239. {0, 0, 0, 0, 2, 1, 0, BORDERLESS | NOCAREREFRESH, &WDragGadget, NULL, NULL, NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN};
  240.  
  241. struct Task *buddy;
  242. ULONG creatclisig;
  243. ULONG unblanksig;
  244. ULONG mousemovesig;
  245. ULONG noevents;
  246. short creatsignum = -1;
  247. short blanksignum = -1;
  248. short mousemovenum = -1;
  249. struct Screen *blankscreen;
  250. struct Window *blankwindow;
  251. USHORT instantblank, defeatblank;
  252. ULONG scsiDisp;
  253. struct Task *child;
  254. struct Task *securer;
  255. struct ViewPort *blankVP;
  256. struct RastPort *blankRP;
  257. USHORT xlim, ylim;
  258. int maxchip, maxfast;
  259. USHORT StartedFromWB;
  260.  
  261. /* * * * * * * * * * * PROTOTYPES * * * * * * * * * * * * */
  262. struct InputEvent *__saveds __asm myhandler (register __a0 struct InputEvent *);
  263. void createchild (void);
  264. void __saveds blankertask (void);
  265. void killchild (void);
  266. void createsecurer (void);
  267. void __saveds securertask (void);
  268. void killsecurer (void);
  269. void __saveds scsifriendlosing (void);
  270. int ParseConfigFile (void);
  271. void _main (char *);
  272. void changecolor (void);
  273. void updatedisplay (void);
  274. void MemCleanup (void);
  275. void QueueTimer (struct timerequest *, ULONG);
  276.  
  277.  
  278. /* * * * * * * * * * * OUR ROUTINES * * * * * * * * * * * */
  279. struct InputEvent *__saveds __asm 
  280. myhandler (register __a0 struct InputEvent * ev)
  281. {
  282.   struct InputEvent *ep, *laste;
  283.  
  284.   for (ep = ev, laste = NULL; ep != NULL; ep = ep->ie_NextEvent)
  285.     {
  286.       if ((ep->ie_Class == IECLASS_RAWKEY) &&
  287.       (ep->ie_Qualifier & IEQUALIFIER_LCOMMAND))
  288.     {
  289.       if ((ep->ie_Code == POPKEY) && (POPKEY))
  290.         Signal (buddy, creatclisig);
  291.       else if ((ep->ie_Code == DEFEATKEY) && (DEFEATKEY))
  292.         {
  293.           defeatblank = !defeatblank;
  294.           instantblank = 0;
  295.         }
  296.       else if ((ep->ie_Code == INSTANTKEY) && (INSTANTKEY))
  297.         {
  298.           defeatblank = 0;
  299.           instantblank = !instantblank;
  300.         }
  301.       else
  302.         goto nomatch;
  303.       if (laste == NULL)
  304.         ev = ep->ie_NextEvent;
  305.       else
  306.         laste->ie_NextEvent = ep->ie_NextEvent;
  307.     }
  308.       else
  309. nomatch:
  310.     laste = ep;
  311.  
  312.       if (ep->ie_Class == IECLASS_RAWMOUSE)
  313.     Signal (buddy, mousemovesig);
  314.  
  315.       if (ep->ie_Class != IECLASS_TIMER)
  316.     {
  317.       noevents = 0;
  318.       if (blankscreen)
  319.         Signal (buddy, unblanksig);
  320.     }
  321.     }
  322.   return (ev);
  323. }
  324.  
  325. void 
  326. createchild (void)
  327. {
  328.   child = CreateTask ("NewPopBlanker", BLANKERPRIORITY, (APTR) blankertask, 4000L);
  329. }
  330.  
  331. void __saveds 
  332. blankertask (void)
  333. {
  334.   struct MsgPort *timerport2;
  335.   struct timerequest *timerreq2 = NULL;
  336.  
  337.   if (timerport2 = CreatePort ("NewPopTimerPort2", 0))
  338.     if (timerreq2 = (struct timerequest *) CreateExtIO (timerport2, sizeof (struct timerequest)))
  339.       if (!(OpenDevice (TIMERNAME, UNIT_VBLANK, (struct IORequest *) timerreq2, 0)))
  340.     {
  341.       while (!(SetSignal (0L, 0L) & SIGBREAKF_CTRL_C))
  342.         {
  343.           updatedisplay ();
  344.           if (child->tc_Node.ln_Pri == 10)
  345.         SetTaskPri (child, BLANKERPRIORITY);
  346.           timerreq2->tr_node.io_Command = TR_ADDREQUEST;
  347.           timerreq2->tr_time.tv_secs = 0;
  348.           timerreq2->tr_time.tv_micro = 1000000 / 60;
  349.           DoIO ((struct IORequest *) timerreq2);
  350.         }
  351.     }
  352.       else
  353.     Wait (SIGBREAKF_CTRL_C);
  354.   if (timerreq2)
  355.     {
  356.       if (timerreq2->tr_node.io_Device)
  357.     CloseDevice ((struct IORequest *) timerreq2);
  358.       DeleteExtIO ((struct IOStdReq *) timerreq2);
  359.     }
  360.   if (timerport2)
  361.     DeletePort (timerport2);
  362.   Signal (buddy, SIGBREAKF_CTRL_D);
  363.   Wait (0L);
  364. }
  365.  
  366. void 
  367. killchild (void)
  368. {
  369.   Signal (child, SIGBREAKF_CTRL_C);
  370.   SetTaskPri (child, 20L);
  371.   Wait (SIGBREAKF_CTRL_D);
  372.   DeleteTask (child);
  373.   child = NULL;
  374. }
  375.  
  376. void 
  377. createsecurer (void)
  378. {
  379.   securer = CreateTask ("NewPopSecurer", 19, (APTR) securertask, 4000L);
  380. }
  381.  
  382. void __saveds 
  383. securertask (void)
  384. {
  385.   while (!(SetSignal (0L, 0L) & SIGBREAKF_CTRL_C))
  386.     {
  387.       ScreenToFront (blankscreen);
  388.       changecolor ();
  389.     }
  390.   Signal (buddy, SIGBREAKF_CTRL_D);
  391.   Wait (0L);
  392. }
  393.  
  394. void 
  395. killsecurer (void)
  396. {
  397.   Signal (securer, SIGBREAKF_CTRL_C);
  398.   Wait (SIGBREAKF_CTRL_D);
  399.   DeleteTask (securer);
  400.   securer = NULL;
  401. }
  402.  
  403. void __saveds 
  404. scsifriendlosing (void)
  405. {
  406.   scsiDisp++;
  407. }
  408.  
  409. int 
  410. ParseConfigFile (void)
  411. {
  412.   BPTR configFile;
  413. #define INPUTBUFFERSIZE 512
  414.   char buffer[INPUTBUFFERSIZE];
  415.   int bp;
  416.   int keyword;
  417. #define KEYWORDBUFFERSIZE 31
  418.   char keywordbuffer[KEYWORDBUFFERSIZE + 1];
  419.   int keywordbp;
  420.   int charinbuffer;
  421.   int state = 0;
  422.   int line = 1;
  423.   int i;
  424.   int neg;
  425.  
  426.   configFile = Open (".newpoprc", MODE_OLDFILE);
  427.   if (!configFile)
  428.     configFile = Open ("s:.newpoprc", MODE_OLDFILE);
  429.   if (!configFile)
  430.     return 0;
  431.  
  432.   while (charinbuffer = Read (configFile, buffer, INPUTBUFFERSIZE))
  433.     {
  434.       for (bp = 0; bp != charinbuffer; bp++)
  435.     {
  436.       switch (state)
  437.         {
  438.         case 0:
  439.           if (buffer[bp] == '#')
  440.         state = 1;
  441.           else if (buffer[bp] == '\n')
  442.         line++;
  443.           else if ((buffer[bp] <= 'z') && (buffer[bp] >= 'a'))
  444.         {
  445.           keywordbuffer[0] = buffer[bp] - 32;
  446.           keywordbp = 1;
  447.           state = 2;
  448.         }
  449.           else if ((buffer[bp] <= 'Z') && (buffer[bp] >= 'A'))
  450.         {
  451.           keywordbuffer[0] = buffer[bp];
  452.           keywordbp = 1;
  453.           state = 2;
  454.         }
  455.           else if ((buffer[bp] != ' ') && (buffer[bp] != '\t'))
  456.         {
  457.           state = 1;
  458.           goto out;
  459.         }
  460.           break;
  461.         case 1:
  462.           if (buffer[bp] == '\n')
  463.         {
  464.           line++;
  465.           state = 0;
  466.         }
  467.           break;
  468.         case 2:
  469.           if ((buffer[bp] <= 'z') && (buffer[bp] >= 'a'))
  470.         {
  471.           if (keywordbp >= KEYWORDBUFFERSIZE)
  472.             {
  473.               state = 1;
  474.               goto out;
  475.             }
  476.           keywordbuffer[keywordbp++] = buffer[bp] - 32;
  477.         }
  478.           else if ((buffer[bp] <= 'Z') && (buffer[bp] >= 'A'))
  479.         {
  480.           if (keywordbp >= KEYWORDBUFFERSIZE)
  481.             {
  482.               state = 1;
  483.               goto out;
  484.             }
  485.           keywordbuffer[keywordbp++] = buffer[bp];
  486.         }
  487.           else if ((buffer[bp] <= '9') && (buffer[bp] >= '0'))
  488.         {
  489.           if (keywordbp >= KEYWORDBUFFERSIZE)
  490.             {
  491.               state = 1;
  492.               goto out;
  493.             }
  494.           keywordbuffer[keywordbp++] = buffer[bp];
  495.         }
  496.           else if ((buffer[bp] == ' ') || (buffer[bp] == '\t'))
  497.         {
  498.           keywordbuffer[keywordbp] = '\0';
  499.           for (i = 0; NewPopOptions[i].name; i++)
  500.             if (!strcmp (NewPopOptions[i].name, keywordbuffer))
  501.               break;
  502.           if (!NewPopOptions[i].name)
  503.             {
  504.               state = 1;
  505.               goto out;
  506.             }
  507.           keyword = i;
  508.           state = 3;
  509.         }
  510.           else
  511.         {
  512.           state = 1;
  513.           goto out;
  514.         }
  515.           break;
  516.         case 3:
  517.           if ((buffer[bp] != ' ') && (buffer[bp] != '\t'))
  518.         switch (NewPopOptions[keyword].type)
  519.           {
  520.           case boolean:
  521.             state = 4;
  522.             if ((buffer[bp] <= 'z') && (buffer[bp] >= 'a'))
  523.               {
  524.             keywordbuffer[0] = buffer[bp] - 32;
  525.             keywordbp = 1;
  526.               }
  527.             else if ((buffer[bp] <= 'Z') && (buffer[bp] >= 'A'))
  528.               {
  529.             keywordbuffer[0] = buffer[bp];
  530.             keywordbp = 1;
  531.               }
  532.             else
  533.               {
  534.             state = 1;
  535.             goto out;
  536.               }
  537.             break;
  538.           case integer:
  539.             state = 5;
  540.             neg = 0;
  541.             if (buffer[bp] == '-')
  542.               {
  543.             neg = 1;
  544.             NewPopOptions[keyword].value.ivalue = 0;
  545.               }
  546.             else if ((buffer[bp] <= '9') && (buffer[bp] >= '0'))
  547.               NewPopOptions[keyword].value.ivalue = buffer[bp] - '0';
  548.             else
  549.               {
  550.             state = 1;
  551.             goto out;
  552.               }
  553.             break;
  554.           case string:
  555.             state = 6;
  556.             if (buffer[bp] != '"')
  557.               {
  558.             state = 1;
  559.             goto out;
  560.               }
  561.             i = 0;
  562.             break;
  563.           }
  564.           break;
  565.         case 4:
  566.           if ((buffer[bp] <= 'z') && (buffer[bp] >= 'a'))
  567.         {
  568.           if (keywordbp >= KEYWORDBUFFERSIZE)
  569.             {
  570.               state = 1;
  571.               goto out;
  572.             }
  573.           keywordbuffer[keywordbp++] = buffer[bp] - 32;
  574.         }
  575.           else if ((buffer[bp] <= 'Z') && (buffer[bp] >= 'A'))
  576.         {
  577.           if (keywordbp >= KEYWORDBUFFERSIZE)
  578.             {
  579.               state = 1;
  580.               goto out;
  581.             }
  582.           keywordbuffer[keywordbp++] = buffer[bp];
  583.         }
  584.           else if ((buffer[bp] == ' ') || (buffer[bp] == '\t') || (buffer[bp] == '\n'))
  585.         {
  586.           keywordbuffer[keywordbp] = '\0';
  587.           NewPopOptions[i].value.ivalue = 2;
  588.           if (!strcmp ("TRUE", keywordbuffer))
  589.             NewPopOptions[i].value.ivalue = 1;
  590.           if (!strcmp ("FALSE", keywordbuffer))
  591.             NewPopOptions[i].value.ivalue = 0;
  592.           if (!strcmp ("ON", keywordbuffer))
  593.             NewPopOptions[i].value.ivalue = 1;
  594.           if (!strcmp ("OFF", keywordbuffer))
  595.             NewPopOptions[i].value.ivalue = 0;
  596.           if (NewPopOptions[i].value.ivalue == 2)
  597.             {
  598.               state = 1;
  599.               goto out;
  600.             }
  601.           if (buffer[bp] == '\n')
  602.             {
  603.               line++;
  604.               state = 0;
  605.             }
  606.           else
  607.             state = 7;
  608.         }
  609.           else
  610.         {
  611.           state = 1;
  612.           goto out;
  613.         }
  614.           break;
  615.         case 5:
  616.           if (buffer[bp] == '\n')
  617.         {
  618.           if (neg)
  619.             NewPopOptions[keyword].value.ivalue *= -1;
  620.           if (NewPopOptions[keyword].value.ivalue > NewPopOptions[keyword].max)
  621.             {
  622.               state = 1;
  623.               goto out;
  624.             }
  625.           if (NewPopOptions[keyword].value.ivalue < NewPopOptions[keyword].min)
  626.             {
  627.               state = 1;
  628.               goto out;
  629.             }
  630.           line++;
  631.           state = 0;
  632.         }
  633.           else if ((buffer[bp] == ' ') || (buffer[bp] == '\t'))
  634.         {
  635.           if (neg)
  636.             NewPopOptions[keyword].value.ivalue *= -1;
  637.           if (NewPopOptions[keyword].value.ivalue > NewPopOptions[keyword].max)
  638.             {
  639.               state = 1;
  640.               goto out;
  641.             }
  642.           if (NewPopOptions[keyword].value.ivalue < NewPopOptions[keyword].min)
  643.             {
  644.               state = 1;
  645.               goto out;
  646.             }
  647.           state = 7;
  648.         }
  649.           else if ((buffer[bp] <= '9') && (buffer[bp] >= '0'))
  650.         {
  651.           NewPopOptions[keyword].value.ivalue *= 10;
  652.           NewPopOptions[keyword].value.ivalue += buffer[bp] - '0';
  653.         }
  654.           else
  655.         {
  656.           state = 1;
  657.           goto out;
  658.         }
  659.           break;
  660.         case 6:
  661.           if ((buffer[bp] == '\n') || (i >= NewPopOptions[keyword].max))
  662.         {
  663.           state = 1;
  664.           goto out;
  665.         }
  666.           NewPopOptions[keyword].value.svalue[i++] = buffer[bp];
  667.           if (buffer[bp] == '"')
  668.         {
  669.           NewPopOptions[keyword].value.svalue[--i] = '\0';
  670.           state = 8;
  671.         }
  672.           break;
  673.         case 7:
  674.           if (buffer[bp] == '#')
  675.         state = 1;
  676.           else if (buffer[bp] == '\n')
  677.         {
  678.           line++;
  679.           state = 0;
  680.         }
  681.           else if ((buffer[bp] != ' ') && (buffer[bp] != '\t'))
  682.         {
  683.           state = 1;
  684.           goto out;
  685.         }
  686.           break;
  687.         case 8:
  688.           if (buffer[bp] == '\n')
  689.         {
  690.           line++;
  691.           state = 0;
  692.         }
  693.           else if ((buffer[bp] != ' ') && (buffer[bp] != '\t'))
  694.         {
  695.           state = 1;
  696.           goto out;
  697.         }
  698.           else
  699.         state = 7;
  700.           break;
  701.         default:
  702.           state = 1;
  703.           goto out;
  704.         }
  705.     }
  706.     }
  707. out:
  708.  
  709.   Close (configFile);
  710.   if (state)
  711.     {
  712.       if (!StartedFromWB)
  713.     {
  714.           sprintf (buffer, "NewPop: parse error on line %d of .newpoprc\n", line);
  715.       Write (Output (), buffer, strlen (buffer));
  716.     }
  717.       return 1;
  718.     }
  719.   return 0;
  720. }
  721.  
  722. void 
  723. _main (char *cmd)
  724. {
  725.   USHORT scsifriendinstalled = 0;
  726.   ULONG timersig, LIdle, LDisp;
  727.   BPTR nullfh = NULL;
  728.   struct MsgPort *port;
  729.   struct MsgPort *timerport = NULL;
  730.   struct MsgPort *inputDevPort = NULL;
  731.   struct timerequest *timerreq = NULL;
  732.   struct IOStdReq *inputRequestBlock = NULL;
  733.   struct TextFont *textFont = NULL;
  734.   struct Task *scsifriend;
  735.   struct Interrupt handlerStuff;
  736.   struct Window *titlewindow = NULL;
  737.   struct RastPort *titleRP;
  738.  
  739.   {
  740.     if (!(cmd && *cmd))
  741.       StartedFromWB = 1;
  742.     Forbid ();
  743.     if (!(port = FindPort (PORTNAME)))
  744.       {
  745.     if (!(port = CreatePort (PORTNAME, 0)))
  746.       {
  747.         Permit ();
  748.         goto grandexit;
  749.       }
  750.     Permit ();
  751.     if (!StartedFromWB)
  752.       Write (Output (), BANNER, sizeof (BANNER));
  753.     if (ParseConfigFile ())
  754.       goto abort;
  755.       }
  756.     else
  757.       {
  758.     Permit ();
  759.     if (StartedFromWB)
  760.       Signal (port->mp_SigTask, SIGBREAKF_CTRL_C);
  761.     else
  762.       Write (Output (), ALREADYHEREMESSAGE, sizeof (ALREADYHEREMESSAGE));
  763.     goto grandexit;
  764.       }
  765.     buddy = FindTask (NULL);
  766.     if (!(nullfh = Open ("NIL:", MODE_NEWFILE)))
  767.       goto abort;
  768.     if (!(inputDevPort = CreatePort ("NewPopInputPort", 0)))
  769.       goto abort;
  770.     if (!(inputRequestBlock = CreateExtIO (inputDevPort, sizeof (struct IOStdReq))))
  771.       goto abort;
  772.     if (!(timerport = CreatePort ("NewPopTimerPort", 0)))
  773.       goto abort;
  774.     if (!(timerreq = (struct timerequest *) CreateExtIO (timerport, sizeof (struct timerequest))))
  775.       goto abort;
  776.     if ((creatsignum = AllocSignal (-1)) == -1)
  777.       goto abort;
  778.     if ((blanksignum = AllocSignal (-1)) == -1)
  779.       goto abort;
  780.     if ((mousemovenum = AllocSignal (-1)) == -1)
  781.       goto abort;
  782.     if (!(GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", 0)))
  783.       goto abort;
  784.     if (!(LayersBase = (struct LayersBase *) OpenLibrary ("layers.library", 0)))
  785.       goto abort;
  786.     if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 0)))
  787.       goto abort;
  788.     if (!(DiskfontBase = (struct DiskfontBase *) OpenLibrary ("diskfont.library", 0)))
  789.       goto abort;
  790.     if (!(ExecBase = (struct ExecBase *) OpenLibrary ("exec.library", 0)))
  791.       goto abort;
  792.     if (LOCK)
  793.       ReqBase = (struct ReqLib *) OpenLibrary ("req.library", 0);
  794.     if (!NEWPOPLITE)
  795.       {
  796.     if (MEMORYMONWIDTH)
  797.       {
  798.         struct MemHeader *mem;
  799.  
  800.         Forbid ();
  801.         for (mem = (struct MemHeader *)ExecBase->MemList.lh_Head;
  802.          mem->mh_Node.ln_Succ;
  803.          mem = (struct MemHeader *)mem->mh_Node.ln_Succ)
  804.           {
  805.         if (mem -> mh_Attributes & MEMF_CHIP)
  806.           maxchip += ((ULONG) mem -> mh_Upper - (ULONG) mem -> mh_Lower);
  807.         /* Just in case we have something that is both chip and fast... */
  808.         if (mem -> mh_Attributes & MEMF_FAST)
  809.           maxfast += ((ULONG) mem -> mh_Upper - (ULONG) mem -> mh_Lower);
  810.           }
  811.         Permit ();
  812.       }
  813.     else
  814.       GAPBETWEEN3 = 0;
  815.     if (SCSIIOMONWIDTH)
  816.       {
  817.         Forbid ();
  818.         if (scsifriend = FindTask (SCSITASKNAME))
  819.           if (!(scsifriend->tc_Flags & TF_SWITCH))
  820.             {
  821.               scsifriend->tc_Switch = scsifriendlosing;
  822.               scsifriend->tc_Flags |= TF_SWITCH;
  823.               scsifriendinstalled = 1;
  824.             }
  825.         Permit ();
  826.       }
  827.     else
  828.       GAPBETWEEN2 = 0;
  829.     if (!CPULOADMONWIDTH)
  830.       GAPBETWEEN = 0;
  831.     WindowWidth = MEMORYMONWIDTH + GAPBETWEEN3 + SCSIIOMONWIDTH +
  832.       GAPBETWEEN2 + CPULOADMONWIDTH + GAPBETWEEN + MAXTEXTWIDTH;
  833.     WindowHeight = WINDOWHEIGHT;
  834.     NewWindow.LeftEdge = GfxBase->NormalDisplayColumns - WindowWidth - STARTXOFFSET;
  835.     NewWindow.TopEdge = 1;
  836.     NewWindow.Width = WindowWidth;
  837.     NewWindow.Height = WindowHeight;
  838.     if (WEWANTWINDOWDRAG)
  839.       {
  840.         WDragGadget.Height = WindowHeight;
  841.         WDragGadget.Width = WindowWidth;
  842.       }
  843.     else
  844.       NewWindow.FirstGadget = NULL;
  845.     if (BACKDROPWINDOW)
  846.       NewWindow.Flags |= BACKDROP;
  847.     if ((NewWindow.LeftEdge < 0) || !(titlewindow = OpenWindow (&NewWindow)))
  848.       goto abort;
  849.     titleRP = titlewindow->RPort;
  850.     SetAPen (titleRP, 1);
  851.     SetBPen (titleRP, 1);
  852.     SetDrMd (titleRP, JAM2);
  853.     RectFill (titleRP, 0, 0, (WindowWidth - 1), (WindowHeight - 1));
  854.     if (MAXTEXTWIDTH)
  855.       {
  856.         struct TextAttr textAttr = {NULL, 0, 0, 0};
  857.  
  858.         textAttr.ta_Name = FONTNAME;
  859.         textAttr.ta_YSize = FONTSIZE;
  860.         if (textFont = OpenFont (&textAttr))
  861.           {
  862.             if ((textFont->tf_YSize != FONTSIZE) || (textFont->tf_Style != 0))
  863.               {
  864.             CloseFont (textFont);
  865.             if (!(textFont = OpenDiskFont (&textAttr)))
  866.               goto abort;
  867.               }
  868.           }
  869.         else
  870.           {
  871.             if (!(textFont = OpenDiskFont (&textAttr)))
  872.               goto abort;
  873.           }
  874.         SetFont (titleRP, textFont);
  875.       }
  876.     LIdle = ExecBase->IdleCount;
  877.     LDisp = ExecBase->DispCount;
  878.       }
  879.     if (OpenDevice ("input.device", 0, (struct IORequest *) inputRequestBlock, 0))
  880.       goto abort;
  881.     handlerStuff.is_Data = (APTR) NULL;
  882.     handlerStuff.is_Code = (VOID (*) ()) myhandler;
  883.     handlerStuff.is_Node.ln_Pri = 51;
  884.     timersig = (1 << timerport->mp_SigBit);
  885.     creatclisig = 1 << creatsignum;
  886.     unblanksig = 1 << blanksignum;
  887.     mousemovesig = 1 << mousemovenum;
  888.     inputRequestBlock->io_Command = IND_ADDHANDLER;
  889.     inputRequestBlock->io_Data = (APTR) & handlerStuff;
  890.     DoIO ((struct IORequest *) inputRequestBlock);
  891.     if (OpenDevice (TIMERNAME, UNIT_VBLANK, (struct IORequest *) timerreq, 0))
  892.       goto abort;
  893.     QueueTimer (timerreq, 1 /* 1/60th of a second */ );
  894.   }
  895.  
  896.   {
  897.     UWORD newsecond;
  898.     ULONG sig, Seconds, Micros, LastSeconds = 0;
  899.     int topscreenwidth = GfxBase->NormalDisplayColumns;
  900.     int topscreenheight = GfxBase->NormalDisplayRows;
  901.  
  902.     for (;;)
  903.       {
  904.     sig = Wait (creatclisig | unblanksig | timersig |
  905.             mousemovesig | SIGBREAKF_CTRL_C);
  906.  
  907.     if (sig & mousemovesig)
  908.       {
  909.         int left, right, upper, lower;
  910.  
  911.         if (!blankscreen)
  912.           {
  913.         int lock = LockIBase (0);
  914.         struct Screen *screen = IntuitionBase->FirstScreen;
  915.  
  916.         while (screen && IntuitionBase->MouseY <
  917.                (screen->TopEdge << ((screen->ViewPort.Modes & LACE) ? 0 : 1)))
  918.           screen = screen->NextScreen;
  919.         if (screen)
  920.           {
  921.             topscreenwidth = screen->Width << ((screen->ViewPort.Modes & HIRES) ? 0 : 1);
  922.             topscreenheight = screen->Height >> ((screen->ViewPort.Modes & LACE) ? 1 : 0);
  923.           }
  924.         else
  925.           {
  926.             topscreenwidth = GfxBase->NormalDisplayColumns;
  927.             topscreenheight = GfxBase->NormalDisplayRows;
  928.           }
  929.         UnlockIBase (lock);
  930.           }
  931.  
  932.         left = IntuitionBase->MouseX < 10;
  933.         right = (topscreenwidth - IntuitionBase->MouseX) < 10;
  934.         upper = IntuitionBase->MouseY < 10;
  935.         lower = (topscreenheight - IntuitionBase->MouseY / 2) < 10;
  936.  
  937.         instantblank = ((((ULC == 1) && upper) || ((LLC == 1) && lower)) && left) ||
  938.           ((((URC == 1) && upper) || ((LRC == 1) && lower)) && right);
  939.         defeatblank = ((((ULC == 2) && upper) || ((LLC == 2) && lower)) && left) ||
  940.           ((((URC == 2) && upper) || ((LRC == 2) && lower)) && right);
  941.       }
  942.  
  943.     CurrentTime (&Seconds, &Micros);
  944.     newsecond = (Seconds != LastSeconds);
  945.     LastSeconds = Seconds;
  946.  
  947.     if (newsecond && !NEWPOPLITE && !blankscreen)
  948.       {
  949.         SHORT x = 0;
  950.         ULONG DIdle, DDisp, Usage;
  951.         long t;
  952.         struct tm *p;
  953.         char *timestr;
  954.  
  955.         UpfrontLayer (0L, titlewindow->WLayer);
  956.  
  957.         DIdle = ExecBase->IdleCount - LIdle;
  958.         DDisp = ExecBase->DispCount - LDisp;
  959.         LIdle = ExecBase->IdleCount;
  960.         LDisp = ExecBase->DispCount;
  961.         if (!DDisp)
  962.           DDisp++;
  963.  
  964.         if (MEMORYMONWIDTH)
  965.           {
  966.         int pixels;
  967.  
  968.         SetAPen (titleRP, 3);
  969.         pixels = AvailMem (MEMF_CHIP) * MEMORYMONWIDTH / maxchip;
  970.         RectFill (titleRP, x, 0, x+pixels, ((WindowHeight/2) - 1));
  971.             SetAPen (titleRP, 1);
  972.         RectFill (titleRP, x+pixels+1, 0, MEMORYMONWIDTH, ((WindowHeight/2) - 1));
  973.  
  974.         SetAPen (titleRP, 2);
  975.         pixels = AvailMem (MEMF_FAST) * MEMORYMONWIDTH / maxfast;
  976.         RectFill (titleRP, x, (WindowHeight/2), x+pixels, (WindowHeight - 1));
  977.             SetAPen (titleRP, 1);
  978.         RectFill (titleRP, x+pixels+1, (WindowHeight/2), MEMORYMONWIDTH, (WindowHeight - 1));
  979.  
  980.             x = MEMORYMONWIDTH;
  981.           }
  982.  
  983.         x += GAPBETWEEN3;
  984.  
  985.         if (scsifriendinstalled)
  986.           {
  987.         Usage = (scsiDisp * 256) / (DDisp + DIdle);
  988.         if (Usage > MAXSCSIUSAGE)
  989.           Usage = MAXSCSIUSAGE;
  990.         SetAPen (titleRP, 3);
  991.         ScrollRaster (titleRP, 1, 0, x, 0, x + SCSIIOMONWIDTH, (WindowHeight - 1));
  992.         x += SCSIIOMONWIDTH;
  993.         Move (titleRP, x, (WindowHeight - 1));
  994.         Draw (titleRP, x, WindowHeight - ((WindowHeight * Usage) / MAXSCSIUSAGE));
  995.         scsiDisp = 0;
  996.           }
  997.         else
  998.           x += SCSIIOMONWIDTH;
  999.  
  1000.         x += GAPBETWEEN2;
  1001.  
  1002.         if (CPULOADMONWIDTH)
  1003.           {
  1004.             /* There be magic below!  Where does 456 come from? :-) */
  1005.             if (scsiDisp < DDisp)
  1006.               Usage = ((DDisp - scsiDisp) * 456) / (DDisp + DIdle);
  1007.             else
  1008.               Usage = 0;
  1009.             if (Usage < 200)
  1010.               Usage = 0;
  1011.             else
  1012.               Usage = Usage - 200;
  1013.             ScrollRaster (titleRP, 1, 0, x, 0, x + CPULOADMONWIDTH, (WindowHeight - 1));
  1014.             x += CPULOADMONWIDTH;
  1015.             SetAPen (titleRP, 2);
  1016.             Move (titleRP, x, (WindowHeight - 1));
  1017.             Draw (titleRP, x, WindowHeight - ((WindowHeight * Usage) / 256));
  1018.           }
  1019.  
  1020.         x += GAPBETWEEN;
  1021.  
  1022.         if (MAXTEXTWIDTH)
  1023.           {
  1024.             time (&t);
  1025.             p = localtime (&t);
  1026.             timestr = asctime (p);
  1027.         if (WIMPYCLOCK)
  1028.           switch ((timestr[11] - '0') * 10 + (timestr[12] - '0'))
  1029.             {
  1030.             case 0: timestr[11] = '1'; timestr[12] = '2'; goto am;
  1031.             case 12: goto pm;
  1032.             case 13: timestr[11] = '0'; timestr[12] = '1'; goto pm;
  1033.             case 14: timestr[11] = '0'; timestr[12] = '2'; goto pm;
  1034.             case 15: timestr[11] = '0'; timestr[12] = '3'; goto pm;
  1035.             case 16: timestr[11] = '0'; timestr[12] = '4'; goto pm;
  1036.             case 17: timestr[11] = '0'; timestr[12] = '5'; goto pm;
  1037.             case 18: timestr[11] = '0'; timestr[12] = '6'; goto pm;
  1038.             case 19: timestr[11] = '0'; timestr[12] = '7'; goto pm;
  1039.             case 20: timestr[11] = '0'; timestr[12] = '8'; goto pm;
  1040.             case 21: timestr[11] = '0'; timestr[12] = '9'; goto pm;
  1041.             case 22: timestr[11] = '1'; timestr[12] = '0'; goto pm;
  1042.             case 23: timestr[11] = '1'; timestr[12] = '1'; goto pm;
  1043.             default: am: timestr[19] = 'a'; break;
  1044.             pm: timestr[19] = 'p'; break;
  1045.             }
  1046.             Move (titleRP, x, STARTYOFFSET);
  1047.             Text (titleRP, timestr, 24);
  1048.  
  1049.             x += TextLength (titleRP, timestr, 24);
  1050.             SetAPen (titleRP, 1);
  1051.             if (x < (WindowWidth - 1))
  1052.               RectFill (titleRP, x, 0, (WindowWidth - 1), (WindowHeight - 1));
  1053.           }
  1054.       }
  1055.  
  1056.     if (blankscreen)
  1057.       {
  1058.         if (NICENEWPOP)
  1059.           {
  1060.         if (newsecond)
  1061.           {
  1062.             changecolor ();
  1063.             SetTaskPri (child, 10);
  1064.           }
  1065.           }
  1066.         else
  1067.           {
  1068.         if (newsecond)
  1069.           changecolor ();
  1070.         updatedisplay ();
  1071.           }
  1072.       }
  1073.  
  1074.     if (sig & SIGBREAKF_CTRL_C)
  1075.       goto abort;
  1076.  
  1077.     if (sig & creatclisig)
  1078.       {
  1079.         if (!(blankscreen && LOCK))
  1080.           {
  1081.         WBenchToFront ();
  1082.         if (DOSBase->dl_lib.lib_Version < 36)
  1083.           Execute(COMMAND, nullfh, nullfh);
  1084.         else
  1085.             {
  1086.             static struct TagItem stags[4] =
  1087.             {
  1088.               {SYS_Input, NULL},
  1089.               {SYS_Output, NULL},
  1090.               {SYS_UserShell, TRUE},
  1091.               {TAG_DONE, 0}
  1092.             };
  1093.  
  1094.             stags[0].ti_Data = nullfh;
  1095.             System(COMMAND, stags);
  1096.               }
  1097.         if (blankscreen)
  1098.           goto unblank;
  1099.           }
  1100.       }
  1101.  
  1102.     {
  1103.       static WORD joy0, oldjoy0, joy1, oldjoy1;
  1104.  
  1105.       joy0 = *((WORD *)0x00dff00a) & 0x0303;
  1106.       joy1 = *((WORD *)0x00dff00c) & 0x0303;
  1107.       if ((joy0 != oldjoy0) || (joy1 != oldjoy1))
  1108.         {
  1109.           oldjoy0 = joy0;
  1110.           oldjoy1 = joy1;
  1111.           if (blankscreen && !instantblank)
  1112.         goto unblank;
  1113.         }
  1114.     }
  1115.  
  1116.     if ((sig & unblanksig) && blankscreen && !instantblank)
  1117.       {
  1118.       unblank:
  1119.         if (LOCK && ReqBase)
  1120.           {
  1121.         char InputPassWord[MAXPASSWORD];
  1122.             static int trywait;
  1123.  
  1124.         SetRGB4 (blankVP, 17, 4, 4, 4);
  1125.         SetRGB4 (blankVP, 18, 8, 8, 8);
  1126.         SetRGB4 (blankVP, 19, 12, 12, 12);
  1127.         createsecurer ();
  1128.         InputPassWord[0] = 0;
  1129.         if ((trywait++ % 2) &&
  1130.             GetString (InputPassWord, "Type password, then hit return.",
  1131.             blankwindow, MAXPASSWORD + 10, MAXPASSWORD))
  1132.           {
  1133.             killsecurer ();
  1134.             UpfrontLayer (0L, blankwindow->WLayer);
  1135.             if (strcmp (InputPassWord, PASSWORD))
  1136.               goto noway;
  1137.           }
  1138.         else
  1139.           {
  1140.             killsecurer ();
  1141.             UpfrontLayer (0L, blankwindow->WLayer);
  1142.             goto noway;
  1143.           }
  1144.           }
  1145.         if (NICENEWPOP)
  1146.           killchild ();
  1147.         CloseWindow (blankwindow);
  1148.         CloseScreen (blankscreen);
  1149.         blankscreen = NULL;
  1150.         noevents = 0;
  1151.       noway: ;
  1152.       }
  1153.  
  1154.     if (sig & timersig)
  1155.       {
  1156.         GetMsg (timerport);
  1157.         if (blankscreen && NICENEWPOP)
  1158.           QueueTimer (timerreq, 60 /* One second */ );
  1159.         else
  1160.           QueueTimer (timerreq, 1 /* 1/60th of a second*/ );
  1161.         if ((instantblank || (noevents++ >= (TIMEOUT * 60))) && !blankscreen && !defeatblank)
  1162.           {
  1163.         NewScreen.Height = GfxBase->NormalDisplayRows * 2;
  1164.         NewScreen.Width = GfxBase->NormalDisplayColumns;
  1165.  
  1166.         if (blankscreen = OpenScreen (&NewScreen))
  1167.           {
  1168.             ylim = blankscreen->Height - 1;
  1169.             xlim = blankscreen->Width - 1;
  1170.             NewBlankerWindow.Screen = blankscreen;
  1171.             NewBlankerWindow.Height = blankscreen->Height;
  1172.             NewBlankerWindow.Width = blankscreen->Width;
  1173.             if (blankwindow = OpenWindow (&NewBlankerWindow))
  1174.               {
  1175.             static UWORD __chip NULLpointer[1] = {0x0000};
  1176.  
  1177.             blankRP = blankwindow->RPort;
  1178.             blankVP = &(blankscreen->ViewPort);
  1179.             SetPointer (blankwindow, NULLpointer, 0, 0, 0, 0);
  1180.             changecolor ();
  1181.             SetRGB4 (blankVP, 0, 0, 0, 0);
  1182.             SetRGB4 (blankVP, 17, 0, 0, 0);
  1183.             SetRGB4 (blankVP, 18, 0, 0, 0);
  1184.             SetRGB4 (blankVP, 19, 0, 0, 0);
  1185.             SetDrMd (blankRP, JAM1);
  1186.             UpfrontLayer (0L, blankwindow->WLayer);
  1187.             if (NICENEWPOP)
  1188.               createchild ();
  1189.               }
  1190.             else
  1191.               {
  1192.                 CloseScreen (blankscreen);
  1193.                 blankscreen = NULL;
  1194.               }
  1195.           }
  1196.           }
  1197.       }
  1198.  
  1199.     if (blankscreen)
  1200.       ScreenToFront (blankscreen);
  1201.       }
  1202.   }
  1203.  
  1204. abort:
  1205. #define SafeClose(fh) if (fh) Close (fh)
  1206. #define SafeDeletePort(port) if (port) DeletePort (port)
  1207. #define SafeCloseLibrary(lib) if (lib) CloseLibrary ((struct Library *) lib)
  1208. #define SafeFreeSignal(signum) if (signum != -1) FreeSignal (signum)
  1209. #define SafeCloseFont(font) if (font) CloseFont (font)
  1210. #define SafeCloseWindow(window) if (window) CloseWindow (window)
  1211.   SafeDeletePort (port);
  1212.   if (scsifriendinstalled)
  1213.     {
  1214.       Forbid ();
  1215.       if (scsifriend = FindTask (SCSITASKNAME))
  1216.     if (scsifriend->tc_Switch == scsifriendlosing)
  1217.       {
  1218.         UBYTE oldpri = SetTaskPri (scsifriend, 21);
  1219.         Permit ();
  1220.         // Make SURE scsifriend has lost the CPU!
  1221.         // I don't know why this fixed a problem
  1222.         // people were having with A3000's/2.0/C=
  1223.         // controllers, but it seems to work!
  1224.         Forbid ();
  1225.         SetTaskPri (scsifriend, oldpri);
  1226.         scsifriend->tc_Flags &= ~TF_SWITCH;
  1227.         scsifriend->tc_Switch = NULL;
  1228.       }
  1229.       Permit ();
  1230.     }
  1231.   SafeCloseWindow (titlewindow);
  1232.   if (timerreq)
  1233.     {
  1234.       if (timerreq->tr_node.io_Device)
  1235.         {
  1236.           if (!CheckIO ((struct IOStdReq *) timerreq));
  1237.         {
  1238.           AbortIO ((struct IOStdReq *) timerreq);
  1239.           WaitIO ((struct IOStdReq *) timerreq);
  1240.         }
  1241.       CloseDevice ((struct IORequest *) timerreq);
  1242.     }
  1243.       DeleteExtIO ((struct IOStdReq *) timerreq);
  1244.     }
  1245.   if (inputRequestBlock)
  1246.     {
  1247.       if (inputRequestBlock->io_Device)
  1248.     {
  1249.       inputRequestBlock->io_Command = IND_REMHANDLER;
  1250.       inputRequestBlock->io_Data = (APTR) & handlerStuff;
  1251.       DoIO ((struct IORequest *) inputRequestBlock);
  1252.       CloseDevice ((struct IORequest *) inputRequestBlock);
  1253.     }
  1254.       DeleteExtIO (inputRequestBlock);
  1255.     }
  1256.   SafeCloseFont (textFont);
  1257.   SafeDeletePort (timerport);
  1258.   SafeFreeSignal (creatsignum);
  1259.   SafeFreeSignal (blanksignum);
  1260.   SafeFreeSignal (mousemovenum);
  1261.   if (blankscreen)
  1262.     {
  1263.       if (NICENEWPOP)
  1264.     killchild ();
  1265.       CloseWindow (blankwindow);
  1266.       CloseScreen (blankscreen);
  1267.     }
  1268.   SafeCloseLibrary (IntuitionBase);
  1269.   SafeCloseLibrary (GfxBase);
  1270.   SafeCloseLibrary (LayersBase);
  1271.   SafeCloseLibrary (DiskfontBase);
  1272.   SafeCloseLibrary (ExecBase);
  1273.   SafeCloseLibrary (ReqBase);
  1274.   SafeDeletePort (inputDevPort);
  1275.   SafeClose (nullfh);
  1276.  
  1277.   grandexit: ;
  1278. }
  1279.  
  1280. void 
  1281. changecolor (void)
  1282. {
  1283.   static struct color currentcolor = {15, 0, 5};
  1284.   static struct color colordelta = {-1, 1, 1};
  1285.  
  1286.   switch (rand () % 3)
  1287.     {
  1288.     case 0:
  1289.       currentcolor.red += colordelta.red;
  1290.       if (currentcolor.red == 0 ||
  1291.       currentcolor.red == 15)
  1292.     colordelta.red = -colordelta.red;
  1293.       break;
  1294.     case 1:
  1295.       currentcolor.green += colordelta.green;
  1296.       if (currentcolor.green == 0 ||
  1297.       currentcolor.green == 15)
  1298.     colordelta.green = -colordelta.green;
  1299.       break;
  1300.     case 2:
  1301.       currentcolor.blue += colordelta.blue;
  1302.       if (currentcolor.blue == 0 ||
  1303.       currentcolor.blue == 15)
  1304.     colordelta.blue = -colordelta.blue;
  1305.       break;
  1306.     }
  1307.   SetRGB4 (blankVP, 1, currentcolor.red, currentcolor.green, currentcolor.blue);
  1308. }
  1309.  
  1310. void 
  1311. updatedisplay (void)
  1312. {
  1313.   static SHORT x[2], y[2], xd[2], yd[2], ox[2][16], oy[2][16];
  1314.   static j;
  1315.   SHORT i, k;
  1316.  
  1317.   if (j == 0)
  1318.     {
  1319.       x[0] = rand () % xlim + 1;
  1320.       if ((x[1] = x[0] + rand () % (xlim / 6) - (xlim / 12)) > xlim)
  1321.     x[1] = xlim;
  1322.       if (x[1] < 0)
  1323.     x[1] = 0;
  1324.       y[0] = rand () % ylim + 1;
  1325.       if ((y[1] = y[0] + rand () % (ylim / 4) - (ylim / 8)) > ylim)
  1326.     y[1] = ylim;
  1327.       if (y[1] < 0)
  1328.     y[1] = 0;
  1329.       xd[0] = 11;
  1330.       yd[0] = 7;
  1331.       xd[1] = 3;
  1332.       yd[1] = 4;
  1333.     }
  1334.   SetAPen (blankRP, 0);
  1335.   Move (blankRP, ox[0][j & 15], oy[0][j & 15]);
  1336.   Draw (blankRP, ox[1][j & 15], oy[1][j & 15]);
  1337.   SetAPen (blankRP, 1);
  1338.   Move (blankRP, x[0], y[0]);
  1339.   Draw (blankRP, x[1], y[1]);
  1340.   for (i = 0; i < 2; i++)
  1341.     {
  1342.       ox[i][j & 15] = x[i];
  1343.       oy[i][j & 15] = y[i];
  1344.       x[i] += xd[i];
  1345.       y[i] += yd[i];
  1346.       if (abs (x[1] - x[0]) > xlim / 4)
  1347.     {
  1348.       x[i] -= xd[i] * 4 / 3;
  1349.       xd[i] = -xd[i] / 2;
  1350.     }
  1351.       if (abs (y[1] - y[0]) > ylim / 3)
  1352.     {
  1353.       y[i] -= yd[i] * 4 / 3;
  1354.       yd[i] = -yd[i] / 2;
  1355.     }
  1356.       if (x[i] < 0)
  1357.     {
  1358.       x[i] = 0;
  1359.       xd[i] = -xd[i];
  1360.     }
  1361.       else if (x[i] > xlim)
  1362.     {
  1363.       x[i] = xlim;
  1364.       xd[i] = -xd[i];
  1365.     }
  1366.       if (y[i] < 0)
  1367.     {
  1368.       y[i] = 0;
  1369.       yd[i] = -yd[i];
  1370.     }
  1371.       else if (y[i] > ylim)
  1372.     {
  1373.       y[i] = ylim;
  1374.       yd[i] = -yd[i];
  1375.     }
  1376.       if (((rand () >> 5) & 127) < 2)
  1377.     {
  1378.       if (xd[i] < 1)
  1379.         k = 1;
  1380.       xd[i] = (rand () >> 5) & 7;
  1381.       if (k == (1 - i))
  1382.         xd[i] = -xd[i];
  1383.       k = 0;
  1384.     }
  1385.       if (((rand () >> 5) & 255) < 50)
  1386.     {
  1387.       if (yd[i] < 1)
  1388.         k = 1;
  1389.       yd[i] = (rand () >> 5) & 7;
  1390.       if (k == (1 - i))
  1391.         yd[i] = -yd[i];
  1392.       k = 0;
  1393.     }
  1394.     }
  1395.   ++j;
  1396. }
  1397.  
  1398. void 
  1399. MemCleanup (void)
  1400. {
  1401. }
  1402.  
  1403. void 
  1404. QueueTimer (struct timerequest * tr, ULONG ticks)
  1405. {
  1406.   tr->tr_node.io_Command = TR_ADDREQUEST;
  1407.   tr->tr_time.tv_secs = ticks / 60;
  1408.   tr->tr_time.tv_micro = (ticks % 60) * 1000000 / 60;
  1409.   SendIO ((struct IORequest *) tr);
  1410. }
  1411.