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