1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
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>
29 #include <svtools/embedtransfer.hxx>
30 #include <svtools/insdlg.hxx>
31 #include <unotools/tempfile.hxx>
32 #include <comphelper/fileformat.h>
33 #include <comphelper/processfactory.hxx>
34 #include <comphelper/propertyvalue.hxx>
35 #include <comphelper/servicehelper.hxx>
36 #include <comphelper/storagehelper.hxx>
37 #include <comphelper/string.hxx>
38 #include <o3tl/deleter.hxx>
39 #include <o3tl/temporary.hxx>
40 #include <unotools/ucbstreamhelper.hxx>
41 #include <sot/filelist.hxx>
42 #include <svx/svxdlg.hxx>
43 #include <toolkit/helper/vclunohelper.hxx>
44 #include <osl/endian.h>
45 #include <sfx2/linkmgr.hxx>
46 #include <tools/urlobj.hxx>
47 #include <vcl/weld.hxx>
48 #include <sfx2/dispatch.hxx>
49 #include <sfx2/viewfrm.hxx>
50 #include <svl/stritem.hxx>
51 #include <vcl/imap.hxx>
52 #include <sot/storage.hxx>
53 #include <vcl/graph.hxx>
54 #include <svl/urihelper.hxx>
55 #include <svx/svdmodel.hxx>
56 #include <svx/xmlexchg.hxx>
57 #include <svx/dbaexchange.hxx>
58 #include <svx/clipfmtitem.hxx>
59 #include <sfx2/mieclip.hxx>
60 #include <svl/urlbmk.hxx>
61 #include <vcl/inetimg.hxx>
62 #include <svx/fmview.hxx>
63 #include <sfx2/docfilt.hxx>
64 #include <vcl/imapobj.hxx>
65 #include <sfx2/docfile.hxx>
66 #include <unotools/transliterationwrapper.hxx>
67 #include <unotools/streamwrap.hxx>
68 #include <vcl/graphicfilter.hxx>
73 #include <o3tl/char16_t2wchar_t.hxx>
74 #include <osl/file.hxx>
77 #include <svx/unomodel.hxx>
79 #include <fmtinfmt.hxx>
80 #include <swdtflvr.hxx>
81 #include <shellio.hxx>
84 #include <IDocumentUndoRedo.hxx>
85 #include <IDocumentDrawModelAccess.hxx>
86 #include <IDocumentFieldsAccess.hxx>
87 #include <IDocumentRedlineAccess.hxx>
88 #include <IDocumentState.hxx>
90 #include <section.hxx>
94 #include <navicont.hxx>
97 #include <swmodule.hxx>
100 #include <wdocsh.hxx>
101 #include <fldbas.hxx>
102 #include <swundo.hxx>
105 #include <swwait.hxx>
106 #include <viewopt.hxx>
107 #include <SwCapObjType.hxx>
109 #include <strings.hrc>
110 #include <svx/svditer.hxx>
111 #include <editeng/eeitem.hxx>
112 #include <editeng/fhgtitem.hxx>
113 #include <editeng/prntitem.hxx>
114 #include <svx/svdpage.hxx>
115 #include <avmedia/mediawindow.hxx>
116 #include <swcrsr.hxx>
117 #include <SwRewriter.hxx>
118 #include <vcl/svapp.hxx>
119 #include <swserv.hxx>
120 #include <fmtmeta.hxx>
121 #include <itabenum.hxx>
122 #include <iodetect.hxx>
123 #include <unotextrange.hxx>
124 #include <unoframe.hxx>
125 #include <txatbase.hxx>
126 #include <unoparaframeenum.hxx>
127 #include <vcl/uitest/logger.hxx>
128 #include <vcl/uitest/eventdescription.hxx>
130 #include <vcl/GraphicNativeTransform.hxx>
131 #include <vcl/GraphicNativeMetadata.hxx>
132 #include <vcl/TypeSerializer.hxx>
133 #include <comphelper/lok.hxx>
134 #include <sfx2/classificationhelper.hxx>
135 #include <sfx2/sfxdlg.hxx>
136 #include <comphelper/classids.hxx>
137 #include <osl/diagnose.h>
141 /* default (A4 format) width of 210mm - 2 * border size (border on both sides) */
142 constexpr tools::Long constOleWidthInMm
= 210 - 2 * lMinBorderInMm
;
144 constexpr Size
constOleSize100mm(
145 constOleWidthInMm
* 100, // convert from mm to 100mm
149 constexpr Size constOleSizeTwip
= o3tl::convert(constOleSize100mm
, o3tl::Length::mm100
, o3tl::Length::twip
);
151 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_DRAWMODEL
= 0x00000001;
152 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_HTML
= 0x00000002;
153 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_RTF
= 0x00000004;
154 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_STRING
= 0x00000008;
155 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_SWOLE
= 0x00000010;
156 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_DDE
= 0x00000020;
157 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_RICHTEXT
= 0x00000040;
159 using namespace ::svx
;
160 using namespace ::com::sun::star
;
161 using namespace ::com::sun::star::uno
;
162 using namespace ::com::sun::star::datatransfer
;
165 void collectUIInformation(const OUString
& rAction
, const OUString
& aParameters
)
167 EventDescription aDescription
;
168 aDescription
.aAction
= rAction
;
169 aDescription
.aParameters
= {{"parameters", aParameters
}};
170 aDescription
.aID
= "writer_edit";
171 aDescription
.aKeyWord
= "SwEditWinUIObject";
172 aDescription
.aParent
= "MainWindow";
173 UITestLogger::getInstance().logEvent(aDescription
);
178 class SwTransferDdeLink
: public ::sfx2::SvBaseLink
181 ::sfx2::SvLinkSourceRef m_xRefObj
;
182 SwTransferable
& m_rTransfer
;
183 SwDocShell
* m_pDocShell
;
184 sal_uLong m_nOldTimeOut
;
185 bool m_bDelBookmark
: 1;
186 bool m_bInDisconnect
: 1;
190 using sfx2::SvBaseLink::Disconnect
;
193 virtual ~SwTransferDdeLink() override
;
196 SwTransferDdeLink( SwTransferable
& rTrans
, SwWrtShell
& rSh
);
198 virtual ::sfx2::SvBaseLink::UpdateResult
DataChanged(
199 const OUString
& rMimeType
, const css::uno::Any
& rValue
) override
;
200 virtual void Closed() override
;
202 bool WriteData( SvStream
& rStrm
);
204 void Disconnect( bool bRemoveDataAdvise
);
207 /// Tracks the boundaries of pasted content and notifies listeners.
211 SwPasteContext(SwWrtShell
& rWrtShell
);
218 SwWrtShell
& m_rWrtShell
;
219 std::optional
<SwPaM
> m_oPaM
;
220 sal_Int32 m_nStartContent
= 0;
225 // helper class for Action and Undo enclosing
226 class SwTrnsfrActionAndUndo
230 SwTrnsfrActionAndUndo( SwWrtShell
*pS
, bool bDelSel
= false, SwPasteContext
* pContext
= nullptr)
233 pSh
->StartUndo( SwUndoId::PASTE_CLIPBOARD
);
240 pContext
->remember();
242 pSh
->StartAllAction();
244 ~SwTrnsfrActionAndUndo() COVERITY_NOEXCEPT_FALSE
253 SwTransferable::SwTransferable( SwWrtShell
& rSh
)
254 : m_pWrtShell( &rSh
),
255 m_pCreatorView( nullptr ),
256 m_pOrigGraphic( nullptr ),
257 m_eBufferType( TransferBufferType::NONE
),
261 rSh
.GetView().AddTransferable(*this);
262 SwDocShell
* pDShell
= rSh
.GetDoc()->GetDocShell();
266 pDShell
->FillTransferableObjectDescriptor( m_aObjDesc
);
267 if( pDShell
->GetMedium() )
269 const INetURLObject
& rURLObj
= pDShell
->GetMedium()->GetURLObject();
270 m_aObjDesc
.maDisplayName
= URIHelper::removePassword(
271 rURLObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
),
272 INetURLObject::EncodeMechanism::WasEncoded
,
273 INetURLObject::DecodeMechanism::Unambiguous
);
276 PrepareOLE( m_aObjDesc
);
279 SwTransferable::~SwTransferable()
281 SolarMutexGuard aSolarGuard
;
283 // the DDELink still needs the WrtShell!
286 m_pWrtShell
= nullptr;
288 // release reference to the document so that aDocShellRef will delete
289 // it (if aDocShellRef is set). Otherwise, the OLE nodes keep references
290 // to their sub-storage when the storage is already dead.
291 m_pClpDocFac
.reset();
293 // first close, then the Ref. can be cleared as well, so that
294 // the DocShell really gets deleted!
295 if( m_aDocShellRef
.Is() )
297 SfxObjectShell
* pObj
= m_aDocShellRef
;
298 SwDocShell
* pDocSh
= static_cast<SwDocShell
*>(pObj
);
301 m_aDocShellRef
.Clear();
303 if (SwModule
* pMod
= SwModule::get())
305 if ( pMod
->m_pDragDrop
== this )
306 pMod
->m_pDragDrop
= nullptr;
307 else if ( pMod
->m_pXSelection
== this )
308 pMod
->m_pXSelection
= nullptr;
311 m_eBufferType
= TransferBufferType::NONE
;
314 static SwDoc
& lcl_GetDoc(SwDocFac
& rDocFac
)
316 SwDoc
& rDoc
= rDocFac
.GetDoc();
317 rDoc
.SetClipBoard( true );
321 void SwTransferable::ObjectReleased()
323 SwModule
* pMod
= SwModule::get();
326 if( this == pMod
->m_pDragDrop
)
327 pMod
->m_pDragDrop
= nullptr;
328 else if( this == pMod
->m_pXSelection
)
329 pMod
->m_pXSelection
= nullptr;
332 void SwTransferable::AddSupportedFormats()
334 // only need if we are the current XSelection Object
335 if (this == SwModule::get()->m_pXSelection
|| comphelper::LibreOfficeKit::isActive())
337 SetDataForDragAndDrop( Point( 0,0) );
341 void SwTransferable::InitOle( SfxObjectShell
* pDoc
)
343 //set OleVisArea. Upper left corner of the page and size of
345 const Size
aSz(constOleSizeTwip
);
346 SwRect
aVis( Point( DOCUMENTBORDER
, DOCUMENTBORDER
), aSz
);
347 pDoc
->SetVisArea( aVis
.SVRect() );
350 uno::Reference
< embed::XEmbeddedObject
> SwTransferable::FindOLEObj( sal_Int64
& nAspect
) const
352 uno::Reference
< embed::XEmbeddedObject
> xObj
;
355 SwIterator
<SwContentNode
,SwFormatColl
> aIter( *m_pClpDocFac
->GetDoc().GetDfltGrfFormatColl() );
356 for( SwContentNode
* pNd
= aIter
.First(); pNd
; pNd
= aIter
.Next() )
357 if( SwNodeType::Ole
== pNd
->GetNodeType() )
359 xObj
= static_cast<SwOLENode
*>(pNd
)->GetOLEObj().GetOleRef();
360 nAspect
= static_cast<SwOLENode
*>(pNd
)->GetAspect();
367 const Graphic
* SwTransferable::FindOLEReplacementGraphic() const
371 SwIterator
<SwContentNode
,SwFormatColl
> aIter( *m_pClpDocFac
->GetDoc().GetDfltGrfFormatColl() );
372 for( SwContentNode
* pNd
= aIter
.First(); pNd
; pNd
= aIter
.Next() )
373 if( SwNodeType::Ole
== pNd
->GetNodeType() )
375 return static_cast<SwOLENode
*>(pNd
)->GetGraphic();
382 void SwTransferable::RemoveDDELinkFormat(vcl::Window
& rWin
)
384 RemoveFormat( SotClipboardFormatId::LINK
);
385 if (rWin
.GetClipboard()->getContents().get() == this)
386 CopyToClipboard(&rWin
);
389 void SwTransferable::DisconnectDDE()
391 if( m_xDdeLink
.is() )
393 m_xDdeLink
->Disconnect( true );
400 //Resolves: fdo#40717 surely when we create a clipboard document we should
401 //overwrite the clipboard documents styles and settings with that of the
402 //source, so that we can WYSIWYG paste. If we want that the destinations
403 //styles are used over the source styles, that's a matter of the
404 //destination paste code to handle, not the source paste code.
405 void lclOverWriteDoc(SwWrtShell
&rSrcWrtShell
, SwDoc
&rDest
)
407 const SwDoc
&rSrc
= *rSrcWrtShell
.GetDoc();
409 rDest
.ReplaceCompatibilityOptions(rSrc
);
410 rDest
.ReplaceDefaults(rSrc
);
412 //It would probably make most sense here to only insert the styles used
413 //by the selection, e.g. apply SwDoc::IsUsed on styles ?
414 rDest
.ReplaceStyles(rSrc
, false);
416 rSrcWrtShell
.Copy(rDest
);
418 rDest
.GetMetaFieldManager().copyDocumentProperties(rSrc
);
421 void lclCheckAndPerformRotation(Graphic
& aGraphic
)
423 GraphicNativeMetadata aMetadata
;
424 if ( !aMetadata
.read(aGraphic
) )
427 Degree10 aRotation
= aMetadata
.getRotation();
430 GraphicNativeTransform
aTransform( aGraphic
);
431 aTransform
.rotate( aRotation
);
436 sal_Bool SAL_CALL
SwTransferable::isComplex()
438 sal_Int32 nTextLength
= 0;
439 SwNodes
& aNodes
= m_pWrtShell
->GetDoc()->GetNodes();
440 for (SwPaM
& rPaM
: m_pWrtShell
->GetCursor()->GetRingContainer())
442 for (SwNodeOffset nIndex
= rPaM
.GetMark()->GetNodeIndex();
443 nIndex
<= rPaM
.GetPoint()->GetNodeIndex(); ++nIndex
)
445 SwNode
& rNd
= *aNodes
[nIndex
];
447 SwTextNode
* pTextNode
= rNd
.GetTextNode();
450 if (pTextNode
->HasHints())
452 for (size_t nHint
= 0; nHint
< pTextNode
->GetSwpHints().Count(); ++nHint
)
454 SwTextAttr
* pHint
= pTextNode
->GetSwpHints().Get(nHint
);
455 if (pHint
->Which() == RES_TXTATR_FLYCNT
)
457 return true; // Complex
462 FrameClientSortList_t vFrames
;
463 ::CollectFrameAtNode(rNd
, vFrames
, true);
464 if (!vFrames
.empty())
466 // There is an at-char anchored object to this node, that's complex.
470 nTextLength
+= pTextNode
->GetText().getLength();
471 if (nTextLength
>= 1024 * 512)
472 return true; // Complex
477 if (m_pWrtShell
->GetSelectionType() == SelectionType::DrawObject
)
478 return true; // Complex
484 bool SwTransferable::GetData( const DataFlavor
& rFlavor
, const OUString
& rDestDoc
)
486 SotClipboardFormatId nFormat
= SotExchange::GetFormat( rFlavor
);
488 // we can only fulfil the request if
489 // 1) we have data for this format
490 // 2) we have either a clipboard document (pClpDocFac), or
491 // we have a SwWrtShell (so we can generate a new clipboard document)
492 if( !HasFormat( nFormat
) || ( m_pClpDocFac
== nullptr && m_pWrtShell
== nullptr ) )
497 SelectionType nSelectionType
= m_pWrtShell
->GetSelectionType();
499 // when pending we will not get the correct type, but SelectionType::Text
500 // as fallback. This *happens* during D&D, so we need to check if we are in
501 // the fallback and just try to get a graphic
502 const bool bPending(m_pWrtShell
->ActionPend());
504 // SEL_GRF is from ContentType of editsh
505 if(bPending
|| ((SelectionType::Graphic
| SelectionType::DrawObject
| SelectionType::DbForm
) & nSelectionType
))
507 m_oClpGraphic
.emplace();
508 if( !m_pWrtShell
->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE
, *m_oClpGraphic
))
509 m_pOrigGraphic
= &*m_oClpGraphic
;
510 m_oClpBitmap
.emplace();
511 if( !m_pWrtShell
->GetDrawObjGraphic( SotClipboardFormatId::BITMAP
, *m_oClpBitmap
))
512 m_pOrigGraphic
= &*m_oClpBitmap
;
514 // is it a URL-Button ?
517 if( m_pWrtShell
->GetURLFromButton( sURL
, sDesc
) )
519 m_oBookmark
.emplace( sURL
, sDesc
);
520 m_eBufferType
= TransferBufferType::InetField
;
524 m_pClpDocFac
.reset(new SwDocFac
);
525 SwDoc
& rTmpDoc
= lcl_GetDoc(*m_pClpDocFac
);
527 rTmpDoc
.getIDocumentFieldsAccess().LockExpFields(); // never update fields - leave text as it is
528 lclOverWriteDoc(*m_pWrtShell
, rTmpDoc
);
530 // in CORE a new one was created (OLE-objects copied!)
531 m_aDocShellRef
= rTmpDoc
.GetTmpDocShell();
532 if( m_aDocShellRef
.Is() )
533 SwTransferable::InitOle( m_aDocShellRef
);
534 rTmpDoc
.SetTmpDocShell( nullptr );
536 if( nSelectionType
& SelectionType::Text
&& !m_pWrtShell
->HasMark() )
538 SwContentAtPos
aContentAtPos( IsAttrAtPos::InetAttr
);
540 Point
aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY());
542 bool bSelect
= g_bExecuteDrag
&&
543 m_pWrtShell
->GetView().GetDocShell() &&
544 !m_pWrtShell
->GetView().GetDocShell()->IsReadOnly();
545 if( m_pWrtShell
->GetContentAtPos( aPos
, aContentAtPos
, bSelect
) )
548 static_cast<const SwFormatINetFormat
*>(aContentAtPos
.aFnd
.pAttr
)->GetValue(),
549 aContentAtPos
.sStr
);
550 m_eBufferType
= TransferBufferType::InetField
;
552 m_pWrtShell
->SelectTextAttr( RES_TXTATR_INETFMT
);
555 if( m_pWrtShell
->IsFrameSelected() )
557 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( m_pWrtShell
->GetAttrPool() );
558 m_pWrtShell
->GetFlyFrameAttr( aSet
);
559 const SwFormatURL
& rURL
= aSet
.Get( RES_URL
);
561 m_pImageMap
.reset(new ImageMap( *rURL
.GetMap() ));
562 else if( !rURL
.GetURL().isEmpty() )
563 m_pTargetURL
.reset(new INetImage(OUString(), rURL
.GetURL(),
564 rURL
.GetTargetFrameName() ));
569 if( TransferBufferType::Ole
== m_eBufferType
)
571 //TODO/MBA: testing - is this the "single OLE object" case?!
572 // get OLE-Object from ClipDoc and get the data from that.
573 sal_Int64 nAspect
= embed::Aspects::MSOLE_CONTENT
; // will be set in the next statement
574 uno::Reference
< embed::XEmbeddedObject
> xObj
= FindOLEObj( nAspect
);
575 const Graphic
* pOLEGraph
= FindOLEReplacementGraphic();
578 TransferableDataHelper
aD( new SvEmbedTransferHelper( xObj
, pOLEGraph
, nAspect
) );
579 uno::Any aAny
= aD
.GetAny(rFlavor
, rDestDoc
);
580 if( aAny
.hasValue() )
581 bOK
= SetAny( aAny
);
584 // the following solution will be used in the case when the object can not generate the image
585 // TODO/LATER: in future the transferhelper must probably be created based on object and the replacement stream
586 // TODO: Block not required now, SvEmbedTransferHelper should be able to handle GDIMetaFile format
587 if ( nFormat
== SotClipboardFormatId::GDIMETAFILE
)
589 pOLEGraph
= FindOLEReplacementGraphic();
591 bOK
= SetGDIMetaFile( pOLEGraph
->GetGDIMetaFile() );
598 case SotClipboardFormatId::LINK
:
599 if( m_xDdeLink
.is() )
600 bOK
= SetObject( m_xDdeLink
.get(), SWTRANSFER_OBJECTTYPE_DDE
, rFlavor
);
603 case SotClipboardFormatId::OBJECTDESCRIPTOR
:
604 case SotClipboardFormatId::LINKSRCDESCRIPTOR
:
605 bOK
= SetTransferableObjectDescriptor( m_aObjDesc
);
608 case SotClipboardFormatId::DRAWING
:
610 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
611 bOK
= SetObject( rDoc
.getIDocumentDrawModelAccess().GetDrawModel(),
612 SWTRANSFER_OBJECTTYPE_DRAWMODEL
, rFlavor
);
616 case SotClipboardFormatId::STRING
:
618 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
619 bOK
= SetObject( &rDoc
, SWTRANSFER_OBJECTTYPE_STRING
, rFlavor
);
622 case SotClipboardFormatId::RTF
:
624 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
625 bOK
= SetObject( &rDoc
, SWTRANSFER_OBJECTTYPE_RTF
, rFlavor
);
628 case SotClipboardFormatId::RICHTEXT
:
630 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
631 bOK
= SetObject( &rDoc
, SWTRANSFER_OBJECTTYPE_RICHTEXT
, rFlavor
);
635 case SotClipboardFormatId::HTML
:
637 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
638 bOK
= SetObject( &rDoc
, SWTRANSFER_OBJECTTYPE_HTML
, rFlavor
);
642 case SotClipboardFormatId::SVXB
:
643 if( m_eBufferType
& TransferBufferType::Graphic
&& m_pOrigGraphic
)
644 bOK
= SetGraphic( *m_pOrigGraphic
);
647 case SotClipboardFormatId::GDIMETAFILE
:
648 if( m_eBufferType
& TransferBufferType::Graphic
)
649 bOK
= SetGDIMetaFile( m_oClpGraphic
->GetGDIMetaFile() );
651 case SotClipboardFormatId::BITMAP
:
652 case SotClipboardFormatId::PNG
:
653 // Neither pClpBitmap nor pClpGraphic are necessarily set
654 if( (m_eBufferType
& TransferBufferType::Graphic
) && (m_oClpBitmap
|| m_oClpGraphic
))
655 bOK
= SetBitmapEx( (m_oClpBitmap
? m_oClpBitmap
: m_oClpGraphic
)->GetBitmapEx(), rFlavor
);
658 case SotClipboardFormatId::SVIM
:
660 bOK
= SetImageMap( *m_pImageMap
);
663 case SotClipboardFormatId::INET_IMAGE
:
665 bOK
= SetINetImage( *m_pTargetURL
, rFlavor
);
668 case SotClipboardFormatId::SOLK
:
669 case SotClipboardFormatId::NETSCAPE_BOOKMARK
:
670 case SotClipboardFormatId::FILEGRPDESCRIPTOR
:
671 case SotClipboardFormatId::FILECONTENT
:
672 case SotClipboardFormatId::UNIFORMRESOURCELOCATOR
:
673 case SotClipboardFormatId::SIMPLE_FILE
:
674 if( (TransferBufferType::InetField
& m_eBufferType
) && m_oBookmark
)
675 bOK
= SetINetBookmark( *m_oBookmark
, rFlavor
);
678 case SotClipboardFormatId::EMBED_SOURCE
:
679 if( !m_aDocShellRef
.Is() )
681 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
682 m_aDocShellRef
= new SwDocShell(rDoc
, SfxObjectCreateMode::EMBEDDED
);
683 m_aDocShellRef
->DoInitNew();
684 SwTransferable::InitOle( m_aDocShellRef
);
686 bOK
= SetObject( &m_aDocShellRef
, SWTRANSFER_OBJECTTYPE_SWOLE
,
695 bool SwTransferable::WriteObject( SvStream
& rOStream
,
696 void* pObject
, sal_uInt32 nObjectType
,
697 const DataFlavor
& /*rFlavor*/ )
702 switch( nObjectType
)
704 case SWTRANSFER_OBJECTTYPE_DRAWMODEL
:
706 // don't change the sequence of commands
707 SdrModel
*pModel
= static_cast<SdrModel
*>(pObject
);
708 rOStream
.SetBufferSize( 16348 );
710 // for the changed pool defaults from drawing layer pool set those
711 // attributes as hard attributes to preserve them for saving
712 const SfxItemPool
& rItemPool
= pModel
->GetItemPool();
713 const SvxFontHeightItem
& rDefaultFontHeight
= rItemPool
.GetUserOrPoolDefaultItem(EE_CHAR_FONTHEIGHT
);
715 // SW should have no MasterPages
716 OSL_ENSURE(0 == pModel
->GetMasterPageCount(), "SW with MasterPages (!)");
718 for(sal_uInt16
a(0); a
< pModel
->GetPageCount(); a
++)
720 const SdrPage
* pPage
= pModel
->GetPage(a
);
721 SdrObjListIter
aIter(pPage
, SdrIterMode::DeepNoGroups
);
723 while(aIter
.IsMore())
725 SdrObject
* pObj
= aIter
.Next();
726 const SvxFontHeightItem
& rItem
= pObj
->GetMergedItem(EE_CHAR_FONTHEIGHT
);
728 if(rItem
.GetHeight() == rDefaultFontHeight
.GetHeight())
730 pObj
->SetMergedItem(rDefaultFontHeight
);
736 uno::Reference
<io::XOutputStream
> xDocOut( new utl::OOutputStreamWrapper( rOStream
) );
737 SvxDrawingLayerExport( pModel
, xDocOut
);
740 bRet
= ERRCODE_NONE
== rOStream
.GetError();
744 case SWTRANSFER_OBJECTTYPE_SWOLE
:
746 SfxObjectShell
* pEmbObj
= static_cast<SfxObjectShell
*>(pObject
);
749 ::utl::TempFileFast aTempFile
;
750 SvStream
* pTempStream
= aTempFile
.GetStream(StreamMode::READWRITE
);
751 uno::Reference
< embed::XStorage
> xWorkStore
=
752 ::comphelper::OStorageHelper::GetStorageFromStream( new utl::OStreamWrapper(*pTempStream
), embed::ElementModes::READWRITE
);
754 // write document storage
755 pEmbObj
->SetupStorage( xWorkStore
, SOFFICE_FILEFORMAT_CURRENT
, false );
756 // mba: no BaseURL for clipboard
757 SfxMedium
aMedium( xWorkStore
, OUString() );
758 pEmbObj
->DoSaveObjectAs( aMedium
, false );
759 pEmbObj
->DoSaveCompleted();
761 uno::Reference
< embed::XTransactedObject
> xTransact( xWorkStore
, uno::UNO_QUERY
);
762 if ( xTransact
.is() )
765 rOStream
.SetBufferSize( 0xff00 );
766 rOStream
.WriteStream( *pTempStream
);
768 xWorkStore
->dispose();
771 catch (const uno::Exception
&)
775 bRet
= ( rOStream
.GetError() == ERRCODE_NONE
);
779 case SWTRANSFER_OBJECTTYPE_DDE
:
781 rOStream
.SetBufferSize( 1024 );
782 SwTransferDdeLink
* pDdeLnk
= static_cast<SwTransferDdeLink
*>(pObject
);
783 if( pDdeLnk
->WriteData( rOStream
) )
785 bRet
= ERRCODE_NONE
== rOStream
.GetError();
790 case SWTRANSFER_OBJECTTYPE_HTML
:
792 // LOK is interested in getting images embedded for copy/paste support.
793 GetHTMLWriter( comphelper::LibreOfficeKit::isActive() ? u
"EmbedImages;NoPrettyPrint"_ustr
: OUString(), OUString(), xWrt
);
797 case SWTRANSFER_OBJECTTYPE_RTF
:
798 case SWTRANSFER_OBJECTTYPE_RICHTEXT
:
799 GetRTFWriter(std::u16string_view(), OUString(), xWrt
);
802 case SWTRANSFER_OBJECTTYPE_STRING
:
803 GetASCWriter(std::u16string_view(), OUString(), xWrt
);
806 SwAsciiOptions aAOpt
;
807 aAOpt
.SetCharSet( RTL_TEXTENCODING_UTF8
);
808 xWrt
->SetAsciiOptions( aAOpt
);
810 // no start char for clipboard
811 xWrt
->m_bUCS2_WithStartChar
= false;
819 SwDoc
* pDoc
= static_cast<SwDoc
*>(pObject
);
820 xWrt
->m_bWriteClipboardDoc
= true;
821 xWrt
->m_bWriteOnlyFirstTable
= bool(TransferBufferType::Table
& m_eBufferType
);
822 xWrt
->SetShowProgress(false);
824 #if defined(DEBUGPASTE)
825 SvFileStream
aPasteDebug(
826 u
"PASTEBUFFER.debug"_ustr
, StreamMode::WRITE
|StreamMode::TRUNC
);
827 SwWriter
aDbgWrt( aPasteDebug
, *pDoc
);
828 aDbgWrt
.Write( xWrt
);
831 SwWriter
aWrt( rOStream
, *pDoc
);
832 if( ! aWrt
.Write( xWrt
).IsError() )
834 rOStream
.WriteChar( '\0' ); // terminate with a zero
842 int SwTransferable::Cut()
844 int nRet
= Copy( true );
847 collectUIInformation(u
"CUT"_ustr
, u
"parameter"_ustr
);
851 void SwTransferable::DeleteSelection()
855 // ask for type of selection before action-bracketing
856 const SelectionType nSelection
= m_pWrtShell
->GetSelectionType();
857 // cut rows or columns selected by enhanced table selection and wholly selected tables
858 bool bCutMode
= ( SelectionType::TableCell
& nSelection
) && ( (SelectionType::TableRow
| SelectionType::TableCol
) & nSelection
||
859 m_pWrtShell
->HasWholeTabSelection() );
861 m_pWrtShell
->StartUndo( SwUndoId::START
);
864 if( !(SelectionType::TableCol
& nSelection
) )
865 m_pWrtShell
->DeleteTable();
868 SfxDispatcher
* pDispatch
= m_pWrtShell
->GetView().GetViewFrame().GetDispatcher();
869 pDispatch
->Execute(FN_TABLE_DELETE_COL
, SfxCallMode::SYNCHRON
);
874 if( ( SelectionType::Text
| SelectionType::Table
) & nSelection
)
875 m_pWrtShell
->IntelligentCut( nSelection
);
876 m_pWrtShell
->DelRight();
878 m_pWrtShell
->EndUndo( SwUndoId::END
);
881 static void DeleteDDEMarks(SwDoc
& rDest
)
883 IDocumentMarkAccess
*const pMarkAccess
= rDest
.getIDocumentMarkAccess();
884 std::vector
< ::sw::mark::MarkBase
* > vDdeMarks
;
885 // find all DDE-Bookmarks
886 for (auto ppMark
= pMarkAccess
->getAllMarksBegin();
887 ppMark
!= pMarkAccess
->getAllMarksEnd();
890 if (IDocumentMarkAccess::MarkType::DDE_BOOKMARK
== IDocumentMarkAccess::GetType(**ppMark
))
892 vDdeMarks
.push_back(*ppMark
);
895 // remove all DDE-Bookmarks, they are invalid inside the clipdoc!
896 for (const auto& rpMark
: vDdeMarks
)
898 pMarkAccess
->deleteMark(rpMark
);
902 void SwTransferable::PrepareForCopyTextRange(SwPaM
& rPaM
)
904 std::optional
<SwWait
> oWait
;
905 if (m_pWrtShell
->ShouldWait())
907 oWait
.emplace( *m_pWrtShell
->GetView().GetDocShell(), true );
910 m_pClpDocFac
.reset(new SwDocFac
);
912 SwDoc
& rDest(lcl_GetDoc(*m_pClpDocFac
));
913 rDest
.getIDocumentFieldsAccess().LockExpFields(); // Never update fields - leave text as is
915 SwDoc
const& rSrc(*m_pWrtShell
->GetDoc());
916 assert(&rSrc
== &rPaM
.GetDoc());
918 rDest
.ReplaceCompatibilityOptions(rSrc
);
919 rDest
.ReplaceDefaults(rSrc
);
921 //It would probably make most sense here to only insert the styles used
922 //by the selection, e.g. apply SwDoc::IsUsed on styles ?
923 rDest
.ReplaceStyles(rSrc
, false);
925 // relevant bits of rSrcWrtShell.Copy(rDest);
926 rDest
.GetIDocumentUndoRedo().DoUndo(false); // always false!
927 rDest
.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines
);
929 SwNodeIndex
const aIdx(rDest
.GetNodes().GetEndOfContent(), -1);
930 SwContentNode
*const pContentNode(aIdx
.GetNode().GetContentNode());
931 SwPosition
aPos(aIdx
, pContentNode
, pContentNode
? pContentNode
->Len() : 0);
933 rSrc
.getIDocumentContentOperations().CopyRange(rPaM
, aPos
, SwCopyFlags::CheckPosInFly
);
935 rDest
.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::NONE
);
937 rDest
.GetMetaFieldManager().copyDocumentProperties(rSrc
);
940 DeleteDDEMarks(rDest
);
942 // a new one was created in core (OLE objects copied!)
943 m_aDocShellRef
= rDest
.GetTmpDocShell();
944 if (m_aDocShellRef
.Is())
945 SwTransferable::InitOle( m_aDocShellRef
);
946 rDest
.SetTmpDocShell( nullptr );
948 // let's add some formats
949 AddFormat( SotClipboardFormatId::EMBED_SOURCE
);
950 AddFormat( SotClipboardFormatId::RTF
);
951 #if HAVE_FEATURE_DESKTOP
952 AddFormat( SotClipboardFormatId::RICHTEXT
);
953 AddFormat( SotClipboardFormatId::HTML
);
955 AddFormat( SotClipboardFormatId::STRING
);
958 int SwTransferable::PrepareForCopy( bool bIsCut
)
964 if ( m_pWrtShell
->GetTableInsertMode() != SwTable::SEARCH_NONE
)
965 m_pWrtShell
->SetTableInsertMode( SwTable::SEARCH_NONE
);
967 if ( m_pWrtShell
->GetTableCopied() )
968 m_pWrtShell
->SetTableCopied( false );
971 const SelectionType nSelection
= m_pWrtShell
->GetSelectionType();
972 if( nSelection
== SelectionType::Graphic
)
974 m_oClpGraphic
.emplace();
975 if( !m_pWrtShell
->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE
, *m_oClpGraphic
))
976 m_pOrigGraphic
= &*m_oClpGraphic
;
977 m_oClpBitmap
.emplace();
978 if( !m_pWrtShell
->GetDrawObjGraphic( SotClipboardFormatId::BITMAP
, *m_oClpBitmap
))
979 m_pOrigGraphic
= &*m_oClpBitmap
;
981 m_pClpDocFac
.reset(new SwDocFac
);
982 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
983 m_pWrtShell
->Copy(rDoc
);
985 #if HAVE_FEATURE_DESKTOP
986 if (m_pOrigGraphic
&& !m_pOrigGraphic
->GetBitmapEx().IsEmpty())
987 AddFormat( SotClipboardFormatId::SVXB
);
990 PrepareOLE( m_aObjDesc
);
991 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
);
993 const Graphic
* pGrf
= m_pWrtShell
->GetGraphic();
994 if( pGrf
&& pGrf
->IsSupportedGraphic() )
996 AddFormat( SotClipboardFormatId::PNG
);
997 #if HAVE_FEATURE_DESKTOP
998 AddFormat( SotClipboardFormatId::GDIMETAFILE
);
999 AddFormat( SotClipboardFormatId::BITMAP
);
1002 m_eBufferType
= TransferBufferType::Graphic
;
1003 m_pWrtShell
->GetGrfNms( &sGrfNm
, nullptr );
1005 else if ( nSelection
== SelectionType::Ole
)
1007 m_pClpDocFac
.reset(new SwDocFac
);
1008 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
1009 m_aDocShellRef
= new SwDocShell(rDoc
, SfxObjectCreateMode::EMBEDDED
);
1010 m_aDocShellRef
->DoInitNew();
1011 m_pWrtShell
->Copy(rDoc
);
1013 AddFormat( SotClipboardFormatId::EMBED_SOURCE
);
1016 // set size of embedded object at the object description structure
1017 m_aObjDesc
.maSize
= o3tl::convert(m_pWrtShell
->GetObjSize(), o3tl::Length::twip
, o3tl::Length::mm100
);
1020 PrepareOLE( m_aObjDesc
);
1022 #if HAVE_FEATURE_DESKTOP
1023 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
);
1024 AddFormat( SotClipboardFormatId::GDIMETAFILE
);
1026 // Fetch the formats supported via embedtransferhelper as well
1027 sal_Int64 nAspect
= embed::Aspects::MSOLE_CONTENT
;
1028 uno::Reference
< embed::XEmbeddedObject
> xObj
= FindOLEObj( nAspect
);
1029 const Graphic
* pOLEGraph
= FindOLEReplacementGraphic();
1032 TransferableDataHelper
aD( new SvEmbedTransferHelper( xObj
, pOLEGraph
, nAspect
) );
1033 if ( aD
.GetTransferable().is() )
1035 DataFlavorExVector
aVector( aD
.GetDataFlavorExVector() );
1037 for( const auto& rItem
: aVector
)
1042 m_eBufferType
= TransferBufferType::Ole
;
1044 // Is there anything to provide anyway?
1045 else if ( m_pWrtShell
->IsSelection() || m_pWrtShell
->IsFrameSelected() ||
1046 m_pWrtShell
->IsObjSelected() )
1048 std::optional
<SwWait
> oWait
;
1049 if( m_pWrtShell
->ShouldWait() )
1050 oWait
.emplace( *m_pWrtShell
->GetView().GetDocShell(), true );
1052 m_pClpDocFac
.reset(new SwDocFac
);
1054 // create additional cursor so that equal treatment of keyboard
1055 // and mouse selection is possible.
1056 // In AddMode with keyboard selection, the new cursor is not created
1057 // before the cursor is moved after end of selection.
1058 if( m_pWrtShell
->IsAddMode() && m_pWrtShell
->SwCursorShell::HasSelection() )
1059 m_pWrtShell
->CreateCursor();
1061 SwDoc
& rTmpDoc
= lcl_GetDoc(*m_pClpDocFac
);
1063 rTmpDoc
.getIDocumentFieldsAccess().LockExpFields(); // Never update fields - leave text as is
1064 lclOverWriteDoc(*m_pWrtShell
, rTmpDoc
);
1066 DeleteDDEMarks(rTmpDoc
);
1068 // a new one was created in CORE (OLE objects copied!)
1069 m_aDocShellRef
= rTmpDoc
.GetTmpDocShell();
1070 if( m_aDocShellRef
.Is() )
1071 SwTransferable::InitOle( m_aDocShellRef
);
1072 rTmpDoc
.SetTmpDocShell( nullptr );
1074 if( m_pWrtShell
->IsObjSelected() )
1075 m_eBufferType
= TransferBufferType::Drawing
;
1078 m_eBufferType
= TransferBufferType::Document
;
1079 if (m_pWrtShell
->IntelligentCut(nSelection
, false) != SwWrtShell::NO_WORD
)
1080 m_eBufferType
= TransferBufferType::DocumentWord
| m_eBufferType
;
1083 bool bDDELink
= m_pWrtShell
->IsSelection();
1084 if( nSelection
& SelectionType::TableCell
)
1086 m_eBufferType
= TransferBufferType::Table
| m_eBufferType
;
1087 bDDELink
= m_pWrtShell
->HasWholeTabSelection();
1089 m_pWrtShell
->SetTableCopied(true);
1091 if ( bIsCut
&& (SelectionType::TableRow
| SelectionType::TableCol
) & nSelection
)
1092 m_pWrtShell
->SetTableInsertMode( (SelectionType::TableRow
& nSelection
) ? SwTable::SEARCH_ROW
: SwTable::SEARCH_COL
);
1095 #if HAVE_FEATURE_DESKTOP
1096 //When someone needs it, we 'OLE' him something
1097 AddFormat( SotClipboardFormatId::EMBED_SOURCE
);
1100 //put RTF ahead of the OLE's Metafile to have less loss
1101 if( !m_pWrtShell
->IsObjSelected() )
1103 AddFormat( SotClipboardFormatId::RTF
);
1104 #if HAVE_FEATURE_DESKTOP
1105 AddFormat( SotClipboardFormatId::RICHTEXT
);
1106 AddFormat( SotClipboardFormatId::HTML
);
1109 if( m_pWrtShell
->IsSelection() )
1110 AddFormat( SotClipboardFormatId::STRING
);
1112 if( nSelection
& ( SelectionType::DrawObject
| SelectionType::DbForm
))
1114 AddFormat( SotClipboardFormatId::DRAWING
);
1115 if ( nSelection
& SelectionType::DrawObject
)
1117 #if HAVE_FEATURE_DESKTOP
1118 AddFormat( SotClipboardFormatId::GDIMETAFILE
);
1119 AddFormat( SotClipboardFormatId::BITMAP
);
1121 AddFormat( SotClipboardFormatId::PNG
);
1123 m_eBufferType
= static_cast<TransferBufferType
>( TransferBufferType::Graphic
| m_eBufferType
);
1125 m_oClpGraphic
.emplace();
1126 if( !m_pWrtShell
->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE
, *m_oClpGraphic
))
1127 m_pOrigGraphic
= &*m_oClpGraphic
;
1128 m_oClpBitmap
.emplace();
1129 if( !m_pWrtShell
->GetDrawObjGraphic( SotClipboardFormatId::BITMAP
, *m_oClpBitmap
))
1130 m_pOrigGraphic
= &*m_oClpBitmap
;
1132 // is it a URL-Button ?
1135 if( m_pWrtShell
->GetURLFromButton( sURL
, sDesc
) )
1137 AddFormat( SotClipboardFormatId::STRING
);
1138 #if HAVE_FEATURE_DESKTOP
1139 AddFormat( SotClipboardFormatId::SOLK
);
1140 AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK
);
1141 AddFormat( SotClipboardFormatId::FILECONTENT
);
1142 AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR
);
1144 AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR
);
1145 m_eBufferType
= TransferBufferType::InetField
| m_eBufferType
;
1150 // at Cut, DDE-Link doesn't make sense!!
1151 SwDocShell
* pDShell
;
1152 if( !bIsCut
&& bDDELink
&&
1153 nullptr != ( pDShell
= m_pWrtShell
->GetDoc()->GetDocShell()) &&
1154 SfxObjectCreateMode::STANDARD
== pDShell
->GetCreateMode() )
1156 #if HAVE_FEATURE_DESKTOP
1157 AddFormat( SotClipboardFormatId::LINK
);
1159 m_xDdeLink
= new SwTransferDdeLink( *this, *m_pWrtShell
);
1162 //ObjectDescriptor was already filly from the old DocShell.
1163 //Now adjust it. Thus in GetData the first query can still
1164 //be answered with delayed rendering.
1165 m_aObjDesc
.maSize
= constOleSize100mm
;
1167 PrepareOLE( m_aObjDesc
);
1168 #if HAVE_FEATURE_DESKTOP
1169 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
);
1175 if( m_pWrtShell
->IsFrameSelected() )
1177 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( m_pWrtShell
->GetAttrPool() );
1178 m_pWrtShell
->GetFlyFrameAttr( aSet
);
1179 const SwFormatURL
& rURL
= aSet
.Get( RES_URL
);
1182 m_pImageMap
.reset( new ImageMap( *rURL
.GetMap() ) );
1183 AddFormat( SotClipboardFormatId::SVIM
);
1185 else if( !rURL
.GetURL().isEmpty() )
1187 m_pTargetURL
.reset(new INetImage( sGrfNm
, rURL
.GetURL(),
1188 rURL
.GetTargetFrameName() ));
1189 AddFormat( SotClipboardFormatId::INET_IMAGE
);
1196 int SwTransferable::Copy( bool bIsCut
)
1198 if (m_pWrtShell
->GetView().GetObjectShell()->isContentExtractionLocked())
1201 int nRet
= PrepareForCopy( bIsCut
);
1204 CopyToClipboard( &m_pWrtShell
->GetView().GetEditWin() );
1208 collectUIInformation(u
"COPY"_ustr
, u
"parameter"_ustr
);
1214 void SwTransferable::CalculateAndCopy()
1218 SwWait
aWait( *m_pWrtShell
->GetView().GetDocShell(), true );
1220 OUString
aStr( m_pWrtShell
->Calculate() );
1222 m_pClpDocFac
.reset(new SwDocFac
);
1223 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
1224 m_pWrtShell
->Copy(rDoc
, &aStr
);
1225 m_eBufferType
= TransferBufferType::Document
;
1226 AddFormat( SotClipboardFormatId::STRING
);
1228 CopyToClipboard( &m_pWrtShell
->GetView().GetEditWin() );
1231 bool SwTransferable::CopyGlossary( SwTextBlocks
& rGlossary
, const OUString
& rStr
)
1235 SwWait
aWait( *m_pWrtShell
->GetView().GetDocShell(), true );
1237 m_pClpDocFac
.reset(new SwDocFac
);
1238 SwDoc
& rCDoc
= lcl_GetDoc(*m_pClpDocFac
);
1240 SwNodes
& rNds
= rCDoc
.GetNodes();
1241 SwNodeIndex
aNodeIdx( *rNds
.GetEndOfContent().StartOfSectionNode() );
1242 SwContentNode
* pCNd
= SwNodes::GoNext(&aNodeIdx
); // go to 1st ContentNode
1243 SwPaM
aPam( *pCNd
);
1245 rCDoc
.getIDocumentFieldsAccess().LockExpFields(); // never update fields - leave text as it is
1247 rCDoc
.InsertGlossary( rGlossary
, rStr
, aPam
);
1249 // a new one was created in CORE (OLE-Objects copied!)
1250 m_aDocShellRef
= rCDoc
.GetTmpDocShell();
1251 if( m_aDocShellRef
.Is() )
1252 SwTransferable::InitOle( m_aDocShellRef
);
1253 rCDoc
.SetTmpDocShell( nullptr );
1255 m_eBufferType
= TransferBufferType::Document
;
1257 //When someone needs it, we 'OLE' her something.
1258 AddFormat( SotClipboardFormatId::EMBED_SOURCE
);
1259 AddFormat( SotClipboardFormatId::RTF
);
1260 AddFormat( SotClipboardFormatId::RICHTEXT
);
1261 AddFormat( SotClipboardFormatId::HTML
);
1262 AddFormat( SotClipboardFormatId::STRING
);
1264 //ObjectDescriptor was already filled from the old DocShell.
1265 //Now adjust it. Thus in GetData the first query can still
1266 //be answered with delayed rendering.
1267 m_aObjDesc
.maSize
= constOleSize100mm
;
1269 PrepareOLE( m_aObjDesc
);
1270 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
);
1272 CopyToClipboard( &m_pWrtShell
->GetView().GetEditWin() );
1277 static uno::Reference
< XTransferable
> * lcl_getTransferPointer ( uno::Reference
< XTransferable
> &xRef
)
1282 SwPasteContext::SwPasteContext(SwWrtShell
& rWrtShell
)
1283 : m_rWrtShell(rWrtShell
)
1288 void SwPasteContext::remember()
1290 if (m_rWrtShell
.GetPasteListeners().getLength() == 0)
1293 SwPaM
* pCursor
= m_rWrtShell
.GetCursor();
1297 // Set point to the previous node, so it is not moved.
1298 const SwNode
& rNode
= pCursor
->GetPoint()->GetNode();
1299 m_oPaM
.emplace(rNode
, rNode
, SwNodeOffset(0), SwNodeOffset(-1));
1300 m_nStartContent
= pCursor
->GetPoint()->GetContentIndex();
1303 void SwPasteContext::forget() { m_oPaM
.reset(); }
1305 SwPasteContext::~SwPasteContext()
1309 if (m_rWrtShell
.GetPasteListeners().getLength() == 0)
1312 beans::PropertyValue aPropertyValue
;
1314 switch (m_rWrtShell
.GetView().GetShellMode())
1316 case ShellMode::Graphic
:
1318 SwFrameFormat
* pFormat
= m_rWrtShell
.GetFlyFrameFormat();
1322 aPropertyValue
.Name
= "TextGraphicObject";
1323 aPropertyValue
.Value
1324 <<= uno::Reference
<text::XTextContent
>(SwXTextGraphicObject::CreateXTextGraphicObject(*pFormat
->GetDoc(), pFormat
));
1333 SwPaM
* pCursor
= m_rWrtShell
.GetCursor();
1337 if (!pCursor
->GetPoint()->GetNode().IsTextNode())
1338 // Non-text was pasted.
1341 // Update mark after paste.
1342 *m_oPaM
->GetMark() = *pCursor
->GetPoint();
1345 m_oPaM
->GetPoint()->Adjust(SwNodeOffset(1));
1346 SwNode
& rNode
= m_oPaM
->GetPointNode();
1347 if (!rNode
.IsTextNode())
1348 // Starting point is no longer text.
1351 m_oPaM
->GetPoint()->SetContent(m_nStartContent
);
1353 aPropertyValue
.Name
= "TextRange";
1354 const rtl::Reference
<SwXTextRange
> xTextRange
= SwXTextRange::CreateXTextRange(
1355 m_oPaM
->GetDoc(), *m_oPaM
->GetPoint(), m_oPaM
->GetMark());
1356 aPropertyValue
.Value
<<= uno::Reference
<text::XTextRange
>(xTextRange
);
1361 if (aPropertyValue
.Name
.isEmpty())
1364 // Invoke the listeners.
1365 uno::Sequence
<beans::PropertyValue
> aEvent
{ std::move(aPropertyValue
) };
1366 m_rWrtShell
.GetPasteListeners().notifyEach( &css::text::XPasteListener::notifyPasteEvent
, aEvent
);
1368 catch (const uno::Exception
& rException
)
1371 "SwPasteContext::~SwPasteContext: uncaught exception: " << rException
.Message
);
1375 bool SwTransferable::IsPaste( const SwWrtShell
& rSh
,
1376 const TransferableDataHelper
& rData
)
1378 // Check the common case first: We can always paste our own data!
1379 // If _only_ the internal format can be pasted, this check will
1380 // yield 'true', while the one below would give a (wrong) result 'false'.
1382 bool bIsPaste
= ( GetSwTransferable( rData
) != nullptr );
1384 // if it's not our own data, we need to have a closer look:
1387 // determine the proper paste action, and return true if we find one
1388 uno::Reference
<XTransferable
> xTransferable( rData
.GetXTransferable() );
1390 SotExchangeDest nDestination
= SwTransferable::GetSotDestination( rSh
);
1391 sal_uInt16 nSourceOptions
=
1392 (( SotExchangeDest::DOC_TEXTFRAME
== nDestination
||
1393 SotExchangeDest::SWDOC_FREE_AREA
== nDestination
||
1394 SotExchangeDest::DOC_TEXTFRAME_WEB
== nDestination
||
1395 SotExchangeDest::SWDOC_FREE_AREA_WEB
== nDestination
)
1396 ? EXCHG_IN_ACTION_COPY
1397 : EXCHG_IN_ACTION_MOVE
);
1399 SotClipboardFormatId nFormat
; // output param for GetExchangeAction
1400 sal_uInt8 nEventAction
; // output param for GetExchangeAction
1401 sal_uInt8 nAction
= SotExchange::GetExchangeAction(
1402 rData
.GetDataFlavorExVector(),
1404 nSourceOptions
, /* ?? */
1405 EXCHG_IN_ACTION_DEFAULT
, /* ?? */
1406 nFormat
, nEventAction
, SotClipboardFormatId::NONE
,
1407 lcl_getTransferPointer ( xTransferable
) );
1409 // if we find a suitable action, we can paste!
1410 bIsPaste
= (EXCHG_INOUT_ACTION_NONE
!= nAction
);
1416 void SwTransferable::SelectPasteFormat(TransferableDataHelper
& rData
, sal_uInt8
& nAction
,
1417 SotClipboardFormatId
& nFormat
)
1419 if (nFormat
!= SotClipboardFormatId::RICHTEXT
)
1424 if (!rData
.HasFormat(SotClipboardFormatId::EMBED_SOURCE
))
1429 if (!rData
.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR
))
1434 TransferableObjectDescriptor aObjDesc
;
1435 if (!rData
.GetTransferableObjectDescriptor(SotClipboardFormatId::OBJECTDESCRIPTOR
, aObjDesc
))
1440 if (aObjDesc
.maClassName
!= SvGlobalName(SO3_SW_CLASSID
))
1445 // At this point we know that we paste from Writer to Writer and the clipboard has the content
1446 // in both RTF and ODF formats. Prefer ODF in this case.
1447 nAction
= EXCHG_OUT_ACTION_INSERT_OLE
;
1448 nFormat
= SotClipboardFormatId::EMBED_SOURCE
;
1451 // get HTML indentation level by counting tabulator characters before the index
1452 // (also index value -1 returns with 0)
1453 static sal_Int32
lcl_getLevel(OUString
& sText
, sal_Int32 nIdx
)
1456 while ( nIdx
-- > 0 && sText
[nIdx
] == '\t' )
1463 bool SwTransferable::Paste(SwWrtShell
& rSh
, TransferableDataHelper
& rData
, RndStdIds nAnchorType
, bool bIgnoreComments
, PasteTableType ePasteTable
)
1465 SwPasteContext
aPasteContext(rSh
);
1467 sal_uInt8 nAction
=0;
1468 SotExchangeDest nDestination
= SwTransferable::GetSotDestination( rSh
);
1469 SotClipboardFormatId nFormat
= SotClipboardFormatId::NONE
;
1470 SotExchangeActionFlags nActionFlags
= SotExchangeActionFlags::NONE
;
1471 bool bSingleCellTable
= false;
1473 if( GetSwTransferable( rData
) )
1475 nAction
= EXCHG_OUT_ACTION_INSERT_PRIVATE
;
1479 sal_uInt16 nSourceOptions
=
1480 (( SotExchangeDest::DOC_TEXTFRAME
== nDestination
||
1481 SotExchangeDest::SWDOC_FREE_AREA
== nDestination
||
1482 SotExchangeDest::DOC_TEXTFRAME_WEB
== nDestination
||
1483 SotExchangeDest::SWDOC_FREE_AREA_WEB
== nDestination
)
1484 ? EXCHG_IN_ACTION_COPY
1485 : EXCHG_IN_ACTION_MOVE
);
1486 uno::Reference
<XTransferable
> xTransferable( rData
.GetXTransferable() );
1487 sal_uInt8 nEventAction
;
1488 nAction
= SotExchange::GetExchangeAction(
1489 rData
.GetDataFlavorExVector(),
1491 nSourceOptions
, /* ?? */
1492 EXCHG_IN_ACTION_DEFAULT
, /* ?? */
1493 nFormat
, nEventAction
, SotClipboardFormatId::NONE
,
1494 lcl_getTransferPointer ( xTransferable
),
1498 // when HTML is just an image don't generate new section
1499 if (rData
.HasFormat(SotClipboardFormatId::HTML_SIMPLE
) && rData
.HasFormat(SotClipboardFormatId::HTML_NO_COMMENT
)
1500 && rData
.HasFormat(SotClipboardFormatId::BITMAP
) && nFormat
== SotClipboardFormatId::FILE_LIST
)
1501 nFormat
= SotClipboardFormatId::BITMAP
;
1503 // tdf#37223 avoid non-native insertion of Calc worksheets in the following cases:
1504 // content of 1-cell worksheets are inserted as simple text using RTF format,
1505 // bigger worksheets within native (Writer) table cells are inserted as native tables,
1506 // ie. cell by cell instead of embedding the worksheet in a single cell of the Writer table
1507 if ( EXCHG_IN_ACTION_COPY
== nAction
&& ( rData
.HasFormat( SotClipboardFormatId::SYLK
) ||
1508 rData
.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS
) ) )
1510 // is it a 1-cell worksheet?
1512 if( rData
.GetString( SotClipboardFormatId::STRING
, aExpand
))
1514 const sal_Int32 nNewlines
{comphelper::string::getTokenCount(aExpand
, '\n')};
1515 const sal_Int32 nRows
= nNewlines
? nNewlines
-1 : 0;
1518 const sal_Int32 nCols
= comphelper::string::getTokenCount(o3tl::getToken(aExpand
, 0, '\n'), '\t');
1520 bSingleCellTable
= true;
1524 // convert the worksheet to a temporary native table using HTML format, and copy that into the original native table
1525 if (!bSingleCellTable
&& rData
.HasFormat( SotClipboardFormatId::HTML
) &&
1526 SwDoc::IsInTable(rSh
.GetCursor()->GetPointNode()) != nullptr && rSh
.DoesUndo())
1528 SfxDispatcher
* pDispatch
= rSh
.GetView().GetViewFrame().GetDispatcher();
1529 sal_uInt32 nLevel
= 0;
1531 // within Writer table cells, inserting worksheets using HTML format results only plain text, not a native table,
1532 // so remove all outer nested tables temporary to get a working insertion point
1533 // (RTF format has no such problem, but that inserts the hidden rows of the original Calc worksheet, too)
1535 // For this, switch off change tracking temporarily, if needed
1536 RedlineFlags eOld
= rSh
.GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags();
1537 if ( eOld
& RedlineFlags::On
)
1538 rSh
.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eOld
& ~RedlineFlags::On
);
1540 OUString sPreviousTableName
;
1543 // tdf#152245 add a limit to the loop, if it's not possible to delete the table
1544 const SwTableNode
* pNode
= rSh
.GetCursor()->GetPointNode().FindTableNode();
1545 const OUString sTableName
= pNode
->GetTable().GetFrameFormat()->GetName();
1546 if ( sTableName
== sPreviousTableName
)
1548 sPreviousTableName
= sTableName
;
1549 // insert a random character to redo the place of the insertion at the end
1550 pDispatch
->Execute(FN_INSERT_NNBSP
, SfxCallMode::SYNCHRON
);
1551 pDispatch
->Execute(FN_TABLE_DELETE_TABLE
, SfxCallMode::SYNCHRON
);
1553 } while (SwDoc::IsInTable(rSh
.GetCursor()->GetPointNode()) != nullptr);
1555 // restore change tracking settings
1556 if ( eOld
& RedlineFlags::On
)
1557 rSh
.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eOld
);
1559 if ( SwTransferable::PasteData( rData
, rSh
, EXCHG_OUT_ACTION_INSERT_STRING
, nActionFlags
, SotClipboardFormatId::HTML
,
1560 nDestination
, false, false, nullptr, 0, false, nAnchorType
, bIgnoreComments
, &aPasteContext
, ePasteTable
) )
1562 bool bFoundTemporaryTable
= false;
1563 pDispatch
->Execute(FN_LINE_UP
, SfxCallMode::SYNCHRON
);
1564 if (SwDoc::IsInTable(rSh
.GetCursor()->GetPointNode()) != nullptr)
1566 bFoundTemporaryTable
= true;
1567 pDispatch
->Execute(FN_TABLE_SELECT_ALL
, SfxCallMode::SYNCHRON
);
1568 pDispatch
->Execute(SID_COPY
, SfxCallMode::SYNCHRON
);
1570 for(sal_uInt32 a
= 0; a
< 1 + (nLevel
* 2); a
++)
1571 pDispatch
->Execute(SID_UNDO
, SfxCallMode::SYNCHRON
);
1572 // clipboard content hasn't changed (limit potential infinite
1573 // recursion with the same non-native table, as was in tdf#138688)
1574 if (!bFoundTemporaryTable
)
1576 if (ePasteTable
== PasteTableType::PASTE_TABLE
)
1577 pDispatch
->Execute(FN_PASTE_NESTED_TABLE
, SfxCallMode::SYNCHRON
);
1578 else if (ePasteTable
== PasteTableType::PASTE_ROW
)
1579 pDispatch
->Execute(FN_TABLE_PASTE_ROW_BEFORE
, SfxCallMode::SYNCHRON
);
1580 else if (ePasteTable
== PasteTableType::PASTE_COLUMN
)
1581 pDispatch
->Execute(FN_TABLE_PASTE_COL_BEFORE
, SfxCallMode::SYNCHRON
);
1583 pDispatch
->Execute(SID_PASTE
, SfxCallMode::SYNCHRON
);
1586 for(sal_uInt32 a
= 0; a
< (nLevel
* 2); a
++)
1587 pDispatch
->Execute(SID_UNDO
, SfxCallMode::SYNCHRON
);
1591 // insert clipboard content as new table rows/columns before the actual row/column instead of overwriting it
1592 else if ( (rSh
.GetTableInsertMode() != SwTable::SEARCH_NONE
|| ePasteTable
== PasteTableType::PASTE_ROW
|| ePasteTable
== PasteTableType::PASTE_COLUMN
) &&
1593 rData
.HasFormat( SotClipboardFormatId::HTML
) &&
1594 SwDoc::IsInTable(rSh
.GetCursor()->GetPointNode()) != nullptr )
1598 bool bRowMode
= rSh
.GetTableInsertMode() == SwTable::SEARCH_ROW
|| ePasteTable
== PasteTableType::PASTE_ROW
;
1599 if( rData
.GetString( SotClipboardFormatId::HTML
, aExpand
) && (nIdx
= aExpand
.indexOf("<table")) > -1 )
1601 // calculate table row/column count by analysing indentation of the HTML table extract
1603 // calculate indentation level of <table>, which is the base of the next calculations
1604 // (tdf#148791 table alignment can enlarge it using first level <center>, <div> or <dl>)
1605 sal_Int32 nTableLevel
= lcl_getLevel(aExpand
, nIdx
);
1606 // table rows repeated heading use extra indentation, too:
1607 // <thead> is always used here, and the first table with <thead> is not nested,
1608 // if its indentation level is greater only by 1, than indentation level of the table
1609 bool bShifted
= lcl_getLevel(aExpand
, aExpand
.indexOf("<thead")) == nTableLevel
+ 1;
1610 // calculate count of selected rows or columns
1611 sal_Int32 nSelectedRowsOrCols
= 0;
1612 const OUString sSearchRowOrCol
= bRowMode
? u
"</tr>"_ustr
: u
"<col "_ustr
;
1613 while((nIdx
= aExpand
.indexOf(sSearchRowOrCol
, nIdx
)) > -1)
1615 // skip rows/columns of nested tables, based on HTML indentation
1616 if ( lcl_getLevel(aExpand
, nIdx
) == nTableLevel
+ (bShifted
? 2 : 1) &&
1617 // skip also strange hidden empty rows <tr></tr>
1618 !aExpand
.match("<tr></tr>", nIdx
- 4) )
1620 ++nSelectedRowsOrCols
;
1624 // are we at the beginning of the cell?
1625 bool bStartTableBoxNode
=
1626 // first paragraph of the cell?
1627 rSh
.GetCursor()->GetPointNode().GetIndex() == rSh
.GetCursor()->GetPointNode().FindTableBoxStartNode()->GetIndex()+1 &&
1628 // beginning of the paragraph?
1629 !rSh
.GetCursor()->GetPoint()->GetContentIndex();
1630 SfxDispatcher
* pDispatch
= rSh
.GetView().GetViewFrame().GetDispatcher();
1632 // go start of the cell
1633 if (!bStartTableBoxNode
)
1634 pDispatch
->Execute(FN_START_OF_DOCUMENT
, SfxCallMode::SYNCHRON
);
1636 // store cursor position in row mode
1637 ::sw::mark::MarkBase
* pMark
= (!bRowMode
|| nSelectedRowsOrCols
== 0) ? nullptr : rSh
.SetBookmark(
1640 IDocumentMarkAccess::MarkType::UNO_BOOKMARK
);
1642 // add a new empty row/column before the actual table row/column and go there
1643 const sal_uInt16 nDispatchSlot
= bRowMode
? FN_TABLE_INSERT_ROW_BEFORE
: FN_TABLE_INSERT_COL_BEFORE
;
1644 pDispatch
->Execute(nDispatchSlot
, SfxCallMode::SYNCHRON
);
1645 pDispatch
->Execute(bRowMode
? FN_LINE_UP
: FN_CHAR_LEFT
, SfxCallMode::SYNCHRON
);
1647 // add the other new empty rows/columns after the actual table row/column
1648 if ( nSelectedRowsOrCols
> 1 )
1650 SfxInt16Item
aCountItem( nDispatchSlot
, nSelectedRowsOrCols
-1 );
1651 SfxBoolItem
aAfter( FN_PARAM_INSERT_AFTER
, true );
1652 pDispatch
->ExecuteList(nDispatchSlot
,
1653 SfxCallMode::SYNCHRON
|SfxCallMode::RECORD
,
1654 { &aCountItem
, &aAfter
});
1658 bool bResult
= SwTransferable::PasteData( rData
, rSh
, nAction
, nActionFlags
, nFormat
,
1659 nDestination
, false, false, nullptr, 0, false, nAnchorType
, bIgnoreComments
, &aPasteContext
);
1661 // restore cursor position
1662 if (pMark
!= nullptr)
1664 rSh
.GotoMark( pMark
);
1665 rSh
.getIDocumentMarkAccess()->deleteMark( pMark
);
1672 // special case for tables from draw application or 1-cell tables
1673 if( EXCHG_OUT_ACTION_INSERT_DRAWOBJ
== nAction
|| bSingleCellTable
)
1675 if( rData
.HasFormat( SotClipboardFormatId::RTF
) )
1677 nAction
= EXCHG_OUT_ACTION_INSERT_STRING
;
1678 nFormat
= SotClipboardFormatId::RTF
;
1680 else if( rData
.HasFormat( SotClipboardFormatId::RICHTEXT
) )
1682 nAction
= EXCHG_OUT_ACTION_INSERT_STRING
;
1683 nFormat
= SotClipboardFormatId::RICHTEXT
;
1687 // Tweak the format if necessary: the source application can be considered in this context,
1688 // while not in sot/ code.
1689 SwTransferable::SelectPasteFormat(rData
, nAction
, nFormat
);
1691 collectUIInformation(u
"PASTE"_ustr
, u
"parameter"_ustr
);
1693 return EXCHG_INOUT_ACTION_NONE
!= nAction
&&
1694 SwTransferable::PasteData( rData
, rSh
, nAction
, nActionFlags
, nFormat
,
1695 nDestination
, false, false, nullptr, 0, false, nAnchorType
, bIgnoreComments
, &aPasteContext
, ePasteTable
);
1698 bool SwTransferable::PasteData( const TransferableDataHelper
& rData
,
1699 SwWrtShell
& rSh
, sal_uInt8 nAction
, SotExchangeActionFlags nActionFlags
,
1700 SotClipboardFormatId nFormat
,
1701 SotExchangeDest nDestination
, bool bIsPasteFormat
,
1702 [[maybe_unused
]] bool bIsDefault
,
1703 const Point
* pPt
, sal_Int8 nDropAction
,
1704 bool bPasteSelection
, RndStdIds nAnchorType
,
1705 bool bIgnoreComments
,
1706 SwPasteContext
* pContext
,
1707 PasteTableType ePasteTable
)
1709 SwWait
aWait( *rSh
.GetView().GetDocShell(), false );
1710 std::unique_ptr
<SwTrnsfrActionAndUndo
, o3tl::default_delete
<SwTrnsfrActionAndUndo
>> pAction
;
1711 SwModule
* pMod
= SwModule::get();
1714 bool bCallAutoCaption
= false;
1719 if ((bPasteSelection
? !pMod
->m_pXSelection
: !pMod
->m_pDragDrop
) &&
1720 // The following condition is used for tdf#156111 to prevent a selection from being
1721 // cleared by the default case of the nDestination switch.
1722 !(rSh
.GetCursorCnt() == 1 && rSh
.TestCurrPam(*pPt
) &&
1723 nDestination
== SotExchangeDest::SWDOC_FREE_AREA
&&
1724 nFormat
== SotClipboardFormatId::SONLK
))
1726 switch( nDestination
)
1728 case SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP
:
1729 case SotExchangeDest::DOC_LNKD_GRAPHOBJ
:
1730 case SotExchangeDest::DOC_GRAPH_W_IMAP
:
1731 case SotExchangeDest::DOC_GRAPHOBJ
:
1732 case SotExchangeDest::DOC_OLEOBJ
:
1733 case SotExchangeDest::DOC_DRAWOBJ
:
1734 case SotExchangeDest::DOC_URLBUTTON
:
1735 case SotExchangeDest::DOC_GROUPOBJ
:
1736 // select frames/objects
1737 SwTransferable::SetSelInShell( rSh
, true, pPt
);
1741 bool bLockView
= rSh
.IsViewLocked();
1742 if (nFormat
== SotClipboardFormatId::SONLK
)
1743 rSh
.LockView(true); // prevent view jump
1744 SwTransferable::SetSelInShell( rSh
, false, pPt
);
1745 rSh
.LockView(bLockView
);
1750 else if( ( !GetSwTransferable( rData
) || bIsPasteFormat
) &&
1751 !rSh
.IsTableMode() && rSh
.HasSelection() )
1753 // then delete the selections
1755 //don't delete selected content
1756 // - at table-selection
1757 // - at ReRead of a graphic/DDEData
1758 // - at D&D, for the right selection was taken care of
1760 bool bDelSel
= false;
1761 switch( nDestination
)
1763 case SotExchangeDest::DOC_TEXTFRAME
:
1764 case SotExchangeDest::SWDOC_FREE_AREA
:
1765 case SotExchangeDest::DOC_TEXTFRAME_WEB
:
1766 case SotExchangeDest::SWDOC_FREE_AREA_WEB
:
1775 pAction
.reset(new SwTrnsfrActionAndUndo(&rSh
, true, pContext
));
1778 SwTransferable
*pTrans
=nullptr, *pTunneledTrans
=GetSwTransferable( rData
);
1780 // check for private drop
1781 bool bPrivateDrop(pPt
);
1784 if (bPasteSelection
)
1785 pTrans
= pMod
->m_pXSelection
;
1787 pTrans
= pMod
->m_pDragDrop
;
1788 bPrivateDrop
= nullptr != pTrans
;
1790 bool bNeedToSelectBeforePaste(false);
1792 if(bPrivateDrop
&& DND_ACTION_LINK
== nDropAction
)
1794 // internal drop on object, suppress bPrivateDrop to change internal fill
1795 bPrivateDrop
= false;
1796 bNeedToSelectBeforePaste
= true;
1799 if(bPrivateDrop
&& pPt
&& DND_ACTION_MOVE
== nDropAction
)
1801 // check if dragged over a useful target. If yes, use as content exchange
1802 // drop as if from external
1803 const SwFrameFormat
* pSwFrameFormat
= rSh
.GetFormatFromObj(*pPt
);
1805 if(dynamic_cast< const SwDrawFrameFormat
* >(pSwFrameFormat
))
1807 bPrivateDrop
= false;
1808 bNeedToSelectBeforePaste
= true;
1814 // then internal Drag & Drop or XSelection
1815 bRet
= pTrans
->PrivateDrop( rSh
, *pPt
, DND_ACTION_MOVE
== nDropAction
,
1818 else if( !pPt
&& pTunneledTrans
&&
1819 EXCHG_OUT_ACTION_INSERT_PRIVATE
== nAction
)
1821 // then internal paste
1822 bRet
= pTunneledTrans
->PrivatePaste(rSh
, pContext
, ePasteTable
);
1824 else if( EXCHG_INOUT_ACTION_NONE
!= nAction
)
1828 pAction
.reset(new SwTrnsfrActionAndUndo( &rSh
));
1831 // in Drag&Drop MessageBoxes must not be showed
1832 bool bMsg
= nullptr == pPt
;
1834 // delete selections
1838 case EXCHG_OUT_ACTION_INSERT_PRIVATE
:
1839 OSL_ENSURE( pPt
, "EXCHG_OUT_ACTION_INSERT_PRIVATE: what should happen here?" );
1842 case EXCHG_OUT_ACTION_MOVE_PRIVATE
:
1843 OSL_ENSURE( pPt
, "EXCHG_OUT_ACTION_MOVE_PRIVATE: what should happen here?" );
1846 case EXCHG_IN_ACTION_MOVE
:
1847 case EXCHG_IN_ACTION_COPY
:
1848 case EXCHG_IN_ACTION_LINK
:
1849 case EXCHG_OUT_ACTION_INSERT_HTML
:
1850 case EXCHG_OUT_ACTION_INSERT_STRING
:
1851 case EXCHG_OUT_ACTION_INSERT_IMAGEMAP
:
1852 case EXCHG_OUT_ACTION_REPLACE_IMAGEMAP
:
1854 // then we have to use the format
1857 case SotClipboardFormatId::DRAWING
:
1858 bRet
= SwTransferable::PasteSdrFormat( rData
, rSh
,
1859 SwPasteSdr::Insert
, pPt
,
1860 nActionFlags
, bNeedToSelectBeforePaste
);
1863 case SotClipboardFormatId::HTML
:
1864 case SotClipboardFormatId::HTML_SIMPLE
:
1865 case SotClipboardFormatId::HTML_NO_COMMENT
:
1866 case SotClipboardFormatId::RTF
:
1867 case SotClipboardFormatId::RICHTEXT
:
1868 case SotClipboardFormatId::STRING
:
1869 bRet
= SwTransferable::PasteFileContent( rData
, rSh
,
1870 nFormat
, bMsg
, bIgnoreComments
);
1873 case SotClipboardFormatId::NETSCAPE_BOOKMARK
:
1876 if( rData
.GetINetBookmark( nFormat
, aBkmk
) )
1878 SwFormatINetFormat
aFormat( aBkmk
.GetURL(), OUString() );
1879 rSh
.InsertURL( aFormat
, aBkmk
.GetDescription() );
1885 case SotClipboardFormatId::SD_OLE
:
1886 bRet
= SwTransferable::PasteOLE( rData
, rSh
, nFormat
,
1887 nActionFlags
, bMsg
);
1890 case SotClipboardFormatId::SVIM
:
1891 bRet
= SwTransferable::PasteImageMap( rData
, rSh
);
1894 case SotClipboardFormatId::SVXB
:
1895 case SotClipboardFormatId::BITMAP
:
1896 case SotClipboardFormatId::PNG
:
1897 case SotClipboardFormatId::GDIMETAFILE
:
1898 bRet
= SwTransferable::PasteGrf( rData
, rSh
, nFormat
,
1899 SwPasteSdr::Insert
,pPt
,
1900 nActionFlags
, nDropAction
, bNeedToSelectBeforePaste
);
1903 case SotClipboardFormatId::XFORMS
:
1904 case SotClipboardFormatId::SBA_FIELDDATAEXCHANGE
:
1905 case SotClipboardFormatId::SBA_DATAEXCHANGE
:
1906 case SotClipboardFormatId::SBA_CTRLDATAEXCHANGE
:
1907 bRet
= SwTransferable::PasteDBData( rData
, rSh
, nFormat
,
1908 EXCHG_IN_ACTION_LINK
== nAction
,
1912 case SotClipboardFormatId::SIMPLE_FILE
:
1913 bRet
= SwTransferable::PasteFileName( rData
, rSh
, nFormat
,
1914 ( EXCHG_IN_ACTION_MOVE
== nAction
1915 ? SwPasteSdr::Replace
1916 : EXCHG_IN_ACTION_LINK
== nAction
1917 ? SwPasteSdr::SetAttr
1918 : SwPasteSdr::Insert
),
1919 pPt
, nActionFlags
, nullptr );
1922 case SotClipboardFormatId::FILE_LIST
:
1923 // then insert as graphics only
1924 bRet
= SwTransferable::PasteFileList( rData
, rSh
,
1925 EXCHG_IN_ACTION_LINK
== nAction
,
1929 case SotClipboardFormatId::SONLK
:
1932 NaviContentBookmark aBkmk
;
1933 if (aBkmk
.Paste(rData
, rSh
.GetSelText()))
1935 aWait
.~SwWait(); // end the wait pointer, X11 only annoyance
1936 rSh
.NavigatorPaste(aBkmk
);
1942 case SotClipboardFormatId::INET_IMAGE
:
1943 case SotClipboardFormatId::NETSCAPE_IMAGE
:
1944 bRet
= SwTransferable::PasteTargetURL( rData
, rSh
,
1950 OSL_ENSURE( pPt
, "unknown format" );
1954 case EXCHG_OUT_ACTION_INSERT_FILE
:
1956 bool graphicInserted
;
1957 bRet
= SwTransferable::PasteFileName( rData
, rSh
, nFormat
,
1958 SwPasteSdr::Insert
, pPt
,
1961 if( graphicInserted
)
1962 bCallAutoCaption
= true;
1966 case EXCHG_OUT_ACTION_INSERT_OLE
:
1967 bRet
= SwTransferable::PasteOLE( rData
, rSh
, nFormat
,
1968 nActionFlags
,bMsg
);
1971 case EXCHG_OUT_ACTION_INSERT_DDE
:
1973 bool bReRead
= 0 != CNT_HasGrf( rSh
.GetCntType() );
1974 bRet
= SwTransferable::PasteDDE( rData
, rSh
, bReRead
, bMsg
);
1978 case EXCHG_OUT_ACTION_INSERT_HYPERLINK
:
1980 OUString sURL
, sDesc
;
1981 if( SotClipboardFormatId::SIMPLE_FILE
== nFormat
)
1983 if( rData
.GetString( nFormat
, sURL
) && !sURL
.isEmpty() )
1985 SwTransferable::CheckForURLOrLNKFile( rData
, sURL
, &sDesc
);
1986 if( sDesc
.isEmpty() )
1994 if( rData
.GetINetBookmark( nFormat
, aBkmk
) )
1996 sURL
= aBkmk
.GetURL();
1997 sDesc
= aBkmk
.GetDescription();
2004 SwFormatINetFormat
aFormat( sURL
, OUString() );
2005 rSh
.InsertURL( aFormat
, sDesc
);
2010 case EXCHG_OUT_ACTION_GET_ATTRIBUTES
:
2013 case SotClipboardFormatId::DRAWING
:
2014 bRet
= SwTransferable::PasteSdrFormat( rData
, rSh
,
2015 SwPasteSdr::SetAttr
, pPt
,
2016 nActionFlags
, bNeedToSelectBeforePaste
);
2018 case SotClipboardFormatId::SVXB
:
2019 case SotClipboardFormatId::GDIMETAFILE
:
2020 case SotClipboardFormatId::BITMAP
:
2021 case SotClipboardFormatId::PNG
:
2022 case SotClipboardFormatId::NETSCAPE_BOOKMARK
:
2023 case SotClipboardFormatId::SIMPLE_FILE
:
2024 case SotClipboardFormatId::FILEGRPDESCRIPTOR
:
2025 case SotClipboardFormatId::UNIFORMRESOURCELOCATOR
:
2026 bRet
= SwTransferable::PasteGrf( rData
, rSh
, nFormat
,
2027 SwPasteSdr::SetAttr
, pPt
,
2028 nActionFlags
, nDropAction
, bNeedToSelectBeforePaste
);
2031 OSL_FAIL( "unknown format" );
2036 case EXCHG_OUT_ACTION_INSERT_DRAWOBJ
:
2037 bRet
= SwTransferable::PasteSdrFormat( rData
, rSh
,
2038 SwPasteSdr::Insert
, pPt
,
2039 nActionFlags
, bNeedToSelectBeforePaste
);
2041 case EXCHG_OUT_ACTION_INSERT_SVXB
:
2042 case EXCHG_OUT_ACTION_INSERT_GDIMETAFILE
:
2043 case EXCHG_OUT_ACTION_INSERT_BITMAP
:
2044 case EXCHG_OUT_ACTION_INSERT_GRAPH
:
2045 bRet
= SwTransferable::PasteGrf( rData
, rSh
, nFormat
,
2046 SwPasteSdr::Insert
, pPt
,
2047 nActionFlags
, nDropAction
, bNeedToSelectBeforePaste
, nAnchorType
);
2050 case EXCHG_OUT_ACTION_REPLACE_DRAWOBJ
:
2051 bRet
= SwTransferable::PasteSdrFormat( rData
, rSh
,
2052 SwPasteSdr::Replace
, pPt
,
2053 nActionFlags
, bNeedToSelectBeforePaste
);
2056 case EXCHG_OUT_ACTION_REPLACE_SVXB
:
2057 case EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE
:
2058 case EXCHG_OUT_ACTION_REPLACE_BITMAP
:
2059 case EXCHG_OUT_ACTION_REPLACE_GRAPH
:
2060 bRet
= SwTransferable::PasteGrf( rData
, rSh
, nFormat
,
2061 SwPasteSdr::Replace
,pPt
,
2062 nActionFlags
, nDropAction
, bNeedToSelectBeforePaste
);
2065 case EXCHG_OUT_ACTION_INSERT_INTERACTIVE
:
2066 bRet
= SwTransferable::PasteAsHyperlink( rData
, rSh
, nFormat
);
2070 OSL_FAIL("unknown action" );
2074 if( !bPasteSelection
&& rSh
.IsFrameSelected() )
2076 rSh
.EnterSelFrameMode();
2077 //force ::SelectShell
2078 rSh
.GetView().StopShellTimer();
2082 if( bCallAutoCaption
)
2083 rSh
.GetView().AutoCaption( GRAPHIC_CAP
);
2088 SotExchangeDest
SwTransferable::GetSotDestination( const SwWrtShell
& rSh
)
2090 SotExchangeDest nRet
= SotExchangeDest::NONE
;
2092 ObjCntType eOType
= rSh
.GetObjCntTypeOfSelection();
2099 bIMap
= nullptr != rSh
.GetFlyFrameFormat()->GetURL().GetMap();
2101 rSh
.GetGrfNms( &aDummy
, nullptr );
2102 bLink
= !aDummy
.isEmpty();
2104 if( bLink
&& bIMap
)
2105 nRet
= SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP
;
2107 nRet
= SotExchangeDest::DOC_LNKD_GRAPHOBJ
;
2109 nRet
= SotExchangeDest::DOC_GRAPH_W_IMAP
;
2111 nRet
= SotExchangeDest::DOC_GRAPHOBJ
;
2116 if( dynamic_cast< const SwWebDocShell
*>( rSh
.GetView().GetDocShell() ) != nullptr )
2117 nRet
= SotExchangeDest::DOC_TEXTFRAME_WEB
;
2119 nRet
= SotExchangeDest::DOC_TEXTFRAME
;
2121 case OBJCNT_OLE
: nRet
= SotExchangeDest::DOC_OLEOBJ
; break;
2123 case OBJCNT_CONTROL
: /* no Action avail */
2124 case OBJCNT_SIMPLE
: nRet
= SotExchangeDest::DOC_DRAWOBJ
; break;
2125 case OBJCNT_URLBUTTON
: nRet
= SotExchangeDest::DOC_URLBUTTON
; break;
2126 case OBJCNT_GROUPOBJ
: nRet
= SotExchangeDest::DOC_GROUPOBJ
; break;
2128 // what do we do at multiple selections???
2131 if( dynamic_cast< const SwWebDocShell
*>( rSh
.GetView().GetDocShell() ) != nullptr )
2132 nRet
= SotExchangeDest::SWDOC_FREE_AREA_WEB
;
2134 nRet
= SotExchangeDest::SWDOC_FREE_AREA
;
2143 bool CanSkipInvalidateNumRules(const SwPosition
& rInsertPosition
)
2145 SwTextNode
* pTextNode
= rInsertPosition
.GetNode().GetTextNode();
2151 const SwNodeNum
* pNum
= pTextNode
->GetNum();
2154 SwNumRule
* pNumRule
= pNum
->GetNumRule();
2157 const SvxNumberType rType
= pNumRule
->Get(pTextNode
->GetActualListLevel());
2158 if (rType
.GetNumberingType() == SVX_NUM_CHAR_SPECIAL
)
2160 // Bullet list, skip invalidation.
2165 // Numbered list, invalidate.
2169 // Not a list, skip invalidation.
2174 bool SwTransferable::PasteFileContent( const TransferableDataHelper
& rData
,
2175 SwWrtShell
& rSh
, SotClipboardFormatId nFormat
, bool bMsg
, bool bIgnoreComments
)
2179 MSE40HTMLClipFormatObj aMSE40ClpObj
;
2181 std::unique_ptr
<SvStream
> xStrm
;
2182 SvStream
* pStream
= nullptr;
2183 Reader
* pRead
= nullptr;
2185 bool bSkipInvalidateNumRules
= false;
2188 case SotClipboardFormatId::STRING
:
2192 const SwPosition
& rInsertPosition
= *rSh
.GetCursor()->Start();
2193 if (CanSkipInvalidateNumRules(rInsertPosition
))
2195 // Insertion point is not a numbering and we paste plain text: then no need to
2196 // invalidate all numberings.
2197 bSkipInvalidateNumRules
= true;
2200 if( rData
.GetString( nFormat
, sData
) )
2202 pStream
= new SvMemoryStream( const_cast<sal_Unicode
*>(sData
.getStr()),
2203 sData
.getLength() * sizeof( sal_Unicode
),
2205 #ifdef OSL_BIGENDIAN
2206 pStream
->SetEndian( SvStreamEndian::BIG
);
2208 pStream
->SetEndian( SvStreamEndian::LITTLE
);
2211 SwAsciiOptions aAOpt
;
2212 aAOpt
.SetCharSet( RTL_TEXTENCODING_UCS2
);
2213 pRead
->GetReaderOpt().SetASCIIOpts( aAOpt
);
2217 [[fallthrough
]]; // because then test if we get a stream
2220 if( (xStrm
= rData
.GetSotStorageStream( nFormat
)) )
2222 if( ( SotClipboardFormatId::HTML_SIMPLE
== nFormat
) ||
2223 ( SotClipboardFormatId::HTML_NO_COMMENT
== nFormat
) )
2225 pStream
= aMSE40ClpObj
.IsValid( *xStrm
);
2227 pRead
->SetReadUTF8( true );
2230 ( nFormat
== SotClipboardFormatId::HTML_NO_COMMENT
);
2231 pRead
->SetIgnoreHTMLComments( bNoComments
);
2235 pStream
= xStrm
.get();
2236 if( SotClipboardFormatId::RTF
== nFormat
|| SotClipboardFormatId::RICHTEXT
== nFormat
)
2237 pRead
= SwReaderWriter::GetRtfReader();
2241 pRead
->SetReadUTF8( true );
2249 if( pStream
&& pRead
)
2251 Link
<LinkParamNone
*,void> aOldLink( rSh
.GetChgLnk() );
2252 rSh
.SetChgLnk( Link
<LinkParamNone
*,void>() );
2254 const SwPosition
& rInsPos
= *rSh
.GetCursor()->Start();
2255 SwReader
aReader(*pStream
, OUString(), OUString(), *rSh
.GetCursor());
2256 rSh
.SaveTableBoxContent( &rInsPos
);
2258 if (bIgnoreComments
)
2259 pRead
->SetIgnoreHTMLComments(true);
2260 if (bSkipInvalidateNumRules
)
2262 aReader
.SetSkipInvalidateNumRules(bSkipInvalidateNumRules
);
2265 if( aReader
.Read( *pRead
).IsError() )
2266 pResId
= STR_ERROR_CLPBRD_READ
;
2269 pResId
= TranslateId();
2273 rSh
.SetChgLnk( aOldLink
);
2278 pResId
= STR_CLPBRD_FORMAT_ERROR
;
2280 // Exist a SvMemoryStream? (data in the OUString and xStrm is empty)
2281 if( pStream
&& !xStrm
)
2286 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
2287 VclMessageType::Info
, VclButtonsType::Ok
,
2294 bool SwTransferable::PasteOLE( const TransferableDataHelper
& rData
, SwWrtShell
& rSh
,
2295 SotClipboardFormatId nFormat
, SotExchangeActionFlags nActionFlags
, bool bMsg
)
2298 TransferableObjectDescriptor aObjDesc
;
2299 uno::Reference
< io::XInputStream
> xStrm
;
2300 uno::Reference
< embed::XStorage
> xStore
;
2301 Reader
* pRead
= nullptr;
2303 // Get the preferred format
2304 SotClipboardFormatId nId
;
2305 if( rData
.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ
) )
2306 nId
= SotClipboardFormatId::EMBEDDED_OBJ
;
2307 else if( rData
.HasFormat( SotClipboardFormatId::EMBED_SOURCE
) &&
2308 rData
.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
))
2309 nId
= SotClipboardFormatId::EMBED_SOURCE
;
2311 nId
= SotClipboardFormatId::NONE
;
2313 if (nId
!= SotClipboardFormatId::NONE
)
2315 SwDocShell
* pDocSh
= rSh
.GetDoc()->GetDocShell();
2316 xStrm
= rData
.GetInputStream(nId
, SfxObjectShell::CreateShellID(pDocSh
));
2321 // if there is an embedded object, first try if it's a writer object
2322 // this will be inserted into the document by using a Reader
2325 xStore
= comphelper::OStorageHelper::GetStorageFromInputStream( xStrm
);
2326 switch( SotStorage::GetFormatID( xStore
) )
2328 case SotClipboardFormatId::STARWRITER_60
:
2329 case SotClipboardFormatId::STARWRITERWEB_60
:
2330 case SotClipboardFormatId::STARWRITERGLOB_60
:
2331 case SotClipboardFormatId::STARWRITER_8
:
2332 case SotClipboardFormatId::STARWRITERWEB_8
:
2333 case SotClipboardFormatId::STARWRITERGLOB_8
:
2342 catch (const uno::Exception
&)
2349 catch (const uno::Exception
&)
2351 // it wasn't a storage, but maybe it's a useful stream
2357 SwPaM
&rPAM
= *rSh
.GetCursor();
2358 SwReader
aReader(xStore
, OUString(), rPAM
);
2359 aReader
.SetInPaste(true);
2360 if( ! aReader
.Read( *pRead
).IsError() )
2364 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
2365 VclMessageType::Info
, VclButtonsType::Ok
,
2366 SwResId(STR_ERROR_CLPBRD_READ
)));
2372 // temporary storage until the object is inserted
2373 uno::Reference
< embed::XStorage
> xTmpStor
;
2374 uno::Reference
< embed::XEmbeddedObject
> xObj
;
2376 comphelper::EmbeddedObjectContainer aCnt
;
2380 if ( !rData
.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR
, aObjDesc
) )
2382 OSL_ENSURE( !xStrm
.is(), "An object without descriptor in clipboard!");
2387 if( rData
.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR_OLE
) && rData
.GetTransferableObjectDescriptor( nFormat
, aObjDesc
) )
2389 xStrm
= rData
.GetInputStream(SotClipboardFormatId::EMBED_SOURCE_OLE
, OUString());
2391 xStrm
= rData
.GetInputStream(SotClipboardFormatId::EMBEDDED_OBJ_OLE
, OUString());
2395 // This is MSOLE object that should be created by direct using of system clipboard
2398 xTmpStor
= ::comphelper::OStorageHelper::GetTemporaryStorage();
2399 uno::Reference
< embed::XEmbedObjectClipboardCreator
> xClipboardCreator
=
2400 embed::MSOLEObjectSystemCreator::create( ::comphelper::getProcessComponentContext() );
2402 embed::InsertedObjectInfo aInfo
= xClipboardCreator
->createInstanceInitFromClipboard(
2405 uno::Sequence
< beans::PropertyValue
>() );
2407 // TODO/LATER: in future InsertedObjectInfo will be used to get container related information
2408 // for example whether the object should be an iconified one
2409 xObj
= aInfo
.Object
;
2411 catch (const uno::Exception
&)
2416 else if (rData
.HasFormat(SotClipboardFormatId::SIMPLE_FILE
))
2419 if (rData
.GetString(nFormat
, sFile
) && !sFile
.isEmpty())
2421 // Copied from sd::View::DropInsertFileHdl
2422 uno::Sequence
< beans::PropertyValue
> aMedium
{ comphelper::makePropertyValue(
2423 u
"URL"_ustr
, sFile
) };
2424 SwDocShell
* pDocSh
= rSh
.GetDoc()->GetDocShell();
2425 xObj
= pDocSh
->GetEmbeddedObjectContainer().InsertEmbeddedObject(aMedium
, aName
);
2430 if ( xStrm
.is() && !xObj
.is() )
2431 xObj
= aCnt
.InsertEmbeddedObject( xStrm
, aName
);
2435 svt::EmbeddedObjectRef
xObjRef( xObj
, aObjDesc
.mnViewAspect
);
2437 // try to get the replacement image from the clipboard
2439 SotClipboardFormatId nGrFormat
= SotClipboardFormatId::NONE
;
2441 // limit the size of the preview metafile to 100000 actions
2442 GDIMetaFile aMetafile
;
2443 if (rData
.GetGDIMetaFile(SotClipboardFormatId::GDIMETAFILE
, aMetafile
, 100000))
2445 nGrFormat
= SotClipboardFormatId::GDIMETAFILE
;
2446 aGraphic
= aMetafile
;
2449 // insert replacement image ( if there is one ) into the object helper
2450 if ( nGrFormat
!= SotClipboardFormatId::NONE
)
2452 DataFlavor aDataFlavor
;
2453 SotExchange::GetFormatDataFlavor( nGrFormat
, aDataFlavor
);
2454 xObjRef
.SetGraphic( aGraphic
, aDataFlavor
.MimeType
);
2456 else if ( aObjDesc
.mnViewAspect
== embed::Aspects::MSOLE_ICON
)
2458 // it is important to have an icon, let an empty graphic be used
2459 // if no other graphic is provided
2460 // TODO/LATER: in future a default bitmap could be used
2461 MapMode
aMapMode( MapUnit::Map100thMM
);
2462 aGraphic
.SetPrefSize( Size( 2500, 2500 ) );
2463 aGraphic
.SetPrefMapMode( aMapMode
);
2464 xObjRef
.SetGraphic( aGraphic
, OUString() );
2467 //set size. This is a hack because of handing over, size should be
2468 //passed to the InsertOle!!!!!!!!!!
2470 if ( aObjDesc
.mnViewAspect
== embed::Aspects::MSOLE_ICON
)
2472 if( aObjDesc
.maSize
.Width() && aObjDesc
.maSize
.Height() )
2473 aSize
= aObjDesc
.maSize
;
2476 MapMode
aMapMode( MapUnit::Map100thMM
);
2477 aSize
= xObjRef
.GetSize( &aMapMode
);
2480 else if( aObjDesc
.maSize
.Width() && aObjDesc
.maSize
.Height() )
2482 aSize
= aObjDesc
.maSize
; //always 100TH_MM
2483 MapUnit aUnit
= VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj
->getMapUnit( aObjDesc
.mnViewAspect
) );
2484 aSize
= OutputDevice::LogicToLogic(aSize
, MapMode(MapUnit::Map100thMM
), MapMode(aUnit
));
2488 aSz
= xObj
->getVisualAreaSize( aObjDesc
.mnViewAspect
);
2490 catch (const embed::NoVisualAreaSizeException
&)
2492 // in this case the provided size is used
2495 if ( aSz
.Width
!= aSize
.Width() || aSz
.Height
!= aSize
.Height() )
2497 aSz
.Width
= aSize
.Width();
2498 aSz
.Height
= aSize
.Height();
2499 xObj
->setVisualAreaSize( aObjDesc
.mnViewAspect
, aSz
);
2504 // the descriptor contains the wrong object size
2505 // the following call will let the MSOLE objects cache the size if it is possible
2506 // it should be done while the object is running
2509 xObj
->getVisualAreaSize( aObjDesc
.mnViewAspect
);
2511 catch (const uno::Exception
&)
2517 rSh
.InsertOleObject( xObjRef
);
2520 if( bRet
&& ( nActionFlags
& SotExchangeActionFlags::InsertTargetUrl
) )
2521 SwTransferable::PasteTargetURL( rData
, rSh
, SwPasteSdr::NONE
, nullptr, false );
2523 // let the object be unloaded if possible
2524 SwOLEObj::UnloadObject( xObj
, rSh
.GetDoc(), embed::Aspects::MSOLE_CONTENT
);
2530 bool SwTransferable::PasteTargetURL( const TransferableDataHelper
& rData
,
2531 SwWrtShell
& rSh
, SwPasteSdr nAction
,
2532 const Point
* pPt
, bool bInsertGRF
)
2536 if( ( rData
.HasFormat( SotClipboardFormatId::INET_IMAGE
) &&
2537 rData
.GetINetImage( SotClipboardFormatId::INET_IMAGE
, aINetImg
)) ||
2538 ( rData
.HasFormat( SotClipboardFormatId::NETSCAPE_IMAGE
) &&
2539 rData
.GetINetImage( SotClipboardFormatId::NETSCAPE_IMAGE
, aINetImg
)) )
2541 if( !aINetImg
.GetImageURL().isEmpty() && bInsertGRF
)
2543 OUString
sURL( aINetImg
.GetImageURL() );
2544 SwTransferable::CheckForURLOrLNKFile( rData
, sURL
);
2546 //!!! check at FileSystem - only then it makes sense to test graphics !!!
2548 GraphicFilter
&rFlt
= GraphicFilter::GetGraphicFilter();
2549 bRet
= ERRCODE_NONE
== GraphicFilter::LoadGraphic(sURL
, OUString(), aGraphic
, &rFlt
);
2553 //Check and Perform rotation if needed
2554 lclCheckAndPerformRotation(aGraphic
);
2558 case SwPasteSdr::Insert
:
2559 SwTransferable::SetSelInShell( rSh
, false, pPt
);
2560 rSh
.InsertGraphic(sURL
, OUString(), aGraphic
);
2563 case SwPasteSdr::Replace
:
2564 if( rSh
.IsObjSelected() )
2566 rSh
.ReplaceSdrObj( sURL
, &aGraphic
);
2567 Point
aPt( pPt
? *pPt
: rSh
.GetCursorDocPos() );
2568 SwTransferable::SetSelInShell( rSh
, true, &aPt
);
2571 rSh
.ReRead(sURL
, OUString(), &aGraphic
);
2574 case SwPasteSdr::SetAttr
:
2575 if( rSh
.IsObjSelected() )
2576 rSh
.Paste( aGraphic
, OUString() );
2577 else if( OBJCNT_GRF
== rSh
.GetObjCntTypeOfSelection() )
2578 rSh
.ReRead(sURL
, OUString(), &aGraphic
);
2581 SwTransferable::SetSelInShell( rSh
, false, pPt
);
2582 rSh
.InsertGraphic(sURL
, OUString(), aGraphic
);
2596 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( rSh
.GetAttrPool() );
2597 rSh
.GetFlyFrameAttr( aSet
);
2598 SwFormatURL
aURL( aSet
.Get( RES_URL
) );
2600 if( aURL
.GetURL() != aINetImg
.GetTargetURL() ||
2601 aURL
.GetTargetFrameName() != aINetImg
.GetTargetFrame() )
2603 aURL
.SetURL( aINetImg
.GetTargetURL(), false );
2604 aURL
.SetTargetFrameName( aINetImg
.GetTargetFrame() );
2606 rSh
.SetFlyFrameAttr( aSet
);
2612 void SwTransferable::SetSelInShell( SwWrtShell
& rSh
, bool bSelectFrame
,
2617 // select frames/objects
2618 if( pPt
&& !rSh
.GetView().GetViewFrame().GetDispatcher()->IsLocked() )
2620 rSh
.GetView().NoRotate();
2621 if( rSh
.SelectObj( *pPt
))
2624 rSh
.EnterSelFrameMode( pPt
);
2625 g_bFrameDrag
= true;
2631 if( rSh
.IsFrameSelected() || rSh
.IsObjSelected() )
2633 rSh
.UnSelectFrame();
2634 rSh
.LeaveSelFrameMode();
2635 rSh
.GetView().GetEditWin().StopInsFrame();
2636 g_bFrameDrag
= false;
2638 else if( rSh
.GetView().GetDrawFuncPtr() )
2639 rSh
.GetView().GetEditWin().StopInsFrame();
2643 rSh
.SwCursorShell::SetCursor( *pPt
, true );
2647 bool SwTransferable::PasteDDE( const TransferableDataHelper
& rData
,
2648 SwWrtShell
& rWrtShell
, bool bReReadGrf
,
2651 // data from Clipboardformat
2652 OUString aApp
, aTopic
, aItem
;
2654 if (!rData
.ReadDDELink(aApp
, aTopic
, aItem
, o3tl::temporary(OUString())))
2657 } // report useful error!!
2660 sfx2::MakeLnkName( aCmd
, &aApp
, aTopic
, aItem
);
2662 // do we want to read in a graphic now?
2663 SotClipboardFormatId nFormat
;
2664 if( !rData
.HasFormat( SotClipboardFormatId::RTF
) &&
2665 !rData
.HasFormat( SotClipboardFormatId::RICHTEXT
) &&
2666 !rData
.HasFormat( SotClipboardFormatId::HTML
) &&
2667 !rData
.HasFormat( SotClipboardFormatId::STRING
) &&
2668 (rData
.HasFormat( nFormat
= SotClipboardFormatId::GDIMETAFILE
) ||
2669 rData
.HasFormat( nFormat
= SotClipboardFormatId::BITMAP
)) )
2672 bool bRet
= rData
.GetGraphic( nFormat
, aGrf
);
2675 OUString
sLnkTyp(u
"DDE"_ustr
);
2677 rWrtShell
.ReRead( aCmd
, sLnkTyp
, &aGrf
);
2679 rWrtShell
.InsertGraphic( aCmd
, sLnkTyp
, aGrf
);
2684 SwFieldType
* pTyp
= nullptr;
2688 bool bDoublePaste
= false;
2689 const size_t nSize
= rWrtShell
.GetFieldTypeCount();
2690 const ::utl::TransliterationWrapper
& rColl
= ::GetAppCmpStrIgnore();
2693 aName
= aApp
+ OUString::number( i
);
2694 for( j
= INIT_FLDTYPES
; j
< nSize
; j
++ )
2696 pTyp
= rWrtShell
.GetFieldType( j
);
2697 if( SwFieldIds::Dde
== pTyp
->Which() )
2699 if( rColl
.isEqual( static_cast<SwDDEFieldType
*>(pTyp
)->GetCmd(), aCmd
) &&
2700 SfxLinkUpdateMode::ALWAYS
== static_cast<SwDDEFieldType
*>(pTyp
)->GetType() )
2702 aName
= pTyp
->GetName();
2703 bDoublePaste
= true;
2706 else if( rColl
.isEqual( aName
, pTyp
->GetName() ) )
2714 while( !bDoublePaste
);
2718 SwDDEFieldType
aType( aName
, aCmd
, SfxLinkUpdateMode::ALWAYS
);
2719 pTyp
= rWrtShell
.InsertFieldType( aType
);
2722 SwDDEFieldType
* pDDETyp
= static_cast<SwDDEFieldType
*>(pTyp
);
2725 if( rData
.GetString( SotClipboardFormatId::STRING
, aExpand
))
2727 do { // middle checked loop
2729 const sal_Int32 nNewlines
{comphelper::string::getTokenCount(aExpand
, '\n')};
2730 // When data comes from a spreadsheet, we add a DDE-table
2731 if( !aExpand
.isEmpty() &&
2732 ( rData
.HasFormat( SotClipboardFormatId::SYLK
) ||
2733 rData
.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS
) ) )
2735 sal_Int32 nRows
= nNewlines
? nNewlines
-1 : 0;
2736 if (!aExpand
.endsWith("\n"))
2737 ++nRows
; // last row has no newline, e.g. one single cell
2738 const sal_Int32 nCols
= comphelper::string::getTokenCount(o3tl::getToken(aExpand
, 0, '\n'), '\t');
2740 // don't try to insert tables that are too large for writer
2741 if (nRows
> SAL_MAX_UINT16
|| nCols
> SAL_MAX_UINT16
)
2745 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
2746 VclMessageType::Info
, VclButtonsType::Ok
,
2747 SwResId(STR_TABLE_TOO_LARGE
)));
2754 // at least one column & row must be there
2755 if( !nRows
|| !nCols
)
2759 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
2760 VclMessageType::Info
, VclButtonsType::Ok
,
2761 SwResId(STR_NO_TABLE
)));
2768 rWrtShell
.InsertDDETable(
2769 SwInsertTableOptions( SwInsertTableFlags::SplitLayout
, 1 ), // TODO MULTIHEADER
2770 pDDETyp
, nRows
, nCols
);
2772 else if( nNewlines
> 1 )
2774 // multiple paragraphs -> insert a protected section
2775 if( rWrtShell
.HasSelection() )
2776 rWrtShell
.DelRight();
2778 SwSectionData
aSect( SectionType::DdeLink
, aName
);
2779 aSect
.SetLinkFileName( aCmd
);
2780 aSect
.SetProtectFlag(true);
2781 rWrtShell
.InsertSection( aSect
);
2783 pDDETyp
= nullptr; // remove FieldTypes again
2788 SwDDEField
aSwDDEField( pDDETyp
);
2789 rWrtShell
.InsertField2( aSwDDEField
);
2795 pDDETyp
= nullptr; // remove FieldTypes again
2797 if( !pDDETyp
&& !bDoublePaste
)
2799 // remove FieldType again - error occurred!
2800 for( j
= nSize
; j
>= INIT_FLDTYPES
; --j
)
2801 if( pTyp
== rWrtShell
.GetFieldType( j
) )
2803 rWrtShell
.RemoveFieldType( j
);
2811 bool SwTransferable::PasteSdrFormat( const TransferableDataHelper
& rData
,
2812 SwWrtShell
& rSh
, SwPasteSdr nAction
,
2813 const Point
* pPt
, SotExchangeActionFlags nActionFlags
, bool bNeedToSelectBeforePaste
)
2816 if( std::unique_ptr
<SvStream
> xStrm
= rData
.GetSotStorageStream( SotClipboardFormatId::DRAWING
))
2818 xStrm
->SetVersion( SOFFICE_FILEFORMAT_50
);
2820 if(bNeedToSelectBeforePaste
&& pPt
)
2822 // if this is an internal drag, need to set the target right (select it), else
2823 // still the source will be selected
2824 SwTransferable::SetSelInShell( rSh
, true, pPt
);
2827 rSh
.Paste( *xStrm
, nAction
, pPt
);
2830 if( bRet
&& ( nActionFlags
& SotExchangeActionFlags::InsertTargetUrl
))
2831 SwTransferable::PasteTargetURL( rData
, rSh
, SwPasteSdr::NONE
, nullptr, false );
2836 bool SwTransferable::PasteGrf( const TransferableDataHelper
& rData
, SwWrtShell
& rSh
,
2837 SotClipboardFormatId nFormat
, SwPasteSdr nAction
, const Point
* pPt
,
2838 SotExchangeActionFlags nActionFlags
, sal_Int8 nDropAction
, bool bNeedToSelectBeforePaste
, RndStdIds nAnchorType
)
2844 bool bCheckForGrf
= false, bCheckForImageMap
= false;
2848 case SotClipboardFormatId::BITMAP
:
2849 case SotClipboardFormatId::PNG
:
2850 case SotClipboardFormatId::GDIMETAFILE
:
2851 bRet
= rData
.GetGraphic( nFormat
, aGraphic
);
2854 case SotClipboardFormatId::SVXB
:
2856 if (std::unique_ptr
<SvStream
> xStm
= rData
.GetSotStorageStream(SotClipboardFormatId::SVXB
))
2858 TypeSerializer
aSerializer(*xStm
);
2859 aSerializer
.readGraphic(aGraphic
);
2860 bRet
= (GraphicType::NONE
!= aGraphic
.GetType() && GraphicType::Default
!= aGraphic
.GetType());
2866 case SotClipboardFormatId::NETSCAPE_BOOKMARK
:
2867 case SotClipboardFormatId::FILEGRPDESCRIPTOR
:
2868 case SotClipboardFormatId::UNIFORMRESOURCELOCATOR
:
2869 bRet
= rData
.GetINetBookmark( nFormat
, aBkmk
);
2872 if( SwPasteSdr::SetAttr
== nAction
)
2873 nFormat
= SotClipboardFormatId::NETSCAPE_BOOKMARK
;
2875 bCheckForGrf
= true;
2879 case SotClipboardFormatId::SIMPLE_FILE
:
2882 bRet
= rData
.GetString( nFormat
, sText
);
2886 SwTransferable::CheckForURLOrLNKFile( rData
, sText
, &sDesc
);
2888 sText
= URIHelper::SmartRel2Abs(INetURLObject(), sText
, Link
<OUString
*, bool>(),
2892 // Now that the path could be modified after SwTransferable::CheckForURLOrLNKFile,
2893 // where it could have been converted to URL, and made sure it's actually converted
2894 // to URL in URIHelper::SmartRel2Abs, we can finally convert file: URL back to
2895 // system path to make sure we don't use short path.
2896 // It looks not optimal, when we could apply GetLongPathNameW right to the original
2897 // pasted filename. But I don't know if (1) all arriving strings are system paths;
2898 // and (2) if SwTransferable::CheckForURLOrLNKFile could result in a different short
2899 // path, so taking a safe route.
2900 if (sText
.startsWithIgnoreAsciiCase("file:"))
2902 // tdf#124500: Convert short path to long path which should be used in links
2904 osl::FileBase::getSystemPathFromFileURL(sText
, sSysPath
);
2905 std::unique_ptr
<sal_Unicode
[]> aBuf(new sal_Unicode
[32767]);
2906 DWORD nCopied
= GetLongPathNameW(o3tl::toW(sSysPath
.getStr()),
2907 o3tl::toW(aBuf
.get()), 32767);
2908 if (nCopied
&& nCopied
< 32767)
2909 sText
= URIHelper::SmartRel2Abs(INetURLObject(), OUString(aBuf
.get()),
2910 Link
<OUString
*, bool>(), false);
2914 aBkmk
= INetBookmark(sText
, sDesc
);
2915 bCheckForGrf
= true;
2916 bCheckForImageMap
= SwPasteSdr::Replace
== nAction
;
2922 bRet
= rData
.GetGraphic( nFormat
, aGraphic
);
2928 //!!! check at FileSystem - only then it makes sense to test the graphics !!!
2929 GraphicFilter
&rFlt
= GraphicFilter::GetGraphicFilter();
2930 bRet
= ERRCODE_NONE
== GraphicFilter::LoadGraphic(aBkmk
.GetURL(), OUString(),
2933 if( !bRet
&& SwPasteSdr::SetAttr
== nAction
&&
2934 SotClipboardFormatId::SIMPLE_FILE
== nFormat
&&
2935 // only at frame selection
2936 rSh
.IsFrameSelected() )
2938 // then set as hyperlink after the graphic
2939 nFormat
= SotClipboardFormatId::NETSCAPE_BOOKMARK
;
2944 if(pPt
&& bNeedToSelectBeforePaste
)
2946 // when using internal D&Ds, still the source object is selected and
2947 // this is necessary to get the correct source data which is also
2948 // dependent from selection. After receiving the drag data it is
2949 // now time to select the correct target object
2950 SwTransferable::SetSelInShell( rSh
, true, pPt
);
2955 //Check and Perform rotation if needed
2956 lclCheckAndPerformRotation(aGraphic
);
2959 if( dynamic_cast< const SwWebDocShell
*>( rSh
.GetView().GetDocShell() ) != nullptr
2960 // #i123922# if link action is noted, also take URL
2961 || DND_ACTION_LINK
== nDropAction
)
2963 sURL
= aBkmk
.GetURL();
2968 case SwPasteSdr::Insert
:
2970 SwTransferable::SetSelInShell( rSh
, false, pPt
);
2971 rSh
.InsertGraphic(sURL
, OUString(), aGraphic
, nullptr, nAnchorType
);
2975 case SwPasteSdr::Replace
:
2977 if( rSh
.IsObjSelected() )
2979 // #i123922# for D&D on draw objects, do for now the same for
2980 // SwPasteSdr::Replace (D&D) as for SwPasteSdr::SetAttr (D&D and
2981 // CTRL+SHIFT). The code below replaces the draw object with
2982 // a writer graphic; maybe this is an option later again if wanted
2983 rSh
.Paste( aGraphic
, sURL
);
2985 // rSh.ReplaceSdrObj(sURL, OUString(), &aGraphic);
2986 // Point aPt( pPt ? *pPt : rSh.GetCursorDocPos() );
2987 // SwTransferable::SetSelInShell( rSh, true, &aPt );
2991 // set graphic at writer graphic without link
2992 rSh
.ReRead(sURL
, OUString(), &aGraphic
);
2998 case SwPasteSdr::SetAttr
:
3000 if( SotClipboardFormatId::NETSCAPE_BOOKMARK
== nFormat
)
3002 if( rSh
.IsFrameSelected() )
3004 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( rSh
.GetAttrPool() );
3005 rSh
.GetFlyFrameAttr( aSet
);
3006 SwFormatURL
aURL( aSet
.Get( RES_URL
) );
3007 aURL
.SetURL( aBkmk
.GetURL(), false );
3009 rSh
.SetFlyFrameAttr( aSet
);
3012 else if( rSh
.IsObjSelected() )
3014 // set as attribute at DrawObject
3015 rSh
.Paste( aGraphic
, sURL
);
3017 else if( OBJCNT_GRF
== rSh
.GetObjCntTypeOfSelection() )
3019 // set as linked graphic at writer graphic frame
3020 rSh
.ReRead(sURL
, OUString(), &aGraphic
);
3024 SwTransferable::SetSelInShell( rSh
, false, pPt
);
3025 rSh
.InsertGraphic(aBkmk
.GetURL(), OUString(), aGraphic
);
3041 ( SotExchangeActionFlags::InsertImageMap
| SotExchangeActionFlags::ReplaceImageMap
) )
3042 SwTransferable::PasteImageMap( rData
, rSh
);
3044 if( nActionFlags
& SotExchangeActionFlags::InsertTargetUrl
)
3045 SwTransferable::PasteTargetURL( rData
, rSh
, SwPasteSdr::NONE
, nullptr, false );
3047 else if( bCheckForImageMap
)
3049 // or should the file be an ImageMap-File?
3051 SfxMedium
aMed( INetURLObject(aBkmk
.GetURL()).GetFull(),
3052 StreamMode::STD_READ
);
3053 SvStream
* pStream
= aMed
.GetInStream();
3054 if( pStream
!= nullptr &&
3055 !pStream
->GetError() &&
3056 // mba: no BaseURL for clipboard functionality
3057 aMap
.Read( *pStream
, IMapFormat::Detect
) == IMAP_ERR_OK
&&
3058 aMap
.GetIMapObjectCount() )
3060 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( rSh
.GetAttrPool() );
3061 rSh
.GetFlyFrameAttr( aSet
);
3062 SwFormatURL
aURL( aSet
.Get( RES_URL
) );
3063 aURL
.SetMap( &aMap
);
3065 rSh
.SetFlyFrameAttr( aSet
);
3073 bool SwTransferable::PasteImageMap( const TransferableDataHelper
& rData
,
3077 if( rData
.HasFormat( SotClipboardFormatId::SVIM
))
3079 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( rSh
.GetAttrPool() );
3080 rSh
.GetFlyFrameAttr( aSet
);
3081 SwFormatURL
aURL( aSet
.Get( RES_URL
) );
3082 const ImageMap
* pOld
= aURL
.GetMap();
3084 // set or replace, that is the question
3086 if( rData
.GetImageMap( SotClipboardFormatId::SVIM
, aImageMap
) &&
3087 ( !pOld
|| aImageMap
!= *pOld
))
3089 aURL
.SetMap( &aImageMap
);
3091 rSh
.SetFlyFrameAttr( aSet
);
3098 bool SwTransferable::PasteAsHyperlink( const TransferableDataHelper
& rData
,
3099 SwWrtShell
& rSh
, SotClipboardFormatId nFormat
)
3103 if( rData
.GetString( nFormat
, sFile
) && !sFile
.isEmpty() )
3106 SwTransferable::CheckForURLOrLNKFile( rData
, sFile
, &sDesc
);
3108 // first, make the URL absolute
3110 aURL
.SetSmartProtocol( INetProtocol::File
);
3111 aURL
.SetSmartURL( sFile
);
3112 sFile
= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
3114 switch( rSh
.GetObjCntTypeOfSelection() )
3120 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( rSh
.GetAttrPool() );
3121 rSh
.GetFlyFrameAttr( aSet
);
3122 SwFormatURL
aURL2( aSet
.Get( RES_URL
) );
3123 aURL2
.SetURL( sFile
, false );
3124 if( aURL2
.GetName().isEmpty() )
3125 aURL2
.SetName( sFile
);
3127 rSh
.SetFlyFrameAttr( aSet
);
3133 rSh
.InsertURL( SwFormatINetFormat( sFile
, OUString() ),
3134 sDesc
.isEmpty() ? sFile
: sDesc
);
3142 bool SwTransferable::PasteFileName( const TransferableDataHelper
& rData
,
3143 SwWrtShell
& rSh
, SotClipboardFormatId nFormat
,
3144 SwPasteSdr nAction
, const Point
* pPt
,
3145 SotExchangeActionFlags nActionFlags
,
3146 bool * graphicInserted
)
3148 bool bRet
= SwTransferable::PasteGrf( rData
, rSh
, nFormat
, nAction
,
3149 pPt
, nActionFlags
, 0, false);
3150 if (graphicInserted
!= nullptr) {
3151 *graphicInserted
= bRet
;
3155 OUString sFile
, sDesc
;
3156 if( rData
.GetString( nFormat
, sFile
) && !sFile
.isEmpty() )
3158 #if HAVE_FEATURE_AVMEDIA
3159 INetURLObject aMediaURL
;
3161 aMediaURL
.SetSmartURL( sFile
);
3162 const OUString
aMediaURLStr( aMediaURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
3164 if( ::avmedia::MediaWindow::isMediaURL( aMediaURLStr
, u
""_ustr
/*TODO?*/ ) )
3166 const SfxStringItem
aMediaURLItem( SID_INSERT_AVMEDIA
, aMediaURLStr
);
3167 rSh
.GetView().GetViewFrame().GetDispatcher()->ExecuteList(
3168 SID_INSERT_AVMEDIA
, SfxCallMode::SYNCHRON
,
3169 { &aMediaURLItem
});
3178 bool bIsURLFile
= SwTransferable::CheckForURLOrLNKFile( rData
, sFile
, &sDesc
);
3180 //Own FileFormat? --> insert, not for StarWriter/Web
3181 OUString sFileURL
= URIHelper::SmartRel2Abs(INetURLObject(), sFile
, Link
<OUString
*, bool>(), false );
3182 std::shared_ptr
<const SfxFilter
> pFlt
= SwPasteSdr::SetAttr
== nAction
3183 ? nullptr : SwIoSystem::GetFileFilter(sFileURL
);
3184 if( pFlt
&& dynamic_cast< const SwWebDocShell
*>( rSh
.GetView().GetDocShell() ) == nullptr )
3186 // and then pull up the insert-region-dialog
3187 SwSectionData
aSect(
3188 SectionType::FileLink
,
3189 rSh
.GetDoc()->GetUniqueSectionName() );
3190 aSect
.SetLinkFileName( sFileURL
);
3191 aSect
.SetProtectFlag( true );
3193 rSh
.StartInsertRegionDialog( aSect
); // starts dialog asynchronously
3196 else if (SwPasteSdr::Insert
== nAction
&& rData
.HasFormat(SotClipboardFormatId::SIMPLE_FILE
))
3198 // insert file as OLE
3199 PasteOLE(rData
, rSh
, nFormat
, nActionFlags
, nullptr == pPt
);
3201 else if( SwPasteSdr::SetAttr
== nAction
||
3202 ( bIsURLFile
&& SwPasteSdr::Insert
== nAction
))
3204 //we can insert foreign files as links after all
3206 // first, make the URL absolute
3208 aURL
.SetSmartProtocol( INetProtocol::File
);
3209 aURL
.SetSmartURL( sFile
);
3210 sFile
= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
3212 switch( rSh
.GetObjCntTypeOfSelection() )
3218 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( rSh
.GetAttrPool() );
3219 rSh
.GetFlyFrameAttr( aSet
);
3220 SwFormatURL
aURL2( aSet
.Get( RES_URL
) );
3221 aURL2
.SetURL( sFile
, false );
3222 if( aURL2
.GetName().isEmpty() )
3223 aURL2
.SetName( sFile
);
3225 rSh
.SetFlyFrameAttr( aSet
);
3231 rSh
.InsertURL( SwFormatINetFormat( sFile
, OUString() ),
3232 sDesc
.isEmpty() ? sFile
: sDesc
);
3243 bool SwTransferable::PasteDBData( const TransferableDataHelper
& rData
,
3244 SwWrtShell
& rSh
, SotClipboardFormatId nFormat
, bool bLink
,
3245 const Point
* pDragPt
, bool bMsg
)
3249 if( rData
.GetString( nFormat
, sText
) && !sText
.isEmpty() )
3251 sal_uInt16 nWh
= SotClipboardFormatId::SBA_CTRLDATAEXCHANGE
== nFormat
3253 : SotClipboardFormatId::SBA_DATAEXCHANGE
== nFormat
3255 ? FN_QRY_MERGE_FIELD
3259 : FN_QRY_INSERT_FIELD
);
3260 const DataFlavorExVector
& rVector
= rData
.GetDataFlavorExVector();
3261 bool bHaveColumnDescriptor
= OColumnTransferable::canExtractColumnDescriptor(rVector
, ColumnTransferFormatFlags::COLUMN_DESCRIPTOR
| ColumnTransferFormatFlags::CONTROL_EXCHANGE
);
3262 if ( SotClipboardFormatId::XFORMS
== nFormat
)
3265 FmFormView
* pFmView
= dynamic_cast<FmFormView
*>( rSh
.GetDrawView() );
3266 if (pFmView
&& pDragPt
)
3268 OXFormsDescriptor aDesc
= OXFormsTransferable::extractDescriptor(rData
);
3269 rtl::Reference
<SdrObject
> pObj
= pFmView
->CreateXFormsControl(aDesc
);
3272 rSh
.SwFEShell::InsertDrawObj( *pObj
, *pDragPt
);
3278 std::unique_ptr
<SfxUnoAnyItem
> pConnectionItem
;
3279 std::unique_ptr
<SfxUnoAnyItem
> pCursorItem
;
3280 std::unique_ptr
<SfxUnoAnyItem
> pColumnItem
;
3281 std::unique_ptr
<SfxUnoAnyItem
> pSourceItem
;
3282 std::unique_ptr
<SfxUnoAnyItem
> pCommandItem
;
3283 std::unique_ptr
<SfxUnoAnyItem
> pCommandTypeItem
;
3284 std::unique_ptr
<SfxUnoAnyItem
> pColumnNameItem
;
3285 std::unique_ptr
<SfxUnoAnyItem
> pSelectionItem
;
3287 bool bDataAvailable
= true;
3288 ODataAccessDescriptor aDesc
;
3289 if(bHaveColumnDescriptor
)
3290 aDesc
= OColumnTransferable::extractColumnDescriptor(rData
);
3291 else if(ODataAccessObjectTransferable::canExtractObjectDescriptor(rVector
) )
3292 aDesc
= ODataAccessObjectTransferable::extractObjectDescriptor(rData
);
3294 bDataAvailable
= false;
3296 if ( bDataAvailable
)
3298 pConnectionItem
.reset(new SfxUnoAnyItem(FN_DB_CONNECTION_ANY
, aDesc
[DataAccessDescriptorProperty::Connection
]));
3299 pColumnItem
.reset(new SfxUnoAnyItem(FN_DB_COLUMN_ANY
, aDesc
[DataAccessDescriptorProperty::ColumnObject
]));
3300 pSourceItem
.reset(new SfxUnoAnyItem(FN_DB_DATA_SOURCE_ANY
, Any(aDesc
.getDataSource())));
3301 pCommandItem
.reset(new SfxUnoAnyItem(FN_DB_DATA_COMMAND_ANY
, aDesc
[DataAccessDescriptorProperty::Command
]));
3302 pCommandTypeItem
.reset(new SfxUnoAnyItem(FN_DB_DATA_COMMAND_TYPE_ANY
, aDesc
[DataAccessDescriptorProperty::CommandType
]));
3303 pColumnNameItem
.reset(new SfxUnoAnyItem(FN_DB_DATA_COLUMN_NAME_ANY
, aDesc
[DataAccessDescriptorProperty::ColumnName
]));
3304 pSelectionItem
.reset(new SfxUnoAnyItem(FN_DB_DATA_SELECTION_ANY
, aDesc
[DataAccessDescriptorProperty::Selection
]));
3305 pCursorItem
.reset(new SfxUnoAnyItem(FN_DB_DATA_CURSOR_ANY
, aDesc
[DataAccessDescriptorProperty::Cursor
]));
3308 SwView
& rView
= rSh
.GetView();
3309 //force ::SelectShell
3310 rView
.StopShellTimer();
3312 SfxStringItem
aDataDesc( nWh
, sText
);
3313 rView
.GetViewFrame().GetDispatcher()->ExecuteList(
3314 nWh
, SfxCallMode::ASYNCHRON
,
3315 { &aDataDesc
, pConnectionItem
.get(), pColumnItem
.get(),
3316 pSourceItem
.get(), pCommandItem
.get(), pCommandTypeItem
.get(),
3317 pColumnNameItem
.get(), pSelectionItem
.get(),
3318 pCursorItem
.get() });
3323 FmFormView
* pFmView
= dynamic_cast<FmFormView
*>( rSh
.GetDrawView() );
3324 if (pFmView
&& bHaveColumnDescriptor
&& pDragPt
)
3326 rtl::Reference
<SdrObject
> pObj
= pFmView
->CreateFieldControl( OColumnTransferable::extractColumnDescriptor(rData
) );
3328 rSh
.SwFEShell::InsertDrawObj( *pObj
, *pDragPt
);
3335 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
3336 VclMessageType::Info
, VclButtonsType::Ok
,
3337 SwResId(STR_CLPBRD_FORMAT_ERROR
)));
3343 bool SwTransferable::PasteFileList( const TransferableDataHelper
& rData
,
3344 SwWrtShell
& rSh
, bool bLink
,
3345 const Point
* pPt
, bool bMsg
)
3349 if( rData
.GetFileList( SotClipboardFormatId::FILE_LIST
, aFileList
) &&
3352 SwPasteSdr nAct
= bLink
? SwPasteSdr::SetAttr
: SwPasteSdr::Insert
;
3354 // iterate over the filelist
3355 for( sal_uLong n
= 0, nEnd
= aFileList
.Count(); n
< nEnd
; ++n
)
3357 rtl::Reference
<TransferDataContainer
> pHlp
= new TransferDataContainer
;
3358 pHlp
->CopyString( SotClipboardFormatId::SIMPLE_FILE
, aFileList
.GetFile( n
));
3359 TransferableDataHelper
aData( pHlp
);
3361 if( SwTransferable::PasteFileName( aData
, rSh
, SotClipboardFormatId::SIMPLE_FILE
, nAct
,
3362 pPt
, SotExchangeActionFlags::NONE
, nullptr ))
3366 sFlyNm
= rSh
.GetFlyName();
3367 SwTransferable::SetSelInShell( rSh
, false, pPt
);
3372 if( !sFlyNm
.isEmpty() )
3373 rSh
.GotoFly( sFlyNm
);
3377 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
3378 VclMessageType::Info
, VclButtonsType::Ok
,
3379 SwResId(STR_CLPBRD_FORMAT_ERROR
)));
3385 bool SwTransferable::CheckForURLOrLNKFile( const TransferableDataHelper
& rData
,
3386 OUString
& rFileName
, OUString
* pTitle
)
3388 bool bIsURLFile
= false;
3390 if( rData
.GetINetBookmark( SotClipboardFormatId::SOLK
, aBkmk
) )
3392 rFileName
= aBkmk
.GetURL();
3394 *pTitle
= aBkmk
.GetDescription();
3399 if( rFileName
.getLength()>4 && rFileName
.endsWithIgnoreAsciiCase(".url") )
3401 OSL_ENSURE( false, "how do we read today .URL - Files?" );
3407 bool SwTransferable::IsPasteSpecial( const SwWrtShell
& rWrtShell
,
3408 const TransferableDataHelper
& rData
)
3410 // we can paste-special if there's an entry in the paste-special-format list
3411 SvxClipboardFormatItem
aClipboardFormatItem(TypedWhichId
<SvxClipboardFormatItem
>(0));
3412 FillClipFormatItem( rWrtShell
, rData
, aClipboardFormatItem
);
3413 return aClipboardFormatItem
.Count() > 0;
3416 bool SwTransferable::IsPasteOwnFormat( const TransferableDataHelper
& rData
)
3418 return ( GetSwTransferable( rData
) != nullptr );
3421 bool SwTransferable::PasteFormat( SwWrtShell
& rSh
,
3422 const TransferableDataHelper
& rData
,
3423 SotClipboardFormatId nFormat
)
3425 SwWait
aWait( *rSh
.GetView().GetDocShell(), false );
3428 SotClipboardFormatId nPrivateFormat
= SotClipboardFormatId::PRIVATE
;
3429 SwTransferable
*pClipboard
= GetSwTransferable( rData
);
3431 ((TransferBufferType::Document
|TransferBufferType::Graphic
|TransferBufferType::Ole
) & pClipboard
->m_eBufferType
))
3432 nPrivateFormat
= SotClipboardFormatId::EMBED_SOURCE
;
3434 if( pClipboard
&& nPrivateFormat
== nFormat
)
3435 bRet
= pClipboard
->PrivatePaste( rSh
);
3436 else if( rData
.HasFormat( nFormat
) )
3438 uno::Reference
<XTransferable
> xTransferable( rData
.GetXTransferable() );
3439 sal_uInt8 nEventAction
;
3440 SotExchangeDest nDestination
= SwTransferable::GetSotDestination( rSh
);
3441 sal_uInt16 nSourceOptions
=
3442 (( SotExchangeDest::DOC_TEXTFRAME
== nDestination
||
3443 SotExchangeDest::SWDOC_FREE_AREA
== nDestination
||
3444 SotExchangeDest::DOC_TEXTFRAME_WEB
== nDestination
||
3445 SotExchangeDest::SWDOC_FREE_AREA_WEB
== nDestination
)
3446 ? EXCHG_IN_ACTION_COPY
3447 : EXCHG_IN_ACTION_MOVE
);
3448 SotExchangeActionFlags nActionFlags
;
3449 sal_uInt8 nAction
= SotExchange::GetExchangeAction(
3450 rData
.GetDataFlavorExVector(),
3452 nSourceOptions
, /* ?? */
3453 EXCHG_IN_ACTION_DEFAULT
, /* ?? */
3454 nFormat
, nEventAction
, nFormat
,
3455 lcl_getTransferPointer ( xTransferable
),
3458 if( EXCHG_INOUT_ACTION_NONE
!= nAction
)
3459 bRet
= SwTransferable::PasteData( rData
, rSh
, nAction
, nActionFlags
, nFormat
,
3460 nDestination
, true, false );
3465 bool SwTransferable::TestAllowedFormat( const TransferableDataHelper
& rData
,
3466 SotClipboardFormatId nFormat
, SotExchangeDest nDestination
)
3468 sal_uInt8 nAction
= EXCHG_INOUT_ACTION_NONE
;
3469 if( rData
.HasFormat( nFormat
)) {
3470 uno::Reference
<XTransferable
> xTransferable( rData
.GetXTransferable() );
3471 sal_uInt8 nEventAction
;
3472 nAction
= SotExchange::GetExchangeAction(
3473 rData
.GetDataFlavorExVector(),
3474 nDestination
, EXCHG_IN_ACTION_COPY
,
3475 EXCHG_IN_ACTION_COPY
, nFormat
,
3476 nEventAction
, nFormat
,
3477 lcl_getTransferPointer ( xTransferable
) );
3479 return EXCHG_INOUT_ACTION_NONE
!= nAction
;
3483 * the list of formats which will be offered to the user in the 'Paste
3484 * Special...' dialog and the paste button menu
3486 static SotClipboardFormatId aPasteSpecialIds
[] =
3488 SotClipboardFormatId::HTML
,
3489 SotClipboardFormatId::HTML_SIMPLE
,
3490 SotClipboardFormatId::HTML_NO_COMMENT
,
3491 SotClipboardFormatId::RTF
,
3492 SotClipboardFormatId::RICHTEXT
,
3493 SotClipboardFormatId::STRING
,
3494 SotClipboardFormatId::SONLK
,
3495 SotClipboardFormatId::NETSCAPE_BOOKMARK
,
3496 SotClipboardFormatId::DRAWING
,
3497 SotClipboardFormatId::SVXB
,
3498 SotClipboardFormatId::GDIMETAFILE
,
3499 SotClipboardFormatId::BITMAP
,
3500 SotClipboardFormatId::SVIM
,
3501 SotClipboardFormatId::FILEGRPDESCRIPTOR
,
3502 SotClipboardFormatId::NONE
3505 bool SwTransferable::PasteUnformatted( SwWrtShell
& rSh
, TransferableDataHelper
& rData
)
3507 // Plain text == unformatted
3508 return SwTransferable::PasteFormat( rSh
, rData
, SotClipboardFormatId::STRING
);
3511 void SwTransferable::PrePasteSpecial( const SwWrtShell
& rSh
, const TransferableDataHelper
& rData
, const VclPtr
<SfxAbstractPasteDialog
>& pDlg
)
3513 DataFlavorExVector
aFormats( rData
.GetDataFlavorExVector() );
3514 TransferableObjectDescriptor aDesc
;
3516 SotExchangeDest nDest
= SwTransferable::GetSotDestination( rSh
);
3518 SwTransferable
*pClipboard
= GetSwTransferable( rData
);
3521 aDesc
= pClipboard
->m_aObjDesc
;
3523 if( pClipboard
->m_eBufferType
& TransferBufferType::Document
)
3524 pResId
= STR_PRIVATETEXT
;
3525 else if( pClipboard
->m_eBufferType
& TransferBufferType::Graphic
)
3526 pResId
= STR_PRIVATEGRAPHIC
;
3527 else if( pClipboard
->m_eBufferType
== TransferBufferType::Ole
)
3528 pResId
= STR_PRIVATEOLE
;
3532 if (STR_PRIVATEOLE
== pResId
|| STR_PRIVATEGRAPHIC
== pResId
)
3534 // add SotClipboardFormatId::EMBED_SOURCE to the formats. This
3535 // format display then the private format name.
3536 DataFlavorEx aFlavorEx
;
3537 aFlavorEx
.mnSotId
= SotClipboardFormatId::EMBED_SOURCE
;
3538 aFormats
.insert( aFormats
.begin(), aFlavorEx
);
3540 pDlg
->SetObjName( pClipboard
->m_aObjDesc
.maClassName
,
3542 pDlg
->Insert( SotClipboardFormatId::EMBED_SOURCE
, OUString() );
3547 if( rData
.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
) )
3549 (void)rData
.GetTransferableObjectDescriptor(
3550 SotClipboardFormatId::OBJECTDESCRIPTOR
, aDesc
);
3553 if( SwTransferable::TestAllowedFormat( rData
, SotClipboardFormatId::EMBED_SOURCE
, nDest
))
3554 pDlg
->Insert( SotClipboardFormatId::EMBED_SOURCE
, OUString() );
3555 if( SwTransferable::TestAllowedFormat( rData
, SotClipboardFormatId::LINK_SOURCE
, nDest
))
3556 pDlg
->Insert( SotClipboardFormatId::LINK_SOURCE
, OUString() );
3559 if( SwTransferable::TestAllowedFormat( rData
, SotClipboardFormatId::LINK
, nDest
))
3560 pDlg
->Insert( SotClipboardFormatId::LINK
, SwResId(STR_DDEFORMAT
) );
3562 for( SotClipboardFormatId
* pIds
= aPasteSpecialIds
; *pIds
!= SotClipboardFormatId::NONE
; ++pIds
)
3563 if( SwTransferable::TestAllowedFormat( rData
, *pIds
, nDest
))
3564 pDlg
->Insert( *pIds
, OUString() );
3567 void SwTransferable::FillClipFormatItem( const SwWrtShell
& rSh
,
3568 const TransferableDataHelper
& rData
,
3569 SvxClipboardFormatItem
& rToFill
)
3571 SotExchangeDest nDest
= SwTransferable::GetSotDestination( rSh
);
3573 SwTransferable
*pClipboard
= GetSwTransferable( rData
);
3577 if( pClipboard
->m_eBufferType
& TransferBufferType::Document
)
3578 pResId
= STR_PRIVATETEXT
;
3579 else if( pClipboard
->m_eBufferType
& TransferBufferType::Graphic
)
3580 pResId
= STR_PRIVATEGRAPHIC
;
3581 else if( pClipboard
->m_eBufferType
== TransferBufferType::Ole
)
3582 pResId
= STR_PRIVATEOLE
;
3585 rToFill
.AddClipbrdFormat(SotClipboardFormatId::EMBED_SOURCE
,
3590 TransferableObjectDescriptor aDesc
;
3591 if (rData
.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR
))
3593 (void)rData
.GetTransferableObjectDescriptor(
3594 SotClipboardFormatId::OBJECTDESCRIPTOR
, aDesc
);
3597 if( SwTransferable::TestAllowedFormat( rData
, SotClipboardFormatId::EMBED_SOURCE
, nDest
))
3598 rToFill
.AddClipbrdFormat( SotClipboardFormatId::EMBED_SOURCE
,
3600 if( SwTransferable::TestAllowedFormat( rData
, SotClipboardFormatId::LINK_SOURCE
, nDest
))
3601 rToFill
.AddClipbrdFormat( SotClipboardFormatId::LINK_SOURCE
);
3603 SotClipboardFormatId nFormat
;
3604 if ( rData
.HasFormat(nFormat
= SotClipboardFormatId::EMBED_SOURCE_OLE
) || rData
.HasFormat(nFormat
= SotClipboardFormatId::EMBEDDED_OBJ_OLE
) )
3606 OUString sName
,sSource
;
3607 if ( SvPasteObjectHelper::GetEmbeddedName(rData
,sName
,sSource
,nFormat
) )
3608 rToFill
.AddClipbrdFormat( nFormat
, sName
);
3612 if( SwTransferable::TestAllowedFormat( rData
, SotClipboardFormatId::LINK
, nDest
))
3613 rToFill
.AddClipbrdFormat( SotClipboardFormatId::LINK
, SwResId(STR_DDEFORMAT
) );
3615 for( SotClipboardFormatId
* pIds
= aPasteSpecialIds
; *pIds
!= SotClipboardFormatId::NONE
; ++pIds
)
3616 if( SwTransferable::TestAllowedFormat( rData
, *pIds
, nDest
))
3617 rToFill
.AddClipbrdFormat(*pIds
, OUString());
3620 void SwTransferable::SetDataForDragAndDrop( const Point
& rSttPos
)
3625 const SelectionType nSelection
= m_pWrtShell
->GetSelectionType();
3626 if( SelectionType::Graphic
== nSelection
)
3628 AddFormat( SotClipboardFormatId::SVXB
);
3629 const Graphic
* pGrf
= m_pWrtShell
->GetGraphic();
3630 if ( pGrf
&& pGrf
->IsSupportedGraphic() )
3632 AddFormat( SotClipboardFormatId::GDIMETAFILE
);
3633 AddFormat( SotClipboardFormatId::PNG
);
3634 AddFormat( SotClipboardFormatId::BITMAP
);
3636 m_eBufferType
= TransferBufferType::Graphic
;
3637 m_pWrtShell
->GetGrfNms( &sGrfNm
, nullptr );
3639 else if( SelectionType::Ole
== nSelection
)
3641 AddFormat( SotClipboardFormatId::EMBED_SOURCE
);
3642 PrepareOLE( m_aObjDesc
);
3643 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
);
3644 AddFormat( SotClipboardFormatId::GDIMETAFILE
);
3645 m_eBufferType
= TransferBufferType::Ole
;
3647 //Is there anything to provide anyway?
3648 else if ( m_pWrtShell
->IsSelection() || m_pWrtShell
->IsFrameSelected() ||
3649 m_pWrtShell
->IsObjSelected() )
3651 if( m_pWrtShell
->IsObjSelected() )
3652 m_eBufferType
= TransferBufferType::Drawing
;
3655 m_eBufferType
= TransferBufferType::Document
;
3656 if( SwWrtShell::NO_WORD
!=
3657 m_pWrtShell
->IntelligentCut( nSelection
, false ))
3658 m_eBufferType
= TransferBufferType::DocumentWord
| m_eBufferType
;
3661 if( nSelection
& SelectionType::TableCell
)
3662 m_eBufferType
= TransferBufferType::Table
| m_eBufferType
;
3664 AddFormat( SotClipboardFormatId::EMBED_SOURCE
);
3666 //put RTF ahead of the OLE's Metafile for less loss
3667 if( !m_pWrtShell
->IsObjSelected() )
3669 AddFormat( SotClipboardFormatId::RTF
);
3670 AddFormat( SotClipboardFormatId::RICHTEXT
);
3671 AddFormat( SotClipboardFormatId::HTML
);
3673 if( m_pWrtShell
->IsSelection() )
3674 AddFormat( SotClipboardFormatId::STRING
);
3676 if( nSelection
& ( SelectionType::DrawObject
| SelectionType::DbForm
))
3678 AddFormat( SotClipboardFormatId::DRAWING
);
3679 if ( nSelection
& SelectionType::DrawObject
)
3681 AddFormat( SotClipboardFormatId::GDIMETAFILE
);
3682 AddFormat( SotClipboardFormatId::PNG
);
3683 AddFormat( SotClipboardFormatId::BITMAP
);
3685 m_eBufferType
= TransferBufferType::Graphic
| m_eBufferType
;
3687 // is it a URL-Button ?
3690 if( m_pWrtShell
->GetURLFromButton( sURL
, sDesc
) )
3692 AddFormat( SotClipboardFormatId::STRING
);
3693 AddFormat( SotClipboardFormatId::SOLK
);
3694 AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK
);
3695 AddFormat( SotClipboardFormatId::FILECONTENT
);
3696 AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR
);
3697 AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR
);
3698 m_eBufferType
= TransferBufferType::InetField
| m_eBufferType
;
3702 //ObjectDescriptor was already filled from the old DocShell.
3703 //Now adjust it. Thus in GetData the first query can still
3704 //be answered with delayed rendering.
3705 m_aObjDesc
.maDragStartPos
= rSttPos
;
3706 m_aObjDesc
.maSize
= constOleSize100mm
;
3708 PrepareOLE( m_aObjDesc
);
3709 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
);
3711 else if( nSelection
& SelectionType::Text
&& !m_pWrtShell
->HasMark() )
3713 // is only one field - selected?
3714 SwContentAtPos
aContentAtPos( IsAttrAtPos::InetAttr
);
3715 Point
aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY());
3717 if( m_pWrtShell
->GetContentAtPos( aPos
, aContentAtPos
) )
3719 AddFormat( SotClipboardFormatId::STRING
);
3720 AddFormat( SotClipboardFormatId::SOLK
);
3721 AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK
);
3722 AddFormat( SotClipboardFormatId::FILECONTENT
);
3723 AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR
);
3724 AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR
);
3725 m_eBufferType
= TransferBufferType::InetField
;
3729 if( !m_pWrtShell
->IsFrameSelected() )
3732 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( m_pWrtShell
->GetAttrPool() );
3733 m_pWrtShell
->GetFlyFrameAttr( aSet
);
3734 const SwFormatURL
& rURL
= aSet
.Get( RES_URL
);
3737 m_pImageMap
.reset( new ImageMap( *rURL
.GetMap() ) );
3738 AddFormat( SotClipboardFormatId::SVIM
);
3740 else if( !rURL
.GetURL().isEmpty() )
3742 m_pTargetURL
.reset(new INetImage( sGrfNm
, rURL
.GetURL(),
3743 rURL
.GetTargetFrameName() ));
3744 AddFormat( SotClipboardFormatId::INET_IMAGE
);
3748 void SwTransferable::StartDrag( vcl::Window
* pWin
, const Point
& rPos
)
3752 m_bOldIdle
= m_pWrtShell
->GetViewOptions()->IsIdle();
3755 m_pWrtShell
->GetViewOptions()->SetIdle( false );
3757 if( m_pWrtShell
->IsSelFrameMode() )
3758 m_pWrtShell
->ShowCursor();
3760 SwModule::get()->m_pDragDrop
= this;
3762 SetDataForDragAndDrop( rPos
);
3764 sal_Int8 nDragOptions
= DND_ACTION_COPYMOVE
| DND_ACTION_LINK
;
3765 SwDocShell
* pDShell
= m_pWrtShell
->GetView().GetDocShell();
3766 if( ( pDShell
&& pDShell
->IsReadOnly() ) || m_pWrtShell
->HasReadonlySel() )
3767 nDragOptions
&= ~DND_ACTION_MOVE
;
3769 TransferableHelper::StartDrag( pWin
, nDragOptions
);
3772 void SwTransferable::DragFinished( sal_Int8 nAction
)
3774 //And the last finishing work so that all statuses are right
3775 if( DND_ACTION_MOVE
== nAction
)
3779 //It was dropped outside of Writer. We still have to
3782 m_pWrtShell
->StartAllAction();
3783 m_pWrtShell
->StartUndo( SwUndoId::UI_DRAG_AND_MOVE
);
3784 if ( m_pWrtShell
->IsTableMode() )
3785 m_pWrtShell
->DeleteTableSel();
3788 if ( !(m_pWrtShell
->IsSelFrameMode() || m_pWrtShell
->IsObjSelected()) )
3789 //SmartCut, take one of the blanks along
3790 m_pWrtShell
->IntelligentCut( m_pWrtShell
->GetSelectionType() );
3791 m_pWrtShell
->DelRight();
3793 m_pWrtShell
->EndUndo( SwUndoId::UI_DRAG_AND_MOVE
);
3794 m_pWrtShell
->EndAllAction();
3798 const SelectionType nSelection
= m_pWrtShell
->GetSelectionType();
3799 if( ( SelectionType::Frame
| SelectionType::Graphic
|
3800 SelectionType::Ole
| SelectionType::DrawObject
) & nSelection
)
3802 m_pWrtShell
->EnterSelFrameMode();
3806 m_pWrtShell
->GetView().GetEditWin().DragFinished();
3808 if( m_pWrtShell
->IsSelFrameMode() )
3809 m_pWrtShell
->HideCursor();
3811 m_pWrtShell
->ShowCursor();
3813 m_pWrtShell
->GetViewOptions()->SetIdle( m_bOldIdle
);
3819 bool lcl_checkClassification(SwDoc
* pSourceDoc
, SwDoc
* pDestinationDoc
)
3821 if (!pSourceDoc
|| !pDestinationDoc
)
3824 SwDocShell
* pSourceShell
= pSourceDoc
->GetDocShell();
3825 SwDocShell
* pDestinationShell
= pDestinationDoc
->GetDocShell();
3826 if (!pSourceShell
|| !pDestinationShell
)
3829 SfxClassificationCheckPasteResult eResult
= SfxClassificationHelper::CheckPaste(pSourceShell
->getDocProperties(), pDestinationShell
->getDocProperties());
3830 return SfxClassificationHelper::ShowPasteInfo(eResult
);
3835 bool SwTransferable::PrivatePaste(SwWrtShell
& rShell
, SwPasteContext
* pContext
, PasteTableType ePasteTable
)
3837 // first, ask for the SelectionType, then action-bracketing !!!!
3838 // (otherwise it's not pasted into a TableSelection!!!)
3839 OSL_ENSURE( !rShell
.ActionPend(), "Paste must never have an ActionPend" );
3840 if ( !m_pClpDocFac
)
3841 return false; // the return value of the SwFEShell::Paste also is bool!
3843 const SelectionType nSelection
= rShell
.GetSelectionType();
3845 SwTrnsfrActionAndUndo
aAction( &rShell
);
3847 bool bKillPaMs
= false;
3849 //Delete selected content, not at table-selection and table in Clipboard, and don't delete hovering graphics.
3850 if( rShell
.HasSelection() && !( nSelection
& SelectionType::TableCell
) && !( nSelection
& SelectionType::DrawObject
))
3852 if (!(nSelection
& SelectionType::NumberList
))
3855 rShell
.SetRetainSelection( true );
3861 pContext
->remember();
3862 // when a Fly was selected, a valid cursor position has to be found now
3864 if( ( SelectionType::Frame
| SelectionType::Graphic
|
3865 SelectionType::Ole
| SelectionType::DrawObject
|
3866 SelectionType::DbForm
) & nSelection
)
3868 // position the cursor again
3869 Point
aPt( rShell
.GetCharRect().Pos() );
3870 rShell
.SwCursorShell::SetCursor( aPt
, true );
3872 if (!(nSelection
& SelectionType::NumberList
))
3874 rShell
.SetRetainSelection( false );
3877 if ( nSelection
& SelectionType::DrawObject
) //unselect hovering graphics
3879 rShell
.ResetSelect(nullptr,false);
3882 bool bInWrd
= false, bEndWrd
= false, bSttWrd
= false,
3883 bSmart(TransferBufferType::DocumentWord
& m_eBufferType
);
3886 // Why not for other Scripts? If TransferBufferType::DocumentWord is set, we have a word
3887 // in the buffer, word in this context means 'something with spaces at beginning
3888 // and end'. In this case we definitely want these spaces to be inserted here.
3889 bInWrd
= rShell
.IsInWord();
3890 bEndWrd
= rShell
.IsEndWrd();
3891 bSmart
= bInWrd
|| bEndWrd
;
3894 bSttWrd
= rShell
.IsStartWord();
3895 if (!bSttWrd
&& (bInWrd
|| bEndWrd
))
3896 rShell
.SwEditShell::Insert(' ');
3901 // m_pWrtShell is nullptr when the source document is closed already.
3902 if (!m_pWrtShell
|| lcl_checkClassification(m_pWrtShell
->GetDoc(), rShell
.GetDoc()))
3903 bRet
= rShell
.Paste(m_pClpDocFac
->GetDoc(), ePasteTable
== PasteTableType::PASTE_TABLE
);
3908 // If Smart Paste then insert blank
3909 if( bRet
&& bSmart
&& ((bInWrd
&& !bEndWrd
)|| bSttWrd
) )
3910 rShell
.SwEditShell::Insert(' ');
3915 bool SwTransferable::PrivateDrop( SwWrtShell
& rSh
, const Point
& rDragPt
,
3916 bool bMove
, bool bIsXSelection
)
3919 bool bInWrd
= false;
3920 bool bEndWrd
= false;
3921 bool bSttWrd
= false;
3922 bool bSttPara
= false;
3923 bool bTableSel
= false;
3924 bool bTableMove
= false;
3925 bool bFrameSel
= false;
3927 SwWrtShell
& rSrcSh
= *GetShell();
3929 rSh
.UnSetVisibleCursor();
3931 if( TransferBufferType::InetField
== m_eBufferType
)
3933 if( rSh
.GetFormatFromObj( rDragPt
) )
3936 if( (TransferBufferType::InetField
& m_eBufferType
) && m_oBookmark
)
3937 aTmp
= *m_oBookmark
;
3939 // select target graphic
3940 if( rSh
.SelectObj( rDragPt
) )
3943 rSh
.EnterSelFrameMode( &rDragPt
);
3944 g_bFrameDrag
= true;
3947 const SelectionType nSelection
= rSh
.GetSelectionType();
3949 // not yet consider Draw objects
3950 if( SelectionType::Graphic
& nSelection
)
3952 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( rSh
.GetAttrPool() );
3953 rSh
.GetFlyFrameAttr( aSet
);
3954 SwFormatURL
aURL( aSet
.Get( RES_URL
) );
3955 aURL
.SetURL( aTmp
.GetURL(), false );
3957 rSh
.SetFlyFrameAttr( aSet
);
3961 if( SelectionType::DrawObject
& nSelection
)
3963 rSh
.LeaveSelFrameMode();
3964 rSh
.UnSelectFrame();
3966 g_bFrameDrag
= false;
3971 if( &rSh
!= &rSrcSh
&& (SelectionType::Graphic
& rSh
.GetSelectionType()) &&
3972 TransferBufferType::Graphic
== m_eBufferType
)
3974 // ReRead the graphic
3977 rSrcSh
.GetGrfNms( &sGrfNm
, &sFltNm
);
3978 rSh
.ReRead( sGrfNm
, sFltNm
, rSrcSh
.GetGraphic() );
3982 //not in selections or selected frames
3983 if( rSh
.TestCurrPam( rDragPt
) ||
3984 ( rSh
.IsSelFrameMode() && rSh
.IsInsideSelectedObj( rDragPt
)) )
3987 if( rSrcSh
.IsTableMode() )
3990 const SelectionType nSelection
= rSrcSh
.GetSelectionType();
3991 // at enhanced table row/column selection or wholly selected tables,
3992 // paste rows above or columns before, and in the case of moving, remove the selection
3993 // (limit only to the single document case temporarily)
3994 if( rSrcSh
.GetDoc() == rSh
.GetDoc() &&
3995 ( (( SelectionType::TableRow
| SelectionType::TableCol
) & nSelection
) || rSrcSh
.HasWholeTabSelection() ) )
3997 bool bTableCol(SelectionType::TableCol
& nSelection
);
3999 ::sw::mark::MarkBase
* pMarkMoveFrom
= bMove
4003 IDocumentMarkAccess::MarkType::UNO_BOOKMARK
)
4006 // row count and direction of the table selection:
4007 // up to down, if the cursor is there in its last table row
4008 const SwSelBoxes
& rBoxes
= rSrcSh
.GetTableCursor()->GetSelectedBoxes();
4009 const SwTableNode
* pTableNd
= rSh
.IsCursorInTable();
4012 SAL_WARN("sw", "presumably this case can't arise in practice");
4015 const SwTableLines
& rLines
= pTableNd
->GetTable().GetTabLines();
4016 const SwStartNode
& rDelPos
= rBoxes
.back()
4017 ? *rBoxes
.front()->GetSttNd()
4018 : *pTableNd
->GetStartNode();
4020 // count selected rows or columns
4021 sal_Int32 nSelRowOrCols
= 0;
4022 if ( rBoxes
.back() )
4026 // selected column count is the count of the cells
4027 // in the first row of the selection
4028 auto nLine
= rLines
.GetPos( rBoxes
.front()->GetUpper() );
4029 for (auto pBox
: rBoxes
)
4031 // cell is in the next row
4032 if ( nLine
!= rLines
.GetPos( pBox
->GetUpper() ) )
4039 // selected row count is the difference of the row number of the
4040 // first and the last cell of the selection
4041 nSelRowOrCols
= rLines
.GetPos( rBoxes
.back()->GetUpper() ) -
4042 rLines
.GetPos( rBoxes
.front()->GetUpper() ) + 1;
4046 bool bSelUpToDown
= rBoxes
.back() && rBoxes
.back()->GetUpper() ==
4047 rSh
.GetCursor()->GetPointNode().GetTableBox()->GetUpper();
4049 SwUndoId eUndoId
= bMove
? SwUndoId::UI_DRAG_AND_MOVE
: SwUndoId::UI_DRAG_AND_COPY
;
4051 SwRewriter aRewriter
;
4053 aRewriter
.AddRule(UndoArg1
, rSrcSh
.GetSelDescr());
4055 if(rSrcSh
.GetDoc() != rSh
.GetDoc())
4056 rSrcSh
.StartUndo( eUndoId
, &aRewriter
);
4057 rSh
.StartUndo( eUndoId
, &aRewriter
);
4060 rSrcSh
.StartAction();
4062 SfxDispatcher
* pDispatch
= rSrcSh
.GetView().GetViewFrame().GetDispatcher();
4063 pDispatch
->Execute(SID_COPY
, SfxCallMode::SYNCHRON
);
4065 rSrcSh
.Push(); // save selection for later restoration
4067 rSh
.SwCursorShell::SetCursor(rDragPt
, false);
4069 bool bPasteIntoTable
= rSh
.GetCursor()->GetPointNode().GetTableBox() != nullptr;
4072 ::sw::mark::MarkBase
* pMark
= rSh
.SetBookmark(
4075 IDocumentMarkAccess::MarkType::UNO_BOOKMARK
);
4077 // paste rows above/columns before
4078 pDispatch
->Execute(bTableCol
? FN_TABLE_PASTE_COL_BEFORE
: FN_TABLE_PASTE_ROW_BEFORE
, SfxCallMode::SYNCHRON
);
4080 // go to the previously inserted table rows and set them to tracked insertion, if needed
4081 bool bNeedTrack
= !bTableCol
&& rSh
.getIDocumentRedlineAccess().IsRedlineOn();
4083 // restore cursor position
4084 if (bNeedTrack
&& pMark
!= nullptr)
4085 rSh
.GotoMark( pMark
);
4087 if ( !bNeedTrack
&& !bPasteIntoTable
)
4089 rSrcSh
.Pop(SwCursorShell::PopMode::DeleteCurrent
); // restore selection...
4091 // delete source rows/columns
4093 pDispatch
->Execute(bTableCol
4094 ? FN_TABLE_DELETE_COL
4095 : FN_TABLE_DELETE_ROW
, SfxCallMode::SYNCHRON
);
4099 const SwTableBox
* pBoxStt
= rSh
.GetCursor()->GetPointNode().GetTableBox();
4100 SwTableLine
* pLine
= pBoxStt
? const_cast<SwTableLine
*>( pBoxStt
->GetUpper()): nullptr;
4102 for (sal_Int32 nDeleted
= 0; bNeedTrack
&& nDeleted
< nSelRowOrCols
;)
4104 // move up text cursor (note: "true" is important for the layout level)
4105 if ( !rSh
.Up(false) )
4108 const SwTableBox
* pBox
= rSh
.GetCursor()->GetPointNode().GetTableBox();
4113 // Up() reaches a new row
4114 if ( pBox
->GetUpper() != pLine
)
4116 //rSh.SelTableRow();
4117 SvxPrintItem
aTracked(RES_PRINT
, false);
4118 rSh
.GetDoc()->SetRowNotTracked( *rSh
.GetCursor(), aTracked
);
4120 pLine
= const_cast<SwTableLine
*>(pBox
->GetUpper());
4124 rSrcSh
.Pop(SwCursorShell::PopMode::DeleteCurrent
); // restore selection...
4126 // delete source rows/columns
4129 // restore cursor position
4130 if (pMarkMoveFrom
!= nullptr)
4132 rSh
.GotoMark( pMarkMoveFrom
);
4133 rSh
.getIDocumentMarkAccess()->deleteMark( pMarkMoveFrom
);
4136 // tracked table row moving: set original rows as tracked deletion,
4137 // otherwise delete original rows/columns (tracking column deletion
4138 // and insertion is not supported yet)
4139 if ( !bTableCol
&& bNeedTrack
)
4143 for (sal_Int32 nDeleted
= 0; nDeleted
< nSelRowOrCols
;)
4145 const SwTableBox
* pBox
= rSh
.GetCursor()->GetPointNode().GetTableBox();
4150 if ( pBox
->GetUpper() != pLine
)
4152 pLine
= const_cast<SwTableLine
*>(pBox
->GetUpper());
4153 pDispatch
->Execute(FN_TABLE_DELETE_ROW
, SfxCallMode::SYNCHRON
);
4157 bool bMoved
= false;
4159 bMoved
= rSh
.Up(false);
4161 bMoved
= rSh
.Down(false);
4168 // set cursor in the first cell of the original selection
4169 rSh
.GetCursor()->DeleteMark();
4170 rSh
.GetCursor()->GetPoint()->Assign( rDelPos
.GetIndex() + 1);
4172 for (sal_Int32 nDeleted
= 0; nDeleted
< nSelRowOrCols
; ++nDeleted
)
4174 pDispatch
->Execute(bTableCol
4175 ? FN_TABLE_DELETE_COL
4176 : FN_TABLE_DELETE_ROW
, SfxCallMode::SYNCHRON
);
4182 // restore cursor position
4183 if (pMark
!= nullptr)
4185 rSh
.GotoMark( pMark
);
4186 rSh
.getIDocumentMarkAccess()->deleteMark( pMark
);
4189 rSh
.DestroyCursor();
4196 if ( bMove
&& rSrcSh
.HasWholeTabSelection() )
4199 else if( rSrcSh
.IsSelFrameMode() || rSrcSh
.IsObjSelected() )
4201 // don't move position-protected objects!
4202 if( bMove
&& rSrcSh
.IsSelObjProtected( FlyProtectFlags::Pos
) != FlyProtectFlags::NONE
)
4208 const SelectionType nSel
= rSrcSh
.GetSelectionType();
4210 SwUndoId eUndoId
= bMove
? SwUndoId::UI_DRAG_AND_MOVE
: SwUndoId::UI_DRAG_AND_COPY
;
4212 SwRewriter aRewriter
;
4214 aRewriter
.AddRule(UndoArg1
, rSrcSh
.GetSelDescr());
4216 if(rSrcSh
.GetDoc() != rSh
.GetDoc())
4217 rSrcSh
.StartUndo( eUndoId
, &aRewriter
);
4218 rSh
.StartUndo( eUndoId
, &aRewriter
);
4221 rSrcSh
.StartAction();
4223 if( &rSrcSh
!= &rSh
)
4226 rSh
.SwCursorShell::SetCursor( rDragPt
, true );
4227 cWord
= rSrcSh
.IntelligentCut( nSel
, false );
4229 else if( !bTableSel
&& !bFrameSel
)
4231 if( !rSh
.IsAddMode() )
4234 if ( rSh
.IsBlockMode() )
4236 // preserve order of cursors for block mode
4240 rSh
.SwCursorShell::CreateCursor();
4242 rSh
.SwCursorShell::SetCursor( rDragPt
, true, false );
4244 cWord
= rSh
.IntelligentCut( rSh
.GetSelectionType(), false );
4248 bInWrd
= rSh
.IsInWord();
4249 bEndWrd
= rSh
.IsEndWrd();
4250 bSttWrd
= !bEndWrd
&& rSh
.IsStartWord();
4251 bSttPara
= rSh
.IsSttPara();
4253 Point
aSttPt( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY() );
4255 // at first, select InetFields!
4256 if( TransferBufferType::InetField
== m_eBufferType
)
4258 if( &rSrcSh
== &rSh
)
4261 rSh
.SwCursorShell::SetCursor( aSttPt
, true );
4262 rSh
.SelectTextAttr( RES_TXTATR_INETFMT
);
4263 if( rSh
.TestCurrPam( rDragPt
) )
4265 // don't copy/move inside of yourself
4266 rSh
.DestroyCursor();
4276 rSrcSh
.SwCursorShell::SetCursor( aSttPt
, true );
4277 rSrcSh
.SelectTextAttr( RES_TXTATR_INETFMT
);
4280 // is there a URL attribute at the insert point? Then replace that,
4281 // so simply put up a selection?
4282 rSh
.DelINetAttrWithText();
4283 g_bDDINetAttr
= true;
4286 if ( rSrcSh
.IsSelFrameMode() )
4288 //Hack: fool the special treatment
4289 aSttPt
= rSrcSh
.GetObjRect().Pos();
4292 bool bRet
= rSrcSh
.SwFEShell::Copy(rSh
, aSttPt
, rDragPt
, bMove
,
4295 if( !bIsXSelection
)
4298 if ( bRet
&& bMove
&& !bFrameSel
)
4302 /* delete table contents not cells */
4303 rSrcSh
.Delete(false);
4307 //SmartCut, take one of the blanks along.
4308 rSh
.SwCursorShell::DestroyCursor();
4309 if ( cWord
== SwWrtShell::WORD_SPACE_BEFORE
)
4310 rSh
.ExtendSelection( false );
4311 else if ( cWord
== SwWrtShell::WORD_SPACE_AFTER
)
4312 rSh
.ExtendSelection();
4317 rSrcSh
.Pop(SwCursorShell::PopMode::DeleteCurrent
);
4319 /* after dragging a table selection inside one shell
4320 set cursor to the drop position. */
4321 if( &rSh
== &rSrcSh
&& ( bTableSel
|| rSh
.IsBlockMode() ) )
4323 rSrcSh
.CalcLayout();
4324 rSrcSh
.SwCursorShell::SetCursor(rDragPt
);
4325 rSrcSh
.GetCursor()->SetMark();
4329 if( bRet
&& !bTableSel
&& !bFrameSel
)
4331 if( (bInWrd
|| bEndWrd
) &&
4332 (cWord
== SwWrtShell::WORD_SPACE_AFTER
||
4333 cWord
== SwWrtShell::WORD_SPACE_BEFORE
) )
4335 if ( bSttWrd
|| (bInWrd
&& !bEndWrd
))
4336 rSh
.SwEditShell::Insert(' ', bIsXSelection
);
4337 if ( !bSttWrd
|| (bInWrd
&& !bSttPara
) )
4341 rSh
.SwEditShell::Insert(' ', bIsXSelection
);
4348 if( &rSrcSh
== &rSh
&& !rSh
.IsAddMode() )
4350 rSh
.SwCursorShell::DestroyCursor();
4356 rSh
.SwCursorShell::ClearMark();
4361 if( rSh
.IsAddMode() )
4362 rSh
.SwCursorShell::CreateCursor();
4365 // turn on selection mode
4371 else if ( bRet
&& bTableMove
)
4373 SfxDispatcher
* pDispatch
= rSrcSh
.GetView().GetViewFrame().GetDispatcher();
4374 pDispatch
->Execute(FN_TABLE_DELETE_TABLE
, SfxCallMode::SYNCHRON
);
4377 if( bRet
&& bMove
&& bFrameSel
)
4378 rSrcSh
.LeaveSelFrameMode();
4380 if( rSrcSh
.GetDoc() != rSh
.GetDoc() )
4384 // put the shell in the right state
4385 if( &rSrcSh
!= &rSh
&& ( rSh
.IsFrameSelected() || rSh
.IsObjSelected() ))
4386 rSh
.EnterSelFrameMode();
4393 // Interfaces for Selection
4394 void SwTransferable::CreateSelection( SwWrtShell
& rSh
,
4395 const SwFrameShell
* _pCreatorView
)
4397 rtl::Reference
<SwTransferable
> pNew
= new SwTransferable( rSh
);
4399 pNew
->m_pCreatorView
= _pCreatorView
;
4401 SwModule::get()->m_pXSelection
= pNew
.get();
4402 pNew
->CopyToPrimarySelection();
4405 void SwTransferable::ClearSelection( const SwWrtShell
& rSh
,
4406 const SwFrameShell
* _pCreatorView
)
4408 SwModule
* pMod
= SwModule::get();
4409 if( pMod
->m_pXSelection
&&
4410 ((!pMod
->m_pXSelection
->m_pWrtShell
) || (pMod
->m_pXSelection
->m_pWrtShell
== &rSh
)) &&
4411 (!_pCreatorView
|| (pMod
->m_pXSelection
->m_pCreatorView
== _pCreatorView
)) )
4413 TransferableHelper::ClearPrimarySelection();
4417 SwTransferable
* SwTransferable::GetSwTransferable( const TransferableDataHelper
& rData
)
4419 return dynamic_cast<SwTransferable
*>(rData
.GetTransferable().get());
4422 SwTransferDdeLink::SwTransferDdeLink( SwTransferable
& rTrans
, SwWrtShell
& rSh
)
4423 : m_rTransfer(rTrans
)
4424 , m_pDocShell(nullptr)
4426 , m_bDelBookmark(false)
4427 , m_bInDisconnect(false)
4429 // we only end up here with table- or text selection
4430 if( SelectionType::TableCell
& rSh
.GetSelectionType() )
4432 SwFrameFormat
* pFormat
= rSh
.GetTableFormat();
4434 m_sName
= pFormat
->GetName();
4438 // creating a temp. bookmark without undo
4439 bool bUndo
= rSh
.DoesUndo();
4440 rSh
.DoUndo( false );
4441 bool bIsModified
= rSh
.IsModified();
4443 ::sw::mark::MarkBase
* pMark
= rSh
.SetBookmark(
4446 IDocumentMarkAccess::MarkType::DDE_BOOKMARK
);
4449 m_sName
= pMark
->GetName();
4450 m_bDelBookmark
= true;
4452 rSh
.ResetModified();
4456 rSh
.DoUndo( bUndo
);
4459 if( m_sName
.isEmpty() ||
4460 nullptr == ( m_pDocShell
= rSh
.GetDoc()->GetDocShell() ))
4463 // then we create our "server" and connect to it
4464 m_xRefObj
= m_pDocShell
->DdeCreateLinkSource( m_sName
);
4465 if( m_xRefObj
.is() )
4467 m_xRefObj
->AddConnectAdvise( this );
4468 m_xRefObj
->AddDataAdvise( this,
4470 ADVISEMODE_NODATA
| ADVISEMODE_ONLYONCE
);
4471 m_nOldTimeOut
= m_xRefObj
->GetUpdateTimeout();
4472 m_xRefObj
->SetUpdateTimeout( 0 );
4476 SwTransferDdeLink::~SwTransferDdeLink()
4478 if( m_xRefObj
.is() )
4482 ::sfx2::SvBaseLink::UpdateResult
SwTransferDdeLink::DataChanged( const OUString
& ,
4485 // well, that's it with the link
4486 if( !m_bInDisconnect
)
4488 if( FindDocShell() && m_pDocShell
->GetView() )
4489 m_rTransfer
.RemoveDDELinkFormat( m_pDocShell
->GetView()->GetEditWin() );
4490 Disconnect( false );
4495 bool SwTransferDdeLink::WriteData( SvStream
& rStrm
)
4497 if( !m_xRefObj
.is() || !FindDocShell() )
4500 TransferableDataHelper::WriteDDELink(rStrm
, Application::GetAppName(),
4501 m_pDocShell
->GetTitle(SFX_TITLE_FULLNAME
), m_sName
);
4503 IDocumentMarkAccess
* const pMarkAccess
= m_pDocShell
->GetDoc()->getIDocumentMarkAccess();
4504 auto ppMark
= pMarkAccess
->findMark(m_sName
);
4505 if(ppMark
!= pMarkAccess
->getAllMarksEnd()
4506 && IDocumentMarkAccess::GetType(**ppMark
) != IDocumentMarkAccess::MarkType::BOOKMARK
)
4508 // the mark is still a DdeBookmark
4509 // we replace it with a Bookmark, so it will get saved etc.
4510 ::sw::mark::MarkBase
* const pMark
= *ppMark
;
4511 ::sfx2::SvLinkSource
* p
= m_xRefObj
.get();
4512 SwServerObject
& rServerObject
= dynamic_cast<SwServerObject
&>(*p
);
4514 // collecting state of old mark
4515 SwPaM
aPaM(pMark
->GetMarkStart());
4516 *aPaM
.GetPoint() = pMark
->GetMarkStart();
4517 if(pMark
->IsExpanded())
4520 *aPaM
.GetMark() = pMark
->GetMarkEnd();
4522 OUString sMarkName
= pMark
->GetName();
4525 rServerObject
.SetNoServer(); // this removes the connection between SwServerObject and mark
4526 // N.B. ppMark was not loaded from file and cannot have xml:id
4527 pMarkAccess
->deleteMark(ppMark
, false);
4529 // recreate as Bookmark
4530 ::sw::mark::MarkBase
* const pNewMark
= pMarkAccess
->makeMark(
4533 IDocumentMarkAccess::MarkType::BOOKMARK
,
4534 ::sw::mark::InsertMode::New
);
4535 rServerObject
.SetDdeBookmark(*pNewMark
);
4538 m_bDelBookmark
= false;
4542 void SwTransferDdeLink::Disconnect( bool bRemoveDataAdvise
)
4544 // don't accept DataChanged anymore, when already in Disconnect!
4545 // (DTOR from Bookmark sends a DataChanged!)
4546 bool bOldDisconnect
= m_bInDisconnect
;
4547 m_bInDisconnect
= true;
4549 // destroy the unused bookmark again (without Undo!)?
4550 if( m_bDelBookmark
&& m_xRefObj
.is() && FindDocShell() )
4552 SwDoc
* pDoc
= m_pDocShell
->GetDoc();
4553 ::sw::UndoGuard
const undoGuard(pDoc
->GetIDocumentUndoRedo());
4556 Link
<bool,void> aSavedOle2Link( pDoc
->GetOle2Link() );
4557 pDoc
->SetOle2Link( Link
<bool,void>() );
4559 bool bIsModified
= pDoc
->getIDocumentState().IsModified();
4561 IDocumentMarkAccess
* const pMarkAccess
= pDoc
->getIDocumentMarkAccess();
4562 pMarkAccess
->deleteMark(pMarkAccess
->findMark(m_sName
), false);
4565 pDoc
->getIDocumentState().ResetModified();
4567 pDoc
->SetOle2Link( aSavedOle2Link
);
4569 m_bDelBookmark
= false;
4572 if( m_xRefObj
.is() )
4574 m_xRefObj
->SetUpdateTimeout( m_nOldTimeOut
);
4575 m_xRefObj
->RemoveConnectAdvise( this );
4576 if( bRemoveDataAdvise
)
4577 // in a DataChanged the SelectionObject must NEVER be deleted
4578 // is already handled by the base class
4579 // (ADVISEMODE_ONLYONCE!!!!)
4580 // but always in normal Disconnect!
4581 m_xRefObj
->RemoveAllDataAdvise( this );
4584 m_bInDisconnect
= bOldDisconnect
;
4587 bool SwTransferDdeLink::FindDocShell()
4589 SfxObjectShell
* pTmpSh
= SfxObjectShell::GetFirst( checkSfxObjectShell
<SwDocShell
> );
4592 if( pTmpSh
== m_pDocShell
) // that's what we want to have
4594 if( m_pDocShell
->GetDoc() )
4596 break; // the Doc is not there anymore, so leave!
4598 pTmpSh
= SfxObjectShell::GetNext( *pTmpSh
, checkSfxObjectShell
<SwDocShell
> );
4601 m_pDocShell
= nullptr;
4605 void SwTransferDdeLink::Closed()
4607 if( !m_bInDisconnect
&& m_xRefObj
.is() )
4609 m_xRefObj
->RemoveAllDataAdvise( this );
4610 m_xRefObj
->RemoveConnectAdvise( this );
4615 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */