xref: /AOO41X/main/sw/source/core/doc/ftnidx.cxx (revision efeef26f81c84063fb0a91bde3856d4a51172d90)
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