Coverage Report

Created: 2026-08-14 10:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sw/source/uibase/dochdl/swdtflvr.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 <config_features.h>
21
22
#include <com/sun/star/embed/XTransactedObject.hpp>
23
#include <com/sun/star/embed/Aspects.hpp>
24
#include <com/sun/star/embed/XEmbedObjectClipboardCreator.hpp>
25
#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
26
#include <com/sun/star/embed/MSOLEObjectSystemCreator.hpp>
27
#include <com/sun/star/text/XPasteListener.hpp>
28
29
#include <officecfg/Office/Writer.hxx>
30
31
#include <svtools/embedtransfer.hxx>
32
#include <svtools/insdlg.hxx>
33
#include <unotools/tempfile.hxx>
34
#include <comphelper/fileformat.h>
35
#include <comphelper/processfactory.hxx>
36
#include <comphelper/propertyvalue.hxx>
37
#include <comphelper/servicehelper.hxx>
38
#include <comphelper/storagehelper.hxx>
39
#include <comphelper/string.hxx>
40
#include <o3tl/deleter.hxx>
41
#include <o3tl/temporary.hxx>
42
#include <unotools/ucbstreamhelper.hxx>
43
#include <sot/filelist.hxx>
44
#include <svx/svxdlg.hxx>
45
#include <toolkit/helper/vclunohelper.hxx>
46
#include <sfx2/linkmgr.hxx>
47
#include <tools/urlobj.hxx>
48
#include <vcl/weld/MessageDialog.hxx>
49
#include <sfx2/dispatch.hxx>
50
#include <sfx2/viewfrm.hxx>
51
#include <svl/stritem.hxx>
52
#include <vcl/imap.hxx>
53
#include <sot/storage.hxx>
54
#include <vcl/graph.hxx>
55
#include <svl/urihelper.hxx>
56
#include <svx/svdmodel.hxx>
57
#include <svx/xmlexchg.hxx>
58
#include <svx/dbaexchange.hxx>
59
#include <svx/clipfmtitem.hxx>
60
#include <sfx2/mieclip.hxx>
61
#include <svl/urlbmk.hxx>
62
#include <unicode/regex.h>
63
#include <vcl/inetimg.hxx>
64
#include <svx/fmview.hxx>
65
#include <sfx2/docfilt.hxx>
66
#include <vcl/imapobj.hxx>
67
#include <sfx2/docfile.hxx>
68
#include <unotools/transliterationwrapper.hxx>
69
#include <unotools/streamwrap.hxx>
70
#include <vcl/graphicfilter.hxx>
71
72
#ifdef _WIN32
73
#include <prewin.h>
74
#include <postwin.h>
75
#include <o3tl/char16_t2wchar_t.hxx>
76
#include <osl/file.hxx>
77
#include <systools/win32/extended_max_path.hxx>
78
#endif
79
80
#include <svx/unomodel.hxx>
81
#include <fmturl.hxx>
82
#include <fmtinfmt.hxx>
83
#include <swdtflvr.hxx>
84
#include <shellio.hxx>
85
#include <ddefld.hxx>
86
#include <doc.hxx>
87
#include <IDocumentUndoRedo.hxx>
88
#include <IDocumentDrawModelAccess.hxx>
89
#include <IDocumentFieldsAccess.hxx>
90
#include <IDocumentRedlineAccess.hxx>
91
#include <IDocumentState.hxx>
92
#include <IMark.hxx>
93
#include <section.hxx>
94
#include <ndtxt.hxx>
95
#include <edtdd.hxx>
96
#include <edtwin.hxx>
97
#include <navicont.hxx>
98
#include <swcont.hxx>
99
#include <wrtsh.hxx>
100
#include <swmodule.hxx>
101
#include <view.hxx>
102
#include <docsh.hxx>
103
#include <wdocsh.hxx>
104
#include <fldbas.hxx>
105
#include <swundo.hxx>
106
#include <pam.hxx>
107
#include <ndole.hxx>
108
#include <swwait.hxx>
109
#include <viewopt.hxx>
110
#include <SwCapObjType.hxx>
111
#include <cmdid.h>
112
#include <strings.hrc>
113
#include <svx/svditer.hxx>
114
#include <editeng/eeitem.hxx>
115
#include <editeng/fhgtitem.hxx>
116
#include <editeng/prntitem.hxx>
117
#include <svx/svdpage.hxx>
118
#include <avmedia/mediawindow.hxx>
119
#include <swcrsr.hxx>
120
#include <SwRewriter.hxx>
121
#include <vcl/svapp.hxx>
122
#include <swserv.hxx>
123
#include <fmtmeta.hxx>
124
#include <itabenum.hxx>
125
#include <iodetect.hxx>
126
#include <unotextrange.hxx>
127
#include <unoframe.hxx>
128
#include <txatbase.hxx>
129
#include <unoparaframeenum.hxx>
130
#include <vcl/uitest/logger.hxx>
131
#include <vcl/uitest/eventdescription.hxx>
132
133
#include <vcl/GraphicNativeTransform.hxx>
134
#include <vcl/GraphicNativeMetadata.hxx>
135
#include <vcl/TypeSerializer.hxx>
136
#include <comphelper/lok.hxx>
137
#include <sfx2/classificationhelper.hxx>
138
#include <sfx2/sfxdlg.hxx>
139
#include <comphelper/classids.hxx>
140
#include <osl/diagnose.h>
141
142
#include <memory>
143
144
/* default (A4 format) width of 210mm - 2 * border size (border on both sides) */
145
constexpr tools::Long constOleWidthInMm = 210 - 2 * lMinBorderInMm;
146
147
constexpr Size constOleSize100mm(
148
    constOleWidthInMm * 100, // convert from mm to 100mm
149
    3000 // 3 cm
150
);
151
152
constexpr Size constOleSizeTwip = o3tl::convert(constOleSize100mm, o3tl::Length::mm100, o3tl::Length::twip);
153
154
constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_DRAWMODEL = 0x00000001;
155
constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_HTML      = 0x00000002;
156
constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_RTF       = 0x00000004;
157
constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_STRING    = 0x00000008;
158
constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_SWOLE     = 0x00000010;
159
constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_DDE       = 0x00000020;
160
constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_RICHTEXT  = 0x00000040;
161
constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_MARKDOWN  = 0x00000080;
162
163
using namespace ::svx;
164
using namespace ::com::sun::star;
165
using namespace ::com::sun::star::uno;
166
using namespace ::com::sun::star::datatransfer;
167
namespace {
168
169
void collectUIInformation(const OUString& rAction, const OUString& aParameters)
170
0
{
171
0
    EventDescription aDescription;
172
0
    aDescription.aAction = rAction;
173
0
    aDescription.aParameters = {{"parameters", aParameters}};
174
0
    aDescription.aID = "writer_edit";
175
0
    aDescription.aKeyWord = "SwEditWinUIObject";
176
0
    aDescription.aParent = "MainWindow";
177
0
    UITestLogger::getInstance().logEvent(aDescription);
178
0
}
179
180
}
181
182
class SwTransferDdeLink : public ::sfx2::SvBaseLink
183
{
184
    OUString m_sName;
185
    ::sfx2::SvLinkSourceRef m_xRefObj;
186
    SwTransferable& m_rTransfer;
187
    SwDocShell* m_pDocShell;
188
    sal_uLong m_nOldTimeOut;
189
    bool m_bDelBookmark : 1;
190
    bool m_bInDisconnect : 1;
191
192
    bool FindDocShell();
193
194
    using sfx2::SvBaseLink::Disconnect;
195
196
protected:
197
    virtual ~SwTransferDdeLink() override;
198
199
public:
200
    SwTransferDdeLink( SwTransferable& rTrans, SwWrtShell& rSh );
201
202
    virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
203
        const OUString& rMimeType, const css::uno::Any & rValue ) override;
204
    virtual void Closed() override;
205
206
    bool WriteData( SvStream& rStrm );
207
208
    void Disconnect( bool bRemoveDataAdvise );
209
};
210
211
/// Tracks the boundaries of pasted content and notifies listeners.
212
class SwPasteContext
213
{
214
public:
215
    SwPasteContext(SwWrtShell& rWrtShell);
216
    ~SwPasteContext();
217
218
    void remember();
219
    void forget();
220
221
private:
222
    SwWrtShell& m_rWrtShell;
223
    std::optional<SwPaM> m_oPaM;
224
    sal_Int32 m_nStartContent = 0;
225
};
226
227
namespace {
228
229
// helper class for Action and Undo enclosing
230
class SwTrnsfrActionAndUndo
231
{
232
    SwWrtShell *pSh;
233
public:
234
    SwTrnsfrActionAndUndo( SwWrtShell *pS, bool bDelSel = false, SwPasteContext* pContext = nullptr)
235
0
        : pSh( pS )
236
0
    {
237
0
        pSh->StartUndo( SwUndoId::PASTE_CLIPBOARD );
238
0
        if( bDelSel )
239
0
        {
240
0
            if (pContext)
241
0
                pContext->forget();
242
0
            pSh->DelRight();
243
0
            if (pContext)
244
0
                pContext->remember();
245
0
        }
246
0
        pSh->StartAllAction();
247
0
    }
248
    ~SwTrnsfrActionAndUndo() COVERITY_NOEXCEPT_FALSE
249
0
    {
250
0
        pSh->EndUndo();
251
0
        pSh->EndAllAction();
252
0
    }
253
};
254
255
}
256
257
SwTransferable::SwTransferable( SwWrtShell& rSh )
258
0
    : m_pWrtShell( &rSh ),
259
0
    m_pCreatorView( nullptr ),
260
0
    m_pOrigGraphic( nullptr ),
261
0
    m_eBufferType( TransferBufferType::NONE ),
262
0
    m_bOldIdle(false),
263
0
    m_bCleanUp(false)
264
0
{
265
0
    rSh.GetView().AddTransferable(*this);
266
0
    SwDocShell* pDShell = rSh.GetDoc()->GetDocShell();
267
0
    if( !pDShell )
268
0
        return;
269
270
0
    pDShell->FillTransferableObjectDescriptor( m_aObjDesc );
271
0
    if( pDShell->GetMedium() )
272
0
    {
273
0
        const INetURLObject& rURLObj = pDShell->GetMedium()->GetURLObject();
274
0
        m_aObjDesc.maDisplayName = URIHelper::removePassword(
275
0
                            rURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
276
0
                            INetURLObject::EncodeMechanism::WasEncoded,
277
0
                            INetURLObject::DecodeMechanism::Unambiguous );
278
0
    }
279
280
0
    PrepareOLE( m_aObjDesc );
281
0
}
282
283
SwTransferable::~SwTransferable()
284
0
{
285
0
    SolarMutexGuard aSolarGuard;
286
287
    // the DDELink still needs the WrtShell!
288
0
    DisconnectDDE();
289
290
0
    m_pWrtShell = nullptr;
291
292
    // release reference to the document so that aDocShellRef will delete
293
    // it (if aDocShellRef is set). Otherwise, the OLE nodes keep references
294
    // to their sub-storage when the storage is already dead.
295
0
    m_pClpDocFac.reset();
296
297
    // first close, then the Ref. can be cleared as well, so that
298
    // the DocShell really gets deleted!
299
0
    if( m_aDocShellRef.Is() )
300
0
    {
301
0
        SfxObjectShell * pObj = m_aDocShellRef;
302
0
        SwDocShell* pDocSh = static_cast<SwDocShell*>(pObj);
303
0
        pDocSh->DoClose();
304
0
    }
305
0
    m_aDocShellRef.Clear();
306
307
0
    if (SwModule* pMod = SwModule::get())
308
0
    {
309
0
        if ( pMod->m_pDragDrop == this )
310
0
            pMod->m_pDragDrop = nullptr;
311
0
        else if ( pMod->m_pXSelection == this )
312
0
            pMod->m_pXSelection = nullptr;
313
0
    }
314
315
0
    m_eBufferType = TransferBufferType::NONE;
316
0
}
317
318
static SwDoc& lcl_GetDoc(SwDocFac & rDocFac)
319
0
{
320
0
    SwDoc& rDoc = rDocFac.GetDoc();
321
0
    rDoc.SetClipBoard( true );
322
0
    return rDoc;
323
0
}
324
325
void SwTransferable::ObjectReleased()
326
0
{
327
0
    SwModule* pMod = SwModule::get();
328
0
    if (!pMod)
329
0
        return;
330
0
    if( this == pMod->m_pDragDrop )
331
0
        pMod->m_pDragDrop = nullptr;
332
0
    else if( this == pMod->m_pXSelection )
333
0
        pMod->m_pXSelection = nullptr;
334
0
}
335
336
void SwTransferable::AddSupportedFormats()
337
0
{
338
    // only need if we are the current XSelection Object
339
0
    if (this == SwModule::get()->m_pXSelection || comphelper::LibreOfficeKit::isActive())
340
0
    {
341
0
        SetDataForDragAndDrop( Point( 0,0) );
342
0
    }
343
0
}
344
345
void SwTransferable::InitOle( SfxObjectShell* pDoc )
346
0
{
347
    //set OleVisArea. Upper left corner of the page and size of
348
    //RealSize in Twips.
349
0
    const Size aSz(constOleSizeTwip);
350
0
    SwRect aVis( Point( DOCUMENTBORDER, DOCUMENTBORDER ), aSz );
351
0
    pDoc->SetVisArea( aVis.SVRect() );
352
0
}
353
354
uno::Reference < embed::XEmbeddedObject > SwTransferable::FindOLEObj( sal_Int64& nAspect ) const
355
0
{
356
0
    uno::Reference < embed::XEmbeddedObject > xObj;
357
0
    if( m_pClpDocFac )
358
0
    {
359
0
        SwIterator<SwContentNode,SwFormatColl> aIter( *m_pClpDocFac->GetDoc().GetDfltGrfFormatColl() );
360
0
        for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
361
0
            if( SwNodeType::Ole == pNd->GetNodeType() )
362
0
            {
363
0
                xObj = static_cast<SwOLENode*>(pNd)->GetOLEObj().GetOleRef();
364
0
                nAspect = static_cast<SwOLENode*>(pNd)->GetAspect();
365
0
                break;
366
0
            }
367
0
    }
368
0
    return xObj;
369
0
}
370
371
const Graphic* SwTransferable::FindOLEReplacementGraphic() const
372
0
{
373
0
    if( m_pClpDocFac )
374
0
    {
375
0
        SwIterator<SwContentNode,SwFormatColl> aIter( *m_pClpDocFac->GetDoc().GetDfltGrfFormatColl() );
376
0
        for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
377
0
            if( SwNodeType::Ole == pNd->GetNodeType() )
378
0
            {
379
0
                return static_cast<SwOLENode*>(pNd)->GetGraphic();
380
0
            }
381
0
    }
382
383
0
    return nullptr;
384
0
}
385
386
void SwTransferable::RemoveDDELinkFormat(vcl::Window& rWin)
387
0
{
388
0
    RemoveFormat( SotClipboardFormatId::LINK );
389
0
    if (rWin.GetClipboard()->getContents().get() == this)
390
0
        CopyToClipboard(&rWin);
391
0
}
392
393
void SwTransferable::DisconnectDDE()
394
0
{
395
0
    if( m_xDdeLink.is() )
396
0
    {
397
0
        m_xDdeLink->Disconnect( true );
398
0
        m_xDdeLink.clear();
399
0
    }
400
0
}
401
402
namespace
403
{
404
    //Resolves: fdo#40717 surely when we create a clipboard document we should
405
    //overwrite the clipboard documents styles and settings with that of the
406
    //source, so that we can WYSIWYG paste. If we want that the destinations
407
    //styles are used over the source styles, that's a matter of the
408
    //destination paste code to handle, not the source paste code.
409
    void lclOverWriteDoc(SwWrtShell &rSrcWrtShell, SwDoc &rDest, bool bDeleteRedlines = true)
410
0
    {
411
0
        const SwDoc &rSrc = *rSrcWrtShell.GetDoc();
412
413
0
        rDest.ReplaceCompatibilityOptions(rSrc);
414
0
        rDest.ReplaceDefaults(rSrc);
415
416
        //It would probably make most sense here to only insert the styles used
417
        //by the selection, e.g. apply SwDoc::IsUsed on styles ?
418
0
        rDest.ReplaceStyles(rSrc, false);
419
420
0
        rSrcWrtShell.Copy(rDest, /*pNewClpText=*/nullptr, bDeleteRedlines);
421
422
0
        rDest.GetMetaFieldManager().copyDocumentProperties(rSrc);
423
0
    }
424
425
    void lclCheckAndPerformRotation(Graphic& aGraphic)
426
0
    {
427
0
        GraphicNativeMetadata aMetadata;
428
0
        if ( !aMetadata.read(aGraphic) )
429
0
            return;
430
431
0
        Degree10 aRotation = aMetadata.getRotation();
432
0
        if (aRotation)
433
0
        {
434
0
            GraphicNativeTransform aTransform( aGraphic );
435
0
            aTransform.rotate( aRotation );
436
0
        }
437
0
    }
438
}
439
440
sal_Bool SAL_CALL SwTransferable::isComplex()
441
0
{
442
0
    sal_Int32 nTextLength = 0;
443
0
    SwNodes& aNodes = m_pWrtShell->GetDoc()->GetNodes();
444
0
    for (SwPaM& rPaM : m_pWrtShell->GetCursor()->GetRingContainer())
445
0
    {
446
0
        for (SwNodeOffset nIndex = rPaM.GetMark()->GetNodeIndex();
447
0
             nIndex <= rPaM.GetPoint()->GetNodeIndex(); ++nIndex)
448
0
        {
449
0
            SwNode& rNd = *aNodes[nIndex];
450
451
0
            SwTextNode* pTextNode = rNd.GetTextNode();
452
0
            if (pTextNode)
453
0
            {
454
0
                if (pTextNode->HasHints())
455
0
                {
456
0
                    for (size_t nHint = 0; nHint < pTextNode->GetSwpHints().Count(); ++nHint)
457
0
                    {
458
0
                        SwTextAttr* pHint = pTextNode->GetSwpHints().Get(nHint);
459
0
                        if (pHint->Which() == RES_TXTATR_FLYCNT)
460
0
                        {
461
0
                            return true; // Complex
462
0
                        }
463
0
                    }
464
0
                }
465
466
0
                FrameClientSortList_t vFrames;
467
0
                ::CollectFrameAtNode(rNd, vFrames, true);
468
0
                if (!vFrames.empty())
469
0
                {
470
                    // There is an at-char anchored object to this node, that's complex.
471
0
                    return true;
472
0
                }
473
474
0
                nTextLength += pTextNode->GetText().getLength();
475
0
                if (nTextLength >= 1024 * 512)
476
0
                    return true; // Complex
477
0
            }
478
0
        }
479
0
    }
480
481
0
    if (m_pWrtShell->GetSelectionType() == SelectionType::DrawObject)
482
0
        return true; // Complex
483
484
    // Simple
485
0
    return false;
486
0
}
487
488
bool SwTransferable::GetData( const DataFlavor& rFlavor, const OUString& rDestDoc )
489
0
{
490
0
    SotClipboardFormatId nFormat = SotExchange::GetFormat( rFlavor );
491
492
    // we can only fulfil the request if
493
    // 1) we have data for this format
494
    // 2) we have either a clipboard document (pClpDocFac), or
495
    //    we have a SwWrtShell (so we can generate a new clipboard document)
496
0
    if( !HasFormat( nFormat ) || ( m_pClpDocFac == nullptr && m_pWrtShell == nullptr ) )
497
0
        return false;
498
499
0
    if( !m_pClpDocFac )
500
0
    {
501
0
        SelectionType nSelectionType = m_pWrtShell->GetSelectionType();
502
503
        // when pending we will not get the correct type, but SelectionType::Text
504
        // as fallback. This *happens* during D&D, so we need to check if we are in
505
        // the fallback and just try to get a graphic
506
0
        const bool bPending(m_pWrtShell->ActionPend());
507
508
        // SEL_GRF is from ContentType of editsh
509
0
        if(bPending || ((SelectionType::Graphic | SelectionType::DrawObject | SelectionType::DbForm) & nSelectionType))
510
0
        {
511
0
            m_oClpGraphic.emplace();
512
0
            if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_oClpGraphic ))
513
0
                m_pOrigGraphic = &*m_oClpGraphic;
514
0
            m_oClpBitmap.emplace();
515
0
            if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_oClpBitmap ))
516
0
                m_pOrigGraphic = &*m_oClpBitmap;
517
518
            // is it a URL-Button ?
519
0
            OUString sURL;
520
0
            OUString sDesc;
521
0
            if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) )
522
0
            {
523
0
                m_oBookmark.emplace( sURL, sDesc );
524
0
                m_eBufferType = TransferBufferType::InetField;
525
0
            }
526
0
        }
527
528
0
        m_pClpDocFac.reset(new SwDocFac);
529
0
        SwDoc& rTmpDoc = lcl_GetDoc(*m_pClpDocFac);
530
531
0
        rTmpDoc.getIDocumentFieldsAccess().LockExpFields();     // never update fields - leave text as it is
532
0
        lclOverWriteDoc(*m_pWrtShell, rTmpDoc);
533
534
        // in CORE a new one was created (OLE-objects copied!)
535
0
        m_aDocShellRef = rTmpDoc.GetTmpDocShell();
536
0
        if( m_aDocShellRef.Is() )
537
0
            SwTransferable::InitOle( m_aDocShellRef );
538
0
        rTmpDoc.SetTmpDocShell( nullptr );
539
540
0
        if( nSelectionType & SelectionType::Text && !m_pWrtShell->HasMark() )
541
0
        {
542
0
            SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
543
544
0
            Point aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY());
545
546
0
            bool bSelect = g_bExecuteDrag &&
547
0
                            m_pWrtShell->GetView().GetDocShell() &&
548
0
                            !m_pWrtShell->GetView().GetDocShell()->IsReadOnly();
549
0
            if( m_pWrtShell->GetContentAtPos( aPos, aContentAtPos, bSelect ) )
550
0
            {
551
0
                m_oBookmark.emplace(
552
0
                        static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)->GetValue(),
553
0
                        aContentAtPos.sStr );
554
0
                m_eBufferType = TransferBufferType::InetField;
555
0
                if( bSelect )
556
0
                    m_pWrtShell->SelectTextAttr( RES_TXTATR_INETFMT );
557
0
            }
558
0
        }
559
0
        if( m_pWrtShell->IsFrameSelected() )
560
0
        {
561
0
            SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_URL, RES_URL>( m_pWrtShell->GetAttrPool() ));
562
0
            m_pWrtShell->GetFlyFrameAttr( aSet );
563
0
            const SwFormatURL& rURL = aSet.Get( RES_URL );
564
0
            if( rURL.GetMap() )
565
0
                m_pImageMap.reset(new ImageMap( *rURL.GetMap() ));
566
0
            else if( !rURL.GetURL().isEmpty() )
567
0
                m_pTargetURL.reset(new INetImage(OUString(), rURL.GetURL(),
568
0
                                            rURL.GetTargetFrameName() ));
569
0
        }
570
0
    }
571
572
0
    bool bOK = false;
573
0
    if( TransferBufferType::Ole == m_eBufferType )
574
0
    {
575
        //TODO/MBA: testing - is this the "single OLE object" case?!
576
        // get OLE-Object from ClipDoc and get the data from that.
577
0
        sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT; // will be set in the next statement
578
0
        uno::Reference < embed::XEmbeddedObject > xObj = FindOLEObj( nAspect );
579
0
        const Graphic* pOLEGraph = FindOLEReplacementGraphic();
580
0
        if( xObj.is() )
581
0
        {
582
0
            TransferableDataHelper aD( new SvEmbedTransferHelper( xObj, pOLEGraph, nAspect ) );
583
0
            uno::Any aAny = aD.GetAny(rFlavor, rDestDoc);
584
0
            if( aAny.hasValue() )
585
0
                bOK = SetAny( aAny );
586
0
        }
587
588
        // the following solution will be used in the case when the object can not generate the image
589
        // TODO/LATER: in future the transferhelper must probably be created based on object and the replacement stream
590
        // TODO: Block not required now, SvEmbedTransferHelper should be able to handle GDIMetaFile format
591
0
        if ( nFormat == SotClipboardFormatId::GDIMETAFILE )
592
0
        {
593
0
            pOLEGraph = FindOLEReplacementGraphic();
594
0
            if ( pOLEGraph )
595
0
                bOK = SetGDIMetaFile( pOLEGraph->GetGDIMetaFile() );
596
0
        }
597
0
    }
598
0
    else
599
0
    {
600
0
        switch( nFormat )
601
0
        {
602
0
        case SotClipboardFormatId::LINK:
603
0
            if( m_xDdeLink.is() )
604
0
                bOK = SetObject( m_xDdeLink.get(), SWTRANSFER_OBJECTTYPE_DDE, rFlavor );
605
0
            break;
606
607
0
        case SotClipboardFormatId::OBJECTDESCRIPTOR:
608
0
        case SotClipboardFormatId::LINKSRCDESCRIPTOR:
609
0
            bOK = SetTransferableObjectDescriptor( m_aObjDesc );
610
0
            break;
611
612
0
        case SotClipboardFormatId::DRAWING:
613
0
            {
614
0
                SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
615
0
                bOK = SetObject( rDoc.getIDocumentDrawModelAccess().GetDrawModel(),
616
0
                                SWTRANSFER_OBJECTTYPE_DRAWMODEL, rFlavor );
617
0
            }
618
0
            break;
619
620
0
        case SotClipboardFormatId::STRING:
621
0
        {
622
0
            SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
623
0
            bOK = SetObject( &rDoc, SWTRANSFER_OBJECTTYPE_STRING, rFlavor );
624
0
        }
625
0
        break;
626
0
        case SotClipboardFormatId::RTF:
627
0
        {
628
0
            SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
629
0
            bOK = SetObject( &rDoc, SWTRANSFER_OBJECTTYPE_RTF, rFlavor );
630
0
        }
631
0
        break;
632
0
        case SotClipboardFormatId::RICHTEXT:
633
0
        {
634
0
            SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
635
0
            bOK = SetObject( &rDoc, SWTRANSFER_OBJECTTYPE_RICHTEXT, rFlavor );
636
0
        }
637
0
        break;
638
639
0
        case SotClipboardFormatId::MARKDOWN:
640
0
        {
641
0
            SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
642
0
            bOK = SetObject(&rDoc, SWTRANSFER_OBJECTTYPE_MARKDOWN, rFlavor);
643
0
            break;
644
0
        }
645
646
0
        case SotClipboardFormatId::HTML:
647
0
        {
648
0
            SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
649
0
            bOK = SetObject( &rDoc, SWTRANSFER_OBJECTTYPE_HTML, rFlavor );
650
0
        }
651
0
            break;
652
653
0
        case SotClipboardFormatId::SVXB:
654
0
            if( m_eBufferType & TransferBufferType::Graphic && m_pOrigGraphic )
655
0
                bOK = SetGraphic( *m_pOrigGraphic );
656
0
            break;
657
658
0
        case SotClipboardFormatId::GDIMETAFILE:
659
0
            if( m_eBufferType & TransferBufferType::Graphic )
660
0
                bOK = SetGDIMetaFile( m_oClpGraphic->GetGDIMetaFile() );
661
0
            break;
662
0
        case SotClipboardFormatId::BITMAP:
663
0
        case SotClipboardFormatId::PNG:
664
            // Neither pClpBitmap nor pClpGraphic are necessarily set
665
0
            if( (m_eBufferType & TransferBufferType::Graphic) && (m_oClpBitmap || m_oClpGraphic))
666
0
                bOK = SetBitmap((m_oClpBitmap ? m_oClpBitmap : m_oClpGraphic)->GetBitmap(), rFlavor);
667
0
            break;
668
669
0
        case SotClipboardFormatId::SVIM:
670
0
            if( m_pImageMap )
671
0
                bOK = SetImageMap( *m_pImageMap );
672
0
            break;
673
674
0
        case SotClipboardFormatId::INET_IMAGE:
675
0
            if( m_pTargetURL )
676
0
                bOK = SetINetImage( *m_pTargetURL, rFlavor );
677
0
            break;
678
679
0
        case SotClipboardFormatId::SOLK:
680
0
        case SotClipboardFormatId::NETSCAPE_BOOKMARK:
681
0
        case SotClipboardFormatId::FILEGRPDESCRIPTOR:
682
0
        case SotClipboardFormatId::FILECONTENT:
683
0
        case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
684
0
        case SotClipboardFormatId::SIMPLE_FILE:
685
0
            if( (TransferBufferType::InetField & m_eBufferType) && m_oBookmark )
686
0
                bOK = SetINetBookmark( *m_oBookmark, rFlavor );
687
0
            break;
688
689
0
        case SotClipboardFormatId::EMBED_SOURCE:
690
0
            if( !m_aDocShellRef.Is() )
691
0
            {
692
0
                SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
693
0
                m_aDocShellRef = new SwDocShell(rDoc, SfxObjectCreateMode::EMBEDDED);
694
0
                m_aDocShellRef->DoInitNew();
695
0
                SwTransferable::InitOle( m_aDocShellRef );
696
0
            }
697
0
            bOK = SetObject( &m_aDocShellRef, SWTRANSFER_OBJECTTYPE_SWOLE,
698
0
                            rFlavor );
699
0
            break;
700
0
        default: break;
701
0
        }
702
0
    }
703
0
    return bOK;
704
0
}
705
706
bool SwTransferable::WriteObject( SvStream& rOStream,
707
                                    void* pObject, sal_uInt32 nObjectType,
708
                                    const DataFlavor& /*rFlavor*/ )
709
0
{
710
0
    bool bRet = false;
711
0
    WriterRef xWrt;
712
713
0
    switch( nObjectType )
714
0
    {
715
0
    case SWTRANSFER_OBJECTTYPE_DRAWMODEL:
716
0
        {
717
            // don't change the sequence of commands
718
0
            SdrModel *pModel = static_cast<SdrModel*>(pObject);
719
0
            rOStream.SetBufferSize( 16348 );
720
721
            // for the changed pool defaults from drawing layer pool set those
722
            // attributes as hard attributes to preserve them for saving
723
0
            const SfxItemPool& rItemPool = pModel->GetItemPool();
724
0
            const SvxFontHeightItem& rDefaultFontHeight = rItemPool.GetUserOrPoolDefaultItem(EE_CHAR_FONTHEIGHT);
725
726
            // SW should have no MasterPages
727
0
            OSL_ENSURE(0 == pModel->GetMasterPageCount(), "SW with MasterPages (!)");
728
729
0
            for(sal_uInt16 a(0); a < pModel->GetPageCount(); a++)
730
0
            {
731
0
                const SdrPage* pPage = pModel->GetPage(a);
732
0
                SdrObjListIter aIter(pPage, SdrIterMode::DeepNoGroups);
733
734
0
                while(aIter.IsMore())
735
0
                {
736
0
                    SdrObject* pObj = aIter.Next();
737
0
                    const SvxFontHeightItem& rItem = pObj->GetMergedItem(EE_CHAR_FONTHEIGHT);
738
739
0
                    if(rItem.GetHeight() == rDefaultFontHeight.GetHeight())
740
0
                    {
741
0
                        pObj->SetMergedItem(rDefaultFontHeight);
742
0
                    }
743
0
                }
744
0
            }
745
746
0
            {
747
0
                uno::Reference<io::XOutputStream> xDocOut( new utl::OOutputStreamWrapper( rOStream ) );
748
0
                bRet = SvxDrawingLayerExport( pModel, xDocOut );
749
0
            }
750
751
0
            if (bRet)
752
0
                bRet = ERRCODE_NONE == rOStream.GetError();
753
0
        }
754
0
        break;
755
756
0
    case SWTRANSFER_OBJECTTYPE_SWOLE:
757
0
        {
758
0
            SfxObjectShell*   pEmbObj = static_cast<SfxObjectShell*>(pObject);
759
0
            try
760
0
            {
761
0
                ::utl::TempFileFast aTempFile;
762
0
                SvStream* pTempStream = aTempFile.GetStream(StreamMode::READWRITE);
763
0
                uno::Reference< embed::XStorage > xWorkStore =
764
0
                    ::comphelper::OStorageHelper::GetStorageFromStream( new utl::OStreamWrapper(*pTempStream), embed::ElementModes::READWRITE );
765
766
                // write document storage
767
0
                pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, false );
768
                // mba: no BaseURL for clipboard
769
0
                SfxMedium aMedium( xWorkStore, OUString() );
770
0
                pEmbObj->DoSaveObjectAs( aMedium, false );
771
0
                pEmbObj->DoSaveCompleted();
772
773
0
                uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY );
774
0
                if ( xTransact.is() )
775
0
                    xTransact->commit();
776
777
0
                rOStream.SetBufferSize( 0xff00 );
778
0
                rOStream.WriteStream( *pTempStream );
779
780
0
                xWorkStore->dispose();
781
0
                xWorkStore.clear();
782
0
            }
783
0
            catch (const uno::Exception&)
784
0
            {
785
0
            }
786
787
0
            bRet = ( rOStream.GetError() == ERRCODE_NONE );
788
0
        }
789
0
        break;
790
791
0
    case SWTRANSFER_OBJECTTYPE_DDE:
792
0
        {
793
0
            rOStream.SetBufferSize( 1024 );
794
0
            SwTransferDdeLink* pDdeLnk = static_cast<SwTransferDdeLink*>(pObject);
795
0
            if( pDdeLnk->WriteData( rOStream ) )
796
0
            {
797
0
                bRet = ERRCODE_NONE == rOStream.GetError();
798
0
            }
799
0
        }
800
0
        break;
801
802
0
    case SWTRANSFER_OBJECTTYPE_HTML:
803
0
    {
804
        // LOK is interested in getting images embedded for copy/paste support.
805
0
        GetHTMLWriter( comphelper::LibreOfficeKit::isActive() ? u"EmbedImages;NoPrettyPrint"_ustr : OUString(), OUString(), xWrt );
806
0
        break;
807
0
    }
808
809
0
    case SWTRANSFER_OBJECTTYPE_RTF:
810
0
    case SWTRANSFER_OBJECTTYPE_RICHTEXT:
811
0
        GetRTFWriter(std::u16string_view(), OUString(), xWrt);
812
0
        break;
813
814
0
    case SWTRANSFER_OBJECTTYPE_MARKDOWN:
815
0
    {
816
0
        GetMDWriter(std::u16string_view(), OUString(), xWrt);
817
0
        break;
818
0
    }
819
820
0
    case SWTRANSFER_OBJECTTYPE_STRING:
821
0
        GetASCWriter(std::u16string_view(), OUString(), xWrt);
822
0
        if( xWrt.is() )
823
0
        {
824
0
            SwAsciiOptions aAOpt;
825
0
            aAOpt.SetCharSet( RTL_TEXTENCODING_UTF8 );
826
0
            xWrt->SetAsciiOptions( aAOpt );
827
828
            // no start char for clipboard
829
0
            xWrt->m_bUCS2_WithStartChar = false;
830
0
        }
831
0
        break;
832
0
    default: break;
833
0
    }
834
835
0
    if( xWrt.is() )
836
0
    {
837
0
        SwDoc* pDoc = static_cast<SwDoc*>(pObject);
838
0
        xWrt->m_bWriteClipboardDoc = true;
839
0
        xWrt->m_bWriteOnlyFirstTable = bool(TransferBufferType::Table & m_eBufferType);
840
0
        xWrt->SetShowProgress(false);
841
842
#if defined(DEBUGPASTE)
843
        SvFileStream aPasteDebug(
844
            u"PASTEBUFFER.debug"_ustr, StreamMode::WRITE|StreamMode::TRUNC);
845
        SwWriter aDbgWrt( aPasteDebug, *pDoc );
846
        aDbgWrt.Write( xWrt );
847
#endif
848
849
0
        SwWriter aWrt( rOStream, *pDoc );
850
0
        if( ! aWrt.Write( xWrt ).IsError() )
851
0
        {
852
0
            rOStream.WriteChar( '\0' );               // terminate with a zero
853
0
            bRet = true;
854
0
        }
855
0
    }
856
857
0
    return bRet;
858
0
}
859
860
int SwTransferable::Cut()
861
0
{
862
0
    int nRet = Copy( true );
863
0
    if( nRet )
864
0
        DeleteSelection();
865
0
    collectUIInformation(u"CUT"_ustr, u"parameter"_ustr);
866
0
    return nRet;
867
0
}
868
869
void SwTransferable::DeleteSelection()
870
0
{
871
0
    if(!m_pWrtShell)
872
0
        return;
873
    // ask for type of selection before action-bracketing
874
0
    const SelectionType nSelection = m_pWrtShell->GetSelectionType();
875
    // cut rows or columns selected by enhanced table selection and wholly selected tables
876
0
    bool bCutMode = ( SelectionType::TableCell & nSelection ) && ( (SelectionType::TableRow | SelectionType::TableCol) & nSelection ||
877
0
        m_pWrtShell->HasWholeTabSelection() );
878
879
0
    m_pWrtShell->StartUndo( SwUndoId::START );
880
0
    if( bCutMode )
881
0
    {
882
0
        if( !(SelectionType::TableCol & nSelection) )
883
0
            m_pWrtShell->DeleteTable();
884
0
        else
885
0
        {
886
0
            SfxDispatcher* pDispatch = m_pWrtShell->GetView().GetViewFrame().GetDispatcher();
887
0
            pDispatch->Execute(FN_TABLE_DELETE_COL, SfxCallMode::SYNCHRON);
888
0
        }
889
0
    }
890
0
    else
891
0
    {
892
0
        if( ( SelectionType::Text | SelectionType::Table ) & nSelection )
893
0
            m_pWrtShell->IntelligentCut( nSelection );
894
0
        m_pWrtShell->DelRight();
895
0
    }
896
0
    m_pWrtShell->EndUndo( SwUndoId::END );
897
0
}
898
899
static void DeleteDDEAndReminderMarks(SwDoc & rDest)
900
0
{
901
0
    IDocumentMarkAccess *const pMarkAccess = rDest.getIDocumentMarkAccess();
902
0
    std::vector< ::sw::mark::MarkBase* > vMarks;
903
    // find all DDE-Bookmarks and Navigator-Reminders
904
0
    for (auto ppMark = pMarkAccess->getAllMarksBegin();
905
0
        ppMark != pMarkAccess->getAllMarksEnd();
906
0
        ++ppMark)
907
0
    {
908
0
        IDocumentMarkAccess::MarkType eMarkType = IDocumentMarkAccess::GetType(**ppMark);
909
0
        if (eMarkType == IDocumentMarkAccess::MarkType::DDE_BOOKMARK
910
0
            || eMarkType == IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER)
911
0
        {
912
0
            vMarks.push_back(*ppMark);
913
0
        }
914
0
    }
915
    // remove all DDE-Bookmarks, they are invalid inside the clipdoc!
916
    // and remove all Navigator-Reminders (tdf#165223)
917
0
    for (const auto& rpMark : vMarks)
918
0
    {
919
0
        pMarkAccess->deleteMark(rpMark);
920
0
    }
921
0
}
922
923
void SwTransferable::PrepareForCopyTextRange(SwPaM & rPaM)
924
0
{
925
0
    std::optional<SwWait> oWait;
926
0
    if (m_pWrtShell->ShouldWait())
927
0
    {
928
0
        oWait.emplace( *m_pWrtShell->GetView().GetDocShell(), true );
929
0
    }
930
931
0
    m_pClpDocFac.reset(new SwDocFac);
932
933
0
    SwDoc& rDest(lcl_GetDoc(*m_pClpDocFac));
934
0
    rDest.getIDocumentFieldsAccess().LockExpFields(); // Never update fields - leave text as is
935
0
    {
936
0
        SwDoc const& rSrc(*m_pWrtShell->GetDoc());
937
0
        assert(&rSrc == &rPaM.GetDoc());
938
939
0
        rDest.ReplaceCompatibilityOptions(rSrc);
940
0
        rDest.ReplaceDefaults(rSrc);
941
942
        //It would probably make most sense here to only insert the styles used
943
        //by the selection, e.g. apply SwDoc::IsUsed on styles ?
944
0
        rDest.ReplaceStyles(rSrc, false);
945
946
        // relevant bits of rSrcWrtShell.Copy(rDest);
947
0
        rDest.GetIDocumentUndoRedo().DoUndo(false); // always false!
948
0
        rDest.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );
949
950
0
        SwNodeIndex const aIdx(rDest.GetNodes().GetEndOfContent(), -1);
951
0
        SwContentNode *const pContentNode(aIdx.GetNode().GetContentNode());
952
0
        SwPosition aPos(aIdx, pContentNode, pContentNode ? pContentNode->Len() : 0);
953
954
0
        rSrc.getIDocumentContentOperations().CopyRange(rPaM, aPos, SwCopyFlags::CheckPosInFly);
955
956
0
        rDest.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::NONE );
957
958
0
        rDest.GetMetaFieldManager().copyDocumentProperties(rSrc);
959
0
    }
960
961
0
    DeleteDDEAndReminderMarks(rDest);
962
963
    // a new one was created in core (OLE objects copied!)
964
0
    m_aDocShellRef = rDest.GetTmpDocShell();
965
0
    if (m_aDocShellRef.Is())
966
0
        SwTransferable::InitOle( m_aDocShellRef );
967
0
    rDest.SetTmpDocShell( nullptr );
968
969
    // let's add some formats
970
0
    AddFormat( SotClipboardFormatId::EMBED_SOURCE );
971
0
    AddFormat( SotClipboardFormatId::RTF );
972
#if HAVE_FEATURE_DESKTOP
973
    AddFormat( SotClipboardFormatId::RICHTEXT );
974
    AddFormat( SotClipboardFormatId::HTML );
975
    AddFormat( SotClipboardFormatId::MARKDOWN );
976
#endif
977
0
    AddFormat( SotClipboardFormatId::STRING );
978
0
}
979
980
int SwTransferable::PrepareForCopy( bool bIsCut, bool bDeleteRedlines )
981
0
{
982
0
    int nRet = 1;
983
0
    if(!m_pWrtShell)
984
0
        return 0;
985
986
0
    if ( m_pWrtShell->GetTableInsertMode() != SwTable::SEARCH_NONE )
987
0
        m_pWrtShell->SetTableInsertMode( SwTable::SEARCH_NONE );
988
989
0
    if ( m_pWrtShell->GetTableCopied() )
990
0
        m_pWrtShell->SetTableCopied( false );
991
992
0
    OUString sGrfNm;
993
0
    const SelectionType nSelection = m_pWrtShell->GetSelectionType();
994
0
    if( nSelection == SelectionType::Graphic )
995
0
    {
996
0
        m_oClpGraphic.emplace();
997
0
        if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_oClpGraphic ))
998
0
            m_pOrigGraphic = &*m_oClpGraphic;
999
0
        m_oClpBitmap.emplace();
1000
0
        if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_oClpBitmap ))
1001
0
            m_pOrigGraphic = &*m_oClpBitmap;
1002
1003
0
        m_pClpDocFac.reset(new SwDocFac);
1004
0
        SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
1005
0
        m_pWrtShell->Copy(rDoc);
1006
1007
#if HAVE_FEATURE_DESKTOP
1008
        if (m_pOrigGraphic && !m_pOrigGraphic->GetBitmap().IsEmpty())
1009
          AddFormat( SotClipboardFormatId::SVXB );
1010
#endif
1011
1012
0
        PrepareOLE( m_aObjDesc );
1013
0
        AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
1014
1015
0
        const Graphic* pGrf = m_pWrtShell->GetGraphic();
1016
0
        if( pGrf && pGrf->IsSupportedGraphic() )
1017
0
        {
1018
0
            AddFormat( SotClipboardFormatId::PNG );
1019
#if HAVE_FEATURE_DESKTOP
1020
            AddFormat( SotClipboardFormatId::GDIMETAFILE );
1021
            AddFormat( SotClipboardFormatId::BITMAP );
1022
#endif
1023
0
        }
1024
0
        m_eBufferType = TransferBufferType::Graphic;
1025
0
        m_pWrtShell->GetGrfNms( &sGrfNm, nullptr );
1026
0
    }
1027
0
    else if ( nSelection == SelectionType::Ole )
1028
0
    {
1029
0
        m_pClpDocFac.reset(new SwDocFac);
1030
0
        SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
1031
0
        m_aDocShellRef = new SwDocShell(rDoc, SfxObjectCreateMode::EMBEDDED);
1032
0
        m_aDocShellRef->DoInitNew();
1033
0
        m_pWrtShell->Copy(rDoc);
1034
1035
0
        AddFormat( SotClipboardFormatId::EMBED_SOURCE );
1036
1037
        // --> OD #i98753#
1038
        // set size of embedded object at the object description structure
1039
0
        m_aObjDesc.maSize = o3tl::convert(m_pWrtShell->GetObjSize(), o3tl::Length::twip, o3tl::Length::mm100);
1040
1041
        // <--
1042
0
        PrepareOLE( m_aObjDesc );
1043
1044
#if HAVE_FEATURE_DESKTOP
1045
        AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
1046
        AddFormat( SotClipboardFormatId::GDIMETAFILE );
1047
1048
        // Fetch the formats supported via embedtransferhelper as well
1049
        sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
1050
        uno::Reference < embed::XEmbeddedObject > xObj = FindOLEObj( nAspect );
1051
        const Graphic* pOLEGraph = FindOLEReplacementGraphic();
1052
        if( xObj.is() )
1053
        {
1054
            TransferableDataHelper aD( new SvEmbedTransferHelper( xObj, pOLEGraph, nAspect ) );
1055
            if ( aD.GetTransferable().is() )
1056
            {
1057
                DataFlavorExVector              aVector( aD.GetDataFlavorExVector() );
1058
1059
                for( const auto& rItem : aVector )
1060
                    AddFormat( rItem );
1061
            }
1062
        }
1063
#endif
1064
0
        m_eBufferType = TransferBufferType::Ole;
1065
0
    }
1066
    // Is there anything to provide anyway?
1067
0
    else if ( m_pWrtShell->IsSelection() || m_pWrtShell->IsFrameSelected() ||
1068
0
              m_pWrtShell->GetSelectedObjCount() )
1069
0
    {
1070
0
        std::optional<SwWait> oWait;
1071
0
        if( m_pWrtShell->ShouldWait() )
1072
0
            oWait.emplace( *m_pWrtShell->GetView().GetDocShell(), true );
1073
1074
0
        m_pClpDocFac.reset(new SwDocFac);
1075
1076
        // create additional cursor so that equal treatment of keyboard
1077
        // and mouse selection is possible.
1078
        // In AddMode with keyboard selection, the new cursor is not created
1079
        // before the cursor is moved after end of selection.
1080
0
        if( m_pWrtShell->IsAddMode() && m_pWrtShell->SwCursorShell::HasSelection() )
1081
0
            m_pWrtShell->CreateCursor();
1082
1083
0
        SwDoc& rTmpDoc = lcl_GetDoc(*m_pClpDocFac);
1084
1085
0
        rTmpDoc.getIDocumentFieldsAccess().LockExpFields();     // Never update fields - leave text as is
1086
0
        lclOverWriteDoc(*m_pWrtShell, rTmpDoc, bDeleteRedlines);
1087
1088
0
        DeleteDDEAndReminderMarks(rTmpDoc);
1089
1090
        // a new one was created in CORE (OLE objects copied!)
1091
0
        m_aDocShellRef = rTmpDoc.GetTmpDocShell();
1092
0
        if( m_aDocShellRef.Is() )
1093
0
            SwTransferable::InitOle( m_aDocShellRef );
1094
0
        rTmpDoc.SetTmpDocShell( nullptr );
1095
1096
0
        if( m_pWrtShell->GetSelectedObjCount() )
1097
0
            m_eBufferType = TransferBufferType::Drawing;
1098
0
        else
1099
0
        {
1100
0
            m_eBufferType = TransferBufferType::Document;
1101
0
            if (m_pWrtShell->IntelligentCut(nSelection, false) != SwWrtShell::NO_WORD)
1102
0
                m_eBufferType = TransferBufferType::DocumentWord | m_eBufferType;
1103
0
        }
1104
1105
0
        bool bDDELink = m_pWrtShell->IsSelection();
1106
0
        if( nSelection & SelectionType::TableCell )
1107
0
        {
1108
0
            m_eBufferType = TransferBufferType::Table | m_eBufferType;
1109
0
            bDDELink = m_pWrtShell->HasWholeTabSelection();
1110
1111
0
            m_pWrtShell->SetTableCopied(true);
1112
1113
0
            if ( bIsCut && (SelectionType::TableRow | SelectionType::TableCol) & nSelection )
1114
0
                m_pWrtShell->SetTableInsertMode( (SelectionType::TableRow & nSelection) ? SwTable::SEARCH_ROW : SwTable::SEARCH_COL );
1115
0
        }
1116
1117
#if HAVE_FEATURE_DESKTOP
1118
        //When someone needs it, we 'OLE' him something
1119
        AddFormat( SotClipboardFormatId::EMBED_SOURCE );
1120
#endif
1121
1122
        //put RTF ahead of  the OLE's Metafile to have less loss
1123
0
        if( !m_pWrtShell->GetSelectedObjCount() )
1124
0
        {
1125
0
            AddFormat( SotClipboardFormatId::RTF );
1126
#if HAVE_FEATURE_DESKTOP
1127
            AddFormat( SotClipboardFormatId::RICHTEXT );
1128
            AddFormat( SotClipboardFormatId::HTML );
1129
            AddFormat( SotClipboardFormatId::MARKDOWN );
1130
#endif
1131
0
        }
1132
0
        if( m_pWrtShell->IsSelection() )
1133
0
            AddFormat( SotClipboardFormatId::STRING );
1134
1135
0
        if( nSelection & ( SelectionType::DrawObject | SelectionType::DbForm ))
1136
0
        {
1137
0
            AddFormat( SotClipboardFormatId::DRAWING );
1138
0
            if ( nSelection & SelectionType::DrawObject )
1139
0
            {
1140
#if HAVE_FEATURE_DESKTOP
1141
                AddFormat( SotClipboardFormatId::GDIMETAFILE );
1142
                AddFormat( SotClipboardFormatId::BITMAP );
1143
#endif
1144
0
                AddFormat( SotClipboardFormatId::PNG );
1145
0
            }
1146
0
            m_eBufferType = static_cast<TransferBufferType>( TransferBufferType::Graphic | m_eBufferType );
1147
1148
0
            m_oClpGraphic.emplace();
1149
0
            if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_oClpGraphic ))
1150
0
                m_pOrigGraphic = &*m_oClpGraphic;
1151
0
            m_oClpBitmap.emplace();
1152
0
            if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_oClpBitmap ))
1153
0
                m_pOrigGraphic = &*m_oClpBitmap;
1154
1155
            // is it a URL-Button ?
1156
0
            OUString sURL;
1157
0
            OUString sDesc;
1158
0
            if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) )
1159
0
            {
1160
0
                AddFormat( SotClipboardFormatId::STRING );
1161
#if HAVE_FEATURE_DESKTOP
1162
                AddFormat( SotClipboardFormatId::SOLK );
1163
                AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
1164
                AddFormat( SotClipboardFormatId::FILECONTENT );
1165
                AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
1166
#endif
1167
0
                AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
1168
0
                m_eBufferType = TransferBufferType::InetField | m_eBufferType;
1169
0
                nRet = 1;
1170
0
            }
1171
0
        }
1172
1173
        // at Cut, DDE-Link doesn't make sense!!
1174
0
        SwDocShell* pDShell;
1175
0
        if( !bIsCut && bDDELink &&
1176
0
            nullptr != ( pDShell = m_pWrtShell->GetDoc()->GetDocShell()) &&
1177
0
            SfxObjectCreateMode::STANDARD == pDShell->GetCreateMode() )
1178
0
        {
1179
#if HAVE_FEATURE_DESKTOP
1180
            AddFormat( SotClipboardFormatId::LINK );
1181
#endif
1182
0
            m_xDdeLink = new SwTransferDdeLink( *this, *m_pWrtShell );
1183
0
        }
1184
1185
        //ObjectDescriptor was already filly from the old DocShell.
1186
        //Now adjust it. Thus in GetData the first query can still
1187
        //be answered with delayed rendering.
1188
0
        m_aObjDesc.maSize = constOleSize100mm;
1189
1190
0
        PrepareOLE( m_aObjDesc );
1191
#if HAVE_FEATURE_DESKTOP
1192
        AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
1193
#endif
1194
0
    }
1195
0
    else
1196
0
        nRet = 0;
1197
1198
0
    if( m_pWrtShell->IsFrameSelected() )
1199
0
    {
1200
0
        SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_URL, RES_URL>( m_pWrtShell->GetAttrPool() ));
1201
0
        m_pWrtShell->GetFlyFrameAttr( aSet );
1202
0
        const SwFormatURL& rURL = aSet.Get( RES_URL );
1203
0
        if( rURL.GetMap() )
1204
0
        {
1205
0
            m_pImageMap.reset( new ImageMap( *rURL.GetMap() ) );
1206
0
            AddFormat( SotClipboardFormatId::SVIM );
1207
0
        }
1208
0
        else if( !rURL.GetURL().isEmpty() )
1209
0
        {
1210
0
            m_pTargetURL.reset(new INetImage( sGrfNm, rURL.GetURL(),
1211
0
                                        rURL.GetTargetFrameName() ));
1212
0
            AddFormat( SotClipboardFormatId::INET_IMAGE );
1213
0
        }
1214
0
    }
1215
1216
0
    return nRet;
1217
0
}
1218
1219
int SwTransferable::Copy( bool bIsCut, bool bDeleteRedlines )
1220
0
{
1221
0
    if (m_pWrtShell->GetView().GetObjectShell()->isContentExtractionLocked())
1222
0
        return 0;
1223
1224
0
    int nRet = PrepareForCopy( bIsCut, bDeleteRedlines );
1225
0
    if ( nRet )
1226
0
    {
1227
0
        CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
1228
0
    }
1229
1230
0
    if( !bIsCut ){
1231
0
        collectUIInformation(u"COPY"_ustr, u"parameter"_ustr);
1232
0
    }
1233
1234
0
    return nRet;
1235
0
}
1236
1237
void SwTransferable::CalculateAndCopy()
1238
0
{
1239
0
    if(!m_pWrtShell)
1240
0
        return;
1241
0
    SwWait aWait( *m_pWrtShell->GetView().GetDocShell(), true );
1242
1243
0
    OUString aStr( m_pWrtShell->Calculate() );
1244
1245
0
    m_pClpDocFac.reset(new SwDocFac);
1246
0
    SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
1247
0
    m_pWrtShell->Copy(rDoc, &aStr);
1248
0
    m_eBufferType = TransferBufferType::Document;
1249
0
    AddFormat( SotClipboardFormatId::STRING );
1250
1251
0
    CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
1252
0
}
1253
1254
bool SwTransferable::CopyGlossary( SwTextBlocks& rGlossary, const OUString& rStr )
1255
0
{
1256
0
    if(!m_pWrtShell)
1257
0
        return false;
1258
0
    SwWait aWait( *m_pWrtShell->GetView().GetDocShell(), true );
1259
1260
0
    m_pClpDocFac.reset(new SwDocFac);
1261
0
    SwDoc& rCDoc = lcl_GetDoc(*m_pClpDocFac);
1262
1263
0
    SwNodes& rNds = rCDoc.GetNodes();
1264
0
    SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
1265
0
    SwContentNode* pCNd = SwNodes::GoNext(&aNodeIdx); // go to 1st ContentNode
1266
0
    SwPaM aPam( *pCNd );
1267
1268
0
    rCDoc.getIDocumentFieldsAccess().LockExpFields();   // never update fields - leave text as it is
1269
1270
0
    rCDoc.InsertGlossary( rGlossary, rStr, aPam );
1271
1272
    // a new one was created in CORE (OLE-Objects copied!)
1273
0
    m_aDocShellRef = rCDoc.GetTmpDocShell();
1274
0
    if( m_aDocShellRef.Is() )
1275
0
        SwTransferable::InitOle( m_aDocShellRef );
1276
0
    rCDoc.SetTmpDocShell( nullptr );
1277
1278
0
    m_eBufferType = TransferBufferType::Document;
1279
1280
    //When someone needs it, we 'OLE' her something.
1281
0
    AddFormat( SotClipboardFormatId::EMBED_SOURCE );
1282
0
    AddFormat( SotClipboardFormatId::RTF );
1283
0
    AddFormat( SotClipboardFormatId::RICHTEXT );
1284
0
    AddFormat( SotClipboardFormatId::HTML );
1285
0
    AddFormat( SotClipboardFormatId::STRING );
1286
0
    AddFormat( SotClipboardFormatId::MARKDOWN );
1287
1288
    //ObjectDescriptor was already filled from the old DocShell.
1289
    //Now adjust it. Thus in GetData the first query can still
1290
    //be answered with delayed rendering.
1291
0
    m_aObjDesc.maSize = constOleSize100mm;
1292
1293
0
    PrepareOLE( m_aObjDesc );
1294
0
    AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
1295
1296
0
    CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
1297
1298
0
    return true;
1299
0
}
1300
1301
static uno::Reference < XTransferable > * lcl_getTransferPointer ( uno::Reference < XTransferable > &xRef )
1302
0
{
1303
0
    return &xRef;
1304
0
}
1305
1306
SwPasteContext::SwPasteContext(SwWrtShell& rWrtShell)
1307
0
    : m_rWrtShell(rWrtShell)
1308
0
{
1309
0
    remember();
1310
0
}
1311
1312
void SwPasteContext::remember()
1313
0
{
1314
0
    if (m_rWrtShell.GetPasteListeners().getLength() == 0)
1315
0
        return;
1316
1317
0
    SwPaM* pCursor = m_rWrtShell.GetCursor();
1318
0
    if (!pCursor)
1319
0
        return;
1320
1321
    // Set point to the previous node, so it is not moved.
1322
0
    const SwNode& rNode = pCursor->GetPoint()->GetNode();
1323
0
    m_oPaM.emplace(rNode, rNode, SwNodeOffset(0), SwNodeOffset(-1));
1324
0
    m_nStartContent = pCursor->GetPoint()->GetContentIndex();
1325
0
}
1326
1327
0
void SwPasteContext::forget() { m_oPaM.reset(); }
1328
1329
SwPasteContext::~SwPasteContext()
1330
0
{
1331
0
    try
1332
0
    {
1333
0
        if (m_rWrtShell.GetPasteListeners().getLength() == 0)
1334
0
            return;
1335
1336
0
        beans::PropertyValue aPropertyValue;
1337
1338
0
        switch (m_rWrtShell.GetView().GetShellMode())
1339
0
        {
1340
0
            case ShellMode::Graphic:
1341
0
            {
1342
0
                SwFrameFormat* pFormat = m_rWrtShell.GetFlyFrameFormat();
1343
0
                if (!pFormat)
1344
0
                    return;
1345
1346
0
                aPropertyValue.Name = "TextGraphicObject";
1347
0
                aPropertyValue.Value
1348
0
                    <<= uno::Reference<text::XTextContent>(SwXTextGraphicObject::CreateXTextGraphicObject(pFormat->GetDoc(), pFormat));
1349
0
                break;
1350
0
            }
1351
1352
0
            default:
1353
0
            {
1354
0
                if (!m_oPaM)
1355
0
                    return;
1356
1357
0
                SwPaM* pCursor = m_rWrtShell.GetCursor();
1358
0
                if (!pCursor)
1359
0
                    return;
1360
1361
0
                if (!pCursor->GetPoint()->GetNode().IsTextNode())
1362
                    // Non-text was pasted.
1363
0
                    return;
1364
1365
                // Update mark after paste.
1366
0
                *m_oPaM->GetMark() = *pCursor->GetPoint();
1367
1368
                // Restore point.
1369
0
                m_oPaM->GetPoint()->Adjust(SwNodeOffset(1));
1370
0
                SwNode& rNode = m_oPaM->GetPointNode();
1371
0
                if (!rNode.IsTextNode())
1372
                    // Starting point is no longer text.
1373
0
                    return;
1374
1375
0
                m_oPaM->GetPoint()->SetContent(m_nStartContent);
1376
1377
0
                aPropertyValue.Name = "TextRange";
1378
0
                const rtl::Reference<SwXTextRange> xTextRange = SwXTextRange::CreateXTextRange(
1379
0
                    m_oPaM->GetDoc(), *m_oPaM->GetPoint(), m_oPaM->GetMark());
1380
0
                aPropertyValue.Value <<= uno::Reference<text::XTextRange>(xTextRange);
1381
0
                break;
1382
0
            }
1383
0
        }
1384
1385
0
        if (aPropertyValue.Name.isEmpty())
1386
0
            return;
1387
1388
        // Invoke the listeners.
1389
0
        uno::Sequence<beans::PropertyValue> aEvent{ std::move(aPropertyValue) };
1390
0
        m_rWrtShell.GetPasteListeners().notifyEach( &css::text::XPasteListener::notifyPasteEvent, aEvent );
1391
0
    }
1392
0
    catch (const uno::Exception& rException)
1393
0
    {
1394
0
        SAL_WARN("sw",
1395
0
                 "SwPasteContext::~SwPasteContext: uncaught exception: " << rException.Message);
1396
0
    }
1397
0
}
1398
1399
bool SwTransferable::IsPaste( const SwWrtShell& rSh,
1400
                              const TransferableDataHelper& rData )
1401
0
{
1402
    // Check the common case first: We can always paste our own data!
1403
    // If _only_ the internal format can be pasted, this check will
1404
    // yield 'true', while the one below would give a (wrong) result 'false'.
1405
1406
0
    bool bIsPaste = ( GetSwTransferable( rData ) != nullptr );
1407
1408
    // if it's not our own data, we need to have a closer look:
1409
0
    if( ! bIsPaste )
1410
0
    {
1411
        // determine the proper paste action, and return true if we find one
1412
0
        uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
1413
1414
0
        SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
1415
0
        sal_uInt16 nSourceOptions =
1416
0
                    (( SotExchangeDest::DOC_TEXTFRAME == nDestination ||
1417
0
                       SotExchangeDest::SWDOC_FREE_AREA == nDestination ||
1418
0
                       SotExchangeDest::DOC_TEXTFRAME_WEB == nDestination ||
1419
0
                       SotExchangeDest::SWDOC_FREE_AREA_WEB == nDestination )
1420
0
                                    ? EXCHG_IN_ACTION_COPY
1421
0
                     : EXCHG_IN_ACTION_MOVE);
1422
1423
0
        SotClipboardFormatId nFormat;          // output param for GetExchangeAction
1424
0
        sal_uInt8 nEventAction;    // output param for GetExchangeAction
1425
0
        sal_uInt8 nAction = SotExchange::GetExchangeAction(
1426
0
                                rData.GetDataFlavorExVector(),
1427
0
                                nDestination,
1428
0
                                nSourceOptions,             /* ?? */
1429
0
                                EXCHG_IN_ACTION_DEFAULT,    /* ?? */
1430
0
                                nFormat, nEventAction, SotClipboardFormatId::NONE,
1431
0
                                lcl_getTransferPointer ( xTransferable ) );
1432
1433
        // if we find a suitable action, we can paste!
1434
0
        bIsPaste = (EXCHG_INOUT_ACTION_NONE != nAction);
1435
0
    }
1436
1437
0
    return bIsPaste;
1438
0
}
1439
1440
void SwTransferable::SelectPasteFormat(const TransferableDataHelper& rData, sal_uInt8& nAction,
1441
                                       SotClipboardFormatId& nFormat)
1442
0
{
1443
0
    if (nFormat != SotClipboardFormatId::RICHTEXT)
1444
0
    {
1445
0
        return;
1446
0
    }
1447
1448
0
    if (!rData.HasFormat(SotClipboardFormatId::EMBED_SOURCE))
1449
0
    {
1450
0
        return;
1451
0
    }
1452
1453
0
    if (!rData.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR))
1454
0
    {
1455
0
        return;
1456
0
    }
1457
1458
0
    TransferableObjectDescriptor aObjDesc;
1459
0
    if (!rData.GetTransferableObjectDescriptor(SotClipboardFormatId::OBJECTDESCRIPTOR, aObjDesc))
1460
0
    {
1461
0
        return;
1462
0
    }
1463
1464
0
    if (aObjDesc.maClassName != SvGlobalName(SO3_SW_CLASSID))
1465
0
    {
1466
0
        return;
1467
0
    }
1468
1469
    // At this point we know that we paste from Writer to Writer and the clipboard has the content
1470
    // in both RTF and ODF formats. Prefer ODF in this case.
1471
0
    nAction = EXCHG_OUT_ACTION_INSERT_OLE;
1472
0
    nFormat = SotClipboardFormatId::EMBED_SOURCE;
1473
0
}
1474
1475
// get HTML indentation level by counting tabulator characters before the index
1476
// (also index value -1 returns with 0)
1477
static sal_Int32 lcl_getLevel(std::u16string_view sText, sal_Int32 nIdx)
1478
0
{
1479
0
    sal_Int32 nRet = 0;
1480
0
    while ( nIdx-- > 0 && sText[nIdx] == '\t' )
1481
0
    {
1482
0
        nRet++;
1483
0
    }
1484
0
    return nRet;
1485
0
}
1486
1487
bool SwTransferable::Paste(SwWrtShell& rSh, const TransferableDataHelper& rData, RndStdIds nAnchorType, bool bIgnoreComments, PasteTableType ePasteTable)
1488
0
{
1489
0
    SwPasteContext aPasteContext(rSh);
1490
1491
0
    sal_uInt8 nAction=0;
1492
0
    SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
1493
0
    SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
1494
0
    SotExchangeActionFlags nActionFlags = SotExchangeActionFlags::NONE;
1495
0
    bool bSingleCellTable = false;
1496
1497
0
    if( GetSwTransferable( rData ) )
1498
0
    {
1499
0
        nAction = EXCHG_OUT_ACTION_INSERT_PRIVATE;
1500
0
    }
1501
0
    else
1502
0
    {
1503
0
        sal_uInt16 nSourceOptions =
1504
0
                    (( SotExchangeDest::DOC_TEXTFRAME == nDestination ||
1505
0
                    SotExchangeDest::SWDOC_FREE_AREA == nDestination ||
1506
0
                    SotExchangeDest::DOC_TEXTFRAME_WEB == nDestination ||
1507
0
                    SotExchangeDest::SWDOC_FREE_AREA_WEB == nDestination )
1508
0
                                    ? EXCHG_IN_ACTION_COPY
1509
0
                                    : EXCHG_IN_ACTION_MOVE);
1510
0
        uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
1511
0
        sal_uInt8 nEventAction;
1512
0
        nAction = SotExchange::GetExchangeAction(
1513
0
                                    rData.GetDataFlavorExVector(),
1514
0
                                    nDestination,
1515
0
                                    nSourceOptions,             /* ?? */
1516
0
                                    EXCHG_IN_ACTION_DEFAULT,    /* ?? */
1517
0
                                    nFormat, nEventAction, SotClipboardFormatId::NONE,
1518
0
                                    lcl_getTransferPointer ( xTransferable ),
1519
0
                                    &nActionFlags );
1520
0
    }
1521
1522
    // when HTML is just an image don't generate new section
1523
0
    if (rData.HasFormat(SotClipboardFormatId::HTML_SIMPLE) && rData.HasFormat(SotClipboardFormatId::HTML_NO_COMMENT)
1524
0
        && rData.HasFormat(SotClipboardFormatId::BITMAP) && nFormat == SotClipboardFormatId::FILE_LIST)
1525
0
        nFormat = SotClipboardFormatId::BITMAP;
1526
1527
    // tdf#37223 avoid non-native insertion of Calc worksheets in the following cases:
1528
    // content of 1-cell worksheets are inserted as simple text using RTF format,
1529
    // bigger worksheets within native (Writer) table cells are inserted as native tables,
1530
    // ie. cell by cell instead of embedding the worksheet in a single cell of the Writer table
1531
0
    if ( EXCHG_IN_ACTION_COPY == nAction && ( rData.HasFormat( SotClipboardFormatId::SYLK ) ||
1532
0
                  rData.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS ) ) )
1533
0
    {
1534
        // is it a 1-cell worksheet?
1535
0
        OUString aExpand;
1536
0
        if( rData.GetString( SotClipboardFormatId::STRING, aExpand ))
1537
0
        {
1538
0
            const sal_Int32 nNewlines{comphelper::string::getTokenCount(aExpand, '\n')};
1539
0
            const sal_Int32 nRows = nNewlines ? nNewlines-1 : 0;
1540
0
            if ( nRows == 1 )
1541
0
            {
1542
0
                const sal_Int32 nCols = comphelper::string::getTokenCount(o3tl::getToken(aExpand, 0, '\n'), '\t');
1543
0
                if (nCols == 1)
1544
0
                    bSingleCellTable = true;
1545
0
            }
1546
0
        }
1547
1548
        // convert the worksheet to a temporary native table using HTML format, and copy that into the original native table
1549
0
        if (!bSingleCellTable && rData.HasFormat( SotClipboardFormatId::HTML ) &&
1550
0
                        SwDoc::IsInTable(rSh.GetCursor()->GetPointNode()) != nullptr && rSh.DoesUndo())
1551
0
        {
1552
0
            SfxDispatcher* pDispatch = rSh.GetView().GetViewFrame().GetDispatcher();
1553
0
            sal_uInt32 nLevel = 0;
1554
1555
            // within Writer table cells, inserting worksheets using HTML format results only plain text, not a native table,
1556
            // so remove all outer nested tables temporary to get a working insertion point
1557
            // (RTF format has no such problem, but that inserts the hidden rows of the original Calc worksheet, too)
1558
1559
            // For this, switch off change tracking temporarily, if needed
1560
0
            RedlineFlags eOld = rSh.GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags();
1561
0
            if ( eOld & RedlineFlags::On )
1562
0
                rSh.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eOld & ~RedlineFlags::On );
1563
1564
0
            UIName sPreviousTableName;
1565
0
            do
1566
0
            {
1567
                // tdf#152245 add a limit to the loop, if it's not possible to delete the table
1568
0
                const SwTableNode* pNode = rSh.GetCursor()->GetPointNode().FindTableNode();
1569
0
                const UIName sTableName = pNode->GetTable().GetFrameFormat()->GetName();
1570
0
                if ( sTableName == sPreviousTableName )
1571
0
                    break;
1572
0
                sPreviousTableName = sTableName;
1573
                // insert a random character to redo the place of the insertion at the end
1574
0
                pDispatch->Execute(FN_INSERT_NNBSP, SfxCallMode::SYNCHRON);
1575
0
                pDispatch->Execute(FN_TABLE_DELETE_TABLE, SfxCallMode::SYNCHRON);
1576
0
                nLevel++;
1577
0
            } while (SwDoc::IsInTable(rSh.GetCursor()->GetPointNode()) != nullptr);
1578
1579
            // restore change tracking settings
1580
0
            if ( eOld & RedlineFlags::On )
1581
0
                rSh.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eOld );
1582
1583
0
            if ( SwTransferable::PasteData( rData, rSh, EXCHG_OUT_ACTION_INSERT_STRING, nActionFlags, SotClipboardFormatId::HTML,
1584
0
                                        nDestination, false, false, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext, ePasteTable) )
1585
0
            {
1586
0
                bool bFoundTemporaryTable = false;
1587
0
                pDispatch->Execute(FN_LINE_UP, SfxCallMode::SYNCHRON);
1588
0
                if (SwDoc::IsInTable(rSh.GetCursor()->GetPointNode()) != nullptr)
1589
0
                {
1590
0
                    bFoundTemporaryTable = true;
1591
0
                    pDispatch->Execute(FN_TABLE_SELECT_ALL, SfxCallMode::SYNCHRON);
1592
0
                    pDispatch->Execute(SID_COPY, SfxCallMode::SYNCHRON);
1593
0
                }
1594
0
                for(sal_uInt32 a = 0; a < 1 + (nLevel * 2); a++)
1595
0
                    pDispatch->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
1596
                // clipboard content hasn't changed (limit potential infinite
1597
                // recursion with the same non-native table, as was in tdf#138688)
1598
0
                if (!bFoundTemporaryTable)
1599
0
                    return false;
1600
0
                if (ePasteTable == PasteTableType::PASTE_TABLE)
1601
0
                    pDispatch->Execute(FN_PASTE_NESTED_TABLE, SfxCallMode::SYNCHRON);
1602
0
                else if (ePasteTable == PasteTableType::PASTE_ROW)
1603
0
                    pDispatch->Execute(FN_TABLE_PASTE_ROW_BEFORE, SfxCallMode::SYNCHRON);
1604
0
                else if (ePasteTable == PasteTableType::PASTE_COLUMN)
1605
0
                    pDispatch->Execute(FN_TABLE_PASTE_COL_BEFORE, SfxCallMode::SYNCHRON);
1606
0
                else
1607
0
                    pDispatch->Execute(SID_PASTE, SfxCallMode::SYNCHRON);
1608
0
                return true;
1609
0
            } else {
1610
0
                for(sal_uInt32 a = 0; a < (nLevel * 2); a++)
1611
0
                    pDispatch->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
1612
0
            }
1613
0
        }
1614
0
    }
1615
    // insert clipboard content as new table rows/columns before the actual row/column instead of overwriting it
1616
0
    else if ( (rSh.GetTableInsertMode() != SwTable::SEARCH_NONE || ePasteTable == PasteTableType::PASTE_ROW || ePasteTable == PasteTableType::PASTE_COLUMN) &&
1617
0
        rData.HasFormat( SotClipboardFormatId::HTML ) &&
1618
0
        SwDoc::IsInTable(rSh.GetCursor()->GetPointNode()) != nullptr )
1619
0
    {
1620
0
        OUString aExpand;
1621
0
        sal_Int32 nIdx;
1622
0
        bool bRowMode = rSh.GetTableInsertMode() == SwTable::SEARCH_ROW || ePasteTable == PasteTableType::PASTE_ROW;
1623
0
        if( rData.GetString( SotClipboardFormatId::HTML, aExpand ) && (nIdx = aExpand.indexOf("<table")) > -1 )
1624
0
        {
1625
            // calculate table row/column count by analysing indentation of the HTML table extract
1626
1627
            // calculate indentation level of <table>, which is the base of the next calculations
1628
            // (tdf#148791 table alignment can enlarge it using first level <center>, <div> or <dl>)
1629
0
            sal_Int32 nTableLevel = lcl_getLevel(aExpand, nIdx);
1630
            // table rows repeated heading use extra indentation, too:
1631
            // <thead> is always used here, and the first table with <thead> is not nested,
1632
            // if its indentation level is greater only by 1, than indentation level of the table
1633
0
            bool bShifted = lcl_getLevel(aExpand, aExpand.indexOf("<thead")) == nTableLevel + 1;
1634
            // calculate count of selected rows or columns
1635
0
            sal_Int32 nSelectedRowsOrCols = 0;
1636
0
            const OUString sSearchRowOrCol = bRowMode ? u"</tr>"_ustr : u"<col "_ustr;
1637
0
            while((nIdx = aExpand.indexOf(sSearchRowOrCol, nIdx)) > -1)
1638
0
            {
1639
                // skip rows/columns of nested tables, based on HTML indentation
1640
0
                if ( lcl_getLevel(aExpand, nIdx) == nTableLevel + (bShifted ? 2 : 1) &&
1641
                    // skip also strange hidden empty rows <tr></tr>
1642
0
                    !aExpand.match("<tr></tr>", nIdx - 4) )
1643
0
                {
1644
0
                    ++nSelectedRowsOrCols;
1645
0
                }
1646
0
                ++nIdx;
1647
0
            }
1648
            // are we at the beginning of the cell?
1649
0
            bool bStartTableBoxNode =
1650
                // first paragraph of the cell?
1651
0
                rSh.GetCursor()->GetPointNode().GetIndex() == rSh.GetCursor()->GetPointNode().FindTableBoxStartNode()->GetIndex()+1 &&
1652
                // beginning of the paragraph?
1653
0
                !rSh.GetCursor()->GetPoint()->GetContentIndex();
1654
0
            SfxDispatcher* pDispatch = rSh.GetView().GetViewFrame().GetDispatcher();
1655
1656
            // go start of the cell
1657
0
            if (!bStartTableBoxNode)
1658
0
                pDispatch->Execute(FN_START_OF_DOCUMENT, SfxCallMode::SYNCHRON);
1659
1660
            // store cursor position in row mode
1661
0
            ::sw::mark::MarkBase* pMark = (!bRowMode || nSelectedRowsOrCols == 0) ? nullptr : rSh.SetBookmark(
1662
0
                                    vcl::KeyCode(),
1663
0
                                    SwMarkName(),
1664
0
                                    IDocumentMarkAccess::MarkType::UNO_BOOKMARK );
1665
1666
            // add a new empty row/column before the actual table row/column and go there
1667
0
            const sal_uInt16 nDispatchSlot = bRowMode ? FN_TABLE_INSERT_ROW_BEFORE : FN_TABLE_INSERT_COL_BEFORE;
1668
0
            pDispatch->Execute(nDispatchSlot, SfxCallMode::SYNCHRON);
1669
0
            pDispatch->Execute(bRowMode ? FN_LINE_UP : FN_CHAR_LEFT, SfxCallMode::SYNCHRON);
1670
1671
            // add the other new empty rows/columns after the actual table row/column
1672
0
            if ( nSelectedRowsOrCols > 1 )
1673
0
            {
1674
0
                SfxInt16Item aCountItem( nDispatchSlot, nSelectedRowsOrCols-1 );
1675
0
                SfxBoolItem aAfter( FN_PARAM_INSERT_AFTER, true );
1676
0
                pDispatch->ExecuteList(nDispatchSlot,
1677
0
                    SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
1678
0
                    { &aCountItem, &aAfter });
1679
0
            }
1680
1681
            // paste rows
1682
0
            bool bResult = SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
1683
0
                                        nDestination, false, false, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext );
1684
1685
            // restore cursor position
1686
0
            if (pMark != nullptr)
1687
0
            {
1688
0
                rSh.GotoMark( pMark );
1689
0
                rSh.getIDocumentMarkAccess()->deleteMark( pMark );
1690
0
            }
1691
1692
0
            return bResult;
1693
0
        }
1694
0
    }
1695
1696
    // special case for tables from draw application or 1-cell tables
1697
0
    if( EXCHG_OUT_ACTION_INSERT_DRAWOBJ == nAction || bSingleCellTable )
1698
0
    {
1699
0
        if( rData.HasFormat( SotClipboardFormatId::RTF ) )
1700
0
        {
1701
0
            nAction = EXCHG_OUT_ACTION_INSERT_STRING;
1702
0
            nFormat = SotClipboardFormatId::RTF;
1703
0
        }
1704
0
        else if( rData.HasFormat( SotClipboardFormatId::RICHTEXT ) )
1705
0
        {
1706
0
            nAction = EXCHG_OUT_ACTION_INSERT_STRING;
1707
0
            nFormat = SotClipboardFormatId::RICHTEXT;
1708
0
        }
1709
0
    }
1710
1711
    // Tweak the format if necessary: the source application can be considered in this context,
1712
    // while not in sot/ code.
1713
0
    SwTransferable::SelectPasteFormat(rData, nAction, nFormat);
1714
1715
0
    collectUIInformation(u"PASTE"_ustr, u"parameter"_ustr);
1716
1717
0
    return EXCHG_INOUT_ACTION_NONE != nAction &&
1718
0
            SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
1719
0
                                        nDestination, false, false, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext, ePasteTable);
1720
0
}
1721
1722
bool SwTransferable::PasteData( const TransferableDataHelper& rData,
1723
                            SwWrtShell& rSh, sal_uInt8 nAction, SotExchangeActionFlags nActionFlags,
1724
                            SotClipboardFormatId nFormat,
1725
                            SotExchangeDest nDestination, bool bIsPasteFormat,
1726
                            [[maybe_unused]] bool bIsDefault,
1727
                            const Point* pPt, sal_Int8 nDropAction,
1728
                            bool bPasteSelection, RndStdIds nAnchorType,
1729
                            bool bIgnoreComments,
1730
                            SwPasteContext* pContext,
1731
                            PasteTableType ePasteTable)
1732
0
{
1733
0
    SwWait aWait( *rSh.GetView().GetDocShell(), false );
1734
0
    std::unique_ptr<SwTrnsfrActionAndUndo, o3tl::default_delete<SwTrnsfrActionAndUndo>> pAction;
1735
0
    SwModule* pMod = SwModule::get();
1736
1737
0
    bool bRet = false;
1738
0
    bool bCallAutoCaption = false;
1739
1740
0
    if( pPt )
1741
0
    {
1742
        // external Drop
1743
0
        if ((bPasteSelection ? !pMod->m_pXSelection : !pMod->m_pDragDrop) &&
1744
                // The following condition is used for tdf#156111 to prevent a selection from being
1745
                // cleared by the default case of the nDestination switch.
1746
0
                !(rSh.GetCursorCnt() == 1 && rSh.TestCurrPam(*pPt) &&
1747
0
                nDestination == SotExchangeDest::SWDOC_FREE_AREA &&
1748
0
                nFormat == SotClipboardFormatId::SONLK))
1749
0
        {
1750
0
            switch( nDestination )
1751
0
            {
1752
0
            case SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP:
1753
0
            case SotExchangeDest::DOC_LNKD_GRAPHOBJ:
1754
0
            case SotExchangeDest::DOC_GRAPH_W_IMAP:
1755
0
            case SotExchangeDest::DOC_GRAPHOBJ:
1756
0
            case SotExchangeDest::DOC_OLEOBJ:
1757
0
            case SotExchangeDest::DOC_DRAWOBJ:
1758
0
            case SotExchangeDest::DOC_URLBUTTON:
1759
0
            case SotExchangeDest::DOC_GROUPOBJ:
1760
                // select frames/objects
1761
0
                SwTransferable::SetSelInShell( rSh, true, pPt );
1762
0
                break;
1763
1764
0
            default:
1765
0
                bool bLockView = rSh.IsViewLocked();
1766
0
                if (nFormat == SotClipboardFormatId::SONLK)
1767
0
                    rSh.LockView(true); // prevent view jump
1768
0
                SwTransferable::SetSelInShell( rSh, false, pPt );
1769
0
                rSh.LockView(bLockView);
1770
0
                break;
1771
0
            }
1772
0
        }
1773
0
    }
1774
0
    else if( ( !GetSwTransferable( rData ) || bIsPasteFormat ) &&
1775
0
            !rSh.IsTableMode() && rSh.HasSelection() )
1776
0
    {
1777
        // then delete the selections
1778
1779
        //don't delete selected content
1780
        // - at table-selection
1781
        // - at ReRead of a graphic/DDEData
1782
        // - at D&D, for the right selection was taken care of
1783
        //      in Drop-Handler
1784
0
        bool bDelSel = false;
1785
0
        switch( nDestination )
1786
0
        {
1787
0
        case SotExchangeDest::DOC_TEXTFRAME:
1788
0
        case SotExchangeDest::SWDOC_FREE_AREA:
1789
0
        case SotExchangeDest::DOC_TEXTFRAME_WEB:
1790
0
        case SotExchangeDest::SWDOC_FREE_AREA_WEB:
1791
0
            bDelSel = true;
1792
0
            break;
1793
0
        default:
1794
0
            break;
1795
0
        }
1796
1797
0
        if( bDelSel )
1798
            // #i34830#
1799
0
            pAction.reset(new SwTrnsfrActionAndUndo(&rSh, true, pContext));
1800
0
    }
1801
1802
0
    SwTransferable *pTrans=nullptr, *pTunneledTrans=GetSwTransferable( rData );
1803
1804
    // check for private drop
1805
0
    bool bPrivateDrop(pPt);
1806
0
    if (bPrivateDrop)
1807
0
    {
1808
0
        if (bPasteSelection)
1809
0
            pTrans = pMod->m_pXSelection;
1810
0
        else
1811
0
            pTrans = pMod->m_pDragDrop;
1812
0
        bPrivateDrop = nullptr != pTrans;
1813
0
    }
1814
0
    bool bNeedToSelectBeforePaste(false);
1815
1816
0
    if(bPrivateDrop && DND_ACTION_LINK == nDropAction)
1817
0
    {
1818
        // internal drop on object, suppress bPrivateDrop to change internal fill
1819
0
        bPrivateDrop = false;
1820
0
        bNeedToSelectBeforePaste = true;
1821
0
    }
1822
1823
0
    if(bPrivateDrop && pPt && DND_ACTION_MOVE == nDropAction)
1824
0
    {
1825
        // check if dragged over a useful target. If yes, use as content exchange
1826
        // drop as if from external
1827
0
        const SwFrameFormat* pSwFrameFormat = rSh.GetFormatFromObj(*pPt);
1828
1829
0
        if(dynamic_cast< const SwDrawFrameFormat* >(pSwFrameFormat))
1830
0
        {
1831
0
            bPrivateDrop = false;
1832
0
            bNeedToSelectBeforePaste = true;
1833
0
        }
1834
0
    }
1835
1836
0
    if(bPrivateDrop)
1837
0
    {
1838
        // then internal Drag & Drop or XSelection
1839
0
        bRet = pTrans->PrivateDrop( rSh, *pPt, DND_ACTION_MOVE == nDropAction,
1840
0
                                    bPasteSelection );
1841
0
    }
1842
0
    else if( !pPt && pTunneledTrans &&
1843
0
            EXCHG_OUT_ACTION_INSERT_PRIVATE == nAction )
1844
0
    {
1845
        // then internal paste
1846
0
        bRet = pTunneledTrans->PrivatePaste(rSh, pContext, ePasteTable);
1847
0
    }
1848
0
    else if( EXCHG_INOUT_ACTION_NONE != nAction )
1849
0
    {
1850
0
        if( !pAction )
1851
0
        {
1852
0
            pAction.reset(new SwTrnsfrActionAndUndo( &rSh ));
1853
0
        }
1854
1855
        // in Drag&Drop MessageBoxes must not be showed
1856
0
        bool bMsg = nullptr == pPt;
1857
1858
        // delete selections
1859
1860
0
        switch( nAction )
1861
0
        {
1862
0
        case EXCHG_OUT_ACTION_INSERT_PRIVATE:
1863
0
            OSL_ENSURE( pPt, "EXCHG_OUT_ACTION_INSERT_PRIVATE: what should happen here?" );
1864
0
            break;
1865
1866
0
        case EXCHG_OUT_ACTION_MOVE_PRIVATE:
1867
0
            OSL_ENSURE( pPt, "EXCHG_OUT_ACTION_MOVE_PRIVATE: what should happen here?" );
1868
0
            break;
1869
1870
0
        case EXCHG_IN_ACTION_MOVE:
1871
0
        case EXCHG_IN_ACTION_COPY:
1872
0
        case EXCHG_IN_ACTION_LINK:
1873
0
        case EXCHG_OUT_ACTION_INSERT_HTML:
1874
0
        case EXCHG_OUT_ACTION_INSERT_STRING:
1875
0
        case EXCHG_OUT_ACTION_INSERT_IMAGEMAP:
1876
0
        case EXCHG_OUT_ACTION_REPLACE_IMAGEMAP:
1877
1878
            // then we have to use the format
1879
0
            switch( nFormat )
1880
0
            {
1881
0
            case SotClipboardFormatId::DRAWING:
1882
0
                bRet = SwTransferable::PasteSdrFormat( rData, rSh,
1883
0
                                                SwPasteSdr::Insert, pPt,
1884
0
                                                nActionFlags, bNeedToSelectBeforePaste);
1885
0
                break;
1886
1887
0
            case SotClipboardFormatId::HTML:
1888
0
            case SotClipboardFormatId::HTML_SIMPLE:
1889
0
            case SotClipboardFormatId::HTML_NO_COMMENT:
1890
0
            case SotClipboardFormatId::RTF:
1891
0
            case SotClipboardFormatId::RICHTEXT:
1892
0
            case SotClipboardFormatId::STRING:
1893
0
            case SotClipboardFormatId::MARKDOWN:
1894
0
                bRet = SwTransferable::PasteFileContent( rData, rSh,
1895
0
                                                            nFormat, bMsg, bIgnoreComments);
1896
0
                break;
1897
1898
0
            case SotClipboardFormatId::NETSCAPE_BOOKMARK:
1899
0
                {
1900
0
                    INetBookmark aBkmk;
1901
0
                    if( rData.GetINetBookmark( nFormat, aBkmk ) )
1902
0
                    {
1903
0
                        SwFormatINetFormat aFormat( aBkmk.GetURL(), OUString() );
1904
0
                        rSh.InsertURL( aFormat, aBkmk.GetDescription() );
1905
0
                        bRet = true;
1906
0
                    }
1907
0
                }
1908
0
                break;
1909
1910
0
            case SotClipboardFormatId::SD_OLE:
1911
0
                bRet = SwTransferable::PasteOLE( rData, rSh, nFormat,
1912
0
                                                    nActionFlags, bMsg );
1913
0
                break;
1914
1915
0
            case SotClipboardFormatId::SVIM:
1916
0
                bRet = SwTransferable::PasteImageMap( rData, rSh );
1917
0
                break;
1918
1919
0
            case SotClipboardFormatId::SVXB:
1920
0
            case SotClipboardFormatId::BITMAP:
1921
0
            case SotClipboardFormatId::PNG:
1922
0
            case SotClipboardFormatId::GDIMETAFILE:
1923
0
                bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
1924
0
                                                SwPasteSdr::Insert,pPt,
1925
0
                        nActionFlags, nDropAction, bNeedToSelectBeforePaste,
1926
0
                        &bCallAutoCaption);
1927
0
                break;
1928
1929
0
            case SotClipboardFormatId::XFORMS:
1930
0
            case SotClipboardFormatId::SBA_FIELDDATAEXCHANGE:
1931
0
            case SotClipboardFormatId::SBA_DATAEXCHANGE:
1932
0
            case SotClipboardFormatId::SBA_CTRLDATAEXCHANGE:
1933
0
                bRet = SwTransferable::PasteDBData( rData, rSh, nFormat,
1934
0
                                            EXCHG_IN_ACTION_LINK == nAction,
1935
0
                                            pPt, bMsg );
1936
0
                break;
1937
1938
0
            case SotClipboardFormatId::SIMPLE_FILE:
1939
0
                bRet = SwTransferable::PasteFileName( rData, rSh, nFormat,
1940
0
                                ( EXCHG_IN_ACTION_MOVE == nAction
1941
0
                                    ? SwPasteSdr::Replace
1942
0
                                    : EXCHG_IN_ACTION_LINK == nAction
1943
0
                                        ? SwPasteSdr::SetAttr
1944
0
                                        : SwPasteSdr::Insert),
1945
0
                        pPt, nActionFlags, &bCallAutoCaption);
1946
0
                break;
1947
1948
0
            case SotClipboardFormatId::FILE_LIST:
1949
                // then insert as graphics only
1950
0
                bRet = SwTransferable::PasteFileList( rData, rSh,
1951
0
                                    EXCHG_IN_ACTION_LINK == nAction,
1952
0
                                    pPt, bMsg, &bCallAutoCaption );
1953
0
                break;
1954
1955
0
            case SotClipboardFormatId::SONLK:
1956
0
                if( pPt )
1957
0
                {
1958
0
                    NaviContentBookmark aBkmk;
1959
0
                    if (aBkmk.Paste(rData, rSh.GetSelText()))
1960
0
                    {
1961
0
                        aWait.~SwWait(); // end the wait pointer, X11 only annoyance
1962
0
                        rSh.NavigatorPaste(aBkmk);
1963
0
                        bRet = true;
1964
0
                    }
1965
0
                }
1966
0
                break;
1967
1968
0
            case SotClipboardFormatId::INET_IMAGE:
1969
0
            case SotClipboardFormatId::NETSCAPE_IMAGE:
1970
0
                bRet = SwTransferable::PasteTargetURL( rData, rSh,
1971
0
                                                        SwPasteSdr::Insert,
1972
0
                                                        pPt, true );
1973
0
                break;
1974
1975
0
            default:
1976
0
                OSL_ENSURE( pPt, "unknown format" );
1977
0
            }
1978
0
            break;
1979
1980
0
        case EXCHG_OUT_ACTION_INSERT_FILE:
1981
0
            {
1982
0
                bRet = SwTransferable::PasteFileName( rData, rSh, nFormat,
1983
0
                                            SwPasteSdr::Insert, pPt,
1984
0
                                            nActionFlags,
1985
0
                                            &bCallAutoCaption);
1986
0
            }
1987
0
            break;
1988
1989
0
        case EXCHG_OUT_ACTION_INSERT_OLE:
1990
0
            bRet = SwTransferable::PasteOLE( rData, rSh, nFormat,
1991
0
                                                nActionFlags,bMsg );
1992
0
            break;
1993
1994
0
        case EXCHG_OUT_ACTION_INSERT_DDE:
1995
0
            {
1996
0
                bool bReRead = 0 != CNT_HasGrf( rSh.GetCntType() );
1997
0
                bRet = SwTransferable::PasteDDE( rData, rSh, bReRead, bMsg );
1998
0
            }
1999
0
            break;
2000
2001
0
        case EXCHG_OUT_ACTION_INSERT_HYPERLINK:
2002
0
            {
2003
0
                OUString sURL, sDesc;
2004
0
                if( SotClipboardFormatId::SIMPLE_FILE == nFormat )
2005
0
                {
2006
0
                    if( rData.GetString( nFormat, sURL ) && !sURL.isEmpty() )
2007
0
                    {
2008
0
                        SwTransferable::CheckForURLOrLNKFile( rData, sURL, &sDesc );
2009
0
                        if( sDesc.isEmpty() )
2010
0
                            sDesc = sURL;
2011
0
                        bRet = true;
2012
0
                    }
2013
0
                }
2014
0
                else
2015
0
                {
2016
0
                    INetBookmark aBkmk;
2017
0
                    if( rData.GetINetBookmark( nFormat, aBkmk ) )
2018
0
                    {
2019
0
                        sURL = aBkmk.GetURL();
2020
0
                        sDesc = aBkmk.GetDescription();
2021
0
                        bRet = true;
2022
0
                    }
2023
0
                }
2024
2025
0
                if( bRet )
2026
0
                {
2027
0
                    SwFormatINetFormat aFormat( sURL, OUString() );
2028
0
                    rSh.InsertURL( aFormat, sDesc );
2029
0
                }
2030
0
            }
2031
0
            break;
2032
2033
0
        case EXCHG_OUT_ACTION_GET_ATTRIBUTES:
2034
0
            switch( nFormat )
2035
0
            {
2036
0
            case SotClipboardFormatId::DRAWING:
2037
0
                bRet = SwTransferable::PasteSdrFormat( rData, rSh,
2038
0
                                                SwPasteSdr::SetAttr, pPt,
2039
0
                                                nActionFlags, bNeedToSelectBeforePaste);
2040
0
                break;
2041
0
            case SotClipboardFormatId::SVXB:
2042
0
            case SotClipboardFormatId::GDIMETAFILE:
2043
0
            case SotClipboardFormatId::BITMAP:
2044
0
            case SotClipboardFormatId::PNG:
2045
0
            case SotClipboardFormatId::NETSCAPE_BOOKMARK:
2046
0
            case SotClipboardFormatId::SIMPLE_FILE:
2047
0
            case SotClipboardFormatId::FILEGRPDESCRIPTOR:
2048
0
            case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
2049
0
                bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
2050
0
                                                SwPasteSdr::SetAttr, pPt,
2051
0
                        nActionFlags, nDropAction, bNeedToSelectBeforePaste,
2052
0
                        nullptr/*no caption?*/);
2053
0
                break;
2054
0
            default:
2055
0
                OSL_FAIL( "unknown format" );
2056
0
            }
2057
2058
0
            break;
2059
2060
0
        case EXCHG_OUT_ACTION_INSERT_DRAWOBJ:
2061
0
            bRet = SwTransferable::PasteSdrFormat( rData, rSh,
2062
0
                                                SwPasteSdr::Insert, pPt,
2063
0
                                                nActionFlags, bNeedToSelectBeforePaste);
2064
0
            break;
2065
0
        case EXCHG_OUT_ACTION_INSERT_SVXB:
2066
0
        case EXCHG_OUT_ACTION_INSERT_GDIMETAFILE:
2067
0
        case EXCHG_OUT_ACTION_INSERT_BITMAP:
2068
0
        case EXCHG_OUT_ACTION_INSERT_GRAPH:
2069
0
            bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
2070
0
                                                SwPasteSdr::Insert, pPt,
2071
0
                    nActionFlags, nDropAction, bNeedToSelectBeforePaste,
2072
0
                    &bCallAutoCaption, nAnchorType);
2073
0
            break;
2074
2075
0
        case EXCHG_OUT_ACTION_REPLACE_DRAWOBJ:
2076
0
            bRet = SwTransferable::PasteSdrFormat( rData, rSh,
2077
0
                                                SwPasteSdr::Replace, pPt,
2078
0
                                                nActionFlags, bNeedToSelectBeforePaste);
2079
0
            break;
2080
2081
0
        case EXCHG_OUT_ACTION_REPLACE_SVXB:
2082
0
        case EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE:
2083
0
        case EXCHG_OUT_ACTION_REPLACE_BITMAP:
2084
0
        case EXCHG_OUT_ACTION_REPLACE_GRAPH:
2085
0
            bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
2086
0
                                                SwPasteSdr::Replace,pPt,
2087
0
                    nActionFlags, nDropAction, bNeedToSelectBeforePaste,
2088
0
                    nullptr/*no caption for replace?*/);
2089
0
            break;
2090
2091
0
        case EXCHG_OUT_ACTION_INSERT_INTERACTIVE:
2092
0
            bRet = SwTransferable::PasteAsHyperlink( rData, rSh, nFormat );
2093
0
            break;
2094
2095
0
        default:
2096
0
            OSL_FAIL("unknown action" );
2097
0
        }
2098
0
    }
2099
2100
0
    if( !bPasteSelection && rSh.IsFrameSelected() )
2101
0
    {
2102
0
        rSh.EnterSelFrameMode();
2103
        //force ::SelectShell
2104
0
        rSh.GetView().StopShellTimer();
2105
0
    }
2106
2107
0
    pAction.reset();
2108
0
    if( bCallAutoCaption )
2109
0
        rSh.GetView().AutoCaption( GRAPHIC_CAP );
2110
2111
0
    return bRet;
2112
0
}
2113
2114
SotExchangeDest SwTransferable::GetSotDestination( const SwWrtShell& rSh )
2115
0
{
2116
0
    SotExchangeDest nRet = SotExchangeDest::NONE;
2117
2118
0
    ObjCntType eOType = rSh.GetObjCntTypeOfSelection();
2119
2120
0
    switch( eOType )
2121
0
    {
2122
0
    case OBJCNT_GRF:
2123
0
        {
2124
0
            bool bIMap, bLink;
2125
0
            bIMap = nullptr != rSh.GetFlyFrameFormat()->GetURL().GetMap();
2126
0
            OUString aDummy;
2127
0
            rSh.GetGrfNms( &aDummy, nullptr );
2128
0
            bLink = !aDummy.isEmpty();
2129
2130
0
            if( bLink && bIMap )
2131
0
                nRet = SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP;
2132
0
            else if( bLink )
2133
0
                nRet = SotExchangeDest::DOC_LNKD_GRAPHOBJ;
2134
0
            else if( bIMap )
2135
0
                nRet = SotExchangeDest::DOC_GRAPH_W_IMAP;
2136
0
            else
2137
0
                nRet = SotExchangeDest::DOC_GRAPHOBJ;
2138
0
        }
2139
0
        break;
2140
2141
0
    case OBJCNT_FLY:
2142
0
        if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr  )
2143
0
            nRet = SotExchangeDest::DOC_TEXTFRAME_WEB;
2144
0
        else
2145
0
            nRet = SotExchangeDest::DOC_TEXTFRAME;
2146
0
        break;
2147
0
    case OBJCNT_OLE:        nRet = SotExchangeDest::DOC_OLEOBJ;       break;
2148
2149
0
    case OBJCNT_CONTROL:    /* no Action avail */
2150
0
    case OBJCNT_SIMPLE:     nRet = SotExchangeDest::DOC_DRAWOBJ;      break;
2151
0
    case OBJCNT_URLBUTTON:  nRet = SotExchangeDest::DOC_URLBUTTON;    break;
2152
0
    case OBJCNT_GROUPOBJ:   nRet = SotExchangeDest::DOC_GROUPOBJ;     break;
2153
2154
    // what do we do at multiple selections???
2155
0
    default:
2156
0
        {
2157
0
            if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr  )
2158
0
                nRet = SotExchangeDest::SWDOC_FREE_AREA_WEB;
2159
0
            else
2160
0
                nRet = SotExchangeDest::SWDOC_FREE_AREA;
2161
0
        }
2162
0
    }
2163
2164
0
    return nRet;
2165
0
}
2166
2167
namespace
2168
{
2169
bool CanSkipInvalidateNumRules(const SwPosition& rInsertPosition)
2170
0
{
2171
0
    SwTextNode* pTextNode = rInsertPosition.GetNode().GetTextNode();
2172
0
    if (!pTextNode)
2173
0
    {
2174
0
        return false;
2175
0
    }
2176
2177
0
    const SwNodeNum* pNum = pTextNode->GetNum();
2178
0
    if (pNum)
2179
0
    {
2180
0
        SwNumRule* pNumRule = pNum->GetNumRule();
2181
0
        if (pNumRule)
2182
0
        {
2183
0
            const SvxNumberType rType = pNumRule->Get(pTextNode->GetActualListLevel());
2184
0
            if (rType.GetNumberingType() == SVX_NUM_CHAR_SPECIAL)
2185
0
            {
2186
                // Bullet list, skip invalidation.
2187
0
                return true;
2188
0
            }
2189
0
        }
2190
2191
        // Numbered list, invalidate.
2192
0
        return false;
2193
0
    }
2194
2195
    // Not a list, skip invalidation.
2196
0
    return true;
2197
0
}
2198
}
2199
2200
bool SwTransferable::PasteFileContent( const TransferableDataHelper& rData,
2201
                                    SwWrtShell& rSh, SotClipboardFormatId nFormat, bool bMsg, bool bIgnoreComments)
2202
0
{
2203
0
    bool bRet = false;
2204
2205
0
    MSE40HTMLClipFormatObj aMSE40ClpObj;
2206
2207
0
    std::unique_ptr<SvStream> xStrm;
2208
0
    SvStream* pStream = nullptr;
2209
0
    Reader* pRead = nullptr;
2210
0
    OUString sData;
2211
0
    bool bSkipInvalidateNumRules = false;
2212
0
    bool bCheckStream = true;
2213
2214
0
    if (nFormat == SotClipboardFormatId::STRING || nFormat == SotClipboardFormatId::MARKDOWN)
2215
0
    {
2216
0
        if( rData.GetString( nFormat, sData ) )
2217
0
        {
2218
0
            bCheckStream = false;
2219
0
            pStream = new SvMemoryStream( const_cast<sal_Unicode *>(sData.getStr()),
2220
0
                        sData.getLength() * sizeof( sal_Unicode ),
2221
0
                        StreamMode::READ );
2222
0
            pStream->ResetEndianSwap();
2223
2224
0
            if (nFormat == SotClipboardFormatId::STRING)
2225
0
            {
2226
0
                const SwPosition& rInsertPosition = *rSh.GetCursor()->Start();
2227
0
                if (CanSkipInvalidateNumRules(rInsertPosition))
2228
0
                {
2229
                    // Insertion point is not a numbering and we paste plain text: then no need to
2230
                    // invalidate all numberings.
2231
0
                    bSkipInvalidateNumRules = true;
2232
0
                }
2233
2234
0
                pRead = ReadAscii;
2235
0
            }
2236
0
            else
2237
0
            {
2238
0
                pRead = ReadMarkdown;
2239
0
            }
2240
2241
0
            SwAsciiOptions aAOpt;
2242
0
            aAOpt.SetCharSet( RTL_TEXTENCODING_UCS2 );
2243
0
            pRead->GetReaderOpt().SetASCIIOpts( aAOpt );
2244
0
        }
2245
0
    }
2246
2247
0
    if (bCheckStream)
2248
0
    {
2249
0
        if( (xStrm = rData.GetSotStorageStream( nFormat )) )
2250
0
        {
2251
0
            if( ( SotClipboardFormatId::HTML_SIMPLE == nFormat ) ||
2252
0
                ( SotClipboardFormatId::HTML_NO_COMMENT == nFormat ) )
2253
0
            {
2254
0
                pStream = aMSE40ClpObj.IsValid( *xStrm );
2255
0
                pRead = ReadHTML;
2256
0
                pRead->SetReadUTF8( true );
2257
2258
0
                bool bNoComments =
2259
0
                    ( nFormat == SotClipboardFormatId::HTML_NO_COMMENT );
2260
0
                pRead->SetIgnoreHTMLComments( bNoComments );
2261
0
            }
2262
0
            else
2263
0
            {
2264
0
                pStream = xStrm.get();
2265
0
                if( SotClipboardFormatId::RTF == nFormat || SotClipboardFormatId::RICHTEXT == nFormat)
2266
0
                    pRead = SwReaderWriter::GetRtfReader();
2267
0
                else
2268
0
                {
2269
0
                    pRead = ReadHTML;
2270
0
                    pRead->SetReadUTF8( true );
2271
0
                }
2272
0
            }
2273
0
        }
2274
0
    }
2275
2276
0
    TranslateId pResId;
2277
0
    if( pStream && pRead )
2278
0
    {
2279
0
        Link<LinkParamNone*,void> aOldLink( rSh.GetChgLnk() );
2280
0
        rSh.SetChgLnk( Link<LinkParamNone*,void>() );
2281
2282
0
        const SwPosition& rInsPos = *rSh.GetCursor()->Start();
2283
0
        SwReader aReader(*pStream, OUString(), OUString(), *rSh.GetCursor());
2284
0
        rSh.SaveTableBoxContent( &rInsPos );
2285
2286
0
        if (bIgnoreComments)
2287
0
            pRead->SetIgnoreHTMLComments(true);
2288
0
        if (bSkipInvalidateNumRules)
2289
0
        {
2290
0
            aReader.SetSkipInvalidateNumRules(bSkipInvalidateNumRules);
2291
0
        }
2292
2293
0
        if( aReader.Read( *pRead ).IsError() )
2294
0
            pResId = STR_ERROR_CLPBRD_READ;
2295
0
        else
2296
0
        {
2297
0
            pResId = TranslateId();
2298
0
            bRet = true;
2299
0
        }
2300
2301
0
        rSh.SetChgLnk( aOldLink );
2302
0
        if( bRet )
2303
0
            rSh.CallChgLnk();
2304
0
    }
2305
0
    else
2306
0
        pResId = STR_CLPBRD_FORMAT_ERROR;
2307
2308
    // Exist a SvMemoryStream? (data in the OUString and xStrm is empty)
2309
0
    if( pStream && !xStrm )
2310
0
        delete pStream;
2311
2312
0
    if (bMsg && pResId)
2313
0
    {
2314
0
        std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
2315
0
                                                  VclMessageType::Info, VclButtonsType::Ok,
2316
0
                                                  SwResId(pResId)));
2317
0
        xBox->run();
2318
0
    }
2319
0
    return bRet;
2320
0
}
2321
2322
bool SwTransferable::PasteOLE( const TransferableDataHelper& rData, SwWrtShell& rSh,
2323
                                SotClipboardFormatId nFormat, SotExchangeActionFlags nActionFlags, bool bMsg )
2324
0
{
2325
0
    bool bRet = false;
2326
0
    TransferableObjectDescriptor aObjDesc;
2327
0
    uno::Reference < io::XInputStream > xStrm;
2328
0
    uno::Reference < embed::XStorage > xStore;
2329
0
    Reader* pRead = nullptr;
2330
2331
    // Get the preferred format
2332
0
    SotClipboardFormatId nId;
2333
0
    if( rData.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ ) )
2334
0
        nId = SotClipboardFormatId::EMBEDDED_OBJ;
2335
0
    else if( rData.HasFormat( SotClipboardFormatId::EMBED_SOURCE ) &&
2336
0
             rData.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR ))
2337
0
        nId = SotClipboardFormatId::EMBED_SOURCE;
2338
0
    else
2339
0
        nId = SotClipboardFormatId::NONE;
2340
2341
0
    if (nId != SotClipboardFormatId::NONE)
2342
0
    {
2343
0
        SwDocShell* pDocSh = rSh.GetDoc()->GetDocShell();
2344
0
        xStrm = rData.GetInputStream(nId, SfxObjectShell::CreateShellID(pDocSh));
2345
0
    }
2346
2347
0
    if (xStrm.is())
2348
0
    {
2349
        // if there is an embedded object, first try if it's a writer object
2350
        // this will be inserted into the document by using a Reader
2351
0
        try
2352
0
        {
2353
0
            xStore = comphelper::OStorageHelper::GetStorageFromInputStream( xStrm );
2354
0
            switch( SotStorage::GetFormatID( xStore ) )
2355
0
            {
2356
0
                case SotClipboardFormatId::STARWRITER_60:
2357
0
                case SotClipboardFormatId::STARWRITERWEB_60:
2358
0
                case SotClipboardFormatId::STARWRITERGLOB_60:
2359
0
                case SotClipboardFormatId::STARWRITER_8:
2360
0
                case SotClipboardFormatId::STARWRITERWEB_8:
2361
0
                case SotClipboardFormatId::STARWRITERGLOB_8:
2362
0
                    pRead = ReadXML;
2363
0
                    break;
2364
0
                default:
2365
0
                    try
2366
0
                    {
2367
0
                        xStore->dispose();
2368
0
                        xStore = nullptr;
2369
0
                    }
2370
0
                    catch (const uno::Exception&)
2371
0
                    {
2372
0
                    }
2373
2374
0
                    break;
2375
0
            }
2376
0
        }
2377
0
        catch (const uno::Exception&)
2378
0
        {
2379
            // it wasn't a storage, but maybe it's a useful stream
2380
0
        }
2381
0
    }
2382
2383
0
    if( pRead )
2384
0
    {
2385
0
        SwPaM &rPAM = *rSh.GetCursor();
2386
0
        SwReader aReader(xStore, OUString(), rPAM);
2387
0
        aReader.SetInPaste(true);
2388
0
        if( ! aReader.Read( *pRead ).IsError() )
2389
0
            bRet = true;
2390
0
        else if( bMsg )
2391
0
        {
2392
0
            std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
2393
0
                                                      VclMessageType::Info, VclButtonsType::Ok,
2394
0
                                                      SwResId(STR_ERROR_CLPBRD_READ)));
2395
0
            xBox->run();
2396
0
        }
2397
0
    }
2398
0
    else
2399
0
    {
2400
        // temporary storage until the object is inserted
2401
0
        uno::Reference< embed::XStorage > xTmpStor;
2402
0
        uno::Reference < embed::XEmbeddedObject > xObj;
2403
0
        OUString aName;
2404
0
        comphelper::EmbeddedObjectContainer aCnt;
2405
2406
0
        if ( xStrm.is() )
2407
0
        {
2408
0
            if ( !rData.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR, aObjDesc ) )
2409
0
            {
2410
0
                OSL_ENSURE( !xStrm.is(), "An object without descriptor in clipboard!");
2411
0
            }
2412
0
        }
2413
0
        else
2414
0
        {
2415
0
            if( rData.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR_OLE ) && rData.GetTransferableObjectDescriptor( nFormat, aObjDesc ) )
2416
0
            {
2417
0
                xStrm = rData.GetInputStream(SotClipboardFormatId::EMBED_SOURCE_OLE, OUString());
2418
0
                if (!xStrm.is())
2419
0
                    xStrm = rData.GetInputStream(SotClipboardFormatId::EMBEDDED_OBJ_OLE, OUString());
2420
2421
0
                if ( !xStrm.is() )
2422
0
                {
2423
                    // This is MSOLE object that should be created by direct using of system clipboard
2424
0
                    try
2425
0
                    {
2426
0
                        xTmpStor = ::comphelper::OStorageHelper::GetTemporaryStorage();
2427
0
                        uno::Reference < embed::XEmbedObjectClipboardCreator > xClipboardCreator =
2428
0
                            embed::MSOLEObjectSystemCreator::create( ::comphelper::getProcessComponentContext() );
2429
2430
0
                        embed::InsertedObjectInfo aInfo = xClipboardCreator->createInstanceInitFromClipboard(
2431
0
                                                            xTmpStor,
2432
0
                                                            u"DummyName"_ustr,
2433
0
                                                            uno::Sequence< beans::PropertyValue >() );
2434
2435
                        // TODO/LATER: in future InsertedObjectInfo will be used to get container related information
2436
                        // for example whether the object should be an iconified one
2437
0
                        xObj = aInfo.Object;
2438
0
                    }
2439
0
                    catch (const uno::Exception&)
2440
0
                    {
2441
0
                    }
2442
0
                }
2443
0
            }
2444
0
            else if (rData.HasFormat(SotClipboardFormatId::SIMPLE_FILE))
2445
0
            {
2446
0
                OUString sFile;
2447
0
                if (rData.GetString(nFormat, sFile) && !sFile.isEmpty())
2448
0
                {
2449
                    // Copied from sd::View::DropInsertFileHdl
2450
0
                    uno::Sequence< beans::PropertyValue > aMedium{ comphelper::makePropertyValue(
2451
0
                        u"URL"_ustr, sFile) };
2452
0
                    SwDocShell* pDocSh = rSh.GetDoc()->GetDocShell();
2453
0
                    xObj = pDocSh->GetEmbeddedObjectContainer().InsertEmbeddedObject(aMedium, aName);
2454
0
                }
2455
0
            }
2456
0
        }
2457
2458
0
        if ( xStrm.is() && !xObj.is() )
2459
0
            xObj = aCnt.InsertEmbeddedObject( xStrm, aName );
2460
2461
0
        if( xObj.is() )
2462
0
        {
2463
0
            svt::EmbeddedObjectRef xObjRef( xObj, aObjDesc.mnViewAspect );
2464
2465
            // try to get the replacement image from the clipboard
2466
0
            Graphic aGraphic;
2467
0
            SotClipboardFormatId nGrFormat = SotClipboardFormatId::NONE;
2468
2469
            // limit the size of the preview metafile to 100000 actions
2470
0
            GDIMetaFile aMetafile;
2471
0
            if (rData.GetGDIMetaFile(SotClipboardFormatId::GDIMETAFILE, aMetafile, 100000))
2472
0
            {
2473
0
                nGrFormat = SotClipboardFormatId::GDIMETAFILE;
2474
0
                aGraphic = aMetafile;
2475
0
            }
2476
2477
            // insert replacement image ( if there is one ) into the object helper
2478
0
            if ( nGrFormat != SotClipboardFormatId::NONE )
2479
0
            {
2480
0
                DataFlavor aDataFlavor;
2481
0
                SotExchange::GetFormatDataFlavor( nGrFormat, aDataFlavor );
2482
0
                xObjRef.SetGraphic( aGraphic, aDataFlavor.MimeType );
2483
0
            }
2484
0
            else if ( aObjDesc.mnViewAspect == embed::Aspects::MSOLE_ICON )
2485
0
            {
2486
                // it is important to have an icon, let an empty graphic be used
2487
                // if no other graphic is provided
2488
                // TODO/LATER: in future a default bitmap could be used
2489
0
                MapMode aMapMode( MapUnit::Map100thMM );
2490
0
                aGraphic.SetPrefSize( Size( 2500, 2500 ) );
2491
0
                aGraphic.SetPrefMapMode( aMapMode );
2492
0
                xObjRef.SetGraphic( aGraphic, OUString() );
2493
0
            }
2494
2495
            //set size. This is a hack because of handing over, size should be
2496
            //passed to the InsertOle!!!!!!!!!!
2497
0
            Size aSize;
2498
0
            if ( aObjDesc.mnViewAspect == embed::Aspects::MSOLE_ICON )
2499
0
            {
2500
0
                if( aObjDesc.maSize.Width() && aObjDesc.maSize.Height() )
2501
0
                    aSize = aObjDesc.maSize;
2502
0
                else
2503
0
                {
2504
0
                    MapMode aMapMode( MapUnit::Map100thMM );
2505
0
                    aSize = xObjRef.GetSize( &aMapMode );
2506
0
                }
2507
0
            }
2508
0
            else if( aObjDesc.maSize.Width() && aObjDesc.maSize.Height() )
2509
0
            {
2510
0
                aSize = aObjDesc.maSize;    //always 100TH_MM
2511
0
                MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( aObjDesc.mnViewAspect ) );
2512
0
                aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(aUnit));
2513
0
                awt::Size aSz;
2514
0
                try
2515
0
                {
2516
0
                    aSz = xObj->getVisualAreaSize( aObjDesc.mnViewAspect );
2517
0
                }
2518
0
                catch (const embed::NoVisualAreaSizeException&)
2519
0
                {
2520
                    // in this case the provided size is used
2521
0
                }
2522
2523
0
                if ( aSz.Width != aSize.Width() || aSz.Height != aSize.Height() )
2524
0
                {
2525
0
                    aSz.Width = aSize.Width();
2526
0
                    aSz.Height = aSize.Height();
2527
0
                    xObj->setVisualAreaSize( aObjDesc.mnViewAspect, aSz );
2528
0
                }
2529
0
            }
2530
0
            else
2531
0
            {
2532
                // the descriptor contains the wrong object size
2533
                // the following call will let the MSOLE objects cache the size if it is possible
2534
                // it should be done while the object is running
2535
0
                try
2536
0
                {
2537
0
                    xObj->getVisualAreaSize( aObjDesc.mnViewAspect );
2538
0
                }
2539
0
                catch (const uno::Exception&)
2540
0
                {
2541
0
                }
2542
0
            }
2543
            //End of Hack!
2544
2545
0
            rSh.Push();
2546
0
            rSh.InsertOleObject( xObjRef );
2547
0
            bRet = true;
2548
2549
0
            if( bRet && ( nActionFlags & SotExchangeActionFlags::InsertTargetUrl) )
2550
0
                SwTransferable::PasteTargetURL( rData, rSh, SwPasteSdr::NONE, nullptr, false );
2551
2552
0
            if (!officecfg::Office::Writer::Cursor::Option::SelectPastedAnchoredObject::get())
2553
0
            {
2554
0
                SwTransferable::SetSelInShell(rSh, false, nullptr);
2555
                // shell cursor was put at the end of the document because the
2556
                // fly was not yet positioned; restore stack cursor
2557
0
                rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
2558
0
            }
2559
0
            else
2560
0
            {
2561
0
                rSh.Pop(SwCursorShell::PopMode::DeleteStack);
2562
0
            }
2563
2564
            // let the object be unloaded if possible
2565
0
            SwOLEObj::UnloadObject( xObj, rSh.GetDoc(), embed::Aspects::MSOLE_CONTENT );
2566
0
        }
2567
0
    }
2568
0
    return bRet;
2569
0
}
2570
2571
bool SwTransferable::PasteTargetURL( const TransferableDataHelper& rData,
2572
                                    SwWrtShell& rSh, SwPasteSdr nAction,
2573
                                    const Point* pPt, bool bInsertGRF )
2574
0
{
2575
0
    bool bRet = false;
2576
0
    INetImage aINetImg;
2577
0
    if( ( rData.HasFormat( SotClipboardFormatId::INET_IMAGE ) &&
2578
0
          rData.GetINetImage( SotClipboardFormatId::INET_IMAGE, aINetImg )) ||
2579
0
        ( rData.HasFormat( SotClipboardFormatId::NETSCAPE_IMAGE ) &&
2580
0
          rData.GetINetImage( SotClipboardFormatId::NETSCAPE_IMAGE, aINetImg )) )
2581
0
    {
2582
0
        if( !aINetImg.GetImageURL().isEmpty() && bInsertGRF )
2583
0
        {
2584
0
            OUString sURL( aINetImg.GetImageURL() );
2585
0
            SwTransferable::CheckForURLOrLNKFile( rData, sURL );
2586
2587
            //!!! check at FileSystem - only then it makes sense to test graphics !!!
2588
0
            Graphic aGraphic;
2589
0
            GraphicFilter &rFlt = GraphicFilter::GetGraphicFilter();
2590
0
            bRet = ERRCODE_NONE == GraphicFilter::LoadGraphic(sURL, OUString(), aGraphic, &rFlt);
2591
2592
0
            if( bRet )
2593
0
            {
2594
                //Check and Perform rotation if needed
2595
0
                lclCheckAndPerformRotation(aGraphic);
2596
2597
0
                switch( nAction )
2598
0
                {
2599
0
                case SwPasteSdr::Insert:
2600
0
                    SwTransferable::SetSelInShell( rSh, false, pPt );
2601
0
                    rSh.InsertGraphic(sURL, OUString(), aGraphic);
2602
0
                    break;
2603
2604
0
                case SwPasteSdr::Replace:
2605
0
                    if( rSh.GetSelectedObjCount() )
2606
0
                    {
2607
0
                        rSh.ReplaceSdrObj( sURL, &aGraphic );
2608
0
                        Point aPt( pPt ? *pPt : rSh.GetCursorDocPos() );
2609
0
                        SwTransferable::SetSelInShell( rSh, true, &aPt );
2610
0
                    }
2611
0
                    else
2612
0
                        rSh.ReRead(sURL, OUString(), &aGraphic);
2613
0
                    break;
2614
2615
0
                case SwPasteSdr::SetAttr:
2616
0
                    if( rSh.GetSelectedObjCount() )
2617
0
                        rSh.Paste( aGraphic, OUString() );
2618
0
                    else if( OBJCNT_GRF == rSh.GetObjCntTypeOfSelection() )
2619
0
                        rSh.ReRead(sURL, OUString(), &aGraphic);
2620
0
                    else
2621
0
                    {
2622
0
                        SwTransferable::SetSelInShell( rSh, false, pPt );
2623
0
                        rSh.InsertGraphic(sURL, OUString(), aGraphic);
2624
0
                    }
2625
0
                    break;
2626
0
                default:
2627
0
                    bRet = false;
2628
0
                }
2629
0
            }
2630
0
        }
2631
0
        else
2632
0
            bRet = true;
2633
0
    }
2634
2635
0
    if( bRet )
2636
0
    {
2637
0
        SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_URL, RES_URL>( rSh.GetAttrPool() ));
2638
0
        rSh.GetFlyFrameAttr( aSet );
2639
0
        SwFormatURL aURL( aSet.Get( RES_URL ) );
2640
2641
0
        if( aURL.GetURL() != aINetImg.GetTargetURL() ||
2642
0
            aURL.GetTargetFrameName() != aINetImg.GetTargetFrame() )
2643
0
        {
2644
0
            aURL.SetURL( aINetImg.GetTargetURL(), false );
2645
0
            aURL.SetTargetFrameName( aINetImg.GetTargetFrame() );
2646
0
            aSet.Put( aURL );
2647
0
            rSh.SetFlyFrameAttr( aSet );
2648
0
        }
2649
0
    }
2650
0
    return bRet;
2651
0
}
2652
2653
void SwTransferable::SetSelInShell( SwWrtShell& rSh, bool bSelectFrame,
2654
                                        const Point* pPt )
2655
0
{
2656
0
    if( bSelectFrame )
2657
0
    {
2658
        // select frames/objects
2659
0
        if( pPt && !rSh.GetView().GetViewFrame().GetDispatcher()->IsLocked() )
2660
0
        {
2661
0
            rSh.GetView().NoRotate();
2662
0
            if( rSh.SelectObj( *pPt ))
2663
0
            {
2664
0
                rSh.HideCursor();
2665
0
                rSh.EnterSelFrameMode( pPt );
2666
0
                g_bFrameDrag = true;
2667
0
            }
2668
0
        }
2669
0
    }
2670
0
    else
2671
0
    {
2672
0
        if( rSh.IsFrameSelected() || rSh.GetSelectedObjCount() )
2673
0
        {
2674
0
            rSh.UnSelectFrame();
2675
0
            rSh.LeaveSelFrameMode();
2676
0
            rSh.GetView().GetEditWin().StopInsFrame();
2677
0
            g_bFrameDrag = false;
2678
0
        }
2679
0
        else if( rSh.GetView().GetDrawFuncPtr() )
2680
0
            rSh.GetView().GetEditWin().StopInsFrame();
2681
2682
0
        rSh.EnterStdMode();
2683
0
        if( pPt )
2684
0
            rSh.SwCursorShell::SetCursor( *pPt, true );
2685
0
    }
2686
0
}
2687
2688
bool SwTransferable::PasteDDE( const TransferableDataHelper& rData,
2689
                                SwWrtShell& rWrtShell, bool bReReadGrf,
2690
                                bool bMsg )
2691
0
{
2692
    // data from Clipboardformat
2693
0
    OUString aApp, aTopic, aItem;
2694
2695
0
    if (!rData.ReadDDELink(aApp, aTopic, aItem, o3tl::temporary(OUString())))
2696
0
    {
2697
0
        return false;
2698
0
    }   // report useful error!!
2699
2700
0
    OUString aCmd;
2701
0
    sfx2::MakeLnkName( aCmd, &aApp, aTopic, aItem );
2702
2703
    // do we want to read in a graphic now?
2704
0
    SotClipboardFormatId nFormat;
2705
0
    if( !rData.HasFormat( SotClipboardFormatId::RTF ) &&
2706
0
        !rData.HasFormat( SotClipboardFormatId::RICHTEXT ) &&
2707
0
        !rData.HasFormat( SotClipboardFormatId::HTML ) &&
2708
0
        !rData.HasFormat( SotClipboardFormatId::STRING ) &&
2709
0
        !rData.HasFormat( SotClipboardFormatId::MARKDOWN ) &&
2710
0
        (rData.HasFormat( nFormat = SotClipboardFormatId::GDIMETAFILE ) ||
2711
0
         rData.HasFormat( nFormat = SotClipboardFormatId::BITMAP )) )
2712
0
    {
2713
0
        Graphic aGrf;
2714
0
        bool bRet = rData.GetGraphic( nFormat, aGrf );
2715
0
        if( bRet )
2716
0
        {
2717
0
            OUString sLnkTyp(u"DDE"_ustr);
2718
0
            if ( bReReadGrf )
2719
0
                rWrtShell.ReRead( aCmd, sLnkTyp, &aGrf );
2720
0
            else
2721
0
                rWrtShell.InsertGraphic( aCmd, sLnkTyp, aGrf );
2722
0
        }
2723
0
        return bRet;
2724
0
    }
2725
2726
0
    SwFieldType* pTyp = nullptr;
2727
0
    size_t i = 1;
2728
0
    size_t j;
2729
0
    UIName aName;
2730
0
    bool bDoublePaste = false;
2731
0
    const size_t nSize = rWrtShell.GetFieldTypeCount();
2732
0
    const ::utl::TransliterationWrapper& rColl = ::GetAppCmpStrIgnore();
2733
2734
0
    do {
2735
0
        aName = UIName(aApp + OUString::number( i ));
2736
0
        for( j = INIT_FLDTYPES; j < nSize; j++ )
2737
0
        {
2738
0
            pTyp = rWrtShell.GetFieldType( j );
2739
0
            if( SwFieldIds::Dde == pTyp->Which() )
2740
0
            {
2741
0
                if( rColl.isEqual( static_cast<SwDDEFieldType*>(pTyp)->GetCmd(), aCmd ) &&
2742
0
                    SfxLinkUpdateMode::ALWAYS == static_cast<SwDDEFieldType*>(pTyp)->GetType() )
2743
0
                {
2744
0
                    aName = pTyp->GetName();
2745
0
                    bDoublePaste = true;
2746
0
                    break;
2747
0
                }
2748
0
                else if( rColl.isEqual( aName.toString(), pTyp->GetName().toString() ) )
2749
0
                    break;
2750
0
            }
2751
0
        }
2752
0
        if( j == nSize )
2753
0
            break;
2754
0
        ++i;
2755
0
    }
2756
0
    while( !bDoublePaste );
2757
2758
0
    if( !bDoublePaste )
2759
0
    {
2760
0
        SwDDEFieldType aType( aName, aCmd, SfxLinkUpdateMode::ALWAYS );
2761
0
        pTyp = rWrtShell.InsertFieldType( aType );
2762
0
    }
2763
2764
0
    SwDDEFieldType* pDDETyp = static_cast<SwDDEFieldType*>(pTyp);
2765
2766
0
    OUString aExpand;
2767
0
    if( rData.GetString( SotClipboardFormatId::STRING, aExpand ))
2768
0
    {
2769
0
        do {            // middle checked loop
2770
2771
0
            const sal_Int32 nNewlines{comphelper::string::getTokenCount(aExpand, '\n')};
2772
            // When data comes from a spreadsheet, we add a DDE-table
2773
0
            if( !aExpand.isEmpty() &&
2774
0
                ( rData.HasFormat( SotClipboardFormatId::SYLK ) ||
2775
0
                  rData.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS ) ) )
2776
0
            {
2777
0
                sal_Int32 nRows = nNewlines ? nNewlines-1 : 0;
2778
0
                if (!aExpand.endsWith("\n"))
2779
0
                    ++nRows;    // last row has no newline, e.g. one single cell
2780
0
                const sal_Int32 nCols = comphelper::string::getTokenCount(o3tl::getToken(aExpand, 0, '\n'), '\t');
2781
2782
                // don't try to insert tables that are too large for writer
2783
0
                if (nRows > SAL_MAX_UINT16 || nCols > SAL_MAX_UINT16)
2784
0
                {
2785
0
                    if( bMsg )
2786
0
                    {
2787
0
                        std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
2788
0
                                                                  VclMessageType::Info, VclButtonsType::Ok,
2789
0
                                                                  SwResId(STR_TABLE_TOO_LARGE)));
2790
0
                        xBox->run();
2791
0
                    }
2792
0
                    pDDETyp = nullptr;
2793
0
                    break;
2794
0
                }
2795
2796
                // at least one column & row must be there
2797
0
                if( !nRows || !nCols )
2798
0
                {
2799
0
                    if( bMsg )
2800
0
                    {
2801
0
                        std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
2802
0
                                                                  VclMessageType::Info, VclButtonsType::Ok,
2803
0
                                                                  SwResId(STR_NO_TABLE)));
2804
0
                        xBox->run();
2805
0
                    }
2806
0
                    pDDETyp = nullptr;
2807
0
                    break;
2808
0
                }
2809
2810
0
                rWrtShell.InsertDDETable(
2811
0
                    SwInsertTableOptions( SwInsertTableFlags::SplitLayout, 1 ), // TODO MULTIHEADER
2812
0
                    pDDETyp, nRows, nCols );
2813
0
            }
2814
0
            else if( nNewlines > 1 )
2815
0
            {
2816
                // multiple paragraphs -> insert a protected section
2817
0
                if( rWrtShell.HasSelection() )
2818
0
                    rWrtShell.DelRight();
2819
2820
0
                SwSectionData aSect( SectionType::DdeLink, aName );
2821
0
                aSect.SetLinkFileName( aCmd );
2822
0
                aSect.SetProtectFlag(true);
2823
0
                rWrtShell.InsertSection( aSect );
2824
2825
0
                pDDETyp = nullptr;                // remove FieldTypes again
2826
0
            }
2827
0
            else
2828
0
            {
2829
                // insert
2830
0
                SwDDEField aSwDDEField( pDDETyp );
2831
0
                rWrtShell.InsertField2( aSwDDEField );
2832
0
            }
2833
2834
0
        } while( false );
2835
0
    }
2836
0
    else
2837
0
        pDDETyp = nullptr;                        // remove FieldTypes again
2838
2839
0
    if( !pDDETyp && !bDoublePaste )
2840
0
    {
2841
        // remove FieldType again - error occurred!
2842
0
        for( j = nSize; j >= INIT_FLDTYPES; --j )
2843
0
            if( pTyp == rWrtShell.GetFieldType( j ) )
2844
0
            {
2845
0
                rWrtShell.RemoveFieldType( j );
2846
0
                break;
2847
0
            }
2848
0
    }
2849
2850
0
    return true;
2851
0
}
2852
2853
bool SwTransferable::PasteSdrFormat(  const TransferableDataHelper& rData,
2854
                                    SwWrtShell& rSh, SwPasteSdr nAction,
2855
                                    const Point* pPt, SotExchangeActionFlags nActionFlags, bool bNeedToSelectBeforePaste)
2856
0
{
2857
0
    bool bRet = false;
2858
0
    if( std::unique_ptr<SvStream> xStrm = rData.GetSotStorageStream( SotClipboardFormatId::DRAWING ))
2859
0
    {
2860
0
        xStrm->SetVersion( SOFFICE_FILEFORMAT_50 );
2861
2862
0
        if(bNeedToSelectBeforePaste && pPt)
2863
0
        {
2864
            // if this is an internal drag, need to set the target right (select it), else
2865
            // still the source will be selected
2866
0
            SwTransferable::SetSelInShell( rSh, true, pPt );
2867
0
        }
2868
2869
0
        nAction = rSh.PasteStream(*xStrm, nAction, pPt);
2870
0
        bRet = true;
2871
2872
0
        if( bRet && ( nActionFlags & SotExchangeActionFlags::InsertTargetUrl ))
2873
0
            SwTransferable::PasteTargetURL( rData, rSh, SwPasteSdr::NONE, nullptr, false );
2874
2875
0
        if (nAction == SwPasteSdr::Insert &&
2876
0
            !officecfg::Office::Writer::Cursor::Option::SelectPastedAnchoredObject::get())
2877
0
        {
2878
0
            SwTransferable::SetSelInShell(rSh, false, pPt);
2879
0
        }
2880
0
    }
2881
0
    return bRet;
2882
0
}
2883
2884
bool SwTransferable::PasteGrf( const TransferableDataHelper& rData, SwWrtShell& rSh,
2885
                                SotClipboardFormatId nFormat, SwPasteSdr nAction, const Point* pPt,
2886
        SotExchangeActionFlags const nActionFlags, sal_Int8 const nDropAction,
2887
        bool const bNeedToSelectBeforePaste, bool *const pbCallAutoCaption,
2888
        RndStdIds const nAnchorType)
2889
0
{
2890
0
    bool bRet = false;
2891
2892
0
    Graphic aGraphic;
2893
0
    INetBookmark aBkmk;
2894
0
    bool bCheckForGrf = false, bCheckForImageMap = false;
2895
2896
0
    switch( nFormat )
2897
0
    {
2898
0
    case SotClipboardFormatId::BITMAP:
2899
0
    case SotClipboardFormatId::PNG:
2900
0
    case SotClipboardFormatId::GDIMETAFILE:
2901
0
        bRet = rData.GetGraphic( nFormat, aGraphic );
2902
0
        break;
2903
2904
0
    case SotClipboardFormatId::SVXB:
2905
0
    {
2906
0
        if (std::unique_ptr<SvStream> xStm = rData.GetSotStorageStream(SotClipboardFormatId::SVXB))
2907
0
        {
2908
0
            TypeSerializer aSerializer(*xStm);
2909
0
            aSerializer.readGraphic(aGraphic);
2910
0
            bRet = (GraphicType::NONE != aGraphic.GetType() && GraphicType::Default != aGraphic.GetType());
2911
0
        }
2912
2913
0
        break;
2914
0
    }
2915
2916
0
    case SotClipboardFormatId::NETSCAPE_BOOKMARK:
2917
0
    case SotClipboardFormatId::FILEGRPDESCRIPTOR:
2918
0
    case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
2919
0
        bRet = rData.GetINetBookmark( nFormat, aBkmk );
2920
0
        if( bRet )
2921
0
        {
2922
0
            if( SwPasteSdr::SetAttr == nAction )
2923
0
                nFormat = SotClipboardFormatId::NETSCAPE_BOOKMARK;
2924
0
            else
2925
0
                bCheckForGrf = true;
2926
0
        }
2927
0
        break;
2928
2929
0
    case SotClipboardFormatId::SIMPLE_FILE:
2930
0
        {
2931
0
            OUString sText;
2932
0
            bRet = rData.GetString( nFormat, sText );
2933
0
            if( bRet )
2934
0
            {
2935
0
                OUString sDesc;
2936
0
                SwTransferable::CheckForURLOrLNKFile( rData, sText, &sDesc );
2937
2938
0
                sText = URIHelper::SmartRel2Abs(INetURLObject(), sText, Link<OUString*, bool>(),
2939
0
                    false);
2940
2941
#ifdef _WIN32
2942
                // Now that the path could be modified after SwTransferable::CheckForURLOrLNKFile,
2943
                // where it could have been converted to URL, and made sure it's actually converted
2944
                // to URL in URIHelper::SmartRel2Abs, we can finally convert file: URL back to
2945
                // system path to make sure we don't use short path.
2946
                // It looks not optimal, when we could apply GetLongPathNameW right to the original
2947
                // pasted filename. But I don't know if (1) all arriving strings are system paths;
2948
                // and (2) if SwTransferable::CheckForURLOrLNKFile could result in a different short
2949
                // path, so taking a safe route.
2950
                if (sText.startsWithIgnoreAsciiCase("file:"))
2951
                {
2952
                    // tdf#124500: Convert short path to long path which should be used in links
2953
                    OUString sSysPath;
2954
                    osl::FileBase::getSystemPathFromFileURL(sText, sSysPath);
2955
                    std::unique_ptr<sal_Unicode[]> aBuf(new sal_Unicode[EXTENDED_MAX_PATH]);
2956
                    DWORD nCopied = GetLongPathNameW(o3tl::toW(sSysPath.getStr()),
2957
                                                     o3tl::toW(aBuf.get()), EXTENDED_MAX_PATH);
2958
                    if (nCopied && nCopied < EXTENDED_MAX_PATH)
2959
                        sText = URIHelper::SmartRel2Abs(INetURLObject(), OUString(aBuf.get()),
2960
                                                        Link<OUString*, bool>(), false);
2961
                }
2962
#endif
2963
2964
0
                aBkmk = INetBookmark(sText, sDesc);
2965
0
                bCheckForGrf = true;
2966
0
                bCheckForImageMap = SwPasteSdr::Replace == nAction;
2967
0
            }
2968
0
        }
2969
0
        break;
2970
2971
0
    default:
2972
0
        bRet = rData.GetGraphic( nFormat, aGraphic );
2973
0
        break;
2974
0
    }
2975
2976
0
    if( bCheckForGrf )
2977
0
    {
2978
        //!!! check at FileSystem - only then it makes sense to test the graphics !!!
2979
0
        GraphicFilter &rFlt = GraphicFilter::GetGraphicFilter();
2980
0
        bRet = ERRCODE_NONE == GraphicFilter::LoadGraphic(aBkmk.GetURL(), OUString(),
2981
0
                                            aGraphic, &rFlt );
2982
2983
0
        if( !bRet && SwPasteSdr::SetAttr == nAction &&
2984
0
            SotClipboardFormatId::SIMPLE_FILE == nFormat &&
2985
            // only at frame selection
2986
0
            rSh.IsFrameSelected() )
2987
0
        {
2988
            // then set as hyperlink after the graphic
2989
0
            nFormat = SotClipboardFormatId::NETSCAPE_BOOKMARK;
2990
0
            bRet = true;
2991
0
        }
2992
0
    }
2993
2994
0
    if(pPt && bNeedToSelectBeforePaste)
2995
0
    {
2996
        // when using internal D&Ds, still the source object is selected and
2997
        // this is necessary to get the correct source data which is also
2998
        // dependent from selection. After receiving the drag data it is
2999
        // now time to select the correct target object
3000
0
        SwTransferable::SetSelInShell( rSh, true, pPt );
3001
0
    }
3002
3003
0
    if( bRet )
3004
0
    {
3005
        //Check and Perform rotation if needed
3006
0
        lclCheckAndPerformRotation(aGraphic);
3007
3008
0
        OUString sURL;
3009
0
        if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr
3010
            // #i123922# if link action is noted, also take URL
3011
0
            || DND_ACTION_LINK == nDropAction)
3012
0
        {
3013
0
            sURL = aBkmk.GetURL();
3014
0
        }
3015
3016
0
        switch( nAction )
3017
0
        {
3018
0
            case SwPasteSdr::Insert:
3019
0
            {
3020
0
                rSh.Push();
3021
3022
0
                SwTransferable::SetSelInShell( rSh, false, pPt );
3023
0
                rSh.InsertGraphic(sURL, OUString(), aGraphic, nullptr, nAnchorType);
3024
0
                break;
3025
0
            }
3026
3027
0
            case SwPasteSdr::Replace:
3028
0
            {
3029
0
                if( rSh.GetSelectedObjCount() )
3030
0
                {
3031
                    // #i123922# for D&D on draw objects, do for now the same for
3032
                    // SwPasteSdr::Replace (D&D) as for SwPasteSdr::SetAttr (D&D and
3033
                    // CTRL+SHIFT). The code below replaces the draw object with
3034
                    // a writer graphic; maybe this is an option later again if wanted
3035
0
                    rSh.Paste( aGraphic, sURL );
3036
3037
                    // rSh.ReplaceSdrObj(sURL, OUString(), &aGraphic);
3038
                    // Point aPt( pPt ? *pPt : rSh.GetCursorDocPos() );
3039
                    // SwTransferable::SetSelInShell( rSh, true, &aPt );
3040
0
                }
3041
0
                else
3042
0
                {
3043
                    // set graphic at writer graphic without link
3044
0
                    rSh.ReRead(sURL, OUString(), &aGraphic);
3045
0
                }
3046
3047
0
                break;
3048
0
            }
3049
3050
0
            case SwPasteSdr::SetAttr:
3051
0
            {
3052
0
                if( SotClipboardFormatId::NETSCAPE_BOOKMARK == nFormat )
3053
0
                {
3054
0
                    if( rSh.IsFrameSelected() )
3055
0
                    {
3056
0
                        SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_URL, RES_URL>( rSh.GetAttrPool() ));
3057
0
                        rSh.GetFlyFrameAttr( aSet );
3058
0
                        SwFormatURL aURL( aSet.Get( RES_URL ) );
3059
0
                        aURL.SetURL( aBkmk.GetURL(), false );
3060
0
                        aSet.Put( aURL );
3061
0
                        rSh.SetFlyFrameAttr( aSet );
3062
0
                    }
3063
0
                }
3064
0
                else if( rSh.GetSelectedObjCount() )
3065
0
                {
3066
                    // set as attribute at DrawObject
3067
0
                    rSh.Paste( aGraphic, sURL );
3068
0
                }
3069
0
                else if( OBJCNT_GRF == rSh.GetObjCntTypeOfSelection() )
3070
0
                {
3071
                    // set as linked graphic at writer graphic frame
3072
0
                    rSh.ReRead(sURL, OUString(), &aGraphic);
3073
0
                }
3074
0
                else
3075
0
                {
3076
0
                    SwTransferable::SetSelInShell( rSh, false, pPt );
3077
0
                    rSh.InsertGraphic(aBkmk.GetURL(), OUString(), aGraphic);
3078
0
                }
3079
0
                break;
3080
0
            }
3081
0
            default:
3082
0
            {
3083
0
                bRet = false;
3084
0
                break;
3085
0
            }
3086
0
        }
3087
0
    }
3088
3089
0
    if( bRet )
3090
0
    {
3091
3092
0
        if( nActionFlags &
3093
0
            ( SotExchangeActionFlags::InsertImageMap | SotExchangeActionFlags::ReplaceImageMap ) )
3094
0
            SwTransferable::PasteImageMap( rData, rSh );
3095
3096
0
        if( nActionFlags & SotExchangeActionFlags::InsertTargetUrl )
3097
0
            SwTransferable::PasteTargetURL( rData, rSh, SwPasteSdr::NONE, nullptr, false );
3098
3099
0
        if (nAction == SwPasteSdr::Insert)
3100
0
        {
3101
0
            if (!officecfg::Office::Writer::Cursor::Option::SelectPastedAnchoredObject::get())
3102
0
            {
3103
0
                SwTransferable::SetSelInShell(rSh, false, pPt);
3104
0
                rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
3105
0
            }
3106
0
            else
3107
0
            {
3108
0
                rSh.Pop(SwCursorShell::PopMode::DeleteStack);
3109
0
                if (pbCallAutoCaption)
3110
0
                {   // only possible if selected
3111
0
                    *pbCallAutoCaption = true;
3112
0
                }
3113
0
            }
3114
0
        }
3115
0
    }
3116
0
    else if( bCheckForImageMap )
3117
0
    {
3118
        // or should the file be an ImageMap-File?
3119
0
        ImageMap aMap;
3120
0
        SfxMedium aMed( INetURLObject(aBkmk.GetURL()).GetFull(),
3121
0
                            StreamMode::STD_READ );
3122
0
        SvStream* pStream = aMed.GetInStream();
3123
0
        if( pStream != nullptr  &&
3124
0
            !pStream->GetError()  &&
3125
            // mba: no BaseURL for clipboard functionality
3126
0
            aMap.Read( *pStream, IMapFormat::Detect ) == IMAP_ERR_OK &&
3127
0
            aMap.GetIMapObjectCount() )
3128
0
        {
3129
0
            SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_URL, RES_URL>( rSh.GetAttrPool() ));
3130
0
            rSh.GetFlyFrameAttr( aSet );
3131
0
            SwFormatURL aURL( aSet.Get( RES_URL ) );
3132
0
            aURL.SetMap( &aMap );
3133
0
            aSet.Put( aURL );
3134
0
            rSh.SetFlyFrameAttr( aSet );
3135
0
            bRet = true;
3136
0
        }
3137
0
    }
3138
3139
0
    return bRet;
3140
0
}
3141
3142
bool SwTransferable::PasteImageMap( const TransferableDataHelper& rData,
3143
                                    SwWrtShell& rSh )
3144
0
{
3145
0
    bool bRet = false;
3146
0
    if( rData.HasFormat( SotClipboardFormatId::SVIM ))
3147
0
    {
3148
0
        SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_URL, RES_URL>( rSh.GetAttrPool() ));
3149
0
        rSh.GetFlyFrameAttr( aSet );
3150
0
        SwFormatURL aURL( aSet.Get( RES_URL ) );
3151
0
        const ImageMap* pOld = aURL.GetMap();
3152
3153
        // set or replace, that is the question
3154
0
        ImageMap aImageMap;
3155
0
        if( rData.GetImageMap( SotClipboardFormatId::SVIM, aImageMap ) &&
3156
0
            ( !pOld || aImageMap != *pOld ))
3157
0
        {
3158
0
            aURL.SetMap( &aImageMap );
3159
0
            aSet.Put( aURL );
3160
0
            rSh.SetFlyFrameAttr( aSet );
3161
0
        }
3162
0
        bRet = true;
3163
0
    }
3164
0
    return bRet;
3165
0
}
3166
3167
bool SwTransferable::PasteAsHyperlink( const TransferableDataHelper& rData,
3168
                                        SwWrtShell& rSh, SotClipboardFormatId nFormat )
3169
0
{
3170
0
    bool bRet = false;
3171
0
    OUString sFile;
3172
0
    if( rData.GetString( nFormat, sFile ) && !sFile.isEmpty() )
3173
0
    {
3174
0
        OUString sDesc;
3175
0
        SwTransferable::CheckForURLOrLNKFile( rData, sFile, &sDesc );
3176
3177
        // first, make the URL absolute
3178
0
        INetURLObject aURL;
3179
0
        aURL.SetSmartProtocol( INetProtocol::File );
3180
0
        aURL.SetSmartURL( sFile );
3181
0
        sFile = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
3182
3183
0
        switch( rSh.GetObjCntTypeOfSelection() )
3184
0
        {
3185
0
        case OBJCNT_FLY:
3186
0
        case OBJCNT_GRF:
3187
0
        case OBJCNT_OLE:
3188
0
            {
3189
0
                SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_URL, RES_URL>( rSh.GetAttrPool() ));
3190
0
                rSh.GetFlyFrameAttr( aSet );
3191
0
                SwFormatURL aURL2( aSet.Get( RES_URL ) );
3192
0
                aURL2.SetURL( sFile, false );
3193
0
                if( aURL2.GetName().isEmpty() )
3194
0
                    aURL2.SetName( sFile );
3195
0
                aSet.Put( aURL2 );
3196
0
                rSh.SetFlyFrameAttr( aSet );
3197
0
            }
3198
0
            break;
3199
3200
0
        default:
3201
0
            {
3202
0
                rSh.InsertURL( SwFormatINetFormat( sFile, OUString() ),
3203
0
                                sDesc.isEmpty() ? sFile : sDesc);
3204
0
            }
3205
0
        }
3206
0
        bRet = true;
3207
0
    }
3208
0
    return bRet;
3209
0
}
3210
3211
bool SwTransferable::PasteFileName( const TransferableDataHelper& rData,
3212
                                    SwWrtShell& rSh, SotClipboardFormatId nFormat,
3213
                                    SwPasteSdr nAction, const Point* pPt,
3214
                                    SotExchangeActionFlags nActionFlags,
3215
                                    bool *const pbCallAutoCaption)
3216
0
{
3217
0
    bool bRet = SwTransferable::PasteGrf( rData, rSh, nFormat, nAction,
3218
0
                    pPt, nActionFlags, 0, false, pbCallAutoCaption);
3219
0
    if( !bRet )
3220
0
    {
3221
0
        OUString sFile, sDesc;
3222
0
        if( rData.GetString( nFormat, sFile ) && !sFile.isEmpty() )
3223
0
        {
3224
0
#if HAVE_FEATURE_AVMEDIA
3225
0
            INetURLObject aMediaURL;
3226
3227
0
            aMediaURL.SetSmartURL( sFile );
3228
0
            const OUString aMediaURLStr( aMediaURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
3229
3230
0
            if( ::avmedia::MediaWindow::isMediaURL( aMediaURLStr, u""_ustr/*TODO?*/ ) )
3231
0
            {
3232
0
                const SfxStringItem aMediaURLItem( SID_INSERT_AVMEDIA, aMediaURLStr );
3233
0
                rSh.GetView().GetViewFrame().GetDispatcher()->ExecuteList(
3234
0
                                SID_INSERT_AVMEDIA, SfxCallMode::SYNCHRON,
3235
0
                                { &aMediaURLItem });
3236
0
            }
3237
#else
3238
            if (false)
3239
            {
3240
            }
3241
#endif
3242
0
            else
3243
0
            {
3244
0
                bool bIsURLFile = SwTransferable::CheckForURLOrLNKFile( rData, sFile, &sDesc );
3245
3246
                //Own FileFormat? --> insert, not for StarWriter/Web
3247
0
                OUString sFileURL = URIHelper::SmartRel2Abs(INetURLObject(), sFile, Link<OUString *, bool>(), false );
3248
0
                std::shared_ptr<const SfxFilter> pFlt = SwPasteSdr::SetAttr == nAction
3249
0
                        ? nullptr : SwIoSystem::GetFileFilter(sFileURL);
3250
0
                if( pFlt && dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) == nullptr )
3251
0
                {
3252
                    // and then pull up the insert-region-dialog
3253
0
                    SwSectionData aSect(
3254
0
                                    SectionType::FileLink,
3255
0
                                    UIName(rSh.GetDoc()->GetUniqueSectionName()) );
3256
0
                    aSect.SetLinkFileName( sFileURL );
3257
0
                    aSect.SetProtectFlag( true );
3258
3259
0
                    rSh.StartInsertRegionDialog( aSect ); // starts dialog asynchronously
3260
0
                    bRet = true;
3261
0
                }
3262
0
                else if (SwPasteSdr::Insert == nAction && rData.HasFormat(SotClipboardFormatId::SIMPLE_FILE))
3263
0
                {
3264
                    // insert file as OLE
3265
0
                    PasteOLE(rData, rSh, nFormat, nActionFlags, nullptr == pPt);
3266
0
                }
3267
0
                else if( SwPasteSdr::SetAttr == nAction ||
3268
0
                        ( bIsURLFile && SwPasteSdr::Insert == nAction ))
3269
0
                {
3270
                    //we can insert foreign files as links after all
3271
3272
                    // first, make the URL absolute
3273
0
                    INetURLObject aURL;
3274
0
                    aURL.SetSmartProtocol( INetProtocol::File );
3275
0
                    aURL.SetSmartURL( sFile );
3276
0
                    sFile = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
3277
3278
0
                    switch( rSh.GetObjCntTypeOfSelection() )
3279
0
                    {
3280
0
                    case OBJCNT_FLY:
3281
0
                    case OBJCNT_GRF:
3282
0
                    case OBJCNT_OLE:
3283
0
                        {
3284
0
                            SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_URL, RES_URL>( rSh.GetAttrPool() ));
3285
0
                            rSh.GetFlyFrameAttr( aSet );
3286
0
                            SwFormatURL aURL2( aSet.Get( RES_URL ) );
3287
0
                            aURL2.SetURL( sFile, false );
3288
0
                            if( aURL2.GetName().isEmpty() )
3289
0
                                aURL2.SetName( sFile );
3290
0
                            aSet.Put( aURL2 );
3291
0
                            rSh.SetFlyFrameAttr( aSet );
3292
0
                        }
3293
0
                        break;
3294
3295
0
                    default:
3296
0
                        {
3297
0
                            rSh.InsertURL( SwFormatINetFormat( sFile, OUString() ),
3298
0
                                            sDesc.isEmpty() ? sFile : sDesc );
3299
0
                        }
3300
0
                    }
3301
0
                    bRet = true;
3302
0
                }
3303
0
            }
3304
0
        }
3305
0
    }
3306
0
    return bRet;
3307
0
}
3308
3309
bool SwTransferable::PasteDBData( const TransferableDataHelper& rData,
3310
                                    SwWrtShell& rSh, SotClipboardFormatId nFormat, bool bLink,
3311
                                    const Point* pDragPt, bool bMsg )
3312
0
{
3313
0
    bool bRet = false;
3314
0
    OUString sText;
3315
0
    if( rData.GetString( nFormat, sText ) && !sText.isEmpty() )
3316
0
    {
3317
0
        sal_uInt16 nWh = SotClipboardFormatId::SBA_CTRLDATAEXCHANGE == nFormat
3318
0
                    ? 0
3319
0
                    : SotClipboardFormatId::SBA_DATAEXCHANGE == nFormat
3320
0
                                ? (bLink
3321
0
                                    ? FN_QRY_MERGE_FIELD
3322
0
                                    : FN_QRY_INSERT)
3323
0
                                : (bLink
3324
0
                                    ? 0
3325
0
                                    : FN_QRY_INSERT_FIELD );
3326
0
        const DataFlavorExVector& rVector = rData.GetDataFlavorExVector();
3327
0
        bool bHaveColumnDescriptor = OColumnTransferable::canExtractColumnDescriptor(rVector, ColumnTransferFormatFlags::COLUMN_DESCRIPTOR | ColumnTransferFormatFlags::CONTROL_EXCHANGE);
3328
0
        if ( SotClipboardFormatId::XFORMS == nFormat )
3329
0
        {
3330
0
            rSh.MakeDrawView();
3331
0
            FmFormView* pFmView = dynamic_cast<FmFormView*>( rSh.GetDrawView()  );
3332
0
            if (pFmView && pDragPt)
3333
0
            {
3334
0
                OXFormsDescriptor aDesc = OXFormsTransferable::extractDescriptor(rData);
3335
0
                rtl::Reference<SdrObject> pObj = pFmView->CreateXFormsControl(aDesc);
3336
0
                if(pObj)
3337
0
                {
3338
0
                    rSh.SwFEShell::InsertDrawObj( *pObj, *pDragPt );
3339
0
                }
3340
0
            }
3341
0
        }
3342
0
        else if( nWh )
3343
0
        {
3344
0
            std::unique_ptr<SfxUnoAnyItem> pConnectionItem;
3345
0
            std::unique_ptr<SfxUnoAnyItem> pCursorItem;
3346
0
            std::unique_ptr<SfxUnoAnyItem> pColumnItem;
3347
0
            std::unique_ptr<SfxUnoAnyItem> pSourceItem;
3348
0
            std::unique_ptr<SfxUnoAnyItem> pCommandItem;
3349
0
            std::unique_ptr<SfxUnoAnyItem> pCommandTypeItem;
3350
0
            std::unique_ptr<SfxUnoAnyItem> pColumnNameItem;
3351
0
            std::unique_ptr<SfxUnoAnyItem> pSelectionItem;
3352
3353
0
            bool bDataAvailable = true;
3354
0
            ODataAccessDescriptor aDesc;
3355
0
            if(bHaveColumnDescriptor)
3356
0
                aDesc = OColumnTransferable::extractColumnDescriptor(rData);
3357
0
            else if(ODataAccessObjectTransferable::canExtractObjectDescriptor(rVector) )
3358
0
                aDesc = ODataAccessObjectTransferable::extractObjectDescriptor(rData);
3359
0
            else
3360
0
                bDataAvailable = false;
3361
3362
0
            if ( bDataAvailable )
3363
0
            {
3364
0
                pConnectionItem.reset(new SfxUnoAnyItem(FN_DB_CONNECTION_ANY, aDesc[DataAccessDescriptorProperty::Connection]));
3365
0
                pColumnItem.reset(new SfxUnoAnyItem(FN_DB_COLUMN_ANY, aDesc[DataAccessDescriptorProperty::ColumnObject]));
3366
0
                pSourceItem.reset(new SfxUnoAnyItem(FN_DB_DATA_SOURCE_ANY, Any(aDesc.getDataSource())));
3367
0
                pCommandItem.reset(new SfxUnoAnyItem(FN_DB_DATA_COMMAND_ANY, aDesc[DataAccessDescriptorProperty::Command]));
3368
0
                pCommandTypeItem.reset(new SfxUnoAnyItem(FN_DB_DATA_COMMAND_TYPE_ANY, aDesc[DataAccessDescriptorProperty::CommandType]));
3369
0
                pColumnNameItem.reset(new SfxUnoAnyItem(FN_DB_DATA_COLUMN_NAME_ANY, aDesc[DataAccessDescriptorProperty::ColumnName]));
3370
0
                pSelectionItem.reset(new SfxUnoAnyItem(FN_DB_DATA_SELECTION_ANY, aDesc[DataAccessDescriptorProperty::Selection]));
3371
0
                pCursorItem.reset(new SfxUnoAnyItem(FN_DB_DATA_CURSOR_ANY, aDesc[DataAccessDescriptorProperty::Cursor]));
3372
0
            }
3373
3374
0
            SwView& rView = rSh.GetView();
3375
            //force ::SelectShell
3376
0
            rView.StopShellTimer();
3377
3378
0
            SfxStringItem aDataDesc( nWh, sText );
3379
0
            rView.GetViewFrame().GetDispatcher()->ExecuteList(
3380
0
                nWh, SfxCallMode::ASYNCHRON,
3381
0
                { &aDataDesc, pConnectionItem.get(), pColumnItem.get(),
3382
0
                  pSourceItem.get(), pCommandItem.get(), pCommandTypeItem.get(),
3383
0
                  pColumnNameItem.get(), pSelectionItem.get(),
3384
0
                  pCursorItem.get() });
3385
0
        }
3386
0
        else
3387
0
        {
3388
0
            rSh.MakeDrawView();
3389
0
            FmFormView* pFmView = dynamic_cast<FmFormView*>( rSh.GetDrawView()  );
3390
0
            if (pFmView && bHaveColumnDescriptor && pDragPt)
3391
0
            {
3392
0
                rtl::Reference<SdrObject> pObj = pFmView->CreateFieldControl( OColumnTransferable::extractColumnDescriptor(rData) );
3393
0
                if (pObj)
3394
0
                    rSh.SwFEShell::InsertDrawObj( *pObj, *pDragPt );
3395
0
            }
3396
0
        }
3397
0
        bRet = true;
3398
0
    }
3399
0
    else if( bMsg )
3400
0
    {
3401
0
        std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
3402
0
                                                  VclMessageType::Info, VclButtonsType::Ok,
3403
0
                                                  SwResId(STR_CLPBRD_FORMAT_ERROR)));
3404
0
        xBox->run();
3405
0
    }
3406
0
    return bRet;
3407
0
}
3408
3409
bool SwTransferable::PasteFileList( const TransferableDataHelper& rData,
3410
                                    SwWrtShell& rSh, bool bLink,
3411
                                    const Point* pPt, bool bMsg,
3412
                                    bool *const pbCallAutoCaption)
3413
0
{
3414
0
    bool bRet = false;
3415
0
    FileList aFileList;
3416
0
    if( rData.GetFileList( SotClipboardFormatId::FILE_LIST, aFileList ) &&
3417
0
        aFileList.Count() )
3418
0
    {
3419
0
        SwPasteSdr nAct = bLink ? SwPasteSdr::SetAttr : SwPasteSdr::Insert;
3420
0
        UIName sFlyNm;
3421
        // iterate over the filelist
3422
0
        for( sal_uLong n = 0, nEnd = aFileList.Count(); n < nEnd; ++n )
3423
0
        {
3424
0
            rtl::Reference<TransferDataContainer> pHlp = new TransferDataContainer;
3425
0
            pHlp->CopyString( SotClipboardFormatId::SIMPLE_FILE, aFileList.GetFile( n ));
3426
0
            TransferableDataHelper aData( pHlp );
3427
3428
0
            if( SwTransferable::PasteFileName( aData, rSh, SotClipboardFormatId::SIMPLE_FILE, nAct,
3429
0
                    pPt, SotExchangeActionFlags::NONE,
3430
                    // only caption a single image (PasteGrf only sets true for Insert)
3431
0
                    aFileList.Count() == 1 ? pbCallAutoCaption : nullptr))
3432
0
            {
3433
0
                if( bLink )
3434
0
                {
3435
0
                    sFlyNm = rSh.GetFlyName();
3436
0
                    SwTransferable::SetSelInShell( rSh, false, pPt );
3437
0
                }
3438
0
                bRet = true;
3439
0
            }
3440
0
        }
3441
0
        if( !sFlyNm.isEmpty() )
3442
0
            rSh.GotoFly( sFlyNm );
3443
0
    }
3444
0
    else if( bMsg )
3445
0
    {
3446
0
        std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(nullptr,
3447
0
                                                  VclMessageType::Info, VclButtonsType::Ok,
3448
0
                                                  SwResId(STR_CLPBRD_FORMAT_ERROR)));
3449
0
        xBox->run();
3450
0
    }
3451
0
    return bRet;
3452
0
}
3453
3454
bool SwTransferable::CheckForURLOrLNKFile( const TransferableDataHelper& rData,
3455
                                        OUString& rFileName, OUString* pTitle )
3456
0
{
3457
0
    bool bIsURLFile = false;
3458
0
    INetBookmark aBkmk;
3459
0
    if( rData.GetINetBookmark( SotClipboardFormatId::SOLK, aBkmk ) )
3460
0
    {
3461
0
        rFileName = aBkmk.GetURL();
3462
0
        if( pTitle )
3463
0
            *pTitle = aBkmk.GetDescription();
3464
0
        bIsURLFile = true;
3465
0
    }
3466
0
    else
3467
0
    {
3468
0
        if( rFileName.getLength()>4 && rFileName.endsWithIgnoreAsciiCase(".url") )
3469
0
        {
3470
0
            OSL_ENSURE( false, "how do we read today .URL - Files?" );
3471
0
        }
3472
0
    }
3473
0
    return bIsURLFile;
3474
0
}
3475
3476
bool SwTransferable::IsPasteSpecial( const SwWrtShell& rWrtShell,
3477
                                     const TransferableDataHelper& rData )
3478
0
{
3479
    // we can paste-special if there's an entry in the paste-special-format list
3480
0
    SvxClipboardFormatItem aClipboardFormatItem(TypedWhichId<SvxClipboardFormatItem>(0));
3481
0
    FillClipFormatItem( rWrtShell, rData, aClipboardFormatItem);
3482
0
    return aClipboardFormatItem.Count() > 0;
3483
0
}
3484
3485
bool SwTransferable::IsPasteOwnFormat( const TransferableDataHelper& rData )
3486
0
{
3487
0
    return ( GetSwTransferable( rData ) != nullptr );
3488
0
}
3489
3490
bool SwTransferable::PasteFormat( SwWrtShell& rSh,
3491
                                    const TransferableDataHelper& rData,
3492
                                    SotClipboardFormatId nFormat )
3493
0
{
3494
0
    SwWait aWait( *rSh.GetView().GetDocShell(), false );
3495
0
    bool bRet = false;
3496
3497
0
    SotClipboardFormatId nPrivateFormat = SotClipboardFormatId::PRIVATE;
3498
0
    SwTransferable *pClipboard = GetSwTransferable( rData );
3499
0
    if( pClipboard &&
3500
0
        ((TransferBufferType::Document|TransferBufferType::Graphic|TransferBufferType::Ole) & pClipboard->m_eBufferType ))
3501
0
        nPrivateFormat = SotClipboardFormatId::EMBED_SOURCE;
3502
3503
0
    if( pClipboard && nPrivateFormat == nFormat )
3504
0
        bRet = pClipboard->PrivatePaste( rSh );
3505
0
    else if( rData.HasFormat( nFormat ) )
3506
0
    {
3507
0
        uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
3508
0
        sal_uInt8       nEventAction;
3509
0
        SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
3510
0
        sal_uInt16      nSourceOptions =
3511
0
                    (( SotExchangeDest::DOC_TEXTFRAME == nDestination ||
3512
0
                       SotExchangeDest::SWDOC_FREE_AREA == nDestination ||
3513
0
                       SotExchangeDest::DOC_TEXTFRAME_WEB == nDestination ||
3514
0
                       SotExchangeDest::SWDOC_FREE_AREA_WEB == nDestination )
3515
0
                                        ? EXCHG_IN_ACTION_COPY
3516
0
                                        : EXCHG_IN_ACTION_MOVE);
3517
0
        SotExchangeActionFlags nActionFlags;
3518
0
        sal_uInt8      nAction = SotExchange::GetExchangeAction(
3519
0
                                    rData.GetDataFlavorExVector(),
3520
0
                                    nDestination,
3521
0
                                    nSourceOptions,             /* ?? */
3522
0
                                    EXCHG_IN_ACTION_DEFAULT,    /* ?? */
3523
0
                                    nFormat, nEventAction, nFormat,
3524
0
                                    lcl_getTransferPointer ( xTransferable ),
3525
0
                                    &nActionFlags );
3526
3527
0
        if( EXCHG_INOUT_ACTION_NONE != nAction )
3528
0
            bRet = SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
3529
0
                                                nDestination, true, false );
3530
0
    }
3531
0
    return bRet;
3532
0
}
3533
3534
bool SwTransferable::TestAllowedFormat( const TransferableDataHelper& rData,
3535
                                        SotClipboardFormatId nFormat, SotExchangeDest nDestination )
3536
0
{
3537
0
    sal_uInt8 nAction = EXCHG_INOUT_ACTION_NONE;
3538
0
    if( rData.HasFormat( nFormat )) {
3539
0
        uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
3540
0
        sal_uInt8 nEventAction;
3541
0
        nAction = SotExchange::GetExchangeAction(
3542
0
                        rData.GetDataFlavorExVector(),
3543
0
                        nDestination, EXCHG_IN_ACTION_COPY,
3544
0
                        EXCHG_IN_ACTION_COPY, nFormat,
3545
0
                        nEventAction, nFormat,
3546
0
                        lcl_getTransferPointer ( xTransferable ) );
3547
0
    }
3548
0
    return EXCHG_INOUT_ACTION_NONE != nAction;
3549
0
}
3550
3551
/**
3552
 * the list of formats which will be offered to the user in the 'Paste
3553
 * Special...' dialog and the paste button menu
3554
 */
3555
const SotClipboardFormatId aPasteSpecialIds[] =
3556
{
3557
    SotClipboardFormatId::HTML,
3558
    SotClipboardFormatId::HTML_SIMPLE,
3559
    SotClipboardFormatId::HTML_NO_COMMENT,
3560
    SotClipboardFormatId::RTF,
3561
    SotClipboardFormatId::RICHTEXT,
3562
    SotClipboardFormatId::STRING,
3563
    SotClipboardFormatId::SONLK,
3564
    SotClipboardFormatId::NETSCAPE_BOOKMARK,
3565
    SotClipboardFormatId::DRAWING,
3566
    SotClipboardFormatId::SVXB,
3567
    SotClipboardFormatId::GDIMETAFILE,
3568
    SotClipboardFormatId::BITMAP,
3569
    SotClipboardFormatId::SVIM,
3570
    SotClipboardFormatId::FILEGRPDESCRIPTOR,
3571
    SotClipboardFormatId::MARKDOWN,
3572
    SotClipboardFormatId::NONE
3573
};
3574
3575
bool SwTransferable::PasteUnformatted( SwWrtShell& rSh, const TransferableDataHelper& rData )
3576
0
{
3577
    // Plain text == unformatted
3578
0
    return SwTransferable::PasteFormat( rSh, rData, SotClipboardFormatId::STRING );
3579
0
}
3580
3581
void SwTransferable::PrePasteSpecial( const SwWrtShell& rSh, const TransferableDataHelper& rData, const VclPtr<SfxAbstractPasteDialog>& pDlg )
3582
0
{
3583
0
    DataFlavorExVector aFormats( rData.GetDataFlavorExVector() );
3584
0
    TransferableObjectDescriptor aDesc;
3585
3586
0
    SotExchangeDest nDest = SwTransferable::GetSotDestination( rSh );
3587
3588
0
    SwTransferable *pClipboard = GetSwTransferable( rData );
3589
0
    if( pClipboard )
3590
0
    {
3591
0
        aDesc = pClipboard->m_aObjDesc;
3592
0
        TranslateId pResId;
3593
0
        if( pClipboard->m_eBufferType & TransferBufferType::Document )
3594
0
            pResId = STR_PRIVATETEXT;
3595
0
        else if( pClipboard->m_eBufferType & TransferBufferType::Graphic )
3596
0
            pResId = STR_PRIVATEGRAPHIC;
3597
0
        else if( pClipboard->m_eBufferType == TransferBufferType::Ole )
3598
0
            pResId = STR_PRIVATEOLE;
3599
3600
0
        if (pResId)
3601
0
        {
3602
0
            if (STR_PRIVATEOLE == pResId || STR_PRIVATEGRAPHIC == pResId)
3603
0
            {
3604
                // add SotClipboardFormatId::EMBED_SOURCE to the formats. This
3605
                // format display then the private format name.
3606
0
                DataFlavorEx aFlavorEx;
3607
0
                aFlavorEx.mnSotId = SotClipboardFormatId::EMBED_SOURCE;
3608
0
                aFormats.insert( aFormats.begin(), aFlavorEx );
3609
0
            }
3610
0
            pDlg->SetObjName( pClipboard->m_aObjDesc.maClassName,
3611
0
                                SwResId(pResId) );
3612
0
            pDlg->Insert( SotClipboardFormatId::EMBED_SOURCE, OUString() );
3613
0
        }
3614
0
    }
3615
0
    else
3616
0
    {
3617
0
        if( rData.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR ) )
3618
0
        {
3619
0
            (void)rData.GetTransferableObjectDescriptor(
3620
0
                                SotClipboardFormatId::OBJECTDESCRIPTOR, aDesc );
3621
0
        }
3622
3623
0
        if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::EMBED_SOURCE, nDest ))
3624
0
            pDlg->Insert( SotClipboardFormatId::EMBED_SOURCE, OUString() );
3625
0
        if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK_SOURCE, nDest ))
3626
0
            pDlg->Insert( SotClipboardFormatId::LINK_SOURCE, OUString() );
3627
0
    }
3628
3629
0
    if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK, nDest ))
3630
0
        pDlg->Insert( SotClipboardFormatId::LINK, SwResId(STR_DDEFORMAT) );
3631
3632
0
    for( const SotClipboardFormatId* pIds = aPasteSpecialIds; *pIds != SotClipboardFormatId::NONE; ++pIds )
3633
0
        if( SwTransferable::TestAllowedFormat( rData, *pIds, nDest ))
3634
0
            pDlg->Insert( *pIds, OUString() );
3635
0
}
3636
3637
void SwTransferable::FillClipFormatItem( const SwWrtShell& rSh,
3638
                                const TransferableDataHelper& rData,
3639
                                SvxClipboardFormatItem & rToFill )
3640
0
{
3641
0
    SotExchangeDest nDest = SwTransferable::GetSotDestination( rSh );
3642
3643
0
    SwTransferable *pClipboard = GetSwTransferable( rData );
3644
0
    if( pClipboard )
3645
0
    {
3646
0
        TranslateId pResId;
3647
0
        if( pClipboard->m_eBufferType & TransferBufferType::Document )
3648
0
            pResId = STR_PRIVATETEXT;
3649
0
        else if( pClipboard->m_eBufferType & TransferBufferType::Graphic )
3650
0
            pResId = STR_PRIVATEGRAPHIC;
3651
0
        else if( pClipboard->m_eBufferType == TransferBufferType::Ole )
3652
0
            pResId = STR_PRIVATEOLE;
3653
3654
0
        if (pResId)
3655
0
            rToFill.AddClipbrdFormat(SotClipboardFormatId::EMBED_SOURCE,
3656
0
                                       SwResId(pResId));
3657
0
    }
3658
0
    else
3659
0
    {
3660
0
        TransferableObjectDescriptor aDesc;
3661
0
        if (rData.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR))
3662
0
        {
3663
0
            (void)rData.GetTransferableObjectDescriptor(
3664
0
                                SotClipboardFormatId::OBJECTDESCRIPTOR, aDesc);
3665
0
        }
3666
3667
0
        if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::EMBED_SOURCE, nDest ))
3668
0
            rToFill.AddClipbrdFormat( SotClipboardFormatId::EMBED_SOURCE,
3669
0
                                            aDesc.maTypeName );
3670
0
        if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK_SOURCE, nDest ))
3671
0
            rToFill.AddClipbrdFormat( SotClipboardFormatId::LINK_SOURCE );
3672
3673
0
        SotClipboardFormatId nFormat;
3674
0
        if ( rData.HasFormat(nFormat = SotClipboardFormatId::EMBED_SOURCE_OLE) || rData.HasFormat(nFormat = SotClipboardFormatId::EMBEDDED_OBJ_OLE) )
3675
0
        {
3676
0
            OUString sName,sSource;
3677
0
            if ( SvPasteObjectHelper::GetEmbeddedName(rData,sName,sSource,nFormat) )
3678
0
                rToFill.AddClipbrdFormat( nFormat, sName );
3679
0
        }
3680
0
    }
3681
3682
0
    if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK, nDest ))
3683
0
        rToFill.AddClipbrdFormat( SotClipboardFormatId::LINK, SwResId(STR_DDEFORMAT) );
3684
3685
0
    for( const SotClipboardFormatId* pIds = aPasteSpecialIds; *pIds != SotClipboardFormatId::NONE; ++pIds )
3686
0
        if( SwTransferable::TestAllowedFormat( rData, *pIds, nDest ))
3687
0
            rToFill.AddClipbrdFormat(*pIds, OUString());
3688
0
}
3689
3690
void SwTransferable::SetDataForDragAndDrop( const Point& rSttPos )
3691
0
{
3692
0
    if(!m_pWrtShell)
3693
0
        return;
3694
0
    OUString sGrfNm;
3695
0
    const SelectionType nSelection = m_pWrtShell->GetSelectionType();
3696
0
    if( SelectionType::Graphic == nSelection)
3697
0
    {
3698
0
        AddFormat( SotClipboardFormatId::SVXB );
3699
0
        const Graphic* pGrf = m_pWrtShell->GetGraphic();
3700
0
        if ( pGrf && pGrf->IsSupportedGraphic() )
3701
0
        {
3702
0
            AddFormat( SotClipboardFormatId::GDIMETAFILE );
3703
0
            AddFormat( SotClipboardFormatId::PNG );
3704
0
            AddFormat( SotClipboardFormatId::BITMAP );
3705
0
        }
3706
0
        m_eBufferType = TransferBufferType::Graphic;
3707
0
        m_pWrtShell->GetGrfNms( &sGrfNm, nullptr );
3708
0
    }
3709
0
    else if( SelectionType::Ole == nSelection )
3710
0
    {
3711
0
        AddFormat( SotClipboardFormatId::EMBED_SOURCE );
3712
0
        PrepareOLE( m_aObjDesc );
3713
0
        AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
3714
0
        AddFormat( SotClipboardFormatId::GDIMETAFILE );
3715
0
        m_eBufferType = TransferBufferType::Ole;
3716
0
    }
3717
    //Is there anything to provide anyway?
3718
0
    else if ( m_pWrtShell->IsSelection() || m_pWrtShell->IsFrameSelected() ||
3719
0
              m_pWrtShell->GetSelectedObjCount() )
3720
0
    {
3721
0
        if( m_pWrtShell->GetSelectedObjCount() )
3722
0
            m_eBufferType = TransferBufferType::Drawing;
3723
0
        else
3724
0
        {
3725
0
            m_eBufferType = TransferBufferType::Document;
3726
0
            if( SwWrtShell::NO_WORD !=
3727
0
                m_pWrtShell->IntelligentCut( nSelection, false ))
3728
0
                m_eBufferType = TransferBufferType::DocumentWord | m_eBufferType;
3729
0
        }
3730
3731
0
        if( nSelection & SelectionType::TableCell )
3732
0
            m_eBufferType = TransferBufferType::Table | m_eBufferType;
3733
3734
0
        AddFormat( SotClipboardFormatId::EMBED_SOURCE );
3735
3736
        //put RTF ahead of the OLE's Metafile for less loss
3737
0
        if( !m_pWrtShell->GetSelectedObjCount() )
3738
0
        {
3739
0
            AddFormat( SotClipboardFormatId::RTF );
3740
0
            AddFormat( SotClipboardFormatId::RICHTEXT );
3741
0
            AddFormat( SotClipboardFormatId::HTML );
3742
0
            AddFormat( SotClipboardFormatId::MARKDOWN );
3743
0
        }
3744
0
        if( m_pWrtShell->IsSelection() )
3745
0
            AddFormat( SotClipboardFormatId::STRING );
3746
3747
0
        if( nSelection & ( SelectionType::DrawObject | SelectionType::DbForm ))
3748
0
        {
3749
0
            AddFormat( SotClipboardFormatId::DRAWING );
3750
0
            if ( nSelection & SelectionType::DrawObject )
3751
0
            {
3752
0
                AddFormat( SotClipboardFormatId::GDIMETAFILE );
3753
0
                AddFormat( SotClipboardFormatId::PNG );
3754
0
                AddFormat( SotClipboardFormatId::BITMAP );
3755
0
            }
3756
0
            m_eBufferType = TransferBufferType::Graphic | m_eBufferType;
3757
3758
            // is it a URL-Button ?
3759
0
            OUString sURL;
3760
0
            OUString sDesc;
3761
0
            if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) )
3762
0
            {
3763
0
                AddFormat( SotClipboardFormatId::STRING );
3764
0
                AddFormat( SotClipboardFormatId::SOLK );
3765
0
                AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
3766
0
                AddFormat( SotClipboardFormatId::FILECONTENT );
3767
0
                AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
3768
0
                AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
3769
0
                m_eBufferType = TransferBufferType::InetField | m_eBufferType;
3770
0
            }
3771
0
        }
3772
3773
        //ObjectDescriptor was already filled from the old DocShell.
3774
        //Now adjust it. Thus in GetData the first query can still
3775
        //be answered with delayed rendering.
3776
0
        m_aObjDesc.maDragStartPos = rSttPos;
3777
0
        m_aObjDesc.maSize = constOleSize100mm;
3778
3779
0
        PrepareOLE( m_aObjDesc );
3780
0
        AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
3781
0
    }
3782
0
    else if( nSelection & SelectionType::Text && !m_pWrtShell->HasMark() )
3783
0
    {
3784
        // is only one field - selected?
3785
0
        SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
3786
0
        Point aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY());
3787
3788
0
        if( m_pWrtShell->GetContentAtPos( aPos, aContentAtPos ) )
3789
0
        {
3790
0
            AddFormat( SotClipboardFormatId::STRING );
3791
0
            AddFormat( SotClipboardFormatId::SOLK );
3792
0
            AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
3793
0
            AddFormat( SotClipboardFormatId::FILECONTENT );
3794
0
            AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
3795
0
            AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
3796
0
            m_eBufferType = TransferBufferType::InetField;
3797
0
        }
3798
0
    }
3799
3800
0
    if( !m_pWrtShell->IsFrameSelected() )
3801
0
        return;
3802
3803
0
    SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_URL, RES_URL>( m_pWrtShell->GetAttrPool() ));
3804
0
    m_pWrtShell->GetFlyFrameAttr( aSet );
3805
0
    const SwFormatURL& rURL = aSet.Get( RES_URL );
3806
0
    if( rURL.GetMap() )
3807
0
    {
3808
0
        m_pImageMap.reset( new ImageMap( *rURL.GetMap() ) );
3809
0
        AddFormat( SotClipboardFormatId::SVIM );
3810
0
    }
3811
0
    else if( !rURL.GetURL().isEmpty() )
3812
0
    {
3813
0
        m_pTargetURL.reset(new INetImage( sGrfNm, rURL.GetURL(),
3814
0
                                    rURL.GetTargetFrameName() ));
3815
0
        AddFormat( SotClipboardFormatId::INET_IMAGE );
3816
0
    }
3817
0
}
3818
3819
void SwTransferable::StartDrag( vcl::Window* pWin, const Point& rPos )
3820
0
{
3821
0
    if(!m_pWrtShell)
3822
0
        return;
3823
0
    m_bOldIdle = m_pWrtShell->GetViewOptions()->IsIdle();
3824
0
    m_bCleanUp = true;
3825
3826
0
    m_pWrtShell->GetViewOptions()->SetIdle( false );
3827
3828
0
    if( m_pWrtShell->IsSelFrameMode() )
3829
0
        m_pWrtShell->ShowCursor();
3830
3831
0
    SwModule::get()->m_pDragDrop = this;
3832
3833
0
    SetDataForDragAndDrop( rPos );
3834
3835
0
    sal_Int8 nDragOptions = DND_ACTION_COPYMOVE | DND_ACTION_LINK;
3836
0
    SwDocShell* pDShell = m_pWrtShell->GetView().GetDocShell();
3837
0
    if( ( pDShell && pDShell->IsReadOnly() ) || m_pWrtShell->HasReadonlySel() )
3838
0
        nDragOptions &= ~DND_ACTION_MOVE;
3839
3840
0
    TransferableHelper::StartDrag( pWin, nDragOptions );
3841
0
}
3842
3843
void SwTransferable::DragFinished( sal_Int8 nAction )
3844
0
{
3845
    //And the last finishing work so that all statuses are right
3846
0
    if( DND_ACTION_MOVE == nAction  )
3847
0
    {
3848
0
        if( m_bCleanUp )
3849
0
        {
3850
            //It was dropped outside of Writer. We still have to
3851
            //delete.
3852
3853
0
            m_pWrtShell->StartAllAction();
3854
0
            m_pWrtShell->StartUndo( SwUndoId::UI_DRAG_AND_MOVE );
3855
0
            if ( m_pWrtShell->IsTableMode() )
3856
0
                m_pWrtShell->DeleteTableSel();
3857
0
            else
3858
0
            {
3859
0
                if ( !(m_pWrtShell->IsSelFrameMode() || m_pWrtShell->GetSelectedObjCount()) )
3860
                    //SmartCut, take one of the blanks along
3861
0
                    m_pWrtShell->IntelligentCut( m_pWrtShell->GetSelectionType() );
3862
0
                m_pWrtShell->DelRight();
3863
0
            }
3864
0
            m_pWrtShell->EndUndo( SwUndoId::UI_DRAG_AND_MOVE );
3865
0
            m_pWrtShell->EndAllAction();
3866
0
        }
3867
0
        else
3868
0
        {
3869
0
            const SelectionType nSelection = m_pWrtShell->GetSelectionType();
3870
0
            if( ( SelectionType::Frame | SelectionType::Graphic |
3871
0
                 SelectionType::Ole | SelectionType::DrawObject ) & nSelection )
3872
0
            {
3873
0
                m_pWrtShell->EnterSelFrameMode();
3874
0
            }
3875
0
        }
3876
0
    }
3877
0
    m_pWrtShell->GetView().GetEditWin().DragFinished();
3878
3879
0
    if( m_pWrtShell->IsSelFrameMode() )
3880
0
        m_pWrtShell->HideCursor();
3881
0
    else
3882
0
        m_pWrtShell->ShowCursor();
3883
3884
0
    m_pWrtShell->GetViewOptions()->SetIdle( m_bOldIdle );
3885
0
}
3886
3887
namespace
3888
{
3889
3890
bool lcl_checkClassification(SwDoc* pSourceDoc, SwDoc* pDestinationDoc)
3891
0
{
3892
0
    if (!pSourceDoc || !pDestinationDoc)
3893
0
        return true;
3894
3895
0
    SwDocShell* pSourceShell = pSourceDoc->GetDocShell();
3896
0
    SwDocShell* pDestinationShell = pDestinationDoc->GetDocShell();
3897
0
    if (!pSourceShell || !pDestinationShell)
3898
0
        return true;
3899
3900
0
    SfxClassificationCheckPasteResult eResult = SfxClassificationHelper::CheckPaste(pSourceShell->getDocProperties(), pDestinationShell->getDocProperties());
3901
0
    return SfxClassificationHelper::ShowPasteInfo(eResult);
3902
0
}
3903
3904
}
3905
3906
bool SwTransferable::PrivatePaste(SwWrtShell& rShell, SwPasteContext* pContext, PasteTableType ePasteTable)
3907
0
{
3908
    // first, ask for the SelectionType, then action-bracketing !!!!
3909
    // (otherwise it's not pasted into a TableSelection!!!)
3910
0
    OSL_ENSURE( !rShell.ActionPend(), "Paste must never have an ActionPend" );
3911
0
    if ( !m_pClpDocFac )
3912
0
        return false; // the return value of the SwFEShell::Paste also is bool!
3913
3914
0
    const SelectionType nSelection = rShell.GetSelectionType();
3915
3916
0
    ::std::optional<SwTrnsfrActionAndUndo> oAction(&rShell);
3917
3918
0
    bool bKillPaMs = false;
3919
3920
    //Delete selected content, not at table-selection and table in Clipboard, and don't delete hovering graphics.
3921
0
    if( rShell.HasSelection() && !( nSelection & SelectionType::TableCell) && !( nSelection & SelectionType::DrawObject))
3922
0
    {
3923
0
        if (!(nSelection & SelectionType::NumberList))
3924
0
        {
3925
0
            bKillPaMs = true;
3926
0
            rShell.SetRetainSelection( true );
3927
0
        }
3928
0
        if (pContext)
3929
0
            pContext->forget();
3930
0
        rShell.DelRight();
3931
0
        if (pContext)
3932
0
            pContext->remember();
3933
        // when a Fly was selected, a valid cursor position has to be found now
3934
        // (parked Cursor!)
3935
0
        if( ( SelectionType::Frame | SelectionType::Graphic |
3936
0
            SelectionType::Ole | SelectionType::DrawObject |
3937
0
            SelectionType::DbForm ) & nSelection )
3938
0
        {
3939
            // position the cursor again
3940
0
            Point aPt( rShell.GetCharRect().Pos() );
3941
0
            rShell.SwCursorShell::SetCursor( aPt, true );
3942
0
        }
3943
0
        if (!(nSelection & SelectionType::NumberList))
3944
0
        {
3945
0
            rShell.SetRetainSelection( false );
3946
0
        }
3947
0
    }
3948
0
    if ( nSelection & SelectionType::DrawObject) //unselect hovering graphics
3949
0
    {
3950
0
        rShell.ResetSelect(nullptr, false, ScrollSizeMode::ScrollSizeDefault);
3951
0
    }
3952
3953
0
    bool bInWrd = false, bEndWrd = false, bSttWrd = false,
3954
0
         bSmart(TransferBufferType::DocumentWord & m_eBufferType);
3955
0
    if( bSmart )
3956
0
    {
3957
            // Why not for other Scripts? If TransferBufferType::DocumentWord is set, we have a word
3958
            // in the buffer, word in this context means 'something with spaces at beginning
3959
            // and end'. In this case we definitely want these spaces to be inserted here.
3960
0
            bInWrd = rShell.IsInWord();
3961
0
            bEndWrd = rShell.IsEndWrd();
3962
0
            bSmart = bInWrd || bEndWrd;
3963
0
            if( bSmart )
3964
0
            {
3965
0
                bSttWrd = rShell.IsStartWord();
3966
0
                if (!bSttWrd && (bInWrd || bEndWrd))
3967
0
                    rShell.SwEditShell::Insert(' ');
3968
0
            }
3969
0
    }
3970
3971
0
    bool bRet = true;
3972
0
    SwFrameFormat const* pNewFlyToCaption{nullptr};
3973
    // m_pWrtShell is nullptr when the source document is closed already.
3974
0
    if (!m_pWrtShell || lcl_checkClassification(m_pWrtShell->GetDoc(), rShell.GetDoc()))
3975
0
    {
3976
0
        ::std::tie(bRet, pNewFlyToCaption) = rShell.Paste(
3977
0
            m_pClpDocFac->GetDoc(), ePasteTable == PasteTableType::PASTE_TABLE);
3978
0
    }
3979
3980
0
    if( bKillPaMs )
3981
0
        rShell.KillPams();
3982
3983
    // If Smart Paste then insert blank
3984
0
    if( bRet && bSmart && ((bInWrd && !bEndWrd )|| bSttWrd) )
3985
0
        rShell.SwEditShell::Insert(' ');
3986
3987
0
    oAction.reset(); // inserting caption does not work when ActionPend()
3988
3989
0
    if (pNewFlyToCaption)
3990
0
    {
3991
0
        rShell.GetView().AutoCaption(GRAPHIC_CAP);
3992
0
    }
3993
3994
0
    return bRet;
3995
0
}
3996
3997
bool SwTransferable::PrivateDrop( SwWrtShell& rSh, const Point& rDragPt,
3998
                                bool bMove, bool bIsXSelection )
3999
0
{
4000
0
    int cWord    = 0;
4001
0
    bool bInWrd  = false;
4002
0
    bool bEndWrd = false;
4003
0
    bool bSttWrd = false;
4004
0
    bool bSttPara = false;
4005
0
    bool bTableSel = false;
4006
0
    bool bTableMove = false;
4007
0
    bool bFrameSel = false;
4008
4009
0
    SwWrtShell& rSrcSh = *GetShell();
4010
4011
0
    rSh.UnSetVisibleCursor();
4012
4013
0
    if( TransferBufferType::InetField == m_eBufferType )
4014
0
    {
4015
0
        if( rSh.GetFormatFromObj( rDragPt ) )
4016
0
        {
4017
0
            INetBookmark aTmp;
4018
0
            if( (TransferBufferType::InetField & m_eBufferType) && m_oBookmark )
4019
0
                aTmp = *m_oBookmark;
4020
4021
            // select target graphic
4022
0
            if( rSh.SelectObj( rDragPt ) )
4023
0
            {
4024
0
                rSh.HideCursor();
4025
0
                rSh.EnterSelFrameMode( &rDragPt );
4026
0
                g_bFrameDrag = true;
4027
0
            }
4028
4029
0
            const SelectionType nSelection = rSh.GetSelectionType();
4030
4031
            // not yet consider Draw objects
4032
0
            if( SelectionType::Graphic & nSelection )
4033
0
            {
4034
0
                SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_URL, RES_URL>( rSh.GetAttrPool() ));
4035
0
                rSh.GetFlyFrameAttr( aSet );
4036
0
                SwFormatURL aURL( aSet.Get( RES_URL ) );
4037
0
                aURL.SetURL( aTmp.GetURL(), false );
4038
0
                aSet.Put( aURL );
4039
0
                rSh.SetFlyFrameAttr( aSet );
4040
0
                return true;
4041
0
            }
4042
4043
0
            if( SelectionType::DrawObject & nSelection )
4044
0
            {
4045
0
                rSh.LeaveSelFrameMode();
4046
0
                rSh.UnSelectFrame();
4047
0
                rSh.ShowCursor();
4048
0
                g_bFrameDrag = false;
4049
0
            }
4050
0
        }
4051
0
    }
4052
4053
0
    if( &rSh != &rSrcSh && (SelectionType::Graphic & rSh.GetSelectionType()) &&
4054
0
        TransferBufferType::Graphic == m_eBufferType )
4055
0
    {
4056
        // ReRead the graphic
4057
0
        OUString sGrfNm;
4058
0
        OUString sFltNm;
4059
0
        rSrcSh.GetGrfNms( &sGrfNm, &sFltNm );
4060
0
        rSh.ReRead( sGrfNm, sFltNm, rSrcSh.GetGraphic() );
4061
0
        return true;
4062
0
    }
4063
4064
    //not in selections or selected frames
4065
0
    if( rSh.TestCurrPam( rDragPt ) ||
4066
0
        ( rSh.IsSelFrameMode() && rSh.IsInsideSelectedObj( rDragPt )) )
4067
0
        return false;
4068
4069
0
    if( rSrcSh.IsTableMode() )
