lok: calc: fix needed when position caching is disabled
[LibreOffice.git] / sc / source / ui / view / viewfun5.cxx
blob1590baee2f97ddb07c6ec22d73bf6c7258ded7be
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/embed/XEmbedObjectClipboardCreator.hpp>
21 #include <com/sun/star/embed/Aspects.hpp>
22 #include <com/sun/star/embed/MSOLEObjectSystemCreator.hpp>
24 #include <svx/unomodel.hxx>
25 #include <unotools/streamwrap.hxx>
27 #include <svx/fmmodel.hxx>
28 #include <svx/svdetc.hxx>
29 #include <svx/svditer.hxx>
30 #include <svx/svdobj.hxx>
31 #include <svx/svdogrp.hxx>
32 #include <svx/svdouno.hxx>
33 #include <svx/svdoole2.hxx>
34 #include <svx/svdpage.hxx>
35 #include <sfx2/dispatch.hxx>
36 #include <sfx2/docfile.hxx>
37 #include <comphelper/classids.hxx>
38 #include <sot/formats.hxx>
39 #include <sot/filelist.hxx>
40 #include <sot/storage.hxx>
41 #include <unotools/pathoptions.hxx>
42 #include <svl/ptitem.hxx>
43 #include <svl/stritem.hxx>
44 #include <svtools/transfer.hxx>
45 #include <vcl/graph.hxx>
47 #include <comphelper/lok.hxx>
48 #include <comphelper/processfactory.hxx>
49 #include <comphelper/storagehelper.hxx>
50 #include <comphelper/string.hxx>
52 #include <viewfunc.hxx>
53 #include <docsh.hxx>
54 #include <drawview.hxx>
55 #include <impex.hxx>
56 #include <dbfunc.hxx>
57 #include <dbdata.hxx>
58 #include <sc.hrc>
59 #include <filter.hxx>
60 #include <globstr.hrc>
61 #include <global.hxx>
62 #include <scextopt.hxx>
63 #include <tabvwsh.hxx>
64 #include <compiler.hxx>
66 #include <asciiopt.hxx>
67 #include <scabstdlg.hxx>
68 #include <clipparam.hxx>
69 #include <markdata.hxx>
70 #include <vcl/msgbox.hxx>
71 #include <sfx2/viewfrm.hxx>
72 #include <svx/dbaexchange.hxx>
73 #include <memory>
75 using namespace com::sun::star;
77 bool ScViewFunc::PasteDataFormat( SotClipboardFormatId nFormatId,
78 const uno::Reference<datatransfer::XTransferable>& rxTransferable,
79 SCCOL nPosX, SCROW nPosY, const Point* pLogicPos, bool bLink, bool bAllowDialogs )
81 ScDocument* pDoc = GetViewData().GetDocument();
82 pDoc->SetPastingDrawFromOtherDoc( true );
84 Point aPos; // inserting position (1/100 mm)
85 if (pLogicPos)
86 aPos = *pLogicPos;
87 else
89 // inserting position isn't needed for text formats
90 bool bIsTextFormat = ( ScImportExport::IsFormatSupported( nFormatId ) ||
91 nFormatId == SotClipboardFormatId::RTF );
92 if ( !bIsTextFormat )
94 // Window MapMode isn't drawing MapMode if DrawingLayer hasn't been created yet
96 SCTAB nTab = GetViewData().GetTabNo();
97 long nXT = 0;
98 for (SCCOL i=0; i<nPosX; i++)
99 nXT += pDoc->GetColWidth(i,nTab);
100 if (pDoc->IsNegativePage(nTab))
101 nXT = -nXT;
102 sal_uLong nYT = pDoc->GetRowHeight( 0, nPosY-1, nTab);
103 aPos = Point( (long)(nXT * HMM_PER_TWIPS), (long)(nYT * HMM_PER_TWIPS) );
107 TransferableDataHelper aDataHelper( rxTransferable );
108 bool bRet = false;
110 // handle individual formats
112 if ( nFormatId == SotClipboardFormatId::EMBED_SOURCE ||
113 nFormatId == SotClipboardFormatId::LINK_SOURCE ||
114 nFormatId == SotClipboardFormatId::EMBED_SOURCE_OLE ||
115 nFormatId == SotClipboardFormatId::LINK_SOURCE_OLE ||
116 nFormatId == SotClipboardFormatId::EMBEDDED_OBJ_OLE )
118 uno::Reference < io::XInputStream > xStm;
119 TransferableObjectDescriptor aObjDesc;
121 if (aDataHelper.GetTransferableObjectDescriptor(SotClipboardFormatId::OBJECTDESCRIPTOR, aObjDesc))
122 xStm = aDataHelper.GetInputStream(nFormatId, OUString());
124 if (xStm.is())
126 if ( aObjDesc.maClassName == SvGlobalName( SO3_SC_CLASSID_60 ) )
128 uno::Reference < embed::XStorage > xStore = ::comphelper::OStorageHelper::GetStorageFromInputStream( xStm );
130 // mba: BaseURL doesn't make sense for clipboard
131 // #i43716# Medium must be allocated with "new".
132 // DoLoad stores the pointer and deletes it with the SfxObjectShell.
133 SfxMedium* pMedium = new SfxMedium( xStore, OUString() );
135 // TODO/LATER: is it a problem that we don't support binary formats here?
136 ScDocShellRef xDocShRef = new ScDocShell(SfxModelFlags::EMBEDDED_OBJECT);
137 if (xDocShRef->DoLoad(pMedium))
139 ScDocument& rSrcDoc = xDocShRef->GetDocument();
140 SCTAB nSrcTab = rSrcDoc.GetVisibleTab();
141 if (!rSrcDoc.HasTable(nSrcTab))
142 nSrcTab = 0;
144 ScMarkData aSrcMark;
145 aSrcMark.SelectOneTable( nSrcTab ); // for CopyToClip
146 ScDocumentUniquePtr pClipDoc(new ScDocument( SCDOCMODE_CLIP ));
148 SCCOL nFirstCol, nLastCol;
149 SCROW nFirstRow, nLastRow;
150 if ( rSrcDoc.GetDataStart( nSrcTab, nFirstCol, nFirstRow ) )
151 rSrcDoc.GetCellArea( nSrcTab, nLastCol, nLastRow );
152 else
154 nFirstCol = nLastCol = 0;
155 nFirstRow = nLastRow = 0;
157 ScClipParam aClipParam(ScRange(nFirstCol, nFirstRow, nSrcTab, nLastCol, nLastRow, nSrcTab), false);
158 rSrcDoc.CopyToClip(aClipParam, pClipDoc.get(), &aSrcMark, false, false);
159 ScGlobal::SetClipDocName( xDocShRef->GetTitle( SFX_TITLE_FULLNAME ) );
161 SetCursor( nPosX, nPosY );
162 Unmark();
163 PasteFromClip( InsertDeleteFlags::ALL, pClipDoc.get(),
164 ScPasteFunc::NONE, false, false, false, INS_NONE, InsertDeleteFlags::NONE,
165 bAllowDialogs );
166 bRet = true;
169 xDocShRef->DoClose();
170 xDocShRef.clear();
172 else
174 OUString aName;
175 uno::Reference < embed::XEmbeddedObject > xObj = GetViewData().GetViewShell()->GetObjectShell()->
176 GetEmbeddedObjectContainer().InsertEmbeddedObject( xStm, aName );
177 if ( xObj.is() )
179 // try to get the replacement image from the clipboard
180 Graphic aGraphic;
181 SotClipboardFormatId nGrFormat = SotClipboardFormatId::NONE;
183 // limit the size of the preview metafile to 100000 actions
184 GDIMetaFile aMetafile;
185 if (aDataHelper.GetGDIMetaFile(SotClipboardFormatId::GDIMETAFILE, aMetafile, 100000))
187 nGrFormat = SotClipboardFormatId::GDIMETAFILE;
188 aGraphic = aMetafile;
191 // insert replacement image ( if there is one ) into the object helper
192 if ( nGrFormat != SotClipboardFormatId::NONE )
194 datatransfer::DataFlavor aDataFlavor;
195 SotExchange::GetFormatDataFlavor( nGrFormat, aDataFlavor );
196 PasteObject( aPos, xObj, &aObjDesc.maSize, &aGraphic, aDataFlavor.MimeType, aObjDesc.mnViewAspect );
198 else
199 PasteObject( aPos, xObj, &aObjDesc.maSize );
201 bRet = true;
203 else
205 OSL_FAIL("Error in CreateAndLoad");
209 else
211 if ( aDataHelper.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR_OLE, aObjDesc ) )
213 OUString aName;
214 uno::Reference < embed::XEmbeddedObject > xObj;
215 xStm = aDataHelper.GetInputStream(SotClipboardFormatId::EMBED_SOURCE_OLE, OUString());
216 if (!xStm.is())
217 aDataHelper.GetInputStream(SotClipboardFormatId::EMBEDDED_OBJ_OLE, OUString());
219 if (xStm.is())
221 xObj = GetViewData().GetDocShell()->GetEmbeddedObjectContainer().InsertEmbeddedObject( xStm, aName );
223 else
227 uno::Reference< embed::XStorage > xTmpStor = ::comphelper::OStorageHelper::GetTemporaryStorage();
228 uno::Reference < embed::XEmbedObjectClipboardCreator > xClipboardCreator =
229 embed::MSOLEObjectSystemCreator::create( ::comphelper::getProcessComponentContext() );
231 embed::InsertedObjectInfo aInfo = xClipboardCreator->createInstanceInitFromClipboard(
232 xTmpStor,
233 "DummyName",
234 uno::Sequence< beans::PropertyValue >() );
236 // TODO/LATER: in future InsertedObjectInfo will be used to get container related information
237 // for example whether the object should be an iconified one
238 xObj = aInfo.Object;
239 if ( xObj.is() )
240 GetViewData().GetDocShell()->GetEmbeddedObjectContainer().InsertEmbeddedObject( xObj, aName );
242 catch( uno::Exception& )
246 if ( xObj.is() )
248 // try to get the replacement image from the clipboard
249 Graphic aGraphic;
250 SotClipboardFormatId nGrFormat = SotClipboardFormatId::NONE;
252 // (for Selection Manager in Trusted Solaris)
253 #ifndef __sun
254 if( aDataHelper.GetGraphic( SotClipboardFormatId::SVXB, aGraphic ) )
255 nGrFormat = SotClipboardFormatId::SVXB;
256 else if( aDataHelper.GetGraphic( SotClipboardFormatId::GDIMETAFILE, aGraphic ) )
257 nGrFormat = SotClipboardFormatId::GDIMETAFILE;
258 else if( aDataHelper.GetGraphic( SotClipboardFormatId::BITMAP, aGraphic ) )
259 nGrFormat = SotClipboardFormatId::BITMAP;
260 #endif
262 // insert replacement image ( if there is one ) into the object helper
263 if ( nGrFormat != SotClipboardFormatId::NONE )
265 datatransfer::DataFlavor aDataFlavor;
266 SotExchange::GetFormatDataFlavor( nGrFormat, aDataFlavor );
267 PasteObject( aPos, xObj, &aObjDesc.maSize, &aGraphic, aDataFlavor.MimeType, aObjDesc.mnViewAspect );
269 else
270 PasteObject( aPos, xObj, &aObjDesc.maSize );
272 // let object stay in loaded state after insertion
273 SdrOle2Obj::Unload( xObj, embed::Aspects::MSOLE_CONTENT );
274 bRet = true;
276 else
278 OSL_FAIL("Error creating external OLE object");
281 //TODO/LATER: if format is not available, create picture
284 else if ( nFormatId == SotClipboardFormatId::LINK ) // LINK is also in ScImportExport
286 bRet = PasteLink( rxTransferable );
288 else if ( ScImportExport::IsFormatSupported( nFormatId ) || nFormatId == SotClipboardFormatId::RTF ||
289 nFormatId == SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT )
291 if ( nFormatId == SotClipboardFormatId::RTF && ( aDataHelper.HasFormat( SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT ) ) )
293 // use EditView's PasteSpecial / Drop
294 PasteRTF( nPosX, nPosY, rxTransferable );
295 bRet = true;
297 else
299 ScAddress aCellPos( nPosX, nPosY, GetViewData().GetTabNo() );
300 std::shared_ptr<ScImportExport> pObj(new ScImportExport(GetViewData().GetDocument(), aCellPos));
301 pObj->SetOverwriting( true );
304 std::shared_ptr<OUString> pStrBuffer(new OUString());
305 tools::SvRef<SotStorageStream> xStream;
306 if ( aDataHelper.GetSotStorageStream( nFormatId, xStream ) && xStream.is() )
308 if (nFormatId == SotClipboardFormatId::HTML)
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 ScopedVclPtr<AbstractScTextImportOptionsDlg> pDlg(
315 pFact->CreateScTextImportOptionsDlg());
317 if (pDlg->Execute() == RET_OK)
319 ScAsciiOptions aOptions;
320 aOptions.SetLanguage(pDlg->GetLanguageType());
321 aOptions.SetDetectSpecialNumber(pDlg->IsDateConversionSet());
322 pObj->SetExtOptions(aOptions);
324 else
326 // prevent error dialog for user cancel action
327 bRet = true;
330 if(!bRet)
331 bRet = pObj->ImportStream( *xStream, OUString(), nFormatId );
332 // mba: clipboard always must contain absolute URLs (could be from alien source)
334 else if ((nFormatId == SotClipboardFormatId::STRING || nFormatId == SotClipboardFormatId::STRING_TSVC)
335 && aDataHelper.GetString( nFormatId, *pStrBuffer ))
337 // Do CSV dialog if more than one line.
338 sal_Int32 nDelim = pStrBuffer->indexOf('\n');
339 if (nDelim >= 0 && nDelim != pStrBuffer->getLength () - 1)
341 vcl::Window* pParent = comphelper::LibreOfficeKit::isActive() ? GetActiveWin() : nullptr;
343 std::shared_ptr<ScImportStringStream> pStrm(new ScImportStringStream(*pStrBuffer));
345 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
346 VclPtr<AbstractScImportAsciiDlg> pDlg(
347 pFact->CreateScImportAsciiDlg(pParent, OUString(), pStrm.get(), SC_PASTETEXT));
349 bAllowDialogs = bAllowDialogs && !SC_MOD()->IsInExecuteDrop();
351 pDlg->StartExecuteAsync([this, pDlg, pDoc, pStrm, nFormatId, pStrBuffer, pObj, bAllowDialogs](sal_Int32 nResult){
352 bool bShowErrorDialog = bAllowDialogs;
353 if (RET_OK == nResult)
355 ScAsciiOptions aOptions;
356 pDlg->GetOptions( aOptions );
357 pDlg->SaveParameters();
358 pObj->SetExtOptions( aOptions );
359 pObj->ImportString( *pStrBuffer, nFormatId );
361 // TODO: what if (aObj.IsOverflow())
362 // Content was partially pasted, which can be undone by
363 // the user though.
364 bShowErrorDialog = bShowErrorDialog && pObj->IsOverflow();
366 else
368 bShowErrorDialog = false;
369 // Yes, no failure, don't raise a "couldn't paste"
370 // dialog if user cancelled.
373 InvalidateAttribs();
374 GetViewData().UpdateInputHandler();
376 pDoc->SetPastingDrawFromOtherDoc( false );
378 if (bShowErrorDialog)
379 ErrorMessage(STR_PASTE_ERROR);
381 return true;
383 else
384 bRet = pObj->ImportString( *pStrBuffer, nFormatId );
386 else if ((nFormatId != SotClipboardFormatId::STRING && nFormatId != SotClipboardFormatId::STRING_TSVC)
387 && aDataHelper.GetString( nFormatId, *pStrBuffer ))
388 bRet = pObj->ImportString( *pStrBuffer, nFormatId );
390 InvalidateAttribs();
391 GetViewData().UpdateInputHandler();
394 else if (nFormatId == SotClipboardFormatId::SBA_DATAEXCHANGE)
396 // import of database data into table
398 const DataFlavorExVector& rVector = aDataHelper.GetDataFlavorExVector();
399 if ( svx::ODataAccessObjectTransferable::canExtractObjectDescriptor(rVector) )
401 // transport the whole ODataAccessDescriptor as slot parameter
402 svx::ODataAccessDescriptor aDesc = svx::ODataAccessObjectTransferable::extractObjectDescriptor(aDataHelper);
403 uno::Any aDescAny;
404 uno::Sequence<beans::PropertyValue> aProperties = aDesc.createPropertyValueSequence();
405 aDescAny <<= aProperties;
406 SfxUsrAnyItem aDataDesc(SID_SBA_IMPORT, aDescAny);
408 ScDocShell* pDocSh = GetViewData().GetDocShell();
409 SCTAB nTab = GetViewData().GetTabNo();
411 ClickCursor(nPosX, nPosY, false); // set cursor position
413 // Creation of database area "Import1" isn't here, but in the DocShell
414 // slot execute, so it can be added to the undo action
416 ScDBData* pDBData = pDocSh->GetDBData( ScRange(nPosX,nPosY,nTab), SC_DB_OLD, ScGetDBSelection::Keep );
417 OUString sTarget;
418 if (pDBData)
419 sTarget = pDBData->GetName();
420 else
422 ScAddress aCellPos( nPosX,nPosY,nTab );
423 sTarget = aCellPos.Format(ScRefFlags::ADDR_ABS_3D, pDoc, pDoc->GetAddressConvention());
425 SfxStringItem aTarget(FN_PARAM_1, sTarget);
427 bool bAreaIsNew = !pDBData;
428 SfxBoolItem aAreaNew(FN_PARAM_2, bAreaIsNew);
430 // asynchronous, to avoid doing the whole import in drop handler
431 SfxDispatcher& rDisp = GetViewData().GetDispatcher();
432 rDisp.ExecuteList(SID_SBA_IMPORT, SfxCallMode::ASYNCHRON,
433 { &aDataDesc, &aTarget, &aAreaNew });
435 bRet = true;
438 else if (nFormatId == SotClipboardFormatId::SBA_FIELDDATAEXCHANGE)
440 // insert database field control
442 if ( svx::OColumnTransferable::canExtractColumnDescriptor( aDataHelper.GetDataFlavorExVector(), ColumnTransferFormatFlags::COLUMN_DESCRIPTOR | ColumnTransferFormatFlags::CONTROL_EXCHANGE ) )
444 MakeDrawLayer();
445 ScDrawView* pScDrawView = GetScDrawView();
446 SdrObject* pObj = pScDrawView->CreateFieldControl( svx::OColumnTransferable::extractColumnDescriptor( aDataHelper ) );
447 if (pObj)
449 Point aInsPos = aPos;
450 tools::Rectangle aRect(pObj->GetLogicRect());
451 aInsPos.X() -= aRect.GetSize().Width() / 2;
452 aInsPos.Y() -= aRect.GetSize().Height() / 2;
453 if ( aInsPos.X() < 0 ) aInsPos.X() = 0;
454 if ( aInsPos.Y() < 0 ) aInsPos.Y() = 0;
455 aRect.SetPos(aInsPos);
456 pObj->SetLogicRect(aRect);
458 if ( dynamic_cast<const SdrUnoObj*>( pObj) != nullptr )
459 pObj->NbcSetLayer(SC_LAYER_CONTROLS);
460 else
461 pObj->NbcSetLayer(SC_LAYER_FRONT);
462 if (dynamic_cast<const SdrObjGroup*>( pObj) != nullptr)
464 SdrObjListIter aIter( *pObj, SdrIterMode::DeepWithGroups );
465 SdrObject* pSubObj = aIter.Next();
466 while (pSubObj)
468 if ( dynamic_cast<const SdrUnoObj*>( pSubObj) != nullptr )
469 pSubObj->NbcSetLayer(SC_LAYER_CONTROLS);
470 else
471 pSubObj->NbcSetLayer(SC_LAYER_FRONT);
472 pSubObj = aIter.Next();
476 pScDrawView->InsertObjectSafe(pObj, *pScDrawView->GetSdrPageView());
478 GetViewData().GetViewShell()->SetDrawShell( true );
479 bRet = true;
483 else if (nFormatId == SotClipboardFormatId::BITMAP || nFormatId == SotClipboardFormatId::PNG)
485 BitmapEx aBmpEx;
486 if( aDataHelper.GetBitmapEx( SotClipboardFormatId::BITMAP, aBmpEx ) )
487 bRet = PasteBitmapEx( aPos, aBmpEx );
489 else if (nFormatId == SotClipboardFormatId::GDIMETAFILE)
491 GDIMetaFile aMtf;
492 if( aDataHelper.GetGDIMetaFile( SotClipboardFormatId::GDIMETAFILE, aMtf ) )
493 bRet = PasteMetaFile( aPos, aMtf );
495 else if (nFormatId == SotClipboardFormatId::SVXB)
497 tools::SvRef<SotStorageStream> xStm;
498 if( aDataHelper.GetSotStorageStream( SotClipboardFormatId::SVXB, xStm ) )
500 Graphic aGraphic;
501 ReadGraphic( *xStm, aGraphic );
502 bRet = PasteGraphic( aPos, aGraphic, EMPTY_OUSTRING, EMPTY_OUSTRING );
505 else if ( nFormatId == SotClipboardFormatId::DRAWING )
507 tools::SvRef<SotStorageStream> xStm;
508 if( aDataHelper.GetSotStorageStream( SotClipboardFormatId::DRAWING, xStm ) )
510 MakeDrawLayer(); // before loading model, so 3D factory has been created
512 SvtPathOptions aPathOpt;
513 OUString aPath = aPathOpt.GetPalettePath();
515 ScDocShellRef aDragShellRef( new ScDocShell );
516 aDragShellRef->DoInitNew();
517 std::unique_ptr<FmFormModel> pModel(new FmFormModel( aPath, nullptr, aDragShellRef.get() ));
519 pModel->GetItemPool().FreezeIdRanges();
520 xStm->Seek(0);
522 css::uno::Reference< css::io::XInputStream > xInputStream( new utl::OInputStreamWrapper( *xStm ) );
523 SvxDrawingLayerImport( pModel.get(), xInputStream );
525 // set everything to right layer:
526 size_t nObjCount = 0;
527 sal_uInt16 nPages = pModel->GetPageCount();
528 for (sal_uInt16 i=0; i<nPages; i++)
530 SdrPage* pPage = pModel->GetPage(i);
531 SdrObjListIter aIter( *pPage, SdrIterMode::DeepWithGroups );
532 SdrObject* pObject = aIter.Next();
533 while (pObject)
535 if ( dynamic_cast<const SdrUnoObj*>( pObject) != nullptr )
536 pObject->NbcSetLayer(SC_LAYER_CONTROLS);
537 else
538 pObject->NbcSetLayer(SC_LAYER_FRONT);
539 pObject = aIter.Next();
542 nObjCount += pPage->GetObjCount(); // count group object only once
545 PasteDraw(aPos, pModel.get(), (nObjCount > 1), "A", "B"); // grouped if more than 1 object
546 pModel.reset();
547 aDragShellRef->DoClose();
548 bRet = true;
551 else if ( (nFormatId == SotClipboardFormatId::BIFF_5) || (nFormatId == SotClipboardFormatId::BIFF_8) )
553 // do excel import into a clipboard document
554 //TODO/MBA: testing
555 uno::Reference <io::XInputStream> xStm = aDataHelper.GetInputStream(nFormatId, OUString());
556 if (xStm.is())
558 ScDocument* pInsDoc = new ScDocument( SCDOCMODE_CLIP );
559 SCTAB nSrcTab = 0; // Biff5 in clipboard: always sheet 0
560 pInsDoc->ResetClip( pDoc, nSrcTab );
562 SfxMedium aMed;
563 aMed.GetItemSet()->Put( SfxUsrAnyItem( SID_INPUTSTREAM, uno::makeAny( xStm ) ) );
564 ErrCode eErr = ScFormatFilter::Get().ScImportExcel( aMed, pInsDoc, EIF_AUTO );
565 if ( eErr == ERRCODE_NONE )
567 ScRange aSource;
568 const ScExtDocOptions* pExtOpt = pInsDoc->GetExtDocOptions();
569 const ScExtTabSettings* pTabSett = pExtOpt ? pExtOpt->GetTabSettings( nSrcTab ) : nullptr;
570 if( pTabSett && pTabSett->maUsedArea.IsValid() )
572 aSource = pTabSett->maUsedArea;
573 // ensure correct sheet indexes
574 aSource.aStart.SetTab( nSrcTab );
575 aSource.aEnd.SetTab( nSrcTab );
576 // don't use selection area: if cursor is moved in Excel after Copy, selection
577 // represents the new cursor position and not the copied area
579 else
581 OSL_FAIL("no dimension"); //! possible?
582 SCCOL nFirstCol, nLastCol;
583 SCROW nFirstRow, nLastRow;
584 if ( pInsDoc->GetDataStart( nSrcTab, nFirstCol, nFirstRow ) )
585 pInsDoc->GetCellArea( nSrcTab, nLastCol, nLastRow );
586 else
588 nFirstCol = nLastCol = 0;
589 nFirstRow = nLastRow = 0;
591 aSource = ScRange( nFirstCol, nFirstRow, nSrcTab,
592 nLastCol, nLastRow, nSrcTab );
595 if ( pLogicPos )
597 // position specified (Drag&Drop) - change selection
598 MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, false, false );
599 Unmark();
602 pInsDoc->SetClipArea( aSource );
603 PasteFromClip( InsertDeleteFlags::ALL, pInsDoc,
604 ScPasteFunc::NONE, false, false, false, INS_NONE, InsertDeleteFlags::NONE,
605 bAllowDialogs );
606 delete pInsDoc;
608 bRet = true;
612 else if ( nFormatId == SotClipboardFormatId::SIMPLE_FILE )
614 OUString aFile;
615 if ( aDataHelper.GetString( nFormatId, aFile ) )
616 bRet = PasteFile( aPos, aFile, bLink );
618 else if ( nFormatId == SotClipboardFormatId::FILE_LIST )
620 FileList aFileList;
621 if ( aDataHelper.GetFileList( nFormatId, aFileList ) )
623 sal_uLong nCount = aFileList.Count();
624 for( sal_uLong i = 0; i < nCount ; i++ )
626 OUString aFile = aFileList.GetFile( i );
628 PasteFile( aPos, aFile, bLink );
630 aPos.X() += 400;
631 aPos.Y() += 400;
633 bRet = true;
636 else if ( nFormatId == SotClipboardFormatId::SOLK ||
637 nFormatId == SotClipboardFormatId::UNIFORMRESOURCELOCATOR ||
638 nFormatId == SotClipboardFormatId::NETSCAPE_BOOKMARK ||
639 nFormatId == SotClipboardFormatId::FILEGRPDESCRIPTOR )
641 bRet = PasteBookmark( nFormatId, rxTransferable, nPosX, nPosY );
644 pDoc->SetPastingDrawFromOtherDoc( false );
646 return bRet;
649 bool ScViewFunc::PasteLink( const uno::Reference<datatransfer::XTransferable>& rxTransferable )
651 TransferableDataHelper aDataHelper( rxTransferable );
653 // get link data from transferable before string data,
654 // so the source knows it will be used for a link
656 uno::Sequence<sal_Int8> aSequence = aDataHelper.GetSequence(SotClipboardFormatId::LINK, OUString());
657 if (!aSequence.getLength())
659 OSL_FAIL("DDE Data not found.");
660 return false;
663 // check size (only if string is available in transferable)
665 sal_uInt16 nCols = 1;
666 sal_uInt16 nRows = 1;
667 if ( aDataHelper.HasFormat( SotClipboardFormatId::STRING ) )
669 OUString aDataStr;
670 if ( aDataHelper.GetString( SotClipboardFormatId::STRING, aDataStr ) )
672 // get size from string the same way as in ScDdeLink::DataChanged
674 aDataStr = convertLineEnd(aDataStr, LINEEND_LF);
675 sal_Int32 nLen = aDataStr.getLength();
676 if (nLen && aDataStr[nLen-1] == '\n')
677 aDataStr = aDataStr.copy(0, nLen-1);
679 if (!aDataStr.isEmpty())
681 nRows = comphelper::string::getTokenCount(aDataStr, '\n');
682 OUString aLine = aDataStr.getToken( 0, '\n' );
683 if (!aLine.isEmpty())
684 nCols = comphelper::string::getTokenCount(aLine, '\t');
689 // create formula
691 sal_Int32 nSeqLen = aSequence.getLength();
692 const char* p = reinterpret_cast<const char*>(aSequence.getConstArray());
694 rtl_TextEncoding eSysEnc = osl_getThreadTextEncoding();
696 // char array delimited by \0.
697 // app \0 topic \0 item \0 (extra \0) where the extra is optional.
698 ::std::vector<OUString> aStrs;
699 const char* pStart = p;
700 sal_Int32 nStart = 0;
701 for (sal_Int32 i = 0; i < nSeqLen; ++i, ++p)
703 if (*p == '\0')
705 sal_Int32 nLen = i - nStart;
706 aStrs.emplace_back(pStart, nLen, eSysEnc);
707 nStart = ++i;
708 pStart = ++p;
712 if (aStrs.size() < 3)
713 return false;
715 const OUString* pApp = &aStrs[0];
716 const OUString* pTopic = &aStrs[1];
717 const OUString* pItem = &aStrs[2];
718 const OUString* pExtra = nullptr;
719 if (aStrs.size() > 3)
720 pExtra = &aStrs[3];
722 if ( pExtra && *pExtra == "calc:extref" )
724 // Paste this as an external reference. Note that paste link always
725 // uses Calc A1 syntax even when another formula syntax is specified
726 // in the UI.
727 EnterMatrix("='"
728 + ScGlobal::GetAbsDocName(*pTopic, GetViewData().GetDocument()->GetDocumentShell())
729 + "'#" + *pItem
730 , ::formula::FormulaGrammar::GRAM_NATIVE);
731 return true;
733 else
735 // DDE in all other cases.
737 // TODO: we could define ocQuote for "
738 EnterMatrix("=" + ScCompiler::GetNativeSymbol(ocDde)
739 + ScCompiler::GetNativeSymbol(ocOpen)
740 + "\"" + *pApp + "\""
741 + ScCompiler::GetNativeSymbol(ocSep)
742 + "\"" + *pTopic + "\""
743 + ScCompiler::GetNativeSymbol(ocSep)
744 + "\"" + *pItem + "\""
745 + ScCompiler::GetNativeSymbol(ocClose)
746 , ::formula::FormulaGrammar::GRAM_NATIVE);
749 // mark range
751 SCTAB nTab = GetViewData().GetTabNo();
752 SCCOL nCurX = GetViewData().GetCurX();
753 SCROW nCurY = GetViewData().GetCurY();
754 HideAllCursors();
755 DoneBlockMode();
756 InitBlockMode( nCurX, nCurY, nTab );
757 MarkCursor( nCurX+static_cast<SCCOL>(nCols)-1, nCurY+static_cast<SCROW>(nRows)-1, nTab );
758 ShowAllCursors();
759 CursorPosChanged();
761 return true;
764 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */