1/* 2 * Copyright (C) 2005, 2007, 2008 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#import "WebNSAttributedStringExtras.h" 30 31#import "DOMRangeInternal.h" 32#import "WebDataSourcePrivate.h" 33#import "WebFrame.h" 34#import "WebFrameInternal.h" 35#import "WebTypesInternal.h" 36#import <WebCore/BlockExceptions.h> 37#import <WebCore/ColorMac.h> 38#import <WebCore/CSSHelper.h> 39#import <WebCore/Document.h> 40#import <WebCore/Element.h> 41#import <WebCore/Frame.h> 42#import <WebCore/FrameLoader.h> 43#import <WebCore/HTMLNames.h> 44#import <WebCore/Image.h> 45#import <WebCore/InlineTextBox.h> 46#import <WebCore/Range.h> 47#import <WebCore/RenderImage.h> 48#import <WebCore/RenderListItem.h> 49#import <WebCore/RenderObject.h> 50#import <WebCore/RenderStyle.h> 51#import <WebCore/RenderText.h> 52#import <WebCore/SimpleFontData.h> 53#import <WebCore/Text.h> 54#import <WebCore/TextIterator.h> 55 56using namespace WebCore; 57using namespace HTMLNames; 58 59struct ListItemInfo { 60 unsigned start; 61 unsigned end; 62}; 63 64static NSFileWrapper *fileWrapperForElement(Element* e) 65{ 66 NSFileWrapper *wrapper = nil; 67 BEGIN_BLOCK_OBJC_EXCEPTIONS; 68 69 const AtomicString& attr = e->getAttribute(srcAttr); 70 if (!attr.isEmpty()) { 71 NSURL *URL = e->document()->completeURL(attr); 72 wrapper = [[kit(e->document()->frame()) _dataSource] _fileWrapperForURL:URL]; 73 } 74 if (!wrapper) { 75 RenderImage* renderer = toRenderImage(e->renderer()); 76 if (renderer->cachedImage() && !renderer->cachedImage()->errorOccurred()) { 77 wrapper = [[NSFileWrapper alloc] initRegularFileWithContents:(NSData *)(renderer->cachedImage()->image()->getTIFFRepresentation())]; 78 [wrapper setPreferredFilename:@"image.tiff"]; 79 [wrapper autorelease]; 80 } 81 } 82 83 return wrapper; 84 85 END_BLOCK_OBJC_EXCEPTIONS; 86 87 return nil; 88} 89 90@implementation NSAttributedString (WebKitExtras) 91 92- (NSAttributedString *)_web_attributedStringByStrippingAttachmentCharacters 93{ 94 // This code was originally copied from NSTextView 95 NSRange attachmentRange; 96 NSString *originalString = [self string]; 97 static NSString *attachmentCharString = nil; 98 99 if (!attachmentCharString) { 100 unichar chars[2]; 101 if (!attachmentCharString) { 102 chars[0] = NSAttachmentCharacter; 103 chars[1] = 0; 104 attachmentCharString = [[NSString alloc] initWithCharacters:chars length:1]; 105 } 106 } 107 108 attachmentRange = [originalString rangeOfString:attachmentCharString]; 109 if (attachmentRange.location != NSNotFound && attachmentRange.length > 0) { 110 NSMutableAttributedString *newAttributedString = [[self mutableCopyWithZone:NULL] autorelease]; 111 112 while (attachmentRange.location != NSNotFound && attachmentRange.length > 0) { 113 [newAttributedString replaceCharactersInRange:attachmentRange withString:@""]; 114 attachmentRange = [[newAttributedString string] rangeOfString:attachmentCharString]; 115 } 116 return newAttributedString; 117 } 118 119 return self; 120} 121 122+ (NSAttributedString *)_web_attributedStringFromRange:(Range*)range 123{ 124 NSMutableAttributedString *string = [[NSMutableAttributedString alloc] init]; 125 NSUInteger stringLength = 0; 126 RetainPtr<NSMutableDictionary> attrs(AdoptNS, [[NSMutableDictionary alloc] init]); 127 128 for (TextIterator it(range); !it.atEnd(); it.advance()) { 129 RefPtr<Range> currentTextRange = it.range(); 130 ExceptionCode ec = 0; 131 Node* startContainer = currentTextRange->startContainer(ec); 132 Node* endContainer = currentTextRange->endContainer(ec); 133 int startOffset = currentTextRange->startOffset(ec); 134 int endOffset = currentTextRange->endOffset(ec); 135 136 if (startContainer == endContainer && (startOffset == endOffset - 1)) { 137 Node* node = startContainer->childNode(startOffset); 138 if (node && node->hasTagName(imgTag)) { 139 NSFileWrapper *fileWrapper = fileWrapperForElement(static_cast<Element*>(node)); 140 NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper]; 141 [string appendAttributedString:[NSAttributedString attributedStringWithAttachment:attachment]]; 142 [attachment release]; 143 } 144 } 145 146 int currentTextLength = it.length(); 147 if (!currentTextLength) 148 continue; 149 150 RenderObject* renderer = startContainer->renderer(); 151 ASSERT(renderer); 152 if (!renderer) 153 continue; 154 RenderStyle* style = renderer->style(); 155 NSFont *font = style->font().primaryFont()->getNSFont(); 156 [attrs.get() setObject:font forKey:NSFontAttributeName]; 157 if (style->color().isValid()) 158 [attrs.get() setObject:nsColor(style->color()) forKey:NSForegroundColorAttributeName]; 159 else 160 [attrs.get() removeObjectForKey:NSForegroundColorAttributeName]; 161 if (style->backgroundColor().isValid()) 162 [attrs.get() setObject:nsColor(style->backgroundColor()) forKey:NSBackgroundColorAttributeName]; 163 else 164 [attrs.get() removeObjectForKey:NSBackgroundColorAttributeName]; 165 166 RetainPtr<NSString> substring(AdoptNS, [[NSString alloc] initWithCharactersNoCopy:const_cast<UChar*>(it.characters()) length:currentTextLength freeWhenDone:NO]); 167 [string replaceCharactersInRange:NSMakeRange(stringLength, 0) withString:substring.get()]; 168 [string setAttributes:attrs.get() range:NSMakeRange(stringLength, currentTextLength)]; 169 stringLength += currentTextLength; 170 } 171 172 return [string autorelease]; 173} 174 175@end 176