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 /** Insert field types
70 * @return Always returns a pointer to the type, if it's new or already added.
72 SwFieldType
* SwDoc::InsertFldType(const SwFieldType
&rFldTyp
)
74 sal_uInt16 nSize
= mpFldTypes
->size(),
75 nFldWhich
= rFldTyp
.Which();
77 sal_uInt16 i
= INIT_FLDTYPES
;
82 //JP 29.01.96: SequenceFields start at INIT_FLDTYPES - 3!!
83 // Or we get doubble number circles!!
84 //MIB 14.03.95: From now on also the SW3-Reader relies on this, when
85 //constructing string pools and when reading SetExp fields
86 if( nsSwGetSetExpType::GSE_SEQ
& ((SwSetExpFieldType
&)rFldTyp
).GetType() )
87 i
-= INIT_SEQ_FLDTYPES
;
93 const ::utl::TransliterationWrapper
& rSCmp
= GetAppCmpStrIgnore();
94 String
sFldNm( rFldTyp
.GetName() );
95 for( ; i
< nSize
; ++i
)
96 if( nFldWhich
== (*mpFldTypes
)[i
]->Which() &&
97 rSCmp
.isEqual( sFldNm
, (*mpFldTypes
)[i
]->GetName() ))
98 return (*mpFldTypes
)[i
];
103 for( ; i
< nSize
; ++i
)
104 if( nFldWhich
== (*mpFldTypes
)[i
]->Which() )
105 return (*mpFldTypes
)[i
];
109 for( i
= 0; i
< nSize
; ++i
)
110 if( nFldWhich
== (*mpFldTypes
)[i
]->Which() )
111 return (*mpFldTypes
)[i
];
114 SwFieldType
* pNew
= rFldTyp
.Copy();
118 ((SwDDEFieldType
*)pNew
)->SetDoc( this );
123 case RES_DATETIMEFLD
:
125 ((SwValueFieldType
*)pNew
)->SetDoc( this );
130 ((SwValueFieldType
*)pNew
)->SetDoc( this );
131 // JP 29.07.96: Optionally prepare FieldList for Calculator:
132 mpUpdtFlds
->InsertFldType( *pNew
);
135 ((SwAuthorityFieldType
*)pNew
)->SetDoc( this );
139 mpFldTypes
->insert( mpFldTypes
->begin() + nSize
, pNew
);
142 return (*mpFldTypes
)[ nSize
];
145 /// Insert field type that was marked as deleted
146 void SwDoc::InsDeletedFldType( SwFieldType
& rFldTyp
)
148 // The FldType was marked as deleted and removed from the array.
149 // One has to look this up again, now.
150 // - If it's not present, it can be re-inserted.
151 // - If the same type is found, the deleted one has to be renamed.
153 sal_uInt16 nSize
= mpFldTypes
->size(), nFldWhich
= rFldTyp
.Which();
154 sal_uInt16 i
= INIT_FLDTYPES
;
156 OSL_ENSURE( RES_SETEXPFLD
== nFldWhich
||
157 RES_USERFLD
== nFldWhich
||
158 RES_DDEFLD
== nFldWhich
, "Wrong FldType" );
160 const ::utl::TransliterationWrapper
& rSCmp
= GetAppCmpStrIgnore();
161 const String
& rFldNm
= rFldTyp
.GetName();
164 for( ; i
< nSize
; ++i
)
165 if( nFldWhich
== (pFnd
= (*mpFldTypes
)[i
])->Which() &&
166 rSCmp
.isEqual( rFldNm
, pFnd
->GetName() ) )
171 String
sSrch( rFldNm
);
172 sSrch
.Append( OUString::number( nNum
));
173 for( i
= INIT_FLDTYPES
; i
< nSize
; ++i
)
174 if( nFldWhich
== (pFnd
= (*mpFldTypes
)[i
])->Which() &&
175 rSCmp
.isEqual( sSrch
, pFnd
->GetName() ) )
178 if( i
>= nSize
) // not found
180 ((String
&)rFldNm
) = sSrch
;
181 break; // exit while loop
188 // not found, so insert and delete flag
189 mpFldTypes
->insert( mpFldTypes
->begin() + nSize
, &rFldTyp
);
193 ((SwSetExpFieldType
&)rFldTyp
).SetDeleted( sal_False
);
196 ((SwUserFieldType
&)rFldTyp
).SetDeleted( sal_False
);
199 ((SwDDEFieldType
&)rFldTyp
).SetDeleted( sal_False
);
204 /// Remove field type
205 void SwDoc::RemoveFldType(sal_uInt16 nFld
)
207 OSL_ENSURE( INIT_FLDTYPES
<= nFld
, "don't remove InitFlds" );
209 * Dependent fields present -> ErrRaise
211 sal_uInt16 nSize
= mpFldTypes
->size();
214 SwFieldType
* pTmp
= (*mpFldTypes
)[nFld
];
216 // JP 29.07.96: Optionally prepare FldLst for Calculator
217 sal_uInt16 nWhich
= pTmp
->Which();
222 mpUpdtFlds
->RemoveFldType( *pTmp
);
225 if( pTmp
->GetDepends() && !IsUsed( *pTmp
) )
227 if( RES_SETEXPFLD
== nWhich
)
228 ((SwSetExpFieldType
*)pTmp
)->SetDeleted( sal_True
);
229 else if( RES_USERFLD
== nWhich
)
230 ((SwUserFieldType
*)pTmp
)->SetDeleted( sal_True
);
232 ((SwDDEFieldType
*)pTmp
)->SetDeleted( sal_True
);
240 OSL_ENSURE( !pTmp
->GetDepends(), "Dependent fields present!" );
244 mpFldTypes
->erase( mpFldTypes
->begin() + nFld
);
249 const SwFldTypes
* SwDoc::GetFldTypes() const
254 /// Find first type with ResId and name
255 SwFieldType
* SwDoc::GetFldType( sal_uInt16 nResId
, const String
& rName
,
256 bool bDbFieldMatching
// used in some UNO calls for RES_DBFLD
257 // to use different string matching code
261 sal_uInt16 nSize
= mpFldTypes
->size(), i
= 0;
262 const ::utl::TransliterationWrapper
& rSCmp
= GetAppCmpStrIgnore();
267 //JP 29.01.96: SequenceFields start at INIT_FLDTYPES - 3!!
268 // Or we get doubble number circles!!
269 //MIB 14.03.95: From now on also the SW3-Reader relies on this, when
270 //constructing string pools and when reading SetExp fields
271 i
= INIT_FLDTYPES
- INIT_SEQ_FLDTYPES
;
282 SwFieldType
* pRet
= 0;
283 for( ; i
< nSize
; ++i
)
285 SwFieldType
* pFldType
= (*mpFldTypes
)[i
];
287 String
aFldName( pFldType
->GetName() );
288 if (bDbFieldMatching
&& nResId
== RES_DBFLD
) // #i51815#
289 aFldName
.SearchAndReplaceAll(DB_DELIM
, '.');
291 if( nResId
== pFldType
->Which() &&
292 rSCmp
.isEqual( rName
, aFldName
))
301 // All have to be re-evaluated.
302 void SwDoc::UpdateFlds( SfxPoolItem
*pNewHt
, bool bCloseDB
)
304 // Call Modify() for every field type,
305 // dependent SwTxtFld get notified ...
307 for( sal_uInt16 i
=0; i
< mpFldTypes
->size(); ++i
)
309 switch( (*mpFldTypes
)[i
]->Which() )
311 // Update table fields second to last
312 // Update references last
316 case RES_JUMPEDITFLD
:
317 case RES_REFPAGESETFLD
: // are never expanded!
324 SwMsgPoolItem
aUpdateDDE( RES_UPDATEDDETBL
);
325 (*mpFldTypes
)[i
]->ModifyNotification( 0, &aUpdateDDE
);
328 (*mpFldTypes
)[i
]->ModifyNotification( 0, pNewHt
);
333 case RES_HIDDENTXTFLD
:
334 case RES_HIDDENPARAFLD
:
335 // Expression fields are treated separately
339 (*mpFldTypes
)[i
]->ModifyNotification ( 0, pNewHt
);
343 if( !IsExpFldsLocked() )
344 UpdateExpFlds( 0, sal_False
); // update expression fields
347 UpdateTblFlds(pNewHt
);
350 UpdateRefFlds(pNewHt
);
353 GetNewDBMgr()->CloseAll();
355 // Only evaluate on full update
359 void SwDoc::UpdateUsrFlds()
362 const SwFieldType
* pFldType
;
363 for( sal_uInt16 i
= INIT_FLDTYPES
; i
< mpFldTypes
->size(); ++i
)
364 if( RES_USERFLD
== ( pFldType
= (*mpFldTypes
)[i
] )->Which() )
367 pCalc
= new SwCalc( *this );
368 ((SwUserFieldType
*)pFldType
)->GetValue( *pCalc
);
378 /// Update reference and table fields
379 void SwDoc::UpdateRefFlds( SfxPoolItem
* pHt
)
381 SwFieldType
* pFldType
;
382 for( sal_uInt16 i
= 0; i
< mpFldTypes
->size(); ++i
)
383 if( RES_GETREFFLD
== ( pFldType
= (*mpFldTypes
)[i
] )->Which() )
384 pFldType
->ModifyNotification( 0, pHt
);
387 /// @note For simplicity assume that all field types have updatable contents so
388 /// optimization currently only available when no fields exist.
389 bool SwDoc::containsUpdatableFields()
391 for (sal_uInt16 i
= 0; i
< mpFldTypes
->size(); ++i
)
393 SwFieldType
* pFldType
= (*mpFldTypes
)[i
];
394 SwIterator
<SwFmtFld
,SwFieldType
> aIter(*pFldType
);
401 void SwDoc::UpdateTblFlds( SfxPoolItem
* pHt
)
403 OSL_ENSURE( !pHt
|| RES_TABLEFML_UPDATE
== pHt
->Which(),
404 "What MessageItem is this?" );
406 SwFieldType
* pFldType(0);
408 for (sal_uInt16 i
= 0; i
< mpFldTypes
->size(); ++i
)
410 if( RES_TABLEFLD
== ( pFldType
= (*mpFldTypes
)[i
] )->Which() )
412 SwTableFmlUpdate
* pUpdtFld
= 0;
413 if( pHt
&& RES_TABLEFML_UPDATE
== pHt
->Which() )
414 pUpdtFld
= (SwTableFmlUpdate
*)pHt
;
416 SwIterator
<SwFmtFld
,SwFieldType
> aIter( *pFldType
);
417 for( SwFmtFld
* pFmtFld
= aIter
.First(); pFmtFld
; pFmtFld
= aIter
.Next() )
419 if( pFmtFld
->GetTxtFld() )
421 SwTblField
* pFld
= (SwTblField
*)pFmtFld
->GetFld();
425 // table where this field is located
426 const SwTableNode
* pTblNd
;
427 const SwTxtNode
& rTxtNd
= pFmtFld
->GetTxtFld()->GetTxtNode();
428 if( !rTxtNd
.GetNodes().IsDocNodes() ||
429 0 == ( pTblNd
= rTxtNd
.FindTableNode() ) )
432 switch( pUpdtFld
->eFlags
)
435 // re-set the value flag
436 // JP 17.06.96: internal representation of all formulas
437 // (reference to other table!!!)
438 if( nsSwExtendedSubType::SUB_CMD
& pFld
->GetSubType() )
439 pFld
->PtrToBoxNm( pUpdtFld
->pTbl
);
441 pFld
->ChgValid( sal_False
);
444 // is this the wanted table?
445 if( &pTblNd
->GetTable() == pUpdtFld
->pTbl
)
446 // to the external representation
447 pFld
->PtrToBoxNm( pUpdtFld
->pTbl
);
450 // to the internal representation
451 // JP 17.06.96: internal representation on all formulas
452 // (reference to other table!!!)
453 pFld
->BoxNmToPtr( pUpdtFld
->pTbl
);
456 // is this the wanted table?
457 if( &pTblNd
->GetTable() == pUpdtFld
->pTbl
)
458 // to the relative representation
459 pFld
->ToRelBoxNm( pUpdtFld
->pTbl
);
466 // reset the value flag for all
467 pFld
->ChgValid( sal_False
);
476 // process all table box formuals
477 const SfxPoolItem
* pItem
;
478 sal_uInt32 nMaxItems
= GetAttrPool().GetItemCount2( RES_BOXATR_FORMULA
);
479 for (sal_uInt32 i
= 0; i
< nMaxItems
; ++i
)
481 if( 0 != (pItem
= GetAttrPool().GetItem2( RES_BOXATR_FORMULA
, i
) ) &&
482 ((SwTblBoxFormula
*)pItem
)->GetDefinedIn() )
484 ((SwTblBoxFormula
*)pItem
)->ChangeState( pHt
);
489 // all fields/boxes are now invalid, so we can start to calculate
490 if( pHt
&& ( RES_TABLEFML_UPDATE
!= pHt
->Which() ||
491 TBL_CALC
!= ((SwTableFmlUpdate
*)pHt
)->eFlags
))
498 SwIterator
<SwFmtFld
,SwFieldType
> aIter( *pFldType
);
499 for( SwFmtFld
* pFmtFld
= aIter
.Last(); pFmtFld
; pFmtFld
= aIter
.Previous() )
501 // start calculation at the end
502 // new fields are inserted at the beginning of the modify chain
503 // that gives faster calculation on import
504 // mba: do we really need this "optimization"? Is it still valid?
506 if( !pFmtFld
->GetTxtFld() || (nsSwExtendedSubType::SUB_CMD
&
507 (pFld
= (SwTblField
*)pFmtFld
->GetFld())->GetSubType() ))
510 // needs to be recalculated
511 if( !pFld
->IsValid() )
513 // table where this field is located
514 const SwTxtNode
& rTxtNd
= pFmtFld
->GetTxtFld()->GetTxtNode();
515 if( !rTxtNd
.GetNodes().IsDocNodes() )
517 const SwTableNode
* pTblNd
= rTxtNd
.FindTableNode();
521 // if this field is not in the to-be-updated table, skip it
522 if( pHt
&& &pTblNd
->GetTable() !=
523 ((SwTableFmlUpdate
*)pHt
)->pTbl
)
527 pCalc
= new SwCalc( *this );
529 // get the values of all SetExpression fields that are valid
532 if( pTblNd
->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
534 // is in the special section, that's expensive!
535 Point aPt
; // return the first frame of the layout - Tab.Headline!!
536 pFrm
= rTxtNd
.getLayoutFrm( GetCurrentLayout(), &aPt
);
539 SwPosition
aPos( *pTblNd
);
540 if( GetBodyTxtNode( *this, aPos
, *pFrm
) )
541 FldsToCalc( *pCalc
, _SetGetExpFld(
542 aPos
.nNode
, pFmtFld
->GetTxtFld(),
550 // create index to determine the TextNode
551 SwNodeIndex
aIdx( rTxtNd
);
553 _SetGetExpFld( aIdx
, pFmtFld
->GetTxtFld() ));
556 SwTblCalcPara
aPara( *pCalc
, pTblNd
->GetTable() );
557 pFld
->CalcField( aPara
);
558 if( aPara
.IsStackOverFlow() )
560 bool const bResult
= aPara
.CalcWithStackOverflow();
563 pFld
->CalcField( aPara
);
566 "the chained formula could no be calculated");
568 pCalc
->SetCalcError( CALC_NOERR
);
570 pFmtFld
->ModifyNotification( 0, pHt
);
574 // calculate the formula at the boxes
575 for (sal_uInt32 i
= 0; i
< nMaxItems
; ++i
)
577 if( 0 != (pItem
= GetAttrPool().GetItem2( RES_BOXATR_FORMULA
, i
) ) &&
578 ((SwTblBoxFormula
*)pItem
)->GetDefinedIn() &&
579 !((SwTblBoxFormula
*)pItem
)->IsValid() )
581 SwTblBoxFormula
* pFml
= (SwTblBoxFormula
*)pItem
;
582 SwTableBox
* pBox
= pFml
->GetTableBox();
583 if( pBox
&& pBox
->GetSttNd() &&
584 pBox
->GetSttNd()->GetNodes().IsDocNodes() )
586 const SwTableNode
* pTblNd
= pBox
->GetSttNd()->FindTableNode();
587 if( !pHt
|| &pTblNd
->GetTable() ==
588 ((SwTableFmlUpdate
*)pHt
)->pTbl
)
592 pCalc
= new SwCalc( *this );
594 // get the values of all SetExpression fields that are valid
597 if( pTblNd
->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
599 // is in the special section, that's expensive!
600 Point aPt
; // return the first frame of the layout - Tab.Headline!!
601 SwNodeIndex
aCNdIdx( *pTblNd
, +2 );
602 SwCntntNode
* pCNd
= aCNdIdx
.GetNode().GetCntntNode();
604 pCNd
= GetNodes().GoNext( &aCNdIdx
);
606 if( pCNd
&& 0 != (pFrm
= pCNd
->getLayoutFrm( GetCurrentLayout(), &aPt
)) )
608 SwPosition
aPos( *pCNd
);
609 if( GetBodyTxtNode( *this, aPos
, *pFrm
) )
610 FldsToCalc( *pCalc
, _SetGetExpFld( aPos
.nNode
));
617 // create index to determine the TextNode
618 SwNodeIndex
aIdx( *pTblNd
);
619 FldsToCalc( *pCalc
, _SetGetExpFld( aIdx
));
622 SwTblCalcPara
aPara( *pCalc
, pTblNd
->GetTable() );
623 pFml
->Calc( aPara
, nValue
);
625 if( aPara
.IsStackOverFlow() )
627 bool const bResult
= aPara
.CalcWithStackOverflow();
630 pFml
->Calc( aPara
, nValue
);
633 "the chained formula could no be calculated");
636 SwFrmFmt
* pFmt
= pBox
->ClaimFrmFmt();
637 SfxItemSet
aTmp( GetAttrPool(),
638 RES_BOXATR_BEGIN
,RES_BOXATR_END
-1 );
640 if( pCalc
->IsCalcError() )
642 aTmp
.Put( SwTblBoxValue( nValue
));
643 if( SFX_ITEM_SET
!= pFmt
->GetItemState( RES_BOXATR_FORMAT
))
644 aTmp
.Put( SwTblBoxNumFormat( 0 ));
645 pFmt
->SetFmtAttr( aTmp
);
647 pCalc
->SetCalcError( CALC_NOERR
);
656 void SwDoc::UpdatePageFlds( SfxPoolItem
* pMsgHnt
)
658 SwFieldType
* pFldType
;
659 for( sal_uInt16 i
= 0; i
< INIT_FLDTYPES
; ++i
)
660 switch( ( pFldType
= (*mpFldTypes
)[ i
] )->Which() )
662 case RES_PAGENUMBERFLD
:
665 case RES_REFPAGEGETFLD
:
666 pFldType
->ModifyNotification( 0, pMsgHnt
);
669 pFldType
->ModifyNotification( 0, 0 );
675 /// Remove all unreferenced field types of a document
676 void SwDoc::GCFieldTypes()
678 for( sal_uInt16 n
= mpFldTypes
->size(); n
> INIT_FLDTYPES
; )
679 if( !(*mpFldTypes
)[ --n
]->GetDepends() )
683 void SwDoc::LockExpFlds()
688 void SwDoc::UnlockExpFlds()
694 bool SwDoc::IsExpFldsLocked() const
696 return 0 != mnLockExpFld
;
699 SwDocUpdtFld
& SwDoc::GetUpdtFlds() const
704 bool SwDoc::IsNewFldLst() const
709 void SwDoc::SetNewFldLst(bool bFlag
)
714 // the StartIndex can be supplied optionally (e.g. if it was queried before - is a virtual
715 // method otherwise!)
716 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex
& rNdIdx
, const SwTxtFld
* pFld
,
717 const SwIndex
* pIdx
)
719 eSetGetExpFldType
= TEXTFIELD
;
720 CNTNT
.pTxtFld
= pFld
;
721 nNode
= rNdIdx
.GetIndex();
723 nCntnt
= pIdx
->GetIndex();
725 nCntnt
= *pFld
->GetStart();
730 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex
& rNdIdx
,
731 const SwTxtINetFmt
& rINet
, const SwIndex
* pIdx
)
733 eSetGetExpFldType
= TEXTINET
;
734 CNTNT
.pTxtINet
= &rINet
;
735 nNode
= rNdIdx
.GetIndex();
737 nCntnt
= pIdx
->GetIndex();
739 nCntnt
= *rINet
.GetStart();
742 // Extension for Sections:
743 // these always have content position 0xffff!
744 // There is never a field on this, only up to STRING_MAXLEN possible
745 _SetGetExpFld::_SetGetExpFld( const SwSectionNode
& rSectNd
,
746 const SwPosition
* pPos
)
748 eSetGetExpFldType
= SECTIONNODE
;
749 CNTNT
.pSection
= &rSectNd
.GetSection();
753 nNode
= pPos
->nNode
.GetIndex();
754 nCntnt
= pPos
->nContent
.GetIndex();
758 nNode
= rSectNd
.GetIndex();
763 _SetGetExpFld::_SetGetExpFld( const SwTableBox
& rTBox
, const SwPosition
* pPos
)
765 eSetGetExpFldType
= TABLEBOX
;
766 CNTNT
.pTBox
= &rTBox
;
770 nNode
= pPos
->nNode
.GetIndex();
771 nCntnt
= pPos
->nContent
.GetIndex();
777 if( rTBox
.GetSttNd() )
779 SwNodeIndex
aIdx( *rTBox
.GetSttNd() );
780 const SwCntntNode
* pNd
= aIdx
.GetNode().GetNodes().GoNext( &aIdx
);
782 nNode
= pNd
->GetIndex();
787 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex
& rNdIdx
,
788 const SwTxtTOXMark
& rTOX
,
789 const SwIndex
* pIdx
)
791 eSetGetExpFldType
= TEXTTOXMARK
;
792 CNTNT
.pTxtTOX
= &rTOX
;
793 nNode
= rNdIdx
.GetIndex();
795 nCntnt
= pIdx
->GetIndex();
797 nCntnt
= *rTOX
.GetStart();
800 _SetGetExpFld::_SetGetExpFld( const SwPosition
& rPos
)
802 eSetGetExpFldType
= CRSRPOS
;
804 nNode
= rPos
.nNode
.GetIndex();
805 nCntnt
= rPos
.nContent
.GetIndex();
808 _SetGetExpFld::_SetGetExpFld( const SwFlyFrmFmt
& rFlyFmt
,
809 const SwPosition
* pPos
)
811 eSetGetExpFldType
= FLYFRAME
;
812 CNTNT
.pFlyFmt
= &rFlyFmt
;
815 nNode
= pPos
->nNode
.GetIndex();
816 nCntnt
= pPos
->nContent
.GetIndex();
820 const SwFmtCntnt
& rCntnt
= rFlyFmt
.GetCntnt();
821 nNode
= rCntnt
.GetCntntIdx()->GetIndex() + 1;
826 void _SetGetExpFld::GetPos( SwPosition
& rPos
) const
829 rPos
.nContent
.Assign( rPos
.nNode
.GetNode().GetCntntNode(), nCntnt
);
832 void _SetGetExpFld::GetPosOfContent( SwPosition
& rPos
) const
834 const SwNode
* pNd
= GetNodeFromCntnt();
836 pNd
= pNd
->GetCntntNode();
841 rPos
.nContent
.Assign( (SwCntntNode
*)pNd
,GetCntPosFromCntnt() );
846 rPos
.nContent
.Assign( rPos
.nNode
.GetNode().GetCntntNode(), nCntnt
);
850 void _SetGetExpFld::SetBodyPos( const SwCntntFrm
& rFrm
)
852 if( !rFrm
.IsInDocBody() )
854 SwNodeIndex
aIdx( *rFrm
.GetNode() );
855 SwDoc
& rDoc
= *aIdx
.GetNodes().GetDoc();
856 SwPosition
aPos( aIdx
);
857 bool const bResult
= ::GetBodyTxtNode( rDoc
, aPos
, rFrm
);
858 OSL_ENSURE(bResult
, "Where is the field?");
859 (void) bResult
; // unused in non-debug
860 nNode
= aPos
.nNode
.GetIndex();
861 nCntnt
= aPos
.nContent
.GetIndex();
865 bool _SetGetExpFld::operator<( const _SetGetExpFld
& rFld
) const
867 if( nNode
< rFld
.nNode
|| ( nNode
== rFld
.nNode
&& nCntnt
< rFld
.nCntnt
))
869 else if( nNode
!= rFld
.nNode
|| nCntnt
!= rFld
.nCntnt
)
872 const SwNode
*pFirst
= GetNodeFromCntnt(),
873 *pNext
= rFld
.GetNodeFromCntnt();
875 // Position is the same: continue only if both field pointers are set!
876 if( !pFirst
|| !pNext
)
880 if( pFirst
->StartOfSectionNode() != pNext
->StartOfSectionNode() )
882 // is one in the table?
883 const SwNode
*pFirstStt
, *pNextStt
;
884 const SwTableNode
* pTblNd
= pFirst
->FindTableNode();
886 pFirstStt
= pTblNd
->StartOfSectionNode();
888 pFirstStt
= pFirst
->StartOfSectionNode();
890 if( 0 != ( pTblNd
= pNext
->FindTableNode() ) )
891 pNextStt
= pTblNd
->StartOfSectionNode();
893 pNextStt
= pNext
->StartOfSectionNode();
895 if( pFirstStt
!= pNextStt
)
897 if( pFirst
->IsTxtNode() && pNext
->IsTxtNode() &&
898 ( pFirst
->FindFlyStartNode() || pNext
->FindFlyStartNode() ))
900 return ::IsFrameBehind( *(SwTxtNode
*)pNext
, nCntnt
,
901 *(SwTxtNode
*)pFirst
, nCntnt
);
903 return pFirstStt
->GetIndex() < pNextStt
->GetIndex();
907 // same Section: is the field in the same Node?
908 if( pFirst
!= pNext
)
909 return pFirst
->GetIndex() < pNext
->GetIndex();
911 // same Node in the Section, check Position in the Node
912 return GetCntPosFromCntnt() < rFld
.GetCntPosFromCntnt();
915 const SwNode
* _SetGetExpFld::GetNodeFromCntnt() const
917 const SwNode
* pRet
= 0;
919 switch( eSetGetExpFldType
)
922 pRet
= &CNTNT
.pTxtFld
->GetTxtNode();
926 pRet
= &CNTNT
.pTxtINet
->GetTxtNode();
930 pRet
= CNTNT
.pSection
->GetFmt()->GetSectionNode();
934 pRet
= &CNTNT
.pPos
->nNode
.GetNode();
938 pRet
= &CNTNT
.pTxtTOX
->GetTxtNode();
942 if( CNTNT
.pTBox
->GetSttNd() )
944 SwNodeIndex
aIdx( *CNTNT
.pTBox
->GetSttNd() );
945 pRet
= aIdx
.GetNode().GetNodes().GoNext( &aIdx
);
951 SwNodeIndex
aIdx( *CNTNT
.pFlyFmt
->GetCntnt().GetCntntIdx() );
952 pRet
= aIdx
.GetNode().GetNodes().GoNext( &aIdx
);
959 xub_StrLen
_SetGetExpFld::GetCntPosFromCntnt() const
963 switch( eSetGetExpFldType
)
968 nRet
= *CNTNT
.pTxtFld
->GetStart();
971 nRet
= CNTNT
.pPos
->nContent
.GetIndex();
979 _HashStr::_HashStr( const String
& rName
, const String
& rText
,
981 : SwHash( rName
), aSetStr( rText
)
986 /// Look up the Name, if it is present, return it's String, otherwise return an empty String
987 void LookString( SwHash
** ppTbl
, sal_uInt16 nSize
, const String
& rName
,
988 String
& rRet
, sal_uInt16
* pPos
)
990 rRet
= comphelper::string::strip(rName
, ' ');
991 SwHash
* pFnd
= Find( rRet
, ppTbl
, nSize
, pPos
);
993 rRet
= ((_HashStr
*)pFnd
)->aSetStr
;
998 static String
lcl_GetDBVarName( SwDoc
& rDoc
, SwDBNameInfField
& rDBFld
)
1000 SwDBData
aDBData( rDBFld
.GetDBData( &rDoc
));
1002 SwDBData aDocData
= rDoc
.GetDBData();
1004 if( aDBData
!= aDocData
)
1006 sDBNumNm
= aDBData
.sDataSource
;
1007 sDBNumNm
+= DB_DELIM
;
1008 sDBNumNm
+= String(aDBData
.sCommand
);
1009 sDBNumNm
+= DB_DELIM
;
1011 sDBNumNm
+= SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD
);
1016 static void lcl_CalcFld( SwDoc
& rDoc
, SwCalc
& rCalc
, const _SetGetExpFld
& rSGEFld
,
1019 const SwTxtFld
* pTxtFld
= rSGEFld
.GetFld();
1023 const SwField
* pFld
= pTxtFld
->GetFld().GetFld();
1024 const sal_uInt16 nFldWhich
= pFld
->GetTyp()->Which();
1026 if( RES_SETEXPFLD
== nFldWhich
)
1029 if( nsSwGetSetExpType::GSE_EXPR
& pFld
->GetSubType() )
1030 aValue
.PutDouble( ((SwSetExpField
*)pFld
)->GetValue() );
1032 // Extension to calculate with Strings
1033 aValue
.PutString( ((SwSetExpField
*)pFld
)->GetExpStr() );
1035 // set the new value in Calculator
1036 rCalc
.VarChange( pFld
->GetTyp()->GetName(), aValue
);
1042 case RES_DBNUMSETFLD
:
1044 SwDBNumSetField
* pDBFld
= (SwDBNumSetField
*)pFld
;
1046 SwDBData
aDBData(pDBFld
->GetDBData(&rDoc
));
1048 if( pDBFld
->IsCondValid() &&
1049 pMgr
->OpenDataSource( aDBData
.sDataSource
, aDBData
.sCommand
))
1050 rCalc
.VarChange( lcl_GetDBVarName( rDoc
, *pDBFld
),
1051 pDBFld
->GetFormat() );
1054 case RES_DBNEXTSETFLD
:
1056 SwDBNextSetField
* pDBFld
= (SwDBNextSetField
*)pFld
;
1057 SwDBData
aDBData(pDBFld
->GetDBData(&rDoc
));
1058 if( !pDBFld
->IsCondValid() ||
1059 !pMgr
->OpenDataSource( aDBData
.sDataSource
, aDBData
.sCommand
))
1062 String
sDBNumNm(lcl_GetDBVarName( rDoc
, *pDBFld
));
1063 SwCalcExp
* pExp
= rCalc
.VarLook( sDBNumNm
);
1065 rCalc
.VarChange( sDBNumNm
, pExp
->nValue
.GetLong() + 1 );
1073 void SwDoc::FldsToCalc( SwCalc
& rCalc
, const _SetGetExpFld
& rToThisFld
)
1075 // create the sorted list of all SetFields
1076 mpUpdtFlds
->MakeFldList( *this, mbNewFldLst
, GETFLD_CALC
);
1077 mbNewFldLst
= sal_False
;
1079 SwNewDBMgr
* pMgr
= GetNewDBMgr();
1080 pMgr
->CloseAll(sal_False
);
1082 if( !mpUpdtFlds
->GetSortLst()->empty() )
1084 _SetGetExpFlds::const_iterator
const itLast
=
1085 mpUpdtFlds
->GetSortLst()->upper_bound(
1086 const_cast<_SetGetExpFld
*>(&rToThisFld
));
1087 for( _SetGetExpFlds::const_iterator it
= mpUpdtFlds
->GetSortLst()->begin(); it
!= itLast
; ++it
)
1088 lcl_CalcFld( *this, rCalc
, **it
, pMgr
);
1091 pMgr
->CloseAll(sal_False
);
1094 void SwDoc::FldsToCalc( SwCalc
& rCalc
, sal_uLong nLastNd
, sal_uInt16 nLastCnt
)
1096 // create the sorted list of all SetFields
1097 mpUpdtFlds
->MakeFldList( *this, mbNewFldLst
, GETFLD_CALC
);
1098 mbNewFldLst
= sal_False
;
1100 SwNewDBMgr
* pMgr
= GetNewDBMgr();
1101 pMgr
->CloseAll(sal_False
);
1103 for( _SetGetExpFlds::const_iterator it
= mpUpdtFlds
->GetSortLst()->begin();
1104 it
!= mpUpdtFlds
->GetSortLst()->end() &&
1105 ( (*it
)->GetNode() < nLastNd
||
1106 ( (*it
)->GetNode() == nLastNd
&& (*it
)->GetCntnt() <= nLastCnt
)
1110 lcl_CalcFld( *this, rCalc
, **it
, pMgr
);
1113 pMgr
->CloseAll(sal_False
);
1116 void SwDoc::FldsToExpand( SwHash
**& ppHashTbl
, sal_uInt16
& rTblSize
,
1117 const _SetGetExpFld
& rToThisFld
)
1119 // create the sorted list of all SetFields
1120 mpUpdtFlds
->MakeFldList( *this, mbNewFldLst
, GETFLD_EXPAND
);
1121 mbNewFldLst
= sal_False
;
1123 // Hash table for all string replacements is filled on-the-fly.
1124 // Try to fabricate an uneven number.
1125 rTblSize
= (( mpUpdtFlds
->GetSortLst()->size() / 7 ) + 1 ) * 7;
1126 ppHashTbl
= new SwHash
*[ rTblSize
];
1127 memset( ppHashTbl
, 0, sizeof( _HashStr
* ) * rTblSize
);
1129 _SetGetExpFlds::const_iterator
const itLast
=
1130 mpUpdtFlds
->GetSortLst()->upper_bound(
1131 const_cast<_SetGetExpFld
*>(&rToThisFld
));
1133 for( _SetGetExpFlds::const_iterator it
= mpUpdtFlds
->GetSortLst()->begin(); it
!= itLast
; ++it
)
1135 const SwTxtFld
* pTxtFld
= (*it
)->GetFld();
1139 const SwField
* pFld
= pTxtFld
->GetFld().GetFld();
1140 switch( pFld
->GetTyp()->Which() )
1143 if( nsSwGetSetExpType::GSE_STRING
& pFld
->GetSubType() )
1145 // set the new value in the hash table
1146 // is the formula a field?
1147 SwSetExpField
* pSFld
= (SwSetExpField
*)pFld
;
1149 LookString( ppHashTbl
, rTblSize
, pSFld
->GetFormula(), aNew
);
1151 if( !aNew
.Len() ) // nothing found, then the formula is
1152 aNew
= pSFld
->GetFormula(); // the new value
1154 // #i3141# - update expression of field as in method
1155 // <SwDoc::UpdateExpFlds(..)> for string/text fields
1156 pSFld
->ChgExpStr( aNew
);
1158 // look up the field's name
1159 aNew
= ((SwSetExpFieldType
*)pSFld
->GetTyp())->GetSetRefName();
1162 SwHash
* pFnd
= Find( aNew
, ppHashTbl
, rTblSize
, &nPos
);
1164 // modify entry in the hash table
1165 ((_HashStr
*)pFnd
)->aSetStr
= pSFld
->GetExpStr();
1167 // insert the new entry
1168 *(ppHashTbl
+ nPos
) = new _HashStr( aNew
,
1169 pSFld
->GetExpStr(), (_HashStr
*)*(ppHashTbl
+ nPos
) );
1174 const String
& rName
= pFld
->GetTyp()->GetName();
1176 // Insert entry in the hash table
1179 SwHash
* pFnd
= Find( rName
, ppHashTbl
, rTblSize
, &nPos
);
1180 String
const value(pFld
->ExpandField(IsClipBoard()));
1183 // modify entry in the hash table
1184 static_cast<_HashStr
*>(pFnd
)->aSetStr
= value
;
1188 // insert the new entry
1189 *(ppHashTbl
+ nPos
) = new _HashStr( rName
,
1190 value
, static_cast<_HashStr
*>(*(ppHashTbl
+ nPos
)));
1198 void SwDoc::UpdateExpFlds( SwTxtFld
* pUpdtFld
, bool bUpdRefFlds
)
1200 if( IsExpFldsLocked() || IsInReading() )
1203 bool bOldInUpdateFlds
= mpUpdtFlds
->IsInUpdateFlds();
1204 mpUpdtFlds
->SetInUpdateFlds( true );
1206 mpUpdtFlds
->MakeFldList( *this, sal_True
, GETFLD_ALL
);
1207 mbNewFldLst
= sal_False
;
1209 if( mpUpdtFlds
->GetSortLst()->empty() )
1212 UpdateRefFlds(NULL
);
1214 mpUpdtFlds
->SetInUpdateFlds( bOldInUpdateFlds
);
1215 mpUpdtFlds
->SetFieldsDirty( false );
1219 sal_uInt16 nWhich
, n
;
1221 // Hash table for all string replacements is filled on-the-fly.
1222 // Try to fabricate an uneven number.
1223 sal_uInt16 nStrFmtCnt
= (( mpFldTypes
->size() / 7 ) + 1 ) * 7;
1224 SwHash
** pHashStrTbl
= new SwHash
*[ nStrFmtCnt
];
1225 memset( pHashStrTbl
, 0, sizeof( _HashStr
* ) * nStrFmtCnt
);
1228 const SwFieldType
* pFldType
;
1229 // process separately:
1230 for( n
= mpFldTypes
->size(); n
; )
1231 switch( ( pFldType
= (*mpFldTypes
)[ --n
] )->Which() )
1237 const String
& rNm
= pFldType
->GetName();
1238 String
sExpand(((SwUserFieldType
*)pFldType
)->Expand(nsSwGetSetExpType::GSE_STRING
, 0, 0));
1239 SwHash
* pFnd
= Find( rNm
, pHashStrTbl
, nStrFmtCnt
, &nPos
);
1241 // modify entry in the hash table
1242 ((_HashStr
*)pFnd
)->aSetStr
= sExpand
;
1244 // insert the new entry
1245 *(pHashStrTbl
+ nPos
) = new _HashStr( rNm
, sExpand
,
1246 (_HashStr
*)*(pHashStrTbl
+ nPos
) );
1250 ((SwSetExpFieldType
*)pFldType
)->SetOutlineChgNd( 0 );
1255 // The array is filled with all fields; start calculation.
1256 SwCalc
aCalc( *this );
1258 String
sDBNumNm( SwFieldType::GetTypeStr( TYP_DBSETNUMBERFLD
) );
1260 // already set the current record number
1261 SwNewDBMgr
* pMgr
= GetNewDBMgr();
1262 pMgr
->CloseAll(sal_False
);
1264 // Make sure we don't hide all sections, which would lead to a crash. First, count how many of them do we have.
1265 int nShownSections
= 0;
1266 for( _SetGetExpFlds::const_iterator it
= mpUpdtFlds
->GetSortLst()->begin(); it
!= mpUpdtFlds
->GetSortLst()->end(); ++it
)
1268 SwSection
* pSect
= (SwSection
*)(*it
)->GetSection();
1269 if ( pSect
&& !pSect
->IsCondHidden())
1274 for( _SetGetExpFlds::const_iterator it
= mpUpdtFlds
->GetSortLst()->begin(); it
!= mpUpdtFlds
->GetSortLst()->end(); ++it
)
1276 SwSection
* pSect
= (SwSection
*)(*it
)->GetSection();
1280 SwSbxValue aValue
= aCalc
.Calculate(
1281 pSect
->GetCondition() );
1282 if(!aValue
.IsVoidValue())
1284 // Do we want to hide this one?
1285 bool bHide
= aValue
.GetBool();
1286 if (bHide
&& !pSect
->IsCondHidden())
1288 // This section will be hidden, but it wasn't before
1289 if (nShownSections
== 1)
1291 // Is the last node part of a section?
1292 SwPaM
aPam(GetNodes());
1293 aPam
.Move(fnMoveForward
, fnGoDoc
);
1294 if (aPam
.Start()->nNode
.GetNode().StartOfSectionNode()->IsSectionNode())
1296 // This would be the last section, so set its condition to false, and avoid hiding it.
1297 OUString
aCond("0");
1298 pSect
->SetCondition(aCond
);
1304 pSect
->SetCondHidden( bHide
);
1309 SwTxtFld
* pTxtFld
= (SwTxtFld
*)(*it
)->GetFld();
1312 OSL_ENSURE( !this, "what's wrong now'" );
1316 SwFmtFld
* pFmtFld
= (SwFmtFld
*)&pTxtFld
->GetFld();
1317 SwField
* pFld
= pFmtFld
->GetFld();
1319 switch( nWhich
= pFld
->GetTyp()->Which() )
1321 case RES_HIDDENTXTFLD
:
1323 SwHiddenTxtField
* pHFld
= (SwHiddenTxtField
*)pFld
;
1324 SwSbxValue aValue
= aCalc
.Calculate( pHFld
->GetPar1() );
1325 sal_Bool bValue
= !aValue
.GetBool();
1326 if(!aValue
.IsVoidValue())
1328 pHFld
->SetValue( bValue
);
1330 pHFld
->Evaluate(this);
1334 case RES_HIDDENPARAFLD
:
1336 SwHiddenParaField
* pHPFld
= (SwHiddenParaField
*)pFld
;
1337 SwSbxValue aValue
= aCalc
.Calculate( pHPFld
->GetPar1() );
1338 sal_Bool bValue
= aValue
.GetBool();
1339 if(!aValue
.IsVoidValue())
1340 pHPFld
->SetHidden( bValue
);
1343 case RES_DBSETNUMBERFLD
:
1345 ((SwDBSetNumberField
*)pFld
)->Evaluate(this);
1346 aCalc
.VarChange( sDBNumNm
, ((SwDBSetNumberField
*)pFld
)->GetSetNumber());
1349 case RES_DBNEXTSETFLD
:
1350 case RES_DBNUMSETFLD
:
1351 UpdateDBNumFlds( *(SwDBNameInfField
*)pFld
, aCalc
);
1356 ((SwDBField
*)pFld
)->Evaluate();
1358 SwDBData
aTmpDBData(((SwDBField
*)pFld
)->GetDBData());
1360 if( pMgr
->IsDataSourceOpen(aTmpDBData
.sDataSource
, aTmpDBData
.sCommand
, sal_False
))
1361 aCalc
.VarChange( sDBNumNm
, pMgr
->GetSelectedRecordId(aTmpDBData
.sDataSource
, aTmpDBData
.sCommand
, aTmpDBData
.nCommandType
));
1363 const String
& rName
= pFld
->GetTyp()->GetName();
1365 // Add entry to hash table
1368 SwHash
* pFnd
= Find( rName
, pHashStrTbl
, nStrFmtCnt
, &nPos
);
1369 String
const value(pFld
->ExpandField(IsClipBoard()));
1372 // Modify entry in the hash table
1373 static_cast<_HashStr
*>(pFnd
)->aSetStr
= value
;
1378 *(pHashStrTbl
+ nPos
) = new _HashStr( rName
,
1379 value
, static_cast<_HashStr
*>(*(pHashStrTbl
+ nPos
)));
1386 if( nsSwGetSetExpType::GSE_STRING
& pFld
->GetSubType() ) // replace String
1388 if( RES_GETEXPFLD
== nWhich
)
1390 SwGetExpField
* pGFld
= (SwGetExpField
*)pFld
;
1392 if( (!pUpdtFld
|| pUpdtFld
== pTxtFld
)
1393 && pGFld
->IsInBodyTxt() )
1395 LookString( pHashStrTbl
, nStrFmtCnt
,
1396 pGFld
->GetFormula(), aNew
);
1397 pGFld
->ChgExpStr( aNew
);
1402 SwSetExpField
* pSFld
= (SwSetExpField
*)pFld
;
1403 // is the "formula" a field?
1404 LookString( pHashStrTbl
, nStrFmtCnt
,
1405 pSFld
->GetFormula(), aNew
);
1407 if( !aNew
.Len() ) // nothing found then the formula is the new value
1408 aNew
= pSFld
->GetFormula();
1410 // only update one field
1411 if( !pUpdtFld
|| pUpdtFld
== pTxtFld
)
1412 pSFld
->ChgExpStr( aNew
);
1414 // lookup the field's name
1415 aNew
= ((SwSetExpFieldType
*)pSFld
->GetTyp())->GetSetRefName();
1418 SwHash
* pFnd
= Find( aNew
, pHashStrTbl
, nStrFmtCnt
, &nPos
);
1420 // Modify entry in the hash table
1421 ((_HashStr
*)pFnd
)->aSetStr
= pSFld
->GetExpStr();
1424 *(pHashStrTbl
+ nPos
) = pFnd
= new _HashStr( aNew
,
1426 (_HashStr
*)*(pHashStrTbl
+ nPos
) );
1428 // Extension for calculation with Strings
1430 aValue
.PutString( ((_HashStr
*)pFnd
)->aSetStr
);
1431 aCalc
.VarChange( aNew
, aValue
);
1434 else // recalculate formula
1436 if( RES_GETEXPFLD
== nWhich
)
1438 SwGetExpField
* pGFld
= (SwGetExpField
*)pFld
;
1440 if( (!pUpdtFld
|| pUpdtFld
== pTxtFld
)
1441 && pGFld
->IsInBodyTxt() )
1443 SwSbxValue aValue
= aCalc
.Calculate(
1444 pGFld
->GetFormula());
1445 if(!aValue
.IsVoidValue())
1446 pGFld
->SetValue(aValue
.GetDouble() );
1451 SwSetExpField
* pSFld
= (SwSetExpField
*)pFld
;
1452 SwSetExpFieldType
* pSFldTyp
= (SwSetExpFieldType
*)pFld
->GetTyp();
1453 aNew
= pSFldTyp
->GetName();
1457 if( pSFld
->IsSequenceFld() )
1459 const sal_uInt8 nLvl
= pSFldTyp
->GetOutlineLvl();
1460 if( MAXLEVEL
> nLvl
)
1462 // test if the Number needs to be updated
1463 pSeqNd
= GetNodes()[ (*it
)->GetNode() ];
1465 const SwTxtNode
* pOutlNd
= pSeqNd
->
1466 FindOutlineNodeOfLevel( nLvl
);
1467 if( pSFldTyp
->GetOutlineChgNd() != pOutlNd
)
1469 pSFldTyp
->SetOutlineChgNd( pOutlNd
);
1470 aCalc
.VarChange( aNew
, 0 );
1476 aNew
+= pSFld
->GetFormula();
1478 SwSbxValue aValue
= aCalc
.Calculate( aNew
);
1479 double nErg
= aValue
.GetDouble();
1480 // only update one field
1481 if( !aValue
.IsVoidValue() && (!pUpdtFld
|| pUpdtFld
== pTxtFld
) )
1483 pSFld
->SetValue( nErg
);
1486 pSFldTyp
->SetChapter( *pSFld
, *pSeqNd
);
1493 pFmtFld
->ModifyNotification( 0, 0 ); // trigger formatting
1495 if( pUpdtFld
== pTxtFld
) // if only this one is updated
1497 if( RES_GETEXPFLD
== nWhich
|| // only GetField or
1498 RES_HIDDENTXTFLD
== nWhich
|| // HiddenTxt?
1499 RES_HIDDENPARAFLD
== nWhich
) // HiddenParaFld?
1501 pUpdtFld
= 0; // update all from here on
1505 pMgr
->CloseAll(sal_False
);
1506 // delete hash table
1507 ::DeleteHashTable( pHashStrTbl
, nStrFmtCnt
);
1509 // update reference fields
1511 UpdateRefFlds(NULL
);
1513 mpUpdtFlds
->SetInUpdateFlds( bOldInUpdateFlds
);
1514 mpUpdtFlds
->SetFieldsDirty( false );
1517 void SwDoc::UpdateDBNumFlds( SwDBNameInfField
& rDBFld
, SwCalc
& rCalc
)
1519 SwNewDBMgr
* pMgr
= GetNewDBMgr();
1521 sal_uInt16 nFldType
= rDBFld
.Which();
1523 sal_Bool bPar1
= rCalc
.Calculate( rDBFld
.GetPar1() ).GetBool();
1525 if( RES_DBNEXTSETFLD
== nFldType
)
1526 ((SwDBNextSetField
&)rDBFld
).SetCondValid( bPar1
);
1528 ((SwDBNumSetField
&)rDBFld
).SetCondValid( bPar1
);
1530 if( !rDBFld
.GetRealDBData().sDataSource
.isEmpty() )
1532 // Edit a certain database
1533 if( RES_DBNEXTSETFLD
== nFldType
)
1534 ((SwDBNextSetField
&)rDBFld
).Evaluate(this);
1536 ((SwDBNumSetField
&)rDBFld
).Evaluate(this);
1538 SwDBData
aTmpDBData( rDBFld
.GetDBData(this) );
1540 if( pMgr
->OpenDataSource( aTmpDBData
.sDataSource
, aTmpDBData
.sCommand
, -1, false ))
1541 rCalc
.VarChange( lcl_GetDBVarName( *this, rDBFld
),
1542 pMgr
->GetSelectedRecordId(aTmpDBData
.sDataSource
, aTmpDBData
.sCommand
, aTmpDBData
.nCommandType
) );
1546 OSL_FAIL("TODO: what should happen with unnamed DBFields?");
1550 void SwDoc::_InitFieldTypes() // is being called by the CTOR
1553 mpFldTypes
->push_back( new SwDateTimeFieldType(this) );
1554 mpFldTypes
->push_back( new SwChapterFieldType
);
1555 mpFldTypes
->push_back( new SwPageNumberFieldType
);
1556 mpFldTypes
->push_back( new SwAuthorFieldType
);
1557 mpFldTypes
->push_back( new SwFileNameFieldType(this) );
1558 mpFldTypes
->push_back( new SwDBNameFieldType(this) );
1559 mpFldTypes
->push_back( new SwGetExpFieldType(this) );
1560 mpFldTypes
->push_back( new SwGetRefFieldType( this ) );
1561 mpFldTypes
->push_back( new SwHiddenTxtFieldType
);
1562 mpFldTypes
->push_back( new SwPostItFieldType(this) );
1563 mpFldTypes
->push_back( new SwDocStatFieldType(this) );
1564 mpFldTypes
->push_back( new SwDocInfoFieldType(this) );
1565 mpFldTypes
->push_back( new SwInputFieldType( this ) );
1566 mpFldTypes
->push_back( new SwTblFieldType( this ) );
1567 mpFldTypes
->push_back( new SwMacroFieldType(this) );
1568 mpFldTypes
->push_back( new SwHiddenParaFieldType
);
1569 mpFldTypes
->push_back( new SwDBNextSetFieldType
);
1570 mpFldTypes
->push_back( new SwDBNumSetFieldType
);
1571 mpFldTypes
->push_back( new SwDBSetNumberFieldType
);
1572 mpFldTypes
->push_back( new SwTemplNameFieldType(this) );
1573 mpFldTypes
->push_back( new SwTemplNameFieldType(this) );
1574 mpFldTypes
->push_back( new SwExtUserFieldType
);
1575 mpFldTypes
->push_back( new SwRefPageSetFieldType
);
1576 mpFldTypes
->push_back( new SwRefPageGetFieldType( this ) );
1577 mpFldTypes
->push_back( new SwJumpEditFieldType( this ) );
1578 mpFldTypes
->push_back( new SwScriptFieldType( this ) );
1579 mpFldTypes
->push_back( new SwCombinedCharFieldType
);
1580 mpFldTypes
->push_back( new SwDropDownFieldType
);
1582 // Types have to be at the end!
1583 // We expect this in the InsertFldType!
1584 // MIB 14.04.95: In Sw3StringPool::Setup (sw3imp.cxx) and
1585 // lcl_sw3io_InSetExpField (sw3field.cxx) now also
1586 mpFldTypes
->push_back( new SwSetExpFieldType(this,
1587 SW_RESSTR(STR_POOLCOLL_LABEL_ABB
), nsSwGetSetExpType::GSE_SEQ
) );
1588 mpFldTypes
->push_back( new SwSetExpFieldType(this,
1589 SW_RESSTR(STR_POOLCOLL_LABEL_TABLE
), nsSwGetSetExpType::GSE_SEQ
) );
1590 mpFldTypes
->push_back( new SwSetExpFieldType(this,
1591 SW_RESSTR(STR_POOLCOLL_LABEL_FRAME
), nsSwGetSetExpType::GSE_SEQ
) );
1592 mpFldTypes
->push_back( new SwSetExpFieldType(this,
1593 SW_RESSTR(STR_POOLCOLL_LABEL_DRAWING
), nsSwGetSetExpType::GSE_SEQ
) );
1595 OSL_ENSURE( mpFldTypes
->size() == INIT_FLDTYPES
, "Bad initsize: SwFldTypes" );
1598 void SwDoc::InsDelFldInFldLst( bool bIns
, const SwTxtFld
& rFld
)
1600 if( !mbNewFldLst
|| !IsInDtor() )
1601 mpUpdtFlds
->InsDelFldInFldLst( bIns
, rFld
);
1604 SwDBData
SwDoc::GetDBData()
1609 const SwDBData
& SwDoc::GetDBDesc()
1611 if(maDBData
.sDataSource
.isEmpty())
1613 const sal_uInt16 nSize
= mpFldTypes
->size();
1614 for(sal_uInt16 i
= 0; i
< nSize
&& maDBData
.sDataSource
.isEmpty(); ++i
)
1616 SwFieldType
& rFldType
= *((*mpFldTypes
)[i
]);
1617 sal_uInt16 nWhich
= rFldType
.Which();
1618 if(IsUsed(rFldType
))
1623 case RES_DBNEXTSETFLD
:
1624 case RES_DBNUMSETFLD
:
1625 case RES_DBSETNUMBERFLD
:
1627 SwIterator
<SwFmtFld
,SwFieldType
> aIter( rFldType
);
1628 for( SwFmtFld
* pFld
= aIter
.First(); pFld
; pFld
= aIter
.Next() )
1630 if(pFld
->IsFldInDoc())
1632 if(RES_DBFLD
== nWhich
)
1634 (static_cast < SwDBFieldType
* > (pFld
->GetFld()->GetTyp()))
1637 maDBData
= (static_cast < SwDBNameInfField
* > (pFld
->GetFld()))->GetRealDBData();
1647 if(maDBData
.sDataSource
.isEmpty())
1648 maDBData
= GetNewDBMgr()->GetAddressDBName();
1652 void SwDoc::SetInitDBFields( sal_Bool b
)
1654 GetNewDBMgr()->SetInitDBFields( b
);
1657 /// Get all databases that are used by fields
1658 static String
lcl_DBDataToString(const SwDBData
& rData
)
1660 String sRet
= rData
.sDataSource
;
1662 sRet
+= (String
)rData
.sCommand
;
1664 sRet
+= OUString::number(rData
.nCommandType
);
1668 void SwDoc::GetAllUsedDB( std::vector
<String
>& rDBNameList
,
1669 const std::vector
<String
>* pAllDBNames
)
1671 std::vector
<String
> aUsedDBNames
;
1672 std::vector
<String
> aAllDBNames
;
1676 GetAllDBNames( aAllDBNames
);
1677 pAllDBNames
= &aAllDBNames
;
1680 SwSectionFmts
& rArr
= GetSections();
1681 for (sal_uInt16 n
= rArr
.size(); n
; )
1683 SwSection
* pSect
= rArr
[ --n
]->GetSection();
1687 String
aCond( pSect
->GetCondition() );
1688 AddUsedDBToList( rDBNameList
, FindUsedDBs( *pAllDBNames
,
1689 aCond
, aUsedDBNames
) );
1690 aUsedDBNames
.clear();
1694 const SfxPoolItem
* pItem
;
1695 sal_uInt32 nMaxItems
= GetAttrPool().GetItemCount2( RES_TXTATR_FIELD
);
1696 for (sal_uInt32 n
= 0; n
< nMaxItems
; ++n
)
1698 if( 0 == (pItem
= GetAttrPool().GetItem2( RES_TXTATR_FIELD
, n
) ))
1701 const SwFmtFld
* pFmtFld
= (SwFmtFld
*)pItem
;
1702 const SwTxtFld
* pTxtFld
= pFmtFld
->GetTxtFld();
1703 if( !pTxtFld
|| !pTxtFld
->GetTxtNode().GetNodes().IsDocNodes() )
1706 const SwField
* pFld
= pFmtFld
->GetFld();
1707 switch( pFld
->GetTyp()->Which() )
1710 AddUsedDBToList( rDBNameList
,
1711 lcl_DBDataToString(((SwDBField
*)pFld
)->GetDBData() ));
1714 case RES_DBSETNUMBERFLD
:
1716 AddUsedDBToList( rDBNameList
,
1717 lcl_DBDataToString(((SwDBNameInfField
*)pFld
)->GetRealDBData() ));
1720 case RES_DBNUMSETFLD
:
1721 case RES_DBNEXTSETFLD
:
1722 AddUsedDBToList( rDBNameList
,
1723 lcl_DBDataToString(((SwDBNameInfField
*)pFld
)->GetRealDBData() ));
1724 // no break // JP: is that right like that?
1726 case RES_HIDDENTXTFLD
:
1727 case RES_HIDDENPARAFLD
:
1728 AddUsedDBToList(rDBNameList
, FindUsedDBs( *pAllDBNames
,
1729 pFld
->GetPar1(), aUsedDBNames
));
1730 aUsedDBNames
.clear();
1736 AddUsedDBToList(rDBNameList
, FindUsedDBs( *pAllDBNames
,
1737 pFld
->GetFormula(), aUsedDBNames
));
1738 aUsedDBNames
.clear();
1744 void SwDoc::GetAllDBNames( std::vector
<String
>& rAllDBNames
)
1746 SwNewDBMgr
* pMgr
= GetNewDBMgr();
1748 const SwDSParamArr
& rArr
= pMgr
->GetDSParamArray();
1749 for(sal_uInt16 i
= 0; i
< rArr
.size(); i
++)
1751 const SwDSParam
* pParam
= &rArr
[i
];
1752 OUStringBuffer
sStr(pParam
->sDataSource
.getLength() + pParam
->sCommand
.getLength() + 2);
1753 sStr
.append(pParam
->sDataSource
);
1754 sStr
.append(DB_DELIM
);
1755 sStr
.append(pParam
->sCommand
);
1756 rAllDBNames
.push_back(sStr
.makeStringAndClear());
1760 std::vector
<String
>& SwDoc::FindUsedDBs( const std::vector
<String
>& rAllDBNames
,
1761 const String
& rFormel
,
1762 std::vector
<String
>& rUsedDBNames
)
1764 const CharClass
& rCC
= GetAppCharClass();
1765 String
sFormel( rFormel
);
1767 sFormel
= rCC
.uppercase( sFormel
);
1771 for (sal_uInt16 i
= 0; i
< rAllDBNames
.size(); ++i
)
1773 String
pStr(rAllDBNames
[i
]);
1775 if( STRING_NOTFOUND
!= (nPos
= sFormel
.Search( pStr
)) &&
1776 sFormel
.GetChar( nPos
+ pStr
.Len() ) == '.' &&
1777 (!nPos
|| !rCC
.isLetterNumeric( sFormel
, nPos
- 1 )))
1779 // Look up table name
1781 nPos
+= pStr
.Len() + 1;
1782 if( STRING_NOTFOUND
!= (nEndPos
= sFormel
.Search('.', nPos
)) )
1784 pStr
.Append( DB_DELIM
);
1785 pStr
.Append( sFormel
.Copy( nPos
, nEndPos
- nPos
));
1786 rUsedDBNames
.push_back(pStr
);
1790 return rUsedDBNames
;
1793 void SwDoc::AddUsedDBToList( std::vector
<String
>& rDBNameList
,
1794 const std::vector
<String
>& rUsedDBNames
)
1796 for (sal_uInt16 i
= 0; i
< rUsedDBNames
.size(); ++i
)
1797 AddUsedDBToList( rDBNameList
, rUsedDBNames
[i
] );
1800 void SwDoc::AddUsedDBToList( std::vector
<String
>& rDBNameList
, const String
& rDBName
)
1802 if( !rDBName
.Len() )
1806 for( sal_uInt16 i
= 0; i
< rDBNameList
.size(); ++i
)
1807 if( rDBName
== rDBNameList
[i
].GetToken(0) )
1810 const ::utl::TransliterationWrapper
& rSCmp
= GetAppCmpStrIgnore();
1811 for( sal_uInt16 i
= 0; i
< rDBNameList
.size(); ++i
)
1812 if( rSCmp
.isEqual( rDBName
, rDBNameList
[i
].GetToken(0) ) )
1817 aData
.sDataSource
= rDBName
.GetToken(0, DB_DELIM
);
1818 aData
.sCommand
= rDBName
.GetToken(1, DB_DELIM
);
1819 aData
.nCommandType
= -1;
1820 GetNewDBMgr()->CreateDSData(aData
);
1821 rDBNameList
.push_back(rDBName
);
1824 void SwDoc::ChangeDBFields( const std::vector
<String
>& rOldNames
,
1825 const String
& rNewName
)
1827 SwDBData aNewDBData
;
1828 aNewDBData
.sDataSource
= rNewName
.GetToken(0, DB_DELIM
);
1829 aNewDBData
.sCommand
= rNewName
.GetToken(1, DB_DELIM
);
1830 aNewDBData
.nCommandType
= (short)rNewName
.GetToken(2, DB_DELIM
).ToInt32();
1834 SwSectionFmts
& rArr
= GetSections();
1835 for (sal_uInt16 n
= rArr
.size(); n
; )
1837 SwSection
* pSect
= rArr
[ --n
]->GetSection();
1841 sFormel
= pSect
->GetCondition();
1842 ReplaceUsedDBs( rOldNames
, rNewName
, sFormel
);
1843 pSect
->SetCondition(sFormel
);
1847 const SfxPoolItem
* pItem
;
1848 sal_uInt32 nMaxItems
= GetAttrPool().GetItemCount2( RES_TXTATR_FIELD
);
1850 for (sal_uInt32 n
= 0; n
< nMaxItems
; ++n
)
1852 if( 0 == (pItem
= GetAttrPool().GetItem2( RES_TXTATR_FIELD
, n
) ))
1855 SwFmtFld
* pFmtFld
= (SwFmtFld
*)pItem
;
1856 SwTxtFld
* pTxtFld
= pFmtFld
->GetTxtFld();
1857 if( !pTxtFld
|| !pTxtFld
->GetTxtNode().GetNodes().IsDocNodes() )
1860 SwField
* pFld
= pFmtFld
->GetFld();
1861 bool bExpand
= false;
1863 switch( pFld
->GetTyp()->Which() )
1866 if( IsNameInArray( rOldNames
, lcl_DBDataToString(((SwDBField
*)pFld
)->GetDBData())))
1868 SwDBFieldType
* pOldTyp
= (SwDBFieldType
*)pFld
->GetTyp();
1870 SwDBFieldType
* pTyp
= (SwDBFieldType
*)InsertFldType(
1871 SwDBFieldType(this, pOldTyp
->GetColumnName(), aNewDBData
));
1873 pFmtFld
->RegisterToFieldType( *pTyp
);
1876 ((SwDBField
*)pFld
)->ClearInitialized();
1877 ((SwDBField
*)pFld
)->InitContent();
1883 case RES_DBSETNUMBERFLD
:
1885 if( IsNameInArray( rOldNames
,
1886 lcl_DBDataToString(((SwDBNameInfField
*)pFld
)->GetRealDBData())))
1888 ((SwDBNameInfField
*)pFld
)->SetDBData(aNewDBData
);
1893 case RES_DBNUMSETFLD
:
1894 case RES_DBNEXTSETFLD
:
1895 if( IsNameInArray( rOldNames
,
1896 lcl_DBDataToString(((SwDBNameInfField
*)pFld
)->GetRealDBData())))
1898 ((SwDBNameInfField
*)pFld
)->SetDBData(aNewDBData
);
1902 case RES_HIDDENTXTFLD
:
1903 case RES_HIDDENPARAFLD
:
1904 sFormel
= pFld
->GetPar1();
1905 ReplaceUsedDBs( rOldNames
, rNewName
, sFormel
);
1906 pFld
->SetPar1( sFormel
);
1913 sFormel
= pFld
->GetFormula();
1914 ReplaceUsedDBs( rOldNames
, rNewName
, sFormel
);
1915 pFld
->SetPar2( sFormel
);
1921 pTxtFld
->ExpandAlways();
1926 void SwDoc::ReplaceUsedDBs( const std::vector
<String
>& rUsedDBNames
,
1927 const String
& rNewName
, String
& rFormel
)
1929 const CharClass
& rCC
= GetAppCharClass();
1930 String
sFormel(rFormel
);
1931 String
sNewName( rNewName
);
1932 sNewName
.SearchAndReplace( DB_DELIM
, '.');
1933 //the command type is not part of the condition
1934 sNewName
= sNewName
.GetToken(0, DB_DELIM
);
1935 String
sUpperNewNm( sNewName
);
1937 for( sal_uInt16 i
= 0; i
< rUsedDBNames
.size(); ++i
)
1939 String
sDBName( rUsedDBNames
[i
] );
1941 sDBName
.SearchAndReplace( DB_DELIM
, '.');
1942 //cut off command type
1943 sDBName
= sDBName
.GetToken(0, DB_DELIM
);
1944 if( !sDBName
.Equals( sUpperNewNm
))
1946 xub_StrLen nPos
= 0;
1948 while ((nPos
= sFormel
.Search(sDBName
, nPos
)) != STRING_NOTFOUND
)
1950 if( sFormel
.GetChar( nPos
+ sDBName
.Len() ) == '.' &&
1951 (!nPos
|| !rCC
.isLetterNumeric( sFormel
, nPos
- 1 )))
1953 rFormel
.Erase( nPos
, sDBName
.Len() );
1954 rFormel
.Insert( sNewName
, nPos
);
1955 //prevent re-searching - this is useless and provokes
1956 //endless loops when names containing each other and numbers are exchanged
1957 //e.g.: old ?12345.12345 new: i12345.12345
1958 nPos
= nPos
+ sNewName
.Len();
1966 bool SwDoc::IsNameInArray( const std::vector
<String
>& rArr
, const String
& rName
)
1969 for( sal_uInt16 i
= 0; i
< rArr
.size(); ++i
)
1970 if( rName
== rArr
[ i
] )
1973 const ::utl::TransliterationWrapper
& rSCmp
= GetAppCmpStrIgnore();
1974 for( sal_uInt16 i
= 0; i
< rArr
.size(); ++i
)
1975 if( rSCmp
.isEqual( rName
, rArr
[ i
] ))
1981 void SwDoc::SetFixFields( bool bOnlyTimeDate
, const DateTime
* pNewDateTime
)
1983 sal_Bool bIsModified
= IsModified();
1989 nDate
= pNewDateTime
->GetDate();
1990 nTime
= pNewDateTime
->GetTime();
1994 nDate
= Date( Date::SYSTEM
).GetDate();
1995 nTime
= Time( Time::SYSTEM
).GetTime();
1998 sal_uInt16 aTypes
[5] = {
1999 /*0*/ RES_DOCINFOFLD
,
2000 /*1*/ RES_AUTHORFLD
,
2001 /*2*/ RES_EXTUSERFLD
,
2002 /*3*/ RES_FILENAMEFLD
,
2003 /*4*/ RES_DATETIMEFLD
}; // MUST be at the end!
2005 sal_uInt16 nStt
= bOnlyTimeDate
? 4 : 0;
2007 for( ; nStt
< 5; ++nStt
)
2009 SwFieldType
* pFldType
= GetSysFldType( aTypes
[ nStt
] );
2010 SwIterator
<SwFmtFld
,SwFieldType
> aIter( *pFldType
);
2011 for( SwFmtFld
* pFld
= aIter
.First(); pFld
; pFld
= aIter
.Next() )
2013 if( pFld
&& pFld
->GetTxtFld() )
2016 switch( aTypes
[ nStt
] )
2018 case RES_DOCINFOFLD
:
2019 if( ((SwDocInfoField
*)pFld
->GetFld())->IsFixed() )
2022 SwDocInfoField
* pDocInfFld
= (SwDocInfoField
*)pFld
->GetFld();
2023 pDocInfFld
->SetExpansion( ((SwDocInfoFieldType
*)
2024 pDocInfFld
->GetTyp())->Expand(
2025 pDocInfFld
->GetSubType(),
2026 pDocInfFld
->GetFormat(),
2027 pDocInfFld
->GetLanguage(),
2028 pDocInfFld
->GetName() ) );
2033 if( ((SwAuthorField
*)pFld
->GetFld())->IsFixed() )
2036 SwAuthorField
* pAuthorFld
= (SwAuthorField
*)pFld
->GetFld();
2037 pAuthorFld
->SetExpansion( ((SwAuthorFieldType
*)
2038 pAuthorFld
->GetTyp())->Expand(
2039 pAuthorFld
->GetFormat() ) );
2043 case RES_EXTUSERFLD
:
2044 if( ((SwExtUserField
*)pFld
->GetFld())->IsFixed() )
2047 SwExtUserField
* pExtUserFld
= (SwExtUserField
*)pFld
->GetFld();
2048 pExtUserFld
->SetExpansion( ((SwExtUserFieldType
*)
2049 pExtUserFld
->GetTyp())->Expand(
2050 pExtUserFld
->GetSubType(),
2051 pExtUserFld
->GetFormat()));
2055 case RES_DATETIMEFLD
:
2056 if( ((SwDateTimeField
*)pFld
->GetFld())->IsFixed() )
2059 ((SwDateTimeField
*)pFld
->GetFld())->SetDateTime(
2060 DateTime(Date(nDate
), Time(nTime
)) );
2064 case RES_FILENAMEFLD
:
2065 if( ((SwFileNameField
*)pFld
->GetFld())->IsFixed() )
2068 SwFileNameField
* pFileNameFld
=
2069 (SwFileNameField
*)pFld
->GetFld();
2070 pFileNameFld
->SetExpansion( ((SwFileNameFieldType
*)
2071 pFileNameFld
->GetTyp())->Expand(
2072 pFileNameFld
->GetFormat() ) );
2077 // Trigger formatting
2079 pFld
->ModifyNotification( 0, 0 );
2088 bool SwDoc::SetFieldsDirty( bool b
, const SwNode
* pChk
, sal_uLong nLen
)
2090 // See if the supplied nodes actually contain fields.
2091 // If they don't, the flag doesn't need to be changed.
2092 bool bFldsFnd
= false;
2093 if( b
&& pChk
&& !GetUpdtFlds().IsFieldsDirty() && !IsInDtor()
2094 // ?? what's up with Undo, this is also wanted there!
2095 /*&& &pChk->GetNodes() == &GetNodes()*/ )
2100 sal_uLong nStt
= pChk
->GetIndex();
2101 const SwNodes
& rNds
= pChk
->GetNodes();
2104 const SwTxtNode
* pTNd
= rNds
[ nStt
++ ]->GetTxtNode();
2107 if( pTNd
->GetAttrOutlineLevel() != 0 )
2108 // update chapter fields
2110 else if( pTNd
->GetpSwpHints() && pTNd
->GetSwpHints().Count() )
2111 for( sal_uInt16 n
= 0, nEnd
= pTNd
->GetSwpHints().Count();
2114 const SwTxtAttr
* pAttr
= pTNd
->GetSwpHints()[ n
];
2115 if( RES_TXTATR_FIELD
== pAttr
->Which() )
2128 GetUpdtFlds().SetFieldsDirty( b
);
2132 void SwDoc::ChangeAuthorityData( const SwAuthEntry
* pNewData
)
2134 const sal_uInt16 nSize
= mpFldTypes
->size();
2136 for( sal_uInt16 i
= INIT_FLDTYPES
; i
< nSize
; ++i
)
2138 SwFieldType
* pFldType
= (*mpFldTypes
)[i
];
2139 if( RES_AUTHORITY
== pFldType
->Which() )
2141 SwAuthorityFieldType
* pAuthType
= (SwAuthorityFieldType
*)pFldType
;
2142 pAuthType
->ChangeEntryContent(pNewData
);
2149 void SwDocUpdtFld::InsDelFldInFldLst( bool bIns
, const SwTxtFld
& rFld
)
2151 sal_uInt16 nWhich
= rFld
.GetFld().GetFld()->GetTyp()->Which();
2156 case RES_HIDDENPARAFLD
:
2157 case RES_HIDDENTXTFLD
:
2158 case RES_DBNUMSETFLD
:
2159 case RES_DBNEXTSETFLD
:
2160 case RES_DBSETNUMBERFLD
:
2162 break; // these have to be added/removed!
2168 SetFieldsDirty( true );
2171 if( !bIns
) // if list is present and deleted
2172 return; // don't do a thing
2173 pFldSortLst
= new _SetGetExpFlds
;
2176 if( bIns
) // insert anew:
2177 GetBodyNode( rFld
, nWhich
);
2180 // look up via the pTxtFld pointer. It is a sorted list, but it's sorted by node
2181 // position. Until this is found, the search for the pointer is already done.
2182 for( sal_uInt16 n
= 0; n
< pFldSortLst
->size(); ++n
)
2183 if( &rFld
== (*pFldSortLst
)[ n
]->GetPointer() )
2185 delete (*pFldSortLst
)[n
];
2186 pFldSortLst
->erase(n
);
2187 n
--; // one field can occur multiple times
2192 void SwDocUpdtFld::MakeFldList( SwDoc
& rDoc
, int bAll
, int eGetMode
)
2194 if( !pFldSortLst
|| bAll
|| !( eGetMode
& nFldLstGetMode
) ||
2195 rDoc
.GetNodes().Count() != nNodes
)
2196 _MakeFldList( rDoc
, eGetMode
);
2199 void SwDocUpdtFld::_MakeFldList( SwDoc
& rDoc
, int eGetMode
)
2201 // new version: walk all fields of the attribute pool
2203 pFldSortLst
= new _SetGetExpFlds
;
2205 // consider and unhide sections
2206 // with hide condition, only in mode GETFLD_ALL (<eGetMode == GETFLD_ALL>)
2208 // eGetMode == GETFLD_CALC in call from methods SwDoc::FldsToCalc
2209 // eGetMode == GETFLD_EXPAND in call from method SwDoc::FldsToExpand
2210 // eGetMode == GETFLD_ALL in call from method SwDoc::UpdateExpFlds
2211 // I figured out that hidden section only have to be shown,
2212 // if fields have updated (call by SwDoc::UpdateExpFlds) and thus
2213 // the hide conditions of section have to be updated.
2214 // For correct updating the hide condition of a section, its position
2215 // have to be known in order to insert the hide condition as a new
2216 // expression field into the sorted field list (<pFldSortLst>).
2217 if ( eGetMode
== GETFLD_ALL
)
2218 // Collect the sections first. Supply sections that are hidden by condition
2219 // with frames so that the contained fields are sorted properly.
2221 // In order for the frames to be created the right way, they have to be expanded
2222 // from top to bottom
2223 std::vector
<sal_uLong
> aTmpArr
;
2224 SwSectionFmts
& rArr
= rDoc
.GetSections();
2225 SwSectionNode
* pSectNd
;
2226 sal_uInt16 nArrStt
= 0;
2227 sal_uLong nSttCntnt
= rDoc
.GetNodes().GetEndOfExtras().GetIndex();
2229 for (sal_uInt16 n
= rArr
.size(); n
; )
2231 SwSection
* pSect
= rArr
[ --n
]->GetSection();
2232 if( pSect
&& pSect
->IsHidden() && pSect
->GetCondition().Len() &&
2233 0 != ( pSectNd
= pSect
->GetFmt()->GetSectionNode() ))
2235 sal_uLong nIdx
= pSectNd
->GetIndex();
2236 aTmpArr
.push_back( nIdx
);
2237 if( nIdx
< nSttCntnt
)
2241 std::sort(aTmpArr
.begin(), aTmpArr
.end());
2243 // Display all first so that we have frames. The BodyAnchor is defined by that.
2244 // First the ContentArea, then the special areas!
2245 for (sal_uInt16 n
= nArrStt
; n
< aTmpArr
.size(); ++n
)
2247 pSectNd
= rDoc
.GetNodes()[ aTmpArr
[ n
] ]->GetSectionNode();
2248 OSL_ENSURE( pSectNd
, "Where is my SectionNode" );
2249 pSectNd
->GetSection().SetCondHidden( sal_False
);
2251 for (sal_uInt16 n
= 0; n
< nArrStt
; ++n
)
2253 pSectNd
= rDoc
.GetNodes()[ aTmpArr
[ n
] ]->GetSectionNode();
2254 OSL_ENSURE( pSectNd
, "Where is my SectionNode" );
2255 pSectNd
->GetSection().SetCondHidden( sal_False
);
2258 // add all to the list so that they are sorted
2259 for (sal_uInt16 n
= 0; n
< aTmpArr
.size(); ++n
)
2261 GetBodyNode( *rDoc
.GetNodes()[ aTmpArr
[ n
] ]->GetSectionNode() );
2265 OUString
sTrue("TRUE"), sFalse("FALSE");
2267 bool bIsDBMgr
= 0 != rDoc
.GetNewDBMgr();
2268 sal_uInt16 nWhich
, n
;
2269 const OUString
* pFormel
= 0;
2270 const SfxPoolItem
* pItem
;
2271 sal_uInt32 nMaxItems
= rDoc
.GetAttrPool().GetItemCount2( RES_TXTATR_FIELD
);
2272 for( n
= 0; n
< nMaxItems
; ++n
)
2274 if( 0 == (pItem
= rDoc
.GetAttrPool().GetItem2( RES_TXTATR_FIELD
, n
)) )
2277 const SwFmtFld
* pFmtFld
= (SwFmtFld
*)pItem
;
2278 const SwTxtFld
* pTxtFld
= pFmtFld
->GetTxtFld();
2279 if( !pTxtFld
|| !pTxtFld
->GetTxtNode().GetNodes().IsDocNodes() )
2282 const SwField
* pFld
= pFmtFld
->GetFld();
2283 switch( nWhich
= pFld
->GetTyp()->Which() )
2285 case RES_DBSETNUMBERFLD
:
2287 if( GETFLD_ALL
== eGetMode
)
2292 if( GETFLD_EXPAND
& eGetMode
)
2297 if ( !(eGetMode
== GETFLD_EXPAND
) ||
2298 (nsSwGetSetExpType::GSE_STRING
& pFld
->GetSubType()) )
2304 case RES_HIDDENPARAFLD
:
2305 if( GETFLD_ALL
== eGetMode
)
2307 pFormel
= &pFld
->GetPar1();
2308 if (pFormel
->isEmpty() || pFormel
->equals(sFalse
))
2309 ((SwHiddenParaField
*)pFld
)->SetHidden( sal_False
);
2310 else if (pFormel
->equals(sTrue
))
2311 ((SwHiddenParaField
*)pFld
)->SetHidden( sal_True
);
2316 // trigger formatting
2317 ((SwFmtFld
*)pFmtFld
)->ModifyNotification( 0, 0 );
2321 case RES_HIDDENTXTFLD
:
2322 if( GETFLD_ALL
== eGetMode
)
2324 pFormel
= &pFld
->GetPar1();
2325 if (pFormel
->isEmpty() || pFormel
->equals(sFalse
))
2326 ((SwHiddenTxtField
*)pFld
)->SetValue( sal_True
);
2327 else if (pFormel
->equals(sTrue
))
2328 ((SwHiddenTxtField
*)pFld
)->SetValue( sal_False
);
2335 ((SwHiddenTxtField
*)pFld
)->Evaluate(&rDoc
);
2336 // trigger formatting
2337 ((SwFmtFld
*)pFmtFld
)->ModifyNotification( 0, 0 );
2341 case RES_DBNUMSETFLD
:
2343 SwDBData
aDBData(((SwDBNumSetField
*)pFld
)->GetDBData(&rDoc
));
2346 (bIsDBMgr
&& rDoc
.GetNewDBMgr()->OpenDataSource(aDBData
.sDataSource
, aDBData
.sCommand
)) &&
2347 (GETFLD_ALL
== eGetMode
|| (GETFLD_CALC
& eGetMode
&& ((SwDBNumSetField
*)pFld
)->IsCondValid()))
2350 pFormel
= &pFld
->GetPar1();
2354 case RES_DBNEXTSETFLD
:
2356 SwDBData
aDBData(((SwDBNextSetField
*)pFld
)->GetDBData(&rDoc
));
2359 (bIsDBMgr
&& rDoc
.GetNewDBMgr()->OpenDataSource(aDBData
.sDataSource
, aDBData
.sCommand
)) &&
2360 (GETFLD_ALL
== eGetMode
|| (GETFLD_CALC
& eGetMode
&& ((SwDBNextSetField
*)pFld
)->IsCondValid()))
2363 pFormel
= &pFld
->GetPar1();
2369 if (pFormel
&& !pFormel
->isEmpty())
2371 GetBodyNode( *pTxtFld
, nWhich
);
2375 nFldLstGetMode
= static_cast<sal_uInt8
>( eGetMode
);
2376 nNodes
= rDoc
.GetNodes().Count();
2379 void SwDocUpdtFld::GetBodyNode( const SwTxtFld
& rTFld
, sal_uInt16 nFldWhich
)
2381 const SwTxtNode
& rTxtNd
= rTFld
.GetTxtNode();
2382 const SwDoc
& rDoc
= *rTxtNd
.GetDoc();
2384 // always the first! (in tab headline, header-/footer)
2386 const SwCntntFrm
* pFrm
= rTxtNd
.getLayoutFrm( rDoc
.GetCurrentLayout(), &aPt
, 0, sal_False
);
2388 _SetGetExpFld
* pNew
= NULL
;
2389 sal_Bool bIsInBody
= sal_False
;
2391 if( !pFrm
|| pFrm
->IsInDocBody() )
2393 // create index to determine the TextNode
2394 SwNodeIndex
aIdx( rTxtNd
);
2395 bIsInBody
= rDoc
.GetNodes().GetEndOfExtras().GetIndex() < aIdx
.GetIndex();
2397 // We don't want to update fields in redlines, or those
2398 // in frames whose anchor is in redline. However, we do want to update
2399 // fields in hidden sections. So: In order to be updated, a field 1)
2400 // must have a frame, or 2) it must be in the document body.
2401 if( (pFrm
!= NULL
) || bIsInBody
)
2402 pNew
= new _SetGetExpFld( aIdx
, &rTFld
);
2406 // create index to determine the TextNode
2407 SwPosition
aPos( rDoc
.GetNodes().GetEndOfPostIts() );
2408 bool const bResult
= GetBodyTxtNode( rDoc
, aPos
, *pFrm
);
2409 OSL_ENSURE(bResult
, "where is the Field");
2410 (void) bResult
; // unused in non-debug
2411 pNew
= new _SetGetExpFld( aPos
.nNode
, &rTFld
, &aPos
.nContent
);
2414 // always set the BodyTxtFlag in GetExp or DB fields
2415 if( RES_GETEXPFLD
== nFldWhich
)
2417 SwGetExpField
* pGetFld
= (SwGetExpField
*)rTFld
.GetFld().GetFld();
2418 pGetFld
->ChgBodyTxtFlag( bIsInBody
);
2420 else if( RES_DBFLD
== nFldWhich
)
2422 SwDBField
* pDBFld
= (SwDBField
*)rTFld
.GetFld().GetFld();
2423 pDBFld
->ChgBodyTxtFlag( bIsInBody
);
2427 if( !pFldSortLst
->insert( pNew
).second
)
2431 void SwDocUpdtFld::GetBodyNode( const SwSectionNode
& rSectNd
)
2433 const SwDoc
& rDoc
= *rSectNd
.GetDoc();
2434 _SetGetExpFld
* pNew
= 0;
2436 if( rSectNd
.GetIndex() < rDoc
.GetNodes().GetEndOfExtras().GetIndex() )
2438 do { // middle check loop
2440 // we need to get the anchor first
2441 // create index to determine the TextNode
2442 SwPosition
aPos( rSectNd
);
2443 SwCntntNode
* pCNd
= rDoc
.GetNodes().GoNext( &aPos
.nNode
); // to the next ContentNode
2445 if( !pCNd
|| !pCNd
->IsTxtNode() )
2448 // always the first! (in tab headline, header-/footer)
2450 const SwCntntFrm
* pFrm
= pCNd
->getLayoutFrm( rDoc
.GetCurrentLayout(), &aPt
, 0, sal_False
);
2454 bool const bResult
= GetBodyTxtNode( rDoc
, aPos
, *pFrm
);
2455 OSL_ENSURE(bResult
, "where is the Field");
2456 (void) bResult
; // unused in non-debug
2457 pNew
= new _SetGetExpFld( rSectNd
, &aPos
);
2463 pNew
= new _SetGetExpFld( rSectNd
);
2465 if( !pFldSortLst
->insert( pNew
).second
)
2469 void SwDocUpdtFld::InsertFldType( const SwFieldType
& rType
)
2472 switch( rType
.Which() )
2475 sFldName
= ((SwUserFieldType
&)rType
).GetName();
2478 sFldName
= ((SwSetExpFieldType
&)rType
).GetName();
2481 OSL_ENSURE( !this, "kein gueltiger FeldTyp" );
2484 if( sFldName
.Len() )
2486 SetFieldsDirty( true );
2487 // look up and remove from the hash table
2488 sFldName
= GetAppCharClass().lowercase( sFldName
);
2491 SwHash
* pFnd
= Find( sFldName
, GetFldTypeTable(), TBLSZ
, &n
);
2495 SwCalcFldType
* pNew
= new SwCalcFldType( sFldName
, &rType
);
2496 pNew
->pNext
= aFldTypeTable
[ n
];
2497 aFldTypeTable
[ n
] = pNew
;
2502 void SwDocUpdtFld::RemoveFldType( const SwFieldType
& rType
)
2505 switch( rType
.Which() )
2508 sFldName
= ((SwUserFieldType
&)rType
).GetName();
2511 sFldName
= ((SwSetExpFieldType
&)rType
).GetName();
2515 if( sFldName
.Len() )
2517 SetFieldsDirty( true );
2518 // look up and remove from the hash table
2519 sFldName
= GetAppCharClass().lowercase( sFldName
);
2522 SwHash
* pFnd
= Find( sFldName
, GetFldTypeTable(), TBLSZ
, &n
);
2525 if( aFldTypeTable
[ n
] == pFnd
)
2526 aFldTypeTable
[ n
] = (SwCalcFldType
*)pFnd
->pNext
;
2529 SwHash
* pPrev
= aFldTypeTable
[ n
];
2530 while( pPrev
->pNext
!= pFnd
)
2531 pPrev
= pPrev
->pNext
;
2532 pPrev
->pNext
= pFnd
->pNext
;
2540 SwDocUpdtFld::SwDocUpdtFld(SwDoc
* pDoc
)
2541 : pFldSortLst(0), nFldLstGetMode(0), pDocument(pDoc
)
2543 bInUpdateFlds
= bFldsDirty
= sal_False
;
2544 memset( aFldTypeTable
, 0, sizeof( aFldTypeTable
) );
2547 SwDocUpdtFld::~SwDocUpdtFld()
2551 for( sal_uInt16 n
= 0; n
< TBLSZ
; ++n
)
2552 delete aFldTypeTable
[n
];
2555 bool SwDoc::UpdateFld(SwTxtFld
* pDstTxtFld
, SwField
& rSrcFld
,
2556 SwMsgPoolItem
* pMsgHnt
,
2559 OSL_ENSURE(pDstTxtFld
, "no field to update!");
2561 bool bTblSelBreak
= false;
2563 SwFmtFld
* pDstFmtFld
= (SwFmtFld
*)&pDstTxtFld
->GetFld();
2564 SwField
* pDstFld
= pDstFmtFld
->GetFld();
2565 sal_uInt16 nFldWhich
= rSrcFld
.GetTyp()->Which();
2566 SwNodeIndex
aTblNdIdx(pDstTxtFld
->GetTxtNode());
2568 if (pDstFld
->GetTyp()->Which() ==
2569 rSrcFld
.GetTyp()->Which())
2571 if (GetIDocumentUndoRedo().DoesUndo())
2573 SwPosition
aPosition( pDstTxtFld
->GetTxtNode() );
2574 aPosition
.nContent
= *pDstTxtFld
->GetStart();
2576 SwUndo
*const pUndo( new SwUndoFieldFromDoc(
2577 aPosition
, *pDstFld
, rSrcFld
, pMsgHnt
, bUpdateFlds
) );
2578 GetIDocumentUndoRedo().AppendUndo(pUndo
);
2581 SwField
* pNewFld
= rSrcFld
.CopyField();
2582 pDstFmtFld
->SetFld(pNewFld
);
2588 case RES_HIDDENTXTFLD
:
2589 case RES_HIDDENPARAFLD
:
2590 UpdateExpFlds( pDstTxtFld
, true );
2595 const SwTableNode
* pTblNd
=
2596 IsIdxInTbl(aTblNdIdx
);
2599 SwTableFmlUpdate
aTblUpdate( &pTblNd
->
2602 UpdateTblFlds( &aTblUpdate
);
2604 pNewFld
->GetTyp()->ModifyNotification(0, &aTblUpdate
);
2607 bTblSelBreak
= true;
2613 if( bUpdateFlds
&& pDstTxtFld
->GetpTxtNode() )
2614 (pDstTxtFld
->GetpTxtNode())->
2615 ModifyNotification( 0, pDstFmtFld
);
2619 case RES_DBNEXTSETFLD
:
2620 case RES_DBNUMSETFLD
:
2621 case RES_DBSETNUMBERFLD
:
2622 ChgDBData(((SwDBNameInfField
*) pNewFld
)->GetRealDBData());
2623 pNewFld
->GetTyp()->UpdateFlds();
2629 // JP 10.02.96: call ChgValue, so that the style change sets the
2630 // ContentString correctly
2631 SwDBField
* pDBFld
= (SwDBField
*)pNewFld
;
2632 if (pDBFld
->IsInitialized())
2633 pDBFld
->ChgValue( pDBFld
->GetValue(), sal_True
);
2635 pDBFld
->ClearInitialized();
2636 pDBFld
->InitContent();
2641 pDstFmtFld
->ModifyNotification( 0, pMsgHnt
);
2644 // The fields we can calculate here are being triggered for an update
2646 if( nFldWhich
== RES_USERFLD
)
2650 return bTblSelBreak
;
2653 bool SwDoc::PutValueToField(const SwPosition
& rPos
,
2654 const Any
& rVal
, sal_uInt16 nWhich
)
2657 SwField
* pField
= GetField(rPos
);
2660 if (GetIDocumentUndoRedo().DoesUndo() &&
2661 pField
->QueryValue(aOldVal
, nWhich
))
2663 SwUndo
*const pUndo(new SwUndoFieldFromAPI(rPos
, aOldVal
, rVal
, nWhich
));
2664 GetIDocumentUndoRedo().AppendUndo(pUndo
);
2667 return pField
->PutValue(rVal
, nWhich
);
2670 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */