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 <config_features.h>
23 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
24 #include <com/sun/star/frame/XModel.hpp>
25 #include <DocumentFieldsManager.hxx>
26 #include <DocumentSettingManager.hxx>
27 #include <DocumentDrawModelManager.hxx>
28 #include <DocumentTimerManager.hxx>
29 #include <DocumentDeviceManager.hxx>
30 #include <DocumentChartDataProviderManager.hxx>
31 #include <DocumentLinksAdministrationManager.hxx>
32 #include <DocumentListItemsManager.hxx>
33 #include <DocumentListsManager.hxx>
34 #include <DocumentOutlineNodesManager.hxx>
35 #include <DocumentContentOperationsManager.hxx>
36 #include <DocumentRedlineManager.hxx>
37 #include <DocumentStatisticsManager.hxx>
38 #include <DocumentStateManager.hxx>
39 #include <DocumentStylePoolManager.hxx>
40 #include <DocumentLayoutManager.hxx>
41 #include <DocumentExternalDataManager.hxx>
42 #include <UndoManager.hxx>
44 #include <hintids.hxx>
45 #include <tools/globname.hxx>
46 #include <svx/svxids.hrc>
48 #include <comphelper/random.hxx>
49 #include <tools/urlobj.hxx>
50 #include <tools/poly.hxx>
51 #include <tools/multisel.hxx>
52 #include <rtl/ustring.hxx>
53 #include <vcl/virdev.hxx>
54 #include <svl/itemiter.hxx>
55 #include <svl/poolitem.hxx>
56 #include <unotools/syslocale.hxx>
57 #include <sfx2/printer.hxx>
58 #include <editeng/keepitem.hxx>
59 #include <editeng/formatbreakitem.hxx>
60 #include <sfx2/linkmgr.hxx>
61 #include <svx/svdmodel.hxx>
62 #include <editeng/pbinitem.hxx>
63 #include <unotools/charclass.hxx>
64 #include <unotools/localedatawrapper.hxx>
65 #include <vcl/timer.hxx>
67 #include <swatrset.hxx>
68 #include <swmodule.hxx>
69 #include <fmtpdsc.hxx>
70 #include <fmtanchr.hxx>
71 #include <fmtrfmrk.hxx>
72 #include <fmtinfmt.hxx>
76 #include <txtinet.hxx>
77 #include <txtrfmrk.hxx>
79 #include <pagefrm.hxx>
80 #include <rootfrm.hxx>
81 #include <swtable.hxx>
85 #include <UndoCore.hxx>
86 #include <UndoInsert.hxx>
87 #include <UndoSplitMove.hxx>
88 #include <UndoTable.hxx>
89 #include <pagedesc.hxx>
95 #include <poolfmt.hxx>
97 #include <SwGrammarMarkUp.hxx>
98 #include <scriptinfo.hxx>
99 #include <acorrect.hxx>
100 #include <mdiexp.hxx>
101 #include <docstat.hxx>
102 #include <docary.hxx>
103 #include <redline.hxx>
104 #include <fldupde.hxx>
105 #include <swbaslnk.hxx>
106 #include <printdata.hxx>
108 #include <strings.hrc>
109 #include <SwUndoTOXChange.hxx>
110 #include <unocrsr.hxx>
112 #include <viewopt.hxx>
113 #include <docfld.hxx>
114 #include <docufld.hxx>
115 #include <viewsh.hxx>
116 #include <shellres.hxx>
117 #include <txtfrm.hxx>
118 #include <attrhint.hxx>
121 #include <wdocsh.hxx>
122 #include <prtopt.hxx>
127 #include <osl/diagnose.h>
128 #include <osl/interlck.h>
129 #include <vbahelper/vbaaccesshelper.hxx>
130 #include <calbck.hxx>
132 /* @@@MAINTAINABILITY-HORROR@@@
133 Probably unwanted dependency on SwDocShell
135 #include <layouter.hxx>
137 using namespace ::com::sun::star
;
139 sal_Int32
SwDoc::acquire()
141 assert(mReferenceCount
>= 0);
142 return osl_atomic_increment(&mReferenceCount
);
145 sal_Int32
SwDoc::release()
147 assert(mReferenceCount
>= 1);
148 auto x
= osl_atomic_decrement(&mReferenceCount
);
154 sal_Int32
SwDoc::getReferenceCount() const
156 assert(mReferenceCount
>= 0);
157 return mReferenceCount
;
160 ::sw::MetaFieldManager
& SwDoc::GetMetaFieldManager()
162 return *m_pMetaFieldManager
;
165 ::sw::UndoManager
& SwDoc::GetUndoManager()
167 return *m_pUndoManager
;
170 ::sw::UndoManager
const & SwDoc::GetUndoManager() const
172 return *m_pUndoManager
;
176 IDocumentUndoRedo
& SwDoc::GetIDocumentUndoRedo()
178 return *m_pUndoManager
;
181 IDocumentUndoRedo
const & SwDoc::GetIDocumentUndoRedo() const
183 return *m_pUndoManager
;
186 /* IDocumentDrawModelAccess */
187 IDocumentDrawModelAccess
const & SwDoc::getIDocumentDrawModelAccess() const
189 return GetDocumentDrawModelManager();
192 IDocumentDrawModelAccess
& SwDoc::getIDocumentDrawModelAccess()
194 return GetDocumentDrawModelManager();
197 ::sw::DocumentDrawModelManager
const & SwDoc::GetDocumentDrawModelManager() const
199 return *m_pDocumentDrawModelManager
;
202 ::sw::DocumentDrawModelManager
& SwDoc::GetDocumentDrawModelManager()
204 return *m_pDocumentDrawModelManager
;
207 /* IDocumentSettingAccess */
208 IDocumentSettingAccess
const & SwDoc::getIDocumentSettingAccess() const
210 return GetDocumentSettingManager();
213 IDocumentSettingAccess
& SwDoc::getIDocumentSettingAccess()
215 return GetDocumentSettingManager();
218 ::sw::DocumentSettingManager
& SwDoc::GetDocumentSettingManager()
220 return *m_pDocumentSettingManager
;
223 ::sw::DocumentSettingManager
const & SwDoc::GetDocumentSettingManager() const
225 return *m_pDocumentSettingManager
;
228 sal_uInt32
SwDoc::getRsid() const
233 void SwDoc::setRsid( sal_uInt32 nVal
)
235 static bool bHack
= (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != nullptr);
237 sal_uInt32 nIncrease
= 0;
240 // Increase the rsid with a random number smaller than 2^17. This way we
241 // expect to be able to edit a document 2^12 times before rsid overflows.
242 // start from 1 to ensure the new rsid is not the same
243 nIncrease
= comphelper::rng::uniform_uint_distribution(1, (1 << 17) - 1);
245 mnRsid
= nVal
+ nIncrease
;
248 sal_uInt32
SwDoc::getRsidRoot() const
253 void SwDoc::setRsidRoot( sal_uInt32 nVal
)
258 /* IDocumentChartDataProviderAccess */
259 IDocumentChartDataProviderAccess
const & SwDoc::getIDocumentChartDataProviderAccess() const
261 return *m_pDocumentChartDataProviderManager
;
264 IDocumentChartDataProviderAccess
& SwDoc::getIDocumentChartDataProviderAccess()
266 return *m_pDocumentChartDataProviderManager
;
269 // IDocumentDeviceAccess
270 IDocumentDeviceAccess
const & SwDoc::getIDocumentDeviceAccess() const
272 return *m_pDeviceAccess
;
275 IDocumentDeviceAccess
& SwDoc::getIDocumentDeviceAccess()
277 return *m_pDeviceAccess
;
280 //IDocumentTimerAccess
281 IDocumentTimerAccess
const & SwDoc::getIDocumentTimerAccess() const
283 return *m_pDocumentTimerManager
;
286 IDocumentTimerAccess
& SwDoc::getIDocumentTimerAccess()
288 return *m_pDocumentTimerManager
;
291 // IDocumentLinksAdministration
292 IDocumentLinksAdministration
const & SwDoc::getIDocumentLinksAdministration() const
294 return *m_pDocumentLinksAdministrationManager
;
297 IDocumentLinksAdministration
& SwDoc::getIDocumentLinksAdministration()
299 return *m_pDocumentLinksAdministrationManager
;
302 ::sw::DocumentLinksAdministrationManager
const & SwDoc::GetDocumentLinksAdministrationManager() const
304 return *m_pDocumentLinksAdministrationManager
;
307 ::sw::DocumentLinksAdministrationManager
& SwDoc::GetDocumentLinksAdministrationManager()
309 return *m_pDocumentLinksAdministrationManager
;
313 IDocumentListItems
const & SwDoc::getIDocumentListItems() const
315 return *m_pDocumentListItemsManager
;
319 IDocumentListItems
& SwDoc::getIDocumentListItems()
321 return *m_pDocumentListItemsManager
;
324 //IDocumentListsAccess
325 IDocumentListsAccess
const & SwDoc::getIDocumentListsAccess() const
327 return *m_pDocumentListsManager
;
330 IDocumentListsAccess
& SwDoc::getIDocumentListsAccess()
332 return *m_pDocumentListsManager
;
335 //IDocumentOutlinesNodes
336 IDocumentOutlineNodes
const & SwDoc::getIDocumentOutlineNodes() const
338 return *m_pDocumentOutlineNodesManager
;
341 IDocumentOutlineNodes
& SwDoc::getIDocumentOutlineNodes()
343 return *m_pDocumentOutlineNodesManager
;
346 //IDocumentContentOperations
347 IDocumentContentOperations
const & SwDoc::getIDocumentContentOperations() const
349 return *m_pDocumentContentOperationsManager
;
352 IDocumentContentOperations
& SwDoc::getIDocumentContentOperations()
354 return *m_pDocumentContentOperationsManager
;
357 ::sw::DocumentContentOperationsManager
const & SwDoc::GetDocumentContentOperationsManager() const
359 return *m_pDocumentContentOperationsManager
;
361 ::sw::DocumentContentOperationsManager
& SwDoc::GetDocumentContentOperationsManager()
363 return *m_pDocumentContentOperationsManager
;
366 //IDocumentRedlineAccess
367 IDocumentRedlineAccess
const & SwDoc::getIDocumentRedlineAccess() const
369 return *m_pDocumentRedlineManager
;
372 IDocumentRedlineAccess
& SwDoc::getIDocumentRedlineAccess()
374 return *m_pDocumentRedlineManager
;
377 ::sw::DocumentRedlineManager
const & SwDoc::GetDocumentRedlineManager() const
379 return *m_pDocumentRedlineManager
;
382 ::sw::DocumentRedlineManager
& SwDoc::GetDocumentRedlineManager()
384 return *m_pDocumentRedlineManager
;
387 //IDocumentFieldsAccess
389 IDocumentFieldsAccess
const & SwDoc::getIDocumentFieldsAccess() const
391 return *m_pDocumentFieldsManager
;
394 IDocumentFieldsAccess
& SwDoc::getIDocumentFieldsAccess()
396 return *m_pDocumentFieldsManager
;
399 ::sw::DocumentFieldsManager
& SwDoc::GetDocumentFieldsManager()
401 return *m_pDocumentFieldsManager
;
404 //IDocumentStatistics
405 IDocumentStatistics
const & SwDoc::getIDocumentStatistics() const
407 return *m_pDocumentStatisticsManager
;
410 IDocumentStatistics
& SwDoc::getIDocumentStatistics()
412 return *m_pDocumentStatisticsManager
;
415 ::sw::DocumentStatisticsManager
const & SwDoc::GetDocumentStatisticsManager() const
417 return *m_pDocumentStatisticsManager
;
420 ::sw::DocumentStatisticsManager
& SwDoc::GetDocumentStatisticsManager()
422 return *m_pDocumentStatisticsManager
;
426 IDocumentState
const & SwDoc::getIDocumentState() const
428 return *m_pDocumentStateManager
;
431 IDocumentState
& SwDoc::getIDocumentState()
433 return *m_pDocumentStateManager
;
436 //IDocumentLayoutAccess
437 IDocumentLayoutAccess
const & SwDoc::getIDocumentLayoutAccess() const
439 return *m_pDocumentLayoutManager
;
442 IDocumentLayoutAccess
& SwDoc::getIDocumentLayoutAccess()
444 return *m_pDocumentLayoutManager
;
447 ::sw::DocumentLayoutManager
const & SwDoc::GetDocumentLayoutManager() const
449 return *m_pDocumentLayoutManager
;
452 ::sw::DocumentLayoutManager
& SwDoc::GetDocumentLayoutManager()
454 return *m_pDocumentLayoutManager
;
457 //IDocumentStylePoolAccess
458 IDocumentStylePoolAccess
const & SwDoc::getIDocumentStylePoolAccess() const
460 return *m_pDocumentStylePoolManager
;
463 IDocumentStylePoolAccess
& SwDoc::getIDocumentStylePoolAccess()
465 return *m_pDocumentStylePoolManager
;
468 //IDocumentExternalData
469 IDocumentExternalData
const & SwDoc::getIDocumentExternalData() const
471 return *m_pDocumentExternalDataManager
;
474 IDocumentExternalData
& SwDoc::getIDocumentExternalData()
476 return *m_pDocumentExternalDataManager
;
479 /* Implementations the next Interface here */
482 * Document editing (Doc-SS) to fill the document
483 * by the RTF parser and for the EditShell.
485 void SwDoc::ChgDBData(const SwDBData
& rNewData
)
487 if( rNewData
!= maDBData
)
490 getIDocumentState().SetModified();
492 m_pDBManager
->CommitLastRegistrations();
494 getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::DatabaseName
)->UpdateFields();
497 struct PostItField_
: public SetGetExpField
499 PostItField_( const SwNodeIndex
& rNdIdx
, const SwTextField
* pField
)
500 : SetGetExpField( rNdIdx
, pField
, nullptr ) {}
502 sal_uInt16
GetPageNo( const StringRangeEnumerator
&rRangeEnum
,
503 const std::set
< sal_Int32
> &rPossiblePages
,
504 sal_uInt16
& rVirtPgNo
, sal_uInt16
& rLineNo
);
506 const SwPostItField
* GetPostIt() const
508 return static_cast<const SwPostItField
*>( GetTextField()->GetFormatField().GetField() );
512 sal_uInt16
PostItField_::GetPageNo(
513 const StringRangeEnumerator
&rRangeEnum
,
514 const std::set
< sal_Int32
> &rPossiblePages
,
515 /* out */ sal_uInt16
& rVirtPgNo
, /* out */ sal_uInt16
& rLineNo
)
517 //Problem: If a PostItField is contained in a Node that is represented
518 //by more than one layout instance,
519 //we have to decide whether it should be printed once or n-times.
520 //Probably only once. For the page number we don't select a random one,
521 //but the PostIt's first occurrence in the selected area.
523 SwIterator
<SwTextFrame
, SwTextNode
, sw::IteratorMode::UnwrapMulti
> aIter(GetTextField()->GetTextNode());
524 for( SwTextFrame
* pFrame
= aIter
.First(); pFrame
; pFrame
= aIter
.Next() )
526 TextFrameIndex
const nPos
= pFrame
->MapModelToView(
527 &GetTextField()->GetTextNode(), GetContent());
528 if( pFrame
->GetOfst() > nPos
||
529 (pFrame
->HasFollow() && pFrame
->GetFollow()->GetOfst() <= nPos
) )
531 sal_uInt16 nPgNo
= pFrame
->GetPhyPageNum();
532 if( rRangeEnum
.hasValue( nPgNo
, &rPossiblePages
))
534 rLineNo
= static_cast<sal_uInt16
>(pFrame
->GetLineCount( nPos
) +
535 pFrame
->GetAllLines() - pFrame
->GetThisLines());
536 rVirtPgNo
= pFrame
->GetVirtPageNum();
544 IDocumentFieldsAccess
const * pIDFA
,
545 SetGetExpFields
* pSrtLst
)
547 bool bHasPostIts
= false;
549 SwFieldType
* pFieldType
= pIDFA
->GetSysFieldType( SwFieldIds::Postit
);
552 if( pFieldType
->HasWriterListeners() )
554 // Found modify object; insert all fields into the array
555 SwIterator
<SwFormatField
,SwFieldType
> aIter( *pFieldType
);
556 for( SwFormatField
* pField
= aIter
.First(); pField
; pField
= aIter
.Next() )
558 const SwTextField
* pTextField
;
559 if( nullptr != ( pTextField
= pField
->GetTextField() ) &&
560 pTextField
->GetTextNode().GetNodes().IsDocNodes() )
565 SwNodeIndex
aIdx( pTextField
->GetTextNode() );
566 std::unique_ptr
<PostItField_
> pNew(new PostItField_( aIdx
, pTextField
));
567 pSrtLst
->insert( std::move(pNew
) );
570 break; // we just wanted to check for the existence of postits ...
578 static void lcl_FormatPostIt(
579 IDocumentContentOperations
* pIDCO
,
581 const SwPostItField
* pField
,
582 bool bNewPage
, bool bIsFirstPostIt
,
583 sal_uInt16 nPageNo
, sal_uInt16 nLineNo
)
585 static char const sTmp
[] = " : ";
587 assert(SwViewShell::GetShellRes());
591 pIDCO
->InsertPoolItem( aPam
, SvxFormatBreakItem( SvxBreak::PageAfter
, RES_BREAK
) );
592 pIDCO
->SplitNode( *aPam
.GetPoint(), false );
594 else if (!bIsFirstPostIt
)
596 // add an empty line between different notes
597 pIDCO
->SplitNode( *aPam
.GetPoint(), false );
598 pIDCO
->SplitNode( *aPam
.GetPoint(), false );
601 OUString
aStr( SwViewShell::GetShellRes()->aPostItPage
);
604 aStr
+= OUString::number( nPageNo
);
608 aStr
+= SwViewShell::GetShellRes()->aPostItLine
;
610 aStr
+= OUString::number( nLineNo
);
613 aStr
+= SwViewShell::GetShellRes()->aPostItAuthor
;
615 aStr
+= pField
->GetPar1();
617 SvtSysLocale aSysLocale
;
618 aStr
+= /*(LocaleDataWrapper&)*/aSysLocale
.GetLocaleData().getDate( pField
->GetDate() );
619 pIDCO
->InsertString( aPam
, aStr
);
621 pIDCO
->SplitNode( *aPam
.GetPoint(), false );
622 aStr
= pField
->GetPar2();
624 // Throw out all CR in Windows
625 aStr
= aStr
.replaceAll("\r", "");
627 pIDCO
->InsertString( aPam
, aStr
);
630 /// provide the paper tray to use according to the page style in use,
631 /// but do that only if the respective item is NOT just the default item
632 static sal_Int32
lcl_GetPaperBin( const SwPageFrame
*pStartFrame
)
636 const SwFrameFormat
&rFormat
= pStartFrame
->GetPageDesc()->GetMaster();
637 const SfxPoolItem
*pItem
= nullptr;
638 SfxItemState eState
= rFormat
.GetItemState( RES_PAPER_BIN
, false, &pItem
);
639 const SvxPaperBinItem
*pPaperBinItem
= dynamic_cast< const SvxPaperBinItem
* >(pItem
);
640 if (eState
> SfxItemState::DEFAULT
&& pPaperBinItem
)
641 nRes
= pPaperBinItem
->GetValue();
648 // tdf#:114663 Translates a range string from user input (with page numbering possibly not
649 // taking blank pages into account) to equivalent string which references physical page numbers.
650 // rUIPages2PhyPagesMap must contain a contiguous sequence of UI page numbers
651 OUString
UIPages2PhyPages(const OUString
& rUIPageRange
, const std::map
< sal_Int32
, sal_Int32
>& rUIPages2PhyPagesMap
)
653 if (rUIPages2PhyPagesMap
.empty())
655 auto iMin
= rUIPages2PhyPagesMap
.begin();
656 const sal_Int32 nUIPageMin
= iMin
->first
, nPhyPageMin
= iMin
->second
;
657 auto iMax
= rUIPages2PhyPagesMap
.rbegin();
658 const sal_Int32 nUIPageMax
= iMax
->first
, nPhyPageMax
= iMax
->second
;
659 OUStringBuffer
aOut(rUIPageRange
.getLength());
660 OUStringBuffer
aNumber(16);
661 const sal_Unicode
* pInput
= rUIPageRange
.getStr();
664 while (*pInput
>= '0' && *pInput
<= '9')
665 aNumber
.append(*pInput
++);
666 if (!aNumber
.isEmpty())
668 sal_Int32 nNumber
= aNumber
.makeStringAndClear().toInt32();
669 if (nNumber
< nUIPageMin
)
670 nNumber
= nPhyPageMin
-1;
671 else if (nNumber
> nUIPageMax
)
672 nNumber
= nPhyPageMax
+1;
674 nNumber
= rUIPages2PhyPagesMap
.at(nNumber
);
675 aOut
.append(nNumber
);
678 while (*pInput
&& (*pInput
< '0' || *pInput
> '9'))
679 aOut
.append(*pInput
++);
682 return aOut
.makeStringAndClear();
686 void SwDoc::CalculatePagesForPrinting(
687 const SwRootFrame
& rLayout
,
688 /* out */ SwRenderData
&rData
,
689 const SwPrintUIOptions
&rOptions
,
691 sal_Int32 nDocPageCount
)
693 const sal_Int64 nContent
= rOptions
.getIntValue( "PrintContent", 0 );
694 const bool bPrintSelection
= nContent
== 4;
696 // properties to take into account when calculating the set of pages
697 // (PDF export UI does not allow for selecting left or right pages only)
698 bool bPrintLeftPages
= bIsPDFExport
|| rOptions
.IsPrintLeftPages();
699 bool bPrintRightPages
= bIsPDFExport
|| rOptions
.IsPrintRightPages();
700 // #i103700# printing selections should not allow for automatic inserting empty pages
701 bool bPrintEmptyPages
= !bPrintSelection
&& rOptions
.IsPrintEmptyPages( bIsPDFExport
);
703 std::map
< sal_Int32
, sal_Int32
> &rPrinterPaperTrays
= rData
.GetPrinterPaperTrays();
704 std::set
< sal_Int32
> &rValidPages
= rData
.GetValidPagesSet();
705 // Map page numbers from user input (possibly ignoring blanks) to physical page numbers
706 std::map
< sal_Int32
, sal_Int32
> aUIPages2PhyPagesMap
;
709 sal_Int32 nPageNum
= 1, nUIPageNum
= 1;
710 const SwPageFrame
*pStPage
= dynamic_cast<const SwPageFrame
*>( rLayout
.Lower() );
711 while (pStPage
&& nPageNum
<= nDocPageCount
)
713 const bool bNonEmptyPage
= pStPage
->getFrameArea().Height() != 0;
714 const bool bPrintThisPage
=
715 ( (bPrintRightPages
&& pStPage
->OnRightPage()) ||
716 (bPrintLeftPages
&& !pStPage
->OnRightPage()) ) &&
717 ( bPrintEmptyPages
|| bNonEmptyPage
);
721 rValidPages
.insert( nPageNum
);
722 rPrinterPaperTrays
[ nPageNum
] = lcl_GetPaperBin( pStPage
);
725 if ( bPrintEmptyPages
|| bNonEmptyPage
)
727 aUIPages2PhyPagesMap
[nUIPageNum
++] = nPageNum
;
730 pStPage
= static_cast<const SwPageFrame
*>(pStPage
->GetNext());
733 // now that we have identified the valid pages for printing according
734 // to the print settings we need to get the PageRange to use and
735 // use both results to get the actual pages to be printed
736 // (post-it settings need to be taken into account later on!)
738 // get PageRange value to use
740 // #i116085# - adjusting fix for i113919
744 // 0 -> print all pages (default if aPageRange is empty)
745 // 1 -> print range according to PageRange
746 // 2 -> print even pages
747 // 3 -> print odd pages
748 // 4 -> print selection
750 aPageRange
= rOptions
.getStringValue( "PageRange" );
753 // note that printing selections is actually implemented by copying
754 // the selection to a new temporary document and printing all of that one.
755 // Thus for Writer "PrintContent" must never be 4.
756 // See SwXTextDocument::GetRenderDoc for evaluating if a selection is to be
757 // printed and for creating the temporary document.
762 if (aPageRange
.isEmpty()) // empty string -> print all
764 // set page range to print to 'all pages'
765 aPageRange
= OUString::number( 1 ) + "-" + OUString::number( nDocPageCount
);
769 // Convert page numbers from user input to physical page numbers
770 aPageRange
= UIPages2PhyPages(aPageRange
, aUIPages2PhyPagesMap
);
772 rData
.SetPageRange( aPageRange
);
774 // get vector of pages to print according to PageRange and valid pages set from above
775 // (result may be an empty vector, for example if the range string is not correct)
776 // If excluding empty pages, allow range to specify range of printable pages
777 StringRangeEnumerator::getRangesFromString( aPageRange
, rData
.GetPagesToPrint(),
778 1, nDocPageCount
, 0, &rData
.GetValidPagesSet() );
781 void SwDoc::UpdatePagesForPrintingWithPostItData(
782 /* out */ SwRenderData
&rData
,
783 const SwPrintUIOptions
&rOptions
,
784 sal_Int32 nDocPageCount
)
787 SwPostItMode nPostItMode
= static_cast<SwPostItMode
>( rOptions
.getIntValue( "PrintAnnotationMode", 0 ) );
788 assert((nPostItMode
== SwPostItMode::NONE
|| rData
.HasPostItData())
789 && "print post-its without post-it data?");
790 const SetGetExpFields::size_type nPostItCount
=
791 rData
.HasPostItData() ? rData
.m_pPostItFields
->size() : 0;
792 if (nPostItMode
== SwPostItMode::NONE
|| nPostItCount
<= 0)
795 SET_CURR_SHELL( rData
.m_pPostItShell
.get() );
797 // clear document and move to end of it
798 SwDoc
& rPostItDoc(*rData
.m_pPostItShell
->GetDoc());
799 SwPaM
aPam(rPostItDoc
.GetNodes().GetEndOfContent());
800 aPam
.Move( fnMoveBackward
, GoInDoc
);
802 aPam
.Move( fnMoveForward
, GoInDoc
);
803 rPostItDoc
.getIDocumentContentOperations().DeleteRange( aPam
);
805 const StringRangeEnumerator
aRangeEnum( rData
.GetPageRange(), 1, nDocPageCount
, 0 );
807 // For mode SwPostItMode::EndPage:
808 // maps a physical page number to the page number in post-it document that holds
809 // the first post-it for that physical page . Needed to relate the correct start frames
810 // from the post-it doc to the physical page of the document
811 std::map
< sal_Int32
, sal_Int32
> aPostItLastStartPageNum
;
813 // add all post-its on valid pages within the page range to the
814 // temporary post-it document.
815 // Since the array of post-it fields is sorted by page and line number we will
816 // already get them in the correct order
817 sal_uInt16 nVirtPg
= 0, nLineNo
= 0, nLastPageNum
= 0, nPhyPageNum
= 0;
818 bool bIsFirstPostIt
= true;
819 for (SetGetExpFields::size_type i
= 0; i
< nPostItCount
; ++i
)
821 PostItField_
& rPostIt
= static_cast<PostItField_
&>(*(*rData
.m_pPostItFields
)[ i
]);
822 nLastPageNum
= nPhyPageNum
;
823 nPhyPageNum
= rPostIt
.GetPageNo(
824 aRangeEnum
, rData
.GetValidPagesSet(), nVirtPg
, nLineNo
);
827 // need to insert a page break?
828 // In SwPostItMode::EndPage mode for each document page the following
829 // post-it page needs to start on a new page
830 const bool bNewPage
= nPostItMode
== SwPostItMode::EndPage
&&
831 !bIsFirstPostIt
&& nPhyPageNum
!= nLastPageNum
;
833 lcl_FormatPostIt( &rData
.m_pPostItShell
->GetDoc()->getIDocumentContentOperations(), aPam
,
834 rPostIt
.GetPostIt(), bNewPage
, bIsFirstPostIt
, nVirtPg
, nLineNo
);
835 bIsFirstPostIt
= false;
837 if (nPostItMode
== SwPostItMode::EndPage
)
839 // get the correct number of current pages for the post-it document
840 rData
.m_pPostItShell
->CalcLayout();
841 const sal_Int32 nPages
= rData
.m_pPostItShell
->GetPageCount();
842 aPostItLastStartPageNum
[ nPhyPageNum
] = nPages
;
847 // format post-it doc to get correct number of pages
848 rData
.m_pPostItShell
->CalcLayout();
850 SwRootFrame
* pPostItRoot
= rData
.m_pPostItShell
->GetLayout();
851 //tdf#103313 print dialog maxes out cpu as Idles never get to
852 //complete this postitshell's desire to complete formatting
853 pPostItRoot
->ResetIdleFormat();
855 const sal_Int32 nPostItDocPageCount
= rData
.m_pPostItShell
->GetPageCount();
857 if (nPostItMode
== SwPostItMode::Only
|| nPostItMode
== SwPostItMode::EndDoc
)
859 // now add those post-it pages to the vector of pages to print
860 // or replace them if only post-its should be printed
862 if (nPostItMode
== SwPostItMode::Only
)
864 // no document page to be printed
865 rData
.GetPagesToPrint().clear();
868 // now we just need to add the post-it pages to be printed to the
869 // end of the vector of pages to print
870 sal_Int32 nPageNum
= 0;
871 const SwPageFrame
* pPageFrame
= static_cast<SwPageFrame
*>(pPostItRoot
->Lower());
872 while( pPageFrame
&& nPageNum
< nPostItDocPageCount
)
875 // negative page number indicates page is from the post-it doc
876 rData
.GetPagesToPrint().push_back( -nPageNum
);
877 pPageFrame
= static_cast<const SwPageFrame
*>(pPageFrame
->GetNext());
879 OSL_ENSURE( nPageNum
== nPostItDocPageCount
, "unexpected number of pages" );
881 else if (nPostItMode
== SwPostItMode::EndPage
)
883 // the next step is to find all the pages from the post-it
884 // document that should be printed for a given physical page
887 std::vector
< sal_Int32
> aTmpPagesToPrint
;
888 sal_Int32
nLastPostItPage(0);
889 const size_t nNum
= rData
.GetPagesToPrint().size();
890 for (size_t i
= 0 ; i
< nNum
; ++i
)
892 // add the physical page to print from the document
893 const sal_Int32 nPhysPage
= rData
.GetPagesToPrint()[i
];
894 aTmpPagesToPrint
.push_back( nPhysPage
);
896 // add the post-it document pages to print, i.e those
897 // post-it pages that have the data for the above physical page
898 std::map
<sal_Int32
, sal_Int32
>::const_iterator
const iter(
899 aPostItLastStartPageNum
.find(nPhysPage
));
900 if (iter
!= aPostItLastStartPageNum
.end())
902 for (sal_Int32 j
= nLastPostItPage
+ 1;
903 j
<= iter
->second
; ++j
)
905 // negative page number indicates page is from the
906 aTmpPagesToPrint
.push_back(-j
); // post-it document
908 nLastPostItPage
= iter
->second
;
912 // finally we need to assign those vectors to the resulting ones.
913 // swapping the data should be more efficient than assigning since
914 // we won't need the temporary vectors anymore
915 rData
.GetPagesToPrint().swap( aTmpPagesToPrint
);
920 void SwDoc::CalculatePagePairsForProspectPrinting(
921 const SwRootFrame
& rLayout
,
922 /* out */ SwRenderData
&rData
,
923 const SwPrintUIOptions
&rOptions
,
924 sal_Int32 nDocPageCount
)
926 std::map
< sal_Int32
, sal_Int32
> &rPrinterPaperTrays
= rData
.GetPrinterPaperTrays();
927 std::set
< sal_Int32
> &rValidPagesSet
= rData
.GetValidPagesSet();
928 std::vector
< std::pair
< sal_Int32
, sal_Int32
> > &rPagePairs
= rData
.GetPagePairsForProspectPrinting();
929 std::map
< sal_Int32
, const SwPageFrame
* > validStartFrames
;
932 rValidPagesSet
.clear();
936 // 0 -> print all pages (default if aPageRange is empty)
937 // 1 -> print range according to PageRange
938 // 2 -> print even pages
939 // 3 -> print odd pages
940 // 4 -> print selection
941 const sal_Int64 nContent
= rOptions
.getIntValue( "PrintContent", 0 );
943 aPageRange
= rOptions
.getStringValue( "PageRange" );
944 if (aPageRange
.isEmpty()) // empty string -> print all
946 // set page range to print to 'all pages'
947 aPageRange
= OUString::number( 1 ) + "-" + OUString::number( nDocPageCount
);
949 StringRangeEnumerator
aRange( aPageRange
, 1, nDocPageCount
, 0 );
951 if ( aRange
.size() <= 0)
954 const SwPageFrame
*pStPage
= dynamic_cast<const SwPageFrame
*>( rLayout
.Lower() );
955 for ( sal_Int32 i
= 1; pStPage
&& i
< nDocPageCount
; ++i
)
956 pStPage
= static_cast<const SwPageFrame
*>(pStPage
->GetNext());
957 if ( !pStPage
) // Then it was that
960 // currently for prospect printing all pages are valid to be printed
961 // thus we add them all to the respective map and set for later use
962 sal_Int32 nPageNum
= 0;
963 const SwPageFrame
*pPageFrame
= dynamic_cast<const SwPageFrame
*>( rLayout
.Lower() );
964 while( pPageFrame
&& nPageNum
< nDocPageCount
)
967 rValidPagesSet
.insert( nPageNum
);
968 validStartFrames
[ nPageNum
] = pPageFrame
;
969 pPageFrame
= static_cast<const SwPageFrame
*>(pPageFrame
->GetNext());
971 rPrinterPaperTrays
[ nPageNum
] = lcl_GetPaperBin( pStPage
);
973 OSL_ENSURE( nPageNum
== nDocPageCount
, "unexpected number of pages" );
975 // properties to take into account when calculating the set of pages
976 // Note: here bPrintLeftPages and bPrintRightPages refer to the (virtual) resulting pages
978 bool bPrintLeftPages
= rOptions
.IsPrintLeftPages();
979 bool bPrintRightPages
= rOptions
.IsPrintRightPages();
980 bool bPrintProspectRTL
= rOptions
.getIntValue( "PrintProspectRTL", 0 ) != 0;
982 // get pages for prospect printing according to the 'PageRange'
983 // (duplicates and any order allowed!)
984 std::vector
< sal_Int32
> aPagesToPrint
;
985 StringRangeEnumerator::getRangesFromString(
986 aPageRange
, aPagesToPrint
, 1, nDocPageCount
, 0 );
988 if (aPagesToPrint
.empty())
991 // now fill the vector for calculating the page pairs with the start frames
992 // from the above obtained vector
993 std::vector
< const SwPageFrame
* > aVec
;
994 for (sal_Int32 nPage
: aPagesToPrint
)
996 const SwPageFrame
*pFrame
= validStartFrames
[ nPage
];
997 aVec
.push_back( pFrame
);
1000 // just one page is special ...
1001 if ( 1 == aVec
.size() )
1002 aVec
.insert( aVec
.begin() + 1, nullptr ); // insert a second empty page
1005 // now extend the number of pages to fit a multiple of 4
1006 // (4 'normal' pages are needed for a single prospect paper
1007 // with back and front)
1008 while( aVec
.size() & 3 )
1009 aVec
.push_back( nullptr );
1012 // make sure that all pages are in correct order
1013 std::vector
< const SwPageFrame
* >::size_type nSPg
= 0;
1014 std::vector
< const SwPageFrame
* >::size_type nEPg
= aVec
.size();
1015 sal_Int32 nStep
= 1;
1016 if ( 0 == (nEPg
& 1 )) // there are no uneven ones!
1019 if ( !bPrintLeftPages
)
1021 else if ( !bPrintRightPages
)
1028 // the number of 'virtual' pages to be printed
1029 sal_Int32 nCntPage
= (( nEPg
- nSPg
) / ( 2 * nStep
)) + 1;
1031 for ( sal_Int32 nPrintCount
= 0; nSPg
< nEPg
&&
1032 nPrintCount
< nCntPage
; ++nPrintCount
)
1034 pStPage
= aVec
[ nSPg
];
1035 const SwPageFrame
* pNxtPage
= nEPg
< aVec
.size() ? aVec
[ nEPg
] : nullptr;
1037 short nRtlOfs
= bPrintProspectRTL
? 1 : 0;
1038 if ( 0 == (( nSPg
+ nRtlOfs
) & 1 ) ) // switch for odd number in LTR, even number in RTL
1040 const SwPageFrame
* pTmp
= pStPage
;
1045 sal_Int32 nFirst
= -1, nSecond
= -1;
1046 for ( int nC
= 0; nC
< 2; ++nC
)
1048 sal_Int32 nPage
= -1;
1050 nPage
= pStPage
->GetPhyPageNum();
1058 rPagePairs
.emplace_back(nFirst
, nSecond
);
1060 nSPg
= nSPg
+ nStep
;
1061 nEPg
= nEPg
- nStep
;
1063 OSL_ENSURE( size_t(nCntPage
) == rPagePairs
.size(), "size mismatch for number of page pairs" );
1065 // luckily prospect printing does not make use of post-its so far,
1066 // thus we are done here.
1069 /// @return the reference in the doc for the name
1070 const SwFormatRefMark
* SwDoc::GetRefMark( const OUString
& rName
) const
1072 for (const SfxPoolItem
* pItem
: GetAttrPool().GetItemSurrogates(RES_TXTATR_REFMARK
))
1074 auto pFormatRef
= dynamic_cast<const SwFormatRefMark
*>(pItem
);
1078 const SwTextRefMark
* pTextRef
= pFormatRef
->GetTextRefMark();
1079 if( pTextRef
&& &pTextRef
->GetTextNode().GetNodes() == &GetNodes() &&
1080 rName
== pFormatRef
->GetRefName() )
1086 /// @return the RefMark per index - for Uno
1087 const SwFormatRefMark
* SwDoc::GetRefMark( sal_uInt16 nIndex
) const
1089 const SwTextRefMark
* pTextRef
;
1090 const SwFormatRefMark
* pRet
= nullptr;
1092 sal_uInt32 nCount
= 0;
1093 for (const SfxPoolItem
* pItem
: GetAttrPool().GetItemSurrogates(RES_TXTATR_REFMARK
))
1095 auto pRefMark
= dynamic_cast<const SwFormatRefMark
*>(pItem
);
1098 nullptr != (pTextRef
= pRefMark
->GetTextRefMark()) &&
1099 &pTextRef
->GetTextNode().GetNodes() == &GetNodes() )
1101 if(nCount
== nIndex
)
1112 /// @return the names of all set references in the Doc
1113 //JP 24.06.96: If the array pointer is 0, then just return whether a RefMark is set in the Doc
1114 // OS 25.06.96: From now on we always return the reference count
1115 sal_uInt16
SwDoc::GetRefMarks( std::vector
<OUString
>* pNames
) const
1117 const SwTextRefMark
* pTextRef
;
1119 sal_uInt16 nCount
= 0;
1120 for (const SfxPoolItem
* pItem
: GetAttrPool().GetItemSurrogates(RES_TXTATR_REFMARK
))
1122 auto pRefMark
= dynamic_cast<const SwFormatRefMark
*>(pItem
);
1125 nullptr != (pTextRef
= pRefMark
->GetTextRefMark()) &&
1126 &pTextRef
->GetTextNode().GetNodes() == &GetNodes() )
1130 OUString
aTmp(pRefMark
->GetRefName());
1131 pNames
->insert(pNames
->begin() + nCount
, aTmp
);
1140 static bool lcl_SpellAndGrammarAgain( const SwNodePtr
& rpNd
, void* pArgs
)
1142 SwTextNode
*pTextNode
= rpNd
->GetTextNode();
1143 bool bOnlyWrong
= *static_cast<sal_Bool
*>(pArgs
);
1148 if( pTextNode
->GetWrong() &&
1149 pTextNode
->GetWrong()->InvalidateWrong() )
1150 pTextNode
->SetWrongDirty(SwTextNode::WrongState::TODO
);
1151 if( pTextNode
->GetGrammarCheck() &&
1152 pTextNode
->GetGrammarCheck()->InvalidateWrong() )
1153 pTextNode
->SetGrammarCheckDirty( true );
1157 pTextNode
->SetWrongDirty(SwTextNode::WrongState::TODO
);
1158 if( pTextNode
->GetWrong() )
1159 pTextNode
->GetWrong()->SetInvalid( 0, COMPLETE_STRING
);
1160 pTextNode
->SetGrammarCheckDirty( true );
1161 if( pTextNode
->GetGrammarCheck() )
1162 pTextNode
->GetGrammarCheck()->SetInvalid( 0, COMPLETE_STRING
);
1168 static bool lcl_CheckSmartTagsAgain( const SwNodePtr
& rpNd
, void* )
1170 SwTextNode
*pTextNode
= rpNd
->GetTextNode();
1173 pTextNode
->SetSmartTagDirty( true );
1174 if( pTextNode
->GetSmartTags() )
1176 pTextNode
->SetSmartTags( nullptr );
1183 * Re-trigger spelling in the idle handler.
1185 * @param bInvalid if <true>, the WrongLists in all nodes are invalidated
1186 * and the SpellInvalid flag is set on all pages.
1187 * @param bOnlyWrong controls whether only the areas with wrong words are
1188 * checked or the whole area.
1189 * @param bSmartTags ???
1191 void SwDoc::SpellItAgainSam( bool bInvalid
, bool bOnlyWrong
, bool bSmartTags
)
1193 std::set
<SwRootFrame
*> aAllLayouts
= GetAllLayouts();
1194 assert(getIDocumentLayoutAccess().GetCurrentLayout() && "SpellAgain: Where's my RootFrame?");
1197 for ( auto aLayout
: aAllLayouts
)
1199 aLayout
->AllInvalidateSmartTagsOrSpelling(bSmartTags
);
1200 aLayout
->SetNeedGrammarCheck(true);
1203 GetNodes().ForEach( lcl_CheckSmartTagsAgain
, &bOnlyWrong
);
1204 GetNodes().ForEach( lcl_SpellAndGrammarAgain
, &bOnlyWrong
);
1207 for ( auto aLayout
: aAllLayouts
)
1208 aLayout
->SetIdleFlags();
1211 void SwDoc::InvalidateAutoCompleteFlag()
1213 SwRootFrame
* pTmpRoot
= getIDocumentLayoutAccess().GetCurrentLayout();
1216 std::set
<SwRootFrame
*> aAllLayouts
= GetAllLayouts();
1217 for( auto aLayout
: aAllLayouts
)
1218 aLayout
->AllInvalidateAutoCompleteWords();
1219 for( sal_uLong nNd
= 1, nCnt
= GetNodes().Count(); nNd
< nCnt
; ++nNd
)
1221 SwTextNode
* pTextNode
= GetNodes()[ nNd
]->GetTextNode();
1222 if ( pTextNode
) pTextNode
->SetAutoCompleteWordDirty( true );
1225 for( auto aLayout
: aAllLayouts
)
1226 aLayout
->SetIdleFlags();
1230 const SwFormatINetFormat
* SwDoc::FindINetAttr( const OUString
& rName
) const
1232 const SwTextINetFormat
* pTextAttr
;
1233 const SwTextNode
* pTextNd
;
1234 for (const SfxPoolItem
* pItem
: GetAttrPool().GetItemSurrogates(RES_TXTATR_INETFMT
))
1236 auto pFormatItem
= dynamic_cast<const SwFormatINetFormat
*>(pItem
);
1238 pFormatItem
->GetName() == rName
&&
1239 nullptr != ( pTextAttr
= pFormatItem
->GetTextINetFormat()) &&
1240 nullptr != ( pTextNd
= pTextAttr
->GetpTextNode() ) &&
1241 &pTextNd
->GetNodes() == &GetNodes() )
1249 void SwDoc::Summary( SwDoc
* pExtDoc
, sal_uInt8 nLevel
, sal_uInt8 nPara
, bool bImpress
)
1251 const SwOutlineNodes
& rOutNds
= GetNodes().GetOutLineNds();
1252 if( pExtDoc
&& !rOutNds
.empty() )
1254 ::StartProgress( STR_STATSTR_SUMMARY
, 0, rOutNds
.size(), GetDocShell() );
1255 SwNodeIndex
aEndOfDoc( pExtDoc
->GetNodes().GetEndOfContent(), -1 );
1256 for( SwOutlineNodes::size_type i
= 0; i
< rOutNds
.size(); ++i
)
1258 ::SetProgressState( static_cast<long>(i
), GetDocShell() );
1259 const sal_uLong nIndex
= rOutNds
[ i
]->GetIndex();
1261 const int nLvl
= GetNodes()[ nIndex
]->GetTextNode()->GetAttrOutlineLevel()-1;
1265 sal_uInt8 nWish
= nPara
;
1266 sal_uLong nNextOutNd
= i
+ 1 < rOutNds
.size() ?
1267 rOutNds
[ i
+ 1 ]->GetIndex() : GetNodes().Count();
1269 while( ( nWish
|| bKeep
) && nIndex
+ nEndOfs
< nNextOutNd
&&
1270 GetNodes()[ nIndex
+ nEndOfs
]->IsTextNode() )
1272 SwTextNode
* pTextNode
= GetNodes()[ nIndex
+nEndOfs
]->GetTextNode();
1273 if (pTextNode
->GetText().getLength() && nWish
)
1275 bKeep
= pTextNode
->GetSwAttrSet().GetKeep().GetValue();
1279 SwNodeRange
aRange( *rOutNds
[ i
], 0, *rOutNds
[ i
], nEndOfs
);
1280 GetNodes().Copy_( aRange
, aEndOfDoc
);
1282 const SwTextFormatColls
*pColl
= pExtDoc
->GetTextFormatColls();
1283 for( SwTextFormatColls::size_type i
= 0; i
< pColl
->size(); ++i
)
1284 (*pColl
)[ i
]->ResetFormatAttr( RES_PAGEDESC
, RES_BREAK
);
1285 SwNodeIndex
aIndx( pExtDoc
->GetNodes().GetEndOfExtras() );
1287 while( aIndx
< aEndOfDoc
)
1290 bool bDelete
= false;
1291 if( (pNode
= &aIndx
.GetNode())->IsTextNode() )
1293 SwTextNode
*pNd
= pNode
->GetTextNode();
1294 if( pNd
->HasSwAttrSet() )
1295 pNd
->ResetAttr( RES_PAGEDESC
, RES_BREAK
);
1298 SwTextFormatColl
* pMyColl
= pNd
->GetTextColl();
1300 const sal_uInt16 nHeadLine
= static_cast<sal_uInt16
>(
1301 !pMyColl
->IsAssignedToListLevelOfOutlineStyle()
1302 ? RES_POOLCOLL_HEADLINE2
1303 : RES_POOLCOLL_HEADLINE1
);
1304 pMyColl
= pExtDoc
->getIDocumentStylePoolAccess().GetTextCollFromPool( nHeadLine
);
1305 pNd
->ChgFormatColl( pMyColl
);
1308 pNd
->StartOfSectionIndex()+2 < pNd
->EndOfSectionIndex() )
1311 pExtDoc
->GetNodes().Delete( aIndx
);
1317 ::EndProgress( GetDocShell() );
1323 void RemoveOrDeleteContents(SwTextNode
* pTextNd
, IDocumentContentOperations
& xOperations
)
1325 SwPaM
aPam(*pTextNd
, 0, *pTextNd
, pTextNd
->GetText().getLength());
1327 // Remove hidden paragraph or delete contents:
1328 // Delete contents if
1329 // 1. removing the paragraph would result in an empty section or
1330 // 2. if the paragraph is the last paragraph in the section and
1331 // there is no paragraph in front of the paragraph:
1332 if ((2 == pTextNd
->EndOfSectionIndex() - pTextNd
->StartOfSectionIndex())
1333 || (1 == pTextNd
->EndOfSectionIndex() - pTextNd
->GetIndex()
1334 && !pTextNd
->GetNodes()[pTextNd
->GetIndex() - 1]->GetTextNode()))
1336 xOperations
.DeleteRange(aPam
);
1341 xOperations
.DelFullPara(aPam
);
1344 // Returns if the data was actually modified
1345 bool HandleHidingField(SwFormatField
& rFormatField
, const SwNodes
& rNodes
,
1346 IDocumentContentOperations
& xOperations
)
1348 SwTextNode
* pTextNd
;
1349 if (rFormatField
.GetTextField()
1350 && nullptr != (pTextNd
= rFormatField
.GetTextField()->GetpTextNode())
1351 && pTextNd
->GetpSwpHints() && pTextNd
->IsHiddenByParaField()
1352 && &pTextNd
->GetNodes() == &rNodes
)
1354 RemoveOrDeleteContents(pTextNd
, xOperations
);
1361 // The greater the returned value, the more weight has this field type on deciding the final
1363 int SwDoc::FieldCanHideParaWeight(SwFieldIds eFieldId
) const
1367 case SwFieldIds::HiddenPara
:
1369 case SwFieldIds::Database
:
1370 return GetDocumentSettingManager().get(DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA
)
1378 bool SwDoc::FieldHidesPara(const SwField
& rField
) const
1380 switch (rField
.GetTyp()->Which())
1382 case SwFieldIds::HiddenPara
:
1383 return static_cast<const SwHiddenParaField
&>(rField
).IsHidden();
1384 case SwFieldIds::Database
:
1385 return FieldCanHideParaWeight(SwFieldIds::Database
)
1386 && rField
.ExpandField(true, nullptr).isEmpty();
1392 /// Remove the invisible content from the document e.g. hidden areas, hidden paragraphs
1393 // Returns if the data was actually modified
1394 bool SwDoc::RemoveInvisibleContent()
1397 GetIDocumentUndoRedo().StartUndo( SwUndoId::UI_DELETE_INVISIBLECNTNT
, nullptr );
1400 class FieldTypeGuard
: public SwClient
1403 explicit FieldTypeGuard(SwFieldType
* pType
)
1407 const SwFieldType
* get() const
1409 return static_cast<const SwFieldType
*>(GetRegisteredIn());
1412 // Removing some nodes for one SwFieldIds::Database type might remove the type from
1413 // document's field types, invalidating iterators. So, we need to create own list of
1414 // matching types prior to processing them.
1415 std::vector
<std::unique_ptr
<FieldTypeGuard
>> aHidingFieldTypes
;
1416 for (std::unique_ptr
<SwFieldType
> const & pType
: *getIDocumentFieldsAccess().GetFieldTypes())
1418 if (FieldCanHideParaWeight(pType
->Which()))
1419 aHidingFieldTypes
.push_back(std::make_unique
<FieldTypeGuard
>(pType
.get()));
1421 for (const auto& pTypeGuard
: aHidingFieldTypes
)
1423 if (const SwFieldType
* pType
= pTypeGuard
->get())
1425 SwIterator
<SwFormatField
, SwFieldType
> aIter(*pType
);
1426 for (SwFormatField
* pFormatField
= aIter
.First(); pFormatField
;
1427 pFormatField
= aIter
.Next())
1428 bRet
|= HandleHidingField(*pFormatField
, GetNodes(),
1429 getIDocumentContentOperations());
1434 // Remove any hidden paragraph (hidden text attribute)
1435 for( sal_uLong n
= GetNodes().Count(); n
; )
1437 SwTextNode
* pTextNd
= GetNodes()[ --n
]->GetTextNode();
1440 bool bRemoved
= false;
1441 if ( pTextNd
->HasHiddenCharAttribute( true ) )
1446 if (2 == pTextNd
->EndOfSectionIndex() - pTextNd
->StartOfSectionIndex())
1448 SwFrameFormat
*const pFormat
= pTextNd
->StartOfSectionNode()->GetFlyFormat();
1449 if (nullptr != pFormat
)
1451 // remove hidden text frame
1452 getIDocumentLayoutAccess().DelLayoutFormat(pFormat
);
1456 // default, remove hidden paragraph
1457 RemoveOrDeleteContents(pTextNd
, getIDocumentContentOperations());
1462 // default, remove hidden paragraph
1463 RemoveOrDeleteContents(pTextNd
, getIDocumentContentOperations());
1466 else if ( pTextNd
->HasHiddenCharAttribute( false ) )
1470 SwScriptInfo::DeleteHiddenRanges( *pTextNd
);
1473 // Footnotes/Frames may have been removed, therefore we have
1477 // [n] has to be inside [0 .. GetNodes().Count()] range
1478 if (n
> GetNodes().Count())
1479 n
= GetNodes().Count();
1485 // Delete/empty all hidden areas
1486 o3tl::sorted_vector
<SwSectionFormat
*> aSectFormats
;
1487 SwSectionFormats
& rSectFormats
= GetSections();
1489 for( SwSectionFormats::size_type n
= rSectFormats
.size(); n
; )
1491 SwSectionFormat
* pSectFormat
= rSectFormats
[ --n
];
1492 // don't add sections in Undo/Redo
1493 if( !pSectFormat
->IsInNodesArr())
1495 SwSection
* pSect
= pSectFormat
->GetSection();
1496 if( pSect
->CalcHiddenFlag() )
1498 SwSection
* pParent
= pSect
, *pTmp
;
1499 while( nullptr != (pTmp
= pParent
->GetParent() ))
1501 if( pTmp
->IsHiddenFlag() )
1506 aSectFormats
.insert( pSect
->GetFormat() );
1508 if( !pSect
->GetCondition().isEmpty() )
1510 SwSectionData
aSectionData( *pSect
);
1511 aSectionData
.SetCondition( OUString() );
1512 aSectionData
.SetHidden( false );
1513 UpdateSection( n
, aSectionData
);
1517 auto n
= aSectFormats
.size();
1523 SwSectionFormat
* pSectFormat
= aSectFormats
[ --n
];
1524 SwSectionNode
* pSectNd
= pSectFormat
->GetSectionNode();
1528 SwPaM
aPam( *pSectNd
);
1530 if( pSectNd
->StartOfSectionNode()->StartOfSectionIndex() ==
1531 pSectNd
->GetIndex() - 1 &&
1532 pSectNd
->StartOfSectionNode()->EndOfSectionIndex() ==
1533 pSectNd
->EndOfSectionIndex() + 1 )
1535 // only delete the content
1536 SwContentNode
* pCNd
= GetNodes().GoNext(
1537 &aPam
.GetPoint()->nNode
);
1538 aPam
.GetPoint()->nContent
.Assign( pCNd
, 0 );
1540 aPam
.GetPoint()->nNode
= *pSectNd
->EndOfSectionNode();
1541 pCNd
= SwNodes::GoPrevious(
1542 &aPam
.GetPoint()->nNode
);
1543 aPam
.GetPoint()->nContent
.Assign( pCNd
, pCNd
->Len() );
1545 getIDocumentContentOperations().DeleteRange( aPam
);
1549 // delete the whole section
1551 aPam
.GetPoint()->nNode
= *pSectNd
->EndOfSectionNode();
1552 getIDocumentContentOperations().DelFullPara( aPam
);
1561 getIDocumentState().SetModified();
1562 GetIDocumentUndoRedo().EndUndo( SwUndoId::UI_DELETE_INVISIBLECNTNT
, nullptr );
1566 bool SwDoc::HasInvisibleContent() const
1568 if(SwIterator
<SwFormatField
,SwFieldType
>(*getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::HiddenPara
)).First())
1571 // Search for any hidden paragraph (hidden text attribute)
1572 for( sal_uLong n
= GetNodes().Count()-1; n
; --n
)
1574 SwTextNode
* pTextNd
= GetNodes()[ n
]->GetTextNode();
1576 ( pTextNd
->HasHiddenCharAttribute( true ) || pTextNd
->HasHiddenCharAttribute( false ) ) )
1580 for(auto pSectFormat
: GetSections())
1582 // don't add sections in Undo/Redo
1583 if( !pSectFormat
->IsInNodesArr())
1585 SwSection
* pSect
= pSectFormat
->GetSection();
1586 if( pSect
->IsHidden() )
1592 bool SwDoc::RestoreInvisibleContent()
1594 SwUndoId
nLastUndoId(SwUndoId::EMPTY
);
1595 if (GetIDocumentUndoRedo().GetLastUndoInfo(nullptr, & nLastUndoId
)
1596 && (SwUndoId::UI_DELETE_INVISIBLECNTNT
== nLastUndoId
))
1598 GetIDocumentUndoRedo().Undo();
1599 GetIDocumentUndoRedo().ClearRedo();
1605 bool SwDoc::ConvertFieldsToText(SwRootFrame
const& rLayout
)
1608 getIDocumentFieldsAccess().LockExpFields();
1609 GetIDocumentUndoRedo().StartUndo( SwUndoId::UI_REPLACE
, nullptr );
1611 const SwFieldTypes
* pMyFieldTypes
= getIDocumentFieldsAccess().GetFieldTypes();
1612 const SwFieldTypes::size_type nCount
= pMyFieldTypes
->size();
1613 //go backward, field types are removed
1614 for(SwFieldTypes::size_type nType
= nCount
; nType
> 0; --nType
)
1616 const SwFieldType
*pCurType
= (*pMyFieldTypes
)[nType
- 1].get();
1618 if ( SwFieldIds::Postit
== pCurType
->Which() )
1621 SwIterator
<SwFormatField
,SwFieldType
> aIter( *pCurType
);
1622 std::vector
<const SwFormatField
*> aFieldFormats
;
1623 for( SwFormatField
* pCurFieldFormat
= aIter
.First(); pCurFieldFormat
; pCurFieldFormat
= aIter
.Next() )
1624 aFieldFormats
.push_back(pCurFieldFormat
);
1626 for(const auto& rpFieldFormat
: aFieldFormats
)
1628 const SwTextField
*pTextField
= rpFieldFormat
->GetTextField();
1629 // skip fields that are currently not in the document
1630 // e.g. fields in undo or redo array
1632 bool bSkip
= !pTextField
||
1633 !pTextField
->GetpTextNode()->GetNodes().IsDocNodes();
1637 bool bInHeaderFooter
= IsInHeaderFooter(SwNodeIndex(*pTextField
->GetpTextNode()));
1638 const SwFormatField
& rFormatField
= pTextField
->GetFormatField();
1639 const SwField
* pField
= rFormatField
.GetField();
1641 //#i55595# some fields have to be excluded in headers/footers
1642 SwFieldIds nWhich
= pField
->GetTyp()->Which();
1643 if(!bInHeaderFooter
||
1644 (nWhich
!= SwFieldIds::PageNumber
&&
1645 nWhich
!= SwFieldIds::Chapter
&&
1646 nWhich
!= SwFieldIds::GetExp
&&
1647 nWhich
!= SwFieldIds::SetExp
&&
1648 nWhich
!= SwFieldIds::Input
&&
1649 nWhich
!= SwFieldIds::RefPageGet
&&
1650 nWhich
!= SwFieldIds::RefPageSet
))
1652 OUString sText
= pField
->ExpandField(true, &rLayout
);
1654 // database fields should not convert their command into text
1655 if( SwFieldIds::Database
== pCurType
->Which() && !static_cast<const SwDBField
*>(pField
)->IsInitialized())
1658 SwPaM
aInsertPam(*pTextField
->GetpTextNode(), pTextField
->GetStart());
1659 aInsertPam
.SetMark();
1661 // go to the end of the field
1662 const SwTextField
*pFieldAtEnd
= sw::DocumentFieldsManager::GetTextFieldAtPos(*aInsertPam
.End());
1663 if (pFieldAtEnd
&& pFieldAtEnd
->Which() == RES_TXTATR_INPUTFIELD
)
1665 SwPosition
&rEndPos
= *aInsertPam
.GetPoint();
1666 rEndPos
.nContent
= SwCursorShell::EndOfInputFieldAtPos( *aInsertPam
.End() );
1673 // first insert the text after field to keep the field's attributes,
1674 // then delete the field
1675 if (!sText
.isEmpty())
1677 // to keep the position after insert
1678 SwPaM
aDelPam( *aInsertPam
.GetMark(), *aInsertPam
.GetPoint() );
1679 aDelPam
.Move( fnMoveBackward
);
1680 aInsertPam
.DeleteMark();
1682 getIDocumentContentOperations().InsertString( aInsertPam
, sText
);
1685 // finally remove the field
1686 getIDocumentContentOperations().DeleteAndJoin( aDelPam
);
1690 getIDocumentContentOperations().DeleteAndJoin( aInsertPam
);
1700 getIDocumentState().SetModified();
1701 GetIDocumentUndoRedo().EndUndo( SwUndoId::UI_REPLACE
, nullptr );
1702 getIDocumentFieldsAccess().UnlockExpFields();
1707 bool SwDoc::IsInsTableFormatNum() const
1709 return SW_MOD()->IsInsTableFormatNum(GetDocumentSettingManager().get(DocumentSettingId::HTML_MODE
));
1712 bool SwDoc::IsInsTableChangeNumFormat() const
1714 return SW_MOD()->IsInsTableChangeNumFormat(GetDocumentSettingManager().get(DocumentSettingId::HTML_MODE
));
1717 bool SwDoc::IsInsTableAlignNum() const
1719 return SW_MOD()->IsInsTableAlignNum(GetDocumentSettingManager().get(DocumentSettingId::HTML_MODE
));
1722 bool SwDoc::IsSplitVerticalByDefault() const
1724 return SW_MOD()->IsSplitVerticalByDefault(GetDocumentSettingManager().get(DocumentSettingId::HTML_MODE
));
1727 void SwDoc::SetSplitVerticalByDefault(bool value
)
1729 SW_MOD()->SetSplitVerticalByDefault(GetDocumentSettingManager().get(DocumentSettingId::HTML_MODE
), value
);
1732 /// Set up the InsertDB as Undo table
1733 void SwDoc::AppendUndoForInsertFromDB( const SwPaM
& rPam
, bool bIsTable
)
1737 const SwTableNode
* pTableNd
= rPam
.GetPoint()->nNode
.GetNode().FindTableNode();
1740 std::unique_ptr
<SwUndoCpyTable
> pUndo(new SwUndoCpyTable(this));
1741 pUndo
->SetTableSttIdx( pTableNd
->GetIndex() );
1742 GetIDocumentUndoRedo().AppendUndo( std::move(pUndo
) );
1745 else if( rPam
.HasMark() )
1747 std::unique_ptr
<SwUndoCpyDoc
> pUndo(new SwUndoCpyDoc( rPam
));
1748 pUndo
->SetInsertRange( rPam
, false );
1749 GetIDocumentUndoRedo().AppendUndo( std::move(pUndo
) );
1753 void SwDoc::ChangeTOX(SwTOXBase
& rTOX
, const SwTOXBase
& rNew
)
1755 assert(dynamic_cast<const SwTOXBaseSection
*>(&rTOX
));
1756 SwTOXBaseSection
& rTOXSect(static_cast<SwTOXBaseSection
&>(rTOX
));
1758 if (GetIDocumentUndoRedo().DoesUndo())
1760 GetIDocumentUndoRedo().AppendUndo(
1761 std::make_unique
<SwUndoTOXChange
>(this, rTOXSect
, rNew
));
1766 // note: do not Update the ToX here - the caller will do it, with a ViewShell!
1769 OUString
SwDoc::GetPaMDescr(const SwPaM
& rPam
)
1771 if (&rPam
.GetNode() == &rPam
.GetNode(false))
1773 SwTextNode
* pTextNode
= rPam
.GetNode().GetTextNode();
1775 if (nullptr != pTextNode
)
1777 const sal_Int32 nStart
= rPam
.Start()->nContent
.GetIndex();
1778 const sal_Int32 nEnd
= rPam
.End()->nContent
.GetIndex();
1780 return SwResId(STR_START_QUOTE
)
1781 + ShortenString(pTextNode
->GetText().copy(nStart
, nEnd
- nStart
),
1784 + SwResId(STR_END_QUOTE
);
1789 return SwResId(STR_PARAGRAPHS
);
1792 return OUString("??");
1795 bool SwDoc::ContainsHiddenChars() const
1797 for( sal_uLong n
= GetNodes().Count(); n
; )
1799 SwNode
* pNd
= GetNodes()[ --n
];
1800 if ( pNd
->IsTextNode() && pNd
->GetTextNode()->HasHiddenCharAttribute( false ) )
1807 std::shared_ptr
<SwUnoCursor
> SwDoc::CreateUnoCursor( const SwPosition
& rPos
, bool bTableCursor
)
1809 std::shared_ptr
<SwUnoCursor
> pNew
;
1811 pNew
= std::make_shared
<SwUnoTableCursor
>(rPos
);
1813 pNew
= std::make_shared
<SwUnoCursor
>(rPos
);
1815 mvUnoCursorTable
.push_back( pNew
);
1819 void SwDoc::ChkCondColls()
1821 for (SwTextFormatColls::size_type n
= 0; n
< mpTextFormatCollTable
->size(); ++n
)
1823 SwTextFormatColl
*pColl
= (*mpTextFormatCollTable
)[n
];
1824 if (RES_CONDTXTFMTCOLL
== pColl
->Which())
1825 pColl
->CallSwClientNotify( SwAttrHint() );
1829 uno::Reference
< script::vba::XVBAEventProcessor
> const &
1830 SwDoc::GetVbaEventProcessor()
1832 #if HAVE_FEATURE_SCRIPTING
1833 if( !mxVbaEvents
.is() && mpDocShell
&& ooo::vba::isAlienWordDoc( *mpDocShell
) )
1837 uno::Reference
< frame::XModel
> xModel( mpDocShell
->GetModel(), uno::UNO_SET_THROW
);
1838 uno::Sequence
< uno::Any
> aArgs(1);
1839 aArgs
[0] <<= xModel
;
1840 mxVbaEvents
.set( ooo::vba::createVBAUnoAPIServiceWithArgs( mpDocShell
, "com.sun.star.script.vba.VBATextEventProcessor" , aArgs
), uno::UNO_QUERY_THROW
);
1842 catch( uno::Exception
& )
1850 void SwDoc::SetMissingDictionaries( bool bIsMissing
)
1853 meDictionaryMissing
= MissingDictionary::False
;
1854 else if (meDictionaryMissing
== MissingDictionary::Undefined
)
1855 meDictionaryMissing
= MissingDictionary::True
;
1859 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */