xref: /trunk/main/sw/source/core/doc/docfld.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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