diff options
-rw-r--r-- | Source/CMTextView.h | 10 | ||||
-rw-r--r-- | Source/CMTextView.m | 70 |
2 files changed, 41 insertions, 39 deletions
diff --git a/Source/CMTextView.h b/Source/CMTextView.h index 374704af..152450b0 100644 --- a/Source/CMTextView.h +++ b/Source/CMTextView.h @@ -32,6 +32,16 @@ #define SP_TEXT_SIZE_TRIGGER_FOR_PARTLY_PARSING 10000 + +static inline void NSMutableAttributedStringAddAttributeValueRange (NSMutableAttributedString* self, NSString* aStr, id aValue, NSRange aRange) { + typedef void (*SPMutableAttributedStringAddAttributeValueRangeMethodPtr)(NSMutableAttributedString*, SEL, NSString*, id, NSRange); + static SPMutableAttributedStringAddAttributeValueRangeMethodPtr SPMutableAttributedStringAddAttributeValueRange; + if (!SPMutableAttributedStringAddAttributeValueRange) SPMutableAttributedStringAddAttributeValueRange = (SPMutableAttributedStringAddAttributeValueRangeMethodPtr)[self methodForSelector:@selector(addAttribute:value:range:)]; + SPMutableAttributedStringAddAttributeValueRange(self, @selector(addAttribute:value:range:), aStr, aValue, aRange); + return; +} + + @interface CMTextView : NSTextView { BOOL autoindentEnabled; BOOL autopairEnabled; diff --git a/Source/CMTextView.m b/Source/CMTextView.m index 2cdda2da..5f5bc9be 100644 --- a/Source/CMTextView.m +++ b/Source/CMTextView.m @@ -2101,6 +2101,9 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) { NSTextStorage *textStore = [self textStorage]; + NSString *selfstr = [self string]; + long strlength = [selfstr length]; + NSRange textRange; // If text larger than SP_TEXT_SIZE_TRIGGER_FOR_PARTLY_PARSING @@ -2108,7 +2111,7 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) // The approach is to take the middle position of the current view port // and highlight only ±SP_SYNTAX_HILITE_BIAS of that middle position // considering of line starts resp. ends - if([[self string] length] > SP_TEXT_SIZE_TRIGGER_FOR_PARTLY_PARSING) + if(strlength > SP_TEXT_SIZE_TRIGGER_FOR_PARTLY_PARSING) { // Cancel all doSyntaxHighlighting requests @@ -2124,8 +2127,6 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) // Take roughly the middle position in the current view port int curPos = visibleRange.location+(int)(visibleRange.length/2); - int strlength = [[self string] length]; - // get the last line to parse due to SP_SYNTAX_HILITE_BIAS int end = curPos + SP_SYNTAX_HILITE_BIAS; if (end > strlength ) @@ -2134,7 +2135,7 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) } else { while(end < strlength) { - if([[self string] characterAtIndex:end]=='\n') + if([selfstr characterAtIndex:end]=='\n') break; end++; } @@ -2145,7 +2146,7 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) if (start > 0) while(start>-1) { - if([[self string] characterAtIndex:start]=='\n') + if([selfstr characterAtIndex:start]=='\n') break; start--; } @@ -2161,35 +2162,34 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) } else { // If text size is less SP_TEXT_SIZE_TRIGGER_FOR_PARTLY_PARSING // process syntax highlighting for the entire text view buffer - textRange = NSMakeRange(0,[[self string] length]); + textRange = NSMakeRange(0,strlength); } NSColor *tokenColor; - NSColor *commentColor = [[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorCommentColor"]] retain];//[NSColor colorWithDeviceRed:0.000 green:0.455 blue:0.000 alpha:1.000]; - NSColor *quoteColor = [[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorQuoteColor"]] retain];//[NSColor colorWithDeviceRed:0.769 green:0.102 blue:0.086 alpha:1.000]; - NSColor *keywordColor = [[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorSQLKeywordColor"]] retain];//[NSColor colorWithDeviceRed:0.200 green:0.250 blue:1.000 alpha:1.000]; - NSColor *backtickColor = [[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorBacktickColor"]] retain];//[NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.658 alpha:1.000]; - NSColor *numericColor = [[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorNumericColor"]] retain];//[NSColor colorWithDeviceRed:0.506 green:0.263 blue:0.0 alpha:1.000]; - NSColor *variableColor = [[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorVariableColor"]] retain];//[NSColor colorWithDeviceRed:0.5 green:0.5 blue:0.5 alpha:1.000]; - NSColor *textColor = [[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorTextColor"]] retain];//[NSColor colorWithDeviceRed:0.5 green:0.5 blue:0.5 alpha:1.000]; + NSColor *commentColor = [[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorCommentColor"]] retain]; + NSColor *quoteColor = [[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorQuoteColor"]] retain]; + NSColor *keywordColor = [[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorSQLKeywordColor"]] retain]; + NSColor *backtickColor = [[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorBacktickColor"]] retain]; + NSColor *numericColor = [[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorNumericColor"]] retain]; + NSColor *variableColor = [[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorVariableColor"]] retain]; + NSColor *textColor = [[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorTextColor"]] retain]; BOOL autouppercaseKeywords = [prefs boolForKey:@"CustomQueryAutoUppercaseKeywords"]; unsigned long tokenEnd, token; NSRange tokenRange; - //first remove the old colors and kQuote + // first remove the old colors and kQuote [textStore removeAttribute:NSForegroundColorAttributeName range:textRange]; // mainly for suppressing auto-pairing in [textStore removeAttribute:kLEXToken range:textRange]; - //initialise flex + // initialise flex yyuoffset = textRange.location; yyuleng = 0; - // yy_switch_to_buffer(yy_scan_string([[[self string] substringWithRange:textRange] UTF8String])); - yy_switch_to_buffer(yy_scan_string(NSStringUTF8String([[self string] substringWithRange:textRange]))); + yy_switch_to_buffer(yy_scan_string(NSStringUTF8String([selfstr substringWithRange:textRange]))); - //now loop through all the tokens + // now loop through all the tokens while (token=yylex()){ switch (token) { case SPT_SINGLE_QUOTED_TEXT: @@ -2231,57 +2231,49 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) tokenEnd = tokenRange.location+tokenRange.length-1; // Check the end of the token if (autouppercaseKeywords && !delBackwardsWasPressed - && [[[self textStorage] attribute:kSQLkeyword atIndex:tokenEnd effectiveRange:nil] isEqualToString:kValue]) + && [[textStore attribute:kSQLkeyword atIndex:tokenEnd effectiveRange:nil] isEqualToString:kValue]) // check if next char is not a kSQLkeyword or current kSQLkeyword is at the end; // if so then upper case keyword if not already done // @try catch() for catching valid index esp. after deleteBackward: { - NSString* curTokenString = [[self string] substringWithRange:tokenRange]; + NSString* curTokenString = [selfstr substringWithRange:tokenRange]; + NSString* upperCaseCurTokenString = [curTokenString uppercaseString]; BOOL doIt = NO; @try { - doIt = ![[[self textStorage] attribute:kSQLkeyword atIndex:tokenEnd+1 effectiveRange:nil] isEqualToString:kValue]; + doIt = ![[textStore attribute:kSQLkeyword atIndex:tokenEnd+1 effectiveRange:nil] isEqualToString:kValue]; } @catch(id ae) { doIt = NO; } - if(doIt && ![[curTokenString uppercaseString] isEqualToString:curTokenString]) + if(doIt && ![upperCaseCurTokenString isEqualToString:curTokenString]) { // Register it for undo works only partly for now, at least the uppercased keyword will be selected [self shouldChangeTextInRange:tokenRange replacementString:curTokenString]; - [self replaceCharactersInRange:tokenRange withString:[curTokenString uppercaseString]]; + [self replaceCharactersInRange:tokenRange withString:upperCaseCurTokenString]; } } - [textStore addAttribute: NSForegroundColorAttributeName - value: tokenColor - range: tokenRange ]; + NSMutableAttributedStringAddAttributeValueRange(textStore, NSForegroundColorAttributeName, tokenColor, tokenRange); // Add an attribute to be used in the auto-pairing (keyDown:) // to disable auto-pairing if caret is inside of any token found by lex. // For discussion: maybe change it later (only for quotes not keywords?) if(token < 6) - [textStore addAttribute: kLEXToken - value: kLEXTokenValue - range: tokenRange ]; - + NSMutableAttributedStringAddAttributeValueRange(textStore, kLEXToken, kLEXTokenValue, tokenRange); // Mark each SQL keyword for auto-uppercasing and do it for the next textStorageDidProcessEditing: event. // Performing it one token later allows words which start as reserved keywords to be entered. if(token == SPT_RESERVED_WORD) - [textStore addAttribute: kSQLkeyword - value: kValue - range: tokenRange ]; + NSMutableAttributedStringAddAttributeValueRange(textStore, kSQLkeyword, kValue, tokenRange); + // Add an attribute to be used to distinguish quotes from keywords etc. // used e.g. in completion suggestions else if(token < 4) - [textStore addAttribute: kQuote - value: kQuoteValue - range: tokenRange ]; + NSMutableAttributedStringAddAttributeValueRange(textStore, kQuote, kQuoteValue, tokenRange); + //distinguish backtick quoted word for completion else if(token == SPT_BACKTICK_QUOTED_TEXT) - [textStore addAttribute: kBTQuote - value: kBTQuoteValue - range: tokenRange ]; + NSMutableAttributedStringAddAttributeValueRange(textStore, kBTQuote, kBTQuoteValue, tokenRange); } |