/* * Copyright (C) 2005, 2007, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "WebNSAttributedStringExtras.h" #import "DOMRangeInternal.h" #import "WebDataSourcePrivate.h" #import "WebFrame.h" #import "WebFrameInternal.h" #import "WebTypesInternal.h" #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import using namespace WebCore; using namespace HTMLNames; struct ListItemInfo { unsigned start; unsigned end; }; static NSFileWrapper *fileWrapperForElement(Element* e) { NSFileWrapper *wrapper = nil; BEGIN_BLOCK_OBJC_EXCEPTIONS; const AtomicString& attr = e->getAttribute(srcAttr); if (!attr.isEmpty()) { NSURL *URL = e->document()->completeURL(attr); wrapper = [[kit(e->document()->frame()) _dataSource] _fileWrapperForURL:URL]; } if (!wrapper) { RenderImage* renderer = toRenderImage(e->renderer()); if (renderer->cachedImage() && !renderer->cachedImage()->errorOccurred()) { wrapper = [[NSFileWrapper alloc] initRegularFileWithContents:(NSData *)(renderer->cachedImage()->image()->getTIFFRepresentation())]; [wrapper setPreferredFilename:@"image.tiff"]; [wrapper autorelease]; } } return wrapper; END_BLOCK_OBJC_EXCEPTIONS; return nil; } @implementation NSAttributedString (WebKitExtras) - (NSAttributedString *)_web_attributedStringByStrippingAttachmentCharacters { // This code was originally copied from NSTextView NSRange attachmentRange; NSString *originalString = [self string]; static NSString *attachmentCharString = nil; if (!attachmentCharString) { unichar chars[2]; if (!attachmentCharString) { chars[0] = NSAttachmentCharacter; chars[1] = 0; attachmentCharString = [[NSString alloc] initWithCharacters:chars length:1]; } } attachmentRange = [originalString rangeOfString:attachmentCharString]; if (attachmentRange.location != NSNotFound && attachmentRange.length > 0) { NSMutableAttributedString *newAttributedString = [[self mutableCopyWithZone:NULL] autorelease]; while (attachmentRange.location != NSNotFound && attachmentRange.length > 0) { [newAttributedString replaceCharactersInRange:attachmentRange withString:@""]; attachmentRange = [[newAttributedString string] rangeOfString:attachmentCharString]; } return newAttributedString; } return self; } + (NSAttributedString *)_web_attributedStringFromRange:(Range*)range { NSMutableAttributedString *string = [[NSMutableAttributedString alloc] init]; NSUInteger stringLength = 0; RetainPtr attrs(AdoptNS, [[NSMutableDictionary alloc] init]); for (TextIterator it(range); !it.atEnd(); it.advance()) { RefPtr currentTextRange = it.range(); ExceptionCode ec = 0; Node* startContainer = currentTextRange->startContainer(ec); Node* endContainer = currentTextRange->endContainer(ec); int startOffset = currentTextRange->startOffset(ec); int endOffset = currentTextRange->endOffset(ec); if (startContainer == endContainer && (startOffset == endOffset - 1)) { Node* node = startContainer->childNode(startOffset); if (node && node->hasTagName(imgTag)) { NSFileWrapper *fileWrapper = fileWrapperForElement(static_cast(node)); NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper]; [string appendAttributedString:[NSAttributedString attributedStringWithAttachment:attachment]]; [attachment release]; } } int currentTextLength = it.length(); if (!currentTextLength) continue; RenderObject* renderer = startContainer->renderer(); ASSERT(renderer); if (!renderer) continue; RenderStyle* style = renderer->style(); NSFont *font = style->font().primaryFont()->getNSFont(); [attrs.get() setObject:font forKey:NSFontAttributeName]; if (style->visitedDependentColor(CSSPropertyColor).alpha()) [attrs.get() setObject:nsColor(style->visitedDependentColor(CSSPropertyColor)) forKey:NSForegroundColorAttributeName]; else [attrs.get() removeObjectForKey:NSForegroundColorAttributeName]; if (style->visitedDependentColor(CSSPropertyBackgroundColor).alpha()) [attrs.get() setObject:nsColor(style->visitedDependentColor(CSSPropertyBackgroundColor)) forKey:NSBackgroundColorAttributeName]; else [attrs.get() removeObjectForKey:NSBackgroundColorAttributeName]; RetainPtr substring(AdoptNS, [[NSString alloc] initWithCharactersNoCopy:const_cast(it.characters()) length:currentTextLength freeWhenDone:NO]); [string replaceCharactersInRange:NSMakeRange(stringLength, 0) withString:substring.get()]; [string setAttributes:attrs.get() range:NSMakeRange(stringLength, currentTextLength)]; stringLength += currentTextLength; } return [string autorelease]; } @end