xref: /aoo41x/main/sw/source/core/doc/docfld.cxx (revision c0286415)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 #include <hintids.hxx>
29 
30 #include <string.h>
31 #include <float.h>
32 #include <tools/datetime.hxx>
33 #ifndef _SVSTDARR_HXX
34 #define _SVSTDARR_ULONGS
35 #include <svl/svarray.hxx>
36 #endif
37 #include <vcl/svapp.hxx>
38 #include <vcl/svapp.hxx>
39 #include <unotools/charclass.hxx>
40 #include <unotools/transliterationwrapper.hxx>
41 #include <doc.hxx>
42 #include <IDocumentUndoRedo.hxx>
43 #include <cntfrm.hxx>
44 #include <pam.hxx>
45 #include <ndtxt.hxx>
46 #include <swtable.hxx>
47 #include <calc.hxx>
48 #include <txtfld.hxx>
49 #include <fmtfld.hxx>
50 #include <tox.hxx>
51 #include <txttxmrk.hxx>
52 #include <docfld.hxx>   // fuer Expression-Felder
53 #include <docufld.hxx>
54 #include <ddefld.hxx>
55 #include <usrfld.hxx>
56 #include <expfld.hxx>
57 #include <dbfld.hxx>
58 #include <flddat.hxx>
59 #include <chpfld.hxx>
60 #include <reffld.hxx>
61 #include <flddropdown.hxx>
62 #include <dbmgr.hxx>
63 #include <section.hxx>
64 #include <cellatr.hxx>
65 #include <docary.hxx>
66 #include <authfld.hxx>
67 #include <txtinet.hxx>
68 #include <fmtcntnt.hxx>
69 #include <poolfmt.hrc>      // fuer InitFldTypes
70 
71 #include <SwUndoField.hxx>
72 #include "switerator.hxx"
73 
74 using namespace ::com::sun::star::uno;
75 
76 extern sal_Bool IsFrameBehind( const SwTxtNode& rMyNd, sal_uInt16 nMySttPos,
77 						const SwTxtNode& rBehindNd, sal_uInt16 nSttPos );
78 
79 SV_IMPL_OP_PTRARR_SORT( _SetGetExpFlds, _SetGetExpFldPtr )
80 
81 
82 /*--------------------------------------------------------------------
83 	Beschreibung: Feldtypen einfuegen
84  --------------------------------------------------------------------*/
85 /*
86  *	Implementierung der Feldfunktionen am Doc
87  *	Return immer einen gueltigen Pointer auf den Typ. Wenn er also neu
88  *	zugefuegt oder schon vorhanden ist.
89  */
90 
91 SwFieldType* SwDoc::InsertFldType(const SwFieldType &rFldTyp)
92 {
93 	sal_uInt16 nSize = pFldTypes->Count(),
94 			nFldWhich = rFldTyp.Which();
95 
96 	sal_uInt16 i = INIT_FLDTYPES;
97 
98 	switch( nFldWhich )
99 	{
100 	case RES_SETEXPFLD:
101 			//JP 29.01.96: SequenceFelder beginnen aber bei INIT_FLDTYPES - 3!!
102 			//			   Sonst gibt es doppelte Nummernkreise!!
103 			//MIB 14.03.95: Ab sofort verlaesst sich auch der SW3-Reader
104 			//beim Aufbau der String-Pools und beim Einlesen von SetExp-Feldern
105 			//hierauf
106 			if( nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType&)rFldTyp).GetType() )
107 				i -= INIT_SEQ_FLDTYPES;
108 		// kein break;
109 	case RES_DBFLD:
110 	case RES_USERFLD:
111 	case RES_DDEFLD:
112 		{
113 			const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
114 			String sFldNm( rFldTyp.GetName() );
115 			for( ; i < nSize; ++i )
116 				if( nFldWhich == (*pFldTypes)[i]->Which() &&
117 					rSCmp.isEqual( sFldNm, (*pFldTypes)[i]->GetName() ))
118 						return (*pFldTypes)[i];
119 		}
120 		break;
121 
122 	case RES_AUTHORITY:
123 		for( ; i < nSize; ++i )
124 			if( nFldWhich == (*pFldTypes)[i]->Which() )
125 				return (*pFldTypes)[i];
126 		break;
127 
128 	default:
129 		for( i = 0; i < nSize; ++i )
130 			if( nFldWhich == (*pFldTypes)[i]->Which() )
131 				return (*pFldTypes)[i];
132 	}
133 
134 	SwFieldType* pNew = rFldTyp.Copy();
135 	switch( nFldWhich )
136 	{
137 	case RES_DDEFLD:
138 		((SwDDEFieldType*)pNew)->SetDoc( this );
139 		break;
140 
141 	case RES_DBFLD:
142 	case RES_TABLEFLD:
143 	case RES_DATETIMEFLD:
144 	case RES_GETEXPFLD:
145 		((SwValueFieldType*)pNew)->SetDoc( this );
146 		break;
147 
148 	case RES_USERFLD:
149 	case RES_SETEXPFLD:
150 		((SwValueFieldType*)pNew)->SetDoc( this );
151 		// JP 29.07.96: opt. FeldListe fuer den Calculator vorbereiten:
152 		pUpdtFlds->InsertFldType( *pNew );
153 		break;
154 	case RES_AUTHORITY :
155 		((SwAuthorityFieldType*)pNew)->SetDoc( this );
156 		break;
157 	}
158 
159 	pFldTypes->Insert( pNew, nSize );
160 	SetModified();
161 
162 	return (*pFldTypes)[ nSize ];
163 }
164 
165 void SwDoc::InsDeletedFldType( SwFieldType& rFldTyp )
166 {
167 	// der FeldTyp wurde als geloescht gekennzeichnet und aus dem
168 	// Array entfernt. Nun muss man nach diesem wieder suchen.
169 	// - Ist der nicht vorhanden, dann kann er eingefuegt werden.
170 	// - Wird genau der gleiche Typ gefunden, dann muss der geloeschte
171 	//	 einen anderen Namen erhalten.
172 
173 	sal_uInt16 nSize = pFldTypes->Count(), nFldWhich = rFldTyp.Which();
174 	sal_uInt16 i = INIT_FLDTYPES;
175 
176 	ASSERT( RES_SETEXPFLD == nFldWhich ||
177 			RES_USERFLD == nFldWhich ||
178 			RES_DDEFLD == nFldWhich, "Falscher FeldTyp" );
179 
180 	const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
181 	const String& rFldNm = rFldTyp.GetName();
182 	SwFieldType* pFnd;
183 
184 	for( ; i < nSize; ++i )
185 		if( nFldWhich == (pFnd = (*pFldTypes)[i])->Which() &&
186 			rSCmp.isEqual( rFldNm, pFnd->GetName() ) )
187 		{
188 			// neuen Namen suchen
189 			sal_uInt16 nNum = 1;
190 			do {
191 				String sSrch( rFldNm );
192 				sSrch.Append( String::CreateFromInt32( nNum ));
193 				for( i = INIT_FLDTYPES; i < nSize; ++i )
194 					if( nFldWhich == (pFnd = (*pFldTypes)[i])->Which() &&
195 						rSCmp.isEqual( sSrch, pFnd->GetName() ) )
196 						break;
197 
198 				if( i >= nSize )		// nicht gefunden
199 				{
200 					((String&)rFldNm) = sSrch;
201 					break;		// raus aus der While-Schleife
202 				}
203 				++nNum;
204 			} while( sal_True );
205 			break;
206 		}
207 
208 	// nicht gefunden, also eintragen und Flag loeschen
209 	pFldTypes->Insert( &rFldTyp, nSize );
210 	switch( nFldWhich )
211 	{
212 	case RES_SETEXPFLD:
213 		((SwSetExpFieldType&)rFldTyp).SetDeleted( sal_False );
214 		break;
215 	case RES_USERFLD:
216 		((SwUserFieldType&)rFldTyp).SetDeleted( sal_False );
217 		break;
218 	case RES_DDEFLD:
219 		((SwDDEFieldType&)rFldTyp).SetDeleted( sal_False );
220 		break;
221 	}
222 }
223 
224 /*--------------------------------------------------------------------
225 	Beschreibung: Feldtypen loeschen
226  --------------------------------------------------------------------*/
227 
228 void SwDoc::RemoveFldType(sal_uInt16 nFld)
229 {
230 	ASSERT( INIT_FLDTYPES <= nFld,	"keine InitFields loeschen" );
231 	/*
232 	 * Abheangige Felder vorhanden -> ErrRaise
233 	 */
234 	sal_uInt16 nSize = pFldTypes->Count();
235 	if(nFld < nSize)
236 	{
237 		SwFieldType* pTmp = (*pFldTypes)[nFld];
238 
239 		// JP 29.07.96: opt. FeldListe fuer den Calculator vorbereiten:
240 		sal_uInt16 nWhich = pTmp->Which();
241 		switch( nWhich )
242 		{
243 		case RES_SETEXPFLD:
244 		case RES_USERFLD:
245 			pUpdtFlds->RemoveFldType( *pTmp );
246 			// kein break;
247 		case RES_DDEFLD:
248 			if( pTmp->GetDepends() && !IsUsed( *pTmp ) )
249 			{
250 				if( RES_SETEXPFLD == nWhich )
251 					((SwSetExpFieldType*)pTmp)->SetDeleted( sal_True );
252 				else if( RES_USERFLD == nWhich )
253 					((SwUserFieldType*)pTmp)->SetDeleted( sal_True );
254 				else
255 					((SwDDEFieldType*)pTmp)->SetDeleted( sal_True );
256 				nWhich = 0;
257 			}
258 			break;
259 		}
260 
261 		if( nWhich )
262 		{
263 			ASSERT( !pTmp->GetDepends(), "Abhaengige vorh.!" );
264 			// Feldtype loschen
265 			delete pTmp;
266 		}
267 		pFldTypes->Remove( nFld );
268 		SetModified();
269 	}
270 }
271 
272 const SwFldTypes* SwDoc::GetFldTypes() const
273 {
274     return pFldTypes;
275 }
276 
277 /*--------------------------------------------------------------------
278 	Beschreibung: Den ersten Typen mit ResId und Namen finden
279  --------------------------------------------------------------------*/
280 
281 SwFieldType* SwDoc::GetFldType( sal_uInt16 nResId, const String& rName,
282 		 bool bDbFieldMatching // used in some UNO calls for RES_DBFLD
283 								   // to use different string matching code
284 								   // #i51815#
285 		 ) const
286 {
287 	sal_uInt16 nSize = pFldTypes->Count(), i = 0;
288 	const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
289 
290 	switch( nResId )
291 	{
292 	case RES_SETEXPFLD:
293 			//JP 29.01.96: SequenceFelder beginnen aber bei INIT_FLDTYPES - 3!!
294 			//			   Sonst gibt es doppelte Nummernkreise!!
295 			//MIB 14.03.95: Ab sofort verlaesst sich auch der SW3-Reader
296 			//beim Aufbau der String-Pools und beim Einlesen von SetExp-Feldern
297 			//hierauf
298 		i = INIT_FLDTYPES - INIT_SEQ_FLDTYPES;
299 		break;
300 
301 	case RES_DBFLD:
302 	case RES_USERFLD:
303 	case RES_DDEFLD:
304 	case RES_AUTHORITY:
305 		i = INIT_FLDTYPES;
306 		break;
307 	}
308 
309 	SwFieldType* pRet = 0;
310 	for( ; i < nSize; ++i )
311 	{
312 		SwFieldType* pFldType = (*pFldTypes)[i];
313 
314 		String aFldName( pFldType->GetName() );
315 		if (bDbFieldMatching && nResId == RES_DBFLD)	// #i51815#
316 			aFldName.SearchAndReplaceAll(DB_DELIM, '.');
317 
318 		if( nResId == pFldType->Which() &&
319 			rSCmp.isEqual( rName, aFldName ))
320 		{
321 			pRet = pFldType;
322 			break;
323 		}
324 	}
325 	return pRet;
326 }
327 
328 
329 /*************************************************************************
330 |*				  SwDoc::UpdateFlds()
331 |*	  Beschreibung		Felder updaten
332 *************************************************************************/
333 /*
334  *	  Alle sollen neu evaluiert werden.
335  */
336 
337 void SwDoc::UpdateFlds( SfxPoolItem *pNewHt, bool bCloseDB )
338 {
339     // Modify() fuer jeden Feldtypen rufen,
340 	// abhaengige SwTxtFld werden benachrichtigt ...
341 
342 	for( sal_uInt16 i=0; i < pFldTypes->Count(); ++i)
343 	{
344 		switch( (*pFldTypes)[i]->Which() )
345 		{
346 			// Tabellen-Felder als vorletztes Updaten
347 			// Referenzen als letztes Updaten
348 		case RES_GETREFFLD:
349 		case RES_TABLEFLD:
350 		case RES_DBFLD:
351 		case RES_JUMPEDITFLD:
352 		case RES_REFPAGESETFLD: 	// werden nie expandiert!
353 			break;
354 
355 		case RES_DDEFLD:
356 		{
357 			if( !pNewHt )
358 			{
359 				SwMsgPoolItem aUpdateDDE( RES_UPDATEDDETBL );
360 				(*pFldTypes)[i]->ModifyNotification( 0, &aUpdateDDE );
361 			}
362 			else
363 				(*pFldTypes)[i]->ModifyNotification( 0, pNewHt );
364 			break;
365 		}
366 		case RES_GETEXPFLD:
367 		case RES_SETEXPFLD:
368 		case RES_HIDDENTXTFLD:
369 		case RES_HIDDENPARAFLD:
370 			// Expression-Felder werden gesondert behandelt
371 			if( !pNewHt )
372 				break;
373 		default:
374 			(*pFldTypes)[i]->ModifyNotification ( 0, pNewHt );
375 		}
376 	}
377 
378 	if( !IsExpFldsLocked() )
379 		UpdateExpFlds( 0, sal_False );		// Expression-Felder Updaten
380 
381 	// Tabellen
382 	UpdateTblFlds(pNewHt);
383 
384 	// Referenzen
385 	UpdateRefFlds(pNewHt);
386 
387 	if( bCloseDB )
388 		GetNewDBMgr()->CloseAll();
389 
390 	// Nur bei KomplettUpdate evaluieren
391 	SetModified();
392 }
393 
394 /******************************************************************************
395  *						void SwDoc::UpdateUsrFlds()
396  ******************************************************************************/
397 
398 void SwDoc::UpdateUsrFlds()
399 {
400 	SwCalc* pCalc = 0;
401 	const SwFieldType* pFldType;
402 	for( sal_uInt16 i = INIT_FLDTYPES; i < pFldTypes->Count(); ++i )
403 		if( RES_USERFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
404 		{
405 			if( !pCalc )
406 				pCalc = new SwCalc( *this );
407 			((SwUserFieldType*)pFldType)->GetValue( *pCalc );
408 		}
409 
410 	if( pCalc )
411 	{
412 		delete pCalc;
413 		SetModified();
414 	}
415 }
416 
417 /*--------------------------------------------------------------------
418 	Beschreibung: Referenzfelder und TableFelder erneuern
419  --------------------------------------------------------------------*/
420 
421 void SwDoc::UpdateRefFlds( SfxPoolItem* pHt )
422 {
423 	SwFieldType* pFldType;
424 	for( sal_uInt16 i = 0; i < pFldTypes->Count(); ++i )
425 		if( RES_GETREFFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
426 			pFldType->ModifyNotification( 0, pHt );
427 }
428 
429 void SwDoc::UpdateTblFlds( SfxPoolItem* pHt )
430 {
431 	ASSERT( !pHt || RES_TABLEFML_UPDATE  == pHt->Which(),
432 			"Was ist das fuer ein MessageItem?" );
433 
434 	SwFieldType* pFldType(0);
435 
436 	for (sal_uInt16 i = 0; i < pFldTypes->Count(); ++i)
437 	{
438 		if( RES_TABLEFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
439 		{
440 			SwTableFmlUpdate* pUpdtFld = 0;
441 			if( pHt && RES_TABLEFML_UPDATE == pHt->Which() )
442 				pUpdtFld = (SwTableFmlUpdate*)pHt;
443 
444 			SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
445 			for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
446             {
447 				if( pFmtFld->GetTxtFld() )
448 				{
449 					SwTblField* pFld = (SwTblField*)pFmtFld->GetField();
450 
451 					if( pUpdtFld )
452 					{
453 						// bestimme Tabelle, in der das Feld steht
454 						const SwTableNode* pTblNd;
455 						const SwTxtNode& rTxtNd = pFmtFld->GetTxtFld()->GetTxtNode();
456 						if( !rTxtNd.GetNodes().IsDocNodes() ||
457 							0 == ( pTblNd = rTxtNd.FindTableNode() ) )
458 							continue;
459 
460 						switch( pUpdtFld->eFlags )
461 						{
462 						case TBL_CALC:
463 							// setze das Value-Flag zurueck
464 							// JP 17.06.96: interne Darstellung auf alle Formeln
465 							//				(Referenzen auf andere Tabellen!!!)
466 							if( nsSwExtendedSubType::SUB_CMD & pFld->GetSubType() )
467 								pFld->PtrToBoxNm( pUpdtFld->pTbl );
468 							else
469 								pFld->ChgValid( sal_False );
470 							break;
471 						case TBL_BOXNAME:
472 							// ist es die gesuchte Tabelle ??
473 							if( &pTblNd->GetTable() == pUpdtFld->pTbl )
474 								// zur externen Darstellung
475 								pFld->PtrToBoxNm( pUpdtFld->pTbl );
476 							break;
477 						case TBL_BOXPTR:
478 							// zur internen Darstellung
479 							// JP 17.06.96: interne Darstellung auf alle Formeln
480 							//				(Referenzen auf andere Tabellen!!!)
481 							pFld->BoxNmToPtr( pUpdtFld->pTbl );
482 							break;
483 						case TBL_RELBOXNAME:
484 							// ist es die gesuchte Tabelle ??
485 							if( &pTblNd->GetTable() == pUpdtFld->pTbl )
486 								// zur relativen Darstellung
487 								pFld->ToRelBoxNm( pUpdtFld->pTbl );
488 							break;
489 						default:
490 							break;
491 						}
492 					}
493 					else
494 						// setze bei allen das Value-Flag zurueck
495 						pFld->ChgValid( sal_False );
496 				}
497             }
498 
499 			break;
500 		}
501 		pFldType = 0;
502 	}
503 
504 	// und dann noch alle Tabellen Box Formeln abklappern
505 	const SfxPoolItem* pItem;
506 	sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_BOXATR_FORMULA );
507     for (sal_uInt32 i = 0; i < nMaxItems; ++i)
508     {
509 		if( 0 != (pItem = GetAttrPool().GetItem2( RES_BOXATR_FORMULA, i ) ) &&
510 			((SwTblBoxFormula*)pItem)->GetDefinedIn() )
511 		{
512 			((SwTblBoxFormula*)pItem)->ChangeState( pHt );
513 		}
514     }
515 
516 
517 	// alle Felder/Boxen sind jetzt invalide, also kann das Rechnen anfangen
518 	if( pHt && ( RES_TABLEFML_UPDATE != pHt->Which() ||
519 				TBL_CALC != ((SwTableFmlUpdate*)pHt)->eFlags ))
520 		return ;
521 
522 	SwCalc* pCalc = 0;
523 
524 	if( pFldType )
525 	{
526 		SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
527 		for( SwFmtFld* pFmtFld = aIter.Last(); pFmtFld; pFmtFld = aIter.Previous() )
528         {
529                 // start calculation at the end
530                 // new fields are inserted at the beginning of the modify chain
531                 // that gives faster calculation on import
532                 // mba: do we really need this "optimization"? Is it still valid?
533 				SwTblField* pFld;
534 				if( !pFmtFld->GetTxtFld() || (nsSwExtendedSubType::SUB_CMD &
535 					(pFld = (SwTblField*)pFmtFld->GetField())->GetSubType() ))
536 					continue;
537 
538 				// muss neu berechnet werden (und ist keine textuelle Anzeige)
539 				if( !pFld->IsValid() )
540 				{
541 					// bestimme Tabelle, in der das Feld steht
542 					const SwTxtNode& rTxtNd = pFmtFld->GetTxtFld()->GetTxtNode();
543 					if( !rTxtNd.GetNodes().IsDocNodes() )
544 						continue;
545 					const SwTableNode* pTblNd = rTxtNd.FindTableNode();
546 					if( !pTblNd )
547 						continue;
548 
549 					// falls dieses Feld nicht in der zu updatenden
550 					// Tabelle steht, ueberspringen !!
551 					if( pHt && &pTblNd->GetTable() !=
552 											((SwTableFmlUpdate*)pHt)->pTbl )
553 						continue;
554 
555 					if( !pCalc )
556 						pCalc = new SwCalc( *this );
557 
558 					// bestimme die Werte aller SetExpresion Felder, die
559 					// bis zur Tabelle gueltig sind
560 					SwFrm* pFrm = 0;
561 					if( pTblNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
562 					{
563 						// steht im Sonderbereich, wird teuer !!
564 						Point aPt;		// den im Layout 1. Frame returnen - Tab.Kopfzeile !!
565 						pFrm = rTxtNd.getLayoutFrm( GetCurrentLayout(), &aPt );
566 						if( pFrm )
567 						{
568 							SwPosition aPos( *pTblNd );
569 							if( GetBodyTxtNode( *this, aPos, *pFrm ) )
570 								FldsToCalc( *pCalc, _SetGetExpFld(
571 									aPos.nNode, pFmtFld->GetTxtFld(),
572 									&aPos.nContent ));
573 							else
574 								pFrm = 0;
575 						}
576 					}
577 					if( !pFrm )
578 					{
579 						// einen Index fuers bestimmen vom TextNode anlegen
580 						SwNodeIndex aIdx( rTxtNd );
581 						FldsToCalc( *pCalc,
582 							_SetGetExpFld( aIdx, pFmtFld->GetTxtFld() ));
583 					}
584 
585 					SwTblCalcPara aPara( *pCalc, pTblNd->GetTable() );
586 					pFld->CalcField( aPara );
587 					if( aPara.IsStackOverFlow() )
588 					{
589 						if( aPara.CalcWithStackOverflow() )
590 							pFld->CalcField( aPara );
591 #ifdef DBG_UTIL
592 						else
593 						{
594 							// mind. ein ASSERT
595 							ASSERT( !this, "die Kettenformel konnte nicht errechnet werden" );
596 						}
597 #endif
598 					}
599 					pCalc->SetCalcError( CALC_NOERR );
600 				}
601 				pFmtFld->ModifyNotification( 0, pHt );
602         }
603 	}
604 
605 	// dann berechene noch die Formeln an den Boxen
606     for (sal_uInt32 i = 0; i < nMaxItems; ++i )
607     {
608 		if( 0 != (pItem = GetAttrPool().GetItem2( RES_BOXATR_FORMULA, i ) ) &&
609 			((SwTblBoxFormula*)pItem)->GetDefinedIn() &&
610 			!((SwTblBoxFormula*)pItem)->IsValid() )
611 		{
612 			SwTblBoxFormula* pFml = (SwTblBoxFormula*)pItem;
613 			SwTableBox* pBox = pFml->GetTableBox();
614 			if( pBox && pBox->GetSttNd() &&
615 				pBox->GetSttNd()->GetNodes().IsDocNodes() )
616 			{
617 				const SwTableNode* pTblNd = pBox->GetSttNd()->FindTableNode();
618 				if( !pHt || &pTblNd->GetTable() ==
619 											((SwTableFmlUpdate*)pHt)->pTbl )
620 				{
621 					double nValue;
622 					if( !pCalc )
623 						pCalc = new SwCalc( *this );
624 
625 					// bestimme die Werte aller SetExpresion Felder, die
626 					// bis zur Tabelle gueltig sind
627 					SwFrm* pFrm = 0;
628 					if( pTblNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
629 					{
630 						// steht im Sonderbereich, wird teuer !!
631 						Point aPt;		// den im Layout 1. Frame returnen - Tab.Kopfzeile !!
632 						SwNodeIndex aCNdIdx( *pTblNd, +2 );
633 						SwCntntNode* pCNd = aCNdIdx.GetNode().GetCntntNode();
634 						if( !pCNd )
635 							pCNd = GetNodes().GoNext( &aCNdIdx );
636 
637 						if( pCNd && 0 != (pFrm = pCNd->getLayoutFrm( GetCurrentLayout(), &aPt )) )
638 						{
639 							SwPosition aPos( *pCNd );
640 							if( GetBodyTxtNode( *this, aPos, *pFrm ) )
641 								FldsToCalc( *pCalc, _SetGetExpFld( aPos.nNode ));
642 							else
643 								pFrm = 0;
644 						}
645 					}
646 					if( !pFrm )
647 					{
648 						// einen Index fuers bestimmen vom TextNode anlegen
649 						SwNodeIndex aIdx( *pTblNd );
650 						FldsToCalc( *pCalc, _SetGetExpFld( aIdx ));
651 					}
652 
653 					SwTblCalcPara aPara( *pCalc, pTblNd->GetTable() );
654 					pFml->Calc( aPara, nValue );
655 
656 					if( aPara.IsStackOverFlow() )
657 					{
658 						if( aPara.CalcWithStackOverflow() )
659 							pFml->Calc( aPara, nValue );
660 #ifdef DBG_UTIL
661 						else
662 						{
663 							// mind. ein ASSERT
664 							ASSERT( !this, "die Kettenformel konnte nicht errechnet werden" );
665 						}
666 #endif
667 					}
668 
669 					SwFrmFmt* pFmt = pBox->ClaimFrmFmt();
670 					SfxItemSet aTmp( GetAttrPool(),
671 									RES_BOXATR_BEGIN,RES_BOXATR_END-1 );
672 
673 					if( pCalc->IsCalcError() )
674 						nValue = DBL_MAX;
675 					aTmp.Put( SwTblBoxValue( nValue ));
676 					if( SFX_ITEM_SET != pFmt->GetItemState( RES_BOXATR_FORMAT ))
677 						aTmp.Put( SwTblBoxNumFormat( 0 ));
678                     pFmt->SetFmtAttr( aTmp );
679 
680 					pCalc->SetCalcError( CALC_NOERR );
681 				}
682 			}
683 		}
684     }
685 
686 	if( pCalc )
687 		delete pCalc;
688 }
689 
690 void SwDoc::UpdatePageFlds( SfxPoolItem* pMsgHnt )
691 {
692 	SwFieldType* pFldType;
693 	for( sal_uInt16 i = 0; i < INIT_FLDTYPES; ++i )
694 		switch( ( pFldType = (*pFldTypes)[ i ] )->Which() )
695 		{
696 		case RES_PAGENUMBERFLD:
697 		case RES_CHAPTERFLD:
698 		case RES_GETEXPFLD:
699 		case RES_REFPAGEGETFLD:
700 			pFldType->ModifyNotification( 0, pMsgHnt );
701 			break;
702 		case RES_DOCSTATFLD:
703 			pFldType->ModifyNotification( 0, 0 );
704 			break;
705 		}
706 	SetNewFldLst(true);
707 }
708 
709 /*--------------------------------------------------------------------
710 	Beschreibung:
711  --------------------------------------------------------------------*/
712 
713 // ---- Loesche alle nicht referenzierten FeldTypen eines Dokumentes --
714 void SwDoc::GCFieldTypes()
715 {
716 	for( sal_uInt16 n = pFldTypes->Count(); n > INIT_FLDTYPES; )
717 		if( !(*pFldTypes)[ --n ]->GetDepends() )
718 			RemoveFldType( n );
719 }
720 
721 void SwDoc::LockExpFlds()
722 {
723     ++nLockExpFld;
724 }
725 
726 void SwDoc::UnlockExpFlds()
727 {
728     if( nLockExpFld )
729         --nLockExpFld;
730 }
731 
732 bool SwDoc::IsExpFldsLocked() const
733 {
734     return 0 != nLockExpFld;
735 }
736 
737 SwDocUpdtFld& SwDoc::GetUpdtFlds() const
738 {
739     return *pUpdtFlds;
740 }
741 
742 bool SwDoc::IsNewFldLst() const
743 {
744     return mbNewFldLst;
745 }
746 
747 void SwDoc::SetNewFldLst(bool bFlag)
748 {
749     mbNewFldLst = bFlag;
750 }
751 
752 
753 //----------------------------------------------------------------------
754 
755 // der StartIndex kann optional mit angegeben werden (z.B. wenn dieser
756 // zuvor schon mal erfragt wurde - ist sonst eine virtuelle Methode !!)
757 
758 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx, const SwTxtFld* pFld,
759 							const SwIndex* pIdx )
760 {
761 	eSetGetExpFldType = TEXTFIELD;
762 	CNTNT.pTxtFld = pFld;
763 	nNode = rNdIdx.GetIndex();
764 	if( pIdx )
765 		nCntnt = pIdx->GetIndex();
766 	else if( pFld )
767 		nCntnt = *pFld->GetStart();
768 	else
769 		nCntnt = 0;
770 }
771 
772 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx,
773 							const SwTxtINetFmt& rINet, const SwIndex* pIdx )
774 {
775 	eSetGetExpFldType = TEXTINET;
776 	CNTNT.pTxtINet = &rINet;
777 	nNode = rNdIdx.GetIndex();
778 	if( pIdx )
779 		nCntnt = pIdx->GetIndex();
780 	else
781 		nCntnt = *rINet.GetStart();
782 }
783 
784 	//Erweiterung fuer Sections:
785 	//	diese haben immer als Content-Position 0xffff !!
786 	//	Auf dieser steht nie ein Feld, maximal bis STRING_MAXLEN moeglich
787 _SetGetExpFld::_SetGetExpFld( const SwSectionNode& rSectNd,
788 								const SwPosition* pPos )
789 {
790 	eSetGetExpFldType = SECTIONNODE;
791 	CNTNT.pSection = &rSectNd.GetSection();
792 
793 	if( pPos )
794 	{
795 		nNode = pPos->nNode.GetIndex();
796 		nCntnt = pPos->nContent.GetIndex();
797 	}
798 	else
799 	{
800 		nNode = rSectNd.GetIndex();
801 		nCntnt = 0;
802 	}
803 }
804 
805 _SetGetExpFld::_SetGetExpFld( const SwTableBox& rTBox, const SwPosition* pPos )
806 {
807 	eSetGetExpFldType = TABLEBOX;
808 	CNTNT.pTBox = &rTBox;
809 
810 	if( pPos )
811 	{
812 		nNode = pPos->nNode.GetIndex();
813 		nCntnt = pPos->nContent.GetIndex();
814 	}
815 	else
816 	{
817 		nNode = 0;
818 		nCntnt = 0;
819 		if( rTBox.GetSttNd() )
820 		{
821 			SwNodeIndex aIdx( *rTBox.GetSttNd() );
822 			const SwCntntNode* pNd = aIdx.GetNode().GetNodes().GoNext( &aIdx );
823 			if( pNd )
824 				nNode = pNd->GetIndex();
825 		}
826 	}
827 }
828 
829 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx,
830 								const SwTxtTOXMark& rTOX,
831 								const SwIndex* pIdx )
832 {
833 	eSetGetExpFldType = TEXTTOXMARK;
834 	CNTNT.pTxtTOX = &rTOX;
835 	nNode = rNdIdx.GetIndex();
836 	if( pIdx )
837 		nCntnt = pIdx->GetIndex();
838 	else
839 		nCntnt = *rTOX.GetStart();
840 }
841 
842 _SetGetExpFld::_SetGetExpFld( const SwPosition& rPos )
843 {
844 	eSetGetExpFldType = CRSRPOS;
845 	CNTNT.pPos = &rPos;
846 	nNode = rPos.nNode.GetIndex();
847 	nCntnt = rPos.nContent.GetIndex();
848 }
849 
850 _SetGetExpFld::_SetGetExpFld( const SwFlyFrmFmt& rFlyFmt,
851 								const SwPosition* pPos  )
852 {
853 	eSetGetExpFldType = FLYFRAME;
854 	CNTNT.pFlyFmt = &rFlyFmt;
855 	if( pPos )
856 	{
857 		nNode = pPos->nNode.GetIndex();
858 		nCntnt = pPos->nContent.GetIndex();
859 	}
860 	else
861 	{
862 		const SwFmtCntnt& rCntnt = rFlyFmt.GetCntnt();
863 		nNode = rCntnt.GetCntntIdx()->GetIndex() + 1;
864 		nCntnt = 0;
865 	}
866 }
867 
868 void _SetGetExpFld::GetPos( SwPosition& rPos ) const
869 {
870 	rPos.nNode = nNode;
871 	rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt );
872 }
873 
874 void _SetGetExpFld::GetPosOfContent( SwPosition& rPos ) const
875 {
876 	const SwNode* pNd = GetNodeFromCntnt();
877 	if( pNd )
878 		pNd = pNd->GetCntntNode();
879 
880 	if( pNd )
881 	{
882 		rPos.nNode = *pNd;
883 		rPos.nContent.Assign( (SwCntntNode*)pNd,GetCntPosFromCntnt() );
884 	}
885 	else
886 	{
887 		rPos.nNode = nNode;
888 		rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt );
889 	}
890 }
891 
892 void _SetGetExpFld::SetBodyPos( const SwCntntFrm& rFrm )
893 {
894 	if( !rFrm.IsInDocBody() )
895 	{
896 		SwNodeIndex aIdx( *rFrm.GetNode() );
897 		SwDoc& rDoc = *aIdx.GetNodes().GetDoc();
898 		SwPosition aPos( aIdx );
899 #ifdef DBG_UTIL
900 		ASSERT( ::GetBodyTxtNode( rDoc, aPos, rFrm ), "wo steht das Feld" );
901 #else
902 		::GetBodyTxtNode( rDoc, aPos, rFrm );
903 #endif
904 		nNode = aPos.nNode.GetIndex();
905 		nCntnt = aPos.nContent.GetIndex();
906 	}
907 }
908 
909 sal_Bool _SetGetExpFld::operator<( const _SetGetExpFld& rFld ) const
910 {
911 	if( nNode < rFld.nNode || ( nNode == rFld.nNode && nCntnt < rFld.nCntnt ))
912 		return sal_True;
913 	else if( nNode != rFld.nNode || nCntnt != rFld.nCntnt )
914 		return sal_False;
915 
916 	const SwNode *pFirst = GetNodeFromCntnt(),
917 				 *pNext = rFld.GetNodeFromCntnt();
918 
919 	// Position gleich: nur weiter wenn beide FeldPointer besetzt sind !!
920 	if( !pFirst || !pNext )
921 		return sal_False;
922 
923 	// gleiche Section ??
924 	if( pFirst->StartOfSectionNode() != pNext->StartOfSectionNode() )
925 	{
926 		// sollte einer in der Tabelle stehen ?
927 		const SwNode *pFirstStt, *pNextStt;
928 		const SwTableNode* pTblNd = pFirst->FindTableNode();
929 		if( pTblNd )
930 			pFirstStt = pTblNd->StartOfSectionNode();
931 		else
932 			pFirstStt = pFirst->StartOfSectionNode();
933 
934 		if( 0 != ( pTblNd = pNext->FindTableNode() ) )
935 			pNextStt = pTblNd->StartOfSectionNode();
936 		else
937 			pNextStt = pNext->StartOfSectionNode();
938 
939 		if( pFirstStt != pNextStt )
940 		{
941 			if( pFirst->IsTxtNode() && pNext->IsTxtNode() &&
942 				( pFirst->FindFlyStartNode() || pNext->FindFlyStartNode() ))
943 			{
944 				return ::IsFrameBehind( *(SwTxtNode*)pNext, nCntnt,
945 										*(SwTxtNode*)pFirst, nCntnt );
946 			}
947 			return pFirstStt->GetIndex() < pNextStt->GetIndex();
948 		}
949 	}
950 
951 	// ist gleiche Section, dann Feld im gleichen Node ?
952 	if( pFirst != pNext )
953 		return pFirst->GetIndex() < pNext->GetIndex();
954 
955 	// gleicher Node in der Section, dann Position im Node
956 	return GetCntPosFromCntnt() < rFld.GetCntPosFromCntnt();
957 }
958 
959 const SwNode* _SetGetExpFld::GetNodeFromCntnt() const
960 {
961 	const SwNode* pRet = 0;
962 	if( CNTNT.pTxtFld )
963 		switch( eSetGetExpFldType )
964 		{
965 		case TEXTFIELD:
966 			pRet = &CNTNT.pTxtFld->GetTxtNode();
967 			break;
968 
969 		case TEXTINET:
970 			pRet = &CNTNT.pTxtINet->GetTxtNode();
971 			break;
972 
973 		case SECTIONNODE:
974 			pRet = CNTNT.pSection->GetFmt()->GetSectionNode();
975 			break;
976 
977 		case CRSRPOS:
978 			pRet = &CNTNT.pPos->nNode.GetNode();
979 			break;
980 
981 		case TEXTTOXMARK:
982 			pRet = &CNTNT.pTxtTOX->GetTxtNode();
983 			break;
984 
985 		case TABLEBOX:
986 			if( CNTNT.pTBox->GetSttNd() )
987 			{
988 				SwNodeIndex aIdx( *CNTNT.pTBox->GetSttNd() );
989 				pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx );
990 			}
991 			break;
992 
993 		case FLYFRAME:
994 			{
995 				SwNodeIndex aIdx( *CNTNT.pFlyFmt->GetCntnt().GetCntntIdx() );
996 				pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx );
997 			}
998 			break;
999 		}
1000 	return pRet;
1001 }
1002 
1003 xub_StrLen _SetGetExpFld::GetCntPosFromCntnt() const
1004 {
1005 	sal_uInt16 nRet = 0;
1006 	if( CNTNT.pTxtFld )
1007 		switch( eSetGetExpFldType )
1008 		{
1009 		case TEXTFIELD:
1010 		case TEXTINET:
1011 		case TEXTTOXMARK:
1012 			nRet = *CNTNT.pTxtFld->GetStart();
1013 			break;
1014 		case CRSRPOS:
1015 			nRet =  CNTNT.pPos->nContent.GetIndex();
1016 			break;
1017 		default:
1018 			break;
1019 		}
1020 	return nRet;
1021 }
1022 
1023 _HashStr::_HashStr( const String& rName, const String& rText,
1024 					_HashStr* pNxt )
1025 	: SwHash( rName ), aSetStr( rText )
1026 {
1027 	pNext = pNxt;
1028 }
1029 
1030 // suche nach dem Namen, ist er vorhanden, returne seinen String, sonst
1031 // einen LeerString
1032 void LookString( SwHash** ppTbl, sal_uInt16 nSize, const String& rName,
1033 					String& rRet, sal_uInt16* pPos )
1034 {
1035 	rRet = rName;
1036 	rRet.EraseLeadingChars().EraseTrailingChars();
1037 	SwHash* pFnd = Find( rRet, ppTbl, nSize, pPos );
1038 	if( pFnd )
1039 		rRet = ((_HashStr*)pFnd)->aSetStr;
1040 	else
1041 		rRet.Erase();
1042 }
1043 
1044 /*--------------------------------------------------------------------
1045 	Beschreibung:
1046  --------------------------------------------------------------------*/
1047 
1048 String lcl_GetDBVarName( SwDoc& rDoc, SwDBNameInfField& rDBFld )
1049 {
1050 	SwDBData aDBData( rDBFld.GetDBData( &rDoc ));
1051 	String sDBNumNm;
1052 	SwDBData aDocData = rDoc.GetDBData();
1053 
1054 	if( aDBData != aDocData )
1055 	{
1056 		sDBNumNm = aDBData.sDataSource;
1057 		sDBNumNm += DB_DELIM;
1058 		sDBNumNm += String(aDBData.sCommand);
1059 		sDBNumNm += DB_DELIM;
1060 	}
1061 	sDBNumNm += SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD);
1062 
1063 	return sDBNumNm;
1064 }
1065 
1066 /*--------------------------------------------------------------------
1067 	Beschreibung:
1068  --------------------------------------------------------------------*/
1069 
1070 void lcl_CalcFld( SwDoc& rDoc, SwCalc& rCalc, const _SetGetExpFld& rSGEFld,
1071 						SwNewDBMgr* pMgr )
1072 {
1073 	const SwTxtFld* pTxtFld = rSGEFld.GetTxtFld();
1074 	if( !pTxtFld )
1075 		return ;
1076 
1077 	const SwField* pFld = pTxtFld->GetFmtFld().GetField();
1078 	const sal_uInt16 nFldWhich = pFld->GetTyp()->Which();
1079 
1080 	if( RES_SETEXPFLD == nFldWhich )
1081 	{
1082 		SwSbxValue aValue;
1083 		if( nsSwGetSetExpType::GSE_EXPR & pFld->GetSubType() )
1084 			aValue.PutDouble( ((SwSetExpField*)pFld)->GetValue() );
1085 		else
1086 			// Erweiterung fuers Rechnen mit Strings
1087 			aValue.PutString( ((SwSetExpField*)pFld)->GetExpStr() );
1088 
1089 		// setze im Calculator den neuen Wert
1090 		rCalc.VarChange( pFld->GetTyp()->GetName(), aValue );
1091 	}
1092 	else if( pMgr )
1093 	{
1094 		switch( nFldWhich )
1095 		{
1096 		case RES_DBNUMSETFLD:
1097 			{
1098 				SwDBNumSetField* pDBFld = (SwDBNumSetField*)pFld;
1099 
1100 				SwDBData aDBData(pDBFld->GetDBData(&rDoc));
1101 
1102 				if( pDBFld->IsCondValid() &&
1103 					pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand ))
1104 					rCalc.VarChange( lcl_GetDBVarName( rDoc, *pDBFld),
1105 									pDBFld->GetFormat() );
1106 			}
1107 			break;
1108 		case RES_DBNEXTSETFLD:
1109 			{
1110 				SwDBNextSetField* pDBFld = (SwDBNextSetField*)pFld;
1111 				SwDBData aDBData(pDBFld->GetDBData(&rDoc));
1112 				if( !pDBFld->IsCondValid() ||
1113 					!pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand ))
1114 					break;
1115 
1116 				String sDBNumNm(lcl_GetDBVarName( rDoc, *pDBFld));
1117 				SwCalcExp* pExp = rCalc.VarLook( sDBNumNm );
1118 				if( pExp )
1119 					rCalc.VarChange( sDBNumNm, pExp->nValue.GetLong() + 1 );
1120 			}
1121 			break;
1122 
1123 		}
1124 	}
1125 }
1126 
1127 void SwDoc::FldsToCalc( SwCalc& rCalc, const _SetGetExpFld& rToThisFld )
1128 {
1129 	// erzeuge die Sortierteliste aller SetFelder
1130 	pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC );
1131 	mbNewFldLst = sal_False;
1132 
1133 	SwNewDBMgr* pMgr = GetNewDBMgr();
1134 	pMgr->CloseAll(sal_False);
1135 
1136 	if( pUpdtFlds->GetSortLst()->Count() )
1137 	{
1138 		sal_uInt16 nLast;
1139 		_SetGetExpFld* pFld = (_SetGetExpFld*)&rToThisFld;
1140 		if( pUpdtFlds->GetSortLst()->Seek_Entry( pFld, &nLast ) )
1141 			++nLast;
1142 
1143         const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
1144 		for( sal_uInt16 n = 0; n < nLast; ++n, ++ppSortLst )
1145 			lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr );
1146 	}
1147 
1148 	pMgr->CloseAll(sal_False);
1149 }
1150 
1151 void SwDoc::FldsToCalc( SwCalc& rCalc, sal_uLong nLastNd, sal_uInt16 nLastCnt )
1152 {
1153 	// erzeuge die Sortierteliste aller SetFelder
1154 	pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC );
1155 	mbNewFldLst = sal_False;
1156 
1157 	SwNewDBMgr* pMgr = GetNewDBMgr();
1158 	pMgr->CloseAll(sal_False);
1159 
1160 	const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
1161 
1162 	for( sal_uInt16 n = pUpdtFlds->GetSortLst()->Count();
1163         n &&
1164         ( (*ppSortLst)->GetNode() < nLastNd ||
1165           ( (*ppSortLst)->GetNode() == nLastNd && (*ppSortLst)->GetCntnt() <= nLastCnt )
1166         );
1167 		--n, ++ppSortLst )
1168 		lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr );
1169 
1170 	pMgr->CloseAll(sal_False);
1171 }
1172 
1173 void SwDoc::FldsToExpand( SwHash**& ppHashTbl, sal_uInt16& rTblSize,
1174 							const _SetGetExpFld& rToThisFld )
1175 {
1176 	// erzeuge die Sortierteliste aller SetFelder
1177 	pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_EXPAND );
1178 	mbNewFldLst = sal_False;
1179 
1180 	// HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt
1181 	// (versuche eine "ungerade"-Zahl zu erzeugen)
1182 	rTblSize = (( pUpdtFlds->GetSortLst()->Count() / 7 ) + 1 ) * 7;
1183 	ppHashTbl = new SwHash*[ rTblSize ];
1184 	memset( ppHashTbl, 0, sizeof( _HashStr* ) * rTblSize );
1185 
1186 	sal_uInt16 nLast;
1187 	{
1188 		_SetGetExpFld* pTmp = (_SetGetExpFld*)&rToThisFld;
1189 		if( pUpdtFlds->GetSortLst()->Seek_Entry( pTmp, &nLast ) )
1190 			++nLast;
1191 	}
1192 
1193 	sal_uInt16 nPos;
1194 	SwHash* pFnd;
1195 	String aNew;
1196 	const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
1197 	for( ; nLast; --nLast, ++ppSortLst )
1198 	{
1199 		const SwTxtFld* pTxtFld = (*ppSortLst)->GetTxtFld();
1200 		if( !pTxtFld )
1201 			continue;
1202 
1203 		const SwField* pFld = pTxtFld->GetFmtFld().GetField();
1204 		switch( pFld->GetTyp()->Which() )
1205 		{
1206 		case RES_SETEXPFLD:
1207 			if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() )
1208 			{
1209 				// setze in der HashTabelle den neuen Wert
1210 				// ist die "Formel" ein Feld ??
1211 				SwSetExpField* pSFld = (SwSetExpField*)pFld;
1212 				LookString( ppHashTbl, rTblSize, pSFld->GetFormula(), aNew );
1213 
1214                 if( !aNew.Len() )               // nichts gefunden, dann ist
1215                     aNew = pSFld->GetFormula(); // die Formel der neue Wert
1216 
1217                 // OD 11.02.2003 #i3141# - update expression of field as in
1218                 // method <SwDoc::UpdateExpFlds(..)> for string/text fields
1219                 pSFld->ChgExpStr( aNew );
1220 
1221 				// suche den Namen vom Feld
1222 				aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName();
1223 				// Eintrag vorhanden ?
1224 				pFnd = Find( aNew, ppHashTbl, rTblSize, &nPos );
1225 				if( pFnd )
1226 					// Eintrag in der HashTabelle aendern
1227 					((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr();
1228 				else
1229 					// neuen Eintrag einfuegen
1230 					*(ppHashTbl + nPos ) = new _HashStr( aNew,
1231 							pSFld->GetExpStr(), (_HashStr*)*(ppHashTbl + nPos) );
1232 			}
1233 			break;
1234 		case RES_DBFLD:
1235 			{
1236 				const String& rName = pFld->GetTyp()->GetName();
1237 
1238 				// Eintrag in den HashTable eintragen
1239 				// Eintrag vorhanden ?
1240 				pFnd = Find( rName, ppHashTbl, rTblSize, &nPos );
1241                 String const value(pFld->ExpandField(IsClipBoard()));
1242 				if( pFnd )
1243                 {
1244 					// Eintrag in der HashTabelle aendern
1245                     static_cast<_HashStr*>(pFnd)->aSetStr = value;
1246                 }
1247                 else
1248                 {
1249 					// neuen Eintrag einfuegen
1250 					*(ppHashTbl + nPos ) = new _HashStr( rName,
1251                         value, static_cast<_HashStr *>(*(ppHashTbl + nPos)));
1252                 }
1253 			}
1254 			break;
1255 		}
1256 	}
1257 }
1258 
1259 
1260 void SwDoc::UpdateExpFlds( SwTxtFld* pUpdtFld, bool bUpdRefFlds )
1261 {
1262     if( IsExpFldsLocked() || IsInReading() )
1263 		return;
1264 
1265 	sal_Bool bOldInUpdateFlds = pUpdtFlds->IsInUpdateFlds();
1266 	pUpdtFlds->SetInUpdateFlds( sal_True );
1267 
1268 	pUpdtFlds->MakeFldList( *this, sal_True, GETFLD_ALL );
1269 	mbNewFldLst = sal_False;
1270 
1271 	if( !pUpdtFlds->GetSortLst()->Count() )
1272 	{
1273 		if( bUpdRefFlds )
1274 			UpdateRefFlds(NULL);
1275 
1276 		pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds );
1277 		pUpdtFlds->SetFieldsDirty( sal_False );
1278 		return ;
1279 	}
1280 
1281 	sal_uInt16 nWhich, n;
1282 
1283 	// HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt
1284 	// (versuche eine "ungerade"-Zahl zu erzeugen)
1285 	sal_uInt16 nStrFmtCnt = (( pFldTypes->Count() / 7 ) + 1 ) * 7;
1286 	SwHash** pHashStrTbl = new SwHash*[ nStrFmtCnt ];
1287 	memset( pHashStrTbl, 0, sizeof( _HashStr* ) * nStrFmtCnt );
1288 
1289 	{
1290 		const SwFieldType* pFldType;
1291 		// gesondert behandeln:
1292 		for( n = pFldTypes->Count(); n; )
1293 			switch( ( pFldType = (*pFldTypes)[ --n ] )->Which() )
1294 			{
1295 			case RES_USERFLD:
1296 				{
1297 					// Eintrag vorhanden ?
1298 					sal_uInt16 nPos;
1299 					const String& rNm = pFldType->GetName();
1300 					String sExpand(((SwUserFieldType*)pFldType)->Expand(nsSwGetSetExpType::GSE_STRING, 0, 0));
1301 					SwHash* pFnd = Find( rNm, pHashStrTbl, nStrFmtCnt, &nPos );
1302 					if( pFnd )
1303 						// Eintrag in der HashTabelle aendern ??
1304 						((_HashStr*)pFnd)->aSetStr = sExpand;
1305 					else
1306 						// neuen Eintrag einfuegen
1307 						*(pHashStrTbl + nPos ) = new _HashStr( rNm, sExpand,
1308 												(_HashStr*)*(pHashStrTbl + nPos) );
1309 				}
1310 				break;
1311 			case RES_SETEXPFLD:
1312 				((SwSetExpFieldType*)pFldType)->SetOutlineChgNd( 0 );
1313 				break;
1314 			}
1315 	}
1316 
1317 	// Ok, das Array ist soweit mit allen Feldern gefuellt, dann rechne mal
1318 	SwCalc aCalc( *this );
1319 
1320 	String sDBNumNm( SwFieldType::GetTypeStr( TYP_DBSETNUMBERFLD ) );
1321 
1322 	// aktuelle Datensatznummer schon vorher einstellen
1323 	SwNewDBMgr* pMgr = GetNewDBMgr();
1324 	pMgr->CloseAll(sal_False);
1325 /*
1326 	if(pMgr && pMgr->OpenDB(DBMGR_STD, GetDBDesc(), sal_False))
1327 	{
1328 		if(!pMgr->IsInMerge() )
1329 			pMgr->ToFirstSelectedRecord(DBMGR_STD);
1330 
1331 		aCalc.VarChange( sDBNumNm, pMgr->GetCurSelectedRecordId(DBMGR_STD));
1332 	}
1333 */
1334 
1335 	String aNew;
1336 	const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
1337 	for( n = pUpdtFlds->GetSortLst()->Count(); n; --n, ++ppSortLst )
1338 	{
1339 		SwSection* pSect = (SwSection*)(*ppSortLst)->GetSection();
1340 		if( pSect )
1341 		{
1342 			//!SECTION
1343 
1344             SwSbxValue aValue = aCalc.Calculate(
1345                                         pSect->GetCondition() );
1346             if(!aValue.IsVoidValue())
1347                 pSect->SetCondHidden( aValue.GetBool() );
1348             continue;
1349         }
1350 
1351         SwTxtFld* pTxtFld = (SwTxtFld*)(*ppSortLst)->GetTxtFld();
1352         if( !pTxtFld )
1353         {
1354             ASSERT( !this, "was ist es denn nun" );
1355             continue;
1356         }
1357 
1358         SwFmtFld* pFmtFld = (SwFmtFld*)&pTxtFld->GetFmtFld();
1359         const SwField* pFld = pFmtFld->GetField();
1360 
1361         switch( nWhich = pFld->GetTyp()->Which() )
1362         {
1363         case RES_HIDDENTXTFLD:
1364         {
1365             SwHiddenTxtField* pHFld = (SwHiddenTxtField*)pFld;
1366             SwSbxValue aValue = aCalc.Calculate( pHFld->GetPar1() );
1367             sal_Bool bValue = !aValue.GetBool();
1368             if(!aValue.IsVoidValue())
1369             {
1370                 pHFld->SetValue( bValue );
1371                 // Feld Evaluieren
1372                 pHFld->Evaluate(this);
1373             }
1374         }
1375         break;
1376         case RES_HIDDENPARAFLD:
1377         {
1378             SwHiddenParaField* pHPFld = (SwHiddenParaField*)pFld;
1379             SwSbxValue aValue = aCalc.Calculate( pHPFld->GetPar1() );
1380             sal_Bool bValue = aValue.GetBool();
1381             if(!aValue.IsVoidValue())
1382                 pHPFld->SetHidden( bValue );
1383 		}
1384 		break;
1385 		case RES_DBSETNUMBERFLD:
1386 		{
1387 			((SwDBSetNumberField*)pFld)->Evaluate(this);
1388 			aCalc.VarChange( sDBNumNm, ((SwDBSetNumberField*)pFld)->GetSetNumber());
1389 		}
1390 		break;
1391 		case RES_DBNEXTSETFLD:
1392 		case RES_DBNUMSETFLD:
1393 			UpdateDBNumFlds( *(SwDBNameInfField*)pFld, aCalc );
1394 		break;
1395 		case RES_DBFLD:
1396 		{
1397 			// Feld Evaluieren
1398 			((SwDBField*)pFld)->Evaluate();
1399 
1400 			SwDBData aTmpDBData(((SwDBField*)pFld)->GetDBData());
1401 
1402             if( pMgr->IsDataSourceOpen(aTmpDBData.sDataSource, aTmpDBData.sCommand, sal_False))
1403                 aCalc.VarChange( sDBNumNm, pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType));
1404 
1405 			const String& rName = pFld->GetTyp()->GetName();
1406 
1407 			// Wert fuer den Calculator setzen
1408 //JP 10.02.96: GetValue macht hier doch keinen Sinn
1409 //			((SwDBField*)pFld)->GetValue();
1410 
1411 //!OK			aCalc.VarChange(aName, ((SwDBField*)pFld)->GetValue(aCalc));
1412 
1413 			// Eintrag in den HashTable eintragen
1414 			// Eintrag vorhanden ?
1415 			sal_uInt16 nPos;
1416 			SwHash* pFnd = Find( rName, pHashStrTbl, nStrFmtCnt, &nPos );
1417             String const value(pFld->ExpandField(IsClipBoard()));
1418 			if( pFnd )
1419             {
1420 				// Eintrag in der HashTabelle aendern
1421                 static_cast<_HashStr*>(pFnd)->aSetStr = value;
1422             }
1423 			else
1424             {
1425 				// neuen Eintrag einfuegen
1426 				*(pHashStrTbl + nPos ) = new _HashStr( rName,
1427                     value, static_cast<_HashStr *>(*(pHashStrTbl + nPos)));
1428             }
1429 		}
1430 		break;
1431 		case RES_GETEXPFLD:
1432 		case RES_SETEXPFLD:
1433 		{
1434 			if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() )		// String Ersetzung
1435 			{
1436 				if( RES_GETEXPFLD == nWhich )
1437 				{
1438 					SwGetExpField* pGFld = (SwGetExpField*)pFld;
1439 
1440 					if( (!pUpdtFld || pUpdtFld == pTxtFld )
1441                         && pGFld->IsInBodyTxt() )
1442 					{
1443 						LookString( pHashStrTbl, nStrFmtCnt,
1444 									pGFld->GetFormula(), aNew );
1445 						pGFld->ChgExpStr( aNew );
1446 					}
1447 				}
1448 				else
1449 				{
1450 					SwSetExpField* pSFld = (SwSetExpField*)pFld;
1451 					// ist die "Formel" ein Feld ??
1452 					LookString( pHashStrTbl, nStrFmtCnt,
1453 								pSFld->GetFormula(), aNew );
1454 
1455 					if( !aNew.Len() )				// nichts gefunden, dann ist die
1456 						aNew = pSFld->GetFormula();		// Formel der neue Wert
1457 
1458 					// nur ein spezielles FeldUpdaten ?
1459 					if( !pUpdtFld || pUpdtFld == pTxtFld )
1460 						pSFld->ChgExpStr( aNew );
1461 
1462 					// suche den Namen vom Feld
1463 					aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName();
1464 					// Eintrag vorhanden ?
1465 					sal_uInt16 nPos;
1466 					SwHash* pFnd = Find( aNew, pHashStrTbl, nStrFmtCnt, &nPos );
1467 					if( pFnd )
1468 						// Eintrag in der HashTabelle aendern
1469 						((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr();
1470 					else
1471 						// neuen Eintrag einfuegen
1472 						*(pHashStrTbl + nPos ) = pFnd = new _HashStr( aNew,
1473 										pSFld->GetExpStr(),
1474 										(_HashStr*)*(pHashStrTbl + nPos) );
1475 
1476 					// Erweiterung fuers Rechnen mit Strings
1477 					SwSbxValue aValue;
1478 					aValue.PutString( ((_HashStr*)pFnd)->aSetStr );
1479 					aCalc.VarChange( aNew, aValue );
1480 				}
1481 			}
1482 			else			// Formel neu berechnen
1483 			{
1484 				if( RES_GETEXPFLD == nWhich )
1485 				{
1486 					SwGetExpField* pGFld = (SwGetExpField*)pFld;
1487 
1488 					if( (!pUpdtFld || pUpdtFld == pTxtFld )
1489 						&& pGFld->IsInBodyTxt() )
1490 					{
1491                         SwSbxValue aValue = aCalc.Calculate(
1492                                         pGFld->GetFormula());
1493                         if(!aValue.IsVoidValue())
1494                             pGFld->SetValue(aValue.GetDouble() );
1495 					}
1496 				}
1497 				else
1498 				{
1499 					SwSetExpField* pSFld = (SwSetExpField*)pFld;
1500 					SwSetExpFieldType* pSFldTyp = (SwSetExpFieldType*)pFld->GetTyp();
1501 					aNew = pSFldTyp->GetName();
1502 
1503 					SwNode* pSeqNd = 0;
1504 
1505 					if( pSFld->IsSequenceFld() )
1506 					{
1507                         const sal_uInt8 nLvl = pSFldTyp->GetOutlineLvl();
1508 						if( MAXLEVEL > nLvl )
1509 						{
1510 							// dann teste, ob die Nummer neu aufsetzen muss
1511 							pSeqNd = GetNodes()[ (*ppSortLst)->GetNode() ];
1512 
1513 							const SwTxtNode* pOutlNd = pSeqNd->
1514 									FindOutlineNodeOfLevel( nLvl );
1515 							if( pSFldTyp->GetOutlineChgNd() != pOutlNd )
1516 							{
1517 								pSFldTyp->SetOutlineChgNd( pOutlNd );
1518 								aCalc.VarChange( aNew, 0 );
1519 							}
1520 						}
1521 					}
1522 
1523 					aNew += '=';
1524 					aNew += pSFld->GetFormula();
1525 
1526                     SwSbxValue aValue = aCalc.Calculate( aNew );
1527                     double nErg = aValue.GetDouble();
1528                     // nur ein spezielles Feld updaten ?
1529                     if( !aValue.IsVoidValue() && (!pUpdtFld || pUpdtFld == pTxtFld) )
1530 					{
1531 						pSFld->SetValue( nErg );
1532 
1533 						if( pSeqNd )
1534 							pSFldTyp->SetChapter( *pSFld, *pSeqNd );
1535 					}
1536 				}
1537 			}
1538 		}
1539 		} // switch
1540 
1541 		pFmtFld->ModifyNotification( 0, 0 );		// Formatierung anstossen
1542 
1543 		if( pUpdtFld == pTxtFld )		// sollte nur dieses geupdatet werden
1544 		{
1545 			if( RES_GETEXPFLD == nWhich ||		// nur GetFeld oder
1546 				RES_HIDDENTXTFLD == nWhich ||	// HiddenTxt?
1547 				RES_HIDDENPARAFLD == nWhich)	// HiddenParaFld?
1548 				break;							// beenden
1549 			pUpdtFld = 0;						// ab jetzt alle Updaten
1550 		}
1551 	}
1552 
1553 	pMgr->CloseAll(sal_False);
1554 	// HashTabelle wieder loeschen
1555 	::DeleteHashTable( pHashStrTbl, nStrFmtCnt );
1556 
1557 	// Referenzfelder updaten
1558 	if( bUpdRefFlds )
1559 		UpdateRefFlds(NULL);
1560 
1561 	pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds );
1562 	pUpdtFlds->SetFieldsDirty( sal_False );
1563 }
1564 
1565 /*--------------------------------------------------------------------
1566 	Beschreibung:
1567  --------------------------------------------------------------------*/
1568 
1569 void SwDoc::UpdateDBNumFlds( SwDBNameInfField& rDBFld, SwCalc& rCalc )
1570 {
1571 	SwNewDBMgr* pMgr = GetNewDBMgr();
1572 
1573 	sal_uInt16 nFldType = rDBFld.Which();
1574 
1575 	sal_Bool bPar1 = rCalc.Calculate( rDBFld.GetPar1() ).GetBool();
1576 
1577 	if( RES_DBNEXTSETFLD == nFldType )
1578 		((SwDBNextSetField&)rDBFld).SetCondValid( bPar1 );
1579 	else
1580 		((SwDBNumSetField&)rDBFld).SetCondValid( bPar1 );
1581 
1582 	if( rDBFld.GetRealDBData().sDataSource.getLength() )
1583 	{
1584 		// Eine bestimmte Datenbank bearbeiten
1585 		if( RES_DBNEXTSETFLD == nFldType )
1586 			((SwDBNextSetField&)rDBFld).Evaluate(this);
1587 		else
1588 			((SwDBNumSetField&)rDBFld).Evaluate(this);
1589 
1590 		SwDBData aTmpDBData( rDBFld.GetDBData(this) );
1591 
1592         if( pMgr->OpenDataSource( aTmpDBData.sDataSource, aTmpDBData.sCommand, -1, false ))
1593 			rCalc.VarChange( lcl_GetDBVarName( *this, rDBFld),
1594                         pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType) );
1595 	}
1596 	else
1597 	{
1598 		DBG_ERROR("TODO: what should happen with unnamed DBFields?");
1599 	}
1600 }
1601 
1602 /*--------------------------------------------------------------------
1603 	Beschreibung:
1604  --------------------------------------------------------------------*/
1605 
1606 void SwDoc::_InitFieldTypes()		// wird vom CTOR gerufen!!
1607 {
1608 	// Feldtypen
1609 	sal_uInt16 nFldType = 0;
1610 	pFldTypes->Insert( new SwDateTimeFieldType(this), nFldType++ );
1611 	pFldTypes->Insert( new SwChapterFieldType, nFldType++ );
1612 	pFldTypes->Insert( new SwPageNumberFieldType, nFldType++ );
1613 	pFldTypes->Insert( new SwAuthorFieldType, nFldType++ );
1614 	pFldTypes->Insert( new SwFileNameFieldType(this), nFldType++ );
1615 	pFldTypes->Insert( new SwDBNameFieldType(this), nFldType++);
1616 	pFldTypes->Insert( new SwGetExpFieldType(this), nFldType++ );
1617 	pFldTypes->Insert( new SwGetRefFieldType( this ), nFldType++ );
1618 	pFldTypes->Insert( new SwHiddenTxtFieldType, nFldType++ );
1619 	pFldTypes->Insert( new SwPostItFieldType(this), nFldType++ );
1620 	pFldTypes->Insert( new SwDocStatFieldType(this), nFldType++);
1621 	pFldTypes->Insert( new SwDocInfoFieldType(this), nFldType++);
1622 	pFldTypes->Insert( new SwInputFieldType( this ), nFldType++ );
1623 	pFldTypes->Insert( new SwTblFieldType( this ), nFldType++);
1624 	pFldTypes->Insert( new SwMacroFieldType(this), nFldType++ );
1625 	pFldTypes->Insert( new SwHiddenParaFieldType, nFldType++ );
1626 	pFldTypes->Insert( new SwDBNextSetFieldType, nFldType++ );
1627 	pFldTypes->Insert( new SwDBNumSetFieldType, nFldType++ );
1628 	pFldTypes->Insert( new SwDBSetNumberFieldType, nFldType++ );
1629 	pFldTypes->Insert( new SwTemplNameFieldType(this), nFldType++);
1630 	pFldTypes->Insert( new SwTemplNameFieldType(this),nFldType++);
1631 	pFldTypes->Insert( new SwExtUserFieldType, nFldType++ );
1632 	pFldTypes->Insert( new SwRefPageSetFieldType, nFldType++ );
1633 	pFldTypes->Insert( new SwRefPageGetFieldType( this ), nFldType++ );
1634 	pFldTypes->Insert( new SwJumpEditFieldType( this ), nFldType++ );
1635 	pFldTypes->Insert( new SwScriptFieldType( this ), nFldType++ );
1636 	pFldTypes->Insert( new SwCombinedCharFieldType, nFldType++ );
1637     pFldTypes->Insert( new SwDropDownFieldType, nFldType++ );
1638 
1639 	// Types muessen am Ende stehen !!
1640 	// Im InsertFldType wird davon ausgegangen !!!!
1641 	// MIB 14.04.95: Im Sw3StringPool::Setup (sw3imp.cxx) und
1642 	//				 lcl_sw3io_InSetExpField (sw3field.cxx) jetzt auch
1643 	pFldTypes->Insert( new SwSetExpFieldType(this,
1644 				SW_RESSTR(STR_POOLCOLL_LABEL_ABB), nsSwGetSetExpType::GSE_SEQ), nFldType++);
1645 	pFldTypes->Insert( new SwSetExpFieldType(this,
1646 				SW_RESSTR(STR_POOLCOLL_LABEL_TABLE), nsSwGetSetExpType::GSE_SEQ),nFldType++);
1647 	pFldTypes->Insert( new SwSetExpFieldType(this,
1648 				SW_RESSTR(STR_POOLCOLL_LABEL_FRAME), nsSwGetSetExpType::GSE_SEQ),nFldType++);
1649 	pFldTypes->Insert( new SwSetExpFieldType(this,
1650 				SW_RESSTR(STR_POOLCOLL_LABEL_DRAWING), nsSwGetSetExpType::GSE_SEQ),nFldType++);
1651 
1652 	ASSERT( nFldType == INIT_FLDTYPES, "Bad initsize: SwFldTypes" );
1653 }
1654 
1655 void SwDoc::InsDelFldInFldLst( bool bIns, const SwTxtFld& rFld )
1656 {
1657 	if( !mbNewFldLst || !IsInDtor() )
1658 		pUpdtFlds->InsDelFldInFldLst( bIns, rFld );
1659 }
1660 
1661 SwDBData SwDoc::GetDBData()
1662 {
1663 	return GetDBDesc();
1664 }
1665 
1666 const SwDBData& SwDoc::GetDBDesc()
1667 {
1668     if(!aDBData.sDataSource.getLength())
1669     {
1670         const sal_uInt16 nSize = pFldTypes->Count();
1671         for(sal_uInt16 i = 0; i < nSize && !aDBData.sDataSource.getLength(); ++i)
1672         {
1673             SwFieldType& rFldType = *((*pFldTypes)[i]);
1674             sal_uInt16 nWhich = rFldType.Which();
1675             if(IsUsed(rFldType))
1676             {
1677                 switch(nWhich)
1678                 {
1679                     case RES_DBFLD:
1680                     case RES_DBNEXTSETFLD:
1681                     case RES_DBNUMSETFLD:
1682                     case RES_DBSETNUMBERFLD:
1683                     {
1684                         SwIterator<SwFmtFld,SwFieldType> aIter( rFldType );
1685                         for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
1686                         {
1687                             if(pFld->IsFldInDoc())
1688                             {
1689                                 if(RES_DBFLD == nWhich)
1690                                     aDBData = (static_cast < SwDBFieldType * > (pFld->GetField()->GetTyp()))->GetDBData();
1691                                 else
1692                                     aDBData = (static_cast < SwDBNameInfField* > (pFld->GetField()))->GetRealDBData();
1693                                 break;
1694                             }
1695                         }
1696                     }
1697                     break;
1698                 }
1699             }
1700         }
1701     }
1702     if(!aDBData.sDataSource.getLength())
1703         aDBData = GetNewDBMgr()->GetAddressDBName();
1704     return aDBData;
1705 }
1706 
1707 void SwDoc::SetInitDBFields( sal_Bool b )
1708 {
1709 	GetNewDBMgr()->SetInitDBFields( b );
1710 }
1711 
1712 /*--------------------------------------------------------------------
1713 	Beschreibung: Alle von Feldern verwendete Datenbanken herausfinden
1714  --------------------------------------------------------------------*/
1715 String lcl_DBDataToString(const SwDBData& rData)
1716 {
1717 	String sRet = rData.sDataSource;
1718 	sRet += DB_DELIM;
1719 	sRet += (String)rData.sCommand;
1720 	sRet += DB_DELIM;
1721 	sRet += String::CreateFromInt32(rData.nCommandType);
1722 	return sRet;
1723 }
1724 void SwDoc::GetAllUsedDB( SvStringsDtor& rDBNameList,
1725 							const SvStringsDtor* pAllDBNames )
1726 {
1727 	SvStringsDtor aUsedDBNames;
1728 	SvStringsDtor aAllDBNames;
1729 
1730 	if( !pAllDBNames )
1731 	{
1732 		GetAllDBNames( aAllDBNames );
1733 		pAllDBNames = &aAllDBNames;
1734 	}
1735 
1736 	SwSectionFmts& rArr = GetSections();
1737 	for (sal_uInt16 n = rArr.Count(); n; )
1738 	{
1739 		SwSection* pSect = rArr[ --n ]->GetSection();
1740 
1741 		if( pSect )
1742 		{
1743 			String aCond( pSect->GetCondition() );
1744 			AddUsedDBToList( rDBNameList, FindUsedDBs( *pAllDBNames,
1745 												aCond, aUsedDBNames ) );
1746 			aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
1747 		}
1748 	}
1749 
1750 	const SfxPoolItem* pItem;
1751 	sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
1752     for (sal_uInt32 n = 0; n < nMaxItems; ++n)
1753 	{
1754 		if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) ))
1755 			continue;
1756 
1757 		const SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
1758 		const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1759 		if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
1760 			continue;
1761 
1762 		const SwField* pFld = pFmtFld->GetField();
1763 		switch( pFld->GetTyp()->Which() )
1764 		{
1765 			case RES_DBFLD:
1766 				AddUsedDBToList( rDBNameList,
1767 								lcl_DBDataToString(((SwDBField*)pFld)->GetDBData() ));
1768 				break;
1769 
1770 			case RES_DBSETNUMBERFLD:
1771 			case RES_DBNAMEFLD:
1772 				AddUsedDBToList( rDBNameList,
1773 								lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() ));
1774 				break;
1775 
1776 			case RES_DBNUMSETFLD:
1777 			case RES_DBNEXTSETFLD:
1778 				AddUsedDBToList( rDBNameList,
1779 								lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() ));
1780 				// kein break  // JP: ist das so richtig ??
1781 
1782 			case RES_HIDDENTXTFLD:
1783 			case RES_HIDDENPARAFLD:
1784 				AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames,
1785 											pFld->GetPar1(), aUsedDBNames ));
1786 				aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
1787 				break;
1788 
1789 			case RES_SETEXPFLD:
1790 			case RES_GETEXPFLD:
1791 			case RES_TABLEFLD:
1792 				AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames,
1793 										pFld->GetFormula(), aUsedDBNames ));
1794 				aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
1795 				break;
1796 		}
1797 	}
1798 }
1799 
1800 /*--------------------------------------------------------------------
1801 	Beschreibung:
1802  --------------------------------------------------------------------*/
1803 
1804 void SwDoc::GetAllDBNames( SvStringsDtor& rAllDBNames )
1805 {
1806 	SwNewDBMgr* pMgr = GetNewDBMgr();
1807 
1808 	const SwDSParamArr& rArr = pMgr->GetDSParamArray();
1809 	for(sal_uInt16 i = 0; i < rArr.Count(); i++)
1810 	{
1811 		SwDSParam* pParam = rArr[i];
1812 		String* pStr = new String( pParam->sDataSource );
1813 		(*pStr)	+= DB_DELIM;
1814         (*pStr) += (String)pParam->sCommand;
1815 		rAllDBNames.Insert( pStr, rAllDBNames.Count() );
1816 	}
1817 }
1818 
1819 /*--------------------------------------------------------------------
1820 	Beschreibung:
1821  --------------------------------------------------------------------*/
1822 
1823 SvStringsDtor& SwDoc::FindUsedDBs( const SvStringsDtor& rAllDBNames,
1824 									const String& rFormel,
1825 									SvStringsDtor& rUsedDBNames )
1826 {
1827 	const CharClass& rCC = GetAppCharClass();
1828 	String 	sFormel( rFormel);
1829 #ifndef UNX
1830 	rCC.toUpper( sFormel );
1831 #endif
1832 
1833 	xub_StrLen nPos;
1834 	for (sal_uInt16 i = 0; i < rAllDBNames.Count(); ++i )
1835 	{
1836 		const String* pStr = rAllDBNames.GetObject(i);
1837 
1838 		if( STRING_NOTFOUND != (nPos = sFormel.Search( *pStr )) &&
1839 			sFormel.GetChar( nPos + pStr->Len() ) == '.' &&
1840 			(!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 )))
1841 		{
1842 			// Tabellenname suchen
1843 			xub_StrLen nEndPos;
1844 			nPos += pStr->Len() + 1;
1845 			if( STRING_NOTFOUND != (nEndPos = sFormel.Search('.', nPos)) )
1846 			{
1847 				String* pDBNm = new String( *pStr );
1848 				pDBNm->Append( DB_DELIM );
1849 				pDBNm->Append( sFormel.Copy( nPos, nEndPos - nPos ));
1850 				rUsedDBNames.Insert( pDBNm, rUsedDBNames.Count() );
1851 			}
1852 		}
1853 	}
1854 	return rUsedDBNames;
1855 }
1856 
1857 /*--------------------------------------------------------------------
1858 	Beschreibung:
1859  --------------------------------------------------------------------*/
1860 
1861 void SwDoc::AddUsedDBToList( SvStringsDtor& rDBNameList,
1862 							 const SvStringsDtor& rUsedDBNames )
1863 {
1864 	for (sal_uInt16 i = 0; i < rUsedDBNames.Count(); i++)
1865 		AddUsedDBToList( rDBNameList, *rUsedDBNames.GetObject(i) );
1866 }
1867 
1868 /*--------------------------------------------------------------------
1869 	Beschreibung:
1870  --------------------------------------------------------------------*/
1871 
1872 void SwDoc::AddUsedDBToList( SvStringsDtor& rDBNameList, const String& rDBName)
1873 {
1874 	if( !rDBName.Len() )
1875 		return;
1876 
1877 #ifdef UNX
1878 	for( sal_uInt16 i = 0; i < rDBNameList.Count(); ++i )
1879 		if( rDBName == rDBNameList.GetObject(i)->GetToken(0) )
1880 			return;
1881 #else
1882 	const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
1883 	for( sal_uInt16 i = 0; i < rDBNameList.Count(); ++i )
1884 		if( rSCmp.isEqual( rDBName, rDBNameList.GetObject(i)->GetToken(0) ) )
1885 			return;
1886 #endif
1887 
1888     SwDBData aData;
1889     aData.sDataSource = rDBName.GetToken(0, DB_DELIM);
1890     aData.sCommand = rDBName.GetToken(1, DB_DELIM);
1891     aData.nCommandType = -1;
1892     GetNewDBMgr()->CreateDSData(aData);
1893 	String* pNew = new String( rDBName );
1894 	rDBNameList.Insert( pNew, rDBNameList.Count() );
1895 }
1896 
1897 /*--------------------------------------------------------------------
1898 	 Beschreibung:
1899  --------------------------------------------------------------------*/
1900 
1901 void SwDoc::ChangeDBFields( const SvStringsDtor& rOldNames,
1902 							const String& rNewName )
1903 {
1904 	SwDBData aNewDBData;
1905 	aNewDBData.sDataSource = rNewName.GetToken(0, DB_DELIM);
1906 	aNewDBData.sCommand = rNewName.GetToken(1, DB_DELIM);
1907 	aNewDBData.nCommandType = (short)rNewName.GetToken(2, DB_DELIM).ToInt32();
1908 
1909 	String sFormel;
1910 
1911 	SwSectionFmts& rArr = GetSections();
1912     for (sal_uInt16 n = rArr.Count(); n; )
1913 	{
1914 		SwSection* pSect = rArr[ --n ]->GetSection();
1915 
1916 		if( pSect )
1917 		{
1918 			sFormel = pSect->GetCondition();
1919 			ReplaceUsedDBs( rOldNames, rNewName, sFormel);
1920 			pSect->SetCondition(sFormel);
1921 		}
1922 	}
1923 
1924 	const SfxPoolItem* pItem;
1925 	sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
1926 
1927     for (sal_uInt32 n = 0; n < nMaxItems; ++n )
1928 	{
1929 		if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) ))
1930 			continue;
1931 
1932 		SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
1933 		SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1934 		if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
1935 			continue;
1936 
1937 		SwField* pFld = pFmtFld->GetField();
1938 		sal_Bool bExpand = sal_False;
1939 
1940 		switch( pFld->GetTyp()->Which() )
1941 		{
1942 			case RES_DBFLD:
1943 				if( IsNameInArray( rOldNames, lcl_DBDataToString(((SwDBField*)pFld)->GetDBData())))
1944 				{
1945 					SwDBFieldType* pOldTyp = (SwDBFieldType*)pFld->GetTyp();
1946 
1947 					SwDBFieldType* pTyp = (SwDBFieldType*)InsertFldType(
1948 							SwDBFieldType(this, pOldTyp->GetColumnName(), aNewDBData));
1949 
1950                     pFmtFld->RegisterToFieldType( *pTyp );
1951 					pFld->ChgTyp(pTyp);
1952 
1953 					((SwDBField*)pFld)->ClearInitialized();
1954 					((SwDBField*)pFld)->InitContent();
1955 
1956 					bExpand = sal_True;
1957 				}
1958 				break;
1959 
1960 			case RES_DBSETNUMBERFLD:
1961 			case RES_DBNAMEFLD:
1962 				if( IsNameInArray( rOldNames,
1963 								lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData())))
1964 				{
1965 					((SwDBNameInfField*)pFld)->SetDBData(aNewDBData);
1966 					bExpand = sal_True;
1967 				}
1968 				break;
1969 
1970 			case RES_DBNUMSETFLD:
1971 			case RES_DBNEXTSETFLD:
1972 				if( IsNameInArray( rOldNames,
1973 								lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData())))
1974 				{
1975 					((SwDBNameInfField*)pFld)->SetDBData(aNewDBData);
1976 					bExpand = sal_True;
1977 				}
1978 				// kein break;
1979 			case RES_HIDDENTXTFLD:
1980 			case RES_HIDDENPARAFLD:
1981 				sFormel = pFld->GetPar1();
1982 				ReplaceUsedDBs( rOldNames, rNewName, sFormel);
1983 				pFld->SetPar1( sFormel );
1984 				bExpand = sal_True;
1985 				break;
1986 
1987 			case RES_SETEXPFLD:
1988 			case RES_GETEXPFLD:
1989 			case RES_TABLEFLD:
1990 				sFormel = pFld->GetFormula();
1991 				ReplaceUsedDBs( rOldNames, rNewName, sFormel);
1992 				pFld->SetPar2( sFormel );
1993 				bExpand = sal_True;
1994 				break;
1995 		}
1996 
1997 		if (bExpand)
1998 			pTxtFld->ExpandAlways();
1999 	}
2000 	SetModified();
2001 }
2002 
2003 /*--------------------------------------------------------------------
2004 	Beschreibung:
2005  --------------------------------------------------------------------*/
2006 
2007 void SwDoc::ReplaceUsedDBs( const SvStringsDtor& rUsedDBNames,
2008 							const String& rNewName, String& rFormel )
2009 {
2010 	const CharClass& rCC = GetAppCharClass();
2011 	String 	sFormel(rFormel);
2012 	String	sNewName( rNewName );
2013 	sNewName.SearchAndReplace( DB_DELIM, '.');
2014 	//the command type is not part of the condition
2015 	sNewName = sNewName.GetToken(0, DB_DELIM);
2016 	String sUpperNewNm( sNewName );
2017 
2018 
2019 	for( sal_uInt16 i = 0; i < rUsedDBNames.Count(); ++i )
2020 	{
2021 		String	sDBName( *rUsedDBNames.GetObject( i ) );
2022 
2023 		sDBName.SearchAndReplace( DB_DELIM, '.');
2024 		//cut off command type
2025 		sDBName = sDBName.GetToken(0, DB_DELIM);
2026 		if( !sDBName.Equals( sUpperNewNm ))
2027 		{
2028 			xub_StrLen nPos = 0;
2029 
2030 			while ((nPos = sFormel.Search(sDBName, nPos)) != STRING_NOTFOUND)
2031 			{
2032 				if( sFormel.GetChar( nPos + sDBName.Len() ) == '.' &&
2033 					(!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 )))
2034 				{
2035 					rFormel.Erase( nPos, sDBName.Len() );
2036 					rFormel.Insert( sNewName, nPos );
2037 					//prevent re-searching - this is useless and provokes
2038 					//endless loops when names containing each other and numbers are exchanged
2039 					//e.g.: old ?12345.12345  new: i12345.12345
2040 					nPos = nPos + sNewName.Len();
2041 					sFormel = rFormel;
2042 				}
2043 			}
2044 		}
2045 	}
2046 }
2047 
2048 /*--------------------------------------------------------------------
2049 	 Beschreibung:
2050  --------------------------------------------------------------------*/
2051 
2052 sal_Bool SwDoc::IsNameInArray( const SvStringsDtor& rArr, const String& rName )
2053 {
2054 #ifdef UNX
2055 	for( sal_uInt16 i = 0; i < rArr.Count(); ++i )
2056 		if( rName == *rArr[ i ] )
2057 			return sal_True;
2058 #else
2059 	const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
2060 	for( sal_uInt16 i = 0; i < rArr.Count(); ++i )
2061 		if( rSCmp.isEqual( rName, *rArr[ i] ))
2062 			return sal_True;
2063 #endif
2064 	return sal_False;
2065 }
2066 
2067 void SwDoc::SetFixFields( bool bOnlyTimeDate, const DateTime* pNewDateTime )
2068 {
2069 	sal_Bool bIsModified = IsModified();
2070 
2071 	sal_uLong nDate, nTime;
2072 	if( pNewDateTime )
2073 	{
2074 		nDate = pNewDateTime->GetDate();
2075 		nTime = pNewDateTime->GetTime();
2076 	}
2077 	else
2078 	{
2079 		nDate = Date().GetDate();
2080 		nTime = Time().GetTime();
2081 	}
2082 
2083 	sal_uInt16 aTypes[5] = {
2084 		/*0*/	RES_DOCINFOFLD,
2085 		/*1*/	RES_AUTHORFLD,
2086 		/*2*/	RES_EXTUSERFLD,
2087 		/*3*/	RES_FILENAMEFLD,
2088 		/*4*/	RES_DATETIMEFLD };	// MUSS am Ende stehen!!
2089 
2090 	sal_uInt16 nStt = bOnlyTimeDate ? 4 : 0;
2091 
2092 	for( ; nStt < 5; ++nStt )
2093 	{
2094 		SwFieldType* pFldType = GetSysFldType( aTypes[ nStt ] );
2095 		SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
2096 		for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
2097 		{
2098 			if( pFmtFld && pFmtFld->GetTxtFld() )
2099 			{
2100 				sal_Bool bChgd = sal_False;
2101 				switch( aTypes[ nStt ] )
2102 				{
2103 				case RES_DOCINFOFLD:
2104 					if( ((SwDocInfoField*)pFmtFld->GetField())->IsFixed() )
2105 					{
2106 						bChgd = sal_True;
2107 						SwDocInfoField* pDocInfFld = (SwDocInfoField*)pFmtFld->GetField();
2108 						pDocInfFld->SetExpansion( ((SwDocInfoFieldType*)
2109 									pDocInfFld->GetTyp())->Expand(
2110 										pDocInfFld->GetSubType(),
2111 										pDocInfFld->GetFormat(),
2112 										pDocInfFld->GetLanguage(),
2113 										pDocInfFld->GetName() ) );
2114 					}
2115 					break;
2116 
2117 				case RES_AUTHORFLD:
2118 					if( ((SwAuthorField*)pFmtFld->GetField())->IsFixed() )
2119 					{
2120 						bChgd = sal_True;
2121 						SwAuthorField* pAuthorFld = (SwAuthorField*)pFmtFld->GetField();
2122 						pAuthorFld->SetExpansion( ((SwAuthorFieldType*)
2123 									pAuthorFld->GetTyp())->Expand(
2124 												pAuthorFld->GetFormat() ) );
2125 					}
2126 					break;
2127 
2128 				case RES_EXTUSERFLD:
2129 					if( ((SwExtUserField*)pFmtFld->GetField())->IsFixed() )
2130 					{
2131 						bChgd = sal_True;
2132 						SwExtUserField* pExtUserFld = (SwExtUserField*)pFmtFld->GetField();
2133 						pExtUserFld->SetExpansion( ((SwExtUserFieldType*)
2134 									pExtUserFld->GetTyp())->Expand(
2135 											pExtUserFld->GetSubType(),
2136 											pExtUserFld->GetFormat()));
2137 					}
2138 					break;
2139 
2140 				case RES_DATETIMEFLD:
2141 					if( ((SwDateTimeField*)pFmtFld->GetField())->IsFixed() )
2142 					{
2143 						bChgd = sal_True;
2144 						((SwDateTimeField*)pFmtFld->GetField())->SetDateTime(
2145                                                     DateTime(Date(nDate), Time(nTime)) );
2146 					}
2147 					break;
2148 
2149 				case RES_FILENAMEFLD:
2150 					if( ((SwFileNameField*)pFmtFld->GetField())->IsFixed() )
2151 					{
2152 						bChgd = sal_True;
2153 						SwFileNameField* pFileNameFld =
2154 							(SwFileNameField*)pFmtFld->GetField();
2155 						pFileNameFld->SetExpansion( ((SwFileNameFieldType*)
2156 									pFileNameFld->GetTyp())->Expand(
2157 											pFileNameFld->GetFormat() ) );
2158 					}
2159 					break;
2160 				}
2161 
2162 				// Formatierung anstossen
2163 				if( bChgd )
2164 					pFmtFld->ModifyNotification( 0, 0 );
2165 			}
2166 		}
2167 	}
2168 
2169 	if( !bIsModified )
2170 		ResetModified();
2171 }
2172 
2173 bool SwDoc::SetFieldsDirty( bool b, const SwNode* pChk, sal_uLong nLen )
2174 {
2175 	// teste ggfs. mal, ob die angegbenen Nodes ueberhaupt Felder beinhalten.
2176 	// wenn nicht, braucht das Flag nicht veraendert werden.
2177 	sal_Bool bFldsFnd = sal_False;
2178 	if( b && pChk && !GetUpdtFlds().IsFieldsDirty() && !IsInDtor()
2179 		// ?? was ist mit Undo, da will man es doch auch haben !!
2180 		/*&& &pChk->GetNodes() == &GetNodes()*/ )
2181 	{
2182 		b = sal_False;
2183 		if( !nLen )
2184 			++nLen;
2185 		sal_uLong nStt = pChk->GetIndex();
2186 		const SwNodes& rNds = pChk->GetNodes();
2187 		while( nLen-- )
2188 		{
2189 			const SwTxtNode* pTNd = rNds[ nStt++ ]->GetTxtNode();
2190 			if( pTNd )
2191 			{
2192 				if( //pTNd->GetFmtColl() &&		//#outline level,zhaojianwei
2193 				//	MAXLEVEL > pTNd->GetTxtColl()->GetOutlineLevel() )
2194 					pTNd->GetAttrOutlineLevel() != 0 )//<-end,zhaojianwei
2195 					// Kapitelfelder aktualisieren
2196 					b = sal_True;
2197 				else if( pTNd->GetpSwpHints() && pTNd->GetSwpHints().Count() )
2198 					for( sal_uInt16 n = 0, nEnd = pTNd->GetSwpHints().Count();
2199 							n < nEnd; ++n )
2200 					{
2201 						const SwTxtAttr* pAttr = pTNd->GetSwpHints()[ n ];
2202 						if( RES_TXTATR_FIELD == pAttr->Which() )
2203 						{
2204 							b = sal_True;
2205 							break;
2206 						}
2207 					}
2208 
2209 				if( b )
2210 					break;
2211 			}
2212 		}
2213 		bFldsFnd = b;
2214 	}
2215 	GetUpdtFlds().SetFieldsDirty( b );
2216 	return bFldsFnd;
2217 }
2218 /* -----------------------------21.12.99 12:55--------------------------------
2219 
2220  ---------------------------------------------------------------------------*/
2221 void SwDoc::ChangeAuthorityData( const SwAuthEntry* pNewData )
2222 {
2223 	const sal_uInt16 nSize = pFldTypes->Count();
2224 
2225 	for( sal_uInt16 i = INIT_FLDTYPES; i < nSize; ++i )
2226 	{
2227 		SwFieldType* pFldType = (*pFldTypes)[i];
2228 		if( RES_AUTHORITY  == pFldType->Which() )
2229 		{
2230 			SwAuthorityFieldType* pAuthType = (SwAuthorityFieldType*)pFldType;
2231 			pAuthType->ChangeEntryContent(pNewData);
2232 			break;
2233 		}
2234 	}
2235 
2236 }
2237 /*--------------------------------------------------------------------
2238 	Beschreibung:
2239  --------------------------------------------------------------------*/
2240 
2241 void SwDocUpdtFld::InsDelFldInFldLst( sal_Bool bIns, const SwTxtFld& rFld )
2242 {
2243     const sal_uInt16 nWhich = rFld.GetFmtFld().GetField()->GetTyp()->Which();
2244 	switch( nWhich )
2245 	{
2246 	case RES_DBFLD:
2247 	case RES_SETEXPFLD:
2248 	case RES_HIDDENPARAFLD:
2249 	case RES_HIDDENTXTFLD:
2250 	case RES_DBNUMSETFLD:
2251 	case RES_DBNEXTSETFLD:
2252 	case RES_DBSETNUMBERFLD:
2253 	case RES_GETEXPFLD:
2254 		break;			// diese muessen ein-/ausgetragen werden!
2255 
2256 	default:
2257 		return;
2258 	}
2259 
2260 	SetFieldsDirty( sal_True );
2261 	if( !pFldSortLst )
2262 	{
2263 		if( !bIns ) 			// keine Liste vorhanden und loeschen
2264 			return; 			// dann nichts tun
2265 		pFldSortLst = new _SetGetExpFlds( 64, 16 );
2266 	}
2267 
2268 	if( bIns )		// neu einfuegen:
2269 		GetBodyNode( rFld, nWhich );
2270 	else
2271 	{
2272 		// ueber den pTxtFld Pointer suchen. Ist zwar eine Sortierte
2273 		// Liste, aber nach Node-Positionen sortiert. Bis dieser
2274 		// bestimmt ist, ist das Suchen nach dem Pointer schon fertig
2275 		for( sal_uInt16 n = 0; n < pFldSortLst->Count(); ++n )
2276 			if( &rFld == (*pFldSortLst)[ n ]->GetPointer() )
2277 				pFldSortLst->DeleteAndDestroy( n--, 1 );
2278 				// ein Feld kann mehrfach vorhanden sein!
2279 	}
2280 }
2281 
2282 void SwDocUpdtFld::MakeFldList( SwDoc& rDoc, int bAll, int eGetMode )
2283 {
2284     if( !pFldSortLst || bAll || !( eGetMode & nFldLstGetMode ) ||
2285         rDoc.GetNodes().Count() != nNodes )
2286         _MakeFldList( rDoc, eGetMode );
2287 }
2288 
2289 void SwDocUpdtFld::_MakeFldList( SwDoc& rDoc, int eGetMode )
2290 {
2291 	// neue Version: gehe ueber alle Felder vom Attribut-Pool
2292 	if( pFldSortLst )
2293 		delete pFldSortLst;
2294 	pFldSortLst = new _SetGetExpFlds( 64, 16 );
2295 
2296     /// OD 09.08.2002 [#101207#,#101216#,#101778#] - consider and unhide sections
2297     ///     with hide condition, only in mode GETFLD_ALL (<eGetMode == GETFLD_ALL>)
2298     ///     notes by OD:
2299     ///         eGetMode == GETFLD_CALC in call from methods SwDoc::FldsToCalc
2300     ///         eGetMode == GETFLD_EXPAND in call from method SwDoc::FldsToExpand
2301     ///         eGetMode == GETFLD_ALL in call from method SwDoc::UpdateExpFlds
2302     ///         I figured out that hidden section only have to be shown,
2303     ///         if fields have updated (call by SwDoc::UpdateExpFlds) and thus
2304     ///         the hide conditions of section have to be updated.
2305     ///         For correct updating the hide condition of a section, its position
2306     ///         have to be known in order to insert the hide condition as a new
2307     ///         expression field into the sorted field list (<pFldSortLst>).
2308     if ( eGetMode == GETFLD_ALL )
2309 	// zuerst die Bereiche einsammeln. Alle die ueber Bedingung
2310 	// gehiddet sind, wieder mit Frames versorgen, damit die darin
2311 	// enthaltenen Felder richtig einsortiert werden!!!
2312     {
2313 		// damit die Frames richtig angelegt werden, muessen sie in der
2314 		// Reihenfolgen von oben nach unten expandiert werden
2315 		SvULongs aTmpArr;
2316 		SwSectionFmts& rArr = rDoc.GetSections();
2317 		SwSectionNode* pSectNd;
2318 		sal_uInt16 nArrStt = 0;
2319 		sal_uLong nSttCntnt = rDoc.GetNodes().GetEndOfExtras().GetIndex();
2320 
2321         for (sal_uInt16 n = rArr.Count(); n; )
2322 		{
2323 			SwSection* pSect = rArr[ --n ]->GetSection();
2324             if( pSect && pSect->IsHidden() && pSect->GetCondition().Len() &&
2325 				0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() ))
2326 			{
2327 				sal_uLong nIdx = pSectNd->GetIndex();
2328 				sal_uInt16 i;
2329 
2330 				for( i = 0; i < aTmpArr.Count() && aTmpArr[ i ] < nIdx; ++i )
2331 					;
2332 				aTmpArr.Insert( nIdx, i );
2333 				if( nIdx < nSttCntnt )
2334 					++nArrStt;
2335 			}
2336 		}
2337 
2338         // erst alle anzeigen, damit die Frames vorhanden sind. Mit deren
2339         // Position wird das BodyAnchor ermittelt.
2340         // Dafuer erst den ContentBereich, dann die Sonderbereiche!!!
2341         for (sal_uInt16 n = nArrStt; n < aTmpArr.Count(); ++n)
2342         {
2343             pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
2344             ASSERT( pSectNd, "Wo ist mein SectionNode" );
2345             pSectNd->GetSection().SetCondHidden( sal_False );
2346         }
2347         for (sal_uInt16 n = 0; n < nArrStt; ++n)
2348         {
2349             pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
2350             ASSERT( pSectNd, "Wo ist mein SectionNode" );
2351             pSectNd->GetSection().SetCondHidden( sal_False );
2352         }
2353 
2354         // so, erst jetzt alle sortiert in die Liste eintragen
2355         for (sal_uInt16 n = 0; n < aTmpArr.Count(); ++n)
2356         {
2357             GetBodyNode( *rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode() );
2358         }
2359     }
2360 
2361 	String sTrue( String::CreateFromAscii(
2362 									RTL_CONSTASCII_STRINGPARAM( "sal_True" ))),
2363 		   sFalse( String::CreateFromAscii(
2364 		   							RTL_CONSTASCII_STRINGPARAM( "sal_False" )));
2365 
2366 	sal_Bool bIsDBMgr = 0 != rDoc.GetNewDBMgr();
2367 	sal_uInt16 nWhich, n;
2368 	const String* pFormel = 0;
2369 	const SfxPoolItem* pItem;
2370 	sal_uInt32 nMaxItems = rDoc.GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
2371 	for( n = 0; n < nMaxItems; ++n )
2372 	{
2373         if( 0 == (pItem = rDoc.GetAttrPool().GetItem2( RES_TXTATR_FIELD, n )) )
2374 			continue;
2375 
2376 		const SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
2377 		const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
2378 		if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
2379 			continue;
2380 
2381 		const SwField* pFld = pFmtFld->GetField();
2382 		switch( nWhich = pFld->GetTyp()->Which() )
2383 		{
2384 			case RES_DBSETNUMBERFLD:
2385 			case RES_GETEXPFLD:
2386 				if( GETFLD_ALL == eGetMode )
2387 					pFormel = &sTrue;
2388 				break;
2389 
2390 			case RES_DBFLD:
2391 				if( GETFLD_EXPAND & eGetMode )
2392 					pFormel = &sTrue;
2393 				break;
2394 
2395 			case RES_SETEXPFLD:
2396                 /// fields of subtype <string> have also been add
2397                 /// for calculation (eGetMode == GETFLD_CALC).
2398                 /// Thus, add fields of subtype <string> in all modes
2399                 ///     (eGetMode == GETFLD_EXPAND||GETFLD_CALC||GETFLD_ALL)
2400                 /// and fields of other subtypes only in the modes
2401                 ///     (eGetMode == GETFLD_CALC||GETFLD_ALL)
2402                 /* "old" if construct - not deleted for history and code review
2403                 if( ( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType()
2404                         ? GETFLD_EXPAND : GETFLD_CALC )
2405                         & eGetMode )
2406                 */
2407                 if ( !(eGetMode == GETFLD_EXPAND) ||
2408                      (nsSwGetSetExpType::GSE_STRING & pFld->GetSubType()) )
2409                 {
2410 					pFormel = &sTrue;
2411                 }
2412 				break;
2413 
2414 			case RES_HIDDENPARAFLD:
2415 				if( GETFLD_ALL == eGetMode )
2416 				{
2417 					pFormel = &pFld->GetPar1();
2418 					if( !pFormel->Len() || pFormel->Equals( sFalse ))
2419 						((SwHiddenParaField*)pFld)->SetHidden( sal_False );
2420 					else if( pFormel->Equals( sTrue ))
2421 						((SwHiddenParaField*)pFld)->SetHidden( sal_True );
2422 					else
2423 						break;
2424 
2425 					pFormel = 0;
2426 					// Formatierung anstossen
2427 					((SwFmtFld*)pFmtFld)->ModifyNotification( 0, 0 );
2428 				}
2429 				break;
2430 
2431 			case RES_HIDDENTXTFLD:
2432 				if( GETFLD_ALL == eGetMode )
2433 				{
2434 					pFormel = &pFld->GetPar1();
2435 					if( !pFormel->Len() || pFormel->Equals( sFalse ))
2436 						((SwHiddenTxtField*)pFld)->SetValue( sal_True );
2437 					else if( pFormel->Equals( sTrue ))
2438 						((SwHiddenTxtField*)pFld)->SetValue( sal_False );
2439 					else
2440 						break;
2441 
2442 					pFormel = 0;
2443 
2444 					// Feld Evaluieren
2445 					((SwHiddenTxtField*)pFld)->Evaluate(&rDoc);
2446 					// Formatierung anstossen
2447 					((SwFmtFld*)pFmtFld)->ModifyNotification( 0, 0 );
2448 				}
2449 				break;
2450 
2451 			case RES_DBNUMSETFLD:
2452 			{
2453 				SwDBData aDBData(((SwDBNumSetField*)pFld)->GetDBData(&rDoc));
2454 
2455                 if (
2456                      (bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) &&
2457                      (GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNumSetField*)pFld)->IsCondValid()))
2458                    )
2459                 {
2460                     pFormel = &pFld->GetPar1();
2461                 }
2462 			}
2463 			break;
2464 			case RES_DBNEXTSETFLD:
2465 			{
2466 				SwDBData aDBData(((SwDBNextSetField*)pFld)->GetDBData(&rDoc));
2467 
2468                 if (
2469                      (bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) &&
2470                      (GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNextSetField*)pFld)->IsCondValid()))
2471                    )
2472                 {
2473                     pFormel = &pFld->GetPar1();
2474                 }
2475 			}
2476 			break;
2477 		}
2478 
2479 		if( pFormel && pFormel->Len() )
2480 		{
2481 			GetBodyNode( *pTxtFld, nWhich );
2482 			pFormel = 0;
2483 		}
2484 	}
2485 	nFldLstGetMode = static_cast<sal_uInt8>( eGetMode );
2486 	nNodes = rDoc.GetNodes().Count();
2487 
2488 #ifdef JP_DEBUG
2489 	{
2490 	SvFileStream sOut( "f:\\x.x", STREAM_STD_WRITE );
2491 	sOut.Seek( STREAM_SEEK_TO_END );
2492 	sOut << "------------------" << endl;
2493 	const _SetGetExpFldPtr* pSortLst = pFldSortLst->GetData();
2494 	for( sal_uInt16 n = pFldSortLst->Count(); n; --n, ++pSortLst )
2495 	{
2496 		String sStr( (*pSortLst)->GetNode() );
2497 		sStr += "\t, ";
2498 		sStr += (*pSortLst)->GetCntnt();
2499 		sStr += "\tNode: ";
2500 		sStr += (*pSortLst)->GetFld()->GetTxtNode().StartOfSectionIndex();
2501 		sStr += "\tPos: ";
2502 		sStr += *(*pSortLst)->GetFld()->GetStart();
2503 		sStr += "\tType: ";
2504 		sStr += (*pSortLst)->GetFld()->GetFld().GetFld()->GetTyp()->Which();
2505 
2506 		sOut << sStr.GetStr() << endl;
2507 	}
2508 	}
2509 #endif
2510 	// JP_DEBUG
2511 }
2512 
2513 /*--------------------------------------------------------------------
2514 	Beschreibung:
2515  --------------------------------------------------------------------*/
2516 
2517 void SwDocUpdtFld::GetBodyNode( const SwTxtFld& rTFld, sal_uInt16 nFldWhich )
2518 {
2519 	const SwTxtNode& rTxtNd = rTFld.GetTxtNode();
2520 	const SwDoc& rDoc = *rTxtNd.GetDoc();
2521 
2522 	// immer den ersten !! (in Tab-Headline, Kopf-/Fuss )
2523 	Point aPt;
2524 	const SwCntntFrm* pFrm = rTxtNd.getLayoutFrm( rDoc.GetCurrentLayout(), &aPt, 0, sal_False );
2525 
2526     _SetGetExpFld* pNew = NULL;
2527 	sal_Bool bIsInBody = sal_False;
2528 
2529 	if( !pFrm || pFrm->IsInDocBody() )
2530 	{
2531 		// einen Index fuers bestimmen vom TextNode anlegen
2532 		SwNodeIndex aIdx( rTxtNd );
2533 		bIsInBody = rDoc.GetNodes().GetEndOfExtras().GetIndex() < aIdx.GetIndex();
2534 
2535         // #104291# dvo: We don't want to update fields in redlines, or those
2536         // in frames whose anchor is in redline. However, we do want to update
2537         // fields in hidden sections. So: In order to be updated, a field 1)
2538         // must have a frame, or 2) it must be in the document body.
2539         if( (pFrm != NULL) || bIsInBody )
2540             pNew = new _SetGetExpFld( aIdx, &rTFld );
2541 	}
2542 	else
2543 	{
2544 		// einen Index fuers bestimmen vom TextNode anlegen
2545 		SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() );
2546 #ifdef DBG_UTIL
2547 		ASSERT( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" );
2548 #else
2549 		GetBodyTxtNode( rDoc, aPos, *pFrm );
2550 #endif
2551 		pNew = new _SetGetExpFld( aPos.nNode, &rTFld, &aPos.nContent );
2552 	}
2553 
2554 	// bei GetExp.-/DB.-Felder immer das BodyTxtFlag setzen
2555 	if( RES_GETEXPFLD == nFldWhich )
2556 	{
2557 		SwGetExpField* pGetFld = (SwGetExpField*)rTFld.GetFmtFld().GetField();
2558 		pGetFld->ChgBodyTxtFlag( bIsInBody );
2559 	}
2560 	else if( RES_DBFLD == nFldWhich )
2561 	{
2562 		SwDBField* pDBFld = (SwDBField*)rTFld.GetFmtFld().GetField();
2563 		pDBFld->ChgBodyTxtFlag( bIsInBody );
2564 	}
2565 
2566     if( pNew != NULL )
2567         if( !pFldSortLst->Insert( pNew ))
2568             delete pNew;
2569 }
2570 
2571 void SwDocUpdtFld::GetBodyNode( const SwSectionNode& rSectNd )
2572 {
2573 	const SwDoc& rDoc = *rSectNd.GetDoc();
2574 	_SetGetExpFld* pNew = 0;
2575 
2576 	if( rSectNd.GetIndex() < rDoc.GetNodes().GetEndOfExtras().GetIndex() )
2577 	{
2578 		do {			// middle check loop
2579 
2580 			// dann muessen wir uns mal den Anker besorgen!
2581 			// einen Index fuers bestimmen vom TextNode anlegen
2582 			SwPosition aPos( rSectNd );
2583 			SwCntntNode* pCNd = rDoc.GetNodes().GoNext( &aPos.nNode ); // zum naechsten ContentNode
2584 
2585 			if( !pCNd || !pCNd->IsTxtNode() )
2586 				break;
2587 
2588 			// immer den ersten !! (in Tab-Headline, Kopf-/Fuss )
2589 			Point aPt;
2590 			const SwCntntFrm* pFrm = pCNd->getLayoutFrm( rDoc.GetCurrentLayout(), &aPt, 0, sal_False );
2591 			if( !pFrm )
2592 				break;
2593 
2594 #ifdef DBG_UTIL
2595 			ASSERT( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" );
2596 #else
2597 			GetBodyTxtNode( rDoc, aPos, *pFrm );
2598 #endif
2599 			pNew = new _SetGetExpFld( rSectNd, &aPos );
2600 
2601 		} while( sal_False );
2602 	}
2603 
2604 	if( !pNew )
2605 		pNew = new _SetGetExpFld( rSectNd );
2606 
2607 	if( !pFldSortLst->Insert( pNew ))
2608 		delete pNew;
2609 }
2610 
2611 void SwDocUpdtFld::InsertFldType( const SwFieldType& rType )
2612 {
2613 	String sFldName;
2614 	switch( rType.Which() )
2615 	{
2616 	case RES_USERFLD :
2617 		sFldName = ((SwUserFieldType&)rType).GetName();
2618 		break;
2619 	case RES_SETEXPFLD:
2620 		sFldName = ((SwSetExpFieldType&)rType).GetName();
2621 		break;
2622 	default:
2623 		ASSERT( !this, "kein gueltiger FeldTyp" );
2624 	}
2625 
2626 	if( sFldName.Len() )
2627 	{
2628 		SetFieldsDirty( sal_True );
2629 		// suchen und aus der HashTabelle entfernen
2630 		GetAppCharClass().toLower( sFldName );
2631 		sal_uInt16 n;
2632 
2633 		SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n );
2634 
2635 		if( !pFnd )
2636 		{
2637 			SwCalcFldType* pNew = new SwCalcFldType( sFldName, &rType );
2638 			pNew->pNext = aFldTypeTable[ n ];
2639 			aFldTypeTable[ n ] = pNew;
2640 		}
2641 	}
2642 }
2643 
2644 void SwDocUpdtFld::RemoveFldType( const SwFieldType& rType )
2645 {
2646 	String sFldName;
2647 	switch( rType.Which() )
2648 	{
2649 	case RES_USERFLD :
2650 		sFldName = ((SwUserFieldType&)rType).GetName();
2651 		break;
2652 	case RES_SETEXPFLD:
2653 		sFldName = ((SwSetExpFieldType&)rType).GetName();
2654 		break;
2655 	}
2656 
2657 	if( sFldName.Len() )
2658 	{
2659 		SetFieldsDirty( sal_True );
2660 		// suchen und aus der HashTabelle entfernen
2661 		GetAppCharClass().toLower( sFldName );
2662 		sal_uInt16 n;
2663 
2664 		SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n );
2665 		if( pFnd )
2666 		{
2667 			if( aFldTypeTable[ n ] == pFnd )
2668 				aFldTypeTable[ n ] = (SwCalcFldType*)pFnd->pNext;
2669 			else
2670 			{
2671 				SwHash* pPrev = aFldTypeTable[ n ];
2672 				while( pPrev->pNext != pFnd )
2673 					pPrev = pPrev->pNext;
2674 				pPrev->pNext = pFnd->pNext;
2675 			}
2676 			pFnd->pNext = 0;
2677 			delete pFnd;
2678 		}
2679 	}
2680 }
2681 
2682 SwDocUpdtFld::SwDocUpdtFld()
2683 	: pFldSortLst(0),  nFldUpdtPos(LONG_MAX), nFldLstGetMode(0)
2684 {
2685 	bInUpdateFlds = bFldsDirty = sal_False;
2686 	memset( aFldTypeTable, 0, sizeof( aFldTypeTable ) );
2687 }
2688 
2689 SwDocUpdtFld::~SwDocUpdtFld()
2690 {
2691 	delete pFldSortLst;
2692 
2693 	for( sal_uInt16 n = 0; n < TBLSZ; ++n )
2694 		delete aFldTypeTable[n];
2695 }
2696 
2697 // #111840#
2698 bool SwDoc::UpdateFld(SwTxtFld * pDstTxtFld, SwField & rSrcFld,
2699                       SwMsgPoolItem * pMsgHnt,
2700                       bool bUpdateFlds)
2701 {
2702     ASSERT(pDstTxtFld, "no field to update!");
2703 
2704     sal_Bool bTblSelBreak = sal_False;
2705 
2706     SwFmtFld * pDstFmtFld = (SwFmtFld*)&pDstTxtFld->GetFmtFld();
2707     SwField * pDstFld = pDstFmtFld->GetField();
2708     sal_uInt16 nFldWhich = rSrcFld.GetTyp()->Which();
2709     SwNodeIndex aTblNdIdx(pDstTxtFld->GetTxtNode());
2710 
2711     if (pDstFld->GetTyp()->Which() ==
2712         rSrcFld.GetTyp()->Which())
2713     {
2714         if (GetIDocumentUndoRedo().DoesUndo())
2715         {
2716             SwPosition aPosition( pDstTxtFld->GetTxtNode() );
2717             aPosition.nContent = *pDstTxtFld->GetStart();
2718 
2719             SwUndo *const pUndo( new SwUndoFieldFromDoc(
2720                         aPosition, *pDstFld, rSrcFld, pMsgHnt, bUpdateFlds) );
2721             GetIDocumentUndoRedo().AppendUndo(pUndo);
2722         }
2723 
2724         // Das gefundene Feld wird angepasst ...
2725         //pDstFld->ChangeFormat( rSrcFld.GetFormat() );
2726         //pDstFld->SetLanguage( rSrcFld.GetLanguage() );
2727 
2728         SwField * pNewFld = rSrcFld.CopyField();
2729         pDstFmtFld->SetFld(pNewFld);
2730 
2731         switch( nFldWhich )
2732         {
2733         case RES_SETEXPFLD:
2734         case RES_GETEXPFLD:
2735         case RES_HIDDENTXTFLD:
2736         case RES_HIDDENPARAFLD:
2737             UpdateExpFlds( pDstTxtFld, true );
2738             break;
2739 
2740         case RES_TABLEFLD:
2741             {
2742                 const SwTableNode* pTblNd =
2743                     IsIdxInTbl(aTblNdIdx);
2744                 if( pTblNd )
2745                 {
2746                     SwTableFmlUpdate aTblUpdate( &pTblNd->
2747                                                  GetTable() );
2748                     if (bUpdateFlds)
2749                         UpdateTblFlds( &aTblUpdate );
2750                     else
2751                         pNewFld->GetTyp()->ModifyNotification(0, &aTblUpdate);
2752 
2753                     if (! bUpdateFlds)
2754                         bTblSelBreak = sal_True;
2755                 }
2756             }
2757             break;
2758 
2759         case RES_MACROFLD:
2760             if( bUpdateFlds && pDstTxtFld->GetpTxtNode() )
2761                 (pDstTxtFld->GetpTxtNode())->
2762                     ModifyNotification( 0, pDstFmtFld );
2763             break;
2764 
2765         case RES_DBNAMEFLD:
2766         case RES_DBNEXTSETFLD:
2767         case RES_DBNUMSETFLD:
2768         case RES_DBSETNUMBERFLD:
2769             ChgDBData(((SwDBNameInfField*) pNewFld)->GetRealDBData());
2770             pNewFld->GetTyp()->UpdateFlds();
2771 
2772             break;
2773 
2774         case RES_DBFLD:
2775             {
2776                 // JP 10.02.96: ChgValue aufrufen, damit
2777                 //die Format- aenderung den ContentString
2778                 //richtig setzt
2779                 SwDBField* pDBFld = (SwDBField*)pNewFld;
2780                 if (pDBFld->IsInitialized())
2781                     pDBFld->ChgValue( pDBFld->GetValue(), sal_True );
2782 
2783                 pDBFld->ClearInitialized();
2784                 pDBFld->InitContent();
2785             }
2786             // kein break;
2787 
2788         default:
2789             pDstFmtFld->ModifyNotification( 0, pMsgHnt );
2790         }
2791 
2792         // Die Felder die wir berechnen koennen werden hier expli.
2793         // zum Update angestossen.
2794         if( nFldWhich == RES_USERFLD )
2795             UpdateUsrFlds();
2796     }
2797 
2798     return bTblSelBreak;
2799 }
2800 
2801 bool SwDoc::PutValueToField(const SwPosition & rPos,
2802                             const Any& rVal, sal_uInt16 nWhich)
2803 {
2804     Any aOldVal;
2805     SwField * pField = GetField(rPos);
2806 
2807 
2808     if (GetIDocumentUndoRedo().DoesUndo() &&
2809         pField->QueryValue(aOldVal, nWhich))
2810     {
2811         SwUndo *const pUndo(new SwUndoFieldFromAPI(rPos, aOldVal, rVal, nWhich));
2812         GetIDocumentUndoRedo().AppendUndo(pUndo);
2813     }
2814 
2815     return pField->PutValue(rVal, nWhich);
2816 }
2817