LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/docnode - ndsect.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 177 664 26.7 %
Date: 2012-12-27 Functions: 14 24 58.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10