diff --git a/ChangeLog b/ChangeLog index 265acbb65..5f6d6fb29 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-12-30 Fred Kiefer + + * Source/NSLayoutManager.m: Add code to handle temporary + attributes. This code is taken from NSAttributedString and the two + core methods are still missing. + 2010-12-29 12:31-EST Gregory John Casamento * Source/NSMenuItemCell.m: Implement drawing a line in the menu diff --git a/Source/NSLayoutManager.m b/Source/NSLayoutManager.m index e3f621051..de98e113e 100644 --- a/Source/NSLayoutManager.m +++ b/Source/NSLayoutManager.m @@ -105,21 +105,20 @@ first. Remaining cases, highest priority first: #include -#include "AppKit/NSLayoutManager.h" -#include "GNUstepGUI/GSLayoutManager_internal.h" - -#include -#include -#include "AppKit/NSAttributedString.h" -#include "AppKit/NSColor.h" -#include "AppKit/NSImage.h" -#include "AppKit/NSParagraphStyle.h" -#include "AppKit/NSRulerMarker.h" -#include "AppKit/NSTextContainer.h" -#include "AppKit/NSTextStorage.h" -#include "AppKit/NSWindow.h" -#include "AppKit/DPSOperators.h" +#import +#import +#import "AppKit/NSAttributedString.h" +#import "AppKit/NSColor.h" +#import "AppKit/NSImage.h" +#import "AppKit/NSLayoutManager.h" +#import "AppKit/NSParagraphStyle.h" +#import "AppKit/NSRulerMarker.h" +#import "AppKit/NSTextContainer.h" +#import "AppKit/NSTextStorage.h" +#import "AppKit/NSWindow.h" +#import "AppKit/DPSOperators.h" +#import "GNUstepGUI/GSLayoutManager_internal.h" @interface NSLayoutManager (LayoutHelpers) @@ -1616,7 +1615,7 @@ attachmentSize(linefrag_t *lf, NSUInteger glyphIndex) */ [self showAttachmentCell: (NSCell*)cell inRect: cellFrame - characterIndex: char_index]; + characterIndex: char_index]; [f set]; [color set]; } @@ -2386,17 +2385,6 @@ no_soft_invalidation: @end @implementation NSLayoutManager (temporaryattributes) -- (void) addTemporaryAttributes: (NSDictionary *)attrs forCharacterRange: (NSRange)range -{ - // to be implemented -} - -- (void) addTemporaryAttribute: (NSString *)attr - value: (id)value - forCharacterRange: (NSRange)range -{ - // to be implemented -} - (void) setTemporaryAttributes: (NSDictionary *)attrs forCharacterRange: (NSRange)range @@ -2404,29 +2392,6 @@ no_soft_invalidation: // to be implemented } -- (void) removeTemporaryAttribute: (NSString *)attr - forCharacterRange: (NSRange)range -{ - // to be implemented -} - -- (id) temporaryAttribute: (NSString *)attr - atCharacterIndex: (NSUInteger)index - effectiveRange: (NSRange*)range -{ - // to be implemented - return nil; -} - -- (id) temporaryAttribute: (NSString *)attr - atCharacterIndex: (NSUInteger)index - longestEffectiveRange: (NSRange*)longestRange - inRange: (NSRange)range -{ - // to be implemented - return nil; -} - - (NSDictionary *) temporaryAttributesAtCharacterIndex: (NSUInteger)index effectiveRange: (NSRange*)longestRange { @@ -2434,11 +2399,242 @@ no_soft_invalidation: return nil; } +- (void) addTemporaryAttributes: (NSDictionary *)attrs + forCharacterRange: (NSRange)range +{ + NSRange effectiveRange; + NSDictionary *attrDict; + NSMutableDictionary *newDict; + unsigned int tmpLength; + + if (!attrs) + { + [NSException raise: NSInvalidArgumentException + format: @"attributes is nil in method -addTemporaryAttributes:forCharacterRange: " + @"in class NSLayoutManager"]; + } + tmpLength = [_textStorage length]; + if (NSMaxRange(range) > tmpLength) + { + [NSException raise: NSRangeException + format: @"RangeError in method -addTemporaryAttributes:forCharacterRange: " + @"in class NSLayoutManager"]; + } + + attrDict = [self temporaryAttributesAtCharacterIndex: range.location + effectiveRange: &effectiveRange]; + + while (effectiveRange.location < NSMaxRange(range)) + { + effectiveRange = NSIntersectionRange(range, effectiveRange); + + newDict = [attrDict mutableCopy]; + [newDict addEntriesFromDictionary: attrs]; + [self setTemporaryAttributes: newDict + forCharacterRange: effectiveRange]; + RELEASE(newDict); + + if (NSMaxRange(effectiveRange) >= NSMaxRange(range)) + { + effectiveRange.location = NSMaxRange(range);// stop the loop... + } + else if (NSMaxRange(effectiveRange) < tmpLength) + { + attrDict = [self temporaryAttributesAtCharacterIndex: NSMaxRange(effectiveRange) + effectiveRange: &effectiveRange]; + } + } +} + +- (void) addTemporaryAttribute: (NSString *)attr + value: (id)value + forCharacterRange: (NSRange)range +{ + NSDictionary *dict = [[NSDictionary alloc] initWithObjects: &value + forKeys: &attr + count: 1]; + + [self addTemporaryAttributes: dict forCharacterRange: range]; + RELEASE(dict); +} + +- (void) removeTemporaryAttribute: (NSString *)attr + forCharacterRange: (NSRange)range +{ + NSRange effectiveRange; + NSDictionary *attrDict; + NSMutableDictionary *newDict; + unsigned int tmpLength; + + tmpLength = [_textStorage length]; + if (NSMaxRange(range) > tmpLength) + { + [NSException raise: NSRangeException + format: @"RangeError in method -removeTemporaryAttribute:forCharacterRange: " + @"in class NSLayoutManager"]; + } + + attrDict = [self temporaryAttributesAtCharacterIndex: range.location + effectiveRange: &effectiveRange]; + + while (effectiveRange.location < NSMaxRange(range)) + { + effectiveRange = NSIntersectionRange(range, effectiveRange); + + newDict = [attrDict mutableCopy]; + [newDict removeObjectForKey: attr]; + [self setTemporaryAttributes: newDict + forCharacterRange: effectiveRange]; + RELEASE(newDict); + + if (NSMaxRange(effectiveRange) >= NSMaxRange(range)) + { + effectiveRange.location = NSMaxRange(range);// stop the loop... + } + else if (NSMaxRange(effectiveRange) < tmpLength) + { + attrDict = [self temporaryAttributesAtCharacterIndex: NSMaxRange(effectiveRange) + effectiveRange: &effectiveRange]; + } + } +} + +- (id) temporaryAttribute: (NSString *)attr + atCharacterIndex: (NSUInteger)index + effectiveRange: (NSRange*)range +{ + NSDictionary *tmpDictionary; + + if (attr == nil) + { + if (range != 0) + { + *range = NSMakeRange(0, [_textStorage length]); + /* + * If attr is nil, then the attribute will not exist in the + * entire text - therefore range of the entire text must be correct + */ + } + return nil; + } + + tmpDictionary = [self temporaryAttributesAtCharacterIndex: index + effectiveRange: range]; + return [tmpDictionary objectForKey: attr]; +} + +- (id) temporaryAttribute: (NSString *)attr + atCharacterIndex: (NSUInteger)index + longestEffectiveRange: (NSRange*)longestRange + inRange: (NSRange)range +{ + id attrValue; + id tmpAttrValue; + NSRange tmpRange; + + if (range.location < 0 || NSMaxRange(range) > [_textStorage length]) + { + [NSException raise: NSRangeException + format: @"RangeError in method -temporaryAttribute:atCharacterIndex:longestEffectiveRange:inRange: in class NSLayoutManager"]; + } + + if (attr == nil) + return nil; + + attrValue = [self temporaryAttribute: attr + atCharacterIndex: index + effectiveRange: longestRange]; + + if (longestRange == 0) + return attrValue; + + while (longestRange->location > range.location) + { + //Check extend range backwards + tmpAttrValue = [self temporaryAttribute: attr + atCharacterIndex: longestRange->location-1 + effectiveRange: &tmpRange]; + if (tmpAttrValue == attrValue + || (attrValue != nil && [attrValue isEqual: tmpAttrValue])) + { + longestRange->length = NSMaxRange(*longestRange) - tmpRange.location; + longestRange->location = tmpRange.location; + } + else + { + break; + } + } + while (NSMaxRange(*longestRange) < NSMaxRange(range)) + { + //Check extend range forwards + tmpAttrValue = [self temporaryAttribute: attr + atCharacterIndex: longestRange->location-1 + effectiveRange: &tmpRange]; + if (tmpAttrValue == attrValue + || (attrValue != nil && [attrValue isEqual: tmpAttrValue])) + { + longestRange->length = NSMaxRange(tmpRange) - longestRange->location; + } + else + { + break; + } + } + *longestRange = NSIntersectionRange(*longestRange,range);//Clip to rangeLimit + return attrValue; +} + - (NSDictionary *) temporaryAttributesAtCharacterIndex: (NSUInteger)index longestEffectiveRange: (NSRange*)longestRange inRange: (NSRange)range { - // to be implemented - return nil; + NSDictionary *attrDictionary, *tmpDictionary; + NSRange tmpRange; + + if (range.location < 0 || NSMaxRange(range) > [_textStorage length]) + { + [NSException raise: NSRangeException + format: @"RangeError in method -temporaryAttributesAtCharacterIndex:longestEffectiveRange:inRange: in class NSLayoutManager"]; + } + + attrDictionary = [self temporaryAttributesAtCharacterIndex: index + effectiveRange: longestRange]; + if (longestRange == 0) + return attrDictionary; + + while (longestRange->location > range.location) + { + //Check extend range backwards + tmpDictionary = [self temporaryAttributesAtCharacterIndex: longestRange->location-1 + effectiveRange: &tmpRange]; + if ([tmpDictionary isEqualToDictionary: attrDictionary]) + { + longestRange->length = NSMaxRange(*longestRange) - tmpRange.location; + longestRange->location = tmpRange.location; + } + else + { + break; + } + } + while (NSMaxRange(*longestRange) < NSMaxRange(range)) + { + //Check extend range forwards + tmpDictionary = [self temporaryAttributesAtCharacterIndex: NSMaxRange(*longestRange) + effectiveRange: &tmpRange]; + if ([tmpDictionary isEqualToDictionary: attrDictionary]) + { + longestRange->length = NSMaxRange(tmpRange) - longestRange->location; + } + else + { + break; + } + } + //Clip to range + *longestRange = NSIntersectionRange(*longestRange, range); + return attrDictionary; } + @end