Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / sw / source / uibase / dochdl / swdtflvr.cxx
blob9d480675171baf74800b74fbba6c350deca6571f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
28 #include <svtools/embedtransfer.hxx>
29 #include <svtools/insdlg.hxx>
30 #include <unotools/tempfile.hxx>
31 #include <comphelper/processfactory.hxx>
32 #include <comphelper/servicehelper.hxx>
33 #include <comphelper/storagehelper.hxx>
34 #include <comphelper/string.hxx>
35 #include <unotools/ucbstreamhelper.hxx>
36 #include <sot/filelist.hxx>
37 #include <svx/svxdlg.hxx>
38 #include <toolkit/helper/vclunohelper.hxx>
39 #include <osl/endian.h>
40 #include <sfx2/linkmgr.hxx>
41 #include <tools/urlobj.hxx>
42 #include <vcl/wrkwin.hxx>
43 #include <vcl/layout.hxx>
44 #include <vcl/msgbox.hxx>
45 #include <sfx2/dispatch.hxx>
46 #include <svl/stritem.hxx>
47 #include <svtools/imap.hxx>
48 #include <sot/storage.hxx>
49 #include <vcl/graph.hxx>
50 #include <svl/urihelper.hxx>
51 #include <svx/svdmodel.hxx>
52 #include <svx/xexch.hxx>
53 #include <svx/xmlexchg.hxx>
54 #include <svx/dbaexchange.hxx>
55 #include <svx/clipfmtitem.hxx>
56 #include <sfx2/mieclip.hxx>
57 #include <svx/svdetc.hxx>
58 #include <svx/xoutbmp.hxx>
59 #include <svl/urlbmk.hxx>
60 #include <svtools/htmlout.hxx>
61 #include <svx/hlnkitem.hxx>
62 #include <svtools/inetimg.hxx>
63 #include <editeng/paperinf.hxx>
64 #include <svx/fmview.hxx>
65 #include <editeng/scripttypeitem.hxx>
66 #include <sfx2/docfilt.hxx>
67 #include <svtools/imapobj.hxx>
68 #include <sfx2/docfile.hxx>
69 #include <unotools/transliterationwrapper.hxx>
70 #include <unotools/streamwrap.hxx>
71 #include <vcl/graphicfilter.hxx>
73 #include <svx/unomodel.hxx>
74 #include <fmturl.hxx>
75 #include <fmtinfmt.hxx>
76 #include <fmtfsize.hxx>
77 #include <swdtflvr.hxx>
78 #include <shellio.hxx>
79 #include <ddefld.hxx>
80 #include <doc.hxx>
81 #include <IDocumentUndoRedo.hxx>
82 #include <IDocumentSettingAccess.hxx>
83 #include <IDocumentDeviceAccess.hxx>
84 #include <IDocumentDrawModelAccess.hxx>
85 #include <IDocumentFieldsAccess.hxx>
86 #include <IDocumentState.hxx>
87 #include <pagedesc.hxx>
88 #include <IMark.hxx>
89 #include <docary.hxx>
90 #include <section.hxx>
91 #include <ndtxt.hxx>
92 #include <edtdd.hxx>
93 #include <edtwin.hxx>
94 #include <navicont.hxx>
95 #include <swcont.hxx>
96 #include <wrtsh.hxx>
97 #include <swmodule.hxx>
98 #include <view.hxx>
99 #include <docsh.hxx>
100 #include <wdocsh.hxx>
101 #include <fldbas.hxx>
102 #include <swundo.hxx>
103 #include <pam.hxx>
104 #include <ndole.hxx>
105 #include <swwait.hxx>
106 #include <viewopt.hxx>
107 #include <swerror.h>
108 #include <SwCapObjType.hxx>
109 #include <cmdid.h>
110 #include <dochdl.hrc>
111 #include <comcore.hrc>
112 #include <sot/stg.hxx>
113 #include <svx/svditer.hxx>
114 #include <editeng/eeitem.hxx>
115 #include <editeng/fhgtitem.hxx>
116 #include <svx/svdpage.hxx>
117 #include <avmedia/mediawindow.hxx>
118 #include <swcrsr.hxx>
119 #include <SwRewriter.hxx>
120 #include <globals.hrc>
121 #include <app.hrc>
122 #include <osl/mutex.hxx>
123 #include <vcl/svapp.hxx>
124 #include <swserv.hxx>
125 #include <calbck.hxx>
126 #include <fmtmeta.hxx>
128 #include <vcl/GraphicNativeTransform.hxx>
129 #include <vcl/GraphicNativeMetadata.hxx>
130 #include <comphelper/lok.hxx>
131 #include <sfx2/classificationhelper.hxx>
132 #include <sfx2/sfxresid.hxx>
134 #include <memory>
136 #define OLESIZE 11905 - 2 * lMinBorder, 6 * MM50
138 #define SWTRANSFER_OBJECTTYPE_DRAWMODEL static_cast<SotClipboardFormatId>(0x00000001)
139 #define SWTRANSFER_OBJECTTYPE_HTML static_cast<SotClipboardFormatId>(0x00000002)
140 #define SWTRANSFER_OBJECTTYPE_RTF static_cast<SotClipboardFormatId>(0x00000004)
141 #define SWTRANSFER_OBJECTTYPE_STRING static_cast<SotClipboardFormatId>(0x00000008)
142 #define SWTRANSFER_OBJECTTYPE_SWOLE static_cast<SotClipboardFormatId>(0x00000010)
143 #define SWTRANSFER_OBJECTTYPE_DDE static_cast<SotClipboardFormatId>(0x00000020)
144 #define SWTRANSFER_OBJECTTYPE_RICHTEXT static_cast<SotClipboardFormatId>(0x00000040)
146 using namespace ::svx;
147 using namespace ::com::sun::star;
148 using namespace ::com::sun::star::uno;
149 using namespace ::com::sun::star::datatransfer;
151 #define DDE_TXT_ENCODING osl_getThreadTextEncoding()
153 class SwTrnsfrDdeLink : public ::sfx2::SvBaseLink
155 OUString sName;
156 ::sfx2::SvLinkSourceRef refObj;
157 SwTransferable& rTrnsfr;
158 SwDocShell* pDocShell;
159 sal_uLong nOldTimeOut;
160 bool bDelBookmrk : 1;
161 bool bInDisconnect : 1;
163 bool FindDocShell();
165 using sfx2::SvBaseLink::Disconnect;
167 protected:
168 virtual ~SwTrnsfrDdeLink() override;
170 public:
171 SwTrnsfrDdeLink( SwTransferable& rTrans, SwWrtShell& rSh );
173 virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
174 const OUString& rMimeType, const css::uno::Any & rValue ) override;
175 virtual void Closed() override;
177 bool WriteData( SvStream& rStrm );
179 void Disconnect( bool bRemoveDataAdvise );
182 // helper class for Action and Undo enclosing
183 class SwTrnsfrActionAndUndo
185 SwWrtShell *pSh;
186 public:
187 SwTrnsfrActionAndUndo( SwWrtShell *pS, bool bDelSel = false)
188 : pSh( pS )
190 pSh->StartUndo( SwUndoId::PASTE_CLIPBOARD );
191 if( bDelSel )
192 pSh->DelRight();
193 pSh->StartAllAction();
195 ~SwTrnsfrActionAndUndo()
197 pSh->EndUndo();
198 pSh->EndAllAction();
202 SwTransferable::SwTransferable( SwWrtShell& rSh )
203 : m_pWrtShell( &rSh ),
204 m_pCreatorView( nullptr ),
205 m_pClpDocFac( nullptr ),
206 m_pClpGraphic( nullptr ),
207 m_pClpBitmap( nullptr ),
208 m_pOrigGraphic( nullptr ),
209 m_pBookmark( nullptr ),
210 m_pImageMap( nullptr ),
211 m_pTargetURL( nullptr ),
212 m_eBufferType( TransferBufferType::NONE )
214 rSh.GetView().AddTransferable(*this);
215 SwDocShell* pDShell = rSh.GetDoc()->GetDocShell();
216 if( pDShell )
218 pDShell->FillTransferableObjectDescriptor( m_aObjDesc );
219 if( pDShell->GetMedium() )
221 const INetURLObject& rURLObj = pDShell->GetMedium()->GetURLObject();
222 m_aObjDesc.maDisplayName = URIHelper::removePassword(
223 rURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
224 INetURLObject::EncodeMechanism::WasEncoded,
225 INetURLObject::DecodeMechanism::Unambiguous );
228 PrepareOLE( m_aObjDesc );
232 SwTransferable::~SwTransferable()
234 SolarMutexGuard aSolarGuard;
236 // the DDELink still needs the WrtShell!
237 if( m_xDdeLink.is() )
239 static_cast<SwTrnsfrDdeLink*>( m_xDdeLink.get() )->Disconnect( true );
240 m_xDdeLink.clear();
243 m_pWrtShell = nullptr;
245 // release reference to the document so that aDocShellRef will delete
246 // it (if aDocShellRef is set). Otherwise, the OLE nodes keep references
247 // to their sub-storage when the storage is already dead.
248 delete m_pClpDocFac;
250 // first close, then the Ref. can be cleared as well, so that
251 // the DocShell really gets deleted!
252 if( m_aDocShellRef.Is() )
254 SfxObjectShell * pObj = m_aDocShellRef;
255 SwDocShell* pDocSh = static_cast<SwDocShell*>(pObj);
256 pDocSh->DoClose();
258 m_aDocShellRef.Clear();
260 SwModule* pMod = SW_MOD();
261 if(pMod)
263 if ( pMod->m_pDragDrop == this )
264 pMod->m_pDragDrop = nullptr;
265 else if ( pMod->m_pXSelection == this )
266 pMod->m_pXSelection = nullptr;
269 delete m_pClpGraphic;
270 delete m_pClpBitmap;
271 delete m_pImageMap;
272 delete m_pTargetURL;
273 delete m_pBookmark;
275 m_eBufferType = TransferBufferType::NONE;
278 static SwDoc * lcl_GetDoc(SwDocFac & rDocFac)
280 SwDoc *const pDoc = rDocFac.GetDoc();
281 OSL_ENSURE( pDoc, "Document not found" );
282 if (pDoc)
284 pDoc->SetClipBoard( true );
286 return pDoc;
289 void SwTransferable::ObjectReleased()
291 SwModule *pMod = SW_MOD();
292 if( this == pMod->m_pDragDrop )
293 pMod->m_pDragDrop = nullptr;
294 else if( this == pMod->m_pXSelection )
295 pMod->m_pXSelection = nullptr;
298 void SwTransferable::AddSupportedFormats()
300 // only need if we are the current XSelection Object
301 SwModule *pMod = SW_MOD();
302 if( this == pMod->m_pXSelection || comphelper::LibreOfficeKit::isActive())
304 SetDataForDragAndDrop( Point( 0,0) );
308 void SwTransferable::InitOle( SfxObjectShell* pDoc, SwDoc& rDoc )
310 //set OleVisArea. Upper left corner of the page and size of
311 //RealSize in Twips.
312 const Size aSz( OLESIZE );
313 SwRect aVis( Point( DOCUMENTBORDER, DOCUMENTBORDER ), aSz );
314 pDoc->SetVisArea( aVis.SVRect() );
315 rDoc.getIDocumentSettingAccess().set(DocumentSettingId::BROWSE_MODE, true );
318 uno::Reference < embed::XEmbeddedObject > SwTransferable::FindOLEObj( sal_Int64& nAspect ) const
320 uno::Reference < embed::XEmbeddedObject > xObj;
321 if( m_pClpDocFac )
323 SwIterator<SwContentNode,SwFormatColl> aIter( *m_pClpDocFac->GetDoc()->GetDfltGrfFormatColl() );
324 for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
325 if( SwNodeType::Ole == pNd->GetNodeType() )
327 xObj = static_cast<SwOLENode*>(pNd)->GetOLEObj().GetOleRef();
328 nAspect = static_cast<SwOLENode*>(pNd)->GetAspect();
329 break;
332 return xObj;
335 const Graphic* SwTransferable::FindOLEReplacementGraphic() const
337 if( m_pClpDocFac )
339 SwIterator<SwContentNode,SwFormatColl> aIter( *m_pClpDocFac->GetDoc()->GetDfltGrfFormatColl() );
340 for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
341 if( SwNodeType::Ole == pNd->GetNodeType() )
343 return static_cast<SwOLENode*>(pNd)->GetGraphic();
347 return nullptr;
350 void SwTransferable::RemoveDDELinkFormat( const vcl::Window& rWin )
352 RemoveFormat( SotClipboardFormatId::LINK );
353 CopyToClipboard( const_cast<vcl::Window*>(&rWin) );
356 namespace
358 //Resolves: fdo#40717 surely when we create a clipboard document we should
359 //overwrite the clipboard documents styles and settings with that of the
360 //source, so that we can WYSIWYG paste. If we want that the destinations
361 //styles are used over the source styles, that's a matter of the
362 //destination paste code to handle, not the source paste code.
363 void lclOverWriteDoc(SwWrtShell &rSrcWrtShell, SwDoc &rDest)
365 const SwDoc &rSrc = *rSrcWrtShell.GetDoc();
367 rDest.ReplaceCompatibilityOptions(rSrc);
368 rDest.ReplaceDefaults(rSrc);
370 //It would probably make most sense here to only insert the styles used
371 //by the selection, e.g. apply SwDoc::IsUsed on styles ?
372 rDest.ReplaceStyles(rSrc, false);
374 rSrcWrtShell.Copy(&rDest);
376 rDest.GetMetaFieldManager().copyDocumentProperties(rSrc);
379 void lclCheckAndPerformRotation(Graphic& aGraphic)
381 GraphicNativeMetadata aMetadata;
382 if ( aMetadata.read(aGraphic) )
384 sal_uInt16 aRotation = aMetadata.getRotation();
385 if (aRotation != 0)
387 ScopedVclPtrInstance< MessageDialog > aQueryBox(
388 nullptr, "QueryRotateIntoStandardOrientationDialog",
389 "modules/swriter/ui/queryrotateintostandarddialog.ui");
390 if (aQueryBox->Execute() == RET_YES)
392 GraphicNativeTransform aTransform( aGraphic );
393 aTransform.rotate( aRotation );
400 bool SwTransferable::GetData( const DataFlavor& rFlavor, const OUString& rDestDoc )
402 SotClipboardFormatId nFormat = SotExchange::GetFormat( rFlavor );
404 // we can only fulfil the request if
405 // 1) we have data for this format
406 // 2) we have either a clipboard document (pClpDocFac), or
407 // we have a SwWrtShell (so we can generate a new clipboard document)
408 if( !HasFormat( nFormat ) || ( m_pClpDocFac == nullptr && m_pWrtShell == nullptr ) )
409 return false;
411 if( !m_pClpDocFac )
413 SelectionType nSelectionType = m_pWrtShell->GetSelectionType();
415 // when pending we will not get the correct type, but SelectionType::Text
416 // as fallback. This *happens* during D&D, so we need to check if we are in
417 // the fallback and just try to get a graphic
418 const bool bPending(m_pWrtShell->ActionPend());
420 // SEL_GRF is from ContentType of editsh
421 if(bPending || ((SelectionType::Graphic | SelectionType::DbForm) & nSelectionType))
423 m_pClpGraphic = new Graphic;
424 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_pClpGraphic ))
425 m_pOrigGraphic = m_pClpGraphic;
426 m_pClpBitmap = new Graphic;
427 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_pClpBitmap ))
428 m_pOrigGraphic = m_pClpBitmap;
430 // is it an URL-Button ?
431 OUString sURL;
432 OUString sDesc;
433 if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) )
435 m_pBookmark = new INetBookmark( sURL, sDesc );
436 m_eBufferType = TransferBufferType::InetField;
440 m_pClpDocFac = new SwDocFac;
441 SwDoc *const pTmpDoc = lcl_GetDoc(*m_pClpDocFac);
443 pTmpDoc->getIDocumentFieldsAccess().LockExpFields(); // never update fields - leave text as it is
444 lclOverWriteDoc(*m_pWrtShell, *pTmpDoc);
446 // in CORE a new one was created (OLE-objects copied!)
447 m_aDocShellRef = pTmpDoc->GetTmpDocShell();
448 if( m_aDocShellRef.Is() )
449 SwTransferable::InitOle( m_aDocShellRef, *pTmpDoc );
450 pTmpDoc->SetTmpDocShell( nullptr );
452 if( nSelectionType & SelectionType::Text && !m_pWrtShell->HasMark() )
454 SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
456 Point aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY());
458 bool bSelect = g_bExecuteDrag &&
459 m_pWrtShell->GetView().GetDocShell() &&
460 !m_pWrtShell->GetView().GetDocShell()->IsReadOnly();
461 if( m_pWrtShell->GetContentAtPos( aPos, aContentAtPos, bSelect ) )
463 m_pBookmark = new INetBookmark(
464 static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)->GetValue(),
465 aContentAtPos.sStr );
466 m_eBufferType = TransferBufferType::InetField;
467 if( bSelect )
468 m_pWrtShell->SelectTextAttr( RES_TXTATR_INETFMT );
471 if( m_pWrtShell->IsFrameSelected() )
473 SfxItemSet aSet( m_pWrtShell->GetAttrPool(), RES_URL, RES_URL );
474 m_pWrtShell->GetFlyFrameAttr( aSet );
475 const SwFormatURL& rURL = static_cast<const SwFormatURL&>(aSet.Get( RES_URL ));
476 if( rURL.GetMap() )
477 m_pImageMap = new ImageMap( *rURL.GetMap() );
478 else if( !rURL.GetURL().isEmpty() )
479 m_pTargetURL = new INetImage( aEmptyOUStr, rURL.GetURL(),
480 rURL.GetTargetFrameName() );
484 bool bOK = false;
485 if( TransferBufferType::Ole == m_eBufferType )
487 //TODO/MBA: testing - is this the "single OLE object" case?!
488 // get OLE-Object from ClipDoc and get the data from that.
489 sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT; // will be set in the next statement
490 uno::Reference < embed::XEmbeddedObject > xObj = FindOLEObj( nAspect );
491 const Graphic* pOLEGraph = FindOLEReplacementGraphic();
492 if( xObj.is() )
494 TransferableDataHelper aD( new SvEmbedTransferHelper( xObj, pOLEGraph, nAspect ) );
495 uno::Any aAny = aD.GetAny(rFlavor, rDestDoc);
496 if( aAny.hasValue() )
497 bOK = SetAny( aAny );
500 // the following solution will be used in the case when the object can not generate the image
501 // TODO/LATER: in future the transferhelper must probably be created based on object and the replacement stream
502 // TODO: Block not required now, SvEmbedTransferHelper should be able to handle GDIMetaFile format
503 if ( nFormat == SotClipboardFormatId::GDIMETAFILE )
505 pOLEGraph = FindOLEReplacementGraphic();
506 if ( pOLEGraph )
507 bOK = SetGDIMetaFile( pOLEGraph->GetGDIMetaFile() );
510 else
512 switch( nFormat )
514 case SotClipboardFormatId::LINK:
515 if( m_xDdeLink.is() )
516 bOK = SetObject( m_xDdeLink.get(), SWTRANSFER_OBJECTTYPE_DDE, rFlavor );
517 break;
519 case SotClipboardFormatId::OBJECTDESCRIPTOR:
520 case SotClipboardFormatId::LINKSRCDESCRIPTOR:
521 bOK = SetTransferableObjectDescriptor( m_aObjDesc );
522 break;
524 case SotClipboardFormatId::DRAWING:
526 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
527 bOK = SetObject( pDoc->getIDocumentDrawModelAccess().GetDrawModel(),
528 SWTRANSFER_OBJECTTYPE_DRAWMODEL, rFlavor );
530 break;
532 case SotClipboardFormatId::STRING:
534 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
535 bOK = SetObject( pDoc, SWTRANSFER_OBJECTTYPE_STRING, rFlavor );
537 break;
538 case SotClipboardFormatId::RTF:
540 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
541 bOK = SetObject( pDoc, SWTRANSFER_OBJECTTYPE_RTF, rFlavor );
543 break;
544 case SotClipboardFormatId::RICHTEXT:
546 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
547 bOK = SetObject( pDoc, SWTRANSFER_OBJECTTYPE_RICHTEXT, rFlavor );
549 break;
551 case SotClipboardFormatId::HTML:
553 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
554 bOK = SetObject( pDoc, SWTRANSFER_OBJECTTYPE_HTML, rFlavor );
556 break;
558 case SotClipboardFormatId::SVXB:
559 if( m_eBufferType & TransferBufferType::Graphic && m_pOrigGraphic )
560 bOK = SetGraphic( *m_pOrigGraphic );
561 break;
563 case SotClipboardFormatId::GDIMETAFILE:
564 if( m_eBufferType & TransferBufferType::Graphic )
565 bOK = SetGDIMetaFile( m_pClpGraphic->GetGDIMetaFile() );
566 break;
567 case SotClipboardFormatId::BITMAP:
568 case SotClipboardFormatId::PNG:
569 // Neither pClpBitmap nor pClpGraphic are necessarily set
570 if( (m_eBufferType & TransferBufferType::Graphic) && (m_pClpBitmap != nullptr || m_pClpGraphic != nullptr))
571 bOK = SetBitmapEx( (m_pClpBitmap ? m_pClpBitmap : m_pClpGraphic)->GetBitmapEx(), rFlavor );
572 break;
574 case SotClipboardFormatId::SVIM:
575 if( m_pImageMap )
576 bOK = SetImageMap( *m_pImageMap );
577 break;
579 case SotClipboardFormatId::INET_IMAGE:
580 if( m_pTargetURL )
581 bOK = SetINetImage( *m_pTargetURL, rFlavor );
582 break;
584 case SotClipboardFormatId::SOLK:
585 case SotClipboardFormatId::NETSCAPE_BOOKMARK:
586 case SotClipboardFormatId::FILEGRPDESCRIPTOR:
587 case SotClipboardFormatId::FILECONTENT:
588 case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
589 case SotClipboardFormatId::SIMPLE_FILE:
590 if( (TransferBufferType::InetField & m_eBufferType) && m_pBookmark )
591 bOK = SetINetBookmark( *m_pBookmark, rFlavor );
592 break;
594 case SotClipboardFormatId::EMBED_SOURCE:
595 if( !m_aDocShellRef.Is() )
597 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
598 SwDocShell* pNewDocSh = new SwDocShell( pDoc,
599 SfxObjectCreateMode::EMBEDDED );
600 m_aDocShellRef = pNewDocSh;
601 m_aDocShellRef->DoInitNew();
602 SwTransferable::InitOle( m_aDocShellRef, *pDoc );
604 bOK = SetObject( &m_aDocShellRef, SWTRANSFER_OBJECTTYPE_SWOLE,
605 rFlavor );
606 break;
607 default: break;
610 return bOK;
613 bool SwTransferable::WriteObject( tools::SvRef<SotStorageStream>& xStream,
614 void* pObject, SotClipboardFormatId nObjectType,
615 const DataFlavor& /*rFlavor*/ )
617 bool bRet = false;
618 WriterRef xWrt;
620 switch( nObjectType )
622 case SWTRANSFER_OBJECTTYPE_DRAWMODEL:
624 // don't change the sequence of commands
625 SdrModel *pModel = static_cast<SdrModel*>(pObject);
626 xStream->SetBufferSize( 16348 );
628 // for the changed pool defaults from drawing layer pool set those
629 // attributes as hard attributes to preserve them for saving
630 const SfxItemPool& rItemPool = pModel->GetItemPool();
631 const SvxFontHeightItem& rDefaultFontHeight = static_cast<const SvxFontHeightItem&>(rItemPool.GetDefaultItem(EE_CHAR_FONTHEIGHT));
633 // SW should have no MasterPages
634 OSL_ENSURE(0L == pModel->GetMasterPageCount(), "SW with MasterPages (!)");
636 for(sal_uInt16 a(0); a < pModel->GetPageCount(); a++)
638 const SdrPage* pPage = pModel->GetPage(a);
639 SdrObjListIter aIter(*pPage, SdrIterMode::DeepNoGroups);
641 while(aIter.IsMore())
643 SdrObject* pObj = aIter.Next();
644 const SvxFontHeightItem& rItem = static_cast<const SvxFontHeightItem&>(pObj->GetMergedItem(EE_CHAR_FONTHEIGHT));
646 if(rItem.GetHeight() == rDefaultFontHeight.GetHeight())
648 pObj->SetMergedItem(rDefaultFontHeight);
654 uno::Reference<io::XOutputStream> xDocOut( new utl::OOutputStreamWrapper( *xStream ) );
655 if( SvxDrawingLayerExport( pModel, xDocOut ) )
656 xStream->Commit();
659 bRet = ERRCODE_NONE == xStream->GetError();
661 break;
663 case SWTRANSFER_OBJECTTYPE_SWOLE:
665 SfxObjectShell* pEmbObj = static_cast<SfxObjectShell*>(pObject);
668 ::utl::TempFile aTempFile;
669 aTempFile.EnableKillingFile();
670 uno::Reference< embed::XStorage > xWorkStore =
671 ::comphelper::OStorageHelper::GetStorageFromURL( aTempFile.GetURL(), embed::ElementModes::READWRITE );
673 // write document storage
674 pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, false );
675 // mba: no BaseURL for clipboard
676 SfxMedium aMedium( xWorkStore, OUString() );
677 pEmbObj->DoSaveObjectAs( aMedium, false );
678 pEmbObj->DoSaveCompleted();
680 uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY );
681 if ( xTransact.is() )
682 xTransact->commit();
684 std::unique_ptr<SvStream> pSrcStm(::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), StreamMode::READ ));
685 if( pSrcStm )
687 xStream->SetBufferSize( 0xff00 );
688 xStream->WriteStream( *pSrcStm );
689 pSrcStm.reset();
692 xWorkStore->dispose();
693 xWorkStore.clear();
694 xStream->Commit();
696 catch (const uno::Exception&)
700 bRet = ( xStream->GetError() == ERRCODE_NONE );
702 break;
704 case SWTRANSFER_OBJECTTYPE_DDE:
706 xStream->SetBufferSize( 1024 );
707 SwTrnsfrDdeLink* pDdeLnk = static_cast<SwTrnsfrDdeLink*>(pObject);
708 if( pDdeLnk->WriteData( *xStream ) )
710 xStream->Commit();
711 bRet = ERRCODE_NONE == xStream->GetError();
714 break;
716 case SWTRANSFER_OBJECTTYPE_HTML:
717 GetHTMLWriter( aEmptyOUStr, OUString(), xWrt );
718 break;
720 case SWTRANSFER_OBJECTTYPE_RTF:
721 case SWTRANSFER_OBJECTTYPE_RICHTEXT:
722 GetRTFWriter( aEmptyOUStr, OUString(), xWrt );
723 break;
725 case SWTRANSFER_OBJECTTYPE_STRING:
726 GetASCWriter( aEmptyOUStr, OUString(), xWrt );
727 if( xWrt.is() )
729 SwAsciiOptions aAOpt;
730 aAOpt.SetCharSet( RTL_TEXTENCODING_UTF8 );
731 xWrt->SetAsciiOptions( aAOpt );
733 // no start char for clipboard
734 xWrt->bUCS2_WithStartChar = false;
736 break;
737 default: break;
740 if( xWrt.is() )
742 SwDoc* pDoc = static_cast<SwDoc*>(pObject);
743 xWrt->bWriteClipboardDoc = true;
744 xWrt->bWriteOnlyFirstTable = bool(TransferBufferType::Table & m_eBufferType);
745 xWrt->SetShowProgress(false);
747 #if defined(DEBUGPASTE)
748 SvFileStream aPasteDebug(OUString(
749 "PASTEBUFFER.debug"), StreamMode::WRITE|StreamMode::TRUNC);
750 SwWriter aDbgWrt( aPasteDebug, *pDoc );
751 aDbgWrt.Write( xWrt );
752 #endif
754 SwWriter aWrt( *xStream, *pDoc );
755 if( !IsError( aWrt.Write( xWrt )) )
757 xStream->WriteChar( '\0' ); // terminate with a zero
758 xStream->Commit();
759 bRet = true;
763 return bRet;
766 int SwTransferable::Cut()
768 int nRet = Copy( true );
769 if( nRet )
770 DeleteSelection();
771 return nRet;
774 void SwTransferable::DeleteSelection()
776 if(!m_pWrtShell)
777 return;
778 // ask for type of selection before action-bracketing
779 const SelectionType nSelection = m_pWrtShell->GetSelectionType();
780 m_pWrtShell->StartUndo( SwUndoId::START );
781 if( ( SelectionType::Text | SelectionType::Table ) & nSelection )
782 m_pWrtShell->IntelligentCut( nSelection );
783 m_pWrtShell->DelRight();
784 m_pWrtShell->EndUndo( SwUndoId::END );
787 int SwTransferable::PrepareForCopy( bool bIsCut )
789 int nRet = 1;
790 if(!m_pWrtShell)
791 return 0;
793 OUString sGrfNm;
794 const SelectionType nSelection = m_pWrtShell->GetSelectionType();
795 if( nSelection == SelectionType::Graphic )
797 m_pClpGraphic = new Graphic;
798 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_pClpGraphic ))
799 m_pOrigGraphic = m_pClpGraphic;
800 m_pClpBitmap = new Graphic;
801 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_pClpBitmap ))
802 m_pOrigGraphic = m_pClpBitmap;
804 m_pClpDocFac = new SwDocFac;
805 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
806 m_pWrtShell->Copy( pDoc );
808 if (m_pOrigGraphic && !m_pOrigGraphic->GetBitmap().IsEmpty())
809 AddFormat( SotClipboardFormatId::SVXB );
811 PrepareOLE( m_aObjDesc );
812 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
814 const Graphic* pGrf = m_pWrtShell->GetGraphic();
815 if( pGrf && pGrf->IsSupportedGraphic() )
817 AddFormat( SotClipboardFormatId::GDIMETAFILE );
818 AddFormat( SotClipboardFormatId::PNG );
819 AddFormat( SotClipboardFormatId::BITMAP );
821 m_eBufferType = TransferBufferType::Graphic;
822 m_pWrtShell->GetGrfNms( &sGrfNm, nullptr );
824 else if ( nSelection == SelectionType::Ole )
826 m_pClpDocFac = new SwDocFac;
827 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
828 m_aDocShellRef = new SwDocShell( pDoc, SfxObjectCreateMode::EMBEDDED);
829 m_aDocShellRef->DoInitNew();
830 m_pWrtShell->Copy( pDoc );
832 AddFormat( SotClipboardFormatId::EMBED_SOURCE );
834 // --> OD #i98753#
835 // set size of embedded object at the object description structure
836 m_aObjDesc.maSize = OutputDevice::LogicToLogic( m_pWrtShell->GetObjSize(), MapUnit::MapTwip, MapUnit::Map100thMM );
837 // <--
838 PrepareOLE( m_aObjDesc );
839 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
841 AddFormat( SotClipboardFormatId::GDIMETAFILE );
843 // Fetch the formats supported via embedtransferhelper as well
844 sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
845 uno::Reference < embed::XEmbeddedObject > xObj = FindOLEObj( nAspect );
846 const Graphic* pOLEGraph = FindOLEReplacementGraphic();
847 if( xObj.is() )
849 TransferableDataHelper aD( new SvEmbedTransferHelper( xObj, pOLEGraph, nAspect ) );
850 if ( aD.GetTransferable().is() )
852 DataFlavorExVector aVector( aD.GetDataFlavorExVector() );
853 DataFlavorExVector::iterator aIter( aVector.begin() ), aEnd( aVector.end() );
855 while( aIter != aEnd )
856 AddFormat( *aIter++ );
859 m_eBufferType = TransferBufferType::Ole;
861 // Is there anything to provide anyway?
862 else if ( m_pWrtShell->IsSelection() || m_pWrtShell->IsFrameSelected() ||
863 m_pWrtShell->IsObjSelected() )
865 std::unique_ptr<SwWait> pWait;
866 if( m_pWrtShell->ShouldWait() )
867 pWait.reset(new SwWait( *m_pWrtShell->GetView().GetDocShell(), true ));
869 m_pClpDocFac = new SwDocFac;
871 // create additional cursor so that equal treatment of keyboard
872 // and mouse selection is possible.
873 // In AddMode with keyboard selection, the new cursor is not created
874 // before the cursor is moved after end of selection.
875 if( m_pWrtShell->IsAddMode() && m_pWrtShell->SwCursorShell::HasSelection() )
876 m_pWrtShell->CreateCursor();
878 SwDoc *const pTmpDoc = lcl_GetDoc(*m_pClpDocFac);
880 pTmpDoc->getIDocumentFieldsAccess().LockExpFields(); // Never update fields - leave text as is
881 lclOverWriteDoc(*m_pWrtShell, *pTmpDoc);
884 IDocumentMarkAccess* const pMarkAccess = pTmpDoc->getIDocumentMarkAccess();
885 std::vector< ::sw::mark::IMark* > vDdeMarks;
886 // find all DDE-Bookmarks
887 for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getAllMarksBegin();
888 ppMark != pMarkAccess->getAllMarksEnd();
889 ++ppMark)
891 if(IDocumentMarkAccess::MarkType::DDE_BOOKMARK == IDocumentMarkAccess::GetType(**ppMark))
892 vDdeMarks.push_back(ppMark->get());
894 // remove all DDE-Bookmarks, they are invalid inside the clipdoc!
895 for(std::vector< ::sw::mark::IMark* >::iterator ppMark = vDdeMarks.begin();
896 ppMark != vDdeMarks.end();
897 ++ppMark)
898 pMarkAccess->deleteMark(*ppMark);
901 // a new one was created in CORE (OLE objects copied!)
902 m_aDocShellRef = pTmpDoc->GetTmpDocShell();
903 if( m_aDocShellRef.Is() )
904 SwTransferable::InitOle( m_aDocShellRef, *pTmpDoc );
905 pTmpDoc->SetTmpDocShell( nullptr );
907 if( m_pWrtShell->IsObjSelected() )
908 m_eBufferType = TransferBufferType::Drawing;
909 else
911 m_eBufferType = TransferBufferType::Document;
912 if (m_pWrtShell->IntelligentCut(nSelection, false) != SwWrtShell::NO_WORD)
913 m_eBufferType = TransferBufferType::DocumentWord | m_eBufferType;
916 bool bDDELink = m_pWrtShell->IsSelection();
917 if( nSelection & SelectionType::TableCell )
919 m_eBufferType = TransferBufferType::Table | m_eBufferType;
920 bDDELink = m_pWrtShell->HasWholeTabSelection();
923 //When someone needs it, we 'OLE' him something
924 AddFormat( SotClipboardFormatId::EMBED_SOURCE );
926 //put RTF ahead of the OLE's Metafile to have less loss
927 if( !m_pWrtShell->IsObjSelected() )
929 AddFormat( SotClipboardFormatId::RTF );
930 AddFormat( SotClipboardFormatId::RICHTEXT );
931 AddFormat( SotClipboardFormatId::HTML );
933 if( m_pWrtShell->IsSelection() )
934 AddFormat( SotClipboardFormatId::STRING );
936 if( nSelection & ( SelectionType::DrawObject | SelectionType::DbForm ))
938 AddFormat( SotClipboardFormatId::DRAWING );
939 if ( nSelection & SelectionType::DrawObject )
941 AddFormat( SotClipboardFormatId::GDIMETAFILE );
942 AddFormat( SotClipboardFormatId::PNG );
943 AddFormat( SotClipboardFormatId::BITMAP );
945 m_eBufferType = (TransferBufferType)( TransferBufferType::Graphic | m_eBufferType );
947 m_pClpGraphic = new Graphic;
948 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_pClpGraphic ))
949 m_pOrigGraphic = m_pClpGraphic;
950 m_pClpBitmap = new Graphic;
951 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_pClpBitmap ))
952 m_pOrigGraphic = m_pClpBitmap;
954 // is it an URL-Button ?
955 OUString sURL;
956 OUString sDesc;
957 if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) )
959 AddFormat( SotClipboardFormatId::STRING );
960 AddFormat( SotClipboardFormatId::SOLK );
961 AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
962 AddFormat( SotClipboardFormatId::FILECONTENT );
963 AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
964 AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
965 m_eBufferType = TransferBufferType::InetField | m_eBufferType;
966 nRet = 1;
970 // at Cut, DDE-Link doesn't make sense!!
971 SwDocShell* pDShell;
972 if( !bIsCut && bDDELink &&
973 nullptr != ( pDShell = m_pWrtShell->GetDoc()->GetDocShell()) &&
974 SfxObjectCreateMode::STANDARD == pDShell->GetCreateMode() )
976 AddFormat( SotClipboardFormatId::LINK );
977 m_xDdeLink = new SwTrnsfrDdeLink( *this, *m_pWrtShell );
980 //ObjectDescriptor was already filly from the old DocShell.
981 //Now adjust it. Thus in GetData the first query can still
982 //be answered with delayed rendering.
983 Size aSz( OLESIZE );
984 m_aObjDesc.maSize = OutputDevice::LogicToLogic( aSz, MapUnit::MapTwip, MapUnit::Map100thMM );
986 PrepareOLE( m_aObjDesc );
987 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
989 else
990 nRet = 0;
992 if( m_pWrtShell->IsFrameSelected() )
994 SfxItemSet aSet( m_pWrtShell->GetAttrPool(), RES_URL, RES_URL );
995 m_pWrtShell->GetFlyFrameAttr( aSet );
996 const SwFormatURL& rURL = static_cast<const SwFormatURL&>(aSet.Get( RES_URL ));
997 if( rURL.GetMap() )
999 m_pImageMap = new ImageMap( *rURL.GetMap() );
1000 AddFormat( SotClipboardFormatId::SVIM );
1002 else if( !rURL.GetURL().isEmpty() )
1004 m_pTargetURL = new INetImage( sGrfNm, rURL.GetURL(),
1005 rURL.GetTargetFrameName() );
1006 AddFormat( SotClipboardFormatId::INET_IMAGE );
1010 return nRet;
1013 int SwTransferable::Copy( bool bIsCut )
1015 int nRet = PrepareForCopy( bIsCut );
1016 if ( nRet )
1018 CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
1020 return nRet;
1023 void SwTransferable::CalculateAndCopy()
1025 if(!m_pWrtShell)
1026 return;
1027 SwWait aWait( *m_pWrtShell->GetView().GetDocShell(), true );
1029 OUString aStr( m_pWrtShell->Calculate() );
1031 m_pClpDocFac = new SwDocFac;
1032 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
1033 m_pWrtShell->Copy(pDoc, & aStr);
1034 m_eBufferType = TransferBufferType::Document;
1035 AddFormat( SotClipboardFormatId::STRING );
1037 CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
1040 int SwTransferable::CopyGlossary( SwTextBlocks& rGlossary, const OUString& rStr )
1042 if(!m_pWrtShell)
1043 return 0;
1044 SwWait aWait( *m_pWrtShell->GetView().GetDocShell(), true );
1046 m_pClpDocFac = new SwDocFac;
1047 SwDoc *const pCDoc = lcl_GetDoc(*m_pClpDocFac);
1049 SwNodes& rNds = pCDoc->GetNodes();
1050 SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
1051 SwContentNode* pCNd = rNds.GoNext( &aNodeIdx ); // go to 1st ContentNode
1052 SwPaM aPam( *pCNd );
1054 pCDoc->getIDocumentFieldsAccess().LockExpFields(); // never update fields - leave text as it is
1056 pCDoc->InsertGlossary( rGlossary, rStr, aPam );
1058 // a new one was created in CORE (OLE-Objects copied!)
1059 m_aDocShellRef = pCDoc->GetTmpDocShell();
1060 if( m_aDocShellRef.Is() )
1061 SwTransferable::InitOle( m_aDocShellRef, *pCDoc );
1062 pCDoc->SetTmpDocShell( nullptr );
1064 m_eBufferType = TransferBufferType::Document;
1066 //When someone needs it, we 'OLE' her something.
1067 AddFormat( SotClipboardFormatId::EMBED_SOURCE );
1068 AddFormat( SotClipboardFormatId::RTF );
1069 AddFormat( SotClipboardFormatId::RICHTEXT );
1070 AddFormat( SotClipboardFormatId::HTML );
1071 AddFormat( SotClipboardFormatId::STRING );
1073 //ObjectDescriptor was already filled from the old DocShell.
1074 //Now adjust it. Thus in GetData the first query can still
1075 //be answered with delayed rendering.
1076 Size aSz( OLESIZE );
1077 m_aObjDesc.maSize = OutputDevice::LogicToLogic( aSz, MapUnit::MapTwip, MapUnit::Map100thMM );
1079 PrepareOLE( m_aObjDesc );
1080 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
1082 CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
1084 return 1;
1087 static inline uno::Reference < XTransferable > * lcl_getTransferPointer ( uno::Reference < XTransferable > &xRef )
1089 return &xRef;
1092 bool SwTransferable::IsPaste( const SwWrtShell& rSh,
1093 const TransferableDataHelper& rData )
1095 // Check the common case first: We can always paste our own data!
1096 // If _only_ the internal format can be pasted, this check will
1097 // yield 'true', while the one below would give a (wrong) result 'false'.
1099 bool bIsPaste = ( GetSwTransferable( rData ) != nullptr );
1101 // if it's not our own data, we need to have a closer look:
1102 if( ! bIsPaste )
1104 // determine the proper paste action, and return true if we find one
1105 uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
1107 SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
1108 sal_uInt16 nSourceOptions =
1109 (( SotExchangeDest::DOC_TEXTFRAME == nDestination ||
1110 SotExchangeDest::SWDOC_FREE_AREA == nDestination ||
1111 SotExchangeDest::DOC_TEXTFRAME_WEB == nDestination ||
1112 SotExchangeDest::SWDOC_FREE_AREA_WEB == nDestination )
1113 ? EXCHG_IN_ACTION_COPY
1114 : EXCHG_IN_ACTION_MOVE);
1116 SotClipboardFormatId nFormat; // output param for GetExchangeAction
1117 sal_uInt8 nEventAction; // output param for GetExchangeAction
1118 sal_uInt8 nAction = SotExchange::GetExchangeAction(
1119 rData.GetDataFlavorExVector(),
1120 nDestination,
1121 nSourceOptions, /* ?? */
1122 EXCHG_IN_ACTION_DEFAULT, /* ?? */
1123 nFormat, nEventAction, SotClipboardFormatId::NONE,
1124 lcl_getTransferPointer ( xTransferable ) );
1126 // if we find a suitable action, we can paste!
1127 bIsPaste = (EXCHG_INOUT_ACTION_NONE != nAction);
1130 return bIsPaste;
1133 bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndStdIds nAnchorType)
1135 sal_uInt8 nEventAction, nAction=0;
1136 SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
1137 SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
1138 SotExchangeActionFlags nActionFlags = SotExchangeActionFlags::NONE;
1140 if( GetSwTransferable( rData ) )
1142 nAction = EXCHG_OUT_ACTION_INSERT_PRIVATE;
1144 else
1146 sal_uInt16 nSourceOptions =
1147 (( SotExchangeDest::DOC_TEXTFRAME == nDestination ||
1148 SotExchangeDest::SWDOC_FREE_AREA == nDestination ||
1149 SotExchangeDest::DOC_TEXTFRAME_WEB == nDestination ||
1150 SotExchangeDest::SWDOC_FREE_AREA_WEB == nDestination )
1151 ? EXCHG_IN_ACTION_COPY
1152 : EXCHG_IN_ACTION_MOVE);
1153 uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
1154 nAction = SotExchange::GetExchangeAction(
1155 rData.GetDataFlavorExVector(),
1156 nDestination,
1157 nSourceOptions, /* ?? */
1158 EXCHG_IN_ACTION_DEFAULT, /* ?? */
1159 nFormat, nEventAction, SotClipboardFormatId::NONE,
1160 lcl_getTransferPointer ( xTransferable ),
1161 &nActionFlags );
1164 // special case for tables from draw application
1165 if( EXCHG_OUT_ACTION_INSERT_DRAWOBJ == nAction )
1167 if( rData.HasFormat( SotClipboardFormatId::RTF ) )
1169 nAction = EXCHG_OUT_ACTION_INSERT_STRING;
1170 nFormat = SotClipboardFormatId::RTF;
1172 else if( rData.HasFormat( SotClipboardFormatId::RICHTEXT ) )
1174 nAction = EXCHG_OUT_ACTION_INSERT_STRING;
1175 nFormat = SotClipboardFormatId::RICHTEXT;
1179 return EXCHG_INOUT_ACTION_NONE != nAction &&
1180 SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
1181 nDestination, false, false, nullptr, 0, false, nAnchorType );
1184 bool SwTransferable::PasteData( TransferableDataHelper& rData,
1185 SwWrtShell& rSh, sal_uInt8 nAction, SotExchangeActionFlags nActionFlags,
1186 SotClipboardFormatId nFormat,
1187 SotExchangeDest nDestination, bool bIsPasteFormat,
1188 bool bIsDefault,
1189 const Point* pPt, sal_Int8 nDropAction,
1190 bool bPasteSelection, RndStdIds nAnchorType )
1192 SwWait aWait( *rSh.GetView().GetDocShell(), false );
1193 std::unique_ptr<SwTrnsfrActionAndUndo> pAction;
1194 SwModule* pMod = SW_MOD();
1196 bool bRet = false;
1197 bool bCallAutoCaption = false;
1199 if( pPt )
1201 // external Drop
1202 if( bPasteSelection ? !pMod->m_pXSelection : !pMod->m_pDragDrop )
1204 switch( nDestination )
1206 case SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP:
1207 case SotExchangeDest::DOC_LNKD_GRAPHOBJ:
1208 case SotExchangeDest::DOC_GRAPH_W_IMAP:
1209 case SotExchangeDest::DOC_GRAPHOBJ:
1210 case SotExchangeDest::DOC_OLEOBJ:
1211 case SotExchangeDest::DOC_DRAWOBJ:
1212 case SotExchangeDest::DOC_URLBUTTON:
1213 case SotExchangeDest::DOC_GROUPOBJ:
1214 // select frames/objects
1215 SwTransferable::SetSelInShell( rSh, true, pPt );
1216 break;
1218 default:
1219 SwTransferable::SetSelInShell( rSh, false, pPt );
1220 break;
1224 else if( ( !GetSwTransferable( rData ) || bIsPasteFormat ) &&
1225 !rSh.IsTableMode() && rSh.HasSelection() )
1227 // then delete the selections
1229 //don't delete selected content
1230 // - at table-selection
1231 // - at ReRead of a graphic/DDEData
1232 // - at D&D, for the right selection was taken care of
1233 // in Drop-Handler
1234 bool bDelSel = false;
1235 switch( nDestination )
1237 case SotExchangeDest::DOC_TEXTFRAME:
1238 case SotExchangeDest::SWDOC_FREE_AREA:
1239 case SotExchangeDest::DOC_TEXTFRAME_WEB:
1240 case SotExchangeDest::SWDOC_FREE_AREA_WEB:
1241 bDelSel = true;
1242 break;
1243 default:
1244 break;
1247 if( bDelSel )
1248 // #i34830#
1249 pAction.reset(new SwTrnsfrActionAndUndo( &rSh, true ));
1252 SwTransferable *pTrans=nullptr, *pTunneledTrans=GetSwTransferable( rData );
1254 // check for private drop
1255 bool bPrivateDrop(pPt && (bPasteSelection ? nullptr != (pTrans = pMod->m_pXSelection) : nullptr != (pTrans = pMod->m_pDragDrop)));
1256 bool bNeedToSelectBeforePaste(false);
1258 if(bPrivateDrop && DND_ACTION_LINK == nDropAction)
1260 // internal drop on object, suppress bPrivateDrop to change internal fill
1261 bPrivateDrop = false;
1262 bNeedToSelectBeforePaste = true;
1265 if(bPrivateDrop && pPt && DND_ACTION_MOVE == nDropAction)
1267 // check if dragged over a useful target. If yes, use as content exchange
1268 // drop as if from external
1269 const SwFrameFormat* pSwFrameFormat = rSh.GetFormatFromObj(*pPt);
1271 if(pSwFrameFormat && dynamic_cast< const SwDrawFrameFormat* >(pSwFrameFormat) != nullptr)
1273 bPrivateDrop = false;
1274 bNeedToSelectBeforePaste = true;
1278 if(bPrivateDrop)
1280 // then internal Drag & Drop or XSelection
1281 bRet = pTrans->PrivateDrop( rSh, *pPt, DND_ACTION_MOVE == nDropAction,
1282 bPasteSelection );
1284 else if( !pPt && pTunneledTrans &&
1285 EXCHG_OUT_ACTION_INSERT_PRIVATE == nAction )
1287 // then internal paste
1288 bRet = pTunneledTrans->PrivatePaste( rSh );
1290 else if( EXCHG_INOUT_ACTION_NONE != nAction )
1292 if( !pAction )
1294 pAction.reset(new SwTrnsfrActionAndUndo( &rSh ));
1297 // in Drag&Drop MessageBoxes must not be showed
1298 bool bMsg = nullptr == pPt;
1300 // delete selections
1302 switch( nAction )
1304 case EXCHG_OUT_ACTION_INSERT_PRIVATE:
1305 OSL_ENSURE( pPt, "EXCHG_OUT_ACTION_INSERT_PRIVATE: what should happen here?" );
1306 break;
1308 case EXCHG_OUT_ACTION_MOVE_PRIVATE:
1309 OSL_ENSURE( pPt, "EXCHG_OUT_ACTION_MOVE_PRIVATE: what should happen here?" );
1310 break;
1312 case EXCHG_IN_ACTION_MOVE:
1313 case EXCHG_IN_ACTION_COPY:
1314 case EXCHG_IN_ACTION_LINK:
1315 case EXCHG_OUT_ACTION_INSERT_HTML:
1316 case EXCHG_OUT_ACTION_INSERT_STRING:
1317 case EXCHG_OUT_ACTION_INSERT_IMAGEMAP:
1318 case EXCHG_OUT_ACTION_REPLACE_IMAGEMAP:
1320 // then we have to use the format
1321 switch( nFormat )
1323 case SotClipboardFormatId::DRAWING:
1324 bRet = SwTransferable::PasteSdrFormat( rData, rSh,
1325 SwPasteSdr::Insert, pPt,
1326 nActionFlags, bNeedToSelectBeforePaste);
1327 break;
1329 case SotClipboardFormatId::HTML:
1330 case SotClipboardFormatId::HTML_SIMPLE:
1331 case SotClipboardFormatId::HTML_NO_COMMENT:
1332 case SotClipboardFormatId::RTF:
1333 case SotClipboardFormatId::RICHTEXT:
1334 case SotClipboardFormatId::STRING:
1335 bRet = SwTransferable::PasteFileContent( rData, rSh,
1336 nFormat, bMsg );
1337 break;
1339 case SotClipboardFormatId::NETSCAPE_BOOKMARK:
1341 INetBookmark aBkmk;
1342 if( rData.GetINetBookmark( nFormat, aBkmk ) )
1344 SwFormatINetFormat aFormat( aBkmk.GetURL(), OUString() );
1345 rSh.InsertURL( aFormat, aBkmk.GetDescription() );
1346 bRet = true;
1349 break;
1351 case SotClipboardFormatId::SD_OLE:
1352 bRet = SwTransferable::PasteOLE( rData, rSh, nFormat,
1353 nActionFlags, bMsg );
1354 break;
1356 case SotClipboardFormatId::SVIM:
1357 bRet = SwTransferable::PasteImageMap( rData, rSh );
1358 break;
1360 case SotClipboardFormatId::SVXB:
1361 case SotClipboardFormatId::BITMAP:
1362 case SotClipboardFormatId::PNG:
1363 case SotClipboardFormatId::GDIMETAFILE:
1364 bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
1365 SwPasteSdr::Insert,pPt,
1366 nActionFlags, nDropAction, bNeedToSelectBeforePaste);
1367 break;
1369 case SotClipboardFormatId::XFORMS:
1370 case SotClipboardFormatId::SBA_FIELDDATAEXCHANGE:
1371 case SotClipboardFormatId::SBA_DATAEXCHANGE:
1372 case SotClipboardFormatId::SBA_CTRLDATAEXCHANGE:
1373 bRet = SwTransferable::PasteDBData( rData, rSh, nFormat,
1374 EXCHG_IN_ACTION_LINK == nAction,
1375 pPt, bMsg );
1376 break;
1378 case SotClipboardFormatId::SIMPLE_FILE:
1379 bRet = SwTransferable::PasteFileName( rData, rSh, nFormat,
1380 ( EXCHG_IN_ACTION_MOVE == nAction
1381 ? SwPasteSdr::Replace
1382 : EXCHG_IN_ACTION_LINK == nAction
1383 ? SwPasteSdr::SetAttr
1384 : SwPasteSdr::Insert),
1385 pPt, nActionFlags, bMsg, nullptr );
1386 break;
1388 case SotClipboardFormatId::FILE_LIST:
1389 // then insert as graphics only
1390 bRet = SwTransferable::PasteFileList( rData, rSh,
1391 EXCHG_IN_ACTION_LINK == nAction,
1392 pPt, bMsg );
1393 break;
1395 case SotClipboardFormatId::SONLK:
1396 if( pPt )
1398 NaviContentBookmark aBkmk;
1399 if( aBkmk.Paste( rData ) )
1401 if(bIsDefault)
1403 switch(aBkmk.GetDefaultDragType())
1405 case RegionMode::NONE: nAction = EXCHG_IN_ACTION_COPY; break;
1406 case RegionMode::EMBEDDED: nAction = EXCHG_IN_ACTION_MOVE; break;
1407 case RegionMode::LINK: nAction = EXCHG_IN_ACTION_LINK; break;
1410 rSh.NavigatorPaste( aBkmk, nAction );
1411 bRet = true;
1414 break;
1416 case SotClipboardFormatId::INET_IMAGE:
1417 case SotClipboardFormatId::NETSCAPE_IMAGE:
1418 bRet = SwTransferable::PasteTargetURL( rData, rSh,
1419 SwPasteSdr::Insert,
1420 pPt, true );
1421 break;
1423 default:
1424 OSL_ENSURE( pPt, "unknown format" );
1426 break;
1428 case EXCHG_OUT_ACTION_INSERT_FILE:
1430 bool graphicInserted;
1431 bRet = SwTransferable::PasteFileName( rData, rSh, nFormat,
1432 SwPasteSdr::Insert, pPt,
1433 nActionFlags, bMsg,
1434 &graphicInserted );
1435 if( graphicInserted )
1436 bCallAutoCaption = true;
1438 break;
1440 case EXCHG_OUT_ACTION_INSERT_OLE:
1441 bRet = SwTransferable::PasteOLE( rData, rSh, nFormat,
1442 nActionFlags,bMsg );
1443 break;
1445 case EXCHG_OUT_ACTION_INSERT_DDE:
1447 bool bReRead = 0 != CNT_HasGrf( rSh.GetCntType() );
1448 bRet = SwTransferable::PasteDDE( rData, rSh, bReRead, bMsg );
1450 break;
1452 case EXCHG_OUT_ACTION_INSERT_HYPERLINK:
1454 OUString sURL, sDesc;
1455 if( SotClipboardFormatId::SIMPLE_FILE == nFormat )
1457 if( rData.GetString( nFormat, sURL ) && !sURL.isEmpty() )
1459 SwTransferable::CheckForURLOrLNKFile( rData, sURL, &sDesc );
1460 if( sDesc.isEmpty() )
1461 sDesc = sURL;
1462 bRet = true;
1465 else
1467 INetBookmark aBkmk;
1468 if( rData.GetINetBookmark( nFormat, aBkmk ) )
1470 sURL = aBkmk.GetURL();
1471 sDesc = aBkmk.GetDescription();
1472 bRet = true;
1476 if( bRet )
1478 SwFormatINetFormat aFormat( sURL, OUString() );
1479 rSh.InsertURL( aFormat, sDesc );
1482 break;
1484 case EXCHG_OUT_ACTION_GET_ATTRIBUTES:
1485 switch( nFormat )
1487 case SotClipboardFormatId::DRAWING:
1488 bRet = SwTransferable::PasteSdrFormat( rData, rSh,
1489 SwPasteSdr::SetAttr, pPt,
1490 nActionFlags, bNeedToSelectBeforePaste);
1491 break;
1492 case SotClipboardFormatId::SVXB:
1493 case SotClipboardFormatId::GDIMETAFILE:
1494 case SotClipboardFormatId::BITMAP:
1495 case SotClipboardFormatId::PNG:
1496 case SotClipboardFormatId::NETSCAPE_BOOKMARK:
1497 case SotClipboardFormatId::SIMPLE_FILE:
1498 case SotClipboardFormatId::FILEGRPDESCRIPTOR:
1499 case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
1500 bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
1501 SwPasteSdr::SetAttr, pPt,
1502 nActionFlags, nDropAction, bNeedToSelectBeforePaste);
1503 break;
1504 default:
1505 OSL_FAIL( "unknown format" );
1508 break;
1510 case EXCHG_OUT_ACTION_INSERT_DRAWOBJ:
1511 bRet = SwTransferable::PasteSdrFormat( rData, rSh,
1512 SwPasteSdr::Insert, pPt,
1513 nActionFlags, bNeedToSelectBeforePaste);
1514 break;
1515 case EXCHG_OUT_ACTION_INSERT_SVXB:
1516 case EXCHG_OUT_ACTION_INSERT_GDIMETAFILE:
1517 case EXCHG_OUT_ACTION_INSERT_BITMAP:
1518 case EXCHG_OUT_ACTION_INSERT_GRAPH:
1519 bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
1520 SwPasteSdr::Insert, pPt,
1521 nActionFlags, nDropAction, bNeedToSelectBeforePaste, nAnchorType );
1522 break;
1524 case EXCHG_OUT_ACTION_REPLACE_DRAWOBJ:
1525 bRet = SwTransferable::PasteSdrFormat( rData, rSh,
1526 SwPasteSdr::Replace, pPt,
1527 nActionFlags, bNeedToSelectBeforePaste);
1528 break;
1530 case EXCHG_OUT_ACTION_REPLACE_SVXB:
1531 case EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE:
1532 case EXCHG_OUT_ACTION_REPLACE_BITMAP:
1533 case EXCHG_OUT_ACTION_REPLACE_GRAPH:
1534 bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
1535 SwPasteSdr::Replace,pPt,
1536 nActionFlags, nDropAction, bNeedToSelectBeforePaste);
1537 break;
1539 case EXCHG_OUT_ACTION_INSERT_INTERACTIVE:
1540 bRet = SwTransferable::PasteAsHyperlink( rData, rSh, nFormat );
1541 break;
1543 default:
1544 OSL_FAIL("unknown action" );
1548 if( !bPasteSelection && rSh.IsFrameSelected() )
1550 rSh.EnterSelFrameMode();
1551 //force ::SelectShell
1552 rSh.GetView().StopShellTimer();
1555 pAction.reset();
1556 if( bCallAutoCaption )
1557 rSh.GetView().AutoCaption( GRAPHIC_CAP );
1559 return bRet;
1562 SotExchangeDest SwTransferable::GetSotDestination( const SwWrtShell& rSh )
1564 SotExchangeDest nRet = SotExchangeDest::NONE;
1566 ObjCntType eOType = rSh.GetObjCntTypeOfSelection();
1568 switch( eOType )
1570 case OBJCNT_GRF:
1572 bool bIMap, bLink;
1573 bIMap = nullptr != rSh.GetFlyFrameFormat()->GetURL().GetMap();
1574 OUString aDummy;
1575 rSh.GetGrfNms( &aDummy, nullptr );
1576 bLink = !aDummy.isEmpty();
1578 if( bLink && bIMap )
1579 nRet = SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP;
1580 else if( bLink )
1581 nRet = SotExchangeDest::DOC_LNKD_GRAPHOBJ;
1582 else if( bIMap )
1583 nRet = SotExchangeDest::DOC_GRAPH_W_IMAP;
1584 else
1585 nRet = SotExchangeDest::DOC_GRAPHOBJ;
1587 break;
1589 case OBJCNT_FLY:
1590 if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr )
1591 nRet = SotExchangeDest::DOC_TEXTFRAME_WEB;
1592 else
1593 nRet = SotExchangeDest::DOC_TEXTFRAME;
1594 break;
1595 case OBJCNT_OLE: nRet = SotExchangeDest::DOC_OLEOBJ; break;
1597 case OBJCNT_CONTROL: /* no Action avail */
1598 case OBJCNT_SIMPLE: nRet = SotExchangeDest::DOC_DRAWOBJ; break;
1599 case OBJCNT_URLBUTTON: nRet = SotExchangeDest::DOC_URLBUTTON; break;
1600 case OBJCNT_GROUPOBJ: nRet = SotExchangeDest::DOC_GROUPOBJ; break;
1602 // what do we do at multiple selections???
1603 default:
1605 if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr )
1606 nRet = SotExchangeDest::SWDOC_FREE_AREA_WEB;
1607 else
1608 nRet = SotExchangeDest::SWDOC_FREE_AREA;
1612 return nRet;
1615 bool SwTransferable::PasteFileContent( TransferableDataHelper& rData,
1616 SwWrtShell& rSh, SotClipboardFormatId nFormat, bool bMsg )
1618 sal_uInt16 nResId = STR_CLPBRD_FORMAT_ERROR;
1619 bool bRet = false;
1621 MSE40HTMLClipFormatObj aMSE40ClpObj;
1623 tools::SvRef<SotStorageStream> xStrm;
1624 SvStream* pStream = nullptr;
1625 SwRead pRead = nullptr;
1626 OUString sData;
1627 switch( nFormat )
1629 case SotClipboardFormatId::STRING:
1631 pRead = ReadAscii;
1632 if( rData.GetString( nFormat, sData ) )
1634 pStream = new SvMemoryStream( const_cast<sal_Unicode *>(sData.getStr()),
1635 sData.getLength() * sizeof( sal_Unicode ),
1636 StreamMode::READ );
1637 #ifdef OSL_BIGENDIAN
1638 pStream->SetEndian( SvStreamEndian::BIG );
1639 #else
1640 pStream->SetEndian( SvStreamEndian::LITTLE );
1641 #endif
1643 SwAsciiOptions aAOpt;
1644 aAOpt.SetCharSet( RTL_TEXTENCODING_UCS2 );
1645 pRead->GetReaderOpt().SetASCIIOpts( aAOpt );
1646 break;
1649 SAL_FALLTHROUGH; // because then test if we get a stream
1651 default:
1652 if( rData.GetSotStorageStream( nFormat, xStrm ) )
1654 if( ( SotClipboardFormatId::HTML_SIMPLE == nFormat ) ||
1655 ( SotClipboardFormatId::HTML_NO_COMMENT == nFormat ) )
1657 pStream = aMSE40ClpObj.IsValid( *xStrm );
1658 pRead = ReadHTML;
1659 pRead->SetReadUTF8( true );
1661 bool bNoComments =
1662 ( nFormat == SotClipboardFormatId::HTML_NO_COMMENT );
1663 pRead->SetIgnoreHTMLComments( bNoComments );
1665 else
1667 pStream = xStrm.get();
1668 if( SotClipboardFormatId::RTF == nFormat || SotClipboardFormatId::RICHTEXT == nFormat)
1669 pRead = SwReaderWriter::GetRtfReader();
1670 else if( !pRead )
1672 pRead = ReadHTML;
1673 pRead->SetReadUTF8( true );
1677 break;
1680 if( pStream && pRead )
1682 Link<SwCursorShell*,void> aOldLink( rSh.GetChgLnk() );
1683 rSh.SetChgLnk( Link<SwCursorShell*,void>() );
1685 const SwPosition& rInsPos = *rSh.GetCursor()->Start();
1686 SwReader aReader( *pStream, aEmptyOUStr, OUString(), *rSh.GetCursor() );
1687 rSh.SaveTableBoxContent( &rInsPos );
1688 if( IsError( aReader.Read( *pRead )) )
1689 nResId = STR_ERROR_CLPBRD_READ;
1690 else
1692 nResId = 0;
1693 bRet = true;
1696 rSh.SetChgLnk( aOldLink );
1697 if( bRet )
1698 rSh.CallChgLnk();
1700 else
1701 nResId = STR_CLPBRD_FORMAT_ERROR;
1703 // Exist a SvMemoryStream? (data in the OUString and xStrm is empty)
1704 if( pStream && !xStrm.is() )
1705 delete pStream;
1707 if( bMsg && nResId )
1709 ScopedVclPtrInstance<MessageDialog>(nullptr, SwResId(nResId), VclMessageType::Info)->Execute();
1711 return bRet;
1714 bool SwTransferable::PasteOLE( TransferableDataHelper& rData, SwWrtShell& rSh,
1715 SotClipboardFormatId nFormat, SotExchangeActionFlags nActionFlags, bool bMsg )
1717 bool bRet = false;
1718 TransferableObjectDescriptor aObjDesc;
1719 uno::Reference < io::XInputStream > xStrm;
1720 uno::Reference < embed::XStorage > xStore;
1721 Reader* pRead = nullptr;
1723 // Get the preferred format
1724 SotClipboardFormatId nId;
1725 if( rData.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ ) )
1726 nId = SotClipboardFormatId::EMBEDDED_OBJ;
1727 else if( rData.HasFormat( SotClipboardFormatId::EMBED_SOURCE ) &&
1728 rData.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR ))
1729 nId = SotClipboardFormatId::EMBED_SOURCE;
1730 else
1731 nId = SotClipboardFormatId::NONE;
1733 if (nId != SotClipboardFormatId::NONE)
1735 SwDocShell* pDocSh = rSh.GetDoc()->GetDocShell();
1736 xStrm = rData.GetInputStream(nId, SfxObjectShell::CreateShellID(pDocSh));
1739 if (xStrm.is())
1741 // if there is an embedded object, first try if it's a writer object
1742 // this will be inserted into the document by using a Reader
1745 xStore = comphelper::OStorageHelper::GetStorageFromInputStream( xStrm );
1746 switch( SotStorage::GetFormatID( xStore ) )
1748 case SotClipboardFormatId::STARWRITER_60:
1749 case SotClipboardFormatId::STARWRITERWEB_60:
1750 case SotClipboardFormatId::STARWRITERGLOB_60:
1751 case SotClipboardFormatId::STARWRITER_8:
1752 case SotClipboardFormatId::STARWRITERWEB_8:
1753 case SotClipboardFormatId::STARWRITERGLOB_8:
1754 pRead = ReadXML;
1755 break;
1756 default:
1759 uno::Reference < lang::XComponent > xComp( xStore, uno::UNO_QUERY );
1760 xComp->dispose();
1761 xStore = nullptr;
1763 catch (const uno::Exception&)
1767 break;
1770 catch (const uno::Exception&)
1772 // it wasn't a storage, but maybe it's a useful stream
1776 if( pRead )
1778 SwPaM &rPAM = *rSh.GetCursor();
1779 SwReader aReader( xStore, aEmptyOUStr, rPAM );
1780 if( !IsError( aReader.Read( *pRead )) )
1781 bRet = true;
1782 else if( bMsg )
1783 ScopedVclPtrInstance<MessageDialog>(nullptr, SwResId(STR_ERROR_CLPBRD_READ), VclMessageType::Info)->Execute();
1785 else
1787 // temporary storage until the object is inserted
1788 uno::Reference< embed::XStorage > xTmpStor;
1789 uno::Reference < embed::XEmbeddedObject > xObj;
1790 OUString aName;
1791 comphelper::EmbeddedObjectContainer aCnt;
1793 if ( xStrm.is() )
1795 if ( !rData.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR, aObjDesc ) )
1797 OSL_ENSURE( !xStrm.is(), "An object without descriptor in clipboard!");
1800 else
1802 if( rData.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR_OLE ) && rData.GetTransferableObjectDescriptor( nFormat, aObjDesc ) )
1804 xStrm = rData.GetInputStream(SotClipboardFormatId::EMBED_SOURCE_OLE, OUString());
1805 if (!xStrm.is())
1806 xStrm = rData.GetInputStream(SotClipboardFormatId::EMBEDDED_OBJ_OLE, OUString());
1808 if ( !xStrm.is() )
1810 // This is MSOLE object that should be created by direct using of system clipboard
1813 xTmpStor = ::comphelper::OStorageHelper::GetTemporaryStorage();
1814 uno::Reference < embed::XEmbedObjectClipboardCreator > xClipboardCreator =
1815 embed::MSOLEObjectSystemCreator::create( ::comphelper::getProcessComponentContext() );
1817 embed::InsertedObjectInfo aInfo = xClipboardCreator->createInstanceInitFromClipboard(
1818 xTmpStor,
1819 "DummyName",
1820 uno::Sequence< beans::PropertyValue >() );
1822 // TODO/LATER: in future InsertedObjectInfo will be used to get container related information
1823 // for example whether the object should be an iconified one
1824 xObj = aInfo.Object;
1826 catch (const uno::Exception&)
1833 if ( xStrm.is() && !xObj.is() )
1834 xObj = aCnt.InsertEmbeddedObject( xStrm, aName );
1836 if( xObj.is() )
1838 svt::EmbeddedObjectRef xObjRef( xObj, aObjDesc.mnViewAspect );
1840 // try to get the replacement image from the clipboard
1841 Graphic aGraphic;
1842 SotClipboardFormatId nGrFormat = SotClipboardFormatId::NONE;
1844 // limit the size of the preview metafile to 100000 actions
1845 GDIMetaFile aMetafile;
1846 if (rData.GetGDIMetaFile(SotClipboardFormatId::GDIMETAFILE, aMetafile, 100000))
1848 nGrFormat = SotClipboardFormatId::GDIMETAFILE;
1849 aGraphic = aMetafile;
1852 // insert replacement image ( if there is one ) into the object helper
1853 if ( nGrFormat != SotClipboardFormatId::NONE )
1855 DataFlavor aDataFlavor;
1856 SotExchange::GetFormatDataFlavor( nGrFormat, aDataFlavor );
1857 xObjRef.SetGraphic( aGraphic, aDataFlavor.MimeType );
1859 else if ( aObjDesc.mnViewAspect == embed::Aspects::MSOLE_ICON )
1861 // it is important to have an icon, let an empty graphic be used
1862 // if no other graphic is provided
1863 // TODO/LATER: in future a default bitmap could be used
1864 OUString aMimeType;
1865 MapMode aMapMode( MapUnit::Map100thMM );
1866 aGraphic.SetPrefSize( Size( 2500, 2500 ) );
1867 aGraphic.SetPrefMapMode( aMapMode );
1868 xObjRef.SetGraphic( aGraphic, aMimeType );
1871 //set size. This is a hack because of handing over, size should be
1872 //passed to the InsertOle!!!!!!!!!!
1873 Size aSize;
1874 if ( aObjDesc.mnViewAspect == embed::Aspects::MSOLE_ICON )
1876 if( aObjDesc.maSize.Width() && aObjDesc.maSize.Height() )
1877 aSize = aObjDesc.maSize;
1878 else
1880 MapMode aMapMode( MapUnit::Map100thMM );
1881 aSize = xObjRef.GetSize( &aMapMode );
1884 else if( aObjDesc.maSize.Width() && aObjDesc.maSize.Height() )
1886 aSize = Size( aObjDesc.maSize ); //always 100TH_MM
1887 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( aObjDesc.mnViewAspect ) );
1888 aSize = OutputDevice::LogicToLogic( aSize, MapUnit::Map100thMM, aUnit );
1889 awt::Size aSz;
1892 aSz = xObj->getVisualAreaSize( aObjDesc.mnViewAspect );
1894 catch (const embed::NoVisualAreaSizeException&)
1896 // in this case the provided size is used
1899 if ( aSz.Width != aSize.Width() || aSz.Height != aSize.Height() )
1901 aSz.Width = aSize.Width();
1902 aSz.Height = aSize.Height();
1903 xObj->setVisualAreaSize( aObjDesc.mnViewAspect, aSz );
1906 else
1908 // the descriptor contains the wrong object size
1909 // the following call will let the MSOLE objects cache the size if it is possible
1910 // it should be done while the object is running
1913 xObj->getVisualAreaSize( aObjDesc.mnViewAspect );
1915 catch (const uno::Exception&)
1919 //End of Hack!
1921 rSh.InsertOleObject( xObjRef );
1922 bRet = true;
1924 if( bRet && ( nActionFlags & SotExchangeActionFlags::InsertTargetUrl) )
1925 SwTransferable::PasteTargetURL( rData, rSh, SwPasteSdr::NONE, nullptr, false );
1927 // let the object be unloaded if possible
1928 SwOLEObj::UnloadObject( xObj, rSh.GetDoc(), embed::Aspects::MSOLE_CONTENT );
1931 return bRet;
1934 bool SwTransferable::PasteTargetURL( TransferableDataHelper& rData,
1935 SwWrtShell& rSh, SwPasteSdr nAction,
1936 const Point* pPt, bool bInsertGRF )
1938 bool bRet = false;
1939 INetImage aINetImg;
1940 if( ( rData.HasFormat( SotClipboardFormatId::INET_IMAGE ) &&
1941 rData.GetINetImage( SotClipboardFormatId::INET_IMAGE, aINetImg )) ||
1942 ( rData.HasFormat( SotClipboardFormatId::NETSCAPE_IMAGE ) &&
1943 rData.GetINetImage( SotClipboardFormatId::NETSCAPE_IMAGE, aINetImg )) )
1945 if( !aINetImg.GetImageURL().isEmpty() && bInsertGRF )
1947 OUString sURL( aINetImg.GetImageURL() );
1948 SwTransferable::CheckForURLOrLNKFile( rData, sURL );
1950 //!!! check at FileSystem - only then it make sense to test graphics !!!
1951 Graphic aGraphic;
1952 GraphicFilter &rFlt = GraphicFilter::GetGraphicFilter();
1953 bRet = GRFILTER_OK == GraphicFilter::LoadGraphic( sURL, aEmptyOUStr, aGraphic, &rFlt );
1955 if( bRet )
1957 //Check and Perform rotation if needed
1958 lclCheckAndPerformRotation(aGraphic);
1960 switch( nAction )
1962 case SwPasteSdr::Insert:
1963 SwTransferable::SetSelInShell( rSh, false, pPt );
1964 rSh.Insert( sURL, aEmptyOUStr, aGraphic );
1965 break;
1967 case SwPasteSdr::Replace:
1968 if( rSh.IsObjSelected() )
1970 rSh.ReplaceSdrObj( sURL, &aGraphic );
1971 Point aPt( pPt ? *pPt : rSh.GetCursorDocPos() );
1972 SwTransferable::SetSelInShell( rSh, true, &aPt );
1974 else
1975 rSh.ReRead( sURL, aEmptyOUStr, &aGraphic );
1976 break;
1978 case SwPasteSdr::SetAttr:
1979 if( rSh.IsObjSelected() )
1980 rSh.Paste( aGraphic, OUString() );
1981 else if( OBJCNT_GRF == rSh.GetObjCntTypeOfSelection() )
1982 rSh.ReRead( sURL, aEmptyOUStr, &aGraphic );
1983 else
1985 SwTransferable::SetSelInShell( rSh, false, pPt );
1986 rSh.Insert( sURL, aEmptyOUStr, aGraphic );
1988 break;
1989 default:
1990 bRet = false;
1994 else
1995 bRet = true;
1998 if( bRet )
2000 SfxItemSet aSet( rSh.GetAttrPool(), RES_URL, RES_URL );
2001 rSh.GetFlyFrameAttr( aSet );
2002 SwFormatURL aURL( static_cast<const SwFormatURL&>(aSet.Get( RES_URL )) );
2004 if( aURL.GetURL() != aINetImg.GetTargetURL() ||
2005 aURL.GetTargetFrameName() != aINetImg.GetTargetFrame() )
2007 aURL.SetURL( aINetImg.GetTargetURL(), false );
2008 aURL.SetTargetFrameName( aINetImg.GetTargetFrame() );
2009 aSet.Put( aURL );
2010 rSh.SetFlyFrameAttr( aSet );
2013 return bRet;
2016 void SwTransferable::SetSelInShell( SwWrtShell& rSh, bool bSelectFrame,
2017 const Point* pPt )
2019 if( bSelectFrame )
2021 // select frames/objects
2022 if( pPt && !rSh.GetView().GetViewFrame()->GetDispatcher()->IsLocked() )
2024 rSh.GetView().NoRotate();
2025 if( rSh.SelectObj( *pPt ))
2027 rSh.HideCursor();
2028 rSh.EnterSelFrameMode( pPt );
2029 g_bFrameDrag = true;
2033 else
2035 if( rSh.IsFrameSelected() || rSh.IsObjSelected() )
2037 rSh.UnSelectFrame();
2038 rSh.LeaveSelFrameMode();
2039 rSh.GetView().GetEditWin().StopInsFrame();
2040 g_bFrameDrag = false;
2042 else if( rSh.GetView().GetDrawFuncPtr() )
2043 rSh.GetView().GetEditWin().StopInsFrame();
2045 rSh.EnterStdMode();
2046 if( pPt )
2047 rSh.SwCursorShell::SetCursor( *pPt, true );
2051 bool SwTransferable::PasteDDE( TransferableDataHelper& rData,
2052 SwWrtShell& rWrtShell, bool bReReadGrf,
2053 bool bMsg )
2055 // data from Clipboardformat
2056 OUString aApp, aTopic, aItem;
2059 tools::SvRef<SotStorageStream> xStrm;
2060 if( !rData.GetSotStorageStream( SotClipboardFormatId::LINK, xStrm ))
2062 OSL_ENSURE( false, "DDE Data not found." );
2063 return false;
2064 } // report useful error!!
2066 rtl_TextEncoding eEncoding = DDE_TXT_ENCODING;
2067 aApp = read_zeroTerminated_uInt8s_ToOUString(*xStrm, eEncoding);
2068 aTopic = read_zeroTerminated_uInt8s_ToOUString(*xStrm, eEncoding);
2069 aItem = read_zeroTerminated_uInt8s_ToOUString(*xStrm, eEncoding);
2072 OUString aCmd;
2073 sfx2::MakeLnkName( aCmd, &aApp, aTopic, aItem );
2075 // do we want to read in a graphic now?
2076 SotClipboardFormatId nFormat;
2077 if( !rData.HasFormat( SotClipboardFormatId::RTF ) &&
2078 !rData.HasFormat( SotClipboardFormatId::RICHTEXT ) &&
2079 !rData.HasFormat( SotClipboardFormatId::HTML ) &&
2080 !rData.HasFormat( SotClipboardFormatId::STRING ) &&
2081 (rData.HasFormat( nFormat = SotClipboardFormatId::GDIMETAFILE ) ||
2082 rData.HasFormat( nFormat = SotClipboardFormatId::BITMAP )) )
2084 Graphic aGrf;
2085 bool bRet = rData.GetGraphic( nFormat, aGrf );
2086 if( bRet )
2088 OUString sLnkTyp("DDE");
2089 if ( bReReadGrf )
2090 rWrtShell.ReRead( aCmd, sLnkTyp, &aGrf );
2091 else
2092 rWrtShell.Insert( aCmd, sLnkTyp, aGrf );
2094 return bRet;
2097 SwFieldType* pTyp = nullptr;
2098 size_t i = 1;
2099 size_t j;
2100 OUString aName;
2101 bool bDoublePaste = false;
2102 const size_t nSize = rWrtShell.GetFieldTypeCount();
2103 const ::utl::TransliterationWrapper& rColl = ::GetAppCmpStrIgnore();
2105 do {
2106 aName = aApp;
2107 aName += OUString::number( i );
2108 for( j = INIT_FLDTYPES; j < nSize; j++ )
2110 pTyp = rWrtShell.GetFieldType( j );
2111 if( SwFieldIds::Dde == pTyp->Which() )
2113 OUString sTmp( static_cast<SwDDEFieldType*>(pTyp)->GetCmd() );
2114 if( rColl.isEqual( sTmp, aCmd ) &&
2115 SfxLinkUpdateMode::ALWAYS == static_cast<SwDDEFieldType*>(pTyp)->GetType() )
2117 aName = pTyp->GetName();
2118 bDoublePaste = true;
2119 break;
2121 else if( rColl.isEqual( aName, pTyp->GetName() ) )
2122 break;
2125 if( j == nSize )
2126 break;
2127 ++i;
2129 while( !bDoublePaste );
2131 if( !bDoublePaste )
2133 SwDDEFieldType aType( aName, aCmd, SfxLinkUpdateMode::ALWAYS );
2134 pTyp = rWrtShell.InsertFieldType( aType );
2137 SwDDEFieldType* pDDETyp = static_cast<SwDDEFieldType*>(pTyp);
2139 OUString aExpand;
2140 if( rData.GetString( SotClipboardFormatId::STRING, aExpand ))
2142 do { // middle checked loop
2144 // When data comes from a spreadsheet, we add a DDE-table
2145 if( ( rData.HasFormat( SotClipboardFormatId::SYLK ) ||
2146 rData.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS ) ) &&
2147 !aExpand.isEmpty() &&
2148 ( 1 < comphelper::string::getTokenCount(aExpand, '\n') ||
2149 comphelper::string::getTokenCount(aExpand, '\t') ) )
2151 OUString sTmp( aExpand );
2152 sal_Int32 nRows = comphelper::string::getTokenCount(sTmp, '\n');
2153 if( nRows )
2154 --nRows;
2155 sTmp = sTmp.getToken( 0, '\n' );
2156 sal_Int32 nCols = comphelper::string::getTokenCount(sTmp, '\t');
2158 // don't try to insert tables that are too large for writer
2159 if (nRows > USHRT_MAX || nCols > USHRT_MAX)
2161 if( bMsg )
2162 ScopedVclPtrInstance<MessageDialog>(nullptr, SwResId(STR_TABLE_TOO_LARGE), VclMessageType::Info)->Execute();
2163 pDDETyp = nullptr;
2164 break;
2167 // at least one column & row must be there
2168 if( !nRows || !nCols )
2170 if( bMsg )
2171 ScopedVclPtrInstance<MessageDialog>(nullptr, SwResId(STR_NO_TABLE), VclMessageType::Info)->Execute();
2172 pDDETyp = nullptr;
2173 break;
2176 rWrtShell.InsertDDETable(
2177 SwInsertTableOptions( tabopts::SPLIT_LAYOUT, 1 ), // TODO MULTIHEADER
2178 pDDETyp, nRows, nCols );
2180 else if( 1 < comphelper::string::getTokenCount(aExpand, '\n') )
2182 // multiple paragraphs -> insert a protected section
2183 if( rWrtShell.HasSelection() )
2184 rWrtShell.DelRight();
2186 SwSectionData aSect( DDE_LINK_SECTION, aName );
2187 aSect.SetLinkFileName( aCmd );
2188 aSect.SetProtectFlag(true);
2189 rWrtShell.InsertSection( aSect );
2191 pDDETyp = nullptr; // remove FieldTypes again
2193 else
2195 // Einfuegen
2196 SwDDEField aSwDDEField( pDDETyp );
2197 rWrtShell.Insert( aSwDDEField );
2200 } while( false );
2202 else
2203 pDDETyp = nullptr; // remove FieldTypes again
2205 if( !pDDETyp && !bDoublePaste )
2207 // remove FieldType again - error occurred!
2208 for( j = nSize; j >= INIT_FLDTYPES; --j )
2209 if( pTyp == rWrtShell.GetFieldType( j ) )
2211 rWrtShell.RemoveFieldType( j );
2212 break;
2216 return true;
2219 bool SwTransferable::PasteSdrFormat( TransferableDataHelper& rData,
2220 SwWrtShell& rSh, SwPasteSdr nAction,
2221 const Point* pPt, SotExchangeActionFlags nActionFlags, bool bNeedToSelectBeforePaste)
2223 bool bRet = false;
2224 tools::SvRef<SotStorageStream> xStrm;
2225 if( rData.GetSotStorageStream( SotClipboardFormatId::DRAWING, xStrm ))
2227 xStrm->SetVersion( SOFFICE_FILEFORMAT_50 );
2229 if(bNeedToSelectBeforePaste && pPt)
2231 // if this is an internal drag, need to set the target right (select it), else
2232 // still the source will be selected
2233 SwTransferable::SetSelInShell( rSh, true, pPt );
2236 rSh.Paste( *xStrm, nAction, pPt );
2237 bRet = true;
2239 if( bRet && ( nActionFlags & SotExchangeActionFlags::InsertTargetUrl ))
2240 SwTransferable::PasteTargetURL( rData, rSh, SwPasteSdr::NONE, nullptr, false );
2242 return bRet;
2245 bool SwTransferable::PasteGrf( TransferableDataHelper& rData, SwWrtShell& rSh,
2246 SotClipboardFormatId nFormat, SwPasteSdr nAction, const Point* pPt,
2247 SotExchangeActionFlags nActionFlags, sal_Int8 nDropAction, bool bNeedToSelectBeforePaste, RndStdIds nAnchorType )
2249 bool bRet = false;
2251 Graphic aGraphic;
2252 INetBookmark aBkmk;
2253 bool bCheckForGrf = false, bCheckForImageMap = false;
2255 switch( nFormat )
2257 case SotClipboardFormatId::BITMAP:
2258 case SotClipboardFormatId::PNG:
2259 case SotClipboardFormatId::GDIMETAFILE:
2260 bRet = rData.GetGraphic( nFormat, aGraphic );
2261 break;
2263 case SotClipboardFormatId::SVXB:
2265 tools::SvRef<SotStorageStream> xStm;
2267 if(rData.GetSotStorageStream(SotClipboardFormatId::SVXB, xStm))
2269 ReadGraphic( *xStm, aGraphic );
2270 bRet = (GraphicType::NONE != aGraphic.GetType() && GraphicType::Default != aGraphic.GetType());
2273 break;
2276 case SotClipboardFormatId::NETSCAPE_BOOKMARK:
2277 case SotClipboardFormatId::FILEGRPDESCRIPTOR:
2278 case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
2279 bRet = rData.GetINetBookmark( nFormat, aBkmk );
2280 if( bRet )
2282 if( SwPasteSdr::SetAttr == nAction )
2283 nFormat = SotClipboardFormatId::NETSCAPE_BOOKMARK;
2284 else
2285 bCheckForGrf = true;
2287 break;
2289 case SotClipboardFormatId::SIMPLE_FILE:
2291 OUString sText;
2292 bRet = rData.GetString( nFormat, sText );
2293 if( bRet )
2295 OUString sDesc;
2296 SwTransferable::CheckForURLOrLNKFile( rData, sText, &sDesc );
2298 aBkmk = INetBookmark(
2299 URIHelper::SmartRel2Abs(INetURLObject(), sText, Link<OUString *, bool>(), false ),
2300 sDesc );
2301 bCheckForGrf = true;
2302 bCheckForImageMap = SwPasteSdr::Replace == nAction;
2305 break;
2307 default:
2308 bRet = rData.GetGraphic( nFormat, aGraphic );
2309 break;
2312 if( bCheckForGrf )
2314 //!!! check at FileSystem - only then it makes sense to test the graphics !!!
2315 GraphicFilter &rFlt = GraphicFilter::GetGraphicFilter();
2316 bRet = GRFILTER_OK == GraphicFilter::LoadGraphic( aBkmk.GetURL(), aEmptyOUStr,
2317 aGraphic, &rFlt );
2319 if( !bRet && SwPasteSdr::SetAttr == nAction &&
2320 SotClipboardFormatId::SIMPLE_FILE == nFormat &&
2321 // only at frame selection
2322 rSh.IsFrameSelected() )
2324 // then set as hyperlink after the graphic
2325 nFormat = SotClipboardFormatId::NETSCAPE_BOOKMARK;
2326 bRet = true;
2330 if(pPt && bNeedToSelectBeforePaste)
2332 // when using internal D&Ds, still the source object is selected and
2333 // this is necessary to get the correct source data which is also
2334 // dependent from selection. After receiving the drag data it is
2335 // now time to select the correct target object
2336 SwTransferable::SetSelInShell( rSh, true, pPt );
2339 if( bRet )
2341 //Check and Perform rotation if needed
2342 lclCheckAndPerformRotation(aGraphic);
2344 OUString sURL;
2345 if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr
2346 // #i123922# if link action is noted, also take URL
2347 || DND_ACTION_LINK == nDropAction)
2349 sURL = aBkmk.GetURL();
2352 switch( nAction )
2354 case SwPasteSdr::Insert:
2356 SwTransferable::SetSelInShell( rSh, false, pPt );
2357 rSh.Insert( sURL, aEmptyOUStr, aGraphic, nullptr, nAnchorType );
2358 break;
2361 case SwPasteSdr::Replace:
2363 if( rSh.IsObjSelected() )
2365 // #i123922# for D&D on draw objects, do for now the same for
2366 // SwPasteSdr::Replace (D&D) as for SwPasteSdr::SetAttr (D&D and
2367 // CTRL+SHIFT). The code below replaces the draw object with
2368 // a writer graphic; maybe this is an option later again if wanted
2369 rSh.Paste( aGraphic, sURL );
2371 // rSh.ReplaceSdrObj( sURL, aEmptyOUStr, &aGraphic );
2372 // Point aPt( pPt ? *pPt : rSh.GetCursorDocPos() );
2373 // SwTransferable::SetSelInShell( rSh, true, &aPt );
2375 else
2377 // set graphic at writer graphic without link
2378 rSh.ReRead( sURL, aEmptyOUStr, &aGraphic );
2381 break;
2384 case SwPasteSdr::SetAttr:
2386 if( SotClipboardFormatId::NETSCAPE_BOOKMARK == nFormat )
2388 if( rSh.IsFrameSelected() )
2390 SfxItemSet aSet( rSh.GetAttrPool(), RES_URL, RES_URL );
2391 rSh.GetFlyFrameAttr( aSet );
2392 SwFormatURL aURL( static_cast<const SwFormatURL&>(aSet.Get( RES_URL )) );
2393 aURL.SetURL( aBkmk.GetURL(), false );
2394 aSet.Put( aURL );
2395 rSh.SetFlyFrameAttr( aSet );
2398 else if( rSh.IsObjSelected() )
2400 // set as attribute at DrawObject
2401 rSh.Paste( aGraphic, sURL );
2403 else if( OBJCNT_GRF == rSh.GetObjCntTypeOfSelection() )
2405 // set as linked graphic at writer graphic frame
2406 rSh.ReRead( sURL, aEmptyOUStr, &aGraphic );
2408 else
2410 SwTransferable::SetSelInShell( rSh, false, pPt );
2411 rSh.Insert( aBkmk.GetURL(), aEmptyOUStr, aGraphic );
2413 break;
2415 default:
2417 bRet = false;
2418 break;
2423 if( bRet )
2426 if( nActionFlags &
2427 ( SotExchangeActionFlags::InsertImageMap | SotExchangeActionFlags::ReplaceImageMap ) )
2428 SwTransferable::PasteImageMap( rData, rSh );
2430 if( nActionFlags & SotExchangeActionFlags::InsertTargetUrl )
2431 SwTransferable::PasteTargetURL( rData, rSh, SwPasteSdr::NONE, nullptr, false );
2433 else if( bCheckForImageMap )
2435 // or should the file be an ImageMap-File?
2436 ImageMap aMap;
2437 SfxMedium aMed( INetURLObject(aBkmk.GetURL()).GetFull(),
2438 StreamMode::STD_READ );
2439 SvStream* pStream = aMed.GetInStream();
2440 if( pStream != nullptr &&
2441 !pStream->GetError() &&
2442 // mba: no BaseURL for clipboard functionality
2443 aMap.Read( *pStream, IMAP_FORMAT_DETECT ) == IMAP_ERR_OK &&
2444 aMap.GetIMapObjectCount() )
2446 SfxItemSet aSet( rSh.GetAttrPool(), RES_URL, RES_URL );
2447 rSh.GetFlyFrameAttr( aSet );
2448 SwFormatURL aURL( static_cast<const SwFormatURL&>(aSet.Get( RES_URL )) );
2449 aURL.SetMap( &aMap );
2450 aSet.Put( aURL );
2451 rSh.SetFlyFrameAttr( aSet );
2452 bRet = true;
2456 return bRet;
2459 bool SwTransferable::PasteImageMap( TransferableDataHelper& rData,
2460 SwWrtShell& rSh )
2462 bool bRet = false;
2463 if( rData.HasFormat( SotClipboardFormatId::SVIM ))
2465 SfxItemSet aSet( rSh.GetAttrPool(), RES_URL, RES_URL );
2466 rSh.GetFlyFrameAttr( aSet );
2467 SwFormatURL aURL( static_cast<const SwFormatURL&>(aSet.Get( RES_URL )) );
2468 const ImageMap* pOld = aURL.GetMap();
2470 // set or replace, that is the question
2471 ImageMap aImageMap;
2472 if( rData.GetImageMap( SotClipboardFormatId::SVIM, aImageMap ) &&
2473 ( !pOld || aImageMap != *pOld ))
2475 aURL.SetMap( &aImageMap );
2476 aSet.Put( aURL );
2477 rSh.SetFlyFrameAttr( aSet );
2479 bRet = true;
2481 return bRet;
2484 bool SwTransferable::PasteAsHyperlink( TransferableDataHelper& rData,
2485 SwWrtShell& rSh, SotClipboardFormatId nFormat )
2487 bool bRet = false;
2488 OUString sFile;
2489 if( rData.GetString( nFormat, sFile ) && !sFile.isEmpty() )
2491 OUString sDesc;
2492 SwTransferable::CheckForURLOrLNKFile( rData, sFile, &sDesc );
2494 // first, make the URL absolute
2495 INetURLObject aURL;
2496 aURL.SetSmartProtocol( INetProtocol::File );
2497 aURL.SetSmartURL( sFile );
2498 sFile = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
2500 switch( rSh.GetObjCntTypeOfSelection() )
2502 case OBJCNT_FLY:
2503 case OBJCNT_GRF:
2504 case OBJCNT_OLE:
2506 SfxItemSet aSet( rSh.GetAttrPool(), RES_URL, RES_URL );
2507 rSh.GetFlyFrameAttr( aSet );
2508 SwFormatURL aURL2( static_cast<const SwFormatURL&>(aSet.Get( RES_URL )) );
2509 aURL2.SetURL( sFile, false );
2510 if( aURL2.GetName().isEmpty() )
2511 aURL2.SetName( sFile );
2512 aSet.Put( aURL2 );
2513 rSh.SetFlyFrameAttr( aSet );
2515 break;
2517 default:
2519 rSh.InsertURL( SwFormatINetFormat( sFile, OUString() ),
2520 sDesc.isEmpty() ? sFile : sDesc);
2523 bRet = true;
2525 return bRet;
2528 bool SwTransferable::PasteFileName( TransferableDataHelper& rData,
2529 SwWrtShell& rSh, SotClipboardFormatId nFormat,
2530 SwPasteSdr nAction, const Point* pPt,
2531 SotExchangeActionFlags nActionFlags, bool /* bMsg */,
2532 bool * graphicInserted)
2534 bool bRet = SwTransferable::PasteGrf( rData, rSh, nFormat, nAction,
2535 pPt, nActionFlags, 0, false);
2536 if (graphicInserted != nullptr) {
2537 *graphicInserted = bRet;
2539 if( !bRet )
2541 OUString sFile, sDesc;
2542 if( rData.GetString( nFormat, sFile ) && !sFile.isEmpty() )
2544 #if HAVE_FEATURE_AVMEDIA
2545 INetURLObject aMediaURL;
2547 aMediaURL.SetSmartURL( sFile );
2548 const OUString aMediaURLStr( aMediaURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
2550 if( ::avmedia::MediaWindow::isMediaURL( aMediaURLStr, ""/*TODO?*/ ) )
2552 const SfxStringItem aMediaURLItem( SID_INSERT_AVMEDIA, aMediaURLStr );
2553 rSh.GetView().GetViewFrame()->GetDispatcher()->ExecuteList(
2554 SID_INSERT_AVMEDIA, SfxCallMode::SYNCHRON,
2555 { &aMediaURLItem });
2557 #else
2558 if (false)
2561 #endif
2562 else
2564 bool bIsURLFile = SwTransferable::CheckForURLOrLNKFile( rData, sFile, &sDesc );
2566 //Own FileFormat? --> insert, not for StarWriter/Web
2567 OUString sFileURL = URIHelper::SmartRel2Abs(INetURLObject(), sFile, Link<OUString *, bool>(), false );
2568 std::shared_ptr<const SfxFilter> pFlt = SwPasteSdr::SetAttr == nAction
2569 ? nullptr : SwIoSystem::GetFileFilter(sFileURL);
2570 if( pFlt && dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) == nullptr )
2572 // and then pull up the insert-region-dialog by PostUser event
2573 SwSectionData * pSect = new SwSectionData(
2574 FILE_LINK_SECTION,
2575 rSh.GetDoc()->GetUniqueSectionName() );
2576 pSect->SetLinkFileName( sFileURL );
2577 pSect->SetProtectFlag( true );
2579 Application::PostUserEvent( LINK( &rSh, SwWrtShell,
2580 InsertRegionDialog ), pSect );
2581 bRet = true;
2583 else if( SwPasteSdr::SetAttr == nAction ||
2584 ( bIsURLFile && SwPasteSdr::Insert == nAction ))
2586 //we can insert foreign files as links after all
2588 // first, make the URL absolute
2589 INetURLObject aURL;
2590 aURL.SetSmartProtocol( INetProtocol::File );
2591 aURL.SetSmartURL( sFile );
2592 sFile = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
2594 switch( rSh.GetObjCntTypeOfSelection() )
2596 case OBJCNT_FLY:
2597 case OBJCNT_GRF:
2598 case OBJCNT_OLE:
2600 SfxItemSet aSet( rSh.GetAttrPool(), RES_URL, RES_URL );
2601 rSh.GetFlyFrameAttr( aSet );
2602 SwFormatURL aURL2( static_cast<const SwFormatURL&>(aSet.Get( RES_URL )) );
2603 aURL2.SetURL( sFile, false );
2604 if( aURL2.GetName().isEmpty() )
2605 aURL2.SetName( sFile );
2606 aSet.Put( aURL2 );
2607 rSh.SetFlyFrameAttr( aSet );
2609 break;
2611 default:
2613 rSh.InsertURL( SwFormatINetFormat( sFile, OUString() ),
2614 sDesc.isEmpty() ? sFile : sDesc );
2617 bRet = true;
2622 return bRet;
2625 bool SwTransferable::PasteDBData( TransferableDataHelper& rData,
2626 SwWrtShell& rSh, SotClipboardFormatId nFormat, bool bLink,
2627 const Point* pDragPt, bool bMsg )
2629 bool bRet = false;
2630 OUString sText;
2631 if( rData.GetString( nFormat, sText ) && !sText.isEmpty() )
2633 sal_uInt16 nWh = SotClipboardFormatId::SBA_CTRLDATAEXCHANGE == nFormat
2635 : SotClipboardFormatId::SBA_DATAEXCHANGE == nFormat
2636 ? (bLink
2637 ? FN_QRY_MERGE_FIELD
2638 : FN_QRY_INSERT)
2639 : (bLink
2641 : FN_QRY_INSERT_FIELD );
2642 const DataFlavorExVector& rVector = rData.GetDataFlavorExVector();
2643 bool bHaveColumnDescriptor = OColumnTransferable::canExtractColumnDescriptor(rVector, ColumnTransferFormatFlags::COLUMN_DESCRIPTOR | ColumnTransferFormatFlags::CONTROL_EXCHANGE);
2644 if ( SotClipboardFormatId::XFORMS == nFormat )
2646 rSh.MakeDrawView();
2647 FmFormView* pFmView = dynamic_cast<FmFormView*>( rSh.GetDrawView() );
2648 if (pFmView && pDragPt)
2650 const OXFormsDescriptor &rDesc = OXFormsTransferable::extractDescriptor(rData);
2651 SdrObject* pObj = pFmView->CreateXFormsControl(rDesc);
2652 if(nullptr != pObj)
2654 rSh.SwFEShell::InsertDrawObj( *pObj, *pDragPt );
2658 else if( nWh )
2660 std::unique_ptr<SfxUsrAnyItem> pConnectionItem;
2661 std::unique_ptr<SfxUsrAnyItem> pCursorItem;
2662 std::unique_ptr<SfxUsrAnyItem> pColumnItem;
2663 std::unique_ptr<SfxUsrAnyItem> pSourceItem;
2664 std::unique_ptr<SfxUsrAnyItem> pCommandItem;
2665 std::unique_ptr<SfxUsrAnyItem> pCommandTypeItem;
2666 std::unique_ptr<SfxUsrAnyItem> pColumnNameItem;
2667 std::unique_ptr<SfxUsrAnyItem> pSelectionItem;
2669 bool bDataAvailable = true;
2670 ODataAccessDescriptor aDesc;
2671 if(bHaveColumnDescriptor)
2672 aDesc = OColumnTransferable::extractColumnDescriptor(rData);
2673 else if(ODataAccessObjectTransferable::canExtractObjectDescriptor(rVector) )
2674 aDesc = ODataAccessObjectTransferable::extractObjectDescriptor(rData);
2675 else
2676 bDataAvailable = false;
2678 if ( bDataAvailable )
2680 pConnectionItem.reset(new SfxUsrAnyItem(FN_DB_CONNECTION_ANY, aDesc[DataAccessDescriptorProperty::Connection]));
2681 pColumnItem.reset(new SfxUsrAnyItem(FN_DB_COLUMN_ANY, aDesc[DataAccessDescriptorProperty::ColumnObject]));
2682 pSourceItem.reset(new SfxUsrAnyItem(FN_DB_DATA_SOURCE_ANY, makeAny(aDesc.getDataSource())));
2683 pCommandItem.reset(new SfxUsrAnyItem(FN_DB_DATA_COMMAND_ANY, aDesc[DataAccessDescriptorProperty::Command]));
2684 pCommandTypeItem.reset(new SfxUsrAnyItem(FN_DB_DATA_COMMAND_TYPE_ANY, aDesc[DataAccessDescriptorProperty::CommandType]));
2685 pColumnNameItem.reset(new SfxUsrAnyItem(FN_DB_DATA_COLUMN_NAME_ANY, aDesc[DataAccessDescriptorProperty::ColumnName]));
2686 pSelectionItem.reset(new SfxUsrAnyItem(FN_DB_DATA_SELECTION_ANY, aDesc[DataAccessDescriptorProperty::Selection]));
2687 pCursorItem.reset(new SfxUsrAnyItem(FN_DB_DATA_CURSOR_ANY, aDesc[DataAccessDescriptorProperty::Cursor]));
2690 SwView& rView = rSh.GetView();
2691 //force ::SelectShell
2692 rView.StopShellTimer();
2694 SfxStringItem aDataDesc( nWh, sText );
2695 rView.GetViewFrame()->GetDispatcher()->ExecuteList(
2696 nWh, SfxCallMode::ASYNCHRON,
2697 { &aDataDesc, pConnectionItem.get(), pColumnItem.get(),
2698 pSourceItem.get(), pCommandItem.get(), pCommandTypeItem.get(),
2699 pColumnNameItem.get(), pSelectionItem.get(),
2700 pCursorItem.get() });
2702 else
2704 rSh.MakeDrawView();
2705 FmFormView* pFmView = dynamic_cast<FmFormView*>( rSh.GetDrawView() );
2706 if (pFmView && bHaveColumnDescriptor && pDragPt)
2708 SdrObject* pObj = pFmView->CreateFieldControl( OColumnTransferable::extractColumnDescriptor(rData) );
2709 if ( nullptr != pObj)
2710 rSh.SwFEShell::InsertDrawObj( *pObj, *pDragPt );
2713 bRet = true;
2715 else if( bMsg )
2717 ScopedVclPtrInstance<MessageDialog>(nullptr, SwResId(STR_CLPBRD_FORMAT_ERROR), VclMessageType::Info)->Execute();
2719 return bRet;
2722 bool SwTransferable::PasteFileList( TransferableDataHelper& rData,
2723 SwWrtShell& rSh, bool bLink,
2724 const Point* pPt, bool bMsg )
2726 bool bRet = false;
2727 FileList aFileList;
2728 if( rData.GetFileList( SotClipboardFormatId::FILE_LIST, aFileList ) &&
2729 aFileList.Count() )
2731 SwPasteSdr nAct = bLink ? SwPasteSdr::SetAttr : SwPasteSdr::Insert;
2732 OUString sFlyNm;
2733 // iterate over the filelist
2734 for( sal_uLong n = 0, nEnd = aFileList.Count(); n < nEnd; ++n )
2736 TransferDataContainer* pHlp = new TransferDataContainer;
2737 pHlp->CopyString( SotClipboardFormatId::SIMPLE_FILE, aFileList.GetFile( n ));
2738 TransferableDataHelper aData( pHlp );
2740 if( SwTransferable::PasteFileName( aData, rSh, SotClipboardFormatId::SIMPLE_FILE, nAct,
2741 pPt, SotExchangeActionFlags::NONE, bMsg, nullptr ))
2743 if( bLink )
2745 sFlyNm = rSh.GetFlyName();
2746 SwTransferable::SetSelInShell( rSh, false, pPt );
2748 bRet = true;
2751 if( !sFlyNm.isEmpty() )
2752 rSh.GotoFly( sFlyNm );
2754 else if( bMsg )
2756 ScopedVclPtrInstance<MessageDialog>(nullptr, SwResId(STR_CLPBRD_FORMAT_ERROR), VclMessageType::Info)->Execute();
2758 return bRet;
2761 bool SwTransferable::CheckForURLOrLNKFile( TransferableDataHelper& rData,
2762 OUString& rFileName, OUString* pTitle )
2764 bool bIsURLFile = false;
2765 INetBookmark aBkmk;
2766 if( rData.GetINetBookmark( SotClipboardFormatId::SOLK, aBkmk ) )
2768 rFileName = aBkmk.GetURL();
2769 if( pTitle )
2770 *pTitle = aBkmk.GetDescription();
2771 bIsURLFile = true;
2773 else
2775 sal_Int32 nLen = rFileName.getLength();
2776 if( 4 < nLen && '.' == rFileName[ nLen - 4 ])
2778 OUString sExt( rFileName.copy( nLen - 3 ));
2779 if( sExt.equalsIgnoreAsciiCase( "url" ))
2781 OSL_ENSURE( false, "how do we read today .URL - Files?" );
2785 return bIsURLFile;
2788 bool SwTransferable::IsPasteSpecial( const SwWrtShell& rWrtShell,
2789 const TransferableDataHelper& rData )
2791 // we can paste-special if there's an entry in the paste-special-format list
2792 SvxClipboardFormatItem aClipboardFormatItem(0);
2793 FillClipFormatItem( rWrtShell, rData, aClipboardFormatItem);
2794 return aClipboardFormatItem.Count() > 0;
2797 bool SwTransferable::PasteFormat( SwWrtShell& rSh,
2798 TransferableDataHelper& rData,
2799 SotClipboardFormatId nFormat )
2801 SwWait aWait( *rSh.GetView().GetDocShell(), false );
2802 bool bRet = false;
2804 SotClipboardFormatId nPrivateFormat = SotClipboardFormatId::PRIVATE;
2805 SwTransferable *pClipboard = GetSwTransferable( rData );
2806 if( pClipboard &&
2807 ((TransferBufferType::Document|TransferBufferType::Graphic|TransferBufferType::Ole) & pClipboard->m_eBufferType ))
2808 nPrivateFormat = SotClipboardFormatId::EMBED_SOURCE;
2810 if( pClipboard && nPrivateFormat == nFormat )
2811 bRet = pClipboard->PrivatePaste( rSh );
2812 else if( rData.HasFormat( nFormat ) )
2814 uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
2815 sal_uInt8 nEventAction;
2816 SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
2817 sal_uInt16 nSourceOptions =
2818 (( SotExchangeDest::DOC_TEXTFRAME == nDestination ||
2819 SotExchangeDest::SWDOC_FREE_AREA == nDestination ||
2820 SotExchangeDest::DOC_TEXTFRAME_WEB == nDestination ||
2821 SotExchangeDest::SWDOC_FREE_AREA_WEB == nDestination )
2822 ? EXCHG_IN_ACTION_COPY
2823 : EXCHG_IN_ACTION_MOVE);
2824 SotExchangeActionFlags nActionFlags;
2825 sal_uInt8 nAction = SotExchange::GetExchangeAction(
2826 rData.GetDataFlavorExVector(),
2827 nDestination,
2828 nSourceOptions, /* ?? */
2829 EXCHG_IN_ACTION_DEFAULT, /* ?? */
2830 nFormat, nEventAction, nFormat,
2831 lcl_getTransferPointer ( xTransferable ),
2832 &nActionFlags );
2834 if( EXCHG_INOUT_ACTION_NONE != nAction )
2835 bRet = SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
2836 nDestination, true, false );
2838 return bRet;
2841 bool SwTransferable::TestAllowedFormat( const TransferableDataHelper& rData,
2842 SotClipboardFormatId nFormat, SotExchangeDest nDestination )
2844 sal_uInt8 nAction = EXCHG_INOUT_ACTION_NONE, nEventAction;
2845 if( rData.HasFormat( nFormat )) {
2846 uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
2847 nAction = SotExchange::GetExchangeAction(
2848 rData.GetDataFlavorExVector(),
2849 nDestination, EXCHG_IN_ACTION_COPY,
2850 EXCHG_IN_ACTION_COPY, nFormat,
2851 nEventAction, nFormat,
2852 lcl_getTransferPointer ( xTransferable ) );
2854 return EXCHG_INOUT_ACTION_NONE != nAction;
2858 * the list of formats which will be offered to the user in the 'Paste
2859 * Special...' dialog and the paste button menu
2861 static SotClipboardFormatId aPasteSpecialIds[] =
2863 SotClipboardFormatId::HTML,
2864 SotClipboardFormatId::HTML_SIMPLE,
2865 SotClipboardFormatId::HTML_NO_COMMENT,
2866 SotClipboardFormatId::RTF,
2867 SotClipboardFormatId::RICHTEXT,
2868 SotClipboardFormatId::STRING,
2869 SotClipboardFormatId::SONLK,
2870 SotClipboardFormatId::NETSCAPE_BOOKMARK,
2871 SotClipboardFormatId::DRAWING,
2872 SotClipboardFormatId::SVXB,
2873 SotClipboardFormatId::GDIMETAFILE,
2874 SotClipboardFormatId::BITMAP,
2875 SotClipboardFormatId::SVIM,
2876 SotClipboardFormatId::FILEGRPDESCRIPTOR,
2877 SotClipboardFormatId::NONE
2880 bool SwTransferable::PasteUnformatted( SwWrtShell& rSh, TransferableDataHelper& rData )
2882 // Plain text == unformatted
2883 return SwTransferable::PasteFormat( rSh, rData, SotClipboardFormatId::STRING );
2886 bool SwTransferable::PasteSpecial( SwWrtShell& rSh, TransferableDataHelper& rData, SotClipboardFormatId& rFormatUsed )
2888 bool bRet = false;
2889 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
2890 ScopedVclPtr<SfxAbstractPasteDialog> pDlg(pFact->CreatePasteDialog( &rSh.GetView().GetEditWin() ));
2892 DataFlavorExVector aFormats( rData.GetDataFlavorExVector() );
2893 TransferableObjectDescriptor aDesc;
2895 SotExchangeDest nDest = SwTransferable::GetSotDestination( rSh );
2897 SwTransferable *pClipboard = GetSwTransferable( rData );
2898 if( pClipboard )
2900 aDesc = pClipboard->m_aObjDesc;
2901 sal_uInt16 nResId;
2902 if( pClipboard->m_eBufferType & TransferBufferType::Document )
2903 nResId = STR_PRIVATETEXT;
2904 else if( pClipboard->m_eBufferType & TransferBufferType::Graphic )
2905 nResId = STR_PRIVATEGRAPHIC;
2906 else if( pClipboard->m_eBufferType == TransferBufferType::Ole )
2907 nResId = STR_PRIVATEOLE;
2908 else
2909 nResId = 0;
2911 if( nResId )
2913 if( STR_PRIVATEOLE == nResId || STR_PRIVATEGRAPHIC == nResId )
2915 // add SotClipboardFormatId::EMBED_SOURCE to the formats. This
2916 // format display then the private format name.
2917 DataFlavorEx aFlavorEx;
2918 aFlavorEx.mnSotId = SotClipboardFormatId::EMBED_SOURCE;
2919 aFormats.insert( aFormats.begin(), aFlavorEx );
2921 pDlg->SetObjName( pClipboard->m_aObjDesc.maClassName,
2922 SwResId( nResId ) );
2923 pDlg->Insert( SotClipboardFormatId::EMBED_SOURCE, aEmptyOUStr );
2926 else
2928 if( rData.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR ) )
2930 (void)rData.GetTransferableObjectDescriptor(
2931 SotClipboardFormatId::OBJECTDESCRIPTOR, aDesc );
2934 if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::EMBED_SOURCE, nDest ))
2935 pDlg->Insert( SotClipboardFormatId::EMBED_SOURCE, aEmptyOUStr );
2936 if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK_SOURCE, nDest ))
2937 pDlg->Insert( SotClipboardFormatId::LINK_SOURCE, aEmptyOUStr );
2940 if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK, nDest ))
2941 pDlg->Insert( SotClipboardFormatId::LINK, SwResId(STR_DDEFORMAT) );
2943 for( SotClipboardFormatId* pIds = aPasteSpecialIds; *pIds != SotClipboardFormatId::NONE; ++pIds )
2944 if( SwTransferable::TestAllowedFormat( rData, *pIds, nDest ))
2945 pDlg->Insert( *pIds, aEmptyOUStr );
2947 SotClipboardFormatId nFormat = pDlg->GetFormat( rData.GetTransferable() );
2949 if( nFormat != SotClipboardFormatId::NONE )
2950 bRet = SwTransferable::PasteFormat( rSh, rData, nFormat );
2952 if ( bRet )
2953 rFormatUsed = nFormat;
2955 return bRet;
2958 void SwTransferable::FillClipFormatItem( const SwWrtShell& rSh,
2959 const TransferableDataHelper& rData,
2960 SvxClipboardFormatItem & rToFill )
2962 SotExchangeDest nDest = SwTransferable::GetSotDestination( rSh );
2964 SwTransferable *pClipboard = GetSwTransferable( rData );
2965 if( pClipboard )
2967 sal_uInt16 nResId;
2968 if( pClipboard->m_eBufferType & TransferBufferType::Document )
2969 nResId = STR_PRIVATETEXT;
2970 else if( pClipboard->m_eBufferType & TransferBufferType::Graphic )
2971 nResId = STR_PRIVATEGRAPHIC;
2972 else if( pClipboard->m_eBufferType == TransferBufferType::Ole )
2973 nResId = STR_PRIVATEOLE;
2974 else
2975 nResId = 0;
2977 if( nResId )
2978 rToFill.AddClipbrdFormat( SotClipboardFormatId::EMBED_SOURCE,
2979 SwResId( nResId ) );
2981 else
2983 TransferableObjectDescriptor aDesc;
2984 if (rData.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR))
2986 (void)const_cast<TransferableDataHelper&>(rData).GetTransferableObjectDescriptor(
2987 SotClipboardFormatId::OBJECTDESCRIPTOR, aDesc);
2990 if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::EMBED_SOURCE, nDest ))
2991 rToFill.AddClipbrdFormat( SotClipboardFormatId::EMBED_SOURCE,
2992 aDesc.maTypeName );
2993 if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK_SOURCE, nDest ))
2994 rToFill.AddClipbrdFormat( SotClipboardFormatId::LINK_SOURCE );
2996 SotClipboardFormatId nFormat;
2997 if ( rData.HasFormat(nFormat = SotClipboardFormatId::EMBED_SOURCE_OLE) || rData.HasFormat(nFormat = SotClipboardFormatId::EMBEDDED_OBJ_OLE) )
2999 OUString sName,sSource;
3000 if ( SvPasteObjectHelper::GetEmbeddedName(rData,sName,sSource,nFormat) )
3001 rToFill.AddClipbrdFormat( nFormat, sName );
3005 if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK, nDest ))
3006 rToFill.AddClipbrdFormat( SotClipboardFormatId::LINK, SwResId(STR_DDEFORMAT) );
3008 for( SotClipboardFormatId* pIds = aPasteSpecialIds; *pIds != SotClipboardFormatId::NONE; ++pIds )
3009 if( SwTransferable::TestAllowedFormat( rData, *pIds, nDest ))
3010 rToFill.AddClipbrdFormat( *pIds, aEmptyOUStr );
3013 void SwTransferable::SetDataForDragAndDrop( const Point& rSttPos )
3015 if(!m_pWrtShell)
3016 return;
3017 OUString sGrfNm;
3018 const SelectionType nSelection = m_pWrtShell->GetSelectionType();
3019 if( SelectionType::Graphic == nSelection)
3021 AddFormat( SotClipboardFormatId::SVXB );
3022 const Graphic* pGrf = m_pWrtShell->GetGraphic();
3023 if ( pGrf && pGrf->IsSupportedGraphic() )
3025 AddFormat( SotClipboardFormatId::GDIMETAFILE );
3026 AddFormat( SotClipboardFormatId::PNG );
3027 AddFormat( SotClipboardFormatId::BITMAP );
3029 m_eBufferType = TransferBufferType::Graphic;
3030 m_pWrtShell->GetGrfNms( &sGrfNm, nullptr );
3032 else if( SelectionType::Ole == nSelection )
3034 AddFormat( SotClipboardFormatId::EMBED_SOURCE );
3035 PrepareOLE( m_aObjDesc );
3036 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
3037 AddFormat( SotClipboardFormatId::GDIMETAFILE );
3038 m_eBufferType = TransferBufferType::Ole;
3040 //Is there anything to provide anyway?
3041 else if ( m_pWrtShell->IsSelection() || m_pWrtShell->IsFrameSelected() ||
3042 m_pWrtShell->IsObjSelected() )
3044 if( m_pWrtShell->IsObjSelected() )
3045 m_eBufferType = TransferBufferType::Drawing;
3046 else
3048 m_eBufferType = TransferBufferType::Document;
3049 if( SwWrtShell::NO_WORD !=
3050 m_pWrtShell->IntelligentCut( nSelection, false ))
3051 m_eBufferType = TransferBufferType::DocumentWord | m_eBufferType;
3054 if( nSelection & SelectionType::TableCell )
3055 m_eBufferType = TransferBufferType::Table | m_eBufferType;
3057 AddFormat( SotClipboardFormatId::EMBED_SOURCE );
3059 //put RTF ahead of the OLE's Metafile for less loss
3060 if( !m_pWrtShell->IsObjSelected() )
3062 AddFormat( SotClipboardFormatId::RTF );
3063 AddFormat( SotClipboardFormatId::RICHTEXT );
3064 AddFormat( SotClipboardFormatId::HTML );
3066 if( m_pWrtShell->IsSelection() )
3067 AddFormat( SotClipboardFormatId::STRING );
3069 if( nSelection & ( SelectionType::DrawObject | SelectionType::DbForm ))
3071 AddFormat( SotClipboardFormatId::DRAWING );
3072 if ( nSelection & SelectionType::DrawObject )
3074 AddFormat( SotClipboardFormatId::GDIMETAFILE );
3075 AddFormat( SotClipboardFormatId::PNG );
3076 AddFormat( SotClipboardFormatId::BITMAP );
3078 m_eBufferType = TransferBufferType::Graphic | m_eBufferType;
3080 m_pClpGraphic = new Graphic;
3081 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_pClpGraphic ))
3082 m_pOrigGraphic = m_pClpGraphic;
3083 m_pClpBitmap = new Graphic;
3084 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_pClpBitmap ))
3085 m_pOrigGraphic = m_pClpBitmap;
3087 // is it an URL-Button ?
3088 OUString sURL;
3089 OUString sDesc;
3090 if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) )
3092 AddFormat( SotClipboardFormatId::STRING );
3093 AddFormat( SotClipboardFormatId::SOLK );
3094 AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
3095 AddFormat( SotClipboardFormatId::FILECONTENT );
3096 AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
3097 AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
3098 m_eBufferType = TransferBufferType::InetField | m_eBufferType;
3102 //ObjectDescriptor was already filled from the old DocShell.
3103 //Now adjust it. Thus in GetData the first query can still
3104 //be answered with delayed rendering.
3105 m_aObjDesc.maDragStartPos = rSttPos;
3106 m_aObjDesc.maSize = OutputDevice::LogicToLogic( Size( OLESIZE ),
3107 MapUnit::MapTwip, MapUnit::Map100thMM );
3108 PrepareOLE( m_aObjDesc );
3109 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
3111 else if( nSelection & SelectionType::Text && !m_pWrtShell->HasMark() )
3113 // is only one field - selected?
3114 SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
3115 Point aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY());
3117 if( m_pWrtShell->GetContentAtPos( aPos, aContentAtPos ) )
3119 AddFormat( SotClipboardFormatId::STRING );
3120 AddFormat( SotClipboardFormatId::SOLK );
3121 AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
3122 AddFormat( SotClipboardFormatId::FILECONTENT );
3123 AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
3124 AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
3125 m_eBufferType = TransferBufferType::InetField;
3129 if( m_pWrtShell->IsFrameSelected() )
3131 SfxItemSet aSet( m_pWrtShell->GetAttrPool(), RES_URL, RES_URL );
3132 m_pWrtShell->GetFlyFrameAttr( aSet );
3133 const SwFormatURL& rURL = static_cast<const SwFormatURL&>(aSet.Get( RES_URL ));
3134 if( rURL.GetMap() )
3136 m_pImageMap = new ImageMap( *rURL.GetMap() );
3137 AddFormat( SotClipboardFormatId::SVIM );
3139 else if( !rURL.GetURL().isEmpty() )
3141 m_pTargetURL = new INetImage( sGrfNm, rURL.GetURL(),
3142 rURL.GetTargetFrameName() );
3143 AddFormat( SotClipboardFormatId::INET_IMAGE );
3148 void SwTransferable::StartDrag( vcl::Window* pWin, const Point& rPos )
3150 if(!m_pWrtShell)
3151 return;
3152 m_bOldIdle = m_pWrtShell->GetViewOptions()->IsIdle();
3153 m_bCleanUp = true;
3155 m_pWrtShell->GetViewOptions()->SetIdle( false );
3157 if( m_pWrtShell->IsSelFrameMode() )
3158 m_pWrtShell->ShowCursor();
3160 SW_MOD()->m_pDragDrop = this;
3162 SetDataForDragAndDrop( rPos );
3164 sal_Int8 nDragOptions = DND_ACTION_COPYMOVE | DND_ACTION_LINK;
3165 SwDocShell* pDShell = m_pWrtShell->GetView().GetDocShell();
3166 if( ( pDShell && pDShell->IsReadOnly() ) || m_pWrtShell->HasReadonlySel() )
3167 nDragOptions &= ~DND_ACTION_MOVE;
3169 TransferableHelper::StartDrag( pWin, nDragOptions );
3172 void SwTransferable::DragFinished( sal_Int8 nAction )
3174 //And the last finishing work so that all statuses are right
3175 if( DND_ACTION_MOVE == nAction )
3177 if( m_bCleanUp )
3179 //It was dropped outside of Writer. We still have to
3180 //delete.
3182 m_pWrtShell->StartAllAction();
3183 m_pWrtShell->StartUndo( SwUndoId::UI_DRAG_AND_MOVE );
3184 if ( m_pWrtShell->IsTableMode() )
3185 m_pWrtShell->DeleteTableSel();
3186 else
3188 if ( !(m_pWrtShell->IsSelFrameMode() || m_pWrtShell->IsObjSelected()) )
3189 //SmartCut, take one of the blanks along
3190 m_pWrtShell->IntelligentCut( m_pWrtShell->GetSelectionType() );
3191 m_pWrtShell->DelRight();
3193 m_pWrtShell->EndUndo( SwUndoId::UI_DRAG_AND_MOVE );
3194 m_pWrtShell->EndAllAction();
3196 else
3198 const SelectionType nSelection = m_pWrtShell->GetSelectionType();
3199 if( ( SelectionType::Frame | SelectionType::Graphic |
3200 SelectionType::Ole | SelectionType::DrawObject ) & nSelection )
3202 m_pWrtShell->EnterSelFrameMode();
3206 m_pWrtShell->GetView().GetEditWin().DragFinished();
3208 if( m_pWrtShell->IsSelFrameMode() )
3209 m_pWrtShell->HideCursor();
3210 else
3211 m_pWrtShell->ShowCursor();
3213 m_pWrtShell->GetViewOptions()->SetIdle( m_bOldIdle );
3216 namespace
3219 bool lcl_checkClassification(SwDoc* pSourceDoc, SwDoc* pDestinationDoc)
3221 if (!pSourceDoc || !pDestinationDoc)
3222 return true;
3224 SwDocShell* pSourceShell = pSourceDoc->GetDocShell();
3225 SwDocShell* pDestinationShell = pDestinationDoc->GetDocShell();
3226 if (!pSourceShell || !pDestinationShell)
3227 return true;
3229 SfxClassificationCheckPasteResult eResult = SfxClassificationHelper::CheckPaste(pSourceShell->getDocProperties(), pDestinationShell->getDocProperties());
3230 return SfxClassificationHelper::ShowPasteInfo(eResult);
3235 bool SwTransferable::PrivatePaste( SwWrtShell& rShell )
3237 // first, ask for the SelectionType, then action-bracketing !!!!
3238 // (otherwise it's not pasted into a TableSelection!!!)
3239 OSL_ENSURE( !rShell.ActionPend(), "Paste must never have an ActionPend" );
3240 if ( !m_pClpDocFac )
3241 return false; // the return value of the SwFEShell::Paste also is bool!
3243 const SelectionType nSelection = rShell.GetSelectionType();
3245 SwTrnsfrActionAndUndo aAction( &rShell );
3247 bool bKillPaMs = false;
3249 //Delete selected content, not at table-selection and table in Clipboard, and don't delete hovering graphics.
3250 if( rShell.HasSelection() && !( nSelection & SelectionType::TableCell) && !( nSelection & SelectionType::DrawObject))
3252 bKillPaMs = true;
3253 rShell.SetRetainSelection( true );
3254 rShell.DelRight();
3255 // when a Fly was selected, a valid cursor position has to be found now
3256 // (parked Cursor!)
3257 if( ( SelectionType::Frame | SelectionType::Graphic |
3258 SelectionType::Ole | SelectionType::DrawObject |
3259 SelectionType::DbForm ) & nSelection )
3261 // position the cursor again
3262 Point aPt( rShell.GetCharRect().Pos() );
3263 rShell.SwCursorShell::SetCursor( aPt, true );
3265 rShell.SetRetainSelection( false );
3267 if ( nSelection & SelectionType::DrawObject) //unselect hovering graphics
3269 rShell.ResetSelect(nullptr,false);
3272 bool bInWrd = false, bEndWrd = false, bSttWrd = false,
3273 bSmart(TransferBufferType::DocumentWord & m_eBufferType);
3274 if( bSmart )
3276 // Why not for other Scripts? If TransferBufferType::DocumentWord is set, we have a word
3277 // in the buffer, word in this context means 'something with spaces at beginning
3278 // and end'. In this case we definitely want these spaces to be inserted here.
3279 bInWrd = rShell.IsInWord();
3280 bEndWrd = rShell.IsEndWrd();
3281 bSmart = bInWrd || bEndWrd;
3282 if( bSmart )
3284 bSttWrd = rShell.IsStartWord();
3285 if( bSmart && !bSttWrd && (bInWrd || bEndWrd) )
3286 rShell.SwEditShell::Insert(' ');
3290 bool bRet = true;
3291 // m_pWrtShell is nullptr when the source document is closed already.
3292 if (!m_pWrtShell || lcl_checkClassification(m_pWrtShell->GetDoc(), rShell.GetDoc()))
3293 bRet = rShell.Paste(m_pClpDocFac->GetDoc());
3295 if( bKillPaMs )
3296 rShell.KillPams();
3298 // If Smart Paste then insert blank
3299 if( bRet && bSmart && ((bInWrd && !bEndWrd )|| bSttWrd) )
3300 rShell.SwEditShell::Insert(' ');
3302 return bRet;
3305 bool SwTransferable::PrivateDrop( SwWrtShell& rSh, const Point& rDragPt,
3306 bool bMove, bool bIsXSelection )
3308 int cWord = 0;
3309 bool bInWrd = false;
3310 bool bEndWrd = false;
3311 bool bSttWrd = false;
3312 bool bSttPara = false;
3313 bool bTableSel = false;
3314 bool bFrameSel = false;
3316 SwWrtShell& rSrcSh = *GetShell();
3318 rSh.UnSetVisibleCursor();
3320 if( TransferBufferType::InetField == m_eBufferType )
3322 if( rSh.GetFormatFromObj( rDragPt ) )
3324 INetBookmark aTmp;
3325 if( (TransferBufferType::InetField & m_eBufferType) && m_pBookmark )
3326 aTmp = *m_pBookmark;
3328 // select target graphic
3329 if( rSh.SelectObj( rDragPt ) )
3331 rSh.HideCursor();
3332 rSh.EnterSelFrameMode( &rDragPt );
3333 g_bFrameDrag = true;
3336 const SelectionType nSelection = rSh.GetSelectionType();
3338 // not yet consider Draw objects
3339 if( SelectionType::Graphic & nSelection )
3341 SfxItemSet aSet( rSh.GetAttrPool(), RES_URL, RES_URL );
3342 rSh.GetFlyFrameAttr( aSet );
3343 SwFormatURL aURL( static_cast<const SwFormatURL&>(aSet.Get( RES_URL )) );
3344 aURL.SetURL( aTmp.GetURL(), false );
3345 aSet.Put( aURL );
3346 rSh.SetFlyFrameAttr( aSet );
3347 return true;
3350 if( SelectionType::DrawObject & nSelection )
3352 rSh.LeaveSelFrameMode();
3353 rSh.UnSelectFrame();
3354 rSh.ShowCursor();
3355 g_bFrameDrag = false;
3360 if( &rSh != &rSrcSh && (SelectionType::Graphic & rSh.GetSelectionType()) &&
3361 TransferBufferType::Graphic == m_eBufferType )
3363 // ReRead the graphic
3364 OUString sGrfNm;
3365 OUString sFltNm;
3366 rSrcSh.GetGrfNms( &sGrfNm, &sFltNm );
3367 rSh.ReRead( sGrfNm, sFltNm, rSrcSh.GetGraphic() );
3368 return true;
3371 //not in selections or selected frames
3372 if( rSh.TestCurrPam( rDragPt ) ||
3373 ( rSh.IsSelFrameMode() && rSh.IsInsideSelectedObj( rDragPt )) )
3374 return false;
3376 if( rSrcSh.IsTableMode() )
3377 bTableSel = true;
3378 else if( rSrcSh.IsSelFrameMode() || rSrcSh.IsObjSelected() )
3380 // don't move position-protected objects!
3381 if( bMove && rSrcSh.IsSelObjProtected( FlyProtectFlags::Pos ) != FlyProtectFlags::NONE )
3382 return false;
3384 bFrameSel = true;
3387 const SelectionType nSel = rSrcSh.GetSelectionType();
3389 SwUndoId eUndoId = bMove ? SwUndoId::UI_DRAG_AND_MOVE : SwUndoId::UI_DRAG_AND_COPY;
3391 SwRewriter aRewriter;
3393 aRewriter.AddRule(UndoArg1, rSrcSh.GetSelDescr());
3395 if(rSrcSh.GetDoc() != rSh.GetDoc())
3396 rSrcSh.StartUndo( eUndoId, &aRewriter );
3397 rSh.StartUndo( eUndoId, &aRewriter );
3399 rSh.StartAction();
3400 rSrcSh.StartAction();
3402 if( &rSrcSh != &rSh )
3404 rSh.EnterStdMode();
3405 rSh.SwCursorShell::SetCursor( rDragPt, true );
3406 cWord = rSrcSh.IntelligentCut( nSel, false );
3408 else if( !bTableSel && !bFrameSel )
3410 if( !rSh.IsAddMode() )
3412 // #i87233#
3413 if ( rSh.IsBlockMode() )
3415 // preserve order of cursors for block mode
3416 rSh.GoPrevCursor();
3419 rSh.SwCursorShell::CreateCursor();
3421 rSh.SwCursorShell::SetCursor( rDragPt, true, false );
3422 rSh.GoPrevCursor();
3423 cWord = rSh.IntelligentCut( rSh.GetSelectionType(), false );
3424 rSh.GoNextCursor();
3427 bInWrd = rSh.IsInWord();
3428 bEndWrd = rSh.IsEndWrd();
3429 bSttWrd = !bEndWrd && rSh.IsStartWord();
3430 bSttPara= rSh.IsSttPara();
3432 Point aSttPt( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY() );
3434 // at first, select INetFelder!
3435 if( TransferBufferType::InetField == m_eBufferType )
3437 if( &rSrcSh == &rSh )
3439 rSh.GoPrevCursor();
3440 rSh.SwCursorShell::SetCursor( aSttPt, true );
3441 rSh.SelectTextAttr( RES_TXTATR_INETFMT );
3442 if( rSh.TestCurrPam( rDragPt ) )
3444 // don't copy/move inside of yourself
3445 rSh.DestroyCursor();
3446 rSh.EndUndo();
3447 rSh.EndAction();
3448 rSh.EndAction();
3449 return false;
3451 rSh.GoNextCursor();
3453 else
3455 rSrcSh.SwCursorShell::SetCursor( aSttPt, true );
3456 rSrcSh.SelectTextAttr( RES_TXTATR_INETFMT );
3459 // is there an URL attribute at the insert point? Then replace that,
3460 // so simply put up a selection?
3461 rSh.DelINetAttrWithText();
3462 g_bDDINetAttr = true;
3465 if ( rSrcSh.IsSelFrameMode() )
3467 //Hack: fool the special treatment
3468 aSttPt -= aSttPt - rSrcSh.GetObjRect().Pos();
3471 bool bRet = rSrcSh.SwFEShell::Copy( &rSh, aSttPt, rDragPt, bMove,
3472 !bIsXSelection );
3474 if( !bIsXSelection )
3476 rSrcSh.Push();
3477 if ( bRet && bMove && !bFrameSel )
3479 if ( bTableSel )
3481 /* delete table contents not cells */
3482 rSrcSh.Delete();
3484 else
3486 //SmartCut, take one of the blanks along.
3487 rSh.SwCursorShell::DestroyCursor();
3488 if ( cWord == SwWrtShell::WORD_SPACE_BEFORE )
3489 rSh.ExtendSelection( false );
3490 else if ( cWord == SwWrtShell::WORD_SPACE_AFTER )
3491 rSh.ExtendSelection();
3492 rSrcSh.DelRight();
3495 rSrcSh.KillPams();
3496 rSrcSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
3498 /* after dragging a table selection inside one shell
3499 set cursor to the drop position. */
3500 if( &rSh == &rSrcSh && ( bTableSel || rSh.IsBlockMode() ) )
3502 rSrcSh.CalcLayout();
3503 rSrcSh.SwCursorShell::SetCursor(rDragPt);
3504 rSrcSh.GetSwCursor()->SetMark();
3508 if( bRet && !bTableSel && !bFrameSel )
3510 if( (bInWrd || bEndWrd) &&
3511 (cWord == SwWrtShell::WORD_SPACE_AFTER ||
3512 cWord == SwWrtShell::WORD_SPACE_BEFORE) )
3514 if ( bSttWrd || (bInWrd && !bEndWrd))
3515 rSh.SwEditShell::Insert(' ', bIsXSelection);
3516 if ( !bSttWrd || (bInWrd && !bSttPara) )
3518 rSh.SwapPam();
3519 if ( !bSttWrd )
3520 rSh.SwEditShell::Insert(' ', bIsXSelection);
3521 rSh.SwapPam();
3525 if( bIsXSelection )
3527 if( &rSrcSh == &rSh && !rSh.IsAddMode() )
3529 rSh.SwCursorShell::DestroyCursor();
3530 rSh.GoPrevCursor();
3532 else
3534 rSh.SwapPam();
3535 rSh.SwCursorShell::ClearMark();
3538 else
3540 if( rSh.IsAddMode() )
3541 rSh.SwCursorShell::CreateCursor();
3542 else
3544 // turn on selection mode
3545 rSh.SttSelect();
3546 rSh.EndSelect();
3551 if( bRet && bMove && bFrameSel )
3552 rSrcSh.LeaveSelFrameMode();
3554 if( rSrcSh.GetDoc() != rSh.GetDoc() )
3555 rSrcSh.EndUndo();
3556 rSh.EndUndo();
3558 // put the shell in the right state
3559 if( &rSrcSh != &rSh && ( rSh.IsFrameSelected() || rSh.IsObjSelected() ))
3560 rSh.EnterSelFrameMode();
3562 rSrcSh.EndAction();
3563 rSh.EndAction();
3564 return true;
3567 // Interfaces for Selection
3568 void SwTransferable::CreateSelection( SwWrtShell& rSh,
3569 const SwFrameShell * _pCreatorView )
3571 SwModule *pMod = SW_MOD();
3572 rtl::Reference<SwTransferable> pNew = new SwTransferable( rSh );
3574 pNew->m_pCreatorView = _pCreatorView;
3576 pMod->m_pXSelection = pNew.get();
3577 pNew->CopyToSelection( rSh.GetWin() );
3580 void SwTransferable::ClearSelection( SwWrtShell& rSh,
3581 const SwFrameShell * _pCreatorView)
3583 SwModule *pMod = SW_MOD();
3584 if( pMod->m_pXSelection &&
3585 ((!pMod->m_pXSelection->m_pWrtShell) || (pMod->m_pXSelection->m_pWrtShell == &rSh)) &&
3586 (!_pCreatorView || (pMod->m_pXSelection->m_pCreatorView == _pCreatorView)) )
3588 TransferableHelper::ClearSelection( rSh.GetWin() );
3592 namespace
3594 class theSwTransferableUnoTunnelId : public rtl::Static< UnoTunnelIdInit, SwTransferable > {};
3597 const Sequence< sal_Int8 >& SwTransferable::getUnoTunnelId()
3599 return theSwTransferableUnoTunnelId::get().getSeq();
3602 sal_Int64 SwTransferable::getSomething( const Sequence< sal_Int8 >& rId )
3604 sal_Int64 nRet;
3605 if( ( rId.getLength() == 16 ) &&
3606 ( 0 == memcmp( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
3608 nRet = sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this ) );
3610 else
3611 nRet = TransferableHelper::getSomething(rId);
3612 return nRet;
3615 SwTransferable* SwTransferable::GetSwTransferable( const TransferableDataHelper& rData )
3617 SwTransferable* pSwTransferable = nullptr;
3619 uno::Reference<XUnoTunnel> xTunnel( rData.GetTransferable(), UNO_QUERY );
3620 if ( xTunnel.is() )
3622 sal_Int64 nHandle = xTunnel->getSomething( getUnoTunnelId() );
3623 if ( nHandle )
3624 pSwTransferable = reinterpret_cast<SwTransferable*>( (sal_IntPtr) nHandle );
3627 return pSwTransferable;
3631 SwTrnsfrDdeLink::SwTrnsfrDdeLink( SwTransferable& rTrans, SwWrtShell& rSh )
3632 : rTrnsfr(rTrans)
3633 , pDocShell(nullptr)
3634 , nOldTimeOut(0)
3635 , bDelBookmrk(false)
3636 , bInDisconnect(false)
3638 // we only end up here with table- or text selection
3639 if( SelectionType::TableCell & rSh.GetSelectionType() )
3641 SwFrameFormat* pFormat = rSh.GetTableFormat();
3642 if( pFormat )
3643 sName = pFormat->GetName();
3645 else
3647 // creating a temp. bookmark without undo
3648 bool bUndo = rSh.DoesUndo();
3649 rSh.DoUndo( false );
3650 bool bIsModified = rSh.IsModified();
3652 ::sw::mark::IMark* pMark = rSh.SetBookmark(
3653 vcl::KeyCode(),
3654 OUString(),
3655 IDocumentMarkAccess::MarkType::DDE_BOOKMARK);
3656 if(pMark)
3658 sName = pMark->GetName();
3659 bDelBookmrk = true;
3660 if( !bIsModified )
3661 rSh.ResetModified();
3663 else
3664 sName.clear();
3665 rSh.DoUndo( bUndo );
3668 if( !sName.isEmpty() &&
3669 nullptr != ( pDocShell = rSh.GetDoc()->GetDocShell() ) )
3671 // then we create our "server" and connect to it
3672 refObj = pDocShell->DdeCreateLinkSource( sName );
3673 if( refObj.is() )
3675 refObj->AddConnectAdvise( this );
3676 refObj->AddDataAdvise( this,
3677 aEmptyOUStr,
3678 ADVISEMODE_NODATA | ADVISEMODE_ONLYONCE );
3679 nOldTimeOut = refObj->GetUpdateTimeout();
3680 refObj->SetUpdateTimeout( 0 );
3685 SwTrnsfrDdeLink::~SwTrnsfrDdeLink()
3687 if( refObj.is() )
3688 Disconnect( true );
3691 ::sfx2::SvBaseLink::UpdateResult SwTrnsfrDdeLink::DataChanged( const OUString& ,
3692 const uno::Any& )
3694 // well, that's it with the link
3695 if( !bInDisconnect )
3697 if( FindDocShell() && pDocShell->GetView() )
3698 rTrnsfr.RemoveDDELinkFormat( pDocShell->GetView()->GetEditWin() );
3699 Disconnect( false );
3701 return SUCCESS;
3704 bool SwTrnsfrDdeLink::WriteData( SvStream& rStrm )
3706 if( !refObj.is() || !FindDocShell() )
3707 return false;
3709 rtl_TextEncoding eEncoding = DDE_TXT_ENCODING;
3710 const OString aAppNm(OUStringToOString(
3711 Application::GetAppName(), eEncoding));
3712 const OString aTopic(OUStringToOString(
3713 pDocShell->GetTitle(SFX_TITLE_FULLNAME), eEncoding));
3714 const OString aName(OUStringToOString(sName, eEncoding));
3716 std::unique_ptr<sal_Char[]> pMem(new sal_Char[ aAppNm.getLength() + aTopic.getLength() + aName.getLength() + 4 ]);
3718 sal_Int32 nLen = aAppNm.getLength();
3719 memcpy( pMem.get(), aAppNm.getStr(), nLen );
3720 pMem[ nLen++ ] = 0;
3721 memcpy( pMem.get() + nLen, aTopic.getStr(), aTopic.getLength() );
3722 nLen = nLen + aTopic.getLength();
3723 pMem[ nLen++ ] = 0;
3724 memcpy( pMem.get() + nLen, aName.getStr(), aName.getLength() );
3725 nLen = nLen + aName.getLength();
3726 pMem[ nLen++ ] = 0;
3727 pMem[ nLen++ ] = 0;
3729 rStrm.WriteBytes( pMem.get(), nLen );
3730 pMem.reset();
3732 IDocumentMarkAccess* const pMarkAccess = pDocShell->GetDoc()->getIDocumentMarkAccess();
3733 IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->findMark(sName);
3734 if(ppMark != pMarkAccess->getAllMarksEnd()
3735 && IDocumentMarkAccess::GetType(**ppMark) != IDocumentMarkAccess::MarkType::BOOKMARK)
3737 // the mark is still a DdeBookmark
3738 // we replace it with a Bookmark, so it will get saved etc.
3739 ::sw::mark::IMark* const pMark = ppMark->get();
3740 ::sfx2::SvLinkSource* p = refObj.get();
3741 SwServerObject& rServerObject = dynamic_cast<SwServerObject&>(*p);
3743 // collecting state of old mark
3744 SwPaM aPaM(pMark->GetMarkStart());
3745 *aPaM.GetPoint() = pMark->GetMarkStart();
3746 if(pMark->IsExpanded())
3748 aPaM.SetMark();
3749 *aPaM.GetMark() = pMark->GetMarkEnd();
3751 OUString sMarkName = pMark->GetName();
3753 // remove mark
3754 rServerObject.SetNoServer(); // this removes the connection between SwServerObject and mark
3755 // N.B. ppMark was not loaded from file and cannot have xml:id
3756 pMarkAccess->deleteMark(ppMark);
3758 // recreate as Bookmark
3759 ::sw::mark::IMark* const pNewMark = pMarkAccess->makeMark(
3760 aPaM,
3761 sMarkName,
3762 IDocumentMarkAccess::MarkType::BOOKMARK,
3763 ::sw::mark::InsertMode::New);
3764 rServerObject.SetDdeBookmark(*pNewMark);
3767 bDelBookmrk = false;
3768 return true;
3771 void SwTrnsfrDdeLink::Disconnect( bool bRemoveDataAdvise )
3773 // don't accept DataChanged anymore, when already in Disconnect!
3774 // (DTOR from Bookmark sends a DataChanged!)
3775 bool bOldDisconnect = bInDisconnect;
3776 bInDisconnect = true;
3778 // destroy the unused bookmark again (without Undo!)?
3779 if( bDelBookmrk && refObj.is() && FindDocShell() )
3781 SwDoc* pDoc = pDocShell->GetDoc();
3782 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
3784 // #i58448#
3785 Link<bool,void> aSavedOle2Link( pDoc->GetOle2Link() );
3786 pDoc->SetOle2Link( Link<bool,void>() );
3788 bool bIsModified = pDoc->getIDocumentState().IsModified();
3790 IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
3791 pMarkAccess->deleteMark(pMarkAccess->findMark(sName));
3793 if( !bIsModified )
3794 pDoc->getIDocumentState().ResetModified();
3795 // #i58448#
3796 pDoc->SetOle2Link( aSavedOle2Link );
3798 bDelBookmrk = false;
3801 if( refObj.is() )
3803 refObj->SetUpdateTimeout( nOldTimeOut );
3804 refObj->RemoveConnectAdvise( this );
3805 if( bRemoveDataAdvise )
3806 // in a DataChanged the SelectionObject must NEVER be deleted
3807 // is already handled by the base class
3808 // (ADVISEMODE_ONLYONCE!!!!)
3809 // but always in normal Disconnect!
3810 refObj->RemoveAllDataAdvise( this );
3811 refObj.clear();
3813 bInDisconnect = bOldDisconnect;
3816 bool SwTrnsfrDdeLink::FindDocShell()
3818 SfxObjectShell* pTmpSh = SfxObjectShell::GetFirst( checkSfxObjectShell<SwDocShell> );
3819 while( pTmpSh )
3821 if( pTmpSh == pDocShell ) // that's what we want to have
3823 if( pDocShell->GetDoc() )
3824 return true;
3825 break; // the Doc is not there anymore, so leave!
3827 pTmpSh = SfxObjectShell::GetNext( *pTmpSh, checkSfxObjectShell<SwDocShell> );
3830 pDocShell = nullptr;
3831 return false;
3834 void SwTrnsfrDdeLink::Closed()
3836 if( !bInDisconnect && refObj.is() )
3838 refObj->RemoveAllDataAdvise( this );
3839 refObj->RemoveConnectAdvise( this );
3840 refObj.clear();
3844 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */