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