apps-projectcenter/PCLib/PCEditorView.m
Philippe C.D. Robert 396f6b9751 Began to work on support for an integrated editor, thus much has been rewritten
related to editor handling. This is work in progress... Every PCProject
component now has to conform to the ProjectComponent protocol.
Syntax highlighting is disabled for now, this will undergo a major rewrite soon.
Furthermore I separated the component handling stuff from the main class file
and put it into PCProject+ComponentHandling.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/apps/projectcenter/trunk@12499 72102866-910b-0410-8b05-ffd578937521
2002-02-11 22:19:39 +00:00

423 lines
10 KiB
Objective-C

/*
GNUstep ProjectCenter - http://www.gnustep.org
Copyright (C) 2001 Free Software Foundation
Author: Philippe C.D. Robert <phr@3dkit.org>
This file is part of GNUstep.
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"
#import "PCEditor.h"
#define COLOURISE 0
#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 textContainer:(NSTextContainer*)tc
{
if ((self = [super initWithFrame:frameRect textContainer:tc]))
{
shouldHighlight = NO;
/*
* 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",
@"#ifndef",
@"#if defined",
@"#define",
@"#endif",
@"#pragma",
@"#warning",
@"@interface",
@"@implementation",
@"@end",
@"@protocol",
nil];
}
return self;
}
- (void)dealloc
{
if (scanner)
{
[scanner release];
}
[_keywords release];
[super dealloc];
}
- (void)setEditor:(PCEditor *)anEditor
{
editor = anEditor;
}
- (void)setString:(NSString *)aString
{
[scanner autorelease];
scanner = [[NSScanner alloc] initWithString:aString];
[super setString:aString];
#ifdef COLOURISE
if( shouldHighlight )
{
[self highlightText];
}
#endif //COLOURISE
}
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
return YES;
}
- (void)setShouldHighlight:(BOOL)yn
{
shouldHighlight = yn;
}
- (BOOL)shouldHighlight
{
return shouldHighlight;
}
- (void)insertText:(id)aString
{
NSRange txtRange = NSMakeRange(0, [[self textStorage] length]);
[super insertText:aString];
if( shouldHighlight )
{
[[self textStorage] invalidateAttributesInRange:txtRange];
[self highlightTextInRange:txtRange];
}
}
- (void)highlightText
{
NSRange txtRange = NSMakeRange(0, [[self textStorage] length]);
[self highlightTextInRange:txtRange];
}
- (void)highlightTextInRange:(NSRange)txtRange
{
NSDictionary *aDict;
NSArray *keywords;
aDict = [NSDictionary dictionaryWithObjectsAndKeys:
editorFont, NSFontAttributeName,
@"UnknownCodeType", @"PCCodeTypeAttributeName",
nil];
[_textStorage beginEditing];
[_textStorage setAttributes:aDict range:txtRange];
// 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];
}
}
- (void)keyDown:(NSEvent *)anEvent
{
NSString *chars = [anEvent charactersIgnoringModifiers];
int modifiers = [anEvent modifierFlags];
if(([chars lossyCString][0] == 's') && (modifiers & NSCommandKeyMask))
{
[editor saveFile];
return;
}
[super keyDown:anEvent];
}
@end