Files
libreoffice/sw/source/core/doc/docfld.cxx

2830 lines
95 KiB
C++
Raw Normal View History

2000-09-18 23:08:29 +00:00
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2000-09-18 23:08:29 +00:00
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
2000-09-18 23:08:29 +00:00
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 23:08:29 +00:00
*
* This file is part of OpenOffice.org.
2000-09-18 23:08:29 +00:00
*
* 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.
2000-09-18 23:08:29 +00:00
*
* 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).
2000-09-18 23:08:29 +00:00
*
* 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.
2000-09-18 23:08:29 +00:00
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
2000-09-18 23:08:29 +00:00
#include <hintids.hxx>
#include <string.h>
#include <float.h>
#include <tools/datetime.hxx>
#ifndef _SVSTDARR_HXX
#define _SVSTDARR_ULONGS
#include <svl/svarray.hxx>
2000-09-18 23:08:29 +00:00
#endif
#include <vcl/svapp.hxx>
#include <vcl/svapp.hxx>
#include <unotools/charclass.hxx>
#include <unotools/transliterationwrapper.hxx>
2000-09-18 23:08:29 +00:00
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
2000-09-18 23:08:29 +00:00
#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>
2000-09-18 23:08:29 +00:00
#include <dbmgr.hxx>
#include <section.hxx>
#include <cellatr.hxx>
#include <docary.hxx>
#include <authfld.hxx>
#include <txtinet.hxx>
#include <fmtcntnt.hxx>
2000-09-18 23:08:29 +00:00
#include <poolfmt.hrc> // fuer InitFldTypes
#include <SwUndoField.hxx>
using namespace ::com::sun::star::uno;
2000-09-18 23:08:29 +00:00
extern sal_Bool IsFrameBehind( const SwTxtNode& rMyNd, sal_uInt16 nMySttPos,
const SwTxtNode& rBehindNd, sal_uInt16 nSttPos );
2000-09-18 23:08:29 +00:00
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(),
2000-09-18 23:08:29 +00:00
nFldWhich = rFldTyp.Which();
sal_uInt16 i = INIT_FLDTYPES;
2000-09-18 23:08:29 +00:00
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() )
2000-09-18 23:08:29 +00:00
i -= INIT_SEQ_FLDTYPES;
// kein break;
case RES_DBFLD:
case RES_USERFLD:
case RES_DDEFLD:
{
const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
2000-09-18 23:08:29 +00:00
String sFldNm( rFldTyp.GetName() );
for( ; i < nSize; ++i )
if( nFldWhich == (*pFldTypes)[i]->Which() &&
rSCmp.isEqual( sFldNm, (*pFldTypes)[i]->GetName() ))
2000-09-18 23:08:29 +00:00
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;
2000-09-18 23:08:29 +00:00
ASSERT( RES_SETEXPFLD == nFldWhich ||
RES_USERFLD == nFldWhich ||
RES_DDEFLD == nFldWhich, "Falscher FeldTyp" );
const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
2000-09-18 23:08:29 +00:00
const String& rFldNm = rFldTyp.GetName();
SwFieldType* pFnd;
for( ; i < nSize; ++i )
if( nFldWhich == (pFnd = (*pFldTypes)[i])->Which() &&
rSCmp.isEqual( rFldNm, pFnd->GetName() ) )
2000-09-18 23:08:29 +00:00
{
// neuen Namen suchen
sal_uInt16 nNum = 1;
2000-09-18 23:08:29 +00:00
do {
String sSrch( rFldNm );
2000-09-18 23:08:29 +00:00
sSrch.Append( String::CreateFromInt32( nNum ));
for( i = INIT_FLDTYPES; i < nSize; ++i )
if( nFldWhich == (pFnd = (*pFldTypes)[i])->Which() &&
rSCmp.isEqual( sSrch, pFnd->GetName() ) )
2000-09-18 23:08:29 +00:00
break;
if( i >= nSize ) // nicht gefunden
{
((String&)rFldNm) = sSrch;
2000-09-18 23:08:29 +00:00
break; // raus aus der While-Schleife
}
++nNum;
} while( sal_True );
2000-09-18 23:08:29 +00:00
break;
}
// nicht gefunden, also eintragen und Flag loeschen
pFldTypes->Insert( &rFldTyp, nSize );
switch( nFldWhich )
{
case RES_SETEXPFLD:
((SwSetExpFieldType&)rFldTyp).SetDeleted( sal_False );
2000-09-18 23:08:29 +00:00
break;
case RES_USERFLD:
((SwUserFieldType&)rFldTyp).SetDeleted( sal_False );
2000-09-18 23:08:29 +00:00
break;
case RES_DDEFLD:
((SwDDEFieldType&)rFldTyp).SetDeleted( sal_False );
2000-09-18 23:08:29 +00:00
break;
}
}
/*--------------------------------------------------------------------
Beschreibung: Feldtypen loeschen
--------------------------------------------------------------------*/
void SwDoc::RemoveFldType(sal_uInt16 nFld)
2000-09-18 23:08:29 +00:00
{
ASSERT( INIT_FLDTYPES <= nFld, "keine InitFields loeschen" );
/*
* Abheangige Felder vorhanden -> ErrRaise
*/
sal_uInt16 nSize = pFldTypes->Count();
2000-09-18 23:08:29 +00:00
if(nFld < nSize)
{
SwFieldType* pTmp = (*pFldTypes)[nFld];
// JP 29.07.96: opt. FeldListe fuer den Calculator vorbereiten:
sal_uInt16 nWhich = pTmp->Which();
2000-09-18 23:08:29 +00:00
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 );
2000-09-18 23:08:29 +00:00
else if( RES_USERFLD == nWhich )
((SwUserFieldType*)pTmp)->SetDeleted( sal_True );
2000-09-18 23:08:29 +00:00
else
((SwDDEFieldType*)pTmp)->SetDeleted( sal_True );
2000-09-18 23:08:29 +00:00
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;
}
2000-09-18 23:08:29 +00:00
/*--------------------------------------------------------------------
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
2000-09-18 23:08:29 +00:00
{
sal_uInt16 nSize = pFldTypes->Count(), i = 0;
const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
2000-09-18 23:08:29 +00:00
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 ))
2000-09-18 23:08:29 +00:00
{
pRet = pFldType;
break;
2000-09-18 23:08:29 +00:00
}
}
return pRet;
}
/*************************************************************************
|* SwDoc::UpdateFlds()
|* Beschreibung Felder updaten
*************************************************************************/
/*
* Alle sollen neu evaluiert werden.
*/
void SwDoc::UpdateFlds( SfxPoolItem *pNewHt, bool bCloseDB )
2000-09-18 23:08:29 +00:00
{
// Modify() fuer jeden Feldtypen rufen,
// abhaengige SwTxtFld werden benachrichtigt ...
for( sal_uInt16 i=0; i < pFldTypes->Count(); ++i)
2000-09-18 23:08:29 +00:00
{
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, sal_False ); // Expression-Felder Updaten
2000-09-18 23:08:29 +00:00
// 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 )
2000-09-18 23:08:29 +00:00
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 )
2000-09-18 23:08:29 +00:00
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);
for (sal_uInt16 i = 0; i < pFldTypes->Count(); ++i)
2000-09-18 23:08:29 +00:00
{
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() )
2000-09-18 23:08:29 +00:00
pFld->PtrToBoxNm( pUpdtFld->pTbl );
else
pFld->ChgValid( sal_False );
2000-09-18 23:08:29 +00:00
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;
2000-09-18 23:08:29 +00:00
}
}
else
// setze bei allen das Value-Flag zurueck
pFld->ChgValid( sal_False );
2000-09-18 23:08:29 +00:00
}
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 ) ) &&
2000-09-18 23:08:29 +00:00
((SwTblBoxFormula*)pItem)->GetDefinedIn() )
{
((SwTblBoxFormula*)pItem)->ChangeState( pHt );
}
}
2000-09-18 23:08:29 +00:00
// 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 &
2000-09-18 23:08:29 +00:00
(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
2000-09-18 23:08:29 +00:00
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 (sal_uInt32 i = 0; i < nMaxItems; ++i )
{
if( 0 != (pItem = GetAttrPool().GetItem2( RES_BOXATR_FORMULA, i ) ) &&
2000-09-18 23:08:29 +00:00
((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
2000-09-18 23:08:29 +00:00
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 );
2000-09-18 23:08:29 +00:00
pCalc->SetCalcError( CALC_NOERR );
}
}
}
}
2000-09-18 23:08:29 +00:00
if( pCalc )
delete pCalc;
}
void SwDoc::UpdatePageFlds( SfxPoolItem* pMsgHnt )
{
SwFieldType* pFldType;
for( sal_uInt16 i = 0; i < INIT_FLDTYPES; ++i )
2000-09-18 23:08:29 +00:00
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);
2000-09-18 23:08:29 +00:00
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
// ---- Loesche alle nicht referenzierten FeldTypen eines Dokumentes --
void SwDoc::GCFieldTypes()
{
for( sal_uInt16 n = pFldTypes->Count(); n > INIT_FLDTYPES; )
2000-09-18 23:08:29 +00:00
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;
}
2000-09-18 23:08:29 +00:00
//----------------------------------------------------------------------
// 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();
}
2000-09-18 23:08:29 +00:00
//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;
}
}
2000-09-18 23:08:29 +00:00
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
2000-09-18 23:08:29 +00:00
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
2000-09-18 23:08:29 +00:00
{
if( nNode < rFld.nNode || ( nNode == rFld.nNode && nCntnt < rFld.nCntnt ))
return sal_True;
2000-09-18 23:08:29 +00:00
else if( nNode != rFld.nNode || nCntnt != rFld.nCntnt )
return sal_False;
2000-09-18 23:08:29 +00:00
const SwNode *pFirst = GetNodeFromCntnt(),
*pNext = rFld.GetNodeFromCntnt();
// Position gleich: nur weiter wenn beide FeldPointer besetzt sind !!
if( !pFirst || !pNext )
return sal_False;
2000-09-18 23:08:29 +00:00
// 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;
2000-09-18 23:08:29 +00:00
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;
2000-09-18 23:08:29 +00:00
}
return pRet;
}
xub_StrLen _SetGetExpFld::GetCntPosFromCntnt() const
2000-09-18 23:08:29 +00:00
{
sal_uInt16 nRet = 0;
2000-09-18 23:08:29 +00:00
if( CNTNT.pTxtFld )
switch( eSetGetExpFldType )
{
case TEXTFIELD:
case TEXTINET:
case TEXTTOXMARK:
2000-09-18 23:08:29 +00:00
nRet = *CNTNT.pTxtFld->GetStart();
break;
case CRSRPOS:
nRet = CNTNT.pPos->nContent.GetIndex();
break;
default:
break;
2000-09-18 23:08:29 +00:00
}
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 )
2000-09-18 23:08:29 +00:00
{
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();
2000-09-18 23:08:29 +00:00
if( aDBData != aDocData )
{
sDBNumNm = aDBData.sDataSource;
2000-09-18 23:08:29 +00:00
sDBNumNm += DB_DELIM;
sDBNumNm += String(aDBData.sCommand);
sDBNumNm += DB_DELIM;
}
2000-09-18 23:08:29 +00:00
sDBNumNm += SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD);
return sDBNumNm;
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
void lcl_CalcFld( SwDoc& rDoc, SwCalc& rCalc, const _SetGetExpFld& rSGEFld,
SwNewDBMgr* pMgr )
{
const SwTxtFld* pTxtFld = rSGEFld.GetFld();
if( !pTxtFld )
return ;
const SwField* pFld = pTxtFld->GetFld().GetFld();
const sal_uInt16 nFldWhich = pFld->GetTyp()->Which();
2000-09-18 23:08:29 +00:00
if( RES_SETEXPFLD == nFldWhich )
{
SwSbxValue aValue;
if( nsSwGetSetExpType::GSE_EXPR & pFld->GetSubType() )
2000-09-18 23:08:29 +00:00
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));
2000-09-18 23:08:29 +00:00
if( pDBFld->IsCondValid() &&
pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand ))
2000-09-18 23:08:29 +00:00
rCalc.VarChange( lcl_GetDBVarName( rDoc, *pDBFld),
pDBFld->GetFormat() );
}
break;
case RES_DBNEXTSETFLD:
{
SwDBNextSetField* pDBFld = (SwDBNextSetField*)pFld;
SwDBData aDBData(pDBFld->GetDBData(&rDoc));
2000-09-18 23:08:29 +00:00
if( !pDBFld->IsCondValid() ||
!pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand ))
2000-09-18 23:08:29 +00:00
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;
2000-09-18 23:08:29 +00:00
SwNewDBMgr* pMgr = GetNewDBMgr();
pMgr->CloseAll(sal_False);
2000-09-18 23:08:29 +00:00
if( pUpdtFlds->GetSortLst()->Count() )
{
sal_uInt16 nLast;
2000-09-18 23:08:29 +00:00
_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 )
2000-09-18 23:08:29 +00:00
lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr );
}
pMgr->CloseAll(sal_False);
2000-09-18 23:08:29 +00:00
}
void SwDoc::FldsToCalc( SwCalc& rCalc, sal_uLong nLastNd, sal_uInt16 nLastCnt )
2000-09-18 23:08:29 +00:00
{
// erzeuge die Sortierteliste aller SetFelder
pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC );
mbNewFldLst = sal_False;
2000-09-18 23:08:29 +00:00
SwNewDBMgr* pMgr = GetNewDBMgr();
pMgr->CloseAll(sal_False);
2000-09-18 23:08:29 +00:00
const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
for( sal_uInt16 n = pUpdtFlds->GetSortLst()->Count();
n &&
( (*ppSortLst)->GetNode() < nLastNd ||
( (*ppSortLst)->GetNode() == nLastNd && (*ppSortLst)->GetCntnt() <= nLastCnt )
);
2000-09-18 23:08:29 +00:00
--n, ++ppSortLst )
lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr );
pMgr->CloseAll(sal_False);
2000-09-18 23:08:29 +00:00
}
void SwDoc::FldsToExpand( SwHash**& ppHashTbl, sal_uInt16& rTblSize,
2000-09-18 23:08:29 +00:00
const _SetGetExpFld& rToThisFld )
{
// erzeuge die Sortierteliste aller SetFelder
pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_EXPAND );
mbNewFldLst = sal_False;
2000-09-18 23:08:29 +00:00
// 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;
2000-09-18 23:08:29 +00:00
{
_SetGetExpFld* pTmp = (_SetGetExpFld*)&rToThisFld;
if( pUpdtFlds->GetSortLst()->Seek_Entry( pTmp, &nLast ) )
++nLast;
}
sal_uInt16 nPos;
2000-09-18 23:08:29 +00:00
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() )
2000-09-18 23:08:29 +00:00
{
// 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 );
2000-09-18 23:08:29 +00:00
// 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()));
2000-09-18 23:08:29 +00:00
if( pFnd )
{
2000-09-18 23:08:29 +00:00
// Eintrag in der HashTabelle aendern
static_cast<_HashStr*>(pFnd)->aSetStr = value;
}
2000-09-18 23:08:29 +00:00
else
{
2000-09-18 23:08:29 +00:00
// neuen Eintrag einfuegen
*(ppHashTbl + nPos ) = new _HashStr( rName,
value, static_cast<_HashStr *>(*(ppHashTbl + nPos)));
}
2000-09-18 23:08:29 +00:00
}
break;
}
}
}
void SwDoc::UpdateExpFlds( SwTxtFld* pUpdtFld, bool bUpdRefFlds )
2000-09-18 23:08:29 +00:00
{
if( IsExpFldsLocked() || IsInReading() )
2000-09-18 23:08:29 +00:00
return;
sal_Bool bOldInUpdateFlds = pUpdtFlds->IsInUpdateFlds();
pUpdtFlds->SetInUpdateFlds( sal_True );
2000-09-18 23:08:29 +00:00
pUpdtFlds->MakeFldList( *this, sal_True, GETFLD_ALL );
mbNewFldLst = sal_False;
2000-09-18 23:08:29 +00:00
if( !pUpdtFlds->GetSortLst()->Count() )
{
if( bUpdRefFlds )
UpdateRefFlds(NULL);
2000-09-18 23:08:29 +00:00
pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds );
pUpdtFlds->SetFieldsDirty( sal_False );
2000-09-18 23:08:29 +00:00
return ;
}
sal_uInt16 nWhich, n;
2000-09-18 23:08:29 +00:00
// HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt
// (versuche eine "ungerade"-Zahl zu erzeugen)
sal_uInt16 nStrFmtCnt = (( pFldTypes->Count() / 7 ) + 1 ) * 7;
2000-09-18 23:08:29 +00:00
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;
2000-09-18 23:08:29 +00:00
const String& rNm = pFldType->GetName();
String sExpand(((SwUserFieldType*)pFldType)->Expand(nsSwGetSetExpType::GSE_STRING, 0, 0));
2000-09-18 23:08:29 +00:00
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);
2000-09-18 23:08:29 +00:00
/*
if(pMgr && pMgr->OpenDB(DBMGR_STD, GetDBDesc(), sal_False))
2000-09-18 23:08:29 +00:00
{
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() );
2000-09-18 23:08:29 +00:00
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);
}
2000-09-18 23:08:29 +00:00
}
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 );
2000-09-18 23:08:29 +00:00
}
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());
2000-09-18 23:08:29 +00:00
if( pMgr->IsDataSourceOpen(aTmpDBData.sDataSource, aTmpDBData.sCommand, sal_False))
aCalc.VarChange( sDBNumNm, pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType));
2000-09-18 23:08:29 +00:00
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;
2000-09-18 23:08:29 +00:00
SwHash* pFnd = Find( rName, pHashStrTbl, nStrFmtCnt, &nPos );
String const value(pFld->ExpandField(IsClipBoard()));
2000-09-18 23:08:29 +00:00
if( pFnd )
{
2000-09-18 23:08:29 +00:00
// Eintrag in der HashTabelle aendern
static_cast<_HashStr*>(pFnd)->aSetStr = value;
}
2000-09-18 23:08:29 +00:00
else
{
2000-09-18 23:08:29 +00:00
// neuen Eintrag einfuegen
*(pHashStrTbl + nPos ) = new _HashStr( rName,
value, static_cast<_HashStr *>(*(pHashStrTbl + nPos)));
}
2000-09-18 23:08:29 +00:00
}
break;
case RES_GETEXPFLD:
case RES_SETEXPFLD:
{
if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() ) // String Ersetzung
2000-09-18 23:08:29 +00:00
{
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;
2000-09-18 23:08:29 +00:00
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() );
2000-09-18 23:08:29 +00:00
}
}
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();
2000-09-18 23:08:29 +00:00
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();
2000-09-18 23:08:29 +00:00
// nur ein spezielles Feld updaten ?
if( !aValue.IsVoidValue() && (!pUpdtFld || pUpdtFld == pTxtFld) )
2000-09-18 23:08:29 +00:00
{
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(sal_False);
2000-09-18 23:08:29 +00:00
// HashTabelle wieder loeschen
::DeleteHashTable( pHashStrTbl, nStrFmtCnt );
// Referenzfelder updaten
if( bUpdRefFlds )
UpdateRefFlds(NULL);
2000-09-18 23:08:29 +00:00
pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds );
pUpdtFlds->SetFieldsDirty( sal_False );
2000-09-18 23:08:29 +00:00
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
void SwDoc::UpdateDBNumFlds( SwDBNameInfField& rDBFld, SwCalc& rCalc )
{
SwNewDBMgr* pMgr = GetNewDBMgr();
sal_uInt16 nFldType = rDBFld.Which();
2000-09-18 23:08:29 +00:00
sal_Bool bPar1 = rCalc.Calculate( rDBFld.GetPar1() ).GetBool();
2000-09-18 23:08:29 +00:00
if( RES_DBNEXTSETFLD == nFldType )
((SwDBNextSetField&)rDBFld).SetCondValid( bPar1 );
else
((SwDBNumSetField&)rDBFld).SetCondValid( bPar1 );
if( rDBFld.GetRealDBData().sDataSource.getLength() )
2000-09-18 23:08:29 +00:00
{
// Eine bestimmte Datenbank bearbeiten
if( RES_DBNEXTSETFLD == nFldType )
((SwDBNextSetField&)rDBFld).Evaluate(this);
else
((SwDBNumSetField&)rDBFld).Evaluate(this);
SwDBData aTmpDBData( rDBFld.GetDBData(this) );
2000-09-18 23:08:29 +00:00
if( pMgr->OpenDataSource( aTmpDBData.sDataSource, aTmpDBData.sCommand, -1, false ))
2000-09-18 23:08:29 +00:00
rCalc.VarChange( lcl_GetDBVarName( *this, rDBFld),
pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType) );
2000-09-18 23:08:29 +00:00
}
else
{
DBG_ERROR("TODO: what should happen with unnamed DBFields?");
2000-09-18 23:08:29 +00:00
}
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
void SwDoc::_InitFieldTypes() // wird vom CTOR gerufen!!
{
// Feldtypen
sal_uInt16 nFldType = 0;
2000-09-18 23:08:29 +00:00
pFldTypes->Insert( new SwDateTimeFieldType(this), nFldType++ );
pFldTypes->Insert( new SwChapterFieldType, nFldType++ );
pFldTypes->Insert( new SwPageNumberFieldType, nFldType++ );
2001-01-18 13:08:36 +00:00
pFldTypes->Insert( new SwAuthorFieldType, nFldType++ );
2000-09-18 23:08:29 +00:00
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++ );
2000-09-18 23:08:29 +00:00
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++ );
2001-01-18 13:08:36 +00:00
pFldTypes->Insert( new SwCombinedCharFieldType, nFldType++ );
pFldTypes->Insert( new SwDropDownFieldType, nFldType++ );
2000-09-18 23:08:29 +00:00
// 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++);
2000-09-18 23:08:29 +00:00
pFldTypes->Insert( new SwSetExpFieldType(this,
SW_RESSTR(STR_POOLCOLL_LABEL_TABLE), nsSwGetSetExpType::GSE_SEQ),nFldType++);
2000-09-18 23:08:29 +00:00
pFldTypes->Insert( new SwSetExpFieldType(this,
SW_RESSTR(STR_POOLCOLL_LABEL_FRAME), nsSwGetSetExpType::GSE_SEQ),nFldType++);
2000-09-18 23:08:29 +00:00
pFldTypes->Insert( new SwSetExpFieldType(this,
SW_RESSTR(STR_POOLCOLL_LABEL_DRAWING), nsSwGetSetExpType::GSE_SEQ),nFldType++);
2000-09-18 23:08:29 +00:00
ASSERT( nFldType == INIT_FLDTYPES, "Bad initsize: SwFldTypes" );
}
void SwDoc::InsDelFldInFldLst( bool bIns, const SwTxtFld& rFld )
2000-09-18 23:08:29 +00:00
{
if( !mbNewFldLst || !IsInDtor() )
2000-09-18 23:08:29 +00:00
pUpdtFlds->InsDelFldInFldLst( bIns, rFld );
}
SwDBData SwDoc::GetDBData()
2000-09-18 23:08:29 +00:00
{
return GetDBDesc();
}
const SwDBData& SwDoc::GetDBDesc()
2000-09-18 23:08:29 +00:00
{
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:
{
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;
2000-09-18 23:08:29 +00:00
}
void SwDoc::SetInitDBFields( sal_Bool b )
2000-09-18 23:08:29 +00:00
{
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;
}
2000-09-18 23:08:29 +00:00
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; )
2000-09-18 23:08:29 +00:00
{
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)
2000-09-18 23:08:29 +00:00
{
if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) ))
2000-09-18 23:08:29 +00:00
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() ));
2000-09-18 23:08:29 +00:00
break;
case RES_DBSETNUMBERFLD:
case RES_DBNAMEFLD:
AddUsedDBToList( rDBNameList,
lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() ));
2000-09-18 23:08:29 +00:00
break;
case RES_DBNUMSETFLD:
case RES_DBNEXTSETFLD:
AddUsedDBToList( rDBNameList,
lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() ));
2000-09-18 23:08:29 +00:00
// 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++)
2000-09-18 23:08:29 +00:00
{
SwDSParam* pParam = rArr[i];
String* pStr = new String( pParam->sDataSource );
(*pStr) += DB_DELIM;
(*pStr) += (String)pParam->sCommand;
2000-09-18 23:08:29 +00:00
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 )
2000-09-18 23:08:29 +00:00
{
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++)
2000-09-18 23:08:29 +00:00
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
2000-09-18 23:08:29 +00:00
SwDBData aData;
aData.sDataSource = rDBName.GetToken(0, DB_DELIM);
aData.sCommand = rDBName.GetToken(1, DB_DELIM);
aData.nCommandType = -1;
GetNewDBMgr()->CreateDSData(aData);
2000-09-18 23:08:29 +00:00
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();
2000-09-18 23:08:29 +00:00
String sFormel;
SwSectionFmts& rArr = GetSections();
for (sal_uInt16 n = rArr.Count(); n; )
2000-09-18 23:08:29 +00:00
{
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 );
2000-09-18 23:08:29 +00:00
for (sal_uInt32 n = 0; n < nMaxItems; ++n )
2000-09-18 23:08:29 +00:00
{
if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) ))
2000-09-18 23:08:29 +00:00
continue;
SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
continue;
SwField* pFld = pFmtFld->GetFld();
sal_Bool bExpand = sal_False;
2000-09-18 23:08:29 +00:00
switch( pFld->GetTyp()->Which() )
{
case RES_DBFLD:
if( IsNameInArray( rOldNames, lcl_DBDataToString(((SwDBField*)pFld)->GetDBData())))
2000-09-18 23:08:29 +00:00
{
SwDBFieldType* pOldTyp = (SwDBFieldType*)pFld->GetTyp();
SwDBFieldType* pTyp = (SwDBFieldType*)InsertFldType(
SwDBFieldType(this, pOldTyp->GetColumnName(), aNewDBData));
2000-09-18 23:08:29 +00:00
pTyp->Add(pFmtFld); // Feld auf neuen Typ umhaengen
pFld->ChgTyp(pTyp);
((SwDBField*)pFld)->ClearInitialized();
((SwDBField*)pFld)->InitContent();
bExpand = sal_True;
2000-09-18 23:08:29 +00:00
}
break;
case RES_DBSETNUMBERFLD:
case RES_DBNAMEFLD:
if( IsNameInArray( rOldNames,
lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData())))
2000-09-18 23:08:29 +00:00
{
((SwDBNameInfField*)pFld)->SetDBData(aNewDBData);
bExpand = sal_True;
2000-09-18 23:08:29 +00:00
}
break;
case RES_DBNUMSETFLD:
case RES_DBNEXTSETFLD:
if( IsNameInArray( rOldNames,
lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData())))
2000-09-18 23:08:29 +00:00
{
((SwDBNameInfField*)pFld)->SetDBData(aNewDBData);
bExpand = sal_True;
2000-09-18 23:08:29 +00:00
}
// kein break;
case RES_HIDDENTXTFLD:
case RES_HIDDENPARAFLD:
sFormel = pFld->GetPar1();
ReplaceUsedDBs( rOldNames, rNewName, sFormel);
pFld->SetPar1( sFormel );
bExpand = sal_True;
2000-09-18 23:08:29 +00:00
break;
case RES_SETEXPFLD:
case RES_GETEXPFLD:
case RES_TABLEFLD:
sFormel = pFld->GetFormula();
ReplaceUsedDBs( rOldNames, rNewName, sFormel);
pFld->SetPar2( sFormel );
bExpand = sal_True;
2000-09-18 23:08:29 +00:00
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);
2000-09-18 23:08:29 +00:00
String sUpperNewNm( sNewName );
for( sal_uInt16 i = 0; i < rUsedDBNames.Count(); ++i )
2000-09-18 23:08:29 +00:00
{
String sDBName( *rUsedDBNames.GetObject( i ) );
sDBName.SearchAndReplace( DB_DELIM, '.');
//cut off command type
sDBName = sDBName.GetToken(0, DB_DELIM);
if( !sDBName.Equals( sUpperNewNm ))
2000-09-18 23:08:29 +00:00
{
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();
2000-09-18 23:08:29 +00:00
sFormel = rFormel;
}
}
}
}
}
/*--------------------------------------------------------------------
Beschreibung:
--------------------------------------------------------------------*/
sal_Bool SwDoc::IsNameInArray( const SvStringsDtor& rArr, const String& rName )
2000-09-18 23:08:29 +00:00
{
#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;
2000-09-18 23:08:29 +00:00
}
void SwDoc::SetFixFields( bool bOnlyTimeDate, const DateTime* pNewDateTime )
2000-09-18 23:08:29 +00:00
{
sal_Bool bIsModified = IsModified();
2000-09-18 23:08:29 +00:00
sal_uLong nDate, nTime;
2000-09-18 23:08:29 +00:00
if( pNewDateTime )
{
nDate = pNewDateTime->GetDate();
nTime = pNewDateTime->GetTime();
}
else
{
nDate = Date().GetDate();
nTime = Time().GetTime();
}
sal_uInt16 aTypes[5] = {
2000-09-18 23:08:29 +00:00
/*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;
2000-09-18 23:08:29 +00:00
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() )
{
sal_Bool bChgd = sal_False;
2000-09-18 23:08:29 +00:00
switch( aTypes[ nStt ] )
{
case RES_DOCINFOFLD:
if( ((SwDocInfoField*)pFld->GetFld())->IsFixed() )
{
bChgd = sal_True;
2000-09-18 23:08:29 +00:00
SwDocInfoField* pDocInfFld = (SwDocInfoField*)pFld->GetFld();
pDocInfFld->SetExpansion( ((SwDocInfoFieldType*)
pDocInfFld->GetTyp())->Expand(
pDocInfFld->GetSubType(),
pDocInfFld->GetFormat(),
pDocInfFld->GetLanguage(),
pDocInfFld->GetName() ) );
2000-09-18 23:08:29 +00:00
}
break;
case RES_AUTHORFLD:
if( ((SwAuthorField*)pFld->GetFld())->IsFixed() )
{
bChgd = sal_True;
2000-09-18 23:08:29 +00:00
SwAuthorField* pAuthorFld = (SwAuthorField*)pFld->GetFld();
pAuthorFld->SetExpansion( ((SwAuthorFieldType*)
pAuthorFld->GetTyp())->Expand(
pAuthorFld->GetFormat() ) );
}
break;
case RES_EXTUSERFLD:
if( ((SwExtUserField*)pFld->GetFld())->IsFixed() )
{
bChgd = sal_True;
2000-09-18 23:08:29 +00:00
SwExtUserField* pExtUserFld = (SwExtUserField*)pFld->GetFld();
pExtUserFld->SetExpansion( ((SwExtUserFieldType*)
pExtUserFld->GetTyp())->Expand(
pExtUserFld->GetSubType(),
pExtUserFld->GetFormat()));
}
break;
case RES_DATETIMEFLD:
if( ((SwDateTimeField*)pFld->GetFld())->IsFixed() )
{
bChgd = sal_True;
2000-09-18 23:08:29 +00:00
((SwDateTimeField*)pFld->GetFld())->SetDateTime(
DateTime(Date(nDate), Time(nTime)) );
2000-09-18 23:08:29 +00:00
}
break;
case RES_FILENAMEFLD:
if( ((SwFileNameField*)pFld->GetFld())->IsFixed() )
{
bChgd = sal_True;
2000-09-18 23:08:29 +00:00
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, sal_uLong nLen )
2000-09-18 23:08:29 +00:00
{
// teste ggfs. mal, ob die angegbenen Nodes ueberhaupt Felder beinhalten.
// wenn nicht, braucht das Flag nicht veraendert werden.
sal_Bool bFldsFnd = sal_False;
2000-09-18 23:08:29 +00:00
if( b && pChk && !GetUpdtFlds().IsFieldsDirty() && !IsInDtor()
// ?? was ist mit Undo, da will man es doch auch haben !!
/*&& &pChk->GetNodes() == &GetNodes()*/ )
{
b = sal_False;
2000-09-18 23:08:29 +00:00
if( !nLen )
++nLen;
sal_uLong nStt = pChk->GetIndex();
2000-09-18 23:08:29 +00:00
const SwNodes& rNds = pChk->GetNodes();
while( nLen-- )
{
const SwTxtNode* pTNd = rNds[ nStt++ ]->GetTxtNode();
if( pTNd )
{
CWS-TOOLING: integrate CWS outlinelevel 2008-12-19 10:32:51 +0100 od r265718 : #i70748# method <SwWW8Writer::StartTOX(..)> - correction for custom to outline style assigned paragraph styles 2008-12-19 09:24:41 +0100 od r265715 : #i70748# method <HandleModifyAtTxtNode(..)> - retrieve former applied list style before potential reset of empty list style due to set outline level 2008-12-17 15:33:57 +0100 hde r265608 : #i97013# 2008-12-17 14:43:42 +0100 od r265603 : #i70748# adjust fix i44177 - adjustment of to outline style assigned paragraph styles only for OOo-Templates. 2008-12-17 12:59:42 +0100 od r265598 : #i70748# method <XMLTextImportHelper::SetStyleAndAttrs(..)> - special handling of OOo 2.x document regarding outline numbering of headings. 2008-12-17 12:45:53 +0100 od r265597 : #i70748# method <HandleModifyAtTxtNode(..)> - correct determination of new and former applied list style 2008-12-17 10:18:41 +0100 od r265581 : #i97312# method <XMLTextNumRuleInfo::Set(..)> - check, if numbering rules instance contains any numbering rule. 2008-12-16 14:34:22 +0100 hde r265542 : #i97013 2008-12-16 14:20:24 +0100 od r265541 : #i70748# adjust documentation of "Which"-ID numbers 2008-12-16 14:19:49 +0100 od r265539 : #i70748# Adjust Attribute-Function-Mapping table due to new attribute 2008-12-16 14:06:24 +0100 od r265538 : #i70748# - Correct handling of to outline style assigned paragraph styles on reset of all paragraph style attributes - WW8 import: Consider refactoring of paragraph style's outline level attribute - NO_NUMBERING define no longer exsits. 2008-12-16 10:37:19 +0100 od r265530 : #i70478# Correction on moving outline paragraph up respectively down in its outline level: - Check also outline paragraph, which are not an outline via a to outline style assigned paragraph style, if action is applicable. 2008-12-16 09:10:13 +0100 hde r265523 : #i97277 2008-12-16 09:09:30 +0100 hde r265522 : #i97277 2008-12-16 09:07:40 +0100 hde r265521 : Added control and purged obsolete id's 2008-12-10 13:09:36 +0100 od r265174 : #i70748# correction of previous fix due to warning-free code 2008-12-10 13:03:30 +0100 od r265172 : #i70748# method <XMLTextImportHelper::SetStyleAndAttrs(..)> - Due to performance issues avoid retrieving outline level value from paragraph's paragraph style for each paragraph. Instead retrieve current outline level value from paragraph, which is the inherited value from its paragraph style, and only when it is needed. 2008-12-09 16:50:36 +0100 ufi r265117 : help 2008-12-09 16:49:50 +0100 ufi r265116 : help 2008-12-09 15:45:05 +0100 od r265107 : #i70748# method <XMLTextImportHelper::SetStyleAndAttrs(..)> - some minor rework and check access to paragraph styles 2008-12-09 15:42:04 +0100 od r265106 : #i70748# adjust name of local variable to avoid hiding of class variable 2008-12-09 15:40:51 +0100 od r265105 : #i70748# correct initialization order 2008-12-09 15:35:07 +0100 od r265101 : #i70748# remove duplicate entry in certain property map 2008-12-09 15:33:39 +0100 od r265100 : #i70748# add end of file token 2008-12-07 15:11:54 +0100 zhaojianwei r264952 : conflicts left not to be resolved when cws rebase 2008-12-04 14:52:21 +0100 zhaojianwei r264846 : CWS-TOOLING: rebase CWS outlinelevel to trunk@264325 (milestone: DEV300:m36) 2008-11-28 03:42:09 +0100 zhaojianwei r264525 : #i70748#: migrate CWS outlinelevel to SVN 2008-11-28 03:41:39 +0100 zhaojianwei r264524 : #i70748#: migrate CWS outlinelevel to SVN 2008-11-28 03:41:11 +0100 zhaojianwei r264523 : #i70748#: migrate CWS outlinelevel to SVN
2009-01-07 11:57:24 +00:00
if( //pTNd->GetFmtColl() && //#outline level,zhaojianwei
// MAXLEVEL > pTNd->GetTxtColl()->GetOutlineLevel() )
pTNd->GetAttrOutlineLevel() != 0 )//<-end,zhaojianwei
2000-09-18 23:08:29 +00:00
// Kapitelfelder aktualisieren
b = sal_True;
2000-09-18 23:08:29 +00:00
else if( pTNd->GetpSwpHints() && pTNd->GetSwpHints().Count() )
for( sal_uInt16 n = 0, nEnd = pTNd->GetSwpHints().Count();
2000-09-18 23:08:29 +00:00
n < nEnd; ++n )
{
const SwTxtAttr* pAttr = pTNd->GetSwpHints()[ n ];
if( RES_TXTATR_FIELD == pAttr->Which() )
{
b = sal_True;
2000-09-18 23:08:29 +00:00
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();
2000-09-18 23:08:29 +00:00
for( sal_uInt16 i = INIT_FLDTYPES; i < nSize; ++i )
2000-09-18 23:08:29 +00:00
{
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 )
2000-09-18 23:08:29 +00:00
{
sal_uInt16 nWhich = rFld.GetFld().GetFld()->GetTyp()->Which();
2000-09-18 23:08:29 +00:00
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 );
2000-09-18 23:08:29 +00:00
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 )
2000-09-18 23:08:29 +00:00
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 );
}
2000-09-18 23:08:29 +00:00
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 )
2000-09-18 23:08:29 +00:00
// 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; )
2000-09-18 23:08:29 +00:00
{
SwSection* pSect = rArr[ --n ]->GetSection();
if( pSect && pSect->IsHidden() && pSect->GetCondition().Len() &&
2000-09-18 23:08:29 +00:00
0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() ))
{
sal_uLong nIdx = pSectNd->GetIndex();
sal_uInt16 i;
for( i = 0; i < aTmpArr.Count() && aTmpArr[ i ] < nIdx; ++i )
2000-09-18 23:08:29 +00:00
;
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)
2000-09-18 23:08:29 +00:00
{
pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
ASSERT( pSectNd, "Wo ist mein SectionNode" );
pSectNd->GetSection().SetCondHidden( sal_False );
2000-09-18 23:08:29 +00:00
}
for (sal_uInt16 n = 0; n < nArrStt; ++n)
2000-09-18 23:08:29 +00:00
{
pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
ASSERT( pSectNd, "Wo ist mein SectionNode" );
pSectNd->GetSection().SetCondHidden( sal_False );
2000-09-18 23:08:29 +00:00
}
// so, erst jetzt alle sortiert in die Liste eintragen
for (sal_uInt16 n = 0; n < aTmpArr.Count(); ++n)
{
2000-09-18 23:08:29 +00:00
GetBodyNode( *rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode() );
}
2000-09-18 23:08:29 +00:00
}
String sTrue( String::CreateFromAscii(
RTL_CONSTASCII_STRINGPARAM( "sal_True" ))),
2000-09-18 23:08:29 +00:00
sFalse( String::CreateFromAscii(
RTL_CONSTASCII_STRINGPARAM( "sal_False" )));
2000-09-18 23:08:29 +00:00
sal_Bool bIsDBMgr = 0 != rDoc.GetNewDBMgr();
sal_uInt16 nWhich, n;
2000-09-18 23:08:29 +00:00
const String* pFormel = 0;
const SfxPoolItem* pItem;
sal_uInt32 nMaxItems = rDoc.GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
2000-09-18 23:08:29 +00:00
for( n = 0; n < nMaxItems; ++n )
{
if( 0 == (pItem = rDoc.GetAttrPool().GetItem2( RES_TXTATR_FIELD, n )) )
2000-09-18 23:08:29 +00:00
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()
2000-09-18 23:08:29 +00:00
? GETFLD_EXPAND : GETFLD_CALC )
& eGetMode )
*/
if ( !(eGetMode == GETFLD_EXPAND) ||
(nsSwGetSetExpType::GSE_STRING & pFld->GetSubType()) )
{
2000-09-18 23:08:29 +00:00
pFormel = &sTrue;
}
2000-09-18 23:08:29 +00:00
break;
case RES_HIDDENPARAFLD:
if( GETFLD_ALL == eGetMode )
{
pFormel = &pFld->GetPar1();
if( !pFormel->Len() || pFormel->Equals( sFalse ))
((SwHiddenParaField*)pFld)->SetHidden( sal_False );
2000-09-18 23:08:29 +00:00
else if( pFormel->Equals( sTrue ))
((SwHiddenParaField*)pFld)->SetHidden( sal_True );
2000-09-18 23:08:29 +00:00
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( sal_True );
2000-09-18 23:08:29 +00:00
else if( pFormel->Equals( sTrue ))
((SwHiddenTxtField*)pFld)->SetValue( sal_False );
2000-09-18 23:08:29 +00:00
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));
2000-09-18 23:08:29 +00:00
if (
(bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) &&
(GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNumSetField*)pFld)->IsCondValid()))
)
{
2000-09-18 23:08:29 +00:00
pFormel = &pFld->GetPar1();
}
2000-09-18 23:08:29 +00:00
}
break;
case RES_DBNEXTSETFLD:
{
SwDBData aDBData(((SwDBNextSetField*)pFld)->GetDBData(&rDoc));
2000-09-18 23:08:29 +00:00
if (
(bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) &&
(GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNextSetField*)pFld)->IsCondValid()))
)
{
2000-09-18 23:08:29 +00:00
pFormel = &pFld->GetPar1();
}
2000-09-18 23:08:29 +00:00
}
break;
}
if( pFormel && pFormel->Len() )
{
GetBodyNode( *pTxtFld, nWhich );
pFormel = 0;
}
}
nFldLstGetMode = static_cast<sal_uInt8>( eGetMode );
2000-09-18 23:08:29 +00:00
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 )
2000-09-18 23:08:29 +00:00
{
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 )
2000-09-18 23:08:29 +00:00
{
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, sal_False );
2000-09-18 23:08:29 +00:00
_SetGetExpFld* pNew = NULL;
sal_Bool bIsInBody = sal_False;
2000-09-18 23:08:29 +00:00
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 );
2000-09-18 23:08:29 +00:00
}
else
{
// einen Index fuers bestimmen vom TextNode anlegen
SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() );
#ifdef DBG_UTIL
2000-09-18 23:08:29 +00:00
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;
2000-09-18 23:08:29 +00:00
}
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, sal_False );
2000-09-18 23:08:29 +00:00
if( !pFrm )
break;
#ifdef DBG_UTIL
2000-09-18 23:08:29 +00:00
ASSERT( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" );
#else
GetBodyTxtNode( rDoc, aPos, *pFrm );
#endif
pNew = new _SetGetExpFld( rSectNd, &aPos );
} while( sal_False );
2000-09-18 23:08:29 +00:00
}
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 );
2000-09-18 23:08:29 +00:00
// suchen und aus der HashTabelle entfernen
GetAppCharClass().toLower( sFldName );
sal_uInt16 n;
2000-09-18 23:08:29 +00:00
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 );
2000-09-18 23:08:29 +00:00
// suchen und aus der HashTabelle entfernen
GetAppCharClass().toLower( sFldName );
sal_uInt16 n;
2000-09-18 23:08:29 +00:00
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)
2000-09-18 23:08:29 +00:00
{
bInUpdateFlds = bFldsDirty = sal_False;
2000-09-18 23:08:29 +00:00
memset( aFldTypeTable, 0, sizeof( aFldTypeTable ) );
}
SwDocUpdtFld::~SwDocUpdtFld()
{
delete pFldSortLst;
for( sal_uInt16 n = 0; n < TBLSZ; ++n )
2000-09-18 23:08:29 +00:00
delete aFldTypeTable[n];
}
// #111840#
bool SwDoc::UpdateFld(SwTxtFld * pDstTxtFld, SwField & rSrcFld,
SwMsgPoolItem * pMsgHnt,
bool bUpdateFlds)
{
ASSERT(pDstTxtFld, "no field to update!");
sal_Bool bTblSelBreak = sal_False;
SwFmtFld * pDstFmtFld = (SwFmtFld*)&pDstTxtFld->GetFld();
SwField * pDstFld = pDstFmtFld->GetFld();
sal_uInt16 nFldWhich = rSrcFld.GetTyp()->Which();
SwNodeIndex aTblNdIdx(pDstTxtFld->GetTxtNode());
if (pDstFld->GetTyp()->Which() ==
rSrcFld.GetTyp()->Which())
{
if (GetIDocumentUndoRedo().DoesUndo())
{
CWS-TOOLING: integrate CWS os133 2009-08-17 11:57:21 +0200 od r275041 : #i41413# correction of fix - check, if <Last Name> assignment exist before accessing database 2009-08-13 16:08:34 +0200 tbo r274949 : #i100286# removed from workaround 2009-08-05 10:57:28 +0200 os r274642 : #103994# prevent crash after field undo 2009-08-05 07:58:30 +0200 os r274635 : #103994# prevent crash after field undo 2009-08-04 10:38:40 +0200 os r274611 : #i41413# warnings fixed 2009-08-04 09:34:50 +0200 os r274604 : #103233# unnecessary local variable removed 2009-08-04 09:34:21 +0200 os r274603 : #103233# GetPosition() removed, again 2009-07-27 13:51:58 +0200 os r274362 : CWS-TOOLING: rebase CWS os133 to trunk@274203 (milestone: DEV300:m53) 2009-07-23 12:18:51 +0200 os r274267 : #i41413# salutation preview fixed 2009-07-22 13:55:02 +0200 os r274235 : #i69458# lock expression fields while calculating layout 2009-07-22 10:54:25 +0200 os r274225 : #i103506# page descriptor has to be copied from the working document, not from the source document 2009-07-07 16:01:50 +0200 os r273802 : #i103305# Shift+Ctrl+A should work for single selected drawing objects 2009-07-07 15:36:09 +0200 os r273801 : #ii103137# text:display inversion fixed 2009-07-01 14:19:36 +0200 os r273580 : #103233# access field position directly instead of a text node iteration 2009-06-28 20:05:18 +0200 tbo r273450 : #100285# exchange PDF1/2TBO with HID_FILTER_PDF_INITIAL_VIEW/USER_INTERFACE 2009-06-28 20:04:20 +0200 tbo r273449 : #100285# exchange PDF1/2TBO with HID_FILTER_PDF_INITIAL_VIEW/USER_INTERFACE 2009-06-28 20:03:37 +0200 tbo r273448 : #100285# exchange PDF1/2TBO with HID_FILTER_PDF_INITIAL_VIEW/USER_INTERFACE 2009-06-26 13:58:46 +0200 os r273409 : #i20268# misleading CheckBox name changed and function inverted 2009-06-26 13:33:12 +0200 os r273405 : #i52699# twip convrsion of line width for text documents added 2009-06-26 12:42:47 +0200 os r273399 : #i102967# Gender field name: accept first entry 2009-06-26 12:38:53 +0200 os r273398 : #i103121# caption position in all OLEs can only be below 2009-06-25 14:42:42 +0200 os r273382 : #i99848# member m_xText is not always set 2009-06-25 12:38:30 +0200 os r273377 : #i100285# HelpIds added 2009-06-23 16:01:42 +0200 os r273285 : #i103021# BulletId is a unicode character
2009-08-26 11:47:12 +00:00
SwPosition aPosition( pDstTxtFld->GetTxtNode() );
aPosition.nContent = *pDstTxtFld->GetStart();
SwUndo *const pUndo( new SwUndoFieldFromDoc(
aPosition, *pDstFld, rSrcFld, pMsgHnt, bUpdateFlds) );
GetIDocumentUndoRedo().AppendUndo(pUndo);
}
// Das gefundene Feld wird angepasst ...
//pDstFld->ChangeFormat( rSrcFld.GetFormat() );
//pDstFld->SetLanguage( rSrcFld.GetLanguage() );
SwField * pNewFld = rSrcFld.CopyField();
pDstFmtFld->SetFld(pNewFld);
switch( nFldWhich )
{
case RES_SETEXPFLD:
case RES_GETEXPFLD:
case RES_HIDDENTXTFLD:
case RES_HIDDENPARAFLD:
UpdateExpFlds( pDstTxtFld, true );
break;
case RES_TABLEFLD:
{
const SwTableNode* pTblNd =
IsIdxInTbl(aTblNdIdx);
if( pTblNd )
{
SwTableFmlUpdate aTblUpdate( &pTblNd->
GetTable() );
if (bUpdateFlds)
UpdateTblFlds( &aTblUpdate );
else
pNewFld->GetTyp()->Modify(0, &aTblUpdate);
if (! bUpdateFlds)
bTblSelBreak = sal_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(), sal_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, sal_uInt16 nWhich)
{
Any aOldVal;
SwField * pField = GetField(rPos);
2000-09-18 23:08:29 +00:00
if (GetIDocumentUndoRedo().DoesUndo() &&
pField->QueryValue(aOldVal, nWhich))
{
SwUndo *const pUndo(new SwUndoFieldFromAPI(rPos, aOldVal, rVal, nWhich));
GetIDocumentUndoRedo().AppendUndo(pUndo);
}
2000-09-18 23:08:29 +00:00
return pField->PutValue(rVal, nWhich);
}