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