android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / filter / basflt / shellio.cxx
blob66251f1685258f6bab49ae363fa4782b05098844
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <hintids.hxx>
21 #include <osl/diagnose.h>
22 #include <tools/date.hxx>
23 #include <tools/time.hxx>
24 #include <svl/fstathelper.hxx>
25 #include <unotools/configmgr.hxx>
26 #include <unotools/moduleoptions.hxx>
27 #include <sfx2/docfile.hxx>
28 #include <sfx2/docfilt.hxx>
29 #include <editeng/lrspitem.hxx>
30 #include <editeng/ulspitem.hxx>
31 #include <editeng/boxitem.hxx>
32 #include <editeng/paperinf.hxx>
33 #include <o3tl/deleter.hxx>
34 #include <officecfg/Office/Writer.hxx>
35 #include <node.hxx>
36 #include <docary.hxx>
37 #include <fmtanchr.hxx>
38 #include <fmtfsize.hxx>
39 #include <fmtpdsc.hxx>
40 #include <shellio.hxx>
41 #include <iodetect.hxx>
42 #include <doc.hxx>
43 #include <IDocumentUndoRedo.hxx>
44 #include <IDocumentSettingAccess.hxx>
45 #include <IDocumentDeviceAccess.hxx>
46 #include <IDocumentLinksAdministration.hxx>
47 #include <IDocumentRedlineAccess.hxx>
48 #include <IDocumentFieldsAccess.hxx>
49 #include <IDocumentState.hxx>
50 #include <IDocumentStylePoolAccess.hxx>
51 #include <pam.hxx>
52 #include <editsh.hxx>
53 #include <undobj.hxx>
54 #include <swundo.hxx>
55 #include <swtable.hxx>
56 #include <tblafmt.hxx>
57 #include <tblsel.hxx>
58 #include <pagedesc.hxx>
59 #include <poolfmt.hxx>
60 #include <fltini.hxx>
61 #include <docsh.hxx>
62 #include <ndole.hxx>
63 #include <ndtxt.hxx>
64 #include <redline.hxx>
65 #include <swerror.h>
66 #include <pausethreadstarting.hxx>
67 #include <frameformats.hxx>
68 #include <utility>
70 using namespace ::com::sun::star;
72 static bool sw_MergePortions(SwNode* pNode, void *)
74 if (pNode->IsTextNode())
76 pNode->GetTextNode()->FileLoadedInitHints();
78 return true;
81 void SwAsciiOptions::Reset()
83 m_sFont.clear();
84 m_eCRLF_Flag = GetSystemLineEnd();
85 m_eCharSet = ::osl_getThreadTextEncoding();
86 m_nLanguage = LANGUAGE_SYSTEM;
87 m_bIncludeBOM = true;
88 m_bIncludeHidden = !utl::ConfigManager::IsFuzzing() && officecfg::Office::Writer::FilterFlags::ASCII::IncludeHiddenText::get();
91 ErrCode SwReader::Read( const Reader& rOptions )
93 // copy variables
94 Reader* po = const_cast<Reader*>(&rOptions);
95 po->m_pStream = mpStrm;
96 po->m_pStorage = mpStg;
97 po->m_xStorage = mxStg;
98 po->m_bInsertMode = nullptr != mpCursor;
99 po->m_bSkipImages = mbSkipImages;
101 // if a Medium is selected, get its Stream
102 if( nullptr != (po->m_pMedium = mpMedium ) &&
103 !po->SetStrmStgPtr() )
105 po->SetReadUTF8( false );
106 po->SetBlockMode( false );
107 po->SetOrganizerMode( false );
108 po->SetIgnoreHTMLComments( false );
109 return ERR_SWG_FILE_FORMAT_ERROR;
112 ErrCode nError = ERRCODE_NONE;
114 GetDoc();
116 // while reading, do not call OLE-Modified
117 Link<bool,void> aOLELink( mxDoc->GetOle2Link() );
118 mxDoc->SetOle2Link( Link<bool,void>() );
120 mxDoc->SetInReading( true );
121 mxDoc->SetInXMLImport( dynamic_cast< XMLReader* >(po) != nullptr );
122 mxDoc->SetInWriterfilterImport(mpMedium && mpMedium->GetFilter()
123 && (mpMedium->GetFilter()->GetUserData() == FILTER_RTF
124 || mpMedium->GetFilter()->GetUserData() == sRtfWH
125 || mpMedium->GetFilter()->GetUserData() == FILTER_DOCX));
127 SwPaM *pPam;
128 if( mpCursor )
129 pPam = mpCursor;
130 else
132 // if the Reader was not called by a Shell, create a PaM ourselves
133 pPam = new SwPaM( mxDoc->GetNodes().GetEndOfContent(), SwNodeOffset(-1) );
134 // For Web documents the default template was set already by InitNew,
135 // unless the filter is not HTML,
136 // or a SetTemplateName was called in ConvertFrom.
137 if( !mxDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) || ReadHTML != po || !po->mxTemplate.is() )
138 po->SetTemplate( *mxDoc );
141 // Pams are connected like rings; stop when we return to the 1st element
142 SwPaM *pEnd = pPam;
144 bool bReadPageDescs = false;
145 bool const bDocUndo = mxDoc->GetIDocumentUndoRedo().DoesUndo();
146 bool bSaveUndo = bDocUndo && mpCursor;
147 if( bSaveUndo )
149 // the reading of the page template cannot be undone!
150 bReadPageDescs = po->m_aOption.IsPageDescs();
151 if( bReadPageDescs )
153 bSaveUndo = false;
154 mxDoc->GetIDocumentUndoRedo().DelAllUndoObj();
156 else
158 mxDoc->GetIDocumentUndoRedo().ClearRedo();
159 mxDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSDOKUMENT, nullptr );
162 mxDoc->GetIDocumentUndoRedo().DoUndo(false);
164 RedlineFlags eOld = mxDoc->getIDocumentRedlineAccess().GetRedlineFlags();
165 RedlineFlags ePostReadRedlineFlags( RedlineFlags::Ignore );
167 // Array of FlyFormats
168 SwFrameFormatsV aFlyFrameArr;
169 // only read templates? then ignore multi selection!
170 bool bFormatsOnly = po->m_aOption.IsFormatsOnly();
172 while( true )
174 std::unique_ptr<SwUndoInsDoc> pUndo;
175 if( bSaveUndo )
176 pUndo.reset(new SwUndoInsDoc( *pPam ));
178 mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::Ignore );
180 std::optional<SwPaM> pUndoPam;
181 if( bDocUndo || mpCursor )
183 // set Pam to the previous node, so that it is not also moved
184 const SwNode& rTmp = pPam->GetPoint()->GetNode();
185 pUndoPam.emplace( rTmp, rTmp, SwNodeOffset(0), SwNodeOffset(-1) );
188 // store for now all Fly's
189 if( mpCursor )
191 aFlyFrameArr.insert( aFlyFrameArr.end(), mxDoc->GetSpzFrameFormats()->begin(),
192 mxDoc->GetSpzFrameFormats()->end() );
195 const sal_Int32 nSttContent = pPam->GetPoint()->GetContentIndex();
197 // make sure the End position is correct for all Readers
198 SwContentNode* pCNd = pPam->GetPointContentNode();
199 sal_Int32 nEndContent = pCNd ? pCNd->Len() - nSttContent : 0;
200 SwNodeIndex aEndPos( pPam->GetPoint()->GetNode(), 1 );
202 mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
204 nError = po->Read( *mxDoc, msBaseURL, *pPam, maFileName );
206 // an ODF document may contain redline mode in settings.xml; save it!
207 ePostReadRedlineFlags = mxDoc->getIDocumentRedlineAccess().GetRedlineFlags();
209 mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::Ignore );
211 if( ! nError.IsError() ) // set the End position already
213 --aEndPos;
214 pCNd = aEndPos.GetNode().GetContentNode();
215 if( !pCNd && nullptr == ( pCNd = SwNodes::GoPrevious( &aEndPos ) ))
216 pCNd = mxDoc->GetNodes().GoNext( &aEndPos );
218 const sal_Int32 nLen = pCNd->Len();
219 if( nLen < nEndContent )
220 nEndContent = 0;
221 else
222 nEndContent = nLen - nEndContent;
223 pPam->GetPoint()->Assign( *pCNd, nEndContent );
225 const SwStartNode* pTableBoxStart = pCNd->FindTableBoxStartNode();
226 if ( pTableBoxStart )
228 SwTableBox* pBox = pTableBoxStart->GetTableBox();
229 if ( pBox )
231 mxDoc->ChkBoxNumFormat( *pBox, true );
236 if( mpCursor )
238 *pUndoPam->GetMark() = *pPam->GetPoint();
239 pUndoPam->GetPoint()->Adjust(SwNodeOffset(1));
240 SwNode& rNd = pUndoPam->GetPointNode();
241 if( rNd.IsContentNode() )
242 pUndoPam->GetPoint()->SetContent( nSttContent );
244 bool bChkHeaderFooter = rNd.FindHeaderStartNode() ||
245 rNd.FindFooterStartNode();
247 // search all new Fly's, and store them as individual Undo Objects
248 for( sw::FrameFormats<sw::SpzFrameFormat*>::size_type n = 0; n < mxDoc->GetSpzFrameFormats()->size(); ++n )
250 SwFrameFormat* pFrameFormat = (*mxDoc->GetSpzFrameFormats())[ n ];
251 const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
252 // ok, here IsAlive is a misnomer...
253 if (!aFlyFrameArr.IsAlive(pFrameFormat))
255 if ( (RndStdIds::FLY_AT_PAGE == rAnchor.GetAnchorId())
256 // TODO: why is this not handled via SetInsertRange?
257 || SwUndoInserts::IsCreateUndoForNewFly(rAnchor,
258 pUndoPam->GetPoint()->GetNodeIndex(),
259 pUndoPam->GetMark()->GetNodeIndex()))
261 if( bChkHeaderFooter &&
262 (RndStdIds::FLY_AT_PARA == rAnchor.GetAnchorId()) &&
263 RES_DRAWFRMFMT == pFrameFormat->Which() )
265 // DrawObjects are not allowed in Headers/Footers!
266 pFrameFormat->DelFrames();
267 mxDoc->DelFrameFormat( pFrameFormat );
268 --n;
270 else
272 if( bSaveUndo )
274 mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
275 // UGLY: temp. enable undo
276 mxDoc->GetIDocumentUndoRedo().DoUndo(true);
277 mxDoc->GetIDocumentUndoRedo().AppendUndo(
278 std::make_unique<SwUndoInsLayFormat>( pFrameFormat, SwNodeOffset(0), 0 ) );
279 mxDoc->GetIDocumentUndoRedo().DoUndo(false);
280 mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::Ignore );
282 if( pFrameFormat->HasWriterListeners() )
284 // Draw-Objects create a Frame when being inserted; thus delete them
285 pFrameFormat->DelFrames();
288 if (RndStdIds::FLY_AT_PAGE == rAnchor.GetAnchorId())
290 if( !rAnchor.GetAnchorNode() )
292 pFrameFormat->MakeFrames();
294 else if( mpCursor )
296 mxDoc->SetContainsAtPageObjWithContentAnchor( true );
299 else
300 pFrameFormat->MakeFrames();
305 aFlyFrameArr.clear();
307 mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
308 if( mxDoc->getIDocumentRedlineAccess().IsRedlineOn() )
309 mxDoc->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( RedlineType::Insert, *pUndoPam ), true);
310 else
311 mxDoc->getIDocumentRedlineAccess().SplitRedline( *pUndoPam );
312 mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::Ignore );
314 if( bSaveUndo )
316 mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
317 pUndo->SetInsertRange( *pUndoPam, false );
318 // UGLY: temp. enable undo
319 mxDoc->GetIDocumentUndoRedo().DoUndo(true);
320 mxDoc->GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
321 mxDoc->GetIDocumentUndoRedo().DoUndo(false);
322 mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::Ignore );
325 pUndoPam.reset();
327 pPam = pPam->GetNext();
328 if( pPam == pEnd )
329 break;
331 // only read templates? then ignore multi selection! Bug 68593
332 if( bFormatsOnly )
333 break;
336 * !!! The Status of the Stream has to be reset directly. !!!
337 * When Seeking, the current Status-, EOF- and bad-Bit is set;
338 * nobody knows why
340 if( mpStrm )
342 mpStrm->Seek(0);
343 mpStrm->ResetError();
347 // fdo#52028: ODF file import does not result in MergePortions being called
348 // for every attribute, since that would be inefficient. So call it here.
349 // This is only necessary for formats that may contain RSIDs (ODF,MSO).
350 // It's too hard to figure out which nodes were inserted in Insert->File
351 // case (redlines, flys, footnotes, header/footer) so just do every node.
352 mxDoc->GetNodes().ForEach(&sw_MergePortions);
354 mxDoc->SetInReading( false );
355 mxDoc->SetInXMLImport( false );
356 mxDoc->SetInWriterfilterImport(false);
358 mxDoc->InvalidateNumRules();
359 mxDoc->UpdateNumRule();
360 mxDoc->ChkCondColls();
361 mxDoc->SetAllUniqueFlyNames();
362 // Clear unassigned cell styles, because they aren't needed anymore.
363 mxDoc->GetCellStyles().clear();
365 mxDoc->GetIDocumentUndoRedo().DoUndo(bDocUndo);
366 if (!bReadPageDescs && bSaveUndo )
368 mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
369 mxDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSDOKUMENT, nullptr );
370 mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::Ignore );
373 // delete Pam if it was created only for reading
374 if( !mpCursor )
376 delete pPam; // open a new one
378 // #i42634# Moved common code of SwReader::Read() and
379 // SwDocShell::UpdateLinks() to new SwDoc::UpdateLinks():
380 // ATM still with Update
381 mxDoc->getIDocumentLinksAdministration().UpdateLinks();
383 // not insert: set the redline mode read from settings.xml
384 eOld = ePostReadRedlineFlags & ~RedlineFlags::Ignore;
386 mxDoc->getIDocumentFieldsAccess().SetFieldsDirty(true, nullptr, SwNodeOffset(0));
389 mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
390 mxDoc->SetOle2Link( aOLELink );
392 if( mpCursor ) // the document is now modified
393 mxDoc->getIDocumentState().SetModified();
394 // #i38810# - If links have been updated, the document
395 // have to be modified. During update of links the OLE link at the document
396 // isn't set. Thus, the document's modified state has to be set again after
397 // the OLE link is restored - see above <mxDoc->SetOle2Link( aOLELink )>.
398 if ( mxDoc->getIDocumentLinksAdministration().LinksUpdated() )
400 mxDoc->getIDocumentState().SetModified();
403 po->SetReadUTF8( false );
404 po->SetBlockMode( false );
405 po->SetOrganizerMode( false );
406 po->SetIgnoreHTMLComments( false );
408 return nError;
412 SwReader::SwReader(SfxMedium& rMedium, OUString aFileName, SwDoc *pDocument)
413 : SwDocFac(pDocument), mpStrm(nullptr), mpMedium(&rMedium), mpCursor(nullptr),
414 maFileName(std::move(aFileName)), mbSkipImages(false)
416 SetBaseURL( rMedium.GetBaseURL() );
417 SetSkipImages( rMedium.IsSkipImages() );
421 // Read into an existing document
422 SwReader::SwReader(SvStream& rStrm, OUString aFileName, const OUString& rBaseURL, SwPaM& rPam)
423 : SwDocFac(&rPam.GetDoc()), mpStrm(&rStrm), mpMedium(nullptr), mpCursor(&rPam),
424 maFileName(std::move(aFileName)), mbSkipImages(false)
426 SetBaseURL( rBaseURL );
429 SwReader::SwReader(SfxMedium& rMedium, OUString aFileName, SwPaM& rPam)
430 : SwDocFac(&rPam.GetDoc()), mpStrm(nullptr), mpMedium(&rMedium),
431 mpCursor(&rPam), maFileName(std::move(aFileName)), mbSkipImages(false)
433 SetBaseURL( rMedium.GetBaseURL() );
436 SwReader::SwReader( uno::Reference < embed::XStorage > xStg, OUString aFilename, SwPaM &rPam )
437 : SwDocFac(&rPam.GetDoc()), mpStrm(nullptr), mxStg( std::move(xStg) ), mpMedium(nullptr), mpCursor(&rPam), maFileName(std::move(aFilename)), mbSkipImages(false)
441 Reader::Reader()
442 : m_aDateStamp( Date::EMPTY ),
443 m_aTimeStamp( tools::Time::EMPTY ),
444 m_aCheckDateTime( DateTime::EMPTY ),
445 m_pStream(nullptr), m_pMedium(nullptr), m_bInsertMode(false),
446 m_bTemplateBrowseMode(false), m_bReadUTF8(false), m_bBlockMode(false), m_bOrganizerMode(false),
447 m_bHasAskTemplateName(false), m_bIgnoreHTMLComments(false), m_bSkipImages(false)
451 Reader::~Reader()
455 OUString Reader::GetTemplateName(SwDoc& /*rDoc*/) const
457 return OUString();
460 // load the Filter template, set and release
461 SwDoc* Reader::GetTemplateDoc(SwDoc& rDoc)
463 if( !m_bHasAskTemplateName )
465 SetTemplateName( GetTemplateName(rDoc) );
466 m_bHasAskTemplateName = true;
469 if( m_aTemplateName.isEmpty() )
470 ClearTemplate();
471 else
473 INetURLObject aTDir( m_aTemplateName );
474 const OUString aFileName = aTDir.GetMainURL( INetURLObject::DecodeMechanism::NONE );
475 OSL_ENSURE( !aTDir.HasError(), "No absolute path for template name!" );
476 DateTime aCurrDateTime( DateTime::SYSTEM );
477 bool bLoad = false;
479 // if the template is already loaded, check once-a-minute if it has changed
480 if( !mxTemplate.is() || aCurrDateTime >= m_aCheckDateTime )
482 Date aTstDate( Date::EMPTY );
483 tools::Time aTstTime( tools::Time::EMPTY );
484 if( FStatHelper::GetModifiedDateTimeOfFile(
485 aTDir.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
486 &aTstDate, &aTstTime ) &&
487 ( !mxTemplate.is() || m_aDateStamp != aTstDate || m_aTimeStamp != aTstTime ))
489 bLoad = true;
490 m_aDateStamp = aTstDate;
491 m_aTimeStamp = aTstTime;
494 // only one minute later check if it has changed
495 m_aCheckDateTime = aCurrDateTime;
496 m_aCheckDateTime += tools::Time( 0, 1 );
499 if (bLoad)
501 ClearTemplate();
502 OSL_ENSURE( !mxTemplate.is(), "Who holds the template doc?" );
504 // If the writer module is not installed,
505 // we cannot create a SwDocShell. We could create a
506 // SwWebDocShell however, because this exists always
507 // for the help.
508 SvtModuleOptions aModuleOptions;
509 if (aModuleOptions.IsWriter())
511 SwDocShell *pDocSh = new SwDocShell(SfxObjectCreateMode::INTERNAL);
512 SfxObjectShellLock xDocSh = pDocSh;
513 if (pDocSh->DoInitNew())
515 mxTemplate = pDocSh->GetDoc();
516 mxTemplate->SetOle2Link( Link<bool,void>() );
517 // always FALSE
518 mxTemplate->GetIDocumentUndoRedo().DoUndo( false );
519 mxTemplate->getIDocumentSettingAccess().set(DocumentSettingId::BROWSE_MODE, m_bTemplateBrowseMode );
520 mxTemplate->RemoveAllFormatLanguageDependencies();
522 ReadXML->SetOrganizerMode( true );
523 SfxMedium aMedium( aFileName, StreamMode::NONE );
524 SwReader aRdr( aMedium, OUString(), mxTemplate.get() );
525 aRdr.Read( *ReadXML );
526 ReadXML->SetOrganizerMode( false );
531 OSL_ENSURE( !mxTemplate.is() || FStatHelper::IsDocument( aFileName ) || m_aTemplateName=="$$Dummy$$",
532 "TemplatePtr but no template exist!" );
535 return mxTemplate.get();
538 bool Reader::SetTemplate( SwDoc& rDoc )
540 bool bRet = false;
542 GetTemplateDoc(rDoc);
543 if( mxTemplate.is() )
545 rDoc.RemoveAllFormatLanguageDependencies();
546 rDoc.ReplaceStyles( *mxTemplate );
547 rDoc.getIDocumentFieldsAccess().SetFixFields(nullptr);
548 bRet = true;
551 return bRet;
554 void Reader::ClearTemplate()
556 mxTemplate.clear();
559 void Reader::SetTemplateName( const OUString& rDir )
561 if( !rDir.isEmpty() && m_aTemplateName != rDir )
563 ClearTemplate();
564 m_aTemplateName = rDir;
568 void Reader::MakeHTMLDummyTemplateDoc()
570 ClearTemplate();
571 mxTemplate = new SwDoc;
572 mxTemplate->getIDocumentSettingAccess().set(DocumentSettingId::BROWSE_MODE, m_bTemplateBrowseMode );
573 mxTemplate->getIDocumentDeviceAccess().getPrinter( true );
574 mxTemplate->RemoveAllFormatLanguageDependencies();
575 m_aCheckDateTime = Date( 1, 1, 2300 ); // year 2300 should be sufficient
576 m_aTemplateName = "$$Dummy$$";
579 // Users that do not need to open these Streams / Storages,
580 // have to override this method
581 bool Reader::SetStrmStgPtr()
583 OSL_ENSURE( m_pMedium, "Where is the Media??" );
585 if( m_pMedium->IsStorage() )
587 if( SwReaderType::Storage & GetReaderType() )
589 m_xStorage = m_pMedium->GetStorage();
590 return true;
593 else
595 m_pStream = m_pMedium->GetInStream();
596 if ( m_pStream && SotStorage::IsStorageFile(m_pStream) && (SwReaderType::Storage & GetReaderType()) )
598 m_pStorage = new SotStorage( *m_pStream );
599 m_pStream = nullptr;
601 else if ( !(SwReaderType::Stream & GetReaderType()) )
603 m_pStream = nullptr;
604 return false;
607 return true;
609 return false;
612 SwReaderType Reader::GetReaderType()
614 return SwReaderType::Stream;
617 void Reader::SetFltName( const OUString& )
621 void Reader::ResetFrameFormatAttrs( SfxItemSet &rFrameSet )
623 rFrameSet.Put( SvxLRSpaceItem(RES_LR_SPACE) );
624 rFrameSet.Put( SvxULSpaceItem(RES_UL_SPACE) );
625 rFrameSet.Put( SvxBoxItem(RES_BOX) );
628 void Reader::ResetFrameFormats( SwDoc& rDoc )
630 sal_uInt16 const s_ids[3] = {
631 RES_POOLFRM_FRAME, RES_POOLFRM_GRAPHIC, RES_POOLFRM_OLE
633 for (sal_uInt16 i : s_ids)
635 SwFrameFormat *const pFrameFormat = rDoc.getIDocumentStylePoolAccess().GetFrameFormatFromPool( i );
637 pFrameFormat->ResetFormatAttr( RES_LR_SPACE );
638 pFrameFormat->ResetFormatAttr( RES_UL_SPACE );
639 pFrameFormat->ResetFormatAttr( RES_BOX );
643 // read the sections of the document, which is equal to the medium.
644 // returns the count of it
645 size_t Reader::GetSectionList(SfxMedium&, std::vector<OUString>&) const
647 return 0;
650 bool SwReader::HasGlossaries( const Reader& rOptions )
652 // copy variables
653 Reader* po = const_cast<Reader*>(&rOptions);
654 po->m_pStream = mpStrm;
655 po->m_pStorage = mpStg;
656 po->m_bInsertMode = false;
658 // if a Medium is selected, get its Stream
659 bool bRet = false;
660 if( nullptr == (po->m_pMedium = mpMedium ) || po->SetStrmStgPtr() )
661 bRet = po->HasGlossaries();
662 return bRet;
665 bool SwReader::ReadGlossaries( const Reader& rOptions,
666 SwTextBlocks& rBlocks, bool bSaveRelFiles )
668 // copy variables
669 Reader* po = const_cast<Reader*>(&rOptions);
670 po->m_pStream = mpStrm;
671 po->m_pStorage = mpStg;
672 po->m_bInsertMode = false;
674 // if a Medium is selected, get its Stream
675 bool bRet = false;
676 if( nullptr == (po->m_pMedium = mpMedium ) || po->SetStrmStgPtr() )
677 bRet = po->ReadGlossaries( rBlocks, bSaveRelFiles );
678 return bRet;
681 bool Reader::HasGlossaries() const
683 return false;
686 bool Reader::ReadGlossaries( SwTextBlocks&, bool ) const
688 return false;
691 SwReaderType StgReader::GetReaderType()
693 return SwReaderType::Storage;
697 * Writer
701 * Constructors, Destructors are inline (inc/shellio.hxx).
704 SwWriter::SwWriter(SvStream& rStrm, SwCursorShell &rShell, bool bInWriteAll)
705 : m_pStrm(&rStrm), m_pMedium(nullptr), m_pOutPam(nullptr), m_pShell(&rShell),
706 m_rDoc(*rShell.GetDoc()), m_bWriteAll(bInWriteAll)
710 SwWriter::SwWriter(SvStream& rStrm,SwDoc &rDocument)
711 : m_pStrm(&rStrm), m_pMedium(nullptr), m_pOutPam(nullptr), m_pShell(nullptr), m_rDoc(rDocument),
712 m_bWriteAll(true)
716 SwWriter::SwWriter(SvStream& rStrm, SwPaM& rPam, bool bInWriteAll)
717 : m_pStrm(&rStrm), m_pMedium(nullptr), m_pOutPam(&rPam), m_pShell(nullptr),
718 m_rDoc(rPam.GetDoc()), m_bWriteAll(bInWriteAll)
722 SwWriter::SwWriter( uno::Reference < embed::XStorage > xStg, SwDoc &rDocument)
723 : m_pStrm(nullptr), m_xStg( std::move(xStg) ), m_pMedium(nullptr), m_pOutPam(nullptr), m_pShell(nullptr), m_rDoc(rDocument), m_bWriteAll(true)
727 SwWriter::SwWriter(SfxMedium& rMedium, SwCursorShell &rShell, bool bInWriteAll)
728 : m_pStrm(nullptr), m_pMedium(&rMedium), m_pOutPam(nullptr), m_pShell(&rShell),
729 m_rDoc(*rShell.GetDoc()), m_bWriteAll(bInWriteAll)
733 SwWriter::SwWriter(SfxMedium& rMedium, SwDoc &rDocument)
734 : m_pStrm(nullptr), m_pMedium(&rMedium), m_pOutPam(nullptr), m_pShell(nullptr), m_rDoc(rDocument),
735 m_bWriteAll(true)
739 static bool isFlyNode(const SwPaM& pam)
741 return *pam.GetPoint() == *pam.GetMark()
742 && (pam.GetPoint()->GetNode().IsOLENode() || pam.GetPoint()->GetNode().IsGrfNode());
745 ErrCode SwWriter::Write( WriterRef const & rxWriter, const OUString* pRealFileName )
747 // #i73788#
748 SwPauseThreadStarting aPauseThreadStarting;
750 bool bHasMark = false;
751 std::shared_ptr<SwUnoCursor> pTempCursor;
752 SwPaM * pPam;
754 rtl::Reference<SwDoc> xDoc;
756 if ( m_pShell && !m_bWriteAll && m_pShell->IsTableMode() )
758 m_bWriteAll = true;
759 xDoc = new SwDoc;
761 // Copy parts of a table:
762 // Create a table with the width of the original and copy the selected cells.
763 // The sizes are corrected by ratio.
765 // search the layout for cells
766 SwSelBoxes aBoxes;
767 GetTableSel( *m_pShell, aBoxes );
768 const SwTableNode* pTableNd = static_cast<const SwTableNode*>(aBoxes[0]->GetSttNd()->StartOfSectionNode());
769 SwNodeIndex aIdx( xDoc->GetNodes().GetEndOfExtras(), 2 );
770 SwContentNode *pNd = aIdx.GetNode().GetContentNode();
771 OSL_ENSURE( pNd, "Node not found" );
772 SwPosition aPos( aIdx, pNd, 0 );
773 pTableNd->GetTable().MakeCopy( *xDoc, aPos, aBoxes );
776 if( !m_bWriteAll && ( m_pShell || m_pOutPam ))
778 if( m_pShell )
779 pPam = m_pShell->GetCursor();
780 else
781 pPam = m_pOutPam;
783 SwPaM *pEnd = pPam;
785 // 1st round: Check if there is a selection
788 bHasMark = pPam->HasMark() || isFlyNode(*pPam);
789 pPam = pPam->GetNext();
790 } while (!bHasMark && pPam != pEnd);
792 // if there is no selection, select the whole document
793 if(!bHasMark)
795 if( m_pShell )
797 m_pShell->Push();
798 m_pShell->SttEndDoc(true);
799 m_pShell->SetMark();
800 m_pShell->SttEndDoc(false);
802 else
804 pPam = new SwPaM( *pPam, pPam );
805 pPam->Move( fnMoveBackward, GoInDoc );
806 pPam->SetMark();
807 pPam->Move( fnMoveForward, GoInDoc );
810 // pPam is still the current Cursor !!
812 else
814 // no Shell or write-everything -> create a Pam
815 SwDoc* pOutDoc = xDoc.is() ? xDoc.get() : &m_rDoc;
816 pTempCursor = pOutDoc->CreateUnoCursor(
817 SwPosition(pOutDoc->GetNodes().GetEndOfContent()), false);
818 pPam = pTempCursor.get();
819 if( pOutDoc->IsClipBoard() )
821 pPam->Move( fnMoveBackward, GoInDoc );
822 pPam->SetMark();
823 pPam->Move( fnMoveForward, GoInDoc );
825 else
827 pPam->SetMark();
828 pPam->Move( fnMoveBackward, GoInDoc );
832 rxWriter->m_bWriteAll = m_bWriteAll;
833 SwDoc* pOutDoc = xDoc.is() ? xDoc.get() : &m_rDoc;
835 // If the default PageDesc has still the initial value,
836 // (e.g. if no printer was set) then set it to DIN A4.
837 // #i37248# - Modifications are only allowed at a new document.
838 // <pOutDoc> contains a new document, if <xDoc> is set - see above.
839 if ( xDoc.is() && !pOutDoc->getIDocumentDeviceAccess().getPrinter( false ) )
841 const SwPageDesc& rPgDsc = pOutDoc->GetPageDesc( 0 );
842 //const SwPageDesc& rPgDsc = *pOutDoc->GetPageDescFromPool( RES_POOLPAGE_STANDARD );
843 const SwFormatFrameSize& rSz = rPgDsc.GetMaster().GetFrameSize();
844 // Clipboard-Document is always created w/o printer; thus the
845 // default PageDesc is always aug LONG_MAX !! Set then to DIN A4
846 if( LONG_MAX == rSz.GetHeight() || LONG_MAX == rSz.GetWidth() )
848 SwPageDesc aNew( rPgDsc );
849 SwFormatFrameSize aNewSz( rSz );
850 Size a4(SvxPaperInfo::GetPaperSize( PAPER_A4 ));
851 aNewSz.SetHeight( a4.Width() );
852 aNewSz.SetWidth( a4.Height() );
853 aNew.GetMaster().SetFormatAttr( aNewSz );
854 pOutDoc->ChgPageDesc( 0, aNew );
858 bool bLockedView(false);
859 SwEditShell* pESh = pOutDoc->GetEditShell();
860 if( pESh )
862 bLockedView = pESh->IsViewLocked();
863 pESh->LockView( true ); //lock visible section
864 pESh->StartAllAction();
867 std::unique_ptr<PurgeGuard, o3tl::default_delete<PurgeGuard>> xGuard(new PurgeGuard(*pOutDoc));
869 pOutDoc->SetInWriting(true);
870 ErrCode nError = ERRCODE_NONE;
871 if( m_pMedium )
872 nError = rxWriter->Write( *pPam, *m_pMedium, pRealFileName );
873 else if( m_pStrm )
874 nError = rxWriter->Write( *pPam, *m_pStrm, pRealFileName );
875 else if( m_xStg.is() )
876 nError = rxWriter->Write( *pPam, m_xStg, pRealFileName );
877 pOutDoc->SetInWriting(false);
879 xGuard.reset();
881 if( pESh )
883 pESh->EndAllAction();
884 pESh->LockView( bLockedView );
887 // If the selection was only created for printing, reset the old cursor before returning
888 if( !m_bWriteAll && ( m_pShell || m_pOutPam ))
890 if(!bHasMark)
892 if( m_pShell )
893 m_pShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
894 else
895 delete pPam;
898 else
900 // Everything was written successfully? Tell the document!
901 if ( !nError.IsError() && !xDoc.is() )
903 m_rDoc.getIDocumentState().ResetModified();
904 // #i38810# - reset also flag, that indicates updated links
905 m_rDoc.getIDocumentLinksAdministration().SetLinksUpdated( false );
909 if ( xDoc.is() )
911 pTempCursor.reset();
912 xDoc.clear();
913 m_bWriteAll = false;
916 return nError;
919 bool SetHTMLTemplate( SwDoc & rDoc )
921 // get template name of the Sfx-HTML-Filter !!!
922 if( !ReadHTML->GetTemplateDoc(rDoc) )
923 ReadHTML->MakeHTMLDummyTemplateDoc();
925 bool bRet = ReadHTML->SetTemplate( rDoc );
927 SwNodes& rNds = rDoc.GetNodes();
928 SwNodeIndex aIdx( rNds.GetEndOfExtras(), 1 );
929 SwContentNode* pCNd = rNds.GoNext( &aIdx );
930 if( pCNd )
932 pCNd->SetAttr
933 ( SwFormatPageDesc(rDoc.getIDocumentStylePoolAccess().GetPageDescFromPool(RES_POOLPAGE_HTML, false) ) );
934 pCNd->ChgFormatColl( rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TEXT, false ));
937 return bRet;
940 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */