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