1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <com/sun/star/embed/XEmbedObjectClipboardCreator.hpp> 21 #include <com/sun/star/embed/Aspects.hpp> 22 #include <com/sun/star/embed/MSOLEObjectSystemCreator.hpp> 23 24 #include <svx/unomodel.hxx> 25 #include <unotools/streamwrap.hxx> 26 27 #include <svx/fmmodel.hxx> 28 #include <svx/svditer.hxx> 29 #include <svx/svdobj.hxx> 30 #include <svx/svdogrp.hxx> 31 #include <svx/svdouno.hxx> 32 #include <svx/svdoole2.hxx> 33 #include <svx/svdpage.hxx> 34 #include <sfx2/dispatch.hxx> 35 #include <sfx2/docfile.hxx> 36 #include <sfx2/lokhelper.hxx> 37 #include <comphelper/classids.hxx> 38 #include <sot/formats.hxx> 39 #include <sot/filelist.hxx> 40 #include <sot/storage.hxx> 41 #include <svl/stritem.hxx> 42 #include <vcl/transfer.hxx> 43 #include <vcl/graph.hxx> 44 #include <osl/thread.h> 45 46 #include <comphelper/automationinvokedzone.hxx> 47 #include <comphelper/lok.hxx> 48 #include <comphelper/processfactory.hxx> 49 #include <comphelper/storagehelper.hxx> 50 #include <comphelper/string.hxx> 51 52 #include <viewfunc.hxx> 53 #include <docsh.hxx> 54 #include <drawview.hxx> 55 #include <impex.hxx> 56 #include <dbdata.hxx> 57 #include <sc.hrc> 58 #include <filter.hxx> 59 #include <globstr.hrc> 60 #include <global.hxx> 61 #include <scextopt.hxx> 62 #include <tabvwsh.hxx> 63 #include <compiler.hxx> 64 #include <scmod.hxx> 65 66 #include <asciiopt.hxx> 67 #include <scabstdlg.hxx> 68 #include <clipparam.hxx> 69 #include <markdata.hxx> 70 #include <sfx2/frame.hxx> 71 #include <svx/dbaexchange.hxx> 72 #include <memory> 73 74 using namespace com::sun::star; 75 76 bool ScViewFunc::PasteDataFormat( SotClipboardFormatId nFormatId, 77 const uno::Reference<datatransfer::XTransferable>& rxTransferable, 78 SCCOL nPosX, SCROW nPosY, const Point* pLogicPos, bool bLink, bool bAllowDialogs ) 79 { 80 ScDocument& rDoc = GetViewData().GetDocument(); 81 rDoc.SetPastingDrawFromOtherDoc( true ); 82 83 Point aPos; // inserting position (1/100 mm) 84 if (pLogicPos) 85 aPos = *pLogicPos; 86 else 87 { 88 // inserting position isn't needed for text formats 89 bool bIsTextFormat = ( ScImportExport::IsFormatSupported( nFormatId ) || 90 nFormatId == SotClipboardFormatId::RTF ); 91 if ( !bIsTextFormat ) 92 { 93 // Window MapMode isn't drawing MapMode if DrawingLayer hasn't been created yet 94 95 SCTAB nTab = GetViewData().GetTabNo(); 96 long nXT = 0; 97 for (SCCOL i=0; i<nPosX; i++) 98 nXT += rDoc.GetColWidth(i,nTab); 99 if (rDoc.IsNegativePage(nTab)) 100 nXT = -nXT; 101 sal_uLong nYT = rDoc.GetRowHeight( 0, nPosY-1, nTab); 102 aPos = Point( static_cast<long>(nXT * HMM_PER_TWIPS), static_cast<long>(nYT * HMM_PER_TWIPS) ); 103 } 104 } 105 106 TransferableDataHelper aDataHelper( rxTransferable ); 107 bool bRet = false; 108 109 // handle individual formats 110 111 if ( nFormatId == SotClipboardFormatId::EMBED_SOURCE || 112 nFormatId == SotClipboardFormatId::LINK_SOURCE || 113 nFormatId == SotClipboardFormatId::EMBED_SOURCE_OLE || 114 nFormatId == SotClipboardFormatId::LINK_SOURCE_OLE || 115 nFormatId == SotClipboardFormatId::EMBEDDED_OBJ_OLE ) 116 { 117 uno::Reference < io::XInputStream > xStm; 118 TransferableObjectDescriptor aObjDesc; 119 120 if (aDataHelper.GetTransferableObjectDescriptor(SotClipboardFormatId::OBJECTDESCRIPTOR, aObjDesc)) 121 xStm = aDataHelper.GetInputStream(nFormatId, OUString()); 122 123 if (xStm.is()) 124 { 125 if ( aObjDesc.maClassName == SvGlobalName( SO3_SC_CLASSID_60 ) ) 126 { 127 uno::Reference < embed::XStorage > xStore = ::comphelper::OStorageHelper::GetStorageFromInputStream( xStm ); 128 129 // mba: BaseURL doesn't make sense for clipboard 130 // #i43716# Medium must be allocated with "new". 131 // DoLoad stores the pointer and deletes it with the SfxObjectShell. 132 SfxMedium* pMedium = new SfxMedium( xStore, OUString() ); 133 134 // TODO/LATER: is it a problem that we don't support binary formats here? 135 ScDocShellRef xDocShRef = new ScDocShell(SfxModelFlags::EMBEDDED_OBJECT); 136 if (xDocShRef->DoLoad(pMedium)) 137 { 138 ScDocument& rSrcDoc = xDocShRef->GetDocument(); 139 SCTAB nSrcTab = rSrcDoc.GetVisibleTab(); 140 if (!rSrcDoc.HasTable(nSrcTab)) 141 nSrcTab = 0; 142 143 ScMarkData aSrcMark(rSrcDoc.GetSheetLimits()); 144 aSrcMark.SelectOneTable( nSrcTab ); // for CopyToClip 145 ScDocumentUniquePtr pClipDoc(new ScDocument( SCDOCMODE_CLIP )); 146 147 SCCOL nFirstCol, nLastCol; 148 SCROW nFirstRow, nLastRow; 149 if ( rSrcDoc.GetDataStart( nSrcTab, nFirstCol, nFirstRow ) ) 150 rSrcDoc.GetCellArea( nSrcTab, nLastCol, nLastRow ); 151 else 152 { 153 nFirstCol = nLastCol = 0; 154 nFirstRow = nLastRow = 0; 155 } 156 ScClipParam aClipParam(ScRange(nFirstCol, nFirstRow, nSrcTab, nLastCol, nLastRow, nSrcTab), false); 157 rSrcDoc.CopyToClip(aClipParam, pClipDoc.get(), &aSrcMark, false, false); 158 ScGlobal::SetClipDocName( xDocShRef->GetTitle( SFX_TITLE_FULLNAME ) ); 159 160 SetCursor( nPosX, nPosY ); 161 Unmark(); 162 PasteFromClip( InsertDeleteFlags::ALL, pClipDoc.get(), 163 ScPasteFunc::NONE, false, false, false, INS_NONE, InsertDeleteFlags::NONE, 164 bAllowDialogs ); 165 bRet = true; 166 } 167 168 xDocShRef->DoClose(); 169 xDocShRef.clear(); 170 } 171 else 172 { 173 OUString aName; 174 uno::Reference < embed::XEmbeddedObject > xObj = GetViewData().GetViewShell()->GetObjectShell()-> 175 GetEmbeddedObjectContainer().InsertEmbeddedObject( xStm, aName ); 176 if ( xObj.is() ) 177 { 178 // try to get the replacement image from the clipboard 179 Graphic aGraphic; 180 SotClipboardFormatId nGrFormat = SotClipboardFormatId::NONE; 181 182 // limit the size of the preview metafile to 100000 actions 183 GDIMetaFile aMetafile; 184 if (aDataHelper.GetGDIMetaFile(SotClipboardFormatId::GDIMETAFILE, aMetafile, 100000)) 185 { 186 nGrFormat = SotClipboardFormatId::GDIMETAFILE; 187 aGraphic = aMetafile; 188 } 189 190 // insert replacement image ( if there is one ) into the object helper 191 if ( nGrFormat != SotClipboardFormatId::NONE ) 192 { 193 datatransfer::DataFlavor aDataFlavor; 194 SotExchange::GetFormatDataFlavor( nGrFormat, aDataFlavor ); 195 PasteObject( aPos, xObj, &aObjDesc.maSize, &aGraphic, aDataFlavor.MimeType, aObjDesc.mnViewAspect ); 196 } 197 else 198 PasteObject( aPos, xObj, &aObjDesc.maSize ); 199 200 bRet = true; 201 } 202 else 203 { 204 OSL_FAIL("Error in CreateAndLoad"); 205 } 206 } 207 } 208 else 209 { 210 if ( aDataHelper.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR_OLE, aObjDesc ) ) 211 { 212 OUString aName; 213 uno::Reference < embed::XEmbeddedObject > xObj; 214 xStm = aDataHelper.GetInputStream(SotClipboardFormatId::EMBED_SOURCE_OLE, OUString()); 215 if (!xStm.is()) 216 aDataHelper.GetInputStream(SotClipboardFormatId::EMBEDDED_OBJ_OLE, OUString()); 217 218 if (xStm.is()) 219 { 220 xObj = GetViewData().GetDocShell()->GetEmbeddedObjectContainer().InsertEmbeddedObject( xStm, aName ); 221 } 222 else 223 { 224 try 225 { 226 uno::Reference< embed::XStorage > xTmpStor = ::comphelper::OStorageHelper::GetTemporaryStorage(); 227 uno::Reference < embed::XEmbedObjectClipboardCreator > xClipboardCreator = 228 embed::MSOLEObjectSystemCreator::create( ::comphelper::getProcessComponentContext() ); 229 230 embed::InsertedObjectInfo aInfo = xClipboardCreator->createInstanceInitFromClipboard( 231 xTmpStor, 232 "DummyName", 233 uno::Sequence< beans::PropertyValue >() ); 234 235 // TODO/LATER: in future InsertedObjectInfo will be used to get container related information 236 // for example whether the object should be an iconified one 237 xObj = aInfo.Object; 238 if ( xObj.is() ) 239 GetViewData().GetDocShell()->GetEmbeddedObjectContainer().InsertEmbeddedObject( xObj, aName ); 240 } 241 catch( uno::Exception& ) 242 {} 243 } 244 245 if ( xObj.is() ) 246 { 247 // try to get the replacement image from the clipboard 248 Graphic aGraphic; 249 SotClipboardFormatId nGrFormat = SotClipboardFormatId::NONE; 250 251 // (for Selection Manager in Trusted Solaris) 252 #ifndef __sun 253 if( aDataHelper.GetGraphic( SotClipboardFormatId::SVXB, aGraphic ) ) 254 nGrFormat = SotClipboardFormatId::SVXB; 255 else if( aDataHelper.GetGraphic( SotClipboardFormatId::GDIMETAFILE, aGraphic ) ) 256 nGrFormat = SotClipboardFormatId::GDIMETAFILE; 257 else if( aDataHelper.GetGraphic( SotClipboardFormatId::BITMAP, aGraphic ) ) 258 nGrFormat = SotClipboardFormatId::BITMAP; 259 #endif 260 261 // insert replacement image ( if there is one ) into the object helper 262 if ( nGrFormat != SotClipboardFormatId::NONE ) 263 { 264 datatransfer::DataFlavor aDataFlavor; 265 SotExchange::GetFormatDataFlavor( nGrFormat, aDataFlavor ); 266 PasteObject( aPos, xObj, &aObjDesc.maSize, &aGraphic, aDataFlavor.MimeType, aObjDesc.mnViewAspect ); 267 } 268 else 269 PasteObject( aPos, xObj, &aObjDesc.maSize ); 270 271 // let object stay in loaded state after insertion 272 SdrOle2Obj::Unload( xObj, embed::Aspects::MSOLE_CONTENT ); 273 bRet = true; 274 } 275 else 276 { 277 OSL_FAIL("Error creating external OLE object"); 278 } 279 } 280 //TODO/LATER: if format is not available, create picture 281 } 282 } 283 else if ( nFormatId == SotClipboardFormatId::LINK ) // LINK is also in ScImportExport 284 { 285 bRet = PasteLink( rxTransferable ); 286 } 287 else if ( ScImportExport::IsFormatSupported( nFormatId ) || nFormatId == SotClipboardFormatId::RTF || 288 nFormatId == SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT ) 289 { 290 if ( nFormatId == SotClipboardFormatId::RTF && ( aDataHelper.HasFormat( SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT ) ) ) 291 { 292 // use EditView's PasteSpecial / Drop 293 PasteRTF( nPosX, nPosY, rxTransferable ); 294 bRet = true; 295 } 296 else 297 { 298 ScAddress aCellPos( nPosX, nPosY, GetViewData().GetTabNo() ); 299 auto pObj = std::make_shared<ScImportExport>(GetViewData().GetDocument(), aCellPos); 300 pObj->SetOverwriting( true ); 301 302 303 auto pStrBuffer = std::make_shared<OUString>(); 304 tools::SvRef<SotStorageStream> xStream; 305 if ( aDataHelper.GetSotStorageStream( nFormatId, xStream ) && xStream.is() ) 306 { 307 if (nFormatId == SotClipboardFormatId::HTML && 308 !comphelper::LibreOfficeKit::isActive()) 309 { 310 // Launch the text import options dialog. For now, we do 311 // this for html pasting only, but in the future it may 312 // make sense to do it for other data types too. 313 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); 314 vcl::Window* pParent = GetActiveWin(); 315 ScopedVclPtr<AbstractScTextImportOptionsDlg> pDlg( 316 pFact->CreateScTextImportOptionsDlg(pParent ? pParent->GetFrameWeld() : nullptr)); 317 318 if (pDlg->Execute() == RET_OK) 319 { 320 ScAsciiOptions aOptions; 321 aOptions.SetLanguage(pDlg->GetLanguageType()); 322 aOptions.SetDetectSpecialNumber(pDlg->IsDateConversionSet()); 323 pObj->SetExtOptions(aOptions); 324 } 325 else 326 { 327 // prevent error dialog for user cancel action 328 bRet = true; 329 } 330 } 331 if(!bRet) 332 bRet = pObj->ImportStream( *xStream, OUString(), nFormatId ); 333 // mba: clipboard always must contain absolute URLs (could be from alien source) 334 } 335 else if ((nFormatId == SotClipboardFormatId::STRING || nFormatId == SotClipboardFormatId::STRING_TSVC) 336 && aDataHelper.GetString( nFormatId, *pStrBuffer )) 337 { 338 // Do CSV dialog if more than one line. But not if invoked from Automation. 339 const SfxViewShell* pViewShell = SfxViewShell::Current(); 340 sal_Int32 nDelim = pStrBuffer->indexOf('\n'); 341 if (!(pViewShell && pViewShell->isLOKMobilePhone()) && !comphelper::Automation::AutomationInvokedZone::isActive() 342 && nDelim >= 0 && nDelim != pStrBuffer->getLength () - 1) 343 { 344 vcl::Window* pParent = GetActiveWin(); 345 346 auto pStrm = std::make_shared<ScImportStringStream>(*pStrBuffer); 347 348 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); 349 VclPtr<AbstractScImportAsciiDlg> pDlg( 350 pFact->CreateScImportAsciiDlg(pParent ? pParent->GetFrameWeld() : nullptr, OUString(), pStrm.get(), SC_PASTETEXT)); 351 352 bAllowDialogs = bAllowDialogs && !SC_MOD()->IsInExecuteDrop(); 353 354 pDlg->StartExecuteAsync([this, pDlg, &rDoc, pStrm, nFormatId, pStrBuffer, pObj, bAllowDialogs](sal_Int32 nResult){ 355 bool bShowErrorDialog = bAllowDialogs; 356 if (RET_OK == nResult) 357 { 358 ScAsciiOptions aOptions; 359 pDlg->GetOptions( aOptions ); 360 pDlg->SaveParameters(); 361 pObj->SetExtOptions( aOptions ); 362 pObj->ImportString( *pStrBuffer, nFormatId ); 363 364 // TODO: what if (aObj.IsOverflow()) 365 // Content was partially pasted, which can be undone by 366 // the user though. 367 bShowErrorDialog = bShowErrorDialog && pObj->IsOverflow(); 368 } 369 else 370 { 371 bShowErrorDialog = false; 372 // Yes, no failure, don't raise a "couldn't paste" 373 // dialog if user cancelled. 374 } 375 376 InvalidateAttribs(); 377 GetViewData().UpdateInputHandler(); 378 379 rDoc.SetPastingDrawFromOtherDoc( false ); 380 381 if (bShowErrorDialog) 382 ErrorMessage(STR_PASTE_ERROR); 383 pDlg->disposeOnce(); 384 }); 385 return true; 386 } 387 else 388 bRet = pObj->ImportString( *pStrBuffer, nFormatId ); 389 } 390 else if ((nFormatId != SotClipboardFormatId::STRING && nFormatId != SotClipboardFormatId::STRING_TSVC) 391 && aDataHelper.GetString( nFormatId, *pStrBuffer )) 392 bRet = pObj->ImportString( *pStrBuffer, nFormatId ); 393 394 InvalidateAttribs(); 395 GetViewData().UpdateInputHandler(); 396 } 397 } 398 else if (nFormatId == SotClipboardFormatId::SBA_DATAEXCHANGE) 399 { 400 // import of database data into table 401 402 const DataFlavorExVector& rVector = aDataHelper.GetDataFlavorExVector(); 403 if ( svx::ODataAccessObjectTransferable::canExtractObjectDescriptor(rVector) ) 404 { 405 // transport the whole ODataAccessDescriptor as slot parameter 406 svx::ODataAccessDescriptor aDesc = svx::ODataAccessObjectTransferable::extractObjectDescriptor(aDataHelper); 407 uno::Any aDescAny; 408 uno::Sequence<beans::PropertyValue> aProperties = aDesc.createPropertyValueSequence(); 409 aDescAny <<= aProperties; 410 SfxUnoAnyItem aDataDesc(SID_SBA_IMPORT, aDescAny); 411 412 ScDocShell* pDocSh = GetViewData().GetDocShell(); 413 SCTAB nTab = GetViewData().GetTabNo(); 414 415 ClickCursor(nPosX, nPosY, false); // set cursor position 416 417 // Creation of database area "Import1" isn't here, but in the DocShell 418 // slot execute, so it can be added to the undo action 419 420 ScDBData* pDBData = pDocSh->GetDBData( ScRange(nPosX,nPosY,nTab), SC_DB_OLD, ScGetDBSelection::Keep ); 421 OUString sTarget; 422 if (pDBData) 423 sTarget = pDBData->GetName(); 424 else 425 { 426 ScAddress aCellPos( nPosX,nPosY,nTab ); 427 sTarget = aCellPos.Format(ScRefFlags::ADDR_ABS_3D, &rDoc, rDoc.GetAddressConvention()); 428 } 429 SfxStringItem aTarget(FN_PARAM_1, sTarget); 430 431 bool bAreaIsNew = !pDBData; 432 SfxBoolItem aAreaNew(FN_PARAM_2, bAreaIsNew); 433 434 // asynchronous, to avoid doing the whole import in drop handler 435 SfxDispatcher& rDisp = GetViewData().GetDispatcher(); 436 rDisp.ExecuteList(SID_SBA_IMPORT, SfxCallMode::ASYNCHRON, 437 { &aDataDesc, &aTarget, &aAreaNew }); 438 439 bRet = true; 440 } 441 } 442 else if (nFormatId == SotClipboardFormatId::SBA_FIELDDATAEXCHANGE) 443 { 444 // insert database field control 445 446 if ( svx::OColumnTransferable::canExtractColumnDescriptor( aDataHelper.GetDataFlavorExVector(), ColumnTransferFormatFlags::COLUMN_DESCRIPTOR | ColumnTransferFormatFlags::CONTROL_EXCHANGE ) ) 447 { 448 MakeDrawLayer(); 449 ScDrawView* pScDrawView = GetScDrawView(); 450 SdrObjectUniquePtr pObj = pScDrawView->CreateFieldControl( svx::OColumnTransferable::extractColumnDescriptor( aDataHelper ) ); 451 if (pObj) 452 { 453 Point aInsPos = aPos; 454 tools::Rectangle aRect(pObj->GetLogicRect()); 455 aInsPos.AdjustX( -(aRect.GetSize().Width() / 2) ); 456 aInsPos.AdjustY( -(aRect.GetSize().Height() / 2) ); 457 if ( aInsPos.X() < 0 ) aInsPos.setX( 0 ); 458 if ( aInsPos.Y() < 0 ) aInsPos.setY( 0 ); 459 aRect.SetPos(aInsPos); 460 pObj->SetLogicRect(aRect); 461 462 if ( dynamic_cast<const SdrUnoObj*>( pObj.get() ) != nullptr ) 463 pObj->NbcSetLayer(SC_LAYER_CONTROLS); 464 else 465 pObj->NbcSetLayer(SC_LAYER_FRONT); 466 if (dynamic_cast<const SdrObjGroup*>( pObj.get() ) != nullptr) 467 { 468 SdrObjListIter aIter( *pObj, SdrIterMode::DeepWithGroups ); 469 SdrObject* pSubObj = aIter.Next(); 470 while (pSubObj) 471 { 472 if ( dynamic_cast<const SdrUnoObj*>( pSubObj) != nullptr ) 473 pSubObj->NbcSetLayer(SC_LAYER_CONTROLS); 474 else 475 pSubObj->NbcSetLayer(SC_LAYER_FRONT); 476 pSubObj = aIter.Next(); 477 } 478 } 479 480 pScDrawView->InsertObjectSafe(pObj.release(), *pScDrawView->GetSdrPageView()); 481 482 GetViewData().GetViewShell()->SetDrawShell( true ); 483 bRet = true; 484 } 485 } 486 } 487 else if (nFormatId == SotClipboardFormatId::BITMAP || nFormatId == SotClipboardFormatId::PNG || nFormatId == SotClipboardFormatId::JPEG) 488 { 489 BitmapEx aBmpEx; 490 if( aDataHelper.GetBitmapEx( SotClipboardFormatId::BITMAP, aBmpEx ) ) 491 bRet = PasteBitmapEx( aPos, aBmpEx ); 492 } 493 else if (nFormatId == SotClipboardFormatId::GDIMETAFILE) 494 { 495 GDIMetaFile aMtf; 496 if( aDataHelper.GetGDIMetaFile( SotClipboardFormatId::GDIMETAFILE, aMtf ) ) 497 bRet = PasteMetaFile( aPos, aMtf ); 498 } 499 else if (nFormatId == SotClipboardFormatId::SVXB) 500 { 501 tools::SvRef<SotStorageStream> xStm; 502 if( aDataHelper.GetSotStorageStream( SotClipboardFormatId::SVXB, xStm ) ) 503 { 504 Graphic aGraphic; 505 ReadGraphic( *xStm, aGraphic ); 506 bRet = PasteGraphic( aPos, aGraphic, EMPTY_OUSTRING, EMPTY_OUSTRING ); 507 } 508 } 509 else if ( nFormatId == SotClipboardFormatId::DRAWING ) 510 { 511 tools::SvRef<SotStorageStream> xStm; 512 if( aDataHelper.GetSotStorageStream( SotClipboardFormatId::DRAWING, xStm ) ) 513 { 514 MakeDrawLayer(); // before loading model, so 3D factory has been created 515 516 ScDocShellRef aDragShellRef( new ScDocShell ); 517 aDragShellRef->DoInitNew(); 518 519 std::unique_ptr<FmFormModel> pModel( 520 new FmFormModel( 521 nullptr, 522 aDragShellRef.get())); 523 524 pModel->GetItemPool().FreezeIdRanges(); 525 xStm->Seek(0); 526 527 css::uno::Reference< css::io::XInputStream > xInputStream( new utl::OInputStreamWrapper( *xStm ) ); 528 SvxDrawingLayerImport( pModel.get(), xInputStream ); 529 530 // set everything to right layer: 531 size_t nObjCount = 0; 532 sal_uInt16 nPages = pModel->GetPageCount(); 533 for (sal_uInt16 i=0; i<nPages; i++) 534 { 535 SdrPage* pPage = pModel->GetPage(i); 536 SdrObjListIter aIter( pPage, SdrIterMode::DeepWithGroups ); 537 SdrObject* pObject = aIter.Next(); 538 while (pObject) 539 { 540 if ( dynamic_cast<const SdrUnoObj*>( pObject) != nullptr ) 541 pObject->NbcSetLayer(SC_LAYER_CONTROLS); 542 else 543 pObject->NbcSetLayer(SC_LAYER_FRONT); 544 pObject = aIter.Next(); 545 } 546 547 nObjCount += pPage->GetObjCount(); // count group object only once 548 } 549 550 PasteDraw(aPos, pModel.get(), (nObjCount > 1), "A", "B"); // grouped if more than 1 object 551 pModel.reset(); 552 aDragShellRef->DoClose(); 553 bRet = true; 554 } 555 } 556 else if ( (nFormatId == SotClipboardFormatId::BIFF_5) || (nFormatId == SotClipboardFormatId::BIFF_8) ) 557 { 558 // do excel import into a clipboard document 559 //TODO/MBA: testing 560 uno::Reference <io::XInputStream> xStm = aDataHelper.GetInputStream(nFormatId, OUString()); 561 if (xStm.is()) 562 { 563 std::unique_ptr<ScDocument> pInsDoc(new ScDocument( SCDOCMODE_CLIP )); 564 SCTAB nSrcTab = 0; // Biff5 in clipboard: always sheet 0 565 pInsDoc->ResetClip( &rDoc, nSrcTab ); 566 567 SfxMedium aMed; 568 aMed.GetItemSet()->Put( SfxUnoAnyItem( SID_INPUTSTREAM, uno::makeAny( xStm ) ) ); 569 ErrCode eErr = ScFormatFilter::Get().ScImportExcel( aMed, pInsDoc.get(), EIF_AUTO ); 570 if ( eErr == ERRCODE_NONE ) 571 { 572 ScRange aSource; 573 const ScExtDocOptions* pExtOpt = pInsDoc->GetExtDocOptions(); 574 const ScExtTabSettings* pTabSett = pExtOpt ? pExtOpt->GetTabSettings( nSrcTab ) : nullptr; 575 if( pTabSett && pTabSett->maUsedArea.IsValid() ) 576 { 577 aSource = pTabSett->maUsedArea; 578 // ensure correct sheet indexes 579 aSource.aStart.SetTab( nSrcTab ); 580 aSource.aEnd.SetTab( nSrcTab ); 581 // don't use selection area: if cursor is moved in Excel after Copy, selection 582 // represents the new cursor position and not the copied area 583 } 584 else 585 { 586 OSL_FAIL("no dimension"); //! possible? 587 SCCOL nFirstCol, nLastCol; 588 SCROW nFirstRow, nLastRow; 589 if ( pInsDoc->GetDataStart( nSrcTab, nFirstCol, nFirstRow ) ) 590 pInsDoc->GetCellArea( nSrcTab, nLastCol, nLastRow ); 591 else 592 { 593 nFirstCol = nLastCol = 0; 594 nFirstRow = nLastRow = 0; 595 } 596 aSource = ScRange( nFirstCol, nFirstRow, nSrcTab, 597 nLastCol, nLastRow, nSrcTab ); 598 } 599 600 if ( pLogicPos ) 601 { 602 // position specified (Drag&Drop) - change selection 603 MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, false, false ); 604 Unmark(); 605 } 606 607 pInsDoc->SetClipArea( aSource ); 608 PasteFromClip( InsertDeleteFlags::ALL, pInsDoc.get(), 609 ScPasteFunc::NONE, false, false, false, INS_NONE, InsertDeleteFlags::NONE, 610 bAllowDialogs ); 611 bRet = true; 612 } 613 } 614 } 615 else if ( nFormatId == SotClipboardFormatId::SIMPLE_FILE ) 616 { 617 OUString aFile; 618 if ( aDataHelper.GetString( nFormatId, aFile ) ) 619 bRet = PasteFile( aPos, aFile, bLink ); 620 } 621 else if ( nFormatId == SotClipboardFormatId::FILE_LIST ) 622 { 623 FileList aFileList; 624 if ( aDataHelper.GetFileList( nFormatId, aFileList ) ) 625 { 626 sal_uLong nCount = aFileList.Count(); 627 for( sal_uLong i = 0; i < nCount ; i++ ) 628 { 629 OUString aFile = aFileList.GetFile( i ); 630 631 PasteFile( aPos, aFile, bLink ); 632 633 aPos.AdjustX(400 ); 634 aPos.AdjustY(400 ); 635 } 636 bRet = true; 637 } 638 } 639 else if ( nFormatId == SotClipboardFormatId::SOLK || 640 nFormatId == SotClipboardFormatId::UNIFORMRESOURCELOCATOR || 641 nFormatId == SotClipboardFormatId::NETSCAPE_BOOKMARK || 642 nFormatId == SotClipboardFormatId::FILEGRPDESCRIPTOR ) 643 { 644 bRet = PasteBookmark( nFormatId, rxTransferable, nPosX, nPosY ); 645 } 646 647 rDoc.SetPastingDrawFromOtherDoc( false ); 648 649 return bRet; 650 } 651 652 bool ScViewFunc::PasteLink( const uno::Reference<datatransfer::XTransferable>& rxTransferable ) 653 { 654 TransferableDataHelper aDataHelper( rxTransferable ); 655 656 // get link data from transferable before string data, 657 // so the source knows it will be used for a link 658 659 uno::Sequence<sal_Int8> aSequence = aDataHelper.GetSequence(SotClipboardFormatId::LINK, OUString()); 660 if (!aSequence.hasElements()) 661 { 662 OSL_FAIL("DDE Data not found."); 663 return false; 664 } 665 666 // check size (only if string is available in transferable) 667 668 sal_uInt16 nCols = 1; 669 sal_uInt16 nRows = 1; 670 if ( aDataHelper.HasFormat( SotClipboardFormatId::STRING ) ) 671 { 672 OUString aDataStr; 673 if ( aDataHelper.GetString( SotClipboardFormatId::STRING, aDataStr ) ) 674 { 675 // get size from string the same way as in ScDdeLink::DataChanged 676 677 aDataStr = convertLineEnd(aDataStr, LINEEND_LF); 678 sal_Int32 nLen = aDataStr.getLength(); 679 if (nLen && aDataStr[nLen-1] == '\n') 680 aDataStr = aDataStr.copy(0, nLen-1); 681 682 if (!aDataStr.isEmpty()) 683 { 684 nRows = comphelper::string::getTokenCount(aDataStr, '\n'); 685 OUString aLine = aDataStr.getToken( 0, '\n' ); 686 if (!aLine.isEmpty()) 687 nCols = comphelper::string::getTokenCount(aLine, '\t'); 688 } 689 } 690 } 691 692 // create formula 693 694 sal_Int32 nSeqLen = aSequence.getLength(); 695 const char* p = reinterpret_cast<const char*>(aSequence.getConstArray()); 696 697 rtl_TextEncoding eSysEnc = osl_getThreadTextEncoding(); 698 699 // char array delimited by \0. 700 // app \0 topic \0 item \0 (extra \0) where the extra is optional. 701 ::std::vector<OUString> aStrs; 702 const char* pStart = p; 703 sal_Int32 nStart = 0; 704 for (sal_Int32 i = 0; i < nSeqLen; ++i, ++p) 705 { 706 if (*p == '\0') 707 { 708 sal_Int32 nLen = i - nStart; 709 aStrs.emplace_back(pStart, nLen, eSysEnc); 710 nStart = ++i; 711 pStart = ++p; 712 } 713 } 714 715 if (aStrs.size() < 3) 716 return false; 717 718 const OUString& pApp = aStrs[0]; 719 const OUString& pTopic = aStrs[1]; 720 const OUString& pItem = aStrs[2]; 721 const OUString* pExtra = nullptr; 722 if (aStrs.size() > 3) 723 pExtra = &aStrs[3]; 724 725 if ( pExtra && *pExtra == "calc:extref" ) 726 { 727 // Paste this as an external reference. Note that paste link always 728 // uses Calc A1 syntax even when another formula syntax is specified 729 // in the UI. 730 EnterMatrix("='" 731 + ScGlobal::GetAbsDocName(pTopic, GetViewData().GetDocument().GetDocumentShell()) 732 + "'#" + pItem 733 , ::formula::FormulaGrammar::GRAM_NATIVE); 734 return true; 735 } 736 else 737 { 738 // DDE in all other cases. 739 740 // TODO: we could define ocQuote for " 741 EnterMatrix("=" + ScCompiler::GetNativeSymbol(ocDde) 742 + ScCompiler::GetNativeSymbol(ocOpen) 743 + "\"" + pApp + "\"" 744 + ScCompiler::GetNativeSymbol(ocSep) 745 + "\"" + pTopic + "\"" 746 + ScCompiler::GetNativeSymbol(ocSep) 747 + "\"" + pItem + "\"" 748 + ScCompiler::GetNativeSymbol(ocClose) 749 , ::formula::FormulaGrammar::GRAM_NATIVE); 750 } 751 752 // mark range 753 754 SCTAB nTab = GetViewData().GetTabNo(); 755 SCCOL nCurX = GetViewData().GetCurX(); 756 SCROW nCurY = GetViewData().GetCurY(); 757 HideAllCursors(); 758 DoneBlockMode(); 759 InitBlockMode( nCurX, nCurY, nTab ); 760 MarkCursor( nCurX+static_cast<SCCOL>(nCols)-1, nCurY+static_cast<SCROW>(nRows)-1, nTab ); 761 ShowAllCursors(); 762 CursorPosChanged(); 763 764 return true; 765 } 766 767 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 768
