home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d154
/
wicon.lha
/
Wicon
/
wicon.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-06-15
|
18KB
|
723 lines
/*************************************************************************
*
* 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 <sgs/arg.h>
#include <stdio.h>
#include <libraries/dos.h>
#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<<DeathPort->mp_SigBit) );
DeathPort = 0;
error(PROCSIGNAL);
}
else
{
if ((DeathPort = CreatePort( "wicon.Death", 0L ))==NULL)
error(ERRPORT);
SuicideMask = (1L<<DeathPort->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 ; i<MAXWINFO ; i++)
Winfo[i].Flags = 0; /* Hence all ~WINFO_USED */
Winfos = 0;
/* Allocate a signal for our Handler to use
to tell us to PUSH a window */
WiconTask = FindTask(0L);
if ((PushSignal = AllocSignal( -1L )) == -1L)
error(ERRSIGNAL);
PushMask = (1L << PushSignal);
/* If there is no Backdrop window then create one */
Key = LockIBase(0L);
{
BWindow = WiconScreen->FirstWindow;
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: >NIL: \""); /* cross our fingers */
strncat(command, *argv++ , &command[ARGLIMIT] - p);
argc--;
strncat(command, "\" <NIL: >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