summaryrefslogtreecommitdiffstats
path: root/sw/source/filter/basflt/shellio.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/basflt/shellio.cxx')
-rw-r--r--sw/source/filter/basflt/shellio.cxx940
1 files changed, 940 insertions, 0 deletions
diff --git a/sw/source/filter/basflt/shellio.cxx b/sw/source/filter/basflt/shellio.cxx
new file mode 100644
index 0000000000..888213aa9d
--- /dev/null
+++ b/sw/source/filter/basflt/shellio.cxx
@@ -0,0 +1,940 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+#include <osl/diagnose.h>
+#include <tools/date.hxx>
+#include <tools/time.hxx>
+#include <svl/fstathelper.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/docfilt.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/paperinf.hxx>
+#include <o3tl/deleter.hxx>
+#include <officecfg/Office/Writer.hxx>
+#include <node.hxx>
+#include <docary.hxx>
+#include <fmtanchr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtpdsc.hxx>
+#include <shellio.hxx>
+#include <iodetect.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentLinksAdministration.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentState.hxx>
+#include <IDocumentStylePoolAccess.hxx>
+#include <pam.hxx>
+#include <editsh.hxx>
+#include <undobj.hxx>
+#include <swundo.hxx>
+#include <swtable.hxx>
+#include <tblafmt.hxx>
+#include <tblsel.hxx>
+#include <pagedesc.hxx>
+#include <poolfmt.hxx>
+#include <fltini.hxx>
+#include <docsh.hxx>
+#include <ndole.hxx>
+#include <ndtxt.hxx>
+#include <redline.hxx>
+#include <swerror.h>
+#include <pausethreadstarting.hxx>
+#include <frameformats.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+static bool sw_MergePortions(SwNode* pNode, void *)
+{
+ if (pNode->IsTextNode())
+ {
+ pNode->GetTextNode()->FileLoadedInitHints();
+ }
+ return true;
+}
+
+void SwAsciiOptions::Reset()
+{
+ m_sFont.clear();
+ m_eCRLF_Flag = GetSystemLineEnd();
+ m_eCharSet = ::osl_getThreadTextEncoding();
+ m_nLanguage = LANGUAGE_SYSTEM;
+ m_bIncludeBOM = true;
+ m_bIncludeHidden = !utl::ConfigManager::IsFuzzing() && officecfg::Office::Writer::FilterFlags::ASCII::IncludeHiddenText::get();
+}
+
+ErrCodeMsg SwReader::Read( const Reader& rOptions )
+{
+ // copy variables
+ Reader* po = const_cast<Reader*>(&rOptions);
+ po->m_pStream = mpStrm;
+ po->m_pStorage = mpStg;
+ po->m_xStorage = mxStg;
+ po->m_bInsertMode = nullptr != mpCursor;
+ po->m_bSkipImages = mbSkipImages;
+
+ // if a Medium is selected, get its Stream
+ if( nullptr != (po->m_pMedium = mpMedium ) &&
+ !po->SetStrmStgPtr() )
+ {
+ po->SetReadUTF8( false );
+ po->SetBlockMode( false );
+ po->SetOrganizerMode( false );
+ po->SetIgnoreHTMLComments( false );
+ return ERR_SWG_FILE_FORMAT_ERROR;
+ }
+
+ ErrCodeMsg nError = ERRCODE_NONE;
+
+ GetDoc();
+
+ // while reading, do not call OLE-Modified
+ Link<bool,void> aOLELink( mxDoc->GetOle2Link() );
+ mxDoc->SetOle2Link( Link<bool,void>() );
+
+ mxDoc->SetInReading( true );
+ mxDoc->SetInXMLImport( dynamic_cast< XMLReader* >(po) != nullptr );
+ mxDoc->SetInWriterfilterImport(mpMedium && mpMedium->GetFilter()
+ && (mpMedium->GetFilter()->GetUserData() == FILTER_RTF
+ || mpMedium->GetFilter()->GetUserData() == sRtfWH
+ || mpMedium->GetFilter()->GetUserData() == FILTER_DOCX));
+
+ SwPaM *pPam;
+ if( mpCursor )
+ pPam = mpCursor;
+ else
+ {
+ // if the Reader was not called by a Shell, create a PaM ourselves
+ pPam = new SwPaM( mxDoc->GetNodes().GetEndOfContent(), SwNodeOffset(-1) );
+ // For Web documents the default template was set already by InitNew,
+ // unless the filter is not HTML,
+ // or a SetTemplateName was called in ConvertFrom.
+ if( !mxDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) || ReadHTML != po || !po->mxTemplate.is() )
+ po->SetTemplate( *mxDoc );
+ }
+
+ // Pams are connected like rings; stop when we return to the 1st element
+ SwPaM *pEnd = pPam;
+
+ bool bReadPageDescs = false;
+ bool const bDocUndo = mxDoc->GetIDocumentUndoRedo().DoesUndo();
+ bool bSaveUndo = bDocUndo && mpCursor;
+ if( bSaveUndo )
+ {
+ // the reading of the page template cannot be undone!
+ bReadPageDescs = po->m_aOption.IsPageDescs();
+ if( bReadPageDescs )
+ {
+ bSaveUndo = false;
+ mxDoc->GetIDocumentUndoRedo().DelAllUndoObj();
+ }
+ else
+ {
+ mxDoc->GetIDocumentUndoRedo().ClearRedo();
+ mxDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSDOKUMENT, nullptr );
+ }
+ }
+ mxDoc->GetIDocumentUndoRedo().DoUndo(false);
+
+ RedlineFlags eOld = mxDoc->getIDocumentRedlineAccess().GetRedlineFlags();
+ RedlineFlags ePostReadRedlineFlags( RedlineFlags::Ignore );
+
+ // Array of FlyFormats
+ SwFrameFormatsV aFlyFrameArr;
+ // only read templates? then ignore multi selection!
+ bool bFormatsOnly = po->m_aOption.IsFormatsOnly();
+
+ while( true )
+ {
+ std::unique_ptr<SwUndoInsDoc> pUndo;
+ if( bSaveUndo )
+ pUndo.reset(new SwUndoInsDoc( *pPam ));
+
+ mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::Ignore );
+
+ std::optional<SwPaM> pUndoPam;
+ if( bDocUndo || mpCursor )
+ {
+ // set Pam to the previous node, so that it is not also moved
+ const SwNode& rTmp = pPam->GetPoint()->GetNode();
+ pUndoPam.emplace( rTmp, rTmp, SwNodeOffset(0), SwNodeOffset(-1) );
+ }
+
+ // store for now all Fly's
+ if( mpCursor )
+ {
+ aFlyFrameArr.insert( aFlyFrameArr.end(), mxDoc->GetSpzFrameFormats()->begin(),
+ mxDoc->GetSpzFrameFormats()->end() );
+ }
+
+ const sal_Int32 nSttContent = pPam->GetPoint()->GetContentIndex();
+
+ // make sure the End position is correct for all Readers
+ SwContentNode* pCNd = pPam->GetPointContentNode();
+ sal_Int32 nEndContent = pCNd ? pCNd->Len() - nSttContent : 0;
+ SwNodeIndex aEndPos( pPam->GetPoint()->GetNode(), 1 );
+
+ mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
+
+ nError = po->Read( *mxDoc, msBaseURL, *pPam, maFileName );
+
+ // an ODF document may contain redline mode in settings.xml; save it!
+ ePostReadRedlineFlags = mxDoc->getIDocumentRedlineAccess().GetRedlineFlags();
+
+ mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::Ignore );
+
+ if( ! nError.IsError() ) // set the End position already
+ {
+ --aEndPos;
+ pCNd = aEndPos.GetNode().GetContentNode();
+ if( !pCNd && nullptr == ( pCNd = SwNodes::GoPrevious( &aEndPos ) ))
+ pCNd = mxDoc->GetNodes().GoNext( &aEndPos );
+
+ const sal_Int32 nLen = pCNd->Len();
+ if( nLen < nEndContent )
+ nEndContent = 0;
+ else
+ nEndContent = nLen - nEndContent;
+ pPam->GetPoint()->Assign( *pCNd, nEndContent );
+
+ const SwStartNode* pTableBoxStart = pCNd->FindTableBoxStartNode();
+ if ( pTableBoxStart )
+ {
+ SwTableBox* pBox = pTableBoxStart->GetTableBox();
+ if ( pBox )
+ {
+ mxDoc->ChkBoxNumFormat( *pBox, true );
+ }
+ }
+ }
+
+ if( mpCursor )
+ {
+ *pUndoPam->GetMark() = *pPam->GetPoint();
+ pUndoPam->GetPoint()->Adjust(SwNodeOffset(1));
+ SwNode& rNd = pUndoPam->GetPointNode();
+ if( rNd.IsContentNode() )
+ pUndoPam->GetPoint()->SetContent( nSttContent );
+
+ bool bChkHeaderFooter = rNd.FindHeaderStartNode() ||
+ rNd.FindFooterStartNode();
+
+ // search all new Fly's, and store them as individual Undo Objects
+ for( sw::FrameFormats<sw::SpzFrameFormat*>::size_type n = 0; n < mxDoc->GetSpzFrameFormats()->size(); ++n )
+ {
+ SwFrameFormat* pFrameFormat = (*mxDoc->GetSpzFrameFormats())[ n ];
+ const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
+ // ok, here IsAlive is a misnomer...
+ if (!aFlyFrameArr.IsAlive(pFrameFormat))
+ {
+ if ( (RndStdIds::FLY_AT_PAGE == rAnchor.GetAnchorId())
+ // TODO: why is this not handled via SetInsertRange?
+ || SwUndoInserts::IsCreateUndoForNewFly(rAnchor,
+ pUndoPam->GetPoint()->GetNodeIndex(),
+ pUndoPam->GetMark()->GetNodeIndex()))
+ {
+ if( bChkHeaderFooter &&
+ (RndStdIds::FLY_AT_PARA == rAnchor.GetAnchorId()) &&
+ RES_DRAWFRMFMT == pFrameFormat->Which() )
+ {
+ // DrawObjects are not allowed in Headers/Footers!
+ pFrameFormat->DelFrames();
+ mxDoc->DelFrameFormat( pFrameFormat );
+ --n;
+ }
+ else
+ {
+ if( bSaveUndo )
+ {
+ mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
+ // UGLY: temp. enable undo
+ mxDoc->GetIDocumentUndoRedo().DoUndo(true);
+ mxDoc->GetIDocumentUndoRedo().AppendUndo(
+ std::make_unique<SwUndoInsLayFormat>( pFrameFormat, SwNodeOffset(0), 0 ) );
+ mxDoc->GetIDocumentUndoRedo().DoUndo(false);
+ mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::Ignore );
+ }
+ if( pFrameFormat->HasWriterListeners() )
+ {
+ // Draw-Objects create a Frame when being inserted; thus delete them
+ pFrameFormat->DelFrames();
+ }
+
+ if (RndStdIds::FLY_AT_PAGE == rAnchor.GetAnchorId())
+ {
+ if( !rAnchor.GetAnchorNode() )
+ {
+ pFrameFormat->MakeFrames();
+ }
+ else if( mpCursor )
+ {
+ mxDoc->SetContainsAtPageObjWithContentAnchor( true );
+ }
+ }
+ else
+ pFrameFormat->MakeFrames();
+ }
+ }
+ }
+ }
+ aFlyFrameArr.clear();
+
+ mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
+ if( mxDoc->getIDocumentRedlineAccess().IsRedlineOn() )
+ mxDoc->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( RedlineType::Insert, *pUndoPam ), true);
+ else
+ mxDoc->getIDocumentRedlineAccess().SplitRedline( *pUndoPam );
+ mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::Ignore );
+ }
+ if( bSaveUndo )
+ {
+ mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
+ pUndo->SetInsertRange( *pUndoPam, false );
+ // UGLY: temp. enable undo
+ mxDoc->GetIDocumentUndoRedo().DoUndo(true);
+ mxDoc->GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
+ mxDoc->GetIDocumentUndoRedo().DoUndo(false);
+ mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::Ignore );
+ }
+
+ pUndoPam.reset();
+
+ pPam = pPam->GetNext();
+ if( pPam == pEnd )
+ break;
+
+ // only read templates? then ignore multi selection! Bug 68593
+ if( bFormatsOnly )
+ break;
+
+ /*
+ * !!! The Status of the Stream has to be reset directly. !!!
+ * When Seeking, the current Status-, EOF- and bad-Bit is set;
+ * nobody knows why
+ */
+ if( mpStrm )
+ {
+ mpStrm->Seek(0);
+ mpStrm->ResetError();
+ }
+ }
+
+ // fdo#52028: ODF file import does not result in MergePortions being called
+ // for every attribute, since that would be inefficient. So call it here.
+ // This is only necessary for formats that may contain RSIDs (ODF,MSO).
+ // It's too hard to figure out which nodes were inserted in Insert->File
+ // case (redlines, flys, footnotes, header/footer) so just do every node.
+ mxDoc->GetNodes().ForEach(&sw_MergePortions);
+
+ mxDoc->SetInReading( false );
+ mxDoc->SetInXMLImport( false );
+ mxDoc->SetInWriterfilterImport(false);
+
+ mxDoc->InvalidateNumRules();
+ mxDoc->UpdateNumRule();
+ mxDoc->ChkCondColls();
+ mxDoc->SetAllUniqueFlyNames();
+ // Clear unassigned cell styles, because they aren't needed anymore.
+ mxDoc->GetCellStyles().clear();
+
+ mxDoc->GetIDocumentUndoRedo().DoUndo(bDocUndo);
+ if (!bReadPageDescs && bSaveUndo )
+ {
+ mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
+ mxDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSDOKUMENT, nullptr );
+ mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::Ignore );
+ }
+
+ // delete Pam if it was created only for reading
+ if( !mpCursor )
+ {
+ delete pPam; // open a new one
+
+ // #i42634# Moved common code of SwReader::Read() and
+ // SwDocShell::UpdateLinks() to new SwDoc::UpdateLinks():
+ // ATM still with Update
+ mxDoc->getIDocumentLinksAdministration().UpdateLinks();
+
+ // not insert: set the redline mode read from settings.xml
+ eOld = ePostReadRedlineFlags & ~RedlineFlags::Ignore;
+
+ mxDoc->getIDocumentFieldsAccess().SetFieldsDirty(true, nullptr, SwNodeOffset(0));
+ }
+
+ mxDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
+ mxDoc->SetOle2Link( aOLELink );
+
+ if( mpCursor ) // the document is now modified
+ mxDoc->getIDocumentState().SetModified();
+ // #i38810# - If links have been updated, the document
+ // have to be modified. During update of links the OLE link at the document
+ // isn't set. Thus, the document's modified state has to be set again after
+ // the OLE link is restored - see above <mxDoc->SetOle2Link( aOLELink )>.
+ if ( mxDoc->getIDocumentLinksAdministration().LinksUpdated() )
+ {
+ mxDoc->getIDocumentState().SetModified();
+ }
+
+ po->SetReadUTF8( false );
+ po->SetBlockMode( false );
+ po->SetOrganizerMode( false );
+ po->SetIgnoreHTMLComments( false );
+
+ return nError;
+}
+
+
+SwReader::SwReader(SfxMedium& rMedium, OUString aFileName, SwDoc *pDocument)
+ : SwDocFac(pDocument), mpStrm(nullptr), mpMedium(&rMedium), mpCursor(nullptr),
+ maFileName(std::move(aFileName)), mbSkipImages(false)
+{
+ SetBaseURL( rMedium.GetBaseURL() );
+ SetSkipImages( rMedium.IsSkipImages() );
+}
+
+
+// Read into an existing document
+SwReader::SwReader(SvStream& rStrm, OUString aFileName, const OUString& rBaseURL, SwPaM& rPam)
+ : SwDocFac(&rPam.GetDoc()), mpStrm(&rStrm), mpMedium(nullptr), mpCursor(&rPam),
+ maFileName(std::move(aFileName)), mbSkipImages(false)
+{
+ SetBaseURL( rBaseURL );
+}
+
+SwReader::SwReader(SfxMedium& rMedium, OUString aFileName, SwPaM& rPam)
+ : SwDocFac(&rPam.GetDoc()), mpStrm(nullptr), mpMedium(&rMedium),
+ mpCursor(&rPam), maFileName(std::move(aFileName)), mbSkipImages(false)
+{
+ SetBaseURL( rMedium.GetBaseURL() );
+}
+
+SwReader::SwReader( uno::Reference < embed::XStorage > xStg, OUString aFilename, SwPaM &rPam )
+ : SwDocFac(&rPam.GetDoc()), mpStrm(nullptr), mxStg( std::move(xStg) ), mpMedium(nullptr), mpCursor(&rPam), maFileName(std::move(aFilename)), mbSkipImages(false)
+{
+}
+
+Reader::Reader()
+ : m_aDateStamp( Date::EMPTY ),
+ m_aTimeStamp( tools::Time::EMPTY ),
+ m_aCheckDateTime( DateTime::EMPTY ),
+ m_pStream(nullptr), m_pMedium(nullptr), m_bInsertMode(false),
+ m_bTemplateBrowseMode(false), m_bReadUTF8(false), m_bBlockMode(false), m_bOrganizerMode(false),
+ m_bHasAskTemplateName(false), m_bIgnoreHTMLComments(false), m_bSkipImages(false)
+{
+}
+
+Reader::~Reader()
+{
+}
+
+OUString Reader::GetTemplateName(SwDoc& /*rDoc*/) const
+{
+ return OUString();
+}
+
+// load the Filter template, set and release
+SwDoc* Reader::GetTemplateDoc(SwDoc& rDoc)
+{
+ if( !m_bHasAskTemplateName )
+ {
+ SetTemplateName( GetTemplateName(rDoc) );
+ m_bHasAskTemplateName = true;
+ }
+
+ if( m_aTemplateName.isEmpty() )
+ ClearTemplate();
+ else
+ {
+ INetURLObject aTDir( m_aTemplateName );
+ const OUString aFileName = aTDir.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ OSL_ENSURE( !aTDir.HasError(), "No absolute path for template name!" );
+ DateTime aCurrDateTime( DateTime::SYSTEM );
+ bool bLoad = false;
+
+ // if the template is already loaded, check once-a-minute if it has changed
+ if( !mxTemplate.is() || aCurrDateTime >= m_aCheckDateTime )
+ {
+ Date aTstDate( Date::EMPTY );
+ tools::Time aTstTime( tools::Time::EMPTY );
+ if( FStatHelper::GetModifiedDateTimeOfFile(
+ aTDir.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
+ &aTstDate, &aTstTime ) &&
+ ( !mxTemplate.is() || m_aDateStamp != aTstDate || m_aTimeStamp != aTstTime ))
+ {
+ bLoad = true;
+ m_aDateStamp = aTstDate;
+ m_aTimeStamp = aTstTime;
+ }
+
+ // only one minute later check if it has changed
+ m_aCheckDateTime = aCurrDateTime;
+ m_aCheckDateTime += tools::Time( 0, 1 );
+ }
+
+ if (bLoad)
+ {
+ ClearTemplate();
+ OSL_ENSURE( !mxTemplate.is(), "Who holds the template doc?" );
+
+ // If the writer module is not installed,
+ // we cannot create a SwDocShell. We could create a
+ // SwWebDocShell however, because this exists always
+ // for the help.
+ SvtModuleOptions aModuleOptions;
+ if (aModuleOptions.IsWriter())
+ {
+ SwDocShell *pDocSh = new SwDocShell(SfxObjectCreateMode::INTERNAL);
+ SfxObjectShellLock xDocSh = pDocSh;
+ if (pDocSh->DoInitNew())
+ {
+ mxTemplate = pDocSh->GetDoc();
+ mxTemplate->SetOle2Link( Link<bool,void>() );
+ // always FALSE
+ mxTemplate->GetIDocumentUndoRedo().DoUndo( false );
+ mxTemplate->getIDocumentSettingAccess().set(DocumentSettingId::BROWSE_MODE, m_bTemplateBrowseMode );
+ mxTemplate->RemoveAllFormatLanguageDependencies();
+
+ ReadXML->SetOrganizerMode( true );
+ SfxMedium aMedium( aFileName, StreamMode::NONE );
+ SwReader aRdr( aMedium, OUString(), mxTemplate.get() );
+ aRdr.Read( *ReadXML );
+ ReadXML->SetOrganizerMode( false );
+ }
+ }
+ }
+
+ OSL_ENSURE( !mxTemplate.is() || FStatHelper::IsDocument( aFileName ) || m_aTemplateName=="$$Dummy$$",
+ "TemplatePtr but no template exist!" );
+ }
+
+ return mxTemplate.get();
+}
+
+bool Reader::SetTemplate( SwDoc& rDoc )
+{
+ bool bRet = false;
+
+ GetTemplateDoc(rDoc);
+ if( mxTemplate.is() )
+ {
+ rDoc.RemoveAllFormatLanguageDependencies();
+ rDoc.ReplaceStyles( *mxTemplate );
+ rDoc.getIDocumentFieldsAccess().SetFixFields(nullptr);
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+void Reader::ClearTemplate()
+{
+ mxTemplate.clear();
+}
+
+void Reader::SetTemplateName( const OUString& rDir )
+{
+ if( !rDir.isEmpty() && m_aTemplateName != rDir )
+ {
+ ClearTemplate();
+ m_aTemplateName = rDir;
+ }
+}
+
+void Reader::MakeHTMLDummyTemplateDoc()
+{
+ ClearTemplate();
+ mxTemplate = new SwDoc;
+ mxTemplate->getIDocumentSettingAccess().set(DocumentSettingId::BROWSE_MODE, m_bTemplateBrowseMode );
+ mxTemplate->getIDocumentDeviceAccess().getPrinter( true );
+ mxTemplate->RemoveAllFormatLanguageDependencies();
+ m_aCheckDateTime = Date( 1, 1, 2300 ); // year 2300 should be sufficient
+ m_aTemplateName = "$$Dummy$$";
+}
+
+// Users that do not need to open these Streams / Storages,
+// have to override this method
+bool Reader::SetStrmStgPtr()
+{
+ OSL_ENSURE( m_pMedium, "Where is the Media??" );
+
+ if( m_pMedium->IsStorage() )
+ {
+ if( SwReaderType::Storage & GetReaderType() )
+ {
+ m_xStorage = m_pMedium->GetStorage();
+ return true;
+ }
+ }
+ else
+ {
+ m_pStream = m_pMedium->GetInStream();
+ if ( m_pStream && SotStorage::IsStorageFile(m_pStream) && (SwReaderType::Storage & GetReaderType()) )
+ {
+ m_pStorage = new SotStorage( *m_pStream );
+ m_pStream = nullptr;
+ }
+ else if ( !(SwReaderType::Stream & GetReaderType()) )
+ {
+ m_pStream = nullptr;
+ return false;
+ }
+
+ return true;
+ }
+ return false;
+}
+
+SwReaderType Reader::GetReaderType()
+{
+ return SwReaderType::Stream;
+}
+
+void Reader::SetFltName( const OUString& )
+{
+}
+
+void Reader::ResetFrameFormatAttrs( SfxItemSet &rFrameSet )
+{
+ rFrameSet.Put( SvxLRSpaceItem(RES_LR_SPACE) );
+ rFrameSet.Put( SvxULSpaceItem(RES_UL_SPACE) );
+ rFrameSet.Put( SvxBoxItem(RES_BOX) );
+}
+
+void Reader::ResetFrameFormats( SwDoc& rDoc )
+{
+ sal_uInt16 const s_ids[3] = {
+ RES_POOLFRM_FRAME, RES_POOLFRM_GRAPHIC, RES_POOLFRM_OLE
+ };
+ for (sal_uInt16 i : s_ids)
+ {
+ SwFrameFormat *const pFrameFormat = rDoc.getIDocumentStylePoolAccess().GetFrameFormatFromPool( i );
+
+ pFrameFormat->ResetFormatAttr( RES_LR_SPACE );
+ pFrameFormat->ResetFormatAttr( RES_UL_SPACE );
+ pFrameFormat->ResetFormatAttr( RES_BOX );
+ }
+}
+
+ // read the sections of the document, which is equal to the medium.
+ // returns the count of it
+size_t Reader::GetSectionList(SfxMedium&, std::vector<OUString>&) const
+{
+ return 0;
+}
+
+bool SwReader::HasGlossaries( const Reader& rOptions )
+{
+ // copy variables
+ Reader* po = const_cast<Reader*>(&rOptions);
+ po->m_pStream = mpStrm;
+ po->m_pStorage = mpStg;
+ po->m_bInsertMode = false;
+
+ // if a Medium is selected, get its Stream
+ bool bRet = false;
+ if( nullptr == (po->m_pMedium = mpMedium ) || po->SetStrmStgPtr() )
+ bRet = po->HasGlossaries();
+ return bRet;
+}
+
+bool SwReader::ReadGlossaries( const Reader& rOptions,
+ SwTextBlocks& rBlocks, bool bSaveRelFiles )
+{
+ // copy variables
+ Reader* po = const_cast<Reader*>(&rOptions);
+ po->m_pStream = mpStrm;
+ po->m_pStorage = mpStg;
+ po->m_bInsertMode = false;
+
+ // if a Medium is selected, get its Stream
+ bool bRet = false;
+ if( nullptr == (po->m_pMedium = mpMedium ) || po->SetStrmStgPtr() )
+ bRet = po->ReadGlossaries( rBlocks, bSaveRelFiles );
+ return bRet;
+}
+
+bool Reader::HasGlossaries() const
+{
+ return false;
+}
+
+bool Reader::ReadGlossaries( SwTextBlocks&, bool ) const
+{
+ return false;
+}
+
+SwReaderType StgReader::GetReaderType()
+{
+ return SwReaderType::Storage;
+}
+
+/*
+ * Writer
+ */
+
+/*
+ * Constructors, Destructors are inline (inc/shellio.hxx).
+ */
+
+SwWriter::SwWriter(SvStream& rStrm, SwCursorShell &rShell, bool bInWriteAll)
+ : m_pStrm(&rStrm), m_pMedium(nullptr), m_pOutPam(nullptr), m_pShell(&rShell),
+ m_rDoc(*rShell.GetDoc()), m_bWriteAll(bInWriteAll)
+{
+}
+
+SwWriter::SwWriter(SvStream& rStrm,SwDoc &rDocument)
+ : m_pStrm(&rStrm), m_pMedium(nullptr), m_pOutPam(nullptr), m_pShell(nullptr), m_rDoc(rDocument),
+ m_bWriteAll(true)
+{
+}
+
+SwWriter::SwWriter(SvStream& rStrm, SwPaM& rPam, bool bInWriteAll)
+ : m_pStrm(&rStrm), m_pMedium(nullptr), m_pOutPam(&rPam), m_pShell(nullptr),
+ m_rDoc(rPam.GetDoc()), m_bWriteAll(bInWriteAll)
+{
+}
+
+SwWriter::SwWriter( uno::Reference < embed::XStorage > xStg, SwDoc &rDocument)
+ : m_pStrm(nullptr), m_xStg( std::move(xStg) ), m_pMedium(nullptr), m_pOutPam(nullptr), m_pShell(nullptr), m_rDoc(rDocument), m_bWriteAll(true)
+{
+}
+
+SwWriter::SwWriter(SfxMedium& rMedium, SwCursorShell &rShell, bool bInWriteAll)
+ : m_pStrm(nullptr), m_pMedium(&rMedium), m_pOutPam(nullptr), m_pShell(&rShell),
+ m_rDoc(*rShell.GetDoc()), m_bWriteAll(bInWriteAll)
+{
+}
+
+SwWriter::SwWriter(SfxMedium& rMedium, SwDoc &rDocument)
+ : m_pStrm(nullptr), m_pMedium(&rMedium), m_pOutPam(nullptr), m_pShell(nullptr), m_rDoc(rDocument),
+ m_bWriteAll(true)
+{
+}
+
+static bool isFlyNode(const SwPaM& pam)
+{
+ return *pam.GetPoint() == *pam.GetMark()
+ && (pam.GetPoint()->GetNode().IsOLENode() || pam.GetPoint()->GetNode().IsGrfNode());
+}
+
+ErrCodeMsg SwWriter::Write( WriterRef const & rxWriter, const OUString* pRealFileName )
+{
+ // #i73788#
+ SwPauseThreadStarting aPauseThreadStarting;
+
+ bool bHasMark = false;
+ std::shared_ptr<SwUnoCursor> pTempCursor;
+ SwPaM * pPam;
+
+ rtl::Reference<SwDoc> xDoc;
+
+ if ( m_pShell && !m_bWriteAll && m_pShell->IsTableMode() )
+ {
+ m_bWriteAll = true;
+ xDoc = new SwDoc;
+
+ // Copy parts of a table:
+ // Create a table with the width of the original and copy the selected cells.
+ // The sizes are corrected by ratio.
+
+ // search the layout for cells
+ SwSelBoxes aBoxes;
+ GetTableSel( *m_pShell, aBoxes );
+ const SwTableNode* pTableNd = static_cast<const SwTableNode*>(aBoxes[0]->GetSttNd()->StartOfSectionNode());
+ SwNodeIndex aIdx( xDoc->GetNodes().GetEndOfExtras(), 2 );
+ SwContentNode *pNd = aIdx.GetNode().GetContentNode();
+ OSL_ENSURE( pNd, "Node not found" );
+ SwPosition aPos( aIdx, pNd, 0 );
+ pTableNd->GetTable().MakeCopy( *xDoc, aPos, aBoxes );
+ }
+
+ if( !m_bWriteAll && ( m_pShell || m_pOutPam ))
+ {
+ if( m_pShell )
+ pPam = m_pShell->GetCursor();
+ else
+ pPam = m_pOutPam;
+
+ SwPaM *pEnd = pPam;
+
+ // 1st round: Check if there is a selection
+ do
+ {
+ bHasMark = pPam->HasMark() || isFlyNode(*pPam);
+ pPam = pPam->GetNext();
+ } while (!bHasMark && pPam != pEnd);
+
+ // if there is no selection, select the whole document
+ if(!bHasMark)
+ {
+ if( m_pShell )
+ {
+ m_pShell->Push();
+ m_pShell->SttEndDoc(true);
+ m_pShell->SetMark();
+ m_pShell->SttEndDoc(false);
+ }
+ else
+ {
+ pPam = new SwPaM( *pPam, pPam );
+ pPam->Move( fnMoveBackward, GoInDoc );
+ pPam->SetMark();
+ pPam->Move( fnMoveForward, GoInDoc );
+ }
+ }
+ // pPam is still the current Cursor !!
+ }
+ else
+ {
+ // no Shell or write-everything -> create a Pam
+ SwDoc* pOutDoc = xDoc.is() ? xDoc.get() : &m_rDoc;
+ pTempCursor = pOutDoc->CreateUnoCursor(
+ SwPosition(pOutDoc->GetNodes().GetEndOfContent()), false);
+ pPam = pTempCursor.get();
+ if( pOutDoc->IsClipBoard() )
+ {
+ pPam->Move( fnMoveBackward, GoInDoc );
+ pPam->SetMark();
+ pPam->Move( fnMoveForward, GoInDoc );
+ }
+ else
+ {
+ pPam->SetMark();
+ pPam->Move( fnMoveBackward, GoInDoc );
+ }
+ }
+
+ rxWriter->m_bWriteAll = m_bWriteAll;
+ SwDoc* pOutDoc = xDoc.is() ? xDoc.get() : &m_rDoc;
+
+ // If the default PageDesc has still the initial value,
+ // (e.g. if no printer was set) then set it to DIN A4.
+ // #i37248# - Modifications are only allowed at a new document.
+ // <pOutDoc> contains a new document, if <xDoc> is set - see above.
+ if ( xDoc.is() && !pOutDoc->getIDocumentDeviceAccess().getPrinter( false ) )
+ {
+ const SwPageDesc& rPgDsc = pOutDoc->GetPageDesc( 0 );
+ //const SwPageDesc& rPgDsc = *pOutDoc->GetPageDescFromPool( RES_POOLPAGE_STANDARD );
+ const SwFormatFrameSize& rSz = rPgDsc.GetMaster().GetFrameSize();
+ // Clipboard-Document is always created w/o printer; thus the
+ // default PageDesc is always aug LONG_MAX !! Set then to DIN A4
+ if( LONG_MAX == rSz.GetHeight() || LONG_MAX == rSz.GetWidth() )
+ {
+ SwPageDesc aNew( rPgDsc );
+ SwFormatFrameSize aNewSz( rSz );
+ Size a4(SvxPaperInfo::GetPaperSize( PAPER_A4 ));
+ aNewSz.SetHeight( a4.Width() );
+ aNewSz.SetWidth( a4.Height() );
+ aNew.GetMaster().SetFormatAttr( aNewSz );
+ pOutDoc->ChgPageDesc( 0, aNew );
+ }
+ }
+
+ bool bLockedView(false);
+ SwEditShell* pESh = pOutDoc->GetEditShell();
+ if( pESh )
+ {
+ bLockedView = pESh->IsViewLocked();
+ pESh->LockView( true ); //lock visible section
+ pESh->StartAllAction();
+ }
+
+ std::unique_ptr<PurgeGuard, o3tl::default_delete<PurgeGuard>> xGuard(new PurgeGuard(*pOutDoc));
+
+ pOutDoc->SetInWriting(true);
+ ErrCodeMsg nError = ERRCODE_NONE;
+ if( m_pMedium )
+ nError = rxWriter->Write( *pPam, *m_pMedium, pRealFileName );
+ else if( m_pStrm )
+ nError = rxWriter->Write( *pPam, *m_pStrm, pRealFileName );
+ else if( m_xStg.is() )
+ nError = rxWriter->Write( *pPam, m_xStg, pRealFileName );
+ pOutDoc->SetInWriting(false);
+
+ xGuard.reset();
+
+ if( pESh )
+ {
+ pESh->EndAllAction();
+ pESh->LockView( bLockedView );
+ }
+
+ // If the selection was only created for printing, reset the old cursor before returning
+ if( !m_bWriteAll && ( m_pShell || m_pOutPam ))
+ {
+ if(!bHasMark)
+ {
+ if( m_pShell )
+ m_pShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
+ else
+ delete pPam;
+ }
+ }
+ else
+ {
+ // Everything was written successfully? Tell the document!
+ if ( !nError.IsError() && !xDoc.is() )
+ {
+ m_rDoc.getIDocumentState().ResetModified();
+ // #i38810# - reset also flag, that indicates updated links
+ m_rDoc.getIDocumentLinksAdministration().SetLinksUpdated( false );
+ }
+ }
+
+ if ( xDoc.is() )
+ {
+ pTempCursor.reset();
+ xDoc.clear();
+ m_bWriteAll = false;
+ }
+
+ return nError;
+}
+
+bool SetHTMLTemplate( SwDoc & rDoc )
+{
+ // get template name of the Sfx-HTML-Filter !!!
+ if( !ReadHTML->GetTemplateDoc(rDoc) )
+ ReadHTML->MakeHTMLDummyTemplateDoc();
+
+ bool bRet = ReadHTML->SetTemplate( rDoc );
+
+ SwNodes& rNds = rDoc.GetNodes();
+ SwNodeIndex aIdx( rNds.GetEndOfExtras(), 1 );
+ SwContentNode* pCNd = rNds.GoNext( &aIdx );
+ if( pCNd )
+ {
+ pCNd->SetAttr
+ ( SwFormatPageDesc(rDoc.getIDocumentStylePoolAccess().GetPageDescFromPool(RES_POOLPAGE_HTML, false) ) );
+ pCNd->ChgFormatColl( rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TEXT, false ));
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */