USHRT_MAX -> SAL_MAX_UINT16
[LibreOffice.git] / sw / source / uibase / dochdl / swdtflvr.cxx
blob8157dfd71f8166a9cb77a2cf4bc332d190558832
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/fileformat.h>
32 #include <comphelper/processfactory.hxx>
33 #include <comphelper/servicehelper.hxx>
34 #include <comphelper/storagehelper.hxx>
35 #include <comphelper/string.hxx>
36 #include <o3tl/deleter.hxx>
37 #include <unotools/ucbstreamhelper.hxx>
38 #include <sot/filelist.hxx>
39 #include <svx/svxdlg.hxx>
40 #include <toolkit/helper/vclunohelper.hxx>
41 #include <osl/endian.h>
42 #include <sfx2/linkmgr.hxx>
43 #include <tools/urlobj.hxx>
44 #include <vcl/wrkwin.hxx>
45 #include <vcl/layout.hxx>
46 #include <vcl/msgbox.hxx>
47 #include <sfx2/dispatch.hxx>
48 #include <svl/stritem.hxx>
49 #include <svtools/imap.hxx>
50 #include <sot/storage.hxx>
51 #include <vcl/graph.hxx>
52 #include <svl/urihelper.hxx>
53 #include <svx/svdmodel.hxx>
54 #include <svx/xexch.hxx>
55 #include <svx/xmlexchg.hxx>
56 #include <svx/dbaexchange.hxx>
57 #include <svx/clipfmtitem.hxx>
58 #include <sfx2/mieclip.hxx>
59 #include <svx/svdetc.hxx>
60 #include <svx/xoutbmp.hxx>
61 #include <svl/urlbmk.hxx>
62 #include <svtools/htmlout.hxx>
63 #include <svx/hlnkitem.hxx>
64 #include <svtools/inetimg.hxx>
65 #include <editeng/paperinf.hxx>
66 #include <svx/fmview.hxx>
67 #include <editeng/scripttypeitem.hxx>
68 #include <sfx2/docfilt.hxx>
69 #include <svtools/imapobj.hxx>
70 #include <sfx2/docfile.hxx>
71 #include <unotools/transliterationwrapper.hxx>
72 #include <unotools/streamwrap.hxx>
73 #include <vcl/graphicfilter.hxx>
75 #include <svx/unomodel.hxx>
76 #include <fmturl.hxx>
77 #include <fmtinfmt.hxx>
78 #include <fmtfsize.hxx>
79 #include <swdtflvr.hxx>
80 #include <shellio.hxx>
81 #include <ddefld.hxx>
82 #include <doc.hxx>
83 #include <IDocumentUndoRedo.hxx>
84 #include <IDocumentSettingAccess.hxx>
85 #include <IDocumentDeviceAccess.hxx>
86 #include <IDocumentDrawModelAccess.hxx>
87 #include <IDocumentFieldsAccess.hxx>
88 #include <IDocumentState.hxx>
89 #include <pagedesc.hxx>
90 #include <IMark.hxx>
91 #include <docary.hxx>
92 #include <section.hxx>
93 #include <ndtxt.hxx>
94 #include <edtdd.hxx>
95 #include <edtwin.hxx>
96 #include <navicont.hxx>
97 #include <swcont.hxx>
98 #include <wrtsh.hxx>
99 #include <swmodule.hxx>
100 #include <view.hxx>
101 #include <docsh.hxx>
102 #include <wdocsh.hxx>
103 #include <fldbas.hxx>
104 #include <swundo.hxx>
105 #include <pam.hxx>
106 #include <ndole.hxx>
107 #include <swwait.hxx>
108 #include <viewopt.hxx>
109 #include <swerror.h>
110 #include <SwCapObjType.hxx>
111 #include <cmdid.h>
112 #include <strings.hrc>
113 #include <sot/stg.hxx>
114 #include <svx/svditer.hxx>
115 #include <editeng/eeitem.hxx>
116 #include <editeng/fhgtitem.hxx>
117 #include <svx/svdpage.hxx>
118 #include <avmedia/mediawindow.hxx>
119 #include <swcrsr.hxx>
120 #include <SwRewriter.hxx>
121 #include <globals.hrc>
122 #include <app.hrc>
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 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_DRAWMODEL = 0x00000001;
139 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_HTML = 0x00000002;
140 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_RTF = 0x00000004;
141 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_STRING = 0x00000008;
142 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_SWOLE = 0x00000010;
143 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_DDE = 0x00000020;
144 constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_RICHTEXT = 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() COVERITY_NOEXCEPT_FALSE
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 m_eBufferType = TransferBufferType::NONE;
272 static SwDoc * lcl_GetDoc(SwDocFac & rDocFac)
274 SwDoc *const pDoc = rDocFac.GetDoc();
275 OSL_ENSURE( pDoc, "Document not found" );
276 if (pDoc)
278 pDoc->SetClipBoard( true );
280 return pDoc;
283 void SwTransferable::ObjectReleased()
285 SwModule *pMod = SW_MOD();
286 if( this == pMod->m_pDragDrop )
287 pMod->m_pDragDrop = nullptr;
288 else if( this == pMod->m_pXSelection )
289 pMod->m_pXSelection = nullptr;
292 void SwTransferable::AddSupportedFormats()
294 // only need if we are the current XSelection Object
295 SwModule *pMod = SW_MOD();
296 if( this == pMod->m_pXSelection || comphelper::LibreOfficeKit::isActive())
298 SetDataForDragAndDrop( Point( 0,0) );
302 void SwTransferable::InitOle( SfxObjectShell* pDoc )
304 //set OleVisArea. Upper left corner of the page and size of
305 //RealSize in Twips.
306 const Size aSz( OLESIZE );
307 SwRect aVis( Point( DOCUMENTBORDER, DOCUMENTBORDER ), aSz );
308 pDoc->SetVisArea( aVis.SVRect() );
311 uno::Reference < embed::XEmbeddedObject > SwTransferable::FindOLEObj( sal_Int64& nAspect ) const
313 uno::Reference < embed::XEmbeddedObject > xObj;
314 if( m_pClpDocFac )
316 SwIterator<SwContentNode,SwFormatColl> aIter( *m_pClpDocFac->GetDoc()->GetDfltGrfFormatColl() );
317 for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
318 if( SwNodeType::Ole == pNd->GetNodeType() )
320 xObj = static_cast<SwOLENode*>(pNd)->GetOLEObj().GetOleRef();
321 nAspect = static_cast<SwOLENode*>(pNd)->GetAspect();
322 break;
325 return xObj;
328 const Graphic* SwTransferable::FindOLEReplacementGraphic() const
330 if( m_pClpDocFac )
332 SwIterator<SwContentNode,SwFormatColl> aIter( *m_pClpDocFac->GetDoc()->GetDfltGrfFormatColl() );
333 for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
334 if( SwNodeType::Ole == pNd->GetNodeType() )
336 return static_cast<SwOLENode*>(pNd)->GetGraphic();
340 return nullptr;
343 void SwTransferable::RemoveDDELinkFormat( const vcl::Window& rWin )
345 RemoveFormat( SotClipboardFormatId::LINK );
346 CopyToClipboard( const_cast<vcl::Window*>(&rWin) );
349 namespace
351 //Resolves: fdo#40717 surely when we create a clipboard document we should
352 //overwrite the clipboard documents styles and settings with that of the
353 //source, so that we can WYSIWYG paste. If we want that the destinations
354 //styles are used over the source styles, that's a matter of the
355 //destination paste code to handle, not the source paste code.
356 void lclOverWriteDoc(SwWrtShell &rSrcWrtShell, SwDoc &rDest)
358 const SwDoc &rSrc = *rSrcWrtShell.GetDoc();
360 rDest.ReplaceCompatibilityOptions(rSrc);
361 rDest.ReplaceDefaults(rSrc);
363 //It would probably make most sense here to only insert the styles used
364 //by the selection, e.g. apply SwDoc::IsUsed on styles ?
365 rDest.ReplaceStyles(rSrc, false);
367 rSrcWrtShell.Copy(&rDest);
369 rDest.GetMetaFieldManager().copyDocumentProperties(rSrc);
372 void lclCheckAndPerformRotation(Graphic& aGraphic)
374 GraphicNativeMetadata aMetadata;
375 if ( aMetadata.read(aGraphic) )
377 sal_uInt16 aRotation = aMetadata.getRotation();
378 if (aRotation != 0)
380 ScopedVclPtrInstance< MessageDialog > aQueryBox(
381 nullptr, "QueryRotateIntoStandardOrientationDialog",
382 "modules/swriter/ui/queryrotateintostandarddialog.ui");
383 if (aQueryBox->Execute() == RET_YES)
385 GraphicNativeTransform aTransform( aGraphic );
386 aTransform.rotate( aRotation );
393 bool SwTransferable::GetData( const DataFlavor& rFlavor, const OUString& rDestDoc )
395 SotClipboardFormatId nFormat = SotExchange::GetFormat( rFlavor );
397 // we can only fulfil the request if
398 // 1) we have data for this format
399 // 2) we have either a clipboard document (pClpDocFac), or
400 // we have a SwWrtShell (so we can generate a new clipboard document)
401 if( !HasFormat( nFormat ) || ( m_pClpDocFac == nullptr && m_pWrtShell == nullptr ) )
402 return false;
404 if( !m_pClpDocFac )
406 SelectionType nSelectionType = m_pWrtShell->GetSelectionType();
408 // when pending we will not get the correct type, but SelectionType::Text
409 // as fallback. This *happens* during D&D, so we need to check if we are in
410 // the fallback and just try to get a graphic
411 const bool bPending(m_pWrtShell->ActionPend());
413 // SEL_GRF is from ContentType of editsh
414 if(bPending || ((SelectionType::Graphic | SelectionType::DbForm) & nSelectionType))
416 m_pClpGraphic.reset(new Graphic);
417 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_pClpGraphic ))
418 m_pOrigGraphic = m_pClpGraphic.get();
419 m_pClpBitmap.reset(new Graphic);
420 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_pClpBitmap ))
421 m_pOrigGraphic = m_pClpBitmap.get();
423 // is it an URL-Button ?
424 OUString sURL;
425 OUString sDesc;
426 if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) )
428 m_pBookmark.reset(new INetBookmark( sURL, sDesc ));
429 m_eBufferType = TransferBufferType::InetField;
433 m_pClpDocFac = new SwDocFac;
434 SwDoc *const pTmpDoc = lcl_GetDoc(*m_pClpDocFac);
436 pTmpDoc->getIDocumentFieldsAccess().LockExpFields(); // never update fields - leave text as it is
437 lclOverWriteDoc(*m_pWrtShell, *pTmpDoc);
439 // in CORE a new one was created (OLE-objects copied!)
440 m_aDocShellRef = pTmpDoc->GetTmpDocShell();
441 if( m_aDocShellRef.Is() )
442 SwTransferable::InitOle( m_aDocShellRef );
443 pTmpDoc->SetTmpDocShell( nullptr );
445 if( nSelectionType & SelectionType::Text && !m_pWrtShell->HasMark() )
447 SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
449 Point aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY());
451 bool bSelect = g_bExecuteDrag &&
452 m_pWrtShell->GetView().GetDocShell() &&
453 !m_pWrtShell->GetView().GetDocShell()->IsReadOnly();
454 if( m_pWrtShell->GetContentAtPos( aPos, aContentAtPos, bSelect ) )
456 m_pBookmark.reset(new INetBookmark(
457 static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)->GetValue(),
458 aContentAtPos.sStr ));
459 m_eBufferType = TransferBufferType::InetField;
460 if( bSelect )
461 m_pWrtShell->SelectTextAttr( RES_TXTATR_INETFMT );
464 if( m_pWrtShell->IsFrameSelected() )
466 SfxItemSet aSet( m_pWrtShell->GetAttrPool(), svl::Items<RES_URL, RES_URL>{} );
467 m_pWrtShell->GetFlyFrameAttr( aSet );
468 const SwFormatURL& rURL = aSet.Get( RES_URL );
469 if( rURL.GetMap() )
470 m_pImageMap.reset(new ImageMap( *rURL.GetMap() ));
471 else if( !rURL.GetURL().isEmpty() )
472 m_pTargetURL.reset(new INetImage( aEmptyOUStr, rURL.GetURL(),
473 rURL.GetTargetFrameName() ));
477 bool bOK = false;
478 if( TransferBufferType::Ole == m_eBufferType )
480 //TODO/MBA: testing - is this the "single OLE object" case?!
481 // get OLE-Object from ClipDoc and get the data from that.
482 sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT; // will be set in the next statement
483 uno::Reference < embed::XEmbeddedObject > xObj = FindOLEObj( nAspect );
484 const Graphic* pOLEGraph = FindOLEReplacementGraphic();
485 if( xObj.is() )
487 TransferableDataHelper aD( new SvEmbedTransferHelper( xObj, pOLEGraph, nAspect ) );
488 uno::Any aAny = aD.GetAny(rFlavor, rDestDoc);
489 if( aAny.hasValue() )
490 bOK = SetAny( aAny );
493 // the following solution will be used in the case when the object can not generate the image
494 // TODO/LATER: in future the transferhelper must probably be created based on object and the replacement stream
495 // TODO: Block not required now, SvEmbedTransferHelper should be able to handle GDIMetaFile format
496 if ( nFormat == SotClipboardFormatId::GDIMETAFILE )
498 pOLEGraph = FindOLEReplacementGraphic();
499 if ( pOLEGraph )
500 bOK = SetGDIMetaFile( pOLEGraph->GetGDIMetaFile() );
503 else
505 switch( nFormat )
507 case SotClipboardFormatId::LINK:
508 if( m_xDdeLink.is() )
509 bOK = SetObject( m_xDdeLink.get(), SWTRANSFER_OBJECTTYPE_DDE, rFlavor );
510 break;
512 case SotClipboardFormatId::OBJECTDESCRIPTOR:
513 case SotClipboardFormatId::LINKSRCDESCRIPTOR:
514 bOK = SetTransferableObjectDescriptor( m_aObjDesc );
515 break;
517 case SotClipboardFormatId::DRAWING:
519 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
520 bOK = SetObject( pDoc->getIDocumentDrawModelAccess().GetDrawModel(),
521 SWTRANSFER_OBJECTTYPE_DRAWMODEL, rFlavor );
523 break;
525 case SotClipboardFormatId::STRING:
527 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
528 bOK = SetObject( pDoc, SWTRANSFER_OBJECTTYPE_STRING, rFlavor );
530 break;
531 case SotClipboardFormatId::RTF:
533 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
534 bOK = SetObject( pDoc, SWTRANSFER_OBJECTTYPE_RTF, rFlavor );
536 break;
537 case SotClipboardFormatId::RICHTEXT:
539 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
540 bOK = SetObject( pDoc, SWTRANSFER_OBJECTTYPE_RICHTEXT, rFlavor );
542 break;
544 case SotClipboardFormatId::HTML:
546 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
547 bOK = SetObject( pDoc, SWTRANSFER_OBJECTTYPE_HTML, rFlavor );
549 break;
551 case SotClipboardFormatId::SVXB:
552 if( m_eBufferType & TransferBufferType::Graphic && m_pOrigGraphic )
553 bOK = SetGraphic( *m_pOrigGraphic );
554 break;
556 case SotClipboardFormatId::GDIMETAFILE:
557 if( m_eBufferType & TransferBufferType::Graphic )
558 bOK = SetGDIMetaFile( m_pClpGraphic->GetGDIMetaFile() );
559 break;
560 case SotClipboardFormatId::BITMAP:
561 case SotClipboardFormatId::PNG:
562 // Neither pClpBitmap nor pClpGraphic are necessarily set
563 if( (m_eBufferType & TransferBufferType::Graphic) && (m_pClpBitmap != nullptr || m_pClpGraphic != nullptr))
564 bOK = SetBitmapEx( (m_pClpBitmap ? m_pClpBitmap : m_pClpGraphic)->GetBitmapEx(), rFlavor );
565 break;
567 case SotClipboardFormatId::SVIM:
568 if( m_pImageMap )
569 bOK = SetImageMap( *m_pImageMap );
570 break;
572 case SotClipboardFormatId::INET_IMAGE:
573 if( m_pTargetURL )
574 bOK = SetINetImage( *m_pTargetURL, rFlavor );
575 break;
577 case SotClipboardFormatId::SOLK:
578 case SotClipboardFormatId::NETSCAPE_BOOKMARK:
579 case SotClipboardFormatId::FILEGRPDESCRIPTOR:
580 case SotClipboardFormatId::FILECONTENT:
581 case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
582 case SotClipboardFormatId::SIMPLE_FILE:
583 if( (TransferBufferType::InetField & m_eBufferType) && m_pBookmark )
584 bOK = SetINetBookmark( *m_pBookmark, rFlavor );
585 break;
587 case SotClipboardFormatId::EMBED_SOURCE:
588 if( !m_aDocShellRef.Is() )
590 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
591 SwDocShell* pNewDocSh = new SwDocShell( pDoc,
592 SfxObjectCreateMode::EMBEDDED );
593 m_aDocShellRef = pNewDocSh;
594 m_aDocShellRef->DoInitNew();
595 SwTransferable::InitOle( m_aDocShellRef );
597 bOK = SetObject( &m_aDocShellRef, SWTRANSFER_OBJECTTYPE_SWOLE,
598 rFlavor );
599 break;
600 default: break;
603 return bOK;
606 bool SwTransferable::WriteObject( tools::SvRef<SotStorageStream>& xStream,
607 void* pObject, sal_uInt32 nObjectType,
608 const DataFlavor& /*rFlavor*/ )
610 bool bRet = false;
611 WriterRef xWrt;
613 switch( nObjectType )
615 case SWTRANSFER_OBJECTTYPE_DRAWMODEL:
617 // don't change the sequence of commands
618 SdrModel *pModel = static_cast<SdrModel*>(pObject);
619 xStream->SetBufferSize( 16348 );
621 // for the changed pool defaults from drawing layer pool set those
622 // attributes as hard attributes to preserve them for saving
623 const SfxItemPool& rItemPool = pModel->GetItemPool();
624 const SvxFontHeightItem& rDefaultFontHeight = rItemPool.GetDefaultItem(EE_CHAR_FONTHEIGHT);
626 // SW should have no MasterPages
627 OSL_ENSURE(0 == pModel->GetMasterPageCount(), "SW with MasterPages (!)");
629 for(sal_uInt16 a(0); a < pModel->GetPageCount(); a++)
631 const SdrPage* pPage = pModel->GetPage(a);
632 SdrObjListIter aIter(*pPage, SdrIterMode::DeepNoGroups);
634 while(aIter.IsMore())
636 SdrObject* pObj = aIter.Next();
637 const SvxFontHeightItem& rItem = pObj->GetMergedItem(EE_CHAR_FONTHEIGHT);
639 if(rItem.GetHeight() == rDefaultFontHeight.GetHeight())
641 pObj->SetMergedItem(rDefaultFontHeight);
647 uno::Reference<io::XOutputStream> xDocOut( new utl::OOutputStreamWrapper( *xStream ) );
648 if( SvxDrawingLayerExport( pModel, xDocOut ) )
649 xStream->Commit();
652 bRet = ERRCODE_NONE == xStream->GetError();
654 break;
656 case SWTRANSFER_OBJECTTYPE_SWOLE:
658 SfxObjectShell* pEmbObj = static_cast<SfxObjectShell*>(pObject);
661 ::utl::TempFile aTempFile;
662 aTempFile.EnableKillingFile();
663 uno::Reference< embed::XStorage > xWorkStore =
664 ::comphelper::OStorageHelper::GetStorageFromURL( aTempFile.GetURL(), embed::ElementModes::READWRITE );
666 // write document storage
667 pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, false );
668 // mba: no BaseURL for clipboard
669 SfxMedium aMedium( xWorkStore, OUString() );
670 pEmbObj->DoSaveObjectAs( aMedium, false );
671 pEmbObj->DoSaveCompleted();
673 uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY );
674 if ( xTransact.is() )
675 xTransact->commit();
677 std::unique_ptr<SvStream> pSrcStm(::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), StreamMode::READ ));
678 if( pSrcStm )
680 xStream->SetBufferSize( 0xff00 );
681 xStream->WriteStream( *pSrcStm );
682 pSrcStm.reset();
685 xWorkStore->dispose();
686 xWorkStore.clear();
687 xStream->Commit();
689 catch (const uno::Exception&)
693 bRet = ( xStream->GetError() == ERRCODE_NONE );
695 break;
697 case SWTRANSFER_OBJECTTYPE_DDE:
699 xStream->SetBufferSize( 1024 );
700 SwTrnsfrDdeLink* pDdeLnk = static_cast<SwTrnsfrDdeLink*>(pObject);
701 if( pDdeLnk->WriteData( *xStream ) )
703 xStream->Commit();
704 bRet = ERRCODE_NONE == xStream->GetError();
707 break;
709 case SWTRANSFER_OBJECTTYPE_HTML:
710 GetHTMLWriter( aEmptyOUStr, OUString(), xWrt );
711 break;
713 case SWTRANSFER_OBJECTTYPE_RTF:
714 case SWTRANSFER_OBJECTTYPE_RICHTEXT:
715 GetRTFWriter( aEmptyOUStr, OUString(), xWrt );
716 break;
718 case SWTRANSFER_OBJECTTYPE_STRING:
719 GetASCWriter( aEmptyOUStr, OUString(), xWrt );
720 if( xWrt.is() )
722 SwAsciiOptions aAOpt;
723 aAOpt.SetCharSet( RTL_TEXTENCODING_UTF8 );
724 xWrt->SetAsciiOptions( aAOpt );
726 // no start char for clipboard
727 xWrt->bUCS2_WithStartChar = false;
729 break;
730 default: break;
733 if( xWrt.is() )
735 SwDoc* pDoc = static_cast<SwDoc*>(pObject);
736 xWrt->bWriteClipboardDoc = true;
737 xWrt->bWriteOnlyFirstTable = bool(TransferBufferType::Table & m_eBufferType);
738 xWrt->SetShowProgress(false);
740 #if defined(DEBUGPASTE)
741 SvFileStream aPasteDebug(OUString(
742 "PASTEBUFFER.debug"), StreamMode::WRITE|StreamMode::TRUNC);
743 SwWriter aDbgWrt( aPasteDebug, *pDoc );
744 aDbgWrt.Write( xWrt );
745 #endif
747 SwWriter aWrt( *xStream, *pDoc );
748 if( ! aWrt.Write( xWrt ).IsError() )
750 xStream->WriteChar( '\0' ); // terminate with a zero
751 xStream->Commit();
752 bRet = true;
756 return bRet;
759 int SwTransferable::Cut()
761 int nRet = Copy( true );
762 if( nRet )
763 DeleteSelection();
764 return nRet;
767 void SwTransferable::DeleteSelection()
769 if(!m_pWrtShell)
770 return;
771 // ask for type of selection before action-bracketing
772 const SelectionType nSelection = m_pWrtShell->GetSelectionType();
773 m_pWrtShell->StartUndo( SwUndoId::START );
774 if( ( SelectionType::Text | SelectionType::Table ) & nSelection )
775 m_pWrtShell->IntelligentCut( nSelection );
776 m_pWrtShell->DelRight();
777 m_pWrtShell->EndUndo( SwUndoId::END );
780 int SwTransferable::PrepareForCopy( bool bIsCut )
782 int nRet = 1;
783 if(!m_pWrtShell)
784 return 0;
786 OUString sGrfNm;
787 const SelectionType nSelection = m_pWrtShell->GetSelectionType();
788 if( nSelection == SelectionType::Graphic )
790 m_pClpGraphic.reset(new Graphic);
791 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_pClpGraphic ))
792 m_pOrigGraphic = m_pClpGraphic.get();
793 m_pClpBitmap.reset(new Graphic);
794 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_pClpBitmap ))
795 m_pOrigGraphic = m_pClpBitmap.get();
797 m_pClpDocFac = new SwDocFac;
798 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
799 m_pWrtShell->Copy( pDoc );
801 if (m_pOrigGraphic && !m_pOrigGraphic->GetBitmap().IsEmpty())
802 AddFormat( SotClipboardFormatId::SVXB );
804 PrepareOLE( m_aObjDesc );
805 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
807 const Graphic* pGrf = m_pWrtShell->GetGraphic();
808 if( pGrf && pGrf->IsSupportedGraphic() )
810 AddFormat( SotClipboardFormatId::GDIMETAFILE );
811 AddFormat( SotClipboardFormatId::PNG );
812 AddFormat( SotClipboardFormatId::BITMAP );
814 m_eBufferType = TransferBufferType::Graphic;
815 m_pWrtShell->GetGrfNms( &sGrfNm, nullptr );
817 else if ( nSelection == SelectionType::Ole )
819 m_pClpDocFac = new SwDocFac;
820 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
821 m_aDocShellRef = new SwDocShell( pDoc, SfxObjectCreateMode::EMBEDDED);
822 m_aDocShellRef->DoInitNew();
823 m_pWrtShell->Copy( pDoc );
825 AddFormat( SotClipboardFormatId::EMBED_SOURCE );
827 // --> OD #i98753#
828 // set size of embedded object at the object description structure
829 m_aObjDesc.maSize = OutputDevice::LogicToLogic(m_pWrtShell->GetObjSize(), MapMode(MapUnit::MapTwip), MapMode(MapUnit::Map100thMM));
830 // <--
831 PrepareOLE( m_aObjDesc );
832 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
834 AddFormat( SotClipboardFormatId::GDIMETAFILE );
836 // Fetch the formats supported via embedtransferhelper as well
837 sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
838 uno::Reference < embed::XEmbeddedObject > xObj = FindOLEObj( nAspect );
839 const Graphic* pOLEGraph = FindOLEReplacementGraphic();
840 if( xObj.is() )
842 TransferableDataHelper aD( new SvEmbedTransferHelper( xObj, pOLEGraph, nAspect ) );
843 if ( aD.GetTransferable().is() )
845 DataFlavorExVector aVector( aD.GetDataFlavorExVector() );
846 DataFlavorExVector::iterator aIter( aVector.begin() ), aEnd( aVector.end() );
848 while( aIter != aEnd )
849 AddFormat( *aIter++ );
852 m_eBufferType = TransferBufferType::Ole;
854 // Is there anything to provide anyway?
855 else if ( m_pWrtShell->IsSelection() || m_pWrtShell->IsFrameSelected() ||
856 m_pWrtShell->IsObjSelected() )
858 std::unique_ptr<SwWait> pWait;
859 if( m_pWrtShell->ShouldWait() )
860 pWait.reset(new SwWait( *m_pWrtShell->GetView().GetDocShell(), true ));
862 m_pClpDocFac = new SwDocFac;
864 // create additional cursor so that equal treatment of keyboard
865 // and mouse selection is possible.
866 // In AddMode with keyboard selection, the new cursor is not created
867 // before the cursor is moved after end of selection.
868 if( m_pWrtShell->IsAddMode() && m_pWrtShell->SwCursorShell::HasSelection() )
869 m_pWrtShell->CreateCursor();
871 SwDoc *const pTmpDoc = lcl_GetDoc(*m_pClpDocFac);
873 pTmpDoc->getIDocumentFieldsAccess().LockExpFields(); // Never update fields - leave text as is
874 lclOverWriteDoc(*m_pWrtShell, *pTmpDoc);
877 IDocumentMarkAccess* const pMarkAccess = pTmpDoc->getIDocumentMarkAccess();
878 std::vector< ::sw::mark::IMark* > vDdeMarks;
879 // find all DDE-Bookmarks
880 for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getAllMarksBegin();
881 ppMark != pMarkAccess->getAllMarksEnd();
882 ++ppMark)
884 if(IDocumentMarkAccess::MarkType::DDE_BOOKMARK == IDocumentMarkAccess::GetType(**ppMark))
885 vDdeMarks.push_back(ppMark->get());
887 // remove all DDE-Bookmarks, they are invalid inside the clipdoc!
888 for(std::vector< ::sw::mark::IMark* >::iterator ppMark = vDdeMarks.begin();
889 ppMark != vDdeMarks.end();
890 ++ppMark)
891 pMarkAccess->deleteMark(*ppMark);
894 // a new one was created in CORE (OLE objects copied!)
895 m_aDocShellRef = pTmpDoc->GetTmpDocShell();
896 if( m_aDocShellRef.Is() )
897 SwTransferable::InitOle( m_aDocShellRef );
898 pTmpDoc->SetTmpDocShell( nullptr );
900 if( m_pWrtShell->IsObjSelected() )
901 m_eBufferType = TransferBufferType::Drawing;
902 else
904 m_eBufferType = TransferBufferType::Document;
905 if (m_pWrtShell->IntelligentCut(nSelection, false) != SwWrtShell::NO_WORD)
906 m_eBufferType = TransferBufferType::DocumentWord | m_eBufferType;
909 bool bDDELink = m_pWrtShell->IsSelection();
910 if( nSelection & SelectionType::TableCell )
912 m_eBufferType = TransferBufferType::Table | m_eBufferType;
913 bDDELink = m_pWrtShell->HasWholeTabSelection();
916 //When someone needs it, we 'OLE' him something
917 AddFormat( SotClipboardFormatId::EMBED_SOURCE );
919 //put RTF ahead of the OLE's Metafile to have less loss
920 if( !m_pWrtShell->IsObjSelected() )
922 AddFormat( SotClipboardFormatId::RTF );
923 AddFormat( SotClipboardFormatId::RICHTEXT );
924 AddFormat( SotClipboardFormatId::HTML );
926 if( m_pWrtShell->IsSelection() )
927 AddFormat( SotClipboardFormatId::STRING );
929 if( nSelection & ( SelectionType::DrawObject | SelectionType::DbForm ))
931 AddFormat( SotClipboardFormatId::DRAWING );
932 if ( nSelection & SelectionType::DrawObject )
934 AddFormat( SotClipboardFormatId::GDIMETAFILE );
935 AddFormat( SotClipboardFormatId::PNG );
936 AddFormat( SotClipboardFormatId::BITMAP );
938 m_eBufferType = static_cast<TransferBufferType>( TransferBufferType::Graphic | m_eBufferType );
940 m_pClpGraphic.reset(new Graphic);
941 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_pClpGraphic ))
942 m_pOrigGraphic = m_pClpGraphic.get();
943 m_pClpBitmap.reset(new Graphic);
944 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_pClpBitmap ))
945 m_pOrigGraphic = m_pClpBitmap.get();
947 // is it an URL-Button ?
948 OUString sURL;
949 OUString sDesc;
950 if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) )
952 AddFormat( SotClipboardFormatId::STRING );
953 AddFormat( SotClipboardFormatId::SOLK );
954 AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
955 AddFormat( SotClipboardFormatId::FILECONTENT );
956 AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
957 AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
958 m_eBufferType = TransferBufferType::InetField | m_eBufferType;
959 nRet = 1;
963 // at Cut, DDE-Link doesn't make sense!!
964 SwDocShell* pDShell;
965 if( !bIsCut && bDDELink &&
966 nullptr != ( pDShell = m_pWrtShell->GetDoc()->GetDocShell()) &&
967 SfxObjectCreateMode::STANDARD == pDShell->GetCreateMode() )
969 AddFormat( SotClipboardFormatId::LINK );
970 m_xDdeLink = new SwTrnsfrDdeLink( *this, *m_pWrtShell );
973 //ObjectDescriptor was already filly from the old DocShell.
974 //Now adjust it. Thus in GetData the first query can still
975 //be answered with delayed rendering.
976 Size aSz( OLESIZE );
977 m_aObjDesc.maSize = OutputDevice::LogicToLogic(aSz, MapMode(MapUnit::MapTwip), MapMode(MapUnit::Map100thMM));
979 PrepareOLE( m_aObjDesc );
980 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
982 else
983 nRet = 0;
985 if( m_pWrtShell->IsFrameSelected() )
987 SfxItemSet aSet( m_pWrtShell->GetAttrPool(), svl::Items<RES_URL, RES_URL>{} );
988 m_pWrtShell->GetFlyFrameAttr( aSet );
989 const SwFormatURL& rURL = aSet.Get( RES_URL );
990 if( rURL.GetMap() )
992 m_pImageMap.reset( new ImageMap( *rURL.GetMap() ) );
993 AddFormat( SotClipboardFormatId::SVIM );
995 else if( !rURL.GetURL().isEmpty() )
997 m_pTargetURL.reset(new INetImage( sGrfNm, rURL.GetURL(),
998 rURL.GetTargetFrameName() ));
999 AddFormat( SotClipboardFormatId::INET_IMAGE );
1003 return nRet;
1006 int SwTransferable::Copy( bool bIsCut )
1008 int nRet = PrepareForCopy( bIsCut );
1009 if ( nRet )
1011 CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
1013 return nRet;
1016 void SwTransferable::CalculateAndCopy()
1018 if(!m_pWrtShell)
1019 return;
1020 SwWait aWait( *m_pWrtShell->GetView().GetDocShell(), true );
1022 OUString aStr( m_pWrtShell->Calculate() );
1024 m_pClpDocFac = new SwDocFac;
1025 SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac);
1026 m_pWrtShell->Copy(pDoc, & aStr);
1027 m_eBufferType = TransferBufferType::Document;
1028 AddFormat( SotClipboardFormatId::STRING );
1030 CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
1033 int SwTransferable::CopyGlossary( SwTextBlocks& rGlossary, const OUString& rStr )
1035 if(!m_pWrtShell)
1036 return 0;
1037 SwWait aWait( *m_pWrtShell->GetView().GetDocShell(), true );
1039 m_pClpDocFac = new SwDocFac;
1040 SwDoc *const pCDoc = lcl_GetDoc(*m_pClpDocFac);
1042 SwNodes& rNds = pCDoc->GetNodes();
1043 SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
1044 SwContentNode* pCNd = rNds.GoNext( &aNodeIdx ); // go to 1st ContentNode
1045 SwPaM aPam( *pCNd );
1047 pCDoc->getIDocumentFieldsAccess().LockExpFields(); // never update fields - leave text as it is
1049 pCDoc->InsertGlossary( rGlossary, rStr, aPam );
1051 // a new one was created in CORE (OLE-Objects copied!)
1052 m_aDocShellRef = pCDoc->GetTmpDocShell();
1053 if( m_aDocShellRef.Is() )
1054 SwTransferable::InitOle( m_aDocShellRef );
1055 pCDoc->SetTmpDocShell( nullptr );
1057 m_eBufferType = TransferBufferType::Document;
1059 //When someone needs it, we 'OLE' her something.
1060 AddFormat( SotClipboardFormatId::EMBED_SOURCE );
1061 AddFormat( SotClipboardFormatId::RTF );
1062 AddFormat( SotClipboardFormatId::RICHTEXT );
1063 AddFormat( SotClipboardFormatId::HTML );
1064 AddFormat( SotClipboardFormatId::STRING );
1066 //ObjectDescriptor was already filled from the old DocShell.
1067 //Now adjust it. Thus in GetData the first query can still
1068 //be answered with delayed rendering.
1069 Size aSz( OLESIZE );
1070 m_aObjDesc.maSize = OutputDevice::LogicToLogic(aSz, MapMode(MapUnit::MapTwip), MapMode(MapUnit::Map100thMM));
1072 PrepareOLE( m_aObjDesc );
1073 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
1075 CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
1077 return 1;
1080 static inline uno::Reference < XTransferable > * lcl_getTransferPointer ( uno::Reference < XTransferable > &xRef )
1082 return &xRef;
1085 bool SwTransferable::IsPaste( const SwWrtShell& rSh,
1086 const TransferableDataHelper& rData )
1088 // Check the common case first: We can always paste our own data!
1089 // If _only_ the internal format can be pasted, this check will
1090 // yield 'true', while the one below would give a (wrong) result 'false'.
1092 bool bIsPaste = ( GetSwTransferable( rData ) != nullptr );
1094 // if it's not our own data, we need to have a closer look:
1095 if( ! bIsPaste )
1097 // determine the proper paste action, and return true if we find one
1098 uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
1100 SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
1101 sal_uInt16 nSourceOptions =
1102 (( SotExchangeDest::DOC_TEXTFRAME == nDestination ||
1103 SotExchangeDest::SWDOC_FREE_AREA == nDestination ||
1104 SotExchangeDest::DOC_TEXTFRAME_WEB == nDestination ||
1105 SotExchangeDest::SWDOC_FREE_AREA_WEB == nDestination )
1106 ? EXCHG_IN_ACTION_COPY
1107 : EXCHG_IN_ACTION_MOVE);
1109 SotClipboardFormatId nFormat; // output param for GetExchangeAction
1110 sal_uInt8 nEventAction; // output param for GetExchangeAction
1111 sal_uInt8 nAction = SotExchange::GetExchangeAction(
1112 rData.GetDataFlavorExVector(),
1113 nDestination,
1114 nSourceOptions, /* ?? */
1115 EXCHG_IN_ACTION_DEFAULT, /* ?? */
1116 nFormat, nEventAction, SotClipboardFormatId::NONE,
1117 lcl_getTransferPointer ( xTransferable ) );
1119 // if we find a suitable action, we can paste!
1120 bIsPaste = (EXCHG_INOUT_ACTION_NONE != nAction);
1123 return bIsPaste;
1126 bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndStdIds nAnchorType)
1128 sal_uInt8 nEventAction, nAction=0;
1129 SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
1130 SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
1131 SotExchangeActionFlags nActionFlags = SotExchangeActionFlags::NONE;
1133 if( GetSwTransferable( rData ) )
1135 nAction = EXCHG_OUT_ACTION_INSERT_PRIVATE;
1137 else
1139 sal_uInt16 nSourceOptions =
1140 (( SotExchangeDest::DOC_TEXTFRAME == nDestination ||
1141 SotExchangeDest::SWDOC_FREE_AREA == nDestination ||
1142 SotExchangeDest::DOC_TEXTFRAME_WEB == nDestination ||
1143 SotExchangeDest::SWDOC_FREE_AREA_WEB == nDestination )
1144 ? EXCHG_IN_ACTION_COPY
1145 : EXCHG_IN_ACTION_MOVE);
1146 uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
1147 nAction = SotExchange::GetExchangeAction(
1148 rData.GetDataFlavorExVector(),
1149 nDestination,
1150 nSourceOptions, /* ?? */
1151 EXCHG_IN_ACTION_DEFAULT, /* ?? */
1152 nFormat, nEventAction, SotClipboardFormatId::NONE,
1153 lcl_getTransferPointer ( xTransferable ),
1154 &nActionFlags );
1157 // special case for tables from draw application
1158 if( EXCHG_OUT_ACTION_INSERT_DRAWOBJ == nAction )
1160 if( rData.HasFormat( SotClipboardFormatId::RTF ) )
1162 nAction = EXCHG_OUT_ACTION_INSERT_STRING;
1163 nFormat = SotClipboardFormatId::RTF;
1165 else if( rData.HasFormat( SotClipboardFormatId::RICHTEXT ) )
1167 nAction = EXCHG_OUT_ACTION_INSERT_STRING;
1168 nFormat = SotClipboardFormatId::RICHTEXT;
1172 return EXCHG_INOUT_ACTION_NONE != nAction &&
1173 SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
1174 nDestination, false, false, nullptr, 0, false, nAnchorType );
1177 bool SwTransferable::PasteData( TransferableDataHelper& rData,
1178 SwWrtShell& rSh, sal_uInt8 nAction, SotExchangeActionFlags nActionFlags,
1179 SotClipboardFormatId nFormat,
1180 SotExchangeDest nDestination, bool bIsPasteFormat,
1181 bool bIsDefault,
1182 const Point* pPt, sal_Int8 nDropAction,
1183 bool bPasteSelection, RndStdIds nAnchorType )
1185 SwWait aWait( *rSh.GetView().GetDocShell(), false );
1186 std::unique_ptr<SwTrnsfrActionAndUndo, o3tl::default_delete<SwTrnsfrActionAndUndo>> pAction;
1187 SwModule* pMod = SW_MOD();
1189 bool bRet = false;
1190 bool bCallAutoCaption = false;
1192 if( pPt )
1194 // external Drop
1195 if( bPasteSelection ? !pMod->m_pXSelection : !pMod->m_pDragDrop )
1197 switch( nDestination )
1199 case SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP:
1200 case SotExchangeDest::DOC_LNKD_GRAPHOBJ:
1201 case SotExchangeDest::DOC_GRAPH_W_IMAP:
1202 case SotExchangeDest::DOC_GRAPHOBJ:
1203 case SotExchangeDest::DOC_OLEOBJ:
1204 case SotExchangeDest::DOC_DRAWOBJ:
1205 case SotExchangeDest::DOC_URLBUTTON:
1206 case SotExchangeDest::DOC_GROUPOBJ:
1207 // select frames/objects
1208 SwTransferable::SetSelInShell( rSh, true, pPt );
1209 break;
1211 default:
1212 SwTransferable::SetSelInShell( rSh, false, pPt );
1213 break;
1217 else if( ( !GetSwTransferable( rData ) || bIsPasteFormat ) &&
1218 !rSh.IsTableMode() && rSh.HasSelection() )
1220 // then delete the selections
1222 //don't delete selected content
1223 // - at table-selection
1224 // - at ReRead of a graphic/DDEData
1225 // - at D&D, for the right selection was taken care of
1226 // in Drop-Handler
1227 bool bDelSel = false;
1228 switch( nDestination )
1230 case SotExchangeDest::DOC_TEXTFRAME:
1231 case SotExchangeDest::SWDOC_FREE_AREA:
1232 case SotExchangeDest::DOC_TEXTFRAME_WEB:
1233 case SotExchangeDest::SWDOC_FREE_AREA_WEB:
1234 bDelSel = true;
1235 break;
1236 default:
1237 break;
1240 if( bDelSel )
1241 // #i34830#
1242 pAction.reset(new SwTrnsfrActionAndUndo( &rSh, true ));
1245 SwTransferable *pTrans=nullptr, *pTunneledTrans=GetSwTransferable( rData );
1247 // check for private drop
1248 bool bPrivateDrop(pPt && (bPasteSelection ? nullptr != (pTrans = pMod->m_pXSelection) : nullptr != (pTrans = pMod->m_pDragDrop)));
1249 bool bNeedToSelectBeforePaste(false);
1251 if(bPrivateDrop && DND_ACTION_LINK == nDropAction)
1253 // internal drop on object, suppress bPrivateDrop to change internal fill
1254 bPrivateDrop = false;
1255 bNeedToSelectBeforePaste = true;
1258 if(bPrivateDrop && pPt && DND_ACTION_MOVE == nDropAction)
1260 // check if dragged over a useful target. If yes, use as content exchange
1261 // drop as if from external
1262 const SwFrameFormat* pSwFrameFormat = rSh.GetFormatFromObj(*pPt);
1264 if(pSwFrameFormat && dynamic_cast< const SwDrawFrameFormat* >(pSwFrameFormat) != nullptr)
1266 bPrivateDrop = false;
1267 bNeedToSelectBeforePaste = true;
1271 if(bPrivateDrop)
1273 // then internal Drag & Drop or XSelection
1274 bRet = pTrans->PrivateDrop( rSh, *pPt, DND_ACTION_MOVE == nDropAction,
1275 bPasteSelection );
1277 else if( !pPt && pTunneledTrans &&
1278 EXCHG_OUT_ACTION_INSERT_PRIVATE == nAction )
1280 // then internal paste
1281 bRet = pTunneledTrans->PrivatePaste( rSh );
1283 else if( EXCHG_INOUT_ACTION_NONE != nAction )
1285 if( !pAction )
1287 pAction.reset(new SwTrnsfrActionAndUndo( &rSh ));
1290 // in Drag&Drop MessageBoxes must not be showed
1291 bool bMsg = nullptr == pPt;
1293 // delete selections
1295 switch( nAction )
1297 case EXCHG_OUT_ACTION_INSERT_PRIVATE:
1298 OSL_ENSURE( pPt, "EXCHG_OUT_ACTION_INSERT_PRIVATE: what should happen here?" );
1299 break;
1301 case EXCHG_OUT_ACTION_MOVE_PRIVATE:
1302 OSL_ENSURE( pPt, "EXCHG_OUT_ACTION_MOVE_PRIVATE: what should happen here?" );
1303 break;
1305 case EXCHG_IN_ACTION_MOVE:
1306 case EXCHG_IN_ACTION_COPY:
1307 case EXCHG_IN_ACTION_LINK:
1308 case EXCHG_OUT_ACTION_INSERT_HTML:
1309 case EXCHG_OUT_ACTION_INSERT_STRING:
1310 case EXCHG_OUT_ACTION_INSERT_IMAGEMAP:
1311 case EXCHG_OUT_ACTION_REPLACE_IMAGEMAP:
1313 // then we have to use the format
1314 switch( nFormat )
1316 case SotClipboardFormatId::DRAWING:
1317 bRet = SwTransferable::PasteSdrFormat( rData, rSh,
1318 SwPasteSdr::Insert, pPt,
1319 nActionFlags, bNeedToSelectBeforePaste);
1320 break;
1322 case SotClipboardFormatId::HTML:
1323 case SotClipboardFormatId::HTML_SIMPLE:
1324 case SotClipboardFormatId::HTML_NO_COMMENT:
1325 case SotClipboardFormatId::RTF:
1326 case SotClipboardFormatId::RICHTEXT:
1327 case SotClipboardFormatId::STRING:
1328 bRet = SwTransferable::PasteFileContent( rData, rSh,
1329 nFormat, bMsg );
1330 break;
1332 case SotClipboardFormatId::NETSCAPE_BOOKMARK:
1334 INetBookmark aBkmk;
1335 if( rData.GetINetBookmark( nFormat, aBkmk ) )
1337 SwFormatINetFormat aFormat( aBkmk.GetURL(), OUString() );
1338 rSh.InsertURL( aFormat, aBkmk.GetDescription() );
1339 bRet = true;
1342 break;
1344 case SotClipboardFormatId::SD_OLE:
1345 bRet = SwTransferable::PasteOLE( rData, rSh, nFormat,
1346 nActionFlags, bMsg );
1347 break;
1349 case SotClipboardFormatId::SVIM:
1350 bRet = SwTransferable::PasteImageMap( rData, rSh );
1351 break;
1353 case SotClipboardFormatId::SVXB:
1354 case SotClipboardFormatId::BITMAP:
1355 case SotClipboardFormatId::PNG:
1356 case SotClipboardFormatId::GDIMETAFILE:
1357 bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
1358 SwPasteSdr::Insert,pPt,
1359 nActionFlags, nDropAction, bNeedToSelectBeforePaste);
1360 break;
1362 case SotClipboardFormatId::XFORMS:
1363 case SotClipboardFormatId::SBA_FIELDDATAEXCHANGE:
1364 case SotClipboardFormatId::SBA_DATAEXCHANGE:
1365 case SotClipboardFormatId::SBA_CTRLDATAEXCHANGE:
1366 bRet = SwTransferable::PasteDBData( rData, rSh, nFormat,
1367 EXCHG_IN_ACTION_LINK == nAction,
1368 pPt, bMsg );
1369 break;
1371 case SotClipboardFormatId::SIMPLE_FILE:
1372 bRet = SwTransferable::PasteFileName( rData, rSh, nFormat,
1373 ( EXCHG_IN_ACTION_MOVE == nAction
1374 ? SwPasteSdr::Replace
1375 : EXCHG_IN_ACTION_LINK == nAction
1376 ? SwPasteSdr::SetAttr
1377 : SwPasteSdr::Insert),
1378 pPt, nActionFlags, nullptr );
1379 break;
1381 case SotClipboardFormatId::FILE_LIST:
1382 // then insert as graphics only
1383 bRet = SwTransferable::PasteFileList( rData, rSh,
1384 EXCHG_IN_ACTION_LINK == nAction,
1385 pPt, bMsg );
1386 break;
1388 case SotClipboardFormatId::SONLK:
1389 if( pPt )
1391 NaviContentBookmark aBkmk;
1392 if( aBkmk.Paste( rData ) )
1394 if(bIsDefault)
1396 switch(aBkmk.GetDefaultDragType())
1398 case RegionMode::NONE: nAction = EXCHG_IN_ACTION_COPY; break;
1399 case RegionMode::EMBEDDED: nAction = EXCHG_IN_ACTION_MOVE; break;
1400 case RegionMode::LINK: nAction = EXCHG_IN_ACTION_LINK; break;
1403 rSh.NavigatorPaste( aBkmk, nAction );
1404 bRet = true;
1407 break;
1409 case SotClipboardFormatId::INET_IMAGE:
1410 case SotClipboardFormatId::NETSCAPE_IMAGE:
1411 bRet = SwTransferable::PasteTargetURL( rData, rSh,
1412 SwPasteSdr::Insert,
1413 pPt, true );
1414 break;
1416 default:
1417 OSL_ENSURE( pPt, "unknown format" );
1419 break;
1421 case EXCHG_OUT_ACTION_INSERT_FILE:
1423 bool graphicInserted;
1424 bRet = SwTransferable::PasteFileName( rData, rSh, nFormat,
1425 SwPasteSdr::Insert, pPt,
1426 nActionFlags,
1427 &graphicInserted );
1428 if( graphicInserted )
1429 bCallAutoCaption = true;
1431 break;
1433 case EXCHG_OUT_ACTION_INSERT_OLE:
1434 bRet = SwTransferable::PasteOLE( rData, rSh, nFormat,
1435 nActionFlags,bMsg );
1436 break;
1438 case EXCHG_OUT_ACTION_INSERT_DDE:
1440 bool bReRead = 0 != CNT_HasGrf( rSh.GetCntType() );
1441 bRet = SwTransferable::PasteDDE( rData, rSh, bReRead, bMsg );
1443 break;
1445 case EXCHG_OUT_ACTION_INSERT_HYPERLINK:
1447 OUString sURL, sDesc;
1448 if( SotClipboardFormatId::SIMPLE_FILE == nFormat )
1450 if( rData.GetString( nFormat, sURL ) && !sURL.isEmpty() )
1452 SwTransferable::CheckForURLOrLNKFile( rData, sURL, &sDesc );
1453 if( sDesc.isEmpty() )
1454 sDesc = sURL;
1455 bRet = true;
1458 else
1460 INetBookmark aBkmk;
1461 if( rData.GetINetBookmark( nFormat, aBkmk ) )
1463 sURL = aBkmk.GetURL();
1464 sDesc = aBkmk.GetDescription();
1465 bRet = true;
1469 if( bRet )
1471 SwFormatINetFormat aFormat( sURL, OUString() );
1472 rSh.InsertURL( aFormat, sDesc );
1475 break;
1477 case EXCHG_OUT_ACTION_GET_ATTRIBUTES:
1478 switch( nFormat )
1480 case SotClipboardFormatId::DRAWING:
1481 bRet = SwTransferable::PasteSdrFormat( rData, rSh,
1482 SwPasteSdr::SetAttr, pPt,
1483 nActionFlags, bNeedToSelectBeforePaste);
1484 break;
1485 case SotClipboardFormatId::SVXB:
1486 case SotClipboardFormatId::GDIMETAFILE:
1487 case SotClipboardFormatId::BITMAP:
1488 case SotClipboardFormatId::PNG:
1489 case SotClipboardFormatId::NETSCAPE_BOOKMARK:
1490 case SotClipboardFormatId::SIMPLE_FILE:
1491 case SotClipboardFormatId::FILEGRPDESCRIPTOR:
1492 case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
1493 bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
1494 SwPasteSdr::SetAttr, pPt,
1495 nActionFlags, nDropAction, bNeedToSelectBeforePaste);
1496 break;
1497 default:
1498 OSL_FAIL( "unknown format" );
1501 break;
1503 case EXCHG_OUT_ACTION_INSERT_DRAWOBJ:
1504 bRet = SwTransferable::PasteSdrFormat( rData, rSh,
1505 SwPasteSdr::Insert, pPt,
1506 nActionFlags, bNeedToSelectBeforePaste);
1507 break;
1508 case EXCHG_OUT_ACTION_INSERT_SVXB:
1509 case EXCHG_OUT_ACTION_INSERT_GDIMETAFILE:
1510 case EXCHG_OUT_ACTION_INSERT_BITMAP:
1511 case EXCHG_OUT_ACTION_INSERT_GRAPH:
1512 bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
1513 SwPasteSdr::Insert, pPt,
1514 nActionFlags, nDropAction, bNeedToSelectBeforePaste, nAnchorType );
1515 break;
1517 case EXCHG_OUT_ACTION_REPLACE_DRAWOBJ:
1518 bRet = SwTransferable::PasteSdrFormat( rData, rSh,
1519 SwPasteSdr::Replace, pPt,
1520 nActionFlags, bNeedToSelectBeforePaste);
1521 break;
1523 case EXCHG_OUT_ACTION_REPLACE_SVXB:
1524 case EXCHG_OUT_ACTION_REPLACE_GDIMETAFILE:
1525 case EXCHG_OUT_ACTION_REPLACE_BITMAP:
1526 case EXCHG_OUT_ACTION_REPLACE_GRAPH:
1527 bRet = SwTransferable::PasteGrf( rData, rSh, nFormat,
1528 SwPasteSdr::Replace,pPt,
1529 nActionFlags, nDropAction, bNeedToSelectBeforePaste);
1530 break;
1532 case EXCHG_OUT_ACTION_INSERT_INTERACTIVE:
1533 bRet = SwTransferable::PasteAsHyperlink( rData, rSh, nFormat );
1534 break;
1536 default:
1537 OSL_FAIL("unknown action" );
1541 if( !bPasteSelection && rSh.IsFrameSelected() )
1543 rSh.EnterSelFrameMode();
1544 //force ::SelectShell
1545 rSh.GetView().StopShellTimer();
1548 pAction.reset();
1549 if( bCallAutoCaption )
1550 rSh.GetView().AutoCaption( GRAPHIC_CAP );
1552 return bRet;
1555 SotExchangeDest SwTransferable::GetSotDestination( const SwWrtShell& rSh )
1557 SotExchangeDest nRet = SotExchangeDest::NONE;
1559 ObjCntType eOType = rSh.GetObjCntTypeOfSelection();
1561 switch( eOType )
1563 case OBJCNT_GRF:
1565 bool bIMap, bLink;
1566 bIMap = nullptr != rSh.GetFlyFrameFormat()->GetURL().GetMap();
1567 OUString aDummy;
1568 rSh.GetGrfNms( &aDummy, nullptr );
1569 bLink = !aDummy.isEmpty();
1571 if( bLink && bIMap )
1572 nRet = SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP;
1573 else if( bLink )
1574 nRet = SotExchangeDest::DOC_LNKD_GRAPHOBJ;
1575 else if( bIMap )
1576 nRet = SotExchangeDest::DOC_GRAPH_W_IMAP;
1577 else
1578 nRet = SotExchangeDest::DOC_GRAPHOBJ;
1580 break;
1582 case OBJCNT_FLY:
1583 if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr )
1584 nRet = SotExchangeDest::DOC_TEXTFRAME_WEB;
1585 else
1586 nRet = SotExchangeDest::DOC_TEXTFRAME;
1587 break;
1588 case OBJCNT_OLE: nRet = SotExchangeDest::DOC_OLEOBJ; break;
1590 case OBJCNT_CONTROL: /* no Action avail */
1591 case OBJCNT_SIMPLE: nRet = SotExchangeDest::DOC_DRAWOBJ; break;
1592 case OBJCNT_URLBUTTON: nRet = SotExchangeDest::DOC_URLBUTTON; break;
1593 case OBJCNT_GROUPOBJ: nRet = SotExchangeDest::DOC_GROUPOBJ; break;
1595 // what do we do at multiple selections???
1596 default:
1598 if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr )
1599 nRet = SotExchangeDest::SWDOC_FREE_AREA_WEB;
1600 else
1601 nRet = SotExchangeDest::SWDOC_FREE_AREA;
1605 return nRet;
1608 bool SwTransferable::PasteFileContent( TransferableDataHelper& rData,
1609 SwWrtShell& rSh, SotClipboardFormatId nFormat, bool bMsg )
1611 const char* pResId = STR_CLPBRD_FORMAT_ERROR;
1612 bool bRet = false;
1614 MSE40HTMLClipFormatObj aMSE40ClpObj;
1616 tools::SvRef<SotStorageStream> xStrm;
1617 SvStream* pStream = nullptr;
1618 SwRead pRead = nullptr;
1619 OUString sData;
1620 switch( nFormat )
1622 case SotClipboardFormatId::STRING:
1624 pRead = ReadAscii;
1625 if( rData.GetString( nFormat, sData ) )
1627 pStream = new SvMemoryStream( const_cast<sal_Unicode *>(sData.getStr()),
1628 sData.getLength() * sizeof( sal_Unicode ),
1629 StreamMode::READ );
1630 #ifdef OSL_BIGENDIAN
1631 pStream->SetEndian( SvStreamEndian::BIG );
1632 #else
1633 pStream->SetEndian( SvStreamEndian::LITTLE );
1634 #endif
1636 SwAsciiOptions aAOpt;
1637 aAOpt.SetCharSet( RTL_TEXTENCODING_UCS2 );
1638 pRead->GetReaderOpt().SetASCIIOpts( aAOpt );
1639 break;
1642 SAL_FALLTHROUGH; // because then test if we get a stream
1644 default:
1645 if( rData.GetSotStorageStream( nFormat, xStrm ) )
1647 if( ( SotClipboardFormatId::HTML_SIMPLE == nFormat ) ||
1648 ( SotClipboardFormatId::HTML_NO_COMMENT == nFormat ) )
1650 pStream = aMSE40ClpObj.IsValid( *xStrm );
1651 pRead = ReadHTML;
1652 pRead->SetReadUTF8( true );
1654 bool bNoComments =
1655 ( nFormat == SotClipboardFormatId::HTML_NO_COMMENT );
1656 pRead->SetIgnoreHTMLComments( bNoComments );
1658 else
1660 pStream = xStrm.get();
1661 if( SotClipboardFormatId::RTF == nFormat || SotClipboardFormatId::RICHTEXT == nFormat)
1662 pRead = SwReaderWriter::GetRtfReader();
1663 else if( !pRead )
1665 pRead = ReadHTML;
1666 pRead->SetReadUTF8( true );
1670 break;
1673 if( pStream && pRead )
1675 Link<SwCursorShell*,void> aOldLink( rSh.GetChgLnk() );
1676 rSh.SetChgLnk( Link<SwCursorShell*,void>() );
1678 const SwPosition& rInsPos = *rSh.GetCursor()->Start();
1679 SwReader aReader( *pStream, aEmptyOUStr, OUString(), *rSh.GetCursor() );
1680 rSh.SaveTableBoxContent( &rInsPos );
1681 if( aReader.Read( *pRead ).IsError() )
1682 pResId = STR_ERROR_CLPBRD_READ;
1683 else
1685 pResId = nullptr;
1686 bRet = true;
1689 rSh.SetChgLnk( aOldLink );
1690 if( bRet )
1691 rSh.CallChgLnk();
1693 else
1694 pResId = STR_CLPBRD_FORMAT_ERROR;
1696 // Exist a SvMemoryStream? (data in the OUString and xStrm is empty)
1697 if( pStream && !xStrm.is() )
1698 delete pStream;
1700 if (bMsg && pResId)
1702 ScopedVclPtrInstance<MessageDialog>(nullptr, SwResId(pResId), VclMessageType::Info)->Execute();
1704 return bRet;
1707 bool SwTransferable::PasteOLE( TransferableDataHelper& rData, SwWrtShell& rSh,
1708 SotClipboardFormatId nFormat, SotExchangeActionFlags nActionFlags, bool bMsg )
1710 bool bRet = false;
1711 TransferableObjectDescriptor aObjDesc;
1712 uno::Reference < io::XInputStream > xStrm;
1713 uno::Reference < embed::XStorage > xStore;
1714 Reader* pRead = nullptr;
1716 // Get the preferred format
1717 SotClipboardFormatId nId;
1718 if( rData.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ ) )
1719 nId = SotClipboardFormatId::EMBEDDED_OBJ;
1720 else if( rData.HasFormat( SotClipboardFormatId::EMBED_SOURCE ) &&
1721 rData.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR ))
1722 nId = SotClipboardFormatId::EMBED_SOURCE;
1723 else
1724 nId = SotClipboardFormatId::NONE;
1726 if (nId != SotClipboardFormatId::NONE)
1728 SwDocShell* pDocSh = rSh.GetDoc()->GetDocShell();
1729 xStrm = rData.GetInputStream(nId, SfxObjectShell::CreateShellID(pDocSh));
1732 if (xStrm.is())
1734 // if there is an embedded object, first try if it's a writer object
1735 // this will be inserted into the document by using a Reader
1738 xStore = comphelper::OStorageHelper::GetStorageFromInputStream( xStrm );
1739 switch( SotStorage::GetFormatID( xStore ) )
1741 case SotClipboardFormatId::STARWRITER_60:
1742 case SotClipboardFormatId::STARWRITERWEB_60:
1743 case SotClipboardFormatId::STARWRITERGLOB_60:
1744 case SotClipboardFormatId::STARWRITER_8:
1745 case SotClipboardFormatId::STARWRITERWEB_8:
1746 case SotClipboardFormatId::STARWRITERGLOB_8:
1747 pRead = ReadXML;
1748 break;
1749 default:
1752 uno::Reference < lang::XComponent > xComp( xStore, uno::UNO_QUERY );
1753 xComp->dispose();
1754 xStore = nullptr;
1756 catch (const uno::Exception&)
1760 break;
1763 catch (const uno::Exception&)
1765 // it wasn't a storage, but maybe it's a useful stream
1769 if( pRead )
1771 SwPaM &rPAM = *rSh.GetCursor();
1772 SwReader aReader( xStore, aEmptyOUStr, rPAM );
1773 if( ! aReader.Read( *pRead ).IsError() )
1774 bRet = true;
1775 else if( bMsg )
1776 ScopedVclPtrInstance<MessageDialog>(nullptr, SwResId(STR_ERROR_CLPBRD_READ), VclMessageType::Info)->Execute();
1778 else
1780 // temporary storage until the object is inserted
1781 uno::Reference< embed::XStorage > xTmpStor;
1782 uno::Reference < embed::XEmbeddedObject > xObj;
1783 OUString aName;
1784 comphelper::EmbeddedObjectContainer aCnt;
1786 if ( xStrm.is() )
1788 if ( !rData.GetTransferableObjectDescriptor( SotClipboardFormatId::OBJECTDESCRIPTOR, aObjDesc ) )
1790 OSL_ENSURE( !xStrm.is(), "An object without descriptor in clipboard!");
1793 else
1795 if( rData.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR_OLE ) && rData.GetTransferableObjectDescriptor( nFormat, aObjDesc ) )
1797 xStrm = rData.GetInputStream(SotClipboardFormatId::EMBED_SOURCE_OLE, OUString());
1798 if (!xStrm.is())
1799 xStrm = rData.GetInputStream(SotClipboardFormatId::EMBEDDED_OBJ_OLE, OUString());
1801 if ( !xStrm.is() )
1803 // This is MSOLE object that should be created by direct using of system clipboard
1806 xTmpStor = ::comphelper::OStorageHelper::GetTemporaryStorage();
1807 uno::Reference < embed::XEmbedObjectClipboardCreator > xClipboardCreator =
1808 embed::MSOLEObjectSystemCreator::create( ::comphelper::getProcessComponentContext() );
1810 embed::InsertedObjectInfo aInfo = xClipboardCreator->createInstanceInitFromClipboard(
1811 xTmpStor,
1812 "DummyName",
1813 uno::Sequence< beans::PropertyValue >() );
1815 // TODO/LATER: in future InsertedObjectInfo will be used to get container related information
1816 // for example whether the object should be an iconified one
1817 xObj = aInfo.Object;
1819 catch (const uno::Exception&)
1826 if ( xStrm.is() && !xObj.is() )
1827 xObj = aCnt.InsertEmbeddedObject( xStrm, aName );
1829 if( xObj.is() )
1831 svt::EmbeddedObjectRef xObjRef( xObj, aObjDesc.mnViewAspect );
1833 // try to get the replacement image from the clipboard
1834 Graphic aGraphic;
1835 SotClipboardFormatId nGrFormat = SotClipboardFormatId::NONE;
1837 // limit the size of the preview metafile to 100000 actions
1838 GDIMetaFile aMetafile;
1839 if (rData.GetGDIMetaFile(SotClipboardFormatId::GDIMETAFILE, aMetafile, 100000))
1841 nGrFormat = SotClipboardFormatId::GDIMETAFILE;
1842 aGraphic = aMetafile;
1845 // insert replacement image ( if there is one ) into the object helper
1846 if ( nGrFormat != SotClipboardFormatId::NONE )
1848 DataFlavor aDataFlavor;
1849 SotExchange::GetFormatDataFlavor( nGrFormat, aDataFlavor );
1850 xObjRef.SetGraphic( aGraphic, aDataFlavor.MimeType );
1852 else if ( aObjDesc.mnViewAspect == embed::Aspects::MSOLE_ICON )
1854 // it is important to have an icon, let an empty graphic be used
1855 // if no other graphic is provided
1856 // TODO/LATER: in future a default bitmap could be used
1857 MapMode aMapMode( MapUnit::Map100thMM );
1858 aGraphic.SetPrefSize( Size( 2500, 2500 ) );
1859 aGraphic.SetPrefMapMode( aMapMode );
1860 xObjRef.SetGraphic( aGraphic, OUString() );
1863 //set size. This is a hack because of handing over, size should be
1864 //passed to the InsertOle!!!!!!!!!!
1865 Size aSize;
1866 if ( aObjDesc.mnViewAspect == embed::Aspects::MSOLE_ICON )
1868 if( aObjDesc.maSize.Width() && aObjDesc.maSize.Height() )
1869 aSize = aObjDesc.maSize;
1870 else
1872 MapMode aMapMode( MapUnit::Map100thMM );
1873 aSize = xObjRef.GetSize( &aMapMode );
1876 else if( aObjDesc.maSize.Width() && aObjDesc.maSize.Height() )
1878 aSize = aObjDesc.maSize; //always 100TH_MM
1879 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( aObjDesc.mnViewAspect ) );
1880 aSize = OutputDevice::LogicToLogic(aSize, MapMode(MapUnit::Map100thMM), MapMode(aUnit));
1881 awt::Size aSz;
1884 aSz = xObj->getVisualAreaSize( aObjDesc.mnViewAspect );
1886 catch (const embed::NoVisualAreaSizeException&)
1888 // in this case the provided size is used
1891 if ( aSz.Width != aSize.Width() || aSz.Height != aSize.Height() )
1893 aSz.Width = aSize.Width();
1894 aSz.Height = aSize.Height();
1895 xObj->setVisualAreaSize( aObjDesc.mnViewAspect, aSz );
1898 else
1900 // the descriptor contains the wrong object size
1901 // the following call will let the MSOLE objects cache the size if it is possible
1902 // it should be done while the object is running
1905 xObj->getVisualAreaSize( aObjDesc.mnViewAspect );
1907 catch (const uno::Exception&)
1911 //End of Hack!
1913 rSh.InsertOleObject( xObjRef );
1914 bRet = true;
1916 if( bRet && ( nActionFlags & SotExchangeActionFlags::InsertTargetUrl) )
1917 SwTransferable::PasteTargetURL( rData, rSh, SwPasteSdr::NONE, nullptr, false );
1919 // let the object be unloaded if possible
1920 SwOLEObj::UnloadObject( xObj, rSh.GetDoc(), embed::Aspects::MSOLE_CONTENT );
1923 return bRet;
1926 bool SwTransferable::PasteTargetURL( TransferableDataHelper& rData,
1927 SwWrtShell& rSh, SwPasteSdr nAction,
1928 const Point* pPt, bool bInsertGRF )
1930 bool bRet = false;
1931 INetImage aINetImg;
1932 if( ( rData.HasFormat( SotClipboardFormatId::INET_IMAGE ) &&
1933 rData.GetINetImage( SotClipboardFormatId::INET_IMAGE, aINetImg )) ||
1934 ( rData.HasFormat( SotClipboardFormatId::NETSCAPE_IMAGE ) &&
1935 rData.GetINetImage( SotClipboardFormatId::NETSCAPE_IMAGE, aINetImg )) )
1937 if( !aINetImg.GetImageURL().isEmpty() && bInsertGRF )
1939 OUString sURL( aINetImg.GetImageURL() );
1940 SwTransferable::CheckForURLOrLNKFile( rData, sURL );
1942 //!!! check at FileSystem - only then it make sense to test graphics !!!
1943 Graphic aGraphic;
1944 GraphicFilter &rFlt = GraphicFilter::GetGraphicFilter();
1945 bRet = ERRCODE_NONE == GraphicFilter::LoadGraphic( sURL, aEmptyOUStr, aGraphic, &rFlt );
1947 if( bRet )
1949 //Check and Perform rotation if needed
1950 lclCheckAndPerformRotation(aGraphic);
1952 switch( nAction )
1954 case SwPasteSdr::Insert:
1955 SwTransferable::SetSelInShell( rSh, false, pPt );
1956 rSh.Insert( sURL, aEmptyOUStr, aGraphic );
1957 break;
1959 case SwPasteSdr::Replace:
1960 if( rSh.IsObjSelected() )
1962 rSh.ReplaceSdrObj( sURL, &aGraphic );
1963 Point aPt( pPt ? *pPt : rSh.GetCursorDocPos() );
1964 SwTransferable::SetSelInShell( rSh, true, &aPt );
1966 else
1967 rSh.ReRead( sURL, aEmptyOUStr, &aGraphic );
1968 break;
1970 case SwPasteSdr::SetAttr:
1971 if( rSh.IsObjSelected() )
1972 rSh.Paste( aGraphic, OUString() );
1973 else if( OBJCNT_GRF == rSh.GetObjCntTypeOfSelection() )
1974 rSh.ReRead( sURL, aEmptyOUStr, &aGraphic );
1975 else
1977 SwTransferable::SetSelInShell( rSh, false, pPt );
1978 rSh.Insert( sURL, aEmptyOUStr, aGraphic );
1980 break;
1981 default:
1982 bRet = false;
1986 else
1987 bRet = true;
1990 if( bRet )
1992 SfxItemSet aSet( rSh.GetAttrPool(), svl::Items<RES_URL, RES_URL>{} );
1993 rSh.GetFlyFrameAttr( aSet );
1994 SwFormatURL aURL( aSet.Get( RES_URL ) );
1996 if( aURL.GetURL() != aINetImg.GetTargetURL() ||
1997 aURL.GetTargetFrameName() != aINetImg.GetTargetFrame() )
1999 aURL.SetURL( aINetImg.GetTargetURL(), false );
2000 aURL.SetTargetFrameName( aINetImg.GetTargetFrame() );
2001 aSet.Put( aURL );
2002 rSh.SetFlyFrameAttr( aSet );
2005 return bRet;
2008 void SwTransferable::SetSelInShell( SwWrtShell& rSh, bool bSelectFrame,
2009 const Point* pPt )
2011 if( bSelectFrame )
2013 // select frames/objects
2014 if( pPt && !rSh.GetView().GetViewFrame()->GetDispatcher()->IsLocked() )
2016 rSh.GetView().NoRotate();
2017 if( rSh.SelectObj( *pPt ))
2019 rSh.HideCursor();
2020 rSh.EnterSelFrameMode( pPt );
2021 g_bFrameDrag = true;
2025 else
2027 if( rSh.IsFrameSelected() || rSh.IsObjSelected() )
2029 rSh.UnSelectFrame();
2030 rSh.LeaveSelFrameMode();
2031 rSh.GetView().GetEditWin().StopInsFrame();
2032 g_bFrameDrag = false;
2034 else if( rSh.GetView().GetDrawFuncPtr() )
2035 rSh.GetView().GetEditWin().StopInsFrame();
2037 rSh.EnterStdMode();
2038 if( pPt )
2039 rSh.SwCursorShell::SetCursor( *pPt, true );
2043 bool SwTransferable::PasteDDE( TransferableDataHelper& rData,
2044 SwWrtShell& rWrtShell, bool bReReadGrf,
2045 bool bMsg )
2047 // data from Clipboardformat
2048 OUString aApp, aTopic, aItem;
2051 tools::SvRef<SotStorageStream> xStrm;
2052 if( !rData.GetSotStorageStream( SotClipboardFormatId::LINK, xStrm ))
2054 OSL_ENSURE( false, "DDE Data not found." );
2055 return false;
2056 } // report useful error!!
2058 rtl_TextEncoding eEncoding = DDE_TXT_ENCODING;
2059 aApp = read_zeroTerminated_uInt8s_ToOUString(*xStrm, eEncoding);
2060 aTopic = read_zeroTerminated_uInt8s_ToOUString(*xStrm, eEncoding);
2061 aItem = read_zeroTerminated_uInt8s_ToOUString(*xStrm, eEncoding);
2064 OUString aCmd;
2065 sfx2::MakeLnkName( aCmd, &aApp, aTopic, aItem );
2067 // do we want to read in a graphic now?
2068 SotClipboardFormatId nFormat;
2069 if( !rData.HasFormat( SotClipboardFormatId::RTF ) &&
2070 !rData.HasFormat( SotClipboardFormatId::RICHTEXT ) &&
2071 !rData.HasFormat( SotClipboardFormatId::HTML ) &&
2072 !rData.HasFormat( SotClipboardFormatId::STRING ) &&
2073 (rData.HasFormat( nFormat = SotClipboardFormatId::GDIMETAFILE ) ||
2074 rData.HasFormat( nFormat = SotClipboardFormatId::BITMAP )) )
2076 Graphic aGrf;
2077 bool bRet = rData.GetGraphic( nFormat, aGrf );
2078 if( bRet )
2080 OUString sLnkTyp("DDE");
2081 if ( bReReadGrf )
2082 rWrtShell.ReRead( aCmd, sLnkTyp, &aGrf );
2083 else
2084 rWrtShell.Insert( aCmd, sLnkTyp, aGrf );
2086 return bRet;
2089 SwFieldType* pTyp = nullptr;
2090 size_t i = 1;
2091 size_t j;
2092 OUString aName;
2093 bool bDoublePaste = false;
2094 const size_t nSize = rWrtShell.GetFieldTypeCount();
2095 const ::utl::TransliterationWrapper& rColl = ::GetAppCmpStrIgnore();
2097 do {
2098 aName = aApp;
2099 aName += OUString::number( i );
2100 for( j = INIT_FLDTYPES; j < nSize; j++ )
2102 pTyp = rWrtShell.GetFieldType( j );
2103 if( SwFieldIds::Dde == pTyp->Which() )
2105 OUString sTmp( static_cast<SwDDEFieldType*>(pTyp)->GetCmd() );
2106 if( rColl.isEqual( sTmp, aCmd ) &&
2107 SfxLinkUpdateMode::ALWAYS == static_cast<SwDDEFieldType*>(pTyp)->GetType() )
2109 aName = pTyp->GetName();
2110 bDoublePaste = true;
2111 break;
2113 else if( rColl.isEqual( aName, pTyp->GetName() ) )
2114 break;
2117 if( j == nSize )
2118 break;
2119 ++i;
2121 while( !bDoublePaste );
2123 if( !bDoublePaste )
2125 SwDDEFieldType aType( aName, aCmd, SfxLinkUpdateMode::ALWAYS );
2126 pTyp = rWrtShell.InsertFieldType( aType );
2129 SwDDEFieldType* pDDETyp = static_cast<SwDDEFieldType*>(pTyp);
2131 OUString aExpand;
2132 if( rData.GetString( SotClipboardFormatId::STRING, aExpand ))
2134 do { // middle checked loop
2136 // When data comes from a spreadsheet, we add a DDE-table
2137 if( ( rData.HasFormat( SotClipboardFormatId::SYLK ) ||
2138 rData.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS ) ) &&
2139 !aExpand.isEmpty() &&
2140 ( 1 < comphelper::string::getTokenCount(aExpand, '\n') ||
2141 comphelper::string::getTokenCount(aExpand, '\t') ) )
2143 OUString sTmp( aExpand );
2144 sal_Int32 nRows = comphelper::string::getTokenCount(sTmp, '\n');
2145 if( nRows )
2146 --nRows;
2147 sTmp = sTmp.getToken( 0, '\n' );
2148 sal_Int32 nCols = comphelper::string::getTokenCount(sTmp, '\t');
2150 // don't try to insert tables that are too large for writer
2151 if (nRows > SAL_MAX_UINT16 || nCols > SAL_MAX_UINT16)
2153 if( bMsg )
2154 ScopedVclPtrInstance<MessageDialog>(nullptr, SwResId(STR_TABLE_TOO_LARGE), VclMessageType::Info)->Execute();
2155 pDDETyp = nullptr;
2156 break;
2159 // at least one column & row must be there
2160 if( !nRows || !nCols )
2162 if( bMsg )
2163 ScopedVclPtrInstance<MessageDialog>(nullptr, SwResId(STR_NO_TABLE), VclMessageType::Info)->Execute();
2164 pDDETyp = nullptr;
2165 break;
2168 rWrtShell.InsertDDETable(
2169 SwInsertTableOptions( tabopts::SPLIT_LAYOUT, 1 ), // TODO MULTIHEADER
2170 pDDETyp, nRows, nCols );
2172 else if( 1 < comphelper::string::getTokenCount(aExpand, '\n') )
2174 // multiple paragraphs -> insert a protected section
2175 if( rWrtShell.HasSelection() )
2176 rWrtShell.DelRight();
2178 SwSectionData aSect( DDE_LINK_SECTION, aName );
2179 aSect.SetLinkFileName( aCmd );
2180 aSect.SetProtectFlag(true);
2181 rWrtShell.InsertSection( aSect );
2183 pDDETyp = nullptr; // remove FieldTypes again
2185 else
2187 // insert
2188 SwDDEField aSwDDEField( pDDETyp );
2189 rWrtShell.Insert( aSwDDEField );
2192 } while( false );
2194 else
2195 pDDETyp = nullptr; // remove FieldTypes again
2197 if( !pDDETyp && !bDoublePaste )
2199 // remove FieldType again - error occurred!
2200 for( j = nSize; j >= INIT_FLDTYPES; --j )
2201 if( pTyp == rWrtShell.GetFieldType( j ) )
2203 rWrtShell.RemoveFieldType( j );
2204 break;
2208 return true;
2211 bool SwTransferable::PasteSdrFormat( TransferableDataHelper& rData,
2212 SwWrtShell& rSh, SwPasteSdr nAction,
2213 const Point* pPt, SotExchangeActionFlags nActionFlags, bool bNeedToSelectBeforePaste)
2215 bool bRet = false;
2216 tools::SvRef<SotStorageStream> xStrm;
2217 if( rData.GetSotStorageStream( SotClipboardFormatId::DRAWING, xStrm ))
2219 xStrm->SetVersion( SOFFICE_FILEFORMAT_50 );
2221 if(bNeedToSelectBeforePaste && pPt)
2223 // if this is an internal drag, need to set the target right (select it), else
2224 // still the source will be selected
2225 SwTransferable::SetSelInShell( rSh, true, pPt );
2228 rSh.Paste( *xStrm, nAction, pPt );
2229 bRet = true;
2231 if( bRet && ( nActionFlags & SotExchangeActionFlags::InsertTargetUrl ))
2232 SwTransferable::PasteTargetURL( rData, rSh, SwPasteSdr::NONE, nullptr, false );
2234 return bRet;
2237 bool SwTransferable::PasteGrf( TransferableDataHelper& rData, SwWrtShell& rSh,
2238 SotClipboardFormatId nFormat, SwPasteSdr nAction, const Point* pPt,
2239 SotExchangeActionFlags nActionFlags, sal_Int8 nDropAction, bool bNeedToSelectBeforePaste, RndStdIds nAnchorType )
2241 bool bRet = false;
2243 Graphic aGraphic;
2244 INetBookmark aBkmk;
2245 bool bCheckForGrf = false, bCheckForImageMap = false;
2247 switch( nFormat )
2249 case SotClipboardFormatId::BITMAP:
2250 case SotClipboardFormatId::PNG:
2251 case SotClipboardFormatId::GDIMETAFILE:
2252 bRet = rData.GetGraphic( nFormat, aGraphic );
2253 break;
2255 case SotClipboardFormatId::SVXB:
2257 tools::SvRef<SotStorageStream> xStm;
2259 if(rData.GetSotStorageStream(SotClipboardFormatId::SVXB, xStm))
2261 ReadGraphic( *xStm, aGraphic );
2262 bRet = (GraphicType::NONE != aGraphic.GetType() && GraphicType::Default != aGraphic.GetType());
2265 break;
2268 case SotClipboardFormatId::NETSCAPE_BOOKMARK:
2269 case SotClipboardFormatId::FILEGRPDESCRIPTOR:
2270 case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
2271 bRet = rData.GetINetBookmark( nFormat, aBkmk );
2272 if( bRet )
2274 if( SwPasteSdr::SetAttr == nAction )
2275 nFormat = SotClipboardFormatId::NETSCAPE_BOOKMARK;
2276 else
2277 bCheckForGrf = true;
2279 break;
2281 case SotClipboardFormatId::SIMPLE_FILE:
2283 OUString sText;
2284 bRet = rData.GetString( nFormat, sText );
2285 if( bRet )
2287 OUString sDesc;
2288 SwTransferable::CheckForURLOrLNKFile( rData, sText, &sDesc );
2290 aBkmk = INetBookmark(
2291 URIHelper::SmartRel2Abs(INetURLObject(), sText, Link<OUString *, bool>(), false ),
2292 sDesc );
2293 bCheckForGrf = true;
2294 bCheckForImageMap = SwPasteSdr::Replace == nAction;
2297 break;
2299 default:
2300 bRet = rData.GetGraphic( nFormat, aGraphic );
2301 break;
2304 if( bCheckForGrf )
2306 //!!! check at FileSystem - only then it makes sense to test the graphics !!!
2307 GraphicFilter &rFlt = GraphicFilter::GetGraphicFilter();
2308 bRet = ERRCODE_NONE == GraphicFilter::LoadGraphic( aBkmk.GetURL(), aEmptyOUStr,
2309 aGraphic, &rFlt );
2311 if( !bRet && SwPasteSdr::SetAttr == nAction &&
2312 SotClipboardFormatId::SIMPLE_FILE == nFormat &&
2313 // only at frame selection
2314 rSh.IsFrameSelected() )
2316 // then set as hyperlink after the graphic
2317 nFormat = SotClipboardFormatId::NETSCAPE_BOOKMARK;
2318 bRet = true;
2322 if(pPt && bNeedToSelectBeforePaste)
2324 // when using internal D&Ds, still the source object is selected and
2325 // this is necessary to get the correct source data which is also
2326 // dependent from selection. After receiving the drag data it is
2327 // now time to select the correct target object
2328 SwTransferable::SetSelInShell( rSh, true, pPt );
2331 if( bRet )
2333 //Check and Perform rotation if needed
2334 lclCheckAndPerformRotation(aGraphic);
2336 OUString sURL;
2337 if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr
2338 // #i123922# if link action is noted, also take URL
2339 || DND_ACTION_LINK == nDropAction)
2341 sURL = aBkmk.GetURL();
2344 switch( nAction )
2346 case SwPasteSdr::Insert:
2348 SwTransferable::SetSelInShell( rSh, false, pPt );
2349 rSh.Insert( sURL, aEmptyOUStr, aGraphic, nullptr, nAnchorType );
2350 break;
2353 case SwPasteSdr::Replace:
2355 if( rSh.IsObjSelected() )
2357 // #i123922# for D&D on draw objects, do for now the same for
2358 // SwPasteSdr::Replace (D&D) as for SwPasteSdr::SetAttr (D&D and
2359 // CTRL+SHIFT). The code below replaces the draw object with
2360 // a writer graphic; maybe this is an option later again if wanted
2361 rSh.Paste( aGraphic, sURL );
2363 // rSh.ReplaceSdrObj( sURL, aEmptyOUStr, &aGraphic );
2364 // Point aPt( pPt ? *pPt : rSh.GetCursorDocPos() );
2365 // SwTransferable::SetSelInShell( rSh, true, &aPt );
2367 else
2369 // set graphic at writer graphic without link
2370 rSh.ReRead( sURL, aEmptyOUStr, &aGraphic );
2373 break;
2376 case SwPasteSdr::SetAttr:
2378 if( SotClipboardFormatId::NETSCAPE_BOOKMARK == nFormat )
2380 if( rSh.IsFrameSelected() )
2382 SfxItemSet aSet( rSh.GetAttrPool(), svl::Items<RES_URL, RES_URL>{} );
2383 rSh.GetFlyFrameAttr( aSet );
2384 SwFormatURL aURL( aSet.Get( RES_URL ) );
2385 aURL.SetURL( aBkmk.GetURL(), false );
2386 aSet.Put( aURL );
2387 rSh.SetFlyFrameAttr( aSet );
2390 else if( rSh.IsObjSelected() )
2392 // set as attribute at DrawObject
2393 rSh.Paste( aGraphic, sURL );
2395 else if( OBJCNT_GRF == rSh.GetObjCntTypeOfSelection() )
2397 // set as linked graphic at writer graphic frame
2398 rSh.ReRead( sURL, aEmptyOUStr, &aGraphic );
2400 else
2402 SwTransferable::SetSelInShell( rSh, false, pPt );
2403 rSh.Insert( aBkmk.GetURL(), aEmptyOUStr, aGraphic );
2405 break;
2407 default:
2409 bRet = false;
2410 break;
2415 if( bRet )
2418 if( nActionFlags &
2419 ( SotExchangeActionFlags::InsertImageMap | SotExchangeActionFlags::ReplaceImageMap ) )
2420 SwTransferable::PasteImageMap( rData, rSh );
2422 if( nActionFlags & SotExchangeActionFlags::InsertTargetUrl )
2423 SwTransferable::PasteTargetURL( rData, rSh, SwPasteSdr::NONE, nullptr, false );
2425 else if( bCheckForImageMap )
2427 // or should the file be an ImageMap-File?
2428 ImageMap aMap;
2429 SfxMedium aMed( INetURLObject(aBkmk.GetURL()).GetFull(),
2430 StreamMode::STD_READ );
2431 SvStream* pStream = aMed.GetInStream();
2432 if( pStream != nullptr &&
2433 !pStream->GetError() &&
2434 // mba: no BaseURL for clipboard functionality
2435 aMap.Read( *pStream, IMAP_FORMAT_DETECT ) == IMAP_ERR_OK &&
2436 aMap.GetIMapObjectCount() )
2438 SfxItemSet aSet( rSh.GetAttrPool(), svl::Items<RES_URL, RES_URL>{} );
2439 rSh.GetFlyFrameAttr( aSet );
2440 SwFormatURL aURL( aSet.Get( RES_URL ) );
2441 aURL.SetMap( &aMap );
2442 aSet.Put( aURL );
2443 rSh.SetFlyFrameAttr( aSet );
2444 bRet = true;
2448 return bRet;
2451 bool SwTransferable::PasteImageMap( TransferableDataHelper& rData,
2452 SwWrtShell& rSh )
2454 bool bRet = false;
2455 if( rData.HasFormat( SotClipboardFormatId::SVIM ))
2457 SfxItemSet aSet( rSh.GetAttrPool(), svl::Items<RES_URL, RES_URL>{} );
2458 rSh.GetFlyFrameAttr( aSet );
2459 SwFormatURL aURL( aSet.Get( RES_URL ) );
2460 const ImageMap* pOld = aURL.GetMap();
2462 // set or replace, that is the question
2463 ImageMap aImageMap;
2464 if( rData.GetImageMap( SotClipboardFormatId::SVIM, aImageMap ) &&
2465 ( !pOld || aImageMap != *pOld ))
2467 aURL.SetMap( &aImageMap );
2468 aSet.Put( aURL );
2469 rSh.SetFlyFrameAttr( aSet );
2471 bRet = true;
2473 return bRet;
2476 bool SwTransferable::PasteAsHyperlink( TransferableDataHelper& rData,
2477 SwWrtShell& rSh, SotClipboardFormatId nFormat )
2479 bool bRet = false;
2480 OUString sFile;
2481 if( rData.GetString( nFormat, sFile ) && !sFile.isEmpty() )
2483 OUString sDesc;
2484 SwTransferable::CheckForURLOrLNKFile( rData, sFile, &sDesc );
2486 // first, make the URL absolute
2487 INetURLObject aURL;
2488 aURL.SetSmartProtocol( INetProtocol::File );
2489 aURL.SetSmartURL( sFile );
2490 sFile = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
2492 switch( rSh.GetObjCntTypeOfSelection() )
2494 case OBJCNT_FLY:
2495 case OBJCNT_GRF:
2496 case OBJCNT_OLE:
2498 SfxItemSet aSet( rSh.GetAttrPool(), svl::Items<RES_URL, RES_URL>{} );
2499 rSh.GetFlyFrameAttr( aSet );
2500 SwFormatURL aURL2( aSet.Get( RES_URL ) );
2501 aURL2.SetURL( sFile, false );
2502 if( aURL2.GetName().isEmpty() )
2503 aURL2.SetName( sFile );
2504 aSet.Put( aURL2 );
2505 rSh.SetFlyFrameAttr( aSet );
2507 break;
2509 default:
2511 rSh.InsertURL( SwFormatINetFormat( sFile, OUString() ),
2512 sDesc.isEmpty() ? sFile : sDesc);
2515 bRet = true;
2517 return bRet;
2520 bool SwTransferable::PasteFileName( TransferableDataHelper& rData,
2521 SwWrtShell& rSh, SotClipboardFormatId nFormat,
2522 SwPasteSdr nAction, const Point* pPt,
2523 SotExchangeActionFlags nActionFlags,
2524 bool * graphicInserted)
2526 bool bRet = SwTransferable::PasteGrf( rData, rSh, nFormat, nAction,
2527 pPt, nActionFlags, 0, false);
2528 if (graphicInserted != nullptr) {
2529 *graphicInserted = bRet;
2531 if( !bRet )
2533 OUString sFile, sDesc;
2534 if( rData.GetString( nFormat, sFile ) && !sFile.isEmpty() )
2536 #if HAVE_FEATURE_AVMEDIA
2537 INetURLObject aMediaURL;
2539 aMediaURL.SetSmartURL( sFile );
2540 const OUString aMediaURLStr( aMediaURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
2542 if( ::avmedia::MediaWindow::isMediaURL( aMediaURLStr, ""/*TODO?*/ ) )
2544 const SfxStringItem aMediaURLItem( SID_INSERT_AVMEDIA, aMediaURLStr );
2545 rSh.GetView().GetViewFrame()->GetDispatcher()->ExecuteList(
2546 SID_INSERT_AVMEDIA, SfxCallMode::SYNCHRON,
2547 { &aMediaURLItem });
2549 #else
2550 if (false)
2553 #endif
2554 else
2556 bool bIsURLFile = SwTransferable::CheckForURLOrLNKFile( rData, sFile, &sDesc );
2558 //Own FileFormat? --> insert, not for StarWriter/Web
2559 OUString sFileURL = URIHelper::SmartRel2Abs(INetURLObject(), sFile, Link<OUString *, bool>(), false );
2560 std::shared_ptr<const SfxFilter> pFlt = SwPasteSdr::SetAttr == nAction
2561 ? nullptr : SwIoSystem::GetFileFilter(sFileURL);
2562 if( pFlt && dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) == nullptr )
2564 // and then pull up the insert-region-dialog by PostUser event
2565 SwSectionData * pSect = new SwSectionData(
2566 FILE_LINK_SECTION,
2567 rSh.GetDoc()->GetUniqueSectionName() );
2568 pSect->SetLinkFileName( sFileURL );
2569 pSect->SetProtectFlag( true );
2571 Application::PostUserEvent( LINK( &rSh, SwWrtShell,
2572 InsertRegionDialog ), pSect );
2573 bRet = true;
2575 else if( SwPasteSdr::SetAttr == nAction ||
2576 ( bIsURLFile && SwPasteSdr::Insert == nAction ))
2578 //we can insert foreign files as links after all
2580 // first, make the URL absolute
2581 INetURLObject aURL;
2582 aURL.SetSmartProtocol( INetProtocol::File );
2583 aURL.SetSmartURL( sFile );
2584 sFile = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
2586 switch( rSh.GetObjCntTypeOfSelection() )
2588 case OBJCNT_FLY:
2589 case OBJCNT_GRF:
2590 case OBJCNT_OLE:
2592 SfxItemSet aSet( rSh.GetAttrPool(), svl::Items<RES_URL, RES_URL>{} );
2593 rSh.GetFlyFrameAttr( aSet );
2594 SwFormatURL aURL2( aSet.Get( RES_URL ) );
2595 aURL2.SetURL( sFile, false );
2596 if( aURL2.GetName().isEmpty() )
2597 aURL2.SetName( sFile );
2598 aSet.Put( aURL2 );
2599 rSh.SetFlyFrameAttr( aSet );
2601 break;
2603 default:
2605 rSh.InsertURL( SwFormatINetFormat( sFile, OUString() ),
2606 sDesc.isEmpty() ? sFile : sDesc );
2609 bRet = true;
2614 return bRet;
2617 bool SwTransferable::PasteDBData( TransferableDataHelper& rData,
2618 SwWrtShell& rSh, SotClipboardFormatId nFormat, bool bLink,
2619 const Point* pDragPt, bool bMsg )
2621 bool bRet = false;
2622 OUString sText;
2623 if( rData.GetString( nFormat, sText ) && !sText.isEmpty() )
2625 sal_uInt16 nWh = SotClipboardFormatId::SBA_CTRLDATAEXCHANGE == nFormat
2627 : SotClipboardFormatId::SBA_DATAEXCHANGE == nFormat
2628 ? (bLink
2629 ? FN_QRY_MERGE_FIELD
2630 : FN_QRY_INSERT)
2631 : (bLink
2633 : FN_QRY_INSERT_FIELD );
2634 const DataFlavorExVector& rVector = rData.GetDataFlavorExVector();
2635 bool bHaveColumnDescriptor = OColumnTransferable::canExtractColumnDescriptor(rVector, ColumnTransferFormatFlags::COLUMN_DESCRIPTOR | ColumnTransferFormatFlags::CONTROL_EXCHANGE);
2636 if ( SotClipboardFormatId::XFORMS == nFormat )
2638 rSh.MakeDrawView();
2639 FmFormView* pFmView = dynamic_cast<FmFormView*>( rSh.GetDrawView() );
2640 if (pFmView && pDragPt)
2642 const OXFormsDescriptor &rDesc = OXFormsTransferable::extractDescriptor(rData);
2643 SdrObject* pObj = pFmView->CreateXFormsControl(rDesc);
2644 if(nullptr != pObj)
2646 rSh.SwFEShell::InsertDrawObj( *pObj, *pDragPt );
2650 else if( nWh )
2652 std::unique_ptr<SfxUnoAnyItem> pConnectionItem;
2653 std::unique_ptr<SfxUnoAnyItem> pCursorItem;
2654 std::unique_ptr<SfxUnoAnyItem> pColumnItem;
2655 std::unique_ptr<SfxUnoAnyItem> pSourceItem;
2656 std::unique_ptr<SfxUnoAnyItem> pCommandItem;
2657 std::unique_ptr<SfxUnoAnyItem> pCommandTypeItem;
2658 std::unique_ptr<SfxUnoAnyItem> pColumnNameItem;
2659 std::unique_ptr<SfxUnoAnyItem> pSelectionItem;
2661 bool bDataAvailable = true;
2662 ODataAccessDescriptor aDesc;
2663 if(bHaveColumnDescriptor)
2664 aDesc = OColumnTransferable::extractColumnDescriptor(rData);
2665 else if(ODataAccessObjectTransferable::canExtractObjectDescriptor(rVector) )
2666 aDesc = ODataAccessObjectTransferable::extractObjectDescriptor(rData);
2667 else
2668 bDataAvailable = false;
2670 if ( bDataAvailable )
2672 pConnectionItem.reset(new SfxUnoAnyItem(FN_DB_CONNECTION_ANY, aDesc[DataAccessDescriptorProperty::Connection]));
2673 pColumnItem.reset(new SfxUnoAnyItem(FN_DB_COLUMN_ANY, aDesc[DataAccessDescriptorProperty::ColumnObject]));
2674 pSourceItem.reset(new SfxUnoAnyItem(FN_DB_DATA_SOURCE_ANY, makeAny(aDesc.getDataSource())));
2675 pCommandItem.reset(new SfxUnoAnyItem(FN_DB_DATA_COMMAND_ANY, aDesc[DataAccessDescriptorProperty::Command]));
2676 pCommandTypeItem.reset(new SfxUnoAnyItem(FN_DB_DATA_COMMAND_TYPE_ANY, aDesc[DataAccessDescriptorProperty::CommandType]));
2677 pColumnNameItem.reset(new SfxUnoAnyItem(FN_DB_DATA_COLUMN_NAME_ANY, aDesc[DataAccessDescriptorProperty::ColumnName]));
2678 pSelectionItem.reset(new SfxUnoAnyItem(FN_DB_DATA_SELECTION_ANY, aDesc[DataAccessDescriptorProperty::Selection]));
2679 pCursorItem.reset(new SfxUnoAnyItem(FN_DB_DATA_CURSOR_ANY, aDesc[DataAccessDescriptorProperty::Cursor]));
2682 SwView& rView = rSh.GetView();
2683 //force ::SelectShell
2684 rView.StopShellTimer();
2686 SfxStringItem aDataDesc( nWh, sText );
2687 rView.GetViewFrame()->GetDispatcher()->ExecuteList(
2688 nWh, SfxCallMode::ASYNCHRON,
2689 { &aDataDesc, pConnectionItem.get(), pColumnItem.get(),
2690 pSourceItem.get(), pCommandItem.get(), pCommandTypeItem.get(),
2691 pColumnNameItem.get(), pSelectionItem.get(),
2692 pCursorItem.get() });
2694 else
2696 rSh.MakeDrawView();
2697 FmFormView* pFmView = dynamic_cast<FmFormView*>( rSh.GetDrawView() );
2698 if (pFmView && bHaveColumnDescriptor && pDragPt)
2700 SdrObject* pObj = pFmView->CreateFieldControl( OColumnTransferable::extractColumnDescriptor(rData) );
2701 if ( nullptr != pObj)
2702 rSh.SwFEShell::InsertDrawObj( *pObj, *pDragPt );
2705 bRet = true;
2707 else if( bMsg )
2709 ScopedVclPtrInstance<MessageDialog>(nullptr, SwResId(STR_CLPBRD_FORMAT_ERROR), VclMessageType::Info)->Execute();
2711 return bRet;
2714 bool SwTransferable::PasteFileList( TransferableDataHelper& rData,
2715 SwWrtShell& rSh, bool bLink,
2716 const Point* pPt, bool bMsg )
2718 bool bRet = false;
2719 FileList aFileList;
2720 if( rData.GetFileList( SotClipboardFormatId::FILE_LIST, aFileList ) &&
2721 aFileList.Count() )
2723 SwPasteSdr nAct = bLink ? SwPasteSdr::SetAttr : SwPasteSdr::Insert;
2724 OUString sFlyNm;
2725 // iterate over the filelist
2726 for( sal_uLong n = 0, nEnd = aFileList.Count(); n < nEnd; ++n )
2728 TransferDataContainer* pHlp = new TransferDataContainer;
2729 pHlp->CopyString( SotClipboardFormatId::SIMPLE_FILE, aFileList.GetFile( n ));
2730 TransferableDataHelper aData( pHlp );
2732 if( SwTransferable::PasteFileName( aData, rSh, SotClipboardFormatId::SIMPLE_FILE, nAct,
2733 pPt, SotExchangeActionFlags::NONE, nullptr ))
2735 if( bLink )
2737 sFlyNm = rSh.GetFlyName();
2738 SwTransferable::SetSelInShell( rSh, false, pPt );
2740 bRet = true;
2743 if( !sFlyNm.isEmpty() )
2744 rSh.GotoFly( sFlyNm );
2746 else if( bMsg )
2748 ScopedVclPtrInstance<MessageDialog>(nullptr, SwResId(STR_CLPBRD_FORMAT_ERROR), VclMessageType::Info)->Execute();
2750 return bRet;
2753 bool SwTransferable::CheckForURLOrLNKFile( TransferableDataHelper& rData,
2754 OUString& rFileName, OUString* pTitle )
2756 bool bIsURLFile = false;
2757 INetBookmark aBkmk;
2758 if( rData.GetINetBookmark( SotClipboardFormatId::SOLK, aBkmk ) )
2760 rFileName = aBkmk.GetURL();
2761 if( pTitle )
2762 *pTitle = aBkmk.GetDescription();
2763 bIsURLFile = true;
2765 else
2767 sal_Int32 nLen = rFileName.getLength();
2768 if( 4 < nLen && '.' == rFileName[ nLen - 4 ])
2770 OUString sExt( rFileName.copy( nLen - 3 ));
2771 if( sExt.equalsIgnoreAsciiCase( "url" ))
2773 OSL_ENSURE( false, "how do we read today .URL - Files?" );
2777 return bIsURLFile;
2780 bool SwTransferable::IsPasteSpecial( const SwWrtShell& rWrtShell,
2781 const TransferableDataHelper& rData )
2783 // we can paste-special if there's an entry in the paste-special-format list
2784 SvxClipboardFormatItem aClipboardFormatItem(0);
2785 FillClipFormatItem( rWrtShell, rData, aClipboardFormatItem);
2786 return aClipboardFormatItem.Count() > 0;
2789 bool SwTransferable::PasteFormat( SwWrtShell& rSh,
2790 TransferableDataHelper& rData,
2791 SotClipboardFormatId nFormat )
2793 SwWait aWait( *rSh.GetView().GetDocShell(), false );
2794 bool bRet = false;
2796 SotClipboardFormatId nPrivateFormat = SotClipboardFormatId::PRIVATE;
2797 SwTransferable *pClipboard = GetSwTransferable( rData );
2798 if( pClipboard &&
2799 ((TransferBufferType::Document|TransferBufferType::Graphic|TransferBufferType::Ole) & pClipboard->m_eBufferType ))
2800 nPrivateFormat = SotClipboardFormatId::EMBED_SOURCE;
2802 if( pClipboard && nPrivateFormat == nFormat )
2803 bRet = pClipboard->PrivatePaste( rSh );
2804 else if( rData.HasFormat( nFormat ) )
2806 uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
2807 sal_uInt8 nEventAction;
2808 SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
2809 sal_uInt16 nSourceOptions =
2810 (( SotExchangeDest::DOC_TEXTFRAME == nDestination ||
2811 SotExchangeDest::SWDOC_FREE_AREA == nDestination ||
2812 SotExchangeDest::DOC_TEXTFRAME_WEB == nDestination ||
2813 SotExchangeDest::SWDOC_FREE_AREA_WEB == nDestination )
2814 ? EXCHG_IN_ACTION_COPY
2815 : EXCHG_IN_ACTION_MOVE);
2816 SotExchangeActionFlags nActionFlags;
2817 sal_uInt8 nAction = SotExchange::GetExchangeAction(
2818 rData.GetDataFlavorExVector(),
2819 nDestination,
2820 nSourceOptions, /* ?? */
2821 EXCHG_IN_ACTION_DEFAULT, /* ?? */
2822 nFormat, nEventAction, nFormat,
2823 lcl_getTransferPointer ( xTransferable ),
2824 &nActionFlags );
2826 if( EXCHG_INOUT_ACTION_NONE != nAction )
2827 bRet = SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
2828 nDestination, true, false );
2830 return bRet;
2833 bool SwTransferable::TestAllowedFormat( const TransferableDataHelper& rData,
2834 SotClipboardFormatId nFormat, SotExchangeDest nDestination )
2836 sal_uInt8 nAction = EXCHG_INOUT_ACTION_NONE, nEventAction;
2837 if( rData.HasFormat( nFormat )) {
2838 uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
2839 nAction = SotExchange::GetExchangeAction(
2840 rData.GetDataFlavorExVector(),
2841 nDestination, EXCHG_IN_ACTION_COPY,
2842 EXCHG_IN_ACTION_COPY, nFormat,
2843 nEventAction, nFormat,
2844 lcl_getTransferPointer ( xTransferable ) );
2846 return EXCHG_INOUT_ACTION_NONE != nAction;
2850 * the list of formats which will be offered to the user in the 'Paste
2851 * Special...' dialog and the paste button menu
2853 static SotClipboardFormatId aPasteSpecialIds[] =
2855 SotClipboardFormatId::HTML,
2856 SotClipboardFormatId::HTML_SIMPLE,
2857 SotClipboardFormatId::HTML_NO_COMMENT,
2858 SotClipboardFormatId::RTF,
2859 SotClipboardFormatId::RICHTEXT,
2860 SotClipboardFormatId::STRING,
2861 SotClipboardFormatId::SONLK,
2862 SotClipboardFormatId::NETSCAPE_BOOKMARK,
2863 SotClipboardFormatId::DRAWING,
2864 SotClipboardFormatId::SVXB,
2865 SotClipboardFormatId::GDIMETAFILE,
2866 SotClipboardFormatId::BITMAP,
2867 SotClipboardFormatId::SVIM,
2868 SotClipboardFormatId::FILEGRPDESCRIPTOR,
2869 SotClipboardFormatId::NONE
2872 bool SwTransferable::PasteUnformatted( SwWrtShell& rSh, TransferableDataHelper& rData )
2874 // Plain text == unformatted
2875 return SwTransferable::PasteFormat( rSh, rData, SotClipboardFormatId::STRING );
2878 bool SwTransferable::PasteSpecial( SwWrtShell& rSh, TransferableDataHelper& rData, SotClipboardFormatId& rFormatUsed )
2880 bool bRet = false;
2881 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
2882 ScopedVclPtr<SfxAbstractPasteDialog> pDlg(pFact->CreatePasteDialog( &rSh.GetView().GetEditWin() ));
2884 DataFlavorExVector aFormats( rData.GetDataFlavorExVector() );
2885 TransferableObjectDescriptor aDesc;
2887 SotExchangeDest nDest = SwTransferable::GetSotDestination( rSh );
2889 SwTransferable *pClipboard = GetSwTransferable( rData );
2890 if( pClipboard )
2892 aDesc = pClipboard->m_aObjDesc;
2893 const char* pResId;
2894 if( pClipboard->m_eBufferType & TransferBufferType::Document )
2895 pResId = STR_PRIVATETEXT;
2896 else if( pClipboard->m_eBufferType & TransferBufferType::Graphic )
2897 pResId = STR_PRIVATEGRAPHIC;
2898 else if( pClipboard->m_eBufferType == TransferBufferType::Ole )
2899 pResId = STR_PRIVATEOLE;
2900 else
2901 pResId = nullptr;
2903 if (pResId)
2905 if (strcmp(STR_PRIVATEOLE, pResId) == 0 || strcmp(STR_PRIVATEGRAPHIC, pResId) == 0)
2907 // add SotClipboardFormatId::EMBED_SOURCE to the formats. This
2908 // format display then the private format name.
2909 DataFlavorEx aFlavorEx;
2910 aFlavorEx.mnSotId = SotClipboardFormatId::EMBED_SOURCE;
2911 aFormats.insert( aFormats.begin(), aFlavorEx );
2913 pDlg->SetObjName( pClipboard->m_aObjDesc.maClassName,
2914 SwResId(pResId) );
2915 pDlg->Insert( SotClipboardFormatId::EMBED_SOURCE, aEmptyOUStr );
2918 else
2920 if( rData.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR ) )
2922 (void)rData.GetTransferableObjectDescriptor(
2923 SotClipboardFormatId::OBJECTDESCRIPTOR, aDesc );
2926 if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::EMBED_SOURCE, nDest ))
2927 pDlg->Insert( SotClipboardFormatId::EMBED_SOURCE, aEmptyOUStr );
2928 if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK_SOURCE, nDest ))
2929 pDlg->Insert( SotClipboardFormatId::LINK_SOURCE, aEmptyOUStr );
2932 if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK, nDest ))
2933 pDlg->Insert( SotClipboardFormatId::LINK, SwResId(STR_DDEFORMAT) );
2935 for( SotClipboardFormatId* pIds = aPasteSpecialIds; *pIds != SotClipboardFormatId::NONE; ++pIds )
2936 if( SwTransferable::TestAllowedFormat( rData, *pIds, nDest ))
2937 pDlg->Insert( *pIds, aEmptyOUStr );
2939 SotClipboardFormatId nFormat = pDlg->GetFormat( rData.GetTransferable() );
2941 if( nFormat != SotClipboardFormatId::NONE )
2942 bRet = SwTransferable::PasteFormat( rSh, rData, nFormat );
2944 if ( bRet )
2945 rFormatUsed = nFormat;
2947 return bRet;
2950 void SwTransferable::FillClipFormatItem( const SwWrtShell& rSh,
2951 const TransferableDataHelper& rData,
2952 SvxClipboardFormatItem & rToFill )
2954 SotExchangeDest nDest = SwTransferable::GetSotDestination( rSh );
2956 SwTransferable *pClipboard = GetSwTransferable( rData );
2957 if( pClipboard )
2959 const char* pResId;
2960 if( pClipboard->m_eBufferType & TransferBufferType::Document )
2961 pResId = STR_PRIVATETEXT;
2962 else if( pClipboard->m_eBufferType & TransferBufferType::Graphic )
2963 pResId = STR_PRIVATEGRAPHIC;
2964 else if( pClipboard->m_eBufferType == TransferBufferType::Ole )
2965 pResId = STR_PRIVATEOLE;
2966 else
2967 pResId = nullptr;
2969 if (pResId)
2970 rToFill.AddClipbrdFormat(SotClipboardFormatId::EMBED_SOURCE,
2971 SwResId(pResId));
2973 else
2975 TransferableObjectDescriptor aDesc;
2976 if (rData.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR))
2978 (void)const_cast<TransferableDataHelper&>(rData).GetTransferableObjectDescriptor(
2979 SotClipboardFormatId::OBJECTDESCRIPTOR, aDesc);
2982 if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::EMBED_SOURCE, nDest ))
2983 rToFill.AddClipbrdFormat( SotClipboardFormatId::EMBED_SOURCE,
2984 aDesc.maTypeName );
2985 if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK_SOURCE, nDest ))
2986 rToFill.AddClipbrdFormat( SotClipboardFormatId::LINK_SOURCE );
2988 SotClipboardFormatId nFormat;
2989 if ( rData.HasFormat(nFormat = SotClipboardFormatId::EMBED_SOURCE_OLE) || rData.HasFormat(nFormat = SotClipboardFormatId::EMBEDDED_OBJ_OLE) )
2991 OUString sName,sSource;
2992 if ( SvPasteObjectHelper::GetEmbeddedName(rData,sName,sSource,nFormat) )
2993 rToFill.AddClipbrdFormat( nFormat, sName );
2997 if( SwTransferable::TestAllowedFormat( rData, SotClipboardFormatId::LINK, nDest ))
2998 rToFill.AddClipbrdFormat( SotClipboardFormatId::LINK, SwResId(STR_DDEFORMAT) );
3000 for( SotClipboardFormatId* pIds = aPasteSpecialIds; *pIds != SotClipboardFormatId::NONE; ++pIds )
3001 if( SwTransferable::TestAllowedFormat( rData, *pIds, nDest ))
3002 rToFill.AddClipbrdFormat( *pIds, aEmptyOUStr );
3005 void SwTransferable::SetDataForDragAndDrop( const Point& rSttPos )
3007 if(!m_pWrtShell)
3008 return;
3009 OUString sGrfNm;
3010 const SelectionType nSelection = m_pWrtShell->GetSelectionType();
3011 if( SelectionType::Graphic == nSelection)
3013 AddFormat( SotClipboardFormatId::SVXB );
3014 const Graphic* pGrf = m_pWrtShell->GetGraphic();
3015 if ( pGrf && pGrf->IsSupportedGraphic() )
3017 AddFormat( SotClipboardFormatId::GDIMETAFILE );
3018 AddFormat( SotClipboardFormatId::PNG );
3019 AddFormat( SotClipboardFormatId::BITMAP );
3021 m_eBufferType = TransferBufferType::Graphic;
3022 m_pWrtShell->GetGrfNms( &sGrfNm, nullptr );
3024 else if( SelectionType::Ole == nSelection )
3026 AddFormat( SotClipboardFormatId::EMBED_SOURCE );
3027 PrepareOLE( m_aObjDesc );
3028 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
3029 AddFormat( SotClipboardFormatId::GDIMETAFILE );
3030 m_eBufferType = TransferBufferType::Ole;
3032 //Is there anything to provide anyway?
3033 else if ( m_pWrtShell->IsSelection() || m_pWrtShell->IsFrameSelected() ||
3034 m_pWrtShell->IsObjSelected() )
3036 if( m_pWrtShell->IsObjSelected() )
3037 m_eBufferType = TransferBufferType::Drawing;
3038 else
3040 m_eBufferType = TransferBufferType::Document;
3041 if( SwWrtShell::NO_WORD !=
3042 m_pWrtShell->IntelligentCut( nSelection, false ))
3043 m_eBufferType = TransferBufferType::DocumentWord | m_eBufferType;
3046 if( nSelection & SelectionType::TableCell )
3047 m_eBufferType = TransferBufferType::Table | m_eBufferType;
3049 AddFormat( SotClipboardFormatId::EMBED_SOURCE );
3051 //put RTF ahead of the OLE's Metafile for less loss
3052 if( !m_pWrtShell->IsObjSelected() )
3054 AddFormat( SotClipboardFormatId::RTF );
3055 AddFormat( SotClipboardFormatId::RICHTEXT );
3056 AddFormat( SotClipboardFormatId::HTML );
3058 if( m_pWrtShell->IsSelection() )
3059 AddFormat( SotClipboardFormatId::STRING );
3061 if( nSelection & ( SelectionType::DrawObject | SelectionType::DbForm ))
3063 AddFormat( SotClipboardFormatId::DRAWING );
3064 if ( nSelection & SelectionType::DrawObject )
3066 AddFormat( SotClipboardFormatId::GDIMETAFILE );
3067 AddFormat( SotClipboardFormatId::PNG );
3068 AddFormat( SotClipboardFormatId::BITMAP );
3070 m_eBufferType = TransferBufferType::Graphic | m_eBufferType;
3072 m_pClpGraphic.reset(new Graphic);
3073 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_pClpGraphic ))
3074 m_pOrigGraphic = m_pClpGraphic.get();
3075 m_pClpBitmap.reset(new Graphic);
3076 if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_pClpBitmap ))
3077 m_pOrigGraphic = m_pClpBitmap.get();
3079 // is it an URL-Button ?
3080 OUString sURL;
3081 OUString sDesc;
3082 if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) )
3084 AddFormat( SotClipboardFormatId::STRING );
3085 AddFormat( SotClipboardFormatId::SOLK );
3086 AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
3087 AddFormat( SotClipboardFormatId::FILECONTENT );
3088 AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
3089 AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
3090 m_eBufferType = TransferBufferType::InetField | m_eBufferType;
3094 //ObjectDescriptor was already filled from the old DocShell.
3095 //Now adjust it. Thus in GetData the first query can still
3096 //be answered with delayed rendering.
3097 m_aObjDesc.maDragStartPos = rSttPos;
3098 m_aObjDesc.maSize = OutputDevice::LogicToLogic( Size( OLESIZE ),
3099 MapMode(MapUnit::MapTwip), MapMode(MapUnit::Map100thMM));
3100 PrepareOLE( m_aObjDesc );
3101 AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
3103 else if( nSelection & SelectionType::Text && !m_pWrtShell->HasMark() )
3105 // is only one field - selected?
3106 SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );
3107 Point aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY());
3109 if( m_pWrtShell->GetContentAtPos( aPos, aContentAtPos ) )
3111 AddFormat( SotClipboardFormatId::STRING );
3112 AddFormat( SotClipboardFormatId::SOLK );
3113 AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
3114 AddFormat( SotClipboardFormatId::FILECONTENT );
3115 AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
3116 AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
3117 m_eBufferType = TransferBufferType::InetField;
3121 if( m_pWrtShell->IsFrameSelected() )
3123 SfxItemSet aSet( m_pWrtShell->GetAttrPool(), svl::Items<RES_URL, RES_URL>{} );
3124 m_pWrtShell->GetFlyFrameAttr( aSet );
3125 const SwFormatURL& rURL = aSet.Get( RES_URL );
3126 if( rURL.GetMap() )
3128 m_pImageMap.reset( new ImageMap( *rURL.GetMap() ) );
3129 AddFormat( SotClipboardFormatId::SVIM );
3131 else if( !rURL.GetURL().isEmpty() )
3133 m_pTargetURL.reset(new INetImage( sGrfNm, rURL.GetURL(),
3134 rURL.GetTargetFrameName() ));
3135 AddFormat( SotClipboardFormatId::INET_IMAGE );
3140 void SwTransferable::StartDrag( vcl::Window* pWin, const Point& rPos )
3142 if(!m_pWrtShell)
3143 return;
3144 m_bOldIdle = m_pWrtShell->GetViewOptions()->IsIdle();
3145 m_bCleanUp = true;
3147 m_pWrtShell->GetViewOptions()->SetIdle( false );
3149 if( m_pWrtShell->IsSelFrameMode() )
3150 m_pWrtShell->ShowCursor();
3152 SW_MOD()->m_pDragDrop = this;
3154 SetDataForDragAndDrop( rPos );
3156 sal_Int8 nDragOptions = DND_ACTION_COPYMOVE | DND_ACTION_LINK;
3157 SwDocShell* pDShell = m_pWrtShell->GetView().GetDocShell();
3158 if( ( pDShell && pDShell->IsReadOnly() ) || m_pWrtShell->HasReadonlySel() )
3159 nDragOptions &= ~DND_ACTION_MOVE;
3161 TransferableHelper::StartDrag( pWin, nDragOptions );
3164 void SwTransferable::DragFinished( sal_Int8 nAction )
3166 //And the last finishing work so that all statuses are right
3167 if( DND_ACTION_MOVE == nAction )
3169 if( m_bCleanUp )
3171 //It was dropped outside of Writer. We still have to
3172 //delete.
3174 m_pWrtShell->StartAllAction();
3175 m_pWrtShell->StartUndo( SwUndoId::UI_DRAG_AND_MOVE );
3176 if ( m_pWrtShell->IsTableMode() )
3177 m_pWrtShell->DeleteTableSel();
3178 else
3180 if ( !(m_pWrtShell->IsSelFrameMode() || m_pWrtShell->IsObjSelected()) )
3181 //SmartCut, take one of the blanks along
3182 m_pWrtShell->IntelligentCut( m_pWrtShell->GetSelectionType() );
3183 m_pWrtShell->DelRight();
3185 m_pWrtShell->EndUndo( SwUndoId::UI_DRAG_AND_MOVE );
3186 m_pWrtShell->EndAllAction();
3188 else
3190 const SelectionType nSelection = m_pWrtShell->GetSelectionType();
3191 if( ( SelectionType::Frame | SelectionType::Graphic |
3192 SelectionType::Ole | SelectionType::DrawObject ) & nSelection )
3194 m_pWrtShell->EnterSelFrameMode();
3198 m_pWrtShell->GetView().GetEditWin().DragFinished();
3200 if( m_pWrtShell->IsSelFrameMode() )
3201 m_pWrtShell->HideCursor();
3202 else
3203 m_pWrtShell->ShowCursor();
3205 m_pWrtShell->GetViewOptions()->SetIdle( m_bOldIdle );
3208 namespace
3211 bool lcl_checkClassification(SwDoc* pSourceDoc, SwDoc* pDestinationDoc)
3213 if (!pSourceDoc || !pDestinationDoc)
3214 return true;
3216 SwDocShell* pSourceShell = pSourceDoc->GetDocShell();
3217 SwDocShell* pDestinationShell = pDestinationDoc->GetDocShell();
3218 if (!pSourceShell || !pDestinationShell)
3219 return true;
3221 SfxClassificationCheckPasteResult eResult = SfxClassificationHelper::CheckPaste(pSourceShell->getDocProperties(), pDestinationShell->getDocProperties());
3222 return SfxClassificationHelper::ShowPasteInfo(eResult);
3227 bool SwTransferable::PrivatePaste( SwWrtShell& rShell )
3229 // first, ask for the SelectionType, then action-bracketing !!!!
3230 // (otherwise it's not pasted into a TableSelection!!!)
3231 OSL_ENSURE( !rShell.ActionPend(), "Paste must never have an ActionPend" );
3232 if ( !m_pClpDocFac )
3233 return false; // the return value of the SwFEShell::Paste also is bool!
3235 const SelectionType nSelection = rShell.GetSelectionType();
3237 SwTrnsfrActionAndUndo aAction( &rShell );
3239 bool bKillPaMs = false;
3241 //Delete selected content, not at table-selection and table in Clipboard, and don't delete hovering graphics.
3242 if( rShell.HasSelection() && !( nSelection & SelectionType::TableCell) && !( nSelection & SelectionType::DrawObject))
3244 bKillPaMs = true;
3245 rShell.SetRetainSelection( true );
3246 rShell.DelRight();
3247 // when a Fly was selected, a valid cursor position has to be found now
3248 // (parked Cursor!)
3249 if( ( SelectionType::Frame | SelectionType::Graphic |
3250 SelectionType::Ole | SelectionType::DrawObject |
3251 SelectionType::DbForm ) & nSelection )
3253 // position the cursor again
3254 Point aPt( rShell.GetCharRect().Pos() );
3255 rShell.SwCursorShell::SetCursor( aPt, true );
3257 rShell.SetRetainSelection( false );
3259 if ( nSelection & SelectionType::DrawObject) //unselect hovering graphics
3261 rShell.ResetSelect(nullptr,false);
3264 bool bInWrd = false, bEndWrd = false, bSttWrd = false,
3265 bSmart(TransferBufferType::DocumentWord & m_eBufferType);
3266 if( bSmart )
3268 // Why not for other Scripts? If TransferBufferType::DocumentWord is set, we have a word
3269 // in the buffer, word in this context means 'something with spaces at beginning
3270 // and end'. In this case we definitely want these spaces to be inserted here.
3271 bInWrd = rShell.IsInWord();
3272 bEndWrd = rShell.IsEndWrd();
3273 bSmart = bInWrd || bEndWrd;
3274 if( bSmart )
3276 bSttWrd = rShell.IsStartWord();
3277 if( bSmart && !bSttWrd && (bInWrd || bEndWrd) )
3278 rShell.SwEditShell::Insert(' ');
3282 bool bRet = true;
3283 // m_pWrtShell is nullptr when the source document is closed already.
3284 if (!m_pWrtShell || lcl_checkClassification(m_pWrtShell->GetDoc(), rShell.GetDoc()))
3285 bRet = rShell.Paste(m_pClpDocFac->GetDoc());
3287 if( bKillPaMs )
3288 rShell.KillPams();
3290 // If Smart Paste then insert blank
3291 if( bRet && bSmart && ((bInWrd && !bEndWrd )|| bSttWrd) )
3292 rShell.SwEditShell::Insert(' ');
3294 return bRet;
3297 bool SwTransferable::PrivateDrop( SwWrtShell& rSh, const Point& rDragPt,
3298 bool bMove, bool bIsXSelection )
3300 int cWord = 0;
3301 bool bInWrd = false;
3302 bool bEndWrd = false;
3303 bool bSttWrd = false;
3304 bool bSttPara = false;
3305 bool bTableSel = false;
3306 bool bFrameSel = false;
3308 SwWrtShell& rSrcSh = *GetShell();
3310 rSh.UnSetVisibleCursor();
3312 if( TransferBufferType::InetField == m_eBufferType )
3314 if( rSh.GetFormatFromObj( rDragPt ) )
3316 INetBookmark aTmp;
3317 if( (TransferBufferType::InetField & m_eBufferType) && m_pBookmark )
3318 aTmp = *m_pBookmark;
3320 // select target graphic
3321 if( rSh.SelectObj( rDragPt ) )
3323 rSh.HideCursor();
3324 rSh.EnterSelFrameMode( &rDragPt );
3325 g_bFrameDrag = true;
3328 const SelectionType nSelection = rSh.GetSelectionType();
3330 // not yet consider Draw objects
3331 if( SelectionType::Graphic & nSelection )
3333 SfxItemSet aSet( rSh.GetAttrPool(), svl::Items<RES_URL, RES_URL>{} );
3334 rSh.GetFlyFrameAttr( aSet );
3335 SwFormatURL aURL( aSet.Get( RES_URL ) );
3336 aURL.SetURL( aTmp.GetURL(), false );
3337 aSet.Put( aURL );
3338 rSh.SetFlyFrameAttr( aSet );
3339 return true;
3342 if( SelectionType::DrawObject & nSelection )
3344 rSh.LeaveSelFrameMode();
3345 rSh.UnSelectFrame();
3346 rSh.ShowCursor();
3347 g_bFrameDrag = false;
3352 if( &rSh != &rSrcSh && (SelectionType::Graphic & rSh.GetSelectionType()) &&
3353 TransferBufferType::Graphic == m_eBufferType )
3355 // ReRead the graphic
3356 OUString sGrfNm;
3357 OUString sFltNm;
3358 rSrcSh.GetGrfNms( &sGrfNm, &sFltNm );
3359 rSh.ReRead( sGrfNm, sFltNm, rSrcSh.GetGraphic() );
3360 return true;
3363 //not in selections or selected frames
3364 if( rSh.TestCurrPam( rDragPt ) ||
3365 ( rSh.IsSelFrameMode() && rSh.IsInsideSelectedObj( rDragPt )) )
3366 return false;
3368 if( rSrcSh.IsTableMode() )
3369 bTableSel = true;
3370 else if( rSrcSh.IsSelFrameMode() || rSrcSh.IsObjSelected() )
3372 // don't move position-protected objects!
3373 if( bMove && rSrcSh.IsSelObjProtected( FlyProtectFlags::Pos ) != FlyProtectFlags::NONE )
3374 return false;
3376 bFrameSel = true;
3379 const SelectionType nSel = rSrcSh.GetSelectionType();
3381 SwUndoId eUndoId = bMove ? SwUndoId::UI_DRAG_AND_MOVE : SwUndoId::UI_DRAG_AND_COPY;
3383 SwRewriter aRewriter;
3385 aRewriter.AddRule(UndoArg1, rSrcSh.GetSelDescr());
3387 if(rSrcSh.GetDoc() != rSh.GetDoc())
3388 rSrcSh.StartUndo( eUndoId, &aRewriter );
3389 rSh.StartUndo( eUndoId, &aRewriter );
3391 rSh.StartAction();
3392 rSrcSh.StartAction();
3394 if( &rSrcSh != &rSh )
3396 rSh.EnterStdMode();
3397 rSh.SwCursorShell::SetCursor( rDragPt, true );
3398 cWord = rSrcSh.IntelligentCut( nSel, false );
3400 else if( !bTableSel && !bFrameSel )
3402 if( !rSh.IsAddMode() )
3404 // #i87233#
3405 if ( rSh.IsBlockMode() )
3407 // preserve order of cursors for block mode
3408 rSh.GoPrevCursor();
3411 rSh.SwCursorShell::CreateCursor();
3413 rSh.SwCursorShell::SetCursor( rDragPt, true, false );
3414 rSh.GoPrevCursor();
3415 cWord = rSh.IntelligentCut( rSh.GetSelectionType(), false );
3416 rSh.GoNextCursor();
3419 bInWrd = rSh.IsInWord();
3420 bEndWrd = rSh.IsEndWrd();
3421 bSttWrd = !bEndWrd && rSh.IsStartWord();
3422 bSttPara= rSh.IsSttPara();
3424 Point aSttPt( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY() );
3426 // at first, select INetFelder!
3427 if( TransferBufferType::InetField == m_eBufferType )
3429 if( &rSrcSh == &rSh )
3431 rSh.GoPrevCursor();
3432 rSh.SwCursorShell::SetCursor( aSttPt, true );
3433 rSh.SelectTextAttr( RES_TXTATR_INETFMT );
3434 if( rSh.TestCurrPam( rDragPt ) )
3436 // don't copy/move inside of yourself
3437 rSh.DestroyCursor();
3438 rSh.EndUndo();
3439 rSh.EndAction();
3440 rSh.EndAction();
3441 return false;
3443 rSh.GoNextCursor();
3445 else
3447 rSrcSh.SwCursorShell::SetCursor( aSttPt, true );
3448 rSrcSh.SelectTextAttr( RES_TXTATR_INETFMT );
3451 // is there an URL attribute at the insert point? Then replace that,
3452 // so simply put up a selection?
3453 rSh.DelINetAttrWithText();
3454 g_bDDINetAttr = true;
3457 if ( rSrcSh.IsSelFrameMode() )
3459 //Hack: fool the special treatment
3460 aSttPt -= aSttPt - rSrcSh.GetObjRect().Pos();
3463 bool bRet = rSrcSh.SwFEShell::Copy( &rSh, aSttPt, rDragPt, bMove,
3464 !bIsXSelection );
3466 if( !bIsXSelection )
3468 rSrcSh.Push();
3469 if ( bRet && bMove && !bFrameSel )
3471 if ( bTableSel )
3473 /* delete table contents not cells */
3474 rSrcSh.Delete();
3476 else
3478 //SmartCut, take one of the blanks along.
3479 rSh.SwCursorShell::DestroyCursor();
3480 if ( cWord == SwWrtShell::WORD_SPACE_BEFORE )
3481 rSh.ExtendSelection( false );
3482 else if ( cWord == SwWrtShell::WORD_SPACE_AFTER )
3483 rSh.ExtendSelection();
3484 rSrcSh.DelRight();
3487 rSrcSh.KillPams();
3488 rSrcSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
3490 /* after dragging a table selection inside one shell
3491 set cursor to the drop position. */
3492 if( &rSh == &rSrcSh && ( bTableSel || rSh.IsBlockMode() ) )
3494 rSrcSh.CalcLayout();
3495 rSrcSh.SwCursorShell::SetCursor(rDragPt);
3496 rSrcSh.GetSwCursor()->SetMark();
3500 if( bRet && !bTableSel && !bFrameSel )
3502 if( (bInWrd || bEndWrd) &&
3503 (cWord == SwWrtShell::WORD_SPACE_AFTER ||
3504 cWord == SwWrtShell::WORD_SPACE_BEFORE) )
3506 if ( bSttWrd || (bInWrd && !bEndWrd))
3507 rSh.SwEditShell::Insert(' ', bIsXSelection);
3508 if ( !bSttWrd || (bInWrd && !bSttPara) )
3510 rSh.SwapPam();
3511 if ( !bSttWrd )
3512 rSh.SwEditShell::Insert(' ', bIsXSelection);
3513 rSh.SwapPam();
3517 if( bIsXSelection )
3519 if( &rSrcSh == &rSh && !rSh.IsAddMode() )
3521 rSh.SwCursorShell::DestroyCursor();
3522 rSh.GoPrevCursor();
3524 else
3526 rSh.SwapPam();
3527 rSh.SwCursorShell::ClearMark();
3530 else
3532 if( rSh.IsAddMode() )
3533 rSh.SwCursorShell::CreateCursor();
3534 else
3536 // turn on selection mode
3537 rSh.SttSelect();
3538 rSh.EndSelect();
3543 if( bRet && bMove && bFrameSel )
3544 rSrcSh.LeaveSelFrameMode();
3546 if( rSrcSh.GetDoc() != rSh.GetDoc() )
3547 rSrcSh.EndUndo();
3548 rSh.EndUndo();
3550 // put the shell in the right state
3551 if( &rSrcSh != &rSh && ( rSh.IsFrameSelected() || rSh.IsObjSelected() ))
3552 rSh.EnterSelFrameMode();
3554 rSrcSh.EndAction();
3555 rSh.EndAction();
3556 return true;
3559 // Interfaces for Selection
3560 void SwTransferable::CreateSelection( SwWrtShell& rSh,
3561 const SwFrameShell * _pCreatorView )
3563 SwModule *pMod = SW_MOD();
3564 rtl::Reference<SwTransferable> pNew = new SwTransferable( rSh );
3566 pNew->m_pCreatorView = _pCreatorView;
3568 pMod->m_pXSelection = pNew.get();
3569 pNew->CopyToSelection( rSh.GetWin() );
3572 void SwTransferable::ClearSelection( SwWrtShell& rSh,
3573 const SwFrameShell * _pCreatorView)
3575 SwModule *pMod = SW_MOD();
3576 if( pMod->m_pXSelection &&
3577 ((!pMod->m_pXSelection->m_pWrtShell) || (pMod->m_pXSelection->m_pWrtShell == &rSh)) &&
3578 (!_pCreatorView || (pMod->m_pXSelection->m_pCreatorView == _pCreatorView)) )
3580 TransferableHelper::ClearSelection( rSh.GetWin() );
3584 namespace
3586 class theSwTransferableUnoTunnelId : public rtl::Static< UnoTunnelIdInit, SwTransferable > {};
3589 const Sequence< sal_Int8 >& SwTransferable::getUnoTunnelId()
3591 return theSwTransferableUnoTunnelId::get().getSeq();
3594 sal_Int64 SwTransferable::getSomething( const Sequence< sal_Int8 >& rId )
3596 sal_Int64 nRet;
3597 if( ( rId.getLength() == 16 ) &&
3598 ( 0 == memcmp( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
3600 nRet = sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this ) );
3602 else
3603 nRet = TransferableHelper::getSomething(rId);
3604 return nRet;
3607 SwTransferable* SwTransferable::GetSwTransferable( const TransferableDataHelper& rData )
3609 SwTransferable* pSwTransferable = nullptr;
3611 uno::Reference<XUnoTunnel> xTunnel( rData.GetTransferable(), UNO_QUERY );
3612 if ( xTunnel.is() )
3614 sal_Int64 nHandle = xTunnel->getSomething( getUnoTunnelId() );
3615 if ( nHandle )
3616 pSwTransferable = reinterpret_cast<SwTransferable*>( static_cast<sal_IntPtr>(nHandle) );
3619 return pSwTransferable;
3623 SwTrnsfrDdeLink::SwTrnsfrDdeLink( SwTransferable& rTrans, SwWrtShell& rSh )
3624 : rTrnsfr(rTrans)
3625 , pDocShell(nullptr)
3626 , nOldTimeOut(0)
3627 , bDelBookmrk(false)
3628 , bInDisconnect(false)
3630 // we only end up here with table- or text selection
3631 if( SelectionType::TableCell & rSh.GetSelectionType() )
3633 SwFrameFormat* pFormat = rSh.GetTableFormat();
3634 if( pFormat )
3635 sName = pFormat->GetName();
3637 else
3639 // creating a temp. bookmark without undo
3640 bool bUndo = rSh.DoesUndo();
3641 rSh.DoUndo( false );
3642 bool bIsModified = rSh.IsModified();
3644 ::sw::mark::IMark* pMark = rSh.SetBookmark(
3645 vcl::KeyCode(),
3646 OUString(),
3647 IDocumentMarkAccess::MarkType::DDE_BOOKMARK);
3648 if(pMark)
3650 sName = pMark->GetName();
3651 bDelBookmrk = true;
3652 if( !bIsModified )
3653 rSh.ResetModified();
3655 else
3656 sName.clear();
3657 rSh.DoUndo( bUndo );
3660 if( !sName.isEmpty() &&
3661 nullptr != ( pDocShell = rSh.GetDoc()->GetDocShell() ) )
3663 // then we create our "server" and connect to it
3664 refObj = pDocShell->DdeCreateLinkSource( sName );
3665 if( refObj.is() )
3667 refObj->AddConnectAdvise( this );
3668 refObj->AddDataAdvise( this,
3669 aEmptyOUStr,
3670 ADVISEMODE_NODATA | ADVISEMODE_ONLYONCE );
3671 nOldTimeOut = refObj->GetUpdateTimeout();
3672 refObj->SetUpdateTimeout( 0 );
3677 SwTrnsfrDdeLink::~SwTrnsfrDdeLink()
3679 if( refObj.is() )
3680 Disconnect( true );
3683 ::sfx2::SvBaseLink::UpdateResult SwTrnsfrDdeLink::DataChanged( const OUString& ,
3684 const uno::Any& )
3686 // well, that's it with the link
3687 if( !bInDisconnect )
3689 if( FindDocShell() && pDocShell->GetView() )
3690 rTrnsfr.RemoveDDELinkFormat( pDocShell->GetView()->GetEditWin() );
3691 Disconnect( false );
3693 return SUCCESS;
3696 bool SwTrnsfrDdeLink::WriteData( SvStream& rStrm )
3698 if( !refObj.is() || !FindDocShell() )
3699 return false;
3701 rtl_TextEncoding eEncoding = DDE_TXT_ENCODING;
3702 const OString aAppNm(OUStringToOString(
3703 Application::GetAppName(), eEncoding));
3704 const OString aTopic(OUStringToOString(
3705 pDocShell->GetTitle(SFX_TITLE_FULLNAME), eEncoding));
3706 const OString aName(OUStringToOString(sName, eEncoding));
3708 std::unique_ptr<sal_Char[]> pMem(new sal_Char[ aAppNm.getLength() + aTopic.getLength() + aName.getLength() + 4 ]);
3710 sal_Int32 nLen = aAppNm.getLength();
3711 memcpy( pMem.get(), aAppNm.getStr(), nLen );
3712 pMem[ nLen++ ] = 0;
3713 memcpy( pMem.get() + nLen, aTopic.getStr(), aTopic.getLength() );
3714 nLen = nLen + aTopic.getLength();
3715 pMem[ nLen++ ] = 0;
3716 memcpy( pMem.get() + nLen, aName.getStr(), aName.getLength() );
3717 nLen = nLen + aName.getLength();
3718 pMem[ nLen++ ] = 0;
3719 pMem[ nLen++ ] = 0;
3721 rStrm.WriteBytes( pMem.get(), nLen );
3722 pMem.reset();
3724 IDocumentMarkAccess* const pMarkAccess = pDocShell->GetDoc()->getIDocumentMarkAccess();
3725 IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->findMark(sName);
3726 if(ppMark != pMarkAccess->getAllMarksEnd()
3727 && IDocumentMarkAccess::GetType(**ppMark) != IDocumentMarkAccess::MarkType::BOOKMARK)
3729 // the mark is still a DdeBookmark
3730 // we replace it with a Bookmark, so it will get saved etc.
3731 ::sw::mark::IMark* const pMark = ppMark->get();
3732 ::sfx2::SvLinkSource* p = refObj.get();
3733 SwServerObject& rServerObject = dynamic_cast<SwServerObject&>(*p);
3735 // collecting state of old mark
3736 SwPaM aPaM(pMark->GetMarkStart());
3737 *aPaM.GetPoint() = pMark->GetMarkStart();
3738 if(pMark->IsExpanded())
3740 aPaM.SetMark();
3741 *aPaM.GetMark() = pMark->GetMarkEnd();
3743 OUString sMarkName = pMark->GetName();
3745 // remove mark
3746 rServerObject.SetNoServer(); // this removes the connection between SwServerObject and mark
3747 // N.B. ppMark was not loaded from file and cannot have xml:id
3748 pMarkAccess->deleteMark(ppMark);
3750 // recreate as Bookmark
3751 ::sw::mark::IMark* const pNewMark = pMarkAccess->makeMark(
3752 aPaM,
3753 sMarkName,
3754 IDocumentMarkAccess::MarkType::BOOKMARK,
3755 ::sw::mark::InsertMode::New);
3756 rServerObject.SetDdeBookmark(*pNewMark);
3759 bDelBookmrk = false;
3760 return true;
3763 void SwTrnsfrDdeLink::Disconnect( bool bRemoveDataAdvise )
3765 // don't accept DataChanged anymore, when already in Disconnect!
3766 // (DTOR from Bookmark sends a DataChanged!)
3767 bool bOldDisconnect = bInDisconnect;
3768 bInDisconnect = true;
3770 // destroy the unused bookmark again (without Undo!)?
3771 if( bDelBookmrk && refObj.is() && FindDocShell() )
3773 SwDoc* pDoc = pDocShell->GetDoc();
3774 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
3776 // #i58448#
3777 Link<bool,void> aSavedOle2Link( pDoc->GetOle2Link() );
3778 pDoc->SetOle2Link( Link<bool,void>() );
3780 bool bIsModified = pDoc->getIDocumentState().IsModified();
3782 IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
3783 pMarkAccess->deleteMark(pMarkAccess->findMark(sName));
3785 if( !bIsModified )
3786 pDoc->getIDocumentState().ResetModified();
3787 // #i58448#
3788 pDoc->SetOle2Link( aSavedOle2Link );
3790 bDelBookmrk = false;
3793 if( refObj.is() )
3795 refObj->SetUpdateTimeout( nOldTimeOut );
3796 refObj->RemoveConnectAdvise( this );
3797 if( bRemoveDataAdvise )
3798 // in a DataChanged the SelectionObject must NEVER be deleted
3799 // is already handled by the base class
3800 // (ADVISEMODE_ONLYONCE!!!!)
3801 // but always in normal Disconnect!
3802 refObj->RemoveAllDataAdvise( this );
3803 refObj.clear();
3805 bInDisconnect = bOldDisconnect;
3808 bool SwTrnsfrDdeLink::FindDocShell()
3810 SfxObjectShell* pTmpSh = SfxObjectShell::GetFirst( checkSfxObjectShell<SwDocShell> );
3811 while( pTmpSh )
3813 if( pTmpSh == pDocShell ) // that's what we want to have
3815 if( pDocShell->GetDoc() )
3816 return true;
3817 break; // the Doc is not there anymore, so leave!
3819 pTmpSh = SfxObjectShell::GetNext( *pTmpSh, checkSfxObjectShell<SwDocShell> );
3822 pDocShell = nullptr;
3823 return false;
3826 void SwTrnsfrDdeLink::Closed()
3828 if( !bInDisconnect && refObj.is() )
3830 refObj->RemoveAllDataAdvise( this );
3831 refObj->RemoveConnectAdvise( this );
3832 refObj.clear();
3836 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */