]> git.saurik.com Git - wxWidgets.git/commitdiff
A patch adding wxHTMLDataObject which can be used for handling the standard platform...
authorRobin Dunn <robin@alldunn.com>
Wed, 30 May 2012 19:21:42 +0000 (19:21 +0000)
committerRobin Dunn <robin@alldunn.com>
Wed, 30 May 2012 19:21:42 +0000 (19:21 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@71610 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/dataobj.h
interface/wx/dataobj.h
src/common/dobjcmn.cpp
src/gtk/dataobj.cpp
src/msw/clipbrd.cpp
src/msw/ole/dataobj.cpp
src/osx/carbon/dataobj.cpp

index d255a5064c9e297826a79e737a5036aa1deddb55..8832aad706b8b6d73bdd2eb8331c671475636339 100644 (file)
@@ -334,6 +334,45 @@ private:
     #endif
 #endif // wxUSE_UNICODE
 
+class WXDLLIMPEXP_CORE wxHTMLDataObject : public wxDataObjectSimple
+{
+public:
+    // ctor: you can specify the text here or in SetText(), or override
+    // GetText()
+    wxHTMLDataObject(const wxString& html = wxEmptyString)
+        : wxDataObjectSimple(wxDF_HTML),
+          m_html(html)
+        {
+        }
+
+    // virtual functions which you may override if you want to provide text on
+    // demand only - otherwise, the trivial default versions will be used
+    virtual size_t GetLength() const { return m_html.Len() + 1; }
+    virtual wxString GetHTML() const { return m_html; }
+    virtual void SetHTML(const wxString& html) { m_html = html; }
+    
+    virtual size_t GetDataSize() const;
+    virtual bool GetDataHere(void *buf) const;
+    virtual bool SetData(size_t len, const void *buf);
+    
+    // Must provide overloads to avoid hiding them (and warnings about it)
+    virtual size_t GetDataSize(const wxDataFormat&) const
+    {
+        return GetDataSize();
+    }
+    virtual bool GetDataHere(const wxDataFormat&, void *buf) const
+    {
+        return GetDataHere(buf);
+    }
+    virtual bool SetData(const wxDataFormat&, size_t len, const void *buf)
+    {
+        return SetData(len, buf);
+    }
+
+private:
+    wxString m_html;
+};
+
 class WXDLLIMPEXP_CORE wxTextDataObject : public wxDataObjectSimple
 {
 public:
index b5614303d063c15c196a47dd6625351385d685b7..4e2e9c9bd7c6a0a9e1000c0e7724a50a9508c424 100644 (file)
@@ -34,9 +34,7 @@
     @itemdef{wxDF_FILENAME,
              A list of filenames.}
     @itemdef{wxDF_HTML,
-             An HTML string. This is only valid when passed to
-             wxSetClipboardData when compiled with Visual C++ in non-Unicode
-             mode.}
+             An HTML string. This is currently only valid on Mac and MSW.}
     @endDefList
 
     As mentioned above, these standard formats may be passed to any function
@@ -789,4 +787,31 @@ public:
     const wxArrayString& GetFilenames() const;
 };
 
+/**
+    @class wxHTMLDataObject
+
+    wxHTMLDataObject is used for working with HTML-formatted text.
+    
+    @library{wxcore}
+    @category{dnd}
+
+    @see wxDataObject, wxDataObjectSimple
+*/
+class wxHTMLDataObject : public wxDataObjectSimple
+{
+public:
+    /**
+        Constructor.
+    */
+    wxHTMLDataObject(const wxString& html = wxEmptyString);
 
+    /**
+        Returns the HTML string.
+    */
+    virtual wxString GetHTML() const;
+    
+    /**
+        Sets the HTML string.
+    */
+    virtual void SetHTML(const wxString& html);
+};
index ebe87267b772dcf85d41bc70096d885818168ba8..2fd5984afeeed2e068e72f0524beaec9add01fb0 100644 (file)
@@ -427,6 +427,117 @@ bool wxTextDataObject::SetData(size_t len, const void *buf)
 
 #endif // different wxTextDataObject implementations
 
+size_t wxHTMLDataObject::GetDataSize() const
+{
+    size_t size = 0;
+    // Windows and Mac always use UTF-8, and docs suggest GTK does as well.
+    wxCharBuffer buffer =  wxConvUTF8.cWX2MB( GetHTML().c_str() );
+
+    if (buffer) 
+    {
+        size = strlen( buffer );
+#if __WXMSW__
+        // On Windows we need to add some stuff to the string to satisfy 
+        // its clipboard format requirements.
+        size += 400;
+#endif
+    }
+
+    return size;
+}
+
+bool wxHTMLDataObject::GetDataHere(void *buf) const
+{
+    if ( !buf )
+        return false;
+
+    // Windows and Mac always use UTF-8, and docs suggest GTK does as well.
+    wxCharBuffer html =  wxConvUTF8.cWX2MB( GetHTML().c_str() );
+    if ( !html )
+        return false;
+
+    size_t bytes = GetDataSize();
+#if __WXMSW__
+    // add the extra info that the MSW clipboard format requires.
+    char* buffer = new char[bytes];
+
+        // Create a template string for the HTML header...
+    strcpy(buffer,
+        "Version:0.9\r\n"
+        "StartHTML:00000000\r\n"
+        "EndHTML:00000000\r\n"
+        "StartFragment:00000000\r\n"
+        "EndFragment:00000000\r\n"
+        "<html><body>\r\n"
+        "<!--StartFragment -->\r\n");
+
+    // Append the HTML...
+    strcat(buffer, html);
+    strcat(buffer, "\r\n");
+    // Finish up the HTML format...
+    strcat(buffer,
+        "<!--EndFragment-->\r\n"
+        "</body>\r\n"
+        "</html>");
+
+    // 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(buffer, "StartHTML");
+    sprintf(ptr+10, "%08u", (unsigned)(strstr(buffer, "<html>") - buffer));
+    *(ptr+10+8) = '\r';
+
+    ptr = strstr(buffer, "EndHTML");
+    sprintf(ptr+8, "%08u", (unsigned)strlen(buffer));
+    *(ptr+8+8) = '\r';
+
+    ptr = strstr(buffer, "StartFragment");
+    sprintf(ptr+14, "%08u", (unsigned)(strstr(buffer, "<!--StartFrag") - buffer));
+    *(ptr+14+8) = '\r';
+
+    ptr = strstr(buffer, "EndFragment");
+    sprintf(ptr+12, "%08u", (unsigned)(strstr(buffer, "<!--EndFrag") - buffer));
+    *(ptr+12+8) = '\r';
+#else
+    wxCharBuffer buffer = html;
+#endif // __WXMSW__
+
+    memcpy( (char*) buf, buffer, bytes );
+
+    return true;
+}
+
+bool wxHTMLDataObject::SetData(size_t WXUNUSED(len), const void *buf)
+{
+    if ( buf == NULL )
+        return false;
+
+    // Windows and Mac always use UTF-8, and docs suggest GTK does as well.
+    wxWCharBuffer buffer =  wxConvUTF8.cMB2WX( (const char*)buf );
+
+    wxString html(buffer);
+    // To be consistent with other platforms, we only add the Fragment part
+    // of the Windows HTML clipboard format to the data object.
+#if __WXMSW__
+    int fragmentStart = html.rfind("StartFragment");
+    int fragmentEnd = html.rfind("EndFragment");
+
+    if (fragmentStart != wxNOT_FOUND && fragmentEnd != wxNOT_FOUND) 
+    {
+        int startCommentEnd = html.find("-->", fragmentStart) + 3;
+        int endCommentStart = html.rfind("<!--", fragmentEnd);
+        
+        if (startCommentEnd != wxNOT_FOUND && endCommentStart != wxNOT_FOUND)
+            html = html.Mid(startCommentEnd, endCommentStart - startCommentEnd);
+    }
+#endif
+    SetHTML( html );
+
+    return true;
+}
+
+
 // ----------------------------------------------------------------------------
 // wxCustomDataObject
 // ----------------------------------------------------------------------------
index 5d8854134cad276af5ddac517505e09e5e3e8afd..c742b77f156bf2ce5fe1c9caaa35809b1aecf1f2 100644 (file)
@@ -33,6 +33,7 @@ GdkAtom  g_textAtom        = 0;
 GdkAtom  g_altTextAtom     = 0;
 GdkAtom  g_pngAtom         = 0;
 GdkAtom  g_fileAtom        = 0;
+GdkAtom  g_htmlAtom        = 0;
 
 //-------------------------------------------------------------------------
 // wxDataFormat
@@ -95,6 +96,9 @@ void wxDataFormat::SetType( wxDataFormatId type )
     if (m_type == wxDF_FILENAME)
         m_format = g_fileAtom;
     else
+    if (m_type == wxDF_HTML)
+        m_format = g_htmlAtom;
+    else
     {
        wxFAIL_MSG( wxT("invalid dataformat") );
     }
@@ -131,6 +135,9 @@ void wxDataFormat::SetId( NativeFormat format )
     else
     if (m_format == g_fileAtom)
         m_type = wxDF_FILENAME;
+    else
+    if (m_format == g_htmlAtom)
+        m_type = wxDF_HTML;
     else
         m_type = wxDF_PRIVATE;
 }
@@ -164,6 +171,8 @@ void wxDataFormat::PrepareFormats()
         g_pngAtom = gdk_atom_intern( "image/png", FALSE );
     if (!g_fileAtom)
         g_fileAtom = gdk_atom_intern( "text/uri-list", FALSE );
+    if (!g_htmlAtom)
+        g_htmlAtom = gdk_atom_intern( "text/html", FALSE );
 }
 
 //-------------------------------------------------------------------------
index 55c12d45af3ec798ff2dc5da135b5830ad6d6df9..bd929dcac3fe3168d363439b49e2de783f86f3ee 100644 (file)
@@ -79,6 +79,7 @@
 // ---------------------------------------------------------------------------
 
 static bool gs_wxClipboardIsOpen = false;
