A patch adding wxHTMLDataObject which can be used for handling the standard platform formats for transfering HTML formatted text.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@71610 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -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:
|
||||
|
@@ -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);
|
||||
};
|
||||
|
@@ -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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@@ -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 );
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@@ -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) )
|
||||
|
@@ -67,6 +67,21 @@
|
||||
#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));
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user