merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / doc / docfld.cxx
blob05a3efac0eee4f063a8a664a24f8d62dfca33c44
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: docfld.cxx,v $
10 * $Revision: 1.34 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
37 #include <string.h>
38 #include <float.h>
39 #include <tools/datetime.hxx>
40 #ifndef _SVSTDARR_HXX
41 #define _SVSTDARR_ULONGS
42 #include <svtools/svarray.hxx>
43 #endif
44 #ifndef _APP_HXX //autogen
45 #include <vcl/svapp.hxx>
46 #endif
47 #ifndef _APP_HXX //autogen
48 #include <vcl/svapp.hxx>
49 #endif
50 #include <unotools/charclass.hxx>
51 #include <unotools/transliterationwrapper.hxx>
52 #include <doc.hxx>
53 #include <cntfrm.hxx>
54 #include <pam.hxx>
55 #include <ndtxt.hxx>
56 #include <swtable.hxx>
57 #include <calc.hxx>
58 #include <txtfld.hxx>
59 #include <fmtfld.hxx>
60 #include <tox.hxx>
61 #include <txttxmrk.hxx>
62 #include <docfld.hxx> // fuer Expression-Felder
63 #include <docufld.hxx>
64 #include <ddefld.hxx>
65 #include <usrfld.hxx>
66 #include <expfld.hxx>
67 #include <dbfld.hxx>
68 #include <flddat.hxx>
69 #include <chpfld.hxx>
70 #include <reffld.hxx>
71 #include <flddropdown.hxx>
72 #ifndef _DBMGR_HXX
73 #include <dbmgr.hxx>
74 #endif
75 #include <section.hxx>
76 #include <cellatr.hxx>
77 #include <docary.hxx>
78 #include <authfld.hxx>
79 #include <txtinet.hxx>
80 #ifndef _POOLFMT_HRC
81 #include <poolfmt.hrc> // fuer InitFldTypes
82 #endif
84 #include <SwUndoField.hxx>
86 using namespace ::com::sun::star::uno;
88 extern BOOL IsFrameBehind( const SwTxtNode& rMyNd, USHORT nMySttPos,
89 const SwTxtNode& rBehindNd, USHORT nSttPos );
91 SV_IMPL_OP_PTRARR_SORT( _SetGetExpFlds, _SetGetExpFldPtr )
94 /*--------------------------------------------------------------------
95 Beschreibung: Feldtypen einfuegen
96 --------------------------------------------------------------------*/
98 * Implementierung der Feldfunktionen am Doc
99 * Return immer einen gueltigen Pointer auf den Typ. Wenn er also neu
100 * zugefuegt oder schon vorhanden ist.
103 SwFieldType* SwDoc::InsertFldType(const SwFieldType &rFldTyp)
105 USHORT nSize = pFldTypes->Count(),
106 nFldWhich = rFldTyp.Which();
108 USHORT i = INIT_FLDTYPES;
110 switch( nFldWhich )
112 case RES_SETEXPFLD:
113 //JP 29.01.96: SequenceFelder beginnen aber bei INIT_FLDTYPES - 3!!
114 // Sonst gibt es doppelte Nummernkreise!!
115 //MIB 14.03.95: Ab sofort verlaesst sich auch der SW3-Reader
116 //beim Aufbau der String-Pools und beim Einlesen von SetExp-Feldern
117 //hierauf
118 if( nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType&)rFldTyp).GetType() )
119 i -= INIT_SEQ_FLDTYPES;
120 // kein break;
121 case RES_DBFLD:
122 case RES_USERFLD:
123 case RES_DDEFLD:
125 const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
126 String sFldNm( rFldTyp.GetName() );
127 for( ; i < nSize; ++i )
128 if( nFldWhich == (*pFldTypes)[i]->Which() &&
129 rSCmp.isEqual( sFldNm, (*pFldTypes)[i]->GetName() ))
130 return (*pFldTypes)[i];
132 break;
134 case RES_AUTHORITY:
135 for( ; i < nSize; ++i )
136 if( nFldWhich == (*pFldTypes)[i]->Which() )
137 return (*pFldTypes)[i];
138 break;
140 default:
141 for( i = 0; i < nSize; ++i )
142 if( nFldWhich == (*pFldTypes)[i]->Which() )
143 return (*pFldTypes)[i];
146 SwFieldType* pNew = rFldTyp.Copy();
147 switch( nFldWhich )
149 case RES_DDEFLD:
150 ((SwDDEFieldType*)pNew)->SetDoc( this );
151 break;
153 case RES_DBFLD:
154 case RES_TABLEFLD:
155 case RES_DATETIMEFLD:
156 case RES_GETEXPFLD:
157 ((SwValueFieldType*)pNew)->SetDoc( this );
158 break;
160 case RES_USERFLD:
161 case RES_SETEXPFLD:
162 ((SwValueFieldType*)pNew)->SetDoc( this );
163 // JP 29.07.96: opt. FeldListe fuer den Calculator vorbereiten:
164 pUpdtFlds->InsertFldType( *pNew );
165 break;
166 case RES_AUTHORITY :
167 ((SwAuthorityFieldType*)pNew)->SetDoc( this );
168 break;
171 pFldTypes->Insert( pNew, nSize );
172 SetModified();
174 return (*pFldTypes)[ nSize ];
177 void SwDoc::InsDeletedFldType( SwFieldType& rFldTyp )
179 // der FeldTyp wurde als geloescht gekennzeichnet und aus dem
180 // Array entfernt. Nun muss man nach diesem wieder suchen.
181 // - Ist der nicht vorhanden, dann kann er eingefuegt werden.
182 // - Wird genau der gleiche Typ gefunden, dann muss der geloeschte
183 // einen anderen Namen erhalten.
185 USHORT nSize = pFldTypes->Count(), nFldWhich = rFldTyp.Which();
186 USHORT i = INIT_FLDTYPES;
188 ASSERT( RES_SETEXPFLD == nFldWhich ||
189 RES_USERFLD == nFldWhich ||
190 RES_DDEFLD == nFldWhich, "Falscher FeldTyp" );
192 const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
193 const String& rFldNm = rFldTyp.GetName();
194 SwFieldType* pFnd;
196 for( ; i < nSize; ++i )
197 if( nFldWhich == (pFnd = (*pFldTypes)[i])->Which() &&
198 rSCmp.isEqual( rFldNm, pFnd->GetName() ) )
200 // neuen Namen suchen
201 USHORT nNum = 1;
202 do {
203 String sSrch( rFldNm );
204 sSrch.Append( String::CreateFromInt32( nNum ));
205 for( i = INIT_FLDTYPES; i < nSize; ++i )
206 if( nFldWhich == (pFnd = (*pFldTypes)[i])->Which() &&
207 rSCmp.isEqual( sSrch, pFnd->GetName() ) )
208 break;
210 if( i >= nSize ) // nicht gefunden
212 ((String&)rFldNm) = sSrch;
213 break; // raus aus der While-Schleife
215 ++nNum;
216 } while( TRUE );
217 break;
220 // nicht gefunden, also eintragen und Flag loeschen
221 pFldTypes->Insert( &rFldTyp, nSize );
222 switch( nFldWhich )
224 case RES_SETEXPFLD:
225 ((SwSetExpFieldType&)rFldTyp).SetDeleted( FALSE );
226 break;
227 case RES_USERFLD:
228 ((SwUserFieldType&)rFldTyp).SetDeleted( FALSE );
229 break;
230 case RES_DDEFLD:
231 ((SwDDEFieldType&)rFldTyp).SetDeleted( FALSE );
232 break;
236 /*--------------------------------------------------------------------
237 Beschreibung: Feldtypen loeschen
238 --------------------------------------------------------------------*/
240 void SwDoc::RemoveFldType(USHORT nFld)
242 ASSERT( INIT_FLDTYPES <= nFld, "keine InitFields loeschen" );
244 * Abheangige Felder vorhanden -> ErrRaise
246 USHORT nSize = pFldTypes->Count();
247 if(nFld < nSize)
249 SwFieldType* pTmp = (*pFldTypes)[nFld];
251 // JP 29.07.96: opt. FeldListe fuer den Calculator vorbereiten:
252 USHORT nWhich = pTmp->Which();
253 switch( nWhich )
255 case RES_SETEXPFLD:
256 case RES_USERFLD:
257 pUpdtFlds->RemoveFldType( *pTmp );
258 // kein break;
259 case RES_DDEFLD:
260 if( pTmp->GetDepends() && !IsUsed( *pTmp ) )
262 if( RES_SETEXPFLD == nWhich )
263 ((SwSetExpFieldType*)pTmp)->SetDeleted( TRUE );
264 else if( RES_USERFLD == nWhich )
265 ((SwUserFieldType*)pTmp)->SetDeleted( TRUE );
266 else
267 ((SwDDEFieldType*)pTmp)->SetDeleted( TRUE );
268 nWhich = 0;
270 break;
273 if( nWhich )
275 ASSERT( !pTmp->GetDepends(), "Abhaengige vorh.!" );
276 // Feldtype loschen
277 delete pTmp;
279 pFldTypes->Remove( nFld );
280 SetModified();
284 const SwFldTypes* SwDoc::GetFldTypes() const
286 return pFldTypes;
289 /*--------------------------------------------------------------------
290 Beschreibung: Den ersten Typen mit ResId und Namen finden
291 --------------------------------------------------------------------*/
293 SwFieldType* SwDoc::GetFldType( USHORT nResId, const String& rName,
294 bool bDbFieldMatching // used in some UNO calls for RES_DBFLD
295 // to use different string matching code
296 // #i51815#
297 ) const
299 USHORT nSize = pFldTypes->Count(), i = 0;
300 const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
302 switch( nResId )
304 case RES_SETEXPFLD:
305 //JP 29.01.96: SequenceFelder beginnen aber bei INIT_FLDTYPES - 3!!
306 // Sonst gibt es doppelte Nummernkreise!!
307 //MIB 14.03.95: Ab sofort verlaesst sich auch der SW3-Reader
308 //beim Aufbau der String-Pools und beim Einlesen von SetExp-Feldern
309 //hierauf
310 i = INIT_FLDTYPES - INIT_SEQ_FLDTYPES;
311 break;
313 case RES_DBFLD:
314 case RES_USERFLD:
315 case RES_DDEFLD:
316 case RES_AUTHORITY:
317 i = INIT_FLDTYPES;
318 break;
321 SwFieldType* pRet = 0;
322 for( ; i < nSize; ++i )
324 SwFieldType* pFldType = (*pFldTypes)[i];
326 String aFldName( pFldType->GetName() );
327 if (bDbFieldMatching && nResId == RES_DBFLD) // #i51815#
328 aFldName.SearchAndReplaceAll(DB_DELIM, '.');
330 if( nResId == pFldType->Which() &&
331 rSCmp.isEqual( rName, aFldName ))
333 pRet = pFldType;
334 break;
337 return pRet;
341 /*************************************************************************
342 |* SwDoc::UpdateFlds()
343 |* Beschreibung Felder updaten
344 *************************************************************************/
346 * Alle sollen neu evaluiert werden.
349 void SwDoc::UpdateFlds( SfxPoolItem *pNewHt, bool bCloseDB )
351 // Modify() fuer jeden Feldtypen rufen,
352 // abhaengige SwTxtFld werden benachrichtigt ...
354 for( USHORT i=0; i < pFldTypes->Count(); ++i)
356 switch( (*pFldTypes)[i]->Which() )
358 // Tabellen-Felder als vorletztes Updaten
359 // Referenzen als letztes Updaten
360 case RES_GETREFFLD:
361 case RES_TABLEFLD:
362 case RES_DBFLD:
363 case RES_JUMPEDITFLD:
364 case RES_REFPAGESETFLD: // werden nie expandiert!
365 break;
367 case RES_DDEFLD:
369 if( !pNewHt )
371 SwMsgPoolItem aUpdateDDE( RES_UPDATEDDETBL );
372 (*pFldTypes)[i]->Modify( 0, &aUpdateDDE );
374 else
375 (*pFldTypes)[i]->Modify( 0, pNewHt );
376 break;
378 case RES_GETEXPFLD:
379 case RES_SETEXPFLD:
380 case RES_HIDDENTXTFLD:
381 case RES_HIDDENPARAFLD:
382 // Expression-Felder werden gesondert behandelt
383 if( !pNewHt )
384 break;
385 default:
386 (*pFldTypes)[i]->Modify( 0, pNewHt );
390 if( !IsExpFldsLocked() )
391 UpdateExpFlds( 0, FALSE ); // Expression-Felder Updaten
393 // Tabellen
394 UpdateTblFlds(pNewHt);
396 // Referenzen
397 UpdateRefFlds(pNewHt);
399 if( bCloseDB )
400 GetNewDBMgr()->CloseAll();
402 // Nur bei KomplettUpdate evaluieren
403 SetModified();
406 /******************************************************************************
407 * void SwDoc::UpdateUsrFlds()
408 ******************************************************************************/
410 void SwDoc::UpdateUsrFlds()
412 SwCalc* pCalc = 0;
413 const SwFieldType* pFldType;
414 for( USHORT i = INIT_FLDTYPES; i < pFldTypes->Count(); ++i )
415 if( RES_USERFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
417 if( !pCalc )
418 pCalc = new SwCalc( *this );
419 ((SwUserFieldType*)pFldType)->GetValue( *pCalc );
422 if( pCalc )
424 delete pCalc;
425 SetModified();
429 /*--------------------------------------------------------------------
430 Beschreibung: Referenzfelder und TableFelder erneuern
431 --------------------------------------------------------------------*/
433 void SwDoc::UpdateRefFlds( SfxPoolItem* pHt )
435 SwFieldType* pFldType;
436 for( USHORT i = 0; i < pFldTypes->Count(); ++i )
437 if( RES_GETREFFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
438 pFldType->Modify( 0, pHt );
441 void SwDoc::UpdateTblFlds( SfxPoolItem* pHt )
443 ASSERT( !pHt || RES_TABLEFML_UPDATE == pHt->Which(),
444 "Was ist das fuer ein MessageItem?" );
446 SwFieldType* pFldType(0);
447 USHORT i;
449 for( i = 0; i < pFldTypes->Count(); ++i )
451 if( RES_TABLEFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
453 SwTableFmlUpdate* pUpdtFld = 0;
454 if( pHt && RES_TABLEFML_UPDATE == pHt->Which() )
455 pUpdtFld = (SwTableFmlUpdate*)pHt;
457 SwClientIter aIter( *pFldType );
458 for( SwFmtFld* pFmtFld = (SwFmtFld*)aIter.First( TYPE( SwFmtFld ));
459 pFmtFld; pFmtFld = (SwFmtFld*)aIter.Next() )
460 if( pFmtFld->GetTxtFld() )
462 SwTblField* pFld = (SwTblField*)pFmtFld->GetFld();
464 if( pUpdtFld )
466 // bestimme Tabelle, in der das Feld steht
467 const SwTableNode* pTblNd;
468 const SwTxtNode& rTxtNd = pFmtFld->GetTxtFld()->GetTxtNode();
469 if( !rTxtNd.GetNodes().IsDocNodes() ||
470 0 == ( pTblNd = rTxtNd.FindTableNode() ) )
471 continue;
473 switch( pUpdtFld->eFlags )
475 case TBL_CALC:
476 // setze das Value-Flag zurueck
477 // JP 17.06.96: interne Darstellung auf alle Formeln
478 // (Referenzen auf andere Tabellen!!!)
479 if( nsSwExtendedSubType::SUB_CMD & pFld->GetSubType() )
480 pFld->PtrToBoxNm( pUpdtFld->pTbl );
481 else
482 pFld->ChgValid( FALSE );
483 break;
484 case TBL_BOXNAME:
485 // ist es die gesuchte Tabelle ??
486 if( &pTblNd->GetTable() == pUpdtFld->pTbl )
487 // zur externen Darstellung
488 pFld->PtrToBoxNm( pUpdtFld->pTbl );
489 break;
490 case TBL_BOXPTR:
491 // zur internen Darstellung
492 // JP 17.06.96: interne Darstellung auf alle Formeln
493 // (Referenzen auf andere Tabellen!!!)
494 pFld->BoxNmToPtr( pUpdtFld->pTbl );
495 break;
496 case TBL_RELBOXNAME:
497 // ist es die gesuchte Tabelle ??
498 if( &pTblNd->GetTable() == pUpdtFld->pTbl )
499 // zur relativen Darstellung
500 pFld->ToRelBoxNm( pUpdtFld->pTbl );
501 break;
502 default:
503 break;
506 else
507 // setze bei allen das Value-Flag zurueck
508 pFld->ChgValid( FALSE );
511 break;
513 pFldType = 0;
516 // und dann noch alle Tabellen Box Formeln abklappern
517 const SfxPoolItem* pItem;
518 USHORT nMaxItems = GetAttrPool().GetItemCount( RES_BOXATR_FORMULA );
519 for( i = 0; i < nMaxItems; ++i )
520 if( 0 != (pItem = GetAttrPool().GetItem( RES_BOXATR_FORMULA, i ) ) &&
521 ((SwTblBoxFormula*)pItem)->GetDefinedIn() )
523 ((SwTblBoxFormula*)pItem)->ChangeState( pHt );
527 // alle Felder/Boxen sind jetzt invalide, also kann das Rechnen anfangen
528 if( pHt && ( RES_TABLEFML_UPDATE != pHt->Which() ||
529 TBL_CALC != ((SwTableFmlUpdate*)pHt)->eFlags ))
530 return ;
532 SwCalc* pCalc = 0;
534 if( pFldType )
536 SwClient* pLast;
537 SwClientIter aIter( *pFldType );
538 // dann rechne mal schoen
539 // JP 27.03.97: Beim Berechnen am Ende anfangen - weil neue
540 // Felder immer am Anfang der Modifykette eingefuegt
541 // werden. Beim Import haben wir damit eine bessere/
542 // schnellere Berechnung bei "Kettenformeln"
543 if( 0 != ( pLast = aIter.GoEnd() ))
544 do {
545 SwFmtFld* pFmtFld = (SwFmtFld*)pLast;
546 SwTblField* pFld;
547 if( !pFmtFld->GetTxtFld() || (nsSwExtendedSubType::SUB_CMD &
548 (pFld = (SwTblField*)pFmtFld->GetFld())->GetSubType() ))
549 continue;
551 // muss neu berechnet werden (und ist keine textuelle Anzeige)
552 if( !pFld->IsValid() )
554 // bestimme Tabelle, in der das Feld steht
555 const SwTxtNode& rTxtNd = pFmtFld->GetTxtFld()->GetTxtNode();
556 if( !rTxtNd.GetNodes().IsDocNodes() )
557 continue;
558 const SwTableNode* pTblNd = rTxtNd.FindTableNode();
559 if( !pTblNd )
560 continue;
562 // falls dieses Feld nicht in der zu updatenden
563 // Tabelle steht, ueberspringen !!
564 if( pHt && &pTblNd->GetTable() !=
565 ((SwTableFmlUpdate*)pHt)->pTbl )
566 continue;
568 if( !pCalc )
569 pCalc = new SwCalc( *this );
571 // bestimme die Werte aller SetExpresion Felder, die
572 // bis zur Tabelle gueltig sind
573 SwFrm* pFrm = 0;
574 if( pTblNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
576 // steht im Sonderbereich, wird teuer !!
577 Point aPt; // den im Layout 1. Frame returnen - Tab.Kopfzeile !!
578 pFrm = rTxtNd.GetFrm( &aPt );
579 if( pFrm )
581 SwPosition aPos( *pTblNd );
582 if( GetBodyTxtNode( *this, aPos, *pFrm ) )
583 FldsToCalc( *pCalc, _SetGetExpFld(
584 aPos.nNode, pFmtFld->GetTxtFld(),
585 &aPos.nContent ));
586 else
587 pFrm = 0;
590 if( !pFrm )
592 // einen Index fuers bestimmen vom TextNode anlegen
593 SwNodeIndex aIdx( rTxtNd );
594 FldsToCalc( *pCalc,
595 _SetGetExpFld( aIdx, pFmtFld->GetTxtFld() ));
598 SwTblCalcPara aPara( *pCalc, pTblNd->GetTable() );
599 pFld->CalcField( aPara );
600 if( aPara.IsStackOverFlow() )
602 if( aPara.CalcWithStackOverflow() )
603 pFld->CalcField( aPara );
604 #ifndef PRODUCT
605 else
607 // mind. ein ASSERT
608 ASSERT( !this, "die Kettenformel konnte nicht errechnet werden" );
610 #endif
612 pCalc->SetCalcError( CALC_NOERR );
614 pFmtFld->Modify( 0, pHt );
615 } while( 0 != ( pLast = aIter-- ));
618 // dann berechene noch die Formeln an den Boxen
619 for( i = 0; i < nMaxItems; ++i )
620 if( 0 != (pItem = GetAttrPool().GetItem( RES_BOXATR_FORMULA, i ) ) &&
621 ((SwTblBoxFormula*)pItem)->GetDefinedIn() &&
622 !((SwTblBoxFormula*)pItem)->IsValid() )
624 SwTblBoxFormula* pFml = (SwTblBoxFormula*)pItem;
625 SwTableBox* pBox = pFml->GetTableBox();
626 if( pBox && pBox->GetSttNd() &&
627 pBox->GetSttNd()->GetNodes().IsDocNodes() )
629 const SwTableNode* pTblNd = pBox->GetSttNd()->FindTableNode();
630 if( !pHt || &pTblNd->GetTable() ==
631 ((SwTableFmlUpdate*)pHt)->pTbl )
633 double nValue;
634 if( !pCalc )
635 pCalc = new SwCalc( *this );
637 // bestimme die Werte aller SetExpresion Felder, die
638 // bis zur Tabelle gueltig sind
639 SwFrm* pFrm = 0;
640 if( pTblNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
642 // steht im Sonderbereich, wird teuer !!
643 Point aPt; // den im Layout 1. Frame returnen - Tab.Kopfzeile !!
644 SwNodeIndex aCNdIdx( *pTblNd, +2 );
645 SwCntntNode* pCNd = aCNdIdx.GetNode().GetCntntNode();
646 if( !pCNd )
647 pCNd = GetNodes().GoNext( &aCNdIdx );
649 if( pCNd && 0 != (pFrm = pCNd->GetFrm( &aPt )) )
651 SwPosition aPos( *pCNd );
652 if( GetBodyTxtNode( *this, aPos, *pFrm ) )
653 FldsToCalc( *pCalc, _SetGetExpFld( aPos.nNode ));
654 else
655 pFrm = 0;
658 if( !pFrm )
660 // einen Index fuers bestimmen vom TextNode anlegen
661 SwNodeIndex aIdx( *pTblNd );
662 FldsToCalc( *pCalc, _SetGetExpFld( aIdx ));
665 SwTblCalcPara aPara( *pCalc, pTblNd->GetTable() );
666 pFml->Calc( aPara, nValue );
668 if( aPara.IsStackOverFlow() )
670 if( aPara.CalcWithStackOverflow() )
671 pFml->Calc( aPara, nValue );
672 #ifndef PRODUCT
673 else
675 // mind. ein ASSERT
676 ASSERT( !this, "die Kettenformel konnte nicht errechnet werden" );
678 #endif
681 SwFrmFmt* pFmt = pBox->ClaimFrmFmt();
682 SfxItemSet aTmp( GetAttrPool(),
683 RES_BOXATR_BEGIN,RES_BOXATR_END-1 );
685 if( pCalc->IsCalcError() )
686 nValue = DBL_MAX;
687 aTmp.Put( SwTblBoxValue( nValue ));
688 if( SFX_ITEM_SET != pFmt->GetItemState( RES_BOXATR_FORMAT ))
689 aTmp.Put( SwTblBoxNumFormat( 0 ));
690 pFmt->SetFmtAttr( aTmp );
692 pCalc->SetCalcError( CALC_NOERR );
697 if( pCalc )
698 delete pCalc;
701 void SwDoc::UpdatePageFlds( SfxPoolItem* pMsgHnt )
703 SwFieldType* pFldType;
704 for( USHORT i = 0; i < INIT_FLDTYPES; ++i )
705 switch( ( pFldType = (*pFldTypes)[ i ] )->Which() )
707 case RES_PAGENUMBERFLD:
708 case RES_CHAPTERFLD:
709 case RES_GETEXPFLD:
710 case RES_REFPAGEGETFLD:
711 pFldType->Modify( 0, pMsgHnt );
712 break;
713 case RES_DOCSTATFLD:
714 pFldType->Modify( 0, 0 );
715 break;
717 SetNewFldLst(true);
720 /*--------------------------------------------------------------------
721 Beschreibung:
722 --------------------------------------------------------------------*/
724 // ---- Loesche alle nicht referenzierten FeldTypen eines Dokumentes --
725 void SwDoc::GCFieldTypes()
727 for( USHORT n = pFldTypes->Count(); n > INIT_FLDTYPES; )
728 if( !(*pFldTypes)[ --n ]->GetDepends() )
729 RemoveFldType( n );
732 void SwDoc::LockExpFlds()
734 ++nLockExpFld;
737 void SwDoc::UnlockExpFlds()
739 if( nLockExpFld )
740 --nLockExpFld;
743 bool SwDoc::IsExpFldsLocked() const
745 return 0 != nLockExpFld;
748 SwDocUpdtFld& SwDoc::GetUpdtFlds() const
750 return *pUpdtFlds;
753 bool SwDoc::IsNewFldLst() const
755 return mbNewFldLst;
758 void SwDoc::SetNewFldLst(bool bFlag)
760 mbNewFldLst = bFlag;
764 //----------------------------------------------------------------------
766 // der StartIndex kann optional mit angegeben werden (z.B. wenn dieser
767 // zuvor schon mal erfragt wurde - ist sonst eine virtuelle Methode !!)
769 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx, const SwTxtFld* pFld,
770 const SwIndex* pIdx )
772 eSetGetExpFldType = TEXTFIELD;
773 CNTNT.pTxtFld = pFld;
774 nNode = rNdIdx.GetIndex();
775 if( pIdx )
776 nCntnt = pIdx->GetIndex();
777 else if( pFld )
778 nCntnt = *pFld->GetStart();
779 else
780 nCntnt = 0;
783 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx,
784 const SwTxtINetFmt& rINet, const SwIndex* pIdx )
786 eSetGetExpFldType = TEXTINET;
787 CNTNT.pTxtINet = &rINet;
788 nNode = rNdIdx.GetIndex();
789 if( pIdx )
790 nCntnt = pIdx->GetIndex();
791 else
792 nCntnt = *rINet.GetStart();
795 //Erweiterung fuer Sections:
796 // diese haben immer als Content-Position 0xffff !!
797 // Auf dieser steht nie ein Feld, maximal bis STRING_MAXLEN moeglich
798 _SetGetExpFld::_SetGetExpFld( const SwSectionNode& rSectNd,
799 const SwPosition* pPos )
801 eSetGetExpFldType = SECTIONNODE;
802 CNTNT.pSection = &rSectNd.GetSection();
804 if( pPos )
806 nNode = pPos->nNode.GetIndex();
807 nCntnt = pPos->nContent.GetIndex();
809 else
811 nNode = rSectNd.GetIndex();
812 nCntnt = 0;
816 _SetGetExpFld::_SetGetExpFld( const SwTableBox& rTBox, const SwPosition* pPos )
818 eSetGetExpFldType = TABLEBOX;
819 CNTNT.pTBox = &rTBox;
821 if( pPos )
823 nNode = pPos->nNode.GetIndex();
824 nCntnt = pPos->nContent.GetIndex();
826 else
828 nNode = 0;
829 nCntnt = 0;
830 if( rTBox.GetSttNd() )
832 SwNodeIndex aIdx( *rTBox.GetSttNd() );
833 const SwCntntNode* pNd = aIdx.GetNode().GetNodes().GoNext( &aIdx );
834 if( pNd )
835 nNode = pNd->GetIndex();
840 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx,
841 const SwTxtTOXMark& rTOX,
842 const SwIndex* pIdx )
844 eSetGetExpFldType = TEXTTOXMARK;
845 CNTNT.pTxtTOX = &rTOX;
846 nNode = rNdIdx.GetIndex();
847 if( pIdx )
848 nCntnt = pIdx->GetIndex();
849 else
850 nCntnt = *rTOX.GetStart();
853 _SetGetExpFld::_SetGetExpFld( const SwPosition& rPos )
855 eSetGetExpFldType = CRSRPOS;
856 CNTNT.pPos = &rPos;
857 nNode = rPos.nNode.GetIndex();
858 nCntnt = rPos.nContent.GetIndex();
861 _SetGetExpFld::_SetGetExpFld( const SwFlyFrmFmt& rFlyFmt,
862 const SwPosition* pPos )
864 eSetGetExpFldType = FLYFRAME;
865 CNTNT.pFlyFmt = &rFlyFmt;
866 if( pPos )
868 nNode = pPos->nNode.GetIndex();
869 nCntnt = pPos->nContent.GetIndex();
871 else
873 const SwFmtCntnt& rCntnt = rFlyFmt.GetCntnt();
874 nNode = rCntnt.GetCntntIdx()->GetIndex() + 1;
875 nCntnt = 0;
879 void _SetGetExpFld::GetPos( SwPosition& rPos ) const
881 rPos.nNode = nNode;
882 rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt );
885 void _SetGetExpFld::GetPosOfContent( SwPosition& rPos ) const
887 const SwNode* pNd = GetNodeFromCntnt();
888 if( pNd )
889 pNd = pNd->GetCntntNode();
891 if( pNd )
893 rPos.nNode = *pNd;
894 rPos.nContent.Assign( (SwCntntNode*)pNd,GetCntPosFromCntnt() );
896 else
898 rPos.nNode = nNode;
899 rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt );
903 void _SetGetExpFld::SetBodyPos( const SwCntntFrm& rFrm )
905 if( !rFrm.IsInDocBody() )
907 SwNodeIndex aIdx( *rFrm.GetNode() );
908 SwDoc& rDoc = *aIdx.GetNodes().GetDoc();
909 SwPosition aPos( aIdx );
910 #ifndef PRODUCT
911 ASSERT( ::GetBodyTxtNode( rDoc, aPos, rFrm ), "wo steht das Feld" );
912 #else
913 ::GetBodyTxtNode( rDoc, aPos, rFrm );
914 #endif
915 nNode = aPos.nNode.GetIndex();
916 nCntnt = aPos.nContent.GetIndex();
920 BOOL _SetGetExpFld::operator<( const _SetGetExpFld& rFld ) const
922 if( nNode < rFld.nNode || ( nNode == rFld.nNode && nCntnt < rFld.nCntnt ))
923 return TRUE;
924 else if( nNode != rFld.nNode || nCntnt != rFld.nCntnt )
925 return FALSE;
927 const SwNode *pFirst = GetNodeFromCntnt(),
928 *pNext = rFld.GetNodeFromCntnt();
930 // Position gleich: nur weiter wenn beide FeldPointer besetzt sind !!
931 if( !pFirst || !pNext )
932 return FALSE;
934 // gleiche Section ??
935 if( pFirst->StartOfSectionNode() != pNext->StartOfSectionNode() )
937 // sollte einer in der Tabelle stehen ?
938 const SwNode *pFirstStt, *pNextStt;
939 const SwTableNode* pTblNd = pFirst->FindTableNode();
940 if( pTblNd )
941 pFirstStt = pTblNd->StartOfSectionNode();
942 else
943 pFirstStt = pFirst->StartOfSectionNode();
945 if( 0 != ( pTblNd = pNext->FindTableNode() ) )
946 pNextStt = pTblNd->StartOfSectionNode();
947 else
948 pNextStt = pNext->StartOfSectionNode();
950 if( pFirstStt != pNextStt )
952 if( pFirst->IsTxtNode() && pNext->IsTxtNode() &&
953 ( pFirst->FindFlyStartNode() || pNext->FindFlyStartNode() ))
955 return ::IsFrameBehind( *(SwTxtNode*)pNext, nCntnt,
956 *(SwTxtNode*)pFirst, nCntnt );
958 return pFirstStt->GetIndex() < pNextStt->GetIndex();
962 // ist gleiche Section, dann Feld im gleichen Node ?
963 if( pFirst != pNext )
964 return pFirst->GetIndex() < pNext->GetIndex();
966 // gleicher Node in der Section, dann Position im Node
967 return GetCntPosFromCntnt() < rFld.GetCntPosFromCntnt();
970 const SwNode* _SetGetExpFld::GetNodeFromCntnt() const
972 const SwNode* pRet = 0;
973 if( CNTNT.pTxtFld )
974 switch( eSetGetExpFldType )
976 case TEXTFIELD:
977 pRet = &CNTNT.pTxtFld->GetTxtNode();
978 break;
980 case TEXTINET:
981 pRet = &CNTNT.pTxtINet->GetTxtNode();
982 break;
984 case SECTIONNODE:
985 pRet = CNTNT.pSection->GetFmt()->GetSectionNode();
986 break;
988 case CRSRPOS:
989 pRet = &CNTNT.pPos->nNode.GetNode();
990 break;
992 case TEXTTOXMARK:
993 pRet = &CNTNT.pTxtTOX->GetTxtNode();
994 break;
996 case TABLEBOX:
997 if( CNTNT.pTBox->GetSttNd() )
999 SwNodeIndex aIdx( *CNTNT.pTBox->GetSttNd() );
1000 pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx );
1002 break;
1004 case FLYFRAME:
1006 SwNodeIndex aIdx( *CNTNT.pFlyFmt->GetCntnt().GetCntntIdx() );
1007 pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx );
1009 break;
1011 return pRet;
1014 xub_StrLen _SetGetExpFld::GetCntPosFromCntnt() const
1016 USHORT nRet = 0;
1017 if( CNTNT.pTxtFld )
1018 switch( eSetGetExpFldType )
1020 case TEXTFIELD:
1021 case TEXTINET:
1022 case TEXTTOXMARK:
1023 nRet = *CNTNT.pTxtFld->GetStart();
1024 break;
1025 case CRSRPOS:
1026 nRet = CNTNT.pPos->nContent.GetIndex();
1027 break;
1028 default:
1029 break;
1031 return nRet;
1034 _HashStr::_HashStr( const String& rName, const String& rText,
1035 _HashStr* pNxt )
1036 : SwHash( rName ), aSetStr( rText )
1038 pNext = pNxt;
1041 // suche nach dem Namen, ist er vorhanden, returne seinen String, sonst
1042 // einen LeerString
1043 void LookString( SwHash** ppTbl, USHORT nSize, const String& rName,
1044 String& rRet, USHORT* pPos )
1046 rRet = rName;
1047 rRet.EraseLeadingChars().EraseTrailingChars();
1048 SwHash* pFnd = Find( rRet, ppTbl, nSize, pPos );
1049 if( pFnd )
1050 rRet = ((_HashStr*)pFnd)->aSetStr;
1051 else
1052 rRet.Erase();
1055 /*--------------------------------------------------------------------
1056 Beschreibung:
1057 --------------------------------------------------------------------*/
1059 String lcl_GetDBVarName( SwDoc& rDoc, SwDBNameInfField& rDBFld )
1061 SwDBData aDBData( rDBFld.GetDBData( &rDoc ));
1062 String sDBNumNm;
1063 SwDBData aDocData = rDoc.GetDBData();
1065 if( aDBData != aDocData )
1067 sDBNumNm = aDBData.sDataSource;
1068 sDBNumNm += DB_DELIM;
1069 sDBNumNm += String(aDBData.sCommand);
1070 sDBNumNm += DB_DELIM;
1072 sDBNumNm += SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD);
1074 return sDBNumNm;
1077 /*--------------------------------------------------------------------
1078 Beschreibung:
1079 --------------------------------------------------------------------*/
1081 void lcl_CalcFld( SwDoc& rDoc, SwCalc& rCalc, const _SetGetExpFld& rSGEFld,
1082 SwNewDBMgr* pMgr )
1084 const SwTxtFld* pTxtFld = rSGEFld.GetFld();
1085 if( !pTxtFld )
1086 return ;
1088 const SwField* pFld = pTxtFld->GetFld().GetFld();
1089 const USHORT nFldWhich = pFld->GetTyp()->Which();
1091 if( RES_SETEXPFLD == nFldWhich )
1093 SwSbxValue aValue;
1094 if( nsSwGetSetExpType::GSE_EXPR & pFld->GetSubType() )
1095 aValue.PutDouble( ((SwSetExpField*)pFld)->GetValue() );
1096 else
1097 // Erweiterung fuers Rechnen mit Strings
1098 aValue.PutString( ((SwSetExpField*)pFld)->GetExpStr() );
1100 // setze im Calculator den neuen Wert
1101 rCalc.VarChange( pFld->GetTyp()->GetName(), aValue );
1103 else if( pMgr )
1105 switch( nFldWhich )
1107 case RES_DBNUMSETFLD:
1109 SwDBNumSetField* pDBFld = (SwDBNumSetField*)pFld;
1111 SwDBData aDBData(pDBFld->GetDBData(&rDoc));
1113 if( pDBFld->IsCondValid() &&
1114 pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand ))
1115 rCalc.VarChange( lcl_GetDBVarName( rDoc, *pDBFld),
1116 pDBFld->GetFormat() );
1118 break;
1119 case RES_DBNEXTSETFLD:
1121 SwDBNextSetField* pDBFld = (SwDBNextSetField*)pFld;
1122 SwDBData aDBData(pDBFld->GetDBData(&rDoc));
1123 if( !pDBFld->IsCondValid() ||
1124 !pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand ))
1125 break;
1127 String sDBNumNm(lcl_GetDBVarName( rDoc, *pDBFld));
1128 SwCalcExp* pExp = rCalc.VarLook( sDBNumNm );
1129 if( pExp )
1130 rCalc.VarChange( sDBNumNm, pExp->nValue.GetLong() + 1 );
1132 break;
1138 void SwDoc::FldsToCalc( SwCalc& rCalc, const _SetGetExpFld& rToThisFld )
1140 // erzeuge die Sortierteliste aller SetFelder
1141 pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC );
1142 mbNewFldLst = FALSE;
1144 SwNewDBMgr* pMgr = GetNewDBMgr();
1145 pMgr->CloseAll(FALSE);
1147 if( pUpdtFlds->GetSortLst()->Count() )
1149 USHORT nLast;
1150 _SetGetExpFld* pFld = (_SetGetExpFld*)&rToThisFld;
1151 if( pUpdtFlds->GetSortLst()->Seek_Entry( pFld, &nLast ) )
1152 ++nLast;
1154 const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
1155 for( USHORT n = 0; n < nLast; ++n, ++ppSortLst )
1156 lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr );
1159 pMgr->CloseAll(FALSE);
1162 void SwDoc::FldsToCalc( SwCalc& rCalc, ULONG nLastNd, sal_uInt16 nLastCnt )
1164 // erzeuge die Sortierteliste aller SetFelder
1165 pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC );
1166 mbNewFldLst = FALSE;
1168 SwNewDBMgr* pMgr = GetNewDBMgr();
1169 pMgr->CloseAll(FALSE);
1171 const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
1173 for( USHORT n = pUpdtFlds->GetSortLst()->Count();
1174 n &&
1175 ( (*ppSortLst)->GetNode() < nLastNd ||
1176 ( (*ppSortLst)->GetNode() == nLastNd && (*ppSortLst)->GetCntnt() <= nLastCnt )
1178 --n, ++ppSortLst )
1179 lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr );
1181 pMgr->CloseAll(FALSE);
1184 void SwDoc::FldsToExpand( SwHash**& ppHashTbl, USHORT& rTblSize,
1185 const _SetGetExpFld& rToThisFld )
1187 // erzeuge die Sortierteliste aller SetFelder
1188 pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_EXPAND );
1189 mbNewFldLst = FALSE;
1191 // HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt
1192 // (versuche eine "ungerade"-Zahl zu erzeugen)
1193 rTblSize = (( pUpdtFlds->GetSortLst()->Count() / 7 ) + 1 ) * 7;
1194 ppHashTbl = new SwHash*[ rTblSize ];
1195 memset( ppHashTbl, 0, sizeof( _HashStr* ) * rTblSize );
1197 USHORT nLast;
1199 _SetGetExpFld* pTmp = (_SetGetExpFld*)&rToThisFld;
1200 if( pUpdtFlds->GetSortLst()->Seek_Entry( pTmp, &nLast ) )
1201 ++nLast;
1204 USHORT nPos;
1205 SwHash* pFnd;
1206 String aNew;
1207 const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
1208 for( ; nLast; --nLast, ++ppSortLst )
1210 const SwTxtFld* pTxtFld = (*ppSortLst)->GetFld();
1211 if( !pTxtFld )
1212 continue;
1214 const SwField* pFld = pTxtFld->GetFld().GetFld();
1215 switch( pFld->GetTyp()->Which() )
1217 case RES_SETEXPFLD:
1218 if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() )
1220 // setze in der HashTabelle den neuen Wert
1221 // ist die "Formel" ein Feld ??
1222 SwSetExpField* pSFld = (SwSetExpField*)pFld;
1223 LookString( ppHashTbl, rTblSize, pSFld->GetFormula(), aNew );
1225 if( !aNew.Len() ) // nichts gefunden, dann ist
1226 aNew = pSFld->GetFormula(); // die Formel der neue Wert
1228 // OD 11.02.2003 #i3141# - update expression of field as in
1229 // method <SwDoc::UpdateExpFlds(..)> for string/text fields
1230 pSFld->ChgExpStr( aNew );
1232 // suche den Namen vom Feld
1233 aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName();
1234 // Eintrag vorhanden ?
1235 pFnd = Find( aNew, ppHashTbl, rTblSize, &nPos );
1236 if( pFnd )
1237 // Eintrag in der HashTabelle aendern
1238 ((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr();
1239 else
1240 // neuen Eintrag einfuegen
1241 *(ppHashTbl + nPos ) = new _HashStr( aNew,
1242 pSFld->GetExpStr(), (_HashStr*)*(ppHashTbl + nPos) );
1244 break;
1245 case RES_DBFLD:
1247 const String& rName = pFld->GetTyp()->GetName();
1249 // Eintrag in den HashTable eintragen
1250 // Eintrag vorhanden ?
1251 pFnd = Find( rName, ppHashTbl, rTblSize, &nPos );
1252 if( pFnd )
1253 // Eintrag in der HashTabelle aendern
1254 ((_HashStr*)pFnd)->aSetStr = pFld->Expand();
1255 else
1256 // neuen Eintrag einfuegen
1257 *(ppHashTbl + nPos ) = new _HashStr( rName,
1258 pFld->Expand(), (_HashStr*)*(ppHashTbl + nPos));
1260 break;
1266 void SwDoc::UpdateExpFlds( SwTxtFld* pUpdtFld, bool bUpdRefFlds )
1268 if( IsExpFldsLocked() || IsInReading() )
1269 return;
1271 BOOL bOldInUpdateFlds = pUpdtFlds->IsInUpdateFlds();
1272 pUpdtFlds->SetInUpdateFlds( TRUE );
1274 pUpdtFlds->MakeFldList( *this, TRUE, GETFLD_ALL );
1275 mbNewFldLst = FALSE;
1277 if( !pUpdtFlds->GetSortLst()->Count() )
1279 if( bUpdRefFlds )
1280 UpdateRefFlds(NULL);
1282 pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds );
1283 pUpdtFlds->SetFieldsDirty( FALSE );
1284 return ;
1287 USHORT nWhich, n;
1289 // HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt
1290 // (versuche eine "ungerade"-Zahl zu erzeugen)
1291 USHORT nStrFmtCnt = (( pFldTypes->Count() / 7 ) + 1 ) * 7;
1292 SwHash** pHashStrTbl = new SwHash*[ nStrFmtCnt ];
1293 memset( pHashStrTbl, 0, sizeof( _HashStr* ) * nStrFmtCnt );
1296 const SwFieldType* pFldType;
1297 // gesondert behandeln:
1298 for( n = pFldTypes->Count(); n; )
1299 switch( ( pFldType = (*pFldTypes)[ --n ] )->Which() )
1301 case RES_USERFLD:
1303 // Eintrag vorhanden ?
1304 USHORT nPos;
1305 const String& rNm = pFldType->GetName();
1306 String sExpand(((SwUserFieldType*)pFldType)->Expand(nsSwGetSetExpType::GSE_STRING, 0, 0));
1307 SwHash* pFnd = Find( rNm, pHashStrTbl, nStrFmtCnt, &nPos );
1308 if( pFnd )
1309 // Eintrag in der HashTabelle aendern ??
1310 ((_HashStr*)pFnd)->aSetStr = sExpand;
1311 else
1312 // neuen Eintrag einfuegen
1313 *(pHashStrTbl + nPos ) = new _HashStr( rNm, sExpand,
1314 (_HashStr*)*(pHashStrTbl + nPos) );
1316 break;
1317 case RES_SETEXPFLD:
1318 ((SwSetExpFieldType*)pFldType)->SetOutlineChgNd( 0 );
1319 break;
1323 // Ok, das Array ist soweit mit allen Feldern gefuellt, dann rechne mal
1324 SwCalc aCalc( *this );
1326 String sDBNumNm( SwFieldType::GetTypeStr( TYP_DBSETNUMBERFLD ) );
1328 // aktuelle Datensatznummer schon vorher einstellen
1329 SwNewDBMgr* pMgr = GetNewDBMgr();
1330 pMgr->CloseAll(FALSE);
1332 if(pMgr && pMgr->OpenDB(DBMGR_STD, GetDBDesc(), FALSE))
1334 if(!pMgr->IsInMerge() )
1335 pMgr->ToFirstSelectedRecord(DBMGR_STD);
1337 aCalc.VarChange( sDBNumNm, pMgr->GetCurSelectedRecordId(DBMGR_STD));
1341 String aNew;
1342 const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
1343 for( n = pUpdtFlds->GetSortLst()->Count(); n; --n, ++ppSortLst )
1345 SwSection* pSect = (SwSection*)(*ppSortLst)->GetSection();
1346 if( pSect )
1348 //!SECTION
1350 // if( pGFld->IsInBodyTxt() )
1351 SwSbxValue aValue = aCalc.Calculate(
1352 pSect->GetCondition() );
1353 if(!aValue.IsVoidValue())
1354 pSect->SetCondHidden( aValue.GetBool() );
1355 continue;
1358 SwTxtFld* pTxtFld = (SwTxtFld*)(*ppSortLst)->GetFld();
1359 if( !pTxtFld )
1361 ASSERT( !this, "was ist es denn nun" );
1362 continue;
1365 SwFmtFld* pFmtFld = (SwFmtFld*)&pTxtFld->GetFld();
1366 SwField* pFld = pFmtFld->GetFld();
1368 switch( nWhich = pFld->GetTyp()->Which() )
1370 case RES_HIDDENTXTFLD:
1372 SwHiddenTxtField* pHFld = (SwHiddenTxtField*)pFld;
1373 SwSbxValue aValue = aCalc.Calculate( pHFld->GetPar1() );
1374 sal_Bool bValue = !aValue.GetBool();
1375 if(!aValue.IsVoidValue())
1377 pHFld->SetValue( bValue );
1378 // Feld Evaluieren
1379 pHFld->Evaluate(this);
1382 break;
1383 case RES_HIDDENPARAFLD:
1385 SwHiddenParaField* pHPFld = (SwHiddenParaField*)pFld;
1386 SwSbxValue aValue = aCalc.Calculate( pHPFld->GetPar1() );
1387 sal_Bool bValue = aValue.GetBool();
1388 if(!aValue.IsVoidValue())
1389 pHPFld->SetHidden( bValue );
1391 break;
1392 case RES_DBSETNUMBERFLD:
1394 ((SwDBSetNumberField*)pFld)->Evaluate(this);
1395 aCalc.VarChange( sDBNumNm, ((SwDBSetNumberField*)pFld)->GetSetNumber());
1397 break;
1398 case RES_DBNEXTSETFLD:
1399 case RES_DBNUMSETFLD:
1400 UpdateDBNumFlds( *(SwDBNameInfField*)pFld, aCalc );
1401 break;
1402 case RES_DBFLD:
1404 // Feld Evaluieren
1405 ((SwDBField*)pFld)->Evaluate();
1407 SwDBData aTmpDBData(((SwDBField*)pFld)->GetDBData());
1409 if( pMgr->IsDataSourceOpen(aTmpDBData.sDataSource, aTmpDBData.sCommand, sal_False))
1410 aCalc.VarChange( sDBNumNm, pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType));
1412 const String& rName = pFld->GetTyp()->GetName();
1414 // Wert fuer den Calculator setzen
1415 //JP 10.02.96: GetValue macht hier doch keinen Sinn
1416 // ((SwDBField*)pFld)->GetValue();
1418 //!OK aCalc.VarChange(aName, ((SwDBField*)pFld)->GetValue(aCalc));
1420 // Eintrag in den HashTable eintragen
1421 // Eintrag vorhanden ?
1422 USHORT nPos;
1423 SwHash* pFnd = Find( rName, pHashStrTbl, nStrFmtCnt, &nPos );
1424 if( pFnd )
1425 // Eintrag in der HashTabelle aendern
1426 ((_HashStr*)pFnd)->aSetStr = pFld->Expand();
1427 else
1428 // neuen Eintrag einfuegen
1429 *(pHashStrTbl + nPos ) = new _HashStr( rName,
1430 pFld->Expand(), (_HashStr*)*(pHashStrTbl + nPos));
1432 break;
1433 case RES_GETEXPFLD:
1434 case RES_SETEXPFLD:
1436 if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() ) // String Ersetzung
1438 if( RES_GETEXPFLD == nWhich )
1440 SwGetExpField* pGFld = (SwGetExpField*)pFld;
1442 if( (!pUpdtFld || pUpdtFld == pTxtFld )
1443 && pGFld->IsInBodyTxt() )
1445 LookString( pHashStrTbl, nStrFmtCnt,
1446 pGFld->GetFormula(), aNew );
1447 pGFld->ChgExpStr( aNew );
1450 else
1452 SwSetExpField* pSFld = (SwSetExpField*)pFld;
1453 // ist die "Formel" ein Feld ??
1454 LookString( pHashStrTbl, nStrFmtCnt,
1455 pSFld->GetFormula(), aNew );
1457 if( !aNew.Len() ) // nichts gefunden, dann ist die
1458 aNew = pSFld->GetFormula(); // Formel der neue Wert
1460 // nur ein spezielles FeldUpdaten ?
1461 if( !pUpdtFld || pUpdtFld == pTxtFld )
1462 pSFld->ChgExpStr( aNew );
1464 // suche den Namen vom Feld
1465 aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName();
1466 // Eintrag vorhanden ?
1467 USHORT nPos;
1468 SwHash* pFnd = Find( aNew, pHashStrTbl, nStrFmtCnt, &nPos );
1469 if( pFnd )
1470 // Eintrag in der HashTabelle aendern
1471 ((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr();
1472 else
1473 // neuen Eintrag einfuegen
1474 *(pHashStrTbl + nPos ) = pFnd = new _HashStr( aNew,
1475 pSFld->GetExpStr(),
1476 (_HashStr*)*(pHashStrTbl + nPos) );
1478 // Erweiterung fuers Rechnen mit Strings
1479 SwSbxValue aValue;
1480 aValue.PutString( ((_HashStr*)pFnd)->aSetStr );
1481 aCalc.VarChange( aNew, aValue );
1484 else // Formel neu berechnen
1486 if( RES_GETEXPFLD == nWhich )
1488 SwGetExpField* pGFld = (SwGetExpField*)pFld;
1490 if( (!pUpdtFld || pUpdtFld == pTxtFld )
1491 && pGFld->IsInBodyTxt() )
1493 SwSbxValue aValue = aCalc.Calculate(
1494 pGFld->GetFormula());
1495 if(!aValue.IsVoidValue())
1496 pGFld->SetValue(aValue.GetDouble() );
1499 else
1501 SwSetExpField* pSFld = (SwSetExpField*)pFld;
1502 SwSetExpFieldType* pSFldTyp = (SwSetExpFieldType*)pFld->GetTyp();
1503 aNew = pSFldTyp->GetName();
1505 SwNode* pSeqNd = 0;
1507 if( pSFld->IsSequenceFld() )
1509 const BYTE nLvl = pSFldTyp->GetOutlineLvl();
1510 if( MAXLEVEL > nLvl )
1512 // dann teste, ob die Nummer neu aufsetzen muss
1513 pSeqNd = GetNodes()[ (*ppSortLst)->GetNode() ];
1515 const SwTxtNode* pOutlNd = pSeqNd->
1516 FindOutlineNodeOfLevel( nLvl );
1517 if( pSFldTyp->GetOutlineChgNd() != pOutlNd )
1519 pSFldTyp->SetOutlineChgNd( pOutlNd );
1520 aCalc.VarChange( aNew, 0 );
1525 aNew += '=';
1526 aNew += pSFld->GetFormula();
1528 SwSbxValue aValue = aCalc.Calculate( aNew );
1529 double nErg = aValue.GetDouble();
1530 // nur ein spezielles Feld updaten ?
1531 if( !aValue.IsVoidValue() && (!pUpdtFld || pUpdtFld == pTxtFld) )
1533 pSFld->SetValue( nErg );
1535 if( pSeqNd )
1536 pSFldTyp->SetChapter( *pSFld, *pSeqNd );
1541 } // switch
1543 pFmtFld->Modify( 0, 0 ); // Formatierung anstossen
1545 if( pUpdtFld == pTxtFld ) // sollte nur dieses geupdatet werden
1547 if( RES_GETEXPFLD == nWhich || // nur GetFeld oder
1548 RES_HIDDENTXTFLD == nWhich || // HiddenTxt?
1549 RES_HIDDENPARAFLD == nWhich) // HiddenParaFld?
1550 break; // beenden
1551 pUpdtFld = 0; // ab jetzt alle Updaten
1555 pMgr->CloseAll(FALSE);
1556 // HashTabelle wieder loeschen
1557 ::DeleteHashTable( pHashStrTbl, nStrFmtCnt );
1559 // Referenzfelder updaten
1560 if( bUpdRefFlds )
1561 UpdateRefFlds(NULL);
1563 pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds );
1564 pUpdtFlds->SetFieldsDirty( FALSE );
1567 /*--------------------------------------------------------------------
1568 Beschreibung:
1569 --------------------------------------------------------------------*/
1571 void SwDoc::UpdateDBNumFlds( SwDBNameInfField& rDBFld, SwCalc& rCalc )
1573 SwNewDBMgr* pMgr = GetNewDBMgr();
1575 USHORT nFldType = rDBFld.Which();
1577 BOOL bPar1 = rCalc.Calculate( rDBFld.GetPar1() ).GetBool();
1579 if( RES_DBNEXTSETFLD == nFldType )
1580 ((SwDBNextSetField&)rDBFld).SetCondValid( bPar1 );
1581 else
1582 ((SwDBNumSetField&)rDBFld).SetCondValid( bPar1 );
1584 if( rDBFld.GetRealDBData().sDataSource.getLength() )
1586 // Eine bestimmte Datenbank bearbeiten
1587 if( RES_DBNEXTSETFLD == nFldType )
1588 ((SwDBNextSetField&)rDBFld).Evaluate(this);
1589 else
1590 ((SwDBNumSetField&)rDBFld).Evaluate(this);
1592 SwDBData aTmpDBData( rDBFld.GetDBData(this) );
1594 if( pMgr->OpenDataSource( aTmpDBData.sDataSource, aTmpDBData.sCommand, -1, false ))
1595 rCalc.VarChange( lcl_GetDBVarName( *this, rDBFld),
1596 pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType) );
1598 else
1600 DBG_ERROR("TODO: what should happen with unnamed DBFields?");
1604 /*--------------------------------------------------------------------
1605 Beschreibung:
1606 --------------------------------------------------------------------*/
1608 void SwDoc::_InitFieldTypes() // wird vom CTOR gerufen!!
1610 // Feldtypen
1611 USHORT nFldType = 0;
1612 pFldTypes->Insert( new SwDateTimeFieldType(this), nFldType++ );
1613 pFldTypes->Insert( new SwChapterFieldType, nFldType++ );
1614 pFldTypes->Insert( new SwPageNumberFieldType, nFldType++ );
1615 pFldTypes->Insert( new SwAuthorFieldType, nFldType++ );
1616 pFldTypes->Insert( new SwFileNameFieldType(this), nFldType++ );
1617 pFldTypes->Insert( new SwDBNameFieldType(this), nFldType++);
1618 pFldTypes->Insert( new SwGetExpFieldType(this), nFldType++ );
1619 pFldTypes->Insert( new SwGetRefFieldType( this ), nFldType++ );
1620 pFldTypes->Insert( new SwHiddenTxtFieldType, nFldType++ );
1621 pFldTypes->Insert( new SwPostItFieldType(this), nFldType++ );
1622 pFldTypes->Insert( new SwDocStatFieldType(this), nFldType++);
1623 pFldTypes->Insert( new SwDocInfoFieldType(this), nFldType++);
1624 pFldTypes->Insert( new SwInputFieldType( this ), nFldType++ );
1625 pFldTypes->Insert( new SwTblFieldType( this ), nFldType++);
1626 pFldTypes->Insert( new SwMacroFieldType(this), nFldType++ );
1627 pFldTypes->Insert( new SwHiddenParaFieldType, nFldType++ );
1628 pFldTypes->Insert( new SwDBNextSetFieldType, nFldType++ );
1629 pFldTypes->Insert( new SwDBNumSetFieldType, nFldType++ );
1630 pFldTypes->Insert( new SwDBSetNumberFieldType, nFldType++ );
1631 pFldTypes->Insert( new SwTemplNameFieldType(this), nFldType++);
1632 pFldTypes->Insert( new SwTemplNameFieldType(this),nFldType++);
1633 pFldTypes->Insert( new SwExtUserFieldType, nFldType++ );
1634 pFldTypes->Insert( new SwRefPageSetFieldType, nFldType++ );
1635 pFldTypes->Insert( new SwRefPageGetFieldType( this ), nFldType++ );
1636 pFldTypes->Insert( new SwJumpEditFieldType( this ), nFldType++ );
1637 pFldTypes->Insert( new SwScriptFieldType( this ), nFldType++ );
1638 pFldTypes->Insert( new SwCombinedCharFieldType, nFldType++ );
1639 pFldTypes->Insert( new SwDropDownFieldType, nFldType++ );
1641 // Types muessen am Ende stehen !!
1642 // Im InsertFldType wird davon ausgegangen !!!!
1643 // MIB 14.04.95: Im Sw3StringPool::Setup (sw3imp.cxx) und
1644 // lcl_sw3io_InSetExpField (sw3field.cxx) jetzt auch
1645 pFldTypes->Insert( new SwSetExpFieldType(this,
1646 SW_RESSTR(STR_POOLCOLL_LABEL_ABB), nsSwGetSetExpType::GSE_SEQ), nFldType++);
1647 pFldTypes->Insert( new SwSetExpFieldType(this,
1648 SW_RESSTR(STR_POOLCOLL_LABEL_TABLE), nsSwGetSetExpType::GSE_SEQ),nFldType++);
1649 pFldTypes->Insert( new SwSetExpFieldType(this,
1650 SW_RESSTR(STR_POOLCOLL_LABEL_FRAME), nsSwGetSetExpType::GSE_SEQ),nFldType++);
1651 pFldTypes->Insert( new SwSetExpFieldType(this,
1652 SW_RESSTR(STR_POOLCOLL_LABEL_DRAWING), nsSwGetSetExpType::GSE_SEQ),nFldType++);
1654 ASSERT( nFldType == INIT_FLDTYPES, "Bad initsize: SwFldTypes" );
1657 void SwDoc::InsDelFldInFldLst( bool bIns, const SwTxtFld& rFld )
1659 if( !mbNewFldLst || !IsInDtor() )
1660 pUpdtFlds->InsDelFldInFldLst( bIns, rFld );
1663 SwDBData SwDoc::GetDBData()
1665 return GetDBDesc();
1668 const SwDBData& SwDoc::GetDBDesc()
1670 if(!aDBData.sDataSource.getLength())
1672 const USHORT nSize = pFldTypes->Count();
1673 for(USHORT i = 0; i < nSize && !aDBData.sDataSource.getLength(); ++i)
1675 SwFieldType& rFldType = *((*pFldTypes)[i]);
1676 USHORT nWhich = rFldType.Which();
1677 if(IsUsed(rFldType))
1679 switch(nWhich)
1681 case RES_DBFLD:
1682 case RES_DBNEXTSETFLD:
1683 case RES_DBNUMSETFLD:
1684 case RES_DBSETNUMBERFLD:
1686 SwClientIter aIter( rFldType );
1687 SwFmtFld* pFld = (SwFmtFld*)aIter.First( TYPE( SwFmtFld ));
1688 while(pFld)
1690 if(pFld->IsFldInDoc())
1692 if(RES_DBFLD == nWhich)
1693 aDBData =
1694 (static_cast < SwDBFieldType * > (pFld->GetFld()->GetTyp()))
1695 ->GetDBData();
1696 else
1697 aDBData = (static_cast < SwDBNameInfField* > (pFld->GetFld()))->GetRealDBData();
1698 break;
1700 pFld = (SwFmtFld*)aIter.Next();
1703 break;
1708 if(!aDBData.sDataSource.getLength())
1709 aDBData = GetNewDBMgr()->GetAddressDBName();
1710 return aDBData;
1713 void SwDoc::SetInitDBFields( BOOL b )
1715 GetNewDBMgr()->SetInitDBFields( b );
1718 /*--------------------------------------------------------------------
1719 Beschreibung: Alle von Feldern verwendete Datenbanken herausfinden
1720 --------------------------------------------------------------------*/
1721 String lcl_DBDataToString(const SwDBData& rData)
1723 String sRet = rData.sDataSource;
1724 sRet += DB_DELIM;
1725 sRet += (String)rData.sCommand;
1726 sRet += DB_DELIM;
1727 sRet += String::CreateFromInt32(rData.nCommandType);
1728 return sRet;
1730 void SwDoc::GetAllUsedDB( SvStringsDtor& rDBNameList,
1731 const SvStringsDtor* pAllDBNames )
1733 USHORT n;
1734 SvStringsDtor aUsedDBNames;
1735 SvStringsDtor aAllDBNames;
1737 if( !pAllDBNames )
1739 GetAllDBNames( aAllDBNames );
1740 pAllDBNames = &aAllDBNames;
1743 SwSectionFmts& rArr = GetSections();
1744 for( n = rArr.Count(); n; )
1746 SwSection* pSect = rArr[ --n ]->GetSection();
1748 if( pSect )
1750 String aCond( pSect->GetCondition() );
1751 AddUsedDBToList( rDBNameList, FindUsedDBs( *pAllDBNames,
1752 aCond, aUsedDBNames ) );
1753 aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
1757 const SfxPoolItem* pItem;
1758 USHORT nMaxItems = GetAttrPool().GetItemCount( RES_TXTATR_FIELD );
1759 for( n = 0; n < nMaxItems; ++n )
1761 if( 0 == (pItem = GetAttrPool().GetItem( RES_TXTATR_FIELD, n ) ))
1762 continue;
1764 const SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
1765 const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1766 if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
1767 continue;
1769 const SwField* pFld = pFmtFld->GetFld();
1770 switch( pFld->GetTyp()->Which() )
1772 case RES_DBFLD:
1773 AddUsedDBToList( rDBNameList,
1774 lcl_DBDataToString(((SwDBField*)pFld)->GetDBData() ));
1775 break;
1777 case RES_DBSETNUMBERFLD:
1778 case RES_DBNAMEFLD:
1779 AddUsedDBToList( rDBNameList,
1780 lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() ));
1781 break;
1783 case RES_DBNUMSETFLD:
1784 case RES_DBNEXTSETFLD:
1785 AddUsedDBToList( rDBNameList,
1786 lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() ));
1787 // kein break // JP: ist das so richtig ??
1789 case RES_HIDDENTXTFLD:
1790 case RES_HIDDENPARAFLD:
1791 AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames,
1792 pFld->GetPar1(), aUsedDBNames ));
1793 aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
1794 break;
1796 case RES_SETEXPFLD:
1797 case RES_GETEXPFLD:
1798 case RES_TABLEFLD:
1799 AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames,
1800 pFld->GetFormula(), aUsedDBNames ));
1801 aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
1802 break;
1807 /*--------------------------------------------------------------------
1808 Beschreibung:
1809 --------------------------------------------------------------------*/
1811 void SwDoc::GetAllDBNames( SvStringsDtor& rAllDBNames )
1813 SwNewDBMgr* pMgr = GetNewDBMgr();
1815 const SwDSParamArr& rArr = pMgr->GetDSParamArray();
1816 for(USHORT i = 0; i < rArr.Count(); i++)
1818 SwDSParam* pParam = rArr[i];
1819 String* pStr = new String( pParam->sDataSource );
1820 (*pStr) += DB_DELIM;
1821 (*pStr) += (String)pParam->sCommand;
1822 rAllDBNames.Insert( pStr, rAllDBNames.Count() );
1826 /*--------------------------------------------------------------------
1827 Beschreibung:
1828 --------------------------------------------------------------------*/
1830 SvStringsDtor& SwDoc::FindUsedDBs( const SvStringsDtor& rAllDBNames,
1831 const String& rFormel,
1832 SvStringsDtor& rUsedDBNames )
1834 const CharClass& rCC = GetAppCharClass();
1835 String sFormel( rFormel);
1836 #ifndef UNX
1837 rCC.toUpper( sFormel );
1838 #endif
1840 xub_StrLen nPos;
1841 for (USHORT i = 0; i < rAllDBNames.Count(); ++i )
1843 const String* pStr = rAllDBNames.GetObject(i);
1845 if( STRING_NOTFOUND != (nPos = sFormel.Search( *pStr )) &&
1846 sFormel.GetChar( nPos + pStr->Len() ) == '.' &&
1847 (!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 )))
1849 // Tabellenname suchen
1850 xub_StrLen nEndPos;
1851 nPos += pStr->Len() + 1;
1852 if( STRING_NOTFOUND != (nEndPos = sFormel.Search('.', nPos)) )
1854 String* pDBNm = new String( *pStr );
1855 pDBNm->Append( DB_DELIM );
1856 pDBNm->Append( sFormel.Copy( nPos, nEndPos - nPos ));
1857 rUsedDBNames.Insert( pDBNm, rUsedDBNames.Count() );
1861 return rUsedDBNames;
1864 /*--------------------------------------------------------------------
1865 Beschreibung:
1866 --------------------------------------------------------------------*/
1868 void SwDoc::AddUsedDBToList( SvStringsDtor& rDBNameList,
1869 const SvStringsDtor& rUsedDBNames )
1871 for (USHORT i = 0; i < rUsedDBNames.Count(); i++)
1872 AddUsedDBToList( rDBNameList, *rUsedDBNames.GetObject(i) );
1875 /*--------------------------------------------------------------------
1876 Beschreibung:
1877 --------------------------------------------------------------------*/
1879 void SwDoc::AddUsedDBToList( SvStringsDtor& rDBNameList, const String& rDBName)
1881 if( !rDBName.Len() )
1882 return;
1884 #ifdef UNX
1885 for( USHORT i = 0; i < rDBNameList.Count(); ++i )
1886 if( rDBName == rDBNameList.GetObject(i)->GetToken(0) )
1887 return;
1888 #else
1889 const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
1890 for( USHORT i = 0; i < rDBNameList.Count(); ++i )
1891 if( rSCmp.isEqual( rDBName, rDBNameList.GetObject(i)->GetToken(0) ) )
1892 return;
1893 #endif
1895 SwDBData aData;
1896 aData.sDataSource = rDBName.GetToken(0, DB_DELIM);
1897 aData.sCommand = rDBName.GetToken(1, DB_DELIM);
1898 aData.nCommandType = -1;
1899 GetNewDBMgr()->CreateDSData(aData);
1900 String* pNew = new String( rDBName );
1901 rDBNameList.Insert( pNew, rDBNameList.Count() );
1904 /*--------------------------------------------------------------------
1905 Beschreibung:
1906 --------------------------------------------------------------------*/
1908 void SwDoc::ChangeDBFields( const SvStringsDtor& rOldNames,
1909 const String& rNewName )
1911 SwDBData aNewDBData;
1912 aNewDBData.sDataSource = rNewName.GetToken(0, DB_DELIM);
1913 aNewDBData.sCommand = rNewName.GetToken(1, DB_DELIM);
1914 aNewDBData.nCommandType = (short)rNewName.GetToken(2, DB_DELIM).ToInt32();
1916 String sFormel;
1917 USHORT n;
1919 SwSectionFmts& rArr = GetSections();
1920 for( n = rArr.Count(); n; )
1922 SwSection* pSect = rArr[ --n ]->GetSection();
1924 if( pSect )
1926 sFormel = pSect->GetCondition();
1927 ReplaceUsedDBs( rOldNames, rNewName, sFormel);
1928 pSect->SetCondition(sFormel);
1932 const SfxPoolItem* pItem;
1933 USHORT nMaxItems = GetAttrPool().GetItemCount( RES_TXTATR_FIELD );
1935 for( n = 0; n < nMaxItems; ++n )
1937 if( 0 == (pItem = GetAttrPool().GetItem( RES_TXTATR_FIELD, n ) ))
1938 continue;
1940 SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
1941 SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1942 if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
1943 continue;
1945 SwField* pFld = pFmtFld->GetFld();
1946 BOOL bExpand = FALSE;
1948 switch( pFld->GetTyp()->Which() )
1950 case RES_DBFLD:
1951 if( IsNameInArray( rOldNames, lcl_DBDataToString(((SwDBField*)pFld)->GetDBData())))
1953 SwDBFieldType* pOldTyp = (SwDBFieldType*)pFld->GetTyp();
1955 SwDBFieldType* pTyp = (SwDBFieldType*)InsertFldType(
1956 SwDBFieldType(this, pOldTyp->GetColumnName(), aNewDBData));
1958 pTyp->Add(pFmtFld); // Feld auf neuen Typ umhaengen
1959 pFld->ChgTyp(pTyp);
1961 ((SwDBField*)pFld)->ClearInitialized();
1962 ((SwDBField*)pFld)->InitContent();
1964 bExpand = TRUE;
1966 break;
1968 case RES_DBSETNUMBERFLD:
1969 case RES_DBNAMEFLD:
1970 if( IsNameInArray( rOldNames,
1971 lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData())))
1973 ((SwDBNameInfField*)pFld)->SetDBData(aNewDBData);
1974 bExpand = TRUE;
1976 break;
1978 case RES_DBNUMSETFLD:
1979 case RES_DBNEXTSETFLD:
1980 if( IsNameInArray( rOldNames,
1981 lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData())))
1983 ((SwDBNameInfField*)pFld)->SetDBData(aNewDBData);
1984 bExpand = TRUE;
1986 // kein break;
1987 case RES_HIDDENTXTFLD:
1988 case RES_HIDDENPARAFLD:
1989 sFormel = pFld->GetPar1();
1990 ReplaceUsedDBs( rOldNames, rNewName, sFormel);
1991 pFld->SetPar1( sFormel );
1992 bExpand = TRUE;
1993 break;
1995 case RES_SETEXPFLD:
1996 case RES_GETEXPFLD:
1997 case RES_TABLEFLD:
1998 sFormel = pFld->GetFormula();
1999 ReplaceUsedDBs( rOldNames, rNewName, sFormel);
2000 pFld->SetPar2( sFormel );
2001 bExpand = TRUE;
2002 break;
2005 if (bExpand)
2006 pTxtFld->ExpandAlways();
2008 SetModified();
2011 /*--------------------------------------------------------------------
2012 Beschreibung:
2013 --------------------------------------------------------------------*/
2015 void SwDoc::ReplaceUsedDBs( const SvStringsDtor& rUsedDBNames,
2016 const String& rNewName, String& rFormel )
2018 const CharClass& rCC = GetAppCharClass();
2019 String sFormel(rFormel);
2020 String sNewName( rNewName );
2021 sNewName.SearchAndReplace( DB_DELIM, '.');
2022 //the command type is not part of the condition
2023 sNewName = sNewName.GetToken(0, DB_DELIM);
2024 String sUpperNewNm( sNewName );
2027 for( USHORT i = 0; i < rUsedDBNames.Count(); ++i )
2029 String sDBName( *rUsedDBNames.GetObject( i ) );
2031 sDBName.SearchAndReplace( DB_DELIM, '.');
2032 //cut off command type
2033 sDBName = sDBName.GetToken(0, DB_DELIM);
2034 if( !sDBName.Equals( sUpperNewNm ))
2036 xub_StrLen nPos = 0;
2038 while ((nPos = sFormel.Search(sDBName, nPos)) != STRING_NOTFOUND)
2040 if( sFormel.GetChar( nPos + sDBName.Len() ) == '.' &&
2041 (!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 )))
2043 rFormel.Erase( nPos, sDBName.Len() );
2044 rFormel.Insert( sNewName, nPos );
2045 //prevent re-searching - this is useless and provokes
2046 //endless loops when names containing each other and numbers are exchanged
2047 //e.g.: old ?12345.12345 new: i12345.12345
2048 nPos = nPos + sNewName.Len();
2049 sFormel = rFormel;
2056 /*--------------------------------------------------------------------
2057 Beschreibung:
2058 --------------------------------------------------------------------*/
2060 BOOL SwDoc::IsNameInArray( const SvStringsDtor& rArr, const String& rName )
2062 #ifdef UNX
2063 for( USHORT i = 0; i < rArr.Count(); ++i )
2064 if( rName == *rArr[ i ] )
2065 return TRUE;
2066 #else
2067 const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
2068 for( USHORT i = 0; i < rArr.Count(); ++i )
2069 if( rSCmp.isEqual( rName, *rArr[ i] ))
2070 return TRUE;
2071 #endif
2072 return FALSE;
2075 void SwDoc::SetFixFields( bool bOnlyTimeDate, const DateTime* pNewDateTime )
2077 BOOL bIsModified = IsModified();
2079 ULONG nDate, nTime;
2080 if( pNewDateTime )
2082 nDate = pNewDateTime->GetDate();
2083 nTime = pNewDateTime->GetTime();
2085 else
2087 nDate = Date().GetDate();
2088 nTime = Time().GetTime();
2091 USHORT aTypes[5] = {
2092 /*0*/ RES_DOCINFOFLD,
2093 /*1*/ RES_AUTHORFLD,
2094 /*2*/ RES_EXTUSERFLD,
2095 /*3*/ RES_FILENAMEFLD,
2096 /*4*/ RES_DATETIMEFLD }; // MUSS am Ende stehen!!
2098 USHORT nStt = bOnlyTimeDate ? 4 : 0;
2100 for( ; nStt < 5; ++nStt )
2102 SwFieldType* pFldType = GetSysFldType( aTypes[ nStt ] );
2103 SwClientIter aDocInfIter( *pFldType );
2105 for( SwFmtFld* pFld = (SwFmtFld*)aDocInfIter.First( TYPE( SwFmtFld ));
2106 pFld; pFld = (SwFmtFld*)aDocInfIter.Next() )
2108 if( pFld && pFld->GetTxtFld() )
2110 BOOL bChgd = FALSE;
2111 switch( aTypes[ nStt ] )
2113 case RES_DOCINFOFLD:
2114 if( ((SwDocInfoField*)pFld->GetFld())->IsFixed() )
2116 bChgd = TRUE;
2117 SwDocInfoField* pDocInfFld = (SwDocInfoField*)pFld->GetFld();
2118 pDocInfFld->SetExpansion( ((SwDocInfoFieldType*)
2119 pDocInfFld->GetTyp())->Expand(
2120 pDocInfFld->GetSubType(),
2121 pDocInfFld->GetFormat(),
2122 pDocInfFld->GetLanguage(),
2123 pDocInfFld->GetName() ) );
2125 break;
2127 case RES_AUTHORFLD:
2128 if( ((SwAuthorField*)pFld->GetFld())->IsFixed() )
2130 bChgd = TRUE;
2131 SwAuthorField* pAuthorFld = (SwAuthorField*)pFld->GetFld();
2132 pAuthorFld->SetExpansion( ((SwAuthorFieldType*)
2133 pAuthorFld->GetTyp())->Expand(
2134 pAuthorFld->GetFormat() ) );
2136 break;
2138 case RES_EXTUSERFLD:
2139 if( ((SwExtUserField*)pFld->GetFld())->IsFixed() )
2141 bChgd = TRUE;
2142 SwExtUserField* pExtUserFld = (SwExtUserField*)pFld->GetFld();
2143 pExtUserFld->SetExpansion( ((SwExtUserFieldType*)
2144 pExtUserFld->GetTyp())->Expand(
2145 pExtUserFld->GetSubType(),
2146 pExtUserFld->GetFormat()));
2148 break;
2150 case RES_DATETIMEFLD:
2151 if( ((SwDateTimeField*)pFld->GetFld())->IsFixed() )
2153 bChgd = TRUE;
2154 ((SwDateTimeField*)pFld->GetFld())->SetDateTime(
2155 DateTime(Date(nDate), Time(nTime)) );
2157 break;
2159 case RES_FILENAMEFLD:
2160 if( ((SwFileNameField*)pFld->GetFld())->IsFixed() )
2162 bChgd = TRUE;
2163 SwFileNameField* pFileNameFld =
2164 (SwFileNameField*)pFld->GetFld();
2165 pFileNameFld->SetExpansion( ((SwFileNameFieldType*)
2166 pFileNameFld->GetTyp())->Expand(
2167 pFileNameFld->GetFormat() ) );
2169 break;
2172 // Formatierung anstossen
2173 if( bChgd )
2174 pFld->Modify( 0, 0 );
2179 if( !bIsModified )
2180 ResetModified();
2183 bool SwDoc::SetFieldsDirty( bool b, const SwNode* pChk, ULONG nLen )
2185 // teste ggfs. mal, ob die angegbenen Nodes ueberhaupt Felder beinhalten.
2186 // wenn nicht, braucht das Flag nicht veraendert werden.
2187 BOOL bFldsFnd = FALSE;
2188 if( b && pChk && !GetUpdtFlds().IsFieldsDirty() && !IsInDtor()
2189 // ?? was ist mit Undo, da will man es doch auch haben !!
2190 /*&& &pChk->GetNodes() == &GetNodes()*/ )
2192 b = FALSE;
2193 if( !nLen )
2194 ++nLen;
2195 ULONG nStt = pChk->GetIndex();
2196 const SwNodes& rNds = pChk->GetNodes();
2197 while( nLen-- )
2199 const SwTxtNode* pTNd = rNds[ nStt++ ]->GetTxtNode();
2200 if( pTNd )
2202 if( //pTNd->GetFmtColl() && //#outline level,zhaojianwei
2203 // MAXLEVEL > pTNd->GetTxtColl()->GetOutlineLevel() )
2204 pTNd->GetAttrOutlineLevel() != 0 )//<-end,zhaojianwei
2205 // Kapitelfelder aktualisieren
2206 b = TRUE;
2207 else if( pTNd->GetpSwpHints() && pTNd->GetSwpHints().Count() )
2208 for( USHORT n = 0, nEnd = pTNd->GetSwpHints().Count();
2209 n < nEnd; ++n )
2211 const SwTxtAttr* pAttr = pTNd->GetSwpHints()[ n ];
2212 if( RES_TXTATR_FIELD == pAttr->Which() )
2214 b = TRUE;
2215 break;
2219 if( b )
2220 break;
2223 bFldsFnd = b;
2225 GetUpdtFlds().SetFieldsDirty( b );
2226 return bFldsFnd;
2228 /* -----------------------------21.12.99 12:55--------------------------------
2230 ---------------------------------------------------------------------------*/
2231 void SwDoc::ChangeAuthorityData( const SwAuthEntry* pNewData )
2233 const USHORT nSize = pFldTypes->Count();
2235 for( USHORT i = INIT_FLDTYPES; i < nSize; ++i )
2237 SwFieldType* pFldType = (*pFldTypes)[i];
2238 if( RES_AUTHORITY == pFldType->Which() )
2240 SwAuthorityFieldType* pAuthType = (SwAuthorityFieldType*)pFldType;
2241 pAuthType->ChangeEntryContent(pNewData);
2242 break;
2247 /*--------------------------------------------------------------------
2248 Beschreibung:
2249 --------------------------------------------------------------------*/
2251 void SwDocUpdtFld::InsDelFldInFldLst( BOOL bIns, const SwTxtFld& rFld )
2253 USHORT nWhich = rFld.GetFld().GetFld()->GetTyp()->Which();
2254 switch( nWhich )
2256 case RES_DBFLD:
2257 case RES_SETEXPFLD:
2258 case RES_HIDDENPARAFLD:
2259 case RES_HIDDENTXTFLD:
2260 case RES_DBNUMSETFLD:
2261 case RES_DBNEXTSETFLD:
2262 case RES_DBSETNUMBERFLD:
2263 case RES_GETEXPFLD:
2264 break; // diese muessen ein-/ausgetragen werden!
2266 default:
2267 return;
2270 SetFieldsDirty( TRUE );
2271 if( !pFldSortLst )
2273 if( !bIns ) // keine Liste vorhanden und loeschen
2274 return; // dann nichts tun
2275 pFldSortLst = new _SetGetExpFlds( 64, 16 );
2278 if( bIns ) // neu einfuegen:
2279 GetBodyNode( rFld, nWhich );
2280 else
2282 // ueber den pTxtFld Pointer suchen. Ist zwar eine Sortierte
2283 // Liste, aber nach Node-Positionen sortiert. Bis dieser
2284 // bestimmt ist, ist das Suchen nach dem Pointer schon fertig
2285 for( USHORT n = 0; n < pFldSortLst->Count(); ++n )
2286 if( &rFld == (*pFldSortLst)[ n ]->GetPointer() )
2287 pFldSortLst->DeleteAndDestroy( n--, 1 );
2288 // ein Feld kann mehrfach vorhanden sein!
2292 void SwDocUpdtFld::MakeFldList( SwDoc& rDoc, int bAll, int eGetMode )
2294 if( !pFldSortLst || bAll || !( eGetMode & nFldLstGetMode ) ||
2295 rDoc.GetNodes().Count() != nNodes )
2296 _MakeFldList( rDoc, eGetMode );
2299 void SwDocUpdtFld::_MakeFldList( SwDoc& rDoc, int eGetMode )
2301 // neue Version: gehe ueber alle Felder vom Attribut-Pool
2302 if( pFldSortLst )
2303 delete pFldSortLst;
2304 pFldSortLst = new _SetGetExpFlds( 64, 16 );
2306 /// OD 09.08.2002 [#101207#,#101216#,#101778#] - consider and unhide sections
2307 /// with hide condition, only in mode GETFLD_ALL (<eGetMode == GETFLD_ALL>)
2308 /// notes by OD:
2309 /// eGetMode == GETFLD_CALC in call from methods SwDoc::FldsToCalc
2310 /// eGetMode == GETFLD_EXPAND in call from method SwDoc::FldsToExpand
2311 /// eGetMode == GETFLD_ALL in call from method SwDoc::UpdateExpFlds
2312 /// I figured out that hidden section only have to be shown,
2313 /// if fields have updated (call by SwDoc::UpdateExpFlds) and thus
2314 /// the hide conditions of section have to be updated.
2315 /// For correct updating the hide condition of a section, its position
2316 /// have to be known in order to insert the hide condition as a new
2317 /// expression field into the sorted field list (<pFldSortLst>).
2318 if ( eGetMode == GETFLD_ALL )
2319 // zuerst die Bereiche einsammeln. Alle die ueber Bedingung
2320 // gehiddet sind, wieder mit Frames versorgen, damit die darin
2321 // enthaltenen Felder richtig einsortiert werden!!!
2323 // damit die Frames richtig angelegt werden, muessen sie in der
2324 // Reihenfolgen von oben nach unten expandiert werden
2325 SvULongs aTmpArr;
2326 SwSectionFmts& rArr = rDoc.GetSections();
2327 SwSectionNode* pSectNd;
2328 USHORT nArrStt = 0;
2329 ULONG nSttCntnt = rDoc.GetNodes().GetEndOfExtras().GetIndex();
2330 USHORT n;
2332 for( n = rArr.Count(); n; )
2334 SwSection* pSect = rArr[ --n ]->GetSection();
2335 if( pSect && pSect->IsHidden() && pSect->GetCondition().Len() &&
2336 0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() ))
2338 ULONG nIdx = pSectNd->GetIndex();
2339 USHORT i;
2341 for( i = 0; i < aTmpArr.Count() && aTmpArr[ i ] < nIdx; ++i )
2343 aTmpArr.Insert( nIdx, i );
2344 if( nIdx < nSttCntnt )
2345 ++nArrStt;
2349 // erst alle anzeigen, damit die Frames vorhanden sind. Mit deren
2350 // Position wird das BodyAnchor ermittelt.
2351 // Dafuer erst den ContentBereich, dann die Sonderbereiche!!!
2352 for( n = nArrStt; n < aTmpArr.Count(); ++n )
2354 pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
2355 ASSERT( pSectNd, "Wo ist mein SectionNode" );
2356 pSectNd->GetSection().SetCondHidden( FALSE );
2358 for( n = 0; n < nArrStt; ++n )
2360 pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
2361 ASSERT( pSectNd, "Wo ist mein SectionNode" );
2362 pSectNd->GetSection().SetCondHidden( FALSE );
2365 // so, erst jetzt alle sortiert in die Liste eintragen
2366 for( n = 0; n < aTmpArr.Count(); ++n )
2367 GetBodyNode( *rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode() );
2370 String sTrue( String::CreateFromAscii(
2371 RTL_CONSTASCII_STRINGPARAM( "TRUE" ))),
2372 sFalse( String::CreateFromAscii(
2373 RTL_CONSTASCII_STRINGPARAM( "FALSE" )));
2375 BOOL bIsDBMgr = 0 != rDoc.GetNewDBMgr();
2376 USHORT nWhich, n;
2377 const String* pFormel = 0;
2378 const SfxPoolItem* pItem;
2379 USHORT nMaxItems = rDoc.GetAttrPool().GetItemCount( RES_TXTATR_FIELD );
2380 for( n = 0; n < nMaxItems; ++n )
2382 if( 0 == (pItem = rDoc.GetAttrPool().GetItem( RES_TXTATR_FIELD, n )) )
2383 continue;
2385 const SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
2386 const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
2387 if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
2388 continue;
2390 const SwField* pFld = pFmtFld->GetFld();
2391 switch( nWhich = pFld->GetTyp()->Which() )
2393 case RES_DBSETNUMBERFLD:
2394 case RES_GETEXPFLD:
2395 if( GETFLD_ALL == eGetMode )
2396 pFormel = &sTrue;
2397 break;
2399 case RES_DBFLD:
2400 if( GETFLD_EXPAND & eGetMode )
2401 pFormel = &sTrue;
2402 break;
2404 case RES_SETEXPFLD:
2405 /// OD 04.10.2002 #102894#
2406 /// fields of subtype <string> have also been add
2407 /// for calculation (eGetMode == GETFLD_CALC).
2408 /// Thus, add fields of subtype <string> in all modes
2409 /// (eGetMode == GETFLD_EXPAND||GETFLD_CALC||GETFLD_ALL)
2410 /// and fields of other subtypes only in the modes
2411 /// (eGetMode == GETFLD_CALC||GETFLD_ALL)
2412 /* "old" if construct - not deleted for history and code review
2413 if( ( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType()
2414 ? GETFLD_EXPAND : GETFLD_CALC )
2415 & eGetMode )
2417 if ( !(eGetMode == GETFLD_EXPAND) ||
2418 (nsSwGetSetExpType::GSE_STRING & pFld->GetSubType()) )
2420 pFormel = &sTrue;
2422 break;
2424 case RES_HIDDENPARAFLD:
2425 if( GETFLD_ALL == eGetMode )
2427 pFormel = &pFld->GetPar1();
2428 if( !pFormel->Len() || pFormel->Equals( sFalse ))
2429 ((SwHiddenParaField*)pFld)->SetHidden( FALSE );
2430 else if( pFormel->Equals( sTrue ))
2431 ((SwHiddenParaField*)pFld)->SetHidden( TRUE );
2432 else
2433 break;
2435 pFormel = 0;
2436 // Formatierung anstossen
2437 ((SwFmtFld*)pFmtFld)->Modify( 0, 0 );
2439 break;
2441 case RES_HIDDENTXTFLD:
2442 if( GETFLD_ALL == eGetMode )
2444 pFormel = &pFld->GetPar1();
2445 if( !pFormel->Len() || pFormel->Equals( sFalse ))
2446 ((SwHiddenTxtField*)pFld)->SetValue( TRUE );
2447 else if( pFormel->Equals( sTrue ))
2448 ((SwHiddenTxtField*)pFld)->SetValue( FALSE );
2449 else
2450 break;
2452 pFormel = 0;
2454 // Feld Evaluieren
2455 ((SwHiddenTxtField*)pFld)->Evaluate(&rDoc);
2456 // Formatierung anstossen
2457 ((SwFmtFld*)pFmtFld)->Modify( 0, 0 );
2459 break;
2461 case RES_DBNUMSETFLD:
2463 SwDBData aDBData(((SwDBNumSetField*)pFld)->GetDBData(&rDoc));
2465 if( bIsDBMgr &&
2466 rDoc.GetNewDBMgr()->OpenDataSource( aDBData.sDataSource, aDBData.sCommand )&&
2467 GETFLD_ALL == eGetMode ||
2468 ( GETFLD_CALC & eGetMode &&
2469 ((SwDBNumSetField*)pFld)->IsCondValid()))
2470 pFormel = &pFld->GetPar1();
2472 break;
2473 case RES_DBNEXTSETFLD:
2475 SwDBData aDBData(((SwDBNextSetField*)pFld)->GetDBData(&rDoc));
2477 if( bIsDBMgr &&
2478 rDoc.GetNewDBMgr()->OpenDataSource( aDBData.sDataSource, aDBData.sCommand )&&
2479 GETFLD_ALL == eGetMode ||
2480 ( GETFLD_CALC & eGetMode &&
2481 ((SwDBNextSetField*)pFld)->IsCondValid() ))
2482 pFormel = &pFld->GetPar1();
2484 break;
2487 if( pFormel && pFormel->Len() )
2489 GetBodyNode( *pTxtFld, nWhich );
2490 pFormel = 0;
2493 nFldLstGetMode = static_cast<BYTE>( eGetMode );
2494 nNodes = rDoc.GetNodes().Count();
2496 #ifdef JP_DEBUG
2498 SvFileStream sOut( "f:\\x.x", STREAM_STD_WRITE );
2499 sOut.Seek( STREAM_SEEK_TO_END );
2500 sOut << "------------------" << endl;
2501 const _SetGetExpFldPtr* pSortLst = pFldSortLst->GetData();
2502 for( USHORT n = pFldSortLst->Count(); n; --n, ++pSortLst )
2504 String sStr( (*pSortLst)->GetNode() );
2505 sStr += "\t, ";
2506 sStr += (*pSortLst)->GetCntnt();
2507 sStr += "\tNode: ";
2508 sStr += (*pSortLst)->GetFld()->GetTxtNode().StartOfSectionIndex();
2509 sStr += "\tPos: ";
2510 sStr += *(*pSortLst)->GetFld()->GetStart();
2511 sStr += "\tType: ";
2512 sStr += (*pSortLst)->GetFld()->GetFld().GetFld()->GetTyp()->Which();
2514 sOut << sStr.GetStr() << endl;
2517 #endif
2518 // JP_DEBUG
2521 /*--------------------------------------------------------------------
2522 Beschreibung:
2523 --------------------------------------------------------------------*/
2525 void SwDocUpdtFld::GetBodyNode( const SwTxtFld& rTFld, USHORT nFldWhich )
2527 const SwTxtNode& rTxtNd = rTFld.GetTxtNode();
2528 const SwDoc& rDoc = *rTxtNd.GetDoc();
2530 // immer den ersten !! (in Tab-Headline, Kopf-/Fuss )
2531 Point aPt;
2532 const SwCntntFrm* pFrm = rTxtNd.GetFrm( &aPt, 0, FALSE );
2534 _SetGetExpFld* pNew = NULL;
2535 BOOL bIsInBody = FALSE;
2537 if( !pFrm || pFrm->IsInDocBody() )
2539 // einen Index fuers bestimmen vom TextNode anlegen
2540 SwNodeIndex aIdx( rTxtNd );
2541 bIsInBody = rDoc.GetNodes().GetEndOfExtras().GetIndex() < aIdx.GetIndex();
2543 // #104291# dvo: We don't want to update fields in redlines, or those
2544 // in frames whose anchor is in redline. However, we do want to update
2545 // fields in hidden sections. So: In order to be updated, a field 1)
2546 // must have a frame, or 2) it must be in the document body.
2547 if( (pFrm != NULL) || bIsInBody )
2548 pNew = new _SetGetExpFld( aIdx, &rTFld );
2550 else
2552 // einen Index fuers bestimmen vom TextNode anlegen
2553 SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() );
2554 #ifndef PRODUCT
2555 ASSERT( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" );
2556 #else
2557 GetBodyTxtNode( rDoc, aPos, *pFrm );
2558 #endif
2559 pNew = new _SetGetExpFld( aPos.nNode, &rTFld, &aPos.nContent );
2562 // bei GetExp.-/DB.-Felder immer das BodyTxtFlag setzen
2563 if( RES_GETEXPFLD == nFldWhich )
2565 SwGetExpField* pGetFld = (SwGetExpField*)rTFld.GetFld().GetFld();
2566 pGetFld->ChgBodyTxtFlag( bIsInBody );
2568 else if( RES_DBFLD == nFldWhich )
2570 SwDBField* pDBFld = (SwDBField*)rTFld.GetFld().GetFld();
2571 pDBFld->ChgBodyTxtFlag( bIsInBody );
2574 if( pNew != NULL )
2575 if( !pFldSortLst->Insert( pNew ))
2576 delete pNew;
2579 void SwDocUpdtFld::GetBodyNode( const SwSectionNode& rSectNd )
2581 const SwDoc& rDoc = *rSectNd.GetDoc();
2582 _SetGetExpFld* pNew = 0;
2584 if( rSectNd.GetIndex() < rDoc.GetNodes().GetEndOfExtras().GetIndex() )
2586 do { // middle check loop
2588 // dann muessen wir uns mal den Anker besorgen!
2589 // einen Index fuers bestimmen vom TextNode anlegen
2590 SwPosition aPos( rSectNd );
2591 SwCntntNode* pCNd = rDoc.GetNodes().GoNext( &aPos.nNode ); // zum naechsten ContentNode
2593 if( !pCNd || !pCNd->IsTxtNode() )
2594 break;
2596 // immer den ersten !! (in Tab-Headline, Kopf-/Fuss )
2597 Point aPt;
2598 const SwCntntFrm* pFrm = pCNd->GetFrm( &aPt, 0, FALSE );
2599 if( !pFrm )
2600 break;
2602 #ifndef PRODUCT
2603 ASSERT( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" );
2604 #else
2605 GetBodyTxtNode( rDoc, aPos, *pFrm );
2606 #endif
2607 pNew = new _SetGetExpFld( rSectNd, &aPos );
2609 } while( FALSE );
2612 if( !pNew )
2613 pNew = new _SetGetExpFld( rSectNd );
2615 if( !pFldSortLst->Insert( pNew ))
2616 delete pNew;
2619 void SwDocUpdtFld::InsertFldType( const SwFieldType& rType )
2621 String sFldName;
2622 switch( rType.Which() )
2624 case RES_USERFLD :
2625 sFldName = ((SwUserFieldType&)rType).GetName();
2626 break;
2627 case RES_SETEXPFLD:
2628 sFldName = ((SwSetExpFieldType&)rType).GetName();
2629 break;
2630 default:
2631 ASSERT( !this, "kein gueltiger FeldTyp" );
2634 if( sFldName.Len() )
2636 SetFieldsDirty( TRUE );
2637 // suchen und aus der HashTabelle entfernen
2638 GetAppCharClass().toLower( sFldName );
2639 USHORT n;
2641 SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n );
2643 if( !pFnd )
2645 SwCalcFldType* pNew = new SwCalcFldType( sFldName, &rType );
2646 pNew->pNext = aFldTypeTable[ n ];
2647 aFldTypeTable[ n ] = pNew;
2652 void SwDocUpdtFld::RemoveFldType( const SwFieldType& rType )
2654 String sFldName;
2655 switch( rType.Which() )
2657 case RES_USERFLD :
2658 sFldName = ((SwUserFieldType&)rType).GetName();
2659 break;
2660 case RES_SETEXPFLD:
2661 sFldName = ((SwSetExpFieldType&)rType).GetName();
2662 break;
2665 if( sFldName.Len() )
2667 SetFieldsDirty( TRUE );
2668 // suchen und aus der HashTabelle entfernen
2669 GetAppCharClass().toLower( sFldName );
2670 USHORT n;
2672 SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n );
2673 if( pFnd )
2675 if( aFldTypeTable[ n ] == pFnd )
2676 aFldTypeTable[ n ] = (SwCalcFldType*)pFnd->pNext;
2677 else
2679 SwHash* pPrev = aFldTypeTable[ n ];
2680 while( pPrev->pNext != pFnd )
2681 pPrev = pPrev->pNext;
2682 pPrev->pNext = pFnd->pNext;
2684 pFnd->pNext = 0;
2685 delete pFnd;
2690 SwDocUpdtFld::SwDocUpdtFld()
2691 : pFldSortLst(0), nFldUpdtPos(LONG_MAX), nFldLstGetMode(0)
2693 bInUpdateFlds = bFldsDirty = FALSE;
2694 memset( aFldTypeTable, 0, sizeof( aFldTypeTable ) );
2697 SwDocUpdtFld::~SwDocUpdtFld()
2699 delete pFldSortLst;
2701 for( USHORT n = 0; n < TBLSZ; ++n )
2702 delete aFldTypeTable[n];
2705 // #111840#
2706 bool SwDoc::UpdateFld(SwTxtFld * pDstTxtFld, SwField & rSrcFld,
2707 SwMsgPoolItem * pMsgHnt,
2708 bool bUpdateFlds)
2710 ASSERT(pDstTxtFld, "no field to update!");
2712 BOOL bTblSelBreak = FALSE;
2714 SwFmtFld * pDstFmtFld = (SwFmtFld*)&pDstTxtFld->GetFld();
2715 SwField * pDstFld = pDstFmtFld->GetFld();
2716 USHORT nFldWhich = rSrcFld.GetTyp()->Which();
2717 SwNodeIndex aTblNdIdx(pDstTxtFld->GetTxtNode());
2719 if (pDstFld->GetTyp()->Which() ==
2720 rSrcFld.GetTyp()->Which())
2722 if (DoesUndo())
2724 SwPosition aPosition( pDstTxtFld->GetTxtNode() );
2725 aPosition.nContent = *pDstTxtFld->GetStart();
2727 AppendUndo(new SwUndoFieldFromDoc(aPosition, *pDstFld, rSrcFld,
2728 pMsgHnt, bUpdateFlds));
2731 // Das gefundene Feld wird angepasst ...
2732 //pDstFld->ChangeFormat( rSrcFld.GetFormat() );
2733 //pDstFld->SetLanguage( rSrcFld.GetLanguage() );
2735 SwField * pNewFld = rSrcFld.Copy();
2736 pDstFmtFld->SetFld(pNewFld);
2738 switch( nFldWhich )
2740 case RES_SETEXPFLD:
2741 case RES_GETEXPFLD:
2742 case RES_HIDDENTXTFLD:
2743 case RES_HIDDENPARAFLD:
2744 UpdateExpFlds( pDstTxtFld, true );
2745 break;
2747 case RES_TABLEFLD:
2749 const SwTableNode* pTblNd =
2750 IsIdxInTbl(aTblNdIdx);
2751 if( pTblNd )
2753 SwTableFmlUpdate aTblUpdate( &pTblNd->
2754 GetTable() );
2755 if (bUpdateFlds)
2756 UpdateTblFlds( &aTblUpdate );
2757 else
2758 pNewFld->GetTyp()->Modify(0, &aTblUpdate);
2760 if (! bUpdateFlds)
2761 bTblSelBreak = TRUE;
2764 break;
2766 case RES_MACROFLD:
2767 if( bUpdateFlds && pDstTxtFld->GetpTxtNode() )
2768 (pDstTxtFld->GetpTxtNode())->
2769 Modify( 0, pDstFmtFld );
2770 break;
2772 case RES_DBNAMEFLD:
2773 case RES_DBNEXTSETFLD:
2774 case RES_DBNUMSETFLD:
2775 case RES_DBSETNUMBERFLD:
2776 ChgDBData(((SwDBNameInfField*) pNewFld)->GetRealDBData());
2777 pNewFld->GetTyp()->UpdateFlds();
2779 break;
2781 case RES_DBFLD:
2783 // JP 10.02.96: ChgValue aufrufen, damit
2784 //die Format- aenderung den ContentString
2785 //richtig setzt
2786 SwDBField* pDBFld = (SwDBField*)pNewFld;
2787 if (pDBFld->IsInitialized())
2788 pDBFld->ChgValue( pDBFld->GetValue(), TRUE );
2790 pDBFld->ClearInitialized();
2791 pDBFld->InitContent();
2793 // kein break;
2795 default:
2796 pDstFmtFld->Modify( 0, pMsgHnt );
2799 // Die Felder die wir berechnen koennen werden hier expli.
2800 // zum Update angestossen.
2801 if( nFldWhich == RES_USERFLD )
2802 UpdateUsrFlds();
2805 return bTblSelBreak;
2808 bool SwDoc::PutValueToField(const SwPosition & rPos,
2809 const Any& rVal, USHORT nWhich)
2811 Any aOldVal;
2812 SwField * pField = GetField(rPos);
2815 if (DoesUndo() && pField->QueryValue(aOldVal, nWhich))
2816 AppendUndo(new SwUndoFieldFromAPI(rPos, aOldVal, rVal, nWhich));
2818 return pField->PutValue(rVal, nWhich);