]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/dnd.cpp
Wouldn't compile on Intel/universal binary with those tests, and
[wxWidgets.git] / src / os2 / dnd.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/os2/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// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#if wxUSE_DRAG_AND_DROP
16
17#include "wx/dnd.h"
18
19#ifndef WX_PRECOMP
20 #include "wx/app.h"
21 #include "wx/window.h"
22#endif
23
24#include "wx/gdicmn.h"
25
26#define INCL_PM
27#define INCL_DOS
28#include <os2.h>
29
30// ----------------------------------------------------------------------------
31// global
32// ----------------------------------------------------------------------------
33
34/////////////////////////////////////////////////////////////////////////////
35// Private functions
36/////////////////////////////////////////////////////////////////////////////
37
38#if 0
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
80#endif
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();
126 return true;
127} // end of CIDropTarget::DragLeave
128
129MRESULT CIDropTarget::DragOver ()
130{
131 char zBuffer[128];
132 ULONG ulBytes;
133 USHORT uOp = 0;
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;
203 USHORT uOp = 0;
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 {
256 wxDragResult eRc = wxDragNone;
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 }
266 //else: OnDrop() returned false, no need to copy data
267
268 //
269 // Release the held object
270 //
271 Free();
272 return (MRFROM2SHORT(uIndicator, uOp));
273} // end of CIDropTarget::Drop
274
275// ----------------------------------------------------------------------------
276// wxDropTarget
277// ----------------------------------------------------------------------------
278
279wxDropTarget::wxDropTarget (
280 wxDataObject* pDataObject
281)
282{
283 m_dataObject = pDataObject;
284 m_pDropTarget = new CIDropTarget(this);
285} // end of wxDropTarget::wxDropTarget
286
287wxDropTarget::~wxDropTarget()
288{
289 Release();
290} // end of wxDropTarget::~wxDropTarget
291
292bool wxDropTarget::GetData ()
293{
294 wxDataFormat vFormat = GetSupportedFormat(m_pDropTarget->GetDataSource());
295
296 if (vFormat == wxDF_INVALID)
297 {
298 return false;
299 }
300 //
301 // Under OS/2 we already have the data via the attached DRAGITEM's
302 //
303 return true;
304} // end of wxDropTarget::GetData
305
306wxDataFormat wxDropTarget::GetSupportedFormat (
307 PDRAGINFO pDataSource
308) const
309{
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;
319 bool bValid = false;
320
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:
333 sMechanism = _T("DRM_OS2FILE");
334 sFormat = _T("DRF_TEXT");
335 break;
336
337 case wxDF_OEMTEXT:
338 sMechanism = _T("DRM_OS2FILE");
339 sFormat = _T("DRF_OEMTEXT");
340 break;
341
342 case wxDF_BITMAP:
343 sMechanism = _T("DRM_OS2FILE");
344 sFormat = _T("DRF_BITMAP");
345 break;
346
347 case wxDF_METAFILE:
348 case wxDF_ENHMETAFILE:
349 sMechanism = _T("DRM_OS2FILE");
350 sFormat = _T("DRF_METAFILE");
351 break;
352
353 case wxDF_TIFF:
354 sMechanism = _T("DRM_OS2FILE");
355 sFormat = _T("DRF_TIFF");
356 break;
357
358 case wxDF_SYLK:
359 sMechanism = _T("DRM_OS2FILE");
360 sFormat = _T("DRF_SYLK");
361 break;
362
363 case wxDF_DIF:
364 sMechanism = _T("DRM_OS2FILE");
365 sFormat = _T("DRF_DIF");
366 break;
367
368 case wxDF_DIB:
369 sMechanism = _T("DRM_OS2FILE");
370 sFormat = _T("DRF_DIB");
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:
379 sMechanism = _T("DRM_OS2FILE");
380 sFormat = _T("DRF_UNKNOWN");
381 break;
382
383 case wxDF_PRIVATE:
384 sMechanism = _T("DRM_OBJECT");
385 sFormat = _T("DRF_UNKNOWN");
386 break;
387 }
388 for (i = 0; i < ulItems; i++)
389 {
390 pDragItem = ::DrgQueryDragitemPtr(pDataSource, i);
391 if (::DrgVerifyRMF(pDragItem, (PSZ)sMechanism.c_str(), (PSZ)sFormat.c_str()))
392 {
393 bValid = true;
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
416{
417 return (GetSupportedFormat(pDataSource) != wxDF_INVALID);
418} // end of wxDropTarget::IsAcceptedData
419
420void wxDropTarget::Release ()
421{
422 m_pDropTarget->Free();
423} // end of wxDropTarget::Release
424
425
426wxDragResult wxDropTarget::OnData (
427 wxCoord WXUNUSED(vX)
428, wxCoord WXUNUSED(y)
429, wxDragResult WXUNUSED(vResult)
430)
431{
432 return (wxDragResult)0;
433} // end of wxDropTarget::OnData
434
435bool wxDropTarget::OnDrop (
436 wxCoord WXUNUSED(x)
437, wxCoord WXUNUSED(y)
438)
439{
440 return true;
441} // end of wxDropTarget::OnDrop
442
443//-------------------------------------------------------------------------
444// wxDropSource
445//-------------------------------------------------------------------------
446
447wxDropSource::wxDropSource ( wxWindow* WXUNUSED(pWin) )
448{
449 Init();
450} // end of wxDropSource::wxDropSource
451
452wxDropSource::wxDropSource ( wxDataObject& rData, wxWindow* WXUNUSED(pWin) )
453{
454 Init();
455 SetData(rData);
456} // end of wxDropSource::wxDropSource
457
458wxDropSource::~wxDropSource ()
459{
460 ::DrgFreeDraginfo(m_pDragInfo);
461} // end of wxDropSource::~wxDropSource
462
463wxDragResult 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
497bool 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 case wxDragNone:
522 case wxDragCancel:
523 case wxDragError:
524 break;
525 }
526 return true;
527 }
528 else
529 {
530 return false;
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
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];
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
564 wxStrcpy(zFormats, _T("<DRM_OS2FILE, DRF_UNKNOWN>"));
565 wxStrcpy(zContainer, GetDataObject()->GetPreferredFormat().GetId());
566
567 hStrRMF = ::DrgAddStrHandle((PSZ)zFormats);
568 hStrContainer = ::DrgAddStrHandle((PSZ)zContainer);
569
570 m_pDragItem = new DRAGITEM[m_ulItems];
571 for (ULONG i = 0; i < m_ulItems; i++)
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;
579 m_pDragItem[i].hstrSourceName = ::DrgAddStrHandle((PSZ)pzBuffer);
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
591
592#endif //wxUSE_DRAG_AND_DROP