• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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