/* * LeftyMouse.c * * Commodity * * Author: Stefan Sticht * * Copyright: source is public domain, no copyright * * Version history: * * V1.01 initial release * V1.02 recompiled with main.c V1.02 * V1.03 completly rewritten; shared commodity code thrown away; smaller, uses less CPU time * V1.04 some really minor changes * V1.05 recompiled with changed (for 68040 compatiblity) cback.o * V1.06 removed filter for rawmouse-events, because mousebutton-qualifiers have to be changed * in not-rawmouse-events, too; no one reported me this; anyone using it? * made faults in the change-the-buttons-code; * changed default priority in commodities list to 1 for better * usability with ClickToFront or toBack&Front */ #define VERSION "V1.06" /******************************************************************** * interfacing * ********************************************************************/ /* * include files */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DEBUG #define printf KPrintF #include #endif /* * prototypes */ long request(char *title, char *gadgets, char *text, ...); struct Library *myopenlibrary(char *name, unsigned long version); void __saveds leftymouse(register CxMsg *cxm); void processmessages(void); /* * global data defined in other moduls * * libraries opened by startup code; basepointers needed by function pragmas */ extern struct Library *DOSBase; extern struct Library *SysBase; /* * Disable SAS/C CTRL/C handling */ void chkabort(void) {} /******************************************************************** * global data * ********************************************************************/ /* * definition of all messages (multi language support not completed yet) */ #ifdef GERMAN #define RETRY_GADGETS "Wiederholen|Abbrechen" #define RESUME_GADGETS "Weiter" #define MSG_LIBRARY_OPENERR "Die %s (V%ld+) kann nicht geöffnet werden!" #define COM_NAME "LeftyMouse" #define COM_DESCR "Vertauscht linke und rechte Maustaste" #else #define RETRY_GADGETS "Retry|Cancel" #define RESUME_GADGETS "Resume" #define MSG_LIBRARY_OPENERR "%s (V%ld+) can't be opened!" #define COM_NAME "LeftyMouse" #define COM_DESCR "Swaps left and right mousebutton" #endif #define COM_TITLE COM_NAME " " VERSION #define CX_PRIORITY "CX_PRIORITY" #define DEF_CX_PRIORITY 1 /* * data for cback.o */ long _stack = 2048l; char *_procname = COM_NAME; long _priority = 0l; long _BackGroundIO = 1; extern BPTR _Backstdout; /* * library base pointers */ struct Library *IntuitionBase; struct Library *CxBase; struct Library *IconBase; /* * message port */ struct MsgPort *cxport = NULL; /* * signal flag */ unsigned long cxsigflag = 0l; /* * programtitle and version for Version command */ char versionstring[] ="\0$VER: " COM_NAME " " VERSION; /* * helpstring */ #ifdef GERMAN char helpstring[] = "\033[1m" COM_NAME "\033[0m " VERSION " (Public Domain) von Stefan Sticht\n"\ "Aufruf: " COM_NAME " [" CX_PRIORITY "=]\n"; #else char helpstring[] = "\033[1m" COM_NAME "\033[0m " VERSION " (Public Domain) by Stefan Sticht\n" "Usage: " COM_NAME " [" CX_PRIORITY "=]\n"; #endif /* * the tooltypearray */ char **tooltypes; /* * our broker */ CxObj *broker = NULL; struct NewBroker newbroker = { NB_VERSION, /* BYTE nb_Version */ COM_NAME, /* BYTE *nb_Name */ COM_TITLE, /* BYTE *nb_Title */ COM_DESCR, /* BYTE *nb_Descr */ NBU_NOTIFY | NBU_UNIQUE, /* SHORT nb_Unique */ 0, /* SHORT nb_Flags */ 0, /* BYTE nb_Pri */ NULL, /* struct MsgPort nb_Port */ 0 /* WORD nb_ReservedChannel */ }; /******************************************************************** * functions * ********************************************************************/ /* * request(): a glue routine to EasyRequest as simple as printf plus * titlestring, gadgettexts * * Input: char *title: pointer to the title of the requester * char *gadgets: pointer to gadgettext * char *text: text displayed in requester * * Result: same as EasyrequestArgs() * * !!! for more info see EasyRequestArgs() in Autodocs/intuition.doc !!! */ long request(char *title, char *gadgets, char *text, ...) { /* * structure textreq only needed in this function, so hide it here * must be static, in order to be initialized only once */ static struct EasyStruct textreq = { sizeof (struct EasyStruct), /* ULONG es_StructSize */ 0l, /* ULONG es_Flags */ NULL, /* UBYTE *es_Title */ NULL, /* UBYTE *es_TextFormat */ NULL, /* UBYTE *es_GadgetFormat */ }; va_list ap; long rc; /* * get start of variable arguments */ va_start(ap, text); /* * update textreq */ textreq.es_Title = (UBYTE *)title; textreq.es_TextFormat = (UBYTE *)text; textreq.es_GadgetFormat = (UBYTE *)gadgets; /* * win may be NULL */ rc = EasyRequestArgs(NULL, &textreq, NULL, ap); va_end(ap); return(rc); } /* * myopenlibrary(): same as OpenLibrary(), but opens a retry-requester * if OpenLibrary() fails, to give the user a chance to * copy the library to libs: and retry * requires request(), see above */ struct Library *myopenlibrary(char *name, unsigned long version) { static char errortext[] = MSG_LIBRARY_OPENERR; struct Library *libptr; long ok = TRUE; do { if (!(libptr = OpenLibrary((UBYTE *)name, version))) { if (IntuitionBase) ok = request(COM_NAME ":", RETRY_GADGETS, errortext, name, version); else ok = FALSE; } } while (!libptr && ok); return(libptr); } void main(int argc, char *argv[]) { CxObj *customobj; struct Message *msg; if ((argc > 1) && (*argv[1] == '?')) { /* * display help string */ if (_Backstdout) { Write(_Backstdout, helpstring, sizeof(helpstring) - 1l); Close(_Backstdout); } return; } else if (argc && _Backstdout) Close(_Backstdout); if (IntuitionBase = myopenlibrary("intuition.library", 37l)) { /* * parse command line or tool types * * we need icon.library therefore */ if (IconBase = myopenlibrary("icon.library", 37l)) { /* * create tooltypes array (requires icon.library open!!!) */ tooltypes = (char **)ArgArrayInit(argc, argv); newbroker.nb_Pri = ArgInt(tooltypes, CX_PRIORITY, DEF_CX_PRIORITY); ArgArrayDone(); CloseLibrary(IconBase); if (CxBase = myopenlibrary("commodities.library", 37l)) { /* * create our message port */ if (cxport = CreateMsgPort()) { cxsigflag = 1l << cxport->mp_SigBit; newbroker.nb_Port = cxport; if (broker = CxBroker(&newbroker, NULL)) { if (customobj = CxCustom(leftymouse, 0l)) { AttachCxObj(broker, customobj); if (!CxObjError(broker)) { /* * activate our commodity */ ActivateCxObj(broker, 1l); /* * now watch our numerous ports */ processmessages(); } /* if !CxObjError() */ } /* if customobj */ DeleteCxObjAll(broker); } /* if broker */ #ifdef DEBUG else printf("main(): CxBroker() failed!\n"); #endif /* * delete our message port after replying all pending messages */ while (msg = GetMsg(cxport)) ReplyMsg(msg); DeleteMsgPort(cxport); } /* if cxport */ #ifdef DEBUG else printf("main(): CraeteMsgPort() failed!\n"); #endif CloseLibrary(CxBase); } /* if CxBase */ } /* if IconBase */ CloseLibrary(IntuitionBase); } /* if IntuitionBase */ } /* main() */ void processmessages(void) { struct Message *msg; unsigned long msgid; unsigned long msgtype; unsigned long sigreceived; unsigned short quit = FALSE; while (!quit) { sigreceived = Wait(SIGBREAKF_CTRL_C | cxsigflag); #ifdef DEBUG printf("processmessages(): signal received\n"); #endif if (sigreceived & SIGBREAKF_CTRL_C) quit = TRUE; if (sigreceived & cxsigflag) { while (msg = (struct Message *)GetMsg(cxport)) { msgid = CxMsgID((CxMsg *)msg); msgtype = CxMsgType((CxMsg *)msg); ReplyMsg(msg); switch (msgtype) { case CXM_COMMAND: switch (msgid) { case CXCMD_UNIQUE: case CXCMD_KILL: quit = TRUE; break; case CXCMD_DISABLE: ActivateCxObj(broker, 0l); break; case CXCMD_ENABLE: ActivateCxObj(broker, 1l); break; } break; } /* switch msgtype */ } /* while CxMsg */ } /* if (sigreceived & cxsigflag) */ } /* while !quit */ ActivateCxObj(broker, 0l); } void __saveds leftymouse(CxMsg *cxm) { /* * this function is called directly from somewhere, * so set up base register A4 with __saveds */ register struct InputEvent *ie; register UWORD code; if (ie = (struct InputEvent *)CxMsgData(cxm)) { if (ie->ie_Class == IECLASS_RAWMOUSE && ie->ie_Code != IECODE_NOBUTTON) { code = ie->ie_Code & 0x7f; if (code == IECODE_LBUTTON || code == IECODE_RBUTTON) { /* * IECODE_LBUTTON <-> IECODE_RBUTTON * IECODE_LBUTTON | IECODE_UP_PREFIX <-> IECODE_RBUTTON | IECODE_UP_PREFIX */ #ifdef DEBUG printf("Class: %lx Original code: %lx ", ie->ie_Class, ie->ie_Code); #endif ie->ie_Code ^= 0x0001; #ifdef DEBUG printf("changed to %lx\n", ie->ie_Code); #endif } } /* * IEQUALIFIER_LEFTBUTTON | IEQUALIFIER_RELATIVEMOUSE <-> * IEQUALIFIER_RBUTTON | IEQUALIFIER_RELATIVEMOUSE */ if (ie->ie_Qualifier & 0x6000) { #ifdef DEBUG printf("Class: %lx Original qualifier: %lx ", ie->ie_Class, ie->ie_Qualifier); #endif ie->ie_Qualifier ^= 0x6000; #ifdef DEBUG printf("changed to %lx\n", ie->ie_Qualifier); #endif } } }