Update ooo320-m1
[ooovba.git] / sw / source / core / docnode / section.cxx
blob23dffa13acf09618f3375c880193293ec1ff62e6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: section.cxx,v $
10 * $Revision: 1.31 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <stdlib.h>
36 #include <hintids.hxx>
37 #include <svtools/intitem.hxx>
38 #include <svtools/stritem.hxx>
39 #include <sfx2/docfile.hxx>
40 #include <sfx2/docfilt.hxx>
41 #include <svx/protitem.hxx>
42 #include <svx/linkmgr.hxx>
43 #include <tools/urlobj.hxx>
45 #include <sfx2/sfxsids.hrc>
46 #include <sfx2/fcontnr.hxx>
47 #include <docary.hxx>
48 #include <fmtcntnt.hxx>
49 #include <fmtpdsc.hxx>
50 #include <errhdl.hxx>
51 #include <doc.hxx>
52 #include <node.hxx>
53 #include <pam.hxx>
54 #include <frmtool.hxx>
55 #include <editsh.hxx>
56 #include <hints.hxx>
57 #ifndef _DOCSH_HXX
58 #include <docsh.hxx>
59 #endif
60 #include <ndtxt.hxx>
61 #include <section.hxx>
62 #include <swserv.hxx>
63 #include <shellio.hxx>
64 #include <poolfmt.hxx>
65 #include <expfld.hxx>
66 #include <swbaslnk.hxx>
67 #include <mvsave.hxx>
68 #include <sectfrm.hxx>
69 #include <fmtftntx.hxx>
70 #include <ftnidx.hxx>
71 #include <doctxm.hxx>
72 // --> FME 2004-06-22 #114856# edit in readonly sections
73 #include <fmteiro.hxx>
74 // <--
75 #include <swerror.h>
77 using namespace ::com::sun::star;
80 SV_IMPL_REF( SwServerObject )
82 //static const char __FAR_DATA sSectionFmtNm[] = "Section";
83 #define sSectionFmtNm aEmptyStr
85 class SwIntrnlSectRefLink : public SwBaseLink
87 SwSectionFmt& rSectFmt;
88 public:
89 SwIntrnlSectRefLink( SwSectionFmt& rFmt, USHORT nUpdateType, USHORT nFmt )
90 : SwBaseLink( nUpdateType, nFmt ),
91 rSectFmt( rFmt )
94 virtual void Closed();
95 virtual void DataChanged( const String& rMimeType,
96 const uno::Any & rValue );
98 virtual const SwNode* GetAnchor() const;
99 virtual BOOL IsInRange( ULONG nSttNd, ULONG nEndNd, xub_StrLen nStt = 0,
100 xub_StrLen nEnd = STRING_NOTFOUND ) const;
102 // --> OD 2007-02-14 #b6521322#
103 inline SwSectionNode* GetSectNode()
105 const SwNode* pSectNd( const_cast<SwIntrnlSectRefLink*>(this)->GetAnchor() );
106 return const_cast<SwSectionNode*>( dynamic_cast<const SwSectionNode*>( pSectNd ) );
108 // <--
112 TYPEINIT1(SwSectionFmt,SwFrmFmt );
113 TYPEINIT1(SwSection,SwClient );
115 typedef SwSection* SwSectionPtr;
117 SV_IMPL_PTRARR( SwSections, SwSection*)
118 SV_IMPL_PTRARR(SwSectionFmts,SwSectionFmt*)
122 SwSection::SwSection( SectionType eTyp, const String& rName,
123 SwSectionFmt* pFmt )
124 : SwClient( pFmt ), sSectionNm( rName ),
125 eType( eTyp )
127 bHidden = FALSE;
128 bHiddenFlag = FALSE;
129 bProtectFlag = FALSE;
130 // --> FME 2004-06-22 #114856# edit in readonly sections
131 bEditInReadonlyFlag = FALSE;
132 // <--
133 bCondHiddenFlag = TRUE;
134 bConnectFlag = TRUE;
136 SwSectionPtr pParentSect = GetParent();
137 if( pParentSect )
139 if( pParentSect->IsHiddenFlag() )
140 SetHidden( TRUE );
142 _SetProtectFlag( pParentSect->IsProtectFlag() );
143 // --> FME 2004-06-22 #114856# edit in readonly sections
144 _SetEditInReadonlyFlag( pParentSect->IsEditInReadonlyFlag() );
145 // <--
148 if( pFmt && !bProtectFlag )
149 _SetProtectFlag( pFmt->GetProtect().IsCntntProtected() );
151 // --> FME 2004-06-22 #114856# edit in readonly sections
152 if ( pFmt && !bEditInReadonlyFlag )
153 _SetEditInReadonlyFlag( pFmt->GetEditInReadonly().GetValue() );
154 // <--
158 SwSection::~SwSection()
160 SwSectionFmt* pFmt = GetFmt();
161 if( !pFmt )
162 return;
164 SwDoc* pDoc = pFmt->GetDoc();
165 if( pDoc->IsInDtor() )
167 // dann melden wir noch schnell unser Format um ans dflt FrameFmt,
168 // damit es keine Abhaengigkeiten gibt
169 if( pFmt->DerivedFrom() != pDoc->GetDfltFrmFmt() )
170 pDoc->GetDfltFrmFmt()->Add( pFmt );
172 else
174 pFmt->Remove( this ); // austragen,
176 if( CONTENT_SECTION != eType ) // den Link austragen
177 pDoc->GetLinkManager().Remove( refLink );
179 if( refObj.Is() ) // als Server austragen
180 pDoc->GetLinkManager().RemoveServer( &refObj );
182 // ist die Section der letzte Client im Format, kann dieses
183 // geloescht werden
184 SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFmt );
185 pFmt->Modify( &aMsgHint, &aMsgHint );
186 if( !pFmt->GetDepends() )
188 // Bug: 28191 - nicht ins Undo aufnehmen, sollte schon vorher
189 // geschehen sein!!
190 BOOL bUndo = pDoc->DoesUndo();
191 pDoc->DoUndo( FALSE );
192 pDoc->DelSectionFmt( pFmt ); // und loeschen
193 pDoc->DoUndo( bUndo );
196 if( refObj.Is() )
197 refObj->Closed();
201 SwSection& SwSection::operator=( const SwSection& rCpy )
203 sSectionNm = rCpy.sSectionNm;
204 sCondition = rCpy.sCondition;
205 sLinkFileName = rCpy.GetLinkFileName();
206 SetLinkFilePassWd( rCpy.GetLinkFilePassWd() );
207 SetConnectFlag( rCpy.IsConnectFlag() );
208 SetPasswd( rCpy.GetPasswd() );
210 eType = rCpy.eType;
212 if( !GetFmt() )
214 SetProtect( rCpy.IsProtect() );
215 // --> FME 2004-06-22 #114856# edit in readonly sections
216 SetEditInReadonly( rCpy.IsEditInReadonly() );
217 // <--
219 else if( rCpy.GetFmt() )
221 _SetProtectFlag( rCpy.bProtectFlag );
222 // --> FME 2004-06-22 #114856# edit in readonly sections
223 _SetEditInReadonlyFlag( rCpy.bEditInReadonlyFlag );
224 // <--
226 else
228 SetProtect( rCpy.bProtectFlag );
229 // --> FME 2004-06-22 #114856# edit in readonly sections
230 SetEditInReadonly( rCpy.bEditInReadonlyFlag );
231 // <--
234 bCondHiddenFlag = TRUE; // sollte immer defaultet werden
235 SetHidden( rCpy.bHidden );
237 return *this;
241 BOOL SwSection::operator==( const SwSection& rCmp ) const
243 return sSectionNm == rCmp.sSectionNm &&
244 sCondition == rCmp.sCondition &&
245 eType == rCmp.eType &&
246 bHidden == rCmp.bHidden &&
247 IsProtect() == rCmp.IsProtect() &&
248 // --> FME 2004-06-22 #114856# edit in readonly sections
249 IsEditInReadonly() == rCmp.IsEditInReadonly() &&
250 // <--
251 GetLinkFileName() == rCmp.GetLinkFileName() &&
252 GetLinkFilePassWd() == rCmp.GetLinkFilePassWd() &&
253 GetPasswd() == rCmp.GetPasswd() &&
254 ( !GetFmt() || !rCmp.GetFmt() || GetFmt() == rCmp.GetFmt());
258 void SwSection::_SetHiddenFlag( BOOL bTmpHidden, BOOL bCondition )
260 SwSectionFmt* pFmt = GetFmt();
261 if( pFmt )
263 BOOL bHide = bTmpHidden && bCondition;
265 if( bHide ) // die Nodes also "verstecken"
267 if( !bHiddenFlag ) // ist nicht versteckt
269 // wie sieht es mit dem Parent aus, ist der versteckt ?
270 // (eigentlich muesste das vom bHiddenFlag angezeigt werden!)
272 // erstmal allen Childs sagen, das sie versteckt sind
273 SwMsgPoolItem aMsgItem( RES_SECTION_HIDDEN );
274 pFmt->Modify( &aMsgItem, &aMsgItem );
276 // alle Frames loeschen
277 pFmt->DelFrms();
280 else if( bHiddenFlag ) // die Nodes wieder anzeigen
282 // alle Frames sichtbar machen ( Childs Sections werden vom
283 // MakeFrms beruecksichtigt). Aber nur wenn die ParentSection
284 // nichts dagegen hat !
285 SwSection* pParentSect = pFmt->GetParentSection();
286 if( !pParentSect || !pParentSect->IsHiddenFlag() )
288 // erstmal allen Childs sagen, das der Parent nicht mehr
289 // versteckt ist
290 SwMsgPoolItem aMsgItem( RES_SECTION_NOT_HIDDEN );
291 pFmt->Modify( &aMsgItem, &aMsgItem );
293 pFmt->MakeFrms();
299 BOOL SwSection::CalcHiddenFlag() const
301 const SwSection* pSect = this;
302 do {
303 if( pSect->IsHidden() && pSect->IsCondHidden() )
304 return TRUE;
305 } while( 0 != ( pSect = pSect->GetParent()) );
307 return FALSE;
310 BOOL SwSection::_IsProtect() const
312 return GetFmt()->GetProtect().IsCntntProtected();
315 // --> FME 2004-06-22 #114856# edit in readonly sections
316 BOOL SwSection::_IsEditInReadonly() const
318 return GetFmt()->GetEditInReadonly().GetValue();
320 // <--
322 void SwSection::SetHidden( BOOL bFlag )
324 if( !bHidden == !bFlag )
325 return;
327 bHidden = bFlag;
328 _SetHiddenFlag( bHidden, bCondHiddenFlag );
332 void SwSection::SetProtect( BOOL bFlag )
334 if( GetFmt() )
336 SvxProtectItem aItem( RES_PROTECT );
337 aItem.SetCntntProtect( (BOOL)bFlag );
338 GetFmt()->SetFmtAttr( aItem );
340 else
341 bProtectFlag = bFlag;
344 // --> FME 2004-06-22 #114856# edit in readonly sections
345 void SwSection::SetEditInReadonly( BOOL bFlag )
347 if( GetFmt() )
349 SwFmtEditInReadonly aItem;
350 aItem.SetValue( (BOOL)bFlag );
351 GetFmt()->SetFmtAttr( aItem );
353 else
354 bEditInReadonlyFlag = bFlag;
356 // <--
358 void SwSection::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
360 BOOL bRemake = FALSE, bUpdateFtn = FALSE;
361 switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 )
363 case RES_ATTRSET_CHG:
365 SfxItemSet* pNewSet = ((SwAttrSetChg*)pNew)->GetChgSet();
366 SfxItemSet* pOldSet = ((SwAttrSetChg*)pOld)->GetChgSet();
367 const SfxPoolItem* pItem;
369 if( SFX_ITEM_SET == pNewSet->GetItemState(
370 RES_PROTECT, FALSE, &pItem ) )
372 _SetProtectFlag( ((SvxProtectItem*)pItem)->IsCntntProtected() );
373 pNewSet->ClearItem( RES_PROTECT );
374 pOldSet->ClearItem( RES_PROTECT );
377 // --> FME 2004-06-22 #114856# edit in readonly sections
378 if( SFX_ITEM_SET == pNewSet->GetItemState(
379 RES_EDIT_IN_READONLY, FALSE, &pItem ) )
381 _SetEditInReadonlyFlag( ((SwFmtEditInReadonly*)pItem)->GetValue() );
382 pNewSet->ClearItem( RES_EDIT_IN_READONLY );
383 pOldSet->ClearItem( RES_EDIT_IN_READONLY );
385 // <--
387 if( SFX_ITEM_SET == pNewSet->GetItemState(
388 RES_FTN_AT_TXTEND, FALSE, &pItem ) ||
389 SFX_ITEM_SET == pNewSet->GetItemState(
390 RES_END_AT_TXTEND, FALSE, &pItem ))
391 bUpdateFtn = TRUE;
393 if( !pNewSet->Count() )
394 return;
396 break;
398 case RES_PROTECT:
399 if( pNew )
401 BOOL bNewFlag = ((SvxProtectItem*)pNew)->IsCntntProtected();
402 if( !bNewFlag )
404 // Abschalten: teste ob nicht vielleich ueber die Parents
405 // doch ein Schutzt besteht!
406 const SwSection* pSect = this;
407 do {
408 if( pSect->IsProtect() )
410 bNewFlag = TRUE;
411 break;
413 } while( 0 != ( pSect = pSect->GetParent()) );
416 _SetProtectFlag( bNewFlag );
418 return;
419 // --> FME 2004-06-22 #114856# edit in readonly sections
420 case RES_EDIT_IN_READONLY:
421 if( pNew )
423 BOOL bNewFlag = ((SwFmtEditInReadonly*)pNew)->GetValue();
424 _SetEditInReadonlyFlag( bNewFlag );
426 return;
427 // <--
429 case RES_SECTION_HIDDEN:
430 bHiddenFlag = TRUE;
431 return;
433 case RES_SECTION_NOT_HIDDEN:
434 case RES_SECTION_RESETHIDDENFLAG:
435 bHiddenFlag = bHidden && bCondHiddenFlag;
436 return;
438 case RES_COL:
439 /* wird ggf. vom Layout erledigt */
440 break;
442 case RES_FTN_AT_TXTEND:
443 if( pNew && pOld )
444 bUpdateFtn = TRUE;
445 break;
447 case RES_END_AT_TXTEND:
448 if( pNew && pOld )
449 bUpdateFtn = TRUE;
450 break;
453 if( bRemake )
455 GetFmt()->DelFrms();
456 GetFmt()->MakeFrms();
459 if( bUpdateFtn )
461 SwSectionNode* pSectNd = GetFmt()->GetSectionNode( FALSE );
462 if( pSectNd )
463 pSectNd->GetDoc()->GetFtnIdxs().UpdateFtn(SwNodeIndex( *pSectNd ));
465 SwClient::Modify( pOld, pNew );
468 void SwSection::SetRefObject( SwServerObject* pObj )
470 refObj = pObj;
474 void SwSection::SetCondHidden( BOOL bFlag )
476 if( !bCondHiddenFlag == !bFlag )
477 return;
479 bCondHiddenFlag = bFlag;
480 _SetHiddenFlag( bHidden, bCondHiddenFlag );
484 // setze/erfrage den gelinkten FileNamen
485 const String& SwSection::GetLinkFileName() const
487 if( refLink.Is() )
489 String sTmp;
490 switch( eType )
492 case DDE_LINK_SECTION:
493 sTmp = refLink->GetLinkSourceName();
494 break;
496 case FILE_LINK_SECTION:
498 String sRange, sFilter;
499 if( refLink->GetLinkManager() &&
500 refLink->GetLinkManager()->GetDisplayNames(
501 refLink, 0, &sTmp, &sRange, &sFilter ) )
503 ( sTmp += sfx2::cTokenSeperator ) += sFilter;
504 ( sTmp += sfx2::cTokenSeperator ) += sRange;
506 else if( GetFmt() && !GetFmt()->GetSectionNode() )
508 // ist die Section im UndoNodesArray, dann steht
509 // der Link nicht im LinkManager, kann also auch nicht
510 // erfragt werden. Dann returne den akt. Namen
511 return sLinkFileName;
514 break;
515 default: break;
517 ((SwSection*)this)->sLinkFileName = sTmp;
519 return sLinkFileName;
523 void SwSection::SetLinkFileName( const String& rNew, const String* pPassWd )
525 if( refLink.Is() )
526 refLink->SetLinkSourceName( rNew );
527 else
528 sLinkFileName = rNew;
529 if( pPassWd )
530 SetLinkFilePassWd( *pPassWd );
533 // falls es ein gelinkter Bereich war, dann muessen alle
534 // Child-Verknuepfungen sichtbar bemacht werden.
535 void SwSection::MakeChildLinksVisible( const SwSectionNode& rSectNd )
537 const SwNode* pNd;
538 const ::sfx2::SvBaseLinks& rLnks = rSectNd.GetDoc()->GetLinkManager().GetLinks();
539 for( USHORT n = rLnks.Count(); n; )
541 ::sfx2::SvBaseLink* pBLnk = &(*rLnks[ --n ]);
542 if( pBLnk && !pBLnk->IsVisible() &&
543 pBLnk->ISA( SwBaseLink ) &&
544 0 != ( pNd = ((SwBaseLink*)pBLnk)->GetAnchor() ) )
546 pNd = pNd->StartOfSectionNode(); // falls SectionNode ist!
547 const SwSectionNode* pParent;
548 while( 0 != ( pParent = pNd->FindSectionNode() ) &&
549 ( CONTENT_SECTION == pParent->GetSection().GetType()
550 || pNd == &rSectNd ))
551 pNd = pParent->StartOfSectionNode();
553 // steht nur noch in einer normalen Section, also
554 // wieder anzeigen
555 if( !pParent )
556 pBLnk->SetVisible( TRUE );
561 const SwTOXBase* SwSection::GetTOXBase() const
563 const SwTOXBase* pRet = 0;
564 if( TOX_CONTENT_SECTION == GetType() )
565 pRet = PTR_CAST( SwTOXBaseSection, this );
566 return pRet;
569 SwSectionFmt::SwSectionFmt( SwSectionFmt* pDrvdFrm, SwDoc *pDoc )
570 : SwFrmFmt( pDoc->GetAttrPool(), sSectionFmtNm, pDrvdFrm )
572 LockModify();
573 SetFmtAttr( *GetDfltAttr( RES_COL ) );
574 UnlockModify();
577 SwSectionFmt::~SwSectionFmt()
579 if( !GetDoc()->IsInDtor() )
581 SwSectionNode* pSectNd;
582 const SwNodeIndex* pIdx = GetCntnt( FALSE ).GetCntntIdx();
583 if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
584 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
586 SwSection& rSect = pSectNd->GetSection();
587 // falls es ein gelinkter Bereich war, dann muessen alle
588 // Child-Verknuepfungen sichtbar bemacht werden.
589 if( rSect.IsConnected() )
590 rSect.MakeChildLinksVisible( *pSectNd );
592 // vorm loeschen der Nodes pruefe, ob wir uns nicht
593 // noch anzeigen muessen!
594 if( rSect.IsHiddenFlag() )
596 SwSectionPtr pParentSect = rSect.GetParent();
597 if( !pParentSect || !pParentSect->IsHiddenFlag() )
599 // Nodes wieder anzeigen
600 rSect.SetHidden( FALSE );
603 SwClientIter aIter( *this );
604 SwClient *pLast = aIter.GoStart();
605 while ( pLast )
607 if ( pLast->IsA( TYPE(SwFrm) ) )
609 SwSectionFrm *pFrm = (SwSectionFrm*)pLast;
610 SwSectionFrm::MoveCntntAndDelete( pFrm, TRUE );
611 pLast = aIter.GoStart();
613 else
614 pLast = aIter++;
616 // hebe die Section doch mal auf
617 SwNodeRange aRg( *pSectNd, 0, *pSectNd->EndOfSectionNode() );
618 GetDoc()->GetNodes().SectionUp( &aRg );
620 LockModify();
621 ResetFmtAttr( RES_CNTNT );
622 UnlockModify();
627 SwSectionPtr SwSectionFmt::_GetSection() const
629 if( GetDepends() )
631 SwClientIter aIter( *(SwSectionFmt*)this );
632 return (SwSectionPtr)aIter.First( TYPE(SwSection) );
635 ASSERT( FALSE, "keine Section als Client." )
636 return 0;
639 extern void lcl_DeleteFtn( SwSectionNode *pNd, ULONG nStt, ULONG nEnd );
641 //Vernichtet alle Frms in aDepend (Frms werden per PTR_CAST erkannt).
642 void SwSectionFmt::DelFrms()
644 SwSectionNode* pSectNd;
645 const SwNodeIndex* pIdx = GetCntnt(FALSE).GetCntntIdx();
646 if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
647 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
649 SwClientIter aIter( *this );
650 SwClient *pLast = aIter.GoStart();
651 // --> OD 2007-08-14 #147431#
652 // First delete the <SwSectionFrm> of the <SwSectionFmt> instance
653 while ( pLast )
655 if ( pLast->IsA( TYPE(SwFrm) ) )
657 SwSectionFrm *pFrm = (SwSectionFrm*)pLast;
658 SwSectionFrm::MoveCntntAndDelete( pFrm, FALSE );
659 pLast = aIter.GoStart();
661 else
663 pLast = aIter++;
666 // Then delete frames of the nested <SwSectionFmt> instances
667 pLast = aIter.GoStart();
668 while ( pLast )
670 if ( pLast->IsA( TYPE(SwSectionFmt) ) )
672 ((SwSectionFmt*)pLast)->DelFrms();
674 pLast = aIter++;
676 // <--
677 ULONG nEnde = pSectNd->EndOfSectionIndex();
678 ULONG nStart = pSectNd->GetIndex()+1;
679 lcl_DeleteFtn( pSectNd, nStart, nEnde );
681 if( pIdx )
683 //JP 22.09.98:
684 //Hint fuer Pagedesc versenden. Das mueste eigntlich das Layout im
685 //Paste der Frames selbst erledigen, aber das fuehrt dann wiederum
686 //zu weiteren Folgefehlern, die mit Laufzeitkosten geloest werden
687 //muesten. #56977# #55001# #56135#
688 SwNodeIndex aNextNd( *pIdx );
689 SwCntntNode* pCNd = GetDoc()->GetNodes().GoNextSection( &aNextNd, TRUE, FALSE );
690 if( pCNd )
692 const SfxPoolItem& rItem = pCNd->GetSwAttrSet().Get( RES_PAGEDESC );
693 pCNd->Modify( (SfxPoolItem*)&rItem, (SfxPoolItem*)&rItem );
699 //Erzeugt die Ansichten
700 void SwSectionFmt::MakeFrms()
702 SwSectionNode* pSectNd;
703 const SwNodeIndex* pIdx = GetCntnt(FALSE).GetCntntIdx();
705 if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
706 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
708 SwNodeIndex aIdx( *pIdx );
709 pSectNd->MakeFrms( &aIdx );
713 void lcl_ClientIter( SwSectionFmt* pFmt, const SfxPoolItem* pOld,
714 const SfxPoolItem* pNew )
716 SwClientIter aIter( *pFmt );
717 SwClient * pLast = aIter.GoStart();
718 if( pLast )
719 do {
720 pLast->Modify( (SfxPoolItem*)pOld, (SfxPoolItem*)pNew );
721 } while( 0 != ( pLast = aIter++ ));
724 void SwSectionFmt::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
726 BOOL bClients = FALSE;
727 USHORT nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
728 switch( nWhich )
730 case RES_ATTRSET_CHG:
731 if( GetDepends() )
733 SfxItemSet* pNewSet = ((SwAttrSetChg*)pNew)->GetChgSet();
734 SfxItemSet* pOldSet = ((SwAttrSetChg*)pOld)->GetChgSet();
735 const SfxPoolItem *pItem;
736 if( SFX_ITEM_SET == pNewSet->GetItemState(
737 RES_PROTECT, FALSE, &pItem ))
739 lcl_ClientIter( this, pItem, pItem );
740 pNewSet->ClearItem( RES_PROTECT );
741 pOldSet->ClearItem( RES_PROTECT );
744 // --> FME 2004-06-22 #114856# edit in readonly sections
745 if( SFX_ITEM_SET == pNewSet->GetItemState(
746 RES_EDIT_IN_READONLY, FALSE, &pItem ) )
748 lcl_ClientIter( this, pItem, pItem );
749 pNewSet->ClearItem( RES_EDIT_IN_READONLY );
750 pOldSet->ClearItem( RES_EDIT_IN_READONLY );
752 // <--
754 if( SFX_ITEM_SET == pNewSet->GetItemState(
755 RES_FTN_AT_TXTEND, FALSE, &pItem ))
757 lcl_ClientIter( this, &pOldSet->Get( RES_FTN_AT_TXTEND ),
758 pItem );
759 pNewSet->ClearItem( RES_FTN_AT_TXTEND );
760 pOldSet->ClearItem( RES_FTN_AT_TXTEND );
762 if( SFX_ITEM_SET == pNewSet->GetItemState(
763 RES_END_AT_TXTEND, FALSE, &pItem ))
765 lcl_ClientIter( this, &pOldSet->Get( RES_END_AT_TXTEND ),
766 pItem );
767 pNewSet->ClearItem( RES_END_AT_TXTEND );
768 pOldSet->ClearItem( RES_END_AT_TXTEND );
770 if( !((SwAttrSetChg*)pOld)->GetChgSet()->Count() )
771 return;
773 break;
775 case RES_SECTION_RESETHIDDENFLAG:
776 case RES_FTN_AT_TXTEND:
777 case RES_END_AT_TXTEND : bClients = TRUE;
778 // no break !!
779 case RES_SECTION_HIDDEN:
780 case RES_SECTION_NOT_HIDDEN:
782 SwSection* pSect = GetSection();
783 if( pSect && ( bClients || ( RES_SECTION_HIDDEN == nWhich ?
784 !pSect->IsHiddenFlag() : pSect->IsHiddenFlag() ) ) )
786 // selbst ueber die Clients iterieren, sollte schneller sein!
787 SwClientIter aIter( *this );
788 SwClient * pLast = aIter.GoStart();
789 do {
790 pLast->Modify( pOld, pNew );
791 } while( 0 != ( pLast = aIter++ ));
794 return ;
797 case RES_PROTECT:
798 // --> FME 2004-06-22 #114856# edit in readonly sections
799 case RES_EDIT_IN_READONLY:
800 // <--
801 // diese Messages bis zum Ende des Baums durchreichen !
802 if( GetDepends() )
804 SwClientIter aIter( *this );
805 SwClient * pLast = aIter.GoStart();
806 if( pLast ) // konnte zum Anfang gesprungen werden ??
807 do {
808 pLast->Modify( pOld, pNew );
809 } while( 0 != ( pLast = aIter++ ));
811 return; // das wars
813 case RES_OBJECTDYING:
814 if( !GetDoc()->IsInDtor() &&
815 ((SwPtrMsgPoolItem *)pOld)->pObject == (void*)GetRegisteredIn() )
817 // mein Parent wird vernichtet, dann an den Parent vom Parent
818 // umhaengen und wieder aktualisieren
819 SwFrmFmt::Modify( pOld, pNew ); // erst umhaengen !!!
820 UpdateParent();
821 return;
823 break;
825 case RES_FMT_CHG:
826 if( !GetDoc()->IsInDtor() &&
827 ((SwFmtChg*)pNew)->pChangedFmt == (void*)GetRegisteredIn() &&
828 ((SwFmtChg*)pNew)->pChangedFmt->IsA( TYPE( SwSectionFmt )) )
830 // mein Parent wird veraendert, muss mich aktualisieren
831 SwFrmFmt::Modify( pOld, pNew ); // erst umhaengen !!!
832 UpdateParent();
833 return;
835 break;
837 SwFrmFmt::Modify( pOld, pNew );
840 // erfrage vom Format Informationen
841 BOOL SwSectionFmt::GetInfo( SfxPoolItem& rInfo ) const
843 switch( rInfo.Which() )
845 case RES_FINDNEARESTNODE:
846 if( ((SwFmtPageDesc&)GetFmtAttr( RES_PAGEDESC )).GetPageDesc() )
848 const SwSectionNode* pNd = GetSectionNode();
849 if( pNd )
850 ((SwFindNearestNode&)rInfo).CheckNode( *pNd );
852 return TRUE;
854 case RES_CONTENT_VISIBLE:
856 SwFrm* pFrm = (SwFrm*)SwClientIter( *(SwSectionFmt*)this ).First( TYPE(SwFrm) );
857 // if the current section has no own frame search for the children
858 if(!pFrm)
860 SwClientIter aFormatIter( *(SwSectionFmt*)this );
861 SwSectionFmt* pChild = (SwSectionFmt*)aFormatIter.
862 First( TYPE(SwSectionFmt) );
863 while(pChild && !pFrm)
865 pFrm = (SwFrm*)SwClientIter( *pChild ).First( TYPE(SwFrm) );
866 pChild = (SwSectionFmt*)aFormatIter.Next();
869 ((SwPtrMsgPoolItem&)rInfo).pObject = pFrm;
871 return FALSE;
873 return SwModify::GetInfo( rInfo );
876 extern "C" {
879 #if defined( WNT )
880 __cdecl
881 #endif
882 #if defined( ICC )
883 _Optlink
884 #endif
885 lcl_SectionCmpPos( const void *pFirst, const void *pSecond)
887 const SwSectionFmt* pFSectFmt = (*(SwSectionPtr*)pFirst)->GetFmt();
888 const SwSectionFmt* pSSectFmt = (*(SwSectionPtr*)pSecond)->GetFmt();
889 ASSERT( pFSectFmt && pSSectFmt &&
890 pFSectFmt->GetCntnt(FALSE).GetCntntIdx() &&
891 pSSectFmt->GetCntnt(FALSE).GetCntntIdx(),
892 "ungueltige Sections" );
893 return (int)((long)pFSectFmt->GetCntnt(FALSE).GetCntntIdx()->GetIndex()) -
894 pSSectFmt->GetCntnt(FALSE).GetCntntIdx()->GetIndex();
898 #if defined( WNT )
899 __cdecl
900 #endif
901 #if defined( ICC )
902 _Optlink
903 #endif
904 lcl_SectionCmpNm( const void *pFirst, const void *pSecond)
906 const SwSectionPtr pFSect = *(SwSectionPtr*)pFirst;
907 const SwSectionPtr pSSect = *(SwSectionPtr*)pSecond;
908 ASSERT( pFSect && pSSect, "ungueltige Sections" );
909 StringCompare eCmp = pFSect->GetName().CompareTo( pSSect->GetName() );
910 return eCmp == COMPARE_EQUAL ? 0
911 : eCmp == COMPARE_LESS ? 1 : -1;
915 // alle Sections, die von dieser abgeleitet sind
916 USHORT SwSectionFmt::GetChildSections( SwSections& rArr,
917 SectionSort eSort,
918 BOOL bAllSections ) const
920 rArr.Remove( 0, rArr.Count() );
922 if( GetDepends() )
924 SwClientIter aIter( *(SwSectionFmt*)this );
925 SwClient * pLast;
926 const SwNodeIndex* pIdx;
927 for( pLast = aIter.First(TYPE(SwSectionFmt)); pLast; pLast = aIter.Next() )
928 if( bAllSections ||
929 ( 0 != ( pIdx = ((SwSectionFmt*)pLast)->GetCntnt(FALSE).
930 GetCntntIdx()) && &pIdx->GetNodes() == &GetDoc()->GetNodes() ))
932 const SwSection* Dummy=((SwSectionFmt*)pLast)->GetSection();
933 rArr.C40_INSERT( SwSection,
934 Dummy,
935 rArr.Count() );
938 // noch eine Sortierung erwuenscht ?
939 if( 1 < rArr.Count() )
940 switch( eSort )
942 case SORTSECT_NAME:
943 qsort( (void*)rArr.GetData(),
944 rArr.Count(),
945 sizeof( SwSectionPtr ),
946 lcl_SectionCmpNm );
947 break;
949 case SORTSECT_POS:
950 qsort( (void*)rArr.GetData(),
951 rArr.Count(),
952 sizeof( SwSectionPtr ),
953 lcl_SectionCmpPos );
954 break;
955 case SORTSECT_NOT: break;
958 return rArr.Count();
961 // erfrage, ob sich die Section im Nodes-Array oder UndoNodes-Array
962 // befindet.
963 BOOL SwSectionFmt::IsInNodesArr() const
965 const SwNodeIndex* pIdx = GetCntnt(FALSE).GetCntntIdx();
966 return pIdx && &pIdx->GetNodes() == &GetDoc()->GetNodes();
970 void SwSectionFmt::UpdateParent() // Parent wurde veraendert
972 if( !GetDepends() )
973 return;
975 SwSectionPtr pSection = 0;
976 const SvxProtectItem* pProtect(0);
977 // --> FME 2004-06-22 #114856# edit in readonly sections
978 const SwFmtEditInReadonly* pEditInReadonly = 0;
979 // <--
980 int bIsHidden = FALSE;
982 SwClientIter aIter( *this );
983 SwClient * pLast = aIter.GoStart();
984 if( pLast ) // konnte zum Anfang gesprungen werden ??
985 do {
986 if( pLast->IsA( TYPE(SwSectionFmt) ) )
988 if( !pSection )
990 pSection = GetSection();
991 if( GetRegisteredIn() )
993 const SwSectionPtr pPS = GetParentSection();
994 pProtect = &pPS->GetFmt()->GetProtect();
995 // --> FME 2004-06-22 #114856# edit in readonly sections
996 pEditInReadonly = &pPS->GetFmt()->GetEditInReadonly();
997 // <--
998 bIsHidden = pPS->IsHiddenFlag();
1000 else
1002 pProtect = &GetProtect();
1003 // --> FME 2004-06-22 #114856# edit in readonly sections
1004 pEditInReadonly = &GetEditInReadonly();
1005 // <--
1006 bIsHidden = pSection->IsHidden();
1009 if( pProtect->IsCntntProtected() !=
1010 pSection->IsProtectFlag() )
1011 pLast->Modify( (SfxPoolItem*)pProtect,
1012 (SfxPoolItem*)pProtect );
1014 // --> FME 2004-06-22 #114856# edit in readonly sections
1015 if ( pEditInReadonly->GetValue() !=
1016 pSection->IsEditInReadonlyFlag() )
1017 pLast->Modify( (SfxPoolItem*)pEditInReadonly,
1018 (SfxPoolItem*)pEditInReadonly );
1019 // <--
1021 if( bIsHidden == pSection->IsHiddenFlag() )
1023 SwMsgPoolItem aMsgItem( static_cast<USHORT>(bIsHidden
1024 ? RES_SECTION_HIDDEN
1025 : RES_SECTION_NOT_HIDDEN ) );
1026 pLast->Modify( &aMsgItem, &aMsgItem );
1029 else if( !pSection &&
1030 pLast->IsA( TYPE(SwSection) ) )
1032 pSection = (SwSectionPtr)pLast;
1033 if( GetRegisteredIn() )
1035 const SwSectionPtr pPS = GetParentSection();
1036 pProtect = &pPS->GetFmt()->GetProtect();
1037 // --> FME 2004-06-22 #114856# edit in readonly sections
1038 pEditInReadonly = &pPS->GetFmt()->GetEditInReadonly();
1039 // <--
1040 bIsHidden = pPS->IsHiddenFlag();
1042 else
1044 pProtect = &GetProtect();
1045 // --> FME 2004-06-22 #114856# edit in readonly sections
1046 pEditInReadonly = &GetEditInReadonly();
1047 // <--
1048 bIsHidden = pSection->IsHidden();
1051 } while( 0 != ( pLast = aIter++ ));
1055 SwSectionNode* SwSectionFmt::GetSectionNode( BOOL bAlways )
1057 const SwNodeIndex* pIdx = GetCntnt(FALSE).GetCntntIdx();
1058 if( pIdx && ( bAlways || &pIdx->GetNodes() == &GetDoc()->GetNodes() ))
1059 return pIdx->GetNode().GetSectionNode();
1060 return 0;
1063 // ist die Section eine gueltige fuers GlobalDocument?
1064 const SwSection* SwSectionFmt::GetGlobalDocSection() const
1066 const SwSectionNode* pNd = GetSectionNode();
1067 if( pNd &&
1068 ( FILE_LINK_SECTION == pNd->GetSection().GetType() ||
1069 TOX_CONTENT_SECTION == pNd->GetSection().GetType() ) &&
1070 pNd->GetIndex() > pNd->GetNodes().GetEndOfExtras().GetIndex() &&
1071 !pNd->StartOfSectionNode()->IsSectionNode() &&
1072 !pNd->StartOfSectionNode()->FindSectionNode() )
1073 return &pNd->GetSection();
1074 return 0;
1077 // --> OD 2007-02-14 #b6521322#
1078 // Method to break section links inside a linked section
1079 void lcl_BreakSectionLinksInSect( const SwSectionNode& rSectNd )
1081 if ( !rSectNd.GetDoc() )
1083 ASSERT( false,
1084 "method <lcl_RemoveSectionLinksInSect(..)> - no Doc at SectionNode" );
1085 return;
1088 if ( !rSectNd.GetSection().IsConnected() )
1090 ASSERT( false,
1091 "method <lcl_RemoveSectionLinksInSect(..)> - no Link at Section of SectionNode" );
1092 return;
1094 const ::sfx2::SvBaseLink* pOwnLink( &(rSectNd.GetSection().GetBaseLink() ) );
1095 const ::sfx2::SvBaseLinks& rLnks = rSectNd.GetDoc()->GetLinkManager().GetLinks();
1096 for ( USHORT n = rLnks.Count(); n > 0; )
1098 SwIntrnlSectRefLink* pSectLnk = dynamic_cast<SwIntrnlSectRefLink*>(&(*rLnks[ --n ]));
1099 if ( pSectLnk && pSectLnk != pOwnLink &&
1100 pSectLnk->IsInRange( rSectNd.GetIndex(), rSectNd.EndOfSectionIndex() ) )
1102 // break the link of the corresponding section.
1103 // the link is also removed from the link manager
1104 pSectLnk->GetSectNode()->GetSection().BreakLink();
1106 // for robustness, because link is removed from the link manager
1107 if ( n > rLnks.Count() )
1109 n = rLnks.Count();
1114 // <--
1116 void lcl_UpdateLinksInSect( SwBaseLink& rUpdLnk, SwSectionNode& rSectNd )
1118 SwDoc* pDoc = rSectNd.GetDoc();
1119 SwDocShell* pDShell = pDoc->GetDocShell();
1120 if( !pDShell || !pDShell->GetMedium() )
1121 return ;
1123 String sName( pDShell->GetMedium()->GetName() );
1124 SwBaseLink* pBLink;
1125 String sMimeType( SotExchange::GetFormatMimeType( FORMAT_FILE ));
1126 uno::Any aValue;
1127 aValue <<= ::rtl::OUString( sName ); // beliebiger Name
1129 const ::sfx2::SvBaseLinks& rLnks = pDoc->GetLinkManager().GetLinks();
1130 for( USHORT n = rLnks.Count(); n; )
1132 ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]);
1133 if( pLnk && pLnk != &rUpdLnk &&
1134 OBJECT_CLIENT_FILE == pLnk->GetObjType() &&
1135 pLnk->ISA( SwBaseLink ) &&
1136 ( pBLink = (SwBaseLink*)pLnk )->IsInRange( rSectNd.GetIndex(),
1137 rSectNd.EndOfSectionIndex() ) )
1139 // liegt in dem Bereich: also updaten. Aber nur wenns nicht
1140 // im gleichen File liegt
1141 String sFName;
1142 pDoc->GetLinkManager().GetDisplayNames( pBLink, 0, &sFName, 0, 0 );
1143 if( sFName != sName )
1145 pBLink->DataChanged( sMimeType, aValue );
1147 // ggfs. neu den Link-Pointer wieder suchen, damit nicht einer
1148 // ausgelassen oder doppelt gerufen wird.
1149 if( n >= rLnks.Count() && 0 != ( n = rLnks.Count() ))
1150 --n;
1152 if( n && pLnk != &(*rLnks[ n ]) )
1154 // suchen - kann nur davor liegen!!
1155 while( n )
1156 if( pLnk == &(*rLnks[ --n ] ) )
1157 break;
1165 // sucht sich die richtige DocShell raus oder erzeugt eine neue:
1166 // Der Return-Wert gibt an, was mit der Shell zu geschehen hat:
1167 // 0 - Fehler, konnte DocShell nicht finden
1168 // 1 - DocShell ist ein existieren Document
1169 // 2 - DocShell wurde neu angelegt, muss also wieder geschlossen werden
1171 int lcl_FindDocShell( SfxObjectShellRef& xDocSh,
1172 const String& rFileName,
1173 const String& rPasswd,
1174 String& rFilter,
1175 INT16 nVersion,
1176 SwDocShell* pDestSh )
1178 if( !rFileName.Len() )
1179 return 0;
1181 // 1. existiert die Datei schon in der Liste aller Dokumente?
1182 INetURLObject aTmpObj( rFileName );
1183 aTmpObj.SetMark( aEmptyStr );
1185 // erstmal nur ueber die DocumentShells laufen und die mit dem
1186 // Namen heraussuchen:
1187 TypeId aType( TYPE(SwDocShell) );
1189 SfxObjectShell* pShell = pDestSh;
1190 BOOL bFirst = 0 != pShell;
1192 if( !bFirst )
1193 // keine DocShell uebergeben, also beginne mit der ersten aus der
1194 // DocShell Liste
1195 pShell = SfxObjectShell::GetFirst( &aType );
1197 while( pShell )
1199 // die wollen wir haben
1200 SfxMedium* pMed = pShell->GetMedium();
1201 if( pMed && pMed->GetURLObject() == aTmpObj )
1203 const SfxPoolItem* pItem;
1204 if( ( SFX_ITEM_SET == pMed->GetItemSet()->GetItemState(
1205 SID_VERSION, FALSE, &pItem ) )
1206 ? (nVersion == ((SfxInt16Item*)pItem)->GetValue())
1207 : !nVersion )
1209 // gefunden also returnen
1210 xDocSh = pShell;
1211 return 1;
1215 if( bFirst )
1217 bFirst = FALSE;
1218 pShell = SfxObjectShell::GetFirst( &aType );
1220 else
1221 pShell = SfxObjectShell::GetNext( *pShell, &aType );
1224 // 2. selbst die Date oeffnen
1225 SfxMedium* pMed = new SfxMedium( aTmpObj.GetMainURL(
1226 INetURLObject::NO_DECODE ), STREAM_READ, TRUE );
1227 if( INET_PROT_FILE == aTmpObj.GetProtocol() )
1228 pMed->DownLoad(); // nur mal das Medium anfassen (DownLoaden)
1230 const SfxFilter* pSfxFlt = 0;
1231 if( !pMed->GetError() )
1233 String sFactory(String::CreateFromAscii(SwDocShell::Factory().GetShortName()));
1234 SfxFilterMatcher aMatcher( sFactory );
1236 // kein Filter, dann suche ihn. Ansonsten teste, ob der angegebene
1237 // ein gueltiger ist
1238 if( rFilter.Len() )
1240 pSfxFlt = aMatcher.GetFilter4FilterName( rFilter );
1243 if( nVersion )
1244 pMed->GetItemSet()->Put( SfxInt16Item( SID_VERSION, nVersion ));
1246 if( rPasswd.Len() )
1247 pMed->GetItemSet()->Put( SfxStringItem( SID_PASSWORD, rPasswd ));
1249 if( !pSfxFlt )
1250 aMatcher.DetectFilter( *pMed, &pSfxFlt, FALSE, FALSE );
1252 if( pSfxFlt )
1254 // ohne Filter geht gar nichts
1255 pMed->SetFilter( pSfxFlt );
1257 xDocSh = new SwDocShell( SFX_CREATE_MODE_INTERNAL );
1258 if( xDocSh->DoLoad( pMed ) )
1259 return 2;
1263 if( !xDocSh.Is() ) // Medium muss noch geloescht werden
1264 delete pMed;
1266 return 0; // das war wohl nichts
1270 void SwIntrnlSectRefLink::DataChanged( const String& rMimeType,
1271 const uno::Any & rValue )
1273 SwSectionNode* pSectNd = rSectFmt.GetSectionNode( FALSE );
1274 SwDoc* pDoc = rSectFmt.GetDoc();
1276 ULONG nDataFormat = SotExchange::GetFormatIdFromMimeType( rMimeType );
1278 if( !pSectNd || !pDoc || pDoc->IsInDtor() || ChkNoDataFlag() ||
1279 SvxLinkManager::RegisterStatusInfoId() == nDataFormat )
1281 // sollten wir schon wieder im Undo stehen?
1282 return ;
1285 // --> OD 2005-02-11 #i38810# - Due to possible existing signatures, the
1286 // document has to be modified after updating a link.
1287 pDoc->SetModified();
1288 // set additional flag that links have been updated, in order to check this
1289 // during load.
1290 pDoc->SetLinksUpdated( sal_True );
1291 // <--
1293 // Undo immer abschalten
1294 BOOL bWasUndo = pDoc->DoesUndo();
1295 pDoc->DoUndo( FALSE );
1296 BOOL bWasVisibleLinks = pDoc->IsVisibleLinks();
1297 pDoc->SetVisibleLinks( FALSE );
1299 SwPaM* pPam;
1300 ViewShell* pVSh = 0;
1301 SwEditShell* pESh = pDoc->GetEditShell( &pVSh );
1302 pDoc->LockExpFlds();
1304 // am Anfang des Bereichs einen leeren TextNode einfuegen
1305 SwNodeIndex aIdx( *pSectNd, +1 );
1306 SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() );
1307 SwTxtNode* pNewNd = pDoc->GetNodes().MakeTxtNode( aIdx,
1308 pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT ) );
1310 if( pESh )
1311 pESh->StartAllAction();
1312 else if( pVSh )
1313 pVSh->StartAction();
1315 SwPosition aPos( aIdx, SwIndex( pNewNd, 0 ));
1316 aPos.nNode--;
1317 pDoc->CorrAbs( aIdx, aEndIdx, aPos, TRUE );
1319 pPam = new SwPaM( aPos );
1321 //und alles dahinter liegende loeschen
1322 aIdx--;
1323 DelFlyInRange( aIdx, aEndIdx );
1324 _DelBookmarks(aIdx, aEndIdx);
1325 aIdx++;
1327 pDoc->GetNodes().Delete( aIdx, aEndIdx.GetIndex() - aIdx.GetIndex() );
1330 SwSection& rSection = pSectNd->GetSection();
1331 rSection.SetConnectFlag( FALSE );
1333 ::rtl::OUString sNewFileName;
1334 Reader* pRead = 0;
1335 switch( nDataFormat )
1337 case FORMAT_STRING:
1338 pRead = ReadAscii;
1339 break;
1341 case FORMAT_RTF:
1342 pRead = SwReaderWriter::GetReader( READER_WRITER_RTF );
1343 break;
1345 case FORMAT_FILE:
1346 if( rValue.hasValue() && ( rValue >>= sNewFileName ) )
1348 String sFilter, sRange, sFileName( sNewFileName );
1349 pDoc->GetLinkManager().GetDisplayNames( this, 0, &sFileName,
1350 &sRange, &sFilter );
1352 RedlineMode_t eOldRedlineMode = nsRedlineMode_t::REDLINE_NONE;
1353 SfxObjectShellRef xDocSh;
1354 int nRet;
1355 if( !sFileName.Len() )
1357 xDocSh = pDoc->GetDocShell();
1358 nRet = 1;
1360 else
1362 nRet = lcl_FindDocShell( xDocSh, sFileName,
1363 rSection.GetLinkFilePassWd(),
1364 sFilter, 0, pDoc->GetDocShell() );
1365 if( nRet )
1367 SwDoc* pSrcDoc = ((SwDocShell*)&xDocSh)->GetDoc();
1368 eOldRedlineMode = pSrcDoc->GetRedlineMode();
1369 pSrcDoc->SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_INSERT );
1373 if( nRet )
1375 rSection.SetConnectFlag( TRUE );
1377 SwNodeIndex aSave( pPam->GetPoint()->nNode, -1 );
1378 SwNodeRange* pCpyRg = 0;
1380 if( xDocSh->GetMedium() &&
1381 !rSection.GetLinkFilePassWd().Len() )
1383 const SfxPoolItem* pItem;
1384 if( SFX_ITEM_SET == xDocSh->GetMedium()->GetItemSet()->
1385 GetItemState( SID_PASSWORD, FALSE, &pItem ) )
1386 rSection.SetLinkFilePassWd(
1387 ((SfxStringItem*)pItem)->GetValue() );
1390 SwDoc* pSrcDoc = ((SwDocShell*)&xDocSh)->GetDoc();
1392 if( sRange.Len() )
1394 // Rekursionen abfangen
1395 BOOL bRecursion = FALSE;
1396 if( pSrcDoc == pDoc )
1398 SwServerObjectRef refObj( (SwServerObject*)
1399 pDoc->CreateLinkSource( sRange ));
1400 if( refObj.Is() )
1402 bRecursion = refObj->IsLinkInServer( this ) ||
1403 ChkNoDataFlag();
1407 SwNodeIndex& rInsPos = pPam->GetPoint()->nNode;
1409 SwPaM* pCpyPam = 0;
1410 if( !bRecursion &&
1411 pSrcDoc->SelectServerObj( sRange, pCpyPam, pCpyRg )
1412 && pCpyPam )
1414 if( pSrcDoc != pDoc ||
1415 pCpyPam->Start()->nNode > rInsPos ||
1416 rInsPos >= pCpyPam->End()->nNode )
1418 pSrcDoc->CopyRange( *pCpyPam, *pPam->GetPoint(),
1419 false );
1421 delete pCpyPam;
1423 if( pCpyRg && pSrcDoc == pDoc &&
1424 pCpyRg->aStart < rInsPos && rInsPos < pCpyRg->aEnd )
1425 delete pCpyRg, pCpyRg = 0;
1427 else if( pSrcDoc != pDoc )
1428 pCpyRg = new SwNodeRange( pSrcDoc->GetNodes().GetEndOfExtras(), 2,
1429 pSrcDoc->GetNodes().GetEndOfContent() );
1431 // --> OD 2007-11-30 #i81653#
1432 // Update links of extern linked document or extern linked
1433 // document section, if section is protected.
1434 if ( pSrcDoc != pDoc &&
1435 rSection.IsProtectFlag() )
1437 pSrcDoc->GetLinkManager().UpdateAllLinks( FALSE, TRUE, FALSE, 0 );
1439 // <--
1440 if( pCpyRg )
1442 SwNodeIndex& rInsPos = pPam->GetPoint()->nNode;
1443 BOOL bCreateFrm = rInsPos.GetIndex() <=
1444 pDoc->GetNodes().GetEndOfExtras().GetIndex() ||
1445 rInsPos.GetNode().FindTableNode();
1447 SwTblNumFmtMerge aTNFM( *pSrcDoc, *pDoc );
1449 pSrcDoc->CopyWithFlyInFly( *pCpyRg, 0, rInsPos, bCreateFrm );
1450 aSave++;
1452 if( !bCreateFrm )
1453 ::MakeFrms( pDoc, aSave, rInsPos );
1455 // den letzten Node noch loeschen, aber nur wenn
1456 // erfolgreich kopiert werden konnte, also der Bereich
1457 // mehr als 1 Node enthaelt
1458 if( 2 < pSectNd->EndOfSectionIndex() - pSectNd->GetIndex() )
1460 aSave = rInsPos;
1461 pPam->Move( fnMoveBackward, fnGoNode );
1462 pPam->SetMark(); // beide SwPositions ummelden!
1464 pDoc->CorrAbs( aSave, *pPam->GetPoint(), 0, TRUE );
1465 pDoc->GetNodes().Delete( aSave, 1 );
1467 delete pCpyRg;
1470 // --> OD 2007-02-14 #b6521322#
1471 lcl_BreakSectionLinksInSect( *pSectNd );
1472 // <--
1474 // update alle Links in diesem Bereich
1475 lcl_UpdateLinksInSect( *this, *pSectNd );
1477 if( xDocSh.Is() )
1479 if( 2 == nRet )
1480 xDocSh->DoClose();
1481 else if( ((SwDocShell*)&xDocSh)->GetDoc() )
1482 ((SwDocShell*)&xDocSh)->GetDoc()->SetRedlineMode(
1483 eOldRedlineMode );
1486 break;
1489 // !!!! DDE nur updaten wenn Shell vorhanden ist??
1490 uno::Sequence< sal_Int8 > aSeq;
1491 if( pRead && rValue.hasValue() && ( rValue >>= aSeq ) )
1493 if( pESh )
1495 pESh->Push();
1496 SwPaM* pCrsr = pESh->GetCrsr();
1497 *pCrsr->GetPoint() = *pPam->GetPoint();
1498 delete pPam;
1499 pPam = pCrsr;
1502 SvMemoryStream aStrm( (void*)aSeq.getConstArray(), aSeq.getLength(),
1503 STREAM_READ );
1504 aStrm.Seek( 0 );
1506 #if OSL_DEBUG_LEVEL > 1
1508 SvFileStream aDeb( String::CreateFromAscii(
1509 "file:///d|/temp/update.txt" ), STREAM_WRITE );
1510 aDeb << aStrm;
1512 aStrm.Seek( 0 );
1513 #endif
1515 // TODO/MBA: it's impossible to set a BaseURL here!
1516 SwReader aTmpReader( aStrm, aEmptyStr, pDoc->GetDocShell()->GetMedium()->GetBaseURL(), *pPam );
1518 if( !IsError( aTmpReader.Read( *pRead ) ))
1519 rSection.SetConnectFlag( TRUE );
1521 if( pESh )
1523 pESh->Pop( FALSE );
1524 pPam = 0; // pam is deleted before
1529 // Alle UndoActions entfernen und Undo wieder einschalten
1530 pDoc->DelAllUndoObj();
1531 pDoc->DoUndo( bWasUndo );
1532 pDoc->SetVisibleLinks( bWasVisibleLinks );
1534 pDoc->UnlockExpFlds();
1535 if( !pDoc->IsExpFldsLocked() )
1536 pDoc->UpdateExpFlds(NULL, true);
1538 if( pESh )
1539 pESh->EndAllAction();
1540 else if( pVSh )
1541 pVSh->EndAction();
1542 delete pPam; // wurde am Anfang angelegt
1546 void SwIntrnlSectRefLink::Closed()
1548 SwDoc* pDoc = rSectFmt.GetDoc();
1549 if( pDoc && !pDoc->IsInDtor() )
1551 // Advise verabschiedet sich, den Bereich als nicht geschuetzt
1552 // kennzeichnen und das Flag umsetzen
1554 const SwSectionFmts& rFmts = pDoc->GetSections();
1555 for( USHORT n = rFmts.Count(); n; )
1556 if( rFmts[ --n ] == &rSectFmt )
1558 ViewShell* pSh;
1559 SwEditShell* pESh = pDoc->GetEditShell( &pSh );
1561 if( pESh )
1562 pESh->StartAllAction();
1563 else
1564 pSh->StartAction();
1566 SwSection aSect( CONTENT_SECTION, aEmptyStr );
1567 aSect = *rSectFmt.GetSection();
1568 aSect.SetType( CONTENT_SECTION );
1569 aSect.SetLinkFileName( aEmptyStr );
1570 aSect.SetHidden( FALSE );
1571 aSect.SetProtect( FALSE );
1572 // --> FME 2004-06-22 #114856# edit in readonly sections
1573 aSect.SetEditInReadonly( FALSE );
1574 // <--
1576 aSect.SetConnectFlag( FALSE );
1578 pDoc->ChgSection( n, aSect );
1580 // alle in der Section liegenden Links werden sichtbar
1581 SwSectionNode* pSectNd = rSectFmt.GetSectionNode( FALSE );
1582 if( pSectNd )
1583 pSectNd->GetSection().MakeChildLinksVisible( *pSectNd );
1585 if( pESh )
1586 pESh->EndAllAction();
1587 else
1588 pSh->EndAction();
1589 break;
1592 SvBaseLink::Closed();
1596 void SwSection::CreateLink( LinkCreateType eCreateType )
1598 SwSectionFmt* pFmt = GetFmt();
1599 if( !pFmt || CONTENT_SECTION == eType )
1600 return ;
1602 USHORT nUpdateType = sfx2::LINKUPDATE_ALWAYS;
1604 if( !refLink.Is() )
1605 // dann mal den BaseLink aufbauen
1606 refLink = new SwIntrnlSectRefLink( *pFmt, nUpdateType, FORMAT_RTF );
1607 else
1608 // sonst aus dem Linkmanager entfernen
1609 pFmt->GetDoc()->GetLinkManager().Remove( refLink );
1611 SwIntrnlSectRefLink* pLnk = (SwIntrnlSectRefLink*)&refLink;
1613 String sCmd( sLinkFileName );
1614 xub_StrLen nPos;
1615 while( STRING_NOTFOUND != (nPos = sCmd.SearchAscii( " " )) )
1616 sCmd.Erase( nPos, 1 );
1618 pLnk->SetUpdateMode( nUpdateType );
1619 pLnk->SetVisible( pFmt->GetDoc()->IsVisibleLinks() );
1621 switch( eType )
1623 case DDE_LINK_SECTION:
1624 pLnk->SetLinkSourceName( sCmd );
1625 pFmt->GetDoc()->GetLinkManager().InsertDDELink( pLnk );
1626 break;
1627 case FILE_LINK_SECTION:
1629 pLnk->SetContentType( FORMAT_FILE );
1630 String sFltr( sCmd.GetToken( 1, sfx2::cTokenSeperator ) );
1631 String sRange( sCmd.GetToken( 2, sfx2::cTokenSeperator ) );
1632 pFmt->GetDoc()->GetLinkManager().InsertFileLink( *pLnk,
1633 static_cast<USHORT>(eType),
1634 sCmd.GetToken( 0, sfx2::cTokenSeperator ),
1635 ( sFltr.Len() ? &sFltr : 0 ),
1636 ( sRange.Len() ? &sRange : 0 ) );
1638 break;
1639 default:
1640 ASSERT( !this, "Was ist das fuer ein Link?" )
1643 switch( eCreateType )
1645 case CREATE_CONNECT: // Link gleich connecten
1646 pLnk->Connect();
1647 break;
1649 case CREATE_UPDATE: // Link connecten und updaten
1650 pLnk->Update();
1651 break;
1652 case CREATE_NONE: break;
1656 // --> OD 2007-02-14 #b6521322#
1657 void SwSection::BreakLink()
1659 const SectionType eCurrentType( GetType() );
1660 if ( eCurrentType == CONTENT_SECTION ||
1661 eCurrentType == TOX_HEADER_SECTION ||
1662 eCurrentType == TOX_CONTENT_SECTION )
1664 // nothing to do
1665 return;
1668 // release link, if it exists
1669 if ( refLink.Is() )
1671 if ( GetFmt() )
1673 GetFmt()->GetDoc()->GetLinkManager().Remove( refLink );
1675 refLink.Clear();
1677 // change type
1678 SetType( CONTENT_SECTION );
1679 // reset linked file data
1680 SetLinkFileName( aEmptyStr );
1681 SetLinkFilePassWd( aEmptyStr );
1683 // <--
1685 const SwNode* SwIntrnlSectRefLink::GetAnchor() const
1687 return rSectFmt.GetSectionNode( FALSE );
1691 BOOL SwIntrnlSectRefLink::IsInRange( ULONG nSttNd, ULONG nEndNd,
1692 xub_StrLen , xub_StrLen ) const
1694 SwStartNode* pSttNd = rSectFmt.GetSectionNode( FALSE );
1695 return pSttNd &&
1696 nSttNd < pSttNd->GetIndex() &&
1697 pSttNd->EndOfSectionIndex() < nEndNd;