// 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<nsISupportsArray> 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; PRUint32 cFormats = 0; pFormats->Count(&cFormats); for (PRUint32 i = 0; i < cFormats; i++) { nsCOMPtr<nsISupports> genericFlavor; pFormats->GetElementAt(i, getter_AddRefs(genericFlavor)); nsCOMPtr<nsISupportsCString> 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; }
// nsIObserver NS_IMETHODIMP nsClipboard::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) { // This will be called on shutdown. // make sure we have a good transferable if (!mTransferable) return NS_ERROR_FAILURE; if (WinOpenClipbrd(0/*hab*/)) { WinEmptyClipbrd(0/*hab*/); // get flavor list that includes all flavors that can be written (including ones // obtained through conversion) nsCOMPtr<nsISupportsArray> flavorList; nsresult errCode = mTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList)); if (NS_FAILED(errCode)) return NS_ERROR_FAILURE; // Walk through flavors and put data on to clipboard PRUint32 i; PRUint32 cnt; flavorList->Count(&cnt); for (i = 0; i < cnt; i++) { nsCOMPtr<nsISupports> genericFlavor; flavorList->GetElementAt(i, getter_AddRefs(genericFlavor)); nsCOMPtr<nsISupportsCString> currentFlavor(do_QueryInterface(genericFlavor)); if (currentFlavor) { nsXPIDLCString flavorStr; currentFlavor->ToString(getter_Copies(flavorStr)); SetClipboardData(flavorStr); } } WinCloseClipbrd(0/*hab*/); } return NS_OK; }
//------------------------------------------------------------------------- nsresult nsClipboard::GetDataFromDataObject(IDataObject * aDataObject, UINT anIndex, nsIWidget * aWindow, nsITransferable * aTransferable) { // make sure we have a good transferable if ( !aTransferable ) return NS_ERROR_INVALID_ARG; nsresult res = NS_ERROR_FAILURE; // get flavor list that includes all flavors that can be written (including ones // obtained through conversion) nsCOMPtr<nsISupportsArray> flavorList; res = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) ); if ( NS_FAILED(res) ) return NS_ERROR_FAILURE; // Walk through flavors and see which flavor is on the clipboard them on the native clipboard, PRUint32 i; PRUint32 cnt; flavorList->Count(&cnt); for (i=0;i<cnt;i++) { nsCOMPtr<nsISupports> genericFlavor; flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) ); nsCOMPtr<nsISupportsCString> currentFlavor ( do_QueryInterface(genericFlavor) ); if ( currentFlavor ) { nsXPIDLCString flavorStr; currentFlavor->ToString(getter_Copies(flavorStr)); UINT format = GetFormat(flavorStr); // Try to get the data using the desired flavor. This might fail, but all is // not lost. void* data = nullptr; PRUint32 dataLen = 0; bool dataFound = false; if (nullptr != aDataObject) { if ( NS_SUCCEEDED(GetNativeDataOffClipboard(aDataObject, anIndex, format, flavorStr, &data, &dataLen)) ) dataFound = true; } else if (nullptr != aWindow) { if ( NS_SUCCEEDED(GetNativeDataOffClipboard(aWindow, anIndex, format, &data, &dataLen)) ) dataFound = true; } // This is our second chance to try to find some data, having not found it // when directly asking for the flavor. Let's try digging around in other // flavors to help satisfy our craving for data. if ( !dataFound ) { if ( strcmp(flavorStr, kUnicodeMime) == 0 ) dataFound = FindUnicodeFromPlainText ( aDataObject, anIndex, &data, &dataLen ); else if ( strcmp(flavorStr, kURLMime) == 0 ) { // drags from other windows apps expose the native // CFSTR_INETURL{A,W} flavor dataFound = FindURLFromNativeURL ( aDataObject, anIndex, &data, &dataLen ); if ( !dataFound ) dataFound = FindURLFromLocalFile ( aDataObject, anIndex, &data, &dataLen ); } } // if we try one last ditch effort to find our data // Hopefully by this point we've found it and can go about our business if ( dataFound ) { nsCOMPtr<nsISupports> genericDataWrapper; if ( strcmp(flavorStr, kFileMime) == 0 ) { // we have a file path in |data|. Create an nsLocalFile object. nsDependentString filepath(reinterpret_cast<PRUnichar*>(data)); nsCOMPtr<nsIFile> file; if ( NS_SUCCEEDED(NS_NewLocalFile(filepath, false, getter_AddRefs(file))) ) genericDataWrapper = do_QueryInterface(file); nsMemory::Free(data); } else if ( strcmp(flavorStr, kNativeHTMLMime) == 0) { // the editor folks want CF_HTML exactly as it's on the clipboard, no conversions, // no fancy stuff. Pull it off the clipboard, stuff it into a wrapper and hand // it back to them. if ( FindPlatformHTML(aDataObject, anIndex, &data, &dataLen) ) nsPrimitiveHelpers::CreatePrimitiveForData ( flavorStr, data, dataLen, getter_AddRefs(genericDataWrapper) ); else { nsMemory::Free(data); continue; // something wrong with this flavor, keep looking for other data } nsMemory::Free(data); } else if ( strcmp(flavorStr, kJPEGImageMime) == 0 || strcmp(flavorStr, kJPGImageMime) == 0 || strcmp(flavorStr, kPNGImageMime) == 0) { nsIInputStream * imageStream = reinterpret_cast<nsIInputStream*>(data); genericDataWrapper = do_QueryInterface(imageStream); NS_IF_RELEASE(imageStream); } else { // we probably have some form of text. The DOM only wants LF, so convert from Win32 line // endings to DOM line endings. PRInt32 signedLen = static_cast<PRInt32>(dataLen); nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks ( flavorStr, &data, &signedLen ); dataLen = signedLen; nsPrimitiveHelpers::CreatePrimitiveForData ( flavorStr, data, dataLen, getter_AddRefs(genericDataWrapper) ); nsMemory::Free(data); } NS_ASSERTION ( genericDataWrapper, "About to put null data into the transferable" ); aTransferable->SetTransferData(flavorStr, genericDataWrapper, dataLen); res = NS_OK; // we found one, get out of the loop break; } } } // foreach flavor return res; }
//------------------------------------------------------------------------- nsresult nsClipboard::SetupNativeDataObject(nsITransferable * aTransferable, IDataObject * aDataObj) { if (nullptr == aTransferable || nullptr == aDataObj) { return NS_ERROR_FAILURE; } nsDataObj * dObj = static_cast<nsDataObj *>(aDataObj); // Now give the Transferable to the DataObject // for getting the data out of it dObj->SetTransferable(aTransferable); // Get the transferable list of data flavors nsCOMPtr<nsISupportsArray> dfList; aTransferable->FlavorsTransferableCanExport(getter_AddRefs(dfList)); // Walk through flavors that contain data and register them // into the DataObj as supported flavors PRUint32 i; PRUint32 cnt; dfList->Count(&cnt); for (i=0;i<cnt;i++) { nsCOMPtr<nsISupports> genericFlavor; dfList->GetElementAt ( i, getter_AddRefs(genericFlavor) ); nsCOMPtr<nsISupportsCString> currentFlavor ( do_QueryInterface(genericFlavor) ); if ( currentFlavor ) { nsXPIDLCString flavorStr; currentFlavor->ToString(getter_Copies(flavorStr)); UINT format = GetFormat(flavorStr); // Now tell the native IDataObject about both our mime type and // the native data format FORMATETC fe; SET_FORMATETC(fe, format, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL); dObj->AddDataFlavor(flavorStr, &fe); // Do various things internal to the implementation, like map one // flavor to another or add additional flavors based on what's required // for the win32 impl. if ( strcmp(flavorStr, kUnicodeMime) == 0 ) { // if we find text/unicode, also advertise text/plain (which we will convert // on our own in nsDataObj::GetText(). FORMATETC textFE; SET_FORMATETC(textFE, CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL); dObj->AddDataFlavor(kTextMime, &textFE); } else if ( strcmp(flavorStr, kHTMLMime) == 0 ) { // if we find text/html, also advertise win32's html flavor (which we will convert // on our own in nsDataObj::GetText(). FORMATETC htmlFE; SET_FORMATETC(htmlFE, CF_HTML, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL); dObj->AddDataFlavor(kHTMLMime, &htmlFE); } else if ( strcmp(flavorStr, kURLMime) == 0 ) { // if we're a url, in addition to also being text, we need to register // the "file" flavors so that the win32 shell knows to create an internet // shortcut when it sees one of these beasts. FORMATETC shortcutFE; SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL) dObj->AddDataFlavor(kURLMime, &shortcutFE); SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL) dObj->AddDataFlavor(kURLMime, &shortcutFE); SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_FILECONTENTS), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL) dObj->AddDataFlavor(kURLMime, &shortcutFE); SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_INETURLA), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL) dObj->AddDataFlavor(kURLMime, &shortcutFE); SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_INETURLW), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL) dObj->AddDataFlavor(kURLMime, &shortcutFE); } else if ( strcmp(flavorStr, kPNGImageMime) == 0 || strcmp(flavorStr, kJPEGImageMime) == 0 || strcmp(flavorStr, kJPGImageMime) == 0 || strcmp(flavorStr, kGIFImageMime) == 0 || strcmp(flavorStr, kNativeImageMime) == 0 ) { // if we're an image, register the native bitmap flavor FORMATETC imageFE; SET_FORMATETC(imageFE, CF_DIBV5, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL) dObj->AddDataFlavor(flavorStr, &imageFE); } else if ( strcmp(flavorStr, kFilePromiseMime) == 0 ) { // if we're a file promise flavor, also register the // CFSTR_PREFERREDDROPEFFECT format. The data object // returns a value of DROPEFFECTS_MOVE to the drop target // when it asks for the value of this format. This causes // the file to be moved from the temporary location instead // of being copied. The right thing to do here is to call // SetData() on the data object and set the value of this format // to DROPEFFECTS_MOVE on this particular data object. But, // since all the other clipboard formats follow the model of setting // data on the data object only when the drop object calls GetData(), // I am leaving this format's value hard coded in the data object. // We can change this if other consumers of this format get added to this // codebase and they need different values. FORMATETC shortcutFE; SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL) dObj->AddDataFlavor(kFilePromiseMime, &shortcutFE); } } } return NS_OK; }
// // The blocking Paste routine // NS_IMETHODIMP nsClipboard::GetNativeClipboardData(nsITransferable * aTransferable, PRInt32 aWhichClipboard ) { #ifdef DEBUG_CLIPBOARD printf(" nsClipboard::GetNativeClipboardData()\n"); #endif /* DEBUG_CLIPBOARD */ // make sure we have a good transferable if (nsnull == aTransferable) { printf(" GetNativeClipboardData: Transferable is null!\n"); return NS_ERROR_FAILURE; } // get flavor list nsresult rv; nsCOMPtr<nsISupportsArray> flavorList; rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavorList)); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; // get native clipboard data if (!be_clipboard->Lock()) return NS_ERROR_FAILURE; BMessage *msg = be_clipboard->Data(); if (!msg) return NS_ERROR_FAILURE; #ifdef DEBUG_CLIPBOARD msg->PrintToStream(); #endif /* DEBUG_CLIPBOARD */ PRUint32 cnt; flavorList->Count(&cnt); for (PRUint32 i = 0; i < cnt; i++) { nsCOMPtr<nsISupports> genericFlavor; flavorList->GetElementAt(i, getter_AddRefs(genericFlavor)); nsCOMPtr<nsISupportsCString> currentFlavor(do_QueryInterface(genericFlavor)); if (currentFlavor) { nsXPIDLCString flavorStr; currentFlavor->ToString(getter_Copies(flavorStr)); #ifdef DEBUG_CLIPBOARD printf("nsClipboard: %d/%d = %s\n", i, cnt, (const char *)flavorStr); #endif /* DEBUG_CLIPBOARD */ const void *data; ssize_t size; if (0 == strncmp(flavorStr, "text/", 5)) { // [Be] text/ * => [NS] text/ * status_t rc; if (0 == strcmp(flavorStr, kUnicodeMime)) rc = msg->FindData(kTextMime, B_MIME_TYPE, &data, &size); else rc = msg->FindData(flavorStr, B_MIME_TYPE, &data, &size); if (rc != B_OK || !data || !size) { #ifdef DEBUG_CLIPBOARD printf("nsClipboard: not found in BMessage\n"); #endif /* DEBUG_CLIPBOARD */ } else { NS_ConvertUTF8toUTF16 ucs2Str((const char *)data, (PRUint32)size); nsCOMPtr<nsISupports> genericDataWrapper; nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, (void *)ucs2Str.get(), ucs2Str.Length() * 2, getter_AddRefs(genericDataWrapper)); rv = aTransferable->SetTransferData(flavorStr, genericDataWrapper, ucs2Str.Length() * 2); } } else { // [Be] * / * => [NS] * / * if (B_OK != msg->FindData(flavorStr, B_MIME_TYPE, &data, &size)) { #ifdef DEBUG_CLIPBOARD printf("nsClipboard: not found in BMessage\n"); #endif /* DEBUG_CLIPBOARD */ } else { nsCOMPtr<nsISupports> genericDataWrapper; nsPrimitiveHelpers::CreatePrimitiveForData(flavorStr, (void *)data, (PRUint32)size, getter_AddRefs(genericDataWrapper)); rv = aTransferable->SetTransferData(flavorStr, genericDataWrapper, size); } } #ifdef DEBUG_CLIPBOARD if (NS_FAILED(rv)) printf("nsClipboard: Error SetTransferData\n"); #endif /* DEBUG_CLIPBOARD */ } else { rv = NS_ERROR_FAILURE; #ifdef DEBUG_CLIPBOARD printf("nsClipboard: Error gerring flavor"); #endif /* DEBUG_CLIPBOARD */ } if (rv != NS_OK) break; } /* for */ be_clipboard->Unlock(); return rv; }
// // The copy routine // NS_IMETHODIMP nsClipboard::SetNativeClipboardData(PRInt32 aWhichClipboard) { mIgnoreEmptyNotification = PR_TRUE; #ifdef DEBUG_CLIPBOARD printf(" nsClipboard::SetNativeClipboardData()\n"); #endif /* DEBUG_CLIPBOARD */ // make sure we have a good transferable if (nsnull == mTransferable) { #ifdef DEBUG_CLIPBOARD printf(" SetNativeClipboardData: no transferable!\n"); #endif /* DEBUG_CLIPBOARD */ return NS_ERROR_FAILURE; } // lock the native clipboard if (!be_clipboard->Lock()) return NS_ERROR_FAILURE; // clear the native clipboard nsresult rv = NS_OK; if (B_OK == be_clipboard->Clear()) { // set data to the native clipboard if (BMessage *msg = be_clipboard->Data()) { // Get the transferable list of data flavors nsCOMPtr<nsISupportsArray> dfList; mTransferable->FlavorsTransferableCanExport(getter_AddRefs(dfList)); // Walk through flavors that contain data and register them // into the BMessage as supported flavors PRUint32 i; PRUint32 cnt; dfList->Count(&cnt); for (i = 0; i < cnt && rv == NS_OK; i++) { nsCOMPtr<nsISupports> genericFlavor; dfList->GetElementAt(i, getter_AddRefs(genericFlavor)); nsCOMPtr<nsISupportsCString> currentFlavor (do_QueryInterface(genericFlavor)); if (currentFlavor) { nsXPIDLCString flavorStr; currentFlavor->ToString(getter_Copies(flavorStr)); #ifdef DEBUG_CLIPBOARD printf("nsClipboard: %d/%d = %s\n", i, cnt, (const char *)flavorStr); #endif /* DEBUG_CLIPBOARD */ if (0 == strncmp(flavorStr, "text/", 5)) { // [NS] text/ * => [Be] text/ * void *data = nsnull; PRUint32 dataSize = 0; nsCOMPtr<nsISupports> genericDataWrapper; rv = mTransferable->GetTransferData(flavorStr, getter_AddRefs(genericDataWrapper), &dataSize); nsPrimitiveHelpers::CreateDataFromPrimitive(flavorStr, genericDataWrapper, &data, dataSize); #ifdef DEBUG_CLIPBOARD if (NS_FAILED(rv)) printf("nsClipboard: Error getting data from transferable\n"); #endif /* DEBUG_CLIPBOARD */ if (dataSize && data != nsnull) { NS_ConvertUCS2toUTF8 cv((const PRUnichar *)data, (PRUint32)dataSize / 2); const char *utf8Str = cv.get(); uint32 utf8Len = strlen(utf8Str); #ifdef DEBUG_CLIPBOARD if (0 == strcmp(flavorStr, kUnicodeMime)) printf(" => [%s]%s\n", kTextMime, utf8Str); else printf(" => [%s]%s\n", (const char *)flavorStr, utf8Str); #endif /* DEBUG_CLIPBOARD */ status_t rc; if (0 == strcmp(flavorStr, kUnicodeMime)) { // [NS] text/unicode => [Be] text/plain rc = msg->AddData(kTextMime, B_MIME_TYPE, (void *)utf8Str, utf8Len); } else { // [NS] text/ * => [Be] text/ * rc = msg->AddData((const char *)flavorStr, B_MIME_TYPE, (void *)utf8Str, utf8Len); } if (rc != B_OK) rv = NS_ERROR_FAILURE; } else { #ifdef DEBUG_CLIPBOARD printf("nsClipboard: Error null data from transferable\n"); #endif /* DEBUG_CLIPBOARD */ // not fatal. force to continue... rv = NS_OK; } } else { // [NS] * / * => [Be] * / * void *data = nsnull; PRUint32 dataSize = 0; nsCOMPtr<nsISupports> genericDataWrapper; rv = mTransferable->GetTransferData(flavorStr, getter_AddRefs(genericDataWrapper), &dataSize); nsPrimitiveHelpers::CreateDataFromPrimitive(flavorStr, genericDataWrapper, &data, dataSize); #ifdef DEBUG_CLIPBOARD if (NS_FAILED(rv)) printf("nsClipboard: Error getting data from transferable\n"); #endif /* DEBUG_CLIPBOARD */ if (dataSize && data != nsnull) { #ifdef DEBUG_CLIPBOARD printf("[%s](binary)\n", (const char *)flavorStr); #endif /* DEBUG_CLIPBOARD */ if (B_OK != msg->AddData((const char *)flavorStr, B_MIME_TYPE, data, dataSize)) rv = NS_ERROR_FAILURE; } } } else { #ifdef DEBUG_CLIPBOARD printf("nsClipboard: Error getting flavor\n"); #endif /* DEBUG_CLIPBOARD */ rv = NS_ERROR_FAILURE; } } /* for */ } else { rv = NS_ERROR_FAILURE; } } else { rv = NS_ERROR_FAILURE; } if (B_OK != be_clipboard->Commit()) rv = NS_ERROR_FAILURE; be_clipboard->Unlock(); mIgnoreEmptyNotification = PR_FALSE; return rv; }
NS_IMETHODIMP nsClipboard::SetNativeClipboardData( nsITransferable *aTransferable, QClipboard::Mode clipboardMode ) { if (nsnull == aTransferable) { qDebug("nsClipboard::SetNativeClipboardData(): no transferable!"); return NS_ERROR_FAILURE; } // get flavor list that includes all flavors that can be written (including // ones obtained through conversion) nsCOMPtr<nsISupportsArray> flavorList; nsresult errCode = aTransferable->FlavorsTransferableCanExport( getter_AddRefs(flavorList) ); if (NS_FAILED(errCode)) { qDebug("nsClipboard::SetNativeClipboardData(): no FlavorsTransferable !"); return NS_ERROR_FAILURE; } QClipboard *cb = QApplication::clipboard(); PRUint32 flavorCount = 0; flavorList->Count(&flavorCount); for (PRUint32 i = 0; i < flavorCount; ++i) { nsCOMPtr<nsISupports> genericFlavor; flavorList->GetElementAt(i,getter_AddRefs(genericFlavor)); nsCOMPtr<nsISupportsCString> currentFlavor(do_QueryInterface(genericFlavor)); if (currentFlavor) { // flavorStr is the mime type nsXPIDLCString flavorStr; currentFlavor->ToString(getter_Copies(flavorStr)); // Clip is the data which will be sent to the clipboard nsCOMPtr<nsISupports> clip; // len is the length of the data PRUint32 len; // Unicode text? if (!strcmp(flavorStr.get(), kUnicodeMime)) { aTransferable->GetTransferData(flavorStr,getter_AddRefs(clip),&len); nsCOMPtr<nsISupportsString> wideString; wideString = do_QueryInterface(clip); if (!wideString) { return NS_ERROR_FAILURE; } nsAutoString utf16string; wideString->GetData(utf16string); QString str = QString::fromUtf16(utf16string.get()); // Set the date to the clipboard cb->setText(str, clipboardMode); break; } if ( !strcmp(flavorStr.get(), kNativeImageMime) || !strcmp(flavorStr.get(), kPNGImageMime) || !strcmp(flavorStr.get(), kJPEGImageMime) || !strcmp(flavorStr.get(), kGIFImageMime)) { qDebug("nsClipboard::SetNativeClipboardData(): Copying image data not implemented!"); } } } return NS_OK; }
// nsClipboard::GetNativeClipboardData ie. Paste // NS_IMETHODIMP nsClipboard::GetNativeClipboardData(nsITransferable *aTransferable, QClipboard::Mode clipboardMode) { if (nsnull == aTransferable) { qDebug(" GetNativeClipboardData: Transferable is null!"); return NS_ERROR_FAILURE; } // get flavor list that includes all acceptable flavors (including // ones obtained through conversion) nsCOMPtr<nsISupportsArray> flavorList; nsresult errCode = aTransferable->FlavorsTransferableCanImport( getter_AddRefs(flavorList)); if (NS_FAILED(errCode)) { qDebug("nsClipboard::GetNativeClipboardData(): no FlavorsTransferable %i !", errCode); return NS_ERROR_FAILURE; } QClipboard *cb = QApplication::clipboard(); const QMimeData *mimeData = cb->mimeData(clipboardMode); // Walk through flavors and see which flavor matches the one being pasted PRUint32 flavorCount; flavorList->Count(&flavorCount); nsCAutoString foundFlavor; for (PRUint32 i = 0; i < flavorCount; ++i) { nsCOMPtr<nsISupports> genericFlavor; flavorList->GetElementAt(i,getter_AddRefs(genericFlavor)); nsCOMPtr<nsISupportsCString> currentFlavor(do_QueryInterface( genericFlavor) ); if (currentFlavor) { nsXPIDLCString flavorStr; currentFlavor->ToString(getter_Copies(flavorStr)); // Ok, so which flavor the data being pasted could be? // Text? if (!strcmp(flavorStr.get(), kUnicodeMime)) { if (mimeData->hasText()) { // Clipboard has text and flavor accepts text, so lets // handle the data as text foundFlavor = nsCAutoString(flavorStr); // Get the text data from clipboard QString text = mimeData->text(); const QChar *unicode = text.unicode(); // Is there a more correct way to get the size in UTF16? PRUint32 len = (PRUint32) 2*text.size(); // And then to genericDataWrapper nsCOMPtr<nsISupports> genericDataWrapper; nsPrimitiveHelpers::CreatePrimitiveForData( foundFlavor.get(), (void*)unicode, len, getter_AddRefs(genericDataWrapper)); // Data is good, set it to the transferable aTransferable->SetTransferData(foundFlavor.get(), genericDataWrapper,len); // And thats all break; } } // Image? if (!strcmp(flavorStr.get(), kJPEGImageMime) || !strcmp(flavorStr.get(), kPNGImageMime) || !strcmp(flavorStr.get(), kGIFImageMime)) { qDebug("nsClipboard::GetNativeClipboardData(): Pasting image data not implemented!"); break; } } } return NS_OK; }
// // GetData // // Pull data out of the OS drag item at the requested index and stash it into the // given transferable. Only put in the data with the highest fidelity asked for and // stop as soon as we find a match. // NS_IMETHODIMP nsDragService::GetData ( nsITransferable * aTransferable, PRUint32 aItemIndex ) { nsresult errCode = NS_ERROR_FAILURE; // make sure we have a good transferable if ( !aTransferable ) return NS_ERROR_INVALID_ARG; // get flavor list that includes all acceptable flavors (including ones obtained through // conversion). Flavors are nsISupportsCStrings so that they can be seen from JS. nsCOMPtr<nsISupportsArray> flavorList; errCode = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) ); if ( NS_FAILED(errCode) ) return errCode; // get the data for the requested drag item. Remember that GetDragItemReferenceNumber() // is one-based NOT zero-based like |aItemIndex| is. ItemReference itemRef; ::GetDragItemReferenceNumber ( mDragRef, aItemIndex + 1, &itemRef ); // create a mime mapper to help us out based on data in a special flavor for this item char* mappings = LookupMimeMappingsForItem(mDragRef, itemRef); nsMimeMapperMac theMapper ( mappings ); nsMemory::Free ( mappings ); // Now walk down the list of flavors. When we find one that is actually present, // copy out the data into the transferable in that format. SetTransferData() // implicitly handles conversions. PRUint32 cnt; flavorList->Count ( &cnt ); for (PRUint32 i = 0; i < cnt; ++i) { nsCOMPtr<nsISupports> genericWrapper; flavorList->GetElementAt ( i, getter_AddRefs(genericWrapper) ); nsCOMPtr<nsISupportsCString> currentFlavor ( do_QueryInterface(genericWrapper) ); if ( currentFlavor ) { // find MacOS flavor (but don't add it if it's not there) nsCAutoString flavorStr; currentFlavor->GetData(flavorStr); FlavorType macOSFlavor = theMapper.MapMimeTypeToMacOSType(flavorStr.get(), PR_FALSE); #if DEBUG_DD printf("looking for data in type %s, mac flavor %ld\n", flavorStr.get(), macOSFlavor); #endif // check if it is present in the current drag item. FlavorFlags unused; PRBool dataFound = PR_FALSE; void* dataBuff = nsnull; PRUint32 dataSize = 0; if ( macOSFlavor && ::GetFlavorFlags(mDragRef, itemRef, macOSFlavor, &unused) == noErr ) { nsresult loadResult = ExtractDataFromOS(mDragRef, itemRef, macOSFlavor, &dataBuff, &dataSize); if ( NS_SUCCEEDED(loadResult) && dataBuff ) dataFound = PR_TRUE; } else { // if we are looking for text/unicode and we fail to find it on the clipboard first, // try again with text/plain. If that is present, convert it to unicode. if ( strcmp(flavorStr.get(), kUnicodeMime) == 0 ) { if ( ::GetFlavorFlags(mDragRef, itemRef, 'TEXT', &unused) == noErr ) { // if 'styl' is available, we can get a script of the first run // and use it for converting 'TEXT' nsresult loadResult = ExtractDataFromOS(mDragRef, itemRef, 'styl', &dataBuff, &dataSize); if (NS_SUCCEEDED(loadResult) && dataBuff && (dataSize >= (sizeof(ScrpSTElement) + 2))) { StScrpRec *scrpRecP = (StScrpRec *) dataBuff; ScrpSTElement *styl = scrpRecP->scrpStyleTab; ScriptCode script = styl ? ::FontToScript(styl->scrpFont) : smCurrentScript; // free 'styl' and get 'TEXT' nsMemory::Free(dataBuff); loadResult = ExtractDataFromOS(mDragRef, itemRef, 'TEXT', &dataBuff, &dataSize); if ( NS_SUCCEEDED(loadResult) && dataBuff ) { PRUnichar* convertedText = nsnull; PRInt32 convertedTextLen = 0; errCode = nsMacNativeUnicodeConverter::ConvertScripttoUnicode(script, (const char *) dataBuff, dataSize, &convertedText, &convertedTextLen); if (NS_SUCCEEDED(errCode) && convertedText) { nsMemory::Free(dataBuff); dataBuff = convertedText; dataSize = convertedTextLen * sizeof(PRUnichar); dataFound = PR_TRUE; } } } if (!dataFound) { loadResult = ExtractDataFromOS(mDragRef, itemRef, 'TEXT', &dataBuff, &dataSize); if ( NS_SUCCEEDED(loadResult) && dataBuff ) { const char* castedText = NS_REINTERPRET_CAST(char*, dataBuff); PRUnichar* convertedText = nsnull; PRInt32 convertedTextLen = 0; nsPrimitiveHelpers::ConvertPlatformPlainTextToUnicode ( castedText, dataSize, &convertedText, &convertedTextLen ); if ( convertedText ) { // out with the old, in with the new nsMemory::Free(dataBuff); dataBuff = convertedText; dataSize = convertedTextLen * 2; dataFound = PR_TRUE; } } // if plain text data on clipboard } } // if plain text flavor present } // if looking for text/unicode } // else we try one last ditch effort to find our data if ( dataFound ) { nsCOMPtr<nsISupports> genericDataWrapper; if ( strcmp(flavorStr.get(), kFileMime) == 0 ) { // we have a HFSFlavor struct in |dataBuff|. Create an nsLocalFileMac object. HFSFlavor* fileData = NS_REINTERPRET_CAST(HFSFlavor*, dataBuff); NS_ASSERTION ( sizeof(HFSFlavor) == dataSize, "Ooops, we really don't have a HFSFlavor" ); nsCOMPtr<nsILocalFileMac> file; if ( NS_SUCCEEDED(NS_NewLocalFileWithFSSpec(&fileData->fileSpec, PR_TRUE, getter_AddRefs(file))) ) genericDataWrapper = do_QueryInterface(file); } else if ((strcmp(flavorStr.get(), kURLDataMime) == 0) || (strcmp(flavorStr.get(), kURLDescriptionMime) == 0)) {
// // RegisterDragItemsAndFlavors // // Takes the multiple drag items from an array of transferables and registers them // and their flavors with the MacOS DragManager. Note that we don't actually place // any of the data there yet, but will rely on a sendDataProc to get the data as // requested. // void nsDragService::RegisterDragItemsAndFlavors(nsISupportsArray* inArray, RgnHandle inDragRgn) { const FlavorFlags flags = 0; Rect dragRgnBounds = {0, 0, 0, 0}; if (inDragRgn) GetRegionBounds(inDragRgn, &dragRgnBounds); PRUint32 numDragItems = 0; inArray->Count ( &numDragItems ) ; for ( PRUint32 itemIndex = 0; itemIndex < numDragItems; ++itemIndex ) { nsMimeMapperMac theMapper; nsCOMPtr<nsISupports> genericItem; inArray->GetElementAt ( itemIndex, getter_AddRefs(genericItem) ); nsCOMPtr<nsITransferable> currItem ( do_QueryInterface(genericItem) ); if ( currItem ) { nsCOMPtr<nsISupportsArray> flavorList; if ( NS_SUCCEEDED(currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList))) ) { PRUint32 numFlavors; flavorList->Count ( &numFlavors ); for ( PRUint32 flavorIndex = 0; flavorIndex < numFlavors; ++flavorIndex ) { nsCOMPtr<nsISupports> genericWrapper; flavorList->GetElementAt ( flavorIndex, getter_AddRefs(genericWrapper) ); nsCOMPtr<nsISupportsCString> currentFlavor ( do_QueryInterface(genericWrapper) ); if ( currentFlavor ) { nsCAutoString flavorStr; currentFlavor->GetData(flavorStr); FlavorType macOSFlavor = theMapper.MapMimeTypeToMacOSType(flavorStr.get()); if (macOSFlavor == kDragFlavorTypePromiseHFS) { // we got kFilePromiseMime // kDragFlavorTypePromiseHFS is special. See http://developer.apple.com/technotes/tn/tn1085.html PromiseHFSFlavor promiseData; promiseData.fileType = 0; // let the file extension prevail! promiseData.fileCreator = 0; promiseData.fdFlags = 0; promiseData.promisedFlavor = kDragPromisedFlavor; ::AddDragItemFlavor(mDragRef, itemIndex, kDragFlavorTypePromiseHFS, &promiseData, sizeof(promiseData), flavorNotSaved); ::AddDragItemFlavor(mDragRef, itemIndex, kDragPromisedFlavor, NULL, 0, flavorNotSaved); } else ::AddDragItemFlavor(mDragRef, itemIndex, macOSFlavor, NULL, 0, flags); // If we advertise text/unicode, then make sure we add 'TEXT' to the list // of flavors supported since we will do the conversion ourselves in GetDataForFlavor() if ( strcmp(flavorStr.get(), kUnicodeMime) == 0 ) { theMapper.MapMimeTypeToMacOSType(kTextMime); ::AddDragItemFlavor ( mDragRef, itemIndex, 'TEXT', NULL, 0, flags ); ::AddDragItemFlavor ( mDragRef, itemIndex, 'styl', NULL, 0, flags ); } } } // foreach flavor in item } // if valid flavor list } // if item is a transferable // put the mime mapping data for this item in a special flavor. Unlike the other data, // we have to put the data in now (rather than defer it) or the mappings will go out // of scope by the time they are asked for. Remember that the |mappingLen| // includes the null, and we need to maintain that for when we parse it. short mappingLen; char* mapping = theMapper.ExportMapping(&mappingLen); if ( mapping && mappingLen ) { ::AddDragItemFlavor ( mDragRef, itemIndex, nsMimeMapperMac::MappingFlavor(), mapping, mappingLen, flags ); nsMemory::Free ( mapping ); ::SetDragItemBounds(mDragRef, itemIndex, &dragRgnBounds); } } // foreach drag item } // RegisterDragItemsAndFlavors