4070
0
    {
4071
0
        bTableSel = true;
4072
0
        const SelectionType nSelection = rSrcSh.GetSelectionType();
4073
        // at enhanced table row/column selection or wholly selected tables,
4074
        // paste rows above or columns before, and in the case of moving, remove the selection
4075
        // (limit only to the single document case temporarily)
4076
0
        if( rSrcSh.GetDoc() == rSh.GetDoc() &&
4077
0
                ( (( SelectionType::TableRow | SelectionType::TableCol) & nSelection ) || rSrcSh.HasWholeTabSelection() ) )
4078
0
        {
4079
0
            bool bTableCol(SelectionType::TableCol & nSelection);
4080
4081
0
            ::sw::mark::MarkBase* pMarkMoveFrom = bMove
4082
0
                    ? rSh.SetBookmark(
4083
0
                                    vcl::KeyCode(),
4084
0
                                    SwMarkName(),
4085
0
                                    IDocumentMarkAccess::MarkType::UNO_BOOKMARK )
4086
0
                    : nullptr;
4087
4088
            // row count and direction of the table selection:
4089
            // up to down, if the cursor is there in its last table row
4090
0
            const SwSelBoxes& rBoxes = rSrcSh.GetTableCursor()->GetSelectedBoxes();
4091
0
            const SwTableNode* pTableNd = rSh.IsCursorInTable();
4092
0
            if (!pTableNd)
4093
0
            {
4094
0
                SAL_WARN("sw", "presumably this case can't arise in practice");
4095
0
                return false;
4096
0
            }
4097
0
            const SwTableLines& rLines = pTableNd->GetTable().GetTabLines();
4098
0
            const SwStartNode& rDelPos = rBoxes.back()
4099
0
                    ? *rBoxes.front()->GetSttNd()
4100
0
                    : *pTableNd->GetStartNode();
4101
4102
            // count selected rows or columns
4103
0
            sal_Int32 nSelRowOrCols = 0;
4104
0
            if ( rBoxes.back() )
4105
0
            {
4106
0
                if ( bTableCol )
4107
0
                {
4108
                    // selected column count is the count of the cells
4109
                    // in the first row of the selection
4110
0
                    auto nLine = rLines.GetPos( rBoxes.front()->GetUpper() );
4111
0
                    for (auto pBox : rBoxes)
4112
0
                    {
4113
                        // cell is in the next row
4114
0
                        if ( nLine != rLines.GetPos( pBox->GetUpper() ) )
4115
0
                            break;
4116
0
                        ++nSelRowOrCols;
4117
0
                    }
4118
0
                }
4119
0
                else
4120
0
                {
4121
                   // selected row count is the difference of the row number of the
4122
                   // first and the last cell of the selection
4123
0
                   nSelRowOrCols = rLines.GetPos( rBoxes.back()->GetUpper() ) -
4124
0
                                   rLines.GetPos( rBoxes.front()->GetUpper() ) + 1;
4125
0
                }
4126
0
            }
4127
4128
0
            bool bSelUpToDown = rBoxes.back() && rBoxes.back()->GetUpper() ==
4129
0
                           rSh.GetCursor()->GetPointNode().GetTableBox()->GetUpper();
4130
4131
0
            SwUndoId eUndoId = bMove ? SwUndoId::UI_DRAG_AND_MOVE : SwUndoId::UI_DRAG_AND_COPY;
4132
4133
0
            SwRewriter aRewriter;
4134
4135
0
            aRewriter.AddRule(UndoArg1, rSrcSh.GetSelDescr());
4136
4137
0
            if(rSrcSh.GetDoc() != rSh.GetDoc())
4138
0
                rSrcSh.StartUndo( eUndoId, &aRewriter );
4139
0
            rSh.StartUndo( eUndoId, &aRewriter );
4140
4141
0
            rSh.StartAction();
4142
0
            rSrcSh.StartAction();
4143
4144
0
            SfxDispatcher* pDispatch = rSrcSh.GetView().GetViewFrame().GetDispatcher();
4145
0
            pDispatch->Execute(SID_COPY, SfxCallMode::SYNCHRON);
4146
4147
0
            rSrcSh.Push(); // save selection for later restoration
4148
0
            rSh.EnterStdMode();
4149
0
            rSh.SwCursorShell::SetCursor(rDragPt, false);
4150
4151
0
            bool bPasteIntoTable = rSh.GetCursor()->GetPointNode().GetTableBox() != nullptr;
4152
4153
            // store cursor
4154
0
            ::sw::mark::MarkBase* pMark = rSh.SetBookmark(
4155
0
                                    vcl::KeyCode(),
4156
0
                                    SwMarkName(),
4157
0
                                    IDocumentMarkAccess::MarkType::UNO_BOOKMARK );
4158
4159
            // paste rows above/columns before
4160
0
            pDispatch->Execute(bTableCol ? FN_TABLE_PASTE_COL_BEFORE : FN_TABLE_PASTE_ROW_BEFORE, SfxCallMode::SYNCHRON);
4161
4162
            // go to the previously inserted table rows and set them to tracked insertion, if needed
4163
0
            bool bNeedTrack = !bTableCol && rSh.getIDocumentRedlineAccess().IsRedlineOn();
4164
4165
            // restore cursor position
4166
0
            if (bNeedTrack && pMark != nullptr)
4167
0
                rSh.GotoMark( pMark );
4168
4169
0
            if ( !bNeedTrack && !bPasteIntoTable )
4170
0
            {
4171
0
                rSrcSh.Pop(SwCursorShell::PopMode::DeleteCurrent); // restore selection...
4172
4173
                // delete source rows/columns
4174
0
                if (bMove)
4175
0
                    pDispatch->Execute(bTableCol
4176
0
                        ? FN_TABLE_DELETE_COL
4177
0
                        : FN_TABLE_DELETE_ROW, SfxCallMode::SYNCHRON);
4178
0
            }
4179
0
            else
4180
0
            {
4181
0
                const SwTableBox* pBoxStt = rSh.GetCursor()->GetPointNode().GetTableBox();
4182
0
                SwTableLine* pLine = pBoxStt ? const_cast<SwTableLine*>( pBoxStt->GetUpper()): nullptr;
4183
4184
0
                for (sal_Int32 nDeleted = 0; bNeedTrack && nDeleted < nSelRowOrCols;)
4185
0
                {
4186
                    // move up text cursor (note: "true" is important for the layout level)
4187
0
                    if ( !rSh.Up(false) )
4188
0
                        break;
4189
4190
0
                    const SwTableBox* pBox = rSh.GetCursor()->GetPointNode().GetTableBox();
4191
4192
0
                    if ( !pBox )
4193
0
                        break;
4194
4195
                    // Up() reaches a new row
4196
0
                    if ( pBox->GetUpper() != pLine )
4197
0
                    {
4198
                        //rSh.SelTableRow();
4199
0
                        SvxPrintItem aTracked(RES_PRINT, false);
4200
0
                        rSh.GetDoc()->SetRowNotTracked( *rSh.GetCursor(), aTracked );
4201
0
                        ++nDeleted;
4202
0
                        pLine = const_cast<SwTableLine*>(pBox->GetUpper());
4203
0
                    }
4204
0
                }
4205
4206
0
                rSrcSh.Pop(SwCursorShell::PopMode::DeleteCurrent); // restore selection...
4207
4208
                // delete source rows/columns
4209
0
                if (bMove)
4210
0
                {
4211
                    // restore cursor position
4212
0
                    if (pMarkMoveFrom != nullptr)
4213
0
                    {
4214
0
                        rSh.GotoMark( pMarkMoveFrom );
4215
0
                        rSh.getIDocumentMarkAccess()->deleteMark( pMarkMoveFrom );
4216
0
                    }
4217
4218
                    // tracked table row moving: set original rows as tracked deletion,
4219
                    // otherwise delete original rows/columns (tracking column deletion
4220
                    // and insertion is not supported yet)
4221
0
                    if ( !bTableCol && bNeedTrack )
4222
0
                    {
4223
0
                        pLine = nullptr;
4224
4225
0
                        for (sal_Int32 nDeleted = 0; nDeleted < nSelRowOrCols;)
4226
0
                        {
4227
0
                            const SwTableBox* pBox = rSh.GetCursor()->GetPointNode().GetTableBox();
4228
4229
0
                            if ( !pBox )
4230
0
                                break;
4231
4232
0
                            if ( pBox->GetUpper() != pLine )
4233
0
                            {
4234
0
                                pLine = const_cast<SwTableLine*>(pBox->GetUpper());
4235
0
                                pDispatch->Execute(FN_TABLE_DELETE_ROW, SfxCallMode::SYNCHRON);
4236
0
                                ++nDeleted;
4237
0
                            }
4238
4239
0
                            bool bMoved = false;
4240
0
                            if (bSelUpToDown)
4241
0
                                bMoved = rSh.Up(false);
4242
0
                            else
4243
0
                                bMoved = rSh.Down(false);
4244
0
                            if (!bMoved)
4245
0
                                break;
4246
0
                        }
4247
0
                    }
4248
0
                    else
4249
0
                    {
4250
                        // set cursor in the first cell of the original selection
4251
0
                        rSh.GetCursor()->DeleteMark();
4252
0
                        rSh.GetCursor()->GetPoint()->Assign( rDelPos.GetIndex() + 1);
4253
4254
0
                        for (sal_Int32 nDeleted = 0; nDeleted < nSelRowOrCols; ++nDeleted)
4255
0
                        {
4256
0
                            pDispatch->Execute(bTableCol
4257
0
                                ? FN_TABLE_DELETE_COL
4258
0
                                : FN_TABLE_DELETE_ROW, SfxCallMode::SYNCHRON);
4259
0
                        }
4260
0
                    }
4261
0
                }
4262
0
            }
4263
4264
            // restore cursor position
4265
0
            if (pMark != nullptr)
4266
0
            {
4267
0
                rSh.GotoMark( pMark );
4268
0
                rSh.getIDocumentMarkAccess()->deleteMark( pMark );
4269
0
            }
4270
4271
0
            rSh.DestroyCursor();
4272
0
            rSh.EndUndo();
4273
0
            rSh.EndAction();
4274
0
            rSh.EndAction();
4275
0
            return true;
4276
0
        }
4277
4278
0
        if ( bMove && rSrcSh.HasWholeTabSelection() )
4279
0
            bTableMove = true;
4280
0
    }
4281
0
    else if( rSrcSh.IsSelFrameMode() || rSrcSh.GetSelectedObjCount() )
4282
0
    {
4283
        // don't move position-protected objects!
4284
0
        if( bMove && rSrcSh.IsSelObjProtected( FlyProtectFlags::Pos ) != FlyProtectFlags::NONE )
4285
0
            return false;
4286
4287
0
        bFrameSel = true;
4288
0
    }
4289
4290
0
    const SelectionType nSel = rSrcSh.GetSelectionType();
4291
4292
0
    SwUndoId eUndoId = bMove ? SwUndoId::UI_DRAG_AND_MOVE : SwUndoId::UI_DRAG_AND_COPY;
4293
4294
0
    SwRewriter aRewriter;
4295
4296
0
    aRewriter.AddRule(UndoArg1, rSrcSh.GetSelDescr());
4297
4298
0
    if(rSrcSh.GetDoc() != rSh.GetDoc())
4299
0
        rSrcSh.StartUndo( eUndoId, &aRewriter );
4300
0
    rSh.StartUndo( eUndoId, &aRewriter );
4301
4302
0
    rSh.StartAction();
4303
0
    rSrcSh.StartAction();
4304
4305
0
    if( &rSrcSh != &rSh )
4306
0
    {
4307
0
        rSh.EnterStdMode();
4308
0
        rSh.SwCursorShell::SetCursor( rDragPt, true );
4309
0
        cWord = rSrcSh.IntelligentCut( nSel, false );
4310
0
    }
4311
0
    else if( !bTableSel && !bFrameSel )
4312
0
    {
4313
0
        if( !rSh.IsAddMode() )
4314
0
        {
4315
            // #i87233#
4316
0
            if ( rSh.IsBlockMode() )
4317
0
            {
4318
                // preserve order of cursors for block mode
4319
0
                rSh.GoPrevCursor();
4320
0
            }
4321
4322
0
            rSh.SwCursorShell::CreateCursor();
4323
0
        }
4324
0
        rSh.SwCursorShell::SetCursor( rDragPt, true, false );
4325
0
        rSh.GoPrevCursor();
4326
0
        cWord = rSh.IntelligentCut( rSh.GetSelectionType(), false );
4327
0
        rSh.GoNextCursor();
4328
0
    }
4329
4330
0
    bInWrd  = rSh.IsInWord();
4331
0
    bEndWrd = rSh.IsEndWrd();
4332
0
    bSttWrd = !bEndWrd && rSh.IsStartWord();
4333
0
    bSttPara= rSh.IsSttPara();
4334
4335
0
    Point aSttPt( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY() );
4336
4337
    // at first, select InetFields!
4338
0
    if( TransferBufferType::InetField == m_eBufferType )
4339
0
    {
4340
0
        if( &rSrcSh == &rSh )
4341
0
        {
4342
0
            rSh.GoPrevCursor();
4343
0
            rSh.SwCursorShell::SetCursor( aSttPt, true );
4344
0
            rSh.SelectTextAttr( RES_TXTATR_INETFMT );
4345
0
            if( rSh.TestCurrPam( rDragPt ) )
4346
0
            {
4347
                // don't copy/move inside of yourself
4348
0
                rSh.DestroyCursor();
4349
0
                rSh.EndUndo();
4350
0
                rSh.EndAction();
4351
0
                rSh.EndAction();
4352
0
                return false;
4353
0
            }
4354
0
            rSh.GoNextCursor();
4355
0
        }
4356
0
        else
4357
0
        {
4358
0
            rSrcSh.SwCursorShell::SetCursor( aSttPt, true );
4359
0
            rSrcSh.SelectTextAttr( RES_TXTATR_INETFMT );
4360
0
        }
4361
4362
        // is there a URL attribute at the insert point? Then replace that,
4363
        // so simply put up a selection?
4364
0
        rSh.DelINetAttrWithText();
4365
0
        g_bDDINetAttr = true;
4366
0
    }
4367
4368
0
    if ( rSrcSh.IsSelFrameMode() )
4369
0
    {
4370
        //Hack: fool the special treatment
4371
0
        aSttPt = rSrcSh.GetObjRect().Pos();
4372
0
    }
4373
4374
0
    bool bRet = rSrcSh.SwFEShell::Copy(rSh, aSttPt, rDragPt, bMove,
4375
0
                                       !bIsXSelection);
4376
4377
0
    if( !bIsXSelection )
4378
0
    {
4379
0
        rSrcSh.Push();
4380
0
        if ( bRet && bMove && !bFrameSel )
4381
0
        {
4382
0
            if ( bTableSel )
4383
0
            {
4384
                /* delete table contents not cells */
4385
0
                rSrcSh.Delete(false);
4386
0
            }
4387
0
            else
4388
0
            {
4389
                //SmartCut, take one of the blanks along.
4390
0
                rSh.SwCursorShell::DestroyCursor();
4391
0
                if ( cWord == SwWrtShell::WORD_SPACE_BEFORE )
4392
0
                    rSh.ExtendSelection( false );
4393
0
                else if ( cWord == SwWrtShell::WORD_SPACE_AFTER )
4394
0
                    rSh.ExtendSelection();
4395
0
                rSrcSh.DelRight();
4396
0
            }
4397
0
        }
4398
0
        rSrcSh.KillPams();
4399
0
        rSrcSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
4400
4401
        /* after dragging a table selection inside one shell
4402
            set cursor to the drop position. */
4403
0
        if( &rSh == &rSrcSh && ( bTableSel || rSh.IsBlockMode() ) )
4404
0
        {
4405
0
            rSrcSh.CalcLayout();
4406
0
            rSrcSh.SwCursorShell::SetCursor(rDragPt);
4407
0
            rSrcSh.GetCursor()->SetMark();
4408
0
        }
4409
0
    }
4410
4411
0
    if( bRet && !bTableSel && !bFrameSel )
4412
0
    {
4413
0
        if( (bInWrd || bEndWrd) &&
4414
0
            (cWord == SwWrtShell::WORD_SPACE_AFTER ||
4415
0
                cWord == SwWrtShell::WORD_SPACE_BEFORE) )
4416
0
        {
4417
0
            if ( bSttWrd || (bInWrd && !bEndWrd))
4418
0
                rSh.SwEditShell::Insert(' ', bIsXSelection);
4419
0
            if ( !bSttWrd || (bInWrd && !bSttPara) )
4420
0
            {
4421
0
                rSh.SwapPam();
4422
0
                if ( !bSttWrd )
4423
0
                    rSh.SwEditShell::Insert(' ', bIsXSelection);
4424
0
                rSh.SwapPam();
4425
0
            }
4426
0
        }
4427
4428
0
        if( bIsXSelection )
4429
0
        {
4430
0
            if( &rSrcSh == &rSh && !rSh.IsAddMode() )
4431
0
            {
4432
0
                rSh.SwCursorShell::DestroyCursor();
4433
0
                rSh.GoPrevCursor();
4434
0
            }
4435
0
            else
4436
0
            {
4437
0
                rSh.SwapPam();
4438
0
                rSh.SwCursorShell::ClearMark();
4439
0
            }
4440
0
        }
4441
0
        else
4442
0
        {
4443
0
            if( rSh.IsAddMode() )
4444
0
                rSh.SwCursorShell::CreateCursor();
4445
0
            else
4446
0
            {
4447
                // turn on selection mode
4448
0
                rSh.SttSelect();
4449
0
                rSh.EndSelect();
4450
0
            }
4451
0
        }
4452
0
    }
4453
0
    else if ( bRet && bTableMove )
4454
0
    {
4455
0
        SfxDispatcher* pDispatch = rSrcSh.GetView().GetViewFrame().GetDispatcher();
4456
0
        pDispatch->Execute(FN_TABLE_DELETE_TABLE, SfxCallMode::SYNCHRON);
4457
0
    }
4458
4459
0
    if( bRet && bMove && bFrameSel )
4460
0
        rSrcSh.LeaveSelFrameMode();
4461
4462
0
    if( rSrcSh.GetDoc() != rSh.GetDoc() )
4463
0
        rSrcSh.EndUndo();
4464
0
    rSh.EndUndo();
4465
4466
        // put the shell in the right state
4467
0
    if( &rSrcSh != &rSh && ( rSh.IsFrameSelected() || rSh.GetSelectedObjCount() ))
4468
0
        rSh.EnterSelFrameMode();
4469
4470
0
    rSrcSh.EndAction();
4471
0
    rSh.EndAction();
4472
0
    return true;
4473
0
}
4474
4475
// Interfaces for Selection
4476
void SwTransferable::CreateSelection( SwWrtShell& rSh,
4477
                                      const SwFrameShell * _pCreatorView )
4478
0
{
4479
0
    rtl::Reference<SwTransferable> pNew = new SwTransferable( rSh );
4480
4481
0
    pNew->m_pCreatorView = _pCreatorView;
4482
4483
0
    SwModule::get()->m_pXSelection = pNew.get();
4484
0
    pNew->CopyToPrimarySelection();
4485
0
}
4486
4487
void SwTransferable::ClearSelection( const SwWrtShell& rSh,
4488
                                     const SwFrameShell * _pCreatorView)
4489
4.14k
{
4490
4.14k
    SwModule* pMod = SwModule::get();
4491
4.14k
    if( pMod->m_pXSelection &&
4492
0
        ((!pMod->m_pXSelection->m_pWrtShell) || (pMod->m_pXSelection->m_pWrtShell == &rSh)) &&
4493
0
        (!_pCreatorView || (pMod->m_pXSelection->m_pCreatorView == _pCreatorView)) )
4494
0
    {
4495
0
        TransferableHelper::ClearPrimarySelection();
4496
0
    }
4497
4.14k
}
4498
4499
SwTransferable* SwTransferable::GetSwTransferable( const TransferableDataHelper& rData )
4500
0
{
4501
0
    return dynamic_cast<SwTransferable*>(rData.GetTransferable().get());
4502
0
}
4503
4504
SwTransferDdeLink::SwTransferDdeLink( SwTransferable& rTrans, SwWrtShell& rSh )
4505
0
    : m_rTransfer(rTrans)
4506
0
    , m_pDocShell(nullptr)
4507
0
    , m_nOldTimeOut(0)
4508
0
    , m_bDelBookmark(false)
4509
0
    , m_bInDisconnect(false)
4510
0
{
4511
    // we only end up here with table- or text selection
4512
0
    if( SelectionType::TableCell & rSh.GetSelectionType() )
4513
0
    {
4514
0
        SwFrameFormat* pFormat = rSh.GetTableFormat();
4515
0
        if( pFormat )
4516
0
            m_sName = pFormat->GetName().toString();
4517
0
    }
4518
0
    else
4519
0
    {
4520
        // creating a temp. bookmark without undo
4521
0
        bool bUndo = rSh.DoesUndo();
4522
0
        rSh.DoUndo( false );
4523
0
        bool bIsModified = rSh.IsModified();
4524
4525
0
        ::sw::mark::MarkBase* pMark = rSh.SetBookmark(
4526
0
            vcl::KeyCode(),
4527
0
            SwMarkName(),
4528
0
            IDocumentMarkAccess::MarkType::DDE_BOOKMARK);
4529
0
        if(pMark)
4530
0
        {
4531
0
            m_sName = pMark->GetName().toString();
4532
0
            m_bDelBookmark = true;
4533
0
            if( !bIsModified )
4534
0
                rSh.ResetModified();
4535
0
        }
4536
0
        else
4537
0
            m_sName.clear();
4538
0
        rSh.DoUndo( bUndo );
4539
0
    }
4540
4541
0
    if( m_sName.isEmpty() ||
4542
0
        nullptr == ( m_pDocShell = rSh.GetDoc()->GetDocShell() ))
4543
0
        return;
4544
4545
    // then we create our "server" and connect to it
4546
0
    m_xRefObj = m_pDocShell->DdeCreateLinkSource( m_sName );
4547
0
    if( m_xRefObj.is() )
4548
0
    {
4549
0
        m_xRefObj->AddConnectAdvise( this );
4550
0
        m_xRefObj->AddDataAdvise( this,
4551
0
                        OUString(),
4552
0
                        ADVISEMODE_NODATA | ADVISEMODE_ONLYONCE );
4553
0
        m_nOldTimeOut = m_xRefObj->GetUpdateTimeout();
4554
0
        m_xRefObj->SetUpdateTimeout( 0 );
4555
0
    }
4556
0
}
4557
4558
SwTransferDdeLink::~SwTransferDdeLink()
4559
0
{
4560
0
    if( m_xRefObj.is() )
4561
0
        Disconnect( true );
4562
0
}
4563
4564
::sfx2::SvBaseLink::UpdateResult SwTransferDdeLink::DataChanged( const OUString& ,
4565
                                    const uno::Any& )
4566
0
{
4567
    // well, that's it with the link
4568
0
    if( !m_bInDisconnect )
4569
0
    {
4570
0
        if( FindDocShell() && m_pDocShell->GetView() )
4571
0
            m_rTransfer.RemoveDDELinkFormat( m_pDocShell->GetView()->GetEditWin() );
4572
0
        Disconnect( false );
4573
0
    }
4574
0
    return SUCCESS;
4575
0
}
4576
4577
bool SwTransferDdeLink::WriteData( SvStream& rStrm )
4578
0
{
4579
0
    if( !m_xRefObj.is() || !FindDocShell() )
4580
0
        return false;
4581
4582
0
    TransferableDataHelper::WriteDDELink(rStrm, Application::GetAppName(),
4583
0
                                         m_pDocShell->GetTitle(SFX_TITLE_FULLNAME), m_sName);
4584
4585
0
    IDocumentMarkAccess* const pMarkAccess = m_pDocShell->GetDoc()->getIDocumentMarkAccess();
4586
0
    auto ppMark = pMarkAccess->findMark(SwMarkName(m_sName));
4587
0
    if(ppMark != pMarkAccess->getAllMarksEnd()
4588
0
        && IDocumentMarkAccess::GetType(**ppMark) != IDocumentMarkAccess::MarkType::BOOKMARK)
4589
0
    {
4590
        // the mark is still a DdeBookmark
4591
        // we replace it with a Bookmark, so it will get saved etc.
4592
0
        ::sw::mark::MarkBase* const pMark = *ppMark;
4593
0
        ::sfx2::SvLinkSource* p = m_xRefObj.get();
4594
0
        SwServerObject& rServerObject = dynamic_cast<SwServerObject&>(*p);
4595
4596
        // collecting state of old mark
4597
0
        SwPaM aPaM(pMark->GetMarkStart());
4598
0
        *aPaM.GetPoint() = pMark->GetMarkStart();
4599
0
        if(pMark->IsExpanded())
4600
0
        {
4601
0
            aPaM.SetMark();
4602
0
            *aPaM.GetMark() = pMark->GetMarkEnd();
4603
0
        }
4604
0
        SwMarkName sMarkName = pMark->GetName();
4605
4606
        // remove mark
4607
0
        rServerObject.SetNoServer(); // this removes the connection between SwServerObject and mark
4608
        // N.B. ppMark was not loaded from file and cannot have xml:id
4609
0
        pMarkAccess->deleteMark(ppMark, false);
4610
4611
        // recreate as Bookmark
4612
0
        ::sw::mark::MarkBase* const pNewMark = pMarkAccess->makeMark(
4613
0
            aPaM,
4614
0
            sMarkName,
4615
0
            IDocumentMarkAccess::MarkType::BOOKMARK,
4616
0
            ::sw::mark::InsertMode::New);
4617
0
        rServerObject.SetDdeBookmark(*pNewMark);
4618
0
    }
4619
4620
0
    m_bDelBookmark = false;
4621
0
    return true;
4622
0
}
4623
4624
void SwTransferDdeLink::Disconnect( bool bRemoveDataAdvise )
4625
0
{
4626
    //  don't accept DataChanged anymore, when already in Disconnect!
4627
    //  (DTOR from Bookmark sends a DataChanged!)
4628
0
    bool bOldDisconnect = m_bInDisconnect;
4629
0
    m_bInDisconnect = true;
4630
4631
    // destroy the unused bookmark again (without Undo!)?
4632
0
    if( m_bDelBookmark && m_xRefObj.is() && FindDocShell() )
4633
0
    {
4634
0
        SwDoc* pDoc = m_pDocShell->GetDoc();
4635
0
        ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
4636
4637
        // #i58448#
4638
0
        Link<bool,void> aSavedOle2Link( pDoc->GetOle2Link() );
4639
0
        pDoc->SetOle2Link( Link<bool,void>() );
4640
4641
0
        bool bIsModified = pDoc->getIDocumentState().IsModified();
4642
4643
0
        IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
4644
0
        pMarkAccess->deleteMark(pMarkAccess->findMark(SwMarkName(m_sName)), false);
4645
4646
0
        if( !bIsModified )
4647
0
            pDoc->getIDocumentState().ResetModified();
4648
        // #i58448#
4649
0
        pDoc->SetOle2Link( aSavedOle2Link );
4650
4651
0
        m_bDelBookmark = false;
4652
0
    }
4653
4654
0
    if( m_xRefObj.is() )
4655
0
    {
4656
0
        m_xRefObj->SetUpdateTimeout( m_nOldTimeOut );
4657
0
        m_xRefObj->RemoveConnectAdvise( this );
4658
0
        if( bRemoveDataAdvise )
4659
            // in a DataChanged the SelectionObject must NEVER be deleted
4660
            // is already handled by the base class
4661
            // (ADVISEMODE_ONLYONCE!!!!)
4662
            // but always in normal Disconnect!
4663
0
            m_xRefObj->RemoveAllDataAdvise( this );
4664
0
        m_xRefObj.clear();
4665
0
    }
4666
0
    m_bInDisconnect = bOldDisconnect;
4667
0
}
4668
4669
bool SwTransferDdeLink::FindDocShell()
4670
0
{
4671
0
    SfxObjectShell* pTmpSh = SfxObjectShell::GetFirst( checkSfxObjectShell<SwDocShell> );
4672
0
    while( pTmpSh )
4673
0
    {
4674
0
        if( pTmpSh == m_pDocShell )       // that's what we want to have
4675
0
        {
4676
0
            if( m_pDocShell->GetDoc() )
4677
0
                return true;
4678
0
            break;      // the Doc is not there anymore, so leave!
4679
0
        }
4680
0
        pTmpSh = SfxObjectShell::GetNext( *pTmpSh, checkSfxObjectShell<SwDocShell> );
4681
0
    }
4682
4683
0
    m_pDocShell = nullptr;
4684
0
    return false;
4685
0
}
4686
4687
void SwTransferDdeLink::Closed()
4688
0
{
4689
0
    if( !m_bInDisconnect && m_xRefObj.is() )
4690
0
    {
4691
0
        m_xRefObj->RemoveAllDataAdvise( this );
4692
0
        m_xRefObj->RemoveConnectAdvise( this );
4693
0
        m_xRefObj.clear();
4694
0
    }
4695
0
}
4696
4697
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */