#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:
@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
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);
+};
#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
// ----------------------------------------------------------------------------
GdkAtom g_altTextAtom = 0;
GdkAtom g_pngAtom = 0;
GdkAtom g_fileAtom = 0;
+GdkAtom g_htmlAtom = 0;
//-------------------------------------------------------------------------
// wxDataFormat
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") );
}
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;
}
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 );
}
//-------------------------------------------------------------------------
// ---------------------------------------------------------------------------
static bool gs_wxClipboardIsOpen = false;
+static int gs_htmlcfid = 0;
bool wxOpenClipboard()
{
bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
{
- wxDataFormat::NativeFormat cf = dataFormat.GetFormatId();
+ wxDataFormat::NativeFormat cf = dataFormat.GetFormatId();
+ if (cf == wxDF_HTML)
+ cf = gs_htmlcfid;
if ( ::IsClipboardFormatAvailable(cf) )
{
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"
strcpy(ptr, buf);
GlobalUnlock(hText);
- handle = ::SetClipboardData(cfid, hText);
+ handle = ::SetClipboardData(gs_htmlcfid, hText);
// Free memory...
GlobalFree(hText);
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
// 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) )
#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
// ----------------------------------------------------------------------------
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"));
}
}
// 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 )
{
{
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!
//
size_t size;
switch ( format )
{
+ case wxDF_HTML:
case CF_TEXT:
case CF_OEMTEXT:
size = strlen((const char *)pBuf);
// 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));
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;
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;