Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <stdlib.h>
21 : #include <hintids.hxx>
22 : #include <svl/intitem.hxx>
23 : #include <svl/stritem.hxx>
24 : #include <sfx2/docfile.hxx>
25 : #include <sfx2/docfilt.hxx>
26 : #include <editeng/protitem.hxx>
27 : #include <sfx2/linkmgr.hxx>
28 : #include <tools/urlobj.hxx>
29 : #include <sfx2/sfxsids.hrc>
30 : #include <sfx2/fcontnr.hxx>
31 : #include <docary.hxx>
32 : #include <fmtcntnt.hxx>
33 : #include <fmtpdsc.hxx>
34 : #include <doc.hxx>
35 : #include <IDocumentUndoRedo.hxx>
36 : #include <node.hxx>
37 : #include <pam.hxx>
38 : #include <frmtool.hxx>
39 : #include <editsh.hxx>
40 : #include <hints.hxx>
41 : #include <docsh.hxx>
42 : #include <ndtxt.hxx>
43 : #include <section.hxx>
44 : #include <swserv.hxx>
45 : #include <shellio.hxx>
46 : #include <poolfmt.hxx>
47 : #include <expfld.hxx>
48 : #include <swbaslnk.hxx>
49 : #include <mvsave.hxx>
50 : #include <sectfrm.hxx>
51 : #include <fmtftntx.hxx>
52 : #include <ftnidx.hxx>
53 : #include <doctxm.hxx>
54 : #include <fmteiro.hxx>
55 : #include <swerror.h>
56 : #include <unosection.hxx>
57 : #include <switerator.hxx>
58 : #include <svl/smplhint.hxx>
59 : #include <algorithm>
60 :
61 : using namespace ::com::sun::star;
62 :
63 0 : class SwIntrnlSectRefLink : public SwBaseLink
64 : {
65 : SwSectionFmt& rSectFmt;
66 : public:
67 0 : SwIntrnlSectRefLink( SwSectionFmt& rFmt, sal_uInt16 nUpdateType, sal_uInt16 nFmt )
68 : : SwBaseLink( nUpdateType, nFmt ),
69 0 : rSectFmt( rFmt )
70 0 : {}
71 :
72 : virtual void Closed() SAL_OVERRIDE;
73 : virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
74 : const OUString& rMimeType, const ::com::sun::star::uno::Any & rValue ) SAL_OVERRIDE;
75 :
76 : virtual const SwNode* GetAnchor() const SAL_OVERRIDE;
77 : virtual bool IsInRange( sal_uLong nSttNd, sal_uLong nEndNd, sal_Int32 nStt = 0,
78 : sal_Int32 nEnd = -1 ) const SAL_OVERRIDE;
79 :
80 0 : inline SwSectionNode* GetSectNode()
81 : {
82 0 : const SwNode* pSectNd( const_cast<SwIntrnlSectRefLink*>(this)->GetAnchor() );
83 0 : return const_cast<SwSectionNode*>( dynamic_cast<const SwSectionNode*>( pSectNd ) );
84 : }
85 : };
86 :
87 0 : TYPEINIT1(SwSectionFmt,SwFrmFmt );
88 0 : TYPEINIT1(SwSection,SwClient );
89 :
90 0 : SwSectionData::SwSectionData(SectionType const eType, OUString const& rName)
91 : : m_eType(eType)
92 : , m_sSectionName(rName)
93 : , m_bHiddenFlag(false)
94 : , m_bProtectFlag(false)
95 : , m_bEditInReadonlyFlag(false) // edit in readonly sections
96 : , m_bHidden(false)
97 : , m_bCondHiddenFlag(true)
98 0 : , m_bConnectFlag(true)
99 : {
100 0 : }
101 :
102 : // this must have the same semantics as operator=()
103 0 : SwSectionData::SwSectionData(SwSection const& rSection)
104 0 : : m_eType(rSection.GetType())
105 : , m_sSectionName(rSection.GetSectionName())
106 : , m_sCondition(rSection.GetCondition())
107 : , m_sLinkFileName(rSection.GetLinkFileName())
108 : , m_sLinkFilePassword(rSection.GetLinkFilePassword())
109 0 : , m_Password(rSection.GetPassword())
110 0 : , m_bHiddenFlag(rSection.IsHiddenFlag())
111 0 : , m_bProtectFlag(rSection.IsProtect())
112 : // edit in readonly sections
113 0 : , m_bEditInReadonlyFlag(rSection.IsEditInReadonly())
114 0 : , m_bHidden(rSection.IsHidden())
115 : , m_bCondHiddenFlag(true)
116 0 : , m_bConnectFlag(rSection.IsConnectFlag())
117 : {
118 0 : }
119 :
120 : // this must have the same semantics as operator=()
121 0 : SwSectionData::SwSectionData(SwSectionData const& rOther)
122 : : m_eType(rOther.m_eType)
123 : , m_sSectionName(rOther.m_sSectionName)
124 : , m_sCondition(rOther.m_sCondition)
125 : , m_sLinkFileName(rOther.m_sLinkFileName)
126 : , m_sLinkFilePassword(rOther.m_sLinkFilePassword)
127 : , m_Password(rOther.m_Password)
128 : , m_bHiddenFlag(rOther.m_bHiddenFlag)
129 : , m_bProtectFlag(rOther.m_bProtectFlag)
130 : // edit in readonly sections
131 : , m_bEditInReadonlyFlag(rOther.m_bEditInReadonlyFlag)
132 : , m_bHidden(rOther.m_bHidden)
133 : , m_bCondHiddenFlag(true)
134 0 : , m_bConnectFlag(rOther.m_bConnectFlag)
135 : {
136 0 : }
137 :
138 : // the semantics here are weird for reasons of backward compatibility
139 0 : SwSectionData & SwSectionData::operator= (SwSectionData const& rOther)
140 : {
141 0 : m_eType = rOther.m_eType;
142 0 : m_sSectionName = rOther.m_sSectionName;
143 0 : m_sCondition = rOther.m_sCondition;
144 0 : m_sLinkFileName = rOther.m_sLinkFileName;
145 0 : m_sLinkFilePassword = rOther.m_sLinkFilePassword;
146 0 : m_bConnectFlag = rOther.m_bConnectFlag;
147 0 : m_Password = rOther.m_Password;
148 :
149 0 : m_bEditInReadonlyFlag = rOther.m_bEditInReadonlyFlag;
150 0 : m_bProtectFlag = rOther.m_bProtectFlag;
151 :
152 0 : m_bHidden = rOther.m_bHidden;
153 : // FIXME: old code did not assign m_bHiddenFlag ?
154 : // FIXME: why should m_bCondHiddenFlag always default to true?
155 0 : m_bCondHiddenFlag = true;
156 :
157 0 : return *this;
158 : }
159 :
160 : // the semantics here are weird for reasons of backward compatibility
161 0 : bool SwSectionData::operator==(SwSectionData const& rOther) const
162 : {
163 0 : return (m_eType == rOther.m_eType)
164 0 : && (m_sSectionName == rOther.m_sSectionName)
165 0 : && (m_sCondition == rOther.m_sCondition)
166 0 : && (m_bHidden == rOther.m_bHidden)
167 0 : && (m_bProtectFlag == rOther.m_bProtectFlag)
168 0 : && (m_bEditInReadonlyFlag == rOther.m_bEditInReadonlyFlag)
169 0 : && (m_sLinkFileName == rOther.m_sLinkFileName)
170 0 : && (m_sLinkFilePassword == rOther.m_sLinkFilePassword)
171 0 : && (m_Password == rOther.m_Password);
172 : // FIXME: old code ignored m_bCondHiddenFlag m_bHiddenFlag m_bConnectFlag
173 : }
174 :
175 0 : OUString SwSectionData::CollapseWhiteSpaces(const OUString& sName)
176 : {
177 0 : const sal_Int32 nLen = sName.getLength();
178 0 : const sal_Unicode cRef = ' ';
179 0 : OUStringBuffer aBuf(nLen+1);
180 0 : for (sal_Int32 i = 0; i<nLen; )
181 : {
182 0 : const sal_Unicode cCur = sName[i++];
183 0 : aBuf.append(cCur);
184 0 : if (cCur!=cRef)
185 0 : continue;
186 0 : while (i<nLen && sName[i]==cRef)
187 0 : ++i;
188 : }
189 0 : return aBuf.makeStringAndClear();
190 : }
191 :
192 : // SwSection ===========================================================
193 :
194 0 : SwSection::SwSection(
195 : SectionType const eType, OUString const& rName, SwSectionFmt & rFormat)
196 : : SwClient(& rFormat)
197 0 : , m_Data(eType, rName)
198 : {
199 0 : SwSection *const pParentSect = GetParent();
200 0 : if( pParentSect )
201 : {
202 0 : if( pParentSect->IsHiddenFlag() )
203 : {
204 0 : SetHidden( true );
205 : }
206 :
207 0 : m_Data.SetProtectFlag( pParentSect->IsProtectFlag() );
208 : // edit in readonly sections
209 0 : m_Data.SetEditInReadonlyFlag( pParentSect->IsEditInReadonlyFlag() );
210 : }
211 :
212 0 : if (!m_Data.IsProtectFlag())
213 : {
214 0 : m_Data.SetProtectFlag( rFormat.GetProtect().IsCntntProtected() );
215 : }
216 :
217 0 : if (!m_Data.IsEditInReadonlyFlag()) // edit in readonly sections
218 : {
219 0 : m_Data.SetEditInReadonlyFlag( rFormat.GetEditInReadonly().GetValue() );
220 : }
221 0 : }
222 :
223 0 : SwSection::~SwSection()
224 : {
225 0 : SwSectionFmt* pFmt = GetFmt();
226 0 : if( !pFmt )
227 0 : return;
228 :
229 0 : SwDoc* pDoc = pFmt->GetDoc();
230 0 : if( pDoc->IsInDtor() )
231 : {
232 : // We reattach our Format to the default FrameFmt
233 : // to not get any dependencies
234 0 : if( pFmt->DerivedFrom() != pDoc->GetDfltFrmFmt() )
235 0 : pFmt->RegisterToFormat( *pDoc->GetDfltFrmFmt() );
236 : }
237 : else
238 : {
239 0 : pFmt->Remove( this ); // remove
240 :
241 0 : if (CONTENT_SECTION != m_Data.GetType())
242 : {
243 0 : pDoc->GetLinkManager().Remove( m_RefLink );
244 : }
245 :
246 0 : if (m_RefObj.Is())
247 : {
248 0 : pDoc->GetLinkManager().RemoveServer( &m_RefObj );
249 : }
250 :
251 : // If the Section is the last Client in the Format we can delete it
252 0 : SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFmt );
253 0 : pFmt->ModifyNotification( &aMsgHint, &aMsgHint );
254 0 : if( !pFmt->GetDepends() )
255 : {
256 : // Do not add to the Undo. This should've happened earlier.
257 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
258 0 : pDoc->DelSectionFmt( pFmt );
259 0 : }
260 : }
261 0 : if (m_RefObj.Is())
262 : {
263 0 : m_RefObj->Closed();
264 : }
265 0 : }
266 :
267 0 : void SwSection::SetSectionData(SwSectionData const& rData)
268 : {
269 0 : bool const bOldHidden( m_Data.IsHidden() );
270 0 : m_Data = rData;
271 : // The next two may actually overwrite the m_Data.m_bProtect or EditInReadonly Flag
272 : // in Modify, which should result in same flag value as the old code!
273 0 : SetProtect(m_Data.IsProtectFlag());
274 0 : SetEditInReadonly(m_Data.IsEditInReadonlyFlag());
275 0 : if (bOldHidden != m_Data.IsHidden()) // check if changed...
276 : {
277 0 : ImplSetHiddenFlag(m_Data.IsHidden(), m_Data.IsCondHidden());
278 : }
279 0 : }
280 :
281 0 : bool SwSection::DataEquals(SwSectionData const& rCmp) const
282 : {
283 : // note that the old code compared the flags of the parameter with the
284 : // format attributes of this; the following mess should do the same...
285 0 : (void) GetLinkFileName(); // updates m_sLinkFileName
286 0 : bool const bProtect(m_Data.IsProtectFlag());
287 0 : bool const bEditInReadonly(m_Data.IsEditInReadonlyFlag());
288 0 : m_Data.SetProtectFlag(IsProtect());
289 0 : m_Data.SetEditInReadonlyFlag(IsEditInReadonly());
290 0 : bool const bResult( m_Data == rCmp );
291 0 : m_Data.SetProtectFlag(bProtect);
292 0 : m_Data.SetEditInReadonlyFlag(bEditInReadonly);
293 0 : return bResult;
294 : }
295 :
296 0 : void SwSection::ImplSetHiddenFlag(bool const bTmpHidden, bool const bCondition)
297 : {
298 0 : SwSectionFmt* pFmt = GetFmt();
299 : OSL_ENSURE(pFmt, "ImplSetHiddenFlag: no format?");
300 0 : if( pFmt )
301 : {
302 0 : const bool bHide = bTmpHidden && bCondition;
303 :
304 0 : if (bHide) // should be hidden
305 : {
306 0 : if (!m_Data.IsHiddenFlag()) // is not hidden
307 : {
308 : // Is the Parent hidden?
309 : // This should be shown by the bHiddenFlag.
310 :
311 : // Tell all Children that they are hidden
312 0 : SwMsgPoolItem aMsgItem( RES_SECTION_HIDDEN );
313 0 : pFmt->ModifyNotification( &aMsgItem, &aMsgItem );
314 :
315 : // Delete all Frames
316 0 : pFmt->DelFrms();
317 : }
318 : }
319 0 : else if (m_Data.IsHiddenFlag()) // show Nodes again
320 : {
321 : // Show all Frames (Child Sections are accounted for by MakeFrms)
322 : // Only if the Parent Section is not restricting us!
323 0 : SwSection* pParentSect = pFmt->GetParentSection();
324 0 : if( !pParentSect || !pParentSect->IsHiddenFlag() )
325 : {
326 : // Tell all Children that the Parent is not hidden anymore
327 0 : SwMsgPoolItem aMsgItem( RES_SECTION_NOT_HIDDEN );
328 0 : pFmt->ModifyNotification( &aMsgItem, &aMsgItem );
329 :
330 0 : pFmt->MakeFrms();
331 : }
332 : }
333 : }
334 0 : }
335 :
336 0 : sal_Bool SwSection::CalcHiddenFlag() const
337 : {
338 0 : const SwSection* pSect = this;
339 0 : do {
340 0 : if( pSect->IsHidden() && pSect->IsCondHidden() )
341 0 : return sal_True;
342 : } while( 0 != ( pSect = pSect->GetParent()) );
343 :
344 0 : return sal_False;
345 : }
346 :
347 0 : bool SwSection::IsProtect() const
348 : {
349 0 : SwSectionFmt *const pFmt( GetFmt() );
350 : OSL_ENSURE(pFmt, "SwSection::IsProtect: no format?");
351 : return (pFmt)
352 0 : ? pFmt->GetProtect().IsCntntProtected()
353 0 : : IsProtectFlag();
354 : }
355 :
356 : // edit in readonly sections
357 0 : bool SwSection::IsEditInReadonly() const
358 : {
359 0 : SwSectionFmt *const pFmt( GetFmt() );
360 : OSL_ENSURE(pFmt, "SwSection::IsEditInReadonly: no format?");
361 : return (pFmt)
362 0 : ? pFmt->GetEditInReadonly().GetValue()
363 0 : : IsEditInReadonlyFlag();
364 : }
365 :
366 0 : void SwSection::SetHidden(bool const bFlag)
367 : {
368 0 : if (!m_Data.IsHidden() == !bFlag)
369 0 : return;
370 :
371 0 : m_Data.SetHidden(bFlag);
372 0 : ImplSetHiddenFlag(bFlag, m_Data.IsCondHidden());
373 : }
374 :
375 0 : void SwSection::SetProtect(bool const bFlag)
376 : {
377 0 : SwSectionFmt *const pFormat( GetFmt() );
378 : OSL_ENSURE(pFormat, "SwSection::SetProtect: no format?");
379 0 : if (pFormat)
380 : {
381 0 : SvxProtectItem aItem( RES_PROTECT );
382 0 : aItem.SetCntntProtect( (sal_Bool)bFlag );
383 0 : pFormat->SetFmtAttr( aItem );
384 : // note: this will call m_Data.SetProtectFlag via Modify!
385 : }
386 : else
387 : {
388 0 : m_Data.SetProtectFlag(bFlag);
389 : }
390 0 : }
391 :
392 : // edit in readonly sections
393 0 : void SwSection::SetEditInReadonly(bool const bFlag)
394 : {
395 0 : SwSectionFmt *const pFormat( GetFmt() );
396 : OSL_ENSURE(pFormat, "SwSection::SetEditInReadonly: no format?");
397 0 : if (pFormat)
398 : {
399 0 : SwFmtEditInReadonly aItem;
400 0 : aItem.SetValue( (sal_Bool)bFlag );
401 0 : pFormat->SetFmtAttr( aItem );
402 : // note: this will call m_Data.SetEditInReadonlyFlag via Modify!
403 : }
404 : else
405 : {
406 0 : m_Data.SetEditInReadonlyFlag(bFlag);
407 : }
408 0 : }
409 :
410 0 : void SwSection::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
411 : {
412 0 : bool bUpdateFtn = false;
413 0 : switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 )
414 : {
415 : case RES_ATTRSET_CHG:
416 0 : if (pNew && pOld)
417 : {
418 0 : SfxItemSet* pNewSet = ((SwAttrSetChg*)pNew)->GetChgSet();
419 0 : SfxItemSet* pOldSet = ((SwAttrSetChg*)pOld)->GetChgSet();
420 : const SfxPoolItem* pItem;
421 :
422 0 : if( SFX_ITEM_SET == pNewSet->GetItemState(
423 0 : RES_PROTECT, false, &pItem ) )
424 : {
425 : m_Data.SetProtectFlag( static_cast<SvxProtectItem const*>(pItem)
426 0 : ->IsCntntProtected() );
427 0 : pNewSet->ClearItem( RES_PROTECT );
428 0 : pOldSet->ClearItem( RES_PROTECT );
429 : }
430 :
431 : // --> edit in readonly sections
432 0 : if( SFX_ITEM_SET == pNewSet->GetItemState(
433 0 : RES_EDIT_IN_READONLY, false, &pItem ) )
434 : {
435 : m_Data.SetEditInReadonlyFlag(
436 0 : static_cast<SwFmtEditInReadonly const*>(pItem)->GetValue());
437 0 : pNewSet->ClearItem( RES_EDIT_IN_READONLY );
438 0 : pOldSet->ClearItem( RES_EDIT_IN_READONLY );
439 : }
440 :
441 0 : if( SFX_ITEM_SET == pNewSet->GetItemState(
442 0 : RES_FTN_AT_TXTEND, false, &pItem ) ||
443 : SFX_ITEM_SET == pNewSet->GetItemState(
444 0 : RES_END_AT_TXTEND, false, &pItem ))
445 : {
446 0 : bUpdateFtn = true;
447 : }
448 :
449 0 : if( !pNewSet->Count() )
450 0 : return;
451 : }
452 0 : break;
453 :
454 : case RES_PROTECT:
455 0 : if( pNew )
456 : {
457 : bool bNewFlag =
458 0 : static_cast<const SvxProtectItem*>(pNew)->IsCntntProtected();
459 0 : if( !bNewFlag )
460 : {
461 : // Switching off: See if there is protection transferred
462 : // by the Parents
463 0 : const SwSection* pSect = this;
464 0 : do {
465 0 : if( pSect->IsProtect() )
466 : {
467 0 : bNewFlag = true;
468 0 : break;
469 : }
470 0 : pSect = pSect->GetParent();
471 : } while (pSect);
472 : }
473 :
474 0 : m_Data.SetProtectFlag( bNewFlag );
475 : }
476 0 : return;
477 : // edit in readonly sections
478 : case RES_EDIT_IN_READONLY:
479 0 : if( pNew )
480 : {
481 : const bool bNewFlag =
482 0 : static_cast<const SwFmtEditInReadonly*>(pNew)->GetValue();
483 0 : m_Data.SetEditInReadonlyFlag( bNewFlag );
484 : }
485 0 : return;
486 :
487 : case RES_SECTION_HIDDEN:
488 0 : m_Data.SetHiddenFlag(true);
489 0 : return;
490 :
491 : case RES_SECTION_NOT_HIDDEN:
492 : case RES_SECTION_RESETHIDDENFLAG:
493 0 : m_Data.SetHiddenFlag( m_Data.IsHidden() && m_Data.IsCondHidden() );
494 0 : return;
495 :
496 : case RES_COL:
497 : // Is handeled by the Layout, if appropriate
498 0 : break;
499 :
500 : case RES_FTN_AT_TXTEND:
501 0 : if( pNew && pOld )
502 : {
503 0 : bUpdateFtn = true;
504 : }
505 0 : break;
506 :
507 : case RES_END_AT_TXTEND:
508 0 : if( pNew && pOld )
509 : {
510 0 : bUpdateFtn = true;
511 : }
512 0 : break;
513 :
514 : default:
515 0 : CheckRegistration( pOld, pNew );
516 0 : break;
517 : }
518 :
519 0 : if( bUpdateFtn )
520 : {
521 0 : SwSectionNode* pSectNd = GetFmt()->GetSectionNode( false );
522 0 : if( pSectNd )
523 0 : pSectNd->GetDoc()->GetFtnIdxs().UpdateFtn(SwNodeIndex( *pSectNd ));
524 : }
525 : }
526 :
527 0 : void SwSection::SetRefObject( SwServerObject* pObj )
528 : {
529 0 : m_RefObj = pObj;
530 0 : }
531 :
532 0 : void SwSection::SetCondHidden(bool const bFlag)
533 : {
534 0 : if (!m_Data.IsCondHidden() == !bFlag)
535 0 : return;
536 :
537 0 : m_Data.SetCondHidden(bFlag);
538 0 : ImplSetHiddenFlag(m_Data.IsHidden(), bFlag);
539 : }
540 :
541 : // Set/remove the linked FileName
542 0 : OUString SwSection::GetLinkFileName() const
543 : {
544 0 : if (m_RefLink.Is())
545 : {
546 0 : OUString sTmp;
547 0 : switch (m_Data.GetType())
548 : {
549 : case DDE_LINK_SECTION:
550 0 : sTmp = m_RefLink->GetLinkSourceName();
551 0 : break;
552 :
553 : case FILE_LINK_SECTION:
554 : {
555 0 : OUString sRange;
556 0 : OUString sFilter;
557 0 : if (m_RefLink->GetLinkManager() &&
558 : m_RefLink->GetLinkManager()->GetDisplayNames(
559 0 : m_RefLink, 0, &sTmp, &sRange, &sFilter ))
560 : {
561 0 : sTmp += OUString(sfx2::cTokenSeparator) + sFilter
562 0 : + OUString(sfx2::cTokenSeparator) + sRange;
563 : }
564 0 : else if( GetFmt() && !GetFmt()->GetSectionNode() )
565 : {
566 : // If the Section is in the UndoNodesArray, the LinkManager
567 : // does not contain the Link, thus it cannot be queried for it.
568 : // Thus return the current Name.
569 0 : return m_Data.GetLinkFileName();
570 0 : }
571 : }
572 0 : break;
573 0 : default: break;
574 : }
575 0 : m_Data.SetLinkFileName(sTmp);
576 : }
577 0 : return m_Data.GetLinkFileName();
578 : }
579 :
580 0 : void SwSection::SetLinkFileName(const OUString& rNew, OUString const*const pPassWd)
581 : {
582 0 : if (m_RefLink.Is())
583 : {
584 0 : m_RefLink->SetLinkSourceName( rNew );
585 : }
586 0 : m_Data.SetLinkFileName(rNew);
587 0 : if( pPassWd )
588 : {
589 0 : SetLinkFilePassword( *pPassWd );
590 : }
591 0 : }
592 :
593 : // If it was a Linked Section, we need to make all Child Links visible
594 0 : void SwSection::MakeChildLinksVisible( const SwSectionNode& rSectNd )
595 : {
596 : const SwNode* pNd;
597 0 : const ::sfx2::SvBaseLinks& rLnks = rSectNd.GetDoc()->GetLinkManager().GetLinks();
598 0 : for( sal_uInt16 n = rLnks.size(); n; )
599 : {
600 0 : ::sfx2::SvBaseLink* pBLnk = &(*rLnks[ --n ]);
601 0 : if( pBLnk && !pBLnk->IsVisible() &&
602 0 : pBLnk->ISA( SwBaseLink ) &&
603 0 : 0 != ( pNd = ((SwBaseLink*)pBLnk)->GetAnchor() ) )
604 : {
605 0 : pNd = pNd->StartOfSectionNode(); // If it's a SectionNode
606 : const SwSectionNode* pParent;
607 0 : while( 0 != ( pParent = pNd->FindSectionNode() ) &&
608 0 : ( CONTENT_SECTION == pParent->GetSection().GetType()
609 0 : || pNd == &rSectNd ))
610 0 : pNd = pParent->StartOfSectionNode();
611 :
612 : // It's within a normal Section, so show again
613 0 : if( !pParent )
614 0 : pBLnk->SetVisible( true );
615 : }
616 : }
617 0 : }
618 :
619 0 : const SwTOXBase* SwSection::GetTOXBase() const
620 : {
621 0 : const SwTOXBase* pRet = 0;
622 0 : if( TOX_CONTENT_SECTION == GetType() )
623 0 : pRet = PTR_CAST( SwTOXBaseSection, this );
624 0 : return pRet;
625 : }
626 :
627 : // SwSectionFmt ========================================================
628 :
629 0 : SwSectionFmt::SwSectionFmt( SwSectionFmt* pDrvdFrm, SwDoc *pDoc )
630 0 : : SwFrmFmt( pDoc->GetAttrPool(), OUString(), pDrvdFrm )
631 : {
632 0 : LockModify();
633 0 : SetFmtAttr( *GetDfltAttr( RES_COL ) );
634 0 : UnlockModify();
635 0 : }
636 :
637 0 : SwSectionFmt::~SwSectionFmt()
638 : {
639 0 : if( !GetDoc()->IsInDtor() )
640 : {
641 : SwSectionNode* pSectNd;
642 0 : const SwNodeIndex* pIdx = GetCntnt( sal_False ).GetCntntIdx();
643 0 : if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
644 0 : 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
645 : {
646 0 : SwSection& rSect = pSectNd->GetSection();
647 : // If it was a linked Section, we need to make all Child Links
648 : // visible again
649 0 : if( rSect.IsConnected() )
650 0 : rSect.MakeChildLinksVisible( *pSectNd );
651 :
652 : // Check whether we need to be visible, before deleting the Nodes
653 0 : if( rSect.IsHiddenFlag() )
654 : {
655 0 : SwSection* pParentSect = rSect.GetParent();
656 0 : if( !pParentSect || !pParentSect->IsHiddenFlag() )
657 : {
658 : // Make Nodes visible again
659 0 : rSect.SetHidden(false);
660 : }
661 : }
662 : // mba: test iteration; objects are removed while iterating
663 : // use hint which allows to specify, if the content shall be saved or not
664 0 : CallSwClientNotify( SwSectionFrmMoveAndDeleteHint( sal_True ) );
665 :
666 : // Raise the Section up
667 0 : SwNodeRange aRg( *pSectNd, 0, *pSectNd->EndOfSectionNode() );
668 0 : GetDoc()->GetNodes().SectionUp( &aRg );
669 : }
670 0 : LockModify();
671 0 : ResetFmtAttr( RES_CNTNT );
672 0 : UnlockModify();
673 : }
674 0 : }
675 :
676 0 : SwSection * SwSectionFmt::GetSection() const
677 : {
678 0 : return SwIterator<SwSection,SwSectionFmt>::FirstElement( *this );
679 : }
680 :
681 : extern void sw_DeleteFtn( SwSectionNode *pNd, sal_uLong nStt, sal_uLong nEnd );
682 :
683 : // Do not destroy all Frms in aDepend (Frms are recognized with a PTR_CAST).
684 0 : void SwSectionFmt::DelFrms()
685 : {
686 : SwSectionNode* pSectNd;
687 0 : const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx();
688 0 : if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
689 0 : 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
690 : {
691 : // First delete the <SwSectionFrm> of the <SwSectionFmt> instance
692 : // mba: test iteration as objects are removed in iteration
693 : // use hint which allows to specify, if the content shall be saved or not
694 0 : CallSwClientNotify( SwSectionFrmMoveAndDeleteHint( sal_False ) );
695 :
696 : // Then delete frames of the nested <SwSectionFmt> instances
697 0 : SwIterator<SwSectionFmt,SwSectionFmt> aIter( *this );
698 0 : SwSectionFmt *pLast = aIter.First();
699 0 : while ( pLast )
700 : {
701 0 : pLast->DelFrms();
702 0 : pLast = aIter.Next();
703 : }
704 :
705 0 : sal_uLong nEnde = pSectNd->EndOfSectionIndex();
706 0 : sal_uLong nStart = pSectNd->GetIndex()+1;
707 0 : sw_DeleteFtn( pSectNd, nStart, nEnde );
708 : }
709 0 : if( pIdx )
710 : {
711 : // Send Hint for PageDesc. Actually the Layout contained in the
712 : // Paste of the Framei tself would need to do this. But that leads
713 : // to subsequent errors, which we'd need to solve at run-time.
714 0 : SwNodeIndex aNextNd( *pIdx );
715 0 : SwCntntNode* pCNd = GetDoc()->GetNodes().GoNextSection( &aNextNd, true, false );
716 0 : if( pCNd )
717 : {
718 0 : const SfxPoolItem& rItem = pCNd->GetSwAttrSet().Get( RES_PAGEDESC );
719 0 : pCNd->ModifyNotification( (SfxPoolItem*)&rItem, (SfxPoolItem*)&rItem );
720 0 : }
721 : }
722 0 : }
723 :
724 : // Create the Views
725 0 : void SwSectionFmt::MakeFrms()
726 : {
727 : SwSectionNode* pSectNd;
728 0 : const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx();
729 :
730 0 : if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
731 0 : 0 != (pSectNd = pIdx->GetNode().GetSectionNode() ))
732 : {
733 0 : SwNodeIndex aIdx( *pIdx );
734 0 : pSectNd->MakeFrms( &aIdx );
735 : }
736 0 : }
737 :
738 0 : void SwSectionFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
739 : {
740 0 : bool bClients = false;
741 0 : sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
742 0 : switch( nWhich )
743 : {
744 : case RES_ATTRSET_CHG:
745 0 : if (GetDepends() && pOld && pNew)
746 : {
747 0 : SfxItemSet* pNewSet = ((SwAttrSetChg*)pNew)->GetChgSet();
748 0 : SfxItemSet* pOldSet = ((SwAttrSetChg*)pOld)->GetChgSet();
749 : const SfxPoolItem *pItem;
750 0 : if( SFX_ITEM_SET == pNewSet->GetItemState(
751 0 : RES_PROTECT, false, &pItem ))
752 : {
753 0 : ModifyBroadcast( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem );
754 0 : pNewSet->ClearItem( RES_PROTECT );
755 0 : pOldSet->ClearItem( RES_PROTECT );
756 : }
757 :
758 : // --> edit in readonly sections
759 0 : if( SFX_ITEM_SET == pNewSet->GetItemState(
760 0 : RES_EDIT_IN_READONLY, false, &pItem ) )
761 : {
762 0 : ModifyBroadcast( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem );
763 0 : pNewSet->ClearItem( RES_EDIT_IN_READONLY );
764 0 : pOldSet->ClearItem( RES_EDIT_IN_READONLY );
765 : }
766 :
767 0 : if( SFX_ITEM_SET == pNewSet->GetItemState(
768 0 : RES_FTN_AT_TXTEND, false, &pItem ))
769 : {
770 0 : ModifyBroadcast( (SfxPoolItem*)&pOldSet->Get( RES_FTN_AT_TXTEND ), (SfxPoolItem*)pItem );
771 0 : pNewSet->ClearItem( RES_FTN_AT_TXTEND );
772 0 : pOldSet->ClearItem( RES_FTN_AT_TXTEND );
773 : }
774 0 : if( SFX_ITEM_SET == pNewSet->GetItemState(
775 0 : RES_END_AT_TXTEND, false, &pItem ))
776 : {
777 0 : ModifyBroadcast( (SfxPoolItem*)&pOldSet->Get( RES_END_AT_TXTEND ), (SfxPoolItem*)pItem );
778 0 : pNewSet->ClearItem( RES_END_AT_TXTEND );
779 0 : pOldSet->ClearItem( RES_END_AT_TXTEND );
780 : }
781 0 : if( !((SwAttrSetChg*)pOld)->GetChgSet()->Count() )
782 0 : return;
783 : }
784 0 : break;
785 :
786 : case RES_SECTION_RESETHIDDENFLAG:
787 : case RES_FTN_AT_TXTEND:
788 0 : case RES_END_AT_TXTEND : bClients = true;
789 : // no break !!
790 : case RES_SECTION_HIDDEN:
791 : case RES_SECTION_NOT_HIDDEN:
792 : {
793 0 : SwSection* pSect = GetSection();
794 0 : if( pSect && ( bClients || ( RES_SECTION_HIDDEN == nWhich ?
795 0 : !pSect->IsHiddenFlag() : pSect->IsHiddenFlag() ) ) )
796 : {
797 0 : ModifyBroadcast( pOld, pNew );
798 : }
799 : }
800 0 : return ;
801 :
802 : case RES_PROTECT:
803 : case RES_EDIT_IN_READONLY: // edit in readonly sections
804 : // Pass through these Messages until the End of the tree!
805 0 : if( GetDepends() )
806 : {
807 0 : ModifyBroadcast( pOld, pNew );
808 : }
809 0 : return; // That's it!
810 :
811 : case RES_OBJECTDYING:
812 0 : if( !GetDoc()->IsInDtor() && pOld &&
813 0 : ((SwPtrMsgPoolItem *)pOld)->pObject == (void*)GetRegisteredIn() )
814 : {
815 : // My Parents will be destroyed, so get the Parent's Parent
816 : // and update
817 0 : SwFrmFmt::Modify( pOld, pNew ); // Rewire first!
818 0 : UpdateParent();
819 0 : return;
820 : }
821 0 : break;
822 :
823 : case RES_FMT_CHG:
824 0 : if( !GetDoc()->IsInDtor() &&
825 0 : ((SwFmtChg*)pNew)->pChangedFmt == (void*)GetRegisteredIn() &&
826 0 : ((SwFmtChg*)pNew)->pChangedFmt->IsA( TYPE( SwSectionFmt )) )
827 : {
828 : // My Parent will be changed, thus I need to update
829 0 : SwFrmFmt::Modify( pOld, pNew ); // Rewire first!
830 0 : UpdateParent();
831 0 : return;
832 : }
833 0 : break;
834 : }
835 0 : SwFrmFmt::Modify( pOld, pNew );
836 :
837 0 : if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
838 : { // invalidate cached uno object
839 0 : SetXTextSection(uno::Reference<text::XTextSection>(0));
840 : }
841 : }
842 :
843 : // Get info from the Format
844 0 : bool SwSectionFmt::GetInfo( SfxPoolItem& rInfo ) const
845 : {
846 0 : switch( rInfo.Which() )
847 : {
848 : case RES_FINDNEARESTNODE:
849 0 : if( ((SwFmtPageDesc&)GetFmtAttr( RES_PAGEDESC )).GetPageDesc() )
850 : {
851 0 : const SwSectionNode* pNd = GetSectionNode();
852 0 : if( pNd )
853 0 : ((SwFindNearestNode&)rInfo).CheckNode( *pNd );
854 : }
855 0 : return true;
856 :
857 : case RES_CONTENT_VISIBLE:
858 : {
859 0 : SwFrm* pFrm = SwIterator<SwFrm,SwFmt>::FirstElement(*this);
860 : // if the current section has no own frame search for the children
861 0 : if(!pFrm)
862 : {
863 0 : SwIterator<SwSectionFmt,SwSectionFmt> aFormatIter(*this);
864 0 : SwSectionFmt* pChild = aFormatIter.First();
865 0 : while(pChild && !pFrm)
866 : {
867 0 : pFrm = SwIterator<SwFrm,SwFmt>::FirstElement(*pChild);
868 0 : pChild = aFormatIter.Next();
869 0 : }
870 : }
871 0 : ((SwPtrMsgPoolItem&)rInfo).pObject = pFrm;
872 : }
873 0 : return false;
874 : }
875 0 : return SwModify::GetInfo( rInfo );
876 : }
877 :
878 0 : static bool lcl_SectionCmpPos( const SwSection *pFirst, const SwSection *pSecond)
879 : {
880 0 : const SwSectionFmt* pFSectFmt = pFirst->GetFmt();
881 0 : const SwSectionFmt* pSSectFmt = pSecond->GetFmt();
882 : OSL_ENSURE( pFSectFmt && pSSectFmt &&
883 : pFSectFmt->GetCntnt(sal_False).GetCntntIdx() &&
884 : pSSectFmt->GetCntnt(sal_False).GetCntntIdx(),
885 : "ungueltige Sections" );
886 0 : return pFSectFmt->GetCntnt(sal_False).GetCntntIdx()->GetIndex() <
887 0 : pSSectFmt->GetCntnt(sal_False).GetCntntIdx()->GetIndex();
888 : }
889 :
890 0 : static bool lcl_SectionCmpNm( const SwSection *pFSect, const SwSection *pSSect)
891 : {
892 : OSL_ENSURE( pFSect && pSSect, "Invalid Sections" );
893 0 : return pFSect->GetSectionName() < pSSect->GetSectionName();
894 : }
895 :
896 : // get all Sections that have been derived from this one
897 0 : sal_uInt16 SwSectionFmt::GetChildSections( SwSections& rArr,
898 : SectionSort eSort,
899 : sal_Bool bAllSections ) const
900 : {
901 0 : rArr.clear();
902 :
903 0 : if( GetDepends() )
904 : {
905 0 : SwIterator<SwSectionFmt,SwSectionFmt> aIter(*this);
906 : const SwNodeIndex* pIdx;
907 0 : for( SwSectionFmt* pLast = aIter.First(); pLast; pLast = aIter.Next() )
908 0 : if( bAllSections ||
909 0 : ( 0 != ( pIdx = pLast->GetCntnt(sal_False).
910 0 : GetCntntIdx()) && &pIdx->GetNodes() == &GetDoc()->GetNodes() ))
911 : {
912 0 : SwSection* pDummy = pLast->GetSection();
913 0 : rArr.push_back( pDummy );
914 : }
915 :
916 : // Do we need any sorting?
917 0 : if( 1 < rArr.size() )
918 0 : switch( eSort )
919 : {
920 : case SORTSECT_NAME:
921 0 : std::sort( rArr.begin(), rArr.end(), lcl_SectionCmpNm );
922 0 : break;
923 :
924 : case SORTSECT_POS:
925 0 : std::sort( rArr.begin(), rArr.end(), lcl_SectionCmpPos );
926 0 : break;
927 0 : case SORTSECT_NOT: break;
928 0 : }
929 : }
930 0 : return rArr.size();
931 : }
932 :
933 : // See whether the Section is within the Nodes or the UndoNodes array
934 0 : sal_Bool SwSectionFmt::IsInNodesArr() const
935 : {
936 0 : const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx();
937 0 : return pIdx && &pIdx->GetNodes() == &GetDoc()->GetNodes();
938 : }
939 :
940 : // Parent was changed
941 0 : void SwSectionFmt::UpdateParent()
942 : {
943 0 : if( !GetDepends() )
944 0 : return;
945 :
946 0 : SwSection* pSection = 0;
947 0 : const SvxProtectItem* pProtect(0);
948 : // edit in readonly sections
949 0 : const SwFmtEditInReadonly* pEditInReadonly = 0;
950 0 : bool bIsHidden = false;
951 :
952 0 : SwClientIter aIter( *this ); // TODO
953 0 : ::SwClient * pLast = aIter.GoStart();
954 0 : if( pLast ) // Could we jump to the beginning?
955 0 : do {
956 0 : if( pLast->IsA( TYPE(SwSectionFmt) ) )
957 : {
958 0 : if( !pSection )
959 : {
960 0 : pSection = GetSection();
961 0 : if( GetRegisteredIn() )
962 : {
963 0 : const SwSection* pPS = GetParentSection();
964 0 : pProtect = &pPS->GetFmt()->GetProtect();
965 : // edit in readonly sections
966 0 : pEditInReadonly = &pPS->GetFmt()->GetEditInReadonly();
967 0 : bIsHidden = pPS->IsHiddenFlag();
968 : }
969 : else
970 : {
971 0 : pProtect = &GetProtect();
972 : // edit in readonly sections
973 0 : pEditInReadonly = &GetEditInReadonly();
974 0 : bIsHidden = pSection->IsHidden();
975 : }
976 : }
977 0 : if (!pProtect->IsCntntProtected() !=
978 0 : !pSection->IsProtectFlag())
979 : {
980 : pLast->ModifyNotification( (SfxPoolItem*)pProtect,
981 0 : (SfxPoolItem*)pProtect );
982 : }
983 :
984 : // edit in readonly sections
985 0 : if (!pEditInReadonly->GetValue() !=
986 0 : !pSection->IsEditInReadonlyFlag())
987 : {
988 : pLast->ModifyNotification( (SfxPoolItem*)pEditInReadonly,
989 0 : (SfxPoolItem*)pEditInReadonly );
990 : }
991 :
992 0 : if( bIsHidden == pSection->IsHiddenFlag() )
993 : {
994 : SwMsgPoolItem aMsgItem( static_cast<sal_uInt16>(bIsHidden
995 : ? RES_SECTION_HIDDEN
996 0 : : RES_SECTION_NOT_HIDDEN ) );
997 0 : pLast->ModifyNotification( &aMsgItem, &aMsgItem );
998 : }
999 : }
1000 0 : else if( !pSection &&
1001 0 : pLast->IsA( TYPE(SwSection) ) )
1002 : {
1003 0 : pSection = (SwSection*)pLast;
1004 0 : if( GetRegisteredIn() )
1005 : {
1006 0 : const SwSection* pPS = GetParentSection();
1007 0 : pProtect = &pPS->GetFmt()->GetProtect();
1008 : // edit in readonly sections
1009 0 : pEditInReadonly = &pPS->GetFmt()->GetEditInReadonly();
1010 0 : bIsHidden = pPS->IsHiddenFlag();
1011 : }
1012 : else
1013 : {
1014 0 : pProtect = &GetProtect();
1015 : // edit in readonly sections
1016 0 : pEditInReadonly = &GetEditInReadonly();
1017 0 : bIsHidden = pSection->IsHidden();
1018 : }
1019 : }
1020 0 : } while( 0 != ( pLast = ++aIter ));
1021 : }
1022 :
1023 0 : SwSectionNode* SwSectionFmt::GetSectionNode(bool const bAlways)
1024 : {
1025 0 : const SwNodeIndex* pIdx = GetCntnt(sal_False).GetCntntIdx();
1026 0 : if( pIdx && ( bAlways || &pIdx->GetNodes() == &GetDoc()->GetNodes() ))
1027 0 : return pIdx->GetNode().GetSectionNode();
1028 0 : return 0;
1029 : }
1030 :
1031 : // Is this Section valid for the GlobalDocument?
1032 0 : const SwSection* SwSectionFmt::GetGlobalDocSection() const
1033 : {
1034 0 : const SwSectionNode* pNd = GetSectionNode();
1035 0 : if( pNd &&
1036 0 : ( FILE_LINK_SECTION == pNd->GetSection().GetType() ||
1037 0 : TOX_CONTENT_SECTION == pNd->GetSection().GetType() ) &&
1038 0 : pNd->GetIndex() > pNd->GetNodes().GetEndOfExtras().GetIndex() &&
1039 0 : !pNd->StartOfSectionNode()->IsSectionNode() &&
1040 0 : !pNd->StartOfSectionNode()->FindSectionNode() )
1041 0 : return &pNd->GetSection();
1042 0 : return 0;
1043 : }
1044 :
1045 : // sw::Metadatable
1046 0 : ::sfx2::IXmlIdRegistry& SwSectionFmt::GetRegistry()
1047 : {
1048 0 : return GetDoc()->GetXmlIdRegistry();
1049 : }
1050 :
1051 0 : bool SwSectionFmt::IsInClipboard() const
1052 : {
1053 0 : return GetDoc()->IsClipBoard();
1054 : }
1055 :
1056 0 : bool SwSectionFmt::IsInUndo() const
1057 : {
1058 0 : return !IsInNodesArr();
1059 : }
1060 :
1061 0 : bool SwSectionFmt::IsInContent() const
1062 : {
1063 0 : SwNodeIndex const*const pIdx = GetCntnt(sal_False).GetCntntIdx();
1064 : OSL_ENSURE(pIdx, "SwSectionFmt::IsInContent: no index?");
1065 0 : return (pIdx) ? !GetDoc()->IsInHeaderFooter(*pIdx) : true;
1066 : }
1067 :
1068 : // n.b.: if the section format represents an index, then there is both a
1069 : // SwXDocumentIndex and a SwXTextSection instance for this single core object.
1070 : // these two can both implement XMetadatable and forward to the same core
1071 : // section format. but here only one UNO object can be returned,
1072 : // so always return the text section.
1073 : uno::Reference< rdf::XMetadatable >
1074 0 : SwSectionFmt::MakeUnoObject()
1075 : {
1076 0 : uno::Reference<rdf::XMetadatable> xMeta;
1077 0 : SwSection *const pSection( GetSection() );
1078 0 : if (pSection)
1079 : {
1080 : xMeta.set( SwXTextSection::CreateXTextSection(this,
1081 0 : TOX_HEADER_SECTION == pSection->GetType()),
1082 0 : uno::UNO_QUERY );
1083 : }
1084 0 : return xMeta;
1085 : }
1086 :
1087 : // Method to break section links inside a linked section
1088 0 : static void lcl_BreakSectionLinksInSect( const SwSectionNode& rSectNd )
1089 : {
1090 0 : if ( !rSectNd.GetDoc() )
1091 : {
1092 : OSL_FAIL( "method <lcl_RemoveSectionLinksInSect(..)> - no Doc at SectionNode" );
1093 0 : return;
1094 : }
1095 :
1096 0 : if ( !rSectNd.GetSection().IsConnected() )
1097 : {
1098 : OSL_FAIL( "method <lcl_RemoveSectionLinksInSect(..)> - no Link at Section of SectionNode" );
1099 0 : return;
1100 : }
1101 0 : const ::sfx2::SvBaseLink* pOwnLink( &(rSectNd.GetSection().GetBaseLink() ) );
1102 0 : const ::sfx2::SvBaseLinks& rLnks = rSectNd.GetDoc()->GetLinkManager().GetLinks();
1103 0 : for ( sal_uInt16 n = rLnks.size(); n > 0; )
1104 : {
1105 0 : SwIntrnlSectRefLink* pSectLnk = dynamic_cast<SwIntrnlSectRefLink*>(&(*rLnks[ --n ]));
1106 0 : if ( pSectLnk && pSectLnk != pOwnLink &&
1107 0 : pSectLnk->IsInRange( rSectNd.GetIndex(), rSectNd.EndOfSectionIndex() ) )
1108 : {
1109 : // break the link of the corresponding section.
1110 : // the link is also removed from the link manager
1111 0 : pSectLnk->GetSectNode()->GetSection().BreakLink();
1112 :
1113 : // for robustness, because link is removed from the link manager
1114 0 : if ( n > rLnks.size() )
1115 : {
1116 0 : n = rLnks.size();
1117 : }
1118 : }
1119 : }
1120 : }
1121 :
1122 0 : static void lcl_UpdateLinksInSect( SwBaseLink& rUpdLnk, SwSectionNode& rSectNd )
1123 : {
1124 0 : SwDoc* pDoc = rSectNd.GetDoc();
1125 0 : SwDocShell* pDShell = pDoc->GetDocShell();
1126 0 : if( !pDShell || !pDShell->GetMedium() )
1127 0 : return ;
1128 :
1129 0 : const OUString sName( pDShell->GetMedium()->GetName() );
1130 : SwBaseLink* pBLink;
1131 0 : const OUString sMimeType( SotExchange::GetFormatMimeType( FORMAT_FILE ));
1132 0 : uno::Any aValue;
1133 0 : aValue <<= sName; // Arbitrary name
1134 :
1135 0 : const ::sfx2::SvBaseLinks& rLnks = pDoc->GetLinkManager().GetLinks();
1136 0 : for( sal_uInt16 n = rLnks.size(); n; )
1137 : {
1138 0 : ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]);
1139 0 : if( pLnk && pLnk != &rUpdLnk &&
1140 0 : OBJECT_CLIENT_FILE == pLnk->GetObjType() &&
1141 0 : pLnk->ISA( SwBaseLink ) &&
1142 : ( pBLink = (SwBaseLink*)pLnk )->IsInRange( rSectNd.GetIndex(),
1143 0 : rSectNd.EndOfSectionIndex() ) )
1144 : {
1145 : // It's in the Section, so update. But only if it's not in the same File!
1146 0 : OUString sFName;
1147 0 : pDoc->GetLinkManager().GetDisplayNames( pBLink, 0, &sFName, 0, 0 );
1148 0 : if( sFName != sName )
1149 : {
1150 0 : pBLink->DataChanged( sMimeType, aValue );
1151 :
1152 : // If needed find the Link pointer to avoid skipping one or calling one twice
1153 0 : if( n >= rLnks.size() && 0 != ( n = rLnks.size() ))
1154 0 : --n;
1155 :
1156 0 : if( n && pLnk != &(*rLnks[ n ]) )
1157 : {
1158 : // Find - it can only precede it!
1159 0 : while( n )
1160 0 : if( pLnk == &(*rLnks[ --n ] ) )
1161 0 : break;
1162 : }
1163 0 : }
1164 : }
1165 0 : }
1166 : }
1167 :
1168 0 : ::sfx2::SvBaseLink::UpdateResult SwIntrnlSectRefLink::DataChanged(
1169 : const OUString& rMimeType, const uno::Any & rValue )
1170 : {
1171 0 : SwSectionNode* pSectNd = rSectFmt.GetSectionNode( false );
1172 0 : SwDoc* pDoc = rSectFmt.GetDoc();
1173 :
1174 0 : sal_uLong nDataFormat = SotExchange::GetFormatIdFromMimeType( rMimeType );
1175 :
1176 0 : if( !pSectNd || !pDoc || pDoc->IsInDtor() || ChkNoDataFlag() ||
1177 0 : sfx2::LinkManager::RegisterStatusInfoId() == nDataFormat )
1178 : {
1179 : // Should we be in the Undo already?
1180 0 : return SUCCESS;
1181 : }
1182 :
1183 : // #i38810# - Due to possible existing signatures, the
1184 : // document has to be modified after updating a link.
1185 0 : pDoc->SetModified();
1186 : // set additional flag that links have been updated, in order to check this
1187 : // during load.
1188 0 : pDoc->SetLinksUpdated( true );
1189 :
1190 : // Always switch off Undo
1191 0 : bool const bWasUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
1192 0 : pDoc->GetIDocumentUndoRedo().DoUndo(false);
1193 0 : sal_Bool bWasVisibleLinks = pDoc->IsVisibleLinks();
1194 0 : pDoc->SetVisibleLinks( false );
1195 :
1196 : SwPaM* pPam;
1197 0 : SwViewShell* pVSh = 0;
1198 0 : SwEditShell* pESh = pDoc->GetEditShell( &pVSh );
1199 0 : pDoc->LockExpFlds();
1200 : {
1201 : // Insert an empty TextNode at the Section's start
1202 0 : SwNodeIndex aIdx( *pSectNd, +1 );
1203 0 : SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() );
1204 0 : SwTxtNode* pNewNd = pDoc->GetNodes().MakeTxtNode( aIdx,
1205 0 : pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT ) );
1206 :
1207 0 : if( pESh )
1208 0 : pESh->StartAllAction();
1209 0 : else if( pVSh )
1210 0 : pVSh->StartAction();
1211 :
1212 0 : SwPosition aPos( aIdx, SwIndex( pNewNd, 0 ));
1213 0 : aPos.nNode--;
1214 0 : pDoc->CorrAbs( aIdx, aEndIdx, aPos, sal_True );
1215 :
1216 0 : pPam = new SwPaM( aPos );
1217 :
1218 : // Delete everything succeeding it
1219 0 : aIdx--;
1220 0 : DelFlyInRange( aIdx, aEndIdx );
1221 0 : _DelBookmarks(aIdx, aEndIdx);
1222 0 : ++aIdx;
1223 :
1224 0 : pDoc->GetNodes().Delete( aIdx, aEndIdx.GetIndex() - aIdx.GetIndex() );
1225 : }
1226 :
1227 0 : SwSection& rSection = pSectNd->GetSection();
1228 0 : rSection.SetConnectFlag(false);
1229 :
1230 0 : Reader* pRead = 0;
1231 0 : switch( nDataFormat )
1232 : {
1233 : case FORMAT_STRING:
1234 0 : pRead = ReadAscii;
1235 0 : break;
1236 :
1237 : case FORMAT_RTF:
1238 0 : pRead = SwReaderWriter::GetReader( READER_WRITER_RTF );
1239 0 : break;
1240 :
1241 : case FORMAT_FILE:
1242 0 : if ( rValue.hasValue() )
1243 : {
1244 0 : OUString sFileName;
1245 0 : if ( !(rValue >>= sFileName) )
1246 0 : break;
1247 0 : OUString sFilter;
1248 0 : OUString sRange;
1249 0 : pDoc->GetLinkManager().GetDisplayNames( this, 0, &sFileName,
1250 0 : &sRange, &sFilter );
1251 :
1252 0 : RedlineMode_t eOldRedlineMode = nsRedlineMode_t::REDLINE_NONE;
1253 0 : SfxObjectShellRef xDocSh;
1254 0 : SfxObjectShellLock xLockRef;
1255 : int nRet;
1256 0 : if( sFileName.isEmpty() )
1257 : {
1258 0 : xDocSh = pDoc->GetDocShell();
1259 0 : nRet = 1;
1260 : }
1261 : else
1262 : {
1263 : nRet = SwFindDocShell( xDocSh, xLockRef, sFileName,
1264 : rSection.GetLinkFilePassword(),
1265 0 : sFilter, 0, pDoc->GetDocShell() );
1266 0 : if( nRet )
1267 : {
1268 0 : SwDoc* pSrcDoc = ((SwDocShell*)&xDocSh)->GetDoc();
1269 0 : eOldRedlineMode = pSrcDoc->GetRedlineMode();
1270 0 : pSrcDoc->SetRedlineMode( nsRedlineMode_t::REDLINE_SHOW_INSERT );
1271 : }
1272 : }
1273 :
1274 0 : if( nRet )
1275 : {
1276 0 : rSection.SetConnectFlag(true);
1277 :
1278 0 : SwNodeIndex aSave( pPam->GetPoint()->nNode, -1 );
1279 0 : SwNodeRange* pCpyRg = 0;
1280 :
1281 0 : if( xDocSh->GetMedium() &&
1282 0 : rSection.GetLinkFilePassword().isEmpty() )
1283 : {
1284 : const SfxPoolItem* pItem;
1285 0 : if( SFX_ITEM_SET == xDocSh->GetMedium()->GetItemSet()->
1286 0 : GetItemState( SID_PASSWORD, false, &pItem ) )
1287 : rSection.SetLinkFilePassword(
1288 0 : ((SfxStringItem*)pItem)->GetValue() );
1289 : }
1290 :
1291 0 : SwDoc* pSrcDoc = ((SwDocShell*)&xDocSh)->GetDoc();
1292 :
1293 0 : if( !sRange.isEmpty() )
1294 : {
1295 : // Catch recursion
1296 0 : bool bRecursion = false;
1297 0 : if( pSrcDoc == pDoc )
1298 : {
1299 : SwServerObjectRef refObj( (SwServerObject*)
1300 0 : pDoc->CreateLinkSource( sRange ));
1301 0 : if( refObj.Is() )
1302 : {
1303 0 : bRecursion = refObj->IsLinkInServer( this ) ||
1304 0 : ChkNoDataFlag();
1305 0 : }
1306 : }
1307 :
1308 0 : SwNodeIndex& rInsPos = pPam->GetPoint()->nNode;
1309 :
1310 0 : SwPaM* pCpyPam = 0;
1311 0 : if( !bRecursion &&
1312 0 : pSrcDoc->SelectServerObj( sRange, pCpyPam, pCpyRg )
1313 0 : && pCpyPam )
1314 : {
1315 0 : if( pSrcDoc != pDoc ||
1316 0 : pCpyPam->Start()->nNode > rInsPos ||
1317 0 : rInsPos >= pCpyPam->End()->nNode )
1318 : {
1319 0 : pSrcDoc->CopyRange( *pCpyPam, *pPam->GetPoint(),
1320 0 : false );
1321 : }
1322 0 : delete pCpyPam;
1323 : }
1324 0 : if( pCpyRg && pSrcDoc == pDoc &&
1325 0 : pCpyRg->aStart < rInsPos && rInsPos < pCpyRg->aEnd )
1326 0 : delete pCpyRg, pCpyRg = 0;
1327 : }
1328 0 : else if( pSrcDoc != pDoc )
1329 0 : pCpyRg = new SwNodeRange( pSrcDoc->GetNodes().GetEndOfExtras(), 2,
1330 0 : pSrcDoc->GetNodes().GetEndOfContent() );
1331 :
1332 : // #i81653#
1333 : // Update links of extern linked document or extern linked
1334 : // document section, if section is protected.
1335 0 : if ( pSrcDoc != pDoc &&
1336 0 : rSection.IsProtectFlag() )
1337 : {
1338 0 : pSrcDoc->GetLinkManager().UpdateAllLinks( false, true, false, 0 );
1339 : }
1340 :
1341 0 : if( pCpyRg )
1342 : {
1343 0 : SwNodeIndex& rInsPos = pPam->GetPoint()->nNode;
1344 0 : sal_Bool bCreateFrm = rInsPos.GetIndex() <=
1345 0 : pDoc->GetNodes().GetEndOfExtras().GetIndex() ||
1346 0 : rInsPos.GetNode().FindTableNode();
1347 :
1348 0 : SwTblNumFmtMerge aTNFM( *pSrcDoc, *pDoc );
1349 :
1350 0 : pSrcDoc->CopyWithFlyInFly( *pCpyRg, 0, rInsPos, NULL, bCreateFrm );
1351 0 : ++aSave;
1352 :
1353 0 : if( !bCreateFrm )
1354 0 : ::MakeFrms( pDoc, aSave, rInsPos );
1355 :
1356 : // Delete last Node, only if it was copied successfully
1357 : // (the Section contains more than one Node)
1358 0 : if( 2 < pSectNd->EndOfSectionIndex() - pSectNd->GetIndex() )
1359 : {
1360 0 : aSave = rInsPos;
1361 0 : pPam->Move( fnMoveBackward, fnGoNode );
1362 0 : pPam->SetMark(); // Rewire both SwPositions
1363 :
1364 0 : pDoc->CorrAbs( aSave, *pPam->GetPoint(), 0, sal_True );
1365 0 : pDoc->GetNodes().Delete( aSave, 1 );
1366 : }
1367 0 : delete pCpyRg;
1368 : }
1369 :
1370 0 : lcl_BreakSectionLinksInSect( *pSectNd );
1371 :
1372 : // Update all Links in this Section
1373 0 : lcl_UpdateLinksInSect( *this, *pSectNd );
1374 : }
1375 0 : if( xDocSh.Is() )
1376 : {
1377 0 : if( 2 == nRet )
1378 0 : xDocSh->DoClose();
1379 0 : else if( ((SwDocShell*)&xDocSh)->GetDoc() )
1380 0 : ((SwDocShell*)&xDocSh)->GetDoc()->SetRedlineMode(
1381 0 : eOldRedlineMode );
1382 0 : }
1383 : }
1384 0 : break;
1385 : }
1386 :
1387 : // Only create DDE if Shell is available!
1388 0 : uno::Sequence< sal_Int8 > aSeq;
1389 0 : if( pRead && rValue.hasValue() && ( rValue >>= aSeq ) )
1390 : {
1391 0 : if( pESh )
1392 : {
1393 0 : pESh->Push();
1394 0 : SwPaM* pCrsr = pESh->GetCrsr();
1395 0 : *pCrsr->GetPoint() = *pPam->GetPoint();
1396 0 : delete pPam;
1397 0 : pPam = pCrsr;
1398 : }
1399 :
1400 0 : SvMemoryStream aStrm( (void*)aSeq.getConstArray(), aSeq.getLength(),
1401 0 : STREAM_READ );
1402 0 : aStrm.Seek( 0 );
1403 :
1404 : // TODO/MBA: it's impossible to set a BaseURL here!
1405 0 : SwReader aTmpReader( aStrm, OUString(), pDoc->GetDocShell()->GetMedium()->GetBaseURL(), *pPam );
1406 :
1407 0 : if( !IsError( aTmpReader.Read( *pRead ) ))
1408 : {
1409 0 : rSection.SetConnectFlag(true);
1410 : }
1411 :
1412 0 : if( pESh )
1413 : {
1414 0 : pESh->Pop( sal_False );
1415 0 : pPam = 0; // pam was deleted earlier
1416 0 : }
1417 : }
1418 :
1419 : // remove all undo actions and turn undo on again
1420 0 : pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
1421 0 : pDoc->GetIDocumentUndoRedo().DoUndo(bWasUndo);
1422 0 : pDoc->SetVisibleLinks( bWasVisibleLinks );
1423 :
1424 0 : pDoc->UnlockExpFlds();
1425 0 : if( !pDoc->IsExpFldsLocked() )
1426 0 : pDoc->UpdateExpFlds(NULL, true);
1427 :
1428 0 : if( pESh )
1429 0 : pESh->EndAllAction();
1430 0 : else if( pVSh )
1431 0 : pVSh->EndAction();
1432 0 : delete pPam; // Was created at the start
1433 :
1434 0 : return SUCCESS;
1435 : }
1436 :
1437 0 : void SwIntrnlSectRefLink::Closed()
1438 : {
1439 0 : SwDoc* pDoc = rSectFmt.GetDoc();
1440 0 : if( pDoc && !pDoc->IsInDtor() )
1441 : {
1442 : // Advise says goodbye: mark the Section as not protected
1443 : // and change the Flag
1444 0 : const SwSectionFmts& rFmts = pDoc->GetSections();
1445 0 : for( sal_uInt16 n = rFmts.size(); n; )
1446 0 : if( rFmts[ --n ] == &rSectFmt )
1447 : {
1448 : SwViewShell* pSh;
1449 0 : SwEditShell* pESh = pDoc->GetEditShell( &pSh );
1450 :
1451 0 : if( pESh )
1452 0 : pESh->StartAllAction();
1453 : else
1454 0 : pSh->StartAction();
1455 :
1456 0 : SwSectionData aSectionData(*rSectFmt.GetSection());
1457 0 : aSectionData.SetType( CONTENT_SECTION );
1458 0 : aSectionData.SetLinkFileName( OUString() );
1459 0 : aSectionData.SetHidden( false );
1460 0 : aSectionData.SetProtectFlag( false );
1461 : // edit in readonly sections
1462 0 : aSectionData.SetEditInReadonlyFlag( false );
1463 :
1464 0 : aSectionData.SetConnectFlag( false );
1465 :
1466 0 : pDoc->UpdateSection( n, aSectionData );
1467 :
1468 : // Make all Links within the Section visible again
1469 0 : SwSectionNode* pSectNd = rSectFmt.GetSectionNode( false );
1470 0 : if( pSectNd )
1471 0 : pSectNd->GetSection().MakeChildLinksVisible( *pSectNd );
1472 :
1473 0 : if( pESh )
1474 0 : pESh->EndAllAction();
1475 : else
1476 0 : pSh->EndAction();
1477 0 : break;
1478 : }
1479 : }
1480 0 : SvBaseLink::Closed();
1481 0 : }
1482 :
1483 0 : void SwSection::CreateLink( LinkCreateType eCreateType )
1484 : {
1485 0 : SwSectionFmt* pFmt = GetFmt();
1486 : OSL_ENSURE(pFmt, "SwSection::CreateLink: no format?");
1487 0 : if (!pFmt || (CONTENT_SECTION == m_Data.GetType()))
1488 0 : return ;
1489 :
1490 0 : sal_uInt16 nUpdateType = sfx2::LINKUPDATE_ALWAYS;
1491 :
1492 0 : if (!m_RefLink.Is())
1493 : {
1494 : // create BaseLink
1495 0 : m_RefLink = new SwIntrnlSectRefLink( *pFmt, nUpdateType, FORMAT_RTF );
1496 : }
1497 : else
1498 : {
1499 0 : pFmt->GetDoc()->GetLinkManager().Remove( m_RefLink );
1500 : }
1501 :
1502 : SwIntrnlSectRefLink *const pLnk =
1503 0 : static_cast<SwIntrnlSectRefLink*>(& m_RefLink);
1504 :
1505 0 : const OUString sCmd(SwSectionData::CollapseWhiteSpaces(m_Data.GetLinkFileName()));
1506 0 : pLnk->SetUpdateMode( nUpdateType );
1507 0 : pLnk->SetVisible( pFmt->GetDoc()->IsVisibleLinks() );
1508 :
1509 0 : switch (m_Data.GetType())
1510 : {
1511 : case DDE_LINK_SECTION:
1512 0 : pLnk->SetLinkSourceName( sCmd );
1513 0 : pFmt->GetDoc()->GetLinkManager().InsertDDELink( pLnk );
1514 0 : break;
1515 : case FILE_LINK_SECTION:
1516 : {
1517 0 : pLnk->SetContentType( FORMAT_FILE );
1518 0 : sal_Int32 nIndex = 0;
1519 0 : const OUString sFile(sCmd.getToken( 0, sfx2::cTokenSeparator, nIndex ));
1520 0 : const OUString sFltr(sCmd.getToken( 0, sfx2::cTokenSeparator, nIndex ));
1521 0 : const OUString sRange(sCmd.getToken( 0, sfx2::cTokenSeparator, nIndex ));
1522 0 : pFmt->GetDoc()->GetLinkManager().InsertFileLink( *pLnk,
1523 0 : static_cast<sal_uInt16>(m_Data.GetType()),
1524 : sFile,
1525 0 : ( !sFltr.isEmpty() ? &sFltr : 0 ),
1526 0 : ( !sRange.isEmpty() ? &sRange : 0 ) );
1527 : }
1528 0 : break;
1529 : default:
1530 : OSL_ENSURE( !this, "What kind of Link is this?" );
1531 : }
1532 :
1533 0 : switch( eCreateType )
1534 : {
1535 : case CREATE_CONNECT: // Connect Link right away
1536 0 : pLnk->Connect();
1537 0 : break;
1538 :
1539 : case CREATE_UPDATE: // Connect Link and update
1540 0 : pLnk->Update();
1541 0 : break;
1542 0 : case CREATE_NONE: break;
1543 0 : }
1544 : }
1545 :
1546 0 : void SwSection::BreakLink()
1547 : {
1548 0 : const SectionType eCurrentType( GetType() );
1549 0 : if ( eCurrentType == CONTENT_SECTION ||
1550 0 : eCurrentType == TOX_HEADER_SECTION ||
1551 : eCurrentType == TOX_CONTENT_SECTION )
1552 : {
1553 : // nothing to do
1554 0 : return;
1555 : }
1556 :
1557 : // Release link, if it exists
1558 0 : if (m_RefLink.Is())
1559 : {
1560 0 : SwSectionFmt *const pFormat( GetFmt() );
1561 : OSL_ENSURE(pFormat, "SwSection::BreakLink: no format?");
1562 0 : if (pFormat)
1563 : {
1564 0 : pFormat->GetDoc()->GetLinkManager().Remove( m_RefLink );
1565 : }
1566 0 : m_RefLink.Clear();
1567 : }
1568 : // change type
1569 0 : SetType( CONTENT_SECTION );
1570 : // reset linked file data
1571 0 : SetLinkFileName( OUString() );
1572 0 : SetLinkFilePassword( OUString() );
1573 : }
1574 :
1575 0 : const SwNode* SwIntrnlSectRefLink::GetAnchor() const
1576 : {
1577 0 : return rSectFmt.GetSectionNode( false );
1578 : }
1579 :
1580 0 : bool SwIntrnlSectRefLink::IsInRange( sal_uLong nSttNd, sal_uLong nEndNd,
1581 : sal_Int32 , sal_Int32 ) const
1582 : {
1583 0 : SwStartNode* pSttNd = rSectFmt.GetSectionNode( false );
1584 0 : return pSttNd &&
1585 0 : nSttNd < pSttNd->GetIndex() &&
1586 0 : pSttNd->EndOfSectionIndex() < nEndNd;
1587 : }
1588 :
1589 0 : sal_uInt16 SwSectionFmts::GetPos(const SwSectionFmt* p) const
1590 : {
1591 0 : const_iterator it = std::find(begin(), end(), p);
1592 0 : return it == end() ? USHRT_MAX : it - begin();
1593 : }
1594 :
1595 0 : bool SwSectionFmts::Contains(const SwSectionFmt* p) const
1596 : {
1597 0 : return std::find(begin(), end(), p) != end();
1598 : }
1599 :
1600 0 : SwSectionFmts::~SwSectionFmts()
1601 : {
1602 0 : for(const_iterator it = begin(); it != end(); ++it)
1603 0 : delete *it;
1604 0 : }
1605 :
1606 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|