/* 
   NSWindow.m

   Window class

   Copyright (C) 1998 Free Software Foundation, Inc.

   Author:  Felipe A. Rodriguez <far@pcmagic.net>
   Date:    June 1998
   
   This file is part of the mySTEP Library and is provided
   under the terms of the GNU Library General Public License.
*/ 

#import <Foundation/NSString.h>
#import <Foundation/NSCoder.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSNotification.h>
#import <Foundation/NSValue.h>
#import <Foundation/NSException.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSUserDefaults.h>
#import <Foundation/NSDictionary.h>

#import <AppKit/NSWindow.h>
#import <AppKit/NSWindowController.h>
#import <AppKit/NSPanel.h>
#import <AppKit/NSMenu.h>
#import <AppKit/NSApplication.h>
#import <AppKit/NSImage.h>
#import <AppKit/NSTextFieldCell.h>
#import <AppKit/NSTextField.h>
#import <AppKit/NSTextView.h>
#import <AppKit/NSColor.h>
#import <AppKit/NSSliderCell.h>
#import <AppKit/NSButtonCell.h>
#import <AppKit/NSButton.h>
#import <AppKit/NSScreen.h>
#import <AppKit/NSCursor.h>
#import <AppKit/NSDragging.h>
#import <AppKit/NSToolbar.h>
#import <AppKit/NSAnimation.h>
#import <AppKit/NSBezierPath.h>

#import "NSAppKitPrivate.h"
#import "NSBackendPrivate.h"

#define NOTE(notif_name) NSWindow##notif_name##Notification

// Class variables
static id __responderClass = nil;
static id __panelClass = nil;
static id __lastKeyDown = nil;
static id __frameNames = nil;
static BOOL __cursorHidden = NO;

@interface _NSThemeWidget : NSButton
- (id) initWithFrame:(NSRect) f forStyleMask:(unsigned int) aStyle;
@end

@interface _NSThemeCloseWidget : _NSThemeWidget
{
	BOOL isDocumentEdited;
}
- (BOOL) isDocumentEdited;
- (void) setDocumentEdited:(BOOL) flag;	// changes image
@end

@interface NSThemeFrame : NSView
{
	NSString *_title;
	NSImage *_titleIcon;
	NSButton *_resizeButton;	// really here?
	NSToolbar *_toolbar;
	NSColor *_backgroundColor;	// window background color
	float _height;	// title bar height
	unsigned int _style;
	BOOL _inLiveResize;
	BOOL _didSetShape;
}

// handle active/inactive by dimming out everything

- (id) initWithFrame:(NSRect) frame forStyleMask:(unsigned int) aStyle forScreen:(NSScreen *) screen;
- (unsigned int) style;

- (NSString *) title;
- (void) setTitle:(NSString *) title;
- (NSImage *) titleIcon;
- (void) setTitleIcon:(NSImage *) img;
- (NSColor *) backgroundColor;
- (void) setBackgroundColor:(NSColor *) color;

- (NSButton *) standardWindowButton:(NSWindowButton) button;
- (NSView *) contentView;
- (void) setContentView:(NSView *) view;
- (void) layout;	// set frame of content view to fit to buttons bar and toolbar (if present)
- (NSToolbar *) toolbar;
- (void) setToolbar:(NSToolbar *) toolbar;
- (BOOL) showsToolbarButton;
- (void) setShowsToolbarButton:(BOOL) flag;

@end

@interface NSGrayFrame : NSThemeFrame	// for textured windows
@end

@interface NSNextStepFrame : NSThemeFrame	// for borderless windows (has no buttons and only contentView)
@end

// what about panels?

@interface NSToolbarView : NSView
{
	NSToolbar *_toolbar;
}
- (void) setToolbar:(NSToolbar *) _toolbar;
- (NSToolbar *) toolbar;

@end

@implementation NSThemeFrame

/* FIXME:
* draw icon
* properly handle window resizing
*/

- (BOOL) isOpaque;	{ return YES; }	// only if background color has alpha==1.0
- (BOOL) isFlipped;	{ return YES; }	// to simplify coordinate calculations: titlebar is at (0,0)

- (BOOL) acceptsFirstResponder;	{ return YES; }	// to allow selecting the window

- (id) initWithFrame:(NSRect) f forStyleMask:(unsigned int) aStyle forScreen:(NSScreen *) screen;
{
	if((aStyle&GSAllWindowMask) == NSBorderlessWindowMask)
		{
		[self release];
		self=[NSNextStepFrame alloc];
		}
	else if(aStyle&NSTexturedBackgroundWindowMask)
		{
		[self release];
		self=[NSGrayFrame alloc];
		}
	if((self=[super initWithFrame:f]))
		{
		_style=aStyle;
		if((aStyle&GSAllWindowMask) != NSBorderlessWindowMask)
			{
			NSButton *b0, *b1, *b2;
			[self addSubview:b0=[NSWindow standardWindowButton:NSWindowCloseButton forStyleMask:aStyle]];
			[self addSubview:b1=[NSWindow standardWindowButton:NSWindowMiniaturizeButton forStyleMask:aStyle]];
			[self addSubview:b2=[NSWindow standardWindowButton:NSWindowZoomButton forStyleMask:aStyle]];
#if 0
			if([self interfaceStyle] >= NSPDAInterfaceStyle)
				[b1 setHidden:YES], [b2 setHidden:YES];	// standard PDA screen is not large enough for multiple resizable windows
			else
#endif	
			if((aStyle & (NSClosableWindowMask | NSMiniaturizableWindowMask| NSResizableWindowMask)) == 0)
				{ // no visible buttons!
				[b0 setHidden:YES], [b1 setHidden:YES], [b2 setHidden:YES];
				}
			// add window title button (?)
			}
		[self addSubview:[[NSView new] autorelease]];	// always add a default content view
		[self layout];
		ASSIGN(_backgroundColor, [NSColor windowBackgroundColor]);	// default background
		}
	return self;
}

- (void) dealloc;
{
	[_title release];
	[_titleIcon release];
	[_backgroundColor release];
	[super dealloc];
}

- (void) drawRect:(NSRect)rect
{ // draw window background
	static NSDictionary *a;
	if(!_didSetShape)
		{
		if((_style&NSUtilityWindowMask) == 0)
			{ // make title bar with rounded corners
			NSGraphicsContext *ctxt=[NSGraphicsContext currentContext];
			float radius=9.0;
			NSBezierPath *b=[NSBezierPath new];
			[b appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(frame)+radius, NSMinY(frame)+radius)
										  radius:radius
									  startAngle:180.0
										endAngle:270.0
									   clockwise:NO];	// top left corner
			[b appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(frame)-radius, NSMinY(frame)+radius)
										  radius:radius
									  startAngle:270.0
										endAngle:360.0
									   clockwise:NO];	// top right corner
			[b lineToPoint:NSMakePoint(NSMaxX(frame), NSMaxY(frame))];	// bottom right
			[b lineToPoint:NSMakePoint(0.0, NSMaxY(frame))];	// bottom left
			[b closePath];
			[ctxt _setShape:b];
			}
		_didSetShape=YES;
		}
	// FIXME: constrain fill operations to rect!
	[_backgroundColor set];
	NSRectFill(rect);	// draw window background
	[[NSColor windowFrameColor] set];
	NSFrameRect(bounds);	// draw a frame
	// FIXME: should also fill background behind toolbar
	NSRectFill((NSRect){NSZeroPoint, {bounds.size.width, _height}});	// fill titlebar background behind buttons
	if(!_title)
		return;
	if(!a)
		a=[[NSDictionary dictionaryWithObjectsAndKeys:		// FIXME: how does this differ from the defaults?
			[NSColor windowFrameTextColor], NSForegroundColorAttributeName,
			// use smaller font for NSUtilityWindowMask - we could e.g. use something like frame.size.height-10
			// but we have only one cache! -> add instance variable _titleAttributes
			[NSFont titleBarFontOfSize:12.0], NSFontAttributeName,
			nil] retain];
	// draw document icon or shouldn't we better use a document NSButton to store the window icon and title?
	// [_titleButton drawInteriorWithFrame:rect between buttons inView:self];
	[_title drawAtPoint:NSMakePoint((bounds.size.width-[_title sizeWithAttributes:a].width)/2.0, 1.0+(_height-16.0)/2.0) withAttributes:a]; // draw centered window title
	// draw resize area (how to draw it in front of the subviews?) - or add another subview?
}

- (void) unlockFocus;
{ // last chance to draw anything
	if((_style & NSResizableWindowMask) != 0)
		{ // draw resizing handle in the lower right corner
#if 0			// FIXME: collides somehow with changing the CTM by subviews?
		[[NSBezierPath bezierPathWithRect:bounds] setClip];
		[[NSColor grayColor] set];
//		[[NSColor redColor] set];
		[NSBezierPath strokeLineFromPoint:NSMakePoint(0-2, 0-8)
								  toPoint:NSMakePoint(bounds.size.width-8, bounds.size.height-2)];
#endif
		}
	[super unlockFocus];
}

- (unsigned int) style; { return _style; }
- (NSString *) title; { return _title; }
- (void) setTitle:(NSString *) title; { ASSIGN(_title, title); }
- (NSImage *) titleIcon; { return _titleIcon; }
- (void) setTitleIcon:(NSImage *) img; { ASSIGN(_titleIcon, img); }
- (NSColor *) backgroundColor; { return _backgroundColor; }
- (void) setBackgroundColor:(NSColor *) color; { ASSIGN(_backgroundColor, color); }

- (NSButton *) standardWindowButton:(NSWindowButton) button;
{
	switch(button)
		{
		case NSWindowCloseButton: return [sub_views objectAtIndex:0];
		case NSWindowMiniaturizeButton: return [sub_views objectAtIndex:1];
		case NSWindowZoomButton: return [sub_views objectAtIndex:2];
		case NSWindowToolbarButton: return [sub_views count] > 4?[sub_views objectAtIndex:4]:nil;
		case NSWindowDocumentIconButton:
		default: return nil;
		}
}

- (NSView *) contentView; { return [sub_views objectAtIndex:3]; }

- (void) layout;
{ // NOTE: if the window fills the screen, the content view has to be made smaller
	NSView *cv;
	NSRect f=[self frame];
	_height=[NSWindow _titleBarHeightForStyleMask:_style];
	f.origin.y+=_height;		// add room for buttons
	f.size.height-=_height;
	if(/* toolbar exists and is visible */ NO)
		{
		// resize everything to have room for toolbar frame
		}
	// should we call resizeSubviewsWithOldSize?
	cv=[self contentView];
#if 0
	NSLog(@"layout %@", self);
	NSLog(@"  cv=%@", cv);
	NSLog(@"  frame=%@", NSStringFromRect(f));
#endif
	[cv setFrame:f];	// enforce size of content view to fit
}

- (void) setContentView:(NSView *) view;
{
	NSView *cv=[self contentView];	// current content view
#if 0
	NSLog(@"setContentView %@", self);
	NSLog(@"  view=%@", view);
	NSLog(@"  cv=%@", [self contentView]);
#endif
	[self replaceSubview:cv with:view];	// this checks if a content view exists
	[view setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
	[self layout];
	[self setNeedsDisplay:YES];	// show everything
#if 0
	NSLog(@"self=%@", [self _descriptionWithSubviews]);
#endif	
}

- (NSToolbar *) toolbar; { return [sub_views count] > 4?[[sub_views objectAtIndex:5] toolbar]:nil; }

- (void) setToolbar:(NSToolbar *) toolbar;
{
	if(toolbar && [sub_views count] < 4)
		{ // we don't have a toolbar (yet)
		NSToolbarView *tv;
		NSButton *wb;
		NSRect f, wf;
		[self addSubview:wb=[NSWindow standardWindowButton:NSWindowToolbarButton forStyleMask:_style]];
		[wb setTarget:window];
		f=[wb frame];		// button frame
		wf=[window frame];	// window frame
		f.origin.x+=wf.size.width-f.size.width;	// flush button to the right end
		[wb setFrameOrigin:f.origin];
		tv=[[NSToolbarView alloc] initWithFrame:(NSRect){{0.0, wf.size.width}, {20.0, 20.0}}];	// as wide as the window
		[tv setAutoresizingMask:NSViewMaxYMargin|NSViewWidthSizable];
		[self addSubview:tv];
		[tv release];
		}
	if(!toolbar && [sub_views count] >= 4)
		{ // remove
		[[sub_views objectAtIndex:5] removeFromSuperviewWithoutNeedingDisplay];	// toolbar view
		[[sub_views objectAtIndex:4] removeFromSuperviewWithoutNeedingDisplay];	// toolbar button
		}
	else if(toolbar)
		[[sub_views objectAtIndex:5] setToolbar:toolbar];	// update
	[self layout];
}

- (BOOL) showsToolbarButton; { return ![[self standardWindowButton:NSWindowToolbarButton] isHidden]; }
- (void) setShowsToolbarButton:(BOOL) flag; { [[self standardWindowButton:NSWindowToolbarButton] setHidden:!flag]; }

- (BOOL) inLiveResize	{ return _inLiveResize; }

- (BOOL) shouldBeTreatedAsInkEvent:(NSEvent *) theEvent;
{
	return NO;	// don't ink on theme frame...
}

- (BOOL) mouseDownCanMoveWindow; { return YES; }

	// might need to modify hit-test to detect resize...

- (BOOL) acceptsFirstMouse:(NSEvent *) event; { return YES; }	// send us the first event

// FIXME: should we move that to NSWindow so that we can detect movements in any area where the underlying NSView tells us to do so?

- (void) mouseDown:(NSEvent *)theEvent
{ // NSTheme frame
	NSPoint p = [self convertPoint:[theEvent locationInWindow] fromView:nil];
	// we can make this dependent on activatingWindow
	// activate application?
	[NSMenuView _deactivate];			// close any open menu
#if 0
	NSLog(@"NSThemeFrame clicked (%@)", NSStringFromPoint(p));
#endif
	if((_style & NSResizableWindowMask) != 0 && ([self interfaceStyle] >= NSPDAInterfaceStyle))
		return;	// resizable window has been enlarged for full screen - don't permit to move
	if(p.y > _height)
		{ // check if we a have resize enabled in _style and we clicked on lower right corner
		if((_style & NSResizableWindowMask) == 0 || p.y < frame.size.height-10.0 || p.x < frame.size.width-10.0)
			return;	// ignore if not in title bar (or we ask hitTest's view if it permits for textured windows)
		_inLiveResize=YES;
#if 1
		NSLog(@"liveResize started");
#endif
		// call viewWillStartLiveResize for all subviews
		}
	p=[NSEvent mouseLocation];	// get in screen coordinates
	while(YES)
		{ // loop until mouse goes up
		theEvent = [NSApp nextEventMatchingMask:GSTrackingLoopMask
									  untilDate:[NSDate distantFuture]						// get next event
										 inMode:NSEventTrackingRunLoopMode 
										dequeue:YES];
		
		switch([theEvent type])
			{
			default: break;	// ignore
			case NSLeftMouseUp:					// If mouse went up then we are done
				if(_inLiveResize)
					; // call viewDidEndLiveResize for all subviews
				_inLiveResize=NO;
				return;
			case NSLeftMouseDragged:
				{
					NSRect wframe=[window frame];
					NSPoint loc=[NSEvent mouseLocation];
					if(_inLiveResize)
						{ // resizing
						wframe.size.width+=(loc.x-p.x);
						wframe.size.height+=(loc.y-p.y);	// move like mouse moves
						// FIXME: handle resizeIncrements
						[window setFrame:wframe display:YES];
						}
					else
						{ // moving
						wframe.origin.x+=(loc.x-p.x);
						wframe.origin.y+=(loc.y-p.y);	// move like mouse moves
						// FIXME: this has some issues when frame is clipped to the visible screen
#if 0
						NSLog(@"move window from (%@) to (%@)", NSStringFromPoint([window frame].origin), NSStringFromPoint(wframe.origin));
#endif
						[window setFrameOrigin:wframe.origin];	// move window (no need to redisplay)
						}
					p=loc;
					break;
				}
			}
  		}
}

@end

@implementation NSGrayFrame		// used for NSTexturedBackgroundWindowMask

// we don't distinguish here
// but might initialize our window for a different layout and style here

@end

@implementation NSNextStepFrame	// used for borderless window

- (void) drawRect:(NSRect)rect
{ // draw window background only (no title, no shape!)
	[_backgroundColor set];
	NSRectFill(rect);	// draw window background
}

- (NSButton *) standardWindowButton:(NSWindowButton) button;
{
	return nil;	// has no buttons
}

- (NSView *) contentView; { return [sub_views objectAtIndex:0]; }

- (void) layout;
{ // we don't have a button bar
	[[self contentView] setFrame:[self frame]];	// adjust the content view to the frame
	// should we call resizeSubviewsWithOldSize?
}

- (void) setToolbar:(NSToolbar *) toolbar; { NIMP; }	// don't save/create

// - (BOOL) mouseDownCanMoveWindow; { return YES; } but only in titlebar area!

@end

@implementation _NSThemeWidget

- (id) initWithFrame:(NSRect) f forStyleMask:(unsigned int) aStyle;
{
	if((self=[super initWithFrame:f]))
		{
// FIXME: this might require a _NSWidgetCell
		// set/modify style for 'textured'
		[self setButtonType:NSMomentaryChangeButton];	// toggle images
		[_cell setAlignment:NSCenterTextAlignment];
		[_cell setImagePosition:NSImageOverlaps];
		[_cell setBordered:NO];	// no bezel
		// [self setBezelStyle:NSCircularBezelStyle];
		[_cell setFont:[NSFont titleBarFontOfSize:0]];
//		ASSIGN(_cell->_textColor, [NSColor windowFrameTextColor]);
		}
	return self;
}

- (void) viewDidMoveToWindow
{ // set window as target for buttons
	[self setTarget:window];
}

- (BOOL) shouldDelayWindowOrderingForEvent:(NSEvent*)event	{ return YES; }		// always delay window ordering

- (void) mouseDown:(NSEvent *) e;
{
	[NSApp preventWindowOrdering];	// don't order front
	[super mouseDown:e];
}

@end

@implementation _NSThemeCloseWidget

- (BOOL) isDocumentEdited; { return isDocumentEdited; }
- (void) setDocumentEdited:(BOOL) flag;
{
	isDocumentEdited=flag;
	[self setImage:[NSImage imageNamed:flag?@"NSWindowChangedButton":@"NSWindowCloseButton"]];	// change button image
	[self setNeedsDisplay];
	// notify backend
}

@end

@implementation NSToolbarView

- (void) setToolbar:(NSToolbar *) toolbar;
{
	ASSIGN(_toolbar, toolbar);
	// layout
}

- (NSToolbar *) toolbar; { return _toolbar; }

@end

@implementation NSWindow

+ (void) initialize
{
	if (self == [NSWindow class])
		{
		NSDebugLog(@"Initialize NSWindow class\n");
		__responderClass = [NSResponder class];
		__panelClass = [NSPanel class];
		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didExpose:) name:NSWindowDidExposeNotification object:nil];	// handle expose events		
		}
}

+ (NSWindowDepth) defaultDepthLimit							{ return 32; }

+ (NSRect) contentRectForFrameRect:(NSRect)aRect
						 styleMask:(unsigned int)aStyle
{
	aRect.size.height-=[self _titleBarHeightForStyleMask:aStyle];  // remove space for title bar
	return aRect;
}

+ (NSRect) frameRectForContentRect:(NSRect)aRect
						 styleMask:(unsigned int)aStyle
{
	aRect.size.height+=[self _titleBarHeightForStyleMask:aStyle];  // make space for title bar
	return aRect;
}

+ (NSRect) minFrameWidthWithTitle:(NSString *)aTitle
						styleMask:(unsigned int)aStyle
{
	return NSZeroRect;
}

+ (float) _titleBarHeightForStyleMask:(unsigned int) mask
{ // make dependent on total window height (i.e. smaller title bar on a QVGA PDA screen)
	if((mask&GSAllWindowMask) == NSBorderlessWindowMask && [[NSScreen screens] count] > 0)
		return 0.0;	// no title bar
	if([[[NSScreen screens] objectAtIndex:0] frame].size.height < 400)
		return (mask&NSUtilityWindowMask)?12.0:16.0;
	else
		return (mask&NSUtilityWindowMask)?16.0:23.0;
}

- (void) dealloc
{
	[[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidChangeScreenParametersNotification object:nil];
	[self resignKeyWindow];
	[self resignMainWindow];
//	[_firstResponder release];
	[_fieldEditor release];	// if it exists
	[self setDelegate:nil];	// release delegate
//	[_backgroundColor release];
	[_miniWindowImage release];
	[_miniWindowTitle release];
	[_representedFilename release];
	[_windowTitle release];
	[_themeFrame removeFromSuperview]; // delete old one (does not really have a superview) - will issue a release
	[_frameSaveName release];
	[_windowController release];
	[_context release];	// if still existing
	[super dealloc];
}

- (id) init
{
	return [self initWithContentRect:NSZeroRect
				 styleMask:GSAllWindowMask				// default style mask
				 backing:NSBackingStoreBuffered
				 defer:NO
				 screen:nil];
}

- (NSWindow *) initWithWindowRef:(void *) ref;
{
	if((self=[super init]))
		{
		_context=[[NSGraphicsContext graphicsContextWithGraphicsPort:ref flipped:YES] retain];
		frame=[_context _frame];	// get frame from window
		_w.isOneShot=NO;
		// FIXME: anything else to init?
		}
	return self;
}

- (void) _screenParametersNotification:(NSNotification *) notification;
{
	NSRect f;
#if 0
	NSLog(@"%@ _screenParametersNotification: %@", NSStringFromClass([self class]), notification);
#endif
	if((_w.styleMask&GSAllWindowMask) == NSBorderlessWindowMask)
		// FIXME: we still might have to rearrange menus!
		return;	// don't touch borderless windows (e.g. menus)
	f=[self constrainFrameRect:frame toScreen:_screen];		// default: constrain to screen
	if((_w.styleMask & NSResizableWindowMask) && [self interfaceStyle] >= NSPDAInterfaceStyle)
		{ // this is a special procedure for PDA screens
		f=[_screen visibleFrame];	// resize to full screen
		}
#if 0
	NSLog(@"frame=%@", NSStringFromRect(frame));
#endif
	if(notification)
		[self setFrame:f display:YES animate:YES];	// make window reflect changed frame
	else
		frame=f;	// initialize (is being called from within initWithContentRect:)
	// FIXME: what about moving/resizing/rearranging views?
}

- (id) initWithContentRect:(NSRect)cRect
				 styleMask:(unsigned int)aStyle
				   backing:(NSBackingStoreType)bufferingType
					 defer:(BOOL)flag
{
	return [self initWithContentRect:cRect 
						   styleMask:aStyle
							 backing:bufferingType 
							   defer:flag 
							  screen:nil];
}

- (id) initWithContentRect:(NSRect)cRect
				 styleMask:(unsigned int)aStyle
				 backing:(NSBackingStoreType)bufferingType
				 defer:(BOOL)defer
				 screen:(NSScreen *)aScreen
{
	if((self=[super init]))
		{
#if 0
		NSLog(@"NSWindow initWithContentRect:%@ styleMask:%04x backing:%04x screen:%@", NSStringFromRect(cRect), aStyle, bufferingType, aScreen);
#endif
		_miniWindowTitle = _windowTitle = _representedFilename = @"Window";
		if(!aScreen)
			aScreen=[NSScreen mainScreen];	// use main screen (defined by keyWindow) if possible
		if(!aScreen)
			aScreen=[[NSScreen screens] objectAtIndex:0];	// menu bar screen if there is no main screen (yet)
		if(!aScreen)
			[NSException raise:NSGenericException format:@"Unable to find a default NSScreen"];
		_screen=aScreen;	// screens are never released
		if([[self class] isSubclassOfClass:[NSPanel class]])
			_level=NSModalPanelWindowLevel;	// default for panels
		else
			_level=NSNormalWindowLevel;	// default
		// handle NSUnscaledWindowMask -> userSpaceScaleFactor==1
		_w.needsDisplay = NO;	// will be set by first expose
		_w.autodisplay = YES;
		_w.optimizeDrawing = YES;
		_w.dynamicDepthLimit = YES;
		_w.releasedWhenClosed = YES;
		_w.acceptsMouseMoved = NO;  // default
		_w.cursorRectsEnabled = YES;
		_w.backingType = bufferingType;
		_w.styleMask = aStyle;
		_w.menuExclude = ((aStyle&GSAllWindowMask) == NSBorderlessWindowMask);	// default to be excluded
		frame=[NSWindow frameRectForContentRect:cRect styleMask:aStyle];		// get requested screen frame
		[self _screenParametersNotification:nil];								// initially adjust/restrict frame
#if 0	// postpone until orderFront:
		// the next 2 calls should be deferred until orderFront: is called
		_context=[[NSGraphicsContext graphicsContextWithWindow:self] retain];	// now, create window
		_gState=[_context _currentGState];			// save gState
#endif
		_themeFrame=[[NSThemeFrame alloc] initWithFrame:(NSRect){{0, 0}, frame.size} forStyleMask:aStyle forScreen:_screen];	// create view hierarchy
		[_themeFrame _setWindow:self];
		[_themeFrame setNextResponder:self];
		[self setNextResponder:NSApp];				// NSApp is next responder
		[[NSCursor arrowCursor] push];	// push the arrow as the default cursor	- FIXME: are we doing that for every new window???
		if(!defer)
			[self orderWindow:NSWindowAbove relativeTo:0];	// insert sort relative to self
#if 0
		NSLog(@"NSWindow end of designated initializer\n");
#endif
		[[NSNotificationCenter defaultCenter] addObserver:self
												 selector:@selector(_screenParametersNotification:)
													 name:NSApplicationDidChangeScreenParametersNotification
												   object:nil];
		if(!_w.menuExclude)
			[NSApp addWindowsItem:self title:@"Window" filename:NO];
		}
	return self;
}

- (NSString *) title						{ return _windowTitle; }
- (NSString *) miniwindowTitle				{ return _miniWindowTitle; }
- (NSString *) representedFilename			{ return _representedFilename; }
- (NSImage *) miniwindowImage				{ return _miniWindowImage; }
- (unsigned int) styleMask					{ return _w.styleMask; }
- (void)setBackingType:(NSBackingStoreType)t{ _w.backingType = t; }
- (NSBackingStoreType) backingType			{ return _w.backingType; }
- (NSDictionary *) deviceDescription		{ return [_screen deviceDescription]; }
- (NSGraphicsContext*) graphicsContext		{ return _context; }
- (int) gState								{ return _gState; }
- (int) windowNumber						{ return [_context _windowNumber]; }
- (void *) windowRef						{ return [_context graphicsPort]; }
- (NSColor *) backgroundColor				{ return [(NSThemeFrame *) _themeFrame backgroundColor]; }
- (void) setBackgroundColor:(NSColor*)color	{ [(NSThemeFrame *) _themeFrame setBackgroundColor:color]; }
- (void) setMiniwindowImage:(NSImage*)image	{ ASSIGN(_miniWindowImage,image); }
- (void) setOneShot:(BOOL)flag				{ _w.isOneShot = flag; }

- (void) setTitle:(NSString*)aString
{
	ASSIGN(_windowTitle, aString);						// local cache
	[(NSThemeFrame *) _themeFrame setTitle:aString];	// theme frame
	[_context _setTitle:aString];						// backend might want to pass to some window manager
	if(!_w.menuExclude)
		[NSApp changeWindowsItem:self title:_windowTitle filename:NO];
}

- (void) setTitleWithRepresentedFilename:(NSString*)aString
{
	[self setRepresentedFilename: aString];
	ASSIGN(_windowTitle, aString);						// local cache
	[(NSThemeFrame *) _themeFrame setTitle:aString];	// theme frame
	[_context _setTitle:aString];						// backend might want to pass to some window manager
	if(!_w.menuExclude)
		[NSApp addWindowsItem:self title:_windowTitle filename:YES];
}

- (BOOL) isOneShot							{ return _w.isOneShot; }
- (id) contentView							{ return [(NSThemeFrame *) _themeFrame contentView]; }

- (void) setContentView:(NSView *)aView				
{
#if 0
	NSLog(@"setContentView: %@", [aView _descriptionWithSubviews]);
#endif
	[(NSThemeFrame *) _themeFrame setContentView:aView];
}

- (void) setRepresentedFilename:(NSString *)aString
{
	ASSIGN(_representedFilename, aString);
}

- (void) setMiniwindowTitle:(NSString *)title
{
	ASSIGN(_miniWindowTitle, title);
	//	if (_w.miniaturized == NO);					// FIX ME redisplay miniWin
}

- (void) endEditingFor:(id)anObject					// field editor
{
#if 1
	NSLog(@"NSWindow endEditingFor: %@", anObject);
#endif
	if(![_fieldEditor resignFirstResponder] && _fieldEditor == _firstResponder)
		{ // if not force resignation
		NSLog(@" NSWindow endEditingFor: current field editor did not resign voluntarily.");
		[[NSNotificationCenter defaultCenter] postNotificationName:NSTextDidEndEditingNotification
							object:_fieldEditor];
		[(_firstResponder = self) becomeFirstResponder];
		}
}

- (NSText *) fieldEditor:(BOOL)createFlag forObject:(id)anObject
{
	SEL s = @selector(windowWillReturnFieldEditor:toObject:);
	NSText *d;											// ask delegate if it can
														// provide a field editor
	if (_delegate && [_delegate respondsToSelector:s])
		if ((d = [_delegate windowWillReturnFieldEditor:self toObject:anObject]))
			return d;
	
	if(!_fieldEditor && createFlag)					// each window has a global
		{											// text field editor, if it
		_fieldEditor = [NSTextView new];			// doesn't exist create it
		[_fieldEditor setFieldEditor:YES]; 			// if create flag is set					 
		}
	
	return _fieldEditor;							
}

- (int) level								{ return _level; }
- (BOOL) hidesOnDeactivate					{ return _w.hidesOnDeactivate; }
- (BOOL) isMiniaturized						{ return _w.miniaturized; }
- (BOOL) isVisible							{ return _w.visible; }

- (void) _setIsVisible:(BOOL) flag
{
	if(_w.visible == flag)
		return;
	if((_w.visible=flag))
		{ // became visible for the first time - process postponed actions
		if(_w.isKey)
			[_context _makeKeyWindow];
		if(_w.needsDisplay)
			[NSApp setWindowsNeedUpdate:YES];		// next update will handle drawing (which was pending while not visible)
		}
}

- (BOOL) isKeyWindow						{ return [_context _isKeyWindow]; }	// this asks the backend if we are really the key window!
- (BOOL) isMainWindow						{ return _w.isMain; }

- (void) becomeKeyWindow
{
	if(_w.isKey)	// already key window
		return;
	_w.isKey = YES;
#if 0
	NSLog(@"becomeKeyWin %@", _windowTitle);
#endif
	if(_w.visible)	// already visible
		{
#if 0
		NSLog(@"XSetInputFocus");
#endif
		[_context _makeKeyWindow];
		}
	if(!_w.cursorRectsValid)
		[self resetCursorRects];	
	[_firstResponder becomeFirstResponder];
	[[NSNotificationCenter defaultCenter] postNotificationName: NOTE(DidBecomeKey) object: self];
}

- (void) becomeMainWindow
{
	if (_w.isMain)
		return;										
	_w.isMain = YES;								// We are the main window
	[[NSNotificationCenter defaultCenter] postNotificationName:NSWindowDidBecomeMainNotification object: self];
}

- (BOOL) canBecomeKeyWindow					
{ 
	return (_w.styleMask & (NSTitledWindowMask|NSResizableWindowMask)); 
}

- (BOOL) canBecomeMainWindow					
{ 
	if((_w.styleMask & (NSTitledWindowMask|NSResizableWindowMask)))
		if(![self isKindOfClass:__panelClass])
			return YES;

	return NO; 
}

- (void) makeKeyAndOrderFront:sender
{	
	[self orderFront:sender];						// order self to the front
	if(!_w.isKey)
		{
		[self makeKeyWindow];						// Make self the key window
		[self makeMainWindow];
		}
}

- (void) makeKeyWindow
{													// Can we become the key
	if ((_w.isKey) || ![self canBecomeKeyWindow]) 	// window?
		return;										
													// ask current key window
	[[NSApp keyWindow] resignKeyWindow];			// to resign status
	[self becomeKeyWindow];
}													 
	
- (void) makeMainWindow
{													// Can we become main win
	if ((_w.isMain) || ![self canBecomeMainWindow])
		return;
													// ask current main window
	[[NSApp mainWindow] resignMainWindow];			// to resign status
	[self becomeMainWindow];
}													

- (void) resignKeyWindow
{
	if (!(_w.isKey))
		return;
	_w.isKey = NO;
	[_firstResponder resignFirstResponder];
	[NSCursor pop];									// empty cursor stack
	[[NSNotificationCenter defaultCenter] postNotificationName:NSWindowDidResignKeyNotification object: self];
}

- (void) resignMainWindow
{
	if (!(_w.isMain))
		return;
	_w.isMain = NO;
	[[NSNotificationCenter defaultCenter] postNotificationName:NSWindowDidResignMainNotification object:self];
}

- (void) orderWindow:(NSWindowOrderingMode)place 
		  relativeTo:(int)otherWin
{ // main interface call
	if(place == NSWindowOut)
		{ // close window
		if(_w.isOneShot)
			{ // close screen representation
			[_context release];
			_context=nil;
			_gState=0;
			return;
			}
		}
	else if(!_context)
		{ // allocate context (had been temporarily deallocated if we are a oneshot window)
		_context=[[NSGraphicsContext graphicsContextWithWindow:self] retain];	// now, create window
		_gState=[_context _currentGState];			// save gState
		}
	if(!otherWin)
		{
		// go through window list
		// [NSScreen _getLevelOfWindowNumber:other]
		// compare
		// determine other window according to current level (might still be 0 if we are the first window)
		}
	[_context _orderWindow:place relativeTo:otherWin];	// handle in backend
	// should we run the loop to wait for mapping events or status to really change?
}

// convenience calls

// FIXME: don't move a window in front of the key window unless both are in the same application
// make dependent on [self isKeyWindodow];

- (void) orderFront:(id) Sender; { [self orderWindow:NSWindowAbove relativeTo:0]; }
- (void) orderBack:(id) Sender; { [self orderWindow:NSWindowBelow relativeTo:0]; }
- (void) orderOut:(id) Sender; { [self orderWindow:NSWindowOut relativeTo:0]; }
- (void) orderFrontRegardless	{ [self orderFront:nil]; }

- (void) setLevel:(int)newLevel
{
	if(_level == newLevel)
		return;	// unchanged
	_level=newLevel;
	[_context _setLevel:newLevel];	// save in window list
	[self orderWindow:NSWindowAbove relativeTo:0];
}

- (void) setHidesOnDeactivate:(BOOL)flag	{ _w.hidesOnDeactivate = flag; }

- (NSPoint) cascadeTopLeftFromPoint:(NSPoint)topLeftPoint
{
static NSPoint cascadePoint = {0,0};
NSSize screenSize = [_screen visibleFrame].size;
NSPoint new = {topLeftPoint.x + 25, topLeftPoint.y - 25};

	if(new.x + frame.size.width > screenSize.width)
		{
		new.x = 30 + cascadePoint.x;
		cascadePoint.x = (cascadePoint.x < 200) ? cascadePoint.x + 50 : 25;
		}
	if(new.y - frame.size.height < 0)
		{
		new.y = screenSize.height - (30 + cascadePoint.y);
		cascadePoint.y = (cascadePoint.y < 200) ? cascadePoint.y + 50 : 25;
		}
	return new;
}

- (void) center
{ // center the window within it's screen
	NSSize screenSize = [_screen visibleFrame].size;
	NSPoint origin = frame.origin;
	origin.x = (screenSize.width - frame.size.width) / 2;
	origin.y = (screenSize.height - frame.size.height) / 2;
	[self setFrameOrigin:origin];
}

- (NSRect) constrainFrameRect:(NSRect)rect toScreen:(NSScreen *)screen
{
	NSRect vf=[screen visibleFrame];
	if(!NSContainsRect(vf, rect))
		{ // scale down and shift to visibleFrame - might also try to rotate if that fits better
#if 1
		NSLog(@"rescale/move windowFrame %@ to visibleFrame %@", NSStringFromRect(rect), NSStringFromRect(vf));
#endif
		if(rect.size.height > vf.size.height)
			{ // scale down
			float scale=vf.size.height/rect.size.height;
#if 1
			NSLog(@"scale down by %lf", scale);
#endif
			rect.size.height *= scale;  // limit
			// set content view scaling factor
			}
		if(rect.origin.y < vf.origin.y)
			rect.origin.y = vf.origin.y;  // move up as needed
		else if(rect.origin.y + rect.size.height > vf.origin.y + vf.size.height)
			rect.origin.y = vf.origin.y + vf.size.height - rect.size.height;	// move down
		if(rect.origin.x < vf.origin.x)
			rect.origin.x = vf.origin.x;  // move right as needed
		else if(rect.origin.x + rect.size.width > vf.origin.x + vf.size.width)
			rect.origin.x = vf.origin.x + vf.size.width - rect.size.width;	// move left		
#if 1
		NSLog(@"result %@", NSStringFromRect(rect));
#endif
		}
	// check for minimum width
	return rect;
}

- (NSRect) contentRectForFrameRect:(NSRect) frameRect
{
	frameRect=[NSWindow contentRectForFrameRect:frameRect styleMask:_w.styleMask];
	// FIXME: subtract toolbar height
	return frameRect;
}

- (NSRect) frameRectForContentRect:(NSRect) cRect
{
	cRect=[NSWindow frameRectForContentRect:cRect styleMask:_w.styleMask];
	// FIXME: add toolbar height
	return cRect;
}

- (NSRect) frame								{ return frame; }
- (NSSize) minSize								{ return _minSize; }
- (NSSize) maxSize								{ return _maxSize; }

- (void) setContentSize:(NSSize)aSize
{
	NSRect r={frame.origin, aSize};
	// limit to be larger than minSize and smaller than maxSize!
	[self setFrame:[self frameRectForContentRect:r] display:_w.visible];
}

- (void) setFrameTopLeftPoint:(NSPoint)aPoint
{
	[self setFrameOrigin:NSMakePoint(aPoint.x, aPoint.y-frame.size.height)];
}

- (void) setFrameOrigin:(NSPoint)aPoint
{
	if(!NSEqualPoints(aPoint, frame.origin))
		{
		NSRect r={aPoint, frame.size};
		[_context _setOrigin:r.origin];
		[self _setFrame:r];
		}
}

- (void) setFrame:(NSRect)r display:(BOOL)flag
{
	if(!NSEqualSizes(r.size, frame.size))
		{ // resize (and move)
		[_context _setOriginAndSize:r];	// set origin since we must "move" in X11 coordinates even if we resize only
		[self _setFrame:r];	// update content view etc.
		}
	else if(!NSEqualPoints(r.origin, frame.origin))
		{ // move only
		[_context _setOrigin:r.origin];
		[self _setFrame:r];	// update content view etc.
		}
	else if(flag)
		{ // no change, but display requested
		[self display];
		return;
		}
	else
		return;	// NOOP request
	if(flag)
		[self display];	// if requested in addition
}

- (void) _setFrame:(NSRect) rect
{ // this is also a callback from window manager
#if 0
	NSLog(@"_setFrame:%@", NSStringFromRect(rect));
#endif
	if(NSEqualRects(rect, frame))
		return;	// no change
	frame=rect;
	[(NSThemeFrame *) _themeFrame setFrameSize:rect.size];	// adjust theme frame and content View
	[(NSThemeFrame *) _themeFrame layout];
}

- (void) animation:(NSAnimation*) animation didReachProgressMark:(NSAnimationProgress) progress;
{
	NSRect v;	// velocity
	// calculate precise origin/size values which we need
	[self setFrame:v display:YES];	// setFrame and display
}

- (void) setFrame:(NSRect)rect display:(BOOL)flag animate:(BOOL)animate
{
	// FIXME: use NSAnimation to schedule
	if(NSEqualRects(rect, frame))
		return;	// no change
#if FIXME
	if(animate)
		{ // smooth resize
		static NSAnimation *a;
		NSRect v;	// velocity
		v.origin.x = rect.origin.x-frame.origin.x;
		v.origin.y = rect.origin.y-frame.origin.y;
		v.size.width = rect.size.width-frame.size.width;
		v.size.height = rect.size.height-frame.size.height;
		if(!a)
			{ // needs s new animation
			a=[[NSAnimation alloc] initWithDuration:[self animationResizeTime:rect]
									 animationCurve:0];
			[a setAnimationBlockingMode:NSAnimationNonblocking];
			[a setDelegate:self];
			}
//		targetFrame=rect;	// overwrite
		[a startAnimation];	// start (over)
		return;
		}
#endif
	[self setFrame:rect display:flag];	// just setFrame...
}

- (NSTimeInterval) animationResizeTime:(NSRect) rect
{
	static float t=0.0;
	float chg;	// pixels of change
	if(t == 0.0)
		{
		// replace by NSWindowResizeTime from NSUserDefaults if defined
		t=0.2;	// default
		t/=150.0;	// time per 150 pixels movement
		}
	chg = fabs(rect.origin.x-frame.origin.x);
	chg += fabs(rect.origin.y-frame.origin.y);
	chg += fabs(rect.size.width-frame.size.width);
	chg += fabs(rect.size.height-frame.size.height);
	return chg*t;
}

- (void) setMinSize:(NSSize)aSize				{ _minSize = aSize; }
- (void) setMaxSize:(NSSize)aSize				{ _maxSize = aSize; }
- (void) setResizeIncrements:(NSSize)aSize		{ resizeIncrements = aSize; }

- (NSAffineTransform *) _base2screen;
{ // return matrix to transform base coordinates to screen coordinates
	NSAffineTransform *atm=[NSAffineTransform transform];
	// FIXME: handle userSpaceScaling here?
	[atm translateXBy:frame.origin.x yBy:frame.origin.y];
#if 0
	NSLog(@"_base2screen=%@", atm);
#endif
	return atm;
}

- (NSPoint) convertBaseToScreen:(NSPoint)base
{
	return [[self _base2screen] transformPoint:base];
}

- (NSPoint) convertScreenToBase:(NSPoint)screen
{
	NSAffineTransform *atm=[[self _base2screen] copy];
	[atm invert];
	[atm autorelease];
	return [atm transformPoint:screen];
}

- (void) display
{
	if(!_w.visible)
		[self orderFront:nil];	// will call -update when window becomes mapped
	else
		{
		NSAutoreleasePool *arp=[NSAutoreleasePool new];	// collect all drawing temporaries here
		_w.needsDisplay = NO;	// reset first - display may result in callbacks that will set this flag again
		[self disableFlushWindow];						// tmp disable of display
		[_themeFrame displayIfNeeded];					// Draw the window view hierarchy (where changed)
		[self enableFlushWindow];						// Reenable displaying
		[self flushWindowIfNeeded];
		[arp release];
		}
}													

- (void) displayIfNeeded
{
	if(_w.needsDisplay) 
		[self display];
}

- (void) update
{
#if 0
	NSLog(@"%@ update %d %d", self, _w.autodisplay, _w.needsDisplay);
#endif
	if(_w.autodisplay && _w.needsDisplay && _w.visible)
		{ // if autodisplay is enabled and window needs display
#if 0
		NSLog(@"%@ update %@", self, [_themeFrame _descriptionWithSubviews]);
#endif
		[self display];
    	}
	[[NSNotificationCenter defaultCenter] postNotificationName:NSWindowDidUpdateNotification object:self];
}

- (void) _didExpose:(NSNotification *) n;
{ // some rect became visible and needs to be redrawn
	NSValue *val=[[n userInfo] objectForKey:@"NSExposedRect"];
	NSRect rect=[val rectValue];
	rect=[_themeFrame convertRect:rect fromView:nil];	// from window to theme frame
#if 1
	NSLog(@"%@ _didExpose:%@", self, NSStringFromRect(rect));
#endif
	[_themeFrame setNeedsDisplayInRect:rect];	// we know that we are the top-level view...
	if(!_w.needsDisplay)
		NSLog(@"window did expose but does not need to display? %@", self);
}

+ (void) _didExpose:(NSNotification *) n;
{ // pass to specified window
	[[n object] _didExpose:n];
}

- (void) flushWindowIfNeeded
{
	if (!_w.disableFlushWindow && _w.needsFlush) 
		[self flushWindow];
}

- (void) disableFlushWindow					{ _w.disableFlushWindow = YES; }
- (void) flushWindow						{ [_context flushGraphics]; }						
- (void) enableFlushWindow					{ _w.disableFlushWindow = NO; }
- (BOOL) isAutodisplay						{ return _w.autodisplay; }
- (BOOL) isFlushWindowDisabled				{ return _w.disableFlushWindow; }
- (void) setAutodisplay:(BOOL)flag			{ _w.autodisplay = flag; }
- (void) setViewsNeedDisplay:(BOOL)flag		{ _w.needsDisplay = flag; }
- (BOOL) viewsNeedDisplay					{ return _w.needsDisplay; }
- (void) useOptimizedDrawing:(BOOL)flag		{ _w.optimizeDrawing = flag; }
- (BOOL) canStoreColor						{ return (_w.depthLimit > 1); }
- (NSWindowDepth) depthLimit				{ return _w.depthLimit; }
- (BOOL) hasDynamicDepthLimit				{ return _w.dynamicDepthLimit; }
- (NSScreen *) screen						{ return _screen; }
- (NSScreen *) deepestScreen				{ return _screen?_screen:[NSScreen deepestScreen]; }
- (void) setDepthLimit:(NSWindowDepth)limit	{ _w.depthLimit = limit; }
- (void) setDynamicDepthLimit:(BOOL)flag	{ _w.dynamicDepthLimit = flag; }
- (int) resizeFlags							{ return 0; }

- (void) setDocumentEdited:(BOOL)flag
{
	_w.isEdited=flag;	// keep a local copy if we have no close button for any reason
	[(_NSThemeCloseWidget*) [(NSThemeFrame *) _themeFrame standardWindowButton:NSWindowCloseButton] setDocumentEdited:flag];
	[NSApp updateWindowsItem:self];	// modify menu state
	// we could/should forward to the backend...
}

- (void) setReleasedWhenClosed:(BOOL)flag
{
#if 0
	NSLog(@"%@: setReleasedWhenClosed:%d", _windowTitle, flag);
#endif
	_w.releasedWhenClosed = flag; 
}

- (BOOL) acceptsMouseMovedEvents			{ return _w.acceptsMouseMoved; }
- (BOOL) isExcludedFromWindowsMenu			{ return _w.menuExclude; }
- (void) setAcceptsMouseMovedEvents:(BOOL)f	{ _w.acceptsMouseMoved = f;}

- (void) setExcludedFromWindowsMenu:(BOOL)f
{
	if(_w.menuExclude == f)
		return;	// no change
	if((_w.menuExclude = f))
		[NSApp removeWindowsItem:self];	// now hidden
	else
		[NSApp addWindowsItem:self title:_windowTitle filename:NO];	// add
}

- (NSEvent *) currentEvent					{ return [NSApp currentEvent]; }
- (id) delegate								{ return _delegate; }

- (void) setDelegate:(id)anObject
{
	NSNotificationCenter *n;

	if(_delegate == anObject)
		return;

#define IGNORE_(notif_name) [n removeObserver:_delegate \
								name:NSWindow##notif_name##Notification \
								object:self]

	n = [NSNotificationCenter defaultCenter];
	if (_delegate)
		{
		IGNORE_(DidBecomeKey);
		IGNORE_(DidBecomeMain);
		IGNORE_(DidChangeScreen);
		IGNORE_(DidDeminiaturize);
		IGNORE_(DidExpose);
		IGNORE_(DidMiniaturize);
		IGNORE_(DidMove);
		IGNORE_(DidResignKey);
		IGNORE_(DidResignMain);
		IGNORE_(DidResize);
		IGNORE_(DidUpdate);
		IGNORE_(WillClose);
		IGNORE_(WillMiniaturize);
		}

	ASSIGN(_delegate, anObject);
	if(!anObject)
		return;

#define OBSERVE_(notif_name) \
	if ([_delegate respondsToSelector:@selector(window##notif_name:)]) \
		[n addObserver:_delegate \
		   selector:@selector(window##notif_name:) \
		   name:NSWindow##notif_name##Notification \
		   object:self]

	OBSERVE_(DidBecomeKey);
	OBSERVE_(DidBecomeMain);
	OBSERVE_(DidChangeScreen);
	OBSERVE_(DidDeminiaturize);
	OBSERVE_(DidExpose);
	OBSERVE_(DidMiniaturize);
	OBSERVE_(DidMove);
	OBSERVE_(DidResignKey);
	OBSERVE_(DidResignMain);
	OBSERVE_(DidResize);
	OBSERVE_(DidUpdate);
	OBSERVE_(WillClose);
	OBSERVE_(WillMiniaturize);
	OBSERVE_(WillMove);
}

- (void) discardCursorRects
{
	[_cursorRects removeAllObjects];
}

- (void) invalidateCursorRectsForView:(NSView *)aView
{
	if(aView)
		{
		if(_w.isKey)
			{
			[aView discardCursorRects];
			[aView resetCursorRects];
			}
		else
			_w.cursorRectsValid = NO;
		}
}

- (void) resetCursorRects
{
	[self discardCursorRects];
	[_themeFrame resetCursorRects];
	_w.cursorRectsValid = YES;
}

- (void) disableCursorRects					{ _w.cursorRectsEnabled = NO; }
- (void) enableCursorRects					{ _w.cursorRectsEnabled = YES; }
- (BOOL) areCursorRectsEnabled				{ return _w.cursorRectsEnabled; }
- (BOOL) isDocumentEdited					{ return _w.isEdited; }
- (BOOL) isReleasedWhenClosed				{ return _w.releasedWhenClosed; }
- (BOOL) isZoomed							{ return _w.isZoomed; }

- (void) miniaturize:(id)sender
{
	if(_w.miniaturized)
		return;
	[[NSNotificationCenter defaultCenter] postNotificationName: NOTE(WillMiniaturize) object:self];
	_w.miniaturized = YES; 
	[_context _miniaturize];
	[[NSNotificationCenter defaultCenter] postNotificationName: NOTE(DidMiniaturize) object:self];
}

- (void) deminiaturize:(id)sender
{
	if(!_w.miniaturized)
		return;
	_w.miniaturized = NO;
	[_context _deminiaturize];
	[[NSNotificationCenter defaultCenter] postNotificationName: NOTE(DidDeminiaturize) object:self];
}

- (void) zoom:(id)sender
{
	NSLog(@"Zoom");
	if(_w.isZoomed)
		{
		}
	else
		{
		}
}

- (void) close
{
#if 0
	NSLog(@"close %@", self);
	NSLog(@"retain count %d", [self retainCount]);
	if(_w.releasedWhenClosed)
		NSLog(@"close %@: releasedWhenClosed", _windowTitle);
#endif
	// Notify window's delegate
	[[NSNotificationCenter defaultCenter] postNotificationName:NSWindowWillCloseNotification object:self];
	[self orderOut:self];	// might dealloc graphics context
	[NSApp removeWindowsItem:self];
	if(_w.releasedWhenClosed)	// do so.  Default is YES for windows and NO for panels
		{
		// FIXME: handle the terminate on last window closed mechanism
		// FIXME: if app has no menu
		//	if(![NSApp mainMenu] && _w.releasedWhenClosed)	// terminate
		//		[NSApp terminate:self];
#if 0
		NSLog(@"close %@: releasedWhenClosed", _windowTitle);
		NSLog(@"our retain count %d", [self retainCount]);
#endif
		[self autorelease]; 
		}
}

- (void) _close:(id)sender									
{
#if 0
	NSLog(@"_close");
#endif
	if(!(_w.styleMask & NSClosableWindowMask))
		{											// self must have a close
		NSBeep();									// button in order to be
		return;										// closed
		}
	if([_delegate respondsToSelector:@selector(windowShouldClose:)])
		{											// if delegate responds to
    	if(![_delegate windowShouldClose:self])		// windowShouldClose query
			{										// it to see if it's ok to
			NSBeep();								// close the window
			return;									
			}
		}
	else
		{
		if([self respondsToSelector:@selector(windowShouldClose:)])
			{										// else if self (i.e. a subclass of NSWindow) responds to
			if(![self windowShouldClose:self])		// windowShouldClose query
				{									// self to see if it's ok
				NSBeep();							// to close self
				return;								
				}
			}
		} 
	[self close];									// it's ok to close self								
}

- (void) performClose:(id)sender									
{
	// FIXME: should highlight miniaturize button temporarily
	[self _close:sender];
}

- (void) performMiniaturize:(id)sender									
{
	// FIXME: should highlight miniaturize button temporarily
	[self miniaturize:sender];
}

- (void) performZoom:(id)sender									
{
	// FIXME: should highlight zoom button temporarily
	[self zoom:sender];
}

- (void) discardEventsMatchingMask:(unsigned int)mask
					   beforeEvent:(NSEvent *)lastEvent
{
	[NSApp discardEventsMatchingMask:mask beforeEvent:lastEvent];
}

- (void) doCommandBySelector:(SEL) sel;
{
	if([self respondsToSelector:sel])
		[self performSelector:sel withObject:nil];
	else if(_nextResponder)
		[_nextResponder doCommandBySelector:sel];	// pass down
	else if(_delegate && [self respondsToSelector:_cmd])
		[_delegate doCommandBySelector:sel];		// pass down
	else
		[self noResponderFor:sel];	// Beep
}

#if 0	// FIX ME should provide default handling per NSResponder docs
- (void) keyDown:(NSEvent *)event					
{											
	switch([event keyCode])
		{
		case '\t':			// Tab
			[self selectNextKeyView:self];
			break;
		default:								// FIX ME should provide default
			NSBeep();							// handling per NSResponder docs
		}
}													
#endif

- (NSResponder *) firstResponder			{ return _firstResponder; }
- (BOOL) acceptsFirstResponder				{ return YES; }

- (BOOL) makeFirstResponder:(NSResponder *)aResponder
{
#if 1
	NSLog(@"makeFirstResponder: %@", aResponder);
#endif
	if (_firstResponder == aResponder)				// if responder is already
		return YES;									// first responder return Y

	if(!aResponder)
		aResponder=self;
	if (![aResponder isKindOfClass: __responderClass])
		return NO;									// not a responder return N

	if (![aResponder acceptsFirstResponder])		
		return NO;									// does not accept status

	if (_firstResponder)
		{ // resign first responder status
		NSResponder *first = _firstResponder;

		_firstResponder = nil;
		if (![first resignFirstResponder])			// the first responder must
			{										// agree to resign
			_firstResponder = first;	// did not!
			return NO;
			}
		}
	
	if (__cursorHidden)
		[NSCursor unhide];
	__cursorHidden = NO;

	if (_firstResponder == aResponder)				// in case resignFirstResponder already set
		return YES;									// a new first responder

	if([(_firstResponder = aResponder) becomeFirstResponder])
		return YES;									// Notify responder of it's	
													// new status, make window
	_firstResponder = self;							// first if it refuses

	return NO;
}

- (NSEvent *) nextEventMatchingMask:(unsigned int)mask
{
	return [NSApp nextEventMatchingMask:mask 
							  untilDate:[NSDate distantFuture]
								 inMode:NSEventTrackingRunLoopMode 
								dequeue:YES];
}

- (NSEvent *) nextEventMatchingMask:(unsigned int)mask
						  untilDate:(NSDate *)expiration
						  inMode:(NSString *)mode
						  dequeue:(BOOL)deqFlag
{
	return [NSApp nextEventMatchingMask:mask 
							  untilDate:expiration
								 inMode:mode 
								dequeue:deqFlag];
}

- (void) postEvent:(NSEvent *)event atStart:(BOOL)flag
{
	[NSApp postEvent:event atStart:flag];
}

- (BOOL) shouldBeTreatedAsInkEvent:(NSEvent *) theEvent;
{ // permit ink-anywhere
	_lastLeftHit=[_themeFrame hitTest:[theEvent locationInWindow]];	// cache
	return [_lastLeftHit shouldBeTreatedAsInkEvent:theEvent];	// pass to view under pen (subview of theme frame)
}

- (void) sendEvent:(NSEvent *)event
{
	if (!_w.cursorRectsValid)
		[self resetCursorRects];

	switch ([event type])
    	{													
		case NSAppKitDefined:	// Focus In
			[_firstResponder becomeFirstResponder];
			if (!_w.isKey)
				[self makeKeyAndOrderFront:self];
			break;

		case NSLeftMouseDown:								// Left mouse down
			if (__cursorHidden)
				{ 
				[NSCursor unhide]; 
				__cursorHidden = NO; 
				}
//			_lastLeftHit = [_themeFrame hitTest:[event locationInWindow]];	// this assumes that we have already called shouldBeTreatedAsInkEvent!
			NSDebugLog([_lastLeftHit description]);
#if 0
			NSLog(@"NSLeftMouseDown: %@", event);
			NSLog(@"  locationInWindow=%@", NSStringFromPoint([event locationInWindow]));
			NSLog(@"  _themeFrame=%@", _themeFrame);
			NSLog(@"  _lastLeftHit=%@", _lastLeftHit);
#endif
			// FIXME: we should check for window movement and resize here so that we can honor [_lastleftHit mouseDownCanMoveWindow]

			if((NSResponder *) _lastLeftHit != _firstResponder && [(NSResponder *) _lastLeftHit acceptsFirstResponder])
				[self makeFirstResponder:_lastLeftHit];		// make hit view first responder if not already and if it accepts
			if(_w.isKey)
				[_lastLeftHit mouseDown:event];
			else
				{ // first click makes it the key window
				if(![_lastLeftHit shouldDelayWindowOrderingForEvent:event])
					[self makeKeyAndOrderFront:self];	// bring clicked window to front
				else
					[NSApp _setPendingWindow:self];		// register for delayed ordering
				if([_lastLeftHit acceptsFirstMouse:event])
					[_lastLeftHit mouseDown:event];
				}
			break;

		case NSLeftMouseUp:									// Left mouse up
#if 0
			NSLog(@"NSLeftMouseUp %@", _lastLeftHit);
#endif
			if (__cursorHidden)
				{ 
				[NSCursor unhide]; 
				__cursorHidden = NO;
				}
			[_lastLeftHit mouseUp:event];
			break;

		case NSRightMouseDown:								// Right mouse down
			if (__cursorHidden)
				{ [NSCursor unhide]; __cursorHidden = NO; }
			_lastRightHit = [_themeFrame hitTest:[event locationInWindow]];
			[_lastRightHit rightMouseDown:event];
			break;

		case NSRightMouseUp:								// Right mouse up
			if (__cursorHidden)
				{ [NSCursor unhide]; __cursorHidden = NO; }
			[_lastRightHit rightMouseUp:event];
			break;

		case NSMouseMoved:									// Mouse moved
			if (__cursorHidden)
				{ [NSCursor unhide]; __cursorHidden = NO; }
			if(_w.acceptsMouseMoved)
				{
				NSView *v = [_themeFrame hitTest:[event locationInWindow]];
				[v mouseMoved:event];				// hit view passes event up
				}									// responder chain to self
			else									// if we accept mouse moved
				if(_w.cursorRectsEnabled)
					[self mouseMoved:event];
			break;

		case NSLeftMouseDragged:									// Mouse moved
#if 0
			NSLog(@"NSLeftMouseDragged %@", _lastLeftHit);
#endif
			[_lastLeftHit mouseDragged:event];
			break;
			
		case NSRightMouseDragged:									// Mouse moved
			[_lastRightHit mouseDragged:event];
			break;
			
		case NSKeyDown:										// Key down
			{
			__lastKeyDown = _firstResponder;	// save the first responder so that the key up goes to it and not a possible new first responder
			if(!__cursorHidden)
				{
				if([_firstResponder respondsToSelector:@selector(isEditable)] &&
				   [(NSText *) _firstResponder isEditable] &&
				   (__cursorHidden = [NSCursor isHiddenUntilMouseMoves]))
					[NSCursor hide];
				}
#if 1
			NSLog(@"first Responder %@ keyDown %@", _firstResponder, event);
#endif
			[_firstResponder keyDown:event];
			break;
			}

		case NSKeyUp:
			if (__lastKeyDown)
				[__lastKeyDown keyUp:event];		// send Key Up to object that got the key down
			__lastKeyDown = nil;
			break;

		case NSScrollWheel:
		    [[_themeFrame hitTest:[event locationInWindow]] scrollWheel:event];
			break;

		case NSCursorUpdate:
			if([event trackingNumber])						// a mouse entered
				[(id)[event userData] push];				// push the cursor
			else
				[NSCursor pop];								// a mouse exited
															// pop the cursor
		default:
			break;
		}
}

- (BOOL) performKeyEquivalent:(NSEvent*)event
{
#if 0
	BOOL r=[_themeFrame performKeyEquivalent:event];
	NSLog(@"%@ performKeyEquivalent -> %@", self, r?@"YES":@"NO");
	return r;
#else
	return [_themeFrame performKeyEquivalent:event];
#endif
}

- (BOOL) tryToPerform:(SEL)anAction with:anObject
{
	return [super tryToPerform:anAction with:anObject];
}

- (BOOL) worksWhenModal
{
	return NO;
}

- (void) dragImage:(NSImage *)anImage						// Drag and Drop
				at:(NSPoint)baseLocation
				offset:(NSSize)initialOffset
				event:(NSEvent *)event
				pasteboard:(NSPasteboard *)pboard
				source:sourceObject
				slideBack:(BOOL)slideFlag		{ BACKEND }

- (void) registerForDraggedTypes:(NSArray *)newTypes
{
	[_themeFrame registerForDraggedTypes:newTypes];
}

- (void) unregisterDraggedTypes		
{ 
	[_themeFrame unregisterDraggedTypes];
}

- (void) concludeDragOperation:(id <NSDraggingInfo>)sender
{
	if(_delegate)
		if ([_delegate respondsToSelector:@selector(concludeDragOperation:)])
			[_delegate concludeDragOperation:sender];
}

- (unsigned int) draggingEntered:(id <NSDraggingInfo>)sender
{
	if(_delegate && [_delegate respondsToSelector:@selector(draggingEntered:)])
		return [_delegate draggingEntered:sender];

	return NSDragOperationNone;
}

- (void) draggingExited:(id <NSDraggingInfo>)sender
{
	if (_delegate && [_delegate respondsToSelector:@selector(draggingExited:)])
		[_delegate draggingExited:sender];
}

- (unsigned int) draggingUpdated:(id <NSDraggingInfo>)sender
{
	if(_delegate && [_delegate respondsToSelector:@selector(draggingUpdated:)])
		return [_delegate draggingUpdated:sender];

	return NSDragOperationNone;
}

- (BOOL) performDragOperation:(id <NSDraggingInfo>)sender
{
	if(_delegate)
		if ([_delegate respondsToSelector:@selector(performDragOperation:)])
			return [_delegate performDragOperation:sender];

	return NO;
}

- (BOOL) prepareForDragOperation:(id <NSDraggingInfo>)sender
{
	if(_delegate)
		if ([_delegate respondsToSelector:@selector(prepareForDragOperation:)])
			return [_delegate prepareForDragOperation:sender];

	return NO;
}

- (id) validRequestorForSendType:(NSString *)sendType		// Services menu
					  returnType:(NSString *)returnType
{
id result = nil;

	if (_delegate && [_delegate respondsToSelector: _cmd])
		result = [_delegate validRequestorForSendType: sendType
							returnType: returnType];

	if (result == nil)
		result = [NSApp validRequestorForSendType: sendType 
						returnType: returnType];
	return result;
}

+ (void) removeFrameUsingName:(NSString *)name			// Save / restore frame	
{
	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	NSString *key = [NSString stringWithFormat:@"NSWindow Frame %@",name];

	[defaults removeObjectForKey:key];
	[defaults synchronize];
	[__frameNames removeObjectForKey:name];
}

- (BOOL) setFrameAutosaveName:(NSString *)name
{
	if(!__frameNames)
		__frameNames = [NSMutableDictionary new];

	if([__frameNames objectForKey:name])
		return NO;

	ASSIGN(_frameSaveName, name);
	[__frameNames setObject:self forKey:name];

	return YES;
}

- (NSString *) frameAutosaveName			{ return _frameSaveName; }

- (void) saveFrameUsingName:(NSString *)name
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *key = [NSString stringWithFormat:@"NSWindow Frame %@",name];
		
	NSDebugLog(@"saveFrameUsingName %@\n",[NSValue valueWithRect:frame]);

	[defaults setObject:[NSValue valueWithRect:frame] forKey:key];
	[defaults synchronize];
}

- (BOOL) setFrameUsingName:(NSString *)name	
{
	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	NSString *key = [NSString stringWithFormat:@"NSWindow Frame %@",name];
	NSString *value = [defaults stringForKey:key];

	if(!value)
		return NO;

	NSDebugLog(@"setFrameUsingName %@\n", value);
	[self setFrameFromString: value];

	return YES;
}

- (void) setFrameFromString:(NSString *)string
{
	NSDictionary *d = [string propertyList];
	NSRect r;
#if 0
	NSLog(@"NSWindow setFrameFromString %@\n", string);
#endif
	r.origin.x = [[d objectForKey:@"x"] floatValue];
	r.origin.y = [[d objectForKey:@"y"] floatValue];
	r.size.width = [[d objectForKey:@"width"] floatValue];
	r.size.height = [[d objectForKey:@"height"] floatValue];
	r.size.width = MIN(MAX(r.size.width, _minSize.width), _maxSize.width);
	r.size.height = MIN(MAX(r.size.height, _minSize.height), _maxSize.height);

	if(_delegate)
		{
		if ([_delegate respondsToSelector:@selector(windowWillResize:toSize:)])
			r.size = [_delegate windowWillResize:self toSize:r.size];
		}
	[self setFrame:r display:NO];
}

- (NSString *) stringWithSavedFrame				
{ 
	return [[NSValue valueWithRect:frame] description]; 
}

- (void) print:(id) sender
{
	NSPrintOperation *po=[NSPrintOperation printOperationWithView:[(NSThemeFrame *) _themeFrame contentView]];
	[po runOperationModalForWindow:self delegate:nil didRunSelector:_cmd contextInfo:NULL];
}

- (NSString *) description;
{
	return [NSString stringWithFormat:@"%@ [%lu]: title=%@ frame=%@",
		NSStringFromClass([self class]),
		[_context _windowNumber],
		[self title],
		NSStringFromRect(frame)];
}

- (NSView *) initialFirstResponder			{ return _initialFirstResponder; }

- (void) setInitialFirstResponder:(NSView *)aView
{
	_initialFirstResponder = aView;
}

- (void) selectNextKeyView:(id)sender
{
id next;

	if(_firstResponder && _firstResponder != self)
		next = [(NSView *)_firstResponder nextValidKeyView];
	else
		if((next = _initialFirstResponder) && ![next acceptsFirstResponder])
			next = [(NSView *)_initialFirstResponder nextValidKeyView];

	if(next && [self makeFirstResponder:next])
		{
		if([next respondsToSelector:@selector(selectText:)])
			[(NSTextField *)next selectText:self];
		}
	else
		NSBeep();
}

- (void) selectPreviousKeyView:(id)sender
{
id prev;

	if(_firstResponder && _firstResponder != self)
		prev = [(NSView *)_firstResponder previousValidKeyView];
	else
		if((prev = _initialFirstResponder) && ![prev acceptsFirstResponder])
			prev = [(NSView *)_initialFirstResponder previousValidKeyView];

	if(prev && [self makeFirstResponder:prev])
		{
		if([prev respondsToSelector:@selector(selectText:)])
			[(NSTextField *)prev selectText:self];
		}
	else
		NSBeep();
}

- (void) selectKeyViewFollowingView:(NSView *)aView
{
	if((aView = [aView nextValidKeyView]) && [self makeFirstResponder:aView] && [aView respondsToSelector:@selector(selectText:)])
		[(NSTextField *)aView selectText:self];
}

- (void) selectKeyViewPrecedingView:(NSView *)aView
{
	if((aView = [aView previousValidKeyView]) && [self makeFirstResponder:aView] && [aView respondsToSelector:@selector(selectText:)])
		[(NSTextField *)aView selectText:self];
}

- (void) encodeWithCoder:(NSCoder *)aCoder				// NSCoding protocol
{
	int _windowNum=[self windowNumber];
	[super encodeWithCoder:aCoder];
	
	NSDebugLog(@"NSWindow: start encoding\n");
	[aCoder encodeRect:frame];
	[aCoder encodeObject:_themeFrame];
	[aCoder encodeObject:_initialFirstResponder];
//  [aCoder encodeObjectReference: _delegate withName:NULL];
	[aCoder encodeValueOfObjCType:"i" at:&_windowNum];
//	[aCoder encodeObject:_backgroundColor];
	[aCoder encodeObject:_representedFilename];
	[aCoder encodeObject:_miniWindowTitle];
	[aCoder encodeObject:_windowTitle];
	[aCoder encodeSize:_minSize];
	[aCoder encodeSize:_maxSize];
	[aCoder encodeObject:_miniWindowImage];
	[aCoder encodeValueOfObjCType:@encode(int) at: &_level];
	[aCoder encodeValueOfObjCType:@encode(unsigned int) at: &_w];
}

- (id) initWithCoder:(NSCoder *)aDecoder
{
	// FIXME: we will only decode NSWindowTemplate from NIBs and doc says that this should create an error message!
	int _windowNum;
	self=[super initWithCoder:aDecoder];
	if([aDecoder allowsKeyedCoding])
		return NIMP;
	
	NSDebugLog(@"NSWindow: start decoding\n");
	frame = [aDecoder decodeRect];
	_themeFrame = [aDecoder decodeObject];
	_initialFirstResponder = [aDecoder decodeObject];
//  [aDecoder decodeObjectAt: &_delegate withName:NULL];
	[aDecoder decodeValueOfObjCType:"i" at:&_windowNum];
	[self setBackgroundColor:[aDecoder decodeObject]];
	_representedFilename = [aDecoder decodeObject];
	_miniWindowTitle = [aDecoder decodeObject];
	_windowTitle = [aDecoder decodeObject];
	_minSize = [aDecoder decodeSize];
	_maxSize = [aDecoder decodeSize];
	_miniWindowImage = [aDecoder decodeObject];
	[aDecoder decodeValueOfObjCType:@encode(int) at: &_level];
	[aDecoder decodeValueOfObjCType:@encode(unsigned int) at: &_w];

								// FIX ME do this here or in awakeFromCoder ?
	[NSApp addWindowsItem:self title:nil filename:NO];

	return self;
}

- (void) setWindowController:(NSWindowController *)windowController; { ASSIGN(_windowController, windowController); }
- (id) windowController; { return _windowController; }

+ (NSButton *) standardWindowButton:(NSWindowButton) type forStyleMask:(unsigned int) aStyle;
{
	NSButton *b=nil;
	static NSSize smallImage={ 15.0, 15.0 };
	float button=[self _titleBarHeightForStyleMask:aStyle];
	// set style dependent windget cell, i.e. brushed metal
	switch(type)
		{
		case NSWindowCloseButton:
			b=[[_NSThemeCloseWidget alloc] initWithFrame:NSMakeRect(4.0, 0.0, button, button) forStyleMask:aStyle];
			[b setAction:@selector(_close:)];
			[b setEnabled:(aStyle&NSClosableWindowMask) != 0];
			[b setImage:[NSImage imageNamed:@"NSWindowCloseButton"]];
//			[[b cell] setBackgroundColor:[NSColor redColor]];
			[b setTitle:@"x"];
			[b setAutoresizingMask:NSViewMaxXMargin|NSViewMinYMargin];
			break;
		case NSWindowMiniaturizeButton:
			b=[[_NSThemeWidget alloc] initWithFrame:NSMakeRect(3.0+button, 0.0, button, button) forStyleMask:aStyle];
			[b setAction:@selector(miniaturize:)];
			[b setEnabled:(aStyle&NSMiniaturizableWindowMask) != 0];
			[b setImage:[NSImage imageNamed:@"NSWindowMiniaturizeButton"]];
			[b setTitle:@"-"];
			[b setAutoresizingMask:NSViewMaxXMargin|NSViewMinYMargin];
			break;
		case NSWindowZoomButton:
			b=[[_NSThemeWidget alloc] initWithFrame:NSMakeRect(2.0+2.0*button, 0.0, button, button) forStyleMask:aStyle];
			[b setAction:@selector(zoom:)];
			[b setEnabled:(aStyle&NSResizableWindowMask) != 0];
			[b setImage:[NSImage imageNamed:@"NSWindowZoomButton"]];
			[b setTitle:@"+"];
			[b setAutoresizingMask:NSViewMaxXMargin|NSViewMinYMargin];
			break;
		case NSWindowToolbarButton:
			b=[[_NSThemeWidget alloc] initWithFrame:NSMakeRect(100.0, 0.0, button, button) forStyleMask:aStyle];	// we must adapt the origin when using this button!
			[b setAction:@selector(toggleToolbarShown:)];
			[b setEnabled:YES];
			[b setImage:[NSImage imageNamed:@"NSWindowToolbarButton"]];
			[b setTitle:@""];
			[b setAutoresizingMask:NSViewMinXMargin|NSViewMinYMargin];
			break;
		case NSWindowDocumentIconButton:
			// make centered button
			// set text font as required by size
			return nil;
		}
	[b setImagePosition:NSImageOverlaps];
	if(aStyle & NSUtilityWindowMask)
		{
		NSImage *i=[[b image] copy];
		// [b setFrameSize:small];
		[i setSize:smallImage];	// scale button image
		[i setScalesWhenResized:YES];
		[b setImage:i];	// store a copy
		[i release];
		[b setNeedsDisplay:YES];
		}
	return [b autorelease];
}

- (float) userSpaceScaleFactor;
{ // value defined in NSScreen profile
	return [_screen userSpaceScaleFactor];
}

- (void) setShowsResizeIndicator:(BOOL) flag;
{
	NIMP;
}

- (void) setShowsToolbarButton:(BOOL) flag;
{
	NIMP;
}

- (BOOL) showsResizeIndicator;
{
	NIMP; return NO;
}

- (BOOL) showsToolbarButton;
{
	NIMP; return NO;
}

- (NSButton *) standardWindowButton:(NSWindowButton) button;
{
	return [(NSThemeFrame *) _themeFrame standardWindowButton:button];
}

- (void) enableKeyEquivalentForDefaultButtonCell
{
	[_defaultButtonCell setKeyEquivalent:@"\r"];
}

- (void) disableKeyEquivalentForDefaultButtonCell
{
	[_defaultButtonCell setKeyEquivalent:@""];
}

- (void) setDefaultButtonCell:(NSButtonCell *) cell
{
	_defaultButtonCell=cell;
	[self enableKeyEquivalentForDefaultButtonCell];
}

- (NSButtonCell *) defaultButtonCell; { return _defaultButtonCell; }

- (NSPoint) mouseLocationOutsideOfEventStream
{ // ask backend for relative mouse position (might be outside of the Window!)
	return [_context _mouseLocationOutsideOfEventStream];
}

+ (void) menuChanged:(NSMenu *)aMenu; { return; } // does nothing for backward compatibility


@end /* NSWindow */
