]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dnd.cpp
added wxMOTIF_STR() macro casting away string literal constness for use with Motif...
[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
12#ifdef __GNUG__
13#pragma implementation "dnd.h"
14#endif
15
6670f564
WS
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#if wxUSE_DRAG_AND_DROP
20
0e320a79
DW
21#include "wx/window.h"
22#include "wx/app.h"
23#include "wx/gdicmn.h"
e6ebb514 24#include "wx/dnd.h"
0e320a79 25
55945915
SN
26#define INCL_PM
27#define INCL_DOS
28#include <os2.h>
29
0e320a79
DW
30// ----------------------------------------------------------------------------
31// global
32// ----------------------------------------------------------------------------
33
4fd899b6
DW
34/////////////////////////////////////////////////////////////////////////////
35// Private functions
36/////////////////////////////////////////////////////////////////////////////
37
9923c37d 38#if 0
4fd899b6
DW
39static 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
60static 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
9923c37d 80#endif
4fd899b6
DW
81
82class CIDropTarget
83{
84public:
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
107protected:
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
115bool CIDropTarget::DragLeave()
116{
117 //
118 // Remove the UI feedback
119 //
120 m_pTarget->OnLeave();
121
122 //
123 // Release the held object
124 //
125 Free();
d0ee33f5 126 return true;
4fd899b6
DW
127} // end of CIDropTarget::DragLeave
128
129MRESULT CIDropTarget::DragOver ()
130{
131 char zBuffer[128];
132 ULONG ulBytes;
322d45dd 133 USHORT uOp = 0;
4fd899b6
DW
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/////////////////////////////////////////////////////////////////////////////
199MRESULT CIDropTarget::Drop ()
200{
201 char zBuffer[128];
202 ULONG ulBytes;
322d45dd 203 USHORT uOp = 0;
4fd899b6
DW
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 {
d0ee33f5 256 wxDragResult eRc = wxDragNone;
4fd899b6
DW
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 }
d0ee33f5 266 //else: OnDrop() returned false, no need to copy data
4fd899b6
DW
267
268 //
269 // Release the held object
270 //
271 Free();
272 return (MRFROM2SHORT(uIndicator, uOp));
273} // end of CIDropTarget::Drop
274
0e320a79
DW
275// ----------------------------------------------------------------------------
276// wxDropTarget
277// ----------------------------------------------------------------------------
278
4fd899b6 279wxDropTarget::wxDropTarget (
6dddc146
DW
280 wxDataObject* pDataObject
281)
0e320a79 282{
4fd899b6
DW
283 m_dataObject = pDataObject;
284 m_pDropTarget = new CIDropTarget(this);
285} // end of wxDropTarget::wxDropTarget
0e320a79
DW
286
287wxDropTarget::~wxDropTarget()
288{
4fd899b6
DW
289 Release();
290} // end of wxDropTarget::~wxDropTarget
0e320a79 291
4fd899b6 292bool wxDropTarget::GetData ()
6dddc146 293{
4fd899b6 294 wxDataFormat vFormat = GetSupportedFormat(m_pDropTarget->GetDataSource());
0e320a79 295
4fd899b6
DW
296 if (vFormat == wxDF_INVALID)
297 {
d0ee33f5 298 return false;
4fd899b6
DW
299 }
300 //
301 // Under OS/2 we already have the data via the attached DRAGITEM's
302 //
d0ee33f5 303 return true;
4fd899b6
DW
304} // end of wxDropTarget::GetData
305
306wxDataFormat wxDropTarget::GetSupportedFormat (
307 PDRAGINFO pDataSource
308) const
0e320a79 309{
4fd899b6
DW
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;
d0ee33f5 319 bool bValid = false;
0e320a79 320
4fd899b6
DW
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:
0fba44b4
DW
333 sMechanism = _T("DRM_OS2FILE");
334 sFormat = _T("DRF_TEXT");
4fd899b6
DW
335 break;
336
337 case wxDF_OEMTEXT:
0fba44b4
DW
338 sMechanism = _T("DRM_OS2FILE");
339 sFormat = _T("DRF_OEMTEXT");
4fd899b6
DW
340 break;
341
342 case wxDF_BITMAP:
0fba44b4
DW
343 sMechanism = _T("DRM_OS2FILE");
344 sFormat = _T("DRF_BITMAP");
4fd899b6
DW
345 break;
346
347 case wxDF_METAFILE:
348 case wxDF_ENHMETAFILE:
0fba44b4
DW
349 sMechanism = _T("DRM_OS2FILE");
350 sFormat = _T("DRF_METAFILE");
4fd899b6
DW
351 break;
352
353 case wxDF_TIFF:
0fba44b4
DW
354 sMechanism = _T("DRM_OS2FILE");
355 sFormat = _T("DRF_TIFF");
4fd899b6
DW
356 break;
357
358 case wxDF_SYLK:
0fba44b4
DW
359 sMechanism = _T("DRM_OS2FILE");
360 sFormat = _T("DRF_SYLK");
4fd899b6
DW
361 break;
362
363 case wxDF_DIF:
0fba44b4
DW
364 sMechanism = _T("DRM_OS2FILE");
365 sFormat = _T("DRF_DIF");
4fd899b6
DW
366 break;
367
368 case wxDF_DIB:
0fba44b4
DW
369 sMechanism = _T("DRM_OS2FILE");
370 sFormat = _T("DRF_DIB");
4fd899b6
DW
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:
0fba44b4
DW
379 sMechanism = _T("DRM_OS2FILE");
380 sFormat = _T("DRF_UNKNOWN");
4fd899b6
DW
381 break;
382
383 case wxDF_PRIVATE:
0fba44b4
DW
384 sMechanism = _T("DRM_OBJECT");
385 sFormat = _T("DRF_UNKNOWN");
4fd899b6
DW
386 break;
387 }
388 for (i = 0; i < ulItems; i++)
389 {
390 pDragItem = ::DrgQueryDragitemPtr(pDataSource, i);
0fba44b4 391 if (::DrgVerifyRMF(pDragItem, (PSZ)sMechanism.c_str(), (PSZ)sFormat.c_str()))
4fd899b6 392 {
d0ee33f5 393 bValid = true;
4fd899b6
DW
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
413bool wxDropTarget::IsAcceptedData (
414 PDRAGINFO pDataSource
415) const
0e320a79 416{
4fd899b6
DW
417 return (GetSupportedFormat(pDataSource) != wxDF_INVALID);
418} // end of wxDropTarget::IsAcceptedData
0e320a79 419
4fd899b6 420void wxDropTarget::Release ()
0e320a79 421{
4fd899b6
DW
422 m_pDropTarget->Free();
423} // end of wxDropTarget::Release
424
0e320a79 425
4fd899b6
DW
426wxDragResult wxDropTarget::OnData (
427 wxCoord WXUNUSED(vX)
428, wxCoord WXUNUSED(y)
429, wxDragResult WXUNUSED(vResult)
004fd0c8
DW
430)
431{
004fd0c8 432 return (wxDragResult)0;
4fd899b6 433} // end of wxDropTarget::OnData
004fd0c8 434
4fd899b6
DW
435bool wxDropTarget::OnDrop (
436 wxCoord WXUNUSED(x)
437, wxCoord WXUNUSED(y)
6dddc146
DW
438)
439{
d0ee33f5 440 return true;
4fd899b6 441} // end of wxDropTarget::OnDrop
0e320a79 442
0e320a79
DW
443//-------------------------------------------------------------------------
444// wxDropSource
445//-------------------------------------------------------------------------
446
4fd899b6 447wxDropSource::wxDropSource (
6dddc146
DW
448 wxWindow* pWin
449)
0e320a79 450{
4fd899b6
DW
451 Init();
452} // end of wxDropSource::wxDropSource
0e320a79 453
4fd899b6 454wxDropSource::wxDropSource (
6dddc146
DW
455 wxDataObject& rData
456, wxWindow* pWin
457)
0e320a79 458{
4fd899b6
DW
459 Init();
460 SetData(rData);
461} // end of wxDropSource::wxDropSource
0e320a79 462
4fd899b6 463wxDropSource::~wxDropSource ()
0e320a79 464{
4fd899b6
DW
465 ::DrgFreeDraginfo(m_pDragInfo);
466} // end of wxDropSource::~wxDropSource
0e320a79 467
4fd899b6 468wxDragResult wxDropSource::DoDragDrop (
2245b2b2 469 int WXUNUSED(flags)
6dddc146 470)
0e320a79 471{
4fd899b6
DW
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 }
6dddc146 499 return wxDragError;
4fd899b6 500} // end of wxDropSource::DoDragDrop
6dddc146 501
4fd899b6
DW
502bool wxDropSource::GiveFeedback (
503 wxDragResult eEffect
504)
0e320a79 505{
4fd899b6
DW
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;
9923c37d
DW
525
526 case wxDragNone:
527 case wxDragCancel:
528 case wxDragError:
529 break;
4fd899b6 530 }
d0ee33f5 531 return true;
4fd899b6
DW
532 }
533 else
534 {
d0ee33f5 535 return false;
4fd899b6
DW
536 }
537} // end of GuiAdvDnd_CDropSource::GiveFeedback
538
539void 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;
0fba44b4
DW
558 wxChar zFormats[128];
559 wxChar zContainer[128];
4fd899b6 560 USHORT uSize = GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat()) + 1;
0fba44b4 561 wxChar* pzBuffer = new wxChar[uSize];
4fd899b6
DW
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
0fba44b4
DW
569 wxStrcpy(zFormats, _T("<DRM_OS2FILE, DRF_UNKNOWN>"));
570 wxStrcpy(zContainer, GetDataObject()->GetPreferredFormat().GetId());
4fd899b6 571
0fba44b4
DW
572 hStrRMF = ::DrgAddStrHandle((PSZ)zFormats);
573 hStrContainer = ::DrgAddStrHandle((PSZ)zContainer);
4fd899b6
DW
574
575 m_pDragItem = new DRAGITEM[m_ulItems];
55945915 576 for (ULONG i = 0; i < m_ulItems; i++)
4fd899b6
DW
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;
0fba44b4 584 m_pDragItem[i].hstrSourceName = ::DrgAddStrHandle((PSZ)pzBuffer);
4fd899b6
DW
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
0e320a79 596
7e99520b 597#endif //wxUSE_DRAG_AND_DROP