diff options
author | Brian Cully <bjc@kublai.com> | 2008-04-02 19:20:20 -0400 |
---|---|---|
committer | Brian Cully <bjc@kublai.com> | 2008-04-02 19:20:20 -0400 |
commit | ab10720260e2c184b319026da89f4dfd338500bb (patch) | |
tree | a692a27435da0296972e43b21b2f35762e720bfd /LispREPLController.m | |
download | moxie-ab10720260e2c184b319026da89f4dfd338500bb.tar.gz moxie-ab10720260e2c184b319026da89f4dfd338500bb.zip |
Initial commit
Diffstat (limited to 'LispREPLController.m')
-rw-r--r-- | LispREPLController.m | 847 |
1 files changed, 847 insertions, 0 deletions
diff --git a/LispREPLController.m b/LispREPLController.m new file mode 100644 index 0000000..889b9f1 --- /dev/null +++ b/LispREPLController.m @@ -0,0 +1,847 @@ +// +// LispREPLController.m +// Moxie +// +// Created by Brian Cully on Mon Aug 09 2004. +// Copyright (c) 2004 Brian Cully. All rights reserved. +// + +#import "LispREPLController.h" + +enum repl_lock_condition { NO_DATA, HAS_DATA }; + +@implementation LispREPLController ++ (LispREPLController *)sharedController +{ + static LispREPLController *sharedController = nil; + + if (sharedController == nil) { + sharedController = [[LispREPLController alloc] init]; + } + return sharedController; +} + +- (id)init +{ + self = [self initWithWindowNibName: @"LispREPL"]; + if (self) { + theHistoryLevel = 0; + waitingForResult = YES; + [self setWindowFrameAutosaveName: @"lispREPLWindow"]; + // Make sure the window is there, so we get all the output even if it isn't open. + [self window]; + + } + return self; +} + +- (void)dealloc +{ + NSNotificationCenter *defaultCenter; + + defaultCenter = [NSNotificationCenter defaultCenter]; + [defaultCenter removeObserver: self]; + + [theUpdates release]; + [theREPLUpdateLock release]; + + [super dealloc]; +} + +- (void)scrollToEnd: (NSTextView *)aTextView +{ + NSScroller *verticalScroller; + NSScrollView *myScrollView; + + myScrollView = (NSScrollView *)[[aTextView superview] superview]; + verticalScroller = [myScrollView verticalScroller]; + [aTextView scrollRangeToVisible: NSMakeRange([[aTextView textStorage] length], 0)]; +// if ([verticalScroller isEnabled] == NO || (1.0 - [verticalScroller floatValue]) < 0.000001) +// [aTextView scrollRangeToVisible: NSMakeRange([[aTextView textStorage] length], 0)]; +} + +// Add a newline, print the prompt, and set the mark to the end of the buffer. +- (void)updateREPLFont +{ + NSTextStorage *ts; + NSUserDefaults *defaults; + + defaults = [NSUserDefaults standardUserDefaults]; + ts = [[self textView] textStorage]; + [ts addAttribute: NSFontAttributeName + value: [defaults REPLFont] + range: NSMakeRange(0, [ts length])]; +} + +// TODO: +// Optimize redraw by caching previous values and checking for deltas. +// Unfortunately, the notification posted for changes doesn't include said deltas. +- (void)redisplay +{ + NSRect fontRect; + NSTextView *tv; + NSUserDefaults *defaults; + + defaults = [NSUserDefaults standardUserDefaults]; + tv = [self textView]; + [tv setBackgroundColor: [defaults REPLBackgroundColor]]; + [tv setInsertionPointColor: [defaults REPLInputTextColor]]; + [tv setTypingAttributes: [self REPLInputAttributes]]; + [self updateREPLFont]; + + fontRect = [[defaults REPLFont] boundingRectForFont]; + if (fontRect.size.height > 0) { + [[self window] setContentResizeIncrements: + NSMakeSize(fontRect.size.width, fontRect.size.height)]; + } +} + +- (void)windowDidLoad +{ + NSNotificationCenter *defaultCenter; + + [super windowDidLoad]; + [[self window] setOpaque: NO]; + + [[LispREPL sharedREPL] addCommand: @":REPL-RESULT" + handler: self + selector: @selector(setLispResult:)]; + [[LispREPL sharedREPL] addCommand: @":REPL-DBG" + handler: self + selector: @selector(lispInDebugger:)]; + [[LispREPL sharedREPL] addCommand: @":REGISTER-KEYSTROKE" + handler: self + selector: @selector(registerKeystrokeMacro:)]; + [[LispREPL sharedREPL] addCommand: @":UNREGISTER-KEYSTROKE" + handler: self + selector: @selector(unregisterKeystrokeMacro:)]; + + theREPLUpdateLock = [[NSConditionLock alloc] initWithCondition: NO_DATA]; + theUpdates = [[NSMutableArray alloc] init]; + [NSThread detachNewThreadSelector: @selector(readREPLData:) + toTarget: self + withObject: [[LispREPL sharedREPL] stdoutReader]]; + + [LispREPL sharedREPL]; + + theREPLUpdateTimer = [NSTimer scheduledTimerWithTimeInterval: 0.1 + target: self + selector: @selector(scanForREPLData:) + userInfo: nil + repeats: YES]; + + defaultCenter = [NSNotificationCenter defaultCenter]; + [defaultCenter addObserver: self + selector: @selector(preferencesChanged:) + name: NSUserDefaultsDidChangeNotification + object: [NSUserDefaults standardUserDefaults]]; + + [self redisplay]; +} + +- (LispSymbol *)keystrokeFromEvent: (NSEvent *)anEvent +{ + LispSymbol *rc; + + rc = nil; + if ([anEvent type] == NSKeyDown) { + NSString *characters; + NSString *modifier, *keycode; + unsigned int i; + + modifier = @""; + if ([anEvent modifierFlags] & NSCommandKeyMask) { + modifier = [modifier stringByAppendingString: @"CMD-"]; + } + if ([anEvent modifierFlags] & NSAlternateKeyMask) { + modifier = [modifier stringByAppendingString: @"OPT-"]; + } + if ([anEvent modifierFlags] & NSControlKeyMask) { + modifier = [modifier stringByAppendingString: @"CTRL-"]; + } + if ([anEvent modifierFlags] & NSShiftKeyMask) { + modifier = [modifier stringByAppendingString: @"SHIFT-"]; + } + if ([anEvent modifierFlags] & NSNumericPadKeyMask) { + modifier = [modifier stringByAppendingString: @"NUMPAD-"]; + } + + // This sucks. We should be encoding things in a structure, not a keyword. + keycode = @""; + characters = [anEvent charactersIgnoringModifiers]; + for (i = 0; i < [characters length]; i++) { + switch ([characters characterAtIndex: i]) { + case '(': + keycode = @"LPAREN"; + break; + case ')': + keycode = @"RPAREN"; + break; + case ':': + keycode = @"COLON"; + break; + case '|': + keycode = @"PIPE"; + break; + case ';': + keycode = @"SEMICOLON"; + break; + case '\\': + keycode = @"BACKSLASH"; + break; + case '\'': + keycode = @"QUOTE"; + break; + case '`': + keycode = @"BACKQUOTE"; + break; + case '\t': + keycode = @"TAB"; + break; + case 27: + keycode = @"ESC"; + break; + case 127: + keycode = @"BACKSPACE"; + break; + case 3: + case 13: + keycode = @"RETURN"; + break; + case NSUpArrowFunctionKey: + keycode = @"UP"; + break; + case NSDownArrowFunctionKey: + keycode = @"DOWN"; + break; + case NSLeftArrowFunctionKey: + keycode = @"LEFT"; + break; + case NSRightArrowFunctionKey: + keycode = @"RIGHT"; + break; + case NSF1FunctionKey: + keycode = @"F1"; + break; + case NSF2FunctionKey: + keycode = @"F2"; + break; + case NSF3FunctionKey: + keycode = @"F3"; + break; + case NSF4FunctionKey: + keycode = @"F4"; + break; + case NSF5FunctionKey: + keycode = @"F5"; + break; + case NSF6FunctionKey: + keycode = @"F6"; + break; + case NSF7FunctionKey: + keycode = @"F7"; + break; + case NSF8FunctionKey: + keycode = @"F8"; + break; + case NSF9FunctionKey: + keycode = @"F9"; + break; + case NSF10FunctionKey: + keycode = @"F10"; + break; + case NSF11FunctionKey: + keycode = @"F11"; + break; + case NSF12FunctionKey: + keycode = @"F12"; + break; + case NSF13FunctionKey: + keycode = @"F13"; + break; + case NSF14FunctionKey: + keycode = @"F14"; + break; + case NSF15FunctionKey: + keycode = @"F15"; + break; + case NSF16FunctionKey: + keycode = @"F16"; + break; + case NSF17FunctionKey: + keycode = @"F17"; + break; + case NSF18FunctionKey: + keycode = @"F18"; + break; + case NSF19FunctionKey: + keycode = @"F19"; + break; + case NSF20FunctionKey: + keycode = @"F20"; + break; + case NSF21FunctionKey: + keycode = @"F21"; + break; + case NSF22FunctionKey: + keycode = @"F22"; + break; + case NSF23FunctionKey: + keycode = @"F23"; + break; + case NSF24FunctionKey: + keycode = @"F24"; + break; + case NSF25FunctionKey: + keycode = @"F25"; + break; + case NSF26FunctionKey: + keycode = @"F26"; + break; + case NSF27FunctionKey: + keycode = @"F27"; + break; + case NSF28FunctionKey: + keycode = @"F28"; + break; + case NSF29FunctionKey: + keycode = @"F29"; + break; + case NSF30FunctionKey: + keycode = @"F30"; + break; + case NSF31FunctionKey: + keycode = @"F31"; + break; + case NSF32FunctionKey: + keycode = @"F32"; + break; + case NSF33FunctionKey: + keycode = @"F33"; + break; + case NSF34FunctionKey: + keycode = @"F34"; + break; + case NSF35FunctionKey: + keycode = @"F35"; + break; + case NSInsertFunctionKey: + keycode = @"INS"; + break; + case NSDeleteFunctionKey: + keycode = @"DEL"; + break; + case NSHomeFunctionKey: + keycode = @"HOME"; + break; + case NSBeginFunctionKey: + keycode = @"BEGIN"; + break; + case NSEndFunctionKey: + keycode = @"END"; + break; + case NSPageUpFunctionKey: + keycode = @"PAGEUP"; + break; + case NSPageDownFunctionKey: + keycode = @"PAGEDOWN"; + break; + case NSClearLineFunctionKey: + keycode = @"CLEAR"; + break; + default: + keycode = [NSString stringWithFormat: @"%c", [characters characterAtIndex: i]]; + } + } + rc = [LispSymbol symbolNamed: [NSString stringWithFormat: @":%@%@", modifier, keycode]]; + } + NSLog(@"DEBUG: sending keycode: %@", rc); + return rc; +} + +- (BOOL)dispatchKeystrokeMacro: (NSEvent *)anEvent + fromID: (NSNumber *)anID +{ + LispSymbol *keystroke; + BOOL rc; + + rc = NO; + keystroke = [self keystrokeFromEvent: anEvent]; + if (keystroke) { + if ([[self keystrokeMacros] containsObject: keystroke]) { + [[LispREPL sharedREPL] eval: + [NSString stringWithFormat: @"(moxie::world-event %@ :keystroke-macro-hook %@)", + anID, [keystroke lispForm]]]; + rc = YES; + } + } + return rc; +} + +- (void)registerKeystrokeMacro: (NSArray *)form +{ + LispSymbol *keystroke; + + keystroke = [form objectAtIndex: 0]; + [[self keystrokeMacros] addObject: keystroke]; +} + +- (void)unregisterKeystrokeMacro: (NSArray *)form +{ + LispSymbol *keystroke; + + keystroke = [form objectAtIndex: 0]; + [[self keystrokeMacros] removeObject: keystroke]; +} + +- (void)goBackwardInHistory +{ + if (theHistoryLevel > 0) { + NSMutableString *buffer; + + buffer = [[[self textView] textStorage] mutableString]; + if (NO) { + [[self inputHistory] addObject: [buffer substringWithRange: NSMakeRange(0, [buffer length])]]; + theInputViewIsDirty = NO; + theHistoryLevel = [[self inputHistory] count] - 1; + } + theHistoryLevel--; + + [buffer replaceCharactersInRange: NSMakeRange([self mark], + [buffer length] - [self mark]) + withString: [[self inputHistory] objectAtIndex: theHistoryLevel]]; + [self scrollToEnd: [self textView]]; + } +} + +- (void)goForwardInHistory +{ + if (theHistoryLevel < [[self inputHistory] count]-1) { + NSMutableString *buffer; + + buffer = [[[self textView] textStorage] mutableString]; + if (theInputViewIsDirty) { + [[self inputHistory] addObject: [buffer substringWithRange: NSMakeRange(0, [buffer length])]]; + theInputViewIsDirty = NO; + theHistoryLevel = [[self inputHistory] count]; + } else + theHistoryLevel++; + + [buffer replaceCharactersInRange: NSMakeRange([self mark], + [buffer length] - [self mark]) + withString: [[self inputHistory] objectAtIndex: theHistoryLevel]]; + [self scrollToEnd: [self textView]]; + } +} + +- (void)textDidChange: (NSNotification *)aNotification +{ + if ([aNotification object] == theTextView) { + // Flag the input view as changed. + theInputViewIsDirty = YES; + } +} + +// XXX - this needs to change badly. We need to do full form +// parsing here or figure out a way around it entirely. +// +// This can probably tie into the indentation system. +- (BOOL)isValidLispForm: (NSString *)aForm +{ + int parenCount; + int i, formLen; + + formLen = [aForm length]; + parenCount = 0; + for (i = 0; i < formLen; i++) { + switch ([aForm characterAtIndex: i]) { + case '(': + parenCount++; + break; + case ')': + parenCount--; + break; + } + } + + return parenCount == 0; +} + +- (void)sendInputToLisp: (NSString *)aForm +{ + int formLen; + + // Get the new text, which is between the old mark and the end of the buffer. + formLen = [aForm length]; + if (formLen > 0) { + NSMutableString *buffer; + NSTextStorage *ts; + + // Save line in history. + if (theInputViewIsDirty || theHistoryLevel < [[self inputHistory] count]-1) { + [[self inputHistory] addObject: [aForm substringWithRange: NSMakeRange(0, formLen)]]; + theInputViewIsDirty = NO; + } + theHistoryLevel = [[self inputHistory] count]; + + // Update the marks when we send data to lisp. + ts = [[self textView] textStorage]; + buffer = [[[self textView] textStorage] mutableString]; + [self setMark: [buffer length]]; + [self setValueMark: [buffer length]]; + + if (waitingForResult) + [[LispREPL sharedREPL] eval: aForm]; + else + [self sendEvent: @":eval" withArg: [LispSymbol symbolNamed: aForm]]; // XXX: This is a cheap and dirty way to avoid getting + // the string quoted. We should just parse out the tree + // and send that array. + waitingForResult = YES; + } +} + +- (void)setLispResult: (NSArray *)alist +{ + NSArray *result; + NSDictionary *resultDict; + NSMutableString *resultStr; + NSMutableString *buffer; + NSTextStorage *ts; + NSString *prompt; + + ts = [[self textView] textStorage]; + buffer = [[[self textView] textStorage] mutableString]; + + resultDict = [NSDictionary dictionaryWithAlist: alist]; + prompt = [[resultDict objectForKey: @":PROMPT"] objectAtIndex: 0]; + result = [resultDict objectForKey: @":VALUES"]; + + if (result) { + resultStr = [NSMutableString stringWithString: @"=>"]; + if ([result isKindOfClass: [NSArray class]]) { + NSEnumerator *resultEnum; + id obj; + + resultEnum = [result objectEnumerator]; + while ((obj = [resultEnum nextObject]) != nil) + [resultStr appendFormat: @" %@", [obj lispForm]]; + } else + [resultStr appendFormat: @" %@", [result lispForm]]; + + [resultStr appendString: @"\n"]; + + [buffer appendString: resultStr]; + [ts addAttributes: [self REPLReturnValueAttributes] + range: NSMakeRange([self valueMark], [resultStr length])]; + } + [self setMark: [buffer length]]; + + if (prompt) { + waitingForResult = NO; + + [buffer appendString: prompt]; + [ts addAttributes: [self REPLPromptAttributes] + range: NSMakeRange([self mark], [prompt length])]; + } + [self setMark: [buffer length]]; + + [ts addAttributes: [self REPLInputAttributes] + range: NSMakeRange([self mark] - 1, 1)]; + [[self textView] setTypingAttributes: [self REPLInputAttributes]]; + + [self scrollToEnd: [self textView]]; +} + +/* + * When we're in the debugger, let it use its own prompt. And in the event that we've already printed our + * prompt, delete it. + */ +- (void)lispInDebugger: (NSArray *)args +{ + NSMutableString *buffer; + NSRange range; + + waitingForResult = YES; + + buffer = [[[self textView] textStorage] mutableString]; + range = NSMakeRange([self valueMark], [self mark] - [self valueMark]); + [buffer deleteCharactersInRange: range]; + [self setMark: [self mark] - range.length]; +} + +- (void)scanForREPLData: (NSDictionary *)userInfo +{ + [theREPLUpdateLock lock]; + while ([theUpdates count] > 0) { + NSAttributedString *replString; + NSData *updateData; + NSTextStorage *ts; + + updateData = [theUpdates objectAtIndex: 0]; + replString = [NSAttributedString attributedStringWithString: + [NSString stringWithCString: [updateData bytes] + length: [updateData length]] + attributes: [self REPLOutputAttributes]]; + + // Insert before values, and update marks. + ts = [[self textView] textStorage]; + [ts insertAttributedString: replString atIndex: [self valueMark]]; + [self setMark: [self mark] + [replString length]]; + [self setValueMark: [self valueMark] + [replString length]]; + + [self scrollToEnd: [self textView]]; + [theUpdates removeObjectAtIndex: 0]; + } + [theREPLUpdateLock unlock]; +} + +- (void)readREPLData: (NSFileHandle *)stdoutInput +{ + while (1) { + NSAutoreleasePool *rp; + NSData *inputData; + + rp = [[NSAutoreleasePool alloc] init]; + inputData = [stdoutInput availableData]; + if ([inputData length] == 0) + continue; + [theREPLUpdateLock lock]; + [theUpdates addObject: inputData]; + [theREPLUpdateLock unlock]; + [rp release]; + } +} + +- (void)preferencesChanged: (NSNotification *)aNotification +{ + [self redisplay]; +} + +- (void)changeFont: (id)sender +{ + NSDictionary *attrs; + NSFont *oldFont, *newFont; + + attrs = [[self textView] typingAttributes]; + oldFont = [attrs objectForKey: NSFontAttributeName]; + newFont = [sender convertFont: oldFont]; + + [[NSUserDefaults standardUserDefaults] setREPLFontData: + [NSArchiver archivedDataWithRootObject: newFont]]; +} + +- (BOOL)textView: (NSTextView *)aTextView +shouldChangeTextInRange: (NSRange)affectedCharRange + replacementString: (NSString *)replacementString +{ + if (replacementString && affectedCharRange.location < (unsigned)[self mark]) { + NSBeep(); + [[self textView] setSelectedRange: NSMakeRange([self mark], 0)]; + [self scrollToEnd: [self textView]]; + return NO; + } + return YES; +} + +- (NSArray *)textView: (NSTextView *)textView + completions: (NSArray *)words + forPartialWordRange: (NSRange)charRange + indexOfSelectedItem: (int *)i +{ + NSLog(@"[LispREPLController textView %@ completions: %@ forPartialWordRange: (%d, %d) indexOfSelectedItem: %d]", + textView, words, charRange.location, charRange.length, *i); + return words; +} + +- (void)sendEvent: (NSString *)anEvent +{ + [self sendEventWithArgs: anEvent, nil]; +} + +- (void)sendEvent: (NSString *)anEvent withArg: (id)anArg +{ + [self sendEventWithArgs: anEvent, anArg, nil]; +} + +-(void)sendEventWithArgs: (NSString *)anEvent, ... +{ + va_list ap; + + va_start(ap, anEvent); + [self sendEvent: anEvent arguments: ap]; + va_end(ap); +} + +-(void)sendEvent: (NSString *)anEvent arguments: (va_list)args +{ + NSMutableArray *argArray; + id arg; + + argArray = [NSMutableArray arrayWithObject: [LispSymbol symbolNamed: anEvent]]; + while ((arg = va_arg(args, id)) != nil) { + [argArray addObject: arg]; + } + [[LispREPL sharedREPL] eval: [NSString stringWithFormat: @"(apply #'moxie::moxie-event-handler '%@)", + [argArray lispForm]]]; +} + +- (NSNumber *)handleEvent: (NSEvent *)anEvent from: (id)sender +{ + BOOL rc; + + rc = NO; + if ([anEvent type] == NSKeyDown) { + NSMutableString *buffer; + NSString *characters; + unsigned int i; + + buffer = [[[self textView] textStorage] mutableString]; + characters = [anEvent charactersIgnoringModifiers]; + for (i = 0; i < [characters length]; i++) { + switch ([characters characterAtIndex: i]) { + case '\r': + case '\n': { + NSString *changedBuffer; + + changedBuffer = [buffer substringFromIndex: [self mark]]; + if ([self isValidLispForm: changedBuffer]) { + [buffer appendString: @"\n"]; + [self sendInputToLisp: changedBuffer]; + + [[self textView] setSelectedRange: NSMakeRange([buffer length], 0)]; + rc = YES; + } + break; + } + case NSUpArrowFunctionKey: + if ([anEvent modifierFlags] & NSCommandKeyMask) { + [self goBackwardInHistory]; + rc = YES; + } + break; + case NSDownArrowFunctionKey: + if ([anEvent modifierFlags] & NSCommandKeyMask) { + [self goForwardInHistory]; + rc = YES; + } + break; + } + } + } + + return [NSNumber numberWithBool: rc]; +} +@end + +@implementation LispREPLController (TextAttributes) +- (NSDictionary *)REPLPromptAttributes +{ + NSMutableDictionary *myAttrs; + NSUserDefaults *defaults; + + defaults = [NSUserDefaults standardUserDefaults]; + myAttrs = [NSMutableDictionary dictionary]; + [myAttrs setObject: [defaults REPLFont] forKey: NSFontAttributeName]; + [myAttrs setObject: [defaults REPLPromptColor] forKey: NSForegroundColorAttributeName]; + [myAttrs setObject: @"prompt" forKey: @"REPL.style"]; + + return myAttrs; +} + +- (NSDictionary *)REPLInputAttributes +{ + NSMutableDictionary *myAttrs; + NSUserDefaults *defaults; + + defaults = [NSUserDefaults standardUserDefaults]; + myAttrs = [NSMutableDictionary dictionary]; + [myAttrs setObject: [defaults REPLFont] forKey: NSFontAttributeName]; + [myAttrs setObject: [defaults REPLInputTextColor] forKey: NSForegroundColorAttributeName]; + [myAttrs setObject: @"input" forKey: @"REPL.style"]; + + return myAttrs; +} + +- (NSDictionary *)REPLOutputAttributes +{ + NSMutableDictionary *myAttrs; + NSUserDefaults *defaults; + + defaults = [NSUserDefaults standardUserDefaults]; + myAttrs = [NSMutableDictionary dictionary]; + [myAttrs setObject: [defaults REPLFont] forKey: NSFontAttributeName]; + [myAttrs setObject: [defaults REPLOutputTextColor] forKey: NSForegroundColorAttributeName]; + [myAttrs setObject: @"output" forKey: @"REPL.style"]; + + return myAttrs; +} + +- (NSDictionary *)REPLReturnValueAttributes +{ + NSMutableDictionary *myAttrs; + NSUserDefaults *defaults; + + defaults = [NSUserDefaults standardUserDefaults]; + myAttrs = [NSMutableDictionary dictionary]; + [myAttrs setObject: [defaults REPLFont] forKey: NSFontAttributeName]; + [myAttrs setObject: [defaults REPLReturnValueColor] forKey: NSForegroundColorAttributeName]; + [myAttrs setObject: @"result" forKey: @"REPL.style"]; + + return myAttrs; +} +@end + +@implementation LispREPLController (Accessors) +- (NSTextView *)textView +{ + return theTextView; +} + +- (int)mark +{ + return theMark; +} + +- (void)setMark: (int)aPoint +{ + theMark = aPoint; +} + +- (NSMutableSet *)keystrokeMacros +{ + if (theKeystrokeMacros == nil) + [self setKeystrokeMacros: [NSMutableSet set]]; + return theKeystrokeMacros; +} + +- (void)setKeystrokeMacros: (NSMutableSet *)macros +{ + [macros retain]; + [theKeystrokeMacros release]; + theKeystrokeMacros = macros; +} + +- (NSMutableArray *)inputHistory +{ + if (theInputHistory == nil) + [self setInputHistory: [NSMutableArray array]]; + return theInputHistory; +} + +- (int)valueMark +{ + return theValueMark; +} + +- (void)setValueMark: (int)aPoint +{ + theValueMark = aPoint; +} + +- (void)setInputHistory: (NSMutableArray *)aHistory +{ + [aHistory retain]; + [theInputHistory release]; + theInputHistory = aHistory; +} +@end
\ No newline at end of file |