update dev300-m58
[ooovba.git] / sw / source / core / docnode / ndsect.cxx
bloba6363a209b7601f1600947a1e579ee53212d0d22
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ndsect.cxx,v $
10 * $Revision: 1.35 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <svx/linkmgr.hxx>
37 #include <svtools/itemiter.hxx>
38 #include <tools/resid.hxx>
39 #include <fmtcntnt.hxx>
40 #include <fmtanchr.hxx>
41 #include <txtftn.hxx>
42 #include <fmtclds.hxx>
43 #include <doc.hxx>
44 #include <rootfrm.hxx>
45 #include <pam.hxx>
46 #include <ndtxt.hxx>
47 #include <section.hxx>
48 #include <undobj.hxx>
49 #include <swundo.hxx>
50 #include <calc.hxx>
51 #include <swtable.hxx>
52 #include <swserv.hxx>
53 #include <frmfmt.hxx>
54 #include <frmtool.hxx>
55 #include <ftnidx.hxx>
56 #include <docary.hxx>
57 #include <redline.hxx>
58 #include <sectfrm.hxx>
59 #include <pagefrm.hxx>
60 #include <cntfrm.hxx>
61 #include <node2lay.hxx>
62 #include <doctxm.hxx>
63 #include <fmtftntx.hxx>
64 #ifndef _COMCORE_HRC
65 #include <comcore.hrc>
66 #endif
67 // --> OD 2005-12-01 #i27138#
68 #include <viewsh.hxx>
69 #include <txtfrm.hxx>
70 // <--
73 // OD 04.11.2003 #i21457# - new implementation of local method <lcl_IsInSameTblBox(..)>.
74 // Method now determines the previous/next on its own. Thus, it can be controlled,
75 // for which previous/next is checked, if it's visible.
76 bool lcl_IsInSameTblBox( SwNodes& _rNds,
77 const SwNode& _rNd,
78 const bool _bPrev )
80 const SwTableNode* pTblNd = _rNd.FindTableNode();
81 if ( !pTblNd )
83 return true;
86 // determine index to be checked. Its assumed that a previous/next exist.
87 SwNodeIndex aChkIdx( _rNd );
89 // determine index of previous/next - skip hidden ones, which are
90 // inside the table.
91 // If found one is before/after table, this one isn't in the same
92 // table box as <_rNd>.
93 bool bFound = false;
96 if ( _bPrev
97 ? !_rNds.GoPrevSection( &aChkIdx, FALSE, FALSE )
98 : !_rNds.GoNextSection( &aChkIdx, FALSE, FALSE ) )
100 ASSERT( false, "<lcl_IsInSameTblBox(..)> - no previous/next!" );
101 return false;
103 else
105 if ( aChkIdx < pTblNd->GetIndex() ||
106 aChkIdx > pTblNd->EndOfSectionNode()->GetIndex() )
108 return false;
110 else
112 // check, if found one isn't inside a hidden section, which
113 // is also inside the table.
114 SwSectionNode* pSectNd = aChkIdx.GetNode().FindSectionNode();
115 if ( !pSectNd ||
116 pSectNd->GetIndex() < pTblNd->GetIndex() ||
117 !pSectNd->GetSection().IsHiddenFlag() )
119 bFound = true;
123 } while ( !bFound );
126 // dann suche den StartNode der Box
127 const SwTableSortBoxes& rSortBoxes = pTblNd->GetTable().GetTabSortBoxes();
128 ULONG nIdx = _rNd.GetIndex();
129 for( USHORT n = 0; n < rSortBoxes.Count(); ++n )
131 const SwStartNode* pNd = rSortBoxes[ n ]->GetSttNd();
132 if ( pNd->GetIndex() < nIdx && nIdx < pNd->EndOfSectionIndex() )
134 // dann muss der andere Index in derselben Section liegen
135 nIdx = aChkIdx.GetIndex();
136 return pNd->GetIndex() < nIdx && nIdx < pNd->EndOfSectionIndex();
140 return true;
143 void lcl_CheckEmptyLayFrm( SwNodes& rNds, SwSection& rSect,
144 const SwNode& rStt, const SwNode& rEnd )
146 SwNodeIndex aIdx( rStt );
147 if( !rNds.GoPrevSection( &aIdx, TRUE, FALSE ) ||
148 !CheckNodesRange( rStt, aIdx, TRUE ) ||
149 // OD 04.11.2003 #i21457#
150 !lcl_IsInSameTblBox( rNds, rStt, true ))
152 aIdx = rEnd;
153 if( !rNds.GoNextSection( &aIdx, TRUE, FALSE ) ||
154 !CheckNodesRange( rEnd, aIdx, TRUE ) ||
155 // OD 04.11.2003 #i21457#
156 !lcl_IsInSameTblBox( rNds, rEnd, false ))
157 rSect.SetHidden( FALSE );
161 SwSection* SwDoc::Insert( const SwPaM& rRange, const SwSection& rNew,
162 const SfxItemSet* pAttr, BOOL bUpdate )
164 const SwNode* pPrvNd = 0;
165 USHORT nRegionRet = 0;
166 if( rRange.HasMark() &&
167 0 == ( nRegionRet = IsInsRegionAvailable( rRange, &pPrvNd ) ))
169 ASSERT( !this, "Selection ueber verschiedene Sections" );
170 return 0;
173 // Teste ob das gesamte Dokument versteckt werden soll,
174 // koennen wir zur Zeit nicht !!!!
175 if( rNew.IsHidden() && rRange.HasMark() )
177 const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End();
178 if( !pStt->nContent.GetIndex() &&
179 pEnd->nNode.GetNode().GetCntntNode()->Len() ==
180 pEnd->nContent.GetIndex() )
182 ::lcl_CheckEmptyLayFrm( GetNodes(), (SwSection&)rNew,
183 pStt->nNode.GetNode(),
184 pEnd->nNode.GetNode() );
187 SwUndoInsSection* pUndoInsSect = 0;
188 if( DoesUndo() )
190 ClearRedo();
191 pUndoInsSect = new SwUndoInsSection( rRange, rNew, pAttr );
192 AppendUndo( pUndoInsSect );
193 DoUndo( FALSE );
196 SwSectionFmt* pFmt = MakeSectionFmt( 0 );
197 if( pAttr )
198 pFmt->SetFmtAttr( *pAttr );
200 SwSectionNode* pNewSectNode = 0;
202 RedlineMode_t eOld = GetRedlineMode();
203 SetRedlineMode_intern( (RedlineMode_t)((eOld & ~nsRedlineMode_t::REDLINE_SHOW_MASK) | nsRedlineMode_t::REDLINE_IGNORE));
205 if( rRange.HasMark() )
207 SwPosition *pSttPos = (SwPosition*)rRange.Start(),
208 *pEndPos = (SwPosition*)rRange.End();
209 if( pPrvNd && 3 == nRegionRet )
211 ASSERT( pPrvNd, "der SectionNode fehlt" );
212 SwNodeIndex aStt( pSttPos->nNode ), aEnd( pEndPos->nNode, +1 );
213 while( pPrvNd != aStt.GetNode().StartOfSectionNode() )
214 aStt--;
215 while( pPrvNd != aEnd.GetNode().StartOfSectionNode() )
216 aEnd++;
218 --aEnd; // im InsertSection ist Ende inclusive
219 pNewSectNode = GetNodes().InsertSection( aStt, *pFmt, rNew, &aEnd );
221 else
223 if( pUndoInsSect )
225 SwTxtNode* pTNd;
226 if( !( pPrvNd && 1 == nRegionRet ) &&
227 pSttPos->nContent.GetIndex() &&
228 0 != ( pTNd = pSttPos->nNode.GetNode().GetTxtNode() ))
229 pUndoInsSect->SaveSplitNode( pTNd, TRUE );
231 if( !( pPrvNd && 2 == nRegionRet ) &&
232 0 != ( pTNd = pEndPos->nNode.GetNode().GetTxtNode() ) &&
233 pTNd->GetTxt().Len() != pEndPos->nContent.GetIndex() )
234 pUndoInsSect->SaveSplitNode( pTNd, FALSE );
237 const SwCntntNode* pCNd;
238 if( pPrvNd && 1 == nRegionRet )
240 pSttPos->nNode.Assign( *pPrvNd );
241 pSttPos->nContent.Assign( pSttPos->nNode.GetNode().GetCntntNode(), 0 );
243 else if( pSttPos->nContent.GetIndex() )
244 SplitNode( *pSttPos, false );
246 if( pPrvNd && 2 == nRegionRet )
248 pEndPos->nNode.Assign( *pPrvNd );
249 pEndPos->nContent.Assign( pEndPos->nNode.GetNode().GetCntntNode(), 0 );
251 else
253 pCNd = pEndPos->nNode.GetNode().GetCntntNode();
254 if( pCNd && pCNd->Len() != pEndPos->nContent.GetIndex() )
256 xub_StrLen nCntnt = pSttPos->nContent.GetIndex();
257 SplitNode( *pEndPos, false );
259 SwTxtNode* pTNd;
260 if( pEndPos->nNode.GetIndex() == pSttPos->nNode.GetIndex() )
262 pSttPos->nNode--;
263 pEndPos->nNode--;
264 pTNd = pSttPos->nNode.GetNode().GetTxtNode();
265 pSttPos->nContent.Assign( pTNd, nCntnt );
267 else
269 // wieder ans Ende vom vorherigen setzen
270 pEndPos->nNode--;
271 pTNd = pEndPos->nNode.GetNode().GetTxtNode();
273 if( pTNd ) nCntnt = pTNd->GetTxt().Len(); else nCntnt = 0;
274 pEndPos->nContent.Assign( pTNd, nCntnt );
277 pNewSectNode = GetNodes().InsertSection( pSttPos->nNode, *pFmt, rNew,
278 &pEndPos->nNode );
281 else
283 const SwPosition* pPos = rRange.GetPoint();
284 const SwCntntNode* pCNd = pPos->nNode.GetNode().GetCntntNode();
285 if( !pPos->nContent.GetIndex() )
287 pNewSectNode = GetNodes().InsertSection( pPos->nNode, *pFmt, rNew, 0, TRUE );
289 else if( pPos->nContent.GetIndex() == pCNd->Len() )
291 pNewSectNode = GetNodes().InsertSection( pPos->nNode, *pFmt, rNew, 0, FALSE );
293 else
295 if( pUndoInsSect && pCNd->IsTxtNode() )
296 pUndoInsSect->SaveSplitNode( (SwTxtNode*)pCNd, TRUE );
297 SplitNode( *pPos, false );
298 pNewSectNode = GetNodes().InsertSection( pPos->nNode, *pFmt, rNew, 0, TRUE );
302 //FEATURE::CONDCOLL
303 pNewSectNode->CheckSectionCondColl();
304 //FEATURE::CONDCOLL
306 SetRedlineMode_intern( eOld );
308 if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
310 SwPaM aPam( *pNewSectNode->EndOfSectionNode(), *pNewSectNode, 1 );
311 if( IsRedlineOn() )
312 AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
313 else
314 SplitRedline( aPam );
317 // ist eine Condition gesetzt
318 if( rNew.IsHidden() && rNew.GetCondition().Len() )
320 // dann berechne bis zu dieser Position
321 SwCalc aCalc( *this );
322 if( ! IsInReading() )
323 FldsToCalc( aCalc, pNewSectNode->GetIndex(), USHRT_MAX );
324 SwSection& rNewSect = pNewSectNode->GetSection();
325 rNewSect.SetCondHidden( aCalc.Calculate( rNewSect.GetCondition() ).GetBool() );
328 BOOL bUpdateFtn = FALSE;
329 if( GetFtnIdxs().Count() && pAttr )
331 USHORT nVal = ((SwFmtFtnAtTxtEnd&)pAttr->Get(
332 RES_FTN_AT_TXTEND )).GetValue();
333 if( ( FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
334 FTNEND_ATTXTEND_OWNNUMANDFMT == nVal ) ||
335 ( FTNEND_ATTXTEND_OWNNUMSEQ == ( nVal = ((SwFmtEndAtTxtEnd&)
336 pAttr->Get( RES_END_AT_TXTEND )).GetValue() ) ||
337 FTNEND_ATTXTEND_OWNNUMANDFMT == nVal ))
338 bUpdateFtn = TRUE;
341 if( pUndoInsSect )
343 pUndoInsSect->SetSectNdPos( pNewSectNode->GetIndex() );
344 pUndoInsSect->SetUpdtFtnFlag( bUpdateFtn );
345 DoUndo( TRUE );
348 if( rNew.IsLinkType() )
349 pNewSectNode->GetSection().CreateLink( bUpdate ? CREATE_UPDATE : CREATE_CONNECT );
351 if( bUpdateFtn )
352 GetFtnIdxs().UpdateFtn( SwNodeIndex( *pNewSectNode ));
354 SetModified();
355 return &pNewSectNode->GetSection();
358 USHORT SwDoc::IsInsRegionAvailable( const SwPaM& rRange,
359 const SwNode** ppSttNd ) const
361 USHORT nRet = 1;
362 if( rRange.HasMark() )
364 // teste ob es sich um eine gueltige Selektion handelt
365 const SwPosition* pStt = rRange.Start(),
366 * pEnd = rRange.End();
368 const SwCntntNode* pCNd = pEnd->nNode.GetNode().GetCntntNode();
369 const SwNode* pNd = &pStt->nNode.GetNode();
370 const SwSectionNode* pSectNd = pNd->FindSectionNode();
371 const SwSectionNode* pEndSectNd = pCNd ? pCNd->FindSectionNode() : 0;
372 if( pSectNd && pEndSectNd && pSectNd != pEndSectNd )
374 // versuche eine umschliessende Section zu erzeugen
375 // Aber, nur wenn der Start am Sectionanfang und das Ende am
376 // Section Ende liegt!
377 nRet = 0;
378 if( !pStt->nContent.GetIndex() && pSectNd->GetIndex()
379 == pStt->nNode.GetIndex() - 1 && pEnd->nContent.GetIndex() ==
380 pCNd->Len() )
382 SwNodeIndex aIdx( pStt->nNode, -1 );
383 ULONG nCmp = pEnd->nNode.GetIndex();
384 const SwStartNode* pPrvNd;
385 const SwEndNode* pNxtNd;
386 while( 0 != ( pPrvNd = (pNd = &aIdx.GetNode())->GetSectionNode() ) &&
387 !( aIdx.GetIndex() < nCmp &&
388 nCmp < pPrvNd->EndOfSectionIndex() ) )
390 aIdx--;
392 if( !pPrvNd )
393 pPrvNd = pNd->IsStartNode() ? (SwStartNode*)pNd
394 : pNd->StartOfSectionNode();
396 aIdx = pEnd->nNode.GetIndex() + 1;
397 nCmp = pStt->nNode.GetIndex();
398 while( 0 != ( pNxtNd = (pNd = &aIdx.GetNode())->GetEndNode() ) &&
399 pNxtNd->StartOfSectionNode()->IsSectionNode() &&
400 !( pNxtNd->StartOfSectionIndex() < nCmp &&
401 nCmp < aIdx.GetIndex() ) )
403 aIdx++;
405 if( !pNxtNd )
406 pNxtNd = pNd->EndOfSectionNode();
408 if( pPrvNd && pNxtNd && pPrvNd == pNxtNd->StartOfSectionNode() )
410 nRet = 3;
412 if( ppSttNd )
413 *ppSttNd = pPrvNd;
417 else if( !pSectNd && pEndSectNd )
419 // versuche eine umschliessende Section zu erzeugen
420 // Aber, nur wenn das Ende am Section Ende liegt!
421 nRet = 0;
422 if( pEnd->nContent.GetIndex() == pCNd->Len() )
424 SwNodeIndex aIdx( pEnd->nNode, 1 );
425 if( aIdx.GetNode().IsEndNode() &&
426 0 != aIdx.GetNode().FindSectionNode() )
428 do {
429 aIdx++;
430 } while( aIdx.GetNode().IsEndNode() &&
431 0 != aIdx.GetNode().FindSectionNode() );
432 // if( !aIdx.GetNode().IsEndNode() )
434 nRet = 2;
435 if( ppSttNd )
437 aIdx--;
438 *ppSttNd = &aIdx.GetNode();
444 else if( pSectNd && !pEndSectNd )
446 // versuche eine umschliessende Section zu erzeugen
447 // Aber, nur wenn der Start am Section Anfang liegt!
448 nRet = 0;
449 if( !pStt->nContent.GetIndex() )
451 SwNodeIndex aIdx( pStt->nNode, -1 );
452 if( aIdx.GetNode().IsSectionNode() )
454 do {
455 aIdx--;
456 } while( aIdx.GetNode().IsSectionNode() );
457 if( !aIdx.GetNode().IsSectionNode() )
459 nRet = 1;
460 if( ppSttNd )
462 aIdx++;
463 *ppSttNd = &aIdx.GetNode();
470 return nRet;
473 SwSection* SwDoc::GetCurrSection( const SwPosition& rPos ) const
475 const SwSectionNode* pSectNd = rPos.nNode.GetNode().FindSectionNode();
476 if( pSectNd )
477 return (SwSection*)&pSectNd->GetSection();
478 return 0;
481 SwSectionFmt* SwDoc::MakeSectionFmt( SwSectionFmt *pDerivedFrom )
483 if( !pDerivedFrom )
484 pDerivedFrom = (SwSectionFmt*)pDfltFrmFmt;
485 SwSectionFmt* pNew = new SwSectionFmt( pDerivedFrom, this );
486 pSectionFmtTbl->Insert( pNew, pSectionFmtTbl->Count() );
487 return pNew;
490 void SwDoc::DelSectionFmt( SwSectionFmt *pFmt, BOOL bDelNodes )
492 USHORT nPos = pSectionFmtTbl->GetPos( pFmt );
494 StartUndo(UNDO_DELSECTION, NULL);
496 if( USHRT_MAX != nPos )
498 const SwNodeIndex* pIdx = pFmt->GetCntnt( FALSE ).GetCntntIdx();
499 const SfxPoolItem* pFtnEndAtTxtEnd;
500 if( SFX_ITEM_SET != pFmt->GetItemState(
501 RES_FTN_AT_TXTEND, TRUE, &pFtnEndAtTxtEnd ) ||
502 SFX_ITEM_SET != pFmt->GetItemState(
503 RES_END_AT_TXTEND, TRUE, &pFtnEndAtTxtEnd ))
504 pFtnEndAtTxtEnd = 0;
506 const SwSectionNode* pSectNd;
508 if( DoesUndo() )
510 ClearRedo();
511 if( bDelNodes && pIdx && &GetNodes() == &pIdx->GetNodes() &&
512 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
514 SwNodeIndex aUpdIdx( *pIdx );
515 ClearRedo();
516 SwPaM aPaM( *pSectNd->EndOfSectionNode(), *pSectNd );
517 AppendUndo( new SwUndoDelete( aPaM ));
518 if( pFtnEndAtTxtEnd )
519 GetFtnIdxs().UpdateFtn( aUpdIdx );
520 SetModified();
521 //#126178# start/end undo have to be pairs!
522 EndUndo(UNDO_DELSECTION, NULL);
523 return ;
525 AppendUndo( new SwUndoDelSection( *pFmt ) );
527 else if( bDelNodes && pIdx && &GetNodes() == &pIdx->GetNodes() &&
528 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
530 SwNodeIndex aUpdIdx( *pIdx );
531 DeleteSection( (SwNode*)pSectNd );
532 if( pFtnEndAtTxtEnd )
533 GetFtnIdxs().UpdateFtn( aUpdIdx );
534 SetModified();
535 //#126178# start/end undo have to be pairs!
536 EndUndo(UNDO_DELSECTION, NULL);
537 return ;
541 SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFmt );
542 pFmt->Modify( &aMsgHint, &aMsgHint );
545 // A ClearRedo could result in a rekursive call of this function and delete some section
546 // formats => the position iside the SectionFmtTbl could have changed
547 nPos = pSectionFmtTbl->GetPos( pFmt );
549 // ACHTUNG: erst aus dem Array entfernen und dann loeschen.
550 // Der Section-DTOR versucht selbst noch sein Format
551 // zu loeschen!
552 pSectionFmtTbl->Remove( nPos );
553 //FEATURE::CONDCOLL
554 ULONG nCnt = 0, nSttNd = 0;
555 if( pIdx && &GetNodes() == &pIdx->GetNodes() &&
556 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
558 nSttNd = pSectNd->GetIndex();
559 nCnt = pSectNd->EndOfSectionIndex() - nSttNd - 1;
561 //FEATURE::CONDCOLL
563 delete pFmt;
565 if( nSttNd && pFtnEndAtTxtEnd )
567 SwNodeIndex aUpdIdx( GetNodes(), nSttNd );
568 GetFtnIdxs().UpdateFtn( aUpdIdx );
571 //FEATURE::CONDCOLL
572 SwCntntNode* pCNd;
573 for( ; nCnt--; ++nSttNd )
574 if( 0 != (pCNd = GetNodes()[ nSttNd ]->GetCntntNode() ) &&
575 RES_CONDTXTFMTCOLL == pCNd->GetFmtColl()->Which() )
576 pCNd->ChkCondColl();
577 //FEATURE::CONDCOLL
580 EndUndo(UNDO_DELSECTION, NULL);
582 SetModified();
585 void SwDoc::ChgSection( USHORT nPos, const SwSection& rSect,
586 const SfxItemSet* pAttr,
587 sal_Bool bPreventLinkUpdate )
589 SwSectionFmt* pFmt = (*pSectionFmtTbl)[ nPos ];
590 SwSection* pSection = pFmt->GetSection();
591 /// OD 04.10.2002 #102894#
592 /// remember hidden condition flag of SwSection before changes
593 bool bOldCondHidden = pSection->IsCondHidden() ? true : false;
595 if( *pSection == rSect )
597 // die Attribute ueberpruefen
598 BOOL bOnlyAttrChg = FALSE;
599 if( pAttr && pAttr->Count() )
601 SfxItemIter aIter( *pAttr );
602 USHORT nWhich = aIter.GetCurItem()->Which();
603 while( TRUE )
605 if( pFmt->GetFmtAttr( nWhich ) != *aIter.GetCurItem() )
607 bOnlyAttrChg = TRUE;
608 break;
611 if( aIter.IsAtEnd() )
612 break;
613 nWhich = aIter.NextItem()->Which();
617 if( bOnlyAttrChg )
619 const BOOL bDoesUndo = DoesUndo();
620 if( DoesUndo() )
622 ClearRedo();
623 AppendUndo( new SwUndoChgSection( *pFmt, TRUE ) );
624 // --> FME 2004-10-13 #i32968#
625 // Inserting columns in the section causes MakeFrmFmt to put two
626 // objects of type SwUndoFrmFmt on the undo stack. We don't want them.
627 DoUndo( FALSE );
628 // <--
630 pFmt->SetFmtAttr( *pAttr );
631 SetModified();
633 // --> FME 2004-10-13 #i32968#
634 DoUndo( bDoesUndo );
635 // <--
637 return;
640 // Teste ob eine gesamte Content-Section (Dokument/TabellenBox/Fly)
641 // versteckt werden soll, koennen wir zur Zeit nicht !!!!
642 const SwNodeIndex* pIdx = 0;
644 const SwSectionNode* pSectNd;
645 if( rSect.IsHidden() && 0 != (pIdx = pFmt->GetCntnt().GetCntntIdx() )
646 && 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ) )
648 ::lcl_CheckEmptyLayFrm( GetNodes(), (SwSection&)rSect,
649 *pSectNd, *pSectNd->EndOfSectionNode() );
653 const BOOL bDoesUndo = DoesUndo();
654 if( DoesUndo() )
656 ClearRedo();
657 AppendUndo( new SwUndoChgSection( *pFmt, FALSE ) );
658 // --> FME 2004-10-13 #i32968#
659 // Inserting columns in the section causes MakeFrmFmt to put two
660 // objects of type SwUndoFrmFmt on the undo stack. We don't want them.
661 DoUndo( FALSE );
662 // <--
665 // #56167# Der LinkFileName koennte auch nur aus Separatoren bestehen
666 String sCompareString = sfx2::cTokenSeperator;
667 sCompareString += sfx2::cTokenSeperator;
668 BOOL bUpdate = ( !pSection->IsLinkType() && rSect.IsLinkType() ) ||
669 ( rSect.GetLinkFileName().Len() &&
670 rSect.GetLinkFileName() != sCompareString &&
671 rSect.GetLinkFileName() !=
672 pSection->GetLinkFileName());
674 String sSectName( rSect.GetName() );
675 if( sSectName != pSection->GetName() )
676 GetUniqueSectionName( &sSectName );
677 else
678 sSectName.Erase();
680 /// OD 04.10.2002 #102894# - NOTE
681 /// In SwSection::operator=(..) class member bCondHiddenFlag is always set to TRUE.
682 /// IMHO this have to be changed, but I can't estimate the consequences:
683 /// Either it is set to TRUE using corresponding method <SwSection.SetCondHidden(..)>,
684 /// or it is set to the value of SwSection which is assigned to it.
685 /// Discussion with AMA results that the adjustment to the assignment operator
686 /// could be very risky -> see notes in bug #102894#.
687 *pSection = rSect;
689 if( pAttr )
690 pSection->GetFmt()->SetFmtAttr( *pAttr );
692 if( sSectName.Len() )
693 pSection->SetName( sSectName );
695 // ist eine Condition gesetzt
696 if( pSection->IsHidden() && pSection->GetCondition().Len() )
698 // dann berechne bis zu dieser Position
699 SwCalc aCalc( *this );
700 if( !pIdx )
701 pIdx = pFmt->GetCntnt().GetCntntIdx();
702 FldsToCalc( aCalc, pIdx->GetIndex(), USHRT_MAX );
703 /// OD 04.10.2002 #102894#
704 /// Because on using SwSection::operator=() to set up <pSection>
705 /// with <rSect> and the above given note, the hidden condition flag
706 /// has to be set to FALSE, if hidden condition flag of <pFmt->GetSection()>
707 /// (SwSection before the changes) is FALSE (already saved in <bOldCondHidden>)
708 /// and new calculated condition is TRUE.
709 /// This is necessary, because otherwise the <SetCondHidden> would have
710 /// no effect.
711 bool bCalculatedCondHidden =
712 aCalc.Calculate( pSection->GetCondition() ).GetBool() ? true : false;
713 if ( bCalculatedCondHidden && !bOldCondHidden )
715 pSection->SetCondHidden( false );
717 pSection->SetCondHidden( bCalculatedCondHidden );
720 if( bUpdate )
721 pSection->CreateLink( bPreventLinkUpdate ? CREATE_CONNECT : CREATE_UPDATE );
722 else if( !pSection->IsLinkType() && pSection->IsConnected() )
724 pSection->Disconnect();
725 GetLinkManager().Remove( &pSection->GetBaseLink() );
728 SetModified();
730 // --> FME 2004-10-13 #i32968#
731 DoUndo( bDoesUndo );
732 // <--
735 /* -----------------19.02.99 09:31-------------------
736 * LockFrms wurde im InsertSection genutzt, um zu verhindern, dass
737 * SectionFrms durch das DelFrms zerstoert werden. Dies ist durch
738 * den Destroy-Listen-Mechanismus ueberfluessig geworden.
739 * Falls diese Methode doch noch einmal reanimiert wird, bietet es
740 * sich vielleicht an, beim Entlocken die SectionFrms auf Inhalt zu
741 * pruefen und dann ggf. zur Zerstoerung anzumelden.
742 * --------------------------------------------------*/
744 // und dann waren da noch die Fussnoten:
745 void lcl_DeleteFtn( SwSectionNode *pNd, ULONG nStt, ULONG nEnd )
747 SwFtnIdxs& rFtnArr = pNd->GetDoc()->GetFtnIdxs();
748 if( rFtnArr.Count() )
750 USHORT nPos;
751 rFtnArr.SeekEntry( SwNodeIndex( *pNd ), &nPos );
752 SwTxtFtn* pSrch;
754 // loesche erstmal alle, die dahinter stehen
755 while( nPos < rFtnArr.Count() &&
756 _SwTxtFtn_GetIndex( (pSrch = rFtnArr[ nPos ]) ) <= nEnd )
758 // Werden die Nodes nicht geloescht mussen sie bei den Seiten
759 // abmeldet (Frms loeschen) werden, denn sonst bleiben sie
760 // stehen (Undo loescht sie nicht!)
761 pSrch->DelFrms();
762 ++nPos;
765 while( nPos-- &&
766 _SwTxtFtn_GetIndex( (pSrch = rFtnArr[ nPos ]) ) >= nStt )
768 // Werden die Nodes nicht geloescht mussen sie bei den Seiten
769 // abmeldet (Frms loeschen) werden, denn sonst bleiben sie
770 // stehen (Undo loescht sie nicht!)
771 pSrch->DelFrms();
776 inline BOOL lcl_IsTOXSection( const SwSection& rSection )
778 return TOX_CONTENT_SECTION == rSection.GetType() ||
779 TOX_HEADER_SECTION == rSection.GetType();
782 SwSectionNode* SwNodes::InsertSection( const SwNodeIndex& rNdIdx,
783 SwSectionFmt& rSectionFmt,
784 const SwSection& rSection,
785 const SwNodeIndex* pEnde,
786 BOOL bInsAtStart, BOOL bCreateFrms )
788 SwNodeIndex aInsPos( rNdIdx );
789 if( !pEnde ) // kein Bereich also neue Section davor/hinter anlegen
791 // #i26762#
792 ASSERT(!pEnde || rNdIdx <= *pEnde,
793 "Section start and end in wrong order!");
795 if( bInsAtStart )
797 if( !lcl_IsTOXSection( rSection ))
799 do {
800 aInsPos--;
801 } while( aInsPos.GetNode().IsSectionNode() );
802 aInsPos++;
805 else
807 SwNode* pNd;
808 aInsPos++;
809 if( !lcl_IsTOXSection( rSection ))
810 while( aInsPos.GetIndex() < Count() - 1 &&
811 ( pNd = &aInsPos.GetNode())->IsEndNode() &&
812 pNd->StartOfSectionNode()->IsSectionNode())
813 aInsPos++;
817 SwSectionNode* pSectNd = new SwSectionNode( aInsPos, rSectionFmt );
818 if( pEnde )
820 // Sonderfall fuer die Reader/Writer
821 if( &pEnde->GetNode() != &GetEndOfContent() )
822 aInsPos = pEnde->GetIndex()+1;
823 // #i58710: We created a RTF document with a section break inside a table cell
824 // We are not able to handle a section start inside a table and the section end outside.
825 const SwNode* pLastNode = pSectNd->StartOfSectionNode()->EndOfSectionNode();
826 if( aInsPos > pLastNode->GetIndex() )
827 aInsPos = pLastNode->GetIndex();
828 // Another way round: if the section starts outside a table but the end is inside...
829 // aInsPos is at the moment the Position where my EndNode will be inserted
830 const SwStartNode* pStartNode = aInsPos.GetNode().StartOfSectionNode();
831 // This StartNode should be in front of me, but if not, I wanna survive
832 ULONG nMyIndex = pSectNd->GetIndex();
833 if( pStartNode->GetIndex() > nMyIndex ) // Suspicious!
835 const SwNode* pTemp;
838 pTemp = pStartNode; // pTemp is a suspicious one
839 pStartNode = pStartNode->StartOfSectionNode();
841 while( pStartNode->GetIndex() > nMyIndex );
842 pTemp = pTemp->EndOfSectionNode();
843 // If it starts behind me but ends behind my end...
844 if( pTemp->GetIndex() >= aInsPos.GetIndex() )
845 aInsPos = pTemp->GetIndex()+1; // ...I have to correct my end position
849 else
851 SwTxtNode* pCpyTNd = rNdIdx.GetNode().GetTxtNode();
852 if( pCpyTNd )
854 SwTxtNode* pTNd = new SwTxtNode( aInsPos, pCpyTNd->GetTxtColl() );
855 if( pCpyTNd->HasSwAttrSet() )
857 // Task 70955 - move PageDesc/Break to the first Node of the
858 // section
859 const SfxItemSet& rSet = *pCpyTNd->GetpSwAttrSet();
860 if( SFX_ITEM_SET == rSet.GetItemState( RES_BREAK ) ||
861 SFX_ITEM_SET == rSet.GetItemState( RES_PAGEDESC ))
863 SfxItemSet aSet( rSet );
864 if( bInsAtStart )
865 pCpyTNd->ResetAttr( RES_PAGEDESC, RES_BREAK );
866 else
868 aSet.ClearItem( RES_PAGEDESC );
869 aSet.ClearItem( RES_BREAK );
871 pTNd->SetAttr( aSet );
873 else
874 pTNd->SetAttr( rSet );
876 // den Frame anlegen nicht vergessen !!
877 pCpyTNd->MakeFrms( *pTNd );
879 else
880 new SwTxtNode( aInsPos, (SwTxtFmtColl*)GetDoc()->GetDfltTxtFmtColl() );
882 new SwEndNode( aInsPos, *pSectNd );
884 pSectNd->GetSection() = rSection;
885 SwSectionFmt* pSectFmt = pSectNd->GetSection().GetFmt();
887 // Hier bietet sich als Optimierung an, vorhandene Frames nicht zu
888 // zerstoeren und wieder neu anzulegen, sondern nur umzuhaengen.
889 BOOL bInsFrm = bCreateFrms && !pSectNd->GetSection().IsHidden() &&
890 GetDoc()->GetRootFrm();
891 SwNode2Layout *pNode2Layout = NULL;
892 if( bInsFrm )
894 SwNodeIndex aTmp( *pSectNd );
895 if( !pSectNd->GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() ) )
896 // dann sammel mal alle Uppers ein
897 pNode2Layout = new SwNode2Layout( *pSectNd );
900 // jetzt noch bei allen im Bereich den richtigen StartNode setzen
901 ULONG nEnde = pSectNd->EndOfSectionIndex();
902 ULONG nStart = pSectNd->GetIndex()+1;
903 ULONG nSkipIdx = ULONG_MAX;
904 for( ULONG n = nStart; n < nEnde; ++n )
906 SwNode* pNd = (*this)[n];
908 //JP 30.04.99: Bug 65644 - alle in der NodeSection liegenden
909 // Sections unter die neue haengen
910 if( ULONG_MAX == nSkipIdx )
911 pNd->pStartOfSection = pSectNd;
912 else if( n >= nSkipIdx )
913 nSkipIdx = ULONG_MAX;
915 if( pNd->IsStartNode() )
917 // die Verschachtelung der Formate herstellen!
918 if( pNd->IsSectionNode() )
920 ((SwSectionNode*)pNd)->GetSection().GetFmt()->
921 SetDerivedFrom( pSectFmt );
922 ((SwSectionNode*)pNd)->DelFrms();
923 n = pNd->EndOfSectionIndex();
925 else
927 if( pNd->IsTableNode() )
928 ((SwTableNode*)pNd)->DelFrms();
930 if( ULONG_MAX == nSkipIdx )
931 nSkipIdx = pNd->EndOfSectionIndex();
934 else if( pNd->IsCntntNode() )
935 ((SwCntntNode*)pNd)->DelFrms();
938 lcl_DeleteFtn( pSectNd, nStart, nEnde );
940 if( bInsFrm )
942 if( pNode2Layout )
944 ULONG nIdx = pSectNd->GetIndex();
945 pNode2Layout->RestoreUpperFrms( pSectNd->GetNodes(), nIdx, nIdx + 1 );
946 delete pNode2Layout;
948 else
949 pSectNd->MakeFrms( &aInsPos );
952 return pSectNd;
955 SwSectionNode* SwNode::FindSectionNode()
957 if( IsSectionNode() )
958 return GetSectionNode();
959 SwStartNode* pTmp = pStartOfSection;
960 while( !pTmp->IsSectionNode() && pTmp->GetIndex() )
961 #if defined( ALPHA ) && defined( UNX )
962 pTmp = ((SwNode*)pTmp)->pStartOfSection;
963 #else
964 pTmp = pTmp->pStartOfSection;
965 #endif
966 return pTmp->GetSectionNode();
970 //---------
971 // SwSectionNode
972 //---------
974 SwSectionNode::SwSectionNode( const SwNodeIndex& rIdx, SwSectionFmt& rFmt )
975 : SwStartNode( rIdx, ND_SECTIONNODE )
977 SwSectionNode* pParent = StartOfSectionNode()->FindSectionNode();
978 if( pParent )
980 // das Format beim richtigen Parent anmelden.
981 rFmt.SetDerivedFrom( pParent->GetSection().GetFmt() );
983 pSection = new SwSection( CONTENT_SECTION, rFmt.GetName(), &rFmt );
985 // jetzt noch die Verbindung von Format zum Node setzen
986 // Modify unterdruecken, interresiert keinen
987 rFmt.LockModify();
988 rFmt.SetFmtAttr( SwFmtCntnt( this ) );
989 rFmt.UnlockModify();
992 #if OSL_DEBUG_LEVEL > 1
993 //Hier werden ueberfluessige SectionFrms entfernt
994 SwFrm* SwClearDummies( SwFrm* pFrm )
996 SwFrm* pTmp = pFrm;
997 while( pTmp )
999 ASSERT( !pTmp->GetUpper(), "SwClearDummies: No Upper allowed!" );
1000 if( pTmp->IsSctFrm() )
1002 SwSectionFrm* pSectFrm = (SwSectionFrm*)pFrm;
1003 pTmp = pTmp->GetNext();
1004 if( !pSectFrm->GetLower() )
1006 if( pSectFrm->GetPrev() )
1007 pSectFrm->GetPrev()->pNext = pTmp;
1008 else
1009 pFrm = pTmp;
1010 if( pTmp )
1011 pTmp->pPrev = pSectFrm->GetPrev();
1012 delete pSectFrm;
1015 else
1016 pTmp = pTmp->GetNext();
1018 return pFrm;
1020 #endif
1022 SwSectionNode::~SwSectionNode()
1025 SwClientIter aIter( *(pSection->GetFmt()) );
1026 SwClient *pLast = aIter.GoStart();
1027 while ( pLast )
1029 if ( pLast->IsA( TYPE(SwFrm) ) )
1031 SwSectionFrm *pSectFrm = (SwSectionFrm*)pLast;
1032 SwSectionFrm::MoveCntntAndDelete( pSectFrm, TRUE );
1033 pLast = aIter.GoStart();
1035 else
1036 pLast = aIter++;
1039 SwDoc* pDoc = GetDoc();
1041 SwSectionFmt* pFmt = pSection->GetFmt();
1042 if( pFmt )
1044 // das Attribut entfernen, weil die Section ihr Format loescht
1045 // und falls das Cntnt-Attribut vorhanden ist, die Section aufhebt.
1046 pFmt->LockModify();
1047 pFmt->ResetFmtAttr( RES_CNTNT );
1048 pFmt->UnlockModify();
1051 BOOL bUndo = pDoc->DoesUndo();
1052 // verhinder beim Loeschen aus der Undo/Redo-History einen rekursiven Aufruf
1053 if( bUndo && &pDoc->GetNodes() != &GetNodes() )
1054 pDoc->DoUndo( FALSE );
1055 DELETEZ( pSection );
1056 pDoc->DoUndo( bUndo );
1059 // setze ein neues SectionObject. Erstmal nur gedacht fuer die
1060 // neuen VerzeichnisSections. Der geht ueber in den Besitz des Nodes!
1061 void SwSectionNode::SetNewSection( SwSection* pNewSection )
1063 ASSERT( pNewSection, "ohne Pointer geht hier nichts" );
1064 if( pNewSection )
1066 SwNode2Layout aN2L( *this );
1068 // einige Flags sollten ueber nommen werden!
1069 pNewSection->bProtectFlag = pSection->bProtectFlag;
1070 pNewSection->bHiddenFlag = pSection->bHiddenFlag;
1071 pNewSection->bHidden = pSection->bHidden;
1072 pNewSection->bCondHiddenFlag = pSection->bCondHiddenFlag;
1074 // The section frame contains a pointer to the section. That for,
1075 // the frame must be destroyed before deleting the section.
1076 DelFrms();
1078 delete pSection;
1079 pSection = pNewSection;
1081 ULONG nIdx = GetIndex();
1082 aN2L.RestoreUpperFrms( GetNodes(), nIdx, nIdx + 1 );
1086 SwFrm *SwSectionNode::MakeFrm()
1088 pSection->bHiddenFlag = FALSE;
1089 return new SwSectionFrm( *pSection );
1092 //Methode erzeugt fuer den vorhergehenden Node alle Ansichten vom
1093 //Dokument. Die erzeugten Contentframes werden in das entsprechende
1094 //Layout gehaengt.
1095 void SwSectionNode::MakeFrms(const SwNodeIndex & rIdx )
1097 // also nehme meinen nachfolgenden oder vorhergehenden ContentFrame:
1098 SwNodes& rNds = GetNodes();
1099 if( rNds.IsDocNodes() && rNds.GetDoc()->GetRootFrm() )
1101 if( GetSection().IsHidden() || IsCntntHidden() )
1103 SwNodeIndex aIdx( *EndOfSectionNode() );
1104 SwCntntNode* pCNd = rNds.GoNextSection( &aIdx, TRUE, FALSE );
1105 if( !pCNd )
1107 aIdx = *this;
1108 if( 0 == ( pCNd = rNds.GoPrevSection( &aIdx, TRUE, FALSE )) )
1109 return ;
1111 pCNd = rNds[ aIdx ]->GetCntntNode();
1112 pCNd->MakeFrms( (SwCntntNode&)rIdx.GetNode() );
1114 else
1116 SwNode2Layout aNode2Layout( *this, rIdx.GetIndex() );
1117 SwFrm *pFrm, *pNew;
1118 while( 0 != (pFrm = aNode2Layout.NextFrm()) )
1120 ASSERT( pFrm->IsSctFrm(), "Depend von Section keine Section." );
1121 pNew = rIdx.GetNode().GetCntntNode()->MakeFrm();
1123 SwSectionNode* pS = rIdx.GetNode().FindSectionNode();
1124 // --> OD 2008-06-23 #156927#
1125 // Assure that node is not inside a table, which is inside the
1126 // found section.
1127 if ( pS )
1129 SwTableNode* pTableNode = rIdx.GetNode().FindTableNode();
1130 if ( pTableNode &&
1131 pTableNode->GetIndex() > pS->GetIndex() )
1133 pS = 0;
1136 // <--
1137 // if the node is in a section, the sectionframe now
1138 // has to be created..
1139 // OD 14.11.2002 #104684# - boolean to control <Init()> of a new
1140 // section frame.
1141 bool bInitNewSect = false;
1142 if( pS )
1144 SwSectionFrm *pSct = new SwSectionFrm( pS->GetSection() );
1145 // OD 14.11.2002 #104684# - prepare <Init()> of new section frame.
1146 bInitNewSect = true;
1147 SwLayoutFrm* pUp = pSct;
1148 while( pUp->Lower() ) // for columned sections
1150 ASSERT( pUp->Lower()->IsLayoutFrm(),"Who's in there?" );
1151 pUp = (SwLayoutFrm*)pUp->Lower();
1153 pNew->Paste( pUp, NULL );
1154 // --> OD 2005-12-01 #i27138#
1155 // notify accessibility paragraphs objects about changed
1156 // CONTENT_FLOWS_FROM/_TO relation.
1157 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1158 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1159 if ( pNew->IsTxtFrm() )
1161 ViewShell* pViewShell( pNew->GetShell() );
1162 if ( pViewShell && pViewShell->GetLayout() &&
1163 pViewShell->GetLayout()->IsAnyShellAccessible() )
1165 pViewShell->InvalidateAccessibleParaFlowRelation(
1166 dynamic_cast<SwTxtFrm*>(pNew->FindNextCnt( true )),
1167 dynamic_cast<SwTxtFrm*>(pNew->FindPrevCnt( true )) );
1170 // <--
1171 pNew = pSct;
1174 // wird ein Node vorher oder nachher mit Frames versehen
1175 if ( rIdx < GetIndex() )
1176 // der neue liegt vor mir
1177 pNew->Paste( pFrm->GetUpper(), pFrm );
1178 else
1179 // der neue liegt hinter mir
1180 pNew->Paste( pFrm->GetUpper(), pFrm->GetNext() );
1181 // --> OD 2005-12-01 #i27138#
1182 // notify accessibility paragraphs objects about changed
1183 // CONTENT_FLOWS_FROM/_TO relation.
1184 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1185 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1186 if ( pNew->IsTxtFrm() )
1188 ViewShell* pViewShell( pNew->GetShell() );
1189 if ( pViewShell && pViewShell->GetLayout() &&
1190 pViewShell->GetLayout()->IsAnyShellAccessible() )
1192 pViewShell->InvalidateAccessibleParaFlowRelation(
1193 dynamic_cast<SwTxtFrm*>(pNew->FindNextCnt( true )),
1194 dynamic_cast<SwTxtFrm*>(pNew->FindPrevCnt( true )) );
1197 // <--
1198 if ( bInitNewSect )
1199 static_cast<SwSectionFrm*>(pNew)->Init();
1205 //Fuer jedes vorkommen im Layout einen SectionFrm anlegen und vor den
1206 //entsprechenden CntntFrm pasten.
1208 void SwSectionNode::MakeFrms( SwNodeIndex* pIdxBehind, SwNodeIndex* pEndIdx )
1210 ASSERT( pIdxBehind, "kein Index" );
1211 SwNodes& rNds = GetNodes();
1212 SwDoc* pDoc = rNds.GetDoc();
1214 *pIdxBehind = *this;
1216 pSection->bHiddenFlag = TRUE;
1218 if( rNds.IsDocNodes() )
1220 SwNodeIndex *pEnd = pEndIdx ? pEndIdx :
1221 new SwNodeIndex( *EndOfSectionNode(), 1 );
1222 ::MakeFrms( pDoc, *pIdxBehind, *pEnd );
1223 if( !pEndIdx )
1224 delete pEnd;
1229 void SwSectionNode::DelFrms()
1231 ULONG nStt = GetIndex()+1, nEnd = EndOfSectionIndex();
1232 if( nStt >= nEnd )
1234 // unser Flag muessen wir noch aktualisieren
1235 // pSection->bHiddenFlag = TRUE;
1236 return ;
1239 SwNodes& rNds = GetNodes();
1240 pSection->GetFmt()->DelFrms();
1242 // unser Flag muessen wir noch aktualisieren
1243 pSection->bHiddenFlag = TRUE;
1245 // Bug 30582: falls der Bereich in Fly oder TabellenBox ist, dann
1246 // kann er nur "gehiddet" werden, wenn weiterer Content
1247 // vorhanden ist, der "Frames" haelt. Sonst hat der
1248 // Fly/TblBox-Frame keinen Lower !!!
1250 SwNodeIndex aIdx( *this );
1251 if( !rNds.GoPrevSection( &aIdx, TRUE, FALSE ) ||
1252 !CheckNodesRange( *this, aIdx, TRUE ) ||
1253 // OD 04.11.2003 #i21457#
1254 !lcl_IsInSameTblBox( rNds, *this, true ))
1256 aIdx = *EndOfSectionNode();
1257 if( !rNds.GoNextSection( &aIdx, TRUE, FALSE ) ||
1258 !CheckNodesRange( *EndOfSectionNode(), aIdx, TRUE ) ||
1259 // OD 04.11.2003 #i21457#
1260 !lcl_IsInSameTblBox( rNds, *EndOfSectionNode(), false ))
1261 pSection->bHiddenFlag = FALSE;
1266 SwSectionNode* SwSectionNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
1268 // in welchen Array steht ich denn: Nodes, UndoNodes ??
1269 const SwNodes& rNds = GetNodes();
1271 // das SectionFrmFmt kopieren
1272 SwSectionFmt* pSectFmt = pDoc->MakeSectionFmt( 0 );
1273 pSectFmt->CopyAttrs( *GetSection().GetFmt() );
1275 SwSectionNode* pSectNd = new SwSectionNode( rIdx, *pSectFmt );
1276 SwEndNode* pEndNd = new SwEndNode( rIdx, *pSectNd );
1277 SwNodeIndex aInsPos( *pEndNd );
1279 // Werte uebertragen
1280 SwSection* pNewSect = pSectNd->pSection;
1282 switch( GetSection().GetType() )
1284 case TOX_CONTENT_SECTION:
1286 ASSERT( GetSection().ISA( SwTOXBaseSection ), "keine TOXBaseSection!" );
1287 SwTOXBaseSection& rTOXSect = (SwTOXBaseSection&)GetSection();
1288 SwTOXBase aTmp( rTOXSect, pDoc );
1290 SwTOXBaseSection* pNew = new SwTOXBaseSection( aTmp );
1292 pNewSect = pNew;
1293 pSectFmt->Add( pNewSect );
1294 pSectNd->SetNewSection( pNew );
1296 break;
1298 default:
1299 // beim Move den Namen beibehalten
1300 if( rNds.GetDoc() == pDoc && pDoc->IsCopyIsMove() )
1301 pNewSect->SetName( GetSection().GetName() );
1302 else
1303 pNewSect->SetName( pDoc->GetUniqueSectionName(
1304 &GetSection().GetName() ) );
1305 break;
1309 pNewSect->SetType( GetSection().GetType() );
1310 pNewSect->SetCondition( GetSection().GetCondition() );
1311 pNewSect->SetLinkFileName( GetSection().GetLinkFileName() );
1312 if( !pNewSect->IsHiddenFlag() && GetSection().IsHidden() )
1313 pNewSect->SetHidden( TRUE );
1314 if( !pNewSect->IsProtectFlag() && GetSection().IsProtect() )
1315 pNewSect->SetProtect( TRUE );
1316 // --> FME 2004-06-22 #114856# edit in readonly sections
1317 if( !pNewSect->IsEditInReadonlyFlag() && GetSection().IsEditInReadonly() )
1318 pNewSect->SetEditInReadonly( TRUE );
1319 // <--
1321 SwNodeRange aRg( *this, +1, *EndOfSectionNode() ); // (wo stehe in denn nun ??)
1322 rNds._Copy( aRg, aInsPos, FALSE );
1324 // loesche alle Frames vom kopierten Bereich, diese werden beim
1325 // erzeugen des SectionFrames angelegt !
1326 pSectNd->DelFrms();
1328 // dann kopiere auch noch die Links/Server
1329 if( pNewSect->IsLinkType() ) // den Link eintragen
1330 pNewSect->CreateLink( pDoc->GetRootFrm() ? CREATE_CONNECT
1331 : CREATE_NONE );
1333 // falls als Server aus dem Undo kopiert wird, wieder eintragen
1334 if( pSection->IsServer() && pDoc->GetUndoNds() == &rNds )
1336 pNewSect->SetRefObject( pSection->GetObject() );
1337 pDoc->GetLinkManager().InsertServer( pNewSect->GetObject() );
1340 return pSectNd;
1343 BOOL SwSectionNode::IsCntntHidden() const
1345 ASSERT( !pSection->IsHidden(), "That's simple: Hidden Section => Hidden Content" );
1346 SwNodeIndex aTmp( *this, 1 );
1347 ULONG nEnd = EndOfSectionIndex();
1348 while( aTmp < nEnd )
1350 if( aTmp.GetNode().IsSectionNode() )
1352 const SwSection& rSect = ((SwSectionNode&)aTmp.GetNode()).GetSection();
1353 if( rSect.IsHiddenFlag() )
1354 // dann diese Section ueberspringen
1355 aTmp = *aTmp.GetNode().EndOfSectionNode();
1357 else
1359 if( aTmp.GetNode().IsCntntNode() || aTmp.GetNode().IsTableNode() )
1360 return FALSE; // Nicht versteckter Inhalt wurde gefunden
1361 ASSERT( aTmp.GetNode().IsEndNode(), "EndNode expected" );
1363 aTmp++;
1365 return TRUE; // Alles versteckt
1369 void SwSectionNode::NodesArrChgd()
1371 SwSectionFmt* pFmt = pSection->GetFmt();
1372 if( pFmt )
1374 SwNodes& rNds = GetNodes();
1375 SwDoc* pDoc = pFmt->GetDoc();
1377 if( !rNds.IsDocNodes() )
1379 SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFmt );
1380 pFmt->Modify( &aMsgHint, &aMsgHint );
1383 pFmt->LockModify();
1384 pFmt->SetFmtAttr( SwFmtCntnt( this ));
1385 pFmt->UnlockModify();
1387 SwSectionNode* pSectNd = StartOfSectionNode()->FindSectionNode();
1388 // set the correct parent from the new section
1389 pFmt->SetDerivedFrom( pSectNd ? pSectNd->GetSection().GetFmt()
1390 : pDoc->GetDfltFrmFmt() );
1392 // jetzt noch bei allen im Bereich den richtigen StartNode setzen
1393 ULONG nStart = GetIndex()+1, nEnde = EndOfSectionIndex();
1394 for( ULONG n = nStart; n < nEnde; ++n )
1395 // die Verschachtelung der Formate herstellen!
1396 if( 0 != ( pSectNd = rNds[ n ]->GetSectionNode() ) )
1398 pSectNd->GetSection().GetFmt()->SetDerivedFrom( pFmt );
1399 n = pSectNd->EndOfSectionIndex();
1402 // verschieben vom Nodes- ins UndoNodes-Array?
1403 if( rNds.IsDocNodes() )
1405 ASSERT( pDoc == GetDoc(),
1406 "verschieben in unterschiedliche Documente?" );
1407 if( pSection->IsLinkType() ) // den Link austragen
1408 pSection->CreateLink( pDoc->GetRootFrm() ? CREATE_CONNECT
1409 : CREATE_NONE );
1411 if( pSection->IsServer() ) // als Server austragen
1412 pDoc->GetLinkManager().InsertServer( pSection->GetObject() );
1414 else
1416 if( CONTENT_SECTION != pSection->GetType() ) // den Link austragen
1417 pDoc->GetLinkManager().Remove( &pSection->GetBaseLink() );
1419 if( pSection->IsServer() ) // als Server austragen
1420 pDoc->GetLinkManager().RemoveServer( pSection->GetObject() );
1426 String SwDoc::GetUniqueSectionName( const String* pChkStr ) const
1428 ResId aId( STR_REGION_DEFNAME, *pSwResMgr );
1429 String aName( aId );
1430 xub_StrLen nNmLen = aName.Len();
1432 USHORT nNum = 0;
1433 USHORT nTmp, nFlagSize = ( pSectionFmtTbl->Count() / 8 ) +2;
1434 BYTE* pSetFlags = new BYTE[ nFlagSize ];
1435 memset( pSetFlags, 0, nFlagSize );
1437 const SwSectionNode* pSectNd;
1438 USHORT n;
1440 for( n = 0; n < pSectionFmtTbl->Count(); ++n )
1441 if( 0 != ( pSectNd = (*pSectionFmtTbl)[ n ]->GetSectionNode( FALSE ) ))
1443 const String& rNm = pSectNd->GetSection().GetName();
1444 if( rNm.Match( aName ) == nNmLen )
1446 // Nummer bestimmen und das Flag setzen
1447 nNum = static_cast<USHORT>(rNm.Copy( nNmLen ).ToInt32());
1448 if( nNum-- && nNum < pSectionFmtTbl->Count() )
1449 pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
1451 if( pChkStr && pChkStr->Equals( rNm ) )
1452 pChkStr = 0;
1455 if( !pChkStr )
1457 // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
1458 nNum = pSectionFmtTbl->Count();
1459 for( n = 0; n < nFlagSize; ++n )
1460 if( 0xff != ( nTmp = pSetFlags[ n ] ))
1462 // also die Nummer bestimmen
1463 nNum = n * 8;
1464 while( nTmp & 1 )
1465 ++nNum, nTmp >>= 1;
1466 break;
1470 delete [] pSetFlags;
1471 if( pChkStr )
1472 return *pChkStr;
1473 return aName += String::CreateFromInt32( ++nNum );