Home | History | Annotate | Download | only in gtk
      1 /*
      2  *  Copyright (C) 2007 Holger Hans Peter Freyther
      3  *  Copyright (C) 2007 Alp Toker <alp (at) atoker.com>
      4  *
      5  *  This library is free software; you can redistribute it and/or
      6  *  modify it under the terms of the GNU Lesser General Public
      7  *  License as published by the Free Software Foundation; either
      8  *  version 2 of the License, or (at your option) any later version.
      9  *
     10  *  This library is distributed in the hope that it will be useful,
     11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  *  Lesser General Public License for more details.
     14  *
     15  *  You should have received a copy of the GNU Lesser General Public
     16  *  License along with this library; if not, write to the Free Software
     17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     18  */
     19 
     20 #include "config.h"
     21 #include "Pasteboard.h"
     22 
     23 #include "CString.h"
     24 #include "DocumentFragment.h"
     25 #include "Frame.h"
     26 #include "NotImplemented.h"
     27 #include "PlatformString.h"
     28 #include "TextResourceDecoder.h"
     29 #include "Image.h"
     30 #include "RenderImage.h"
     31 #include "KURL.h"
     32 #include "markup.h"
     33 
     34 #include <gtk/gtk.h>
     35 
     36 namespace WebCore {
     37 
     38 class PasteboardSelectionData {
     39 public:
     40     PasteboardSelectionData(gchar* text, gchar* markup)
     41         : m_text(text)
     42         , m_markup(markup) { }
     43 
     44     ~PasteboardSelectionData() {
     45         g_free(m_text);
     46         g_free(m_markup);
     47     }
     48 
     49     const gchar* text() const { return m_text; }
     50     const gchar* markup() const { return m_markup; }
     51 
     52 private:
     53     gchar* m_text;
     54     gchar* m_markup;
     55 };
     56 
     57 static void clipboard_get_contents_cb(GtkClipboard *clipboard, GtkSelectionData *selection_data,
     58                                       guint info, gpointer data) {
     59     PasteboardSelectionData* clipboardData = reinterpret_cast<PasteboardSelectionData*>(data);
     60     ASSERT(clipboardData);
     61     if ((gint)info == Pasteboard::generalPasteboard()->m_helper->getWebViewTargetInfoHtml())
     62         gtk_selection_data_set(selection_data, selection_data->target, 8,
     63                                reinterpret_cast<const guchar*>(clipboardData->markup()),
     64                                g_utf8_strlen(clipboardData->markup(), -1));
     65     else
     66         gtk_selection_data_set_text(selection_data, clipboardData->text(), -1);
     67 }
     68 
     69 static void clipboard_clear_contents_cb(GtkClipboard *clipboard, gpointer data) {
     70     PasteboardSelectionData* clipboardData = reinterpret_cast<PasteboardSelectionData*>(data);
     71     ASSERT(clipboardData);
     72     delete clipboardData;
     73 }
     74 
     75 
     76 Pasteboard* Pasteboard::generalPasteboard()
     77 {
     78     static Pasteboard* pasteboard = new Pasteboard();
     79     return pasteboard;
     80 }
     81 
     82 Pasteboard::Pasteboard()
     83 {
     84     notImplemented();
     85 }
     86 
     87 Pasteboard::~Pasteboard()
     88 {
     89     delete m_helper;
     90 }
     91 
     92 void Pasteboard::setHelper(PasteboardHelper* helper)
     93 {
     94     m_helper = helper;
     95 }
     96 
     97 void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
     98 {
     99     GtkClipboard* clipboard = m_helper->getClipboard(frame);
    100     gchar* text = g_strdup(frame->selectedText().utf8().data());
    101     gchar* markup = g_strdup(createMarkup(selectedRange, 0, AnnotateForInterchange).utf8().data());
    102     PasteboardSelectionData* data = new PasteboardSelectionData(text, markup);
    103 
    104     gint n_targets;
    105     GtkTargetEntry* targets = gtk_target_table_new_from_list(m_helper->targetList(), &n_targets);
    106     gtk_clipboard_set_with_data(clipboard, targets, n_targets,
    107                                 clipboard_get_contents_cb, clipboard_clear_contents_cb, data);
    108     gtk_target_table_free(targets, n_targets);
    109 }
    110 
    111 void Pasteboard::writePlainText(const String& text)
    112 {
    113     CString utf8 = text.utf8();
    114     GtkClipboard* clipboard = gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD);
    115     gtk_clipboard_set_text(clipboard, utf8.data(), utf8.length());
    116 }
    117 
    118 void Pasteboard::writeURL(const KURL& url, const String&, Frame* frame)
    119 {
    120     if (url.isEmpty())
    121         return;
    122 
    123     GtkClipboard* clipboard = m_helper->getClipboard(frame);
    124     GtkClipboard* primary = m_helper->getPrimary(frame);
    125     CString utf8 = url.string().utf8();
    126     gtk_clipboard_set_text(clipboard, utf8.data(), utf8.length());
    127     gtk_clipboard_set_text(primary, utf8.data(), utf8.length());
    128 }
    129 
    130 void Pasteboard::writeImage(Node* node, const KURL&, const String&)
    131 {
    132     GtkClipboard* clipboard = gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD);
    133 
    134     ASSERT(node && node->renderer() && node->renderer()->isImage());
    135     RenderImage* renderer = toRenderImage(node->renderer());
    136     CachedImage* cachedImage = renderer->cachedImage();
    137     ASSERT(cachedImage);
    138     Image* image = cachedImage->image();
    139     ASSERT(image);
    140 
    141     GdkPixbuf* pixbuf = image->getGdkPixbuf();
    142     gtk_clipboard_set_image(clipboard, pixbuf);
    143     g_object_unref(pixbuf);
    144 }
    145 
    146 void Pasteboard::clear()
    147 {
    148     GtkClipboard* clipboard = gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD);
    149 
    150     gtk_clipboard_clear(clipboard);
    151 }
    152 
    153 bool Pasteboard::canSmartReplace()
    154 {
    155     notImplemented();
    156     return false;
    157 }
    158 
    159 PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context,
    160                                                           bool allowPlainText, bool& chosePlainText)
    161 {
    162     GdkAtom textHtml = gdk_atom_intern_static_string("text/html");
    163     GtkClipboard* clipboard = m_helper->getCurrentTarget(frame);
    164     chosePlainText = false;
    165 
    166     if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, textHtml)) {
    167         ASSERT(data->data);
    168         RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/plain", "UTF-8", true);
    169         String html = decoder->decode(reinterpret_cast<char*>(data->data), data->length);
    170         html += decoder->flush();
    171         gtk_selection_data_free(data);
    172 
    173         if (!html.isEmpty()) {
    174             RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, "", FragmentScriptingNotAllowed);
    175             if (fragment)
    176                 return fragment.release();
    177         }
    178     }
    179 
    180     if (!allowPlainText)
    181         return 0;
    182 
    183     if (gchar* utf8 = gtk_clipboard_wait_for_text(clipboard)) {
    184         String text = String::fromUTF8(utf8);
    185         g_free(utf8);
    186 
    187         chosePlainText = true;
    188         RefPtr<DocumentFragment> fragment = createFragmentFromText(context.get(), text);
    189         if (fragment)
    190             return fragment.release();
    191     }
    192 
    193     return 0;
    194 }
    195 
    196 String Pasteboard::plainText(Frame* frame)
    197 {
    198     GtkClipboard* clipboard = m_helper->getCurrentTarget(frame);
    199 
    200     gchar* utf8 = gtk_clipboard_wait_for_text(clipboard);
    201 
    202     if (!utf8)
    203         return String();
    204 
    205     String text = String::fromUTF8(utf8);
    206     g_free(utf8);
    207 
    208     return text;
    209 }
    210 
    211 }
    212