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