[comp.sources.amiga] v02i008: dmouse - mouse accelerator plus V1.10

page@swan.ulowell.edu (Bob Page) (10/22/88)

Submitted-by: dillon@cory.berkeley.edu (Matt Dillon)
Posting-number: Volume 2, Issue 8
Archive-name: intuition/dmouse.1

[Docs are with the binary, source hackers read the code.  :-)   ..Bob]

# This is a shell archive.  Remove anything before this line
# then unpack it by saving it in a file and typing "sh file"
# (Files unpacked will be owned by you and have default permissions).
# This archive contains the following files:
#	./Makefile
#	./dmouse-handler.c
#	./dmouse.c
#	./dmouse.h
#
if `test ! -s ./Makefile`
then
echo "writing ./Makefile"
cat > ./Makefile << '\Rogue\Monster\'

#   Makefile for DMouse
#
#   +L = 32 bit ints

SYMS=	include:symbols.m
SYMC=	include:local/makesymbols.c
CFLAGS= +L +I$(SYMS)

SR1 = dmouse.c
SR2 = dmouse-handler.c

OB1 = ram:dmouse.o
OB2 = ram:dmouse-handler.o

EX1 = c:dmouse
EX2 = l:dmouse-handler


all:	$(SYMS) $(EX1) $(EX2)

arc:
    copy dmouse-handler.c ram:dmouse-h.c
    copy l:dmouse-handler ram:dmouse-h
    -delete ram:dm.arc
    arc a ram:dm ram:dmouse-h.c ram:dmouse-h dmouse.doc dmouse.c c:dmouse execute.me
    delete ram:dmouse-h.c ram:dmouse-h

$(EX1) : $(OB1)
    ln +Q $(OB1) -lc32 -o $(EX1)

$(EX2) : $(OB2)
    ln +Q $(OB2) -lc32 -ldres -o $(EX2)


$(OB1) : $(SR1)
    cc $(CFLAGS) $(SR1) -o $(OB1)

$(OB2) : $(SR2)
    cc $(CFLAGS) $(SR2) -o $(OB2)

$(SYMS):    $(SYMC)
    make -f include:local/Makefile

\Rogue\Monster\
else
  echo "will not over write ./Makefile"
fi
if [ `wc -c ./Makefile | awk '{printf $1}'` -ne 782 ]
then
echo `wc -c ./Makefile | awk '{print "Got " $1 ", Expected " 782}'`
fi
if `test ! -s ./dmouse-handler.c`
then
echo "writing ./dmouse-handler.c"
cat > ./dmouse-handler.c << '\Rogue\Monster\'

/*
 *  DMOUSE-HANDLER.C		compile 32 bit integers (+L), c32.lib
 *				AZTEC COMPILATION
 *  28 June 1988
 *
 *  Note on upping the handler process priority.  This is done to cause the
 *  handler task to get CPU before the current input event completes its
 *  processing so intuition calls made by the process are executed before
 *  the event is propogated.  If said intuition calls block, it's ok
 *  because they are not blocking the input handler process.
 */

#include "dmouse.h"


DMS	*Dms;
IBASE	*IntuitionBase;
GFXBASE *GfxBase;
long	*LayersBase;
long	*DResBase;

static PORT    *IPCPort = NULL;

static char	STimedout = 0;
static char	MTimedout = 0;
static long	STime = 0, MTime = 0;


#define IBASE IntuitionBase

NS	Ns = {	0, 0, 64, -1, 1, -1, -1, 0, CUSTOMSCREEN|SCREENQUIET };
IE DummyIE = { 0 };

IE *handler();

short	NRMe;	/*  Don't Repeat Mouse Events   */

_main()
{
    register DMS *dms;
    IOR  *ior;
    INT addhand;

    {
	register PROC *proc = (PROC *)FindTask(NULL);
	proc->pr_ConsoleTask = NULL;
    }
    NRMe = 0;
    dms = Dms = (DMS *)FindPort(PORTNAME);
    if (!dms)
	_exit(0);
    dms->Port.mp_Flags = PA_SIGNAL;
    dms->Port.mp_SigBit = AllocSignal(-1);
    dms->Port.mp_SigTask = FindTask(NULL);
    dms->HandTask = dms->Port.mp_SigTask;
    ior = CreateStdIO(&dms->Port);
    IntuitionBase = OpenLibrary("intuition.library", 0);
    GfxBase = OpenLibrary("graphics.library", 0);
    LayersBase = OpenLibrary("layers.library", 0);
    DResBase = OpenLibrary("dres.library", 0);      /*  not required    */

    if (!IntuitionBase || !GfxBase || !LayersBase)
	goto startupfail;
    addhand.is_Node.ln_Pri = dms->IPri;
    addhand.is_Code = (FPTR)handler;
    addhand.is_Data = NULL;

    if (OpenDevice("input.device", 0, ior, 0)) {
	goto startupfail;
    } else {
	SCR *scr = NULL;
	uword *SprSavePtr = NULL;
	long ipc_mask = 0;

	Signal(dms->ShakeTask, 1 << dms->ShakeSig);
	ior->io_Command = IND_ADDHANDLER;
	ior->io_Data = (APTR)&addhand;
	ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
	DoIO(ior);

	if (DResBase) {
	    if (IPCPort = OpenIPC("dmouse.CMD", 0))
		ipc_mask = 1 << IPCPort->mp_SigBit;
	}
	for (;;) {
	    register long sigs = Wait(SBF_C|(1<<dms->Port.mp_SigBit)|ipc_mask);
	    if (sigs & (1 << dms->Port.mp_SigBit)) {
		register REQ *msg;
		while (msg = GetMsg(&dms->Port)) {
		    switch((long)msg->Msg.mn_Node.ln_Name) {
		    case REQ_SCREENON:
			if (scr)
			    CloseScreen(scr);
			scr = NULL;
			break;
		    case REQ_SCREENOFF:
			if (scr) {
			    ScreenToFront(scr);
			} else {
			    if (scr = OpenScreen(&Ns))
				SetRGB4(&scr->ViewPort, 0, 0, 0, 0);
			}
			break;
		    case REQ_MOUSEON:
			if (SprSavePtr) {
			    register COPINIT *ci = GfxBase->copinit;
			    ci->sprstrtup[1] = (ulong)SprSavePtr >> 16;
			    ci->sprstrtup[3] = (uword)(long)SprSavePtr;
			    SprSavePtr = NULL;
			}
			break;
		    case REQ_MOUSEOFF:
			{
			    register COPINIT *ci = GfxBase->copinit;
			    if (!SprSavePtr)
				SprSavePtr = (uword *)((ci->sprstrtup[1] << 16) | ci->sprstrtup[3]);
			    ci->sprstrtup[1] = (ulong)dms->NoSprData >> 16;
			    ci->sprstrtup[3] = (uword)(long)dms->NoSprData;
			}
			break;
		    case REQ_DOCMD:
			{
			    long fh = Open("nil:", 1006);
			    Execute(dms->Cmd, NULL, fh);
			    if (fh)
				Close(fh);
			}
			break;
		    case REQ_RAWMOUSE:
			{
			    register LAYER *layer;

			    NRMe = 0;
			    Forbid();
			    layer = WhichMouseLayer();
			    if (msg->ie_Code == IECODE_RBUTTON && dms->LMBEnable && (msg->ie_Qualifier & dms->RQual)) {
				register WIN *win;
				if (layer && (win = (WIN *)layer->Window) && !(win->Flags & BACKDROP) && (win->NextWindow || win->WScreen->FirstWindow != win)) {
				    if (dms->Workbench)
					WindowToBack(win);
				    else
					BehindLayer(0, layer);
				} else if (IBASE->FirstScreen)
				    ScreenToBack(IBASE->FirstScreen);
			    }
			    if (layer && layer->Window) {
				if (msg->ie_Code == IECODE_LBUTTON && !(((WIN *)layer->Window)->Flags & BACKDROP) && dms->LMBEnable && layer->ClipRect && layer->ClipRect->Next) {
				    /*
				     *	Note: Case where it is the 'first' click in a series, where dms->CTime is
				     *	      garbage, works properly no matter what DoubleClick returns.
				     */
				    if (dms->LQual == 0 || (msg->ie_Qualifier & dms->LQual)) {
					if ((APTR)dms->CWin == layer->Window && DoubleClick(dms->CTime.tv_secs, dms->CTime.tv_micro, msg->ie_TimeStamp.tv_secs, msg->ie_TimeStamp.tv_micro))
					    --dms->CLeft;
					else
					    dms->CLeft = dms->Clicks - 1;
					dms->CTime = msg->ie_TimeStamp;
					dms->CWin = (WIN *)layer->Window;
					if (dms->CLeft == 0) {
					    dms->CLeft = dms->Clicks;
					    if (dms->Workbench)
						WindowToFront(layer->Window);
					    else
						UpfrontLayer(0, layer);
					}
				    }
				}
				if ((dms->AAEnable & 1) && layer->Window != IBASE->ActiveWindow && msg->ie_Code == IECODE_NOBUTTON && !(msg->ie_Qualifier & 0x7000)) {
				    if (!IBASE->ActiveWindow || !IBASE->ActiveWindow->FirstRequest)
					ActivateWindow(layer->Window);
				}
			    }
			    Permit();
			}
			break;
		    case REQ_RAWKEY:
			{
			    register LAYER *layer;

			    Forbid();
			    layer = WhichMouseLayer();
			    if (layer && layer->Window && layer->Window != IBASE->ActiveWindow) {
				if (!IBASE->ActiveWindow || !IBASE->ActiveWindow->FirstRequest)
				    ActivateWindow(layer->Window);
			    }
			    Permit();
			}
			break;
		    }
		    FreeMem(msg, msg->Msg.mn_Length);
		}
	    }
	    if (sigs & SBF_C)
		break;
	    if (sigs & ipc_mask) {
		register IPCMSG *msg;
		register char *ptr;
		long req;
		while (msg = GetMsg(IPCPort)) {
		    req = 0;
		    if (ptr = (char *)msg->TBuf) {
			while (*ptr++);
			if (strcmp(ptr, "blank") == 0) {
			    req = REQ_SCREENOFF;
			    STimedout = 1;
			}
			if (strcmp(ptr, "noblank") == 0)
			    req = REQ_SCREENON;
			if (strcmp(ptr, "mouse") == 0)
			    req = REQ_MOUSEON;
			if (strcmp(ptr, "nomouse") == 0) {
			    MTimedout = 1;
			    req = REQ_MOUSEOFF;
			}
		    }
		    if (req)
			sendrequest(req, NULL);
		    ReplyIPC(msg, NULL, 0, ((req)?0:IF_NOTFND));
		}
	    }
	}
	ior->io_Command = IND_REMHANDLER;
	ior->io_Data = (APTR)&addhand;
	ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
	DoIO(ior);
	ior->io_Command = IND_WRITEEVENT;	/*  NULL EVENT	*/
	ior->io_Length = sizeof(IE);
	ior->io_Data = (APTR)&DummyIE;
	ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
	DoIO(ior);
	CloseDevice(ior);
	{
	    register MSG *msg;
	    while (msg = GetMsg(&dms->Port))
		FreeMem(msg, msg->mn_Length);
	}
	if (scr)
	    CloseScreen(scr);
	if (SprSavePtr) {
	    register COPINIT *ci = GfxBase->copinit;
	    ci->sprstrtup[1] = (ulong)SprSavePtr >> 16;
	    ci->sprstrtup[3] = (uword)(long)SprSavePtr;
	    SprSavePtr = NULL;
	}
    }
    goto closedown;
startupfail:
    dms->StartupError = 1;
    Signal(dms->ShakeTask, 1 << dms->ShakeSig);
    Wait(SBF_C);
closedown:
    DeleteStdIO(ior);
fail:
    if (IPCPort)
	CloseIPC(IPCPort);
    if (DResBase)
	CloseLibrary(DResBase);
    if (IntuitionBase)
	CloseLibrary(IntuitionBase);
    if (GfxBase)
	CloseLibrary(GfxBase);
    if (LayersBase)
	CloseLibrary(LayersBase);
    Forbid();
    Signal(dms->ShakeTask, 1 << dms->ShakeSig);
}


#asm
	    ;	A0 = pointer to event linked list
	    ;	A1 = pointer to my data segment
	    ;	return new event linked list in D0

	    public  _CHandler

_handler:
	    movem.l D2/D3/A0/A1/A4/A6,-(sp)
	    jsr     _CHandler
	    movem.l (sp)+,D2/D3/A0/A1/A4/A6
	    rts

#endasm

/*
 *  (1) Accellerate mouse movements.
 *  (2) Auto-Select window
 */

IE *
CHandler(scr0, scr1, Ev)
IE *Ev;
{
    register IE *ev;
    register DMS *dms;

    geta4();
    dms = Dms;
    for (ev = Ev; ev; ev = Ev->ie_NextEvent) {
	switch(ev->ie_Class) {
	case IECLASS_RAWMOUSE:
	    /*
	     *	Mouse events restore both the screen and mouse pointer.
	     */

	    STime = ev->ie_TimeStamp.tv_secs + dms->STo;
	    MTime = ev->ie_TimeStamp.tv_secs + dms->MTo;
	    if (STimedout)
		sendrequest(REQ_SCREENON, ev);
	    if (MTimedout)
		sendrequest(REQ_MOUSEON, ev);
	    STimedout = MTimedout = 0;

	    /*
	     *	Mouse Acceleration
	     */
	    {
		register short n;
		register short s;

		if (dms->Acc != 1) {
		    n = ev->ie_X;
		    s = 1;
		    if (n < 0) {
			n = -n;
			s = -1;
		    }
		    if (n > dms->AThresh)
			ev->ie_X = s * (short)((n - dms->AThresh - 1) * dms->Acc + dms->AThresh + 1);
		    n = ev->ie_Y;
		    s = 1;
		    if (n < 0) {
			n = -n;
			s = -1;
		    }
		    if (n > dms->AThresh)
			ev->ie_Y = s * (short)((n - dms->AThresh - 1) * dms->Acc + dms->AThresh + 1);
		}
	    }

	    /*
	     *	Auto Activate and LMB (win/scrn front/bak)
	     */

	    if (dms->LMBEnable && ev->ie_Code == IECODE_RBUTTON && (ev->ie_Qualifier & dms->RQual))
		ev->ie_Class = IECLASS_NULL;	/*  remove event    */
	    if (NRMe == 0 && ((dms->AAEnable & 1) || dms->LMBEnable)) {
		register short old;
		NRMe = 1;
		if (ev->ie_Code != IECODE_NOBUTTON)
		    old = SetTaskPri(dms->Port.mp_SigTask, 21);
		sendrequest(REQ_RAWMOUSE, ev);
		if (ev->ie_Code != IECODE_NOBUTTON)
		    SetTaskPri(dms->Port.mp_SigTask, old);
	    }
	    break;
	case IECLASS_RAWKEY:
	    /*
	     *	Keyboard events will kill the screen timeout but not
	     *	the mouse timeout.  Note that the priority of the
	     *	co-process must be upped to ensure it is able to make the
	     *	window active before the keystroke is passed further.
	     *
	     *	key releases are ignored
	     */
	    if (ev->ie_Code & 0x80)
		break;
	    if (dms->AAEnable & 2) {
		register short old = SetTaskPri(dms->Port.mp_SigTask, 21);
		sendrequest(REQ_RAWKEY, ev);
		SetTaskPri(dms->Port.mp_SigTask, old);
	    }
	    STime = ev->ie_TimeStamp.tv_secs + dms->STo;
	    if (STimedout) {
		sendrequest(REQ_SCREENON, ev);
		if (dms->MTo == 0)
		    sendrequest(REQ_MOUSEON, ev);
	    }
	    STimedout = 0;
	    if (ev->ie_Code == dms->Code && ev->ie_Qualifier == dms->Qual) {
		sendrequest(REQ_DOCMD, ev);
		ev->ie_Class = IECLASS_NULL;	/*  remove event    */
	    }
	    break;
	case IECLASS_TIMER:
	    /*
	     *	On a timer event, if timeout has occured execute the operation
	     *	and reset the timeout.	Note that this will cause continuous
	     *	timeouts every STo and MTo seconds... required because at any
	     *	time Intuition might turn the mouse back on or open a screen or
	     *	something and I want the blanker's to work in the long run.
	     */
	    {
		register long old;
		if (dms->Reset) {
		    dms->Reset = 0;
		    STime = ev->ie_TimeStamp.tv_secs + dms->STo;
		    MTime = ev->ie_TimeStamp.tv_secs + dms->MTo;
		}
		if (dms->STo && (old = STime - ev->ie_TimeStamp.tv_secs) < 0) {
		    STime = ev->ie_TimeStamp.tv_secs + dms->STo + 10;
		    STimedout = 1;
		    MTimedout = 1;
		    if (old > -10) {
			sendrequest(REQ_SCREENOFF, ev);
			sendrequest(REQ_MOUSEOFF, ev);
		    }
		}
		if (dms->MTo && (old = MTime - ev->ie_TimeStamp.tv_secs) < 0) {
		    MTime = ev->ie_TimeStamp.tv_secs + dms->MTo + 1;
		    MTimedout = 1;
		    if (old > -10)
			sendrequest(REQ_MOUSEOFF, ev);
		}
	    }
	    break;
	}
    }
    return(Ev);
}

sendrequest(creq, ev)
long creq;
register IE *ev;
{
    register REQ *req = AllocMem(sizeof(REQ), MEMF_PUBLIC);

    if (req) {
	req->Msg.mn_Node.ln_Name = (char *)creq;
	req->Msg.mn_ReplyPort = NULL;
	req->Msg.mn_Length = sizeof(REQ);
	if (ev) {
	    req->ie_Code = ev->ie_Code;
	    req->ie_Qualifier = ev->ie_Qualifier;
	    req->ie_TimeStamp = ev->ie_TimeStamp;
	}
	PutMsg(&Dms->Port, req);
    }
}

LAYER *
WhichMouseLayer()
{
    register struct IntuitionBase *ib = IBASE;
    register LAYER *layer = NULL;
    register SCR *scr = ib->FirstScreen;

    for (scr = ib->FirstScreen; scr; scr = scr->NextScreen) {
	register short mousey = ib->MouseY;
	register short mousex = ib->MouseX;
	if (!(scr->ViewPort.Modes & LACE))
	    mousey >>= 1;
	if (!(scr->ViewPort.Modes & HIRES))
	    mousex >>= 1;
	if (layer = WhichLayer(&scr->LayerInfo, mousex, mousey - scr->ViewPort.DyOffset))
	    break;
	if (mousey >= scr->ViewPort.DyOffset)
	    break;
    }
    return(layer);
}


\Rogue\Monster\
else
  echo "will not over write ./dmouse-handler.c"
fi
if [ `wc -c ./dmouse-handler.c | awk '{printf $1}'` -ne 12127 ]
then
echo `wc -c ./dmouse-handler.c | awk '{print "Got " $1 ", Expected " 12127}'`
fi
if `test ! -s ./dmouse.c`
then
echo "writing ./dmouse.c"
cat > ./dmouse.c << '\Rogue\Monster\'

/*
 *  DMOUSE.C	V1.10  31 July 1988	(Aztec Compile, +L  ... 32 bit ints)
 *					 and link w/ c32.lib
 *
 *  DMOUSE QUIT
 *  DMOUSE -a# -t# -s# -m# -c# -p# -w# -Ln -lqqqq -Rqqqq -An -Kcccc -Qqqqq -C cmd
 *
 *  -a#     # = acceleration, default 3.	1 to disable
 *  -t#     # = mouse threshold before acceleration takes effect, def. 0
 *		(in pixels/event)
 *  -s#     # = screen timeout, default 5min,	0 to disable
 *  -m#     # = pointer timeout, default 5 secs,0 to disable
 *  -c#     # = # of clicks to bring window to front
 *  -p#     # = input device priority
 *  -w#     1 = Use WindowToFront()/WindowToBack()  else    (workbench users)
 *	    0 = Use UpFrontLayer(), etc...                  (cli users)
 *  -L0     Disable LeftMouseButton->WindowToFront (LMB+RMB->ToBack)
 *  -L1     Enable it
 *  -lqqqq  Set qualifier + LMB for Window to front (default none)
 *  -Rqqqq  Set qualifier + RMB for Window/ScreenToBack (default LMB)
 *  -A0     Disable Auto-Activate window on mouse move
 *  -A1     Enable it, keyhit-auto-activate disabled	(bit 0 = mouse aa)
 *  -A3     Enable it, keyhit-auto-activate enabled	(bit 1 = key aa)
 *  -Kcccc  Set key code in hex that activates cmd, def is escape
 *  -Qqqqq  Set key qualifier in hex for keycode, def is left-amiga
 *  -C cmd  Set command (must be last option on command line), def NewCli
 */

#include <stdio.h>
#include "dmouse.h"

#define VERSION 10

int	Enable_Abort;	    /*	CLI break enable	*/

main(ac, av)
char *av[];
{
    register short i, j, len;
    register long val;
    register char *ptr;
    register DMS  *dms = (DMS *)FindPort(PORTNAME);
    short   exists = (dms != NULL);
    short   create = (dms == NULL);
    short   quit = 0;

    Enable_Abort = 0;
    if (create) {
	dms = AllocMem(sizeof(DMS), MEMF_PUBLIC|MEMF_CLEAR);
	dms->IPri = 51;
	dms->Version = VERSION;
	dms->Acc = 3;
	dms->STo = 5*60;
	dms->MTo = 5;
	dms->Code = 0x45;
	dms->Qual = 0x8040;
	dms->RQual= 0x4000;
	dms->Clicks = 1;
	dms->CLeft = dms->Clicks;
	strcpy(dms->Cmd, "newcli");
	dms->LMBEnable = 1;
	dms->AAEnable = 3;
	dms->NoSprData = AllocMem(12, MEMF_PUBLIC|MEMF_CHIP|MEMF_CLEAR);
	dms->NoSprData[0] = 0xFE00;
	dms->NoSprData[1] = 0xFF00;
    }

    for (i = 1; i < ac; ++i) {
	ptr = av[i];
	if (strcmp(ptr, "QUIT") == 0 || strcmp(ptr, "quit") == 0) {
	    quit = 1;
	    create = 0;
	    break;
	}
	val = atoi(ptr+2);
	if (*ptr != '-')
	    goto def;

	switch(ptr[1]) {
	case 'a':
	    dms->Acc = val;
	    break;
	case 'c':
	    if (val < 1)
		val = 1;
	    dms->Clicks = dms->CLeft = val;
	    break;
	case 'w':
	    dms->Workbench = val;
	    break;
	case 'p':
	    dms->IPri = val;
	    break;
	case 't':
	    dms->AThresh = val;
	    break;
	case 's':
	    dms->STo = val;
	    break;
	case 'm':
	    dms->MTo = val;
	    break;
	case 'L':
	    dms->LMBEnable = val;
	    break;
	case 'l':
	    dms->LQual = ahtoi(ptr+2);
	    break;
	case 'R':
	    dms->RQual = ahtoi(ptr+2);
	    break;
	case 'A':
	    dms->AAEnable = val;
	    break;
	case 'K':
	    dms->Code = ahtoi(ptr+2);
	    break;
	case 'Q':
	    dms->Qual = ahtoi(ptr+2) | 0x8000;
	    break;
	case 'C':
	    for (len = strlen(ptr+2) + 2, j = i + 1; j < ac; ++j)
		len += strlen(av[j]) + 1;
	    strcpy(dms->Cmd, ptr + 2);
	    for (j = i + 1; j < ac; ++j) {
		if (dms->Cmd[0])
		    strcat(dms->Cmd, " ");
		strcat(dms->Cmd, av[j]);
	    }
	    i = ac;
	    break;
	default:    def:
	    puts("DMOUSE QUIT  or");
	    puts("DMOUSE -a# -t# -s# -m# -Ln -Rqqqq -An -Kcccc -Qqqqq -C cmd");
	    printf("V1.%02d PUBLIC DOMAIN, Matthew Dillon, 28 June 1988\n\n", VERSION);
	    puts("  -a#     Acceleration (default 3)");
	    puts("  -t#     Accel. threshold (default 0)");
	    puts("  -s#     Screen timeout (default 300)");
	    puts("  -m#     Mouse timeout (default 5)");
	    puts("  -c#     Set # of clicks for wintofront (default 1)");
	    puts("  -p#     # = input device priority");
	    puts("  -w#     0 = use UpFrontLayer().. 1 = use WindowToFront()");
	    puts("  -L0/1   LMB disable/enable (default 1=enabled)");
	    puts("  -lqqqq  LMB qualifier wintofront (default 0=none)");
	    puts("  -Rqqqq  RMB qualifier wintoback (default 4000=LMB)");
	    puts("  -A0-3   Auto-Activate Window disable/enable. B0=mouse B1=keyboard");
	    puts("  -Kcccc  Command Key Code, default 45 = esc");
	    puts("  -Qqqqq  Command Key Qualifier, default 40 = Left Amiga");
	    puts("  -C cmd  cmd to run, must be last option");
	    puts("Note: LMB(or -R qualifier)(hold)+RMB = WindowToBack");
	    puts("\n");
	    puts("Additionaly, Most options may be modified while DMOUSE is active");
	    create = 0;
	    i = ac;
	    break;
	}
    }
    dms->Reset = 1;
    if (!exists && create) {
	PROC *proc;
	printf("Installing DMouse, ");
	fflush(stdout);
	dms->Port.mp_Flags = PA_IGNORE;
	dms->Port.mp_Node.ln_Pri = 0;
	dms->Port.mp_Node.ln_Type= NT_MSGPORT;
	dms->Port.mp_Node.ln_Name= AllocMem(sizeof(PORTNAME), MEMF_PUBLIC);
	strcpy(dms->Port.mp_Node.ln_Name, PORTNAME);
	NewList(&dms->Port.mp_MsgList);
	dms->Segment = LoadSeg("l:DMouse-Handler");
	if (!dms->Segment)
	    dms->Segment = LoadSeg("DMouse-Handler");
	if (!dms->Segment) {
	    puts("Unable to find L:DMouse-Handler");
	    FreeMem(dms->Port.mp_Node.ln_Name, sizeof(PORTNAME));
	    create = 0;
	} else {
	    AddPort(&dms->Port);
	    dms->ShakeTask = FindTask(NULL);
	    dms->ShakeSig = AllocSignal(-1);
	    proc = CreateProc(dms->Port.mp_Node.ln_Name, 1, dms->Segment, 4096);
	    Wait(1 << dms->ShakeSig);
	    FreeSignal(dms->ShakeSig);
	    exists = 1;
	    quit = dms->StartupError;
	    if (quit)
		puts("Handler error");
	    else
		printf("ok.  DMouse V1.%02d, by Matthew Dillon.  PUBLIC DOMAIN.\n", VERSION);
	}
    }
    if (quit) {
	if (exists) {
	    printf("Removing, ");
	    fflush(stdout);
	    dms->ShakeTask = FindTask(NULL);
	    dms->ShakeSig = AllocSignal(-1);
	    Signal(dms->HandTask, SBF_C);
	    Wait(1 << dms->ShakeSig);
	    FreeSignal(dms->ShakeSig);
	    RemPort(&dms->Port);
	    FreeMem(dms->Port.mp_Node.ln_Name, sizeof(PORTNAME));
	    UnLoadSeg(dms->Segment);
	    puts("ok");
	}
	exists = 0;
	create = 0;
    }
    if (!exists) {
	FreeMem(dms->NoSprData, 12);
	FreeMem(dms, sizeof(DMS));
    }
}

ahtoi(str)
register char *str;
{
    register long val = 0;
    register char c;
    while (c = *str) {
	val <<= 4;
	if (c >= '0' && c <= '9')
	    val |= (c & 15);
	else
	    val |= (c & 15) + 9;
	++str;
    }
    return(val);
}


\Rogue\Monster\
else
  echo "will not over write ./dmouse.c"
fi
if [ `wc -c ./dmouse.c | awk '{printf $1}'` -ne 6451 ]
then
echo `wc -c ./dmouse.c | awk '{print "Got " $1 ", Expected " 6451}'`
fi
if `test ! -s ./dmouse.h`
then
echo "writing ./dmouse.h"
cat > ./dmouse.h << '\Rogue\Monster\'

/*
 *  DMOUSE.H
 */

#include <local/typedefs.h>
#include <local/ipc.h>

#define DMS struct _DMS
#define REQ struct _REQ

#define PORTNAME    "DMouse"

#define REQ_SCREENON	-1
#define REQ_SCREENOFF	-2
#define REQ_MOUSEON	-3
#define REQ_MOUSEOFF	-4
#define REQ_DOCMD	-5
#define REQ_RAWMOUSE	-6
#define REQ_RAWKEY	-7

#define SBF_C	SIGBREAKF_CTRL_C
#define SBF_D	SIGBREAKF_CTRL_D
#define SBF_E	SIGBREAKF_CTRL_E
#define SBF_F	SIGBREAKF_CTRL_F

typedef struct IOStdReq     IOR;
typedef struct Interrupt    INT;
typedef struct timeval	    TS;
typedef void		    (*FPTR)();


DMS {
    PORT    Port;
    short   Version;
    short   Acc;
    short   AThresh;
    long    STo;
    long    MTo;
    uword   Code;
    uword   Qual;
    uword   RQual;	    /*	Right button qualifier	*/
    uword   LQual;	    /*	Left button qualifier	*/
    char    Cmd[256];
    char    LMBEnable;
    char    AAEnable;
    char    IPri;
    char    FSEnable;	    /*	Foreign Screen Enable	*/
    char    Workbench;	    /*	Use WindowToFront/Back	*/
    char    Reserved2;
    char    Reserved3;
    TASK    *HandTask;
    TASK    *ShakeTask;
    short   ShakeSig;
    short   StartupError;
    uword   *NoSprData;
    long    Segment;

    uword   Clicks;	/*  # clicks required		*/
    uword   CLeft;	/*  # clicks left to do 	*/
    TS	    CTime;	/*  time of last click		*/
    WIN     *CWin;	/*  All clicks in same window	*/
    char    Reset;	/*  Option modified, reset tos	*/
};

REQ {
    MSG     Msg;
    TS	    ie_TimeStamp;
    uword   ie_Code;
    uword   ie_Qualifier;
};

extern IOR *CreateStdIO();
extern SCR *OpenScreen();
extern void *AllocMem();
extern void *malloc();
extern void *GetMsg();
extern void *OpenLibrary();
extern PORT *CreatePort();
extern PROC *CreateProc();
extern LAYER *WhichMouseLayer();
extern LAYER *WhichLayer();


\Rogue\Monster\
else
  echo "will not over write ./dmouse.h"
fi
if [ `wc -c ./dmouse.h | awk '{printf $1}'` -ne 1823 ]
then
echo `wc -c ./dmouse.h | awk '{print "Got " $1 ", Expected " 1823}'`
fi
echo "Finished archive 1 of 1"
# if you want to concatenate archives, remove anything after this line
exit
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.