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