]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dnd.cpp
wxWinCE power build fixes.
[wxWidgets.git] / src / os2 / dnd.cpp
CommitLineData
0e320a79 1///////////////////////////////////////////////////////////////////////////////
cb7d7375 2// Name: src/os2/dnd.cpp
0e320a79 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
6670f564
WS
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#if wxUSE_DRAG_AND_DROP
16
670f9935
WS
17#include "wx/dnd.h"
18
19#ifndef WX_PRECOMP
20 #include "wx/app.h"
cdccdfab 21 #include "wx/window.h"
670f9935
WS
22#endif
23
0e320a79
DW
24#include "wx/gdicmn.h"
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
cb7d7375 447wxDropSource::wxDropSource ( wxWindow* WXUNUSED(pWin) )
0e320a79 448{
4fd899b6
DW
449 Init();
450} // end of wxDropSource::wxDropSource
0e320a79 451
cb7d7375 452wxDropSource::wxDropSource ( wxDataObject& rData, wxWindow* WXUNUSED(pWin) )
0e320a79 453{
4fd899b6
DW
454 Init();
455 SetData(rData);
456} // end of wxDropSource::wxDropSource
0e320a79 457
4fd899b6 458wxDropSource::~wxDropSource ()
0e320a79 459{
4fd899b6
DW
460 ::DrgFreeDraginfo(m_pDragInfo);
461} // end of wxDropSource::~wxDropSource
0e320a79 462
4fd899b6 463wxDragResult wxDropSource::DoDragDrop (
2245b2b2 464 int WXUNUSED(flags)
6dddc146 465)
0e320a79 466{
4fd899b6
DW
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 }
6dddc146 494 return wxDragError;
4fd899b6 495} // end of wxDropSource::DoDragDrop
6dddc146 496
4fd899b6
DW
497bool wxDropSource::GiveFeedback (
498 wxDragResult eEffect
499)
0e320a79 500{
4fd899b6
DW
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;
9923c37d
DW
520
521 case wxDragNone:
522 case wxDragCancel:
523 case wxDragError:
524 break;
4fd899b6 525 }
d0ee33f5 526 return true;
4fd899b6
DW
527 }
528 else
529 {
d0ee33f5 530 return false;
4fd899b6
DW
531 }
532} // end of GuiAdvDnd_CDropSource::GiveFeedback
533
534void wxDropSource::Init ()
535{
536 m_pDragInfo = ::DrgAllocDraginfo(m_ulItems);
537
538 //
539 // Set a default drag image struct with what we know so far
540 //
541 m_vDragImage.cb = sizeof(DRAGIMAGE);
542 m_vDragImage.cptl = 0; // non-zero if fl is DRG_POLYGON
543 m_vDragImage.hImage = 0; // Set in GiveFeedback
544 m_vDragImage.sizlStretch.cx = 20L;
545 m_vDragImage.sizlStretch.cy = 20L;
546 m_vDragImage.fl = DRG_ICON | DRG_STRETCH;
547 m_vDragImage.cxOffset = 0;
548 m_vDragImage.cyOffset = 0;
549
cb7d7375
WS
550 HSTR hStrType = ::DrgAddStrHandle(DRT_UNKNOWN);
551 HSTR hStrRMF;
552 HSTR hStrContainer;
553 wxChar zFormats[128];
554 wxChar zContainer[128];
555 USHORT uSize = (USHORT)(GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat()) + 1);
556 wxChar* pzBuffer = new wxChar[uSize];
4fd899b6
DW
557
558 memset(pzBuffer, '\0', GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat()));
559 pzBuffer[GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat())] = '\0';
560 GetDataObject()->GetDataHere( GetDataObject()->GetPreferredFormat()
561 ,(void*)pzBuffer
562 );
563
0fba44b4
DW
564 wxStrcpy(zFormats, _T("<DRM_OS2FILE, DRF_UNKNOWN>"));
565 wxStrcpy(zContainer, GetDataObject()->GetPreferredFormat().GetId());
4fd899b6 566
0fba44b4
DW
567 hStrRMF = ::DrgAddStrHandle((PSZ)zFormats);
568 hStrContainer = ::DrgAddStrHandle((PSZ)zContainer);
4fd899b6
DW
569
570 m_pDragItem = new DRAGITEM[m_ulItems];
55945915 571 for (ULONG i = 0; i < m_ulItems; i++)
4fd899b6
DW
572 {
573 m_pDragItem[i].hwndItem = m_pWindow->GetHWND();
574 m_pDragItem[i].hstrType = hStrType;
575 m_pDragItem[i].hstrRMF = hStrRMF;
576 m_pDragItem[i].hstrContainerName = hStrContainer;
577 m_pDragItem[i].fsControl = 0;
578 m_pDragItem[i].fsSupportedOps = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE;
0fba44b4 579 m_pDragItem[i].hstrSourceName = ::DrgAddStrHandle((PSZ)pzBuffer);
4fd899b6
DW
580 m_pDragItem[i].hstrTargetName = m_pDragItem[i].hstrSourceName;
581 m_pDragItem[i].ulItemID = i;
582 ::DrgSetDragitem( m_pDragInfo
583 ,&m_pDragItem[i]
584 ,sizeof(DRAGITEM)
585 ,0
586 );
587 }
588 delete [] pzBuffer;
589 delete [] m_pDragItem;
590} // end of wxDropSource::Init
0e320a79 591
7e99520b 592#endif //wxUSE_DRAG_AND_DROP