Clean up uses of Any::getValue() in sw
[LibreOffice.git] / sw / source / core / fields / expfld.cxx
blob68e882af3a517d35a7df46280c99cc9775fab500
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <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>
33 #include <frmfmt.hxx>
34 #include <fmtfld.hxx>
35 #include <txtfld.hxx>
36 #include <fmtanchr.hxx>
37 #include <txtftn.hxx>
38 #include <doc.hxx>
39 #include <IDocumentFieldsAccess.hxx>
40 #include <layfrm.hxx>
41 #include <pagefrm.hxx>
42 #include <cntfrm.hxx>
43 #include <rootfrm.hxx>
44 #include <tabfrm.hxx>
45 #include <flyfrm.hxx>
46 #include <ftnfrm.hxx>
47 #include <rowfrm.hxx>
48 #include <expfld.hxx>
49 #include <usrfld.hxx>
50 #include <ndtxt.hxx>
51 #include <calc.hxx>
52 #include <pam.hxx>
53 #include <docfld.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>
60 #include <calbck.hxx>
62 using namespace ::com::sun::star;
63 using namespace ::com::sun::star::text;
65 static sal_Int16 lcl_SubTypeToAPI(sal_uInt16 nSubType)
67 sal_Int16 nRet = 0;
68 switch(nSubType)
70 case nsSwGetSetExpType::GSE_EXPR:
71 nRet = SetVariableType::VAR; // 0
72 break;
73 case nsSwGetSetExpType::GSE_SEQ:
74 nRet = SetVariableType::SEQUENCE; // 1
75 break;
76 case nsSwGetSetExpType::GSE_FORMULA:
77 nRet = SetVariableType::FORMULA; // 2
78 break;
79 case nsSwGetSetExpType::GSE_STRING:
80 nRet = SetVariableType::STRING; // 3
81 break;
83 return nRet;
86 static sal_Int32 lcl_APIToSubType(const uno::Any& rAny)
88 sal_Int16 nVal = 0;
89 rAny >>= nVal;
90 sal_Int32 nSet = 0;
91 switch(nVal)
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;
97 default:
98 OSL_FAIL("wrong value");
99 nSet = -1;
101 return nSet;
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('.');
110 if (nIndex<0)
112 return rTmpName;
115 OUString sRes = rTmpName.replaceAt(nIndex, 1, OUString(DB_DELIM));
117 if (bWithCommandType)
119 nIndex = sRes.lastIndexOf('.', nIndex);
120 if (nIndex<0)
122 return sRes;
124 sRes = sRes.replaceAt(nIndex, 1, OUString(DB_DELIM));
127 nIndex = sRes.indexOf('.');
128 if (nIndex>=0)
130 sRes = sRes.replaceAt(nIndex, 1, OUString(DB_DELIM));
132 return sRes;
135 SwTextNode* GetFirstTextNode( const SwDoc& rDoc, SwPosition& rPos,
136 const SwContentFrame *pCFrame, Point &rPt )
138 SwTextNode* pTextNode = nullptr;
139 if ( !pCFrame )
141 const SwNodes& rNodes = rDoc.GetNodes();
142 rPos.nNode = *rNodes.GetEndOfContent().StartOfSectionNode();
143 SwContentNode* pCNd;
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 );
156 else
158 pCFrame->GetCursorOfst( &rPos, rPt );
159 pTextNode = rPos.nNode.GetNode().GetTextNode();
161 return pTextNode;
164 const SwTextNode* GetBodyTextNode( const SwDoc& rDoc, SwPosition& rPos,
165 const SwFrame& rFrame )
167 const SwLayoutFrame* pLayout = rFrame.GetUpper();
168 const SwTextNode* pTextNode = nullptr;
170 while( pLayout )
172 if( pLayout->IsFlyFrame() )
174 // get the FlyFormat
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());
184 continue;
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(
196 &rPos.nContent );
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;
202 continue;
204 else
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();
236 else
237 pContentFrame = pPgFrame->FindLastBodyContent();
239 if( pContentFrame )
241 pTextNode = pContentFrame->GetNode()->GetTextNode();
242 rPos.nNode = *pTextNode;
243 const_cast<SwTextNode*>(pTextNode)->MakeEndIndex( &rPos.nContent );
245 else
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 );
253 else
255 pLayout = pLayout->GetUpper();
256 continue;
258 break; // found, so finish loop
260 return pTextNode;
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 ),
284 nSubType(nSub),
285 bLateInitialization( false )
287 SetFormula( rFormel );
290 OUString SwGetExpField::Expand() const
292 if(nSubType & nsSwExtendedSubType::SUB_CMD)
293 return GetFormula();
295 return sExpand;
298 OUString SwGetExpField::GetFieldName() const
300 const sal_uInt16 nType = static_cast<sal_uInt16>(
301 (nsSwGetSetExpType::GSE_FORMULA & nSubType)
302 ? TYP_FORMELFLD
303 : TYP_GETFLD);
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();
320 return pTmp;
323 void SwGetExpField::ChangeExpansion( const SwFrame& rFrame, const SwTextField& rField )
325 if( bIsInBodyText ) // only fields in Footer, Header, FootNote, Flys
326 return;
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.
340 if(!pTextNode)
341 return;
342 // #i82544#
343 if( bLateInitialization )
345 SwFieldType* pSetExpField = rDoc.getIDocumentFieldsAccess().GetFieldType(RES_SETEXPFLD, GetFormula(), false);
346 if( pSetExpField )
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;
359 sal_uInt16 nSize;
360 rDoc.getIDocumentFieldsAccess().FieldsToExpand( ppHashTable, nSize, aEndField );
361 sExpand = LookString( ppHashTable, nSize, GetFormula() );
362 ::DeleteHashTable( ppHashTable, nSize );
364 else
366 // fill calculator with values
367 SwCalc aCalc( rDoc );
368 rDoc.getIDocumentFieldsAccess().FieldsToCalc(aCalc, aEndField);
370 // calculate value
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
381 return GetFormula();
384 void SwGetExpField::SetPar2(const OUString& rStr)
386 SetFormula(rStr);
389 sal_uInt16 SwGetExpField::GetSubType() const
391 return nSubType;
394 void SwGetExpField::SetSubType(sal_uInt16 nType)
396 nSubType = nType;
399 void SwGetExpField::SetLanguage(sal_uInt16 nLng)
401 if (nSubType & nsSwExtendedSubType::SUB_CMD)
402 SwField::SetLanguage(nLng);
403 else
404 SwValueField::SetLanguage(nLng);
407 bool SwGetExpField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
409 switch( nWhichId )
411 case FIELD_PROP_DOUBLE:
412 rAny <<= GetValue();
413 break;
414 case FIELD_PROP_FORMAT:
415 rAny <<= (sal_Int32)GetFormat();
416 break;
417 case FIELD_PROP_USHORT1:
418 rAny <<= (sal_Int16)nSubType;
419 break;
420 case FIELD_PROP_PAR1:
421 rAny <<= GetFormula();
422 break;
423 case FIELD_PROP_SUBTYPE:
425 sal_Int16 nRet = lcl_SubTypeToAPI(GetSubType() & 0xff);
426 rAny <<= nRet;
428 break;
429 case FIELD_PROP_BOOL2:
430 rAny <<= 0 != (nSubType & nsSwExtendedSubType::SUB_CMD);
431 break;
432 case FIELD_PROP_PAR4:
433 rAny <<= GetExpStr();
434 break;
435 default:
436 return SwField::QueryValue(rAny, nWhichId);
438 return true;
441 bool SwGetExpField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
443 sal_Int32 nTmp = 0;
444 switch( nWhichId )
446 case FIELD_PROP_DOUBLE:
447 SwValueField::SetValue(*o3tl::doAccess<double>(rAny));
448 break;
449 case FIELD_PROP_FORMAT:
450 rAny >>= nTmp;
451 SetFormat(nTmp);
452 break;
453 case FIELD_PROP_USHORT1:
454 rAny >>= nTmp;
455 nSubType = static_cast<sal_uInt16>(nTmp);
456 break;
457 case FIELD_PROP_PAR1:
459 OUString sTmp;
460 rAny >>= sTmp;
461 SetFormula(sTmp);
462 break;
464 case FIELD_PROP_SUBTYPE:
465 nTmp = lcl_APIToSubType(rAny);
466 if( nTmp >=0 )
467 SetSubType( static_cast<sal_uInt16>((GetSubType() & 0xff00) | nTmp));
468 break;
469 case FIELD_PROP_BOOL2:
470 if(*o3tl::doAccess<bool>(rAny))
471 nSubType |= nsSwExtendedSubType::SUB_CMD;
472 else
473 nSubType &= (~nsSwExtendedSubType::SUB_CMD);
474 break;
475 case FIELD_PROP_PAR4:
477 OUString sTmp;
478 rAny >>= sTmp;
479 ChgExpStr(sTmp);
480 break;
482 default:
483 return SwField::PutValue(rAny, nWhichId);
485 return true;
488 SwSetExpFieldType::SwSetExpFieldType( SwDoc* pDc, const OUString& rName, sal_uInt16 nTyp )
489 : SwValueFieldType( pDc, RES_SETEXPFLD ),
490 sName( rName ),
491 pOutlChgNd( nullptr ),
492 sDelim( "." ),
493 nType(nTyp), nLevel( UCHAR_MAX ),
494 bDeleted( false )
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;
507 return pNew;
510 OUString SwSetExpFieldType::GetName() const
512 return sName;
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) )
539 return;
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 )
564 break;
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 )
577 if( n != aArr[ n ] )
578 break;
581 rField.SetSeqNumber( n );
584 size_t SwSetExpFieldType::GetSeqFieldList( SwSeqFieldList& rList )
586 rList.Clear();
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 );
609 if( pTextNd )
611 SwNumRule * pRule = pTextNd->GetNumRule();
613 if (pRule)
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() );
626 else
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
636 switch( nWhichId )
638 case FIELD_PROP_SUBTYPE:
640 sal_Int16 nRet = lcl_SubTypeToAPI(GetType());
641 rAny <<= nRet;
643 break;
644 case FIELD_PROP_PAR2:
645 rAny <<= GetDelimiter();
646 break;
647 case FIELD_PROP_SHORT1:
649 sal_Int8 nRet = nLevel < MAXLEVEL? nLevel : -1;
650 rAny <<= nRet;
652 break;
653 default:
654 assert(false);
656 return true;
659 bool SwSetExpFieldType::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
661 switch( nWhichId )
663 case FIELD_PROP_SUBTYPE:
665 sal_Int32 nSet = lcl_APIToSubType(rAny);
666 if(nSet >=0)
667 SetType(static_cast<sal_uInt16>(nSet));
669 break;
670 case FIELD_PROP_PAR2:
672 OUString sTmp;
673 rAny >>= sTmp;
674 if( !sTmp.isEmpty() )
675 SetDelimiter( sTmp );
676 else
677 SetDelimiter( " " );
679 break;
680 case FIELD_PROP_SHORT1:
682 sal_Int8 nLvl = 0;
683 rAny >>= nLvl;
684 if(nLvl < 0 || nLvl >= MAXLEVEL)
685 SetOutlineLvl(UCHAR_MAX);
686 else
687 SetOutlineLvl(nLvl);
689 break;
690 default:
691 assert(false);
693 return true;
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)
702 if (aBuf[i]<' ')
704 aBuf[i]=' ';
707 pNew->sDlgEntry = aBuf.makeStringAndClear();
709 size_t nPos = 0;
710 bool bRet = SeekEntry( *pNew, &nPos );
711 if( !bRet )
712 maData.insert( maData.begin() + nPos, pNew );
713 return bRet;
716 bool SwSeqFieldList::SeekEntry( const SeqFieldLstElem& rNew, size_t* pP ) const
718 size_t nO = maData.size();
719 size_t nU = 0;
720 if( nO > 0 )
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;
733 nO--;
734 while( nU <= nO )
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 ));
742 sal_Int32 nCmp;
744 if( bIsNum2IsNumeric && rCC.isNumeric( sNum1 ) )
746 sal_Int32 nNum1 = sNum1.toInt32();
747 nCmp = nNum2 - nNum1;
748 if( 0 == nCmp )
750 OUString aTmp1 = nFndPos1 != -1 ? rTmp1.copy(nFndPos1) : OUString();
751 OUString aTmp2 = nFndPos2 != -1 ? rTmp2.copy(nFndPos2) : OUString();
752 nCmp = rCaseColl.compareString(aTmp2, aTmp1);
755 else
756 nCmp = rColl.compareString( rTmp2, rTmp1 );
758 if( 0 == nCmp )
760 if( pP ) *pP = nM;
761 return true;
763 else if( 0 < nCmp )
764 nU = nM + 1;
765 else if( nM == 0 )
766 break;
767 else
768 nO = nM - 1;
771 if( pP ) *pP = nU;
772 return false;
775 SwSetExpField::SwSetExpField(SwSetExpFieldType* pTyp, const OUString& rFormel,
776 sal_uLong nFormat)
777 : SwFormulaField( pTyp, nFormat, 0.0 ), nSeqNo( USHRT_MAX ),
778 nSubType(0)
779 , mpFormatField(nullptr)
781 SetFormula(rFormel);
782 // ignore SubType
783 bInput = false;
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
807 return sExpand;
809 return OUString();
812 /// @return the field name
813 OUString SwSetExpField::GetFieldName() const
815 SwFieldTypesEnum const nStrType( (IsSequenceField())
816 ? TYP_SEQFLD
817 : (bInput)
818 ? TYP_SETINPFLD
819 : TYP_SETFLD );
821 OUString aStr(
822 SwFieldType::GetTypeStr( static_cast<sal_uInt16>(nStrType) )
823 + " "
824 + GetTyp()->GetName() );
826 // Sequence: without formula
827 if (TYP_SEQFLD != nStrType)
829 aStr += " = " + GetFormula();
831 return aStr;
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());
847 return pTmp;
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() );
869 else
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(),
878 GetLanguage());
881 /** Find the index of the reference text following the current field
883 * @param rFormat
884 * @param rDoc
885 * @param nHint search starting position after the current field (or 0 if default)
886 * @return
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,
912 0, 0
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 );
926 if( !bIsAlphaNum ||
927 (c0 == ' ' || c0 == '\t'))
929 // ignoring blanks
930 nRet++;
931 const sal_Int32 nLen = sNodeText.getLength();
932 for (sal_Int32 i = 1;
933 i<nLen && (sNodeText[i]==' ' || sNodeText[i]=='\t');
936 ++nRet;
940 return nRet;
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)
953 return GetFormula();
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)
964 SetFormula(rStr);
965 else
966 SetExpandedFormula(rStr);
970 bool SwSetExpField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
972 sal_Int32 nTmp32 = 0;
973 sal_Int16 nTmp16 = 0;
974 switch( nWhichId )
976 case FIELD_PROP_BOOL2:
977 if(*o3tl::doAccess<bool>(rAny))
978 nSubType &= ~nsSwExtendedSubType::SUB_INVISIBLE;
979 else
980 nSubType |= nsSwExtendedSubType::SUB_INVISIBLE;
981 break;
982 case FIELD_PROP_FORMAT:
983 rAny >>= nTmp32;
984 SetFormat(nTmp32);
985 break;
986 case FIELD_PROP_USHORT2:
988 rAny >>= nTmp16;
989 if(nTmp16 <= SVX_NUMBER_NONE )
990 SetFormat(nTmp16);
991 else {
992 //exception(wrong_value)
996 break;
997 case FIELD_PROP_USHORT1:
998 rAny >>= nTmp16;
999 nSeqNo = nTmp16;
1000 break;
1001 case FIELD_PROP_PAR1:
1003 OUString sTmp;
1004 rAny >>= sTmp;
1005 SetPar1( SwStyleNameMapper::GetUIName( sTmp, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL ) );
1007 break;
1008 case FIELD_PROP_PAR2:
1010 OUString uTmp;
1011 rAny >>= uTmp;
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 );
1018 break;
1019 case FIELD_PROP_DOUBLE:
1021 double fVal = 0.0;
1022 rAny >>= fVal;
1023 SetValue(fVal);
1025 break;
1026 case FIELD_PROP_SUBTYPE:
1027 nTmp32 = lcl_APIToSubType(rAny);
1028 if(nTmp32 >= 0)
1029 SetSubType(static_cast<sal_uInt16>((GetSubType() & 0xff00) | nTmp32));
1030 break;
1031 case FIELD_PROP_PAR3:
1032 rAny >>= aPText;
1033 break;
1034 case FIELD_PROP_BOOL3:
1035 if(*o3tl::doAccess<bool>(rAny))
1036 nSubType |= nsSwExtendedSubType::SUB_CMD;
1037 else
1038 nSubType &= (~nsSwExtendedSubType::SUB_CMD);
1039 break;
1040 case FIELD_PROP_BOOL1:
1041 SetInputFlag(*o3tl::doAccess<bool>(rAny));
1042 break;
1043 case FIELD_PROP_PAR4:
1045 OUString sTmp;
1046 rAny >>= sTmp;
1047 ChgExpStr( sTmp );
1049 break;
1050 default:
1051 return SwField::PutValue(rAny, nWhichId);
1053 return true;
1056 bool SwSetExpField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1058 switch( nWhichId )
1060 case FIELD_PROP_BOOL2:
1061 rAny <<= 0 == (nSubType & nsSwExtendedSubType::SUB_INVISIBLE);
1062 break;
1063 case FIELD_PROP_FORMAT:
1064 rAny <<= (sal_Int32)GetFormat();
1065 break;
1066 case FIELD_PROP_USHORT2:
1067 rAny <<= (sal_Int16)GetFormat();
1068 break;
1069 case FIELD_PROP_USHORT1:
1070 rAny <<= (sal_Int16)nSeqNo;
1071 break;
1072 case FIELD_PROP_PAR1:
1073 rAny <<= OUString ( SwStyleNameMapper::GetProgName(GetPar1(), nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL ) );
1074 break;
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 );
1083 break;
1084 case FIELD_PROP_DOUBLE:
1085 rAny <<= (double)GetValue();
1086 break;
1087 case FIELD_PROP_SUBTYPE:
1089 sal_Int16 nRet = 0;
1090 nRet = lcl_SubTypeToAPI(GetSubType() & 0xff);
1091 rAny <<= nRet;
1093 break;
1094 case FIELD_PROP_PAR3:
1095 rAny <<= OUString( aPText );
1096 break;
1097 case FIELD_PROP_BOOL3:
1098 rAny <<= 0 != (nSubType & nsSwExtendedSubType::SUB_CMD);
1099 break;
1100 case FIELD_PROP_BOOL1:
1101 rAny <<= GetInputFlag();
1102 break;
1103 case FIELD_PROP_PAR4:
1104 rAny <<= OUString(GetExpStr());
1105 break;
1106 default:
1107 return SwField::QueryValue(rAny, nWhichId);
1109 return true;
1112 SwInputFieldType::SwInputFieldType( SwDoc* pD )
1113 : SwFieldType( RES_INPUTFLD )
1114 , pDoc( pD )
1118 SwFieldType* SwInputFieldType::Copy() const
1120 SwInputFieldType* pType = new SwInputFieldType( pDoc );
1121 return pType;
1124 SwInputField::SwInputField( SwInputFieldType* pFieldType,
1125 const OUString& rContent,
1126 const OUString& rPrompt,
1127 sal_uInt16 nSub,
1128 sal_uLong nFormat,
1129 bool bIsFormField )
1130 : SwField( pFieldType, nFormat, LANGUAGE_SYSTEM, false )
1131 , aContent(rContent)
1132 , aPText(rPrompt)
1133 , nSubType(nSub)
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 ) );
1183 if( pUserTyp )
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();
1204 return aStr;
1207 SwField* SwInputField::Copy() const
1209 SwInputField* pField =
1210 new SwInputField(
1211 static_cast<SwInputFieldType*>(GetTyp()),
1212 getContent(),
1213 aPText,
1214 GetSubType(),
1215 GetFormat(),
1216 mbIsFormField );
1218 pField->SetHelp( aHelp );
1219 pField->SetToolTip( aToolTip );
1221 pField->SetAutomaticLanguage(IsAutomaticLanguage());
1222 return pField;
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 ) );
1236 if( pUserTyp )
1237 return pUserTyp->GetContent();
1240 return OUString();
1243 bool SwInputField::isFormField() const
1245 return mbIsFormField
1246 || !aHelp.isEmpty()
1247 || !aToolTip.isEmpty();
1250 bool SwInputField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
1252 switch( nWhichId )
1254 case FIELD_PROP_PAR1:
1255 rAny <<= getContent();
1256 break;
1257 case FIELD_PROP_PAR2:
1258 rAny <<= aPText;
1259 break;
1260 case FIELD_PROP_PAR3:
1261 rAny <<= aHelp;
1262 break;
1263 case FIELD_PROP_PAR4:
1264 rAny <<= aToolTip;
1265 break;
1266 default:
1267 assert(false);
1269 return true;
1272 bool SwInputField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
1274 switch( nWhichId )
1276 case FIELD_PROP_PAR1:
1277 rAny >>= aContent;
1278 break;
1279 case FIELD_PROP_PAR2:
1280 rAny >>= aPText;
1281 break;
1282 case FIELD_PROP_PAR3:
1283 rAny >>= aHelp;
1284 break;
1285 case FIELD_PROP_PAR4:
1286 rAny >>= aToolTip;
1287 break;
1288 default:
1289 assert(false);
1291 return true;
1294 /// set condition
1295 void SwInputField::SetPar1(const OUString& rStr)
1297 aContent = rStr;
1300 OUString SwInputField::GetPar1() const
1302 return getContent();
1305 void SwInputField::SetPar2(const OUString& rStr)
1307 aPText = rStr;
1310 OUString SwInputField::GetPar2() const
1312 return aPText;
1315 void SwInputField::SetHelp(const OUString & rStr)
1317 aHelp = rStr;
1320 const OUString& SwInputField::GetHelp() const
1322 return aHelp;
1325 void SwInputField::SetToolTip(const OUString & rStr)
1327 aToolTip = rStr;
1330 const OUString& SwInputField::GetToolTip() const
1332 return aToolTip;
1335 sal_uInt16 SwInputField::GetSubType() const
1337 return nSubType;
1340 void SwInputField::SetSubType(sal_uInt16 nSub)
1342 nSubType = nSub;
1345 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */