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