Rev 590 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
//// RDocument.m// aa//// Created by stefano iacus on Sat Aug 14 2004.// Copyright (c) 2004 __MyCompanyName__. All rights reserved.//#import "RDocument.h"#import "RController.h"BOOL defaultsInitialized = NO;NSColor *shColorNormal;NSColor *shColorString;NSColor *shColorNumber;NSColor *shColorKeyword;NSColor *shColorComment;NSColor *shColorIdentifier;NSArray *keywordList;@implementation RDocument+ (void) setDefaultSyntaxHighlightingColors{shColorNormal=[NSColor blackColor];shColorString=[NSColor blueColor];shColorNumber=[NSColor blueColor];shColorKeyword=[NSColor colorWithDeviceRed:0.7 green:0.6 blue:0.0 alpha:1.0];shColorComment=[NSColor colorWithDeviceRed:0.6 green:0.4 blue:0.4 alpha:1.0];shColorIdentifier=[NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.4 alpha:1.0];keywordList = [NSArray arrayWithObjects: @"for", @"if", @"else", @"TRUE", @"FALSE", @"while",@"do", @"NULL", @"Inf", @"NA", @"NaN", @"in", nil];}/* Here we only break the modal loop for the R_Edit call. Wether a windowis to be saved on exit or no, is up to Cocoa*/- (BOOL)windowShouldClose:(id)sender{if(isREdit){[NSApp stopModal];isREdit = NO;}return YES;}- (id)init{self = [super init];if (self) {updating=NO;execNewlineFlag=NO;if (!defaultsInitialized) {[RDocument setDefaultSyntaxHighlightingColors];defaultsInitialized=YES;}initialContents=nil;initialContentsType=nil;useHighlighting=YES;isEditable=YES;isREdit=NO;}return self;}- (void)dealloc {if (initialContents) [initialContents release];if (initialContentsType) [initialContentsType release];[[NSNotificationCenter defaultCenter] removeObserver:self];[super dealloc];}- (NSString *)windowNibName{// Override returning the nib file name of the document// If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.return @"RDocument";}- (void) loadInitialContents{if (!initialContents || !textView) return;if ([initialContentsType isEqual:@"rtf"])[textView replaceCharactersInRange:NSMakeRange(0, [[textView textStorage] length])withRTF:initialContents];else[textView replaceCharactersInRange:NSMakeRange(0, [[textView textStorage] length])withString:[NSString stringWithCString:[initialContents bytes] length:[initialContents length]]];[self updateSyntaxHighlightingForRange:NSMakeRange(0,[[textView textStorage] length])];[initialContents release];initialContents=nil;}- (void)windowControllerDidLoadNib:(NSWindowController *) aController{[super windowControllerDidLoadNib:aController];[textView setFont:[[RController getRController] currentFont]];[textView setContinuousSpellCheckingEnabled:NO]; // by default no continuous spell checking[textView setAllowsUndo: YES];[self loadInitialContents];[textView setEditable: isEditable];[[NSNotificationCenter defaultCenter]addObserver:selfselector:@selector(textDidChange:)name:NSTextDidChangeNotificationobject: textView];[[textView textStorage] setDelegate:self];}- (NSData *)dataRepresentationOfType:(NSString *)aType{// Insert code here to write your document from the given data. You can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead.if([aType isEqual:@"rtf"])return [textView RTFFromRange:NSMakeRange(0, [[textView string] length])];elsereturn (NSData *)[textView string];}- (IBAction)printDocument:(id)sender{NSPrintInfo *printInfo;NSPrintInfo *sharedInfo;NSPrintOperation *printOp;NSMutableDictionary *printInfoDict;NSMutableDictionary *sharedDict;sharedInfo = [NSPrintInfo sharedPrintInfo];sharedDict = [sharedInfo dictionary];printInfoDict = [NSMutableDictionary dictionaryWithDictionary:sharedDict];printInfo = [[NSPrintInfo alloc] initWithDictionary: printInfoDict];[printInfo setHorizontalPagination: NSAutoPagination];[printInfo setVerticalPagination: NSAutoPagination];[printInfo setVerticallyCentered:NO];printOp = [NSPrintOperation printOperationWithView:textViewprintInfo:printInfo];[printOp setShowPanels:YES];[printOp runOperation];}- (BOOL) loadDataRepresentation: (NSData *)data ofType:(NSString *)aType {if (initialContents) {[initialContents release];initialContents=nil;}initialContentsType = [[NSString alloc] initWithString:aType];initialContents = [[NSData alloc] initWithData: data];if (textView) [self loadInitialContents];return YES;}+ (void) changeDocumentTitle: (NSDocument *)document Title:(NSString *)title{NSEnumerator *e = [[document windowControllers] objectEnumerator];NSWindowController *wc = nil;while (wc = [e nextObject]) {NSWindow *window = [wc window];[window setTitle: title];}}- (void) setHighlighting: (BOOL) use{useHighlighting=use;if (textView) {if (use)[self updateSyntaxHighlightingForRange:NSMakeRange(0,[[textView textStorage] length])];else[textView setTextColor:[NSColor blackColor] range:NSMakeRange(0,[[textView textStorage] length])];}}- (void) setEditable: (BOOL) editable{isEditable=editable;if (textView)[textView setEditable:editable];}- (void) setREditFlag: (BOOL) flag{isREdit=flag;}- (BOOL) hasREditFlag{return isREdit;}/* This is needed to force the NSDocument to know when edited windows are dirty */- (void) textDidChange: (NSNotification *)notification{NSDocument *document = [[NSDocumentController sharedDocumentController] currentDocument];[ document updateChangeCount:NSChangeDone];}/* this method is called after editing took place - we use it for updating the syntax highlighting */- (void)updateSyntaxHighlightingForRange: (NSRange) range{NSTextStorage *ts = [textView textStorage];NSString *s = [ts string];//NSLog(@"colorize \"%@\"", [s substringWithRange:lr]);int i = range.location;int bb = i;int last = i+range.length;BOOL foundItem=NO;if (updating || !useHighlighting) return;updating=YES;[ts beginEditing];while (i < last) {foundItem=NO;unichar c = [s characterAtIndex:i];if (c=='\'' || c=='"') {unichar lc=c;int ss=i;NSRange fr;if (i-bb>0) {fr=NSMakeRange(bb,i-bb);[ts addAttribute:@"shType" value:@"none" range:fr];[ts addAttribute:@"NSColor" value:shColorNormal range:fr];/*NSRange drr;NSDictionary *dict = [ts attributesAtIndex:fr.location effectiveRange:&drr];NSLog(@"dict: %@", dict);*/}i++;while (i<last && (c=[s characterAtIndex:i])!=lc) {if (c=='\\') { i++; if (i>=last) break; }i++;}fr=NSMakeRange(ss,i-ss+((i==last)?0:1));[ts addAttribute:@"shType" value:@"string" range:fr];[ts addAttribute:@"NSColor" value:shColorString range:fr];bb=i; if (i==last) break;i++; bb=i; if (i==last) break;c=[s characterAtIndex:i];foundItem=YES;}if (c>='0' && c<='9') {int ss=i;NSRange fr;if (i-bb>0) {fr=NSMakeRange(bb,i-bb);[ts addAttribute:@"shType" value:@"none" range:fr];[ts addAttribute:@"NSColor" value:shColorNormal range:fr];}i++;while (i<last && ((c=[s characterAtIndex:i])=='.' || (c>='0' && c<='9'))) i++;fr=NSMakeRange(ss,i-ss);[ts addAttribute:@"shType" value:@"number" range:fr];[ts addAttribute:@"NSColor" value:shColorNumber range:fr];bb=i;if (i==last) break;c=[s characterAtIndex:i];foundItem=YES;}if ((c>='a' && c<='z') || (c>='A' && c<='Z') || c=='.') {int ss=i;NSRange fr;if (i-bb>0) {fr=NSMakeRange(bb,i-bb);[ts addAttribute:@"shType" value:@"none" range:fr];[ts addAttribute:@"NSColor" value:shColorNormal range:fr];}i++;while (i<last && ((c=[s characterAtIndex:i])=='_' || c=='.' || (c>='a' && c<='z') || (c>='A' && c<='Z'))) i++;fr=NSMakeRange(ss,i-ss);if ([keywordList containsObject:[s substringWithRange:fr]]) {[ts addAttribute:@"shType" value:@"keyword" range:fr];[ts addAttribute:@"NSColor" value:shColorKeyword range:fr];} else {[ts addAttribute:@"shType" value:@"id" range:fr];[ts addAttribute:@"NSColor" value:shColorIdentifier range:fr];}bb=i;if (i==last) break;c=[s characterAtIndex:i];foundItem=YES;}if (c=='#') {int ss=i;NSRange fr;if (i-bb>0) {fr=NSMakeRange(bb,i-bb);[ts addAttribute:@"shType" value:@"none" range:fr];[ts addAttribute:@"NSColor" value:shColorNormal range:fr];}i++;while (i<last && ((c=[s characterAtIndex:i])!='\n' && c!='\r')) i++;fr=NSMakeRange(ss,i-ss);[ts addAttribute:@"shType" value:@"comment" range:fr];[ts addAttribute:@"NSColor" value:shColorComment range:fr];bb=i;if (i==last) break;c=[s characterAtIndex:i];foundItem=YES;}if (!foundItem) i++;}if (bb<last && i-bb>0) {NSRange fr=NSMakeRange(bb,i-bb);[ts addAttribute:@"shType" value:@"none" range:fr];[ts addAttribute:@"NSColor" value:shColorNormal range:fr];}[ts endEditing];updating=NO;}- (void)textStorageDidProcessEditing:(NSNotification *)aNotification {NSTextStorage *ts = [aNotification object];NSString *s = [ts string];NSRange er = [ts editedRange];/* get all lines that span the range that was affected. this impementation updates only lines containing the change, not beyond */NSRange lr = [s lineRangeForRange:er];lr.length = [ts length]-lr.location; // change everything up to the end of the document ...//NSLog(@"line range %d:%d (original was %d:%d)", lr.location, lr.length, er.location, er.length);[self updateSyntaxHighlightingForRange:lr];}- (BOOL)textView:(NSTextView *)textViewSrc doCommandBySelector:(SEL)commandSelector {BOOL retval = NO;if (textViewSrc!=textView) return NO;//NSLog(@"RTextView commandSelector: %@\n", NSStringFromSelector(commandSelector));if (@selector(insertNewline:) == commandSelector && execNewlineFlag) {execNewlineFlag=NO;return YES;}if (@selector(insertNewline:) == commandSelector) {// handling of indentation// currently we just copy what we get and add tabs for additional non-matched { bracketsNSTextStorage *ts = [textView textStorage];NSString *s = [ts string];NSRange csr = [textView selectedRange];NSRange ssr = NSMakeRange(csr.location, 0);NSRange lr = [s lineRangeForRange:ssr]; // line on which enter was pressed - this will be taken as guideif (csr.location>0) {int i=lr.location;int last=csr.location;int whiteSpaces=0, addShift=0;BOOL initial=YES;NSString *wss=@"\n";while (i<last) {unichar c=[s characterAtIndex:i];if (initial) {if (c=='\t' || c==' ') whiteSpaces++;else initial=NO;}if (c=='{') addShift++;if (c=='}' && addShift>0) addShift--;i++;}if (whiteSpaces>0)wss = [wss stringByAppendingString:[s substringWithRange:NSMakeRange(lr.location,whiteSpaces)]];while (addShift>0) { wss=[wss stringByAppendingString:@"\t"]; addShift--; }[textView insertText:wss];return YES;}}return retval;}- (IBAction)executeSelection:(id)sender{NSRange sr = [textView selectedRange];if (sr.length>0) {NSString *stx = [[[textView textStorage] string] substringWithRange:sr];[[RController getRController] sendInput:stx];}execNewlineFlag=YES;}@end