/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sw.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef _COMCORE_HRC #include #endif // --> OD 2005-12-01 #i27138# #include #include // <-- // OD 04.11.2003 #i21457# - new implementation of local method . // Method now determines the previous/next on its own. Thus, it can be controlled, // for which previous/next is checked, if it's visible. bool lcl_IsInSameTblBox( SwNodes& _rNds, const SwNode& _rNd, const bool _bPrev ) { const SwTableNode* pTblNd = _rNd.FindTableNode(); if ( !pTblNd ) { return true; } // determine index to be checked. Its assumed that a previous/next exist. SwNodeIndex aChkIdx( _rNd ); { // determine index of previous/next - skip hidden ones, which are // inside the table. // If found one is before/after table, this one isn't in the same // table box as <_rNd>. bool bFound = false; do { if ( _bPrev ? !_rNds.GoPrevSection( &aChkIdx, FALSE, FALSE ) : !_rNds.GoNextSection( &aChkIdx, FALSE, FALSE ) ) { ASSERT( false, " - no previous/next!" ); return false; } else { if ( aChkIdx < pTblNd->GetIndex() || aChkIdx > pTblNd->EndOfSectionNode()->GetIndex() ) { return false; } else { // check, if found one isn't inside a hidden section, which // is also inside the table. SwSectionNode* pSectNd = aChkIdx.GetNode().FindSectionNode(); if ( !pSectNd || pSectNd->GetIndex() < pTblNd->GetIndex() || !pSectNd->GetSection().IsHiddenFlag() ) { bFound = true; } } } } while ( !bFound ); } // dann suche den StartNode der Box const SwTableSortBoxes& rSortBoxes = pTblNd->GetTable().GetTabSortBoxes(); ULONG nIdx = _rNd.GetIndex(); for( USHORT n = 0; n < rSortBoxes.Count(); ++n ) { const SwStartNode* pNd = rSortBoxes[ n ]->GetSttNd(); if ( pNd->GetIndex() < nIdx && nIdx < pNd->EndOfSectionIndex() ) { // dann muss der andere Index in derselben Section liegen nIdx = aChkIdx.GetIndex(); return pNd->GetIndex() < nIdx && nIdx < pNd->EndOfSectionIndex(); } } return true; } void lcl_CheckEmptyLayFrm( SwNodes& rNds, SwSection& rSect, const SwNode& rStt, const SwNode& rEnd ) { SwNodeIndex aIdx( rStt ); if( !rNds.GoPrevSection( &aIdx, TRUE, FALSE ) || !CheckNodesRange( rStt, aIdx, TRUE ) || // OD 04.11.2003 #i21457# !lcl_IsInSameTblBox( rNds, rStt, true )) { aIdx = rEnd; if( !rNds.GoNextSection( &aIdx, TRUE, FALSE ) || !CheckNodesRange( rEnd, aIdx, TRUE ) || // OD 04.11.2003 #i21457# !lcl_IsInSameTblBox( rNds, rEnd, false )) rSect.SetHidden( FALSE ); } } SwSection* SwDoc::InsertSwSection( const SwPaM& rRange, const SwSection& rNew, const SfxItemSet* pAttr, bool bUpdate ) { const SwNode* pPrvNd = 0; USHORT nRegionRet = 0; if( rRange.HasMark() && 0 == ( nRegionRet = IsInsRegionAvailable( rRange, &pPrvNd ) )) { ASSERT( !this, "Selection ueber verschiedene Sections" ); return 0; } // Teste ob das gesamte Dokument versteckt werden soll, // koennen wir zur Zeit nicht !!!! if( rNew.IsHidden() && rRange.HasMark() ) { const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End(); if( !pStt->nContent.GetIndex() && pEnd->nNode.GetNode().GetCntntNode()->Len() == pEnd->nContent.GetIndex() ) { ::lcl_CheckEmptyLayFrm( GetNodes(), const_cast(rNew), pStt->nNode.GetNode(), pEnd->nNode.GetNode() ); } } SwUndoInsSection* pUndoInsSect = 0; if( DoesUndo() ) { ClearRedo(); pUndoInsSect = new SwUndoInsSection( rRange, rNew, pAttr ); AppendUndo( pUndoInsSect ); DoUndo( FALSE ); } SwSectionFmt* const pFmt = MakeSectionFmt( 0 ); if ( pAttr ) { pFmt->SetFmtAttr( *pAttr ); } SwSectionNode* pNewSectNode = 0; RedlineMode_t eOld = GetRedlineMode(); SetRedlineMode_intern( (RedlineMode_t)((eOld & ~nsRedlineMode_t::REDLINE_SHOW_MASK) | nsRedlineMode_t::REDLINE_IGNORE)); if( rRange.HasMark() ) { SwPosition *pSttPos = (SwPosition*)rRange.Start(), *pEndPos = (SwPosition*)rRange.End(); if( pPrvNd && 3 == nRegionRet ) { ASSERT( pPrvNd, "der SectionNode fehlt" ); SwNodeIndex aStt( pSttPos->nNode ), aEnd( pEndPos->nNode, +1 ); while( pPrvNd != aStt.GetNode().StartOfSectionNode() ) aStt--; while( pPrvNd != aEnd.GetNode().StartOfSectionNode() ) aEnd++; --aEnd; // im InsertSection ist Ende inclusive pNewSectNode = GetNodes().InsertSection( aStt, *pFmt, rNew, &aEnd ); } else { if( pUndoInsSect ) { if( !( pPrvNd && 1 == nRegionRet ) && pSttPos->nContent.GetIndex() ) { SwTxtNode* const pTNd = pSttPos->nNode.GetNode().GetTxtNode(); if (pTNd) { pUndoInsSect->SaveSplitNode( pTNd, TRUE ); } } if ( !( pPrvNd && 2 == nRegionRet ) ) { SwTxtNode *const pTNd = pEndPos->nNode.GetNode().GetTxtNode(); if (pTNd && (pTNd->GetTxt().Len() != pEndPos->nContent.GetIndex())) { pUndoInsSect->SaveSplitNode( pTNd, FALSE ); } } } const SwCntntNode* pCNd; if( pPrvNd && 1 == nRegionRet ) { pSttPos->nNode.Assign( *pPrvNd ); pSttPos->nContent.Assign( pSttPos->nNode.GetNode().GetCntntNode(), 0 ); } else if( pSttPos->nContent.GetIndex() ) { SplitNode( *pSttPos, false ); } if( pPrvNd && 2 == nRegionRet ) { pEndPos->nNode.Assign( *pPrvNd ); pEndPos->nContent.Assign( pEndPos->nNode.GetNode().GetCntntNode(), 0 ); } else { pCNd = pEndPos->nNode.GetNode().GetCntntNode(); if( pCNd && pCNd->Len() != pEndPos->nContent.GetIndex() ) { xub_StrLen nCntnt = pSttPos->nContent.GetIndex(); SplitNode( *pEndPos, false ); SwTxtNode* pTNd; if( pEndPos->nNode.GetIndex() == pSttPos->nNode.GetIndex() ) { pSttPos->nNode--; pEndPos->nNode--; pTNd = pSttPos->nNode.GetNode().GetTxtNode(); pSttPos->nContent.Assign( pTNd, nCntnt ); } else { // wieder ans Ende vom vorherigen setzen pEndPos->nNode--; pTNd = pEndPos->nNode.GetNode().GetTxtNode(); } if( pTNd ) nCntnt = pTNd->GetTxt().Len(); else nCntnt = 0; pEndPos->nContent.Assign( pTNd, nCntnt ); } } pNewSectNode = GetNodes().InsertSection( pSttPos->nNode, *pFmt, rNew, &pEndPos->nNode ); } } else { const SwPosition* pPos = rRange.GetPoint(); const SwCntntNode* pCNd = pPos->nNode.GetNode().GetCntntNode(); if( !pPos->nContent.GetIndex() ) { pNewSectNode = GetNodes().InsertSection( pPos->nNode, *pFmt, rNew, 0, TRUE ); } else if( pPos->nContent.GetIndex() == pCNd->Len() ) { pNewSectNode = GetNodes().InsertSection( pPos->nNode, *pFmt, rNew, 0, FALSE ); } else { if( pUndoInsSect && pCNd->IsTxtNode() ) { pUndoInsSect->SaveSplitNode( (SwTxtNode*)pCNd, TRUE ); } SplitNode( *pPos, false ); pNewSectNode = GetNodes().InsertSection( pPos->nNode, *pFmt, rNew, 0, TRUE ); } } //FEATURE::CONDCOLL pNewSectNode->CheckSectionCondColl(); //FEATURE::CONDCOLL SetRedlineMode_intern( eOld ); if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() )) { SwPaM aPam( *pNewSectNode->EndOfSectionNode(), *pNewSectNode, 1 ); if( IsRedlineOn() ) { AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true); } else { SplitRedline( aPam ); } } // ist eine Condition gesetzt if( rNew.IsHidden() && rNew.GetCondition().Len() ) { // dann berechne bis zu dieser Position SwCalc aCalc( *this ); if( ! IsInReading() ) { FldsToCalc( aCalc, pNewSectNode->GetIndex(), USHRT_MAX ); } SwSection& rNewSect = pNewSectNode->GetSection(); rNewSect.SetCondHidden( aCalc.Calculate( rNewSect.GetCondition() ).GetBool() ); } BOOL bUpdateFtn = FALSE; if( GetFtnIdxs().Count() && pAttr ) { USHORT nVal = ((SwFmtFtnAtTxtEnd&)pAttr->Get( RES_FTN_AT_TXTEND )).GetValue(); if( ( FTNEND_ATTXTEND_OWNNUMSEQ == nVal || FTNEND_ATTXTEND_OWNNUMANDFMT == nVal ) || ( FTNEND_ATTXTEND_OWNNUMSEQ == ( nVal = ((SwFmtEndAtTxtEnd&) pAttr->Get( RES_END_AT_TXTEND )).GetValue() ) || FTNEND_ATTXTEND_OWNNUMANDFMT == nVal )) { bUpdateFtn = TRUE; } } if( pUndoInsSect ) { pUndoInsSect->SetSectNdPos( pNewSectNode->GetIndex() ); pUndoInsSect->SetUpdtFtnFlag( bUpdateFtn ); DoUndo( TRUE ); } if( rNew.IsLinkType() ) { pNewSectNode->GetSection().CreateLink( bUpdate ? CREATE_UPDATE : CREATE_CONNECT ); } if( bUpdateFtn ) { GetFtnIdxs().UpdateFtn( SwNodeIndex( *pNewSectNode )); } SetModified(); return &pNewSectNode->GetSection(); } USHORT SwDoc::IsInsRegionAvailable( const SwPaM& rRange, const SwNode** ppSttNd ) const { USHORT nRet = 1; if( rRange.HasMark() ) { // teste ob es sich um eine gueltige Selektion handelt const SwPosition* pStt = rRange.Start(), * pEnd = rRange.End(); const SwCntntNode* pCNd = pEnd->nNode.GetNode().GetCntntNode(); const SwNode* pNd = &pStt->nNode.GetNode(); const SwSectionNode* pSectNd = pNd->FindSectionNode(); const SwSectionNode* pEndSectNd = pCNd ? pCNd->FindSectionNode() : 0; if( pSectNd && pEndSectNd && pSectNd != pEndSectNd ) { // versuche eine umschliessende Section zu erzeugen // Aber, nur wenn der Start am Sectionanfang und das Ende am // Section Ende liegt! nRet = 0; if( !pStt->nContent.GetIndex() && pSectNd->GetIndex() == pStt->nNode.GetIndex() - 1 && pEnd->nContent.GetIndex() == pCNd->Len() ) { SwNodeIndex aIdx( pStt->nNode, -1 ); ULONG nCmp = pEnd->nNode.GetIndex(); const SwStartNode* pPrvNd; const SwEndNode* pNxtNd; while( 0 != ( pPrvNd = (pNd = &aIdx.GetNode())->GetSectionNode() ) && !( aIdx.GetIndex() < nCmp && nCmp < pPrvNd->EndOfSectionIndex() ) ) { aIdx--; } if( !pPrvNd ) pPrvNd = pNd->IsStartNode() ? (SwStartNode*)pNd : pNd->StartOfSectionNode(); aIdx = pEnd->nNode.GetIndex() + 1; nCmp = pStt->nNode.GetIndex(); while( 0 != ( pNxtNd = (pNd = &aIdx.GetNode())->GetEndNode() ) && pNxtNd->StartOfSectionNode()->IsSectionNode() && !( pNxtNd->StartOfSectionIndex() < nCmp && nCmp < aIdx.GetIndex() ) ) { aIdx++; } if( !pNxtNd ) pNxtNd = pNd->EndOfSectionNode(); if( pPrvNd && pNxtNd && pPrvNd == pNxtNd->StartOfSectionNode() ) { nRet = 3; if( ppSttNd ) *ppSttNd = pPrvNd; } } } else if( !pSectNd && pEndSectNd ) { // versuche eine umschliessende Section zu erzeugen // Aber, nur wenn das Ende am Section Ende liegt! nRet = 0; if( pEnd->nContent.GetIndex() == pCNd->Len() ) { SwNodeIndex aIdx( pEnd->nNode, 1 ); if( aIdx.GetNode().IsEndNode() && 0 != aIdx.GetNode().FindSectionNode() ) { do { aIdx++; } while( aIdx.GetNode().IsEndNode() && 0 != aIdx.GetNode().FindSectionNode() ); // if( !aIdx.GetNode().IsEndNode() ) { nRet = 2; if( ppSttNd ) { aIdx--; *ppSttNd = &aIdx.GetNode(); } } } } } else if( pSectNd && !pEndSectNd ) { // versuche eine umschliessende Section zu erzeugen // Aber, nur wenn der Start am Section Anfang liegt! nRet = 0; if( !pStt->nContent.GetIndex() ) { SwNodeIndex aIdx( pStt->nNode, -1 ); if( aIdx.GetNode().IsSectionNode() ) { do { aIdx--; } while( aIdx.GetNode().IsSectionNode() ); if( !aIdx.GetNode().IsSectionNode() ) { nRet = 1; if( ppSttNd ) { aIdx++; *ppSttNd = &aIdx.GetNode(); } } } } } } return nRet; } SwSection* SwDoc::GetCurrSection( const SwPosition& rPos ) const { const SwSectionNode* pSectNd = rPos.nNode.GetNode().FindSectionNode(); if( pSectNd ) return (SwSection*)&pSectNd->GetSection(); return 0; } SwSectionFmt* SwDoc::MakeSectionFmt( SwSectionFmt *pDerivedFrom ) { if( !pDerivedFrom ) pDerivedFrom = (SwSectionFmt*)pDfltFrmFmt; SwSectionFmt* pNew = new SwSectionFmt( pDerivedFrom, this ); pSectionFmtTbl->Insert( pNew, pSectionFmtTbl->Count() ); return pNew; } void SwDoc::DelSectionFmt( SwSectionFmt *pFmt, BOOL bDelNodes ) { USHORT nPos = pSectionFmtTbl->GetPos( pFmt ); StartUndo(UNDO_DELSECTION, NULL); if( USHRT_MAX != nPos ) { const SwNodeIndex* pIdx = pFmt->GetCntnt( FALSE ).GetCntntIdx(); const SfxPoolItem* pFtnEndAtTxtEnd; if( SFX_ITEM_SET != pFmt->GetItemState( RES_FTN_AT_TXTEND, TRUE, &pFtnEndAtTxtEnd ) || SFX_ITEM_SET != pFmt->GetItemState( RES_END_AT_TXTEND, TRUE, &pFtnEndAtTxtEnd )) pFtnEndAtTxtEnd = 0; const SwSectionNode* pSectNd; if( DoesUndo() ) { ClearRedo(); if( bDelNodes && pIdx && &GetNodes() == &pIdx->GetNodes() && 0 != (pSectNd = pIdx->GetNode().GetSectionNode() )) { SwNodeIndex aUpdIdx( *pIdx ); ClearRedo(); SwPaM aPaM( *pSectNd->EndOfSectionNode(), *pSectNd ); AppendUndo( new SwUndoDelete( aPaM )); if( pFtnEndAtTxtEnd ) GetFtnIdxs().UpdateFtn( aUpdIdx ); SetModified(); //#126178# start/end undo have to be pairs! EndUndo(UNDO_DELSECTION, NULL); return ; } AppendUndo( new SwUndoDelSection( *pFmt ) ); } else if( bDelNodes && pIdx && &GetNodes() == &pIdx->GetNodes() && 0 != (pSectNd = pIdx->GetNode().GetSectionNode() )) { SwNodeIndex aUpdIdx( *pIdx ); DeleteSection( (SwNode*)pSectNd ); if( pFtnEndAtTxtEnd ) GetFtnIdxs().UpdateFtn( aUpdIdx ); SetModified(); //#126178# start/end undo have to be pairs! EndUndo(UNDO_DELSECTION, NULL); return ; } { SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFmt ); pFmt->Modify( &aMsgHint, &aMsgHint ); } // A ClearRedo could result in a rekursive call of this function and delete some section // formats => the position iside the SectionFmtTbl could have changed nPos = pSectionFmtTbl->GetPos( pFmt ); // ACHTUNG: erst aus dem Array entfernen und dann loeschen. // Der Section-DTOR versucht selbst noch sein Format // zu loeschen! pSectionFmtTbl->Remove( nPos ); //FEATURE::CONDCOLL ULONG nCnt = 0, nSttNd = 0; if( pIdx && &GetNodes() == &pIdx->GetNodes() && 0 != (pSectNd = pIdx->GetNode().GetSectionNode() )) { nSttNd = pSectNd->GetIndex(); nCnt = pSectNd->EndOfSectionIndex() - nSttNd - 1; } //FEATURE::CONDCOLL delete pFmt; if( nSttNd && pFtnEndAtTxtEnd ) { SwNodeIndex aUpdIdx( GetNodes(), nSttNd ); GetFtnIdxs().UpdateFtn( aUpdIdx ); } //FEATURE::CONDCOLL SwCntntNode* pCNd; for( ; nCnt--; ++nSttNd ) if( 0 != (pCNd = GetNodes()[ nSttNd ]->GetCntntNode() ) && RES_CONDTXTFMTCOLL == pCNd->GetFmtColl()->Which() ) pCNd->ChkCondColl(); //FEATURE::CONDCOLL } EndUndo(UNDO_DELSECTION, NULL); SetModified(); } void SwDoc::ChgSection( USHORT nPos, const SwSection& rSect, const SfxItemSet* pAttr, sal_Bool bPreventLinkUpdate ) { SwSectionFmt* pFmt = (*pSectionFmtTbl)[ nPos ]; SwSection* pSection = pFmt->GetSection(); /// OD 04.10.2002 #102894# /// remember hidden condition flag of SwSection before changes bool bOldCondHidden = pSection->IsCondHidden() ? true : false; if( *pSection == rSect ) { // die Attribute ueberpruefen BOOL bOnlyAttrChg = FALSE; if( pAttr && pAttr->Count() ) { SfxItemIter aIter( *pAttr ); USHORT nWhich = aIter.GetCurItem()->Which(); while( TRUE ) { if( pFmt->GetFmtAttr( nWhich ) != *aIter.GetCurItem() ) { bOnlyAttrChg = TRUE; break; } if( aIter.IsAtEnd() ) break; nWhich = aIter.NextItem()->Which(); } } if( bOnlyAttrChg ) { const BOOL bDoesUndo = DoesUndo(); if( DoesUndo() ) { ClearRedo(); AppendUndo( new SwUndoChgSection( *pFmt, TRUE ) ); // --> FME 2004-10-13 #i32968# // Inserting columns in the section causes MakeFrmFmt to put two // objects of type SwUndoFrmFmt on the undo stack. We don't want them. DoUndo( FALSE ); // <-- } pFmt->SetFmtAttr( *pAttr ); SetModified(); // --> FME 2004-10-13 #i32968# DoUndo( bDoesUndo ); // <-- } return; } // Teste ob eine gesamte Content-Section (Dokument/TabellenBox/Fly) // versteckt werden soll, koennen wir zur Zeit nicht !!!! const SwNodeIndex* pIdx = 0; { const SwSectionNode* pSectNd; if( rSect.IsHidden() && 0 != (pIdx = pFmt->GetCntnt().GetCntntIdx() ) && 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ) ) { ::lcl_CheckEmptyLayFrm( GetNodes(), (SwSection&)rSect, *pSectNd, *pSectNd->EndOfSectionNode() ); } } const BOOL bDoesUndo = DoesUndo(); if( DoesUndo() ) { ClearRedo(); AppendUndo( new SwUndoChgSection( *pFmt, FALSE ) ); // --> FME 2004-10-13 #i32968# // Inserting columns in the section causes MakeFrmFmt to put two // objects of type SwUndoFrmFmt on the undo stack. We don't want them. DoUndo( FALSE ); // <-- } // #56167# Der LinkFileName koennte auch nur aus Separatoren bestehen String sCompareString = sfx2::cTokenSeperator; sCompareString += sfx2::cTokenSeperator; BOOL bUpdate = ( !pSection->IsLinkType() && rSect.IsLinkType() ) || ( rSect.GetLinkFileName().Len() && rSect.GetLinkFileName() != sCompareString && rSect.GetLinkFileName() != pSection->GetLinkFileName()); String sSectName( rSect.GetName() ); if( sSectName != pSection->GetName() ) GetUniqueSectionName( &sSectName ); else sSectName.Erase(); /// OD 04.10.2002 #102894# - NOTE /// In SwSection::operator=(..) class member bCondHiddenFlag is always set to TRUE. /// IMHO this have to be changed, but I can't estimate the consequences: /// Either it is set to TRUE using corresponding method , /// or it is set to the value of SwSection which is assigned to it. /// Discussion with AMA results that the adjustment to the assignment operator /// could be very risky -> see notes in bug #102894#. *pSection = rSect; if( pAttr ) pSection->GetFmt()->SetFmtAttr( *pAttr ); if( sSectName.Len() ) pSection->SetName( sSectName ); // ist eine Condition gesetzt if( pSection->IsHidden() && pSection->GetCondition().Len() ) { // dann berechne bis zu dieser Position SwCalc aCalc( *this ); if( !pIdx ) pIdx = pFmt->GetCntnt().GetCntntIdx(); FldsToCalc( aCalc, pIdx->GetIndex(), USHRT_MAX ); /// OD 04.10.2002 #102894# /// Because on using SwSection::operator=() to set up /// with and the above given note, the hidden condition flag /// has to be set to FALSE, if hidden condition flag of GetSection()> /// (SwSection before the changes) is FALSE (already saved in ) /// and new calculated condition is TRUE. /// This is necessary, because otherwise the would have /// no effect. bool bCalculatedCondHidden = aCalc.Calculate( pSection->GetCondition() ).GetBool() ? true : false; if ( bCalculatedCondHidden && !bOldCondHidden ) { pSection->SetCondHidden( false ); } pSection->SetCondHidden( bCalculatedCondHidden ); } if( bUpdate ) pSection->CreateLink( bPreventLinkUpdate ? CREATE_CONNECT : CREATE_UPDATE ); else if( !pSection->IsLinkType() && pSection->IsConnected() ) { pSection->Disconnect(); GetLinkManager().Remove( &pSection->GetBaseLink() ); } SetModified(); // --> FME 2004-10-13 #i32968# DoUndo( bDoesUndo ); // <-- } /* -----------------19.02.99 09:31------------------- * LockFrms wurde im InsertSection genutzt, um zu verhindern, dass * SectionFrms durch das DelFrms zerstoert werden. Dies ist durch * den Destroy-Listen-Mechanismus ueberfluessig geworden. * Falls diese Methode doch noch einmal reanimiert wird, bietet es * sich vielleicht an, beim Entlocken die SectionFrms auf Inhalt zu * pruefen und dann ggf. zur Zerstoerung anzumelden. * --------------------------------------------------*/ // und dann waren da noch die Fussnoten: void lcl_DeleteFtn( SwSectionNode *pNd, ULONG nStt, ULONG nEnd ) { SwFtnIdxs& rFtnArr = pNd->GetDoc()->GetFtnIdxs(); if( rFtnArr.Count() ) { USHORT nPos; rFtnArr.SeekEntry( SwNodeIndex( *pNd ), &nPos ); SwTxtFtn* pSrch; // loesche erstmal alle, die dahinter stehen while( nPos < rFtnArr.Count() && _SwTxtFtn_GetIndex( (pSrch = rFtnArr[ nPos ]) ) <= nEnd ) { // Werden die Nodes nicht geloescht mussen sie bei den Seiten // abmeldet (Frms loeschen) werden, denn sonst bleiben sie // stehen (Undo loescht sie nicht!) pSrch->DelFrms(); ++nPos; } while( nPos-- && _SwTxtFtn_GetIndex( (pSrch = rFtnArr[ nPos ]) ) >= nStt ) { // Werden die Nodes nicht geloescht mussen sie bei den Seiten // abmeldet (Frms loeschen) werden, denn sonst bleiben sie // stehen (Undo loescht sie nicht!) pSrch->DelFrms(); } } } inline BOOL lcl_IsTOXSection( const SwSection& rSection ) { return TOX_CONTENT_SECTION == rSection.GetType() || TOX_HEADER_SECTION == rSection.GetType(); } SwSectionNode* SwNodes::InsertSection( const SwNodeIndex& rNdIdx, SwSectionFmt& rSectionFmt, const SwSection& rSection, const SwNodeIndex* pEnde, BOOL bInsAtStart, BOOL bCreateFrms ) { SwNodeIndex aInsPos( rNdIdx ); if( !pEnde ) // kein Bereich also neue Section davor/hinter anlegen { // #i26762# ASSERT(!pEnde || rNdIdx <= *pEnde, "Section start and end in wrong order!"); if( bInsAtStart ) { if( !lcl_IsTOXSection( rSection )) { do { aInsPos--; } while( aInsPos.GetNode().IsSectionNode() ); aInsPos++; } } else { SwNode* pNd; aInsPos++; if( !lcl_IsTOXSection( rSection )) while( aInsPos.GetIndex() < Count() - 1 && ( pNd = &aInsPos.GetNode())->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode()) aInsPos++; } } SwSectionNode* pSectNd = new SwSectionNode( aInsPos, rSectionFmt ); if( pEnde ) { // Sonderfall fuer die Reader/Writer if( &pEnde->GetNode() != &GetEndOfContent() ) aInsPos = pEnde->GetIndex()+1; // #i58710: We created a RTF document with a section break inside a table cell // We are not able to handle a section start inside a table and the section end outside. const SwNode* pLastNode = pSectNd->StartOfSectionNode()->EndOfSectionNode(); if( aInsPos > pLastNode->GetIndex() ) aInsPos = pLastNode->GetIndex(); // Another way round: if the section starts outside a table but the end is inside... // aInsPos is at the moment the Position where my EndNode will be inserted const SwStartNode* pStartNode = aInsPos.GetNode().StartOfSectionNode(); // This StartNode should be in front of me, but if not, I wanna survive ULONG nMyIndex = pSectNd->GetIndex(); if( pStartNode->GetIndex() > nMyIndex ) // Suspicious! { const SwNode* pTemp; do { pTemp = pStartNode; // pTemp is a suspicious one pStartNode = pStartNode->StartOfSectionNode(); } while( pStartNode->GetIndex() > nMyIndex ); pTemp = pTemp->EndOfSectionNode(); // If it starts behind me but ends behind my end... if( pTemp->GetIndex() >= aInsPos.GetIndex() ) aInsPos = pTemp->GetIndex()+1; // ...I have to correct my end position } } else { SwTxtNode* pCpyTNd = rNdIdx.GetNode().GetTxtNode(); if( pCpyTNd ) { SwTxtNode* pTNd = new SwTxtNode( aInsPos, pCpyTNd->GetTxtColl() ); if( pCpyTNd->HasSwAttrSet() ) { // Task 70955 - move PageDesc/Break to the first Node of the // section const SfxItemSet& rSet = *pCpyTNd->GetpSwAttrSet(); if( SFX_ITEM_SET == rSet.GetItemState( RES_BREAK ) || SFX_ITEM_SET == rSet.GetItemState( RES_PAGEDESC )) { SfxItemSet aSet( rSet ); if( bInsAtStart ) pCpyTNd->ResetAttr( RES_PAGEDESC, RES_BREAK ); else { aSet.ClearItem( RES_PAGEDESC ); aSet.ClearItem( RES_BREAK ); } pTNd->SetAttr( aSet ); } else pTNd->SetAttr( rSet ); } // den Frame anlegen nicht vergessen !! pCpyTNd->MakeFrms( *pTNd ); } else new SwTxtNode( aInsPos, (SwTxtFmtColl*)GetDoc()->GetDfltTxtFmtColl() ); } new SwEndNode( aInsPos, *pSectNd ); pSectNd->GetSection() = rSection; SwSectionFmt* pSectFmt = pSectNd->GetSection().GetFmt(); // Hier bietet sich als Optimierung an, vorhandene Frames nicht zu // zerstoeren und wieder neu anzulegen, sondern nur umzuhaengen. BOOL bInsFrm = bCreateFrms && !pSectNd->GetSection().IsHidden() && GetDoc()->GetRootFrm(); SwNode2Layout *pNode2Layout = NULL; if( bInsFrm ) { SwNodeIndex aTmp( *pSectNd ); if( !pSectNd->GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() ) ) // dann sammel mal alle Uppers ein pNode2Layout = new SwNode2Layout( *pSectNd ); } // jetzt noch bei allen im Bereich den richtigen StartNode setzen ULONG nEnde = pSectNd->EndOfSectionIndex(); ULONG nStart = pSectNd->GetIndex()+1; ULONG nSkipIdx = ULONG_MAX; for( ULONG n = nStart; n < nEnde; ++n ) { SwNode* pNd = (*this)[n]; //JP 30.04.99: Bug 65644 - alle in der NodeSection liegenden // Sections unter die neue haengen if( ULONG_MAX == nSkipIdx ) pNd->pStartOfSection = pSectNd; else if( n >= nSkipIdx ) nSkipIdx = ULONG_MAX; if( pNd->IsStartNode() ) { // die Verschachtelung der Formate herstellen! if( pNd->IsSectionNode() ) { ((SwSectionNode*)pNd)->GetSection().GetFmt()-> SetDerivedFrom( pSectFmt ); ((SwSectionNode*)pNd)->DelFrms(); n = pNd->EndOfSectionIndex(); } else { if( pNd->IsTableNode() ) ((SwTableNode*)pNd)->DelFrms(); if( ULONG_MAX == nSkipIdx ) nSkipIdx = pNd->EndOfSectionIndex(); } } else if( pNd->IsCntntNode() ) ((SwCntntNode*)pNd)->DelFrms(); } lcl_DeleteFtn( pSectNd, nStart, nEnde ); if( bInsFrm ) { if( pNode2Layout ) { ULONG nIdx = pSectNd->GetIndex(); pNode2Layout->RestoreUpperFrms( pSectNd->GetNodes(), nIdx, nIdx + 1 ); delete pNode2Layout; } else pSectNd->MakeFrms( &aInsPos ); } return pSectNd; } SwSectionNode* SwNode::FindSectionNode() { if( IsSectionNode() ) return GetSectionNode(); SwStartNode* pTmp = pStartOfSection; while( !pTmp->IsSectionNode() && pTmp->GetIndex() ) #if defined( ALPHA ) && defined( UNX ) pTmp = ((SwNode*)pTmp)->pStartOfSection; #else pTmp = pTmp->pStartOfSection; #endif return pTmp->GetSectionNode(); } //--------- // SwSectionNode //--------- SwSectionNode::SwSectionNode( const SwNodeIndex& rIdx, SwSectionFmt& rFmt ) : SwStartNode( rIdx, ND_SECTIONNODE ) { SwSectionNode* pParent = StartOfSectionNode()->FindSectionNode(); if( pParent ) { // das Format beim richtigen Parent anmelden. rFmt.SetDerivedFrom( pParent->GetSection().GetFmt() ); } pSection = new SwSection( CONTENT_SECTION, rFmt.GetName(), &rFmt ); // jetzt noch die Verbindung von Format zum Node setzen // Modify unterdruecken, interresiert keinen rFmt.LockModify(); rFmt.SetFmtAttr( SwFmtCntnt( this ) ); rFmt.UnlockModify(); } #if OSL_DEBUG_LEVEL > 1 //Hier werden ueberfluessige SectionFrms entfernt SwFrm* SwClearDummies( SwFrm* pFrm ) { SwFrm* pTmp = pFrm; while( pTmp ) { ASSERT( !pTmp->GetUpper(), "SwClearDummies: No Upper allowed!" ); if( pTmp->IsSctFrm() ) { SwSectionFrm* pSectFrm = (SwSectionFrm*)pFrm; pTmp = pTmp->GetNext(); if( !pSectFrm->GetLower() ) { if( pSectFrm->GetPrev() ) pSectFrm->GetPrev()->pNext = pTmp; else pFrm = pTmp; if( pTmp ) pTmp->pPrev = pSectFrm->GetPrev(); delete pSectFrm; } } else pTmp = pTmp->GetNext(); } return pFrm; } #endif SwSectionNode::~SwSectionNode() { { SwClientIter aIter( *(pSection->GetFmt()) ); SwClient *pLast = aIter.GoStart(); while ( pLast ) { if ( pLast->IsA( TYPE(SwFrm) ) ) { SwSectionFrm *pSectFrm = (SwSectionFrm*)pLast; SwSectionFrm::MoveCntntAndDelete( pSectFrm, TRUE ); pLast = aIter.GoStart(); } else pLast = aIter++; } } SwDoc* pDoc = GetDoc(); SwSectionFmt* pFmt = pSection->GetFmt(); if( pFmt ) { // das Attribut entfernen, weil die Section ihr Format loescht // und falls das Cntnt-Attribut vorhanden ist, die Section aufhebt. pFmt->LockModify(); pFmt->ResetFmtAttr( RES_CNTNT ); pFmt->UnlockModify(); } BOOL bUndo = pDoc->DoesUndo(); // verhinder beim Loeschen aus der Undo/Redo-History einen rekursiven Aufruf if( bUndo && &pDoc->GetNodes() != &GetNodes() ) pDoc->DoUndo( FALSE ); DELETEZ( pSection ); pDoc->DoUndo( bUndo ); } // setze ein neues SectionObject. Erstmal nur gedacht fuer die // neuen VerzeichnisSections. Der geht ueber in den Besitz des Nodes! void SwSectionNode::SetNewSection( SwSection* pNewSection ) { ASSERT( pNewSection, "ohne Pointer geht hier nichts" ); if( pNewSection ) { SwNode2Layout aN2L( *this ); // einige Flags sollten ueber nommen werden! pNewSection->bProtectFlag = pSection->bProtectFlag; pNewSection->bHiddenFlag = pSection->bHiddenFlag; pNewSection->bHidden = pSection->bHidden; pNewSection->bCondHiddenFlag = pSection->bCondHiddenFlag; // The section frame contains a pointer to the section. That for, // the frame must be destroyed before deleting the section. DelFrms(); delete pSection; pSection = pNewSection; ULONG nIdx = GetIndex(); aN2L.RestoreUpperFrms( GetNodes(), nIdx, nIdx + 1 ); } } SwFrm *SwSectionNode::MakeFrm() { pSection->bHiddenFlag = FALSE; return new SwSectionFrm( *pSection ); } //Methode erzeugt fuer den vorhergehenden Node alle Ansichten vom //Dokument. Die erzeugten Contentframes werden in das entsprechende //Layout gehaengt. void SwSectionNode::MakeFrms(const SwNodeIndex & rIdx ) { // also nehme meinen nachfolgenden oder vorhergehenden ContentFrame: SwNodes& rNds = GetNodes(); if( rNds.IsDocNodes() && rNds.GetDoc()->GetRootFrm() ) { if( GetSection().IsHidden() || IsCntntHidden() ) { SwNodeIndex aIdx( *EndOfSectionNode() ); SwCntntNode* pCNd = rNds.GoNextSection( &aIdx, TRUE, FALSE ); if( !pCNd ) { aIdx = *this; if( 0 == ( pCNd = rNds.GoPrevSection( &aIdx, TRUE, FALSE )) ) return ; } pCNd = rNds[ aIdx ]->GetCntntNode(); pCNd->MakeFrms( (SwCntntNode&)rIdx.GetNode() ); } else { SwNode2Layout aNode2Layout( *this, rIdx.GetIndex() ); SwFrm *pFrm, *pNew; while( 0 != (pFrm = aNode2Layout.NextFrm()) ) { ASSERT( pFrm->IsSctFrm(), "Depend von Section keine Section." ); pNew = rIdx.GetNode().GetCntntNode()->MakeFrm(); SwSectionNode* pS = rIdx.GetNode().FindSectionNode(); // --> OD 2008-06-23 #156927# // Assure that node is not inside a table, which is inside the // found section. if ( pS ) { SwTableNode* pTableNode = rIdx.GetNode().FindTableNode(); if ( pTableNode && pTableNode->GetIndex() > pS->GetIndex() ) { pS = 0; } } // <-- // if the node is in a section, the sectionframe now // has to be created.. // OD 14.11.2002 #104684# - boolean to control of a new // section frame. bool bInitNewSect = false; if( pS ) { SwSectionFrm *pSct = new SwSectionFrm( pS->GetSection() ); // OD 14.11.2002 #104684# - prepare of new section frame. bInitNewSect = true; SwLayoutFrm* pUp = pSct; while( pUp->Lower() ) // for columned sections { ASSERT( pUp->Lower()->IsLayoutFrm(),"Who's in there?" ); pUp = (SwLayoutFrm*)pUp->Lower(); } pNew->Paste( pUp, NULL ); // --> OD 2005-12-01 #i27138# // notify accessibility paragraphs objects about changed // CONTENT_FLOWS_FROM/_TO relation. // Relation CONTENT_FLOWS_FROM for next paragraph will change // and relation CONTENT_FLOWS_TO for previous paragraph will change. if ( pNew->IsTxtFrm() ) { ViewShell* pViewShell( pNew->GetShell() ); if ( pViewShell && pViewShell->GetLayout() && pViewShell->GetLayout()->IsAnyShellAccessible() ) { pViewShell->InvalidateAccessibleParaFlowRelation( dynamic_cast(pNew->FindNextCnt( true )), dynamic_cast(pNew->FindPrevCnt( true )) ); } } // <-- pNew = pSct; } // wird ein Node vorher oder nachher mit Frames versehen if ( rIdx < GetIndex() ) // der neue liegt vor mir pNew->Paste( pFrm->GetUpper(), pFrm ); else // der neue liegt hinter mir pNew->Paste( pFrm->GetUpper(), pFrm->GetNext() ); // --> OD 2005-12-01 #i27138# // notify accessibility paragraphs objects about changed // CONTENT_FLOWS_FROM/_TO relation. // Relation CONTENT_FLOWS_FROM for next paragraph will change // and relation CONTENT_FLOWS_TO for previous paragraph will change. if ( pNew->IsTxtFrm() ) { ViewShell* pViewShell( pNew->GetShell() ); if ( pViewShell && pViewShell->GetLayout() && pViewShell->GetLayout()->IsAnyShellAccessible() ) { pViewShell->InvalidateAccessibleParaFlowRelation( dynamic_cast(pNew->FindNextCnt( true )), dynamic_cast(pNew->FindPrevCnt( true )) ); } } // <-- if ( bInitNewSect ) static_cast(pNew)->Init(); } } } } //Fuer jedes vorkommen im Layout einen SectionFrm anlegen und vor den //entsprechenden CntntFrm pasten. void SwSectionNode::MakeFrms( SwNodeIndex* pIdxBehind, SwNodeIndex* pEndIdx ) { ASSERT( pIdxBehind, "kein Index" ); SwNodes& rNds = GetNodes(); SwDoc* pDoc = rNds.GetDoc(); *pIdxBehind = *this; pSection->bHiddenFlag = TRUE; if( rNds.IsDocNodes() ) { SwNodeIndex *pEnd = pEndIdx ? pEndIdx : new SwNodeIndex( *EndOfSectionNode(), 1 ); ::MakeFrms( pDoc, *pIdxBehind, *pEnd ); if( !pEndIdx ) delete pEnd; } } void SwSectionNode::DelFrms() { ULONG nStt = GetIndex()+1, nEnd = EndOfSectionIndex(); if( nStt >= nEnd ) { // unser Flag muessen wir noch aktualisieren // pSection->bHiddenFlag = TRUE; return ; } SwNodes& rNds = GetNodes(); pSection->GetFmt()->DelFrms(); // unser Flag muessen wir noch aktualisieren pSection->bHiddenFlag = TRUE; // Bug 30582: falls der Bereich in Fly oder TabellenBox ist, dann // kann er nur "gehiddet" werden, wenn weiterer Content // vorhanden ist, der "Frames" haelt. Sonst hat der // Fly/TblBox-Frame keinen Lower !!! { SwNodeIndex aIdx( *this ); if( !rNds.GoPrevSection( &aIdx, TRUE, FALSE ) || !CheckNodesRange( *this, aIdx, TRUE ) || // OD 04.11.2003 #i21457# !lcl_IsInSameTblBox( rNds, *this, true )) { aIdx = *EndOfSectionNode(); if( !rNds.GoNextSection( &aIdx, TRUE, FALSE ) || !CheckNodesRange( *EndOfSectionNode(), aIdx, TRUE ) || // OD 04.11.2003 #i21457# !lcl_IsInSameTblBox( rNds, *EndOfSectionNode(), false )) pSection->bHiddenFlag = FALSE; } } } SwSectionNode* SwSectionNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const { // in welchen Array steht ich denn: Nodes, UndoNodes ?? const SwNodes& rNds = GetNodes(); // das SectionFrmFmt kopieren SwSectionFmt* pSectFmt = pDoc->MakeSectionFmt( 0 ); pSectFmt->CopyAttrs( *GetSection().GetFmt() ); SwSectionNode* pSectNd = new SwSectionNode( rIdx, *pSectFmt ); SwEndNode* pEndNd = new SwEndNode( rIdx, *pSectNd ); SwNodeIndex aInsPos( *pEndNd ); // Werte uebertragen SwSection* pNewSect = pSectNd->pSection; switch( GetSection().GetType() ) { case TOX_CONTENT_SECTION: { ASSERT( GetSection().ISA( SwTOXBaseSection ), "keine TOXBaseSection!" ); SwTOXBaseSection& rTOXSect = (SwTOXBaseSection&)GetSection(); SwTOXBase aTmp( rTOXSect, pDoc ); SwTOXBaseSection* pNew = new SwTOXBaseSection( aTmp ); pNewSect = pNew; pSectFmt->Add( pNewSect ); pSectNd->SetNewSection( pNew ); } break; default: // beim Move den Namen beibehalten if( rNds.GetDoc() == pDoc && pDoc->IsCopyIsMove() ) pNewSect->SetName( GetSection().GetName() ); else pNewSect->SetName( pDoc->GetUniqueSectionName( &GetSection().GetName() ) ); break; } pNewSect->SetType( GetSection().GetType() ); pNewSect->SetCondition( GetSection().GetCondition() ); pNewSect->SetLinkFileName( GetSection().GetLinkFileName() ); if( !pNewSect->IsHiddenFlag() && GetSection().IsHidden() ) pNewSect->SetHidden( TRUE ); if( !pNewSect->IsProtectFlag() && GetSection().IsProtect() ) pNewSect->SetProtect( TRUE ); // --> FME 2004-06-22 #114856# edit in readonly sections if( !pNewSect->IsEditInReadonlyFlag() && GetSection().IsEditInReadonly() ) pNewSect->SetEditInReadonly( TRUE ); // <-- SwNodeRange aRg( *this, +1, *EndOfSectionNode() ); // (wo stehe in denn nun ??) rNds._Copy( aRg, aInsPos, FALSE ); // loesche alle Frames vom kopierten Bereich, diese werden beim // erzeugen des SectionFrames angelegt ! pSectNd->DelFrms(); // dann kopiere auch noch die Links/Server if( pNewSect->IsLinkType() ) // den Link eintragen pNewSect->CreateLink( pDoc->GetRootFrm() ? CREATE_CONNECT : CREATE_NONE ); // falls als Server aus dem Undo kopiert wird, wieder eintragen if( pSection->IsServer() && pDoc->GetUndoNds() == &rNds ) { pNewSect->SetRefObject( pSection->GetObject() ); pDoc->GetLinkManager().InsertServer( pNewSect->GetObject() ); } return pSectNd; } BOOL SwSectionNode::IsCntntHidden() const { ASSERT( !pSection->IsHidden(), "That's simple: Hidden Section => Hidden Content" ); SwNodeIndex aTmp( *this, 1 ); ULONG nEnd = EndOfSectionIndex(); while( aTmp < nEnd ) { if( aTmp.GetNode().IsSectionNode() ) { const SwSection& rSect = ((SwSectionNode&)aTmp.GetNode()).GetSection(); if( rSect.IsHiddenFlag() ) // dann diese Section ueberspringen aTmp = *aTmp.GetNode().EndOfSectionNode(); } else { if( aTmp.GetNode().IsCntntNode() || aTmp.GetNode().IsTableNode() ) return FALSE; // Nicht versteckter Inhalt wurde gefunden ASSERT( aTmp.GetNode().IsEndNode(), "EndNode expected" ); } aTmp++; } return TRUE; // Alles versteckt } void SwSectionNode::NodesArrChgd() { SwSectionFmt* pFmt = pSection->GetFmt(); if( pFmt ) { SwNodes& rNds = GetNodes(); SwDoc* pDoc = pFmt->GetDoc(); if( !rNds.IsDocNodes() ) { SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFmt ); pFmt->Modify( &aMsgHint, &aMsgHint ); } pFmt->LockModify(); pFmt->SetFmtAttr( SwFmtCntnt( this )); pFmt->UnlockModify(); SwSectionNode* pSectNd = StartOfSectionNode()->FindSectionNode(); // set the correct parent from the new section pFmt->SetDerivedFrom( pSectNd ? pSectNd->GetSection().GetFmt() : pDoc->GetDfltFrmFmt() ); // jetzt noch bei allen im Bereich den richtigen StartNode setzen ULONG nStart = GetIndex()+1, nEnde = EndOfSectionIndex(); for( ULONG n = nStart; n < nEnde; ++n ) // die Verschachtelung der Formate herstellen! if( 0 != ( pSectNd = rNds[ n ]->GetSectionNode() ) ) { pSectNd->GetSection().GetFmt()->SetDerivedFrom( pFmt ); n = pSectNd->EndOfSectionIndex(); } // verschieben vom Nodes- ins UndoNodes-Array? if( rNds.IsDocNodes() ) { ASSERT( pDoc == GetDoc(), "verschieben in unterschiedliche Documente?" ); if( pSection->IsLinkType() ) // den Link austragen pSection->CreateLink( pDoc->GetRootFrm() ? CREATE_CONNECT : CREATE_NONE ); if( pSection->IsServer() ) // als Server austragen pDoc->GetLinkManager().InsertServer( pSection->GetObject() ); } else { if( CONTENT_SECTION != pSection->GetType() ) // den Link austragen pDoc->GetLinkManager().Remove( &pSection->GetBaseLink() ); if( pSection->IsServer() ) // als Server austragen pDoc->GetLinkManager().RemoveServer( pSection->GetObject() ); } } } String SwDoc::GetUniqueSectionName( const String* pChkStr ) const { ResId aId( STR_REGION_DEFNAME, *pSwResMgr ); String aName( aId ); xub_StrLen nNmLen = aName.Len(); USHORT nNum = 0; USHORT nTmp, nFlagSize = ( pSectionFmtTbl->Count() / 8 ) +2; BYTE* pSetFlags = new BYTE[ nFlagSize ]; memset( pSetFlags, 0, nFlagSize ); const SwSectionNode* pSectNd; USHORT n; for( n = 0; n < pSectionFmtTbl->Count(); ++n ) if( 0 != ( pSectNd = (*pSectionFmtTbl)[ n ]->GetSectionNode( FALSE ) )) { const String& rNm = pSectNd->GetSection().GetName(); if( rNm.Match( aName ) == nNmLen ) { // Nummer bestimmen und das Flag setzen nNum = static_cast(rNm.Copy( nNmLen ).ToInt32()); if( nNum-- && nNum < pSectionFmtTbl->Count() ) pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 )); } if( pChkStr && pChkStr->Equals( rNm ) ) pChkStr = 0; } if( !pChkStr ) { // alle Nummern entsprechend geflag, also bestimme die richtige Nummer nNum = pSectionFmtTbl->Count(); for( n = 0; n < nFlagSize; ++n ) if( 0xff != ( nTmp = pSetFlags[ n ] )) { // also die Nummer bestimmen nNum = n * 8; while( nTmp & 1 ) ++nNum, nTmp >>= 1; break; } } delete [] pSetFlags; if( pChkStr ) return *pChkStr; return aName += String::CreateFromInt32( ++nNum ); }