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