1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
22 #include <libxml/xmlwriter.h>
26 #include <txtannotationfld.hxx>
28 #include <docufld.hxx>
30 #include <unofield.hxx>
39 #include <IDocumentFieldsAccess.hxx>
40 #include <IDocumentMarkAccess.hxx>
41 #include <IDocumentLayoutAccess.hxx>
42 #include <fieldhint.hxx>
43 #include <sal/log.hxx>
44 #include <osl/diagnose.h>
47 // constructor for default item in attribute-pool
48 SwFormatField::SwFormatField( sal_uInt16 nWhich
)
49 : SfxPoolItem( nWhich
)
51 , mpTextField( nullptr )
56 SwFormatField::SwFormatField( const SwField
&rField
)
57 : SfxPoolItem( RES_TXTATR_FIELD
)
59 , mpField( rField
.CopyField() )
60 , mpTextField( nullptr )
63 rField
.GetTyp()->Add(*this);
64 if ( mpField
->GetTyp()->Which() == SwFieldIds::Input
)
66 // input field in-place editing
67 SetWhich( RES_TXTATR_INPUTFIELD
);
68 static_cast<SwInputField
*>(mpField
.get())->SetFormatField( *this );
70 else if (mpField
->GetTyp()->Which() == SwFieldIds::SetExp
)
72 // see SwWrtShell::StartInputFieldDlg
73 SwSetExpField
*const pSetField(static_cast<SwSetExpField
*>(mpField
.get()));
74 if (pSetField
->GetInputFlag()
75 // only for string fields for now - inline editing of number fields
76 // tends to produce error messages...
77 && (static_cast<SwSetExpFieldType
*>(pSetField
->GetTyp())->GetType()
78 & nsSwGetSetExpType::GSE_STRING
))
80 SetWhich( RES_TXTATR_INPUTFIELD
);
82 pSetField
->SetFormatField(*this);
84 else if ( mpField
->GetTyp()->Which() == SwFieldIds::Postit
)
86 // text annotation field
87 SetWhich( RES_TXTATR_ANNOTATION
);
92 // Since Items are used in ItemPool and in default constructed ItemSets with
93 // full pool range, all items need to be clonable. Thus, this one needed to be
95 SwFormatField::SwFormatField( const SwFormatField
& rAttr
)
96 : SfxPoolItem( rAttr
)
98 , mpTextField( nullptr )
101 if ( !rAttr
.mpField
)
104 rAttr
.mpField
->GetTyp()->Add(*this);
105 mpField
= rAttr
.mpField
->CopyField();
106 if ( mpField
->GetTyp()->Which() == SwFieldIds::Input
)
108 // input field in-place editing
109 SetWhich( RES_TXTATR_INPUTFIELD
);
110 SwInputField
*pField
= dynamic_cast<SwInputField
*>(mpField
.get());
113 pField
->SetFormatField( *this );
115 else if (mpField
->GetTyp()->Which() == SwFieldIds::SetExp
)
117 SwSetExpField
*const pSetField(static_cast<SwSetExpField
*>(mpField
.get()));
118 if (pSetField
->GetInputFlag()
119 && (static_cast<SwSetExpFieldType
*>(pSetField
->GetTyp())->GetType()
120 & nsSwGetSetExpType::GSE_STRING
))
122 SetWhich( RES_TXTATR_INPUTFIELD
);
124 // see SwWrtShell::StartInputFieldDlg
125 pSetField
->SetFormatField(*this);
127 else if ( mpField
->GetTyp()->Which() == SwFieldIds::Postit
)
129 // text annotation field
130 SetWhich( RES_TXTATR_ANNOTATION
);
134 SwFormatField::~SwFormatField()
136 Broadcast( SwFormatFieldHint( this, SwFormatFieldHintWhich::REMOVED
) );
138 SwFieldType
* pType
= mpField
? mpField
->GetTyp() : nullptr;
139 if (pType
&& pType
->Which() == SwFieldIds::Database
)
140 pType
= nullptr; // DB field types destroy themselves
144 // some fields need to delete their field type
145 if( !(pType
&& pType
->HasOnlyOneListener()) )
149 switch( pType
->Which() )
151 case SwFieldIds::User
:
152 bDel
= static_cast<SwUserFieldType
*>(pType
)->IsDeleted();
155 case SwFieldIds::SetExp
:
156 bDel
= static_cast<SwSetExpFieldType
*>(pType
)->IsDeleted();
159 case SwFieldIds::Dde
:
160 bDel
= static_cast<SwDDEFieldType
*>(pType
)->IsDeleted();
167 // unregister before deleting
168 pType
->Remove(*this);
173 void SwFormatField::RegisterToFieldType( SwFieldType
& rType
)
178 void SwFormatField::SetField(std::unique_ptr
<SwField
> _pField
)
180 mpField
= std::move(_pField
);
181 if ( mpField
->GetTyp()->Which() == SwFieldIds::Input
)
183 static_cast<SwInputField
* >(mpField
.get())->SetFormatField( *this );
185 else if (mpField
->GetTyp()->Which() == SwFieldIds::SetExp
)
187 // see SwWrtShell::StartInputFieldDlg
188 static_cast<SwSetExpField
*>(mpField
.get())->SetFormatField(*this);
190 Broadcast( SwFormatFieldHint( this, SwFormatFieldHintWhich::CHANGED
) );
193 void SwFormatField::SetTextField( SwTextField
& rTextField
)
195 mpTextField
= &rTextField
;
198 void SwFormatField::ClearTextField()
200 mpTextField
= nullptr;
203 bool SwFormatField::operator==( const SfxPoolItem
& rAttr
) const
205 assert(SfxPoolItem::operator==(rAttr
));
207 && static_cast<const SwFormatField
&>(rAttr
).mpField
208 && mpField
->GetTyp() == static_cast<const SwFormatField
&>(rAttr
).mpField
->GetTyp()
209 && mpField
->GetFormat() == static_cast<const SwFormatField
&>(rAttr
).mpField
->GetFormat() )
211 ( !mpField
&& !static_cast<const SwFormatField
&>(rAttr
).mpField
);
214 SwFormatField
* SwFormatField::Clone( SfxItemPool
* ) const
216 return new SwFormatField( *this );
219 void SwFormatField::InvalidateField()
221 if (auto xUnoField
= m_wXTextField
.get())
223 xUnoField
->OnFormatFieldDelete();
224 m_wXTextField
.clear();
228 void SwFormatField::SwClientNotify( const SwModify
& rModify
, const SfxHint
& rHint
)
230 SwClient::SwClientNotify(rModify
, rHint
);
231 if (rHint
.GetId() == SfxHintId::SwAutoFormatUsedHint
) {
233 static_cast<const sw::AutoFormatUsedHint
&>(rHint
).CheckNode(mpTextField
->GetpTextNode());
236 else if (rHint
.GetId() == SfxHintId::SwField
)
238 const auto pFieldHint
= static_cast<const SwFieldHint
*>( &rHint
);
239 // replace field content by text
240 SwPaM
* pPaM
= pFieldHint
->m_pPaM
;
241 pPaM
->DeleteMark(); // TODO: this is really hackish
246 SwDoc
& rDoc
= pPaM
->GetDoc();
247 const SwTextNode
& rTextNode
= mpTextField
->GetTextNode();
248 pPaM
->GetPoint()->Assign(rTextNode
, mpTextField
->GetStart());
250 OUString
const aEntry(mpField
->ExpandField(rDoc
.IsClipBoard(), pFieldHint
->m_pLayout
));
252 pPaM
->Move( fnMoveForward
);
253 rDoc
.getIDocumentContentOperations().DeleteRange( *pPaM
);
254 rDoc
.getIDocumentContentOperations().InsertString( *pPaM
, aEntry
);
256 else if (rHint
.GetId() == SfxHintId::SwLegacyModify
|| rHint
.GetId() == SfxHintId::SwFormatChange
)
260 UpdateTextNode(rHint
);
262 else if (rHint
.GetId() == SfxHintId::SwFindFormatForField
)
264 const auto pFindForFieldHint
= static_cast<const sw::FindFormatForFieldHint
*>( &rHint
);
265 if(pFindForFieldHint
->m_rpFormat
== nullptr && pFindForFieldHint
->m_pField
== GetField())
266 pFindForFieldHint
->m_rpFormat
= this;
268 else if (rHint
.GetId() == SfxHintId::SwFindFormatForPostItId
)
270 const auto pFindForPostItIdHint
= static_cast<const sw::FindFormatForPostItIdHint
*>( &rHint
);
271 auto pPostItField
= dynamic_cast<SwPostItField
*>(mpField
.get());
272 if(pPostItField
&& pFindForPostItIdHint
->m_rpFormat
== nullptr && pFindForPostItIdHint
->m_nPostItId
== pPostItField
->GetPostItId())
273 pFindForPostItIdHint
->m_rpFormat
= this;
275 else if (rHint
.GetId() == SfxHintId::SwCollectPostIts
)
277 const auto pCollectPostItsHint
= static_cast<const sw::CollectPostItsHint
*>( &rHint
);
278 if(GetTextField() && IsFieldInDoc() && (!pCollectPostItsHint
->m_bHideRedlines
|| !sw::IsFieldDeletedInModel(pCollectPostItsHint
->m_rIDRA
, *GetTextField())))
279 pCollectPostItsHint
->m_rvFormatFields
.push_back(this);
281 else if (rHint
.GetId() == SfxHintId::SwHasHiddenInformationNotes
)
283 const auto pHasHiddenInfoHint
= static_cast<const sw::HasHiddenInformationNotesHint
*>( &rHint
);
284 if(!pHasHiddenInfoHint
->m_rbHasHiddenInformationNotes
&& GetTextField() && IsFieldInDoc())
285 pHasHiddenInfoHint
->m_rbHasHiddenInformationNotes
= true;
287 else if (rHint
.GetId() == SfxHintId::SwGatherNodeIndex
)
289 const auto pGatherNodeIndexHint
= static_cast<const sw::GatherNodeIndexHint
*>( &rHint
);
290 if(auto pTextField
= GetTextField())
291 pGatherNodeIndexHint
->m_rvNodeIndex
.push_back(pTextField
->GetTextNode().GetIndex());
293 else if (rHint
.GetId() == SfxHintId::SwGatherRefFields
)
295 const auto pGatherRefFieldsHint
= static_cast<const sw::GatherRefFieldsHint
*>( &rHint
);
296 if(!GetTextField() || pGatherRefFieldsHint
->m_nType
!= GetField()->GetSubType())
298 SwTextNode
* pNd
= GetTextField()->GetpTextNode();
299 if(pNd
&& pNd
->GetNodes().IsDocNodes())
300 pGatherRefFieldsHint
->m_rvRFields
.push_back(static_cast<SwGetRefField
*>(GetField()));
302 else if (rHint
.GetId() == SfxHintId::SwGatherFields
)
304 const auto pGatherFieldsHint
= static_cast<const sw::GatherFieldsHint
*>( &rHint
);
305 if(pGatherFieldsHint
->m_bCollectOnlyInDocNodes
)
309 SwTextNode
* pNd
= GetTextField()->GetpTextNode();
310 if(!pNd
|| !pNd
->GetNodes().IsDocNodes())
313 pGatherFieldsHint
->m_rvFields
.push_back(this);
315 else if (rHint
.GetId() == SfxHintId::SwDocPosUpdate
)
317 UpdateDocPos(static_cast<const sw::DocPosUpdate
*>(&rHint
)->m_nDocPos
);
323 bool lcl_ExpandField(const SwFieldIds eId
)
327 case SwFieldIds::DbSetNumber
:
328 case SwFieldIds::DbNumSet
:
329 case SwFieldIds::DbNextSet
:
330 case SwFieldIds::DatabaseName
:
337 bool lcl_TriggerNode(const SwFieldIds eId
)
341 case SwFieldIds::HiddenPara
:
342 case SwFieldIds::DbSetNumber
:
343 case SwFieldIds::DbNumSet
:
344 case SwFieldIds::DbNextSet
:
345 case SwFieldIds::DatabaseName
:
351 void lcl_EnsureUserFieldValid(SwFieldType
& rType
)
353 if(rType
.Which() != SwFieldIds::User
)
355 static_cast<SwUserFieldType
*>(&rType
)->EnsureValid();
357 bool lcl_NeedsForcedUpdate(const SwField
& rField
)
359 if (rField
.GetTyp()->Which() == SwFieldIds::DocInfo
)
361 auto pDocInfoField
= static_cast<const SwDocInfoField
*>(&rField
);
362 sal_uInt16 nSubType
= pDocInfoField
->GetSubType();
363 // Do not consider extended SubTypes.
367 case nsSwDocInfoSubType::DI_TITLE
:
368 case nsSwDocInfoSubType::DI_SUBJECT
:
369 case nsSwDocInfoSubType::DI_CHANGE
:
370 case nsSwDocInfoSubType::DI_CUSTOM
:
378 void SwFormatField::ForceUpdateTextNode()
383 SwTextNode
* pTextNd
= &mpTextField
->GetTextNode();
384 OSL_ENSURE(pTextNd
, "Where is my Node?");
386 auto pType
= mpField
->GetTyp();
387 lcl_EnsureUserFieldValid(*pType
);
388 if(lcl_TriggerNode(pType
->Which()))
389 pTextNd
->TriggerNodeUpdate(sw::LegacyModifyHint(nullptr, nullptr));
390 if(!lcl_ExpandField(pType
->Which()))
393 // Force notify was added for conditional text fields,
394 // at least the below fields need no forced notify.
395 bool bNeedForced
= lcl_NeedsForcedUpdate(*mpTextField
->GetFormatField().GetField());
396 mpTextField
->ExpandTextField(bNeedForced
);
398 void SwFormatField::UpdateDocPos(const SwTwips nDocPos
)
402 auto pTextNd
= &mpTextField
->GetTextNode();
404 pTextNd
->UpdateDocPos(nDocPos
, mpTextField
->GetStart());
406 void SwFormatField::UpdateTextNode(const SfxHint
& rHint
)
408 if(SfxHintId::SwHiddenParaPrint
== rHint
.GetId())
412 auto pType
= mpField
->GetTyp();
413 lcl_EnsureUserFieldValid(*pType
);
414 bool bTriggerNode
= lcl_TriggerNode(pType
->Which());
415 bool bExpand
= lcl_ExpandField(pType
->Which());
418 SwTextNode
* pTextNd
= &mpTextField
->GetTextNode();
419 OSL_ENSURE(pTextNd
, "Where is my Node?");
420 pTextNd
->TriggerNodeUpdate(sw::LegacyModifyHint(nullptr, nullptr));
423 mpTextField
->ExpandTextField(false);
426 else if(SfxHintId::SwRemoveUnoObject
== rHint
.GetId())
427 { // invalidate cached UNO object
428 m_wXTextField
.clear();
429 // ??? why does this Modify method not already do this?
430 CallSwClientNotify(rHint
);
433 if (rHint
.GetId() == SfxHintId::SwFormatChange
)
435 auto pChangeHint
= static_cast<const SwFormatChangeHint
*>(&rHint
);
439 SwTextNode
* pTextNd
= &mpTextField
->GetTextNode();
440 OSL_ENSURE(pTextNd
, "Where is my Node?");
442 bool bTriggerNode
= pChangeHint
->m_pNewFormat
!= nullptr;
444 pTextNd
->TriggerNodeUpdate(*pChangeHint
);
447 if(SfxHintId::SwLegacyModify
!= rHint
.GetId())
449 auto pLegacy
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
450 auto pOld
= pLegacy
->m_pOld
;
451 auto pNew
= pLegacy
->m_pNew
;
452 if (pOld
== nullptr && pNew
== nullptr)
454 ForceUpdateTextNode();
461 // don't do anything, especially not expand!
462 if( pNew
&& pNew
->Which() == RES_OBJECTDYING
)
465 SwTextNode
* pTextNd
= &mpTextField
->GetTextNode();
466 OSL_ENSURE(pTextNd
, "Where is my Node?");
468 bool bTriggerNode
= pNew
!= nullptr;
469 bool bExpand
= false;
472 switch(pNew
->Which())
474 case RES_ATTRSET_CHG
:
478 auto pType
= mpField
->GetTyp();
479 lcl_EnsureUserFieldValid(*pType
);
480 bTriggerNode
= lcl_TriggerNode(pType
->Which());
481 bExpand
= lcl_ExpandField(pType
->Which());
487 pTextNd
->TriggerNodeUpdate(sw::LegacyModifyHint(pOld
, pNew
));
489 mpTextField
->ExpandTextField(false);
492 bool SwFormatField::IsFieldInDoc() const
494 return mpTextField
!= nullptr
495 && mpTextField
->IsFieldInDoc();
498 bool SwFormatField::IsProtect() const
500 return mpTextField
!= nullptr
501 && mpTextField
->GetpTextNode() != nullptr
502 && mpTextField
->GetpTextNode()->IsProtect();
505 void SwFormatField::dumpAsXml(xmlTextWriterPtr pWriter
) const
507 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwFormatField"));
508 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
509 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("mpTextField"), "%p", mpTextField
);
511 SfxPoolItem::dumpAsXml(pWriter
);
512 if (mpField
) // pool default doesn't have one
514 mpField
->dumpAsXml(pWriter
);
517 (void)xmlTextWriterEndElement(pWriter
);
520 // class SwTextField ////////////////////////////////////////////////////
522 SwTextField::SwTextField(
523 const SfxPoolItemHolder
& rAttr
,
524 sal_Int32
const nStartPos
,
525 bool const bInClipboard
)
526 : SwTextAttr( rAttr
, nStartPos
)
527 // fdo#39694 the ExpandField here may not give the correct result in all cases,
528 // but is better than nothing
530 , m_pTextNode( nullptr )
532 SwFormatField
& rSwFormatField(static_cast<SwFormatField
&>(GetAttr()));
533 m_aExpand
= rSwFormatField
.GetField()->ExpandField(bInClipboard
, nullptr);
534 rSwFormatField
.SetTextField( *this );
535 SetHasDummyChar(true);
538 SwTextField::~SwTextField( )
540 SwFormatField
& rFormatField( static_cast<SwFormatField
&>(GetAttr()) );
541 if ( this == rFormatField
.GetTextField() )
543 rFormatField
.ClearTextField();
547 bool SwTextField::IsFieldInDoc() const
549 return GetpTextNode() != nullptr
550 && GetpTextNode()->GetNodes().IsDocNodes();
553 void SwTextField::ExpandTextField(const bool bForceNotify
) const
555 OSL_ENSURE( m_pTextNode
, "SwTextField: where is my TextNode?" );
557 const SwField
* pField
= GetFormatField().GetField();
558 const OUString
aNewExpand( pField
->ExpandField(m_pTextNode
->GetDoc().IsClipBoard(),
559 // can't do any better than this here...
560 m_pTextNode
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout()) );
562 const SwFieldIds nWhich
= pField
->GetTyp()->Which();
563 const bool bSameExpandSimpleNotification
564 = SwFieldIds::Chapter
!= nWhich
&& SwFieldIds::PageNumber
!= nWhich
565 && SwFieldIds::RefPageGet
!= nWhich
566 // Page count fields to not use aExpand during formatting,
567 // therefore an invalidation of the text frame has to be triggered even if aNewExpand == aExpand:
568 && (SwFieldIds::DocStat
!= nWhich
569 || DS_PAGE
!= static_cast<const SwDocStatField
*>(pField
)->GetSubType())
570 && (SwFieldIds::GetExp
!= nWhich
571 || static_cast<const SwGetExpField
*>(pField
)->IsInBodyText());
573 bool bHiddenParaChanged
= false;
574 if (aNewExpand
!= m_aExpand
|| bSameExpandSimpleNotification
)
575 bHiddenParaChanged
= m_pTextNode
->CalcHiddenParaField();
577 if (aNewExpand
== m_aExpand
)
579 if ( bSameExpandSimpleNotification
)
581 if( bHiddenParaChanged
)
582 m_pTextNode
->TriggerNodeUpdate(sw::LegacyModifyHint(nullptr, nullptr));
585 // done, if no further notification forced.
591 m_aExpand
= aNewExpand
;
593 const_cast<SwTextField
*>(this)->NotifyContentChange( const_cast<SwFormatField
&>(GetFormatField()) );
596 void SwTextField::CopyTextField( SwTextField
*pDest
) const
598 OSL_ENSURE( m_pTextNode
, "SwTextField: where is my TextNode?" );
599 OSL_ENSURE( pDest
->m_pTextNode
, "SwTextField: where is pDest's TextNode?" );
601 IDocumentFieldsAccess
* pIDFA
= &m_pTextNode
->getIDocumentFieldsAccess();
602 IDocumentFieldsAccess
* pDestIDFA
= &pDest
->m_pTextNode
->getIDocumentFieldsAccess();
604 SwFormatField
& rDestFormatField
= const_cast<SwFormatField
&>(pDest
->GetFormatField());
605 const SwFieldIds nFieldWhich
= rDestFormatField
.GetField()->GetTyp()->Which();
607 if( pIDFA
!= pDestIDFA
)
609 // different documents, e.g. clipboard:
610 // register field type in target document
611 SwFieldType
* pFieldType
;
612 if( nFieldWhich
!= SwFieldIds::Database
613 && nFieldWhich
!= SwFieldIds::User
614 && nFieldWhich
!= SwFieldIds::SetExp
615 && nFieldWhich
!= SwFieldIds::Dde
616 && SwFieldIds::TableOfAuthorities
!= nFieldWhich
)
618 pFieldType
= pDestIDFA
->GetSysFieldType( nFieldWhich
);
622 pFieldType
= pDestIDFA
->InsertFieldType( *rDestFormatField
.GetField()->GetTyp() );
625 // DDE fields need special treatment
626 if( SwFieldIds::Dde
== nFieldWhich
)
628 if( rDestFormatField
.GetTextField() )
630 static_cast<SwDDEFieldType
*>(rDestFormatField
.GetField()->GetTyp())->DecRefCnt();
632 static_cast<SwDDEFieldType
*>(pFieldType
)->IncRefCnt();
635 OSL_ENSURE( pFieldType
, "unknown FieldType" );
636 pFieldType
->Add(rDestFormatField
); // register at the field type
637 rDestFormatField
.GetField()->ChgTyp( pFieldType
);
640 // update expression fields
641 if( nFieldWhich
== SwFieldIds::SetExp
642 || nFieldWhich
== SwFieldIds::GetExp
643 || nFieldWhich
== SwFieldIds::HiddenText
)
645 SwTextField
* pField
= const_cast<SwTextField
*>(this);
646 pDestIDFA
->UpdateExpFields( pField
, true );
648 // table fields: external display
649 else if( SwFieldIds::Table
== nFieldWhich
650 && static_cast<SwTableField
*>(rDestFormatField
.GetField())->IsIntrnlName() )
652 // convert internal (core) to external (UI) formula
653 const SwTableNode
* pTableNd
= m_pTextNode
->FindTableNode();
654 if( pTableNd
) // in a table?
655 static_cast<SwTableField
*>(rDestFormatField
.GetField())->PtrToBoxNm( &pTableNd
->GetTable() );
659 void SwTextField::NotifyContentChange(SwFormatField
& rFormatField
)
661 //if not in undo section notify the change
662 if (m_pTextNode
&& m_pTextNode
->GetNodes().IsDocNodes())
663 m_pTextNode
->TriggerNodeUpdate(sw::LegacyModifyHint(nullptr, &rFormatField
));
667 void SwTextField::GetPamForTextField(
668 const SwTextField
& rTextField
,
669 std::shared_ptr
< SwPaM
>& rPamForTextField
)
671 if (rTextField
.GetpTextNode() == nullptr)
673 SAL_WARN("sw.core", "<SwTextField::GetPamForField> - missing <SwTextNode>");
677 const SwTextNode
& rTextNode
= rTextField
.GetTextNode();
679 rPamForTextField
= std::make_shared
<SwPaM
>( rTextNode
,
680 (rTextField
.End() != nullptr) ? *(rTextField
.End()) : ( rTextField
.GetStart() + 1 ),
682 rTextField
.GetStart() );
687 void SwTextField::DeleteTextField( const SwTextField
& rTextField
)
689 if (rTextField
.GetpTextNode() != nullptr)
691 std::shared_ptr
< SwPaM
> pPamForTextField
;
692 GetPamForTextField(rTextField
, pPamForTextField
);
693 if (pPamForTextField
!= nullptr)
695 rTextField
.GetTextNode().GetDoc().getIDocumentContentOperations().DeleteAndJoin(*pPamForTextField
);
700 // class SwTextInputField ///////////////////////////////////////////////
702 // input field in-place editing
703 SwTextInputField::SwTextInputField(
704 const SfxPoolItemHolder
& rAttr
,
705 sal_Int32
const nStart
,
706 sal_Int32
const nEnd
,
707 bool const bInClipboard
)
709 : SwTextAttr( rAttr
, nStart
)
710 , SwTextAttrNesting( rAttr
, nStart
, nEnd
)
711 , SwTextField( rAttr
, nStart
, bInClipboard
)
712 , m_bLockNotifyContentChange( false )
714 SetHasDummyChar( false );
715 SetHasContent( true );
718 SwTextInputField::~SwTextInputField()
722 bool SwTextInputField::LockNotifyContentChange()
724 if (m_bLockNotifyContentChange
)
728 m_bLockNotifyContentChange
= true;
732 void SwTextInputField::UnlockNotifyContentChange()
734 m_bLockNotifyContentChange
= false;
737 void SwTextInputField::NotifyContentChange( SwFormatField
& rFormatField
)
739 if ( !m_bLockNotifyContentChange
)
741 LockNotifyContentChange();
743 SwTextField::NotifyContentChange( rFormatField
);
744 UpdateTextNodeContent( GetFieldContent() );
746 UnlockNotifyContentChange();
750 OUString
SwTextInputField::GetFieldContent() const
752 return GetFormatField().GetField()->ExpandField(false, nullptr/*ignored anyway*/);
755 void SwTextInputField::UpdateFieldContent()
757 if ( !(IsFieldInDoc()
758 && GetStart() != (*End())) )
761 assert( (*End()) - GetStart() >= 2 &&
762 "<SwTextInputField::UpdateFieldContent()> - Are CH_TXT_ATR_INPUTFIELDSTART and/or CH_TXT_ATR_INPUTFIELDEND missing?" );
763 // skip CH_TXT_ATR_INPUTFIELDSTART character
764 const sal_Int32 nIdx
= GetStart() + 1;
765 // skip CH_TXT_ATR_INPUTFIELDEND character
766 const sal_Int32 nLen
= static_cast<sal_Int32
>(std::max
<sal_Int32
>( 0, ( (*End()) - 1 - nIdx
) ));
767 const OUString aNewFieldContent
= GetTextNode().GetExpandText(nullptr, nIdx
, nLen
);
769 const SwField
* pField
= GetFormatField().GetField();
770 const SwInputField
* pInputField
= dynamic_cast<const SwInputField
*>(pField
);
772 const_cast<SwInputField
*>(pInputField
)->applyFieldContent( aNewFieldContent
);
774 const SwSetExpField
* pExpField
= dynamic_cast<const SwSetExpField
*>(pField
);
777 assert(pExpField
->GetInputFlag());
778 const_cast<SwSetExpField
*>(pExpField
)->SetPar2(aNewFieldContent
);
780 assert(pInputField
|| pExpField
);
782 // trigger update of fields for scenarios in which the Input Field's content is part of e.g. a table formula
783 GetTextNode().GetDoc().getIDocumentFieldsAccess().GetUpdateFields().SetFieldsDirty(true);
786 void SwTextInputField::UpdateTextNodeContent( const OUString
& rNewContent
)
788 assert(IsFieldInDoc() &&
789 "<SwTextInputField::UpdateTextNodeContent(..)> - misusage as Input Field is not in document content.");
791 assert( (*End()) - GetStart() >= 2 &&
792 "<SwTextInputField::UpdateTextNodeContent(..)> - Are CH_TXT_ATR_INPUTFIELDSTART and/or CH_TXT_ATR_INPUTFIELDEND missing?" );
793 // skip CH_TXT_ATR_INPUTFIELDSTART character
794 const sal_Int32 nIdx
= GetStart() + 1;
795 // skip CH_TXT_ATR_INPUTFIELDEND character
796 const sal_Int32 nDelLen
= std::max
<sal_Int32
>( 0, ( (*End()) - 1 - nIdx
) );
797 SwContentIndex
aIdx( &GetTextNode(), nIdx
);
798 GetTextNode().ReplaceText( aIdx
, nDelLen
, rNewContent
);
801 // class SwTextAnnotationField //////////////////////////////////////////
803 // text annotation field
804 SwTextAnnotationField::SwTextAnnotationField(
805 const SfxPoolItemHolder
& rAttr
,
806 sal_Int32
const nStart
,
807 bool const bInClipboard
)
808 : SwTextAttr( rAttr
, nStart
)
809 , SwTextField( rAttr
, nStart
, bInClipboard
)
813 SwTextAnnotationField::~SwTextAnnotationField()
817 ::sw::mark::AnnotationMark
* SwTextAnnotationField::GetAnnotationMark() const
819 auto pPostItField
= dynamic_cast<const SwPostItField
*>(GetFormatField().GetField());
820 assert(pPostItField
);
822 SwDoc
& rDoc
= static_cast<const SwPostItFieldType
*>(pPostItField
->GetTyp())->GetDoc();
824 IDocumentMarkAccess
* pMarksAccess
= rDoc
.getIDocumentMarkAccess();
825 auto pMark
= pMarksAccess
->findAnnotationMark( pPostItField
->GetName() );
826 return pMark
!= pMarksAccess
->getAnnotationMarksEnd()
831 void SwFormatField::SetXTextField(rtl::Reference
<SwXTextField
> const& xTextField
)
832 { m_wXTextField
= xTextField
.get(); }
834 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */