/* * toBack&Front.c * * Commodity * * Author: Stefan Sticht * * Copyright: source is public domain, no copyright * * Version history: * * V1.00 initial release * V1.01 some minor changes * V1.02 changed myparseix for commodities.library 37.27 * uses now utility.library's Stricmp() * V1.03 added some LockIBase() */ #define VERSION "V1.03" /******************************************************************** * interfacing * ********************************************************************/ /* * include files */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DEBUG #define printf KPrintF #include #endif /* * prototypes */ struct Library *myopenlibrary(char *name, unsigned long version); void processmessages(void); void backorfront(unsigned short mode); /* located in myparseix.c */ long myparseix(char *description, IX *ix); /* * 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 messages */ #ifdef GERMAN /* * Wenn jemand bessere Übersetzungsvorschläge hat, soll er mir die bitte mitteilen! * (This is german. If you don't understand, doesn't matter) */ #define COM_NAME "toBack&Front" #define RETRY_GADGETS "Wiederholen|Abbrechen" #define RESUME_GADGETS "Weiter" #define MSG_LIBRARY_OPENERR "Die %s (V%ld+) kann nicht geöffnet werden!" #define COM_DESCR "Fenster o. Schirm nach hinten o. vorne" #define YES "JA" #define NO "NEIN" #else #define COM_NAME "toBack&Front" #define RETRY_GADGETS "Retry|Cancel" #define RESUME_GADGETS "Resume" #define MSG_LIBRARY_OPENERR "%s (V%ld+) can't be opened!" #define COM_DESCR "Window or screen to back or front" #define YES "YES" #define NO "NO" #endif #define COM_TITLE COM_NAME " " VERSION #define CX_PRIORITY "CX_PRIORITY" #define DEF_CX_PRIORITY 0 #define TT_FRONT_ACTION "FRONT_ACTION" #define TT_FRONT_CLICKS "FRONT_CLICKS" #define TT_FRONT_REMOVE "FRONT_REMOVE" #define DEF_TT_FRONT_ACTION "rawmouse leftbutton lbuttoncode" #define DEF_TT_FRONT_CLICKS 2 #define DEF_TT_FRONT_REMOVE NO #define TT_BACK_ACTION "BACK_ACTION" #define TT_BACK_CLICKS "BACK_CLICKS" #define TT_BACK_REMOVE "BACK_REMOVE" #define DEF_TT_BACK_ACTION "rawmouse lalt leftbutton lbuttoncode" #define DEF_TT_BACK_CLICKS 2 #define DEF_TT_BACK_REMOVE YES /* * data for cback.o */ #ifndef DEBUG long _stack = 2048l; char *_procname = COM_NAME; long _priority = 21l; long _BackGroundIO = 1; extern BPTR _Backstdout; #endif /* * library base pointers */ struct IntuitionBase *IntuitionBase; struct Library *CxBase; struct Library *IconBase; struct Library *LayersBase; struct Library *UtilityBase; /* * message ports */ struct MsgPort *cxport; /* * signal flags */ unsigned long cxsigflag; /* * 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 "=] [" TT_FRONT_ACTION "=]"\ " [" TT_FRONT_REMOVE "=" YES "|" NO "] [" TT_FRONT_CLICKS "=] ["\ TT_BACK_ACTION "=] [" TT_BACK_REMOVE "=" YES "|" NO "] [" TT_BACK_CLICKS "=]\n"; #else char helpstring[] = "\033[1m" COM_NAME "\033[0m " VERSION " (Public Domain) by Stefan Sticht\n" "Usage: " COM_NAME " [" CX_PRIORITY "=] [" TT_FRONT_ACTION "=]"\ " [" TT_FRONT_REMOVE "=" YES "|" NO "] [" TT_FRONT_CLICKS "=] ["\ TT_BACK_ACTION "=] [" TT_BACK_REMOVE "=" YES "|" NO "] [" TT_BACK_CLICKS "=]\n"; #endif /* * number of clicks required */ unsigned char requiredbackclicks; unsigned char requiredfrontclicks; #define FRONT 1 #define BACK 2 /* * the tooltypearray */ char **tooltypes; /* * our broker */ CxObj *broker; 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 */ }; IX backix = { IX_VERSION, /* UBYTE ix_version */ 0, /* UBYTE ix_Class */ 0, /* UWORD ix_Code */ 0, /* UWORD ix_CodeMask */ 0, /* UWORD ix_Qualifier */ 0, /* UWORD ix_QualMask */ 0 /* UWORD ix_QualSame */ }; IX frontix = { IX_VERSION, /* UBYTE ix_version */ 0, /* UBYTE ix_Class */ 0, /* UWORD ix_Code */ 0, /* UWORD ix_CodeMask */ 0, /* UWORD ix_Qualifier */ 0, /* UWORD ix_QualMask */ 0 /* UWORD ix_QualSame */ }; /******************************************************************** * 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); #ifdef DEBUG printf("myopenlibrary(%s, %ld) = 0x%lx\n", name, version, libptr); #endif return(libptr); } void main(int argc, char *argv[]) { CxObj *obj; CxObj *frontfilter = NULL; CxObj *backfilter = NULL; char *frontaction; char *backaction; struct Message *msg; if ((argc > 1) && (*argv[1] == '?')) { /* * display help string */ #ifndef DEBUG if (_Backstdout) { Write(_Backstdout, helpstring, sizeof(helpstring) - 1l); Close(_Backstdout); } #else Write(Output(), helpstring, sizeof(helpstring) - 1l); #endif return; } #ifndef DEBUG else if (argc && _Backstdout) Close(_Backstdout); #endif /* * open required libraries first */ if (IntuitionBase = (struct IntuitionBase *)myopenlibrary("intuition.library", 37l)) { if (CxBase = myopenlibrary("commodities.library", 37l)) { if (IconBase = myopenlibrary("icon.library", 37l)) { if (LayersBase = myopenlibrary("layers.library", 37l)) { /* * create tooltypes array (requires icon.library open!!!) */ tooltypes = (char **)ArgArrayInit(argc, argv); backaction = ArgString(tooltypes, TT_BACK_ACTION, DEF_TT_BACK_ACTION); frontaction = ArgString(tooltypes, TT_FRONT_ACTION, DEF_TT_FRONT_ACTION); if (backaction && *backaction) { myparseix(backaction, &backix); requiredbackclicks = (unsigned char)ArgInt(tooltypes, TT_BACK_CLICKS, DEF_TT_BACK_CLICKS); } else backaction = NULL; if (frontaction && *frontaction) { myparseix(frontaction, &frontix); requiredfrontclicks = (unsigned char)ArgInt(tooltypes, TT_FRONT_CLICKS, DEF_TT_FRONT_CLICKS); } else frontaction = NULL; if (frontaction || backaction) { /* * create our message port */ if (cxport = CreateMsgPort()) { cxsigflag = 1l << cxport->mp_SigBit; /* * set up some broker data */ newbroker.nb_Pri = ArgInt(tooltypes, CX_PRIORITY, DEF_CX_PRIORITY); newbroker.nb_Port = cxport; if (broker = CxBroker(&newbroker, NULL)) { if (frontaction && (frontfilter = CxFilter(NULL))) { AttachCxObj(broker, frontfilter); SetFilterIX(frontfilter, &frontix); } if (backaction && (backfilter = CxFilter(NULL))) { AttachCxObj(broker, backfilter); SetFilterIX(backfilter, &backix); } if (frontfilter || backfilter) { if (UtilityBase = myopenlibrary("utility.library", 37l)) { if (frontfilter && (obj = CxSender(cxport, FRONT))) { AttachCxObj(frontfilter, obj); /* * check if input-event shall be removed */ if (!Stricmp((char *)ArgString(tooltypes, TT_FRONT_REMOVE, DEF_TT_FRONT_REMOVE), YES)) { #ifdef DEBUG printf("main(): installing NULL-translator for front-action\n"); #endif /* * install a NULL-translator, which removes the ie */ if (obj = CxTranslate(NULL)) AttachCxObj(frontfilter, obj); } } if (backfilter && (obj = CxSender(cxport, BACK))) { AttachCxObj(backfilter, obj); /* * check if input-event shall be removed */ if (!Stricmp((char *)ArgString(tooltypes, TT_FRONT_REMOVE, DEF_TT_FRONT_REMOVE), YES)) { #ifdef DEBUG printf("main(): installing NULL-translator for front-action\n"); #endif /* * install a NULL-translator, which removes the ie */ if (obj = CxTranslate(NULL)) AttachCxObj(backfilter, obj); } } /* * close library here, we don't need it any longer */ CloseLibrary(UtilityBase); if ((frontfilter && !CxObjError(frontfilter)) || (backfilter && !CxObjError(backfilter))) { /* * activate our commodity */ ActivateCxObj(broker, 1l); /* * now watch our numerous ports */ processmessages(); } /* if !CxObjError() */ } /* if UtilityBase */ } /* if frontfilter || backfilter */ 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(): CreateMsgPort() failed!\n"); #endif } /* if (frontaction || backaction) */ ArgArrayDone(); CloseLibrary(LayersBase); } /* if LayersBase */ CloseLibrary(IconBase); } /* if IconBase */ CloseLibrary(CxBase); } /* if CxBase */ CloseLibrary((struct Library *)IntuitionBase); } /* if IntuitionBase */ } /* main() */ void processmessages(void) { static unsigned long lastfrontmicros = 0l; static unsigned long lastfrontsecs = 0l; static unsigned long lastbackmicros = 0l; static unsigned long lastbacksecs = 0l; static unsigned char frontclicks = 0; static unsigned char backclicks = 0; struct InputEvent *ie; struct Message *msg; unsigned long sigreceived; unsigned long msgtype; unsigned long msgid; unsigned long micros; unsigned long secs; unsigned char quit = FALSE; if (requiredfrontclicks == 1) frontclicks = 1; if (requiredbackclicks == 1) backclicks = 1; 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); if ((msgtype == CXM_IEVENT) && (ie = (struct InputEvent *)CxMsgData((CxMsg *)msg))) { /* * copy the interesting data of the inputevent */ secs = ie->ie_TimeStamp.tv_secs; micros = ie->ie_TimeStamp.tv_micro; #ifdef DEBUG if (msgid == FRONT) printf("action = FRONT\n"); else printf("action = BACK\n"); printf("ie_Class = 0x%lx\n", ie->ie_Class); printf("ie_SubClass = 0x%lx\n", ie->ie_SubClass); printf("ie_Code= 0x%lx\n", ie->ie_Code); printf("ie_Qualifier = 0x%lx\n", ie->ie_Qualifier); printf("secs = 0x%lx\n", secs); printf("micros = 0x%lx\n", micros); #endif } ReplyMsg(msg); switch (msgtype) { case CXM_IEVENT: switch (msgid) { case FRONT: if (requiredfrontclicks > 1) { if (DoubleClick(lastfrontsecs, lastfrontmicros, secs, micros)) frontclicks++; else frontclicks = 1; lastfrontsecs = secs; lastfrontmicros = micros; } if (frontclicks == requiredfrontclicks) { backorfront(FRONT); if (requiredfrontclicks > 1) frontclicks = 0; } break; case BACK: if (requiredbackclicks > 1) { if (DoubleClick(lastbacksecs, lastbackmicros, secs, micros)) backclicks++; else backclicks = 1; lastbacksecs = secs; lastbackmicros = micros; } if (backclicks == requiredbackclicks) { backorfront(BACK); if (requiredbackclicks > 1) backclicks = 0; } break; } case CXM_COMMAND: switch (msgid) { case CXCMD_UNIQUE: case CXCMD_KILL: quit = TRUE; 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 backorfront(unsigned short mode) { unsigned long lock; register struct Screen *scr; register struct Window *win; register struct Layer *layer; #ifdef DEBUG if (mode == BACK) printf("backorfront(BACK)\n"); else printf("backorfront(FRONT)\n"); #endif /* * here we go: find screen */ lock = LockIBase(0l); for (scr = IntuitionBase->FirstScreen; scr && (scr->TopEdge > 0) && (scr->MouseY < 0); scr = scr->NextScreen); if (scr) { #ifdef DEBUG printf("backorfront(): scr = 0x%lx\n", scr); #endif /* * get layer */ LockLayerInfo(&scr->LayerInfo); layer = WhichLayer(&scr->LayerInfo, (long)scr->MouseX, (long)scr->MouseY); UnlockLayerInfo(&scr->LayerInfo); #ifdef DEBUG printf("backorfront(): layer = 0x%lx\n", layer); #endif if (layer && layer != scr->BarLayer) { if ((win = (struct Window *)layer->Window) && !(win->Flags & BACKDROP)) { if (win->NextWindow || win->WScreen->FirstWindow != win) { #ifdef DEBUG printf("backorfront(): using win 0x%lx for action\n", win); #endif UnlockIBase(lock); if (mode == BACK) WindowToBack(win); else WindowToFront(win); } else UnlockIBase(lock); } /* if win */ else { /* * no win or win = backdrop => switch screen to back */ #ifdef DEBUG printf("backorfront(): using scr 0x%lx for action (no win)\n", scr); #endif UnlockIBase(lock); if (mode == BACK) ScreenToBack(scr); else if (scr != IntuitionBase->FirstScreen) ScreenToFront(scr); } } /* if layer */ else { /* * no layer: */ #ifdef DEBUG printf("backorfront(): using scr 0x%lx for action (no layer)\n", scr); #endif UnlockIBase(0l); if (mode == BACK) ScreenToBack(scr); else if (scr != IntuitionBase->FirstScreen) ScreenToFront(scr); } } /* if scr */ else UnlockIBase(0l); }