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