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