1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Pierre Phaneuf <pp@ludusdesign.com>
24 * Takashi Toyoshima <toyoshim@be-in.org>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "nsClipboard.h"
42 #include "nsITransferable.h"
43 #include "nsWidgetsCID.h"
44 #include "nsXPIDLString.h"
45 #include "nsPrimitiveHelpers.h"
47 #include "nsISupportsPrimitives.h"
51 #include <Clipboard.h>
55 BView
*nsClipboard::sView
= 0;
57 #if defined(DEBUG_akkana) || defined(DEBUG_mcafee) || defined(DEBUG_toyoshim)
58 # define DEBUG_CLIPBOARD
62 //-------------------------------------------------------------------------
64 // nsClipboard constructor
66 //-------------------------------------------------------------------------
67 nsClipboard::nsClipboard() : nsBaseClipboard()
69 #ifdef DEBUG_CLIPBOARD
70 printf(" nsClipboard::nsClipboard()\n");
71 #endif /* DEBUG_CLIPBOARD */
73 mIgnoreEmptyNotification
= PR_FALSE
;
74 mClipboardOwner
= nsnull
;
75 mTransferable
= nsnull
;
78 //-------------------------------------------------------------------------
80 // nsClipboard destructor
82 //-------------------------------------------------------------------------
83 nsClipboard::~nsClipboard()
85 #ifdef DEBUG_CLIPBOARD
86 printf(" nsClipboard::~nsClipboard()\n");
87 #endif /* DEBUG_CLIPBOARD */
90 void nsClipboard::SetTopLevelView(BView
*v
)
92 // Don't set up any more event handlers if we're being called twice
93 // for the same toplevel widget
97 if (sView
!= 0 && sView
->Window() != 0)
100 if(v
== 0 || v
->Window() == 0)
102 #ifdef DEBUG_CLIPBOARD
103 printf(" nsClipboard::SetTopLevelView: widget passed in is null or has no window!\n");
104 #endif /* DEBUG_CLIPBOARD */
108 #ifdef DEBUG_CLIPBOARD
109 printf(" nsClipboard::SetTopLevelView\n");
110 #endif /* DEBUG_CLIPBOARD */
116 NS_IMETHODIMP
nsClipboard::SetNativeClipboardData(PRInt32 aWhichClipboard
)
118 mIgnoreEmptyNotification
= PR_TRUE
;
120 #ifdef DEBUG_CLIPBOARD
121 printf(" nsClipboard::SetNativeClipboardData()\n");
122 #endif /* DEBUG_CLIPBOARD */
124 // make sure we have a good transferable
125 if (nsnull
== mTransferable
) {
126 #ifdef DEBUG_CLIPBOARD
127 printf(" SetNativeClipboardData: no transferable!\n");
128 #endif /* DEBUG_CLIPBOARD */
129 return NS_ERROR_FAILURE
;
132 // lock the native clipboard
133 if (!be_clipboard
->Lock())
134 return NS_ERROR_FAILURE
;
136 // clear the native clipboard
138 if (B_OK
== be_clipboard
->Clear()) {
139 // set data to the native clipboard
140 if (BMessage
*msg
= be_clipboard
->Data()) {
141 // Get the transferable list of data flavors
142 nsCOMPtr
<nsISupportsArray
> dfList
;
143 mTransferable
->FlavorsTransferableCanExport(getter_AddRefs(dfList
));
145 // Walk through flavors that contain data and register them
146 // into the BMessage as supported flavors
150 for (i
= 0; i
< cnt
&& rv
== NS_OK
; i
++) {
151 nsCOMPtr
<nsISupports
> genericFlavor
;
152 dfList
->GetElementAt(i
, getter_AddRefs(genericFlavor
));
153 nsCOMPtr
<nsISupportsCString
> currentFlavor (do_QueryInterface(genericFlavor
));
155 nsXPIDLCString flavorStr
;
156 currentFlavor
->ToString(getter_Copies(flavorStr
));
158 #ifdef DEBUG_CLIPBOARD
159 printf("nsClipboard: %d/%d = %s\n", i
, cnt
, (const char *)flavorStr
);
160 #endif /* DEBUG_CLIPBOARD */
161 if (0 == strncmp(flavorStr
, "text/", 5)) {
162 // [NS] text/ * => [Be] text/ *
164 PRUint32 dataSize
= 0;
165 nsCOMPtr
<nsISupports
> genericDataWrapper
;
166 rv
= mTransferable
->GetTransferData(flavorStr
, getter_AddRefs(genericDataWrapper
), &dataSize
);
167 nsPrimitiveHelpers::CreateDataFromPrimitive(flavorStr
, genericDataWrapper
, &data
, dataSize
);
168 #ifdef DEBUG_CLIPBOARD
170 printf("nsClipboard: Error getting data from transferable\n");
171 #endif /* DEBUG_CLIPBOARD */
172 if (dataSize
&& data
!= nsnull
) {
173 NS_ConvertUTF16toUTF8
cv((const PRUnichar
*)data
, (PRUint32
)dataSize
/ 2);
174 const char *utf8Str
= cv
.get();
175 uint32 utf8Len
= strlen(utf8Str
);
176 #ifdef DEBUG_CLIPBOARD
177 if (0 == strcmp(flavorStr
, kUnicodeMime
))
178 printf(" => [%s]%s\n", kTextMime
, utf8Str
);
180 printf(" => [%s]%s\n", (const char *)flavorStr
, utf8Str
);
181 #endif /* DEBUG_CLIPBOARD */
183 if (0 == strcmp(flavorStr
, kUnicodeMime
)) {
184 // [NS] text/unicode => [Be] text/plain
185 rc
= msg
->AddData(kTextMime
, B_MIME_TYPE
, (void *)utf8Str
, utf8Len
);
187 // [NS] text/ * => [Be] text/ *
188 rc
= msg
->AddData((const char *)flavorStr
, B_MIME_TYPE
, (void *)utf8Str
, utf8Len
);
191 rv
= NS_ERROR_FAILURE
;
193 #ifdef DEBUG_CLIPBOARD
194 printf("nsClipboard: Error null data from transferable\n");
195 #endif /* DEBUG_CLIPBOARD */
196 // not fatal. force to continue...
200 // [NS] * / * => [Be] * / *
202 PRUint32 dataSize
= 0;
203 nsCOMPtr
<nsISupports
> genericDataWrapper
;
204 rv
= mTransferable
->GetTransferData(flavorStr
, getter_AddRefs(genericDataWrapper
), &dataSize
);
205 nsPrimitiveHelpers::CreateDataFromPrimitive(flavorStr
, genericDataWrapper
, &data
, dataSize
);
206 #ifdef DEBUG_CLIPBOARD
208 printf("nsClipboard: Error getting data from transferable\n");
209 #endif /* DEBUG_CLIPBOARD */
210 if (dataSize
&& data
!= nsnull
) {
211 #ifdef DEBUG_CLIPBOARD
212 printf("[%s](binary)\n", (const char *)flavorStr
);
213 #endif /* DEBUG_CLIPBOARD */
214 if (B_OK
!= msg
->AddData((const char *)flavorStr
, B_MIME_TYPE
, data
, dataSize
))
215 rv
= NS_ERROR_FAILURE
;
219 #ifdef DEBUG_CLIPBOARD
220 printf("nsClipboard: Error getting flavor\n");
221 #endif /* DEBUG_CLIPBOARD */
222 rv
= NS_ERROR_FAILURE
;
226 rv
= NS_ERROR_FAILURE
;
229 rv
= NS_ERROR_FAILURE
;
231 if (B_OK
!= be_clipboard
->Commit())
232 rv
= NS_ERROR_FAILURE
;
233 be_clipboard
->Unlock();
235 mIgnoreEmptyNotification
= PR_FALSE
;
242 // The blocking Paste routine
245 nsClipboard::GetNativeClipboardData(nsITransferable
* aTransferable
, PRInt32 aWhichClipboard
)
247 #ifdef DEBUG_CLIPBOARD
248 printf(" nsClipboard::GetNativeClipboardData()\n");
249 #endif /* DEBUG_CLIPBOARD */
251 // make sure we have a good transferable
252 if (nsnull
== aTransferable
) {
253 printf(" GetNativeClipboardData: Transferable is null!\n");
254 return NS_ERROR_FAILURE
;
259 nsCOMPtr
<nsISupportsArray
> flavorList
;
260 rv
= aTransferable
->FlavorsTransferableCanImport(getter_AddRefs(flavorList
));
262 return NS_ERROR_FAILURE
;
264 // get native clipboard data
265 if (!be_clipboard
->Lock())
266 return NS_ERROR_FAILURE
;
268 BMessage
*msg
= be_clipboard
->Data();
270 return NS_ERROR_FAILURE
;
271 #ifdef DEBUG_CLIPBOARD
272 msg
->PrintToStream();
273 #endif /* DEBUG_CLIPBOARD */
276 flavorList
->Count(&cnt
);
277 for (PRUint32 i
= 0; i
< cnt
; i
++) {
278 nsCOMPtr
<nsISupports
> genericFlavor
;
279 flavorList
->GetElementAt(i
, getter_AddRefs(genericFlavor
));
280 nsCOMPtr
<nsISupportsCString
> currentFlavor(do_QueryInterface(genericFlavor
));
282 nsXPIDLCString flavorStr
;
283 currentFlavor
->ToString(getter_Copies(flavorStr
));
285 #ifdef DEBUG_CLIPBOARD
286 printf("nsClipboard: %d/%d = %s\n", i
, cnt
, (const char *)flavorStr
);
287 #endif /* DEBUG_CLIPBOARD */
290 if (0 == strncmp(flavorStr
, "text/", 5)) {
291 // [Be] text/ * => [NS] text/ *
293 if (0 == strcmp(flavorStr
, kUnicodeMime
))
294 rc
= msg
->FindData(kTextMime
, B_MIME_TYPE
, &data
, &size
);
296 rc
= msg
->FindData(flavorStr
, B_MIME_TYPE
, &data
, &size
);
297 if (rc
!= B_OK
|| !data
|| !size
) {
298 #ifdef DEBUG_CLIPBOARD
299 printf("nsClipboard: not found in BMessage\n");
300 #endif /* DEBUG_CLIPBOARD */
302 NS_ConvertUTF8toUTF16
ucs2Str((const char *)data
, (PRUint32
)size
);
303 nsCOMPtr
<nsISupports
> genericDataWrapper
;
304 nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr
, (void *)ucs2Str
.get(), ucs2Str
.Length() * 2, getter_AddRefs(genericDataWrapper
));
305 rv
= aTransferable
->SetTransferData(flavorStr
, genericDataWrapper
, ucs2Str
.Length() * 2);
308 // [Be] * / * => [NS] * / *
309 if (B_OK
!= msg
->FindData(flavorStr
, B_MIME_TYPE
, &data
, &size
)) {
310 #ifdef DEBUG_CLIPBOARD
311 printf("nsClipboard: not found in BMessage\n");
312 #endif /* DEBUG_CLIPBOARD */
314 nsCOMPtr
<nsISupports
> genericDataWrapper
;
315 nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr
, (void *)data
, (PRUint32
)size
, getter_AddRefs(genericDataWrapper
));
316 rv
= aTransferable
->SetTransferData(flavorStr
, genericDataWrapper
, size
);
319 #ifdef DEBUG_CLIPBOARD
321 printf("nsClipboard: Error SetTransferData\n");
322 #endif /* DEBUG_CLIPBOARD */
324 rv
= NS_ERROR_FAILURE
;
325 #ifdef DEBUG_CLIPBOARD
326 printf("nsClipboard: Error gerring flavor");
327 #endif /* DEBUG_CLIPBOARD */
333 be_clipboard
->Unlock();