/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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, OUString(DB_DELIM)); if (bWithCommandType) { nIndex = sRes.lastIndexOf('.', nIndex); if (nIndex<0) { return sRes; } sRes = sRes.replaceAt(nIndex, 1, OUString(DB_DELIM)); } nIndex = sRes.indexOf('.'); if (nIndex>=0) { sRes = sRes.replaceAt(nIndex, 1, OUString(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(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(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(static_cast(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(pTextNode)->MakeStartIndex( &rPos.nContent ); } // do not break yet, might be as well in Header/Footer/Footnote/Fly pLayout = static_cast(pLayout)->GetAnchorFrame() ? static_cast(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(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(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 SwGetExpFieldType::Copy() const { return std::make_unique(GetDoc()); } void SwGetExpFieldType::Modify( const SfxPoolItem*, const SfxPoolItem* pNew ) { if( pNew && RES_DOCPOS_UPDATE == pNew->Which() ) NotifyClients( nullptr, pNew ); // do not expand anything else } 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 SwGetExpField::Copy() const { std::unique_ptr pTmp(new SwGetExpField(static_cast(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(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(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); SetGetExpField aEndField( aPos.nNode, &rField, &aPos.nContent ); if(GetSubType() & nsSwGetSetExpType::GSE_STRING) { SwHashTable 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(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(GetFormat()); break; case FIELD_PROP_USHORT1: rAny <<= static_cast(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(rAny)); m_fValueRLHidden = *o3tl::doAccess(rAny); break; case FIELD_PROP_FORMAT: rAny >>= nTmp; SetFormat(nTmp); break; case FIELD_PROP_USHORT1: rAny >>= nTmp; m_nSubType = static_cast(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( static_cast((GetSubType() & 0xff00) | nTmp)); break; case FIELD_PROP_BOOL2: if(*o3tl::doAccess(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 SwSetExpFieldType::Copy() const { std::unique_ptr 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::Modify( const SfxPoolItem*, const SfxPoolItem* ) { // do not expand further } void SwSetExpFieldType::SetSeqFormat(sal_uLong nFormat) { std::vector 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 vFields; GatherFields(vFields, false); return vFields.front()->GetField()->GetFormat(); } void SwSetExpFieldType::SetSeqRefNo( SwSetExpField& rField ) { if( !HasWriterListeners() || !(nsSwGetSetExpType::GSE_SEQ & m_nType) ) return; std::vector aArr; // check if number is already used and if a new one needs to be created std::vector vFields; GatherFields(vFields); for(SwFormatField* pF: vFields) if(pF->GetField() != &rField) InsertSort(aArr, static_cast(pF->GetField())->GetSeqNumber()); // check first if number already exists sal_uInt16 nNum = rField.GetSeqNumber(); if( USHRT_MAX != nNum ) { std::vector::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::size_type n = aArr.size(); OSL_ENSURE( n <= std::numeric_limits::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 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(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 ) { SwNumRule * pRule = pTextNd->GetNumRule(); if (pRule) { // --> 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), " - 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(static_cast(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 SwSetExpField::Copy() const { std::unique_ptr pTmp(new SwSetExpField(static_cast(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(pTmp.release()); } void SwSetExpField::SetSubType(sal_uInt16 nSub) { static_cast(GetTyp())->SetType(nSub & 0xff); mnSubType = nSub & 0xff00; OSL_ENSURE( (nSub & 0xff) != 3, "SubType is illegal!" ); } sal_uInt16 SwSetExpField::GetSubType() const { return static_cast(GetTyp())->GetType() | mnSubType; } void SwSetExpField::SetValue( const double& rAny ) { SwValueField::SetValue(rAny); if( IsSequenceField() ) msExpand = FormatNumber( GetValue(), static_cast(GetFormat()), GetLanguage() ); else msExpand = static_cast(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()) { m_fValueRLHidden = rValue; if (IsSequenceField()) { msExpandRLHidden = FormatNumber(rValue, static_cast(GetFormat()), GetLanguage()); } else { msExpandRLHidden = static_cast(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(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(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(nRetGetRealScriptOfText( sNodeText, 0 ); static const sal_uInt16 nIds[] = { RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE, RES_CHRATR_FONT, RES_CHRATR_FONT, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONT, 0, 0 }; SwAttrSet aSet(rDoc.GetAttrPool(), nIds); rTextNode.GetParaAttr(aSet, nRet, nRet+1); if( RTL_TEXTENCODING_SYMBOL != static_cast(aSet.Get( GetWhichOfScript( RES_CHRATR_FONT, nSrcpt )) ).GetCharSet() ) { LanguageType eLang = static_cast(aSet.Get( GetWhichOfScript( RES_CHRATR_LANGUAGE, nSrcpt )) ).GetLanguage(); LanguageTag aLanguageTag( eLang); CharClass aCC( aLanguageTag); 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(GetTyp())->GetName(); } OUString SwSetExpField::GetPar2() const { sal_uInt16 nType = static_cast(GetTyp())->GetType(); if (nType & nsSwGetSetExpType::GSE_STRING) return GetFormula(); return GetExpandedFormula(); } void SwSetExpField::SetPar2(const OUString& rStr) { sal_uInt16 nType = static_cast(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(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(static_cast((GetSubType() & 0xff00) | nTmp32)); break; case FIELD_PROP_PAR3: rAny >>= maPText; break; case FIELD_PROP_BOOL3: if(*o3tl::doAccess(rAny)) mnSubType |= nsSwExtendedSubType::SUB_CMD; else mnSubType &= (~nsSwExtendedSubType::SUB_CMD); break; case FIELD_PROP_BOOL1: { bool newInput(*o3tl::doAccess(rAny)); if (newInput != GetInputFlag()) { if (static_cast(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(GetFormat()); break; case FIELD_PROP_USHORT2: rAny <<= static_cast(GetFormat()); break; case FIELD_PROP_USHORT1: rAny <<= static_cast(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 SwInputFieldType::Copy() const { return std::make_unique( 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( static_cast(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(GetFormatField()->GetTextField()); if (pTextInputField != nullptr) { bUnlock = pTextInputField->LockNotifyContentChange(); } } pUserTyp->UpdateFields(); if (bUnlock) { SwTextInputField *const pTextInputField = dynamic_cast(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 SwInputField::Copy() const { std::unique_ptr pField( new SwInputField( static_cast(GetTyp()), getContent(), maPText, GetSubType(), GetFormat(), mbIsFormField )); pField->SetHelp( maHelp ); pField->SetToolTip( maToolTip ); pField->SetAutomaticLanguage(IsAutomaticLanguage()); return std::unique_ptr(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( static_cast(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; 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; 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: */