From ed780c26483def8c54ee9c2a4c6262a824cff093 Mon Sep 17 00:00:00 2001 From: "pinkerton%netscape.com" Date: Tue, 20 Feb 2001 23:27:57 +0000 Subject: [PATCH] Support for CF_HTML flavor when copying data to other win32 apps. r=saari/sr=hyatt. bug#69363 --- widget/src/windows/nsClipboard.cpp | 7 ++ widget/src/windows/nsClipboard.h | 1 + widget/src/windows/nsDataObj.cpp | 102 ++++++++++++++++++++++++++++- widget/src/windows/nsDataObj.h | 6 +- 4 files changed, 112 insertions(+), 4 deletions(-) diff --git a/widget/src/windows/nsClipboard.cpp b/widget/src/windows/nsClipboard.cpp index 59c948d3be35..54e7d1716a34 100644 --- a/widget/src/windows/nsClipboard.cpp +++ b/widget/src/windows/nsClipboard.cpp @@ -163,6 +163,13 @@ nsresult nsClipboard::SetupNativeDataObject(nsITransferable * aTransferable, IDa 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, ::RegisterClipboardFormat("HTML Format"), 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 diff --git a/widget/src/windows/nsClipboard.h b/widget/src/windows/nsClipboard.h index e784ed5e3c46..6905b6668804 100644 --- a/widget/src/windows/nsClipboard.h +++ b/widget/src/windows/nsClipboard.h @@ -84,3 +84,4 @@ protected: #endif // nsClipboard_h__ + diff --git a/widget/src/windows/nsDataObj.cpp b/widget/src/windows/nsDataObj.cpp index 099da1a1e8ea..994157dba097 100644 --- a/widget/src/windows/nsDataObj.cpp +++ b/widget/src/windows/nsDataObj.cpp @@ -589,8 +589,12 @@ HRESULT nsDataObj::GetText(nsAReadableCString & aDataFlavor, FORMATETC& aFE, STG aSTG.tymed = TYMED_HGLOBAL; aSTG.pUnkForRelease = NULL; - // If someone is asking for text/plain, we need to convert unicode (assuming it's present) - // to text with the correct platform encoding. + // oddly, this isn't in the MSVC headers anywhere. + static int CF_HTML = ::RegisterClipboardFormat("HTML Format"); + + // We play games under the hood and advertise flavors that we know we + // can support, only they require a bit of conversion or munging of the data. + // Do that here. // // The transferable gives us data that is null-terminated, but this isn't reflected in // the |len| parameter. Windoze apps expect this null to be there so bump our data buffer @@ -598,6 +602,8 @@ HRESULT nsDataObj::GetText(nsAReadableCString & aDataFlavor, FORMATETC& aFE, STG // CF_UNICODETEXT). DWORD allocLen = (DWORD)len; if ( aFE.cfFormat == CF_TEXT ) { + // Someone is asking for text/plain; convert the unicode (assuming it's present) + // to text with the correct platform encoding. char* plainTextData = nsnull; PRUnichar* castedUnicode = NS_REINTERPRET_CAST(PRUnichar*, data); PRInt32 plainTextLen = 0; @@ -615,8 +621,26 @@ HRESULT nsDataObj::GetText(nsAReadableCString & aDataFlavor, FORMATETC& aFE, STG return ResultFromScode(S_OK); } } + else if ( aFE.cfFormat == CF_HTML ) { + // Someone is asking for win32's HTML flavor. Convert our html fragment + // from unicode to UTF-8 then put it into a format specified by msft. + NS_ConvertUCS2toUTF8 converter ( NS_REINTERPRET_CAST(PRUnichar*, data) ); + char* utf8HTML = nsnull; + nsresult rv = BuildPlatformHTML ( converter.get(), &utf8HTML ); // null terminates + + nsMemory::Free(data); + if ( NS_SUCCEEDED(rv) && utf8HTML ) { + // replace the unicode data with our HTML data. Don't forget the null. + data = utf8HTML; + allocLen = strlen(utf8HTML) + sizeof(char); + } + else { + NS_WARNING ( "Oh no, couldn't convert to HTML" ); + return ResultFromScode(S_OK); + } + } else { - // we assume that any data that isn't CF_TEXT is unicode. This may + // we assume that any data that isn't caught above is unicode. This may // be an erroneous assumption, but is true so far. allocLen += sizeof(PRUnichar); } @@ -801,3 +825,75 @@ nsDataObj :: ExtractShortcutTitle ( nsString & outTitle ) return rv; } // ExtractShortcutTitle + + +// +// BuildPlatformHTML +// +// Munge our HTML data to win32's CF_HTML spec. Basically, put the requisite +// header information on it. This will null terminate |outPlatformHTML|. See +// http://msdn.microsoft.com/workshop/networking/clipboard/htmlclipboard.asp +// for details. +// +// We assume that |inOurHTML| is already a fragment (ie, doesn't have +// or tags). We'll wrap the fragment with them to make other apps +// happy. +// +// This code is derived from sample code from MSDN. It's ugly, I agree. +// +nsresult +nsDataObj :: BuildPlatformHTML ( const char* inOurHTML, char** outPlatformHTML ) +{ + *outPlatformHTML = nsnull; + + // Create temporary buffer for HTML header... + char *buf = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(400 + strlen(inOurHTML))); + if( !buf ) + return NS_ERROR_FAILURE; + + // Get clipboard id for HTML format... + static int cfid = RegisterClipboardFormat("HTML Format");; + + // Create a template string for the HTML header... + strcpy(buf, + "Version:0.9\r\n" + "StartHTML:00000000\r\n" + "EndHTML:00000000\r\n" + "StartFragment:00000000\r\n" + "EndFragment:00000000\r\n" + "\r\n" + "\r\n"); + + // Append the HTML... + strcat(buf, inOurHTML); + strcat(buf, "\r\n"); + // Finish up the HTML format... + strcat(buf, + "\r\n" + "\r\n" + ""); + + // Now go back, calculate all the lengths, and write out the + // necessary header information. Note, wsprintf() truncates the + // string when you overwrite it so you follow up with code to replace + // the 0 appended at the end with a '\r'... + char *ptr = strstr(buf, "StartHTML"); + wsprintf(ptr+10, "%08u", strstr(buf, "") - buf); + *(ptr+10+8) = '\r'; + + ptr = strstr(buf, "EndHTML"); + wsprintf(ptr+8, "%08u", strlen(buf)); + *(ptr+8+8) = '\r'; + + ptr = strstr(buf, "StartFragment"); + wsprintf(ptr+14, "%08u", strstr(buf, "