///////////////////////////////////////////////////////////////////////////////
-// Name: dnd.cpp
+// Name: src/os2/dnd.cpp
// Purpose: wxDropTarget, wxDropSource, wxDataObject implementation
// Author: David Webster
// Modified by:
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
-#ifdef __GNUG__
-#pragma implementation "dnd.h"
-#endif
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#if wxUSE_DRAG_AND_DROP
-#define INCL_PM
-#define INCL_DOS
-#include <os2.h>
#include "wx/window.h"
#include "wx/app.h"
#include "wx/gdicmn.h"
#include "wx/dnd.h"
-#if wxUSE_DRAG_AND_DROP
+#define INCL_PM
+#define INCL_DOS
+#include <os2.h>
// ----------------------------------------------------------------------------
// global
// ----------------------------------------------------------------------------
+/////////////////////////////////////////////////////////////////////////////
+// Private functions
+/////////////////////////////////////////////////////////////////////////////
+
+#if 0
+static wxDragResult ConvertDragEffectToResult (
+ DWORD dwEffect
+)
+{
+ switch (dwEffect)
+ {
+ case DO_COPY:
+ return wxDragCopy;
+
+ case DO_LINK:
+ return wxDragLink;
+
+ case DO_MOVE:
+ return wxDragMove;
+
+ default:
+ case DO_DEFAULT:
+ return wxDragNone;
+ }
+} // end of ConvertDragEffectToResult
+
+static DWORD ConvertDragResultToEffect (
+ wxDragResult eResult
+)
+{
+ switch (eResult)
+ {
+ case wxDragCopy:
+ return DO_COPY;
+
+ case wxDragLink:
+ return DO_LINK;
+
+ case wxDragMove:
+ return DO_MOVE;
+
+ default:
+ case wxDragNone:
+ return DO_DEFAULT;
+ }
+} // end of ConvertDragResultToEffect
+#endif
+
+class CIDropTarget
+{
+public:
+ CIDropTarget(wxDropTarget* pTarget)
+ {
+ m_pTarget = pTarget;
+ m_pDragItem = NULL;
+ }
+ virtual ~CIDropTarget() { }
+
+ //
+ // Accessors for CDropTarget
+ //
+ void Free(void) { ::DrgFreeDraginfo(m_pDragInfo); }
+ PDRAGINFO GetDataSource(void) { return m_pDragInfo; }
+ void SetDataSource(PDRAGINFO pDragInfo) { m_pDragInfo = pDragInfo; }
+ void SetHWND(HWND hWnd) { m_hWnd = hWnd; }
+
+ //
+ // CIDropTarget methods
+ //
+ bool DragLeave(void);
+ MRESULT DragOver(void);
+ MRESULT Drop(void);
+
+protected:
+
+ PDRAGINFO m_pDragInfo;
+ PDRAGITEM m_pDragItem; // !NULL between DragEnter and DragLeave/Drop
+ wxDropTarget* m_pTarget; // the real target (we're just a proxy)
+ HWND m_hWnd; // window we're associated with
+}; // end of CLASS CIDropTarget
+
+bool CIDropTarget::DragLeave()
+{
+ //
+ // Remove the UI feedback
+ //
+ m_pTarget->OnLeave();
+
+ //
+ // Release the held object
+ //
+ Free();
+ return true;
+} // end of CIDropTarget::DragLeave
+
+MRESULT CIDropTarget::DragOver ()
+{
+ char zBuffer[128];
+ ULONG ulBytes;
+ USHORT uOp = 0;
+ USHORT uIndicator;
+ ULONG ulItems;
+ ULONG i;
+
+ ::DrgAccessDraginfo(m_pDragInfo);
+ switch(m_pDragInfo->usOperation)
+ {
+ case DO_UNKNOWN:
+ Free();
+ return (MRFROM2SHORT(DOR_NODROPOP, 0));
+
+ case DO_DEFAULT:
+ m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, 0);
+ ulBytes = ::DrgQueryStrName( m_pDragItem->hstrContainerName
+ ,128
+ ,zBuffer
+ );
+ if (!ulBytes)
+ return (MRFROM2SHORT(DOR_NODROPOP, 0));
+ else
+ uOp = DO_MOVE;
+ break;
+
+ case DO_COPY:
+ case DO_MOVE:
+ uOp = m_pDragInfo->usOperation;
+ break;
+ }
+ uIndicator = DOR_DROP;
+ ulItems = (ULONG)::DrgQueryDragitemCount(m_pDragInfo);
+ for (i = 0; i < ulItems; i++)
+ {
+ m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, i);
+ if (((m_pDragItem->fsSupportedOps & DO_COPYABLE) &&
+ (uOp == (USHORT)DO_COPY)) ||
+ ((m_pDragItem->fsSupportedOps & DO_MOVEABLE) &&
+ (uOp == (USHORT)DO_COPY)))
+ {
+ if (::DrgVerifyRMF(m_pDragItem, "DRM_OS2FILE", "DRF_UNKNOWN"))
+ uIndicator = (USHORT)DOR_DROP;
+ else
+ uIndicator = (USHORT)DOR_NEVERDROP;
+ }
+ }
+ Free();
+ return (MRFROM2SHORT(uIndicator, uOp));
+} // end of CIDropTarget::DragOver
+
+// #pragma page "CIDropTarget::Drop"
+/////////////////////////////////////////////////////////////////////////////
+//
+// CIDropTarget::Drop
+//
+// Instructs the drop target to paste data that was just now dropped on it.
+//
+// PARAMETERS
+// pIDataSource -- the data to paste
+// dwKeyState -- kbd & mouse state
+// pt -- mouse coordinates
+// pdwEffect -- effect flag
+//
+// RETURN VALUE
+// STDMETHODIMP S_OK
+//
+/////////////////////////////////////////////////////////////////////////////
+MRESULT CIDropTarget::Drop ()
+{
+ char zBuffer[128];
+ ULONG ulBytes;
+ USHORT uOp = 0;
+ USHORT uIndicator;
+ ULONG ulItems;
+ ULONG i;
+
+ ::DrgAccessDraginfo(m_pDragInfo);
+ switch(m_pDragInfo->usOperation)
+ {
+ case DO_UNKNOWN:
+ Free();
+ return (MRFROM2SHORT(DOR_NODROPOP, 0));
+
+ case DO_DEFAULT:
+ m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, 0);
+ ulBytes = ::DrgQueryStrName( m_pDragItem->hstrContainerName
+ ,128
+ ,zBuffer
+ );
+ if (!ulBytes)
+ return (MRFROM2SHORT(DOR_NODROPOP, 0));
+ else
+ uOp = DO_MOVE;
+ break;
+
+ case DO_COPY:
+ case DO_MOVE:
+ uOp = m_pDragInfo->usOperation;
+ break;
+ }
+ uIndicator = DOR_DROP;
+ ulItems = (ULONG)::DrgQueryDragitemCount(m_pDragInfo);
+ for (i = 0; i < ulItems; i++)
+ {
+ m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, i);
+ if (((m_pDragItem->fsSupportedOps & DO_COPYABLE) &&
+ (uOp == (USHORT)DO_COPY)) ||
+ ((m_pDragItem->fsSupportedOps & DO_MOVEABLE) &&
+ (uOp == (USHORT)DO_COPY)))
+ {
+ if (::DrgVerifyRMF(m_pDragItem, "DRM_OS2FILE", "DRF_UNKNOWN"))
+ uIndicator = (USHORT)DOR_DROP;
+ else
+ uIndicator = (USHORT)DOR_NEVERDROP;
+ }
+ }
+
+ //
+ // First ask the drop target if it wants data
+ //
+ if (m_pTarget->OnDrop( m_pDragInfo->xDrop
+ ,m_pDragInfo->yDrop
+ ))
+ {
+ wxDragResult eRc = wxDragNone;
+
+ //
+ // And now it has the data
+ //
+ eRc = m_pTarget->OnData( m_pDragInfo->xDrop
+ ,m_pDragInfo->yDrop
+ ,eRc
+ );
+ }
+ //else: OnDrop() returned false, no need to copy data
+
+ //
+ // Release the held object
+ //
+ Free();
+ return (MRFROM2SHORT(uIndicator, uOp));
+} // end of CIDropTarget::Drop
+
// ----------------------------------------------------------------------------
// wxDropTarget
// ----------------------------------------------------------------------------
-wxDropTarget::wxDropTarget(
+wxDropTarget::wxDropTarget (
wxDataObject* pDataObject
)
{
- // TODO:
-};
+ m_dataObject = pDataObject;
+ m_pDropTarget = new CIDropTarget(this);
+} // end of wxDropTarget::wxDropTarget
wxDropTarget::~wxDropTarget()
{
-};
+ Release();
+} // end of wxDropTarget::~wxDropTarget
-void wxDropTarget::Register(
- WXHWND hwnd
-)
+bool wxDropTarget::GetData ()
{
- //TODO:
-};
+ wxDataFormat vFormat = GetSupportedFormat(m_pDropTarget->GetDataSource());
-void wxDropTarget::Revoke(
- WXHWND hwnd
-)
+ if (vFormat == wxDF_INVALID)
+ {
+ return false;
+ }
+ //
+ // Under OS/2 we already have the data via the attached DRAGITEM's
+ //
+ return true;
+} // end of wxDropTarget::GetData
+
+wxDataFormat wxDropTarget::GetSupportedFormat (
+ PDRAGINFO pDataSource
+) const
{
- //TODO:
-};
+ PDRAGITEM pDragItem;
+ wxDataFormat vFormat;
+ wxDataFormat* pFormats;
+ ULONG ulFormats = m_dataObject->GetFormatCount(wxDataObject::Set);
+ ULONG ulItems = (ULONG)::DrgQueryDragitemCount(pDataSource);
+ ULONG i;
+ ULONG n;
+ wxString sMechanism;
+ wxString sFormat;
+ bool bValid = false;
-wxDragResult wxDropTarget::OnDragOver(
- wxCoord x
-, wxCoord y
-, wxDragResult vDef
-)
+ pFormats = ulFormats == 1 ? &vFormat : new wxDataFormat[ulFormats];
+ m_dataObject->GetAllFormats( pFormats
+ ,wxDataObject::Set
+ );
+
+ for (n = 0; n < ulFormats; n++)
+ {
+ switch(pFormats[n].GetType())
+ {
+ case wxDF_TEXT:
+ case wxDF_FILENAME:
+ case wxDF_HTML:
+ sMechanism = _T("DRM_OS2FILE");
+ sFormat = _T("DRF_TEXT");
+ break;
+
+ case wxDF_OEMTEXT:
+ sMechanism = _T("DRM_OS2FILE");
+ sFormat = _T("DRF_OEMTEXT");
+ break;
+
+ case wxDF_BITMAP:
+ sMechanism = _T("DRM_OS2FILE");
+ sFormat = _T("DRF_BITMAP");
+ break;
+
+ case wxDF_METAFILE:
+ case wxDF_ENHMETAFILE:
+ sMechanism = _T("DRM_OS2FILE");
+ sFormat = _T("DRF_METAFILE");
+ break;
+
+ case wxDF_TIFF:
+ sMechanism = _T("DRM_OS2FILE");
+ sFormat = _T("DRF_TIFF");
+ break;
+
+ case wxDF_SYLK:
+ sMechanism = _T("DRM_OS2FILE");
+ sFormat = _T("DRF_SYLK");
+ break;
+
+ case wxDF_DIF:
+ sMechanism = _T("DRM_OS2FILE");
+ sFormat = _T("DRF_DIF");
+ break;
+
+ case wxDF_DIB:
+ sMechanism = _T("DRM_OS2FILE");
+ sFormat = _T("DRF_DIB");
+ break;
+
+ case wxDF_PALETTE:
+ case wxDF_PENDATA:
+ case wxDF_RIFF:
+ case wxDF_WAVE:
+ case wxDF_UNICODETEXT:
+ case wxDF_LOCALE:
+ sMechanism = _T("DRM_OS2FILE");
+ sFormat = _T("DRF_UNKNOWN");
+ break;
+
+ case wxDF_PRIVATE:
+ sMechanism = _T("DRM_OBJECT");
+ sFormat = _T("DRF_UNKNOWN");
+ break;
+ }
+ for (i = 0; i < ulItems; i++)
+ {
+ pDragItem = ::DrgQueryDragitemPtr(pDataSource, i);
+ if (::DrgVerifyRMF(pDragItem, (PSZ)sMechanism.c_str(), (PSZ)sFormat.c_str()))
+ {
+ bValid = true;
+ break;
+ }
+ }
+ if (bValid)
+ {
+ vFormat = pFormats[n];
+ break;
+ }
+ }
+ if (pFormats != &vFormat)
+ {
+ //
+ // Free memory if we allocated it
+ //
+ delete [] pFormats;
+ }
+ return (n < ulFormats ? vFormat : wxFormatInvalid);
+} // end of wxDropTarget::GetSupportedFormat
+
+bool wxDropTarget::IsAcceptedData (
+ PDRAGINFO pDataSource
+) const
{
- //TODO:
- return vDef;
-};
+ return (GetSupportedFormat(pDataSource) != wxDF_INVALID);
+} // end of wxDropTarget::IsAcceptedData
-bool wxDropTarget::OnDrop(
- wxCoord x
-, wxCoord y
-)
+void wxDropTarget::Release ()
{
- //TODO:
- return FALSE;
-};
+ m_pDropTarget->Free();
+} // end of wxDropTarget::Release
+
-wxDragResult wxDropTarget::OnData(
- wxCoord x
-, wxCoord y
-, wxDragResult vResult
+wxDragResult wxDropTarget::OnData (
+ wxCoord WXUNUSED(vX)
+, wxCoord WXUNUSED(y)
+, wxDragResult WXUNUSED(vResult)
)
{
- //TODO:
return (wxDragResult)0;
-};
+} // end of wxDropTarget::OnData
-bool wxDropTarget::GetData()
-{
- //TODO:
- return FALSE;
-};
-
-bool wxDropTarget::IsAcceptable(
- DRAGINFO* pInfo
+bool wxDropTarget::OnDrop (
+ wxCoord WXUNUSED(x)
+, wxCoord WXUNUSED(y)
)
{
- //TODO:
- return FALSE;
-};
+ return true;
+} // end of wxDropTarget::OnDrop
//-------------------------------------------------------------------------
// wxDropSource
//-------------------------------------------------------------------------
-wxDropSource::wxDropSource(
- wxWindow* pWin
-)
+wxDropSource::wxDropSource ( wxWindow* WXUNUSED(pWin) )
{
- // TODO
-};
+ Init();
+} // end of wxDropSource::wxDropSource
-wxDropSource::wxDropSource(
- wxDataObject& rData
-, wxWindow* pWin
-)
+wxDropSource::wxDropSource ( wxDataObject& rData, wxWindow* WXUNUSED(pWin) )
{
- // TODO
-};
+ Init();
+ SetData(rData);
+} // end of wxDropSource::wxDropSource
-wxDropSource::~wxDropSource()
+wxDropSource::~wxDropSource ()
{
- // TODO
-};
+ ::DrgFreeDraginfo(m_pDragInfo);
+} // end of wxDropSource::~wxDropSource
-wxDragResult wxDropSource::DoDragDrop(
- bool WXUNUSED(bAllowMove)
+wxDragResult wxDropSource::DoDragDrop (
+ int WXUNUSED(flags)
)
{
- // TODO
+ //
+ // Need to specify drag items in derived classes that know their data types
+ // before calling DoDragDrop
+ //
+ if (::DrgDrag( m_pWindow->GetHWND()
+ ,m_pDragInfo
+ ,&m_vDragImage
+ ,m_ulItems
+ ,VK_BUTTON2
+ ,NULL
+ ) != NULLHANDLE)
+ {
+ switch(m_pDragInfo->usOperation)
+ {
+ case DO_COPY:
+ return wxDragCopy;
+
+ case DO_MOVE:
+ return wxDragCopy;
+
+ case DO_LINK:
+ return wxDragCopy;
+
+ default:
+ return wxDragNone;
+ }
+ }
return wxDragError;
-};
+} // end of wxDropSource::DoDragDrop
+
+bool wxDropSource::GiveFeedback (
+ wxDragResult eEffect
+)
+{
+ const wxCursor& rCursor = GetCursor(eEffect);
-void wxDropSource::Init()
+ if (rCursor.Ok())
+ {
+ ::WinSetPointer(HWND_DESKTOP, (HPOINTER)rCursor.GetHCURSOR());
+ m_vDragImage.hImage = (LHANDLE)rCursor.GetHCURSOR();
+ switch(eEffect)
+ {
+ case wxDragCopy:
+ m_pDragInfo->usOperation = DO_COPY;
+ break;
+
+ case wxDragMove:
+ m_pDragInfo->usOperation = DO_MOVE;
+ break;
+
+ case wxDragLink:
+ m_pDragInfo->usOperation = DO_LINK;
+ break;
+
+ case wxDragNone:
+ case wxDragCancel:
+ case wxDragError:
+ break;
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+} // end of GuiAdvDnd_CDropSource::GiveFeedback
+
+void wxDropSource::Init ()
{
- // TODO
-};
+ m_pDragInfo = ::DrgAllocDraginfo(m_ulItems);
+
+ //
+ // Set a default drag image struct with what we know so far
+ //
+ m_vDragImage.cb = sizeof(DRAGIMAGE);
+ m_vDragImage.cptl = 0; // non-zero if fl is DRG_POLYGON
+ m_vDragImage.hImage = 0; // Set in GiveFeedback
+ m_vDragImage.sizlStretch.cx = 20L;
+ m_vDragImage.sizlStretch.cy = 20L;
+ m_vDragImage.fl = DRG_ICON | DRG_STRETCH;
+ m_vDragImage.cxOffset = 0;
+ m_vDragImage.cyOffset = 0;
+
+ HSTR hStrType = ::DrgAddStrHandle(DRT_UNKNOWN);
+ HSTR hStrRMF;
+ HSTR hStrContainer;
+ wxChar zFormats[128];
+ wxChar zContainer[128];
+ USHORT uSize = (USHORT)(GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat()) + 1);
+ wxChar* pzBuffer = new wxChar[uSize];
+
+ memset(pzBuffer, '\0', GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat()));
+ pzBuffer[GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat())] = '\0';
+ GetDataObject()->GetDataHere( GetDataObject()->GetPreferredFormat()
+ ,(void*)pzBuffer
+ );
+
+ wxStrcpy(zFormats, _T("<DRM_OS2FILE, DRF_UNKNOWN>"));
+ wxStrcpy(zContainer, GetDataObject()->GetPreferredFormat().GetId());
+
+ hStrRMF = ::DrgAddStrHandle((PSZ)zFormats);
+ hStrContainer = ::DrgAddStrHandle((PSZ)zContainer);
+
+ m_pDragItem = new DRAGITEM[m_ulItems];
+ for (ULONG i = 0; i < m_ulItems; i++)
+ {
+ m_pDragItem[i].hwndItem = m_pWindow->GetHWND();
+ m_pDragItem[i].hstrType = hStrType;
+ m_pDragItem[i].hstrRMF = hStrRMF;
+ m_pDragItem[i].hstrContainerName = hStrContainer;
+ m_pDragItem[i].fsControl = 0;
+ m_pDragItem[i].fsSupportedOps = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE;
+ m_pDragItem[i].hstrSourceName = ::DrgAddStrHandle((PSZ)pzBuffer);
+ m_pDragItem[i].hstrTargetName = m_pDragItem[i].hstrSourceName;
+ m_pDragItem[i].ulItemID = i;
+ ::DrgSetDragitem( m_pDragInfo
+ ,&m_pDragItem[i]
+ ,sizeof(DRAGITEM)
+ ,0
+ );
+ }
+ delete [] pzBuffer;
+ delete [] m_pDragItem;
+} // end of wxDropSource::Init
#endif //wxUSE_DRAG_AND_DROP