/************************************************************** * * 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 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sw.hxx" #include #include #include #include #ifndef _SVSTDARR_HXX #define _SVSTDARR_ULONGS #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // fuer Expression-Felder #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // fuer InitFldTypes #include #include "switerator.hxx" using namespace ::com::sun::star::uno; extern sal_Bool IsFrameBehind( const SwTxtNode& rMyNd, sal_uInt16 nMySttPos, const SwTxtNode& rBehindNd, sal_uInt16 nSttPos ); SV_IMPL_OP_PTRARR_SORT( _SetGetExpFlds, _SetGetExpFldPtr ) /*-------------------------------------------------------------------- Beschreibung: Feldtypen einfuegen --------------------------------------------------------------------*/ /* * Implementierung der Feldfunktionen am Doc * Return immer einen gueltigen Pointer auf den Typ. Wenn er also neu * zugefuegt oder schon vorhanden ist. */ SwFieldType* SwDoc::InsertFldType(const SwFieldType &rFldTyp) { sal_uInt16 nSize = pFldTypes->Count(), nFldWhich = rFldTyp.Which(); sal_uInt16 i = INIT_FLDTYPES; switch( nFldWhich ) { case RES_SETEXPFLD: //JP 29.01.96: SequenceFelder beginnen aber bei INIT_FLDTYPES - 3!! // Sonst gibt es doppelte Nummernkreise!! //MIB 14.03.95: Ab sofort verlaesst sich auch der SW3-Reader //beim Aufbau der String-Pools und beim Einlesen von SetExp-Feldern //hierauf if( nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType&)rFldTyp).GetType() ) i -= INIT_SEQ_FLDTYPES; // kein break; case RES_DBFLD: case RES_USERFLD: case RES_DDEFLD: { const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore(); String sFldNm( rFldTyp.GetName() ); for( ; i < nSize; ++i ) if( nFldWhich == (*pFldTypes)[i]->Which() && rSCmp.isEqual( sFldNm, (*pFldTypes)[i]->GetName() )) return (*pFldTypes)[i]; } break; case RES_AUTHORITY: for( ; i < nSize; ++i ) if( nFldWhich == (*pFldTypes)[i]->Which() ) return (*pFldTypes)[i]; break; default: for( i = 0; i < nSize; ++i ) if( nFldWhich == (*pFldTypes)[i]->Which() ) return (*pFldTypes)[i]; } SwFieldType* pNew = rFldTyp.Copy(); switch( nFldWhich ) { case RES_DDEFLD: ((SwDDEFieldType*)pNew)->SetDoc( this ); break; case RES_DBFLD: case RES_TABLEFLD: case RES_DATETIMEFLD: case RES_GETEXPFLD: ((SwValueFieldType*)pNew)->SetDoc( this ); break; case RES_USERFLD: case RES_SETEXPFLD: ((SwValueFieldType*)pNew)->SetDoc( this ); // JP 29.07.96: opt. FeldListe fuer den Calculator vorbereiten: pUpdtFlds->InsertFldType( *pNew ); break; case RES_AUTHORITY : ((SwAuthorityFieldType*)pNew)->SetDoc( this ); break; } pFldTypes->Insert( pNew, nSize ); SetModified(); return (*pFldTypes)[ nSize ]; } void SwDoc::InsDeletedFldType( SwFieldType& rFldTyp ) { // der FeldTyp wurde als geloescht gekennzeichnet und aus dem // Array entfernt. Nun muss man nach diesem wieder suchen. // - Ist der nicht vorhanden, dann kann er eingefuegt werden. // - Wird genau der gleiche Typ gefunden, dann muss der geloeschte // einen anderen Namen erhalten. sal_uInt16 nSize = pFldTypes->Count(), nFldWhich = rFldTyp.Which(); sal_uInt16 i = INIT_FLDTYPES; ASSERT( RES_SETEXPFLD == nFldWhich || RES_USERFLD == nFldWhich || RES_DDEFLD == nFldWhich, "Falscher FeldTyp" ); const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore(); const String& rFldNm = rFldTyp.GetName(); SwFieldType* pFnd; for( ; i < nSize; ++i ) if( nFldWhich == (pFnd = (*pFldTypes)[i])->Which() && rSCmp.isEqual( rFldNm, pFnd->GetName() ) ) { // neuen Namen suchen sal_uInt16 nNum = 1; do { String sSrch( rFldNm ); sSrch.Append( String::CreateFromInt32( nNum )); for( i = INIT_FLDTYPES; i < nSize; ++i ) if( nFldWhich == (pFnd = (*pFldTypes)[i])->Which() && rSCmp.isEqual( sSrch, pFnd->GetName() ) ) break; if( i >= nSize ) // nicht gefunden { ((String&)rFldNm) = sSrch; break; // raus aus der While-Schleife } ++nNum; } while( sal_True ); break; } // nicht gefunden, also eintragen und Flag loeschen pFldTypes->Insert( &rFldTyp, nSize ); switch( nFldWhich ) { case RES_SETEXPFLD: ((SwSetExpFieldType&)rFldTyp).SetDeleted( sal_False ); break; case RES_USERFLD: ((SwUserFieldType&)rFldTyp).SetDeleted( sal_False ); break; case RES_DDEFLD: ((SwDDEFieldType&)rFldTyp).SetDeleted( sal_False ); break; } } /*-------------------------------------------------------------------- Beschreibung: Feldtypen loeschen --------------------------------------------------------------------*/ void SwDoc::RemoveFldType(sal_uInt16 nFld) { ASSERT( INIT_FLDTYPES <= nFld, "keine InitFields loeschen" ); /* * Abheangige Felder vorhanden -> ErrRaise */ sal_uInt16 nSize = pFldTypes->Count(); if(nFld < nSize) { SwFieldType* pTmp = (*pFldTypes)[nFld]; // JP 29.07.96: opt. FeldListe fuer den Calculator vorbereiten: sal_uInt16 nWhich = pTmp->Which(); switch( nWhich ) { case RES_SETEXPFLD: case RES_USERFLD: pUpdtFlds->RemoveFldType( *pTmp ); // kein break; case RES_DDEFLD: if( pTmp->GetDepends() && !IsUsed( *pTmp ) ) { if( RES_SETEXPFLD == nWhich ) ((SwSetExpFieldType*)pTmp)->SetDeleted( sal_True ); else if( RES_USERFLD == nWhich ) ((SwUserFieldType*)pTmp)->SetDeleted( sal_True ); else ((SwDDEFieldType*)pTmp)->SetDeleted( sal_True ); nWhich = 0; } break; } if( nWhich ) { ASSERT( !pTmp->GetDepends(), "Abhaengige vorh.!" ); // Feldtype loschen delete pTmp; } pFldTypes->Remove( nFld ); SetModified(); } } const SwFldTypes* SwDoc::GetFldTypes() const { return pFldTypes; } /*-------------------------------------------------------------------- Beschreibung: Den ersten Typen mit ResId und Namen finden --------------------------------------------------------------------*/ SwFieldType* SwDoc::GetFldType( sal_uInt16 nResId, const String& rName, bool bDbFieldMatching // used in some UNO calls for RES_DBFLD // to use different string matching code // #i51815# ) const { sal_uInt16 nSize = pFldTypes->Count(), i = 0; const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore(); switch( nResId ) { case RES_SETEXPFLD: //JP 29.01.96: SequenceFelder beginnen aber bei INIT_FLDTYPES - 3!! // Sonst gibt es doppelte Nummernkreise!! //MIB 14.03.95: Ab sofort verlaesst sich auch der SW3-Reader //beim Aufbau der String-Pools und beim Einlesen von SetExp-Feldern //hierauf i = INIT_FLDTYPES - INIT_SEQ_FLDTYPES; break; case RES_DBFLD: case RES_USERFLD: case RES_DDEFLD: case RES_AUTHORITY: i = INIT_FLDTYPES; break; } SwFieldType* pRet = 0; for( ; i < nSize; ++i ) { SwFieldType* pFldType = (*pFldTypes)[i]; String aFldName( pFldType->GetName() ); if (bDbFieldMatching && nResId == RES_DBFLD) // #i51815# aFldName.SearchAndReplaceAll(DB_DELIM, '.'); if( nResId == pFldType->Which() && rSCmp.isEqual( rName, aFldName )) { pRet = pFldType; break; } } return pRet; } /************************************************************************* |* SwDoc::UpdateFlds() |* Beschreibung Felder updaten *************************************************************************/ /* * Alle sollen neu evaluiert werden. */ void SwDoc::UpdateFlds( SfxPoolItem *pNewHt, bool bCloseDB ) { // Modify() fuer jeden Feldtypen rufen, // abhaengige SwTxtFld werden benachrichtigt ... for( sal_uInt16 i=0; i < pFldTypes->Count(); ++i) { switch( (*pFldTypes)[i]->Which() ) { // Tabellen-Felder als vorletztes Updaten // Referenzen als letztes Updaten case RES_GETREFFLD: case RES_TABLEFLD: case RES_DBFLD: case RES_JUMPEDITFLD: case RES_REFPAGESETFLD: // werden nie expandiert! break; case RES_DDEFLD: { if( !pNewHt ) { SwMsgPoolItem aUpdateDDE( RES_UPDATEDDETBL ); (*pFldTypes)[i]->ModifyNotification( 0, &aUpdateDDE ); } else (*pFldTypes)[i]->ModifyNotification( 0, pNewHt ); break; } case RES_GETEXPFLD: case RES_SETEXPFLD: case RES_HIDDENTXTFLD: case RES_HIDDENPARAFLD: // Expression-Felder werden gesondert behandelt if( !pNewHt ) break; default: (*pFldTypes)[i]->ModifyNotification ( 0, pNewHt ); } } if( !IsExpFldsLocked() ) UpdateExpFlds( 0, sal_False ); // Expression-Felder Updaten // Tabellen UpdateTblFlds(pNewHt); // Referenzen UpdateRefFlds(pNewHt); if( bCloseDB ) GetNewDBMgr()->CloseAll(); // Nur bei KomplettUpdate evaluieren SetModified(); } /****************************************************************************** * void SwDoc::UpdateUsrFlds() ******************************************************************************/ void SwDoc::UpdateUsrFlds() { SwCalc* pCalc = 0; const SwFieldType* pFldType; for( sal_uInt16 i = INIT_FLDTYPES; i < pFldTypes->Count(); ++i ) if( RES_USERFLD == ( pFldType = (*pFldTypes)[i] )->Which() ) { if( !pCalc ) pCalc = new SwCalc( *this ); ((SwUserFieldType*)pFldType)->GetValue( *pCalc ); } if( pCalc ) { delete pCalc; SetModified(); } } /*-------------------------------------------------------------------- Beschreibung: Referenzfelder und TableFelder erneuern --------------------------------------------------------------------*/ void SwDoc::UpdateRefFlds( SfxPoolItem* pHt ) { SwFieldType* pFldType; for( sal_uInt16 i = 0; i < pFldTypes->Count(); ++i ) if( RES_GETREFFLD == ( pFldType = (*pFldTypes)[i] )->Which() ) pFldType->ModifyNotification( 0, pHt ); } void SwDoc::UpdateTblFlds( SfxPoolItem* pHt ) { ASSERT( !pHt || RES_TABLEFML_UPDATE == pHt->Which(), "Was ist das fuer ein MessageItem?" ); SwFieldType* pFldType(0); for (sal_uInt16 i = 0; i < pFldTypes->Count(); ++i) { if( RES_TABLEFLD == ( pFldType = (*pFldTypes)[i] )->Which() ) { SwTableFmlUpdate* pUpdtFld = 0; if( pHt && RES_TABLEFML_UPDATE == pHt->Which() ) pUpdtFld = (SwTableFmlUpdate*)pHt; SwIterator aIter( *pFldType ); for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() ) { if( pFmtFld->GetTxtFld() ) { SwTblField* pFld = (SwTblField*)pFmtFld->GetFld(); if( pUpdtFld ) { // bestimme Tabelle, in der das Feld steht const SwTableNode* pTblNd; const SwTxtNode& rTxtNd = pFmtFld->GetTxtFld()->GetTxtNode(); if( !rTxtNd.GetNodes().IsDocNodes() || 0 == ( pTblNd = rTxtNd.FindTableNode() ) ) continue; switch( pUpdtFld->eFlags ) { case TBL_CALC: // setze das Value-Flag zurueck // JP 17.06.96: interne Darstellung auf alle Formeln // (Referenzen auf andere Tabellen!!!) if( nsSwExtendedSubType::SUB_CMD & pFld->GetSubType() ) pFld->PtrToBoxNm( pUpdtFld->pTbl ); else pFld->ChgValid( sal_False ); break; case TBL_BOXNAME: // ist es die gesuchte Tabelle ?? if( &pTblNd->GetTable() == pUpdtFld->pTbl ) // zur externen Darstellung pFld->PtrToBoxNm( pUpdtFld->pTbl ); break; case TBL_BOXPTR: // zur internen Darstellung // JP 17.06.96: interne Darstellung auf alle Formeln // (Referenzen auf andere Tabellen!!!) pFld->BoxNmToPtr( pUpdtFld->pTbl ); break; case TBL_RELBOXNAME: // ist es die gesuchte Tabelle ?? if( &pTblNd->GetTable() == pUpdtFld->pTbl ) // zur relativen Darstellung pFld->ToRelBoxNm( pUpdtFld->pTbl ); break; default: break; } } else // setze bei allen das Value-Flag zurueck pFld->ChgValid( sal_False ); } } break; } pFldType = 0; } // und dann noch alle Tabellen Box Formeln abklappern const SfxPoolItem* pItem; sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_BOXATR_FORMULA ); for (sal_uInt32 i = 0; i < nMaxItems; ++i) { if( 0 != (pItem = GetAttrPool().GetItem2( RES_BOXATR_FORMULA, i ) ) && ((SwTblBoxFormula*)pItem)->GetDefinedIn() ) { ((SwTblBoxFormula*)pItem)->ChangeState( pHt ); } } // alle Felder/Boxen sind jetzt invalide, also kann das Rechnen anfangen if( pHt && ( RES_TABLEFML_UPDATE != pHt->Which() || TBL_CALC != ((SwTableFmlUpdate*)pHt)->eFlags )) return ; SwCalc* pCalc = 0; if( pFldType ) { SwIterator aIter( *pFldType ); for( SwFmtFld* pFmtFld = aIter.Last(); pFmtFld; pFmtFld = 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 this "optimization"? Is it still valid? SwTblField* pFld; if( !pFmtFld->GetTxtFld() || (nsSwExtendedSubType::SUB_CMD & (pFld = (SwTblField*)pFmtFld->GetFld())->GetSubType() )) continue; // muss neu berechnet werden (und ist keine textuelle Anzeige) if( !pFld->IsValid() ) { // bestimme Tabelle, in der das Feld steht const SwTxtNode& rTxtNd = pFmtFld->GetTxtFld()->GetTxtNode(); if( !rTxtNd.GetNodes().IsDocNodes() ) continue; const SwTableNode* pTblNd = rTxtNd.FindTableNode(); if( !pTblNd ) continue; // falls dieses Feld nicht in der zu updatenden // Tabelle steht, ueberspringen !! if( pHt && &pTblNd->GetTable() != ((SwTableFmlUpdate*)pHt)->pTbl ) continue; if( !pCalc ) pCalc = new SwCalc( *this ); // bestimme die Werte aller SetExpresion Felder, die // bis zur Tabelle gueltig sind SwFrm* pFrm = 0; if( pTblNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() ) { // steht im Sonderbereich, wird teuer !! Point aPt; // den im Layout 1. Frame returnen - Tab.Kopfzeile !! pFrm = rTxtNd.getLayoutFrm( GetCurrentLayout(), &aPt ); if( pFrm ) { SwPosition aPos( *pTblNd ); if( GetBodyTxtNode( *this, aPos, *pFrm ) ) FldsToCalc( *pCalc, _SetGetExpFld( aPos.nNode, pFmtFld->GetTxtFld(), &aPos.nContent )); else pFrm = 0; } } if( !pFrm ) { // einen Index fuers bestimmen vom TextNode anlegen SwNodeIndex aIdx( rTxtNd ); FldsToCalc( *pCalc, _SetGetExpFld( aIdx, pFmtFld->GetTxtFld() )); } SwTblCalcPara aPara( *pCalc, pTblNd->GetTable() ); pFld->CalcField( aPara ); if( aPara.IsStackOverFlow() ) { if( aPara.CalcWithStackOverflow() ) pFld->CalcField( aPara ); #ifdef DBG_UTIL else { // mind. ein ASSERT ASSERT( !this, "die Kettenformel konnte nicht errechnet werden" ); } #endif } pCalc->SetCalcError( CALC_NOERR ); } pFmtFld->ModifyNotification( 0, pHt ); } } // dann berechene noch die Formeln an den Boxen for (sal_uInt32 i = 0; i < nMaxItems; ++i ) { if( 0 != (pItem = GetAttrPool().GetItem2( RES_BOXATR_FORMULA, i ) ) && ((SwTblBoxFormula*)pItem)->GetDefinedIn() && !((SwTblBoxFormula*)pItem)->IsValid() ) { SwTblBoxFormula* pFml = (SwTblBoxFormula*)pItem; SwTableBox* pBox = pFml->GetTableBox(); if( pBox && pBox->GetSttNd() && pBox->GetSttNd()->GetNodes().IsDocNodes() ) { const SwTableNode* pTblNd = pBox->GetSttNd()->FindTableNode(); if( !pHt || &pTblNd->GetTable() == ((SwTableFmlUpdate*)pHt)->pTbl ) { double nValue; if( !pCalc ) pCalc = new SwCalc( *this ); // bestimme die Werte aller SetExpresion Felder, die // bis zur Tabelle gueltig sind SwFrm* pFrm = 0; if( pTblNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() ) { // steht im Sonderbereich, wird teuer !! Point aPt; // den im Layout 1. Frame returnen - Tab.Kopfzeile !! SwNodeIndex aCNdIdx( *pTblNd, +2 ); SwCntntNode* pCNd = aCNdIdx.GetNode().GetCntntNode(); if( !pCNd ) pCNd = GetNodes().GoNext( &aCNdIdx ); if( pCNd && 0 != (pFrm = pCNd->getLayoutFrm( GetCurrentLayout(), &aPt )) ) { SwPosition aPos( *pCNd ); if( GetBodyTxtNode( *this, aPos, *pFrm ) ) FldsToCalc( *pCalc, _SetGetExpFld( aPos.nNode )); else pFrm = 0; } } if( !pFrm ) { // einen Index fuers bestimmen vom TextNode anlegen SwNodeIndex aIdx( *pTblNd ); FldsToCalc( *pCalc, _SetGetExpFld( aIdx )); } SwTblCalcPara aPara( *pCalc, pTblNd->GetTable() ); pFml->Calc( aPara, nValue ); if( aPara.IsStackOverFlow() ) { if( aPara.CalcWithStackOverflow() ) pFml->Calc( aPara, nValue ); #ifdef DBG_UTIL else { // mind. ein ASSERT ASSERT( !this, "die Kettenformel konnte nicht errechnet werden" ); } #endif } SwFrmFmt* pFmt = pBox->ClaimFrmFmt(); SfxItemSet aTmp( GetAttrPool(), RES_BOXATR_BEGIN,RES_BOXATR_END-1 ); if( pCalc->IsCalcError() ) nValue = DBL_MAX; aTmp.Put( SwTblBoxValue( nValue )); if( SFX_ITEM_SET != pFmt->GetItemState( RES_BOXATR_FORMAT )) aTmp.Put( SwTblBoxNumFormat( 0 )); pFmt->SetFmtAttr( aTmp ); pCalc->SetCalcError( CALC_NOERR ); } } } } if( pCalc ) delete pCalc; } void SwDoc::UpdatePageFlds( SfxPoolItem* pMsgHnt ) { SwFieldType* pFldType; for( sal_uInt16 i = 0; i < INIT_FLDTYPES; ++i ) switch( ( pFldType = (*pFldTypes)[ i ] )->Which() ) { case RES_PAGENUMBERFLD: case RES_CHAPTERFLD: case RES_GETEXPFLD: case RES_REFPAGEGETFLD: pFldType->ModifyNotification( 0, pMsgHnt ); break; case RES_DOCSTATFLD: pFldType->ModifyNotification( 0, 0 ); break; } SetNewFldLst(true); } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ // ---- Loesche alle nicht referenzierten FeldTypen eines Dokumentes -- void SwDoc::GCFieldTypes() { for( sal_uInt16 n = pFldTypes->Count(); n > INIT_FLDTYPES; ) if( !(*pFldTypes)[ --n ]->GetDepends() ) RemoveFldType( n ); } void SwDoc::LockExpFlds() { ++nLockExpFld; } void SwDoc::UnlockExpFlds() { if( nLockExpFld ) --nLockExpFld; } bool SwDoc::IsExpFldsLocked() const { return 0 != nLockExpFld; } SwDocUpdtFld& SwDoc::GetUpdtFlds() const { return *pUpdtFlds; } bool SwDoc::IsNewFldLst() const { return mbNewFldLst; } void SwDoc::SetNewFldLst(bool bFlag) { mbNewFldLst = bFlag; } //---------------------------------------------------------------------- // der StartIndex kann optional mit angegeben werden (z.B. wenn dieser // zuvor schon mal erfragt wurde - ist sonst eine virtuelle Methode !!) _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx, const SwTxtFld* pFld, const SwIndex* pIdx ) { eSetGetExpFldType = TEXTFIELD; CNTNT.pTxtFld = pFld; nNode = rNdIdx.GetIndex(); if( pIdx ) nCntnt = pIdx->GetIndex(); else if( pFld ) nCntnt = *pFld->GetStart(); else nCntnt = 0; } _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx, const SwTxtINetFmt& rINet, const SwIndex* pIdx ) { eSetGetExpFldType = TEXTINET; CNTNT.pTxtINet = &rINet; nNode = rNdIdx.GetIndex(); if( pIdx ) nCntnt = pIdx->GetIndex(); else nCntnt = *rINet.GetStart(); } //Erweiterung fuer Sections: // diese haben immer als Content-Position 0xffff !! // Auf dieser steht nie ein Feld, maximal bis STRING_MAXLEN moeglich _SetGetExpFld::_SetGetExpFld( const SwSectionNode& rSectNd, const SwPosition* pPos ) { eSetGetExpFldType = SECTIONNODE; CNTNT.pSection = &rSectNd.GetSection(); if( pPos ) { nNode = pPos->nNode.GetIndex(); nCntnt = pPos->nContent.GetIndex(); } else { nNode = rSectNd.GetIndex(); nCntnt = 0; } } _SetGetExpFld::_SetGetExpFld( const SwTableBox& rTBox, const SwPosition* pPos ) { eSetGetExpFldType = TABLEBOX; CNTNT.pTBox = &rTBox; if( pPos ) { nNode = pPos->nNode.GetIndex(); nCntnt = pPos->nContent.GetIndex(); } else { nNode = 0; nCntnt = 0; if( rTBox.GetSttNd() ) { SwNodeIndex aIdx( *rTBox.GetSttNd() ); const SwCntntNode* pNd = aIdx.GetNode().GetNodes().GoNext( &aIdx ); if( pNd ) nNode = pNd->GetIndex(); } } } _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx, const SwTxtTOXMark& rTOX, const SwIndex* pIdx ) { eSetGetExpFldType = TEXTTOXMARK; CNTNT.pTxtTOX = &rTOX; nNode = rNdIdx.GetIndex(); if( pIdx ) nCntnt = pIdx->GetIndex(); else nCntnt = *rTOX.GetStart(); } _SetGetExpFld::_SetGetExpFld( const SwPosition& rPos ) { eSetGetExpFldType = CRSRPOS; CNTNT.pPos = &rPos; nNode = rPos.nNode.GetIndex(); nCntnt = rPos.nContent.GetIndex(); } _SetGetExpFld::_SetGetExpFld( const SwFlyFrmFmt& rFlyFmt, const SwPosition* pPos ) { eSetGetExpFldType = FLYFRAME; CNTNT.pFlyFmt = &rFlyFmt; if( pPos ) { nNode = pPos->nNode.GetIndex(); nCntnt = pPos->nContent.GetIndex(); } else { const SwFmtCntnt& rCntnt = rFlyFmt.GetCntnt(); nNode = rCntnt.GetCntntIdx()->GetIndex() + 1; nCntnt = 0; } } void _SetGetExpFld::GetPos( SwPosition& rPos ) const { rPos.nNode = nNode; rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt ); } void _SetGetExpFld::GetPosOfContent( SwPosition& rPos ) const { const SwNode* pNd = GetNodeFromCntnt(); if( pNd ) pNd = pNd->GetCntntNode(); if( pNd ) { rPos.nNode = *pNd; rPos.nContent.Assign( (SwCntntNode*)pNd,GetCntPosFromCntnt() ); } else { rPos.nNode = nNode; rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt ); } } void _SetGetExpFld::SetBodyPos( const SwCntntFrm& rFrm ) { if( !rFrm.IsInDocBody() ) { SwNodeIndex aIdx( *rFrm.GetNode() ); SwDoc& rDoc = *aIdx.GetNodes().GetDoc(); SwPosition aPos( aIdx ); #ifdef DBG_UTIL ASSERT( ::GetBodyTxtNode( rDoc, aPos, rFrm ), "wo steht das Feld" ); #else ::GetBodyTxtNode( rDoc, aPos, rFrm ); #endif nNode = aPos.nNode.GetIndex(); nCntnt = aPos.nContent.GetIndex(); } } sal_Bool _SetGetExpFld::operator<( const _SetGetExpFld& rFld ) const { if( nNode < rFld.nNode || ( nNode == rFld.nNode && nCntnt < rFld.nCntnt )) return sal_True; else if( nNode != rFld.nNode || nCntnt != rFld.nCntnt ) return sal_False; const SwNode *pFirst = GetNodeFromCntnt(), *pNext = rFld.GetNodeFromCntnt(); // Position gleich: nur weiter wenn beide FeldPointer besetzt sind !! if( !pFirst || !pNext ) return sal_False; // gleiche Section ?? if( pFirst->StartOfSectionNode() != pNext->StartOfSectionNode() ) { // sollte einer in der Tabelle stehen ? const SwNode *pFirstStt, *pNextStt; const SwTableNode* pTblNd = pFirst->FindTableNode(); if( pTblNd ) pFirstStt = pTblNd->StartOfSectionNode(); else pFirstStt = pFirst->StartOfSectionNode(); if( 0 != ( pTblNd = pNext->FindTableNode() ) ) pNextStt = pTblNd->StartOfSectionNode(); else pNextStt = pNext->StartOfSectionNode(); if( pFirstStt != pNextStt ) { if( pFirst->IsTxtNode() && pNext->IsTxtNode() && ( pFirst->FindFlyStartNode() || pNext->FindFlyStartNode() )) { return ::IsFrameBehind( *(SwTxtNode*)pNext, nCntnt, *(SwTxtNode*)pFirst, nCntnt ); } return pFirstStt->GetIndex() < pNextStt->GetIndex(); } } // ist gleiche Section, dann Feld im gleichen Node ? if( pFirst != pNext ) return pFirst->GetIndex() < pNext->GetIndex(); // gleicher Node in der Section, dann Position im Node return GetCntPosFromCntnt() < rFld.GetCntPosFromCntnt(); } const SwNode* _SetGetExpFld::GetNodeFromCntnt() const { const SwNode* pRet = 0; if( CNTNT.pTxtFld ) switch( eSetGetExpFldType ) { case TEXTFIELD: pRet = &CNTNT.pTxtFld->GetTxtNode(); break; case TEXTINET: pRet = &CNTNT.pTxtINet->GetTxtNode(); break; case SECTIONNODE: pRet = CNTNT.pSection->GetFmt()->GetSectionNode(); break; case CRSRPOS: pRet = &CNTNT.pPos->nNode.GetNode(); break; case TEXTTOXMARK: pRet = &CNTNT.pTxtTOX->GetTxtNode(); break; case TABLEBOX: if( CNTNT.pTBox->GetSttNd() ) { SwNodeIndex aIdx( *CNTNT.pTBox->GetSttNd() ); pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx ); } break; case FLYFRAME: { SwNodeIndex aIdx( *CNTNT.pFlyFmt->GetCntnt().GetCntntIdx() ); pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx ); } break; } return pRet; } xub_StrLen _SetGetExpFld::GetCntPosFromCntnt() const { sal_uInt16 nRet = 0; if( CNTNT.pTxtFld ) switch( eSetGetExpFldType ) { case TEXTFIELD: case TEXTINET: case TEXTTOXMARK: nRet = *CNTNT.pTxtFld->GetStart(); break; case CRSRPOS: nRet = CNTNT.pPos->nContent.GetIndex(); break; default: break; } return nRet; } _HashStr::_HashStr( const String& rName, const String& rText, _HashStr* pNxt ) : SwHash( rName ), aSetStr( rText ) { pNext = pNxt; } // suche nach dem Namen, ist er vorhanden, returne seinen String, sonst // einen LeerString void LookString( SwHash** ppTbl, sal_uInt16 nSize, const String& rName, String& rRet, sal_uInt16* pPos ) { rRet = rName; rRet.EraseLeadingChars().EraseTrailingChars(); SwHash* pFnd = Find( rRet, ppTbl, nSize, pPos ); if( pFnd ) rRet = ((_HashStr*)pFnd)->aSetStr; else rRet.Erase(); } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ String lcl_GetDBVarName( SwDoc& rDoc, SwDBNameInfField& rDBFld ) { SwDBData aDBData( rDBFld.GetDBData( &rDoc )); String sDBNumNm; SwDBData aDocData = rDoc.GetDBData(); if( aDBData != aDocData ) { sDBNumNm = aDBData.sDataSource; sDBNumNm += DB_DELIM; sDBNumNm += String(aDBData.sCommand); sDBNumNm += DB_DELIM; } sDBNumNm += SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD); return sDBNumNm; } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ void lcl_CalcFld( SwDoc& rDoc, SwCalc& rCalc, const _SetGetExpFld& rSGEFld, SwNewDBMgr* pMgr ) { const SwTxtFld* pTxtFld = rSGEFld.GetFld(); if( !pTxtFld ) return ; const SwField* pFld = pTxtFld->GetFld().GetFld(); const sal_uInt16 nFldWhich = pFld->GetTyp()->Which(); if( RES_SETEXPFLD == nFldWhich ) { SwSbxValue aValue; if( nsSwGetSetExpType::GSE_EXPR & pFld->GetSubType() ) aValue.PutDouble( ((SwSetExpField*)pFld)->GetValue() ); else // Erweiterung fuers Rechnen mit Strings aValue.PutString( ((SwSetExpField*)pFld)->GetExpStr() ); // setze im Calculator den neuen Wert rCalc.VarChange( pFld->GetTyp()->GetName(), aValue ); } else if( pMgr ) { switch( nFldWhich ) { case RES_DBNUMSETFLD: { SwDBNumSetField* pDBFld = (SwDBNumSetField*)pFld; SwDBData aDBData(pDBFld->GetDBData(&rDoc)); if( pDBFld->IsCondValid() && pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand )) rCalc.VarChange( lcl_GetDBVarName( rDoc, *pDBFld), pDBFld->GetFormat() ); } break; case RES_DBNEXTSETFLD: { SwDBNextSetField* pDBFld = (SwDBNextSetField*)pFld; SwDBData aDBData(pDBFld->GetDBData(&rDoc)); if( !pDBFld->IsCondValid() || !pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand )) break; String sDBNumNm(lcl_GetDBVarName( rDoc, *pDBFld)); SwCalcExp* pExp = rCalc.VarLook( sDBNumNm ); if( pExp ) rCalc.VarChange( sDBNumNm, pExp->nValue.GetLong() + 1 ); } break; } } } void SwDoc::FldsToCalc( SwCalc& rCalc, const _SetGetExpFld& rToThisFld ) { // erzeuge die Sortierteliste aller SetFelder pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC ); mbNewFldLst = sal_False; SwNewDBMgr* pMgr = GetNewDBMgr(); pMgr->CloseAll(sal_False); if( pUpdtFlds->GetSortLst()->Count() ) { sal_uInt16 nLast; _SetGetExpFld* pFld = (_SetGetExpFld*)&rToThisFld; if( pUpdtFlds->GetSortLst()->Seek_Entry( pFld, &nLast ) ) ++nLast; const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData(); for( sal_uInt16 n = 0; n < nLast; ++n, ++ppSortLst ) lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr ); } pMgr->CloseAll(sal_False); } void SwDoc::FldsToCalc( SwCalc& rCalc, sal_uLong nLastNd, sal_uInt16 nLastCnt ) { // erzeuge die Sortierteliste aller SetFelder pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC ); mbNewFldLst = sal_False; SwNewDBMgr* pMgr = GetNewDBMgr(); pMgr->CloseAll(sal_False); const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData(); for( sal_uInt16 n = pUpdtFlds->GetSortLst()->Count(); n && ( (*ppSortLst)->GetNode() < nLastNd || ( (*ppSortLst)->GetNode() == nLastNd && (*ppSortLst)->GetCntnt() <= nLastCnt ) ); --n, ++ppSortLst ) lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr ); pMgr->CloseAll(sal_False); } void SwDoc::FldsToExpand( SwHash**& ppHashTbl, sal_uInt16& rTblSize, const _SetGetExpFld& rToThisFld ) { // erzeuge die Sortierteliste aller SetFelder pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_EXPAND ); mbNewFldLst = sal_False; // HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt // (versuche eine "ungerade"-Zahl zu erzeugen) rTblSize = (( pUpdtFlds->GetSortLst()->Count() / 7 ) + 1 ) * 7; ppHashTbl = new SwHash*[ rTblSize ]; memset( ppHashTbl, 0, sizeof( _HashStr* ) * rTblSize ); sal_uInt16 nLast; { _SetGetExpFld* pTmp = (_SetGetExpFld*)&rToThisFld; if( pUpdtFlds->GetSortLst()->Seek_Entry( pTmp, &nLast ) ) ++nLast; } sal_uInt16 nPos; SwHash* pFnd; String aNew; const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData(); for( ; nLast; --nLast, ++ppSortLst ) { const SwTxtFld* pTxtFld = (*ppSortLst)->GetFld(); if( !pTxtFld ) continue; const SwField* pFld = pTxtFld->GetFld().GetFld(); switch( pFld->GetTyp()->Which() ) { case RES_SETEXPFLD: if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() ) { // setze in der HashTabelle den neuen Wert // ist die "Formel" ein Feld ?? SwSetExpField* pSFld = (SwSetExpField*)pFld; LookString( ppHashTbl, rTblSize, pSFld->GetFormula(), aNew ); if( !aNew.Len() ) // nichts gefunden, dann ist aNew = pSFld->GetFormula(); // die Formel der neue Wert // OD 11.02.2003 #i3141# - update expression of field as in // method for string/text fields pSFld->ChgExpStr( aNew ); // suche den Namen vom Feld aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName(); // Eintrag vorhanden ? pFnd = Find( aNew, ppHashTbl, rTblSize, &nPos ); if( pFnd ) // Eintrag in der HashTabelle aendern ((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr(); else // neuen Eintrag einfuegen *(ppHashTbl + nPos ) = new _HashStr( aNew, pSFld->GetExpStr(), (_HashStr*)*(ppHashTbl + nPos) ); } break; case RES_DBFLD: { const String& rName = pFld->GetTyp()->GetName(); // Eintrag in den HashTable eintragen // Eintrag vorhanden ? pFnd = Find( rName, ppHashTbl, rTblSize, &nPos ); String const value(pFld->ExpandField(IsClipBoard())); if( pFnd ) { // Eintrag in der HashTabelle aendern static_cast<_HashStr*>(pFnd)->aSetStr = value; } else { // neuen Eintrag einfuegen *(ppHashTbl + nPos ) = new _HashStr( rName, value, static_cast<_HashStr *>(*(ppHashTbl + nPos))); } } break; } } } void SwDoc::UpdateExpFlds( SwTxtFld* pUpdtFld, bool bUpdRefFlds ) { if( IsExpFldsLocked() || IsInReading() ) return; sal_Bool bOldInUpdateFlds = pUpdtFlds->IsInUpdateFlds(); pUpdtFlds->SetInUpdateFlds( sal_True ); pUpdtFlds->MakeFldList( *this, sal_True, GETFLD_ALL ); mbNewFldLst = sal_False; if( !pUpdtFlds->GetSortLst()->Count() ) { if( bUpdRefFlds ) UpdateRefFlds(NULL); pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds ); pUpdtFlds->SetFieldsDirty( sal_False ); return ; } sal_uInt16 nWhich, n; // HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt // (versuche eine "ungerade"-Zahl zu erzeugen) sal_uInt16 nStrFmtCnt = (( pFldTypes->Count() / 7 ) + 1 ) * 7; SwHash** pHashStrTbl = new SwHash*[ nStrFmtCnt ]; memset( pHashStrTbl, 0, sizeof( _HashStr* ) * nStrFmtCnt ); { const SwFieldType* pFldType; // gesondert behandeln: for( n = pFldTypes->Count(); n; ) switch( ( pFldType = (*pFldTypes)[ --n ] )->Which() ) { case RES_USERFLD: { // Eintrag vorhanden ? sal_uInt16 nPos; const String& rNm = pFldType->GetName(); String sExpand(((SwUserFieldType*)pFldType)->Expand(nsSwGetSetExpType::GSE_STRING, 0, 0)); SwHash* pFnd = Find( rNm, pHashStrTbl, nStrFmtCnt, &nPos ); if( pFnd ) // Eintrag in der HashTabelle aendern ?? ((_HashStr*)pFnd)->aSetStr = sExpand; else // neuen Eintrag einfuegen *(pHashStrTbl + nPos ) = new _HashStr( rNm, sExpand, (_HashStr*)*(pHashStrTbl + nPos) ); } break; case RES_SETEXPFLD: ((SwSetExpFieldType*)pFldType)->SetOutlineChgNd( 0 ); break; } } // Ok, das Array ist soweit mit allen Feldern gefuellt, dann rechne mal SwCalc aCalc( *this ); String sDBNumNm( SwFieldType::GetTypeStr( TYP_DBSETNUMBERFLD ) ); // aktuelle Datensatznummer schon vorher einstellen SwNewDBMgr* pMgr = GetNewDBMgr(); pMgr->CloseAll(sal_False); /* if(pMgr && pMgr->OpenDB(DBMGR_STD, GetDBDesc(), sal_False)) { if(!pMgr->IsInMerge() ) pMgr->ToFirstSelectedRecord(DBMGR_STD); aCalc.VarChange( sDBNumNm, pMgr->GetCurSelectedRecordId(DBMGR_STD)); } */ String aNew; const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData(); for( n = pUpdtFlds->GetSortLst()->Count(); n; --n, ++ppSortLst ) { SwSection* pSect = (SwSection*)(*ppSortLst)->GetSection(); if( pSect ) { //!SECTION // if( pGFld->IsInBodyTxt() ) SwSbxValue aValue = aCalc.Calculate( pSect->GetCondition() ); if(!aValue.IsVoidValue()) pSect->SetCondHidden( aValue.GetBool() ); continue; } SwTxtFld* pTxtFld = (SwTxtFld*)(*ppSortLst)->GetFld(); if( !pTxtFld ) { ASSERT( !this, "was ist es denn nun" ); continue; } SwFmtFld* pFmtFld = (SwFmtFld*)&pTxtFld->GetFld(); SwField* pFld = pFmtFld->GetFld(); switch( nWhich = pFld->GetTyp()->Which() ) { case RES_HIDDENTXTFLD: { SwHiddenTxtField* pHFld = (SwHiddenTxtField*)pFld; SwSbxValue aValue = aCalc.Calculate( pHFld->GetPar1() ); sal_Bool bValue = !aValue.GetBool(); if(!aValue.IsVoidValue()) { pHFld->SetValue( bValue ); // Feld Evaluieren pHFld->Evaluate(this); } } break; case RES_HIDDENPARAFLD: { SwHiddenParaField* pHPFld = (SwHiddenParaField*)pFld; SwSbxValue aValue = aCalc.Calculate( pHPFld->GetPar1() ); sal_Bool bValue = aValue.GetBool(); if(!aValue.IsVoidValue()) pHPFld->SetHidden( bValue ); } break; case RES_DBSETNUMBERFLD: { ((SwDBSetNumberField*)pFld)->Evaluate(this); aCalc.VarChange( sDBNumNm, ((SwDBSetNumberField*)pFld)->GetSetNumber()); } break; case RES_DBNEXTSETFLD: case RES_DBNUMSETFLD: UpdateDBNumFlds( *(SwDBNameInfField*)pFld, aCalc ); break; case RES_DBFLD: { // Feld Evaluieren ((SwDBField*)pFld)->Evaluate(); SwDBData aTmpDBData(((SwDBField*)pFld)->GetDBData()); if( pMgr->IsDataSourceOpen(aTmpDBData.sDataSource, aTmpDBData.sCommand, sal_False)) aCalc.VarChange( sDBNumNm, pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType)); const String& rName = pFld->GetTyp()->GetName(); // Wert fuer den Calculator setzen //JP 10.02.96: GetValue macht hier doch keinen Sinn // ((SwDBField*)pFld)->GetValue(); //!OK aCalc.VarChange(aName, ((SwDBField*)pFld)->GetValue(aCalc)); // Eintrag in den HashTable eintragen // Eintrag vorhanden ? sal_uInt16 nPos; SwHash* pFnd = Find( rName, pHashStrTbl, nStrFmtCnt, &nPos ); String const value(pFld->ExpandField(IsClipBoard())); if( pFnd ) { // Eintrag in der HashTabelle aendern static_cast<_HashStr*>(pFnd)->aSetStr = value; } else { // neuen Eintrag einfuegen *(pHashStrTbl + nPos ) = new _HashStr( rName, value, static_cast<_HashStr *>(*(pHashStrTbl + nPos))); } } break; case RES_GETEXPFLD: case RES_SETEXPFLD: { if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() ) // String Ersetzung { if( RES_GETEXPFLD == nWhich ) { SwGetExpField* pGFld = (SwGetExpField*)pFld; if( (!pUpdtFld || pUpdtFld == pTxtFld ) && pGFld->IsInBodyTxt() ) { LookString( pHashStrTbl, nStrFmtCnt, pGFld->GetFormula(), aNew ); pGFld->ChgExpStr( aNew ); } } else { SwSetExpField* pSFld = (SwSetExpField*)pFld; // ist die "Formel" ein Feld ?? LookString( pHashStrTbl, nStrFmtCnt, pSFld->GetFormula(), aNew ); if( !aNew.Len() ) // nichts gefunden, dann ist die aNew = pSFld->GetFormula(); // Formel der neue Wert // nur ein spezielles FeldUpdaten ? if( !pUpdtFld || pUpdtFld == pTxtFld ) pSFld->ChgExpStr( aNew ); // suche den Namen vom Feld aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName(); // Eintrag vorhanden ? sal_uInt16 nPos; SwHash* pFnd = Find( aNew, pHashStrTbl, nStrFmtCnt, &nPos ); if( pFnd ) // Eintrag in der HashTabelle aendern ((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr(); else // neuen Eintrag einfuegen *(pHashStrTbl + nPos ) = pFnd = new _HashStr( aNew, pSFld->GetExpStr(), (_HashStr*)*(pHashStrTbl + nPos) ); // Erweiterung fuers Rechnen mit Strings SwSbxValue aValue; aValue.PutString( ((_HashStr*)pFnd)->aSetStr ); aCalc.VarChange( aNew, aValue ); } } else // Formel neu berechnen { if( RES_GETEXPFLD == nWhich ) { SwGetExpField* pGFld = (SwGetExpField*)pFld; if( (!pUpdtFld || pUpdtFld == pTxtFld ) && pGFld->IsInBodyTxt() ) { SwSbxValue aValue = aCalc.Calculate( pGFld->GetFormula()); if(!aValue.IsVoidValue()) pGFld->SetValue(aValue.GetDouble() ); } } else { SwSetExpField* pSFld = (SwSetExpField*)pFld; SwSetExpFieldType* pSFldTyp = (SwSetExpFieldType*)pFld->GetTyp(); aNew = pSFldTyp->GetName(); SwNode* pSeqNd = 0; if( pSFld->IsSequenceFld() ) { const sal_uInt8 nLvl = pSFldTyp->GetOutlineLvl(); if( MAXLEVEL > nLvl ) { // dann teste, ob die Nummer neu aufsetzen muss pSeqNd = GetNodes()[ (*ppSortLst)->GetNode() ]; const SwTxtNode* pOutlNd = pSeqNd-> FindOutlineNodeOfLevel( nLvl ); if( pSFldTyp->GetOutlineChgNd() != pOutlNd ) { pSFldTyp->SetOutlineChgNd( pOutlNd ); aCalc.VarChange( aNew, 0 ); } } } aNew += '='; aNew += pSFld->GetFormula(); SwSbxValue aValue = aCalc.Calculate( aNew ); double nErg = aValue.GetDouble(); // nur ein spezielles Feld updaten ? if( !aValue.IsVoidValue() && (!pUpdtFld || pUpdtFld == pTxtFld) ) { pSFld->SetValue( nErg ); if( pSeqNd ) pSFldTyp->SetChapter( *pSFld, *pSeqNd ); } } } } } // switch pFmtFld->ModifyNotification( 0, 0 ); // Formatierung anstossen if( pUpdtFld == pTxtFld ) // sollte nur dieses geupdatet werden { if( RES_GETEXPFLD == nWhich || // nur GetFeld oder RES_HIDDENTXTFLD == nWhich || // HiddenTxt? RES_HIDDENPARAFLD == nWhich) // HiddenParaFld? break; // beenden pUpdtFld = 0; // ab jetzt alle Updaten } } pMgr->CloseAll(sal_False); // HashTabelle wieder loeschen ::DeleteHashTable( pHashStrTbl, nStrFmtCnt ); // Referenzfelder updaten if( bUpdRefFlds ) UpdateRefFlds(NULL); pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds ); pUpdtFlds->SetFieldsDirty( sal_False ); } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ void SwDoc::UpdateDBNumFlds( SwDBNameInfField& rDBFld, SwCalc& rCalc ) { SwNewDBMgr* pMgr = GetNewDBMgr(); sal_uInt16 nFldType = rDBFld.Which(); sal_Bool bPar1 = rCalc.Calculate( rDBFld.GetPar1() ).GetBool(); if( RES_DBNEXTSETFLD == nFldType ) ((SwDBNextSetField&)rDBFld).SetCondValid( bPar1 ); else ((SwDBNumSetField&)rDBFld).SetCondValid( bPar1 ); if( rDBFld.GetRealDBData().sDataSource.getLength() ) { // Eine bestimmte Datenbank bearbeiten if( RES_DBNEXTSETFLD == nFldType ) ((SwDBNextSetField&)rDBFld).Evaluate(this); else ((SwDBNumSetField&)rDBFld).Evaluate(this); SwDBData aTmpDBData( rDBFld.GetDBData(this) ); if( pMgr->OpenDataSource( aTmpDBData.sDataSource, aTmpDBData.sCommand, -1, false )) rCalc.VarChange( lcl_GetDBVarName( *this, rDBFld), pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType) ); } else { DBG_ERROR("TODO: what should happen with unnamed DBFields?"); } } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ void SwDoc::_InitFieldTypes() // wird vom CTOR gerufen!! { // Feldtypen sal_uInt16 nFldType = 0; pFldTypes->Insert( new SwDateTimeFieldType(this), nFldType++ ); pFldTypes->Insert( new SwChapterFieldType, nFldType++ ); pFldTypes->Insert( new SwPageNumberFieldType, nFldType++ ); pFldTypes->Insert( new SwAuthorFieldType, nFldType++ ); pFldTypes->Insert( new SwFileNameFieldType(this), nFldType++ ); pFldTypes->Insert( new SwDBNameFieldType(this), nFldType++); pFldTypes->Insert( new SwGetExpFieldType(this), nFldType++ ); pFldTypes->Insert( new SwGetRefFieldType( this ), nFldType++ ); pFldTypes->Insert( new SwHiddenTxtFieldType, nFldType++ ); pFldTypes->Insert( new SwPostItFieldType(this), nFldType++ ); pFldTypes->Insert( new SwDocStatFieldType(this), nFldType++); pFldTypes->Insert( new SwDocInfoFieldType(this), nFldType++); pFldTypes->Insert( new SwInputFieldType( this ), nFldType++ ); pFldTypes->Insert( new SwTblFieldType( this ), nFldType++); pFldTypes->Insert( new SwMacroFieldType(this), nFldType++ ); pFldTypes->Insert( new SwHiddenParaFieldType, nFldType++ ); pFldTypes->Insert( new SwDBNextSetFieldType, nFldType++ ); pFldTypes->Insert( new SwDBNumSetFieldType, nFldType++ ); pFldTypes->Insert( new SwDBSetNumberFieldType, nFldType++ ); pFldTypes->Insert( new SwTemplNameFieldType(this), nFldType++); pFldTypes->Insert( new SwTemplNameFieldType(this),nFldType++); pFldTypes->Insert( new SwExtUserFieldType, nFldType++ ); pFldTypes->Insert( new SwRefPageSetFieldType, nFldType++ ); pFldTypes->Insert( new SwRefPageGetFieldType( this ), nFldType++ ); pFldTypes->Insert( new SwJumpEditFieldType( this ), nFldType++ ); pFldTypes->Insert( new SwScriptFieldType( this ), nFldType++ ); pFldTypes->Insert( new SwCombinedCharFieldType, nFldType++ ); pFldTypes->Insert( new SwDropDownFieldType, nFldType++ ); // Types muessen am Ende stehen !! // Im InsertFldType wird davon ausgegangen !!!! // MIB 14.04.95: Im Sw3StringPool::Setup (sw3imp.cxx) und // lcl_sw3io_InSetExpField (sw3field.cxx) jetzt auch pFldTypes->Insert( new SwSetExpFieldType(this, SW_RESSTR(STR_POOLCOLL_LABEL_ABB), nsSwGetSetExpType::GSE_SEQ), nFldType++); pFldTypes->Insert( new SwSetExpFieldType(this, SW_RESSTR(STR_POOLCOLL_LABEL_TABLE), nsSwGetSetExpType::GSE_SEQ),nFldType++); pFldTypes->Insert( new SwSetExpFieldType(this, SW_RESSTR(STR_POOLCOLL_LABEL_FRAME), nsSwGetSetExpType::GSE_SEQ),nFldType++); pFldTypes->Insert( new SwSetExpFieldType(this, SW_RESSTR(STR_POOLCOLL_LABEL_DRAWING), nsSwGetSetExpType::GSE_SEQ),nFldType++); ASSERT( nFldType == INIT_FLDTYPES, "Bad initsize: SwFldTypes" ); } void SwDoc::InsDelFldInFldLst( bool bIns, const SwTxtFld& rFld ) { if( !mbNewFldLst || !IsInDtor() ) pUpdtFlds->InsDelFldInFldLst( bIns, rFld ); } SwDBData SwDoc::GetDBData() { return GetDBDesc(); } const SwDBData& SwDoc::GetDBDesc() { if(!aDBData.sDataSource.getLength()) { const sal_uInt16 nSize = pFldTypes->Count(); for(sal_uInt16 i = 0; i < nSize && !aDBData.sDataSource.getLength(); ++i) { SwFieldType& rFldType = *((*pFldTypes)[i]); sal_uInt16 nWhich = rFldType.Which(); if(IsUsed(rFldType)) { switch(nWhich) { case RES_DBFLD: case RES_DBNEXTSETFLD: case RES_DBNUMSETFLD: case RES_DBSETNUMBERFLD: { SwIterator aIter( rFldType ); for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() ) { if(pFld->IsFldInDoc()) { if(RES_DBFLD == nWhich) aDBData = (static_cast < SwDBFieldType * > (pFld->GetFld()->GetTyp())) ->GetDBData(); else aDBData = (static_cast < SwDBNameInfField* > (pFld->GetFld()))->GetRealDBData(); break; } } } break; } } } } if(!aDBData.sDataSource.getLength()) aDBData = GetNewDBMgr()->GetAddressDBName(); return aDBData; } void SwDoc::SetInitDBFields( sal_Bool b ) { GetNewDBMgr()->SetInitDBFields( b ); } /*-------------------------------------------------------------------- Beschreibung: Alle von Feldern verwendete Datenbanken herausfinden --------------------------------------------------------------------*/ String lcl_DBDataToString(const SwDBData& rData) { String sRet = rData.sDataSource; sRet += DB_DELIM; sRet += (String)rData.sCommand; sRet += DB_DELIM; sRet += String::CreateFromInt32(rData.nCommandType); return sRet; } void SwDoc::GetAllUsedDB( SvStringsDtor& rDBNameList, const SvStringsDtor* pAllDBNames ) { SvStringsDtor aUsedDBNames; SvStringsDtor aAllDBNames; if( !pAllDBNames ) { GetAllDBNames( aAllDBNames ); pAllDBNames = &aAllDBNames; } SwSectionFmts& rArr = GetSections(); for (sal_uInt16 n = rArr.Count(); n; ) { SwSection* pSect = rArr[ --n ]->GetSection(); if( pSect ) { String aCond( pSect->GetCondition() ); AddUsedDBToList( rDBNameList, FindUsedDBs( *pAllDBNames, aCond, aUsedDBNames ) ); aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() ); } } const SfxPoolItem* pItem; sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_FIELD ); for (sal_uInt32 n = 0; n < nMaxItems; ++n) { if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) )) continue; const SwFmtFld* pFmtFld = (SwFmtFld*)pItem; const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld(); if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() ) continue; const SwField* pFld = pFmtFld->GetFld(); switch( pFld->GetTyp()->Which() ) { case RES_DBFLD: AddUsedDBToList( rDBNameList, lcl_DBDataToString(((SwDBField*)pFld)->GetDBData() )); break; case RES_DBSETNUMBERFLD: case RES_DBNAMEFLD: AddUsedDBToList( rDBNameList, lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() )); break; case RES_DBNUMSETFLD: case RES_DBNEXTSETFLD: AddUsedDBToList( rDBNameList, lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() )); // kein break // JP: ist das so richtig ?? case RES_HIDDENTXTFLD: case RES_HIDDENPARAFLD: AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames, pFld->GetPar1(), aUsedDBNames )); aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() ); break; case RES_SETEXPFLD: case RES_GETEXPFLD: case RES_TABLEFLD: AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames, pFld->GetFormula(), aUsedDBNames )); aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() ); break; } } } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ void SwDoc::GetAllDBNames( SvStringsDtor& rAllDBNames ) { SwNewDBMgr* pMgr = GetNewDBMgr(); const SwDSParamArr& rArr = pMgr->GetDSParamArray(); for(sal_uInt16 i = 0; i < rArr.Count(); i++) { SwDSParam* pParam = rArr[i]; String* pStr = new String( pParam->sDataSource ); (*pStr) += DB_DELIM; (*pStr) += (String)pParam->sCommand; rAllDBNames.Insert( pStr, rAllDBNames.Count() ); } } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ SvStringsDtor& SwDoc::FindUsedDBs( const SvStringsDtor& rAllDBNames, const String& rFormel, SvStringsDtor& rUsedDBNames ) { const CharClass& rCC = GetAppCharClass(); String sFormel( rFormel); #ifndef UNX rCC.toUpper( sFormel ); #endif xub_StrLen nPos; for (sal_uInt16 i = 0; i < rAllDBNames.Count(); ++i ) { const String* pStr = rAllDBNames.GetObject(i); if( STRING_NOTFOUND != (nPos = sFormel.Search( *pStr )) && sFormel.GetChar( nPos + pStr->Len() ) == '.' && (!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 ))) { // Tabellenname suchen xub_StrLen nEndPos; nPos += pStr->Len() + 1; if( STRING_NOTFOUND != (nEndPos = sFormel.Search('.', nPos)) ) { String* pDBNm = new String( *pStr ); pDBNm->Append( DB_DELIM ); pDBNm->Append( sFormel.Copy( nPos, nEndPos - nPos )); rUsedDBNames.Insert( pDBNm, rUsedDBNames.Count() ); } } } return rUsedDBNames; } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ void SwDoc::AddUsedDBToList( SvStringsDtor& rDBNameList, const SvStringsDtor& rUsedDBNames ) { for (sal_uInt16 i = 0; i < rUsedDBNames.Count(); i++) AddUsedDBToList( rDBNameList, *rUsedDBNames.GetObject(i) ); } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ void SwDoc::AddUsedDBToList( SvStringsDtor& rDBNameList, const String& rDBName) { if( !rDBName.Len() ) return; #ifdef UNX for( sal_uInt16 i = 0; i < rDBNameList.Count(); ++i ) if( rDBName == rDBNameList.GetObject(i)->GetToken(0) ) return; #else const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore(); for( sal_uInt16 i = 0; i < rDBNameList.Count(); ++i ) if( rSCmp.isEqual( rDBName, rDBNameList.GetObject(i)->GetToken(0) ) ) return; #endif SwDBData aData; aData.sDataSource = rDBName.GetToken(0, DB_DELIM); aData.sCommand = rDBName.GetToken(1, DB_DELIM); aData.nCommandType = -1; GetNewDBMgr()->CreateDSData(aData); String* pNew = new String( rDBName ); rDBNameList.Insert( pNew, rDBNameList.Count() ); } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ void SwDoc::ChangeDBFields( const SvStringsDtor& rOldNames, const String& rNewName ) { SwDBData aNewDBData; aNewDBData.sDataSource = rNewName.GetToken(0, DB_DELIM); aNewDBData.sCommand = rNewName.GetToken(1, DB_DELIM); aNewDBData.nCommandType = (short)rNewName.GetToken(2, DB_DELIM).ToInt32(); String sFormel; SwSectionFmts& rArr = GetSections(); for (sal_uInt16 n = rArr.Count(); n; ) { SwSection* pSect = rArr[ --n ]->GetSection(); if( pSect ) { sFormel = pSect->GetCondition(); ReplaceUsedDBs( rOldNames, rNewName, sFormel); pSect->SetCondition(sFormel); } } const SfxPoolItem* pItem; sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_FIELD ); for (sal_uInt32 n = 0; n < nMaxItems; ++n ) { if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) )) continue; SwFmtFld* pFmtFld = (SwFmtFld*)pItem; SwTxtFld* pTxtFld = pFmtFld->GetTxtFld(); if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() ) continue; SwField* pFld = pFmtFld->GetFld(); sal_Bool bExpand = sal_False; switch( pFld->GetTyp()->Which() ) { case RES_DBFLD: if( IsNameInArray( rOldNames, lcl_DBDataToString(((SwDBField*)pFld)->GetDBData()))) { SwDBFieldType* pOldTyp = (SwDBFieldType*)pFld->GetTyp(); SwDBFieldType* pTyp = (SwDBFieldType*)InsertFldType( SwDBFieldType(this, pOldTyp->GetColumnName(), aNewDBData)); pFmtFld->RegisterToFieldType( *pTyp ); pFld->ChgTyp(pTyp); ((SwDBField*)pFld)->ClearInitialized(); ((SwDBField*)pFld)->InitContent(); bExpand = sal_True; } break; case RES_DBSETNUMBERFLD: case RES_DBNAMEFLD: if( IsNameInArray( rOldNames, lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData()))) { ((SwDBNameInfField*)pFld)->SetDBData(aNewDBData); bExpand = sal_True; } break; case RES_DBNUMSETFLD: case RES_DBNEXTSETFLD: if( IsNameInArray( rOldNames, lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData()))) { ((SwDBNameInfField*)pFld)->SetDBData(aNewDBData); bExpand = sal_True; } // kein break; case RES_HIDDENTXTFLD: case RES_HIDDENPARAFLD: sFormel = pFld->GetPar1(); ReplaceUsedDBs( rOldNames, rNewName, sFormel); pFld->SetPar1( sFormel ); bExpand = sal_True; break; case RES_SETEXPFLD: case RES_GETEXPFLD: case RES_TABLEFLD: sFormel = pFld->GetFormula(); ReplaceUsedDBs( rOldNames, rNewName, sFormel); pFld->SetPar2( sFormel ); bExpand = sal_True; break; } if (bExpand) pTxtFld->ExpandAlways(); } SetModified(); } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ void SwDoc::ReplaceUsedDBs( const SvStringsDtor& rUsedDBNames, const String& rNewName, String& rFormel ) { const CharClass& rCC = GetAppCharClass(); String sFormel(rFormel); String sNewName( rNewName ); sNewName.SearchAndReplace( DB_DELIM, '.'); //the command type is not part of the condition sNewName = sNewName.GetToken(0, DB_DELIM); String sUpperNewNm( sNewName ); for( sal_uInt16 i = 0; i < rUsedDBNames.Count(); ++i ) { String sDBName( *rUsedDBNames.GetObject( i ) ); sDBName.SearchAndReplace( DB_DELIM, '.'); //cut off command type sDBName = sDBName.GetToken(0, DB_DELIM); if( !sDBName.Equals( sUpperNewNm )) { xub_StrLen nPos = 0; while ((nPos = sFormel.Search(sDBName, nPos)) != STRING_NOTFOUND) { if( sFormel.GetChar( nPos + sDBName.Len() ) == '.' && (!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 ))) { rFormel.Erase( nPos, sDBName.Len() ); rFormel.Insert( sNewName, nPos ); //prevent re-searching - this is useless and provokes //endless loops when names containing each other and numbers are exchanged //e.g.: old ?12345.12345 new: i12345.12345 nPos = nPos + sNewName.Len(); sFormel = rFormel; } } } } } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ sal_Bool SwDoc::IsNameInArray( const SvStringsDtor& rArr, const String& rName ) { #ifdef UNX for( sal_uInt16 i = 0; i < rArr.Count(); ++i ) if( rName == *rArr[ i ] ) return sal_True; #else const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore(); for( sal_uInt16 i = 0; i < rArr.Count(); ++i ) if( rSCmp.isEqual( rName, *rArr[ i] )) return sal_True; #endif return sal_False; } void SwDoc::SetFixFields( bool bOnlyTimeDate, const DateTime* pNewDateTime ) { sal_Bool bIsModified = IsModified(); sal_uLong nDate, nTime; if( pNewDateTime ) { nDate = pNewDateTime->GetDate(); nTime = pNewDateTime->GetTime(); } else { nDate = Date().GetDate(); nTime = Time().GetTime(); } sal_uInt16 aTypes[5] = { /*0*/ RES_DOCINFOFLD, /*1*/ RES_AUTHORFLD, /*2*/ RES_EXTUSERFLD, /*3*/ RES_FILENAMEFLD, /*4*/ RES_DATETIMEFLD }; // MUSS am Ende stehen!! sal_uInt16 nStt = bOnlyTimeDate ? 4 : 0; for( ; nStt < 5; ++nStt ) { SwFieldType* pFldType = GetSysFldType( aTypes[ nStt ] ); SwIterator aIter( *pFldType ); for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() ) { if( pFld && pFld->GetTxtFld() ) { sal_Bool bChgd = sal_False; switch( aTypes[ nStt ] ) { case RES_DOCINFOFLD: if( ((SwDocInfoField*)pFld->GetFld())->IsFixed() ) { bChgd = sal_True; SwDocInfoField* pDocInfFld = (SwDocInfoField*)pFld->GetFld(); pDocInfFld->SetExpansion( ((SwDocInfoFieldType*) pDocInfFld->GetTyp())->Expand( pDocInfFld->GetSubType(), pDocInfFld->GetFormat(), pDocInfFld->GetLanguage(), pDocInfFld->GetName() ) ); } break; case RES_AUTHORFLD: if( ((SwAuthorField*)pFld->GetFld())->IsFixed() ) { bChgd = sal_True; SwAuthorField* pAuthorFld = (SwAuthorField*)pFld->GetFld(); pAuthorFld->SetExpansion( ((SwAuthorFieldType*) pAuthorFld->GetTyp())->Expand( pAuthorFld->GetFormat() ) ); } break; case RES_EXTUSERFLD: if( ((SwExtUserField*)pFld->GetFld())->IsFixed() ) { bChgd = sal_True; SwExtUserField* pExtUserFld = (SwExtUserField*)pFld->GetFld(); pExtUserFld->SetExpansion( ((SwExtUserFieldType*) pExtUserFld->GetTyp())->Expand( pExtUserFld->GetSubType(), pExtUserFld->GetFormat())); } break; case RES_DATETIMEFLD: if( ((SwDateTimeField*)pFld->GetFld())->IsFixed() ) { bChgd = sal_True; ((SwDateTimeField*)pFld->GetFld())->SetDateTime( DateTime(Date(nDate), Time(nTime)) ); } break; case RES_FILENAMEFLD: if( ((SwFileNameField*)pFld->GetFld())->IsFixed() ) { bChgd = sal_True; SwFileNameField* pFileNameFld = (SwFileNameField*)pFld->GetFld(); pFileNameFld->SetExpansion( ((SwFileNameFieldType*) pFileNameFld->GetTyp())->Expand( pFileNameFld->GetFormat() ) ); } break; } // Formatierung anstossen if( bChgd ) pFld->ModifyNotification( 0, 0 ); } } } if( !bIsModified ) ResetModified(); } bool SwDoc::SetFieldsDirty( bool b, const SwNode* pChk, sal_uLong nLen ) { // teste ggfs. mal, ob die angegbenen Nodes ueberhaupt Felder beinhalten. // wenn nicht, braucht das Flag nicht veraendert werden. sal_Bool bFldsFnd = sal_False; if( b && pChk && !GetUpdtFlds().IsFieldsDirty() && !IsInDtor() // ?? was ist mit Undo, da will man es doch auch haben !! /*&& &pChk->GetNodes() == &GetNodes()*/ ) { b = sal_False; if( !nLen ) ++nLen; sal_uLong nStt = pChk->GetIndex(); const SwNodes& rNds = pChk->GetNodes(); while( nLen-- ) { const SwTxtNode* pTNd = rNds[ nStt++ ]->GetTxtNode(); if( pTNd ) { if( //pTNd->GetFmtColl() && //#outline level,zhaojianwei // MAXLEVEL > pTNd->GetTxtColl()->GetOutlineLevel() ) pTNd->GetAttrOutlineLevel() != 0 )//<-end,zhaojianwei // Kapitelfelder aktualisieren b = sal_True; else if( pTNd->GetpSwpHints() && pTNd->GetSwpHints().Count() ) for( sal_uInt16 n = 0, nEnd = pTNd->GetSwpHints().Count(); n < nEnd; ++n ) { const SwTxtAttr* pAttr = pTNd->GetSwpHints()[ n ]; if( RES_TXTATR_FIELD == pAttr->Which() ) { b = sal_True; break; } } if( b ) break; } } bFldsFnd = b; } GetUpdtFlds().SetFieldsDirty( b ); return bFldsFnd; } /* -----------------------------21.12.99 12:55-------------------------------- ---------------------------------------------------------------------------*/ void SwDoc::ChangeAuthorityData( const SwAuthEntry* pNewData ) { const sal_uInt16 nSize = pFldTypes->Count(); for( sal_uInt16 i = INIT_FLDTYPES; i < nSize; ++i ) { SwFieldType* pFldType = (*pFldTypes)[i]; if( RES_AUTHORITY == pFldType->Which() ) { SwAuthorityFieldType* pAuthType = (SwAuthorityFieldType*)pFldType; pAuthType->ChangeEntryContent(pNewData); break; } } } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ void SwDocUpdtFld::InsDelFldInFldLst( sal_Bool bIns, const SwTxtFld& rFld ) { sal_uInt16 nWhich = rFld.GetFld().GetFld()->GetTyp()->Which(); switch( nWhich ) { case RES_DBFLD: case RES_SETEXPFLD: case RES_HIDDENPARAFLD: case RES_HIDDENTXTFLD: case RES_DBNUMSETFLD: case RES_DBNEXTSETFLD: case RES_DBSETNUMBERFLD: case RES_GETEXPFLD: break; // diese muessen ein-/ausgetragen werden! default: return; } SetFieldsDirty( sal_True ); if( !pFldSortLst ) { if( !bIns ) // keine Liste vorhanden und loeschen return; // dann nichts tun pFldSortLst = new _SetGetExpFlds( 64, 16 ); } if( bIns ) // neu einfuegen: GetBodyNode( rFld, nWhich ); else { // ueber den pTxtFld Pointer suchen. Ist zwar eine Sortierte // Liste, aber nach Node-Positionen sortiert. Bis dieser // bestimmt ist, ist das Suchen nach dem Pointer schon fertig for( sal_uInt16 n = 0; n < pFldSortLst->Count(); ++n ) if( &rFld == (*pFldSortLst)[ n ]->GetPointer() ) pFldSortLst->DeleteAndDestroy( n--, 1 ); // ein Feld kann mehrfach vorhanden sein! } } void SwDocUpdtFld::MakeFldList( SwDoc& rDoc, int bAll, int eGetMode ) { if( !pFldSortLst || bAll || !( eGetMode & nFldLstGetMode ) || rDoc.GetNodes().Count() != nNodes ) _MakeFldList( rDoc, eGetMode ); } void SwDocUpdtFld::_MakeFldList( SwDoc& rDoc, int eGetMode ) { // neue Version: gehe ueber alle Felder vom Attribut-Pool if( pFldSortLst ) delete pFldSortLst; pFldSortLst = new _SetGetExpFlds( 64, 16 ); /// OD 09.08.2002 [#101207#,#101216#,#101778#] - consider and unhide sections /// with hide condition, only in mode GETFLD_ALL () /// notes by OD: /// eGetMode == GETFLD_CALC in call from methods SwDoc::FldsToCalc /// eGetMode == GETFLD_EXPAND in call from method SwDoc::FldsToExpand /// eGetMode == GETFLD_ALL in call from method SwDoc::UpdateExpFlds /// I figured out that hidden section only have to be shown, /// if fields have updated (call by SwDoc::UpdateExpFlds) and thus /// the hide conditions of section have to be updated. /// For correct updating the hide condition of a section, its position /// have to be known in order to insert the hide condition as a new /// expression field into the sorted field list (). if ( eGetMode == GETFLD_ALL ) // zuerst die Bereiche einsammeln. Alle die ueber Bedingung // gehiddet sind, wieder mit Frames versorgen, damit die darin // enthaltenen Felder richtig einsortiert werden!!! { // damit die Frames richtig angelegt werden, muessen sie in der // Reihenfolgen von oben nach unten expandiert werden SvULongs aTmpArr; SwSectionFmts& rArr = rDoc.GetSections(); SwSectionNode* pSectNd; sal_uInt16 nArrStt = 0; sal_uLong nSttCntnt = rDoc.GetNodes().GetEndOfExtras().GetIndex(); for (sal_uInt16 n = rArr.Count(); n; ) { SwSection* pSect = rArr[ --n ]->GetSection(); if( pSect && pSect->IsHidden() && pSect->GetCondition().Len() && 0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() )) { sal_uLong nIdx = pSectNd->GetIndex(); sal_uInt16 i; for( i = 0; i < aTmpArr.Count() && aTmpArr[ i ] < nIdx; ++i ) ; aTmpArr.Insert( nIdx, i ); if( nIdx < nSttCntnt ) ++nArrStt; } } // erst alle anzeigen, damit die Frames vorhanden sind. Mit deren // Position wird das BodyAnchor ermittelt. // Dafuer erst den ContentBereich, dann die Sonderbereiche!!! for (sal_uInt16 n = nArrStt; n < aTmpArr.Count(); ++n) { pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode(); ASSERT( pSectNd, "Wo ist mein SectionNode" ); pSectNd->GetSection().SetCondHidden( sal_False ); } for (sal_uInt16 n = 0; n < nArrStt; ++n) { pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode(); ASSERT( pSectNd, "Wo ist mein SectionNode" ); pSectNd->GetSection().SetCondHidden( sal_False ); } // so, erst jetzt alle sortiert in die Liste eintragen for (sal_uInt16 n = 0; n < aTmpArr.Count(); ++n) { GetBodyNode( *rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode() ); } } String sTrue( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "sal_True" ))), sFalse( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "sal_False" ))); sal_Bool bIsDBMgr = 0 != rDoc.GetNewDBMgr(); sal_uInt16 nWhich, n; const String* pFormel = 0; const SfxPoolItem* pItem; sal_uInt32 nMaxItems = rDoc.GetAttrPool().GetItemCount2( RES_TXTATR_FIELD ); for( n = 0; n < nMaxItems; ++n ) { if( 0 == (pItem = rDoc.GetAttrPool().GetItem2( RES_TXTATR_FIELD, n )) ) continue; const SwFmtFld* pFmtFld = (SwFmtFld*)pItem; const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld(); if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() ) continue; const SwField* pFld = pFmtFld->GetFld(); switch( nWhich = pFld->GetTyp()->Which() ) { case RES_DBSETNUMBERFLD: case RES_GETEXPFLD: if( GETFLD_ALL == eGetMode ) pFormel = &sTrue; break; case RES_DBFLD: if( GETFLD_EXPAND & eGetMode ) pFormel = &sTrue; break; case RES_SETEXPFLD: /// OD 04.10.2002 #102894# /// fields of subtype have also been add /// for calculation (eGetMode == GETFLD_CALC). /// Thus, add fields of subtype in all modes /// (eGetMode == GETFLD_EXPAND||GETFLD_CALC||GETFLD_ALL) /// and fields of other subtypes only in the modes /// (eGetMode == GETFLD_CALC||GETFLD_ALL) /* "old" if construct - not deleted for history and code review if( ( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() ? GETFLD_EXPAND : GETFLD_CALC ) & eGetMode ) */ if ( !(eGetMode == GETFLD_EXPAND) || (nsSwGetSetExpType::GSE_STRING & pFld->GetSubType()) ) { pFormel = &sTrue; } break; case RES_HIDDENPARAFLD: if( GETFLD_ALL == eGetMode ) { pFormel = &pFld->GetPar1(); if( !pFormel->Len() || pFormel->Equals( sFalse )) ((SwHiddenParaField*)pFld)->SetHidden( sal_False ); else if( pFormel->Equals( sTrue )) ((SwHiddenParaField*)pFld)->SetHidden( sal_True ); else break; pFormel = 0; // Formatierung anstossen ((SwFmtFld*)pFmtFld)->ModifyNotification( 0, 0 ); } break; case RES_HIDDENTXTFLD: if( GETFLD_ALL == eGetMode ) { pFormel = &pFld->GetPar1(); if( !pFormel->Len() || pFormel->Equals( sFalse )) ((SwHiddenTxtField*)pFld)->SetValue( sal_True ); else if( pFormel->Equals( sTrue )) ((SwHiddenTxtField*)pFld)->SetValue( sal_False ); else break; pFormel = 0; // Feld Evaluieren ((SwHiddenTxtField*)pFld)->Evaluate(&rDoc); // Formatierung anstossen ((SwFmtFld*)pFmtFld)->ModifyNotification( 0, 0 ); } break; case RES_DBNUMSETFLD: { SwDBData aDBData(((SwDBNumSetField*)pFld)->GetDBData(&rDoc)); if ( (bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) && (GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNumSetField*)pFld)->IsCondValid())) ) { pFormel = &pFld->GetPar1(); } } break; case RES_DBNEXTSETFLD: { SwDBData aDBData(((SwDBNextSetField*)pFld)->GetDBData(&rDoc)); if ( (bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) && (GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNextSetField*)pFld)->IsCondValid())) ) { pFormel = &pFld->GetPar1(); } } break; } if( pFormel && pFormel->Len() ) { GetBodyNode( *pTxtFld, nWhich ); pFormel = 0; } } nFldLstGetMode = static_cast( eGetMode ); nNodes = rDoc.GetNodes().Count(); #ifdef JP_DEBUG { SvFileStream sOut( "f:\\x.x", STREAM_STD_WRITE ); sOut.Seek( STREAM_SEEK_TO_END ); sOut << "------------------" << endl; const _SetGetExpFldPtr* pSortLst = pFldSortLst->GetData(); for( sal_uInt16 n = pFldSortLst->Count(); n; --n, ++pSortLst ) { String sStr( (*pSortLst)->GetNode() ); sStr += "\t, "; sStr += (*pSortLst)->GetCntnt(); sStr += "\tNode: "; sStr += (*pSortLst)->GetFld()->GetTxtNode().StartOfSectionIndex(); sStr += "\tPos: "; sStr += *(*pSortLst)->GetFld()->GetStart(); sStr += "\tType: "; sStr += (*pSortLst)->GetFld()->GetFld().GetFld()->GetTyp()->Which(); sOut << sStr.GetStr() << endl; } } #endif // JP_DEBUG } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ void SwDocUpdtFld::GetBodyNode( const SwTxtFld& rTFld, sal_uInt16 nFldWhich ) { const SwTxtNode& rTxtNd = rTFld.GetTxtNode(); const SwDoc& rDoc = *rTxtNd.GetDoc(); // immer den ersten !! (in Tab-Headline, Kopf-/Fuss ) Point aPt; const SwCntntFrm* pFrm = rTxtNd.getLayoutFrm( rDoc.GetCurrentLayout(), &aPt, 0, sal_False ); _SetGetExpFld* pNew = NULL; sal_Bool bIsInBody = sal_False; if( !pFrm || pFrm->IsInDocBody() ) { // einen Index fuers bestimmen vom TextNode anlegen SwNodeIndex aIdx( rTxtNd ); bIsInBody = rDoc.GetNodes().GetEndOfExtras().GetIndex() < aIdx.GetIndex(); // #104291# dvo: We don't want to update fields in redlines, or those // in frames whose anchor is in redline. However, we do want to update // fields in hidden sections. So: In order to be updated, a field 1) // must have a frame, or 2) it must be in the document body. if( (pFrm != NULL) || bIsInBody ) pNew = new _SetGetExpFld( aIdx, &rTFld ); } else { // einen Index fuers bestimmen vom TextNode anlegen SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() ); #ifdef DBG_UTIL ASSERT( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" ); #else GetBodyTxtNode( rDoc, aPos, *pFrm ); #endif pNew = new _SetGetExpFld( aPos.nNode, &rTFld, &aPos.nContent ); } // bei GetExp.-/DB.-Felder immer das BodyTxtFlag setzen if( RES_GETEXPFLD == nFldWhich ) { SwGetExpField* pGetFld = (SwGetExpField*)rTFld.GetFld().GetFld(); pGetFld->ChgBodyTxtFlag( bIsInBody ); } else if( RES_DBFLD == nFldWhich ) { SwDBField* pDBFld = (SwDBField*)rTFld.GetFld().GetFld(); pDBFld->ChgBodyTxtFlag( bIsInBody ); } if( pNew != NULL ) if( !pFldSortLst->Insert( pNew )) delete pNew; } void SwDocUpdtFld::GetBodyNode( const SwSectionNode& rSectNd ) { const SwDoc& rDoc = *rSectNd.GetDoc(); _SetGetExpFld* pNew = 0; if( rSectNd.GetIndex() < rDoc.GetNodes().GetEndOfExtras().GetIndex() ) { do { // middle check loop // dann muessen wir uns mal den Anker besorgen! // einen Index fuers bestimmen vom TextNode anlegen SwPosition aPos( rSectNd ); SwCntntNode* pCNd = rDoc.GetNodes().GoNext( &aPos.nNode ); // zum naechsten ContentNode if( !pCNd || !pCNd->IsTxtNode() ) break; // immer den ersten !! (in Tab-Headline, Kopf-/Fuss ) Point aPt; const SwCntntFrm* pFrm = pCNd->getLayoutFrm( rDoc.GetCurrentLayout(), &aPt, 0, sal_False ); if( !pFrm ) break; #ifdef DBG_UTIL ASSERT( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" ); #else GetBodyTxtNode( rDoc, aPos, *pFrm ); #endif pNew = new _SetGetExpFld( rSectNd, &aPos ); } while( sal_False ); } if( !pNew ) pNew = new _SetGetExpFld( rSectNd ); if( !pFldSortLst->Insert( pNew )) delete pNew; } void SwDocUpdtFld::InsertFldType( const SwFieldType& rType ) { String sFldName; switch( rType.Which() ) { case RES_USERFLD : sFldName = ((SwUserFieldType&)rType).GetName(); break; case RES_SETEXPFLD: sFldName = ((SwSetExpFieldType&)rType).GetName(); break; default: ASSERT( !this, "kein gueltiger FeldTyp" ); } if( sFldName.Len() ) { SetFieldsDirty( sal_True ); // suchen und aus der HashTabelle entfernen GetAppCharClass().toLower( sFldName ); sal_uInt16 n; SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n ); if( !pFnd ) { SwCalcFldType* pNew = new SwCalcFldType( sFldName, &rType ); pNew->pNext = aFldTypeTable[ n ]; aFldTypeTable[ n ] = pNew; } } } void SwDocUpdtFld::RemoveFldType( const SwFieldType& rType ) { String sFldName; switch( rType.Which() ) { case RES_USERFLD : sFldName = ((SwUserFieldType&)rType).GetName(); break; case RES_SETEXPFLD: sFldName = ((SwSetExpFieldType&)rType).GetName(); break; } if( sFldName.Len() ) { SetFieldsDirty( sal_True ); // suchen und aus der HashTabelle entfernen GetAppCharClass().toLower( sFldName ); sal_uInt16 n; SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n ); if( pFnd ) { if( aFldTypeTable[ n ] == pFnd ) aFldTypeTable[ n ] = (SwCalcFldType*)pFnd->pNext; else { SwHash* pPrev = aFldTypeTable[ n ]; while( pPrev->pNext != pFnd ) pPrev = pPrev->pNext; pPrev->pNext = pFnd->pNext; } pFnd->pNext = 0; delete pFnd; } } } SwDocUpdtFld::SwDocUpdtFld() : pFldSortLst(0), nFldUpdtPos(LONG_MAX), nFldLstGetMode(0) { bInUpdateFlds = bFldsDirty = sal_False; memset( aFldTypeTable, 0, sizeof( aFldTypeTable ) ); } SwDocUpdtFld::~SwDocUpdtFld() { delete pFldSortLst; for( sal_uInt16 n = 0; n < TBLSZ; ++n ) delete aFldTypeTable[n]; } // #111840# bool SwDoc::UpdateFld(SwTxtFld * pDstTxtFld, SwField & rSrcFld, SwMsgPoolItem * pMsgHnt, bool bUpdateFlds) { ASSERT(pDstTxtFld, "no field to update!"); sal_Bool bTblSelBreak = sal_False; SwFmtFld * pDstFmtFld = (SwFmtFld*)&pDstTxtFld->GetFld(); SwField * pDstFld = pDstFmtFld->GetFld(); sal_uInt16 nFldWhich = rSrcFld.GetTyp()->Which(); SwNodeIndex aTblNdIdx(pDstTxtFld->GetTxtNode()); if (pDstFld->GetTyp()->Which() == rSrcFld.GetTyp()->Which()) { if (GetIDocumentUndoRedo().DoesUndo()) { SwPosition aPosition( pDstTxtFld->GetTxtNode() ); aPosition.nContent = *pDstTxtFld->GetStart(); SwUndo *const pUndo( new SwUndoFieldFromDoc( aPosition, *pDstFld, rSrcFld, pMsgHnt, bUpdateFlds) ); GetIDocumentUndoRedo().AppendUndo(pUndo); } // Das gefundene Feld wird angepasst ... //pDstFld->ChangeFormat( rSrcFld.GetFormat() ); //pDstFld->SetLanguage( rSrcFld.GetLanguage() ); SwField * pNewFld = rSrcFld.CopyField(); pDstFmtFld->SetFld(pNewFld); switch( nFldWhich ) { case RES_SETEXPFLD: case RES_GETEXPFLD: case RES_HIDDENTXTFLD: case RES_HIDDENPARAFLD: UpdateExpFlds( pDstTxtFld, true ); break; case RES_TABLEFLD: { const SwTableNode* pTblNd = IsIdxInTbl(aTblNdIdx); if( pTblNd ) { SwTableFmlUpdate aTblUpdate( &pTblNd-> GetTable() ); if (bUpdateFlds) UpdateTblFlds( &aTblUpdate ); else pNewFld->GetTyp()->ModifyNotification(0, &aTblUpdate); if (! bUpdateFlds) bTblSelBreak = sal_True; } } break; case RES_MACROFLD: if( bUpdateFlds && pDstTxtFld->GetpTxtNode() ) (pDstTxtFld->GetpTxtNode())-> ModifyNotification( 0, pDstFmtFld ); break; case RES_DBNAMEFLD: case RES_DBNEXTSETFLD: case RES_DBNUMSETFLD: case RES_DBSETNUMBERFLD: ChgDBData(((SwDBNameInfField*) pNewFld)->GetRealDBData()); pNewFld->GetTyp()->UpdateFlds(); break; case RES_DBFLD: { // JP 10.02.96: ChgValue aufrufen, damit //die Format- aenderung den ContentString //richtig setzt SwDBField* pDBFld = (SwDBField*)pNewFld; if (pDBFld->IsInitialized()) pDBFld->ChgValue( pDBFld->GetValue(), sal_True ); pDBFld->ClearInitialized(); pDBFld->InitContent(); } // kein break; default: pDstFmtFld->ModifyNotification( 0, pMsgHnt ); } // Die Felder die wir berechnen koennen werden hier expli. // zum Update angestossen. if( nFldWhich == RES_USERFLD ) UpdateUsrFlds(); } return bTblSelBreak; } bool SwDoc::PutValueToField(const SwPosition & rPos, const Any& rVal, sal_uInt16 nWhich) { Any aOldVal; SwField * pField = GetField(rPos); if (GetIDocumentUndoRedo().DoesUndo() && pField->QueryValue(aOldVal, nWhich)) { SwUndo *const pUndo(new SwUndoFieldFromAPI(rPos, aOldVal, rVal, nWhich)); GetIDocumentUndoRedo().AppendUndo(pUndo); } return pField->PutValue(rVal, nWhich); }