home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
100-199
/
ff187.lzh
/
Mackie
/
mackie.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-02-26
|
42KB
|
1,563 lines
/*
Modified to work with Manx 3.6a; probably won't work with Lattice.
Based on:
*/
/* Compile with -DSPLINES for splines instead of 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
*/
/* * * * * * * * * INCLUDE FILES * * * * * * * * * * * */
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <exec/ports.h>
#include <exec/libraries.h>
#include <exec/io.h>
#include <exec/tasks.h>
#include <exec/execbase.h>
#include <exec/devices.h>
#include <devices/timer.h>
#include <devices/input.h>
#include <devices/inputevent.h>
#include <devices/console.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <graphics/gfxmacros.h>
#include <hardware/custom.h>
#include <hardware/dmabits.h>
/*
* I need this kludge because of a bug in functions.h.
*/
#define ConsoleDevice IDontReallyExist
#include <functions.h>
#undef ConsoleDevice
#include <stdio.h>
/* * * * * * * * * * * CONSTANTS * * * * * * * * * * * * */
#define PORTNAME "Mackie.port"
#define TIMEINTERVAL 1L /* in seconds */
#define DEFTIME 300 /* two minute timeout */
#define MAXCMD 200
#define MAXPENDINGSYSTEM 20
#define DEFKEY 0x45
#define DEFCMD "NEWCLI >NIL: <NIL:"
#define STARTUPFILE "s:.mackierc"
/*
* Macro to make BPTR things easier to work with.
*/
#define BSTRtoS(a) ((char *)(((long)(a))<<2))
/* * * * * * * * * * * GLOBAL VARIABLES * * * * * * * * * */
/*
* Detach stuff (doesn't work, somehow!)
*/
struct Task *globalbuddy ;
ULONG globalcreatclisig ;
ULONG globalunblanksig ;
ULONG globalfrontsig ;
ULONG globalnoevents ;
short globalcreatsignum ;
short globalblanksignum ;
short globalreplysignum ;
short globalfrontsignum ;
short globalkey ;
char globalfrontkey[MAXPENDINGSYSTEM] ;
char globalfrontqual[MAXPENDINGSYSTEM] ;
short globalfrontptr ;
short globaldraw ;
short globalhelppressed ;
struct Screen *globalblankscreen ;
#define SHIFT 1
#define NOTCLI 2
#define NOTINTUITION 4
struct hotkey {
struct hotkey*next ;
char key, flags ;
int structlen ;
char *matchstring, *startstring ;
char strings[2] ;
} *hotkeys ;
struct Window *lastwindows[200] ;
struct Task *task ;
long taskreply ; /* the signal the line drawing task will return */
#define STACKSIZE (1000)
long stackmem[STACKSIZE/4] ;
struct InfoData *infoptr ;
struct MsgPort *FindPort(), *CreatePort();
void DeletePort();
char *startupfile = STARTUPFILE ;
struct OURMSG {
struct Message msgpart;
short key;
short interval;
short draw ;
char cmd[MAXCMD];
};
extern char *strcpy() ;
/************************************************************************/
/* the handler subroutine - called through the handler stub */
/************************************************************************/
extern void HandlerInterface();
void foobar() {
#asm
_HandlerInterface:
movem.l a4,-(a7)
movem.L A0/A1,-(A7)
jsr _geta4#
jsr _myhandler
addq.L #8,A7
movem.L (a7)+,a4
rts
#endasm
}
char keytoasc[128] ;
struct InputEvent *myhandler(ev, gptr)
struct InputEvent *ev; /* and a pointer to a list of events */
long gptr ; /* ignore */
{
register struct InputEvent *ep, *laste;
int key ;
/*
* run down the list of events
* to see if they pressed
* one of the magic buttons
*/
for (ep = ev, laste = NULL; ep != NULL; ep = ep->ie_NextEvent) {
if ((ep->ie_Class == IECLASS_RAWKEY) &&
(((ep->ie_Qualifier & IEQUALIFIER_LCOMMAND) &&
(ep->ie_Code == globalkey)) ||
(!globalhelppressed && ep->ie_Code == 0x5f) ||
(globalhelppressed &&
(ep->ie_Code & 0x80) == 0 &&
/*
* All the qualifiers have code = 0x6?; dangerous to take advantage
* of?
*/
(ep->ie_Code & 0xf0) != 0x60 &&
globalfrontkey[globalfrontptr] == 0 &&
(globalhelppressed = (keytoasc[ep->ie_Code] != '.'))))) {
if ((ep->ie_Qualifier & IEQUALIFIER_LCOMMAND) &&
(ep->ie_Code == globalkey))
key = -1 ;
else if (globalhelppressed) {
globalfrontkey[globalfrontptr] = key = ep->ie_Code ;
globalfrontqual[globalfrontptr] = ep->ie_Qualifier ;
globalfrontptr++ ;
if (globalfrontptr >= MAXPENDINGSYSTEM)
globalfrontptr = 0 ;
globalhelppressed = 0 ;
} else {
globalhelppressed = 1 ;
key = 0 ;
}
/* we can handle this event so take it off the chain */
if (laste == NULL)
ev = ep->ie_NextEvent;
else
laste->ie_NextEvent = ep->ie_NextEvent;
/* now tell him to create the new cli */
if (key == -1)
Signal(globalbuddy, globalcreatclisig);
else if (key > 0)
Signal(globalbuddy, globalfrontsig);
} else
laste = ep;
if (ep->ie_Class != IECLASS_TIMER) {
globalnoevents = 0;
if (globalblankscreen != NULL)
Signal(globalbuddy, globalunblanksig);
}
}
/* pass on the pointer to the event */
return(ev);
}
/* * * * * * * * * * * EXTERNAL ROUTINES * * * * * * * * * */
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct DosLibrary *DosBase;
struct NewScreen NewScreen =
{ 0, 0, 320, 30, 1, 0, 1, NULL, CUSTOMSCREEN, NULL, NULL, NULL, NULL };
extern struct MsgPort *CreatePort();
struct IOStdReq *CreateIOReq();
void DeleteIOReq();
/************************************************************************/
/* Queue a timer to go off in a given number of seconds */
/************************************************************************/
void QueueTimer(tr,seconds)
register struct timerequest *tr;
ULONG seconds;
{
tr->tr_node.io_Command = TR_ADDREQUEST; /* add a new timer request */
tr->tr_time.tv_secs = seconds; /* seconds */
tr->tr_time.tv_micro = 0;
SendIO( (struct IORequest *)tr );
}
/*
* A utility to change our priority.
*/
prito(n)
int n ;
{
SetTaskPri(FindTask(0L), (long)n) ;
}
/************************************************************************/
/* the main program to do the popcli stuff */
/************************************************************************/
main(argc, argv)
int argc ;
char *argv[] ;
{
struct MsgPort *port;
int stay = 0;
register struct OURMSG *msg;
int i ;
char cmdstr[MAXCMD];
short key, timeout ;
struct FileHandle *nullfh = NULL ;
ULONG sig, timersig;
struct timerequest *timerreq;
struct MsgPort *timerport;
struct MsgPort *inputDevPort;
struct IOStdReq *inputRequestBlock;
register struct Interrupt handlerStuff;
char *cmd ;
int draw = 0 ;
int nextfront = 0 ;
prito(20) ;
globalcreatsignum = -1;
globalblanksignum = -1;
globalreplysignum = -1;
globalfrontsignum = -1;
globalblankscreen = NULL;
globalkey = DEFKEY ;
globaldraw = 1 ;
timerreq = NULL;
timerport = NULL;
inputDevPort = NULL;
inputRequestBlock = NULL;
/* now see if we are already installed */
if ((port = FindPort(PORTNAME)) == NULL) {
stay = 1; /* remember to hang around when we are done */
/* not installed, we need to install our own port */
if ((port = CreatePort(PORTNAME,0L)) == NULL)
goto abort;
}
/*
* If we are hanging around, initialize our keyboard translation table.
* If we have difficulty, exit angry.
*/
if (stay)
if (initkeytoasc())
goto abort ;
/* now send the parameter to the waiting program */
if ((msg = (struct OURMSG *)
AllocMem((long)sizeof(struct OURMSG), MEMF_CLEAR|MEMF_PUBLIC)) == NULL)
goto abort;
if ((infoptr = (struct InfoData *)
AllocMem((long)sizeof(struct InfoData), MEMF_CLEAR)) == NULL)
goto abort ;
/* fill in the message information */
msg->msgpart.mn_Length = sizeof(struct OURMSG);
strcpy(cmdstr, DEFCMD);
timeout = -1 ;
key = 0 ;
msg->cmd[0] = 0;
/* if we were run from CLI then output our banner and process parameters */
if (argc > 0) {
/* display our copyright */
if (stay)
puts("Mackie 1.13 by Tomas Rokicki - Copyright \xa9 1987, 1988 Radical Eye Software") ;
if (argc == 1)
puts("Usage: Mackie [-q] [-l] [-b] [-f startup] [time] [\"command\"]") ;
argc-- ;
argv++ ;
while (argc > 0) {
cmd = argv[0] ;
if (*cmd == '-') {
cmd++ ;
switch (*cmd) {
case 'q' : case 'Q' :
key = -1 ;
puts("\x9B1mMackie\x9B0m Terminating") ;
break ;
case 'l' : case 'L' :
draw = 1 ;
break ;
case 'b' : case 'B' :
draw = -1 ;
break ;
case 'f' : case 'F' :
if (cmd[1])
startupfile = cmd + 1 ;
else {
argv++ ;
argc-- ;
startupfile = argv[0] ;
}
break ;
default :
puts("Error in parameter!") ;
}
} else if ('0' <= *cmd && *cmd <= '9') {
timeout = 0;
while ((*cmd >= '0') && (*cmd <= '9'))
timeout = (timeout*10) + *cmd++ - '0';
if (timeout < 0)
timeout = DEFTIME;
} else {
strcpy(msg->cmd, cmd) ;
}
argc-- ;
argv++ ;
}
}
msg->interval = timeout;
msg->key = key;
msg->draw = draw ;
if (stay)
processstartup(startupfile, msg) ;
if (draw)
globaldraw = draw ;
PutMsg(port,(struct Message *)msg);
if (!stay) goto abort;
if (timeout == -1)
timeout = DEFTIME ;
globalblankscreen = NULL;
globalbuddy = FindTask(0L);
globalnoevents = 0;
nullfh = Open("NIL:", MODE_NEWFILE);
if (((inputDevPort = CreatePort(0L,0L)) == NULL) ||
((inputRequestBlock =
CreateIOReq(inputDevPort, (long)sizeof(struct IOStdReq))) == NULL) ||
((timerport = CreatePort(0L,0L)) == NULL) ||
((timerreq = (struct timerequest *)
CreateIOReq(timerport, (long)sizeof(struct timerequest))) == NULL))
goto abort ;
if (((globalcreatsignum = AllocSignal(-1L)) == -1) ||
((globalblanksignum = AllocSignal(-1L)) == -1) ||
((globalreplysignum = AllocSignal(-1L)) == -1) ||
((globalfrontsignum = AllocSignal(-1L)) == -1) ||
((GfxBase = (struct GfxBase *)
OpenLibrary("graphics.library", 0L)) == NULL) ||
((IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", 0L)) == NULL) ||
OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)timerreq, 0L) ||
OpenDevice("input.device",0L,(struct IORequest *)inputRequestBlock,0L))
goto abort;
handlerStuff.is_Data = (APTR)0L ;
handlerStuff.is_Code = HandlerInterface;
handlerStuff.is_Node.ln_Pri = 51;
timersig = (1L << timerport->mp_SigBit);
globalcreatclisig = 1L << globalcreatsignum;
globalunblanksig = 1L << globalblanksignum;
globalfrontsig = 1L << globalfrontsignum;
inputRequestBlock->io_Command = IND_ADDHANDLER;
inputRequestBlock->io_Data = (APTR)&handlerStuff;
DoIO((struct IORequest *)inputRequestBlock);
QueueTimer(timerreq, TIMEINTERVAL);
for(;;) { /* FOREVER */
sig = Wait( globalcreatclisig | globalunblanksig | timersig |
globalfrontsig);
/* see if they asked us to change the interval */
if ((msg = (struct OURMSG *)GetMsg(port)) != NULL) {
if (msg->cmd[0]) strcpy(cmdstr, msg->cmd);
if (msg->key)
globalkey = msg->key;
if (msg->interval != -1)
timeout = msg->interval;
if (msg->draw)
globaldraw = msg->draw ;
FreeMem((char *)msg, (long)msg->msgpart.mn_Length);
if (msg->key == -1) goto abort;
}
if ((sig & globalunblanksig) && globalblankscreen)
screenunblank() ;
if (sig & globalcreatclisig) {
WBenchToFront();
prito(0) ;
(void)Execute(cmdstr,nullfh,nullfh);
prito(20) ;
}
if (sig & globalfrontsig) {
while (i=globalfrontkey[nextfront]) {
windowtofront(keytoasc[i], globalfrontqual[nextfront]) ;
globalfrontkey[nextfront] = 0 ;
nextfront++ ;
if (nextfront >= MAXPENDINGSYSTEM)
nextfront = 0 ;
}
}
if (sig & timersig) {
/* get rid of the message */
(void)GetMsg(timerport);
QueueTimer(timerreq, TIMEINTERVAL);
if (task)
SetTaskPri(task, 10L) ;
if (timeout != 0 && (globalnoevents++ >= timeout) && (globalblankscreen == NULL))
blankscreen() ;
}
}
abort:
if (infoptr) {
FreeMem(infoptr, (long)sizeof(struct InfoData)) ;
infoptr = NULL ;
}
if (timerreq != NULL) {
if (timerreq->tr_node.io_Device != NULL)
CloseDevice((struct IORequest *)timerreq);
DeleteIOReq((struct IOStdReq *)timerreq);
}
if (inputRequestBlock != NULL) {
if (inputRequestBlock->io_Device != NULL) {
inputRequestBlock->io_Command = IND_REMHANDLER;
inputRequestBlock->io_Data = (APTR)&handlerStuff;
DoIO((struct IORequest *)inputRequestBlock);
CloseDevice((struct IORequest *)inputRequestBlock);
}
DeleteIOReq(inputRequestBlock);
}
screenunblank() ;
if (timerport != NULL) DeletePort(timerport);
if (globalcreatsignum != -1) FreeSignal(globalcreatsignum);
if (globalblanksignum != -1) FreeSignal(globalblanksignum);
if (globalreplysignum != -1) FreeSignal(globalreplysignum);
if (globalfrontsignum != -1) FreeSignal(globalfrontsignum);
if (IntuitionBase != NULL) CloseLibrary((struct Library *)IntuitionBase);
if (GfxBase != NULL) CloseLibrary((struct Library *)GfxBase);
if (inputDevPort != NULL) DeletePort(inputDevPort);
if (stay && (port != NULL)) DeletePort(port);
{
struct hotkey *hk ;
while (hotkeys) {
hk = hotkeys->next ;
FreeMem(hotkeys, (long)hotkeys->structlen) ;
hotkeys = hk ;
}
}
if (nullfh) Close(nullfh);
prito(0) ;
}
struct IOStdReq *
CreateIOReq(port, size)
struct MsgPort *port;
long size;
{
register struct IOStdReq *ioReq;
if ((ioReq = (struct IOStdReq *)
AllocMem(size, MEMF_CLEAR | MEMF_PUBLIC)) != NULL) {
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(ioReq)
register 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, (long)ioReq->io_Message.mn_Length);
}
/*
* All of this stuff down here was written by Tomas Rokicki.
* (C) Copyright 1987, 1988, Radical Eye Software.
*/
#include "graphics/gfxbase.h"
/*
* The maximum number of lines on the screen at once.
*/
#define MAXLINES (125)
#define MAXPOINTS (4)
int maxpoints ;
/*
* The external variables we access.
*/
struct RastPort *rastport ;
short screenheight, screenwidth ;
/*
* Some locals to this file.
*/
static struct NewScreen newscreen = {
0, 0,
640, 400,
1,
0, 1,
HIRES | LACE | SCREENQUIET,
CUSTOMSCREEN,
NULL,
NULL,
NULL,
NULL } ;
/*
* This routine opens a screen and fires off the task if apropriate.
*/
void taskrout() ;
blankscreen() {
register struct Task *rtask ;
screenheight = 2 * GfxBase->NormalDisplayRows ;
screenwidth = GfxBase->NormalDisplayColumns ;
newscreen.Height = screenheight ;
newscreen.Width = screenwidth ;
if (globaldraw == -1 || AvailMem(MEMF_CHIP) < 70000L ||
(globalblankscreen = OpenScreen(&newscreen)) == NULL) {
if ((globalblankscreen = OpenScreen(&NewScreen)) != NULL) {
SetRGB4(&(globalblankscreen->ViewPort), 0L, 0L, 0L, 0L);
OFF_DISPLAY ;
}
} else {
if (globalblankscreen == NULL &&
(globalblankscreen = OpenScreen(&newscreen))==NULL)
return ;
/*
* Turning off the sprites is a little bit tricky. A simple OFF_SPRITE
* will continue to display the data in the current sprite registers.
* This happens most often with the cursor. To fix, we simply clear out
* the sprite control registers after turning the sprites off. This
* might break all of the sprites when the system comes back up . . .
*/
OFF_SPRITE ;
custom.spr[0].ctl = 0 ;
custom.spr[1].ctl = 0 ;
custom.spr[2].ctl = 0 ;
custom.spr[3].ctl = 0 ;
custom.spr[4].ctl = 0 ;
custom.spr[5].ctl = 0 ;
custom.spr[6].ctl = 0 ;
custom.spr[7].ctl = 0 ;
SetRGB4(&(globalblankscreen->ViewPort), 0L, 0L, 0L, 0L) ;
rastport = &(globalblankscreen->RastPort) ;
SetAPen(rastport, 0L) ;
Forbid() ;
RectFill(rastport, 0L, 0L, (long)screenwidth-1, 30L) ;
Permit() ;
SetAPen(rastport, 1L) ;
rtask = (struct Task *)AllocMem((long)sizeof(struct Task),
MEMF_CLEAR | MEMF_PUBLIC) ;
if (rtask != NULL) {
rtask->tc_Node.ln_Pri = 10 ;
rtask->tc_Node.ln_Type = NT_TASK ;
rtask->tc_Node.ln_Name = "ri.Lines" ;
rtask->tc_SPLower = (APTR)stackmem ;
rtask->tc_SPUpper = rtask->tc_SPReg =
(APTR)(stackmem + STACKSIZE/4 - 8) ;
AddTask(rtask, taskrout, 0L) ;
task = rtask ;
}
}
}
/*
* Unblank the screen. We kill the task with the standard ^C kill signal.
*/
screenunblank() {
if (task != NULL) {
Signal(task, 1L << SIGBREAKB_CTRL_C) ;
SetTaskPri(task, 11L) ;
Wait(1L << globalreplysignum) ;
RemTask(task);
FreeMem(task, (long)sizeof(struct Task)) ;
task = NULL ;
}
if (globalblankscreen != NULL) {
CloseScreen(globalblankscreen);
globalblankscreen = NULL ;
ON_DISPLAY ;
ON_SPRITE ;
}
}
/*
* This routine returns a random value from 0 to n-1.
*/
int randm(i)
int i ;
{
static long seed ;
register long rseed ;
register long rval ;
rseed = seed ;
if (rseed == 0)
rseed = 323214521 + globalblankscreen->MouseX +
globalblankscreen->MouseY ;
rseed = rseed * 123213 + 121 ;
rval = (rseed >> 5) & 65535 ;
seed = rseed ;
return ((i * rval) >> 16) ;
}
/*
* This routine sets x and y values to a random number.
*/
static long x, y ;
randomxy() {
x = randm(screenwidth) ;
y = randm(screenheight) ;
}
/*
* Main routines are always fun.
*/
struct box {
short x[MAXPOINTS], y[MAXPOINTS] ;
} store[MAXLINES] ;
#define FIX(x) (((long)(x)) << 7)
struct box *ptr ;
struct box *eptr ;
int numlines ;
int mdelta = -1 ;
int maxlines = MAXLINES/2 ;
short dx[MAXPOINTS], dy[MAXPOINTS] ;
short ox[MAXPOINTS], oy[MAXPOINTS] ;
short nx[MAXPOINTS], ny[MAXPOINTS] ;
short dr, dg, db ;
short or, og, ob ;
short nr, ng, nb ;
/*
* Draws a spline! Expects all arguments in registers.
*/
#asm
public _Draw
cseg
rspline
move.l a0,d0
sub.l d6,d0
move.l d0,d3
bpl save1
neg.l d0
save1
move.l a1,d1
sub.l d7,d1
move.l d1,d4
bpl save2
neg.l d1
save2
move.l d0,d2
cmp.l d0,d1
bmi save3
lsr.l #3,d2
bra save9
save3
lsr.l #3,d1
save9
add.l d1,d2
asr.l #3,d2
asr.l #5,d3
asr.l #5,d4
move.l a2,d0
sub.l a0,d0
move.l a3,d1
sub.l a1,d1
asr.l #5,d0
asr.l #5,d1
muls.w d4,d0
muls.w d3,d1
sub.l d1,d0
bpl save4
neg.l d0
save4
cmp.l d0,d2
bmi pushem
move.l a5,d0
sub.l a0,d0
move.l a6,d1
sub.l a1,d1
asr.l #5,d0
asr.l #5,d1
muls.w d4,d0
muls.w d3,d1
sub.l d1,d0
bpl save5
neg.l d0
save5
cmp.l d0,d2
bmi pushem
makeline
lsr.l #7,d7
move.l d7,-(sp)
lsr.l #7,d6
move.l d6,-(sp)
move.l _rastport,-(sp)
jsr _Draw
add.w #12,a7
rts
pushem
movem.l d6/d7,-(sp)
move.l a5,d0
add.l d6,d0
asr.l #1,d0
move.l a6,d1
add.l d7,d1
asr.l #1,d1
movem.l d0/d1,-(sp)
move.l a2,d2
add.l a5,d2
asr.l #1,d2
move.l a3,d3
add.l a6,d3
asr.l #1,d3
move.l d0,d4
add.l d2,d4
asr.l #1,d4
move.l d1,d5
add.l d3,d5
asr.l #1,d5
movem.l d4/d5,-(sp)
move.l a0,d6
add.l a2,d6
asr.l #1,d6
move.l a1,d7
add.l a3,d7
asr.l #1,d7
move.l d2,d0
add.l d6,d0
asr.l #1,d0
move.l d3,d1
add.l d7,d1
asr.l #1,d1
move.l d6,a2
move.l d7,a3
move.l d0,d6
add.l d4,d6
asr.l #1,d6
move.l d1,d7
add.l d5,d7
asr.l #1,d7
movem.l d6/d7,-(sp)
move.l d0,a5
move.l d1,a6
jsr rspline
movem.l (sp)+,a0/a1
movem.l (sp)+,a2/a3/a5/a6
movem.l (sp)+,d6/d7
bra rspline
#endasm
/*
* Now our linkage to the spline routine. Parameters are in 8(a5)...
*/
int drawspline(x1, y1, x2, y2, x3, y3, x4, y4)
long x1, y1, x2, y2, x3, y3, x4, y4 ;
{
#asm
movem.l saver,-(sp)
move.l 8(a5),a0
move.l 12(a5),a1
move.l 16(a5),a2
move.l 20(a5),a3
move.l 28(a5),a6
move.l 32(a5),d6
move.l 36(a5),d7
move.l 24(a5),a5
jsr rspline
movem.l (sp)+,saver
saver reg d0-d7/a0-a6
#endasm
}
/*
* Here we draw splines! Magic, you know.
*/
dosplines(bptr)
register struct box *bptr ;
{
Move(rastport, (long)(bptr->x[0]), (long)(bptr->y[0])) ;
drawspline(FIX(bptr->x[0]), FIX(bptr->y[0]), FIX(bptr->x[1]),
FIX(bptr->y[1]), FIX(bptr->x[2]), FIX(bptr->y[2]),
FIX(bptr->x[3]), FIX(bptr->y[3])) ;
}
/*
* Here we draw lines!
*/
dolines(bptr)
register struct box *bptr ;
{
Move(rastport, (long)(bptr->x[0]), (long)(bptr->y[0])) ;
Draw(rastport, (long)(bptr->x[1]), (long)(bptr->y[1])) ;
Draw(rastport, (long)(screenwidth-1-bptr->x[0]),
(long)(screenheight-1-bptr->y[0])) ;
Draw(rastport, (long)(screenwidth-1-bptr->x[1]),
(long)(screenheight-1-bptr->y[1])) ;
Draw(rastport, (long)(bptr->x[0]), (long)(bptr->y[0])) ;
}
/*
* Here we draw a single line
*/
doline(bptr)
register struct box *bptr ;
{
Move(rastport, (long)(bptr->x[0]), (long)(bptr->y[0])) ;
Draw(rastport, (long)(bptr->x[1]), (long)(bptr->y[1])) ;
}
/*
* Initialize things for the first lines.
*/
startlines() {
register int i ;
ptr = store ;
eptr = store ;
numlines = 0 ;
if (dx[0] == 0) {
for (i=0; i<maxpoints; i++) {
ox[i] = randm(screenwidth) ;
oy[i] = randm(screenheight) ;
dx[i] = 2 + randm(3) ;
dy[i] = 2 + randm(3) ;
}
}
nr = 53 ;
ng = 33 ;
nb = 35 ;
dr = -3 ;
dg = 5 ;
db = 7 ;
SetRGB4(&(globalblankscreen->ViewPort), 0L, 0L, 0L, 0L) ;
SetRGB4(&(globalblankscreen->ViewPort), 1L, (long)(nr >> 3),
(long)(ng >> 3), (long)(nb >> 3)) ;
for (i=0; i<maxlines; i++) {
advancelines() ;
drawnew() ;
}
}
/*
* Advance the number by the delta, and check the boundaries.
*/
adv(o, d, n, w)
register short *o, *d, *n ;
short w ;
{
*n = *o + *d ;
if (*n < 0) {
*n = 0 ;
*d = randm(6) + 1 ;
} else if (*n >= w) {
*n = w - 1 ;
*d = - randm(6) - 1 ;
}
}
/*
* Advance the two points which make up the lines.
*/
advancelines() {
register int i ;
for (i=0; i<maxpoints; i++) {
adv(ox+i, dx+i, nx+i, screenwidth) ;
adv(oy+i, dy+i, ny+i, screenheight) ;
}
}
int (*drawfunc)() ;
/*
* Draw a new set of lines.
*/
drawnew() {
register int i ;
register short oldpen ;
register struct box *bptr ;
while (numlines >= maxlines) {
oldpen = rastport->FgPen ;
SetAPen(rastport, 0L) ;
bptr = eptr ;
(*drawfunc)(bptr) ;
SetAPen(rastport, (long)oldpen) ;
numlines-- ;
bptr++ ;
if (bptr == store + MAXLINES)
bptr = store ;
eptr = bptr ;
}
bptr = ptr ;
for (i=0; i<maxpoints; i++) {
bptr->x[i] = ox[i] = nx[i] ;
bptr->y[i] = oy[i] = ny[i] ;
}
(*drawfunc)(bptr) ;
numlines++ ;
bptr++ ;
if (bptr == store + MAXLINES) {
bptr = store ;
if (mdelta == 1) {
maxlines++ ;
if (maxlines >= MAXLINES - 1)
mdelta = -1 ;
} else {
maxlines-- ;
if (maxlines <= 2)
mdelta = 1 ;
}
}
ptr = bptr ;
}
/*
* This routine mucks with the colors.
*/
colors() {
or = nr ;
og = ng ;
ob = nb ;
adv(&or, &dr, &nr, 128) ;
adv(&og, &dg, &ng, 128) ;
adv(&ob, &db, &nb, 128) ;
SetRGB4(&(globalblankscreen->ViewPort), 1L, (long)(nr >> 3),
(long)(ng >> 3), (long)(nb >> 3)) ;
}
long oldtime[3] ;
/*
* Call this to set the time.
*/
void settime() {
DateStamp(oldtime) ;
}
/*
* Call this to get the time since the last settime.
*/
long gettime() {
long t[3] ;
DateStamp(t) ;
return(t[2]-oldtime[2] +
(t[1]-oldtime[1]) * 3000 +
(t[0]-oldtime[0]) * 4320000) ;
}
/*
* Our actual task, in an infinite loop.
*/
int (*funcs[3])() = { &dolines, &dosplines, &doline } ;
int maxp[3] = { 2, 4, 2 } ;
int lastfunc = 0 ;
void taskrout() {
register long i ;
register struct Task *task ;
geta4() ;
settime() ;
lastfunc = lastfunc + 1 ;
if (lastfunc == 3)
lastfunc = 0 ;
drawfunc = funcs[lastfunc] ;
maxpoints = maxp[lastfunc] ;
task = FindTask(0L) ;
startlines() ;
i = 100 ;
colors() ;
while (SetSignal(0L, 0L)==0) {
if (task->tc_Node.ln_Pri == 10)
SetTaskPri(task, -20L) ;
advancelines() ;
drawnew() ;
advancelines() ;
drawnew() ;
if (task->tc_Node.ln_Pri == 10)
SetTaskPri(task, -20L) ;
advancelines() ;
drawnew() ;
advancelines() ;
drawnew() ;
if (task->tc_Node.ln_Pri == 10)
SetTaskPri(task, -20L) ;
advancelines() ;
drawnew() ;
advancelines() ;
drawnew() ;
colors() ;
if (--i <= 0) {
if (gettime() >= 15000) {
settime() ;
lastfunc = lastfunc + 1 ;
if (lastfunc == 3)
lastfunc = 0 ;
drawfunc = funcs[lastfunc] ;
maxpoints = maxp[lastfunc] ;
SetRast(rastport, 0L) ;
startlines() ;
}
i = 100 ;
}
}
done:
Signal(globalbuddy, 1L << globalreplysignum) ;
Wait(0L) ;
}
/*
* Now we do hotkey magic to activate windows, bring them to front,
* etc.
*
* Now we have a key, so we have to find a process with that name and
* bring her to front. For now, we just deal with tasks, since the
* CLI stuff is so complicated.
*/
#define MAXMATCH (20)
char simplematch[3] = { ' ', '*', 0 } ;
struct Window *matchwindows[MAXMATCH] ;
extern long LockIBase() ;
windowtofront(key, qual)
char key ;
{
long foo ;
register int i, j ;
int n ;
register struct Window *w ;
struct Screen *s ;
struct Process *p ;
struct MsgPort **mp ;
struct CommandLineInterface *CLI ;
int cli ;
char *nameptr, *matchptr ;
extern struct DosLibrary *DOSBase ;
register struct hotkey *hk ;
int shift, ctrl ;
struct Window *activewindow ;
/*
* First we look for a matching record.
*/
if (key == '.')
goto goner ;
shift = ((qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0) ;
ctrl = ((qual & IEQUALIFIER_CONTROL) != 0) ;
activewindow = NULL ;
for (hk=hotkeys; hk; hk=hk->next)
if (hk->key == key &&
(hk->flags & SHIFT) == shift)
break ;
cli = 0 ;
if (hk && hk->matchstring)
matchptr = hk->matchstring ;
else {
matchptr = simplematch ;
if (key == ' ')
matchptr++ ;
else if ('A' <= key && key <= 'Z')
simplematch[0] = key ;
else if ('0' <= key && key <= '9') {
cli = key ;
if (cli == '0')
cli += 10 ;
matchptr++ ;
} else
goto goner ;
}
n = 0 ;
foo = LockIBase(0L) ;
if (! ctrl && !(hk && (hk->flags & NOTINTUITION)) && !cli) {
for (s=IntuitionBase->FirstScreen; s; s=s->NextScreen)
for (w=s->FirstWindow; w; w=w->NextWindow) {
if (w->UserPort) {
p = (struct Process *)(w->UserPort->mp_SigTask) ;
if (((struct Task *)p)->tc_Node.ln_Type == NT_PROCESS) {
if (p->pr_CLI) {
CLI = (struct CommandLineInterface *)BSTRtoS(p->pr_CLI) ;
if (bstrcmp(BSTRtoS((CLI)->cli_CommandName), matchptr) &&
n < MAXMATCH) {
if (w==IntuitionBase->ActiveWindow)
activewindow = w ;
matchwindows[n++] = w ;
}
} else {
if (sstrcmp(((struct Task *)p)->tc_Node.ln_Name, matchptr)
&& n < MAXMATCH) {
if (w==IntuitionBase->ActiveWindow)
activewindow = w ;
matchwindows[n++] = w ;
}
}
}
}
}
}
/*
* Folks, there are still several/many windows of vulnerability
* here; I'll have to plug them. For instance, what happens if a
* CLI goes away while we are doing this? Or what happens if a
* window goes away later, when we are looking at IntuitionBase?
*/
if (! ctrl && !(hk && (hk->flags & NOTCLI))) {
mp = (struct MsgPort **)BSTRtoS(*(DOSBase->dl_Root)) ;
for (j=1; j<(long)(mp[0]); j++)
if (mp[j] && (cli == 0 || j == cli - '0')) {
p = (struct Process *)(mp[j]->mp_SigTask) ;
CLI = (struct CommandLineInterface *)BSTRtoS(p->pr_CLI) ;
if (!CLI->cli_Background &&
bstrcmp(BSTRtoS((CLI)->cli_CommandName), matchptr)) {
infoptr->id_VolumeNode = NULL ;
dos_packet(p->pr_ConsoleTask, ACTION_DISK_INFO,
((long)(infoptr)) >> 2, 0L, 0L, 0L, 0L, 0L, 0L) ;
if (w=(struct Window *)infoptr->id_VolumeNode)
if (n < MAXMATCH) {
if (w==IntuitionBase->ActiveWindow)
activewindow = w ;
matchwindows[n++] = w ;
}
}
}
}
if (shift)
key += 100 ;
if (ctrl || n==0) {
UnlockIBase(foo) ;
if (hk == NULL || hk->startstring == NULL)
goto goner ;
prito(0) ;
Execute(hk->startstring, 0L, 0L) ;
prito(20) ;
} else {
if (n == 1) {
w = matchwindows[0] ;
} else {
/*
* This is some real neat code. We want to find the next window,
* that is, the window with the least address greater than the
* currently active window, unless the currently active window
* has the highest address, in which case we want to find the
* window with the least address. Why this works is left as a
* puzzle for the reader.
*/
if (activewindow) {
w = activewindow ;
for (j=0; j<n; j++)
if ((w > activewindow) ^
(w > matchwindows[j]) ^
(matchwindows[j] > activewindow))
w = matchwindows[j] ;
} else {
w = NULL ;
for (j=0; j<n; j++)
if (lastwindows[key]==matchwindows[j]) {
w = lastwindows[key] ;
break ;
}
if (w==NULL)
w = matchwindows[0] ;
}
}
lastwindows[key] = w ;
s = w->WScreen ;
UnlockIBase(foo) ;
ScreenToFront(s) ;
/*
* If only one window on screen, don't bring it to front
* (mostly for DPaint, but for other progs as well.)
* (Anyone know an easy way to see if this window is fully
* exposed?)
*/
if (s->FirstWindow != w || w->NextWindow)
WindowToFront(w) ;
ActivateWindow(w) ;
}
return ;
goner:
DisplayBeep(0L) ;
}
/*
* These two functions compare a given string `s' with a `key' string.
* The key string should be all upper case; this is a case insensitive
* match. If the key string contains `*', this character is assumed to
* match the rest of the string (and it can only come at the end.) We
* have a routine for BSTR's, and a routine for regular strings.
*/
int sstrcmp(s, key)
register char *s, *key ;
{
while (1) {
if (*key == '*')
return(1) ;
if (*key == 0)
return(*s == 0) ;
if (*s == 0)
return(0) ;
if (*s != *key &&
(*s != *key + 32 || *s < 'a' || *s > 'z'))
return(0) ;
s++ ;
key++ ;
}
}
/*
* This is the same as above, only instead of using a null to
* end the string, we keep track of the number of characters.
*/
int bstrcmp(s, key)
register char *s, *key ;
{
register int n ;
n = *(unsigned char *)s++ ;
while (1) {
if (*key == '*')
return(1) ;
if (*key == 0)
return(n == 0) ;
if (n == 0)
return(0) ;
if (*s != *key &&
(*s != *key + 32 || *s < 'a' || *s > 'z'))
return(0) ;
s++ ;
key++ ;
n-- ;
}
}
/*
* A place to hold an input line.
*/
#define MAXSTARTUPLINE (100)
char startbuf[MAXSTARTUPLINE] ;
char upline[MAXSTARTUPLINE] ;
/*
* Is a legit separator of some sort.
*/
int issep(s)
register char s ;
{
return (s <= ' ' || s == '=' || s == ':' || s == ',' || s == '-') ;
}
/*
* Go to next `word' in the startup file.
*/
char *getword(s)
register char *s ;
{
while (*s && issep(*s))
s++ ;
return(s) ;
}
/*
* Upper case a string.
*/
char *upcase(dest, s)
char *dest ;
register char *s ;
{
register char *d = dest ;
while (*s) {
if ('a' <= *s && *s <= 'z')
*d++ = *s++ - 32 ;
else
*d++ = *s++ ;
}
*d = 0 ;
return(dest) ;
}
/*
* Say we got a bad line.
*/
badline() {
puts("Error in startup file!") ;
puts(startbuf) ;
}
/*
* Copies a string from one place to another; string delimited by
* double quotes.
*/
char *cpystr(dest, src)
register char *dest, *src ;
{
if (*src != '"')
badline() ;
else {
src++ ;
while (*src != '"' && *src != 0) {
if (*src == '\\' && src[1] != 0)
src++ ;
*dest++ = *src++ ;
}
if (*src)
src++ ;
}
*dest = 0 ;
return(getword(src)) ;
}
/*
* Handle a single startup line that's not a comment and non-empty
* and been converted to all upper case.
*/
parseline(s, msg)
register char *s ;
struct OURMSG *msg ;
{
int flags ;
register short t ;
register int key ;
char *p ;
register struct hotkey *hk ;
flags = 0 ;
if (strncmp(s, "COMMAND", 7)==0) {
s = getword(s+7) ;
cpystr(msg->cmd, s) ;
} else if (strncmp(s, "TIMEOUT", 7)==0) {
s = getword(s+7) ;
t = 0 ;
while ('0' <= *s && *s <= '9')
t = t * 10 + *s++ - '0' ;
if (t < 0)
t = DEFTIME ;
msg->interval = t ;
} else if (strncmp(s, "LINES", 5)==0) {
msg->draw = 1 ;
} else if (strncmp(s, "BLANK", 5)==0) {
msg->draw = -1 ;
} else {
if (strncmp(s, "SHIFT", 5)==0) {
flags = SHIFT ;
s = getword(s+5) ;
}
if (*s == 0)
badline() ;
else {
if (issep(s[1]) &&
(('A' <= *s && *s <= 'Z') ||
('0' <= *s && *s <= '9'))) {
key = *s ;
s = getword(s+1) ;
} else if (strncmp(s, "SPACE", 5)==0) {
key = ' ' ;
s = getword(s+5) ;
} else if (*s == 'F' && ('1' <= s[1] && s[1] <= '9')) {
s++ ;
t = *s++ - '0' ;
if (t == 1 && *s == '0') {
t = 10 ;
s++ ;
}
key = t ;
s = getword(s) ;
} else {
badline() ;
return ;
}
if (strncmp(s, "INTUITION", 9)==0) {
flags |= NOTCLI ;
s = getword(s+9) ;
} else if (strncmp(s, "CLI", 3)==0) {
flags |= NOTINTUITION ;
s = getword(s+3) ;
}
s = cpystr(upline, s) ;
p = upline + strlen(upline) + 1 ;
if (*s)
cpystr(p, startbuf + (s-upline)) ;
else
*p = 0 ;
t = sizeof(struct hotkey) + strlen(p) + strlen(upline) ;
hk = AllocMem((long)t, MEMF_CLEAR | MEMF_PUBLIC) ;
if (hk) {
hk->key = key ;
hk->flags = flags ;
hk->next = hotkeys ;
hk->structlen = t ;
hk->matchstring = strcpy(hk->strings, upline) ;
hk->startstring = strcpy(hk->strings + strlen(upline) + 1, p) ;
if (hk->startstring[0]==0)
hk->startstring = NULL ;
hotkeys = hk ;
} else
puts("Out of memory in startup") ;
}
}
}
/*
* Handle the startup file.
*/
processstartup(s, msg)
char *s ;
struct OURMSG *msg ;
{
FILE *f ;
register char *p ;
if (f=fopen(s, "r")) {
while (fgets(startbuf, MAXSTARTUPLINE, f)) {
p = getword(startbuf) ;
if (*p != '*' && *p != '#' && *p != ';' && *p != 0) {
upcase(upline, p) ;
parseline(upline, msg) ;
}
}
fclose(f) ;
} else {
puts("Couldn't open startup file:") ;
puts(s) ;
}
}
/*
* This stuff down here handles the raw key conversion stuff
* properly. Thanks to Willy Langeveld and Carolyn Scheppner.
*/
char *dos_rkcv();
int dos_rkcvinit(), dos_rkcvexit();
struct IOStdReq ConStdReq;
/*
* This code won't compile under Manx unless you delete the
* `ConsoleDevice' function in functions.h, or perform a kludge
* like the one I did when I included it. Why the hell does
* Manx have that in there? If you try to use it, it comes out
* undefined, but if you rename the following, it won't link
* because it needs the function `ConsoleDevice'.
*/
long ConsoleDevice ;
/**
*
* Calling sequence:
* =================
*
* result = (char *) dos_rkcv(code, buffer, length);
*
* Description:
* ============
*
* Covert raw key number to array of console device ascii text
* using the default keymap.
*
* Inputs:
* =======
*
* int code Raw key number.
* int qual Qualifier.
* char *buffer Pointer to an array of char to receive the
* conversion.
* int length length of buffer.
*
* Outputs:
* ========
*
* F. value: NULL on conversion failure, or pointer to
* buffer on success.
*
**/
char *dos_rkcv(code, qual, buffer, length)
int code;
int qual;
char *buffer;
int length;
{
static struct InputEvent event;
event.ie_Class = IECLASS_RAWKEY;
event.ie_Code = code;
event.ie_Qualifier = qual;
if (RawKeyConvert(&event, buffer, (long) length, NULL) == 0L) return(0L);
return(buffer);
}
/**
*
* Calling sequence:
* =================
*
* error = dos_rkcvinit();
*
* Description:
* ============
*
* Open the Console device for later use with dos_rkcv().
*
* Inputs:
* =======
*
* None
*
* Outputs:
* ========
*
* F. value: 1 on failure, zero otherwise.
*
*
**/
int dos_rkcvinit()
{
if (OpenDevice("console.device", -1L, &ConStdReq, 0L) != NULL) {
ConsoleDevice = 0L;
return(1);
}
else {
ConsoleDevice = (long) ConStdReq.io_Device;
return(0);
}
}
/**
*
* Calling sequence:
* =================
*
* error = dos_rkcvexit();
*
* Description:
* ============
*
* Close the Console device after use with dos_rkcv().
*
* Inputs:
* =======
*
* None
*
* Outputs:
* ========
*
* F. value: Always zero;
*
**/
int dos_rkcvexit()
{
if (ConsoleDevice) CloseDevice(&ConStdReq);
return(0);
}
/*
* Set up the key conversion table. Note that the buffer has to be
* long word aligned!
*/
initkeytoasc() {
register int i ;
char buf[100] ;
for (i=0; i<128; i++)
keytoasc[i] = '.' ;
if (dos_rkcvinit())
return(1) ;
for (i=0; i<128; i++) {
buf[1] = 0 ;
if (dos_rkcv(i, 0, buf, 100) && buf[1] == 0 &&
(buf[0] == ' ' ||
('a' <= buf[0] && buf[0] <= 'z' && (buf[0] -= 32)) ||
('0' <= buf[0] && buf[0] <= '9'))) {
keytoasc[i] = buf[0] ;
}
}
/*
* Have to handle the function keys separately
*/
for (i=80; i<90; i++)
keytoasc[i] = i-79 ;
dos_rkcvexit() ;
return(0) ;
}
/*
* Save a byte or two.
*/
_wb_parse() {}