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