Impress Remote 1.0.5, tag sdremote-1.0.5
[LibreOffice.git] / sw / source / core / doc / docfld.cxx
blobc2d1dbc063e52455c7de1ea1a45395c5938a973d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <hintids.hxx>
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
59 #include <SwUndoField.hxx>
60 #include "switerator.hxx"
62 using namespace ::com::sun::star::uno;
64 extern bool IsFrameBehind( const SwTxtNode& rMyNd, sal_uInt16 nMySttPos,
65 const SwTxtNode& rBehindNd, sal_uInt16 nSttPos );
67 /*--------------------------------------------------------------------
68 Description: Insert field types
69 --------------------------------------------------------------------*/
71 * Implementation of field methods at the Doc
72 * Always returns a pointer to the type, if it's new or already added.
74 SwFieldType* SwDoc::InsertFldType(const SwFieldType &rFldTyp)
76 sal_uInt16 nSize = pFldTypes->size(),
77 nFldWhich = rFldTyp.Which();
79 sal_uInt16 i = INIT_FLDTYPES;
81 switch( nFldWhich )
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 if( nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType&)rFldTyp).GetType() )
89 i -= INIT_SEQ_FLDTYPES;
90 // no break;
91 case RES_DBFLD:
92 case RES_USERFLD:
93 case RES_DDEFLD:
95 const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
96 String sFldNm( rFldTyp.GetName() );
97 for( ; i < nSize; ++i )
98 if( nFldWhich == (*pFldTypes)[i]->Which() &&
99 rSCmp.isEqual( sFldNm, (*pFldTypes)[i]->GetName() ))
100 return (*pFldTypes)[i];
102 break;
104 case RES_AUTHORITY:
105 for( ; i < nSize; ++i )
106 if( nFldWhich == (*pFldTypes)[i]->Which() )
107 return (*pFldTypes)[i];
108 break;
110 default:
111 for( i = 0; i < nSize; ++i )
112 if( nFldWhich == (*pFldTypes)[i]->Which() )
113 return (*pFldTypes)[i];
116 SwFieldType* pNew = rFldTyp.Copy();
117 switch( nFldWhich )
119 case RES_DDEFLD:
120 ((SwDDEFieldType*)pNew)->SetDoc( this );
121 break;
123 case RES_DBFLD:
124 case RES_TABLEFLD:
125 case RES_DATETIMEFLD:
126 case RES_GETEXPFLD:
127 ((SwValueFieldType*)pNew)->SetDoc( this );
128 break;
130 case RES_USERFLD:
131 case RES_SETEXPFLD:
132 ((SwValueFieldType*)pNew)->SetDoc( this );
133 // JP 29.07.96: Optionally prepare FieldList for Calculator:
134 pUpdtFlds->InsertFldType( *pNew );
135 break;
136 case RES_AUTHORITY :
137 ((SwAuthorityFieldType*)pNew)->SetDoc( this );
138 break;
141 pFldTypes->insert( pFldTypes->begin() + nSize, pNew );
142 SetModified();
144 return (*pFldTypes)[ nSize ];
147 void SwDoc::InsDeletedFldType( SwFieldType& rFldTyp )
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.
154 sal_uInt16 nSize = pFldTypes->size(), nFldWhich = rFldTyp.Which();
155 sal_uInt16 i = INIT_FLDTYPES;
157 OSL_ENSURE( RES_SETEXPFLD == nFldWhich ||
158 RES_USERFLD == nFldWhich ||
159 RES_DDEFLD == nFldWhich, "Wrong FldType" );
161 const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
162 const String& rFldNm = rFldTyp.GetName();
163 SwFieldType* pFnd;
165 for( ; i < nSize; ++i )
166 if( nFldWhich == (pFnd = (*pFldTypes)[i])->Which() &&
167 rSCmp.isEqual( rFldNm, pFnd->GetName() ) )
169 // find new name
170 sal_uInt16 nNum = 1;
171 do {
172 String sSrch( rFldNm );
173 sSrch.Append( String::CreateFromInt32( nNum ));
174 for( i = INIT_FLDTYPES; i < nSize; ++i )
175 if( nFldWhich == (pFnd = (*pFldTypes)[i])->Which() &&
176 rSCmp.isEqual( sSrch, pFnd->GetName() ) )
177 break;
179 if( i >= nSize ) // not found
181 ((String&)rFldNm) = sSrch;
182 break; // exit while loop
184 ++nNum;
185 } while( sal_True );
186 break;
189 // not found, so insert and delete flag
190 pFldTypes->insert( pFldTypes->begin() + nSize, &rFldTyp );
191 switch( nFldWhich )
193 case RES_SETEXPFLD:
194 ((SwSetExpFieldType&)rFldTyp).SetDeleted( sal_False );
195 break;
196 case RES_USERFLD:
197 ((SwUserFieldType&)rFldTyp).SetDeleted( sal_False );
198 break;
199 case RES_DDEFLD:
200 ((SwDDEFieldType&)rFldTyp).SetDeleted( sal_False );
201 break;
205 /*--------------------------------------------------------------------
206 Description: Remove field type
207 --------------------------------------------------------------------*/
208 void SwDoc::RemoveFldType(sal_uInt16 nFld)
210 OSL_ENSURE( INIT_FLDTYPES <= nFld, "don't remove InitFlds" );
212 * Dependent fields present -> ErrRaise
214 sal_uInt16 nSize = pFldTypes->size();
215 if(nFld < nSize)
217 SwFieldType* pTmp = (*pFldTypes)[nFld];
219 // JP 29.07.96: Optionally prepare FldLst for Calculator
220 sal_uInt16 nWhich = pTmp->Which();
221 switch( nWhich )
223 case RES_SETEXPFLD:
224 case RES_USERFLD:
225 pUpdtFlds->RemoveFldType( *pTmp );
226 // no break;
227 case RES_DDEFLD:
228 if( pTmp->GetDepends() && !IsUsed( *pTmp ) )
230 if( RES_SETEXPFLD == nWhich )
231 ((SwSetExpFieldType*)pTmp)->SetDeleted( sal_True );
232 else if( RES_USERFLD == nWhich )
233 ((SwUserFieldType*)pTmp)->SetDeleted( sal_True );
234 else
235 ((SwDDEFieldType*)pTmp)->SetDeleted( sal_True );
236 nWhich = 0;
238 break;
241 if( nWhich )
243 OSL_ENSURE( !pTmp->GetDepends(), "Dependent fields present!" );
244 // delete field type
245 delete pTmp;
247 pFldTypes->erase( pFldTypes->begin() + nFld );
248 SetModified();
252 const SwFldTypes* SwDoc::GetFldTypes() const
254 return pFldTypes;
257 /*--------------------------------------------------------------------
258 Description: Find first type with ResId and name
259 --------------------------------------------------------------------*/
260 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
266 sal_uInt16 nSize = pFldTypes->size(), i = 0;
267 const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
269 switch( nResId )
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 i = INIT_FLDTYPES - INIT_SEQ_FLDTYPES;
277 break;
279 case RES_DBFLD:
280 case RES_USERFLD:
281 case RES_DDEFLD:
282 case RES_AUTHORITY:
283 i = INIT_FLDTYPES;
284 break;
287 SwFieldType* pRet = 0;
288 for( ; i < nSize; ++i )
290 SwFieldType* pFldType = (*pFldTypes)[i];
292 String aFldName( pFldType->GetName() );
293 if (bDbFieldMatching && nResId == RES_DBFLD) // #i51815#
294 aFldName.SearchAndReplaceAll(DB_DELIM, '.');
296 if( nResId == pFldType->Which() &&
297 rSCmp.isEqual( rName, aFldName ))
299 pRet = pFldType;
300 break;
303 return pRet;
306 /*************************************************************************
307 |* SwDoc::UpdateFlds()
308 |* Description: Update fields
309 *************************************************************************/
311 * All have to be re-evaluated.
313 void SwDoc::UpdateFlds( SfxPoolItem *pNewHt, bool bCloseDB )
315 // Call Modify() for every field type,
316 // dependent SwTxtFld get notified ...
318 for( sal_uInt16 i=0; i < pFldTypes->size(); ++i)
320 switch( (*pFldTypes)[i]->Which() )
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 break;
331 case RES_DDEFLD:
333 if( !pNewHt )
335 SwMsgPoolItem aUpdateDDE( RES_UPDATEDDETBL );
336 (*pFldTypes)[i]->ModifyNotification( 0, &aUpdateDDE );
338 else
339 (*pFldTypes)[i]->ModifyNotification( 0, pNewHt );
340 break;
342 case RES_GETEXPFLD:
343 case RES_SETEXPFLD:
344 case RES_HIDDENTXTFLD:
345 case RES_HIDDENPARAFLD:
346 // Expression fields are treated seperately
347 if( !pNewHt )
348 break;
349 default:
350 (*pFldTypes)[i]->ModifyNotification ( 0, pNewHt );
354 if( !IsExpFldsLocked() )
355 UpdateExpFlds( 0, sal_False ); // update expression fields
357 // Tables
358 UpdateTblFlds(pNewHt);
360 // References
361 UpdateRefFlds(pNewHt);
363 if( bCloseDB )
364 GetNewDBMgr()->CloseAll();
366 // Only evaluate on full update
367 SetModified();
370 /******************************************************************************
371 * void SwDoc::UpdateUsrFlds()
372 ******************************************************************************/
373 void SwDoc::UpdateUsrFlds()
375 SwCalc* pCalc = 0;
376 const SwFieldType* pFldType;
377 for( sal_uInt16 i = INIT_FLDTYPES; i < pFldTypes->size(); ++i )
378 if( RES_USERFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
380 if( !pCalc )
381 pCalc = new SwCalc( *this );
382 ((SwUserFieldType*)pFldType)->GetValue( *pCalc );
385 if( pCalc )
387 delete pCalc;
388 SetModified();
392 /*--------------------------------------------------------------------
393 Description: Update reference and table fields
394 --------------------------------------------------------------------*/
395 void SwDoc::UpdateRefFlds( SfxPoolItem* pHt )
397 SwFieldType* pFldType;
398 for( sal_uInt16 i = 0; i < pFldTypes->size(); ++i )
399 if( RES_GETREFFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
400 pFldType->ModifyNotification( 0, pHt );
403 //For simplicity assume that all field types have updatable contents so
404 //optimization currently only available when no fields exist.
405 bool SwDoc::containsUpdatableFields()
407 for (sal_uInt16 i = 0; i < pFldTypes->size(); ++i)
409 SwFieldType* pFldType = (*pFldTypes)[i];
410 SwIterator<SwFmtFld,SwFieldType> aIter(*pFldType);
411 if (aIter.First())
412 return true;
414 return false;
417 void SwDoc::UpdateTblFlds( SfxPoolItem* pHt )
419 OSL_ENSURE( !pHt || RES_TABLEFML_UPDATE == pHt->Which(),
420 "What MessageItem is this?" );
422 SwFieldType* pFldType(0);
424 for (sal_uInt16 i = 0; i < pFldTypes->size(); ++i)
426 if( RES_TABLEFLD == ( pFldType = (*pFldTypes)[i] )->Which() )
428 SwTableFmlUpdate* pUpdtFld = 0;
429 if( pHt && RES_TABLEFML_UPDATE == pHt->Which() )
430 pUpdtFld = (SwTableFmlUpdate*)pHt;
432 SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
433 for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
435 if( pFmtFld->GetTxtFld() )
437 SwTblField* pFld = (SwTblField*)pFmtFld->GetFld();
439 if( pUpdtFld )
441 // table where this field is located
442 const SwTableNode* pTblNd;
443 const SwTxtNode& rTxtNd = pFmtFld->GetTxtFld()->GetTxtNode();
444 if( !rTxtNd.GetNodes().IsDocNodes() ||
445 0 == ( pTblNd = rTxtNd.FindTableNode() ) )
446 continue;
448 switch( pUpdtFld->eFlags )
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 if( nsSwExtendedSubType::SUB_CMD & pFld->GetSubType() )
455 pFld->PtrToBoxNm( pUpdtFld->pTbl );
456 else
457 pFld->ChgValid( sal_False );
458 break;
459 case TBL_BOXNAME:
460 // is this the wanted table?
461 if( &pTblNd->GetTable() == pUpdtFld->pTbl )
462 // to the external representation
463 pFld->PtrToBoxNm( pUpdtFld->pTbl );
464 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 pFld->BoxNmToPtr( pUpdtFld->pTbl );
470 break;
471 case TBL_RELBOXNAME:
472 // is this the wanted table?
473 if( &pTblNd->GetTable() == pUpdtFld->pTbl )
474 // to the relative representation
475 pFld->ToRelBoxNm( pUpdtFld->pTbl );
476 break;
477 default:
478 break;
481 else
482 // reset the value flag for all
483 pFld->ChgValid( sal_False );
487 break;
489 pFldType = 0;
492 // process all table box formuals
493 const SfxPoolItem* pItem;
494 sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_BOXATR_FORMULA );
495 for (sal_uInt32 i = 0; i < nMaxItems; ++i)
497 if( 0 != (pItem = GetAttrPool().GetItem2( RES_BOXATR_FORMULA, i ) ) &&
498 ((SwTblBoxFormula*)pItem)->GetDefinedIn() )
500 ((SwTblBoxFormula*)pItem)->ChangeState( pHt );
505 // all fields/boxes are now invalid, so we can start to calculate
506 if( pHt && ( RES_TABLEFML_UPDATE != pHt->Which() ||
507 TBL_CALC != ((SwTableFmlUpdate*)pHt)->eFlags ))
508 return ;
510 SwCalc* pCalc = 0;
512 if( pFldType )
514 SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
515 for( SwFmtFld* pFmtFld = aIter.Last(); pFmtFld; pFmtFld = aIter.Previous() )
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 if( !pFmtFld->GetTxtFld() || (nsSwExtendedSubType::SUB_CMD &
523 (pFld = (SwTblField*)pFmtFld->GetFld())->GetSubType() ))
524 continue;
526 // needs to be recalculated
527 if( !pFld->IsValid() )
529 // table where this field is located
530 const SwTxtNode& rTxtNd = pFmtFld->GetTxtFld()->GetTxtNode();
531 if( !rTxtNd.GetNodes().IsDocNodes() )
532 continue;
533 const SwTableNode* pTblNd = rTxtNd.FindTableNode();
534 if( !pTblNd )
535 continue;
537 // if this field is not in the to-be-updated table, skip it
538 if( pHt && &pTblNd->GetTable() !=
539 ((SwTableFmlUpdate*)pHt)->pTbl )
540 continue;
542 if( !pCalc )
543 pCalc = new SwCalc( *this );
545 // get the values of all SetExpression fields that are valid
546 // until the table
547 SwFrm* pFrm = 0;
548 if( pTblNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
550 // is in the special section, that's expensive!
551 Point aPt; // return the first frame of the layout - Tab.Headline!!
552 pFrm = rTxtNd.getLayoutFrm( GetCurrentLayout(), &aPt );
553 if( pFrm )
555 SwPosition aPos( *pTblNd );
556 if( GetBodyTxtNode( *this, aPos, *pFrm ) )
557 FldsToCalc( *pCalc, _SetGetExpFld(
558 aPos.nNode, pFmtFld->GetTxtFld(),
559 &aPos.nContent ));
560 else
561 pFrm = 0;
564 if( !pFrm )
566 // create index to determine the TextNode
567 SwNodeIndex aIdx( rTxtNd );
568 FldsToCalc( *pCalc,
569 _SetGetExpFld( aIdx, pFmtFld->GetTxtFld() ));
572 SwTblCalcPara aPara( *pCalc, pTblNd->GetTable() );
573 pFld->CalcField( aPara );
574 if( aPara.IsStackOverFlow() )
576 bool const bResult = aPara.CalcWithStackOverflow();
577 if (bResult)
579 pFld->CalcField( aPara );
581 OSL_ENSURE(bResult,
582 "the chained formula could no be calculated");
584 pCalc->SetCalcError( CALC_NOERR );
586 pFmtFld->ModifyNotification( 0, pHt );
590 // calculate the formula at the boxes
591 for (sal_uInt32 i = 0; i < nMaxItems; ++i )
593 if( 0 != (pItem = GetAttrPool().GetItem2( RES_BOXATR_FORMULA, i ) ) &&
594 ((SwTblBoxFormula*)pItem)->GetDefinedIn() &&
595 !((SwTblBoxFormula*)pItem)->IsValid() )
597 SwTblBoxFormula* pFml = (SwTblBoxFormula*)pItem;
598 SwTableBox* pBox = pFml->GetTableBox();
599 if( pBox && pBox->GetSttNd() &&
600 pBox->GetSttNd()->GetNodes().IsDocNodes() )
602 const SwTableNode* pTblNd = pBox->GetSttNd()->FindTableNode();
603 if( !pHt || &pTblNd->GetTable() ==
604 ((SwTableFmlUpdate*)pHt)->pTbl )
606 double nValue;
607 if( !pCalc )
608 pCalc = new SwCalc( *this );
610 // get the values of all SetExpression fields that are valid
611 // until the table
612 SwFrm* pFrm = 0;
613 if( pTblNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
615 // is in the special section, that's expensive!
616 Point aPt; // return the first frame of the layout - Tab.Headline!!
617 SwNodeIndex aCNdIdx( *pTblNd, +2 );
618 SwCntntNode* pCNd = aCNdIdx.GetNode().GetCntntNode();
619 if( !pCNd )
620 pCNd = GetNodes().GoNext( &aCNdIdx );
622 if( pCNd && 0 != (pFrm = pCNd->getLayoutFrm( GetCurrentLayout(), &aPt )) )
624 SwPosition aPos( *pCNd );
625 if( GetBodyTxtNode( *this, aPos, *pFrm ) )
626 FldsToCalc( *pCalc, _SetGetExpFld( aPos.nNode ));
627 else
628 pFrm = 0;
631 if( !pFrm )
633 // create index to determine the TextNode
634 SwNodeIndex aIdx( *pTblNd );
635 FldsToCalc( *pCalc, _SetGetExpFld( aIdx ));
638 SwTblCalcPara aPara( *pCalc, pTblNd->GetTable() );
639 pFml->Calc( aPara, nValue );
641 if( aPara.IsStackOverFlow() )
643 bool const bResult = aPara.CalcWithStackOverflow();
644 if (bResult)
646 pFml->Calc( aPara, nValue );
648 OSL_ENSURE(bResult,
649 "the chained formula could no be calculated");
652 SwFrmFmt* pFmt = pBox->ClaimFrmFmt();
653 SfxItemSet aTmp( GetAttrPool(),
654 RES_BOXATR_BEGIN,RES_BOXATR_END-1 );
656 if( pCalc->IsCalcError() )
657 nValue = DBL_MAX;
658 aTmp.Put( SwTblBoxValue( nValue ));
659 if( SFX_ITEM_SET != pFmt->GetItemState( RES_BOXATR_FORMAT ))
660 aTmp.Put( SwTblBoxNumFormat( 0 ));
661 pFmt->SetFmtAttr( aTmp );
663 pCalc->SetCalcError( CALC_NOERR );
669 delete pCalc;
672 void SwDoc::UpdatePageFlds( SfxPoolItem* pMsgHnt )
674 SwFieldType* pFldType;
675 for( sal_uInt16 i = 0; i < INIT_FLDTYPES; ++i )
676 switch( ( pFldType = (*pFldTypes)[ i ] )->Which() )
678 case RES_PAGENUMBERFLD:
679 case RES_CHAPTERFLD:
680 case RES_GETEXPFLD:
681 case RES_REFPAGEGETFLD:
682 pFldType->ModifyNotification( 0, pMsgHnt );
683 break;
684 case RES_DOCSTATFLD:
685 pFldType->ModifyNotification( 0, 0 );
686 break;
688 SetNewFldLst(true);
691 // ---- Remove all unreferenced field types of a document --
692 void SwDoc::GCFieldTypes()
694 for( sal_uInt16 n = pFldTypes->size(); n > INIT_FLDTYPES; )
695 if( !(*pFldTypes)[ --n ]->GetDepends() )
696 RemoveFldType( n );
699 void SwDoc::LockExpFlds()
701 ++nLockExpFld;
704 void SwDoc::UnlockExpFlds()
706 if( nLockExpFld )
707 --nLockExpFld;
710 bool SwDoc::IsExpFldsLocked() const
712 return 0 != nLockExpFld;
715 SwDocUpdtFld& SwDoc::GetUpdtFlds() const
717 return *pUpdtFlds;
720 bool SwDoc::IsNewFldLst() const
722 return mbNewFldLst;
725 void SwDoc::SetNewFldLst(bool bFlag)
727 mbNewFldLst = bFlag;
730 // the StartIndex can be supplied optionally (e.g. if it was queried before - is a virtual
731 // method otherwise!)
732 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx, const SwTxtFld* pFld,
733 const SwIndex* pIdx )
735 eSetGetExpFldType = TEXTFIELD;
736 CNTNT.pTxtFld = pFld;
737 nNode = rNdIdx.GetIndex();
738 if( pIdx )
739 nCntnt = pIdx->GetIndex();
740 else if( pFld )
741 nCntnt = *pFld->GetStart();
742 else
743 nCntnt = 0;
746 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx,
747 const SwTxtINetFmt& rINet, const SwIndex* pIdx )
749 eSetGetExpFldType = TEXTINET;
750 CNTNT.pTxtINet = &rINet;
751 nNode = rNdIdx.GetIndex();
752 if( pIdx )
753 nCntnt = pIdx->GetIndex();
754 else
755 nCntnt = *rINet.GetStart();
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 _SetGetExpFld::_SetGetExpFld( const SwSectionNode& rSectNd,
762 const SwPosition* pPos )
764 eSetGetExpFldType = SECTIONNODE;
765 CNTNT.pSection = &rSectNd.GetSection();
767 if( pPos )
769 nNode = pPos->nNode.GetIndex();
770 nCntnt = pPos->nContent.GetIndex();
772 else
774 nNode = rSectNd.GetIndex();
775 nCntnt = 0;
779 _SetGetExpFld::_SetGetExpFld( const SwTableBox& rTBox, const SwPosition* pPos )
781 eSetGetExpFldType = TABLEBOX;
782 CNTNT.pTBox = &rTBox;
784 if( pPos )
786 nNode = pPos->nNode.GetIndex();
787 nCntnt = pPos->nContent.GetIndex();
789 else
791 nNode = 0;
792 nCntnt = 0;
793 if( rTBox.GetSttNd() )
795 SwNodeIndex aIdx( *rTBox.GetSttNd() );
796 const SwCntntNode* pNd = aIdx.GetNode().GetNodes().GoNext( &aIdx );
797 if( pNd )
798 nNode = pNd->GetIndex();
803 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx,
804 const SwTxtTOXMark& rTOX,
805 const SwIndex* pIdx )
807 eSetGetExpFldType = TEXTTOXMARK;
808 CNTNT.pTxtTOX = &rTOX;
809 nNode = rNdIdx.GetIndex();
810 if( pIdx )
811 nCntnt = pIdx->GetIndex();
812 else
813 nCntnt = *rTOX.GetStart();
816 _SetGetExpFld::_SetGetExpFld( const SwPosition& rPos )
818 eSetGetExpFldType = CRSRPOS;
819 CNTNT.pPos = &rPos;
820 nNode = rPos.nNode.GetIndex();
821 nCntnt = rPos.nContent.GetIndex();
824 _SetGetExpFld::_SetGetExpFld( const SwFlyFrmFmt& rFlyFmt,
825 const SwPosition* pPos )
827 eSetGetExpFldType = FLYFRAME;
828 CNTNT.pFlyFmt = &rFlyFmt;
829 if( pPos )
831 nNode = pPos->nNode.GetIndex();
832 nCntnt = pPos->nContent.GetIndex();
834 else
836 const SwFmtCntnt& rCntnt = rFlyFmt.GetCntnt();
837 nNode = rCntnt.GetCntntIdx()->GetIndex() + 1;
838 nCntnt = 0;
842 void _SetGetExpFld::GetPos( SwPosition& rPos ) const
844 rPos.nNode = nNode;
845 rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt );
848 void _SetGetExpFld::GetPosOfContent( SwPosition& rPos ) const
850 const SwNode* pNd = GetNodeFromCntnt();
851 if( pNd )
852 pNd = pNd->GetCntntNode();
854 if( pNd )
856 rPos.nNode = *pNd;
857 rPos.nContent.Assign( (SwCntntNode*)pNd,GetCntPosFromCntnt() );
859 else
861 rPos.nNode = nNode;
862 rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt );
866 void _SetGetExpFld::SetBodyPos( const SwCntntFrm& rFrm )
868 if( !rFrm.IsInDocBody() )
870 SwNodeIndex aIdx( *rFrm.GetNode() );
871 SwDoc& rDoc = *aIdx.GetNodes().GetDoc();
872 SwPosition aPos( aIdx );
873 bool const bResult = ::GetBodyTxtNode( rDoc, aPos, rFrm );
874 OSL_ENSURE(bResult, "Where is the field?");
875 (void) bResult; // unused in non-debug
876 nNode = aPos.nNode.GetIndex();
877 nCntnt = aPos.nContent.GetIndex();
881 bool _SetGetExpFld::operator<( const _SetGetExpFld& rFld ) const
883 if( nNode < rFld.nNode || ( nNode == rFld.nNode && nCntnt < rFld.nCntnt ))
884 return true;
885 else if( nNode != rFld.nNode || nCntnt != rFld.nCntnt )
886 return false;
888 const SwNode *pFirst = GetNodeFromCntnt(),
889 *pNext = rFld.GetNodeFromCntnt();
891 // Position is the same: continue only if both field pointers are set!
892 if( !pFirst || !pNext )
893 return false;
895 // same Section?
896 if( pFirst->StartOfSectionNode() != pNext->StartOfSectionNode() )
898 // is one in the table?
899 const SwNode *pFirstStt, *pNextStt;
900 const SwTableNode* pTblNd = pFirst->FindTableNode();
901 if( pTblNd )
902 pFirstStt = pTblNd->StartOfSectionNode();
903 else
904 pFirstStt = pFirst->StartOfSectionNode();
906 if( 0 != ( pTblNd = pNext->FindTableNode() ) )
907 pNextStt = pTblNd->StartOfSectionNode();
908 else
909 pNextStt = pNext->StartOfSectionNode();
911 if( pFirstStt != pNextStt )
913 if( pFirst->IsTxtNode() && pNext->IsTxtNode() &&
914 ( pFirst->FindFlyStartNode() || pNext->FindFlyStartNode() ))
916 return ::IsFrameBehind( *(SwTxtNode*)pNext, nCntnt,
917 *(SwTxtNode*)pFirst, nCntnt );
919 return pFirstStt->GetIndex() < pNextStt->GetIndex();
923 // same Section: is the field in the same Node?
924 if( pFirst != pNext )
925 return pFirst->GetIndex() < pNext->GetIndex();
927 // same Node in the Section, check Position in the Node
928 return GetCntPosFromCntnt() < rFld.GetCntPosFromCntnt();
931 const SwNode* _SetGetExpFld::GetNodeFromCntnt() const
933 const SwNode* pRet = 0;
934 if( CNTNT.pTxtFld )
935 switch( eSetGetExpFldType )
937 case TEXTFIELD:
938 pRet = &CNTNT.pTxtFld->GetTxtNode();
939 break;
941 case TEXTINET:
942 pRet = &CNTNT.pTxtINet->GetTxtNode();
943 break;
945 case SECTIONNODE:
946 pRet = CNTNT.pSection->GetFmt()->GetSectionNode();
947 break;
949 case CRSRPOS:
950 pRet = &CNTNT.pPos->nNode.GetNode();
951 break;
953 case TEXTTOXMARK:
954 pRet = &CNTNT.pTxtTOX->GetTxtNode();
955 break;
957 case TABLEBOX:
958 if( CNTNT.pTBox->GetSttNd() )
960 SwNodeIndex aIdx( *CNTNT.pTBox->GetSttNd() );
961 pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx );
963 break;
965 case FLYFRAME:
967 SwNodeIndex aIdx( *CNTNT.pFlyFmt->GetCntnt().GetCntntIdx() );
968 pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx );
970 break;
972 return pRet;
975 xub_StrLen _SetGetExpFld::GetCntPosFromCntnt() const
977 sal_uInt16 nRet = 0;
978 if( CNTNT.pTxtFld )
979 switch( eSetGetExpFldType )
981 case TEXTFIELD:
982 case TEXTINET:
983 case TEXTTOXMARK:
984 nRet = *CNTNT.pTxtFld->GetStart();
985 break;
986 case CRSRPOS:
987 nRet = CNTNT.pPos->nContent.GetIndex();
988 break;
989 default:
990 break;
992 return nRet;
995 _HashStr::_HashStr( const String& rName, const String& rText,
996 _HashStr* pNxt )
997 : SwHash( rName ), aSetStr( rText )
999 pNext = pNxt;
1002 // Look up the Name, if it is present, return it's String, otherwise return an empty String
1003 void LookString( SwHash** ppTbl, sal_uInt16 nSize, const String& rName,
1004 String& rRet, sal_uInt16* pPos )
1006 rRet = comphelper::string::strip(rName, ' ');
1007 SwHash* pFnd = Find( rRet, ppTbl, nSize, pPos );
1008 if( pFnd )
1009 rRet = ((_HashStr*)pFnd)->aSetStr;
1010 else
1011 rRet.Erase();
1014 static String lcl_GetDBVarName( SwDoc& rDoc, SwDBNameInfField& rDBFld )
1016 SwDBData aDBData( rDBFld.GetDBData( &rDoc ));
1017 String sDBNumNm;
1018 SwDBData aDocData = rDoc.GetDBData();
1020 if( aDBData != aDocData )
1022 sDBNumNm = aDBData.sDataSource;
1023 sDBNumNm += DB_DELIM;
1024 sDBNumNm += String(aDBData.sCommand);
1025 sDBNumNm += DB_DELIM;
1027 sDBNumNm += SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD);
1029 return sDBNumNm;
1032 static void lcl_CalcFld( SwDoc& rDoc, SwCalc& rCalc, const _SetGetExpFld& rSGEFld,
1033 SwNewDBMgr* pMgr )
1035 const SwTxtFld* pTxtFld = rSGEFld.GetFld();
1036 if( !pTxtFld )
1037 return ;
1039 const SwField* pFld = pTxtFld->GetFld().GetFld();
1040 const sal_uInt16 nFldWhich = pFld->GetTyp()->Which();
1042 if( RES_SETEXPFLD == nFldWhich )
1044 SwSbxValue aValue;
1045 if( nsSwGetSetExpType::GSE_EXPR & pFld->GetSubType() )
1046 aValue.PutDouble( ((SwSetExpField*)pFld)->GetValue() );
1047 else
1048 // Extension to calculate with Strings
1049 aValue.PutString( ((SwSetExpField*)pFld)->GetExpStr() );
1051 // set the new value in Calculator
1052 rCalc.VarChange( pFld->GetTyp()->GetName(), aValue );
1054 else if( pMgr )
1056 switch( nFldWhich )
1058 case RES_DBNUMSETFLD:
1060 SwDBNumSetField* pDBFld = (SwDBNumSetField*)pFld;
1062 SwDBData aDBData(pDBFld->GetDBData(&rDoc));
1064 if( pDBFld->IsCondValid() &&
1065 pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand ))
1066 rCalc.VarChange( lcl_GetDBVarName( rDoc, *pDBFld),
1067 pDBFld->GetFormat() );
1069 break;
1070 case RES_DBNEXTSETFLD:
1072 SwDBNextSetField* pDBFld = (SwDBNextSetField*)pFld;
1073 SwDBData aDBData(pDBFld->GetDBData(&rDoc));
1074 if( !pDBFld->IsCondValid() ||
1075 !pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand ))
1076 break;
1078 String sDBNumNm(lcl_GetDBVarName( rDoc, *pDBFld));
1079 SwCalcExp* pExp = rCalc.VarLook( sDBNumNm );
1080 if( pExp )
1081 rCalc.VarChange( sDBNumNm, pExp->nValue.GetLong() + 1 );
1083 break;
1089 void SwDoc::FldsToCalc( SwCalc& rCalc, const _SetGetExpFld& rToThisFld )
1091 // create the sorted list of all SetFields
1092 pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC );
1093 mbNewFldLst = sal_False;
1095 SwNewDBMgr* pMgr = GetNewDBMgr();
1096 pMgr->CloseAll(sal_False);
1098 if( !pUpdtFlds->GetSortLst()->empty() )
1100 _SetGetExpFlds::const_iterator const itLast =
1101 pUpdtFlds->GetSortLst()->upper_bound(
1102 const_cast<_SetGetExpFld*>(&rToThisFld));
1103 for( _SetGetExpFlds::const_iterator it = pUpdtFlds->GetSortLst()->begin(); it != itLast; ++it )
1104 lcl_CalcFld( *this, rCalc, **it, pMgr );
1107 pMgr->CloseAll(sal_False);
1110 void SwDoc::FldsToCalc( SwCalc& rCalc, sal_uLong nLastNd, sal_uInt16 nLastCnt )
1112 // create the sorted list of all SetFields
1113 pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC );
1114 mbNewFldLst = sal_False;
1116 SwNewDBMgr* pMgr = GetNewDBMgr();
1117 pMgr->CloseAll(sal_False);
1119 for( _SetGetExpFlds::const_iterator it = pUpdtFlds->GetSortLst()->begin();
1120 it != pUpdtFlds->GetSortLst()->end() &&
1121 ( (*it)->GetNode() < nLastNd ||
1122 ( (*it)->GetNode() == nLastNd && (*it)->GetCntnt() <= nLastCnt )
1124 ++it )
1126 lcl_CalcFld( *this, rCalc, **it, pMgr );
1129 pMgr->CloseAll(sal_False);
1132 void SwDoc::FldsToExpand( SwHash**& ppHashTbl, sal_uInt16& rTblSize,
1133 const _SetGetExpFld& rToThisFld )
1135 // create the sorted list of all SetFields
1136 pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_EXPAND );
1137 mbNewFldLst = sal_False;
1139 // Hash table for all string replacements is filled on-the-fly.
1140 // Try to fabricate an uneven number.
1141 rTblSize = (( pUpdtFlds->GetSortLst()->size() / 7 ) + 1 ) * 7;
1142 ppHashTbl = new SwHash*[ rTblSize ];
1143 memset( ppHashTbl, 0, sizeof( _HashStr* ) * rTblSize );
1145 _SetGetExpFlds::const_iterator const itLast =
1146 pUpdtFlds->GetSortLst()->upper_bound(
1147 const_cast<_SetGetExpFld*>(&rToThisFld));
1149 for( _SetGetExpFlds::const_iterator it = pUpdtFlds->GetSortLst()->begin(); it != itLast; ++it )
1151 const SwTxtFld* pTxtFld = (*it)->GetFld();
1152 if( !pTxtFld )
1153 continue;
1155 const SwField* pFld = pTxtFld->GetFld().GetFld();
1156 switch( pFld->GetTyp()->Which() )
1158 case RES_SETEXPFLD:
1159 if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() )
1161 // set the new value in the hash table
1162 // is the formula a field?
1163 SwSetExpField* pSFld = (SwSetExpField*)pFld;
1164 String aNew;
1165 LookString( ppHashTbl, rTblSize, pSFld->GetFormula(), aNew );
1167 if( !aNew.Len() ) // nothing found, then the formula is
1168 aNew = pSFld->GetFormula(); // the new value
1170 // #i3141# - update expression of field as in method
1171 // <SwDoc::UpdateExpFlds(..)> for string/text fields
1172 pSFld->ChgExpStr( aNew );
1174 // look up the field's name
1175 aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName();
1176 // Entry present?
1177 sal_uInt16 nPos;
1178 SwHash* pFnd = Find( aNew, ppHashTbl, rTblSize, &nPos );
1179 if( pFnd )
1180 // modify entry in the hash table
1181 ((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr();
1182 else
1183 // insert the new entry
1184 *(ppHashTbl + nPos ) = new _HashStr( aNew,
1185 pSFld->GetExpStr(), (_HashStr*)*(ppHashTbl + nPos) );
1187 break;
1188 case RES_DBFLD:
1190 const String& rName = pFld->GetTyp()->GetName();
1192 // Insert entry in the hash table
1193 // Entry present?
1194 sal_uInt16 nPos;
1195 SwHash* pFnd = Find( rName, ppHashTbl, rTblSize, &nPos );
1196 String const value(pFld->ExpandField(IsClipBoard()));
1197 if( pFnd )
1199 // modify entry in the hash table
1200 static_cast<_HashStr*>(pFnd)->aSetStr = value;
1202 else
1204 // insert the new entry
1205 *(ppHashTbl + nPos ) = new _HashStr( rName,
1206 value, static_cast<_HashStr *>(*(ppHashTbl + nPos)));
1209 break;
1214 void SwDoc::UpdateExpFlds( SwTxtFld* pUpdtFld, bool bUpdRefFlds )
1216 if( IsExpFldsLocked() || IsInReading() )
1217 return;
1219 bool bOldInUpdateFlds = pUpdtFlds->IsInUpdateFlds();
1220 pUpdtFlds->SetInUpdateFlds( true );
1222 pUpdtFlds->MakeFldList( *this, sal_True, GETFLD_ALL );
1223 mbNewFldLst = sal_False;
1225 if( pUpdtFlds->GetSortLst()->empty() )
1227 if( bUpdRefFlds )
1228 UpdateRefFlds(NULL);
1230 pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds );
1231 pUpdtFlds->SetFieldsDirty( false );
1232 return ;
1235 sal_uInt16 nWhich, n;
1237 // Hash table for all string replacements is filled on-the-fly.
1238 // Try to fabricate an uneven number.
1239 sal_uInt16 nStrFmtCnt = (( pFldTypes->size() / 7 ) + 1 ) * 7;
1240 SwHash** pHashStrTbl = new SwHash*[ nStrFmtCnt ];
1241 memset( pHashStrTbl, 0, sizeof( _HashStr* ) * nStrFmtCnt );
1244 const SwFieldType* pFldType;
1245 // process seperately:
1246 for( n = pFldTypes->size(); n; )
1247 switch( ( pFldType = (*pFldTypes)[ --n ] )->Which() )
1249 case RES_USERFLD:
1251 // Entry present?
1252 sal_uInt16 nPos;
1253 const String& rNm = pFldType->GetName();
1254 String sExpand(((SwUserFieldType*)pFldType)->Expand(nsSwGetSetExpType::GSE_STRING, 0, 0));
1255 SwHash* pFnd = Find( rNm, pHashStrTbl, nStrFmtCnt, &nPos );
1256 if( pFnd )
1257 // modify entry in the hash table
1258 ((_HashStr*)pFnd)->aSetStr = sExpand;
1259 else
1260 // insert the new entry
1261 *(pHashStrTbl + nPos ) = new _HashStr( rNm, sExpand,
1262 (_HashStr*)*(pHashStrTbl + nPos) );
1264 break;
1265 case RES_SETEXPFLD:
1266 ((SwSetExpFieldType*)pFldType)->SetOutlineChgNd( 0 );
1267 break;
1271 // The array is filled with all fields; start calculation.
1272 SwCalc aCalc( *this );
1274 String sDBNumNm( SwFieldType::GetTypeStr( TYP_DBSETNUMBERFLD ) );
1276 // already set the current record number
1277 SwNewDBMgr* pMgr = GetNewDBMgr();
1278 pMgr->CloseAll(sal_False);
1280 // Make sure we don't hide all sections, which would lead to a crash. First, count how many of them do we have.
1281 int nShownSections = 0;
1282 for( _SetGetExpFlds::const_iterator it = pUpdtFlds->GetSortLst()->begin(); it != pUpdtFlds->GetSortLst()->end(); ++it )
1284 SwSection* pSect = (SwSection*)(*it)->GetSection();
1285 if ( pSect && !pSect->IsCondHidden())
1286 nShownSections++;
1289 String aNew;
1290 for( _SetGetExpFlds::const_iterator it = pUpdtFlds->GetSortLst()->begin(); it != pUpdtFlds->GetSortLst()->end(); ++it )
1292 SwSection* pSect = (SwSection*)(*it)->GetSection();
1293 if( pSect )
1296 SwSbxValue aValue = aCalc.Calculate(
1297 pSect->GetCondition() );
1298 if(!aValue.IsVoidValue())
1300 // Do we want to hide this one?
1301 bool bHide = aValue.GetBool();
1302 if (bHide && !pSect->IsCondHidden())
1304 // This section will be hidden, but it wasn't before
1305 if (nShownSections == 1)
1307 // This would be the last section, so set its condition to false, and avoid hiding it.
1308 OUString aCond("0");
1309 pSect->SetCondition(aCond);
1310 bHide = false;
1312 nShownSections--;
1314 pSect->SetCondHidden( bHide );
1316 continue;
1319 SwTxtFld* pTxtFld = (SwTxtFld*)(*it)->GetFld();
1320 if( !pTxtFld )
1322 OSL_ENSURE( !this, "what's wrong now'" );
1323 continue;
1326 SwFmtFld* pFmtFld = (SwFmtFld*)&pTxtFld->GetFld();
1327 SwField* pFld = pFmtFld->GetFld();
1329 switch( nWhich = pFld->GetTyp()->Which() )
1331 case RES_HIDDENTXTFLD:
1333 SwHiddenTxtField* pHFld = (SwHiddenTxtField*)pFld;
1334 SwSbxValue aValue = aCalc.Calculate( pHFld->GetPar1() );
1335 sal_Bool bValue = !aValue.GetBool();
1336 if(!aValue.IsVoidValue())
1338 pHFld->SetValue( bValue );
1339 // evaluate field
1340 pHFld->Evaluate(this);
1343 break;
1344 case RES_HIDDENPARAFLD:
1346 SwHiddenParaField* pHPFld = (SwHiddenParaField*)pFld;
1347 SwSbxValue aValue = aCalc.Calculate( pHPFld->GetPar1() );
1348 sal_Bool bValue = aValue.GetBool();
1349 if(!aValue.IsVoidValue())
1350 pHPFld->SetHidden( bValue );
1352 break;
1353 case RES_DBSETNUMBERFLD:
1355 ((SwDBSetNumberField*)pFld)->Evaluate(this);
1356 aCalc.VarChange( sDBNumNm, ((SwDBSetNumberField*)pFld)->GetSetNumber());
1358 break;
1359 case RES_DBNEXTSETFLD:
1360 case RES_DBNUMSETFLD:
1361 UpdateDBNumFlds( *(SwDBNameInfField*)pFld, aCalc );
1362 break;
1363 case RES_DBFLD:
1365 // evaluate field
1366 ((SwDBField*)pFld)->Evaluate();
1368 SwDBData aTmpDBData(((SwDBField*)pFld)->GetDBData());
1370 if( pMgr->IsDataSourceOpen(aTmpDBData.sDataSource, aTmpDBData.sCommand, sal_False))
1371 aCalc.VarChange( sDBNumNm, pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType));
1373 const String& rName = pFld->GetTyp()->GetName();
1375 // Set value for Calculator
1376 //JP 10.02.96: GetValue doesn't make sense here
1377 // ((SwDBField*)pFld)->GetValue();
1379 //!OK aCalc.VarChange(aName, ((SwDBField*)pFld)->GetValue(aCalc));
1381 // Add entry to hash table
1382 // Entry present?
1383 sal_uInt16 nPos;
1384 SwHash* pFnd = Find( rName, pHashStrTbl, nStrFmtCnt, &nPos );
1385 String const value(pFld->ExpandField(IsClipBoard()));
1386 if( pFnd )
1388 // Modify entry in the hash table
1389 static_cast<_HashStr*>(pFnd)->aSetStr = value;
1391 else
1393 // insert new entry
1394 *(pHashStrTbl + nPos ) = new _HashStr( rName,
1395 value, static_cast<_HashStr *>(*(pHashStrTbl + nPos)));
1398 break;
1399 case RES_GETEXPFLD:
1400 case RES_SETEXPFLD:
1402 if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() ) // replace String
1404 if( RES_GETEXPFLD == nWhich )
1406 SwGetExpField* pGFld = (SwGetExpField*)pFld;
1408 if( (!pUpdtFld || pUpdtFld == pTxtFld )
1409 && pGFld->IsInBodyTxt() )
1411 LookString( pHashStrTbl, nStrFmtCnt,
1412 pGFld->GetFormula(), aNew );
1413 pGFld->ChgExpStr( aNew );
1416 else
1418 SwSetExpField* pSFld = (SwSetExpField*)pFld;
1419 // is the "formula" a field?
1420 LookString( pHashStrTbl, nStrFmtCnt,
1421 pSFld->GetFormula(), aNew );
1423 if( !aNew.Len() ) // nothing found then the formula is the new value
1424 aNew = pSFld->GetFormula();
1426 // only update one field
1427 if( !pUpdtFld || pUpdtFld == pTxtFld )
1428 pSFld->ChgExpStr( aNew );
1430 // lookup the field's name
1431 aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName();
1432 // Entry present?
1433 sal_uInt16 nPos;
1434 SwHash* pFnd = Find( aNew, pHashStrTbl, nStrFmtCnt, &nPos );
1435 if( pFnd )
1436 // Modify entry in the hash table
1437 ((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr();
1438 else
1439 // insert new entry
1440 *(pHashStrTbl + nPos ) = pFnd = new _HashStr( aNew,
1441 pSFld->GetExpStr(),
1442 (_HashStr*)*(pHashStrTbl + nPos) );
1444 // Extension for calculation with Strings
1445 SwSbxValue aValue;
1446 aValue.PutString( ((_HashStr*)pFnd)->aSetStr );
1447 aCalc.VarChange( aNew, aValue );
1450 else // recalculate formula
1452 if( RES_GETEXPFLD == nWhich )
1454 SwGetExpField* pGFld = (SwGetExpField*)pFld;
1456 if( (!pUpdtFld || pUpdtFld == pTxtFld )
1457 && pGFld->IsInBodyTxt() )
1459 SwSbxValue aValue = aCalc.Calculate(
1460 pGFld->GetFormula());
1461 if(!aValue.IsVoidValue())
1462 pGFld->SetValue(aValue.GetDouble() );
1465 else
1467 SwSetExpField* pSFld = (SwSetExpField*)pFld;
1468 SwSetExpFieldType* pSFldTyp = (SwSetExpFieldType*)pFld->GetTyp();
1469 aNew = pSFldTyp->GetName();
1471 SwNode* pSeqNd = 0;
1473 if( pSFld->IsSequenceFld() )
1475 const sal_uInt8 nLvl = pSFldTyp->GetOutlineLvl();
1476 if( MAXLEVEL > nLvl )
1478 // test if the Number needs to be updated
1479 pSeqNd = GetNodes()[ (*it)->GetNode() ];
1481 const SwTxtNode* pOutlNd = pSeqNd->
1482 FindOutlineNodeOfLevel( nLvl );
1483 if( pSFldTyp->GetOutlineChgNd() != pOutlNd )
1485 pSFldTyp->SetOutlineChgNd( pOutlNd );
1486 aCalc.VarChange( aNew, 0 );
1491 aNew += '=';
1492 aNew += pSFld->GetFormula();
1494 SwSbxValue aValue = aCalc.Calculate( aNew );
1495 double nErg = aValue.GetDouble();
1496 // only update one field
1497 if( !aValue.IsVoidValue() && (!pUpdtFld || pUpdtFld == pTxtFld) )
1499 pSFld->SetValue( nErg );
1501 if( pSeqNd )
1502 pSFldTyp->SetChapter( *pSFld, *pSeqNd );
1507 } // switch
1509 pFmtFld->ModifyNotification( 0, 0 ); // trigger formatting
1511 if( pUpdtFld == pTxtFld ) // if only this one is updated
1513 if( RES_GETEXPFLD == nWhich || // only GetField or
1514 RES_HIDDENTXTFLD == nWhich || // HiddenTxt?
1515 RES_HIDDENPARAFLD == nWhich) // HiddenParaFld?
1516 break; // quit
1517 pUpdtFld = 0; // update all from here on
1521 pMgr->CloseAll(sal_False);
1522 // delete hash table
1523 ::DeleteHashTable( pHashStrTbl, nStrFmtCnt );
1525 // update reference fields
1526 if( bUpdRefFlds )
1527 UpdateRefFlds(NULL);
1529 pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds );
1530 pUpdtFlds->SetFieldsDirty( false );
1533 void SwDoc::UpdateDBNumFlds( SwDBNameInfField& rDBFld, SwCalc& rCalc )
1535 SwNewDBMgr* pMgr = GetNewDBMgr();
1537 sal_uInt16 nFldType = rDBFld.Which();
1539 sal_Bool bPar1 = rCalc.Calculate( rDBFld.GetPar1() ).GetBool();
1541 if( RES_DBNEXTSETFLD == nFldType )
1542 ((SwDBNextSetField&)rDBFld).SetCondValid( bPar1 );
1543 else
1544 ((SwDBNumSetField&)rDBFld).SetCondValid( bPar1 );
1546 if( !rDBFld.GetRealDBData().sDataSource.isEmpty() )
1548 // Edit a certain database
1549 if( RES_DBNEXTSETFLD == nFldType )
1550 ((SwDBNextSetField&)rDBFld).Evaluate(this);
1551 else
1552 ((SwDBNumSetField&)rDBFld).Evaluate(this);
1554 SwDBData aTmpDBData( rDBFld.GetDBData(this) );
1556 if( pMgr->OpenDataSource( aTmpDBData.sDataSource, aTmpDBData.sCommand, -1, false ))
1557 rCalc.VarChange( lcl_GetDBVarName( *this, rDBFld),
1558 pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType) );
1560 else
1562 OSL_FAIL("TODO: what should happen with unnamed DBFields?");
1566 void SwDoc::_InitFieldTypes() // is being called by the CTOR
1568 // Field types
1569 pFldTypes->push_back( new SwDateTimeFieldType(this) );
1570 pFldTypes->push_back( new SwChapterFieldType );
1571 pFldTypes->push_back( new SwPageNumberFieldType );
1572 pFldTypes->push_back( new SwAuthorFieldType );
1573 pFldTypes->push_back( new SwFileNameFieldType(this) );
1574 pFldTypes->push_back( new SwDBNameFieldType(this) );
1575 pFldTypes->push_back( new SwGetExpFieldType(this) );
1576 pFldTypes->push_back( new SwGetRefFieldType( this ) );
1577 pFldTypes->push_back( new SwHiddenTxtFieldType );
1578 pFldTypes->push_back( new SwPostItFieldType(this) );
1579 pFldTypes->push_back( new SwDocStatFieldType(this) );
1580 pFldTypes->push_back( new SwDocInfoFieldType(this) );
1581 pFldTypes->push_back( new SwInputFieldType( this ) );
1582 pFldTypes->push_back( new SwTblFieldType( this ) );
1583 pFldTypes->push_back( new SwMacroFieldType(this) );
1584 pFldTypes->push_back( new SwHiddenParaFieldType );
1585 pFldTypes->push_back( new SwDBNextSetFieldType );
1586 pFldTypes->push_back( new SwDBNumSetFieldType );
1587 pFldTypes->push_back( new SwDBSetNumberFieldType );
1588 pFldTypes->push_back( new SwTemplNameFieldType(this) );
1589 pFldTypes->push_back( new SwTemplNameFieldType(this) );
1590 pFldTypes->push_back( new SwExtUserFieldType );
1591 pFldTypes->push_back( new SwRefPageSetFieldType );
1592 pFldTypes->push_back( new SwRefPageGetFieldType( this ) );
1593 pFldTypes->push_back( new SwJumpEditFieldType( this ) );
1594 pFldTypes->push_back( new SwScriptFieldType( this ) );
1595 pFldTypes->push_back( new SwCombinedCharFieldType );
1596 pFldTypes->push_back( new SwDropDownFieldType );
1598 // Types have to be at the end!
1599 // We expect this in the InsertFldType!
1600 // MIB 14.04.95: In Sw3StringPool::Setup (sw3imp.cxx) and
1601 // lcl_sw3io_InSetExpField (sw3field.cxx) now also
1602 pFldTypes->push_back( new SwSetExpFieldType(this,
1603 SW_RESSTR(STR_POOLCOLL_LABEL_ABB), nsSwGetSetExpType::GSE_SEQ) );
1604 pFldTypes->push_back( new SwSetExpFieldType(this,
1605 SW_RESSTR(STR_POOLCOLL_LABEL_TABLE), nsSwGetSetExpType::GSE_SEQ) );
1606 pFldTypes->push_back( new SwSetExpFieldType(this,
1607 SW_RESSTR(STR_POOLCOLL_LABEL_FRAME), nsSwGetSetExpType::GSE_SEQ) );
1608 pFldTypes->push_back( new SwSetExpFieldType(this,
1609 SW_RESSTR(STR_POOLCOLL_LABEL_DRAWING), nsSwGetSetExpType::GSE_SEQ) );
1611 OSL_ENSURE( pFldTypes->size() == INIT_FLDTYPES, "Bad initsize: SwFldTypes" );
1614 void SwDoc::InsDelFldInFldLst( bool bIns, const SwTxtFld& rFld )
1616 if( !mbNewFldLst || !IsInDtor() )
1617 pUpdtFlds->InsDelFldInFldLst( bIns, rFld );
1620 SwDBData SwDoc::GetDBData()
1622 return GetDBDesc();
1625 const SwDBData& SwDoc::GetDBDesc()
1627 if(aDBData.sDataSource.isEmpty())
1629 const sal_uInt16 nSize = pFldTypes->size();
1630 for(sal_uInt16 i = 0; i < nSize && aDBData.sDataSource.isEmpty(); ++i)
1632 SwFieldType& rFldType = *((*pFldTypes)[i]);
1633 sal_uInt16 nWhich = rFldType.Which();
1634 if(IsUsed(rFldType))
1636 switch(nWhich)
1638 case RES_DBFLD:
1639 case RES_DBNEXTSETFLD:
1640 case RES_DBNUMSETFLD:
1641 case RES_DBSETNUMBERFLD:
1643 SwIterator<SwFmtFld,SwFieldType> aIter( rFldType );
1644 for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
1646 if(pFld->IsFldInDoc())
1648 if(RES_DBFLD == nWhich)
1649 aDBData =
1650 (static_cast < SwDBFieldType * > (pFld->GetFld()->GetTyp()))
1651 ->GetDBData();
1652 else
1653 aDBData = (static_cast < SwDBNameInfField* > (pFld->GetFld()))->GetRealDBData();
1654 break;
1658 break;
1663 if(aDBData.sDataSource.isEmpty())
1664 aDBData = GetNewDBMgr()->GetAddressDBName();
1665 return aDBData;
1668 void SwDoc::SetInitDBFields( sal_Bool b )
1670 GetNewDBMgr()->SetInitDBFields( b );
1673 /*--------------------------------------------------------------------
1674 Description: Get all databases that are used by fields
1675 --------------------------------------------------------------------*/
1676 static String lcl_DBDataToString(const SwDBData& rData)
1678 String sRet = rData.sDataSource;
1679 sRet += DB_DELIM;
1680 sRet += (String)rData.sCommand;
1681 sRet += DB_DELIM;
1682 sRet += String::CreateFromInt32(rData.nCommandType);
1683 return sRet;
1686 void SwDoc::GetAllUsedDB( std::vector<String>& rDBNameList,
1687 const std::vector<String>* pAllDBNames )
1689 std::vector<String> aUsedDBNames;
1690 std::vector<String> aAllDBNames;
1692 if( !pAllDBNames )
1694 GetAllDBNames( aAllDBNames );
1695 pAllDBNames = &aAllDBNames;
1698 SwSectionFmts& rArr = GetSections();
1699 for (sal_uInt16 n = rArr.size(); n; )
1701 SwSection* pSect = rArr[ --n ]->GetSection();
1703 if( pSect )
1705 String aCond( pSect->GetCondition() );
1706 AddUsedDBToList( rDBNameList, FindUsedDBs( *pAllDBNames,
1707 aCond, aUsedDBNames ) );
1708 aUsedDBNames.clear();
1712 const SfxPoolItem* pItem;
1713 sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
1714 for (sal_uInt32 n = 0; n < nMaxItems; ++n)
1716 if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) ))
1717 continue;
1719 const SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
1720 const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1721 if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
1722 continue;
1724 const SwField* pFld = pFmtFld->GetFld();
1725 switch( pFld->GetTyp()->Which() )
1727 case RES_DBFLD:
1728 AddUsedDBToList( rDBNameList,
1729 lcl_DBDataToString(((SwDBField*)pFld)->GetDBData() ));
1730 break;
1732 case RES_DBSETNUMBERFLD:
1733 case RES_DBNAMEFLD:
1734 AddUsedDBToList( rDBNameList,
1735 lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() ));
1736 break;
1738 case RES_DBNUMSETFLD:
1739 case RES_DBNEXTSETFLD:
1740 AddUsedDBToList( rDBNameList,
1741 lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() ));
1742 // no break // JP: is that right like that?
1744 case RES_HIDDENTXTFLD:
1745 case RES_HIDDENPARAFLD:
1746 AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames,
1747 pFld->GetPar1(), aUsedDBNames ));
1748 aUsedDBNames.clear();
1749 break;
1751 case RES_SETEXPFLD:
1752 case RES_GETEXPFLD:
1753 case RES_TABLEFLD:
1754 AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames,
1755 pFld->GetFormula(), aUsedDBNames ));
1756 aUsedDBNames.clear();
1757 break;
1762 void SwDoc::GetAllDBNames( std::vector<String>& rAllDBNames )
1764 SwNewDBMgr* pMgr = GetNewDBMgr();
1766 const SwDSParamArr& rArr = pMgr->GetDSParamArray();
1767 for(sal_uInt16 i = 0; i < rArr.size(); i++)
1769 const SwDSParam* pParam = &rArr[i];
1770 String* pStr = new String( pParam->sDataSource );
1771 (*pStr) += DB_DELIM;
1772 (*pStr) += (String)pParam->sCommand;
1773 rAllDBNames.push_back(*pStr);
1777 std::vector<String>& SwDoc::FindUsedDBs( const std::vector<String>& rAllDBNames,
1778 const String& rFormel,
1779 std::vector<String>& rUsedDBNames )
1781 const CharClass& rCC = GetAppCharClass();
1782 String sFormel( rFormel);
1783 #ifndef UNX
1784 sFormel = rCC.uppercase( sFormel );
1785 #endif
1787 xub_StrLen nPos;
1788 for (sal_uInt16 i = 0; i < rAllDBNames.size(); ++i )
1790 String pStr(rAllDBNames[i]);
1792 if( STRING_NOTFOUND != (nPos = sFormel.Search( pStr )) &&
1793 sFormel.GetChar( nPos + pStr.Len() ) == '.' &&
1794 (!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 )))
1796 // Look up table name
1797 xub_StrLen nEndPos;
1798 nPos += pStr.Len() + 1;
1799 if( STRING_NOTFOUND != (nEndPos = sFormel.Search('.', nPos)) )
1801 pStr.Append( DB_DELIM );
1802 pStr.Append( sFormel.Copy( nPos, nEndPos - nPos ));
1803 rUsedDBNames.push_back(pStr);
1807 return rUsedDBNames;
1810 void SwDoc::AddUsedDBToList( std::vector<String>& rDBNameList,
1811 const std::vector<String>& rUsedDBNames )
1813 for (sal_uInt16 i = 0; i < rUsedDBNames.size(); ++i)
1814 AddUsedDBToList( rDBNameList, rUsedDBNames[i] );
1817 void SwDoc::AddUsedDBToList( std::vector<String>& rDBNameList, const String& rDBName)
1819 if( !rDBName.Len() )
1820 return;
1822 #ifdef UNX
1823 for( sal_uInt16 i = 0; i < rDBNameList.size(); ++i )
1824 if( rDBName == rDBNameList[i].GetToken(0) )
1825 return;
1826 #else
1827 const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
1828 for( sal_uInt16 i = 0; i < rDBNameList.size(); ++i )
1829 if( rSCmp.isEqual( rDBName, rDBNameList[i].GetToken(0) ) )
1830 return;
1831 #endif
1833 SwDBData aData;
1834 aData.sDataSource = rDBName.GetToken(0, DB_DELIM);
1835 aData.sCommand = rDBName.GetToken(1, DB_DELIM);
1836 aData.nCommandType = -1;
1837 GetNewDBMgr()->CreateDSData(aData);
1838 rDBNameList.push_back(rDBName);
1841 void SwDoc::ChangeDBFields( const std::vector<String>& rOldNames,
1842 const String& rNewName )
1844 SwDBData aNewDBData;
1845 aNewDBData.sDataSource = rNewName.GetToken(0, DB_DELIM);
1846 aNewDBData.sCommand = rNewName.GetToken(1, DB_DELIM);
1847 aNewDBData.nCommandType = (short)rNewName.GetToken(2, DB_DELIM).ToInt32();
1849 String sFormel;
1851 SwSectionFmts& rArr = GetSections();
1852 for (sal_uInt16 n = rArr.size(); n; )
1854 SwSection* pSect = rArr[ --n ]->GetSection();
1856 if( pSect )
1858 sFormel = pSect->GetCondition();
1859 ReplaceUsedDBs( rOldNames, rNewName, sFormel);
1860 pSect->SetCondition(sFormel);
1864 const SfxPoolItem* pItem;
1865 sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
1867 for (sal_uInt32 n = 0; n < nMaxItems; ++n )
1869 if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) ))
1870 continue;
1872 SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
1873 SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
1874 if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
1875 continue;
1877 SwField* pFld = pFmtFld->GetFld();
1878 bool bExpand = false;
1880 switch( pFld->GetTyp()->Which() )
1882 case RES_DBFLD:
1883 if( IsNameInArray( rOldNames, lcl_DBDataToString(((SwDBField*)pFld)->GetDBData())))
1885 SwDBFieldType* pOldTyp = (SwDBFieldType*)pFld->GetTyp();
1887 SwDBFieldType* pTyp = (SwDBFieldType*)InsertFldType(
1888 SwDBFieldType(this, pOldTyp->GetColumnName(), aNewDBData));
1890 pFmtFld->RegisterToFieldType( *pTyp );
1891 pFld->ChgTyp(pTyp);
1893 ((SwDBField*)pFld)->ClearInitialized();
1894 ((SwDBField*)pFld)->InitContent();
1896 bExpand = true;
1898 break;
1900 case RES_DBSETNUMBERFLD:
1901 case RES_DBNAMEFLD:
1902 if( IsNameInArray( rOldNames,
1903 lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData())))
1905 ((SwDBNameInfField*)pFld)->SetDBData(aNewDBData);
1906 bExpand = true;
1908 break;
1910 case RES_DBNUMSETFLD:
1911 case RES_DBNEXTSETFLD:
1912 if( IsNameInArray( rOldNames,
1913 lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData())))
1915 ((SwDBNameInfField*)pFld)->SetDBData(aNewDBData);
1916 bExpand = true;
1918 // no break;
1919 case RES_HIDDENTXTFLD:
1920 case RES_HIDDENPARAFLD:
1921 sFormel = pFld->GetPar1();
1922 ReplaceUsedDBs( rOldNames, rNewName, sFormel);
1923 pFld->SetPar1( sFormel );
1924 bExpand = true;
1925 break;
1927 case RES_SETEXPFLD:
1928 case RES_GETEXPFLD:
1929 case RES_TABLEFLD:
1930 sFormel = pFld->GetFormula();
1931 ReplaceUsedDBs( rOldNames, rNewName, sFormel);
1932 pFld->SetPar2( sFormel );
1933 bExpand = true;
1934 break;
1937 if (bExpand)
1938 pTxtFld->ExpandAlways();
1940 SetModified();
1943 void SwDoc::ReplaceUsedDBs( const std::vector<String>& rUsedDBNames,
1944 const String& rNewName, String& rFormel )
1946 const CharClass& rCC = GetAppCharClass();
1947 String sFormel(rFormel);
1948 String sNewName( rNewName );
1949 sNewName.SearchAndReplace( DB_DELIM, '.');
1950 //the command type is not part of the condition
1951 sNewName = sNewName.GetToken(0, DB_DELIM);
1952 String sUpperNewNm( sNewName );
1954 for( sal_uInt16 i = 0; i < rUsedDBNames.size(); ++i )
1956 String sDBName( rUsedDBNames[i] );
1958 sDBName.SearchAndReplace( DB_DELIM, '.');
1959 //cut off command type
1960 sDBName = sDBName.GetToken(0, DB_DELIM);
1961 if( !sDBName.Equals( sUpperNewNm ))
1963 xub_StrLen nPos = 0;
1965 while ((nPos = sFormel.Search(sDBName, nPos)) != STRING_NOTFOUND)
1967 if( sFormel.GetChar( nPos + sDBName.Len() ) == '.' &&
1968 (!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 )))
1970 rFormel.Erase( nPos, sDBName.Len() );
1971 rFormel.Insert( sNewName, nPos );
1972 //prevent re-searching - this is useless and provokes
1973 //endless loops when names containing each other and numbers are exchanged
1974 //e.g.: old ?12345.12345 new: i12345.12345
1975 nPos = nPos + sNewName.Len();
1976 sFormel = rFormel;
1983 bool SwDoc::IsNameInArray( const std::vector<String>& rArr, const String& rName )
1985 #ifdef UNX
1986 for( sal_uInt16 i = 0; i < rArr.size(); ++i )
1987 if( rName == rArr[ i ] )
1988 return true;
1989 #else
1990 const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
1991 for( sal_uInt16 i = 0; i < rArr.size(); ++i )
1992 if( rSCmp.isEqual( rName, rArr[ i] ))
1993 return true;
1994 #endif
1995 return false;
1998 void SwDoc::SetFixFields( bool bOnlyTimeDate, const DateTime* pNewDateTime )
2000 sal_Bool bIsModified = IsModified();
2002 sal_uLong nDate, nTime;
2003 if( pNewDateTime )
2005 nDate = pNewDateTime->GetDate();
2006 nTime = pNewDateTime->GetTime();
2008 else
2010 nDate = Date( Date::SYSTEM ).GetDate();
2011 nTime = Time( Time::SYSTEM ).GetTime();
2014 sal_uInt16 aTypes[5] = {
2015 /*0*/ RES_DOCINFOFLD,
2016 /*1*/ RES_AUTHORFLD,
2017 /*2*/ RES_EXTUSERFLD,
2018 /*3*/ RES_FILENAMEFLD,
2019 /*4*/ RES_DATETIMEFLD }; // MUST be at the end!
2021 sal_uInt16 nStt = bOnlyTimeDate ? 4 : 0;
2023 for( ; nStt < 5; ++nStt )
2025 SwFieldType* pFldType = GetSysFldType( aTypes[ nStt ] );
2026 SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
2027 for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
2029 if( pFld && pFld->GetTxtFld() )
2031 bool bChgd = false;
2032 switch( aTypes[ nStt ] )
2034 case RES_DOCINFOFLD:
2035 if( ((SwDocInfoField*)pFld->GetFld())->IsFixed() )
2037 bChgd = true;
2038 SwDocInfoField* pDocInfFld = (SwDocInfoField*)pFld->GetFld();
2039 pDocInfFld->SetExpansion( ((SwDocInfoFieldType*)
2040 pDocInfFld->GetTyp())->Expand(
2041 pDocInfFld->GetSubType(),
2042 pDocInfFld->GetFormat(),
2043 pDocInfFld->GetLanguage(),
2044 pDocInfFld->GetName() ) );
2046 break;
2048 case RES_AUTHORFLD:
2049 if( ((SwAuthorField*)pFld->GetFld())->IsFixed() )
2051 bChgd = true;
2052 SwAuthorField* pAuthorFld = (SwAuthorField*)pFld->GetFld();
2053 pAuthorFld->SetExpansion( ((SwAuthorFieldType*)
2054 pAuthorFld->GetTyp())->Expand(
2055 pAuthorFld->GetFormat() ) );
2057 break;
2059 case RES_EXTUSERFLD:
2060 if( ((SwExtUserField*)pFld->GetFld())->IsFixed() )
2062 bChgd = true;
2063 SwExtUserField* pExtUserFld = (SwExtUserField*)pFld->GetFld();
2064 pExtUserFld->SetExpansion( ((SwExtUserFieldType*)
2065 pExtUserFld->GetTyp())->Expand(
2066 pExtUserFld->GetSubType(),
2067 pExtUserFld->GetFormat()));
2069 break;
2071 case RES_DATETIMEFLD:
2072 if( ((SwDateTimeField*)pFld->GetFld())->IsFixed() )
2074 bChgd = true;
2075 ((SwDateTimeField*)pFld->GetFld())->SetDateTime(
2076 DateTime(Date(nDate), Time(nTime)) );
2078 break;
2080 case RES_FILENAMEFLD:
2081 if( ((SwFileNameField*)pFld->GetFld())->IsFixed() )
2083 bChgd = true;
2084 SwFileNameField* pFileNameFld =
2085 (SwFileNameField*)pFld->GetFld();
2086 pFileNameFld->SetExpansion( ((SwFileNameFieldType*)
2087 pFileNameFld->GetTyp())->Expand(
2088 pFileNameFld->GetFormat() ) );
2090 break;
2093 // Trigger formatting
2094 if( bChgd )
2095 pFld->ModifyNotification( 0, 0 );
2100 if( !bIsModified )
2101 ResetModified();
2104 bool SwDoc::SetFieldsDirty( bool b, const SwNode* pChk, sal_uLong nLen )
2106 // See if the supplied nodes actually contain fields.
2107 // If they don't, the flag doesn't need to be changed.
2108 bool bFldsFnd = false;
2109 if( b && pChk && !GetUpdtFlds().IsFieldsDirty() && !IsInDtor()
2110 // ?? what's up with Undo, this is also wanted there!
2111 /*&& &pChk->GetNodes() == &GetNodes()*/ )
2113 b = false;
2114 if( !nLen )
2115 ++nLen;
2116 sal_uLong nStt = pChk->GetIndex();
2117 const SwNodes& rNds = pChk->GetNodes();
2118 while( nLen-- )
2120 const SwTxtNode* pTNd = rNds[ nStt++ ]->GetTxtNode();
2121 if( pTNd )
2123 if( pTNd->GetAttrOutlineLevel() != 0 )
2124 // update chapter fields
2125 b = true;
2126 else if( pTNd->GetpSwpHints() && pTNd->GetSwpHints().Count() )
2127 for( sal_uInt16 n = 0, nEnd = pTNd->GetSwpHints().Count();
2128 n < nEnd; ++n )
2130 const SwTxtAttr* pAttr = pTNd->GetSwpHints()[ n ];
2131 if( RES_TXTATR_FIELD == pAttr->Which() )
2133 b = true;
2134 break;
2138 if( b )
2139 break;
2142 bFldsFnd = b;
2144 GetUpdtFlds().SetFieldsDirty( b );
2145 return bFldsFnd;
2148 void SwDoc::ChangeAuthorityData( const SwAuthEntry* pNewData )
2150 const sal_uInt16 nSize = pFldTypes->size();
2152 for( sal_uInt16 i = INIT_FLDTYPES; i < nSize; ++i )
2154 SwFieldType* pFldType = (*pFldTypes)[i];
2155 if( RES_AUTHORITY == pFldType->Which() )
2157 SwAuthorityFieldType* pAuthType = (SwAuthorityFieldType*)pFldType;
2158 pAuthType->ChangeEntryContent(pNewData);
2159 break;
2165 void SwDocUpdtFld::InsDelFldInFldLst( bool bIns, const SwTxtFld& rFld )
2167 sal_uInt16 nWhich = rFld.GetFld().GetFld()->GetTyp()->Which();
2168 switch( nWhich )
2170 case RES_DBFLD:
2171 case RES_SETEXPFLD:
2172 case RES_HIDDENPARAFLD:
2173 case RES_HIDDENTXTFLD:
2174 case RES_DBNUMSETFLD:
2175 case RES_DBNEXTSETFLD:
2176 case RES_DBSETNUMBERFLD:
2177 case RES_GETEXPFLD:
2178 break; // these have to be added/removed!
2180 default:
2181 return;
2184 SetFieldsDirty( true );
2185 if( !pFldSortLst )
2187 if( !bIns ) // if list is present and deleted
2188 return; // don't do a thing
2189 pFldSortLst = new _SetGetExpFlds;
2192 if( bIns ) // insert anew:
2193 GetBodyNode( rFld, nWhich );
2194 else
2196 // look up via the pTxtFld pointer. It is a sorted list, but it's sorted by node
2197 // position. Until this is found, the search for the pointer is already done.
2198 for( sal_uInt16 n = 0; n < pFldSortLst->size(); ++n )
2199 if( &rFld == (*pFldSortLst)[ n ]->GetPointer() )
2201 delete (*pFldSortLst)[n];
2202 pFldSortLst->erase(n);
2203 n--; // one field can occur multiple times
2208 void SwDocUpdtFld::MakeFldList( SwDoc& rDoc, int bAll, int eGetMode )
2210 if( !pFldSortLst || bAll || !( eGetMode & nFldLstGetMode ) ||
2211 rDoc.GetNodes().Count() != nNodes )
2212 _MakeFldList( rDoc, eGetMode );
2215 void SwDocUpdtFld::_MakeFldList( SwDoc& rDoc, int eGetMode )
2217 // new version: walk all fields of the attribute pool
2218 delete pFldSortLst;
2219 pFldSortLst = new _SetGetExpFlds;
2221 /// consider and unhide sections
2222 /// with hide condition, only in mode GETFLD_ALL (<eGetMode == GETFLD_ALL>)
2223 /// notes by OD:
2224 /// eGetMode == GETFLD_CALC in call from methods SwDoc::FldsToCalc
2225 /// eGetMode == GETFLD_EXPAND in call from method SwDoc::FldsToExpand
2226 /// eGetMode == GETFLD_ALL in call from method SwDoc::UpdateExpFlds
2227 /// I figured out that hidden section only have to be shown,
2228 /// if fields have updated (call by SwDoc::UpdateExpFlds) and thus
2229 /// the hide conditions of section have to be updated.
2230 /// For correct updating the hide condition of a section, its position
2231 /// have to be known in order to insert the hide condition as a new
2232 /// expression field into the sorted field list (<pFldSortLst>).
2233 if ( eGetMode == GETFLD_ALL )
2234 // Collect the sections first. Supply sections that are hidden by condition
2235 // with frames so that the contained fields are sorted properly.
2237 // In order for the frames to be created the right way, they have to be expanded
2238 // from top to bottom
2239 std::vector<sal_uLong> aTmpArr;
2240 SwSectionFmts& rArr = rDoc.GetSections();
2241 SwSectionNode* pSectNd;
2242 sal_uInt16 nArrStt = 0;
2243 sal_uLong nSttCntnt = rDoc.GetNodes().GetEndOfExtras().GetIndex();
2245 for (sal_uInt16 n = rArr.size(); n; )
2247 SwSection* pSect = rArr[ --n ]->GetSection();
2248 if( pSect && pSect->IsHidden() && pSect->GetCondition().Len() &&
2249 0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() ))
2251 sal_uLong nIdx = pSectNd->GetIndex();
2252 aTmpArr.push_back( nIdx );
2253 if( nIdx < nSttCntnt )
2254 ++nArrStt;
2257 std::sort(aTmpArr.begin(), aTmpArr.end());
2259 // Display all first so that we have frames. The BodyAnchor is defined by that.
2260 // First the ContentArea, then the special areas!
2261 for (sal_uInt16 n = nArrStt; n < aTmpArr.size(); ++n)
2263 pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
2264 OSL_ENSURE( pSectNd, "Where is my SectionNode" );
2265 pSectNd->GetSection().SetCondHidden( sal_False );
2267 for (sal_uInt16 n = 0; n < nArrStt; ++n)
2269 pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode();
2270 OSL_ENSURE( pSectNd, "Where is my SectionNode" );
2271 pSectNd->GetSection().SetCondHidden( sal_False );
2274 // add all to the list so that they are sorted
2275 for (sal_uInt16 n = 0; n < aTmpArr.size(); ++n)
2277 GetBodyNode( *rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode() );
2281 rtl::OUString sTrue("TRUE"), sFalse("FALSE");
2283 bool bIsDBMgr = 0 != rDoc.GetNewDBMgr();
2284 sal_uInt16 nWhich, n;
2285 const rtl::OUString* pFormel = 0;
2286 const SfxPoolItem* pItem;
2287 sal_uInt32 nMaxItems = rDoc.GetAttrPool().GetItemCount2( RES_TXTATR_FIELD );
2288 for( n = 0; n < nMaxItems; ++n )
2290 if( 0 == (pItem = rDoc.GetAttrPool().GetItem2( RES_TXTATR_FIELD, n )) )
2291 continue;
2293 const SwFmtFld* pFmtFld = (SwFmtFld*)pItem;
2294 const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
2295 if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
2296 continue;
2298 const SwField* pFld = pFmtFld->GetFld();
2299 switch( nWhich = pFld->GetTyp()->Which() )
2301 case RES_DBSETNUMBERFLD:
2302 case RES_GETEXPFLD:
2303 if( GETFLD_ALL == eGetMode )
2304 pFormel = &sTrue;
2305 break;
2307 case RES_DBFLD:
2308 if( GETFLD_EXPAND & eGetMode )
2309 pFormel = &sTrue;
2310 break;
2312 case RES_SETEXPFLD:
2313 if ( !(eGetMode == GETFLD_EXPAND) ||
2314 (nsSwGetSetExpType::GSE_STRING & pFld->GetSubType()) )
2316 pFormel = &sTrue;
2318 break;
2320 case RES_HIDDENPARAFLD:
2321 if( GETFLD_ALL == eGetMode )
2323 pFormel = &pFld->GetPar1();
2324 if (pFormel->isEmpty() || pFormel->equals(sFalse))
2325 ((SwHiddenParaField*)pFld)->SetHidden( sal_False );
2326 else if (pFormel->equals(sTrue))
2327 ((SwHiddenParaField*)pFld)->SetHidden( sal_True );
2328 else
2329 break;
2331 pFormel = 0;
2332 // trigger formatting
2333 ((SwFmtFld*)pFmtFld)->ModifyNotification( 0, 0 );
2335 break;
2337 case RES_HIDDENTXTFLD:
2338 if( GETFLD_ALL == eGetMode )
2340 pFormel = &pFld->GetPar1();
2341 if (pFormel->isEmpty() || pFormel->equals(sFalse))
2342 ((SwHiddenTxtField*)pFld)->SetValue( sal_True );
2343 else if (pFormel->equals(sTrue))
2344 ((SwHiddenTxtField*)pFld)->SetValue( sal_False );
2345 else
2346 break;
2348 pFormel = 0;
2350 // evaluate field
2351 ((SwHiddenTxtField*)pFld)->Evaluate(&rDoc);
2352 // trigger formatting
2353 ((SwFmtFld*)pFmtFld)->ModifyNotification( 0, 0 );
2355 break;
2357 case RES_DBNUMSETFLD:
2359 SwDBData aDBData(((SwDBNumSetField*)pFld)->GetDBData(&rDoc));
2361 if (
2362 (bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) &&
2363 (GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNumSetField*)pFld)->IsCondValid()))
2366 pFormel = &pFld->GetPar1();
2369 break;
2370 case RES_DBNEXTSETFLD:
2372 SwDBData aDBData(((SwDBNextSetField*)pFld)->GetDBData(&rDoc));
2374 if (
2375 (bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) &&
2376 (GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNextSetField*)pFld)->IsCondValid()))
2379 pFormel = &pFld->GetPar1();
2382 break;
2385 if (pFormel && !pFormel->isEmpty())
2387 GetBodyNode( *pTxtFld, nWhich );
2388 pFormel = 0;
2391 nFldLstGetMode = static_cast<sal_uInt8>( eGetMode );
2392 nNodes = rDoc.GetNodes().Count();
2395 void SwDocUpdtFld::GetBodyNode( const SwTxtFld& rTFld, sal_uInt16 nFldWhich )
2397 const SwTxtNode& rTxtNd = rTFld.GetTxtNode();
2398 const SwDoc& rDoc = *rTxtNd.GetDoc();
2400 // always the first! (in tab headline, header-/footer)
2401 Point aPt;
2402 const SwCntntFrm* pFrm = rTxtNd.getLayoutFrm( rDoc.GetCurrentLayout(), &aPt, 0, sal_False );
2404 _SetGetExpFld* pNew = NULL;
2405 sal_Bool bIsInBody = sal_False;
2407 if( !pFrm || pFrm->IsInDocBody() )
2409 // create index to determine the TextNode
2410 SwNodeIndex aIdx( rTxtNd );
2411 bIsInBody = rDoc.GetNodes().GetEndOfExtras().GetIndex() < aIdx.GetIndex();
2413 // We don't want to update fields in redlines, or those
2414 // in frames whose anchor is in redline. However, we do want to update
2415 // fields in hidden sections. So: In order to be updated, a field 1)
2416 // must have a frame, or 2) it must be in the document body.
2417 if( (pFrm != NULL) || bIsInBody )
2418 pNew = new _SetGetExpFld( aIdx, &rTFld );
2420 else
2422 // create index to determine the TextNode
2423 SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() );
2424 bool const bResult = GetBodyTxtNode( rDoc, aPos, *pFrm );
2425 OSL_ENSURE(bResult, "where is the Field");
2426 (void) bResult; // unused in non-debug
2427 pNew = new _SetGetExpFld( aPos.nNode, &rTFld, &aPos.nContent );
2430 // always set the BodyTxtFlag in GetExp or DB fields
2431 if( RES_GETEXPFLD == nFldWhich )
2433 SwGetExpField* pGetFld = (SwGetExpField*)rTFld.GetFld().GetFld();
2434 pGetFld->ChgBodyTxtFlag( bIsInBody );
2436 else if( RES_DBFLD == nFldWhich )
2438 SwDBField* pDBFld = (SwDBField*)rTFld.GetFld().GetFld();
2439 pDBFld->ChgBodyTxtFlag( bIsInBody );
2442 if( pNew != NULL )
2443 if( !pFldSortLst->insert( pNew ).second )
2444 delete pNew;
2447 void SwDocUpdtFld::GetBodyNode( const SwSectionNode& rSectNd )
2449 const SwDoc& rDoc = *rSectNd.GetDoc();
2450 _SetGetExpFld* pNew = 0;
2452 if( rSectNd.GetIndex() < rDoc.GetNodes().GetEndOfExtras().GetIndex() )
2454 do { // middle check loop
2456 // we need to get the anchor first
2457 // create index to determine the TextNode
2458 SwPosition aPos( rSectNd );
2459 SwCntntNode* pCNd = rDoc.GetNodes().GoNext( &aPos.nNode ); // to the next ContentNode
2461 if( !pCNd || !pCNd->IsTxtNode() )
2462 break;
2464 // always the first! (in tab headline, header-/footer)
2465 Point aPt;
2466 const SwCntntFrm* pFrm = pCNd->getLayoutFrm( rDoc.GetCurrentLayout(), &aPt, 0, sal_False );
2467 if( !pFrm )
2468 break;
2470 bool const bResult = GetBodyTxtNode( rDoc, aPos, *pFrm );
2471 OSL_ENSURE(bResult, "where is the Field");
2472 (void) bResult; // unused in non-debug
2473 pNew = new _SetGetExpFld( rSectNd, &aPos );
2475 } while( sal_False );
2478 if( !pNew )
2479 pNew = new _SetGetExpFld( rSectNd );
2481 if( !pFldSortLst->insert( pNew ).second )
2482 delete pNew;
2485 void SwDocUpdtFld::InsertFldType( const SwFieldType& rType )
2487 String sFldName;
2488 switch( rType.Which() )
2490 case RES_USERFLD :
2491 sFldName = ((SwUserFieldType&)rType).GetName();
2492 break;
2493 case RES_SETEXPFLD:
2494 sFldName = ((SwSetExpFieldType&)rType).GetName();
2495 break;
2496 default:
2497 OSL_ENSURE( !this, "kein gueltiger FeldTyp" );
2500 if( sFldName.Len() )
2502 SetFieldsDirty( true );
2503 // look up and remove from the hash table
2504 sFldName = GetAppCharClass().lowercase( sFldName );
2505 sal_uInt16 n;
2507 SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n );
2509 if( !pFnd )
2511 SwCalcFldType* pNew = new SwCalcFldType( sFldName, &rType );
2512 pNew->pNext = aFldTypeTable[ n ];
2513 aFldTypeTable[ n ] = pNew;
2518 void SwDocUpdtFld::RemoveFldType( const SwFieldType& rType )
2520 String sFldName;
2521 switch( rType.Which() )
2523 case RES_USERFLD :
2524 sFldName = ((SwUserFieldType&)rType).GetName();
2525 break;
2526 case RES_SETEXPFLD:
2527 sFldName = ((SwSetExpFieldType&)rType).GetName();
2528 break;
2531 if( sFldName.Len() )
2533 SetFieldsDirty( true );
2534 // look up and remove from the hash table
2535 sFldName = GetAppCharClass().lowercase( sFldName );
2536 sal_uInt16 n;
2538 SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n );
2539 if( pFnd )
2541 if( aFldTypeTable[ n ] == pFnd )
2542 aFldTypeTable[ n ] = (SwCalcFldType*)pFnd->pNext;
2543 else
2545 SwHash* pPrev = aFldTypeTable[ n ];
2546 while( pPrev->pNext != pFnd )
2547 pPrev = pPrev->pNext;
2548 pPrev->pNext = pFnd->pNext;
2550 pFnd->pNext = 0;
2551 delete pFnd;
2556 SwDocUpdtFld::SwDocUpdtFld()
2557 : pFldSortLst(0), nFldLstGetMode(0)
2559 bInUpdateFlds = bFldsDirty = sal_False;
2560 memset( aFldTypeTable, 0, sizeof( aFldTypeTable ) );
2563 SwDocUpdtFld::~SwDocUpdtFld()
2565 delete pFldSortLst;
2567 for( sal_uInt16 n = 0; n < TBLSZ; ++n )
2568 delete aFldTypeTable[n];
2571 bool SwDoc::UpdateFld(SwTxtFld * pDstTxtFld, SwField & rSrcFld,
2572 SwMsgPoolItem * pMsgHnt,
2573 bool bUpdateFlds)
2575 OSL_ENSURE(pDstTxtFld, "no field to update!");
2577 bool bTblSelBreak = false;
2579 SwFmtFld * pDstFmtFld = (SwFmtFld*)&pDstTxtFld->GetFld();
2580 SwField * pDstFld = pDstFmtFld->GetFld();
2581 sal_uInt16 nFldWhich = rSrcFld.GetTyp()->Which();
2582 SwNodeIndex aTblNdIdx(pDstTxtFld->GetTxtNode());
2584 if (pDstFld->GetTyp()->Which() ==
2585 rSrcFld.GetTyp()->Which())
2587 if (GetIDocumentUndoRedo().DoesUndo())
2589 SwPosition aPosition( pDstTxtFld->GetTxtNode() );
2590 aPosition.nContent = *pDstTxtFld->GetStart();
2592 SwUndo *const pUndo( new SwUndoFieldFromDoc(
2593 aPosition, *pDstFld, rSrcFld, pMsgHnt, bUpdateFlds) );
2594 GetIDocumentUndoRedo().AppendUndo(pUndo);
2597 SwField * pNewFld = rSrcFld.CopyField();
2598 pDstFmtFld->SetFld(pNewFld);
2600 switch( nFldWhich )
2602 case RES_SETEXPFLD:
2603 case RES_GETEXPFLD:
2604 case RES_HIDDENTXTFLD:
2605 case RES_HIDDENPARAFLD:
2606 UpdateExpFlds( pDstTxtFld, true );
2607 break;
2609 case RES_TABLEFLD:
2611 const SwTableNode* pTblNd =
2612 IsIdxInTbl(aTblNdIdx);
2613 if( pTblNd )
2615 SwTableFmlUpdate aTblUpdate( &pTblNd->
2616 GetTable() );
2617 if (bUpdateFlds)
2618 UpdateTblFlds( &aTblUpdate );
2619 else
2620 pNewFld->GetTyp()->ModifyNotification(0, &aTblUpdate);
2622 if (! bUpdateFlds)
2623 bTblSelBreak = true;
2626 break;
2628 case RES_MACROFLD:
2629 if( bUpdateFlds && pDstTxtFld->GetpTxtNode() )
2630 (pDstTxtFld->GetpTxtNode())->
2631 ModifyNotification( 0, pDstFmtFld );
2632 break;
2634 case RES_DBNAMEFLD:
2635 case RES_DBNEXTSETFLD:
2636 case RES_DBNUMSETFLD:
2637 case RES_DBSETNUMBERFLD:
2638 ChgDBData(((SwDBNameInfField*) pNewFld)->GetRealDBData());
2639 pNewFld->GetTyp()->UpdateFlds();
2641 break;
2643 case RES_DBFLD:
2645 // JP 10.02.96: call ChgValue, so that the style change sets the
2646 // ContentString correctly
2647 SwDBField* pDBFld = (SwDBField*)pNewFld;
2648 if (pDBFld->IsInitialized())
2649 pDBFld->ChgValue( pDBFld->GetValue(), sal_True );
2651 pDBFld->ClearInitialized();
2652 pDBFld->InitContent();
2654 // no break;
2656 default:
2657 pDstFmtFld->ModifyNotification( 0, pMsgHnt );
2660 // The fields we can calculate here are being triggered for an update
2661 // here explicitly.
2662 if( nFldWhich == RES_USERFLD )
2663 UpdateUsrFlds();
2666 return bTblSelBreak;
2669 bool SwDoc::PutValueToField(const SwPosition & rPos,
2670 const Any& rVal, sal_uInt16 nWhich)
2672 Any aOldVal;
2673 SwField * pField = GetField(rPos);
2676 if (GetIDocumentUndoRedo().DoesUndo() &&
2677 pField->QueryValue(aOldVal, nWhich))
2679 SwUndo *const pUndo(new SwUndoFieldFromAPI(rPos, aOldVal, rVal, nWhich));
2680 GetIDocumentUndoRedo().AppendUndo(pUndo);
2683 return pField->PutValue(rVal, nWhich);
2686 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */