diff --git a/PCLib/GNUmakefile b/PCLib/GNUmakefile index b59e6e7..1ff4909 100644 --- a/PCLib/GNUmakefile +++ b/PCLib/GNUmakefile @@ -50,6 +50,7 @@ libProjectCenter_MFILES = \ PCBrowserController.m \ PCBundleLoader.m \ PCDataSource.m \ + PCEditorView.m \ PCFileManager.m \ PCProject.m \ PCProjectBuilder.m \ @@ -63,6 +64,7 @@ libProjectCenter_HFILES = \ PCBrowserController.h \ PCBundleLoader.h \ PCDataSource.h \ + PCEditorView.h \ PCFileManager.h \ PCProject.h \ PCProjectBuilder.h \ diff --git a/PCLib/PCBrowserController.m b/PCLib/PCBrowserController.m index d43c89d..0fac011 100644 --- a/PCLib/PCBrowserController.m +++ b/PCLib/PCBrowserController.m @@ -41,35 +41,26 @@ NSString *FileShouldOpenNotification = @"FileShouldOpenNotification"; - (void)click:(id)sender { - NSTextView *pTextView; - if ([[sender selectedCell] isLeaf]) { NSString *ltitle = [[sender selectedCell] stringValue]; NSString *ctitle = [[sender selectedCellInColumn:0] stringValue]; NSString *ctitlef = [[project projectPath] stringByAppendingPathComponent:ltitle]; - pTextView = [project textView]; - - NSLog(@"****** %@",ctitlef); - if ([ctitle isEqualToString:@"Classes"]) { NSString *f = [NSString stringWithContentsOfFile:ctitlef]; - [pTextView setString:f]; + [project editSelectedFile:f]; } else if ([ctitle isEqualToString:@"Headers"]) { NSString *f = [NSString stringWithContentsOfFile:ctitlef]; - [pTextView setString:f]; + [project editSelectedFile:f]; } else if ([ctitle isEqualToString:@"Other Sources"]) { NSString *f = [NSString stringWithContentsOfFile:ctitlef]; - [pTextView setString:f]; + [project editSelectedFile:f]; } - - // This should not be needed! - [pTextView display]; } } diff --git a/PCLib/PCEditorView.h b/PCLib/PCEditorView.h new file mode 100644 index 0000000..af11126 --- /dev/null +++ b/PCLib/PCEditorView.h @@ -0,0 +1,53 @@ +/* + GNUstep ProjectCenter - http://www.projectcenter.ch + + Copyright (C) 2000 Philippe C.D. Robert + + Author: Philippe C.D. Robert + + This file is part of ProjectCenter. + + This application 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 application 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 + Library General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + + $Id$ +*/ + +#import + +@interface PCEditorView : NSTextView +{ + NSScanner *scanner; + + @private + NSRange range; + NSArray *_keywords; +} + +- (id)initWithFrame:(NSRect)frameRect; +- (void)dealloc; + +- (void)setString:(NSString *)aString; + +- (void)colourise:(id)sender; + +- (void)colouriseKeyword:(NSString *)keyword; +- (void)colouriseKeywords:(NSArray *)keywords; + +- (void)colouriseStrings; +- (void)colouriseCharStrings; +- (void)colouriseComments; +- (void)colouriseCPPComments; + +@end diff --git a/PCLib/PCEditorView.m b/PCLib/PCEditorView.m new file mode 100644 index 0000000..dd9ad36 --- /dev/null +++ b/PCLib/PCEditorView.m @@ -0,0 +1,347 @@ +/* + GNUstep ProjectCenter - http://www.projectcenter.ch + + Copyright (C) 2000 Philippe C.D. Robert + + Author: Philippe C.D. Robert + + This file is part of ProjectCenter. + + This application 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 application 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 + Library General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + + $Id$ +*/ + +#import "PCEditorView.h" + +#define SCANLOC [scanner scanLocation] + +@implementation PCEditorView + +static NSColor *commentColor = nil; +static NSColor *keywordColor = nil; +static NSColor *cppCommentColor = nil; +static NSColor *stringColor = nil; +static NSColor *cStringColor = nil; +static NSFont *editorFont = nil; +static BOOL isInitialised = NO; + +- (id)initWithFrame:(NSRect)frameRect +{ + if ((self = [super initWithFrame:frameRect])) { + + /* + * Should move that to initialize... + */ + + if (isInitialised == NO) { + commentColor = [[NSColor colorWithCalibratedRed: 0.0 green: 0.5 blue: 0.0 alpha: 1.0] retain]; + cppCommentColor = [[NSColor colorWithCalibratedRed: 0.0 green: 0.5 blue: 0.0 alpha: 1.0] retain]; + keywordColor = [[NSColor colorWithCalibratedRed: 0.8 green: 0.0 blue: 0.0 alpha: 1.0] retain]; + stringColor = [[NSColor colorWithCalibratedRed: 0.0 green: 0.0 blue: 0.8 alpha: 1.0] retain]; + cStringColor = [[NSColor colorWithCalibratedRed: 0.0 green: 0.0 blue: 0.8 alpha: 1.0] retain]; + editorFont = [[NSFont userFixedPitchFontOfSize:12] retain]; + isInitialised = YES; + } + + _keywords = [[NSArray alloc] initWithObjects:@"@class",@"@selector",@"#import",@"#include",@"#define",@"#pragma",@"#warning",@"@interface",@"@implementation",nil]; + } + return self; +} + +- (void)dealloc +{ + if (scanner) { + [scanner release]; + } + [_keywords release]; + + [super dealloc]; +} + +- (void)setString:(NSString *)aString +{ + [scanner autorelease]; + scanner = [[NSScanner alloc] initWithString:aString]; + + [super setString:aString]; + [self colourise:self]; +} + +- (void)colourise:(id)sender +{ + NSRange aRange; + NSDictionary *aDict; + NSArray *keywords; + + aRange = NSMakeRange(0,[_textStorage length]); + aDict = [NSDictionary dictionaryWithObjectsAndKeys: + editorFont, NSFontAttributeName, + @"UnknownCodeType", @"PCCodeTypeAttributeName", + nil]; + + [_textStorage beginEditing]; + [_textStorage setAttributes:aDict range:aRange]; + + // Scan the CodeType first... + + [self colouriseKeywords:_keywords]; + [self colouriseStrings]; + [self colouriseCharStrings]; + [self colouriseComments]; + [self colouriseCPPComments]; + + /* + * BIG HACK! + */ + + NS_DURING + [_textStorage endEditing]; + NS_HANDLER + NSLog(@"Excpetion: %@",[localException description]); + NS_ENDHANDLER + + [self setNeedsDisplay:YES]; +} + +- (void)colouriseStrings +{ + BOOL foundRange; + id aDict = [NSDictionary dictionaryWithObjectsAndKeys: + stringColor, NSForegroundColorAttributeName, + @"StringConstantCodeType", @"PCCodeTypeAttributeName", nil ]; + + [scanner setScanLocation:0]; + + while( ![scanner isAtEnd] ) { + foundRange = NO; + + [scanner scanUpToString:@"\"" intoString:NULL]; + range.location = SCANLOC; + [scanner scanString:@"\"" intoString:NULL]; + + if( ![scanner isAtEnd] && + range.location > 0 && + [[_textStorage string] characterAtIndex:(SCANLOC - 2)] == '@' ) { + range.location -= 1; + } + + while( ![scanner isAtEnd] ) { + [scanner scanUpToString:@"\"" intoString:NULL]; + [scanner scanString:@"\"" intoString:NULL]; + + // If there is no escape char before then we are done.. + + if( [[scanner string] characterAtIndex:(SCANLOC - 2)] != '\\' || + [[scanner string] characterAtIndex:(SCANLOC - 3)] == '\\' ) { + range.length = SCANLOC - range.location; + foundRange = YES; + break; + } + } + + if( foundRange ) { + NS_DURING + [_textStorage addAttributes:aDict range:range]; + NS_HANDLER + NSLog(@"<%@ %x> raised (-scanForStrings):\n%@",[self class],self,[localException description]); + NS_ENDHANDLER + } + } +} + +- (void)colouriseCharStrings +{ + NSRange tmpRange; + BOOL foundRange; + id aDict = [NSDictionary dictionaryWithObjectsAndKeys: + cStringColor,NSForegroundColorAttributeName, + @"StringConstantCodeType", @"PCCodeTypeAttributeName", nil ]; + + [scanner setScanLocation:0]; + + while( ![scanner isAtEnd] ) { + foundRange = NO; + [scanner scanUpToString:@"'" intoString:NULL]; + range.location = SCANLOC; + [scanner scanString:@"'" intoString:NULL]; + + while( ![scanner isAtEnd] ) { + [scanner scanUpToString:@"'" intoString:NULL]; + [scanner scanString:@"'" intoString:NULL]; + + // No escape => we are done! (ugly hack...) + if( [[scanner string] characterAtIndex:(SCANLOC - 2)] != '\\' || + [[scanner string] characterAtIndex:(SCANLOC - 3)] == '\\' ) { + + range.length = SCANLOC - range.location; + + // Ranges are not longer than 8 chars! (ugly hack...) + if( range.length > 8 ) { + [scanner setScanLocation:SCANLOC - 1]; + } + else { + foundRange = YES; + } + break; + } + } + + if( foundRange ) { + NS_DURING + [_textStorage addAttributes:aDict range:range]; + NS_HANDLER + NSLog(@"<%@ %x> raised (-colouriseCharStrings):\n%@",[self class],self,[localException description]); + NS_ENDHANDLER + } + } +} + +- (void)colouriseComments +{ + NSRange tmpRange; + BOOL foundRange; + id anObject; + id aDict = [NSDictionary dictionaryWithObjectsAndKeys: + commentColor,NSForegroundColorAttributeName, + @"CommentCodeType", @"PCCodeTypeAttributeName", + nil ]; + + [scanner setScanLocation:0]; + + while( ![scanner isAtEnd] ) { + foundRange = NO; + + while( ![scanner isAtEnd] ) { + [scanner scanUpToString:@"/*" intoString:NULL]; + range.location = SCANLOC; + [scanner scanString:@"/*" intoString:NULL]; + + if(![scanner isAtEnd] && + [[_textStorage attribute:@"PCCodeTypeAttributeName" + atIndex:range.location + effectiveRange:&tmpRange] isEqual:@"UnknownCodeType"]){ + foundRange = YES; + break; + } + } + + [scanner scanUpToString:@"*/" intoString:NULL]; + [scanner scanString:@"*/" intoString:NULL]; + range.length = SCANLOC - range.location; + + if( foundRange ) { + NS_DURING + /* + * BIG HACK!!! + */ + if (range.location == 0) {range.location = 1;range.length--;} + [_textStorage addAttributes:aDict range:range]; + NS_HANDLER + NSLog(@"<%@ %x> raised (-colouriseComments):\n%@",[self class],self,[localException description]); + NS_ENDHANDLER + } + } +} + +- (void)colouriseCPPComments +{ + NSRange tmpRange; + BOOL foundRange; + id anObject; + id aDict = [NSDictionary dictionaryWithObjectsAndKeys: + cppCommentColor, NSForegroundColorAttributeName, + @"CommentCodeType", @"PCCodeTypeAttributeName", nil ]; + + [scanner setScanLocation:0]; + + while( ![scanner isAtEnd] ) { + foundRange = NO; + + while( ![scanner isAtEnd] ) { + [scanner scanUpToString:@"//" intoString:NULL]; + range.location = SCANLOC; + [scanner scanString:@"//" intoString:NULL]; + + if( ![scanner isAtEnd] && + [[_textStorage attribute:@"PCCodeTypeAttributeName" + atIndex:range.location + effectiveRange:&tmpRange] isEqual:@"UnknownCodeType"]){ + foundRange = YES; + break; + } + } + + [scanner scanUpToString:@"\n" intoString:NULL]; + [scanner scanString:@"\n" intoString:NULL]; + range.length = SCANLOC - range.location; + + if( foundRange ) { + NS_DURING + [_textStorage addAttributes:aDict range:range]; + NS_HANDLER + NSLog(@"<%@ %x> raised (-colouriseCPPComments):\n%@",[self class],self,[localException description]); + NS_ENDHANDLER + } + } +} + +- (void)colouriseKeyword:(NSString *)keyword +{ + NSRange tmpRange; + BOOL foundRange; + id anObject; + + id keywordDict = [NSDictionary dictionaryWithObjectsAndKeys: + keywordColor,NSForegroundColorAttributeName, + @"KeywordCodeType", @"PCCodeTypeAttributeName", nil ]; + + // First scan for docu style comments + [scanner setScanLocation:0]; + + while( ![scanner isAtEnd] ) { + + [scanner scanUpToString:keyword intoString:NULL]; + range.location = SCANLOC; + + if( ![scanner isAtEnd] && + [[_textStorage attribute:@"PCCodeTypeAttributeName" + atIndex:range.location + effectiveRange:&tmpRange] isEqual:@"UnknownCodeType"] ) { + NS_DURING + [_textStorage addAttributes:keywordDict range:NSMakeRange( range.location, [keyword length])]; + NS_HANDLER + NSLog(@"<%@ %x> raised (-colouriseKeyword:):\n%@",[self class],self,[localException description]); + NS_ENDHANDLER + } + [scanner scanString:keyword intoString:NULL]; + } +} + +- (void)colouriseKeywords:(NSArray *)keywords +{ + NSEnumerator *enumerator = [keywords objectEnumerator]; + id object; + + while ((object = [enumerator nextObject])) { + [self colouriseKeyword:object]; + } +} + +@end + + + + diff --git a/PCLib/PCProject.h b/PCLib/PCProject.h index f63152e..7d2b1b8 100644 --- a/PCLib/PCProject.h +++ b/PCLib/PCProject.h @@ -172,6 +172,9 @@ static NSString * const PCLibraryVar = @"LIBRARY_VAR"; // ==== Miscellaneous //=========================================================================================== +- (void)editSelectedFile:(NSString *)file; +- (void)structureEditedFile:(id)sender; + - (BOOL)doesAcceptFile:(NSString *)file forKey:(NSString *)key; // Returns YES if type is a valid key and file is not contained in the project already diff --git a/PCLib/PCProject.m b/PCLib/PCProject.m index 61bfec7..c1adef9 100644 --- a/PCLib/PCProject.m +++ b/PCLib/PCProject.m @@ -77,9 +77,12 @@ [browserController setBrowser:browser]; [browserController setProject:self]; - textView = [[NSTextView alloc] initWithFrame:NSMakeRect(0,0,472,88)]; + // textView = [[NSTextView alloc] initWithFrame:NSMakeRect(0,0,472,88)]; + textView = [[PCEditorView alloc] initWithFrame:NSMakeRect(0,0,472,88)]; [textView setMaxSize:NSMakeSize(1e7, 1e7)]; [textView setRichText:NO]; + [textView setEditable:YES]; + [textView setSelectable:YES]; [textView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; [textView setVerticallyResizable:YES]; [textView setHorizontallyResizable:YES]; @@ -485,6 +488,34 @@ // ==== Miscellaneous //=========================================================================================== +- (void)editSelectedFile:(NSString *)file +{ + // NSLayoutManager *_lm = [textView layoutManager]; + // NSTextStorage *_ts = [[NSTextStorage alloc] initWithString:file]; + + /* + [_ts beginEditing]; + [[_ts mutableString] setString:file]; + [_ts endEditing]; + */ + + /* + if (_lm) { + [_lm replaceTextStorage:_ts]; + } + */ + + [textView setString:file]; + // [textView structure:self]; + [textView display]; + // [_ts autorelease]; +} + +- (void)structureEditedFile:(id)sender +{ + [textView structure:self]; +} + - (BOOL)doesAcceptFile:(NSString *)file forKey:(NSString *)type { if ([[projectDict allKeys] containsObject:type]) { @@ -831,3 +862,4 @@ @end + diff --git a/PCLib/PCServer.m b/PCLib/PCServer.m index 4835d8b..a90b2b4 100644 --- a/PCLib/PCServer.m +++ b/PCLib/PCServer.m @@ -106,7 +106,7 @@ styleMask:style backing:NSBackingStoreBuffered defer:NO]; - NSTextView *textView; + PCEditorView *textView; NSScrollView *scrollView; NSString *text = [NSString stringWithContentsOfFile:aFile]; @@ -114,10 +114,10 @@ [window setMinSize:NSMakeSize(512,320)]; [window setTitle:[aFile lastPathComponent]]; - textView = [[NSTextView alloc] initWithFrame:NSMakeRect(0,0,498,306)]; + textView = [[PCEditorView alloc] initWithFrame:NSMakeRect(0,0,498,306)]; [textView setMaxSize:NSMakeSize(1e7, 1e7)]; [textView setVerticallyResizable:YES]; - [textView setHorizontallyResizable:YES]; + [textView setHorizontallyResizable:NO]; [textView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; [textView setBackgroundColor:[NSColor whiteColor]]; [[textView textContainer] setWidthTracksTextView:YES]; diff --git a/PCLib/ProjectCenter.h b/PCLib/ProjectCenter.h index 21a5bca..58b6054 100644 --- a/PCLib/ProjectCenter.h +++ b/PCLib/ProjectCenter.h @@ -70,3 +70,8 @@ #import "ProjectBuilder.h" #import "FileCreator.h" #import "PCProjectBuilder.h" +#import "PCEditorView.h" + + + +