tdf#35361 Add a Quick Look plugins for .od* files on macOS
[LibreOffice.git] / sw / source / core / txtnode / atrfld.cxx
blob356fbd5879a3f9f9027c5765ce72958a8d2b09f7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <fmtfld.hxx>
22 #include <libxml/xmlwriter.h>
24 #include <fldbas.hxx>
25 #include <txtfld.hxx>
26 #include <txtannotationfld.hxx>
27 #include <docfld.hxx>
28 #include <docufld.hxx>
29 #include <doc.hxx>
30 #include <unofield.hxx>
32 #include <pam.hxx>
33 #include <reffld.hxx>
34 #include <ddefld.hxx>
35 #include <usrfld.hxx>
36 #include <expfld.hxx>
37 #include <ndtxt.hxx>
38 #include <hints.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 )
50 , SfxBroadcaster()
51 , mpTextField( nullptr )
53 setNonShareable();
56 SwFormatField::SwFormatField( const SwField &rField )
57 : SfxPoolItem( RES_TXTATR_FIELD )
58 , SfxBroadcaster()
59 , mpField( rField.CopyField() )
60 , mpTextField( nullptr )
62 setNonShareable();
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 );
91 // #i24434#
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
94 // corrected
95 SwFormatField::SwFormatField( const SwFormatField& rAttr )
96 : SfxPoolItem( rAttr )
97 , SfxBroadcaster()
98 , mpTextField( nullptr )
100 setNonShareable();
101 if ( !rAttr.mpField )
102 return;
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());
111 assert(pField);
112 if (pField)
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
142 mpField.reset();
144 // some fields need to delete their field type
145 if( !(pType && pType->HasOnlyOneListener()) )
146 return;
148 bool bDel = false;
149 switch( pType->Which() )
151 case SwFieldIds::User:
152 bDel = static_cast<SwUserFieldType*>(pType)->IsDeleted();
153 break;
155 case SwFieldIds::SetExp:
156 bDel = static_cast<SwSetExpFieldType*>(pType)->IsDeleted();
157 break;
159 case SwFieldIds::Dde:
160 bDel = static_cast<SwDDEFieldType*>(pType)->IsDeleted();
161 break;
162 default: break;
165 if( bDel )
167 // unregister before deleting
168 pType->Remove(*this);
169 delete pType;
173 void SwFormatField::RegisterToFieldType( SwFieldType& rType )
175 rType.Add(*this);
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));
206 return ( mpField
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) {
232 if(mpTextField)
233 static_cast<const sw::AutoFormatUsedHint&>(rHint).CheckNode(mpTextField->GetpTextNode());
234 return;
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
243 if( !mpTextField )
244 return;
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));
251 pPaM->SetMark();
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)
258 if(!mpTextField)
259 return;
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())
297 return;
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)
307 if(!GetTextField())
308 return;
309 SwTextNode* pNd = GetTextField()->GetpTextNode();
310 if(!pNd || !pNd->GetNodes().IsDocNodes())
311 return;
313 pGatherFieldsHint->m_rvFields.push_back(this);
315 else if (rHint.GetId() == SfxHintId::SwDocPosUpdate)
317 UpdateDocPos(static_cast<const sw::DocPosUpdate*>(&rHint)->m_nDocPos);
321 namespace
323 bool lcl_ExpandField(const SwFieldIds eId)
325 switch(eId)
327 case SwFieldIds::DbSetNumber:
328 case SwFieldIds::DbNumSet:
329 case SwFieldIds::DbNextSet:
330 case SwFieldIds::DatabaseName:
331 return false;
332 default:
333 return true;
337 bool lcl_TriggerNode(const SwFieldIds eId)
339 switch(eId)
341 case SwFieldIds::HiddenPara:
342 case SwFieldIds::DbSetNumber:
343 case SwFieldIds::DbNumSet:
344 case SwFieldIds::DbNextSet:
345 case SwFieldIds::DatabaseName:
346 return true;
347 default:
348 return false;
351 void lcl_EnsureUserFieldValid(SwFieldType& rType)
353 if(rType.Which() != SwFieldIds::User)
354 return;
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.
364 nSubType &= 0xff;
365 switch (nSubType)
367 case nsSwDocInfoSubType::DI_TITLE:
368 case nsSwDocInfoSubType::DI_SUBJECT:
369 case nsSwDocInfoSubType::DI_CHANGE:
370 case nsSwDocInfoSubType::DI_CUSTOM:
371 return false;
374 return true;
378 void SwFormatField::ForceUpdateTextNode()
380 if (!IsFieldInDoc())
381 return;
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()))
391 return;
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)
400 if (!IsFieldInDoc())
401 return;
402 auto pTextNd = &mpTextField->GetTextNode();
404 pTextNd->UpdateDocPos(nDocPos, mpTextField->GetStart());
406 void SwFormatField::UpdateTextNode(const SfxHint& rHint)
408 if(SfxHintId::SwHiddenParaPrint == rHint.GetId())
410 if (!IsFieldInDoc())
411 return;
412 auto pType = mpField->GetTyp();
413 lcl_EnsureUserFieldValid(*pType);
414 bool bTriggerNode = lcl_TriggerNode(pType->Which());
415 bool bExpand = lcl_ExpandField(pType->Which());
416 if(bTriggerNode)
418 SwTextNode* pTextNd = &mpTextField->GetTextNode();
419 OSL_ENSURE(pTextNd, "Where is my Node?");
420 pTextNd->TriggerNodeUpdate(sw::LegacyModifyHint(nullptr, nullptr));
422 if(bExpand)
423 mpTextField->ExpandTextField(false);
424 return;
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);
431 return;
433 if (rHint.GetId() == SfxHintId::SwFormatChange)
435 auto pChangeHint = static_cast<const SwFormatChangeHint*>(&rHint);
436 if (!IsFieldInDoc())
437 return;
439 SwTextNode* pTextNd = &mpTextField->GetTextNode();
440 OSL_ENSURE(pTextNd, "Where is my Node?");
442 bool bTriggerNode = pChangeHint->m_pNewFormat != nullptr;
443 if(bTriggerNode)
444 pTextNd->TriggerNodeUpdate(*pChangeHint);
445 return;
447 if(SfxHintId::SwLegacyModify != rHint.GetId())
448 return;
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();
455 return;
458 if (!IsFieldInDoc())
459 return;
461 // don't do anything, especially not expand!
462 if( pNew && pNew->Which() == RES_OBJECTDYING )
463 return;
465 SwTextNode* pTextNd = &mpTextField->GetTextNode();
466 OSL_ENSURE(pTextNd, "Where is my Node?");
468 bool bTriggerNode = pNew != nullptr;
469 bool bExpand = false;
470 if(pNew)
472 switch(pNew->Which())
474 case RES_ATTRSET_CHG:
475 break;
476 default:
478 auto pType = mpField->GetTyp();
479 lcl_EnsureUserFieldValid(*pType);
480 bTriggerNode = lcl_TriggerNode(pType->Which());
481 bExpand = lcl_ExpandField(pType->Which());
482 pOld = nullptr;
486 if(bTriggerNode)
487 pTextNd->TriggerNodeUpdate(sw::LegacyModifyHint(pOld, pNew));
488 if(bExpand)
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
529 , m_aExpand()
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));
583 if ( !bForceNotify )
585 // done, if no further notification forced.
586 return;
590 else
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 );
620 else
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));
666 /*static*/
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>");
674 return;
677 const SwTextNode& rTextNode = rTextField.GetTextNode();
679 rPamForTextField = std::make_shared<SwPaM>( rTextNode,
680 (rTextField.End() != nullptr) ? *(rTextField.End()) : ( rTextField.GetStart() + 1 ),
681 rTextNode,
682 rTextField.GetStart() );
686 /*static*/
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)
726 return false;
728 m_bLockNotifyContentChange = true;
729 return 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())) )
759 return;
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);
771 if (pInputField)
772 const_cast<SwInputField*>(pInputField)->applyFieldContent( aNewFieldContent );
774 const SwSetExpField* pExpField = dynamic_cast<const SwSetExpField*>(pField);
775 if (pExpField)
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()
827 ? *pMark
828 : nullptr;
831 void SwFormatField::SetXTextField(rtl::Reference<SwXTextField> const& xTextField)
832 { m_wXTextField = xTextField.get(); }
834 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */