2 Copyright (C) 2004 Marcus Mueller <znek@mulle-kybernetik.com>
4 This file is part of OGo
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 // $Id: SOPEXRangeUtilities.m,v 1.2 2004/05/02 16:27:46 znek Exp $
22 // Created by znek on Tue Mar 23 2004.
25 #import "SOPEXRangeUtilities.h"
28 extern BOOL SOPEX_isValidTagNameCharacter(unichar character);
30 extern NSRange SOPEX_findOpenTagForRangeInString(NSRange range, NSString *string);
31 extern NSRange SOPEX_findMatchingClosingTagForRangeInString(NSRange range, NSString *string);
32 extern NSRange SOPEX_findClosingTagForRangeInString(NSRange range, NSString *string);
33 extern NSRange SOPEX_findMatchingOpenTagForRangeInString(NSRange range, NSString *string);
36 /* 'valid' is really bound to the SOPE context, here */
37 BOOL SOPEX_isValidTagNameCharacter(unichar character)
39 static NSCharacterSet *validTagNameCharacterSet = nil;
41 if(validTagNameCharacterSet == nil)
43 validTagNameCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-:.#?!"];
44 [validTagNameCharacterSet retain];
47 return [validTagNameCharacterSet characterIsMember:character];
50 /* This implementation is pretty naive, it doesn't know SGML rules and doesn't perform any
51 other sophisticated matching. It works pretty well in real life, though. */
52 NSRange SOPEX_findMatchingTagForRangeInString(NSRange range, NSString *string)
54 NSRange matchingRange;
56 if((matchingRange = SOPEX_findOpenTagForRangeInString(range, string)).location != NSNotFound)
60 closingRange = SOPEX_findMatchingClosingTagForRangeInString(matchingRange, string);
61 if(closingRange.location == NSNotFound)
62 return NSMakeRange(NSNotFound, 0);
63 matchingRange = NSUnionRange(matchingRange, closingRange);
65 else if((matchingRange = SOPEX_findClosingTagForRangeInString(range, string)).location != NSNotFound)
69 openRange = SOPEX_findMatchingOpenTagForRangeInString(matchingRange, string);
70 if(openRange.location == NSNotFound)
71 return NSMakeRange(NSNotFound, 0);
72 matchingRange = NSUnionRange(matchingRange, openRange);
77 NSRange SOPEX_findOpenTagForRangeInString(NSRange range, NSString *string)
80 int left, right, count;
82 if(range.location == NSNotFound)
83 return NSMakeRange(NSNotFound, 0);
85 if((range.length == 2) && ([[string substringWithRange:range] isEqualToString:@"</"]))
86 return NSMakeRange(NSNotFound, 0);
89 left = range.location + 1; // offset 1 to right because we might have hit a '<'
91 while(!found && left >= 0)
95 charToLeft = [string characterAtIndex:--left];
96 if (!SOPEX_isValidTagNameCharacter(charToLeft)) {
104 return NSMakeRange(NSNotFound, 0);
106 right = range.location + range.length;
107 count = [string length];
109 while(SOPEX_isValidTagNameCharacter([string characterAtIndex:right]) && right <= count)
112 return NSMakeRange(left, right - left);
115 NSRange SOPEX_findMatchingClosingTagForRangeInString(NSRange range, NSString *string)
117 unsigned depth, loc, count;
122 count = [string length];
123 loc = range.location + range.length;
125 current = [string characterAtIndex:range.location + 1];
126 if((current == '!') && ([string characterAtIndex:range.location + 2] != '-'))
133 current = [string characterAtIndex:loc];
136 if((loc + 1) < count)
137 if([string characterAtIndex:loc + 1] != '/')
140 else if(current == '>')
145 return NSUnionRange(range, NSMakeRange(loc, 1));
147 else if((current == '/') || (current == '-') || (current == '?'))
151 else if(!SOPEX_isValidTagNameCharacter(current))
157 return NSMakeRange(NSNotFound, 0);
160 NSRange SOPEX_findClosingTagForRangeInString(NSRange range, NSString *string)
162 return NSMakeRange(NSNotFound, 0);
165 NSRange SOPEX_findMatchingOpenTagForRangeInString(NSRange range, NSString *string)
167 return NSMakeRange(NSNotFound, 0);