gscheme/SchemeDelegate.m

568 lines
14 KiB
Objective-C

#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