xref: /aoo41x/main/sw/source/core/doc/docfld.cxx (revision 69a74367)
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(
759     const SwNodeIndex& rNdIdx,
760     const SwTxtFld* pFld,
761     const SwIndex* pIdx )
762 {
763     eSetGetExpFldType = TEXTFIELD;
764     CNTNT.pTxtFld = pFld;
765     nNode = rNdIdx.GetIndex();
766     if( pIdx )
767         nCntnt = pIdx->GetIndex();
768     else if( pFld )
769         nCntnt = *pFld->GetStart();
770     else
771         nCntnt = 0;
772 }
773 
774 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx,
775 							const SwTxtINetFmt& rINet, const SwIndex* pIdx )
776 {
777 	eSetGetExpFldType = TEXTINET;
778 	CNTNT.pTxtINet = &rINet;
779 	nNode = rNdIdx.GetIndex();
780 	if( pIdx )
781 		nCntnt = pIdx->GetIndex();
782 	else
783 		nCntnt = *rINet.GetStart();
784 }
785 
786 	//Erweiterung fuer Sections:
787 	//	diese haben immer als Content-Position 0xffff !!
788 	//	Auf dieser steht nie ein Feld, maximal bis STRING_MAXLEN moeglich
789 _SetGetExpFld::_SetGetExpFld( const SwSectionNode& rSectNd,
790 								const SwPosition* pPos )
791 {
792 	eSetGetExpFldType = SECTIONNODE;
793 	CNTNT.pSection = &rSectNd.GetSection();
794 
795 	if( pPos )
796 	{
797 		nNode = pPos->nNode.GetIndex();
798 		nCntnt = pPos->nContent.GetIndex();
799 	}
800 	else
801 	{
802 		nNode = rSectNd.GetIndex();
803 		nCntnt = 0;
804 	}
805 }
806 
807 _SetGetExpFld::_SetGetExpFld( const SwTableBox& rTBox, const SwPosition* pPos )
808 {
809 	eSetGetExpFldType = TABLEBOX;
810 	CNTNT.pTBox = &rTBox;
811 
812 	if( pPos )
813 	{
814 		nNode = pPos->nNode.GetIndex();
815 		nCntnt = pPos->nContent.GetIndex();
816 	}
817 	else
818 	{
819 		nNode = 0;
820 		nCntnt = 0;
821 		if( rTBox.GetSttNd() )
822 		{
823 			SwNodeIndex aIdx( *rTBox.GetSttNd() );
824 			const SwCntntNode* pNd = aIdx.GetNode().GetNodes().GoNext( &aIdx );
825 			if( pNd )
826 				nNode = pNd->GetIndex();
827 		}
828 	}
829 }
830 
831 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx,
832 								const SwTxtTOXMark& rTOX,
833 								const SwIndex* pIdx )
834 {
835 	eSetGetExpFldType = TEXTTOXMARK;
836 	CNTNT.pTxtTOX = &rTOX;
837 	nNode = rNdIdx.GetIndex();
838 	if( pIdx )
839 		nCntnt = pIdx->GetIndex();
840 	else
841 		nCntnt = *rTOX.GetStart();
842 }
843 
844 _SetGetExpFld::_SetGetExpFld( const SwPosition& rPos )
845 {
846 	eSetGetExpFldType = CRSRPOS;
847 	CNTNT.pPos = &rPos;
848 	nNode = rPos.nNode.GetIndex();
849 	nCntnt = rPos.nContent.GetIndex();
850 }
851 
852 _SetGetExpFld::_SetGetExpFld( const SwFlyFrmFmt& rFlyFmt,
853 								const SwPosition* pPos  )
854 {
855 	eSetGetExpFldType = FLYFRAME;
856 	CNTNT.pFlyFmt = &rFlyFmt;
857 	if( pPos )
858 	{
859 		nNode = pPos->nNode.GetIndex();
860 		nCntnt = pPos->nContent.GetIndex();
861 	}
862 	else
863 	{
864 		const SwFmtCntnt& rCntnt = rFlyFmt.GetCntnt();
865 		nNode = rCntnt.GetCntntIdx()->GetIndex() + 1;
866 		nCntnt = 0;
867 	}
868 }
869 
870 void _SetGetExpFld::GetPos( SwPosition& rPos ) const
871 {
872 	rPos.nNode = nNode;
873 	rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt );
874 }
875 
876 void _SetGetExpFld::GetPosOfContent( SwPosition& rPos ) const
877 {
878 	const SwNode* pNd = GetNodeFromCntnt();
879 	if( pNd )
880 		pNd = pNd->GetCntntNode();
881 
882 	if( pNd )
883 	{
884 		rPos.nNode = *pNd;
885 		rPos.nContent.Assign( (SwCntntNode*)pNd,GetCntPosFromCntnt() );
886 	}
887 	else
888 	{
889 		rPos.nNode = nNode;
890 		rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt );
891 	}
892 }
893 
894 void _SetGetExpFld::SetBodyPos( const SwCntntFrm& rFrm )
895 {
896 	if( !rFrm.IsInDocBody() )
897 	{
898 		SwNodeIndex aIdx( *rFrm.GetNode() );
899 		SwDoc& rDoc = *aIdx.GetNodes().GetDoc();
900 		SwPosition aPos( aIdx );
901 #ifdef DBG_UTIL
902 		ASSERT( ::GetBodyTxtNode( rDoc, aPos, rFrm ), "wo steht das Feld" );
903 #else
904 		::GetBodyTxtNode( rDoc, aPos, rFrm );
905 #endif
906 		nNode = aPos.nNode.GetIndex();
907 		nCntnt = aPos.nContent.GetIndex();
908 	}
909 }
910 
911 sal_Bool _SetGetExpFld::operator==( const _SetGetExpFld& rFld ) const
912 {
913     return nNode == rFld.nNode
914            && nCntnt == rFld.nCntnt
915            && ( !CNTNT.pTxtFld
916                 || !rFld.CNTNT.pTxtFld
917                 || CNTNT.pTxtFld == rFld.CNTNT.pTxtFld );
918 }
919 
920 sal_Bool _SetGetExpFld::operator<( const _SetGetExpFld& rFld ) const
921 {
922 	if( nNode < rFld.nNode || ( nNode == rFld.nNode && nCntnt < rFld.nCntnt ))
923 		return sal_True;
924 	else if( nNode != rFld.nNode || nCntnt != rFld.nCntnt )
925 		return sal_False;
926 
927 	const SwNode *pFirst = GetNodeFromCntnt(),
928 				 *pNext = rFld.GetNodeFromCntnt();
929 
930 	// Position gleich: nur weiter wenn beide FeldPointer besetzt sind !!
931 	if( !pFirst || !pNext )
932 		return sal_False;
933 
934 	// gleiche Section ??
935 	if( pFirst->StartOfSectionNode() != pNext->StartOfSectionNode() )
936 	{
937 		// sollte einer in der Tabelle stehen ?
938 		const SwNode *pFirstStt, *pNextStt;
939 		const SwTableNode* pTblNd = pFirst->FindTableNode();
940 		if( pTblNd )
941 			pFirstStt = pTblNd->StartOfSectionNode();
942 		else
943 			pFirstStt = pFirst->StartOfSectionNode();
944 
945 		if( 0 != ( pTblNd = pNext->FindTableNode() ) )
946 			pNextStt = pTblNd->StartOfSectionNode();
947 		else
948 			pNextStt = pNext->StartOfSectionNode();
949 
950 		if( pFirstStt != pNextStt )
951 		{
952 			if( pFirst->IsTxtNode() && pNext->IsTxtNode() &&
953 				( pFirst->FindFlyStartNode() || pNext->FindFlyStartNode() ))
954 			{
955 				return ::IsFrameBehind( *(SwTxtNode*)pNext, nCntnt,
956 										*(SwTxtNode*)pFirst, nCntnt );
957 			}
958 			return pFirstStt->GetIndex() < pNextStt->GetIndex();
959 		}
960 	}
961 
962 	// ist gleiche Section, dann Feld im gleichen Node ?
963 	if( pFirst != pNext )
964 		return pFirst->GetIndex() < pNext->GetIndex();
965 
966 	// gleicher Node in der Section, dann Position im Node
967 	return GetCntPosFromCntnt() < rFld.GetCntPosFromCntnt();
968 }
969 
970 const SwNode* _SetGetExpFld::GetNodeFromCntnt() const
971 {
972 	const SwNode* pRet = 0;
973 	if( CNTNT.pTxtFld )
974 		switch( eSetGetExpFldType )
975 		{
976 		case TEXTFIELD:
977 			pRet = &CNTNT.pTxtFld->GetTxtNode();
978 			break;
979 
980 		case TEXTINET:
981 			pRet = &CNTNT.pTxtINet->GetTxtNode();
982 			break;
983 
984 		case SECTIONNODE:
985 			pRet = CNTNT.pSection->GetFmt()->GetSectionNode();
986 			break;
987 
988 		case CRSRPOS:
989 			pRet = &CNTNT.pPos->nNode.GetNode();
990 			break;
991 
992 		case TEXTTOXMARK:
993 			pRet = &CNTNT.pTxtTOX->GetTxtNode();
994 			break;
995 
996 		case TABLEBOX:
997 			if( CNTNT.pTBox->GetSttNd() )
998 			{
999 				SwNodeIndex aIdx( *CNTNT.pTBox->GetSttNd() );
1000 				pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx );
1001 			}
1002 			break;
1003 
1004 		case FLYFRAME:
1005 			{
1006 				SwNodeIndex aIdx( *CNTNT.pFlyFmt->GetCntnt().GetCntntIdx() );
1007 				pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx );
1008 			}
1009 			break;
1010 		}
1011 	return pRet;
1012 }
1013 
1014 xub_StrLen _SetGetExpFld::GetCntPosFromCntnt() const
1015 {
1016 	sal_uInt16 nRet = 0;
1017 	if( CNTNT.pTxtFld )
1018 		switch( eSetGetExpFldType )
1019 		{
1020 		case TEXTFIELD:
1021 		case TEXTINET:
1022 		case TEXTTOXMARK:
1023 			nRet = *CNTNT.pTxtFld->GetStart();
1024 			break;
1025 		case CRSRPOS:
1026 			nRet =  CNTNT.pPos->nContent.GetIndex();
1027 			break;
1028 		default:
1029 			break;
1030 		}
1031 	return nRet;
1032 }
1033 
1034 _HashStr::_HashStr( const String& rName, const String& rText,
1035 					_HashStr* pNxt )
1036 	: SwHash( rName ), aSetStr( rText )
1037 {
1038 	pNext = pNxt;
1039 }
1040 
1041 // suche nach dem Namen, ist er vorhanden, returne seinen String, sonst
1042 // einen LeerString
1043 void LookString( SwHash** ppTbl, sal_uInt16 nSize, const String& rName,
1044 					String& rRet, sal_uInt16* pPos )
1045 {
1046 	rRet = rName;
1047 	rRet.EraseLeadingChars().EraseTrailingChars();
1048 	SwHash* pFnd = Find( rRet, ppTbl, nSize, pPos );
1049 	if( pFnd )
1050 		rRet = ((_HashStr*)pFnd)->aSetStr;
1051 	else
1052 		rRet.Erase();
1053 }
1054 
1055 /*--------------------------------------------------------------------
1056 	Beschreibung:
1057  --------------------------------------------------------------------*/
1058 
1059 String lcl_GetDBVarName( SwDoc& rDoc, SwDBNameInfField& rDBFld )
1060 {
1061 	SwDBData aDBData( rDBFld.GetDBData( &rDoc ));
1062 	String sDBNumNm;
1063 	SwDBData aDocData = rDoc.GetDBData();
1064 
1065 	if( aDBData != aDocData )
1066 	{
1067 		sDBNumNm = aDBData.sDataSource;
1068 		sDBNumNm += DB_DELIM;
1069 		sDBNumNm += String(aDBData.sCommand);
1070 		sDBNumNm += DB_DELIM;
1071 	}
1072 	sDBNumNm += SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD);
1073 
1074 	return sDBNumNm;
1075 }
1076 
1077 /*--------------------------------------------------------------------
1078 	Beschreibung:
1079  --------------------------------------------------------------------*/
1080 
1081 void lcl_CalcFld( SwDoc& rDoc, SwCalc& rCalc, const _SetGetExpFld& rSGEFld,
1082 						SwNewDBMgr* pMgr )
1083 {
1084 	const SwTxtFld* pTxtFld = rSGEFld.GetTxtFld();
1085 	if( !pTxtFld )
1086 		return ;
1087 
1088 	const SwField* pFld = pTxtFld->GetFmtFld().GetField();
1089 	const sal_uInt16 nFldWhich = pFld->GetTyp()->Which();
1090 
1091 	if( RES_SETEXPFLD == nFldWhich )
1092 	{
1093 		SwSbxValue aValue;
1094 		if( nsSwGetSetExpType::GSE_EXPR & pFld->GetSubType() )
1095 			aValue.PutDouble( ((SwSetExpField*)pFld)->GetValue() );
1096 		else
1097 			// Erweiterung fuers Rechnen mit Strings
1098 			aValue.PutString( ((SwSetExpField*)pFld)->GetExpStr() );
1099 
1100 		// setze im Calculator den neuen Wert
1101 		rCalc.VarChange( pFld->GetTyp()->GetName(), aValue );
1102 	}
1103 	else if( pMgr )
1104 	{
1105 		switch( nFldWhich )
1106 		{
1107 		case RES_DBNUMSETFLD:
1108 			{
1109 				SwDBNumSetField* pDBFld = (SwDBNumSetField*)pFld;
1110 
1111 				SwDBData aDBData(pDBFld->GetDBData(&rDoc));
1112 
1113 				if( pDBFld->IsCondValid() &&
1114 					pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand ))
1115 					rCalc.VarChange( lcl_GetDBVarName( rDoc, *pDBFld),
1116 									pDBFld->GetFormat() );
1117 			}
1118 			break;
1119 		case RES_DBNEXTSETFLD:
1120 			{
1121 				SwDBNextSetField* pDBFld = (SwDBNextSetField*)pFld;
1122 				SwDBData aDBData(pDBFld->GetDBData(&rDoc));
1123 				if( !pDBFld->IsCondValid() ||
1124 					!pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand ))
1125 					break;
1126 
1127 				String sDBNumNm(lcl_GetDBVarName( rDoc, *pDBFld));
1128 				SwCalcExp* pExp = rCalc.VarLook( sDBNumNm );
1129 				if( pExp )
1130 					rCalc.VarChange( sDBNumNm, pExp->nValue.GetLong() + 1 );
1131 			}
1132 			break;
1133 
1134 		}
1135 	}
1136 }
1137 
1138 void SwDoc::FldsToCalc( SwCalc& rCalc, const _SetGetExpFld& rToThisFld )
1139 {
1140 	// erzeuge die Sortierteliste aller SetFelder
1141 	pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC );
1142 	mbNewFldLst = sal_False;
1143 
1144 	SwNewDBMgr* pMgr = GetNewDBMgr();
1145 	pMgr->CloseAll(sal_False);
1146 
1147 	if( pUpdtFlds->GetSortLst()->Count() )
1148 	{
1149 		sal_uInt16 nLast;
1150 		_SetGetExpFld* pFld = (_SetGetExpFld*)&rToThisFld;
1151 		if( pUpdtFlds->GetSortLst()->Seek_Entry( pFld, &nLast ) )
1152 			++nLast;
1153 
1154         const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
1155 		for( sal_uInt16 n = 0; n < nLast; ++n, ++ppSortLst )
1156 			lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr );
1157 	}
1158 
1159 	pMgr->CloseAll(sal_False);
1160 }
1161 
1162 void SwDoc::FldsToCalc( SwCalc& rCalc, sal_uLong nLastNd, sal_uInt16 nLastCnt )
1163 {
1164 	// erzeuge die Sortierteliste aller SetFelder
1165 	pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC );
1166 	mbNewFldLst = sal_False;
1167 
1168 	SwNewDBMgr* pMgr = GetNewDBMgr();
1169 	pMgr->CloseAll(sal_False);
1170 
1171 	const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
1172 
1173 	for( sal_uInt16 n = pUpdtFlds->GetSortLst()->Count();
1174         n &&
1175         ( (*ppSortLst)->GetNode() < nLastNd ||
1176           ( (*ppSortLst)->GetNode() == nLastNd && (*ppSortLst)->GetCntnt() <= nLastCnt )
1177         );
1178 		--n, ++ppSortLst )
1179 		lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr );
1180 
1181 	pMgr->CloseAll(sal_False);
1182 }
1183 
1184 void SwDoc::FldsToExpand( SwHash**& ppHashTbl, sal_uInt16& rTblSize,
1185 							const _SetGetExpFld& rToThisFld )
1186 {
1187 	// erzeuge die Sortierteliste aller SetFelder
1188 	pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_EXPAND );
1189 	mbNewFldLst = sal_False;
1190 
1191 	// HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt
1192 	// (versuche eine "ungerade"-Zahl zu erzeugen)
1193 	rTblSize = (( pUpdtFlds->GetSortLst()->Count() / 7 ) + 1 ) * 7;
1194 	ppHashTbl = new SwHash*[ rTblSize ];
1195 	memset( ppHashTbl, 0, sizeof( _HashStr* ) * rTblSize );
1196 
1197 	sal_uInt16 nLast;
1198 	{
1199 		_SetGetExpFld* pTmp = (_SetGetExpFld*)&rToThisFld;
1200 		if( pUpdtFlds->GetSortLst()->Seek_Entry( pTmp, &nLast ) )
1201 			++nLast;
1202 	}
1203 
1204 	sal_uInt16 nPos;
1205 	SwHash* pFnd;
1206 	String aNew;
1207 	const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
1208 	for( ; nLast; --nLast, ++ppSortLst )
1209 	{
1210 		const SwTxtFld* pTxtFld = (*ppSortLst)->GetTxtFld();
1211 		if( !pTxtFld )
1212 			continue;
1213 
1214 		const SwField* pFld = pTxtFld->GetFmtFld().GetField();
1215 		switch( pFld->GetTyp()->Which() )
1216 		{
1217 		case RES_SETEXPFLD:
1218 			if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() )
1219 			{
1220 				// setze in der HashTabelle den neuen Wert
1221 				// ist die "Formel" ein Feld ??
1222 				SwSetExpField* pSFld = (SwSetExpField*)pFld;
1223 				LookString( ppHashTbl, rTblSize, pSFld->GetFormula(), aNew );
1224 
1225                 if( !aNew.Len() )               // nichts gefunden, dann ist
1226                     aNew = pSFld->GetFormula(); // die Formel der neue Wert
1227 
1228                 // OD 11.02.2003 #i3141# - update expression of field as in
1229                 // method <SwDoc::UpdateExpFlds(..)> for string/text fields
1230                 pSFld->ChgExpStr( aNew );
1231 
1232 				// suche den Namen vom Feld
1233 				aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName();
1234 				// Eintrag vorhanden ?
1235 				pFnd = Find( aNew, ppHashTbl, rTblSize, &nPos );
1236 				if( pFnd )
1237 					// Eintrag in der HashTabelle aendern
1238 					((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr();
1239 				else
1240 					// neuen Eintrag einfuegen
1241 					*(ppHashTbl + nPos ) = new _HashStr( aNew,
1242 							pSFld->GetExpStr(), (_HashStr*)*(ppHashTbl + nPos) );
1243 			}
1244 			break;
1245 		case RES_DBFLD:
1246 			{
1247 				const String& rName = pFld->GetTyp()->GetName();
1248 
1249 				// Eintrag in den HashTable eintragen
1250 				// Eintrag vorhanden ?
1251 				pFnd = Find( rName, ppHashTbl, rTblSize, &nPos );
1252                 String const value(pFld->ExpandField(IsClipBoard()));
1253 				if( pFnd )
1254                 {
1255 					// Eintrag in der HashTabelle aendern
1256                     static_cast<_HashStr*>(pFnd)->aSetStr = value;
1257                 }
1258                 else
1259                 {
1260 					// neuen Eintrag einfuegen
1261 					*(ppHashTbl + nPos ) = new _HashStr( rName,
1262                         value, static_cast<_HashStr *>(*(ppHashTbl + nPos)));
1263                 }
1264 			}
1265 			break;
1266 		}
1267 	}
1268 }
1269 
1270 
1271 void SwDoc::UpdateExpFlds( SwTxtFld* pUpdtFld, bool bUpdRefFlds )
1272 {
1273     if( IsExpFldsLocked() || IsInReading() )
1274 		return;
1275 
1276 	sal_Bool bOldInUpdateFlds = pUpdtFlds->IsInUpdateFlds();
1277 	pUpdtFlds->SetInUpdateFlds( sal_True );
1278 
1279 	pUpdtFlds->MakeFldList( *this, sal_True, GETFLD_ALL );
1280 	mbNewFldLst = sal_False;
1281 
1282 	if( !pUpdtFlds->GetSortLst()->Count() )
1283 	{
1284 		if( bUpdRefFlds )
1285 			UpdateRefFlds(NULL);
1286 
1287 		pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds );
1288 		pUpdtFlds->SetFieldsDirty( sal_False );
1289 		return ;
1290 	}
1291 
1292 	sal_uInt16 nWhich, n;
1293 
1294 	// HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt
1295 	// (versuche eine "ungerade"-Zahl zu erzeugen)
1296 	sal_uInt16 nStrFmtCnt = (( pFldTypes->Count() / 7 ) + 1 ) * 7;
1297 	SwHash** pHashStrTbl = new SwHash*[ nStrFmtCnt ];
1298 	memset( pHashStrTbl, 0, sizeof( _HashStr* ) * nStrFmtCnt );
1299 
1300 	{
1301 		const SwFieldType* pFldType;
1302 		// gesondert behandeln:
1303 		for( n = pFldTypes->Count(); n; )
1304 			switch( ( pFldType = (*pFldTypes)[ --n ] )->Which() )
1305 			{
1306 			case RES_USERFLD:
1307 				{
1308 					// Eintrag vorhanden ?
1309 					sal_uInt16 nPos;
1310 					const String& rNm = pFldType->GetName();
1311 					String sExpand(((SwUserFieldType*)pFldType)->Expand(nsSwGetSetExpType::GSE_STRING, 0, 0));
1312 					SwHash* pFnd = Find( rNm, pHashStrTbl, nStrFmtCnt, &nPos );
1313 					if( pFnd )
1314 						// Eintrag in der HashTabelle aendern ??
1315 						((_HashStr*)pFnd)->aSetStr = sExpand;
1316 					else
1317 						// neuen Eintrag einfuegen
1318 						*(pHashStrTbl + nPos ) = new _HashStr( rNm, sExpand,
1319 												(_HashStr*)*(pHashStrTbl + nPos) );
1320 				}
1321 				break;
1322 			case RES_SETEXPFLD:
1323 				((SwSetExpFieldType*)pFldType)->SetOutlineChgNd( 0 );
1324 				break;
1325 			}
1326 	}
1327 
1328 	// Ok, das Array ist soweit mit allen Feldern gefuellt, dann rechne mal
1329 	SwCalc aCalc( *this );
1330 
1331 	String sDBNumNm( SwFieldType::GetTypeStr( TYP_DBSETNUMBERFLD ) );
1332 
1333 	// aktuelle Datensatznummer schon vorher einstellen
1334 	SwNewDBMgr* pMgr = GetNewDBMgr();
1335 	pMgr->CloseAll(sal_False);
1336 /*
1337 	if(pMgr && pMgr->OpenDB(DBMGR_STD, GetDBDesc(), sal_False))
1338 	{
1339 		if(!pMgr->IsInMerge() )
1340 			pMgr->ToFirstSelectedRecord(DBMGR_STD);
1341 
1342 		aCalc.VarChange( sDBNumNm, pMgr->GetCurSelectedRecordId(DBMGR_STD));
1343 	}
1344 */
1345 
1346 	String aNew;
1347 	const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData();
1348 	for( n = pUpdtFlds->GetSortLst()->Count(); n; --n, ++ppSortLst )
1349 	{
1350 		SwSection* pSect = (SwSection*)(*ppSortLst)->GetSection();
1351 		if( pSect )
1352 		{
1353 			//!SECTION
1354 
1355             SwSbxValue aValue = aCalc.Calculate(
1356                                         pSect->GetCondition() );
1357             if(!aValue.IsVoidValue())
1358                 pSect->SetCondHidden( aValue.GetBool() );
1359             continue;
1360         }
1361 
1362         SwTxtFld* pTxtFld = (SwTxtFld*)(*ppSortLst)->GetTxtFld();
1363         if( !pTxtFld )
1364         {
1365             ASSERT( !this, "was ist es denn nun" );
1366             continue;
1367         }
1368 
1369         SwFmtFld* pFmtFld = (SwFmtFld*)&pTxtFld->GetFmtFld();
1370         const SwField* pFld = pFmtFld->GetField();
1371 
1372         switch( nWhich = pFld->GetTyp()->Which() )
1373         {
1374         case RES_HIDDENTXTFLD:
1375         {
1376             SwHiddenTxtField* pHFld = (SwHiddenTxtField*)pFld;
1377             SwSbxValue aValue = aCalc.Calculate( pHFld->GetPar1() );
1378             sal_Bool bValue = !aValue.GetBool();
1379             if(!aValue.IsVoidValue())
1380             {
1381                 pHFld->SetValue( bValue );
1382                 // Feld Evaluieren
1383                 pHFld->Evaluate(this);
1384             }
1385         }
1386         break;
1387         case RES_HIDDENPARAFLD:
1388         {
1389             SwHiddenParaField* pHPFld = (SwHiddenParaField*)pFld;
1390             SwSbxValue aValue = aCalc.Calculate( pHPFld->GetPar1() );
1391             sal_Bool bValue = aValue.GetBool();
1392             if(!aValue.IsVoidValue())
1393                 pHPFld->SetHidden( bValue );
1394 		}
1395 		break;
1396 		case RES_DBSETNUMBERFLD:
1397 		{
1398 			((SwDBSetNumberField*)pFld)->Evaluate(this);
1399 			aCalc.VarChange( sDBNumNm, ((SwDBSetNumberField*)pFld)->GetSetNumber());
1400 		}
1401 		break;
1402 		case RES_DBNEXTSETFLD:
1403 		case RES_DBNUMSETFLD:
1404 			UpdateDBNumFlds( *(SwDBNameInfField*)pFld, aCalc );
1405 		break;
1406 		case RES_DBFLD:
1407 		{
1408 			// Feld Evaluieren
1409 			((SwDBField*)pFld)->Evaluate();
1410 
1411 			SwDBData aTmpDBData(((SwDBField*)pFld)->GetDBData());
1412 
1413             if( pMgr->IsDataSourceOpen(aTmpDBData.sDataSource, aTmpDBData.sCommand, sal_False))
1414                 aCalc.VarChange( sDBNumNm, pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType));
1415 
1416 			const String& rName = pFld->GetTyp()->GetName();
1417 
1418 			// Wert fuer den Calculator setzen
1419 //JP 10.02.96: GetValue macht hier doch keinen Sinn
1420 //			((SwDBField*)pFld)->GetValue();
1421 
1422 //!OK			aCalc.VarChange(aName, ((SwDBField*)pFld)->GetValue(aCalc));
1423 
1424 			// Eintrag in den HashTable eintragen
1425 			// Eintrag vorhanden ?
1426 			sal_uInt16 nPos;
1427 			SwHash* pFnd = Find( rName, pHashStrTbl, nStrFmtCnt, &nPos );
1428             String const value(pFld->ExpandField(IsClipBoard()));
1429 			if( pFnd )
1430             {
1431 				// Eintrag in der HashTabelle aendern
1432                 static_cast<_HashStr*>(pFnd)->aSetStr = value;
1433             }
1434 			else
1435             {
1436 				// neuen Eintrag einfuegen
1437 				*(pHashStrTbl + nPos ) = new _HashStr( rName,
1438                     value, static_cast<_HashStr *>(*(pHashStrTbl + nPos)));
1439             }
1440 		}
1441 		break;
1442 		case RES_GETEXPFLD:
1443 		case RES_SETEXPFLD:
1444 		{
1445 			if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() )		// String Ersetzung
1446 			{
1447 				if( RES_GETEXPFLD == nWhich )
1448 				{
1449 					SwGetExpField* pGFld = (SwGetExpField*)pFld;
1450 
1451 					if( (!pUpdtFld || pUpdtFld == pTxtFld )
1452                         && pGFld->IsInBodyTxt() )
1453 					{
1454 						LookString( pHashStrTbl, nStrFmtCnt,
1455 									pGFld->GetFormula(), aNew );
1456 						pGFld->ChgExpStr( aNew );
1457 					}
1458 				}
1459 				else
1460 				{
1461 					SwSetExpField* pSFld = (SwSetExpField*)pFld;
1462 					// ist die "Formel" ein Feld ??
1463 					LookString( pHashStrTbl, nStrFmtCnt,
1464 								pSFld->GetFormula(), aNew );
1465 
1466 					if( !aNew.Len() )				// nichts gefunden, dann ist die
1467 						aNew = pSFld->GetFormula();		// Formel der neue Wert
1468 
1469 					// nur ein spezielles FeldUpdaten ?
1470 					if( !pUpdtFld || pUpdtFld == pTxtFld )
1471 						pSFld->ChgExpStr( aNew );
1472 
1473 					// suche den Namen vom Feld
1474 					aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName();
1475 					// Eintrag vorhanden ?
1476 					sal_uInt16 nPos;
1477 					SwHash* pFnd = Find( aNew, pHashStrTbl, nStrFmtCnt, &nPos );
1478 					if( pFnd )
1479 						// Eintrag in der HashTabelle aendern
1480 						((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr();
1481 					else
1482 						// neuen Eintrag einfuegen
1483 						*(pHashStrTbl + nPos ) = pFnd = new _HashStr( aNew,
1484 										pSFld->GetExpStr(),
1485 										(_HashStr*)*(pHashStrTbl + nPos) );
1486 
1487 					// Erweiterung fuers Rechnen mit Strings
1488 					SwSbxValue aValue;
1489 					aValue.PutString( ((_HashStr*)pFnd)->aSetStr );
1490 					aCalc.VarChange( aNew, aValue );
1491 				}
1492 			}
1493 			else			// Formel neu berechnen
1494 			{
1495 				if( RES_GETEXPFLD == nWhich )
1496 				{
1497 					SwGetExpField* pGFld = (SwGetExpField*)pFld;
1498 
1499 					if( (!pUpdtFld || pUpdtFld == pTxtFld )
1500 						&& pGFld->IsInBodyTxt() )
1501 					{
1502                         SwSbxValue aValue = aCalc.Calculate(
1503                                         pGFld->GetFormula());
1504                         if(!aValue.IsVoidValue())
1505                             pGFld->SetValue(aValue.GetDouble() );
1506 					}
1507 				}
1508 				else
1509 				{
1510 					SwSetExpField* pSFld = (SwSetExpField*)pFld;
1511 					SwSetExpFieldType* pSFldTyp = (SwSetExpFieldType*)pFld->GetTyp();
1512 					aNew = pSFldTyp->GetName();
1513 
1514 					SwNode* pSeqNd = 0;
1515 
1516 					if( pSFld->IsSequenceFld() )
1517 					{
1518                         const sal_uInt8 nLvl = pSFldTyp->GetOutlineLvl();
1519 						if( MAXLEVEL > nLvl )
1520 						{
1521 							// dann teste, ob die Nummer neu aufsetzen muss
1522 							pSeqNd = GetNodes()[ (*ppSortLst)->GetNode() ];
1523 
1524 							const SwTxtNode* pOutlNd = pSeqNd->
1525 									FindOutlineNodeOfLevel( nLvl );
1526 							if( pSFldTyp->GetOutlineChgNd() != pOutlNd )
1527 							{
1528 								pSFldTyp->SetOutlineChgNd( pOutlNd );
1529 								aCalc.VarChange( aNew, 0 );
1530 							}
1531 						}
1532 					}
1533 
1534 					aNew += '=';
1535 					aNew += pSFld->GetFormula();
1536 
1537                     SwSbxValue aValue = aCalc.Calculate( aNew );
1538                     double nErg = aValue.GetDouble();
1539                     // nur ein spezielles Feld updaten ?
1540                     if( !aValue.IsVoidValue() && (!pUpdtFld || pUpdtFld == pTxtFld) )
1541 					{
1542 						pSFld->SetValue( nErg );
1543 
1544 						if( pSeqNd )
1545 							pSFldTyp->SetChapter( *pSFld, *pSeqNd );
1546 					}
1547 				}
1548 			}
1549 		}
1550 		} // switch
1551 
1552 		pFmtFld->ModifyNotification( 0, 0 );		// Formatierung anstossen
1553 
1554 		if( pUpdtFld == pTxtFld )		// sollte nur dieses geupdatet werden
1555 		{
1556 			if( RES_GETEXPFLD == nWhich ||		// nur GetFeld oder
1557 				RES_HIDDENTXTFLD == nWhich ||	// HiddenTxt?
1558 				RES_HIDDENPARAFLD == nWhich)	// HiddenParaFld?
1559 				break;							// beenden
1560 			pUpdtFld = 0;						// ab jetzt alle Updaten
1561 		}
1562 	}
1563 
1564 	pMgr->CloseAll(sal_False);
1565 	// HashTabelle wieder loeschen
1566 	::DeleteHashTable( pHashStrTbl, nStrFmtCnt );
1567 
1568 	// Referenzfelder updaten
1569 	if( bUpdRefFlds )
1570 		UpdateRefFlds(NULL);
1571 
1572 	pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds );
1573 	pUpdtFlds->SetFieldsDirty( sal_False );
1574 }
1575 
1576 /*--------------------------------------------------------------------
1577 	Beschreibung:
1578  --------------------------------------------------------------------*/
1579 
1580 void SwDoc::UpdateDBNumFlds( SwDBNameInfField& rDBFld, SwCalc& rCalc )
1581 {
1582 	SwNewDBMgr* pMgr = GetNewDBMgr();
1583 
1584 	sal_uInt16 nFldType = rDBFld.Which();
1585 
1586 	sal_Bool bPar1 = rCalc.Calculate( rDBFld.GetPar1() ).GetBool();
1587 
1588 	if( RES_DBNEXTSETFLD == nFldType )
1589 		((SwDBNextSetField&)rDBFld).SetCondValid( bPar1 );
1590 	else
1591 		((SwDBNumSetField&)rDBFld).SetCondValid( bPar1 );
1592 
1593 	if( rDBFld.GetRealDBData().sDataSource.getLength() )
1594 	{
1595 		// Eine bestimmte Datenbank bearbeiten
1596 		if( RES_DBNEXTSETFLD == nFldType )
1597 			((SwDBNextSetField&)rDBFld).Evaluate(this);
1598 		else
1599 			((SwDBNumSetField&)rDBFld).Evaluate(this);
1600 
1601 		SwDBData aTmpDBData( rDBFld.GetDBData(this) );
1602 
1603         if( pMgr->OpenDataSource( aTmpDBData.sDataSource, aTmpDBData.sCommand, -1, false ))
1604 			rCalc.VarChange( lcl_GetDBVarName( *this, rDBFld),
1605                         pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType) );
1606 	}
1607 	else
1608 	{
1609 		DBG_ERROR("TODO: what should happen with unnamed DBFields?");
1610 	}
1611 }
1612 
1613 /*--------------------------------------------------------------------
1614 	Beschreibung:
1615  --------------------------------------------------------------------*/
1616 
1617 void SwDoc::_InitFieldTypes()		// wird vom CTOR gerufen!!
1618 {
1619 	// Feldtypen
1620 	sal_uInt16 nFldType = 0;
1621 	pFldTypes->Insert( new SwDateTimeFieldType(this), nFldType++ );
1622 	pFldTypes->Insert( new SwChapterFieldType, nFldType++ );
1623 	pFldTypes->Insert( new SwPageNumberFieldType, nFldType++ );
1624 	pFldTypes->Insert( new SwAuthorFieldType, nFldType++ );
1625 	pFldTypes->Insert( new SwFileNameFieldType(this), nFldType++ );
1626 	pFldTypes->Insert( new SwDBNameFieldType(this), nFldType++);
1627 	pFldTypes->Insert( new SwGetExpFieldType(this), nFldType++ );
1628 	pFldTypes->Insert( new SwGetRefFieldType( this ), nFldType++ );
1629 	pFldTypes->Insert( new SwHiddenTxtFieldType, nFldType++ );
1630 	pFldTypes->Insert( new SwPostItFieldType(this), nFldType++ );
1631 	pFldTypes->Insert( new SwDocStatFieldType(this), nFldType++);
1632 	pFldTypes->Insert( new SwDocInfoFieldType(this), nFldType++);
1633 	pFldTypes->Insert( new SwInputFieldType( this ), nFldType++ );
1634 	pFldTypes->Insert( new SwTblFieldType( this ), nFldType++);
1635 	pFldTypes->Insert( new SwMacroFieldType(this), nFldType++ );
1636 	pFldTypes->Insert( new SwHiddenParaFieldType, nFldType++ );
1637 	pFldTypes->Insert( new SwDBNextSetFieldType, nFldType++ );
1638 	pFldTypes->Insert( new SwDBNumSetFieldType, nFldType++ );
1639 	pFldTypes->Insert( new SwDBSetNumberFieldType, nFldType++ );
1640 	pFldTypes->Insert( new SwTemplNameFieldType(this), nFldType++);
1641 	pFldTypes->Insert( new SwTemplNameFieldType(this),nFldType++);
1642 	pFldTypes->Insert( new SwExtUserFieldType, nFldType++ );
1643 	pFldTypes->Insert( new SwRefPageSetFieldType, nFldType++ );
1644 	pFldTypes->Insert( new SwRefPageGetFieldType( this ), nFldType++ );
1645 	pFldTypes->Insert( new SwJumpEditFieldType( this ), nFldType++ );
1646 	pFldTypes->Insert( new SwScriptFieldType( this ), nFldType++ );
1647 	pFldTypes->Insert( new SwCombinedCharFieldType, nFldType++ );
1648     pFldTypes->Insert( new SwDropDownFieldType, nFldType++ );
1649 
1650 	// Types muessen am Ende stehen !!
1651 	// Im InsertFldType wird davon ausgegangen !!!!
1652 	// MIB 14.04.95: Im Sw3StringPool::Setup (sw3imp.cxx) und
1653 	//				 lcl_sw3io_InSetExpField (sw3field.cxx) jetzt auch
1654 	pFldTypes->Insert( new SwSetExpFieldType(this,
1655 				SW_RESSTR(STR_POOLCOLL_LABEL_ABB), nsSwGetSetExpType::GSE_SEQ), nFldType++);
1656 	pFldTypes->Insert( new SwSetExpFieldType(this,
1657 				SW_RESSTR(STR_POOLCOLL_LABEL_TABLE), nsSwGetSetExpType::GSE_SEQ),nFldType++);
1658 	pFldTypes->Insert( new SwSetExpFieldType(this,
1659 				SW_RESSTR(STR_POOLCOLL_LABEL_FRAME), nsSwGetSetExpType::GSE_SEQ),nFldType++);
1660 	pFldTypes->Insert( new SwSetExpFieldType(this,
1661 				SW_RESSTR(STR_POOLCOLL_LABEL_DRAWING), nsSwGetSetExpType::GSE_SEQ),nFldType++);
1662 
1663 	ASSERT( nFldType == INIT_FLDTYPES, "Bad initsize: SwFldTypes" );
1664 }
1665 
1666 void SwDoc::InsDelFldInFldLst( bool bIns, const SwTxtFld& rFld )
1667 {
1668 	if( !mbNewFldLst || !IsInDtor() )
1669 		pUpdtFlds->InsDelFldInFldLst( bIns, rFld );
1670 }
1671 
1672 SwDBData SwDoc::GetDBData()
1673 {
1674 	return GetDBDesc();
1675 }
1676 
1677 const SwDBData& SwDoc::GetDBDesc()
1678 {
1679     if(!aDBData.sDataSource.getLength())
1680     {
1681         const sal_uInt16 nSize = pFldTypes->Count();
1682         for(sal_uInt16 i = 0; i < nSize && !aDBData.sDataSource.getLength(); ++i)
1683         {
1684             SwFieldType& rFldType = *((*pFldTypes)[i]);
1685             sal_uInt16 nWhich = rFldType.Which();
1686             if(IsUsed(rFldType))
1687             {
1688                 switch(nWhich)
1689                 {
1690                     case RES_DBFLD:
1691                     case RES_DBNEXTSETFLD:
1692                     case RES_DBNUMSETFLD:
1693                     case RES_DBSETNUMBERFLD:
1694                     {
1695                         SwIterator<SwFmtFld,SwFieldType> aIter( rFldType );
1696                         for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
1697                         {
1698                             if(pFld->IsFldInDoc())
1699                             {
1700                                 if(RES_DBFLD == nWhich)
1701                                     aDBData = (static_cast < SwDBFieldType * > (pFld->GetField()->GetTyp()))->GetDBData();
1702                                 else
1703                                     aDBData = (static_cast < SwDBNameInfField* > (pFld->GetField()))->GetRealDBData();
1704                                 break;
1705                             }
1706                         }
1707                     }
1708                     break;
1709                 }
1710             }
1711         }
1712     }
1713     if(!aDBData.sDataSource.getLength())
1714         aDBData = GetNewDBMgr()->GetAddressDBName();
1715     return aDBData;
1716 }
1717 
1718 void SwDoc::SetInitDBFields( sal_Bool b )
1719 {
1720 	GetNewDBMgr()->SetInitDBFields( b );
1721 }
1722 
1723 /*--------------------------------------------------------------------
1724 	Beschreibung: Alle von Feldern verwendete Datenbanken herausfinden
1725  --------------------------------------------------------------------*/
1726 String lcl_DBDataToString(const SwDBData& rData)
1727 {
1728 	String sRet = rData.sDataSource;
1729 	sRet += DB_DELIM;
1730 	sRet += (String)rData.sCommand;
1731 	sRet += DB_DELIM;
1732 	sRet += String::CreateFromInt32(rData.nCommandType);
1733 	return sRet;
1734 }
1735 void SwDoc::GetAllUsedDB( SvStringsDtor& rDBNameList,
1736 							const SvStringsDtor* pAllDBNames )
1737 {
1738 	SvStringsDtor aUsedDBNames;
1739 	SvStringsDtor aAllDBNames;
1740 
1741 	if( !pAllDBNames )
1742 	{
1743 		GetAllDBNames( aAllDBNames );
1744 		pAllDBNames = &aAllDBNames;
1745 	}
1746 
1747 	SwSectionFmts& rArr = GetSections();
1748 	for (sal_uInt16 n = rArr.Count(); n; )
1749 	{
1750 		SwSection* pSect = rArr[ --n ]->GetSection();
1751 
1752 		if( pSect )
1753 		{
1754 			String aCond( pSect->GetCondition() );
1755 			AddUsedDBToList( rDBNameList, FindUsedDBs( *pAllDBNames,
1756 												aCond, aUsedDBNames ) );
1757 			aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
1758 		}
1759 	}
1760 
1761 	const SfxPoolItem* pItem;
1762 	sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
1763     for (sal_uInt32 n = 0; n < nMaxItems; ++n)
1764 	{
1765 		if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) ))
1766 			continue;
1767 
1768 		const SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
1769 		const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1770 		if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
1771 			continue;
1772 
1773 		const SwField* pFld = pFmtFld->GetField();
1774 		switch( pFld->GetTyp()->Which() )
1775 		{
1776 			case RES_DBFLD:
1777 				AddUsedDBToList( rDBNameList,
1778 								lcl_DBDataToString(((SwDBField*)pFld)->GetDBData() ));
1779 				break;
1780 
1781 			case RES_DBSETNUMBERFLD:
1782 			case RES_DBNAMEFLD:
1783 				AddUsedDBToList( rDBNameList,
1784 								lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() ));
1785 				break;
1786 
1787 			case RES_DBNUMSETFLD:
1788 			case RES_DBNEXTSETFLD:
1789 				AddUsedDBToList( rDBNameList,
1790 								lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() ));
1791 				// kein break  // JP: ist das so richtig ??
1792 
1793 			case RES_HIDDENTXTFLD:
1794 			case RES_HIDDENPARAFLD:
1795 				AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames,
1796 											pFld->GetPar1(), aUsedDBNames ));
1797 				aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
1798 				break;
1799 
1800 			case RES_SETEXPFLD:
1801 			case RES_GETEXPFLD:
1802 			case RES_TABLEFLD:
1803 				AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames,
1804 										pFld->GetFormula(), aUsedDBNames ));
1805 				aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() );
1806 				break;
1807 		}
1808 	}
1809 }
1810 
1811 /*--------------------------------------------------------------------
1812 	Beschreibung:
1813  --------------------------------------------------------------------*/
1814 
1815 void SwDoc::GetAllDBNames( SvStringsDtor& rAllDBNames )
1816 {
1817 	SwNewDBMgr* pMgr = GetNewDBMgr();
1818 
1819 	const SwDSParamArr& rArr = pMgr->GetDSParamArray();
1820 	for(sal_uInt16 i = 0; i < rArr.Count(); i++)
1821 	{
1822 		SwDSParam* pParam = rArr[i];
1823 		String* pStr = new String( pParam->sDataSource );
1824 		(*pStr)	+= DB_DELIM;
1825         (*pStr) += (String)pParam->sCommand;
1826 		rAllDBNames.Insert( pStr, rAllDBNames.Count() );
1827 	}
1828 }
1829 
1830 /*--------------------------------------------------------------------
1831 	Beschreibung:
1832  --------------------------------------------------------------------*/
1833 
1834 SvStringsDtor& SwDoc::FindUsedDBs( const SvStringsDtor& rAllDBNames,
1835 									const String& rFormel,
1836 									SvStringsDtor& rUsedDBNames )
1837 {
1838 	const CharClass& rCC = GetAppCharClass();
1839 	String 	sFormel( rFormel);
1840 #ifndef UNX
1841 	rCC.toUpper( sFormel );
1842 #endif
1843 
1844 	xub_StrLen nPos;
1845 	for (sal_uInt16 i = 0; i < rAllDBNames.Count(); ++i )
1846 	{
1847 		const String* pStr = rAllDBNames.GetObject(i);
1848 
1849 		if( STRING_NOTFOUND != (nPos = sFormel.Search( *pStr )) &&
1850 			sFormel.GetChar( nPos + pStr->Len() ) == '.' &&
1851 			(!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 )))
1852 		{
1853 			// Tabellenname suchen
1854 			xub_StrLen nEndPos;
1855 			nPos += pStr->Len() + 1;
1856 			if( STRING_NOTFOUND != (nEndPos = sFormel.Search('.', nPos)) )
1857 			{
1858 				String* pDBNm = new String( *pStr );
1859 				pDBNm->Append( DB_DELIM );
1860 				pDBNm->Append( sFormel.Copy( nPos, nEndPos - nPos ));
1861 				rUsedDBNames.Insert( pDBNm, rUsedDBNames.Count() );
1862 			}
1863 		}
1864 	}
1865 	return rUsedDBNames;
1866 }
1867 
1868 /*--------------------------------------------------------------------
1869 	Beschreibung:
1870  --------------------------------------------------------------------*/
1871 
1872 void SwDoc::AddUsedDBToList( SvStringsDtor& rDBNameList,
1873 							 const SvStringsDtor& rUsedDBNames )
1874 {
1875 	for (sal_uInt16 i = 0; i < rUsedDBNames.Count(); i++)
1876 		AddUsedDBToList( rDBNameList, *rUsedDBNames.GetObject(i) );
1877 }
1878 
1879 /*--------------------------------------------------------------------
1880 	Beschreibung:
1881  --------------------------------------------------------------------*/
1882 
1883 void SwDoc::AddUsedDBToList( SvStringsDtor& rDBNameList, const String& rDBName)
1884 {
1885 	if( !rDBName.Len() )
1886 		return;
1887 
1888 #ifdef UNX
1889 	for( sal_uInt16 i = 0; i < rDBNameList.Count(); ++i )
1890 		if( rDBName == rDBNameList.GetObject(i)->GetToken(0) )
1891 			return;
1892 #else
1893 	const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
1894 	for( sal_uInt16 i = 0; i < rDBNameList.Count(); ++i )
1895 		if( rSCmp.isEqual( rDBName, rDBNameList.GetObject(i)->GetToken(0) ) )
1896 			return;
1897 #endif
1898 
1899     SwDBData aData;
1900     aData.sDataSource = rDBName.GetToken(0, DB_DELIM);
1901     aData.sCommand = rDBName.GetToken(1, DB_DELIM);
1902     aData.nCommandType = -1;
1903     GetNewDBMgr()->CreateDSData(aData);
1904 	String* pNew = new String( rDBName );
1905 	rDBNameList.Insert( pNew, rDBNameList.Count() );
1906 }
1907 
1908 /*--------------------------------------------------------------------
1909 	 Beschreibung:
1910  --------------------------------------------------------------------*/
1911 
1912 void SwDoc::ChangeDBFields( const SvStringsDtor& rOldNames,
1913 							const String& rNewName )
1914 {
1915 	SwDBData aNewDBData;
1916 	aNewDBData.sDataSource = rNewName.GetToken(0, DB_DELIM);
1917 	aNewDBData.sCommand = rNewName.GetToken(1, DB_DELIM);
1918 	aNewDBData.nCommandType = (short)rNewName.GetToken(2, DB_DELIM).ToInt32();
1919 
1920 	String sFormel;
1921 
1922 	SwSectionFmts& rArr = GetSections();
1923     for (sal_uInt16 n = rArr.Count(); n; )
1924 	{
1925 		SwSection* pSect = rArr[ --n ]->GetSection();
1926 
1927 		if( pSect )
1928 		{
1929 			sFormel = pSect->GetCondition();
1930 			ReplaceUsedDBs( rOldNames, rNewName, sFormel);
1931 			pSect->SetCondition(sFormel);
1932 		}
1933 	}
1934 
1935 	const SfxPoolItem* pItem;
1936 	sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
1937 
1938     for (sal_uInt32 n = 0; n < nMaxItems; ++n )
1939 	{
1940 		if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) ))
1941 			continue;
1942 
1943 		SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
1944 		SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1945 		if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
1946 			continue;
1947 
1948 		SwField* pFld = pFmtFld->GetField();
1949 		sal_Bool bExpand = sal_False;
1950 
1951 		switch( pFld->GetTyp()->Which() )
1952 		{
1953 			case RES_DBFLD:
1954 				if( IsNameInArray( rOldNames, lcl_DBDataToString(((SwDBField*)pFld)->GetDBData())))
1955 				{
1956 					SwDBFieldType* pOldTyp = (SwDBFieldType*)pFld->GetTyp();
1957 
1958 					SwDBFieldType* pTyp = (SwDBFieldType*)InsertFldType(
1959 							SwDBFieldType(this, pOldTyp->GetColumnName(), aNewDBData));
1960 
1961                     pFmtFld->RegisterToFieldType( *pTyp );
1962 					pFld->ChgTyp(pTyp);
1963 
1964 					((SwDBField*)pFld)->ClearInitialized();
1965 					((SwDBField*)pFld)->InitContent();
1966 
1967 					bExpand = sal_True;
1968 				}
1969 				break;
1970 
1971 			case RES_DBSETNUMBERFLD:
1972 			case RES_DBNAMEFLD:
1973 				if( IsNameInArray( rOldNames,
1974 								lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData())))
1975 				{
1976 					((SwDBNameInfField*)pFld)->SetDBData(aNewDBData);
1977 					bExpand = sal_True;
1978 				}
1979 				break;
1980 
1981 			case RES_DBNUMSETFLD:
1982 			case RES_DBNEXTSETFLD:
1983 				if( IsNameInArray( rOldNames,
1984 								lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData())))
1985 				{
1986 					((SwDBNameInfField*)pFld)->SetDBData(aNewDBData);
1987 					bExpand = sal_True;
1988 				}
1989 				// kein break;
1990 			case RES_HIDDENTXTFLD:
1991 			case RES_HIDDENPARAFLD:
1992 				sFormel = pFld->GetPar1();
1993 				ReplaceUsedDBs( rOldNames, rNewName, sFormel);
1994 				pFld->SetPar1( sFormel );
1995 				bExpand = sal_True;
1996 				break;
1997 
1998 			case RES_SETEXPFLD:
1999 			case RES_GETEXPFLD:
2000 			case RES_TABLEFLD:
2001 				sFormel = pFld->GetFormula();
2002 				ReplaceUsedDBs( rOldNames, rNewName, sFormel);
2003 				pFld->SetPar2( sFormel );
2004 				bExpand = sal_True;
2005 				break;
2006 		}
2007 
2008 		if (bExpand)
2009 			pTxtFld->ExpandAlways();
2010 	}
2011 	SetModified();
2012 }
2013 
2014 /*--------------------------------------------------------------------
2015 	Beschreibung:
2016  --------------------------------------------------------------------*/
2017 
2018 void SwDoc::ReplaceUsedDBs( const SvStringsDtor& rUsedDBNames,
2019 							const String& rNewName, String& rFormel )
2020 {
2021 	const CharClass& rCC = GetAppCharClass();
2022 	String 	sFormel(rFormel);
2023 	String	sNewName( rNewName );
2024 	sNewName.SearchAndReplace( DB_DELIM, '.');
2025 	//the command type is not part of the condition
2026 	sNewName = sNewName.GetToken(0, DB_DELIM);
2027 	String sUpperNewNm( sNewName );
2028 
2029 
2030 	for( sal_uInt16 i = 0; i < rUsedDBNames.Count(); ++i )
2031 	{
2032 		String	sDBName( *rUsedDBNames.GetObject( i ) );
2033 
2034 		sDBName.SearchAndReplace( DB_DELIM, '.');
2035 		//cut off command type
2036 		sDBName = sDBName.GetToken(0, DB_DELIM);
2037 		if( !sDBName.Equals( sUpperNewNm ))
2038 		{
2039 			xub_StrLen nPos = 0;
2040 
2041 			while ((nPos = sFormel.Search(sDBName, nPos)) != STRING_NOTFOUND)
2042 			{
2043 				if( sFormel.GetChar( nPos + sDBName.Len() ) == '.' &&
2044 					(!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 )))
2045 				{
2046 					rFormel.Erase( nPos, sDBName.Len() );
2047 					rFormel.Insert( sNewName, nPos );
2048 					//prevent re-searching - this is useless and provokes
2049 					//endless loops when names containing each other and numbers are exchanged
2050 					//e.g.: old ?12345.12345  new: i12345.12345
2051 					nPos = nPos + sNewName.Len();
2052 					sFormel = rFormel;
2053 				}
2054 			}
2055 		}
2056 	}
2057 }
2058 
2059 /*--------------------------------------------------------------------
2060 	 Beschreibung:
2061  --------------------------------------------------------------------*/
2062 
2063 sal_Bool SwDoc::IsNameInArray( const SvStringsDtor& rArr, const String& rName )
2064 {
2065 #ifdef UNX
2066 	for( sal_uInt16 i = 0; i < rArr.Count(); ++i )
2067 		if( rName == *rArr[ i ] )
2068 			return sal_True;
2069 #else
2070 	const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
2071 	for( sal_uInt16 i = 0; i < rArr.Count(); ++i )
2072 		if( rSCmp.isEqual( rName, *rArr[ i] ))
2073 			return sal_True;
2074 #endif
2075 	return sal_False;
2076 }
2077 
2078 void SwDoc::SetFixFields( bool bOnlyTimeDate, const DateTime* pNewDateTime )
2079 {
2080 	sal_Bool bIsModified = IsModified();
2081 
2082 	sal_uLong nDate, nTime;
2083 	if( pNewDateTime )
2084 	{
2085 		nDate = pNewDateTime->GetDate();
2086 		nTime = pNewDateTime->GetTime();
2087 	}
2088 	else
2089 	{
2090 		nDate = Date().GetDate();
2091 		nTime = Time().GetTime();
2092 	}
2093 
2094 	sal_uInt16 aTypes[5] = {
2095 		/*0*/	RES_DOCINFOFLD,
2096 		/*1*/	RES_AUTHORFLD,
2097 		/*2*/	RES_EXTUSERFLD,
2098 		/*3*/	RES_FILENAMEFLD,
2099 		/*4*/	RES_DATETIMEFLD };	// MUSS am Ende stehen!!
2100 
2101 	sal_uInt16 nStt = bOnlyTimeDate ? 4 : 0;
2102 
2103 	for( ; nStt < 5; ++nStt )
2104 	{
2105 		SwFieldType* pFldType = GetSysFldType( aTypes[ nStt ] );
2106 		SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
2107 		for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
2108 		{
2109 			if( pFmtFld && pFmtFld->GetTxtFld() )
2110 			{
2111 				sal_Bool bChgd = sal_False;
2112 				switch( aTypes[ nStt ] )
2113 				{
2114 				case RES_DOCINFOFLD:
2115 					if( ((SwDocInfoField*)pFmtFld->GetField())->IsFixed() )
2116 					{
2117 						bChgd = sal_True;
2118 						SwDocInfoField* pDocInfFld = (SwDocInfoField*)pFmtFld->GetField();
2119 						pDocInfFld->SetExpansion( ((SwDocInfoFieldType*)
2120 									pDocInfFld->GetTyp())->Expand(
2121 										pDocInfFld->GetSubType(),
2122 										pDocInfFld->GetFormat(),
2123 										pDocInfFld->GetLanguage(),
2124 										pDocInfFld->GetName() ) );
2125 					}
2126 					break;
2127 
2128 				case RES_AUTHORFLD:
2129 					if( ((SwAuthorField*)pFmtFld->GetField())->IsFixed() )
2130 					{
2131 						bChgd = sal_True;
2132 						SwAuthorField* pAuthorFld = (SwAuthorField*)pFmtFld->GetField();
2133 						pAuthorFld->SetExpansion( ((SwAuthorFieldType*)
2134 									pAuthorFld->GetTyp())->Expand(
2135 												pAuthorFld->GetFormat() ) );
2136 					}
2137 					break;
2138 
2139 				case RES_EXTUSERFLD:
2140 					if( ((SwExtUserField*)pFmtFld->GetField())->IsFixed() )
2141 					{
2142 						bChgd = sal_True;
2143 						SwExtUserField* pExtUserFld = (SwExtUserField*)pFmtFld->GetField();
2144 						pExtUserFld->SetExpansion( ((SwExtUserFieldType*)
2145 									pExtUserFld->GetTyp())->Expand(
2146 											pExtUserFld->GetSubType(),
2147 											pExtUserFld->GetFormat()));
2148 					}
2149 					break;
2150 
2151 				case RES_DATETIMEFLD:
2152 					if( ((SwDateTimeField*)pFmtFld->GetField())->IsFixed() )
2153 					{
2154 						bChgd = sal_True;
2155 						((SwDateTimeField*)pFmtFld->GetField())->SetDateTime(
2156                                                     DateTime(Date(nDate), Time(nTime)) );
2157 					}
2158 					break;
2159 
2160 				case RES_FILENAMEFLD:
2161 					if( ((SwFileNameField*)pFmtFld->GetField())->IsFixed() )
2162 					{
2163 						bChgd = sal_True;
2164 						SwFileNameField* pFileNameFld =
2165 							(SwFileNameField*)pFmtFld->GetField();
2166 						pFileNameFld->SetExpansion( ((SwFileNameFieldType*)
2167 									pFileNameFld->GetTyp())->Expand(
2168 											pFileNameFld->GetFormat() ) );
2169 					}
2170 					break;
2171 				}
2172 
2173 				// Formatierung anstossen
2174 				if( bChgd )
2175 					pFmtFld->ModifyNotification( 0, 0 );
2176 			}
2177 		}
2178 	}
2179 
2180 	if( !bIsModified )
2181 		ResetModified();
2182 }
2183 
2184 bool SwDoc::SetFieldsDirty( bool b, const SwNode* pChk, sal_uLong nLen )
2185 {
2186 	// teste ggfs. mal, ob die angegbenen Nodes ueberhaupt Felder beinhalten.
2187 	// wenn nicht, braucht das Flag nicht veraendert werden.
2188 	sal_Bool bFldsFnd = sal_False;
2189 	if( b && pChk && !GetUpdtFlds().IsFieldsDirty() && !IsInDtor()
2190 		// ?? was ist mit Undo, da will man es doch auch haben !!
2191 		/*&& &pChk->GetNodes() == &GetNodes()*/ )
2192 	{
2193 		b = sal_False;
2194 		if( !nLen )
2195 			++nLen;
2196 		sal_uLong nStt = pChk->GetIndex();
2197 		const SwNodes& rNds = pChk->GetNodes();
2198 		while( nLen-- )
2199 		{
2200 			const SwTxtNode* pTNd = rNds[ nStt++ ]->GetTxtNode();
2201 			if( pTNd )
2202 			{
2203 				if( //pTNd->GetFmtColl() &&		//#outline level,zhaojianwei
2204 				//	MAXLEVEL > pTNd->GetTxtColl()->GetOutlineLevel() )
2205 					pTNd->GetAttrOutlineLevel() != 0 )//<-end,zhaojianwei
2206 					// Kapitelfelder aktualisieren
2207 					b = sal_True;
2208 				else if( pTNd->GetpSwpHints() && pTNd->GetSwpHints().Count() )
2209 					for( sal_uInt16 n = 0, nEnd = pTNd->GetSwpHints().Count();
2210 							n < nEnd; ++n )
2211 					{
2212 						const SwTxtAttr* pAttr = pTNd->GetSwpHints()[ n ];
2213 						if( RES_TXTATR_FIELD == pAttr->Which() )
2214 						{
2215 							b = sal_True;
2216 							break;
2217 						}
2218 					}
2219 
2220 				if( b )
2221 					break;
2222 			}
2223 		}
2224 		bFldsFnd = b;
2225 	}
2226 	GetUpdtFlds().SetFieldsDirty( b );
2227 	return bFldsFnd;
2228 }
2229 /* -----------------------------21.12.99 12:55--------------------------------
2230 
2231  ---------------------------------------------------------------------------*/
2232 void SwDoc::ChangeAuthorityData( const SwAuthEntry* pNewData )
2233 {
2234 	const sal_uInt16 nSize = pFldTypes->Count();
2235 
2236 	for( sal_uInt16 i = INIT_FLDTYPES; i < nSize; ++i )
2237 	{
2238 		SwFieldType* pFldType = (*pFldTypes)[i];
2239 		if( RES_AUTHORITY  == pFldType->Which() )
2240 		{
2241 			SwAuthorityFieldType* pAuthType = (SwAuthorityFieldType*)pFldType;
2242 			pAuthType->ChangeEntryContent(pNewData);
2243 			break;
2244 		}
2245 	}
2246 
2247 }
2248 /*--------------------------------------------------------------------
2249 	Beschreibung:
2250  --------------------------------------------------------------------*/
2251 
2252 void SwDocUpdtFld::InsDelFldInFldLst( sal_Bool bIns, const SwTxtFld& rFld )
2253 {
2254     const sal_uInt16 nWhich = rFld.GetFmtFld().GetField()->GetTyp()->Which();
2255 	switch( nWhich )
2256 	{
2257 	case RES_DBFLD:
2258 	case RES_SETEXPFLD:
2259 	case RES_HIDDENPARAFLD:
2260 	case RES_HIDDENTXTFLD:
2261 	case RES_DBNUMSETFLD:
2262 	case RES_DBNEXTSETFLD:
2263 	case RES_DBSETNUMBERFLD:
2264 	case RES_GETEXPFLD:
2265 		break;			// diese muessen ein-/ausgetragen werden!
2266 
2267 	default:
2268 		return;
2269 	}
2270 
2271 	SetFieldsDirty( sal_True );
2272 	if( !pFldSortLst )
2273 	{
2274 		if( !bIns ) 			// keine Liste vorhanden und loeschen
2275 			return; 			// dann nichts tun
2276 		pFldSortLst = new _SetGetExpFlds( 64, 16 );
2277 	}
2278 
2279 	if( bIns )		// neu einfuegen:
2280 		GetBodyNode( rFld, nWhich );
2281 	else
2282 	{
2283 		// ueber den pTxtFld Pointer suchen. Ist zwar eine Sortierte
2284 		// Liste, aber nach Node-Positionen sortiert. Bis dieser
2285 		// bestimmt ist, ist das Suchen nach dem Pointer schon fertig
2286 		for( sal_uInt16 n = 0; n < pFldSortLst->Count(); ++n )
2287 			if( &rFld == (*pFldSortLst)[ n ]->GetPointer() )
2288 				pFldSortLst->DeleteAndDestroy( n--, 1 );
2289 				// ein Feld kann mehrfach vorhanden sein!
2290 	}
2291 }
2292 
2293 void SwDocUpdtFld::MakeFldList( SwDoc& rDoc, int bAll, int eGetMode )
2294 {
2295     if( !pFldSortLst || bAll || !( eGetMode & nFldLstGetMode ) ||
2296         rDoc.GetNodes().Count() != nNodes )
2297         _MakeFldList( rDoc, eGetMode );
2298 }
2299 
2300 void SwDocUpdtFld::_MakeFldList( SwDoc& rDoc, int eGetMode )
2301 {
2302 	// neue Version: gehe ueber alle Felder vom Attribut-Pool
2303 	if( pFldSortLst )
2304 		delete pFldSortLst;
2305 	pFldSortLst = new _SetGetExpFlds( 64, 16 );
2306 
2307     /// OD 09.08.2002 [#101207#,#101216#,#101778#] - consider and unhide sections
2308     ///     with hide condition, only in mode GETFLD_ALL (<eGetMode == GETFLD_ALL>)
2309     ///     notes by OD:
2310     ///         eGetMode == GETFLD_CALC in call from methods SwDoc::FldsToCalc
2311     ///         eGetMode == GETFLD_EXPAND in call from method SwDoc::FldsToExpand
2312     ///         eGetMode == GETFLD_ALL in call from method SwDoc::UpdateExpFlds
2313     ///         I figured out that hidden section only have to be shown,
2314     ///         if fields have updated (call by SwDoc::UpdateExpFlds) and thus
2315     ///         the hide conditions of section have to be updated.
2316     ///         For correct updating the hide condition of a section, its position
2317     ///         have to be known in order to insert the hide condition as a new
2318     ///         expression field into the sorted field list (<pFldSortLst>).
2319     if ( eGetMode == GETFLD_ALL )
2320 	// zuerst die Bereiche einsammeln. Alle die ueber Bedingung
2321 	// gehiddet sind, wieder mit Frames versorgen, damit die darin
2322 	// enthaltenen Felder richtig einsortiert werden!!!
2323     {
2324 		// damit die Frames richtig angelegt werden, muessen sie in der
2325 		// Reihenfolgen von oben nach unten expandiert werden
2326 		SvULongs aTmpArr;
2327 		SwSectionFmts& rArr = rDoc.GetSections();
2328 		SwSectionNode* pSectNd;
2329 		sal_uInt16 nArrStt = 0;
2330 		sal_uLong nSttCntnt = rDoc.GetNodes().GetEndOfExtras().GetIndex();
2331 
2332         for (sal_uInt16 n = rArr.Count(); n; )
2333 		{
2334 			SwSection* pSect = rArr[ --n ]->GetSection();
2335             if( pSect && pSect->IsHidden() && pSect->GetCondition().Len() &&
2336 				0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() ))
2337 			{
2338 				sal_uLong nIdx = pSectNd->GetIndex();
2339 				sal_uInt16 i;
2340 
2341 				for( i = 0; i < aTmpArr.Count() && aTmpArr[ i ] < nIdx; ++i )
2342 					;
2343 				aTmpArr.Insert( nIdx, i );
2344 				if( nIdx < nSttCntnt )
2345 					++nArrStt;
2346 			}
2347 		}
2348 
2349         // erst alle anzeigen, damit die Frames vorhanden sind. Mit deren
2350         // Position wird das BodyAnchor ermittelt.
2351         // Dafuer erst den ContentBereich, dann die Sonderbereiche!!!
2352         for (sal_uInt16 n = nArrStt; n < aTmpArr.Count(); ++n)
2353         {
2354             pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
2355             ASSERT( pSectNd, "Wo ist mein SectionNode" );
2356             pSectNd->GetSection().SetCondHidden( sal_False );
2357         }
2358         for (sal_uInt16 n = 0; n < nArrStt; ++n)
2359         {
2360             pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
2361             ASSERT( pSectNd, "Wo ist mein SectionNode" );
2362             pSectNd->GetSection().SetCondHidden( sal_False );
2363         }
2364 
2365         // so, erst jetzt alle sortiert in die Liste eintragen
2366         for (sal_uInt16 n = 0; n < aTmpArr.Count(); ++n)
2367         {
2368             GetBodyNode( *rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode() );
2369         }
2370     }
2371 
2372 	String sTrue( String::CreateFromAscii(
2373 									RTL_CONSTASCII_STRINGPARAM( "sal_True" ))),
2374 		   sFalse( String::CreateFromAscii(
2375 		   							RTL_CONSTASCII_STRINGPARAM( "sal_False" )));
2376 
2377 	sal_Bool bIsDBMgr = 0 != rDoc.GetNewDBMgr();
2378 	sal_uInt16 nWhich, n;
2379 	const String* pFormel = 0;
2380 	const SfxPoolItem* pItem;
2381 	sal_uInt32 nMaxItems = rDoc.GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
2382 	for( n = 0; n < nMaxItems; ++n )
2383 	{
2384         if( 0 == (pItem = rDoc.GetAttrPool().GetItem2( RES_TXTATR_FIELD, n )) )
2385 			continue;
2386 
2387 		const SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
2388 		const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
2389 		if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
2390 			continue;
2391 
2392 		const SwField* pFld = pFmtFld->GetField();
2393 		switch( nWhich = pFld->GetTyp()->Which() )
2394 		{
2395 			case RES_DBSETNUMBERFLD:
2396 			case RES_GETEXPFLD:
2397 				if( GETFLD_ALL == eGetMode )
2398 					pFormel = &sTrue;
2399 				break;
2400 
2401 			case RES_DBFLD:
2402 				if( GETFLD_EXPAND & eGetMode )
2403 					pFormel = &sTrue;
2404 				break;
2405 
2406 			case RES_SETEXPFLD:
2407                 /// fields of subtype <string> have also been add
2408                 /// for calculation (eGetMode == GETFLD_CALC).
2409                 /// Thus, add fields of subtype <string> in all modes
2410                 ///     (eGetMode == GETFLD_EXPAND||GETFLD_CALC||GETFLD_ALL)
2411                 /// and fields of other subtypes only in the modes
2412                 ///     (eGetMode == GETFLD_CALC||GETFLD_ALL)
2413                 /* "old" if construct - not deleted for history and code review
2414                 if( ( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType()
2415                         ? GETFLD_EXPAND : GETFLD_CALC )
2416                         & eGetMode )
2417                 */
2418                 if ( !(eGetMode == GETFLD_EXPAND) ||
2419                      (nsSwGetSetExpType::GSE_STRING & pFld->GetSubType()) )
2420                 {
2421 					pFormel = &sTrue;
2422                 }
2423 				break;
2424 
2425 			case RES_HIDDENPARAFLD:
2426 				if( GETFLD_ALL == eGetMode )
2427 				{
2428 					pFormel = &pFld->GetPar1();
2429 					if( !pFormel->Len() || pFormel->Equals( sFalse ))
2430 						((SwHiddenParaField*)pFld)->SetHidden( sal_False );
2431 					else if( pFormel->Equals( sTrue ))
2432 						((SwHiddenParaField*)pFld)->SetHidden( sal_True );
2433 					else
2434 						break;
2435 
2436 					pFormel = 0;
2437 					// Formatierung anstossen
2438 					((SwFmtFld*)pFmtFld)->ModifyNotification( 0, 0 );
2439 				}
2440 				break;
2441 
2442 			case RES_HIDDENTXTFLD:
2443 				if( GETFLD_ALL == eGetMode )
2444 				{
2445 					pFormel = &pFld->GetPar1();
2446 					if( !pFormel->Len() || pFormel->Equals( sFalse ))
2447 						((SwHiddenTxtField*)pFld)->SetValue( sal_True );
2448 					else if( pFormel->Equals( sTrue ))
2449 						((SwHiddenTxtField*)pFld)->SetValue( sal_False );
2450 					else
2451 						break;
2452 
2453 					pFormel = 0;
2454 
2455 					// Feld Evaluieren
2456 					((SwHiddenTxtField*)pFld)->Evaluate(&rDoc);
2457 					// Formatierung anstossen
2458 					((SwFmtFld*)pFmtFld)->ModifyNotification( 0, 0 );
2459 				}
2460 				break;
2461 
2462 			case RES_DBNUMSETFLD:
2463 			{
2464 				SwDBData aDBData(((SwDBNumSetField*)pFld)->GetDBData(&rDoc));
2465 
2466                 if (
2467                      (bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) &&
2468                      (GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNumSetField*)pFld)->IsCondValid()))
2469                    )
2470                 {
2471                     pFormel = &pFld->GetPar1();
2472                 }
2473 			}
2474 			break;
2475 			case RES_DBNEXTSETFLD:
2476 			{
2477 				SwDBData aDBData(((SwDBNextSetField*)pFld)->GetDBData(&rDoc));
2478 
2479                 if (
2480                      (bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) &&
2481                      (GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNextSetField*)pFld)->IsCondValid()))
2482                    )
2483                 {
2484                     pFormel = &pFld->GetPar1();
2485                 }
2486 			}
2487 			break;
2488 		}
2489 
2490 		if( pFormel && pFormel->Len() )
2491 		{
2492 			GetBodyNode( *pTxtFld, nWhich );
2493 			pFormel = 0;
2494 		}
2495 	}
2496 	nFldLstGetMode = static_cast<sal_uInt8>( eGetMode );
2497 	nNodes = rDoc.GetNodes().Count();
2498 
2499 #ifdef JP_DEBUG
2500 	{
2501 	SvFileStream sOut( "f:\\x.x", STREAM_STD_WRITE );
2502 	sOut.Seek( STREAM_SEEK_TO_END );
2503 	sOut << "------------------" << endl;
2504 	const _SetGetExpFldPtr* pSortLst = pFldSortLst->GetData();
2505 	for( sal_uInt16 n = pFldSortLst->Count(); n; --n, ++pSortLst )
2506 	{
2507 		String sStr( (*pSortLst)->GetNode() );
2508 		sStr += "\t, ";
2509 		sStr += (*pSortLst)->GetCntnt();
2510 		sStr += "\tNode: ";
2511 		sStr += (*pSortLst)->GetFld()->GetTxtNode().StartOfSectionIndex();
2512 		sStr += "\tPos: ";
2513 		sStr += *(*pSortLst)->GetFld()->GetStart();
2514 		sStr += "\tType: ";
2515 		sStr += (*pSortLst)->GetFld()->GetFld().GetFld()->GetTyp()->Which();
2516 
2517 		sOut << sStr.GetStr() << endl;
2518 	}
2519 	}
2520 #endif
2521 	// JP_DEBUG
2522 }
2523 
2524 /*--------------------------------------------------------------------
2525 	Beschreibung:
2526  --------------------------------------------------------------------*/
2527 
2528 void SwDocUpdtFld::GetBodyNode( const SwTxtFld& rTFld, sal_uInt16 nFldWhich )
2529 {
2530 	const SwTxtNode& rTxtNd = rTFld.GetTxtNode();
2531 	const SwDoc& rDoc = *rTxtNd.GetDoc();
2532 
2533 	// immer den ersten !! (in Tab-Headline, Kopf-/Fuss )
2534 	Point aPt;
2535 	const SwCntntFrm* pFrm = rTxtNd.getLayoutFrm( rDoc.GetCurrentLayout(), &aPt, 0, sal_False );
2536 
2537     _SetGetExpFld* pNew = NULL;
2538 	sal_Bool bIsInBody = sal_False;
2539 
2540 	if( !pFrm || pFrm->IsInDocBody() )
2541 	{
2542 		// einen Index fuers bestimmen vom TextNode anlegen
2543 		SwNodeIndex aIdx( rTxtNd );
2544 		bIsInBody = rDoc.GetNodes().GetEndOfExtras().GetIndex() < aIdx.GetIndex();
2545 
2546         // #104291# dvo: We don't want to update fields in redlines, or those
2547         // in frames whose anchor is in redline. However, we do want to update
2548         // fields in hidden sections. So: In order to be updated, a field 1)
2549         // must have a frame, or 2) it must be in the document body.
2550         if( (pFrm != NULL) || bIsInBody )
2551             pNew = new _SetGetExpFld( aIdx, &rTFld );
2552 	}
2553 	else
2554 	{
2555 		// einen Index fuers bestimmen vom TextNode anlegen
2556 		SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() );
2557 #ifdef DBG_UTIL
2558 		ASSERT( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" );
2559 #else
2560 		GetBodyTxtNode( rDoc, aPos, *pFrm );
2561 #endif
2562 		pNew = new _SetGetExpFld( aPos.nNode, &rTFld, &aPos.nContent );
2563 	}
2564 
2565 	// bei GetExp.-/DB.-Felder immer das BodyTxtFlag setzen
2566 	if( RES_GETEXPFLD == nFldWhich )
2567 	{
2568 		SwGetExpField* pGetFld = (SwGetExpField*)rTFld.GetFmtFld().GetField();
2569 		pGetFld->ChgBodyTxtFlag( bIsInBody );
2570 	}
2571 	else if( RES_DBFLD == nFldWhich )
2572 	{
2573 		SwDBField* pDBFld = (SwDBField*)rTFld.GetFmtFld().GetField();
2574 		pDBFld->ChgBodyTxtFlag( bIsInBody );
2575 	}
2576 
2577     if( pNew != NULL )
2578         if( !pFldSortLst->Insert( pNew ))
2579             delete pNew;
2580 }
2581 
2582 void SwDocUpdtFld::GetBodyNode( const SwSectionNode& rSectNd )
2583 {
2584 	const SwDoc& rDoc = *rSectNd.GetDoc();
2585 	_SetGetExpFld* pNew = 0;
2586 
2587 	if( rSectNd.GetIndex() < rDoc.GetNodes().GetEndOfExtras().GetIndex() )
2588 	{
2589 		do {			// middle check loop
2590 
2591 			// dann muessen wir uns mal den Anker besorgen!
2592 			// einen Index fuers bestimmen vom TextNode anlegen
2593 			SwPosition aPos( rSectNd );
2594 			SwCntntNode* pCNd = rDoc.GetNodes().GoNext( &aPos.nNode ); // zum naechsten ContentNode
2595 
2596 			if( !pCNd || !pCNd->IsTxtNode() )
2597 				break;
2598 
2599 			// immer den ersten !! (in Tab-Headline, Kopf-/Fuss )
2600 			Point aPt;
2601 			const SwCntntFrm* pFrm = pCNd->getLayoutFrm( rDoc.GetCurrentLayout(), &aPt, 0, sal_False );
2602 			if( !pFrm )
2603 				break;
2604 
2605 #ifdef DBG_UTIL
2606 			ASSERT( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" );
2607 #else
2608 			GetBodyTxtNode( rDoc, aPos, *pFrm );
2609 #endif
2610 			pNew = new _SetGetExpFld( rSectNd, &aPos );
2611 
2612 		} while( sal_False );
2613 	}
2614 
2615 	if( !pNew )
2616 		pNew = new _SetGetExpFld( rSectNd );
2617 
2618 	if( !pFldSortLst->Insert( pNew ))
2619 		delete pNew;
2620 }
2621 
2622 void SwDocUpdtFld::InsertFldType( const SwFieldType& rType )
2623 {
2624 	String sFldName;
2625 	switch( rType.Which() )
2626 	{
2627 	case RES_USERFLD :
2628 		sFldName = ((SwUserFieldType&)rType).GetName();
2629 		break;
2630 	case RES_SETEXPFLD:
2631 		sFldName = ((SwSetExpFieldType&)rType).GetName();
2632 		break;
2633 	default:
2634 		ASSERT( !this, "kein gueltiger FeldTyp" );
2635 	}
2636 
2637 	if( sFldName.Len() )
2638 	{
2639 		SetFieldsDirty( sal_True );
2640 		// suchen und aus der HashTabelle entfernen
2641 		GetAppCharClass().toLower( sFldName );
2642 		sal_uInt16 n;
2643 
2644 		SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n );
2645 
2646 		if( !pFnd )
2647 		{
2648 			SwCalcFldType* pNew = new SwCalcFldType( sFldName, &rType );
2649 			pNew->pNext = aFldTypeTable[ n ];
2650 			aFldTypeTable[ n ] = pNew;
2651 		}
2652 	}
2653 }
2654 
2655 void SwDocUpdtFld::RemoveFldType( const SwFieldType& rType )
2656 {
2657 	String sFldName;
2658 	switch( rType.Which() )
2659 	{
2660 	case RES_USERFLD :
2661 		sFldName = ((SwUserFieldType&)rType).GetName();
2662 		break;
2663 	case RES_SETEXPFLD:
2664 		sFldName = ((SwSetExpFieldType&)rType).GetName();
2665 		break;
2666 	}
2667 
2668 	if( sFldName.Len() )
2669 	{
2670 		SetFieldsDirty( sal_True );
2671 		// suchen und aus der HashTabelle entfernen
2672 		GetAppCharClass().toLower( sFldName );
2673 		sal_uInt16 n;
2674 
2675 		SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n );
2676 		if( pFnd )
2677 		{
2678 			if( aFldTypeTable[ n ] == pFnd )
2679 				aFldTypeTable[ n ] = (SwCalcFldType*)pFnd->pNext;
2680 			else
2681 			{
2682 				SwHash* pPrev = aFldTypeTable[ n ];
2683 				while( pPrev->pNext != pFnd )
2684 					pPrev = pPrev->pNext;
2685 				pPrev->pNext = pFnd->pNext;
2686 			}
2687 			pFnd->pNext = 0;
2688 			delete pFnd;
2689 		}
2690 	}
2691 }
2692 
2693 SwDocUpdtFld::SwDocUpdtFld()
2694 	: pFldSortLst(0),  nFldUpdtPos(LONG_MAX), nFldLstGetMode(0)
2695 {
2696 	bInUpdateFlds = bFldsDirty = sal_False;
2697 	memset( aFldTypeTable, 0, sizeof( aFldTypeTable ) );
2698 }
2699 
2700 SwDocUpdtFld::~SwDocUpdtFld()
2701 {
2702 	delete pFldSortLst;
2703 
2704 	for( sal_uInt16 n = 0; n < TBLSZ; ++n )
2705 		delete aFldTypeTable[n];
2706 }
2707 
2708 // #111840#
2709 bool SwDoc::UpdateFld(SwTxtFld * pDstTxtFld, SwField & rSrcFld,
2710                       SwMsgPoolItem * pMsgHnt,
2711                       bool bUpdateFlds)
2712 {
2713     ASSERT(pDstTxtFld, "no field to update!");
2714 
2715     sal_Bool bTblSelBreak = sal_False;
2716 
2717     SwFmtFld * pDstFmtFld = (SwFmtFld*)&pDstTxtFld->GetFmtFld();
2718     SwField * pDstFld = pDstFmtFld->GetField();
2719     sal_uInt16 nFldWhich = rSrcFld.GetTyp()->Which();
2720     SwNodeIndex aTblNdIdx(pDstTxtFld->GetTxtNode());
2721 
2722     if (pDstFld->GetTyp()->Which() ==
2723         rSrcFld.GetTyp()->Which())
2724     {
2725         if (GetIDocumentUndoRedo().DoesUndo())
2726         {
2727             SwPosition aPosition( pDstTxtFld->GetTxtNode() );
2728             aPosition.nContent = *pDstTxtFld->GetStart();
2729 
2730             SwUndo *const pUndo( new SwUndoFieldFromDoc( aPosition, *pDstFld, rSrcFld, pMsgHnt, bUpdateFlds) );
2731             GetIDocumentUndoRedo().AppendUndo(pUndo);
2732         }
2733 
2734         SwField * pNewFld = rSrcFld.CopyField();
2735         pDstFmtFld->SetField(pNewFld);
2736 
2737         switch( nFldWhich )
2738         {
2739         case RES_SETEXPFLD:
2740         case RES_GETEXPFLD:
2741         case RES_HIDDENTXTFLD:
2742         case RES_HIDDENPARAFLD:
2743             UpdateExpFlds( pDstTxtFld, true );
2744             break;
2745 
2746         case RES_TABLEFLD:
2747             {
2748                 const SwTableNode* pTblNd =
2749                     IsIdxInTbl(aTblNdIdx);
2750                 if( pTblNd )
2751                 {
2752                     SwTableFmlUpdate aTblUpdate( &pTblNd->
2753                                                  GetTable() );
2754                     if (bUpdateFlds)
2755                         UpdateTblFlds( &aTblUpdate );
2756                     else
2757                         pNewFld->GetTyp()->ModifyNotification(0, &aTblUpdate);
2758 
2759                     if (! bUpdateFlds)
2760                         bTblSelBreak = sal_True;
2761                 }
2762             }
2763             break;
2764 
2765         case RES_MACROFLD:
2766             if( bUpdateFlds && pDstTxtFld->GetpTxtNode() )
2767                 (pDstTxtFld->GetpTxtNode())->
2768                     ModifyNotification( 0, pDstFmtFld );
2769             break;
2770 
2771         case RES_DBNAMEFLD:
2772         case RES_DBNEXTSETFLD:
2773         case RES_DBNUMSETFLD:
2774         case RES_DBSETNUMBERFLD:
2775             ChgDBData(((SwDBNameInfField*) pNewFld)->GetRealDBData());
2776             pNewFld->GetTyp()->UpdateFlds();
2777 
2778             break;
2779 
2780         case RES_DBFLD:
2781             {
2782                 // JP 10.02.96: ChgValue aufrufen, damit
2783                 //die Format- aenderung den ContentString
2784                 //richtig setzt
2785                 SwDBField* pDBFld = (SwDBField*)pNewFld;
2786                 if (pDBFld->IsInitialized())
2787                     pDBFld->ChgValue( pDBFld->GetValue(), sal_True );
2788 
2789                 pDBFld->ClearInitialized();
2790                 pDBFld->InitContent();
2791             }
2792             // kein break;
2793 
2794         default:
2795             pDstFmtFld->ModifyNotification( 0, pMsgHnt );
2796         }
2797 
2798         // Die Felder die wir berechnen koennen werden hier expli.
2799         // zum Update angestossen.
2800         if( nFldWhich == RES_USERFLD )
2801             UpdateUsrFlds();
2802     }
2803 
2804     return bTblSelBreak;
2805 }
2806 
2807 bool SwDoc::PutValueToField(const SwPosition & rPos,
2808                             const Any& rVal, sal_uInt16 nWhich)
2809 {
2810     Any aOldVal;
2811     SwField * pField = GetFieldAtPos(rPos);
2812 
2813 
2814     if (GetIDocumentUndoRedo().DoesUndo() &&
2815         pField->QueryValue(aOldVal, nWhich))
2816     {
2817         SwUndo *const pUndo(new SwUndoFieldFromAPI(rPos, aOldVal, rVal, nWhich));
2818         GetIDocumentUndoRedo().AppendUndo(pUndo);
2819     }
2820 
2821     return pField->PutValue(rVal, nWhich);
2822 }
2823