Home | History | Annotate | Download | only in haiku
      1 /*
      2  * Copyright (C) 2006 Zack Rusin <zack (at) kde.org>
      3  * Copyright (C) 2007 Ryan Leavengood <leavengood (at) gmail.com>
      4  * Copyright (C) 2010 Stephan Amus <superstippi (at) gmx.de>
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include "config.h"
     29 #include "Pasteboard.h"
     30 
     31 #include "DocumentFragment.h"
     32 #include "Editor.h"
     33 #include "Frame.h"
     34 #include "KURL.h"
     35 #include "NotImplemented.h"
     36 #include "TextResourceDecoder.h"
     37 #include "markup.h"
     38 #include <support/Locker.h>
     39 #include <Clipboard.h>
     40 #include <Message.h>
     41 #include <String.h>
     42 #include <wtf/text/CString.h>
     43 
     44 
     45 namespace WebCore {
     46 
     47 Pasteboard::Pasteboard()
     48 {
     49 }
     50 
     51 Pasteboard::~Pasteboard()
     52 {
     53 }
     54 
     55 Pasteboard* Pasteboard::generalPasteboard()
     56 {
     57     static Pasteboard pasteboard;
     58     return &pasteboard;
     59 }
     60 
     61 // BClipboard unfortunately does not derive from BLocker, so we cannot use BAutolock.
     62 class AutoClipboardLocker {
     63 public:
     64     AutoClipboardLocker(BClipboard* clipboard)
     65         : m_clipboard(clipboard)
     66         , m_isLocked(clipboard && clipboard->Lock())
     67     {
     68     }
     69 
     70     ~AutoClipboardLocker()
     71     {
     72         if (m_isLocked)
     73             m_clipboard->Unlock();
     74     }
     75 
     76     bool isLocked() const
     77     {
     78         return m_isLocked;
     79     }
     80 
     81 private:
     82     BClipboard* m_clipboard;
     83     bool m_isLocked;
     84 };
     85 
     86 void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
     87 {
     88     AutoClipboardLocker locker(be_clipboard);
     89     if (!locker.isLocked())
     90         return;
     91 
     92     be_clipboard->Clear();
     93     BMessage* data = be_clipboard->Data();
     94     if (!data)
     95         return;
     96 
     97     BString string(frame->selectedText());
     98 
     99     // Replace unwanted representation of blank lines
    100     const char* utf8BlankLine = "\302\240\n";
    101     string.ReplaceAll(utf8BlankLine, "\n");
    102 
    103     data->AddData("text/plain", B_MIME_TYPE, string.String(), string.Length());
    104 
    105     BString markupString(createMarkup(selectedRange, 0, AnnotateForInterchange, false, AbsoluteURLs));
    106     data->AddData("text/html", B_MIME_TYPE, markupString.String(), markupString.Length());
    107 
    108     be_clipboard->Commit();
    109 }
    110 
    111 void Pasteboard::writePlainText(const String& text)
    112 {
    113     AutoClipboardLocker locker(be_clipboard);
    114     if (!locker.isLocked())
    115         return;
    116 
    117     be_clipboard->Clear();
    118     BMessage* data = be_clipboard->Data();
    119     if (!data)
    120         return;
    121 
    122     BString string(text);
    123     data->AddData("text/plain", B_MIME_TYPE, string.String(), string.Length());
    124     be_clipboard->Commit();
    125 }
    126 
    127 bool Pasteboard::canSmartReplace()
    128 {
    129     notImplemented();
    130     return false;
    131 }
    132 
    133 String Pasteboard::plainText(Frame* frame)
    134 {
    135     AutoClipboardLocker locker(be_clipboard);
    136     if (!locker.isLocked())
    137         return String();
    138 
    139     BMessage* data = be_clipboard->Data();
    140     if (!data)
    141         return String();
    142 
    143     const char* buffer = 0;
    144     ssize_t bufferLength;
    145     BString string;
    146     if (data->FindData("text/plain", B_MIME_TYPE, reinterpret_cast<const void**>(&buffer), &bufferLength) == B_OK)
    147         string.Append(buffer, bufferLength);
    148 
    149     return string;
    150 }
    151 
    152 PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context,
    153                                                           bool allowPlainText, bool& chosePlainText)
    154 {
    155     chosePlainText = false;
    156 
    157     AutoClipboardLocker locker(be_clipboard);
    158     if (!locker.isLocked())
    159         return 0;
    160 
    161     BMessage* data = be_clipboard->Data();
    162     if (!data)
    163         return 0;
    164 
    165     const char* buffer = 0;
    166     ssize_t bufferLength;
    167     if (data->FindData("text/html", B_MIME_TYPE, reinterpret_cast<const void**>(&buffer), &bufferLength) == B_OK) {
    168         RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/plain", "UTF-8", true);
    169         String html = decoder->decode(buffer, bufferLength);
    170         html += decoder->flush();
    171 
    172         if (!html.isEmpty()) {
    173             RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, "", FragmentScriptingNotAllowed);
    174             if (fragment)
    175                 return fragment.release();
    176         }
    177     }
    178 
    179     if (!allowPlainText)
    180         return 0;
    181 
    182     if (data->FindData("text/plain", B_MIME_TYPE, reinterpret_cast<const void**>(&buffer), &bufferLength) == B_OK) {
    183         BString plainText(buffer, bufferLength);
    184 
    185         chosePlainText = true;
    186         RefPtr<DocumentFragment> fragment = createFragmentFromText(context.get(), plainText);
    187         if (fragment)
    188             return fragment.release();
    189     }
    190 
    191     return 0;
    192 }
    193 
    194 void Pasteboard::writeURL(const KURL& url, const String&, Frame*)
    195 {
    196     AutoClipboardLocker locker(be_clipboard);
    197     if (!locker.isLocked())
    198         return;
    199 
    200     be_clipboard->Clear();
    201 
    202     BMessage* data = be_clipboard->Data();
    203     if (!data)
    204         return;
    205 
    206     BString string(url.string());
    207     data->AddData("text/plain", B_MIME_TYPE, string.String(), string.Length());
    208     be_clipboard->Commit();
    209 }
    210 
    211 void Pasteboard::writeImage(Node*, const KURL&, const String&)
    212 {
    213     notImplemented();
    214 }
    215 
    216 void Pasteboard::clear()
    217 {
    218     AutoClipboardLocker locker(be_clipboard);
    219     if (!locker.isLocked())
    220         return;
    221 
    222     be_clipboard->Clear();
    223     be_clipboard->Commit();
    224 }
    225 
    226 } // namespace WebCore
    227 
    228