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