]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dnd.cpp
SF bug 1327872
[wxWidgets.git] / src / os2 / dnd.cpp
CommitLineData
0e320a79
DW
1///////////////////////////////////////////////////////////////////////////////
2// Name: dnd.cpp
3// Purpose: wxDropTarget, wxDropSource, wxDataObject implementation
6dddc146 4// Author: David Webster
0e320a79 5// Modified by:
6dddc146 6// Created: 10/21/99
0e320a79
DW
7// RCS-ID: $Id$
8// Copyright: (c) 1998 AUTHOR
65571936 9// Licence: wxWindows licence
0e320a79
DW
10///////////////////////////////////////////////////////////////////////////////
11
6670f564
WS
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#if wxUSE_DRAG_AND_DROP
16
0e320a79
DW
17#include "wx/window.h"
18#include "wx/app.h"
19#include "wx/gdicmn.h"
e6ebb514 20#include "wx/dnd.h"
0e320a79 21
55945915
SN
22#define INCL_PM
23#define INCL_DOS
24#include <os2.h>
25
0e320a79
DW
26// ----------------------------------------------------------------------------
27// global
28// ----------------------------------------------------------------------------
29
4fd899b6
DW
30/////////////////////////////////////////////////////////////////////////////
31// Private functions
32/////////////////////////////////////////////////////////////////////////////
33
9923c37d 34#if 0
4fd899b6
DW
35static wxDragResult ConvertDragEffectToResult (
36 DWORD dwEffect
37)
38{
39 switch (dwEffect)
40 {
41 case DO_COPY:
42 return wxDragCopy;
43
44 case DO_LINK:
45 return wxDragLink;
46
47 case DO_MOVE:
48 return wxDragMove;
49
50 default:
51 case DO_DEFAULT:
52 return wxDragNone;
53 }
54} // end of ConvertDragEffectToResult
55
56static DWORD ConvertDragResultToEffect (
57 wxDragResult eResult
58)
59{
60 switch (eResult)
61 {
62 case wxDragCopy:
63 return DO_COPY;
64
65 case wxDragLink:
66 return DO_LINK;
67
68 case wxDragMove:
69 return DO_MOVE;
70
71 default:
72 case wxDragNone:
73 return DO_DEFAULT;
74 }
75} // end of ConvertDragResultToEffect
9923c37d 76#endif
4fd899b6
DW
77
78class CIDropTarget
79{
80public:
81 CIDropTarget(wxDropTarget* pTarget)
82 {
83 m_pTarget = pTarget;
84 m_pDragItem = NULL;
85 }
86 virtual ~CIDropTarget() { }
87
88 //
89 // Accessors for CDropTarget
90 //
91 void Free(void) { ::DrgFreeDraginfo(m_pDragInfo); }
92 PDRAGINFO GetDataSource(void) { return m_pDragInfo; }
93 void SetDataSource(PDRAGINFO pDragInfo) { m_pDragInfo = pDragInfo; }
94 void SetHWND(HWND hWnd) { m_hWnd = hWnd; }
95
96 //
97 // CIDropTarget methods
98 //
99 bool DragLeave(void);
100 MRESULT DragOver(void);
101 MRESULT Drop(void);
102
103protected:
104
105 PDRAGINFO m_pDragInfo;
106 PDRAGITEM m_pDragItem; // !NULL between DragEnter and DragLeave/Drop
107 wxDropTarget* m_pTarget; // the real target (we're just a proxy)
108 HWND m_hWnd; // window we're associated with
109}; // end of CLASS CIDropTarget
110
111bool CIDropTarget::DragLeave()
112{
113 //
114 // Remove the UI feedback
115 //
116 m_pTarget->OnLeave();
117
118 //
119 // Release the held object
120 //
121 Free();
d0ee33f5 122 return true;
4fd899b6
DW
123} // end of CIDropTarget::DragLeave
124
125MRESULT CIDropTarget::DragOver ()
126{
127 char zBuffer[128];
128 ULONG ulBytes;
322d45dd 129 USHORT uOp = 0;
4fd899b6
DW
130 USHORT uIndicator;
131 ULONG ulItems;
132 ULONG i;
133
134 ::DrgAccessDraginfo(m_pDragInfo);
135 switch(m_pDragInfo->usOperation)
136 {
137 case DO_UNKNOWN:
138 Free();
139 return (MRFROM2SHORT(DOR_NODROPOP, 0));
140
141 case DO_DEFAULT:
142 m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, 0);
143 ulBytes = ::DrgQueryStrName( m_pDragItem->hstrContainerName
144 ,128
145 ,zBuffer
146 );
147 if (!ulBytes)
148 return (MRFROM2SHORT(DOR_NODROPOP, 0));
149 else
150 uOp = DO_MOVE;
151 break;
152
153 case DO_COPY:
154 case DO_MOVE:
155 uOp = m_pDragInfo->usOperation;
156 break;
157 }
158 uIndicator = DOR_DROP;
159 ulItems = (ULONG)::DrgQueryDragitemCount(m_pDragInfo);
160 for (i = 0; i < ulItems; i++)
161 {
162 m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, i);
163 if (((m_pDragItem->fsSupportedOps & DO_COPYABLE) &&
164 (uOp == (USHORT)DO_COPY)) ||
165 ((m_pDragItem->fsSupportedOps & DO_MOVEABLE) &&
166 (uOp == (USHORT)DO_COPY)))
167 {
168 if (::DrgVerifyRMF(m_pDragItem, "DRM_OS2FILE", "DRF_UNKNOWN"))
169 uIndicator = (USHORT)DOR_DROP;
170 else
171 uIndicator = (USHORT)DOR_NEVERDROP;
172 }
173 }
174 Free();
175 return (MRFROM2SHORT(uIndicator, uOp));
176} // end of CIDropTarget::DragOver
177
178// #pragma page "CIDropTarget::Drop"
179/////////////////////////////////////////////////////////////////////////////
180//
181// CIDropTarget::Drop
182//
183// Instructs the drop target to paste data that was just now dropped on it.
184//
185// PARAMETERS
186// pIDataSource -- the data to paste
187// dwKeyState -- kbd & mouse state
188// pt -- mouse coordinates
189// pdwEffect -- effect flag
190//
191// RETURN VALUE
192// STDMETHODIMP S_OK
193//
194/////////////////////////////////////////////////////////////////////////////
195MRESULT CIDropTarget::Drop ()
196{
197 char zBuffer[128];
198 ULONG ulBytes;
322d45dd 199 USHORT uOp = 0;
4fd899b6
DW
200 USHORT uIndicator;
201 ULONG ulItems;
202 ULONG i;
203
204 ::DrgAccessDraginfo(m_pDragInfo);
205 switch(m_pDragInfo->usOperation)
206 {
207 case DO_UNKNOWN:
208 Free();
209 return (MRFROM2SHORT(DOR_NODROPOP, 0));
210
211 case DO_DEFAULT:
212 m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, 0);
213 ulBytes = ::DrgQueryStrName( m_pDragItem->hstrContainerName
214 ,128
215 ,zBuffer
216 );
217 if (!ulBytes)
218 return (MRFROM2SHORT(DOR_NODROPOP, 0));
219 else
220 uOp = DO_MOVE;
221 break;
222
223 case DO_COPY:
224 case DO_MOVE:
225 uOp = m_pDragInfo->usOperation;
226 break;
227 }
228 uIndicator = DOR_DROP;
229 ulItems = (ULONG)::DrgQueryDragitemCount(m_pDragInfo);
230 for (i = 0; i < ulItems; i++)
231 {
232 m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, i);
233 if (((m_pDragItem->fsSupportedOps & DO_COPYABLE) &&
234 (uOp == (USHORT)DO_COPY)) ||
235 ((m_pDragItem->fsSupportedOps & DO_MOVEABLE) &&
236 (uOp == (USHORT)DO_COPY)))
237 {
238 if (::DrgVerifyRMF(m_pDragItem, "DRM_OS2FILE", "DRF_UNKNOWN"))
239 uIndicator = (USHORT)DOR_DROP;
240 else
241 uIndicator = (USHORT)DOR_NEVERDROP;
242 }
243 }
244
245 //
246 // First ask the drop target if it wants data
247 //
248 if (m_pTarget->OnDrop( m_pDragInfo->xDrop
249 ,m_pDragInfo->yDrop
250 ))
251 {
d0ee33f5 252 wxDragResult eRc = wxDragNone;
4fd899b6
DW
253
254 //
255 // And now it has the data
256 //
257 eRc = m_pTarget->OnData( m_pDragInfo->xDrop
258 ,m_pDragInfo->yDrop
259 ,eRc
260 );
261 }
d0ee33f5 262 //else: OnDrop() returned false, no need to copy data
4fd899b6
DW
263
264 //
265 // Release the held object
266 //
267 Free();
268 return (MRFROM2SHORT(uIndicator, uOp));
269} // end of CIDropTarget::Drop
270
0e320a79
DW
271// ----------------------------------------------------------------------------
272// wxDropTarget
273// ----------------------------------------------------------------------------
274
4fd899b6 275wxDropTarget::wxDropTarget (
6dddc146
DW
276 wxDataObject* pDataObject
277)
0e320a79 278{
4fd899b6
DW
279 m_dataObject = pDataObject;
280 m_pDropTarget = new CIDropTarget(this);
281} // end of wxDropTarget::wxDropTarget
0e320a79
DW
282
283wxDropTarget::~wxDropTarget()
284{
4fd899b6
DW
285 Release();
286} // end of wxDropTarget::~wxDropTarget
0e320a79 287
4fd899b6 288bool wxDropTarget::GetData ()
6dddc146 289{
4fd899b6 290 wxDataFormat vFormat = GetSupportedFormat(m_pDropTarget->GetDataSource());
0e320a79 291
4fd899b6
DW
292 if (vFormat == wxDF_INVALID)
293 {
d0ee33f5 294 return false;
4fd899b6
DW
295 }
296 //
297 // Under OS/2 we already have the data via the attached DRAGITEM's
298 //
d0ee33f5 299 return true;
4fd899b6
DW
300} // end of wxDropTarget::GetData
301
302wxDataFormat wxDropTarget::GetSupportedFormat (
303 PDRAGINFO pDataSource
304) const
0e320a79 305{
4fd899b6
DW
306 PDRAGITEM pDragItem;
307 wxDataFormat vFormat;
308 wxDataFormat* pFormats;
309 ULONG ulFormats = m_dataObject->GetFormatCount(wxDataObject::Set);
310 ULONG ulItems = (ULONG)::DrgQueryDragitemCount(pDataSource);
311 ULONG i;
312 ULONG n;
313 wxString sMechanism;
314 wxString sFormat;
d0ee33f5 315 bool bValid = false;
0e320a79 316
4fd899b6
DW
317 pFormats = ulFormats == 1 ? &vFormat : new wxDataFormat[ulFormats];
318 m_dataObject->GetAllFormats( pFormats
319 ,wxDataObject::Set
320 );
321
322 for (n = 0; n < ulFormats; n++)
323 {
324 switch(pFormats[n].GetType())
325 {
326 case wxDF_TEXT:
327 case wxDF_FILENAME:
328 case wxDF_HTML:
0fba44b4
DW
329 sMechanism = _T("DRM_OS2FILE");
330 sFormat = _T("DRF_TEXT");
4fd899b6
DW
331 break;
332
333 case wxDF_OEMTEXT:
0fba44b4
DW
334 sMechanism = _T("DRM_OS2FILE");
335 sFormat = _T("DRF_OEMTEXT");
4fd899b6
DW
336 break;
337
338 case wxDF_BITMAP:
0fba44b4
DW
339 sMechanism = _T("DRM_OS2FILE");
340 sFormat = _T("DRF_BITMAP");
4fd899b6
DW
341 break;
342
343 case wxDF_METAFILE:
344 case wxDF_ENHMETAFILE:
0fba44b4
DW
345 sMechanism = _T("DRM_OS2FILE");
346 sFormat = _T("DRF_METAFILE");
4fd899b6
DW
347 break;
348
349 case wxDF_TIFF:
0fba44b4
DW
350 sMechanism = _T("DRM_OS2FILE");
351 sFormat = _T("DRF_TIFF");
4fd899b6
DW
352 break;
353
354 case wxDF_SYLK:
0fba44b4
DW
355 sMechanism = _T("DRM_OS2FILE");
356 sFormat = _T("DRF_SYLK");
4fd899b6
DW
357 break;
358
359 case wxDF_DIF:
0fba44b4
DW
360 sMechanism = _T("DRM_OS2FILE");
361 sFormat = _T("DRF_DIF");
4fd899b6
DW
362 break;
363
364 case wxDF_DIB:
0fba44b4
DW
365 sMechanism = _T("DRM_OS2FILE");
366 sFormat = _T("DRF_DIB");
4fd899b6
DW
367 break;
368
369 case wxDF_PALETTE:
370 case wxDF_PENDATA:
371 case wxDF_RIFF:
372 case wxDF_WAVE:
373 case wxDF_UNICODETEXT:
374 case wxDF_LOCALE:
0fba44b4
DW
375 sMechanism = _T("DRM_OS2FILE");
376 sFormat = _T("DRF_UNKNOWN");
4fd899b6
DW
377 break;
378
379 case wxDF_PRIVATE:
0fba44b4
DW
380 sMechanism = _T("DRM_OBJECT");
381 sFormat = _T("DRF_UNKNOWN");
4fd899b6
DW
382 break;
383 }
384 for (i = 0; i < ulItems; i++)
385 {
386 pDragItem = ::DrgQueryDragitemPtr(pDataSource, i);
0fba44b4 387 if (::DrgVerifyRMF(pDragItem, (PSZ)sMechanism.c_str(), (PSZ)sFormat.c_str()))
4fd899b6 388 {
d0ee33f5 389 bValid = true;
4fd899b6
DW
390 break;
391 }
392 }
393 if (bValid)
394 {
395 vFormat = pFormats[n];
396 break;
397 }
398 }
399 if (pFormats != &vFormat)
400 {
401 //
402 // Free memory if we allocated it
403 //
404 delete [] pFormats;
405 }
406 return (n < ulFormats ? vFormat : wxFormatInvalid);
407} // end of wxDropTarget::GetSupportedFormat
408
409bool wxDropTarget::IsAcceptedData (
410 PDRAGINFO pDataSource
411) const
0e320a79 412{
4fd899b6
DW
413 return (GetSupportedFormat(pDataSource) != wxDF_INVALID);
414} // end of wxDropTarget::IsAcceptedData
0e320a79 415
4fd899b6 416void wxDropTarget::Release ()
0e320a79 417{
4fd899b6
DW
418 m_pDropTarget->Free();
419} // end of wxDropTarget::Release
420
0e320a79 421
4fd899b6
DW
422wxDragResult wxDropTarget::OnData (
423 wxCoord WXUNUSED(vX)
424, wxCoord WXUNUSED(y)
425, wxDragResult WXUNUSED(vResult)
004fd0c8
DW
426)
427{
004fd0c8 428 return (wxDragResult)0;
4fd899b6 429} // end of wxDropTarget::OnData
004fd0c8 430
4fd899b6
DW
431bool wxDropTarget::OnDrop (
432 wxCoord WXUNUSED(x)
433, wxCoord WXUNUSED(y)
6dddc146
DW
434)
435{
d0ee33f5 436 return true;
4fd899b6 437} // end of wxDropTarget::OnDrop
0e320a79 438
0e320a79
DW
439//-------------------------------------------------------------------------
440// wxDropSource
441//-------------------------------------------------------------------------
442
4fd899b6 443wxDropSource::wxDropSource (
6dddc146
DW
444 wxWindow* pWin
445)
0e320a79 446{
4fd899b6
DW
447 Init();
448} // end of wxDropSource::wxDropSource
0e320a79 449
4fd899b6 450wxDropSource::wxDropSource (
6dddc146
DW
451 wxDataObject& rData
452, wxWindow* pWin
453)
0e320a79 454{
4fd899b6
DW
455 Init();
456 SetData(rData);
457} // end of wxDropSource::wxDropSource
0e320a79 458
4fd899b6 459wxDropSource::~wxDropSource ()
0e320a79 460{
4fd899b6
DW
461 ::DrgFreeDraginfo(m_pDragInfo);
462} // end of wxDropSource::~wxDropSource
0e320a79 463
4fd899b6 464wxDragResult wxDropSource::DoDragDrop (
2245b2b2 465 int WXUNUSED(flags)
6dddc146 466)
0e320a79 467{
4fd899b6
DW
468 //
469 // Need to specify drag items in derived classes that know their data types
470 // before calling DoDragDrop
471 //
472 if (::DrgDrag( m_pWindow->GetHWND()
473 ,m_pDragInfo
474 ,&m_vDragImage
475 ,m_ulItems
476 ,VK_BUTTON2
477 ,NULL
478 ) != NULLHANDLE)
479 {
480 switch(m_pDragInfo->usOperation)
481 {
482 case DO_COPY:
483 return wxDragCopy;
484
485 case DO_MOVE:
486 return wxDragCopy;
487
488 case DO_LINK:
489 return wxDragCopy;
490
491 default:
492 return wxDragNone;
493 }
494 }
6dddc146 495 return wxDragError;
4fd899b6 496} // end of wxDropSource::DoDragDrop
6dddc146 497
4fd899b6
DW
498bool wxDropSource::GiveFeedback (
499 wxDragResult eEffect
500)
0e320a79 501{
4fd899b6
DW
502 const wxCursor& rCursor = GetCursor(eEffect);
503
504 if (rCursor.Ok())
505 {
506 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)rCursor.GetHCURSOR());
507 m_vDragImage.hImage = (LHANDLE)rCursor.GetHCURSOR();
508 switch(eEffect)
509 {
510 case wxDragCopy:
511 m_pDragInfo->usOperation = DO_COPY;
512 break;
513
514 case wxDragMove:
515 m_pDragInfo->usOperation = DO_MOVE;
516 break;
517
518 case wxDragLink:
519 m_pDragInfo->usOperation = DO_LINK;
520 break;
9923c37d
DW
521
522 case wxDragNone:
523 case wxDragCancel:
524 case wxDragError:
525 break;
4fd899b6 526 }
d0ee33f5 527 return true;
4fd899b6
DW
528 }
529 else
530 {
d0ee33f5 531 return false;
4fd899b6
DW
532 }
533} // end of GuiAdvDnd_CDropSource::GiveFeedback
534
535void wxDropSource::Init ()
536{
537 m_pDragInfo = ::DrgAllocDraginfo(m_ulItems);
538
539 //
540 // Set a default drag image struct with what we know so far
541 //
542 m_vDragImage.cb = sizeof(DRAGIMAGE);
543 m_vDragImage.cptl = 0; // non-zero if fl is DRG_POLYGON
544 m_vDragImage.hImage = 0; // Set in GiveFeedback
545 m_vDragImage.sizlStretch.cx = 20L;
546 m_vDragImage.sizlStretch.cy = 20L;
547 m_vDragImage.fl = DRG_ICON | DRG_STRETCH;
548 m_vDragImage.cxOffset = 0;
549 m_vDragImage.cyOffset = 0;
550
551 HSTR hStrType = ::DrgAddStrHandle(DRT_UNKNOWN);
552 HSTR hStrRMF;
553 HSTR hStrContainer;
0fba44b4
DW
554 wxChar zFormats[128];
555 wxChar zContainer[128];
4fd899b6 556 USHORT uSize = GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat()) + 1;
0fba44b4 557 wxChar* pzBuffer = new wxChar[uSize];
4fd899b6
DW
558
559 memset(pzBuffer, '\0', GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat()));
560 pzBuffer[GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat())] = '\0';
561 GetDataObject()->GetDataHere( GetDataObject()->GetPreferredFormat()
562 ,(void*)pzBuffer
563 );
564
0fba44b4
DW
565 wxStrcpy(zFormats, _T("<DRM_OS2FILE, DRF_UNKNOWN>"));
566 wxStrcpy(zContainer, GetDataObject()->GetPreferredFormat().GetId());
4fd899b6 567
0fba44b4
DW
568 hStrRMF = ::DrgAddStrHandle((PSZ)zFormats);
569 hStrContainer = ::DrgAddStrHandle((PSZ)zContainer);
4fd899b6
DW
570
571 m_pDragItem = new DRAGITEM[m_ulItems];
55945915 572 for (ULONG i = 0; i < m_ulItems; i++)
4fd899b6
DW
573 {
574 m_pDragItem[i].hwndItem = m_pWindow->GetHWND();
575 m_pDragItem[i].hstrType = hStrType;
576 m_pDragItem[i].hstrRMF = hStrRMF;
577 m_pDragItem[i].hstrContainerName = hStrContainer;
578 m_pDragItem[i].fsControl = 0;
579 m_pDragItem[i].fsSupportedOps = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE;
0fba44b4 580 m_pDragItem[i].hstrSourceName = ::DrgAddStrHandle((PSZ)pzBuffer);
4fd899b6
DW
581 m_pDragItem[i].hstrTargetName = m_pDragItem[i].hstrSourceName;
582 m_pDragItem[i].ulItemID = i;
583 ::DrgSetDragitem( m_pDragInfo
584 ,&m_pDragItem[i]
585 ,sizeof(DRAGITEM)
586 ,0
587 );
588 }
589 delete [] pzBuffer;
590 delete [] m_pDragItem;
591} // end of wxDropSource::Init
0e320a79 592
7e99520b 593#endif //wxUSE_DRAG_AND_DROP