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