/*
* Swap_Buttons.c
*
* This example swaps the function of the left and right mouse buttons
* The C code is just the wrapper that installs and removes the
* input.device handler that does the work.
*
* The handler is written in assembly code since it is important that
* handlers be as fast as possible while processing the input events.
*
* Compile and link as follows:
*
* SAS C 5.10:
* LC -b1 -cfirst -v -w Swap_Buttons.c
*
* Adapt assemble:
* HX68 InputHandler.a to InputHandler.o
*
* BLink:
* BLink from LIB:c.o+Swap_Buttons.o+InputHandler.o LIB LIB:lc.lib
* LIB:amiga.lib TO Swap_Buttons
*
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <devices/input.h>
#include <intuition/intuition.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/intuition_protos.h>
#include <stdio.h>
#ifdef LATTICE
int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */
int chkabort(void) { return(0); } /* really */
#endif
UBYTE NameString[]="Swap Buttons";
struct NewWindow mywin={50,40,124,18,0,1,CLOSEWINDOW,
WINDOWDRAG|WINDOWCLOSE|SIMPLE_REFRESH|NOCAREREFRESH,
NULL,NULL,NameString,NULL,NULL,0,0,0,0,WBENCHSCREEN};
extern VOID ButtonSwap();
extern struct IntuitionBase *IntuitionBase;
/*
* This routine opens a window and waits for the one event that
* can happen (CLOSEWINDOW) This is just to let the user play with
* the swapped buttons and then close the program...
*/
VOID WaitForUser(VOID)
{
struct Window *win;
if (IntuitionBase=(struct IntuitionBase *)
OpenLibrary("intuition.library",33L))
{
if (win=OpenWindow(&mywin))
{
WaitPort(win->UserPort);
ReplyMsg(GetMsg(win->UserPort));
CloseWindow(win);
}
CloseLibrary((struct Library *)IntuitionBase);
}
}
VOID main(VOID)
{
struct IOStdReq *inputReqBlk;
struct MsgPort *inputPort;
struct Interrupt *inputHandler;
if (inputPort=CreatePort(NULL,NULL))
{
if (inputHandler=AllocMem(sizeof(struct Interrupt),
MEMF_PUBLIC|MEMF_CLEAR))
{
if (inputReqBlk=(struct IOStdReq *)CreateExtIO(inputPort,
sizeof(struct IOStdReq)))
{
if (!OpenDevice("input.device",NULL,
(struct IORequest *)inputReqBlk,NULL))
{
inputHandler->is_Code=ButtonSwap;
inputHandler->is_Data=NULL;
inputHandler->is_Node.ln_Pri=100;
inputHandler->is_Node.ln_Name=NameString;
inputReqBlk->io_Data=(APTR)inputHandler;
inputReqBlk->io_Command=IND_ADDHANDLER;
DoIO((struct IORequest *)inputReqBlk);
WaitForUser();
inputReqBlk->io_Data=(APTR)inputHandler;
inputReqBlk->io_Command=IND_REMHANDLER;
DoIO((struct IORequest *)inputReqBlk);
CloseDevice((struct IORequest *)inputReqBlk);
}
else
printf("Error: Could not open input.device\n");
DeleteExtIO((struct IORequest *)inputReqBlk);
}
else
printf("Error: Could not create I/O request\n");
FreeMem(inputHandler,sizeof(struct Interrupt));
}
else
printf("Error: Could not allocate interrupt struct memory\n");
DeletePort(inputPort);
}
else
printf("Error: Could not create message port\n");
}
************************************************************************
* InputHandler.a
*
* InputHandler that does a Left/Right mouse button swap...
*
* See Swap_Buttons.c for details on how to compile/assemble/link...
*
************************************************************************
*
* Required includes...
*
INCDIR "include:"
INCLUDE "exec/types.i"
INCLUDE "exec/io.i"
INCLUDE "devices/inputevent.i"
*
************************************************************************
*
* Make the entry point external...
*
xdef _ButtonSwap
*
************************************************************************
*
* This is the input handler that will swap the
* mouse buttons for left handed use.
*
* The event list gets passed to you in a0.
* The is_Data field is passed to you in a1.
* This example does not use the is_Data field...
*
* On exit you must return the event list in d0. In this way
* you could add or remove items from the event list.
*
* The handler gets called here...
*
*
_ButtonSwap: move.l a0,-(sp) ; Save the event list
*
* Since the event list could be a linked list, we start a loop
* here to handle all of the events passed to us.
*
CheckLoop: move.w ie_Qualifier(a0),d1 ; Get qualifiers...
move.w d1,d0 ; Two places...
*
* Since we are changing left and right mouse buttons, we need to make
* sure that we change the qualifiers on all of the messages. The
* left and right mouse buttons are tracked in the message qualifiers
* for use in such things as dragging. To make sure that we continue
* to drag correctly, we change the qualifiers.
*
CheckRight: btst #IEQUALIFIERB_RBUTTON,d1 ; Check for right
beq.s NoRight
bset #IEQUALIFIERB_LEFTBUTTON,d0 ; Set the left...
beq.s CheckLeft
NoRight: bclr #IEQUALIFIERB_LEFTBUTTON,d0 ; Clear the left...
*
CheckLeft: btst #IEQUALIFIERB_LEFTBUTTON,d1 ; Check for left
beq.s NoLeft
bset #IEQUALIFIERB_RBUTTON,d0 ; Set the right...
beq.s SaveQual
NoLeft: bclr #IEQUALIFIERB_RBUTTON,d0 ; Clear the right..
*
SaveQual: move.w d0,ie_Qualifier(a0) ; Save back...
*
* The actual button up/down events are transmitted as the
* code field in RAWMOUSE events. The code field must the be
* checked and modified when needed on RAWMOUSE events. If the
* event is not a RAWMOUSE, we are done with it.
*
cmp.b #IECLASS_RAWMOUSE,ie_Class(a0) ; Check for mouse
bne.s NextEvent ; If not, next...
*
move.w ie_Code(a0),d0 ; Get code...
move.w d0,d1 ; Save...
and.w #$7F,d0 ; Mask UP_PREFIX
cmp.w #IECODE_LBUTTON,d0 ; Check for Left...
beq.s SwapThem ; If so, swap...
cmp.w #IECODE_RBUTTON,d0 ; Check for Right..
bne.s NextEvent ; If not, next...
*
SwapThem: eor.w #1,d1 ; Flip bottom bit
move.w d1,ie_Code(a0) ; Save it...
*
* The event list is linked via a pointer to the next event
* in the first element of the structure. That is why it is not
* nessesary to use: move.l ie_NextEvent(a0),d0
*
* The reason I move to d0 first is that this also checks for zero.
* The last event in the list will have a NULL ie_NextEvent field.
* This is NOT as standard EXEC list where the node after the last
* node is NULL. Input events are single-linked for performance.
*
NextEvent: move.l (a0),d0 ; Get next event
move.l d0,a0 ; into a0...
bne.s CheckLoop ; Do some more.
*
* All done, just return the event list... (in d0)
*
move.l (sp)+,d0 ; Get event list back...
rts ; return from handler...