/*
	File:		LayerMgr.c

	Contains:	Layer Manager primitives

	Written by:	Ed Tecot

	Copyright:	© 1989-1992 by Apple Computer, Inc., all rights reserved.

	Change History (most recent first):

		<SM3>	 11/10/92	CSS		Update from Reality:
									<74>	10/28/92	DTY		Use Get/Set macros to access ExpandMem.
									<73>	 6/29/92	DC		added a condition to the conditional "theFuture" to eliminate
																this change when compiling the INIT so as to be CubeE clean.
									<72>	 5/31/92	DC		Added a call to ShowHide to __CloseWindow when it is called on a
																layer, since the new implementation of ShowHide for a layer will
																crash in the middle of a close.
									<71>	 5/15/92	DC		Fixes to make ShowHide work for layers to provide application
																hiding.  Still not working.
									<70>	 5/14/92	DC		Fixed more bugs in layerless apps (again all changes are
																conditionalized to not affect CubeE)
									<69>	 4/20/92	DC		Fixed bugs in layerless apps mods (all conditionalized to
																protect CubeE and System builds)
									<68>	 4/10/92	DC		Put in conditional changes to WindowMgrPatches.a and LayerMgr.c
																for implementing layerless apps.
		<SM2>	 5/22/92	FM		
		<SM2>	  5/7/92	FM		renamed the romXXX routines as XXXXGlue since thats what they are highlevel interfaces for
									register based routines. The windowmgrpatches file in reality will need to be changed to reflect this.

									renamed oldXXXX routines as XXXXGuts. These are assembly core routines that the
									LayerMgr is building on (originally in the form of a tail patch.)

									renamed __BeginUpdate as BeginUpdateOfLayersChildren to reflect the funstion of this
									routine. It is now called from WindowMgr.a in BeginUpdate. I did this to replace the 
									sick, fragmented jumping around that used to be done in the patch file.

		<67>	 10/4/91	JSM		Change PsychoticFarmerOrLater conditionals to TheFuture.
		<66>	 9/22/91	DTY		Change PsychoticFarmerAndLater to PsychoticFarmerOrLater.
		<65>	 9/13/91	dba		Fix the bug where a window which is created with a nil
									titleHandle gets an empty string for its handle, even though
									layers donÕt use the titleHandle field.
		<64>	 9/12/91	DTY		This is the last time I listen to Greg. The title handle needs
									to be checked because LayerRecords get hosed without it.
		<63>	 8/30/91	DTY		Always create a title handle. (For PsychoticFarmerAndLater.)
		<62>	 7/15/91	dba		get rid of MemErr
		<61>	  4/3/91	dba		kill enjoyable part of the code
		<60>	 3/26/91	dba		BAL: add a selector for VisRgnChanged so we donÕt burn a whole
									trap
		<59>	 3/14/91	dba		dty, #b6q8crash: check for nil titleHandle before dereferencing
		<58>	  3/4/91	dba		gbm: put in SetWTitle workaround
		<57>	 1/30/91	VL		RLC, #VL003: Invalidate balloon saved bits when creating a new
									layer. Also, add HMGetBalloons check before
									HMInvalidateSavedBits for better performance.
		<56>	 1/30/91	VL		dba, #Whiteboard7.0b4q6HowDoYouLikeThisBugNumberChris?: Use a
									flag for checking whether ancestor regions have already been
									recalcÕed.
		<55>	 1/17/91	VL		(dba) Changed PaintOne to PaintOneLite and PaintBehind to
									PaintBehindLite. These routines do not recalculate ancestor
									rgns.
		<54>	 1/14/91	VL		(stb) Added kIsLayer for FastIsLayer. FastIsLayer used to check
									for negative values but some apps set txSize to negative and
									totally hosed us.
		<53>	  1/3/91	VL		(RLC) Provide a new call RedrawAll for redrawing the whole
									screen.
		<52>	 12/7/90	DC		& dba; Put a sanity check on calls to AutoPositionWindow when
									the where option is lcParentWindow to reposition a partially
									obscured window on the lcParentWindowScreen.
		<51>	 12/6/90	VL		& dba; Added 3 new routines (PreShowHide, ShowWindowAction and
									HideWindowAction). These 3 routines together maintain the
									regions of layers when they become visible and invisible. When a
									layer is becoming invisible, all its children will have their
									structRgn, contRgn and visRgn cleared out. When a layer is
									becoming visible, the regions of its children will be
									recalculated.
		<50>	 12/3/90	VL		& dba; Changed PaintWhite from a Boolean to a short (to match
									what MultiFinder did).
		<49>	 11/1/90	csd		& dba; Add CalcDeskPortVisRgn and call it after creating a new
									window.
		<48>	10/30/90	dba		special case for Finder; donÕt calculate visRgns if the visRgn
									is shared with the DeskPort
		<47>	10/24/90	DC		VL - Fix a bug in my inline divide (ShortDiv) that was
									introduced in the conversion to C3.2
		<46>	10/21/90	gbm		(with dba) Made compatible with 3.2 C compiler (and incompatible
									with previous compilers).
		<46>	 10/2/90	JAL		Changing #pragmas to 3.2 version.
		<45>	 9/23/90	dba		Add an ActivatePalette in NewWindowCommon so that newly created
									windows with default palettes will work properly. Maintain the
									DeskPortÕs visRgn when painting the desk so that the Finder can
									use it and avoid extraneous region calculations. Also tighten
									code and check it agains the 3.2 C compiler (optimize register
									use for locals).
		<44>	 9/14/90	gbm		Mark layers with the txSize field negative instead of using the
									stringWidth field. This field exists for grafports, too, so we
									no longer mistakenly return true for some grafport owners of
									controls (control owners are supposed to be windows, but tell
									that to SuperCard). Change SetWindowState to no longer accept
									window state handles that are too small, or that have a version
									number of 0 or negative. Get rid of the DeviceLoop declaration,
									and change the call a bit to correspond to the new declaration
									in QuickDraw.h.
		<43>	 9/10/90	dba		move allocation of deskPort (in __InitWindows) before call to
									oldInitWindows
		<42>	 8/31/90	dba		Got rid of locked layers. This allows us to get rid of a lot of
									code, and use FastIsLayer, instead of (slow) WindowType. Since
									the Process Mgr. used a locked layer for the desktop, we have
									created a replacement, the DeskPort. Optimized some of the
									window centering code, including fixing a bug where a region
									would be orphaned.
		<41>	 8/30/90	dba		Extensive changes to speed up the Layer Manager.
		<40>	 8/17/90	RLC		Change interface call to private HMInvalidateSavedBits() in
									used __PaintOne patch.
		<39>	 8/16/90	dba		get rid of extraneous CalcAncestorRgns in PaintBehind
		<38>	  8/2/90	RLC		Insert code in __PaintOne to invalidate bits behind balloon if
									window environment changes.
		<37>	 7/23/90	EMT		Changed IsLayerLocked to WindowType.
		<36>	 7/20/90	dba		get rid of a C warning
		<35>	 7/19/90	EMT		Returned to older style paint and calcvis loops.
		<34>	 7/16/90	EMT		Fixed PaintOnePal accidentally erasing too much. Fixed hiding
									layers in EmptyVisAction.
		<33>	 7/13/90	KSM		Since WindowMgr has a comefrom patch on CheckUpdate, we need to
									make this call the ValidateMenuBar from InvalMenubarPatch.
		<32>	 7/11/90	EMT		Fixed BeginUpdate/EndUpdate reentrancy problem.
		<31>	 7/10/90	dba		get rid of C warnings
		<30>	  7/2/90	EMT		Miscellaneous size and performance improvements: Rewrite
									__NewWindow, __NewCWindow and __DrawNew in 68000. DonÕt Call
									PaintOne or CalcVisBehind for invisible windows. Content region
									of layers is now empty instead of "wide open".
		<29>	 6/15/90	DC		Improved time complexity of stagger algorithm
		<28>	 5/30/90	DC		Exported GlobalPortRect
		<27>	 5/22/90	DC		Removed some redundant code in GetNewStructRect. Fixed a bug in
	   								NewWindowCommon caused by calling AutoPositionWindow on a window
									in a half-made state.
		<26>	 4/20/90	dba		make ClipAbove(root) work so that PaintOne(root) will work; note
									that ClipAbove(root) doesnÕt need to do anything at all
		<25>	 4/18/90	DC		Change the Dialog centering constant from 3 to 5
		<24>	  4/3/90	DC		Fixed MoveWindow bug in SetWindowState
		<23>	  4/2/90	EMT		Made friends with Palette Manager.
		<22>	 3/20/90	EMT		Rewrote HaveCQD() macro to generate less code.
		<21>	 3/16/90	DC		Added CheckWindow
		<20>	 3/15/90	EMT		Fixed Activate bug when creating layers in NewWindowCommon.
		<19>	 3/14/90	DC		Completed staggering algorithm for PositionWindow
		<18>	 3/14/90	EMT		NewLayer has problems with MakeWindowRecord. Combined to form
									NewWindowCommon.
		<11>	  3/2/90	DC		Merged in Window Positioning code.  Set conditional
									hasWindowPositioning to in line.
		<10>	  3/2/90	JSM		No changes, just check in new version to force BBS to rebuild
									new object.
		 <9>	 2/27/90	EMT		No more AppLayer.
		 <8>	 2/26/90	EMT		Moved bracketed routines to LayerMgrPatchTail.a to save space.
		 <7>	 2/20/90	EMT		Speeded up ClipAbove. Fixed bug in CalcVisAction on invisible
									layers.  Fixed bug in EachWindow when parent->nextWindow == nil.
		 <6>	 2/15/90	EMT		Changed AuxCtlHndl to AuxCtlHandle to match I.M.
		 <5>	 2/15/90	JAL		Changed AuxWinHndl to AuxWinHandle to match I.M.
		 <4>	 2/14/90	EMT		Fix CalcVisAction with embedded layers and speed up
									CalcVisAction and PaintAction to boot! Moved reserved2 bits to
									Layers.h. Added SyncCurLayer. SetCurLayer(nil) now sets the
									current layer to the root. GetParent(nil) now returns CurLayer.
		 <3>	 1/18/90	EMT		Call SetCurLayer(nil) in FrontWindowIn to make sure hierarchy
									remains intact.
		 <2>	12/21/89	EMT		Put back change to CheckUpdate. CheckUpdateIn now checks the
									layer it is passed as well as its children. Rewrote
									FrontWindowIn to stay "in bounds".
	   <2.3>	12/12/89	EMT		Back out change to CheckUpdate until MultiFinderÕs ready for it.
	   <2.2>	12/11/89	EMT		Fixed bug in IsLayer when a "window" has no defProc. Added
									CheckUpdateIn, FrontWindowIn and ActiveWindow. Changed
									CheckUpdate to only look in applicationÕs windows.
	   <2.1>	 12/7/89	JSM		Replace code accidentally deleted from __EachWindow.
	   <2.0>	 12/6/89	DAM		Added UNTESTED window positioning code, compiles with
									'hasWindowPositioning' defined.
	   <1.9>	 9/15/89	EMT		Ripped out centering code until it can be done properly. Made
									GetRootLayer survive during early initialization.
	   <1.8>	 8/15/89	EMT		Fixed bug in GetParent when CurLayer is not correct.
	   <1.7>	  7/7/89	EMT		Forgot to check for color in one placeÉ
	   <1.6>	 6/27/89	EMT		Rewrite NewWindow, NewCWindow, NewLayer to use common code and
									splice window into the list before making any window manager or
									defproc calls. Swap AuxWinHead and AuxCtlHead with layers. Added
									Chris DerossiÕs centering code.
	   <1.5>	 6/12/89	EMT		Use CallWindowCalc in ROM. Blast PaintWhite in PaintBehind for
									compatibility.
	   <1.4>	  6/9/89	EMT		Enforce window hierarchy in CalcAncestorRgns.
	   <1.3>	  6/5/89	EMT		CloseWindow clears subWindows for layers to prevent KillPicture
									from being called. A better fix than 1.1 for CalcVis and
									CalcVisBehind.
	   <1.2>	 5/31/89	EMT		CheckUpdate now looks at all windows.
	   <1.1>	 5/31/89	EMT		Fixed CalcVisBehind for invisible layers.
	   <1.0>	 5/13/89	EMT		Added to EASE.

	To Do:
*/

#include <Memory.h>
#include <OSUtils.h>
#include <ToolUtils.h>
#include <Resources.h>
#include <Fonts.h>
#include <Palettes.h>
#include <PalettesPriv.h>
#include <Layers.h>
#include <Traps.h>
#include <Errors.h>
#include <Menus.h>
#include <Balloons.h>
#include <ExpandMemPriv.h>

#ifndef hasLayerlessAppsINIT
#define hasLayerlessAppsINIT 0
#endif

pascal short HMInvalidateSavedBits(WindowPtr)
	= { 0x303C, 0x02FA, _Pack14 };	/* selector = -6, 2 words of parameters */

#pragma parameter VisRgnChanged(__A0)
pascal void VisRgnChanged(WindowPtr)
	= { 0x7000, 0xA0A5 };

#define	ROM85			(* (unsigned short*) 0x28E)
#define	WindowList		(* (WindowPeek*) 0x9D6)
#define	PaintWhite		(* (short*) 0x9DC)
#define	WMgrPort		(* (GrafPtr*) 0x9DE)
#define	DeskPort		(* (GrafPtr*) 0x9E2)
#define	GrayRgn			(* (RgnHandle*) 0x9EE)
#define	SaveVisRgn		(* (RgnHandle*) 0x9F2)
#define	CurActivate		(* (WindowPeek*) 0xA64)
#define	GhostWindow		(* (WindowPeek*) 0xA84)
#define	CurLayer		(* (LayerPeek*) 0xA90)
#define	WMgrUpdate		(* (WindowPeek*) 0xAFC)
#define	ROMMapInsert	(* (short*) 0xB9E)
#define	MBarHeight		(* (short*) 0xBAA)
#define	MMU32Bit		(* (Boolean*) 0xCB2)
#define	AuxWinHead		(* (AuxWinHandle*) 0xCD0)
#define	AuxCtlHead		(* (AuxCtlHandle*) 0xCD4)
#define	WMgrCPort		(* (CGrafPtr*) 0xD2C)
#define MainDevice		(* (GDHandle*) 0x8A4)

#define	HaveCQD()		(ROM85 <= 0x3FFF)

#define	dsWDEFNotFound	87
#define	kDoPaintWhite	-1
#define kDontPaintWhite	0

// These are machine language multiply and divide routines, which are
// used to avoid using CRuntime.o

#pragma parameter __D0 ShortMul(__D1, __D0)
long ShortMul(short, short)
	= 0xC1C1;

#pragma parameter __D0 ShortDiv(__D0, __D1)
short ShortDiv(short, short)
	= 0x81C1;

#define TOPLEFT(aRect) (*((Point *)(&(aRect))))

#if DEBUG
#define	assert(what) do { if (!(what)) DebugStr("\pLayers: Assertion failed!"); } while (0)
#else
#define assert(what)
#endif

/* Philosophy:
 *
 * We can get the ROM Window Manager to do most of the work by carefully maintaining the globals
 * WindowList and GrayRgn.  It is important for all calls to "do the right thing".  The way
 * we can achieve this is to never make assumptions about CurLayer; whenever an operation is
 * performed on a window, great pains are taken to ensure that these globals are correct.
 * The notable exception are a few routines which implicitly take CurLayer as a parameter.
 *
 * The following is a table of routines and their use of these globals.  Routines which
 * implicitly use CurLayer as a parameter are marked with a + following their name.
 * Traps not listed either do not use these globals or call one of the routines below.
 *
 * 					reads WindowList	writes WindowList		reads GrayRgn	writes GrayRgn
 * BringToFront				x					x
 * CalcVis					x											x
 * CheckUpdate+				x
 * ClipAbove				x											x
 * CloseWindow				x					x
 * DragWindow				x(with patch)											x
 * FindWindow+				x
 * FrontWindow+				x
 * GrowWindow															x
 * InitWindows									x									x
 * MoveWindow				x					x						x
 * NewCWindow+				x					x
 * NewWindow+				x					x
 * PaintBehind															x
 * PaintOne																x
 * SelectWindow				x					x
 * SendBehind				x					x
 * SetDeskCPat															x
 * ShowWindow				x
 * ZoomWindow				x					x
 *
 * A simple application using layers might be organized as follows:
 *
 *							_________________________________________________
 *							|	Application Layer (created by InitWindows)	|
 *							|_______________________________________________|
 *										 /					\
 *										/					 \
 *				_________________________________		_____________________________
 *				|	Float Layer (neverActive)	|		|		Document Layer		|
 *				|_______________________________|		|___________________________|
 *						 /			\						 /		  |			\
 *						/			 \						/		  |			 \
 *					Window			Window				Window		Window		Window
 *														^
 *														|
 *														FrontWindow
 */

#define notPaletteUpdate	((void *) -1)

#define	layerWDEF	127
#define	layerProc	layerWDEF*16

#if	!hasLayerlessAppsINIT
pascal void			InitWindowsGuts(void);
#endif
pascal void			ClipAboveGuts(WindowPeek);
pascal void			PaintOneGuts(WindowPeek, RgnHandle);
pascal void			CloseWindowGuts(WindowPtr);
pascal void			InsertWindow(WindowPtr, WindowPtr);
pascal void			MakeDeactiveGlue(WindowPtr);
pascal void			CallWindowGlue(WindowPeek, short, long);
pascal void			CallWindowDrawGlue(WindowPeek);
pascal void			CallWindowCalcGlue(WindowPeek);

pascal void			PaintDesk(void);
pascal void			ValidateMenuBar(void);

#if hasLayerlessApps
pascal LayerPeek	__patchGetParent(WindowPtr);
#define __GetParent	__patchGetParent
#else
pascal void			CalcAncestorRgns(WindowPtr);
pascal LayerPeek	__GetParent(WindowPtr);
#endif

pascal LayerPtr		__GetRootLayer(void);

void				CalcDeskPortVisRgn(void);

struct AutoWindowPosition {
	unsigned short	screenControl:2;
	unsigned short	hPosition:1;
	unsigned short	vPosition:2;
	unsigned short	check:11;
};

typedef struct {
	short	infoVersion;
	Rect	userState;
	Boolean	zoomed;
} WindowStateInfo;
typedef WindowStateInfo *WindowStateInfoPtr;

#define autoPositionTopCookie 0x7FFC


//	ScreenWithMostOF() returns the bounding rectangle of the screen which
//	contains the largest amount of area of the rectangle theRefRect.

struct procData
{
	Rect		theRect,		//	The winning device rect;
				theRefRect;		//	The reference Rect to test against
	long		theArea;		//	High-water mark for eclipsed area
};

pascal void CheckProc(short, short, GDHandle targetDevice, struct procData *theData)
{
	if (targetDevice) {
		Rect	testRect,
				intersectRect;

		testRect = (*targetDevice)->gdRect;

		if (targetDevice == MainDevice)
			testRect.top += MBarHeight;

		if (SectRect(&testRect, &(theData->theRefRect), &intersectRect)) {
			long testArea = ShortMul(intersectRect.right - intersectRect.left,
									intersectRect.bottom - intersectRect.top);

			if (testArea > theData->theArea) {
				theData->theRect = testRect;
				theData->theArea = testArea;
			}
		}
	} else {
		theData->theRect = WMgrPort->portRect;
		theData->theRect.top += MBarHeight;
	}
}

void ScreenWithMostOf(Rect *theRefRect)
{
	struct procData theData;

	theData.theArea = 0;
	theData.theRefRect = *theRefRect;

#ifndef leaveOutDeviceLoop
	DeviceLoop(nil, (DeviceLoopDrawingProcPtr) CheckProc, (long) &theData, singleDevices | allDevices);
#endif

	*theRefRect = theData.theRect;
}

//	TestContent() tests if a the rectangle contentRect has at least 75% of
//	its area on the screen with rectangle screenRect

Boolean TestContent(const Rect *contentRect, const Rect *screenRect)
{
	Rect	sRect;

	if (!SectRect(contentRect, screenRect, &sRect))
		return false;

	{
		unsigned long sArea = ShortMul(sRect.right - sRect.left, sRect.bottom - sRect.top);
		unsigned long cArea = ShortMul(contentRect->right - contentRect->left,
			contentRect->bottom - contentRect->top);

		// is the area that intersects screenRect greater than 3/4 of the content area?
		return (sArea > (cArea - (cArea >> 2)));
	}
}

//	GetNewStructRect takes a WindowPtr and a rectangle and returns the bounding
//	rectangle of the window if its content region were in the area specified by
//	thePort.  It must work even if the window is invisible, which means that the
//	WDEF must be faked out to produce the desired information.

void GetNewStructRect(Rect *newStruct, WindowPeek whichWindow, Rect *thePort)
{
	Rect		aRect;

	Point		oldPos,
				oldSize;

	GrafPtr		curPort;

	Boolean		oldVisibility;

	//	Save the current port and install the windowÕs (in case theyÕre not the
	//	same (more than likely))

	GetPort(&curPort);
	SetPort((GrafPtr) whichWindow);

	//	Save the current condition of the windowÕs GrafPort	because weÕre going
	//	to doctor it up considerably to fool the WDEF into giving us its strucRgn.

	oldVisibility = whichWindow->visible;
	whichWindow->visible = true;

	aRect = ((WindowPtr) whichWindow)->portRect;
	oldPos = TOPLEFT(aRect);					//	Get old topLeft;
	LocalToGlobal(&oldPos);						//	Make it global;
	oldSize.h = aRect.right - aRect.left;		//	Get old size;
	oldSize.v = aRect.bottom - aRect.top;

	//	Move the windowÕs GrafPort to the new location. thePort is already global.

	MovePortTo(thePort->left, thePort->top);

	//	Make it the new size.

	PortSize(thePort->right - thePort->left, thePort->bottom - thePort->top);

	//	call the WDEF with the wCalcRgns message in this new faked up state.

	CallWindowCalcGlue(whichWindow);

	//	get the bounding box of the structure rgn.

	*newStruct = (*(whichWindow->strucRgn))->rgnBBox;

	//	restore things to their old condition.

	MovePortTo(oldPos.h, oldPos.v);
	PortSize(oldSize.h, oldSize.v);
	whichWindow->visible = oldVisibility;

	SetPort(curPort);

	CallWindowCalcGlue(whichWindow);
}

#define staggerIncrement 20
#define initialWindowListSize 100
#define blockSize	(initialWindowListSize * sizeof(WindowPtr))

typedef struct
{
	Rect		checkRect;

	WindowPeek	**backList,
				windowToAvoid;

	int			listSize,
				noOfWindows;
} GetNextPrivateData;

#define slopConstant 3		// amount of slack in deciding whether a window is in position

//	Creates a rectangular around a point.  the area is used to check a windowÕs position
//	against the point, taking a few pixels of slack into account.

void CreateCheckRect(Rect *checkRect, Point thePoint)
{
	TOPLEFT(*checkRect) = thePoint;
	TOPLEFT(checkRect->bottom) = thePoint;
	InsetRect(checkRect, -slopConstant, -slopConstant);
}

//	returns true if the window is visible and is located within the checkrect contained
//	in privateData (called by FindFirst and GetNextStaggerPos).

int	WindowAtPos(WindowPeek window, GetNextPrivateData *privateData)
{
	if (window->visible)
		return PtInRect(TOPLEFT((*(window->contRgn))->rgnBBox), &(privateData->checkRect));
	else
		return false;
}

//	FindFirst is an ActionProc passed into EachWindow to find the first window that occupies the first
//	stagger position.  FindFirst keeps a "trail" of windows it has traversed in trying to find
//	the first window.  We will use this record to retrace our steps if the first and subsequent
//	stagger positions are occupied.

pascal OSErr FindFirst(WindowPeek window, LayerPeek /* parent */, GetNextPrivateData *privateData)
{
	//	if this is the window weÕre trying to position, just ignore it.

	if (window == privateData->windowToAvoid)
		return noErr;

	//	check if this window is in the first stagger position.

	if (WindowAtPos(window, privateData))
		return haltIterator;

	//	if necessary, burst the size of the backward list of windows.

	if (privateData->noOfWindows == privateData->listSize) {
		SetHandleSize((Handle) privateData->backList, privateData->listSize + initialWindowListSize);
		if (MemError() != noErr)
			return haltIterator;
		privateData->listSize += initialWindowListSize;
	}

	//	record the window in our list.

	(*(privateData->backList))[privateData->noOfWindows++] = window;

	return noErr;
}

//	NextPosToCheck moves windCont to the next stagger position in the sequence.  If
//	the window dosenÕt fit in any possible next step, NextPosToCheck returns false.

int	NextPosToCheck(Point *curStaggerPos, Rect *windCont, Rect *theScreen)
{
	OffsetRect(windCont, windCont->right - windCont->left + staggerIncrement, 0);	// Try to move one window-width to the right

	if (TestContent(windCont, theScreen))
		return true;

	// if that doesnÕt work, move down to the beginning of another row.

	curStaggerPos->h += staggerIncrement;
	curStaggerPos->v += staggerIncrement;
	OffsetRect(windCont, curStaggerPos->h - windCont->left, curStaggerPos->v - windCont->top);

	// if that doesnÕt work, weÕve occupied all possible locations and need to start over.

	return TestContent(windCont, theScreen);
}

//	GetNextStaggerPos returns the stagger position into which the newly created window
//	should be placed.

Point GetNextStaggerPos(WindowPeek whichWindow,
					Point firstStaggerPos,
					Rect *theScreen,
					Rect *windCont,
					Point structOffset)
{
	GetNextPrivateData	privateData;		//	structure for use by FindFirst.
	int					noOfWindows;
	Point				curStaggerPos;
	WindowPeek			*backPtr;

	AddPt(structOffset, &firstStaggerPos);	//	adjust upper left of stagger world to
											//	account for the difference between the
											//	content and structure region.

	curStaggerPos = firstStaggerPos;		//	curStaggerPos is the place we are currently
											//	testing for validity.

	//	Move windCont to the first stagger position.

	OffsetRect(windCont, firstStaggerPos.h - windCont->left,
		firstStaggerPos.v - windCont->top);

	//	If it doesnÕt fit in the first stagger position, it wonÕt fit any better anywhere
	//	else.  Might as well place it the beginning.

	if (!TestContent(windCont, theScreen))
		goto out;

	//	create space for the backward list of window ptr generated by FindFirst.

	privateData.backList = (WindowPeek **)NewHandleClear(blockSize);

	//	if weÕre real low on memory, weÕre stuck with the first stagger position.

	if (MemError() != noErr)
		goto out;

	//	Initialize privateData for call to EachWindow

	privateData.listSize = initialWindowListSize,
	privateData.noOfWindows = 0;
	privateData.windowToAvoid = whichWindow;

	//	Create an area for testing the windowÕs position.

	CreateCheckRect(&(privateData.checkRect), TOPLEFT(*windCont));

	//	Search all windows in the layer for one that occupies the first stagger position,
	//	keeping a record of all the foreward windows you covered along the way.  If
	//	EachWindow returns noErr, it means there is no window in the first location, so
	//	weÕre going to occupy that prime piece of real-estate.

	if (EachWindow(firstWindow, afterLastWindow, nil,
					(WindowAction *)FindFirst, (void *)(&privateData)) == noErr)
		goto cleanup;


	//	Get the results of the search for the window in the first stagger position.
	//	noOfWindows is the number of windows we walked over in trying to find
	//	a window in the first stagger position (minus the one weÕre trying to
	//	position and the one in the first position).  backPtr points to the
	//	rear-most member of this list, i.e. the window in front of the first window.

	noOfWindows = privateData.noOfWindows;
	backPtr = *(privateData.backList) + noOfWindows;


	//	The following loop tests each position after the first to see if any window
	//	in our stored path ocupies it.  The first unoccupied position it finds, it
	//	takes.  If no unoccupied positions are found, we assume the screen is full
	//	of windows and we must start at the top of the order.

topOfLoop:
	if (!NextPosToCheck(&curStaggerPos, windCont, theScreen))
		TOPLEFT(*windCont) = firstStaggerPos;
	else {
		CreateCheckRect(&(privateData.checkRect), TOPLEFT(*windCont));
		while (noOfWindows) {
			--backPtr;
			--noOfWindows;
			if (WindowAtPos(*backPtr, &privateData))
				goto topOfLoop;
		}
	}

cleanup:
	DisposHandle((Handle)privateData.backList);		//	clean up the backward list.
out:
	return TOPLEFT(*windCont);						//	return the point to use
													//	in positioning the
													//	window.
}

//	This routine will return a point which can be used to position a window relative to the
//	supplied reference rectangle (in global coords).  The params horizControl and vertControl
//	determine how the window will be positioned.  If 'findScreen' is true, then the rectange
//	is not used directly.  Instead, we find what graphics device contains most of the
//	rectangle, and use the boundary of this screen as the reference rect.

pascal void __PositionWindow(WindowPtr whichWindow,
								const Rect *referenceRect,
								Boolean findScreen,
								HorizontalControlValues horizontalControl,
								VerticalControlValues verticalControl)
{
	Rect	windStruct,			//	bounding box of the windowÕs structure region
			windCont,			//	bounding box of the windowÕs content region
			theRefRect;			//	adjusted reference rect.

	Point	thePoint,			//	the position to move the structure region of the window
			structOffset;		//	to offset of structure region from contentregion

	//	get the boundary rect of the windows content region.  We donÕt care about what
	//	coordinate system its in.
	windCont = whichWindow->portRect;

	// get the boundary rect of a window with windCont for a portRect
	GetNewStructRect(&windStruct, (WindowPeek)whichWindow, &windCont);

	structOffset = TOPLEFT(windCont);
	SubPt(TOPLEFT(windStruct), &structOffset);

	//	adjust referenceRect for findScreen

	theRefRect = *referenceRect;

	if (findScreen)
		ScreenWithMostOf(&theRefRect);

	thePoint = TOPLEFT(theRefRect);		//	Set default value for thePoint

	if (verticalControl != vcStagger) {
		AddPt(structOffset, &thePoint);

		//	center vertically, if necessary

		if (verticalControl != vcNoVerticalControl) {
			short leftovery = (theRefRect.bottom - theRefRect.top) -
									(windStruct.bottom - windStruct.top);

			if (leftovery < 0)
				leftovery = 0;

			if (verticalControl == vcAlertCenter)
				thePoint.v += ShortDiv(leftovery, lmDialogConstant);
			else
				thePoint.v += (leftovery >> 1);
		}

		//	center horizontally, if necessary

		if (horizontalControl == hcCenter) {
			short leftoverx = (theRefRect.right - theRefRect.left) -
									(windStruct.right - windStruct.left);

			if (leftoverx < 0)
				leftoverx = 0;

			thePoint.h += (leftoverx >> 1);
		}
	} else
		thePoint = GetNextStaggerPos((WindowPeek)whichWindow, thePoint, &theRefRect, &windCont, structOffset);

	// Do the actual positioning

	MoveWindow(whichWindow, thePoint.h,  thePoint.v, false);
}

//	This routine gets the rectangle of the main screen with the menubar chopped off the top

void GetMainScreenRect(Rect *theMainScreenRect)
{
	if (HaveCQD()) {
		GDHandle theGDHand = MainDevice;
		*theMainScreenRect = (*theGDHand)->gdRect;
	} else
		*theMainScreenRect = WMgrPort->portRect;

	theMainScreenRect->top += MBarHeight;
}

//	This routine will position a window in various ways, relative to a rectangle that
//	it computes.  The postion location for where the window should be moved to is
//	returned as a point.  The 'locationControl' param determines how it computes the
//	reference rectangle.  The horizontalControl, and verticalControl params determine
//	how the window will be positioned.

pascal void __AutoPositionWindow(WindowPtr whichWindow, LocationControlValues where,
								HorizontalControlValues horizontalControl,
								VerticalControlValues verticalControl)
{
	Rect		theRect;
	Boolean		lookup;

again:

	lookup = false;

	// location control determines what we send to __PositionWindow as reference Rect

	if (where == lcMainScreen)
		GetMainScreenRect(&theRect);
	else {
		//	Find the window behind the one being positioned.

		WindowPtr parentWind = whichWindow;

		// starting at the one behind and going "toward the desktop", find first visible window.

		while ((parentWind = (WindowPtr) ((WindowPeek)parentWind)->nextWindow) != nil)
			if (((WindowPeek) parentWind)->visible)
				break;

		//	if there is such a window use the bounding box of its structure region

		if (parentWind) {
			theRect = (*(((WindowPeek) parentWind)->strucRgn))->rgnBBox;
			if (where == lcParentWindowScreen)	// use containing screen
				lookup = true;
		} else
			GetMainScreenRect(&theRect);		// if no good windows, use the main screen
	}

	//	Do the positioning

	PositionWindow(whichWindow, &theRect, lookup, horizontalControl, verticalControl);

	//	If the parent option is being used, a sanity check is done
	//	for the caller.

	if ((where == lcParentWindow) && (!CheckWindow(whichWindow, ccContent, true))) {
		where = lcParentWindowScreen;
		goto again;
	}
}

//	This routine returns the portRect of whichWindow in global coordinates.

pascal void __GlobalPortRect(WindowPtr whichWindow, Rect *theRect)
{
	/* Adjust to global coordinates. */
	BitMap* theMap;

	if ((theMap = &whichWindow->portBits)->rowBytes < 0)
		/* ItÕs a CGrafPort. */
		theMap = *((BitMap**) theMap->baseAddr);

	*theRect = whichWindow->portRect;
	OffsetRect(theRect, -theMap->bounds.left, -theMap->bounds.top);
}


//	IsZoomed determines if the window is zoomable, and if it is, checks whether or not it is in the
//	zoomed state in much the same way that the standard WDEF does it.

Boolean IsZoomed(WindowPtr window)
{
	if (((WindowPeek) window)->spareFlag) {		// check that window has concept of zooming
		Rect	zoomedRect,
				curRect,
				testRect;

		zoomedRect = ((WStateData*) (*((WindowPeek) window)->dataHandle))->stdState;
		GlobalPortRect(window, &curRect);

		InsetRect(&zoomedRect, -7, -7);			// create largest rect that is considered zoomed.

		if (SectRect(&zoomedRect, &curRect, &testRect) && EqualRect(&testRect, &curRect)) {
			// continue if all of the port is within largest rect

			InsetRect(&zoomedRect, 14, 14);		// create smallest rect that is considered zoomed.

			if (SectRect(&zoomedRect, &curRect, &testRect) && EqualRect(&testRect, &zoomedRect))
				return true;
				// if all of small rect is inside currect, return true
		}
	}
	return false;
}


//	GetWindowState returns a handle to data which records the current size of the window as
//	a Rect in global coordinates.  If the window is zoomable and it is zoomed this information
//	is stored and the size recorded is the windowÕs stored userState.

pascal OSErr __GetWindowState(WindowPtr whichWindow, Handle windState, Size *infoSize)
{
	SetHandleSize(windState, sizeof(WindowStateInfo));
	{
		OSErr e;
		if ((e = MemError()) != noErr)
			return e;
	}

	{
		WindowStateInfoPtr windStatePtr = (WindowStateInfoPtr) *windState;
		char savedState = HGetState(windState);
		HLock(windState);

		windStatePtr->infoVersion = 1;

		if (windStatePtr->zoomed = IsZoomed(whichWindow))
			windStatePtr->userState = ((WStateData*) (*((WindowPeek) whichWindow)->dataHandle))->userState;
		else
			GlobalPortRect(whichWindow, &(windStatePtr->userState));

		if (infoSize)
			*infoSize = sizeof(WindowStateInfo);

		HSetState(windState, savedState);
	}

	return noErr;
}

//	This should be generalized and made public (or at least exported for internal use).  There should be a way of legally
//	querying a window about its nature, i.e. is it draggable, sizeable, modal.  Better still would be a new message for the
//	window def which asks the window to give an account of itself.

pascal short IsDraggable(WindowPtr whichWindow)
{
	short draggable = false;
	short id;

	GetResInfo(((WindowPeek) whichWindow)->windowDefProc, &id, nil, nil);

	//	if this was a hand-stuffed, non-resource-based WDEF, assume it is not draggable

	if (ResError() == noErr) {

		//	if the id of the WDEF was 0 and the the variant was not 1, 2 or 3, we assume that the window is draggable
		//	if the id was 1, then its our old friend, the rounded WDEF and it is draggable.
		//	we assume all other WDEFs to be non-draggable.

		if (id == 0) {
			register short variant = GetWVariant(whichWindow);
			if ((variant < 1) || (variant > 3))
				draggable = true;
		} else if (id == 1)
			draggable = true;
	}

	return draggable;
}

//	SetWindowState takes a handle produced by GetWindowState adjusts a window accordingly.  The window
//	must be valid, but not necessarily visible.  If invisible when the routine is called, the window will
//	be invisible after.  A valid dataHandle field with a valid stdState must available before this routine
//	is called.  If the window was zoomed and the userState is not valid for the current configuration, an
//	error will be generated.

pascal OSErr __SetWindowState(WindowPtr whichWindow, Handle windState)
{
	WindowStateInfo		windStateRec;
	Rect				testRect;

	// Check for valid handle

	if ((whichWindow == nil) || (GetHandleSize(windState) < sizeof(WindowStateInfo)))
		return paramErr;

	windStateRec = * (WindowStateInfoPtr) *windState;

	// Check if version is one we donÕt know about

	if (windStateRec.infoVersion != 1)
		return badVersNo;

	// if the saved info indicates a zoomed window and the window isnÕt zoomable, its an error

	if (windStateRec.zoomed && !((WindowPeek) whichWindow)->spareFlag)
		return badWindowType;

	//	Test the saved position (or userState if zoomed) of the window to see if it is valid
	//	with the current screen configuration.

	GetNewStructRect(&testRect, (WindowPeek) whichWindow, &windStateRec.userState);		// get bounds of proposed structure region.

	{
		RgnHandle rgn = NewRgn();	// create region for testing visibility on the screen.

		//	if the window is draggable, weÕre only testing the drag bar for a valid location

		if (IsDraggable(whichWindow))
			testRect.bottom = testRect.top + 20;	// assume a drag bar in the top 20 pixels of the structure region;

		//	check the structure region (or drag bar) against the screen configuration.

		RectRgn(rgn, &testRect);
		DiffRgn(rgn, GrayRgn, rgn);

		// if 100% of windows structure region or dragbar is not on-screen, return an error

		{
			Boolean empty = EmptyRgn(rgn);
			DisposeRgn(rgn);
			if (!empty)
				return badWindPos;
		}
	}

	//	if the window was in the zoomed state when the windStateInfo was generated, it should be restored
	//	to a zoomed state and the old userState restored from the windStateInfo.  OtherWise, it should simply
	//	be moved to the userState in the windStateInfo.

	if (windStateRec.zoomed) {
		((WStateData *)(*(((WindowPeek)whichWindow)->dataHandle)))->userState = windStateRec.userState;
		testRect = ((WStateData *)(*(((WindowPeek)whichWindow)->dataHandle)))->stdState;
	} else
		testRect = windStateRec.userState;

	MoveWindow(whichWindow, testRect.left, testRect.top, false);
	SizeWindow(whichWindow, testRect.right - testRect.left, testRect.bottom - testRect.top, true);

	return noErr;
}

//	Checks the position of a window according to the checkControl parameter (assumes a rectangular window):
//		ccFrame - checks the entire window, including the structure region.
//		ccDragBar - assumes a dragbar in the top 20 pixels of the structure region bounding box
//		ccContent - checks the content region of the window.
//
//	If entirelyOnScreen is true, CheckWindow will return true only if the entire portion (structure,
//	dragbar or content) is on the screen.  Otherwise, CheckWindow will return true if the portion
//	intersects the visible screen at all.

pascal Boolean __CheckWindow(WindowPtr whichWindow, CheckControlValues checkControl,
	Boolean entirelyOnScreen)
{
	Rect theRect;
	RgnHandle theRgn;
	Boolean rval;

	//	Get the rectangle of the portion of the window weÕre concerned about

	if (checkControl < ccDragBar)	// If the we are checking the structure or dragbar, É
	{
		//	Get the bounding box of the structure region.

		if (((WindowPeek)whichWindow)->visible)
			theRect = (*(((WindowPeek)whichWindow)->strucRgn))->rgnBBox;
		else {
			GlobalPortRect(whichWindow, &theRect);
			GetNewStructRect(&theRect, (WindowPeek)whichWindow, &theRect);
		}

		//	if we are checking the dragbar, chop off all but the top 20 pixels.

		if (checkControl == ccDragBar)
			theRect.bottom = theRect.top + 20;
	} else
		GlobalPortRect(whichWindow, &theRect);	// else, get the content.

	theRgn = NewRgn();					//	turn the check rect into a region.
	RectRgn(theRgn, &theRect);

	//	compare the check region to the GrayRgn to determine the return value.

	if (entirelyOnScreen) {
		DiffRgn(theRgn, GrayRgn, theRgn);
		rval = EmptyRgn(theRgn);
	} else {
		SectRgn(theRgn, GrayRgn, theRgn);
		rval = !EmptyRgn(theRgn);
	}

	DisposeRgn(theRgn);		//	Clean up and goÉ

	return rval;
}

#define kIsLayer	((short) 0xDEAD)
#define FastIsLayer(window) (((GrafPtr) window)->txSize == kIsLayer)

/* Returns true iff window is really a layer. */
pascal Boolean
__IsLayer(WindowPtr window)
{
	return (window != nil) && FastIsLayer(window);
}


/* Returns the windowÕs "type". */
pascal short
__WindowType(WindowPtr window)
{
	return ((window != nil) && FastIsLayer(window)) ? isLayer : isWindow;
}

/* Creates a new window or layer.  This is common code used by NewWindow, NewCWindow and NewLayer. */
pascal WindowPtr
NewWindowCommon(register Ptr wStorage, register const Rect *boundsRect, const Str255 title,
	register Boolean visible, short theProc, WindowPtr behind, Boolean goAwayFlag, long refCon,
	Boolean isColor)
{
#if hasLayerlessApps
	pascal void HashWindow(WindowPeek theWindow, WindowPeek behind, Boolean visible);
#endif
	GrafPtr		savePort;

	GetPort(&savePort);

	/* Be sure to allocate the storage */
	wStorage = (wStorage == nil) ? NewPtr(sizeof(WindowRecord)) : StripAddress(wStorage);

	/* Zero out all the fields in the window record.
	 * Since WindowRecord is 0x9C long, we can use a fast longword clear.
	 */
	{
		register int countDown;
		register long* longPtr = (long *) wStorage;
		for (countDown = sizeof(WindowRecord) >> 2; countDown > 0; countDown--)
			*(longPtr++) = 0;
	}

	/* Open the correct style port. */
	if (isColor && HaveCQD())
		OpenCPort((CGrafPtr) wStorage);
	else
		OpenPort((GrafPtr) wStorage);

	/* Set the default font. */
	TextFont(applFont);

	{
		/* Get the active window before we splice into the window list. */
		WindowPtr oldFront = ActiveWindow();

		/* Insert it into the window list. */
		if (behind == (WindowPtr) -1) {
			/* Special case - insert it first. */
			((WindowPeek) wStorage)->nextWindow = WindowList;
			WindowList = ((WindowPeek) wStorage);
		} else
			InsertWindow((WindowPtr) wStorage, behind);

		/* Get the WDEF.  If the one weÕre looking for doesnÕt exist, get id = 0. */
		{
			register short wdefID = theProc >> 4;
			register Handle wdefHandle;

			ROMMapInsert = mapTrue;
			if ((wdefHandle = GetResource('WDEF', wdefID)) == nil) {
				ROMMapInsert = mapTrue;
				if ((wdefHandle = GetResource('WDEF', 0)) == nil)
					SysError(dsWDEFNotFound);
			}
			((WindowPeek) wStorage)->windowDefProc = wdefHandle;

			if (wdefID == layerWDEF) {
				/* Initialize layer-specific fields. */
				((LayerPeek) wStorage)->parent = CurLayer;
				if (HaveCQD()) {
					GetAuxWin(nil, &((LayerPeek) wStorage)->auxWinHead);
					GetAuxCtl(nil, &((LayerPeek) wStorage)->auxCtlHead);
				}
				((GrafPtr) wStorage)->txSize = kIsLayer;	/* kIsLayer text size is the mark of being a layer */
			}
#if TheFuture && !hasLayerlessAppsINIT
			else {
				/* All windows have titles. */
				if (title == nil)
					title = "\p";	/* empty string is the default title */
			}
#endif
		}

#if hasLayerlessApps
		if (((GrafPtr) wStorage)->txSize != kIsLayer)
			HashWindow((WindowPeek)wStorage, (WindowPeek)behind, visible);
#endif

		/* Put the variant in the right place. */
		{
			register unsigned char variant = theProc & 0xF;
			if (HaveCQD() && MMU32Bit) {
				AuxWinHandle awHndl;

				/* Auxiliary window record is mandatory in 32 bit mode. */
				SetWinColor((WindowPtr) wStorage, (WCTabHandle) -1);
				(void) GetAuxWin((WindowPtr) wStorage, &awHndl);
				(*(unsigned char *) &((**awHndl).awFlags)) = variant;
			} else
				(*(unsigned char *) &(((WindowPeek) wStorage)->windowDefProc)) = variant;
		}

		/* Initialize windowKind, visible, goAwayFlag, refCon */
		((WindowPeek) wStorage)->windowKind = userKind;
		((WindowPeek) wStorage)->visible = visible;
		((WindowPeek) wStorage)->goAwayFlag = goAwayFlag;
		((WindowPeek) wStorage)->refCon = refCon;

		/* Allocate 3 regions. */
		((WindowPeek) wStorage)->strucRgn = NewRgn();
		((WindowPeek) wStorage)->contRgn = NewRgn();
		((WindowPeek) wStorage)->updateRgn = NewRgn();

		/* Get the new active window, and make activate/deactivate events if necessary. */
		{
			WindowPtr newFront = ActiveWindow();
			if (newFront != oldFront) {
				if (oldFront != nil)
					MakeDeactiveGlue(oldFront);
				if (newFront != nil)
					((WindowPeek) newFront)->hilited = true;
					CurActivate = (WindowPeek) newFront;
			}
		}
	}

	{
		/* Finish setting up the port before doing anything else. */
		Boolean	autoPosition = false;
		if (boundsRect != nil) {
			/* Adjust the portRect first. */
			if ((boundsRect->top == autoPositionTopCookie) && ((boundsRect->left & 0x7FF) == 0xA)) {
				autoPosition = true;
				MovePortTo(0, 0);
				PortSize(boundsRect->right, boundsRect->bottom);
			} else {
				MovePortTo(boundsRect->left, boundsRect->top);
				PortSize(boundsRect->right - boundsRect->left, boundsRect->bottom - boundsRect->top);
			}
		}

		/* Go to the window manager port for string width calculation. */
		SetPort(WMgrPort);

		if (title != nil) {
			/* Do the title. */
			((WindowPeek) wStorage)->titleHandle = NewString(title);
			((WindowPeek) wStorage)->titleWidth = StringWidth(title);
		}

		CallWindowGlue((WindowPeek) wStorage, wNew, 0);

		if (autoPosition) {
			struct	AutoWindowPosition *info = (struct AutoWindowPosition *) &(boundsRect->left);

			//	This window is actually invisible since its regions are zeroed out and it has
			//	not been displayed yet.  Thus we make the visible flag reflect this fact for
			//	so that AutoPositionWindow (which does not expect a window to be in a limbo
			//	state) will do the right thing.

			((WindowPeek) wStorage)->visible = false;

			AutoPositionWindow((WindowPtr) wStorage, info->screenControl,
				info->hPosition, info->vPosition);

			//	Restore the flag to its "correct" state.

			((WindowPeek) wStorage)->visible = visible;
		}
	}

	/* Calculate the structure and content of this window or layer.
	 * If it is a visible window, it can also affect the structure of the layers it is contained in
	 * and needs to be drawn and obscure other windows.
	 */
	CallWindowCalcGlue((WindowPeek) wStorage);
	if (visible && !FastIsLayer(wStorage)) {
		ActivatePalette((WindowPtr) wStorage);
		PaintOne((WindowPeek) wStorage, ((WindowPeek) wStorage)->strucRgn);
		CalcVisBehind((WindowPeek) wStorage, ((WindowPeek) wStorage)->strucRgn);
		CalcDeskPortVisRgn();
	}

	SetPort(savePort);
	
	return (WindowPtr) wStorage;
}


/* Creates a layer. */
pascal OSErr
__NewLayer(LayerPtr *layer, Boolean visible, Boolean neverActive, WindowPtr behind, long refCon)
{
	*layer = NewWindowCommon((Ptr) *layer, nil, nil, visible, layerProc, behind, neverActive, refCon, true);
	if (HMGetBalloons())
		HMInvalidateSavedBits((WindowPtr) *layer);
	return noErr;
}


/* Gets the current layer. */
pascal LayerPtr
__GetCurLayer(void)
{
	return (LayerPtr) CurLayer;
}


/* Synchronizes the old Window Manager globals with the current layer. */
pascal void
SyncCurLayer(void)
{
	LayerPeek curLayer;

	if ((curLayer = CurLayer) != nil) {
		if (HaveCQD()) {
			curLayer->auxWinHead = AuxWinHead;
			curLayer->auxCtlHead = AuxCtlHead;
		}
		curLayer->subWindows = WindowList;
	}
}


/* Sets the current layer.  Note that WindowList always contains the children of the current layer. */
pascal void
__SetCurLayer(LayerPtr layer)
{
	register LayerPeek newLayer;

	/* Reassert child pointer and auxiliary lists in case they changed. */
	SyncCurLayer();

	if ((newLayer = (LayerPeek) layer) == nil)
		newLayer = (LayerPeek) GetRootLayer();

	if (newLayer != nil) {		/* Needed because GetRootLayer() returns nil during InitWindows. */
		assert(IsLayer((LayerPtr) layer));

		/* Change the current layer. */
		CurLayer = newLayer;

		/* Set up the window and auxiliary lists. */
		if (HaveCQD()) {
			AuxWinHead = newLayer->auxWinHead;
			AuxCtlHead = newLayer->auxCtlHead;
		}
		WindowList = newLayer->subWindows;
	}
}


/* Sets the current layer.  Returns the previous current layer.  Does not use traps for speed. */
pascal LayerPtr
__SwapCurLayer(LayerPtr layer)
{
	LayerPtr saveLayer = (LayerPtr) CurLayer;

	/* Replace with old value. */
	__SetCurLayer(layer);

	return saveLayer;
}


/* Gets the desk port. */
pascal OSErr
__GetDeskPort(GrafPtr* result)
{
	*result = DeskPort;
	return noErr;
}


/* Gets the children of a layer. */
pascal WindowPeek
__GetSubWindows(LayerPtr layer)
{
	if (IsLayer(layer))
		return ((LayerPeek) layer)->subWindows;
	else
		return nil;
}


/* This iterates over the hierarchy. It starts with start and calls the action procedure for each
 * object (layer or window), up to but not including stop in the layer denoted by parent.
 * Nil and -1 are valid for start and stop, nil meaning after the last window in parent, and
 * -1 meaning the first window in parent.    If stop is -1, the iteration "wraps", causing the
 * iteration to continue to the end of the hierarchy (useful for xxxBehind traps).  If parent is
 * nil, EachWindow will use startÕs parent, or CurLayer if start is nil or -1.
 */
pascal OSErr
__EachWindow(WindowPeek start, WindowPeek stop, LayerPeek parent, WindowAction *action, void *privateData)
{
	/* Since EachWindow requires that the hierarchy remains intact, reassert the
	 * child pointer in case it changed.
	 */
	SyncCurLayer();

	/* Check for nil parent. */
	if (parent == nil) {
		if ((start == afterLastWindow) || (start == firstWindow))
			parent = CurLayer;
		else
			parent = __GetParent((WindowPtr) start);
	}
	assert(IsLayer(parent));

	/* Check for firstWindow start. */
	if (start == firstWindow)
		start = __GetSubWindows((LayerPtr) parent);

	/* Check for afterLastWindow or afterLastLayer stop. */
	if (stop == afterLastWindow)
		stop = (WindowPeek) parent;
	else if (stop == afterLastLayer)
		stop = nil;

	for (;;) {
		while ((start == nil) && (parent != nil)) {
			/* WeÕve just finished searching a family with no luck.  Pop up a level.
			 * The next child to be searched is DadÕs little sister.
			 */
			if ((WindowPeek) parent == stop)
				/* WeÕre done. */
				return noErr;
			start = parent->nextWindow;
			parent = parent->parent;
		}

		if ((start == stop) || (start == nil))
			/* WeÕre done looking. */
			return noErr;

		{
			/* If we found the little critter, reunite the family. */
			OSErr result = (*action)(start, parent, privateData);
			if ((result != noErr) && (result != skipChildren))
				return result;

			/* If the kid is a layer, he might have kids of his own.
			 * Search his family unless he has the plague.
			 */
			if ((result != skipChildren) && FastIsLayer(start)) {
				parent = (LayerPeek) start;
				start = parent->subWindows;
				/* Note that we are now searching a new family. */
			} else {
				/* Advance to the next sibling. */
				start = start->nextWindow;
			}
		}
	}

	/* Not reached due to for (;;) above. */
}


#if !hasLayerlessApps

/* ParentSearch is an action procedure that finds a specific windowÕs parent.
 * It always descends into sub-trees.
 */
pascal OSErr
ParentSearch(WindowPeek window, LayerPeek parent, WindowPtr *target)
{
	if (window == (WindowPeek) *target) {
		*target = (WindowPtr) parent;
		return haltIterator;
	} else
		return noErr;
}

/* Finds the parent of the given window. */
pascal LayerPeek
__GetParent(WindowPtr window)
{
	if (window == nil)
		/* By Imperial decree, the parent of nil is CurLayer. */
		return CurLayer;
	else if (FastIsLayer(window)) {
		/* Layers and Earth girls are easy. */
		return ((LayerPeek) window)->parent;
	} else {
		/* Look high and low... */
		LayerPeek	parent = (LayerPeek) window;

		/* Start looking in Curlayer. */
		if (EachWindow(firstWindow, afterLastLayer, nil, ParentSearch, &parent) == noErr)
			/* If not there, try the rest of the hierarchy. */
			if (EachWindow(firstWindow, (WindowPeek) CurLayer, (LayerPeek) __GetRootLayer(), ParentSearch, &parent) == noErr)
				/* If not there, give up. */
				return nil;

		return parent;
	}
}
#endif

/* Finds the root layer.  Returns nil if there is none (during initialization). */
pascal LayerPtr
__GetRootLayer(void)
{
	LayerPtr	layer, parent;

	/* Start with the current layer. */
	if ((layer = (LayerPtr) CurLayer) == nil)
		return nil;

	/* The root is the only layer that doesnÕt have a parent. */
	while ((parent = (LayerPtr) ((LayerPeek) layer)->parent) != nil)
		layer = parent;

	return layer;
}


/* Returns true iff artifact is an ancestor of or equal to child. */
Boolean
IsAncestor(WindowPtr artifact, LayerPtr child)
{
	assert(IsLayer(child));

	do
		if (child == artifact)
			return true;
	while ((child = (WindowPtr) ((LayerPeek) child)->parent) != nil);

	return false;
}
  
/* Initializes the layer and window managers. */
pascal OSErr
__InitLayers(void)
{
	CurLayer = nil;

	/* Create the DeskPort, which is a port that has an updateRgn. */
	{
		register GrafPtr deskPort = (GrafPtr) NewPtrClear(sizeof(WindowRecord));
		OpenPort(deskPort);
		((WindowPeek) deskPort)->updateRgn = NewRgn();
		DeskPort = deskPort;
	}

	/* Call the old InitWindows. */
#if hasLayerlessAppsINIT
	InitWindows();
#else
	InitWindowsGuts();
#endif

	/* Create the two layers (one for system stuff). */
	{
		short i;
		for (i = 0; i < 2; i++) {
			LayerPtr layer = nil;
			(void) __NewLayer(&layer, true, false, (WindowPtr) -1, 0);
			SetCurLayer(layer);
		}
	}

	return noErr;
}

/* DrawWindowPic draws the window picture in a window. */
pascal void
DrawWindowPic(WindowPeek window)
{
	PicHandle	windowPic = window->windowPic;
	Rect		picFrame = (**windowPic).picFrame;
	GrafPtr		savePort;
	RgnHandle	saveClip = NewRgn();

	GetPort(&savePort);
	SetPort(&window->port);
	GetClip(saveClip);
	ClipRect(&window->port.portRect);

	BeginUpdate((WindowPtr) window);
	DrawPicture(windowPic, &picFrame);
	EndUpdate((WindowPtr) window);

	SetClip(saveClip);
	DisposeRgn(saveClip);
	SetPort(savePort);
}

#if !hasLayerlessApps
/* Tells all ancestor layers to calculate their regions. */
pascal void
CalcAncestorRgns(WindowPtr window)
{
	/* Since CalcAncestorRgns requires that the hierarchy remains intact, reassert the
	 * child pointer in case it changed.
	 */
	SyncCurLayer();

	{
		LayerPeek layer = __GetParent(window);
		while (layer != nil) {
			CallWindowCalcGlue((WindowPeek) layer);
			layer = layer->parent;
		}
	}
}
#endif


/* CheckUpdateSearch is an action procedure used by CheckUpdate that finds the frontmost
 * window or layer that needs updating.  It will update any windowPics automatically.
 * It always descends into sub-trees, but skips invisible layers and windows.
 */
pascal OSErr
CheckUpdateSearch(WindowPeek window, LayerPeek, WindowPeek *updateWindow)
{
	if (!window->visible)
		return skipChildren;

	if (EmptyRgn(window->updateRgn))
		return noErr;

	if (!FastIsLayer((WindowPtr) window) && (window->windowPic != nil)) {
		DrawWindowPic(window);
		return noErr;
	}

	*updateWindow = window;
	return haltIterator;
}


/* Called by the Event Manager to look for update events.  Will fill out event record and
 * return true if a window is found that needs to be updated.  Checks for updates in the
 * layer given and all its children.
 */
pascal Boolean
__CheckUpdateIn(EventRecord *event, LayerPtr inLayer)
{
	register Boolean result = false;

	ValidateMenuBar();

	if ((EachWindow((WindowPeek) inLayer, ((WindowPeek) inLayer)->nextWindow,
		((LayerPeek) inLayer)->parent, CheckUpdateSearch, &event->message) != noErr)) {
		/* Make an update event and return true. */
		event->what = updateEvt;
		result = true;
	}

	return result;
}


/* Called by others to look for update events.  Replaces the routine in ROM.
 * Changes include looking for layers and only examining WindowPic if it is not one.
 * CheckUpdate only searches in the application layer.
 */
pascal Boolean
__CheckUpdate(EventRecord *event)
{
	return __CheckUpdateIn(event, (LayerPtr) CurLayer);
}


/* If window is a layer, BeginUpdate will correctly paint and calculate visRgns for its children. */
pascal void
BeginUpdateOfLayersChildren(WindowPtr window)
{
	if (FastIsLayer(window)) {
		PaintOne((WindowPeek) window, ((WindowPeek) window)->updateRgn);
		/* Note that only the children of window really need CalcVis. */
		CalcVis((WindowPeek) window);
	}
}

#if !hasLayerlessApps
/* Sets the clipRgn of the Window Manager port to be the desktop intersected with the current
 * clipRgn, minus the structure regions of all the windows in front of the given window.  If
 * window is nil, all windows in the current layer are "in front".  It makes use of the old code
 * in ROM.
 */
pascal void
__ClipAbove(WindowPeek window)
{
	LayerPtr	saveLayer = (LayerPtr) CurLayer;
	LayerPtr	parent = (LayerPtr) __GetParent((WindowPtr) window);

	while (parent != nil) {
		if (!((LayerPeek) parent)->visible) {
			/* Parent is invisible, set the clip to the empty region and get out! */
			SetEmptyRgn(WMgrPort->clipRgn);
			break;
		}

		/* Call the old ClipAbove (set the current layer for it). */
		__SetCurLayer(parent);
		ClipAboveGuts(window);

		/* Jump up a layer. */
		window = (WindowPeek) parent;
		parent = (LayerPtr) ((LayerPeek) parent)->parent;
	}

	/* Restore the current layer. */
	__SetCurLayer(saveLayer);
}
#endif

#if !hasLayerlessApps
/* Recalculate the visRgn of the DeskPort. */
void
CalcDeskPortVisRgn(void)
{
	register GrafPtr wMgrPort = WMgrPort;
	register RgnHandle deskPortVisRgn = (long) DeskPort->visRgn;
	RgnHandle wMgrPortClipRgn = wMgrPort->clipRgn;

	/* Recalculate the visible part of the desktop.
	 * Note that we use ClipAbove, which works on the WMgrPortÕs clipRgn directly.
	 * Start by opening the region wide, and putting it in the WMgrPortÕs clipRgn.
	 */
	CopyRgn(GrayRgn, deskPortVisRgn);
	wMgrPort->clipRgn = deskPortVisRgn;
	/* Now call ClipAbove(nil) at the root. */
	{
		register long saveLayer = (long) SwapCurLayer(nil);	/* get a D register (SLIME) */
		ClipAbove(nil);
		SetCurLayer((LayerPtr) saveLayer);
	}
	/* Finally, restore the WMgrPortÕs clipRgn.. */
	wMgrPort->clipRgn = wMgrPortClipRgn;
}
#endif

#if hasLayerlessApps
void PaintTheDesk(RgnHandle clobberedRgn);
#else
/* Call this to update the desktop when part of the desktop is clobbered. */
void
PaintTheDesk(RgnHandle clobberedRgn)
{
	register GrafPtr wMgrPort = WMgrPort;
	register GrafPtr deskPort = DeskPort;
	register RgnHandle wMgrPortClipRgn = wMgrPort->clipRgn;

	CalcDeskPortVisRgn();
	/* Set up clipping of the WMgrPort to intersection of what was clobbered and visible. */
	SectRgn(clobberedRgn, deskPort->visRgn, wMgrPortClipRgn);
	/* Accumulate visible clobbered areas into the DeskPortÕs updateRgn. */
	{
		register RgnHandle deskUpdate = ((WindowPeek) deskPort)->updateRgn;
		UnionRgn(deskUpdate, wMgrPortClipRgn, deskUpdate);
	}
	/* Draw gray, and leave the clipRgn set, for compatibility with old apps. that expect it.
	 * Use the WMgrCPort on CQD machines, so that we can draw color patterns.
	 */
	if (HaveCQD())
		wMgrPort = (GrafPtr) WMgrCPort;
	SetPort(wMgrPort);
	PaintDesk();
}
#endif

typedef struct {
	WindowPtr	frontWindow;
	RgnHandle	clobberedRgn;
} PaintInfoRec, *PaintInfoPtr;

/* PaintAction is an action procedure that doesnÕt find anything.
 * It paints the window, clipped to clobberedRgn.
 */
pascal OSErr
PaintAction(WindowPeek window, LayerPeek, PaintInfoPtr paintInfo)
{
	if (!window->visible)
		return skipChildren;

	if ((!FastIsLayer(window)) &&
		((paintInfo->frontWindow == notPaletteUpdate) ||
		 ((*WhatPal((WindowPtr) window))->pmPrivate &
		  ((window == paintInfo->frontWindow) ? CForeMask : CBackMask)))) {

		/* Call the old PaintOne for real windows only in normal loops and when a palette update
		 * is necessary.
		 */
		PaintOneGuts(window, paintInfo->clobberedRgn);
	}

	return noErr;
}

#if !hasLayerlessApps
/* <56> CalcAncestorRgns for the normal case. If the one-shot in ExpandMem is set, that
 * means that some other call has already calculated the ancestor regions, so we can be
 * faster by not recalculating them.
 */
void CalcAncestorRgnsForPaintActions(WindowPtr window)
{
	ExpandMemRec *emRec = ExpandMem;
	if (GetExpandMemAncestorRgnsCalced() == 0)
		CalcAncestorRgns(window);		// calculate the regions if the one-shot is off
	else
		SetExpandMemAncestorRgnsCalced(0);		// reset the one-shot
}
#endif

/* Paints the given window, and any children, clipped to clobberedRgn. */
/* <55> VL 	PaintOne calls CalcAncestorRgns before calling PaintOneLite. */
pascal void
__PaintOne(WindowPeek window, RgnHandle clobberedRgn)
{
#if !hasLayerlessApps
	CalcAncestorRgnsForPaintActions((WindowPtr) window);
#endif

	if (window == nil) {
		PaintTheDesk(clobberedRgn);
	} else {
		PaintInfoRec	paintInfo;

		if (HMGetBalloons())
			HMInvalidateSavedBits((WindowPtr) window);

		paintInfo.frontWindow = notPaletteUpdate;
		paintInfo.clobberedRgn = clobberedRgn;
		(void) EachWindow(window, window->nextWindow, nil, PaintAction, &paintInfo);
	}
}

#if !hasLayerlessApps
/* Paints the given window, and any children, and all windows behind the given window, even
 * in layers behind its parent, and the desktop, clipped to clobberedRgn.  If startWindow is
 * nil, it paints all windows behind CurLayer.
 */
/* <55> VL   PaintBehind calls CalcAncestorRgns before calling PaintBehindLite. */
pascal void
__PaintBehind(WindowPeek startWindow, RgnHandle clobberedRgn)
{
	PaintInfoRec	paintInfo;

	CalcAncestorRgnsForPaintActions((WindowPtr) startWindow);

	PaintTheDesk(clobberedRgn);

	paintInfo.frontWindow = notPaletteUpdate;
	paintInfo.clobberedRgn = clobberedRgn;
	(void) EachWindow(startWindow, afterLastLayer, nil, PaintAction, &paintInfo);

	/* Blast PaintWhite to be compatible. */
	PaintWhite = kDoPaintWhite;
}
#endif


/* Similar to PaintOne, but only paints windows that have the proper Palette Manager flags.
 */
pascal void
__PaintOnePal(WindowPeek window, RgnHandle clobberedRgn)
{
	PaintInfoRec	paintInfo;
	short			savePaintWhite = PaintWhite;

	if (window == nil) {
		/* In this case, weÕre painting everything. */
		PaintTheDesk(clobberedRgn);
		window = (WindowPeek) GetRootLayer();
	}

	/* Never PaintWhite in palette update. */
	PaintWhite = kDontPaintWhite;
	paintInfo.frontWindow = ActiveWindow();
	paintInfo.clobberedRgn = clobberedRgn;
	(void) EachWindow(window, window->nextWindow, nil, PaintAction, &paintInfo);
	PaintWhite = savePaintWhite;
}


/* UpdatedVisRgn is called whenever a visRgn has been changed. */
pascal void
UpdatedVisRgn(WindowPeek window)
{
	VisRgnChanged((WindowPtr) window);

	if (window == WMgrUpdate) {
		/* WeÕre changing the visRgn of a window inside BeginUpdate/EndUpdate.
		 * Invalidate SaveVisRgn.
		 */
		WMgrUpdate = nil;
		SetEmptyRgn(SaveVisRgn);
	}
}

#if !hasLayerlessApps

/* EmptyVisAction is an action procedure that doesnÕt find anything.  It sets the visRgn
 * of all its windows to be empty.  It skips the children of all layers whose visRgn is
 * already empty as an optimization.
 */
pascal OSErr
EmptyVisAction(WindowPeek window, LayerPeek, void*)
{
	if (!FastIsLayer(window)) {
		RgnHandle myVis = window->port.visRgn;
		if (myVis != DeskPort->visRgn) {
			SetEmptyRgn(myVis);
			UpdatedVisRgn(window);
		}
	}

	return noErr;
}

/* CalcVisAction is an action procedure that doesnÕt find anything.  It recalculates the visRgn
 * for any window that intersects the clobberedRgn.
 */
pascal OSErr
CalcVisAction(WindowPeek window, LayerPeek parent, RgnHandle clobberedRgn)
{
	if (!window->visible) {
		/* If itÕs invisible, donÕt waste time, just make all the visRgns empty. */
		(void) EachWindow(window, window->nextWindow, parent, EmptyVisAction, nil);
		return skipChildren;
	}

	if ((clobberedRgn == nil) || RectInRgn(&(**window->contRgn).rgnBBox, clobberedRgn)) {
		/* If the clobbered region intersects then recalculate the visRgn. */
		register long myVis = (long) window->port.visRgn;			/* get a D register (SLIME) */

		if ((RgnHandle) myVis != DeskPort->visRgn) {
			{
				/* Borrow ClipAbove technology to calculate the visRgn. */
				register RgnHandle* wMgrPortClipRgnPtr = &WMgrPort->clipRgn;
				register long saveClip = (long) *wMgrPortClipRgnPtr;	/* get a D register (SLIME) */
				CopyRgn(window->contRgn, (RgnHandle) myVis);
				*wMgrPortClipRgnPtr = (RgnHandle) myVis;
				ClipAbove(window);
				*wMgrPortClipRgnPtr = (RgnHandle) saveClip;
			}

			{
				/* Adjust to local coordinates. */
				BitMap* theMap;
				if ((theMap = &window->port.portBits)->rowBytes < 0)
					/* ItÕs a CGrafPort. */
					theMap = *((BitMap **) theMap->baseAddr);
				OffsetRgn((RgnHandle) myVis, theMap->bounds.left, theMap->bounds.top);
			}

			UpdatedVisRgn(window);
		}
	}
	else if (FastIsLayer(window) && !RectInRgn(&(**window->strucRgn).rgnBBox, clobberedRgn))
		/* DonÕt waste time looking at children if structure doesnÕt intersect. */
		return skipChildren;

	return noErr;
}

/* Calculates the visRgn for window and any children. */
pascal void
__CalcVis(WindowPeek window)
{
	if (window != nil)
		(void) EachWindow(window, window->nextWindow, nil, CalcVisAction, nil);
}


/* Calculates the visRgn for window and all windows behind, even in layers behind its parent
 * and any children that intersect clobberedRgn.  If startWindow is nil, it calculates the
 * visRgn for all windows behind CurLayer that intersect.
 */
pascal void
__CalcVisBehind(WindowPeek startWindow, RgnHandle clobberedRgn)
{
	if (startWindow != nil) {
		/* Always CalcVis the startWindow and go to next one. */
		__CalcVis(startWindow);
		startWindow = startWindow->nextWindow;
	}

	(void) EachWindow(startWindow, afterLastLayer, nil, CalcVisAction, clobberedRgn);
}

#endif

#if !hasLayerlessApps
/* Determines which region of which window a point lies inside.  Descends layers until a window is
 * found.  Starts with the current subtree.
 */
pascal short
__FindWindow(Point point, WindowPtr *window)
{
	/* Save the current layer. */
	LayerPtr	saveLayer = (LayerPtr) CurLayer;
	short		result;

	/* Loop indefinitely until break is used. */
	for (;;) {
		/* Call the old FindWindow. */
		result = FindLayer(point, window);

		/* WeÕre done if itÕs not in a layer. */
		if ((result != inContent) || !FastIsLayer(*window))
			break;

		/* ItÕs a layer, go down and try again. */
		__SetCurLayer((LayerPtr) *window);
	}

	/* Restore the current layer. */
	__SetCurLayer(saveLayer);

	return result;
}
#endif

/* Returns the frontmost active window in the given layer.  Note that FrontWindowIn, like
 * FindWindow, only descends into subtrees, and never leaves them; so EachWindow is not usable here.
 */
pascal WindowPtr
__FrontWindowIn(LayerPtr layer)
{
	/* Since FrontWindowIn requires that the hierarchy remains intact, reassert the
	 * child pointer in case it changed.
	 */
	SyncCurLayer();

	/* Check the window list, descending into each candidate.  If we find a window, break
	 * out of the loop.
	 */
	{
		WindowPeek window = __GetSubWindows(layer);
		while (window != nil) {
			if (window->visible && (window != GhostWindow)) {
				if (!FastIsLayer((WindowPtr) window))
					/* ItÕs not a layer, so it must be the right one. */
					break;
				if (!((LayerPeek) window)->neverActive) {
					/* ItÕs a normal layer (not neverActive), so descend and continue. */
					window = __GetSubWindows((LayerPtr) window);
					continue;
				}
			}
			/* Otherwise, just go on to the next window. */
			window = window->nextWindow;
		}

		return (WindowPtr) window;
	}
}

/* Returns the frontmost active window in the application layer. */
pascal WindowPtr
__FrontWindow(void)
{
	return __FrontWindowIn((LayerPtr) CurLayer);
}

/* Returns the frontmost active window. */
pascal WindowPtr
__ActiveWindow(void)
{
	return __FrontWindowIn(GetRootLayer());
}

/* Bracketed to ensure layer is correct.  If this window is a layer, its children will
 * be orphaned.
 */
pascal void
__CloseWindow(WindowPtr window)
{
	/* Save the current layer. */
	LayerPtr saveLayer = __SwapCurLayer((LayerPtr) __GetParent(window));

	if (FastIsLayer(window)) {
#if hasLayerlessApps
		//	We do this now because the old CloseWindow will do it eventually and when
		//	it dose it, auxWindHead will be NULL etc., which will cause crashes in
		//	ShowHideLayer.
		
		ShowHide(window, false);
#endif
		/* CloseWindow can orphan saveLayer.  If this is about to happen, correct, by not
		 * restoring the current layer.
		 */
		if (IsAncestor(window, saveLayer))
			saveLayer = (LayerPtr) CurLayer;

		/* Clear out title handle so we donÕt crash.  Layers use this as auxWinHead. */
		((WindowPeek) window)->titleHandle = nil;

		/* Clear out control list so we donÕt crash.  Layers use this as auxCtlHead. */
		((WindowPeek) window)->controlList = nil;

#if !hasLayerlessApps
		//	we will do this in our come-from patch DisposeRgn in the rom CloseWindow
		
		/* Set subWindows to nil so that KillPicture isnÕt called.
		 * If any of the children are also layers, their parent pointers will be invalid,
		 * but youÕre not supposed to call CloseWindow on a layer in this case anyway.
		 */
		((LayerPeek) window)->subWindows = nil;
#endif
	}

	/* Call the old CloseWindow. */
	CloseWindowGuts(window);

	/* Restore the current layer. */
	__SetCurLayer(saveLayer);
}

#if !hasLayerlessApps

/* Empty out the structRgn, contRgn and visRgn as the layer to which the window belongs is becoming invisible. */
pascal OSErr
HideWindowAction(WindowPeek window, LayerPeek, PaintInfoPtr)
{
	SetEmptyRgn(window->strucRgn);
	SetEmptyRgn(window->contRgn);
	SetEmptyRgn(((GrafPtr) window)->visRgn);

	return noErr;
}

/* Calculate the structRgn and contRgn of the window as the layer to which it belongs is becoming visible.	*/
/* The visRgn is not calculated here.  But it will be calculated in ShowHide where CalcVBehind is called 	*/
pascal OSErr
ShowWindowAction(WindowPeek window, LayerPeek layer, PaintInfoPtr)
{
	if (!window->visible)
		return skipChildren;
	if (!FastIsLayer(window)) {
		CallWindowCalcGlue(window);
		if (window->nextWindow == nil)					/* calculate parent only after the last child of a layer */
			CallWindowCalcGlue((WindowPeek) layer);
	}
	return noErr;
}

/* This routine is called by the ShowHide patch to fix up the regions if the object to be shown/hidden is a layer */
pascal void
PreShowHide(WindowPtr window, Boolean showFlag)
{
	if (FastIsLayer(window)) {
		EachWindow(firstWindow,afterLastWindow,(LayerPeek) window,(showFlag ? ShowWindowAction : HideWindowAction),nil);
		CalcAncestorRgns(window);
	}
}

#endif

/* This routine is a local routine used to redraw a region. All the windows from the root layer will be refreshed. */
pascal void
Redraw(RgnHandle region)
{
	GrafPtr				origPort;
	register GrafPtr	wmgrPort = WMgrPort;
	EventRecord			discardEvent;
	Rect				menuBarRect;

	PaintBehind((WindowPeek) __GetRootLayer(), region);

	GetPort(&origPort);
	SetPort(wmgrPort);

	SetRect(&menuBarRect, wmgrPort->portRect.left, wmgrPort->portRect.top,  wmgrPort->portRect.right, wmgrPort->portRect.top+MBarHeight);
	if (SectRect(&((**region).rgnBBox), &menuBarRect, &menuBarRect))
		InvalMenuBar();

	/* Here is a hack to get help windows updated. Since Process Mgr. uses CheckUpdate only on the appl layer, 	*/
	/* it never passes updates to the system windows (e.g. help windows).										*/
	/* This CheckUpdateIn doesnÕt really work unless the system windows use the WindowPic updating scheme. 		*/
	(void) __CheckUpdateIn(&discardEvent, __GetRootLayer());

	SetPort(origPort);
}

/* This routine redraws all the windows in the layer structure. */
pascal void
__RedrawAll(void)
{
	RgnHandle	wideOpenArea = NewRgn();
	SetRectRgn(wideOpenArea, -32768,  -32768,  32767, 32767);
	Redraw(wideOpenArea);
	DisposeRgn(wideOpenArea);
}
