Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <config_features.h>
21 :
22 : #include <doc.hxx>
23 : #include <dcontact.hxx>
24 : #include <proofreadingiterator.hxx>
25 : #include <com/sun/star/document/PrinterIndependentLayout.hpp>
26 : #include <com/sun/star/document/UpdateDocMode.hpp>
27 : #include <com/sun/star/text/XTextDocument.hpp>
28 : #include <com/sun/star/text/XFlatParagraphIteratorProvider.hpp>
29 :
30 : #include <comphelper/processfactory.hxx>
31 : #include <vcl/svapp.hxx>
32 : #include <vcl/virdev.hxx>
33 : #include <rtl/random.h>
34 : #include <sfx2/printer.hxx>
35 : #include <sfx2/docfile.hxx>
36 : #include <sfx2/frame.hxx>
37 : #include <sfx2/viewfrm.hxx>
38 :
39 : #include <svl/macitem.hxx>
40 : #include <svx/svxids.hrc>
41 : #include <svx/svdogrp.hxx>
42 : #include <sfx2/linkmgr.hxx>
43 : #include <editeng/forbiddencharacterstable.hxx>
44 : #include <svl/zforlist.hxx>
45 : #include <unotools/lingucfg.hxx>
46 : #include <svx/svdpage.hxx>
47 : #include <paratr.hxx>
48 : #include <fchrfmt.hxx>
49 : #include <fmtcntnt.hxx>
50 : #include <fmtanchr.hxx>
51 : #include <fmtfsize.hxx>
52 : #include <fmtfordr.hxx>
53 : #include <fmtpdsc.hxx>
54 : #include <pvprtdat.hxx>
55 : #include <rootfrm.hxx>
56 : #include <layouter.hxx>
57 : #include <pagedesc.hxx>
58 : #include <ndtxt.hxx>
59 : #include <printdata.hxx>
60 : #include <docfld.hxx>
61 : #include <ftninfo.hxx>
62 : #include <ftnidx.hxx>
63 : #include <docstat.hxx>
64 : #include <charfmt.hxx>
65 : #include <frmfmt.hxx>
66 : #include <rolbck.hxx>
67 : #include <poolfmt.hxx>
68 : #include <dbmgr.hxx>
69 : #include <docsh.hxx>
70 : #include <acorrect.hxx>
71 : #include <visiturl.hxx>
72 : #include <docary.hxx>
73 : #include <lineinfo.hxx>
74 : #include <drawdoc.hxx>
75 : #include <linkenum.hxx>
76 : #include <fldupde.hxx>
77 : #include <extinput.hxx>
78 : #include <viewsh.hxx>
79 : #include <doctxm.hxx>
80 : #include <shellres.hxx>
81 : #include <breakit.hxx>
82 : #include <laycache.hxx>
83 : #include <mvsave.hxx>
84 : #include <istyleaccess.hxx>
85 : #include <swstylemanager.hxx>
86 : #include <IGrammarContact.hxx>
87 : #include <tblsel.hxx>
88 : #include <MarkManager.hxx>
89 : #include <UndoManager.hxx>
90 : #include <DocumentDeviceManager.hxx>
91 : #include <DocumentSettingManager.hxx>
92 : #include <DocumentDrawModelManager.hxx>
93 : #include <DocumentChartDataProviderManager.hxx>
94 : #include <DocumentTimerManager.hxx>
95 : #include <DocumentLinksAdministrationManager.hxx>
96 : #include <DocumentListItemsManager.hxx>
97 : #include <DocumentListsManager.hxx>
98 : #include <DocumentOutlineNodesManager.hxx>
99 : #include <DocumentContentOperationsManager.hxx>
100 : #include <DocumentRedlineManager.hxx>
101 : #include <DocumentFieldsManager.hxx>
102 : #include <DocumentStatisticsManager.hxx>
103 : #include <DocumentStateManager.hxx>
104 : #include <DocumentLayoutManager.hxx>
105 : #include <DocumentStylePoolManager.hxx>
106 : #include <DocumentExternalDataManager.hxx>
107 : #include <unochart.hxx>
108 : #include <fldbas.hxx>
109 : #include <wrtsh.hxx>
110 : #include <unocrsr.hxx>
111 :
112 : #include <cmdid.h>
113 :
114 : #include <pausethreadstarting.hxx>
115 : #include <numrule.hxx>
116 : #include <list.hxx>
117 :
118 : #include <sfx2/Metadatable.hxx>
119 : #include <fmtmeta.hxx>
120 :
121 : //UUUU
122 : #include <svx/xfillit0.hxx>
123 :
124 : using namespace ::com::sun::star;
125 : using namespace ::com::sun::star::document;
126 :
127 : const sal_Char sFrameFormatStr[] = "Frameformat";
128 : const sal_Char sEmptyPageStr[] = "Empty Page";
129 : const sal_Char sColumnCntStr[] = "Columncontainer";
130 : const sal_Char sCharFormatStr[] = "Character style";
131 : const sal_Char sTextCollStr[] = "Paragraph style";
132 : const sal_Char sGrfCollStr[] = "Graphikformatvorlage";
133 :
134 : /*
135 : * global functions...
136 : */
137 26718264 : uno::Reference< linguistic2::XProofreadingIterator > SwDoc::GetGCIterator() const
138 : {
139 26718264 : if (!m_xGCIterator.is() && SvtLinguConfig().HasGrammarChecker())
140 : {
141 0 : uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
142 : try
143 : {
144 0 : m_xGCIterator = sw::proofreadingiterator::get( xContext );
145 : }
146 0 : catch (const uno::Exception &)
147 : {
148 : OSL_FAIL( "No GCIterator" );
149 0 : }
150 : }
151 :
152 26718264 : return m_xGCIterator;
153 : }
154 :
155 26780438 : void StartGrammarChecking( SwDoc &rDoc )
156 : {
157 : // check for a visible view
158 26780438 : bool bVisible = false;
159 26780438 : const SwDocShell *mpDocShell = rDoc.GetDocShell();
160 26780438 : SfxViewFrame *pFrame = SfxViewFrame::GetFirst( mpDocShell, false );
161 80341314 : while (pFrame && !bVisible)
162 : {
163 26780438 : if (pFrame->IsVisible())
164 26718264 : bVisible = true;
165 26780438 : pFrame = SfxViewFrame::GetNext( *pFrame, mpDocShell, false );
166 : }
167 :
168 : //!! only documents with visible views need to be checked
169 : //!! (E.g. don't check temporary documents created for printing, see printing of notes and selections.
170 : //!! Those get created on the fly and get hard deleted a bit later as well, and no one should have
171 : //!! a uno reference to them)
172 26780438 : if (bVisible)
173 : {
174 26718264 : uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( rDoc.GetGCIterator() );
175 26718264 : if ( xGCIterator.is() )
176 : {
177 0 : uno::Reference< lang::XComponent > xDoc( rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY );
178 0 : uno::Reference< text::XFlatParagraphIteratorProvider > xFPIP( xDoc, uno::UNO_QUERY );
179 :
180 : // start automatic background checking if not active already
181 0 : if ( xFPIP.is() && !xGCIterator->isProofreading( xDoc ) )
182 0 : xGCIterator->startProofreading( xDoc, xFPIP );
183 26718264 : }
184 : }
185 26780438 : }
186 :
187 : /*
188 : * internal functions
189 : */
190 8421 : static void lcl_DelFormatIndices( SwFormat* pFormat )
191 : {
192 8421 : SwFormatContent &rFormatContent = (SwFormatContent&)pFormat->GetContent();
193 8421 : if ( rFormatContent.GetContentIdx() )
194 2630 : rFormatContent.SetNewContentIdx( 0 );
195 8421 : SwFormatAnchor &rFormatAnchor = (SwFormatAnchor&)pFormat->GetAnchor();
196 8421 : if ( rFormatAnchor.GetContentAnchor() )
197 3383 : rFormatAnchor.SetAnchor( 0 );
198 8421 : }
199 :
200 : /*
201 : * exported methods
202 : */
203 2958 : SwDoc::SwDoc()
204 2958 : : m_pNodes( new SwNodes(this) ),
205 2958 : mpAttrPool(new SwAttrPool(this)),
206 2958 : mpMarkManager(new ::sw::mark::MarkManager(*this)),
207 0 : m_pMetaFieldManager(new ::sw::MetaFieldManager()),
208 2958 : m_pDocumentDrawModelManager( new ::sw::DocumentDrawModelManager( *this ) ),
209 2958 : m_pDocumentRedlineManager( new ::sw::DocumentRedlineManager( *this ) ),
210 2958 : m_pDocumentStateManager( new ::sw::DocumentStateManager( *this ) ),
211 : m_pUndoManager(new ::sw::UndoManager(
212 14790 : boost::shared_ptr<SwNodes>(new SwNodes(this)), *m_pDocumentDrawModelManager, *m_pDocumentRedlineManager, *m_pDocumentStateManager)),
213 2958 : m_pDocumentSettingManager(new ::sw::DocumentSettingManager(*this)),
214 2958 : m_pDocumentChartDataProviderManager( new sw::DocumentChartDataProviderManager( *this ) ),
215 2958 : m_pDeviceAccess( new ::sw::DocumentDeviceManager( *this ) ),
216 2958 : m_pDocumentTimerManager( new ::sw::DocumentTimerManager( *this ) ),
217 2958 : m_pDocumentLinksAdministrationManager( new ::sw::DocumentLinksAdministrationManager( *this ) ),
218 0 : m_pDocumentListItemsManager( new ::sw::DocumentListItemsManager() ),
219 2958 : m_pDocumentListsManager( new ::sw::DocumentListsManager( *this ) ),
220 2958 : m_pDocumentOutlineNodesManager( new ::sw::DocumentOutlineNodesManager( *this ) ),
221 2958 : m_pDocumentContentOperationsManager( new ::sw::DocumentContentOperationsManager( *this ) ),
222 2958 : m_pDocumentFieldsManager( new ::sw::DocumentFieldsManager( *this ) ),
223 2958 : m_pDocumentStatisticsManager( new ::sw::DocumentStatisticsManager( *this ) ),
224 2958 : m_pDocumentLayoutManager( new ::sw::DocumentLayoutManager( *this ) ),
225 2958 : m_pDocumentStylePoolManager( new ::sw::DocumentStylePoolManager( *this ) ),
226 0 : m_pDocumentExternalDataManager( new ::sw::DocumentExternalDataManager() ),
227 2958 : mpDfltFrameFormat( new SwFrameFormat( GetAttrPool(), sFrameFormatStr, 0 ) ),
228 2958 : mpEmptyPageFormat( new SwFrameFormat( GetAttrPool(), sEmptyPageStr, mpDfltFrameFormat ) ),
229 2958 : mpColumnContFormat( new SwFrameFormat( GetAttrPool(), sColumnCntStr, mpDfltFrameFormat ) ),
230 2958 : mpDfltCharFormat( new SwCharFormat( GetAttrPool(), sCharFormatStr, 0 ) ),
231 2958 : mpDfltTextFormatColl( new SwTextFormatColl( GetAttrPool(), sTextCollStr ) ),
232 2958 : mpDfltGrfFormatColl( new SwGrfFormatColl( GetAttrPool(), sGrfCollStr ) ),
233 0 : mpFrameFormatTable( new SwFrameFormats() ),
234 0 : mpCharFormatTable( new SwCharFormats() ),
235 0 : mpSpzFrameFormatTable( new SwFrameFormats() ),
236 0 : mpSectionFormatTable( new SwSectionFormats() ),
237 0 : mpTableFrameFormatTable( new SwFrameFormats() ),
238 0 : mpTextFormatCollTable( new SwTextFormatColls() ),
239 0 : mpGrfFormatCollTable( new SwGrfFormatColls() ),
240 0 : mpTOXTypes( new SwTOXTypes() ),
241 : mpDefTOXBases( new SwDefTOXBase_Impl() ),
242 : mpGlossaryDoc( 0 ),
243 : mpOutlineRule( 0 ),
244 2958 : mpFootnoteInfo( new SwFootnoteInfo ),
245 2958 : mpEndNoteInfo( new SwEndNoteInfo ),
246 2958 : mpLineNumberInfo( new SwLineNumberInfo ),
247 2958 : mpFootnoteIdxs( new SwFootnoteIdxs ),
248 : mpDocShell( 0 ),
249 : mpACEWord( 0 ),
250 : mpURLStateChgd( 0 ),
251 : mpNumberFormatter( 0 ),
252 2958 : mpNumRuleTable( new SwNumRuleTable ),
253 : mpPgPViewPrtData( 0 ),
254 : mpExtInputRing( 0 ),
255 : mpStyleAccess( 0 ),
256 : mpLayoutCache( 0 ),
257 2958 : mpGrammarContact(createGrammarContact()),
258 : m_pXmlIdRegistry(),
259 : mReferenceCount(0),
260 : mbGlossDoc(false),
261 : mbDtor(false),
262 : mbCopyIsMove(false),
263 : mbInReading(false),
264 : mbInMailMerge(false),
265 : mbInXMLImport(false),
266 : mbUpdateTOX(false),
267 : mbInLoadAsynchron(false),
268 : mbIsAutoFormatRedline(false),
269 : mbOLEPrtNotifyPending(false),
270 : mbAllOLENotify(false),
271 : mbInsOnlyTextGlssry(false),
272 : mbContains_MSVBasic(false),
273 : mbClipBoard( false ),
274 : mbColumnSelection( false ),
275 : mbIsPrepareSelAll(false),
276 : #ifdef DBG_UTIL
277 : mbXMLExport(false),
278 : #endif
279 : mbContainsAtPageObjWithContentAnchor(false), //#i119292#, fdo#37024
280 :
281 : mbReadOnly(false),
282 106488 : meDocType(DOCTYPE_NATIVE)
283 : {
284 : //UUUU The DrawingLayer ItemPool which is used as 2nd pool for Writer documents' pool
285 : // has a default for the XFillStyleItem of XFILL_SOLID and the color for it is the default
286 : // fill color (blue7 or similar). This is a problem, in Writer we want the default fill
287 : // style to be drawing::FillStyle_NONE. This cannot simply be done by changing it in the 2nd pool at the
288 : // pool defaults when the DrawingLayer ItemPool is used for Writer, that would lead to
289 : // countless problems like DrawObjects initial fill and others.
290 : // It is also hard to find all places where the initial ItemSets for Writer (including
291 : // style hierarchies) are created and to always set (but only at the root) the FillStyle
292 : // to NONE fixed; that will add that attribute to the file format. It will be hard to reset
293 : // attribbute sets (which is done at import and using UI). Also not a good solution.
294 : // Luckily Writer uses pDfltTextFormatColl as default parent for all paragraphs and similar, thus
295 : // it is possible to set this attribute here. It will be not reset when importing.
296 2958 : mpDfltTextFormatColl->SetFormatAttr(XFillStyleItem(drawing::FillStyle_NONE));
297 2958 : mpDfltFrameFormat->SetFormatAttr(XFillStyleItem(drawing::FillStyle_NONE));
298 :
299 : /*
300 : * DefaultFormats and DefaultFormatCollections (FormatColl)
301 : * are inserted at position 0 at the respective array.
302 : * The formats in the FormatColls are derived from the
303 : * DefaultFormats and are also in the list.
304 : */
305 : /* Formats */
306 2958 : mpFrameFormatTable->push_back(mpDfltFrameFormat);
307 2958 : mpCharFormatTable->push_back(mpDfltCharFormat);
308 :
309 : /* FormatColls */
310 : // TXT
311 2958 : mpTextFormatCollTable->push_back(mpDfltTextFormatColl);
312 : // GRF
313 2958 : mpGrfFormatCollTable->push_back(mpDfltGrfFormatColl);
314 :
315 : // Create PageDesc, EmptyPageFormat and ColumnFormat
316 2958 : if ( maPageDescs.empty() )
317 2958 : getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_STANDARD );
318 :
319 : // Set to "Empty Page"
320 2958 : mpEmptyPageFormat->SetFormatAttr( SwFormatFrmSize( ATT_FIX_SIZE ) );
321 : // Set BodyFormat for columns
322 2958 : mpColumnContFormat->SetFormatAttr( SwFormatFillOrder( ATT_LEFT_TO_RIGHT ) );
323 :
324 2958 : GetDocumentFieldsManager()._InitFieldTypes();
325 :
326 : // Create a default OutlineNumRule (for Filters)
327 : mpOutlineRule = new SwNumRule( SwNumRule::GetOutlineRuleName(),
328 : // #i89178#
329 : numfunc::GetDefaultPositionAndSpaceMode(),
330 2958 : OUTLINE_RULE );
331 2958 : AddNumRule(mpOutlineRule);
332 : // Counting of phantoms depends on <IsOldNumbering()>
333 2958 : mpOutlineRule->SetCountPhantoms( !GetDocumentSettingManager().get(DocumentSettingId::OLD_NUMBERING) );
334 :
335 : new SwTextNode(
336 2958 : SwNodeIndex(GetUndoManager().GetUndoNodes().GetEndOfContent()),
337 2958 : mpDfltTextFormatColl );
338 2958 : new SwTextNode( SwNodeIndex( GetNodes().GetEndOfContent() ),
339 2958 : getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD ));
340 :
341 2958 : maOLEModifiedIdle.SetPriority( SchedulerPriority::LOWEST );
342 2958 : maOLEModifiedIdle.SetIdleHdl( LINK( this, SwDoc, DoUpdateModifiedOLE ));
343 :
344 : #if HAVE_FEATURE_DBCONNECTIVITY
345 : // Create DBManager
346 2958 : mpDBManager = new SwDBManager(this);
347 : #endif
348 :
349 : // create TOXTypes
350 2958 : InitTOXTypes();
351 :
352 : // pass empty item set containing the paragraph's list attributes
353 : // as ignorable items to the stype manager.
354 : {
355 2958 : SfxItemSet aIgnorableParagraphItems( GetAttrPool(), RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1);
356 2958 : mpStyleAccess = createStyleManager( &aIgnorableParagraphItems );
357 : }
358 :
359 2958 : static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != NULL);
360 :
361 2958 : if (bHack)
362 : {
363 0 : mnRsid = 0;
364 : }
365 : else
366 : {
367 : // Initialize the session id of the current document to a random number
368 : // smaller than 2^21.
369 2958 : static rtlRandomPool aPool = rtl_random_createPool();
370 2958 : rtl_random_getBytes( aPool, &mnRsid, sizeof ( mnRsid ) );
371 2958 : mnRsid &= ( 1<<21 ) - 1;
372 2958 : mnRsid++;
373 : }
374 2958 : mnRsidRoot = mnRsid;
375 :
376 2958 : getIDocumentState().ResetModified();
377 2958 : }
378 :
379 : /**
380 : * Speciality: a member of the class SwDoc is located at
381 : * position 0 in the array of the Format and GDI objects.
382 : * This MUST not be destroyed using 'delete' in any case!
383 : */
384 8846 : SwDoc::~SwDoc()
385 : {
386 : // nothing here should create Undo actions!
387 2949 : GetIDocumentUndoRedo().DoUndo(false);
388 :
389 2949 : if (mpDocShell)
390 : {
391 0 : mpDocShell->SetUndoManager(0);
392 : }
393 :
394 2949 : delete mpGrammarContact;
395 2949 : mpGrammarContact = 0;
396 :
397 : //!! needs to be done to destroy a possible SwFormatDrop format that may
398 : //!! be connected to a char format which may not otherwise be removed
399 : //!! and thus would leave a unremoved SwFormat object. (TL)
400 : //!! (this is case is not possible via UI but via API...)
401 2949 : SwFormatDrop aDrop;
402 2949 : SetDefault(aDrop);
403 : //!! same for SwFormatCharFormat
404 5898 : SwFormatCharFormat aCharFormat(NULL);
405 2949 : SetDefault(aCharFormat);
406 :
407 2949 : getIDocumentTimerAccess().StopIdling(); // stop idle timer
408 :
409 2949 : delete mpURLStateChgd;
410 :
411 : // Deactivate Undo notification from Draw
412 2949 : if( GetDocumentDrawModelManager().GetDrawModel() )
413 : {
414 2949 : GetDocumentDrawModelManager().DrawNotifyUndoHdl();
415 2949 : ClrContourCache();
416 : }
417 :
418 2949 : delete mpPgPViewPrtData;
419 :
420 2949 : mbDtor = true;
421 :
422 : //Clear the redline table before the nodes array is destroyed
423 2949 : getIDocumentRedlineAccess().GetRedlineTable().DeleteAndDestroyAll();
424 2949 : getIDocumentRedlineAccess().GetExtraRedlineTable().DeleteAndDestroyAll();
425 :
426 5898 : const sw::DocDisposingHint aHint;
427 5898 : std::vector< std::weak_ptr<SwUnoCrsr> > vCursorsToKill(mvUnoCrsrTbl.begin(), mvUnoCrsrTbl.end());
428 216143 : for(auto& pWeakCursor : vCursorsToKill)
429 : {
430 213194 : auto pCursor(pWeakCursor.lock());
431 213194 : if(pCursor)
432 3408 : pCursor->CallSwClientNotify(aHint);
433 213194 : }
434 2949 : delete mpACEWord;
435 :
436 : // Release the BaseLinks
437 : {
438 2949 : ::sfx2::SvLinkSources aTemp(getIDocumentLinksAdministration().GetLinkManager().GetServers());
439 8850 : for( ::sfx2::SvLinkSources::const_iterator it = aTemp.begin();
440 5900 : it != aTemp.end(); ++it )
441 1 : (*it)->Closed();
442 :
443 2949 : if( !getIDocumentLinksAdministration().GetLinkManager().GetLinks().empty() )
444 13 : getIDocumentLinksAdministration().GetLinkManager().Remove( 0, getIDocumentLinksAdministration().GetLinkManager().GetLinks().size() );
445 : }
446 :
447 : // The ChapterNumbers/Numbers need to be deleted before the styles
448 : // or we update all the time!
449 2949 : m_pNodes->pOutlineNds->clear();
450 2949 : SwNodes & rUndoNodes( GetUndoManager().GetUndoNodes() );
451 2949 : rUndoNodes.pOutlineNds->clear();
452 :
453 2949 : mpFootnoteIdxs->clear();
454 :
455 : // indices could be registered in attributes
456 2949 : m_pUndoManager->DelAllUndoObj();
457 :
458 : // The BookMarks contain indices to the Content. These must be deleted
459 : // before deleting the Nodes.
460 2949 : mpMarkManager->clearAllMarks();
461 :
462 2949 : if( mpExtInputRing )
463 : {
464 0 : SwPaM* pTmp = mpExtInputRing;
465 0 : mpExtInputRing = 0;
466 0 : while( pTmp->GetNext() != pTmp )
467 0 : delete pTmp->GetNext();
468 0 : delete pTmp;
469 : }
470 :
471 : // Old - deletion without a Flag is expensive, because we send a Modify
472 : // aTOXTypes.DeleteAndDestroy( 0, aTOXTypes.Count() );
473 : {
474 29658 : for( auto n = mpTOXTypes->size(); n; )
475 : {
476 23760 : (*mpTOXTypes)[ --n ]->SetInDocDTOR();
477 23760 : delete (*mpTOXTypes)[ n ];
478 : }
479 2949 : mpTOXTypes->clear();
480 : }
481 2949 : delete mpDefTOXBases;
482 :
483 : // Any of the FrmFormats can still have indices registered.
484 : // These need to be destroyed now at the latest.
485 7509 : for( SwFrameFormat* pFormat : *mpFrameFormatTable )
486 4560 : lcl_DelFormatIndices( pFormat );
487 6474 : for( SwFrameFormat* pFormat : *mpSpzFrameFormatTable )
488 3525 : lcl_DelFormatIndices( pFormat );
489 3285 : for( SwSectionFormat* pFormat : *mpSectionFormatTable )
490 336 : lcl_DelFormatIndices( pFormat );
491 :
492 : // The formats/styles that follow depend on the default formats.
493 : // Destroy these only after destroying the FormatIndices, because the content
494 : // of headers/footers has to be deleted as well. If in the headers/footers
495 : // there are still Flys registered at that point, we have a problem.
496 2949 : maPageDescs.clear();
497 :
498 : // Delete content selections.
499 : // Don't wait for the SwNodes dtor to destroy them; so that Formats
500 : // do not have any dependencies anymore.
501 2949 : m_pNodes->DelNodes( SwNodeIndex(*m_pNodes), m_pNodes->Count() );
502 2949 : rUndoNodes.DelNodes( SwNodeIndex( rUndoNodes ), rUndoNodes.Count() );
503 :
504 : // Delete Formats, make it permanent some time in the future
505 :
506 : // Delete for Collections
507 : // So that we get rid of the dependencies
508 2949 : mpFootnoteInfo->ReleaseCollection();
509 2949 : mpEndNoteInfo->ReleaseCollection();
510 :
511 : OSL_ENSURE( mpDfltTextFormatColl == (*mpTextFormatCollTable)[0],
512 : "Default-Text-Collection must always be at the start" );
513 :
514 : // Optimization: Based on the fact that Standard is always 2nd in the
515 : // array, we should delete it as the last. With this we avoid
516 : // reparenting the Formats all the time!
517 2949 : if( 2 < mpTextFormatCollTable->size() )
518 2935 : mpTextFormatCollTable->DeleteAndDestroy(2, mpTextFormatCollTable->size());
519 2949 : mpTextFormatCollTable->DeleteAndDestroy(1, mpTextFormatCollTable->size());
520 2949 : delete mpTextFormatCollTable;
521 :
522 : OSL_ENSURE( mpDfltGrfFormatColl == (*mpGrfFormatCollTable)[0],
523 : "DefaultGrfCollection must always be at the start" );
524 :
525 2949 : mpGrfFormatCollTable->DeleteAndDestroy(1, mpGrfFormatCollTable->size());
526 2949 : delete mpGrfFormatCollTable;
527 :
528 : // Without explicitly freeing the DocumentDeviceManager
529 : // and relying on the implicit freeing there would be a crash
530 : // due to it happening after SwAttrPool is freed.
531 2949 : m_pDeviceAccess.reset();
532 :
533 : /*
534 : * DefaultFormats and DefaultFormatCollections (FormatColl)
535 : * are at position 0 of their respective arrays.
536 : * In order to not be deleted by the array's dtor, we remove them
537 : * now.
538 : */
539 2949 : mpFrameFormatTable->erase( mpFrameFormatTable->begin() );
540 2949 : mpCharFormatTable->erase( mpCharFormatTable->begin() );
541 :
542 : #if HAVE_FEATURE_DBCONNECTIVITY
543 : // On load, SwDBManager::setEmbeddedName() may register a data source.
544 : // If we have an embedded one, then sDataSoure points to the registered name, so revoke it here.
545 2949 : if (!mpDBManager->getEmbeddedName().isEmpty() && !maDBData.sDataSource.isEmpty())
546 : {
547 : // Remove the revoke listener here first, so that we don't remove the data source from the document.
548 2 : mpDBManager->releaseRevokeListener();
549 2 : SwDBManager::RevokeDataSource(maDBData.sDataSource);
550 : }
551 :
552 2949 : DELETEZ( mpDBManager );
553 : #endif
554 :
555 : // All Flys need to be destroyed before the Drawing Model,
556 : // because Flys can still contain DrawContacts, when no
557 : // Layout could be constructed due to a read error.
558 2949 : mpSpzFrameFormatTable->DeleteAndDestroy( 0, mpSpzFrameFormatTable->size() );
559 :
560 : // Only now destroy the Model, the drawing objects - which are also
561 : // contained in the Undo - need to remove their attributes from the
562 : // Model. Also, DrawContacts could exist before this.
563 2949 : GetDocumentDrawModelManager().ReleaseDrawModel();
564 : // Destroy DrawModel before the LinkManager, because it's always set
565 : // in the DrawModel.
566 : //The LinkManager gets destroyed automatically with m_pLinksAdministrationManager
567 :
568 : // Clear the Tables before deleting the defaults, or we crash due to
569 : // dependencies on defaults.
570 2949 : delete mpFrameFormatTable;
571 2949 : delete mpSpzFrameFormatTable;
572 :
573 2949 : delete mpStyleAccess;
574 :
575 2949 : delete mpCharFormatTable;
576 2949 : delete mpSectionFormatTable;
577 2949 : delete mpTableFrameFormatTable;
578 2949 : delete mpDfltTextFormatColl;
579 2949 : delete mpDfltGrfFormatColl;
580 2949 : delete mpNumRuleTable;
581 :
582 2949 : disposeXForms(); // #i113606#, dispose the XForms objects
583 :
584 2949 : delete mpNumberFormatter;
585 2949 : delete mpFootnoteInfo;
586 2949 : delete mpEndNoteInfo;
587 2949 : delete mpLineNumberInfo;
588 2949 : delete mpFootnoteIdxs;
589 2949 : delete mpTOXTypes;
590 2949 : delete mpEmptyPageFormat;
591 2949 : delete mpColumnContFormat;
592 2949 : delete mpDfltCharFormat;
593 2949 : delete mpDfltFrameFormat;
594 2949 : delete mpLayoutCache;
595 :
596 5898 : SfxItemPool::Free(mpAttrPool);
597 5897 : }
598 :
599 6117 : void SwDoc::SetDocShell( SwDocShell* pDSh )
600 : {
601 6117 : if( mpDocShell != pDSh )
602 : {
603 6117 : if (mpDocShell)
604 : {
605 3056 : mpDocShell->SetUndoManager(0);
606 : }
607 6117 : mpDocShell = pDSh;
608 6117 : if (mpDocShell)
609 : {
610 3061 : mpDocShell->SetUndoManager(& GetUndoManager());
611 : }
612 :
613 6117 : getIDocumentLinksAdministration().GetLinkManager().SetPersist( mpDocShell );
614 :
615 : // set DocShell pointer also on DrawModel
616 6117 : InitDrawModelAndDocShell(mpDocShell, GetDocumentDrawModelManager().GetDrawModel());
617 : OSL_ENSURE(!GetDocumentDrawModelManager().GetDrawModel() ||
618 : GetDocumentDrawModelManager().GetDrawModel()->GetPersist() == GetPersist(),
619 : "draw model's persist is out of sync");
620 : }
621 6117 : }
622 :
623 : // Convenience method; to avoid excessive includes from docsh.hxx
624 69 : uno::Reference < embed::XStorage > SwDoc::GetDocStorage()
625 : {
626 69 : if( mpDocShell )
627 69 : return mpDocShell->GetStorage();
628 0 : if( getIDocumentLinksAdministration().GetLinkManager().GetPersist() )
629 0 : return getIDocumentLinksAdministration().GetLinkManager().GetPersist()->GetStorage();
630 0 : return NULL;
631 : }
632 :
633 3045 : SfxObjectShell* SwDoc::GetPersist() const
634 : {
635 3045 : return mpDocShell ? mpDocShell : getIDocumentLinksAdministration().GetLinkManager().GetPersist();
636 : }
637 :
638 21 : void SwDoc::ClearDoc()
639 : {
640 21 : GetIDocumentUndoRedo().DelAllUndoObj();
641 21 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
642 :
643 : // Deactivate Undo notification from Draw
644 21 : if( GetDocumentDrawModelManager().GetDrawModel() )
645 : {
646 21 : GetDocumentDrawModelManager().DrawNotifyUndoHdl();
647 21 : ClrContourCache();
648 : }
649 :
650 : // if there are still FlyFrames dangling around, delete them too
651 42 : while ( !mpSpzFrameFormatTable->empty() )
652 0 : getIDocumentLayoutAccess().DelLayoutFormat((*mpSpzFrameFormatTable)[mpSpzFrameFormatTable->size()-1]);
653 : OSL_ENSURE( !GetDocumentDrawModelManager().GetDrawModel() || !GetDocumentDrawModelManager().GetDrawModel()->GetPage(0)->GetObjCount(),
654 : "not all DrawObjects removed from the page" );
655 :
656 21 : getIDocumentRedlineAccess().GetRedlineTable().DeleteAndDestroyAll();
657 21 : getIDocumentRedlineAccess().GetExtraRedlineTable().DeleteAndDestroyAll();
658 :
659 21 : delete mpACEWord;
660 :
661 : // The BookMarks contain indices to the Content. These must be deleted
662 : // before deleting the Nodes.
663 21 : mpMarkManager->clearAllMarks();
664 21 : InitTOXTypes();
665 :
666 : // create a dummy pagedesc for the layout
667 21 : SwPageDesc* pDummyPgDsc = MakePageDesc("?DUMMY?");
668 :
669 42 : SwNodeIndex aSttIdx( *GetNodes().GetEndOfContent().StartOfSectionNode(), 1 );
670 : // create the first one over and over again (without attributes/style etc.
671 21 : SwTextNode* pFirstNd = GetNodes().MakeTextNode( aSttIdx, mpDfltTextFormatColl );
672 :
673 21 : if( getIDocumentLayoutAccess().GetCurrentViewShell() )
674 : {
675 : // set the layout to the dummy pagedesc
676 0 : pFirstNd->SetAttr( SwFormatPageDesc( pDummyPgDsc ));
677 :
678 0 : SwPosition aPos( *pFirstNd, SwIndex( pFirstNd ));
679 0 : SwPaM const tmpPaM(aSttIdx, SwNodeIndex(GetNodes().GetEndOfContent()));
680 0 : ::PaMCorrAbs(tmpPaM, aPos);
681 : }
682 :
683 21 : GetNodes().Delete( aSttIdx,
684 42 : GetNodes().GetEndOfContent().GetIndex() - aSttIdx.GetIndex() );
685 :
686 : // #i62440#
687 : // destruction of numbering rules and creation of new outline rule
688 : // *after* the document nodes are deleted.
689 21 : mpOutlineRule = NULL;
690 42 : for( SwNumRule* pNumRule : *mpNumRuleTable )
691 21 : delete pNumRule;
692 21 : mpNumRuleTable->clear();
693 :
694 : // creation of new outline numbering rule
695 : mpOutlineRule = new SwNumRule( SwNumRule::GetOutlineRuleName(),
696 : // #i89178#
697 : numfunc::GetDefaultPositionAndSpaceMode(),
698 21 : OUTLINE_RULE );
699 21 : AddNumRule(mpOutlineRule);
700 : // Counting of phantoms depends on <IsOldNumbering()>
701 21 : mpOutlineRule->SetCountPhantoms( !GetDocumentSettingManager().get(DocumentSettingId::OLD_NUMBERING) );
702 :
703 : // remove the dummy pagedesc from the array and delete all the old ones
704 21 : size_t nDummyPgDsc = 0;
705 21 : if (FindPageDesc(pDummyPgDsc->GetName(), &nDummyPgDsc))
706 21 : pDummyPgDsc = maPageDescs.release(maPageDescs.begin() + nDummyPgDsc).release();
707 21 : maPageDescs.clear();
708 :
709 : // Delete for Collections
710 : // So that we get rid of the dependencies
711 21 : mpFootnoteInfo->ReleaseCollection();
712 21 : mpEndNoteInfo->ReleaseCollection();
713 :
714 : // Optimization: Based on the fact that Standard is always 2nd in the
715 : // array, we should delete it as the last. With this we avoid
716 : // reparenting the Formats all the time!
717 21 : if( 2 < mpTextFormatCollTable->size() )
718 14 : mpTextFormatCollTable->DeleteAndDestroy(2, mpTextFormatCollTable->size());
719 21 : mpTextFormatCollTable->DeleteAndDestroy(1, mpTextFormatCollTable->size());
720 21 : mpGrfFormatCollTable->DeleteAndDestroy(1, mpGrfFormatCollTable->size());
721 21 : mpCharFormatTable->DeleteAndDestroy(1, mpCharFormatTable->size());
722 :
723 21 : if( getIDocumentLayoutAccess().GetCurrentViewShell() )
724 : {
725 : // search the FrameFormat of the root frm. This is not allowed to delete
726 0 : mpFrameFormatTable->erase( std::find( mpFrameFormatTable->begin(), mpFrameFormatTable->end(), getIDocumentLayoutAccess().GetCurrentViewShell()->GetLayout()->GetFormat() ) );
727 0 : mpFrameFormatTable->DeleteAndDestroy(1, mpFrameFormatTable->size());
728 0 : mpFrameFormatTable->push_back( getIDocumentLayoutAccess().GetCurrentViewShell()->GetLayout()->GetFormat() );
729 : }
730 : else
731 21 : mpFrameFormatTable->DeleteAndDestroy(1, mpFrameFormatTable->size());
732 :
733 21 : mxForbiddenCharsTable.clear();
734 :
735 21 : GetDocumentFieldsManager().ClearFieldTypes();
736 :
737 21 : delete mpNumberFormatter, mpNumberFormatter = 0;
738 :
739 21 : getIDocumentStylePoolAccess().GetPageDescFromPool( RES_POOLPAGE_STANDARD );
740 21 : pFirstNd->ChgFormatColl( getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD ));
741 21 : nDummyPgDsc = maPageDescs.size();
742 21 : maPageDescs.push_back( pDummyPgDsc );
743 : // set the layout back to the new standard pagedesc
744 21 : pFirstNd->ResetAllAttr();
745 : // delete now the dummy pagedesc
746 42 : DelPageDesc( nDummyPgDsc );
747 21 : }
748 :
749 0 : void SwDoc::SetPreviewPrtData( const SwPagePreviewPrtData* pNew )
750 : {
751 0 : if( pNew )
752 : {
753 0 : if( mpPgPViewPrtData )
754 0 : *mpPgPViewPrtData = *pNew;
755 : else
756 0 : mpPgPViewPrtData = new SwPagePreviewPrtData( *pNew );
757 : }
758 0 : else if( mpPgPViewPrtData )
759 0 : DELETEZ( mpPgPViewPrtData );
760 0 : getIDocumentState().SetModified();
761 0 : }
762 :
763 262 : void SwDoc::SetOLEObjModified()
764 : {
765 262 : if( getIDocumentLayoutAccess().GetCurrentViewShell() ) maOLEModifiedIdle.Start();
766 262 : }
767 :
768 : /** SwDoc: Reading and writing of the layout cache. */
769 41 : void SwDoc::ReadLayoutCache( SvStream& rStream )
770 : {
771 41 : if( !mpLayoutCache )
772 41 : mpLayoutCache = new SwLayoutCache();
773 41 : if( !mpLayoutCache->IsLocked() )
774 : {
775 41 : mpLayoutCache->GetLockCount() |= 0x8000;
776 41 : mpLayoutCache->Read( rStream );
777 41 : mpLayoutCache->GetLockCount() &= 0x7fff;
778 : }
779 41 : }
780 :
781 15 : void SwDoc::WriteLayoutCache( SvStream& rStream )
782 : {
783 15 : SwLayoutCache::Write( rStream, *this );
784 15 : }
785 :
786 12239 : IGrammarContact* getGrammarContact( const SwTextNode& rTextNode )
787 : {
788 12239 : const SwDoc* pDoc = rTextNode.GetDoc();
789 12239 : if( !pDoc || pDoc->IsInDtor() )
790 0 : return 0;
791 12239 : return pDoc->getGrammarContact();
792 : }
793 :
794 : ::sfx2::IXmlIdRegistry&
795 171 : SwDoc::GetXmlIdRegistry()
796 : {
797 : // UGLY: this relies on SetClipBoard being called before GetXmlIdRegistry!
798 171 : if (!m_pXmlIdRegistry.get())
799 : {
800 34 : m_pXmlIdRegistry.reset( ::sfx2::createXmlIdRegistry( IsClipBoard() ) );
801 : }
802 171 : return *m_pXmlIdRegistry;
803 : }
804 :
805 2979 : void SwDoc::InitTOXTypes()
806 : {
807 2979 : ShellResource* pShellRes = SwViewShell::GetShellRes();
808 2979 : SwTOXType * pNew = new SwTOXType(TOX_CONTENT, pShellRes->aTOXContentName );
809 2979 : mpTOXTypes->push_back( pNew );
810 2979 : pNew = new SwTOXType(TOX_INDEX, pShellRes->aTOXIndexName );
811 2979 : mpTOXTypes->push_back( pNew );
812 2979 : pNew = new SwTOXType(TOX_USER, pShellRes->aTOXUserName );
813 2979 : mpTOXTypes->push_back( pNew );
814 2979 : pNew = new SwTOXType(TOX_ILLUSTRATIONS, pShellRes->aTOXIllustrationsName );
815 2979 : mpTOXTypes->push_back( pNew );
816 2979 : pNew = new SwTOXType(TOX_OBJECTS, pShellRes->aTOXObjectsName );
817 2979 : mpTOXTypes->push_back( pNew );
818 2979 : pNew = new SwTOXType(TOX_TABLES, pShellRes->aTOXTablesName );
819 2979 : mpTOXTypes->push_back( pNew );
820 2979 : pNew = new SwTOXType(TOX_AUTHORITIES, pShellRes->aTOXAuthoritiesName );
821 2979 : mpTOXTypes->push_back( pNew );
822 2979 : pNew = new SwTOXType(TOX_CITATION, pShellRes->aTOXCitationName );
823 2979 : mpTOXTypes->push_back( pNew );
824 2979 : }
825 :
826 53 : void SwDoc::ReplaceDefaults(const SwDoc& rSource)
827 : {
828 : // copy property defaults
829 : const sal_uInt16 aRangeOfDefaults[] =
830 : {
831 : RES_FRMATR_BEGIN, RES_FRMATR_END-1,
832 : RES_CHRATR_BEGIN, RES_CHRATR_END-1,
833 : RES_PARATR_BEGIN, RES_PARATR_END-1,
834 : RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
835 : RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
836 : XATTR_START, XATTR_END-1,
837 : 0
838 53 : };
839 :
840 53 : SfxItemSet aNewDefaults(GetAttrPool(), aRangeOfDefaults);
841 :
842 371 : for (auto nRange = 0; aRangeOfDefaults[nRange] != 0; nRange += 2)
843 : {
844 17490 : for (sal_uInt16 nWhich = aRangeOfDefaults[nRange];
845 8745 : nWhich <= aRangeOfDefaults[nRange + 1]; ++nWhich)
846 : {
847 : const SfxPoolItem& rSourceAttr =
848 8427 : rSource.mpAttrPool->GetDefaultItem(nWhich);
849 8427 : if (rSourceAttr != mpAttrPool->GetDefaultItem(nWhich))
850 337 : aNewDefaults.Put(rSourceAttr);
851 : }
852 : }
853 :
854 53 : if (aNewDefaults.Count())
855 53 : SetDefault(aNewDefaults);
856 53 : }
857 :
858 53 : void SwDoc::ReplaceCompatibilityOptions(const SwDoc& rSource)
859 : {
860 53 : m_pDocumentSettingManager->ReplaceCompatibilityOptions(rSource.GetDocumentSettingManager());
861 53 : }
862 :
863 : #ifdef DBG_UTIL
864 : #define CNTNT_DOC( doc ) \
865 : ((doc)->GetNodes().GetEndOfContent().GetIndex() - (doc)->GetNodes().GetEndOfExtras().GetIndex() - 2)
866 : #define CNTNT_IDX( idx ) \
867 : ((idx).GetNode().GetIndex() - GetNodes().GetEndOfExtras().GetIndex() - 1)
868 : #endif
869 :
870 47 : SfxObjectShell* SwDoc::CreateCopy(bool bCallInitNew ) const
871 : {
872 47 : SwDoc* pRet = new SwDoc;
873 :
874 : // we have to use pointer here, since the callee has to decide whether
875 : // SfxObjectShellLock or SfxObjectShellRef should be used sometimes the
876 : // object will be returned with refcount set to 0 ( if no DoInitNew is done )
877 47 : SfxObjectShell* pRetShell = new SwDocShell( pRet, SfxObjectCreateMode::STANDARD );
878 47 : if( bCallInitNew )
879 : {
880 : // it could happen that DoInitNew creates model,
881 : // that increases the refcount of the object
882 47 : pRetShell->DoInitNew();
883 : }
884 :
885 47 : (void)pRet->acquire();
886 :
887 47 : pRet->ReplaceDefaults(*this);
888 :
889 47 : pRet->ReplaceCompatibilityOptions(*this);
890 :
891 47 : pRet->ReplaceStyles(*this);
892 :
893 : #ifdef DBG_UTIL
894 : SAL_INFO( "sw.createcopy", "CC-Nd-Src: " << CNTNT_DOC( this ) );
895 : SAL_INFO( "sw.createcopy", "CC-Nd: " << CNTNT_DOC( pRet ) );
896 : #endif
897 47 : pRet->AppendDoc(*this, 0, NULL, bCallInitNew);
898 : #ifdef DBG_UTIL
899 : SAL_INFO( "sw.createcopy", "CC-Nd: " << CNTNT_DOC( pRet ) );
900 : #endif
901 :
902 : // remove the temporary shell if it is there as it was done before
903 47 : pRet->SetTmpDocShell( nullptr );
904 :
905 47 : (void)pRet->release();
906 :
907 47 : return pRetShell;
908 : }
909 :
910 : // appends all pages of source SwDoc - based on SwFEShell::Paste( SwDoc* )
911 91 : SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, sal_uInt16 const nStartPageNumber,
912 : SwPageDesc *const pTargetPageDesc, bool const bDeletePrevious, int pageOffset)
913 : {
914 : // GetEndOfExtras + 1 = StartOfContent == no content node!
915 : // @see IDocumentContentOperations::CopyRange
916 91 : SwNodeIndex aSourceIdx( rSource.GetNodes().GetEndOfExtras(), 1 );
917 182 : SwNodeIndex aSourceEndIdx( rSource.GetNodes().GetEndOfContent(), -1 );
918 182 : SwPaM aCpyPam( aSourceIdx );
919 :
920 91 : if ( aSourceEndIdx.GetNode().IsTextNode() ) {
921 91 : aCpyPam.SetMark();
922 : // moves to the last content node before EOC; for single paragraph
923 : // documents this would result in [n, n], which is considered empty
924 91 : aCpyPam.Move( fnMoveForward, fnGoDoc );
925 : }
926 : else
927 0 : aCpyPam = SwPaM( aSourceIdx, aSourceEndIdx );
928 :
929 : #ifdef DBG_UTIL
930 : SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceIdx.GetNode().GetNodeType()
931 : << std::dec << " " << aSourceIdx.GetNode().GetIndex() );
932 : aSourceIdx++;
933 : SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceIdx.GetNode().GetNodeType()
934 : << std::dec << " " << aSourceIdx.GetNode().GetIndex() );
935 : if ( aSourceIdx.GetNode().GetNodeType() != ND_ENDNODE ) {
936 : aSourceIdx++;
937 : SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceIdx.GetNode().GetNodeType() << std::dec );
938 : aSourceIdx--;
939 : }
940 : aSourceIdx--;
941 : SAL_INFO( "sw.docappend", ".." );
942 : SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceEndIdx.GetNode().GetNodeType()
943 : << std::dec << " " << aSourceEndIdx.GetNode().GetIndex() );
944 : aSourceEndIdx++;
945 : SAL_INFO( "sw.docappend", "NodeType 0x" << std::hex << (int) aSourceEndIdx.GetNode().GetNodeType()
946 : << std::dec << " " << aSourceEndIdx.GetNode().GetIndex() );
947 : aSourceEndIdx--;
948 : SAL_INFO( "sw.docappend", "Src-Nd: " << CNTNT_DOC( &rSource ) );
949 : SAL_INFO( "sw.docappend", "Nd: " << CNTNT_DOC( this ) );
950 : #endif
951 :
952 91 : SwWrtShell* pTargetShell = GetDocShell()->GetWrtShell();
953 91 : if ( pTargetShell ) {
954 : #ifdef DBG_UTIL
955 : SAL_INFO( "sw.docappend", "Has target write shell" );
956 : #endif
957 44 : pTargetShell->StartAllAction();
958 :
959 : // Otherwise we have to handle SwPlaceholderNodes as first node
960 44 : if ( pTargetPageDesc ) {
961 44 : OUString name = pTargetPageDesc->GetName();
962 44 : pTargetShell->InsertPageBreak( &name, nStartPageNumber );
963 :
964 : // There is now a new empty text node on the new page. If it has
965 : // any marks, those are from the previous page: move them back
966 : // there, otherwise later we can't delete that empty text node.
967 88 : SwNodeIndex aNodeIndex(GetNodes().GetEndOfContent(), -1);
968 44 : if (SwTextNode* pTextNode = aNodeIndex.GetNode().GetTextNode())
969 : {
970 : // Position of the last paragraph on the previous page.
971 44 : --aNodeIndex;
972 44 : SwPaM aPaM(aNodeIndex);
973 : // Collect the marks starting or ending at this text node.
974 88 : std::set<sw::mark::IMark*> aSeenMarks;
975 44 : IDocumentMarkAccess* pMarkAccess = getIDocumentMarkAccess();
976 97 : for (const SwIndex* pIndex = pTextNode->GetFirstIndex(); pIndex; pIndex = pIndex->GetNext())
977 : {
978 53 : sw::mark::IMark* pMark = const_cast<sw::mark::IMark*>(pIndex->GetMark());
979 53 : if (!pMark)
980 88 : continue;
981 9 : if (aSeenMarks.find(pMark) != aSeenMarks.end())
982 0 : continue;
983 9 : aSeenMarks.insert(pMark);
984 : }
985 : // And move them back.
986 53 : for (sw::mark::IMark* pMark : aSeenMarks)
987 53 : pMarkAccess->repositionMark(pMark, aPaM);
988 44 : }
989 : }
990 : }
991 : #ifdef DBG_UTIL
992 : SAL_INFO( "sw.docappend", "Nd: " << CNTNT_DOC( this ) );
993 : #endif
994 :
995 : // -1, otherwise aFixupIdx would move to new EOC
996 182 : SwNodeIndex aFixupIdx( GetNodes().GetEndOfContent(), -1 );
997 :
998 : // append at the end of document / content
999 182 : SwNodeIndex aTargetIdx( GetNodes().GetEndOfContent() );
1000 182 : SwPaM aInsertPam( aTargetIdx );
1001 :
1002 : #ifdef DBG_UTIL
1003 : SAL_INFO( "sw.docappend", "Pam-Nd: " << aCpyPam.GetNode( true ).GetIndex() - aCpyPam.GetNode( false ).GetIndex() + 1
1004 : << " (0x" << std::hex << (int) aCpyPam.GetNode( false ).GetNodeType() << std::dec
1005 : << " " << aCpyPam.GetNode( false ).GetIndex()
1006 : << " - 0x" << std::hex << (int) aCpyPam.GetNode( true ).GetNodeType() << std::dec
1007 : << " " << aCpyPam.GetNode( true ).GetIndex() << ")" );
1008 : #endif
1009 :
1010 91 : this->GetIDocumentUndoRedo().StartUndo( UNDO_INSGLOSSARY, NULL );
1011 91 : this->getIDocumentFieldsAccess().LockExpFields();
1012 :
1013 : // Position where the appended doc starts. Will be filled in later (uses GetEndOfContent() because SwNodeIndex has no default ctor).
1014 91 : SwNodeIndex aStartAppendIndex( GetNodes().GetEndOfContent() );
1015 :
1016 : {
1017 : // **
1018 : // ** refer to SwFEShell::Paste, if you change the following code **
1019 : // **
1020 :
1021 91 : SwPosition& rInsPos = *aInsertPam.GetPoint();
1022 :
1023 : {
1024 91 : SwNodeIndex aIndexBefore(rInsPos.nNode);
1025 :
1026 91 : aIndexBefore--;
1027 : #ifdef DBG_UTIL
1028 : SAL_INFO( "sw.docappend", "CopyRange In: " << CNTNT_DOC( this ) );
1029 : #endif
1030 91 : rSource.getIDocumentContentOperations().CopyRange( aCpyPam, rInsPos, /*bCopyAll=*/true, /*bCheckPos=*/true );
1031 : // Note: aCpyPam is invalid now
1032 : #ifdef DBG_UTIL
1033 : SAL_INFO( "sw.docappend", "CopyRange Out: " << CNTNT_DOC( this ) );
1034 : #endif
1035 :
1036 91 : ++aIndexBefore;
1037 : SwPaM aPaM(SwPosition(aIndexBefore),
1038 182 : SwPosition(rInsPos.nNode));
1039 :
1040 91 : aPaM.GetDoc()->MakeUniqueNumRules(aPaM);
1041 :
1042 : // Update the rsid of each pasted text node
1043 91 : SwNodes &rDestNodes = GetNodes();
1044 91 : sal_uLong const nEndIdx = aPaM.End()->nNode.GetIndex();
1045 :
1046 461 : for (sal_uLong nIdx = aPaM.Start()->nNode.GetIndex();
1047 : nIdx <= nEndIdx; ++nIdx)
1048 : {
1049 370 : SwTextNode *const pTextNode = rDestNodes[nIdx]->GetTextNode();
1050 370 : if ( pTextNode )
1051 366 : UpdateParRsid( pTextNode );
1052 91 : }
1053 : }
1054 :
1055 : {
1056 91 : sal_uLong iDelNodes = 0;
1057 91 : SwNodeIndex aDelIdx( aFixupIdx );
1058 :
1059 : // we just need to set the new page description and reset numbering
1060 : // this keeps all other settings as in the pasted document
1061 91 : if ( nStartPageNumber || pTargetPageDesc ) {
1062 : SfxPoolItem *pNewItem;
1063 44 : SwTextNode *aTextNd = 0;
1064 44 : SwFormat *pFormat = 0;
1065 :
1066 : // find the first node allowed to contain a RES_PAGEDESC
1067 : while (true) {
1068 44 : aFixupIdx++;
1069 :
1070 44 : SwNode &node = aFixupIdx.GetNode();
1071 44 : if ( node.IsTextNode() ) {
1072 : // every document contains at least one text node!
1073 44 : aTextNd = node.GetTextNode();
1074 44 : pNewItem = aTextNd->GetAttr( RES_PAGEDESC ).Clone();
1075 44 : break;
1076 : }
1077 0 : else if ( node.IsTableNode() ) {
1078 0 : pFormat = node.GetTableNode()->GetTable().GetFrameFormat();
1079 0 : pNewItem = pFormat->GetFormatAttr( RES_PAGEDESC ).Clone();
1080 0 : break;
1081 : }
1082 : }
1083 :
1084 : #ifdef DBG_UTIL
1085 : SAL_INFO( "sw.docappend", "Idx Del " << CNTNT_IDX( aDelIdx ) );
1086 : SAL_INFO( "sw.docappend", "Idx Fix " << CNTNT_IDX( aFixupIdx ) );
1087 : #endif
1088 : // just update the original instead of overwriting
1089 44 : SwFormatPageDesc *aDesc = static_cast< SwFormatPageDesc* >( pNewItem );
1090 : #ifdef DBG_UTIL
1091 : if ( aDesc->GetPageDesc() )
1092 : SAL_INFO( "sw.docappend", "PD Update " << aDesc->GetPageDesc()->GetName() );
1093 : else
1094 : SAL_INFO( "sw.docappend", "PD New" );
1095 : #endif
1096 44 : if ( nStartPageNumber )
1097 44 : aDesc->SetNumOffset( nStartPageNumber );
1098 44 : if ( pTargetPageDesc )
1099 44 : aDesc->RegisterToPageDesc( *pTargetPageDesc );
1100 44 : if ( aTextNd )
1101 44 : aTextNd->SetAttr( *aDesc );
1102 : else
1103 0 : pFormat->SetFormatAttr( *aDesc );
1104 44 : delete pNewItem;
1105 :
1106 : #ifdef DBG_UTIL
1107 : SAL_INFO( "sw.docappend", "Idx " << CNTNT_IDX( aDelIdx ) );
1108 : #endif
1109 44 : iDelNodes++;
1110 : }
1111 :
1112 91 : if ( bDeletePrevious )
1113 52 : iDelNodes++;
1114 :
1115 91 : if ( iDelNodes ) {
1116 : // delete leading empty page(s), e.g. from InsertPageBreak or
1117 : // new SwDoc. this has to be done before copying the page bound
1118 : // frames, otherwise the drawing layer gets confused.
1119 91 : if ( pTargetShell )
1120 44 : pTargetShell->SttEndDoc( false );
1121 91 : aDelIdx -= (iDelNodes - 1);
1122 : #ifdef DBG_UTIL
1123 : SAL_INFO( "sw.docappend", "iDelNodes: " << iDelNodes
1124 : << " Idx: " << aDelIdx.GetNode().GetIndex()
1125 : << " EOE: " << GetNodes().GetEndOfExtras().GetIndex() );
1126 : #endif
1127 91 : GetNodes().Delete( aDelIdx, iDelNodes );
1128 91 : aStartAppendIndex = aFixupIdx;
1129 : }
1130 : else
1131 : {
1132 0 : aStartAppendIndex = aFixupIdx;
1133 0 : ++aStartAppendIndex;
1134 91 : }
1135 : }
1136 :
1137 : // finally copy page bound frames
1138 122 : for ( auto pCpyFormat : *rSource.GetSpzFrameFormats() )
1139 : {
1140 31 : const SwFrameFormat& rCpyFormat = *pCpyFormat;
1141 31 : SwFormatAnchor aAnchor( rCpyFormat.GetAnchor() );
1142 31 : if (FLY_AT_PAGE != aAnchor.GetAnchorId())
1143 14 : continue;
1144 : #ifdef DBG_UTIL
1145 : SAL_INFO( "sw.docappend", "PaAn: " << aAnchor.GetPageNum()
1146 : << " => " << aAnchor.GetPageNum() + pageOffset );
1147 : #endif
1148 17 : if ( pageOffset != 0 )
1149 6 : aAnchor.SetPageNum( aAnchor.GetPageNum() + pageOffset );
1150 17 : this->getIDocumentLayoutAccess().CopyLayoutFormat( rCpyFormat, aAnchor, true, true );
1151 17 : }
1152 : }
1153 :
1154 91 : this->GetIDocumentUndoRedo().EndUndo( UNDO_INSGLOSSARY, NULL );
1155 :
1156 91 : getIDocumentFieldsAccess().UnlockExpFields();
1157 91 : getIDocumentFieldsAccess().UpdateFields(NULL, false);
1158 :
1159 91 : if ( pTargetShell )
1160 44 : pTargetShell->EndAllAction();
1161 :
1162 182 : return aStartAppendIndex;
1163 177 : }
1164 :
1165 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|