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 <unotools/ucbstreamhelper.hxx>
40 #include <sot/filelist.hxx>
41 #include <svx/svxdlg.hxx>
42 #include <toolkit/helper/vclunohelper.hxx>
43 #include <osl/endian.h>
44 #include <sfx2/linkmgr.hxx>
45 #include <tools/urlobj.hxx>
46 #include <vcl/weld.hxx>
47 #include <sfx2/dispatch.hxx>
48 #include <sfx2/viewfrm.hxx>
49 #include <svl/stritem.hxx>
50 #include <vcl/imap.hxx>
51 #include <sot/storage.hxx>
52 #include <vcl/graph.hxx>
53 #include <svl/urihelper.hxx>
54 #include <svx/svdmodel.hxx>
55 #include <svx/xmlexchg.hxx>
56 #include <svx/dbaexchange.hxx>
57 #include <svx/clipfmtitem.hxx>
58 #include <sfx2/mieclip.hxx>
59 #include <svl/urlbmk.hxx>
60 #include <vcl/inetimg.hxx>
61 #include <svx/fmview.hxx>
62 #include <sfx2/docfilt.hxx>
63 #include <vcl/imapobj.hxx>
64 #include <sfx2/docfile.hxx>
65 #include <unotools/transliterationwrapper.hxx>
66 #include <unotools/streamwrap.hxx>
67 #include <vcl/graphicfilter.hxx>
72 #include <o3tl/char16_t2wchar_t.hxx>
73 #include <osl/file.hxx>
76 #include <svx/unomodel.hxx>
78 #include <fmtinfmt.hxx>
79 #include <swdtflvr.hxx>
80 #include <shellio.hxx>
83 #include <IDocumentUndoRedo.hxx>
84 #include <IDocumentDrawModelAccess.hxx>
85 #include <IDocumentFieldsAccess.hxx>
86 #include <IDocumentRedlineAccess.hxx>
87 #include <IDocumentState.hxx>
89 #include <section.hxx>
93 #include <navicont.hxx>
96 #include <swmodule.hxx>
100 #include <fldbas.hxx>
101 #include <swundo.hxx>
104 #include <swwait.hxx>
105 #include <viewopt.hxx>
106 #include <SwCapObjType.hxx>
108 #include <strings.hrc>
109 #include <svx/svditer.hxx>
110 #include <editeng/eeitem.hxx>
111 #include <editeng/fhgtitem.hxx>
112 #include <editeng/prntitem.hxx>
113 #include <svx/svdpage.hxx>
114 #include <avmedia/mediawindow.hxx>
115 #include <swcrsr.hxx>
116 #include <SwRewriter.hxx>
117 #include <vcl/svapp.hxx>
118 #include <swserv.hxx>
119 #include <fmtmeta.hxx>
120 #include <itabenum.hxx>
121 #include <iodetect.hxx>
122 #include <unotextrange.hxx>
123 #include <unoframe.hxx>
124 #include <txatbase.hxx>
125 #include <vcl/uitest/logger.hxx>
126 #include <vcl/uitest/eventdescription.hxx>
128 #include <vcl/GraphicNativeTransform.hxx>
129 #include <vcl/GraphicNativeMetadata.hxx>
130 #include <vcl/TypeSerializer.hxx>
131 #include <comphelper/lok.hxx>
132 #include <sfx2/classificationhelper.hxx>
133 #include <sfx2/sfxdlg.hxx>
134 #include <comphelper/classids.hxx>
135 #include <osl/diagnose.h>
139 /* default (A4 format) width of 210mm - 2 * border size (border on both sides) */
140 constexpr tools::Long constOleWidthInMm
= 210 - 2 * lMinBorderInMm
;
142 constexpr Size
constOleSize100mm(
143 constOleWidthInMm
* 100, // convert from mm to 100mm
147 constexpr Size constOleSizeTwip
= o3tl::convert(constOleSize100mm
, o3tl::Length::mm100
, o3tl::Length::twip
);
149 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_DRAWMODEL
= 0x00000001;
150 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_HTML
= 0x00000002;
151 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_RTF
= 0x00000004;
152 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_STRING
= 0x00000008;
153 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_SWOLE
= 0x00000010;
154 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_DDE
= 0x00000020;
155 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_RICHTEXT
= 0x00000040;
157 using namespace ::svx
;
158 using namespace ::com::sun::star
;
159 using namespace ::com::sun::star::uno
;
160 using namespace ::com::sun::star::datatransfer
;
163 void collectUIInformation(const OUString
& rAction
, const OUString
& aParameters
)
165 EventDescription aDescription
;
166 aDescription
.aAction
= rAction
;
167 aDescription
.aParameters
= {{"parameters", aParameters
}};
168 aDescription
.aID
= "writer_edit";
169 aDescription
.aKeyWord
= "SwEditWinUIObject";
170 aDescription
.aParent
= "MainWindow";
171 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
);
209 /// Tracks the boundaries of pasted content and notifies listeners.
213 SwPasteContext(SwWrtShell
& rWrtShell
);
220 SwWrtShell
& m_rWrtShell
;
221 std::optional
<SwPaM
> m_oPaM
;
222 sal_Int32 m_nStartContent
= 0;
227 // helper class for Action and Undo enclosing
228 class SwTrnsfrActionAndUndo
232 SwTrnsfrActionAndUndo( SwWrtShell
*pS
, bool bDelSel
= false, SwPasteContext
* pContext
= nullptr)
235 pSh
->StartUndo( SwUndoId::PASTE_CLIPBOARD
);
242 pContext
->remember();
244 pSh
->StartAllAction();
246 ~SwTrnsfrActionAndUndo() COVERITY_NOEXCEPT_FALSE
255 SwTransferable::SwTransferable( SwWrtShell
& rSh
)
256 : m_pWrtShell( &rSh
),
257 m_pCreatorView( nullptr ),
258 m_pOrigGraphic( nullptr ),
259 m_eBufferType( TransferBufferType::NONE
),
263 rSh
.GetView().AddTransferable(*this);
264 SwDocShell
* pDShell
= rSh
.GetDoc()->GetDocShell();
268 pDShell
->FillTransferableObjectDescriptor( m_aObjDesc
);
269 if( pDShell
->GetMedium() )
271 const INetURLObject
& rURLObj
= pDShell
->GetMedium()->GetURLObject();
272 m_aObjDesc
.maDisplayName
= URIHelper::removePassword(
273 rURLObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
),
274 INetURLObject::EncodeMechanism::WasEncoded
,
275 INetURLObject::DecodeMechanism::Unambiguous
);
278 PrepareOLE( m_aObjDesc
);
281 SwTransferable::~SwTransferable()
283 SolarMutexGuard aSolarGuard
;
285 // the DDELink still needs the WrtShell!
286 if( m_xDdeLink
.is() )
288 static_cast<SwTransferDdeLink
*>( m_xDdeLink
.get() )->Disconnect( true );
292 m_pWrtShell
= nullptr;
294 // release reference to the document so that aDocShellRef will delete
295 // it (if aDocShellRef is set). Otherwise, the OLE nodes keep references
296 // to their sub-storage when the storage is already dead.
297 m_pClpDocFac
.reset();
299 // first close, then the Ref. can be cleared as well, so that
300 // the DocShell really gets deleted!
301 if( m_aDocShellRef
.Is() )
303 SfxObjectShell
* pObj
= m_aDocShellRef
;
304 SwDocShell
* pDocSh
= static_cast<SwDocShell
*>(pObj
);
307 m_aDocShellRef
.Clear();
309 SwModule
* pMod
= SW_MOD();
312 if ( pMod
->m_pDragDrop
== this )
313 pMod
->m_pDragDrop
= nullptr;
314 else if ( pMod
->m_pXSelection
== this )
315 pMod
->m_pXSelection
= nullptr;
318 m_eBufferType
= TransferBufferType::NONE
;
321 static SwDoc
& lcl_GetDoc(SwDocFac
& rDocFac
)
323 SwDoc
& rDoc
= rDocFac
.GetDoc();
324 rDoc
.SetClipBoard( true );
328 void SwTransferable::ObjectReleased()
330 SwModule
*pMod
= SW_MOD();
333 if( this == pMod
->m_pDragDrop
)
334 pMod
->m_pDragDrop
= nullptr;
335 else if( this == pMod
->m_pXSelection
)
336 pMod
->m_pXSelection
= nullptr;
339 void SwTransferable::AddSupportedFormats()
341 // only need if we are the current XSelection Object
342 SwModule
*pMod
= SW_MOD();
343 if( this == pMod
->m_pXSelection
|| comphelper::LibreOfficeKit::isActive())
345 SetDataForDragAndDrop( Point( 0,0) );
349 void SwTransferable::InitOle( SfxObjectShell
* pDoc
)
351 //set OleVisArea. Upper left corner of the page and size of
353 const Size
aSz(constOleSizeTwip
);
354 SwRect
aVis( Point( DOCUMENTBORDER
, DOCUMENTBORDER
), aSz
);
355 pDoc
->SetVisArea( aVis
.SVRect() );
358 uno::Reference
< embed::XEmbeddedObject
> SwTransferable::FindOLEObj( sal_Int64
& nAspect
) const
360 uno::Reference
< embed::XEmbeddedObject
> xObj
;
363 SwIterator
<SwContentNode
,SwFormatColl
> aIter( *m_pClpDocFac
->GetDoc().GetDfltGrfFormatColl() );
364 for( SwContentNode
* pNd
= aIter
.First(); pNd
; pNd
= aIter
.Next() )
365 if( SwNodeType::Ole
== pNd
->GetNodeType() )
367 xObj
= static_cast<SwOLENode
*>(pNd
)->GetOLEObj().GetOleRef();
368 nAspect
= static_cast<SwOLENode
*>(pNd
)->GetAspect();
375 const Graphic
* SwTransferable::FindOLEReplacementGraphic() const
379 SwIterator
<SwContentNode
,SwFormatColl
> aIter( *m_pClpDocFac
->GetDoc().GetDfltGrfFormatColl() );
380 for( SwContentNode
* pNd
= aIter
.First(); pNd
; pNd
= aIter
.Next() )
381 if( SwNodeType::Ole
== pNd
->GetNodeType() )
383 return static_cast<SwOLENode
*>(pNd
)->GetGraphic();
390 void SwTransferable::RemoveDDELinkFormat(vcl::Window
& rWin
)
392 RemoveFormat( SotClipboardFormatId::LINK
);
393 CopyToClipboard(&rWin
);
398 //Resolves: fdo#40717 surely when we create a clipboard document we should
399 //overwrite the clipboard documents styles and settings with that of the
400 //source, so that we can WYSIWYG paste. If we want that the destinations
401 //styles are used over the source styles, that's a matter of the
402 //destination paste code to handle, not the source paste code.
403 void lclOverWriteDoc(SwWrtShell
&rSrcWrtShell
, SwDoc
&rDest
)
405 const SwDoc
&rSrc
= *rSrcWrtShell
.GetDoc();
407 rDest
.ReplaceCompatibilityOptions(rSrc
);
408 rDest
.ReplaceDefaults(rSrc
);
410 //It would probably make most sense here to only insert the styles used
411 //by the selection, e.g. apply SwDoc::IsUsed on styles ?
412 rDest
.ReplaceStyles(rSrc
, false);
414 rSrcWrtShell
.Copy(rDest
);
416 rDest
.GetMetaFieldManager().copyDocumentProperties(rSrc
);
419 void lclCheckAndPerformRotation(Graphic
& aGraphic
)
421 GraphicNativeMetadata aMetadata
;
422 if ( !aMetadata
.read(aGraphic
) )
425 Degree10 aRotation
= aMetadata
.getRotation();
428 GraphicNativeTransform
aTransform( aGraphic
);
429 aTransform
.rotate( aRotation
);
434 sal_Bool SAL_CALL
SwTransferable::isComplex()
436 sal_Int32 nTextLength
= 0;
437 SwNodes
& aNodes
= m_pWrtShell
->GetDoc()->GetNodes();
438 for (SwPaM
& rPaM
: m_pWrtShell
->GetCursor()->GetRingContainer())
440 for (SwNodeOffset nIndex
= rPaM
.GetMark()->GetNodeIndex();
441 nIndex
<= rPaM
.GetPoint()->GetNodeIndex(); ++nIndex
)
443 SwNode
& rNd
= *aNodes
[nIndex
];
445 SwTextNode
* pTextNode
= rNd
.GetTextNode();
448 if (pTextNode
->HasHints())
450 for (size_t nHint
= 0; nHint
< pTextNode
->GetSwpHints().Count(); ++nHint
)
452 SwTextAttr
* pHint
= pTextNode
->GetSwpHints().Get(nHint
);
453 if (pHint
->Which() == RES_TXTATR_FLYCNT
)
455 return true; // Complex
460 nTextLength
+= pTextNode
->GetText().getLength();
461 if (nTextLength
>= 1024 * 512)
462 return true; // Complex
467 if (m_pWrtShell
->GetSelectionType() == SelectionType::DrawObject
)
468 return true; // Complex
474 bool SwTransferable::GetData( const DataFlavor
& rFlavor
, const OUString
& rDestDoc
)
476 SotClipboardFormatId nFormat
= SotExchange::GetFormat( rFlavor
);
478 // we can only fulfil the request if
479 // 1) we have data for this format
480 // 2) we have either a clipboard document (pClpDocFac), or
481 // we have a SwWrtShell (so we can generate a new clipboard document)
482 if( !HasFormat( nFormat
) || ( m_pClpDocFac
== nullptr && m_pWrtShell
== nullptr ) )
487 SelectionType nSelectionType
= m_pWrtShell
->GetSelectionType();
489 // when pending we will not get the correct type, but SelectionType::Text
490 // as fallback. This *happens* during D&D, so we need to check if we are in
491 // the fallback and just try to get a graphic
492 const bool bPending(m_pWrtShell
->ActionPend());
494 // SEL_GRF is from ContentType of editsh
495 if(bPending
|| ((SelectionType::Graphic
| SelectionType::DrawObject
| SelectionType::DbForm
) & nSelectionType
))
497 m_oClpGraphic
.emplace();
498 if( !m_pWrtShell
->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE
, *m_oClpGraphic
))
499 m_pOrigGraphic
= &*m_oClpGraphic
;
500 m_oClpBitmap
.emplace();
501 if( !m_pWrtShell
->GetDrawObjGraphic( SotClipboardFormatId::BITMAP
, *m_oClpBitmap
))
502 m_pOrigGraphic
= &*m_oClpBitmap
;
504 // is it a URL-Button ?
507 if( m_pWrtShell
->GetURLFromButton( sURL
, sDesc
) )
509 m_oBookmark
.emplace( sURL
, sDesc
);
510 m_eBufferType
= TransferBufferType::InetField
;
514 m_pClpDocFac
.reset(new SwDocFac
);
515 SwDoc
& rTmpDoc
= lcl_GetDoc(*m_pClpDocFac
);
517 rTmpDoc
.getIDocumentFieldsAccess().LockExpFields(); // never update fields - leave text as it is
518 lclOverWriteDoc(*m_pWrtShell
, rTmpDoc
);
520 // in CORE a new one was created (OLE-objects copied!)
521 m_aDocShellRef
= rTmpDoc
.GetTmpDocShell();
522 if( m_aDocShellRef
.Is() )
523 SwTransferable::InitOle( m_aDocShellRef
);
524 rTmpDoc
.SetTmpDocShell( nullptr );
526 if( nSelectionType
& SelectionType::Text
&& !m_pWrtShell
->HasMark() )
528 SwContentAtPos
aContentAtPos( IsAttrAtPos::InetAttr
);
530 Point
aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY());
532 bool bSelect
= g_bExecuteDrag
&&
533 m_pWrtShell
->GetView().GetDocShell() &&
534 !m_pWrtShell
->GetView().GetDocShell()->IsReadOnly();
535 if( m_pWrtShell
->GetContentAtPos( aPos
, aContentAtPos
, bSelect
) )
538 static_cast<const SwFormatINetFormat
*>(aContentAtPos
.aFnd
.pAttr
)->GetValue(),
539 aContentAtPos
.sStr
);
540 m_eBufferType
= TransferBufferType::InetField
;
542 m_pWrtShell
->SelectTextAttr( RES_TXTATR_INETFMT
);
545 if( m_pWrtShell
->IsFrameSelected() )
547 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( m_pWrtShell
->GetAttrPool() );
548 m_pWrtShell
->GetFlyFrameAttr( aSet
);
549 const SwFormatURL
& rURL
= aSet
.Get( RES_URL
);
551 m_pImageMap
.reset(new ImageMap( *rURL
.GetMap() ));
552 else if( !rURL
.GetURL().isEmpty() )
553 m_pTargetURL
.reset(new INetImage(OUString(), rURL
.GetURL(),
554 rURL
.GetTargetFrameName() ));
559 if( TransferBufferType::Ole
== m_eBufferType
)
561 //TODO/MBA: testing - is this the "single OLE object" case?!
562 // get OLE-Object from ClipDoc and get the data from that.
563 sal_Int64 nAspect
= embed::Aspects::MSOLE_CONTENT
; // will be set in the next statement
564 uno::Reference
< embed::XEmbeddedObject
> xObj
= FindOLEObj( nAspect
);
565 const Graphic
* pOLEGraph
= FindOLEReplacementGraphic();
568 TransferableDataHelper
aD( new SvEmbedTransferHelper( xObj
, pOLEGraph
, nAspect
) );
569 uno::Any aAny
= aD
.GetAny(rFlavor
, rDestDoc
);
570 if( aAny
.hasValue() )
571 bOK
= SetAny( aAny
);
574 // the following solution will be used in the case when the object can not generate the image
575 // TODO/LATER: in future the transferhelper must probably be created based on object and the replacement stream
576 // TODO: Block not required now, SvEmbedTransferHelper should be able to handle GDIMetaFile format
577 if ( nFormat
== SotClipboardFormatId::GDIMETAFILE
)
579 pOLEGraph
= FindOLEReplacementGraphic();
581 bOK
= SetGDIMetaFile( pOLEGraph
->GetGDIMetaFile() );
588 case SotClipboardFormatId::LINK
:
589 if( m_xDdeLink
.is() )
590 bOK
= SetObject( m_xDdeLink
.get(), SWTRANSFER_OBJECTTYPE_DDE
, rFlavor
);
593 case SotClipboardFormatId::OBJECTDESCRIPTOR
:
594 case SotClipboardFormatId::LINKSRCDESCRIPTOR
:
595 bOK
= SetTransferableObjectDescriptor( m_aObjDesc
);
598 case SotClipboardFormatId::DRAWING
:
600 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
601 bOK
= SetObject( rDoc
.getIDocumentDrawModelAccess().GetDrawModel(),
602 SWTRANSFER_OBJECTTYPE_DRAWMODEL
, rFlavor
);
606 case SotClipboardFormatId::STRING
:
608 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
609 bOK
= SetObject( &rDoc
, SWTRANSFER_OBJECTTYPE_STRING
, rFlavor
);
612 case SotClipboardFormatId::RTF
:
614 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
615 bOK
= SetObject( &rDoc
, SWTRANSFER_OBJECTTYPE_RTF
, rFlavor
);
618 case SotClipboardFormatId::RICHTEXT
:
620 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
621 bOK
= SetObject( &rDoc
, SWTRANSFER_OBJECTTYPE_RICHTEXT
, rFlavor
);
625 case SotClipboardFormatId::HTML
:
627 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
628 bOK
= SetObject( &rDoc
, SWTRANSFER_OBJECTTYPE_HTML
, rFlavor
);
632 case SotClipboardFormatId::SVXB
:
633 if( m_eBufferType
& TransferBufferType::Graphic
&& m_pOrigGraphic
)
634 bOK
= SetGraphic( *m_pOrigGraphic
);
637 case SotClipboardFormatId::GDIMETAFILE
:
638 if( m_eBufferType
& TransferBufferType::Graphic
)
639 bOK
= SetGDIMetaFile( m_oClpGraphic
->GetGDIMetaFile() );
641 case SotClipboardFormatId::BITMAP
:
642 case SotClipboardFormatId::PNG
:
643 // Neither pClpBitmap nor pClpGraphic are necessarily set
644 if( (m_eBufferType
& TransferBufferType::Graphic
) && (m_oClpBitmap
|| m_oClpGraphic
))
645 bOK
= SetBitmapEx( (m_oClpBitmap
? m_oClpBitmap
: m_oClpGraphic
)->GetBitmapEx(), rFlavor
);
648 case SotClipboardFormatId::SVIM
:
650 bOK
= SetImageMap( *m_pImageMap
);
653 case SotClipboardFormatId::INET_IMAGE
:
655 bOK
= SetINetImage( *m_pTargetURL
, rFlavor
);
658 case SotClipboardFormatId::SOLK
:
659 case SotClipboardFormatId::NETSCAPE_BOOKMARK
:
660 case SotClipboardFormatId::FILEGRPDESCRIPTOR
:
661 case SotClipboardFormatId::FILECONTENT
:
662 case SotClipboardFormatId::UNIFORMRESOURCELOCATOR
:
663 case SotClipboardFormatId::SIMPLE_FILE
:
664 if( (TransferBufferType::InetField
& m_eBufferType
) && m_oBookmark
)
665 bOK
= SetINetBookmark( *m_oBookmark
, rFlavor
);
668 case SotClipboardFormatId::EMBED_SOURCE
:
669 if( !m_aDocShellRef
.Is() )
671 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
672 SwDocShell
* pNewDocSh
= new SwDocShell( rDoc
,
673 SfxObjectCreateMode::EMBEDDED
);
674 m_aDocShellRef
= pNewDocSh
;
675 m_aDocShellRef
->DoInitNew();
676 SwTransferable::InitOle( m_aDocShellRef
);
678 bOK
= SetObject( &m_aDocShellRef
, SWTRANSFER_OBJECTTYPE_SWOLE
,
687 bool SwTransferable::WriteObject( tools::SvRef
<SotTempStream
>& xStream
,
688 void* pObject
, sal_uInt32 nObjectType
,
689 const DataFlavor
& /*rFlavor*/ )
694 switch( nObjectType
)
696 case SWTRANSFER_OBJECTTYPE_DRAWMODEL
:
698 // don't change the sequence of commands
699 SdrModel
*pModel
= static_cast<SdrModel
*>(pObject
);
700 xStream
->SetBufferSize( 16348 );
702 // for the changed pool defaults from drawing layer pool set those
703 // attributes as hard attributes to preserve them for saving
704 const SfxItemPool
& rItemPool
= pModel
->GetItemPool();
705 const SvxFontHeightItem
& rDefaultFontHeight
= rItemPool
.GetDefaultItem(EE_CHAR_FONTHEIGHT
);
707 // SW should have no MasterPages
708 OSL_ENSURE(0 == pModel
->GetMasterPageCount(), "SW with MasterPages (!)");
710 for(sal_uInt16
a(0); a
< pModel
->GetPageCount(); a
++)
712 const SdrPage
* pPage
= pModel
->GetPage(a
);
713 SdrObjListIter
aIter(pPage
, SdrIterMode::DeepNoGroups
);
715 while(aIter
.IsMore())
717 SdrObject
* pObj
= aIter
.Next();
718 const SvxFontHeightItem
& rItem
= pObj
->GetMergedItem(EE_CHAR_FONTHEIGHT
);
720 if(rItem
.GetHeight() == rDefaultFontHeight
.GetHeight())
722 pObj
->SetMergedItem(rDefaultFontHeight
);
728 uno::Reference
<io::XOutputStream
> xDocOut( new utl::OOutputStreamWrapper( *xStream
) );
729 SvxDrawingLayerExport( pModel
, xDocOut
);
732 bRet
= ERRCODE_NONE
== xStream
->GetError();
736 case SWTRANSFER_OBJECTTYPE_SWOLE
:
738 SfxObjectShell
* pEmbObj
= static_cast<SfxObjectShell
*>(pObject
);
741 ::utl::TempFileFast aTempFile
;
742 SvStream
* pTempStream
= aTempFile
.GetStream(StreamMode::READWRITE
);
743 uno::Reference
< embed::XStorage
> xWorkStore
=
744 ::comphelper::OStorageHelper::GetStorageFromStream( new utl::OStreamWrapper(*pTempStream
), embed::ElementModes::READWRITE
);
746 // write document storage
747 pEmbObj
->SetupStorage( xWorkStore
, SOFFICE_FILEFORMAT_CURRENT
, false );
748 // mba: no BaseURL for clipboard
749 SfxMedium
aMedium( xWorkStore
, OUString() );
750 pEmbObj
->DoSaveObjectAs( aMedium
, false );
751 pEmbObj
->DoSaveCompleted();
753 uno::Reference
< embed::XTransactedObject
> xTransact( xWorkStore
, uno::UNO_QUERY
);
754 if ( xTransact
.is() )
757 xStream
->SetBufferSize( 0xff00 );
758 xStream
->WriteStream( *pTempStream
);
760 xWorkStore
->dispose();
763 catch (const uno::Exception
&)
767 bRet
= ( xStream
->GetError() == ERRCODE_NONE
);
771 case SWTRANSFER_OBJECTTYPE_DDE
:
773 xStream
->SetBufferSize( 1024 );
774 SwTransferDdeLink
* pDdeLnk
= static_cast<SwTransferDdeLink
*>(pObject
);
775 if( pDdeLnk
->WriteData( *xStream
) )
777 bRet
= ERRCODE_NONE
== xStream
->GetError();
782 case SWTRANSFER_OBJECTTYPE_HTML
:
784 // LOK is interested in getting images embedded for copy/paste support.
785 GetHTMLWriter( comphelper::LibreOfficeKit::isActive() ? OUString("EmbedImages;NoPrettyPrint") : OUString(), OUString(), xWrt
);
789 case SWTRANSFER_OBJECTTYPE_RTF
:
790 case SWTRANSFER_OBJECTTYPE_RICHTEXT
:
791 GetRTFWriter(std::u16string_view(), OUString(), xWrt
);
794 case SWTRANSFER_OBJECTTYPE_STRING
:
795 GetASCWriter(std::u16string_view(), OUString(), xWrt
);
798 SwAsciiOptions aAOpt
;
799 aAOpt
.SetCharSet( RTL_TEXTENCODING_UTF8
);
800 xWrt
->SetAsciiOptions( aAOpt
);
802 // no start char for clipboard
803 xWrt
->m_bUCS2_WithStartChar
= false;
811 SwDoc
* pDoc
= static_cast<SwDoc
*>(pObject
);
812 xWrt
->m_bWriteClipboardDoc
= true;
813 xWrt
->m_bWriteOnlyFirstTable
= bool(TransferBufferType::Table
& m_eBufferType
);
814 xWrt
->SetShowProgress(false);
816 #if defined(DEBUGPASTE)
817 SvFileStream
aPasteDebug(OUString(
818 "PASTEBUFFER.debug"), StreamMode::WRITE
|StreamMode::TRUNC
);
819 SwWriter
aDbgWrt( aPasteDebug
, *pDoc
);
820 aDbgWrt
.Write( xWrt
);
823 SwWriter
aWrt( *xStream
, *pDoc
);
824 if( ! aWrt
.Write( xWrt
).IsError() )
826 xStream
->WriteChar( '\0' ); // terminate with a zero
834 int SwTransferable::Cut()
836 int nRet
= Copy( true );
839 collectUIInformation("CUT", "parameter");
843 void SwTransferable::DeleteSelection()
847 // ask for type of selection before action-bracketing
848 const SelectionType nSelection
= m_pWrtShell
->GetSelectionType();
849 // cut rows or columns selected by enhanced table selection and wholly selected tables
850 bool bCutMode
= ( SelectionType::TableCell
& nSelection
) && ( (SelectionType::TableRow
| SelectionType::TableCol
) & nSelection
||
851 m_pWrtShell
->HasWholeTabSelection() );
853 m_pWrtShell
->StartUndo( SwUndoId::START
);
856 if( !(SelectionType::TableCol
& nSelection
) )
857 m_pWrtShell
->DeleteTable();
860 SfxDispatcher
* pDispatch
= m_pWrtShell
->GetView().GetViewFrame().GetDispatcher();
861 pDispatch
->Execute(FN_TABLE_DELETE_COL
, SfxCallMode::SYNCHRON
);
866 if( ( SelectionType::Text
| SelectionType::Table
) & nSelection
)
867 m_pWrtShell
->IntelligentCut( nSelection
);
868 m_pWrtShell
->DelRight();
870 m_pWrtShell
->EndUndo( SwUndoId::END
);
873 static void DeleteDDEMarks(SwDoc
& rDest
)
875 IDocumentMarkAccess
*const pMarkAccess
= rDest
.getIDocumentMarkAccess();
876 std::vector
< ::sw::mark::IMark
* > vDdeMarks
;
877 // find all DDE-Bookmarks
878 for (IDocumentMarkAccess::const_iterator_t ppMark
= pMarkAccess
->getAllMarksBegin();
879 ppMark
!= pMarkAccess
->getAllMarksEnd();
882 if (IDocumentMarkAccess::MarkType::DDE_BOOKMARK
== IDocumentMarkAccess::GetType(**ppMark
))
884 vDdeMarks
.push_back(*ppMark
);
887 // remove all DDE-Bookmarks, they are invalid inside the clipdoc!
888 for (const auto& rpMark
: vDdeMarks
)
890 pMarkAccess
->deleteMark(rpMark
);
894 void SwTransferable::PrepareForCopyTextRange(SwPaM
& rPaM
)
896 std::optional
<SwWait
> oWait
;
897 if (m_pWrtShell
->ShouldWait())
899 oWait
.emplace( *m_pWrtShell
->GetView().GetDocShell(), true );
902 m_pClpDocFac
.reset(new SwDocFac
);
904 SwDoc
& rDest(lcl_GetDoc(*m_pClpDocFac
));
905 rDest
.getIDocumentFieldsAccess().LockExpFields(); // Never update fields - leave text as is
907 SwDoc
const& rSrc(*m_pWrtShell
->GetDoc());
908 assert(&rSrc
== &rPaM
.GetDoc());
910 rDest
.ReplaceCompatibilityOptions(rSrc
);
911 rDest
.ReplaceDefaults(rSrc
);
913 //It would probably make most sense here to only insert the styles used
914 //by the selection, e.g. apply SwDoc::IsUsed on styles ?
915 rDest
.ReplaceStyles(rSrc
, false);
917 // relevant bits of rSrcWrtShell.Copy(rDest);
918 rDest
.GetIDocumentUndoRedo().DoUndo(false); // always false!
919 rDest
.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines
);
921 SwNodeIndex
const aIdx(rDest
.GetNodes().GetEndOfContent(), -1);
922 SwContentNode
*const pContentNode(aIdx
.GetNode().GetContentNode());
923 SwPosition
aPos(aIdx
, pContentNode
, pContentNode
? pContentNode
->Len() : 0);
925 rSrc
.getIDocumentContentOperations().CopyRange(rPaM
, aPos
, SwCopyFlags::CheckPosInFly
);
927 rDest
.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::NONE
);
929 rDest
.GetMetaFieldManager().copyDocumentProperties(rSrc
);
932 DeleteDDEMarks(rDest
);
934 // a new one was created in core (OLE objects copied!)
935 m_aDocShellRef
= rDest
.GetTmpDocShell();
936 if (m_aDocShellRef
.Is())
937 SwTransferable::InitOle( m_aDocShellRef
);
938 rDest
.SetTmpDocShell( nullptr );
940 // let's add some formats
941 AddFormat( SotClipboardFormatId::EMBED_SOURCE
);
942 AddFormat( SotClipboardFormatId::RTF
);
943 #if HAVE_FEATURE_DESKTOP
944 AddFormat( SotClipboardFormatId::RICHTEXT
);
945 AddFormat( SotClipboardFormatId::HTML
);
947 AddFormat( SotClipboardFormatId::STRING
);
950 int SwTransferable::PrepareForCopy( bool bIsCut
)
956 if ( m_pWrtShell
->GetTableInsertMode() != SwTable::SEARCH_NONE
)
957 m_pWrtShell
->SetTableInsertMode( SwTable::SEARCH_NONE
);
959 if ( m_pWrtShell
->GetTableCopied() )
960 m_pWrtShell
->SetTableCopied( false );
963 const SelectionType nSelection
= m_pWrtShell
->GetSelectionType();
964 if( nSelection
== SelectionType::Graphic
)
966 m_oClpGraphic
.emplace();
967 if( !m_pWrtShell
->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE
, *m_oClpGraphic
))
968 m_pOrigGraphic
= &*m_oClpGraphic
;
969 m_oClpBitmap
.emplace();
970 if( !m_pWrtShell
->GetDrawObjGraphic( SotClipboardFormatId::BITMAP
, *m_oClpBitmap
))
971 m_pOrigGraphic
= &*m_oClpBitmap
;
973 m_pClpDocFac
.reset(new SwDocFac
);
974 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
975 m_pWrtShell
->Copy(rDoc
);
977 #if HAVE_FEATURE_DESKTOP
978 if (m_pOrigGraphic
&& !m_pOrigGraphic
->GetBitmapEx().IsEmpty())
979 AddFormat( SotClipboardFormatId::SVXB
);
982 PrepareOLE( m_aObjDesc
);
983 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
);
985 const Graphic
* pGrf
= m_pWrtShell
->GetGraphic();
986 if( pGrf
&& pGrf
->IsSupportedGraphic() )
988 AddFormat( SotClipboardFormatId::PNG
);
989 #if HAVE_FEATURE_DESKTOP
990 AddFormat( SotClipboardFormatId::GDIMETAFILE
);
991 AddFormat( SotClipboardFormatId::BITMAP
);
994 m_eBufferType
= TransferBufferType::Graphic
;
995 m_pWrtShell
->GetGrfNms( &sGrfNm
, nullptr );
997 else if ( nSelection
== SelectionType::Ole
)
999 m_pClpDocFac
.reset(new SwDocFac
);
1000 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
1001 m_aDocShellRef
= new SwDocShell(rDoc
, SfxObjectCreateMode::EMBEDDED
);
1002 m_aDocShellRef
->DoInitNew();
1003 m_pWrtShell
->Copy(rDoc
);
1005 AddFormat( SotClipboardFormatId::EMBED_SOURCE
);
1008 // set size of embedded object at the object description structure
1009 m_aObjDesc
.maSize
= o3tl::convert(m_pWrtShell
->GetObjSize(), o3tl::Length::twip
, o3tl::Length::mm100
);
1012 PrepareOLE( m_aObjDesc
);
1014 #if HAVE_FEATURE_DESKTOP
1015 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
);
1016 AddFormat( SotClipboardFormatId::GDIMETAFILE
);
1018 // Fetch the formats supported via embedtransferhelper as well
1019 sal_Int64 nAspect
= embed::Aspects::MSOLE_CONTENT
;
1020 uno::Reference
< embed::XEmbeddedObject
> xObj
= FindOLEObj( nAspect
);
1021 const Graphic
* pOLEGraph
= FindOLEReplacementGraphic();
1024 TransferableDataHelper
aD( new SvEmbedTransferHelper( xObj
, pOLEGraph
, nAspect
) );
1025 if ( aD
.GetTransferable().is() )
1027 DataFlavorExVector
aVector( aD
.GetDataFlavorExVector() );
1029 for( const auto& rItem
: aVector
)
1034 m_eBufferType
= TransferBufferType::Ole
;
1036 // Is there anything to provide anyway?
1037 else if ( m_pWrtShell
->IsSelection() || m_pWrtShell
->IsFrameSelected() ||
1038 m_pWrtShell
->IsObjSelected() )
1040 std::optional
<SwWait
> oWait
;
1041 if( m_pWrtShell
->ShouldWait() )
1042 oWait
.emplace( *m_pWrtShell
->GetView().GetDocShell(), true );
1044 m_pClpDocFac
.reset(new SwDocFac
);
1046 // create additional cursor so that equal treatment of keyboard
1047 // and mouse selection is possible.
1048 // In AddMode with keyboard selection, the new cursor is not created
1049 // before the cursor is moved after end of selection.
1050 if( m_pWrtShell
->IsAddMode() && m_pWrtShell
->SwCursorShell::HasSelection() )
1051 m_pWrtShell
->CreateCursor();
1053 SwDoc
& rTmpDoc
= lcl_GetDoc(*m_pClpDocFac
);
1055 rTmpDoc
.getIDocumentFieldsAccess().LockExpFields(); // Never update fields - leave text as is
1056 lclOverWriteDoc(*m_pWrtShell
, rTmpDoc
);
1058 DeleteDDEMarks(rTmpDoc
);
1060 // a new one was created in CORE (OLE objects copied!)
1061 m_aDocShellRef
= rTmpDoc
.GetTmpDocShell();
1062 if( m_aDocShellRef
.Is() )
1063 SwTransferable::InitOle( m_aDocShellRef
);
1064 rTmpDoc
.SetTmpDocShell( nullptr );
1066 if( m_pWrtShell
->IsObjSelected() )
1067 m_eBufferType
= TransferBufferType::Drawing
;
1070 m_eBufferType
= TransferBufferType::Document
;
1071 if (m_pWrtShell
->IntelligentCut(nSelection
, false) != SwWrtShell::NO_WORD
)
1072 m_eBufferType
= TransferBufferType::DocumentWord
| m_eBufferType
;
1075 bool bDDELink
= m_pWrtShell
->IsSelection();
1076 if( nSelection
& SelectionType::TableCell
)
1078 m_eBufferType
= TransferBufferType::Table
| m_eBufferType
;
1079 bDDELink
= m_pWrtShell
->HasWholeTabSelection();
1081 m_pWrtShell
->SetTableCopied(true);
1083 if ( bIsCut
&& (SelectionType::TableRow
| SelectionType::TableCol
) & nSelection
)
1084 m_pWrtShell
->SetTableInsertMode( (SelectionType::TableRow
& nSelection
) ? SwTable::SEARCH_ROW
: SwTable::SEARCH_COL
);
1087 #if HAVE_FEATURE_DESKTOP
1088 //When someone needs it, we 'OLE' him something
1089 AddFormat( SotClipboardFormatId::EMBED_SOURCE
);
1092 //put RTF ahead of the OLE's Metafile to have less loss
1093 if( !m_pWrtShell
->IsObjSelected() )
1095 AddFormat( SotClipboardFormatId::RTF
);
1096 #if HAVE_FEATURE_DESKTOP
1097 AddFormat( SotClipboardFormatId::RICHTEXT
);
1098 AddFormat( SotClipboardFormatId::HTML
);
1101 if( m_pWrtShell
->IsSelection() )
1102 AddFormat( SotClipboardFormatId::STRING
);
1104 if( nSelection
& ( SelectionType::DrawObject
| SelectionType::DbForm
))
1106 AddFormat( SotClipboardFormatId::DRAWING
);
1107 if ( nSelection
& SelectionType::DrawObject
)
1109 #if HAVE_FEATURE_DESKTOP
1110 AddFormat( SotClipboardFormatId::GDIMETAFILE
);
1111 AddFormat( SotClipboardFormatId::BITMAP
);
1113 AddFormat( SotClipboardFormatId::PNG
);
1115 m_eBufferType
= static_cast<TransferBufferType
>( TransferBufferType::Graphic
| m_eBufferType
);
1117 m_oClpGraphic
.emplace();
1118 if( !m_pWrtShell
->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE
, *m_oClpGraphic
))
1119 m_pOrigGraphic
= &*m_oClpGraphic
;
1120 m_oClpBitmap
.emplace();
1121 if( !m_pWrtShell
->GetDrawObjGraphic( SotClipboardFormatId::BITMAP
, *m_oClpBitmap
))
1122 m_pOrigGraphic
= &*m_oClpBitmap
;
1124 // is it a URL-Button ?
1127 if( m_pWrtShell
->GetURLFromButton( sURL
, sDesc
) )
1129 AddFormat( SotClipboardFormatId::STRING
);
1130 #if HAVE_FEATURE_DESKTOP
1131 AddFormat( SotClipboardFormatId::SOLK
);
1132 AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK
);
1133 AddFormat( SotClipboardFormatId::FILECONTENT
);
1134 AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR
);
1136 AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR
);
1137 m_eBufferType
= TransferBufferType::InetField
| m_eBufferType
;
1142 // at Cut, DDE-Link doesn't make sense!!
1143 SwDocShell
* pDShell
;
1144 if( !bIsCut
&& bDDELink
&&
1145 nullptr != ( pDShell
= m_pWrtShell
->GetDoc()->GetDocShell()) &&
1146 SfxObjectCreateMode::STANDARD
== pDShell
->GetCreateMode() )
1148 #if HAVE_FEATURE_DESKTOP
1149 AddFormat( SotClipboardFormatId::LINK
);
1151 m_xDdeLink
= new SwTransferDdeLink( *this, *m_pWrtShell
);
1154 //ObjectDescriptor was already filly from the old DocShell.
1155 //Now adjust it. Thus in GetData the first query can still
1156 //be answered with delayed rendering.
1157 m_aObjDesc
.maSize
= constOleSize100mm
;
1159 PrepareOLE( m_aObjDesc
);
1160 #if HAVE_FEATURE_DESKTOP
1161 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
);
1167 if( m_pWrtShell
->IsFrameSelected() )
1169 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( m_pWrtShell
->GetAttrPool() );
1170 m_pWrtShell
->GetFlyFrameAttr( aSet
);
1171 const SwFormatURL
& rURL
= aSet
.Get( RES_URL
);
1174 m_pImageMap
.reset( new ImageMap( *rURL
.GetMap() ) );
1175 AddFormat( SotClipboardFormatId::SVIM
);
1177 else if( !rURL
.GetURL().isEmpty() )
1179 m_pTargetURL
.reset(new INetImage( sGrfNm
, rURL
.GetURL(),
1180 rURL
.GetTargetFrameName() ));
1181 AddFormat( SotClipboardFormatId::INET_IMAGE
);
1188 int SwTransferable::Copy( bool bIsCut
)
1190 if (m_pWrtShell
->GetView().GetObjectShell()->isContentExtractionLocked())
1193 int nRet
= PrepareForCopy( bIsCut
);
1196 CopyToClipboard( &m_pWrtShell
->GetView().GetEditWin() );
1200 collectUIInformation("COPY", "parameter");
1206 void SwTransferable::CalculateAndCopy()
1210 SwWait
aWait( *m_pWrtShell
->GetView().GetDocShell(), true );
1212 OUString
aStr( m_pWrtShell
->Calculate() );
1214 m_pClpDocFac
.reset(new SwDocFac
);
1215 SwDoc
& rDoc
= lcl_GetDoc(*m_pClpDocFac
);
1216 m_pWrtShell
->Copy(rDoc
, &aStr
);
1217 m_eBufferType
= TransferBufferType::Document
;
1218 AddFormat( SotClipboardFormatId::STRING
);
1220 CopyToClipboard( &m_pWrtShell
->GetView().GetEditWin() );
1223 bool SwTransferable::CopyGlossary( SwTextBlocks
& rGlossary
, const OUString
& rStr
)
1227 SwWait
aWait( *m_pWrtShell
->GetView().GetDocShell(), true );
1229 m_pClpDocFac
.reset(new SwDocFac
);
1230 SwDoc
& rCDoc
= lcl_GetDoc(*m_pClpDocFac
);
1232 SwNodes
& rNds
= rCDoc
.GetNodes();
1233 SwNodeIndex
aNodeIdx( *rNds
.GetEndOfContent().StartOfSectionNode() );
1234 SwContentNode
* pCNd
= rNds
.GoNext( &aNodeIdx
); // go to 1st ContentNode
1235 SwPaM
aPam( *pCNd
);
1237 rCDoc
.getIDocumentFieldsAccess().LockExpFields(); // never update fields - leave text as it is
1239 rCDoc
.InsertGlossary( rGlossary
, rStr
, aPam
);
1241 // a new one was created in CORE (OLE-Objects copied!)
1242 m_aDocShellRef
= rCDoc
.GetTmpDocShell();
1243 if( m_aDocShellRef
.Is() )
1244 SwTransferable::InitOle( m_aDocShellRef
);
1245 rCDoc
.SetTmpDocShell( nullptr );
1247 m_eBufferType
= TransferBufferType::Document
;
1249 //When someone needs it, we 'OLE' her something.
1250 AddFormat( SotClipboardFormatId::EMBED_SOURCE
);
1251 AddFormat( SotClipboardFormatId::RTF
);
1252 AddFormat( SotClipboardFormatId::RICHTEXT
);
1253 AddFormat( SotClipboardFormatId::HTML
);
1254 AddFormat( SotClipboardFormatId::STRING
);
1256 //ObjectDescriptor was already filled from the old DocShell.
1257 //Now adjust it. Thus in GetData the first query can still
1258 //be answered with delayed rendering.
1259 m_aObjDesc
.maSize
= constOleSize100mm
;
1261 PrepareOLE( m_aObjDesc
);
1262 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
);
1264 CopyToClipboard( &m_pWrtShell
->GetView().GetEditWin() );
1269 static uno::Reference
< XTransferable
> * lcl_getTransferPointer ( uno::Reference
< XTransferable
> &xRef
)
1274 SwPasteContext::SwPasteContext(SwWrtShell
& rWrtShell
)
1275 : m_rWrtShell(rWrtShell
)
1280 void SwPasteContext::remember()
1282 if (m_rWrtShell
.GetPasteListeners().getLength() == 0)
1285 SwPaM
* pCursor
= m_rWrtShell
.GetCursor();
1289 // Set point to the previous node, so it is not moved.
1290 const SwNode
& rNode
= pCursor
->GetPoint()->GetNode();
1291 m_oPaM
.emplace(rNode
, rNode
, SwNodeOffset(0), SwNodeOffset(-1));
1292 m_nStartContent
= pCursor
->GetPoint()->GetContentIndex();
1295 void SwPasteContext::forget() { m_oPaM
.reset(); }
1297 SwPasteContext::~SwPasteContext()
1301 if (m_rWrtShell
.GetPasteListeners().getLength() == 0)
1304 beans::PropertyValue aPropertyValue
;
1306 switch (m_rWrtShell
.GetView().GetShellMode())
1308 case ShellMode::Graphic
:
1310 SwFrameFormat
* pFormat
= m_rWrtShell
.GetFlyFrameFormat();
1314 aPropertyValue
.Name
= "TextGraphicObject";
1315 aPropertyValue
.Value
1316 <<= uno::Reference
<text::XTextContent
>(SwXTextGraphicObject::CreateXTextGraphicObject(*pFormat
->GetDoc(), pFormat
));
1325 SwPaM
* pCursor
= m_rWrtShell
.GetCursor();
1329 if (!pCursor
->GetPoint()->GetNode().IsTextNode())
1330 // Non-text was pasted.
1333 // Update mark after paste.
1334 *m_oPaM
->GetMark() = *pCursor
->GetPoint();
1337 m_oPaM
->GetPoint()->Adjust(SwNodeOffset(1));
1338 SwNode
& rNode
= m_oPaM
->GetPointNode();
1339 if (!rNode
.IsTextNode())
1340 // Starting point is no longer text.
1343 m_oPaM
->GetPoint()->SetContent(m_nStartContent
);
1345 aPropertyValue
.Name
= "TextRange";
1346 const rtl::Reference
<SwXTextRange
> xTextRange
= SwXTextRange::CreateXTextRange(
1347 m_oPaM
->GetDoc(), *m_oPaM
->GetPoint(), m_oPaM
->GetMark());
1348 aPropertyValue
.Value
<<= uno::Reference
<text::XTextRange
>(xTextRange
);
1353 if (aPropertyValue
.Name
.isEmpty())
1356 // Invoke the listeners.
1357 uno::Sequence
<beans::PropertyValue
> aEvent
{ aPropertyValue
};
1358 m_rWrtShell
.GetPasteListeners().notifyEach( &css::text::XPasteListener::notifyPasteEvent
, aEvent
);
1360 catch (const uno::Exception
& rException
)
1363 "SwPasteContext::~SwPasteContext: uncaught exception: " << rException
.Message
);
1367 bool SwTransferable::IsPaste( const SwWrtShell
& rSh
,
1368 const TransferableDataHelper
& rData
)
1370 // Check the common case first: We can always paste our own data!
1371 // If _only_ the internal format can be pasted, this check will
1372 // yield 'true', while the one below would give a (wrong) result 'false'.
1374 bool bIsPaste
= ( GetSwTransferable( rData
) != nullptr );
1376 // if it's not our own data, we need to have a closer look:
1379 // determine the proper paste action, and return true if we find one
1380 uno::Reference
<XTransferable
> xTransferable( rData
.GetXTransferable() );
1382 SotExchangeDest nDestination
= SwTransferable::GetSotDestination( rSh
);
1383 sal_uInt16 nSourceOptions
=
1384 (( SotExchangeDest::DOC_TEXTFRAME
== nDestination
||
1385 SotExchangeDest::SWDOC_FREE_AREA
== nDestination
||
1386 SotExchangeDest::DOC_TEXTFRAME_WEB
== nDestination
||
1387 SotExchangeDest::SWDOC_FREE_AREA_WEB
== nDestination
)
1388 ? EXCHG_IN_ACTION_COPY
1389 : EXCHG_IN_ACTION_MOVE
);
1391 SotClipboardFormatId nFormat
; // output param for GetExchangeAction
1392 sal_uInt8 nEventAction
; // output param for GetExchangeAction
1393 sal_uInt8 nAction
= SotExchange::GetExchangeAction(
1394 rData
.GetDataFlavorExVector(),
1396 nSourceOptions
, /* ?? */
1397 EXCHG_IN_ACTION_DEFAULT
, /* ?? */
1398 nFormat
, nEventAction
, SotClipboardFormatId::NONE
,
1399 lcl_getTransferPointer ( xTransferable
) );
1401 // if we find a suitable action, we can paste!
1402 bIsPaste
= (EXCHG_INOUT_ACTION_NONE
!= nAction
);
1408 void SwTransferable::SelectPasteFormat(TransferableDataHelper
& rData
, sal_uInt8
& nAction
,
1409 SotClipboardFormatId
& nFormat
)
1411 if (nFormat
!= SotClipboardFormatId::RICHTEXT
)
1416 if (!rData
.HasFormat(SotClipboardFormatId::EMBED_SOURCE
))
1421 if (!rData
.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR
))
1426 TransferableObjectDescriptor aObjDesc
;
1427 if (!rData
.GetTransferableObjectDescriptor(SotClipboardFormatId::OBJECTDESCRIPTOR
, aObjDesc
))
1432 if (aObjDesc
.maClassName
!= SvGlobalName(SO3_SW_CLASSID
))
1437 // At this point we know that we paste from Writer to Writer and the clipboard has the content
1438 // in both RTF and ODF formats. Prefer ODF in this case.
1439 nAction
= EXCHG_OUT_ACTION_INSERT_OLE
;
1440 nFormat
= SotClipboardFormatId::EMBED_SOURCE
;
1443 // get HTML indentation level by counting tabulator characters before the index
1444 // (also index value -1 returns with 0)
1445 static sal_Int32
lcl_getLevel(OUString
& sText
, sal_Int32 nIdx
)
1448 while ( nIdx
-- > 0 && sText
[nIdx
] == '\t' )
1455 bool SwTransferable::Paste(SwWrtShell
& rSh
, TransferableDataHelper
& rData
, RndStdIds nAnchorType
, bool bIgnoreComments
, PasteTableType ePasteTable
)
1457 SwPasteContext
aPasteContext(rSh
);
1459 sal_uInt8 nAction
=0;
1460 SotExchangeDest nDestination
= SwTransferable::GetSotDestination( rSh
);
1461 SotClipboardFormatId nFormat
= SotClipboardFormatId::NONE
;
1462 SotExchangeActionFlags nActionFlags
= SotExchangeActionFlags::NONE
;
1463 bool bSingleCellTable
= false;
1465 if( GetSwTransferable( rData
) )
1467 nAction
= EXCHG_OUT_ACTION_INSERT_PRIVATE
;
1471 sal_uInt16 nSourceOptions
=
1472 (( SotExchangeDest::DOC_TEXTFRAME
== nDestination
||
1473 SotExchangeDest::SWDOC_FREE_AREA
== nDestination
||
1474 SotExchangeDest::DOC_TEXTFRAME_WEB
== nDestination
||
1475 SotExchangeDest::SWDOC_FREE_AREA_WEB
== nDestination
)
1476 ? EXCHG_IN_ACTION_COPY
1477 : EXCHG_IN_ACTION_MOVE
);
1478 uno::Reference
<XTransferable
> xTransferable( rData
.GetXTransferable() );
1479 sal_uInt8 nEventAction
;
1480 nAction
= SotExchange::GetExchangeAction(
1481 rData
.GetDataFlavorExVector(),
1483 nSourceOptions
, /* ?? */
1484 EXCHG_IN_ACTION_DEFAULT
, /* ?? */
1485 nFormat
, nEventAction
, SotClipboardFormatId::NONE
,
1486 lcl_getTransferPointer ( xTransferable
),
1490 // when HTML is just an image don't generate new section
1491 if (rData
.HasFormat(SotClipboardFormatId::HTML_SIMPLE
) && rData
.HasFormat(SotClipboardFormatId::HTML_NO_COMMENT
)
1492 && rData
.HasFormat(SotClipboardFormatId::BITMAP
) && nFormat
== SotClipboardFormatId::FILE_LIST
)
1493 nFormat
= SotClipboardFormatId::BITMAP
;
1495 // tdf#37223 avoid non-native insertion of Calc worksheets in the following cases:
1496 // content of 1-cell worksheets are inserted as simple text using RTF format,
1497 // bigger worksheets within native (Writer) table cells are inserted as native tables,
1498 // ie. cell by cell instead of embedding the worksheet in a single cell of the Writer table
1499 if ( EXCHG_IN_ACTION_COPY
== nAction
&& ( rData
.HasFormat( SotClipboardFormatId::SYLK
) ||
1500 rData
.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS
) ) )
1502 // is it a 1-cell worksheet?
1504 if( rData
.GetString( SotClipboardFormatId::STRING
, aExpand
))
1506 const sal_Int32 nNewlines
{comphelper::string::getTokenCount(aExpand
, '\n')};
1507 const sal_Int32 nRows
= nNewlines
? nNewlines
-1 : 0;
1510 const sal_Int32 nCols
= comphelper::string::getTokenCount(o3tl::getToken(aExpand
, 0, '\n'), '\t');
1512 bSingleCellTable
= true;
1516 // convert the worksheet to a temporary native table using HTML format, and copy that into the original native table
1517 if (!bSingleCellTable
&& rData
.HasFormat( SotClipboardFormatId::HTML
) &&
1518 SwDoc::IsInTable(rSh
.GetCursor()->GetPointNode()) != nullptr && rSh
.DoesUndo())
1520 SfxDispatcher
* pDispatch
= rSh
.GetView().GetViewFrame().GetDispatcher();
1521 sal_uInt32 nLevel
= 0;
1523 // within Writer table cells, inserting worksheets using HTML format results only plain text, not a native table,
1524 // so remove all outer nested tables temporary to get a working insertion point
1525 // (RTF format has no such problem, but that inserts the hidden rows of the original Calc worksheet, too)
1527 // For this, switch off change tracking temporarily, if needed
1528 RedlineFlags eOld
= rSh
.GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags();
1529 if ( eOld
& RedlineFlags::On
)
1530 rSh
.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eOld
& ~RedlineFlags::On
);
1532 OUString sPreviousTableName
;
1535 // tdf#152245 add a limit to the loop, if it's not possible to delete the table
1536 const SwTableNode
* pNode
= rSh
.GetCursor()->GetPointNode().FindTableNode();
1537 const OUString sTableName
= pNode
->GetTable().GetFrameFormat()->GetName();
1538 if ( sTableName
== sPreviousTableName
)
1540 sPreviousTableName
= sTableName
;
1541 // insert a random character to redo the place of the insertion at the end
1542 pDispatch
->Execute(FN_INSERT_NNBSP
, SfxCallMode::SYNCHRON
);
1543 pDispatch
->Execute(FN_TABLE_DELETE_TABLE
, SfxCallMode::SYNCHRON
);
1545 } while (SwDoc::IsInTable(rSh
.GetCursor()->GetPointNode()) != nullptr);
1547 // restore change tracking settings
1548 if ( eOld
& RedlineFlags::On
)
1549 rSh
.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eOld
);
1551 if ( SwTransferable::PasteData( rData
, rSh
, EXCHG_OUT_ACTION_INSERT_STRING
, nActionFlags
, SotClipboardFormatId::HTML
,
1552 nDestination
, false, false, nullptr, 0, false, nAnchorType
, bIgnoreComments
, &aPasteContext
, ePasteTable
) )
1554 bool bFoundTemporaryTable
= false;
1555 pDispatch
->Execute(FN_LINE_UP
, SfxCallMode::SYNCHRON
);
1556 if (SwDoc::IsInTable(rSh
.GetCursor()->GetPointNode()) != nullptr)
1558 bFoundTemporaryTable
= true;
1559 pDispatch
->Execute(FN_TABLE_SELECT_ALL
, SfxCallMode::SYNCHRON
);
1560 pDispatch
->Execute(SID_COPY
, SfxCallMode::SYNCHRON
);
1562 for(sal_uInt32 a
= 0; a
< 1 + (nLevel
* 2); a
++)
1563 pDispatch
->Execute(SID_UNDO
, SfxCallMode::SYNCHRON
);
1564 // clipboard content hasn't changed (limit potential infinite
1565 // recursion with the same non-native table, as was in tdf#138688)
1566 if (!bFoundTemporaryTable
)
1568 if (ePasteTable
== PasteTableType::PASTE_TABLE
)
1569 pDispatch
->Execute(FN_PASTE_NESTED_TABLE
, SfxCallMode::SYNCHRON
);
1570 else if (ePasteTable
== PasteTableType::PASTE_ROW
)
1571 pDispatch
->Execute(FN_TABLE_PASTE_ROW_BEFORE
, SfxCallMode::SYNCHRON
);
1572 else if (ePasteTable
== PasteTableType::PASTE_COLUMN
)
1573 pDispatch
->Execute(FN_TABLE_PASTE_COL_BEFORE
, SfxCallMode::SYNCHRON
);
1575 pDispatch
->Execute(SID_PASTE
, SfxCallMode::SYNCHRON
);
1578 for(sal_uInt32 a
= 0; a
< (nLevel
* 2); a
++)
1579 pDispatch
->Execute(SID_UNDO
, SfxCallMode::SYNCHRON
);
1583 // insert clipboard content as new table rows/columns before the actual row/column instead of overwriting it
1584 else if ( (rSh
.GetTableInsertMode() != SwTable::SEARCH_NONE
|| ePasteTable
== PasteTableType::PASTE_ROW
|| ePasteTable
== PasteTableType::PASTE_COLUMN
) &&
1585 rData
.HasFormat( SotClipboardFormatId::HTML
) &&
1586 SwDoc::IsInTable(rSh
.GetCursor()->GetPointNode()) != nullptr )
1590 bool bRowMode
= rSh
.GetTableInsertMode() == SwTable::SEARCH_ROW
|| ePasteTable
== PasteTableType::PASTE_ROW
;
1591 if( rData
.GetString( SotClipboardFormatId::HTML
, aExpand
) && (nIdx
= aExpand
.indexOf("<table")) > -1 )
1593 // calculate table row/column count by analysing indentation of the HTML table extract
1595 // calculate indentation level of <table>, which is the base of the next calculations
1596 // (tdf#148791 table alignment can enlarge it using first level <center>, <div> or <dl>)
1597 sal_Int32 nTableLevel
= lcl_getLevel(aExpand
, nIdx
);
1598 // table rows repeated heading use extra indentation, too:
1599 // <thead> is always used here, and the first table with <thead> is not nested,
1600 // if its indentation level is greater only by 1, than indentation level of the table
1601 bool bShifted
= lcl_getLevel(aExpand
, aExpand
.indexOf("<thead")) == nTableLevel
+ 1;
1602 // calculate count of selected rows or columns
1603 sal_Int32 nSelectedRowsOrCols
= 0;
1604 const OUString sSearchRowOrCol
= bRowMode
? OUString("</tr>") : OUString("<col ");
1605 while((nIdx
= aExpand
.indexOf(sSearchRowOrCol
, nIdx
)) > -1)
1607 // skip rows/columns of nested tables, based on HTML indentation
1608 if ( lcl_getLevel(aExpand
, nIdx
) == nTableLevel
+ (bShifted
? 2 : 1) &&
1609 // skip also strange hidden empty rows <tr></tr>
1610 !aExpand
.match("<tr></tr>", nIdx
- 4) )
1612 ++nSelectedRowsOrCols
;
1616 // are we at the beginning of the cell?
1617 bool bStartTableBoxNode
=
1618 // first paragraph of the cell?
1619 rSh
.GetCursor()->GetPointNode().GetIndex() == rSh
.GetCursor()->GetPointNode().FindTableBoxStartNode()->GetIndex()+1 &&
1620 // beginning of the paragraph?
1621 !rSh
.GetCursor()->GetPoint()->GetContentIndex();
1622 SfxDispatcher
* pDispatch
= rSh
.GetView().GetViewFrame().GetDispatcher();
1624 // go start of the cell
1625 if (!bStartTableBoxNode
)
1626 pDispatch
->Execute(FN_START_OF_DOCUMENT
, SfxCallMode::SYNCHRON
);
1628 // store cursor position in row mode
1629 ::sw::mark::IMark
* pMark
= (!bRowMode
|| nSelectedRowsOrCols
== 0) ? nullptr : rSh
.SetBookmark(
1632 IDocumentMarkAccess::MarkType::UNO_BOOKMARK
);
1634 // add a new empty row/column before the actual table row/column and go there
1635 const sal_uInt16 nDispatchSlot
= bRowMode
? FN_TABLE_INSERT_ROW_BEFORE
: FN_TABLE_INSERT_COL_BEFORE
;
1636 pDispatch
->Execute(nDispatchSlot
, SfxCallMode::SYNCHRON
);
1637 pDispatch
->Execute(bRowMode
? FN_LINE_UP
: FN_CHAR_LEFT
, SfxCallMode::SYNCHRON
);
1639 // add the other new empty rows/columns after the actual table row/column
1640 if ( nSelectedRowsOrCols
> 1 )
1642 SfxInt16Item
aCountItem( nDispatchSlot
, nSelectedRowsOrCols
-1 );
1643 SfxBoolItem
aAfter( FN_PARAM_INSERT_AFTER
, true );
1644 pDispatch
->ExecuteList(nDispatchSlot
,
1645 SfxCallMode::SYNCHRON
|SfxCallMode::RECORD
,
1646 { &aCountItem
, &aAfter
});
1650 bool bResult
= SwTransferable::PasteData( rData
, rSh
, nAction
, nActionFlags
, nFormat
,
1651 nDestination
, false, false, nullptr, 0, false, nAnchorType
, bIgnoreComments
, &aPasteContext
);
1653 // restore cursor position
1654 if (pMark
!= nullptr)
1656 rSh
.GotoMark( pMark
);
1657 rSh
.getIDocumentMarkAccess()->deleteMark( pMark
);
1664 // special case for tables from draw application or 1-cell tables
1665 if( EXCHG_OUT_ACTION_INSERT_DRAWOBJ
== nAction
|| bSingleCellTable
)
1667 if( rData
.HasFormat( SotClipboardFormatId::RTF
) )
1669 nAction
= EXCHG_OUT_ACTION_INSERT_STRING
;
1670 nFormat
= SotClipboardFormatId::RTF
;
1672 else if( rData
.HasFormat( SotClipboardFormatId::RICHTEXT
) )
1674 nAction
= EXCHG_OUT_ACTION_INSERT_STRING
;
1675 nFormat
= SotClipboardFormatId::RICHTEXT
;
1679 // Tweak the format if necessary: the source application can be considered in this context,
1680 // while not in sot/ code.
1681 SwTransferable::SelectPasteFormat(rData
, nAction
, nFormat
);
1683 collectUIInformation("PASTE", "parameter");
1685 return EXCHG_INOUT_ACTION_NONE
!= nAction
&&
1686 SwTransferable::PasteData( rData
, rSh
, nAction
, nActionFlags
, nFormat
,
1687 nDestination
, false, false, nullptr, 0, false, nAnchorType
, bIgnoreComments
, &aPasteContext
, ePasteTable
);
1690 bool SwTransferable::PasteData( TransferableDataHelper
& rData
,
1691 SwWrtShell
& rSh
, sal_uInt8 nAction
, SotExchangeActionFlags nActionFlags
,
1692 SotClipboardFormatId nFormat
,
1693 SotExchangeDest nDestination
, bool bIsPasteFormat
,
1695 const Point
* pPt
, sal_Int8 nDropAction
,
1696 bool bPasteSelection
, RndStdIds nAnchorType
,
1697 bool bIgnoreComments
,
1698 SwPasteContext
* pContext
,
1699 PasteTableType ePasteTable
)
1701 SwWait
aWait( *rSh
.GetView().GetDocShell(), false );
1702 std::unique_ptr
<SwTrnsfrActionAndUndo
, o3tl::default_delete
<SwTrnsfrActionAndUndo
>> pAction
;
1703 SwModule
* pMod
= SW_MOD();
1706 bool bCallAutoCaption
= false;
1711 if( bPasteSelection
? !pMod
->m_pXSelection
: !pMod
->m_pDragDrop
)
1713 switch( nDestination
)
1715 case SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP
:
1716 case SotExchangeDest::DOC_LNKD_GRAPHOBJ
:
1717 case SotExchangeDest::DOC_GRAPH_W_IMAP
:
1718 case SotExchangeDest::DOC_GRAPHOBJ
:
1719 case SotExchangeDest::DOC_OLEOBJ
:
1720 case SotExchangeDest::DOC_DRAWOBJ
:
1721 case SotExchangeDest::DOC_URLBUTTON
:
1722 case SotExchangeDest::DOC_GROUPOBJ
:
1723 // select frames/objects
1724 SwTransferable::SetSelInShell( rSh
, true, pPt
);
1728 SwTransferable::SetSelInShell( rSh
, false, pPt
);
1733 else if( ( !GetSwTransferable( rData
) || bIsPasteFormat
) &&
1734 !rSh
.IsTableMode() && rSh
.HasSelection() )
1736 // then delete the selections
1738 //don't delete selected content
1739 // - at table-selection
1740 // - at ReRead of a graphic/DDEData
1741 // - at D&D, for the right selection was taken care of
1743 bool bDelSel
= false;
1744 switch( nDestination
)
1746 case SotExchangeDest::DOC_TEXTFRAME
:
1747 case SotExchangeDest::SWDOC_FREE_AREA
:
1748 case SotExchangeDest::DOC_TEXTFRAME_WEB
:
1749 case SotExchangeDest::SWDOC_FREE_AREA_WEB
:
1758 pAction
.reset(new SwTrnsfrActionAndUndo(&rSh
, true, pContext
));
1761 SwTransferable
*pTrans
=nullptr, *pTunneledTrans
=GetSwTransferable( rData
);
1763 // check for private drop
1764 bool bPrivateDrop(pPt
);
1767 if (bPasteSelection
)
1768 pTrans
= pMod
->m_pXSelection
;
1770 pTrans
= pMod
->m_pDragDrop
;
1771 bPrivateDrop
= nullptr != pTrans
;
1773 bool bNeedToSelectBeforePaste(false);
1775 if(bPrivateDrop
&& DND_ACTION_LINK
== nDropAction
)
1777 // internal drop on object, suppress bPrivateDrop to change internal fill
1778 bPrivateDrop
= false;
1779 bNeedToSelectBeforePaste
= true;
1782 if(bPrivateDrop
&& pPt
&& DND_ACTION_MOVE
== nDropAction
)
1784 // check if dragged over a useful target. If yes, use as content exchange
1785 // drop as if from external
1786 const SwFrameFormat
* pSwFrameFormat
= rSh
.GetFormatFromObj(*pPt
);
1788 if(dynamic_cast< const SwDrawFrameFormat
* >(pSwFrameFormat
))
1790 bPrivateDrop
= false;
1791 bNeedToSelectBeforePaste
= true;
1797 // then internal Drag & Drop or XSelection
1798 bRet
= pTrans
->PrivateDrop( rSh
, *pPt
, DND_ACTION_MOVE
== nDropAction
,
1801 else if( !pPt
&& pTunneledTrans
&&
1802 EXCHG_OUT_ACTION_INSERT_PRIVATE
== nAction
)
1804 // then internal paste
1805 bRet
= pTunneledTrans
->PrivatePaste(rSh
, pContext
, ePasteTable
);
1807 else if( EXCHG_INOUT_ACTION_NONE
!= nAction
)
1811 pAction
.reset(new SwTrnsfrActionAndUndo( &rSh
));
1814 // in Drag&Drop MessageBoxes must not be showed
1815 bool bMsg
= nullptr == pPt
;
1817 // delete selections
1821 case EXCHG_OUT_ACTION_INSERT_PRIVATE
:
1822 OSL_ENSURE( pPt
, "EXCHG_OUT_ACTION_INSERT_PRIVATE: what should happen here?" );
1825 case EXCHG_OUT_ACTION_MOVE_PRIVATE
:
1826 OSL_ENSURE( pPt
, "EXCHG_OUT_ACTION_MOVE_PRIVATE: what should happen here?" );
1829 case EXCHG_IN_ACTION_MOVE
:
1830 case EXCHG_IN_ACTION_COPY
:
1831 case EXCHG_IN_ACTION_LINK
:
1832 case EXCHG_OUT_ACTION_INSERT_HTML
:
1833 case EXCHG_OUT_ACTION_INSERT_STRING
:
1834 case EXCHG_OUT_ACTION_INSERT_IMAGEMAP
:
1835 case EXCHG_OUT_ACTION_REPLACE_IMAGEMAP
:
1837 // then we have to use the format
1840 case SotClipboardFormatId::DRAWING
:
1841 bRet
= SwTransferable::PasteSdrFormat( rData
, rSh
,
1842 SwPasteSdr::Insert
, pPt
,
1843 nActionFlags
, bNeedToSelectBeforePaste
);
1846 case SotClipboardFormatId::HTML
:
1847 case SotClipboardFormatId::HTML_SIMPLE
:
1848 case SotClipboardFormatId::HTML_NO_COMMENT
:
1849 case SotClipboardFormatId::RTF
:
1850 case SotClipboardFormatId::RICHTEXT
:
1851 case SotClipboardFormatId::STRING
:
1852 bRet
= SwTransferable::PasteFileContent( rData
, rSh
,
1853 nFormat
, bMsg
, bIgnoreComments
);
1856 case SotClipboardFormatId::NETSCAPE_BOOKMARK
:
1859 if( rData
.GetINetBookmark( nFormat
, aBkmk
) )
1861 SwFormatINetFormat
aFormat( aBkmk
.GetURL(), OUString() );
1862 rSh
.InsertURL( aFormat
, aBkmk
.GetDescription() );
1868 case SotClipboardFormatId::SD_OLE
:
1869 bRet
= SwTransferable::PasteOLE( rData
, rSh
, nFormat
,
1870 nActionFlags
, bMsg
);
1873 case SotClipboardFormatId::SVIM
:
1874 bRet
= SwTransferable::PasteImageMap( rData
, rSh
);
1877 case SotClipboardFormatId::SVXB
:
1878 case SotClipboardFormatId::BITMAP
:
1879 case SotClipboardFormatId::PNG
:
1880 case SotClipboardFormatId::GDIMETAFILE
:
1881 bRet
= SwTransferable::PasteGrf( rData
, rSh
, nFormat
,
1882 SwPasteSdr::Insert
,pPt
,
1883 nActionFlags
, nDropAction
, bNeedToSelectBeforePaste
);
1886 case SotClipboardFormatId::XFORMS
:
1887 case SotClipboardFormatId::SBA_FIELDDATAEXCHANGE
:
1888 case SotClipboardFormatId::SBA_DATAEXCHANGE
:
1889 case SotClipboardFormatId::SBA_CTRLDATAEXCHANGE
:
1890 bRet
= SwTransferable::PasteDBData( rData
, rSh
, nFormat
,
1891 EXCHG_IN_ACTION_LINK
== nAction
,
1895 case SotClipboardFormatId::SIMPLE_FILE
:
1896 bRet
= SwTransferable::PasteFileName( rData
, rSh
, nFormat
,
1897 ( EXCHG_IN_ACTION_MOVE
== nAction
1898 ? SwPasteSdr::Replace
1899 : EXCHG_IN_ACTION_LINK
== nAction
1900 ? SwPasteSdr::SetAttr
1901 : SwPasteSdr::Insert
),
1902 pPt
, nActionFlags
, nullptr );
1905 case SotClipboardFormatId::FILE_LIST
:
1906 // then insert as graphics only
1907 bRet
= SwTransferable::PasteFileList( rData
, rSh
,
1908 EXCHG_IN_ACTION_LINK
== nAction
,
1912 case SotClipboardFormatId::SONLK
:
1915 NaviContentBookmark aBkmk
;
1916 if( aBkmk
.Paste( rData
) )
1920 switch(aBkmk
.GetDefaultDragType())
1922 case RegionMode::NONE
: nAction
= EXCHG_IN_ACTION_COPY
; break;
1923 case RegionMode::EMBEDDED
: nAction
= EXCHG_IN_ACTION_MOVE
; break;
1924 case RegionMode::LINK
: nAction
= EXCHG_IN_ACTION_LINK
; break;
1927 rSh
.NavigatorPaste( aBkmk
, nAction
);
1933 case SotClipboardFormatId::INET_IMAGE
:
1934 case SotClipboardFormatId::NETSCAPE_IMAGE
:
1935 bRet
= SwTransferable::PasteTargetURL( rData
, rSh
,
1941 OSL_ENSURE( pPt
, "unknown format" );
1945 case EXCHG_OUT_ACTION_INSERT_FILE
:
1947 bool graphicInserted
;
1948 bRet
= SwTransferable::PasteFileName( rData
, rSh
, nFormat
,
1949 SwPasteSdr::Insert
, pPt
,
1952 if( graphicInserted
)
1953 bCallAutoCaption
= true;
1957 case EXCHG_OUT_ACTION_INSERT_OLE
:
1958 bRet
= SwTransferable::PasteOLE( rData
, rSh
, nFormat
,
1959 nActionFlags
,bMsg
);
1962 case EXCHG_OUT_ACTION_INSERT_DDE
:
1964 bool bReRead
= 0 != CNT_HasGrf( rSh
.GetCntType() );
1965 bRet
= SwTransferable::PasteDDE( rData
, rSh
, bReRead
, bMsg
);
1969 case EXCHG_OUT_ACTION_INSERT_HYPERLINK
:
1971 OUString sURL
, sDesc
;
1972 if( SotClipboardFormatId::SIMPLE_FILE
== nFormat
)
1974 if( rData
.GetString( nFormat
, sURL
) && !sURL
.isEmpty() )
1976 SwTransferable::CheckForURLOrLNKFile( rData
, sURL
, &sDesc
);
1977 if( sDesc
.isEmpty() )
1985 if( rData
.GetINetBookmark( nFormat
, aBkmk
) )
1987 sURL
= aBkmk
.GetURL();
1988 sDesc
= aBkmk
.GetDescription();
1995 SwFormatINetFormat
aFormat( sURL
, OUString() );
1996 rSh
.InsertURL( aFormat
, sDesc
);
2001 case EXCHG_OUT_ACTION_GET_ATTRIBUTES
:
2004 case SotClipboardFormatId::DRAWING
:
2005 bRet
= SwTransferable::PasteSdrFormat( rData
, rSh
,
2006 SwPasteSdr::SetAttr
, pPt
,
2007 nActionFlags
, bNeedToSelectBeforePaste
);
2009 case SotClipboardFormatId::SVXB
:
2010 case SotClipboardFormatId::GDIMETAFILE
:
2011 case SotClipboardFormatId::BITMAP
:
2012 case SotClipboardFormatId::PNG
:
2013 case SotClipboardFormatId::NETSCAPE_BOOKMARK
:
2014 case SotClipboardFormatId::SIMPLE_FILE
:
2015 case SotClipboardFormatId::FILEGRPDESCRIPTOR
:
2016 case SotClipboardFormatId::UNIFORMRESOURCELOCATOR
:
2017 bRet
= SwTransferable::PasteGrf( rData
, rSh
, nFormat
,
2018 SwPasteSdr::SetAttr
, pPt
,
2019 nActionFlags
, nDropAction
, bNeedToSelectBeforePaste
);
2022 OSL_FAIL( "unknown format" );
2027 case EXCHG_OUT_ACTION_INSERT_DRAWOBJ
:
2028 bRet
= SwTransferable::PasteSdrFormat( rData
, rSh
,
2029 SwPasteSdr::Insert
, pPt
,
2030 nActionFlags
, bNeedToSelectBeforePaste
);
2032 case EXCHG_OUT_ACTION_INSERT_SVXB
:
2033 case EXCHG_OUT_ACTION_INSERT_GDIMETAFILE
:
2034 case EXCHG_OUT_ACTION_INSERT_BITMAP
:
2035 case EXCHG_OUT_ACTION_INSERT_GRAPH
:
2036 bRet
= SwTransferable::PasteGrf( rData
, rSh
, nFormat
,
2037 SwPasteSdr::Insert
, pPt
,
2038 nActionFlags
, nDropAction
, bNeedToSelectBeforePaste
, nAnchorType
);
2041 case EXCHG_OUT_ACTION_REPLACE_DRAWOBJ
:
2042 bRet
= SwTransferable::PasteSdrFormat( rData
, rSh
,
2043 SwPasteSdr::Replace
, pPt
,
2044 nActionFlags
, bNeedToSelectBeforePaste
);
2047 case EXCHG_OUT_ACTION_REPLACE_SVXB
:
2048 case EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE
:
2049 case EXCHG_OUT_ACTION_REPLACE_BITMAP
:
2050 case EXCHG_OUT_ACTION_REPLACE_GRAPH
:
2051 bRet
= SwTransferable::PasteGrf( rData
, rSh
, nFormat
,
2052 SwPasteSdr::Replace
,pPt
,
2053 nActionFlags
, nDropAction
, bNeedToSelectBeforePaste
);
2056 case EXCHG_OUT_ACTION_INSERT_INTERACTIVE
:
2057 bRet
= SwTransferable::PasteAsHyperlink( rData
, rSh
, nFormat
);
2061 OSL_FAIL("unknown action" );
2065 if( !bPasteSelection
&& rSh
.IsFrameSelected() )
2067 rSh
.EnterSelFrameMode();
2068 //force ::SelectShell
2069 rSh
.GetView().StopShellTimer();
2073 if( bCallAutoCaption
)
2074 rSh
.GetView().AutoCaption( GRAPHIC_CAP
);
2079 SotExchangeDest
SwTransferable::GetSotDestination( const SwWrtShell
& rSh
)
2081 SotExchangeDest nRet
= SotExchangeDest::NONE
;
2083 ObjCntType eOType
= rSh
.GetObjCntTypeOfSelection();
2090 bIMap
= nullptr != rSh
.GetFlyFrameFormat()->GetURL().GetMap();
2092 rSh
.GetGrfNms( &aDummy
, nullptr );
2093 bLink
= !aDummy
.isEmpty();
2095 if( bLink
&& bIMap
)
2096 nRet
= SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP
;
2098 nRet
= SotExchangeDest::DOC_LNKD_GRAPHOBJ
;
2100 nRet
= SotExchangeDest::DOC_GRAPH_W_IMAP
;
2102 nRet
= SotExchangeDest::DOC_GRAPHOBJ
;
2107 if( dynamic_cast< const SwWebDocShell
*>( rSh
.GetView().GetDocShell() ) != nullptr )
2108 nRet
= SotExchangeDest::DOC_TEXTFRAME_WEB
;
2110 nRet
= SotExchangeDest::DOC_TEXTFRAME
;
2112 case OBJCNT_OLE
: nRet
= SotExchangeDest::DOC_OLEOBJ
; break;
2114 case OBJCNT_CONTROL
: /* no Action avail */
2115 case OBJCNT_SIMPLE
: nRet
= SotExchangeDest::DOC_DRAWOBJ
; break;
2116 case OBJCNT_URLBUTTON
: nRet
= SotExchangeDest::DOC_URLBUTTON
; break;
2117 case OBJCNT_GROUPOBJ
: nRet
= SotExchangeDest::DOC_GROUPOBJ
; break;
2119 // what do we do at multiple selections???
2122 if( dynamic_cast< const SwWebDocShell
*>( rSh
.GetView().GetDocShell() ) != nullptr )
2123 nRet
= SotExchangeDest::SWDOC_FREE_AREA_WEB
;
2125 nRet
= SotExchangeDest::SWDOC_FREE_AREA
;
2132 bool SwTransferable::PasteFileContent( const TransferableDataHelper
& rData
,
2133 SwWrtShell
& rSh
, SotClipboardFormatId nFormat
, bool bMsg
, bool bIgnoreComments
)
2135 TranslateId pResId
= STR_CLPBRD_FORMAT_ERROR
;
2138 MSE40HTMLClipFormatObj aMSE40ClpObj
;
2140 tools::SvRef
<SotTempStream
> xStrm
;
2141 SvStream
* pStream
= nullptr;
2142 Reader
* pRead
= nullptr;
2146 case SotClipboardFormatId::STRING
:
2149 if( rData
.GetString( nFormat
, sData
) )
2151 pStream
= new SvMemoryStream( const_cast<sal_Unicode
*>(sData
.getStr()),
2152 sData
.getLength() * sizeof( sal_Unicode
),
2154 #ifdef OSL_BIGENDIAN
2155 pStream
->SetEndian( SvStreamEndian::BIG
);
2157 pStream
->SetEndian( SvStreamEndian::LITTLE
);
2160 SwAsciiOptions aAOpt
;
2161 aAOpt
.SetCharSet( RTL_TEXTENCODING_UCS2
);
2162 pRead
->GetReaderOpt().SetASCIIOpts( aAOpt
);
2166 [[fallthrough
]]; // because then test if we get a stream
2169 if( rData
.GetSotStorageStream( nFormat
, xStrm
) )
2171 if( ( SotClipboardFormatId::HTML_SIMPLE
== nFormat
) ||
2172 ( SotClipboardFormatId::HTML_NO_COMMENT
== nFormat
) )
2174 pStream
= aMSE40ClpObj
.IsValid( *xStrm
);
2176 pRead
->SetReadUTF8( true );
2179 ( nFormat
== SotClipboardFormatId::HTML_NO_COMMENT
);
2180 pRead
->SetIgnoreHTMLComments( bNoComments
);
2184 pStream
= xStrm
.get();
2185 if( SotClipboardFormatId::RTF
== nFormat
|| SotClipboardFormatId::RICHTEXT
== nFormat
)
2186 pRead
= SwReaderWriter::GetRtfReader();
2190 pRead
->SetReadUTF8( true );
2197 if( pStream
&& pRead
)
2199 Link
<LinkParamNone
*,void> aOldLink( rSh
.GetChgLnk() );
2200 rSh
.SetChgLnk( Link
<LinkParamNone
*,void>() );
2202 const SwPosition
& rInsPos
= *rSh
.GetCursor()->Start();
2203 SwReader
aReader(*pStream
, OUString(), OUString(), *rSh
.GetCursor());
2204 rSh
.SaveTableBoxContent( &rInsPos
);
2206 if (bIgnoreComments
)
2207 pRead
->SetIgnoreHTMLComments(true);
2209 if( aReader
.Read( *pRead
).IsError() )
2210 pResId
= STR_ERROR_CLPBRD_READ
;
2213 pResId
= TranslateId();
2217 rSh
.SetChgLnk( aOldLink
);
2222 pResId
= STR_CLPBRD_FORMAT_ERROR
;
2224 // Exist a SvMemoryStream? (data in the OUString and xStrm is empty)
2225 if( pStream
&& !xStrm
.is() )
2230 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
2231 VclMessageType::Info
, VclButtonsType::Ok
,
2238 bool SwTransferable::PasteOLE( TransferableDataHelper
& rData
, SwWrtShell
& rSh
,
2239 SotClipboardFormatId nFormat
, SotExchangeActionFlags nActionFlags
, bool bMsg
)
2242 TransferableObjectDescriptor aObjDesc
;
2243 uno::Reference
< io::XInputStream
> xStrm
;
2244 uno::Reference
< embed::XStorage
> xStore
;
2245 Reader
* pRead
= nullptr;
2247 // Get the preferred format
2248 SotClipboardFormatId nId
;
2249 if( rData
.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ
) )
2250 nId
= SotClipboardFormatId::EMBEDDED_OBJ
;
2251 else if( rData
.HasFormat( SotClipboardFormatId::EMBED_SOURCE
) &&
2252 rData
.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
))
2253 nId
= SotClipboardFormatId::EMBED_SOURCE
;
2255 nId
= SotClipboardFormatId::NONE
;
2257 if (nId
!= SotClipboardFormatId::NONE
)
2259 SwDocShell
* pDocSh
= rSh
.GetDoc()->GetDocShell();
2260 xStrm
= rData
.GetInputStream(nId
, SfxObjectShell::CreateShellID(pDocSh
));
2265 // if there is an embedded object, first try if it's a writer object
2266 // this will be inserted into the document by using a Reader
2269 xStore
= comphelper::OStorageHelper::GetStorageFromInputStream( xStrm
);
2270 switch( SotStorage::GetFormatID( xStore
) )
2272 case SotClipboardFormatId::STARWRITER_60
:
2273 case SotClipboardFormatId::STARWRITERWEB_60
:
2274 case SotClipboardFormatId::STARWRITERGLOB_60
:
2275 case SotClipboardFormatId::STARWRITER_8
:
2276 case SotClipboardFormatId::STARWRITERWEB_8
:
2277 case SotClipboardFormatId::STARWRITERGLOB_8
:
2286 catch (const uno::Exception
&)
2293 catch (const uno::Exception
&)
2295 // it wasn't a storage, but maybe it's a useful stream
2301 SwPaM
&rPAM
= *rSh
.GetCursor();
2302 SwReader
aReader(xStore
, OUString(), rPAM
);
2303 if( ! aReader
.Read( *pRead
).IsError() )
2307 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
2308 VclMessageType::Info
, VclButtonsType::Ok
,
2309 SwResId(STR_ERROR_CLPBRD_READ
)));
2315 // temporary storage until the object is inserted
2316 uno::Reference
< embed::XStorage
> xTmpStor
;
2317 uno::Reference
< embed::XEmbeddedObject
> xObj
;
2319 comphelper::EmbeddedObjectContainer aCnt
;
2323 if ( !rData
.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR
, aObjDesc
) )
2325 OSL_ENSURE( !xStrm
.is(), "An object without descriptor in clipboard!");
2330 if( rData
.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR_OLE
) && rData
.GetTransferableObjectDescriptor( nFormat
, aObjDesc
) )
2332 xStrm
= rData
.GetInputStream(SotClipboardFormatId::EMBED_SOURCE_OLE
, OUString());
2334 xStrm
= rData
.GetInputStream(SotClipboardFormatId::EMBEDDED_OBJ_OLE
, OUString());
2338 // This is MSOLE object that should be created by direct using of system clipboard
2341 xTmpStor
= ::comphelper::OStorageHelper::GetTemporaryStorage();
2342 uno::Reference
< embed::XEmbedObjectClipboardCreator
> xClipboardCreator
=
2343 embed::MSOLEObjectSystemCreator::create( ::comphelper::getProcessComponentContext() );
2345 embed::InsertedObjectInfo aInfo
= xClipboardCreator
->createInstanceInitFromClipboard(
2348 uno::Sequence
< beans::PropertyValue
>() );
2350 // TODO/LATER: in future InsertedObjectInfo will be used to get container related information
2351 // for example whether the object should be an iconified one
2352 xObj
= aInfo
.Object
;
2354 catch (const uno::Exception
&)
2359 else if (rData
.HasFormat(SotClipboardFormatId::SIMPLE_FILE
))
2362 if (rData
.GetString(nFormat
, sFile
) && !sFile
.isEmpty())
2364 // Copied from sd::View::DropInsertFileHdl
2365 uno::Sequence
< beans::PropertyValue
> aMedium
{ comphelper::makePropertyValue(
2367 SwDocShell
* pDocSh
= rSh
.GetDoc()->GetDocShell();
2368 xObj
= pDocSh
->GetEmbeddedObjectContainer().InsertEmbeddedObject(aMedium
, aName
);
2373 if ( xStrm
.is() && !xObj
.is() )
2374 xObj
= aCnt
.InsertEmbeddedObject( xStrm
, aName
);
2378 svt::EmbeddedObjectRef
xObjRef( xObj
, aObjDesc
.mnViewAspect
);
2380 // try to get the replacement image from the clipboard
2382 SotClipboardFormatId nGrFormat
= SotClipboardFormatId::NONE
;
2384 // limit the size of the preview metafile to 100000 actions
2385 GDIMetaFile aMetafile
;
2386 if (rData
.GetGDIMetaFile(SotClipboardFormatId::GDIMETAFILE
, aMetafile
, 100000))
2388 nGrFormat
= SotClipboardFormatId::GDIMETAFILE
;
2389 aGraphic
= aMetafile
;
2392 // insert replacement image ( if there is one ) into the object helper
2393 if ( nGrFormat
!= SotClipboardFormatId::NONE
)
2395 DataFlavor aDataFlavor
;
2396 SotExchange::GetFormatDataFlavor( nGrFormat
, aDataFlavor
);
2397 xObjRef
.SetGraphic( aGraphic
, aDataFlavor
.MimeType
);
2399 else if ( aObjDesc
.mnViewAspect
== embed::Aspects::MSOLE_ICON
)
2401 // it is important to have an icon, let an empty graphic be used
2402 // if no other graphic is provided
2403 // TODO/LATER: in future a default bitmap could be used
2404 MapMode
aMapMode( MapUnit::Map100thMM
);
2405 aGraphic
.SetPrefSize( Size( 2500, 2500 ) );
2406 aGraphic
.SetPrefMapMode( aMapMode
);
2407 xObjRef
.SetGraphic( aGraphic
, OUString() );
2410 //set size. This is a hack because of handing over, size should be
2411 //passed to the InsertOle!!!!!!!!!!
2413 if ( aObjDesc
.mnViewAspect
== embed::Aspects::MSOLE_ICON
)
2415 if( aObjDesc
.maSize
.Width() && aObjDesc
.maSize
.Height() )
2416 aSize
= aObjDesc
.maSize
;
2419 MapMode
aMapMode( MapUnit::Map100thMM
);
2420 aSize
= xObjRef
.GetSize( &aMapMode
);
2423 else if( aObjDesc
.maSize
.Width() && aObjDesc
.maSize
.Height() )
2425 aSize
= aObjDesc
.maSize
; //always 100TH_MM
2426 MapUnit aUnit
= VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj
->getMapUnit( aObjDesc
.mnViewAspect
) );
2427 aSize
= OutputDevice::LogicToLogic(aSize
, MapMode(MapUnit::Map100thMM
), MapMode(aUnit
));
2431 aSz
= xObj
->getVisualAreaSize( aObjDesc
.mnViewAspect
);
2433 catch (const embed::NoVisualAreaSizeException
&)
2435 // in this case the provided size is used
2438 if ( aSz
.Width
!= aSize
.Width() || aSz
.Height
!= aSize
.Height() )
2440 aSz
.Width
= aSize
.Width();
2441 aSz
.Height
= aSize
.Height();
2442 xObj
->setVisualAreaSize( aObjDesc
.mnViewAspect
, aSz
);
2447 // the descriptor contains the wrong object size
2448 // the following call will let the MSOLE objects cache the size if it is possible
2449 // it should be done while the object is running
2452 xObj
->getVisualAreaSize( aObjDesc
.mnViewAspect
);
2454 catch (const uno::Exception
&)
2460 rSh
.InsertOleObject( xObjRef
);
2463 if( bRet
&& ( nActionFlags
& SotExchangeActionFlags::InsertTargetUrl
) )
2464 SwTransferable::PasteTargetURL( rData
, rSh
, SwPasteSdr::NONE
, nullptr, false );
2466 // let the object be unloaded if possible
2467 SwOLEObj::UnloadObject( xObj
, rSh
.GetDoc(), embed::Aspects::MSOLE_CONTENT
);
2473 bool SwTransferable::PasteTargetURL( const TransferableDataHelper
& rData
,
2474 SwWrtShell
& rSh
, SwPasteSdr nAction
,
2475 const Point
* pPt
, bool bInsertGRF
)
2479 if( ( rData
.HasFormat( SotClipboardFormatId::INET_IMAGE
) &&
2480 rData
.GetINetImage( SotClipboardFormatId::INET_IMAGE
, aINetImg
)) ||
2481 ( rData
.HasFormat( SotClipboardFormatId::NETSCAPE_IMAGE
) &&
2482 rData
.GetINetImage( SotClipboardFormatId::NETSCAPE_IMAGE
, aINetImg
)) )
2484 if( !aINetImg
.GetImageURL().isEmpty() && bInsertGRF
)
2486 OUString
sURL( aINetImg
.GetImageURL() );
2487 SwTransferable::CheckForURLOrLNKFile( rData
, sURL
);
2489 //!!! check at FileSystem - only then it makes sense to test graphics !!!
2491 GraphicFilter
&rFlt
= GraphicFilter::GetGraphicFilter();
2492 bRet
= ERRCODE_NONE
== GraphicFilter::LoadGraphic(sURL
, OUString(), aGraphic
, &rFlt
);
2496 //Check and Perform rotation if needed
2497 lclCheckAndPerformRotation(aGraphic
);
2501 case SwPasteSdr::Insert
:
2502 SwTransferable::SetSelInShell( rSh
, false, pPt
);
2503 rSh
.InsertGraphic(sURL
, OUString(), aGraphic
);
2506 case SwPasteSdr::Replace
:
2507 if( rSh
.IsObjSelected() )
2509 rSh
.ReplaceSdrObj( sURL
, &aGraphic
);
2510 Point
aPt( pPt
? *pPt
: rSh
.GetCursorDocPos() );
2511 SwTransferable::SetSelInShell( rSh
, true, &aPt
);
2514 rSh
.ReRead(sURL
, OUString(), &aGraphic
);
2517 case SwPasteSdr::SetAttr
:
2518 if( rSh
.IsObjSelected() )
2519 rSh
.Paste( aGraphic
, OUString() );
2520 else if( OBJCNT_GRF
== rSh
.GetObjCntTypeOfSelection() )
2521 rSh
.ReRead(sURL
, OUString(), &aGraphic
);
2524 SwTransferable::SetSelInShell( rSh
, false, pPt
);
2525 rSh
.InsertGraphic(sURL
, OUString(), aGraphic
);
2539 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( rSh
.GetAttrPool() );
2540 rSh
.GetFlyFrameAttr( aSet
);
2541 SwFormatURL
aURL( aSet
.Get( RES_URL
) );
2543 if( aURL
.GetURL() != aINetImg
.GetTargetURL() ||
2544 aURL
.GetTargetFrameName() != aINetImg
.GetTargetFrame() )
2546 aURL
.SetURL( aINetImg
.GetTargetURL(), false );
2547 aURL
.SetTargetFrameName( aINetImg
.GetTargetFrame() );
2549 rSh
.SetFlyFrameAttr( aSet
);
2555 void SwTransferable::SetSelInShell( SwWrtShell
& rSh
, bool bSelectFrame
,
2560 // select frames/objects
2561 if( pPt
&& !rSh
.GetView().GetViewFrame().GetDispatcher()->IsLocked() )
2563 rSh
.GetView().NoRotate();
2564 if( rSh
.SelectObj( *pPt
))
2567 rSh
.EnterSelFrameMode( pPt
);
2568 g_bFrameDrag
= true;
2574 if( rSh
.IsFrameSelected() || rSh
.IsObjSelected() )
2576 rSh
.UnSelectFrame();
2577 rSh
.LeaveSelFrameMode();
2578 rSh
.GetView().GetEditWin().StopInsFrame();
2579 g_bFrameDrag
= false;
2581 else if( rSh
.GetView().GetDrawFuncPtr() )
2582 rSh
.GetView().GetEditWin().StopInsFrame();
2586 rSh
.SwCursorShell::SetCursor( *pPt
, true );
2590 bool SwTransferable::PasteDDE( const TransferableDataHelper
& rData
,
2591 SwWrtShell
& rWrtShell
, bool bReReadGrf
,
2594 // data from Clipboardformat
2595 OUString aApp
, aTopic
, aItem
;
2598 tools::SvRef
<SotTempStream
> xStrm
;
2599 if( !rData
.GetSotStorageStream( SotClipboardFormatId::LINK
, xStrm
))
2601 OSL_ENSURE( false, "DDE Data not found." );
2603 } // report useful error!!
2605 rtl_TextEncoding eEncoding
= osl_getThreadTextEncoding();
2606 aApp
= read_zeroTerminated_uInt8s_ToOUString(*xStrm
, eEncoding
);
2607 aTopic
= read_zeroTerminated_uInt8s_ToOUString(*xStrm
, eEncoding
);
2608 aItem
= read_zeroTerminated_uInt8s_ToOUString(*xStrm
, eEncoding
);
2612 sfx2::MakeLnkName( aCmd
, &aApp
, aTopic
, aItem
);
2614 // do we want to read in a graphic now?
2615 SotClipboardFormatId nFormat
;
2616 if( !rData
.HasFormat( SotClipboardFormatId::RTF
) &&
2617 !rData
.HasFormat( SotClipboardFormatId::RICHTEXT
) &&
2618 !rData
.HasFormat( SotClipboardFormatId::HTML
) &&
2619 !rData
.HasFormat( SotClipboardFormatId::STRING
) &&
2620 (rData
.HasFormat( nFormat
= SotClipboardFormatId::GDIMETAFILE
) ||
2621 rData
.HasFormat( nFormat
= SotClipboardFormatId::BITMAP
)) )
2624 bool bRet
= rData
.GetGraphic( nFormat
, aGrf
);
2627 OUString
sLnkTyp("DDE");
2629 rWrtShell
.ReRead( aCmd
, sLnkTyp
, &aGrf
);
2631 rWrtShell
.InsertGraphic( aCmd
, sLnkTyp
, aGrf
);
2636 SwFieldType
* pTyp
= nullptr;
2640 bool bDoublePaste
= false;
2641 const size_t nSize
= rWrtShell
.GetFieldTypeCount();
2642 const ::utl::TransliterationWrapper
& rColl
= ::GetAppCmpStrIgnore();
2645 aName
= aApp
+ OUString::number( i
);
2646 for( j
= INIT_FLDTYPES
; j
< nSize
; j
++ )
2648 pTyp
= rWrtShell
.GetFieldType( j
);
2649 if( SwFieldIds::Dde
== pTyp
->Which() )
2651 if( rColl
.isEqual( static_cast<SwDDEFieldType
*>(pTyp
)->GetCmd(), aCmd
) &&
2652 SfxLinkUpdateMode::ALWAYS
== static_cast<SwDDEFieldType
*>(pTyp
)->GetType() )
2654 aName
= pTyp
->GetName();
2655 bDoublePaste
= true;
2658 else if( rColl
.isEqual( aName
, pTyp
->GetName() ) )
2666 while( !bDoublePaste
);
2670 SwDDEFieldType
aType( aName
, aCmd
, SfxLinkUpdateMode::ALWAYS
);
2671 pTyp
= rWrtShell
.InsertFieldType( aType
);
2674 SwDDEFieldType
* pDDETyp
= static_cast<SwDDEFieldType
*>(pTyp
);
2677 if( rData
.GetString( SotClipboardFormatId::STRING
, aExpand
))
2679 do { // middle checked loop
2681 const sal_Int32 nNewlines
{comphelper::string::getTokenCount(aExpand
, '\n')};
2682 // When data comes from a spreadsheet, we add a DDE-table
2683 if( !aExpand
.isEmpty() &&
2684 ( rData
.HasFormat( SotClipboardFormatId::SYLK
) ||
2685 rData
.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS
) ) )
2687 sal_Int32 nRows
= nNewlines
? nNewlines
-1 : 0;
2688 if (!aExpand
.endsWith("\n"))
2689 ++nRows
; // last row has no newline, e.g. one single cell
2690 const sal_Int32 nCols
= comphelper::string::getTokenCount(o3tl::getToken(aExpand
, 0, '\n'), '\t');
2692 // don't try to insert tables that are too large for writer
2693 if (nRows
> SAL_MAX_UINT16
|| nCols
> SAL_MAX_UINT16
)
2697 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
2698 VclMessageType::Info
, VclButtonsType::Ok
,
2699 SwResId(STR_TABLE_TOO_LARGE
)));
2706 // at least one column & row must be there
2707 if( !nRows
|| !nCols
)
2711 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
2712 VclMessageType::Info
, VclButtonsType::Ok
,
2713 SwResId(STR_NO_TABLE
)));
2720 rWrtShell
.InsertDDETable(
2721 SwInsertTableOptions( SwInsertTableFlags::SplitLayout
, 1 ), // TODO MULTIHEADER
2722 pDDETyp
, nRows
, nCols
);
2724 else if( nNewlines
> 1 )
2726 // multiple paragraphs -> insert a protected section
2727 if( rWrtShell
.HasSelection() )
2728 rWrtShell
.DelRight();
2730 SwSectionData
aSect( SectionType::DdeLink
, aName
);
2731 aSect
.SetLinkFileName( aCmd
);
2732 aSect
.SetProtectFlag(true);
2733 rWrtShell
.InsertSection( aSect
);
2735 pDDETyp
= nullptr; // remove FieldTypes again
2740 SwDDEField
aSwDDEField( pDDETyp
);
2741 rWrtShell
.InsertField2( aSwDDEField
);
2747 pDDETyp
= nullptr; // remove FieldTypes again
2749 if( !pDDETyp
&& !bDoublePaste
)
2751 // remove FieldType again - error occurred!
2752 for( j
= nSize
; j
>= INIT_FLDTYPES
; --j
)
2753 if( pTyp
== rWrtShell
.GetFieldType( j
) )
2755 rWrtShell
.RemoveFieldType( j
);
2763 bool SwTransferable::PasteSdrFormat( const TransferableDataHelper
& rData
,
2764 SwWrtShell
& rSh
, SwPasteSdr nAction
,
2765 const Point
* pPt
, SotExchangeActionFlags nActionFlags
, bool bNeedToSelectBeforePaste
)
2768 tools::SvRef
<SotTempStream
> xStrm
;
2769 if( rData
.GetSotStorageStream( SotClipboardFormatId::DRAWING
, xStrm
))
2771 xStrm
->SetVersion( SOFFICE_FILEFORMAT_50
);
2773 if(bNeedToSelectBeforePaste
&& pPt
)
2775 // if this is an internal drag, need to set the target right (select it), else
2776 // still the source will be selected
2777 SwTransferable::SetSelInShell( rSh
, true, pPt
);
2780 rSh
.Paste( *xStrm
, nAction
, pPt
);
2783 if( bRet
&& ( nActionFlags
& SotExchangeActionFlags::InsertTargetUrl
))
2784 SwTransferable::PasteTargetURL( rData
, rSh
, SwPasteSdr::NONE
, nullptr, false );
2789 bool SwTransferable::PasteGrf( const TransferableDataHelper
& rData
, SwWrtShell
& rSh
,
2790 SotClipboardFormatId nFormat
, SwPasteSdr nAction
, const Point
* pPt
,
2791 SotExchangeActionFlags nActionFlags
, sal_Int8 nDropAction
, bool bNeedToSelectBeforePaste
, RndStdIds nAnchorType
)
2797 bool bCheckForGrf
= false, bCheckForImageMap
= false;
2801 case SotClipboardFormatId::BITMAP
:
2802 case SotClipboardFormatId::PNG
:
2803 case SotClipboardFormatId::GDIMETAFILE
:
2804 bRet
= rData
.GetGraphic( nFormat
, aGraphic
);
2807 case SotClipboardFormatId::SVXB
:
2809 tools::SvRef
<SotTempStream
> xStm
;
2811 if(rData
.GetSotStorageStream(SotClipboardFormatId::SVXB
, xStm
))
2813 TypeSerializer
aSerializer(*xStm
);
2814 aSerializer
.readGraphic(aGraphic
);
2815 bRet
= (GraphicType::NONE
!= aGraphic
.GetType() && GraphicType::Default
!= aGraphic
.GetType());
2821 case SotClipboardFormatId::NETSCAPE_BOOKMARK
:
2822 case SotClipboardFormatId::FILEGRPDESCRIPTOR
:
2823 case SotClipboardFormatId::UNIFORMRESOURCELOCATOR
:
2824 bRet
= rData
.GetINetBookmark( nFormat
, aBkmk
);
2827 if( SwPasteSdr::SetAttr
== nAction
)
2828 nFormat
= SotClipboardFormatId::NETSCAPE_BOOKMARK
;
2830 bCheckForGrf
= true;
2834 case SotClipboardFormatId::SIMPLE_FILE
:
2837 bRet
= rData
.GetString( nFormat
, sText
);
2841 SwTransferable::CheckForURLOrLNKFile( rData
, sText
, &sDesc
);
2843 sText
= URIHelper::SmartRel2Abs(INetURLObject(), sText
, Link
<OUString
*, bool>(),
2847 // Now that the path could be modified after SwTransferable::CheckForURLOrLNKFile,
2848 // where it could have been converted to URL, and made sure it's actually converted
2849 // to URL in URIHelper::SmartRel2Abs, we can finally convert file: URL back to
2850 // system path to make sure we don't use short path.
2851 // It looks not optimal, when we could apply GetLongPathNameW right to the original
2852 // pasted filename. But I don't know if (1) all arriving strings are system paths;
2853 // and (2) if SwTransferable::CheckForURLOrLNKFile could result in a different short
2854 // path, so taking a safe route.
2855 if (sText
.startsWithIgnoreAsciiCase("file:"))
2857 // tdf#124500: Convert short path to long path which should be used in links
2859 osl::FileBase::getSystemPathFromFileURL(sText
, sSysPath
);
2860 std::unique_ptr
<sal_Unicode
[]> aBuf(new sal_Unicode
[32767]);
2861 DWORD nCopied
= GetLongPathNameW(o3tl::toW(sSysPath
.getStr()),
2862 o3tl::toW(aBuf
.get()), 32767);
2863 if (nCopied
&& nCopied
< 32767)
2864 sText
= URIHelper::SmartRel2Abs(INetURLObject(), OUString(aBuf
.get()),
2865 Link
<OUString
*, bool>(), false);
2869 aBkmk
= INetBookmark(sText
, sDesc
);
2870 bCheckForGrf
= true;
2871 bCheckForImageMap
= SwPasteSdr::Replace
== nAction
;
2877 bRet
= rData
.GetGraphic( nFormat
, aGraphic
);
2883 //!!! check at FileSystem - only then it makes sense to test the graphics !!!
2884 GraphicFilter
&rFlt
= GraphicFilter::GetGraphicFilter();
2885 bRet
= ERRCODE_NONE
== GraphicFilter::LoadGraphic(aBkmk
.GetURL(), OUString(),
2888 if( !bRet
&& SwPasteSdr::SetAttr
== nAction
&&
2889 SotClipboardFormatId::SIMPLE_FILE
== nFormat
&&
2890 // only at frame selection
2891 rSh
.IsFrameSelected() )
2893 // then set as hyperlink after the graphic
2894 nFormat
= SotClipboardFormatId::NETSCAPE_BOOKMARK
;
2899 if(pPt
&& bNeedToSelectBeforePaste
)
2901 // when using internal D&Ds, still the source object is selected and
2902 // this is necessary to get the correct source data which is also
2903 // dependent from selection. After receiving the drag data it is
2904 // now time to select the correct target object
2905 SwTransferable::SetSelInShell( rSh
, true, pPt
);
2910 //Check and Perform rotation if needed
2911 lclCheckAndPerformRotation(aGraphic
);
2914 if( dynamic_cast< const SwWebDocShell
*>( rSh
.GetView().GetDocShell() ) != nullptr
2915 // #i123922# if link action is noted, also take URL
2916 || DND_ACTION_LINK
== nDropAction
)
2918 sURL
= aBkmk
.GetURL();
2923 case SwPasteSdr::Insert
:
2925 SwTransferable::SetSelInShell( rSh
, false, pPt
);
2926 rSh
.InsertGraphic(sURL
, OUString(), aGraphic
, nullptr, nAnchorType
);
2930 case SwPasteSdr::Replace
:
2932 if( rSh
.IsObjSelected() )
2934 // #i123922# for D&D on draw objects, do for now the same for
2935 // SwPasteSdr::Replace (D&D) as for SwPasteSdr::SetAttr (D&D and
2936 // CTRL+SHIFT). The code below replaces the draw object with
2937 // a writer graphic; maybe this is an option later again if wanted
2938 rSh
.Paste( aGraphic
, sURL
);
2940 // rSh.ReplaceSdrObj(sURL, OUString(), &aGraphic);
2941 // Point aPt( pPt ? *pPt : rSh.GetCursorDocPos() );
2942 // SwTransferable::SetSelInShell( rSh, true, &aPt );
2946 // set graphic at writer graphic without link
2947 rSh
.ReRead(sURL
, OUString(), &aGraphic
);
2953 case SwPasteSdr::SetAttr
:
2955 if( SotClipboardFormatId::NETSCAPE_BOOKMARK
== nFormat
)
2957 if( rSh
.IsFrameSelected() )
2959 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( rSh
.GetAttrPool() );
2960 rSh
.GetFlyFrameAttr( aSet
);
2961 SwFormatURL
aURL( aSet
.Get( RES_URL
) );
2962 aURL
.SetURL( aBkmk
.GetURL(), false );
2964 rSh
.SetFlyFrameAttr( aSet
);
2967 else if( rSh
.IsObjSelected() )
2969 // set as attribute at DrawObject
2970 rSh
.Paste( aGraphic
, sURL
);
2972 else if( OBJCNT_GRF
== rSh
.GetObjCntTypeOfSelection() )
2974 // set as linked graphic at writer graphic frame
2975 rSh
.ReRead(sURL
, OUString(), &aGraphic
);
2979 SwTransferable::SetSelInShell( rSh
, false, pPt
);
2980 rSh
.InsertGraphic(aBkmk
.GetURL(), OUString(), aGraphic
);
2996 ( SotExchangeActionFlags::InsertImageMap
| SotExchangeActionFlags::ReplaceImageMap
) )
2997 SwTransferable::PasteImageMap( rData
, rSh
);
2999 if( nActionFlags
& SotExchangeActionFlags::InsertTargetUrl
)
3000 SwTransferable::PasteTargetURL( rData
, rSh
, SwPasteSdr::NONE
, nullptr, false );
3002 else if( bCheckForImageMap
)
3004 // or should the file be an ImageMap-File?
3006 SfxMedium
aMed( INetURLObject(aBkmk
.GetURL()).GetFull(),
3007 StreamMode::STD_READ
);
3008 SvStream
* pStream
= aMed
.GetInStream();
3009 if( pStream
!= nullptr &&
3010 !pStream
->GetError() &&
3011 // mba: no BaseURL for clipboard functionality
3012 aMap
.Read( *pStream
, IMapFormat::Detect
) == IMAP_ERR_OK
&&
3013 aMap
.GetIMapObjectCount() )
3015 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( rSh
.GetAttrPool() );
3016 rSh
.GetFlyFrameAttr( aSet
);
3017 SwFormatURL
aURL( aSet
.Get( RES_URL
) );
3018 aURL
.SetMap( &aMap
);
3020 rSh
.SetFlyFrameAttr( aSet
);
3028 bool SwTransferable::PasteImageMap( const TransferableDataHelper
& rData
,
3032 if( rData
.HasFormat( SotClipboardFormatId::SVIM
))
3034 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( rSh
.GetAttrPool() );
3035 rSh
.GetFlyFrameAttr( aSet
);
3036 SwFormatURL
aURL( aSet
.Get( RES_URL
) );
3037 const ImageMap
* pOld
= aURL
.GetMap();
3039 // set or replace, that is the question
3041 if( rData
.GetImageMap( SotClipboardFormatId::SVIM
, aImageMap
) &&
3042 ( !pOld
|| aImageMap
!= *pOld
))
3044 aURL
.SetMap( &aImageMap
);
3046 rSh
.SetFlyFrameAttr( aSet
);
3053 bool SwTransferable::PasteAsHyperlink( const TransferableDataHelper
& rData
,
3054 SwWrtShell
& rSh
, SotClipboardFormatId nFormat
)
3058 if( rData
.GetString( nFormat
, sFile
) && !sFile
.isEmpty() )
3061 SwTransferable::CheckForURLOrLNKFile( rData
, sFile
, &sDesc
);
3063 // first, make the URL absolute
3065 aURL
.SetSmartProtocol( INetProtocol::File
);
3066 aURL
.SetSmartURL( sFile
);
3067 sFile
= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
3069 switch( rSh
.GetObjCntTypeOfSelection() )
3075 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( rSh
.GetAttrPool() );
3076 rSh
.GetFlyFrameAttr( aSet
);
3077 SwFormatURL
aURL2( aSet
.Get( RES_URL
) );
3078 aURL2
.SetURL( sFile
, false );
3079 if( aURL2
.GetName().isEmpty() )
3080 aURL2
.SetName( sFile
);
3082 rSh
.SetFlyFrameAttr( aSet
);
3088 rSh
.InsertURL( SwFormatINetFormat( sFile
, OUString() ),
3089 sDesc
.isEmpty() ? sFile
: sDesc
);
3097 bool SwTransferable::PasteFileName( TransferableDataHelper
& rData
,
3098 SwWrtShell
& rSh
, SotClipboardFormatId nFormat
,
3099 SwPasteSdr nAction
, const Point
* pPt
,
3100 SotExchangeActionFlags nActionFlags
,
3101 bool * graphicInserted
)
3103 bool bRet
= SwTransferable::PasteGrf( rData
, rSh
, nFormat
, nAction
,
3104 pPt
, nActionFlags
, 0, false);
3105 if (graphicInserted
!= nullptr) {
3106 *graphicInserted
= bRet
;
3110 OUString sFile
, sDesc
;
3111 if( rData
.GetString( nFormat
, sFile
) && !sFile
.isEmpty() )
3113 #if HAVE_FEATURE_AVMEDIA
3114 INetURLObject aMediaURL
;
3116 aMediaURL
.SetSmartURL( sFile
);
3117 const OUString
aMediaURLStr( aMediaURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
3119 if( ::avmedia::MediaWindow::isMediaURL( aMediaURLStr
, ""/*TODO?*/ ) )
3121 const SfxStringItem
aMediaURLItem( SID_INSERT_AVMEDIA
, aMediaURLStr
);
3122 rSh
.GetView().GetViewFrame().GetDispatcher()->ExecuteList(
3123 SID_INSERT_AVMEDIA
, SfxCallMode::SYNCHRON
,
3124 { &aMediaURLItem
});
3133 bool bIsURLFile
= SwTransferable::CheckForURLOrLNKFile( rData
, sFile
, &sDesc
);
3135 //Own FileFormat? --> insert, not for StarWriter/Web
3136 OUString sFileURL
= URIHelper::SmartRel2Abs(INetURLObject(), sFile
, Link
<OUString
*, bool>(), false );
3137 std::shared_ptr
<const SfxFilter
> pFlt
= SwPasteSdr::SetAttr
== nAction
3138 ? nullptr : SwIoSystem::GetFileFilter(sFileURL
);
3139 if( pFlt
&& dynamic_cast< const SwWebDocShell
*>( rSh
.GetView().GetDocShell() ) == nullptr )
3141 // and then pull up the insert-region-dialog
3142 SwSectionData
aSect(
3143 SectionType::FileLink
,
3144 rSh
.GetDoc()->GetUniqueSectionName() );
3145 aSect
.SetLinkFileName( sFileURL
);
3146 aSect
.SetProtectFlag( true );
3148 rSh
.StartInsertRegionDialog( aSect
); // starts dialog asynchronously
3151 else if (SwPasteSdr::Insert
== nAction
&& rData
.HasFormat(SotClipboardFormatId::SIMPLE_FILE
))
3153 // insert file as OLE
3154 PasteOLE(rData
, rSh
, nFormat
, nActionFlags
, nullptr == pPt
);
3156 else if( SwPasteSdr::SetAttr
== nAction
||
3157 ( bIsURLFile
&& SwPasteSdr::Insert
== nAction
))
3159 //we can insert foreign files as links after all
3161 // first, make the URL absolute
3163 aURL
.SetSmartProtocol( INetProtocol::File
);
3164 aURL
.SetSmartURL( sFile
);
3165 sFile
= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
3167 switch( rSh
.GetObjCntTypeOfSelection() )
3173 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( rSh
.GetAttrPool() );
3174 rSh
.GetFlyFrameAttr( aSet
);
3175 SwFormatURL
aURL2( aSet
.Get( RES_URL
) );
3176 aURL2
.SetURL( sFile
, false );
3177 if( aURL2
.GetName().isEmpty() )
3178 aURL2
.SetName( sFile
);
3180 rSh
.SetFlyFrameAttr( aSet
);
3186 rSh
.InsertURL( SwFormatINetFormat( sFile
, OUString() ),
3187 sDesc
.isEmpty() ? sFile
: sDesc
);
3198 bool SwTransferable::PasteDBData( const TransferableDataHelper
& rData
,
3199 SwWrtShell
& rSh
, SotClipboardFormatId nFormat
, bool bLink
,
3200 const Point
* pDragPt
, bool bMsg
)
3204 if( rData
.GetString( nFormat
, sText
) && !sText
.isEmpty() )
3206 sal_uInt16 nWh
= SotClipboardFormatId::SBA_CTRLDATAEXCHANGE
== nFormat
3208 : SotClipboardFormatId::SBA_DATAEXCHANGE
== nFormat
3210 ? FN_QRY_MERGE_FIELD
3214 : FN_QRY_INSERT_FIELD
);
3215 const DataFlavorExVector
& rVector
= rData
.GetDataFlavorExVector();
3216 bool bHaveColumnDescriptor
= OColumnTransferable::canExtractColumnDescriptor(rVector
, ColumnTransferFormatFlags::COLUMN_DESCRIPTOR
| ColumnTransferFormatFlags::CONTROL_EXCHANGE
);
3217 if ( SotClipboardFormatId::XFORMS
== nFormat
)
3220 FmFormView
* pFmView
= dynamic_cast<FmFormView
*>( rSh
.GetDrawView() );
3221 if (pFmView
&& pDragPt
)
3223 OXFormsDescriptor aDesc
= OXFormsTransferable::extractDescriptor(rData
);
3224 rtl::Reference
<SdrObject
> pObj
= pFmView
->CreateXFormsControl(aDesc
);
3227 rSh
.SwFEShell::InsertDrawObj( *pObj
, *pDragPt
);
3233 std::unique_ptr
<SfxUnoAnyItem
> pConnectionItem
;
3234 std::unique_ptr
<SfxUnoAnyItem
> pCursorItem
;
3235 std::unique_ptr
<SfxUnoAnyItem
> pColumnItem
;
3236 std::unique_ptr
<SfxUnoAnyItem
> pSourceItem
;
3237 std::unique_ptr
<SfxUnoAnyItem
> pCommandItem
;
3238 std::unique_ptr
<SfxUnoAnyItem
> pCommandTypeItem
;
3239 std::unique_ptr
<SfxUnoAnyItem
> pColumnNameItem
;
3240 std::unique_ptr
<SfxUnoAnyItem
> pSelectionItem
;
3242 bool bDataAvailable
= true;
3243 ODataAccessDescriptor aDesc
;
3244 if(bHaveColumnDescriptor
)
3245 aDesc
= OColumnTransferable::extractColumnDescriptor(rData
);
3246 else if(ODataAccessObjectTransferable::canExtractObjectDescriptor(rVector
) )
3247 aDesc
= ODataAccessObjectTransferable::extractObjectDescriptor(rData
);
3249 bDataAvailable
= false;
3251 if ( bDataAvailable
)
3253 pConnectionItem
.reset(new SfxUnoAnyItem(FN_DB_CONNECTION_ANY
, aDesc
[DataAccessDescriptorProperty::Connection
]));
3254 pColumnItem
.reset(new SfxUnoAnyItem(FN_DB_COLUMN_ANY
, aDesc
[DataAccessDescriptorProperty::ColumnObject
]));
3255 pSourceItem
.reset(new SfxUnoAnyItem(FN_DB_DATA_SOURCE_ANY
, Any(aDesc
.getDataSource())));
3256 pCommandItem
.reset(new SfxUnoAnyItem(FN_DB_DATA_COMMAND_ANY
, aDesc
[DataAccessDescriptorProperty::Command
]));
3257 pCommandTypeItem
.reset(new SfxUnoAnyItem(FN_DB_DATA_COMMAND_TYPE_ANY
, aDesc
[DataAccessDescriptorProperty::CommandType
]));
3258 pColumnNameItem
.reset(new SfxUnoAnyItem(FN_DB_DATA_COLUMN_NAME_ANY
, aDesc
[DataAccessDescriptorProperty::ColumnName
]));
3259 pSelectionItem
.reset(new SfxUnoAnyItem(FN_DB_DATA_SELECTION_ANY
, aDesc
[DataAccessDescriptorProperty::Selection
]));
3260 pCursorItem
.reset(new SfxUnoAnyItem(FN_DB_DATA_CURSOR_ANY
, aDesc
[DataAccessDescriptorProperty::Cursor
]));
3263 SwView
& rView
= rSh
.GetView();
3264 //force ::SelectShell
3265 rView
.StopShellTimer();
3267 SfxStringItem
aDataDesc( nWh
, sText
);
3268 rView
.GetViewFrame().GetDispatcher()->ExecuteList(
3269 nWh
, SfxCallMode::ASYNCHRON
,
3270 { &aDataDesc
, pConnectionItem
.get(), pColumnItem
.get(),
3271 pSourceItem
.get(), pCommandItem
.get(), pCommandTypeItem
.get(),
3272 pColumnNameItem
.get(), pSelectionItem
.get(),
3273 pCursorItem
.get() });
3278 FmFormView
* pFmView
= dynamic_cast<FmFormView
*>( rSh
.GetDrawView() );
3279 if (pFmView
&& bHaveColumnDescriptor
&& pDragPt
)
3281 rtl::Reference
<SdrObject
> pObj
= pFmView
->CreateFieldControl( OColumnTransferable::extractColumnDescriptor(rData
) );
3283 rSh
.SwFEShell::InsertDrawObj( *pObj
, *pDragPt
);
3290 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
3291 VclMessageType::Info
, VclButtonsType::Ok
,
3292 SwResId(STR_CLPBRD_FORMAT_ERROR
)));
3298 bool SwTransferable::PasteFileList( const TransferableDataHelper
& rData
,
3299 SwWrtShell
& rSh
, bool bLink
,
3300 const Point
* pPt
, bool bMsg
)
3304 if( rData
.GetFileList( SotClipboardFormatId::FILE_LIST
, aFileList
) &&
3307 SwPasteSdr nAct
= bLink
? SwPasteSdr::SetAttr
: SwPasteSdr::Insert
;
3309 // iterate over the filelist
3310 for( sal_uLong n
= 0, nEnd
= aFileList
.Count(); n
< nEnd
; ++n
)
3312 rtl::Reference
<TransferDataContainer
> pHlp
= new TransferDataContainer
;
3313 pHlp
->CopyString( SotClipboardFormatId::SIMPLE_FILE
, aFileList
.GetFile( n
));
3314 TransferableDataHelper
aData( pHlp
);
3316 if( SwTransferable::PasteFileName( aData
, rSh
, SotClipboardFormatId::SIMPLE_FILE
, nAct
,
3317 pPt
, SotExchangeActionFlags::NONE
, nullptr ))
3321 sFlyNm
= rSh
.GetFlyName();
3322 SwTransferable::SetSelInShell( rSh
, false, pPt
);
3327 if( !sFlyNm
.isEmpty() )
3328 rSh
.GotoFly( sFlyNm
);
3332 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(nullptr,
3333 VclMessageType::Info
, VclButtonsType::Ok
,
3334 SwResId(STR_CLPBRD_FORMAT_ERROR
)));
3340 bool SwTransferable::CheckForURLOrLNKFile( const TransferableDataHelper
& rData
,
3341 OUString
& rFileName
, OUString
* pTitle
)
3343 bool bIsURLFile
= false;
3345 if( rData
.GetINetBookmark( SotClipboardFormatId::SOLK
, aBkmk
) )
3347 rFileName
= aBkmk
.GetURL();
3349 *pTitle
= aBkmk
.GetDescription();
3354 if( rFileName
.getLength()>4 && rFileName
.endsWithIgnoreAsciiCase(".url") )
3356 OSL_ENSURE( false, "how do we read today .URL - Files?" );
3362 bool SwTransferable::IsPasteSpecial( const SwWrtShell
& rWrtShell
,
3363 const TransferableDataHelper
& rData
)
3365 // we can paste-special if there's an entry in the paste-special-format list
3366 SvxClipboardFormatItem
aClipboardFormatItem(TypedWhichId
<SvxClipboardFormatItem
>(0));
3367 FillClipFormatItem( rWrtShell
, rData
, aClipboardFormatItem
);
3368 return aClipboardFormatItem
.Count() > 0;
3371 bool SwTransferable::IsPasteOwnFormat( const TransferableDataHelper
& rData
)
3373 return ( GetSwTransferable( rData
) != nullptr );
3376 bool SwTransferable::PasteFormat( SwWrtShell
& rSh
,
3377 TransferableDataHelper
& rData
,
3378 SotClipboardFormatId nFormat
)
3380 SwWait
aWait( *rSh
.GetView().GetDocShell(), false );
3383 SotClipboardFormatId nPrivateFormat
= SotClipboardFormatId::PRIVATE
;
3384 SwTransferable
*pClipboard
= GetSwTransferable( rData
);
3386 ((TransferBufferType::Document
|TransferBufferType::Graphic
|TransferBufferType::Ole
) & pClipboard
->m_eBufferType
))
3387 nPrivateFormat
= SotClipboardFormatId::EMBED_SOURCE
;
3389 if( pClipboard
&& nPrivateFormat
== nFormat
)
3390 bRet
= pClipboard
->PrivatePaste( rSh
);
3391 else if( rData
.HasFormat( nFormat
) )
3393 uno::Reference
<XTransferable
> xTransferable( rData
.GetXTransferable() );
3394 sal_uInt8 nEventAction
;
3395 SotExchangeDest nDestination
= SwTransferable::GetSotDestination( rSh
);
3396 sal_uInt16 nSourceOptions
=
3397 (( SotExchangeDest::DOC_TEXTFRAME
== nDestination
||
3398 SotExchangeDest::SWDOC_FREE_AREA
== nDestination
||
3399 SotExchangeDest::DOC_TEXTFRAME_WEB
== nDestination
||
3400 SotExchangeDest::SWDOC_FREE_AREA_WEB
== nDestination
)
3401 ? EXCHG_IN_ACTION_COPY
3402 : EXCHG_IN_ACTION_MOVE
);
3403 SotExchangeActionFlags nActionFlags
;
3404 sal_uInt8 nAction
= SotExchange::GetExchangeAction(
3405 rData
.GetDataFlavorExVector(),
3407 nSourceOptions
, /* ?? */
3408 EXCHG_IN_ACTION_DEFAULT
, /* ?? */
3409 nFormat
, nEventAction
, nFormat
,
3410 lcl_getTransferPointer ( xTransferable
),
3413 if( EXCHG_INOUT_ACTION_NONE
!= nAction
)
3414 bRet
= SwTransferable::PasteData( rData
, rSh
, nAction
, nActionFlags
, nFormat
,
3415 nDestination
, true, false );
3420 bool SwTransferable::TestAllowedFormat( const TransferableDataHelper
& rData
,
3421 SotClipboardFormatId nFormat
, SotExchangeDest nDestination
)
3423 sal_uInt8 nAction
= EXCHG_INOUT_ACTION_NONE
;
3424 if( rData
.HasFormat( nFormat
)) {
3425 uno::Reference
<XTransferable
> xTransferable( rData
.GetXTransferable() );
3426 sal_uInt8 nEventAction
;
3427 nAction
= SotExchange::GetExchangeAction(
3428 rData
.GetDataFlavorExVector(),
3429 nDestination
, EXCHG_IN_ACTION_COPY
,
3430 EXCHG_IN_ACTION_COPY
, nFormat
,
3431 nEventAction
, nFormat
,
3432 lcl_getTransferPointer ( xTransferable
) );
3434 return EXCHG_INOUT_ACTION_NONE
!= nAction
;
3438 * the list of formats which will be offered to the user in the 'Paste
3439 * Special...' dialog and the paste button menu
3441 static SotClipboardFormatId aPasteSpecialIds
[] =
3443 SotClipboardFormatId::HTML
,
3444 SotClipboardFormatId::HTML_SIMPLE
,
3445 SotClipboardFormatId::HTML_NO_COMMENT
,
3446 SotClipboardFormatId::RTF
,
3447 SotClipboardFormatId::RICHTEXT
,
3448 SotClipboardFormatId::STRING
,
3449 SotClipboardFormatId::SONLK
,
3450 SotClipboardFormatId::NETSCAPE_BOOKMARK
,
3451 SotClipboardFormatId::DRAWING
,
3452 SotClipboardFormatId::SVXB
,
3453 SotClipboardFormatId::GDIMETAFILE
,
3454 SotClipboardFormatId::BITMAP
,
3455 SotClipboardFormatId::SVIM
,
3456 SotClipboardFormatId::FILEGRPDESCRIPTOR
,
3457 SotClipboardFormatId::NONE
3460 bool SwTransferable::PasteUnformatted( SwWrtShell
& rSh
, TransferableDataHelper
& rData
)
3462 // Plain text == unformatted
3463 return SwTransferable::PasteFormat( rSh
, rData
, SotClipboardFormatId::STRING
);
3466 void SwTransferable::PrePasteSpecial( const SwWrtShell
& rSh
, TransferableDataHelper
& rData
, const VclPtr
<SfxAbstractPasteDialog
>& pDlg
)
3468 DataFlavorExVector
aFormats( rData
.GetDataFlavorExVector() );
3469 TransferableObjectDescriptor aDesc
;
3471 SotExchangeDest nDest
= SwTransferable::GetSotDestination( rSh
);
3473 SwTransferable
*pClipboard
= GetSwTransferable( rData
);
3476 aDesc
= pClipboard
->m_aObjDesc
;
3478 if( pClipboard
->m_eBufferType
& TransferBufferType::Document
)
3479 pResId
= STR_PRIVATETEXT
;
3480 else if( pClipboard
->m_eBufferType
& TransferBufferType::Graphic
)
3481 pResId
= STR_PRIVATEGRAPHIC
;
3482 else if( pClipboard
->m_eBufferType
== TransferBufferType::Ole
)
3483 pResId
= STR_PRIVATEOLE
;
3487 if (STR_PRIVATEOLE
== pResId
|| STR_PRIVATEGRAPHIC
== pResId
)
3489 // add SotClipboardFormatId::EMBED_SOURCE to the formats. This
3490 // format display then the private format name.
3491 DataFlavorEx aFlavorEx
;
3492 aFlavorEx
.mnSotId
= SotClipboardFormatId::EMBED_SOURCE
;
3493 aFormats
.insert( aFormats
.begin(), aFlavorEx
);
3495 pDlg
->SetObjName( pClipboard
->m_aObjDesc
.maClassName
,
3497 pDlg
->Insert( SotClipboardFormatId::EMBED_SOURCE
, OUString() );
3502 if( rData
.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
) )
3504 (void)rData
.GetTransferableObjectDescriptor(
3505 SotClipboardFormatId::OBJECTDESCRIPTOR
, aDesc
);
3508 if( SwTransferable::TestAllowedFormat( rData
, SotClipboardFormatId::EMBED_SOURCE
, nDest
))
3509 pDlg
->Insert( SotClipboardFormatId::EMBED_SOURCE
, OUString() );
3510 if( SwTransferable::TestAllowedFormat( rData
, SotClipboardFormatId::LINK_SOURCE
, nDest
))
3511 pDlg
->Insert( SotClipboardFormatId::LINK_SOURCE
, OUString() );
3514 if( SwTransferable::TestAllowedFormat( rData
, SotClipboardFormatId::LINK
, nDest
))
3515 pDlg
->Insert( SotClipboardFormatId::LINK
, SwResId(STR_DDEFORMAT
) );
3517 for( SotClipboardFormatId
* pIds
= aPasteSpecialIds
; *pIds
!= SotClipboardFormatId::NONE
; ++pIds
)
3518 if( SwTransferable::TestAllowedFormat( rData
, *pIds
, nDest
))
3519 pDlg
->Insert( *pIds
, OUString() );
3522 void SwTransferable::FillClipFormatItem( const SwWrtShell
& rSh
,
3523 const TransferableDataHelper
& rData
,
3524 SvxClipboardFormatItem
& rToFill
)
3526 SotExchangeDest nDest
= SwTransferable::GetSotDestination( rSh
);
3528 SwTransferable
*pClipboard
= GetSwTransferable( rData
);
3532 if( pClipboard
->m_eBufferType
& TransferBufferType::Document
)
3533 pResId
= STR_PRIVATETEXT
;
3534 else if( pClipboard
->m_eBufferType
& TransferBufferType::Graphic
)
3535 pResId
= STR_PRIVATEGRAPHIC
;
3536 else if( pClipboard
->m_eBufferType
== TransferBufferType::Ole
)
3537 pResId
= STR_PRIVATEOLE
;
3540 rToFill
.AddClipbrdFormat(SotClipboardFormatId::EMBED_SOURCE
,
3545 TransferableObjectDescriptor aDesc
;
3546 if (rData
.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR
))
3548 (void)const_cast<TransferableDataHelper
&>(rData
).GetTransferableObjectDescriptor(
3549 SotClipboardFormatId::OBJECTDESCRIPTOR
, aDesc
);
3552 if( SwTransferable::TestAllowedFormat( rData
, SotClipboardFormatId::EMBED_SOURCE
, nDest
))
3553 rToFill
.AddClipbrdFormat( SotClipboardFormatId::EMBED_SOURCE
,
3555 if( SwTransferable::TestAllowedFormat( rData
, SotClipboardFormatId::LINK_SOURCE
, nDest
))
3556 rToFill
.AddClipbrdFormat( SotClipboardFormatId::LINK_SOURCE
);
3558 SotClipboardFormatId nFormat
;
3559 if ( rData
.HasFormat(nFormat
= SotClipboardFormatId::EMBED_SOURCE_OLE
) || rData
.HasFormat(nFormat
= SotClipboardFormatId::EMBEDDED_OBJ_OLE
) )
3561 OUString sName
,sSource
;
3562 if ( SvPasteObjectHelper::GetEmbeddedName(rData
,sName
,sSource
,nFormat
) )
3563 rToFill
.AddClipbrdFormat( nFormat
, sName
);
3567 if( SwTransferable::TestAllowedFormat( rData
, SotClipboardFormatId::LINK
, nDest
))
3568 rToFill
.AddClipbrdFormat( SotClipboardFormatId::LINK
, SwResId(STR_DDEFORMAT
) );
3570 for( SotClipboardFormatId
* pIds
= aPasteSpecialIds
; *pIds
!= SotClipboardFormatId::NONE
; ++pIds
)
3571 if( SwTransferable::TestAllowedFormat( rData
, *pIds
, nDest
))
3572 rToFill
.AddClipbrdFormat(*pIds
, OUString());
3575 void SwTransferable::SetDataForDragAndDrop( const Point
& rSttPos
)
3580 const SelectionType nSelection
= m_pWrtShell
->GetSelectionType();
3581 if( SelectionType::Graphic
== nSelection
)
3583 AddFormat( SotClipboardFormatId::SVXB
);
3584 const Graphic
* pGrf
= m_pWrtShell
->GetGraphic();
3585 if ( pGrf
&& pGrf
->IsSupportedGraphic() )
3587 AddFormat( SotClipboardFormatId::GDIMETAFILE
);
3588 AddFormat( SotClipboardFormatId::PNG
);
3589 AddFormat( SotClipboardFormatId::BITMAP
);
3591 m_eBufferType
= TransferBufferType::Graphic
;
3592 m_pWrtShell
->GetGrfNms( &sGrfNm
, nullptr );
3594 else if( SelectionType::Ole
== nSelection
)
3596 AddFormat( SotClipboardFormatId::EMBED_SOURCE
);
3597 PrepareOLE( m_aObjDesc
);
3598 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
);
3599 AddFormat( SotClipboardFormatId::GDIMETAFILE
);
3600 m_eBufferType
= TransferBufferType::Ole
;
3602 //Is there anything to provide anyway?
3603 else if ( m_pWrtShell
->IsSelection() || m_pWrtShell
->IsFrameSelected() ||
3604 m_pWrtShell
->IsObjSelected() )
3606 if( m_pWrtShell
->IsObjSelected() )
3607 m_eBufferType
= TransferBufferType::Drawing
;
3610 m_eBufferType
= TransferBufferType::Document
;
3611 if( SwWrtShell::NO_WORD
!=
3612 m_pWrtShell
->IntelligentCut( nSelection
, false ))
3613 m_eBufferType
= TransferBufferType::DocumentWord
| m_eBufferType
;
3616 if( nSelection
& SelectionType::TableCell
)
3617 m_eBufferType
= TransferBufferType::Table
| m_eBufferType
;
3619 AddFormat( SotClipboardFormatId::EMBED_SOURCE
);
3621 //put RTF ahead of the OLE's Metafile for less loss
3622 if( !m_pWrtShell
->IsObjSelected() )
3624 AddFormat( SotClipboardFormatId::RTF
);
3625 AddFormat( SotClipboardFormatId::RICHTEXT
);
3626 AddFormat( SotClipboardFormatId::HTML
);
3628 if( m_pWrtShell
->IsSelection() )
3629 AddFormat( SotClipboardFormatId::STRING
);
3631 if( nSelection
& ( SelectionType::DrawObject
| SelectionType::DbForm
))
3633 AddFormat( SotClipboardFormatId::DRAWING
);
3634 if ( nSelection
& SelectionType::DrawObject
)
3636 AddFormat( SotClipboardFormatId::GDIMETAFILE
);
3637 AddFormat( SotClipboardFormatId::PNG
);
3638 AddFormat( SotClipboardFormatId::BITMAP
);
3640 m_eBufferType
= TransferBufferType::Graphic
| m_eBufferType
;
3642 // is it a URL-Button ?
3645 if( m_pWrtShell
->GetURLFromButton( sURL
, sDesc
) )
3647 AddFormat( SotClipboardFormatId::STRING
);
3648 AddFormat( SotClipboardFormatId::SOLK
);
3649 AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK
);
3650 AddFormat( SotClipboardFormatId::FILECONTENT
);
3651 AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR
);
3652 AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR
);
3653 m_eBufferType
= TransferBufferType::InetField
| m_eBufferType
;
3657 //ObjectDescriptor was already filled from the old DocShell.
3658 //Now adjust it. Thus in GetData the first query can still
3659 //be answered with delayed rendering.
3660 m_aObjDesc
.maDragStartPos
= rSttPos
;
3661 m_aObjDesc
.maSize
= constOleSize100mm
;
3663 PrepareOLE( m_aObjDesc
);
3664 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
);
3666 else if( nSelection
& SelectionType::Text
&& !m_pWrtShell
->HasMark() )
3668 // is only one field - selected?
3669 SwContentAtPos
aContentAtPos( IsAttrAtPos::InetAttr
);
3670 Point
aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY());
3672 if( m_pWrtShell
->GetContentAtPos( aPos
, aContentAtPos
) )
3674 AddFormat( SotClipboardFormatId::STRING
);
3675 AddFormat( SotClipboardFormatId::SOLK
);
3676 AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK
);
3677 AddFormat( SotClipboardFormatId::FILECONTENT
);
3678 AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR
);
3679 AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR
);
3680 m_eBufferType
= TransferBufferType::InetField
;
3684 if( !m_pWrtShell
->IsFrameSelected() )
3687 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( m_pWrtShell
->GetAttrPool() );
3688 m_pWrtShell
->GetFlyFrameAttr( aSet
);
3689 const SwFormatURL
& rURL
= aSet
.Get( RES_URL
);
3692 m_pImageMap
.reset( new ImageMap( *rURL
.GetMap() ) );
3693 AddFormat( SotClipboardFormatId::SVIM
);
3695 else if( !rURL
.GetURL().isEmpty() )
3697 m_pTargetURL
.reset(new INetImage( sGrfNm
, rURL
.GetURL(),
3698 rURL
.GetTargetFrameName() ));
3699 AddFormat( SotClipboardFormatId::INET_IMAGE
);
3703 void SwTransferable::StartDrag( vcl::Window
* pWin
, const Point
& rPos
)
3707 m_bOldIdle
= m_pWrtShell
->GetViewOptions()->IsIdle();
3710 m_pWrtShell
->GetViewOptions()->SetIdle( false );
3712 if( m_pWrtShell
->IsSelFrameMode() )
3713 m_pWrtShell
->ShowCursor();
3715 SW_MOD()->m_pDragDrop
= this;
3717 SetDataForDragAndDrop( rPos
);
3719 sal_Int8 nDragOptions
= DND_ACTION_COPYMOVE
| DND_ACTION_LINK
;
3720 SwDocShell
* pDShell
= m_pWrtShell
->GetView().GetDocShell();
3721 if( ( pDShell
&& pDShell
->IsReadOnly() ) || m_pWrtShell
->HasReadonlySel() )
3722 nDragOptions
&= ~DND_ACTION_MOVE
;
3724 TransferableHelper::StartDrag( pWin
, nDragOptions
);
3727 void SwTransferable::DragFinished( sal_Int8 nAction
)
3729 //And the last finishing work so that all statuses are right
3730 if( DND_ACTION_MOVE
== nAction
)
3734 //It was dropped outside of Writer. We still have to
3737 m_pWrtShell
->StartAllAction();
3738 m_pWrtShell
->StartUndo( SwUndoId::UI_DRAG_AND_MOVE
);
3739 if ( m_pWrtShell
->IsTableMode() )
3740 m_pWrtShell
->DeleteTableSel();
3743 if ( !(m_pWrtShell
->IsSelFrameMode() || m_pWrtShell
->IsObjSelected()) )
3744 //SmartCut, take one of the blanks along
3745 m_pWrtShell
->IntelligentCut( m_pWrtShell
->GetSelectionType() );
3746 m_pWrtShell
->DelRight();
3748 m_pWrtShell
->EndUndo( SwUndoId::UI_DRAG_AND_MOVE
);
3749 m_pWrtShell
->EndAllAction();
3753 const SelectionType nSelection
= m_pWrtShell
->GetSelectionType();
3754 if( ( SelectionType::Frame
| SelectionType::Graphic
|
3755 SelectionType::Ole
| SelectionType::DrawObject
) & nSelection
)
3757 m_pWrtShell
->EnterSelFrameMode();
3761 m_pWrtShell
->GetView().GetEditWin().DragFinished();
3763 if( m_pWrtShell
->IsSelFrameMode() )
3764 m_pWrtShell
->HideCursor();
3766 m_pWrtShell
->ShowCursor();
3768 m_pWrtShell
->GetViewOptions()->SetIdle( m_bOldIdle
);
3774 bool lcl_checkClassification(SwDoc
* pSourceDoc
, SwDoc
* pDestinationDoc
)
3776 if (!pSourceDoc
|| !pDestinationDoc
)
3779 SwDocShell
* pSourceShell
= pSourceDoc
->GetDocShell();
3780 SwDocShell
* pDestinationShell
= pDestinationDoc
->GetDocShell();
3781 if (!pSourceShell
|| !pDestinationShell
)
3784 SfxClassificationCheckPasteResult eResult
= SfxClassificationHelper::CheckPaste(pSourceShell
->getDocProperties(), pDestinationShell
->getDocProperties());
3785 return SfxClassificationHelper::ShowPasteInfo(eResult
);
3790 bool SwTransferable::PrivatePaste(SwWrtShell
& rShell
, SwPasteContext
* pContext
, PasteTableType ePasteTable
)
3792 // first, ask for the SelectionType, then action-bracketing !!!!
3793 // (otherwise it's not pasted into a TableSelection!!!)
3794 OSL_ENSURE( !rShell
.ActionPend(), "Paste must never have an ActionPend" );
3795 if ( !m_pClpDocFac
)
3796 return false; // the return value of the SwFEShell::Paste also is bool!
3798 const SelectionType nSelection
= rShell
.GetSelectionType();
3800 SwTrnsfrActionAndUndo
aAction( &rShell
);
3802 bool bKillPaMs
= false;
3804 //Delete selected content, not at table-selection and table in Clipboard, and don't delete hovering graphics.
3805 if( rShell
.HasSelection() && !( nSelection
& SelectionType::TableCell
) && !( nSelection
& SelectionType::DrawObject
))
3807 if (!(nSelection
& SelectionType::NumberList
))
3810 rShell
.SetRetainSelection( true );
3816 pContext
->remember();
3817 // when a Fly was selected, a valid cursor position has to be found now
3819 if( ( SelectionType::Frame
| SelectionType::Graphic
|
3820 SelectionType::Ole
| SelectionType::DrawObject
|
3821 SelectionType::DbForm
) & nSelection
)
3823 // position the cursor again
3824 Point
aPt( rShell
.GetCharRect().Pos() );
3825 rShell
.SwCursorShell::SetCursor( aPt
, true );
3827 if (!(nSelection
& SelectionType::NumberList
))
3829 rShell
.SetRetainSelection( false );
3832 if ( nSelection
& SelectionType::DrawObject
) //unselect hovering graphics
3834 rShell
.ResetSelect(nullptr,false);
3837 bool bInWrd
= false, bEndWrd
= false, bSttWrd
= false,
3838 bSmart(TransferBufferType::DocumentWord
& m_eBufferType
);
3841 // Why not for other Scripts? If TransferBufferType::DocumentWord is set, we have a word
3842 // in the buffer, word in this context means 'something with spaces at beginning
3843 // and end'. In this case we definitely want these spaces to be inserted here.
3844 bInWrd
= rShell
.IsInWord();
3845 bEndWrd
= rShell
.IsEndWrd();
3846 bSmart
= bInWrd
|| bEndWrd
;
3849 bSttWrd
= rShell
.IsStartWord();
3850 if (!bSttWrd
&& (bInWrd
|| bEndWrd
))
3851 rShell
.SwEditShell::Insert(' ');
3856 // m_pWrtShell is nullptr when the source document is closed already.
3857 if (!m_pWrtShell
|| lcl_checkClassification(m_pWrtShell
->GetDoc(), rShell
.GetDoc()))
3858 bRet
= rShell
.Paste(m_pClpDocFac
->GetDoc(), ePasteTable
== PasteTableType::PASTE_TABLE
);
3863 // If Smart Paste then insert blank
3864 if( bRet
&& bSmart
&& ((bInWrd
&& !bEndWrd
)|| bSttWrd
) )
3865 rShell
.SwEditShell::Insert(' ');
3870 bool SwTransferable::PrivateDrop( SwWrtShell
& rSh
, const Point
& rDragPt
,
3871 bool bMove
, bool bIsXSelection
)
3874 bool bInWrd
= false;
3875 bool bEndWrd
= false;
3876 bool bSttWrd
= false;
3877 bool bSttPara
= false;
3878 bool bTableSel
= false;
3879 bool bTableMove
= false;
3880 bool bFrameSel
= false;
3882 SwWrtShell
& rSrcSh
= *GetShell();
3884 rSh
.UnSetVisibleCursor();
3886 if( TransferBufferType::InetField
== m_eBufferType
)
3888 if( rSh
.GetFormatFromObj( rDragPt
) )
3891 if( (TransferBufferType::InetField
& m_eBufferType
) && m_oBookmark
)
3892 aTmp
= *m_oBookmark
;
3894 // select target graphic
3895 if( rSh
.SelectObj( rDragPt
) )
3898 rSh
.EnterSelFrameMode( &rDragPt
);
3899 g_bFrameDrag
= true;
3902 const SelectionType nSelection
= rSh
.GetSelectionType();
3904 // not yet consider Draw objects
3905 if( SelectionType::Graphic
& nSelection
)
3907 SfxItemSetFixed
<RES_URL
, RES_URL
> aSet( rSh
.GetAttrPool() );
3908 rSh
.GetFlyFrameAttr( aSet
);
3909 SwFormatURL
aURL( aSet
.Get( RES_URL
) );
3910 aURL
.SetURL( aTmp
.GetURL(), false );
3912 rSh
.SetFlyFrameAttr( aSet
);
3916 if( SelectionType::DrawObject
& nSelection
)
3918 rSh
.LeaveSelFrameMode();
3919 rSh
.UnSelectFrame();
3921 g_bFrameDrag
= false;
3926 if( &rSh
!= &rSrcSh
&& (SelectionType::Graphic
& rSh
.GetSelectionType()) &&
3927 TransferBufferType::Graphic
== m_eBufferType
)
3929 // ReRead the graphic
3932 rSrcSh
.GetGrfNms( &sGrfNm
, &sFltNm
);
3933 rSh
.ReRead( sGrfNm
, sFltNm
, rSrcSh
.GetGraphic() );
3937 //not in selections or selected frames
3938 if( rSh
.TestCurrPam( rDragPt
) ||
3939 ( rSh
.IsSelFrameMode() && rSh
.IsInsideSelectedObj( rDragPt
)) )
3942 if( rSrcSh
.IsTableMode() )
3945 const SelectionType nSelection
= rSrcSh
.GetSelectionType();
3946 // at enhanced table row/column selection or wholly selected tables,
3947 // paste rows above or columns before, and in the case of moving, remove the selection
3948 // (limit only to the single document case temporarily)
3949 if( rSrcSh
.GetDoc() == rSh
.GetDoc() &&
3950 ( (( SelectionType::TableRow
| SelectionType::TableCol
) & nSelection
) || rSrcSh
.HasWholeTabSelection() ) )
3952 bool bTableCol(SelectionType::TableCol
& nSelection
);
3954 ::sw::mark::IMark
* pMarkMoveFrom
= bMove
3958 IDocumentMarkAccess::MarkType::UNO_BOOKMARK
)
3961 // row count and direction of the table selection:
3962 // up to down, if the cursor is there in its last table row
3963 const SwSelBoxes
& rBoxes
= rSrcSh
.GetTableCursor()->GetSelectedBoxes();
3964 const SwTableNode
* pTableNd
= rSh
.IsCursorInTable();
3967 SAL_WARN("sw", "presumably this case can't arise in practice");
3970 const SwTableLines
& rLines
= pTableNd
->GetTable().GetTabLines();
3971 const SwStartNode
& rDelPos
= rBoxes
.back()
3972 ? *rBoxes
.front()->GetSttNd()
3973 : *pTableNd
->GetStartNode();
3975 // count selected rows or columns
3976 sal_Int32 nSelRowOrCols
= 0;
3977 if ( rBoxes
.back() )
3981 // selected column count is the count of the cells
3982 // in the first row of the selection
3983 auto nLine
= rLines
.GetPos( rBoxes
.front()->GetUpper() );
3984 for (auto pBox
: rBoxes
)
3986 // cell is in the next row
3987 if ( nLine
!= rLines
.GetPos( pBox
->GetUpper() ) )
3994 // selected row count is the difference of the row number of the
3995 // first and the last cell of the selection
3996 nSelRowOrCols
= rLines
.GetPos( rBoxes
.back()->GetUpper() ) -
3997 rLines
.GetPos( rBoxes
.front()->GetUpper() ) + 1;
4001 bool bSelUpToDown
= rBoxes
.back() && rBoxes
.back()->GetUpper() ==
4002 rSh
.GetCursor()->GetPointNode().GetTableBox()->GetUpper();
4004 SwUndoId eUndoId
= bMove
? SwUndoId::UI_DRAG_AND_MOVE
: SwUndoId::UI_DRAG_AND_COPY
;
4006 SwRewriter aRewriter
;
4008 aRewriter
.AddRule(UndoArg1
, rSrcSh
.GetSelDescr());
4010 if(rSrcSh
.GetDoc() != rSh
.GetDoc())
4011 rSrcSh
.StartUndo( eUndoId
, &aRewriter
);
4012 rSh
.StartUndo( eUndoId
, &aRewriter
);
4015 rSrcSh
.StartAction();
4017 SfxDispatcher
* pDispatch
= rSrcSh
.GetView().GetViewFrame().GetDispatcher();
4018 pDispatch
->Execute(SID_COPY
, SfxCallMode::SYNCHRON
);
4020 rSrcSh
.Push(); // save selection for later restoration
4022 rSh
.SwCursorShell::SetCursor(rDragPt
, false);
4024 bool bPasteIntoTable
= rSh
.GetCursor()->GetPointNode().GetTableBox() != nullptr;
4027 ::sw::mark::IMark
* pMark
= rSh
.SetBookmark(
4030 IDocumentMarkAccess::MarkType::UNO_BOOKMARK
);
4032 // paste rows above/columns before
4033 pDispatch
->Execute(bTableCol
? FN_TABLE_PASTE_COL_BEFORE
: FN_TABLE_PASTE_ROW_BEFORE
, SfxCallMode::SYNCHRON
);
4035 // go to the previously inserted table rows and set them to tracked insertion, if needed
4036 bool bNeedTrack
= !bTableCol
&& rSh
.getIDocumentRedlineAccess().IsRedlineOn();
4038 // restore cursor position
4039 if (bNeedTrack
&& pMark
!= nullptr)
4040 rSh
.GotoMark( pMark
);
4042 if ( !bNeedTrack
&& !bPasteIntoTable
)
4044 rSrcSh
.Pop(SwCursorShell::PopMode::DeleteCurrent
); // restore selection...
4046 // delete source rows/columns
4048 pDispatch
->Execute(bTableCol
4049 ? FN_TABLE_DELETE_COL
4050 : FN_TABLE_DELETE_ROW
, SfxCallMode::SYNCHRON
);
4054 const SwTableBox
* pBoxStt
= rSh
.GetCursor()->GetPointNode().GetTableBox();
4055 SwTableLine
* pLine
= pBoxStt
? const_cast<SwTableLine
*>( pBoxStt
->GetUpper()): nullptr;
4057 for (sal_Int32 nDeleted
= 0; bNeedTrack
&& nDeleted
< nSelRowOrCols
;)
4059 // move up text cursor (note: "true" is important for the layout level)
4060 if ( !rSh
.Up(false) )
4063 const SwTableBox
* pBox
= rSh
.GetCursor()->GetPointNode().GetTableBox();
4068 // Up() reaches a new row
4069 if ( pBox
->GetUpper() != pLine
)
4071 //rSh.SelTableRow();
4072 SvxPrintItem
aTracked(RES_PRINT
, false);
4073 rSh
.GetDoc()->SetRowNotTracked( *rSh
.GetCursor(), aTracked
);
4075 pLine
= const_cast<SwTableLine
*>(pBox
->GetUpper());
4079 rSrcSh
.Pop(SwCursorShell::PopMode::DeleteCurrent
); // restore selection...
4081 // delete source rows/columns
4084 // restore cursor position
4085 if (pMarkMoveFrom
!= nullptr)
4087 rSh
.GotoMark( pMarkMoveFrom
);
4088 rSh
.getIDocumentMarkAccess()->deleteMark( pMarkMoveFrom
);
4091 // tracked table row moving: set original rows as tracked deletion,
4092 // otherwise delete original rows/columns (tracking column deletion
4093 // and insertion is not supported yet)
4094 if ( !bTableCol
&& bNeedTrack
)
4098 for (sal_Int32 nDeleted
= 0; nDeleted
< nSelRowOrCols
;)
4100 const SwTableBox
* pBox
= rSh
.GetCursor()->GetPointNode().GetTableBox();
4105 if ( pBox
->GetUpper() != pLine
)
4107 pLine
= const_cast<SwTableLine
*>(pBox
->GetUpper());
4108 pDispatch
->Execute(FN_TABLE_DELETE_ROW
, SfxCallMode::SYNCHRON
);
4112 bool bMoved
= false;
4114 bMoved
= rSh
.Up(false);
4116 bMoved
= rSh
.Down(false);
4123 // set cursor in the first cell of the original selection
4124 rSh
.GetCursor()->DeleteMark();
4125 rSh
.GetCursor()->GetPoint()->Assign( rDelPos
.GetIndex() + 1);
4127 for (sal_Int32 nDeleted
= 0; nDeleted
< nSelRowOrCols
; ++nDeleted
)
4129 pDispatch
->Execute(bTableCol
4130 ? FN_TABLE_DELETE_COL
4131 : FN_TABLE_DELETE_ROW
, SfxCallMode::SYNCHRON
);
4137 // restore cursor position
4138 if (pMark
!= nullptr)
4140 rSh
.GotoMark( pMark
);
4141 rSh
.getIDocumentMarkAccess()->deleteMark( pMark
);
4144 rSh
.DestroyCursor();
4151 if ( bMove
&& rSrcSh
.HasWholeTabSelection() )
4154 else if( rSrcSh
.IsSelFrameMode() || rSrcSh
.IsObjSelected() )
4156 // don't move position-protected objects!
4157 if( bMove
&& rSrcSh
.IsSelObjProtected( FlyProtectFlags::Pos
) != FlyProtectFlags::NONE
)
4163 const SelectionType nSel
= rSrcSh
.GetSelectionType();
4165 SwUndoId eUndoId
= bMove
? SwUndoId::UI_DRAG_AND_MOVE
: SwUndoId::UI_DRAG_AND_COPY
;
4167 SwRewriter aRewriter
;
4169 aRewriter
.AddRule(UndoArg1
, rSrcSh
.GetSelDescr());
4171 if(rSrcSh
.GetDoc() != rSh
.GetDoc())
4172 rSrcSh
.StartUndo( eUndoId
, &aRewriter
);
4173 rSh
.StartUndo( eUndoId
, &aRewriter
);
4176 rSrcSh
.StartAction();
4178 if( &rSrcSh
!= &rSh
)
4181 rSh
.SwCursorShell::SetCursor( rDragPt
, true );
4182 cWord
= rSrcSh
.IntelligentCut( nSel
, false );
4184 else if( !bTableSel
&& !bFrameSel
)
4186 if( !rSh
.IsAddMode() )
4189 if ( rSh
.IsBlockMode() )
4191 // preserve order of cursors for block mode
4195 rSh
.SwCursorShell::CreateCursor();
4197 rSh
.SwCursorShell::SetCursor( rDragPt
, true, false );
4199 cWord
= rSh
.IntelligentCut( rSh
.GetSelectionType(), false );
4203 bInWrd
= rSh
.IsInWord();
4204 bEndWrd
= rSh
.IsEndWrd();
4205 bSttWrd
= !bEndWrd
&& rSh
.IsStartWord();
4206 bSttPara
= rSh
.IsSttPara();
4208 Point
aSttPt( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY() );
4210 // at first, select InetFields!
4211 if( TransferBufferType::InetField
== m_eBufferType
)
4213 if( &rSrcSh
== &rSh
)
4216 rSh
.SwCursorShell::SetCursor( aSttPt
, true );
4217 rSh
.SelectTextAttr( RES_TXTATR_INETFMT
);
4218 if( rSh
.TestCurrPam( rDragPt
) )
4220 // don't copy/move inside of yourself
4221 rSh
.DestroyCursor();
4231 rSrcSh
.SwCursorShell::SetCursor( aSttPt
, true );
4232 rSrcSh
.SelectTextAttr( RES_TXTATR_INETFMT
);
4235 // is there a URL attribute at the insert point? Then replace that,
4236 // so simply put up a selection?
4237 rSh
.DelINetAttrWithText();
4238 g_bDDINetAttr
= true;
4241 if ( rSrcSh
.IsSelFrameMode() )
4243 //Hack: fool the special treatment
4244 aSttPt
= rSrcSh
.GetObjRect().Pos();
4247 bool bRet
= rSrcSh
.SwFEShell::Copy(rSh
, aSttPt
, rDragPt
, bMove
,
4250 if( !bIsXSelection
)
4253 if ( bRet
&& bMove
&& !bFrameSel
)
4257 /* delete table contents not cells */
4258 rSrcSh
.Delete(false);
4262 //SmartCut, take one of the blanks along.
4263 rSh
.SwCursorShell::DestroyCursor();
4264 if ( cWord
== SwWrtShell::WORD_SPACE_BEFORE
)
4265 rSh
.ExtendSelection( false );
4266 else if ( cWord
== SwWrtShell::WORD_SPACE_AFTER
)
4267 rSh
.ExtendSelection();
4272 rSrcSh
.Pop(SwCursorShell::PopMode::DeleteCurrent
);
4274 /* after dragging a table selection inside one shell
4275 set cursor to the drop position. */
4276 if( &rSh
== &rSrcSh
&& ( bTableSel
|| rSh
.IsBlockMode() ) )
4278 rSrcSh
.CalcLayout();
4279 rSrcSh
.SwCursorShell::SetCursor(rDragPt
);
4280 rSrcSh
.GetCursor()->SetMark();
4284 if( bRet
&& !bTableSel
&& !bFrameSel
)
4286 if( (bInWrd
|| bEndWrd
) &&
4287 (cWord
== SwWrtShell::WORD_SPACE_AFTER
||
4288 cWord
== SwWrtShell::WORD_SPACE_BEFORE
) )
4290 if ( bSttWrd
|| (bInWrd
&& !bEndWrd
))
4291 rSh
.SwEditShell::Insert(' ', bIsXSelection
);
4292 if ( !bSttWrd
|| (bInWrd
&& !bSttPara
) )
4296 rSh
.SwEditShell::Insert(' ', bIsXSelection
);
4303 if( &rSrcSh
== &rSh
&& !rSh
.IsAddMode() )
4305 rSh
.SwCursorShell::DestroyCursor();
4311 rSh
.SwCursorShell::ClearMark();
4316 if( rSh
.IsAddMode() )
4317 rSh
.SwCursorShell::CreateCursor();
4320 // turn on selection mode
4326 else if ( bRet
&& bTableMove
)
4328 SfxDispatcher
* pDispatch
= rSrcSh
.GetView().GetViewFrame().GetDispatcher();
4329 pDispatch
->Execute(FN_TABLE_DELETE_TABLE
, SfxCallMode::SYNCHRON
);
4332 if( bRet
&& bMove
&& bFrameSel
)
4333 rSrcSh
.LeaveSelFrameMode();
4335 if( rSrcSh
.GetDoc() != rSh
.GetDoc() )
4339 // put the shell in the right state
4340 if( &rSrcSh
!= &rSh
&& ( rSh
.IsFrameSelected() || rSh
.IsObjSelected() ))
4341 rSh
.EnterSelFrameMode();
4348 // Interfaces for Selection
4349 void SwTransferable::CreateSelection( SwWrtShell
& rSh
,
4350 const SwFrameShell
* _pCreatorView
)
4352 SwModule
*pMod
= SW_MOD();
4353 rtl::Reference
<SwTransferable
> pNew
= new SwTransferable( rSh
);
4355 pNew
->m_pCreatorView
= _pCreatorView
;
4357 pMod
->m_pXSelection
= pNew
.get();
4358 pNew
->CopyToPrimarySelection();
4361 void SwTransferable::ClearSelection( const SwWrtShell
& rSh
,
4362 const SwFrameShell
* _pCreatorView
)
4364 SwModule
*pMod
= SW_MOD();
4365 if( pMod
->m_pXSelection
&&
4366 ((!pMod
->m_pXSelection
->m_pWrtShell
) || (pMod
->m_pXSelection
->m_pWrtShell
== &rSh
)) &&
4367 (!_pCreatorView
|| (pMod
->m_pXSelection
->m_pCreatorView
== _pCreatorView
)) )
4369 TransferableHelper::ClearPrimarySelection();
4373 SwTransferable
* SwTransferable::GetSwTransferable( const TransferableDataHelper
& rData
)
4375 return dynamic_cast<SwTransferable
*>(rData
.GetTransferable().get());
4378 SwTransferDdeLink::SwTransferDdeLink( SwTransferable
& rTrans
, SwWrtShell
& rSh
)
4379 : m_rTransfer(rTrans
)
4380 , m_pDocShell(nullptr)
4382 , m_bDelBookmark(false)
4383 , m_bInDisconnect(false)
4385 // we only end up here with table- or text selection
4386 if( SelectionType::TableCell
& rSh
.GetSelectionType() )
4388 SwFrameFormat
* pFormat
= rSh
.GetTableFormat();
4390 m_sName
= pFormat
->GetName();
4394 // creating a temp. bookmark without undo
4395 bool bUndo
= rSh
.DoesUndo();
4396 rSh
.DoUndo( false );
4397 bool bIsModified
= rSh
.IsModified();
4399 ::sw::mark::IMark
* pMark
= rSh
.SetBookmark(
4402 IDocumentMarkAccess::MarkType::DDE_BOOKMARK
);
4405 m_sName
= pMark
->GetName();
4406 m_bDelBookmark
= true;
4408 rSh
.ResetModified();
4412 rSh
.DoUndo( bUndo
);
4415 if( m_sName
.isEmpty() ||
4416 nullptr == ( m_pDocShell
= rSh
.GetDoc()->GetDocShell() ))
4419 // then we create our "server" and connect to it
4420 m_xRefObj
= m_pDocShell
->DdeCreateLinkSource( m_sName
);
4421 if( m_xRefObj
.is() )
4423 m_xRefObj
->AddConnectAdvise( this );
4424 m_xRefObj
->AddDataAdvise( this,
4426 ADVISEMODE_NODATA
| ADVISEMODE_ONLYONCE
);
4427 m_nOldTimeOut
= m_xRefObj
->GetUpdateTimeout();
4428 m_xRefObj
->SetUpdateTimeout( 0 );
4432 SwTransferDdeLink::~SwTransferDdeLink()
4434 if( m_xRefObj
.is() )
4438 ::sfx2::SvBaseLink::UpdateResult
SwTransferDdeLink::DataChanged( const OUString
& ,
4441 // well, that's it with the link
4442 if( !m_bInDisconnect
)
4444 if( FindDocShell() && m_pDocShell
->GetView() )
4445 m_rTransfer
.RemoveDDELinkFormat( m_pDocShell
->GetView()->GetEditWin() );
4446 Disconnect( false );
4451 bool SwTransferDdeLink::WriteData( SvStream
& rStrm
)
4453 if( !m_xRefObj
.is() || !FindDocShell() )
4456 rtl_TextEncoding eEncoding
= osl_getThreadTextEncoding();
4457 const OString
aAppNm(OUStringToOString(
4458 Application::GetAppName(), eEncoding
));
4459 const OString
aTopic(OUStringToOString(
4460 m_pDocShell
->GetTitle(SFX_TITLE_FULLNAME
), eEncoding
));
4461 const OString
aName(OUStringToOString(m_sName
, eEncoding
));
4463 std::unique_ptr
<char[]> pMem(new char[ aAppNm
.getLength() + aTopic
.getLength() + aName
.getLength() + 4 ]);
4465 sal_Int32 nLen
= aAppNm
.getLength();
4466 memcpy( pMem
.get(), aAppNm
.getStr(), nLen
);
4468 memcpy( pMem
.get() + nLen
, aTopic
.getStr(), aTopic
.getLength() );
4469 nLen
= nLen
+ aTopic
.getLength();
4471 memcpy( pMem
.get() + nLen
, aName
.getStr(), aName
.getLength() );
4472 nLen
= nLen
+ aName
.getLength();
4476 rStrm
.WriteBytes( pMem
.get(), nLen
);
4479 IDocumentMarkAccess
* const pMarkAccess
= m_pDocShell
->GetDoc()->getIDocumentMarkAccess();
4480 IDocumentMarkAccess::const_iterator_t ppMark
= pMarkAccess
->findMark(m_sName
);
4481 if(ppMark
!= pMarkAccess
->getAllMarksEnd()
4482 && IDocumentMarkAccess::GetType(**ppMark
) != IDocumentMarkAccess::MarkType::BOOKMARK
)
4484 // the mark is still a DdeBookmark
4485 // we replace it with a Bookmark, so it will get saved etc.
4486 ::sw::mark::IMark
* const pMark
= *ppMark
;
4487 ::sfx2::SvLinkSource
* p
= m_xRefObj
.get();
4488 SwServerObject
& rServerObject
= dynamic_cast<SwServerObject
&>(*p
);
4490 // collecting state of old mark
4491 SwPaM
aPaM(pMark
->GetMarkStart());
4492 *aPaM
.GetPoint() = pMark
->GetMarkStart();
4493 if(pMark
->IsExpanded())
4496 *aPaM
.GetMark() = pMark
->GetMarkEnd();
4498 OUString sMarkName
= pMark
->GetName();
4501 rServerObject
.SetNoServer(); // this removes the connection between SwServerObject and mark
4502 // N.B. ppMark was not loaded from file and cannot have xml:id
4503 pMarkAccess
->deleteMark(ppMark
, false);
4505 // recreate as Bookmark
4506 ::sw::mark::IMark
* const pNewMark
= pMarkAccess
->makeMark(
4509 IDocumentMarkAccess::MarkType::BOOKMARK
,
4510 ::sw::mark::InsertMode::New
);
4511 rServerObject
.SetDdeBookmark(*pNewMark
);
4514 m_bDelBookmark
= false;
4518 void SwTransferDdeLink::Disconnect( bool bRemoveDataAdvise
)
4520 // don't accept DataChanged anymore, when already in Disconnect!
4521 // (DTOR from Bookmark sends a DataChanged!)
4522 bool bOldDisconnect
= m_bInDisconnect
;
4523 m_bInDisconnect
= true;
4525 // destroy the unused bookmark again (without Undo!)?
4526 if( m_bDelBookmark
&& m_xRefObj
.is() && FindDocShell() )
4528 SwDoc
* pDoc
= m_pDocShell
->GetDoc();
4529 ::sw::UndoGuard
const undoGuard(pDoc
->GetIDocumentUndoRedo());
4532 Link
<bool,void> aSavedOle2Link( pDoc
->GetOle2Link() );
4533 pDoc
->SetOle2Link( Link
<bool,void>() );
4535 bool bIsModified
= pDoc
->getIDocumentState().IsModified();
4537 IDocumentMarkAccess
* const pMarkAccess
= pDoc
->getIDocumentMarkAccess();
4538 pMarkAccess
->deleteMark(pMarkAccess
->findMark(m_sName
), false);
4541 pDoc
->getIDocumentState().ResetModified();
4543 pDoc
->SetOle2Link( aSavedOle2Link
);
4545 m_bDelBookmark
= false;
4548 if( m_xRefObj
.is() )
4550 m_xRefObj
->SetUpdateTimeout( m_nOldTimeOut
);
4551 m_xRefObj
->RemoveConnectAdvise( this );
4552 if( bRemoveDataAdvise
)
4553 // in a DataChanged the SelectionObject must NEVER be deleted
4554 // is already handled by the base class
4555 // (ADVISEMODE_ONLYONCE!!!!)
4556 // but always in normal Disconnect!
4557 m_xRefObj
->RemoveAllDataAdvise( this );
4560 m_bInDisconnect
= bOldDisconnect
;
4563 bool SwTransferDdeLink::FindDocShell()
4565 SfxObjectShell
* pTmpSh
= SfxObjectShell::GetFirst( checkSfxObjectShell
<SwDocShell
> );
4568 if( pTmpSh
== m_pDocShell
) // that's what we want to have
4570 if( m_pDocShell
->GetDoc() )
4572 break; // the Doc is not there anymore, so leave!
4574 pTmpSh
= SfxObjectShell::GetNext( *pTmpSh
, checkSfxObjectShell
<SwDocShell
> );
4577 m_pDocShell
= nullptr;
4581 void SwTransferDdeLink::Closed()
4583 if( !m_bInDisconnect
&& m_xRefObj
.is() )
4585 m_xRefObj
->RemoveAllDataAdvise( this );
4586 m_xRefObj
->RemoveConnectAdvise( this );
4591 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */