1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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>
30 #include <IDocumentUndoRedo.hxx>
34 #include <swtable.hxx>
39 #include <txttxmrk.hxx>
40 #include <docfld.hxx> // for expression fields
41 #include <docufld.hxx>
49 #include <flddropdown.hxx>
51 #include <section.hxx>
52 #include <cellatr.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
;
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
;
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
];
105 for( ; i
< nSize
; ++i
)
106 if( nFldWhich
== (*pFldTypes
)[i
]->Which() )
107 return (*pFldTypes
)[i
];
111 for( i
= 0; i
< nSize
; ++i
)
112 if( nFldWhich
== (*pFldTypes
)[i
]->Which() )
113 return (*pFldTypes
)[i
];
116 SwFieldType
* pNew
= rFldTyp
.Copy();
120 ((SwDDEFieldType
*)pNew
)->SetDoc( this );
125 case RES_DATETIMEFLD
:
127 ((SwValueFieldType
*)pNew
)->SetDoc( this );
132 ((SwValueFieldType
*)pNew
)->SetDoc( this );
133 // JP 29.07.96: Optionally prepare FieldList for Calculator:
134 pUpdtFlds
->InsertFldType( *pNew
);
137 ((SwAuthorityFieldType
*)pNew
)->SetDoc( this );
141 pFldTypes
->insert( pFldTypes
->begin() + nSize
, pNew
);
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();
165 for( ; i
< nSize
; ++i
)
166 if( nFldWhich
== (pFnd
= (*pFldTypes
)[i
])->Which() &&
167 rSCmp
.isEqual( rFldNm
, pFnd
->GetName() ) )
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() ) )
179 if( i
>= nSize
) // not found
181 ((String
&)rFldNm
) = sSrch
;
182 break; // exit while loop
189 // not found, so insert and delete flag
190 pFldTypes
->insert( pFldTypes
->begin() + nSize
, &rFldTyp
);
194 ((SwSetExpFieldType
&)rFldTyp
).SetDeleted( sal_False
);
197 ((SwUserFieldType
&)rFldTyp
).SetDeleted( sal_False
);
200 ((SwDDEFieldType
&)rFldTyp
).SetDeleted( sal_False
);
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();
217 SwFieldType
* pTmp
= (*pFldTypes
)[nFld
];
219 // JP 29.07.96: Optionally prepare FldLst for Calculator
220 sal_uInt16 nWhich
= pTmp
->Which();
225 pUpdtFlds
->RemoveFldType( *pTmp
);
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
);
235 ((SwDDEFieldType
*)pTmp
)->SetDeleted( sal_True
);
243 OSL_ENSURE( !pTmp
->GetDepends(), "Dependent fields present!" );
247 pFldTypes
->erase( pFldTypes
->begin() + nFld
);
252 const SwFldTypes
* SwDoc::GetFldTypes() const
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
266 sal_uInt16 nSize
= pFldTypes
->size(), i
= 0;
267 const ::utl::TransliterationWrapper
& rSCmp
= GetAppCmpStrIgnore();
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
;
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
))
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
327 case RES_JUMPEDITFLD
:
328 case RES_REFPAGESETFLD
: // are never expanded!
335 SwMsgPoolItem
aUpdateDDE( RES_UPDATEDDETBL
);
336 (*pFldTypes
)[i
]->ModifyNotification( 0, &aUpdateDDE
);
339 (*pFldTypes
)[i
]->ModifyNotification( 0, pNewHt
);
344 case RES_HIDDENTXTFLD
:
345 case RES_HIDDENPARAFLD
:
346 // Expression fields are treated seperately
350 (*pFldTypes
)[i
]->ModifyNotification ( 0, pNewHt
);
354 if( !IsExpFldsLocked() )
355 UpdateExpFlds( 0, sal_False
); // update expression fields
358 UpdateTblFlds(pNewHt
);
361 UpdateRefFlds(pNewHt
);
364 GetNewDBMgr()->CloseAll();
366 // Only evaluate on full update
370 /******************************************************************************
371 * void SwDoc::UpdateUsrFlds()
372 ******************************************************************************/
373 void SwDoc::UpdateUsrFlds()
376 const SwFieldType
* pFldType
;
377 for( sal_uInt16 i
= INIT_FLDTYPES
; i
< pFldTypes
->size(); ++i
)
378 if( RES_USERFLD
== ( pFldType
= (*pFldTypes
)[i
] )->Which() )
381 pCalc
= new SwCalc( *this );
382 ((SwUserFieldType
*)pFldType
)->GetValue( *pCalc
);
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
);
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();
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() ) )
448 switch( pUpdtFld
->eFlags
)
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
);
457 pFld
->ChgValid( sal_False
);
460 // is this the wanted table?
461 if( &pTblNd
->GetTable() == pUpdtFld
->pTbl
)
462 // to the external representation
463 pFld
->PtrToBoxNm( pUpdtFld
->pTbl
);
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
);
472 // is this the wanted table?
473 if( &pTblNd
->GetTable() == pUpdtFld
->pTbl
)
474 // to the relative representation
475 pFld
->ToRelBoxNm( pUpdtFld
->pTbl
);
482 // reset the value flag for all
483 pFld
->ChgValid( sal_False
);
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
))
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?
522 if( !pFmtFld
->GetTxtFld() || (nsSwExtendedSubType::SUB_CMD
&
523 (pFld
= (SwTblField
*)pFmtFld
->GetFld())->GetSubType() ))
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() )
533 const SwTableNode
* pTblNd
= rTxtNd
.FindTableNode();
537 // if this field is not in the to-be-updated table, skip it
538 if( pHt
&& &pTblNd
->GetTable() !=
539 ((SwTableFmlUpdate
*)pHt
)->pTbl
)
543 pCalc
= new SwCalc( *this );
545 // get the values of all SetExpression fields that are valid
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
);
555 SwPosition
aPos( *pTblNd
);
556 if( GetBodyTxtNode( *this, aPos
, *pFrm
) )
557 FldsToCalc( *pCalc
, _SetGetExpFld(
558 aPos
.nNode
, pFmtFld
->GetTxtFld(),
566 // create index to determine the TextNode
567 SwNodeIndex
aIdx( rTxtNd
);
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();
579 pFld
->CalcField( aPara
);
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
)
608 pCalc
= new SwCalc( *this );
610 // get the values of all SetExpression fields that are valid
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();
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
));
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();
646 pFml
->Calc( aPara
, nValue
);
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() )
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
);
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
:
681 case RES_REFPAGEGETFLD
:
682 pFldType
->ModifyNotification( 0, pMsgHnt
);
685 pFldType
->ModifyNotification( 0, 0 );
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() )
699 void SwDoc::LockExpFlds()
704 void SwDoc::UnlockExpFlds()
710 bool SwDoc::IsExpFldsLocked() const
712 return 0 != nLockExpFld
;
715 SwDocUpdtFld
& SwDoc::GetUpdtFlds() const
720 bool SwDoc::IsNewFldLst() const
725 void SwDoc::SetNewFldLst(bool 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();
739 nCntnt
= pIdx
->GetIndex();
741 nCntnt
= *pFld
->GetStart();
746 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex
& rNdIdx
,
747 const SwTxtINetFmt
& rINet
, const SwIndex
* pIdx
)
749 eSetGetExpFldType
= TEXTINET
;
750 CNTNT
.pTxtINet
= &rINet
;
751 nNode
= rNdIdx
.GetIndex();
753 nCntnt
= pIdx
->GetIndex();
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();
769 nNode
= pPos
->nNode
.GetIndex();
770 nCntnt
= pPos
->nContent
.GetIndex();
774 nNode
= rSectNd
.GetIndex();
779 _SetGetExpFld::_SetGetExpFld( const SwTableBox
& rTBox
, const SwPosition
* pPos
)
781 eSetGetExpFldType
= TABLEBOX
;
782 CNTNT
.pTBox
= &rTBox
;
786 nNode
= pPos
->nNode
.GetIndex();
787 nCntnt
= pPos
->nContent
.GetIndex();
793 if( rTBox
.GetSttNd() )
795 SwNodeIndex
aIdx( *rTBox
.GetSttNd() );
796 const SwCntntNode
* pNd
= aIdx
.GetNode().GetNodes().GoNext( &aIdx
);
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();
811 nCntnt
= pIdx
->GetIndex();
813 nCntnt
= *rTOX
.GetStart();
816 _SetGetExpFld::_SetGetExpFld( const SwPosition
& rPos
)
818 eSetGetExpFldType
= CRSRPOS
;
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
;
831 nNode
= pPos
->nNode
.GetIndex();
832 nCntnt
= pPos
->nContent
.GetIndex();
836 const SwFmtCntnt
& rCntnt
= rFlyFmt
.GetCntnt();
837 nNode
= rCntnt
.GetCntntIdx()->GetIndex() + 1;
842 void _SetGetExpFld::GetPos( SwPosition
& rPos
) const
845 rPos
.nContent
.Assign( rPos
.nNode
.GetNode().GetCntntNode(), nCntnt
);
848 void _SetGetExpFld::GetPosOfContent( SwPosition
& rPos
) const
850 const SwNode
* pNd
= GetNodeFromCntnt();
852 pNd
= pNd
->GetCntntNode();
857 rPos
.nContent
.Assign( (SwCntntNode
*)pNd
,GetCntPosFromCntnt() );
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
))
885 else if( nNode
!= rFld
.nNode
|| nCntnt
!= rFld
.nCntnt
)
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
)
896 if( pFirst
->StartOfSectionNode() != pNext
->StartOfSectionNode() )
898 // is one in the table?
899 const SwNode
*pFirstStt
, *pNextStt
;
900 const SwTableNode
* pTblNd
= pFirst
->FindTableNode();
902 pFirstStt
= pTblNd
->StartOfSectionNode();
904 pFirstStt
= pFirst
->StartOfSectionNode();
906 if( 0 != ( pTblNd
= pNext
->FindTableNode() ) )
907 pNextStt
= pTblNd
->StartOfSectionNode();
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;
935 switch( eSetGetExpFldType
)
938 pRet
= &CNTNT
.pTxtFld
->GetTxtNode();
942 pRet
= &CNTNT
.pTxtINet
->GetTxtNode();
946 pRet
= CNTNT
.pSection
->GetFmt()->GetSectionNode();
950 pRet
= &CNTNT
.pPos
->nNode
.GetNode();
954 pRet
= &CNTNT
.pTxtTOX
->GetTxtNode();
958 if( CNTNT
.pTBox
->GetSttNd() )
960 SwNodeIndex
aIdx( *CNTNT
.pTBox
->GetSttNd() );
961 pRet
= aIdx
.GetNode().GetNodes().GoNext( &aIdx
);
967 SwNodeIndex
aIdx( *CNTNT
.pFlyFmt
->GetCntnt().GetCntntIdx() );
968 pRet
= aIdx
.GetNode().GetNodes().GoNext( &aIdx
);
975 xub_StrLen
_SetGetExpFld::GetCntPosFromCntnt() const
979 switch( eSetGetExpFldType
)
984 nRet
= *CNTNT
.pTxtFld
->GetStart();
987 nRet
= CNTNT
.pPos
->nContent
.GetIndex();
995 _HashStr::_HashStr( const String
& rName
, const String
& rText
,
997 : SwHash( rName
), aSetStr( rText
)
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
);
1009 rRet
= ((_HashStr
*)pFnd
)->aSetStr
;
1014 static String
lcl_GetDBVarName( SwDoc
& rDoc
, SwDBNameInfField
& rDBFld
)
1016 SwDBData
aDBData( rDBFld
.GetDBData( &rDoc
));
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
);
1032 static void lcl_CalcFld( SwDoc
& rDoc
, SwCalc
& rCalc
, const _SetGetExpFld
& rSGEFld
,
1035 const SwTxtFld
* pTxtFld
= rSGEFld
.GetFld();
1039 const SwField
* pFld
= pTxtFld
->GetFld().GetFld();
1040 const sal_uInt16 nFldWhich
= pFld
->GetTyp()->Which();
1042 if( RES_SETEXPFLD
== nFldWhich
)
1045 if( nsSwGetSetExpType::GSE_EXPR
& pFld
->GetSubType() )
1046 aValue
.PutDouble( ((SwSetExpField
*)pFld
)->GetValue() );
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
);
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() );
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
))
1078 String
sDBNumNm(lcl_GetDBVarName( rDoc
, *pDBFld
));
1079 SwCalcExp
* pExp
= rCalc
.VarLook( sDBNumNm
);
1081 rCalc
.VarChange( sDBNumNm
, pExp
->nValue
.GetLong() + 1 );
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
)
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();
1155 const SwField
* pFld
= pTxtFld
->GetFld().GetFld();
1156 switch( pFld
->GetTyp()->Which() )
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
;
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();
1178 SwHash
* pFnd
= Find( aNew
, ppHashTbl
, rTblSize
, &nPos
);
1180 // modify entry in the hash table
1181 ((_HashStr
*)pFnd
)->aSetStr
= pSFld
->GetExpStr();
1183 // insert the new entry
1184 *(ppHashTbl
+ nPos
) = new _HashStr( aNew
,
1185 pSFld
->GetExpStr(), (_HashStr
*)*(ppHashTbl
+ nPos
) );
1190 const String
& rName
= pFld
->GetTyp()->GetName();
1192 // Insert entry in the hash table
1195 SwHash
* pFnd
= Find( rName
, ppHashTbl
, rTblSize
, &nPos
);
1196 String
const value(pFld
->ExpandField(IsClipBoard()));
1199 // modify entry in the hash table
1200 static_cast<_HashStr
*>(pFnd
)->aSetStr
= value
;
1204 // insert the new entry
1205 *(ppHashTbl
+ nPos
) = new _HashStr( rName
,
1206 value
, static_cast<_HashStr
*>(*(ppHashTbl
+ nPos
)));
1214 void SwDoc::UpdateExpFlds( SwTxtFld
* pUpdtFld
, bool bUpdRefFlds
)
1216 if( IsExpFldsLocked() || IsInReading() )
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() )
1228 UpdateRefFlds(NULL
);
1230 pUpdtFlds
->SetInUpdateFlds( bOldInUpdateFlds
);
1231 pUpdtFlds
->SetFieldsDirty( false );
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() )
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
);
1257 // modify entry in the hash table
1258 ((_HashStr
*)pFnd
)->aSetStr
= sExpand
;
1260 // insert the new entry
1261 *(pHashStrTbl
+ nPos
) = new _HashStr( rNm
, sExpand
,
1262 (_HashStr
*)*(pHashStrTbl
+ nPos
) );
1266 ((SwSetExpFieldType
*)pFldType
)->SetOutlineChgNd( 0 );
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())
1290 for( _SetGetExpFlds::const_iterator it
= pUpdtFlds
->GetSortLst()->begin(); it
!= pUpdtFlds
->GetSortLst()->end(); ++it
)
1292 SwSection
* pSect
= (SwSection
*)(*it
)->GetSection();
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
);
1314 pSect
->SetCondHidden( bHide
);
1319 SwTxtFld
* pTxtFld
= (SwTxtFld
*)(*it
)->GetFld();
1322 OSL_ENSURE( !this, "what's wrong now'" );
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
);
1340 pHFld
->Evaluate(this);
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
);
1353 case RES_DBSETNUMBERFLD
:
1355 ((SwDBSetNumberField
*)pFld
)->Evaluate(this);
1356 aCalc
.VarChange( sDBNumNm
, ((SwDBSetNumberField
*)pFld
)->GetSetNumber());
1359 case RES_DBNEXTSETFLD
:
1360 case RES_DBNUMSETFLD
:
1361 UpdateDBNumFlds( *(SwDBNameInfField
*)pFld
, aCalc
);
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
1384 SwHash
* pFnd
= Find( rName
, pHashStrTbl
, nStrFmtCnt
, &nPos
);
1385 String
const value(pFld
->ExpandField(IsClipBoard()));
1388 // Modify entry in the hash table
1389 static_cast<_HashStr
*>(pFnd
)->aSetStr
= value
;
1394 *(pHashStrTbl
+ nPos
) = new _HashStr( rName
,
1395 value
, static_cast<_HashStr
*>(*(pHashStrTbl
+ nPos
)));
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
);
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();
1434 SwHash
* pFnd
= Find( aNew
, pHashStrTbl
, nStrFmtCnt
, &nPos
);
1436 // Modify entry in the hash table
1437 ((_HashStr
*)pFnd
)->aSetStr
= pSFld
->GetExpStr();
1440 *(pHashStrTbl
+ nPos
) = pFnd
= new _HashStr( aNew
,
1442 (_HashStr
*)*(pHashStrTbl
+ nPos
) );
1444 // Extension for calculation with Strings
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() );
1467 SwSetExpField
* pSFld
= (SwSetExpField
*)pFld
;
1468 SwSetExpFieldType
* pSFldTyp
= (SwSetExpFieldType
*)pFld
->GetTyp();
1469 aNew
= pSFldTyp
->GetName();
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 );
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
);
1502 pSFldTyp
->SetChapter( *pSFld
, *pSeqNd
);
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?
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
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
);
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);
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
) );
1562 OSL_FAIL("TODO: what should happen with unnamed DBFields?");
1566 void SwDoc::_InitFieldTypes() // is being called by the CTOR
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()
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
))
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
)
1650 (static_cast < SwDBFieldType
* > (pFld
->GetFld()->GetTyp()))
1653 aDBData
= (static_cast < SwDBNameInfField
* > (pFld
->GetFld()))->GetRealDBData();
1663 if(aDBData
.sDataSource
.isEmpty())
1664 aDBData
= GetNewDBMgr()->GetAddressDBName();
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
;
1680 sRet
+= (String
)rData
.sCommand
;
1682 sRet
+= String::CreateFromInt32(rData
.nCommandType
);
1686 void SwDoc::GetAllUsedDB( std::vector
<String
>& rDBNameList
,
1687 const std::vector
<String
>* pAllDBNames
)
1689 std::vector
<String
> aUsedDBNames
;
1690 std::vector
<String
> aAllDBNames
;
1694 GetAllDBNames( aAllDBNames
);
1695 pAllDBNames
= &aAllDBNames
;
1698 SwSectionFmts
& rArr
= GetSections();
1699 for (sal_uInt16 n
= rArr
.size(); n
; )
1701 SwSection
* pSect
= rArr
[ --n
]->GetSection();
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
) ))
1719 const SwFmtFld
* pFmtFld
= (SwFmtFld
*)pItem
;
1720 const SwTxtFld
* pTxtFld
= pFmtFld
->GetTxtFld();
1721 if( !pTxtFld
|| !pTxtFld
->GetTxtNode().GetNodes().IsDocNodes() )
1724 const SwField
* pFld
= pFmtFld
->GetFld();
1725 switch( pFld
->GetTyp()->Which() )
1728 AddUsedDBToList( rDBNameList
,
1729 lcl_DBDataToString(((SwDBField
*)pFld
)->GetDBData() ));
1732 case RES_DBSETNUMBERFLD
:
1734 AddUsedDBToList( rDBNameList
,
1735 lcl_DBDataToString(((SwDBNameInfField
*)pFld
)->GetRealDBData() ));
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();
1754 AddUsedDBToList(rDBNameList
, FindUsedDBs( *pAllDBNames
,
1755 pFld
->GetFormula(), aUsedDBNames
));
1756 aUsedDBNames
.clear();
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
);
1784 sFormel
= rCC
.uppercase( sFormel
);
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
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() )
1823 for( sal_uInt16 i
= 0; i
< rDBNameList
.size(); ++i
)
1824 if( rDBName
== rDBNameList
[i
].GetToken(0) )
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) ) )
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();
1851 SwSectionFmts
& rArr
= GetSections();
1852 for (sal_uInt16 n
= rArr
.size(); n
; )
1854 SwSection
* pSect
= rArr
[ --n
]->GetSection();
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
) ))
1872 SwFmtFld
* pFmtFld
= (SwFmtFld
*)pItem
;
1873 SwTxtFld
* pTxtFld
= pFmtFld
->GetTxtFld();
1874 if( !pTxtFld
|| !pTxtFld
->GetTxtNode().GetNodes().IsDocNodes() )
1877 SwField
* pFld
= pFmtFld
->GetFld();
1878 bool bExpand
= false;
1880 switch( pFld
->GetTyp()->Which() )
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
);
1893 ((SwDBField
*)pFld
)->ClearInitialized();
1894 ((SwDBField
*)pFld
)->InitContent();
1900 case RES_DBSETNUMBERFLD
:
1902 if( IsNameInArray( rOldNames
,
1903 lcl_DBDataToString(((SwDBNameInfField
*)pFld
)->GetRealDBData())))
1905 ((SwDBNameInfField
*)pFld
)->SetDBData(aNewDBData
);
1910 case RES_DBNUMSETFLD
:
1911 case RES_DBNEXTSETFLD
:
1912 if( IsNameInArray( rOldNames
,
1913 lcl_DBDataToString(((SwDBNameInfField
*)pFld
)->GetRealDBData())))
1915 ((SwDBNameInfField
*)pFld
)->SetDBData(aNewDBData
);
1919 case RES_HIDDENTXTFLD
:
1920 case RES_HIDDENPARAFLD
:
1921 sFormel
= pFld
->GetPar1();
1922 ReplaceUsedDBs( rOldNames
, rNewName
, sFormel
);
1923 pFld
->SetPar1( sFormel
);
1930 sFormel
= pFld
->GetFormula();
1931 ReplaceUsedDBs( rOldNames
, rNewName
, sFormel
);
1932 pFld
->SetPar2( sFormel
);
1938 pTxtFld
->ExpandAlways();
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();
1983 bool SwDoc::IsNameInArray( const std::vector
<String
>& rArr
, const String
& rName
)
1986 for( sal_uInt16 i
= 0; i
< rArr
.size(); ++i
)
1987 if( rName
== rArr
[ i
] )
1990 const ::utl::TransliterationWrapper
& rSCmp
= GetAppCmpStrIgnore();
1991 for( sal_uInt16 i
= 0; i
< rArr
.size(); ++i
)
1992 if( rSCmp
.isEqual( rName
, rArr
[ i
] ))
1998 void SwDoc::SetFixFields( bool bOnlyTimeDate
, const DateTime
* pNewDateTime
)
2000 sal_Bool bIsModified
= IsModified();
2002 sal_uLong nDate
, nTime
;
2005 nDate
= pNewDateTime
->GetDate();
2006 nTime
= pNewDateTime
->GetTime();
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() )
2032 switch( aTypes
[ nStt
] )
2034 case RES_DOCINFOFLD
:
2035 if( ((SwDocInfoField
*)pFld
->GetFld())->IsFixed() )
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() ) );
2049 if( ((SwAuthorField
*)pFld
->GetFld())->IsFixed() )
2052 SwAuthorField
* pAuthorFld
= (SwAuthorField
*)pFld
->GetFld();
2053 pAuthorFld
->SetExpansion( ((SwAuthorFieldType
*)
2054 pAuthorFld
->GetTyp())->Expand(
2055 pAuthorFld
->GetFormat() ) );
2059 case RES_EXTUSERFLD
:
2060 if( ((SwExtUserField
*)pFld
->GetFld())->IsFixed() )
2063 SwExtUserField
* pExtUserFld
= (SwExtUserField
*)pFld
->GetFld();
2064 pExtUserFld
->SetExpansion( ((SwExtUserFieldType
*)
2065 pExtUserFld
->GetTyp())->Expand(
2066 pExtUserFld
->GetSubType(),
2067 pExtUserFld
->GetFormat()));
2071 case RES_DATETIMEFLD
:
2072 if( ((SwDateTimeField
*)pFld
->GetFld())->IsFixed() )
2075 ((SwDateTimeField
*)pFld
->GetFld())->SetDateTime(
2076 DateTime(Date(nDate
), Time(nTime
)) );
2080 case RES_FILENAMEFLD
:
2081 if( ((SwFileNameField
*)pFld
->GetFld())->IsFixed() )
2084 SwFileNameField
* pFileNameFld
=
2085 (SwFileNameField
*)pFld
->GetFld();
2086 pFileNameFld
->SetExpansion( ((SwFileNameFieldType
*)
2087 pFileNameFld
->GetTyp())->Expand(
2088 pFileNameFld
->GetFormat() ) );
2093 // Trigger formatting
2095 pFld
->ModifyNotification( 0, 0 );
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()*/ )
2116 sal_uLong nStt
= pChk
->GetIndex();
2117 const SwNodes
& rNds
= pChk
->GetNodes();
2120 const SwTxtNode
* pTNd
= rNds
[ nStt
++ ]->GetTxtNode();
2123 if( pTNd
->GetAttrOutlineLevel() != 0 )
2124 // update chapter fields
2126 else if( pTNd
->GetpSwpHints() && pTNd
->GetSwpHints().Count() )
2127 for( sal_uInt16 n
= 0, nEnd
= pTNd
->GetSwpHints().Count();
2130 const SwTxtAttr
* pAttr
= pTNd
->GetSwpHints()[ n
];
2131 if( RES_TXTATR_FIELD
== pAttr
->Which() )
2144 GetUpdtFlds().SetFieldsDirty( b
);
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
);
2165 void SwDocUpdtFld::InsDelFldInFldLst( bool bIns
, const SwTxtFld
& rFld
)
2167 sal_uInt16 nWhich
= rFld
.GetFld().GetFld()->GetTyp()->Which();
2172 case RES_HIDDENPARAFLD
:
2173 case RES_HIDDENTXTFLD
:
2174 case RES_DBNUMSETFLD
:
2175 case RES_DBNEXTSETFLD
:
2176 case RES_DBSETNUMBERFLD
:
2178 break; // these have to be added/removed!
2184 SetFieldsDirty( true );
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
);
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
2219 pFldSortLst
= new _SetGetExpFlds
;
2221 /// consider and unhide sections
2222 /// with hide condition, only in mode GETFLD_ALL (<eGetMode == GETFLD_ALL>)
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
)
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
)) )
2293 const SwFmtFld
* pFmtFld
= (SwFmtFld
*)pItem
;
2294 const SwTxtFld
* pTxtFld
= pFmtFld
->GetTxtFld();
2295 if( !pTxtFld
|| !pTxtFld
->GetTxtNode().GetNodes().IsDocNodes() )
2298 const SwField
* pFld
= pFmtFld
->GetFld();
2299 switch( nWhich
= pFld
->GetTyp()->Which() )
2301 case RES_DBSETNUMBERFLD
:
2303 if( GETFLD_ALL
== eGetMode
)
2308 if( GETFLD_EXPAND
& eGetMode
)
2313 if ( !(eGetMode
== GETFLD_EXPAND
) ||
2314 (nsSwGetSetExpType::GSE_STRING
& pFld
->GetSubType()) )
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
);
2332 // trigger formatting
2333 ((SwFmtFld
*)pFmtFld
)->ModifyNotification( 0, 0 );
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
);
2351 ((SwHiddenTxtField
*)pFld
)->Evaluate(&rDoc
);
2352 // trigger formatting
2353 ((SwFmtFld
*)pFmtFld
)->ModifyNotification( 0, 0 );
2357 case RES_DBNUMSETFLD
:
2359 SwDBData
aDBData(((SwDBNumSetField
*)pFld
)->GetDBData(&rDoc
));
2362 (bIsDBMgr
&& rDoc
.GetNewDBMgr()->OpenDataSource(aDBData
.sDataSource
, aDBData
.sCommand
)) &&
2363 (GETFLD_ALL
== eGetMode
|| (GETFLD_CALC
& eGetMode
&& ((SwDBNumSetField
*)pFld
)->IsCondValid()))
2366 pFormel
= &pFld
->GetPar1();
2370 case RES_DBNEXTSETFLD
:
2372 SwDBData
aDBData(((SwDBNextSetField
*)pFld
)->GetDBData(&rDoc
));
2375 (bIsDBMgr
&& rDoc
.GetNewDBMgr()->OpenDataSource(aDBData
.sDataSource
, aDBData
.sCommand
)) &&
2376 (GETFLD_ALL
== eGetMode
|| (GETFLD_CALC
& eGetMode
&& ((SwDBNextSetField
*)pFld
)->IsCondValid()))
2379 pFormel
= &pFld
->GetPar1();
2385 if (pFormel
&& !pFormel
->isEmpty())
2387 GetBodyNode( *pTxtFld
, nWhich
);
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)
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
);
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
);
2443 if( !pFldSortLst
->insert( pNew
).second
)
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() )
2464 // always the first! (in tab headline, header-/footer)
2466 const SwCntntFrm
* pFrm
= pCNd
->getLayoutFrm( rDoc
.GetCurrentLayout(), &aPt
, 0, sal_False
);
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
);
2479 pNew
= new _SetGetExpFld( rSectNd
);
2481 if( !pFldSortLst
->insert( pNew
).second
)
2485 void SwDocUpdtFld::InsertFldType( const SwFieldType
& rType
)
2488 switch( rType
.Which() )
2491 sFldName
= ((SwUserFieldType
&)rType
).GetName();
2494 sFldName
= ((SwSetExpFieldType
&)rType
).GetName();
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
);
2507 SwHash
* pFnd
= Find( sFldName
, GetFldTypeTable(), TBLSZ
, &n
);
2511 SwCalcFldType
* pNew
= new SwCalcFldType( sFldName
, &rType
);
2512 pNew
->pNext
= aFldTypeTable
[ n
];
2513 aFldTypeTable
[ n
] = pNew
;
2518 void SwDocUpdtFld::RemoveFldType( const SwFieldType
& rType
)
2521 switch( rType
.Which() )
2524 sFldName
= ((SwUserFieldType
&)rType
).GetName();
2527 sFldName
= ((SwSetExpFieldType
&)rType
).GetName();
2531 if( sFldName
.Len() )
2533 SetFieldsDirty( true );
2534 // look up and remove from the hash table
2535 sFldName
= GetAppCharClass().lowercase( sFldName
);
2538 SwHash
* pFnd
= Find( sFldName
, GetFldTypeTable(), TBLSZ
, &n
);
2541 if( aFldTypeTable
[ n
] == pFnd
)
2542 aFldTypeTable
[ n
] = (SwCalcFldType
*)pFnd
->pNext
;
2545 SwHash
* pPrev
= aFldTypeTable
[ n
];
2546 while( pPrev
->pNext
!= pFnd
)
2547 pPrev
= pPrev
->pNext
;
2548 pPrev
->pNext
= pFnd
->pNext
;
2556 SwDocUpdtFld::SwDocUpdtFld()
2557 : pFldSortLst(0), nFldLstGetMode(0)
2559 bInUpdateFlds
= bFldsDirty
= sal_False
;
2560 memset( aFldTypeTable
, 0, sizeof( aFldTypeTable
) );
2563 SwDocUpdtFld::~SwDocUpdtFld()
2567 for( sal_uInt16 n
= 0; n
< TBLSZ
; ++n
)
2568 delete aFldTypeTable
[n
];
2571 bool SwDoc::UpdateFld(SwTxtFld
* pDstTxtFld
, SwField
& rSrcFld
,
2572 SwMsgPoolItem
* pMsgHnt
,
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
);
2604 case RES_HIDDENTXTFLD
:
2605 case RES_HIDDENPARAFLD
:
2606 UpdateExpFlds( pDstTxtFld
, true );
2611 const SwTableNode
* pTblNd
=
2612 IsIdxInTbl(aTblNdIdx
);
2615 SwTableFmlUpdate
aTblUpdate( &pTblNd
->
2618 UpdateTblFlds( &aTblUpdate
);
2620 pNewFld
->GetTyp()->ModifyNotification(0, &aTblUpdate
);
2623 bTblSelBreak
= true;
2629 if( bUpdateFlds
&& pDstTxtFld
->GetpTxtNode() )
2630 (pDstTxtFld
->GetpTxtNode())->
2631 ModifyNotification( 0, pDstFmtFld
);
2635 case RES_DBNEXTSETFLD
:
2636 case RES_DBNUMSETFLD
:
2637 case RES_DBSETNUMBERFLD
:
2638 ChgDBData(((SwDBNameInfField
*) pNewFld
)->GetRealDBData());
2639 pNewFld
->GetTyp()->UpdateFlds();
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();
2657 pDstFmtFld
->ModifyNotification( 0, pMsgHnt
);
2660 // The fields we can calculate here are being triggered for an update
2662 if( nFldWhich
== RES_USERFLD
)
2666 return bTblSelBreak
;
2669 bool SwDoc::PutValueToField(const SwPosition
& rPos
,
2670 const Any
& rVal
, sal_uInt16 nWhich
)
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: */