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>
22 #include <UndoTable.hxx>
23 #include <hintids.hxx>
24 #include <o3tl/any.hxx>
25 #include <unotools/collatorwrapper.hxx>
26 #include <unotools/charclass.hxx>
27 #include <editeng/unolingu.hxx>
28 #include <svx/pageitem.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>
43 #include <rootfrm.hxx>
54 #include <swcache.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 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
->IsValid() )
152 pTextNode
= const_cast<SwTextNode
*>(static_cast<const SwTextNode
*>(pCFrame
->GetNode()));
153 rPos
.nNode
= *pTextNode
;
154 rPos
.nContent
.Assign( pTextNode
, 0 );
158 pCFrame
->GetCursorOfst( &rPos
, rPt
);
159 pTextNode
= rPos
.nNode
.GetNode().GetTextNode();
164 const SwTextNode
* GetBodyTextNode( const SwDoc
& rDoc
, SwPosition
& rPos
,
165 const SwFrame
& rFrame
)
167 const SwLayoutFrame
* pLayout
= rFrame
.GetUpper();
168 const SwTextNode
* pTextNode
= nullptr;
172 if( pLayout
->IsFlyFrame() )
175 const SwFrameFormat
* pFlyFormat
= static_cast<const SwFlyFrame
*>(pLayout
)->GetFormat();
176 OSL_ENSURE( pFlyFormat
, "Could not find FlyFormat, where is the field?" );
178 const SwFormatAnchor
&rAnchor
= pFlyFormat
->GetAnchor();
180 if( FLY_AT_FLY
== rAnchor
.GetAnchorId() )
182 // the fly needs to be attached somewhere, so ask it
183 pLayout
= static_cast<const SwLayoutFrame
*>(static_cast<const SwFlyFrame
*>(pLayout
)->GetAnchorFrame());
186 else if ((FLY_AT_PARA
== rAnchor
.GetAnchorId()) ||
187 (FLY_AT_CHAR
== rAnchor
.GetAnchorId()) ||
188 (FLY_AS_CHAR
== rAnchor
.GetAnchorId()))
190 OSL_ENSURE( rAnchor
.GetContentAnchor(), "no valid position" );
191 rPos
= *rAnchor
.GetContentAnchor();
192 pTextNode
= rPos
.nNode
.GetNode().GetTextNode();
193 if ( FLY_AT_PARA
== rAnchor
.GetAnchorId() )
195 const_cast<SwTextNode
*>(pTextNode
)->MakeStartIndex(
199 // do not break yet, might be as well in Header/Footer/Footnote/Fly
200 pLayout
= static_cast<const SwFlyFrame
*>(pLayout
)->GetAnchorFrame()
201 ? static_cast<const SwFlyFrame
*>(pLayout
)->GetAnchorFrame()->GetUpper() : nullptr;
206 pLayout
->FindPageFrame()->GetContentPosition(
207 pLayout
->Frame().Pos(), rPos
);
208 pTextNode
= rPos
.nNode
.GetNode().GetTextNode();
211 else if( pLayout
->IsFootnoteFrame() )
213 // get the anchor's node
214 const SwTextFootnote
* pFootnote
= static_cast<const SwFootnoteFrame
*>(pLayout
)->GetAttr();
215 pTextNode
= &pFootnote
->GetTextNode();
216 rPos
.nNode
= *pTextNode
;
217 rPos
.nContent
= pFootnote
->GetStart();
219 else if( pLayout
->IsHeaderFrame() || pLayout
->IsFooterFrame() )
221 const SwContentFrame
* pContentFrame
;
222 const SwPageFrame
* pPgFrame
= pLayout
->FindPageFrame();
223 if( pLayout
->IsHeaderFrame() )
225 const SwTabFrame
*pTab
;
226 if( nullptr != ( pContentFrame
= pPgFrame
->FindFirstBodyContent()) &&
227 nullptr != (pTab
= pContentFrame
->FindTabFrame()) && pTab
->IsFollow() &&
228 pTab
->GetTable()->GetRowsToRepeat() > 0 &&
229 pTab
->IsInHeadline( *pContentFrame
) )
231 // take the next line
232 const SwLayoutFrame
* pRow
= pTab
->GetFirstNonHeadlineRow();
233 pContentFrame
= pRow
->ContainsContent();
237 pContentFrame
= pPgFrame
->FindLastBodyContent();
241 pTextNode
= pContentFrame
->GetNode()->GetTextNode();
242 rPos
.nNode
= *pTextNode
;
243 const_cast<SwTextNode
*>(pTextNode
)->MakeEndIndex( &rPos
.nContent
);
247 Point
aPt( pLayout
->Frame().Pos() );
248 aPt
.Y()++; // get out of the header
249 pContentFrame
= pPgFrame
->GetContentPos( aPt
, false, true );
250 pTextNode
= GetFirstTextNode( rDoc
, rPos
, pContentFrame
, aPt
);
255 pLayout
= pLayout
->GetUpper();
258 break; // found, so finish loop
263 SwGetExpFieldType::SwGetExpFieldType(SwDoc
* pDc
)
264 : SwValueFieldType( pDc
, RES_GETEXPFLD
)
268 SwFieldType
* SwGetExpFieldType::Copy() const
270 return new SwGetExpFieldType(GetDoc());
273 void SwGetExpFieldType::Modify( const SfxPoolItem
*, const SfxPoolItem
* pNew
)
275 if( pNew
&& RES_DOCPOS_UPDATE
== pNew
->Which() )
276 NotifyClients( nullptr, pNew
);
277 // do not expand anything else
280 SwGetExpField::SwGetExpField(SwGetExpFieldType
* pTyp
, const OUString
& rFormel
,
281 sal_uInt16 nSub
, sal_uLong nFormat
)
282 : SwFormulaField( pTyp
, nFormat
, 0.0 ),
283 bIsInBodyText( true ),
285 bLateInitialization( false )
287 SetFormula( rFormel
);
290 OUString
SwGetExpField::Expand() const
292 if(nSubType
& nsSwExtendedSubType::SUB_CMD
)
298 OUString
SwGetExpField::GetFieldName() const
300 const sal_uInt16 nType
= static_cast<sal_uInt16
>(
301 (nsSwGetSetExpType::GSE_FORMULA
& nSubType
)
305 return SwFieldType::GetTypeStr(nType
) + " " + GetFormula();
308 SwField
* SwGetExpField::Copy() const
310 SwGetExpField
*pTmp
= new SwGetExpField(static_cast<SwGetExpFieldType
*>(GetTyp()),
311 GetFormula(), nSubType
, GetFormat());
312 pTmp
->SetLanguage(GetLanguage());
313 pTmp
->SwValueField::SetValue(GetValue());
314 pTmp
->sExpand
= sExpand
;
315 pTmp
->bIsInBodyText
= bIsInBodyText
;
316 pTmp
->SetAutomaticLanguage(IsAutomaticLanguage());
317 if( bLateInitialization
)
318 pTmp
->SetLateInitialization();
323 void SwGetExpField::ChangeExpansion( const SwFrame
& rFrame
, const SwTextField
& rField
)
325 if( bIsInBodyText
) // only fields in Footer, Header, FootNote, Flys
328 OSL_ENSURE( !rFrame
.IsInDocBody(), "Flag incorrect, frame is in DocBody" );
330 // determine document (or is there an easier way?)
331 const SwTextNode
* pTextNode
= &rField
.GetTextNode();
332 SwDoc
& rDoc
= *const_cast<SwDoc
*>(pTextNode
->GetDoc());
334 // create index for determination of the TextNode
335 SwPosition
aPos( SwNodeIndex( rDoc
.GetNodes() ) );
336 pTextNode
= GetBodyTextNode( rDoc
, aPos
, rFrame
);
338 // If no layout exists, ChangeExpansion is called for header and
339 // footer lines via layout formatting without existing TextNode.
343 if( bLateInitialization
)
345 SwFieldType
* pSetExpField
= rDoc
.getIDocumentFieldsAccess().GetFieldType(RES_SETEXPFLD
, GetFormula(), false);
348 bLateInitialization
= false;
349 if( !(GetSubType() & nsSwGetSetExpType::GSE_STRING
) &&
350 static_cast< SwSetExpFieldType
* >(pSetExpField
)->GetType() == nsSwGetSetExpType::GSE_STRING
)
351 SetSubType( nsSwGetSetExpType::GSE_STRING
);
355 SetGetExpField
aEndField( aPos
.nNode
, &rField
, &aPos
.nContent
);
356 if(GetSubType() & nsSwGetSetExpType::GSE_STRING
)
358 SwHash
** ppHashTable
;
360 rDoc
.getIDocumentFieldsAccess().FieldsToExpand( ppHashTable
, nSize
, aEndField
);
361 sExpand
= LookString( ppHashTable
, nSize
, GetFormula() );
362 ::DeleteHashTable( ppHashTable
, nSize
);
366 // fill calculator with values
367 SwCalc
aCalc( rDoc
);
368 rDoc
.getIDocumentFieldsAccess().FieldsToCalc(aCalc
, aEndField
);
371 SetValue(aCalc
.Calculate(GetFormula()).GetDouble());
373 // analyse based on format
374 sExpand
= static_cast<SwValueFieldType
*>(GetTyp())->ExpandValue(
375 GetValue(), GetFormat(), GetLanguage());
379 OUString
SwGetExpField::GetPar2() const
384 void SwGetExpField::SetPar2(const OUString
& rStr
)
389 sal_uInt16
SwGetExpField::GetSubType() const
394 void SwGetExpField::SetSubType(sal_uInt16 nType
)
399 void SwGetExpField::SetLanguage(sal_uInt16 nLng
)
401 if (nSubType
& nsSwExtendedSubType::SUB_CMD
)
402 SwField::SetLanguage(nLng
);
404 SwValueField::SetLanguage(nLng
);
407 bool SwGetExpField::QueryValue( uno::Any
& rAny
, sal_uInt16 nWhichId
) const
411 case FIELD_PROP_DOUBLE
:
414 case FIELD_PROP_FORMAT
:
415 rAny
<<= (sal_Int32
)GetFormat();
417 case FIELD_PROP_USHORT1
:
418 rAny
<<= (sal_Int16
)nSubType
;
420 case FIELD_PROP_PAR1
:
421 rAny
<<= GetFormula();
423 case FIELD_PROP_SUBTYPE
:
425 sal_Int16 nRet
= lcl_SubTypeToAPI(GetSubType() & 0xff);
429 case FIELD_PROP_BOOL2
:
430 rAny
<<= 0 != (nSubType
& nsSwExtendedSubType::SUB_CMD
);
432 case FIELD_PROP_PAR4
:
433 rAny
<<= GetExpStr();
436 return SwField::QueryValue(rAny
, nWhichId
);
441 bool SwGetExpField::PutValue( const uno::Any
& rAny
, sal_uInt16 nWhichId
)
446 case FIELD_PROP_DOUBLE
:
447 SwValueField::SetValue(*o3tl::doAccess
<double>(rAny
));
449 case FIELD_PROP_FORMAT
:
453 case FIELD_PROP_USHORT1
:
455 nSubType
= static_cast<sal_uInt16
>(nTmp
);
457 case FIELD_PROP_PAR1
:
464 case FIELD_PROP_SUBTYPE
:
465 nTmp
= lcl_APIToSubType(rAny
);
467 SetSubType( static_cast<sal_uInt16
>((GetSubType() & 0xff00) | nTmp
));
469 case FIELD_PROP_BOOL2
:
470 if(*o3tl::doAccess
<bool>(rAny
))
471 nSubType
|= nsSwExtendedSubType::SUB_CMD
;
473 nSubType
&= (~nsSwExtendedSubType::SUB_CMD
);
475 case FIELD_PROP_PAR4
:
483 return SwField::PutValue(rAny
, nWhichId
);
488 SwSetExpFieldType::SwSetExpFieldType( SwDoc
* pDc
, const OUString
& rName
, sal_uInt16 nTyp
)
489 : SwValueFieldType( pDc
, RES_SETEXPFLD
),
491 pOutlChgNd( nullptr ),
493 nType(nTyp
), nLevel( UCHAR_MAX
),
496 if( ( nsSwGetSetExpType::GSE_SEQ
| nsSwGetSetExpType::GSE_STRING
) & nType
)
497 EnableFormat(false); // do not use Numberformatter
500 SwFieldType
* SwSetExpFieldType::Copy() const
502 SwSetExpFieldType
* pNew
= new SwSetExpFieldType(GetDoc(), sName
, nType
);
503 pNew
->bDeleted
= bDeleted
;
504 pNew
->sDelim
= sDelim
;
505 pNew
->nLevel
= nLevel
;
510 OUString
SwSetExpFieldType::GetName() const
515 void SwSetExpFieldType::Modify( const SfxPoolItem
*, const SfxPoolItem
* )
517 return; // do not expand further
520 void SwSetExpFieldType::SetSeqFormat(sal_uLong nFormat
)
522 SwIterator
<SwFormatField
,SwFieldType
> aIter(*this);
523 for( SwFormatField
* pFormatField
= aIter
.First(); pFormatField
; pFormatField
= aIter
.Next() )
524 pFormatField
->GetField()->ChangeFormat( nFormat
);
527 sal_uLong
SwSetExpFieldType::GetSeqFormat()
529 if( !HasWriterListeners() )
530 return SVX_NUM_ARABIC
;
532 const SwField
*pField
= SwIterator
<SwFormatField
,SwSetExpFieldType
>(*this).First()->GetField();
533 return pField
->GetFormat();
536 void SwSetExpFieldType::SetSeqRefNo( SwSetExpField
& rField
)
538 if( !HasWriterListeners() || !(nsSwGetSetExpType::GSE_SEQ
& nType
) )
541 std::vector
<sal_uInt16
> aArr
;
543 // check if number is already used and if a new one needs to be created
544 SwIterator
<SwFormatField
,SwFieldType
> aIter( *this );
545 for( SwFormatField
* pF
= aIter
.First(); pF
; pF
= aIter
.Next() )
547 const SwTextNode
* pNd
;
548 if( pF
->GetField() != &rField
&& pF
->GetTextField() &&
549 nullptr != ( pNd
= pF
->GetTextField()->GetpTextNode() ) &&
550 pNd
->GetNodes().IsDocNodes() )
552 InsertSort( aArr
, static_cast<SwSetExpField
*>(pF
->GetField())->GetSeqNumber() );
556 // check first if number already exists
557 sal_uInt16 nNum
= rField
.GetSeqNumber();
558 if( USHRT_MAX
!= nNum
)
560 std::vector
<sal_uInt16
>::size_type n
{0};
562 for( n
= 0; n
< aArr
.size(); ++n
)
563 if( aArr
[ n
] >= nNum
)
566 if( n
== aArr
.size() || aArr
[ n
] > nNum
)
567 return; // no -> use it
570 // flagged all numbers, so determine the right number
571 sal_uInt16 n
= aArr
.size();
572 OSL_ENSURE( n
== aArr
.size(), "Array is too big for using a sal_uInt16 index" );
574 if ( n
> 0 && aArr
[ n
-1 ] != n
-1 )
576 for( n
= 0; n
< aArr
.size(); ++n
)
581 rField
.SetSeqNumber( n
);
584 size_t SwSetExpFieldType::GetSeqFieldList( SwSeqFieldList
& rList
)
588 SwIterator
<SwFormatField
,SwFieldType
> aIter( *this );
589 for( SwFormatField
* pF
= aIter
.First(); pF
; pF
= aIter
.Next() )
591 const SwTextNode
* pNd
;
592 if( pF
->GetTextField() &&
593 nullptr != ( pNd
= pF
->GetTextField()->GetpTextNode() ) &&
594 pNd
->GetNodes().IsDocNodes() )
596 SeqFieldLstElem
* pNew
= new SeqFieldLstElem(
597 pNd
->GetExpandText(),
598 static_cast<SwSetExpField
*>(pF
->GetField())->GetSeqNumber() );
599 rList
.InsertSort( pNew
);
603 return rList
.Count();
606 void SwSetExpFieldType::SetChapter( SwSetExpField
& rField
, const SwNode
& rNd
)
608 const SwTextNode
* pTextNd
= rNd
.FindOutlineNodeOfLevel( nLevel
);
611 SwNumRule
* pRule
= pTextNd
->GetNumRule();
615 // --> OD 2005-11-02 #i51089 - TUNING#
616 if ( pTextNd
->GetNum() )
618 const SwNodeNum
& aNum
= *(pTextNd
->GetNum());
620 // only get the number, without pre-/post-fixstrings
621 OUString
sNumber( pRule
->MakeNumString(aNum
, false ));
623 if( !sNumber
.isEmpty() )
624 rField
.ChgExpStr( sNumber
+ sDelim
+ rField
.GetExpStr() );
628 OSL_FAIL( "<SwSetExpFieldType::SetChapter(..)> - text node with numbering rule, but without number. This is a serious defect" );
634 bool SwSetExpFieldType::QueryValue( uno::Any
& rAny
, sal_uInt16 nWhichId
) const
638 case FIELD_PROP_SUBTYPE
:
640 sal_Int16 nRet
= lcl_SubTypeToAPI(GetType());
644 case FIELD_PROP_PAR2
:
645 rAny
<<= GetDelimiter();
647 case FIELD_PROP_SHORT1
:
649 sal_Int8 nRet
= nLevel
< MAXLEVEL
? nLevel
: -1;
659 bool SwSetExpFieldType::PutValue( const uno::Any
& rAny
, sal_uInt16 nWhichId
)
663 case FIELD_PROP_SUBTYPE
:
665 sal_Int32 nSet
= lcl_APIToSubType(rAny
);
667 SetType(static_cast<sal_uInt16
>(nSet
));
670 case FIELD_PROP_PAR2
:
674 if( !sTmp
.isEmpty() )
675 SetDelimiter( sTmp
);
680 case FIELD_PROP_SHORT1
:
684 if(nLvl
< 0 || nLvl
>= MAXLEVEL
)
685 SetOutlineLvl(UCHAR_MAX
);
696 bool SwSeqFieldList::InsertSort( SeqFieldLstElem
* pNew
)
698 OUStringBuffer
aBuf(pNew
->sDlgEntry
);
699 const sal_Int32 nLen
= aBuf
.getLength();
700 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
707 pNew
->sDlgEntry
= aBuf
.makeStringAndClear();
710 bool bRet
= SeekEntry( *pNew
, &nPos
);
712 maData
.insert( maData
.begin() + nPos
, pNew
);
716 bool SwSeqFieldList::SeekEntry( const SeqFieldLstElem
& rNew
, size_t* pP
) const
718 size_t nO
= maData
.size();
722 CollatorWrapper
& rCaseColl
= ::GetAppCaseCollator(),
723 & rColl
= ::GetAppCollator();
724 const CharClass
& rCC
= GetAppCharClass();
726 //#59900# Sorting should sort number correctly (e.g. "10" after "9" not after "1")
727 const OUString rTmp2
= rNew
.sDlgEntry
;
728 sal_Int32 nFndPos2
= 0;
729 const OUString
sNum2( rTmp2
.getToken( 0, ' ', nFndPos2
));
730 bool bIsNum2IsNumeric
= CharClass::isAsciiNumeric( sNum2
);
731 sal_Int32 nNum2
= bIsNum2IsNumeric
? sNum2
.toInt32() : 0;
736 const size_t nM
= nU
+ ( nO
- nU
) / 2;
738 //#59900# Sorting should sort number correctly (e.g. "10" after "9" not after "1")
739 const OUString rTmp1
= maData
[nM
]->sDlgEntry
;
740 sal_Int32 nFndPos1
= 0;
741 const OUString
sNum1( rTmp1
.getToken( 0, ' ', nFndPos1
));
744 if( bIsNum2IsNumeric
&& rCC
.isNumeric( sNum1
) )
746 sal_Int32 nNum1
= sNum1
.toInt32();
747 nCmp
= nNum2
- nNum1
;
750 OUString aTmp1
= nFndPos1
!= -1 ? rTmp1
.copy(nFndPos1
) : OUString();
751 OUString aTmp2
= nFndPos2
!= -1 ? rTmp2
.copy(nFndPos2
) : OUString();
752 nCmp
= rCaseColl
.compareString(aTmp2
, aTmp1
);
756 nCmp
= rColl
.compareString( rTmp2
, rTmp1
);
775 SwSetExpField::SwSetExpField(SwSetExpFieldType
* pTyp
, const OUString
& rFormel
,
777 : SwFormulaField( pTyp
, nFormat
, 0.0 ), nSeqNo( USHRT_MAX
),
779 , mpFormatField(nullptr)
784 if( IsSequenceField() )
786 SwValueField::SetValue(1.0);
787 if( rFormel
.isEmpty() )
789 SetFormula(pTyp
->GetName() + "+1");
794 void SwSetExpField::SetFormatField(SwFormatField
& rFormatField
)
796 mpFormatField
= &rFormatField
;
799 OUString
SwSetExpField::Expand() const
801 if (nSubType
& nsSwExtendedSubType::SUB_CMD
)
802 { // we need the CommandString
803 return GetTyp()->GetName() + " = " + GetFormula();
805 if(!(nSubType
& nsSwExtendedSubType::SUB_INVISIBLE
))
806 { // value is visible
812 /// @return the field name
813 OUString
SwSetExpField::GetFieldName() const
815 SwFieldTypesEnum
const nStrType( (IsSequenceField())
822 SwFieldType::GetTypeStr( static_cast<sal_uInt16
>(nStrType
) )
824 + GetTyp()->GetName() );
826 // Sequence: without formula
827 if (TYP_SEQFLD
!= nStrType
)
829 aStr
+= " = " + GetFormula();
834 SwField
* SwSetExpField::Copy() const
836 SwSetExpField
*pTmp
= new SwSetExpField(static_cast<SwSetExpFieldType
*>(GetTyp()),
837 GetFormula(), GetFormat());
838 pTmp
->SwValueField::SetValue(GetValue());
839 pTmp
->sExpand
= sExpand
;
840 pTmp
->SetAutomaticLanguage(IsAutomaticLanguage());
841 pTmp
->SetLanguage(GetLanguage());
842 pTmp
->aPText
= aPText
;
843 pTmp
->bInput
= bInput
;
844 pTmp
->nSeqNo
= nSeqNo
;
845 pTmp
->SetSubType(GetSubType());
850 void SwSetExpField::SetSubType(sal_uInt16 nSub
)
852 static_cast<SwSetExpFieldType
*>(GetTyp())->SetType(nSub
& 0xff);
853 nSubType
= nSub
& 0xff00;
855 OSL_ENSURE( (nSub
& 0xff) != 3, "SubType ist illegal!" );
858 sal_uInt16
SwSetExpField::GetSubType() const
860 return static_cast<SwSetExpFieldType
*>(GetTyp())->GetType() | nSubType
;
863 void SwSetExpField::SetValue( const double& rAny
)
865 SwValueField::SetValue(rAny
);
867 if( IsSequenceField() )
868 sExpand
= FormatNumber( GetValue(), GetFormat() );
870 sExpand
= static_cast<SwValueFieldType
*>(GetTyp())->ExpandValue( rAny
,
871 GetFormat(), GetLanguage());
874 void SwGetExpField::SetValue( const double& rAny
)
876 SwValueField::SetValue(rAny
);
877 sExpand
= static_cast<SwValueFieldType
*>(GetTyp())->ExpandValue( rAny
, GetFormat(),
881 /** Find the index of the reference text following the current field
885 * @param nHint search starting position after the current field (or 0 if default)
888 sal_Int32
SwGetExpField::GetReferenceTextPos( const SwFormatField
& rFormat
, SwDoc
& rDoc
, sal_Int32 nHint
)
891 const SwTextField
* pTextField
= rFormat
.GetTextField();
892 const SwTextNode
& rTextNode
= pTextField
->GetTextNode();
894 sal_Int32 nRet
= nHint
? nHint
: pTextField
->GetStart() + 1;
895 OUString sNodeText
= rTextNode
.GetText();
897 if(nRet
<sNodeText
.getLength())
899 sNodeText
= sNodeText
.copy(nRet
);
901 // now check if sNodeText starts with a non-alphanumeric character plus blanks
902 sal_uInt16 nSrcpt
= g_pBreakIt
->GetRealScriptOfText( sNodeText
, 0 );
904 static const sal_uInt16 nIds
[] =
906 RES_CHRATR_LANGUAGE
, RES_CHRATR_LANGUAGE
,
907 RES_CHRATR_FONT
, RES_CHRATR_FONT
,
908 RES_CHRATR_CJK_LANGUAGE
, RES_CHRATR_CJK_LANGUAGE
,
909 RES_CHRATR_CJK_FONT
, RES_CHRATR_CJK_FONT
,
910 RES_CHRATR_CTL_LANGUAGE
, RES_CHRATR_CTL_LANGUAGE
,
911 RES_CHRATR_CTL_FONT
, RES_CHRATR_CTL_FONT
,
914 SwAttrSet
aSet(rDoc
.GetAttrPool(), nIds
);
915 rTextNode
.GetAttr(aSet
, nRet
, nRet
+1);
917 if( RTL_TEXTENCODING_SYMBOL
!= static_cast<const SvxFontItem
&>(aSet
.Get(
918 GetWhichOfScript( RES_CHRATR_FONT
, nSrcpt
)) ).GetCharSet() )
920 LanguageType eLang
= static_cast<const SvxLanguageItem
&>(aSet
.Get(
921 GetWhichOfScript( RES_CHRATR_LANGUAGE
, nSrcpt
)) ).GetLanguage();
922 LanguageTag
aLanguageTag( eLang
);
923 CharClass
aCC( aLanguageTag
);
924 sal_Unicode c0
= sNodeText
[0];
925 bool bIsAlphaNum
= aCC
.isAlphaNumeric( sNodeText
, 0 );
927 (c0
== ' ' || c0
== '\t'))
931 const sal_Int32 nLen
= sNodeText
.getLength();
932 for (sal_Int32 i
= 1;
933 i
<nLen
&& (sNodeText
[i
]==' ' || sNodeText
[i
]=='\t');
943 OUString
SwSetExpField::GetPar1() const
945 return static_cast<const SwSetExpFieldType
*>(GetTyp())->GetName();
948 OUString
SwSetExpField::GetPar2() const
950 sal_uInt16 nType
= static_cast<SwSetExpFieldType
*>(GetTyp())->GetType();
952 if (nType
& nsSwGetSetExpType::GSE_STRING
)
954 return GetExpandedFormula();
957 void SwSetExpField::SetPar2(const OUString
& rStr
)
959 sal_uInt16 nType
= static_cast<SwSetExpFieldType
*>(GetTyp())->GetType();
961 if( !(nType
& nsSwGetSetExpType::GSE_SEQ
) || !rStr
.isEmpty() )
963 if (nType
& nsSwGetSetExpType::GSE_STRING
)
966 SetExpandedFormula(rStr
);
970 bool SwSetExpField::PutValue( const uno::Any
& rAny
, sal_uInt16 nWhichId
)
972 sal_Int32 nTmp32
= 0;
973 sal_Int16 nTmp16
= 0;
976 case FIELD_PROP_BOOL2
:
977 if(*o3tl::doAccess
<bool>(rAny
))
978 nSubType
&= ~nsSwExtendedSubType::SUB_INVISIBLE
;
980 nSubType
|= nsSwExtendedSubType::SUB_INVISIBLE
;
982 case FIELD_PROP_FORMAT
:
986 case FIELD_PROP_USHORT2
:
989 if(nTmp16
<= SVX_NUMBER_NONE
)
992 //exception(wrong_value)
997 case FIELD_PROP_USHORT1
:
1001 case FIELD_PROP_PAR1
:
1005 SetPar1( SwStyleNameMapper::GetUIName( sTmp
, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL
) );
1008 case FIELD_PROP_PAR2
:
1012 //I18N - if the formula contains only "TypeName+1"
1013 //and it's one of the initially created sequence fields
1014 //then the localized names has to be replaced by a programmatic name
1015 OUString sMyFormula
= SwXFieldMaster::LocalizeFormula(*this, uTmp
, false);
1016 SetFormula( sMyFormula
);
1019 case FIELD_PROP_DOUBLE
:
1026 case FIELD_PROP_SUBTYPE
:
1027 nTmp32
= lcl_APIToSubType(rAny
);
1029 SetSubType(static_cast<sal_uInt16
>((GetSubType() & 0xff00) | nTmp32
));
1031 case FIELD_PROP_PAR3
:
1034 case FIELD_PROP_BOOL3
:
1035 if(*o3tl::doAccess
<bool>(rAny
))
1036 nSubType
|= nsSwExtendedSubType::SUB_CMD
;
1038 nSubType
&= (~nsSwExtendedSubType::SUB_CMD
);
1040 case FIELD_PROP_BOOL1
:
1041 SetInputFlag(*o3tl::doAccess
<bool>(rAny
));
1043 case FIELD_PROP_PAR4
:
1051 return SwField::PutValue(rAny
, nWhichId
);
1056 bool SwSetExpField::QueryValue( uno::Any
& rAny
, sal_uInt16 nWhichId
) const
1060 case FIELD_PROP_BOOL2
:
1061 rAny
<<= 0 == (nSubType
& nsSwExtendedSubType::SUB_INVISIBLE
);
1063 case FIELD_PROP_FORMAT
:
1064 rAny
<<= (sal_Int32
)GetFormat();
1066 case FIELD_PROP_USHORT2
:
1067 rAny
<<= (sal_Int16
)GetFormat();
1069 case FIELD_PROP_USHORT1
:
1070 rAny
<<= (sal_Int16
)nSeqNo
;
1072 case FIELD_PROP_PAR1
:
1073 rAny
<<= OUString ( SwStyleNameMapper::GetProgName(GetPar1(), nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL
) );
1075 case FIELD_PROP_PAR2
:
1077 //I18N - if the formula contains only "TypeName+1"
1078 //and it's one of the initially created sequence fields
1079 //then the localized names has to be replaced by a programmatic name
1080 OUString sMyFormula
= SwXFieldMaster::LocalizeFormula(*this, GetFormula(), true);
1081 rAny
<<= OUString( sMyFormula
);
1084 case FIELD_PROP_DOUBLE
:
1085 rAny
<<= (double)GetValue();
1087 case FIELD_PROP_SUBTYPE
:
1090 nRet
= lcl_SubTypeToAPI(GetSubType() & 0xff);
1094 case FIELD_PROP_PAR3
:
1095 rAny
<<= OUString( aPText
);
1097 case FIELD_PROP_BOOL3
:
1098 rAny
<<= 0 != (nSubType
& nsSwExtendedSubType::SUB_CMD
);
1100 case FIELD_PROP_BOOL1
:
1101 rAny
<<= GetInputFlag();
1103 case FIELD_PROP_PAR4
:
1104 rAny
<<= OUString(GetExpStr());
1107 return SwField::QueryValue(rAny
, nWhichId
);
1112 SwInputFieldType::SwInputFieldType( SwDoc
* pD
)
1113 : SwFieldType( RES_INPUTFLD
)
1118 SwFieldType
* SwInputFieldType::Copy() const
1120 SwInputFieldType
* pType
= new SwInputFieldType( pDoc
);
1124 SwInputField::SwInputField( SwInputFieldType
* pFieldType
,
1125 const OUString
& rContent
,
1126 const OUString
& rPrompt
,
1130 : SwField( pFieldType
, nFormat
, LANGUAGE_SYSTEM
, false )
1131 , aContent(rContent
)
1134 , mbIsFormField( bIsFormField
)
1135 , mpFormatField( nullptr )
1139 SwInputField::~SwInputField()
1143 void SwInputField::SetFormatField( SwFormatField
& rFormatField
)
1145 mpFormatField
= &rFormatField
;
1149 void SwInputField::LockNotifyContentChange()
1151 if ( GetFormatField() != nullptr )
1153 SwTextInputField
* pTextInputField
= dynamic_cast< SwTextInputField
* >(GetFormatField()->GetTextField());
1154 if ( pTextInputField
!= nullptr )
1156 pTextInputField
->LockNotifyContentChange();
1161 void SwInputField::UnlockNotifyContentChange()
1163 if ( GetFormatField() != nullptr )
1165 SwTextInputField
* pTextInputField
= dynamic_cast< SwTextInputField
* >(GetFormatField()->GetTextField());
1166 if ( pTextInputField
!= nullptr )
1168 pTextInputField
->UnlockNotifyContentChange();
1173 void SwInputField::applyFieldContent( const OUString
& rNewFieldContent
)
1175 if ( (nSubType
& 0x00ff) == INP_TXT
)
1177 aContent
= rNewFieldContent
;
1179 else if( (nSubType
& 0x00ff) == INP_USR
)
1181 SwUserFieldType
* pUserTyp
= static_cast<SwUserFieldType
*>(
1182 static_cast<SwInputFieldType
*>(GetTyp())->GetDoc()->getIDocumentFieldsAccess().GetFieldType( RES_USERFLD
, getContent(), false ) );
1185 pUserTyp
->SetContent( rNewFieldContent
);
1187 // trigger update of the corresponding User Fields and other related Input Fields
1189 LockNotifyContentChange();
1190 pUserTyp
->UpdateFields();
1191 UnlockNotifyContentChange();
1197 OUString
SwInputField::GetFieldName() const
1199 OUString
aStr(SwField::GetFieldName());
1200 if ((nSubType
& 0x00ff) == INP_USR
)
1202 aStr
+= GetTyp()->GetName() + " " + getContent();
1207 SwField
* SwInputField::Copy() const
1209 SwInputField
* pField
=
1211 static_cast<SwInputFieldType
*>(GetTyp()),
1218 pField
->SetHelp( aHelp
);
1219 pField
->SetToolTip( aToolTip
);
1221 pField
->SetAutomaticLanguage(IsAutomaticLanguage());
1225 OUString
SwInputField::Expand() const
1227 if((nSubType
& 0x00ff) == INP_TXT
)
1229 return getContent();
1232 if( (nSubType
& 0x00ff) == INP_USR
)
1234 SwUserFieldType
* pUserTyp
= static_cast<SwUserFieldType
*>(
1235 static_cast<SwInputFieldType
*>(GetTyp())->GetDoc()->getIDocumentFieldsAccess().GetFieldType( RES_USERFLD
, getContent(), false ) );
1237 return pUserTyp
->GetContent();
1243 bool SwInputField::isFormField() const
1245 return mbIsFormField
1247 || !aToolTip
.isEmpty();
1250 bool SwInputField::QueryValue( uno::Any
& rAny
, sal_uInt16 nWhichId
) const
1254 case FIELD_PROP_PAR1
:
1255 rAny
<<= getContent();
1257 case FIELD_PROP_PAR2
:
1260 case FIELD_PROP_PAR3
:
1263 case FIELD_PROP_PAR4
:
1272 bool SwInputField::PutValue( const uno::Any
& rAny
, sal_uInt16 nWhichId
)
1276 case FIELD_PROP_PAR1
:
1279 case FIELD_PROP_PAR2
:
1282 case FIELD_PROP_PAR3
:
1285 case FIELD_PROP_PAR4
:
1295 void SwInputField::SetPar1(const OUString
& rStr
)
1300 OUString
SwInputField::GetPar1() const
1302 return getContent();
1305 void SwInputField::SetPar2(const OUString
& rStr
)
1310 OUString
SwInputField::GetPar2() const
1315 void SwInputField::SetHelp(const OUString
& rStr
)
1320 const OUString
& SwInputField::GetHelp() const
1325 void SwInputField::SetToolTip(const OUString
& rStr
)
1330 const OUString
& SwInputField::GetToolTip() const
1335 sal_uInt16
SwInputField::GetSubType() const
1340 void SwInputField::SetSubType(sal_uInt16 nSub
)
1345 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */