// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//


/*	CFAttributedString.c
	Copyright (c) 2004-2015, Apple Inc. All rights reserved.
*/

#include <CoreFoundation/CFBase.h>
#include <CoreFoundation/CFAttributedString.h>
#include "CFRunArray.h"
#include <CoreFoundation/ForFoundationOnly.h>
#include "CFInternal.h"

struct __CFAttributedString {
    CFRuntimeBase base;
    CFStringRef string;
    CFRunArrayRef attributeArray;
};

/* Mutability is determined by a bit in the CF base. Mutable if bit 0 is 0.  So by default freshly created attributed strings are mutable.  Don't change mutability once the object has been created and initialized!
*/
CF_INLINE Boolean __CFAttributedStringIsMutable(CFAttributedStringRef attrStr) {
    return __CFBitfieldGetValue(((const CFRuntimeBase *)attrStr)->_cfinfo[CF_INFO_BITS], 0, 0) ? false : true;
}

CF_INLINE void __CFAttributedStringSetMutable(CFAttributedStringRef attrStr, Boolean flag) {
    __CFBitfieldSetValue(((CFRuntimeBase *)attrStr)->_cfinfo[CF_INFO_BITS], 0, 0, (flag ? 0 : 1));
}


/* Assertions
*/
#define __CFAssertIsAttributedString(cf) __CFGenericValidateType(cf, CFAttributedStringGetTypeID())
#define __CFAssertIndexIsInBounds(cf, idx) CFAssert((idx) >= 0 && (idx) < CFAttributedStringGetLength(cf), __kCFLogAssertion, "%s(): index %d out of bounds (length %d)", __PRETTY_FUNCTION__, idx, CFAttributedStringGetLength(cf))
#define __CFAssertRangeIsInBounds(cf, idx, count) CFAssert((idx) >= 0 && (idx + count) <= CFAttributedStringGetLength(cf), __kCFLogAssertion, "%s(): range %d,%d out of bounds (length %d)", __PRETTY_FUNCTION__, idx, count, CFAttributedStringGetLength(cf))
#define __CFAssertRangeIsWithinLength(len, idx, count) CFAssert((idx) >= 0 && (idx + count) <= len, __kCFLogAssertion, "%s(): range %d,%d out of bounds (length %d)", __PRETTY_FUNCTION__, idx, count, len)
#define __CFAssertIsAttributedStringAndMutable(cf) CFAssert((CFGetTypeID(cf) == CFAttributedStringGetTypeID()) && __CFAttributedStringIsMutable(cf), __kCFLogAssertion, "%s(): argument not a CFMutableAttributedString", __PRETTY_FUNCTION__)


/*** "Polymorphic" functions ***/

static Boolean __CFAttributedStringEqual(CFTypeRef cf1, CFTypeRef cf2) {
    CFAttributedStringRef attrStr = (CFAttributedStringRef)cf1;
    CFAttributedStringRef otherAttrStr = (CFAttributedStringRef)cf2;

    if (!CFEqual(attrStr->string, CFAttributedStringGetString(otherAttrStr))) return false;
        
    CFIndex len = CFStringGetLength(attrStr->string);
    CFIndex curLoc = 0;
    CFRange myRange = {0, 0};
    CFRange otherRange = {0, 0};
    CFDictionaryRef myAttrs = NULL;
    CFDictionaryRef otherAttrs = NULL;
    
    while (curLoc < len) {	
	if (curLoc >= myRange.length + myRange.location) myAttrs = CFAttributedStringGetAttributes(attrStr, curLoc, &myRange);
	if (curLoc >= otherRange.length + otherRange.location) otherAttrs = CFAttributedStringGetAttributes(otherAttrStr, curLoc, &otherRange);
	if (!CFEqual(myAttrs, otherAttrs)) return false;
	curLoc = otherRange.length + otherRange.location;
	if (myRange.length + myRange.location < curLoc) curLoc = myRange.length + myRange.location;
    }        
    return true;
}

static CFHashCode __CFAttributedStringHash(CFTypeRef cf) {
    CFAttributedStringRef attrStr = (CFAttributedStringRef)cf;
    return CFHash(attrStr->string);
}

// Create a stack or malloc'ed array of CFTypeRef

#define localArrayStackSize 256

#define createLocalArray(array, count) \
    CFTypeRef array ## Buf[localArrayStackSize];  \
    CFTypeRef *array = (count <= localArrayStackSize) ? (array ## Buf) : ((count < LONG_MAX / sizeof(CFTypeRef)) ? malloc(count * sizeof(CFTypeRef)) : NULL);

#define freeLocalArray(array) \
    if (array != array ## Buf) free(array);

static CFStringRef __CFAttributedStringCopyDescription(CFTypeRef cf) {
    CFMutableStringRef result = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
    CFAttributedStringRef attrStr = (CFAttributedStringRef)cf;
    CFIndex len = CFStringGetLength(attrStr->string);
    CFRange range = {0, 0};
    while (range.location < len) {
	CFDictionaryRef attrs = CFAttributedStringGetAttributes(attrStr, range.location, &range);
	CFStringRef substring = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, attrStr->string, range);
	CFStringAppend(result, substring);
	CFRelease(substring);
	CFStringAppendFormat(result, NULL, CFSTR(" %p {"), attrs);
        CFIndex cnt = CFDictionaryGetCount(attrs);
        createLocalArray(keys, cnt);
        createLocalArray(values, cnt);
	CFDictionaryGetKeysAndValues(attrs, keys, values);
	while (cnt--) CFStringAppendFormat(result, NULL, CFSTR("%@=%@%s"), keys[cnt], values[cnt], ((cnt == 0) ? "" : ", "));
	CFStringAppendFormat(result, NULL, CFSTR("} Len %ld\n"), (long)range.length);
	range.location += range.length;
        freeLocalArray(keys);
        freeLocalArray(values);
    }
    return result;
}

static void __CFAttributedStringDeallocate(CFTypeRef cf) {
    CFAttributedStringRef attrStr = (CFAttributedStringRef)cf;
    CFRelease(attrStr->string);
    CFRelease(attrStr->attributeArray);
}

static CFTypeID __kCFAttributedStringTypeID = _kCFRuntimeNotATypeID;

static const CFRuntimeClass __CFAttributedStringClass = {
    0,
    "CFAttributedString",
    NULL,	// init
    NULL,	// copy
    __CFAttributedStringDeallocate,
    __CFAttributedStringEqual,
    __CFAttributedStringHash,
    NULL,	// 
    __CFAttributedStringCopyDescription
};

CFTypeID CFAttributedStringGetTypeID(void) {
    static dispatch_once_t initOnce;
    dispatch_once(&initOnce, ^{ __kCFAttributedStringTypeID = _CFRuntimeRegisterClass(&__CFAttributedStringClass); });
    return __kCFAttributedStringTypeID;
}


/*** Creation and Copy routines ***/

/* Create an "internal" attributes dictionary
*/
static CFMutableDictionaryRef __CFAttributedStringCreateAttributesDictionary(CFAllocatorRef alloc, CFDictionaryRef attrs) {
    if (attrs) {
        return CFDictionaryCreateMutableCopy(alloc, 0, attrs);
    } else {
        return CFDictionaryCreateMutable(alloc, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    }
}

/* Does no argument checking; doesn't shortcut to doing a copy if the range is the whole string. (This is used by the other functions to create copies). 
*/
CFMutableAttributedStringRef __CFAttributedStringCreateMutableWithSubstring(CFAllocatorRef alloc, CFAttributedStringRef attrStr, CFRange range) {
    CFMutableAttributedStringRef newAttrStr = CFAttributedStringCreateMutable(alloc, 0);

    // Initialize the string (!!! this should be done more efficiently!) 
    CFStringRef str = CFStringCreateWithSubstring(alloc, attrStr->string, range); 
    CFAttributedStringReplaceString(newAttrStr, CFRangeMake(0, 0), str);
    CFRelease(str);
    
    CFIndex curLoc = range.location;
    CFIndex endLoc = range.location + range.length;
  
    while (curLoc < endLoc) {
	CFRange effectiveRange;
	CFDictionaryRef attrs = CFAttributedStringGetAttributes(attrStr, curLoc, &effectiveRange);
	if (curLoc != effectiveRange.location) effectiveRange.length -= (curLoc - effectiveRange.location);
	if (curLoc + effectiveRange.length > endLoc) effectiveRange.length = endLoc - curLoc;
        CFAttributedStringSetAttributes(newAttrStr, CFRangeMake(curLoc - range.location, effectiveRange.length), attrs, true);
	curLoc += effectiveRange.length;
    }    

    return newAttrStr;
}


CFAttributedStringRef CFAttributedStringCreate(CFAllocatorRef alloc, CFStringRef str, CFDictionaryRef attributes) {
    CFIndex size = sizeof(struct __CFAttributedString) - sizeof(CFRuntimeBase);
    struct __CFAttributedString *newAttrStr = (struct __CFAttributedString *)_CFRuntimeCreateInstance(alloc, CFAttributedStringGetTypeID(), size, NULL);

    if (newAttrStr == NULL) return NULL;

    newAttrStr->string = CFStringCreateCopy(alloc, str);
    newAttrStr->attributeArray = CFRunArrayCreate(alloc);
    
    CFIndex len = CFStringGetLength(newAttrStr->string);
    if (len) {
	CFMutableDictionaryRef attrs = __CFAttributedStringCreateAttributesDictionary(alloc, attributes);
	CFRunArrayInsert(newAttrStr->attributeArray, CFRangeMake(0, len), attrs);
	CFRelease(attrs);
    }

    __CFAttributedStringSetMutable(newAttrStr, false);     // Make it immutable
    
    return (CFAttributedStringRef)newAttrStr;
}

CFAttributedStringRef CFAttributedStringCreateWithSubstring(CFAllocatorRef alloc, CFAttributedStringRef attrStr, CFRange range) {
//  CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), CFAttributedStringRef, (NSAttributedString *)attrStr, _createAttributedSubstringWithRange:NSMakeRange(range.location, range.length));

    __CFAssertIsAttributedString(attrStr);
    __CFAssertRangeIsInBounds(attrStr, range.location, range.length);

    CFIndex len = CFAttributedStringGetLength(attrStr);
    
    // !!! Bounds check on range here

    if (range.location == 0 && range.length == len) {
        return CFAttributedStringCreateCopy(alloc, attrStr);  /* This in turn might take a retain shortcut */
    } else {
        struct __CFAttributedString *newAttrStr = __CFAttributedStringCreateMutableWithSubstring(alloc, attrStr, range);
        __CFAttributedStringSetMutable(newAttrStr, false);
        return (CFAttributedStringRef)newAttrStr;
    }
}

/* CFAttributedStringCreateCopy() will do a refcount bump if the argument is immutable and has the same allocator
*/
CFAttributedStringRef CFAttributedStringCreateCopy(CFAllocatorRef alloc, CFAttributedStringRef attrStr) {
//  CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), CFAttributedStringRef, (NSAttributedString *)attrStr, copy);
    
    __CFAssertIsAttributedString(attrStr);
    if (!__CFAttributedStringIsMutable(attrStr) &&                                      // If the string is not mutable
        ((alloc ? alloc : __CFGetDefaultAllocator()) == __CFGetAllocator(attrStr))) {   //  and it has the same allocator as the one we're using
	CFRetain(attrStr);                                                              // Then just retain instead of making a true copy
	return attrStr;
    } else {
        CFIndex len = CFAttributedStringGetLength(attrStr);
        CFMutableAttributedStringRef newAttrStr =__CFAttributedStringCreateMutableWithSubstring(alloc, attrStr, CFRangeMake(0, len));
        __CFAttributedStringSetMutable(newAttrStr, false);     // Make it immutable
        return (CFAttributedStringRef)newAttrStr;
    }
}

/* CFAttributedStringCreateWithRuns() creates an attributed string from the specified string and a list of sparse attribute dictionaries.  See CFAttributedStringPriv.h for info.
*/
CFAttributedStringRef _CFAttributedStringCreateWithRuns(CFAllocatorRef alloc, CFStringRef str, const CFDictionaryRef *attrDictionaries, const CFRange *runRanges, CFIndex numRuns) {
    CFIndex size = sizeof(struct __CFAttributedString) - sizeof(CFRuntimeBase);
    struct __CFAttributedString *newAttrStr = (struct __CFAttributedString *)_CFRuntimeCreateInstance(alloc, CFAttributedStringGetTypeID(), size, NULL);

    if (newAttrStr == NULL) return NULL;

    newAttrStr->string = CFStringCreateCopy(alloc, str);
    newAttrStr->attributeArray = CFRunArrayCreate(alloc);

    // First fill attributed string with empty attribute dictionary
    CFIndex len = CFStringGetLength(newAttrStr->string);
    if (len) {
	CFMutableDictionaryRef attrs = __CFAttributedStringCreateAttributesDictionary(alloc, NULL);
	CFRunArrayInsert(newAttrStr->attributeArray, CFRangeMake(0, len), attrs);
	CFRelease(attrs);
    }

    // Now set the various ranges    
    CFIndex cnt;
    for (cnt = 0; cnt < numRuns; cnt++) {
	CFMutableDictionaryRef attrs = __CFAttributedStringCreateAttributesDictionary(alloc, attrDictionaries[cnt]);
	__CFAssertRangeIsWithinLength(len, runRanges[cnt].location, runRanges[cnt].length);
	CFRunArrayReplace(newAttrStr->attributeArray, runRanges[cnt], attrs, runRanges[cnt].length);
	CFRelease(attrs);
    }

    __CFAttributedStringSetMutable(newAttrStr, false);     // Make it immutable
    
    return (CFAttributedStringRef)newAttrStr;
}


CFMutableAttributedStringRef CFAttributedStringCreateMutable(CFAllocatorRef alloc, CFIndex maxLength) {
    CFIndex size = sizeof(struct __CFAttributedString) - sizeof(CFRuntimeBase);
    struct __CFAttributedString *newAttrStr = (CFMutableAttributedStringRef)_CFRuntimeCreateInstance(alloc, CFAttributedStringGetTypeID(), size, NULL);

    if (newAttrStr == NULL) return NULL;

    newAttrStr->string = CFStringCreateMutable(alloc, maxLength);
    newAttrStr->attributeArray = CFRunArrayCreate(alloc);

    return (CFMutableAttributedStringRef)newAttrStr;

}

CFMutableAttributedStringRef CFAttributedStringCreateMutableCopy(CFAllocatorRef alloc, CFIndex maxLength, CFAttributedStringRef attrStr) {
//  CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), CFMutableAttributedStringRef, (NSAttributedString *)attrStr, mutableCopy);
    
    __CFAssertIsAttributedString(attrStr);

    // !!! Need to deal with maxLength
    return __CFAttributedStringCreateMutableWithSubstring(alloc, attrStr, CFRangeMake(0, CFStringGetLength(attrStr->string)));
}



/*** CFAttributedString functionality ***/

CFStringRef CFAttributedStringGetString(CFAttributedStringRef attrStr) {
    CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), CFStringRef, (NSAttributedString *)attrStr, string);
    __CFAssertIsAttributedString(attrStr);
    
    return attrStr->string;
}

CFIndex CFAttributedStringGetLength(CFAttributedStringRef attrStr) {
    CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), CFIndex, (NSAttributedString *)attrStr, length);
    __CFAssertIsAttributedString(attrStr);
    
    return CFStringGetLength(attrStr->string);
}

CFDictionaryRef CFAttributedStringGetAttributes(CFAttributedStringRef attrStr, CFIndex loc, CFRange *effectiveRange) {
    CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), CFDictionaryRef, (NSAttributedString *)attrStr, attributesAtIndex:(NSUInteger)loc effectiveRange:(NSRange *)effectiveRange);
    __CFAssertIsAttributedString(attrStr);
    __CFAssertIndexIsInBounds(attrStr, loc);
    
    return (CFDictionaryRef)CFRunArrayGetValueAtIndex(attrStr->attributeArray, loc, effectiveRange, NULL);
}

CFTypeRef CFAttributedStringGetAttribute(CFAttributedStringRef attrStr, CFIndex loc, CFStringRef attrName, CFRange *effectiveRange) {
    CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), CFTypeRef, (NSAttributedString *)attrStr, attribute:(NSString *)attrName atIndex:(NSUInteger)loc effectiveRange:(NSRange *)effectiveRange);
    __CFAssertIsAttributedString(attrStr);
    __CFAssertIndexIsInBounds(attrStr, loc);

    CFDictionaryRef attrs = (CFDictionaryRef)CFRunArrayGetValueAtIndex(attrStr->attributeArray, loc, effectiveRange, NULL);
    return CFDictionaryGetValue(attrs, attrName);
}

CFDictionaryRef CFAttributedStringGetAttributesAndLongestEffectiveRange(CFAttributedStringRef attrStr, CFIndex location, CFRange rangeLimit, CFRange *longestEffectiveRange) {
    CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), CFDictionaryRef, (NSAttributedString *)attrStr, attributesAtIndex:(NSUInteger)location longestEffectiveRange:(NSRange *)longestEffectiveRange inRange:NSMakeRange(rangeLimit.location, rangeLimit.length));
    __CFAssertIsAttributedString(attrStr);
    __CFAssertRangeIsInBounds(attrStr, rangeLimit.location, rangeLimit.length);
    __CFAssertIndexIsInBounds(attrStr, location);

    CFDictionaryRef attrs = CFAttributedStringGetAttributes(attrStr, location, longestEffectiveRange);
    
    if (longestEffectiveRange) {    // No need to do any of this if the range isn't desired
        CFIndex leftEnd, rightEnd;
	CFDictionaryRef other;
        CFRange tmpRange;

        // First go right and set rightEnd pointing past the end
	tmpRange = *longestEffectiveRange;
        do {
            if ((rightEnd = tmpRange.location + tmpRange.length) >= rangeLimit.location + rangeLimit.length) break;
            other = CFAttributedStringGetAttributes(attrStr, rightEnd, &tmpRange);
        } while (CFEqual(other, attrs));

	// Now go back and set leftEnd
	tmpRange = *longestEffectiveRange;
        do {
	    if ((leftEnd = tmpRange.location) <= rangeLimit.location) break;
            other = CFAttributedStringGetAttributes(attrStr, leftEnd - 1, &tmpRange);
        } while (CFEqual(other, attrs));

        // This basically intersects the rangeLimit with leftEnd,rightEnd
        longestEffectiveRange->location = (leftEnd < rangeLimit.location) ? rangeLimit.location : leftEnd;
        CFIndex rangeEnd = rangeLimit.location + rangeLimit.length;
        longestEffectiveRange->length = ((rangeEnd < rightEnd) ? rangeEnd : rightEnd) - longestEffectiveRange->location;
    }
    return attrs;
}

CFTypeRef CFAttributedStringGetAttributeAndLongestEffectiveRange(CFAttributedStringRef attrStr, CFIndex location, CFStringRef attrName, CFRange rangeLimit, CFRange *longestEffectiveRange) {
    CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), CFTypeRef, (NSAttributedString *)attrStr, attribute:(NSString *)attrName atIndex:(NSUInteger)location longestEffectiveRange:(NSRange *)longestEffectiveRange inRange: NSMakeRange(rangeLimit.location, rangeLimit.length));
    __CFAssertIsAttributedString(attrStr);
    __CFAssertRangeIsInBounds(attrStr, rangeLimit.location, rangeLimit.length);
    __CFAssertIndexIsInBounds(attrStr, location);

    CFTypeRef attr = CFAttributedStringGetAttribute(attrStr, location, attrName, longestEffectiveRange);

    if (longestEffectiveRange) {    // No need to do any of this if the range isn't desired
        CFIndex leftEnd, rightEnd;
	CFTypeRef other;
        CFRange tmpRange;

        // First go right and set rightEnd pointing past the end
	tmpRange = *longestEffectiveRange;
        do {
            if ((rightEnd = tmpRange.location + tmpRange.length) >= rangeLimit.location + rangeLimit.length) break;
            other = CFAttributedStringGetAttribute(attrStr, rightEnd, attrName, &tmpRange);
        } while ((other == attr) || (other && attr && CFEqual(other, attr)));  // The first check is to catch nil as well

	// Now go back and set leftEnd
	tmpRange = *longestEffectiveRange;
        do {
	    if ((leftEnd = tmpRange.location) <= rangeLimit.location) break;
            other = CFAttributedStringGetAttribute(attrStr, leftEnd - 1, attrName, &tmpRange);
        } while ((other == attr) || (other && attr && CFEqual(other, attr)));  // The first check is to catch nil as well

        // This basically intersects the rangeLimit with leftEnd,rightEnd
        longestEffectiveRange->location = (leftEnd < rangeLimit.location) ? rangeLimit.location : leftEnd;
        CFIndex rangeEnd = rangeLimit.location + rangeLimit.length;
        longestEffectiveRange->length = ((rangeEnd < rightEnd) ? rangeEnd : rightEnd) - longestEffectiveRange->location;
    }
    return attr;
}


/* The next two functions are SPI which allow return bulk information about attributes.  See CFAttributedStringPriv.h for info.
*/
CFIndex _CFAttributedStringGetNumberOfRuns(CFAttributedStringRef attrStr, Boolean includeEmpty) {
    CFIndex numRuns = 0;
    CFRange remainingRange = CFRangeMake(0, CFAttributedStringGetLength(attrStr));
    while (remainingRange.length > 0) {
	CFRange thisRange;
	CFDictionaryRef dict = CFAttributedStringGetAttributesAndLongestEffectiveRange(attrStr, remainingRange.location, remainingRange, &thisRange);
	if (includeEmpty || (CFDictionaryGetCount(dict) > 0)) numRuns++;
	remainingRange.length -= thisRange.length;
	remainingRange.location += thisRange.length;
    }
    return numRuns;
}

void _CFAttributedStringGetRuns(CFAttributedStringRef attrStr, Boolean includeEmpty, CFDictionaryRef *attrDictionaries, CFRange *runRanges) {
    CFRange remainingRange = CFRangeMake(0, CFAttributedStringGetLength(attrStr));
    while (remainingRange.length > 0) {
	CFRange thisRange;
	CFDictionaryRef dict = CFAttributedStringGetAttributesAndLongestEffectiveRange(attrStr, remainingRange.location, remainingRange, &thisRange);
	if (includeEmpty || (CFDictionaryGetCount(dict) > 0)) {
	    if (attrDictionaries) *attrDictionaries++ = dict;
	    if (runRanges) *runRanges++ = thisRange;
	}
	remainingRange.length -= thisRange.length;
	remainingRange.location += thisRange.length;
    }
}


/*** CFMutableAttributedString functionality ***/

static void __CFDictionaryAddMultiple(CFMutableDictionaryRef dict, CFTypeRef *keys, CFTypeRef *values, CFIndex numAdditionalItems) {
    CFIndex cnt;
    for (cnt = 0; cnt < numAdditionalItems; cnt++) CFDictionarySetValue(dict, keys[cnt], values[cnt]);
}

/* ??? This is not properly implemented at this point! We need to return a proxy
*/
CFMutableStringRef CFAttributedStringGetMutableString(CFMutableAttributedStringRef attrStr) {
    CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), CFMutableStringRef, (NSMutableAttributedString *)attrStr, mutableString);
    return NULL;  /* (CFMutableStringRef)(attrStr->string); */
}

void CFAttributedStringReplaceString(CFMutableAttributedStringRef attrStr, CFRange range, CFStringRef replacement) {
    CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), void, (NSMutableAttributedString *)attrStr, replaceCharactersInRange:NSMakeRange(range.location, range.length) withString:(NSString *)replacement);
    __CFAssertIsAttributedStringAndMutable(attrStr);
    __CFAssertRangeIsInBounds(attrStr, range.location, range.length);
    
    CFIndex replacementLen = CFStringGetLength(replacement);
    CFMutableDictionaryRef attributesToBeUsed = NULL;
    if (replacementLen > 0) {
        // By default extend replaced attributes, or take them from the previous character
        if (range.length > 0) {
            attributesToBeUsed = (CFMutableDictionaryRef)CFRunArrayGetValueAtIndex(attrStr->attributeArray, range.location, NULL, NULL);
	    CFRetain(attributesToBeUsed);
        } else if (range.location > 0) {
            attributesToBeUsed = (CFMutableDictionaryRef)CFRunArrayGetValueAtIndex(attrStr->attributeArray, range.location - 1, NULL, NULL);
	    CFRetain(attributesToBeUsed);
        } else if (CFStringGetLength(attrStr->string) > 0) {
            attributesToBeUsed = (CFMutableDictionaryRef)CFRunArrayGetValueAtIndex(attrStr->attributeArray, 0, NULL, NULL);
	    CFRetain(attributesToBeUsed);
       } else {
            attributesToBeUsed = __CFAttributedStringCreateAttributesDictionary(CFGetAllocator(attrStr), NULL);
        }
    }
    if (range.length > 0) {
        CFRunArrayReplace(attrStr->attributeArray, range, attributesToBeUsed, replacementLen);
    } else if (replacementLen) {
        CFRunArrayInsert(attrStr->attributeArray, CFRangeMake(range.location, replacementLen), attributesToBeUsed);
    }
    if (attributesToBeUsed) CFRelease(attributesToBeUsed);
    CFStringReplace((CFMutableStringRef)(attrStr->string), range, replacement);
    // !!! [self edited:NSAttributedStringEditedCharacters range:range changeInLength:replacementLen - range.length];
}

void CFAttributedStringSetAttributes(CFMutableAttributedStringRef attrStr, CFRange range, CFDictionaryRef replacementAttrs, Boolean clearOtherAttributes) {
    if (clearOtherAttributes) {
	CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), void, (NSMutableAttributedString *)attrStr, setAttributes:(NSDictionary *)replacementAttrs range: NSMakeRange(range.location, range.length));
    } else {
	CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), void, (NSMutableAttributedString *)attrStr, addAttributes:(NSDictionary *)replacementAttrs range: NSMakeRange(range.location, range.length));
    }

    __CFAssertIsAttributedStringAndMutable(attrStr);
    __CFAssertRangeIsInBounds(attrStr, range.location, range.length);

    if (clearOtherAttributes) { // Just blast all attribute dictionaries in the specified range
        if (range.length) {
            CFMutableDictionaryRef attrs = __CFAttributedStringCreateAttributesDictionary(CFGetAllocator(attrStr), replacementAttrs);
            CFRunArrayReplace(attrStr->attributeArray, range, attrs, range.length);
            CFRelease(attrs);
            // !!! [self edited:NSAttributedStringEditedAttributes range:range changeInLength:0];
        }
    } else {    // More difficult --- set specified keys and values on the existing dictionaries in the specified range
        CFIndex numAdditionalItems = CFDictionaryGetCount(replacementAttrs);
        if (numAdditionalItems) {
            // Extract the new keys and values so we don't do it over and over for each range
            createLocalArray(additionalKeys, numAdditionalItems);
            createLocalArray(additionalValues, numAdditionalItems);
            CFDictionaryGetKeysAndValues(replacementAttrs, additionalKeys, additionalValues);
            
            // CFAttributedStringBeginEditing(attrStr);
            while (range.length) {
                CFRange effectiveRange;
                CFMutableDictionaryRef attrs = (CFMutableDictionaryRef)CFRunArrayGetValueAtIndex(attrStr->attributeArray, range.location, &effectiveRange, NULL);
                // Intersect effectiveRange and range
                if (effectiveRange.location < range.location) {
                    effectiveRange.length -= (range.location - effectiveRange.location);
                    effectiveRange.location = range.location;
                }
                if (effectiveRange.length > range.length) effectiveRange.length = range.length;
                // We need to make a new copy
                attrs = __CFAttributedStringCreateAttributesDictionary(CFGetAllocator(attrStr), attrs);
                __CFDictionaryAddMultiple(attrs, additionalKeys, additionalValues, numAdditionalItems);
                CFRunArrayReplace(attrStr->attributeArray, effectiveRange, attrs, effectiveRange.length);
                CFRelease(attrs);
                range.length -= effectiveRange.length;
                range.location += effectiveRange.length;
            }
            // CFAttributedStringEndEditing(attrStr);
            
            freeLocalArray(additionalKeys);
            freeLocalArray(additionalValues);
        }
    }
}

void CFAttributedStringSetAttribute(CFMutableAttributedStringRef attrStr, CFRange range, CFStringRef attrName, CFTypeRef value) {
    CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), void, (NSMutableAttributedString *)attrStr, addAttribute:(NSString *)attrName value:(id) value range:NSMakeRange(range.location, range.length));
    __CFAssertIsAttributedStringAndMutable(attrStr);
    __CFAssertRangeIsInBounds(attrStr, range.location, range.length);

    // CFAttributedStringBeginEditing(attrStr);
    while (range.length) {
        CFRange effectiveRange;
        // effectiveRange.location returned here may be equal to or smaller than range.location
        CFMutableDictionaryRef attrs = (CFMutableDictionaryRef)CFRunArrayGetValueAtIndex(attrStr->attributeArray, range.location, &effectiveRange, NULL);
        // Intersect effectiveRange and range
        if (effectiveRange.location < range.location) {
            effectiveRange.length -= (range.location - effectiveRange.location);
            effectiveRange.location = range.location;	    
        }
        if (effectiveRange.length > range.length) effectiveRange.length = range.length;
        // First check to see if the same value already exists; this will avoid a copy
        CFTypeRef existingValue = CFDictionaryGetValue(attrs, attrName);
        if (!existingValue || !CFEqual(existingValue, value)) {
            // We need to make a new copy
            attrs = __CFAttributedStringCreateAttributesDictionary(CFGetAllocator(attrStr), attrs);
            CFDictionarySetValue(attrs, attrName, value);
            CFRunArrayReplace(attrStr->attributeArray, effectiveRange, attrs, effectiveRange.length);
            CFRelease(attrs);
        }
        range.length -= effectiveRange.length;
        range.location += effectiveRange.length;
    }
    // CFAttributedStringEndEditing(attrStr);
}

void CFAttributedStringRemoveAttribute(CFMutableAttributedStringRef attrStr, CFRange range, CFStringRef attrName) {
    CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), void, (NSMutableAttributedString *)attrStr, removeAttribute:(NSString *)attrName range:NSMakeRange(range.location, range.length));
    __CFAssertIsAttributedStringAndMutable(attrStr);
    __CFAssertRangeIsInBounds(attrStr, range.location, range.length);

    // CFAttributedStringBeginEditing(attrStr);
    while (range.length) {
        CFRange effectiveRange;
        CFMutableDictionaryRef attrs = (CFMutableDictionaryRef)CFRunArrayGetValueAtIndex(attrStr->attributeArray, range.location, &effectiveRange, NULL);
        // Intersect effectiveRange and range
        if (effectiveRange.location < range.location) {
            effectiveRange.length -= (range.location - effectiveRange.location);
            effectiveRange.location = range.location;	    
        }
        if (effectiveRange.length > range.length) effectiveRange.length = range.length;
        // First check to see if the value is not there; this will avoid a copy
        if (CFDictionaryContainsKey(attrs, attrName)) {
            // We need to make a new copy
            attrs = __CFAttributedStringCreateAttributesDictionary(CFGetAllocator(attrStr), attrs);
            CFDictionaryRemoveValue(attrs, attrName);
            CFRunArrayReplace(attrStr->attributeArray, effectiveRange, attrs, effectiveRange.length);
            CFRelease(attrs);
        }
        range.length -= effectiveRange.length;
        range.location += effectiveRange.length;
    }
    // CFAttributedStringEndEditing(attrStr);
}

void CFAttributedStringReplaceAttributedString(CFMutableAttributedStringRef attrStr, CFRange range, CFAttributedStringRef replacement) {
    CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), void, (NSMutableAttributedString *)attrStr, replaceCharactersInRange:NSMakeRange(range.location, range.length) withAttributedString:(NSAttributedString *)replacement);
    __CFAssertIsAttributedStringAndMutable(attrStr);
    __CFAssertRangeIsInBounds(attrStr, range.location, range.length);

    CFStringRef otherStr = CFAttributedStringGetString(replacement);
    CFIndex stringLen = CFStringGetLength(otherStr);

    if (stringLen > 0) {
	CFAllocatorRef allocator = CFGetAllocator(attrStr);
	CFRange attrRange = {0, 0};
	while (attrRange.location < stringLen) {
	    CFDictionaryRef otherAttrs = CFAttributedStringGetAttributes(replacement, attrRange.location, &attrRange);
            CFMutableDictionaryRef attrs = __CFAttributedStringCreateAttributesDictionary(allocator, otherAttrs);
	    CFRunArrayInsert(attrStr->attributeArray, CFRangeMake(attrRange.location + range.location, attrRange.length), attrs);
	    CFRelease(attrs);
	    attrRange.location += attrRange.length;
	}
    }
    if (range.length > 0) CFRunArrayDelete(attrStr->attributeArray, CFRangeMake(range.location + stringLen, range.length));
    CFStringReplace((CFMutableStringRef)(attrStr->string), range, otherStr);
    // [self edited:NSAttributedStringEditedCharacters|NSAttributedStringEditedAttributes range:range changeInLength:stringLen - range.length];
}

void CFAttributedStringBeginEditing(CFMutableAttributedStringRef attrStr) {
    CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), void, (NSMutableAttributedString *)attrStr, beginEditing);
}

void CFAttributedStringEndEditing(CFMutableAttributedStringRef attrStr) {
    CF_OBJC_FUNCDISPATCHV(CFAttributedStringGetTypeID(), void, (NSMutableAttributedString *)attrStr, endEditing);
}



/*** Functions for NSCFAttributedString usage ***/

CFIndex _CFAttributedStringGetLength(CFAttributedStringRef attrStr) {
    return CFStringGetLength(attrStr->string);
}


int _CFAttributedStringCheckAndReplace(CFMutableAttributedStringRef attrStr, CFRange range, CFStringRef replacement) {
    CFIndex len = CFStringGetLength(attrStr->string);
    if (range.location > len || (range.location + range.length > len)) return _CFStringErrBounds;
    if (!__CFAttributedStringIsMutable(attrStr)) return _CFStringErrNotMutable;
    CFAttributedStringReplaceString(attrStr, range, replacement);   // ??? Do this faster!
    return _CFStringErrNone;
}

int _CFAttributedStringCheckAndReplaceAttributed(CFMutableAttributedStringRef attrStr, CFRange range, CFAttributedStringRef replacement) {
    CFIndex len = CFStringGetLength(attrStr->string);
    if (range.location > len || (range.location + range.length > len)) return _CFStringErrBounds;
    if (!__CFAttributedStringIsMutable(attrStr)) return _CFStringErrNotMutable;
    if (replacement) {  // Special: NULL means delete
	CFAttributedStringReplaceAttributedString(attrStr, range, replacement);   // ??? Do this faster!
    } else {
        CFAttributedStringReplaceString(attrStr, range, CFSTR(""));
    }
    return _CFStringErrNone;
}

int _CFAttributedStringCheckAndSetAttributes(CFMutableAttributedStringRef attrStr, CFRange range, CFTypeRef attrOrAttrs, Boolean clearOthers) {
    CFIndex len = CFStringGetLength(attrStr->string);
    if (range.location > len || (range.location + range.length > len)) return _CFStringErrBounds;
    if (!__CFAttributedStringIsMutable(attrStr)) return _CFStringErrNotMutable;
    CFAttributedStringSetAttributes(attrStr, range, (CFDictionaryRef)attrOrAttrs, clearOthers);  // ??? Do this faster!
    return _CFStringErrNone;
}

int _CFAttributedStringCheckAndSetAttribute(CFMutableAttributedStringRef attrStr, CFRange range, CFStringRef attrName, CFTypeRef attr) {
    CFIndex len = CFStringGetLength(attrStr->string);
    if (range.location > len || (range.location + range.length > len)) return _CFStringErrBounds;
    if (!__CFAttributedStringIsMutable(attrStr)) return _CFStringErrNotMutable;
    if (!attrName) return _CFStringErrNilArg;
    if (attr) {
	CFAttributedStringSetAttribute(attrStr, range, attrName, attr);  // ??? Do this faster!
    } else {
	CFAttributedStringRemoveAttribute(attrStr, range, attrName);    // ??? Do this faster!
    }
    return _CFStringErrNone;
}



