home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD1.img
/
d1xx
/
d161
/
mackie
/
mackie.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-10-02
|
37KB
|
1,311 lines
/*
Modified to work with Manx 3.6a; probably won't work with Lattice.
Based on:
*/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* |_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!)
*/
typedef struct
{
struct Task *buddy ;
ULONG creatclisig ;
ULONG unblanksig ;
ULONG frontsig ;
ULONG noevents ;
short creatsignum ;
short blanksignum ;
short replysignum ;
short frontsignum ;
short key ;
char frontkey[MAXPENDINGSYSTEM] ;
char frontqual[MAXPENDINGSYSTEM] ;
short frontptr ;
short draw ;
short helppressed ;
struct Screen *blankscreen ;
} GLOBAL_DATA;
#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 */
register GLOBAL_DATA *gptr; /* Everything we need to know about */
{
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 == gptr->key)) ||
(!gptr->helppressed && ep->ie_Code == 0x5f) ||
(gptr->helppressed &&
(ep->ie_Code & 0x80) == 0 &&
/*
* All the qualifiers have code = 0x6?; dangerous to take advantage
* of?
*/
(ep->ie_Code & 0xf0) != 0x60 &&
gptr->frontkey[gptr->frontptr] == 0 &&
(gptr->helppressed = (keytoasc[ep->ie_Code] != '.'))))) {
if ((ep->ie_Qualifier & IEQUALIFIER_LCOMMAND) &&
(ep->ie_Code == gptr->key))
key = -1 ;
else if (gptr->helppressed) {
gptr->frontkey[gptr->frontptr] = key = ep->ie_Code ;
gptr->frontqual[gptr->frontptr] = ep->ie_Qualifier ;
gptr->frontptr++ ;
if (gptr->frontptr >= MAXPENDINGSYSTEM)
gptr->frontptr = 0 ;
gptr->helppressed = 0 ;
} else {
gptr->helppressed = 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(gptr->buddy, gptr->creatclisig);
else if (key > 0)
Signal(gptr->buddy, gptr->frontsig);
} else
laste = ep;
if (ep->ie_Class != IECLASS_TIMER) {
gptr->noevents = 0;
if (gptr->blankscreen != NULL)
Signal(gptr->buddy, gptr->unblanksig);
}
}
/* 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)
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 );
}
/************************************************************************/
/* the main program to do the popcli stuff */
/************************************************************************/
GLOBAL_DATA global;
main(argc, argv)
int argc ;
char *argv[] ;
{
struct MsgPort *port;
int stay = 0;
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;
struct Interrupt handlerStuff;
char *cmd ;
int draw = 0 ;
int nextfront = 0 ;
SetTaskPri(FindTask(0L), 20L) ;
global.creatsignum = -1;
global.blanksignum = -1;
global.replysignum = -1;
global.frontsignum = -1;
global.blankscreen = NULL;
global.key = DEFKEY ;
global.draw = 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 = 0 ;
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.1 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] ;
}
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)
global.draw = draw ;
PutMsg(port,(struct Message *)msg);
if (!stay) goto abort;
if (timeout == 0)
timeout = DEFTIME ;
global.blankscreen = NULL;
global.buddy = FindTask(0L);
global.noevents = 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) ||
((global.creatsignum = AllocSignal(-1L)) == -1) ||
((global.blanksignum = AllocSignal(-1L)) == -1) ||
((global.replysignum = AllocSignal(-1L)) == -1) ||
((global.frontsignum = 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)&global;
handlerStuff.is_Code = HandlerInterface;
handlerStuff.is_Node.ln_Pri = 51;
timersig = (1L << timerport->mp_SigBit);
global.creatclisig = 1L << global.creatsignum;
global.unblanksig = 1L << global.blanksignum;
global.frontsig = 1L << global.frontsignum;
inputRequestBlock->io_Command = IND_ADDHANDLER;
inputRequestBlock->io_Data = (APTR)&handlerStuff;
DoIO((struct IORequest *)inputRequestBlock);
QueueTimer(timerreq, TIMEINTERVAL);
for(;;) { /* FOREVER */
sig = Wait( global.creatclisig | global.unblanksig | timersig |
global.frontsig);
/* 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)
global.key = msg->key;
if (msg->interval)
timeout = msg->interval;
if (msg->draw)
global.draw = msg->draw ;
FreeMem((char *)msg, (long)msg->msgpart.mn_Length);
if (msg->key == -1) goto abort;
}
if ((sig & global.unblanksig) && global.blankscreen)
screenunblank() ;
if (sig & global.creatclisig) {
WBenchToFront();
(void)Execute(cmdstr,nullfh,nullfh);
}
if (sig & global.frontsig) {
while (i=global.frontkey[nextfront]) {
windowtofront(keytoasc[i], global.frontqual[nextfront]) ;
global.frontkey[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 ((global.noevents++ >= timeout) && (global.blankscreen == 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 (global.creatsignum != -1) FreeSignal(global.creatsignum);
if (global.blanksignum != -1) FreeSignal(global.blanksignum);
if (global.replysignum != -1) FreeSignal(global.replysignum);
if (global.frontsignum != -1) FreeSignal(global.frontsignum);
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);
SetTaskPri(FindTask(0L), 0L) ;
}
struct IOStdReq *
CreateIOReq(port, size)
struct MsgPort *port;
long size;
{
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)
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 (100)
/*
* 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() {
screenheight = 2 * GfxBase->NormalDisplayRows ;
screenwidth = GfxBase->NormalDisplayColumns ;
newscreen.Height = screenheight ;
newscreen.Width = screenwidth ;
if (global.draw == -1 || AvailMem(MEMF_CHIP) < 70000L ||
(global.blankscreen = OpenScreen(&newscreen)) == NULL) {
if ((global.blankscreen = OpenScreen(&NewScreen)) != NULL) {
SetRGB4(&(global.blankscreen->ViewPort), 0L, 0L, 0L, 0L);
OFF_DISPLAY ;
}
} else {
if (global.blankscreen == NULL &&
(global.blankscreen = 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(&(global.blankscreen->ViewPort), 0L, 0L, 0L, 0L) ;
rastport = &(global.blankscreen->RastPort) ;
SetAPen(rastport, 0L) ;
Forbid() ;
RectFill(rastport, 0L, 0L, (long)screenwidth-1, 30L) ;
Permit() ;
SetAPen(rastport, 1L) ;
task = (struct Task *)AllocMem((long)sizeof(struct Task),
MEMF_CLEAR | MEMF_PUBLIC) ;
if (task != NULL) {
task->tc_Node.ln_Pri = 10 ;
task->tc_Node.ln_Type = NT_TASK ;
task->tc_Node.ln_Name = "ri.Lines" ;
task->tc_SPLower = (APTR)stackmem ;
task->tc_SPUpper = task->tc_SPReg = (APTR)(stackmem + STACKSIZE/4 - 8) ;
AddTask(task, taskrout, 0L) ;
}
}
}
/*
* 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 << global.replysignum) ;
RemTask(task);
FreeMem(task, (long)sizeof(struct Task)) ;
task = NULL ;
}
if (global.blankscreen != NULL) {
CloseScreen(global.blankscreen);
global.blankscreen = NULL ;
ON_DISPLAY ;
ON_SPRITE ;
}
}
/*
* This routine returns a random value from 0 to n-1.
*/
int randm(i)
int i ;
{
static long seed ;
long rval ;
if (seed == 0)
seed = 323214521 + global.blankscreen->MouseX +
global.blankscreen->MouseY ;
seed = seed * 123213 + 121 ;
rval = (seed >> 5) & 65535 ;
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.
*/
short x1store[MAXLINES], y1store[MAXLINES] ;
short x2store[MAXLINES], y2store[MAXLINES] ;
short ptr ;
short dx1, dy1, dx2, dy2 ;
short ox1, oy1, ox2, oy2 ;
short nx1, ny1, nx2, ny2 ;
short dr, dg, db ;
short or, og, ob ;
short nr, ng, nb ;
/*
* Initialize things for the first lines.
*/
startlines() {
ptr = 0 ;
if (dx1 == 0) {
ox1 = randm(screenwidth) ;
ox2 = randm(screenwidth) ;
oy1 = randm(screenheight) ;
oy2 = randm(screenheight) ;
dx1 = 3 ;
dx2 = 4 ;
dy1 = 1 ;
dy2 = 6 ;
nr = 53 ;
ng = 33 ;
nb = 35 ;
dr = -3 ;
dg = 5 ;
db = 7 ;
}
SetRGB4(&(global.blankscreen->ViewPort), 0L, 0L, 0L, 0L) ;
SetRGB4(&(global.blankscreen->ViewPort), 1L, (long)(nr >> 3),
(long)(ng >> 3), (long)(nb >> 3)) ;
}
/*
* Advance the number by the delta, and check the boundaries.
*/
adv(o, d, n, w)
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() {
adv(&ox1, &dx1, &nx1, screenwidth) ;
adv(&ox2, &dx2, &nx2, screenwidth) ;
adv(&oy1, &dy1, &ny1, screenheight) ;
adv(&oy2, &dy2, &ny2, screenheight) ;
}
/*
* Draw a new set of lines.
*/
drawnew() {
x1store[ptr] = ox1 = nx1 ;
x2store[ptr] = ox2 = nx2 ;
y1store[ptr] = oy1 = ny1 ;
y2store[ptr] = oy2 = ny2 ;
Move(rastport, (long)ox1, (long)oy1) ;
Draw(rastport, (long)ox2, (long)oy2) ;
Draw(rastport, (long)(screenwidth-ox1-1), (long)(screenheight-oy1-1)) ;
Draw(rastport, (long)(screenwidth-ox2-1), (long)(screenheight-oy2-1)) ;
Draw(rastport, (long)ox1, (long)oy1) ;
ptr++ ;
if (ptr == MAXLINES)
ptr = 0 ;
}
/*
* Erase the old line.
*/
eraseold() {
short oldpen ;
oldpen = rastport->FgPen ;
SetAPen(rastport, 0L) ;
Move(rastport, (long)x1store[ptr], (long)y1store[ptr]) ;
Draw(rastport, (long)x2store[ptr], (long)y2store[ptr]) ;
Draw(rastport, (long)(screenwidth-x1store[ptr]-1),
(long)(screenheight-y1store[ptr]-1)) ;
Draw(rastport, (long)(screenwidth-x2store[ptr]-1),
(long)(screenheight-y2store[ptr]-1)) ;
Draw(rastport, (long)x1store[ptr], (long)y1store[ptr]) ;
SetAPen(rastport, (long)oldpen) ;
}
/*
* 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(&(global.blankscreen->ViewPort), 1L, (long)(nr >> 3),
(long)(ng >> 3), (long)(nb >> 3)) ;
}
/*
* Our actual task, in an infinite loop.
*/
void taskrout() {
long i ;
struct Task *task ;
geta4() ;
task = FindTask(0L) ;
startlines() ;
for (i=0; i<MAXLINES; i++) {
advancelines() ;
drawnew() ;
if (SetSignal(0L, 0L))
goto done ;
}
colors() ;
while (SetSignal(0L, 0L)==0) {
if (task->tc_Node.ln_Pri == 10)
SetTaskPri(task, -20L) ;
eraseold() ;
advancelines() ;
drawnew() ;
eraseold() ;
advancelines() ;
drawnew() ;
if (task->tc_Node.ln_Pri == 10)
SetTaskPri(task, -20L) ;
eraseold() ;
advancelines() ;
drawnew() ;
eraseold() ;
advancelines() ;
drawnew() ;
if (task->tc_Node.ln_Pri == 10)
SetTaskPri(task, -20L) ;
eraseold() ;
advancelines() ;
drawnew() ;
eraseold() ;
advancelines() ;
drawnew() ;
colors() ;
}
done:
Signal(global.buddy, 1L << global.replysignum) ;
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 ;
int i, j ;
int n ;
struct Window *w ;
struct Screen *s ;
struct Process *p ;
struct MsgPort **mp ;
struct CommandLineInterface *CLI ;
int cli ;
char *nameptr, *matchptr ;
extern struct DosLibrary *DOSBase ;
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 ;
Execute(hk->startstring, 0L, 0L) ;
} 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)
char *s, *key ;
{
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 ;
short t ;
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++ ;
}
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 ;
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) ;
}
}
} 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) ;
}