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 .
20 #include <sal/config.h>
24 #include <UndoTable.hxx>
25 #include <hintids.hxx>
26 #include <o3tl/any.hxx>
27 #include <osl/diagnose.h>
28 #include <unotools/collatorwrapper.hxx>
29 #include <unotools/charclass.hxx>
30 #include <editeng/langitem.hxx>
31 #include <editeng/fontitem.hxx>
32 #include <com/sun/star/text/SetVariableType.hpp>
33 #include <unofield.hxx>
37 #include <fmtanchr.hxx>
40 #include <IDocumentFieldsAccess.hxx>
42 #include <pagefrm.hxx>
45 #include <rootfrm.hxx>
56 #include <swtable.hxx>
57 #include <breakit.hxx>
58 #include <SwStyleNameMapper.hxx>
59 #include <unofldmid.h>
60 #include <numrule.hxx>
63 using namespace ::com::sun::star
;
64 using namespace ::com::sun::star::text
;
66 static sal_Int16
lcl_SubTypeToAPI(sal_uInt16 nSubType
)
71 case nsSwGetSetExpType::GSE_EXPR
:
72 nRet
= SetVariableType::VAR
; // 0
74 case nsSwGetSetExpType::GSE_SEQ
:
75 nRet
= SetVariableType::SEQUENCE
; // 1
77 case nsSwGetSetExpType::GSE_FORMULA
:
78 nRet
= SetVariableType::FORMULA
; // 2
80 case nsSwGetSetExpType::GSE_STRING
:
81 nRet
= SetVariableType::STRING
; // 3
87 static sal_Int32
lcl_APIToSubType(const uno::Any
& rAny
)
94 case SetVariableType::VAR
: nSet
= nsSwGetSetExpType::GSE_EXPR
; break;
95 case SetVariableType::SEQUENCE
: nSet
= nsSwGetSetExpType::GSE_SEQ
; break;
96 case SetVariableType::FORMULA
: nSet
= nsSwGetSetExpType::GSE_FORMULA
; break;
97 case SetVariableType::STRING
: nSet
= nsSwGetSetExpType::GSE_STRING
; break;
99 OSL_FAIL("wrong value");
105 OUString
ReplacePoint( const OUString
& rTmpName
, bool bWithCommandType
)
107 // replace first and last (if bWithCommandType: last two) dot
108 // since table names may contain dots
110 sal_Int32 nIndex
= rTmpName
.lastIndexOf('.');
116 OUString sRes
= rTmpName
.replaceAt(nIndex
, 1, rtl::OUStringChar(DB_DELIM
));
118 if (bWithCommandType
)
120 nIndex
= sRes
.lastIndexOf('.', nIndex
);
125 sRes
= sRes
.replaceAt(nIndex
, 1, rtl::OUStringChar(DB_DELIM
));
128 nIndex
= sRes
.indexOf('.');
131 sRes
= sRes
.replaceAt(nIndex
, 1, rtl::OUStringChar(DB_DELIM
));
136 static SwTextNode
* GetFirstTextNode( const SwDoc
& rDoc
, SwPosition
& rPos
,
137 const SwContentFrame
*pCFrame
, Point
&rPt
)
139 SwTextNode
* pTextNode
= nullptr;
142 const SwNodes
& rNodes
= rDoc
.GetNodes();
143 rPos
.Assign( *rNodes
.GetEndOfContent().StartOfSectionNode() );
145 while( nullptr != (pCNd
= SwNodes::GoNext( &rPos
) ) &&
146 nullptr == ( pTextNode
= pCNd
->GetTextNode() ) )
148 OSL_ENSURE( pTextNode
, "Where is the 1. TextNode?" );
150 else if ( !pCFrame
->isFrameAreaDefinitionValid() )
152 assert(pCFrame
->IsTextFrame());
153 rPos
= static_cast<SwTextFrame
const*>(pCFrame
)->MapViewToModelPos(TextFrameIndex(0));
157 pCFrame
->GetModelPositionForViewPoint( &rPos
, rPt
);
158 pTextNode
= rPos
.GetNode().GetTextNode();
163 const SwTextNode
* GetBodyTextNode( const SwDoc
& rDoc
, SwPosition
& rPos
,
164 const SwFrame
& rFrame
)
166 const SwLayoutFrame
* pLayout
= rFrame
.GetUpper();
167 const SwTextNode
* pTextNode
= nullptr;
171 if( pLayout
->IsFlyFrame() )
174 const SwFrameFormat
* pFlyFormat
= static_cast<const SwFlyFrame
*>(pLayout
)->GetFormat();
175 assert(pFlyFormat
&& "Could not find FlyFormat, where is the field?");
177 const SwFormatAnchor
&rAnchor
= pFlyFormat
->GetAnchor();
179 if( RndStdIds::FLY_AT_FLY
== rAnchor
.GetAnchorId() )
181 // the fly needs to be attached somewhere, so ask it
182 pLayout
= static_cast<const SwLayoutFrame
*>(static_cast<const SwFlyFrame
*>(pLayout
)->GetAnchorFrame());
185 else if ((RndStdIds::FLY_AT_PARA
== rAnchor
.GetAnchorId()) ||
186 (RndStdIds::FLY_AT_CHAR
== rAnchor
.GetAnchorId()) ||
187 (RndStdIds::FLY_AS_CHAR
== rAnchor
.GetAnchorId()))
189 OSL_ENSURE( rAnchor
.GetContentAnchor(), "no valid position" );
190 rPos
= *rAnchor
.GetContentAnchor();
191 pTextNode
= rPos
.GetNode().GetTextNode();
192 if ( RndStdIds::FLY_AT_PARA
== rAnchor
.GetAnchorId() )
194 rPos
.AssignStartIndex(*pTextNode
);
197 // do not break yet, might be as well in Header/Footer/Footnote/Fly
198 pLayout
= static_cast<const SwFlyFrame
*>(pLayout
)->GetAnchorFrame()
199 ? static_cast<const SwFlyFrame
*>(pLayout
)->GetAnchorFrame()->GetUpper() : nullptr;
204 pLayout
->FindPageFrame()->GetContentPosition(
205 pLayout
->getFrameArea().Pos(), rPos
);
206 pTextNode
= rPos
.GetNode().GetTextNode();
209 else if( pLayout
->IsFootnoteFrame() )
211 // get the anchor's node
212 const SwTextFootnote
* pFootnote
= static_cast<const SwFootnoteFrame
*>(pLayout
)->GetAttr();
213 pTextNode
= &pFootnote
->GetTextNode();
214 rPos
.Assign( *pTextNode
, pFootnote
->GetStart() );
216 else if( pLayout
->IsHeaderFrame() || pLayout
->IsFooterFrame() )
218 const SwContentFrame
* pContentFrame
;
219 const SwPageFrame
* pPgFrame
= pLayout
->FindPageFrame();
220 if( pLayout
->IsHeaderFrame() )
222 const SwTabFrame
*pTab
;
223 if( nullptr != ( pContentFrame
= pPgFrame
->FindFirstBodyContent()) &&
224 nullptr != (pTab
= pContentFrame
->FindTabFrame()) && pTab
->IsFollow() &&
225 pTab
->GetTable()->GetRowsToRepeat() > 0 &&
226 pTab
->IsInHeadline( *pContentFrame
) )
228 // take the next line
229 const SwLayoutFrame
* pRow
= pTab
->GetFirstNonHeadlineRow();
230 pContentFrame
= pRow
->ContainsContent();
234 pContentFrame
= pPgFrame
->FindLastBodyContent();
236 if( pContentFrame
&& !pContentFrame
->IsInFootnote() )
238 assert(pContentFrame
->IsTextFrame());
239 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(pContentFrame
));
240 rPos
= pFrame
->MapViewToModelPos(TextFrameIndex(pFrame
->GetText().getLength()));
241 pTextNode
= rPos
.GetNode().GetTextNode();
246 Point
aPt( pLayout
->getFrameArea().Pos() );
247 aPt
.AdjustY( 1 ); // get out of the header
248 pContentFrame
= pPgFrame
->GetContentPos( aPt
, false, true );
249 pTextNode
= GetFirstTextNode( rDoc
, rPos
, pContentFrame
, aPt
);
254 pLayout
= pLayout
->GetUpper();
257 break; // found, so finish loop
262 SwGetExpFieldType::SwGetExpFieldType(SwDoc
* pDc
)
263 : SwValueFieldType( pDc
, SwFieldIds::GetExp
)
267 std::unique_ptr
<SwFieldType
> SwGetExpFieldType::Copy() const
269 return std::make_unique
<SwGetExpFieldType
>(GetDoc());
272 void SwGetExpFieldType::SwClientNotify(const SwModify
&, const SfxHint
&)
274 // do not expand anything (else)
277 SwGetExpField::SwGetExpField(SwGetExpFieldType
* pTyp
, const OUString
& rFormel
,
278 sal_uInt16 nSub
, sal_uLong nFormat
)
279 : SwFormulaField( pTyp
, nFormat
, 0.0 )
280 , m_fValueRLHidden(0.0)
282 m_bIsInBodyText( true ),
284 m_bLateInitialization( false )
286 SetFormula( rFormel
);
289 void SwGetExpField::ChgExpStr(const OUString
& rExpand
, SwRootFrame
const*const pLayout
)
291 if (!pLayout
|| pLayout
->IsHideRedlines())
293 m_sExpandRLHidden
= rExpand
;
295 if (!pLayout
|| !pLayout
->IsHideRedlines())
301 OUString
SwGetExpField::ExpandImpl(SwRootFrame
const*const pLayout
) const
303 if(m_nSubType
& nsSwExtendedSubType::SUB_CMD
)
306 return (pLayout
&& pLayout
->IsHideRedlines()) ? m_sExpandRLHidden
: m_sExpand
;
309 OUString
SwGetExpField::GetFieldName() const
311 const SwFieldTypesEnum nType
=
312 (nsSwGetSetExpType::GSE_FORMULA
& m_nSubType
)
313 ? SwFieldTypesEnum::Formel
314 : SwFieldTypesEnum::Get
;
316 return SwFieldType::GetTypeStr(nType
) + " " + GetFormula();
319 std::unique_ptr
<SwField
> SwGetExpField::Copy() const
321 std::unique_ptr
<SwGetExpField
> pTmp(new SwGetExpField(static_cast<SwGetExpFieldType
*>(GetTyp()),
322 GetFormula(), m_nSubType
, GetFormat()));
323 pTmp
->SetLanguage(GetLanguage());
324 pTmp
->m_fValueRLHidden
= m_fValueRLHidden
;
325 pTmp
->SwValueField::SetValue(GetValue());
326 pTmp
->m_sExpand
= m_sExpand
;
327 pTmp
->m_sExpandRLHidden
= m_sExpandRLHidden
;
328 pTmp
->m_bIsInBodyText
= m_bIsInBodyText
;
329 pTmp
->SetAutomaticLanguage(IsAutomaticLanguage());
330 if( m_bLateInitialization
)
331 pTmp
->SetLateInitialization();
333 return std::unique_ptr
<SwField
>(pTmp
.release());
336 void SwGetExpField::ChangeExpansion( const SwFrame
& rFrame
, const SwTextField
& rField
)
338 if( m_bIsInBodyText
) // only fields in Footer, Header, FootNote, Flys
341 OSL_ENSURE( !rFrame
.IsInDocBody(), "Flag incorrect, frame is in DocBody" );
343 // determine document (or is there an easier way?)
344 const SwTextNode
* pTextNode
= &rField
.GetTextNode();
345 SwDoc
& rDoc
= const_cast<SwDoc
&>(pTextNode
->GetDoc());
347 // create index for determination of the TextNode
348 SwPosition
aPos( rDoc
.GetNodes() );
349 pTextNode
= GetBodyTextNode( rDoc
, aPos
, rFrame
);
351 // If no layout exists, ChangeExpansion is called for header and
352 // footer lines via layout formatting without existing TextNode.
356 if( m_bLateInitialization
)
358 SwFieldType
* pSetExpField
= rDoc
.getIDocumentFieldsAccess().GetFieldType(SwFieldIds::SetExp
, GetFormula(), false);
361 m_bLateInitialization
= false;
362 if( !(GetSubType() & nsSwGetSetExpType::GSE_STRING
) &&
363 static_cast< SwSetExpFieldType
* >(pSetExpField
)->GetType() == nsSwGetSetExpType::GSE_STRING
)
364 SetSubType( nsSwGetSetExpType::GSE_STRING
);
368 SwRootFrame
const& rLayout(*rFrame
.getRootFrame());
369 OUString
& rExpand(rLayout
.IsHideRedlines() ? m_sExpandRLHidden
: m_sExpand
);
370 // here a page number is needed to sort correctly
371 SetGetExpField
aEndField(aPos
.GetNode(), &rField
, aPos
.GetContentIndex(), rFrame
.GetPhyPageNum());
372 if(GetSubType() & nsSwGetSetExpType::GSE_STRING
)
374 std::unordered_map
<OUString
, OUString
> aHashTable
;
375 rDoc
.getIDocumentFieldsAccess().FieldsToExpand(aHashTable
, aEndField
, rLayout
);
376 rExpand
= LookString( aHashTable
, GetFormula() );
380 // fill calculator with values
381 SwCalc
aCalc( rDoc
);
382 rDoc
.getIDocumentFieldsAccess().FieldsToCalc(aCalc
, aEndField
, &rLayout
);
385 SetValue(aCalc
.Calculate(GetFormula()).GetDouble(), &rLayout
);
387 // analyse based on format
388 rExpand
= static_cast<SwValueFieldType
*>(GetTyp())->ExpandValue(
389 GetValue(&rLayout
), GetFormat(), GetLanguage());
393 OUString
SwGetExpField::GetPar2() const
398 void SwGetExpField::SetPar2(const OUString
& rStr
)
403 sal_uInt16
SwGetExpField::GetSubType() const
408 void SwGetExpField::SetSubType(sal_uInt16 nType
)
413 void SwGetExpField::SetLanguage(LanguageType nLng
)
415 if (m_nSubType
& nsSwExtendedSubType::SUB_CMD
)
416 SwField::SetLanguage(nLng
);
418 SwValueField::SetLanguage(nLng
);
421 bool SwGetExpField::QueryValue( uno::Any
& rAny
, sal_uInt16 nWhichId
) const
425 case FIELD_PROP_DOUBLE
:
428 case FIELD_PROP_FORMAT
:
429 rAny
<<= static_cast<sal_Int32
>(GetFormat());
431 case FIELD_PROP_USHORT1
:
432 rAny
<<= static_cast<sal_Int16
>(m_nSubType
);
434 case FIELD_PROP_PAR1
:
435 rAny
<<= GetFormula();
437 case FIELD_PROP_SUBTYPE
:
439 sal_Int16 nRet
= lcl_SubTypeToAPI(GetSubType() & 0xff);
443 case FIELD_PROP_BOOL2
:
444 rAny
<<= 0 != (m_nSubType
& nsSwExtendedSubType::SUB_CMD
);
446 case FIELD_PROP_PAR4
:
450 return SwField::QueryValue(rAny
, nWhichId
);
455 bool SwGetExpField::PutValue( const uno::Any
& rAny
, sal_uInt16 nWhichId
)
460 case FIELD_PROP_DOUBLE
:
461 SwValueField::SetValue(*o3tl::doAccess
<double>(rAny
));
462 m_fValueRLHidden
= *o3tl::doAccess
<double>(rAny
);
464 case FIELD_PROP_FORMAT
:
468 case FIELD_PROP_USHORT1
:
470 m_nSubType
= o3tl::narrowing
<sal_uInt16
>(nTmp
);
472 case FIELD_PROP_PAR1
:
479 case FIELD_PROP_SUBTYPE
:
480 nTmp
= lcl_APIToSubType(rAny
);
482 SetSubType( o3tl::narrowing
<sal_uInt16
>((GetSubType() & 0xff00) | nTmp
));
484 case FIELD_PROP_BOOL2
:
485 if(*o3tl::doAccess
<bool>(rAny
))
486 m_nSubType
|= nsSwExtendedSubType::SUB_CMD
;
488 m_nSubType
&= (~nsSwExtendedSubType::SUB_CMD
);
490 case FIELD_PROP_PAR4
:
494 ChgExpStr(sTmp
, nullptr);
498 return SwField::PutValue(rAny
, nWhichId
);
503 SwSetExpFieldType::SwSetExpFieldType( SwDoc
* pDc
, OUString aName
, sal_uInt16 nTyp
)
504 : SwValueFieldType( pDc
, SwFieldIds::SetExp
),
505 m_sName( std::move(aName
) ),
506 m_sDelim( u
"."_ustr
),
507 m_nType(nTyp
), m_nLevel( UCHAR_MAX
),
510 if( ( nsSwGetSetExpType::GSE_SEQ
| nsSwGetSetExpType::GSE_STRING
) & m_nType
)
511 EnableFormat(false); // do not use Numberformatter
514 std::unique_ptr
<SwFieldType
> SwSetExpFieldType::Copy() const
516 std::unique_ptr
<SwSetExpFieldType
> pNew(new SwSetExpFieldType(GetDoc(), m_sName
, m_nType
));
517 pNew
->m_bDeleted
= m_bDeleted
;
518 pNew
->m_sDelim
= m_sDelim
;
519 pNew
->m_nLevel
= m_nLevel
;
524 OUString
SwSetExpFieldType::GetName() const
529 const OUString
& SwSetExpField::GetExpStr(SwRootFrame
const*const pLayout
) const
531 return (pLayout
&& pLayout
->IsHideRedlines()) ? msExpandRLHidden
: msExpand
;
534 void SwSetExpField::ChgExpStr(const OUString
& rExpand
, SwRootFrame
const*const pLayout
)
536 if (!pLayout
|| pLayout
->IsHideRedlines())
538 msExpandRLHidden
= rExpand
;
540 if (!pLayout
|| !pLayout
->IsHideRedlines())
546 void SwSetExpFieldType::SwClientNotify(const SwModify
&, const SfxHint
&)
548 // do not expand further
551 void SwSetExpFieldType::SetSeqFormat(sal_uLong nFormat
)
553 std::vector
<SwFormatField
*> vFields
;
554 GatherFields(vFields
, false);
555 for(auto pFormatField
: vFields
)
556 pFormatField
->GetField()->ChangeFormat(nFormat
);
559 sal_uLong
SwSetExpFieldType::GetSeqFormat() const
561 if( !HasWriterListeners() )
562 return SVX_NUM_ARABIC
;
564 std::vector
<SwFormatField
*> vFields
;
565 GatherFields(vFields
, false);
566 return vFields
.front()->GetField()->GetFormat();
569 void SwSetExpFieldType::SetSeqRefNo( SwSetExpField
& rField
)
571 if( !HasWriterListeners() || !(nsSwGetSetExpType::GSE_SEQ
& m_nType
) )
574 std::vector
<sal_uInt16
> aArr
;
576 // check if number is already used and if a new one needs to be created
577 std::vector
<SwFormatField
*> vFields
;
578 GatherFields(vFields
);
579 for(SwFormatField
* pF
: vFields
)
580 if(pF
->GetField() != &rField
)
581 InsertSort(aArr
, static_cast<SwSetExpField
*>(pF
->GetField())->GetSeqNumber());
583 // check first if number already exists
584 sal_uInt16 nNum
= rField
.GetSeqNumber();
585 if( USHRT_MAX
!= nNum
)
587 std::vector
<sal_uInt16
>::size_type n
{0};
589 for( n
= 0; n
< aArr
.size(); ++n
)
590 if( aArr
[ n
] >= nNum
)
593 if( n
== aArr
.size() || aArr
[ n
] > nNum
)
594 return; // no -> use it
597 // flagged all numbers, so determine the right number
598 std::vector
<sal_uInt16
>::size_type n
= aArr
.size();
599 OSL_ENSURE( n
<= std::numeric_limits
<sal_uInt16
>::max(), "Array is too big for using a sal_uInt16 index" );
601 if ( n
> 0 && aArr
[ n
-1 ] != n
-1 )
603 for( n
= 0; n
< aArr
.size(); ++n
)
608 rField
.SetSeqNumber( n
);
611 size_t SwSetExpFieldType::GetSeqFieldList(SwSeqFieldList
& rList
,
612 SwRootFrame
const*const pLayout
)
616 IDocumentRedlineAccess
const& rIDRA(GetDoc()->getIDocumentRedlineAccess());
618 std::vector
<SwFormatField
*> vFields
;
619 GatherFields(vFields
);
620 for(SwFormatField
* pF
: vFields
)
622 const SwTextNode
* pNd
;
623 if( nullptr != ( pNd
= pF
->GetTextField()->GetpTextNode() )
624 && (!pLayout
|| !pLayout
->IsHideRedlines()
625 || !sw::IsFieldDeletedInModel(rIDRA
, *pF
->GetTextField())))
627 SeqFieldLstElem
aNew(
628 pNd
->GetExpandText(pLayout
),
629 static_cast<SwSetExpField
*>(pF
->GetField())->GetSeqNumber() );
630 rList
.InsertSort( std::move(aNew
) );
633 return rList
.Count();
636 void SwSetExpFieldType::SetChapter(SwSetExpField
& rField
, const SwNode
& rNd
,
637 SwRootFrame
const*const pLayout
)
639 const SwTextNode
* pTextNd
= rNd
.FindOutlineNodeOfLevel(m_nLevel
, pLayout
);
643 SwNumRule
* pRule
= pTextNd
->GetNumRule();
648 // --> OD 2005-11-02 #i51089 - TUNING#
649 if (SwNodeNum
const*const pNum
= pTextNd
->GetNum(pLayout
))
651 // only get the number, without pre-/post-fixstrings
652 OUString
const sNumber(pRule
->MakeNumString(*pNum
, false));
654 if( !sNumber
.isEmpty() )
655 rField
.ChgExpStr(sNumber
+ m_sDelim
+ rField
.GetExpStr(pLayout
), pLayout
);
659 OSL_ENSURE(pTextNd
->GetNum(nullptr), "<SwSetExpFieldType::SetChapter(..)> - text node with numbering rule, but without number. This is a serious defect");
663 void SwSetExpFieldType::QueryValue( uno::Any
& rAny
, sal_uInt16 nWhichId
) const
667 case FIELD_PROP_SUBTYPE
:
669 sal_Int16 nRet
= lcl_SubTypeToAPI(GetType());
673 case FIELD_PROP_PAR2
:
674 rAny
<<= GetDelimiter();
676 case FIELD_PROP_SHORT1
:
678 sal_Int8 nRet
= m_nLevel
< MAXLEVEL
? m_nLevel
: -1;
687 void SwSetExpFieldType::PutValue( const uno::Any
& rAny
, sal_uInt16 nWhichId
)
691 case FIELD_PROP_SUBTYPE
:
693 sal_Int32 nSet
= lcl_APIToSubType(rAny
);
695 SetType(o3tl::narrowing
<sal_uInt16
>(nSet
));
698 case FIELD_PROP_PAR2
:
702 if( !sTmp
.isEmpty() )
703 SetDelimiter( sTmp
);
705 SetDelimiter( u
" "_ustr
);
708 case FIELD_PROP_SHORT1
:
712 if(nLvl
< 0 || nLvl
>= MAXLEVEL
)
713 SetOutlineLvl(UCHAR_MAX
);
723 bool SwSeqFieldList::InsertSort( SeqFieldLstElem aNew
)
725 OUStringBuffer
aBuf(aNew
.sDlgEntry
);
726 const sal_Int32 nLen
= aBuf
.getLength();
727 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
734 aNew
.sDlgEntry
= aBuf
.makeStringAndClear();
737 bool bRet
= SeekEntry( aNew
, &nPos
);
739 maData
.insert( maData
.begin() + nPos
, aNew
);
743 bool SwSeqFieldList::SeekEntry( const SeqFieldLstElem
& rNew
, size_t* pP
) const
745 size_t nO
= maData
.size();
749 CollatorWrapper
& rCaseColl
= ::GetAppCaseCollator(),
750 & rColl
= ::GetAppCollator();
751 const CharClass
& rCC
= GetAppCharClass();
753 //#59900# Sorting should sort number correctly (e.g. "10" after "9" not after "1")
754 const OUString rTmp2
= rNew
.sDlgEntry
;
755 sal_Int32 nFndPos2
= 0;
756 const OUString
sNum2( rTmp2
.getToken( 0, ' ', nFndPos2
));
757 bool bIsNum2IsNumeric
= CharClass::isAsciiNumeric( sNum2
);
758 sal_Int32 nNum2
= bIsNum2IsNumeric
? sNum2
.toInt32() : 0;
763 const size_t nM
= nU
+ ( nO
- nU
) / 2;
765 //#59900# Sorting should sort number correctly (e.g. "10" after "9" not after "1")
766 const OUString rTmp1
= maData
[nM
].sDlgEntry
;
767 sal_Int32 nFndPos1
= 0;
768 const OUString
sNum1( rTmp1
.getToken( 0, ' ', nFndPos1
));
771 if( bIsNum2IsNumeric
&& rCC
.isNumeric( sNum1
) )
773 sal_Int32 nNum1
= sNum1
.toInt32();
774 nCmp
= nNum2
- nNum1
;
777 OUString aTmp1
= nFndPos1
!= -1 ? rTmp1
.copy(nFndPos1
) : OUString();
778 OUString aTmp2
= nFndPos2
!= -1 ? rTmp2
.copy(nFndPos2
) : OUString();
779 nCmp
= rCaseColl
.compareString(aTmp2
, aTmp1
);
783 nCmp
= rColl
.compareString( rTmp2
, rTmp1
);
802 SwSetExpField::SwSetExpField(SwSetExpFieldType
* pTyp
, const OUString
& rFormel
,
804 : SwFormulaField( pTyp
, nFormat
, 0.0 )
805 , m_fValueRLHidden(0.0)
806 , mnSeqNo( USHRT_MAX
)
808 , mpFormatField(nullptr)
813 if( IsSequenceField() )
815 SwValueField::SetValue(1.0);
816 m_fValueRLHidden
= 1.0;
817 if( rFormel
.isEmpty() )
819 SetFormula(pTyp
->GetName() + "+1");
824 void SwSetExpField::SetFormatField(SwFormatField
& rFormatField
)
826 mpFormatField
= &rFormatField
;
829 OUString
SwSetExpField::ExpandImpl(SwRootFrame
const*const pLayout
) const
831 if (mnSubType
& nsSwExtendedSubType::SUB_CMD
)
832 { // we need the CommandString
833 return GetTyp()->GetName() + " = " + GetFormula();
835 if(!(mnSubType
& nsSwExtendedSubType::SUB_INVISIBLE
))
836 { // value is visible
837 return (pLayout
&& pLayout
->IsHideRedlines()) ? msExpandRLHidden
: msExpand
;
842 /// @return the field name
843 OUString
SwSetExpField::GetFieldName() const
845 SwFieldTypesEnum
const nStrType( (IsSequenceField())
846 ? SwFieldTypesEnum::Sequence
848 ? SwFieldTypesEnum::SetInput
849 : SwFieldTypesEnum::Set
);
852 SwFieldType::GetTypeStr( nStrType
)
854 + GetTyp()->GetName() );
856 // Sequence: without formula
857 if (SwFieldTypesEnum::Sequence
!= nStrType
)
859 aStr
+= " = " + GetFormula();
864 std::unique_ptr
<SwField
> SwSetExpField::Copy() const
866 std::unique_ptr
<SwSetExpField
> pTmp(new SwSetExpField(static_cast<SwSetExpFieldType
*>(GetTyp()),
867 GetFormula(), GetFormat()));
868 pTmp
->SwValueField::SetValue(GetValue());
869 pTmp
->m_fValueRLHidden
= m_fValueRLHidden
;
870 pTmp
->msExpand
= msExpand
;
871 pTmp
->msExpandRLHidden
= msExpandRLHidden
;
872 pTmp
->SetAutomaticLanguage(IsAutomaticLanguage());
873 pTmp
->SetLanguage(GetLanguage());
874 pTmp
->maPText
= maPText
;
875 pTmp
->mbInput
= mbInput
;
876 pTmp
->mnSeqNo
= mnSeqNo
;
877 pTmp
->SetSubType(GetSubType());
879 return std::unique_ptr
<SwField
>(pTmp
.release());
882 void SwSetExpField::SetSubType(sal_uInt16 nSub
)
884 assert((nSub
& 0xff) != (nsSwGetSetExpType::GSE_STRING
|nsSwGetSetExpType::GSE_EXPR
) && "SubType is illegal!");
885 static_cast<SwSetExpFieldType
*>(GetTyp())->SetType(nSub
& 0xff);
886 mnSubType
= nSub
& 0xff00;
889 sal_uInt16
SwSetExpField::GetSubType() const
891 return static_cast<SwSetExpFieldType
*>(GetTyp())->GetType() | mnSubType
;
894 void SwSetExpField::SetValue( const double& rAny
)
896 SwValueField::SetValue(rAny
);
898 if( IsSequenceField() )
899 msExpand
= FormatNumber( GetValue(), static_cast<SvxNumType
>(GetFormat()), GetLanguage() );
901 msExpand
= static_cast<SwValueFieldType
*>(GetTyp())->ExpandValue( rAny
,
902 GetFormat(), GetLanguage());
905 void SwSetExpField::SetValue(const double& rValue
, SwRootFrame
const*const pLayout
)
907 if (!pLayout
|| !pLayout
->IsHideRedlines())
911 if (pLayout
&& !pLayout
->IsHideRedlines())
914 m_fValueRLHidden
= rValue
;
915 if (IsSequenceField())
917 msExpandRLHidden
= FormatNumber(rValue
, static_cast<SvxNumType
>(GetFormat()), GetLanguage());
921 msExpandRLHidden
= static_cast<SwValueFieldType
*>(GetTyp())->ExpandValue(
922 rValue
, GetFormat(), GetLanguage());
926 double SwSetExpField::GetValue(SwRootFrame
const* pLayout
) const
928 return (pLayout
&& pLayout
->IsHideRedlines()) ? m_fValueRLHidden
: GetValue();
931 void SwGetExpField::SetValue( const double& rAny
)
933 SwValueField::SetValue(rAny
);
934 m_sExpand
= static_cast<SwValueFieldType
*>(GetTyp())->ExpandValue( rAny
, GetFormat(),
938 void SwGetExpField::SetValue(const double& rValue
, SwRootFrame
const*const pLayout
)
940 if (!pLayout
|| !pLayout
->IsHideRedlines())
944 if (!pLayout
|| pLayout
->IsHideRedlines())
946 m_fValueRLHidden
= rValue
;
947 m_sExpandRLHidden
= static_cast<SwValueFieldType
*>(GetTyp())->ExpandValue(
948 rValue
, GetFormat(), GetLanguage());
952 double SwGetExpField::GetValue(SwRootFrame
const* pLayout
) const
954 return (pLayout
&& pLayout
->IsHideRedlines()) ? m_fValueRLHidden
: GetValue();
957 /** Find the index of the reference text following the current field
961 * @param nHint search starting position after the current field (or 0 if default)
964 sal_Int32
SwGetExpField::GetReferenceTextPos( const SwFormatField
& rFormat
, SwDoc
& rDoc
, sal_Int32 nHint
)
967 const SwTextField
* pTextField
= rFormat
.GetTextField();
968 const SwTextNode
& rTextNode
= pTextField
->GetTextNode();
970 sal_Int32 nRet
= nHint
? nHint
: pTextField
->GetStart() + 1;
971 OUString sNodeText
= rTextNode
.GetText();
973 if(nRet
<sNodeText
.getLength())
975 sNodeText
= sNodeText
.copy(nRet
);
977 // now check if sNodeText starts with a non-alphanumeric character plus blanks
978 sal_uInt16 nSrcpt
= g_pBreakIt
->GetRealScriptOfText( sNodeText
, 0 );
980 static const WhichRangesContainer
nIds(svl::Items
<
981 RES_CHRATR_FONT
, RES_CHRATR_FONT
,
982 RES_CHRATR_LANGUAGE
, RES_CHRATR_LANGUAGE
,
983 RES_CHRATR_CJK_FONT
, RES_CHRATR_CJK_FONT
,
984 RES_CHRATR_CJK_LANGUAGE
, RES_CHRATR_CJK_LANGUAGE
,
985 RES_CHRATR_CTL_FONT
, RES_CHRATR_CTL_FONT
,
986 RES_CHRATR_CTL_LANGUAGE
, RES_CHRATR_CTL_LANGUAGE
988 SwAttrSet
aSet(rDoc
.GetAttrPool(), nIds
);
989 rTextNode
.GetParaAttr(aSet
, nRet
, nRet
+1);
991 TypedWhichId
<SvxFontItem
> nFontWhich
= GetWhichOfScript( RES_CHRATR_FONT
, nSrcpt
);
992 if( RTL_TEXTENCODING_SYMBOL
!= aSet
.Get( nFontWhich
).GetCharSet() )
994 TypedWhichId
<SvxLanguageItem
> nLangWhich
= GetWhichOfScript( RES_CHRATR_LANGUAGE
, nSrcpt
) ;
995 LanguageType eLang
= aSet
.Get(nLangWhich
).GetLanguage();
996 CharClass
aCC(( LanguageTag(eLang
) ));
997 sal_Unicode c0
= sNodeText
[0];
998 bool bIsAlphaNum
= aCC
.isAlphaNumeric( sNodeText
, 0 );
1000 (c0
== ' ' || c0
== '\t'))
1004 const sal_Int32 nLen
= sNodeText
.getLength();
1005 for (sal_Int32 i
= 1;
1006 i
<nLen
&& (sNodeText
[i
]==' ' || sNodeText
[i
]=='\t');
1016 OUString
SwSetExpField::GetPar1() const
1018 return static_cast<const SwSetExpFieldType
*>(GetTyp())->GetName();
1021 OUString
SwSetExpField::GetPar2() const
1023 sal_uInt16 nType
= static_cast<SwSetExpFieldType
*>(GetTyp())->GetType();
1025 if (nType
& nsSwGetSetExpType::GSE_STRING
)
1026 return GetFormula();
1027 return GetExpandedFormula();
1030 void SwSetExpField::SetPar2(const OUString
& rStr
)
1032 sal_uInt16 nType
= static_cast<SwSetExpFieldType
*>(GetTyp())->GetType();
1034 if( !(nType
& nsSwGetSetExpType::GSE_SEQ
) || !rStr
.isEmpty() )
1036 if (nType
& nsSwGetSetExpType::GSE_STRING
)
1039 SetExpandedFormula(rStr
);
1043 bool SwSetExpField::PutValue( const uno::Any
& rAny
, sal_uInt16 nWhichId
)
1045 sal_Int32 nTmp32
= 0;
1046 sal_Int16 nTmp16
= 0;
1049 case FIELD_PROP_BOOL2
:
1050 if(*o3tl::doAccess
<bool>(rAny
))
1051 mnSubType
&= ~nsSwExtendedSubType::SUB_INVISIBLE
;
1053 mnSubType
|= nsSwExtendedSubType::SUB_INVISIBLE
;
1055 case FIELD_PROP_FORMAT
:
1059 case FIELD_PROP_USHORT2
:
1062 if(nTmp16
<= css::style::NumberingType::NUMBER_NONE
)
1065 //exception(wrong_value)
1070 case FIELD_PROP_USHORT1
:
1074 case FIELD_PROP_PAR1
:
1078 SetPar1( SwStyleNameMapper::GetUIName( sTmp
, SwGetPoolIdFromName::TxtColl
) );
1081 case FIELD_PROP_PAR2
:
1085 //I18N - if the formula contains only "TypeName+1"
1086 //and it's one of the initially created sequence fields
1087 //then the localized names has to be replaced by a programmatic name
1088 OUString sMyFormula
= SwXFieldMaster::LocalizeFormula(*this, uTmp
, false);
1089 SetFormula( sMyFormula
);
1092 case FIELD_PROP_DOUBLE
:
1097 m_fValueRLHidden
= fVal
;
1100 case FIELD_PROP_SUBTYPE
:
1101 nTmp32
= lcl_APIToSubType(rAny
);
1102 if (0 <= nTmp32
&& nTmp32
!= (GetSubType() & 0xff))
1104 auto const subType(o3tl::narrowing
<sal_uInt16
>((GetSubType() & 0xff00) | nTmp32
));
1105 if (((nTmp32
& nsSwGetSetExpType::GSE_STRING
) != (GetSubType() & nsSwGetSetExpType::GSE_STRING
))
1108 SwXTextField::TransmuteLeadToInputField(*this, &subType
);
1112 SetSubType(subType
);
1116 case FIELD_PROP_PAR3
:
1119 case FIELD_PROP_BOOL3
:
1120 if(*o3tl::doAccess
<bool>(rAny
))
1121 mnSubType
|= nsSwExtendedSubType::SUB_CMD
;
1123 mnSubType
&= (~nsSwExtendedSubType::SUB_CMD
);
1125 case FIELD_PROP_BOOL1
:
1127 bool newInput(*o3tl::doAccess
<bool>(rAny
));
1128 if (newInput
!= GetInputFlag())
1130 if (static_cast<SwSetExpFieldType
*>(GetTyp())->GetType()
1131 & nsSwGetSetExpType::GSE_STRING
)
1133 SwXTextField::TransmuteLeadToInputField(*this, nullptr);
1137 SetInputFlag(newInput
);
1142 case FIELD_PROP_PAR4
:
1146 ChgExpStr(sTmp
, nullptr);
1150 return SwField::PutValue(rAny
, nWhichId
);
1155 bool SwSetExpField::QueryValue( uno::Any
& rAny
, sal_uInt16 nWhichId
) const
1159 case FIELD_PROP_BOOL2
:
1160 rAny
<<= 0 == (mnSubType
& nsSwExtendedSubType::SUB_INVISIBLE
);
1162 case FIELD_PROP_FORMAT
:
1163 rAny
<<= static_cast<sal_Int32
>(GetFormat());
1165 case FIELD_PROP_USHORT2
:
1166 rAny
<<= static_cast<sal_Int16
>(GetFormat());
1168 case FIELD_PROP_USHORT1
:
1169 rAny
<<= static_cast<sal_Int16
>(mnSeqNo
);
1171 case FIELD_PROP_PAR1
:
1172 rAny
<<= SwStyleNameMapper::GetProgName(GetPar1(), SwGetPoolIdFromName::TxtColl
);
1174 case FIELD_PROP_PAR2
:
1176 //I18N - if the formula contains only "TypeName+1"
1177 //and it's one of the initially created sequence fields
1178 //then the localized names has to be replaced by a programmatic name
1179 OUString sMyFormula
= SwXFieldMaster::LocalizeFormula(*this, GetFormula(), true);
1180 rAny
<<= sMyFormula
;
1183 case FIELD_PROP_DOUBLE
:
1184 rAny
<<= GetValue();
1186 case FIELD_PROP_SUBTYPE
:
1188 sal_Int16 nRet
= lcl_SubTypeToAPI(GetSubType() & 0xff);
1192 case FIELD_PROP_PAR3
:
1195 case FIELD_PROP_BOOL3
:
1196 rAny
<<= 0 != (mnSubType
& nsSwExtendedSubType::SUB_CMD
);
1198 case FIELD_PROP_BOOL1
:
1199 rAny
<<= GetInputFlag();
1201 case FIELD_PROP_PAR4
:
1202 rAny
<<= GetExpStr(nullptr);
1205 return SwField::QueryValue(rAny
, nWhichId
);
1210 SwInputFieldType::SwInputFieldType( SwDoc
* pD
)
1211 : SwFieldType( SwFieldIds::Input
)
1216 std::unique_ptr
<SwFieldType
> SwInputFieldType::Copy() const
1218 return std::make_unique
<SwInputFieldType
>( mpDoc
);
1221 SwInputField::SwInputField( SwInputFieldType
* pFieldType
,
1227 : SwField( pFieldType
, nFormat
, LANGUAGE_SYSTEM
, false )
1228 , maContent(std::move(aContent
))
1229 , maPText(std::move(aPrompt
))
1231 , mbIsFormField( bIsFormField
)
1232 , mpFormatField( nullptr )
1236 SwInputField::~SwInputField()
1240 void SwInputField::SetFormatField( SwFormatField
& rFormatField
)
1242 mpFormatField
= &rFormatField
;
1246 void SwInputField::applyFieldContent( const OUString
& rNewFieldContent
)
1248 if ( (mnSubType
& 0x00ff) == INP_TXT
)
1250 maContent
= rNewFieldContent
;
1252 else if( (mnSubType
& 0x00ff) == INP_USR
)
1254 SwUserFieldType
* pUserTyp
= static_cast<SwUserFieldType
*>(
1255 static_cast<SwInputFieldType
*>(GetTyp())->GetDoc()->getIDocumentFieldsAccess().GetFieldType( SwFieldIds::User
, getContent(), false ) );
1258 pUserTyp
->SetContent( rNewFieldContent
);
1259 if (!pUserTyp
->IsModifyLocked())
1261 // trigger update of the corresponding User Fields and other
1262 // related Input Fields
1263 bool bUnlock(false);
1264 if (GetFormatField() != nullptr)
1266 SwTextInputField
*const pTextInputField
=
1267 dynamic_cast<SwTextInputField
*>(GetFormatField()->GetTextField());
1268 if (pTextInputField
!= nullptr)
1270 bUnlock
= pTextInputField
->LockNotifyContentChange();
1273 pUserTyp
->UpdateFields();
1276 SwTextInputField
*const pTextInputField
=
1277 dynamic_cast<SwTextInputField
*>(GetFormatField()->GetTextField());
1278 if (pTextInputField
!= nullptr)
1280 pTextInputField
->UnlockNotifyContentChange();
1288 OUString
SwInputField::GetFieldName() const
1290 OUString
aStr(SwField::GetFieldName());
1291 if ((mnSubType
& 0x00ff) == INP_USR
)
1293 aStr
+= GetTyp()->GetName() + " " + getContent();
1298 std::unique_ptr
<SwField
> SwInputField::Copy() const
1300 std::unique_ptr
<SwInputField
> pField(
1302 static_cast<SwInputFieldType
*>(GetTyp()),
1309 pField
->SetHelp( maHelp
);
1310 pField
->SetToolTip( maToolTip
);
1311 pField
->maGrabBag
= maGrabBag
;
1313 pField
->SetAutomaticLanguage(IsAutomaticLanguage());
1314 return std::unique_ptr
<SwField
>(pField
.release());
1317 OUString
SwInputField::ExpandImpl(SwRootFrame
const*const) const
1319 if((mnSubType
& 0x00ff) == INP_TXT
)
1321 return getContent();
1324 if( (mnSubType
& 0x00ff) == INP_USR
)
1326 SwUserFieldType
* pUserTyp
= static_cast<SwUserFieldType
*>(
1327 static_cast<SwInputFieldType
*>(GetTyp())->GetDoc()->getIDocumentFieldsAccess().GetFieldType( SwFieldIds::User
, getContent(), false ) );
1329 return pUserTyp
->GetContent();
1335 bool SwInputField::isFormField() const
1337 return mbIsFormField
1338 || !maHelp
.isEmpty()
1339 || !maToolTip
.isEmpty();
1342 bool SwInputField::QueryValue( uno::Any
& rAny
, sal_uInt16 nWhichId
) const
1346 case FIELD_PROP_PAR1
:
1347 rAny
<<= getContent();
1349 case FIELD_PROP_PAR2
:
1352 case FIELD_PROP_PAR3
:
1355 case FIELD_PROP_PAR4
:
1358 case FIELD_PROP_GRABBAG
:
1361 case FIELD_PROP_TITLE
:
1369 bool SwInputField::PutValue( const uno::Any
& rAny
, sal_uInt16 nWhichId
)
1373 case FIELD_PROP_PAR1
:
1376 case FIELD_PROP_PAR2
:
1379 case FIELD_PROP_PAR3
:
1382 case FIELD_PROP_PAR4
:
1385 case FIELD_PROP_GRABBAG
:
1388 case FIELD_PROP_TITLE
:
1397 void SwInputField::SetPar1(const OUString
& rStr
)
1402 OUString
SwInputField::GetPar1() const
1404 return getContent();
1407 void SwInputField::SetPar2(const OUString
& rStr
)
1412 OUString
SwInputField::GetPar2() const
1417 void SwInputField::SetHelp(const OUString
& rStr
)
1422 const OUString
& SwInputField::GetHelp() const
1427 void SwInputField::SetToolTip(const OUString
& rStr
)
1432 const OUString
& SwInputField::GetToolTip() const
1437 sal_uInt16
SwInputField::GetSubType() const
1442 void SwInputField::SetSubType(sal_uInt16 nSub
)
1447 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */