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 #include <stdlib.h> 32 #include <hintids.hxx> 33 #include <svl/intitem.hxx> 34 #include <svl/stritem.hxx> 35 #include <sfx2/docfile.hxx> 36 #include <sfx2/docfilt.hxx> 37 #include <editeng/protitem.hxx> 38 #include <sfx2/linkmgr.hxx> 39 #include <tools/urlobj.hxx> 40 #include <sfx2/sfxsids.hrc> 41 #include <sfx2/fcontnr.hxx> 42 #include <docary.hxx> 43 #include <fmtcntnt.hxx> 44 #include <fmtpdsc.hxx> 45 #include <errhdl.hxx> 46 #include <doc.hxx> 47 #include <IDocumentUndoRedo.hxx> 48 #include <node.hxx> 49 #include <pam.hxx> 50 #include <frmtool.hxx> 51 #include <editsh.hxx> 52 #include <hints.hxx> 53 #include <docsh.hxx> 54 #include <ndtxt.hxx> 55 #include <section.hxx> 56 #include <swserv.hxx> 57 #include <shellio.hxx> 58 #include <poolfmt.hxx> 59 #include <expfld.hxx> 60 #include <swbaslnk.hxx> 61 #include <mvsave.hxx> 62 #include <sectfrm.hxx> 63 #include <fmtftntx.hxx> 64 #include <ftnidx.hxx> 65 #include <doctxm.hxx> 66 #include <fmteiro.hxx> 67 #include <swerror.h> 68 #include <unosection.hxx> 69 #include <switerator.hxx> 70 #include <svl/smplhint.hxx> 71 72 using namespace ::com::sun::star; 73 74 75 SV_IMPL_REF( SwServerObject ) 76 77 //static const char __FAR_DATA sSectionFmtNm[] = "Section"; 78 #define sSectionFmtNm aEmptyStr 79 80 class SwIntrnlSectRefLink : public SwBaseLink 81 { 82 SwSectionFmt& rSectFmt; 83 public: 84 SwIntrnlSectRefLink( SwSectionFmt& rFmt, sal_uInt16 nUpdateType, sal_uInt16 nFmt ) 85 : SwBaseLink( nUpdateType, nFmt ), 86 rSectFmt( rFmt ) 87 {} 88 89 virtual void Closed(); 90 virtual void DataChanged( const String& rMimeType, 91 const uno::Any & rValue ); 92 93 virtual const SwNode* GetAnchor() const; 94 virtual sal_Bool IsInRange( sal_uLong nSttNd, sal_uLong nEndNd, xub_StrLen nStt = 0, 95 xub_StrLen nEnd = STRING_NOTFOUND ) const; 96 97 // --> OD 2007-02-14 #b6521322# 98 inline SwSectionNode* GetSectNode() 99 { 100 const SwNode* pSectNd( const_cast<SwIntrnlSectRefLink*>(this)->GetAnchor() ); 101 return const_cast<SwSectionNode*>( dynamic_cast<const SwSectionNode*>( pSectNd ) ); 102 } 103 // <-- 104 }; 105 106 107 TYPEINIT1(SwSectionFmt,SwFrmFmt ); 108 TYPEINIT1(SwSection,SwClient ); 109 110 typedef SwSection* SwSectionPtr; 111 112 SV_IMPL_PTRARR( SwSections, SwSection*) 113 SV_IMPL_PTRARR(SwSectionFmts,SwSectionFmt*) 114 115 116 SwSectionData::SwSectionData(SectionType const eType, String const& rName) 117 : m_eType(eType) 118 , m_sSectionName(rName) 119 , m_bHiddenFlag(false) 120 , m_bProtectFlag(false) 121 // --> FME 2004-06-22 #114856# edit in readonly sections 122 , m_bEditInReadonlyFlag(false) 123 // <-- 124 , m_bHidden(false) 125 , m_bCondHiddenFlag(true) 126 , m_bConnectFlag(true) 127 { 128 } 129 130 // this must have the same semantics as operator=() 131 SwSectionData::SwSectionData(SwSection const& rSection) 132 : m_eType(rSection.GetType()) 133 , m_sSectionName(rSection.GetSectionName()) 134 , m_sCondition(rSection.GetCondition()) 135 , m_sLinkFileName(rSection.GetLinkFileName()) 136 , m_sLinkFilePassword(rSection.GetLinkFilePassword()) 137 , m_Password(rSection.GetPassword()) 138 , m_bHiddenFlag(rSection.IsHiddenFlag()) 139 , m_bProtectFlag(rSection.IsProtect()) 140 // --> FME 2004-06-22 #114856# edit in readonly sections 141 , m_bEditInReadonlyFlag(rSection.IsEditInReadonly()) 142 // <-- 143 , m_bHidden(rSection.IsHidden()) 144 , m_bCondHiddenFlag(true) 145 , m_bConnectFlag(rSection.IsConnectFlag()) 146 { 147 } 148 149 // this must have the same semantics as operator=() 150 SwSectionData::SwSectionData(SwSectionData const& rOther) 151 : m_eType(rOther.m_eType) 152 , m_sSectionName(rOther.m_sSectionName) 153 , m_sCondition(rOther.m_sCondition) 154 , m_sLinkFileName(rOther.m_sLinkFileName) 155 , m_sLinkFilePassword(rOther.m_sLinkFilePassword) 156 , m_Password(rOther.m_Password) 157 , m_bHiddenFlag(rOther.m_bHiddenFlag) 158 , m_bProtectFlag(rOther.m_bProtectFlag) 159 // --> FME 2004-06-22 #114856# edit in readonly sections 160 , m_bEditInReadonlyFlag(rOther.m_bEditInReadonlyFlag) 161 // <-- 162 , m_bHidden(rOther.m_bHidden) 163 , m_bCondHiddenFlag(true) 164 , m_bConnectFlag(rOther.m_bConnectFlag) 165 { 166 } 167 168 // the semantics here are weird for reasons of backward compatibility 169 SwSectionData & SwSectionData::operator= (SwSectionData const& rOther) 170 { 171 m_eType = rOther.m_eType; 172 m_sSectionName = rOther.m_sSectionName; 173 m_sCondition = rOther.m_sCondition; 174 m_sLinkFileName = rOther.m_sLinkFileName; 175 m_sLinkFilePassword = rOther.m_sLinkFilePassword; 176 m_bConnectFlag = rOther.m_bConnectFlag; 177 m_Password = rOther.m_Password; 178 179 m_bEditInReadonlyFlag = rOther.m_bEditInReadonlyFlag; 180 m_bProtectFlag = rOther.m_bProtectFlag; 181 182 m_bHidden = rOther.m_bHidden; 183 // FIXME: old code did not assign m_bHiddenFlag ? 184 // FIXME: why should m_bCondHiddenFlag always default to true? 185 m_bCondHiddenFlag = true; 186 187 return *this; 188 } 189 190 // the semantics here are weird for reasons of backward compatibility 191 bool SwSectionData::operator==(SwSectionData const& rOther) const 192 { 193 return (m_eType == rOther.m_eType) 194 && (m_sSectionName == rOther.m_sSectionName) 195 && (m_sCondition == rOther.m_sCondition) 196 && (m_bHidden == rOther.m_bHidden) 197 && (m_bProtectFlag == rOther.m_bProtectFlag) 198 && (m_bEditInReadonlyFlag == rOther.m_bEditInReadonlyFlag) 199 && (m_sLinkFileName == rOther.m_sLinkFileName) 200 && (m_sLinkFilePassword == rOther.m_sLinkFilePassword) 201 && (m_Password == rOther.m_Password); 202 // FIXME: old code ignored m_bCondHiddenFlag m_bHiddenFlag m_bConnectFlag 203 } 204 205 // SwSection =========================================================== 206 207 SwSection::SwSection( 208 SectionType const eType, String const& rName, SwSectionFmt & rFormat) 209 : SwClient(& rFormat) 210 , m_Data(eType, rName) 211 { 212 SwSection *const pParentSect = GetParent(); 213 if( pParentSect ) 214 { 215 if( pParentSect->IsHiddenFlag() ) 216 { 217 SetHidden( true ); 218 } 219 220 m_Data.SetProtectFlag( pParentSect->IsProtectFlag() ); 221 // --> FME 2004-06-22 #114856# edit in readonly sections 222 m_Data.SetEditInReadonlyFlag( pParentSect->IsEditInReadonlyFlag() ); 223 // <-- 224 } 225 226 if (!m_Data.IsProtectFlag()) 227 { 228 m_Data.SetProtectFlag( rFormat.GetProtect().IsCntntProtected() ); 229 } 230 231 // --> FME 2004-06-22 #114856# edit in readonly sections 232 if (!m_Data.IsEditInReadonlyFlag()) 233 { 234 m_Data.SetEditInReadonlyFlag( rFormat.GetEditInReadonly().GetValue() ); 235 } 236 // <-- 237 } 238 239 240 SwSection::~SwSection() 241 { 242 SwSectionFmt* pFmt = GetFmt(); 243 if( !pFmt ) 244 return; 245 246 SwDoc* pDoc = pFmt->GetDoc(); 247 if( pDoc->IsInDtor() ) 248 { 249 // dann melden wir noch schnell unser Format um ans dflt FrameFmt, 250 // damit es keine Abhaengigkeiten gibt 251 if( pFmt->DerivedFrom() != pDoc->GetDfltFrmFmt() ) 252 pFmt->RegisterToFormat( *pDoc->GetDfltFrmFmt() ); 253 } 254 else 255 { 256 pFmt->Remove( this ); // austragen, 257 258 if (CONTENT_SECTION != m_Data.GetType()) 259 { 260 pDoc->GetLinkManager().Remove( m_RefLink ); 261 } 262 263 if (m_RefObj.Is()) 264 { 265 pDoc->GetLinkManager().RemoveServer( &m_RefObj ); 266 } 267 268 // ist die Section der letzte Client im Format, kann dieses 269 // geloescht werden 270 SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFmt ); 271 pFmt->ModifyNotification( &aMsgHint, &aMsgHint ); 272 if( !pFmt->GetDepends() ) 273 { 274 // Bug: 28191 - nicht ins Undo aufnehmen, sollte schon vorher 275 // geschehen sein!! 276 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 277 pDoc->DelSectionFmt( pFmt ); // und loeschen 278 } 279 } 280 if (m_RefObj.Is()) 281 { 282 m_RefObj->Closed(); 283 } 284 } 285 286 void SwSection::SetSectionData(SwSectionData const& rData) 287 { 288 bool const bOldHidden( m_Data.IsHidden() ); 289 m_Data = rData; 290 // now update format and reflink with new data 291 // SetLinkFileName(m_Data.GetLinkFileName()); // old code did not do this? 292 // next 2 may actually overwrite m_Data.m_b{Protect,EditInReadonly}Flag 293 // in Modify, which should result in same flag value as the old code! 294 SetProtect(m_Data.IsProtectFlag()); 295 SetEditInReadonly(m_Data.IsEditInReadonlyFlag()); 296 if (bOldHidden != m_Data.IsHidden()) // check if changed... 297 { 298 ImplSetHiddenFlag(m_Data.IsHidden(), m_Data.IsCondHidden()); 299 } 300 } 301 302 bool SwSection::DataEquals(SwSectionData const& rCmp) const 303 { 304 // note that the old code compared the flags of the parameter with the 305 // format attributes of this; the following mess should do the same... 306 (void) GetLinkFileName(); // updates m_sLinkFileName 307 bool const bProtect(m_Data.IsProtectFlag()); 308 bool const bEditInReadonly(m_Data.IsEditInReadonlyFlag()); 309 const_cast<SwSection*>(this)->m_Data.SetProtectFlag(IsProtect()); 310 const_cast<SwSection*>(this)->m_Data 311 .SetEditInReadonlyFlag(IsEditInReadonly()); 312 bool const bResult( m_Data == rCmp ); 313 const_cast<SwSection*>(this)->m_Data.SetProtectFlag(bProtect); 314 const_cast<SwSection*>(this)->m_Data.SetEditInReadonlyFlag(bEditInReadonly); 315 return bResult; 316 } 317 318 319 void SwSection::ImplSetHiddenFlag(bool const bTmpHidden, bool const bCondition) 320 { 321 SwSectionFmt* pFmt = GetFmt(); 322 ASSERT(pFmt, "ImplSetHiddenFlag: no format?"); 323 if( pFmt ) 324 { 325 const bool bHide = bTmpHidden && bCondition; 326 327 if (bHide) // should be hidden 328 { 329 if (!m_Data.IsHiddenFlag()) // is not hidden 330 { 331 // wie sieht es mit dem Parent aus, ist der versteckt ? 332 // (eigentlich muesste das vom bHiddenFlag angezeigt werden!) 333 334 // erstmal allen Childs sagen, das sie versteckt sind 335 SwMsgPoolItem aMsgItem( RES_SECTION_HIDDEN ); 336 pFmt->ModifyNotification( &aMsgItem, &aMsgItem ); 337 338 // alle Frames loeschen 339 pFmt->DelFrms(); 340 } 341 } 342 else if (m_Data.IsHiddenFlag()) // show Nodes again 343 { 344 // alle Frames sichtbar machen ( Childs Sections werden vom 345 // MakeFrms beruecksichtigt). Aber nur wenn die ParentSection 346 // nichts dagegen hat ! 347 SwSection* pParentSect = pFmt->GetParentSection(); 348 if( !pParentSect || !pParentSect->IsHiddenFlag() ) 349 { 350 // erstmal allen Childs sagen, das der Parent nicht mehr 351 // versteckt ist 352 SwMsgPoolItem aMsgItem( RES_SECTION_NOT_HIDDEN ); 353 pFmt->ModifyNotification( &aMsgItem, &aMsgItem ); 354 355 pFmt->MakeFrms(); 356 } 357 } 358 } 359 } 360 361 sal_Bool SwSection::CalcHiddenFlag() const 362 { 363 const SwSection* pSect = this; 364 do { 365 if( pSect->IsHidden() && pSect->IsCondHidden() ) 366 return sal_True; 367 } while( 0 != ( pSect = pSect->GetParent()) ); 368 369 return sal_False; 370 } 371 372 bool SwSection::IsProtect() const 373 { 374 SwSectionFmt *const pFmt( GetFmt() ); 375 ASSERT(pFmt, "SwSection::IsProtect: no format?"); 376 return (pFmt) 377 ? pFmt->GetProtect().IsCntntProtected() 378 : IsProtectFlag(); 379 } 380 381 // --> FME 2004-06-22 #114856# edit in readonly sections 382 bool SwSection::IsEditInReadonly() const 383 { 384 SwSectionFmt *const pFmt( GetFmt() ); 385 ASSERT(pFmt, "SwSection::IsEditInReadonly: no format?"); 386 return (pFmt) 387 ? pFmt->GetEditInReadonly().GetValue() 388 : IsEditInReadonlyFlag(); 389 } 390 // <-- 391 392 void SwSection::SetHidden(bool const bFlag) 393 { 394 if (!m_Data.IsHidden() == !bFlag) 395 return; 396 397 m_Data.SetHidden(bFlag); 398 ImplSetHiddenFlag(bFlag, m_Data.IsCondHidden()); 399 } 400 401 402 void SwSection::SetProtect(bool const bFlag) 403 { 404 SwSectionFmt *const pFormat( GetFmt() ); 405 ASSERT(pFormat, "SwSection::SetProtect: no format?"); 406 if (pFormat) 407 { 408 SvxProtectItem aItem( RES_PROTECT ); 409 aItem.SetCntntProtect( (sal_Bool)bFlag ); 410 pFormat->SetFmtAttr( aItem ); 411 // note: this will call m_Data.SetProtectFlag via Modify! 412 } 413 else 414 { 415 m_Data.SetProtectFlag(bFlag); 416 } 417 } 418 419 // --> FME 2004-06-22 #114856# edit in readonly sections 420 void SwSection::SetEditInReadonly(bool const bFlag) 421 { 422 SwSectionFmt *const pFormat( GetFmt() ); 423 ASSERT(pFormat, "SwSection::SetEditInReadonly: no format?"); 424 if (pFormat) 425 { 426 SwFmtEditInReadonly aItem; 427 aItem.SetValue( (sal_Bool)bFlag ); 428 pFormat->SetFmtAttr( aItem ); 429 // note: this will call m_Data.SetEditInReadonlyFlag via Modify! 430 } 431 else 432 { 433 m_Data.SetEditInReadonlyFlag(bFlag); 434 } 435 } 436 // <-- 437 438 void SwSection::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 439 { 440 bool bRemake = false; 441 bool bUpdateFtn = false; 442 switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ) 443 { 444 case RES_ATTRSET_CHG: 445 { 446 SfxItemSet* pNewSet = ((SwAttrSetChg*)pNew)->GetChgSet(); 447 SfxItemSet* pOldSet = ((SwAttrSetChg*)pOld)->GetChgSet(); 448 const SfxPoolItem* pItem; 449 450 if( SFX_ITEM_SET == pNewSet->GetItemState( 451 RES_PROTECT, sal_False, &pItem ) ) 452 { 453 m_Data.SetProtectFlag( static_cast<SvxProtectItem const*>(pItem) 454 ->IsCntntProtected() ); 455 pNewSet->ClearItem( RES_PROTECT ); 456 pOldSet->ClearItem( RES_PROTECT ); 457 } 458 459 // --> FME 2004-06-22 #114856# edit in readonly sections 460 if( SFX_ITEM_SET == pNewSet->GetItemState( 461 RES_EDIT_IN_READONLY, sal_False, &pItem ) ) 462 { 463 m_Data.SetEditInReadonlyFlag( 464 static_cast<SwFmtEditInReadonly const*>(pItem)->GetValue()); 465 pNewSet->ClearItem( RES_EDIT_IN_READONLY ); 466 pOldSet->ClearItem( RES_EDIT_IN_READONLY ); 467 } 468 // <-- 469 470 if( SFX_ITEM_SET == pNewSet->GetItemState( 471 RES_FTN_AT_TXTEND, sal_False, &pItem ) || 472 SFX_ITEM_SET == pNewSet->GetItemState( 473 RES_END_AT_TXTEND, sal_False, &pItem )) 474 { 475 bUpdateFtn = true; 476 } 477 478 if( !pNewSet->Count() ) 479 return; 480 } 481 break; 482 483 case RES_PROTECT: 484 if( pNew ) 485 { 486 bool bNewFlag = 487 static_cast<const SvxProtectItem*>(pNew)->IsCntntProtected(); 488 if( !bNewFlag ) 489 { 490 // Abschalten: teste ob nicht vielleich ueber die Parents 491 // doch ein Schutzt besteht! 492 const SwSection* pSect = this; 493 do { 494 if( pSect->IsProtect() ) 495 { 496 bNewFlag = true; 497 break; 498 } 499 pSect = pSect->GetParent(); 500 } while (pSect); 501 } 502 503 m_Data.SetProtectFlag( bNewFlag ); 504 } 505 return; 506 // --> FME 2004-06-22 #114856# edit in readonly sections 507 case RES_EDIT_IN_READONLY: 508 if( pNew ) 509 { 510 const bool bNewFlag = 511 static_cast<const SwFmtEditInReadonly*>(pNew)->GetValue(); 512 m_Data.SetEditInReadonlyFlag( bNewFlag ); 513 } 514 return; 515 // <-- 516 517 case RES_SECTION_HIDDEN: 518 m_Data.SetHiddenFlag(true); 519 return; 520 521 case RES_SECTION_NOT_HIDDEN: 522 case RES_SECTION_RESETHIDDENFLAG: 523 m_Data.SetHiddenFlag( m_Data.IsHidden() && m_Data.IsCondHidden() ); 524 return; 525 526 case RES_COL: 527 /* wird ggf. vom Layout erledigt */ 528 break; 529 530 case RES_FTN_AT_TXTEND: 531 if( pNew && pOld ) 532 { 533 bUpdateFtn = true; 534 } 535 break; 536 537 case RES_END_AT_TXTEND: 538 if( pNew && pOld ) 539 { 540 bUpdateFtn = true; 541 } 542 break; 543 544 default: 545 CheckRegistration( pOld, pNew ); 546 break; 547 } 548 549 if( bRemake ) 550 { 551 GetFmt()->DelFrms(); 552 GetFmt()->MakeFrms(); 553 } 554 555 if( bUpdateFtn ) 556 { 557 SwSectionNode* pSectNd = GetFmt()->GetSectionNode( sal_False ); 558 if( pSectNd ) 559 pSectNd->GetDoc()->GetFtnIdxs().UpdateFtn(SwNodeIndex( *pSectNd )); 560 } 561 } 562 563 void SwSection::SetRefObject( SwServerObject* pObj ) 564 { 565 m_RefObj = pObj; 566 } 567 568 569 void SwSection::SetCondHidden(bool const bFlag) 570 { 571 if (!m_Data.IsCondHidden() == !bFlag) 572 return; 573 574 m_Data.SetCondHidden(bFlag); 575 ImplSetHiddenFlag(m_Data.IsHidden(), bFlag); 576 } 577 578 579 // setze/erfrage den gelinkten FileNamen 580 const String& SwSection::GetLinkFileName() const 581 { 582 if (m_RefLink.Is()) 583 { 584 String sTmp; 585 switch (m_Data.GetType()) 586 { 587 case DDE_LINK_SECTION: 588 sTmp = m_RefLink->GetLinkSourceName(); 589 break; 590 591 case FILE_LINK_SECTION: 592 { 593 String sRange, sFilter; 594 if (m_RefLink->GetLinkManager() && 595 m_RefLink->GetLinkManager()->GetDisplayNames( 596 m_RefLink, 0, &sTmp, &sRange, &sFilter )) 597 { 598 ( sTmp += sfx2::cTokenSeperator ) += sFilter; 599 ( sTmp += sfx2::cTokenSeperator ) += sRange; 600 } 601 else if( GetFmt() && !GetFmt()->GetSectionNode() ) 602 { 603 // ist die Section im UndoNodesArray, dann steht 604 // der Link nicht im LinkManager, kann also auch nicht 605 // erfragt werden. Dann returne den akt. Namen 606 return m_Data.GetLinkFileName(); 607 } 608 } 609 break; 610 default: break; 611 } 612 const_cast<SwSection*>(this)->m_Data.SetLinkFileName(sTmp); 613 } 614 return m_Data.GetLinkFileName(); 615 } 616 617 618 void SwSection::SetLinkFileName(const String& rNew, String const*const pPassWd) 619 { 620 if (m_RefLink.Is()) 621 { 622 m_RefLink->SetLinkSourceName( rNew ); 623 } 624 m_Data.SetLinkFileName(rNew); 625 if( pPassWd ) 626 { 627 SetLinkFilePassword( *pPassWd ); 628 } 629 } 630 631 // falls es ein gelinkter Bereich war, dann muessen alle 632 // Child-Verknuepfungen sichtbar bemacht werden. 633 void SwSection::MakeChildLinksVisible( const SwSectionNode& rSectNd ) 634 { 635 const SwNode* pNd; 636 const ::sfx2::SvBaseLinks& rLnks = rSectNd.GetDoc()->GetLinkManager().GetLinks(); 637 for( sal_uInt16 n = rLnks.Count(); n; ) 638 { 639 ::sfx2::SvBaseLink* pBLnk = &(*rLnks[ --n ]); 640 if( pBLnk && !pBLnk->IsVisible() && 641 pBLnk->ISA( SwBaseLink ) && 642 0 != ( pNd = ((SwBaseLink*)pBLnk)->GetAnchor() ) ) 643 { 644 pNd = pNd->StartOfSectionNode(); // falls SectionNode ist! 645 const SwSectionNode* pParent; 646 while( 0 != ( pParent = pNd->FindSectionNode() ) && 647 ( CONTENT_SECTION == pParent->GetSection().GetType() 648 || pNd == &rSectNd )) 649 pNd = pParent->StartOfSectionNode(); 650 651 // steht nur noch in einer normalen Section, also 652 // wieder anzeigen 653 if( !pParent ) 654 pBLnk->SetVisible( sal_True ); 655 } 656 } 657 } 658 659 const SwTOXBase* SwSection::GetTOXBase() const 660 { 661 const SwTOXBase* pRet = 0; 662 if( TOX_CONTENT_SECTION == GetType() ) 663 pRet = PTR_CAST( SwTOXBaseSection, this ); 664 return pRet; 665 } 666 667 // SwSectionFmt ======================================================== 668 669 SwSectionFmt::SwSectionFmt( SwSectionFmt* pDrvdFrm, SwDoc *pDoc ) 670 : SwFrmFmt( pDoc->GetAttrPool(), sSectionFmtNm, pDrvdFrm ) 671 { 672 LockModify(); 673 SetFmtAttr( *GetDfltAttr( RES_COL ) ); 674 UnlockModify(); 675 } 676 677 SwSectionFmt::~SwSectionFmt() 678 { 679 if( !GetDoc()->IsInDtor() ) 680 { 681 SwSectionNode* pSectNd; 682 const SwNodeIndex* pIdx = GetCntnt( sal_False ).GetCntntIdx(); 683 if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() && 684 0 != (pSectNd = pIdx->GetNode().GetSectionNode() )) 685 { 686 SwSection& rSect = pSectNd->GetSection(); 687 // falls es ein gelinkter Bereich war, dann muessen alle 688 // Child-Verknuepfungen sichtbar bemacht werden. 689 if( rSect.IsConnected() ) 690 rSect.MakeChildLinksVisible( *pSectNd ); 691 692 // vorm loeschen der Nodes pruefe, ob wir uns nicht 693 // noch anzeigen muessen! 694 if( rSect.IsHiddenFlag() ) 695 { 696 SwSectionPtr pParentSect = rSect.GetParent(); 697 if( !pParentSect || !pParentSect->IsHiddenFlag() ) 698 { 699 // Nodes wieder anzeigen 700 rSect.SetHidden(false); 701 } 702 } 703 // mba: test iteration; objects are removed while iterating 704 // --> OD #i117863# 705 // use hint which allows to specify, if the content shall be saved or not 706 CallSwClientNotify( SwSectionFrmMoveAndDeleteHint( sal_True ) ); 707 // <-- 708 709 // hebe die Section doch mal auf 710 SwNodeRange aRg( *pSectNd, 0, *pSectNd->EndOfSectionNode() ); 711 GetDoc()->GetNodes().SectionUp( &aRg ); 712 } 713 LockModify(); 714 ResetFmtAttr( RES_CNTNT ); 715 UnlockModify(); 716 } 717 } 718 719 720 SwSection * SwSectionFmt::GetSection() const 721 { 722 return SwIterator<SwSection,SwSectionFmt>::FirstElement( *this ); 723 } 724 725 extern void lcl_DeleteFtn( SwSectionNode *pNd, sal_uLong nStt, sal_uLong nEnd ); 726 727 //Vernichtet alle Frms in aDepend (Frms werden per PTR_CAST erkannt). 728 void SwSectionFmt::DelFrms() 729 { 730 SwSectionNode* pSectNd; 731 const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx(); 732 if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() && 733 0 != (pSectNd = pIdx->GetNode().GetSectionNode() )) 734 { 735 // #147431# : First delete the <SwSectionFrm> of the <SwSectionFmt> instance 736 // mba: test iteration as objects are removed in iteration 737 // --> OD #i117863# 738 // use hint which allows to specify, if the content shall be saved or not 739 CallSwClientNotify( SwSectionFrmMoveAndDeleteHint( sal_False ) ); 740 // <-- 741 742 // Then delete frames of the nested <SwSectionFmt> instances 743 SwIterator<SwSectionFmt,SwSectionFmt> aIter( *this ); 744 SwSectionFmt *pLast = aIter.First(); 745 while ( pLast ) 746 { 747 pLast->DelFrms(); 748 pLast = aIter.Next(); 749 } 750 751 sal_uLong nEnde = pSectNd->EndOfSectionIndex(); 752 sal_uLong nStart = pSectNd->GetIndex()+1; 753 lcl_DeleteFtn( pSectNd, nStart, nEnde ); 754 } 755 if( pIdx ) 756 { 757 //JP 22.09.98: 758 //Hint fuer Pagedesc versenden. Das mueste eigntlich das Layout im 759 //Paste der Frames selbst erledigen, aber das fuehrt dann wiederum 760 //zu weiteren Folgefehlern, die mit Laufzeitkosten geloest werden 761 //muesten. #56977# #55001# #56135# 762 SwNodeIndex aNextNd( *pIdx ); 763 SwCntntNode* pCNd = GetDoc()->GetNodes().GoNextSection( &aNextNd, sal_True, sal_False ); 764 if( pCNd ) 765 { 766 const SfxPoolItem& rItem = pCNd->GetSwAttrSet().Get( RES_PAGEDESC ); 767 pCNd->ModifyNotification( (SfxPoolItem*)&rItem, (SfxPoolItem*)&rItem ); 768 } 769 } 770 } 771 772 773 //Erzeugt die Ansichten 774 void SwSectionFmt::MakeFrms() 775 { 776 SwSectionNode* pSectNd; 777 const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx(); 778 779 if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() && 780 0 != (pSectNd = pIdx->GetNode().GetSectionNode() )) 781 { 782 SwNodeIndex aIdx( *pIdx ); 783 pSectNd->MakeFrms( &aIdx ); 784 } 785 } 786 787 void SwSectionFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 788 { 789 sal_Bool bClients = sal_False; 790 sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0; 791 switch( nWhich ) 792 { 793 case RES_ATTRSET_CHG: 794 if( GetDepends() ) 795 { 796 SfxItemSet* pNewSet = ((SwAttrSetChg*)pNew)->GetChgSet(); 797 SfxItemSet* pOldSet = ((SwAttrSetChg*)pOld)->GetChgSet(); 798 const SfxPoolItem *pItem; 799 if( SFX_ITEM_SET == pNewSet->GetItemState( 800 RES_PROTECT, sal_False, &pItem )) 801 { 802 ModifyBroadcast( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem ); 803 pNewSet->ClearItem( RES_PROTECT ); 804 pOldSet->ClearItem( RES_PROTECT ); 805 } 806 807 // --> FME 2004-06-22 #114856# edit in readonly sections 808 if( SFX_ITEM_SET == pNewSet->GetItemState( 809 RES_EDIT_IN_READONLY, sal_False, &pItem ) ) 810 { 811 ModifyBroadcast( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem ); 812 pNewSet->ClearItem( RES_EDIT_IN_READONLY ); 813 pOldSet->ClearItem( RES_EDIT_IN_READONLY ); 814 } 815 // <-- 816 817 if( SFX_ITEM_SET == pNewSet->GetItemState( 818 RES_FTN_AT_TXTEND, sal_False, &pItem )) 819 { 820 ModifyBroadcast( (SfxPoolItem*)&pOldSet->Get( RES_FTN_AT_TXTEND ), (SfxPoolItem*)pItem ); 821 pNewSet->ClearItem( RES_FTN_AT_TXTEND ); 822 pOldSet->ClearItem( RES_FTN_AT_TXTEND ); 823 } 824 if( SFX_ITEM_SET == pNewSet->GetItemState( 825 RES_END_AT_TXTEND, sal_False, &pItem )) 826 { 827 ModifyBroadcast( (SfxPoolItem*)&pOldSet->Get( RES_END_AT_TXTEND ), (SfxPoolItem*)pItem ); 828 pNewSet->ClearItem( RES_END_AT_TXTEND ); 829 pOldSet->ClearItem( RES_END_AT_TXTEND ); 830 } 831 if( !((SwAttrSetChg*)pOld)->GetChgSet()->Count() ) 832 return; 833 } 834 break; 835 836 case RES_SECTION_RESETHIDDENFLAG: 837 case RES_FTN_AT_TXTEND: 838 case RES_END_AT_TXTEND : bClients = sal_True; 839 // no break !! 840 case RES_SECTION_HIDDEN: 841 case RES_SECTION_NOT_HIDDEN: 842 { 843 SwSection* pSect = GetSection(); 844 if( pSect && ( bClients || ( RES_SECTION_HIDDEN == nWhich ? 845 !pSect->IsHiddenFlag() : pSect->IsHiddenFlag() ) ) ) 846 { 847 ModifyBroadcast( pOld, pNew ); 848 } 849 } 850 return ; 851 852 853 case RES_PROTECT: 854 // --> FME 2004-06-22 #114856# edit in readonly sections 855 case RES_EDIT_IN_READONLY: 856 // <-- 857 // diese Messages bis zum Ende des Baums durchreichen ! 858 if( GetDepends() ) 859 { 860 ModifyBroadcast( pOld, pNew ); 861 } 862 return; // das wars 863 864 case RES_OBJECTDYING: 865 if( !GetDoc()->IsInDtor() && 866 ((SwPtrMsgPoolItem *)pOld)->pObject == (void*)GetRegisteredIn() ) 867 { 868 // mein Parent wird vernichtet, dann an den Parent vom Parent 869 // umhaengen und wieder aktualisieren 870 SwFrmFmt::Modify( pOld, pNew ); // erst umhaengen !!! 871 UpdateParent(); 872 return; 873 } 874 break; 875 876 case RES_FMT_CHG: 877 if( !GetDoc()->IsInDtor() && 878 ((SwFmtChg*)pNew)->pChangedFmt == (void*)GetRegisteredIn() && 879 ((SwFmtChg*)pNew)->pChangedFmt->IsA( TYPE( SwSectionFmt )) ) 880 { 881 // mein Parent wird veraendert, muss mich aktualisieren 882 SwFrmFmt::Modify( pOld, pNew ); // erst umhaengen !!! 883 UpdateParent(); 884 return; 885 } 886 break; 887 } 888 SwFrmFmt::Modify( pOld, pNew ); 889 890 if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which())) 891 { // invalidate cached uno object 892 SetXTextSection(uno::Reference<text::XTextSection>(0)); 893 } 894 } 895 896 // erfrage vom Format Informationen 897 sal_Bool SwSectionFmt::GetInfo( SfxPoolItem& rInfo ) const 898 { 899 switch( rInfo.Which() ) 900 { 901 case RES_FINDNEARESTNODE: 902 if( ((SwFmtPageDesc&)GetFmtAttr( RES_PAGEDESC )).GetPageDesc() ) 903 { 904 const SwSectionNode* pNd = GetSectionNode(); 905 if( pNd ) 906 ((SwFindNearestNode&)rInfo).CheckNode( *pNd ); 907 } 908 return sal_True; 909 910 case RES_CONTENT_VISIBLE: 911 { 912 SwFrm* pFrm = SwIterator<SwFrm,SwFmt>::FirstElement(*this); 913 // if the current section has no own frame search for the children 914 if(!pFrm) 915 { 916 SwIterator<SwSectionFmt,SwSectionFmt> aFormatIter(*this); 917 SwSectionFmt* pChild = aFormatIter.First(); 918 while(pChild && !pFrm) 919 { 920 pFrm = SwIterator<SwFrm,SwFmt>::FirstElement(*pChild); 921 pChild = aFormatIter.Next(); 922 } 923 } 924 ((SwPtrMsgPoolItem&)rInfo).pObject = pFrm; 925 } 926 return sal_False; 927 } 928 return SwModify::GetInfo( rInfo ); 929 } 930 931 extern "C" { 932 933 int 934 #if defined( WNT ) 935 __cdecl 936 #endif 937 #if defined( ICC ) 938 _Optlink 939 #endif 940 lcl_SectionCmpPos( const void *pFirst, const void *pSecond) 941 { 942 const SwSectionFmt* pFSectFmt = (*(SwSectionPtr*)pFirst)->GetFmt(); 943 const SwSectionFmt* pSSectFmt = (*(SwSectionPtr*)pSecond)->GetFmt(); 944 ASSERT( pFSectFmt && pSSectFmt && 945 pFSectFmt->GetCntnt(sal_False).GetCntntIdx() && 946 pSSectFmt->GetCntnt(sal_False).GetCntntIdx(), 947 "ungueltige Sections" ); 948 return (int)((long)pFSectFmt->GetCntnt(sal_False).GetCntntIdx()->GetIndex()) - 949 pSSectFmt->GetCntnt(sal_False).GetCntntIdx()->GetIndex(); 950 } 951 952 int 953 #if defined( WNT ) 954 __cdecl 955 #endif 956 #if defined( ICC ) 957 _Optlink 958 #endif 959 lcl_SectionCmpNm( const void *pFirst, const void *pSecond) 960 { 961 const SwSectionPtr pFSect = *(SwSectionPtr*)pFirst; 962 const SwSectionPtr pSSect = *(SwSectionPtr*)pSecond; 963 ASSERT( pFSect && pSSect, "ungueltige Sections" ); 964 StringCompare const eCmp = 965 pFSect->GetSectionName().CompareTo( pSSect->GetSectionName() ); 966 return eCmp == COMPARE_EQUAL ? 0 967 : eCmp == COMPARE_LESS ? 1 : -1; 968 } 969 } 970 971 // alle Sections, die von dieser abgeleitet sind 972 sal_uInt16 SwSectionFmt::GetChildSections( SwSections& rArr, 973 SectionSort eSort, 974 sal_Bool bAllSections ) const 975 { 976 rArr.Remove( 0, rArr.Count() ); 977 978 if( GetDepends() ) 979 { 980 SwIterator<SwSectionFmt,SwSectionFmt> aIter(*this); 981 const SwNodeIndex* pIdx; 982 for( SwSectionFmt* pLast = aIter.First(); pLast; pLast = aIter.Next() ) 983 if( bAllSections || 984 ( 0 != ( pIdx = pLast->GetCntnt(sal_False). 985 GetCntntIdx()) && &pIdx->GetNodes() == &GetDoc()->GetNodes() )) 986 { 987 const SwSection* Dummy = pLast->GetSection(); 988 rArr.C40_INSERT( SwSection, 989 Dummy, 990 rArr.Count() ); 991 } 992 993 // noch eine Sortierung erwuenscht ? 994 if( 1 < rArr.Count() ) 995 switch( eSort ) 996 { 997 case SORTSECT_NAME: 998 qsort( (void*)rArr.GetData(), 999 rArr.Count(), 1000 sizeof( SwSectionPtr ), 1001 lcl_SectionCmpNm ); 1002 break; 1003 1004 case SORTSECT_POS: 1005 qsort( (void*)rArr.GetData(), 1006 rArr.Count(), 1007 sizeof( SwSectionPtr ), 1008 lcl_SectionCmpPos ); 1009 break; 1010 case SORTSECT_NOT: break; 1011 } 1012 } 1013 return rArr.Count(); 1014 } 1015 1016 // erfrage, ob sich die Section im Nodes-Array oder UndoNodes-Array 1017 // befindet. 1018 sal_Bool SwSectionFmt::IsInNodesArr() const 1019 { 1020 const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx(); 1021 return pIdx && &pIdx->GetNodes() == &GetDoc()->GetNodes(); 1022 } 1023 1024 1025 void SwSectionFmt::UpdateParent() // Parent wurde veraendert 1026 { 1027 if( !GetDepends() ) 1028 return; 1029 1030 SwSectionPtr pSection = 0; 1031 const SvxProtectItem* pProtect(0); 1032 // --> FME 2004-06-22 #114856# edit in readonly sections 1033 const SwFmtEditInReadonly* pEditInReadonly = 0; 1034 // <-- 1035 bool bIsHidden = false; 1036 1037 SwClientIter aIter( *this ); // TODO 1038 ::SwClient * pLast = aIter.GoStart(); 1039 if( pLast ) // konnte zum Anfang gesprungen werden ?? 1040 do { 1041 if( pLast->IsA( TYPE(SwSectionFmt) ) ) 1042 { 1043 if( !pSection ) 1044 { 1045 pSection = GetSection(); 1046 if( GetRegisteredIn() ) 1047 { 1048 const SwSectionPtr pPS = GetParentSection(); 1049 pProtect = &pPS->GetFmt()->GetProtect(); 1050 // --> FME 2004-06-22 #114856# edit in readonly sections 1051 pEditInReadonly = &pPS->GetFmt()->GetEditInReadonly(); 1052 // <-- 1053 bIsHidden = pPS->IsHiddenFlag(); 1054 } 1055 else 1056 { 1057 pProtect = &GetProtect(); 1058 // --> FME 2004-06-22 #114856# edit in readonly sections 1059 pEditInReadonly = &GetEditInReadonly(); 1060 // <-- 1061 bIsHidden = pSection->IsHidden(); 1062 } 1063 } 1064 if (!pProtect->IsCntntProtected() != 1065 !pSection->IsProtectFlag()) 1066 { 1067 pLast->ModifyNotification( (SfxPoolItem*)pProtect, 1068 (SfxPoolItem*)pProtect ); 1069 } 1070 1071 // --> FME 2004-06-22 #114856# edit in readonly sections 1072 if (!pEditInReadonly->GetValue() != 1073 !pSection->IsEditInReadonlyFlag()) 1074 { 1075 pLast->ModifyNotification( (SfxPoolItem*)pEditInReadonly, 1076 (SfxPoolItem*)pEditInReadonly ); 1077 } 1078 // <-- 1079 1080 if( bIsHidden == pSection->IsHiddenFlag() ) 1081 { 1082 SwMsgPoolItem aMsgItem( static_cast<sal_uInt16>(bIsHidden 1083 ? RES_SECTION_HIDDEN 1084 : RES_SECTION_NOT_HIDDEN ) ); 1085 pLast->ModifyNotification( &aMsgItem, &aMsgItem ); 1086 } 1087 } 1088 else if( !pSection && 1089 pLast->IsA( TYPE(SwSection) ) ) 1090 { 1091 pSection = (SwSectionPtr)pLast; 1092 if( GetRegisteredIn() ) 1093 { 1094 const SwSectionPtr pPS = GetParentSection(); 1095 pProtect = &pPS->GetFmt()->GetProtect(); 1096 // --> FME 2004-06-22 #114856# edit in readonly sections 1097 pEditInReadonly = &pPS->GetFmt()->GetEditInReadonly(); 1098 // <-- 1099 bIsHidden = pPS->IsHiddenFlag(); 1100 } 1101 else 1102 { 1103 pProtect = &GetProtect(); 1104 // --> FME 2004-06-22 #114856# edit in readonly sections 1105 pEditInReadonly = &GetEditInReadonly(); 1106 // <-- 1107 bIsHidden = pSection->IsHidden(); 1108 } 1109 } 1110 } while( 0 != ( pLast = ++aIter )); 1111 } 1112 1113 1114 SwSectionNode* SwSectionFmt::GetSectionNode(bool const bAlways) 1115 { 1116 const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx(); 1117 if( pIdx && ( bAlways || &pIdx->GetNodes() == &GetDoc()->GetNodes() )) 1118 return pIdx->GetNode().GetSectionNode(); 1119 return 0; 1120 } 1121 1122 // ist die Section eine gueltige fuers GlobalDocument? 1123 const SwSection* SwSectionFmt::GetGlobalDocSection() const 1124 { 1125 const SwSectionNode* pNd = GetSectionNode(); 1126 if( pNd && 1127 ( FILE_LINK_SECTION == pNd->GetSection().GetType() || 1128 TOX_CONTENT_SECTION == pNd->GetSection().GetType() ) && 1129 pNd->GetIndex() > pNd->GetNodes().GetEndOfExtras().GetIndex() && 1130 !pNd->StartOfSectionNode()->IsSectionNode() && 1131 !pNd->StartOfSectionNode()->FindSectionNode() ) 1132 return &pNd->GetSection(); 1133 return 0; 1134 } 1135 1136 // sw::Metadatable 1137 ::sfx2::IXmlIdRegistry& SwSectionFmt::GetRegistry() 1138 { 1139 return GetDoc()->GetXmlIdRegistry(); 1140 } 1141 1142 bool SwSectionFmt::IsInClipboard() const 1143 { 1144 return GetDoc()->IsClipBoard(); 1145 } 1146 1147 bool SwSectionFmt::IsInUndo() const 1148 { 1149 return !IsInNodesArr(); 1150 } 1151 1152 bool SwSectionFmt::IsInContent() const 1153 { 1154 SwNodeIndex const*const pIdx = GetCntnt(sal_False).GetCntntIdx(); 1155 OSL_ENSURE(pIdx, "SwSectionFmt::IsInContent: no index?"); 1156 return (pIdx) ? !GetDoc()->IsInHeaderFooter(*pIdx) : true; 1157 } 1158 1159 // n.b.: if the section format represents an index, then there is both a 1160 // SwXDocumentIndex and a SwXTextSection instance for this single core object. 1161 // these two can both implement XMetadatable and forward to the same core 1162 // section format. but here only one UNO object can be returned, 1163 // so always return the text section. 1164 uno::Reference< rdf::XMetadatable > 1165 SwSectionFmt::MakeUnoObject() 1166 { 1167 uno::Reference<rdf::XMetadatable> xMeta; 1168 SwSection *const pSection( GetSection() ); 1169 if (pSection) 1170 { 1171 xMeta.set( SwXTextSection::CreateXTextSection(this, 1172 TOX_HEADER_SECTION == pSection->GetType()), 1173 uno::UNO_QUERY ); 1174 } 1175 return xMeta; 1176 } 1177 1178 1179 // --> OD 2007-02-14 #b6521322# 1180 // Method to break section links inside a linked section 1181 void lcl_BreakSectionLinksInSect( const SwSectionNode& rSectNd ) 1182 { 1183 if ( !rSectNd.GetDoc() ) 1184 { 1185 ASSERT( false, 1186 "method <lcl_RemoveSectionLinksInSect(..)> - no Doc at SectionNode" ); 1187 return; 1188 } 1189 1190 if ( !rSectNd.GetSection().IsConnected() ) 1191 { 1192 ASSERT( false, 1193 "method <lcl_RemoveSectionLinksInSect(..)> - no Link at Section of SectionNode" ); 1194 return; 1195 } 1196 const ::sfx2::SvBaseLink* pOwnLink( &(rSectNd.GetSection().GetBaseLink() ) ); 1197 const ::sfx2::SvBaseLinks& rLnks = rSectNd.GetDoc()->GetLinkManager().GetLinks(); 1198 for ( sal_uInt16 n = rLnks.Count(); n > 0; ) 1199 { 1200 SwIntrnlSectRefLink* pSectLnk = dynamic_cast<SwIntrnlSectRefLink*>(&(*rLnks[ --n ])); 1201 if ( pSectLnk && pSectLnk != pOwnLink && 1202 pSectLnk->IsInRange( rSectNd.GetIndex(), rSectNd.EndOfSectionIndex() ) ) 1203 { 1204 // break the link of the corresponding section. 1205 // the link is also removed from the link manager 1206 pSectLnk->GetSectNode()->GetSection().BreakLink(); 1207 1208 // for robustness, because link is removed from the link manager 1209 if ( n > rLnks.Count() ) 1210 { 1211 n = rLnks.Count(); 1212 } 1213 } 1214 } 1215 } 1216 // <-- 1217 1218 void lcl_UpdateLinksInSect( SwBaseLink& rUpdLnk, SwSectionNode& rSectNd ) 1219 { 1220 SwDoc* pDoc = rSectNd.GetDoc(); 1221 SwDocShell* pDShell = pDoc->GetDocShell(); 1222 if( !pDShell || !pDShell->GetMedium() ) 1223 return ; 1224 1225 String sName( pDShell->GetMedium()->GetName() ); 1226 SwBaseLink* pBLink; 1227 String sMimeType( SotExchange::GetFormatMimeType( FORMAT_FILE )); 1228 uno::Any aValue; 1229 aValue <<= ::rtl::OUString( sName ); // beliebiger Name 1230 1231 const ::sfx2::SvBaseLinks& rLnks = pDoc->GetLinkManager().GetLinks(); 1232 for( sal_uInt16 n = rLnks.Count(); n; ) 1233 { 1234 ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]); 1235 if( pLnk && pLnk != &rUpdLnk && 1236 OBJECT_CLIENT_FILE == pLnk->GetObjType() && 1237 pLnk->ISA( SwBaseLink ) && 1238 ( pBLink = (SwBaseLink*)pLnk )->IsInRange( rSectNd.GetIndex(), 1239 rSectNd.EndOfSectionIndex() ) ) 1240 { 1241 // liegt in dem Bereich: also updaten. Aber nur wenns nicht 1242 // im gleichen File liegt 1243 String sFName; 1244 pDoc->GetLinkManager().GetDisplayNames( pBLink, 0, &sFName, 0, 0 ); 1245 if( sFName != sName ) 1246 { 1247 pBLink->DataChanged( sMimeType, aValue ); 1248 1249 // ggfs. neu den Link-Pointer wieder suchen, damit nicht einer 1250 // ausgelassen oder doppelt gerufen wird. 1251 if( n >= rLnks.Count() && 0 != ( n = rLnks.Count() )) 1252 --n; 1253 1254 if( n && pLnk != &(*rLnks[ n ]) ) 1255 { 1256 // suchen - kann nur davor liegen!! 1257 while( n ) 1258 if( pLnk == &(*rLnks[ --n ] ) ) 1259 break; 1260 } 1261 } 1262 } 1263 } 1264 } 1265 1266 1267 // sucht sich die richtige DocShell raus oder erzeugt eine neue: 1268 // Der Return-Wert gibt an, was mit der Shell zu geschehen hat: 1269 // 0 - Fehler, konnte DocShell nicht finden 1270 // 1 - DocShell ist ein existieren Document 1271 // 2 - DocShell wurde neu angelegt, muss also wieder geschlossen werden ( will be assigned to xLockRef additionaly ) 1272 1273 int lcl_FindDocShell( SfxObjectShellRef& xDocSh, 1274 SfxObjectShellLock& xLockRef, 1275 const String& rFileName, 1276 const String& rPasswd, 1277 String& rFilter, 1278 sal_Int16 nVersion, 1279 SwDocShell* pDestSh ) 1280 { 1281 if( !rFileName.Len() ) 1282 return 0; 1283 1284 // 1. existiert die Datei schon in der Liste aller Dokumente? 1285 INetURLObject aTmpObj( rFileName ); 1286 aTmpObj.SetMark( aEmptyStr ); 1287 1288 // erstmal nur ueber die DocumentShells laufen und die mit dem 1289 // Namen heraussuchen: 1290 TypeId aType( TYPE(SwDocShell) ); 1291 1292 SfxObjectShell* pShell = pDestSh; 1293 sal_Bool bFirst = 0 != pShell; 1294 1295 if( !bFirst ) 1296 // keine DocShell uebergeben, also beginne mit der ersten aus der 1297 // DocShell Liste 1298 pShell = SfxObjectShell::GetFirst( &aType ); 1299 1300 while( pShell ) 1301 { 1302 // die wollen wir haben 1303 SfxMedium* pMed = pShell->GetMedium(); 1304 if( pMed && pMed->GetURLObject() == aTmpObj ) 1305 { 1306 const SfxPoolItem* pItem; 1307 if( ( SFX_ITEM_SET == pMed->GetItemSet()->GetItemState( 1308 SID_VERSION, sal_False, &pItem ) ) 1309 ? (nVersion == ((SfxInt16Item*)pItem)->GetValue()) 1310 : !nVersion ) 1311 { 1312 // gefunden also returnen 1313 xDocSh = pShell; 1314 return 1; 1315 } 1316 } 1317 1318 if( bFirst ) 1319 { 1320 bFirst = sal_False; 1321 pShell = SfxObjectShell::GetFirst( &aType ); 1322 } 1323 else 1324 pShell = SfxObjectShell::GetNext( *pShell, &aType ); 1325 } 1326 1327 // 2. selbst die Date oeffnen 1328 SfxMedium* pMed = new SfxMedium( aTmpObj.GetMainURL( 1329 INetURLObject::NO_DECODE ), STREAM_READ, sal_True ); 1330 if( INET_PROT_FILE == aTmpObj.GetProtocol() ) 1331 pMed->DownLoad(); // nur mal das Medium anfassen (DownLoaden) 1332 1333 const SfxFilter* pSfxFlt = 0; 1334 if( !pMed->GetError() ) 1335 { 1336 String sFactory(String::CreateFromAscii(SwDocShell::Factory().GetShortName())); 1337 SfxFilterMatcher aMatcher( sFactory ); 1338 1339 // kein Filter, dann suche ihn. Ansonsten teste, ob der angegebene 1340 // ein gueltiger ist 1341 if( rFilter.Len() ) 1342 { 1343 pSfxFlt = aMatcher.GetFilter4FilterName( rFilter ); 1344 } 1345 1346 if( nVersion ) 1347 pMed->GetItemSet()->Put( SfxInt16Item( SID_VERSION, nVersion )); 1348 1349 if( rPasswd.Len() ) 1350 pMed->GetItemSet()->Put( SfxStringItem( SID_PASSWORD, rPasswd )); 1351 1352 if( !pSfxFlt ) 1353 aMatcher.DetectFilter( *pMed, &pSfxFlt, sal_False, sal_False ); 1354 1355 if( pSfxFlt ) 1356 { 1357 // ohne Filter geht gar nichts 1358 pMed->SetFilter( pSfxFlt ); 1359 1360 // if the new shell is created, SfxObjectShellLock should be used to let it be closed later for sure 1361 xLockRef = new SwDocShell( SFX_CREATE_MODE_INTERNAL ); 1362 xDocSh = (SfxObjectShell*)xLockRef; 1363 if( xDocSh->DoLoad( pMed ) ) 1364 return 2; 1365 } 1366 } 1367 1368 if( !xDocSh.Is() ) // Medium muss noch geloescht werden 1369 delete pMed; 1370 1371 return 0; // das war wohl nichts 1372 } 1373 1374 1375 void SwIntrnlSectRefLink::DataChanged( const String& rMimeType, 1376 const uno::Any & rValue ) 1377 { 1378 SwSectionNode* pSectNd = rSectFmt.GetSectionNode( sal_False ); 1379 SwDoc* pDoc = rSectFmt.GetDoc(); 1380 1381 sal_uLong nDataFormat = SotExchange::GetFormatIdFromMimeType( rMimeType ); 1382 1383 if( !pSectNd || !pDoc || pDoc->IsInDtor() || ChkNoDataFlag() || 1384 sfx2::LinkManager::RegisterStatusInfoId() == nDataFormat ) 1385 { 1386 // sollten wir schon wieder im Undo stehen? 1387 return ; 1388 } 1389 1390 // --> OD 2005-02-11 #i38810# - Due to possible existing signatures, the 1391 // document has to be modified after updating a link. 1392 pDoc->SetModified(); 1393 // set additional flag that links have been updated, in order to check this 1394 // during load. 1395 pDoc->SetLinksUpdated( sal_True ); 1396 // <-- 1397 1398 // Undo immer abschalten 1399 bool const bWasUndo = pDoc->GetIDocumentUndoRedo().DoesUndo(); 1400 pDoc->GetIDocumentUndoRedo().DoUndo(false); 1401 sal_Bool bWasVisibleLinks = pDoc->IsVisibleLinks(); 1402 pDoc->SetVisibleLinks( sal_False ); 1403 1404 SwPaM* pPam; 1405 ViewShell* pVSh = 0; 1406 SwEditShell* pESh = pDoc->GetEditShell( &pVSh ); 1407 pDoc->LockExpFlds(); 1408 { 1409 // am Anfang des Bereichs einen leeren TextNode einfuegen 1410 SwNodeIndex aIdx( *pSectNd, +1 ); 1411 SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() ); 1412 SwTxtNode* pNewNd = pDoc->GetNodes().MakeTxtNode( aIdx, 1413 pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT ) ); 1414 1415 if( pESh ) 1416 pESh->StartAllAction(); 1417 else if( pVSh ) 1418 pVSh->StartAction(); 1419 1420 SwPosition aPos( aIdx, SwIndex( pNewNd, 0 )); 1421 aPos.nNode--; 1422 pDoc->CorrAbs( aIdx, aEndIdx, aPos, sal_True ); 1423 1424 pPam = new SwPaM( aPos ); 1425 1426 //und alles dahinter liegende loeschen 1427 aIdx--; 1428 DelFlyInRange( aIdx, aEndIdx ); 1429 _DelBookmarks(aIdx, aEndIdx); 1430 aIdx++; 1431 1432 pDoc->GetNodes().Delete( aIdx, aEndIdx.GetIndex() - aIdx.GetIndex() ); 1433 } 1434 1435 SwSection& rSection = pSectNd->GetSection(); 1436 rSection.SetConnectFlag(false); 1437 1438 ::rtl::OUString sNewFileName; 1439 Reader* pRead = 0; 1440 switch( nDataFormat ) 1441 { 1442 case FORMAT_STRING: 1443 pRead = ReadAscii; 1444 break; 1445 1446 case FORMAT_RTF: 1447 pRead = SwReaderWriter::GetReader( READER_WRITER_RTF ); 1448 break; 1449 1450 case FORMAT_FILE: 1451 if( rValue.hasValue() && ( rValue >>= sNewFileName ) ) 1452 { 1453 String sFilter, sRange, sFileName( sNewFileName ); 1454 pDoc->GetLinkManager().GetDisplayNames( this, 0, &sFileName, 1455 &sRange, &sFilter ); 1456 1457 RedlineMode_t eOldRedlineMode = nsRedlineMode_t::REDLINE_NONE; 1458 SfxObjectShellRef xDocSh; 1459 SfxObjectShellLock xLockRef; 1460 int nRet; 1461 if( !sFileName.Len() ) 1462 { 1463 xDocSh = pDoc->GetDocShell(); 1464 nRet = 1; 1465 } 1466 else 1467 { 1468 nRet = lcl_FindDocShell( xDocSh, xLockRef, sFileName, 1469 rSection.GetLinkFilePassword(), 1470 sFilter, 0, pDoc->GetDocShell() ); 1471 if( nRet ) 1472 { 1473 SwDoc* pSrcDoc = ((SwDocShell*)&xDocSh)->GetDoc(); 1474 eOldRedlineMode = pSrcDoc->GetRedlineMode(); 1475 pSrcDoc->SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_INSERT ); 1476 } 1477 } 1478 1479 if( nRet ) 1480 { 1481 rSection.SetConnectFlag(true); 1482 1483 SwNodeIndex aSave( pPam->GetPoint()->nNode, -1 ); 1484 SwNodeRange* pCpyRg = 0; 1485 1486 if( xDocSh->GetMedium() && 1487 !rSection.GetLinkFilePassword().Len() ) 1488 { 1489 const SfxPoolItem* pItem; 1490 if( SFX_ITEM_SET == xDocSh->GetMedium()->GetItemSet()-> 1491 GetItemState( SID_PASSWORD, sal_False, &pItem ) ) 1492 rSection.SetLinkFilePassword( 1493 ((SfxStringItem*)pItem)->GetValue() ); 1494 } 1495 1496 SwDoc* pSrcDoc = ((SwDocShell*)&xDocSh)->GetDoc(); 1497 1498 if( sRange.Len() ) 1499 { 1500 // Rekursionen abfangen 1501 sal_Bool bRecursion = sal_False; 1502 if( pSrcDoc == pDoc ) 1503 { 1504 SwServerObjectRef refObj( (SwServerObject*) 1505 pDoc->CreateLinkSource( sRange )); 1506 if( refObj.Is() ) 1507 { 1508 bRecursion = refObj->IsLinkInServer( this ) || 1509 ChkNoDataFlag(); 1510 } 1511 } 1512 1513 SwNodeIndex& rInsPos = pPam->GetPoint()->nNode; 1514 1515 SwPaM* pCpyPam = 0; 1516 if( !bRecursion && 1517 pSrcDoc->SelectServerObj( sRange, pCpyPam, pCpyRg ) 1518 && pCpyPam ) 1519 { 1520 if( pSrcDoc != pDoc || 1521 pCpyPam->Start()->nNode > rInsPos || 1522 rInsPos >= pCpyPam->End()->nNode ) 1523 { 1524 pSrcDoc->CopyRange( *pCpyPam, *pPam->GetPoint(), 1525 false ); 1526 } 1527 delete pCpyPam; 1528 } 1529 if( pCpyRg && pSrcDoc == pDoc && 1530 pCpyRg->aStart < rInsPos && rInsPos < pCpyRg->aEnd ) 1531 delete pCpyRg, pCpyRg = 0; 1532 } 1533 else if( pSrcDoc != pDoc ) 1534 pCpyRg = new SwNodeRange( pSrcDoc->GetNodes().GetEndOfExtras(), 2, 1535 pSrcDoc->GetNodes().GetEndOfContent() ); 1536 1537 // --> OD 2007-11-30 #i81653# 1538 // Update links of extern linked document or extern linked 1539 // document section, if section is protected. 1540 if ( pSrcDoc != pDoc && 1541 rSection.IsProtectFlag() ) 1542 { 1543 pSrcDoc->GetLinkManager().UpdateAllLinks( sal_False, sal_True, sal_False, 0 ); 1544 } 1545 // <-- 1546 if( pCpyRg ) 1547 { 1548 SwNodeIndex& rInsPos = pPam->GetPoint()->nNode; 1549 sal_Bool bCreateFrm = rInsPos.GetIndex() <= 1550 pDoc->GetNodes().GetEndOfExtras().GetIndex() || 1551 rInsPos.GetNode().FindTableNode(); 1552 1553 SwTblNumFmtMerge aTNFM( *pSrcDoc, *pDoc ); 1554 1555 pSrcDoc->CopyWithFlyInFly( *pCpyRg, 0, rInsPos, bCreateFrm ); 1556 aSave++; 1557 1558 if( !bCreateFrm ) 1559 ::MakeFrms( pDoc, aSave, rInsPos ); 1560 1561 // den letzten Node noch loeschen, aber nur wenn 1562 // erfolgreich kopiert werden konnte, also der Bereich 1563 // mehr als 1 Node enthaelt 1564 if( 2 < pSectNd->EndOfSectionIndex() - pSectNd->GetIndex() ) 1565 { 1566 aSave = rInsPos; 1567 pPam->Move( fnMoveBackward, fnGoNode ); 1568 pPam->SetMark(); // beide SwPositions ummelden! 1569 1570 pDoc->CorrAbs( aSave, *pPam->GetPoint(), 0, sal_True ); 1571 pDoc->GetNodes().Delete( aSave, 1 ); 1572 } 1573 delete pCpyRg; 1574 } 1575 1576 // --> OD 2007-02-14 #b6521322# 1577 lcl_BreakSectionLinksInSect( *pSectNd ); 1578 // <-- 1579 1580 // update alle Links in diesem Bereich 1581 lcl_UpdateLinksInSect( *this, *pSectNd ); 1582 } 1583 if( xDocSh.Is() ) 1584 { 1585 if( 2 == nRet ) 1586 xDocSh->DoClose(); 1587 else if( ((SwDocShell*)&xDocSh)->GetDoc() ) 1588 ((SwDocShell*)&xDocSh)->GetDoc()->SetRedlineMode( 1589 eOldRedlineMode ); 1590 } 1591 } 1592 break; 1593 } 1594 1595 // !!!! DDE nur updaten wenn Shell vorhanden ist?? 1596 uno::Sequence< sal_Int8 > aSeq; 1597 if( pRead && rValue.hasValue() && ( rValue >>= aSeq ) ) 1598 { 1599 if( pESh ) 1600 { 1601 pESh->Push(); 1602 SwPaM* pCrsr = pESh->GetCrsr(); 1603 *pCrsr->GetPoint() = *pPam->GetPoint(); 1604 delete pPam; 1605 pPam = pCrsr; 1606 } 1607 1608 SvMemoryStream aStrm( (void*)aSeq.getConstArray(), aSeq.getLength(), 1609 STREAM_READ ); 1610 aStrm.Seek( 0 ); 1611 1612 #if OSL_DEBUG_LEVEL > 1 1613 { 1614 SvFileStream aDeb( String::CreateFromAscii( 1615 "file:///d|/temp/update.txt" ), STREAM_WRITE ); 1616 aDeb << aStrm; 1617 } 1618 aStrm.Seek( 0 ); 1619 #endif 1620 1621 // TODO/MBA: it's impossible to set a BaseURL here! 1622 SwReader aTmpReader( aStrm, aEmptyStr, pDoc->GetDocShell()->GetMedium()->GetBaseURL(), *pPam ); 1623 1624 if( !IsError( aTmpReader.Read( *pRead ) )) 1625 { 1626 rSection.SetConnectFlag(true); 1627 } 1628 1629 if( pESh ) 1630 { 1631 pESh->Pop( sal_False ); 1632 pPam = 0; // pam is deleted before 1633 } 1634 } 1635 1636 1637 // remove all undo actions and turn undo on again 1638 pDoc->GetIDocumentUndoRedo().DelAllUndoObj(); 1639 pDoc->GetIDocumentUndoRedo().DoUndo(bWasUndo); 1640 pDoc->SetVisibleLinks( bWasVisibleLinks ); 1641 1642 pDoc->UnlockExpFlds(); 1643 if( !pDoc->IsExpFldsLocked() ) 1644 pDoc->UpdateExpFlds(NULL, true); 1645 1646 if( pESh ) 1647 pESh->EndAllAction(); 1648 else if( pVSh ) 1649 pVSh->EndAction(); 1650 delete pPam; // wurde am Anfang angelegt 1651 } 1652 1653 1654 void SwIntrnlSectRefLink::Closed() 1655 { 1656 SwDoc* pDoc = rSectFmt.GetDoc(); 1657 if( pDoc && !pDoc->IsInDtor() ) 1658 { 1659 // Advise verabschiedet sich, den Bereich als nicht geschuetzt 1660 // kennzeichnen und das Flag umsetzen 1661 1662 const SwSectionFmts& rFmts = pDoc->GetSections(); 1663 for( sal_uInt16 n = rFmts.Count(); n; ) 1664 if( rFmts[ --n ] == &rSectFmt ) 1665 { 1666 ViewShell* pSh; 1667 SwEditShell* pESh = pDoc->GetEditShell( &pSh ); 1668 1669 if( pESh ) 1670 pESh->StartAllAction(); 1671 else 1672 pSh->StartAction(); 1673 1674 SwSectionData aSectionData(*rSectFmt.GetSection()); 1675 aSectionData.SetType( CONTENT_SECTION ); 1676 aSectionData.SetLinkFileName( aEmptyStr ); 1677 aSectionData.SetHidden( false ); 1678 aSectionData.SetProtectFlag( false ); 1679 // --> FME 2004-06-22 #114856# edit in readonly sections 1680 aSectionData.SetEditInReadonlyFlag( false ); 1681 // <-- 1682 1683 aSectionData.SetConnectFlag( false ); 1684 1685 pDoc->UpdateSection( n, aSectionData ); 1686 1687 // alle in der Section liegenden Links werden sichtbar 1688 SwSectionNode* pSectNd = rSectFmt.GetSectionNode( sal_False ); 1689 if( pSectNd ) 1690 pSectNd->GetSection().MakeChildLinksVisible( *pSectNd ); 1691 1692 if( pESh ) 1693 pESh->EndAllAction(); 1694 else 1695 pSh->EndAction(); 1696 break; 1697 } 1698 } 1699 SvBaseLink::Closed(); 1700 } 1701 1702 1703 void SwSection::CreateLink( LinkCreateType eCreateType ) 1704 { 1705 SwSectionFmt* pFmt = GetFmt(); 1706 ASSERT(pFmt, "SwSection::CreateLink: no format?"); 1707 if (!pFmt || (CONTENT_SECTION == m_Data.GetType())) 1708 return ; 1709 1710 sal_uInt16 nUpdateType = sfx2::LINKUPDATE_ALWAYS; 1711 1712 if (!m_RefLink.Is()) 1713 { 1714 // create BaseLink 1715 m_RefLink = new SwIntrnlSectRefLink( *pFmt, nUpdateType, FORMAT_RTF ); 1716 } 1717 else 1718 { 1719 pFmt->GetDoc()->GetLinkManager().Remove( m_RefLink ); 1720 } 1721 1722 SwIntrnlSectRefLink *const pLnk = 1723 static_cast<SwIntrnlSectRefLink*>(& m_RefLink); 1724 1725 String sCmd( m_Data.GetLinkFileName() ); 1726 xub_StrLen nPos; 1727 while( STRING_NOTFOUND != (nPos = sCmd.SearchAscii( " " )) ) 1728 sCmd.Erase( nPos, 1 ); 1729 1730 pLnk->SetUpdateMode( nUpdateType ); 1731 pLnk->SetVisible( pFmt->GetDoc()->IsVisibleLinks() ); 1732 1733 switch (m_Data.GetType()) 1734 { 1735 case DDE_LINK_SECTION: 1736 pLnk->SetLinkSourceName( sCmd ); 1737 pFmt->GetDoc()->GetLinkManager().InsertDDELink( pLnk ); 1738 break; 1739 case FILE_LINK_SECTION: 1740 { 1741 pLnk->SetContentType( FORMAT_FILE ); 1742 String sFltr( sCmd.GetToken( 1, sfx2::cTokenSeperator ) ); 1743 String sRange( sCmd.GetToken( 2, sfx2::cTokenSeperator ) ); 1744 pFmt->GetDoc()->GetLinkManager().InsertFileLink( *pLnk, 1745 static_cast<sal_uInt16>(m_Data.GetType()), 1746 sCmd.GetToken( 0, sfx2::cTokenSeperator ), 1747 ( sFltr.Len() ? &sFltr : 0 ), 1748 ( sRange.Len() ? &sRange : 0 ) ); 1749 } 1750 break; 1751 default: 1752 ASSERT( !this, "Was ist das fuer ein Link?" ) 1753 } 1754 1755 switch( eCreateType ) 1756 { 1757 case CREATE_CONNECT: // Link gleich connecten 1758 pLnk->Connect(); 1759 break; 1760 1761 case CREATE_UPDATE: // Link connecten und updaten 1762 pLnk->Update(); 1763 break; 1764 case CREATE_NONE: break; 1765 } 1766 } 1767 1768 // --> OD 2007-02-14 #b6521322# 1769 void SwSection::BreakLink() 1770 { 1771 const SectionType eCurrentType( GetType() ); 1772 if ( eCurrentType == CONTENT_SECTION || 1773 eCurrentType == TOX_HEADER_SECTION || 1774 eCurrentType == TOX_CONTENT_SECTION ) 1775 { 1776 // nothing to do 1777 return; 1778 } 1779 1780 // release link, if it exists 1781 if (m_RefLink.Is()) 1782 { 1783 SwSectionFmt *const pFormat( GetFmt() ); 1784 ASSERT(pFormat, "SwSection::BreakLink: no format?"); 1785 if (pFormat) 1786 { 1787 pFormat->GetDoc()->GetLinkManager().Remove( m_RefLink ); 1788 } 1789 m_RefLink.Clear(); 1790 } 1791 // change type 1792 SetType( CONTENT_SECTION ); 1793 // reset linked file data 1794 SetLinkFileName( aEmptyStr ); 1795 SetLinkFilePassword( aEmptyStr ); 1796 } 1797 // <-- 1798 1799 const SwNode* SwIntrnlSectRefLink::GetAnchor() const 1800 { 1801 return rSectFmt.GetSectionNode( sal_False ); 1802 } 1803 1804 1805 sal_Bool SwIntrnlSectRefLink::IsInRange( sal_uLong nSttNd, sal_uLong nEndNd, 1806 xub_StrLen , xub_StrLen ) const 1807 { 1808 SwStartNode* pSttNd = rSectFmt.GetSectionNode( sal_False ); 1809 return pSttNd && 1810 nSttNd < pSttNd->GetIndex() && 1811 pSttNd->EndOfSectionIndex() < nEndNd; 1812 } 1813 1814 1815 1816