/*	XGWindow.cpp
 *
 *		This is the core window processing routines
 */

/**********************************************************************

  YAAF is Copyright 1997-1999 by William Woody.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions 
  are met:

  Redistributions of source code must retain the above copyright notice, 
  this list of conditions and the following disclaimer.

  Neither the name of the copyright holder or other contributors may
  be used to promote products derived from this software without
  specific written prior permission.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
  SOFTWARE.
  
  Contact:   woody@alumni.caltech.edu
  Web page:  http://www.pandawave.com/yaaf/

**********************************************************************/

#include <XConfig.h>			// must be first to optimize compile on MSVC++
#include <string.h>
#include <XDocument.h>
#include <XForm.h>
#include <XMessages.h>
#include <XApplication.h>
#include <XWindow.h>
#include <XDataUtil.h>
#include <XStringUtil.h>
#include <XCursorUtil.h>
#include <XError.h>
#include <XMisc.h>

#include <XDialog.h>

#if OPT_XWIN
#include <X11/Xutil.h>
#include "XGMenuView.h"
#endif

#if OPT_MACOS
#include "MacFloater.h"
#endif

#if OPT_WINOS || OPT_XWIN
#include <XButtons.h>
#endif


/************************************************************************/
/*																		*/
/*	Globals																*/
/*																		*/
/************************************************************************/

#if OPT_XWIN
extern Display *_GDisplay;
extern bool _GDialogFlag;
#endif

/*
 *	Module specific globals
 */

static short GDefaultPosition;

/*
 *	External globals
 */

XGWindow *XGWindow::gList;
XGView *XGWindow::gLastView = NULL;
bool XGWindow::gHoldCapture = false;
XGView *XGWindow::gCapture = NULL;

#if OPT_WINOS == 1
HWND XGWindow::gLastHWND = NULL;
#endif

/*
 *	Click time stuff
 */

static unsigned long GClickTime;
static bool			 GClickLast = false;

/************************************************************************/
/*																		*/
/*	Construction/Destruction											*/
/*																		*/
/************************************************************************/

#if 0
#pragma mark Construction/Destruction
#endif

/*$	XGWindow::XGWindow
 *
 *		Three versions of me to create/destroy me
 */

XGWindow::XGWindow(XGArgStream &stream, XGForm *form) : XGView(this)
{
	XGSWindowInitRecord r;

	fForm = form;
	
	r.windowType = stream.ReadInteger();
	r.windowKind = stream.ReadInteger();
	r.windowID = stream.ReadInteger();
	r.fVisible = stream.ReadBoolean();
	r.screenLeft = stream.ReadInteger();
	r.screenTop = stream.ReadInteger();
	r.screenRight = stream.ReadInteger();
	r.screenBottom = stream.ReadInteger();
	r.minx = stream.ReadInteger();
	r.miny = stream.ReadInteger();
	r.maxx = stream.ReadInteger();
	r.maxy = stream.ReadInteger();
	r.initx = stream.ReadInteger();
	r.inity = stream.ReadInteger();
	r.zoomx = stream.ReadInteger();
	r.zoomy = stream.ReadInteger();
	stream.ReadString(r.windowName);
	r.menuID = stream.ReadInteger();
	IInitWindow(r);
	
	/*
	 *	Add to my linked list
	 */

	fPrev = NULL;
	fNext = gList;
	gList = this;
	if (fNext) fNext->fPrev = this;
	
	/*
	 *	The window is now invisible. Kludge create message by sending
	 *	it to my parent's receive method
	 */
	
	XGSWindowEvent we;
	we.window = this;
	XGDispatch::DoDispatch(KXGEventWindowCreate,r.windowID,(void *)&we);

	/*
	 *	Show the window if it's hidden
	 */
	
	if (r.fVisible) {
		ShowWindow();
		SelectWindow();
	}
}

XGWindow::XGWindow(XGSWindowInitRecord &r, XGForm *form) : XGView(this)
{
	fForm = form;
	
	IInitWindow(r);
	
	/*
	 *	Add to my linked list
	 */
	
	fPrev = NULL;
	fNext = gList;
	gList = this;
	if (fNext) fNext->fPrev = this;
	
	/*
	 *	The window is now invisible. Kludge create message by sending
	 *	it to my parent's receive method
	 */
	
	XGSWindowEvent we;
	we.window = this;
	XGDispatch::DoDispatch(KXGEventWindowCreate,r.windowID,(void *)&we);

	/*
	 *	Show the window if it's hidden
	 */
	
	if (r.fVisible) {
		ShowWindow();
		SelectWindow();
	}
}

/*$	XGWindow::~XGWindow
 *
 *		Close me
 */

XGWindow::~XGWindow()
{
	XGView *view;
	
	/*
	 *	Blow away the children views from this window here. Yes,
	 *	I know this is done in the view class's destructor, but
	 *	it needs to be done here first, before I blow the window away.
	 */
	
	while (NULL != (view = GetChild())) delete view;
	
	/*
	 *	Remove from double-linked list
	 */

	if (gList == this) {
		gList = fNext;
		if (fNext) fNext->fPrev = NULL;
	} else {
		fPrev->fNext = fNext;
		if (fNext) fNext->fPrev = fPrev;
	}

	/*
	 *  Tell my document I'm gone
	 */
	
	XGSWindowEvent we;
	we.window = this;
	XGDispatch::DoDispatch(KXGEventWindowDestroy,GetWindowID(),(void *)&we);
	
	/*
	 *	Remove the document and form
	 */
	
	if (fForm) {
		fForm->DoFormTerminate();
		fForm->fWindow = NULL;
		delete fForm;
		fForm = NULL;
	}
	
	/*
	 *  Close this window itself
	 */
	
#if OPT_MACOS == 1
	if (fWindow.tw != NULL) {
		::MCloseWindow((WindowPtr)&fWindow.w);
	}
#endif

#if OPT_WINOS == 1
	if (fWindow) {
		if (fDlogParent != NULL) {
			HWND w;
			XGWindow *xw;
			
			/*
			 *	This was a dialog window. Reactivate the window I was in
			 *	front of. Also go ahead and disable all the parents above
			 *	this one...
			 */
			
			::EnableWindow(fDlogParent,TRUE);
			::SetWindowPos(fDlogParent,HWND_TOP,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);

			xw = XGWindow::GetXGWindow(fDlogParent);
			while (xw) {
				w = xw->fDlogParent;
				if (w) {
					::EnableWindow(w,FALSE);
					xw = XGWindow::GetXGWindow(w);
				} else break;
			}
		}

		SetProp(fWindow,_GWindowClass,NULL);
		if (_GMDIWindow) {
			::SendMessage(_GMDIWindow,WM_MDIDESTROY,(WPARAM)fWindow,NULL);
		} else {
			DestroyWindow(fWindow);
		}
		fWindow = NULL;							// and forget the window
	}
#endif

#if OPT_XWIN == 1
	if (fWindow) {
		/*
		 *	Destroy me.
		 */
		
		::XUnmapWindow(_GDisplay,fWindow);
		::XDestroyWindow(_GDisplay,fWindow);
		fWindow = NULL;
	}
#endif

	/*
	 *	And clear the reference to me from my view. (My children
	 *	views have already been fried)
	 */
	
	SetRootWindow(0);
}


/*$	XGWindow::CloseWindow
 *
 *		Handle closing this window. This queries the contained document
 *	and processes the close after saving the file
 */

bool XGWindow::CloseWindow()
{
	XGSWindowEvent vr;
	
	/*
	 *	Ask the form. if DoQueryDestroyWindow returns false, punt.
	 */
	
	if (fForm) {
		if (!fForm->DoQueryDestroyWindow()) return false;
	}
	
	/*
	 *	Send the predestroy message. Sent after the attempts to save this
	 *	document are made, as there may be other reasons why a window
	 *	may not allowed to be destroyed
	 */
	
	vr.window = this;
	if (0 == DoDispatch(KXGEventWindowPreDestroy,GetWindowID(),(void *)&vr)) {
		return false;
	}
	
	/*
	 *	We got here. Kill the window and return success.
	 */
	 
	delete this;
	return 1;
}

/************************************************************************/
/*																		*/
/*	Window Min/Max stuff												*/
/*																		*/
/************************************************************************/

#if 0
#pragma mark -
#pragma mark Window size support
#endif

/*$	XGWindow::MinWindowSize
 *
 *		Default: return what I read in
 */

XPoint XGWindow::MinWindowSize()
{
	return fMin;
}

/*$	XGWindow::MaxWindowSize
 *
 *		Default: return what I read in
 */

XPoint XGWindow::MaxWindowSize()
{
	return fMax;
}

/*$	XGWindow::ZoomWindowSize
 *
 *		Default: return what I read in
 */

XPoint XGWindow::ZoomWindowSize()
{
	return fZoom;
}


void XGWindow::SetMinWindowSize( XPoint p )
{
	fMin = p;
	XPoint size = GetWindowSize();
	XPoint limited = size;
	LimitWindowSize( &limited );
	if (size.h != limited.h || size.v != limited.v) {
		SetWindowSize( limited );
	}
}


void XGWindow::SetMaxWindowSize( XPoint p )
{
	fMax = p;
	XPoint size = GetWindowSize();
	XPoint limited = size;
	LimitWindowSize( &limited );
	if (size.h != limited.h || size.v != limited.v) {
		SetWindowSize( limited );
	}
}


void XGWindow::SetZoomWindowSize( XPoint p )
{
	fZoom = p;
	XPoint size = GetWindowSize();
	XPoint limited = size;
	LimitWindowSize( &limited );
	if (size.h != limited.h || size.v != limited.v) {
		SetWindowSize( limited );
	}
}

/*$	XGWindow::LimitWindowSize
 *
 *		This is a support routine used for limiting the window's size
 */

void XGWindow::LimitWindowSize(XPoint *pt)
{
	XPoint m;
	
	m = MinWindowSize();
	if (m.h > pt->h) pt->h = m.h;
	if (m.v > pt->v) pt->v = m.v;
	
	m = MaxWindowSize();
	if ((m.h != 0) && (m.h < pt->h)) pt->h = m.h;
	if ((m.v != 0) && (m.v < pt->v)) pt->v = m.v;
}

/************************************************************************/
/*																		*/
/*	Window Attributes													*/
/*																		*/
/************************************************************************/

#if 0
#pragma mark -
#pragma mark Window Attributes
#endif

/*$	XGWindow::GetTitle
 *
 *		Get the name of this window
 */

void XGWindow::GetTitle(char *name) const
{
#if OPT_MACOS == 1
	::GetWTitle((WindowPtr)&fWindow.w,(unsigned char *)name);
	p2cstr((unsigned char *)name);
#endif

#if OPT_WINOS == 1
	::GetWindowText(fWindow,name,256);
#endif

#if OPT_XWIN == 1
	char *n;
	
	::XFetchName(_GDisplay,fWindow,&n);
	strcpy(name,n);
#endif
}

/*$	XGWindow::SetTitle
 *
 *		Set the window name
 */

void XGWindow::SetTitle(const char *name)
{
	XGSWindowEvent vr;
	
#if OPT_MACOS == 1
	unsigned char buffer[256];

	::SetWTitle((WindowPtr)&fWindow.w,cvtc2p(buffer,name));
#endif

#if OPT_WINOS == 1
	::SetWindowText(fWindow,name);
#endif

#if OPT_XWIN == 1
	::XStoreName(_GDisplay,fWindow,name);
#endif

	vr.window = this;
	XGDispatch::DoDispatch(KXGEventWindowName,GetWindowID(),(void *)&vr);
}

/*$	XGWindow::GetWindowAttributes
 *
 *		Based on the type of window, this returns an attribute flag
 */

unsigned short XGWindow::GetWindowAttributes()
{
	unsigned short a;
	
	if (fWindowKind & KWinAttributes) {
		a = 0;
		if (0 == (KWinClose & fWindowKind)) a |= KAttrNoClose;
		if (0 == (KWinResize & fWindowKind)) a |= KAttrNoResize;
		if (0 != (KWinNoMenu & fWindowKind)) a |= KAttrNoMenu;
		if (0 != (KWinHideOnSwitch & fWindowKind)) a |= KAttrHideOnSwitch;
		if (0 != (KWinNoClick & fWindowKind)) a |= KAttrNoClick;
		if ((fWindowKind & KMaskType) == KWinFloating) a |= KAttrFloater;
		return a;
	}
	
	switch (fWindowKind & KMaskType) {
		case KWinDocument:
			a = 0;
			break;
		case KWinModal:
			a = KAttrNoClose | KAttrNoResize | KAttrNoMenu;
			break;
		case KWinMovableModal:
			a = KAttrNoClose | KAttrNoResize | KAttrNoMenu;
			break;
		case KWinFloating:
			a = KAttrNoClose | KAttrNoResize | KAttrHideOnSwitch | KAttrFloater;
			break;
		default:
			a = 0;
			break;
	}
	return a;
}

/*$	XGWindow::ShowWindow
 *
 *		Show this window.
 */

void XGWindow::ShowWindow()
{
	if (!IsVisible()) {
	
#if OPT_MACOS == 1
		::MShowWindow((WindowPtr)&fWindow.w);
#endif /* OPT_MACOS */

#if OPT_WINOS == 1
		::ShowWindow(fWindow,SW_SHOW);
#endif

#if OPT_XWIN == 1
		::XMapWindow(_GDisplay,fWindow);
#endif
	}
}

/*$	XGWindow::HideWindow
 *
 *		Show this window.
 */

void XGWindow::HideWindow()
{
	if (IsVisible()) {
	
#if OPT_MACOS == 1
		::MHideWindow((WindowPtr)&fWindow.w);
#endif /* OPT_MACOS */

#if OPT_WINOS == 1
		::ShowWindow(fWindow,SW_HIDE);
#endif

#if OPT_XWIN == 1
		::XUnmapWindow(_GDisplay,fWindow);
#endif
	}
}

/*$	XGWindow::IsVisible
 *
 *		Is this window visible?
 */

bool XGWindow::IsVisible()
{
#if OPT_MACOS == 1
	return fWindow.w.visible;
#endif

#if OPT_WINOS == 1
	return (bool)IsWindowVisible(fWindow);
#endif

#if OPT_XWIN == 1
	XWindowAttributes wa;
	::XGetWindowAttributes(_GDisplay,fWindow,&wa);
	if (wa.map_state == IsUnmapped) return false;
	return true;
#endif
}

/*$	XGWindow::IsMinimized
 *
 *		Is this window minimized? "Minimized" means collapsed
 *	on the Mac, or iconic on windows.
 */

bool XGWindow::IsMinimized (void)
{
#if OPT_MACOS == 1
	if (_GAppearance)
		return(IsWindowCollapsed((WindowPtr)&fWindow.w));
	return false;
#endif

#if OPT_WINOS == 1
	return (bool)IsIconic(fWindow);
#endif

#if OPT_XWIN == 1
	Assert(false);
	return false;
#endif
}

/*$	XGWindow::IsMaximized
 *
 *		Is this window maximized? "Maximized" means zooomed on either
 *	the Mac or Windows.
 */

bool XGWindow::IsMaximized (void)
{
#if OPT_MACOS == 1
	GrafPtr port;
	Rect r;
	r = fWindow.w.port.portRect;
	GetPort(&port);
	SetPort(&fWindow.w.port);
	LocalToGlobal((Point *)&r.top);
	LocalToGlobal((Point *)&r.bottom);
	SetPort(port);
	if (fWindow.w.dataHandle)
		if (::EqualRect(&r, &(*((WStateDataHandle)fWindow.w.dataHandle))->stdState))
			return true;
	return false;
#endif

#if OPT_WINOS == 1
	return (bool)IsZoomed(fWindow);
#endif

#if OPT_XWIN == 1
	Assert(false);			/* not yet implemented */
	return false;
#endif
}

/*$	XGWindow::GetFrontWindow
 *
 *		Get the front window
 */

XGWindow *XGWindow::GetFrontWindow()
{
	XGWindow *retval;
	
	retval = XGAppCore::GetApplication()->fModalWindow;
	if (retval) return retval;

#if OPT_MACOS == 1
	WindowPtr w;
	
	w = MFrontWindow();
	return GetXGWindow(w);
#endif

#if OPT_WINOS == 1
	HWND w;
	
	/* If this is an SDI app, we have only one window */
	if (_GMDIWindow == NULL) {
		if (_GMainWindow == NULL) {
			/*
			 *	We're a multi-window SDI app. Return the event
			 *	owner.
			 */
			
			return GetXGWindow(::GetActiveWindow());
		} else {
			/*
			 *	There is only one SDI window. Return it
			 */
			 
			return XGWindow::GetXGWindow(_GMainWindow);
		}
	}
	
	/* It's an MDI window. Find the frontmost child to the MDI pane */
	w = ::GetWindow(_GMDIWindow,GW_CHILD);
	while (w != NULL) {
		if (::GetProp(w,_GWindowClass)) {
			if (::IsWindowVisible(w)) break;
		}
		w = ::GetWindow(w,GW_HWNDNEXT);
	}
	if (w == NULL) return NULL;
	return XGWindow::GetXGWindow(w);
#endif

#if OPT_XWIN == 1
	/*
	 *	The "front window" is the current window used when I'm
	 *	dealing with processing what's going on. On X Windows, this
	 *	does not necessarly mean the physically frontmost window.
	 *
	 *	If there is an event pending when this is called, I return
	 *	the window that is the target of that event. If not, this
	 *	returns the frontmost window in the window list, an arbitrary
	 *	choice.
	 */

	XGWindow *w;
		
	for (w = gList; w != NULL; w = w->fNext) {
		if (w->fActive) return w;
	}
	return gList;
#endif
}

/*$	XGWindow::SelectWindow
 *
 *		Bring this window frontmost
 */

void XGWindow::SelectWindow()
{
#if OPT_MACOS == 1
	MSelectWindow((WindowPtr)&fWindow.w);
#endif

#if OPT_WINOS == 1
	/* WM_MDIACTIVATE arguments same for Win16 and Win32 in this mode */
	if (_GMDIWindow) {
		::SendMessage(_GMDIWindow,WM_MDIACTIVATE,(WPARAM)fWindow,NULL);
		if (::IsIconic(fWindow)) ::SendMessage(_GMDIWindow,WM_MDIRESTORE,(WPARAM)fWindow,NULL);
	} else {
		::SetWindowPos(fWindow,HWND_TOP,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
		::ShowWindow(fWindow,SW_RESTORE);
	}
#endif

#if OPT_XWIN == 1
	/*
	 *	Raise my container window
	 */
	
	if (fWMWindow) ::XRaiseWindow(_GDisplay,fWMWindow);
	else ::XRaiseWindow(_GDisplay,fWindow);
#endif
}

/*$	XGWindow::ShowWindow
 *
 *		The static version of the show window method
 */

void XGWindow::ShowWindow (short id)
{
	XGWindow *w = GetWindowByID(id);
	if (w)
		w->ShowWindow();
}

/*$	XGWindow::HideWindow
 *
 *		The static version of the hide window method
 */

void XGWindow::HideWindow (short id)
{
	XGWindow *w = GetWindowByID(id);
	if (w)
		w->HideWindow();
}

/*$	XGWindow::IsVisible
 *
 *		Returns true if this window is visible
 */

bool XGWindow::IsVisible (short id)
{
	XGWindow *w = GetWindowByID(id);
	if (w)
		return(w->IsVisible());
	return(false);
}

/*$	XGWindow::IsMinimized
 *
 *		Returns true if this window has been minimized
 */

bool XGWindow::IsMinimized (short id)
{
	XGWindow *w = GetWindowByID(id);
	if (w)
		return(w->IsMinimized());
	return(false);
}

/*$	XGWindow::IsMaximized
 *
 *		Returns true if this window has been maximized
 */

bool XGWindow::IsMaximized (short id)
{
	XGWindow *w = GetWindowByID(id);
	if (w)
		return(w->IsMaximized());
	return(false);
}

/*$	XGWindow::GetWindowByID
 *
 *		Find the window that has the specified identifier.
 */

XGWindow *XGWindow::GetWindowByID (short id)
{
	XGWindow *w;

	for (w = gList; w; w = w->fNext) {
		if (w->fWindowID == id)
			return(w);
	}
	return(NULL);
}

/*$	XGWindow::SelectWindow
 *
 *		Selects the window by it's identifier
 */

void XGWindow::SelectWindow (short id)
{
	XGWindow *w = GetWindowByID(id);
	if (w)
		w->SelectWindow();
}

/*$	XGWindow::GetScreenSize
 *
 *		Return the size of the main screen (minus the menu bar)
 */

void XGWindow::GetScreenSize(XRect *r)
{
#if OPT_MACOS == 1
	WindowPtr w;
		
	GetWMgrPort(&w);
	*r = w->portRect;
	r->top += LMGetMBarHeight();
#endif

#if OPT_WINOS == 1
	if (_GMDIWindow) {
		::GetClientRect(_GMDIWindow,r);
	} else {
		r->left   = 0;
		r->top    = 0;
		r->right  = ::GetSystemMetrics(SM_CXFULLSCREEN);
		r->bottom = ::GetSystemMetrics(SM_CYFULLSCREEN);
	}
#endif

#if OPT_XWIN == 1
	int i;
	
	i = DefaultScreen(_GDisplay);
	r->left = 0;
	r->top = 0;
	r->right = DisplayWidth(_GDisplay,i);
	r->bottom = DisplayHeight(_GDisplay,i);
#endif
}

/*$	XGWindow::GetMenuBarID
 *
 *		Get the current menu bar for me
 */

short XGWindow::GetMenuBarID()
{
	return fMenuBar;
}

/************************************************************************/
/*																		*/
/*	Window Size															*/
/*																		*/
/************************************************************************/

#if 0
#pragma mark -
#pragma mark Window Size
#endif

/*$	XGWindow::GetContentSize
 *
 *		Return the size of the content area
 */

XPoint XGWindow::GetContentSize(void) const
{
#if OPT_MACOS == 1
	XPoint pt;
	
	pt.h = fWindow.w.port.portRect.right - fWindow.w.port.portRect.left;
	pt.v = fWindow.w.port.portRect.bottom - fWindow.w.port.portRect.top;
	
	return pt;
#endif

#if OPT_WINOS == 1
	XPoint pt;
	XRect r;
	
	GetClientRect(fWindow,&r);
	
	pt.h = r.right - r.left;
	pt.v = r.bottom - r.top;
	
	return pt;
#endif

#if OPT_XWIN == 1
	XWindowAttributes wa;
	XPoint pt;
	
	::XGetWindowAttributes(_GDisplay,fWindow,&wa);
	pt.h = wa.width;			/* ### Menu bar height */
	pt.v = wa.height - 20;
	return pt;
#endif
}

/*$	XGWindow::GetContentRect
 *
 *		Get the content rectangle
 */

XRect XGWindow::GetContentRect() const
{
	XRect r;
	XPoint size;
	
	size = GetContentSize();
	r.left = 0;
	r.top = 0;
	r.right = size.h;
	r.bottom = size.v;
	
	return r;
}

/*$	XGWindow::SetWindowSize
 *
 *		Resize this window
 */

void XGWindow::SetWindowSize(XPoint size)
{
	LimitWindowSize(&size);
	
#if OPT_MACOS == 1
	SizeWindow((WindowPtr)&fWindow.w,size.h,size.v,1);
	ProcessSizeWindow();
#endif

#if OPT_WINOS == 1
	ContentToSize(&size);
	/* This depends on the window resize event to resize the contents */
	::SetWindowPos(fWindow,NULL,0,0,size.h,size.v,SWP_NOMOVE | SWP_NOZORDER);
#endif

#if OPT_XWIN == 1
	/* This depends on the window resize event to resize the contents */
	::XResizeWindow(_GDisplay,fWindow,size.h,size.v);
#endif
}

/*$	XGWindow::SetWindowPos
 *
 *		Set the window's location (by the window's outer border)
 */

void XGWindow::SetWindowPos(XPoint pos)
{
#if OPT_MACOS == 1
	pos.h += 1;
	pos.v += 21;
	MoveWindow((WindowPtr)&fWindow.w,pos.h,pos.v,0);
#endif

#if OPT_WINOS == 1
	::SetWindowPos(fWindow,NULL,pos.h,pos.v,0,0,SWP_NOSIZE | SWP_NOZORDER);
#endif

#if OPT_XWIN == 1
	::XMoveWindow(_GDisplay,fWindow,pos.h,pos.v);
#endif
}

/*$	XGWindow::SetWindowLocation
 *
 *		Set the window's global location
 */

void XGWindow::SetWindowLocation(XRect r)
{
	XPoint pt;
	
	pt.h = r.right - r.left;
	pt.v = r.bottom - r.top;
	LimitWindowSize(&pt);
	r.right = r.left + pt.h;
	r.bottom = r.top + pt.v;
	
#if OPT_MACOS == 1
	bool vis;
	
	vis = fWindow.w.visible;
	if (vis) ShowHide((WindowPtr)&fWindow.w,0);		// Temporary hide
	SizeWindow((WindowPtr)&fWindow.w,r.right-r.left,r.bottom-r.top,0);
	MoveWindow((WindowPtr)&fWindow.w,r.left,r.top,0);
	if (vis) ShowHide((WindowPtr)&fWindow.w,1);		// show it again

	ProcessSizeWindow();
#endif

#if OPT_WINOS == 1
	ContentToSize(&r);
	/* This depends on the window resize event to resize the contents */
	::SetWindowPos(fWindow,NULL,r.left,r.top,r.right-r.left,r.bottom-r.top,SWP_NOZORDER);
#endif

#if OPT_XWIN == 1
	/* This depends on the window resize event to resize the contents */
	::XMoveResizeWindow(_GDisplay,fWindow,r.left,r.top,r.right-r.left,r.bottom-r.top);
#endif
}

/*$	XGWindow::GetWindowSize
 *
 *		Get the window's current size
 */

XPoint XGWindow::GetWindowSize() const
{
	XPoint pt;

#if OPT_MACOS == 1
	XRect r;
	
	r = fWindow.w.port.portRect;
	pt.h = r.right - r.left;
	pt.v = r.bottom - r.top;
#endif

#if OPT_WINOS == 1
	XRect r;
	
	GetWindowRect(fWindow,&r);
	pt.h = r.right - r.left;
	pt.v = r.bottom - r.top;
	SizeToContent(&pt);
#endif

#if OPT_XWIN == 1
	pt = GetContentSize();
#endif

	return pt;
}

/*$	XGWindow::GetWindowPos
 *
 *		Get the window's current location
 */

XPoint XGWindow::GetWindowPos() const
{
	XPoint pt;
	
#if OPT_MACOS == 1
	const Rect *r;
	CGrafPtr port;
#endif

#if OPT_WINOS == 1
	XRect r;
#endif

#if OPT_MACOS == 1
	if (fWindow.w.port.portBits.rowBytes & 0x8000) {	// Color version
		port = (CGrafPtr)&fWindow.w.port;
		r = &(**(port->portPixMap)).bounds;
	} else {
		r = &fWindow.w.port.portBits.bounds;
	}
	pt.h = fWindow.w.port.portRect.left - r->left;
	pt.v = fWindow.w.port.portRect.top- r->top;
#endif

#if OPT_WINOS == 1
	GetWindowRect(fWindow,&r);
	if (::GetParent(fWindow))
		MapWindowPoints(NULL, ::GetParent(fWindow), (LPPOINT)&r, 2);
	SizeToContent(&r);
	pt.h = r.left;
	pt.v = r.top;
#endif

#if OPT_XWIN == 1
	XWindowAttributes wa;
	
	::XGetWindowAttributes(_GDisplay,fWindow,&wa);
	pt.h = wa.x;
	pt.v = wa.y;
#endif
	
	return pt;
}

/*$	XGWindow::GetWindowLocation
 *
 *		Get the location of this thing. This is basically the screen
 *	location of the content region.
 */

XRect XGWindow::GetWindowLocation() const
{
	XRect r;
	XPoint pt;
	
	pt = GetWindowPos();
	r.left = pt.h;
	r.top = pt.v;
	pt = GetWindowSize();
	r.right = r.left + pt.h;
	r.bottom = r.top + pt.v;
	return r;
}

/*$	XGWindow::ContentToSize
 *
 *		Convert from content to outer size of window. We don't care as
 *	much about the outer size of the window because that's used to
 *	approximate the location of a bunch of tiled windows on the screen.
 *		We *do* care about the interior, however.
 */

void XGWindow::ContentToSize(XPoint *size)
{
#if OPT_MACOS || OPT_XWIN
	/* X: What the hell. This varies from window manager to window manger */
	if (size->h > 0) size->h += 2;
	if (size->v > 0) size->v += 22;
#endif

#if OPT_WINOS
	/* This must be precise. */
	if (size->h > 0) size->h += 2 * ::GetSystemMetrics(SM_CXSIZEFRAME);
	if (size->v > 0) size->v += 2 * ::GetSystemMetrics(SM_CYSIZEFRAME) +
							    ::GetSystemMetrics(SM_CYCAPTION) +
							    ::GetSystemMetrics(SM_CYMENU);
#endif
}

/*$	XGWindow::ContentToSize
 *
 *		The rectangle version of the above.
 */

void XGWindow::ContentToSize(XRect *size)
{
	if (EmptyRect(size)) return;
	
#if OPT_MACOS || OPT_XWIN
	/* X: What the hell. This varies from window manager to window manger */
	size->left -= 1;
	size->right += 1;
	size->top -= 21;
	size->bottom += 1;
#endif

#if OPT_WINOS
	/* This must be precise. */
	size->left -= ::GetSystemMetrics(SM_CXSIZEFRAME);
	size->right += ::GetSystemMetrics(SM_CXSIZEFRAME);
	size->bottom += ::GetSystemMetrics(SM_CYSIZEFRAME);
	size->top -= ::GetSystemMetrics(SM_CYSIZEFRAME) +
				 ::GetSystemMetrics(SM_CYCAPTION) +
				 ::GetSystemMetrics(SM_CYMENU);
#endif
}

/*$	XGWindow::SizeToContent
 *
 *		Inverse of the ContentToSize conversions.
 */

void XGWindow::SizeToContent(XPoint *size)
{
#if OPT_MACOS || OPT_XWIN
	/* X: What the hell. This varies from window manager to window manger */
	if (size->h > 0) size->h -= 2;
	if (size->v > 0) size->v -= 22;
#endif

#if OPT_WINOS
	/* This must be precise. */
	if (size->h > 0) size->h -= 2 * ::GetSystemMetrics(SM_CXSIZEFRAME);
	if (size->v > 0) size->v -= 2 * ::GetSystemMetrics(SM_CYSIZEFRAME) +
			   					::GetSystemMetrics(SM_CYCAPTION) +
							    ::GetSystemMetrics(SM_CYMENU);
#endif
}

/*$	XGWindow::SizeToContent
 *
 *		Inverse of the ContentToSize conversions.
 */

void XGWindow::SizeToContent(XRect *size)
{
	if (EmptyRect(size)) return;

#if OPT_MACOS || OPT_XWIN
	/* X: What the hell. This varies from window manager to window manger */
	size->left += 1;
	size->right -= 1;
	size->top += 21;
	size->bottom -= 1;
#endif

#if OPT_WINOS
	/* This must be precise. */
	size->left += ::GetSystemMetrics(SM_CXSIZEFRAME);
	size->right -= ::GetSystemMetrics(SM_CXSIZEFRAME);
	size->bottom -= ::GetSystemMetrics(SM_CYSIZEFRAME);
	size->top += ::GetSystemMetrics(SM_CYSIZEFRAME) +
				 ::GetSystemMetrics(SM_CYCAPTION) +
				 ::GetSystemMetrics(SM_CYMENU);
#endif
}


/************************************************************************/
/*																		*/
/*	Event Support														*/
/*																		*/
/************************************************************************/

#if 0
#pragma mark -
#pragma mark Window Events
#endif

BEGINDISPATCHPROC(XGWindow,XGDispatch,XGWindow::Dispatch)
	DISPATCHTABLE(KXGKeyEvent,XGWindow::DoKey)
	DISPATCHTABLE(KXGMenuKey,XGDialog::DoMenuKey)
ENDDISPATCH

/*	XGWindow::Dispatch
 *
 *		Send message to the form if present
 */
 
long XGWindow::Dispatch(long msg, long, void *)
{
	/*
	 *	Special case: with modal windows, bump out the
	 *	menus that are not handled by this window.
	 */
		
	if (XGAppCore::GetApplication()->fModalWindow) {
		if (msg == KXGGetMenuStatus) return 0;
		if (msg == KXGDoMenuCommand) return 0;
	}
	return -1;
}

/*$	XGWindow::DoKey
 *
 *		Handle keyboard event.
 */

long XGWindow::DoKey(long k, void *)
{
	short key,code;
	
	key = GETLOWORD(k);
	code = GETHIWORD(k);
	
	if ((0 == (code & KSpecialKey)) && (key == '\t')) {
		/*
		 *	Tab key processing
		 */
		
		if (code & KKeyShift) PrevTabStop();
		else NextTabStop();
		return 0;
	}
	
	return -1;
}


/*$	XGWindow::DoMenuKey
 *
 *		Handle menu key; find the accelerator and move to the
 *	appropriate tab stop. This is only done on windows and X 
 *	programs to allow keyboard navigation
 */

long XGWindow::DoMenuKey(long k, void *)
{
#if OPT_MACOS
	#pragma unused (k)
#endif

#if OPT_WINOS || OPT_XWIN
	short key;
	XGView *view;
	XGView *ptr;
	XGButton *btn;
	
	key = GETLOWORD(k);
	
	/*
	 *	Step 1: Find if there is a view with this accelerator
	 */
	
	view = FindViewByAccel(key);
	if (view == NULL) return -1;
	
	/*
	 *	Step 2: Find the view with the tab stop that is either
	 *	me or right after me. If it is me, simulate the push of
	 *	the button
	 */
	
	if (view->IsTabStop()) {
		view->SetFocus();
		
		/* And simulate push if this is the control I selected */
		btn = dynamic_cast<XGButton *>(view);
		if (btn) btn->PushButton();
		return 0;
	}
	ptr = view;
	for (;;) {
		ptr = ptr->FindNextView();
		if (ptr == NULL) ptr = this;
		if (ptr == view) break;				// no tab stop controls???
		
		if (ptr->IsTabStop()) {
			ptr->SetFocus();
			return 0;
		}
	}
#endif
	
	return -1;
}

/*$	XGWindow::FirstTabStop
 *
 *		Find the first non-zero ID'ed view with the tab stop,
 *	visible, and enabled views
 */

void XGWindow::FirstTabStop(void)
{
	XGView *v = FindFirstView();
	if (v) v->SetFocus();
}

/*$	XGWindow::NextTabStop
 *
 *		Find the next non-zero ID'ed view with the tab stop,
 *	visible, and enabled views
 */

void XGWindow::NextTabStop(void)
{
	XGView *v;
	
	v = dynamic_cast<XGView *>(XGDispatch::GetFocus());
	if (v == NULL) v = FindFirstView();
	else if (v == dynamic_cast<XGView *>(this)) v = FindFirstView();
	else {
		v = FindAfterView(v->GetViewID());
		if (v == NULL) v = FindFirstView();
	}
	
	if (v) v->SetFocus();
}

/*$	XGWindow::PrevTabStop
 *
 *		Find the previous non-zero ID'ed view with the tab stop,
 *	visible, and enabled views
 */

void XGWindow::PrevTabStop(void)
{
	XGView *v;
	
	v = dynamic_cast<XGView *>(XGDispatch::GetFocus());
	if (v == NULL) v = FindLastView();
	else if (v == dynamic_cast<XGView *>(this)) v = FindLastView();
	else {
		v = FindBeforeView(v->GetViewID());
		if (v == NULL) v = FindLastView();
	}
	
	if (v) v->SetFocus();
}

/************************************************************************/
/*																		*/
/*	Event Dispatch														*/
/*																		*/
/************************************************************************/

#if 0
#pragma mark -
#pragma mark Event Dispatch
#endif

/*$	XGWindow::ProcessDraw
 *
 *		Handle drawing inside of this window. This draws the grow icon,
 *	the view, and redoes the grow icon again.
 */

void XGWindow::ProcessDraw(XRect r)
{
	XGView::ProcessDraw(r);
	
#if OPT_XWIN == 1
	if (fMenuBarView) fMenuBarView->ProcessDraw(r);
#endif
}

/*$	XGWindow::ProcessSizeWindow
 *
 *		Resize the view to fit within this window. This can also
 *	be called when the window is first opened
 */

void XGWindow::ProcessSizeWindow()
{
	XRect r;
	
#if OPT_MACOS == 1
	r = fWindow.w.port.portRect;
	r.bottom -= r.top;
	r.right -= r.left;
	r.top = 0;
	r.left = 0;
#endif

#if OPT_WINOS == 1
	::GetClientRect(fWindow,&r);

	if (fCorner) {
		XRect rr = r;

		rr.top = rr.bottom - ::GetSystemMetrics(SM_CYHSCROLL);
		rr.left = rr.right - ::GetSystemMetrics(SM_CXVSCROLL);
		::SetWindowPos(fCorner,NULL,rr.left,rr.top,rr.right-rr.left,rr.bottom-rr.top,SWP_NOZORDER);
	}	

	r.bottom -= r.top;
	r.right -= r.left;
	r.top = 0;
	r.left = 0;
#endif

#if OPT_XWIN == 1
	XWindowAttributes wa;
	
	::XGetWindowAttributes(_GDisplay,fWindow,&wa);
	if ((wa.width == fOldWidth) && (wa.height == fOldHeight)) return;
	if (fMenuBarView) {
		r.left = 0;
		r.top = 0;
		r.right = wa.width;
		r.bottom = 20;
		if (wa.width != fOldWidth) fMenuBarView->SetLocation(r);
	}
	r.left = 0;
	r.top = 0;
	r.right = wa.width;
	r.bottom = wa.height;
	if (fMenuBarView) {
		r.top += 20;
	}
	
	fOldWidth = wa.width;
	fOldHeight = wa.height;
#endif

	SetLocation(r);
}

/*$	XGWindow::ProcessMouseDown
 *
 *		Handle the mouse down
 */

XGView *XGWindow::ProcessMouseDown(XPoint pt, short flags)
{
	GClickLast = false;
	GClickTime = XGGetTime() + XGGetDoubleClick();

#if OPT_XWIN == 1
	if ((pt.v < 20) && (fMenuBarView)) {
		gCapture = fMenuBarView->FindClick(pt);
	} else {
		gCapture = FindClick(pt);
	}
#else
	gCapture = FindClick(pt);
#endif

	ProcessMouseEnter(pt,flags,gCapture);
	if (!gCapture) return NULL;
	gCapture->GlobalToView(&pt);
	if (!gCapture->DoMouseDown(pt,flags)) return NULL;
	return gCapture;
}

/*$	XGWindow::ProcessMouseMove
 *
 *		Handle mouse move
 */

void XGWindow::ProcessMouseMove(XPoint pt, short flags, XGView *v)
{
	if (v == NULL) {
#if OPT_XWIN == 1
		if ((pt.v < 20) && (fMenuBarView)) {
			v = fMenuBarView->FindClick(pt);
		} else {
			v = FindClick(pt);
		}
#else
		v = FindClick(pt);
#endif
	}

	ProcessMouseEnter(pt,flags,v);
	if (v) {
		v->GlobalToView(&pt);
		v->DoMouseMove(pt,flags);
	}
}

/*$	XGWindow::ProcessMouseUp
 *
 *		Handle mouse up
 */

bool XGWindow::ProcessMouseUp(XPoint pt, short flags, XGView *v)
{
	gHoldCapture = false;
	
	if ((GClickLast == false) && (0 != (flags & KCapturedMouse))) {
		GClickLast = true;
		if (XGGetTime() <= GClickTime) {
			flags |= KFastClick;
		}
	}

	if (v == NULL) {
#if OPT_XWIN == 1
		if ((pt.v < 20) && (fMenuBarView)) {
			v = fMenuBarView->FindClick(pt);
		} else {
			v = FindClick(pt);
		}
		if (v == NULL) return;
#else
		if (NULL == (v = FindClick(pt))) return false;
#endif
	}

	v->GlobalToView(&pt);
	v->DoMouseUp(pt,flags);
	return gHoldCapture;
}

/*$	XGWindow::ProcessMouseEnter
 *
 *		Handle the mouse enter 
 */

void XGWindow::ProcessMouseEnter(XPoint pt, short flags, XGView *v)
{
	if (gLastView != v) {
		if (gLastView) gLastView->DoMouseLeave();
		gLastView = v;
		if (gLastView) {
			gLastView->GlobalToView(&pt);
			gLastView->DoMouseEnter(pt,flags);
#if OPT_WINOS == 1
			gLastHWND = gLastView->GetRootWindow();
#endif
		} else {
#if OPT_WINOS == 1
			gLastHWND = NULL;
#endif
		}
	}
}

/*$	XGWindow::ProcessMouseLeave
 *
 *		Handle the fact that the mouse is no longer inside of me
 */

void XGWindow::ProcessMouseLeave()
{
	if (gLastView) {
		gLastView->DoMouseLeave();
		gLastView = NULL;
#if OPT_WINOS == 1
		gLastHWND = NULL;
#endif
	}
}


/************************************************************************/
/*																		*/
/*	Event Dispatch														*/
/*																		*/
/************************************************************************/

#if 0
#pragma mark -
#pragma mark Internal Support
#endif

#if OPT_MACOS == 1

/*	XGWindow::GetXGWindow
 *
 *		OS dependant routines go from the OS window to my window class
 */

XGWindow *XGWindow::GetXGWindow(GrafPtr p)
{
	XGSWindowRecord *r;
	
	if ((((WindowPeek)p)->windowKind != KFloatingWindow) &&
			(((WindowPeek)p)->windowKind != KNormalWindow) &&
			(((WindowPeek)p)->windowKind != KDialogWindow))
		return NULL;
	r = (XGSWindowRecord *)p;
	return r->tw;
}

#endif

#if OPT_WINOS == 1

XGWindow *XGWindow::GetXGWindow(HWND w)
{
	XGWindow *tw;
	
	for (tw = gList; tw != NULL; tw = tw->fNext) {
		if (tw->fWindow == w) return tw;
	}
	return NULL;
}

#endif

#if OPT_XWIN == 1

XGWindow *XGWindow::GetXGWindow(Window w)
{
	XGWindow *tw;
	
	for (tw = gList; tw != NULL; tw = tw->fNext) {
		if (tw->fWindow == w) return tw;
	}
	return NULL;
}

/*$	XGWindow::GetXGWindowByParent
 *
 *		For X, this scans for the XGWindow object by the 
 *	parent window (the window that is the immediate child of the
 *	X root window
 */

XGWindow *XGWindow::GetXGWindowByParent(Window w)
{
	XGWindow *tw;
	
	for (tw = gList; tw != NULL; tw = tw->fNext) {
		if (tw->fWMWindow == w) return tw;
	}
	return NULL;
}

/*$	XGWindow::SetMenuBar
 *
 *		Set the menu bar
 */

void XGWindow::SetMenuBar(XGMenuBar *bar)
{
	fMenuBarView = new XGMenuView(this,bar);

	fMenuBarView->SetRootWindow(fWindow);
	fOldWidth = -1;
	fOldHeight = -1;			// cause resize always.
	ProcessSizeWindow();
}

/*$	XGWindow::RedrawMenuBar
 *
 *		If I have a menu bar view, redraw it
 */

void XGWindow::RedrawMenuBar(void)
{
	if (fMenuBarView) {
		XRect r;
		
		r = fMenuBarView->GetContentRect();
		fMenuBarView->DoDrawView(r);
	}
}

#endif

/*$	XGWindow::GetParentDispatch
 *
 *		Who gets my messages when I don't process them?
 */

XGDispatch *XGWindow::GetParentDispatch()
{
	if (fForm) return fForm;
	else return XGAppCore::GetApplication();
}

/************************************************************************/
/*																		*/
/*	Initialization Support												*/
/*																		*/
/************************************************************************/

#if 0
#pragma mark -
#pragma mark Initialization Support
#endif

/*$	XGWindow::IInitWindow
 *
 *		Initialize the window
 */

void XGWindow::IInitWindow(XGSWindowInitRecord &w)
{
	long autopos;
	XRect r;
	char buffer[256];
	short width,height;
	XRect s;
	XGWindow *wptr;
#if OPT_WINOS
	short kind;
	bool inmdio,inmdin;
#endif
	
	/*
	 *	Give the application a chance to muck with this
	 */
	
	fFocus = this;
	if (fForm) fForm->DoPreCreateWindow(&w);
	
	/*
	 *	Copy data structures
	 */
	 
	fMin.h = w.minx;
	fMin.v = w.miny;
	fMax.h = w.maxx;
	fMax.v = w.maxy;
	fZoom.h = w.zoomx;
	fZoom.v = w.zoomy;
	
	fMenuBar = w.menuID;
	
	fWindowKind = w.windowKind;
	fWindowType = w.windowType;	
	fWindowID = w.windowID;
	
#if OPT_WINOS
	fCorner = NULL;
#endif

#if OPT_XWIN
	fWMWindow = 0;
	fUpdateRgn = 0;
	fOldWidth = -1;
	fOldHeight = -1;
#endif
	
	/*
	 *	Figure out my name
	 */
	 
	strcpy(buffer,w.windowName);			// use default
	
#if OPT_XWIN == 1
	fMenuBarView = NULL;
	fCursorID = -1;
	fActive = false;
#endif
	
	/*
	 *	Figure out the window width/height.
	 */
		
	if (w.screenRight == 0) {
		if (w.initx <= 0) {
			width = 320;
			
			if ((width < w.minx) && (w.minx != 0)) width = w.minx;
			if ((width > w.maxx) && (w.maxx != 0)) width = w.maxx;
		} else {
			width = w.initx;
		}
	} else {
		width = w.screenRight - w.screenLeft;
	}
	if (w.screenBottom == 0) {
		if (w.inity <= 0) {
			height = 320;
			
			if ((height < w.miny) && (w.miny != 0)) height = w.miny;
			if ((height > w.maxy) && (w.maxy != 0)) height = w.maxy;
		} else {
			height = w.inity;
		}
	} else {
		height = w.screenBottom - w.screenTop;
	}
	
	/*
	 *	Figure out where to put my window.
	 */
	
	if ((w.screenLeft == 0) && (w.screenTop == 0)) {
		/*
		 *	Is the left, top zero? Then use the auto location
		 *	parameter specified
		 */
		
		autopos = fWindowKind & KMaskPos;
		if (autopos == KWinPosStagger) {
		
#if OPT_MACOS || OPT_XWIN
			r.top = GDefaultPosition * 15 + 44;
			r.left = GDefaultPosition * 15 + 6;
#endif

#if OPT_WINOS
			r.top = (1+GDefaultPosition) * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION));
			r.left = GDefaultPosition * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION));
			
			r.top += ::GetSystemMetrics(SM_CYMENU);
			r.left += GetSystemMetrics(SM_CXFRAME);
#endif

			GDefaultPosition++;
			if (GDefaultPosition >= 5) GDefaultPosition = 0;
		} else {
			/*
			 *	Center on frontmost window or in screen...
			 */
					
			if (autopos == KWinPosAlert) {
				wptr = GetFrontWindow();
				if (wptr == NULL) GetScreenSize(&r);
				else {
					r = wptr->GetWindowLocation();
					ContentToSize(&r);
				}
			} else {
				GetScreenSize(&r);
			}

			r.left = (r.left + r.right - width)/2;
			r.top = (r.top + r.bottom - height)/2;

#if OPT_MACOS
			if (r.top < 50) r.top = 50;
#endif

#if OPT_WINOS
			if (_GMDIWindow) {
				/*
				 *	We may have to adjust the window's location to deal
				 *	with the fact that one window is in the MDI frame
				 *	while another is not
				 */
				
				if ((autopos == KWinPosAlert) && (wptr != NULL)) {
					kind = wptr->fWindowKind & KMaskType;
					if ((kind == KWinDocument) || (kind == KWinFloating)) {
						inmdio = true;
					} else {
						inmdio = false;
					}
				} else {
					inmdio = true;
				}					
				
				kind = fWindowKind & KMaskType;
				if ((kind == KWinDocument) || (kind == KWinFloating)) {
					inmdin = true;
				} else {
					inmdin = false;
				}
				
				/*
				 *	Now determine what adjustments to the coordinate system
				 *	we need to make (if any)
				 */
				
				if (inmdin != inmdio) {
					POINT pt;
					
					pt.x = 0, pt.y = 0;
					::ClientToScreen(_GMDIWindow,&pt);
					if (inmdin) {
						/*
						 *	Old window outside, new window inside
						 */
						
						::OffsetRect(&r,-pt.x,-pt.y);
					} else {
						/*
						 *	Old window inside, new window outside
						 */
						
						::OffsetRect(&r,pt.x,pt.y);
					}
				}
			}
#endif

#if OPT_XWIN || OPT_WINOS
			if (r.top < 0) r.top = 0;
#endif

			/*
			 *	Make sure the center of the frontmost window isn't
			 *	visually right at the edge of the screen...
			 */
			
			if (r.left < 24) r.left = 24;
		}
	} else {
		r.top = w.screenTop;
		r.left = w.screenLeft;
	}
	
	r.bottom = r.top + height;
	r.right = r.left + width;
	
	/*
	 *	Keep window on screen
	 */
	
#if OPT_WINOS
	if (_GMDIWindow) {
		/*
		 *	On an MDI window, the screen size for this depends on if
		 *	the window is inside or outside the MDI frame
		 */
		
		kind = fWindowKind & KMaskType;
		if ((kind == KWinDocument) || (kind == KWinFloating)) {
			GetScreenSize(&s);			// gets the right thing
		} else {
			s.left = 0;
			s.top = 0;
			s.right =  ::GetSystemMetrics(SM_CXFULLSCREEN);
			s.bottom = ::GetSystemMetrics(SM_CYFULLSCREEN);
		}
	} else {
		GetScreenSize(&s);
	}
#else
	GetScreenSize(&s);
#endif

	SizeToContent(&s);

	if (r.right > s.right) {
		r.left += s.right - r.right;
		r.right = s.right;
	}
	if (r.bottom > s.bottom) {
		r.top += s.bottom - r.bottom;
		r.bottom = s.bottom;
	}
	if (r.left < s.left) {
		r.right += s.left - r.left;
		r.left = s.left;
	}
	if (r.top < s.top) {
		r.bottom += s.top - r.top;
		r.top = s.top;
	}
	
	/*
	 *	And open it.
	 */
	
	XGWindow::ICreateWindow(buffer,r);
	
#if OPT_MACOS
	SetRootWindow(GetGrafPtr());
#endif

#if OPT_WINOS
	SetRootWindow(GetHWND());
#endif

#if OPT_XWIN
	SetRootWindow(GetWindow());
#endif

	ProcessSizeWindow();			// force my view resize
}

#if OPT_MACOS == 1

/*$	SetWindowColor
 *
 *		This sets the background color of the specified window to grey.
 *	This is used for my dialog boxes
 */

static void SetWindowColor(WindowPtr w)
{
	WCTabHandle ctab;
	
	ctab = (WCTabHandle)::NewHandle(sizeof(WinCTab));
	if (ctab == NULL) return;
	
	(**ctab).wCSeed = 0;
	(**ctab).wCReserved = 0;
	(**ctab).ctSize = 0;					// one element
	(**ctab).ctTable[0].value = wContentColor;
	(**ctab).ctTable[0].rgb.red = 0xDDDD;
	(**ctab).ctTable[0].rgb.green = 0xDDDD;
	(**ctab).ctTable[0].rgb.blue = 0xDDDD;
	SetWinColor(w,ctab);
}

#endif

/*$	XGWindow::ICreateWindow
 *
 *		This is the code to create the window based on the information
 *	just loaded
 */

void XGWindow::ICreateWindow(char *name, XRect s)
{
	long kind = fWindowKind & KMaskType;
	
#if OPT_MACOS == 1
	unsigned char buffer[256];
	short whichProc;
	long color;
#endif

#if OPT_WINOS == 1
//	XRect sizerect;
	unsigned long flags;
#endif

#if OPT_XWIN == 1
	XGWindow *front;
	extern Atom _GDelWindowAtom;
#endif
	
#if OPT_MACOS == 1
	/*
	 *	Open the window itself [Macintosh version]
	 */
	
	Gestalt(gestaltQuickdrawVersion,&color);
	if (color >= 0x100) color = 1;		// Do I have color?
	else color = 0;
	
	fWindow.tw = this;					// Get the backpointer correct.	

	c2pstr(strcpy((char *)buffer,name));
	
	/*
	 *	Figure out the window kind given the attribute bits
	 */
	
	if (kind == KWinDocument) {
		/*
		 *	Document kind
		 */
		
		if (kind & KWinAttributes) {
			if (kind & KWinResize) {
				whichProc = 8;
			} else {
				whichProc = 4;							// noGrowDocProc
			}
		} else {
			whichProc = 8;								// zoomDocProc
		}
	} else if (kind == KWinModal) {
		/*
		 *	Modal dialog box
		 */
		
		whichProc = 1;
	} else if (kind == KWinMovableModal) {
		/*
		 *	Movable modal dialog
		 */
		
		if (_GMacOSVersion < 0x0700) {
			/*
			 *	Version 6.0.8 or earlier
			 */
			
			whichProc = 2048;							// My WDEF#128 var 0
		} else {
			/*
			 *	Version 7.0.0 or greater
			 */
			 
			whichProc = 5;
		}
	} else if (kind == KWinFloating) {
		/*
		 *	Floating window
		 */
		
		if (kind & KWinAttributes) {
			if (kind & KWinResize) {
				whichProc = 1987;
			} else {
				whichProc = 1985;
			}
		} else {
			whichProc = 1985;
		}
		if (_GMacOSVersion < 0x0750) {
			/*
			 *	Before 7.5
			 */
			
			if (whichProc == 1987) whichProc = 2050;	// My WDEF#128 var 2
			else whichProc = 2049;						// My WDEF#128 var 1
		}
	} else {
		/*
		 *	???
		 */
		
		whichProc = noGrowDocProc;
	}
	
	Rect mr = s.MacRect();
	if (color) {
		if (NULL == ::MNewCWindow((Ptr)&fWindow.w,&mr,buffer,0,whichProc,(WindowPtr)-1,!(GetWindowAttributes() & KAttrNoClose),0L)) {
			fWindow.tw = NULL;			// Clear the backpointer
			throw XGPostError(KXGOutMemory);
		}
	} else {
		if (NULL == ::MNewWindow((Ptr)&fWindow.w,&mr,buffer,0,whichProc,(WindowPtr)-1,!(GetWindowAttributes() & KAttrNoClose),0L)){
			fWindow.tw = NULL;			// Clear the backpointer
			throw XGPostError(KXGOutMemory);
		}
	}
	
	/*
	 *	Set the background content color to gray for dialogs
	 */
	
	if ((kind == KWinModal) || (kind == KWinMovableModal)) {
		SetWindowColor((WindowPtr)&fWindow.w);
	}
 
    /*
     *  Initialize drawing port
     */
	
	::SetPort((WindowPtr)&fWindow.w);
	::TextSize(9);						// Set a reasonable default font size
	fWindow.w.windowKind = (GetWindowAttributes() & KAttrFloater) ? KFloatingWindow : KNormalWindow;
#endif /* OPT_MACOS */

	/*
	 *	Windows version of this
	 */
	
#if OPT_WINOS == 1
	ContentToSize(&s);
	
	::SetFocus(NULL);					// temporary fixup
	fDlogParent = NULL;
	if ((_GMDIWindow) && ((kind == KWinDocument) || (kind == KWinFloating))) {
		_GWindow = this;
		
		if (fWindowKind & KWinAttributes) {
			if (fWindowKind & KWinResize) {
				flags = WS_CHILD | WS_OVERLAPPEDWINDOW;
			} else {
				flags = WS_CHILD | WS_OVERLAPPED | WS_DLGFRAME | WS_BORDER | WS_SYSMENU;
			}
		} else {
			flags = WS_CHILD | WS_OVERLAPPEDWINDOW;
		}
		fWindow = CreateMDIWindow(_GWindowClass,
								  name,
								  flags,
								  s.left,
								  s.top,
								  s.right-s.left,
								  s.bottom-s.top,
								  _GMDIWindow,
								  _GInstance,
								  NULL);
		_GWindow = NULL;
		if (fWindow == NULL) {
			throw XGPostError(KXGOutMemory);
		}

		/*
		 * this was redundant, and was getting in the way of the
		 * "Visible" paramter in the arg stream/init record.
		 */
	
//		::BringWindowToTop(fWindow);
//		::SendMessage(_GMDIWindow,WM_MDIACTIVATE,(WPARAM)fWindow,NULL);
//		::ShowWindow(fWindow,SW_SHOW);
	} else {
		_GWindow = this;
		
		if ((kind == KWinDocument) || (kind == KWinFloating)) {
			if (fWindowKind & KWinAttributes) {
				if (fWindowKind & KWinResize) {
					flags = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | 
							WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
				} else {
					flags = WS_OVERLAPPED | WS_DLGFRAME | WS_BORDER | WS_SYSMENU |
							WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
				}
			} else {
				flags = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | 
						WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
			}
			// Window
			fWindow = CreateWindowEx((kind == KWinFloating) ? 
										WS_EX_TOOLWINDOW | WS_EX_TOPMOST : 0,
									 _GWindowClass,
									 name,
									 flags,
									 s.left,
									 s.top,
									 s.right-s.left,
									 s.bottom-s.top,
									 NULL,
									 NULL,
									 _GInstance,
									 NULL);
									 
		} else if ((kind == KWinModal) || 
					(kind == KWinMovableModal)) {
			fDlogParent = _GMainWindow;
			if (XGAppCore::GetApplication()->fModalWindow) {
				fDlogParent = XGAppCore::GetApplication()->fModalWindow->GetHWND();
			}
			
			// Dialog
			
			/*
			 *	Kludge: the ContentToSize/SizeToContent routines only
			 *	work with windows containing a menu bar. Otherwise, they
			 *	give a result that's a hair too tall. Change this to
			 *	fix the problem
			 */
			
			s.bottom -= ::GetSystemMetrics(SM_CYMENU);
			fWindow = CreateWindowEx(WS_EX_DLGMODALFRAME,
									 _GDlogClass,
									 name,
									 WS_CLIPCHILDREN | 
								   		WS_POPUP | WS_CAPTION | WS_SYSMENU,
									 s.left,
									 s.top,
									 s.right-s.left,
									 s.bottom-s.top,
									 fDlogParent,
									 NULL,
									 _GInstance,
									 NULL);
									 
			/*
			 *	We've created the dialog box. Now disable the owner
			 */
			
			::EnableWindow(fDlogParent,FALSE);
		}
		_GWindow = NULL;
		
		if (fWindow == NULL) {
			throw XGPostError(KXGOutMemory);
		}
	}
	
	/*
	 *	Add the corner icon window control
	 */
	
	if (!(GetWindowAttributes() & KAttrNoResize)) {
		RECT rr;
		
		GetClientRect(fWindow,&rr);
		rr.top = rr.bottom - ::GetSystemMetrics(SM_CYHSCROLL);
		rr.left = rr.right - ::GetSystemMetrics(SM_CXVSCROLL);
		fCorner = CreateWindowEx(0L,
								 "SCROLLBAR",
								 NULL,
								 WS_CHILD | SBS_SIZEGRIP | SBS_SIZEBOXBOTTOMRIGHTALIGN,
								 rr.left,rr.top,
								 rr.right-rr.left,rr.bottom-rr.top,
								 fWindow,
								 NULL,
								 _GInstance,
								 NULL);
		::ShowWindow(fCorner,SW_SHOW);
	}
	
	if (fWindow) ::SetFocus(fWindow);
#endif

#if OPT_XWIN == 1
	bool dialog;
	
	/*
	 *	Sanity check--we can only open modal or movable modal windows
	 *	if there is a document window available.
	 */

	dialog = false;
	front = XGWindow::GetFrontWindow();
	if ((kind == KWinModal) || (kind == KWinMovableModal)) {
		if (front) dialog = true;
	}
	
	/*
	 *	Windows version of this thing
	 */
	
	XSetWindowAttributes attrib;
	int gx,gy;
	
	if (kind == KWinDocument) {
		gx = 0;
		gy = 0;
	} else {
		gx = s.left;
		gy = s.top;
	}
							
	attrib.event_mask = KeyPressMask |
						ButtonPressMask |
						ButtonReleaseMask |
						EnterWindowMask |
						LeaveWindowMask |
						PointerMotionHintMask |
						PointerMotionMask |
						ExposureMask |
						StructureNotifyMask |
						FocusChangeMask |
						ColormapChangeMask;

	fWindow = XCreateWindow(_GDisplay,
							DefaultRootWindow(_GDisplay),
							gx,
							gy,
							s.right - s.left,
							s.bottom - s.top,
							0,
							CopyFromParent,
							InputOutput,
							CopyFromParent,
							CWEventMask,&attrib);
	XStoreName(_GDisplay,fWindow,name);
	XSetWindowBackgroundPixmap(_GDisplay,fWindow,None);
	
	/*
     *	Set some attributes
     */
    
    XSetWMProtocols(_GDisplay,fWindow,&_GDelWindowAtom,1);
    if (dialog) {   
//	    if (_GDialogFlag) {
//  		/*
//    		 *	We're a modal dialog box.
//	    	 */
//    
//    		::XSetTransientForHint(_GDisplay,fWindow,front->GetWindow());
//    	} else {
    		/*
    		 *	We're a modeless dialog box
    		 */
    		
    		XWMHints *h;
    		
    		h = XAllocWMHints();
    		h->flags = WindowGroupHint;
    		h->window_group = front->GetWindow();
    		XSetWMHints(_GDisplay,fWindow,h);
    		
    		XSetTransientForHint(_GDisplay,fWindow,front->GetWindow());
//    	}
    } else {
    	XWMHints *h;
    	
		h = XAllocWMHints();
    	h->flags = WindowGroupHint;
    	h->window_group = fWindow;
    	XSetWMHints(_GDisplay,fWindow,h);
    }
    
    /*
     *	Now if I'm not a document, move the damned window where I want it.
     */
    
    if (kind != KWinDocument) {
		::XMoveResizeWindow(_GDisplay,
							fWindow,
							s.left,
							s.top,
							s.right-s.left,
							s.bottom-s.top);
	}
#endif
}

