diff options
Diffstat (limited to 'sw/source/filter/basflt/shellio.cxx')
-rw-r--r-- | sw/source/filter/basflt/shellio.cxx | 940 |
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: */ |