LCOV - code coverage report
Current view: top level - sw/source/core/doc - ftnidx.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 126 174 72.4 %
Date: 2014-11-03 Functions: 8 9 88.9 %
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 <txtftn.hxx>
      21             : #include <fmtftn.hxx>
      22             : #include <ftninfo.hxx>
      23             : #include <doc.hxx>
      24             : #include <IDocumentLayoutAccess.hxx>
      25             : #include <ftnidx.hxx>
      26             : #include <ndtxt.hxx>
      27             : #include <ndindex.hxx>
      28             : #include <section.hxx>
      29             : #include <fmtftntx.hxx>
      30             : #include <rootfrm.hxx>
      31             : 
      32        1362 : bool CompareSwFtnIdxs::operator()(SwTxtFtn* const& lhs, SwTxtFtn* const& rhs) const
      33             : {
      34        1362 :     sal_uLong nIdxLHS = _SwTxtFtn_GetIndex( lhs );
      35        1362 :     sal_uLong nIdxRHS = _SwTxtFtn_GetIndex( rhs );
      36        1362 :     return ( nIdxLHS == nIdxRHS && lhs->GetStart() < rhs->GetStart() ) || nIdxLHS < nIdxRHS;
      37             : }
      38             : 
      39        3824 : void SwFtnIdxs::UpdateFtn( const SwNodeIndex& rStt )
      40             : {
      41        3824 :     if( empty() )
      42        7062 :         return;
      43             : 
      44             :     // Get the NodesArray using the first foot note's StartIndex
      45         352 :     SwDoc* pDoc = rStt.GetNode().GetDoc();
      46         352 :     if( pDoc->IsInReading() )
      47         118 :         return ;
      48             :     SwTxtFtn* pTxtFtn;
      49             : 
      50         234 :     const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
      51         234 :     const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();
      52             : 
      53             :     // For normal foot notes we treat per-chapter and per-document numbering
      54             :     // separately. For Endnotes we only have per-document numbering.
      55         234 :     if( FTNNUM_CHAPTER == rFtnInfo.eNum )
      56             :     {
      57           6 :         const SwOutlineNodes& rOutlNds = pDoc->GetNodes().GetOutLineNds();
      58           6 :         const SwNode* pCapStt = &pDoc->GetNodes().GetEndOfExtras();
      59           6 :         sal_uLong nCapEnd = pDoc->GetNodes().GetEndOfContent().GetIndex();
      60           6 :         if( !rOutlNds.empty() )
      61             :         {
      62             :             // Find the Chapter's start, which contains rStt
      63           0 :             size_t n = 0;
      64             : 
      65           0 :             for( ; n < rOutlNds.size(); ++n )
      66           0 :                 if( rOutlNds[ n ]->GetIndex() > rStt.GetIndex() )
      67           0 :                     break;      // found it!
      68           0 :                 else if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )
      69           0 :                     pCapStt = rOutlNds[ n ];    // Beginning of a new Chapter
      70             :             // now find the end of the range
      71           0 :             for( ; n < rOutlNds.size(); ++n )
      72           0 :                 if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )
      73             :                 {
      74           0 :                     nCapEnd = rOutlNds[ n ]->GetIndex();    // End of the found Chapter
      75           0 :                     break;
      76             :                 }
      77             :         }
      78             : 
      79           6 :         size_t nPos = 0;
      80           6 :         size_t nFtnNo = 1;
      81           6 :         if( SeekEntry( *pCapStt, &nPos ) && nPos )
      82             :         {
      83             :             // Step forward until the Index is not the same anymore
      84           0 :             const SwNode* pCmpNd = &rStt.GetNode();
      85           0 :             while( nPos && pCmpNd == &((*this)[ --nPos ]->GetTxtNode()) )
      86             :                 ;
      87           0 :             ++nPos;
      88             :         }
      89             : 
      90           6 :         if( nPos == size() )       // nothing found
      91           0 :             return;
      92             : 
      93           6 :         if( rOutlNds.empty() )
      94           6 :             nFtnNo = nPos+1;
      95             : 
      96          12 :         for( ; nPos < size(); ++nPos )
      97             :         {
      98           6 :             pTxtFtn = (*this)[ nPos ];
      99           6 :             if( pTxtFtn->GetTxtNode().GetIndex() >= nCapEnd )
     100           0 :                 break;
     101             : 
     102           6 :             const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
     103          12 :             if( rFtn.GetNumStr().isEmpty() && !rFtn.IsEndNote() &&
     104           6 :                 !SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
     105             :             {
     106           6 :                 pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nFtnNo++, rFtn.GetNumStr() );
     107             :             }
     108             :         }
     109             :     }
     110             : 
     111         234 :     SwUpdFtnEndNtAtEnd aNumArr;
     112             : 
     113             :     // unless we have per-document numbering, only look at endnotes here
     114         234 :     const bool bEndNoteOnly = FTNNUM_DOC != rFtnInfo.eNum;
     115             : 
     116             :     size_t nPos;
     117         234 :     size_t nFtnNo = 1;
     118         234 :     size_t nEndNo = 1;
     119         234 :     sal_uLong nUpdNdIdx = rStt.GetIndex();
     120         270 :     for( nPos = 0; nPos < size(); ++nPos )
     121             :     {
     122         270 :         pTxtFtn = (*this)[ nPos ];
     123         270 :         if( nUpdNdIdx <= pTxtFtn->GetTxtNode().GetIndex() )
     124         234 :             break;
     125             : 
     126          36 :         const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
     127          36 :         if( rFtn.GetNumStr().isEmpty() )
     128             :         {
     129          36 :             if( !aNumArr.ChkNumber( *pTxtFtn ) )
     130             :             {
     131          36 :                 if( pTxtFtn->GetFtn().IsEndNote() )
     132          18 :                     nEndNo++;
     133             :                 else
     134          18 :                     nFtnNo++;
     135             :             }
     136             :         }
     137             :     }
     138             : 
     139             :     // Set the array number for all footnotes starting from nPos
     140         578 :     for( ; nPos < size(); ++nPos )
     141             :     {
     142         344 :         pTxtFtn = (*this)[ nPos ];
     143         344 :         const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
     144         344 :         if( rFtn.GetNumStr().isEmpty() )
     145             :         {
     146         180 :             sal_uInt16 nSectNo = aNumArr.ChkNumber( *pTxtFtn );
     147         180 :             if( !nSectNo && ( rFtn.IsEndNote() || !bEndNoteOnly ))
     148         174 :                 nSectNo = rFtn.IsEndNote()
     149             :                             ? rEndInfo.nFtnOffset + nEndNo++
     150         174 :                             : rFtnInfo.nFtnOffset + nFtnNo++;
     151             : 
     152         180 :             if( nSectNo )
     153             :             {
     154         174 :                 pTxtFtn->SetNumber( nSectNo, rFtn.GetNumStr() );
     155             :             }
     156             :         }
     157         234 :     }
     158             : }
     159             : 
     160          76 : void SwFtnIdxs::UpdateAllFtn()
     161             : {
     162          76 :     if( empty() )
     163         118 :         return;
     164             : 
     165             :     // Get the NodesArray via the StartIndex of the first Footnote
     166          34 :     SwDoc* pDoc = (SwDoc*) (*this)[ 0 ]->GetTxtNode().GetDoc();
     167             :     SwTxtFtn* pTxtFtn;
     168          34 :     const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
     169          34 :     const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();
     170             : 
     171          34 :     SwUpdFtnEndNtAtEnd aNumArr;
     172             : 
     173          34 :     SwRootFrm* pTmpRoot = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
     174          68 :     std::set<SwRootFrm*> aAllLayouts = pDoc->GetAllLayouts();
     175             :     // For normal Footnotes per-chapter and per-document numbering are treated separately.
     176             :     // For Endnotes we only have document-wise numbering.
     177          34 :     if( FTNNUM_CHAPTER == rFtnInfo.eNum )
     178             :     {
     179          10 :         const SwOutlineNodes& rOutlNds = pDoc->GetNodes().GetOutLineNds();
     180          10 :         sal_uInt16 nNo = 1;     // Number for the Footnotes
     181          10 :         size_t nFtnIdx = 0;     // Index into theFtnIdx array
     182          10 :         for( size_t n = 0; n < rOutlNds.size(); ++n )
     183             :         {
     184           0 :             if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )
     185             :             {
     186           0 :                 sal_uLong nCapStt = rOutlNds[ n ]->GetIndex();  // Start of a new chapter
     187           0 :                 for( ; nFtnIdx < size(); ++nFtnIdx )
     188             :                 {
     189           0 :                     pTxtFtn = (*this)[ nFtnIdx ];
     190           0 :                     if( pTxtFtn->GetTxtNode().GetIndex() >= nCapStt )
     191           0 :                         break;
     192             : 
     193             :                     // Endnotes are per-document only
     194           0 :                     const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
     195           0 :                     if( !rFtn.IsEndNote() && rFtn.GetNumStr().isEmpty() &&
     196           0 :                         !SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
     197             :                     {
     198           0 :                         pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nNo++, rFtn.GetNumStr() );
     199             :                     }
     200             :                 }
     201           0 :                 if( nFtnIdx >= size() )
     202           0 :                     break;          // ok, everything is updated
     203           0 :                 nNo = 1;
     204             :             }
     205             :         }
     206             : 
     207          20 :         for( nNo = 1; nFtnIdx < size(); ++nFtnIdx )
     208             :         {
     209             :             // Endnotes are per-document
     210          10 :             pTxtFtn = (*this)[ nFtnIdx ];
     211          10 :             const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
     212          20 :             if( !rFtn.IsEndNote() && rFtn.GetNumStr().isEmpty() &&
     213          10 :                 !SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
     214             :             {
     215          10 :                 pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nNo++, rFtn.GetNumStr() );
     216             :             }
     217             :         }
     218             :     }
     219             : 
     220             :     // We use bool here, so that we also iterate through the Endnotes with a chapter setting.
     221          34 :     const bool bEndNoteOnly = FTNNUM_DOC != rFtnInfo.eNum;
     222          34 :     sal_uInt16 nFtnNo = 0, nEndNo = 0;
     223          68 :     for( size_t nPos = 0; nPos < size(); ++nPos )
     224             :     {
     225          34 :         pTxtFtn = (*this)[ nPos ];
     226          34 :         const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
     227          34 :         if( rFtn.GetNumStr().isEmpty() )
     228             :         {
     229          32 :             sal_uInt16 nSectNo = aNumArr.ChkNumber( *pTxtFtn );
     230          32 :             if( !nSectNo && ( rFtn.IsEndNote() || !bEndNoteOnly ))
     231          22 :                 nSectNo = rFtn.IsEndNote()
     232             :                                 ? rEndInfo.nFtnOffset + (++nEndNo)
     233          22 :                                 : rFtnInfo.nFtnOffset + (++nFtnNo);
     234             : 
     235          32 :             if( nSectNo )
     236             :             {
     237          22 :                 pTxtFtn->SetNumber( nSectNo, rFtn.GetNumStr() );
     238             :             }
     239             :         }
     240             :     }
     241             : 
     242          34 :     if( pTmpRoot && FTNNUM_PAGE == rFtnInfo.eNum )
     243          34 :         std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::UpdateFtnNums));
     244             : }
     245             : 
     246         370 : SwTxtFtn* SwFtnIdxs::SeekEntry( const SwNodeIndex& rPos, size_t* pFndPos ) const
     247             : {
     248         370 :     sal_uLong nIdx = rPos.GetIndex();
     249             : 
     250         370 :     size_t nO = size();
     251         370 :     size_t nU = 0;
     252         370 :     if( nO > 0 )
     253             :     {
     254         370 :         nO--;
     255         898 :         while( nU <= nO )
     256             :         {
     257         450 :             const size_t nM = nU + ( nO - nU ) / 2;
     258         450 :             sal_uLong nNdIdx = _SwTxtFtn_GetIndex( (*this)[ nM ] );
     259         450 :             if( nNdIdx == nIdx )
     260             :             {
     261         154 :                 if( pFndPos )
     262         154 :                     *pFndPos = nM;
     263         154 :                 return (*this)[ nM ];
     264             :             }
     265         296 :             else if( nNdIdx < nIdx )
     266         124 :                 nU = nM + 1;
     267         172 :             else if( nM == 0 )
     268             :             {
     269         138 :                 if( pFndPos )
     270         138 :                     *pFndPos = nU;
     271         138 :                 return 0;
     272             :             }
     273             :             else
     274          34 :                 nO = nM - 1;
     275             :         }
     276             :     }
     277          78 :     if( pFndPos )
     278          78 :         *pFndPos = nU;
     279          78 :     return 0;
     280             : }
     281             : 
     282         696 : const SwSectionNode* SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr(
     283             :                 const SwTxtFtn& rTxtFtn )
     284             : {
     285         696 :     sal_uInt16 nWh = static_cast<sal_uInt16>( rTxtFtn.GetFtn().IsEndNote() ?
     286         696 :                         RES_END_AT_TXTEND : RES_FTN_AT_TXTEND );
     287             :     sal_uInt16 nVal;
     288         696 :     const SwSectionNode* pNd = rTxtFtn.GetTxtNode().FindSectionNode();
     289        1720 :     while( pNd && FTNEND_ATTXTEND_OWNNUMSEQ != ( nVal =
     290         164 :             ((const SwFmtFtnEndAtTxtEnd&)pNd->GetSection().GetFmt()->
     291        1188 :             GetFmtAttr( nWh, true )).GetValue() ) &&
     292             :             FTNEND_ATTXTEND_OWNNUMANDFMT != nVal )
     293         164 :         pNd = pNd->StartOfSectionNode()->FindSectionNode();
     294             : 
     295         696 :     return pNd;
     296             : }
     297             : 
     298           0 : sal_uInt16 SwUpdFtnEndNtAtEnd::GetNumber( const SwTxtFtn& rTxtFtn,
     299             :                                     const SwSectionNode& rNd )
     300             : {
     301           0 :     sal_uInt16 nRet = 0, nWh;
     302             :     std::vector<const SwSectionNode*>* pArr;
     303             :     std::vector<sal_uInt16> *pNum;
     304           0 :     if( rTxtFtn.GetFtn().IsEndNote() )
     305             :     {
     306           0 :         pArr = &aEndSects;
     307           0 :         pNum = &aEndNums;
     308           0 :         nWh = RES_END_AT_TXTEND;
     309             :     }
     310             :     else
     311             :     {
     312           0 :         pArr = &aFtnSects;
     313           0 :         pNum = &aFtnNums;
     314           0 :         nWh = RES_FTN_AT_TXTEND;
     315             :     }
     316             : 
     317           0 :     for( size_t n = pArr->size(); n; )
     318           0 :         if( (*pArr)[ --n ] == &rNd )
     319             :         {
     320           0 :             nRet = ++((*pNum)[ n ]);
     321           0 :             break;
     322             :         }
     323             : 
     324           0 :     if( !nRet )
     325             :     {
     326           0 :         pArr->push_back( &rNd );
     327           0 :         nRet = ((SwFmtFtnEndAtTxtEnd&)rNd.GetSection().GetFmt()->
     328           0 :                                 GetFmtAttr( nWh )).GetOffset();
     329           0 :         ++nRet;
     330           0 :         pNum->push_back( nRet );
     331             :     }
     332           0 :     return nRet;
     333             : }
     334             : 
     335         248 : sal_uInt16 SwUpdFtnEndNtAtEnd::ChkNumber( const SwTxtFtn& rTxtFtn )
     336             : {
     337         248 :     const SwSectionNode* pSectNd = FindSectNdWithEndAttr( rTxtFtn );
     338         248 :     return pSectNd ? GetNumber( rTxtFtn, *pSectNd ) : 0;
     339         270 : }
     340             : 
     341             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10