]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dnd.cpp
Deallocate wxThreadSpecificInfo when wxThread ends.
[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 7// Copyright: (c) 1998 AUTHOR
65571936 8// Licence: wxWindows licence
0e320a79
DW
9///////////////////////////////////////////////////////////////////////////////
10
6670f564
WS
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#if wxUSE_DRAG_AND_DROP
15
670f9935
WS
16#include "wx/dnd.h"
17
18#ifndef WX_PRECOMP
19 #include "wx/app.h"
cdccdfab 20 #include "wx/window.h"
dd05139a 21 #include "wx/gdicmn.h"
670f9935
WS
22#endif
23
55945915
SN
24#define INCL_PM
25#define INCL_DOS
26#include <os2.h>
27
0e320a79
DW
28// ----------------------------------------------------------------------------
29// global
30// ----------------------------------------------------------------------------
31
4fd899b6
DW
32/////////////////////////////////////////////////////////////////////////////
33// Private functions
34/////////////////////////////////////////////////////////////////////////////
35
9923c37d 36#if 0
4fd899b6
DW
37static 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
58static 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
9923c37d 78#endif
4fd899b6
DW
79
80class CIDropTarget
81{
82public:
83 CIDropTarget(wxDropTarget* pTarget)
84 {
85 m_pTarget = pTarget;
86 m_pDragItem = NULL;
87 }
88 virtual ~CIDropTarget() { }
89
90 //
91 // Accessors for CDropTarget
92 //
93 void Free(void) { ::DrgFreeDraginfo(m_pDragInfo); }
94 PDRAGINFO GetDataSource(void) { return m_pDragInfo; }
95 void SetDataSource(PDRAGINFO pDragInfo) { m_pDragInfo = pDragInfo; }
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
105protected:
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
113bool CIDropTarget::DragLeave()
114{
115 //
116 // Remove the UI feedback
117 //
118 m_pTarget->OnLeave();
119
120 //
121 // Release the held object
122 //
123 Free();
d0ee33f5 124 return true;
4fd899b6
DW
125} // end of CIDropTarget::DragLeave
126
127MRESULT CIDropTarget::DragOver ()
128{
129 char zBuffer[128];
130 ULONG ulBytes;
322d45dd 131 USHORT uOp = 0;
4fd899b6
DW
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/////////////////////////////////////////////////////////////////////////////
197MRESULT CIDropTarget::Drop ()
198{
199 char zBuffer[128];
200 ULONG ulBytes;
322d45dd 201 USHORT uOp = 0;
4fd899b6
DW
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 {
d0ee33f5 254 wxDragResult eRc = wxDragNone;
4fd899b6
DW
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 }
d0ee33f5 264 //else: OnDrop() returned false, no need to copy data
4fd899b6
DW
265
266 //
267 // Release the held object
268 //
269 Free();
270 return (MRFROM2SHORT(uIndicator, uOp));
271} // end of CIDropTarget::Drop
272
0e320a79
DW
273// ----------------------------------------------------------------------------
274// wxDropTarget
275// ----------------------------------------------------------------------------
276
4fd899b6 277wxDropTarget::wxDropTarget (
6dddc146
DW
278 wxDataObject* pDataObject
279)
0e320a79 280{
4fd899b6
DW
281 m_dataObject = pDataObject;
282 m_pDropTarget = new CIDropTarget(this);
283} // end of wxDropTarget::wxDropTarget
0e320a79
DW
284
285wxDropTarget::~wxDropTarget()
286{
4fd899b6
DW
287 Release();
288} // end of wxDropTarget::~wxDropTarget
0e320a79 289
4fd899b6 290bool wxDropTarget::GetData ()
6dddc146 291{
4fd899b6 292 wxDataFormat vFormat = GetSupportedFormat(m_pDropTarget->GetDataSource());
0e320a79 293
4fd899b6
DW
294 if (vFormat == wxDF_INVALID)
295 {
d0ee33f5 296 return false;
4fd899b6
DW
297 }
298 //
299 // Under OS/2 we already have the data via the attached DRAGITEM's
300 //
d0ee33f5 301 return true;
4fd899b6
DW
302} // end of wxDropTarget::GetData
303
304wxDataFormat wxDropTarget::GetSupportedFormat (
305 PDRAGINFO pDataSource
306) const
0e320a79 307{
4fd899b6
DW
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;
d0ee33f5 317 bool bValid = false;
0e320a79 318
4fd899b6
DW
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:
9a83f860
VZ
331 sMechanism = wxT("DRM_OS2FILE");
332 sFormat = wxT("DRF_TEXT");
4fd899b6
DW
333 break;
334
335 case wxDF_OEMTEXT:
9a83f860
VZ
336 sMechanism = wxT("DRM_OS2FILE");
337 sFormat = wxT("DRF_OEMTEXT");
4fd899b6
DW
338 break;
339
340 case wxDF_BITMAP:
9a83f860
VZ
341 sMechanism = wxT("DRM_OS2FILE");
342 sFormat = wxT("DRF_BITMAP");
4fd899b6
DW
343 break;
344
345 case wxDF_METAFILE:
346 case wxDF_ENHMETAFILE:
9a83f860
VZ
347 sMechanism = wxT("DRM_OS2FILE");
348 sFormat = wxT("DRF_METAFILE");
4fd899b6
DW
349 break;
350
351 case wxDF_TIFF:
9a83f860
VZ
352 sMechanism = wxT("DRM_OS2FILE");
353 sFormat = wxT("DRF_TIFF");
4fd899b6
DW
354 break;
355
356 case wxDF_SYLK:
9a83f860
VZ
357 sMechanism = wxT("DRM_OS2FILE");
358 sFormat = wxT("DRF_SYLK");
4fd899b6
DW
359 break;
360
361 case wxDF_DIF:
9a83f860
VZ
362 sMechanism = wxT("DRM_OS2FILE");
363 sFormat = wxT("DRF_DIF");
4fd899b6
DW
364 break;
365
366 case wxDF_DIB:
9a83f860
VZ
367 sMechanism = wxT("DRM_OS2FILE");
368 sFormat = wxT("DRF_DIB");
4fd899b6
DW
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:
9a83f860
VZ
377 sMechanism = wxT("DRM_OS2FILE");
378 sFormat = wxT("DRF_UNKNOWN");
4fd899b6
DW
379 break;
380
381 case wxDF_PRIVATE:
9a83f860
VZ
382 sMechanism = wxT("DRM_OBJECT");
383 sFormat = wxT("DRF_UNKNOWN");
4fd899b6
DW
384 break;
385 }
386 for (i = 0; i < ulItems; i++)
387 {
388 pDragItem = ::DrgQueryDragitemPtr(pDataSource, i);
f450b5cf 389 if (::DrgVerifyRMF(pDragItem, sMechanism.c_str(), sFormat.c_str()))
4fd899b6 390 {
d0ee33f5 391 bValid = true;
4fd899b6
DW
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
411bool wxDropTarget::IsAcceptedData (
412 PDRAGINFO pDataSource
413) const
0e320a79 414{
4fd899b6
DW
415 return (GetSupportedFormat(pDataSource) != wxDF_INVALID);
416} // end of wxDropTarget::IsAcceptedData
0e320a79 417
4fd899b6 418void wxDropTarget::Release ()
0e320a79 419{
4fd899b6
DW
420 m_pDropTarget->Free();
421} // end of wxDropTarget::Release
422
0e320a79 423
4fd899b6
DW
424wxDragResult wxDropTarget::OnData (
425 wxCoord WXUNUSED(vX)
426, wxCoord WXUNUSED(y)
427, wxDragResult WXUNUSED(vResult)
004fd0c8
DW
428)
429{
004fd0c8 430 return (wxDragResult)0;
4fd899b6 431} // end of wxDropTarget::OnData
004fd0c8 432
4fd899b6
DW
433bool wxDropTarget::OnDrop (
434 wxCoord WXUNUSED(x)
435, wxCoord WXUNUSED(y)
6dddc146
DW
436)
437{
d0ee33f5 438 return true;
4fd899b6 439} // end of wxDropTarget::OnDrop
0e320a79 440
0e320a79
DW
441//-------------------------------------------------------------------------
442// wxDropSource
443//-------------------------------------------------------------------------
444
cb7d7375 445wxDropSource::wxDropSource ( wxWindow* WXUNUSED(pWin) )
0e320a79 446{
4fd899b6
DW
447 Init();
448} // end of wxDropSource::wxDropSource
0e320a79 449
cb7d7375 450wxDropSource::wxDropSource ( wxDataObject& rData, wxWindow* WXUNUSED(pWin) )
0e320a79 451{
4fd899b6
DW
452 Init();
453 SetData(rData);
454} // end of wxDropSource::wxDropSource
0e320a79 455
4fd899b6 456wxDropSource::~wxDropSource ()
0e320a79 457{
4fd899b6
DW
458 ::DrgFreeDraginfo(m_pDragInfo);
459} // end of wxDropSource::~wxDropSource
0e320a79 460
4fd899b6 461wxDragResult wxDropSource::DoDragDrop (
2245b2b2 462 int WXUNUSED(flags)
6dddc146 463)
0e320a79 464{
4fd899b6
DW
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 }
6dddc146 492 return wxDragError;
4fd899b6 493} // end of wxDropSource::DoDragDrop
6dddc146 494
4fd899b6
DW
495bool wxDropSource::GiveFeedback (
496 wxDragResult eEffect
497)
0e320a79 498{
4fd899b6
DW
499 const wxCursor& rCursor = GetCursor(eEffect);
500
a1b806b9 501 if (rCursor.IsOk())
4fd899b6
DW
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;
9923c37d
DW
518
519 case wxDragNone:
520 case wxDragCancel:
521 case wxDragError:
522 break;
4fd899b6 523 }
d0ee33f5 524 return true;
4fd899b6
DW
525 }
526 else
527 {
d0ee33f5 528 return false;
4fd899b6
DW
529 }
530} // end of GuiAdvDnd_CDropSource::GiveFeedback
531
532void 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
cb7d7375
WS
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];
4fd899b6
DW
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
9a83f860 562 wxStrcpy(zFormats, wxT("<DRM_OS2FILE, DRF_UNKNOWN>"));
0fba44b4 563 wxStrcpy(zContainer, GetDataObject()->GetPreferredFormat().GetId());
4fd899b6 564
0fba44b4
DW
565 hStrRMF = ::DrgAddStrHandle((PSZ)zFormats);
566 hStrContainer = ::DrgAddStrHandle((PSZ)zContainer);
4fd899b6
DW
567
568 m_pDragItem = new DRAGITEM[m_ulItems];
55945915 569 for (ULONG i = 0; i < m_ulItems; i++)
4fd899b6
DW
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;
0fba44b4 577 m_pDragItem[i].hstrSourceName = ::DrgAddStrHandle((PSZ)pzBuffer);
4fd899b6
DW
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
0e320a79 589
7e99520b 590#endif //wxUSE_DRAG_AND_DROP