• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 Zack Rusin <zack@kde.org>
3  * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
4  * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "config.h"
29 #include "Pasteboard.h"
30 
31 #include "DocumentFragment.h"
32 #include "Editor.h"
33 #include "Frame.h"
34 #include "KURL.h"
35 #include "NotImplemented.h"
36 #include "TextResourceDecoder.h"
37 #include "markup.h"
38 #include <support/Locker.h>
39 #include <Clipboard.h>
40 #include <Message.h>
41 #include <String.h>
42 #include <wtf/text/CString.h>
43 
44 
45 namespace WebCore {
46 
Pasteboard()47 Pasteboard::Pasteboard()
48 {
49 }
50 
~Pasteboard()51 Pasteboard::~Pasteboard()
52 {
53 }
54 
generalPasteboard()55 Pasteboard* Pasteboard::generalPasteboard()
56 {
57     static Pasteboard pasteboard;
58     return &pasteboard;
59 }
60 
61 // BClipboard unfortunately does not derive from BLocker, so we cannot use BAutolock.
62 class AutoClipboardLocker {
63 public:
AutoClipboardLocker(BClipboard * clipboard)64     AutoClipboardLocker(BClipboard* clipboard)
65         : m_clipboard(clipboard)
66         , m_isLocked(clipboard && clipboard->Lock())
67     {
68     }
69 
~AutoClipboardLocker()70     ~AutoClipboardLocker()
71     {
72         if (m_isLocked)
73             m_clipboard->Unlock();
74     }
75 
isLocked() const76     bool isLocked() const
77     {
78         return m_isLocked;
79     }
80 
81 private:
82     BClipboard* m_clipboard;
83     bool m_isLocked;
84 };
85 
writeSelection(Range * selectedRange,bool canSmartCopyOrDelete,Frame * frame)86 void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
87 {
88     AutoClipboardLocker locker(be_clipboard);
89     if (!locker.isLocked())
90         return;
91 
92     be_clipboard->Clear();
93     BMessage* data = be_clipboard->Data();
94     if (!data)
95         return;
96 
97     BString string(frame->selectedText());
98 
99     // Replace unwanted representation of blank lines
100     const char* utf8BlankLine = "\302\240\n";
101     string.ReplaceAll(utf8BlankLine, "\n");
102 
103     data->AddData("text/plain", B_MIME_TYPE, string.String(), string.Length());
104 
105     BString markupString(createMarkup(selectedRange, 0, AnnotateForInterchange, false, AbsoluteURLs));
106     data->AddData("text/html", B_MIME_TYPE, markupString.String(), markupString.Length());
107 
108     be_clipboard->Commit();
109 }
110 
writePlainText(const String & text)111 void Pasteboard::writePlainText(const String& text)
112 {
113     AutoClipboardLocker locker(be_clipboard);
114     if (!locker.isLocked())
115         return;
116 
117     be_clipboard->Clear();
118     BMessage* data = be_clipboard->Data();
119     if (!data)
120         return;
121 
122     BString string(text);
123     data->AddData("text/plain", B_MIME_TYPE, string.String(), string.Length());
124     be_clipboard->Commit();
125 }
126 
canSmartReplace()127 bool Pasteboard::canSmartReplace()
128 {
129     notImplemented();
130     return false;
131 }
132 
plainText(Frame * frame)133 String Pasteboard::plainText(Frame* frame)
134 {
135     AutoClipboardLocker locker(be_clipboard);
136     if (!locker.isLocked())
137         return String();
138 
139     BMessage* data = be_clipboard->Data();
140     if (!data)
141         return String();
142 
143     const char* buffer = 0;
144     ssize_t bufferLength;
145     BString string;
146     if (data->FindData("text/plain", B_MIME_TYPE, reinterpret_cast<const void**>(&buffer), &bufferLength) == B_OK)
147         string.Append(buffer, bufferLength);
148 
149     return string;
150 }
151 
documentFragment(Frame * frame,PassRefPtr<Range> context,bool allowPlainText,bool & chosePlainText)152 PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context,
153                                                           bool allowPlainText, bool& chosePlainText)
154 {
155     chosePlainText = false;
156 
157     AutoClipboardLocker locker(be_clipboard);
158     if (!locker.isLocked())
159         return 0;
160 
161     BMessage* data = be_clipboard->Data();
162     if (!data)
163         return 0;
164 
165     const char* buffer = 0;
166     ssize_t bufferLength;
167     if (data->FindData("text/html", B_MIME_TYPE, reinterpret_cast<const void**>(&buffer), &bufferLength) == B_OK) {
168         RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/plain", "UTF-8", true);
169         String html = decoder->decode(buffer, bufferLength);
170         html += decoder->flush();
171 
172         if (!html.isEmpty()) {
173             RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, "", FragmentScriptingNotAllowed);
174             if (fragment)
175                 return fragment.release();
176         }
177     }
178 
179     if (!allowPlainText)
180         return 0;
181 
182     if (data->FindData("text/plain", B_MIME_TYPE, reinterpret_cast<const void**>(&buffer), &bufferLength) == B_OK) {
183         BString plainText(buffer, bufferLength);
184 
185         chosePlainText = true;
186         RefPtr<DocumentFragment> fragment = createFragmentFromText(context.get(), plainText);
187         if (fragment)
188             return fragment.release();
189     }
190 
191     return 0;
192 }
193 
writeURL(const KURL & url,const String &,Frame *)194 void Pasteboard::writeURL(const KURL& url, const String&, Frame*)
195 {
196     AutoClipboardLocker locker(be_clipboard);
197     if (!locker.isLocked())
198         return;
199 
200     be_clipboard->Clear();
201 
202     BMessage* data = be_clipboard->Data();
203     if (!data)
204         return;
205 
206     BString string(url.string());
207     data->AddData("text/plain", B_MIME_TYPE, string.String(), string.Length());
208     be_clipboard->Commit();
209 }
210 
writeImage(Node *,const KURL &,const String &)211 void Pasteboard::writeImage(Node*, const KURL&, const String&)
212 {
213     notImplemented();
214 }
215 
clear()216 void Pasteboard::clear()
217 {
218     AutoClipboardLocker locker(be_clipboard);
219     if (!locker.isLocked())
220         return;
221 
222     be_clipboard->Clear();
223     be_clipboard->Commit();
224 }
225 
226 } // namespace WebCore
227 
228