blob: 1b194a113df694447815997edabc8eec146b1a72 [file] [log] [blame]
/**************************************************************
*
* 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 <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 <IDocumentUndoRedo.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>
#include <poolfmt.hrc> // fuer InitFldTypes
#include <SwUndoField.hxx>
#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<SwFmtFld,SwFieldType> aIter( *pFldType );
for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
{
if( pFmtFld->GetTxtFld() )
{
SwTblField* pFld = (SwTblField*)pFmtFld->GetField();
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<SwFmtFld,SwFieldType> 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->GetField())->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
{
return nNode == rFld.nNode
&& nCntnt == rFld.nCntnt
&& ( !CNTNT.pTxtFld
|| !rFld.CNTNT.pTxtFld
|| CNTNT.pTxtFld == rFld.CNTNT.pTxtFld );
}
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.GetTxtFld();
if( !pTxtFld )
return ;
const SwField* pFld = pTxtFld->GetFmtFld().GetField();
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)->GetTxtFld();
if( !pTxtFld )
continue;
const SwField* pFld = pTxtFld->GetFmtFld().GetField();
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;
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
SwSbxValue aValue = aCalc.Calculate(
pSect->GetCondition() );
if(!aValue.IsVoidValue())
pSect->SetCondHidden( aValue.GetBool() );
continue;
}
SwTxtFld* pTxtFld = (SwTxtFld*)(*ppSortLst)->GetTxtFld();
if( !pTxtFld )
{
ASSERT( !this, "was ist es denn nun" );
continue;
}
SwFmtFld* pFmtFld = (SwFmtFld*)&pTxtFld->GetFmtFld();
const SwField* pFld = pFmtFld->GetField();
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<SwFmtFld,SwFieldType> aIter( rFldType );
for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
{
if(pFld->IsFldInDoc())
{
if(RES_DBFLD == nWhich)
aDBData = (static_cast < SwDBFieldType * > (pFld->GetField()->GetTyp()))->GetDBData();
else
aDBData = (static_cast < SwDBNameInfField* > (pFld->GetField()))->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->GetField();
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->GetField();
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->ExpandTxtFld( true );
}
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<SwFmtFld,SwFieldType> aIter( *pFldType );
for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
{
if( pFmtFld && pFmtFld->GetTxtFld() )
{
sal_Bool bChgd = sal_False;
switch( aTypes[ nStt ] )
{
case RES_DOCINFOFLD:
if( ((SwDocInfoField*)pFmtFld->GetField())->IsFixed() )
{
bChgd = sal_True;
SwDocInfoField* pDocInfFld = (SwDocInfoField*)pFmtFld->GetField();
pDocInfFld->SetExpansion( ((SwDocInfoFieldType*)
pDocInfFld->GetTyp())->Expand(
pDocInfFld->GetSubType(),
pDocInfFld->GetFormat(),
pDocInfFld->GetLanguage(),
pDocInfFld->GetName() ) );
}
break;
case RES_AUTHORFLD:
if( ((SwAuthorField*)pFmtFld->GetField())->IsFixed() )
{
bChgd = sal_True;
SwAuthorField* pAuthorFld = (SwAuthorField*)pFmtFld->GetField();
pAuthorFld->SetExpansion( ((SwAuthorFieldType*)
pAuthorFld->GetTyp())->Expand(
pAuthorFld->GetFormat() ) );
}
break;
case RES_EXTUSERFLD:
if( ((SwExtUserField*)pFmtFld->GetField())->IsFixed() )
{
bChgd = sal_True;
SwExtUserField* pExtUserFld = (SwExtUserField*)pFmtFld->GetField();
pExtUserFld->SetExpansion( ((SwExtUserFieldType*)
pExtUserFld->GetTyp())->Expand(
pExtUserFld->GetSubType(),
pExtUserFld->GetFormat()));
}
break;
case RES_DATETIMEFLD:
if( ((SwDateTimeField*)pFmtFld->GetField())->IsFixed() )
{
bChgd = sal_True;
((SwDateTimeField*)pFmtFld->GetField())->SetDateTime(
DateTime(Date(nDate), Time(nTime)) );
}
break;
case RES_FILENAMEFLD:
if( ((SwFileNameField*)pFmtFld->GetField())->IsFixed() )
{
bChgd = sal_True;
SwFileNameField* pFileNameFld =
(SwFileNameField*)pFmtFld->GetField();
pFileNameFld->SetExpansion( ((SwFileNameFieldType*)
pFileNameFld->GetTyp())->Expand(
pFileNameFld->GetFormat() ) );
}
break;
}
// Formatierung anstossen
if( bChgd )
pFmtFld->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 ( pAttr->Which() == RES_TXTATR_FIELD )
{
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 )
{
const sal_uInt16 nWhich = rFld.GetFmtFld().GetField()->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 (<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;
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->GetField();
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:
/// 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( 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<sal_uInt8>( 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.GetFmtFld().GetField();
pGetFld->ChgBodyTxtFlag( bIsInBody );
}
else if( RES_DBFLD == nFldWhich )
{
SwDBField* pDBFld = (SwDBField*)rTFld.GetFmtFld().GetField();
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->GetFmtFld();
SwField * pDstFld = pDstFmtFld->GetField();
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);
}
SwField * pNewFld = rSrcFld.CopyField();
pDstFmtFld->SetField(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 = GetFieldAtPos(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);
}