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