Coverage Report

Created: 2026-10-14 09:33

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