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 <unotools/collatorwrapper.hxx>
28 #include <unotools/charclass.hxx>
29 #include <editeng/langitem.hxx>
30 #include <editeng/fontitem.hxx>
31 #include <com/sun/star/text/SetVariableType.hpp>
32 #include <unofield.hxx>
36 #include <fmtanchr.hxx>
39 #include <IDocumentFieldsAccess.hxx>
41 #include <pagefrm.hxx>
44 #include <rootfrm.hxx>
55 #include <swtable.hxx>
56 #include <breakit.hxx>
57 #include <SwStyleNameMapper.hxx>
58 #include <unofldmid.h>
59 #include <numrule.hxx>
62 using namespace ::com::sun::star
;
63 using namespace ::com::sun::star::text
;
65 static sal_Int16
lcl_SubTypeToAPI(sal_uInt16 nSubType
)
70 case nsSwGetSetExpType::GSE_EXPR
:
71 nRet
= SetVariableType::VAR
; // 0
73 case nsSwGetSetExpType::GSE_SEQ
:
74 nRet
= SetVariableType::SEQUENCE
; // 1
76 case nsSwGetSetExpType::GSE_FORMULA
:
77 nRet
= SetVariableType::FORMULA
; // 2
79 case nsSwGetSetExpType::GSE_STRING
:
80 nRet
= SetVariableType::STRING
; // 3
86 static sal_Int32
lcl_APIToSubType(const uno::Any
& rAny
)
93 case SetVariableType::VAR
: nSet
= nsSwGetSetExpType::GSE_EXPR
; break;
94 case SetVariableType::SEQUENCE
: nSet
= nsSwGetSetExpType::GSE_SEQ
; break;
95 case SetVariableType::FORMULA
: nSet
= nsSwGetSetExpType::GSE_FORMULA
; break;
96 case SetVariableType::STRING
: nSet
= nsSwGetSetExpType::GSE_STRING
; break;
98 OSL_FAIL("wrong value");
104 OUString
ReplacePoint( const OUString
& rTmpName
, bool bWithCommandType
)
106 // replace first and last (if bWithCommandType: last two) dot
107 // since table names may contain dots
109 sal_Int32 nIndex
= rTmpName
.lastIndexOf('.');
115 OUString sRes
= rTmpName
.replaceAt(nIndex
, 1, OUString(DB_DELIM
));
117 if (bWithCommandType
)
119 nIndex
= sRes
.lastIndexOf('.', nIndex
);
124 sRes
= sRes
.replaceAt(nIndex
, 1, OUString(DB_DELIM
));
127 nIndex
= sRes
.indexOf('.');
130 sRes
= sRes
.replaceAt(nIndex
, 1, OUString(DB_DELIM
));
135 static SwTextNode
* GetFirstTextNode( const SwDoc
& rDoc
, SwPosition
& rPos
,
136 const SwContentFrame
*pCFrame
, Point
&rPt
)
138 SwTextNode
* pTextNode
= nullptr;
141 const SwNodes
& rNodes
= rDoc
.GetNodes();
142 rPos
.nNode
= *rNodes
.GetEndOfContent().StartOfSectionNode();
144 while( nullptr != (pCNd
= rNodes
.GoNext( &rPos
.nNode
) ) &&
145 nullptr == ( pTextNode
= pCNd
->GetTextNode() ) )
147 OSL_ENSURE( pTextNode
, "Where is the 1. TextNode?" );
148 rPos
.nContent
.Assign( pTextNode
, 0 );
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
.nNode
.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 OSL_ENSURE( 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
.nNode
.GetNode().GetTextNode();
192 if ( RndStdIds::FLY_AT_PARA
== rAnchor
.GetAnchorId() )
194 const_cast<SwTextNode
*>(pTextNode
)->MakeStartIndex(
198 // do not break yet, might be as well in Header/Footer/Footnote/Fly
199 pLayout
= static_cast<const SwFlyFrame
*>(pLayout
)->GetAnchorFrame()
200 ? static_cast<const SwFlyFrame
*>(pLayout
)->GetAnchorFrame()->GetUpper() : nullptr;
205 pLayout
->FindPageFrame()->GetContentPosition(
206 pLayout
->getFrameArea().Pos(), rPos
);
207 pTextNode
= rPos
.nNode
.GetNode().GetTextNode();
210 else if( pLayout
->IsFootnoteFrame() )
212 // get the anchor's node
213 const SwTextFootnote
* pFootnote
= static_cast<const SwFootnoteFrame
*>(pLayout
)->GetAttr();
214 pTextNode
= &pFootnote
->GetTextNode();
215 rPos
.nNode
= *pTextNode
;
216 rPos
.nContent
= pFootnote
->GetStart();
218 else if( pLayout
->IsHeaderFrame() || pLayout
->IsFooterFrame() )
220 const SwContentFrame
* pContentFrame
;
221 const SwPageFrame
* pPgFrame
= pLayout
->FindPageFrame();
222 if( pLayout
->IsHeaderFrame() )
224 const SwTabFrame
*pTab
;
225 if( nullptr != ( pContentFrame
= pPgFrame
->FindFirstBodyContent()) &&
226 nullptr != (pTab
= pContentFrame
->FindTabFrame()) && pTab
->IsFollow() &&
227 pTab
->GetTable()->GetRowsToRepeat() > 0 &&
228 pTab
->IsInHeadline( *pContentFrame
) )
230 // take the next line
231 const SwLayoutFrame
* pRow
= pTab
->GetFirstNonHeadlineRow();
232 pContentFrame
= pRow
->ContainsContent();
236 pContentFrame
= pPgFrame
->FindLastBodyContent();
240 assert(pContentFrame
->IsTextFrame());
241 SwTextFrame
const*const pFrame(static_cast<SwTextFrame
const*>(pContentFrame
));
242 rPos
= pFrame
->MapViewToModelPos(TextFrameIndex(pFrame
->GetText().getLength()));
243 pTextNode
= rPos
.nNode
.GetNode().GetTextNode();
248 Point
aPt( pLayout
->getFrameArea().Pos() );
249 aPt
.AdjustY( 1 ); // get out of the header
250 pContentFrame
= pPgFrame
->GetContentPos( aPt
, false, true );
251 pTextNode
= GetFirstTextNode( rDoc
, rPos
, pContentFrame
, aPt
);
256 pLayout
= pLayout
->GetUpper();
259 break; // found, so finish loop
264 SwGetExpFieldType::SwGetExpFieldType(SwDoc
* pDc
)
265 : SwValueFieldType( pDc
, SwFieldIds::GetExp
)
269 std::unique_ptr
<SwFieldType
> SwGetExpFieldType::Copy() const
271 return std::make_unique
<SwGetExpFieldType
>(GetDoc());
274 void SwGetExpFieldType::Modify( const SfxPoolItem
*, const SfxPoolItem
* pNew
)
276 if( pNew
&& RES_DOCPOS_UPDATE
== pNew
->Which() )
277 NotifyClients( nullptr, pNew
);
278 // do not expand anything else
281 SwGetExpField::SwGetExpField(SwGetExpFieldType
* pTyp
, const OUString
& rFormel
,
282 sal_uInt16 nSub
, sal_uLong nFormat
)
283 : SwFormulaField( pTyp
, nFormat
, 0.0 )
284 , m_fValueRLHidden(0.0)
286 m_bIsInBodyText( true ),
288 m_bLateInitialization( false )
290 SetFormula( rFormel
);
293 void SwGetExpField::ChgExpStr(const OUString
& rExpand
, SwRootFrame
const*const pLayout
)
295 if (!pLayout
|| pLayout
->IsHideRedlines())
297 m_sExpandRLHidden
= rExpand
;
299 if (!pLayout
|| !pLayout
->IsHideRedlines())
305 OUString
SwGetExpField::ExpandImpl(SwRootFrame
const*const pLayout
) const
307 if(m_nSubType
& nsSwExtendedSubType::SUB_CMD
)
310 return (pLayout
&& pLayout
->IsHideRedlines()) ? m_sExpandRLHidden
: m_sExpand
;
313 OUString
SwGetExpField::GetFieldName() const
315 const SwFieldTypesEnum nType
=
316 (nsSwGetSetExpType::GSE_FORMULA
& m_nSubType
)
317 ? SwFieldTypesEnum::Formel
318 : SwFieldTypesEnum::Get
;
320 return SwFieldType::GetTypeStr(nType
) + " " + GetFormula();
323 std::unique_ptr
<SwField
> SwGetExpField::Copy() const
325 std::unique_ptr
<SwGetExpField
> pTmp(new SwGetExpField(static_cast<SwGetExpFieldType
*>(GetTyp()),
326 GetFormula(), m_nSubType
, GetFormat()));
327 pTmp
->SetLanguage(GetLanguage());
328 pTmp
->m_fValueRLHidden
= m_fValueRLHidden
;
329 pTmp
->SwValueField::SetValue(GetValue());
330 pTmp
->m_sExpand
= m_sExpand
;
331 pTmp
->m_sExpandRLHidden
= m_sExpandRLHidden
;
332 pTmp
->m_bIsInBodyText
= m_bIsInBodyText
;
333 pTmp
->SetAutomaticLanguage(IsAutomaticLanguage());
334 if( m_bLateInitialization
)
335 pTmp
->SetLateInitialization();
337 return std::unique_ptr
<SwField
>(pTmp
.release());
340 void SwGetExpField::ChangeExpansion( const SwFrame
& rFrame
, const SwTextField
& rField
)
342 if( m_bIsInBodyText
) // only fields in Footer, Header, FootNote, Flys
345 OSL_ENSURE( !rFrame
.IsInDocBody(), "Flag incorrect, frame is in DocBody" );
347 // determine document (or is there an easier way?)
348 const SwTextNode
* pTextNode
= &rField
.GetTextNode();
349 SwDoc
& rDoc
= const_cast<SwDoc
&>(pTextNode
->GetDoc());
351 // create index for determination of the TextNode
352 SwPosition
aPos( SwNodeIndex( rDoc
.GetNodes() ) );
353 pTextNode
= GetBodyTextNode( rDoc
, aPos
, rFrame
);
355 // If no layout exists, ChangeExpansion is called for header and
356 // footer lines via layout formatting without existing TextNode.
360 if( m_bLateInitialization
)
362 SwFieldType
* pSetExpField
= rDoc
.getIDocumentFieldsAccess().GetFieldType(SwFieldIds::SetExp
, GetFormula(), false);
365 m_bLateInitialization
= false;
366 if( !(GetSubType() & nsSwGetSetExpType::GSE_STRING
) &&
367 static_cast< SwSetExpFieldType
* >(pSetExpField
)->GetType() == nsSwGetSetExpType::GSE_STRING
)
368 SetSubType( nsSwGetSetExpType::GSE_STRING
);
372 SwRootFrame
const& rLayout(*rFrame
.getRootFrame());
373 OUString
& rExpand(rLayout
.IsHideRedlines() ? m_sExpandRLHidden
: m_sExpand
);
374 SetGetExpField
aEndField( aPos
.nNode
, &rField
, &aPos
.nContent
);
375 if(GetSubType() & nsSwGetSetExpType::GSE_STRING
)
377 SwHashTable
<HashStr
> aHashTable(0);
378 rDoc
.getIDocumentFieldsAccess().FieldsToExpand(aHashTable
, aEndField
, rLayout
);
379 rExpand
= LookString( aHashTable
, GetFormula() );
383 // fill calculator with values
384 SwCalc
aCalc( rDoc
);
385 rDoc
.getIDocumentFieldsAccess().FieldsToCalc(aCalc
, aEndField
, &rLayout
);
388 SetValue(aCalc
.Calculate(GetFormula()).GetDouble(), &rLayout
);
390 // analyse based on format
391 rExpand
= static_cast<SwValueFieldType
*>(GetTyp())->ExpandValue(
392 GetValue(&rLayout
), GetFormat(), GetLanguage());
396 OUString
SwGetExpField::GetPar2() const
401 void SwGetExpField::SetPar2(const OUString
& rStr
)
406 sal_uInt16
SwGetExpField::GetSubType() const
411 void SwGetExpField::SetSubType(sal_uInt16 nType
)
416 void SwGetExpField::SetLanguage(LanguageType nLng
)
418 if (m_nSubType
& nsSwExtendedSubType::SUB_CMD
)
419 SwField::SetLanguage(nLng
);
421 SwValueField::SetLanguage(nLng
);
424 bool SwGetExpField::QueryValue( uno::Any
& rAny
, sal_uInt16 nWhichId
) const
428 case FIELD_PROP_DOUBLE
:
431 case FIELD_PROP_FORMAT
:
432 rAny
<<= static_cast<sal_Int32
>(GetFormat());
434 case FIELD_PROP_USHORT1
:
435 rAny
<<= static_cast<sal_Int16
>(m_nSubType
);
437 case FIELD_PROP_PAR1
:
438 rAny
<<= GetFormula();
440 case FIELD_PROP_SUBTYPE
:
442 sal_Int16 nRet
= lcl_SubTypeToAPI(GetSubType() & 0xff);
446 case FIELD_PROP_BOOL2
:
447 rAny
<<= 0 != (m_nSubType
& nsSwExtendedSubType::SUB_CMD
);
449 case FIELD_PROP_PAR4
:
453 return SwField::QueryValue(rAny
, nWhichId
);
458 bool SwGetExpField::PutValue( const uno::Any
& rAny
, sal_uInt16 nWhichId
)
463 case FIELD_PROP_DOUBLE
:
464 SwValueField::SetValue(*o3tl::doAccess
<double>(rAny
));
465 m_fValueRLHidden
= *o3tl::doAccess
<double>(rAny
);
467 case FIELD_PROP_FORMAT
:
471 case FIELD_PROP_USHORT1
:
473 m_nSubType
= static_cast<sal_uInt16
>(nTmp
);
475 case FIELD_PROP_PAR1
:
482 case FIELD_PROP_SUBTYPE
:
483 nTmp
= lcl_APIToSubType(rAny
);
485 SetSubType( static_cast<sal_uInt16
>((GetSubType() & 0xff00) | nTmp
));
487 case FIELD_PROP_BOOL2
:
488 if(*o3tl::doAccess
<bool>(rAny
))
489 m_nSubType
|= nsSwExtendedSubType::SUB_CMD
;
491 m_nSubType
&= (~nsSwExtendedSubType::SUB_CMD
);
493 case FIELD_PROP_PAR4
:
497 ChgExpStr(sTmp
, nullptr);
501 return SwField::PutValue(rAny
, nWhichId
);
506 SwSetExpFieldType::SwSetExpFieldType( SwDoc
* pDc
, const OUString
& rName
, sal_uInt16 nTyp
)
507 : SwValueFieldType( pDc
, SwFieldIds::SetExp
),
510 m_nType(nTyp
), m_nLevel( UCHAR_MAX
),
513 if( ( nsSwGetSetExpType::GSE_SEQ
| nsSwGetSetExpType::GSE_STRING
) & m_nType
)
514 EnableFormat(false); // do not use Numberformatter
517 std::unique_ptr
<SwFieldType
> SwSetExpFieldType::Copy() const
519 std::unique_ptr
<SwSetExpFieldType
> pNew(new SwSetExpFieldType(GetDoc(), m_sName
, m_nType
));
520 pNew
->m_bDeleted
= m_bDeleted
;
521 pNew
->m_sDelim
= m_sDelim
;
522 pNew
->m_nLevel
= m_nLevel
;
527 OUString
SwSetExpFieldType::GetName() const
532 const OUString
& SwSetExpField::GetExpStr(SwRootFrame
const*const pLayout
) const
534 return (pLayout
&& pLayout
->IsHideRedlines()) ? msExpandRLHidden
: msExpand
;
537 void SwSetExpField::ChgExpStr(const OUString
& rExpand
, SwRootFrame
const*const pLayout
)
539 if (!pLayout
|| pLayout
->IsHideRedlines())
541 msExpandRLHidden
= rExpand
;
543 if (!pLayout
|| !pLayout
->IsHideRedlines())
549 void SwSetExpFieldType::Modify( const SfxPoolItem
*, const SfxPoolItem
* )
551 // do not expand further
554 void SwSetExpFieldType::SetSeqFormat(sal_uLong nFormat
)
556 std::vector
<SwFormatField
*> vFields
;
557 GatherFields(vFields
, false);
558 for(auto pFormatField
: vFields
)
559 pFormatField
->GetField()->ChangeFormat(nFormat
);
562 sal_uLong
SwSetExpFieldType::GetSeqFormat() const
564 if( !HasWriterListeners() )
565 return SVX_NUM_ARABIC
;
567 std::vector
<SwFormatField
*> vFields
;
568 GatherFields(vFields
, false);
569 return vFields
.front()->GetField()->GetFormat();
572 void SwSetExpFieldType::SetSeqRefNo( SwSetExpField
& rField
)
574 if( !HasWriterListeners() || !(nsSwGetSetExpType::GSE_SEQ
& m_nType
) )
577 std::vector
<sal_uInt16
> aArr
;
579 // check if number is already used and if a new one needs to be created
580 std::vector
<SwFormatField
*> vFields
;
581 GatherFields(vFields
);
582 for(SwFormatField
* pF
: vFields
)
583 if(pF
->GetField() != &rField
)
584 InsertSort(aArr
, static_cast<SwSetExpField
*>(pF
->GetField())->GetSeqNumber());
586 // check first if number already exists
587 sal_uInt16 nNum
= rField
.GetSeqNumber();
588 if( USHRT_MAX
!= nNum
)
590 std::vector
<sal_uInt16
>::size_type n
{0};
592 for( n
= 0; n
< aArr
.size(); ++n
)
593 if( aArr
[ n
] >= nNum
)
596 if( n
== aArr
.size() || aArr
[ n
] > nNum
)
597 return; // no -> use it
600 // flagged all numbers, so determine the right number
601 std::vector
<sal_uInt16
>::size_type n
= aArr
.size();
602 OSL_ENSURE( n
<= std::numeric_limits
<sal_uInt16
>::max(), "Array is too big for using a sal_uInt16 index" );
604 if ( n
> 0 && aArr
[ n
-1 ] != n
-1 )
606 for( n
= 0; n
< aArr
.size(); ++n
)
611 rField
.SetSeqNumber( n
);
614 size_t SwSetExpFieldType::GetSeqFieldList(SwSeqFieldList
& rList
,
615 SwRootFrame
const*const pLayout
)
619 IDocumentRedlineAccess
const& rIDRA(GetDoc()->getIDocumentRedlineAccess());
621 std::vector
<SwFormatField
*> vFields
;
622 GatherFields(vFields
);
623 for(SwFormatField
* pF
: vFields
)
625 const SwTextNode
* pNd
;
626 if( nullptr != ( pNd
= pF
->GetTextField()->GetpTextNode() )
627 && (!pLayout
|| !pLayout
->IsHideRedlines()
628 || !sw::IsFieldDeletedInModel(rIDRA
, *pF
->GetTextField())))
630 SeqFieldLstElem
aNew(
631 pNd
->GetExpandText(pLayout
),
632 static_cast<SwSetExpField
*>(pF
->GetField())->GetSeqNumber() );
633 rList
.InsertSort( aNew
);
636 return rList
.Count();
639 void SwSetExpFieldType::SetChapter(SwSetExpField
& rField
, const SwNode
& rNd
,
640 SwRootFrame
const*const pLayout
)
642 const SwTextNode
* pTextNd
= rNd
.FindOutlineNodeOfLevel(m_nLevel
, pLayout
);
646 SwNumRule
* pRule
= pTextNd
->GetNumRule();
651 // --> OD 2005-11-02 #i51089 - TUNING#
652 if (SwNodeNum
const*const pNum
= pTextNd
->GetNum(pLayout
))
654 // only get the number, without pre-/post-fixstrings
655 OUString
const sNumber(pRule
->MakeNumString(*pNum
, false));
657 if( !sNumber
.isEmpty() )
658 rField
.ChgExpStr(sNumber
+ m_sDelim
+ rField
.GetExpStr(pLayout
), pLayout
);
662 OSL_ENSURE(pTextNd
->GetNum(nullptr), "<SwSetExpFieldType::SetChapter(..)> - text node with numbering rule, but without number. This is a serious defect");
666 void SwSetExpFieldType::QueryValue( uno::Any
& rAny
, sal_uInt16 nWhichId
) const
670 case FIELD_PROP_SUBTYPE
:
672 sal_Int16 nRet
= lcl_SubTypeToAPI(GetType());
676 case FIELD_PROP_PAR2
:
677 rAny
<<= GetDelimiter();
679 case FIELD_PROP_SHORT1
:
681 sal_Int8 nRet
= m_nLevel
< MAXLEVEL
? m_nLevel
: -1;
690 void SwSetExpFieldType::PutValue( const uno::Any
& rAny
, sal_uInt16 nWhichId
)
694 case FIELD_PROP_SUBTYPE
:
696 sal_Int32 nSet
= lcl_APIToSubType(rAny
);
698 SetType(static_cast<sal_uInt16
>(nSet
));
701 case FIELD_PROP_PAR2
:
705 if( !sTmp
.isEmpty() )
706 SetDelimiter( sTmp
);
711 case FIELD_PROP_SHORT1
:
715 if(nLvl
< 0 || nLvl
>= MAXLEVEL
)
716 SetOutlineLvl(UCHAR_MAX
);
726 bool SwSeqFieldList::InsertSort( SeqFieldLstElem aNew
)
728 OUStringBuffer
aBuf(aNew
.sDlgEntry
);
729 const sal_Int32 nLen
= aBuf
.getLength();
730 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
737 aNew
.sDlgEntry
= aBuf
.makeStringAndClear();
740 bool bRet
= SeekEntry( aNew
, &nPos
);
742 maData
.insert( maData
.begin() + nPos
, aNew
);
746 bool SwSeqFieldList::SeekEntry( const SeqFieldLstElem
& rNew
, size_t* pP
) const
748 size_t nO
= maData
.size();
752 CollatorWrapper
& rCaseColl
= ::GetAppCaseCollator(),
753 & rColl
= ::GetAppCollator();
754 const CharClass
& rCC
= GetAppCharClass();
756 //#59900# Sorting should sort number correctly (e.g. "10" after "9" not after "1")
757 const OUString rTmp2
= rNew
.sDlgEntry
;
758 sal_Int32 nFndPos2
= 0;
759 const OUString
sNum2( rTmp2
.getToken( 0, ' ', nFndPos2
));
760 bool bIsNum2IsNumeric
= CharClass::isAsciiNumeric( sNum2
);
761 sal_Int32 nNum2
= bIsNum2IsNumeric
? sNum2
.toInt32() : 0;
766 const size_t nM
= nU
+ ( nO
- nU
) / 2;
768 //#59900# Sorting should sort number correctly (e.g. "10" after "9" not after "1")
769 const OUString rTmp1
= maData
[nM
].sDlgEntry
;
770 sal_Int32 nFndPos1
= 0;
771 const OUString
sNum1( rTmp1
.getToken( 0, ' ', nFndPos1
));
774 if( bIsNum2IsNumeric
&& rCC
.isNumeric( sNum1
) )
776 sal_Int32 nNum1
= sNum1
.toInt32();
777 nCmp
= nNum2
- nNum1
;
780 OUString aTmp1
= nFndPos1
!= -1 ? rTmp1
.copy(nFndPos1
) : OUString();
781 OUString aTmp2
= nFndPos2
!= -1 ? rTmp2
.copy(nFndPos2
) : OUString();
782 nCmp
= rCaseColl
.compareString(aTmp2
, aTmp1
);
786 nCmp
= rColl
.compareString( rTmp2
, rTmp1
);
805 SwSetExpField::SwSetExpField(SwSetExpFieldType
* pTyp
, const OUString
& rFormel
,
807 : SwFormulaField( pTyp
, nFormat
, 0.0 )
808 , m_fValueRLHidden(0.0)
809 , mnSeqNo( USHRT_MAX
)
811 , mpFormatField(nullptr)
816 if( IsSequenceField() )
818 SwValueField::SetValue(1.0);
819 m_fValueRLHidden
= 1.0;
820 if( rFormel
.isEmpty() )
822 SetFormula(pTyp
->GetName() + "+1");
827 void SwSetExpField::SetFormatField(SwFormatField
& rFormatField
)
829 mpFormatField
= &rFormatField
;
832 OUString
SwSetExpField::ExpandImpl(SwRootFrame
const*const pLayout
) const
834 if (mnSubType
& nsSwExtendedSubType::SUB_CMD
)
835 { // we need the CommandString
836 return GetTyp()->GetName() + " = " + GetFormula();
838 if(!(mnSubType
& nsSwExtendedSubType::SUB_INVISIBLE
))
839 { // value is visible
840 return (pLayout
&& pLayout
->IsHideRedlines()) ? msExpandRLHidden
: msExpand
;
845 /// @return the field name
846 OUString
SwSetExpField::GetFieldName() const
848 SwFieldTypesEnum
const nStrType( (IsSequenceField())
849 ? SwFieldTypesEnum::Sequence
851 ? SwFieldTypesEnum::SetInput
852 : SwFieldTypesEnum::Set
);
855 SwFieldType::GetTypeStr( nStrType
)
857 + GetTyp()->GetName() );
859 // Sequence: without formula
860 if (SwFieldTypesEnum::Sequence
!= nStrType
)
862 aStr
+= " = " + GetFormula();
867 std::unique_ptr
<SwField
> SwSetExpField::Copy() const
869 std::unique_ptr
<SwSetExpField
> pTmp(new SwSetExpField(static_cast<SwSetExpFieldType
*>(GetTyp()),
870 GetFormula(), GetFormat()));
871 pTmp
->SwValueField::SetValue(GetValue());
872 pTmp
->m_fValueRLHidden
= m_fValueRLHidden
;
873 pTmp
->msExpand
= msExpand
;
874 pTmp
->msExpandRLHidden
= msExpandRLHidden
;
875 pTmp
->SetAutomaticLanguage(IsAutomaticLanguage());
876 pTmp
->SetLanguage(GetLanguage());
877 pTmp
->maPText
= maPText
;
878 pTmp
->mbInput
= mbInput
;
879 pTmp
->mnSeqNo
= mnSeqNo
;
880 pTmp
->SetSubType(GetSubType());
882 return std::unique_ptr
<SwField
>(pTmp
.release());
885 void SwSetExpField::SetSubType(sal_uInt16 nSub
)
887 static_cast<SwSetExpFieldType
*>(GetTyp())->SetType(nSub
& 0xff);
888 mnSubType
= nSub
& 0xff00;
890 OSL_ENSURE( (nSub
& 0xff) != 3, "SubType is illegal!" );
893 sal_uInt16
SwSetExpField::GetSubType() const
895 return static_cast<SwSetExpFieldType
*>(GetTyp())->GetType() | mnSubType
;
898 void SwSetExpField::SetValue( const double& rAny
)
900 SwValueField::SetValue(rAny
);
902 if( IsSequenceField() )
903 msExpand
= FormatNumber( GetValue(), static_cast<SvxNumType
>(GetFormat()), GetLanguage() );
905 msExpand
= static_cast<SwValueFieldType
*>(GetTyp())->ExpandValue( rAny
,
906 GetFormat(), GetLanguage());
909 void SwSetExpField::SetValue(const double& rValue
, SwRootFrame
const*const pLayout
)
911 if (!pLayout
|| !pLayout
->IsHideRedlines())
915 if (pLayout
&& !pLayout
->IsHideRedlines())
918 m_fValueRLHidden
= rValue
;
919 if (IsSequenceField())
921 msExpandRLHidden
= FormatNumber(rValue
, static_cast<SvxNumType
>(GetFormat()), GetLanguage());
925 msExpandRLHidden
= static_cast<SwValueFieldType
*>(GetTyp())->ExpandValue(
926 rValue
, GetFormat(), GetLanguage());
930 double SwSetExpField::GetValue(SwRootFrame
const* pLayout
) const
932 return (pLayout
&& pLayout
->IsHideRedlines()) ? m_fValueRLHidden
: GetValue();
935 void SwGetExpField::SetValue( const double& rAny
)
937 SwValueField::SetValue(rAny
);
938 m_sExpand
= static_cast<SwValueFieldType
*>(GetTyp())->ExpandValue( rAny
, GetFormat(),
942 void SwGetExpField::SetValue(const double& rValue
, SwRootFrame
const*const pLayout
)
944 if (!pLayout
|| !pLayout
->IsHideRedlines())
948 if (!pLayout
|| pLayout
->IsHideRedlines())
950 m_fValueRLHidden
= rValue
;
951 m_sExpandRLHidden
= static_cast<SwValueFieldType
*>(GetTyp())->ExpandValue(
952 rValue
, GetFormat(), GetLanguage());
956 double SwGetExpField::GetValue(SwRootFrame
const* pLayout
) const
958 return (pLayout
&& pLayout
->IsHideRedlines()) ? m_fValueRLHidden
: GetValue();
961 /** Find the index of the reference text following the current field
965 * @param nHint search starting position after the current field (or 0 if default)
968 sal_Int32
SwGetExpField::GetReferenceTextPos( const SwFormatField
& rFormat
, SwDoc
& rDoc
, sal_Int32 nHint
)
971 const SwTextField
* pTextField
= rFormat
.GetTextField();
972 const SwTextNode
& rTextNode
= pTextField
->GetTextNode();
974 sal_Int32 nRet
= nHint
? nHint
: pTextField
->GetStart() + 1;
975 OUString sNodeText
= rTextNode
.GetText();
977 if(nRet
<sNodeText
.getLength())
979 sNodeText
= sNodeText
.copy(nRet
);
981 // now check if sNodeText starts with a non-alphanumeric character plus blanks
982 sal_uInt16 nSrcpt
= g_pBreakIt
->GetRealScriptOfText( sNodeText
, 0 );
984 static const sal_uInt16 nIds
[] =
986 RES_CHRATR_LANGUAGE
, RES_CHRATR_LANGUAGE
,
987 RES_CHRATR_FONT
, RES_CHRATR_FONT
,
988 RES_CHRATR_CJK_LANGUAGE
, RES_CHRATR_CJK_LANGUAGE
,
989 RES_CHRATR_CJK_FONT
, RES_CHRATR_CJK_FONT
,
990 RES_CHRATR_CTL_LANGUAGE
, RES_CHRATR_CTL_LANGUAGE
,
991 RES_CHRATR_CTL_FONT
, RES_CHRATR_CTL_FONT
,
994 SwAttrSet
aSet(rDoc
.GetAttrPool(), nIds
);
995 rTextNode
.GetParaAttr(aSet
, nRet
, nRet
+1);
997 if( RTL_TEXTENCODING_SYMBOL
!= static_cast<const SvxFontItem
&>(aSet
.Get(
998 GetWhichOfScript( RES_CHRATR_FONT
, nSrcpt
)) ).GetCharSet() )
1000 LanguageType eLang
= static_cast<const SvxLanguageItem
&>(aSet
.Get(
1001 GetWhichOfScript( RES_CHRATR_LANGUAGE
, nSrcpt
)) ).GetLanguage();
1002 LanguageTag
aLanguageTag( eLang
);
1003 CharClass
aCC( aLanguageTag
);
1004 sal_Unicode c0
= sNodeText
[0];
1005 bool bIsAlphaNum
= aCC
.isAlphaNumeric( sNodeText
, 0 );
1007 (c0
== ' ' || c0
== '\t'))
1011 const sal_Int32 nLen
= sNodeText
.getLength();
1012 for (sal_Int32 i
= 1;
1013 i
<nLen
&& (sNodeText
[i
]==' ' || sNodeText
[i
]=='\t');
1023 OUString
SwSetExpField::GetPar1() const
1025 return static_cast<const SwSetExpFieldType
*>(GetTyp())->GetName();
1028 OUString
SwSetExpField::GetPar2() const
1030 sal_uInt16 nType
= static_cast<SwSetExpFieldType
*>(GetTyp())->GetType();
1032 if (nType
& nsSwGetSetExpType::GSE_STRING
)
1033 return GetFormula();
1034 return GetExpandedFormula();
1037 void SwSetExpField::SetPar2(const OUString
& rStr
)
1039 sal_uInt16 nType
= static_cast<SwSetExpFieldType
*>(GetTyp())->GetType();
1041 if( !(nType
& nsSwGetSetExpType::GSE_SEQ
) || !rStr
.isEmpty() )
1043 if (nType
& nsSwGetSetExpType::GSE_STRING
)
1046 SetExpandedFormula(rStr
);
1050 bool SwSetExpField::PutValue( const uno::Any
& rAny
, sal_uInt16 nWhichId
)
1052 sal_Int32 nTmp32
= 0;
1053 sal_Int16 nTmp16
= 0;
1056 case FIELD_PROP_BOOL2
:
1057 if(*o3tl::doAccess
<bool>(rAny
))
1058 mnSubType
&= ~nsSwExtendedSubType::SUB_INVISIBLE
;
1060 mnSubType
|= nsSwExtendedSubType::SUB_INVISIBLE
;
1062 case FIELD_PROP_FORMAT
:
1066 case FIELD_PROP_USHORT2
:
1069 if(nTmp16
<= css::style::NumberingType::NUMBER_NONE
)
1072 //exception(wrong_value)
1077 case FIELD_PROP_USHORT1
:
1081 case FIELD_PROP_PAR1
:
1085 SetPar1( SwStyleNameMapper::GetUIName( sTmp
, SwGetPoolIdFromName::TxtColl
) );
1088 case FIELD_PROP_PAR2
:
1092 //I18N - if the formula contains only "TypeName+1"
1093 //and it's one of the initially created sequence fields
1094 //then the localized names has to be replaced by a programmatic name
1095 OUString sMyFormula
= SwXFieldMaster::LocalizeFormula(*this, uTmp
, false);
1096 SetFormula( sMyFormula
);
1099 case FIELD_PROP_DOUBLE
:
1104 m_fValueRLHidden
= fVal
;
1107 case FIELD_PROP_SUBTYPE
:
1108 nTmp32
= lcl_APIToSubType(rAny
);
1110 SetSubType(static_cast<sal_uInt16
>((GetSubType() & 0xff00) | nTmp32
));
1112 case FIELD_PROP_PAR3
:
1115 case FIELD_PROP_BOOL3
:
1116 if(*o3tl::doAccess
<bool>(rAny
))
1117 mnSubType
|= nsSwExtendedSubType::SUB_CMD
;
1119 mnSubType
&= (~nsSwExtendedSubType::SUB_CMD
);
1121 case FIELD_PROP_BOOL1
:
1123 bool newInput(*o3tl::doAccess
<bool>(rAny
));
1124 if (newInput
!= GetInputFlag())
1126 if (static_cast<SwSetExpFieldType
*>(GetTyp())->GetType()
1127 & nsSwGetSetExpType::GSE_STRING
)
1129 SwXTextField::TransmuteLeadToInputField(*this);
1133 SetInputFlag(newInput
);
1138 case FIELD_PROP_PAR4
:
1142 ChgExpStr(sTmp
, nullptr);
1146 return SwField::PutValue(rAny
, nWhichId
);
1151 bool SwSetExpField::QueryValue( uno::Any
& rAny
, sal_uInt16 nWhichId
) const
1155 case FIELD_PROP_BOOL2
:
1156 rAny
<<= 0 == (mnSubType
& nsSwExtendedSubType::SUB_INVISIBLE
);
1158 case FIELD_PROP_FORMAT
:
1159 rAny
<<= static_cast<sal_Int32
>(GetFormat());
1161 case FIELD_PROP_USHORT2
:
1162 rAny
<<= static_cast<sal_Int16
>(GetFormat());
1164 case FIELD_PROP_USHORT1
:
1165 rAny
<<= static_cast<sal_Int16
>(mnSeqNo
);
1167 case FIELD_PROP_PAR1
:
1168 rAny
<<= SwStyleNameMapper::GetProgName(GetPar1(), SwGetPoolIdFromName::TxtColl
);
1170 case FIELD_PROP_PAR2
:
1172 //I18N - if the formula contains only "TypeName+1"
1173 //and it's one of the initially created sequence fields
1174 //then the localized names has to be replaced by a programmatic name
1175 OUString sMyFormula
= SwXFieldMaster::LocalizeFormula(*this, GetFormula(), true);
1176 rAny
<<= sMyFormula
;
1179 case FIELD_PROP_DOUBLE
:
1180 rAny
<<= GetValue();
1182 case FIELD_PROP_SUBTYPE
:
1184 sal_Int16 nRet
= lcl_SubTypeToAPI(GetSubType() & 0xff);
1188 case FIELD_PROP_PAR3
:
1191 case FIELD_PROP_BOOL3
:
1192 rAny
<<= 0 != (mnSubType
& nsSwExtendedSubType::SUB_CMD
);
1194 case FIELD_PROP_BOOL1
:
1195 rAny
<<= GetInputFlag();
1197 case FIELD_PROP_PAR4
:
1198 rAny
<<= GetExpStr(nullptr);
1201 return SwField::QueryValue(rAny
, nWhichId
);
1206 SwInputFieldType::SwInputFieldType( SwDoc
* pD
)
1207 : SwFieldType( SwFieldIds::Input
)
1212 std::unique_ptr
<SwFieldType
> SwInputFieldType::Copy() const
1214 return std::make_unique
<SwInputFieldType
>( mpDoc
);
1217 SwInputField::SwInputField( SwInputFieldType
* pFieldType
,
1218 const OUString
& rContent
,
1219 const OUString
& rPrompt
,
1223 : SwField( pFieldType
, nFormat
, LANGUAGE_SYSTEM
, false )
1224 , maContent(rContent
)
1227 , mbIsFormField( bIsFormField
)
1228 , mpFormatField( nullptr )
1232 SwInputField::~SwInputField()
1236 void SwInputField::SetFormatField( SwFormatField
& rFormatField
)
1238 mpFormatField
= &rFormatField
;
1242 void SwInputField::applyFieldContent( const OUString
& rNewFieldContent
)
1244 if ( (mnSubType
& 0x00ff) == INP_TXT
)
1246 maContent
= rNewFieldContent
;
1248 else if( (mnSubType
& 0x00ff) == INP_USR
)
1250 SwUserFieldType
* pUserTyp
= static_cast<SwUserFieldType
*>(
1251 static_cast<SwInputFieldType
*>(GetTyp())->GetDoc()->getIDocumentFieldsAccess().GetFieldType( SwFieldIds::User
, getContent(), false ) );
1254 pUserTyp
->SetContent( rNewFieldContent
);
1255 if (!pUserTyp
->IsModifyLocked())
1257 // trigger update of the corresponding User Fields and other
1258 // related Input Fields
1259 bool bUnlock(false);
1260 if (GetFormatField() != nullptr)
1262 SwTextInputField
*const pTextInputField
=
1263 dynamic_cast<SwTextInputField
*>(GetFormatField()->GetTextField());
1264 if (pTextInputField
!= nullptr)
1266 bUnlock
= pTextInputField
->LockNotifyContentChange();
1269 pUserTyp
->UpdateFields();
1272 SwTextInputField
*const pTextInputField
=
1273 dynamic_cast<SwTextInputField
*>(GetFormatField()->GetTextField());
1274 if (pTextInputField
!= nullptr)
1276 pTextInputField
->UnlockNotifyContentChange();
1284 OUString
SwInputField::GetFieldName() const
1286 OUString
aStr(SwField::GetFieldName());
1287 if ((mnSubType
& 0x00ff) == INP_USR
)
1289 aStr
+= GetTyp()->GetName() + " " + getContent();
1294 std::unique_ptr
<SwField
> SwInputField::Copy() const
1296 std::unique_ptr
<SwInputField
> pField(
1298 static_cast<SwInputFieldType
*>(GetTyp()),
1305 pField
->SetHelp( maHelp
);
1306 pField
->SetToolTip( maToolTip
);
1308 pField
->SetAutomaticLanguage(IsAutomaticLanguage());
1309 return std::unique_ptr
<SwField
>(pField
.release());
1312 OUString
SwInputField::ExpandImpl(SwRootFrame
const*const) const
1314 if((mnSubType
& 0x00ff) == INP_TXT
)
1316 return getContent();
1319 if( (mnSubType
& 0x00ff) == INP_USR
)
1321 SwUserFieldType
* pUserTyp
= static_cast<SwUserFieldType
*>(
1322 static_cast<SwInputFieldType
*>(GetTyp())->GetDoc()->getIDocumentFieldsAccess().GetFieldType( SwFieldIds::User
, getContent(), false ) );
1324 return pUserTyp
->GetContent();
1330 bool SwInputField::isFormField() const
1332 return mbIsFormField
1333 || !maHelp
.isEmpty()
1334 || !maToolTip
.isEmpty();
1337 bool SwInputField::QueryValue( uno::Any
& rAny
, sal_uInt16 nWhichId
) const
1341 case FIELD_PROP_PAR1
:
1342 rAny
<<= getContent();
1344 case FIELD_PROP_PAR2
:
1347 case FIELD_PROP_PAR3
:
1350 case FIELD_PROP_PAR4
:
1359 bool SwInputField::PutValue( const uno::Any
& rAny
, sal_uInt16 nWhichId
)
1363 case FIELD_PROP_PAR1
:
1366 case FIELD_PROP_PAR2
:
1369 case FIELD_PROP_PAR3
:
1372 case FIELD_PROP_PAR4
:
1382 void SwInputField::SetPar1(const OUString
& rStr
)
1387 OUString
SwInputField::GetPar1() const
1389 return getContent();
1392 void SwInputField::SetPar2(const OUString
& rStr
)
1397 OUString
SwInputField::GetPar2() const
1402 void SwInputField::SetHelp(const OUString
& rStr
)
1407 const OUString
& SwInputField::GetHelp() const
1412 void SwInputField::SetToolTip(const OUString
& rStr
)
1417 const OUString
& SwInputField::GetToolTip() const
1422 sal_uInt16
SwInputField::GetSubType() const
1427 void SwInputField::SetSubType(sal_uInt16 nSub
)
1432 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */