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