apps-gorm/Gorm.m

1000 lines
23 KiB
Mathematica
Raw Normal View History

/* Gorm.m
*
* Copyright (C) 1999 Free Software Foundation, Inc.
*
* Author: Richard Frith-Macdonald <richard@brainstrom.co.uk>
* Date: 1999
*
* This file is part of GNUstep.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "GormPrivate.h"
NSString *IBWillBeginTestingInterfaceNotification
= @"IBWillBeginTestingInterfaceNotification";
NSString *IBDidBeginTestingInterfaceNotification
= @"IBDidBeginTestingInterfaceNotification";
NSString *IBWillEndTestingInterfaceNotification
= @"IBWillEndTestingInterfaceNotification";
NSString *IBDidEndTestingInterfaceNotification
= @"IBDidEndTestingInterfaceNotification";
NSString *GormLinkPboardType = @"GormLinkPboardType";
@class InfoPanel;
@implementation Gorm
- (id<IBDocuments>) activeDocument
{
unsigned i = [documents count];
if (i > 0)
{
while (i-- > 0)
{
id doc = [documents objectAtIndex: i];
if ([doc isActive] == YES)
{
return doc;
}
}
}
return nil;
}
- (BOOL) applicationShouldTerminate: (NSApplication*)sender
{
NSEnumerator *enumerator = [[self windows] objectEnumerator];
NSWindow *win;
BOOL edited = NO;
while ((win = [enumerator nextObject]) != nil)
{
if ([win isDocumentEdited] == YES)
{
edited = YES;
}
}
if (edited == YES)
{
int result;
result = NSRunAlertPanel(NULL, @"There are edited windows",
@"Review Unsaved", @"Cancel", @"Quit Anyway");
if (result == NSAlertAlternateReturn)
{
return NO;
}
else if (result != NSAlertOtherReturn)
{
enumerator = [[self windows] objectEnumerator];
while ((win = [enumerator nextObject]) != nil)
{
if ([win isDocumentEdited] == YES)
{
[win performClose: self];
}
}
}
}
return YES;
}
- (GormClassManager*) classManager
{
if (classManager == nil)
{
classManager = [GormClassManager new];
}
return classManager;
}
- (id) close: (id)sender
{
NSWindow *window = [(id)[self activeDocument] window];
[window setReleasedWhenClosed: YES];
[window performClose: self];
return nil;
}
- (id) copy: (id)sender
{
if ([[selectionOwner selection] count] == 0
|| [selectionOwner respondsToSelector: @selector(copySelection)] == NO)
return nil;
[selectionOwner copySelection];
return self;
}
- (id) connectDestination
{
return connectDestination;
}
- (id) connectSource
{
return connectSource;
}
- (id) cut: (id)sender
{
if ([[selectionOwner selection] count] == 0
|| [selectionOwner respondsToSelector: @selector(copySelection)] == NO
|| [selectionOwner respondsToSelector: @selector(deleteSelection)] == NO)
return nil;
[selectionOwner copySelection];
[selectionOwner deleteSelection];
return self;
}
- (void) dealloc
{
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc removeObserver: self];
RELEASE(infoPanel);
RELEASE(inspectorsManager);
RELEASE(palettesManager);
RELEASE(documents);
RELEASE(classManager);
[super dealloc];
}
- (id) delete: (id)sender
{
if ([[selectionOwner selection] count] == 0
|| [selectionOwner respondsToSelector: @selector(deleteSelection)] == NO)
return nil;
[selectionOwner deleteSelection];
return self;
}
- (void) displayConnectionBetween: (id)source and: (id)destination
{
NSWindow *w;
NSRect r;
if (source != connectSource)
{
if (connectSource != nil)
{
w = [[self activeDocument] windowAndRect: &r
forObject: connectSource];
if (w != nil)
{
NSView *wv = [[w contentView] superview];
/*
* Erase image from old location.
*/
r.origin.x -= 1.0;
r.origin.y += 1.0;
r.size = [sourceImage size];
r.size.width += 2.0;
r.size.height += 2.0;
[wv lockFocus];
[wv displayRect: r];
[wv unlockFocus];
[w flushWindow];
}
}
connectSource = source;
}
if (connectSource != nil)
{
w = [[self activeDocument] windowAndRect: &r forObject: connectSource];
if (w != nil)
{
NSView *wv = [[w contentView] superview];
[wv lockFocus];
[sourceImage compositeToPoint: r.origin
operation: NSCompositeCopy];
[wv unlockFocus];
[w flushWindow];
}
}
if (destination != connectDestination)
{
if (connectDestination != nil)
{
w = [[self activeDocument] windowAndRect: &r
forObject: connectDestination];
if (w != nil)
{
NSView *wv = [[w contentView] superview];
/*
* Erase image from old location.
*/
r.origin.x -= 1.0;
r.origin.y += 1.0;
r.size = [targetImage size];
r.size.width += 2.0;
r.size.height += 2.0;
[wv lockFocus];
[wv displayRect: r];
[wv unlockFocus];
[w flushWindow];
}
}
connectDestination = destination;
}
if (connectDestination != nil)
{
w = [[self activeDocument] windowAndRect: &r
forObject: connectDestination];
if (w != nil)
{
NSView *wv = [[w contentView] superview];
[wv lockFocus];
[targetImage compositeToPoint: r.origin
operation: NSCompositeCopy];
[wv unlockFocus];
[w flushWindow];
}
}
}
- (id) endTesting: (id)sender
{
if (isTesting == NO)
{
return nil;
}
else
{
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
NSUserDefaults *defs;
NSEnumerator *e;
id val;
CREATE_AUTORELEASE_POOL(pool);
[nc postNotificationName: IBWillEndTestingInterfaceNotification
object: self];
/*
* Make sure windows will go away when the container is destroyed.
*/
e = [[testContainer nameTable] objectEnumerator];
while ((val = [e nextObject]) != nil)
{
if ([val isKindOfClass: [NSWindow class]] == YES)
{
[val close];
}
}
defs = [NSUserDefaults standardUserDefaults];
[defs setObject: menuLocations forKey: @"NSMenuLocations"];
DESTROY(menuLocations);
[self setMainMenu: mainMenu];
DESTROY(testContainer);
isTesting = NO;
if ([selectionOwner conformsToProtocol: @protocol(IBEditors)] == YES)
{
[(id<IBEditors>)selectionOwner makeSelectionVisible: YES];
}
[nc postNotificationName: IBDidEndTestingInterfaceNotification
object: self];
RELEASE(pool);
return self;
}
}
- (void) finishLaunching
{
NSMenu *aMenu;
NSMenu *modulesMenu;
NSMenu *windowsMenu;
NSMenuItem *menuItem;
NSBundle *bundle;
NSString *path;
/*
* establish registration domain defaults from file.
*/
bundle = [NSBundle mainBundle];
path = [bundle pathForResource: @"Defaults" ofType: @"plist"];
if (path != nil)
{
NSDictionary *dict;
dict = [NSDictionary dictionaryWithContentsOfFile: path];
if (dict != nil)
{
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
[defs registerDefaults: dict];
}
}
mainMenu = [[NSMenu alloc] initWithTitle: @"Gorm"];
/*
* Set up info menu.
*/
aMenu = [NSMenu new];
[aMenu addItemWithTitle: @"Info Panel..."
action: @selector(infoPanel:)
keyEquivalent: @""];
[aMenu addItemWithTitle: @"Preferences..."
action: NULL
keyEquivalent: @""];
[aMenu addItemWithTitle: @"Help..."
action: NULL
keyEquivalent: @"?"];
menuItem = [mainMenu addItemWithTitle: @"Info"
action: NULL
keyEquivalent: @""];
[mainMenu setSubmenu: aMenu forItem: menuItem];
RELEASE(aMenu);
/*
* Set up document menu.
*/
aMenu = [NSMenu new];
[aMenu addItemWithTitle: @"Open..."
action: @selector(open:)
keyEquivalent: @"o"];
[aMenu addItemWithTitle: @"New Application"
action: @selector(newApplication:)
keyEquivalent: @"n"];
modulesMenu = [NSMenu new];
[modulesMenu addItemWithTitle: @"New Empty"
action: @selector(newEmpty:)
keyEquivalent: @"N"];
[modulesMenu addItemWithTitle: @"New Inspector"
action: @selector(newInspector:)
keyEquivalent: @""];
[modulesMenu addItemWithTitle: @"New Palette"
action: @selector(newPalette:)
keyEquivalent: @""];
menuItem = [aMenu addItemWithTitle: @"New Module"
action: NULL
keyEquivalent: @""];
[aMenu setSubmenu: modulesMenu forItem: menuItem];
RELEASE(modulesMenu);
[aMenu addItemWithTitle: @"Save"
action: @selector(save:)
keyEquivalent: @"s"];
[aMenu addItemWithTitle: @"Save As..."
action: @selector(saveAs:)
keyEquivalent: @"S"];
[aMenu addItemWithTitle: @"Save All"
action: @selector(saveAll:)
keyEquivalent: @""];
[aMenu addItemWithTitle: @"Revert to Saved"
action: @selector(revertToSaved:)
keyEquivalent: @"u"];
[aMenu addItemWithTitle: @"Test Interface"
action: @selector(testInterface:)
keyEquivalent: @"r"];
[aMenu addItemWithTitle: @"Miniaturize"
action: @selector(miniaturize:)
keyEquivalent: @"m"];
[aMenu addItemWithTitle: @"Close"
action: @selector(close:)
keyEquivalent: @""];
menuItem = [mainMenu addItemWithTitle: @"Document"
action: NULL
keyEquivalent: @""];
[mainMenu setSubmenu: aMenu forItem: menuItem];
RELEASE(aMenu);
/*
* Set up edit menu.
*/
aMenu = [NSMenu new];
[aMenu addItemWithTitle: @"Cut"
action: @selector(cut:)
keyEquivalent: @"x"];
[aMenu addItemWithTitle: @"Copy"
action: @selector(copy:)
keyEquivalent: @"c"];
[aMenu addItemWithTitle: @"Paste"
action: @selector(paste:)
keyEquivalent: @"v"];
[aMenu addItemWithTitle: @"Delete"
action: @selector(delete:)
keyEquivalent: @""];
[aMenu addItemWithTitle: @"Select All"
action: @selector(selectAll:)
keyEquivalent: @"a"];
[aMenu addItemWithTitle: @"Set Name..."
action: @selector(setName:)
keyEquivalent: @""];
menuItem = [mainMenu addItemWithTitle: @"Edit"
action: NULL
keyEquivalent: @""];
[mainMenu setSubmenu: aMenu forItem: menuItem];
RELEASE(aMenu);
/*
* Set up tools menu.
*/
aMenu = [NSMenu new];
[aMenu addItemWithTitle: @"Inspector..."
action: @selector(inspector:)
keyEquivalent: @""];
[aMenu addItemWithTitle: @"Palettes..."
action: @selector(palettes:)
keyEquivalent: @""];
[aMenu addItemWithTitle: @"Load Palette..."
action: @selector(loadPalette:)
keyEquivalent: @""];
menuItem = [mainMenu addItemWithTitle: @"Tools"
action: NULL
keyEquivalent: @""];
[mainMenu setSubmenu: aMenu forItem: menuItem];
RELEASE(aMenu);
/*
* Set up Windows menu
*/
windowsMenu = [NSMenu new];
[windowsMenu addItemWithTitle: @"Arrange"
action: @selector(arrangeInFront:)
keyEquivalent: @""];
[windowsMenu addItemWithTitle: @"Miniaturize"
action: @selector(performMiniaturize:)
keyEquivalent: @"m"];
[windowsMenu addItemWithTitle: @"Close"
action: @selector(performClose:)
keyEquivalent: @"w"];
menuItem = [mainMenu addItemWithTitle: @"Windows"
action: NULL
keyEquivalent: @""];
[mainMenu setSubmenu: windowsMenu forItem: menuItem];
RELEASE(windowsMenu);
/*
* Set up Services menu
*/
aMenu = [NSMenu new];
menuItem = [mainMenu addItemWithTitle: @"Services"
action: NULL
keyEquivalent: @""];
[mainMenu setSubmenu: aMenu forItem: menuItem];
RELEASE(aMenu);
[mainMenu addItemWithTitle: @"Hide"
action: @selector(hide:)
keyEquivalent: @"h"];
[mainMenu addItemWithTitle: @"Quit"
action: @selector(terminate:)
keyEquivalent: @"q"];
[self setMainMenu: mainMenu];
[self setWindowsMenu: windowsMenu];
[mainMenu display];
[self setDelegate: self];
[super finishLaunching];
}
- (void) handleNotification: (NSNotification*)notification
{
NSString *name = [notification name];
id obj = [notification object];
if ([name isEqual: IBSelectionChangedNotification])
{
/*
* If we are connecting - stop it - a change in selection must mean
* that the connection process has ended.
*/
if ([self isConnecting] == YES)
{
[self stopConnecting];
}
selectionOwner = obj;
[[self inspectorsManager] updateSelection];
}
else if ([name isEqual: IBWillCloseDocumentNotification])
{
RETAIN(obj);
[documents removeObjectIdenticalTo: obj];
AUTORELEASE(obj);
}
}
- (id) infoPanel: (id) sender
{
NSMutableDictionary *d;
d = [NSMutableDictionary dictionaryWithCapacity: 8];
[d setObject: @"Gorm" forKey: @"ApplicationName"];
[d setObject: @"GNUstep Graphicsl Object Relationship Modeller"
forKey: @"ApplicationDescription"];
[d setObject: @"Gorm 0.1" forKey: @"ApplicationRelease"];
[d setObject: @"0.1 Feb 2000" forKey: @"FullVersionID"];
[d setObject: [NSArray arrayWithObject:
@"Richard Frith-Macdonald <richard@brainstorm.co.uk>"]
forKey: @"Authors"];
// [d setObject: @"See http://www.gnustep.org" forKey: @"URL"];
[d setObject: @"Copyright (C) 1999, 2000 Free Software Foundation, Inc."
forKey: @"Copyright"];
[d setObject: @"Released under the GNU General Public License 2.0"
forKey: @"CopyrightDescription"];
[self orderFrontStandardInfoPanelWithOptions: d];
return self;
}
- (id) init
{
self = [super init];
if (self != nil)
{
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
NSBundle *bundle = [NSBundle mainBundle];
NSString *path;
path = [bundle pathForImageResource: @"GormLinkImage"];
linkImage = [[NSImage alloc] initWithContentsOfFile: path];
path = [bundle pathForImageResource: @"GormSourceTag"];
sourceImage = [[NSImage alloc] initWithContentsOfFile: path];
path = [bundle pathForImageResource: @"GormTargetTag"];
targetImage = [[NSImage alloc] initWithContentsOfFile: path];
documents = [NSMutableArray new];
[nc addObserver: self
selector: @selector(handleNotification:)
name: IBSelectionChangedNotification
object: nil];
[nc addObserver: self
selector: @selector(handleNotification:)
name: IBWillCloseDocumentNotification
object: nil];
/*
* Make sure the palettes manager exists, so that the editors and
* inspectors provided in the standard palettes are available.
*/
[self palettesManager];
}
return self;
}
- (id) inspector: (id) sender
{
[[[self inspectorsManager] panel] makeKeyAndOrderFront: self];
return self;
}
- (GormInspectorsManager*) inspectorsManager
{
if (inspectorsManager == nil)
{
inspectorsManager = [GormInspectorsManager new];
}
return inspectorsManager;
}
- (BOOL) isConnecting
{
return isConnecting;
}
- (BOOL) isTestingInterface
{
return isTesting;
}
- (NSImage*) linkImage
{
return linkImage;
}
- (id) loadPalette: (id) sender
{
return [[self palettesManager] openPalette: sender];
}
- (id) miniaturize: (id)sender
{
NSWindow *window = [(id)[self activeDocument] window];
[window miniaturize: self];
return nil;
}
- (id) newApplication: (id) sender
{
id doc = [GormDocument new];
[documents addObject: doc];
RELEASE(doc);
[doc setupDefaults: @"Application"];
[[doc window] makeKeyAndOrderFront: self];
return doc;
}
- (id) newEmpty: (id) sender
{
id doc = [GormDocument new];
[documents addObject: doc];
RELEASE(doc);
[doc setupDefaults: @"Empty"];
[[doc window] makeKeyAndOrderFront: self];
return doc;
}
- (id) newInspector: (id) sender
{
id doc = [GormDocument new];
[documents addObject: doc];
RELEASE(doc);
[doc setupDefaults: @"Inspector"];
[[doc window] makeKeyAndOrderFront: self];
return doc;
}
- (id) newPalette: (id) sender
{
id doc = [GormDocument new];
[documents addObject: doc];
RELEASE(doc);
[doc setupDefaults: @"Palette"];
[[doc window] makeKeyAndOrderFront: self];
return doc;
}
- (id) open: (id) sender
{
GormDocument *doc = [GormDocument new];
[documents addObject: doc];
RELEASE(doc);
if ([doc openDocument: sender] == nil)
{
[documents removeObjectIdenticalTo: doc];
doc = nil;
}
else
{
[[doc window] makeKeyAndOrderFront: self];
}
return doc;
}
- (GormPalettesManager*) palettesManager
{
if (palettesManager == nil)
{
palettesManager = [GormPalettesManager new];
}
return palettesManager;
}
- (id) palettes: (id) sender
{
[[[self palettesManager] panel] makeKeyAndOrderFront: self];
return self;
}
- (id) paste: (id)sender
{
if ([selectionOwner respondsToSelector: @selector(pasteInSelection)] == NO)
return nil;
[selectionOwner pasteInSelection];
return self;
}
- (id) revertToSaved: (id)sender
{
id doc = [(id)[self activeDocument] revertDocument: sender];
if (doc != nil)
{
[documents addObject: doc];
[[doc window] makeKeyAndOrderFront: self];
}
return nil;
}
- (id) save: (id)sender
{
return [(id)[self activeDocument] saveDocument: sender];
}
- (id) saveAll: (id)sender
{
NSEnumerator *e = [documents objectEnumerator];
id doc;
while ((doc = [e nextObject]) != nil)
{
if ([[doc window] isDocumentEdited] == YES)
{
[doc saveDocument: sender];
}
}
return self;
}
- (id) saveAs: (id)sender
{
return [(id)[self activeDocument] saveAsDocument: sender];
}
- (id) selectAll: (id)sender
{
/* FIXME */
return nil;
}
- (id<IBSelectionOwners>) selectionOwner
{
return selectionOwner;
}
- (id) selectedObject
{
return [[selectionOwner selection] lastObject];
}
- (id) setName: (id)sender
{
NSPanel *p;
int r;
NSTextField *t;
NSArray *s = [selectionOwner selection];
id o = [s objectAtIndex: 0];
NSString *n;
p = NSGetAlertPanel(@"Set Name", @"Name: ", @"OK", @"Cancel", nil);
t = [[NSTextField alloc] initWithFrame: NSMakeRect(60,46,240,20)];
[[p contentView] addSubview: t];
[p makeFirstResponder: t];
[p makeKeyAndOrderFront: self];
[t performClick: self];
r = [(id)p runModal];
if (r == NSAlertDefaultReturn)
{
n = [[t stringValue] stringByTrimmingSpaces];
if (n != nil && [n isEqual: @""] == NO)
{
[[self activeDocument] setName: n forObject: o];
}
}
[t removeFromSuperview];
RELEASE(t);
NSReleaseAlertPanel(p);
return self;
}
- (void) startConnecting
{
if (isConnecting == YES)
{
return;
}
if (connectDestination == nil || connectSource == nil)
{
return;
}
if ([[self activeDocument] containsObject: connectDestination] == NO)
{
NSLog(@"Oops - connectDestination not in active document");
return;
}
if ([[self activeDocument] containsObject: connectSource] == NO)
{
NSLog(@"Oops - connectSource not in active document");
return;
}
isConnecting = YES;
[[self inspectorsManager] updateSelection];
}
- (void) stopConnecting
{
[self displayConnectionBetween: nil and: nil];
isConnecting = NO;
}
- (id) testInterface: (id)sender
{
if (isTesting == YES)
{
return nil;
}
else
{
NSUserDefaults *defs;
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
GormDocument *a = (GormDocument*)[self activeDocument];
NSData *d;
[a beginArchiving];
d = [NSArchiver archivedDataWithRootObject: a];
[a endArchiving];
[nc postNotificationName: IBWillBeginTestingInterfaceNotification
object: self];
isTesting = YES;
if ([selectionOwner conformsToProtocol: @protocol(IBEditors)] == YES)
{
[(id<IBEditors>)selectionOwner makeSelectionVisible: NO];
}
defs = [NSUserDefaults standardUserDefaults];
menuLocations = [[defs objectForKey: @"NSMenuLocations"] copy];
[defs removeObjectForKey: @"NSMenuLocations"];
testContainer = [NSUnarchiver unarchiveObjectWithData: d];
if (testContainer != nil)
{
[testContainer awakeWithContext: nil];
RETAIN(testContainer);
}
/*
* If the NIB didn't have a main menu, create one,
* otherwise, ensure that 'quit' ends testing mode.
*/
if ([self mainMenu] == mainMenu)
{
NSMenu *testMenu;
testMenu = [[NSMenu alloc] initWithTitle: @"Test"];
[testMenu addItemWithTitle: @"Quit"
action: @selector(endTesting:)
keyEquivalent: @"q"];
[self setMainMenu: testMenu];
RELEASE(testMenu);
}
else
{
NSMenu *testMenu = [self mainMenu];
NSMenuItem *item;
item = [testMenu itemWithTitle: @"Quit"];
if (item != nil)
{
[item setAction: @selector(endTesting:)];
}
else
{
[testMenu addItemWithTitle: @"Quit"
action: @selector(endTesting:)
keyEquivalent: @"q"];
}
}
[nc postNotificationName: IBDidBeginTestingInterfaceNotification
object: self];
return self;
}
}
- (BOOL) validateMenuItem: (NSMenuItem*)item
{
GormDocument *active = (GormDocument*)[self activeDocument];
SEL action = [item action];
if (sel_eq(action, @selector(close:))
|| sel_eq(action, @selector(miniaturize:))
|| sel_eq(action, @selector(save:))
|| sel_eq(action, @selector(saveAs:))
|| sel_eq(action, @selector(saveAll:)))
{
if (active == nil)
return NO;
}
if (sel_eq(action, @selector(revertToSaved:)))
{
if (active == nil || [active documentPath] == nil
|| [[active window] isDocumentEdited] == NO)
return NO;
}
if (sel_eq(action, @selector(testInterface:)))
{
if (active == nil)
return NO;
}
if (sel_eq(action, @selector(copy:)))
{
if ([[selectionOwner selection] count] == 0)
return NO;
return [selectionOwner respondsToSelector: @selector(copySelection)];
}
if (sel_eq(action, @selector(cut:)))
{
if ([[selectionOwner selection] count] == 0)
return NO;
return ([selectionOwner respondsToSelector: @selector(copySelection)]
&& [selectionOwner respondsToSelector: @selector(deleteSelection)]);
}
if (sel_eq(action, @selector(delete:)))
{
if ([[selectionOwner selection] count] == 0)
return NO;
return [selectionOwner respondsToSelector: @selector(deleteSelection)];
}
if (sel_eq(action, @selector(paste:)))
{
return [selectionOwner respondsToSelector: @selector(pasteInSelection)];
}
if (sel_eq(action, @selector(setName:)))
{
NSArray *s = [selectionOwner selection];
NSString *n;
id o;
if ([s count] == 0)
{
return NO;
}
if ([s count] > 1)
{
return NO;
}
o = [s objectAtIndex: 0];
n = [active nameForObject: o];
if ([n isEqual: @"NSOwner"] || [n isEqual: @"NSFirst"]
|| [n isEqual: @"NSFont"])
{
return NO;
}
}
return YES;
}
@end
int
main(int argc, const char **argv)
{
extern BOOL NSImageDoesCaching;
NSImageDoesCaching = YES;
//[NSObject enableDoubleReleaseCheck: YES];
NSApplicationMain(argc, argv);
return 0;
}