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