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