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