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

Generated by: LCOV version 1.10