home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 500.lha / NewPop_v3.0 / newpop.c < prev    next >
C/C++ Source or Header  |  1991-04-08  |  36KB  |  1,319 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.  *    LJR added the titlebar clock sometime in 1988 or early 1989.
  53.  *    LJR added the Q*X pattern sometime in 1988 or early 1989.
  54.  *    LJR added the auto- and defeat- blanking in 1988 or early 1989.
  55.  *    EAH and LJR added color to the Q*X sometime in late 1989.
  56.  *    EAH and LJR added the titlebar PrefMon around 1/18/90.
  57.  *    LJR improved the titlebar PrefMon on 2/8/90.
  58.  *    LJR added the titlebar disk I/O PrefMon on 2/8/90.
  59.  *    LJR reworked the way the titlebar stuff renders into
  60.  *        the `titlebar', now implemented with a backdrop window
  61.  *        positioned over the titlebar on 12/20/90.
  62.  *    LJR reworked all of newpop to be a bit more system independent
  63.  *        on 12/30/90.
  64.  *    LJR reworked Q*X code to spawn a new task on 1/13/91.
  65.  *    LJR reworked parts of newpop to be a bit more explicit
  66.  *        in declaring which registers arguments *MUST* be passed
  67.  *        in (mainly for the event handler).  Also switched back
  68.  *        to '-b1' and we now use __saveds on functions that need
  69.  *        to load A4.  This saves a few hundred bytes. 1/18/91.
  70.  *    LJR got rid of all _enforcer_ hits NewPop was causing.
  71.  *        The strange thing is that they were all happening in
  72.  *        ROM code because my message ports had no names and had
  73.  *        not been added to the system's port list.  I now name
  74.  *        and add to the system's list all message ports.  Not
  75.  *        only was this a bitch to track down, but it should
  76.  *        also be legal!  If anyone can comment on this, send me
  77.  *        mail at `l-rittle@uiuc.edu'. 1/19/91.
  78.  *    LJR recoded the entire thing to allow dynamic (at startup
  79.  *        time) configuration instead of hardcoded compile time
  80.  *        configuration.  This added many, many bytes! Why did I
  81.  *        do it?  Because my public asked for it, will I ever get
  82.  *        a pizza out of this deal? YOW 1/27/91.
  83.  *    LJR added URC, LRC, LLC, ULC options to allow the user
  84.  *        to decide what NewPop should do when the pointer enters
  85.  *        the given screen corner.  Also, changed the method
  86.  *        by which a running NewPop is told to halt. 2/1/91
  87.  *    LJR modified the method used to shut down a running
  88.  *        NewPop:  Signal(NewPopTask, SIGBREAKF_CTRL_C) is now the
  89.  *        way to kill it, instead of a custom message with the quit
  90.  *        flag set. 2/1/91
  91.  *    LJR cleaned up one last time for first UseNet release. 3/16/91
  92.  */
  93.  
  94.  
  95. /* * * * * * * * * * * INCLUDES * * * * * * * * * * * * */
  96. #include <exec/types.h>
  97. #include <exec/exec.h>
  98. #include <exec/execbase.h>
  99. #include <exec/tasks.h>
  100. #include <devices/timer.h>
  101. #include <devices/input.h>
  102. #include <devices/inputevent.h>
  103. #include <intuition/intuition.h>
  104. #include <intuition/intuitionbase.h>
  105. #include <libraries/dos.h>
  106. #include <graphics/gfxmacros.h>
  107. #include <graphics/layers.h>
  108. #include <graphics/gfxbase.h>
  109. #include <hardware/custom.h>
  110. #include <hardware/dmabits.h>
  111. #include <graphics/text.h>
  112. #include <proto/dos.h>
  113. #include <proto/exec.h>
  114. #include <proto/layers.h>
  115. #include <proto/intuition.h>
  116. #include <proto/graphics.h>
  117. #include <proto/diskfont.h>
  118. #include <string.h>
  119. #include <time.h>
  120.  
  121.  
  122. /* * * * * * * * * * * CONSTANTS * * * * * * * * * * * * */
  123. #define PORTNAME     "NewPop.port"
  124.  /* The name of our well known *PRIVATE* message port */
  125.  
  126. #define MAXCMD        200
  127. #define MAXTASKNAME    32
  128. #define MAXFONTNAME    32
  129.  /* Maximum string size of various things */
  130.  
  131. #define KILLMSG        "\x9B" "0;33mNewPop\x9B" "0m Terminating\n"
  132.  /* The kill message */
  133.  
  134. #define BANNER        "\x9B" "0;33mNewPop\x9B" "0m v3.2 by Loren J. Rittle - Copyright \xA9 1989 - 1991 Based upon:\n" \
  135.             "\x9B" "0;33mPOPCLI III\x9B" "0m by John Toebes - Copyright \xA9 1987 The Software Distillery\n"
  136.  /* The hello banner */
  137.  
  138.  
  139. /* * * * * * * * * * * * * * * * TYPES * * * * * * * * * * * * * */
  140. struct GLOBAL_DATA
  141. {
  142.   struct Task *buddy;
  143.   ULONG creatclisig;
  144.   ULONG unblanksig;
  145.   ULONG mousemovesig;
  146.   ULONG noevents;
  147.   short creatsignum;
  148.   short blanksignum;
  149.   short mousemovenum;
  150.   short key;
  151.   struct Screen *blankscreen;
  152. };
  153.  
  154. struct color
  155. {
  156.   int red, green, blue;
  157. };
  158.  
  159. enum OptionTypes
  160. {
  161.   boolean, integer, string
  162. };
  163.  
  164. struct NewPopOption
  165. {
  166.   char *name;
  167.   enum OptionTypes type;
  168.   union
  169.   {
  170.     int ivalue;
  171.     char *svalue;
  172.   } value;
  173.   int min, max;
  174. };
  175.  
  176.  
  177. /* * * * * * * * * * * EXTERNALS AND GLOBAL DATA * * * * * * * * */
  178. /*
  179.  *  See .newpoprc for the meanings of these options!
  180.  */
  181. struct NewPopOption NewPopOptions[] =
  182. {
  183. #define NICENEWPOP (NewPopOptions[0].value.ivalue)
  184.   {"NICENEWPOP", boolean, 1, 0, 1},
  185. #define NEWPOPLITE (NewPopOptions[1].value.ivalue)
  186.   {"NEWPOPLITE", boolean, 0, 0, 1},
  187. #define WEWANTWINDOWDRAG (NewPopOptions[2].value.ivalue)
  188.   {"WEWANTWINDOWDRAG", boolean, 0, 0, 1},
  189. #define SCSITASKNAME (NewPopOptions[3].value.svalue)
  190.   {"SCSITASKNAME", string, (int) "gvpscsi.device", 0, MAXTASKNAME},
  191. #define FONTNAME (NewPopOptions[4].value.svalue)
  192.   {"FONTNAME", string, (int) "Helvetica.font", 0, MAXFONTNAME},
  193. #define COMMAND (NewPopOptions[5].value.svalue)
  194. #ifndef LJR_FAVORITE
  195.   {"COMMAND", string, (int) "NEWCLI >NIL:", 0, MAXCMD},
  196. #else
  197.   {"COMMAND", string, (int) "NewWSH <nil: >nil: cnn:0/11/640/189/WShell/c", 0, MAXCMD},
  198. #endif
  199. #define MAXSCSIUSAGE (NewPopOptions[6].value.ivalue)
  200.   {"MAXSCSIUSAGE", integer, 55, 20, 255},
  201. #define SCSIIOMONWIDTH (NewPopOptions[7].value.ivalue)
  202.   {"SCSIIOMONWIDTH", integer, 100, 0, 100},
  203. #define CPULOADMONWIDTH (NewPopOptions[8].value.ivalue)
  204.   {"CPULOADMONWIDTH", integer, 100, 0, 100},
  205. #define GAPBETWEEN2 (NewPopOptions[9].value.ivalue)
  206.   {"GAPBETWEEN2", integer, 16, 0, 32},
  207. #define GAPBETWEEN (NewPopOptions[10].value.ivalue)
  208.   {"GAPBETWEEN", integer, 16, 0, 32},
  209. #define FONTSIZE (NewPopOptions[11].value.ivalue)
  210.   {"FONTSIZE", integer, 9, 4, 56},
  211. #define STARTYOFFSET (NewPopOptions[12].value.ivalue)
  212.   {"STARTYOFFSET", integer, 7, 2, 60},
  213. #define MAXTEXTWIDTH (NewPopOptions[13].value.ivalue)
  214.   {"MAXTEXTWIDTH", integer, 107, 10, 300},
  215. #define STARTXOFFSET (NewPopOptions[14].value.ivalue)
  216.   {"STARTXOFFSET", integer, 56, 10, 200},
  217. #define WINDOWHEIGHT (NewPopOptions[15].value.ivalue)
  218.   {"WINDOWHEIGHT", integer, 8, 4, 56},
  219. #define TIMEOUT (NewPopOptions[16].value.ivalue)
  220.   {"TIMEOUT", integer, 180, 0, 0x00ffffff},
  221. #define POPKEY (NewPopOptions[17].value.ivalue)
  222.   {"POPKEY", integer, 69, 0, 255},
  223. #define BLANKERPRIORITY (NewPopOptions[18].value.ivalue)
  224.   {"BLANKERPRIORITY", integer, -20, -20, 10},
  225. #define ULC (NewPopOptions[19].value.ivalue)
  226.   {"ULC", integer, 0, 0, 2},
  227. #define URC (NewPopOptions[20].value.ivalue)
  228.   {"URC", integer, 1, 0, 2},
  229. #define LLC (NewPopOptions[21].value.ivalue)
  230.   {"LLC", integer, 0, 0, 2},
  231. #define LRC (NewPopOptions[22].value.ivalue)
  232.   {"LRC", integer, 2, 0, 2},
  233. /* Add new enties before this line! */
  234.   {NULL, boolean, 0, 0, 0}
  235. };
  236.  
  237. char NewFontName[MAXFONTNAME];
  238. char NewTaskName[MAXTASKNAME];
  239. char NewCmd[MAXCMD];
  240.  
  241. struct IntuitionBase *IntuitionBase;
  242. struct LayersBase *LayersBase;
  243. struct GfxBase *GfxBase;
  244. struct DiskfontBase *DiskfontBase;
  245. struct DosLibrary *DosBase;
  246. struct ExecBase *ExecBase;
  247.  
  248. struct NewScreen NewScreen =
  249. {0, 0, 640, 400, 1, 0, 1, HIRES | LACE, SCREENQUIET | CUSTOMSCREEN, NULL, NULL, NULL, NULL};
  250.  
  251. int WindowWidth, WindowHeight;
  252.  
  253. struct Gadget WDragGadget =
  254. {NULL, 0, 0, 0, 0, GADGHNONE, NULL, WDRAGGING, NULL, NULL, NULL, NULL, NULL, 0, 0};
  255.  
  256. struct NewWindow NewWindow =
  257. {
  258.   0, 0,                /* window XY origin relative to TopLeft of screen.  Set later. */
  259.   0, 0,                /* window width and height */
  260.   2, 1,                /* detail and block pens */
  261.   0,                /* IDCMP flags */
  262.   BACKDROP + BORDERLESS + NOCAREREFRESH,    /* other window flags */
  263.   &WDragGadget,            /* first gadget in gadget list */
  264.   NULL,                /* custom CHECKMARK imagery */
  265.   NULL,                /* window title */
  266.   NULL,                /* custom screen pointer */
  267.   NULL,                /* custom bitmap */
  268.   0, 0,                /* minimum width and height */
  269.   0, 0,                /* maximum width and height */
  270.   WBENCHSCREEN            /* destination screen type */
  271. };
  272.  
  273. extern BPTR _Backstdout;    /* standard output when run in background */
  274. long _BackGroundIO = 1;        /* Flag to tell it we want to do I/O      */
  275. long _stack = 4000;        /* Amount of stack space our task needs   */
  276. char *_procname = "NewPop";    /* The name of the task to create         */
  277. long _priority = 20;        /* The priority to run us at              */
  278.  
  279. struct GLOBAL_DATA global;
  280. ULONG scsiDisp = 0;
  281. struct Task *child = NULL;
  282. struct ViewPort *blankVP = NULL;
  283. struct RastPort *blankRP = NULL;
  284. SHORT x[2], y[2], xd[2], yd[2], ox[2][16], oy[2][16];
  285. USHORT xlim, ylim, j;
  286.  
  287. /* * * * * * * * * * * PROTOTYPES * * * * * * * * * * * * */
  288. struct InputEvent *__saveds __asm myhandler (register __a0 struct InputEvent *);
  289. void createchild (void);
  290. void __saveds blankertask (void);
  291. void killchild (void);
  292. void __saveds scsifriendlosing (void);
  293. int ParseConfigFile (void);
  294. void _main (char *);
  295. void MemCleanup (void);
  296. int sprintf (char *, char *,...);
  297. int abs (int);
  298. long rand (void);
  299. void changecolor (void);
  300. void updatedisplay (void);
  301. void QueueTimer (struct timerequest *, ULONG);
  302. struct MsgPort *CreatePort (char *, long);
  303. void DeletePort (struct MsgPort *);
  304. struct IOStdReq *CreateIOReq (struct MsgPort *, int);
  305. void DeleteIOReq (struct IOStdReq *);
  306.  
  307.  
  308. /* * * * * * * * * * * OUR ROUTINES * * * * * * * * * * * */
  309. struct InputEvent *__saveds __asm 
  310. myhandler (register __a0 struct InputEvent * ev)
  311. {
  312.   struct InputEvent *ep, *laste;
  313.  
  314.   for (ep = ev, laste = NULL; ep != NULL; ep = ep->ie_NextEvent)
  315.     {
  316.       if ((ep->ie_Class == IECLASS_RAWKEY) &&
  317.       (ep->ie_Code == global.key) &&
  318.       (ep->ie_Qualifier & IEQUALIFIER_LCOMMAND) &&
  319.       (global.key))
  320.     {
  321.       if (laste == NULL)
  322.         ev = ep->ie_NextEvent;
  323.       else
  324.         laste->ie_NextEvent = ep->ie_NextEvent;
  325.       Signal (global.buddy, global.creatclisig);
  326.     }
  327.       else
  328.     laste = ep;
  329.  
  330.       if (ep->ie_Class == IECLASS_RAWMOUSE)
  331.     Signal (global.buddy, global.mousemovesig);
  332.  
  333.       if (ep->ie_Class != IECLASS_TIMER)
  334.     {
  335.       global.noevents = 0;
  336.       if (global.blankscreen)
  337.         Signal (global.buddy, global.unblanksig);
  338.     }
  339.     }
  340.   return (ev);
  341. }
  342.  
  343. void 
  344. createchild (void)
  345. {
  346.   child = CreateTask ("NewPopBlanker", BLANKERPRIORITY, (APTR) blankertask, 4000L);
  347. }
  348.  
  349. void __saveds 
  350. blankertask (void)
  351. {
  352.   struct MsgPort *timerport2;
  353.   struct timerequest *timerreq2 = NULL;
  354.  
  355.   if (timerport2 = CreatePort ("NewPopTimerPort2", 0))
  356.     if (timerreq2 = (struct timerequest *) CreateIOReq (timerport2, sizeof (struct timerequest)))
  357.       if (!(OpenDevice (TIMERNAME, UNIT_VBLANK, (struct IORequest *) timerreq2, 0)))
  358.     {
  359.       while (!(SetSignal (0L, 0L) & SIGBREAKF_CTRL_C))
  360.         {
  361.           updatedisplay ();
  362.           if (child->tc_Node.ln_Pri == 10)
  363.         SetTaskPri (child, BLANKERPRIORITY);
  364.           timerreq2->tr_node.io_Command = TR_ADDREQUEST;
  365.           timerreq2->tr_time.tv_secs = 0;
  366.           timerreq2->tr_time.tv_micro = 1000000 / 60;
  367.           DoIO ((struct IORequest *) timerreq2);
  368.         }
  369.     }
  370.       else
  371.     Wait (SIGBREAKF_CTRL_C);
  372.   if (timerreq2)
  373.     {
  374.       if (timerreq2->tr_node.io_Device)
  375.     CloseDevice ((struct IORequest *) timerreq2);
  376.       DeleteIOReq ((struct IOStdReq *) timerreq2);
  377.     }
  378.   if (timerport2)
  379.     DeletePort (timerport2);
  380.   Signal (global.buddy, SIGBREAKF_CTRL_D);
  381.   Wait (0L);
  382. }
  383.  
  384. void 
  385. killchild (void)
  386. {
  387.   Signal (child, SIGBREAKF_CTRL_C);
  388.   SetTaskPri (child, 20L);
  389.   Wait (SIGBREAKF_CTRL_D);
  390.   DeleteTask (child);
  391.   child = NULL;
  392. }
  393.  
  394. void __saveds 
  395. scsifriendlosing (void)
  396. {
  397.   scsiDisp++;
  398. }
  399.  
  400. int 
  401. ParseConfigFile (void)
  402. {
  403.   BPTR configFile;
  404. #define INPUTBUFFERSIZE 512
  405.   char buffer[INPUTBUFFERSIZE];
  406.   int bp;
  407.   int keyword;
  408. #define KEYWORDBUFFERSIZE 31
  409.   char keywordbuffer[KEYWORDBUFFERSIZE + 1];
  410.   int keywordbp;
  411.   int charinbuffer;
  412.   int state = 0;
  413.   int line = 1;
  414.   int i;
  415.   int neg;
  416.  
  417.   configFile = Open (".newpoprc", MODE_OLDFILE);
  418.   if (!configFile)
  419.     configFile = Open ("s:.newpoprc", MODE_OLDFILE);
  420.   if (!configFile)
  421.     return 0;
  422.  
  423.   while (charinbuffer = Read (configFile, buffer, INPUTBUFFERSIZE))
  424.     {
  425.       for (bp = 0; bp != charinbuffer; bp++)
  426.     {
  427.       switch (state)
  428.         {
  429.         case 0:
  430.           if (buffer[bp] == '#')
  431.         state = 1;
  432.           else if (buffer[bp] == '\n')
  433.         line++;
  434.           else if ((buffer[bp] <= 'z') && (buffer[bp] >= 'a'))
  435.         {
  436.           keywordbuffer[0] = buffer[bp] - 32;
  437.           keywordbp = 1;
  438.           state = 2;
  439.         }
  440.           else if ((buffer[bp] <= 'Z') && (buffer[bp] >= 'A'))
  441.         {
  442.           keywordbuffer[0] = buffer[bp];
  443.           keywordbp = 1;
  444.           state = 2;
  445.         }
  446.           else if ((buffer[bp] != ' ') && (buffer[bp] != '\t'))
  447.         {
  448.           state = 1;
  449.           goto out;
  450.         }
  451.           break;
  452.         case 1:
  453.           if (buffer[bp] == '\n')
  454.         {
  455.           line++;
  456.           state = 0;
  457.         }
  458.           break;
  459.         case 2:
  460.           if ((buffer[bp] <= 'z') && (buffer[bp] >= 'a'))
  461.         {
  462.           if (keywordbp >= KEYWORDBUFFERSIZE)
  463.             {
  464.               state = 1;
  465.               goto out;
  466.             }
  467.           keywordbuffer[keywordbp++] = buffer[bp] - 32;
  468.         }
  469.           else 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];
  477.         }
  478.           else if ((buffer[bp] <= '9') && (buffer[bp] >= '0'))
  479.         {
  480.           if (keywordbp >= KEYWORDBUFFERSIZE)
  481.             {
  482.               state = 1;
  483.               goto out;
  484.             }
  485.           keywordbuffer[keywordbp++] = buffer[bp];
  486.         }
  487.           else if ((buffer[bp] == ' ') || (buffer[bp] == '\t'))
  488.         {
  489.           keywordbuffer[keywordbp] = '\0';
  490.           for (i = 0; NewPopOptions[i].name; i++)
  491.             if (!strcmp (NewPopOptions[i].name, keywordbuffer))
  492.               break;
  493.           if (!NewPopOptions[i].name)
  494.             {
  495.               state = 1;
  496.               goto out;
  497.             }
  498.           keyword = i;
  499.           state = 3;
  500.         }
  501.           else
  502.         {
  503.           state = 1;
  504.           goto out;
  505.         }
  506.           break;
  507.         case 3:
  508.           if ((buffer[bp] != ' ') && (buffer[bp] != '\t'))
  509.         switch (NewPopOptions[keyword].type)
  510.           {
  511.           case boolean:
  512.             state = 4;
  513.             if ((buffer[bp] <= 'z') && (buffer[bp] >= 'a'))
  514.               {
  515.             keywordbuffer[0] = buffer[bp] - 32;
  516.             keywordbp = 1;
  517.               }
  518.             else if ((buffer[bp] <= 'Z') && (buffer[bp] >= 'A'))
  519.               {
  520.             keywordbuffer[0] = buffer[bp];
  521.             keywordbp = 1;
  522.               }
  523.             else
  524.               {
  525.             state = 1;
  526.             goto out;
  527.               }
  528.             break;
  529.           case integer:
  530.             state = 5;
  531.             neg = 0;
  532.             if (buffer[bp] == '-')
  533.               {
  534.             neg = 1;
  535.             NewPopOptions[keyword].value.ivalue = 0;
  536.               }
  537.             else if ((buffer[bp] <= '9') && (buffer[bp] >= '0'))
  538.               NewPopOptions[keyword].value.ivalue = buffer[bp] - '0';
  539.             else
  540.               {
  541.             state = 1;
  542.             goto out;
  543.               }
  544.             break;
  545.           case string:
  546.             state = 6;
  547.             if (buffer[bp] != '"')
  548.               {
  549.             state = 1;
  550.             goto out;
  551.               }
  552.             i = 0;
  553.             switch (keyword)
  554.               {
  555.               case 3:
  556.             NewPopOptions[3].value.svalue = NewTaskName;
  557.             break;
  558.               case 4:
  559.             NewPopOptions[4].value.svalue = NewFontName;
  560.             break;
  561.               case 5:
  562.             NewPopOptions[5].value.svalue = NewCmd;
  563.             break;
  564.               default:
  565.             state = 1;
  566.             goto out;
  567.               }
  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.       sprintf (buffer, "NewPop: parse error on line %d of .newpoprc\n", line);
  719.       if (_Backstdout)
  720.     Write (_Backstdout, buffer, strlen (buffer));
  721.       return 1;
  722.     }
  723.   return 0;
  724. }
  725.  
  726. void 
  727. _main (char *cmd)
  728. {
  729.   USHORT scsifriendinstalled = 0;
  730.   ULONG timersig, LIdle, LDisp;
  731.   BPTR nullfh = NULL;
  732.   USHORT stay = 0;
  733.   struct MsgPort *port;
  734.   struct MsgPort *timerport = NULL;
  735.   struct MsgPort *inputDevPort = NULL;
  736.   struct timerequest *timerreq = NULL;
  737.   struct IOStdReq *inputRequestBlock = NULL;
  738.   struct TextFont *textFont = NULL;
  739.   struct Task *scsifriend;
  740.   struct Interrupt handlerStuff;
  741.   struct Window *titlewindow = NULL;
  742.   struct RastPort *titleRP;
  743.   struct Screen *WBScreen;
  744.  
  745.   {
  746.     struct TextAttr textAttr =
  747.     {NULL, 0, 0, 0};
  748.     int quitflag = 0;
  749.  
  750.     global.creatsignum = -1;
  751.     global.mousemovenum = -1;
  752.     global.blanksignum = -1;
  753.     Forbid ();
  754.     if (!(port = FindPort (PORTNAME)))
  755.       {
  756.     stay = 1;
  757.     if (!(port = CreatePort (PORTNAME, 0)))
  758.       {
  759.         Permit ();
  760.         goto abort;
  761.       }
  762.       }
  763.     Permit ();
  764.     if (cmd && *cmd)
  765.       {
  766.     while (*cmd != ' ')
  767.       cmd++;
  768.     while (*cmd == ' ')
  769.       cmd++;
  770.     if ((cmd[0] == '-') && (cmd[1] == 'q') && (cmd[2] == '\n') && (!cmd[3]))
  771.       {
  772.         quitflag = 1;
  773.         if (_Backstdout)
  774.           Write (_Backstdout, KILLMSG, sizeof (KILLMSG));
  775.       }
  776.     else
  777.       {
  778.         if (_Backstdout)
  779.           Write (_Backstdout, BANNER, sizeof (BANNER));
  780.         if (ParseConfigFile ())
  781.           goto abort;
  782.       }
  783.       }
  784.     else
  785.       {
  786.     quitflag = !stay;
  787.     if (stay)
  788.       if (ParseConfigFile ())
  789.         goto abort;
  790.       }
  791.     textAttr.ta_Name = FONTNAME;
  792.     textAttr.ta_YSize = FONTSIZE;
  793.     global.blankscreen = NULL;
  794.     global.buddy = FindTask (0);
  795.     global.noevents = 0;
  796.     global.key = POPKEY;
  797.     if (quitflag)
  798.       Signal (port->mp_SigTask, SIGBREAKF_CTRL_C);
  799.     if (!stay)
  800.       goto abort;
  801.     if (_Backstdout)
  802.       Close (_Backstdout);
  803.     _Backstdout = NULL;
  804.     if (!(nullfh = Open ("NIL:", MODE_NEWFILE)))
  805.       goto abort;
  806.     if (!(inputDevPort = CreatePort ("NewPopInputPort", 0)))
  807.       goto abort;
  808.     if (!(inputRequestBlock = CreateIOReq (inputDevPort, sizeof (struct IOStdReq))))
  809.       goto abort;
  810.     if (!(timerport = CreatePort ("NewPopTimerPort", 0)))
  811.       goto abort;
  812.     if (!(timerreq = (struct timerequest *) CreateIOReq (timerport, sizeof (struct timerequest))))
  813.       goto abort;
  814.     if ((global.creatsignum = AllocSignal (-1)) == -1)
  815.       goto abort;
  816.     if ((global.blanksignum = AllocSignal (-1)) == -1)
  817.       goto abort;
  818.     if ((global.mousemovenum = AllocSignal (-1)) == -1)
  819.       goto abort;
  820.     if (!(GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", 0)))
  821.       goto abort;
  822.     if (!(LayersBase = (struct LayersBase *) OpenLibrary ("layers.library", 0)))
  823.       goto abort;
  824.     if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 0)))
  825.       goto abort;
  826.     if (!(DiskfontBase = (struct DiskfontBase *) OpenLibrary ("diskfont.library", 0)))
  827.       goto abort;
  828.     if (!(ExecBase = (struct ExecBase *) OpenLibrary ("exec.library", 0)))
  829.       goto abort;
  830.     if (OpenDevice (TIMERNAME, UNIT_VBLANK, (struct IORequest *) timerreq, 0))
  831.       goto abort;
  832.     if (OpenDevice ("input.device", 0, (struct IORequest *) inputRequestBlock, 0))
  833.       goto abort;
  834.     if (!NEWPOPLITE)
  835.       {
  836.     Forbid ();
  837.     if (WBScreen = (struct Screen *) OpenWorkBench ())
  838.       {
  839.         WindowWidth = SCSIIOMONWIDTH + GAPBETWEEN2 + CPULOADMONWIDTH +
  840.           GAPBETWEEN + MAXTEXTWIDTH;
  841.         WindowHeight = WINDOWHEIGHT;
  842.         NewWindow.LeftEdge = WBScreen->Width - 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.       }
  854.     Permit ();
  855.     if (!(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 (textFont = OpenFont (&textAttr))
  863.       {
  864.         if ((textFont->tf_YSize != FONTSIZE) || (textFont->tf_Style != 0))
  865.           {
  866.         CloseFont (textFont);
  867.         if (!(textFont = OpenDiskFont (&textAttr)))
  868.           goto abort;
  869.           }
  870.       }
  871.     else
  872.       {
  873.         if (!(textFont = OpenDiskFont (&textAttr)))
  874.           goto abort;
  875.       }
  876.     SetFont (titleRP, textFont);
  877.       }
  878.     handlerStuff.is_Data = (APTR) & global;
  879.     handlerStuff.is_Code = (VOID (*) ()) myhandler;
  880.     handlerStuff.is_Node.ln_Pri = 51;
  881.     timersig = (1 << timerport->mp_SigBit);
  882.     global.creatclisig = 1 << global.creatsignum;
  883.     global.unblanksig = 1 << global.blanksignum;
  884.     global.mousemovesig = 1 << global.mousemovenum;
  885.     inputRequestBlock->io_Command = IND_ADDHANDLER;
  886.     inputRequestBlock->io_Data = (APTR) & handlerStuff;
  887.     DoIO ((struct IORequest *) inputRequestBlock);
  888.     QueueTimer (timerreq, 1 /* 1/60th of a second */ );
  889.     if (!NEWPOPLITE)
  890.       {
  891.     Forbid ();
  892.     if (scsifriend = FindTask (SCSITASKNAME))
  893.       if (!(scsifriend->tc_Flags & TF_SWITCH))
  894.         {
  895.           scsifriend->tc_Switch = scsifriendlosing;
  896.           scsifriend->tc_Flags |= TF_SWITCH;
  897.           scsifriendinstalled = 1;
  898.         }
  899.     Permit ();
  900.     LIdle = ExecBase->IdleCount;
  901.     LDisp = ExecBase->DispCount;
  902.       }
  903.   }
  904.  
  905.   {
  906.     UWORD newsecond;
  907.     ULONG sig, Seconds, Micros, LastSeconds = 0;
  908.     SHORT instantblank = 0, defeatblank = 0;
  909.  
  910.     for (;;)
  911.       {
  912.     sig = Wait (global.creatclisig | global.unblanksig | timersig |
  913.             global.mousemovesig | SIGBREAKF_CTRL_C);
  914.  
  915.     if (sig & global.mousemovesig)
  916.       {
  917.         int left = IntuitionBase->MouseX < 10;
  918.         int right = (GfxBase->NormalDisplayColumns - IntuitionBase->MouseX) < 10;
  919.         int upper = IntuitionBase->MouseY < 10;
  920.         int lower = (GfxBase->NormalDisplayRows - IntuitionBase->MouseY / 2) < 10;
  921.  
  922.         instantblank = ((((ULC == 1) && upper) || ((LLC == 1) && lower)) && left) ||
  923.           ((((URC == 1) && upper) || ((LRC == 1) && lower)) && right);
  924.         defeatblank = ((((ULC == 2) && upper) || ((LLC == 2) && lower)) && left) ||
  925.           ((((URC == 2) && upper) || ((LRC == 2) && lower)) && right);
  926.       }
  927.  
  928.     CurrentTime (&Seconds, &Micros);
  929.     newsecond = (Seconds != LastSeconds);
  930.     LastSeconds = Seconds;
  931.  
  932.     if (newsecond && !NEWPOPLITE && !global.blankscreen)
  933.       {
  934.         SHORT x;
  935.         ULONG DIdle, DDisp, Usage;
  936.         long t;
  937.         struct tm *p;
  938.         char *timestr;
  939.  
  940.         UpfrontLayer (0L, titlewindow->WLayer);
  941.  
  942.         DIdle = ExecBase->IdleCount - LIdle;
  943.         DDisp = ExecBase->DispCount - LDisp;
  944.         LIdle = ExecBase->IdleCount;
  945.         LDisp = ExecBase->DispCount;
  946.         if (!DDisp)
  947.           DDisp++;
  948.  
  949.         x = 0;
  950.         if (scsifriendinstalled)
  951.           {
  952.         Usage = (scsiDisp * 256) / (DDisp + DIdle);
  953.         if (Usage > MAXSCSIUSAGE)
  954.           Usage = MAXSCSIUSAGE;
  955.         SetAPen (titleRP, 3);
  956.         ScrollRaster (titleRP, 1, 0, x, 0, x + SCSIIOMONWIDTH, (WindowHeight - 1));
  957.         x += SCSIIOMONWIDTH;
  958.         Move (titleRP, x, (WindowHeight - 1));
  959.         Draw (titleRP, x, WindowHeight - ((WindowHeight * Usage) / MAXSCSIUSAGE));
  960.         scsiDisp = 0;
  961.           }
  962.         else
  963.           x += SCSIIOMONWIDTH;
  964.  
  965.         /* There be magic below!  Where does 456 come from? :-) */
  966.         x += GAPBETWEEN2;
  967.         if (scsiDisp < DDisp)
  968.           Usage = ((DDisp - scsiDisp) * 456) / (DDisp + DIdle);
  969.         else
  970.           Usage = 0;
  971.         if (Usage < 200)
  972.           Usage = 0;
  973.         else
  974.           Usage = Usage - 200;
  975.         ScrollRaster (titleRP, 1, 0, x, 0, x + CPULOADMONWIDTH, (WindowHeight - 1));
  976.         x += CPULOADMONWIDTH;
  977.         SetAPen (titleRP, 2);
  978.         Move (titleRP, x, (WindowHeight - 1));
  979.         Draw (titleRP, x, WindowHeight - ((WindowHeight * Usage) / 256));
  980.  
  981.         x += GAPBETWEEN;
  982.         time (&t);
  983.         p = localtime (&t);
  984.         timestr = asctime (p);
  985.         Move (titleRP, x, STARTYOFFSET);
  986.         Text (titleRP, timestr, 24);
  987.  
  988.         x += TextLength (titleRP, timestr, 24);
  989.         SetAPen (titleRP, 1);
  990.         if (x < (WindowWidth - 1))
  991.           RectFill (titleRP, x, 0, (WindowWidth - 1), (WindowHeight - 1));
  992.       }
  993.  
  994.     if (global.blankscreen)
  995.       {
  996.         if (NICENEWPOP)
  997.           {
  998.         if (newsecond)
  999.           {
  1000.             changecolor ();
  1001.             SetTaskPri (child, 10);
  1002.           }
  1003.           }
  1004.         else
  1005.           {
  1006.         if (newsecond)
  1007.           changecolor ();
  1008.         updatedisplay ();
  1009.           }
  1010.       }
  1011.  
  1012.     if (sig & SIGBREAKF_CTRL_C)
  1013.       {
  1014.         goto abort;
  1015.       }
  1016.  
  1017.     if ((sig & global.unblanksig) &&global.blankscreen && !instantblank)
  1018.       {
  1019.         if (NICENEWPOP)
  1020.           killchild ();
  1021.         CloseScreen (global.blankscreen);
  1022.         global.blankscreen = NULL;
  1023.       }
  1024.  
  1025.     if (sig & global.creatclisig)
  1026.       {
  1027.         WBenchToFront ();
  1028.         (void) Execute (COMMAND, nullfh, nullfh);
  1029.       }
  1030.  
  1031.     if (sig & timersig)
  1032.       {
  1033.         GetMsg (timerport);
  1034.         if (global.blankscreen && NICENEWPOP)
  1035.           QueueTimer (timerreq, 60 /* One second */ );
  1036.         else
  1037.           QueueTimer (timerreq, 1 /* 1/60th of a second*/ );
  1038.         if ((instantblank || (global.noevents++ >= (TIMEOUT * 60))) && !global.blankscreen && !defeatblank)
  1039.           {
  1040.         NewScreen.Height = GfxBase->NormalDisplayRows * 2;
  1041.         NewScreen.Width = GfxBase->NormalDisplayColumns;
  1042.         if (global.blankscreen = OpenScreen (&NewScreen))
  1043.           {
  1044.             xlim = global.blankscreen->Width - 1;
  1045.             ylim = global.blankscreen->Height - 1;
  1046.             blankRP = &(global.blankscreen->RastPort);
  1047.             blankVP = &(global.blankscreen->ViewPort);
  1048.             changecolor ();
  1049.             SetRGB4 (blankVP, 0, 0, 0, 0);
  1050.             SetRGB4 (blankVP, 17, 0, 0, 0);
  1051.             SetRGB4 (blankVP, 18, 0, 0, 0);
  1052.             SetRGB4 (blankVP, 19, 0, 0, 0);
  1053.             SetDrMd (blankRP, JAM1);
  1054.             if (j == 0)
  1055.               {
  1056.             x[0] = rand () % xlim + 1;
  1057.             if ((x[1] = x[0] + rand () % (xlim / 6) - (xlim / 12)) > xlim)
  1058.               x[1] = xlim;
  1059.             if (x[1] < 0)
  1060.               x[1] = 0;
  1061.             y[0] = rand () % ylim + 1;
  1062.             if ((y[1] = y[0] + rand () % (ylim / 4) - (ylim / 8)) > ylim)
  1063.               y[1] = ylim;
  1064.             if (y[1] < 0)
  1065.               y[1] = 0;
  1066.             xd[0] = 11;
  1067.             yd[0] = 7;
  1068.             xd[1] = 3;
  1069.             yd[1] = 4;
  1070.               }
  1071.             if (NICENEWPOP)
  1072.               createchild ();
  1073.           }
  1074.           }
  1075.       }
  1076.  
  1077.     if (global.blankscreen)
  1078.       ScreenToFront (global.blankscreen);
  1079.       }
  1080.   }
  1081.  
  1082. abort:
  1083.   if (stay && port)
  1084.     DeletePort (port);
  1085.   if (stay && scsifriendinstalled && !NEWPOPLITE)
  1086.     {
  1087.       Forbid ();
  1088.       if (scsifriend = FindTask (SCSITASKNAME))
  1089.     if (scsifriend->tc_Switch == scsifriendlosing)
  1090.       {
  1091.         scsifriend->tc_Flags &= !TF_SWITCH;
  1092.         scsifriend->tc_Switch = NULL;
  1093.       }
  1094.       Permit ();
  1095.     }
  1096.   if (stay && titlewindow)
  1097.     CloseWindow (titlewindow);
  1098.   if (timerreq)
  1099.     {
  1100.       if (timerreq->tr_node.io_Device)
  1101.     CloseDevice ((struct IORequest *) timerreq);
  1102.       DeleteIOReq ((struct IOStdReq *) timerreq);
  1103.     }
  1104.   if (inputRequestBlock)
  1105.     {
  1106.       if (inputRequestBlock->io_Device)
  1107.     {
  1108.       inputRequestBlock->io_Command = IND_REMHANDLER;
  1109.       inputRequestBlock->io_Data = (APTR) & handlerStuff;
  1110.       DoIO ((struct IORequest *) inputRequestBlock);
  1111.       CloseDevice ((struct IORequest *) inputRequestBlock);
  1112.     }
  1113.       DeleteIOReq (inputRequestBlock);
  1114.     }
  1115.   if (textFont && !NEWPOPLITE)
  1116.     CloseFont (textFont);
  1117.   if (timerport)
  1118.     DeletePort (timerport);
  1119.   if (global.creatsignum != -1)
  1120.     FreeSignal (global.creatsignum);
  1121.   if (global.blanksignum != -1)
  1122.     FreeSignal (global.blanksignum);
  1123.   if (global.mousemovenum != -1)
  1124.     FreeSignal (global.mousemovenum);
  1125.   if (global.blankscreen)
  1126.     {
  1127.       if (NICENEWPOP)
  1128.     killchild ();
  1129.       CloseScreen (global.blankscreen);
  1130.     }
  1131.   if (IntuitionBase)
  1132.     CloseLibrary ((struct Library *) IntuitionBase);
  1133.   if (GfxBase)
  1134.     CloseLibrary ((struct Library *) GfxBase);
  1135.   if (LayersBase)
  1136.     CloseLibrary ((struct Library *) LayersBase);
  1137.   if (DiskfontBase)
  1138.     CloseLibrary ((struct Library *) DiskfontBase);
  1139.   if (ExecBase)
  1140.     CloseLibrary ((struct Library *) ExecBase);
  1141.   if (inputDevPort)
  1142.     DeletePort (inputDevPort);
  1143.   if (_Backstdout)
  1144.     Close (_Backstdout);
  1145.   if (nullfh)
  1146.     Close (nullfh);
  1147. }
  1148.  
  1149. void 
  1150. changecolor (void)
  1151. {
  1152.   static struct color currentcolor =
  1153.   {15, 0, 5}, colordelta =
  1154.   {-1, 1, 1};
  1155.  
  1156.   switch (rand () % 3)
  1157.     {
  1158.     case 0:
  1159.       currentcolor.red += colordelta.red;
  1160.       if (currentcolor.red == 0 ||
  1161.       currentcolor.red == 15)
  1162.     colordelta.red = -colordelta.red;
  1163.       break;
  1164.     case 1:
  1165.       currentcolor.green += colordelta.green;
  1166.       if (currentcolor.green == 0 ||
  1167.       currentcolor.green == 15)
  1168.     colordelta.green = -colordelta.green;
  1169.       break;
  1170.     case 2:
  1171.       currentcolor.blue += colordelta.blue;
  1172.       if (currentcolor.blue == 0 ||
  1173.       currentcolor.blue == 15)
  1174.     colordelta.blue = -colordelta.blue;
  1175.       break;
  1176.     }
  1177.   SetRGB4 (blankVP, 1, currentcolor.red, currentcolor.green, currentcolor.blue);
  1178. }
  1179.  
  1180. void 
  1181. updatedisplay (void)
  1182. {
  1183.   SHORT i, k;
  1184.  
  1185.   SetAPen (blankRP, 0);
  1186.   Move (blankRP, ox[0][j & 15], oy[0][j & 15]);
  1187.   Draw (blankRP, ox[1][j & 15], oy[1][j & 15]);
  1188.   SetAPen (blankRP, 1);
  1189.   Move (blankRP, x[0], y[0]);
  1190.   Draw (blankRP, x[1], y[1]);
  1191.   for (i = 0; i < 2; i++)
  1192.     {
  1193.       ox[i][j & 15] = x[i];
  1194.       oy[i][j & 15] = y[i];
  1195.       x[i] += xd[i];
  1196.       y[i] += yd[i];
  1197.       if (abs (x[1] - x[0]) > xlim / 4)
  1198.     {
  1199.       x[i] -= xd[i] * 4 / 3;
  1200.       xd[i] = -xd[i] / 2;
  1201.     }
  1202.       if (abs (y[1] - y[0]) > ylim / 3)
  1203.     {
  1204.       y[i] -= yd[i] * 4 / 3;
  1205.       yd[i] = -yd[i] / 2;
  1206.     }
  1207.       if (x[i] < 0)
  1208.     {
  1209.       x[i] = 0;
  1210.       xd[i] = -xd[i];
  1211.     }
  1212.       else if (x[i] > xlim)
  1213.     {
  1214.       x[i] = xlim;
  1215.       xd[i] = -xd[i];
  1216.     }
  1217.       if (y[i] < 0)
  1218.     {
  1219.       y[i] = 0;
  1220.       yd[i] = -yd[i];
  1221.     }
  1222.       else if (y[i] > ylim)
  1223.     {
  1224.       y[i] = ylim;
  1225.       yd[i] = -yd[i];
  1226.     }
  1227.       if (((rand () >> 5) & 127) < 2)
  1228.     {
  1229.       if (xd[i] < 1)
  1230.         k = 1;
  1231.       xd[i] = (rand () >> 5) & 7;
  1232.       if (k == (1 - i))
  1233.         xd[i] = -xd[i];
  1234.       k = 0;
  1235.     }
  1236.       if (((rand () >> 5) & 255) < 50)
  1237.     {
  1238.       if (yd[i] < 1)
  1239.         k = 1;
  1240.       yd[i] = (rand () >> 5) & 7;
  1241.       if (k == (1 - i))
  1242.         yd[i] = -yd[i];
  1243.       k = 0;
  1244.     }
  1245.     }
  1246.   ++j;
  1247. }
  1248.  
  1249. void 
  1250. MemCleanup (void)
  1251. {
  1252. }
  1253.  
  1254. void 
  1255. QueueTimer (struct timerequest * tr, ULONG ticks)
  1256. {
  1257.   tr->tr_node.io_Command = TR_ADDREQUEST;
  1258.   tr->tr_time.tv_secs = ticks / 60;
  1259.   tr->tr_time.tv_micro = (ticks % 60) * 1000000 / 60;
  1260.   SendIO ((struct IORequest *) tr);
  1261. }
  1262.  
  1263. struct MsgPort *
  1264. CreatePort (char *name, long pri)
  1265. {
  1266.   UBYTE sigbit;
  1267.   register struct MsgPort *port;
  1268.  
  1269.   if ((sigbit = AllocSignal (-1)) == -1)
  1270.     return ((struct MsgPort *) 0);
  1271.   if (!(port = (struct MsgPort *) AllocMem (sizeof (struct MsgPort), MEMF_CLEAR | MEMF_PUBLIC)))
  1272.     {
  1273.       FreeSignal (sigbit);
  1274.       return ((struct MsgPort *) 0);
  1275.     }
  1276.   port->mp_Node.ln_Name = name;
  1277.   port->mp_Node.ln_Pri = pri;
  1278.   port->mp_Node.ln_Type = NT_MSGPORT;
  1279.   port->mp_Flags = PA_SIGNAL;
  1280.   port->mp_SigBit = sigbit;
  1281.   port->mp_SigTask = (struct Task *) FindTask (0);
  1282.   if (name)
  1283.     AddPort (port);
  1284.   return (port);
  1285. }
  1286.  
  1287. void 
  1288. DeletePort (struct MsgPort * port)
  1289. {
  1290.   if (port->mp_Node.ln_Name)
  1291.     RemPort (port);
  1292.   FreeSignal (port->mp_SigBit);
  1293.   FreeMem ((char *) port, sizeof (struct MsgPort));
  1294. }
  1295.  
  1296. struct IOStdReq *
  1297. CreateIOReq (struct MsgPort * port, int size)
  1298. {
  1299.   struct IOStdReq *ioReq;
  1300.  
  1301.   if (ioReq = (struct IOStdReq *) AllocMem (size, MEMF_CLEAR | MEMF_PUBLIC))
  1302.     {
  1303.       ioReq->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  1304.       ioReq->io_Message.mn_Node.ln_Pri = 0;
  1305.       ioReq->io_Message.mn_Length = size;
  1306.       ioReq->io_Message.mn_ReplyPort = port;
  1307.     }
  1308.   return (ioReq);
  1309. }
  1310.  
  1311. void 
  1312. DeleteIOReq (struct IOStdReq * ioReq)
  1313. {
  1314.   ioReq->io_Message.mn_Node.ln_Type = 0xff;
  1315.   ioReq->io_Device = (struct Device *) - 1;
  1316.   ioReq->io_Unit = (struct Unit *) - 1;
  1317.   FreeMem ((char *) ioReq, ioReq->io_Message.mn_Length);
  1318. }
  1319.