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