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 <svl/smplhint.hxx>
21 : #include <hintids.hxx>
22 : #include <sfx2/linkmgr.hxx>
23 : #include <svl/itemiter.hxx>
24 : #include <tools/resid.hxx>
25 : #include <fmtcntnt.hxx>
26 : #include <fmtanchr.hxx>
27 : #include <txtftn.hxx>
28 : #include <fmtclds.hxx>
29 : #include <doc.hxx>
30 : #include <IDocumentUndoRedo.hxx>
31 : #include <IDocumentLinksAdministration.hxx>
32 : #include <IDocumentLayoutAccess.hxx>
33 : #include <IDocumentFieldsAccess.hxx>
34 : #include <IDocumentState.hxx>
35 : #include <rootfrm.hxx>
36 : #include <pam.hxx>
37 : #include <ndtxt.hxx>
38 : #include <section.hxx>
39 : #include <UndoSection.hxx>
40 : #include <UndoDelete.hxx>
41 : #include <swundo.hxx>
42 : #include <calc.hxx>
43 : #include <swtable.hxx>
44 : #include <swserv.hxx>
45 : #include <frmfmt.hxx>
46 : #include <frmtool.hxx>
47 : #include <ftnidx.hxx>
48 : #include <docary.hxx>
49 : #include <redline.hxx>
50 : #include <sectfrm.hxx>
51 : #include <pagefrm.hxx>
52 : #include <cntfrm.hxx>
53 : #include <node2lay.hxx>
54 : #include <doctxm.hxx>
55 : #include <fmtftntx.hxx>
56 : #include <comcore.hrc>
57 : #include <viewsh.hxx>
58 : #include <txtfrm.hxx>
59 : #include <boost/scoped_ptr.hpp>
60 : #include <ndsect.hxx>
61 : #include <tools/datetimeutils.hxx>
62 :
63 : // #i21457# - new implementation of local method <lcl_IsInSameTableBox(..)>.
64 : // Method now determines the previous/next on its own. Thus, it can be controlled,
65 : // for which previous/next is checked, if it's visible.
66 39 : static bool lcl_IsInSameTableBox( SwNodes& _rNds,
67 : const SwNode& _rNd,
68 : const bool _bPrev )
69 : {
70 39 : const SwTableNode* pTableNd = _rNd.FindTableNode();
71 39 : if ( !pTableNd )
72 : {
73 38 : return true;
74 : }
75 :
76 : // determine index to be checked. Its assumed that a previous/next exist.
77 1 : SwNodeIndex aChkIdx( _rNd );
78 : {
79 : // determine index of previous/next - skip hidden ones, which are
80 : // inside the table.
81 : // If found one is before/after table, this one isn't in the same
82 : // table box as <_rNd>.
83 1 : bool bFound = false;
84 1 : do
85 : {
86 2 : if ( _bPrev
87 1 : ? !SwNodes::GoPrevSection( &aChkIdx, false, false )
88 0 : : !_rNds.GoNextSection( &aChkIdx, false, false ) )
89 : {
90 : OSL_FAIL( "<lcl_IsInSameTableBox(..)> - no previous/next!" );
91 0 : return false;
92 : }
93 : else
94 : {
95 2 : if ( aChkIdx < pTableNd->GetIndex() ||
96 1 : aChkIdx > pTableNd->EndOfSectionNode()->GetIndex() )
97 : {
98 0 : return false;
99 : }
100 : else
101 : {
102 : // check, if found one isn't inside a hidden section, which
103 : // is also inside the table.
104 1 : SwSectionNode* pSectNd = aChkIdx.GetNode().FindSectionNode();
105 1 : if ( !pSectNd ||
106 1 : pSectNd->GetIndex() < pTableNd->GetIndex() ||
107 0 : !pSectNd->GetSection().IsHiddenFlag() )
108 : {
109 1 : bFound = true;
110 : }
111 : }
112 : }
113 1 : } while ( !bFound );
114 : }
115 :
116 : // Find the Box's StartNode
117 1 : const SwTableSortBoxes& rSortBoxes = pTableNd->GetTable().GetTabSortBoxes();
118 1 : sal_uLong nIdx = _rNd.GetIndex();
119 1 : for (size_t n = 0; n < rSortBoxes.size(); ++n)
120 : {
121 1 : const SwStartNode* pNd = rSortBoxes[ n ]->GetSttNd();
122 1 : if ( pNd->GetIndex() < nIdx && nIdx < pNd->EndOfSectionIndex() )
123 : {
124 : // The other index needs to be within the same Section
125 1 : nIdx = aChkIdx.GetIndex();
126 1 : return pNd->GetIndex() < nIdx && nIdx < pNd->EndOfSectionIndex();
127 : }
128 : }
129 :
130 0 : return true;
131 : }
132 :
133 18 : static void lcl_CheckEmptyLayFrm( SwNodes& rNds, SwSectionData& rSectionData,
134 : const SwNode& rStt, const SwNode& rEnd )
135 : {
136 18 : SwNodeIndex aIdx( rStt );
137 90 : if( !SwNodes::GoPrevSection( &aIdx, true, false ) ||
138 106 : !CheckNodesRange( rStt, aIdx, true ) ||
139 : // #i21457#
140 16 : !lcl_IsInSameTableBox( rNds, rStt, true ))
141 : {
142 2 : aIdx = rEnd;
143 10 : if( !rNds.GoNextSection( &aIdx, true, false ) ||
144 12 : !CheckNodesRange( rEnd, aIdx, true ) ||
145 : // #i21457#
146 2 : !lcl_IsInSameTableBox( rNds, rEnd, false ))
147 : {
148 0 : rSectionData.SetHidden( false );
149 : }
150 18 : }
151 18 : }
152 :
153 : SwSection *
154 331 : SwDoc::InsertSwSection(SwPaM const& rRange, SwSectionData & rNewData,
155 : SwTOXBase const*const pTOXBase,
156 : SfxItemSet const*const pAttr, bool const bUpdate)
157 : {
158 331 : const SwNode* pPrvNd = 0;
159 331 : sal_uInt16 nRegionRet = 0;
160 331 : if( rRange.HasMark() &&
161 : 0 == ( nRegionRet = IsInsRegionAvailable( rRange, &pPrvNd ) ))
162 : {
163 : // demoted to info because this is called from SwXTextSection::attach,
164 : // so it could be invalid input
165 : SAL_INFO("sw.core" , "InsertSwSection: rRange overlaps other sections");
166 0 : return 0;
167 : }
168 :
169 : // See if the whole Document should be hidden, which we currently are not able to do.
170 331 : if (rNewData.IsHidden() && rRange.HasMark())
171 : {
172 18 : const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End();
173 36 : if( !pStt->nContent.GetIndex() &&
174 18 : pEnd->nNode.GetNode().GetContentNode()->Len() ==
175 18 : pEnd->nContent.GetIndex() )
176 : {
177 18 : ::lcl_CheckEmptyLayFrm( GetNodes(),
178 : rNewData,
179 18 : pStt->nNode.GetNode(),
180 36 : pEnd->nNode.GetNode() );
181 : }
182 : }
183 :
184 331 : SwUndoInsSection* pUndoInsSect = 0;
185 331 : bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
186 331 : if (bUndo)
187 : {
188 21 : pUndoInsSect = new SwUndoInsSection(rRange, rNewData, pAttr, pTOXBase);
189 21 : GetIDocumentUndoRedo().AppendUndo( pUndoInsSect );
190 21 : GetIDocumentUndoRedo().DoUndo(false);
191 : }
192 :
193 331 : SwSectionFormat* const pFormat = MakeSectionFormat( 0 );
194 331 : if ( pAttr )
195 : {
196 95 : pFormat->SetFormatAttr( *pAttr );
197 : }
198 :
199 331 : SwSectionNode* pNewSectNode = 0;
200 :
201 331 : RedlineMode_t eOld = getIDocumentRedlineAccess().GetRedlineMode();
202 331 : getIDocumentRedlineAccess().SetRedlineMode_intern( (RedlineMode_t)((eOld & ~nsRedlineMode_t::REDLINE_SHOW_MASK) | nsRedlineMode_t::REDLINE_IGNORE));
203 :
204 331 : if( rRange.HasMark() )
205 : {
206 199 : SwPosition *pSttPos = const_cast<SwPosition*>(rRange.Start()),
207 199 : *pEndPos = const_cast<SwPosition*>(rRange.End());
208 199 : if( pPrvNd && 3 == nRegionRet )
209 : {
210 : OSL_ENSURE( pPrvNd, "The SectionNode is missing" );
211 2 : SwNodeIndex aStt( pSttPos->nNode ), aEnd( pEndPos->nNode, +1 );
212 3 : while( pPrvNd != aStt.GetNode().StartOfSectionNode() )
213 1 : --aStt;
214 3 : while( pPrvNd != aEnd.GetNode().StartOfSectionNode() )
215 1 : ++aEnd;
216 :
217 1 : --aEnd; // End is inclusive in the InsertSection
218 1 : pNewSectNode = GetNodes().InsertTextSection(
219 2 : aStt, *pFormat, rNewData, pTOXBase, & aEnd);
220 : }
221 : else
222 : {
223 198 : if( pUndoInsSect )
224 : {
225 22 : if( !( pPrvNd && 1 == nRegionRet ) &&
226 11 : pSttPos->nContent.GetIndex() )
227 : {
228 : SwTextNode* const pTNd =
229 0 : pSttPos->nNode.GetNode().GetTextNode();
230 0 : if (pTNd)
231 : {
232 0 : pUndoInsSect->SaveSplitNode( pTNd, true );
233 : }
234 : }
235 :
236 11 : if ( !( pPrvNd && 2 == nRegionRet ) )
237 : {
238 : SwTextNode *const pTNd =
239 11 : pEndPos->nNode.GetNode().GetTextNode();
240 22 : if (pTNd && (pTNd->GetText().getLength()
241 11 : != pEndPos->nContent.GetIndex()))
242 : {
243 0 : pUndoInsSect->SaveSplitNode( pTNd, false );
244 : }
245 : }
246 : }
247 :
248 198 : if( pPrvNd && 1 == nRegionRet )
249 : {
250 0 : pSttPos->nNode.Assign( *pPrvNd );
251 0 : pSttPos->nContent.Assign( pSttPos->nNode.GetNode().GetContentNode(), 0 );
252 : }
253 198 : else if( pSttPos->nContent.GetIndex() )
254 : {
255 1 : getIDocumentContentOperations().SplitNode( *pSttPos, false );
256 : }
257 :
258 198 : if( pPrvNd && 2 == nRegionRet )
259 : {
260 0 : pEndPos->nNode.Assign( *pPrvNd );
261 0 : pEndPos->nContent.Assign( pEndPos->nNode.GetNode().GetContentNode(), 0 );
262 : }
263 : else
264 : {
265 198 : const SwContentNode* pCNd = pEndPos->nNode.GetNode().GetContentNode();
266 198 : if( pCNd && pCNd->Len() != pEndPos->nContent.GetIndex() )
267 : {
268 0 : sal_Int32 nContent = pSttPos->nContent.GetIndex();
269 0 : getIDocumentContentOperations().SplitNode( *pEndPos, false );
270 :
271 : SwTextNode* pTNd;
272 0 : if( pEndPos->nNode.GetIndex() == pSttPos->nNode.GetIndex() )
273 : {
274 0 : --pSttPos->nNode;
275 0 : --pEndPos->nNode;
276 0 : pTNd = pSttPos->nNode.GetNode().GetTextNode();
277 0 : pSttPos->nContent.Assign( pTNd, nContent );
278 : }
279 : else
280 : {
281 : // Set to the end of the previous
282 0 : --pEndPos->nNode;
283 0 : pTNd = pEndPos->nNode.GetNode().GetTextNode();
284 : }
285 0 : nContent = (pTNd) ? pTNd->GetText().getLength() : 0;
286 0 : pEndPos->nContent.Assign( pTNd, nContent );
287 : }
288 : }
289 198 : pNewSectNode = GetNodes().InsertTextSection(
290 396 : pSttPos->nNode, *pFormat, rNewData, pTOXBase, &pEndPos->nNode);
291 : }
292 : }
293 : else
294 : {
295 132 : const SwPosition* pPos = rRange.GetPoint();
296 132 : const SwContentNode* pCNd = pPos->nNode.GetNode().GetContentNode();
297 132 : if( !pPos->nContent.GetIndex() )
298 : {
299 64 : pNewSectNode = GetNodes().InsertTextSection(
300 128 : pPos->nNode, *pFormat, rNewData, pTOXBase, 0, true);
301 : }
302 68 : else if( pPos->nContent.GetIndex() == pCNd->Len() )
303 : {
304 68 : pNewSectNode = GetNodes().InsertTextSection(
305 136 : pPos->nNode, *pFormat, rNewData, pTOXBase, 0, false);
306 : }
307 : else
308 : {
309 0 : if( pUndoInsSect && pCNd->IsTextNode() )
310 : {
311 0 : pUndoInsSect->SaveSplitNode( const_cast<SwTextNode*>(static_cast<const SwTextNode*>(pCNd)), true );
312 : }
313 0 : getIDocumentContentOperations().SplitNode( *pPos, false );
314 0 : pNewSectNode = GetNodes().InsertTextSection(
315 0 : pPos->nNode, *pFormat, rNewData, pTOXBase, 0, true);
316 : }
317 : }
318 :
319 : //FEATURE::CONDCOLL
320 331 : pNewSectNode->CheckSectionCondColl();
321 : //FEATURE::CONDCOLL
322 :
323 331 : getIDocumentRedlineAccess().SetRedlineMode_intern( eOld );
324 :
325 : // To-Do - add 'SwExtraRedlineTable' also ?
326 331 : if( getIDocumentRedlineAccess().IsRedlineOn() || (!getIDocumentRedlineAccess().IsIgnoreRedline() && !getIDocumentRedlineAccess().GetRedlineTable().empty() ))
327 : {
328 23 : SwPaM aPam( *pNewSectNode->EndOfSectionNode(), *pNewSectNode, 1 );
329 23 : if( getIDocumentRedlineAccess().IsRedlineOn() )
330 : {
331 0 : getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
332 : }
333 : else
334 : {
335 23 : getIDocumentRedlineAccess().SplitRedline( aPam );
336 23 : }
337 : }
338 :
339 : // Is a Condition set?
340 331 : if (rNewData.IsHidden() && !rNewData.GetCondition().isEmpty())
341 : {
342 : // The calculate up to that position
343 5 : SwCalc aCalc( *this );
344 5 : if( ! IsInReading() )
345 : {
346 1 : getIDocumentFieldsAccess().FieldsToCalc( aCalc, pNewSectNode->GetIndex(), USHRT_MAX );
347 : }
348 5 : SwSection& rNewSect = pNewSectNode->GetSection();
349 5 : rNewSect.SetCondHidden( aCalc.Calculate( rNewSect.GetCondition() ).GetBool() );
350 : }
351 :
352 331 : bool bUpdateFootnote = false;
353 331 : if( GetFootnoteIdxs().size() && pAttr )
354 : {
355 : sal_uInt16 nVal = static_cast<const SwFormatFootnoteAtTextEnd&>(pAttr->Get(
356 2 : RES_FTN_AT_TXTEND )).GetValue();
357 4 : if( ( FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
358 4 : FTNEND_ATTXTEND_OWNNUMANDFMT == nVal ) ||
359 : ( FTNEND_ATTXTEND_OWNNUMSEQ == ( nVal = static_cast<const SwFormatEndAtTextEnd&>(
360 4 : pAttr->Get( RES_END_AT_TXTEND )).GetValue() ) ||
361 : FTNEND_ATTXTEND_OWNNUMANDFMT == nVal ))
362 : {
363 0 : bUpdateFootnote = true;
364 : }
365 : }
366 :
367 331 : if( pUndoInsSect )
368 : {
369 21 : pUndoInsSect->SetSectNdPos( pNewSectNode->GetIndex() );
370 21 : pUndoInsSect->SetUpdateFootnoteFlag( bUpdateFootnote );
371 21 : GetIDocumentUndoRedo().DoUndo(bUndo);
372 : }
373 :
374 331 : if (rNewData.IsLinkType())
375 : {
376 0 : pNewSectNode->GetSection().CreateLink( bUpdate ? CREATE_UPDATE : CREATE_CONNECT );
377 : }
378 :
379 331 : if( bUpdateFootnote )
380 : {
381 0 : GetFootnoteIdxs().UpdateFootnote( SwNodeIndex( *pNewSectNode ));
382 : }
383 :
384 331 : getIDocumentState().SetModified();
385 331 : return &pNewSectNode->GetSection();
386 : }
387 :
388 199 : sal_uInt16 SwDoc::IsInsRegionAvailable( const SwPaM& rRange,
389 : const SwNode** ppSttNd )
390 : {
391 199 : sal_uInt16 nRet = 1;
392 199 : if( rRange.HasMark() )
393 : {
394 : // See if we have a valid Section
395 199 : const SwPosition* pStt = rRange.Start();
396 199 : const SwPosition* pEnd = rRange.End();
397 :
398 199 : const SwContentNode* pCNd = pEnd->nNode.GetNode().GetContentNode();
399 199 : const SwNode* pNd = &pStt->nNode.GetNode();
400 199 : const SwSectionNode* pSectNd = pNd->FindSectionNode();
401 199 : const SwSectionNode* pEndSectNd = pCNd ? pCNd->FindSectionNode() : 0;
402 199 : if( pSectNd && pEndSectNd && pSectNd != pEndSectNd )
403 : {
404 : // Try to create an enclosing Section, but only if Start is
405 : // located at the Section's beginning and End at it's end
406 1 : nRet = 0;
407 2 : if( !pStt->nContent.GetIndex()
408 1 : && pSectNd->GetIndex() == pStt->nNode.GetIndex() - 1
409 2 : && pEnd->nContent.GetIndex() == pCNd->Len() )
410 : {
411 1 : SwNodeIndex aIdx( pStt->nNode, -1 );
412 1 : sal_uLong nCmp = pEnd->nNode.GetIndex();
413 : const SwStartNode* pPrvNd;
414 : const SwEndNode* pNxtNd;
415 5 : while( 0 != ( pPrvNd = (pNd = &aIdx.GetNode())->GetSectionNode() ) &&
416 1 : !( aIdx.GetIndex() < nCmp &&
417 1 : nCmp < pPrvNd->EndOfSectionIndex() ) )
418 : {
419 1 : --aIdx;
420 : }
421 1 : if( !pPrvNd )
422 1 : pPrvNd = pNd->IsStartNode() ? static_cast<const SwStartNode*>(pNd)
423 1 : : pNd->StartOfSectionNode();
424 :
425 1 : aIdx = pEnd->nNode.GetIndex() + 1;
426 1 : nCmp = pStt->nNode.GetIndex();
427 4 : while( 0 != ( pNxtNd = (pNd = &aIdx.GetNode())->GetEndNode() ) &&
428 4 : pNxtNd->StartOfSectionNode()->IsSectionNode() &&
429 1 : !( pNxtNd->StartOfSectionIndex() < nCmp &&
430 0 : nCmp < aIdx.GetIndex() ) )
431 : {
432 1 : ++aIdx;
433 : }
434 1 : if( !pNxtNd )
435 1 : pNxtNd = pNd->EndOfSectionNode();
436 :
437 1 : if( pPrvNd && pNxtNd && pPrvNd == pNxtNd->StartOfSectionNode() )
438 : {
439 1 : nRet = 3;
440 :
441 1 : if( ppSttNd )
442 1 : *ppSttNd = pPrvNd;
443 1 : }
444 1 : }
445 : }
446 198 : else if( !pSectNd && pEndSectNd )
447 : {
448 : // Try to create an enclosing Section, but only if the End
449 : // is at the Section's end.
450 0 : nRet = 0;
451 0 : if( pEnd->nContent.GetIndex() == pCNd->Len() )
452 : {
453 0 : SwNodeIndex aIdx( pEnd->nNode, 1 );
454 0 : if( aIdx.GetNode().IsEndNode() &&
455 0 : 0 != aIdx.GetNode().FindSectionNode() )
456 : {
457 0 : do {
458 0 : ++aIdx;
459 0 : } while( aIdx.GetNode().IsEndNode() &&
460 0 : 0 != aIdx.GetNode().FindSectionNode() );
461 : {
462 0 : nRet = 2;
463 0 : if( ppSttNd )
464 : {
465 0 : --aIdx;
466 0 : *ppSttNd = &aIdx.GetNode();
467 : }
468 : }
469 0 : }
470 0 : }
471 : }
472 198 : else if( pSectNd && !pEndSectNd )
473 : {
474 : // Try to create an enclosing Section, but only if Start
475 : // is at the Section's start.
476 0 : nRet = 0;
477 0 : if( !pStt->nContent.GetIndex() )
478 : {
479 0 : SwNodeIndex aIdx( pStt->nNode, -1 );
480 0 : if( aIdx.GetNode().IsSectionNode() )
481 : {
482 0 : do {
483 0 : --aIdx;
484 0 : } while( aIdx.GetNode().IsSectionNode() );
485 0 : if( !aIdx.GetNode().IsSectionNode() )
486 : {
487 0 : nRet = 1;
488 0 : if( ppSttNd )
489 : {
490 0 : ++aIdx;
491 0 : *ppSttNd = &aIdx.GetNode();
492 : }
493 : }
494 0 : }
495 : }
496 : }
497 : }
498 199 : return nRet;
499 : }
500 :
501 6556 : SwSection* SwDoc::GetCurrSection( const SwPosition& rPos )
502 : {
503 6556 : const SwSectionNode* pSectNd = rPos.nNode.GetNode().FindSectionNode();
504 6556 : if( pSectNd )
505 90 : return const_cast<SwSection*>(&pSectNd->GetSection());
506 6466 : return 0;
507 : }
508 :
509 341 : SwSectionFormat* SwDoc::MakeSectionFormat( SwSectionFormat *pDerivedFrom )
510 : {
511 : SwSectionFormat* pNew = new SwSectionFormat(
512 341 : pDerivedFrom == 0 ? mpDfltFrameFormat : pDerivedFrom, this );
513 341 : mpSectionFormatTable->push_back( pNew );
514 341 : return pNew;
515 : }
516 :
517 10 : void SwDoc::DelSectionFormat( SwSectionFormat *pFormat, bool bDelNodes )
518 : {
519 10 : SwSectionFormats::iterator itFormatPos = std::find( mpSectionFormatTable->begin(), mpSectionFormatTable->end(), pFormat );
520 :
521 10 : GetIDocumentUndoRedo().StartUndo(UNDO_DELSECTION, NULL);
522 :
523 10 : if( mpSectionFormatTable->end() != itFormatPos )
524 : {
525 7 : const SwNodeIndex* pIdx = pFormat->GetContent( false ).GetContentIdx();
526 : const SfxPoolItem* pFootnoteEndAtTextEnd;
527 7 : if( SfxItemState::SET != pFormat->GetItemState(
528 7 : RES_FTN_AT_TXTEND, true, &pFootnoteEndAtTextEnd ) ||
529 : SfxItemState::SET != pFormat->GetItemState(
530 0 : RES_END_AT_TXTEND, true, &pFootnoteEndAtTextEnd ))
531 7 : pFootnoteEndAtTextEnd = 0;
532 :
533 : const SwSectionNode* pSectNd;
534 :
535 7 : if( GetIDocumentUndoRedo().DoesUndo() )
536 : {
537 6 : if( bDelNodes && pIdx && &GetNodes() == &pIdx->GetNodes() &&
538 2 : 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
539 : {
540 2 : SwNodeIndex aUpdIdx( *pIdx );
541 4 : SwPaM aPaM( *pSectNd->EndOfSectionNode(), *pSectNd );
542 2 : GetIDocumentUndoRedo().AppendUndo( new SwUndoDelete( aPaM ));
543 2 : if( pFootnoteEndAtTextEnd )
544 0 : GetFootnoteIdxs().UpdateFootnote( aUpdIdx );
545 2 : getIDocumentState().SetModified();
546 : //#126178# start/end undo have to be pairs!
547 2 : GetIDocumentUndoRedo().EndUndo(UNDO_DELSECTION, NULL);
548 4 : return ;
549 : }
550 2 : GetIDocumentUndoRedo().AppendUndo( MakeUndoDelSection( *pFormat ) );
551 : }
552 3 : else if( bDelNodes && pIdx && &GetNodes() == &pIdx->GetNodes() &&
553 0 : 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
554 : {
555 0 : SwNodeIndex aUpdIdx( *pIdx );
556 0 : getIDocumentContentOperations().DeleteSection( const_cast<SwNode*>(static_cast<SwNode const *>(pSectNd)) );
557 0 : if( pFootnoteEndAtTextEnd )
558 0 : GetFootnoteIdxs().UpdateFootnote( aUpdIdx );
559 0 : getIDocumentState().SetModified();
560 : //#126178# start/end undo have to be pairs!
561 0 : GetIDocumentUndoRedo().EndUndo(UNDO_DELSECTION, NULL);
562 0 : return ;
563 : }
564 :
565 : {
566 5 : SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFormat );
567 5 : pFormat->ModifyNotification( &aMsgHint, &aMsgHint );
568 : }
569 :
570 : // A ClearRedo could result in a recursive call of this function and delete some section
571 : // formats, thus the position inside the SectionFormatTable could have changed
572 5 : itFormatPos = std::find( mpSectionFormatTable->begin(), mpSectionFormatTable->end(), pFormat );
573 :
574 : // WARNING: First remove from the array and then delete,
575 : // as the Section DTOR tries to delete it's format itself.
576 5 : mpSectionFormatTable->erase( itFormatPos );
577 : //FEATURE::CONDCOLL
578 5 : sal_uLong nCnt = 0, nSttNd = 0;
579 8 : if( pIdx && &GetNodes() == &pIdx->GetNodes() &&
580 3 : 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
581 : {
582 3 : nSttNd = pSectNd->GetIndex();
583 3 : nCnt = pSectNd->EndOfSectionIndex() - nSttNd - 1;
584 : }
585 : //FEATURE::CONDCOLL
586 :
587 5 : delete pFormat;
588 :
589 5 : if( nSttNd && pFootnoteEndAtTextEnd )
590 : {
591 0 : SwNodeIndex aUpdIdx( GetNodes(), nSttNd );
592 0 : GetFootnoteIdxs().UpdateFootnote( aUpdIdx );
593 : }
594 :
595 : //FEATURE::CONDCOLL
596 : SwContentNode* pCNd;
597 11 : for( ; nCnt--; ++nSttNd )
598 12 : if( 0 != (pCNd = GetNodes()[ nSttNd ]->GetContentNode() ) &&
599 6 : RES_CONDTXTFMTCOLL == pCNd->GetFormatColl()->Which() )
600 0 : pCNd->ChkCondColl();
601 : //FEATURE::CONDCOLL
602 : }
603 :
604 8 : GetIDocumentUndoRedo().EndUndo(UNDO_DELSECTION, NULL);
605 :
606 8 : getIDocumentState().SetModified();
607 : }
608 :
609 142 : void SwDoc::UpdateSection( size_t const nPos, SwSectionData & rNewData,
610 : SfxItemSet const*const pAttr, bool const bPreventLinkUpdate )
611 : {
612 142 : SwSectionFormat* pFormat = (*mpSectionFormatTable)[ nPos ];
613 142 : SwSection* pSection = pFormat->GetSection();
614 :
615 : /// remember hidden condition flag of SwSection before changes
616 142 : bool bOldCondHidden = pSection->IsCondHidden();
617 :
618 142 : if (pSection->DataEquals(rNewData))
619 : {
620 : // Check Attributes
621 138 : bool bOnlyAttrChg = false;
622 138 : if( pAttr && pAttr->Count() )
623 : {
624 138 : SfxItemIter aIter( *pAttr );
625 138 : sal_uInt16 nWhich = aIter.GetCurItem()->Which();
626 : while( true )
627 : {
628 318 : if( pFormat->GetFormatAttr( nWhich ) != *aIter.GetCurItem() )
629 : {
630 116 : bOnlyAttrChg = true;
631 116 : break;
632 : }
633 :
634 202 : if( aIter.IsAtEnd() )
635 22 : break;
636 180 : nWhich = aIter.NextItem()->Which();
637 138 : }
638 : }
639 :
640 138 : if( bOnlyAttrChg )
641 : {
642 116 : if (GetIDocumentUndoRedo().DoesUndo())
643 : {
644 6 : GetIDocumentUndoRedo().AppendUndo(
645 6 : MakeUndoUpdateSection( *pFormat, true ) );
646 : }
647 : // #i32968# Inserting columns in the section causes MakeFrameFormat
648 : // to put two objects of type SwUndoFrameFormat on the undo stack.
649 : // We don't want them.
650 116 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
651 116 : pFormat->SetFormatAttr( *pAttr );
652 116 : getIDocumentState().SetModified();
653 : }
654 276 : return;
655 : }
656 :
657 : // Test if the whole Content Section (Document/TableBox/Fly) should be hidden,
658 : // which we're currently not able to do.
659 4 : const SwNodeIndex* pIdx = 0;
660 : {
661 4 : if (rNewData.IsHidden())
662 : {
663 0 : pIdx = pFormat->GetContent().GetContentIdx();
664 0 : if (pIdx)
665 : {
666 : const SwSectionNode* pSectNd =
667 0 : pIdx->GetNode().GetSectionNode();
668 0 : if (pSectNd)
669 : {
670 0 : ::lcl_CheckEmptyLayFrm( GetNodes(), rNewData,
671 0 : *pSectNd, *pSectNd->EndOfSectionNode() );
672 : }
673 : }
674 : }
675 : }
676 :
677 4 : if (GetIDocumentUndoRedo().DoesUndo())
678 : {
679 0 : GetIDocumentUndoRedo().AppendUndo(MakeUndoUpdateSection(*pFormat, false));
680 : }
681 : // #i32968# Inserting columns in the section causes MakeFrameFormat to put two
682 : // objects of type SwUndoFrameFormat on the undo stack. We don't want them.
683 4 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
684 :
685 : // The LinkFileName could only consist of separators
686 8 : OUString sCompareString = OUString(sfx2::cTokenSeparator) + OUString(sfx2::cTokenSeparator);
687 : const bool bUpdate =
688 6 : (!pSection->IsLinkType() && rNewData.IsLinkType())
689 20 : || (!rNewData.GetLinkFileName().isEmpty()
690 6 : && (rNewData.GetLinkFileName() != sCompareString)
691 8 : && (rNewData.GetLinkFileName() != pSection->GetLinkFileName()));
692 :
693 8 : OUString sSectName( rNewData.GetSectionName() );
694 4 : if (sSectName != pSection->GetSectionName())
695 0 : sSectName = GetUniqueSectionName( &sSectName );
696 : else
697 4 : sSectName.clear();
698 :
699 : /// In SwSection::operator=(..) class member m_bCondHiddenFlag is always set to true.
700 : /// IMHO this have to be changed, but I can't estimate the consequences:
701 : /// Either it is set to true using corresponding method <SwSection.SetCondHidden(..)>,
702 : /// or it is set to the value of SwSection which is assigned to it.
703 : /// Discussion with AMA results that the adjustment to the assignment operator
704 : /// could be very risky.
705 4 : pSection->SetSectionData(rNewData);
706 :
707 4 : if( pAttr )
708 0 : pSection->GetFormat()->SetFormatAttr( *pAttr );
709 :
710 4 : if( !sSectName.isEmpty() )
711 : {
712 0 : pSection->SetSectionName( sSectName );
713 : }
714 :
715 : // Is a Condition set
716 4 : if( pSection->IsHidden() && !pSection->GetCondition().isEmpty() )
717 : {
718 : // Then calculate up to that position
719 0 : SwCalc aCalc( *this );
720 0 : if( !pIdx )
721 0 : pIdx = pFormat->GetContent().GetContentIdx();
722 0 : getIDocumentFieldsAccess().FieldsToCalc( aCalc, pIdx->GetIndex(), USHRT_MAX );
723 :
724 : /// Because on using SwSection::operator=() to set up <pSection>
725 : /// with <rNewData> and the above given note, the hidden condition flag
726 : /// has to be set to false, if hidden condition flag of <pFormat->GetSection()>
727 : /// (SwSection before the changes) is false (already saved in <bOldCondHidden>)
728 : /// and new calculated condition is true.
729 : /// This is necessary, because otherwise the <SetCondHidden> would have
730 : /// no effect.
731 : bool bCalculatedCondHidden =
732 0 : aCalc.Calculate( pSection->GetCondition() ).GetBool();
733 0 : if ( bCalculatedCondHidden && !bOldCondHidden )
734 : {
735 0 : pSection->SetCondHidden( false );
736 : }
737 0 : pSection->SetCondHidden( bCalculatedCondHidden );
738 : }
739 :
740 4 : if( bUpdate )
741 4 : pSection->CreateLink( bPreventLinkUpdate ? CREATE_CONNECT : CREATE_UPDATE );
742 0 : else if( !pSection->IsLinkType() && pSection->IsConnected() )
743 : {
744 0 : pSection->Disconnect();
745 0 : getIDocumentLinksAdministration().GetLinkManager().Remove( &pSection->GetBaseLink() );
746 : }
747 :
748 8 : getIDocumentState().SetModified();
749 : }
750 :
751 383 : void sw_DeleteFootnote( SwSectionNode *pNd, sal_uLong nStt, sal_uLong nEnd )
752 : {
753 383 : SwFootnoteIdxs& rFootnoteArr = pNd->GetDoc()->GetFootnoteIdxs();
754 383 : if( rFootnoteArr.size() )
755 : {
756 14 : size_t nPos = 0;
757 14 : rFootnoteArr.SeekEntry( SwNodeIndex( *pNd ), &nPos );
758 : SwTextFootnote* pSrch;
759 :
760 : // Delete all succeeding Footnotes
761 72 : while( nPos < rFootnoteArr.size() &&
762 34 : _SwTextFootnote_GetIndex( (pSrch = rFootnoteArr[ nPos ]) ) <= nEnd )
763 : {
764 : // If the Nodes are not deleted, they need to deregister at the Pages
765 : // (delete Frms) or else they will remain there (Undo does not delete them!)
766 10 : pSrch->DelFrms(0);
767 10 : ++nPos;
768 : }
769 :
770 66 : while( nPos-- &&
771 28 : _SwTextFootnote_GetIndex( (pSrch = rFootnoteArr[ nPos ]) ) >= nStt )
772 : {
773 : // If the Nodes are not deleted, they need to deregister at the Pages
774 : // (delete Frms) or else they will remain there (Undo does not delete them!)
775 10 : pSrch->DelFrms(0);
776 : }
777 : }
778 383 : }
779 :
780 132 : static inline bool lcl_IsTOXSection(SwSectionData const& rSectionData)
781 : {
782 132 : return (TOX_CONTENT_SECTION == rSectionData.GetType())
783 132 : || (TOX_HEADER_SECTION == rSectionData.GetType());
784 : }
785 :
786 335 : SwSectionNode* SwNodes::InsertTextSection(SwNodeIndex const& rNdIdx,
787 : SwSectionFormat& rSectionFormat,
788 : SwSectionData const& rSectionData,
789 : SwTOXBase const*const pTOXBase,
790 : SwNodeIndex const*const pEnde,
791 : bool const bInsAtStart, bool const bCreateFrms)
792 : {
793 335 : SwNodeIndex aInsPos( rNdIdx );
794 335 : if( !pEnde ) // No Area, thus create a new Section before/after it
795 : {
796 : // #i26762#
797 : OSL_ENSURE(!pEnde || rNdIdx <= *pEnde,
798 : "Section start and end in wrong order!");
799 :
800 132 : if( bInsAtStart )
801 : {
802 64 : if (!lcl_IsTOXSection(rSectionData))
803 : {
804 13 : do {
805 13 : --aInsPos;
806 13 : } while( aInsPos.GetNode().IsSectionNode() );
807 13 : ++aInsPos;
808 : }
809 : }
810 : else
811 : {
812 68 : ++aInsPos;
813 68 : if (!lcl_IsTOXSection(rSectionData))
814 : {
815 : SwNode* pNd;
816 0 : while( aInsPos.GetIndex() < Count() - 1 &&
817 0 : ( pNd = &aInsPos.GetNode())->IsEndNode() &&
818 0 : pNd->StartOfSectionNode()->IsSectionNode())
819 : {
820 0 : ++aInsPos;
821 : }
822 : }
823 : }
824 : }
825 :
826 : SwSectionNode *const pSectNd =
827 335 : new SwSectionNode(aInsPos, rSectionFormat, pTOXBase);
828 335 : if( pEnde )
829 : {
830 : // Special case for the Reader/Writer
831 203 : if( &pEnde->GetNode() != &GetEndOfContent() )
832 203 : aInsPos = pEnde->GetIndex()+1;
833 : // #i58710: We created a RTF document with a section break inside a table cell
834 : // We are not able to handle a section start inside a table and the section end outside.
835 203 : const SwNode* pLastNode = pSectNd->StartOfSectionNode()->EndOfSectionNode();
836 203 : if( aInsPos > pLastNode->GetIndex() )
837 0 : aInsPos = pLastNode->GetIndex();
838 : // Another way round: if the section starts outside a table but the end is inside...
839 : // aInsPos is at the moment the Position where my EndNode will be inserted
840 203 : const SwStartNode* pStartNode = aInsPos.GetNode().StartOfSectionNode();
841 : // This StartNode should be in front of me, but if not, I want to survive
842 203 : sal_uLong nMyIndex = pSectNd->GetIndex();
843 203 : if( pStartNode->GetIndex() > nMyIndex ) // Suspicious!
844 : {
845 : const SwNode* pTemp;
846 0 : do
847 : {
848 0 : pTemp = pStartNode; // pTemp is a suspicious one
849 0 : pStartNode = pStartNode->StartOfSectionNode();
850 : }
851 0 : while( pStartNode->GetIndex() > nMyIndex );
852 0 : pTemp = pTemp->EndOfSectionNode();
853 : // If it starts behind me but ends behind my end...
854 0 : if( pTemp->GetIndex() >= aInsPos.GetIndex() )
855 0 : aInsPos = pTemp->GetIndex()+1; // ...I have to correct my end position
856 : }
857 : }
858 : else
859 : {
860 132 : SwTextNode* pCpyTNd = rNdIdx.GetNode().GetTextNode();
861 132 : if( pCpyTNd )
862 : {
863 132 : SwTextNode* pTNd = new SwTextNode( aInsPos, pCpyTNd->GetTextColl() );
864 132 : if( pCpyTNd->HasSwAttrSet() )
865 : {
866 : // Move PageDesc/Break to the first Node of the section
867 14 : const SfxItemSet& rSet = *pCpyTNd->GetpSwAttrSet();
868 28 : if( SfxItemState::SET == rSet.GetItemState( RES_BREAK ) ||
869 14 : SfxItemState::SET == rSet.GetItemState( RES_PAGEDESC ))
870 : {
871 1 : SfxItemSet aSet( rSet );
872 1 : if( bInsAtStart )
873 1 : pCpyTNd->ResetAttr( RES_PAGEDESC, RES_BREAK );
874 : else
875 : {
876 0 : aSet.ClearItem( RES_PAGEDESC );
877 0 : aSet.ClearItem( RES_BREAK );
878 : }
879 1 : pTNd->SetAttr( aSet );
880 : }
881 : else
882 13 : pTNd->SetAttr( rSet );
883 : }
884 : // Do not forget to create the Frame!
885 132 : pCpyTNd->MakeFrms( *pTNd );
886 : }
887 : else
888 0 : new SwTextNode( aInsPos, GetDoc()->GetDfltTextFormatColl() );
889 : }
890 335 : new SwEndNode( aInsPos, *pSectNd );
891 :
892 335 : pSectNd->GetSection().SetSectionData(rSectionData);
893 335 : SwSectionFormat* pSectFormat = pSectNd->GetSection().GetFormat();
894 :
895 : // We could optimize this, by not removing already contained Frames and recreating them,
896 : // but by simply rewiring them
897 648 : bool bInsFrm = bCreateFrms && !pSectNd->GetSection().IsHidden() &&
898 648 : GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
899 335 : SwNode2Layout *pNode2Layout = NULL;
900 335 : if( bInsFrm )
901 : {
902 20 : SwNodeIndex aTmp( *pSectNd );
903 20 : if( !pSectNd->GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() ) )
904 : // Collect all Uppers
905 1 : pNode2Layout = new SwNode2Layout( *pSectNd );
906 : }
907 :
908 : // Set the right StartNode for all in this Area
909 335 : sal_uLong nEnde = pSectNd->EndOfSectionIndex();
910 335 : sal_uLong nStart = pSectNd->GetIndex()+1;
911 335 : sal_uLong nSkipIdx = ULONG_MAX;
912 4006 : for( sal_uLong n = nStart; n < nEnde; ++n )
913 : {
914 3671 : SwNode* pNd = (*this)[n];
915 :
916 : // Attach all Sections in the NodeSection underneath the new one
917 3671 : if( ULONG_MAX == nSkipIdx )
918 1475 : pNd->pStartOfSection = pSectNd;
919 2196 : else if( n >= nSkipIdx )
920 33 : nSkipIdx = ULONG_MAX;
921 :
922 3671 : if( pNd->IsStartNode() )
923 : {
924 : // Make up the Format's nesting
925 754 : if( pNd->IsSectionNode() )
926 : {
927 13 : static_cast<SwSectionNode*>(pNd)->GetSection().GetFormat()->
928 13 : SetDerivedFrom( pSectFormat );
929 13 : static_cast<SwSectionNode*>(pNd)->DelFrms();
930 13 : n = pNd->EndOfSectionIndex();
931 : }
932 : else
933 : {
934 741 : if( pNd->IsTableNode() )
935 40 : static_cast<SwTableNode*>(pNd)->DelFrms();
936 :
937 741 : if( ULONG_MAX == nSkipIdx )
938 33 : nSkipIdx = pNd->EndOfSectionIndex();
939 : }
940 : }
941 2917 : else if( pNd->IsContentNode() )
942 2176 : static_cast<SwContentNode*>(pNd)->DelFrms();
943 : }
944 :
945 335 : sw_DeleteFootnote( pSectNd, nStart, nEnde );
946 :
947 335 : if( bInsFrm )
948 : {
949 20 : if( pNode2Layout )
950 : {
951 1 : sal_uLong nIdx = pSectNd->GetIndex();
952 1 : pNode2Layout->RestoreUpperFrms( pSectNd->GetNodes(), nIdx, nIdx + 1 );
953 1 : delete pNode2Layout;
954 : }
955 : else
956 19 : pSectNd->MakeFrms( &aInsPos );
957 : }
958 :
959 335 : return pSectNd;
960 : }
961 :
962 11588638 : SwSectionNode* SwNode::FindSectionNode()
963 : {
964 11588638 : if( IsSectionNode() )
965 41 : return GetSectionNode();
966 11588597 : SwStartNode* pTmp = pStartOfSection;
967 35876107 : while( !pTmp->IsSectionNode() && pTmp->GetIndex() )
968 12698913 : pTmp = pTmp->pStartOfSection;
969 11588597 : return pTmp->GetSectionNode();
970 : }
971 :
972 : // SwSectionNode
973 :
974 : // ugly hack to make m_pSection const
975 : static SwSectionFormat &
976 341 : lcl_initParent(SwSectionNode & rThis, SwSectionFormat & rFormat)
977 : {
978 : SwSectionNode *const pParent =
979 341 : rThis.StartOfSectionNode()->FindSectionNode();
980 341 : if( pParent )
981 : {
982 : // Register the Format at the right Parent
983 35 : rFormat.SetDerivedFrom( pParent->GetSection().GetFormat() );
984 : }
985 341 : return rFormat;
986 : }
987 :
988 341 : SwSectionNode::SwSectionNode(SwNodeIndex const& rIdx,
989 : SwSectionFormat & rFormat, SwTOXBase const*const pTOXBase)
990 : : SwStartNode( rIdx, ND_SECTIONNODE )
991 : , m_pSection( (pTOXBase)
992 119 : ? new SwTOXBaseSection(*pTOXBase, lcl_initParent(*this, rFormat))
993 : : new SwSection( CONTENT_SECTION, rFormat.GetName(),
994 460 : lcl_initParent(*this, rFormat) ) )
995 : {
996 : // Set the connection from Format to Node
997 : // Suppress Modify; no one's interessted anyway
998 341 : rFormat.LockModify();
999 341 : rFormat.SetFormatAttr( SwFormatContent( this ) );
1000 341 : rFormat.UnlockModify();
1001 341 : }
1002 :
1003 : #ifdef DBG_UTIL
1004 : //remove superfluous SectionFrms
1005 : SwFrm* SwClearDummies( SwFrm* pFrm )
1006 : {
1007 : SwFrm* pTmp = pFrm;
1008 : while( pTmp )
1009 : {
1010 : OSL_ENSURE( !pTmp->GetUpper(), "SwClearDummies: No Upper allowed!" );
1011 : if( pTmp->IsSctFrm() )
1012 : {
1013 : SwSectionFrm* pSectFrm = static_cast<SwSectionFrm*>(pFrm);
1014 : pTmp = pTmp->GetNext();
1015 : if( !pSectFrm->GetLower() )
1016 : {
1017 : if( pSectFrm->GetPrev() )
1018 : pSectFrm->GetPrev()->mpNext = pTmp;
1019 : else
1020 : pFrm = pTmp;
1021 : if( pTmp )
1022 : pTmp->mpPrev = pSectFrm->GetPrev();
1023 : SwFrm::DestroyFrm(pSectFrm);
1024 : }
1025 : }
1026 : else
1027 : pTmp = pTmp->GetNext();
1028 : }
1029 : return pFrm;
1030 : }
1031 : #endif
1032 :
1033 1023 : SwSectionNode::~SwSectionNode()
1034 : {
1035 : // mba: test if iteration works as clients will be removed in callback
1036 : // use hint which allows to specify, if the content shall be saved or not
1037 341 : m_pSection->GetFormat()->CallSwClientNotify( SwSectionFrmMoveAndDeleteHint( true ) );
1038 341 : SwSectionFormat* pFormat = m_pSection->GetFormat();
1039 341 : if( pFormat )
1040 : {
1041 : // Remove the Attributei, because the Section deletes it's Format
1042 : // and it will neutralize the Section, if the Content Attribute is set
1043 341 : pFormat->LockModify();
1044 341 : pFormat->ResetFormatAttr( RES_CNTNT );
1045 341 : pFormat->UnlockModify();
1046 : }
1047 682 : }
1048 :
1049 358 : SwFrm *SwSectionNode::MakeFrm( SwFrm *pSib )
1050 : {
1051 358 : m_pSection->m_Data.SetHiddenFlag(false);
1052 358 : return new SwSectionFrm( *m_pSection, pSib );
1053 : }
1054 :
1055 : // Creates all Document Views for the precedeing Node.
1056 : // The created ContentFrames are attached to the corresponding Layout
1057 2 : void SwSectionNode::MakeFrms(const SwNodeIndex & rIdx )
1058 : {
1059 : // Take my succsessive or preceding ContentFrame
1060 2 : SwNodes& rNds = GetNodes();
1061 2 : if( rNds.IsDocNodes() && rNds.GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell() )
1062 : {
1063 2 : if( GetSection().IsHidden() || IsContentHidden() )
1064 : {
1065 0 : SwNodeIndex aIdx( *EndOfSectionNode() );
1066 0 : SwContentNode* pCNd = rNds.GoNextSection( &aIdx, true, false );
1067 0 : if( !pCNd )
1068 : {
1069 0 : aIdx = *this;
1070 0 : pCNd = SwNodes::GoPrevSection(&aIdx, true, false);
1071 0 : if (!pCNd)
1072 2 : return;
1073 : }
1074 0 : pCNd = aIdx.GetNode().GetContentNode();
1075 0 : pCNd->MakeFrms( static_cast<SwContentNode&>(rIdx.GetNode()) );
1076 : }
1077 : else
1078 : {
1079 2 : SwNode2Layout aNode2Layout( *this, rIdx.GetIndex() );
1080 : SwFrm *pFrm;
1081 6 : while( 0 != (pFrm = aNode2Layout.NextFrm()) )
1082 : {
1083 : OSL_ENSURE( pFrm->IsSctFrm(), "Depend of Section not a Section." );
1084 2 : SwFrm *pNew = rIdx.GetNode().GetContentNode()->MakeFrm( pFrm );
1085 :
1086 2 : SwSectionNode* pS = rIdx.GetNode().FindSectionNode();
1087 :
1088 : // Assure that node is not inside a table, which is inside the
1089 : // found section.
1090 2 : if ( pS )
1091 : {
1092 0 : SwTableNode* pTableNode = rIdx.GetNode().FindTableNode();
1093 0 : if ( pTableNode &&
1094 0 : pTableNode->GetIndex() > pS->GetIndex() )
1095 : {
1096 0 : pS = 0;
1097 : }
1098 : }
1099 :
1100 : // if the node is in a section, the sectionframe now
1101 : // has to be created..
1102 : // boolean to control <Init()> of a new section frame.
1103 2 : bool bInitNewSect = false;
1104 2 : if( pS )
1105 : {
1106 0 : SwSectionFrm *pSct = new SwSectionFrm( pS->GetSection(), pFrm );
1107 : // prepare <Init()> of new section frame.
1108 0 : bInitNewSect = true;
1109 0 : SwLayoutFrm* pUp = pSct;
1110 0 : while( pUp->Lower() ) // for columned sections
1111 : {
1112 : OSL_ENSURE( pUp->Lower()->IsLayoutFrm(),"Who's in there?" );
1113 0 : pUp = static_cast<SwLayoutFrm*>(pUp->Lower());
1114 : }
1115 0 : pNew->Paste( pUp, NULL );
1116 : // #i27138#
1117 : // notify accessibility paragraphs objects about changed
1118 : // CONTENT_FLOWS_FROM/_TO relation.
1119 : // Relation CONTENT_FLOWS_FROM for next paragraph will change
1120 : // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1121 0 : if ( pNew->IsTextFrm() )
1122 : {
1123 0 : SwViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() );
1124 0 : if ( pViewShell && pViewShell->GetLayout() &&
1125 0 : pViewShell->GetLayout()->IsAnyShellAccessible() )
1126 : {
1127 : pViewShell->InvalidateAccessibleParaFlowRelation(
1128 0 : dynamic_cast<SwTextFrm*>(pNew->FindNextCnt( true )),
1129 0 : dynamic_cast<SwTextFrm*>(pNew->FindPrevCnt( true )) );
1130 : }
1131 : }
1132 0 : pNew = pSct;
1133 : }
1134 :
1135 : // If a Node got Frames attached before or after
1136 2 : if ( rIdx < GetIndex() )
1137 : // the new one precedes me
1138 2 : pNew->Paste( pFrm->GetUpper(), pFrm );
1139 : else
1140 : // the new one succeeds me
1141 0 : pNew->Paste( pFrm->GetUpper(), pFrm->GetNext() );
1142 : // #i27138#
1143 : // notify accessibility paragraphs objects about changed
1144 : // CONTENT_FLOWS_FROM/_TO relation.
1145 : // Relation CONTENT_FLOWS_FROM for next paragraph will change
1146 : // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1147 2 : if ( pNew->IsTextFrm() )
1148 : {
1149 2 : SwViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() );
1150 4 : if ( pViewShell && pViewShell->GetLayout() &&
1151 2 : pViewShell->GetLayout()->IsAnyShellAccessible() )
1152 : {
1153 : pViewShell->InvalidateAccessibleParaFlowRelation(
1154 0 : dynamic_cast<SwTextFrm*>(pNew->FindNextCnt( true )),
1155 0 : dynamic_cast<SwTextFrm*>(pNew->FindPrevCnt( true )) );
1156 : }
1157 : }
1158 2 : if ( bInitNewSect )
1159 0 : static_cast<SwSectionFrm*>(pNew)->Init();
1160 2 : }
1161 : }
1162 : }
1163 : }
1164 :
1165 : // Create a new SectionFrm for every occurrence in the Layout and insert before
1166 : // the corresponding ContentFrm
1167 29 : void SwSectionNode::MakeFrms( SwNodeIndex* pIdxBehind, SwNodeIndex* pEndIdx )
1168 : {
1169 : OSL_ENSURE( pIdxBehind, "no Index" );
1170 29 : SwNodes& rNds = GetNodes();
1171 29 : SwDoc* pDoc = rNds.GetDoc();
1172 :
1173 29 : *pIdxBehind = *this;
1174 :
1175 29 : m_pSection->m_Data.SetHiddenFlag(true);
1176 :
1177 29 : if( rNds.IsDocNodes() )
1178 : {
1179 : SwNodeIndex *pEnd = pEndIdx ? pEndIdx :
1180 27 : new SwNodeIndex( *EndOfSectionNode(), 1 );
1181 27 : ::MakeFrms( pDoc, *pIdxBehind, *pEnd );
1182 27 : if( !pEndIdx )
1183 27 : delete pEnd;
1184 : }
1185 29 : }
1186 :
1187 25 : void SwSectionNode::DelFrms()
1188 : {
1189 25 : sal_uLong nStt = GetIndex()+1, nEnd = EndOfSectionIndex();
1190 25 : if( nStt >= nEnd )
1191 : {
1192 25 : return ;
1193 : }
1194 :
1195 25 : SwNodes& rNds = GetNodes();
1196 25 : m_pSection->GetFormat()->DelFrms();
1197 :
1198 : // Update our Flag
1199 25 : m_pSection->m_Data.SetHiddenFlag(true);
1200 :
1201 : // If the Area is within a Fly or TableBox, we can only hide it if
1202 : // there is more Content which has Frames.
1203 : // Or else the Fly/TableBox Frame does not have a Lower!
1204 : {
1205 25 : SwNodeIndex aIdx( *this );
1206 119 : if( !SwNodes::GoPrevSection( &aIdx, true, false ) ||
1207 128 : !CheckNodesRange( *this, aIdx, true ) ||
1208 : // #i21457#
1209 15 : !lcl_IsInSameTableBox( rNds, *this, true ))
1210 : {
1211 10 : aIdx = *EndOfSectionNode();
1212 50 : if( !rNds.GoNextSection( &aIdx, true, false ) ||
1213 56 : !CheckNodesRange( *EndOfSectionNode(), aIdx, true ) ||
1214 : // #i21457#
1215 6 : !lcl_IsInSameTableBox( rNds, *EndOfSectionNode(), false ))
1216 : {
1217 4 : m_pSection->m_Data.SetHiddenFlag(false);
1218 : }
1219 25 : }
1220 : }
1221 : }
1222 :
1223 6 : SwSectionNode* SwSectionNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
1224 : {
1225 : // In which array am I: Nodes, UndoNodes?
1226 6 : const SwNodes& rNds = GetNodes();
1227 :
1228 : // Copy the SectionFrameFormat
1229 6 : SwSectionFormat* pSectFormat = pDoc->MakeSectionFormat( 0 );
1230 6 : pSectFormat->CopyAttrs( *GetSection().GetFormat() );
1231 :
1232 6 : boost::scoped_ptr<SwTOXBase> pTOXBase;
1233 6 : if (TOX_CONTENT_SECTION == GetSection().GetType())
1234 : {
1235 : OSL_ENSURE( GetSection().ISA( SwTOXBaseSection ), "no TOXBaseSection!" );
1236 : SwTOXBaseSection const& rTBS(
1237 0 : dynamic_cast<SwTOXBaseSection const&>(GetSection()));
1238 0 : pTOXBase.reset( new SwTOXBase(rTBS, pDoc) );
1239 : }
1240 :
1241 : SwSectionNode *const pSectNd =
1242 6 : new SwSectionNode(rIdx, *pSectFormat, pTOXBase.get());
1243 6 : SwEndNode* pEndNd = new SwEndNode( rIdx, *pSectNd );
1244 12 : SwNodeIndex aInsPos( *pEndNd );
1245 :
1246 : // Take over values
1247 6 : SwSection *const pNewSect = pSectNd->m_pSection.get();
1248 :
1249 6 : if (TOX_CONTENT_SECTION != GetSection().GetType())
1250 : {
1251 : // Keep the Name for Move
1252 6 : if( rNds.GetDoc() == pDoc && pDoc->IsCopyIsMove() )
1253 : {
1254 0 : pNewSect->SetSectionName( GetSection().GetSectionName() );
1255 : }
1256 : else
1257 : {
1258 6 : const OUString sSectionName(GetSection().GetSectionName());
1259 6 : pNewSect->SetSectionName(pDoc->GetUniqueSectionName( &sSectionName ));
1260 : }
1261 : }
1262 :
1263 6 : pNewSect->SetType( GetSection().GetType() );
1264 6 : pNewSect->SetCondition( GetSection().GetCondition() );
1265 6 : pNewSect->SetLinkFileName( GetSection().GetLinkFileName() );
1266 6 : if( !pNewSect->IsHiddenFlag() && GetSection().IsHidden() )
1267 0 : pNewSect->SetHidden( true );
1268 6 : if( !pNewSect->IsProtectFlag() && GetSection().IsProtect() )
1269 0 : pNewSect->SetProtect( true );
1270 : // edit in readonly sections
1271 6 : if( !pNewSect->IsEditInReadonlyFlag() && GetSection().IsEditInReadonly() )
1272 0 : pNewSect->SetEditInReadonly( true );
1273 :
1274 12 : SwNodeRange aRg( *this, +1, *EndOfSectionNode() ); // Where am I?
1275 6 : rNds._Copy( aRg, aInsPos, false );
1276 :
1277 : // Delete all Frames from the copied Area. They are created when creating
1278 : // the SectionFrames.
1279 6 : pSectNd->DelFrms();
1280 :
1281 : // Copy the Links/Server
1282 6 : if( pNewSect->IsLinkType() ) // Add the Link
1283 0 : pNewSect->CreateLink( pDoc->getIDocumentLayoutAccess().GetCurrentViewShell() ? CREATE_CONNECT : CREATE_NONE );
1284 :
1285 : // If we copy from the Undo as Server, enter it again
1286 12 : if (m_pSection->IsServer()
1287 6 : && pDoc->GetIDocumentUndoRedo().IsUndoNodes(rNds))
1288 : {
1289 0 : pNewSect->SetRefObject( m_pSection->GetObject() );
1290 0 : pDoc->getIDocumentLinksAdministration().GetLinkManager().InsertServer( pNewSect->GetObject() );
1291 : }
1292 :
1293 : // METADATA: copy xml:id; must be done after insertion of node
1294 6 : pSectFormat->RegisterAsCopyOf(*GetSection().GetFormat());
1295 :
1296 12 : return pSectNd;
1297 : }
1298 :
1299 4 : bool SwSectionNode::IsContentHidden() const
1300 : {
1301 : OSL_ENSURE( !m_pSection->IsHidden(),
1302 : "That's simple: Hidden Section => Hidden Content" );
1303 4 : SwNodeIndex aTmp( *this, 1 );
1304 4 : sal_uLong nEnd = EndOfSectionIndex();
1305 8 : while( aTmp < nEnd )
1306 : {
1307 4 : if( aTmp.GetNode().IsSectionNode() )
1308 : {
1309 0 : const SwSection& rSect = static_cast<SwSectionNode&>(aTmp.GetNode()).GetSection();
1310 0 : if( rSect.IsHiddenFlag() )
1311 : // Skip this Section
1312 0 : aTmp = *aTmp.GetNode().EndOfSectionNode();
1313 : }
1314 : else
1315 : {
1316 4 : if( aTmp.GetNode().IsContentNode() || aTmp.GetNode().IsTableNode() )
1317 4 : return false; // We found non-hidden content
1318 : OSL_ENSURE( aTmp.GetNode().IsEndNode(), "EndNode expected" );
1319 : }
1320 0 : ++aTmp;
1321 : }
1322 0 : return true; // Hide everything
1323 : }
1324 :
1325 4 : void SwSectionNode::NodesArrChgd()
1326 : {
1327 4 : SwSectionFormat *const pFormat = m_pSection->GetFormat();
1328 4 : if( pFormat )
1329 : {
1330 4 : SwNodes& rNds = GetNodes();
1331 4 : SwDoc* pDoc = pFormat->GetDoc();
1332 :
1333 4 : if( !rNds.IsDocNodes() )
1334 : {
1335 4 : SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFormat );
1336 4 : pFormat->ModifyNotification( &aMsgHint, &aMsgHint );
1337 : }
1338 :
1339 4 : pFormat->LockModify();
1340 4 : pFormat->SetFormatAttr( SwFormatContent( this ));
1341 4 : pFormat->UnlockModify();
1342 :
1343 4 : SwSectionNode* pSectNd = StartOfSectionNode()->FindSectionNode();
1344 : // set the correct parent from the new section
1345 2 : pFormat->SetDerivedFrom( pSectNd ? pSectNd->GetSection().GetFormat()
1346 6 : : pDoc->GetDfltFrameFormat() );
1347 :
1348 : // Set the right StartNode for all in this Area
1349 4 : sal_uLong nStart = GetIndex()+1, nEnde = EndOfSectionIndex();
1350 4 : for( sal_uLong n = nStart; n < nEnde; ++n )
1351 : // Make up the Format's nesting
1352 0 : if( 0 != ( pSectNd = rNds[ n ]->GetSectionNode() ) )
1353 : {
1354 0 : pSectNd->GetSection().GetFormat()->SetDerivedFrom( pFormat );
1355 0 : n = pSectNd->EndOfSectionIndex();
1356 : }
1357 :
1358 : // Moving Nodes to the UndoNodes array?
1359 4 : if( rNds.IsDocNodes() )
1360 : {
1361 : OSL_ENSURE( pDoc == GetDoc(),
1362 : "Moving to different Documents?" );
1363 0 : if( m_pSection->IsLinkType() ) // Remove the Link
1364 0 : m_pSection->CreateLink( pDoc->getIDocumentLayoutAccess().GetCurrentViewShell() ? CREATE_CONNECT : CREATE_NONE );
1365 :
1366 0 : if (m_pSection->IsServer())
1367 0 : pDoc->getIDocumentLinksAdministration().GetLinkManager().InsertServer( m_pSection->GetObject() );
1368 : }
1369 : else
1370 : {
1371 8 : if (CONTENT_SECTION != m_pSection->GetType()
1372 4 : && m_pSection->IsConnected())
1373 : {
1374 0 : pDoc->getIDocumentLinksAdministration().GetLinkManager().Remove( &m_pSection->GetBaseLink() );
1375 : }
1376 4 : if (m_pSection->IsServer())
1377 0 : pDoc->getIDocumentLinksAdministration().GetLinkManager().RemoveServer( m_pSection->GetObject() );
1378 : }
1379 : }
1380 4 : }
1381 :
1382 218 : OUString SwDoc::GetUniqueSectionName( const OUString* pChkStr ) const
1383 : {
1384 218 : if( IsInMailMerge())
1385 : {
1386 : OUString newName = "MailMergeSection"
1387 0 : + OStringToOUString( DateTimeToOString( DateTime( DateTime::SYSTEM )), RTL_TEXTENCODING_ASCII_US )
1388 0 : + OUString::number( mpSectionFormatTable->size() + 1 );
1389 0 : if( pChkStr )
1390 0 : newName += *pChkStr;
1391 0 : return newName;
1392 : }
1393 :
1394 218 : const OUString aName( ResId( STR_REGION_DEFNAME, *pSwResMgr ) );
1395 :
1396 218 : SwSectionFormats::size_type nNum = 0;
1397 218 : const SwSectionFormats::size_type nFlagSize = ( mpSectionFormatTable->size() / 8 ) + 2;
1398 218 : sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
1399 218 : memset( pSetFlags, 0, nFlagSize );
1400 :
1401 802 : for( auto pFormat : *mpSectionFormatTable )
1402 : {
1403 584 : const SwSectionNode *const pSectNd = pFormat->GetSectionNode( false );
1404 584 : if( pSectNd != nullptr )
1405 : {
1406 584 : const OUString rNm = pSectNd->GetSection().GetSectionName();
1407 584 : if (rNm.startsWith( aName ))
1408 : {
1409 : // Calculate the Number and reset the Flag
1410 205 : nNum = rNm.copy( aName.getLength() ).toInt32();
1411 205 : if( nNum-- && nNum < mpSectionFormatTable->size() )
1412 199 : pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
1413 : }
1414 584 : if( pChkStr && *pChkStr==rNm )
1415 50 : pChkStr = 0;
1416 : }
1417 : }
1418 :
1419 218 : if( !pChkStr )
1420 : {
1421 : // Flagged all Numbers accordingly, so get the right Number
1422 55 : nNum = mpSectionFormatTable->size();
1423 63 : for( SwSectionFormats::size_type n = 0; n < nFlagSize; ++n )
1424 : {
1425 63 : auto nTmp = pSetFlags[ n ];
1426 63 : if( nTmp != 0xFF )
1427 : {
1428 : // Calculate the Number
1429 55 : nNum = n * 8;
1430 189 : while( nTmp & 1 )
1431 : {
1432 79 : ++nNum;
1433 79 : nTmp >>= 1;
1434 : }
1435 55 : break;
1436 : }
1437 : }
1438 : }
1439 218 : delete [] pSetFlags;
1440 218 : if( pChkStr )
1441 163 : return *pChkStr;
1442 55 : return aName + OUString::number( ++nNum );
1443 177 : }
1444 :
1445 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|