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