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 <ftnidx.hxx> 29 #include <rootfrm.hxx> 30 #include <txtftn.hxx> 31 #include <fmtftn.hxx> 32 #include <pam.hxx> 33 #include <pagedesc.hxx> 34 #include <charfmt.hxx> 35 #include <UndoAttribute.hxx> 36 #include <hints.hxx> 37 #include <rolbck.hxx> 38 #include <doc.hxx> 39 #include <IDocumentUndoRedo.hxx> 40 #include <ndtxt.hxx> 41 #include <poolfmt.hxx> 42 #include <ftninfo.hxx> 43 44 /*********************** SwFtnInfo ***************************/ 45 46 SwEndNoteInfo& SwEndNoteInfo::operator=(const SwEndNoteInfo& rInfo) 47 { 48 if( rInfo.GetFtnTxtColl() ) 49 rInfo.GetFtnTxtColl()->Add(this); 50 else if ( GetRegisteredIn()) 51 GetRegisteredInNonConst()->Remove(this); 52 53 if ( rInfo.aPageDescDep.GetRegisteredIn() ) 54 ((SwModify*)rInfo.aPageDescDep.GetRegisteredIn())->Add( &aPageDescDep ); 55 else if ( aPageDescDep.GetRegisteredIn() ) 56 ((SwModify*)aPageDescDep.GetRegisteredIn())->Remove( &aPageDescDep ); 57 58 if ( rInfo.aCharFmtDep.GetRegisteredIn() ) 59 ((SwModify*)rInfo.aCharFmtDep.GetRegisteredIn())->Add( &aCharFmtDep ); 60 else if ( aCharFmtDep.GetRegisteredIn() ) 61 ((SwModify*)aCharFmtDep.GetRegisteredIn())->Remove( &aCharFmtDep ); 62 63 if ( rInfo.aAnchorCharFmtDep.GetRegisteredIn() ) 64 ((SwModify*)rInfo.aAnchorCharFmtDep.GetRegisteredIn())->Add( 65 &aAnchorCharFmtDep ); 66 else if( aAnchorCharFmtDep.GetRegisteredIn() ) 67 ((SwModify*)aAnchorCharFmtDep.GetRegisteredIn())->Remove( 68 &aAnchorCharFmtDep ); 69 70 aFmt = rInfo.aFmt; 71 nFtnOffset = rInfo.nFtnOffset; 72 m_bEndNote = rInfo.m_bEndNote; 73 sPrefix = rInfo.sPrefix; 74 sSuffix = rInfo.sSuffix; 75 return *this; 76 } 77 78 79 sal_Bool SwEndNoteInfo::operator==( const SwEndNoteInfo& rInfo ) const 80 { 81 return aPageDescDep.GetRegisteredIn() == 82 rInfo.aPageDescDep.GetRegisteredIn() && 83 aCharFmtDep.GetRegisteredIn() == 84 rInfo.aCharFmtDep.GetRegisteredIn() && 85 aAnchorCharFmtDep.GetRegisteredIn() == 86 rInfo.aAnchorCharFmtDep.GetRegisteredIn() && 87 GetFtnTxtColl() == rInfo.GetFtnTxtColl() && 88 aFmt.GetNumberingType() == rInfo.aFmt.GetNumberingType() && 89 nFtnOffset == rInfo.nFtnOffset && 90 m_bEndNote == rInfo.m_bEndNote && 91 sPrefix == rInfo.sPrefix && 92 sSuffix == rInfo.sSuffix; 93 } 94 95 96 SwEndNoteInfo::SwEndNoteInfo(const SwEndNoteInfo& rInfo) : 97 SwClient( rInfo.GetFtnTxtColl() ), 98 aPageDescDep( this, 0 ), 99 aCharFmtDep( this, 0 ), 100 aAnchorCharFmtDep( this, 0 ), 101 sPrefix( rInfo.sPrefix ), 102 sSuffix( rInfo.sSuffix ), 103 m_bEndNote( true ), 104 aFmt( rInfo.aFmt ), 105 nFtnOffset( rInfo.nFtnOffset ) 106 { 107 if( rInfo.aPageDescDep.GetRegisteredIn() ) 108 ((SwModify*)rInfo.aPageDescDep.GetRegisteredIn())->Add( &aPageDescDep ); 109 110 if( rInfo.aCharFmtDep.GetRegisteredIn() ) 111 ((SwModify*)rInfo.aCharFmtDep.GetRegisteredIn())->Add( &aCharFmtDep ); 112 113 if( rInfo.aAnchorCharFmtDep.GetRegisteredIn() ) 114 ((SwModify*)rInfo.aAnchorCharFmtDep.GetRegisteredIn())->Add( 115 &aAnchorCharFmtDep ); 116 } 117 118 SwEndNoteInfo::SwEndNoteInfo(SwTxtFmtColl *pFmt) : 119 SwClient(pFmt), 120 aPageDescDep( this, 0 ), 121 aCharFmtDep( this, 0 ), 122 aAnchorCharFmtDep( this, 0 ), 123 m_bEndNote( true ), 124 nFtnOffset( 0 ) 125 { 126 aFmt.SetNumberingType(SVX_NUM_ROMAN_LOWER); 127 } 128 129 SwPageDesc *SwEndNoteInfo::GetPageDesc( SwDoc &rDoc ) const 130 { 131 if ( !aPageDescDep.GetRegisteredIn() ) 132 { 133 SwPageDesc *pDesc = rDoc.GetPageDescFromPool( static_cast<sal_uInt16>( 134 m_bEndNote ? RES_POOLPAGE_ENDNOTE : RES_POOLPAGE_FOOTNOTE ) ); 135 pDesc->Add( &((SwClient&)aPageDescDep) ); 136 } 137 138 return (SwPageDesc*)( aPageDescDep.GetRegisteredIn() ); 139 } 140 141 bool SwEndNoteInfo::KnowsPageDesc() const 142 { 143 return (aPageDescDep.GetRegisteredIn() != 0); 144 } 145 146 bool SwEndNoteInfo::DependsOn( const SwPageDesc* pDesc ) const 147 { 148 return ( aPageDescDep.GetRegisteredIn() == pDesc ); 149 } 150 151 void SwEndNoteInfo::ChgPageDesc( SwPageDesc *pDesc ) 152 { 153 pDesc->Add( &((SwClient&)aPageDescDep) ); 154 } 155 156 void SwEndNoteInfo::SetFtnTxtColl(SwTxtFmtColl& rFmt) 157 { 158 rFmt.Add(this); 159 } 160 161 SwCharFmt* SwEndNoteInfo::GetCharFmt(SwDoc &rDoc) const 162 { 163 if ( !aCharFmtDep.GetRegisteredIn() ) 164 { 165 SwCharFmt* pFmt = rDoc.GetCharFmtFromPool( static_cast<sal_uInt16>( 166 m_bEndNote ? RES_POOLCHR_ENDNOTE : RES_POOLCHR_FOOTNOTE ) ); 167 pFmt->Add( &((SwClient&)aCharFmtDep) ); 168 } 169 return (SwCharFmt*)aCharFmtDep.GetRegisteredIn(); 170 } 171 172 void SwEndNoteInfo::SetCharFmt( SwCharFmt* pChFmt ) 173 { 174 DBG_ASSERT(pChFmt, "kein CharFmt?"); 175 pChFmt->Add( &((SwClient&)aCharFmtDep) ); 176 } 177 178 SwCharFmt* SwEndNoteInfo::GetAnchorCharFmt(SwDoc &rDoc) const 179 { 180 if( !aAnchorCharFmtDep.GetRegisteredIn() ) 181 { 182 SwCharFmt* pFmt = rDoc.GetCharFmtFromPool( static_cast<sal_uInt16>( 183 m_bEndNote ? RES_POOLCHR_ENDNOTE_ANCHOR : RES_POOLCHR_FOOTNOTE_ANCHOR ) ); 184 pFmt->Add( &((SwClient&)aAnchorCharFmtDep) ); 185 } 186 return (SwCharFmt*)aAnchorCharFmtDep.GetRegisteredIn(); 187 } 188 189 void SwEndNoteInfo::SetAnchorCharFmt( SwCharFmt* pChFmt ) 190 { 191 DBG_ASSERT(pChFmt, "kein CharFmt?"); 192 pChFmt->Add( &((SwClient&)aAnchorCharFmtDep) ); 193 } 194 195 void SwEndNoteInfo::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 196 { 197 sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ; 198 199 if( RES_ATTRSET_CHG == nWhich || 200 RES_FMT_CHG == nWhich ) 201 { 202 SwDoc* pDoc; 203 if( aCharFmtDep.GetRegisteredIn() ) 204 pDoc = ((SwCharFmt*)aCharFmtDep.GetRegisteredIn())->GetDoc(); 205 else 206 pDoc = ((SwCharFmt*)aAnchorCharFmtDep.GetRegisteredIn())->GetDoc(); 207 SwFtnIdxs& rFtnIdxs = pDoc->GetFtnIdxs(); 208 for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos ) 209 { 210 SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ]; 211 const SwFmtFtn &rFtn = pTxtFtn->GetFtn(); 212 if ( rFtn.IsEndNote() == m_bEndNote ) 213 { 214 pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr()); 215 } 216 } 217 } 218 else 219 CheckRegistration( pOld, pNew ); 220 } 221 222 SwFtnInfo& SwFtnInfo::operator=(const SwFtnInfo& rInfo) 223 { 224 SwEndNoteInfo::operator=(rInfo); 225 aQuoVadis = rInfo.aQuoVadis; 226 aErgoSum = rInfo.aErgoSum; 227 ePos = rInfo.ePos; 228 eNum = rInfo.eNum; 229 return *this; 230 } 231 232 233 sal_Bool SwFtnInfo::operator==( const SwFtnInfo& rInfo ) const 234 { 235 return ePos == rInfo.ePos && 236 eNum == rInfo.eNum && 237 SwEndNoteInfo::operator==(rInfo) && 238 aQuoVadis == rInfo.aQuoVadis && 239 aErgoSum == rInfo.aErgoSum; 240 } 241 242 243 SwFtnInfo::SwFtnInfo(const SwFtnInfo& rInfo) : 244 SwEndNoteInfo( rInfo ), 245 aQuoVadis( rInfo.aQuoVadis ), 246 aErgoSum( rInfo.aErgoSum ), 247 ePos( rInfo.ePos ), 248 eNum( rInfo.eNum ) 249 { 250 m_bEndNote = false; 251 } 252 253 SwFtnInfo::SwFtnInfo(SwTxtFmtColl *pFmt) : 254 SwEndNoteInfo( pFmt ), 255 ePos( FTNPOS_PAGE ), 256 eNum( FTNNUM_DOC ) 257 { 258 aFmt.SetNumberingType(SVX_NUM_ARABIC); 259 m_bEndNote = false; 260 } 261 262 /*********************** SwDoc ***************************/ 263 264 265 void SwDoc::SetFtnInfo(const SwFtnInfo& rInfo) 266 { 267 SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219 268 if( !(GetFtnInfo() == rInfo) ) 269 { 270 const SwFtnInfo &rOld = GetFtnInfo(); 271 272 if (GetIDocumentUndoRedo().DoesUndo()) 273 { 274 GetIDocumentUndoRedo().AppendUndo( new SwUndoFootNoteInfo(rOld) ); 275 } 276 277 sal_Bool bFtnPos = rInfo.ePos != rOld.ePos; 278 sal_Bool bFtnDesc = rOld.ePos == FTNPOS_CHAPTER && 279 rInfo.GetPageDesc( *this ) != rOld.GetPageDesc( *this ); 280 sal_Bool bExtra = rInfo.aQuoVadis != rOld.aQuoVadis || 281 rInfo.aErgoSum != rOld.aErgoSum || 282 rInfo.aFmt.GetNumberingType() != rOld.aFmt.GetNumberingType() || 283 rInfo.GetPrefix() != rOld.GetPrefix() || 284 rInfo.GetSuffix() != rOld.GetSuffix(); 285 SwCharFmt *pOldChrFmt = rOld.GetCharFmt( *this ), 286 *pNewChrFmt = rInfo.GetCharFmt( *this ); 287 sal_Bool bFtnChrFmts = pOldChrFmt != pNewChrFmt; 288 289 *pFtnInfo = rInfo; 290 291 if (pTmpRoot) 292 { 293 std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();//swmod 080304 294 if ( bFtnPos ) 295 //pTmpRoot->RemoveFtns(); 296 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllRemoveFtns));//swmod 080305 297 else 298 { 299 //pTmpRoot->UpdateFtnNums(); 300 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::UpdateFtnNums));//swmod 080304 301 if ( bFtnDesc ) 302 //pTmpRoot->CheckFtnPageDescs( FALSE ); 303 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::CheckFtnPageDescs), sal_False));//swmod 080304 304 if ( bExtra ) 305 { 306 //Fuer die Benachrichtung bezueglich ErgoSum usw. sparen wir uns 307 //extra-Code und nutzen die vorhandenen Wege. 308 SwFtnIdxs& rFtnIdxs = GetFtnIdxs(); 309 for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos ) 310 { 311 SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ]; 312 const SwFmtFtn &rFtn = pTxtFtn->GetFtn(); 313 if ( !rFtn.IsEndNote() ) 314 pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr()); 315 } 316 } 317 } 318 } //swmod 080219 319 if( FTNNUM_PAGE != rInfo.eNum ) 320 GetFtnIdxs().UpdateAllFtn(); 321 else if( bFtnChrFmts ) 322 { 323 SwFmtChg aOld( pOldChrFmt ); 324 SwFmtChg aNew( pNewChrFmt ); 325 pFtnInfo->ModifyNotification( &aOld, &aNew ); 326 } 327 328 // --> OD 2008-01-09 #i81002# 329 // no update during loading 330 if ( !IsInReading() ) 331 { 332 UpdateRefFlds(NULL); 333 } 334 SetModified(); 335 } 336 } 337 338 void SwDoc::SetEndNoteInfo(const SwEndNoteInfo& rInfo) 339 { 340 SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219 341 if( !(GetEndNoteInfo() == rInfo) ) 342 { 343 if(GetIDocumentUndoRedo().DoesUndo()) 344 { 345 SwUndo *const pUndo( new SwUndoEndNoteInfo( GetEndNoteInfo() ) ); 346 GetIDocumentUndoRedo().AppendUndo(pUndo); 347 } 348 349 sal_Bool bNumChg = rInfo.nFtnOffset != GetEndNoteInfo().nFtnOffset; 350 // this seems to be an optimization: UpdateAllFtn() is only called 351 // if the offset changes; if the offset is the same, 352 // but type/prefix/suffix changes, just set new numbers. 353 bool const bExtra = !bNumChg && 354 ( (rInfo.aFmt.GetNumberingType() != 355 GetEndNoteInfo().aFmt.GetNumberingType()) 356 || (rInfo.GetPrefix() != GetEndNoteInfo().GetPrefix()) 357 || (rInfo.GetSuffix() != GetEndNoteInfo().GetSuffix()) 358 ); 359 sal_Bool bFtnDesc = rInfo.GetPageDesc( *this ) != 360 GetEndNoteInfo().GetPageDesc( *this ); 361 SwCharFmt *pOldChrFmt = GetEndNoteInfo().GetCharFmt( *this ), 362 *pNewChrFmt = rInfo.GetCharFmt( *this ); 363 sal_Bool bFtnChrFmts = pOldChrFmt != pNewChrFmt; 364 365 *pEndNoteInfo = rInfo; 366 367 if ( pTmpRoot ) 368 { 369 if ( bFtnDesc ) 370 //pTmpRoot->CheckFtnPageDescs( TRUE ); 371 { 372 std::set<SwRootFrm*> aAllLayouts = GetAllLayouts(); 373 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::CheckFtnPageDescs), sal_True));//swmod 080304 374 } 375 if ( bExtra ) 376 { 377 //Fuer die Benachrichtung bezueglich ErgoSum usw. sparen wir uns 378 //extra-Code und nutzen die vorhandenen Wege. 379 SwFtnIdxs& rFtnIdxs = GetFtnIdxs(); 380 for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos ) 381 { 382 SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ]; 383 const SwFmtFtn &rFtn = pTxtFtn->GetFtn(); 384 if ( rFtn.IsEndNote() ) 385 pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr()); 386 } 387 } 388 } //swmod 080219 389 if( bNumChg ) 390 GetFtnIdxs().UpdateAllFtn(); 391 else if( bFtnChrFmts ) 392 { 393 SwFmtChg aOld( pOldChrFmt ); 394 SwFmtChg aNew( pNewChrFmt ); 395 pEndNoteInfo->ModifyNotification( &aOld, &aNew ); 396 } 397 398 // --> OD 2008-01-09 #i81002# 399 // no update during loading 400 if ( !IsInReading() ) 401 { 402 UpdateRefFlds(NULL); 403 } 404 SetModified(); 405 } 406 } 407 408 409 bool SwDoc::SetCurFtn( const SwPaM& rPam, const String& rNumStr, 410 sal_uInt16 nNumber, bool bIsEndNote ) 411 { 412 SwFtnIdxs& rFtnArr = GetFtnIdxs(); 413 SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219 414 415 const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End(); 416 const sal_uLong nSttNd = pStt->nNode.GetIndex(); 417 const xub_StrLen nSttCnt = pStt->nContent.GetIndex(); 418 const sal_uLong nEndNd = pEnd->nNode.GetIndex(); 419 const xub_StrLen nEndCnt = pEnd->nContent.GetIndex(); 420 421 sal_uInt16 nPos; 422 rFtnArr.SeekEntry( pStt->nNode, &nPos ); 423 424 SwUndoChangeFootNote* pUndo = 0; 425 if (GetIDocumentUndoRedo().DoesUndo()) 426 { 427 GetIDocumentUndoRedo().ClearRedo(); // AppendUndo far below, so leave it 428 pUndo = new SwUndoChangeFootNote( rPam, rNumStr, nNumber, bIsEndNote ); 429 } 430 431 SwTxtFtn* pTxtFtn; 432 sal_uLong nIdx; 433 sal_Bool bChg = sal_False; 434 sal_Bool bTypeChgd = sal_False; 435 sal_uInt16 n = nPos; // sichern 436 while( nPos < rFtnArr.Count() && 437 (( nIdx = _SwTxtFtn_GetIndex((pTxtFtn = rFtnArr[ nPos++ ] ))) 438 < nEndNd || ( nIdx == nEndNd && 439 nEndCnt >= *pTxtFtn->GetStart() )) ) 440 if( nIdx > nSttNd || ( nIdx == nSttNd && 441 nSttCnt <= *pTxtFtn->GetStart() ) ) 442 { 443 const SwFmtFtn& rFtn = pTxtFtn->GetFtn(); 444 if( /*rFtn.GetNumber() != nNumber ||*/ 445 rFtn.GetNumStr() != rNumStr || 446 rFtn.IsEndNote() != bIsEndNote ) 447 { 448 bChg = sal_True; 449 if ( pUndo ) 450 { 451 pUndo->GetHistory().Add( *pTxtFtn ); 452 } 453 454 pTxtFtn->SetNumber( nNumber, &rNumStr ); 455 if( rFtn.IsEndNote() != bIsEndNote ) 456 { 457 ((SwFmtFtn&)rFtn).SetEndNote( bIsEndNote ); 458 bTypeChgd = sal_True; 459 pTxtFtn->CheckCondColl(); 460 //#i11339# dispose UNO wrapper when a footnote is changed to an endnote or vice versa 461 SwPtrMsgPoolItem aMsgHint( RES_FOOTNOTE_DELETED, (void*)&pTxtFtn->GetAttr() ); 462 GetUnoCallBack()->ModifyNotification( &aMsgHint, &aMsgHint ); 463 } 464 } 465 } 466 467 nPos = n; // nach vorne gibt es auch noch welche ! 468 while( nPos && 469 (( nIdx = _SwTxtFtn_GetIndex((pTxtFtn = rFtnArr[ --nPos ] ))) 470 > nSttNd || ( nIdx == nSttNd && 471 nSttCnt <= *pTxtFtn->GetStart() )) ) 472 if( nIdx < nEndNd || ( nIdx == nEndNd && 473 nEndCnt >= *pTxtFtn->GetStart() ) ) 474 { 475 const SwFmtFtn& rFtn = pTxtFtn->GetFtn(); 476 if( /*rFtn.GetNumber() != nNumber ||*/ 477 rFtn.GetNumStr() != rNumStr || 478 rFtn.IsEndNote() != bIsEndNote ) 479 { 480 bChg = sal_True; 481 if ( pUndo ) 482 { 483 pUndo->GetHistory().Add( *pTxtFtn ); 484 } 485 486 pTxtFtn->SetNumber( nNumber, &rNumStr ); 487 if( rFtn.IsEndNote() != bIsEndNote ) 488 { 489 ((SwFmtFtn&)rFtn).SetEndNote( bIsEndNote ); 490 bTypeChgd = sal_True; 491 pTxtFtn->CheckCondColl(); 492 } 493 } 494 } 495 496 // wer muss angestossen werden ?? 497 if( bChg ) 498 { 499 if( pUndo ) 500 { 501 GetIDocumentUndoRedo().AppendUndo(pUndo); 502 } 503 504 if ( bTypeChgd ) 505 rFtnArr.UpdateAllFtn(); 506 if( FTNNUM_PAGE != GetFtnInfo().eNum ) 507 { 508 if ( !bTypeChgd ) 509 rFtnArr.UpdateAllFtn(); 510 } 511 else if( pTmpRoot ) 512 // 513 { 514 std::set<SwRootFrm*> aAllLayouts = GetAllLayouts(); 515 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::UpdateFtnNums)); 516 } //swmod 080304pTmpRoot->UpdateFtnNums(); //swmod 080219 517 SetModified(); 518 } 519 else 520 delete pUndo; 521 return bChg; 522 } 523 524 525 526 527 528