]> git.saurik.com Git - wxWidgets.git/blob - src/os2/dnd.cpp
SF bug 1327872
[wxWidgets.git] / src / os2 / dnd.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: dnd.cpp
3 // Purpose: wxDropTarget, wxDropSource, wxDataObject implementation
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/21/99
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 AUTHOR
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #if wxUSE_DRAG_AND_DROP
16
17 #include "wx/window.h"
18 #include "wx/app.h"
19 #include "wx/gdicmn.h"
20 #include "wx/dnd.h"
21
22 #define INCL_PM
23 #define INCL_DOS
24 #include <os2.h>
25
26 // ----------------------------------------------------------------------------
27 // global
28 // ----------------------------------------------------------------------------
29
30 /////////////////////////////////////////////////////////////////////////////
31 // Private functions
32 /////////////////////////////////////////////////////////////////////////////
33
34 #if 0
35 static 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
56 static 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
76 #endif
77
78 class CIDropTarget
79 {
80 public:
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
103 protected:
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
111 bool CIDropTarget::DragLeave()
112 {
113 //
114 // Remove the UI feedback
115 //
116 m_pTarget->OnLeave();
117
118 //
119 // Release the held object
120 //
121 Free();
122 return true;
123 } // end of CIDropTarget::DragLeave
124
125 MRESULT CIDropTarget::DragOver ()
126 {
127 char zBuffer[128];
128 ULONG ulBytes;
129 USHORT uOp = 0;
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 /////////////////////////////////////////////////////////////////////////////
195 MRESULT CIDropTarget::Drop ()
196 {
197 char zBuffer[128];
198 ULONG ulBytes;
199 USHORT uOp = 0;
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 {
252 wxDragResult eRc = wxDragNone;
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 }
262 //else: OnDrop() returned false, no need to copy data
263
264 //
265 // Release the held object
266 //
267 Free();
268 return (MRFROM2SHORT(uIndicator, uOp));
269 } // end of CIDropTarget::Drop
270
271 // ----------------------------------------------------------------------------
272 // wxDropTarget
273 // ----------------------------------------------------------------------------
274
275 wxDropTarget::wxDropTarget (
276 wxDataObject* pDataObject
277 )
278 {
279 m_dataObject = pDataObject;
280 m_pDropTarget = new CIDropTarget(this);
281 } // end of wxDropTarget::wxDropTarget
282
283 wxDropTarget::~wxDropTarget()
284 {
285 Release();
286 } // end of wxDropTarget::~wxDropTarget
287
288 bool wxDropTarget::GetData ()
289 {
290 wxDataFormat vFormat = GetSupportedFormat(m_pDropTarget->GetDataSource());
291
292 if (vFormat == wxDF_INVALID)
293 {
294 return false;
295 }
296 //
297 // Under OS/2 we already have the data via the attached DRAGITEM's
298 //
299 return true;
300 } // end of wxDropTarget::GetData
301
302 wxDataFormat wxDropTarget::GetSupportedFormat (
303 PDRAGINFO pDataSource
304 ) const
305 {
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;
315 bool bValid = false;
316
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:
329 sMechanism = _T("DRM_OS2FILE");
330 sFormat = _T("DRF_TEXT");
331 break;
332
333 case wxDF_OEMTEXT:
334 sMechanism = _T("DRM_OS2FILE");
335 sFormat = _T("DRF_OEMTEXT");
336 break;
337
338 case wxDF_BITMAP:
339 sMechanism = _T("DRM_OS2FILE");
340 sFormat = _T("DRF_BITMAP");
341 break;
342
343 case wxDF_METAFILE:
344 case wxDF_ENHMETAFILE:
345 sMechanism = _T("DRM_OS2FILE");
346 sFormat = _T("DRF_METAFILE");
347 break;
348
349 case wxDF_TIFF:
350 sMechanism = _T("DRM_OS2FILE");
351 sFormat = _T("DRF_TIFF");
352 break;
353
354 case wxDF_SYLK:
355 sMechanism = _T("DRM_OS2FILE");
356 sFormat = _T("DRF_SYLK");
357 break;
358
359 case wxDF_DIF:
360 sMechanism = _T("DRM_OS2FILE");
361 sFormat = _T("DRF_DIF");
362 break;
363
364 case wxDF_DIB:
365 sMechanism = _T("DRM_OS2FILE");
366 sFormat = _T("DRF_DIB");
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:
375 sMechanism = _T("DRM_OS2FILE");
376 sFormat = _T("DRF_UNKNOWN");
377 break;
378
379 case wxDF_PRIVATE:
380 sMechanism = _T("DRM_OBJECT");
381 sFormat = _T("DRF_UNKNOWN");
382 break;
383 }
384 for (i = 0; i < ulItems; i++)
385 {
386 pDragItem = ::DrgQueryDragitemPtr(pDataSource, i);
387 if (::DrgVerifyRMF(pDragItem, (PSZ)sMechanism.c_str(), (PSZ)sFormat.c_str()))
388 {
389 bValid = true;
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
409 bool wxDropTarget::IsAcceptedData (
410 PDRAGINFO pDataSource
411 ) const
412 {
413 return (GetSupportedFormat(pDataSource) != wxDF_INVALID);
414 } // end of wxDropTarget::IsAcceptedData
415
416 void wxDropTarget::Release ()
417 {
418 m_pDropTarget->Free();
419 } // end of wxDropTarget::Release
420
421
422 wxDragResult wxDropTarget::OnData (
423 wxCoord WXUNUSED(vX)
424 , wxCoord WXUNUSED(y)
425 , wxDragResult WXUNUSED(vResult)
426 )
427 {
428 return (wxDragResult)0;
429 } // end of wxDropTarget::OnData
430
431 bool wxDropTarget::OnDrop (
432 wxCoord WXUNUSED(x)
433 , wxCoord WXUNUSED(y)
434 )
435 {
436 return true;
437 } // end of wxDropTarget::OnDrop
438
439 //-------------------------------------------------------------------------
440 // wxDropSource
441 //-------------------------------------------------------------------------
442
443 wxDropSource::wxDropSource (
444 wxWindow* pWin
445 )
446 {
447 Init();
448 } // end of wxDropSource::wxDropSource
449
450 wxDropSource::wxDropSource (
451 wxDataObject& rData
452 , wxWindow* pWin
453 )
454 {
455 Init();
456 SetData(rData);
457 } // end of wxDropSource::wxDropSource
458
459 wxDropSource::~wxDropSource ()
460 {
461 ::DrgFreeDraginfo(m_pDragInfo);
462 } // end of wxDropSource::~wxDropSource
463
464 wxDragResult wxDropSource::DoDragDrop (
465 int WXUNUSED(flags)
466 )
467 {
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 }
495 return wxDragError;
496 } // end of wxDropSource::DoDragDrop
497
498 bool wxDropSource::GiveFeedback (
499 wxDragResult eEffect
500 )
501 {
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;
521
522 case wxDragNone:
523 case wxDragCancel:
524 case wxDragError:
525 break;
526 }
527 return true;
528 }
529 else
530 {
531 return false;
532 }
533 } // end of GuiAdvDnd_CDropSource::GiveFeedback
534
535 void 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;
554 wxChar zFormats[128];
555 wxChar zContainer[128];
556 USHORT uSize = GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat()) + 1;
557 wxChar* pzBuffer = new wxChar[uSize];
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
565 wxStrcpy(zFormats, _T("<DRM_OS2FILE, DRF_UNKNOWN>"));
566 wxStrcpy(zContainer, GetDataObject()->GetPreferredFormat().GetId());
567
568 hStrRMF = ::DrgAddStrHandle((PSZ)zFormats);
569 hStrContainer = ::DrgAddStrHandle((PSZ)zContainer);
570
571 m_pDragItem = new DRAGITEM[m_ulItems];
572 for (ULONG i = 0; i < m_ulItems; i++)
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;
580 m_pDragItem[i].hstrSourceName = ::DrgAddStrHandle((PSZ)pzBuffer);
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
592
593 #endif //wxUSE_DRAG_AND_DROP