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 749 : bool CompareSwFootnoteIdxs::operator()(SwTextFootnote* const& lhs, SwTextFootnote* const& rhs) const
33 : {
34 749 : sal_uLong nIdxLHS = _SwTextFootnote_GetIndex( lhs );
35 749 : sal_uLong nIdxRHS = _SwTextFootnote_GetIndex( rhs );
36 749 : return ( nIdxLHS == nIdxRHS && lhs->GetStart() < rhs->GetStart() ) || nIdxLHS < nIdxRHS;
37 : }
38 :
39 2113 : void SwFootnoteIdxs::UpdateFootnote( const SwNodeIndex& rStt )
40 : {
41 2113 : if( empty() )
42 3923 : return;
43 :
44 : // Get the NodesArray using the first foot note's StartIndex
45 184 : SwDoc* pDoc = rStt.GetNode().GetDoc();
46 184 : if( pDoc->IsInReading() )
47 65 : return ;
48 : SwTextFootnote* pTextFootnote;
49 :
50 119 : const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
51 119 : const SwFootnoteInfo& rFootnoteInfo = pDoc->GetFootnoteInfo();
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 119 : if( FTNNUM_CHAPTER == rFootnoteInfo.eNum )
56 : {
57 3 : const SwOutlineNodes& rOutlNds = pDoc->GetNodes().GetOutLineNds();
58 3 : const SwNode* pCapStt = &pDoc->GetNodes().GetEndOfExtras();
59 3 : sal_uLong nCapEnd = pDoc->GetNodes().GetEndOfContent().GetIndex();
60 3 : 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 ]->GetTextNode()->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 ]->GetTextNode()->GetAttrOutlineLevel() == 1 )
73 : {
74 0 : nCapEnd = rOutlNds[ n ]->GetIndex(); // End of the found Chapter
75 0 : break;
76 : }
77 : }
78 :
79 3 : size_t nPos = 0;
80 3 : size_t nFootnoteNo = 1;
81 3 : 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 ]->GetTextNode()) )
86 : ;
87 0 : ++nPos;
88 : }
89 :
90 3 : if( nPos == size() ) // nothing found
91 0 : return;
92 :
93 3 : if( rOutlNds.empty() )
94 3 : nFootnoteNo = nPos+1;
95 :
96 6 : for( ; nPos < size(); ++nPos )
97 : {
98 3 : pTextFootnote = (*this)[ nPos ];
99 3 : if( pTextFootnote->GetTextNode().GetIndex() >= nCapEnd )
100 0 : break;
101 :
102 3 : const SwFormatFootnote &rFootnote = pTextFootnote->GetFootnote();
103 6 : if( rFootnote.GetNumStr().isEmpty() && !rFootnote.IsEndNote() &&
104 3 : !SwUpdFootnoteEndNtAtEnd::FindSectNdWithEndAttr( *pTextFootnote ))
105 : {
106 3 : pTextFootnote->SetNumber( rFootnoteInfo.nFootnoteOffset + nFootnoteNo++, rFootnote.GetNumStr() );
107 : }
108 : }
109 : }
110 :
111 119 : SwUpdFootnoteEndNtAtEnd aNumArr;
112 :
113 : // unless we have per-document numbering, only look at endnotes here
114 119 : const bool bEndNoteOnly = FTNNUM_DOC != rFootnoteInfo.eNum;
115 :
116 : size_t nPos;
117 119 : size_t nFootnoteNo = 1;
118 119 : size_t nEndNo = 1;
119 119 : sal_uLong nUpdNdIdx = rStt.GetIndex();
120 137 : for( nPos = 0; nPos < size(); ++nPos )
121 : {
122 137 : pTextFootnote = (*this)[ nPos ];
123 137 : if( nUpdNdIdx <= pTextFootnote->GetTextNode().GetIndex() )
124 119 : break;
125 :
126 18 : const SwFormatFootnote &rFootnote = pTextFootnote->GetFootnote();
127 18 : if( rFootnote.GetNumStr().isEmpty() )
128 : {
129 18 : if( !aNumArr.ChkNumber( *pTextFootnote ) )
130 : {
131 18 : if( pTextFootnote->GetFootnote().IsEndNote() )
132 9 : nEndNo++;
133 : else
134 9 : nFootnoteNo++;
135 : }
136 : }
137 : }
138 :
139 : // Set the array number for all footnotes starting from nPos
140 295 : for( ; nPos < size(); ++nPos )
141 : {
142 176 : pTextFootnote = (*this)[ nPos ];
143 176 : const SwFormatFootnote &rFootnote = pTextFootnote->GetFootnote();
144 176 : if( rFootnote.GetNumStr().isEmpty() )
145 : {
146 94 : sal_uInt16 nSectNo = aNumArr.ChkNumber( *pTextFootnote );
147 94 : if( !nSectNo && ( rFootnote.IsEndNote() || !bEndNoteOnly ))
148 87 : nSectNo = rFootnote.IsEndNote()
149 : ? rEndInfo.nFootnoteOffset + nEndNo++
150 87 : : rFootnoteInfo.nFootnoteOffset + nFootnoteNo++;
151 :
152 94 : if( nSectNo )
153 : {
154 91 : pTextFootnote->SetNumber( nSectNo, rFootnote.GetNumStr() );
155 : }
156 : }
157 119 : }
158 : }
159 :
160 62 : void SwFootnoteIdxs::UpdateAllFootnote()
161 : {
162 62 : if( empty() )
163 107 : return;
164 :
165 : // Get the NodesArray via the StartIndex of the first Footnote
166 17 : SwDoc* pDoc = const_cast<SwDoc*>((*this)[ 0 ]->GetTextNode().GetDoc());
167 : SwTextFootnote* pTextFootnote;
168 17 : const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
169 17 : const SwFootnoteInfo& rFootnoteInfo = pDoc->GetFootnoteInfo();
170 :
171 17 : SwUpdFootnoteEndNtAtEnd aNumArr;
172 :
173 17 : SwRootFrm* pTmpRoot = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
174 34 : 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 17 : if( FTNNUM_CHAPTER == rFootnoteInfo.eNum )
178 : {
179 5 : const SwOutlineNodes& rOutlNds = pDoc->GetNodes().GetOutLineNds();
180 5 : sal_uInt16 nNo = 1; // Number for the Footnotes
181 5 : size_t nFootnoteIdx = 0; // Index into theFootnoteIdx array
182 5 : for( size_t n = 0; n < rOutlNds.size(); ++n )
183 : {
184 0 : if ( rOutlNds[ n ]->GetTextNode()->GetAttrOutlineLevel() == 1 )
185 : {
186 0 : sal_uLong nCapStt = rOutlNds[ n ]->GetIndex(); // Start of a new chapter
187 0 : for( ; nFootnoteIdx < size(); ++nFootnoteIdx )
188 : {
189 0 : pTextFootnote = (*this)[ nFootnoteIdx ];
190 0 : if( pTextFootnote->GetTextNode().GetIndex() >= nCapStt )
191 0 : break;
192 :
193 : // Endnotes are per-document only
194 0 : const SwFormatFootnote &rFootnote = pTextFootnote->GetFootnote();
195 0 : if( !rFootnote.IsEndNote() && rFootnote.GetNumStr().isEmpty() &&
196 0 : !SwUpdFootnoteEndNtAtEnd::FindSectNdWithEndAttr( *pTextFootnote ))
197 : {
198 0 : pTextFootnote->SetNumber( rFootnoteInfo.nFootnoteOffset + nNo++, rFootnote.GetNumStr() );
199 : }
200 : }
201 0 : if( nFootnoteIdx >= size() )
202 0 : break; // ok, everything is updated
203 0 : nNo = 1;
204 : }
205 : }
206 :
207 10 : for( nNo = 1; nFootnoteIdx < size(); ++nFootnoteIdx )
208 : {
209 : // Endnotes are per-document
210 5 : pTextFootnote = (*this)[ nFootnoteIdx ];
211 5 : const SwFormatFootnote &rFootnote = pTextFootnote->GetFootnote();
212 10 : if( !rFootnote.IsEndNote() && rFootnote.GetNumStr().isEmpty() &&
213 5 : !SwUpdFootnoteEndNtAtEnd::FindSectNdWithEndAttr( *pTextFootnote ))
214 : {
215 5 : pTextFootnote->SetNumber( rFootnoteInfo.nFootnoteOffset + nNo++, rFootnote.GetNumStr() );
216 : }
217 : }
218 : }
219 :
220 : // We use bool here, so that we also iterate through the Endnotes with a chapter setting.
221 17 : const bool bEndNoteOnly = FTNNUM_DOC != rFootnoteInfo.eNum;
222 17 : sal_uInt16 nFootnoteNo = 0, nEndNo = 0;
223 34 : for( size_t nPos = 0; nPos < size(); ++nPos )
224 : {
225 17 : pTextFootnote = (*this)[ nPos ];
226 17 : const SwFormatFootnote &rFootnote = pTextFootnote->GetFootnote();
227 17 : if( rFootnote.GetNumStr().isEmpty() )
228 : {
229 16 : sal_uInt16 nSectNo = aNumArr.ChkNumber( *pTextFootnote );
230 16 : if( !nSectNo && ( rFootnote.IsEndNote() || !bEndNoteOnly ))
231 11 : nSectNo = rFootnote.IsEndNote()
232 : ? rEndInfo.nFootnoteOffset + (++nEndNo)
233 11 : : rFootnoteInfo.nFootnoteOffset + (++nFootnoteNo);
234 :
235 16 : if( nSectNo )
236 : {
237 11 : pTextFootnote->SetNumber( nSectNo, rFootnote.GetNumStr() );
238 : }
239 : }
240 : }
241 :
242 17 : if( pTmpRoot && FTNNUM_PAGE == rFootnoteInfo.eNum )
243 17 : std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::UpdateFootnoteNums));
244 : }
245 :
246 144 : SwTextFootnote* SwFootnoteIdxs::SeekEntry( const SwNodeIndex& rPos, size_t* pFndPos ) const
247 : {
248 144 : sal_uLong nIdx = rPos.GetIndex();
249 :
250 144 : size_t nO = size();
251 144 : size_t nU = 0;
252 144 : if( nO > 0 )
253 : {
254 144 : nO--;
255 344 : while( nU <= nO )
256 : {
257 184 : const size_t nM = nU + ( nO - nU ) / 2;
258 184 : sal_uLong nNdIdx = _SwTextFootnote_GetIndex( (*this)[ nM ] );
259 184 : if( nNdIdx == nIdx )
260 : {
261 78 : if( pFndPos )
262 78 : *pFndPos = nM;
263 78 : return (*this)[ nM ];
264 : }
265 106 : else if( nNdIdx < nIdx )
266 39 : nU = nM + 1;
267 67 : else if( nM == 0 )
268 : {
269 50 : if( pFndPos )
270 50 : *pFndPos = nU;
271 50 : return 0;
272 : }
273 : else
274 17 : nO = nM - 1;
275 : }
276 : }
277 16 : if( pFndPos )
278 16 : *pFndPos = nU;
279 16 : return 0;
280 : }
281 :
282 391 : const SwSectionNode* SwUpdFootnoteEndNtAtEnd::FindSectNdWithEndAttr(
283 : const SwTextFootnote& rTextFootnote )
284 : {
285 391 : sal_uInt16 nWh = static_cast<sal_uInt16>( rTextFootnote.GetFootnote().IsEndNote() ?
286 391 : RES_END_AT_TXTEND : RES_FTN_AT_TXTEND );
287 : sal_uInt16 nVal;
288 391 : const SwSectionNode* pNd = rTextFootnote.GetTextNode().FindSectionNode();
289 965 : while( pNd && FTNEND_ATTXTEND_OWNNUMSEQ != ( nVal =
290 101 : static_cast<const SwFormatFootnoteEndAtTextEnd&>(pNd->GetSection().GetFormat()->
291 656 : GetFormatAttr( nWh, true )).GetValue() ) &&
292 : FTNEND_ATTXTEND_OWNNUMANDFMT != nVal )
293 82 : pNd = pNd->StartOfSectionNode()->FindSectionNode();
294 :
295 391 : return pNd;
296 : }
297 :
298 4 : sal_uInt16 SwUpdFootnoteEndNtAtEnd::GetNumber( const SwTextFootnote& rTextFootnote,
299 : const SwSectionNode& rNd )
300 : {
301 4 : sal_uInt16 nRet = 0, nWh;
302 : std::vector<const SwSectionNode*>* pArr;
303 : std::vector<sal_uInt16> *pNum;
304 4 : if( rTextFootnote.GetFootnote().IsEndNote() )
305 : {
306 2 : pArr = &aEndSects;
307 2 : pNum = &aEndNums;
308 2 : nWh = RES_END_AT_TXTEND;
309 : }
310 : else
311 : {
312 2 : pArr = &aFootnoteSects;
313 2 : pNum = &aFootnoteNums;
314 2 : nWh = RES_FTN_AT_TXTEND;
315 : }
316 :
317 8 : 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 4 : if( !nRet )
325 : {
326 4 : pArr->push_back( &rNd );
327 4 : nRet = static_cast<const SwFormatFootnoteEndAtTextEnd&>(rNd.GetSection().GetFormat()->
328 8 : GetFormatAttr( nWh )).GetOffset();
329 4 : ++nRet;
330 4 : pNum->push_back( nRet );
331 : }
332 4 : return nRet;
333 : }
334 :
335 128 : sal_uInt16 SwUpdFootnoteEndNtAtEnd::ChkNumber( const SwTextFootnote& rTextFootnote )
336 : {
337 128 : const SwSectionNode* pSectNd = FindSectNdWithEndAttr( rTextFootnote );
338 128 : return pSectNd ? GetNumber( rTextFootnote, *pSectNd ) : 0;
339 177 : }
340 :
341 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|