]> git.saurik.com Git - wxWidgets.git/blob - src/os2/dnd.cpp
Set MONOLITHIC for posix platforms based on the output of wx-config,
[wxWidgets.git] / src / os2 / dnd.cpp
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
39 static 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
60 static 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
82 class CIDropTarget
83 {
84 public:
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
107 protected:
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
115 bool 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
129 MRESULT 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 /////////////////////////////////////////////////////////////////////////////
199 MRESULT 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
279 wxDropTarget::wxDropTarget (
280 wxDataObject* pDataObject
281 )
282 {
283 m_dataObject = pDataObject;
284 m_pDropTarget = new CIDropTarget(this);
285 } // end of wxDropTarget::wxDropTarget
286
287 wxDropTarget::~wxDropTarget()
288 {
289 Release();
290 } // end of wxDropTarget::~wxDropTarget
291
292 bool 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
306 wxDataFormat 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
413 bool wxDropTarget::IsAcceptedData (
414 PDRAGINFO pDataSource
415 ) const
416 {
417 return (GetSupportedFormat(pDataSource) != wxDF_INVALID);
418 } // end of wxDropTarget::IsAcceptedData
419
420 void wxDropTarget::Release ()
421 {
422 m_pDropTarget->Free();
423 } // end of wxDropTarget::Release
424
425
426 wxDragResult 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
435 bool 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
447 wxDropSource::wxDropSource ( wxWindow* WXUNUSED(pWin) )
448 {
449 Init();
450 } // end of wxDropSource::wxDropSource
451
452 wxDropSource::wxDropSource ( wxDataObject& rData, wxWindow* WXUNUSED(pWin) )
453 {
454 Init();
455 SetData(rData);
456 } // end of wxDropSource::wxDropSource
457
458 wxDropSource::~wxDropSource ()
459 {
460 ::DrgFreeDraginfo(m_pDragInfo);
461 } // end of wxDropSource::~wxDropSource
462
463 wxDragResult 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
497 bool 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
534 void 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