1 /*
2 * Copyright (C) 2007 Holger Hans Peter Freyther
3 * Copyright (C) 2007 Alp Toker <alp@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:
PasteboardSelectionData(gchar * text,gchar * markup)40 PasteboardSelectionData(gchar* text, gchar* markup)
41 : m_text(text)
42 , m_markup(markup) { }
43
~PasteboardSelectionData()44 ~PasteboardSelectionData() {
45 g_free(m_text);
46 g_free(m_markup);
47 }
48
text() const49 const gchar* text() const { return m_text; }
markup() const50 const gchar* markup() const { return m_markup; }
51
52 private:
53 gchar* m_text;
54 gchar* m_markup;
55 };
56
clipboard_get_contents_cb(GtkClipboard * clipboard,GtkSelectionData * selection_data,guint info,gpointer data)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
clipboard_clear_contents_cb(GtkClipboard * clipboard,gpointer data)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
generalPasteboard()76 Pasteboard* Pasteboard::generalPasteboard()
77 {
78 static Pasteboard* pasteboard = new Pasteboard();
79 return pasteboard;
80 }
81
Pasteboard()82 Pasteboard::Pasteboard()
83 {
84 notImplemented();
85 }
86
~Pasteboard()87 Pasteboard::~Pasteboard()
88 {
89 delete m_helper;
90 }
91
setHelper(PasteboardHelper * helper)92 void Pasteboard::setHelper(PasteboardHelper* helper)
93 {
94 m_helper = helper;
95 }
96
writeSelection(Range * selectedRange,bool canSmartCopyOrDelete,Frame * frame)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
writePlainText(const String & text)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
writeURL(const KURL & url,const String &,Frame * frame)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
writeImage(Node * node,const KURL &,const String &)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
clear()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
canSmartReplace()153 bool Pasteboard::canSmartReplace()
154 {
155 notImplemented();
156 return false;
157 }
158
documentFragment(Frame * frame,PassRefPtr<Range> context,bool allowPlainText,bool & chosePlainText)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
plainText(Frame * frame)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