<commit_before>/*
 * Copyright (C) 2006 Apple Computer, 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
 * 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 "config.h"
#import "Pasteboard.h"

#import "CachedResource.h"
#import "CharacterNames.h"
#import "Document.h"
#import "DocumentFragment.h"
#import "Editor.h"
#import "EditorClient.h"
#import "Frame.h"
#import "HitTestResult.h"
#import "Image.h"
#import "KURL.h"
#import "LegacyWebArchive.h"
#import "LoaderNSURLExtras.h"
#import "MIMETypeRegistry.h"
#import "RenderImage.h"
#import "WebCoreNSStringExtras.h"
#import "WebCoreSystemInterface.h"
#import "markup.h"

#import <wtf/RetainPtr.h>

#include "webkit/glue/glue_util.h"
#include "webkit/glue/webkit_glue.h"


#if 0
@interface NSAttributedString (AppKitSecretsIKnowAbout)
- (id)_initWithDOMRange:(DOMRange *)domRange;
@end
#endif

namespace WebCore {

// FIXME: It's not great to have these both here and in WebKit.
NSString *WebArchivePboardType = @"Apple Web Archive pasteboard type";
NSString *WebSmartPastePboardType = @"NeXT smart paste pasteboard type";
NSString *WebURLNamePboardType = @"public.url-name";
NSString *WebURLPboardType = @"public.url";
NSString *WebURLsWithTitlesPboardType = @"WebURLsWithTitlesPboardType";

#ifndef BUILDING_ON_TIGER
static NSArray* selectionPasteboardTypes(bool canSmartCopyOrDelete, bool selectionContainsAttachments)
{
    if (selectionContainsAttachments) {
        if (canSmartCopyOrDelete)
            return [NSArray arrayWithObjects:WebSmartPastePboardType, WebArchivePboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, nil];
        else
            return [NSArray arrayWithObjects:WebArchivePboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, nil];
    } else { // Don't write RTFD to the pasteboard when the copied attributed string has no attachments.
        if (canSmartCopyOrDelete)
            return [NSArray arrayWithObjects:WebSmartPastePboardType, WebArchivePboardType, NSRTFPboardType, NSStringPboardType, nil];
        else
            return [NSArray arrayWithObjects:WebArchivePboardType, NSRTFPboardType, NSStringPboardType, nil];
    }
}
#endif

static NSArray* writableTypesForURL()
{
    static RetainPtr<NSArray> types = nil;
    if (!types) {
        types = [[NSArray alloc] initWithObjects:
            WebURLsWithTitlesPboardType,
            NSURLPboardType,
            WebURLPboardType,
            WebURLNamePboardType,
            NSStringPboardType,
            nil];
    }
    return types.get();
}

static NSArray* writableTypesForImage()
{
    static RetainPtr<NSMutableArray> types = nil;
    if (!types) {
        types = [[NSMutableArray alloc] initWithObjects:NSTIFFPboardType, nil];
        [types.get() addObjectsFromArray:writableTypesForURL()];
        [types.get() addObject:NSRTFDPboardType];
    }
    return types.get();
}

Pasteboard* Pasteboard::generalPasteboard() 
{
    static Pasteboard* pasteboard = new Pasteboard([NSPasteboard generalPasteboard]);
    return pasteboard;
}

Pasteboard::Pasteboard(NSPasteboard* pboard)
    : m_pasteboard(pboard)
{
}

void Pasteboard::clear()
{
    [m_pasteboard.get() declareTypes:[NSArray array] owner:nil];
}

static NSAttributedString *stripAttachmentCharacters(NSAttributedString *string)
{
    const unichar attachmentCharacter = NSAttachmentCharacter;
    static RetainPtr<NSString> attachmentCharacterString = [NSString stringWithCharacters:&attachmentCharacter length:1];
    NSMutableAttributedString *result = [[string mutableCopy] autorelease];
    NSRange attachmentRange = [[result string] rangeOfString:attachmentCharacterString.get()];
    while (attachmentRange.location != NSNotFound) {
        [result replaceCharactersInRange:attachmentRange withString:@""];
        attachmentRange = [[result string] rangeOfString:attachmentCharacterString.get()];
    }
    return result;
}

void Pasteboard::writeSelection(NSPasteboard* pasteboard, Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
{
    if (WebArchivePboardType == nil)
        Pasteboard::generalPasteboard(); //Initialises pasteboard types
    ASSERT(selectedRange);

    ExceptionCode ec = 0;
    WebCore::String html = createMarkup(selectedRange, 0, AnnotateForInterchange);
    
    NSData* htmlData = [NSData dataWithBytes:reinterpret_cast<const void*>(html.characters()) length:html.length()];
    NSAttributedString *attributedString = 
      [[[NSAttributedString alloc] initWithHTML:htmlData documentAttributes:NULL] autorelease];

#ifdef BUILDING_ON_TIGER
    // TODO(pinkerton): I don't think we need this, since we won't be used by the
    // OS as a web view embedded in Mail or other apps.
    //
    // 4930197: Mail overrides [WebHTMLView pasteboardTypesForSelection] in order to add another type to the pasteboard
    // after WebKit does.  On Tiger we must call this function so that Mail code will be executed, meaning that 
    // we can't call WebCore::Pasteboard's method for setting types. 
    
    NSArray *types = frame->editor()->client()->pasteboardTypesForSelection(frame);
    // Don't write RTFD to the pasteboard when the copied attributed string has no attachments.
    NSMutableArray *mutableTypes = nil;
    if (![attributedString containsAttachments]) {
        mutableTypes = [[types mutableCopy] autorelease];
        [mutableTypes removeObject:NSRTFDPboardType];
        types = mutableTypes;
    }
    [pasteboard declareTypes:types owner:nil];    
#else
    NSArray *types = selectionPasteboardTypes(canSmartCopyOrDelete, [attributedString containsAttachments]);
    [pasteboard declareTypes:types owner:nil];
    frame->editor()->client()->didSetSelectionTypesForPasteboard();
#endif
    
    // Put HTML on the pasteboard.
    if ([types containsObject:WebArchivePboardType]) {
        RefPtr<LegacyWebArchive> archive = LegacyWebArchive::createFromSelection(frame);
        RetainPtr<CFDataRef> data = archive ? archive->rawDataRepresentation() : 0;
        [pasteboard setData:(NSData *)data.get() forType:WebArchivePboardType];
    }
    
    // Put the attributed string on the pasteboard (RTF/RTFD format).
    if ([types containsObject:NSRTFDPboardType]) {
        NSData *RTFDData = [attributedString RTFDFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
        [pasteboard setData:RTFDData forType:NSRTFDPboardType];
    }
    if ([types containsObject:NSRTFPboardType]) {
        if ([attributedString containsAttachments])
            attributedString = stripAttachmentCharacters(attributedString);
        NSData *RTFData = [attributedString RTFFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
        [pasteboard setData:RTFData forType:NSRTFPboardType];
    }
    
    // Put plain string on the pasteboard.
    if ([types containsObject:NSStringPboardType]) {
        // Map &nbsp; to a plain old space because this is better for source code, other browsers do it,
        // and because HTML forces you to do this any time you want two spaces in a row.
        String text = selectedRange->text();
        text.replace('\\', frame->backslashAsCurrencySymbol());
        NSMutableString *s = [[[(NSString*)text copy] autorelease] mutableCopy];
        
        NSString *NonBreakingSpaceString = [NSString stringWithCharacters:&noBreakSpace length:1];
        [s replaceOccurrencesOfString:NonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
        [pasteboard setString:s forType:NSStringPboardType];
        [s release];
    }
    
    if ([types containsObject:WebSmartPastePboardType]) {
        [pasteboard setData:nil forType:WebSmartPastePboardType];
    }
}
    
void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
{
    Pasteboard::writeSelection(m_pasteboard.get(), selectedRange, canSmartCopyOrDelete, frame);
}

void Pasteboard::writeURL(NSPasteboard* pasteboard, NSArray* types, const KURL& url, const String& titleStr, Frame* frame)
{
    if (WebArchivePboardType == nil)
        Pasteboard::generalPasteboard(); //Initialises pasteboard types
   
    if (types == nil) {
        types = writableTypesForURL();
        [pasteboard declareTypes:types owner:nil];
    }
    
    ASSERT(!url.isEmpty());
    
    NSURL *cocoaURL = url;
    NSString *userVisibleString = frame->editor()->client()->userVisibleString(cocoaURL);
    
    NSString *title = (NSString*)titleStr;
    if ([title length] == 0) {
        title = [[cocoaURL path] lastPathComponent];<commit_msg>Stub out writing to the pasteboard. Ends up calling NSAttributedString initWithHTML which tries to load the system WebKit...and then EPIC FAIL. Helps the layout tests not time out so much until we think about this more. Review URL: http://codereview.chromium.org/7623<commit_after>/*
 * Copyright (C) 2006 Apple Computer, 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
 * 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 "config.h"
#import "Pasteboard.h"

#import "CachedResource.h"
#import "CharacterNames.h"
#import "Document.h"
#import "DocumentFragment.h"
#import "Editor.h"
#import "EditorClient.h"
#import "Frame.h"
#import "HitTestResult.h"
#import "Image.h"
#import "KURL.h"
#import "LegacyWebArchive.h"
#import "LoaderNSURLExtras.h"
#import "MIMETypeRegistry.h"
#import "RenderImage.h"
#import "WebCoreNSStringExtras.h"
#import "WebCoreSystemInterface.h"
#import "markup.h"

#import <wtf/RetainPtr.h>

#include "webkit/glue/glue_util.h"
#include "webkit/glue/webkit_glue.h"


#if 0
@interface NSAttributedString (AppKitSecretsIKnowAbout)
- (id)_initWithDOMRange:(DOMRange *)domRange;
@end
#endif

namespace WebCore {

// FIXME: It's not great to have these both here and in WebKit.
NSString *WebArchivePboardType = @"Apple Web Archive pasteboard type";
NSString *WebSmartPastePboardType = @"NeXT smart paste pasteboard type";
NSString *WebURLNamePboardType = @"public.url-name";
NSString *WebURLPboardType = @"public.url";
NSString *WebURLsWithTitlesPboardType = @"WebURLsWithTitlesPboardType";

#ifndef BUILDING_ON_TIGER
static NSArray* selectionPasteboardTypes(bool canSmartCopyOrDelete, bool selectionContainsAttachments)
{
    if (selectionContainsAttachments) {
        if (canSmartCopyOrDelete)
            return [NSArray arrayWithObjects:WebSmartPastePboardType, WebArchivePboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, nil];
        else
            return [NSArray arrayWithObjects:WebArchivePboardType, NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, nil];
    } else { // Don't write RTFD to the pasteboard when the copied attributed string has no attachments.
        if (canSmartCopyOrDelete)
            return [NSArray arrayWithObjects:WebSmartPastePboardType, WebArchivePboardType, NSRTFPboardType, NSStringPboardType, nil];
        else
            return [NSArray arrayWithObjects:WebArchivePboardType, NSRTFPboardType, NSStringPboardType, nil];
    }
}
#endif

static NSArray* writableTypesForURL()
{
    static RetainPtr<NSArray> types = nil;
    if (!types) {
        types = [[NSArray alloc] initWithObjects:
            WebURLsWithTitlesPboardType,
            NSURLPboardType,
            WebURLPboardType,
            WebURLNamePboardType,
            NSStringPboardType,
            nil];
    }
    return types.get();
}

static NSArray* writableTypesForImage()
{
    static RetainPtr<NSMutableArray> types = nil;
    if (!types) {
        types = [[NSMutableArray alloc] initWithObjects:NSTIFFPboardType, nil];
        [types.get() addObjectsFromArray:writableTypesForURL()];
        [types.get() addObject:NSRTFDPboardType];
    }
    return types.get();
}

Pasteboard* Pasteboard::generalPasteboard() 
{
    static Pasteboard* pasteboard = new Pasteboard([NSPasteboard generalPasteboard]);
    return pasteboard;
}

Pasteboard::Pasteboard(NSPasteboard* pboard)
    : m_pasteboard(pboard)
{
}

void Pasteboard::clear()
{
    [m_pasteboard.get() declareTypes:[NSArray array] owner:nil];
}

static NSAttributedString *stripAttachmentCharacters(NSAttributedString *string)
{
    const unichar attachmentCharacter = NSAttachmentCharacter;
    static RetainPtr<NSString> attachmentCharacterString = [NSString stringWithCharacters:&attachmentCharacter length:1];
    NSMutableAttributedString *result = [[string mutableCopy] autorelease];
    NSRange attachmentRange = [[result string] rangeOfString:attachmentCharacterString.get()];
    while (attachmentRange.location != NSNotFound) {
        [result replaceCharactersInRange:attachmentRange withString:@""];
        attachmentRange = [[result string] rangeOfString:attachmentCharacterString.get()];
    }
    return result;
}

void Pasteboard::writeSelection(NSPasteboard* pasteboard, Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
{
#if 0
// TODO(pinkerton): We need to figure out how to get copy/paste info back
// to the main process and let it manage the pasteboard. One major problem is
// that we can't rely on -[NSAttributedString initWithHTML] since it calls
// the system WebKit and that wrecks havoc with ObjC's single-level 
// namespace. That will cause some big problems getting rtf strings
// onto the pasteboard since we have no other way of creating that data
// ourselves. Punt for now.

    if (WebArchivePboardType == nil)
        Pasteboard::generalPasteboard(); //Initialises pasteboard types
    ASSERT(selectedRange);

    ExceptionCode ec = 0;
    WebCore::String html = createMarkup(selectedRange, 0, AnnotateForInterchange);
    
    NSData* htmlData = [NSData dataWithBytes:reinterpret_cast<const void*>(html.characters()) length:html.length()];
    NSAttributedString *attributedString = 
      [[[NSAttributedString alloc] initWithHTML:htmlData documentAttributes:NULL] autorelease];

#ifdef BUILDING_ON_TIGER
    // TODO(pinkerton): I don't think we need this, since we won't be used by the
    // OS as a web view embedded in Mail or other apps.
    //
    // 4930197: Mail overrides [WebHTMLView pasteboardTypesForSelection] in order to add another type to the pasteboard
    // after WebKit does.  On Tiger we must call this function so that Mail code will be executed, meaning that 
    // we can't call WebCore::Pasteboard's method for setting types. 
    
    NSArray *types = frame->editor()->client()->pasteboardTypesForSelection(frame);
    // Don't write RTFD to the pasteboard when the copied attributed string has no attachments.
    NSMutableArray *mutableTypes = nil;
    if (![attributedString containsAttachments]) {
        mutableTypes = [[types mutableCopy] autorelease];
        [mutableTypes removeObject:NSRTFDPboardType];
        types = mutableTypes;
    }
    [pasteboard declareTypes:types owner:nil];    
#else
    NSArray *types = selectionPasteboardTypes(canSmartCopyOrDelete, [attributedString containsAttachments]);
    [pasteboard declareTypes:types owner:nil];
    frame->editor()->client()->didSetSelectionTypesForPasteboard();
#endif
    
    // Put HTML on the pasteboard.
    if ([types containsObject:WebArchivePboardType]) {
        RefPtr<LegacyWebArchive> archive = LegacyWebArchive::createFromSelection(frame);
        RetainPtr<CFDataRef> data = archive ? archive->rawDataRepresentation() : 0;
        [pasteboard setData:(NSData *)data.get() forType:WebArchivePboardType];
    }
    
    // Put the attributed string on the pasteboard (RTF/RTFD format).
    if ([types containsObject:NSRTFDPboardType]) {
        NSData *RTFDData = [attributedString RTFDFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
        [pasteboard setData:RTFDData forType:NSRTFDPboardType];
    }
    if ([types containsObject:NSRTFPboardType]) {
        if ([attributedString containsAttachments])
            attributedString = stripAttachmentCharacters(attributedString);
        NSData *RTFData = [attributedString RTFFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil];
        [pasteboard setData:RTFData forType:NSRTFPboardType];
    }
    
    // Put plain string on the pasteboard.
    if ([types containsObject:NSStringPboardType]) {
        // Map &nbsp; to a plain old space because this is better for source code, other browsers do it,
        // and because HTML forces you to do this any time you want two spaces in a row.
        String text = selectedRange->text();
        text.replace('\\', frame->backslashAsCurrencySymbol());
        NSMutableString *s = [[[(NSString*)text copy] autorelease] mutableCopy];
        
        NSString *NonBreakingSpaceString = [NSString stringWithCharacters:&noBreakSpace length:1];
        [s replaceOccurrencesOfString:NonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])];
        [pasteboard setString:s forType:NSStringPboardType];
        [s release];
    }
    
    if ([types containsObject:WebSmartPastePboardType]) {
        [pasteboard setData:nil forType:WebSmartPastePboardType];
    }
#endif
}
    
void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
{
    Pasteboard::writeSelection(m_pasteboard.get(), selectedRange, canSmartCopyOrDelete, frame);
}

void Pasteboard::writeURL(NSPasteboard* pasteboard, NSArray* types, const KURL& url, const String& titleStr, Frame* frame)
{
    if (WebArchivePboardType == nil)
        Pasteboard::generalPasteboard(); //Initialises pasteboard types
   
    if (types == nil) {
        types = writableTypesForURL();
        [pasteboard declareTypes:types owner:nil];
    }
    
    ASSERT(!url.isEmpty());
    
    NSURL *cocoaURL = url;
    NSString *userVisibleString = frame->editor()->client()->userVisibleString(cocoaURL);
    
    NSString *title = (NSString*)titleStr;
    if ([title length] == 0) {
        title = [[cocoaURL path] lastPathComponent];
{'fraction_non_alphanumeric': 0.09263646234330274, 'fraction_numerical': 0.002615733886092192, 'mean_word_length': 4.282325338894682, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '964980', 'n_tokens_mistral': 6095, 'n_tokens_neox': 5712, 'n_words': 1683}