/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-* * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsXPCOM.h" #include "nsISupportsPrimitives.h" #include "nsCOMPtr.h" #include "nsPrimitiveHelpers.h" #include "nsXPIDLString.h" #include "nsOS2Uni.h" #include "nsClipboard.h" #define INCL_DOSERRORS #define INCL_WIN #include inline uint32_t RegisterClipboardFormat(PCSZ pcszFormat) { ATOM atom = WinFindAtom(WinQuerySystemAtomTable(), pcszFormat); if (!atom) { atom = WinAddAtom(WinQuerySystemAtomTable(), pcszFormat); } return atom; } nsClipboard::nsClipboard() : nsBaseClipboard() { RegisterClipboardFormat(kTextMime); RegisterClipboardFormat(kUnicodeMime); RegisterClipboardFormat(kHTMLMime); RegisterClipboardFormat(kAOLMailMime); RegisterClipboardFormat(kPNGImageMime); RegisterClipboardFormat(kJPEGImageMime); RegisterClipboardFormat(kJPGImageMime); RegisterClipboardFormat(kGIFImageMime); RegisterClipboardFormat(kFileMime); RegisterClipboardFormat(kURLMime); RegisterClipboardFormat(kNativeImageMime); RegisterClipboardFormat(kNativeHTMLMime); } nsClipboard::~nsClipboard() {} nsresult nsClipboard::SetNativeClipboardData(int32_t aWhichClipboard) { if (aWhichClipboard != kGlobalClipboard) return NS_ERROR_FAILURE; return DoClipboardAction(Write); } nsresult nsClipboard::GetNativeClipboardData(nsITransferable *aTransferable, int32_t aWhichClipboard) { // make sure we have a good transferable if (!aTransferable || aWhichClipboard != kGlobalClipboard) return NS_ERROR_FAILURE; nsITransferable *tmp = mTransferable; mTransferable = aTransferable; nsresult rc = DoClipboardAction(Read); mTransferable = tmp; return rc; } // Get some data from the clipboard bool nsClipboard::GetClipboardData(const char *aFlavor) { uint32_t ulFormatID = GetFormatID(aFlavor); bool found = GetClipboardDataByID( ulFormatID, aFlavor ); if (!found) { if (!strcmp( aFlavor, kUnicodeMime )) { found = GetClipboardDataByID( CF_TEXT, aFlavor ); } else if (strstr( aFlavor, "image/" )) { found = GetClipboardDataByID( CF_BITMAP, aFlavor ); } } return found; } bool nsClipboard::GetClipboardDataByID(uint32_t aFormatID, const char *aFlavor) { PVOID pDataMem; uint32_t NumOfBytes; bool TempBufAllocated = false; PVOID pClipboardData = reinterpret_cast(WinQueryClipbrdData(0, aFormatID)); if (!pClipboardData) return false; if (strstr( aFlavor, "text/" )) // All text/.. flavors are null-terminated { pDataMem = pClipboardData; if (aFormatID == CF_TEXT) // CF_TEXT is one byte character set { uint32_t NumOfChars = strlen( static_cast(pDataMem) ); NumOfBytes = NumOfChars; if (!strcmp( aFlavor, kUnicodeMime )) // Asked for unicode, but only plain text available. Convert it! { nsAutoChar16Buffer buffer; int32_t bufLength; MultiByteToWideChar(0, static_cast(pDataMem), NumOfChars, buffer, bufLength); pDataMem = ToNewUnicode(nsDependentString(buffer.Elements())); TempBufAllocated = true; NumOfBytes = bufLength * sizeof(UniChar); } } else // All other text/.. flavors are in unicode { uint32_t NumOfChars = UniStrlen( static_cast(pDataMem) ); NumOfBytes = NumOfChars * sizeof(UniChar); PVOID pTempBuf = nsMemory::Alloc(NumOfBytes); memcpy(pTempBuf, pDataMem, NumOfBytes); pDataMem = pTempBuf; TempBufAllocated = true; } // DOM wants LF only, so convert from CRLF nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks( aFlavor, &pDataMem, // pDataMem could be reallocated !! reinterpret_cast(&NumOfBytes) ); // yuck } else // Assume rest of flavors are binary data { if (aFormatID == CF_BITMAP) { if (!strcmp( aFlavor, kJPEGImageMime ) || !strcmp( aFlavor, kJPGImageMime )) { // OS2TODO Convert bitmap to jpg #ifdef DEBUG printf( "nsClipboard:: No JPG found on clipboard; need to convert BMP\n"); #endif } else if (!strcmp( aFlavor, kGIFImageMime )) { // OS2TODO Convert bitmap to gif #ifdef DEBUG printf( "nsClipboard:: No GIF found on clipboard; need to convert BMP\n"); #endif } else if (!strcmp( aFlavor, kPNGImageMime )) { // OS2TODO Convert bitmap to png #ifdef DEBUG printf( "nsClipboard:: No PNG found on clipboard; need to convert BMP\n"); #endif } } else { pDataMem = static_cast(pClipboardData) + sizeof(uint32_t); NumOfBytes = *(static_cast(pClipboardData)); } } nsCOMPtr genericDataWrapper; nsPrimitiveHelpers::CreatePrimitiveForData( aFlavor, pDataMem, NumOfBytes, getter_AddRefs(genericDataWrapper) ); #ifdef DEBUG nsresult errCode = #endif mTransferable->SetTransferData( aFlavor, genericDataWrapper, NumOfBytes ); #ifdef DEBUG if (errCode != NS_OK) printf( "nsClipboard:: Error setting data into transferable\n" ); #endif if (TempBufAllocated) nsMemory::Free(pDataMem); return true; } // Set some data onto the clipboard void nsClipboard::SetClipboardData(const char *aFlavor) { void *pMozData = nullptr; uint32_t NumOfBytes = 0; // Get the data from the transferable nsCOMPtr genericDataWrapper; #ifdef DEBUG nsresult errCode = #endif mTransferable->GetTransferData( aFlavor, getter_AddRefs(genericDataWrapper), &NumOfBytes ); #ifdef DEBUG if (NS_FAILED(errCode)) printf( "nsClipboard:: Error getting data from transferable\n" ); #endif if (NumOfBytes == 0) return; nsPrimitiveHelpers::CreateDataFromPrimitive( aFlavor, genericDataWrapper, &pMozData, NumOfBytes ); /* If creating the data failed, just return */ if (!pMozData) { return; } uint32_t ulFormatID = GetFormatID(aFlavor); if (strstr( aFlavor, "text/" )) // All text/.. flavors are null-terminated { if (ulFormatID == CF_TEXT) // CF_TEXT is one byte character set { char* pByteMem = nullptr; if (DosAllocSharedMem( reinterpret_cast(&pByteMem), nullptr, NumOfBytes + sizeof(char), PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE ) == NO_ERROR) { memcpy( pByteMem, pMozData, NumOfBytes ); // Copy text string pByteMem[NumOfBytes] = '\0'; // Append terminator // With Warp4 copying more than 64K to the clipboard works well, but // legacy apps cannot always handle it. So output an alarm to alert the // user that there might be a problem. if (strlen(pByteMem) > 0xFFFF) { WinAlarm(HWND_DESKTOP, WA_ERROR); } WinSetClipbrdData(0, reinterpret_cast(pByteMem), ulFormatID, CFI_POINTER); } } else // All other text/.. flavors are in unicode { UniChar* pUnicodeMem = nullptr; uint32_t NumOfChars = NumOfBytes / sizeof(UniChar); if (DosAllocSharedMem( reinterpret_cast(&pUnicodeMem), nullptr, NumOfBytes + sizeof(UniChar), PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE ) == NO_ERROR) { memcpy( pUnicodeMem, pMozData, NumOfBytes ); // Copy text string pUnicodeMem[NumOfChars] = L'\0'; // Append terminator WinSetClipbrdData( 0, reinterpret_cast(pUnicodeMem), ulFormatID, CFI_POINTER ); } // If the flavor is unicode, we also put it on the clipboard as CF_TEXT // after conversion to locale charset. if (!strcmp( aFlavor, kUnicodeMime )) { char* pByteMem = nullptr; if (DosAllocSharedMem(reinterpret_cast(&pByteMem), nullptr, NumOfBytes + 1, PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE ) == NO_ERROR) { PRUnichar* uchtemp = (PRUnichar*)pMozData; for (uint32_t i=0;i(pMozData), NumOfBytes, buffer, bufLength); memcpy(pByteMem, buffer.Elements(), NumOfBytes); // With Warp4 copying more than 64K to the clipboard works well, but // legacy apps cannot always handle it. So output an alarm to alert the // user that there might be a problem. if (strlen(pByteMem) > 0xFFFF) { WinAlarm(HWND_DESKTOP, WA_ERROR); } WinSetClipbrdData(0, reinterpret_cast(pByteMem), CF_TEXT, CFI_POINTER); } } } } else // Assume rest of flavors are binary data { PBYTE pBinaryMem = nullptr; if (DosAllocSharedMem( reinterpret_cast(&pBinaryMem), nullptr, NumOfBytes + sizeof(uint32_t), PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE ) == NO_ERROR) { *(reinterpret_cast(pBinaryMem)) = NumOfBytes; // First DWORD contains data length memcpy( pBinaryMem + sizeof(uint32_t), pMozData, NumOfBytes ); // Copy binary data WinSetClipbrdData( 0, reinterpret_cast(pBinaryMem), ulFormatID, CFI_POINTER ); } // If the flavor is image, we also put it on clipboard as CF_BITMAP // after conversion to OS2 bitmap if (strstr (aFlavor, "image/")) { // XXX OS2TODO Convert jpg, gif, png to bitmap #ifdef DEBUG printf( "nsClipboard:: Putting image on clipboard; should also convert to BMP\n" ); #endif } } nsMemory::Free(pMozData); } // Go through the flavors in the transferable and either get or set them nsresult nsClipboard::DoClipboardAction(ClipboardAction aAction) { nsresult rc = NS_ERROR_FAILURE; if (WinOpenClipbrd(0/*hab*/)) { if (aAction == Write) WinEmptyClipbrd(0/*hab*/); // Get the list of formats the transferable can handle nsCOMPtr pFormats; if(aAction == Read) rc = mTransferable->FlavorsTransferableCanImport(getter_AddRefs(pFormats)); else rc = mTransferable->FlavorsTransferableCanExport(getter_AddRefs(pFormats)); if (NS_FAILED(rc)) return NS_ERROR_FAILURE; uint32_t cFormats = 0; pFormats->Count(&cFormats); for (uint32_t i = 0; i < cFormats; i++) { nsCOMPtr genericFlavor; pFormats->GetElementAt(i, getter_AddRefs(genericFlavor)); nsCOMPtr currentFlavor(do_QueryInterface(genericFlavor)); if (currentFlavor) { nsXPIDLCString flavorStr; currentFlavor->ToString(getter_Copies(flavorStr)); if (aAction == Read) { if (GetClipboardData(flavorStr)) break; } else SetClipboardData(flavorStr); } } WinCloseClipbrd(0/*hab*/); rc = NS_OK; } return rc; } // get the format ID for a given mimetype uint32_t nsClipboard::GetFormatID(const char *aMimeStr) { if (strcmp(aMimeStr, kTextMime) == 0) return CF_TEXT; return RegisterClipboardFormat(aMimeStr); } NS_IMETHODIMP nsClipboard::HasDataMatchingFlavors(const char** aFlavorList, uint32_t aLength, int32_t aWhichClipboard, bool *_retval) { *_retval = false; if (aWhichClipboard != kGlobalClipboard || !aFlavorList) return NS_OK; for (uint32_t i = 0; i < aLength; ++i) { ULONG fmtInfo = 0; uint32_t format = GetFormatID(aFlavorList[i]); if (WinQueryClipbrdFmtInfo(0/*hab*/, format, &fmtInfo)) { *_retval = true; break; } // if the client asked for unicode and it wasn't present, check if we have CF_TEXT. if (!strcmp(aFlavorList[i], kUnicodeMime)) { if (WinQueryClipbrdFmtInfo(0/*hab*/, CF_TEXT, &fmtInfo)) { *_retval = true; break; } } // OS2TODO - Support for Images // if the client asked for image/.. and it wasn't present, check if we have CF_BITMAP. if (strstr(aFlavorList[i], "image/")) { if (WinQueryClipbrdFmtInfo (0, CF_BITMAP, &fmtInfo)) { #ifdef DEBUG printf("nsClipboard:: Image present on clipboard; need to add BMP conversion!\n"); #endif // *_retval = true; // break; } } } return NS_OK; }