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