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 >
Wrap
C/C++ Source or Header
|
1991-04-08
|
36KB
|
1,319 lines
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* |_o_o|\\ Copyright (c) 1986 The Software Distillery. All Rights Reserved */
/* |. o.| || This program may not be distributed without the permission of */
/* | . | || the authors. */
/* | o | || Dave Baker Ed Burnette Stan Chow Jay Denebeim */
/* | . |// Gordon Keener Jack Rouse John Toebes Doug Walker */
/* ====== BBS:(919)-471-6436 VOICE:(919)-469-4210 */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* VERY loosely based on the input.device example by Rob Peck, 12/1/85
*
*
* Additions and modifications Copyright (c) 1989, 1990, 1991 Loren J. Rittle
* Modifications Copyright (c) 1990 Ed A. Hutchins and Loren J. Rittle
*
* As stated in the original POPCLI documentation file:
*
* Permission is hereby granted to distribute this program provided
* both the documentation accompanies the executable and that no
* charge is made for its distribution.
* I assume that this statement includes the right to modify the source
* and futher distribute the modified work under this same agreement. - LJR
* (Actually, at this point, 'diff newpop.c popcli3.c | wc'
* > 'wc -c newpop.c' + 'wc -c popcli3.c'. :-)
*
*
* Note: Some code to do the Q*X pattern lifted (and modified) from:
* Line drawing demo for the Commodore/Amiga
* Written by John Riley, Lattice, Inc.
*
* Note: The spawning of a lower priority task to do graphics
* was inspired by Mackie to some degree (and by
* one person who claimed that NewPop slowed down
* HST modem transfers! I think that they were
* on a non-A3000 class machine :-) Later, I got
* a report that it also happened on an A3000! :-(
* See NICENEWPOP in `[s:].newpoprc'.
*
* UpfrontLayer is used instead of WindowToFront() because of
* a WorkBench/INTUITION bug. From dmouse.doc:
*
* WORKBENCH USERS!!!!!!!!!! There appears to be a bug in
* intuition's WindowToFront() call, which can lock up
* intuition when workbench icons are active. Under the
* defaults, this will occur whenever you depress the left
* mouse button over an icon.
*
* Thanks to Matt Dillon for showing the work around
* in DMouse's source code.
*
* LJR added the titlebar clock sometime in 1988 or early 1989.
* LJR added the Q*X pattern sometime in 1988 or early 1989.
* LJR added the auto- and defeat- blanking in 1988 or early 1989.
* EAH and LJR added color to the Q*X sometime in late 1989.
* EAH and LJR added the titlebar PrefMon around 1/18/90.
* LJR improved the titlebar PrefMon on 2/8/90.
* LJR added the titlebar disk I/O PrefMon on 2/8/90.
* LJR reworked the way the titlebar stuff renders into
* the `titlebar', now implemented with a backdrop window
* positioned over the titlebar on 12/20/90.
* LJR reworked all of newpop to be a bit more system independent
* on 12/30/90.
* LJR reworked Q*X code to spawn a new task on 1/13/91.
* LJR reworked parts of newpop to be a bit more explicit
* in declaring which registers arguments *MUST* be passed
* in (mainly for the event handler). Also switched back
* to '-b1' and we now use __saveds on functions that need
* to load A4. This saves a few hundred bytes. 1/18/91.
* LJR got rid of all _enforcer_ hits NewPop was causing.
* The strange thing is that they were all happening in
* ROM code because my message ports had no names and had
* not been added to the system's port list. I now name
* and add to the system's list all message ports. Not
* only was this a bitch to track down, but it should
* also be legal! If anyone can comment on this, send me
* mail at `l-rittle@uiuc.edu'. 1/19/91.
* LJR recoded the entire thing to allow dynamic (at startup
* time) configuration instead of hardcoded compile time
* configuration. This added many, many bytes! Why did I
* do it? Because my public asked for it, will I ever get
* a pizza out of this deal? YOW 1/27/91.
* LJR added URC, LRC, LLC, ULC options to allow the user
* to decide what NewPop should do when the pointer enters
* the given screen corner. Also, changed the method
* by which a running NewPop is told to halt. 2/1/91
* LJR modified the method used to shut down a running
* NewPop: Signal(NewPopTask, SIGBREAKF_CTRL_C) is now the
* way to kill it, instead of a custom message with the quit
* flag set. 2/1/91
* LJR cleaned up one last time for first UseNet release. 3/16/91
*/
/* * * * * * * * * * * INCLUDES * * * * * * * * * * * * */
#include <exec/types.h>
#include <exec/exec.h>
#include <exec/execbase.h>
#include <exec/tasks.h>
#include <devices/timer.h>
#include <devices/input.h>
#include <devices/inputevent.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <libraries/dos.h>
#include <graphics/gfxmacros.h>
#include <graphics/layers.h>
#include <graphics/gfxbase.h>
#include <hardware/custom.h>
#include <hardware/dmabits.h>
#include <graphics/text.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/layers.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/diskfont.h>
#include <string.h>
#include <time.h>
/* * * * * * * * * * * CONSTANTS * * * * * * * * * * * * */
#define PORTNAME "NewPop.port"
/* The name of our well known *PRIVATE* message port */
#define MAXCMD 200
#define MAXTASKNAME 32
#define MAXFONTNAME 32
/* Maximum string size of various things */
#define KILLMSG "\x9B" "0;33mNewPop\x9B" "0m Terminating\n"
/* The kill message */
#define BANNER "\x9B" "0;33mNewPop\x9B" "0m v3.2 by Loren J. Rittle - Copyright \xA9 1989 - 1991 Based upon:\n" \
"\x9B" "0;33mPOPCLI III\x9B" "0m by John Toebes - Copyright \xA9 1987 The Software Distillery\n"
/* The hello banner */
/* * * * * * * * * * * * * * * * TYPES * * * * * * * * * * * * * */
struct GLOBAL_DATA
{
struct Task *buddy;
ULONG creatclisig;
ULONG unblanksig;
ULONG mousemovesig;
ULONG noevents;
short creatsignum;
short blanksignum;
short mousemovenum;
short key;
struct Screen *blankscreen;
};
struct color
{
int red, green, blue;
};
enum OptionTypes
{
boolean, integer, string
};
struct NewPopOption
{
char *name;
enum OptionTypes type;
union
{
int ivalue;
char *svalue;
} value;
int min, max;
};
/* * * * * * * * * * * EXTERNALS AND GLOBAL DATA * * * * * * * * */
/*
* See .newpoprc for the meanings of these options!
*/
struct NewPopOption NewPopOptions[] =
{
#define NICENEWPOP (NewPopOptions[0].value.ivalue)
{"NICENEWPOP", boolean, 1, 0, 1},
#define NEWPOPLITE (NewPopOptions[1].value.ivalue)
{"NEWPOPLITE", boolean, 0, 0, 1},
#define WEWANTWINDOWDRAG (NewPopOptions[2].value.ivalue)
{"WEWANTWINDOWDRAG", boolean, 0, 0, 1},
#define SCSITASKNAME (NewPopOptions[3].value.svalue)
{"SCSITASKNAME", string, (int) "gvpscsi.device", 0, MAXTASKNAME},
#define FONTNAME (NewPopOptions[4].value.svalue)
{"FONTNAME", string, (int) "Helvetica.font", 0, MAXFONTNAME},
#define COMMAND (NewPopOptions[5].value.svalue)
#ifndef LJR_FAVORITE
{"COMMAND", string, (int) "NEWCLI >NIL:", 0, MAXCMD},
#else
{"COMMAND", string, (int) "NewWSH <nil: >nil: cnn:0/11/640/189/WShell/c", 0, MAXCMD},
#endif
#define MAXSCSIUSAGE (NewPopOptions[6].value.ivalue)
{"MAXSCSIUSAGE", integer, 55, 20, 255},
#define SCSIIOMONWIDTH (NewPopOptions[7].value.ivalue)
{"SCSIIOMONWIDTH", integer, 100, 0, 100},
#define CPULOADMONWIDTH (NewPopOptions[8].value.ivalue)
{"CPULOADMONWIDTH", integer, 100, 0, 100},
#define GAPBETWEEN2 (NewPopOptions[9].value.ivalue)
{"GAPBETWEEN2", integer, 16, 0, 32},
#define GAPBETWEEN (NewPopOptions[10].value.ivalue)
{"GAPBETWEEN", integer, 16, 0, 32},
#define FONTSIZE (NewPopOptions[11].value.ivalue)
{"FONTSIZE", integer, 9, 4, 56},
#define STARTYOFFSET (NewPopOptions[12].value.ivalue)
{"STARTYOFFSET", integer, 7, 2, 60},
#define MAXTEXTWIDTH (NewPopOptions[13].value.ivalue)
{"MAXTEXTWIDTH", integer, 107, 10, 300},
#define STARTXOFFSET (NewPopOptions[14].value.ivalue)
{"STARTXOFFSET", integer, 56, 10, 200},
#define WINDOWHEIGHT (NewPopOptions[15].value.ivalue)
{"WINDOWHEIGHT", integer, 8, 4, 56},
#define TIMEOUT (NewPopOptions[16].value.ivalue)
{"TIMEOUT", integer, 180, 0, 0x00ffffff},
#define POPKEY (NewPopOptions[17].value.ivalue)
{"POPKEY", integer, 69, 0, 255},
#define BLANKERPRIORITY (NewPopOptions[18].value.ivalue)
{"BLANKERPRIORITY", integer, -20, -20, 10},
#define ULC (NewPopOptions[19].value.ivalue)
{"ULC", integer, 0, 0, 2},
#define URC (NewPopOptions[20].value.ivalue)
{"URC", integer, 1, 0, 2},
#define LLC (NewPopOptions[21].value.ivalue)
{"LLC", integer, 0, 0, 2},
#define LRC (NewPopOptions[22].value.ivalue)
{"LRC", integer, 2, 0, 2},
/* Add new enties before this line! */
{NULL, boolean, 0, 0, 0}
};
char NewFontName[MAXFONTNAME];
char NewTaskName[MAXTASKNAME];
char NewCmd[MAXCMD];
struct IntuitionBase *IntuitionBase;
struct LayersBase *LayersBase;
struct GfxBase *GfxBase;
struct DiskfontBase *DiskfontBase;
struct DosLibrary *DosBase;
struct ExecBase *ExecBase;
struct NewScreen NewScreen =
{0, 0, 640, 400, 1, 0, 1, HIRES | LACE, SCREENQUIET | CUSTOMSCREEN, NULL, NULL, NULL, NULL};
int WindowWidth, WindowHeight;
struct Gadget WDragGadget =
{NULL, 0, 0, 0, 0, GADGHNONE, NULL, WDRAGGING, NULL, NULL, NULL, NULL, NULL, 0, 0};
struct NewWindow NewWindow =
{
0, 0, /* window XY origin relative to TopLeft of screen. Set later. */
0, 0, /* window width and height */
2, 1, /* detail and block pens */
0, /* IDCMP flags */
BACKDROP + BORDERLESS + NOCAREREFRESH, /* other window flags */
&WDragGadget, /* first gadget in gadget list */
NULL, /* custom CHECKMARK imagery */
NULL, /* window title */
NULL, /* custom screen pointer */
NULL, /* custom bitmap */
0, 0, /* minimum width and height */
0, 0, /* maximum width and height */
WBENCHSCREEN /* destination screen type */
};
extern BPTR _Backstdout; /* standard output when run in background */
long _BackGroundIO = 1; /* Flag to tell it we want to do I/O */
long _stack = 4000; /* Amount of stack space our task needs */
char *_procname = "NewPop"; /* The name of the task to create */
long _priority = 20; /* The priority to run us at */
struct GLOBAL_DATA global;
ULONG scsiDisp = 0;
struct Task *child = NULL;
struct ViewPort *blankVP = NULL;
struct RastPort *blankRP = NULL;
SHORT x[2], y[2], xd[2], yd[2], ox[2][16], oy[2][16];
USHORT xlim, ylim, j;
/* * * * * * * * * * * PROTOTYPES * * * * * * * * * * * * */
struct InputEvent *__saveds __asm myhandler (register __a0 struct InputEvent *);
void createchild (void);
void __saveds blankertask (void);
void killchild (void);
void __saveds scsifriendlosing (void);
int ParseConfigFile (void);
void _main (char *);
void MemCleanup (void);
int sprintf (char *, char *,...);
int abs (int);
long rand (void);
void changecolor (void);
void updatedisplay (void);
void QueueTimer (struct timerequest *, ULONG);
struct MsgPort *CreatePort (char *, long);
void DeletePort (struct MsgPort *);
struct IOStdReq *CreateIOReq (struct MsgPort *, int);
void DeleteIOReq (struct IOStdReq *);
/* * * * * * * * * * * OUR ROUTINES * * * * * * * * * * * */
struct InputEvent *__saveds __asm
myhandler (register __a0 struct InputEvent * ev)
{
struct InputEvent *ep, *laste;
for (ep = ev, laste = NULL; ep != NULL; ep = ep->ie_NextEvent)
{
if ((ep->ie_Class == IECLASS_RAWKEY) &&
(ep->ie_Code == global.key) &&
(ep->ie_Qualifier & IEQUALIFIER_LCOMMAND) &&
(global.key))
{
if (laste == NULL)
ev = ep->ie_NextEvent;
else
laste->ie_NextEvent = ep->ie_NextEvent;
Signal (global.buddy, global.creatclisig);
}
else
laste = ep;
if (ep->ie_Class == IECLASS_RAWMOUSE)
Signal (global.buddy, global.mousemovesig);
if (ep->ie_Class != IECLASS_TIMER)
{
global.noevents = 0;
if (global.blankscreen)
Signal (global.buddy, global.unblanksig);
}
}
return (ev);
}
void
createchild (void)
{
child = CreateTask ("NewPopBlanker", BLANKERPRIORITY, (APTR) blankertask, 4000L);
}
void __saveds
blankertask (void)
{
struct MsgPort *timerport2;
struct timerequest *timerreq2 = NULL;
if (timerport2 = CreatePort ("NewPopTimerPort2", 0))
if (timerreq2 = (struct timerequest *) CreateIOReq (timerport2, sizeof (struct timerequest)))
if (!(OpenDevice (TIMERNAME, UNIT_VBLANK, (struct IORequest *) timerreq2, 0)))
{
while (!(SetSignal (0L, 0L) & SIGBREAKF_CTRL_C))
{
updatedisplay ();
if (child->tc_Node.ln_Pri == 10)
SetTaskPri (child, BLANKERPRIORITY);
timerreq2->tr_node.io_Command = TR_ADDREQUEST;
timerreq2->tr_time.tv_secs = 0;
timerreq2->tr_time.tv_micro = 1000000 / 60;
DoIO ((struct IORequest *) timerreq2);
}
}
else
Wait (SIGBREAKF_CTRL_C);
if (timerreq2)
{
if (timerreq2->tr_node.io_Device)
CloseDevice ((struct IORequest *) timerreq2);
DeleteIOReq ((struct IOStdReq *) timerreq2);
}
if (timerport2)
DeletePort (timerport2);
Signal (global.buddy, SIGBREAKF_CTRL_D);
Wait (0L);
}
void
killchild (void)
{
Signal (child, SIGBREAKF_CTRL_C);
SetTaskPri (child, 20L);
Wait (SIGBREAKF_CTRL_D);
DeleteTask (child);
child = NULL;
}
void __saveds
scsifriendlosing (void)
{
scsiDisp++;
}
int
ParseConfigFile (void)
{
BPTR configFile;
#define INPUTBUFFERSIZE 512
char buffer[INPUTBUFFERSIZE];
int bp;
int keyword;
#define KEYWORDBUFFERSIZE 31
char keywordbuffer[KEYWORDBUFFERSIZE + 1];
int keywordbp;
int charinbuffer;
int state = 0;
int line = 1;
int i;
int neg;
configFile = Open (".newpoprc", MODE_OLDFILE);
if (!configFile)
configFile = Open ("s:.newpoprc", MODE_OLDFILE);
if (!configFile)
return 0;
while (charinbuffer = Read (configFile, buffer, INPUTBUFFERSIZE))
{
for (bp = 0; bp != charinbuffer; bp++)
{
switch (state)
{
case 0:
if (buffer[bp] == '#')
state = 1;
else if (buffer[bp] == '\n')
line++;
else if ((buffer[bp] <= 'z') && (buffer[bp] >= 'a'))
{
keywordbuffer[0] = buffer[bp] - 32;
keywordbp = 1;
state = 2;
}
else if ((buffer[bp] <= 'Z') && (buffer[bp] >= 'A'))
{
keywordbuffer[0] = buffer[bp];
keywordbp = 1;
state = 2;
}
else if ((buffer[bp] != ' ') && (buffer[bp] != '\t'))
{
state = 1;
goto out;
}
break;
case 1:
if (buffer[bp] == '\n')
{
line++;
state = 0;
}
break;
case 2:
if ((buffer[bp] <= 'z') && (buffer[bp] >= 'a'))
{
if (keywordbp >= KEYWORDBUFFERSIZE)
{
state = 1;
goto out;
}
keywordbuffer[keywordbp++] = buffer[bp] - 32;
}
else if ((buffer[bp] <= 'Z') && (buffer[bp] >= 'A'))
{
if (keywordbp >= KEYWORDBUFFERSIZE)
{
state = 1;
goto out;
}
keywordbuffer[keywordbp++] = buffer[bp];
}
else if ((buffer[bp] <= '9') && (buffer[bp] >= '0'))
{
if (keywordbp >= KEYWORDBUFFERSIZE)
{
state = 1;
goto out;
}
keywordbuffer[keywordbp++] = buffer[bp];
}
else if ((buffer[bp] == ' ') || (buffer[bp] == '\t'))
{
keywordbuffer[keywordbp] = '\0';
for (i = 0; NewPopOptions[i].name; i++)
if (!strcmp (NewPopOptions[i].name, keywordbuffer))
break;
if (!NewPopOptions[i].name)
{
state = 1;
goto out;
}
keyword = i;
state = 3;
}
else
{
state = 1;
goto out;
}
break;
case 3:
if ((buffer[bp] != ' ') && (buffer[bp] != '\t'))
switch (NewPopOptions[keyword].type)
{
case boolean:
state = 4;
if ((buffer[bp] <= 'z') && (buffer[bp] >= 'a'))
{
keywordbuffer[0] = buffer[bp] - 32;
keywordbp = 1;
}
else if ((buffer[bp] <= 'Z') && (buffer[bp] >= 'A'))
{
keywordbuffer[0] = buffer[bp];
keywordbp = 1;
}
else
{
state = 1;
goto out;
}
break;
case integer:
state = 5;
neg = 0;
if (buffer[bp] == '-')
{
neg = 1;
NewPopOptions[keyword].value.ivalue = 0;
}
else if ((buffer[bp] <= '9') && (buffer[bp] >= '0'))
NewPopOptions[keyword].value.ivalue = buffer[bp] - '0';
else
{
state = 1;
goto out;
}
break;
case string:
state = 6;
if (buffer[bp] != '"')
{
state = 1;
goto out;
}
i = 0;
switch (keyword)
{
case 3:
NewPopOptions[3].value.svalue = NewTaskName;
break;
case 4:
NewPopOptions[4].value.svalue = NewFontName;
break;
case 5:
NewPopOptions[5].value.svalue = NewCmd;
break;
default:
state = 1;
goto out;
}
break;
}
break;
case 4:
if ((buffer[bp] <= 'z') && (buffer[bp] >= 'a'))
{
if (keywordbp >= KEYWORDBUFFERSIZE)
{
state = 1;
goto out;
}
keywordbuffer[keywordbp++] = buffer[bp] - 32;
}
else if ((buffer[bp] <= 'Z') && (buffer[bp] >= 'A'))
{
if (keywordbp >= KEYWORDBUFFERSIZE)
{
state = 1;
goto out;
}
keywordbuffer[keywordbp++] = buffer[bp];
}
else if ((buffer[bp] == ' ') || (buffer[bp] == '\t') || (buffer[bp] == '\n'))
{
keywordbuffer[keywordbp] = '\0';
NewPopOptions[i].value.ivalue = 2;
if (!strcmp ("TRUE", keywordbuffer))
NewPopOptions[i].value.ivalue = 1;
if (!strcmp ("FALSE", keywordbuffer))
NewPopOptions[i].value.ivalue = 0;
if (!strcmp ("ON", keywordbuffer))
NewPopOptions[i].value.ivalue = 1;
if (!strcmp ("OFF", keywordbuffer))
NewPopOptions[i].value.ivalue = 0;
if (NewPopOptions[i].value.ivalue == 2)
{
state = 1;
goto out;
}
if (buffer[bp] == '\n')
{
line++;
state = 0;
}
else
state = 7;
}
else
{
state = 1;
goto out;
}
break;
case 5:
if (buffer[bp] == '\n')
{
if (neg)
NewPopOptions[keyword].value.ivalue *= -1;
if (NewPopOptions[keyword].value.ivalue > NewPopOptions[keyword].max)
{
state = 1;
goto out;
}
if (NewPopOptions[keyword].value.ivalue < NewPopOptions[keyword].min)
{
state = 1;
goto out;
}
line++;
state = 0;
}
else if ((buffer[bp] == ' ') || (buffer[bp] == '\t'))
{
if (neg)
NewPopOptions[keyword].value.ivalue *= -1;
if (NewPopOptions[keyword].value.ivalue > NewPopOptions[keyword].max)
{
state = 1;
goto out;
}
if (NewPopOptions[keyword].value.ivalue < NewPopOptions[keyword].min)
{
state = 1;
goto out;
}
state = 7;
}
else if ((buffer[bp] <= '9') && (buffer[bp] >= '0'))
{
NewPopOptions[keyword].value.ivalue *= 10;
NewPopOptions[keyword].value.ivalue += buffer[bp] - '0';
}
else
{
state = 1;
goto out;
}
break;
case 6:
if ((buffer[bp] == '\n') || (i >= NewPopOptions[keyword].max))
{
state = 1;
goto out;
}
NewPopOptions[keyword].value.svalue[i++] = buffer[bp];
if (buffer[bp] == '"')
{
NewPopOptions[keyword].value.svalue[--i] = '\0';
state = 8;
}
break;
case 7:
if (buffer[bp] == '#')
state = 1;
else if (buffer[bp] == '\n')
{
line++;
state = 0;
}
else if ((buffer[bp] != ' ') && (buffer[bp] != '\t'))
{
state = 1;
goto out;
}
break;
case 8:
if (buffer[bp] == '\n')
{
line++;
state = 0;
}
else if ((buffer[bp] != ' ') && (buffer[bp] != '\t'))
{
state = 1;
goto out;
}
else
state = 7;
break;
default:
state = 1;
goto out;
}
}
}
out:
Close (configFile);
if (state)
{
sprintf (buffer, "NewPop: parse error on line %d of .newpoprc\n", line);
if (_Backstdout)
Write (_Backstdout, buffer, strlen (buffer));
return 1;
}
return 0;
}
void
_main (char *cmd)
{
USHORT scsifriendinstalled = 0;
ULONG timersig, LIdle, LDisp;
BPTR nullfh = NULL;
USHORT stay = 0;
struct MsgPort *port;
struct MsgPort *timerport = NULL;
struct MsgPort *inputDevPort = NULL;
struct timerequest *timerreq = NULL;
struct IOStdReq *inputRequestBlock = NULL;
struct TextFont *textFont = NULL;
struct Task *scsifriend;
struct Interrupt handlerStuff;
struct Window *titlewindow = NULL;
struct RastPort *titleRP;
struct Screen *WBScreen;
{
struct TextAttr textAttr =
{NULL, 0, 0, 0};
int quitflag = 0;
global.creatsignum = -1;
global.mousemovenum = -1;
global.blanksignum = -1;
Forbid ();
if (!(port = FindPort (PORTNAME)))
{
stay = 1;
if (!(port = CreatePort (PORTNAME, 0)))
{
Permit ();
goto abort;
}
}
Permit ();
if (cmd && *cmd)
{
while (*cmd != ' ')
cmd++;
while (*cmd == ' ')
cmd++;
if ((cmd[0] == '-') && (cmd[1] == 'q') && (cmd[2] == '\n') && (!cmd[3]))
{
quitflag = 1;
if (_Backstdout)
Write (_Backstdout, KILLMSG, sizeof (KILLMSG));
}
else
{
if (_Backstdout)
Write (_Backstdout, BANNER, sizeof (BANNER));
if (ParseConfigFile ())
goto abort;
}
}
else
{
quitflag = !stay;
if (stay)
if (ParseConfigFile ())
goto abort;
}
textAttr.ta_Name = FONTNAME;
textAttr.ta_YSize = FONTSIZE;
global.blankscreen = NULL;
global.buddy = FindTask (0);
global.noevents = 0;
global.key = POPKEY;
if (quitflag)
Signal (port->mp_SigTask, SIGBREAKF_CTRL_C);
if (!stay)
goto abort;
if (_Backstdout)
Close (_Backstdout);
_Backstdout = NULL;
if (!(nullfh = Open ("NIL:", MODE_NEWFILE)))
goto abort;
if (!(inputDevPort = CreatePort ("NewPopInputPort", 0)))
goto abort;
if (!(inputRequestBlock = CreateIOReq (inputDevPort, sizeof (struct IOStdReq))))
goto abort;
if (!(timerport = CreatePort ("NewPopTimerPort", 0)))
goto abort;
if (!(timerreq = (struct timerequest *) CreateIOReq (timerport, sizeof (struct timerequest))))
goto abort;
if ((global.creatsignum = AllocSignal (-1)) == -1)
goto abort;
if ((global.blanksignum = AllocSignal (-1)) == -1)
goto abort;
if ((global.mousemovenum = AllocSignal (-1)) == -1)
goto abort;
if (!(GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", 0)))
goto abort;
if (!(LayersBase = (struct LayersBase *) OpenLibrary ("layers.library", 0)))
goto abort;
if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 0)))
goto abort;
if (!(DiskfontBase = (struct DiskfontBase *) OpenLibrary ("diskfont.library", 0)))
goto abort;
if (!(ExecBase = (struct ExecBase *) OpenLibrary ("exec.library", 0)))
goto abort;
if (OpenDevice (TIMERNAME, UNIT_VBLANK, (struct IORequest *) timerreq, 0))
goto abort;
if (OpenDevice ("input.device", 0, (struct IORequest *) inputRequestBlock, 0))
goto abort;
if (!NEWPOPLITE)
{
Forbid ();
if (WBScreen = (struct Screen *) OpenWorkBench ())
{
WindowWidth = SCSIIOMONWIDTH + GAPBETWEEN2 + CPULOADMONWIDTH +
GAPBETWEEN + MAXTEXTWIDTH;
WindowHeight = WINDOWHEIGHT;
NewWindow.LeftEdge = WBScreen->Width - WindowWidth - STARTXOFFSET;
NewWindow.TopEdge = 1;
NewWindow.Width = WindowWidth;
NewWindow.Height = WindowHeight;
if (WEWANTWINDOWDRAG)
{
WDragGadget.Height = WindowHeight;
WDragGadget.Width = WindowWidth;
}
else
NewWindow.FirstGadget = NULL;
}
Permit ();
if (!(titlewindow = OpenWindow (&NewWindow)))
goto abort;
titleRP = titlewindow->RPort;
SetAPen (titleRP, 1);
SetBPen (titleRP, 1);
SetDrMd (titleRP, JAM2);
RectFill (titleRP, 0, 0, (WindowWidth - 1), (WindowHeight - 1));
if (textFont = OpenFont (&textAttr))
{
if ((textFont->tf_YSize != FONTSIZE) || (textFont->tf_Style != 0))
{
CloseFont (textFont);
if (!(textFont = OpenDiskFont (&textAttr)))
goto abort;
}
}
else
{
if (!(textFont = OpenDiskFont (&textAttr)))
goto abort;
}
SetFont (titleRP, textFont);
}
handlerStuff.is_Data = (APTR) & global;
handlerStuff.is_Code = (VOID (*) ()) myhandler;
handlerStuff.is_Node.ln_Pri = 51;
timersig = (1 << timerport->mp_SigBit);
global.creatclisig = 1 << global.creatsignum;
global.unblanksig = 1 << global.blanksignum;
global.mousemovesig = 1 << global.mousemovenum;
inputRequestBlock->io_Command = IND_ADDHANDLER;
inputRequestBlock->io_Data = (APTR) & handlerStuff;
DoIO ((struct IORequest *) inputRequestBlock);
QueueTimer (timerreq, 1 /* 1/60th of a second */ );
if (!NEWPOPLITE)
{
Forbid ();
if (scsifriend = FindTask (SCSITASKNAME))
if (!(scsifriend->tc_Flags & TF_SWITCH))
{
scsifriend->tc_Switch = scsifriendlosing;
scsifriend->tc_Flags |= TF_SWITCH;
scsifriendinstalled = 1;
}
Permit ();
LIdle = ExecBase->IdleCount;
LDisp = ExecBase->DispCount;
}
}
{
UWORD newsecond;
ULONG sig, Seconds, Micros, LastSeconds = 0;
SHORT instantblank = 0, defeatblank = 0;
for (;;)
{
sig = Wait (global.creatclisig | global.unblanksig | timersig |
global.mousemovesig | SIGBREAKF_CTRL_C);
if (sig & global.mousemovesig)
{
int left = IntuitionBase->MouseX < 10;
int right = (GfxBase->NormalDisplayColumns - IntuitionBase->MouseX) < 10;
int upper = IntuitionBase->MouseY < 10;
int lower = (GfxBase->NormalDisplayRows - IntuitionBase->MouseY / 2) < 10;
instantblank = ((((ULC == 1) && upper) || ((LLC == 1) && lower)) && left) ||
((((URC == 1) && upper) || ((LRC == 1) && lower)) && right);
defeatblank = ((((ULC == 2) && upper) || ((LLC == 2) && lower)) && left) ||
((((URC == 2) && upper) || ((LRC == 2) && lower)) && right);
}
CurrentTime (&Seconds, &Micros);
newsecond = (Seconds != LastSeconds);
LastSeconds = Seconds;
if (newsecond && !NEWPOPLITE && !global.blankscreen)
{
SHORT x;
ULONG DIdle, DDisp, Usage;
long t;
struct tm *p;
char *timestr;
UpfrontLayer (0L, titlewindow->WLayer);
DIdle = ExecBase->IdleCount - LIdle;
DDisp = ExecBase->DispCount - LDisp;
LIdle = ExecBase->IdleCount;
LDisp = ExecBase->DispCount;
if (!DDisp)
DDisp++;
x = 0;
if (scsifriendinstalled)
{
Usage = (scsiDisp * 256) / (DDisp + DIdle);
if (Usage > MAXSCSIUSAGE)
Usage = MAXSCSIUSAGE;
SetAPen (titleRP, 3);
ScrollRaster (titleRP, 1, 0, x, 0, x + SCSIIOMONWIDTH, (WindowHeight - 1));
x += SCSIIOMONWIDTH;
Move (titleRP, x, (WindowHeight - 1));
Draw (titleRP, x, WindowHeight - ((WindowHeight * Usage) / MAXSCSIUSAGE));
scsiDisp = 0;
}
else
x += SCSIIOMONWIDTH;
/* There be magic below! Where does 456 come from? :-) */
x += GAPBETWEEN2;
if (scsiDisp < DDisp)
Usage = ((DDisp - scsiDisp) * 456) / (DDisp + DIdle);
else
Usage = 0;
if (Usage < 200)
Usage = 0;
else
Usage = Usage - 200;
ScrollRaster (titleRP, 1, 0, x, 0, x + CPULOADMONWIDTH, (WindowHeight - 1));
x += CPULOADMONWIDTH;
SetAPen (titleRP, 2);
Move (titleRP, x, (WindowHeight - 1));
Draw (titleRP, x, WindowHeight - ((WindowHeight * Usage) / 256));
x += GAPBETWEEN;
time (&t);
p = localtime (&t);
timestr = asctime (p);
Move (titleRP, x, STARTYOFFSET);
Text (titleRP, timestr, 24);
x += TextLength (titleRP, timestr, 24);
SetAPen (titleRP, 1);
if (x < (WindowWidth - 1))
RectFill (titleRP, x, 0, (WindowWidth - 1), (WindowHeight - 1));
}
if (global.blankscreen)
{
if (NICENEWPOP)
{
if (newsecond)
{
changecolor ();
SetTaskPri (child, 10);
}
}
else
{
if (newsecond)
changecolor ();
updatedisplay ();
}
}
if (sig & SIGBREAKF_CTRL_C)
{
goto abort;
}
if ((sig & global.unblanksig) &&global.blankscreen && !instantblank)
{
if (NICENEWPOP)
killchild ();
CloseScreen (global.blankscreen);
global.blankscreen = NULL;
}
if (sig & global.creatclisig)
{
WBenchToFront ();
(void) Execute (COMMAND, nullfh, nullfh);
}
if (sig & timersig)
{
GetMsg (timerport);
if (global.blankscreen && NICENEWPOP)
QueueTimer (timerreq, 60 /* One second */ );
else
QueueTimer (timerreq, 1 /* 1/60th of a second*/ );
if ((instantblank || (global.noevents++ >= (TIMEOUT * 60))) && !global.blankscreen && !defeatblank)
{
NewScreen.Height = GfxBase->NormalDisplayRows * 2;
NewScreen.Width = GfxBase->NormalDisplayColumns;
if (global.blankscreen = OpenScreen (&NewScreen))
{
xlim = global.blankscreen->Width - 1;
ylim = global.blankscreen->Height - 1;
blankRP = &(global.blankscreen->RastPort);
blankVP = &(global.blankscreen->ViewPort);
changecolor ();
SetRGB4 (blankVP, 0, 0, 0, 0);
SetRGB4 (blankVP, 17, 0, 0, 0);
SetRGB4 (blankVP, 18, 0, 0, 0);
SetRGB4 (blankVP, 19, 0, 0, 0);
SetDrMd (blankRP, JAM1);
if (j == 0)
{
x[0] = rand () % xlim + 1;
if ((x[1] = x[0] + rand () % (xlim / 6) - (xlim / 12)) > xlim)
x[1] = xlim;
if (x[1] < 0)
x[1] = 0;
y[0] = rand () % ylim + 1;
if ((y[1] = y[0] + rand () % (ylim / 4) - (ylim / 8)) > ylim)
y[1] = ylim;
if (y[1] < 0)
y[1] = 0;
xd[0] = 11;
yd[0] = 7;
xd[1] = 3;
yd[1] = 4;
}
if (NICENEWPOP)
createchild ();
}
}
}
if (global.blankscreen)
ScreenToFront (global.blankscreen);
}
}
abort:
if (stay && port)
DeletePort (port);
if (stay && scsifriendinstalled && !NEWPOPLITE)
{
Forbid ();
if (scsifriend = FindTask (SCSITASKNAME))
if (scsifriend->tc_Switch == scsifriendlosing)
{
scsifriend->tc_Flags &= !TF_SWITCH;
scsifriend->tc_Switch = NULL;
}
Permit ();
}
if (stay && titlewindow)
CloseWindow (titlewindow);
if (timerreq)
{
if (timerreq->tr_node.io_Device)
CloseDevice ((struct IORequest *) timerreq);
DeleteIOReq ((struct IOStdReq *) timerreq);
}
if (inputRequestBlock)
{
if (inputRequestBlock->io_Device)
{
inputRequestBlock->io_Command = IND_REMHANDLER;
inputRequestBlock->io_Data = (APTR) & handlerStuff;
DoIO ((struct IORequest *) inputRequestBlock);
CloseDevice ((struct IORequest *) inputRequestBlock);
}
DeleteIOReq (inputRequestBlock);
}
if (textFont && !NEWPOPLITE)
CloseFont (textFont);
if (timerport)
DeletePort (timerport);
if (global.creatsignum != -1)
FreeSignal (global.creatsignum);
if (global.blanksignum != -1)
FreeSignal (global.blanksignum);
if (global.mousemovenum != -1)
FreeSignal (global.mousemovenum);
if (global.blankscreen)
{
if (NICENEWPOP)
killchild ();
CloseScreen (global.blankscreen);
}
if (IntuitionBase)
CloseLibrary ((struct Library *) IntuitionBase);
if (GfxBase)
CloseLibrary ((struct Library *) GfxBase);
if (LayersBase)
CloseLibrary ((struct Library *) LayersBase);
if (DiskfontBase)
CloseLibrary ((struct Library *) DiskfontBase);
if (ExecBase)
CloseLibrary ((struct Library *) ExecBase);
if (inputDevPort)
DeletePort (inputDevPort);
if (_Backstdout)
Close (_Backstdout);
if (nullfh)
Close (nullfh);
}
void
changecolor (void)
{
static struct color currentcolor =
{15, 0, 5}, colordelta =
{-1, 1, 1};
switch (rand () % 3)
{
case 0:
currentcolor.red += colordelta.red;
if (currentcolor.red == 0 ||
currentcolor.red == 15)
colordelta.red = -colordelta.red;
break;
case 1:
currentcolor.green += colordelta.green;
if (currentcolor.green == 0 ||
currentcolor.green == 15)
colordelta.green = -colordelta.green;
break;
case 2:
currentcolor.blue += colordelta.blue;
if (currentcolor.blue == 0 ||
currentcolor.blue == 15)
colordelta.blue = -colordelta.blue;
break;
}
SetRGB4 (blankVP, 1, currentcolor.red, currentcolor.green, currentcolor.blue);
}
void
updatedisplay (void)
{
SHORT i, k;
SetAPen (blankRP, 0);
Move (blankRP, ox[0][j & 15], oy[0][j & 15]);
Draw (blankRP, ox[1][j & 15], oy[1][j & 15]);
SetAPen (blankRP, 1);
Move (blankRP, x[0], y[0]);
Draw (blankRP, x[1], y[1]);
for (i = 0; i < 2; i++)
{
ox[i][j & 15] = x[i];
oy[i][j & 15] = y[i];
x[i] += xd[i];
y[i] += yd[i];
if (abs (x[1] - x[0]) > xlim / 4)
{
x[i] -= xd[i] * 4 / 3;
xd[i] = -xd[i] / 2;
}
if (abs (y[1] - y[0]) > ylim / 3)
{
y[i] -= yd[i] * 4 / 3;
yd[i] = -yd[i] / 2;
}
if (x[i] < 0)
{
x[i] = 0;
xd[i] = -xd[i];
}
else if (x[i] > xlim)
{
x[i] = xlim;
xd[i] = -xd[i];
}
if (y[i] < 0)
{
y[i] = 0;
yd[i] = -yd[i];
}
else if (y[i] > ylim)
{
y[i] = ylim;
yd[i] = -yd[i];
}
if (((rand () >> 5) & 127) < 2)
{
if (xd[i] < 1)
k = 1;
xd[i] = (rand () >> 5) & 7;
if (k == (1 - i))
xd[i] = -xd[i];
k = 0;
}
if (((rand () >> 5) & 255) < 50)
{
if (yd[i] < 1)
k = 1;
yd[i] = (rand () >> 5) & 7;
if (k == (1 - i))
yd[i] = -yd[i];
k = 0;
}
}
++j;
}
void
MemCleanup (void)
{
}
void
QueueTimer (struct timerequest * tr, ULONG ticks)
{
tr->tr_node.io_Command = TR_ADDREQUEST;
tr->tr_time.tv_secs = ticks / 60;
tr->tr_time.tv_micro = (ticks % 60) * 1000000 / 60;
SendIO ((struct IORequest *) tr);
}
struct MsgPort *
CreatePort (char *name, long pri)
{
UBYTE sigbit;
register struct MsgPort *port;
if ((sigbit = AllocSignal (-1)) == -1)
return ((struct MsgPort *) 0);
if (!(port = (struct MsgPort *) AllocMem (sizeof (struct MsgPort), MEMF_CLEAR | MEMF_PUBLIC)))
{
FreeSignal (sigbit);
return ((struct MsgPort *) 0);
}
port->mp_Node.ln_Name = name;
port->mp_Node.ln_Pri = pri;
port->mp_Node.ln_Type = NT_MSGPORT;
port->mp_Flags = PA_SIGNAL;
port->mp_SigBit = sigbit;
port->mp_SigTask = (struct Task *) FindTask (0);
if (name)
AddPort (port);
return (port);
}
void
DeletePort (struct MsgPort * port)
{
if (port->mp_Node.ln_Name)
RemPort (port);
FreeSignal (port->mp_SigBit);
FreeMem ((char *) port, sizeof (struct MsgPort));
}
struct IOStdReq *
CreateIOReq (struct MsgPort * port, int size)
{
struct IOStdReq *ioReq;
if (ioReq = (struct IOStdReq *) AllocMem (size, MEMF_CLEAR | MEMF_PUBLIC))
{
ioReq->io_Message.mn_Node.ln_Type = NT_MESSAGE;
ioReq->io_Message.mn_Node.ln_Pri = 0;
ioReq->io_Message.mn_Length = size;
ioReq->io_Message.mn_ReplyPort = port;
}
return (ioReq);
}
void
DeleteIOReq (struct IOStdReq * ioReq)
{
ioReq->io_Message.mn_Node.ln_Type = 0xff;
ioReq->io_Device = (struct Device *) - 1;
ioReq->io_Unit = (struct Unit *) - 1;
FreeMem ((char *) ioReq, ioReq->io_Message.mn_Length);
}