1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
37 #include <fmtanchr.hxx>
38 #include <fmtfsize.hxx>
39 #include <fmtpdsc.hxx>
40 #include <shellio.hxx>
41 #include <iodetect.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>
55 #include <swtable.hxx>
56 #include <tblafmt.hxx>
58 #include <pagedesc.hxx>
59 #include <poolfmt.hxx>
64 #include <redline.hxx>
66 #include <pausethreadstarting.hxx>
67 #include <frameformats.hxx>
70 using namespace ::com::sun::star
;
72 static bool sw_MergePortions(SwNode
* pNode
, void *)
74 if (pNode
->IsTextNode())
76 pNode
->GetTextNode()->FileLoadedInitHints();
81 void SwAsciiOptions::Reset()
84 m_eCRLF_Flag
= GetSystemLineEnd();
85 m_eCharSet
= ::osl_getThreadTextEncoding();
86 m_nLanguage
= LANGUAGE_SYSTEM
;
88 m_bIncludeHidden
= !utl::ConfigManager::IsFuzzing() && officecfg::Office::Writer::FilterFlags::ASCII::IncludeHiddenText::get();
91 ErrCode
SwReader::Read( const Reader
& rOptions
)
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
;
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
));
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
144 bool bReadPageDescs
= false;
145 bool const bDocUndo
= mxDoc
->GetIDocumentUndoRedo().DoesUndo();
146 bool bSaveUndo
= bDocUndo
&& mpCursor
;
149 // the reading of the page template cannot be undone!
150 bReadPageDescs
= po
->m_aOption
.IsPageDescs();
154 mxDoc
->GetIDocumentUndoRedo().DelAllUndoObj();
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();
174 std::unique_ptr
<SwUndoInsDoc
> pUndo
;
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
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
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
)
222 nEndContent
= nLen
- nEndContent
;
223 pPam
->GetPoint()->Assign( *pCNd
, nEndContent
);
225 const SwStartNode
* pTableBoxStart
= pCNd
->FindTableBoxStartNode();
226 if ( pTableBoxStart
)
228 SwTableBox
* pBox
= pTableBoxStart
->GetTableBox();
231 mxDoc
->ChkBoxNumFormat( *pBox
, true );
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
);
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();
296 mxDoc
->SetContainsAtPageObjWithContentAnchor( true );
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);
311 mxDoc
->getIDocumentRedlineAccess().SplitRedline( *pUndoPam
);
312 mxDoc
->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::Ignore
);
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
);
327 pPam
= pPam
->GetNext();
331 // only read templates? then ignore multi selection! Bug 68593
336 * !!! The Status of the Stream has to be reset directly. !!!
337 * When Seeking, the current Status-, EOF- and bad-Bit is set;
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
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 );
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)
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)
455 OUString
Reader::GetTemplateName(SwDoc
& /*rDoc*/) const
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() )
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
);
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
))
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 );
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
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>() );
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
)
542 GetTemplateDoc(rDoc
);
543 if( mxTemplate
.is() )
545 rDoc
.RemoveAllFormatLanguageDependencies();
546 rDoc
.ReplaceStyles( *mxTemplate
);
547 rDoc
.getIDocumentFieldsAccess().SetFixFields(nullptr);
554 void Reader::ClearTemplate()
559 void Reader::SetTemplateName( const OUString
& rDir
)
561 if( !rDir
.isEmpty() && m_aTemplateName
!= rDir
)
564 m_aTemplateName
= rDir
;
568 void Reader::MakeHTMLDummyTemplateDoc()
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();
595 m_pStream
= m_pMedium
->GetInStream();
596 if ( m_pStream
&& SotStorage::IsStorageFile(m_pStream
) && (SwReaderType::Storage
& GetReaderType()) )
598 m_pStorage
= new SotStorage( *m_pStream
);
601 else if ( !(SwReaderType::Stream
& GetReaderType()) )
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
650 bool SwReader::HasGlossaries( const Reader
& rOptions
)
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
660 if( nullptr == (po
->m_pMedium
= mpMedium
) || po
->SetStrmStgPtr() )
661 bRet
= po
->HasGlossaries();
665 bool SwReader::ReadGlossaries( const Reader
& rOptions
,
666 SwTextBlocks
& rBlocks
, bool bSaveRelFiles
)
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
676 if( nullptr == (po
->m_pMedium
= mpMedium
) || po
->SetStrmStgPtr() )
677 bRet
= po
->ReadGlossaries( rBlocks
, bSaveRelFiles
);
681 bool Reader::HasGlossaries() const
686 bool Reader::ReadGlossaries( SwTextBlocks
&, bool ) const
691 SwReaderType
StgReader::GetReaderType()
693 return SwReaderType::Storage
;
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
),
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
),
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
)
748 SwPauseThreadStarting aPauseThreadStarting
;
750 bool bHasMark
= false;
751 std::shared_ptr
<SwUnoCursor
> pTempCursor
;
754 rtl::Reference
<SwDoc
> xDoc
;
756 if ( m_pShell
&& !m_bWriteAll
&& m_pShell
->IsTableMode() )
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
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
))
779 pPam
= m_pShell
->GetCursor();
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
798 m_pShell
->SttEndDoc(true);
800 m_pShell
->SttEndDoc(false);
804 pPam
= new SwPaM( *pPam
, pPam
);
805 pPam
->Move( fnMoveBackward
, GoInDoc
);
807 pPam
->Move( fnMoveForward
, GoInDoc
);
810 // pPam is still the current Cursor !!
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
);
823 pPam
->Move( fnMoveForward
, GoInDoc
);
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();
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
;
872 nError
= rxWriter
->Write( *pPam
, *m_pMedium
, pRealFileName
);
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);
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
))
893 m_pShell
->Pop(SwCursorShell::PopMode::DeleteCurrent
);
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 );
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
);
933 ( SwFormatPageDesc(rDoc
.getIDocumentStylePoolAccess().GetPageDescFromPool(RES_POOLPAGE_HTML
, false) ) );
934 pCNd
->ChgFormatColl( rDoc
.getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TEXT
, false ));
940 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */