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