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