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