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