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