| /************************************************************** |
| * |
| * 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); |
| } |