home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
204.lha
/
Wicon
/
winfo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-02-14
|
13KB
|
611 lines
/*************************************************************************
*
* WINFO.c for wicon.c a *Window iconifier
*
* 1.7 24-Apr-88 Copyright (c) 1987 Steven Sweeting 16-Dec-87
*
* Contains routines for maintaining the Winfo[] data structures
*
*
* Semaphores are used to make sure that the Winfo[] data structure
* is never accessed by two processes at the same time. (Note:
* CloseWindows and OpenWindows are both vectored to the routines
* below.
*
* Note: I have used Procure & Vacate for my function names but these
* functions in the Amiga are slightly DIFFERENT. I am using
* SignalSemaphores (as opposed to just Semaphores), with the
* ObtainSemaphore & ReleaseSemaphore routines.
*
* When a process obtains a semaphore, (Procures), every other process
* who trys to Procure the same Semaphore will be blocked (made to
* Wait()) until the original process gives up, or releases (Vacates)
* that Semaphore.
*
* Semaphores are new to 1.2. eg LockIBase() now uses them.
*
* { yes I know V stands for Signal and P for Wait but I was never
* good at Dutch and I like Acronyms!-}
*
************************************************************************/
#ifdef DEBUG
#define Static
#else DEBUG
#define Static static
#endif DEBUG
#include "wicon.h"
#include <ctype.h>
#include <exec/semaphores.h> /* Amazing ! they work too :-) */
#define PULL(w) {\
(w)->RPort->Layer->Flags &= ~LAYERBACKDROP;\
WindowToFront( w );\
Delay(1L);\
ActivateWindow( w );\
}
#define PUSH(w) { \
(w)->RPort->Layer->Flags |= LAYERBACKDROP;\
WindowToBack( w );\
Delay(1L);\
}
/* The Delay(1L)s above are used to given Intuition a fighting chance
to do the Window..() routines. */
struct SignalSemaphore WiconSemaphore;
/*************************************************************************
* W_Init - Initialises Semaphore structure for use
* as signalling
* 30-Dec-87
*/
W_Init()
{
InitSemaphore( &WiconSemaphore );
}
/*************************************************************************
* W_Procure - obtains a lock on Winfo[]
* blocking wait
* 30-Dec-87
*/
W_Procure()
{
ObtainSemaphore( &WiconSemaphore );
}
/*************************************************************************
* W_Vacate - releases a lock on Winfo[]
*
* 30-Dec-87
*/
W_Vacate()
{
ReleaseSemaphore( &WiconSemaphore );
}
/*************************************************************************
* W_Delete - deletes a Winfo[] entry, we must already have
* W_Procure ed
* 01-Jan-88
*/
W_Delete(index)
WORD index;
{
Winfo[index].IconWindow = NULL;
Winfo[index].Window = NULL;
Winfo[index].Flags = 0;
if (Winfos-1==index)
Winfos--;
}
/*************************************************************************
* W_Pull - Winfo[index].IconWindow was pushed, which means
* we should Pull Winfo[index].Window
* Called from W_Push
* 02-Jan-88
*/
W_Pull( Window, index )
struct Window *Window;
WORD index;
{
W_Procure(); /* We want to access the Winfo[] structure, if
someone else is using it, the W_Procure() will
make us Wait() until they are finished */
if (Winfo[index].IconWindow == Window)
{
if (Winfo[index].Flags & WINFO_CLOSING)
{
W_Vacate(); /* That window is being closed, forget it! */
return;
}
else
{
if (Winfo[index].Flags & WINFO_WAIT)
{
/* this is the only process that should be using the
WINFO_WAIT flag */
DBG("WICON: a Window has WAIT?\n");
W_Vacate();
return;
}
else
{
/* Now other processes can't access the Winfo[]
structure for this window, eg through our CloseWindow
vector */
Winfo[index].Flags |= WINFO_WAIT;
}
}
}
else
{
W_Vacate();
return;
}
W_Vacate();
/* At this stage we have suspended the particular window from closing
because we have our own WAIT on it. we must release this when we are
finished so that other things can continue */
PUSH( Winfo[index].IconWindow );
/* Does the Mac-like rubber banding */
SizeRec( Window->WScreen, &(Winfo[index].IconWindow->LeftEdge),
&(Winfo[index].Window->LeftEdge) );
/* The hidden window magically reappears... */
PULL( Winfo[index].Window );
W_Procure();
{
Winfo[index].Flags ^= WINFO_WAIT;
}
W_Vacate();
}
/*************************************************************************
* W_CheckWindow - check our list of windows that it does exist
* this is mainly because I'm paranoid, but a
* Window may get closed before we get a message
* saying we have pushed this particular window
* 30-Dec-88
*/
LONG W_CheckWindow( Window )
struct Window *Window;
{
struct Window *CheckWindow;
/* Don't trust anyone, check that the Window exists for ourselves */
Forbid();
CheckWindow = WiconScreen->FirstWindow;
while (CheckWindow)
{
if (CheckWindow == Window)
break;
CheckWindow = CheckWindow->NextWindow;
}
Permit();
return ((LONG)CheckWindow);
}
/*************************************************************************
*
* W_Push - a window has been pushed 21-Apr-87
*
*/
W_Push( Window )
struct Window *Window;
{
WORD i;
W_Procure();
for (i=0;i<Winfos;i++)
if (Winfo[i].IconWindow == Window)
break;
if (i!=Winfos)
{
W_Vacate();
W_Pull( Window, i );
return;
}
for (i=0;i<Winfos;i++)
{
if (Winfo[i].Window == Window)
{
/* We're in business */
if (Winfo[i].Flags & WINFO_CLOSING)
{
W_Vacate();
return;
}
if (Winfo[i].Flags & WINFO_WAIT)
{
DBG("WICON: Window, WAIT active?\n");
W_Vacate();
return;
}
break;
}
}
if (i==Winfos) /* Then we need to create a new entry */
{
if (!W_CheckWindow(Window)) /* Check its existence */
{
W_Vacate();
return;
}
if ((Window->RPort->Layer->Flags & LAYERBACKDROP) ||
((Window->Flags & WBENCHWINDOW ) && (!Arg_WBWs)) )
{
W_Vacate();
return;
}
for (i=0;i<Winfos;i++) /* search for empty slot */
if ((Winfo[i].Flags & WINFO_USED)==0)
break;
if (i==MAXWINFO)
{
DBG("WICON: not enough Winfo slots\n");
W_Vacate();
return;
}
if (i==Winfos)
Winfos++;
Winfo[i].Window = Window;
Winfo[i].Flags = 0;
Winfo[i].IconWindow = NULL;
}
/* Here we are saying (to CloseWindow & W_Close), I am playing with
these data structures, don't touch until I say so */
Winfo[i].Flags |= (WINFO_WAIT | WINFO_USED);
W_Vacate();
PUSH( Winfo[i].Window );
if (Winfo[i].IconWindow)
{
SizeRec( Window->WScreen, &(Winfo[i].Window->LeftEdge),
&(Winfo[i].IconWindow->LeftEdge) );
if (Arg_Sticky)
{
struct Window *w = Winfo[i].IconWindow;
WindowToFront( w );
Delay(1L);
ActivateWindow( w );
if (w->TopEdge < 5) /* almost hidden behind screen title */
MoveWindow(w, 5, 0);
}
else
PULL( Winfo[i].IconWindow );
W_Procure();
{
Winfo[i].Flags ^= WINFO_WAIT;
}
W_Vacate();
}
else
{
struct NewWindow NewWindow;
/* No I didn't copy this from that textbook :-> */
NewWindow.LeftEdge = Window->LeftEdge; /* See also */
NewWindow.TopEdge = Window->TopEdge; /* GetNextIconPos */
NewWindow.Screen = Window->WScreen;
NewWindow.Flags = ACTIVATE | SMART_REFRESH | WINDOWDRAG
| (Arg_Sticky || !Arg_Depth ? 0 : WINDOWDEPTH);
NewWindow.Width = Arg_Chars * NewWindow.Screen->RastPort.TxWidth
+ (NewWindow.Flags & WINDOWDEPTH ? 52 : 0 );
NewWindow.Height = 10;
NewWindow.DetailPen = 1;
NewWindow.BlockPen = 2;
NewWindow.IDCMPFlags = 0; /* we have to put some in later */
NewWindow.FirstGadget = NULL;
NewWindow.CheckMark = NULL;
NewWindow.Title = Window->Title;
NewWindow.BitMap = NULL;
NewWindow.MinWidth = 50;
NewWindow.MinHeight = 10;
NewWindow.MaxWidth = -1;
NewWindow.MaxHeight = 15;
NewWindow.Type = CUSTOMSCREEN;
GetNextIconPos( &NewWindow ); /* Overwrite Edges if Arg_Lines */
/* Do a couple of minor checks here for Limits */
if (NewWindow.LeftEdge + NewWindow.Width > NewWindow.Screen->Width)
if (NewWindow.Screen->Width > NewWindow.Width)
NewWindow.LeftEdge = NewWindow.Screen->Width - NewWindow.Width;
SizeRec( Window->WScreen, &(Winfo[i].Window->LeftEdge),
&(NewWindow.LeftEdge) );
if ( (Winfo[i].IconWindow = OldOpenWindow(&NewWindow)) == NULL) /* failure */
{
PULL( Winfo[i].Window );
W_Procure();
{
W_Delete(i);
}
W_Vacate();
}
else
{
SetWindowTitles(Winfo[i].IconWindow, -1L, Winfo[i].Window->ScreenTitle);
/* Intuition won't give us a DRAG bar if we open a
* window.Flags |= BACKDROP, so to get the desired effect we open
* one normally, make it a BACKDROP, then WindowToBack(), and
* WindowToFront() it to get it between the WorkBench Window
* (icons etc.) and other (normal) windows. ie acting like a
* draggable icon
*/
if (Arg_Sticky)
{
register struct Window *w = Winfo[i].IconWindow;
w->RPort->Layer->Flags |= LAYERBACKDROP;
WindowToBack( w );
Delay( 1L );
WindowToFront( w );
}
W_Procure();
{
Winfo[i].Flags ^= WINFO_WAIT;
}
W_Vacate();
}
}
} /* W_Push */
/*************************************************************************
*
* W_Close - closes a window if it is not locked
*
*/
W_Close( Window )
struct Window *Window;
{
WORD i,Found=FALSE,Flags;
static struct BoxInfo ToBox = { 0,0,0,0 };
struct BoxInfo FromBox;
if (Window->WScreen != WiconScreen)
{
if (!Arg_AllScreens)
return ( OldCloseWindow( Window ) );
}
else
{
W_Procure();
for (i=0;i<Winfos;i++) /* Is this window under our management ? */
{
if (Winfo[i].Window == Window)
{
/* We're in business */
if (Winfo[i].Flags & WINFO_CLOSING)
{
/* Give up its closing anyway (should never happen) */
W_Vacate();
return;
}
if (Winfo[i].Flags & WINFO_WAIT)
/* someone's got it, wait for it */
while (Winfo[i].Flags & WINFO_WAIT)
{
W_Vacate();
Delay(5L); /* 5/50ths of a second */
W_Procure();
}
Winfo[i].Flags |= WINFO_CLOSING;
Found = TRUE;
break; /* Quit the for loop */
}
}
W_Vacate();
}
FromBox = *((struct BoxInfo *)&Window->LeftEdge);
OldCloseWindow( Window );
ToBox.LeftEdge = FromBox.LeftEdge + (FromBox.Width >> 1);
ToBox.TopEdge = FromBox.TopEdge + (FromBox.Height >> 1);
SizeRec( Window->WScreen, &FromBox, &ToBox );
if (Found)
{
/* Note: the IconWindow may be no longer there (W_Cleanup()) */
if (Winfo[i].IconWindow)
{
Flags = Winfo[i].IconWindow->RPort->Layer->Flags;
FromBox = *((struct BoxInfo *)&Window->TopEdge);
OldCloseWindow( Winfo[i].IconWindow );
if (!(Flags & LAYERBACKDROP))
{
ToBox.LeftEdge = FromBox.LeftEdge + FromBox.Width >> 1;
ToBox.TopEdge = FromBox.TopEdge + FromBox.Height >> 1;
SizeRec( Winfo[i].IconWindow->WScreen, &FromBox, &ToBox );
}
}
W_Procure();
W_Delete(i);
W_Vacate();
}
} /* W_Close */
/*************************************************************************
*
* W_Cleanup - restores all the windows back
*
*/
W_Cleanup()
{
WORD i;
WORD WinfoSize=Winfos;
W_Procure();
for (i=0;i<WinfoSize;i++)
{
if (Winfo[i].Flags & WINFO_USED)
{
if ((Winfo[i].Flags & WINFO_CLOSING)==0 )
{
Winfo[i].Flags |= WINFO_WAIT;
W_Vacate();
if (Winfo[i].IconWindow)
OldCloseWindow( Winfo[i].IconWindow );
if (Winfo[i].Window->RPort->Layer->Flags & LAYERBACKDROP)
PULL( Winfo[i].Window );
W_Procure();
W_Delete(i);
}
}
}
W_Vacate();
Winfos = 0;
}
/*************************************************************************
*
* _wb_parse - stub so we don't get Manx C's
*
*/
_wb_parse()
{}
/*************************************************************************
*
* GetNextIconPos - keeps track of the last icon position, and creates
* a non-overlapping line of them
* 21-Apr-88
*/
GetNextIconPos( NewWindow )
struct NewWindow *NewWindow;
{
#define YGAP (2) /* spacing */
#define XGAP (4) /* between icons */
static WORD IconX=0,IconY=0;
static short Top;
short width = NewWindow->Width + XGAP;
short height = NewWindow->Height + YGAP;
if (Arg_Lines)
{
if (IconY==0)
/* Set up everything & first position */
{
IconX = 0;
IconY = Top = WiconScreen->Height - height * Arg_Lines;
}
else
/* back for more */
{
if ((IconX += width) > WiconScreen->Width - NewWindow->Width)
{
IconX = 0;
if (IconY < Top)
{
if ((IconY -= height) < 0) /* building upwards */
IconY = 0; /* 100's of windows or a small screen */
}
else
{
if ((IconY += height) > WiconScreen->Height - NewWindow->Height)
IconY = Top - height;
}
}
}
NewWindow->TopEdge = IconY;
NewWindow->LeftEdge = IconX;
}
} /* GetNextIconPos */