afb@j.cc.purdue.edu (Matthew Bradburn) (12/07/87)
This is an update to the ClickToFront utility by Davide P. Cervone, which brings a window or screen to the front or pushes it to the back when the user double clicks in that window or screen. Docs in comp.binaries.amiga. The author: Davide P. Cervone dpvc@tut.cc.rochester.edu dpvc@ur-tut.UUCP DPVC@UORDBV.BITNET The poster: Matthew Bradburn ARPA: afb@j.cc.purdue.edu UUCP: j.cc.purdue.edu!afb BITNET: bradburn@purccvm.bitnet # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # Click-Handler.c # ClickUpFront.c # Click-Handler.lnk # ClickUpFront.lnk # HandlerStub.a # This archive created: Sun Dec 6 20:50:52 1987 # By: Matthew Bradburn (Purdue University) echo shar: extracting Click-Handler.c '(7244 characters)' cat << \SHAR_EOF > Click-Handler.c /* * Click-Handler.c Input Handler for ClickUpFront, which brings a * window to the front when you double-click in it. * * Copyright (c) 1987 by Davide P. Cervone * You may use this code provided this copyright notice is left intact. */ #include <exec/types.h> #include <devices/inputevent.h> #include <intuition/intuitionbase.h> static char *version = "Click-Handler v2.1 (October 1987)"; static char *author = "Copyright (c) 1987 by Davide P. Cervone"; extern struct Layer *WhichLayer(); extern void myHandlerStub(); #define WINDOW(layer) ((struct Window *)((layer)->Window)) #define TOPLAYER(screen) ((screen)->LayerInfo.top_layer) #define ie_Secs ie_TimeStamp.tv_secs #define ie_Mics ie_TimeStamp.tv_micro static UBYTE LastCode = 0; /* the last ie_Code for a button event */ static long LastSecs = 0; /* seconds field from last mouse click */ static long LastMics = 0; /* micros field from last mouse click */ static long StayMask; /* qualifier keys that allow you to click */ /* a window without bringing it to the front */ struct IntuitionBase *IntuitionBase = NULL; struct LayersBase *LayersBase = NULL; struct SysBase *SysBase = NULL; /* * Setup() * * ClickUpFront calls LoadSeg() to get this handler into memory. The segment * that it gets points to this routine. ClickUpFront calls Setup() and * passes the IntuitionBase, LayersBase and SysBase pointers that it * has initialized (with OpenLibrary()). Setup returns a pointer to * the actual input handler, which ClickUpFront installs. */ static long Setup(Ibase,Lbase,Sbase,flags) struct IntuitionBase *Ibase; struct LayersBase *Lbase; struct SysBase *Sbase; long flags; { IntuitionBase = Ibase; LayersBase = Lbase; SysBase = Sbase; StayMask = flags; return((long) &myHandlerStub); } /* * myHandler() * * This is the input handler. For each event in the event list: * If it is a raw mouse event: * Ignore button-up events, * For button down events, if it is the same as the last button, and * the mouse has not moved, and the button was a double click, then * Find the active window and screen (where the button press occured) * for SELECTDOWN buttons: * If the screen is not the first one, then bring it to the front. * If a window is selected, then find the top layer with a window. * If the window where the click ocurred is not the top, and * the stay-put qualifier key is not pressed, then * bring the window to the front. * for MENUDOWN buttons: * If a window is selected, and the window is not the bottom window * already, and the window below it is not a backdrop window, then * if the selected window has no double-menu requester and * the stay-put qualifier is not present (if there IS a * DM request and the stay-put qualifier IS present), then * send the window to the back. * change the event into a mouse move with zero offsets * (that is, remove one of the right button clicks). * otherwise (there is no window, or it is already at the bottom, * or the one below is a backdrop), then * find the first window on the next screen and activate it. * Send the active screen to the back. * Otherwise (the mouse was moved, or it was not a double click, etc.) * record this click and the time it ocurred. * For mouse moves, clear the last code (ie, don't match a double click) * If the event was a keyboard event, then set the times to zero. * Ignore all other event types (timer, disk). * * Finally, return the event list so that Intuition can do its thing. * */ struct InputEvent *myHandler(EventList,data) struct InputEvent *EventList; APTR data; { register struct InputEvent *theEvent = EventList; register struct Window *theWindow; register struct Screen *theScreen; register struct Layer *topLayer; Forbid(); while(theEvent) { switch(theEvent->ie_Class) { case IECLASS_RAWMOUSE: if ((theEvent->ie_Code & IECODE_UP_PREFIX) == 0) { if (theEvent->ie_Code == LastCode && theEvent->ie_X == 0 && theEvent->ie_Y == 0 && DoubleClick(LastSecs,LastMics, theEvent->ie_Secs,theEvent->ie_Mics)) { theWindow = IntuitionBase->ActiveWindow; theScreen = IntuitionBase->ActiveScreen; switch(LastCode) { case SELECTDOWN: if (theScreen != IntuitionBase->FirstScreen) ScreenToFront(theScreen); if (theWindow) { topLayer = TOPLAYER(theScreen); while (topLayer && WINDOW(topLayer) == NULL) topLayer = topLayer->back; if (theWindow != WINDOW(topLayer) && (theEvent->ie_Qualifier & StayMask) == 0) WindowToFront(theWindow); } break; case MENUDOWN: if (theWindow && theWindow->WLayer->back && (theWindow->Flags & BACKDROP) == 0 && (theWindow->WLayer->back->Flags & LAYERBACKDROP) == 0) { if (theWindow && (theWindow->DMRequest == NULL) == ((theEvent->ie_Qualifier & StayMask) == 0)) { WindowToBack(theWindow); theEvent->ie_Code = IECODE_NOBUTTON; theEvent->ie_X = theEvent->ie_Y = 0; } } else { if (theScreen->NextScreen) { topLayer = TOPLAYER(theScreen->NextScreen); while (topLayer && WINDOW(topLayer) == NULL) topLayer = topLayer->back; if (topLayer && WINDOW(topLayer)) ActivateWindow(WINDOW(topLayer)); ScreenToBack(theScreen); } } break; } LastCode = 0; } else { LastCode = theEvent->ie_Code; LastSecs = theEvent->ie_Secs; LastMics = theEvent->ie_Mics; } } else { if (theEvent->ie_Code == IECODE_NOBUTTON) LastCode = 0; } break; case IECLASS_RAWKEY: LastSecs = LastMics = 0; break; } theEvent = theEvent->ie_NextEvent; } Permit(); return(EventList); } SHAR_EOF if test 7244 -ne "`wc -c Click-Handler.c`" then echo shar: error transmitting Click-Handler.c '(should have been 7244 characters)' fi echo shar: extracting ClickUpFront.c '(9317 characters)' cat << \SHAR_EOF > ClickUpFront.c /* * ClickUpFront.c Brings a window to the front when you double-click * in it (unless specified qualifier keys are also pressed). * * Copyright (c) 1987 by Davide P. Cervone * You may use this code provided this copyright notice is left intact. */ #include <exec/types.h> #include <libraries/dos.h> #include <exec/io.h> #include <exec/memory.h> #include <exec/interrupts.h> #include <devices/input.h> #include <devices/inputevent.h> static char *program = "ClickUpFront"; static char *version = "v1.0"; static char *date = "July 1987"; static char *author = "Copyright (c) 1987 by Davide P. Cervone"; static char *PortName = "ClickUpFrontPort"; static char *handler = "L:Click-Handler"; /* the handler file */ #define HANDLER &(handler[2]) /* without the "L:" */ #define STAYMASK (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT) /* * This is the structure that holds the handler information between calls * to ClickUpFront. We create a named, public message-port that points to * an instance of this structure so that we can find this information * when we are asked to remove the handler. The PortName is stored here * (NamedPort->mp_Node.ln_Name uses this area for it's name). The other * data are what we need in order to remove the handler and clean up properly. */ struct HandlerBlock { char *PortName; /* name of the public, named message-port */ struct Interrupt Handler; /* the handler added to the handler chain */ struct IntuitionBase *Ibase; /* library base used by the handler */ struct LayersBase *Lbase; /* library base used by the handler */ long Segment; /* pointer from LoadSeg() */ }; #define HANDLERINFOSIZE sizeof(struct HandlerBlock) #define NAMESIZE (strlen(PortName)+1) extern struct MsgPort *CreatePort(); extern struct IOStdReq *CreateStdIO(); extern struct MsgPort *FindPort(), *CreatePort(); extern APTR AllocMem(); extern long LoadSeg(); #define INTUITION_REV 0L #define LAYERS_REV 0L struct IntuitionBase *IntuitionBase = NULL; struct LayersBase *LayersBase = NULL; extern struct SysBase *SysBase; struct MsgPort *InputPort = NULL; /* Port used to talk to Input.Device */ struct IOStdReq *InputBlock = NULL; /* request block used with Input.Device */ LONG InputDevice = 0; /* flag whether Input.Device is open */ struct MsgPort *NamedPort = NULL; /* holds info needed to remove handler */ struct HandlerBlock *HandlerInfo = NULL; /* holds info stored in NamedPort */ /* * DoExit() * * General purpose exit routine. If 's' is not NULL, then print an * error message with up to three parameters. Free any memory, close * any open device, delete any ports, close any libraries, etc. */ void DoExit(s,x1,x2,x3) char *s, *x1, *x2, *x3; { long status = RETURN_OK; if (s != NULL) { printf(s,x1,x2,x3); printf("\n"); status = RETURN_ERROR; } if (InputDevice) CloseDevice(InputBlock); if (InputBlock) DeleteStdIO(InputBlock); if (InputPort) DeletePort(InputPort); if (NamedPort) DeletePort(NamedPort); if (HandlerInfo) { if (HandlerInfo->PortName) FreeMem(HandlerInfo->PortName,NAMESIZE); FreeMem(HandlerInfo,HANDLERINFOSIZE); } if (IntuitionBase) CloseLibrary(IntuitionBase); if (LayersBase) CloseLibrary(LayersBase); exit(status); } /* * CheckLibOpen() * * General library open routine. It opens a library and sets a pointer * to it. It checks that the library was openned successfully. */ void CheckLibOpen(lib,name,rev) APTR *lib; char *name; int rev; { extern APTR OpenLibrary(); if ((*lib = OpenLibrary(name,(LONG)rev)) == NULL) DoExit("Can't open '%s'\n",name); } /* * Macros that make memory allocation easier. */ #define NEW(s,var) (var = (struct s *)New("var",sizeof(struct s))) #define NEWCHAR(var,s) (var = (char *)New("var",s)) /* * New() * * Allocate public memory of a given size and set it to all zeros. If there * is not enough memory, then exit with an error, otherwise return the * pointer to the newly allocated memory. */ APTR New(name,size) char *name; int size; { APTR ptr; if ((ptr = AllocMem(size,MEMF_PUBLIC | MEMF_CLEAR)) == NULL) DoExit("Can't Get Memory for '%s'"); return(ptr); } /* * TellInputDevice() * * Create a port and I/O block, and open the input device. Set up the * I/O block to add or remove the input handler, and send the request * to the input device. Finally, close the device and delete the * I/O block and port. */ void TellInputDevice(function) int function; { long status; if ((InputPort = CreatePort(0,0)) == NULL) DoExit("Can't Create Port"); if ((InputBlock = CreateStdIO(InputPort)) == NULL) DoExit("Can't Create Standard IO Block"); InputDevice = (OpenDevice("input.device",0,InputBlock,0) == 0); if (InputDevice == FALSE) DoExit("Can't Open 'input.device'"); InputBlock->io_Command = (long) function; InputBlock->io_Data = (APTR) &(HandlerInfo->Handler); if (status = DoIO(InputBlock)) DoExit("Error from DoIO: %ld",status); CloseDevice(InputBlock); DeleteStdIO(InputBlock); DeletePort(InputPort); } /* * CreateHandler() * * Open the libraries needed by the input handler and store their locations * in the HandlerInfo structure (so we can close them later). Try to * LoadSeg() the handler. If it is not in the current directory, try the * L: directory. Exit with an error if the handler can't be found. * Convert the segment pointer into a pointer to the Setup routine (the * first routine in the handler executable). Call Setup() and pass it * the pointers to the libraries that it will need to use. Setup() returns * a pointer to the actual handler routine that should be added into the * input handler chain. Store this in the HandlerInfo structure so we * can use it to remove the handler later. Set the handler priority to * 51 so that it is ahead of Intuition. * * Finally, add the handler in the chain and tell the user that the * handler has been installed. */ void CreateHandler(argc,argv) int argc; char **argv; { long (*Setup)(); long flags = STAYMASK; CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV); CheckLibOpen(&LayersBase,"layers.library",LAYERS_REV); if (argc > 1) sscanf(argv[1],"%lx",&flags); HandlerInfo->Ibase = IntuitionBase; HandlerInfo->Lbase = LayersBase; if ((HandlerInfo->Segment = LoadSeg(HANDLER)) == NULL) if ((HandlerInfo->Segment = LoadSeg(handler)) == NULL) DoExit("Can't Load '%s'",handler); Setup = (long (*)()) ((HandlerInfo->Segment << 2) + 4); HandlerInfo->Handler.is_Code = (void (*)()) ((*Setup)(IntuitionBase,LayersBase,SysBase,flags)); HandlerInfo->Handler.is_Node.ln_Pri = 51; TellInputDevice(IND_ADDHANDLER); printf("%s %s (%s) Installed\n",program,version,date); } /* * Delete Handler() * * Retreive the library pointers fro mthe HandlerInfo structure, where * we stored them when we originally installed the handler, then remove * the handler from the input handler chain. Tell the user that the * handler is gone, and then close the libraries that are no longer needed. */ void DeleteHandler() { IntuitionBase = HandlerInfo->Ibase; LayersBase = HandlerInfo->Lbase; TellInputDevice(IND_REMHANDLER); UnLoadSeg(HandlerInfo->Segment); printf("%s Removed\n",program); CloseLibrary(IntuitionBase); CloseLibrary(LayersBase); } /* * main() * * Check if a message port with our name already exists. * If not, then the handler is not already installed, so: * Allocate a new HandlerInfo structure and initialize the port name. * Create a public, named message-port (we will look for this the next * time ClickUpFront is called). * Make the message port point to the HandlerInfo structure so we * can use it later when the user asks us to remove the handler. * Note that the port is not actually used for putting and getting * messages, so the Task field is never used, so we can take it for * our own uses. * Finally, add the input handler into the chain. * Otherwise, the port exists, so ClickUpFront already is installed: * Retreive the HandlerInfo poiner from the port, and remove the * handler from the input handler chain. * Free the memory used by the HandlerInfo, and delete the message port. */ void main(argc,argv) int argc; char **argv; { NamedPort = FindPort(PortName); if (NamedPort == NULL) { NEW(HandlerBlock,HandlerInfo); NEWCHAR(HandlerInfo->PortName,NAMESIZE); strcpy(HandlerInfo->PortName,PortName); if ((NamedPort = CreatePort(HandlerInfo->PortName,0)) == NULL) DoExit("Can't Create Message Port '%s'",PortName); NamedPort->mp_SigTask = (struct Task *)HandlerInfo; CreateHandler(argc,argv); } else { HandlerInfo = (struct HandlerBlock *)(NamedPort->mp_SigTask); DeleteHandler(); FreeMem(HandlerInfo->PortName,NAMESIZE); FreeMem(HandlerInfo,HANDLERINFOSIZE); DeletePort(NamedPort); } } SHAR_EOF if test 9317 -ne "`wc -c ClickUpFront.c`" then echo shar: error transmitting ClickUpFront.c '(should have been 9317 characters)' fi echo shar: extracting Click-Handler.lnk '(98 characters)' cat << \SHAR_EOF > Click-Handler.lnk FROM Click-Handler.o+handlerstub.o TO Click-Handler LIB LIB:amiga.lib NODEBUG SMALLDATA SMALLCODE SHAR_EOF if test 98 -ne "`wc -c Click-Handler.lnk`" then echo shar: error transmitting Click-Handler.lnk '(should have been 98 characters)' fi echo shar: extracting ClickUpFront.lnk '(101 characters)' cat << \SHAR_EOF > ClickUpFront.lnk FROM LIB:c.o+ClickUpFront.o TO ClickUpFront LIB LIB:lc.lib+LIB:amiga.lib NODEBUG SMALLDATA SMALLCODE SHAR_EOF if test 101 -ne "`wc -c ClickUpFront.lnk`" then echo shar: error transmitting ClickUpFront.lnk '(should have been 101 characters)' fi echo shar: extracting HandlerStub.a '(215 characters)' cat << \SHAR_EOF > HandlerStub.a CSECT text XREF _myHandler XDEF _myHandlerStub _myHandlerStub: MOVEM.L A0/A1,-(A7) JSR _myHandler ADDQ.L #8,A7 RTS END SHAR_EOF if test 215 -ne "`wc -c HandlerStub.a`" then echo shar: error transmitting HandlerStub.a '(should have been 215 characters)' fi # End of shell archive exit 0