merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / doc / ftnidx.cxx
blobb0a8cb67af78e9f5d2ae9e2d34fba7c02407685a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ftnidx.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <txtftn.hxx>
36 #include <fmtftn.hxx>
37 #include <ftninfo.hxx>
38 #include <doc.hxx>
39 #include <ftnidx.hxx>
40 #include <ndtxt.hxx>
41 #include <ndindex.hxx>
42 #include <section.hxx>
43 #include <fmtftntx.hxx>
44 #include <rootfrm.hxx>
47 _SV_IMPL_SORTAR_ALG( _SwFtnIdxs, SwTxtFtnPtr )
48 BOOL _SwFtnIdxs::Seek_Entry( const SwTxtFtnPtr rSrch, USHORT* pFndPos ) const
50 ULONG nIdx = _SwTxtFtn_GetIndex( rSrch );
51 xub_StrLen nCntIdx = *rSrch->GetStart();
53 USHORT nO = Count(), nM, nU = 0;
54 if( nO > 0 )
56 nO--;
57 while( nU <= nO )
59 nM = nU + ( nO - nU ) / 2;
60 ULONG nFndIdx = _SwTxtFtn_GetIndex( (*this)[ nM ] );
61 if( nFndIdx == nIdx && *(*this)[ nM ]->GetStart() == nCntIdx )
63 if( pFndPos )
64 *pFndPos = nM;
65 return TRUE;
67 else if( nFndIdx < nIdx ||
68 (nFndIdx == nIdx && *(*this)[ nM ]->GetStart() < nCntIdx ))
69 nU = nM + 1;
70 else if( nM == 0 )
72 if( pFndPos )
73 *pFndPos = nU;
74 return FALSE;
76 else
77 nO = nM - 1;
80 if( pFndPos )
81 *pFndPos = nU;
82 return FALSE;
86 void SwFtnIdxs::UpdateFtn( const SwNodeIndex& rStt )
88 if( !Count() )
89 return;
91 // besorge erstmal das Nodes-Array ueber den StartIndex der ersten Fussnote
92 SwDoc* pDoc = rStt.GetNode().GetDoc();
93 if( pDoc->IsInReading() )
94 return ;
95 SwTxtFtn* pTxtFtn;
97 const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
98 const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();
100 //Fuer normale Fussnoten werden Chapter- und Dokumentweise Nummerierung
101 //getrennt behandelt. Fuer Endnoten gibt es nur die Dokumentweise
102 //Nummerierung.
103 if( FTNNUM_CHAPTER == rFtnInfo.eNum )
105 const SwOutlineNodes& rOutlNds = pDoc->GetNodes().GetOutLineNds();
106 const SwNode* pCapStt = &pDoc->GetNodes().GetEndOfExtras();
107 ULONG nCapEnd = pDoc->GetNodes().GetEndOfContent().GetIndex();
108 if( rOutlNds.Count() )
110 // suche den Start des Kapitels, in den rStt steht.
111 USHORT n;
113 for( n = 0; n < rOutlNds.Count(); ++n )
114 if( rOutlNds[ n ]->GetIndex() > rStt.GetIndex() )
115 break; // gefunden
116 //else if( !rOutlNds[ n ]->GetTxtNode()->GetTxtColl()->GetOutlineLevel() ) //#outline level,zhaojianwei
117 else if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 ) //<-end,zhaojianwei
118 pCapStt = rOutlNds[ n ]; // Start eines neuen Kapitels
119 // dann suche jetzt noch das Ende vom Bereich
120 for( ; n < rOutlNds.Count(); ++n )
121 //if( !rOutlNds[ n ]->GetTxtNode()->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
122 if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )//<-end,zhaojianwei
124 nCapEnd = rOutlNds[ n ]->GetIndex(); // Ende des gefundenen Kapitels
125 break;
129 USHORT nPos, nFtnNo = 1;
130 if( SeekEntry( *pCapStt, &nPos ) && nPos )
132 // gehe nach vorne bis der Index nicht mehr gleich ist
133 const SwNode* pCmpNd = &rStt.GetNode();
134 while( nPos && pCmpNd == &((*this)[ --nPos ]->GetTxtNode()) )
136 ++nPos;
139 if( nPos == Count() ) // nichts gefunden
140 return;
142 if( !rOutlNds.Count() )
143 nFtnNo = nPos+1;
145 for( ; nPos < Count(); ++nPos )
147 pTxtFtn = (*this)[ nPos ];
148 if( pTxtFtn->GetTxtNode().GetIndex() >= nCapEnd )
149 break;
151 const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
152 if( !rFtn.GetNumStr().Len() && !rFtn.IsEndNote() &&
153 !SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
154 pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nFtnNo++,
155 &rFtn.GetNumStr() );
159 SwUpdFtnEndNtAtEnd aNumArr;
161 // BOOL, damit hier auch bei Chapter-Einstellung die Endnoten
162 // durchlaufen.
163 const BOOL bEndNoteOnly = FTNNUM_DOC != rFtnInfo.eNum;
165 USHORT nPos, nFtnNo = 1, nEndNo = 1;
166 ULONG nUpdNdIdx = rStt.GetIndex();
167 for( nPos = 0; nPos < Count(); ++nPos )
169 pTxtFtn = (*this)[ nPos ];
170 if( nUpdNdIdx <= pTxtFtn->GetTxtNode().GetIndex() )
171 break;
173 const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
174 if( !rFtn.GetNumStr().Len() )
176 if( !aNumArr.ChkNumber( *pTxtFtn ) )
178 if( pTxtFtn->GetFtn().IsEndNote() )
179 nEndNo++;
180 else
181 nFtnNo++;
186 // ab nPos bei allen FootNotes die Array-Nummer setzen
187 for( ; nPos < Count(); ++nPos )
189 pTxtFtn = (*this)[ nPos ];
190 const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
191 if( !rFtn.GetNumStr().Len() )
193 USHORT nSectNo = aNumArr.ChkNumber( *pTxtFtn );
194 if( !nSectNo && ( rFtn.IsEndNote() || !bEndNoteOnly ))
195 nSectNo = rFtn.IsEndNote()
196 ? rEndInfo.nFtnOffset + nEndNo++
197 : rFtnInfo.nFtnOffset + nFtnNo++;
199 if( nSectNo )
201 if( rFtn.IsEndNote() )
202 pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
203 else
204 pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
208 // Pageweise wird vom MA erfuellt !!
212 void SwFtnIdxs::UpdateAllFtn()
214 if( !Count() )
215 return;
217 // besorge erstmal das Nodes-Array ueber den StartIndex der
218 // ersten Fussnote
219 SwDoc* pDoc = (SwDoc*) (*this)[ 0 ]->GetTxtNode().GetDoc();
220 SwTxtFtn* pTxtFtn;
221 const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
222 const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();
224 SwUpdFtnEndNtAtEnd aNumArr;
226 //Fuer normale Fussnoten werden Chapter- und Dokumentweise Nummerierung
227 //getrennt behandelt. Fuer Endnoten gibt es nur die Dokumentweise
228 //Nummerierung.
229 if( FTNNUM_CHAPTER == rFtnInfo.eNum )
231 const SwOutlineNodes& rOutlNds = pDoc->GetNodes().GetOutLineNds();
232 USHORT nNo = 1, // Nummer fuer die Fussnoten
233 nFtnIdx = 0; // Index in das FtnIdx-Array
234 for( USHORT n = 0; n < rOutlNds.Count(); ++n )
236 //if( !rOutlNds[ n ]->GetTxtNode()->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
237 if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )//<-end,zhaojianwei
239 ULONG nCapStt = rOutlNds[ n ]->GetIndex(); // Start eines neuen Kapitels
240 for( ; nFtnIdx < Count(); ++nFtnIdx )
242 pTxtFtn = (*this)[ nFtnIdx ];
243 if( pTxtFtn->GetTxtNode().GetIndex() >= nCapStt )
244 break;
246 // Endnoten nur Dokumentweise
247 const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
248 if( !rFtn.IsEndNote() && !rFtn.GetNumStr().Len() &&
249 !SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
250 pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nNo++,
251 &rFtn.GetNumStr() );
253 if( nFtnIdx >= Count() )
254 break; // ok alles geupdatet
255 nNo = 1;
259 for( nNo = 1; nFtnIdx < Count(); ++nFtnIdx )
261 //Endnoten nur Dokumentweise
262 pTxtFtn = (*this)[ nFtnIdx ];
263 const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
264 if( !rFtn.IsEndNote() && !rFtn.GetNumStr().Len() &&
265 !SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
266 pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nNo++,
267 &rFtn.GetNumStr() );
272 // BOOL, damit hier auch bei Chapter-Einstellung die Endnoten
273 // durchlaufen.
274 const BOOL bEndNoteOnly = FTNNUM_DOC != rFtnInfo.eNum;
275 USHORT nFtnNo = 0, nEndNo = 0;
276 for( USHORT nPos = 0; nPos < Count(); ++nPos )
278 pTxtFtn = (*this)[ nPos ];
279 const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
280 if( !rFtn.GetNumStr().Len() )
282 USHORT nSectNo = aNumArr.ChkNumber( *pTxtFtn );
283 if( !nSectNo && ( rFtn.IsEndNote() || !bEndNoteOnly ))
284 nSectNo = rFtn.IsEndNote()
285 ? rEndInfo.nFtnOffset + (++nEndNo)
286 : rFtnInfo.nFtnOffset + (++nFtnNo);
288 if( nSectNo )
290 if( rFtn.IsEndNote() )
291 pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
292 else
293 pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
298 if( pDoc->GetRootFrm() && FTNNUM_PAGE == rFtnInfo.eNum )
299 pDoc->GetRootFrm()->UpdateFtnNums();
302 SwTxtFtn* SwFtnIdxs::SeekEntry( const SwNodeIndex& rPos, USHORT* pFndPos ) const
304 ULONG nIdx = rPos.GetIndex();
306 USHORT nO = Count(), nM, nU = 0;
307 if( nO > 0 )
309 nO--;
310 while( nU <= nO )
312 nM = nU + ( nO - nU ) / 2;
313 ULONG nNdIdx = _SwTxtFtn_GetIndex( (*this)[ nM ] );
314 if( nNdIdx == nIdx )
316 if( pFndPos )
317 *pFndPos = nM;
318 return (*this)[ nM ];
320 else if( nNdIdx < nIdx )
321 nU = nM + 1;
322 else if( nM == 0 )
324 if( pFndPos )
325 *pFndPos = nU;
326 return 0;
328 else
329 nO = nM - 1;
332 if( pFndPos )
333 *pFndPos = nU;
334 return 0;
337 /* \f */
339 const SwSectionNode* SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr(
340 const SwTxtFtn& rTxtFtn )
342 USHORT nWh = static_cast<USHORT>( rTxtFtn.GetFtn().IsEndNote() ?
343 RES_END_AT_TXTEND : RES_FTN_AT_TXTEND );
344 USHORT nVal;
345 const SwSectionNode* pNd = rTxtFtn.GetTxtNode().FindSectionNode();
346 while( pNd && FTNEND_ATTXTEND_OWNNUMSEQ != ( nVal =
347 ((const SwFmtFtnAtTxtEnd&)pNd->GetSection().GetFmt()->
348 GetFmtAttr( nWh, TRUE )).GetValue() ) &&
349 FTNEND_ATTXTEND_OWNNUMANDFMT != nVal )
350 pNd = pNd->StartOfSectionNode()->FindSectionNode();
352 return pNd;
355 USHORT SwUpdFtnEndNtAtEnd::GetNumber( const SwTxtFtn& rTxtFtn,
356 const SwSectionNode& rNd )
358 USHORT nRet = 0, nWh;
359 SvPtrarr* pArr;
360 SvUShorts* pNum;
361 if( rTxtFtn.GetFtn().IsEndNote() )
363 pArr = &aEndSects;
364 pNum = &aEndNums;
365 nWh = RES_END_AT_TXTEND;
367 else
369 pArr = &aFtnSects;
370 pNum = &aFtnNums;
371 nWh = RES_FTN_AT_TXTEND;
373 void* pNd = (void*)&rNd;
375 for( USHORT n = pArr->Count(); n; )
376 if( pArr->GetObject( --n ) == pNd )
378 nRet = ++pNum->GetObject( n );
379 break;
382 if( !nRet )
384 pArr->Insert( pNd, pArr->Count() );
385 nRet = ((SwFmtFtnEndAtTxtEnd&)rNd.GetSection().GetFmt()->
386 GetFmtAttr( nWh )).GetOffset();
387 ++nRet;
388 pNum->Insert( nRet, pNum->Count() );
390 return nRet;
393 USHORT SwUpdFtnEndNtAtEnd::ChkNumber( const SwTxtFtn& rTxtFtn )
395 const SwSectionNode* pSectNd = FindSectNdWithEndAttr( rTxtFtn );
396 return pSectNd ? GetNumber( rTxtFtn, *pSectNd ) : 0;