Home | History | Annotate | Download | only in Misc
      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 
     56 using namespace WebCore;
     57 using namespace HTMLNames;
     58 
     59 struct ListItemInfo {
     60     unsigned start;
     61     unsigned end;
     62 };
     63 
     64 static 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