+static int gs_htmlcfid = 0;
 
 bool wxOpenClipboard()
 {
@@ -139,7 +140,9 @@ bool wxIsClipboardOpened()
 
 bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
 {
-   wxDataFormat::NativeFormat cf = dataFormat.GetFormatId();
+    wxDataFormat::NativeFormat cf = dataFormat.GetFormatId();
+    if (cf == wxDF_HTML)
+        cf = gs_htmlcfid;
 
     if ( ::IsClipboardFormatAvailable(cf) )
     {
@@ -304,10 +307,6 @@ bool wxSetClipboardData(wxDataFormat dataFormat,
                 char *buf = new char [400 + strlen(html)];
                 if(!buf) return false;
 
-                // Get clipboard id for HTML format...
-                static int cfid = 0;
-                if(!cfid) cfid = RegisterClipboardFormat(wxT("HTML Format"));
-
                 // Create a template string for the HTML header...
                 strcpy(buf,
                     "Version:0.9\r\n"
@@ -358,7 +357,7 @@ bool wxSetClipboardData(wxDataFormat dataFormat,
                 strcpy(ptr, buf);
                 GlobalUnlock(hText);
 
-                handle = ::SetClipboardData(cfid, hText);
+                handle = ::SetClipboardData(gs_htmlcfid, hText);
 
                 // Free memory...
                 GlobalFree(hText);
@@ -598,6 +597,10 @@ bool wxClipboard::Flush()
 
 bool wxClipboard::Open()
 {
+    // Get clipboard id for HTML format...
+    if(!gs_htmlcfid)
+        gs_htmlcfid = RegisterClipboardFormat(wxT("HTML Format"));
+
     // OLE opens clipboard for us
     m_isOpened = true;
 #if wxUSE_OLE_CLIPBOARD
@@ -814,6 +817,8 @@ bool wxClipboard::GetData( wxDataObject& data )
         // convert to NativeFormat Id
         cf = formats[n].GetFormatId();
 
+        if (cf == wxDF_HTML)
+            cf = gs_htmlcfid;
         // if the format is not available, try the next one
         // this test includes implicit / sythetic formats
         if ( !::IsClipboardFormatAvailable(cf) )
index b1d1e0e8aa2727b80314a4bb5048284cfdccc17d..8558237ec9ecf65b12e81c9186cd7673de0f52f3 100644 (file)
     #define GetTymedName(tymed) wxEmptyString
 #endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL
 
+wxDataFormat HtmlFormatFixup(wxDataFormat format)
+{
+    // Since the HTML format is dynamically registered, the wxDF_HTML
+    // format does not match the native constant in the way other formats do,
+    // so for the format checks below to work, we must change the native
+    // id to the wxDF_HTML constant.
+    wxChar s_szBuf[256];
+    if (::GetClipboardFormatName(format, s_szBuf, WXSIZEOF(s_szBuf)))
+    {
+        if (s_szBuf == wxString("HTML Format"))
+            format = wxDF_HTML;
+    }
+    return format;
+}
+
 // ----------------------------------------------------------------------------
 // wxIEnumFORMATETC interface implementation
 // ----------------------------------------------------------------------------
@@ -183,7 +198,10 @@ wxIEnumFORMATETC::wxIEnumFORMATETC(const wxDataFormat *formats, ULONG nCount)
     m_nCount = nCount;
     m_formats = new CLIPFORMAT[nCount];
     for ( ULONG n = 0; n < nCount; n++ ) {
-        m_formats[n] = formats[n].GetFormatId();
+        if (formats[n].GetFormatId() != wxDF_HTML)
+            m_formats[n] = formats[n].GetFormatId();
+        else
+            m_formats[n] = ::RegisterClipboardFormat(wxT("HTML Format"));
     }
 }
 
@@ -290,6 +308,7 @@ STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
     // for the bitmaps and metafiles we use the handles instead of global memory
     // to pass the data
     wxDataFormat format = (wxDataFormat::NativeFormat)pformatetcIn->cfFormat;
+    format = HtmlFormatFixup(format);
 
     switch ( format )
     {
@@ -432,6 +451,8 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
             {
                 wxDataFormat format = pformatetc->cfFormat;
 
+                format = HtmlFormatFixup(format);
+
                 // this is quite weird, but for file drag and drop, explorer
                 // calls our SetData() with the formats we do *not* support!
                 //
@@ -459,6 +480,7 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
                 size_t size;
                 switch ( format )
                 {
+                    case wxDF_HTML:
                     case CF_TEXT:
                     case CF_OEMTEXT:
                         size = strlen((const char *)pBuf);
@@ -567,6 +589,8 @@ STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
 
     // and now check the type of data requested
     wxDataFormat format = pformatetc->cfFormat;
+    format = HtmlFormatFixup(format);
+
     if ( m_pDataObject->IsSupportedFormat(format) ) {
         wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"),
                    wxGetFormatName(format));
index a4cfb843afe5a50ba1f34c523eaab2186b249567..00bd2207aea0665a1368b04dbf0ab9816f140686 100644 (file)
@@ -128,6 +128,10 @@ void wxDataFormat::SetType( wxDataFormatId dataType )
         m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.utf16-plain-text") );
         break;
 
+    case wxDF_HTML:
+        m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.html") );
+        break;
+
     case wxDF_BITMAP:
         m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.tiff") );
         break;
@@ -158,6 +162,10 @@ void wxDataFormat::SetId( NativeFormat format )
         m_format = 0;
     }
     m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)format);
+    if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.html") ) )
+    {
+        m_type = wxDF_HTML;
+    }
     if (  UTTypeConformsTo( (CFStringRef)format, CFSTR("public.utf16-plain-text") )  )
     {
         m_type = wxDF_UNICODETEXT;