• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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