2009-07-07 Jiahua Huang <jhuangjiahua@gmail.com>
[WebKit-https.git] / WebCore / platform / gtk / PasteboardGtk.cpp
index 6301aed..781baf5 100644 (file)
@@ -1,31 +1,20 @@
 /*
- * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
- * Copyright (C) 2007 Holger Hans Peter Freyther
- * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ *  Copyright (C) 2007 Holger Hans Peter Freyther
+ *  Copyright (C) 2007 Alp Toker <alp@atoker.com>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
  *
- * 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. 
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission. 
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
  *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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.
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include "config.h"
 #include "Frame.h"
 #include "NotImplemented.h"
 #include "PlatformString.h"
+#include "TextResourceDecoder.h"
 #include "Image.h"
 #include "RenderImage.h"
 #include "KURL.h"
+#include "markup.h"
 
 #include <gtk/gtk.h>
 
 namespace WebCore {
 
+/* FIXME: we must get rid of this and use the enum in webkitwebview.h someway */
+typedef enum
+{
+    WEBKIT_WEB_VIEW_TARGET_INFO_HTML = - 1,
+    WEBKIT_WEB_VIEW_TARGET_INFO_TEXT = - 2
+} WebKitWebViewTargetInfo;
+
+class PasteboardSelectionData {
+public:
+    PasteboardSelectionData(gchar* text, gchar* markup)
+        : m_text(text)
+        , m_markup(markup) { }
+
+    ~PasteboardSelectionData() {
+        g_free(m_text);
+        g_free(m_markup);
+    }
+
+    const gchar* text() const { return m_text; }
+    const gchar* markup() const { return m_markup; }
+
+private:
+    gchar* m_text;
+    gchar* m_markup;
+};
+
+static void clipboard_get_contents_cb(GtkClipboard *clipboard, GtkSelectionData *selection_data,
+                                      guint info, gpointer data) {
+    PasteboardSelectionData* clipboardData = reinterpret_cast<PasteboardSelectionData*>(data);
+    ASSERT(clipboardData);
+    if ((gint)info == WEBKIT_WEB_VIEW_TARGET_INFO_HTML) {
+        gtk_selection_data_set(selection_data, selection_data->target, 8,
+                               reinterpret_cast<const guchar*>(clipboardData->markup()),
+                               g_utf8_strlen(clipboardData->markup(), -1));
+    } else
+        gtk_selection_data_set_text(selection_data, clipboardData->text(), -1);
+}
+
+static void clipboard_clear_contents_cb(GtkClipboard *clipboard, gpointer data) {
+    PasteboardSelectionData* clipboardData = reinterpret_cast<PasteboardSelectionData*>(data);
+    ASSERT(clipboardData);
+    delete clipboardData;
+}
+
+
 Pasteboard* Pasteboard::generalPasteboard()
 {
     static Pasteboard* pasteboard = new Pasteboard();
@@ -57,27 +93,41 @@ Pasteboard::Pasteboard()
 
 Pasteboard::~Pasteboard()
 {
-    notImplemented();
+    delete m_helper;
 }
 
-void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
+void Pasteboard::setHelper(PasteboardHelper* helper)
 {
-    GtkClipboard* clipboard = gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD);
+    m_helper = helper;
+}
 
-    String text = frame->selectedText();
-    gtk_clipboard_set_text(clipboard, text.utf8().data(), text.utf8().length());
+void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
+{
+    GtkClipboard* clipboard = m_helper->getClipboard(frame);
+    gchar* text = g_strdup(frame->selectedText().utf8().data());
+    gchar* markup = g_strdup(createMarkup(selectedRange, 0, AnnotateForInterchange).utf8().data());
+    PasteboardSelectionData* data = new PasteboardSelectionData(text, markup);
+
+    gint n_targets;
+    GtkTargetEntry* targets = gtk_target_table_new_from_list(m_helper->getCopyTargetList(frame), &n_targets);
+    gtk_clipboard_set_with_data(clipboard, targets, n_targets,
+                                clipboard_get_contents_cb, clipboard_clear_contents_cb, data);
+    gtk_target_table_free(targets, n_targets);
 }
 
-void Pasteboard::writeURL(const KURL&, const String&, Frame*)
+void Pasteboard::writeURL(const KURL& url, const String&, Frame* frame)
 {
-    notImplemented();
+    if (url.isEmpty())
+        return;
+
+    GtkClipboard* clipboard = m_helper->getClipboard(frame);
+    GtkClipboard* primary = m_helper->getPrimary(frame);
+    gtk_clipboard_set_text(clipboard, url.string().utf8().data(), url.string().utf8().length());
+    gtk_clipboard_set_text(primary, url.string().utf8().data(), url.string().utf8().length());
 }
 
 void Pasteboard::writeImage(Node* node, const KURL&, const String&)
 {
-    // TODO: Enable this when Image gets GdkPixbuf support
-
-    /*
     GtkClipboard* clipboard = gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD);
 
     ASSERT(node && node->renderer() && node->renderer()->isImage());
@@ -87,10 +137,9 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String&)
     Image* image = cachedImage->image();
     ASSERT(image);
 
-    gtk_clipboard_set_image(clipboard, image->pixbuf());
-    */
-
-    notImplemented();
+    GdkPixbuf* pixbuf = image->getGdkPixbuf();
+    gtk_clipboard_set_image(clipboard, pixbuf);
+    g_object_unref(pixbuf);
 }
 
 void Pasteboard::clear()
@@ -106,15 +155,46 @@ bool Pasteboard::canSmartReplace()
     return false;
 }
 
-PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame*, PassRefPtr<Range>, bool, bool&)
+PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context,
+                                                          bool allowPlainText, bool& chosePlainText)
 {
-    notImplemented();
+    GdkAtom textHtml = gdk_atom_intern_static_string("text/html");
+    GtkClipboard* clipboard = m_helper->getCurrentTarget(frame);
+    chosePlainText = false;
+
+    if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, textHtml)) {
+        ASSERT(data->data);
+        RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/plain", "UTF-8", true);
+        String html = decoder->decode(reinterpret_cast<char*>(data->data), data->length);
+        html += decoder->flush();
+        gtk_selection_data_free(data);
+
+        if (!html.isEmpty()) {
+            RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, "");
+            if (fragment)
+                return fragment.release();
+        }
+    }
+
+    if (!allowPlainText)
+        return 0;
+
+    if (gchar* utf8 = gtk_clipboard_wait_for_text(clipboard)) {
+        String text = String::fromUTF8(utf8);
+        g_free(utf8);
+
+        chosePlainText = true;
+        RefPtr<DocumentFragment> fragment = createFragmentFromText(context.get(), text);
+        if (fragment)
+            return fragment.release();
+    }
+
     return 0;
 }
 
-String Pasteboard::plainText(Frame*)
+String Pasteboard::plainText(Frame* frame)
 {
-    GtkClipboard* clipboard = gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD);
+    GtkClipboard* clipboard = m_helper->getCurrentTarget(frame);
 
     gchar* utf8 = gtk_clipboard_wait_for_text(clipboard);
 
@@ -126,4 +206,5 @@ String Pasteboard::plainText(Frame*)
 
     return text;
 }
+
 }