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 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 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 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 296 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 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 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 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