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