1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is the Mozilla OS/2 libraries.
18 * The Initial Developer of the Original Code is
19 * John Fairhurst, <john_fairhurst@iname.com>.
20 * Portions created by the Initial Developer are Copyright (C) 1999
21 * the Initial Developer. All Rights Reserved.
24 * 2000/08/04 Henry Sobotka <sobotka@axess.com> Update from M7
25 * 2000/10/02 IBM Corp. Sync-up to M18 level
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
42 #include "nsISupportsPrimitives.h"
44 #include "nsPrimitiveHelpers.h"
45 #include "nsXPIDLString.h"
47 #include "nsIObserverService.h"
48 #include "nsIServiceManager.h"
50 #include "nsClipboard.h"
51 #include "mozilla/Services.h"
53 inline ULONG
RegisterClipboardFormat(PCSZ pcszFormat
)
55 ATOM atom
= WinFindAtom(WinQuerySystemAtomTable(), pcszFormat
);
57 atom
= WinAddAtom(WinQuerySystemAtomTable(), pcszFormat
);
62 nsClipboard::nsClipboard() : nsBaseClipboard()
64 RegisterClipboardFormat(kTextMime
);
65 RegisterClipboardFormat(kUnicodeMime
);
66 RegisterClipboardFormat(kHTMLMime
);
67 RegisterClipboardFormat(kAOLMailMime
);
68 RegisterClipboardFormat(kPNGImageMime
);
69 RegisterClipboardFormat(kJPEGImageMime
);
70 RegisterClipboardFormat(kGIFImageMime
);
71 RegisterClipboardFormat(kFileMime
);
72 RegisterClipboardFormat(kURLMime
);
73 RegisterClipboardFormat(kNativeImageMime
);
74 RegisterClipboardFormat(kNativeHTMLMime
);
76 // Register for a shutdown notification so that we can flush data
77 // to the OS clipboard.
78 nsCOMPtr
<nsIObserverService
> observerService
=
79 mozilla::services::GetObserverService();
81 observerService
->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
, PR_FALSE
);
84 nsClipboard::~nsClipboard()
87 NS_IMPL_ISUPPORTS_INHERITED1(nsClipboard
, nsBaseClipboard
, nsIObserver
)
89 nsresult
nsClipboard::SetNativeClipboardData(PRInt32 aWhichClipboard
)
91 if (aWhichClipboard
!= kGlobalClipboard
)
92 return NS_ERROR_FAILURE
;
94 return DoClipboardAction(Write
);
97 nsresult
nsClipboard::GetNativeClipboardData(nsITransferable
*aTransferable
, PRInt32 aWhichClipboard
)
99 // make sure we have a good transferable
100 if (!aTransferable
|| aWhichClipboard
!= kGlobalClipboard
)
101 return NS_ERROR_FAILURE
;
103 nsITransferable
*tmp
= mTransferable
;
104 mTransferable
= aTransferable
;
105 nsresult rc
= DoClipboardAction(Read
);
110 // Get some data from the clipboard
111 PRBool
nsClipboard::GetClipboardData(const char *aFlavor
)
113 ULONG ulFormatID
= GetFormatID( aFlavor
);
115 PRBool found
= GetClipboardDataByID( ulFormatID
, aFlavor
);
119 if (!strcmp( aFlavor
, kUnicodeMime
))
121 found
= GetClipboardDataByID( CF_TEXT
, aFlavor
);
123 else if (strstr( aFlavor
, "image/" ))
125 found
= GetClipboardDataByID( CF_BITMAP
, aFlavor
);
132 PRBool
nsClipboard::GetClipboardDataByID(ULONG ulFormatID
, const char *aFlavor
)
136 PRBool TempBufAllocated
= PR_FALSE
;
138 PVOID pClipboardData
= reinterpret_cast<PVOID
>(WinQueryClipbrdData( 0, ulFormatID
));
143 if (strstr( aFlavor
, "text/" )) // All text/.. flavors are null-terminated
145 pDataMem
= pClipboardData
;
147 if (ulFormatID
== CF_TEXT
) // CF_TEXT is one byte character set
149 PRUint32 NumOfChars
= strlen( static_cast<char*>(pDataMem
) );
150 NumOfBytes
= NumOfChars
;
152 if (!strcmp( aFlavor
, kUnicodeMime
)) // Asked for unicode, but only plain text available. Convert it!
154 nsAutoChar16Buffer buffer
;
156 MultiByteToWideChar(0, static_cast<char*>(pDataMem
), NumOfChars
,
158 pDataMem
= ToNewUnicode(nsDependentString(buffer
.Elements()));
159 TempBufAllocated
= PR_TRUE
;
160 NumOfBytes
= bufLength
* sizeof(UniChar
);
164 else // All other text/.. flavors are in unicode
166 PRUint32 NumOfChars
= UniStrlen( static_cast<UniChar
*>(pDataMem
) );
167 NumOfBytes
= NumOfChars
* sizeof(UniChar
);
168 PVOID pTempBuf
= nsMemory::Alloc(NumOfBytes
);
169 memcpy(pTempBuf
, pDataMem
, NumOfBytes
);
171 TempBufAllocated
= PR_TRUE
;
174 // DOM wants LF only, so convert from CRLF
175 nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks( aFlavor
, &pDataMem
, // pDataMem could be reallocated !!
176 reinterpret_cast<PRInt32
*>(&NumOfBytes
) ); // yuck
179 else // Assume rest of flavors are binary data
181 if (ulFormatID
== CF_BITMAP
)
183 if (!strcmp( aFlavor
, kJPEGImageMime
))
185 // OS2TODO Convert bitmap to jpg
187 printf( "nsClipboard:: No JPG found on clipboard; need to convert BMP\n");
190 else if (!strcmp( aFlavor
, kGIFImageMime
))
192 // OS2TODO Convert bitmap to gif
194 printf( "nsClipboard:: No GIF found on clipboard; need to convert BMP\n");
197 else if (!strcmp( aFlavor
, kPNGImageMime
))
199 // OS2TODO Convert bitmap to png
201 printf( "nsClipboard:: No PNG found on clipboard; need to convert BMP\n");
207 pDataMem
= static_cast<PBYTE
>(pClipboardData
) + sizeof(PRUint32
);
208 NumOfBytes
= *(static_cast<PRUint32
*>(pClipboardData
));
212 nsCOMPtr
<nsISupports
> genericDataWrapper
;
213 nsPrimitiveHelpers::CreatePrimitiveForData( aFlavor
, pDataMem
, NumOfBytes
, getter_AddRefs(genericDataWrapper
) );
217 mTransferable
->SetTransferData( aFlavor
, genericDataWrapper
, NumOfBytes
);
219 if (errCode
!= NS_OK
)
220 printf( "nsClipboard:: Error setting data into transferable\n" );
223 if (TempBufAllocated
)
224 nsMemory::Free(pDataMem
);
230 // Set some data onto the clipboard
231 void nsClipboard::SetClipboardData(const char *aFlavor
)
233 void *pMozData
= nsnull
;
234 PRUint32 NumOfBytes
= 0;
236 // Get the data from the transferable
237 nsCOMPtr
<nsISupports
> genericDataWrapper
;
241 mTransferable
->GetTransferData( aFlavor
, getter_AddRefs(genericDataWrapper
), &NumOfBytes
);
243 if (NS_FAILED(errCode
)) printf( "nsClipboard:: Error getting data from transferable\n" );
245 if (NumOfBytes
== 0) return;
246 nsPrimitiveHelpers::CreateDataFromPrimitive( aFlavor
, genericDataWrapper
, &pMozData
, NumOfBytes
);
248 /* If creating the data failed, just return */
253 ULONG ulFormatID
= GetFormatID( aFlavor
);
255 if (strstr( aFlavor
, "text/" )) // All text/.. flavors are null-terminated
257 if (ulFormatID
== CF_TEXT
) // CF_TEXT is one byte character set
259 char* pByteMem
= nsnull
;
261 if (DosAllocSharedMem( reinterpret_cast<PPVOID
>(&pByteMem
), nsnull
, NumOfBytes
+ sizeof(char),
262 PAG_WRITE
| PAG_COMMIT
| OBJ_GIVEABLE
) == NO_ERROR
)
264 memcpy( pByteMem
, pMozData
, NumOfBytes
); // Copy text string
265 pByteMem
[NumOfBytes
] = '\0'; // Append terminator
267 // With Warp4 copying more than 64K to the clipboard works well, but
268 // legacy apps cannot always handle it. So output an alarm to alert the
269 // user that there might be a problem.
270 if (strlen(pByteMem
) > 0xFFFF) {
271 WinAlarm(HWND_DESKTOP
, WA_ERROR
);
273 WinSetClipbrdData(0, reinterpret_cast<ULONG
>(pByteMem
), ulFormatID
, CFI_POINTER
);
276 else // All other text/.. flavors are in unicode
278 UniChar
* pUnicodeMem
= nsnull
;
279 PRUint32 NumOfChars
= NumOfBytes
/ sizeof(UniChar
);
281 if (DosAllocSharedMem( reinterpret_cast<PPVOID
>(&pUnicodeMem
), nsnull
, NumOfBytes
+ sizeof(UniChar
),
282 PAG_WRITE
| PAG_COMMIT
| OBJ_GIVEABLE
) == NO_ERROR
)
284 memcpy( pUnicodeMem
, pMozData
, NumOfBytes
); // Copy text string
285 pUnicodeMem
[NumOfChars
] = L
'\0'; // Append terminator
287 WinSetClipbrdData( 0, reinterpret_cast<ULONG
>(pUnicodeMem
), ulFormatID
, CFI_POINTER
);
290 // If the flavor is unicode, we also put it on the clipboard as CF_TEXT
291 // after conversion to locale charset.
293 if (!strcmp( aFlavor
, kUnicodeMime
))
295 char* pByteMem
= nsnull
;
297 if (DosAllocSharedMem(reinterpret_cast<PPVOID
>(&pByteMem
), nsnull
,
299 PAG_WRITE
| PAG_COMMIT
| OBJ_GIVEABLE
) == NO_ERROR
)
301 PRUnichar
* uchtemp
= (PRUnichar
*)pMozData
;
302 for (PRUint32 i
=0;i
<NumOfChars
;i
++) {
303 switch (uchtemp
[i
]) {
318 nsAutoCharBuffer buffer
;
320 WideCharToMultiByte(0, static_cast<PRUnichar
*>(pMozData
),
321 NumOfBytes
, buffer
, bufLength
);
322 memcpy(pByteMem
, buffer
.Elements(), NumOfBytes
);
323 // With Warp4 copying more than 64K to the clipboard works well, but
324 // legacy apps cannot always handle it. So output an alarm to alert the
325 // user that there might be a problem.
326 if (strlen(pByteMem
) > 0xFFFF) {
327 WinAlarm(HWND_DESKTOP
, WA_ERROR
);
329 WinSetClipbrdData(0, reinterpret_cast<ULONG
>(pByteMem
), CF_TEXT
, CFI_POINTER
);
334 else // Assume rest of flavors are binary data
336 PBYTE pBinaryMem
= nsnull
;
338 if (DosAllocSharedMem( reinterpret_cast<PPVOID
>(&pBinaryMem
), nsnull
, NumOfBytes
+ sizeof(PRUint32
),
339 PAG_WRITE
| PAG_COMMIT
| OBJ_GIVEABLE
) == NO_ERROR
)
341 *(reinterpret_cast<PRUint32
*>(pBinaryMem
)) = NumOfBytes
; // First DWORD contains data length
342 memcpy( pBinaryMem
+ sizeof(PRUint32
), pMozData
, NumOfBytes
); // Copy binary data
344 WinSetClipbrdData( 0, reinterpret_cast<ULONG
>(pBinaryMem
), ulFormatID
, CFI_POINTER
);
347 // If the flavor is image, we also put it on clipboard as CF_BITMAP
348 // after conversion to OS2 bitmap
350 if (strstr (aFlavor
, "image/"))
352 // XXX OS2TODO Convert jpg, gif, png to bitmap
354 printf( "nsClipboard:: Putting image on clipboard; should also convert to BMP\n" );
358 nsMemory::Free(pMozData
);
361 // Go through the flavors in the transferable and either get or set them
362 nsresult
nsClipboard::DoClipboardAction(ClipboardAction aAction
)
364 nsresult rc
= NS_ERROR_FAILURE
;
366 if (WinOpenClipbrd(0/*hab*/)) {
368 if (aAction
== Write
)
369 WinEmptyClipbrd(0/*hab*/);
371 // Get the list of formats the transferable can handle
372 nsCOMPtr
<nsISupportsArray
> pFormats
;
374 rc
= mTransferable
->FlavorsTransferableCanImport(getter_AddRefs(pFormats
));
376 rc
= mTransferable
->FlavorsTransferableCanExport(getter_AddRefs(pFormats
));
379 return NS_ERROR_FAILURE
;
381 PRUint32 cFormats
= 0;
382 pFormats
->Count(&cFormats
);
384 for (PRUint32 i
= 0; i
< cFormats
; i
++) {
386 nsCOMPtr
<nsISupports
> genericFlavor
;
387 pFormats
->GetElementAt(i
, getter_AddRefs(genericFlavor
));
388 nsCOMPtr
<nsISupportsCString
> currentFlavor(do_QueryInterface(genericFlavor
));
391 nsXPIDLCString flavorStr
;
392 currentFlavor
->ToString(getter_Copies(flavorStr
));
394 if (aAction
== Read
) {
395 if (GetClipboardData(flavorStr
))
399 SetClipboardData(flavorStr
);
402 WinCloseClipbrd(0/*hab*/);
408 // get the format ID for a given mimetype
409 ULONG
nsClipboard::GetFormatID(const char *aMimeStr
)
411 if (strcmp(aMimeStr
, kTextMime
) == 0)
414 return RegisterClipboardFormat(aMimeStr
);
419 nsClipboard::Observe(nsISupports
*aSubject
, const char *aTopic
,
420 const PRUnichar
*aData
)
422 // This will be called on shutdown.
424 // make sure we have a good transferable
426 return NS_ERROR_FAILURE
;
428 if (WinOpenClipbrd(0/*hab*/)) {
429 WinEmptyClipbrd(0/*hab*/);
431 // get flavor list that includes all flavors that can be written (including ones
432 // obtained through conversion)
433 nsCOMPtr
<nsISupportsArray
> flavorList
;
434 nsresult errCode
= mTransferable
->FlavorsTransferableCanExport(getter_AddRefs(flavorList
));
435 if (NS_FAILED(errCode
))
436 return NS_ERROR_FAILURE
;
438 // Walk through flavors and put data on to clipboard
441 flavorList
->Count(&cnt
);
442 for (i
= 0; i
< cnt
; i
++) {
443 nsCOMPtr
<nsISupports
> genericFlavor
;
444 flavorList
->GetElementAt(i
, getter_AddRefs(genericFlavor
));
445 nsCOMPtr
<nsISupportsCString
> currentFlavor(do_QueryInterface(genericFlavor
));
447 nsXPIDLCString flavorStr
;
448 currentFlavor
->ToString(getter_Copies(flavorStr
));
449 SetClipboardData(flavorStr
);
452 WinCloseClipbrd(0/*hab*/);
457 NS_IMETHODIMP
nsClipboard::HasDataMatchingFlavors(const char** aFlavorList
,
459 PRInt32 aWhichClipboard
,
463 if (aWhichClipboard
!= kGlobalClipboard
|| !aFlavorList
)
466 for (PRUint32 i
= 0; i
< aLength
; ++i
) {
468 ULONG format
= GetFormatID(aFlavorList
[i
]);
470 if (WinQueryClipbrdFmtInfo(0/*hab*/, format
, &fmtInfo
)) {
475 // if the client asked for unicode and it wasn't present, check if we have CF_TEXT.
476 if (!strcmp(aFlavorList
[i
], kUnicodeMime
)) {
477 if (WinQueryClipbrdFmtInfo(0/*hab*/, CF_TEXT
, &fmtInfo
)) {
483 // OS2TODO - Support for Images
484 // if the client asked for image/.. and it wasn't present, check if we have CF_BITMAP.
485 if (strstr(aFlavorList
[i
], "image/")) {
486 if (WinQueryClipbrdFmtInfo (0, CF_BITMAP
, &fmtInfo
)) {
488 printf("nsClipboard:: Image present on clipboard; need to add BMP conversion!\n");
490 // *_retval = PR_TRUE;