Remove wxUSE_OLE_CLIPBOARD and always use OLE for wxClipboard

It doesn't make sense to keep the old and almost never used alternative
wxClipboard implementation which has known fatal bugs (such as casts of
wxDataObject that could be wxDataObjectComposite to wxBitmapDataObject,
see #23564) when wxUSE_OLE is never going to be disabled anyhow.

Note that this means wxSetClipboardData() function doesn't exist at all
any longer when previously it was available in the wxUSE_OLE==0 builds.
As the official builds always used wxUSE_OLE==1, this doesn't look like
a huge loss, but if needed, we could add it back later and reimplement
it in terms of wxClipboard::SetData().
This commit is contained in:
Vadim Zeitlin 2023-06-20 20:52:08 +01:00
parent 675728e1c0
commit 8a95a93a1d
4 changed files with 11 additions and 481 deletions

View file

@ -323,7 +323,6 @@ library:
manifest from wxWidgets RC file. See also wxUSE_RC_MANIFEST.} manifest from wxWidgets RC file. See also wxUSE_RC_MANIFEST.}
@itemdef{wxUSE_OLE, Enables OLE helper routines.} @itemdef{wxUSE_OLE, Enables OLE helper routines.}
@itemdef{wxUSE_OLE_AUTOMATION, Enable OLE automation utilities.} @itemdef{wxUSE_OLE_AUTOMATION, Enable OLE automation utilities.}
@itemdef{wxUSE_OLE_CLIPBOARD, Use OLE clipboard.}
@itemdef{wxUSE_POSTSCRIPT_ARCHITECTURE_IN_MSW, Use PS printing in wxMSW.} @itemdef{wxUSE_POSTSCRIPT_ARCHITECTURE_IN_MSW, Use PS printing in wxMSW.}
@itemdef{wxUSE_PS_PRINTING, See src/msw/dcprint.cpp file.} @itemdef{wxUSE_PS_PRINTING, See src/msw/dcprint.cpp file.}
@itemdef{wxUSE_RC_MANIFEST, Include manifest for common controls library v6 @itemdef{wxUSE_RC_MANIFEST, Include manifest for common controls library v6

View file

@ -302,6 +302,15 @@
# endif # endif
# endif # endif
# if wxUSE_CLIPBOARD
# ifdef wxABORT_ON_CONFIG_ERROR
# error "wxUSE_CLIPBOARD requires wxUSE_OLE"
# else
# undef wxUSE_CLIPBOARD
# define wxUSE_CLIPBOARD 0
# endif
# endif
# if wxUSE_DRAG_AND_DROP # if wxUSE_DRAG_AND_DROP
# ifdef wxABORT_ON_CONFIG_ERROR # ifdef wxABORT_ON_CONFIG_ERROR
# error "wxUSE_DRAG_AND_DROP requires wxUSE_OLE" # error "wxUSE_DRAG_AND_DROP requires wxUSE_OLE"

View file

@ -24,11 +24,6 @@ WXDLLIMPEXP_CORE bool wxCloseClipboard();
// get/set data // get/set data
WXDLLIMPEXP_CORE bool wxEmptyClipboard(); WXDLLIMPEXP_CORE bool wxEmptyClipboard();
#if !wxUSE_OLE
WXDLLIMPEXP_CORE bool wxSetClipboardData(wxDataFormat dataFormat,
const void *data,
int width = 0, int height = 0);
#endif // !wxUSE_OLE
// clipboard formats // clipboard formats
WXDLLIMPEXP_CORE bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat); WXDLLIMPEXP_CORE bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat);

View file

@ -50,17 +50,7 @@
#include "wx/msw/dib.h" #include "wx/msw/dib.h"
#endif #endif
#if wxUSE_OLE #include <ole2.h>
// use OLE clipboard
#define wxUSE_OLE_CLIPBOARD 1
#else // !wxUSE_DATAOBJ
// use Win clipboard API
#define wxUSE_OLE_CLIPBOARD 0
#endif
#if wxUSE_OLE_CLIPBOARD
#include <ole2.h>
#endif // wxUSE_OLE_CLIPBOARD
// =========================================================================== // ===========================================================================
// implementation // implementation
@ -162,294 +152,6 @@ bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
} }
} }
#if !wxUSE_OLE_CLIPBOARD
namespace
{
struct wxRawImageData
{
size_t m_size;
void* m_data;
};
}
bool wxSetClipboardData(wxDataFormat dataFormat,
const void *data,
int width, int height)
{
HANDLE handle = 0; // return value of SetClipboardData
switch (dataFormat)
{
case wxDF_BITMAP:
{
wxBitmap *bitmap = (wxBitmap *)data;
HDC hdcMem = CreateCompatibleDC(nullptr);
HDC hdcSrc = CreateCompatibleDC(nullptr);
HBITMAP old = (HBITMAP)
::SelectObject(hdcSrc, (HBITMAP)bitmap->GetHBITMAP());
HBITMAP hBitmap = CreateCompatibleBitmap(hdcSrc,
bitmap->GetWidth(),
bitmap->GetHeight());
if (!hBitmap)
{
SelectObject(hdcSrc, old);
DeleteDC(hdcMem);
DeleteDC(hdcSrc);
return false;
}
HBITMAP old1 = (HBITMAP) SelectObject(hdcMem, hBitmap);
BitBlt(hdcMem, 0, 0, bitmap->GetWidth(), bitmap->GetHeight(),
hdcSrc, 0, 0, SRCCOPY);
// Select new bitmap out of memory DC
SelectObject(hdcMem, old1);
// Set the data
handle = ::SetClipboardData(CF_BITMAP, hBitmap);
// Clean up
SelectObject(hdcSrc, old);
DeleteDC(hdcSrc);
DeleteDC(hdcMem);
break;
}
#if wxUSE_WXDIB
case wxDF_DIB:
{
wxBitmap *bitmap = (wxBitmap *)data;
if ( bitmap && bitmap->IsOk() )
{
wxDIB dib(*bitmap);
if ( dib.IsOk() )
{
DIBSECTION ds;
int n = ::GetObject(dib.GetHandle(), sizeof(DIBSECTION), &ds);
wxASSERT( n == sizeof(DIBSECTION) && ds.dsBm.bmBits );
// Number of colours in the palette.
int numColors;
switch ( ds.dsBmih.biCompression )
{
case BI_BITFIELDS:
numColors = 3;
break;
case BI_RGB:
case BI_RLE8:
case BI_RLE4:
numColors = ds.dsBmih.biClrUsed;
if ( !numColors )
{
numColors = ds.dsBmih.biBitCount <= 8 ? 1 << ds.dsBmih.biBitCount : 0;
}
break;
default:
numColors = 0;
}
unsigned long bmpSize = wxDIB::GetLineSize(ds.dsBmih.biWidth, ds.dsBmih.biBitCount) *
abs(ds.dsBmih.biHeight);
HANDLE hMem;
hMem = ::GlobalAlloc(GHND, ds.dsBmih.biSize + numColors*sizeof(RGBQUAD) + bmpSize);
if ( !hMem )
break;
{
GlobalPtrLock ptr(hMem);
char* pDst = (char*)ptr.Get();
memcpy(pDst, &ds.dsBmih, ds.dsBmih.biSize);
pDst += ds.dsBmih.biSize;
if ( numColors > 0 )
{
// Get colour table.
MemoryHDC hDC;
SelectInHDC sDC(hDC, dib.GetHandle());
::GetDIBColorTable(hDC, 0, numColors, (RGBQUAD*)pDst);
pDst += numColors*sizeof(RGBQUAD);
}
memcpy(pDst, dib.GetData(), bmpSize);
} // unlock hMem
handle = ::SetClipboardData(CF_DIB, hMem);
}
}
break;
}
#endif
// VZ: I'm told that this code works, but it doesn't seem to work for me
// and, anyhow, I'd be highly surprised if it did. So I leave it here
// but IMNSHO it is completely broken.
#if wxUSE_METAFILE && !defined(wxMETAFILE_IS_ENH)
case wxDF_METAFILE:
{
wxMetafile *wxMF = (wxMetafile *)data;
HANDLE data = GlobalAlloc(GHND, sizeof(METAFILEPICT) + 1);
{
GlobalPtrLock ptr(data);
METAFILEPICT *mf = (METAFILEPICT *)data.Get();
mf->mm = wxMF->GetWindowsMappingMode();
mf->xExt = width;
mf->yExt = height;
mf->hMF = (HMETAFILE) wxMF->GetHMETAFILE();
wxMF->SetHMETAFILE(nullptr);
} // unlock data
handle = SetClipboardData(CF_METAFILEPICT, data);
break;
}
#endif // wxUSE_METAFILE
#if wxUSE_ENH_METAFILE
case wxDF_ENHMETAFILE:
{
wxEnhMetaFile *emf = (wxEnhMetaFile *)data;
wxEnhMetaFile emfCopy = *emf;
handle = SetClipboardData(CF_ENHMETAFILE,
(void *)emfCopy.GetHENHMETAFILE());
}
break;
#endif // wxUSE_ENH_METAFILE
case CF_SYLK:
case CF_DIF:
case CF_TIFF:
case CF_PALETTE:
default:
{
wxLogError(_("Unsupported clipboard format."));
return false;
}
case wxDF_OEMTEXT:
dataFormat = wxDF_TEXT;
// fall through
case wxDF_TEXT:
{
char *s = (char *)data;
width = strlen(s) + 1;
height = 1;
DWORD l = (width * height);
HANDLE hGlobalMemory = GlobalAlloc(GHND, l);
if ( hGlobalMemory )
{
memcpy(GlobalPtrLock(hGlobalMemory), s, l);
}
handle = SetClipboardData(dataFormat, hGlobalMemory);
break;
}
case wxDF_UNICODETEXT:
{
LPWSTR s = (LPWSTR)data;
DWORD size = sizeof(WCHAR) * (lstrlenW(s) + 1);
HANDLE hGlobalMemory = ::GlobalAlloc(GHND, size);
if ( hGlobalMemory )
{
memcpy(GlobalPtrLock(hGlobalMemory), s, size);
}
handle = ::SetClipboardData(CF_UNICODETEXT, hGlobalMemory);
}
break;
case wxDF_HTML:
{
char* html = (char *)data;
// Create temporary buffer for HTML header...
char *buf = new char [400 + strlen(html)];
if(!buf) return false;
// 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"
"<html><body>\r\n"
"<!--StartFragment -->\r\n");
// Append the HTML...
strcat(buf, html);
strcat(buf, "\r\n");
// Finish up the HTML format...
strcat(buf,
"<!--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(buf, "StartHTML");
sprintf(ptr+10, "%08u", (unsigned)(strstr(buf, "<html>") - buf));
*(ptr+10+8) = '\r';
ptr = strstr(buf, "EndHTML");
sprintf(ptr+8, "%08u", (unsigned)strlen(buf));
*(ptr+8+8) = '\r';
ptr = strstr(buf, "StartFragment");
sprintf(ptr+14, "%08u", (unsigned)(strstr(buf, "<!--StartFrag") - buf));
*(ptr+14+8) = '\r';
ptr = strstr(buf, "EndFragment");
sprintf(ptr+12, "%08u", (unsigned)(strstr(buf, "<!--EndFrag") - buf));
*(ptr+12+8) = '\r';
// Now you have everything in place ready to put on the
// clipboard.
// Allocate global memory for transfer...
HGLOBAL hText = GlobalAlloc(GMEM_MOVEABLE |GMEM_DDESHARE, strlen(buf)+4);
// Put your string in the global memory...
strcpy((char*)GlobalPtrLock(hText).Get(), buf);
handle = ::SetClipboardData(gs_htmlcfid, hText);
// Free memory...
GlobalFree(hText);
// Clean up...
delete [] buf;
break;
}
case wxDF_PNG:
{
const wxRawImageData* imgData = reinterpret_cast<const wxRawImageData*>(data);
GlobalPtr hImage(imgData->m_size, GMEM_MOVEABLE | GMEM_DDESHARE);
memcpy(GlobalPtrLock(hImage).Get(), imgData->m_data, imgData->m_size);
handle = ::SetClipboardData(gs_pngcfid, hImage);
break;
}
}
if ( handle == 0 )
{
wxLogSysError(_("Failed to set clipboard data."));
return false;
}
return true;
}
#endif // !wxUSE_OLE_CLIPBOARD
wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat) wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat)
{ {
return (wxDataFormat::NativeFormat)::EnumClipboardFormats(dataFormat); return (wxDataFormat::NativeFormat)::EnumClipboardFormats(dataFormat);
@ -492,7 +194,6 @@ void wxClipboard::Clear()
if ( IsUsingPrimarySelection() ) if ( IsUsingPrimarySelection() )
return; return;
#if wxUSE_OLE_CLIPBOARD
if (m_lastDataObject) if (m_lastDataObject)
{ {
// don't touch data set by other applications // don't touch data set by other applications
@ -507,12 +208,10 @@ void wxClipboard::Clear()
} }
m_lastDataObject = nullptr; m_lastDataObject = nullptr;
} }
#endif // wxUSE_OLE_CLIPBOARD
} }
bool wxClipboard::Flush() bool wxClipboard::Flush()
{ {
#if wxUSE_OLE_CLIPBOARD
if (m_lastDataObject) if (m_lastDataObject)
{ {
// don't touch data set by other applications // don't touch data set by other applications
@ -531,9 +230,6 @@ bool wxClipboard::Flush()
} }
} }
return false; return false;
#else // !wxUSE_OLE_CLIPBOARD
return false;
#endif // wxUSE_OLE_CLIPBOARD/!wxUSE_OLE_CLIPBOARD
} }
bool wxClipboard::Open() bool wxClipboard::Open()
@ -546,20 +242,13 @@ bool wxClipboard::Open()
// OLE opens clipboard for us // OLE opens clipboard for us
m_isOpened = true; m_isOpened = true;
#if wxUSE_OLE_CLIPBOARD
return true; return true;
#else
return wxOpenClipboard();
#endif
} }
bool wxClipboard::IsOpened() const bool wxClipboard::IsOpened() const
{ {
#if wxUSE_OLE_CLIPBOARD
return m_isOpened; return m_isOpened;
#else
return wxIsClipboardOpened();
#endif
} }
bool wxClipboard::SetData( wxDataObject *data ) bool wxClipboard::SetData( wxDataObject *data )
@ -567,10 +256,6 @@ bool wxClipboard::SetData( wxDataObject *data )
if ( IsUsingPrimarySelection() ) if ( IsUsingPrimarySelection() )
return false; return false;
#if !wxUSE_OLE_CLIPBOARD
(void)wxEmptyClipboard();
#endif // wxUSE_OLE_CLIPBOARD
if ( data ) if ( data )
return AddData(data); return AddData(data);
else else
@ -584,7 +269,6 @@ bool wxClipboard::AddData( wxDataObject *data )
wxCHECK_MSG( data, false, wxT("data is invalid") ); wxCHECK_MSG( data, false, wxT("data is invalid") );
#if wxUSE_OLE_CLIPBOARD
HRESULT hr = OleSetClipboard(data->GetInterface()); HRESULT hr = OleSetClipboard(data->GetInterface());
if ( FAILED(hr) ) if ( FAILED(hr) )
{ {
@ -609,89 +293,11 @@ bool wxClipboard::AddData( wxDataObject *data )
data->SetAutoDelete(); data->SetAutoDelete();
return true; return true;
#elif wxUSE_DATAOBJ
wxCHECK_MSG( wxIsClipboardOpened(), false, wxT("clipboard not open") );
bool bRet = false;
switch ( format )
{
case wxDF_TEXT:
case wxDF_OEMTEXT:
{
wxTextDataObject* textDataObject = (wxTextDataObject*) data;
wxString str(textDataObject->GetText());
bRet = wxSetClipboardData(format, str.c_str());
}
break;
case wxDF_UNICODETEXT:
{
wxTextDataObject* textDataObject = (wxTextDataObject*)data;
wxString str(textDataObject->GetText());
bRet = wxSetClipboardData(format, str.wc_str());
}
break;
case wxDF_BITMAP:
case wxDF_DIB:
{
wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
wxBitmap bitmap(bitmapDataObject->GetBitmap());
bRet = wxSetClipboardData(format, &bitmap);
}
break;
case wxDF_PNG:
{
wxCustomDataObject* imageDataObject = reinterpret_cast<wxCustomDataObject*>(data);
wxRawImageData imgData;
imgData.m_size = imageDataObject->GetDataSize();
imgData.m_data = imageDataObject->GetData();
bRet = wxSetClipboardData(format, &imgData);
}
break;
#if wxUSE_METAFILE
case wxDF_METAFILE:
{
#if 1
// TODO
wxLogError(wxT("Not implemented because wxMetafileDataObject does not contain width and height values."));
#else
wxMetafileDataObject* metaFileDataObject =
(wxMetafileDataObject*) data;
wxMetafile metaFile = metaFileDataObject->GetMetafile();
bRet = wxSetClipboardData(wxDF_METAFILE, &metaFile,
metaFileDataObject->GetWidth(),
metaFileDataObject->GetHeight());
#endif
}
break;
#endif // wxUSE_METAFILE
default:
{
// This didn't compile, of course
// return wxSetClipboardData(data);
// TODO
wxLogError(wxT("Not implemented."));
}
}
// Delete owned, no longer necessary data.
delete data;
return bRet;
#else // !wxUSE_DATAOBJ
return false;
#endif // wxUSE_DATAOBJ/!wxUSE_DATAOBJ
} }
void wxClipboard::Close() void wxClipboard::Close()
{ {
m_isOpened = false; m_isOpened = false;
// OLE closes clipboard for us
#if !wxUSE_OLE_CLIPBOARD
wxCloseClipboard();
#endif
} }
bool wxClipboard::IsSupported( const wxDataFormat& format ) bool wxClipboard::IsSupported( const wxDataFormat& format )
@ -704,7 +310,6 @@ bool wxClipboard::GetData( wxDataObject& data )
if ( IsUsingPrimarySelection() ) if ( IsUsingPrimarySelection() )
return false; return false;
#if wxUSE_OLE_CLIPBOARD
IDataObject *pDataObject = nullptr; IDataObject *pDataObject = nullptr;
HRESULT hr = OleGetClipboard(&pDataObject); HRESULT hr = OleGetClipboard(&pDataObject);
if ( FAILED(hr) || !pDataObject ) if ( FAILED(hr) || !pDataObject )
@ -856,84 +461,6 @@ bool wxClipboard::GetData( wxDataObject& data )
pDataObject->Release(); pDataObject->Release();
return result; return result;
#elif wxUSE_DATAOBJ
wxCHECK_MSG( wxIsClipboardOpened(), false, wxT("clipboard not open") );
wxDataFormat format = data.GetPreferredFormat();
switch ( format )
{
case wxDF_TEXT:
case wxDF_OEMTEXT:
case wxDF_UNICODETEXT:
{
// System provides an automatic type conversion
// from CF_TEXT and CF_OEMTEXT to CF_UNICODETEXT
HANDLE hMem = ::GetClipboardData(CF_UNICODETEXT);
if ( hMem )
{
wxTextDataObject& textDataObject = (wxTextDataObject &)data;
GlobalPtrLock ptr(hMem);
return textDataObject.SetData(ptr.GetSize(), ptr);
}
}
break;
case wxDF_BITMAP:
{
HANDLE hBmp = ::GetClipboardData(CF_BITMAP);
if ( hBmp )
{
wxBitmapDataObject2& bitmapDataObject = (wxBitmapDataObject2 &)data;
return bitmapDataObject.SetData(0, &hBmp);
}
}
break;
case wxDF_DIB:
{
HANDLE hMem = ::GetClipboardData(CF_DIB);
if ( hMem )
{
wxBitmapDataObject& bitmapDataObject = (wxBitmapDataObject &)data;
GlobalPtrLock ptr(hMem);
return bitmapDataObject.SetData(ptr.GetSize(), ptr);
}
}
break;
#if wxUSE_METAFILE && !defined(wxMETAFILE_IS_ENH)
case wxDF_METAFILE:
{
HANDLE hMem = ::GetClipboardData(CF_METAFILEPICT);
if ( hMem )
{
wxMetafileDataObject& metaFileDataObject = (wxMetafileDataObject &)data;
GlobalPtrLock ptr(hMem);
return metaFileDataObject.SetData(wxDF_METAFILE, ptr.GetSize(), ptr);
}
}
break;
#endif // wxUSE_METAFILE && !defined(wxMETAFILE_IS_ENH)
#if wxUSE_ENH_METAFILE
case wxDF_ENHMETAFILE:
{
HANDLE hFile = ::GetClipboardData(CF_ENHMETAFILE);
if ( hFile )
{
wxMetafileDataObject& metaFileDataObject = (wxMetafileDataObject &)data;
return metaFileDataObject.SetData(wxDF_ENHMETAFILE, 0, &hFile);
}
}
break;
#endif // wxUSE_ENH_METAFILE
}
return false;
#else // !wxUSE_DATAOBJ
wxFAIL_MSG( wxT("no clipboard implementation") );
return false;
#endif // wxUSE_OLE_CLIPBOARD/wxUSE_DATAOBJ
} }
#endif // wxUSE_CLIPBOARD #endif // wxUSE_CLIPBOARD