diff options
Diffstat (limited to 'sw/source/core/doc/docfld.cxx')
-rw-r--r-- | sw/source/core/doc/docfld.cxx | 2821 |
1 files changed, 2821 insertions, 0 deletions
diff --git a/sw/source/core/doc/docfld.cxx b/sw/source/core/doc/docfld.cxx new file mode 100644 index 000000000000..f4e80e9de52a --- /dev/null +++ b/sw/source/core/doc/docfld.cxx @@ -0,0 +1,2821 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include <hintids.hxx> + +#include <string.h> +#include <float.h> +#include <tools/datetime.hxx> +#ifndef _SVSTDARR_HXX +#define _SVSTDARR_ULONGS +#include <svl/svarray.hxx> +#endif +#include <vcl/svapp.hxx> +#include <vcl/svapp.hxx> +#include <unotools/charclass.hxx> +#include <unotools/transliterationwrapper.hxx> +#include <doc.hxx> +#include <cntfrm.hxx> +#include <pam.hxx> +#include <ndtxt.hxx> +#include <swtable.hxx> +#include <calc.hxx> +#include <txtfld.hxx> +#include <fmtfld.hxx> +#include <tox.hxx> +#include <txttxmrk.hxx> +#include <docfld.hxx> // fuer Expression-Felder +#include <docufld.hxx> +#include <ddefld.hxx> +#include <usrfld.hxx> +#include <expfld.hxx> +#include <dbfld.hxx> +#include <flddat.hxx> +#include <chpfld.hxx> +#include <reffld.hxx> +#include <flddropdown.hxx> +#include <dbmgr.hxx> +#include <section.hxx> +#include <cellatr.hxx> +#include <docary.hxx> +#include <authfld.hxx> +#include <txtinet.hxx> +#include <fmtcntnt.hxx> +#ifndef _POOLFMT_HRC +#include <poolfmt.hrc> // fuer InitFldTypes +#endif + +#include <SwUndoField.hxx> + +using namespace ::com::sun::star::uno; + +extern BOOL IsFrameBehind( const SwTxtNode& rMyNd, USHORT nMySttPos, + const SwTxtNode& rBehindNd, USHORT 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) +{ + USHORT nSize = pFldTypes->Count(), + nFldWhich = rFldTyp.Which(); + + USHORT 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. + + USHORT nSize = pFldTypes->Count(), nFldWhich = rFldTyp.Which(); + USHORT 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 + USHORT 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( TRUE ); + break; + } + + // nicht gefunden, also eintragen und Flag loeschen + pFldTypes->Insert( &rFldTyp, nSize ); + switch( nFldWhich ) + { + case RES_SETEXPFLD: + ((SwSetExpFieldType&)rFldTyp).SetDeleted( FALSE ); + break; + case RES_USERFLD: + ((SwUserFieldType&)rFldTyp).SetDeleted( FALSE ); + break; + case RES_DDEFLD: + ((SwDDEFieldType&)rFldTyp).SetDeleted( FALSE ); + break; + } +} + +/*-------------------------------------------------------------------- + Beschreibung: Feldtypen loeschen + --------------------------------------------------------------------*/ + +void SwDoc::RemoveFldType(USHORT nFld) +{ + ASSERT( INIT_FLDTYPES <= nFld, "keine InitFields loeschen" ); + /* + * Abheangige Felder vorhanden -> ErrRaise + */ + USHORT nSize = pFldTypes->Count(); + if(nFld < nSize) + { + SwFieldType* pTmp = (*pFldTypes)[nFld]; + + // JP 29.07.96: opt. FeldListe fuer den Calculator vorbereiten: + USHORT 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( TRUE ); + else if( RES_USERFLD == nWhich ) + ((SwUserFieldType*)pTmp)->SetDeleted( TRUE ); + else + ((SwDDEFieldType*)pTmp)->SetDeleted( 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( USHORT nResId, const String& rName, + bool bDbFieldMatching // used in some UNO calls for RES_DBFLD + // to use different string matching code + // #i51815# + ) const +{ + USHORT 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( USHORT 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]->Modify( 0, &aUpdateDDE ); + } + else + (*pFldTypes)[i]->Modify( 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]->Modify( 0, pNewHt ); + } + } + + if( !IsExpFldsLocked() ) + UpdateExpFlds( 0, 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( USHORT 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( USHORT i = 0; i < pFldTypes->Count(); ++i ) + if( RES_GETREFFLD == ( pFldType = (*pFldTypes)[i] )->Which() ) + pFldType->Modify( 0, pHt ); +} + +void SwDoc::UpdateTblFlds( SfxPoolItem* pHt ) +{ + ASSERT( !pHt || RES_TABLEFML_UPDATE == pHt->Which(), + "Was ist das fuer ein MessageItem?" ); + + SwFieldType* pFldType(0); + USHORT i; + + for( 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; + + SwClientIter aIter( *pFldType ); + for( SwFmtFld* pFmtFld = (SwFmtFld*)aIter.First( TYPE( SwFmtFld )); + pFmtFld; pFmtFld = (SwFmtFld*)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( 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( FALSE ); + } + + break; + } + pFldType = 0; + } + + // und dann noch alle Tabellen Box Formeln abklappern + const SfxPoolItem* pItem; + USHORT nMaxItems = GetAttrPool().GetItemCount( RES_BOXATR_FORMULA ); + for( i = 0; i < nMaxItems; ++i ) + if( 0 != (pItem = GetAttrPool().GetItem( 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 ) + { + SwClient* pLast; + SwClientIter aIter( *pFldType ); + // dann rechne mal schoen + // JP 27.03.97: Beim Berechnen am Ende anfangen - weil neue + // Felder immer am Anfang der Modifykette eingefuegt + // werden. Beim Import haben wir damit eine bessere/ + // schnellere Berechnung bei "Kettenformeln" + if( 0 != ( pLast = aIter.GoEnd() )) + do { + SwFmtFld* pFmtFld = (SwFmtFld*)pLast; + 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.GetFrm( &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->Modify( 0, pHt ); + } while( 0 != ( pLast = aIter-- )); + } + + // dann berechene noch die Formeln an den Boxen + for( i = 0; i < nMaxItems; ++i ) + if( 0 != (pItem = GetAttrPool().GetItem( 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->GetFrm( &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( USHORT i = 0; i < INIT_FLDTYPES; ++i ) + switch( ( pFldType = (*pFldTypes)[ i ] )->Which() ) + { + case RES_PAGENUMBERFLD: + case RES_CHAPTERFLD: + case RES_GETEXPFLD: + case RES_REFPAGEGETFLD: + pFldType->Modify( 0, pMsgHnt ); + break; + case RES_DOCSTATFLD: + pFldType->Modify( 0, 0 ); + break; + } + SetNewFldLst(true); +} + +/*-------------------------------------------------------------------- + Beschreibung: + --------------------------------------------------------------------*/ + +// ---- Loesche alle nicht referenzierten FeldTypen eines Dokumentes -- +void SwDoc::GCFieldTypes() +{ + for( USHORT 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(); + } +} + +BOOL _SetGetExpFld::operator<( const _SetGetExpFld& rFld ) const +{ + if( nNode < rFld.nNode || ( nNode == rFld.nNode && nCntnt < rFld.nCntnt )) + return TRUE; + else if( nNode != rFld.nNode || nCntnt != rFld.nCntnt ) + return FALSE; + + const SwNode *pFirst = GetNodeFromCntnt(), + *pNext = rFld.GetNodeFromCntnt(); + + // Position gleich: nur weiter wenn beide FeldPointer besetzt sind !! + if( !pFirst || !pNext ) + return 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 +{ + USHORT 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, USHORT nSize, const String& rName, + String& rRet, USHORT* 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 USHORT 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 = FALSE; + + SwNewDBMgr* pMgr = GetNewDBMgr(); + pMgr->CloseAll(FALSE); + + if( pUpdtFlds->GetSortLst()->Count() ) + { + USHORT nLast; + _SetGetExpFld* pFld = (_SetGetExpFld*)&rToThisFld; + if( pUpdtFlds->GetSortLst()->Seek_Entry( pFld, &nLast ) ) + ++nLast; + + const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData(); + for( USHORT n = 0; n < nLast; ++n, ++ppSortLst ) + lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr ); + } + + pMgr->CloseAll(FALSE); +} + +void SwDoc::FldsToCalc( SwCalc& rCalc, ULONG nLastNd, sal_uInt16 nLastCnt ) +{ + // erzeuge die Sortierteliste aller SetFelder + pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC ); + mbNewFldLst = FALSE; + + SwNewDBMgr* pMgr = GetNewDBMgr(); + pMgr->CloseAll(FALSE); + + const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData(); + + for( USHORT n = pUpdtFlds->GetSortLst()->Count(); + n && + ( (*ppSortLst)->GetNode() < nLastNd || + ( (*ppSortLst)->GetNode() == nLastNd && (*ppSortLst)->GetCntnt() <= nLastCnt ) + ); + --n, ++ppSortLst ) + lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr ); + + pMgr->CloseAll(FALSE); +} + +void SwDoc::FldsToExpand( SwHash**& ppHashTbl, USHORT& rTblSize, + const _SetGetExpFld& rToThisFld ) +{ + // erzeuge die Sortierteliste aller SetFelder + pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_EXPAND ); + mbNewFldLst = 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 ); + + USHORT nLast; + { + _SetGetExpFld* pTmp = (_SetGetExpFld*)&rToThisFld; + if( pUpdtFlds->GetSortLst()->Seek_Entry( pTmp, &nLast ) ) + ++nLast; + } + + USHORT 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 <SwDoc::UpdateExpFlds(..)> 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; + + BOOL bOldInUpdateFlds = pUpdtFlds->IsInUpdateFlds(); + pUpdtFlds->SetInUpdateFlds( TRUE ); + + pUpdtFlds->MakeFldList( *this, TRUE, GETFLD_ALL ); + mbNewFldLst = FALSE; + + if( !pUpdtFlds->GetSortLst()->Count() ) + { + if( bUpdRefFlds ) + UpdateRefFlds(NULL); + + pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds ); + pUpdtFlds->SetFieldsDirty( FALSE ); + return ; + } + + USHORT nWhich, n; + + // HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt + // (versuche eine "ungerade"-Zahl zu erzeugen) + USHORT 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 ? + USHORT 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(FALSE); +/* + if(pMgr && pMgr->OpenDB(DBMGR_STD, GetDBDesc(), 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 ? + USHORT 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 ? + USHORT 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 BYTE 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->Modify( 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(FALSE); + // HashTabelle wieder loeschen + ::DeleteHashTable( pHashStrTbl, nStrFmtCnt ); + + // Referenzfelder updaten + if( bUpdRefFlds ) + UpdateRefFlds(NULL); + + pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds ); + pUpdtFlds->SetFieldsDirty( FALSE ); +} + +/*-------------------------------------------------------------------- + Beschreibung: + --------------------------------------------------------------------*/ + +void SwDoc::UpdateDBNumFlds( SwDBNameInfField& rDBFld, SwCalc& rCalc ) +{ + SwNewDBMgr* pMgr = GetNewDBMgr(); + + USHORT nFldType = rDBFld.Which(); + + 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 + USHORT 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 USHORT nSize = pFldTypes->Count(); + for(USHORT i = 0; i < nSize && !aDBData.sDataSource.getLength(); ++i) + { + SwFieldType& rFldType = *((*pFldTypes)[i]); + USHORT nWhich = rFldType.Which(); + if(IsUsed(rFldType)) + { + switch(nWhich) + { + case RES_DBFLD: + case RES_DBNEXTSETFLD: + case RES_DBNUMSETFLD: + case RES_DBSETNUMBERFLD: + { + SwClientIter aIter( rFldType ); + SwFmtFld* pFld = (SwFmtFld*)aIter.First( TYPE( SwFmtFld )); + while(pFld) + { + if(pFld->IsFldInDoc()) + { + if(RES_DBFLD == nWhich) + aDBData = + (static_cast < SwDBFieldType * > (pFld->GetFld()->GetTyp())) + ->GetDBData(); + else + aDBData = (static_cast < SwDBNameInfField* > (pFld->GetFld()))->GetRealDBData(); + break; + } + pFld = (SwFmtFld*)aIter.Next(); + } + } + break; + } + } + } + } + if(!aDBData.sDataSource.getLength()) + aDBData = GetNewDBMgr()->GetAddressDBName(); + return aDBData; +} + +void SwDoc::SetInitDBFields( 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 ) +{ + USHORT n; + SvStringsDtor aUsedDBNames; + SvStringsDtor aAllDBNames; + + if( !pAllDBNames ) + { + GetAllDBNames( aAllDBNames ); + pAllDBNames = &aAllDBNames; + } + + SwSectionFmts& rArr = GetSections(); + for( 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; + USHORT nMaxItems = GetAttrPool().GetItemCount( RES_TXTATR_FIELD ); + for( n = 0; n < nMaxItems; ++n ) + { + if( 0 == (pItem = GetAttrPool().GetItem( 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(USHORT 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 (USHORT 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 (USHORT 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( USHORT i = 0; i < rDBNameList.Count(); ++i ) + if( rDBName == rDBNameList.GetObject(i)->GetToken(0) ) + return; +#else + const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore(); + for( USHORT 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; + USHORT n; + + SwSectionFmts& rArr = GetSections(); + for( n = rArr.Count(); n; ) + { + SwSection* pSect = rArr[ --n ]->GetSection(); + + if( pSect ) + { + sFormel = pSect->GetCondition(); + ReplaceUsedDBs( rOldNames, rNewName, sFormel); + pSect->SetCondition(sFormel); + } + } + + const SfxPoolItem* pItem; + USHORT nMaxItems = GetAttrPool().GetItemCount( RES_TXTATR_FIELD ); + + for( n = 0; n < nMaxItems; ++n ) + { + if( 0 == (pItem = GetAttrPool().GetItem( RES_TXTATR_FIELD, n ) )) + continue; + + SwFmtFld* pFmtFld = (SwFmtFld*)pItem; + SwTxtFld* pTxtFld = pFmtFld->GetTxtFld(); + if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() ) + continue; + + SwField* pFld = pFmtFld->GetFld(); + BOOL bExpand = 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)); + + pTyp->Add(pFmtFld); // Feld auf neuen Typ umhaengen + pFld->ChgTyp(pTyp); + + ((SwDBField*)pFld)->ClearInitialized(); + ((SwDBField*)pFld)->InitContent(); + + bExpand = TRUE; + } + break; + + case RES_DBSETNUMBERFLD: + case RES_DBNAMEFLD: + if( IsNameInArray( rOldNames, + lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData()))) + { + ((SwDBNameInfField*)pFld)->SetDBData(aNewDBData); + bExpand = TRUE; + } + break; + + case RES_DBNUMSETFLD: + case RES_DBNEXTSETFLD: + if( IsNameInArray( rOldNames, + lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData()))) + { + ((SwDBNameInfField*)pFld)->SetDBData(aNewDBData); + bExpand = TRUE; + } + // kein break; + case RES_HIDDENTXTFLD: + case RES_HIDDENPARAFLD: + sFormel = pFld->GetPar1(); + ReplaceUsedDBs( rOldNames, rNewName, sFormel); + pFld->SetPar1( sFormel ); + bExpand = TRUE; + break; + + case RES_SETEXPFLD: + case RES_GETEXPFLD: + case RES_TABLEFLD: + sFormel = pFld->GetFormula(); + ReplaceUsedDBs( rOldNames, rNewName, sFormel); + pFld->SetPar2( sFormel ); + bExpand = 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( USHORT 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: + --------------------------------------------------------------------*/ + +BOOL SwDoc::IsNameInArray( const SvStringsDtor& rArr, const String& rName ) +{ +#ifdef UNX + for( USHORT i = 0; i < rArr.Count(); ++i ) + if( rName == *rArr[ i ] ) + return TRUE; +#else + const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore(); + for( USHORT i = 0; i < rArr.Count(); ++i ) + if( rSCmp.isEqual( rName, *rArr[ i] )) + return TRUE; +#endif + return FALSE; +} + +void SwDoc::SetFixFields( bool bOnlyTimeDate, const DateTime* pNewDateTime ) +{ + BOOL bIsModified = IsModified(); + + ULONG nDate, nTime; + if( pNewDateTime ) + { + nDate = pNewDateTime->GetDate(); + nTime = pNewDateTime->GetTime(); + } + else + { + nDate = Date().GetDate(); + nTime = Time().GetTime(); + } + + USHORT aTypes[5] = { + /*0*/ RES_DOCINFOFLD, + /*1*/ RES_AUTHORFLD, + /*2*/ RES_EXTUSERFLD, + /*3*/ RES_FILENAMEFLD, + /*4*/ RES_DATETIMEFLD }; // MUSS am Ende stehen!! + + USHORT nStt = bOnlyTimeDate ? 4 : 0; + + for( ; nStt < 5; ++nStt ) + { + SwFieldType* pFldType = GetSysFldType( aTypes[ nStt ] ); + SwClientIter aDocInfIter( *pFldType ); + + for( SwFmtFld* pFld = (SwFmtFld*)aDocInfIter.First( TYPE( SwFmtFld )); + pFld; pFld = (SwFmtFld*)aDocInfIter.Next() ) + { + if( pFld && pFld->GetTxtFld() ) + { + BOOL bChgd = FALSE; + switch( aTypes[ nStt ] ) + { + case RES_DOCINFOFLD: + if( ((SwDocInfoField*)pFld->GetFld())->IsFixed() ) + { + bChgd = 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 = TRUE; + SwAuthorField* pAuthorFld = (SwAuthorField*)pFld->GetFld(); + pAuthorFld->SetExpansion( ((SwAuthorFieldType*) + pAuthorFld->GetTyp())->Expand( + pAuthorFld->GetFormat() ) ); + } + break; + + case RES_EXTUSERFLD: + if( ((SwExtUserField*)pFld->GetFld())->IsFixed() ) + { + bChgd = 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 = TRUE; + ((SwDateTimeField*)pFld->GetFld())->SetDateTime( + DateTime(Date(nDate), Time(nTime)) ); + } + break; + + case RES_FILENAMEFLD: + if( ((SwFileNameField*)pFld->GetFld())->IsFixed() ) + { + bChgd = TRUE; + SwFileNameField* pFileNameFld = + (SwFileNameField*)pFld->GetFld(); + pFileNameFld->SetExpansion( ((SwFileNameFieldType*) + pFileNameFld->GetTyp())->Expand( + pFileNameFld->GetFormat() ) ); + } + break; + } + + // Formatierung anstossen + if( bChgd ) + pFld->Modify( 0, 0 ); + } + } + } + + if( !bIsModified ) + ResetModified(); +} + +bool SwDoc::SetFieldsDirty( bool b, const SwNode* pChk, ULONG nLen ) +{ + // teste ggfs. mal, ob die angegbenen Nodes ueberhaupt Felder beinhalten. + // wenn nicht, braucht das Flag nicht veraendert werden. + BOOL bFldsFnd = FALSE; + if( b && pChk && !GetUpdtFlds().IsFieldsDirty() && !IsInDtor() + // ?? was ist mit Undo, da will man es doch auch haben !! + /*&& &pChk->GetNodes() == &GetNodes()*/ ) + { + b = FALSE; + if( !nLen ) + ++nLen; + 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 = TRUE; + else if( pTNd->GetpSwpHints() && pTNd->GetSwpHints().Count() ) + for( USHORT n = 0, nEnd = pTNd->GetSwpHints().Count(); + n < nEnd; ++n ) + { + const SwTxtAttr* pAttr = pTNd->GetSwpHints()[ n ]; + if( RES_TXTATR_FIELD == pAttr->Which() ) + { + b = TRUE; + break; + } + } + + if( b ) + break; + } + } + bFldsFnd = b; + } + GetUpdtFlds().SetFieldsDirty( b ); + return bFldsFnd; +} +/* -----------------------------21.12.99 12:55-------------------------------- + + ---------------------------------------------------------------------------*/ +void SwDoc::ChangeAuthorityData( const SwAuthEntry* pNewData ) +{ + const USHORT nSize = pFldTypes->Count(); + + for( USHORT 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( BOOL bIns, const SwTxtFld& rFld ) +{ + USHORT 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( 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( USHORT 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 (<eGetMode == 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 (<pFldSortLst>). + 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; + USHORT nArrStt = 0; + ULONG nSttCntnt = rDoc.GetNodes().GetEndOfExtras().GetIndex(); + USHORT n; + + for( n = rArr.Count(); n; ) + { + SwSection* pSect = rArr[ --n ]->GetSection(); + if( pSect && pSect->IsHidden() && pSect->GetCondition().Len() && + 0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() )) + { + ULONG nIdx = pSectNd->GetIndex(); + USHORT 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( n = nArrStt; n < aTmpArr.Count(); ++n ) + { + pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode(); + ASSERT( pSectNd, "Wo ist mein SectionNode" ); + pSectNd->GetSection().SetCondHidden( FALSE ); + } + for( n = 0; n < nArrStt; ++n ) + { + pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode(); + ASSERT( pSectNd, "Wo ist mein SectionNode" ); + pSectNd->GetSection().SetCondHidden( FALSE ); + } + + // so, erst jetzt alle sortiert in die Liste eintragen + for( n = 0; n < aTmpArr.Count(); ++n ) + GetBodyNode( *rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode() ); + } + + String sTrue( String::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( "TRUE" ))), + sFalse( String::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( "FALSE" ))); + + BOOL bIsDBMgr = 0 != rDoc.GetNewDBMgr(); + USHORT nWhich, n; + const String* pFormel = 0; + const SfxPoolItem* pItem; + USHORT nMaxItems = rDoc.GetAttrPool().GetItemCount( RES_TXTATR_FIELD ); + for( n = 0; n < nMaxItems; ++n ) + { + if( 0 == (pItem = rDoc.GetAttrPool().GetItem( 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 <string> have also been add + /// for calculation (eGetMode == GETFLD_CALC). + /// Thus, add fields of subtype <string> 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( FALSE ); + else if( pFormel->Equals( sTrue )) + ((SwHiddenParaField*)pFld)->SetHidden( TRUE ); + else + break; + + pFormel = 0; + // Formatierung anstossen + ((SwFmtFld*)pFmtFld)->Modify( 0, 0 ); + } + break; + + case RES_HIDDENTXTFLD: + if( GETFLD_ALL == eGetMode ) + { + pFormel = &pFld->GetPar1(); + if( !pFormel->Len() || pFormel->Equals( sFalse )) + ((SwHiddenTxtField*)pFld)->SetValue( TRUE ); + else if( pFormel->Equals( sTrue )) + ((SwHiddenTxtField*)pFld)->SetValue( FALSE ); + else + break; + + pFormel = 0; + + // Feld Evaluieren + ((SwHiddenTxtField*)pFld)->Evaluate(&rDoc); + // Formatierung anstossen + ((SwFmtFld*)pFmtFld)->Modify( 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<BYTE>( 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( USHORT 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, USHORT 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.GetFrm( &aPt, 0, FALSE ); + + _SetGetExpFld* pNew = NULL; + BOOL bIsInBody = 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->GetFrm( &aPt, 0, 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( 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( TRUE ); + // suchen und aus der HashTabelle entfernen + GetAppCharClass().toLower( sFldName ); + USHORT 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( TRUE ); + // suchen und aus der HashTabelle entfernen + GetAppCharClass().toLower( sFldName ); + USHORT 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 = FALSE; + memset( aFldTypeTable, 0, sizeof( aFldTypeTable ) ); +} + +SwDocUpdtFld::~SwDocUpdtFld() +{ + delete pFldSortLst; + + for( USHORT 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!"); + + BOOL bTblSelBreak = FALSE; + + SwFmtFld * pDstFmtFld = (SwFmtFld*)&pDstTxtFld->GetFld(); + SwField * pDstFld = pDstFmtFld->GetFld(); + USHORT nFldWhich = rSrcFld.GetTyp()->Which(); + SwNodeIndex aTblNdIdx(pDstTxtFld->GetTxtNode()); + + if (pDstFld->GetTyp()->Which() == + rSrcFld.GetTyp()->Which()) + { + if (DoesUndo()) + { + SwPosition aPosition( pDstTxtFld->GetTxtNode() ); + aPosition.nContent = *pDstTxtFld->GetStart(); + + AppendUndo(new SwUndoFieldFromDoc(aPosition, *pDstFld, rSrcFld, + pMsgHnt, bUpdateFlds)); + } + + // 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()->Modify(0, &aTblUpdate); + + if (! bUpdateFlds) + bTblSelBreak = TRUE; + } + } + break; + + case RES_MACROFLD: + if( bUpdateFlds && pDstTxtFld->GetpTxtNode() ) + (pDstTxtFld->GetpTxtNode())-> + Modify( 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(), TRUE ); + + pDBFld->ClearInitialized(); + pDBFld->InitContent(); + } + // kein break; + + default: + pDstFmtFld->Modify( 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, USHORT nWhich) +{ + Any aOldVal; + SwField * pField = GetField(rPos); + + + if (DoesUndo() && pField->QueryValue(aOldVal, nWhich)) + AppendUndo(new SwUndoFieldFromAPI(rPos, aOldVal, rVal, nWhich)); + + return pField->PutValue(rVal, nWhich); +} |