/* -*- 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 using namespace ::com::sun::star::uno; namespace { #if HAVE_FEATURE_DBCONNECTIVITY OUString lcl_GetDBVarName( SwDoc& rDoc, SwDBNameInfField& rDBField ) { SwDBData aDBData( rDBField.GetDBData( &rDoc )); OUString sDBNumNm; SwDBData aDocData = rDoc.GetDBData(); if( aDBData != aDocData ) { sDBNumNm = aDBData.sDataSource + OUStringLiteral1(DB_DELIM) + aDBData.sCommand + OUStringLiteral1(DB_DELIM); } sDBNumNm += SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD); return sDBNumNm; } #endif void lcl_CalcField( SwDoc& rDoc, SwCalc& rCalc, const SetGetExpField& rSGEField, SwDBManager* pMgr ) { const SwTextField* pTextField = rSGEField.GetTextField(); if( !pTextField ) return ; const SwField* pField = pTextField->GetFormatField().GetField(); const SwFieldIds nFieldWhich = pField->GetTyp()->Which(); if( SwFieldIds::SetExp == nFieldWhich ) { SwSbxValue aValue; if( nsSwGetSetExpType::GSE_EXPR & pField->GetSubType() ) aValue.PutDouble( static_cast(pField)->GetValue() ); else // Extension to calculate with Strings aValue.PutString( static_cast(pField)->GetExpStr() ); // set the new value in Calculator rCalc.VarChange( pField->GetTyp()->GetName(), aValue ); } else if( pMgr ) { #if !HAVE_FEATURE_DBCONNECTIVITY (void) rDoc; #else switch( nFieldWhich ) { case SwFieldIds::DbNumSet: { SwDBNumSetField* pDBField = const_cast(static_cast(pField)); SwDBData aDBData(pDBField->GetDBData(&rDoc)); if( pDBField->IsCondValid() && pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand )) rCalc.VarChange( lcl_GetDBVarName( rDoc, *pDBField), pDBField->GetFormat() ); } break; case SwFieldIds::DbNextSet: { SwDBNextSetField* pDBField = const_cast(static_cast(pField)); SwDBData aDBData(pDBField->GetDBData(&rDoc)); if( !pDBField->IsCondValid() || !pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand )) break; OUString sDBNumNm(lcl_GetDBVarName( rDoc, *pDBField)); SwCalcExp* pExp = rCalc.VarLook( sDBNumNm ); if( pExp ) rCalc.VarChange( sDBNumNm, pExp->nValue.GetLong() + 1 ); } break; default: break; } #endif } } } namespace sw { DocumentFieldsManager::DocumentFieldsManager( SwDoc& i_rSwdoc ) : m_rDoc( i_rSwdoc ), mbNewFieldLst(true), mpUpdateFields( new SwDocUpdateField( &m_rDoc ) ), mpFieldTypes( new SwFieldTypes ), mnLockExpField( 0 ) { } const SwFieldTypes* DocumentFieldsManager::GetFieldTypes() const { return mpFieldTypes.get(); } /** Insert field types * * @param rFieldTyp ??? * @return Always returns a pointer to the type, if it's new or already added. */ SwFieldType* DocumentFieldsManager::InsertFieldType(const SwFieldType &rFieldTyp) { const SwFieldTypes::size_type nSize = mpFieldTypes->size(); const SwFieldIds nFieldWhich = rFieldTyp.Which(); SwFieldTypes::size_type i = INIT_FLDTYPES; switch( nFieldWhich ) { case SwFieldIds::SetExp: //JP 29.01.96: SequenceFields start at INIT_FLDTYPES - 3!! // Or we get doubble number circles!! //MIB 14.03.95: From now on also the SW3-Reader relies on &m_rDoc, when //constructing string pools and when reading SetExp fields if( nsSwGetSetExpType::GSE_SEQ & static_cast(rFieldTyp).GetType() ) i -= INIT_SEQ_FLDTYPES; SAL_FALLTHROUGH; case SwFieldIds::Database: case SwFieldIds::User: case SwFieldIds::Dde: { const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore(); OUString sFieldNm( rFieldTyp.GetName() ); for( ; i < nSize; ++i ) if( nFieldWhich == (*mpFieldTypes)[i]->Which() && rSCmp.isEqual( sFieldNm, (*mpFieldTypes)[i]->GetName() )) return (*mpFieldTypes)[i]; } break; case SwFieldIds::TableOfAuthorities: for( ; i < nSize; ++i ) if( nFieldWhich == (*mpFieldTypes)[i]->Which() ) return (*mpFieldTypes)[i]; break; default: for( i = 0; i < nSize; ++i ) if( nFieldWhich == (*mpFieldTypes)[i]->Which() ) return (*mpFieldTypes)[i]; } SwFieldType* pNew = rFieldTyp.Copy(); switch( nFieldWhich ) { case SwFieldIds::Dde: static_cast(pNew)->SetDoc( &m_rDoc ); break; case SwFieldIds::Database: case SwFieldIds::Table: case SwFieldIds::DateTime: case SwFieldIds::GetExp: static_cast(pNew)->SetDoc( &m_rDoc ); break; case SwFieldIds::User: case SwFieldIds::SetExp: static_cast(pNew)->SetDoc( &m_rDoc ); // JP 29.07.96: Optionally prepare FieldList for Calculator: mpUpdateFields->InsertFieldType( *pNew ); break; case SwFieldIds::TableOfAuthorities : static_cast(pNew)->SetDoc( &m_rDoc ); break; default: break; } mpFieldTypes->insert( mpFieldTypes->begin() + nSize, pNew ); m_rDoc.getIDocumentState().SetModified(); return (*mpFieldTypes)[ nSize ]; } /// @returns the field type of the Doc SwFieldType *DocumentFieldsManager::GetSysFieldType( const SwFieldIds eWhich ) const { for( SwFieldTypes::size_type i = 0; i < INIT_FLDTYPES; ++i ) if( eWhich == (*mpFieldTypes)[i]->Which() ) return (*mpFieldTypes)[i]; return nullptr; } /// Find first type with ResId and name SwFieldType* DocumentFieldsManager::GetFieldType( SwFieldIds nResId, const OUString& rName, bool bDbFieldMatching // used in some UNO calls for SwFieldIds::Database to use different string matching code #i51815# ) const { const SwFieldTypes::size_type nSize = mpFieldTypes->size(); SwFieldTypes::size_type i {0}; const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore(); switch( nResId ) { case SwFieldIds::SetExp: //JP 29.01.96: SequenceFields start at INIT_FLDTYPES - 3!! // Or we get doubble number circles!! //MIB 14.03.95: From now on also the SW3-Reader relies on &m_rDoc, when //constructing string pools and when reading SetExp fields i = INIT_FLDTYPES - INIT_SEQ_FLDTYPES; break; case SwFieldIds::Database: case SwFieldIds::User: case SwFieldIds::Dde: case SwFieldIds::TableOfAuthorities: i = INIT_FLDTYPES; break; default: break; } SwFieldType* pRet = nullptr; for( ; i < nSize; ++i ) { SwFieldType* pFieldType = (*mpFieldTypes)[i]; if (nResId == pFieldType->Which()) { OUString aFieldName( pFieldType->GetName() ); if (bDbFieldMatching && nResId == SwFieldIds::Database) // #i51815# aFieldName = aFieldName.replace(DB_DELIM, '.'); if (rSCmp.isEqual( rName, aFieldName )) { pRet = pFieldType; break; } } } return pRet; } /// Remove field type void DocumentFieldsManager::RemoveFieldType(size_t nField) { OSL_ENSURE( INIT_FLDTYPES <= nField, "don't remove InitFields" ); /* * Dependent fields present -> ErrRaise */ if(nField < mpFieldTypes->size()) { SwFieldType* pTmp = (*mpFieldTypes)[nField]; // JP 29.07.96: Optionally prepare FieldList for Calculator SwFieldIds nWhich = pTmp->Which(); switch( nWhich ) { case SwFieldIds::SetExp: case SwFieldIds::User: mpUpdateFields->RemoveFieldType( *pTmp ); SAL_FALLTHROUGH; case SwFieldIds::Dde: if( pTmp->HasWriterListeners() && !m_rDoc.IsUsed( *pTmp ) ) { if( SwFieldIds::SetExp == nWhich ) static_cast(pTmp)->SetDeleted( true ); else if( SwFieldIds::User == nWhich ) static_cast(pTmp)->SetDeleted( true ); else static_cast(pTmp)->SetDeleted( true ); nWhich = SwFieldIds::Database; } break; default: break; } if( nWhich != SwFieldIds::Database ) { OSL_ENSURE( !pTmp->HasWriterListeners(), "Dependent fields present!" ); // delete field type delete pTmp; } mpFieldTypes->erase( mpFieldTypes->begin() + nField ); m_rDoc.getIDocumentState().SetModified(); } } // All have to be re-evaluated. void DocumentFieldsManager::UpdateFields( bool bCloseDB ) { // Call Modify() for every field type, // dependent SwTextField get notified ... for( auto pFieldType : *mpFieldTypes ) { switch( pFieldType->Which() ) { // Update table fields second to last // Update references last case SwFieldIds::GetRef: case SwFieldIds::Table: case SwFieldIds::Database: case SwFieldIds::JumpEdit: case SwFieldIds::RefPageSet: // are never expanded! break; case SwFieldIds::Dde: { SwMsgPoolItem aUpdateDDE( RES_UPDATEDDETBL ); pFieldType->ModifyNotification( nullptr, &aUpdateDDE ); break; } case SwFieldIds::GetExp: case SwFieldIds::SetExp: case SwFieldIds::HiddenText: case SwFieldIds::HiddenPara: // Expression fields are treated separately break; default: pFieldType->ModifyNotification ( nullptr, nullptr ); } } if( !IsExpFieldsLocked() ) UpdateExpFields( nullptr, false ); // update expression fields // Tables UpdateTableFields(nullptr); // References UpdateRefFields(); if( bCloseDB ) { #if HAVE_FEATURE_DBCONNECTIVITY m_rDoc.GetDBManager()->CloseAll(); #endif } // Only evaluate on full update m_rDoc.getIDocumentState().SetModified(); } void DocumentFieldsManager::InsDeletedFieldType( SwFieldType& rFieldTyp ) { // The FieldType was marked as deleted and removed from the array. // One has to look &m_rDoc up again, now. // - If it's not present, it can be re-inserted. // - If the same type is found, the deleted one has to be renamed. const SwFieldTypes::size_type nSize = mpFieldTypes->size(); const SwFieldIds nFieldWhich = rFieldTyp.Which(); OSL_ENSURE( SwFieldIds::SetExp == nFieldWhich || SwFieldIds::User == nFieldWhich || SwFieldIds::Dde == nFieldWhich, "Wrong FieldType" ); const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore(); const OUString& rFieldNm = rFieldTyp.GetName(); for( SwFieldTypes::size_type i = INIT_FLDTYPES; i < nSize; ++i ) { SwFieldType* pFnd; if( nFieldWhich == (pFnd = (*mpFieldTypes)[i])->Which() && rSCmp.isEqual( rFieldNm, pFnd->GetName() ) ) { // find new name SwFieldTypes::size_type nNum = 1; do { OUString sSrch = rFieldNm + OUString::number( nNum ); for( i = INIT_FLDTYPES; i < nSize; ++i ) if( nFieldWhich == (pFnd = (*mpFieldTypes)[i])->Which() && rSCmp.isEqual( sSrch, pFnd->GetName() ) ) break; if( i >= nSize ) // not found { const_cast(rFieldNm) = sSrch; break; // exit while loop } ++nNum; } while( true ); break; } } // not found, so insert and delete flag mpFieldTypes->insert( mpFieldTypes->begin() + nSize, &rFieldTyp ); switch( nFieldWhich ) { case SwFieldIds::SetExp: static_cast(rFieldTyp).SetDeleted( false ); break; case SwFieldIds::User: static_cast(rFieldTyp).SetDeleted( false ); break; case SwFieldIds::Dde: static_cast(rFieldTyp).SetDeleted( false ); break; default: break; } } void DocumentFieldsManager::PutValueToField(const SwPosition & rPos, const Any& rVal, sal_uInt16 nWhich) { Any aOldVal; SwField * pField = GetFieldAtPos(rPos); if (m_rDoc.GetIDocumentUndoRedo().DoesUndo() && pField->QueryValue(aOldVal, nWhich)) { SwUndo *const pUndo(new SwUndoFieldFromAPI(rPos, aOldVal, rVal, nWhich)); m_rDoc.GetIDocumentUndoRedo().AppendUndo(pUndo); } pField->PutValue(rVal, nWhich); } bool DocumentFieldsManager::UpdateField(SwTextField * pDstTextField, SwField & rSrcField, SwMsgPoolItem * pMsgHint, bool bUpdateFields) { OSL_ENSURE(pDstTextField, "no field to update!"); bool bTableSelBreak = false; SwFormatField * pDstFormatField = const_cast(&pDstTextField->GetFormatField()); SwField * pDstField = pDstFormatField->GetField(); SwFieldIds nFieldWhich = rSrcField.GetTyp()->Which(); SwNodeIndex aTableNdIdx(pDstTextField->GetTextNode()); if (pDstField->GetTyp()->Which() == rSrcField.GetTyp()->Which()) { if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) { SwPosition aPosition( pDstTextField->GetTextNode() ); aPosition.nContent = pDstTextField->GetStart(); SwUndo *const pUndo( new SwUndoFieldFromDoc( aPosition, *pDstField, rSrcField, pMsgHint, bUpdateFields) ); m_rDoc.GetIDocumentUndoRedo().AppendUndo(pUndo); } pDstFormatField->SetField(rSrcField.CopyField()); SwField* pNewField = pDstFormatField->GetField(); switch( nFieldWhich ) { case SwFieldIds::SetExp: case SwFieldIds::GetExp: case SwFieldIds::HiddenText: case SwFieldIds::HiddenPara: UpdateExpFields( pDstTextField, true ); break; case SwFieldIds::Table: { const SwTableNode* pTableNd = m_rDoc.IsIdxInTable(aTableNdIdx); if( pTableNd ) { SwTableFormulaUpdate aTableUpdate( &pTableNd-> GetTable() ); if (bUpdateFields) UpdateTableFields( &aTableUpdate ); else pNewField->GetTyp()->ModifyNotification(nullptr, &aTableUpdate); if (! bUpdateFields) bTableSelBreak = true; } } break; case SwFieldIds::Macro: if( bUpdateFields && pDstTextField->GetpTextNode() ) pDstTextField->GetpTextNode()-> ModifyNotification( nullptr, pDstFormatField ); break; case SwFieldIds::DatabaseName: case SwFieldIds::DbNextSet: case SwFieldIds::DbNumSet: case SwFieldIds::DbSetNumber: m_rDoc.ChgDBData(static_cast( pNewField)->GetRealDBData()); pNewField->GetTyp()->UpdateFields(); break; case SwFieldIds::Database: #if HAVE_FEATURE_DBCONNECTIVITY { // JP 10.02.96: call ChgValue, so that the style change sets the // ContentString correctly SwDBField* pDBField = static_cast(pNewField); if (pDBField->IsInitialized()) pDBField->ChgValue( pDBField->GetValue(), true ); pDBField->ClearInitialized(); pDBField->InitContent(); } #endif SAL_FALLTHROUGH; default: pDstFormatField->ModifyNotification( nullptr, pMsgHint ); } // The fields we can calculate here are being triggered for an update // here explicitly. if( nFieldWhich == SwFieldIds::User ) UpdateUsrFields(); } return bTableSelBreak; } /// Update reference and table fields void DocumentFieldsManager::UpdateRefFields() { for( auto pFieldType : *mpFieldTypes ) if( SwFieldIds::GetRef == pFieldType->Which() ) pFieldType->ModifyNotification( nullptr, nullptr ); } void DocumentFieldsManager::UpdateTableFields( SfxPoolItem* pHt ) { OSL_ENSURE( !pHt || RES_TABLEFML_UPDATE == pHt->Which(), "What MessageItem is &m_rDoc?" ); SwFieldType* pFieldType(nullptr); for (auto pFieldTypeTmp : *mpFieldTypes) { if( SwFieldIds::Table == pFieldTypeTmp->Which() ) { SwTableFormulaUpdate* pUpdateField = nullptr; if( pHt && RES_TABLEFML_UPDATE == pHt->Which() ) pUpdateField = static_cast(pHt); SwIterator aIter( *pFieldTypeTmp ); for( SwFormatField* pFormatField = aIter.First(); pFormatField; pFormatField = aIter.Next() ) { if( pFormatField->GetTextField() ) { SwTableField* pField = static_cast(pFormatField->GetField()); if( pUpdateField ) { // table where &m_rDoc field is located const SwTableNode* pTableNd; const SwTextNode& rTextNd = pFormatField->GetTextField()->GetTextNode(); if(!rTextNd.GetNodes().IsDocNodes()) continue; pTableNd = rTextNd.FindTableNode(); if (pTableNd == nullptr) continue; switch( pUpdateField->m_eFlags ) { case TBL_CALC: // re-set the value flag // JP 17.06.96: internal representation of all formulas // (reference to other table!!!) if( nsSwExtendedSubType::SUB_CMD & pField->GetSubType() ) pField->PtrToBoxNm( pUpdateField->m_pTable ); else pField->ChgValid( false ); break; case TBL_BOXNAME: // is &m_rDoc the wanted table? if( &pTableNd->GetTable() == pUpdateField->m_pTable ) // to the external representation pField->PtrToBoxNm( pUpdateField->m_pTable ); break; case TBL_BOXPTR: // to the internal representation // JP 17.06.96: internal representation on all formulas // (reference to other table!!!) pField->BoxNmToPtr( pUpdateField->m_pTable ); break; case TBL_RELBOXNAME: // is &m_rDoc the wanted table? if( &pTableNd->GetTable() == pUpdateField->m_pTable ) // to the relative representation pField->ToRelBoxNm( pUpdateField->m_pTable ); break; default: break; } } else // reset the value flag for all pField->ChgValid( false ); } } pFieldType = pFieldTypeTmp; break; } } // process all table box formulas const SfxPoolItem* pItem; sal_uInt32 nMaxItems = m_rDoc.GetAttrPool().GetItemCount2( RES_BOXATR_FORMULA ); for (sal_uInt32 i = 0; i < nMaxItems; ++i) { if( nullptr != (pItem = m_rDoc.GetAttrPool().GetItem2( RES_BOXATR_FORMULA, i ) ) && static_cast(pItem)->GetDefinedIn() ) { const_cast(static_cast(pItem))->ChangeState( pHt ); } } // all fields/boxes are now invalid, so we can start to calculate if( pHt && ( RES_TABLEFML_UPDATE != pHt->Which() || TBL_CALC != static_cast(pHt)->m_eFlags )) return ; std::unique_ptr pCalc; if( pFieldType ) { SwIterator aIter( *pFieldType ); for( SwFormatField* pFormatField = aIter.Last(); pFormatField; pFormatField = aIter.Previous() ) { // start calculation at the end // new fields are inserted at the beginning of the modify chain // that gives faster calculation on import // mba: do we really need &m_rDoc "optimization"? Is it still valid? if (!pFormatField->GetTextField()) continue; SwTableField *const pField(static_cast(pFormatField->GetField())); if (nsSwExtendedSubType::SUB_CMD & pField->GetSubType()) continue; // needs to be recalculated if( !pField->IsValid() ) { // table where &m_rDoc field is located const SwTextNode& rTextNd = pFormatField->GetTextField()->GetTextNode(); if( !rTextNd.GetNodes().IsDocNodes() ) continue; const SwTableNode* pTableNd = rTextNd.FindTableNode(); if( !pTableNd ) continue; // if &m_rDoc field is not in the to-be-updated table, skip it if( pHt && &pTableNd->GetTable() != static_cast(pHt)->m_pTable ) continue; if( !pCalc ) pCalc.reset(new SwCalc( m_rDoc )); // get the values of all SetExpression fields that are valid // until the table SwFrame* pFrame = nullptr; if( pTableNd->GetIndex() < m_rDoc.GetNodes().GetEndOfExtras().GetIndex() ) { // is in the special section, that's expensive! Point aPt; // return the first frame of the layout - Tab.Headline!! std::pair const tmp(aPt, true); pFrame = rTextNd.getLayoutFrame( m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, &tmp); if( pFrame ) { SwPosition aPos( *pTableNd ); if( GetBodyTextNode( m_rDoc, aPos, *pFrame ) ) FieldsToCalc( *pCalc, SetGetExpField( aPos.nNode, pFormatField->GetTextField(), &aPos.nContent )); else pFrame = nullptr; } } if( !pFrame ) { // create index to determine the TextNode SwNodeIndex aIdx( rTextNd ); FieldsToCalc( *pCalc, SetGetExpField( aIdx, pFormatField->GetTextField() )); } SwTableCalcPara aPara( *pCalc, pTableNd->GetTable() ); pField->CalcField( aPara ); if( aPara.IsStackOverflow() ) { bool const bResult = aPara.CalcWithStackOverflow(); if (bResult) { pField->CalcField( aPara ); } OSL_ENSURE(bResult, "the chained formula could no be calculated"); } pCalc->SetCalcError( SwCalcError::NONE ); } pFormatField->ModifyNotification( nullptr, pHt ); } } // calculate the formula at the boxes for (sal_uInt32 i = 0; i < nMaxItems; ++i ) { if( nullptr != (pItem = m_rDoc.GetAttrPool().GetItem2( RES_BOXATR_FORMULA, i ) ) && static_cast(pItem)->GetDefinedIn() && !static_cast(pItem)->IsValid() ) { SwTableBoxFormula* pFormula = const_cast(static_cast(pItem)); SwTableBox* pBox = pFormula->GetTableBox(); if( pBox && pBox->GetSttNd() && pBox->GetSttNd()->GetNodes().IsDocNodes() ) { const SwTableNode* pTableNd = pBox->GetSttNd()->FindTableNode(); if( !pHt || &pTableNd->GetTable() == static_cast(pHt)->m_pTable ) { double nValue; if( !pCalc ) pCalc.reset(new SwCalc( m_rDoc )); // get the values of all SetExpression fields that are valid // until the table SwFrame* pFrame = nullptr; if( pTableNd->GetIndex() < m_rDoc.GetNodes().GetEndOfExtras().GetIndex() ) { // is in the special section, that's expensive! Point aPt; // return the first frame of the layout - Tab.Headline!! SwNodeIndex aCNdIdx( *pTableNd, +2 ); SwContentNode* pCNd = aCNdIdx.GetNode().GetContentNode(); if( !pCNd ) pCNd = m_rDoc.GetNodes().GoNext( &aCNdIdx ); std::pair const tmp(aPt, true); if (pCNd && nullptr != (pFrame = pCNd->getLayoutFrame( m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, &tmp))) { SwPosition aPos( *pCNd ); if( GetBodyTextNode( m_rDoc, aPos, *pFrame ) ) FieldsToCalc( *pCalc, SetGetExpField( aPos.nNode )); else pFrame = nullptr; } } if( !pFrame ) { // create index to determine the TextNode SwNodeIndex aIdx( *pTableNd ); FieldsToCalc( *pCalc, SetGetExpField( aIdx )); } SwTableCalcPara aPara( *pCalc, pTableNd->GetTable() ); pFormula->Calc( aPara, nValue ); if( aPara.IsStackOverflow() ) { bool const bResult = aPara.CalcWithStackOverflow(); if (bResult) { pFormula->Calc( aPara, nValue ); } OSL_ENSURE(bResult, "the chained formula could no be calculated"); } SwFrameFormat* pFormat = pBox->ClaimFrameFormat(); SfxItemSet aTmp( m_rDoc.GetAttrPool(), svl::Items{} ); if( pCalc->IsCalcError() ) nValue = DBL_MAX; aTmp.Put( SwTableBoxValue( nValue )); if( SfxItemState::SET != pFormat->GetItemState( RES_BOXATR_FORMAT )) aTmp.Put( SwTableBoxNumFormat( 0 )); pFormat->SetFormatAttr( aTmp ); pCalc->SetCalcError( SwCalcError::NONE ); } } } } } void DocumentFieldsManager::UpdateExpFields( SwTextField* pUpdateField, bool bUpdRefFields ) { if( IsExpFieldsLocked() || m_rDoc.IsInReading() ) return; bool bOldInUpdateFields = mpUpdateFields->IsInUpdateFields(); mpUpdateFields->SetInUpdateFields( true ); mpUpdateFields->MakeFieldList( m_rDoc, true, GETFLD_ALL ); mbNewFieldLst = false; if( mpUpdateFields->GetSortLst()->empty() ) { if( bUpdRefFields ) UpdateRefFields(); mpUpdateFields->SetInUpdateFields( bOldInUpdateFields ); mpUpdateFields->SetFieldsDirty( false ); return ; } SwFieldIds nWhich; // Hash table for all string replacements is filled on-the-fly. // Try to fabricate an uneven number. const SwFieldTypes::size_type nHashSize {(( mpFieldTypes->size() / 7 ) + 1 ) * 7}; const sal_uInt16 nStrFormatCnt = static_cast(nHashSize); OSL_ENSURE( nStrFormatCnt == nHashSize, "Downcasting to sal_uInt16 lost information!" ); SwHashTable aHashStrTable(nStrFormatCnt); { const SwFieldType* pFieldType; // process separately: for( auto n = mpFieldTypes->size(); n; ) switch( ( pFieldType = (*mpFieldTypes)[ --n ] )->Which() ) { case SwFieldIds::User: { // Entry present? sal_uInt16 nPos; const OUString& rNm = pFieldType->GetName(); OUString sExpand(const_cast(static_cast(pFieldType))->Expand(nsSwGetSetExpType::GSE_STRING, 0, LANGUAGE_SYSTEM)); SwHash* pFnd = aHashStrTable.Find( rNm, &nPos ); if( pFnd ) // modify entry in the hash table static_cast(pFnd)->aSetStr = sExpand; else // insert the new entry aHashStrTable[nPos].reset( new HashStr( rNm, sExpand, aHashStrTable[nPos].release() ) ); } break; case SwFieldIds::SetExp: const_cast(static_cast(pFieldType))->SetOutlineChgNd( nullptr ); break; default: break; } } // The array is filled with all fields; start calculation. SwCalc aCalc( m_rDoc ); #if HAVE_FEATURE_DBCONNECTIVITY OUString sDBNumNm( SwFieldType::GetTypeStr( TYP_DBSETNUMBERFLD ) ); // already set the current record number SwDBManager* pMgr = m_rDoc.GetDBManager(); pMgr->CloseAll( false ); SvtSysLocale aSysLocale; const LocaleDataWrapper* pLclData = aSysLocale.GetLocaleDataPtr(); const LanguageType nLang = pLclData->getLanguageTag().getLanguageType(); bool bCanFill = pMgr->FillCalcWithMergeData( m_rDoc.GetNumberFormatter(), nLang, aCalc ); #endif // Make sure we don't hide all sections, which would lead to a crash. First, count how many of them do we have. int nShownSections = 0; { SwSectionFormats& rSectFormats = m_rDoc.GetSections(); for( SwSectionFormats::size_type n = 0; nGetSection(); // count only visible sections if ( pSect && !pSect->CalcHiddenFlag()) nShownSections++; } } for( SetGetExpFields::const_iterator it = mpUpdateFields->GetSortLst()->begin(); it != mpUpdateFields->GetSortLst()->end(); ++it ) { SwSection* pSect = const_cast((*it)->GetSection()); if( pSect ) { SwSbxValue aValue = aCalc.Calculate( pSect->GetCondition() ); if(!aValue.IsVoidValue()) { // Do we want to hide this one? bool bHide = aValue.GetBool(); if (bHide && !pSect->IsCondHidden()) { // This section will be hidden, but it wasn't before if (nShownSections == 1) { // Is the last node part of a section? SwPaM aPam(m_rDoc.GetNodes()); aPam.Move(fnMoveForward, GoInDoc); if (aPam.Start()->nNode.GetNode().StartOfSectionNode()->IsSectionNode()) { // This would be the last section, so set its condition to false, and avoid hiding it. pSect->SetCondition("0"); bHide = false; } } nShownSections--; } pSect->SetCondHidden( bHide ); } continue; } SwTextField* pTextField = const_cast((*it)->GetTextField()); if( !pTextField ) { OSL_ENSURE( false, "what's wrong now'" ); continue; } SwFormatField* pFormatField = const_cast(&pTextField->GetFormatField()); const SwField* pField = pFormatField->GetField(); switch( nWhich = pField->GetTyp()->Which() ) { case SwFieldIds::HiddenText: { SwHiddenTextField* pHField = const_cast(static_cast(pField)); SwSbxValue aValue = aCalc.Calculate( pHField->GetPar1() ); bool bValue = !aValue.GetBool(); if(!aValue.IsVoidValue()) { pHField->SetValue( bValue ); // evaluate field pHField->Evaluate(&m_rDoc); } } break; case SwFieldIds::HiddenPara: { SwHiddenParaField* pHPField = const_cast(static_cast(pField)); SwSbxValue aValue = aCalc.Calculate( pHPField->GetPar1() ); bool bValue = aValue.GetBool(); if(!aValue.IsVoidValue()) pHPField->SetHidden( bValue ); } break; case SwFieldIds::DbSetNumber: #if HAVE_FEATURE_DBCONNECTIVITY { const_cast(static_cast(pField))->Evaluate(&m_rDoc); aCalc.VarChange( sDBNumNm, static_cast(pField)->GetSetNumber()); pField->ExpandField(m_rDoc.IsClipBoard()); } #endif break; case SwFieldIds::DbNextSet: case SwFieldIds::DbNumSet: #if HAVE_FEATURE_DBCONNECTIVITY { UpdateDBNumFields( *const_cast(static_cast(pField)), aCalc ); if( bCanFill ) bCanFill = pMgr->FillCalcWithMergeData( m_rDoc.GetNumberFormatter(), nLang, aCalc ); } #endif break; case SwFieldIds::Database: { #if HAVE_FEATURE_DBCONNECTIVITY // evaluate field const_cast(static_cast(pField))->Evaluate(); SwDBData aTmpDBData(static_cast(pField)->GetDBData()); if( pMgr->IsDataSourceOpen(aTmpDBData.sDataSource, aTmpDBData.sCommand, false)) aCalc.VarChange( sDBNumNm, pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType)); const OUString& rName = pField->GetTyp()->GetName(); // Add entry to hash table // Entry present? sal_uInt16 nPos; HashStr* pFnd = aHashStrTable.Find( rName, &nPos ); OUString const value(pField->ExpandField(m_rDoc.IsClipBoard())); if( pFnd ) { // Modify entry in the hash table pFnd->aSetStr = value; } else { // insert new entry aHashStrTable[nPos].reset( new HashStr( rName, value, aHashStrTable[nPos].release()) ); } #endif } break; case SwFieldIds::GetExp: case SwFieldIds::SetExp: { if( nsSwGetSetExpType::GSE_STRING & pField->GetSubType() ) // replace String { if( SwFieldIds::GetExp == nWhich ) { SwGetExpField* pGField = const_cast(static_cast(pField)); if( (!pUpdateField || pUpdateField == pTextField ) && pGField->IsInBodyText() ) { OUString aNew = LookString( aHashStrTable, pGField->GetFormula() ); pGField->ChgExpStr( aNew ); } } else { SwSetExpField* pSField = const_cast(static_cast(pField)); // is the "formula" a field? OUString aNew = LookString( aHashStrTable, pSField->GetFormula() ); if( aNew.isEmpty() ) // nothing found then the formula is the new value aNew = pSField->GetFormula(); // only update one field if( !pUpdateField || pUpdateField == pTextField ) pSField->ChgExpStr( aNew ); // lookup the field's name aNew = static_cast(pSField->GetTyp())->GetSetRefName(); // Entry present? sal_uInt16 nPos; HashStr* pFnd = aHashStrTable.Find( aNew, &nPos ); if( pFnd ) // Modify entry in the hash table pFnd->aSetStr = pSField->GetExpStr(); else { // insert new entry aHashStrTable[nPos].reset( new HashStr( aNew, pSField->GetExpStr(), aHashStrTable[nPos].release() ) ); pFnd = aHashStrTable[nPos].get(); } // Extension for calculation with Strings SwSbxValue aValue; aValue.PutString( pFnd->aSetStr ); aCalc.VarChange( aNew, aValue ); } } else // recalculate formula { if( SwFieldIds::GetExp == nWhich ) { SwGetExpField* pGField = const_cast(static_cast(pField)); if( (!pUpdateField || pUpdateField == pTextField ) && pGField->IsInBodyText() ) { SwSbxValue aValue = aCalc.Calculate( pGField->GetFormula()); if(!aValue.IsVoidValue()) pGField->SetValue(aValue.GetDouble() ); } } else { SwSetExpField* pSField = const_cast(static_cast(pField)); SwSetExpFieldType* pSFieldTyp = static_cast(pField->GetTyp()); OUString aNew = pSFieldTyp->GetName(); SwNode* pSeqNd = nullptr; if( pSField->IsSequenceField() ) { const sal_uInt8 nLvl = pSFieldTyp->GetOutlineLvl(); if( MAXLEVEL > nLvl ) { // test if the Number needs to be updated pSeqNd = m_rDoc.GetNodes()[ (*it)->GetNode() ]; const SwTextNode* pOutlNd = pSeqNd-> FindOutlineNodeOfLevel( nLvl ); if( pSFieldTyp->GetOutlineChgNd() != pOutlNd ) { pSFieldTyp->SetOutlineChgNd( pOutlNd ); aCalc.VarChange( aNew, 0 ); } } } aNew += "="; aNew += pSField->GetFormula(); SwSbxValue aValue = aCalc.Calculate( aNew ); double nErg = aValue.GetDouble(); // only update one field if( !aValue.IsVoidValue() && (!pUpdateField || pUpdateField == pTextField) ) { pSField->SetValue( nErg ); if( pSeqNd ) pSFieldTyp->SetChapter( *pSField, *pSeqNd ); } } } } break; default: break; } // switch pFormatField->ModifyNotification( nullptr, nullptr ); // trigger formatting if( pUpdateField == pTextField ) // if only &m_rDoc one is updated { if( SwFieldIds::GetExp == nWhich || // only GetField or SwFieldIds::HiddenText == nWhich || // HiddenText? SwFieldIds::HiddenPara == nWhich) // HiddenParaField? break; // quit pUpdateField = nullptr; // update all from here on } } #if HAVE_FEATURE_DBCONNECTIVITY pMgr->CloseAll(false); #endif // update reference fields if( bUpdRefFields ) UpdateRefFields(); mpUpdateFields->SetInUpdateFields( bOldInUpdateFields ); mpUpdateFields->SetFieldsDirty( false ); } /// Insert field type that was marked as deleted void DocumentFieldsManager::UpdateUsrFields() { SwCalc* pCalc = nullptr; for( SwFieldTypes::size_type i = INIT_FLDTYPES; i < mpFieldTypes->size(); ++i ) { const SwFieldType* pFieldType; if( SwFieldIds::User == ( pFieldType = (*mpFieldTypes)[i] )->Which() ) { if( !pCalc ) pCalc = new SwCalc( m_rDoc ); const_cast(static_cast(pFieldType))->GetValue( *pCalc ); } } if( pCalc ) { delete pCalc; m_rDoc.getIDocumentState().SetModified(); } } sal_Int32 DocumentFieldsManager::GetRecordsPerDocument() const { sal_Int32 nRecords = 1; mpUpdateFields->MakeFieldList( m_rDoc, true, GETFLD_ALL ); if( mpUpdateFields->GetSortLst()->empty() ) return nRecords; for( SetGetExpFields::const_iterator it = mpUpdateFields->GetSortLst()->begin(); it != mpUpdateFields->GetSortLst()->end(); ++it ) { const SwTextField *pTextField = (*it)->GetTextField(); if( !pTextField ) continue; const SwFormatField &pFormatField = pTextField->GetFormatField(); const SwField* pField = pFormatField.GetField(); switch( pField->GetTyp()->Which() ) { case SwFieldIds::DbNextSet: case SwFieldIds::DbNumSet: nRecords++; break; default: break; } } return nRecords; } void DocumentFieldsManager::UpdatePageFields( SfxPoolItem* pMsgHint ) { for( SwFieldTypes::size_type i = 0; i < INIT_FLDTYPES; ++i ) { SwFieldType* pFieldType = (*mpFieldTypes)[ i ]; switch( pFieldType->Which() ) { case SwFieldIds::PageNumber: case SwFieldIds::Chapter: case SwFieldIds::GetExp: case SwFieldIds::RefPageGet: pFieldType->ModifyNotification( nullptr, pMsgHint ); break; case SwFieldIds::DocStat: pFieldType->ModifyNotification( nullptr, nullptr ); break; default: break; } } SetNewFieldLst(true); } void DocumentFieldsManager::LockExpFields() { ++mnLockExpField; } void DocumentFieldsManager::UnlockExpFields() { assert(mnLockExpField != 0); if( mnLockExpField ) --mnLockExpField; } bool DocumentFieldsManager::IsExpFieldsLocked() const { return 0 != mnLockExpField; } SwDocUpdateField& DocumentFieldsManager::GetUpdateFields() const { return *mpUpdateFields; } bool DocumentFieldsManager::SetFieldsDirty( bool b, const SwNode* pChk, sal_uLong nLen ) { // See if the supplied nodes actually contain fields. // If they don't, the flag doesn't need to be changed. bool bFieldsFnd = false; if( b && pChk && !GetUpdateFields().IsFieldsDirty() && !m_rDoc.IsInDtor() // ?? what's up with Undo, this is also wanted there! /*&& &pChk->GetNodes() == &GetNodes()*/ ) { b = false; if( !nLen ) ++nLen; sal_uLong nStt = pChk->GetIndex(); const SwNodes& rNds = pChk->GetNodes(); while( nLen-- ) { const SwTextNode* pTNd = rNds[ nStt++ ]->GetTextNode(); if( pTNd ) { if( pTNd->GetAttrOutlineLevel() != 0 ) // update chapter fields b = true; else if( pTNd->GetpSwpHints() && pTNd->GetSwpHints().Count() ) { const size_t nEnd = pTNd->GetSwpHints().Count(); for( size_t n = 0 ; n < nEnd; ++n ) { const SwTextAttr* pAttr = pTNd->GetSwpHints().Get(n); if ( pAttr->Which() == RES_TXTATR_FIELD ) { b = true; break; } } } if( b ) break; } } bFieldsFnd = b; } GetUpdateFields().SetFieldsDirty( b ); return bFieldsFnd; } void DocumentFieldsManager::SetFixFields( const DateTime* pNewDateTime ) { bool bIsModified = m_rDoc.getIDocumentState().IsModified(); sal_Int32 nDate; sal_Int64 nTime; if( pNewDateTime ) { nDate = pNewDateTime->GetDate(); nTime = pNewDateTime->GetTime(); } else { DateTime aDateTime( DateTime::SYSTEM ); nDate = aDateTime.GetDate(); nTime = aDateTime.GetTime(); } SwFieldIds const aTypes[] { /*0*/ SwFieldIds::DocInfo, /*1*/ SwFieldIds::Author, /*2*/ SwFieldIds::ExtUser, /*3*/ SwFieldIds::Filename, /*4*/ SwFieldIds::DateTime }; // MUST be at the end! for(SwFieldIds aType : aTypes) { SwFieldType* pFieldType = GetSysFieldType( aType ); SwIterator aIter( *pFieldType ); for( SwFormatField* pFormatField = aIter.First(); pFormatField; pFormatField = aIter.Next() ) { if( pFormatField && pFormatField->GetTextField() ) { bool bChgd = false; switch( aType ) { case SwFieldIds::DocInfo: if( static_cast(pFormatField->GetField())->IsFixed() ) { bChgd = true; SwDocInfoField* pDocInfField = static_cast(pFormatField->GetField()); pDocInfField->SetExpansion( static_cast( pDocInfField->GetTyp())->Expand( pDocInfField->GetSubType(), pDocInfField->GetFormat(), pDocInfField->GetLanguage(), pDocInfField->GetName() ) ); } break; case SwFieldIds::Author: if( static_cast(pFormatField->GetField())->IsFixed() ) { bChgd = true; SwAuthorField* pAuthorField = static_cast(pFormatField->GetField()); pAuthorField->SetExpansion( SwAuthorFieldType::Expand( pAuthorField->GetFormat() ) ); } break; case SwFieldIds::ExtUser: if( static_cast(pFormatField->GetField())->IsFixed() ) { bChgd = true; SwExtUserField* pExtUserField = static_cast(pFormatField->GetField()); pExtUserField->SetExpansion( SwExtUserFieldType::Expand(pExtUserField->GetSubType()) ); } break; case SwFieldIds::DateTime: if( static_cast(pFormatField->GetField())->IsFixed() ) { bChgd = true; static_cast(pFormatField->GetField())->SetDateTime( DateTime(Date(nDate), tools::Time(nTime)) ); } break; case SwFieldIds::Filename: if( static_cast(pFormatField->GetField())->IsFixed() ) { bChgd = true; SwFileNameField* pFileNameField = static_cast(pFormatField->GetField()); pFileNameField->SetExpansion( static_cast( pFileNameField->GetTyp())->Expand( pFileNameField->GetFormat() ) ); } break; default: break; } // Trigger formatting if( bChgd ) pFormatField->ModifyNotification( nullptr, nullptr ); } } } if( !bIsModified ) m_rDoc.getIDocumentState().ResetModified(); } void DocumentFieldsManager::FieldsToCalc( SwCalc& rCalc, const SetGetExpField& rToThisField ) { // create the sorted list of all SetFields mpUpdateFields->MakeFieldList( m_rDoc, mbNewFieldLst, GETFLD_CALC ); mbNewFieldLst = false; #if !HAVE_FEATURE_DBCONNECTIVITY SwDBManager* pMgr = NULL; #else SwDBManager* pMgr = m_rDoc.GetDBManager(); pMgr->CloseAll(false); #endif if( !mpUpdateFields->GetSortLst()->empty() ) { SetGetExpFields::const_iterator const itLast = mpUpdateFields->GetSortLst()->upper_bound( const_cast(&rToThisField)); for( SetGetExpFields::const_iterator it = mpUpdateFields->GetSortLst()->begin(); it != itLast; ++it ) lcl_CalcField( m_rDoc, rCalc, **it, pMgr ); } #if HAVE_FEATURE_DBCONNECTIVITY pMgr->CloseAll(false); #endif } void DocumentFieldsManager::FieldsToCalc( SwCalc& rCalc, sal_uLong nLastNd, sal_uInt16 nLastCnt ) { // create the sorted list of all SetFields mpUpdateFields->MakeFieldList( m_rDoc, mbNewFieldLst, GETFLD_CALC ); mbNewFieldLst = false; #if !HAVE_FEATURE_DBCONNECTIVITY SwDBManager* pMgr = NULL; #else SwDBManager* pMgr = m_rDoc.GetDBManager(); pMgr->CloseAll(false); #endif for( SetGetExpFields::const_iterator it = mpUpdateFields->GetSortLst()->begin(); it != mpUpdateFields->GetSortLst()->end() && ( (*it)->GetNode() < nLastNd || ( (*it)->GetNode() == nLastNd && (*it)->GetContent() <= nLastCnt ) ); ++it ) { lcl_CalcField( m_rDoc, rCalc, **it, pMgr ); } #if HAVE_FEATURE_DBCONNECTIVITY pMgr->CloseAll(false); #endif } void DocumentFieldsManager::FieldsToExpand( SwHashTable & rHashTable, const SetGetExpField& rToThisField ) { // create the sorted list of all SetFields mpUpdateFields->MakeFieldList( m_rDoc, mbNewFieldLst, GETFLD_EXPAND ); mbNewFieldLst = false; // Hash table for all string replacements is filled on-the-fly. // Try to fabricate an uneven number. sal_uInt16 nTableSize = (( mpUpdateFields->GetSortLst()->size() / 7 ) + 1 ) * 7; rHashTable.resize(nTableSize); SetGetExpFields::const_iterator const itLast = mpUpdateFields->GetSortLst()->upper_bound( const_cast(&rToThisField)); for( SetGetExpFields::const_iterator it = mpUpdateFields->GetSortLst()->begin(); it != itLast; ++it ) { const SwTextField* pTextField = (*it)->GetTextField(); if( !pTextField ) continue; const SwField* pField = pTextField->GetFormatField().GetField(); switch( pField->GetTyp()->Which() ) { case SwFieldIds::SetExp: if( nsSwGetSetExpType::GSE_STRING & pField->GetSubType() ) { // set the new value in the hash table // is the formula a field? SwSetExpField* pSField = const_cast(static_cast(pField)); OUString aNew = LookString( rHashTable, pSField->GetFormula() ); if( aNew.isEmpty() ) // nothing found, then the formula is aNew = pSField->GetFormula(); // the new value // #i3141# - update expression of field as in method // for string/text fields pSField->ChgExpStr( aNew ); // look up the field's name aNew = static_cast(pSField->GetTyp())->GetSetRefName(); // Entry present? sal_uInt16 nPos; SwHash* pFnd = rHashTable.Find( aNew, &nPos ); if( pFnd ) // modify entry in the hash table static_cast(pFnd)->aSetStr = pSField->GetExpStr(); else // insert the new entry rHashTable[nPos].reset( new HashStr( aNew, pSField->GetExpStr(), rHashTable[nPos].release() ) ); } break; case SwFieldIds::Database: { const OUString& rName = pField->GetTyp()->GetName(); // Insert entry in the hash table // Entry present? sal_uInt16 nPos; HashStr* pFnd = rHashTable.Find( rName, &nPos ); OUString const value(pField->ExpandField(m_rDoc.IsClipBoard())); if( pFnd ) { // modify entry in the hash table pFnd->aSetStr = value; } else { // insert the new entry rHashTable[nPos].reset( new HashStr( rName, value, rHashTable[nPos].release()) ); } } break; default: break; } } } bool DocumentFieldsManager::IsNewFieldLst() const { return mbNewFieldLst; } void DocumentFieldsManager::SetNewFieldLst(bool bFlag) { mbNewFieldLst = bFlag; } void DocumentFieldsManager::InsDelFieldInFieldLst( bool bIns, const SwTextField& rField ) { if( !mbNewFieldLst || !m_rDoc.IsInDtor() ) mpUpdateFields->InsDelFieldInFieldLst( bIns, rField ); } SwField * DocumentFieldsManager::GetFieldAtPos(const SwPosition & rPos) { SwTextField * const pAttr = GetTextFieldAtPos(rPos); return pAttr ? const_cast( pAttr->GetFormatField().GetField() ) : nullptr; } SwTextField * DocumentFieldsManager::GetTextFieldAtPos(const SwPosition & rPos) { SwTextNode * const pNode = rPos.nNode.GetNode().GetTextNode(); return (pNode != nullptr) ? pNode->GetFieldTextAttrAt( rPos.nContent.GetIndex(), true ) : nullptr; } /// @note For simplicity assume that all field types have updatable contents so /// optimization currently only available when no fields exist. bool DocumentFieldsManager::containsUpdatableFields() { for (auto pFieldType : *mpFieldTypes) { SwIterator aIter(*pFieldType); if (aIter.First()) return true; } return false; } /// Remove all unreferenced field types of a document void DocumentFieldsManager::GCFieldTypes() { for( auto n = mpFieldTypes->size(); n > INIT_FLDTYPES; ) if( !(*mpFieldTypes)[ --n ]->HasWriterListeners() ) RemoveFieldType( n ); } void DocumentFieldsManager::InitFieldTypes() // is being called by the CTOR { // Field types mpFieldTypes->push_back( new SwDateTimeFieldType(&m_rDoc) ); mpFieldTypes->push_back( new SwChapterFieldType ); mpFieldTypes->push_back( new SwPageNumberFieldType ); mpFieldTypes->push_back( new SwAuthorFieldType ); mpFieldTypes->push_back( new SwFileNameFieldType(&m_rDoc) ); mpFieldTypes->push_back( new SwDBNameFieldType(&m_rDoc) ); mpFieldTypes->push_back( new SwGetExpFieldType(&m_rDoc) ); mpFieldTypes->push_back( new SwGetRefFieldType( &m_rDoc ) ); mpFieldTypes->push_back( new SwHiddenTextFieldType ); mpFieldTypes->push_back( new SwPostItFieldType(&m_rDoc) ); mpFieldTypes->push_back( new SwDocStatFieldType(&m_rDoc) ); mpFieldTypes->push_back( new SwDocInfoFieldType(&m_rDoc) ); mpFieldTypes->push_back( new SwInputFieldType( &m_rDoc ) ); mpFieldTypes->push_back( new SwTableFieldType( &m_rDoc ) ); mpFieldTypes->push_back( new SwMacroFieldType(&m_rDoc) ); mpFieldTypes->push_back( new SwHiddenParaFieldType ); mpFieldTypes->push_back( new SwDBNextSetFieldType ); mpFieldTypes->push_back( new SwDBNumSetFieldType ); mpFieldTypes->push_back( new SwDBSetNumberFieldType ); mpFieldTypes->push_back( new SwTemplNameFieldType(&m_rDoc) ); mpFieldTypes->push_back( new SwTemplNameFieldType(&m_rDoc) ); mpFieldTypes->push_back( new SwExtUserFieldType ); mpFieldTypes->push_back( new SwRefPageSetFieldType ); mpFieldTypes->push_back( new SwRefPageGetFieldType( &m_rDoc ) ); mpFieldTypes->push_back( new SwJumpEditFieldType( &m_rDoc ) ); mpFieldTypes->push_back( new SwScriptFieldType( &m_rDoc ) ); mpFieldTypes->push_back( new SwCombinedCharFieldType ); mpFieldTypes->push_back( new SwDropDownFieldType ); // Types have to be at the end! // We expect &m_rDoc in the InsertFieldType! // MIB 14.04.95: In Sw3StringPool::Setup (sw3imp.cxx) and // lcl_sw3io_InSetExpField (sw3field.cxx) now also mpFieldTypes->push_back( new SwSetExpFieldType(&m_rDoc, SwResId(STR_POOLCOLL_LABEL_ABB), nsSwGetSetExpType::GSE_SEQ) ); mpFieldTypes->push_back( new SwSetExpFieldType(&m_rDoc, SwResId(STR_POOLCOLL_LABEL_TABLE), nsSwGetSetExpType::GSE_SEQ) ); mpFieldTypes->push_back( new SwSetExpFieldType(&m_rDoc, SwResId(STR_POOLCOLL_LABEL_FRAME), nsSwGetSetExpType::GSE_SEQ) ); mpFieldTypes->push_back( new SwSetExpFieldType(&m_rDoc, SwResId(STR_POOLCOLL_LABEL_DRAWING), nsSwGetSetExpType::GSE_SEQ) ); mpFieldTypes->push_back( new SwSetExpFieldType(&m_rDoc, SwResId(STR_POOLCOLL_LABEL_FIGURE), nsSwGetSetExpType::GSE_SEQ) ); assert( mpFieldTypes->size() == INIT_FLDTYPES ); } void DocumentFieldsManager::ClearFieldTypes() { for(SwFieldTypes::const_iterator it = mpFieldTypes->begin() + INIT_FLDTYPES; it != mpFieldTypes->end(); ++it) delete *it; mpFieldTypes->erase( mpFieldTypes->begin() + INIT_FLDTYPES, mpFieldTypes->end() ); } void DocumentFieldsManager::UpdateDBNumFields( SwDBNameInfField& rDBField, SwCalc& rCalc ) { #if !HAVE_FEATURE_DBCONNECTIVITY (void) rDBField; (void) rCalc; #else SwDBManager* pMgr = m_rDoc.GetDBManager(); SwFieldIds nFieldType = rDBField.Which(); bool bPar1 = rCalc.Calculate( rDBField.GetPar1() ).GetBool(); if( SwFieldIds::DbNextSet == nFieldType ) static_cast(rDBField).SetCondValid( bPar1 ); else static_cast(rDBField).SetCondValid( bPar1 ); if( !rDBField.GetRealDBData().sDataSource.isEmpty() ) { // Edit a certain database if( SwFieldIds::DbNextSet == nFieldType ) static_cast(rDBField).Evaluate(&m_rDoc); else static_cast(rDBField).Evaluate(&m_rDoc); SwDBData aTmpDBData( rDBField.GetDBData(&m_rDoc) ); if( pMgr->OpenDataSource( aTmpDBData.sDataSource, aTmpDBData.sCommand )) rCalc.VarChange( lcl_GetDBVarName( m_rDoc, rDBField), pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType) ); } else { OSL_FAIL("TODO: what should happen with unnamed DBFields?"); } #endif } DocumentFieldsManager::~DocumentFieldsManager() { mpUpdateFields.reset(); mpFieldTypes.reset(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */