/********************************************************************
*   DrvWindows.c
*
*   Macintosh device specific windows sub-system implementation.
*
*   Copyright (c) 1994-1997, Willows Software Inc.  All rights reserved.
********************************************************************/


/* System includes */
#include <stdlib.h>
#include <string.h>

/* Driver includes */
#include "DrvHook.h"
#include "DrvGlobals.h"
#include "DrvWindows.h"
#include "DrvUtils.h"
#include "DrvSystem.h"
#include "DrvEvents.h"
#include "DrvImages.h"
#include "DrvDP.h"
#include "Log.h"
#include "WinData.h"
#include "DrvMenus.h"
#include "kerndef.h"


/* external library hook */
extern void DrvUpdateCursor(BOOL inWindow);


/* Local Prototypes */
static DWORD DrvInitWindowSubsystem(UINT,BOOL);
static DWORD DrvCreateWindows(LPWINCREATESTRUCT);
static void DrvWindowSetText(WindowRef win, LPSTR title);
static DWORD DrvCapture(BOOL bSet, WindowRef win);
static DWORD DrvDestroyWindows(WindowRef win);
static DWORD DrvShowWindow(DWORD dwShow, WindowRef win);
static DWORD DrvStackingOrder(DWORD, WindowRef, WindowRef);
static void AdjustNCFrame(WindowRef macWin);
static void CalcNCFrameRect(WindowPtr macWin, Rect *rect);

/* Local event related prototypes */
static DWORD DoWindowDrag(WindowRef macWin, Point where);
static DWORD DoContentClick(EventRecord *event, WindowRef macWin);
static Boolean DoMouseDown(EventRecord *event);
static Boolean DoMouseUp(EventRecord *event);
static Boolean DoMouseMoved(EventRecord *event);
static Boolean DoContentEvent(EventRecord *event, WindowPtr macWin);
static Boolean DoUpdate(EventRecord *event);
static Boolean DoGrowWindow(WindowPtr win, EventRecord *event);
static Boolean DoZoomWindow(WindowPtr macWin, EventRecord *event, short fHit);
static void UpdateGrowIcon(WindowPtr macWin);
static long MyGrowWindow(WindowPtr theWindow, Point startPoint, Rect *sizeRect);
static int DecodeButton(short modifiers, short btnMotion, unsigned int *btnMessage);
static DWORD DoCloseWin(WindowPtr macWin, EventRecord *event);
static Boolean WindowConfigure(WindowPtr macWin, short winState);
static void ActivateWindow(WindowPtr macWin, Boolean activate);
static Boolean WindowFocusChange(void);
static void BackingStore(WindowPtr macWin, Boolean show);

static Boolean useSystemGrowProc = FALSE;


/* Misc. definitions */
#define kNoWindowStorage 0L
#define kFrontWindow ((WindowPtr) -1L)
#define MOVERESIZEWIN		0x0000			/* This is just to make things easier to read */
#define MOVEWIN					SWP_NOSIZE
#define RESIZEWIN				SWP_NOMOVE
#define GROWRECTSIZE	15
#define kExtremeNeg -32768
#define kExtremePos (32767 - 1) /* required to address an old region bug, see develop 20 Q&As */

/* Mac wKind's to use in window creation and identification */
#define CAPTIONWINDOWKIND 		zoomDocProc
#define NOCAPTIONWINDOWKIND 	dBoxProc		//plainDBox
#define CAPTIONWINFRAMEHEIGHT 19				/* This is for caption window */
#define NOCAPTIONWINFRAMEHEIGHT 1				/* This is for non-caption window */
#define FrameHeight(wKind)		((wKind == CAPTIONWINDOWKIND) ? CAPTIONWINFRAMEHEIGHT : NOCAPTIONWINFRAMEHEIGHT)

/* Gets the LPPRIVATEWINDOWSTRUCT from the mac win's refCon */
#define GETLPPWS(macWin) (LPPRIVATEWINDOWSTRUCT) ((WindowPeek)macWin)->refCon
#define GETPWS(macWin) (((GETLPPWS(macWin))->magic == WIN_MAGIC) ? GETLPPWS(macWin) : NULL)
#define ISGROWABLE(macWin) ((GETPWS(macWin))->bIsGrowable)
#define HASNCFRAME(macWin) ((GETPWS(macWin))->bHasNCFrame)

/* Limits for frame windows */
#define MINWINSIZEV 64
#define MINWINSIZEH 128
#define MAXWINSIZE 16384

/* Definitions of event messages and bits */
#define	BEC_BUTTONDOWN		0			/* Don't change, DecodeButton relies on these values */
#define	BEC_BUTTONUP				1
#define	BEC_BUTTONDBLCLK		2


PRIVATEDISPLAY *gDspl = NULL;

/********************************************************************
* PrivateWindowsHook
*	
********************************************************************/
DWORD PrivateWindowsHook(WORD wFunc, LPARAM dwParm1, LPARAM dwParm2, LPVOID lpStruct)
{
    switch (wFunc) {
	/* dwParam1 - compatibility mask */
	/* dwParm2 - init/exit flag */
	case DSUBSYSTEM_INIT:
	    return DrvInitWindowSubsystem((UINT)dwParm1, (BOOL)dwParm2);

	case DSUBSYSTEM_GETCAPS:
	    return (LRESULT)WSUB_CANDO_RESTACK;

	/* The lpStruct is a mac EventRecord pointer, it has already been checked and is here because of a window related event only. */
	/*  Returns true if event was posted to library and is available. */
	case DSUBSYSTEM_EVENTS: {
		EventRecord *event = lpStruct;
		/* First let see what we are dealing with */
		switch(event->what) {
		case mouseUp:
			return(DoMouseUp(event));
		case mouseDown:
			return (DoMouseDown(event)); 
		case APP_EVT:			/* Driver specific event. */
			switch (event->message) {
			case EVT_MOUSEMOVE:
				return DoMouseMoved(event);
			case EVT_FOCUSCHANGE:
				return WindowFocusChange();
			default:
				return(0L);
			}	
		case updateEvt:
			return DoUpdate(event);
		case activateEvt:
			return DoActivate((WindowPtr)event->message, event->modifiers & activeFlag, event);
		default:
			return(0L);
		}
	}

	/* dwParm1 - function mask */
	/* dwParm2 - pointer to WINCREATERETURNSTRUCT */
	/* lpStruct - pointer to WINCREATESTRUCT */
	case PWSH_CREATEWINDOW:
	    return DrvCreateWindows((LPWINCREATESTRUCT) lpStruct);

	/* lpStruct - pointer to WINDESTROYSTRUCT */
	case PWSH_DESTROYWINDOW:
	    return DrvDestroyWindows((WindowRef) lpStruct);

	/* dwParm1 - show/hide modifier */
	/* lpStruct - WindowRef */
	case PWSH_SHOWWINDOW:
	    return DrvShowWindow(dwParm1, (WindowRef)lpStruct);


	/* dwParm2 - pointer to RECT */
	/* lpStruct - WindowRef */
	case PWSH_MOVEFRAME:
	    LOGSTR((LF_PWH,"PWH: Move window %x to %d, %d\n",	lpStruct,	((LPRECT)dwParm2)->left,((LPRECT)dwParm2)->top));

		MoveWindow((WindowRef) lpStruct, ((LPRECT)dwParm2)->left, ((LPRECT)dwParm2)->top, FALSE);

		return (DWORD) 1;


	/* dwParm2 - pointer to RECT */
	/* lpStruct - WindowRef */
	case PWSH_MOVERESIZEFRAME:
	    LOGSTR((LF_PWH, "PWH: Move and resize window %x to %d, %d, %d, %d\n",
				lpStruct,
				((LPRECT)dwParm2)->left, ((LPRECT)dwParm2)->top,
				((LPRECT)dwParm2)->right, ((LPRECT)dwParm2)->bottom));

	    /* Do not tolerate windows with negative size */
	    if (((LPRECT)dwParm2)->right < 0)
			((LPRECT)dwParm2)->right = 0;
	    if (((LPRECT)dwParm2)->bottom < 0)
			((LPRECT)dwParm2)->bottom = 0;

		MoveWindow((WindowRef) lpStruct, ((LPRECT)dwParm2)->left, ((LPRECT)dwParm2)->top, FALSE);

		/* Adjust actual size if needed */
		if (HASNCFRAME((WindowRef) lpStruct))
			((LPRECT)dwParm2)->bottom += GROWRECTSIZE;

		SizeWindow((WindowRef) lpStruct, ((LPRECT)dwParm2)->right, ((LPRECT)dwParm2)->bottom, TRUE);

		AdjustNCFrame((WindowRef) lpStruct);

		return (DWORD) 1;


	/* dwParm2 - pointer to RECT */
	/* lpStruct - pointer to DRVWINDOWDATA */
	case PWSH_RESIZEFRAME:
	    LOGSTR((LF_PWH,	"PWH: Resize window %x to %d, %d\n", lpStruct,	((LPRECT)dwParm2)->right,((LPRECT)dwParm2)->bottom));

	    /* Do not tolerate windows with negative size */
	    if (((LPRECT)dwParm2)->right < 0)
			((LPRECT)dwParm2)->right = 0;
	    if (((LPRECT)dwParm2)->bottom < 0)
			((LPRECT)dwParm2)->bottom = 0;

		/* Adjust actual size if needed */
		if (HASNCFRAME((WindowRef) lpStruct))
			((LPRECT)dwParm2)->bottom += GROWRECTSIZE;

		SizeWindow((WindowRef) lpStruct, ((LPRECT)dwParm2)->right, ((LPRECT)dwParm2)->bottom, TRUE);

		AdjustNCFrame((WindowRef) lpStruct);

		return (DWORD) 1;


	/* lpStruct - WindowRef */
	case PWSH_SETCAPTURE:
		return DrvCapture(TRUE, (WindowRef) lpStruct);

	case PWSH_RELEASECAPTURE:
		return DrvCapture(FALSE, NULL);

	/* dwParm1 - hWndInsertAfter */
	/* dwParm2 - LPDRVWINDOWDATA of hWndInsertAfter */
	/* lpStruct - LPDRVWINDOWDATA of the window to restack */
	case PWSH_STACKINGORDER:
	    return DrvStackingOrder(dwParm1,
								(WindowRef)dwParm2,
								(WindowRef)lpStruct);

	/* dwParm2 - LPSTR to window text */
	/* lpStruct - pointer to DRVWINDOWDATA */
	case PWSH_SETTEXT:
	    if (lpStruct) {
			LOGSTR((LF_PWH, "PWH: Set window %x text to %s\n", lpStruct, (LPSTR)dwParm2));
			DrvWindowSetText((WindowRef)lpStruct, (LPSTR)dwParm2);
			return 1L;
		}
	    else
			return 0L;

			
	/* lpStruct - pointer to DRVWINDOWDATA */
	case PWSH_FLUSHEXPOSES:
	    return (DWORD) 0;

	default:
	    return (DWORD) 0;
    }
}


/********************************************************************
* DrvInitWindowSubsystem
*	
********************************************************************/
static DWORD DrvInitWindowSubsystem(UINT uiCompatibility, BOOL bInit)
{
#pragma unused(uiCompatibility)
GDHandle gdh;
OSErr err;
long appearance;

	if (bInit) {
		/* Create the display structure to hold useful information */
		gDspl = DrvMalloc(sizeof(PRIVATEDISPLAY));
		memset(gDspl, '\0', sizeof(PRIVATEDISPLAY));	/* Clear the structure */
		gDspl->qd = &qd;
		gDspl->doubleClickTime = GetDblTime();

		/* Determine the curren depth of the screen */
		gdh = GetMainDevice();
		gDspl->screenDepth = (**(**gdh).gdPMap).pixelSize;

		err = Gestalt('appr', &appearance);
		if(err == noErr && ((appearance & 0x03) == 0x01))
			useSystemGrowProc = TRUE;
	}
	else {
		DrvFree(gDspl);
		gDspl = NULL;
	}
	
    return 0L;
}


/********************************************************************
* DrvCreateWindows
*	
********************************************************************/
static DWORD DrvCreateWindows(LPWINCREATESTRUCT lpwcs)
{
WindowRef macWin;
Rect boundsRect;
Boolean visFlag = FALSE, goAwayFlag = FALSE;
Boolean ncFrameFlag = TRUE;			/* LATER: create a way to turn this on/off programatically */
char pTitle[255];
//short wKind = plainDBox;					/* Default kind (dBoxProc is the "fat" bordered version)*/
//short wKind = altDBoxProc;					/* Default kind */
short wKind = dBoxProc;					/* Default kind (dBoxProc is the "fat" bordered version)*/
LPPRIVATEWINDOWSTRUCT lppws;
	
	/* Place coordinates into mac Rect struct */
	/* Note that the rect is x, y, cx, and cy (topleft pt and width/height)*/
	SETMACRECTFROMXYWH(&boundsRect, lpwcs->rcFrame.left, lpwcs->rcFrame.top, lpwcs->rcFrame.right, lpwcs->rcFrame.bottom);

	/* Create our private structure that contains any info we need */
	lppws = DrvMalloc(sizeof(PRIVATEWINDOWSTRUCT));
	memset(lppws, '\0', sizeof(PRIVATEWINDOWSTRUCT));
	lppws->magic = WIN_MAGIC;								/* Store the magic key */
	lppws->hWnd = lpwcs->hWndFrame;
	lppws->dwStyle = lpwcs->dwStyle;					/* Save the style bits */
	
	/* If this is to be a captioned window, change the default settings */		
	if ((lpwcs->dwStyle & WS_CAPTION) == WS_CAPTION) {
		goAwayFlag = true;
		
		if (lpwcs->dwStyle & WS_THICKFRAME) {		
			lppws->bIsGrowable = TRUE;						/* It is resizable */
			wKind = zoomDocProc;								/* This has zoom box */
		}
		else if (lpwcs->dwStyle & WS_MINIMIZEBOX) {
			wKind = noGrowDocProc;							/* Standard with no zoom box */					
		}
		else {
			wKind = movableDBoxProc;						/* Movable modal dialog box */
		}

		/* Make window bounds adjustment for bottom "non-client frame" for resize box */
		if (lppws->bIsGrowable && ncFrameFlag) {
			lppws->bHasNCFrame = TRUE;		
			boundsRect.bottom += GROWRECTSIZE;		/* Grow the bounds to include NCFrameRect */
		}	
	}
	else if (lpwcs->dwExStyle & WS_EX_POPUPMENU)
		wKind = altDBoxProc;									/* 3D style plain box */
			
	/* Window title */
	if (HIWORD(lpwcs->lpszName)) {
		if (strcmp(lpwcs->lpszName, " ") != 0)		
			strncpy(pTitle, lpwcs->lpszName, 254);
		else
			pTitle[0] = 0;		/* Do not put a "space" as the title */
	}
	else
		pTitle[0] = 0;

	lppws->boundsRect = boundsRect;		/* Save the rect we are asking for */

	/* Transparent windows will never actually be seen, providing logical functions only. */
	if (lpwcs->dwExStyle & WS_EX_TRANSPARENT)
		lppws->bTransparent = TRUE;

	/* Only do backing store for plain windows now, this avoids tracking movements */
	if ((lpwcs->dwExStyle & WS_EX_SAVEBITS)  && ((lppws->dwStyle & WS_CAPTION) != WS_CAPTION)) {
		lppws->bBackStore = TRUE;
		if (wKind == plainDBox)
			InsetRect(&lppws->boundsRect, -1, -1);		/* plainDBox has a 1 pixel frame */
		else if (wKind == altDBoxProc) {
			InsetRect(&lppws->boundsRect, -1, -1);		/* altDBoxProc has a 1 pixel frame */
			lppws->boundsRect.right += 2;						/* altDBoxProc has a 2 pixel drop shadow */
			lppws->boundsRect.bottom += 2;					/* altDBoxProc has a 2 pixel drop shadow */
		}
		else if (wKind == dBoxProc)
			InsetRect(&lppws->boundsRect, -9, -9);		/* altDBoxProc has a 1 pixel frame */
		else
			lppws->bBackStore = FALSE;
	}
	/* Create the mac window */ 			
	macWin = NewCWindow(kNoWindowStorage, &boundsRect, C2PStr(pTitle),
								visFlag, wKind, kFrontWindow, 	goAwayFlag, 
								(long)lppws);

	/* Now set the non-client rectangle, avoiding a global to local conversion */
	AdjustNCFrame(macWin);

    return (DWORD)macWin;
}

/********************************************************************
*  AdjustNCFrame
*
*	Adjusts the NC Frame coordinates.
********************************************************************/
static void AdjustNCFrame(WindowRef macWin)
{
LPPRIVATEWINDOWSTRUCT lppws = GETPWS(macWin);

	if (lppws && lppws->bHasNCFrame) {
		lppws->NCFrameRect.top = macWin->portRect.bottom - GROWRECTSIZE;
		lppws->NCFrameRect.right = macWin->portRect.right - GROWRECTSIZE;
		lppws->NCFrameRect.left = macWin->portRect.left;
		lppws->NCFrameRect.bottom = macWin->portRect.bottom;
	}
	
}

/********************************************************************
*   CalcNCFrameRect
*
*	Calculates the area which we draw the grow icon and/or status area.
********************************************************************/
void CalcNCFrameRect(WindowPtr macWin, Rect *rect)
{

	memcpy(rect, &(macWin->portRect), sizeof(Rect));
	rect->top = rect->bottom - GROWRECTSIZE;
	if (HASNCFRAME(macWin))
		rect->left = macWin->portRect.left;
	else
		rect->left = rect->right - GROWRECTSIZE;
 }
 
/********************************************************************
*  DrvWindowSetText
*
*	Set the title text of a window.
********************************************************************/
static void DrvWindowSetText(WindowRef macWin, LPSTR title)
{
char pTitle[255];

	if(!macWin)
		return;

	/* Make a copy so we can convert into a pascal string */
	strncpy(pTitle, title, 254);
		
	SetWTitle(macWin, c2pstr(pTitle));

}


/********************************************************************
* DrvDestroyWindows
*	
********************************************************************/
static DWORD DrvDestroyWindows(WindowRef macWin)
{
LPPRIVATEWINDOWSTRUCT lppws;

    LOGSTR((LF_PWH,"PWH: Destroy window %x\n",macWin));

	/* Hide the window first (if it has not been done so already) */
	if (((WindowPeek)macWin)->visible)
		DrvShowWindow(DSW_HIDE, macWin);

	/* Remove focus if we had it */
	if (gDspl->focusWin == macWin)
		gDspl->focusWin = NULL;				

	/* Get and free our private window structure */
	lppws = GETPWS(macWin);	
	DrvFree(lppws);
	
 	DisposeWindow(macWin);
 	
    return 1L;
}


/********************************************************************
* ValidateGlobalRect
*	
*	Validate the rectange in all the windows, used primarily for backing store.
********************************************************************/
static void ValidateGlobalRect(Rect globalRect)
{
WindowPtr macWin;
Rect localRect;
GrafPtr savePort;

	/* Start with the topmost window */
	macWin = FrontWindow();
	GetPort(&savePort);
	
	/* Loop through our window list, validating the rectange in each port. */
	while (macWin) {
		/* Set to the window's port, then localize the rect and validate it. */
		SetPort(macWin);
		localRect = globalRect;
		GlobalToLocal(&topLeft(localRect));
		GlobalToLocal(&botRight(localRect));
		ValidRect(&localRect);
		/* Get the next window to validate */
		macWin = (WindowPtr)((WindowPeek)macWin)->nextWindow;
	}
	
	SetPort(savePort);
}

/********************************************************************
* BackingStore
*	
*	Implement a backing store function on a given mac window.
********************************************************************/
static void BackingStore(WindowPtr macWin, Boolean show)
{
LPPRIVATEWINDOWSTRUCT lppws;
GrafPtr savePort;
CGrafPtr screenPort;
Rect srcRect, destRect;
short widthBytes, depth;

	if ((lppws = GETPWS(macWin)) == NULL)
		return;

	/* See if we are to provide backing store functionality */
	if (!lppws->bBackStore)
		return;

	/* Create a new port to copy from/to, it will be the same as the window manager's */
	screenPort = DrvMalloc(sizeof(CGrafPort));
	OpenCPort(screenPort);

	/* Setup our ports */
	GetPort(&savePort);
	SetPort((GrafPtr)screenPort);
	
	if (show && !lppws->backStorePixmap) {
		srcRect = lppws->boundsRect;
		depth = (**screenPort->portPixMap).pixelSize;
		/* make sure rowbytes is a multiple of 4 */
		widthBytes = (((RECTWIDTH(&srcRect) * depth) + 31) / 32) * 4;		

		lppws->backStorePixmap =  DrvCreatePixmap(NULL, RECTWIDTH(&srcRect), RECTHEIGHT(&srcRect), widthBytes, depth, TRUE);

		/* Copy the bits from the screen into our bitmap */
		destRect = (**lppws->backStorePixmap).bounds;
		CopyBits(&qd.screenBits, (BitMapPtr)*lppws->backStorePixmap, &srcRect, &destRect, srcCopy, nil);

	}
	else if (!show && lppws->backStorePixmap) {
		/* Since we are using a temporary CGrafPort, go ahead and set the clip without saving */
		srcRect = (**lppws->backStorePixmap).bounds;
		destRect = lppws->boundsRect;

		/* Copy the store pixmap to the screen */
		ClipRect(&destRect);
		CopyBits((BitMapPtr)*lppws->backStorePixmap, &qd.screenBits, &srcRect, &destRect, srcCopy, nil);

		/* Destroy the pixmap, the call checks for a valid pixmap */
		DrvDestroyPixmap(lppws->backStorePixmap, TRUE);
		lppws->backStorePixmap = NULL;

		/* Validate all of our windows that have been "restored" */
		ValidateGlobalRect(destRect);	
	}

    /* now put things back the way we found them */
	SetPort(savePort);
	CloseCPort(screenPort);
	DrvFree(screenPort);
}


/********************************************************************
* DrvShowWindow
*	
********************************************************************/
static DWORD DrvShowWindow(DWORD dwShow, WindowRef macWin)
{
Rect bounds;
short mbHeight, frameTop, mbAdjust=0;
LPPRIVATEWINDOWSTRUCT lppws;

	LOGSTR((LF_PWH,"PWH: Show window %x , show/hide = %x\n", macWin, dwShow));

	/* Get the window struct and verify it is one of our windows */
	if ((lppws = GETPWS(macWin)) == NULL)
		return FALSE;

	if (macWin) {
		if ((dwShow == DSW_SHOW)) {
			/* Transparent windows are never actually visible */



			if (lppws->bTransparent == TRUE)
				return TRUE;
				
			BackingStore(macWin, TRUE);

			ShowHide(macWin, TRUE);						/* Will not activate window */
			
			//TEMPORARY
			ActivateWindow(macWin, TRUE);			/* LATER this should probably not be here */

			/* Check to see that the window will not be place under the Mac menu bar */
			mbHeight = GetMBarHeight();
			/* Calculate the frame top for now.  The struct and content regions are not */
			/*  valid until the window is shown and I do not know another way to calc the */
			/*  frame height (yet!). */
			frameTop = (**(((WindowPeek)macWin)->strucRgn)).rgnBBox.top;	
			if (frameTop <= mbHeight) {
				mbAdjust += mbHeight - frameTop;		/* Offset the bounds slightly */
				bounds = (**(((WindowPeek)macWin)->contRgn)).rgnBBox;
				OffsetRect(&bounds, 0, mbAdjust);			
				MoveWindow(macWin, bounds.left, bounds.top, FALSE);
				WindowConfigure(macWin, MOVEWIN);
			}
		}
		else {
			ShowHide(macWin, FALSE);					/* Will not activate window */

			PostEvent(APP_EVT, EVT_FOCUSCHANGE);
			BackingStore(macWin, FALSE);
		}
	}
	
    return 1L;
}



/********************************************************************
* DrvCapture
*	
********************************************************************/
DWORD DrvCapture(BOOL bSet, WindowRef macWin)
{
	if (bSet)
		gDspl->captureWin = macWin;
	else
		gDspl->captureWin = NULL;
			
	return (DWORD) 1;
}


/********************************************************************
*	Selects a window and notifies the library of a focus change.
********************************************************************/
static void ActivateWindow(WindowPtr macWin, Boolean activate)
{
LPPRIVATEWINDOWSTRUCT lppws;

	if (!macWin)
		return;

	if ((lppws = GETPWS(macWin)) == NULL)
		return;
	
	if (!activate)										/* Deactivate window */
		HiliteWindow(macWin, FALSE);
	else if (lppws && ((lppws->dwStyle & WS_CAPTION) == WS_CAPTION))
		HiliteWindow(macWin, TRUE);		/* Activate (draw racing stripes) window only if it has a caption */
															/* That way, pop up windows do not steal the activation from the parent window. */

	/* Change the focus on the windows */
	PostEvent(APP_EVT, EVT_FOCUSCHANGE);

}


/********************************************************************
* WindowFocusChange
*	
********************************************************************/
static Boolean WindowFocusChange(void)
{
LPPRIVATEWINDOWSTRUCT lppws;
WindowPtr macWin = FrontWindow();

	/* Notify library of focus leaving a window */
	if (gDspl->focusWin)
		if ((lppws = GETPWS(gDspl->focusWin)) != NULL)
			LibCallback(TWINLIBCALLBACK_FOCUS, lppws->hWnd, IFC_DRIVERFOCUS, (LPVOID) FALSE);

	/* Notify library of focus entering a window */
	if (macWin && (lppws = GETPWS(macWin)) != NULL)
		LibCallback(TWINLIBCALLBACK_FOCUS, lppws->hWnd, IFC_DRIVERFOCUS, (LPVOID) TRUE);

	gDspl->focusWin = macWin;		/* New window with focus */
	
	return(TRUE);							/* Allow main event to return for library to handle */
}


/********************************************************************
* DrvStackingOrder
*	
********************************************************************/
static DWORD DrvStackingOrder(DWORD hWndInsertAfter, WindowRef winAfter,
			WindowRef macWin)
{

	switch(hWndInsertAfter) {
	case HWND_TOP:
	case HWND_TOPMOST:
		BringToFront(macWin);
		break;

	case HWND_BOTTOM:
	case HWND_NOTOPMOST:
		SendBehind(macWin, NULL);
		break;
		
	default:
	    /*  this means a real hWndInsertAfter */
	    if (winAfter && macWin)
			SendBehind(winAfter, macWin);
#ifdef LATER
		/* Must manually expose a portion of the window */
		wPeek = (WindowPeek)macWin;
		PaintOne(wPeek, wPeek->strucRgn);
		CalcVis(wPeek);
#endif		 
		break;
	}
	
    return 1L;
}


/********************************************************************
* DoWindowDrag
*
* Drag a window tracking the users cursor.
********************************************************************/
static DWORD DoWindowDrag(WindowRef macWin, Point where)
{
WindowRef frontMacWin = FrontWindow();
Boolean okToDrag = TRUE;
LPPRIVATEWINDOWSTRUCT lppws;
WINDOWPOS wp;
RgnHandle grayRgn;

	/* Get the HWND from the mac's refcon */
	if ((lppws = GETPWS(macWin)) == NULL)
		return(FALSE);
		
	wp.hwnd = lppws->hWnd;	
	wp.hwndInsertAfter = HWND_TOP;

	/* Set the state flags */
	wp.flags = SWP_DRIVER | SWP_NOSIZE | SWP_NOMOVE;

	/* First check with the library to see if we are allowed to change the z order */
	if (macWin != frontMacWin)
		okToDrag = LibCallback(TWINLIBCALLBACK_CONFIGURE, (LPARAM)wp.hwnd,	0, (LPVOID)&wp);

	if (!okToDrag) {
		SysBeep(1);
		return(FALSE);
	}
	
	/* Library has given us permission to make the change, so do it */	
//	DrvStackingOrder(HWND_TOPMOST, frontMacWin, macWin);
	ActivateWindow(frontMacWin, FALSE);		/* Deselect old */
	ActivateWindow(macWin, TRUE);				/* Select it before dragging it */
	
	/* Since we selected it first, the user may have had time to release. */
	/* In that case the drag will not flash the gray drag box. (good)*/
	grayRgn = GetGrayRgn();
	if (StillDown())
		DragWindow(macWin, where, &((**grayRgn).rgnBBox));
		
	return(WindowConfigure(macWin, MOVEWIN));
}


/********************************************************************
* DoContentClick
*
* Handle the mouse down event in the content region of the window.
********************************************************************/
static DWORD DoContentClick(EventRecord *event, WindowRef macWin)
{
LPPRIVATEWINDOWSTRUCT lppws;
WINDOWPOS wp;
Boolean okToRestack = TRUE;
WindowRef frontMacWin = FrontWindow();

	if (macWin == frontMacWin) {
			/* No window management necessary, let the library have it. */
	    return(DoContentEvent(event, macWin));
	} 
	else {                
		/* mouse down occured in a window other than the front window */
		/* Get the HWND from the mac's refcon */
		if ((lppws = GETPWS(macWin)) == NULL)
			return(FALSE);
		wp.hwnd = lppws->hWnd;	
		wp.hwndInsertAfter = HWND_TOP;

		/* Set the state flags */
		wp.flags = SWP_DRIVER | SWP_NOSIZE | SWP_NOMOVE;
		
		/* Make the callback to the library */
		okToRestack = LibCallback(TWINLIBCALLBACK_CONFIGURE, (LPARAM)wp.hwnd,	0, (LPVOID)&wp);

		if (!okToRestack) {
			SysBeep(1);
			return(FALSE);
		}
	
		/* Library has given us permission to make the change, so do it */	
//		DrvStackingOrder(HWND_TOPMOST, frontMacWin, macWin);
		ActivateWindow(frontMacWin, FALSE);		/* Deselect old */
		ActivateWindow(macWin, TRUE);				/* Select it before dragging it */
	}

	return(TRUE);
}


/********************************************************************
*   DoMouseUp
*
*	There isn't much that handles mouse up's, except the library.
********************************************************************/
static Boolean DoMouseUp(EventRecord *event)
{
short fHit;
WindowPtr macWin;

  	/* If someone has capture, send event to them now and do not handle!! */
	if (gDspl->captureWin)
		return(DoContentEvent(event, gDspl->captureWin));

  	/* No capture, see where the hit was */
	fHit = FindWindow(event->where, &macWin);
	switch (fHit) {
	case inContent:								/* Handle content and control clicks here */
		if (macWin == FrontWindow())
		    return(DoContentEvent(event, macWin));
		break;
		
	default:
		break;
	}
	
	/* No events posted to library */
	return(false);
}



/********************************************************************
*   DoMouseDown
*
*	Perform any window management and/or send event to library.
********************************************************************/
static Boolean DoMouseDown(EventRecord *event)
{
short fHit;
WindowPtr macWin;
  
  	/* If someone has capture, send event to them now and do not handle!! */
	if (gDspl->captureWin)
		return(DoContentEvent(event, gDspl->captureWin));

  	/* No capture, see where the hit was */
	fHit = FindWindow(event->where, &macWin);
	switch (fHit) {
	case inDesk:                          /* if they hit in desk, then the process manager */
		break;								/* will switch us out, we don't need to do anything */

	case inMenuBar: {
		long msel = MenuSelect(event->where);				/* Popup and track the menu */
		DrvMenuDispatch(HiWord(msel), LoWord(msel));	/* Handle the menu selection */
		HiliteMenu(0);														/* Remove menu title hiliting */
		return(TRUE);
	}
	case inSysWindow:
		SystemClick(event, macWin);		/* pass to the system */
		break;

	case inContent:								/* Handle content and control clicks here */
		return DoContentClick(event, macWin);

	case inDrag:
		return DoWindowDrag(macWin, event->where);

	case inGrow:						/* Call GrowWindow here if you have a grow box */
		if (ISGROWABLE(macWin))
			return(DoGrowWindow(macWin, event));
		break;

	case inGoAway:				/* Click in Close box */
		if (TrackGoAway(macWin, event->where))
			return DoCloseWin(macWin, event);
		break;

	case inZoomIn:
	case inZoomOut:
		return DoZoomWindow(macWin, event, fHit);
	
	default:
		break;
	}

	/* We have handled the event, do not send upstairs */
	return(FALSE);	
}


/********************************************************************
*   WindowConfigure
*
*	Handles movement and resize library notification of the window.
********************************************************************/
static Boolean WindowConfigure(WindowPtr macWin, short winState)
{
WINDOWPOS wp;
Rect bounds;
LPPRIVATEWINDOWSTRUCT lppws;

	/* Get the HWND from the mac's refcon */
	if ((lppws = GETPWS(macWin)) == NULL)
		return(FALSE);
			
	wp.hwnd = lppws->hWnd;	
	wp.hwndInsertAfter = (HWND)0;

	/* Get the current bounds (which may have been resized/moved) */	
	bounds = (**(((WindowPeek)macWin)->contRgn)).rgnBBox;
	/* Adjust actual size if needed */
	if (HASNCFRAME(macWin))
		bounds.bottom -= GROWRECTSIZE;

	wp.x = bounds.left;
	wp.y = bounds.top;
	wp.cx = bounds.right - bounds.left;
	wp.cy = bounds.bottom - bounds.top;

	/* Set the state flags */
	wp.flags = winState | SWP_DRIVER | SWP_NOACTIVATE | SWP_NOZORDER;
		
	/* Make the callback to the library */
	LibCallback(TWINLIBCALLBACK_CONFIGURE,(LPARAM)wp.hwnd,	0, (LPVOID)&wp);

	return(TRUE);

}

/********************************************************************
*   CloseFrontWindow
*
*	Closes the front most window.
********************************************************************/
int CloseFrontWindow(void)
{
WindowPtr macWin;
EventRecord event;

	event.when = TickCount();		/* Latch current time for when we issue a close */
	macWin = FrontWindow();		/* Get the frontmost window */
	
	if (macWin)
		return DoCloseWin(macWin, &event);	/* Handle it properly */
	else
		return (FALSE);
}

/********************************************************************
*   DoCloseWin
*
*	Handles the closing of the mac window by posting an event to the library.
********************************************************************/
static DWORD DoCloseWin(WindowPtr macWin, EventRecord *event)
{
MSG msg;
LPPRIVATEWINDOWSTRUCT lppws;

	/* The HWND was stuffed into the mac wins RefCon*/
	if ((lppws = GETPWS(macWin)) == NULL)
		return(FALSE);

    msg.hwnd		= lppws->hWnd;
    msg.time    	= event->when;
	msg.message	= WM_SYSCOMMAND;
	msg.wParam	= SC_CLOSE;
	msg.lParam	= 0;

    return LibCallback(TWINLIBCALLBACK_POSTMESSAGE, 0, 0, &msg);	/* Post close to active window. */
}


/********************************************************************
*   DoMouseMoved
*
*	Any kind of mouse movement is handled here.  If it does not involve the client 
*  area, then return FALSE.
********************************************************************/
static Boolean DoMouseMoved(EventRecord *event)
{
short fHit, inWindow = true;
WindowPtr macWin;
Point localPt;
GrafPtr oldPort;

  	/* If someone has capture, send event to them now and do not handle!! */
	if (gDspl->captureWin)
		return(DoContentEvent(event, gDspl->captureWin));
  
  	/* No capture, see where the mouse was */
	fHit = FindWindow(event->where, &macWin);
	switch (fHit) {
	case inContent:								/* Handle content and control clicks here */
		/* Find window does not mask out other apps windows */
		/*  while in the background (inactive window) */
		if (gInBackground)	{					
			GetPort(&oldPort);
			SetPort(macWin);
			localPt = event->where;
			GlobalToLocal(&localPt);		/* visRgn is local, so map mouse location */
			if(!PtInRgn(localPt, macWin->visRgn))
				inWindow = false;
			SetPort(oldPort);
		}
		
		DrvUpdateCursor(inWindow);	/* Update the cursor */
		if (inWindow)
			return(DoContentEvent(event, macWin));
		break;

	default:						/* Don't care about non-window tracking */
		DrvUpdateCursor(FALSE);
		break;
	}

	/* We have handled the event, do not send upstairs */
	return(false);		
}


/********************************************************************
*   DecodeButton
*
*	Decode modifier keys to check for alternate button press.
*	The btnMessage will be set the the windows message ie WM_LBUTTONDOWN.
*  btnMotion is one of BEC_BUTTONUP, BEC_BUTTONDOWN, BEC_BUTTONDBLCLK.
********************************************************************/
static int DecodeButton(short modifiers, short btnMotion, unsigned int *btnMessage)
{

	/* First determine which button was hit (using modifiers for additional btns ) */
	if (modifiers & cmdKey) {
		*btnMessage = WM_RBUTTONDOWN + btnMotion;
		return(MK_RBUTTON);
		}
	else if (modifiers & optionKey) {
		*btnMessage = WM_MBUTTONDOWN + btnMotion;
		return(MK_MBUTTON);
		}
	else {
		*btnMessage = WM_LBUTTONDOWN + btnMotion;
		return(MK_LBUTTON);
		}

}



/********************************************************************
*   DoContentEvent
*
*	The click was in the content region of the window, deal with it.
********************************************************************/
static Boolean DoContentEvent(EventRecord *event, WindowPtr macWin)
{
MSG msg;
int btnMessage = BEC_BUTTONUP;		/* Must set for fall thru case */
Point locPt;
Rect statusRect;
LPPRIVATEWINDOWSTRUCT lppws;

	/* The window info is stuffed into the mac windows RefCon*/
	if ((lppws = GETPWS(macWin)) == NULL)
		return(FALSE);
	
	SetPort(macWin);

	/* We put a "status" rectange for the grow box */
	/* Do a quick check to make sure that the mouse is in the HWND's area */
	locPt = event->where;
	GlobalToLocal(&locPt);		/* convert */
	if (HASNCFRAME(macWin)) {
		statusRect = macWin->portRect;
		statusRect.top = macWin->portRect.bottom - GROWRECTSIZE;
		if (PtInRect(locPt, &statusRect))
			return(FALSE);
	}
	
	switch(event->what) {
	case mouseDown:
		/* Valid dbl click is within time and small amount of movement */
		if (((event->when - gDspl->lastClickTime) < gDspl->doubleClickTime) &&
				( abs(event->where.h - gDspl->lastClickPt.h) < 5 ) &&
				( abs(event->where.v - gDspl->lastClickPt.v) < 5 ) )  {
			btnMessage = BEC_BUTTONDBLCLK;
		}
		else
			btnMessage = BEC_BUTTONDOWN;

		/* Latch the current when and where for future dbl click verification */
		gDspl->lastClickTime = event->when;
		gDspl->lastClickPt = event->where;

	    /* fall thru into ButtonRelease case */
		
	case mouseUp:		/* nBtnMessage has been setup for this case if not fall thru */
		/* Pack parameters for sending making callback to library */
	    msg.hwnd		= lppws->hWnd;
	    msg.time    	= event->when;
	    msg.pt.x    	= event->where.h;
	    msg.pt.y    	= event->where.v;
	    msg.lParam  = MAKELPARAM(locPt.h, locPt.v);

		/* Check modifiers for other buttons */
		msg.wParam = DecodeButton(event->modifiers, btnMessage, &msg.message);

		/* Forward the button event to the library (call up) */
	    return LibCallback(TWINLIBCALLBACK_BUTTON, 0, 0, &msg);
	    
	case APP_EVT:			/* Mouse moved event */
		/* Pack parameters for sending via callback to library */
	    msg.hwnd		= lppws->hWnd;
	    msg.time    	= event->when;
	    msg.pt.x    	= event->where.h;
	    msg.pt.y    	= event->where.v;
	    msg.lParam  = MAKELPARAM(locPt.h, locPt.v);

		if (event->modifiers & btnState) {
			btnMessage = BEC_BUTTONDOWN;
			msg.wParam = DecodeButton(event->modifiers, btnMessage, &msg.message);		/* Check modifiers for other buttons */
		}
		else
			msg.wParam = 0;
			
	    msg.message = WM_MOUSEMOVE;		/* Override the button message */
	
		/* Forward the button event to the library (call up) */
	    return LibCallback(TWINLIBCALLBACK_BUTTON, 0, 0, (LPVOID)&msg);

	default:
		break;
	}

	return(false);
}



/********************************************************************
*   DoUpdate
*
********************************************************************/
static Boolean DoUpdate(EventRecord *event)
{
WindowPtr	updateWindow;
WindowPeek wPeek;
GrafPtr		savePort;
RgnHandle rgnExposed;
Point pt;
LPPRIVATEWINDOWSTRUCT lppws;

	GetPort(&savePort);						/* save current port */
	updateWindow=(WindowPtr)event->message;	/* get windowPtr from event msg */
	wPeek = (WindowPeek)updateWindow;
	
	SetPort(updateWindow);

	/* Construct the exposed region before calling BeginUpdate */	
	rgnExposed = NewRgn();
	CopyRgn(wPeek->updateRgn, rgnExposed);

	/* Let system do clipping while we redraw any window management related stuff */
	BeginUpdate(updateWindow);
	
	UpdateGrowIcon(updateWindow);		/* Update last, just incase */	
	
	EndUpdate(updateWindow);

	/* The library will provide the clipping now that we have the update region */
	/* The HWND was stuffed into the mac wins RefCon*/
	lppws = GETPWS(updateWindow);

	if (lppws && lppws->hWnd) {	
		/* Localize the region to our window */
		pt.h = 0;		pt.v=0;
		LocalToGlobal(&pt);
		OffsetRgn(rgnExposed, -pt.h, -pt.v);	
 
	    LibCallback(TWINLIBCALLBACK_EXPOSE, (LPARAM)lppws->hWnd,
				COMPLEXREGION, (LPVOID)rgnExposed);
	}

	DisposeRgn(rgnExposed);		/* The library will have made a copy of the rgn */

	SetPort(savePort);

	return(TRUE);
}



/********************************************************************
*   DoActivate
*
********************************************************************/
Boolean DoActivate(WindowPtr win, Boolean activate, EventRecord *event)
{
#pragma unused(event)

	/* Make sure it is one of "our" windows (not the console) */
	if (GETPWS(win) == NULL)
		return(FALSE);
	
	/* This will hide/show the grow icon depending on if the window is front most or not */	
	UpdateGrowIcon(win);

	if (activate) {

	}
	else {
		
	}
	return(FALSE);
}


/********************************************************************
*   DoGrowWindow
*********************************************************************/
static Boolean DoGrowWindow(WindowPtr macWin, EventRecord *event)
{
WindowPtr oldPort;
Rect limitRect, oldGrowRect;
long growSize;	
LPPRIVATEWINDOWSTRUCT lppws = GETPWS(macWin);

	GetPort(&oldPort);
	SetPort(macWin);

	/* If we have a grow rect, then erase it when resized */
	CalcNCFrameRect(macWin, &oldGrowRect);

	/* Setup the window grow limit rectangle */
	SetRect(&limitRect, MINWINSIZEH, MINWINSIZEV, qd.screenBits.bounds.right, qd.screenBits.bounds.bottom);

	if (useSystemGrowProc)
		growSize = GrowWindow(macWin, event->where, &limitRect);
	else
		growSize = MyGrowWindow(macWin, event->where, &limitRect);
	
   /* now size the window for the returned rect */
	if (growSize) {
		SizeWindow(macWin, LoWord(growSize), HiWord(growSize), true);
		AdjustNCFrame(macWin);
		ClipRect(&macWin->portRect);	
		EraseRect(&oldGrowRect);
		InvalRect(&oldGrowRect);			/* Allow refresh of what might now be put there */
		UpdateGrowIcon(macWin);					/* Update the grow icon now */	
		if (lppws && lppws->bHasNCFrame)
			ValidRect(&lppws->NCFrameRect);
			
		/* Notify the library of the change */
		return(WindowConfigure(macWin, RESIZEWIN));
	}
	
	SetPort(oldPort);
	return(FALSE);
}


/********************************************************************
*   DoZoomWindow
*
*	Handle the mouse event within the zoom box of a window.
*********************************************************************/
static Boolean DoZoomWindow(WindowPtr macWin, EventRecord *event, fHit)
{
Rect oldGrowRect, oldFrameRect, newFrameRect;
LPPRIVATEWINDOWSTRUCT lppws = GETPWS(macWin);

	if (TrackBox(macWin, event->where, fHit)) {
		SetPort(macWin);								/* Must set the port before zooming */

		/* If we have a grow rect, then get it before we resized */
		CalcNCFrameRect(macWin, &oldGrowRect);
        /* Get the original frame rect so we can see how much it moved (if any). */
		oldFrameRect = (**(((WindowPeek)macWin)->contRgn)).rgnBBox;
        
		ZoomWindow(macWin, fHit, true);		/* Adjust the window, this may move AND resize the window */
		AdjustNCFrame(macWin);					/* Adjust the frame information */

		/* Now adjust the old grow rect for the window movement */
		newFrameRect = (**(((WindowPeek)macWin)->contRgn)).rgnBBox;
		OffsetRect(&oldGrowRect, oldFrameRect.left - newFrameRect.left, oldFrameRect.top - newFrameRect.top);
		/* Erase the old portion of the grow rectangle */
		ClipRect(&macWin->portRect);	
		RGBBackColor(&whtRgbColor);			/* Make sure we have a white background (we don't cleanup when using the DC's) */
		EraseRect(&oldGrowRect);				/* Remove the old grow rect */

		InvalRect(&macWin->portRect);		/* Invalidate the entire window */

		UpdateGrowIcon(macWin);					/* Update the grow icon now */	
		if (lppws && lppws->bHasNCFrame)
			ValidRect(&lppws->NCFrameRect);	/* Re-validate the grow rect, we updated it */

		/* Notify the library of the change */
		return(WindowConfigure(macWin, MOVERESIZEWIN));
	}

	return(FALSE);										/* Nothing happened */
}


/********************************************************************
*   UpdateGrowIcon
*
********************************************************************/
static void UpdateGrowIcon(WindowPtr macWin)
{
Rect growRect;
RgnHandle tempRgn;
RGBColor rgbColor;
LPPRIVATEWINDOWSTRUCT lppws;
GrafPtr savePort;
char text[] = "Willows Software";
	
	if (!ISGROWABLE(macWin))
		return;

	GetPort(&savePort);
	SetPort(macWin);

	lppws = GETPWS(macWin);
	if (lppws && lppws->bHasNCFrame) {
		/* Fill the area and draw the "Willows Beta" text into this area */
	    ClipRect(&lppws->NCFrameRect);	

		/* Now draw the "Willows Beta" text in a slightly darker grey */
		PenMode(srcCopy);
		PenPat(&qd.black);
		TextFont(applFont);	TextSize(9);	TextFace(italic);
		/* TextBox() calls EraseRect(), so we set the bg color accordingly. */
		rgbColor.red=rgbColor.blue=rgbColor.green=61166;	/* The grey color */
		RGBBackColor(&rgbColor);		
		rgbColor.red=rgbColor.blue=rgbColor.green=43690;	/* Slightly darker grey */
		RGBForeColor(&rgbColor);
		growRect = lppws->NCFrameRect;
		growRect.top +=1;
		growRect.bottom -=1;
		growRect.right -=1;
		TextBox(text, strlen(text), &growRect, teFlushLeft);

		/* Draw the highlights */
		PenSize(1, 1);
		/* First draw the gray lines */
		MoveTo(growRect.left, growRect.bottom);
		LineTo(growRect.right, growRect.bottom);
		LineTo(growRect.right, growRect.top);
		/* Now draw the white lines */
		RGBForeColor(&whtRgbColor);	
		LineTo(growRect.left, growRect.top);
		LineTo(growRect.left, growRect.bottom);

		/* Draw the border line */
		RGBForeColor(&blkRgbColor);	
		MoveTo(lppws->NCFrameRect.left, lppws->NCFrameRect.top);
		LineTo(lppws->NCFrameRect.right, lppws->NCFrameRect.top);

		
	}
	
	/* Setup the rectange where the icon is */
    growRect = macWin->portRect;
    growRect.top = growRect.bottom - 15;
    growRect.left = growRect.right - 15;

	/* Create a new region to clip the icon to */
    tempRgn = NewRgn();
    ClipRect(&growRect);	
    DrawGrowIcon(macWin);		/* Perform the drawing, minus the scroll bar lines (clipped) */
    
    /* Now try to set the clip region of this kind of window */
    RectRgn(macWin->clipRgn, &macWin->portRect);
	if (HASNCFRAME(macWin))
	    growRect.left = macWin->portRect.left;	/* Change the rect to include the "status area" */

    RectRgn(tempRgn, &growRect);					/* Create the growRect rgn */
    DiffRgn(macWin->clipRgn, tempRgn, macWin->clipRgn);
    
    DisposeRgn(tempRgn);
    
	SetPort(savePort);
}



/********************************************************************
*   MyGrowWindow
*
*	Alternate version of the toolbox call GrowWindow.
*  This version will draw only the outside of the window, without the scroll regions.
*********************************************************************/
static long MyGrowWindow(WindowPtr theWindow, Point startPoint, Rect *sizeRect)
{
WindowPtr savePort, WMPort;
PenState oldPen;
short newH, newW, frameH, frameW, offsetX, offsetY;
long growSize;
Point endPoint;
Rect draggingRect, oldRect;
Rect wideOpen =  {kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos};
RgnHandle oldClip = NewRgn();

    GetPort(&savePort);
    GetWMgrPort(&WMPort);
    SetPort(WMPort);									/* Set to the Window Manager port */
    GetPenState(&oldPen);							/* Save WMgrs pen, we will change it */
    GetClip(oldClip);									/* Save the current clip region */
    ClipRect(&wideOpen);							/* Set our wide-open clip */

	/* The gray window drag will be done using the frame bounds */
	draggingRect = (**((WindowPeek)theWindow)->strucRgn).rgnBBox;		/* frame bounds */
	oldRect = (**((WindowPeek)theWindow)->contRgn).rgnBBox;				/* contents bounds */

	/* Since the returned H&W needs to be in content size, */
	/*  calculate the frame H&W for adjustment later */
	frameH = (draggingRect.bottom - draggingRect.top) - (oldRect.bottom - oldRect.top);
	frameW = (draggingRect.right - draggingRect.left) - (oldRect.right - oldRect.left);
   
    /* set up */
    oldRect = draggingRect;
    PenMode(srcXor);                               /* So we can rubberband */
    PenPat(&(qd.gray));

	/* Draw the initial gray frame and grow box */
    FrameRect(&draggingRect);
	MoveTo(draggingRect.right, draggingRect.bottom - GROWRECTSIZE);
	LineTo(draggingRect.right - GROWRECTSIZE, draggingRect.bottom - GROWRECTSIZE);
	LineTo(draggingRect.right - GROWRECTSIZE, draggingRect.bottom);
	
	/* Calculate the offset from the corner to the starting mouse point */
	/* This is to keep the outer frame from jumping to the current mouse point */
    offsetY = draggingRect.bottom - startPoint.v;
    offsetX = draggingRect.right - startPoint.h;

	/* Keep tracking as long as the user keeps the mouse down */
    while (StillDown()) {
        GetMouse(&endPoint);                                /* Current mouse position in local */

		draggingRect.bottom = endPoint.v + offsetY;
		draggingRect.right = endPoint.h + offsetX;

		/* Limit the minimum and maximum height of the grow window */
		newH = draggingRect.bottom - draggingRect.top;
		if (newH < sizeRect->top)
			draggingRect.bottom = draggingRect.top + sizeRect->top;
		else if (newH > sizeRect->bottom)
			draggingRect.bottom = draggingRect.top + sizeRect->bottom;

		/* Limit the minimum and maximum width of the grow window */
		newW = draggingRect.right - draggingRect.left;
		if (newW < sizeRect->left)
			draggingRect.right = draggingRect.left + sizeRect->left;
		else if (newW > sizeRect->right)
			draggingRect.right = draggingRect.left + sizeRect->right;

		/* Redraw the rect only if the mouse moved (anti-flicker)*/
		if(!EqualRect(&draggingRect, &oldRect)) {		
			FrameRect(&oldRect);								/* Erase the old rect and grow box */
			MoveTo(oldRect.right, oldRect.bottom - GROWRECTSIZE);
			LineTo(oldRect.right - GROWRECTSIZE, oldRect.bottom - GROWRECTSIZE);
			LineTo(oldRect.right - GROWRECTSIZE, oldRect.bottom);
			
			FrameRect(&draggingRect);               		/* draw the new rect and grow box*/
			MoveTo(draggingRect.right, draggingRect.bottom - GROWRECTSIZE);
			LineTo(draggingRect.right - GROWRECTSIZE, draggingRect.bottom - GROWRECTSIZE);
			LineTo(draggingRect.right - GROWRECTSIZE, draggingRect.bottom);
			oldRect = draggingRect;
		}
        
	}    
    FrameRect(&draggingRect);
	MoveTo(draggingRect.right, draggingRect.bottom - GROWRECTSIZE);
	LineTo(draggingRect.right - GROWRECTSIZE, draggingRect.bottom - GROWRECTSIZE);
	LineTo(draggingRect.right - GROWRECTSIZE, draggingRect.bottom);
    
    PenMode(srcCopy);
    PenPat(&(qd.black));
    
    /* Calculate new size (accounting for frame) and return */
    newH = (draggingRect.bottom - draggingRect.top) - frameH;
    newW = (draggingRect.right - draggingRect.left) - frameW;
    growSize = (newH << 16) + newW;				/* LoWord is width, HiWord is height */
    
    /* now put things back the way we found them */
	SetClip(oldClip);
	DisposeRgn(oldClip);
	SetPenState(&oldPen);

    SetPort(savePort);

	return(growSize);
}


/********************************************************************
*   ShowAboutWindow
*
*	Shows the about window in ALRT resource 7100 if it exists, otherwise it will
*	  call the WSysMenu() call.
*********************************************************************/
void ShowAboutWindow(void)
{
Handle hRsrc;
WindowRef macWin;
LPPRIVATEWINDOWSTRUCT lppws;


	/* First, try and retrieve a resource based about box */
	hRsrc = Get1Resource(ALERTRSRCTYPE, ABOUTBOXALERT_ID);

	/* If there is an about box resource, use it */
	if (hRsrc) {
		Alert(ABOUTBOXALERT_ID, NULL);
		ReleaseResource(hRsrc);
	}
	else {
		macWin = FrontWindow();
		/* Get the window struct and verify it is one of our windows */
		if ((lppws = GETPWS(macWin)) == NULL)
			return;

		LibCallback(999, (LPARAM)lppws->hWnd, 0, NULL);
	}
}

