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