diff options
Diffstat (limited to 'sw/source/core/fields/expfld.cxx')
-rw-r--r-- | sw/source/core/fields/expfld.cxx | 1445 |
1 files changed, 1445 insertions, 0 deletions
diff --git a/sw/source/core/fields/expfld.cxx b/sw/source/core/fields/expfld.cxx new file mode 100644 index 000000000..e6d810506 --- /dev/null +++ b/sw/source/core/fields/expfld.cxx @@ -0,0 +1,1445 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <limits> + +#include <UndoTable.hxx> +#include <hintids.hxx> +#include <o3tl/any.hxx> +#include <osl/diagnose.h> +#include <unotools/collatorwrapper.hxx> +#include <unotools/charclass.hxx> +#include <editeng/langitem.hxx> +#include <editeng/fontitem.hxx> +#include <com/sun/star/text/SetVariableType.hpp> +#include <unofield.hxx> +#include <frmfmt.hxx> +#include <fmtfld.hxx> +#include <txtfld.hxx> +#include <fmtanchr.hxx> +#include <txtftn.hxx> +#include <doc.hxx> +#include <IDocumentFieldsAccess.hxx> +#include <layfrm.hxx> +#include <pagefrm.hxx> +#include <cntfrm.hxx> +#include <txtfrm.hxx> +#include <rootfrm.hxx> +#include <tabfrm.hxx> +#include <flyfrm.hxx> +#include <ftnfrm.hxx> +#include <rowfrm.hxx> +#include <expfld.hxx> +#include <usrfld.hxx> +#include <ndtxt.hxx> +#include <calc.hxx> +#include <pam.hxx> +#include <docfld.hxx> +#include <swtable.hxx> +#include <breakit.hxx> +#include <SwStyleNameMapper.hxx> +#include <unofldmid.h> +#include <numrule.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::text; + +static sal_Int16 lcl_SubTypeToAPI(sal_uInt16 nSubType) +{ + sal_Int16 nRet = 0; + switch(nSubType) + { + case nsSwGetSetExpType::GSE_EXPR: + nRet = SetVariableType::VAR; // 0 + break; + case nsSwGetSetExpType::GSE_SEQ: + nRet = SetVariableType::SEQUENCE; // 1 + break; + case nsSwGetSetExpType::GSE_FORMULA: + nRet = SetVariableType::FORMULA; // 2 + break; + case nsSwGetSetExpType::GSE_STRING: + nRet = SetVariableType::STRING; // 3 + break; + } + return nRet; +} + +static sal_Int32 lcl_APIToSubType(const uno::Any& rAny) +{ + sal_Int16 nVal = 0; + rAny >>= nVal; + sal_Int32 nSet = 0; + switch(nVal) + { + case SetVariableType::VAR: nSet = nsSwGetSetExpType::GSE_EXPR; break; + case SetVariableType::SEQUENCE: nSet = nsSwGetSetExpType::GSE_SEQ; break; + case SetVariableType::FORMULA: nSet = nsSwGetSetExpType::GSE_FORMULA; break; + case SetVariableType::STRING: nSet = nsSwGetSetExpType::GSE_STRING; break; + default: + OSL_FAIL("wrong value"); + nSet = -1; + } + return nSet; +} + +OUString ReplacePoint( const OUString& rTmpName, bool bWithCommandType ) +{ + // replace first and last (if bWithCommandType: last two) dot + // since table names may contain dots + + sal_Int32 nIndex = rTmpName.lastIndexOf('.'); + if (nIndex<0) + { + return rTmpName; + } + + OUString sRes = rTmpName.replaceAt(nIndex, 1, rtl::OUStringChar(DB_DELIM)); + + if (bWithCommandType) + { + nIndex = sRes.lastIndexOf('.', nIndex); + if (nIndex<0) + { + return sRes; + } + sRes = sRes.replaceAt(nIndex, 1, rtl::OUStringChar(DB_DELIM)); + } + + nIndex = sRes.indexOf('.'); + if (nIndex>=0) + { + sRes = sRes.replaceAt(nIndex, 1, rtl::OUStringChar(DB_DELIM)); + } + return sRes; +} + +static SwTextNode* GetFirstTextNode( const SwDoc& rDoc, SwPosition& rPos, + const SwContentFrame *pCFrame, Point &rPt ) +{ + SwTextNode* pTextNode = nullptr; + if ( !pCFrame ) + { + const SwNodes& rNodes = rDoc.GetNodes(); + rPos.nNode = *rNodes.GetEndOfContent().StartOfSectionNode(); + SwContentNode* pCNd; + while( nullptr != (pCNd = rNodes.GoNext( &rPos.nNode ) ) && + nullptr == ( pTextNode = pCNd->GetTextNode() ) ) + ; + OSL_ENSURE( pTextNode, "Where is the 1. TextNode?" ); + rPos.nContent.Assign( pTextNode, 0 ); + } + else if ( !pCFrame->isFrameAreaDefinitionValid() ) + { + assert(pCFrame->IsTextFrame()); + rPos = static_cast<SwTextFrame const*>(pCFrame)->MapViewToModelPos(TextFrameIndex(0)); + } + else + { + pCFrame->GetModelPositionForViewPoint( &rPos, rPt ); + pTextNode = rPos.nNode.GetNode().GetTextNode(); + } + return pTextNode; +} + +const SwTextNode* GetBodyTextNode( const SwDoc& rDoc, SwPosition& rPos, + const SwFrame& rFrame ) +{ + const SwLayoutFrame* pLayout = rFrame.GetUpper(); + const SwTextNode* pTextNode = nullptr; + + while( pLayout ) + { + if( pLayout->IsFlyFrame() ) + { + // get the FlyFormat + const SwFrameFormat* pFlyFormat = static_cast<const SwFlyFrame*>(pLayout)->GetFormat(); + OSL_ENSURE( pFlyFormat, "Could not find FlyFormat, where is the field?" ); + + const SwFormatAnchor &rAnchor = pFlyFormat->GetAnchor(); + + if( RndStdIds::FLY_AT_FLY == rAnchor.GetAnchorId() ) + { + // the fly needs to be attached somewhere, so ask it + pLayout = static_cast<const SwLayoutFrame*>(static_cast<const SwFlyFrame*>(pLayout)->GetAnchorFrame()); + continue; + } + else if ((RndStdIds::FLY_AT_PARA == rAnchor.GetAnchorId()) || + (RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId()) || + (RndStdIds::FLY_AS_CHAR == rAnchor.GetAnchorId())) + { + OSL_ENSURE( rAnchor.GetContentAnchor(), "no valid position" ); + rPos = *rAnchor.GetContentAnchor(); + pTextNode = rPos.nNode.GetNode().GetTextNode(); + if ( RndStdIds::FLY_AT_PARA == rAnchor.GetAnchorId() ) + { + const_cast<SwTextNode*>(pTextNode)->MakeStartIndex( + &rPos.nContent ); + } + + // do not break yet, might be as well in Header/Footer/Footnote/Fly + pLayout = static_cast<const SwFlyFrame*>(pLayout)->GetAnchorFrame() + ? static_cast<const SwFlyFrame*>(pLayout)->GetAnchorFrame()->GetUpper() : nullptr; + continue; + } + else + { + pLayout->FindPageFrame()->GetContentPosition( + pLayout->getFrameArea().Pos(), rPos ); + pTextNode = rPos.nNode.GetNode().GetTextNode(); + } + } + else if( pLayout->IsFootnoteFrame() ) + { + // get the anchor's node + const SwTextFootnote* pFootnote = static_cast<const SwFootnoteFrame*>(pLayout)->GetAttr(); + pTextNode = &pFootnote->GetTextNode(); + rPos.nNode = *pTextNode; + rPos.nContent = pFootnote->GetStart(); + } + else if( pLayout->IsHeaderFrame() || pLayout->IsFooterFrame() ) + { + const SwContentFrame* pContentFrame; + const SwPageFrame* pPgFrame = pLayout->FindPageFrame(); + if( pLayout->IsHeaderFrame() ) + { + const SwTabFrame *pTab; + if( nullptr != ( pContentFrame = pPgFrame->FindFirstBodyContent()) && + nullptr != (pTab = pContentFrame->FindTabFrame()) && pTab->IsFollow() && + pTab->GetTable()->GetRowsToRepeat() > 0 && + pTab->IsInHeadline( *pContentFrame ) ) + { + // take the next line + const SwLayoutFrame* pRow = pTab->GetFirstNonHeadlineRow(); + pContentFrame = pRow->ContainsContent(); + } + } + else + pContentFrame = pPgFrame->FindLastBodyContent(); + + if( pContentFrame ) + { + assert(pContentFrame->IsTextFrame()); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(pContentFrame)); + rPos = pFrame->MapViewToModelPos(TextFrameIndex(pFrame->GetText().getLength())); + pTextNode = rPos.nNode.GetNode().GetTextNode(); + assert(pTextNode); + } + else + { + Point aPt( pLayout->getFrameArea().Pos() ); + aPt.AdjustY( 1 ); // get out of the header + pContentFrame = pPgFrame->GetContentPos( aPt, false, true ); + pTextNode = GetFirstTextNode( rDoc, rPos, pContentFrame, aPt ); + } + } + else + { + pLayout = pLayout->GetUpper(); + continue; + } + break; // found, so finish loop + } + return pTextNode; +} + +SwGetExpFieldType::SwGetExpFieldType(SwDoc* pDc) + : SwValueFieldType( pDc, SwFieldIds::GetExp ) +{ +} + +std::unique_ptr<SwFieldType> SwGetExpFieldType::Copy() const +{ + return std::make_unique<SwGetExpFieldType>(GetDoc()); +} + +void SwGetExpFieldType::SwClientNotify(const SwModify&, const SfxHint& rHint) +{ + if (rHint.GetId() != SfxHintId::SwLegacyModify) + return; + auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint); + // do not expand anything else + if(pLegacy->GetWhich() != RES_DOCPOS_UPDATE) + return; + CallSwClientNotify(rHint); +} + +SwGetExpField::SwGetExpField(SwGetExpFieldType* pTyp, const OUString& rFormel, + sal_uInt16 nSub, sal_uLong nFormat) + : SwFormulaField( pTyp, nFormat, 0.0 ) + , m_fValueRLHidden(0.0) + , + m_bIsInBodyText( true ), + m_nSubType(nSub), + m_bLateInitialization( false ) +{ + SetFormula( rFormel ); +} + +void SwGetExpField::ChgExpStr(const OUString& rExpand, SwRootFrame const*const pLayout) +{ + if (!pLayout || pLayout->IsHideRedlines()) + { + m_sExpandRLHidden = rExpand; + } + if (!pLayout || !pLayout->IsHideRedlines()) + { + m_sExpand = rExpand; + } +} + +OUString SwGetExpField::ExpandImpl(SwRootFrame const*const pLayout) const +{ + if(m_nSubType & nsSwExtendedSubType::SUB_CMD) + return GetFormula(); + + return (pLayout && pLayout->IsHideRedlines()) ? m_sExpandRLHidden : m_sExpand; +} + +OUString SwGetExpField::GetFieldName() const +{ + const SwFieldTypesEnum nType = + (nsSwGetSetExpType::GSE_FORMULA & m_nSubType) + ? SwFieldTypesEnum::Formel + : SwFieldTypesEnum::Get; + + return SwFieldType::GetTypeStr(nType) + " " + GetFormula(); +} + +std::unique_ptr<SwField> SwGetExpField::Copy() const +{ + std::unique_ptr<SwGetExpField> pTmp(new SwGetExpField(static_cast<SwGetExpFieldType*>(GetTyp()), + GetFormula(), m_nSubType, GetFormat())); + pTmp->SetLanguage(GetLanguage()); + pTmp->m_fValueRLHidden = m_fValueRLHidden; + pTmp->SwValueField::SetValue(GetValue()); + pTmp->m_sExpand = m_sExpand; + pTmp->m_sExpandRLHidden = m_sExpandRLHidden; + pTmp->m_bIsInBodyText = m_bIsInBodyText; + pTmp->SetAutomaticLanguage(IsAutomaticLanguage()); + if( m_bLateInitialization ) + pTmp->SetLateInitialization(); + + return std::unique_ptr<SwField>(pTmp.release()); +} + +void SwGetExpField::ChangeExpansion( const SwFrame& rFrame, const SwTextField& rField ) +{ + if( m_bIsInBodyText ) // only fields in Footer, Header, FootNote, Flys + return; + + OSL_ENSURE( !rFrame.IsInDocBody(), "Flag incorrect, frame is in DocBody" ); + + // determine document (or is there an easier way?) + const SwTextNode* pTextNode = &rField.GetTextNode(); + SwDoc& rDoc = const_cast<SwDoc&>(pTextNode->GetDoc()); + + // create index for determination of the TextNode + SwPosition aPos( SwNodeIndex( rDoc.GetNodes() ) ); + pTextNode = GetBodyTextNode( rDoc, aPos, rFrame ); + + // If no layout exists, ChangeExpansion is called for header and + // footer lines via layout formatting without existing TextNode. + if(!pTextNode) + return; + // #i82544# + if( m_bLateInitialization ) + { + SwFieldType* pSetExpField = rDoc.getIDocumentFieldsAccess().GetFieldType(SwFieldIds::SetExp, GetFormula(), false); + if( pSetExpField ) + { + m_bLateInitialization = false; + if( !(GetSubType() & nsSwGetSetExpType::GSE_STRING) && + static_cast< SwSetExpFieldType* >(pSetExpField)->GetType() == nsSwGetSetExpType::GSE_STRING ) + SetSubType( nsSwGetSetExpType::GSE_STRING ); + } + } + + SwRootFrame const& rLayout(*rFrame.getRootFrame()); + OUString & rExpand(rLayout.IsHideRedlines() ? m_sExpandRLHidden : m_sExpand); + // here a page number is needed to sort correctly + SetGetExpField aEndField(aPos.nNode, &rField, &aPos.nContent, rFrame.GetPhyPageNum()); + if(GetSubType() & nsSwGetSetExpType::GSE_STRING) + { + SwHashTable<HashStr> aHashTable(0); + rDoc.getIDocumentFieldsAccess().FieldsToExpand(aHashTable, aEndField, rLayout); + rExpand = LookString( aHashTable, GetFormula() ); + } + else + { + // fill calculator with values + SwCalc aCalc( rDoc ); + rDoc.getIDocumentFieldsAccess().FieldsToCalc(aCalc, aEndField, &rLayout); + + // calculate value + SetValue(aCalc.Calculate(GetFormula()).GetDouble(), &rLayout); + + // analyse based on format + rExpand = static_cast<SwValueFieldType*>(GetTyp())->ExpandValue( + GetValue(&rLayout), GetFormat(), GetLanguage()); + } +} + +OUString SwGetExpField::GetPar2() const +{ + return GetFormula(); +} + +void SwGetExpField::SetPar2(const OUString& rStr) +{ + SetFormula(rStr); +} + +sal_uInt16 SwGetExpField::GetSubType() const +{ + return m_nSubType; +} + +void SwGetExpField::SetSubType(sal_uInt16 nType) +{ + m_nSubType = nType; +} + +void SwGetExpField::SetLanguage(LanguageType nLng) +{ + if (m_nSubType & nsSwExtendedSubType::SUB_CMD) + SwField::SetLanguage(nLng); + else + SwValueField::SetLanguage(nLng); +} + +bool SwGetExpField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const +{ + switch( nWhichId ) + { + case FIELD_PROP_DOUBLE: + rAny <<= GetValue(); + break; + case FIELD_PROP_FORMAT: + rAny <<= static_cast<sal_Int32>(GetFormat()); + break; + case FIELD_PROP_USHORT1: + rAny <<= static_cast<sal_Int16>(m_nSubType); + break; + case FIELD_PROP_PAR1: + rAny <<= GetFormula(); + break; + case FIELD_PROP_SUBTYPE: + { + sal_Int16 nRet = lcl_SubTypeToAPI(GetSubType() & 0xff); + rAny <<= nRet; + } + break; + case FIELD_PROP_BOOL2: + rAny <<= 0 != (m_nSubType & nsSwExtendedSubType::SUB_CMD); + break; + case FIELD_PROP_PAR4: + rAny <<= m_sExpand; + break; + default: + return SwField::QueryValue(rAny, nWhichId); + } + return true; +} + +bool SwGetExpField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId ) +{ + sal_Int32 nTmp = 0; + switch( nWhichId ) + { + case FIELD_PROP_DOUBLE: + SwValueField::SetValue(*o3tl::doAccess<double>(rAny)); + m_fValueRLHidden = *o3tl::doAccess<double>(rAny); + break; + case FIELD_PROP_FORMAT: + rAny >>= nTmp; + SetFormat(nTmp); + break; + case FIELD_PROP_USHORT1: + rAny >>= nTmp; + m_nSubType = o3tl::narrowing<sal_uInt16>(nTmp); + break; + case FIELD_PROP_PAR1: + { + OUString sTmp; + rAny >>= sTmp; + SetFormula(sTmp); + break; + } + case FIELD_PROP_SUBTYPE: + nTmp = lcl_APIToSubType(rAny); + if( nTmp >=0 ) + SetSubType( o3tl::narrowing<sal_uInt16>((GetSubType() & 0xff00) | nTmp)); + break; + case FIELD_PROP_BOOL2: + if(*o3tl::doAccess<bool>(rAny)) + m_nSubType |= nsSwExtendedSubType::SUB_CMD; + else + m_nSubType &= (~nsSwExtendedSubType::SUB_CMD); + break; + case FIELD_PROP_PAR4: + { + OUString sTmp; + rAny >>= sTmp; + ChgExpStr(sTmp, nullptr); + break; + } + default: + return SwField::PutValue(rAny, nWhichId); + } + return true; +} + +SwSetExpFieldType::SwSetExpFieldType( SwDoc* pDc, const OUString& rName, sal_uInt16 nTyp ) + : SwValueFieldType( pDc, SwFieldIds::SetExp ), + m_sName( rName ), + m_sDelim( "." ), + m_nType(nTyp), m_nLevel( UCHAR_MAX ), + m_bDeleted( false ) +{ + if( ( nsSwGetSetExpType::GSE_SEQ | nsSwGetSetExpType::GSE_STRING ) & m_nType ) + EnableFormat(false); // do not use Numberformatter +} + +std::unique_ptr<SwFieldType> SwSetExpFieldType::Copy() const +{ + std::unique_ptr<SwSetExpFieldType> pNew(new SwSetExpFieldType(GetDoc(), m_sName, m_nType)); + pNew->m_bDeleted = m_bDeleted; + pNew->m_sDelim = m_sDelim; + pNew->m_nLevel = m_nLevel; + + return pNew; +} + +OUString SwSetExpFieldType::GetName() const +{ + return m_sName; +} + +const OUString& SwSetExpField::GetExpStr(SwRootFrame const*const pLayout) const +{ + return (pLayout && pLayout->IsHideRedlines()) ? msExpandRLHidden : msExpand; +} + +void SwSetExpField::ChgExpStr(const OUString& rExpand, SwRootFrame const*const pLayout) +{ + if (!pLayout || pLayout->IsHideRedlines()) + { + msExpandRLHidden = rExpand; + } + if (!pLayout || !pLayout->IsHideRedlines()) + { + msExpand = rExpand; + } +} + +void SwSetExpFieldType::SwClientNotify(const SwModify&, const SfxHint&) +{ + // do not expand further +} + +void SwSetExpFieldType::SetSeqFormat(sal_uLong nFormat) +{ + std::vector<SwFormatField*> vFields; + GatherFields(vFields, false); + for(auto pFormatField: vFields) + pFormatField->GetField()->ChangeFormat(nFormat); +} + +sal_uLong SwSetExpFieldType::GetSeqFormat() const +{ + if( !HasWriterListeners() ) + return SVX_NUM_ARABIC; + + std::vector<SwFormatField*> vFields; + GatherFields(vFields, false); + return vFields.front()->GetField()->GetFormat(); +} + +void SwSetExpFieldType::SetSeqRefNo( SwSetExpField& rField ) +{ + if( !HasWriterListeners() || !(nsSwGetSetExpType::GSE_SEQ & m_nType) ) + return; + + std::vector<sal_uInt16> aArr; + + // check if number is already used and if a new one needs to be created + std::vector<SwFormatField*> vFields; + GatherFields(vFields); + for(SwFormatField* pF: vFields) + if(pF->GetField() != &rField) + InsertSort(aArr, static_cast<SwSetExpField*>(pF->GetField())->GetSeqNumber()); + + // check first if number already exists + sal_uInt16 nNum = rField.GetSeqNumber(); + if( USHRT_MAX != nNum ) + { + std::vector<sal_uInt16>::size_type n {0}; + + for( n = 0; n < aArr.size(); ++n ) + if( aArr[ n ] >= nNum ) + break; + + if( n == aArr.size() || aArr[ n ] > nNum ) + return; // no -> use it + } + + // flagged all numbers, so determine the right number + std::vector<sal_uInt16>::size_type n = aArr.size(); + OSL_ENSURE( n <= std::numeric_limits<sal_uInt16>::max(), "Array is too big for using a sal_uInt16 index" ); + + if ( n > 0 && aArr[ n-1 ] != n-1 ) + { + for( n = 0; n < aArr.size(); ++n ) + if( n != aArr[ n ] ) + break; + } + + rField.SetSeqNumber( n ); +} + +size_t SwSetExpFieldType::GetSeqFieldList(SwSeqFieldList& rList, + SwRootFrame const*const pLayout) +{ + rList.Clear(); + + IDocumentRedlineAccess const& rIDRA(GetDoc()->getIDocumentRedlineAccess()); + + std::vector<SwFormatField*> vFields; + GatherFields(vFields); + for(SwFormatField* pF: vFields) + { + const SwTextNode* pNd; + if( nullptr != ( pNd = pF->GetTextField()->GetpTextNode() ) + && (!pLayout || !pLayout->IsHideRedlines() + || !sw::IsFieldDeletedInModel(rIDRA, *pF->GetTextField()))) + { + SeqFieldLstElem aNew( + pNd->GetExpandText(pLayout), + static_cast<SwSetExpField*>(pF->GetField())->GetSeqNumber() ); + rList.InsertSort( aNew ); + } + } + return rList.Count(); +} + +void SwSetExpFieldType::SetChapter(SwSetExpField& rField, const SwNode& rNd, + SwRootFrame const*const pLayout) +{ + const SwTextNode* pTextNd = rNd.FindOutlineNodeOfLevel(m_nLevel, pLayout); + if( !pTextNd ) + return; + + SwNumRule * pRule = pTextNd->GetNumRule(); + + if (!pRule) + return; + + // --> OD 2005-11-02 #i51089 - TUNING# + if (SwNodeNum const*const pNum = pTextNd->GetNum(pLayout)) + { + // only get the number, without pre-/post-fixstrings + OUString const sNumber(pRule->MakeNumString(*pNum, false)); + + if( !sNumber.isEmpty() ) + rField.ChgExpStr(sNumber + m_sDelim + rField.GetExpStr(pLayout), pLayout); + } + else + { + OSL_ENSURE(pTextNd->GetNum(nullptr), "<SwSetExpFieldType::SetChapter(..)> - text node with numbering rule, but without number. This is a serious defect"); + } +} + +void SwSetExpFieldType::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const +{ + switch( nWhichId ) + { + case FIELD_PROP_SUBTYPE: + { + sal_Int16 nRet = lcl_SubTypeToAPI(GetType()); + rAny <<= nRet; + } + break; + case FIELD_PROP_PAR2: + rAny <<= GetDelimiter(); + break; + case FIELD_PROP_SHORT1: + { + sal_Int8 nRet = m_nLevel < MAXLEVEL? m_nLevel : -1; + rAny <<= nRet; + } + break; + default: + assert(false); + } +} + +void SwSetExpFieldType::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId ) +{ + switch( nWhichId ) + { + case FIELD_PROP_SUBTYPE: + { + sal_Int32 nSet = lcl_APIToSubType(rAny); + if(nSet >=0) + SetType(o3tl::narrowing<sal_uInt16>(nSet)); + } + break; + case FIELD_PROP_PAR2: + { + OUString sTmp; + rAny >>= sTmp; + if( !sTmp.isEmpty() ) + SetDelimiter( sTmp ); + else + SetDelimiter( " " ); + } + break; + case FIELD_PROP_SHORT1: + { + sal_Int8 nLvl = 0; + rAny >>= nLvl; + if(nLvl < 0 || nLvl >= MAXLEVEL) + SetOutlineLvl(UCHAR_MAX); + else + SetOutlineLvl(nLvl); + } + break; + default: + assert(false); + } +} + +bool SwSeqFieldList::InsertSort( SeqFieldLstElem aNew ) +{ + OUStringBuffer aBuf(aNew.sDlgEntry); + const sal_Int32 nLen = aBuf.getLength(); + for (sal_Int32 i = 0; i < nLen; ++i) + { + if (aBuf[i]<' ') + { + aBuf[i]=' '; + } + } + aNew.sDlgEntry = aBuf.makeStringAndClear(); + + size_t nPos = 0; + bool bRet = SeekEntry( aNew, &nPos ); + if( !bRet ) + maData.insert( maData.begin() + nPos, aNew ); + return bRet; +} + +bool SwSeqFieldList::SeekEntry( const SeqFieldLstElem& rNew, size_t* pP ) const +{ + size_t nO = maData.size(); + size_t nU = 0; + if( nO > 0 ) + { + CollatorWrapper & rCaseColl = ::GetAppCaseCollator(), + & rColl = ::GetAppCollator(); + const CharClass& rCC = GetAppCharClass(); + + //#59900# Sorting should sort number correctly (e.g. "10" after "9" not after "1") + const OUString rTmp2 = rNew.sDlgEntry; + sal_Int32 nFndPos2 = 0; + const OUString sNum2( rTmp2.getToken( 0, ' ', nFndPos2 )); + bool bIsNum2IsNumeric = CharClass::isAsciiNumeric( sNum2 ); + sal_Int32 nNum2 = bIsNum2IsNumeric ? sNum2.toInt32() : 0; + + nO--; + while( nU <= nO ) + { + const size_t nM = nU + ( nO - nU ) / 2; + + //#59900# Sorting should sort number correctly (e.g. "10" after "9" not after "1") + const OUString rTmp1 = maData[nM].sDlgEntry; + sal_Int32 nFndPos1 = 0; + const OUString sNum1( rTmp1.getToken( 0, ' ', nFndPos1 )); + sal_Int32 nCmp; + + if( bIsNum2IsNumeric && rCC.isNumeric( sNum1 ) ) + { + sal_Int32 nNum1 = sNum1.toInt32(); + nCmp = nNum2 - nNum1; + if( 0 == nCmp ) + { + OUString aTmp1 = nFndPos1 != -1 ? rTmp1.copy(nFndPos1) : OUString(); + OUString aTmp2 = nFndPos2 != -1 ? rTmp2.copy(nFndPos2) : OUString(); + nCmp = rCaseColl.compareString(aTmp2, aTmp1); + } + } + else + nCmp = rColl.compareString( rTmp2, rTmp1 ); + + if( 0 == nCmp ) + { + if( pP ) *pP = nM; + return true; + } + else if( 0 < nCmp ) + nU = nM + 1; + else if( nM == 0 ) + break; + else + nO = nM - 1; + } + } + if( pP ) *pP = nU; + return false; +} + +SwSetExpField::SwSetExpField(SwSetExpFieldType* pTyp, const OUString& rFormel, + sal_uLong nFormat) + : SwFormulaField( pTyp, nFormat, 0.0 ) + , m_fValueRLHidden(0.0) + , mnSeqNo( USHRT_MAX ) + , mnSubType(0) + , mpFormatField(nullptr) +{ + SetFormula(rFormel); + // ignore SubType + mbInput = false; + if( IsSequenceField() ) + { + SwValueField::SetValue(1.0); + m_fValueRLHidden = 1.0; + if( rFormel.isEmpty() ) + { + SetFormula(pTyp->GetName() + "+1"); + } + } +} + +void SwSetExpField::SetFormatField(SwFormatField & rFormatField) +{ + mpFormatField = &rFormatField; +} + +OUString SwSetExpField::ExpandImpl(SwRootFrame const*const pLayout) const +{ + if (mnSubType & nsSwExtendedSubType::SUB_CMD) + { // we need the CommandString + return GetTyp()->GetName() + " = " + GetFormula(); + } + if(!(mnSubType & nsSwExtendedSubType::SUB_INVISIBLE)) + { // value is visible + return (pLayout && pLayout->IsHideRedlines()) ? msExpandRLHidden : msExpand; + } + return OUString(); +} + +/// @return the field name +OUString SwSetExpField::GetFieldName() const +{ + SwFieldTypesEnum const nStrType( (IsSequenceField()) + ? SwFieldTypesEnum::Sequence + : mbInput + ? SwFieldTypesEnum::SetInput + : SwFieldTypesEnum::Set ); + + OUString aStr( + SwFieldType::GetTypeStr( nStrType ) + + " " + + GetTyp()->GetName() ); + + // Sequence: without formula + if (SwFieldTypesEnum::Sequence != nStrType) + { + aStr += " = " + GetFormula(); + } + return aStr; +} + +std::unique_ptr<SwField> SwSetExpField::Copy() const +{ + std::unique_ptr<SwSetExpField> pTmp(new SwSetExpField(static_cast<SwSetExpFieldType*>(GetTyp()), + GetFormula(), GetFormat())); + pTmp->SwValueField::SetValue(GetValue()); + pTmp->m_fValueRLHidden = m_fValueRLHidden; + pTmp->msExpand = msExpand; + pTmp->msExpandRLHidden = msExpandRLHidden; + pTmp->SetAutomaticLanguage(IsAutomaticLanguage()); + pTmp->SetLanguage(GetLanguage()); + pTmp->maPText = maPText; + pTmp->mbInput = mbInput; + pTmp->mnSeqNo = mnSeqNo; + pTmp->SetSubType(GetSubType()); + + return std::unique_ptr<SwField>(pTmp.release()); +} + +void SwSetExpField::SetSubType(sal_uInt16 nSub) +{ + static_cast<SwSetExpFieldType*>(GetTyp())->SetType(nSub & 0xff); + mnSubType = nSub & 0xff00; + + OSL_ENSURE( (nSub & 0xff) != 3, "SubType is illegal!" ); +} + +sal_uInt16 SwSetExpField::GetSubType() const +{ + return static_cast<SwSetExpFieldType*>(GetTyp())->GetType() | mnSubType; +} + +void SwSetExpField::SetValue( const double& rAny ) +{ + SwValueField::SetValue(rAny); + + if( IsSequenceField() ) + msExpand = FormatNumber( GetValue(), static_cast<SvxNumType>(GetFormat()), GetLanguage() ); + else + msExpand = static_cast<SwValueFieldType*>(GetTyp())->ExpandValue( rAny, + GetFormat(), GetLanguage()); +} + +void SwSetExpField::SetValue(const double& rValue, SwRootFrame const*const pLayout) +{ + if (!pLayout || !pLayout->IsHideRedlines()) + { + SetValue(rValue); + } + if (pLayout && !pLayout->IsHideRedlines()) + return; + + m_fValueRLHidden = rValue; + if (IsSequenceField()) + { + msExpandRLHidden = FormatNumber(rValue, static_cast<SvxNumType>(GetFormat()), GetLanguage()); + } + else + { + msExpandRLHidden = static_cast<SwValueFieldType*>(GetTyp())->ExpandValue( + rValue, GetFormat(), GetLanguage()); + } +} + +double SwSetExpField::GetValue(SwRootFrame const* pLayout) const +{ + return (pLayout && pLayout->IsHideRedlines()) ? m_fValueRLHidden : GetValue(); +} + +void SwGetExpField::SetValue( const double& rAny ) +{ + SwValueField::SetValue(rAny); + m_sExpand = static_cast<SwValueFieldType*>(GetTyp())->ExpandValue( rAny, GetFormat(), + GetLanguage()); +} + +void SwGetExpField::SetValue(const double& rValue, SwRootFrame const*const pLayout) +{ + if (!pLayout || !pLayout->IsHideRedlines()) + { + SetValue(rValue); + } + if (!pLayout || pLayout->IsHideRedlines()) + { + m_fValueRLHidden = rValue; + m_sExpandRLHidden = static_cast<SwValueFieldType*>(GetTyp())->ExpandValue( + rValue, GetFormat(), GetLanguage()); + } +} + +double SwGetExpField::GetValue(SwRootFrame const* pLayout) const +{ + return (pLayout && pLayout->IsHideRedlines()) ? m_fValueRLHidden : GetValue(); +} + +/** Find the index of the reference text following the current field + * + * @param rFormat + * @param rDoc + * @param nHint search starting position after the current field (or 0 if default) + * @return + */ +sal_Int32 SwGetExpField::GetReferenceTextPos( const SwFormatField& rFormat, SwDoc& rDoc, sal_Int32 nHint) +{ + + const SwTextField* pTextField = rFormat.GetTextField(); + const SwTextNode& rTextNode = pTextField->GetTextNode(); + + sal_Int32 nRet = nHint ? nHint : pTextField->GetStart() + 1; + OUString sNodeText = rTextNode.GetText(); + + if(nRet<sNodeText.getLength()) + { + sNodeText = sNodeText.copy(nRet); + + // now check if sNodeText starts with a non-alphanumeric character plus blanks + sal_uInt16 nSrcpt = g_pBreakIt->GetRealScriptOfText( sNodeText, 0 ); + + static const WhichRangesContainer nIds(svl::Items< + RES_CHRATR_FONT, RES_CHRATR_FONT, + RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE, + RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONT, + RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, + RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONT, + RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_LANGUAGE + >); + SwAttrSet aSet(rDoc.GetAttrPool(), nIds); + rTextNode.GetParaAttr(aSet, nRet, nRet+1); + + TypedWhichId<SvxFontItem> nFontWhich = GetWhichOfScript( RES_CHRATR_FONT, nSrcpt ); + if( RTL_TEXTENCODING_SYMBOL != aSet.Get( nFontWhich ).GetCharSet() ) + { + TypedWhichId<SvxLanguageItem> nLangWhich = GetWhichOfScript( RES_CHRATR_LANGUAGE, nSrcpt ) ; + LanguageType eLang = aSet.Get(nLangWhich).GetLanguage(); + CharClass aCC(( LanguageTag(eLang) )); + sal_Unicode c0 = sNodeText[0]; + bool bIsAlphaNum = aCC.isAlphaNumeric( sNodeText, 0 ); + if( !bIsAlphaNum || + (c0 == ' ' || c0 == '\t')) + { + // ignoring blanks + nRet++; + const sal_Int32 nLen = sNodeText.getLength(); + for (sal_Int32 i = 1; + i<nLen && (sNodeText[i]==' ' || sNodeText[i]=='\t'); + ++i + ) + ++nRet; + } + } + } + return nRet; +} + +OUString SwSetExpField::GetPar1() const +{ + return static_cast<const SwSetExpFieldType*>(GetTyp())->GetName(); +} + +OUString SwSetExpField::GetPar2() const +{ + sal_uInt16 nType = static_cast<SwSetExpFieldType*>(GetTyp())->GetType(); + + if (nType & nsSwGetSetExpType::GSE_STRING) + return GetFormula(); + return GetExpandedFormula(); +} + +void SwSetExpField::SetPar2(const OUString& rStr) +{ + sal_uInt16 nType = static_cast<SwSetExpFieldType*>(GetTyp())->GetType(); + + if( !(nType & nsSwGetSetExpType::GSE_SEQ) || !rStr.isEmpty() ) + { + if (nType & nsSwGetSetExpType::GSE_STRING) + SetFormula(rStr); + else + SetExpandedFormula(rStr); + } +} + +bool SwSetExpField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId ) +{ + sal_Int32 nTmp32 = 0; + sal_Int16 nTmp16 = 0; + switch( nWhichId ) + { + case FIELD_PROP_BOOL2: + if(*o3tl::doAccess<bool>(rAny)) + mnSubType &= ~nsSwExtendedSubType::SUB_INVISIBLE; + else + mnSubType |= nsSwExtendedSubType::SUB_INVISIBLE; + break; + case FIELD_PROP_FORMAT: + rAny >>= nTmp32; + SetFormat(nTmp32); + break; + case FIELD_PROP_USHORT2: + { + rAny >>= nTmp16; + if(nTmp16 <= css::style::NumberingType::NUMBER_NONE ) + SetFormat(nTmp16); + else { + //exception(wrong_value) + ; + } + } + break; + case FIELD_PROP_USHORT1: + rAny >>= nTmp16; + mnSeqNo = nTmp16; + break; + case FIELD_PROP_PAR1: + { + OUString sTmp; + rAny >>= sTmp; + SetPar1( SwStyleNameMapper::GetUIName( sTmp, SwGetPoolIdFromName::TxtColl ) ); + } + break; + case FIELD_PROP_PAR2: + { + OUString uTmp; + rAny >>= uTmp; + //I18N - if the formula contains only "TypeName+1" + //and it's one of the initially created sequence fields + //then the localized names has to be replaced by a programmatic name + OUString sMyFormula = SwXFieldMaster::LocalizeFormula(*this, uTmp, false); + SetFormula( sMyFormula ); + } + break; + case FIELD_PROP_DOUBLE: + { + double fVal = 0.0; + rAny >>= fVal; + SetValue(fVal); + m_fValueRLHidden = fVal; + } + break; + case FIELD_PROP_SUBTYPE: + nTmp32 = lcl_APIToSubType(rAny); + if(nTmp32 >= 0) + SetSubType(o3tl::narrowing<sal_uInt16>((GetSubType() & 0xff00) | nTmp32)); + break; + case FIELD_PROP_PAR3: + rAny >>= maPText; + break; + case FIELD_PROP_BOOL3: + if(*o3tl::doAccess<bool>(rAny)) + mnSubType |= nsSwExtendedSubType::SUB_CMD; + else + mnSubType &= (~nsSwExtendedSubType::SUB_CMD); + break; + case FIELD_PROP_BOOL1: + { + bool newInput(*o3tl::doAccess<bool>(rAny)); + if (newInput != GetInputFlag()) + { + if (static_cast<SwSetExpFieldType*>(GetTyp())->GetType() + & nsSwGetSetExpType::GSE_STRING) + { + SwXTextField::TransmuteLeadToInputField(*this); + } + else + { + SetInputFlag(newInput); + } + } + } + break; + case FIELD_PROP_PAR4: + { + OUString sTmp; + rAny >>= sTmp; + ChgExpStr(sTmp, nullptr); + } + break; + default: + return SwField::PutValue(rAny, nWhichId); + } + return true; +} + +bool SwSetExpField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const +{ + switch( nWhichId ) + { + case FIELD_PROP_BOOL2: + rAny <<= 0 == (mnSubType & nsSwExtendedSubType::SUB_INVISIBLE); + break; + case FIELD_PROP_FORMAT: + rAny <<= static_cast<sal_Int32>(GetFormat()); + break; + case FIELD_PROP_USHORT2: + rAny <<= static_cast<sal_Int16>(GetFormat()); + break; + case FIELD_PROP_USHORT1: + rAny <<= static_cast<sal_Int16>(mnSeqNo); + break; + case FIELD_PROP_PAR1: + rAny <<= SwStyleNameMapper::GetProgName(GetPar1(), SwGetPoolIdFromName::TxtColl ); + break; + case FIELD_PROP_PAR2: + { + //I18N - if the formula contains only "TypeName+1" + //and it's one of the initially created sequence fields + //then the localized names has to be replaced by a programmatic name + OUString sMyFormula = SwXFieldMaster::LocalizeFormula(*this, GetFormula(), true); + rAny <<= sMyFormula; + } + break; + case FIELD_PROP_DOUBLE: + rAny <<= GetValue(); + break; + case FIELD_PROP_SUBTYPE: + { + sal_Int16 nRet = lcl_SubTypeToAPI(GetSubType() & 0xff); + rAny <<= nRet; + } + break; + case FIELD_PROP_PAR3: + rAny <<= maPText; + break; + case FIELD_PROP_BOOL3: + rAny <<= 0 != (mnSubType & nsSwExtendedSubType::SUB_CMD); + break; + case FIELD_PROP_BOOL1: + rAny <<= GetInputFlag(); + break; + case FIELD_PROP_PAR4: + rAny <<= GetExpStr(nullptr); + break; + default: + return SwField::QueryValue(rAny, nWhichId); + } + return true; +} + +SwInputFieldType::SwInputFieldType( SwDoc* pD ) + : SwFieldType( SwFieldIds::Input ) + , mpDoc( pD ) +{ +} + +std::unique_ptr<SwFieldType> SwInputFieldType::Copy() const +{ + return std::make_unique<SwInputFieldType>( mpDoc ); +} + +SwInputField::SwInputField( SwInputFieldType* pFieldType, + const OUString& rContent, + const OUString& rPrompt, + sal_uInt16 nSub, + sal_uLong nFormat, + bool bIsFormField ) + : SwField( pFieldType, nFormat, LANGUAGE_SYSTEM, false ) + , maContent(rContent) + , maPText(rPrompt) + , mnSubType(nSub) + , mbIsFormField( bIsFormField ) + , mpFormatField( nullptr ) +{ +} + +SwInputField::~SwInputField() +{ +} + +void SwInputField::SetFormatField( SwFormatField& rFormatField ) +{ + mpFormatField = &rFormatField; +} + + +void SwInputField::applyFieldContent( const OUString& rNewFieldContent ) +{ + if ( (mnSubType & 0x00ff) == INP_TXT ) + { + maContent = rNewFieldContent; + } + else if( (mnSubType & 0x00ff) == INP_USR ) + { + SwUserFieldType* pUserTyp = static_cast<SwUserFieldType*>( + static_cast<SwInputFieldType*>(GetTyp())->GetDoc()->getIDocumentFieldsAccess().GetFieldType( SwFieldIds::User, getContent(), false ) ); + if( pUserTyp ) + { + pUserTyp->SetContent( rNewFieldContent ); + if (!pUserTyp->IsModifyLocked()) + { + // trigger update of the corresponding User Fields and other + // related Input Fields + bool bUnlock(false); + if (GetFormatField() != nullptr) + { + SwTextInputField *const pTextInputField = + dynamic_cast<SwTextInputField*>(GetFormatField()->GetTextField()); + if (pTextInputField != nullptr) + { + bUnlock = pTextInputField->LockNotifyContentChange(); + } + } + pUserTyp->UpdateFields(); + if (bUnlock) + { + SwTextInputField *const pTextInputField = + dynamic_cast<SwTextInputField*>(GetFormatField()->GetTextField()); + if (pTextInputField != nullptr) + { + pTextInputField->UnlockNotifyContentChange(); + } + } + } + } + } +} + +OUString SwInputField::GetFieldName() const +{ + OUString aStr(SwField::GetFieldName()); + if ((mnSubType & 0x00ff) == INP_USR) + { + aStr += GetTyp()->GetName() + " " + getContent(); + } + return aStr; +} + +std::unique_ptr<SwField> SwInputField::Copy() const +{ + std::unique_ptr<SwInputField> pField( + new SwInputField( + static_cast<SwInputFieldType*>(GetTyp()), + getContent(), + maPText, + GetSubType(), + GetFormat(), + mbIsFormField )); + + pField->SetHelp( maHelp ); + pField->SetToolTip( maToolTip ); + pField->maGrabBag = maGrabBag; + + pField->SetAutomaticLanguage(IsAutomaticLanguage()); + return std::unique_ptr<SwField>(pField.release()); +} + +OUString SwInputField::ExpandImpl(SwRootFrame const*const) const +{ + if((mnSubType & 0x00ff) == INP_TXT) + { + return getContent(); + } + + if( (mnSubType & 0x00ff) == INP_USR ) + { + SwUserFieldType* pUserTyp = static_cast<SwUserFieldType*>( + static_cast<SwInputFieldType*>(GetTyp())->GetDoc()->getIDocumentFieldsAccess().GetFieldType( SwFieldIds::User, getContent(), false ) ); + if( pUserTyp ) + return pUserTyp->GetContent(); + } + + return OUString(); +} + +bool SwInputField::isFormField() const +{ + return mbIsFormField + || !maHelp.isEmpty() + || !maToolTip.isEmpty(); +} + +bool SwInputField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const +{ + switch( nWhichId ) + { + case FIELD_PROP_PAR1: + rAny <<= getContent(); + break; + case FIELD_PROP_PAR2: + rAny <<= maPText; + break; + case FIELD_PROP_PAR3: + rAny <<= maHelp; + break; + case FIELD_PROP_PAR4: + rAny <<= maToolTip; + break; + case FIELD_PROP_GRABBAG: + rAny <<= maGrabBag; + break; + case FIELD_PROP_TITLE: + break; + default: + assert(false); + } + return true; +} + +bool SwInputField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId ) +{ + switch( nWhichId ) + { + case FIELD_PROP_PAR1: + rAny >>= maContent; + break; + case FIELD_PROP_PAR2: + rAny >>= maPText; + break; + case FIELD_PROP_PAR3: + rAny >>= maHelp; + break; + case FIELD_PROP_PAR4: + rAny >>= maToolTip; + break; + case FIELD_PROP_GRABBAG: + rAny >>= maGrabBag; + break; + case FIELD_PROP_TITLE: + break; + default: + assert(false); + } + return true; +} + +/// set condition +void SwInputField::SetPar1(const OUString& rStr) +{ + maContent = rStr; +} + +OUString SwInputField::GetPar1() const +{ + return getContent(); +} + +void SwInputField::SetPar2(const OUString& rStr) +{ + maPText = rStr; +} + +OUString SwInputField::GetPar2() const +{ + return maPText; +} + +void SwInputField::SetHelp(const OUString & rStr) +{ + maHelp = rStr; +} + +const OUString& SwInputField::GetHelp() const +{ + return maHelp; +} + +void SwInputField::SetToolTip(const OUString & rStr) +{ + maToolTip = rStr; +} + +const OUString& SwInputField::GetToolTip() const +{ + return maToolTip; +} + +sal_uInt16 SwInputField::GetSubType() const +{ + return mnSubType; +} + +void SwInputField::SetSubType(sal_uInt16 nSub) +{ + mnSubType = nSub; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |