xref: /aoo41x/main/sw/source/core/doc/ftnidx.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 
32 #include <txtftn.hxx>
33 #include <fmtftn.hxx>
34 #include <ftninfo.hxx>
35 #include <doc.hxx>
36 #include <ftnidx.hxx>
37 #include <ndtxt.hxx>
38 #include <ndindex.hxx>
39 #include <section.hxx>
40 #include <fmtftntx.hxx>
41 #include <rootfrm.hxx>
42 
43 
44 _SV_IMPL_SORTAR_ALG( _SwFtnIdxs, SwTxtFtnPtr )
45 sal_Bool _SwFtnIdxs::Seek_Entry( const SwTxtFtnPtr rSrch, sal_uInt16* pFndPos ) const
46 {
47 	sal_uLong nIdx = _SwTxtFtn_GetIndex( rSrch );
48 	xub_StrLen nCntIdx = *rSrch->GetStart();
49 
50 	sal_uInt16 nO = Count(), nM, nU = 0;
51 	if( nO > 0 )
52 	{
53 		nO--;
54 		while( nU <= nO )
55 		{
56 			nM = nU + ( nO - nU ) / 2;
57 			sal_uLong nFndIdx = _SwTxtFtn_GetIndex( (*this)[ nM ] );
58 			if( nFndIdx == nIdx && *(*this)[ nM ]->GetStart() == nCntIdx )
59 			{
60 				if( pFndPos )
61 					*pFndPos = nM;
62 				return sal_True;
63 			}
64 			else if( nFndIdx < nIdx ||
65 				(nFndIdx == nIdx && *(*this)[ nM ]->GetStart() < nCntIdx ))
66 				nU = nM + 1;
67 			else if( nM == 0 )
68 			{
69 				if( pFndPos )
70 					*pFndPos = nU;
71 				return sal_False;
72 			}
73 			else
74 				nO = nM - 1;
75 		}
76 	}
77 	if( pFndPos )
78 		*pFndPos = nU;
79 	return sal_False;
80 }
81 
82 
83 void SwFtnIdxs::UpdateFtn( const SwNodeIndex& rStt )
84 {
85 	if( !Count() )
86 		return;
87 
88 	// besorge erstmal das Nodes-Array ueber den StartIndex der ersten Fussnote
89 	SwDoc* pDoc = rStt.GetNode().GetDoc();
90 	if( pDoc->IsInReading() )
91 		return ;
92 	SwTxtFtn* pTxtFtn;
93 
94 	const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
95 	const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();
96 
97 	//Fuer normale Fussnoten werden Chapter- und Dokumentweise Nummerierung
98 	//getrennt behandelt. Fuer Endnoten gibt es nur die Dokumentweise
99 	//Nummerierung.
100 	if( FTNNUM_CHAPTER == rFtnInfo.eNum )
101 	{
102 		const SwOutlineNodes& rOutlNds = pDoc->GetNodes().GetOutLineNds();
103 		const SwNode* pCapStt = &pDoc->GetNodes().GetEndOfExtras();
104 		sal_uLong nCapEnd = pDoc->GetNodes().GetEndOfContent().GetIndex();
105 		if( rOutlNds.Count() )
106 		{
107 			// suche den Start des Kapitels, in den rStt steht.
108 			sal_uInt16 n;
109 
110 			for( n = 0; n < rOutlNds.Count(); ++n )
111 				if( rOutlNds[ n ]->GetIndex() > rStt.GetIndex() )
112 					break;		// gefunden
113 				//else if( !rOutlNds[ n ]->GetTxtNode()->GetTxtColl()->GetOutlineLevel() )	//#outline level,zhaojianwei
114                 else if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )   //<-end,zhaojianwei
115 					pCapStt = rOutlNds[ n ];	// Start eines neuen Kapitels
116 			// dann suche jetzt noch das Ende vom Bereich
117 			for( ; n < rOutlNds.Count(); ++n )
118 				//if( !rOutlNds[ n ]->GetTxtNode()->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
119                 if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )//<-end,zhaojianwei
120 				{
121 					nCapEnd = rOutlNds[ n ]->GetIndex();	// Ende des gefundenen Kapitels
122 					break;
123 				}
124 		}
125 
126 		sal_uInt16 nPos, nFtnNo = 1;
127 		if( SeekEntry( *pCapStt, &nPos ) && nPos )
128 		{
129 			// gehe nach vorne bis der Index nicht mehr gleich ist
130 			const SwNode* pCmpNd = &rStt.GetNode();
131 			while( nPos && pCmpNd == &((*this)[ --nPos ]->GetTxtNode()) )
132 				;
133 			++nPos;
134 		}
135 
136 		if( nPos == Count() )		// nichts gefunden
137 			return;
138 
139 		if( !rOutlNds.Count() )
140 			nFtnNo = nPos+1;
141 
142 		for( ; nPos < Count(); ++nPos )
143 		{
144 			pTxtFtn = (*this)[ nPos ];
145 			if( pTxtFtn->GetTxtNode().GetIndex() >= nCapEnd )
146 				break;
147 
148 			const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
149 			if( !rFtn.GetNumStr().Len() && !rFtn.IsEndNote() &&
150 				!SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
151 				pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nFtnNo++,
152 									&rFtn.GetNumStr() );
153 		}
154 	}
155 
156 	SwUpdFtnEndNtAtEnd aNumArr;
157 
158 	// sal_Bool, damit hier auch bei Chapter-Einstellung die Endnoten
159 	// durchlaufen.
160 	const sal_Bool bEndNoteOnly = FTNNUM_DOC != rFtnInfo.eNum;
161 
162 	sal_uInt16 nPos, nFtnNo = 1, nEndNo = 1;
163 	sal_uLong nUpdNdIdx = rStt.GetIndex();
164 	for( nPos = 0; nPos < Count(); ++nPos )
165 	{
166 		pTxtFtn = (*this)[ nPos ];
167 		if( nUpdNdIdx <= pTxtFtn->GetTxtNode().GetIndex() )
168 			break;
169 
170 		const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
171 		if( !rFtn.GetNumStr().Len() )
172 		{
173 			if( !aNumArr.ChkNumber( *pTxtFtn ) )
174 			{
175 				if( pTxtFtn->GetFtn().IsEndNote() )
176 					nEndNo++;
177 				else
178 					nFtnNo++;
179 			}
180 		}
181 	}
182 
183 	// ab nPos bei allen FootNotes die Array-Nummer setzen
184 	for( ; nPos < Count(); ++nPos )
185 	{
186 		pTxtFtn = (*this)[ nPos ];
187 		const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
188 		if( !rFtn.GetNumStr().Len() )
189 		{
190 			sal_uInt16 nSectNo = aNumArr.ChkNumber( *pTxtFtn );
191 			if( !nSectNo && ( rFtn.IsEndNote() || !bEndNoteOnly ))
192 				nSectNo = rFtn.IsEndNote()
193 							? rEndInfo.nFtnOffset + nEndNo++
194 							: rFtnInfo.nFtnOffset + nFtnNo++;
195 
196 			if( nSectNo )
197 			{
198 				if( rFtn.IsEndNote() )
199 					pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
200 				else
201 					pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
202 			}
203 		}
204 	}
205 	// Pageweise wird vom MA erfuellt !!
206 }
207 
208 
209 void SwFtnIdxs::UpdateAllFtn()
210 {
211 	if( !Count() )
212 		return;
213 
214 	// besorge erstmal das Nodes-Array ueber den StartIndex der
215 	// ersten Fussnote
216 	SwDoc* pDoc = (SwDoc*) (*this)[ 0 ]->GetTxtNode().GetDoc();
217 	SwTxtFtn* pTxtFtn;
218 	const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
219 	const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();
220 
221 	SwUpdFtnEndNtAtEnd aNumArr;
222 
223 	SwRootFrm* pTmpRoot = pDoc->GetCurrentLayout();//swmod 080305
224 	std::set<SwRootFrm*> aAllLayouts = pDoc->GetAllLayouts();
225 	//Fuer normale Fussnoten werden Chapter- und Dokumentweise Nummerierung
226 	//getrennt behandelt. Fuer Endnoten gibt es nur die Dokumentweise
227 	//Nummerierung.
228 	if( FTNNUM_CHAPTER == rFtnInfo.eNum )
229 	{
230 		const SwOutlineNodes& rOutlNds = pDoc->GetNodes().GetOutLineNds();
231 		sal_uInt16 nNo = 1,			// Nummer fuer die Fussnoten
232 			   nFtnIdx = 0;		// Index in das FtnIdx-Array
233 		for( sal_uInt16 n = 0; n < rOutlNds.Count(); ++n )
234 		{
235             if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )//<-end,zhaojianwei
236 			{
237 				sal_uLong nCapStt = rOutlNds[ n ]->GetIndex();	// Start eines neuen Kapitels
238 				for( ; nFtnIdx < Count(); ++nFtnIdx )
239 				{
240 					pTxtFtn = (*this)[ nFtnIdx ];
241 					if( pTxtFtn->GetTxtNode().GetIndex() >= nCapStt )
242 						break;
243 
244 					// Endnoten nur Dokumentweise
245 					const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
246 					if( !rFtn.IsEndNote() && !rFtn.GetNumStr().Len() &&
247 						!SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
248 						pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nNo++,
249 											&rFtn.GetNumStr() );
250 				}
251 				if( nFtnIdx >= Count() )
252 					break;			// ok alles geupdatet
253 				nNo = 1;
254 			}
255 		}
256 
257 		for( nNo = 1; nFtnIdx < Count(); ++nFtnIdx )
258 		{
259 			//Endnoten nur Dokumentweise
260 			pTxtFtn = (*this)[ nFtnIdx ];
261 			const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
262 			if( !rFtn.IsEndNote() && !rFtn.GetNumStr().Len() &&
263 				!SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
264 				pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nNo++,
265 									&rFtn.GetNumStr() );
266 		}
267 
268 	}
269 
270 	// sal_Bool, damit hier auch bei Chapter-Einstellung die Endnoten
271 	// durchlaufen.
272 	const sal_Bool bEndNoteOnly = FTNNUM_DOC != rFtnInfo.eNum;
273 	sal_uInt16 nFtnNo = 0, nEndNo = 0;
274 	for( sal_uInt16 nPos = 0; nPos < Count(); ++nPos )
275 	{
276 		pTxtFtn = (*this)[ nPos ];
277 		const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
278 		if( !rFtn.GetNumStr().Len() )
279 		{
280 			sal_uInt16 nSectNo = aNumArr.ChkNumber( *pTxtFtn );
281 			if( !nSectNo && ( rFtn.IsEndNote() || !bEndNoteOnly ))
282 				nSectNo = rFtn.IsEndNote()
283 								? rEndInfo.nFtnOffset + (++nEndNo)
284 								: rFtnInfo.nFtnOffset + (++nFtnNo);
285 
286 			if( nSectNo )
287 			{
288 				if( rFtn.IsEndNote() )
289 					pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
290 				else
291 					pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
292 			}
293 		}
294 	}
295 
296 	if( pTmpRoot && FTNNUM_PAGE == rFtnInfo.eNum )
297 		std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::UpdateFtnNums));//swmod 0
298 }
299 
300 SwTxtFtn* SwFtnIdxs::SeekEntry( const SwNodeIndex& rPos, sal_uInt16* pFndPos ) const
301 {
302 	sal_uLong nIdx = rPos.GetIndex();
303 
304 	sal_uInt16 nO = Count(), nM, nU = 0;
305 	if( nO > 0 )
306 	{
307 		nO--;
308 		while( nU <= nO )
309 		{
310 			nM = nU + ( nO - nU ) / 2;
311 			sal_uLong nNdIdx = _SwTxtFtn_GetIndex( (*this)[ nM ] );
312 			if( nNdIdx == nIdx )
313 			{
314 				if( pFndPos )
315 					*pFndPos = nM;
316 				return (*this)[ nM ];
317 			}
318 			else if( nNdIdx < nIdx )
319 				nU = nM + 1;
320 			else if( nM == 0 )
321 			{
322 				if( pFndPos )
323 					*pFndPos = nU;
324 				return 0;
325 			}
326 			else
327 				nO = nM - 1;
328 		}
329 	}
330 	if( pFndPos )
331 		*pFndPos = nU;
332 	return 0;
333 }
334 
335 /*  */
336 
337 const SwSectionNode* SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr(
338 				const SwTxtFtn& rTxtFtn )
339 {
340 	sal_uInt16 nWh = static_cast<sal_uInt16>( rTxtFtn.GetFtn().IsEndNote() ?
341                         RES_END_AT_TXTEND :	RES_FTN_AT_TXTEND );
342 	sal_uInt16 nVal;
343 	const SwSectionNode* pNd = rTxtFtn.GetTxtNode().FindSectionNode();
344 	while( pNd && FTNEND_ATTXTEND_OWNNUMSEQ != ( nVal =
345 			((const SwFmtFtnAtTxtEnd&)pNd->GetSection().GetFmt()->
346             GetFmtAttr( nWh, sal_True )).GetValue() ) &&
347 			FTNEND_ATTXTEND_OWNNUMANDFMT != nVal )
348         pNd = pNd->StartOfSectionNode()->FindSectionNode();
349 
350 	return pNd;
351 }
352 
353 sal_uInt16 SwUpdFtnEndNtAtEnd::GetNumber( const SwTxtFtn& rTxtFtn,
354 									const SwSectionNode& rNd )
355 {
356 	sal_uInt16 nRet = 0, nWh;
357 	SvPtrarr* pArr;
358 	SvUShorts* pNum;
359 	if( rTxtFtn.GetFtn().IsEndNote() )
360 	{
361 		pArr = &aEndSects;
362 		pNum = &aEndNums;
363 		nWh = RES_END_AT_TXTEND;
364 	}
365 	else
366 	{
367 		pArr = &aFtnSects;
368 		pNum = &aFtnNums;
369 		nWh = RES_FTN_AT_TXTEND;
370 	}
371 	void* pNd = (void*)&rNd;
372 
373 	for( sal_uInt16 n = pArr->Count(); n; )
374 		if( pArr->GetObject( --n ) == pNd )
375 		{
376 			nRet = ++pNum->GetObject( n );
377 			break;
378 		}
379 
380 	if( !nRet )
381 	{
382 		pArr->Insert( pNd, pArr->Count() );
383 		nRet = ((SwFmtFtnEndAtTxtEnd&)rNd.GetSection().GetFmt()->
384                                 GetFmtAttr( nWh )).GetOffset();
385 		++nRet;
386 		pNum->Insert( nRet, pNum->Count() );
387 	}
388 	return nRet;
389 }
390 
391 sal_uInt16 SwUpdFtnEndNtAtEnd::ChkNumber( const SwTxtFtn& rTxtFtn )
392 {
393 	const SwSectionNode* pSectNd = FindSectNdWithEndAttr( rTxtFtn );
394 	return pSectNd ? GetNumber( rTxtFtn, *pSectNd ) : 0;
395 }
396 
397 
398 
399 
400