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 CallSwClientNotify( SfxSimpleHint(SFX_HINT_DYING) ); 705 706 // hebe die Section doch mal auf 707 SwNodeRange aRg( *pSectNd, 0, *pSectNd->EndOfSectionNode() ); 708 GetDoc()->GetNodes().SectionUp( &aRg ); 709 } 710 LockModify(); 711 ResetFmtAttr( RES_CNTNT ); 712 UnlockModify(); 713 } 714 } 715 716 717 SwSection * SwSectionFmt::GetSection() const 718 { 719 return SwIterator<SwSection,SwSectionFmt>::FirstElement( *this ); 720 } 721 722 extern void lcl_DeleteFtn( SwSectionNode *pNd, sal_uLong nStt, sal_uLong nEnd ); 723 724 //Vernichtet alle Frms in aDepend (Frms werden per PTR_CAST erkannt). 725 void SwSectionFmt::DelFrms() 726 { 727 SwSectionNode* pSectNd; 728 const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx(); 729 if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() && 730 0 != (pSectNd = pIdx->GetNode().GetSectionNode() )) 731 { 732 // #147431# : First delete the <SwSectionFrm> of the <SwSectionFmt> instance 733 // mba: test iteration as objects are removed in iteration 734 CallSwClientNotify( SfxSimpleHint(SFX_HINT_DYING) ); 735 736 // Then delete frames of the nested <SwSectionFmt> instances 737 SwIterator<SwSectionFmt,SwSectionFmt> aIter( *this ); 738 SwSectionFmt *pLast = aIter.First(); 739 while ( pLast ) 740 { 741 pLast->DelFrms(); 742 pLast = aIter.Next(); 743 } 744 745 sal_uLong nEnde = pSectNd->EndOfSectionIndex(); 746 sal_uLong nStart = pSectNd->GetIndex()+1; 747 lcl_DeleteFtn( pSectNd, nStart, nEnde ); 748 } 749 if( pIdx ) 750 { 751 //JP 22.09.98: 752 //Hint fuer Pagedesc versenden. Das mueste eigntlich das Layout im 753 //Paste der Frames selbst erledigen, aber das fuehrt dann wiederum 754 //zu weiteren Folgefehlern, die mit Laufzeitkosten geloest werden 755 //muesten. #56977# #55001# #56135# 756 SwNodeIndex aNextNd( *pIdx ); 757 SwCntntNode* pCNd = GetDoc()->GetNodes().GoNextSection( &aNextNd, sal_True, sal_False ); 758 if( pCNd ) 759 { 760 const SfxPoolItem& rItem = pCNd->GetSwAttrSet().Get( RES_PAGEDESC ); 761 pCNd->ModifyNotification( (SfxPoolItem*)&rItem, (SfxPoolItem*)&rItem ); 762 } 763 } 764 } 765 766 767 //Erzeugt die Ansichten 768 void SwSectionFmt::MakeFrms() 769 { 770 SwSectionNode* pSectNd; 771 const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx(); 772 773 if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() && 774 0 != (pSectNd = pIdx->GetNode().GetSectionNode() )) 775 { 776 SwNodeIndex aIdx( *pIdx ); 777 pSectNd->MakeFrms( &aIdx ); 778 } 779 } 780 781 void SwSectionFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 782 { 783 sal_Bool bClients = sal_False; 784 sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0; 785 switch( nWhich ) 786 { 787 case RES_ATTRSET_CHG: 788 if( GetDepends() ) 789 { 790 SfxItemSet* pNewSet = ((SwAttrSetChg*)pNew)->GetChgSet(); 791 SfxItemSet* pOldSet = ((SwAttrSetChg*)pOld)->GetChgSet(); 792 const SfxPoolItem *pItem; 793 if( SFX_ITEM_SET == pNewSet->GetItemState( 794 RES_PROTECT, sal_False, &pItem )) 795 { 796 ModifyBroadcast( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem ); 797 pNewSet->ClearItem( RES_PROTECT ); 798 pOldSet->ClearItem( RES_PROTECT ); 799 } 800 801 // --> FME 2004-06-22 #114856# edit in readonly sections 802 if( SFX_ITEM_SET == pNewSet->GetItemState( 803 RES_EDIT_IN_READONLY, sal_False, &pItem ) ) 804 { 805 ModifyBroadcast( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem ); 806 pNewSet->ClearItem( RES_EDIT_IN_READONLY ); 807 pOldSet->ClearItem( RES_EDIT_IN_READONLY ); 808 } 809 // <-- 810 811 if( SFX_ITEM_SET == pNewSet->GetItemState( 812 RES_FTN_AT_TXTEND, sal_False, &pItem )) 813 { 814 ModifyBroadcast( (SfxPoolItem*)&pOldSet->Get( RES_FTN_AT_TXTEND ), (SfxPoolItem*)pItem ); 815 pNewSet->ClearItem( RES_FTN_AT_TXTEND ); 816 pOldSet->ClearItem( RES_FTN_AT_TXTEND ); 817 } 818 if( SFX_ITEM_SET == pNewSet->GetItemState( 819 RES_END_AT_TXTEND, sal_False, &pItem )) 820 { 821 ModifyBroadcast( (SfxPoolItem*)&pOldSet->Get( RES_END_AT_TXTEND ), (SfxPoolItem*)pItem ); 822 pNewSet->ClearItem( RES_END_AT_TXTEND ); 823 pOldSet->ClearItem( RES_END_AT_TXTEND ); 824 } 825 if( !((SwAttrSetChg*)pOld)->GetChgSet()->Count() ) 826 return; 827 } 828 break; 829 830 case RES_SECTION_RESETHIDDENFLAG: 831 case RES_FTN_AT_TXTEND: 832 case RES_END_AT_TXTEND : bClients = sal_True; 833 // no break !! 834 case RES_SECTION_HIDDEN: 835 case RES_SECTION_NOT_HIDDEN: 836 { 837 SwSection* pSect = GetSection(); 838 if( pSect && ( bClients || ( RES_SECTION_HIDDEN == nWhich ? 839 !pSect->IsHiddenFlag() : pSect->IsHiddenFlag() ) ) ) 840 { 841 ModifyBroadcast( pOld, pNew ); 842 } 843 } 844 return ; 845 846 847 case RES_PROTECT: 848 // --> FME 2004-06-22 #114856# edit in readonly sections 849 case RES_EDIT_IN_READONLY: 850 // <-- 851 // diese Messages bis zum Ende des Baums durchreichen ! 852 if( GetDepends() ) 853 { 854 ModifyBroadcast( pOld, pNew ); 855 } 856 return; // das wars 857 858 case RES_OBJECTDYING: 859 if( !GetDoc()->IsInDtor() && 860 ((SwPtrMsgPoolItem *)pOld)->pObject == (void*)GetRegisteredIn() ) 861 { 862 // mein Parent wird vernichtet, dann an den Parent vom Parent 863 // umhaengen und wieder aktualisieren 864 SwFrmFmt::Modify( pOld, pNew ); // erst umhaengen !!! 865 UpdateParent(); 866 return; 867 } 868 break; 869 870 case RES_FMT_CHG: 871 if( !GetDoc()->IsInDtor() && 872 ((SwFmtChg*)pNew)->pChangedFmt == (void*)GetRegisteredIn() && 873 ((SwFmtChg*)pNew)->pChangedFmt->IsA( TYPE( SwSectionFmt )) ) 874 { 875 // mein Parent wird veraendert, muss mich aktualisieren 876 SwFrmFmt::Modify( pOld, pNew ); // erst umhaengen !!! 877 UpdateParent(); 878 return; 879 } 880 break; 881 } 882 SwFrmFmt::Modify( pOld, pNew ); 883 884 if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which())) 885 { // invalidate cached uno object 886 SetXTextSection(uno::Reference<text::XTextSection>(0)); 887 } 888 } 889 890 // erfrage vom Format Informationen 891 sal_Bool SwSectionFmt::GetInfo( SfxPoolItem& rInfo ) const 892 { 893 switch( rInfo.Which() ) 894 { 895 case RES_FINDNEARESTNODE: 896 if( ((SwFmtPageDesc&)GetFmtAttr( RES_PAGEDESC )).GetPageDesc() ) 897 { 898 const SwSectionNode* pNd = GetSectionNode(); 899 if( pNd ) 900 ((SwFindNearestNode&)rInfo).CheckNode( *pNd ); 901 } 902 return sal_True; 903 904 case RES_CONTENT_VISIBLE: 905 { 906 SwFrm* pFrm = SwIterator<SwFrm,SwFmt>::FirstElement(*this); 907 // if the current section has no own frame search for the children 908 if(!pFrm) 909 { 910 SwIterator<SwSectionFmt,SwSectionFmt> aFormatIter(*this); 911 SwSectionFmt* pChild = aFormatIter.First(); 912 while(pChild && !pFrm) 913 { 914 pFrm = SwIterator<SwFrm,SwFmt>::FirstElement(*pChild); 915 pChild = aFormatIter.Next(); 916 } 917 } 918 ((SwPtrMsgPoolItem&)rInfo).pObject = pFrm; 919 } 920 return sal_False; 921 } 922 return SwModify::GetInfo( rInfo ); 923 } 924 925 extern "C" { 926 927 int 928 #if defined( WNT ) 929 __cdecl 930 #endif 931 #if defined( ICC ) 932 _Optlink 933 #endif 934 lcl_SectionCmpPos( const void *pFirst, const void *pSecond) 935 { 936 const SwSectionFmt* pFSectFmt = (*(SwSectionPtr*)pFirst)->GetFmt(); 937 const SwSectionFmt* pSSectFmt = (*(SwSectionPtr*)pSecond)->GetFmt(); 938 ASSERT( pFSectFmt && pSSectFmt && 939 pFSectFmt->GetCntnt(sal_False).GetCntntIdx() && 940 pSSectFmt->GetCntnt(sal_False).GetCntntIdx(), 941 "ungueltige Sections" ); 942 return (int)((long)pFSectFmt->GetCntnt(sal_False).GetCntntIdx()->GetIndex()) - 943 pSSectFmt->GetCntnt(sal_False).GetCntntIdx()->GetIndex(); 944 } 945 946 int 947 #if defined( WNT ) 948 __cdecl 949 #endif 950 #if defined( ICC ) 951 _Optlink 952 #endif 953 lcl_SectionCmpNm( const void *pFirst, const void *pSecond) 954 { 955 const SwSectionPtr pFSect = *(SwSectionPtr*)pFirst; 956 const SwSectionPtr pSSect = *(SwSectionPtr*)pSecond; 957 ASSERT( pFSect && pSSect, "ungueltige Sections" ); 958 StringCompare const eCmp = 959 pFSect->GetSectionName().CompareTo( pSSect->GetSectionName() ); 960 return eCmp == COMPARE_EQUAL ? 0 961 : eCmp == COMPARE_LESS ? 1 : -1; 962 } 963 } 964 965 // alle Sections, die von dieser abgeleitet sind 966 sal_uInt16 SwSectionFmt::GetChildSections( SwSections& rArr, 967 SectionSort eSort, 968 sal_Bool bAllSections ) const 969 { 970 rArr.Remove( 0, rArr.Count() ); 971 972 if( GetDepends() ) 973 { 974 SwIterator<SwSectionFmt,SwSectionFmt> aIter(*this); 975 const SwNodeIndex* pIdx; 976 for( SwSectionFmt* pLast = aIter.First(); pLast; pLast = aIter.Next() ) 977 if( bAllSections || 978 ( 0 != ( pIdx = pLast->GetCntnt(sal_False). 979 GetCntntIdx()) && &pIdx->GetNodes() == &GetDoc()->GetNodes() )) 980 { 981 const SwSection* Dummy = pLast->GetSection(); 982 rArr.C40_INSERT( SwSection, 983 Dummy, 984 rArr.Count() ); 985 } 986 987 // noch eine Sortierung erwuenscht ? 988 if( 1 < rArr.Count() ) 989 switch( eSort ) 990 { 991 case SORTSECT_NAME: 992 qsort( (void*)rArr.GetData(), 993 rArr.Count(), 994 sizeof( SwSectionPtr ), 995 lcl_SectionCmpNm ); 996 break; 997 998 case SORTSECT_POS: 999 qsort( (void*)rArr.GetData(), 1000 rArr.Count(), 1001 sizeof( SwSectionPtr ), 1002 lcl_SectionCmpPos ); 1003 break; 1004 case SORTSECT_NOT: break; 1005 } 1006 } 1007 return rArr.Count(); 1008 } 1009 1010 // erfrage, ob sich die Section im Nodes-Array oder UndoNodes-Array 1011 // befindet. 1012 sal_Bool SwSectionFmt::IsInNodesArr() const 1013 { 1014 const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx(); 1015 return pIdx && &pIdx->GetNodes() == &GetDoc()->GetNodes(); 1016 } 1017 1018 1019 void SwSectionFmt::UpdateParent() // Parent wurde veraendert 1020 { 1021 if( !GetDepends() ) 1022 return; 1023 1024 SwSectionPtr pSection = 0; 1025 const SvxProtectItem* pProtect(0); 1026 // --> FME 2004-06-22 #114856# edit in readonly sections 1027 const SwFmtEditInReadonly* pEditInReadonly = 0; 1028 // <-- 1029 bool bIsHidden = false; 1030 1031 SwClientIter aIter( *this ); // TODO 1032 ::SwClient * pLast = aIter.GoStart(); 1033 if( pLast ) // konnte zum Anfang gesprungen werden ?? 1034 do { 1035 if( pLast->IsA( TYPE(SwSectionFmt) ) ) 1036 { 1037 if( !pSection ) 1038 { 1039 pSection = GetSection(); 1040 if( GetRegisteredIn() ) 1041 { 1042 const SwSectionPtr pPS = GetParentSection(); 1043 pProtect = &pPS->GetFmt()->GetProtect(); 1044 // --> FME 2004-06-22 #114856# edit in readonly sections 1045 pEditInReadonly = &pPS->GetFmt()->GetEditInReadonly(); 1046 // <-- 1047 bIsHidden = pPS->IsHiddenFlag(); 1048 } 1049 else 1050 { 1051 pProtect = &GetProtect(); 1052 // --> FME 2004-06-22 #114856# edit in readonly sections 1053 pEditInReadonly = &GetEditInReadonly(); 1054 // <-- 1055 bIsHidden = pSection->IsHidden(); 1056 } 1057 } 1058 if (!pProtect->IsCntntProtected() != 1059 !pSection->IsProtectFlag()) 1060 { 1061 pLast->ModifyNotification( (SfxPoolItem*)pProtect, 1062 (SfxPoolItem*)pProtect ); 1063 } 1064 1065 // --> FME 2004-06-22 #114856# edit in readonly sections 1066 if (!pEditInReadonly->GetValue() != 1067 !pSection->IsEditInReadonlyFlag()) 1068 { 1069 pLast->ModifyNotification( (SfxPoolItem*)pEditInReadonly, 1070 (SfxPoolItem*)pEditInReadonly ); 1071 } 1072 // <-- 1073 1074 if( bIsHidden == pSection->IsHiddenFlag() ) 1075 { 1076 SwMsgPoolItem aMsgItem( static_cast<sal_uInt16>(bIsHidden 1077 ? RES_SECTION_HIDDEN 1078 : RES_SECTION_NOT_HIDDEN ) ); 1079 pLast->ModifyNotification( &aMsgItem, &aMsgItem ); 1080 } 1081 } 1082 else if( !pSection && 1083 pLast->IsA( TYPE(SwSection) ) ) 1084 { 1085 pSection = (SwSectionPtr)pLast; 1086 if( GetRegisteredIn() ) 1087 { 1088 const SwSectionPtr pPS = GetParentSection(); 1089 pProtect = &pPS->GetFmt()->GetProtect(); 1090 // --> FME 2004-06-22 #114856# edit in readonly sections 1091 pEditInReadonly = &pPS->GetFmt()->GetEditInReadonly(); 1092 // <-- 1093 bIsHidden = pPS->IsHiddenFlag(); 1094 } 1095 else 1096 { 1097 pProtect = &GetProtect(); 1098 // --> FME 2004-06-22 #114856# edit in readonly sections 1099 pEditInReadonly = &GetEditInReadonly(); 1100 // <-- 1101 bIsHidden = pSection->IsHidden(); 1102 } 1103 } 1104 } while( 0 != ( pLast = aIter++ )); 1105 } 1106 1107 1108 SwSectionNode* SwSectionFmt::GetSectionNode(bool const bAlways) 1109 { 1110 const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx(); 1111 if( pIdx && ( bAlways || &pIdx->GetNodes() == &GetDoc()->GetNodes() )) 1112 return pIdx->GetNode().GetSectionNode(); 1113 return 0; 1114 } 1115 1116 // ist die Section eine gueltige fuers GlobalDocument? 1117 const SwSection* SwSectionFmt::GetGlobalDocSection() const 1118 { 1119 const SwSectionNode* pNd = GetSectionNode(); 1120 if( pNd && 1121 ( FILE_LINK_SECTION == pNd->GetSection().GetType() || 1122 TOX_CONTENT_SECTION == pNd->GetSection().GetType() ) && 1123 pNd->GetIndex() > pNd->GetNodes().GetEndOfExtras().GetIndex() && 1124 !pNd->StartOfSectionNode()->IsSectionNode() && 1125 !pNd->StartOfSectionNode()->FindSectionNode() ) 1126 return &pNd->GetSection(); 1127 return 0; 1128 } 1129 1130 // sw::Metadatable 1131 ::sfx2::IXmlIdRegistry& SwSectionFmt::GetRegistry() 1132 { 1133 return GetDoc()->GetXmlIdRegistry(); 1134 } 1135 1136 bool SwSectionFmt::IsInClipboard() const 1137 { 1138 return GetDoc()->IsClipBoard(); 1139 } 1140 1141 bool SwSectionFmt::IsInUndo() const 1142 { 1143 return !IsInNodesArr(); 1144 } 1145 1146 bool SwSectionFmt::IsInContent() const 1147 { 1148 SwNodeIndex const*const pIdx = GetCntnt(sal_False).GetCntntIdx(); 1149 OSL_ENSURE(pIdx, "SwSectionFmt::IsInContent: no index?"); 1150 return (pIdx) ? !GetDoc()->IsInHeaderFooter(*pIdx) : true; 1151 } 1152 1153 // n.b.: if the section format represents an index, then there is both a 1154 // SwXDocumentIndex and a SwXTextSection instance for this single core object. 1155 // these two can both implement XMetadatable and forward to the same core 1156 // section format. but here only one UNO object can be returned, 1157 // so always return the text section. 1158 uno::Reference< rdf::XMetadatable > 1159 SwSectionFmt::MakeUnoObject() 1160 { 1161 uno::Reference<rdf::XMetadatable> xMeta; 1162 SwSection *const pSection( GetSection() ); 1163 if (pSection) 1164 { 1165 xMeta.set( SwXTextSection::CreateXTextSection(this, 1166 TOX_HEADER_SECTION == pSection->GetType()), 1167 uno::UNO_QUERY ); 1168 } 1169 return xMeta; 1170 } 1171 1172 1173 // --> OD 2007-02-14 #b6521322# 1174 // Method to break section links inside a linked section 1175 void lcl_BreakSectionLinksInSect( const SwSectionNode& rSectNd ) 1176 { 1177 if ( !rSectNd.GetDoc() ) 1178 { 1179 ASSERT( false, 1180 "method <lcl_RemoveSectionLinksInSect(..)> - no Doc at SectionNode" ); 1181 return; 1182 } 1183 1184 if ( !rSectNd.GetSection().IsConnected() ) 1185 { 1186 ASSERT( false, 1187 "method <lcl_RemoveSectionLinksInSect(..)> - no Link at Section of SectionNode" ); 1188 return; 1189 } 1190 const ::sfx2::SvBaseLink* pOwnLink( &(rSectNd.GetSection().GetBaseLink() ) ); 1191 const ::sfx2::SvBaseLinks& rLnks = rSectNd.GetDoc()->GetLinkManager().GetLinks(); 1192 for ( sal_uInt16 n = rLnks.Count(); n > 0; ) 1193 { 1194 SwIntrnlSectRefLink* pSectLnk = dynamic_cast<SwIntrnlSectRefLink*>(&(*rLnks[ --n ])); 1195 if ( pSectLnk && pSectLnk != pOwnLink && 1196 pSectLnk->IsInRange( rSectNd.GetIndex(), rSectNd.EndOfSectionIndex() ) ) 1197 { 1198 // break the link of the corresponding section. 1199 // the link is also removed from the link manager 1200 pSectLnk->GetSectNode()->GetSection().BreakLink(); 1201 1202 // for robustness, because link is removed from the link manager 1203 if ( n > rLnks.Count() ) 1204 { 1205 n = rLnks.Count(); 1206 } 1207 } 1208 } 1209 } 1210 // <-- 1211 1212 void lcl_UpdateLinksInSect( SwBaseLink& rUpdLnk, SwSectionNode& rSectNd ) 1213 { 1214 SwDoc* pDoc = rSectNd.GetDoc(); 1215 SwDocShell* pDShell = pDoc->GetDocShell(); 1216 if( !pDShell || !pDShell->GetMedium() ) 1217 return ; 1218 1219 String sName( pDShell->GetMedium()->GetName() ); 1220 SwBaseLink* pBLink; 1221 String sMimeType( SotExchange::GetFormatMimeType( FORMAT_FILE )); 1222 uno::Any aValue; 1223 aValue <<= ::rtl::OUString( sName ); // beliebiger Name 1224 1225 const ::sfx2::SvBaseLinks& rLnks = pDoc->GetLinkManager().GetLinks(); 1226 for( sal_uInt16 n = rLnks.Count(); n; ) 1227 { 1228 ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]); 1229 if( pLnk && pLnk != &rUpdLnk && 1230 OBJECT_CLIENT_FILE == pLnk->GetObjType() && 1231 pLnk->ISA( SwBaseLink ) && 1232 ( pBLink = (SwBaseLink*)pLnk )->IsInRange( rSectNd.GetIndex(), 1233 rSectNd.EndOfSectionIndex() ) ) 1234 { 1235 // liegt in dem Bereich: also updaten. Aber nur wenns nicht 1236 // im gleichen File liegt 1237 String sFName; 1238 pDoc->GetLinkManager().GetDisplayNames( pBLink, 0, &sFName, 0, 0 ); 1239 if( sFName != sName ) 1240 { 1241 pBLink->DataChanged( sMimeType, aValue ); 1242 1243 // ggfs. neu den Link-Pointer wieder suchen, damit nicht einer 1244 // ausgelassen oder doppelt gerufen wird. 1245 if( n >= rLnks.Count() && 0 != ( n = rLnks.Count() )) 1246 --n; 1247 1248 if( n && pLnk != &(*rLnks[ n ]) ) 1249 { 1250 // suchen - kann nur davor liegen!! 1251 while( n ) 1252 if( pLnk == &(*rLnks[ --n ] ) ) 1253 break; 1254 } 1255 } 1256 } 1257 } 1258 } 1259 1260 1261 // sucht sich die richtige DocShell raus oder erzeugt eine neue: 1262 // Der Return-Wert gibt an, was mit der Shell zu geschehen hat: 1263 // 0 - Fehler, konnte DocShell nicht finden 1264 // 1 - DocShell ist ein existieren Document 1265 // 2 - DocShell wurde neu angelegt, muss also wieder geschlossen werden ( will be assigned to xLockRef additionaly ) 1266 1267 int lcl_FindDocShell( SfxObjectShellRef& xDocSh, 1268 SfxObjectShellLock& xLockRef, 1269 const String& rFileName, 1270 const String& rPasswd, 1271 String& rFilter, 1272 sal_Int16 nVersion, 1273 SwDocShell* pDestSh ) 1274 { 1275 if( !rFileName.Len() ) 1276 return 0; 1277 1278 // 1. existiert die Datei schon in der Liste aller Dokumente? 1279 INetURLObject aTmpObj( rFileName ); 1280 aTmpObj.SetMark( aEmptyStr ); 1281 1282 // erstmal nur ueber die DocumentShells laufen und die mit dem 1283 // Namen heraussuchen: 1284 TypeId aType( TYPE(SwDocShell) ); 1285 1286 SfxObjectShell* pShell = pDestSh; 1287 sal_Bool bFirst = 0 != pShell; 1288 1289 if( !bFirst ) 1290 // keine DocShell uebergeben, also beginne mit der ersten aus der 1291 // DocShell Liste 1292 pShell = SfxObjectShell::GetFirst( &aType ); 1293 1294 while( pShell ) 1295 { 1296 // die wollen wir haben 1297 SfxMedium* pMed = pShell->GetMedium(); 1298 if( pMed && pMed->GetURLObject() == aTmpObj ) 1299 { 1300 const SfxPoolItem* pItem; 1301 if( ( SFX_ITEM_SET == pMed->GetItemSet()->GetItemState( 1302 SID_VERSION, sal_False, &pItem ) ) 1303 ? (nVersion == ((SfxInt16Item*)pItem)->GetValue()) 1304 : !nVersion ) 1305 { 1306 // gefunden also returnen 1307 xDocSh = pShell; 1308 return 1; 1309 } 1310 } 1311 1312 if( bFirst ) 1313 { 1314 bFirst = sal_False; 1315 pShell = SfxObjectShell::GetFirst( &aType ); 1316 } 1317 else 1318 pShell = SfxObjectShell::GetNext( *pShell, &aType ); 1319 } 1320 1321 // 2. selbst die Date oeffnen 1322 SfxMedium* pMed = new SfxMedium( aTmpObj.GetMainURL( 1323 INetURLObject::NO_DECODE ), STREAM_READ, sal_True ); 1324 if( INET_PROT_FILE == aTmpObj.GetProtocol() ) 1325 pMed->DownLoad(); // nur mal das Medium anfassen (DownLoaden) 1326 1327 const SfxFilter* pSfxFlt = 0; 1328 if( !pMed->GetError() ) 1329 { 1330 String sFactory(String::CreateFromAscii(SwDocShell::Factory().GetShortName())); 1331 SfxFilterMatcher aMatcher( sFactory ); 1332 1333 // kein Filter, dann suche ihn. Ansonsten teste, ob der angegebene 1334 // ein gueltiger ist 1335 if( rFilter.Len() ) 1336 { 1337 pSfxFlt = aMatcher.GetFilter4FilterName( rFilter ); 1338 } 1339 1340 if( nVersion ) 1341 pMed->GetItemSet()->Put( SfxInt16Item( SID_VERSION, nVersion )); 1342 1343 if( rPasswd.Len() ) 1344 pMed->GetItemSet()->Put( SfxStringItem( SID_PASSWORD, rPasswd )); 1345 1346 if( !pSfxFlt ) 1347 aMatcher.DetectFilter( *pMed, &pSfxFlt, sal_False, sal_False ); 1348 1349 if( pSfxFlt ) 1350 { 1351 // ohne Filter geht gar nichts 1352 pMed->SetFilter( pSfxFlt ); 1353 1354 // if the new shell is created, SfxObjectShellLock should be used to let it be closed later for sure 1355 xLockRef = new SwDocShell( SFX_CREATE_MODE_INTERNAL ); 1356 xDocSh = (SfxObjectShell*)xLockRef; 1357 if( xDocSh->DoLoad( pMed ) ) 1358 return 2; 1359 } 1360 } 1361 1362 if( !xDocSh.Is() ) // Medium muss noch geloescht werden 1363 delete pMed; 1364 1365 return 0; // das war wohl nichts 1366 } 1367 1368 1369 void SwIntrnlSectRefLink::DataChanged( const String& rMimeType, 1370 const uno::Any & rValue ) 1371 { 1372 SwSectionNode* pSectNd = rSectFmt.GetSectionNode( sal_False ); 1373 SwDoc* pDoc = rSectFmt.GetDoc(); 1374 1375 sal_uLong nDataFormat = SotExchange::GetFormatIdFromMimeType( rMimeType ); 1376 1377 if( !pSectNd || !pDoc || pDoc->IsInDtor() || ChkNoDataFlag() || 1378 sfx2::LinkManager::RegisterStatusInfoId() == nDataFormat ) 1379 { 1380 // sollten wir schon wieder im Undo stehen? 1381 return ; 1382 } 1383 1384 // --> OD 2005-02-11 #i38810# - Due to possible existing signatures, the 1385 // document has to be modified after updating a link. 1386 pDoc->SetModified(); 1387 // set additional flag that links have been updated, in order to check this 1388 // during load. 1389 pDoc->SetLinksUpdated( sal_True ); 1390 // <-- 1391 1392 // Undo immer abschalten 1393 bool const bWasUndo = pDoc->GetIDocumentUndoRedo().DoesUndo(); 1394 pDoc->GetIDocumentUndoRedo().DoUndo(false); 1395 sal_Bool bWasVisibleLinks = pDoc->IsVisibleLinks(); 1396 pDoc->SetVisibleLinks( sal_False ); 1397 1398 SwPaM* pPam; 1399 ViewShell* pVSh = 0; 1400 SwEditShell* pESh = pDoc->GetEditShell( &pVSh ); 1401 pDoc->LockExpFlds(); 1402 { 1403 // am Anfang des Bereichs einen leeren TextNode einfuegen 1404 SwNodeIndex aIdx( *pSectNd, +1 ); 1405 SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() ); 1406 SwTxtNode* pNewNd = pDoc->GetNodes().MakeTxtNode( aIdx, 1407 pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT ) ); 1408 1409 if( pESh ) 1410 pESh->StartAllAction(); 1411 else if( pVSh ) 1412 pVSh->StartAction(); 1413 1414 SwPosition aPos( aIdx, SwIndex( pNewNd, 0 )); 1415 aPos.nNode--; 1416 pDoc->CorrAbs( aIdx, aEndIdx, aPos, sal_True ); 1417 1418 pPam = new SwPaM( aPos ); 1419 1420 //und alles dahinter liegende loeschen 1421 aIdx--; 1422 DelFlyInRange( aIdx, aEndIdx ); 1423 _DelBookmarks(aIdx, aEndIdx); 1424 aIdx++; 1425 1426 pDoc->GetNodes().Delete( aIdx, aEndIdx.GetIndex() - aIdx.GetIndex() ); 1427 } 1428 1429 SwSection& rSection = pSectNd->GetSection(); 1430 rSection.SetConnectFlag(false); 1431 1432 ::rtl::OUString sNewFileName; 1433 Reader* pRead = 0; 1434 switch( nDataFormat ) 1435 { 1436 case FORMAT_STRING: 1437 pRead = ReadAscii; 1438 break; 1439 1440 case FORMAT_RTF: 1441 pRead = SwReaderWriter::GetReader( READER_WRITER_RTF ); 1442 break; 1443 1444 case FORMAT_FILE: 1445 if( rValue.hasValue() && ( rValue >>= sNewFileName ) ) 1446 { 1447 String sFilter, sRange, sFileName( sNewFileName ); 1448 pDoc->GetLinkManager().GetDisplayNames( this, 0, &sFileName, 1449 &sRange, &sFilter ); 1450 1451 RedlineMode_t eOldRedlineMode = nsRedlineMode_t::REDLINE_NONE; 1452 SfxObjectShellRef xDocSh; 1453 SfxObjectShellLock xLockRef; 1454 int nRet; 1455 if( !sFileName.Len() ) 1456 { 1457 xDocSh = pDoc->GetDocShell(); 1458 nRet = 1; 1459 } 1460 else 1461 { 1462 nRet = lcl_FindDocShell( xDocSh, xLockRef, sFileName, 1463 rSection.GetLinkFilePassword(), 1464 sFilter, 0, pDoc->GetDocShell() ); 1465 if( nRet ) 1466 { 1467 SwDoc* pSrcDoc = ((SwDocShell*)&xDocSh)->GetDoc(); 1468 eOldRedlineMode = pSrcDoc->GetRedlineMode(); 1469 pSrcDoc->SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_INSERT ); 1470 } 1471 } 1472 1473 if( nRet ) 1474 { 1475 rSection.SetConnectFlag(true); 1476 1477 SwNodeIndex aSave( pPam->GetPoint()->nNode, -1 ); 1478 SwNodeRange* pCpyRg = 0; 1479 1480 if( xDocSh->GetMedium() && 1481 !rSection.GetLinkFilePassword().Len() ) 1482 { 1483 const SfxPoolItem* pItem; 1484 if( SFX_ITEM_SET == xDocSh->GetMedium()->GetItemSet()-> 1485 GetItemState( SID_PASSWORD, sal_False, &pItem ) ) 1486 rSection.SetLinkFilePassword( 1487 ((SfxStringItem*)pItem)->GetValue() ); 1488 } 1489 1490 SwDoc* pSrcDoc = ((SwDocShell*)&xDocSh)->GetDoc(); 1491 1492 if( sRange.Len() ) 1493 { 1494 // Rekursionen abfangen 1495 sal_Bool bRecursion = sal_False; 1496 if( pSrcDoc == pDoc ) 1497 { 1498 SwServerObjectRef refObj( (SwServerObject*) 1499 pDoc->CreateLinkSource( sRange )); 1500 if( refObj.Is() ) 1501 { 1502 bRecursion = refObj->IsLinkInServer( this ) || 1503 ChkNoDataFlag(); 1504 } 1505 } 1506 1507 SwNodeIndex& rInsPos = pPam->GetPoint()->nNode; 1508 1509 SwPaM* pCpyPam = 0; 1510 if( !bRecursion && 1511 pSrcDoc->SelectServerObj( sRange, pCpyPam, pCpyRg ) 1512 && pCpyPam ) 1513 { 1514 if( pSrcDoc != pDoc || 1515 pCpyPam->Start()->nNode > rInsPos || 1516 rInsPos >= pCpyPam->End()->nNode ) 1517 { 1518 pSrcDoc->CopyRange( *pCpyPam, *pPam->GetPoint(), 1519 false ); 1520 } 1521 delete pCpyPam; 1522 } 1523 if( pCpyRg && pSrcDoc == pDoc && 1524 pCpyRg->aStart < rInsPos && rInsPos < pCpyRg->aEnd ) 1525 delete pCpyRg, pCpyRg = 0; 1526 } 1527 else if( pSrcDoc != pDoc ) 1528 pCpyRg = new SwNodeRange( pSrcDoc->GetNodes().GetEndOfExtras(), 2, 1529 pSrcDoc->GetNodes().GetEndOfContent() ); 1530 1531 // --> OD 2007-11-30 #i81653# 1532 // Update links of extern linked document or extern linked 1533 // document section, if section is protected. 1534 if ( pSrcDoc != pDoc && 1535 rSection.IsProtectFlag() ) 1536 { 1537 pSrcDoc->GetLinkManager().UpdateAllLinks( sal_False, sal_True, sal_False, 0 ); 1538 } 1539 // <-- 1540 if( pCpyRg ) 1541 { 1542 SwNodeIndex& rInsPos = pPam->GetPoint()->nNode; 1543 sal_Bool bCreateFrm = rInsPos.GetIndex() <= 1544 pDoc->GetNodes().GetEndOfExtras().GetIndex() || 1545 rInsPos.GetNode().FindTableNode(); 1546 1547 SwTblNumFmtMerge aTNFM( *pSrcDoc, *pDoc ); 1548 1549 pSrcDoc->CopyWithFlyInFly( *pCpyRg, 0, rInsPos, bCreateFrm ); 1550 aSave++; 1551 1552 if( !bCreateFrm ) 1553 ::MakeFrms( pDoc, aSave, rInsPos ); 1554 1555 // den letzten Node noch loeschen, aber nur wenn 1556 // erfolgreich kopiert werden konnte, also der Bereich 1557 // mehr als 1 Node enthaelt 1558 if( 2 < pSectNd->EndOfSectionIndex() - pSectNd->GetIndex() ) 1559 { 1560 aSave = rInsPos; 1561 pPam->Move( fnMoveBackward, fnGoNode ); 1562 pPam->SetMark(); // beide SwPositions ummelden! 1563 1564 pDoc->CorrAbs( aSave, *pPam->GetPoint(), 0, sal_True ); 1565 pDoc->GetNodes().Delete( aSave, 1 ); 1566 } 1567 delete pCpyRg; 1568 } 1569 1570 // --> OD 2007-02-14 #b6521322# 1571 lcl_BreakSectionLinksInSect( *pSectNd ); 1572 // <-- 1573 1574 // update alle Links in diesem Bereich 1575 lcl_UpdateLinksInSect( *this, *pSectNd ); 1576 } 1577 if( xDocSh.Is() ) 1578 { 1579 if( 2 == nRet ) 1580 xDocSh->DoClose(); 1581 else if( ((SwDocShell*)&xDocSh)->GetDoc() ) 1582 ((SwDocShell*)&xDocSh)->GetDoc()->SetRedlineMode( 1583 eOldRedlineMode ); 1584 } 1585 } 1586 break; 1587 } 1588 1589 // !!!! DDE nur updaten wenn Shell vorhanden ist?? 1590 uno::Sequence< sal_Int8 > aSeq; 1591 if( pRead && rValue.hasValue() && ( rValue >>= aSeq ) ) 1592 { 1593 if( pESh ) 1594 { 1595 pESh->Push(); 1596 SwPaM* pCrsr = pESh->GetCrsr(); 1597 *pCrsr->GetPoint() = *pPam->GetPoint(); 1598 delete pPam; 1599 pPam = pCrsr; 1600 } 1601 1602 SvMemoryStream aStrm( (void*)aSeq.getConstArray(), aSeq.getLength(), 1603 STREAM_READ ); 1604 aStrm.Seek( 0 ); 1605 1606 #if OSL_DEBUG_LEVEL > 1 1607 { 1608 SvFileStream aDeb( String::CreateFromAscii( 1609 "file:///d|/temp/update.txt" ), STREAM_WRITE ); 1610 aDeb << aStrm; 1611 } 1612 aStrm.Seek( 0 ); 1613 #endif 1614 1615 // TODO/MBA: it's impossible to set a BaseURL here! 1616 SwReader aTmpReader( aStrm, aEmptyStr, pDoc->GetDocShell()->GetMedium()->GetBaseURL(), *pPam ); 1617 1618 if( !IsError( aTmpReader.Read( *pRead ) )) 1619 { 1620 rSection.SetConnectFlag(true); 1621 } 1622 1623 if( pESh ) 1624 { 1625 pESh->Pop( sal_False ); 1626 pPam = 0; // pam is deleted before 1627 } 1628 } 1629 1630 1631 // remove all undo actions and turn undo on again 1632 pDoc->GetIDocumentUndoRedo().DelAllUndoObj(); 1633 pDoc->GetIDocumentUndoRedo().DoUndo(bWasUndo); 1634 pDoc->SetVisibleLinks( bWasVisibleLinks ); 1635 1636 pDoc->UnlockExpFlds(); 1637 if( !pDoc->IsExpFldsLocked() ) 1638 pDoc->UpdateExpFlds(NULL, true); 1639 1640 if( pESh ) 1641 pESh->EndAllAction(); 1642 else if( pVSh ) 1643 pVSh->EndAction(); 1644 delete pPam; // wurde am Anfang angelegt 1645 } 1646 1647 1648 void SwIntrnlSectRefLink::Closed() 1649 { 1650 SwDoc* pDoc = rSectFmt.GetDoc(); 1651 if( pDoc && !pDoc->IsInDtor() ) 1652 { 1653 // Advise verabschiedet sich, den Bereich als nicht geschuetzt 1654 // kennzeichnen und das Flag umsetzen 1655 1656 const SwSectionFmts& rFmts = pDoc->GetSections(); 1657 for( sal_uInt16 n = rFmts.Count(); n; ) 1658 if( rFmts[ --n ] == &rSectFmt ) 1659 { 1660 ViewShell* pSh; 1661 SwEditShell* pESh = pDoc->GetEditShell( &pSh ); 1662 1663 if( pESh ) 1664 pESh->StartAllAction(); 1665 else 1666 pSh->StartAction(); 1667 1668 SwSectionData aSectionData(*rSectFmt.GetSection()); 1669 aSectionData.SetType( CONTENT_SECTION ); 1670 aSectionData.SetLinkFileName( aEmptyStr ); 1671 aSectionData.SetHidden( false ); 1672 aSectionData.SetProtectFlag( false ); 1673 // --> FME 2004-06-22 #114856# edit in readonly sections 1674 aSectionData.SetEditInReadonlyFlag( false ); 1675 // <-- 1676 1677 aSectionData.SetConnectFlag( false ); 1678 1679 pDoc->UpdateSection( n, aSectionData ); 1680 1681 // alle in der Section liegenden Links werden sichtbar 1682 SwSectionNode* pSectNd = rSectFmt.GetSectionNode( sal_False ); 1683 if( pSectNd ) 1684 pSectNd->GetSection().MakeChildLinksVisible( *pSectNd ); 1685 1686 if( pESh ) 1687 pESh->EndAllAction(); 1688 else 1689 pSh->EndAction(); 1690 break; 1691 } 1692 } 1693 SvBaseLink::Closed(); 1694 } 1695 1696 1697 void SwSection::CreateLink( LinkCreateType eCreateType ) 1698 { 1699 SwSectionFmt* pFmt = GetFmt(); 1700 ASSERT(pFmt, "SwSection::CreateLink: no format?"); 1701 if (!pFmt || (CONTENT_SECTION == m_Data.GetType())) 1702 return ; 1703 1704 sal_uInt16 nUpdateType = sfx2::LINKUPDATE_ALWAYS; 1705 1706 if (!m_RefLink.Is()) 1707 { 1708 // create BaseLink 1709 m_RefLink = new SwIntrnlSectRefLink( *pFmt, nUpdateType, FORMAT_RTF ); 1710 } 1711 else 1712 { 1713 pFmt->GetDoc()->GetLinkManager().Remove( m_RefLink ); 1714 } 1715 1716 SwIntrnlSectRefLink *const pLnk = 1717 static_cast<SwIntrnlSectRefLink*>(& m_RefLink); 1718 1719 String sCmd( m_Data.GetLinkFileName() ); 1720 xub_StrLen nPos; 1721 while( STRING_NOTFOUND != (nPos = sCmd.SearchAscii( " " )) ) 1722 sCmd.Erase( nPos, 1 ); 1723 1724 pLnk->SetUpdateMode( nUpdateType ); 1725 pLnk->SetVisible( pFmt->GetDoc()->IsVisibleLinks() ); 1726 1727 switch (m_Data.GetType()) 1728 { 1729 case DDE_LINK_SECTION: 1730 pLnk->SetLinkSourceName( sCmd ); 1731 pFmt->GetDoc()->GetLinkManager().InsertDDELink( pLnk ); 1732 break; 1733 case FILE_LINK_SECTION: 1734 { 1735 pLnk->SetContentType( FORMAT_FILE ); 1736 String sFltr( sCmd.GetToken( 1, sfx2::cTokenSeperator ) ); 1737 String sRange( sCmd.GetToken( 2, sfx2::cTokenSeperator ) ); 1738 pFmt->GetDoc()->GetLinkManager().InsertFileLink( *pLnk, 1739 static_cast<sal_uInt16>(m_Data.GetType()), 1740 sCmd.GetToken( 0, sfx2::cTokenSeperator ), 1741 ( sFltr.Len() ? &sFltr : 0 ), 1742 ( sRange.Len() ? &sRange : 0 ) ); 1743 } 1744 break; 1745 default: 1746 ASSERT( !this, "Was ist das fuer ein Link?" ) 1747 } 1748 1749 switch( eCreateType ) 1750 { 1751 case CREATE_CONNECT: // Link gleich connecten 1752 pLnk->Connect(); 1753 break; 1754 1755 case CREATE_UPDATE: // Link connecten und updaten 1756 pLnk->Update(); 1757 break; 1758 case CREATE_NONE: break; 1759 } 1760 } 1761 1762 // --> OD 2007-02-14 #b6521322# 1763 void SwSection::BreakLink() 1764 { 1765 const SectionType eCurrentType( GetType() ); 1766 if ( eCurrentType == CONTENT_SECTION || 1767 eCurrentType == TOX_HEADER_SECTION || 1768 eCurrentType == TOX_CONTENT_SECTION ) 1769 { 1770 // nothing to do 1771 return; 1772 } 1773 1774 // release link, if it exists 1775 if (m_RefLink.Is()) 1776 { 1777 SwSectionFmt *const pFormat( GetFmt() ); 1778 ASSERT(pFormat, "SwSection::BreakLink: no format?"); 1779 if (pFormat) 1780 { 1781 pFormat->GetDoc()->GetLinkManager().Remove( m_RefLink ); 1782 } 1783 m_RefLink.Clear(); 1784 } 1785 // change type 1786 SetType( CONTENT_SECTION ); 1787 // reset linked file data 1788 SetLinkFileName( aEmptyStr ); 1789 SetLinkFilePassword( aEmptyStr ); 1790 } 1791 // <-- 1792 1793 const SwNode* SwIntrnlSectRefLink::GetAnchor() const 1794 { 1795 return rSectFmt.GetSectionNode( sal_False ); 1796 } 1797 1798 1799 sal_Bool SwIntrnlSectRefLink::IsInRange( sal_uLong nSttNd, sal_uLong nEndNd, 1800 xub_StrLen , xub_StrLen ) const 1801 { 1802 SwStartNode* pSttNd = rSectFmt.GetSectionNode( sal_False ); 1803 return pSttNd && 1804 nSttNd < pSttNd->GetIndex() && 1805 pSttNd->EndOfSectionIndex() < nEndNd; 1806 } 1807 1808 1809 1810