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