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