#import "SchemeDelegate.h" VScheme *vm = nil; @implementation SchemeDelegate : NSObject - (void)applicationWillFinishLaunching:(NSNotification *)not { // CREATE_AUTORELEASE_POOL(pool); NSMenu *menu, *info, *file, *scheme, *external, *env, *edit, *print, *services, *windows; // Create the app menu menu = [NSMenu new]; [menu addItemWithTitle: @"Info" action: NULL keyEquivalent: @""]; [menu addItemWithTitle: @"File" action: NULL keyEquivalent: @""]; [menu addItemWithTitle: @"Edit" action: NULL keyEquivalent: @""]; [menu addItemWithTitle: @"Windows" action: NULL keyEquivalent: @""]; [menu addItemWithTitle: @"Scheme" action: NULL keyEquivalent: @""]; [menu addItemWithTitle: @"Environment" action: NULL keyEquivalent: @""]; [menu addItemWithTitle: @"Services" action: NULL keyEquivalent: @""]; [menu addItemWithTitle: @"Hide" action: @selector(hide:) keyEquivalent: @"h"]; [menu addItemWithTitle: @"Quit" action: @selector(terminate:) keyEquivalent: @"q"]; // Create the scheme submenu scheme = [NSMenu new]; [menu setSubmenu: scheme forItem: [menu itemWithTitle: @"Scheme"]]; [scheme addItemWithTitle: @"Reset" action: @selector(reset:) keyEquivalent: @"+"]; [scheme addItemWithTitle: @"Evaluate" action: @selector(evaluate:) keyEquivalent: @"#"]; [scheme addItemWithTitle: @"Evaluate external" action:NULL keyEquivalent: @""]; external = [NSMenu new]; [scheme setSubmenu: external forItem: [scheme itemWithTitle: @"Evaluate external"]]; [external addItemWithTitle: @"Add external" action: @selector(addExternal:) keyEquivalent: @""]; // Create the environment submenu env = [NSMenu new]; [menu setSubmenu: env forItem: [menu itemWithTitle: @"Environment"]]; [env addItemWithTitle: @"Up" action: @selector(up:) keyEquivalent: @""]; [env addItemWithTitle: @"Down" action: @selector(down:) keyEquivalent: @""]; // Create the info submenu info = [NSMenu new]; [menu setSubmenu: info forItem: [menu itemWithTitle: @"Info"]]; [info addItemWithTitle: @"Info Panel..." action: @selector(orderFrontStandardInfoPanel:) keyEquivalent: @""]; /* [info addItemWithTitle: @"Preferences..." action: NULL keyEquivalent: @""]; */ [info addItemWithTitle: @"Help" action: @selector (orderFrontHelpPanel:) keyEquivalent: @"?"]; // RELEASE(info); // Create the file submenu file = [NSMenu new]; [menu setSubmenu: file forItem: [menu itemWithTitle: @"File"]]; [file addItemWithTitle: @"Open Document" action: @selector(openDocument:) keyEquivalent: @"o"]; [file addItemWithTitle: @"New Document" action: @selector(newDocument:) keyEquivalent: @"n"]; [file addItemWithTitle: @"Save" action: @selector(saveDocument:) keyEquivalent: @"s"]; [file addItemWithTitle: @"Save To..." action: @selector(saveDocumentTo:) keyEquivalent: @"t"]; [file addItemWithTitle: @"Save As..." action: @selector(saveDocumentAs:) keyEquivalent: @"S"]; [file addItemWithTitle: @"Save All" action: @selector(saveDocumentAll:) keyEquivalent: @""]; [file addItemWithTitle: @"Revert to Saved" action: @selector(revertDocumentToSaved:) keyEquivalent: @"u"]; [file addItemWithTitle: @"Close" action: @selector(close) keyEquivalent: @""]; [file addItemWithTitle: @"Insert File..." action: @selector(insertFile:) keyEquivalent: @""]; // RELEASE(file); // Create the edit submenu edit = [NSMenu new]; [menu setSubmenu: edit forItem: [menu itemWithTitle: @"Edit"]]; [edit addItemWithTitle: @"Cut" action: @selector(cut:) keyEquivalent: @"x"]; [edit addItemWithTitle: @"Copy" action: @selector(copy:) keyEquivalent: @"c"]; [edit addItemWithTitle: @"Paste" action: @selector(paste:) keyEquivalent: @"v"]; [edit addItemWithTitle: @"Delete" action: @selector(delete:) keyEquivalent: @""]; /* [edit addItemWithTitle: @"Undelete" action: NULL keyEquivalent: @""]; */ [edit addItemWithTitle: @"Select All" action: @selector(selectAll:) keyEquivalent: @"a"]; // RELEASE(edit); // Create the windows submenu windows = [NSMenu new]; [menu setSubmenu: windows forItem: [menu itemWithTitle: @"Windows"]]; [windows addItemWithTitle: @"Arrange" action: @selector(arrangeInFront:) keyEquivalent: @""]; [windows addItemWithTitle: @"Miniaturize" action: @selector(performMiniaturize:) keyEquivalent: @"m"]; [windows addItemWithTitle: @"Close" action: @selector(performClose:) keyEquivalent: @"w"]; [windows addItemWithTitle: @"Close image windows" action: @selector(closeImageWindows:) keyEquivalent: @"W"]; [windows addItemWithTitle: @"Close environment windows" action: @selector(closeEnvWindows:) keyEquivalent: @""]; [NSApp setWindowsMenu: windows]; // RELEASE(windows); // Create the service submenu services = [NSMenu new]; [menu setSubmenu: services forItem: [menu itemWithTitle: @"Services"]]; [NSApp setServicesMenu: services]; // RELEASE(services); [NSApp setMainMenu: menu]; // RELEASE(menu); imageWindows = [NSMutableArray arrayWithCapacity:1]; [imageWindows retain]; envWindows = [NSMutableArray arrayWithCapacity:1]; [envWindows retain]; // RELEASE(pool); } - (void)applicationDidFinishLaunching: (NSNotification *)not; { vm = [[VScheme alloc] init]; [vm setDelegate:self]; [self makeStatisticsPanel]; [self makeInterruptPanel]; [self makeInterpreterWindow]; // Make the DocumentController the delegate of the application, // as this is the only way I know to bring it into the responder chain [NSApp setDelegate:[NSDocumentController sharedDocumentController]]; } NSWindow *interpreterWindow = nil; - makeInterpreterWindow { NSWindow *window; NSScrollView *scrollView; SCMInteractive *textView; NSRect scrollViewRect = {{0, 0}, {470, 400}}; NSRect winRect = {{250, 100}, {470, 400}}; NSRect textRect; unsigned int style = NSTitledWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask; // This is expected to be retained, as it would normaly come from a // nib file, where the owner would retain it. window = [[NSWindow alloc] initWithContentRect: winRect styleMask: style backing: NSBackingStoreRetained defer: NO]; [window setMinSize:NSMakeSize(300, 300)]; scrollView = [[NSScrollView alloc] initWithFrame: scrollViewRect]; [scrollView setHasHorizontalScroller: NO]; [scrollView setHasVerticalScroller: YES]; [scrollView setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; [[scrollView contentView] setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; [[scrollView contentView] setAutoresizesSubviews:YES]; // Build up the text network textRect = [[scrollView contentView] frame]; textView = [[SCMInteractive alloc] initWithFrame: textRect]; [textView setBackgroundColor: [NSColor whiteColor]]; [textView setString:GSCHEME]; [textView appendString:@"> "]; [textView setFont:[NSFont userFixedPitchFontOfSize:12]]; [textView setDelegate:vm]; [textView setHorizontallyResizable: NO]; [textView setVerticallyResizable: YES]; [textView setMinSize: NSMakeSize(0, 0)]; [textView setMaxSize: NSMakeSize(1E7, 1E7)]; [textView setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; [[textView textContainer] setContainerSize:NSMakeSize(textRect.size.width, 1e7)]; [[textView textContainer] setWidthTracksTextView: YES]; // Store the text view in an ivar intTextView = textView; [scrollView setDocumentView: textView]; // RELEASE(textView); [window setContentView: scrollView]; // RELEASE(scrollView); // Make the Document the delegate of the window [window setDelegate: self]; [window setTitle:@"GScheme"]; [window display]; [window makeKeyAndOrderFront:nil]; // Make the text view the first responder [textView placeCursorAtEnd]; [window makeFirstResponder:textView]; interpreterWindow = window; return self; } - makeStatisticsPanel { NSPanel *panel; NSScrollView *scrollView; SCMInteractive *textView; NSRect scrollViewRect = {{0, 0}, {470, 400}}; NSRect winRect = {{450, 75}, {470, 400}}; NSRect textRect; unsigned int style = NSTitledWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask; // This is expected to be retained, as it would normaly come from a // nib file, where the owner would retain it. panel = [[NSPanel alloc] initWithContentRect: winRect styleMask: style backing: NSBackingStoreRetained defer: NO]; [panel setMinSize:NSMakeSize(300, 300)]; scrollView = [[NSScrollView alloc] initWithFrame: scrollViewRect]; [scrollView setHasHorizontalScroller: NO]; [scrollView setHasVerticalScroller: YES]; [scrollView setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; [[scrollView contentView] setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; [[scrollView contentView] setAutoresizesSubviews:YES]; // Build up the text network textRect = [[scrollView contentView] frame]; textView = [[NSTextView alloc] initWithFrame: textRect]; [textView setBackgroundColor: [NSColor whiteColor]]; [textView setString:GSCHEME]; [textView setEditable:NO]; [textView setFont:[NSFont userFixedPitchFontOfSize:12]]; [textView setDelegate:vm]; [textView setHorizontallyResizable: NO]; [textView setVerticallyResizable: YES]; [textView setMinSize: NSMakeSize(0, 0)]; [textView setMaxSize: NSMakeSize(1E7, 1E7)]; [textView setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; [[textView textContainer] setContainerSize:NSMakeSize(textRect.size.width, 1e7)]; [[textView textContainer] setWidthTracksTextView: YES]; // Store the text view in an ivar statTextView = textView; [scrollView setDocumentView: textView]; // RELEASE(textView); [panel setContentView: scrollView]; // RELEASE(scrollView); // Make the Document the delegate of the panel [panel setDelegate: self]; [panel setWorksWhenModal:NO]; // Make the text view the first responder // [panel makeFirstResponder:textView]; [panel setTitle:@"GScheme Statistics"]; [panel display]; [panel orderFront:nil]; return self; } #define IPCWIDTH 100 #define IPCHEIGHT 30 - makeInterruptPanel { interruptPanel = [[NSPanel alloc] initWithContentRect:NSMakeRect(0, 0, IPCWIDTH, IPCHEIGHT) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]; [interruptPanel setReleasedWhenClosed:NO]; NSButton *stopper; stopper = [NSButton new]; [stopper setTitle:@"Stop"]; [stopper setTarget:vm]; [stopper setAction:@selector(interrupt:)]; [interruptPanel setContentView:stopper]; return self; } - (NSPanel *)interruptPanel { return interruptPanel; } - input:(NSString *)data { [intTextView appendString:data]; return self; } - output:(NSString *)data { [intTextView appendString:data]; [intTextView placeCursorAtEnd]; return self; } - result:(id)item { [intTextView appendString:@"\n"]; [intTextView appendString:[VScheme valToString:item]]; [intTextView appendString:@"\n> "]; [intTextView placeCursorAtEnd]; return self; } - statistics:(NSString *)stats { NSString *sofar = [statTextView string]; [statTextView replaceCharactersInRange:NSMakeRange([sofar length], 0) withString:stats]; [statTextView placeCursorAtEnd]; return self; } - reset:(id)sender { [vm reset:self]; [intTextView setString:GSCHEME]; [intTextView appendString:@"> "]; [intTextView placeCursorAtEnd]; [[intTextView window] makeFirstResponder:intTextView]; [statTextView setString:GSCHEME]; } - addExternal:(id)sender { NSOpenPanel *openPanel = [NSOpenPanel openPanel]; [openPanel setTitle:@"Add external"]; [openPanel setAllowsMultipleSelection:NO]; [openPanel setPrompt:@"File:"]; [openPanel setCanChooseDirectories:NO]; if([openPanel runModalForTypes: [NSArray arrayWithObject:@"scm"]]==NSOKButton){ [[sender menu] addItemWithTitle:[openPanel filename] action:@selector(evaluateExternal:) keyEquivalent: @""]; } return self; } extern VScheme *vm; extern NSWindow *interpreterWindow; extern int errno; - evaluateExternal:(id)sender { SCMInteractive *intView = [[interpreterWindow contentView] documentView]; NSString *suffix = [intView getSuffix]; if([suffix length]>0){ [intView appendString:@"\n> "]; } NSString *progstr; if((progstr = [NSString stringWithContentsOfFile:[sender title]])==nil){ NSString *msg = @"Load failed"; if(errno){ char *estr = strerror(errno); msg = [msg stringByAppendingFormat:@": %s", estr]; } NSRunAlertPanel(@"Error", msg, @"Ok", nil, nil); return self; } BOOL res = [vm processString:progstr mode:MODE_EVALUATE]; if(res==NO){ NSRunAlertPanel(@"Error", [vm errmsg], @"Ok", nil, nil); } else{ [interpreterWindow makeKeyAndOrderFront:self]; } return self; } - imageWindow:(NSWindow *)window { [imageWindows addObject:window]; [window setDelegate:self]; return self; } - envWindow:(NSWindow *)window { [envWindows addObject:window]; [window setDelegate:self]; return self; } - (void)windowWillClose:(NSNotification *)aNotification { NSWindow *win = [aNotification object]; if([imageWindows containsObject:win]==YES){ [imageWindows removeObject:win]; } else if([envWindows containsObject:win]==YES){ [envWindows removeObject:win]; } } - closeImageWindows:(id)sender { NSArray *cwins = [NSArray arrayWithArray:imageWindows]; [cwins makeObjectsPerformSelector:@selector(close)]; return self; } - closeEnvWindows:(id)sender { NSArray *cwins = [NSArray arrayWithArray:envWindows]; [cwins makeObjectsPerformSelector:@selector(close)]; return self; } @end