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