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