/* ** CEView+BlockMarking.m ** ** Copyright (c) 2002, 2003 ** ** Author: Yen-Ju Chen ** Bjoern Giesler ** ** This program 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 program 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 General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // #include #include "CodeEditorViewPreference.h" #include "CEView+BlockMarking.h" #include "CEView+TextUtils.h" #include "CodeParser.h" #include "FontificationHandler.h" #include "BlockHandler.h" #include "BundleLoader.h" #include @implementation CodeEditorView (BlockMarking) - (void)unmarkPreviouslyMarkedBlock { NSRange effRange; id attr; hasSideMarked = NO; fontifying = YES; // Did we have something marked before? if(markedStartRange.location != NSNotFound) { attr = [[self textStorage] attribute: NSBackgroundColorAttributeName atIndex: markedStartRange.location effectiveRange: &effRange]; [[self textStorage] beginEditing]; [[self textStorage] removeAttribute: NSBackgroundColorAttributeName range: effRange]; if(startColor) { [[self textStorage] addAttribute: NSBackgroundColorAttributeName value: startColor range: markedStartRange]; } [[self textStorage] endEditing]; markedStartRange.location = NSNotFound; } if(markedEndRange.location != NSNotFound) { attr = [[self textStorage] attribute: NSBackgroundColorAttributeName atIndex: markedEndRange.location effectiveRange: &effRange]; [[self textStorage] beginEditing]; [[self textStorage] removeAttribute: NSBackgroundColorAttributeName range: effRange]; if(endColor) { [[self textStorage] addAttribute: NSBackgroundColorAttributeName value: endColor range: markedEndRange]; } [[self textStorage] endEditing]; markedEndRange.location = NSNotFound; } lastMarkedRange.location = NSNotFound; fontifying = NO; } - (void)findAndMarkBlockAtPosition: (int)position { NSString *wordAtCursor; NSRange wordAtCursorRange; NSRange beginRange, endRange; BOOL found; NSRange inRange; CodeParser *parser; id handler; unsigned int index; NSRect beginRect, endRect; NSLog(@"findAndMarkBlockAtPosition"); // Is the cursor at a block delimiter? wordAtCursor = [self wordAtPosition: position inRange: &wordAtCursorRange]; if(wordAtCursorRange.location == NSNotFound) return; if((wordAtCursorRange.location == lastMarkedRange.location) && (wordAtCursorRange.length == lastMarkedRange.length)) return; lastMarkedRange = wordAtCursorRange; found = NO; /* Use CodeParser */ index = [bundleLanguages indexOfObject: languageName]; if (index == NSNotFound) return; if (blockHandlerClass) { handler = [[blockHandlerClass alloc] init]; if (handler == nil) { NSLog(@"Can't load block handler"); return; } } else { return; } [handler setDelimiter: wordAtCursor]; if([handler searchBackward: wordAtCursor]) { /* Backward search */ position = 0; inRange = NSMakeRange(position, wordAtCursorRange.location); endRange = wordAtCursorRange; [handler setBackward: YES]; } else { /* Forward search */ position = NSMaxRange(wordAtCursorRange); inRange = NSMakeRange(position, [[self string] length] - position); beginRange = wordAtCursorRange; [handler setBackward: NO]; } parser = [[CodeParser alloc] initWithCodeHandler: handler withString: [[self string] substringWithRange:inRange ]]; NSLog(@"BlockMarking parse begin"); [parser parse]; NSLog(@"BlockMarking parse end"); if([handler searchBackward: wordAtCursor]) { /* Backward search */ beginRange = [handler result]; if (beginRange.location != NSNotFound) found = YES; } else { /* Forward search */ endRange = [handler result]; if (endRange.location != NSNotFound) found = YES; endRange.location = endRange.location+beginRange.location; /* Since we don't know whether the delimiter starts in comment or in string, we need to do a backward search. If the result from backward search is not the same, it is in comment or string */ if (found) { NSString *endWord; id endHandler; CodeParser *endParser; NSRange endResult; endWord = [[self string] substringWithRange: endRange]; endHandler = [[blockHandlerClass alloc] init]; [endHandler setDelimiter: endWord]; [endHandler setBackward: YES]; endParser = [[CodeParser alloc] initWithCodeHandler: endHandler withString: [[self string] substringWithRange: NSMakeRange(0, endRange.location)]]; [endParser parse]; endResult = [endHandler result]; if ( !NSEqualRanges(endResult, wordAtCursorRange)) found = NO; RELEASE(endHandler); RELEASE(endParser); } } RELEASE(handler); RELEASE(parser); if(!found) { lastMarkedRange = NSMakeRange(0, 0); } else { NSLog(@"beginRange %@", NSStringFromRange(beginRange)); NSLog(@"endRange %@", NSStringFromRange(endRange)); NSLog(@"length %d", [[self textStorage] length]); fontifying = YES; ASSIGN(startColor, [[self textStorage] attribute: NSBackgroundColorAttributeName atIndex: beginRange.location effectiveRange: (NSRange *)nil]); ASSIGN(endColor, [[self textStorage] attribute: NSBackgroundColorAttributeName atIndex: endRange.location effectiveRange: (NSRange *)nil]); NSLog(@"BeginEditing"); [[self textStorage] beginEditing]; NSLog(@"1"); [[self textStorage] addAttribute: NSBackgroundColorAttributeName value: [NSColor colorWithCalibratedRed: 0.5 green: 1 blue: 0.5 alpha: 1.0] range: beginRange]; NSLog(@"2"); [[self textStorage] addAttribute: NSBackgroundColorAttributeName value: [NSColor colorWithCalibratedRed: 0.5 green: 1 blue: 0.5 alpha: 1.0] range: endRange]; NSLog(@"3"); [[self textStorage] endEditing]; NSLog(@"End editing"); markedStartRange = beginRange; markedEndRange = endRange; /* Calcaulte the rect for side text */ if (hasSideTextView) { layoutManager = [self layoutManager]; beginRect = [layoutManager lineFragmentRectForGlyphAtIndex: beginRange.location effectiveRange: NULL]; endRect = [layoutManager lineFragmentRectForGlyphAtIndex: endRange.location effectiveRange: NULL]; sideMarkedRect = NSMakeRect(0, beginRect.origin.y, 40, endRect.origin.y - beginRect.origin.y + endRect.size.height); hasSideMarked = YES; fontifying = NO; } } } - (void)findAndMarkBlockAtCursor { [self findAndMarkBlockAtPosition: [self selectedRange].location-1]; } @end