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 )
55 SwFormatField::SwFormatField( const SwField
&rField
)
56 : SfxPoolItem( RES_TXTATR_FIELD
)
58 , mpField( rField
.CopyField() )
59 , mpTextField( nullptr )
61 rField
.GetTyp()->Add(this);
62 if ( mpField
->GetTyp()->Which() == SwFieldIds::Input
)
64 // input field in-place editing
65 SetWhich( RES_TXTATR_INPUTFIELD
);
66 static_cast<SwInputField
*>(mpField
.get())->SetFormatField( *this );
68 else if (mpField
->GetTyp()->Which() == SwFieldIds::SetExp
)
70 // see SwWrtShell::StartInputFieldDlg
71 SwSetExpField
*const pSetField(static_cast<SwSetExpField
*>(mpField
.get()));
72 if (pSetField
->GetInputFlag()
73 // only for string fields for now - inline editing of number fields
74 // tends to produce error messages...
75 && (static_cast<SwSetExpFieldType
*>(pSetField
->GetTyp())->GetType()
76 & nsSwGetSetExpType::GSE_STRING
))
78 SetWhich( RES_TXTATR_INPUTFIELD
);
80 pSetField
->SetFormatField(*this);
82 else if ( mpField
->GetTyp()->Which() == SwFieldIds::Postit
)
84 // text annotation field
85 SetWhich( RES_TXTATR_ANNOTATION
);
90 // Since Items are used in ItemPool and in default constructed ItemSets with
91 // full pool range, all items need to be clonable. Thus, this one needed to be
93 SwFormatField::SwFormatField( const SwFormatField
& rAttr
)
94 : SfxPoolItem( rAttr
)
96 , mpTextField( nullptr )
101 rAttr
.mpField
->GetTyp()->Add(this);
102 mpField
= rAttr
.mpField
->CopyField();
103 if ( mpField
->GetTyp()->Which() == SwFieldIds::Input
)
105 // input field in-place editing
106 SetWhich( RES_TXTATR_INPUTFIELD
);
107 SwInputField
*pField
= dynamic_cast<SwInputField
*>(mpField
.get());
110 pField
->SetFormatField( *this );
112 else if (mpField
->GetTyp()->Which() == SwFieldIds::SetExp
)
114 SwSetExpField
*const pSetField(static_cast<SwSetExpField
*>(mpField
.get()));
115 if (pSetField
->GetInputFlag()
116 && (static_cast<SwSetExpFieldType
*>(pSetField
->GetTyp())->GetType()
117 & nsSwGetSetExpType::GSE_STRING
))
119 SetWhich( RES_TXTATR_INPUTFIELD
);
121 // see SwWrtShell::StartInputFieldDlg
122 pSetField
->SetFormatField(*this);
124 else if ( mpField
->GetTyp()->Which() == SwFieldIds::Postit
)
126 // text annotation field
127 SetWhich( RES_TXTATR_ANNOTATION
);
131 SwFormatField::~SwFormatField()
133 SwFieldType
* pType
= mpField
? mpField
->GetTyp() : nullptr;
135 if (pType
&& pType
->Which() == SwFieldIds::Database
)
136 pType
= nullptr; // DB field types destroy themselves
138 Broadcast( SwFormatFieldHint( this, SwFormatFieldHintWhich::REMOVED
) );
141 // some fields need to delete their field type
142 if( !(pType
&& pType
->HasOnlyOneListener()) )
146 switch( pType
->Which() )
148 case SwFieldIds::User
:
149 bDel
= static_cast<SwUserFieldType
*>(pType
)->IsDeleted();
152 case SwFieldIds::SetExp
:
153 bDel
= static_cast<SwSetExpFieldType
*>(pType
)->IsDeleted();
156 case SwFieldIds::Dde
:
157 bDel
= static_cast<SwDDEFieldType
*>(pType
)->IsDeleted();
164 // unregister before deleting
165 pType
->Remove( this );
170 void SwFormatField::RegisterToFieldType( SwFieldType
& rType
)
175 void SwFormatField::SetField(std::unique_ptr
<SwField
> _pField
)
177 mpField
= std::move(_pField
);
178 if ( mpField
->GetTyp()->Which() == SwFieldIds::Input
)
180 static_cast<SwInputField
* >(mpField
.get())->SetFormatField( *this );
182 else if (mpField
->GetTyp()->Which() == SwFieldIds::SetExp
)
184 // see SwWrtShell::StartInputFieldDlg
185 static_cast<SwSetExpField
*>(mpField
.get())->SetFormatField(*this);
187 Broadcast( SwFormatFieldHint( this, SwFormatFieldHintWhich::CHANGED
) );
190 void SwFormatField::SetTextField( SwTextField
& rTextField
)
192 mpTextField
= &rTextField
;
195 void SwFormatField::ClearTextField()
197 mpTextField
= nullptr;
200 bool SwFormatField::operator==( const SfxPoolItem
& rAttr
) const
202 assert(SfxPoolItem::operator==(rAttr
));
204 && static_cast<const SwFormatField
&>(rAttr
).mpField
205 && mpField
->GetTyp() == static_cast<const SwFormatField
&>(rAttr
).mpField
->GetTyp()
206 && mpField
->GetFormat() == static_cast<const SwFormatField
&>(rAttr
).mpField
->GetFormat() )
208 ( !mpField
&& !static_cast<const SwFormatField
&>(rAttr
).mpField
);
211 SwFormatField
* SwFormatField::Clone( SfxItemPool
* ) const
213 return new SwFormatField( *this );
216 void SwFormatField::InvalidateField()
218 const SwPtrMsgPoolItem
aItem(RES_REMOVE_UNO_OBJECT
, &static_cast<sw::BroadcastingModify
&>(*this));
219 CallSwClientNotify(sw::LegacyModifyHint
{ &aItem
, &aItem
});
222 void SwFormatField::SwClientNotify( const SwModify
& rModify
, const SfxHint
& rHint
)
224 SwClient::SwClientNotify(rModify
, rHint
);
225 if (rHint
.GetId() == SfxHintId::SwField
)
227 const auto pFieldHint
= static_cast<const SwFieldHint
*>( &rHint
);
228 // replace field content by text
229 SwPaM
* pPaM
= pFieldHint
->m_pPaM
;
230 pPaM
->DeleteMark(); // TODO: this is really hackish
235 SwDoc
& rDoc
= pPaM
->GetDoc();
236 const SwTextNode
& rTextNode
= mpTextField
->GetTextNode();
237 pPaM
->GetPoint()->Assign(rTextNode
, mpTextField
->GetStart());
239 OUString
const aEntry(mpField
->ExpandField(rDoc
.IsClipBoard(), pFieldHint
->m_pLayout
));
241 pPaM
->Move( fnMoveForward
);
242 rDoc
.getIDocumentContentOperations().DeleteRange( *pPaM
);
243 rDoc
.getIDocumentContentOperations().InsertString( *pPaM
, aEntry
);
245 else if (rHint
.GetId() == SfxHintId::SwLegacyModify
)
249 UpdateTextNode(rHint
);
251 else if (rHint
.GetId() == SfxHintId::SwFindFormatForField
)
253 const auto pFindForFieldHint
= static_cast<const sw::FindFormatForFieldHint
*>( &rHint
);
254 if(pFindForFieldHint
->m_rpFormat
== nullptr && pFindForFieldHint
->m_pField
== GetField())
255 pFindForFieldHint
->m_rpFormat
= this;
257 else if (rHint
.GetId() == SfxHintId::SwFindFormatForPostItId
)
259 const auto pFindForPostItIdHint
= static_cast<const sw::FindFormatForPostItIdHint
*>( &rHint
);
260 auto pPostItField
= dynamic_cast<SwPostItField
*>(mpField
.get());
261 if(pPostItField
&& pFindForPostItIdHint
->m_rpFormat
== nullptr && pFindForPostItIdHint
->m_nPostItId
== pPostItField
->GetPostItId())
262 pFindForPostItIdHint
->m_rpFormat
= this;
264 else if (rHint
.GetId() == SfxHintId::SwCollectPostIts
)
266 const auto pCollectPostItsHint
= static_cast<const sw::CollectPostItsHint
*>( &rHint
);
267 if(GetTextField() && IsFieldInDoc() && (!pCollectPostItsHint
->m_bHideRedlines
|| !sw::IsFieldDeletedInModel(pCollectPostItsHint
->m_rIDRA
, *GetTextField())))
268 pCollectPostItsHint
->m_rvFormatFields
.push_back(this);
270 else if (rHint
.GetId() == SfxHintId::SwHasHiddenInformationNotes
)
272 const auto pHasHiddenInfoHint
= static_cast<const sw::HasHiddenInformationNotesHint
*>( &rHint
);
273 if(!pHasHiddenInfoHint
->m_rbHasHiddenInformationNotes
&& GetTextField() && IsFieldInDoc())
274 pHasHiddenInfoHint
->m_rbHasHiddenInformationNotes
= true;
276 else if (rHint
.GetId() == SfxHintId::SwGatherNodeIndex
)
278 const auto pGatherNodeIndexHint
= static_cast<const sw::GatherNodeIndexHint
*>( &rHint
);
279 if(auto pTextField
= GetTextField())
280 pGatherNodeIndexHint
->m_rvNodeIndex
.push_back(pTextField
->GetTextNode().GetIndex());
282 else if (rHint
.GetId() == SfxHintId::SwGatherRefFields
)
284 const auto pGatherRefFieldsHint
= static_cast<const sw::GatherRefFieldsHint
*>( &rHint
);
285 if(!GetTextField() || pGatherRefFieldsHint
->m_nType
!= GetField()->GetSubType())
287 SwTextNode
* pNd
= GetTextField()->GetpTextNode();
288 if(pNd
&& pNd
->GetNodes().IsDocNodes())
289 pGatherRefFieldsHint
->m_rvRFields
.push_back(static_cast<SwGetRefField
*>(GetField()));
291 else if (rHint
.GetId() == SfxHintId::SwGatherFields
)
293 const auto pGatherFieldsHint
= static_cast<const sw::GatherFieldsHint
*>( &rHint
);
294 if(pGatherFieldsHint
->m_bCollectOnlyInDocNodes
)
298 SwTextNode
* pNd
= GetTextField()->GetpTextNode();
299 if(!pNd
|| !pNd
->GetNodes().IsDocNodes())
302 pGatherFieldsHint
->m_rvFields
.push_back(this);
304 else if (rHint
.GetId() == SfxHintId::SwDocPosUpdate
)
306 UpdateDocPos(static_cast<const sw::DocPosUpdate
*>(&rHint
)->m_nDocPos
);
312 bool lcl_ExpandField(const SwFieldIds eId
, const bool bHiddenParaPrint
)
316 case SwFieldIds::HiddenPara
:
317 return !bHiddenParaPrint
;
318 case SwFieldIds::DbSetNumber
:
319 case SwFieldIds::DbNumSet
:
320 case SwFieldIds::DbNextSet
:
321 case SwFieldIds::DatabaseName
:
328 bool lcl_TriggerNode(const SwFieldIds eId
)
332 case SwFieldIds::HiddenPara
:
333 case SwFieldIds::DbSetNumber
:
334 case SwFieldIds::DbNumSet
:
335 case SwFieldIds::DbNextSet
:
336 case SwFieldIds::DatabaseName
:
342 void lcl_EnsureUserFieldValid(SwFieldType
& rType
)
344 if(rType
.Which() != SwFieldIds::User
)
346 static_cast<SwUserFieldType
*>(&rType
)->EnsureValid();
348 bool lcl_NeedsForcedUpdate(const SwField
& rField
)
350 if (rField
.GetTyp()->Which() == SwFieldIds::DocInfo
)
352 auto pDocInfoField
= static_cast<const SwDocInfoField
*>(&rField
);
353 sal_uInt16 nSubType
= pDocInfoField
->GetSubType();
354 // Do not consider extended SubTypes.
358 case nsSwDocInfoSubType::DI_TITLE
:
359 case nsSwDocInfoSubType::DI_SUBJECT
:
360 case nsSwDocInfoSubType::DI_CHANGE
:
361 case nsSwDocInfoSubType::DI_CUSTOM
:
369 void SwFormatField::ForceUpdateTextNode()
374 SwTextNode
* pTextNd
= &mpTextField
->GetTextNode();
375 OSL_ENSURE(pTextNd
, "Where is my Node?");
377 auto pType
= mpField
->GetTyp();
378 lcl_EnsureUserFieldValid(*pType
);
379 if(lcl_TriggerNode(pType
->Which()))
380 pTextNd
->TriggerNodeUpdate(sw::LegacyModifyHint(nullptr, nullptr));
381 if(!lcl_ExpandField(pType
->Which(), false))
384 // Force notify was added for conditional text fields,
385 // at least the below fields need no forced notify.
386 bool bNeedForced
= lcl_NeedsForcedUpdate(*mpTextField
->GetFormatField().GetField());
387 mpTextField
->ExpandTextField(bNeedForced
);
389 void SwFormatField::UpdateDocPos(const SwTwips nDocPos
)
393 auto pTextNd
= &mpTextField
->GetTextNode();
395 pTextNd
->UpdateDocPos(nDocPos
, mpTextField
->GetStart());
397 void SwFormatField::UpdateTextNode(const SfxHint
& rHint
)
399 if(SfxHintId::SwLegacyModify
!= rHint
.GetId())
401 auto pLegacy
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
402 auto pOld
= pLegacy
->m_pOld
;
403 auto pNew
= pLegacy
->m_pNew
;
404 if (pOld
== nullptr && pNew
== nullptr)
406 ForceUpdateTextNode();
409 else if (pOld
&& (RES_REMOVE_UNO_OBJECT
== pOld
->Which()))
410 { // invalidate cached UNO object
411 m_wXTextField
.clear();
412 // ??? why does this Modify method not already do this?
413 CallSwClientNotify(sw::LegacyModifyHint(pOld
, pNew
));
420 // don't do anything, especially not expand!
421 if( pNew
&& pNew
->Which() == RES_OBJECTDYING
)
424 SwTextNode
* pTextNd
= &mpTextField
->GetTextNode();
425 OSL_ENSURE(pTextNd
, "Where is my Node?");
427 bool bTriggerNode
= pNew
!= nullptr;
428 bool bExpand
= false;
431 switch(pNew
->Which())
433 case RES_ATTRSET_CHG
:
438 auto pType
= mpField
->GetTyp();
439 lcl_EnsureUserFieldValid(*pType
);
440 bTriggerNode
= lcl_TriggerNode(pType
->Which());
441 bExpand
= lcl_ExpandField(pType
->Which(), pOld
&& pOld
->Which() == RES_HIDDENPARA_PRINT
);
447 pTextNd
->TriggerNodeUpdate(sw::LegacyModifyHint(pOld
, pNew
));
449 mpTextField
->ExpandTextField(false);
452 bool SwFormatField::GetInfo( SfxPoolItem
& rInfo
) const
454 if( RES_AUTOFMT_DOCNODE
!= rInfo
.Which() || !mpTextField
)
456 const SwTextNode
* pTextNd
= mpTextField
->GetpTextNode();
457 return nullptr == pTextNd
||
458 &pTextNd
->GetNodes() != static_cast<SwAutoFormatGetDocNode
&>(rInfo
).pNodes
;
461 bool SwFormatField::IsFieldInDoc() const
463 return mpTextField
!= nullptr
464 && mpTextField
->IsFieldInDoc();
467 bool SwFormatField::IsProtect() const
469 return mpTextField
!= nullptr
470 && mpTextField
->GetpTextNode() != nullptr
471 && mpTextField
->GetpTextNode()->IsProtect();
474 void SwFormatField::dumpAsXml(xmlTextWriterPtr pWriter
) const
476 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwFormatField"));
477 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
478 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("mpTextField"), "%p", mpTextField
);
480 SfxPoolItem::dumpAsXml(pWriter
);
481 if (mpField
) // pool default doesn't have one
483 mpField
->dumpAsXml(pWriter
);
486 (void)xmlTextWriterEndElement(pWriter
);
489 // class SwTextField ////////////////////////////////////////////////////
491 SwTextField::SwTextField(
492 SwFormatField
& rAttr
,
493 sal_Int32
const nStartPos
,
494 bool const bInClipboard
)
495 : SwTextAttr( rAttr
, nStartPos
)
496 // fdo#39694 the ExpandField here may not give the correct result in all cases,
497 // but is better than nothing
498 , m_aExpand( rAttr
.GetField()->ExpandField(bInClipboard
, nullptr) )
499 , m_pTextNode( nullptr )
501 rAttr
.SetTextField( *this );
502 SetHasDummyChar(true);
505 SwTextField::~SwTextField( )
507 SwFormatField
& rFormatField( static_cast<SwFormatField
&>(GetAttr()) );
508 if ( this == rFormatField
.GetTextField() )
510 rFormatField
.ClearTextField();
514 bool SwTextField::IsFieldInDoc() const
516 return GetpTextNode() != nullptr
517 && GetpTextNode()->GetNodes().IsDocNodes();
520 void SwTextField::ExpandTextField(const bool bForceNotify
) const
522 OSL_ENSURE( m_pTextNode
, "SwTextField: where is my TextNode?" );
524 const SwField
* pField
= GetFormatField().GetField();
525 const OUString
aNewExpand( pField
->ExpandField(m_pTextNode
->GetDoc().IsClipBoard(),
526 // can't do any better than this here...
527 m_pTextNode
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout()) );
529 const SwFieldIds nWhich
= pField
->GetTyp()->Which();
530 const bool bSameExpandSimpleNotification
531 = SwFieldIds::Chapter
!= nWhich
&& SwFieldIds::PageNumber
!= nWhich
532 && SwFieldIds::RefPageGet
!= nWhich
533 // Page count fields to not use aExpand during formatting,
534 // therefore an invalidation of the text frame has to be triggered even if aNewExpand == aExpand:
535 && (SwFieldIds::DocStat
!= nWhich
536 || DS_PAGE
!= static_cast<const SwDocStatField
*>(pField
)->GetSubType())
537 && (SwFieldIds::GetExp
!= nWhich
538 || static_cast<const SwGetExpField
*>(pField
)->IsInBodyText());
540 bool bHiddenParaChanged
= false;
541 if (aNewExpand
!= m_aExpand
|| bSameExpandSimpleNotification
)
542 bHiddenParaChanged
= m_pTextNode
->CalcHiddenParaField();
544 if (aNewExpand
== m_aExpand
)
546 if ( bSameExpandSimpleNotification
)
548 if( bHiddenParaChanged
)
549 m_pTextNode
->TriggerNodeUpdate(sw::LegacyModifyHint(nullptr, nullptr));
552 // done, if no further notification forced.
558 m_aExpand
= aNewExpand
;
560 const_cast<SwTextField
*>(this)->NotifyContentChange( const_cast<SwFormatField
&>(GetFormatField()) );
563 void SwTextField::CopyTextField( SwTextField
*pDest
) const
565 OSL_ENSURE( m_pTextNode
, "SwTextField: where is my TextNode?" );
566 OSL_ENSURE( pDest
->m_pTextNode
, "SwTextField: where is pDest's TextNode?" );
568 IDocumentFieldsAccess
* pIDFA
= &m_pTextNode
->getIDocumentFieldsAccess();
569 IDocumentFieldsAccess
* pDestIDFA
= &pDest
->m_pTextNode
->getIDocumentFieldsAccess();
571 SwFormatField
& rDestFormatField
= const_cast<SwFormatField
&>(pDest
->GetFormatField());
572 const SwFieldIds nFieldWhich
= rDestFormatField
.GetField()->GetTyp()->Which();
574 if( pIDFA
!= pDestIDFA
)
576 // different documents, e.g. clipboard:
577 // register field type in target document
578 SwFieldType
* pFieldType
;
579 if( nFieldWhich
!= SwFieldIds::Database
580 && nFieldWhich
!= SwFieldIds::User
581 && nFieldWhich
!= SwFieldIds::SetExp
582 && nFieldWhich
!= SwFieldIds::Dde
583 && SwFieldIds::TableOfAuthorities
!= nFieldWhich
)
585 pFieldType
= pDestIDFA
->GetSysFieldType( nFieldWhich
);
589 pFieldType
= pDestIDFA
->InsertFieldType( *rDestFormatField
.GetField()->GetTyp() );
592 // DDE fields need special treatment
593 if( SwFieldIds::Dde
== nFieldWhich
)
595 if( rDestFormatField
.GetTextField() )
597 static_cast<SwDDEFieldType
*>(rDestFormatField
.GetField()->GetTyp())->DecRefCnt();
599 static_cast<SwDDEFieldType
*>(pFieldType
)->IncRefCnt();
602 OSL_ENSURE( pFieldType
, "unknown FieldType" );
603 pFieldType
->Add( &rDestFormatField
); // register at the field type
604 rDestFormatField
.GetField()->ChgTyp( pFieldType
);
607 // update expression fields
608 if( nFieldWhich
== SwFieldIds::SetExp
609 || nFieldWhich
== SwFieldIds::GetExp
610 || nFieldWhich
== SwFieldIds::HiddenText
)
612 SwTextField
* pField
= const_cast<SwTextField
*>(this);
613 pDestIDFA
->UpdateExpFields( pField
, true );
615 // table fields: external display
616 else if( SwFieldIds::Table
== nFieldWhich
617 && static_cast<SwTableField
*>(rDestFormatField
.GetField())->IsIntrnlName() )
619 // convert internal (core) to external (UI) formula
620 const SwTableNode
* pTableNd
= m_pTextNode
->FindTableNode();
621 if( pTableNd
) // in a table?
622 static_cast<SwTableField
*>(rDestFormatField
.GetField())->PtrToBoxNm( &pTableNd
->GetTable() );
626 void SwTextField::NotifyContentChange(SwFormatField
& rFormatField
)
628 //if not in undo section notify the change
629 if (m_pTextNode
&& m_pTextNode
->GetNodes().IsDocNodes())
630 m_pTextNode
->TriggerNodeUpdate(sw::LegacyModifyHint(nullptr, &rFormatField
));
634 void SwTextField::GetPamForTextField(
635 const SwTextField
& rTextField
,
636 std::shared_ptr
< SwPaM
>& rPamForTextField
)
638 if (rTextField
.GetpTextNode() == nullptr)
640 SAL_WARN("sw.core", "<SwTextField::GetPamForField> - missing <SwTextNode>");
644 const SwTextNode
& rTextNode
= rTextField
.GetTextNode();
646 rPamForTextField
= std::make_shared
<SwPaM
>( rTextNode
,
647 (rTextField
.End() != nullptr) ? *(rTextField
.End()) : ( rTextField
.GetStart() + 1 ),
649 rTextField
.GetStart() );
654 void SwTextField::DeleteTextField( const SwTextField
& rTextField
)
656 if (rTextField
.GetpTextNode() != nullptr)
658 std::shared_ptr
< SwPaM
> pPamForTextField
;
659 GetPamForTextField(rTextField
, pPamForTextField
);
660 if (pPamForTextField
!= nullptr)
662 rTextField
.GetTextNode().GetDoc().getIDocumentContentOperations().DeleteAndJoin(*pPamForTextField
);
667 // class SwTextInputField ///////////////////////////////////////////////
669 // input field in-place editing
670 SwTextInputField::SwTextInputField(
671 SwFormatField
& rAttr
,
672 sal_Int32
const nStart
,
673 sal_Int32
const nEnd
,
674 bool const bInClipboard
)
676 : SwTextAttr( rAttr
, nStart
)
677 , SwTextAttrNesting( rAttr
, nStart
, nEnd
)
678 , SwTextField( rAttr
, nStart
, bInClipboard
)
679 , m_bLockNotifyContentChange( false )
681 SetHasDummyChar( false );
682 SetHasContent( true );
685 SwTextInputField::~SwTextInputField()
689 bool SwTextInputField::LockNotifyContentChange()
691 if (m_bLockNotifyContentChange
)
695 m_bLockNotifyContentChange
= true;
699 void SwTextInputField::UnlockNotifyContentChange()
701 m_bLockNotifyContentChange
= false;
704 void SwTextInputField::NotifyContentChange( SwFormatField
& rFormatField
)
706 if ( !m_bLockNotifyContentChange
)
708 LockNotifyContentChange();
710 SwTextField::NotifyContentChange( rFormatField
);
711 UpdateTextNodeContent( GetFieldContent() );
713 UnlockNotifyContentChange();
717 OUString
SwTextInputField::GetFieldContent() const
719 return GetFormatField().GetField()->ExpandField(false, nullptr/*ignored anyway*/);
722 void SwTextInputField::UpdateFieldContent()
724 if ( !(IsFieldInDoc()
725 && GetStart() != (*End())) )
728 assert( (*End()) - GetStart() >= 2 &&
729 "<SwTextInputField::UpdateFieldContent()> - Are CH_TXT_ATR_INPUTFIELDSTART and/or CH_TXT_ATR_INPUTFIELDEND missing?" );
730 // skip CH_TXT_ATR_INPUTFIELDSTART character
731 const sal_Int32 nIdx
= GetStart() + 1;
732 // skip CH_TXT_ATR_INPUTFIELDEND character
733 const sal_Int32 nLen
= static_cast<sal_Int32
>(std::max
<sal_Int32
>( 0, ( (*End()) - 1 - nIdx
) ));
734 const OUString aNewFieldContent
= GetTextNode().GetExpandText(nullptr, nIdx
, nLen
);
736 const SwField
* pField
= GetFormatField().GetField();
737 const SwInputField
* pInputField
= dynamic_cast<const SwInputField
*>(pField
);
739 const_cast<SwInputField
*>(pInputField
)->applyFieldContent( aNewFieldContent
);
741 const SwSetExpField
* pExpField
= dynamic_cast<const SwSetExpField
*>(pField
);
744 assert(pExpField
->GetInputFlag());
745 const_cast<SwSetExpField
*>(pExpField
)->SetPar2(aNewFieldContent
);
747 assert(pInputField
|| pExpField
);
749 // trigger update of fields for scenarios in which the Input Field's content is part of e.g. a table formula
750 GetTextNode().GetDoc().getIDocumentFieldsAccess().GetUpdateFields().SetFieldsDirty(true);
753 void SwTextInputField::UpdateTextNodeContent( const OUString
& rNewContent
)
755 assert(IsFieldInDoc() &&
756 "<SwTextInputField::UpdateTextNodeContent(..)> - misusage as Input Field is not in document content.");
758 assert( (*End()) - GetStart() >= 2 &&
759 "<SwTextInputField::UpdateTextNodeContent(..)> - Are CH_TXT_ATR_INPUTFIELDSTART and/or CH_TXT_ATR_INPUTFIELDEND missing?" );
760 // skip CH_TXT_ATR_INPUTFIELDSTART character
761 const sal_Int32 nIdx
= GetStart() + 1;
762 // skip CH_TXT_ATR_INPUTFIELDEND character
763 const sal_Int32 nDelLen
= std::max
<sal_Int32
>( 0, ( (*End()) - 1 - nIdx
) );
764 SwContentIndex
aIdx( &GetTextNode(), nIdx
);
765 GetTextNode().ReplaceText( aIdx
, nDelLen
, rNewContent
);
768 // class SwTextAnnotationField //////////////////////////////////////////
770 // text annotation field
771 SwTextAnnotationField::SwTextAnnotationField(
772 SwFormatField
& rAttr
,
773 sal_Int32
const nStart
,
774 bool const bInClipboard
)
775 : SwTextAttr( rAttr
, nStart
)
776 , SwTextField( rAttr
, nStart
, bInClipboard
)
780 SwTextAnnotationField::~SwTextAnnotationField()
784 ::sw::mark::IMark
* SwTextAnnotationField::GetAnnotationMark() const
786 auto pPostItField
= dynamic_cast<const SwPostItField
*>(GetFormatField().GetField());
787 assert(pPostItField
);
789 SwDoc
& rDoc
= static_cast<const SwPostItFieldType
*>(pPostItField
->GetTyp())->GetDoc();
791 IDocumentMarkAccess
* pMarksAccess
= rDoc
.getIDocumentMarkAccess();
792 IDocumentMarkAccess::const_iterator_t pMark
= pMarksAccess
->findAnnotationMark( pPostItField
->GetName() );
793 return pMark
!= pMarksAccess
->getAnnotationMarksEnd()
798 void SwFormatField::SetXTextField(rtl::Reference
<SwXTextField
> const& xTextField
)
799 { m_wXTextField
= xTextField
.get(); }
801 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */