/************************************************************************* * * wicon.c - window iconifier (Right Mouse Button) 29-Dec-87 */ char *Version =\ "Wicon 1.14 10-May-88 Copyright (c) 1987,88 Steven Sweeting - SMAUG"; /* * Usage: wicon [ -b boxes ] [ -t ] [ -f | -!f ] [ -p priority ] * [ -q ] [ -s | -!s ] * * use the Right Mouse Button (RMB) to iconify the Active window * * Portions Copyright (c) 1987 Davide P. Cervone (Input Handler) * * May be freely distributed, hacked etc. Please include wicon.doc * if the code hasn't changed too much. * * I really like Matt Dillon's DME's iconifying windows, so I thought * there has to be a way of modifying Workbench to make it possible, * I tried doing things like moving other peoples windows from one * screen to another (SILENT) one. Then it hit me, and it was simple, * easy to program and even could be done without violating * all those Intuition laws (don't hold me to that). Try it out before * looking into the source code. * * Even if you chuck this program away, please hang on to * UnSetFunction(), so that the hackers (the old meaning) can * no only co-exist peacefully, but die peacefully as well. * * I urge others to use RMBTRAP to do the iconifying themselves * *************************************************************************/ #define WICON__C #include "wicon.h" #include #include #include #ifdef DEBUG /* hence functions/variables externally available to db */ #define Static #else DEBUG #define Static static #endif DEBUG #ifndef SMALLWICON #define ERROR char * #define ERRIBASE "Can't open intuition.library (V 33)" #define ERRGFXBASE "Can't open graphics.library (V 33)" #define ERRLAYBASE "Can't open layers.library (V 33)" #define ERRICONBASE "Can't open icon.library (V 33)" #define PROCSIGNAL "\nProcess signalled\n" #define ERRPORT "Can't open DeathPort" #define ERRWIND "Can't open little window" #define ERRSIGNAL "Couldn't allocate signal" #define ERRBACKDROP "OpenWindow: Can't open Backdrop Window" #define ERRSTDIO "CreateStdIO: Couldn't create IO block" #define ERRINPUT "OpenDevice: Couldn't open input.device" #define ERRDOIO1 "DoIo1: failed" #define ERRDOIO2 "DoIo2: failed" #define NONE NULL #else SMALLWICON #define ERROR short #define ERRIBASE 1001 #define ERRGFXBASE 1002 #define ERRLAYBASE 1003 #define ERRICONBASE 1004 #define PROCSIGNAL 1005 #define ERRPORT 1006 #define ERRWIND 1007 #define ERRSIGNAL 1008 #define ERRBACKDROP 1009 #define ERRSTDIO 1010 #define ERRINPUT 1011 #define ERRDOIO1 1012 #define ERRDOIO2 1013 #define NONE 0 #endif struct ArgList ArgList[] = { { (void *)&Arg_AllScreens, "ALLSCREENS", 1, 'a', ARGBOOL }, { (void *)&Arg_Boxes, "BOXES", 1, 'b', ARGWORD }, { (void *)&Arg_Chars, "CHARSACROSS", 1, 'c', ARGWORD }, { (void *)&Arg_Depth, "DEPTHGADGETS", 1, 'd', ARGBOOL }, { (void *)&Arg_Execute, "EXECUTE", 1, '&', ARGBOOL }, { (void *)&Arg_FirstScreen, "FIRSTSCREEN", 1, 'f', ARGBOOL }, { (void *)&Arg_Iconify, "ICONIFY", 1, 'i', ARGBOOL }, { (void *)&Arg_Lines, "LINES", 1, 'l', ARGWORD }, { (void *)&Arg_Priority, "PRIORITY", 1, 'p', ARGWORD }, { (void *)&Arg_Quiet, "QUIET", 1, 'q', ARGBOOL }, { (void *)&Arg_RMBTRAP, "RMBTRAP", 1, 'r', ARGBOOL }, { (void *)&Arg_Sticky, "STICKY", 1, 's', ARGBOOL }, { (void *)&Arg_Testing, "TESTING", 1, 't', ARGBOOL }, { (void *)&Arg_Window, "WINDOW", 6, 'W', ARGSTRING }, { (void *)&Arg_WBWs, "WBWINDOWS", 1, 'w', ARGBOOL }, { (void *)NULL } /* End of Array Marker */ }; struct FileHandle *Open(); struct NewWindow WBWindow = { 1,1, 1,1, -1,-1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 50,15, -1,-1, WBENCHSCREEN }; /************************************************************************* * WiconWait - does the hard stuff, waiting for two things * * 1 - PushMask - has a *Window been pushed to the back * 2 - SuicideMask - has this process been oredered to die * * This routine could easily be extended to wait on messages arriving * from the the Icon Windows - eg to pass on CLOSEWINDOW IntuiMessages * * 01-Jan-88 */ WiconWait() { long WaitMask=0; struct Window *Window; UWORD *Flags; while (! (WaitMask & SuicideMask) ) { WaitMask = Wait( PushMask | SuicideMask ); if (WaitMask & PushMask) { Window = PushedWindow; W_Push(Window); /* Note: an Icon may want to PULL */ } } /* We have been sent a suicide signal */ W_Cleanup(); } /************************************************************************* * main - OPENS everything * calls WiconWait * CLOSES everything, calls error(NULL) * 10-Jan-88 */ int main(argc,argv) int argc; char **argv; { WORD i; /* Misc Counter */ LONG Key; /* Lock on IntuitionBase */ #ifndef SMALLWICON extern char *GetArgs(); #endif SMALLWICON char *errString; struct Window *BWindow; struct Window *tmpWindow; static struct BoxInfo MouseBox = {0,0,0,0}; CWVector = NULL; OWVector = NULL; if ( (IntuitionBase = (struct IntuitionBase *)OpenLibrary( "intuition.library", 33L ))==NULL ) error(ERRIBASE); if ( (GfxBase = (struct GfxBase *)OpenLibrary( "graphics.library", 33L ))==NULL ) error(ERRGFXBASE); if ( (LayersBase = (struct LayersBase *)OpenLibrary( "layers.library", 33L ))==NULL ) error(ERRLAYBASE); if ( (IconBase = (struct IconBase *)OpenLibrary( "icon.library", 33L ))==NULL ) error(ERRICONBASE); /* If this program is running already, kill it and exit ourselves */ if (DeathPort = FindPort( "wicon.Death" )) { /* Tell the process to stop */ Signal( DeathPort->mp_SigTask, (1L<mp_SigBit) ); DeathPort = 0; error(PROCSIGNAL); } else { if ((DeathPort = CreatePort( "wicon.Death", 0L ))==NULL) error(ERRPORT); SuicideMask = (1L<mp_SigBit); } #ifndef SMALLWICON SetDefaults(); /* Process arguments */ if (errString = GetArgs(argc, argv)) { FILE *errout=stderr; if (argc==0) /* probably WB */ { errout = fopen( Arg_Window, "w" ); } fputs(Version,stderr); if (*errString) fprintf(errout, "\nWicon: %s\n", errString ); else fprintf(errout, "\nClick the Right Mouse Button quickly to iconify\n"); fprintf(errout, "uSage: \"Wicon ?\" for help (and list of defaults)\n" ); if (argc==0) Delay(5*50L); /* wait 5 seconds */ error(NONE); } #endif SMALLWICON if (!Arg_Quiet) printf("%s\n", Version); if ((Arg_Execute) /* fork another wicon wait for it then exit */ #ifdef SMALLWICON && (argc==1) /* So we don't fork when we have -!& */ #endif SMALLWICON ) { ExecuteWicon(argc, argv); error(NONE); } SetTaskPri( FindTask(0L), (LONG)Arg_Priority); /* This seems to be the only way to find the Workbench screen * Other than doing weird things with GetScreenData() */ if ((tmpWindow = OpenWindow( &WBWindow )) == NULL) error(ERRWIND); WorkBenchScreen = tmpWindow->WScreen; CloseWindow( tmpWindow ); if (Arg_FirstScreen) WiconScreen = IntuitionBase->FirstScreen; else WiconScreen = WorkBenchScreen; if (Arg_Iconify) /* TRUE by default */ { /* clear the array */ for (i=0 ; iFirstWindow; while (BWindow) if (BWindow->RPort->Layer->Flags & LAYERBACKDROP) break; else BWindow = BWindow->NextWindow; } UnlockIBase(Key); if (BWindow==NULL) { NewBackdrop.Screen = WiconScreen; NewBackdrop.Width = WiconScreen->Width - NewBackdrop.LeftEdge; NewBackdrop.Height = WiconScreen->Height - NewBackdrop.TopEdge; if ((BackdropWindow = OpenWindow( &NewBackdrop ))==NULL) error(ERRBACKDROP); SetWindowTitles( BackdropWindow, -1L, (UBYTE *)Version); } /* Set up communication with the input.device */ if ((InputDevPort = CreatePort(0L,0L)) == NULL) error(ERRPORT); if ((InputRequestBlock = CreateStdIO(InputDevPort)) == NULL) error(ERRSTDIO); InputDeviceOpen=(OpenDevice("input.device",0L,InputRequestBlock,0L)==0); if (InputDeviceOpen == NULL) error(ERRINPUT); /* Install the handler */ WiconInterrupt.is_Code = (VOID (*)())WiconHandlerStub; WiconInterrupt.is_Node.ln_Pri = 51; /* priority above Intuition */ InputRequestBlock->io_Command = (long) IND_ADDHANDLER; InputRequestBlock->io_Data = (APTR) &WiconInterrupt; if (DoIO(InputRequestBlock)) error(ERRDOIO1); } /* Install the new functions */ OWVector = SetFunction( IntuitionBase, LVOOpenWindow, WiconOpenW ); CWVector = SetFunction( IntuitionBase, LVOCloseWindow, WiconCloseW ); W_Init(); /* initialise the semaphore and other structures */ if (Arg_Testing) { Test(); /* This just opens and closes a window */ } else { if (argc==0) /* Running from Workbench */ { MouseBox.LeftEdge = WiconScreen->MouseX; MouseBox.TopEdge = WiconScreen->MouseY; SizeRec( WiconScreen, &MouseBox, &WiconScreen->LeftEdge ); } WiconWait(); /* Do all the mumbo jumbo */ if (argc==0) { MouseBox.LeftEdge = WiconScreen->MouseX; MouseBox.TopEdge = WiconScreen->MouseY; SizeRec( WiconScreen, &WiconScreen->LeftEdge, &MouseBox ); } } /* Remove the handler */ if (Arg_Iconify) { InputRequestBlock->io_Command = (long) IND_REMHANDLER; InputRequestBlock->io_Data = (APTR) &WiconInterrupt; if (DoIO(InputRequestBlock)) error(ERRDOIO2); } error(NONE); } /************************************************************************* * error - handles erroneous exits as well as the cleanup * if there is a Message, then print it as an error, * except if (*Message == '\0'). */ error(Message) ERROR Message; { #ifndef SMALLWICON if ((Message!=NULL) && *Message) puts( Message ); #else if (Message!=0) printf("Error status %d\n",Message); #endif if (OWVector) UnSetFunction( IntuitionBase, LVOOpenWindow, OWVector, WiconOpenW ); if (CWVector) UnSetFunction( IntuitionBase, LVOCloseWindow, CWVector, WiconCloseW ); if (BackdropWindow) CloseWindow( BackdropWindow ); if (InputDeviceOpen) CloseDevice( InputRequestBlock ); if (InputRequestBlock) DeleteStdIO( InputRequestBlock ); if (InputDevPort) DeletePort( InputDevPort ); if (PushSignal) FreeSignal( PushSignal ); if (DeathPort) DeletePort( DeathPort ); if (IconBase) CloseLibrary( IconBase ); if (LayersBase) CloseLibrary( LayersBase ); if (GfxBase) CloseLibrary( GfxBase ); if (IntuitionBase) CloseLibrary( IntuitionBase ); exit(0); } /*=======================================================================*/ /* This routine is mostly (c) Davide Cervone's, although all the original shell * was originally based on his as well, thanks Davide!. /* * 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. */ /************************************************************************* * WiconHandler() * * This is the input handler. The `self-documenting code :-)' explains what * it does better than I can. * * Remember RMB events don't get passed to Intuition unless the RMB is * held down longer than DoubleClickTime(), or the mouse is moved, that is * if we are at all interested in the InutionBase->ActiveWindow. */ struct InputEvent *WiconHandler(EventList,data) struct InputEvent *EventList; APTR data; { struct InputEvent *theEvent = EventList; register struct Layer *theLayer, *topLayer; register struct Screen *theScreen; static LastSecs=0; static LastMics=0; struct Window *Window; struct InputEvent **ThisEventPointer; WORD SkipEvent; static struct InputEvent PushDownEvent; static WORD WaitingForMenuUp = FALSE; ThisEventPointer = &EventList; /* Keep track of the pointer to this event */ Forbid(); while(theEvent) { SkipEvent = FALSE; switch(theEvent->ie_Class) { case IECLASS_RAWMOUSE: if (theEvent->ie_Code == MENUUP) { if ( WaitingForMenuUp && DoubleClick(LastSecs,LastMics, theEvent->ie_TimeStamp.tv_secs, theEvent->ie_TimeStamp.tv_micro) && (Window = IntuitionBase->ActiveWindow) && (Window->WScreen == WiconScreen) && (((Window->Flags & RMBTRAP) == 0) || Arg_RMBTRAP) ) { PushedWindow = Window; Signal( WiconTask, PushMask ); SkipEvent = TRUE; /* forget about this event */ WaitingForMenuUp = FALSE; /* forget about the Menu down event too */ } else { /* Put back MENU DOWN event */ if (WaitingForMenuUp) goto putmenudownback; } LastSecs = 0; LastMics = 0; } else { if ( theEvent->ie_Code == MENUDOWN && (Window = IntuitionBase->ActiveWindow) && Window->WScreen == WiconScreen ) { LastSecs = theEvent->ie_TimeStamp.tv_secs; LastMics = theEvent->ie_TimeStamp.tv_micro; PushDownEvent = *theEvent; /* Remember the event structure */ SkipEvent = TRUE; WaitingForMenuUp = TRUE; } else { /* Put back MENU DOWN event */ if (WaitingForMenuUp) goto putmenudownback; } } break; case IECLASS_RAWKEY: LastSecs = LastMics = 0; if (WaitingForMenuUp) goto putmenudownback; break; case IECLASS_TIMER: if (WaitingForMenuUp) /* Do we give up waiting for a MENU up ? */ if (!DoubleClick(LastSecs, LastMics, theEvent->ie_TimeStamp.tv_secs, theEvent->ie_TimeStamp.tv_micro )) { putmenudownback: LastSecs = 0; LastMics = 0; WaitingForMenuUp = FALSE; *ThisEventPointer = &PushDownEvent; ThisEventPointer = &(PushDownEvent.ie_NextEvent); } break; } if (!SkipEvent) { *ThisEventPointer = theEvent; ThisEventPointer = &(theEvent->ie_NextEvent); } theEvent = theEvent->ie_NextEvent; } *ThisEventPointer = NULL; Permit(); return (EventList); } /* For testing purposes */ struct NewWindow nw = { 100,10, 120,200, -1,-1, NULL, WINDOWDEPTH | WINDOWDRAG, NULL, NULL, (UBYTE *)"test", NULL, NULL, 50,15, -1,-1, WBENCHSCREEN }; /************************************************************************* * Test - is just a test routine, called when Arg_Testing is set, the * TESTING=TRUE (from WB) or -t options (from CLI) */ Test() { CloseWindow (OpenWindow( &nw )); /* OpenWindow fail? come on! */ } /************************************************************************* * ExecuteWicon - looks at the command line arguments and makes a wild * hack to put them in back into a single string. * It will work Ok for Wicon, but maybe not for all * 24-Apr-88 other cases (like imbedded `"''s). */ Static ExecuteWicon(argc, argv) int argc; /* Number of arguments */ char **argv; /* Array of arguments */ { #define ARGLIMIT 256 char command[ARGLIMIT+1]; /* the command line we are making */ struct FileHandle *FileH; short limit; /* Counter/Waiting for port */ char *p; p = command; *p = '\0'; strcat(p, "run NIL: \""); /* cross our fingers */ strncat(command, *argv++ , &command[ARGLIMIT] - p); argc--; strncat(command, "\" NIL: -!&", &command[ARGLIMIT] - p); while (*(++p)) ; if (argc!=0) while (argc--) { if ((*argv)[1] != '&') /* We don't want the -& argument */ { *(p++) = ' '; *(p++) = '\"'; *p = '\0'; strncat(command, *argv, &command[ARGLIMIT] - p); while (*(++p)) ; *(p++) = '\"'; *p = '\0'; } argv++; } FileH = Open( "NIL:", MODE_NEWFILE ); /* From Rob Peck's Runback */ #ifdef DEBUG printf("Execute(\"%s\", NIL, NIL)\n", command); #endif DEBUG Execute(command, FileH, FileH); /* Fred Fish 74? */ if (DeathPort) DeletePort( DeathPort ); DeathPort = NULL; limit = 100; /* Wait 5L * 100 / 50 seconds for child process */ while (limit-- > 0) if (FindPort( "wicon.Death" )) /* Other process has started */ break; else Delay(5L); /* 1/10 of a second */ return; } #ifndef SMALLWICON /********************************************************************* * * SetDefaults - they are done here so that no mucking around is * done in the .h files, and Priority must be done * at run-time * */ SetDefaults() { struct Task *Task = FindTask(0L); /* Info about this task */ /* See wicon.doc for documentation */ Arg_AllScreens = TRUE; Arg_Boxes = 15; Arg_Chars = 12; Arg_Depth = TRUE; Arg_Execute = TRUE; Arg_FirstScreen = FALSE; Arg_Iconify = TRUE; Arg_Lines = 1; Arg_Priority = Task->tc_Node.ln_Pri; Arg_Quiet = FALSE; Arg_RMBTRAP = FALSE; Arg_Sticky = FALSE; Arg_Testing = FALSE; Arg_WBWs = FALSE; Arg_Window = "CON:0/0/640/150/Wicon error messages"; } #endif SMALLWICON