Coverage Report

Created: 2026-07-10 11:04

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