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( 282 sal_uInt16 nResId, 283 const String& rName, 284 bool bDbFieldMatching // used in some UNO calls for RES_DBFLD to use different string matching code #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->GetField(); 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->GetField())->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( 759 const SwNodeIndex& rNdIdx, 760 const SwTxtFld* pFld, 761 const SwIndex* pIdx ) 762 { 763 eSetGetExpFldType = TEXTFIELD; 764 CNTNT.pTxtFld = pFld; 765 nNode = rNdIdx.GetIndex(); 766 if( pIdx ) 767 nCntnt = pIdx->GetIndex(); 768 else if( pFld ) 769 nCntnt = *pFld->GetStart(); 770 else 771 nCntnt = 0; 772 } 773 774 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx, 775 const SwTxtINetFmt& rINet, const SwIndex* pIdx ) 776 { 777 eSetGetExpFldType = TEXTINET; 778 CNTNT.pTxtINet = &rINet; 779 nNode = rNdIdx.GetIndex(); 780 if( pIdx ) 781 nCntnt = pIdx->GetIndex(); 782 else 783 nCntnt = *rINet.GetStart(); 784 } 785 786 //Erweiterung fuer Sections: 787 // diese haben immer als Content-Position 0xffff !! 788 // Auf dieser steht nie ein Feld, maximal bis STRING_MAXLEN moeglich 789 _SetGetExpFld::_SetGetExpFld( const SwSectionNode& rSectNd, 790 const SwPosition* pPos ) 791 { 792 eSetGetExpFldType = SECTIONNODE; 793 CNTNT.pSection = &rSectNd.GetSection(); 794 795 if( pPos ) 796 { 797 nNode = pPos->nNode.GetIndex(); 798 nCntnt = pPos->nContent.GetIndex(); 799 } 800 else 801 { 802 nNode = rSectNd.GetIndex(); 803 nCntnt = 0; 804 } 805 } 806 807 _SetGetExpFld::_SetGetExpFld( const SwTableBox& rTBox, const SwPosition* pPos ) 808 { 809 eSetGetExpFldType = TABLEBOX; 810 CNTNT.pTBox = &rTBox; 811 812 if( pPos ) 813 { 814 nNode = pPos->nNode.GetIndex(); 815 nCntnt = pPos->nContent.GetIndex(); 816 } 817 else 818 { 819 nNode = 0; 820 nCntnt = 0; 821 if( rTBox.GetSttNd() ) 822 { 823 SwNodeIndex aIdx( *rTBox.GetSttNd() ); 824 const SwCntntNode* pNd = aIdx.GetNode().GetNodes().GoNext( &aIdx ); 825 if( pNd ) 826 nNode = pNd->GetIndex(); 827 } 828 } 829 } 830 831 _SetGetExpFld::_SetGetExpFld( const SwNodeIndex& rNdIdx, 832 const SwTxtTOXMark& rTOX, 833 const SwIndex* pIdx ) 834 { 835 eSetGetExpFldType = TEXTTOXMARK; 836 CNTNT.pTxtTOX = &rTOX; 837 nNode = rNdIdx.GetIndex(); 838 if( pIdx ) 839 nCntnt = pIdx->GetIndex(); 840 else 841 nCntnt = *rTOX.GetStart(); 842 } 843 844 _SetGetExpFld::_SetGetExpFld( const SwPosition& rPos ) 845 { 846 eSetGetExpFldType = CRSRPOS; 847 CNTNT.pPos = &rPos; 848 nNode = rPos.nNode.GetIndex(); 849 nCntnt = rPos.nContent.GetIndex(); 850 } 851 852 _SetGetExpFld::_SetGetExpFld( const SwFlyFrmFmt& rFlyFmt, 853 const SwPosition* pPos ) 854 { 855 eSetGetExpFldType = FLYFRAME; 856 CNTNT.pFlyFmt = &rFlyFmt; 857 if( pPos ) 858 { 859 nNode = pPos->nNode.GetIndex(); 860 nCntnt = pPos->nContent.GetIndex(); 861 } 862 else 863 { 864 const SwFmtCntnt& rCntnt = rFlyFmt.GetCntnt(); 865 nNode = rCntnt.GetCntntIdx()->GetIndex() + 1; 866 nCntnt = 0; 867 } 868 } 869 870 void _SetGetExpFld::GetPos( SwPosition& rPos ) const 871 { 872 rPos.nNode = nNode; 873 rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt ); 874 } 875 876 void _SetGetExpFld::GetPosOfContent( SwPosition& rPos ) const 877 { 878 const SwNode* pNd = GetNodeFromCntnt(); 879 if( pNd ) 880 pNd = pNd->GetCntntNode(); 881 882 if( pNd ) 883 { 884 rPos.nNode = *pNd; 885 rPos.nContent.Assign( (SwCntntNode*)pNd,GetCntPosFromCntnt() ); 886 } 887 else 888 { 889 rPos.nNode = nNode; 890 rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), nCntnt ); 891 } 892 } 893 894 void _SetGetExpFld::SetBodyPos( const SwCntntFrm& rFrm ) 895 { 896 if( !rFrm.IsInDocBody() ) 897 { 898 SwNodeIndex aIdx( *rFrm.GetNode() ); 899 SwDoc& rDoc = *aIdx.GetNodes().GetDoc(); 900 SwPosition aPos( aIdx ); 901 #ifdef DBG_UTIL 902 ASSERT( ::GetBodyTxtNode( rDoc, aPos, rFrm ), "wo steht das Feld" ); 903 #else 904 ::GetBodyTxtNode( rDoc, aPos, rFrm ); 905 #endif 906 nNode = aPos.nNode.GetIndex(); 907 nCntnt = aPos.nContent.GetIndex(); 908 } 909 } 910 911 sal_Bool _SetGetExpFld::operator==( const _SetGetExpFld& rFld ) const 912 { 913 return nNode == rFld.nNode 914 && nCntnt == rFld.nCntnt 915 && ( !CNTNT.pTxtFld 916 || !rFld.CNTNT.pTxtFld 917 || CNTNT.pTxtFld == rFld.CNTNT.pTxtFld ); 918 } 919 920 sal_Bool _SetGetExpFld::operator<( const _SetGetExpFld& rFld ) const 921 { 922 if( nNode < rFld.nNode || ( nNode == rFld.nNode && nCntnt < rFld.nCntnt )) 923 return sal_True; 924 else if( nNode != rFld.nNode || nCntnt != rFld.nCntnt ) 925 return sal_False; 926 927 const SwNode *pFirst = GetNodeFromCntnt(), 928 *pNext = rFld.GetNodeFromCntnt(); 929 930 // Position gleich: nur weiter wenn beide FeldPointer besetzt sind !! 931 if( !pFirst || !pNext ) 932 return sal_False; 933 934 // gleiche Section ?? 935 if( pFirst->StartOfSectionNode() != pNext->StartOfSectionNode() ) 936 { 937 // sollte einer in der Tabelle stehen ? 938 const SwNode *pFirstStt, *pNextStt; 939 const SwTableNode* pTblNd = pFirst->FindTableNode(); 940 if( pTblNd ) 941 pFirstStt = pTblNd->StartOfSectionNode(); 942 else 943 pFirstStt = pFirst->StartOfSectionNode(); 944 945 if( 0 != ( pTblNd = pNext->FindTableNode() ) ) 946 pNextStt = pTblNd->StartOfSectionNode(); 947 else 948 pNextStt = pNext->StartOfSectionNode(); 949 950 if( pFirstStt != pNextStt ) 951 { 952 if( pFirst->IsTxtNode() && pNext->IsTxtNode() && 953 ( pFirst->FindFlyStartNode() || pNext->FindFlyStartNode() )) 954 { 955 return ::IsFrameBehind( *(SwTxtNode*)pNext, nCntnt, 956 *(SwTxtNode*)pFirst, nCntnt ); 957 } 958 return pFirstStt->GetIndex() < pNextStt->GetIndex(); 959 } 960 } 961 962 // ist gleiche Section, dann Feld im gleichen Node ? 963 if( pFirst != pNext ) 964 return pFirst->GetIndex() < pNext->GetIndex(); 965 966 // gleicher Node in der Section, dann Position im Node 967 return GetCntPosFromCntnt() < rFld.GetCntPosFromCntnt(); 968 } 969 970 const SwNode* _SetGetExpFld::GetNodeFromCntnt() const 971 { 972 const SwNode* pRet = 0; 973 if( CNTNT.pTxtFld ) 974 switch( eSetGetExpFldType ) 975 { 976 case TEXTFIELD: 977 pRet = &CNTNT.pTxtFld->GetTxtNode(); 978 break; 979 980 case TEXTINET: 981 pRet = &CNTNT.pTxtINet->GetTxtNode(); 982 break; 983 984 case SECTIONNODE: 985 pRet = CNTNT.pSection->GetFmt()->GetSectionNode(); 986 break; 987 988 case CRSRPOS: 989 pRet = &CNTNT.pPos->nNode.GetNode(); 990 break; 991 992 case TEXTTOXMARK: 993 pRet = &CNTNT.pTxtTOX->GetTxtNode(); 994 break; 995 996 case TABLEBOX: 997 if( CNTNT.pTBox->GetSttNd() ) 998 { 999 SwNodeIndex aIdx( *CNTNT.pTBox->GetSttNd() ); 1000 pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx ); 1001 } 1002 break; 1003 1004 case FLYFRAME: 1005 { 1006 SwNodeIndex aIdx( *CNTNT.pFlyFmt->GetCntnt().GetCntntIdx() ); 1007 pRet = aIdx.GetNode().GetNodes().GoNext( &aIdx ); 1008 } 1009 break; 1010 } 1011 return pRet; 1012 } 1013 1014 xub_StrLen _SetGetExpFld::GetCntPosFromCntnt() const 1015 { 1016 sal_uInt16 nRet = 0; 1017 if( CNTNT.pTxtFld ) 1018 switch( eSetGetExpFldType ) 1019 { 1020 case TEXTFIELD: 1021 case TEXTINET: 1022 case TEXTTOXMARK: 1023 nRet = *CNTNT.pTxtFld->GetStart(); 1024 break; 1025 case CRSRPOS: 1026 nRet = CNTNT.pPos->nContent.GetIndex(); 1027 break; 1028 default: 1029 break; 1030 } 1031 return nRet; 1032 } 1033 1034 _HashStr::_HashStr( const String& rName, const String& rText, 1035 _HashStr* pNxt ) 1036 : SwHash( rName ), aSetStr( rText ) 1037 { 1038 pNext = pNxt; 1039 } 1040 1041 // suche nach dem Namen, ist er vorhanden, returne seinen String, sonst 1042 // einen LeerString 1043 void LookString( SwHash** ppTbl, sal_uInt16 nSize, const String& rName, 1044 String& rRet, sal_uInt16* pPos ) 1045 { 1046 rRet = rName; 1047 rRet.EraseLeadingChars().EraseTrailingChars(); 1048 SwHash* pFnd = Find( rRet, ppTbl, nSize, pPos ); 1049 if( pFnd ) 1050 rRet = ((_HashStr*)pFnd)->aSetStr; 1051 else 1052 rRet.Erase(); 1053 } 1054 1055 /*-------------------------------------------------------------------- 1056 Beschreibung: 1057 --------------------------------------------------------------------*/ 1058 1059 String lcl_GetDBVarName( SwDoc& rDoc, SwDBNameInfField& rDBFld ) 1060 { 1061 SwDBData aDBData( rDBFld.GetDBData( &rDoc )); 1062 String sDBNumNm; 1063 SwDBData aDocData = rDoc.GetDBData(); 1064 1065 if( aDBData != aDocData ) 1066 { 1067 sDBNumNm = aDBData.sDataSource; 1068 sDBNumNm += DB_DELIM; 1069 sDBNumNm += String(aDBData.sCommand); 1070 sDBNumNm += DB_DELIM; 1071 } 1072 sDBNumNm += SwFieldType::GetTypeStr(TYP_DBSETNUMBERFLD); 1073 1074 return sDBNumNm; 1075 } 1076 1077 /*-------------------------------------------------------------------- 1078 Beschreibung: 1079 --------------------------------------------------------------------*/ 1080 1081 void lcl_CalcFld( SwDoc& rDoc, SwCalc& rCalc, const _SetGetExpFld& rSGEFld, 1082 SwNewDBMgr* pMgr ) 1083 { 1084 const SwTxtFld* pTxtFld = rSGEFld.GetTxtFld(); 1085 if( !pTxtFld ) 1086 return ; 1087 1088 const SwField* pFld = pTxtFld->GetFmtFld().GetField(); 1089 const sal_uInt16 nFldWhich = pFld->GetTyp()->Which(); 1090 1091 if( RES_SETEXPFLD == nFldWhich ) 1092 { 1093 SwSbxValue aValue; 1094 if( nsSwGetSetExpType::GSE_EXPR & pFld->GetSubType() ) 1095 aValue.PutDouble( ((SwSetExpField*)pFld)->GetValue() ); 1096 else 1097 // Erweiterung fuers Rechnen mit Strings 1098 aValue.PutString( ((SwSetExpField*)pFld)->GetExpStr() ); 1099 1100 // setze im Calculator den neuen Wert 1101 rCalc.VarChange( pFld->GetTyp()->GetName(), aValue ); 1102 } 1103 else if( pMgr ) 1104 { 1105 switch( nFldWhich ) 1106 { 1107 case RES_DBNUMSETFLD: 1108 { 1109 SwDBNumSetField* pDBFld = (SwDBNumSetField*)pFld; 1110 1111 SwDBData aDBData(pDBFld->GetDBData(&rDoc)); 1112 1113 if( pDBFld->IsCondValid() && 1114 pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand )) 1115 rCalc.VarChange( lcl_GetDBVarName( rDoc, *pDBFld), 1116 pDBFld->GetFormat() ); 1117 } 1118 break; 1119 case RES_DBNEXTSETFLD: 1120 { 1121 SwDBNextSetField* pDBFld = (SwDBNextSetField*)pFld; 1122 SwDBData aDBData(pDBFld->GetDBData(&rDoc)); 1123 if( !pDBFld->IsCondValid() || 1124 !pMgr->OpenDataSource( aDBData.sDataSource, aDBData.sCommand )) 1125 break; 1126 1127 String sDBNumNm(lcl_GetDBVarName( rDoc, *pDBFld)); 1128 SwCalcExp* pExp = rCalc.VarLook( sDBNumNm ); 1129 if( pExp ) 1130 rCalc.VarChange( sDBNumNm, pExp->nValue.GetLong() + 1 ); 1131 } 1132 break; 1133 1134 } 1135 } 1136 } 1137 1138 void SwDoc::FldsToCalc( SwCalc& rCalc, const _SetGetExpFld& rToThisFld ) 1139 { 1140 // erzeuge die Sortierteliste aller SetFelder 1141 pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC ); 1142 mbNewFldLst = sal_False; 1143 1144 SwNewDBMgr* pMgr = GetNewDBMgr(); 1145 pMgr->CloseAll(sal_False); 1146 1147 if( pUpdtFlds->GetSortLst()->Count() ) 1148 { 1149 sal_uInt16 nLast; 1150 _SetGetExpFld* pFld = (_SetGetExpFld*)&rToThisFld; 1151 if( pUpdtFlds->GetSortLst()->Seek_Entry( pFld, &nLast ) ) 1152 ++nLast; 1153 1154 const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData(); 1155 for( sal_uInt16 n = 0; n < nLast; ++n, ++ppSortLst ) 1156 lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr ); 1157 } 1158 1159 pMgr->CloseAll(sal_False); 1160 } 1161 1162 void SwDoc::FldsToCalc( SwCalc& rCalc, sal_uLong nLastNd, sal_uInt16 nLastCnt ) 1163 { 1164 // erzeuge die Sortierteliste aller SetFelder 1165 pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_CALC ); 1166 mbNewFldLst = sal_False; 1167 1168 SwNewDBMgr* pMgr = GetNewDBMgr(); 1169 pMgr->CloseAll(sal_False); 1170 1171 const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData(); 1172 1173 for( sal_uInt16 n = pUpdtFlds->GetSortLst()->Count(); 1174 n && 1175 ( (*ppSortLst)->GetNode() < nLastNd || 1176 ( (*ppSortLst)->GetNode() == nLastNd && (*ppSortLst)->GetCntnt() <= nLastCnt ) 1177 ); 1178 --n, ++ppSortLst ) 1179 lcl_CalcFld( *this, rCalc, **ppSortLst, pMgr ); 1180 1181 pMgr->CloseAll(sal_False); 1182 } 1183 1184 void SwDoc::FldsToExpand( SwHash**& ppHashTbl, sal_uInt16& rTblSize, 1185 const _SetGetExpFld& rToThisFld ) 1186 { 1187 // erzeuge die Sortierteliste aller SetFelder 1188 pUpdtFlds->MakeFldList( *this, mbNewFldLst, GETFLD_EXPAND ); 1189 mbNewFldLst = sal_False; 1190 1191 // HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt 1192 // (versuche eine "ungerade"-Zahl zu erzeugen) 1193 rTblSize = (( pUpdtFlds->GetSortLst()->Count() / 7 ) + 1 ) * 7; 1194 ppHashTbl = new SwHash*[ rTblSize ]; 1195 memset( ppHashTbl, 0, sizeof( _HashStr* ) * rTblSize ); 1196 1197 sal_uInt16 nLast; 1198 { 1199 _SetGetExpFld* pTmp = (_SetGetExpFld*)&rToThisFld; 1200 if( pUpdtFlds->GetSortLst()->Seek_Entry( pTmp, &nLast ) ) 1201 ++nLast; 1202 } 1203 1204 sal_uInt16 nPos; 1205 SwHash* pFnd; 1206 String aNew; 1207 const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData(); 1208 for( ; nLast; --nLast, ++ppSortLst ) 1209 { 1210 const SwTxtFld* pTxtFld = (*ppSortLst)->GetTxtFld(); 1211 if( !pTxtFld ) 1212 continue; 1213 1214 const SwField* pFld = pTxtFld->GetFmtFld().GetField(); 1215 switch( pFld->GetTyp()->Which() ) 1216 { 1217 case RES_SETEXPFLD: 1218 if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() ) 1219 { 1220 // setze in der HashTabelle den neuen Wert 1221 // ist die "Formel" ein Feld ?? 1222 SwSetExpField* pSFld = (SwSetExpField*)pFld; 1223 LookString( ppHashTbl, rTblSize, pSFld->GetFormula(), aNew ); 1224 1225 if( !aNew.Len() ) // nichts gefunden, dann ist 1226 aNew = pSFld->GetFormula(); // die Formel der neue Wert 1227 1228 // OD 11.02.2003 #i3141# - update expression of field as in 1229 // method <SwDoc::UpdateExpFlds(..)> for string/text fields 1230 pSFld->ChgExpStr( aNew ); 1231 1232 // suche den Namen vom Feld 1233 aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName(); 1234 // Eintrag vorhanden ? 1235 pFnd = Find( aNew, ppHashTbl, rTblSize, &nPos ); 1236 if( pFnd ) 1237 // Eintrag in der HashTabelle aendern 1238 ((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr(); 1239 else 1240 // neuen Eintrag einfuegen 1241 *(ppHashTbl + nPos ) = new _HashStr( aNew, 1242 pSFld->GetExpStr(), (_HashStr*)*(ppHashTbl + nPos) ); 1243 } 1244 break; 1245 case RES_DBFLD: 1246 { 1247 const String& rName = pFld->GetTyp()->GetName(); 1248 1249 // Eintrag in den HashTable eintragen 1250 // Eintrag vorhanden ? 1251 pFnd = Find( rName, ppHashTbl, rTblSize, &nPos ); 1252 String const value(pFld->ExpandField(IsClipBoard())); 1253 if( pFnd ) 1254 { 1255 // Eintrag in der HashTabelle aendern 1256 static_cast<_HashStr*>(pFnd)->aSetStr = value; 1257 } 1258 else 1259 { 1260 // neuen Eintrag einfuegen 1261 *(ppHashTbl + nPos ) = new _HashStr( rName, 1262 value, static_cast<_HashStr *>(*(ppHashTbl + nPos))); 1263 } 1264 } 1265 break; 1266 } 1267 } 1268 } 1269 1270 1271 void SwDoc::UpdateExpFlds( SwTxtFld* pUpdtFld, bool bUpdRefFlds ) 1272 { 1273 if( IsExpFldsLocked() || IsInReading() ) 1274 return; 1275 1276 sal_Bool bOldInUpdateFlds = pUpdtFlds->IsInUpdateFlds(); 1277 pUpdtFlds->SetInUpdateFlds( sal_True ); 1278 1279 pUpdtFlds->MakeFldList( *this, sal_True, GETFLD_ALL ); 1280 mbNewFldLst = sal_False; 1281 1282 if( !pUpdtFlds->GetSortLst()->Count() ) 1283 { 1284 if( bUpdRefFlds ) 1285 UpdateRefFlds(NULL); 1286 1287 pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds ); 1288 pUpdtFlds->SetFieldsDirty( sal_False ); 1289 return ; 1290 } 1291 1292 sal_uInt16 nWhich, n; 1293 1294 // HashTabelle fuer alle String Ersetzungen, wird "one the fly" gefuellt 1295 // (versuche eine "ungerade"-Zahl zu erzeugen) 1296 sal_uInt16 nStrFmtCnt = (( pFldTypes->Count() / 7 ) + 1 ) * 7; 1297 SwHash** pHashStrTbl = new SwHash*[ nStrFmtCnt ]; 1298 memset( pHashStrTbl, 0, sizeof( _HashStr* ) * nStrFmtCnt ); 1299 1300 { 1301 const SwFieldType* pFldType; 1302 // gesondert behandeln: 1303 for( n = pFldTypes->Count(); n; ) 1304 switch( ( pFldType = (*pFldTypes)[ --n ] )->Which() ) 1305 { 1306 case RES_USERFLD: 1307 { 1308 // Eintrag vorhanden ? 1309 sal_uInt16 nPos; 1310 const String& rNm = pFldType->GetName(); 1311 String sExpand(((SwUserFieldType*)pFldType)->Expand(nsSwGetSetExpType::GSE_STRING, 0, 0)); 1312 SwHash* pFnd = Find( rNm, pHashStrTbl, nStrFmtCnt, &nPos ); 1313 if( pFnd ) 1314 // Eintrag in der HashTabelle aendern ?? 1315 ((_HashStr*)pFnd)->aSetStr = sExpand; 1316 else 1317 // neuen Eintrag einfuegen 1318 *(pHashStrTbl + nPos ) = new _HashStr( rNm, sExpand, 1319 (_HashStr*)*(pHashStrTbl + nPos) ); 1320 } 1321 break; 1322 case RES_SETEXPFLD: 1323 ((SwSetExpFieldType*)pFldType)->SetOutlineChgNd( 0 ); 1324 break; 1325 } 1326 } 1327 1328 // Ok, das Array ist soweit mit allen Feldern gefuellt, dann rechne mal 1329 SwCalc aCalc( *this ); 1330 1331 String sDBNumNm( SwFieldType::GetTypeStr( TYP_DBSETNUMBERFLD ) ); 1332 1333 // aktuelle Datensatznummer schon vorher einstellen 1334 SwNewDBMgr* pMgr = GetNewDBMgr(); 1335 pMgr->CloseAll(sal_False); 1336 /* 1337 if(pMgr && pMgr->OpenDB(DBMGR_STD, GetDBDesc(), sal_False)) 1338 { 1339 if(!pMgr->IsInMerge() ) 1340 pMgr->ToFirstSelectedRecord(DBMGR_STD); 1341 1342 aCalc.VarChange( sDBNumNm, pMgr->GetCurSelectedRecordId(DBMGR_STD)); 1343 } 1344 */ 1345 1346 String aNew; 1347 const _SetGetExpFldPtr* ppSortLst = pUpdtFlds->GetSortLst()->GetData(); 1348 for( n = pUpdtFlds->GetSortLst()->Count(); n; --n, ++ppSortLst ) 1349 { 1350 SwSection* pSect = (SwSection*)(*ppSortLst)->GetSection(); 1351 if( pSect ) 1352 { 1353 //!SECTION 1354 1355 SwSbxValue aValue = aCalc.Calculate( 1356 pSect->GetCondition() ); 1357 if(!aValue.IsVoidValue()) 1358 pSect->SetCondHidden( aValue.GetBool() ); 1359 continue; 1360 } 1361 1362 SwTxtFld* pTxtFld = (SwTxtFld*)(*ppSortLst)->GetTxtFld(); 1363 if( !pTxtFld ) 1364 { 1365 ASSERT( !this, "was ist es denn nun" ); 1366 continue; 1367 } 1368 1369 SwFmtFld* pFmtFld = (SwFmtFld*)&pTxtFld->GetFmtFld(); 1370 const SwField* pFld = pFmtFld->GetField(); 1371 1372 switch( nWhich = pFld->GetTyp()->Which() ) 1373 { 1374 case RES_HIDDENTXTFLD: 1375 { 1376 SwHiddenTxtField* pHFld = (SwHiddenTxtField*)pFld; 1377 SwSbxValue aValue = aCalc.Calculate( pHFld->GetPar1() ); 1378 sal_Bool bValue = !aValue.GetBool(); 1379 if(!aValue.IsVoidValue()) 1380 { 1381 pHFld->SetValue( bValue ); 1382 // Feld Evaluieren 1383 pHFld->Evaluate(this); 1384 } 1385 } 1386 break; 1387 case RES_HIDDENPARAFLD: 1388 { 1389 SwHiddenParaField* pHPFld = (SwHiddenParaField*)pFld; 1390 SwSbxValue aValue = aCalc.Calculate( pHPFld->GetPar1() ); 1391 sal_Bool bValue = aValue.GetBool(); 1392 if(!aValue.IsVoidValue()) 1393 pHPFld->SetHidden( bValue ); 1394 } 1395 break; 1396 case RES_DBSETNUMBERFLD: 1397 { 1398 ((SwDBSetNumberField*)pFld)->Evaluate(this); 1399 aCalc.VarChange( sDBNumNm, ((SwDBSetNumberField*)pFld)->GetSetNumber()); 1400 } 1401 break; 1402 case RES_DBNEXTSETFLD: 1403 case RES_DBNUMSETFLD: 1404 UpdateDBNumFlds( *(SwDBNameInfField*)pFld, aCalc ); 1405 break; 1406 case RES_DBFLD: 1407 { 1408 // Feld Evaluieren 1409 ((SwDBField*)pFld)->Evaluate(); 1410 1411 SwDBData aTmpDBData(((SwDBField*)pFld)->GetDBData()); 1412 1413 if( pMgr->IsDataSourceOpen(aTmpDBData.sDataSource, aTmpDBData.sCommand, sal_False)) 1414 aCalc.VarChange( sDBNumNm, pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType)); 1415 1416 const String& rName = pFld->GetTyp()->GetName(); 1417 1418 // Wert fuer den Calculator setzen 1419 //JP 10.02.96: GetValue macht hier doch keinen Sinn 1420 // ((SwDBField*)pFld)->GetValue(); 1421 1422 //!OK aCalc.VarChange(aName, ((SwDBField*)pFld)->GetValue(aCalc)); 1423 1424 // Eintrag in den HashTable eintragen 1425 // Eintrag vorhanden ? 1426 sal_uInt16 nPos; 1427 SwHash* pFnd = Find( rName, pHashStrTbl, nStrFmtCnt, &nPos ); 1428 String const value(pFld->ExpandField(IsClipBoard())); 1429 if( pFnd ) 1430 { 1431 // Eintrag in der HashTabelle aendern 1432 static_cast<_HashStr*>(pFnd)->aSetStr = value; 1433 } 1434 else 1435 { 1436 // neuen Eintrag einfuegen 1437 *(pHashStrTbl + nPos ) = new _HashStr( rName, 1438 value, static_cast<_HashStr *>(*(pHashStrTbl + nPos))); 1439 } 1440 } 1441 break; 1442 case RES_GETEXPFLD: 1443 case RES_SETEXPFLD: 1444 { 1445 if( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() ) // String Ersetzung 1446 { 1447 if( RES_GETEXPFLD == nWhich ) 1448 { 1449 SwGetExpField* pGFld = (SwGetExpField*)pFld; 1450 1451 if( (!pUpdtFld || pUpdtFld == pTxtFld ) 1452 && pGFld->IsInBodyTxt() ) 1453 { 1454 LookString( pHashStrTbl, nStrFmtCnt, 1455 pGFld->GetFormula(), aNew ); 1456 pGFld->ChgExpStr( aNew ); 1457 } 1458 } 1459 else 1460 { 1461 SwSetExpField* pSFld = (SwSetExpField*)pFld; 1462 // ist die "Formel" ein Feld ?? 1463 LookString( pHashStrTbl, nStrFmtCnt, 1464 pSFld->GetFormula(), aNew ); 1465 1466 if( !aNew.Len() ) // nichts gefunden, dann ist die 1467 aNew = pSFld->GetFormula(); // Formel der neue Wert 1468 1469 // nur ein spezielles FeldUpdaten ? 1470 if( !pUpdtFld || pUpdtFld == pTxtFld ) 1471 pSFld->ChgExpStr( aNew ); 1472 1473 // suche den Namen vom Feld 1474 aNew = ((SwSetExpFieldType*)pSFld->GetTyp())->GetSetRefName(); 1475 // Eintrag vorhanden ? 1476 sal_uInt16 nPos; 1477 SwHash* pFnd = Find( aNew, pHashStrTbl, nStrFmtCnt, &nPos ); 1478 if( pFnd ) 1479 // Eintrag in der HashTabelle aendern 1480 ((_HashStr*)pFnd)->aSetStr = pSFld->GetExpStr(); 1481 else 1482 // neuen Eintrag einfuegen 1483 *(pHashStrTbl + nPos ) = pFnd = new _HashStr( aNew, 1484 pSFld->GetExpStr(), 1485 (_HashStr*)*(pHashStrTbl + nPos) ); 1486 1487 // Erweiterung fuers Rechnen mit Strings 1488 SwSbxValue aValue; 1489 aValue.PutString( ((_HashStr*)pFnd)->aSetStr ); 1490 aCalc.VarChange( aNew, aValue ); 1491 } 1492 } 1493 else // Formel neu berechnen 1494 { 1495 if( RES_GETEXPFLD == nWhich ) 1496 { 1497 SwGetExpField* pGFld = (SwGetExpField*)pFld; 1498 1499 if( (!pUpdtFld || pUpdtFld == pTxtFld ) 1500 && pGFld->IsInBodyTxt() ) 1501 { 1502 SwSbxValue aValue = aCalc.Calculate( 1503 pGFld->GetFormula()); 1504 if(!aValue.IsVoidValue()) 1505 pGFld->SetValue(aValue.GetDouble() ); 1506 } 1507 } 1508 else 1509 { 1510 SwSetExpField* pSFld = (SwSetExpField*)pFld; 1511 SwSetExpFieldType* pSFldTyp = (SwSetExpFieldType*)pFld->GetTyp(); 1512 aNew = pSFldTyp->GetName(); 1513 1514 SwNode* pSeqNd = 0; 1515 1516 if( pSFld->IsSequenceFld() ) 1517 { 1518 const sal_uInt8 nLvl = pSFldTyp->GetOutlineLvl(); 1519 if( MAXLEVEL > nLvl ) 1520 { 1521 // dann teste, ob die Nummer neu aufsetzen muss 1522 pSeqNd = GetNodes()[ (*ppSortLst)->GetNode() ]; 1523 1524 const SwTxtNode* pOutlNd = pSeqNd-> 1525 FindOutlineNodeOfLevel( nLvl ); 1526 if( pSFldTyp->GetOutlineChgNd() != pOutlNd ) 1527 { 1528 pSFldTyp->SetOutlineChgNd( pOutlNd ); 1529 aCalc.VarChange( aNew, 0 ); 1530 } 1531 } 1532 } 1533 1534 aNew += '='; 1535 aNew += pSFld->GetFormula(); 1536 1537 SwSbxValue aValue = aCalc.Calculate( aNew ); 1538 double nErg = aValue.GetDouble(); 1539 // nur ein spezielles Feld updaten ? 1540 if( !aValue.IsVoidValue() && (!pUpdtFld || pUpdtFld == pTxtFld) ) 1541 { 1542 pSFld->SetValue( nErg ); 1543 1544 if( pSeqNd ) 1545 pSFldTyp->SetChapter( *pSFld, *pSeqNd ); 1546 } 1547 } 1548 } 1549 } 1550 } // switch 1551 1552 pFmtFld->ModifyNotification( 0, 0 ); // Formatierung anstossen 1553 1554 if( pUpdtFld == pTxtFld ) // sollte nur dieses geupdatet werden 1555 { 1556 if( RES_GETEXPFLD == nWhich || // nur GetFeld oder 1557 RES_HIDDENTXTFLD == nWhich || // HiddenTxt? 1558 RES_HIDDENPARAFLD == nWhich) // HiddenParaFld? 1559 break; // beenden 1560 pUpdtFld = 0; // ab jetzt alle Updaten 1561 } 1562 } 1563 1564 pMgr->CloseAll(sal_False); 1565 // HashTabelle wieder loeschen 1566 ::DeleteHashTable( pHashStrTbl, nStrFmtCnt ); 1567 1568 // Referenzfelder updaten 1569 if( bUpdRefFlds ) 1570 UpdateRefFlds(NULL); 1571 1572 pUpdtFlds->SetInUpdateFlds( bOldInUpdateFlds ); 1573 pUpdtFlds->SetFieldsDirty( sal_False ); 1574 } 1575 1576 /*-------------------------------------------------------------------- 1577 Beschreibung: 1578 --------------------------------------------------------------------*/ 1579 1580 void SwDoc::UpdateDBNumFlds( SwDBNameInfField& rDBFld, SwCalc& rCalc ) 1581 { 1582 SwNewDBMgr* pMgr = GetNewDBMgr(); 1583 1584 sal_uInt16 nFldType = rDBFld.Which(); 1585 1586 sal_Bool bPar1 = rCalc.Calculate( rDBFld.GetPar1() ).GetBool(); 1587 1588 if( RES_DBNEXTSETFLD == nFldType ) 1589 ((SwDBNextSetField&)rDBFld).SetCondValid( bPar1 ); 1590 else 1591 ((SwDBNumSetField&)rDBFld).SetCondValid( bPar1 ); 1592 1593 if( rDBFld.GetRealDBData().sDataSource.getLength() ) 1594 { 1595 // Eine bestimmte Datenbank bearbeiten 1596 if( RES_DBNEXTSETFLD == nFldType ) 1597 ((SwDBNextSetField&)rDBFld).Evaluate(this); 1598 else 1599 ((SwDBNumSetField&)rDBFld).Evaluate(this); 1600 1601 SwDBData aTmpDBData( rDBFld.GetDBData(this) ); 1602 1603 if( pMgr->OpenDataSource( aTmpDBData.sDataSource, aTmpDBData.sCommand, -1, false )) 1604 rCalc.VarChange( lcl_GetDBVarName( *this, rDBFld), 1605 pMgr->GetSelectedRecordId(aTmpDBData.sDataSource, aTmpDBData.sCommand, aTmpDBData.nCommandType) ); 1606 } 1607 else 1608 { 1609 DBG_ERROR("TODO: what should happen with unnamed DBFields?"); 1610 } 1611 } 1612 1613 /*-------------------------------------------------------------------- 1614 Beschreibung: 1615 --------------------------------------------------------------------*/ 1616 1617 void SwDoc::_InitFieldTypes() // wird vom CTOR gerufen!! 1618 { 1619 // Feldtypen 1620 sal_uInt16 nFldType = 0; 1621 pFldTypes->Insert( new SwDateTimeFieldType(this), nFldType++ ); 1622 pFldTypes->Insert( new SwChapterFieldType, nFldType++ ); 1623 pFldTypes->Insert( new SwPageNumberFieldType, nFldType++ ); 1624 pFldTypes->Insert( new SwAuthorFieldType, nFldType++ ); 1625 pFldTypes->Insert( new SwFileNameFieldType(this), nFldType++ ); 1626 pFldTypes->Insert( new SwDBNameFieldType(this), nFldType++); 1627 pFldTypes->Insert( new SwGetExpFieldType(this), nFldType++ ); 1628 pFldTypes->Insert( new SwGetRefFieldType( this ), nFldType++ ); 1629 pFldTypes->Insert( new SwHiddenTxtFieldType, nFldType++ ); 1630 pFldTypes->Insert( new SwPostItFieldType(this), nFldType++ ); 1631 pFldTypes->Insert( new SwDocStatFieldType(this), nFldType++); 1632 pFldTypes->Insert( new SwDocInfoFieldType(this), nFldType++); 1633 pFldTypes->Insert( new SwInputFieldType( this ), nFldType++ ); 1634 pFldTypes->Insert( new SwTblFieldType( this ), nFldType++); 1635 pFldTypes->Insert( new SwMacroFieldType(this), nFldType++ ); 1636 pFldTypes->Insert( new SwHiddenParaFieldType, nFldType++ ); 1637 pFldTypes->Insert( new SwDBNextSetFieldType, nFldType++ ); 1638 pFldTypes->Insert( new SwDBNumSetFieldType, nFldType++ ); 1639 pFldTypes->Insert( new SwDBSetNumberFieldType, nFldType++ ); 1640 pFldTypes->Insert( new SwTemplNameFieldType(this), nFldType++); 1641 pFldTypes->Insert( new SwTemplNameFieldType(this),nFldType++); 1642 pFldTypes->Insert( new SwExtUserFieldType, nFldType++ ); 1643 pFldTypes->Insert( new SwRefPageSetFieldType, nFldType++ ); 1644 pFldTypes->Insert( new SwRefPageGetFieldType( this ), nFldType++ ); 1645 pFldTypes->Insert( new SwJumpEditFieldType( this ), nFldType++ ); 1646 pFldTypes->Insert( new SwScriptFieldType( this ), nFldType++ ); 1647 pFldTypes->Insert( new SwCombinedCharFieldType, nFldType++ ); 1648 pFldTypes->Insert( new SwDropDownFieldType, nFldType++ ); 1649 1650 // Types muessen am Ende stehen !! 1651 // Im InsertFldType wird davon ausgegangen !!!! 1652 // MIB 14.04.95: Im Sw3StringPool::Setup (sw3imp.cxx) und 1653 // lcl_sw3io_InSetExpField (sw3field.cxx) jetzt auch 1654 pFldTypes->Insert( new SwSetExpFieldType(this, 1655 SW_RESSTR(STR_POOLCOLL_LABEL_ABB), nsSwGetSetExpType::GSE_SEQ), nFldType++); 1656 pFldTypes->Insert( new SwSetExpFieldType(this, 1657 SW_RESSTR(STR_POOLCOLL_LABEL_TABLE), nsSwGetSetExpType::GSE_SEQ),nFldType++); 1658 pFldTypes->Insert( new SwSetExpFieldType(this, 1659 SW_RESSTR(STR_POOLCOLL_LABEL_FRAME), nsSwGetSetExpType::GSE_SEQ),nFldType++); 1660 pFldTypes->Insert( new SwSetExpFieldType(this, 1661 SW_RESSTR(STR_POOLCOLL_LABEL_DRAWING), nsSwGetSetExpType::GSE_SEQ),nFldType++); 1662 1663 ASSERT( nFldType == INIT_FLDTYPES, "Bad initsize: SwFldTypes" ); 1664 } 1665 1666 void SwDoc::InsDelFldInFldLst( bool bIns, const SwTxtFld& rFld ) 1667 { 1668 if( !mbNewFldLst || !IsInDtor() ) 1669 pUpdtFlds->InsDelFldInFldLst( bIns, rFld ); 1670 } 1671 1672 SwDBData SwDoc::GetDBData() 1673 { 1674 return GetDBDesc(); 1675 } 1676 1677 const SwDBData& SwDoc::GetDBDesc() 1678 { 1679 if(!aDBData.sDataSource.getLength()) 1680 { 1681 const sal_uInt16 nSize = pFldTypes->Count(); 1682 for(sal_uInt16 i = 0; i < nSize && !aDBData.sDataSource.getLength(); ++i) 1683 { 1684 SwFieldType& rFldType = *((*pFldTypes)[i]); 1685 sal_uInt16 nWhich = rFldType.Which(); 1686 if(IsUsed(rFldType)) 1687 { 1688 switch(nWhich) 1689 { 1690 case RES_DBFLD: 1691 case RES_DBNEXTSETFLD: 1692 case RES_DBNUMSETFLD: 1693 case RES_DBSETNUMBERFLD: 1694 { 1695 SwIterator<SwFmtFld,SwFieldType> aIter( rFldType ); 1696 for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() ) 1697 { 1698 if(pFld->IsFldInDoc()) 1699 { 1700 if(RES_DBFLD == nWhich) 1701 aDBData = (static_cast < SwDBFieldType * > (pFld->GetField()->GetTyp()))->GetDBData(); 1702 else 1703 aDBData = (static_cast < SwDBNameInfField* > (pFld->GetField()))->GetRealDBData(); 1704 break; 1705 } 1706 } 1707 } 1708 break; 1709 } 1710 } 1711 } 1712 } 1713 if(!aDBData.sDataSource.getLength()) 1714 aDBData = GetNewDBMgr()->GetAddressDBName(); 1715 return aDBData; 1716 } 1717 1718 void SwDoc::SetInitDBFields( sal_Bool b ) 1719 { 1720 GetNewDBMgr()->SetInitDBFields( b ); 1721 } 1722 1723 /*-------------------------------------------------------------------- 1724 Beschreibung: Alle von Feldern verwendete Datenbanken herausfinden 1725 --------------------------------------------------------------------*/ 1726 String lcl_DBDataToString(const SwDBData& rData) 1727 { 1728 String sRet = rData.sDataSource; 1729 sRet += DB_DELIM; 1730 sRet += (String)rData.sCommand; 1731 sRet += DB_DELIM; 1732 sRet += String::CreateFromInt32(rData.nCommandType); 1733 return sRet; 1734 } 1735 void SwDoc::GetAllUsedDB( SvStringsDtor& rDBNameList, 1736 const SvStringsDtor* pAllDBNames ) 1737 { 1738 SvStringsDtor aUsedDBNames; 1739 SvStringsDtor aAllDBNames; 1740 1741 if( !pAllDBNames ) 1742 { 1743 GetAllDBNames( aAllDBNames ); 1744 pAllDBNames = &aAllDBNames; 1745 } 1746 1747 SwSectionFmts& rArr = GetSections(); 1748 for (sal_uInt16 n = rArr.Count(); n; ) 1749 { 1750 SwSection* pSect = rArr[ --n ]->GetSection(); 1751 1752 if( pSect ) 1753 { 1754 String aCond( pSect->GetCondition() ); 1755 AddUsedDBToList( rDBNameList, FindUsedDBs( *pAllDBNames, 1756 aCond, aUsedDBNames ) ); 1757 aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() ); 1758 } 1759 } 1760 1761 const SfxPoolItem* pItem; 1762 sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_FIELD ); 1763 for (sal_uInt32 n = 0; n < nMaxItems; ++n) 1764 { 1765 if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) )) 1766 continue; 1767 1768 const SwFmtFld* pFmtFld = (SwFmtFld*)pItem; 1769 const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld(); 1770 if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() ) 1771 continue; 1772 1773 const SwField* pFld = pFmtFld->GetField(); 1774 switch( pFld->GetTyp()->Which() ) 1775 { 1776 case RES_DBFLD: 1777 AddUsedDBToList( rDBNameList, 1778 lcl_DBDataToString(((SwDBField*)pFld)->GetDBData() )); 1779 break; 1780 1781 case RES_DBSETNUMBERFLD: 1782 case RES_DBNAMEFLD: 1783 AddUsedDBToList( rDBNameList, 1784 lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() )); 1785 break; 1786 1787 case RES_DBNUMSETFLD: 1788 case RES_DBNEXTSETFLD: 1789 AddUsedDBToList( rDBNameList, 1790 lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData() )); 1791 // kein break // JP: ist das so richtig ?? 1792 1793 case RES_HIDDENTXTFLD: 1794 case RES_HIDDENPARAFLD: 1795 AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames, 1796 pFld->GetPar1(), aUsedDBNames )); 1797 aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() ); 1798 break; 1799 1800 case RES_SETEXPFLD: 1801 case RES_GETEXPFLD: 1802 case RES_TABLEFLD: 1803 AddUsedDBToList(rDBNameList, FindUsedDBs( *pAllDBNames, 1804 pFld->GetFormula(), aUsedDBNames )); 1805 aUsedDBNames.DeleteAndDestroy( 0, aUsedDBNames.Count() ); 1806 break; 1807 } 1808 } 1809 } 1810 1811 /*-------------------------------------------------------------------- 1812 Beschreibung: 1813 --------------------------------------------------------------------*/ 1814 1815 void SwDoc::GetAllDBNames( SvStringsDtor& rAllDBNames ) 1816 { 1817 SwNewDBMgr* pMgr = GetNewDBMgr(); 1818 1819 const SwDSParamArr& rArr = pMgr->GetDSParamArray(); 1820 for(sal_uInt16 i = 0; i < rArr.Count(); i++) 1821 { 1822 SwDSParam* pParam = rArr[i]; 1823 String* pStr = new String( pParam->sDataSource ); 1824 (*pStr) += DB_DELIM; 1825 (*pStr) += (String)pParam->sCommand; 1826 rAllDBNames.Insert( pStr, rAllDBNames.Count() ); 1827 } 1828 } 1829 1830 /*-------------------------------------------------------------------- 1831 Beschreibung: 1832 --------------------------------------------------------------------*/ 1833 1834 SvStringsDtor& SwDoc::FindUsedDBs( const SvStringsDtor& rAllDBNames, 1835 const String& rFormel, 1836 SvStringsDtor& rUsedDBNames ) 1837 { 1838 const CharClass& rCC = GetAppCharClass(); 1839 String sFormel( rFormel); 1840 #ifndef UNX 1841 rCC.toUpper( sFormel ); 1842 #endif 1843 1844 xub_StrLen nPos; 1845 for (sal_uInt16 i = 0; i < rAllDBNames.Count(); ++i ) 1846 { 1847 const String* pStr = rAllDBNames.GetObject(i); 1848 1849 if( STRING_NOTFOUND != (nPos = sFormel.Search( *pStr )) && 1850 sFormel.GetChar( nPos + pStr->Len() ) == '.' && 1851 (!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 ))) 1852 { 1853 // Tabellenname suchen 1854 xub_StrLen nEndPos; 1855 nPos += pStr->Len() + 1; 1856 if( STRING_NOTFOUND != (nEndPos = sFormel.Search('.', nPos)) ) 1857 { 1858 String* pDBNm = new String( *pStr ); 1859 pDBNm->Append( DB_DELIM ); 1860 pDBNm->Append( sFormel.Copy( nPos, nEndPos - nPos )); 1861 rUsedDBNames.Insert( pDBNm, rUsedDBNames.Count() ); 1862 } 1863 } 1864 } 1865 return rUsedDBNames; 1866 } 1867 1868 /*-------------------------------------------------------------------- 1869 Beschreibung: 1870 --------------------------------------------------------------------*/ 1871 1872 void SwDoc::AddUsedDBToList( SvStringsDtor& rDBNameList, 1873 const SvStringsDtor& rUsedDBNames ) 1874 { 1875 for (sal_uInt16 i = 0; i < rUsedDBNames.Count(); i++) 1876 AddUsedDBToList( rDBNameList, *rUsedDBNames.GetObject(i) ); 1877 } 1878 1879 /*-------------------------------------------------------------------- 1880 Beschreibung: 1881 --------------------------------------------------------------------*/ 1882 1883 void SwDoc::AddUsedDBToList( SvStringsDtor& rDBNameList, const String& rDBName) 1884 { 1885 if( !rDBName.Len() ) 1886 return; 1887 1888 #ifdef UNX 1889 for( sal_uInt16 i = 0; i < rDBNameList.Count(); ++i ) 1890 if( rDBName == rDBNameList.GetObject(i)->GetToken(0) ) 1891 return; 1892 #else 1893 const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore(); 1894 for( sal_uInt16 i = 0; i < rDBNameList.Count(); ++i ) 1895 if( rSCmp.isEqual( rDBName, rDBNameList.GetObject(i)->GetToken(0) ) ) 1896 return; 1897 #endif 1898 1899 SwDBData aData; 1900 aData.sDataSource = rDBName.GetToken(0, DB_DELIM); 1901 aData.sCommand = rDBName.GetToken(1, DB_DELIM); 1902 aData.nCommandType = -1; 1903 GetNewDBMgr()->CreateDSData(aData); 1904 String* pNew = new String( rDBName ); 1905 rDBNameList.Insert( pNew, rDBNameList.Count() ); 1906 } 1907 1908 /*-------------------------------------------------------------------- 1909 Beschreibung: 1910 --------------------------------------------------------------------*/ 1911 1912 void SwDoc::ChangeDBFields( const SvStringsDtor& rOldNames, 1913 const String& rNewName ) 1914 { 1915 SwDBData aNewDBData; 1916 aNewDBData.sDataSource = rNewName.GetToken(0, DB_DELIM); 1917 aNewDBData.sCommand = rNewName.GetToken(1, DB_DELIM); 1918 aNewDBData.nCommandType = (short)rNewName.GetToken(2, DB_DELIM).ToInt32(); 1919 1920 String sFormel; 1921 1922 SwSectionFmts& rArr = GetSections(); 1923 for (sal_uInt16 n = rArr.Count(); n; ) 1924 { 1925 SwSection* pSect = rArr[ --n ]->GetSection(); 1926 1927 if( pSect ) 1928 { 1929 sFormel = pSect->GetCondition(); 1930 ReplaceUsedDBs( rOldNames, rNewName, sFormel); 1931 pSect->SetCondition(sFormel); 1932 } 1933 } 1934 1935 const SfxPoolItem* pItem; 1936 sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_FIELD ); 1937 1938 for (sal_uInt32 n = 0; n < nMaxItems; ++n ) 1939 { 1940 if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_FIELD, n ) )) 1941 continue; 1942 1943 SwFmtFld* pFmtFld = (SwFmtFld*)pItem; 1944 SwTxtFld* pTxtFld = pFmtFld->GetTxtFld(); 1945 if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() ) 1946 continue; 1947 1948 SwField* pFld = pFmtFld->GetField(); 1949 sal_Bool bExpand = sal_False; 1950 1951 switch( pFld->GetTyp()->Which() ) 1952 { 1953 case RES_DBFLD: 1954 if( IsNameInArray( rOldNames, lcl_DBDataToString(((SwDBField*)pFld)->GetDBData()))) 1955 { 1956 SwDBFieldType* pOldTyp = (SwDBFieldType*)pFld->GetTyp(); 1957 1958 SwDBFieldType* pTyp = (SwDBFieldType*)InsertFldType( 1959 SwDBFieldType(this, pOldTyp->GetColumnName(), aNewDBData)); 1960 1961 pFmtFld->RegisterToFieldType( *pTyp ); 1962 pFld->ChgTyp(pTyp); 1963 1964 ((SwDBField*)pFld)->ClearInitialized(); 1965 ((SwDBField*)pFld)->InitContent(); 1966 1967 bExpand = sal_True; 1968 } 1969 break; 1970 1971 case RES_DBSETNUMBERFLD: 1972 case RES_DBNAMEFLD: 1973 if( IsNameInArray( rOldNames, 1974 lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData()))) 1975 { 1976 ((SwDBNameInfField*)pFld)->SetDBData(aNewDBData); 1977 bExpand = sal_True; 1978 } 1979 break; 1980 1981 case RES_DBNUMSETFLD: 1982 case RES_DBNEXTSETFLD: 1983 if( IsNameInArray( rOldNames, 1984 lcl_DBDataToString(((SwDBNameInfField*)pFld)->GetRealDBData()))) 1985 { 1986 ((SwDBNameInfField*)pFld)->SetDBData(aNewDBData); 1987 bExpand = sal_True; 1988 } 1989 // kein break; 1990 case RES_HIDDENTXTFLD: 1991 case RES_HIDDENPARAFLD: 1992 sFormel = pFld->GetPar1(); 1993 ReplaceUsedDBs( rOldNames, rNewName, sFormel); 1994 pFld->SetPar1( sFormel ); 1995 bExpand = sal_True; 1996 break; 1997 1998 case RES_SETEXPFLD: 1999 case RES_GETEXPFLD: 2000 case RES_TABLEFLD: 2001 sFormel = pFld->GetFormula(); 2002 ReplaceUsedDBs( rOldNames, rNewName, sFormel); 2003 pFld->SetPar2( sFormel ); 2004 bExpand = sal_True; 2005 break; 2006 } 2007 2008 if (bExpand) 2009 pTxtFld->ExpandAlways(); 2010 } 2011 SetModified(); 2012 } 2013 2014 /*-------------------------------------------------------------------- 2015 Beschreibung: 2016 --------------------------------------------------------------------*/ 2017 2018 void SwDoc::ReplaceUsedDBs( const SvStringsDtor& rUsedDBNames, 2019 const String& rNewName, String& rFormel ) 2020 { 2021 const CharClass& rCC = GetAppCharClass(); 2022 String sFormel(rFormel); 2023 String sNewName( rNewName ); 2024 sNewName.SearchAndReplace( DB_DELIM, '.'); 2025 //the command type is not part of the condition 2026 sNewName = sNewName.GetToken(0, DB_DELIM); 2027 String sUpperNewNm( sNewName ); 2028 2029 2030 for( sal_uInt16 i = 0; i < rUsedDBNames.Count(); ++i ) 2031 { 2032 String sDBName( *rUsedDBNames.GetObject( i ) ); 2033 2034 sDBName.SearchAndReplace( DB_DELIM, '.'); 2035 //cut off command type 2036 sDBName = sDBName.GetToken(0, DB_DELIM); 2037 if( !sDBName.Equals( sUpperNewNm )) 2038 { 2039 xub_StrLen nPos = 0; 2040 2041 while ((nPos = sFormel.Search(sDBName, nPos)) != STRING_NOTFOUND) 2042 { 2043 if( sFormel.GetChar( nPos + sDBName.Len() ) == '.' && 2044 (!nPos || !rCC.isLetterNumeric( sFormel, nPos - 1 ))) 2045 { 2046 rFormel.Erase( nPos, sDBName.Len() ); 2047 rFormel.Insert( sNewName, nPos ); 2048 //prevent re-searching - this is useless and provokes 2049 //endless loops when names containing each other and numbers are exchanged 2050 //e.g.: old ?12345.12345 new: i12345.12345 2051 nPos = nPos + sNewName.Len(); 2052 sFormel = rFormel; 2053 } 2054 } 2055 } 2056 } 2057 } 2058 2059 /*-------------------------------------------------------------------- 2060 Beschreibung: 2061 --------------------------------------------------------------------*/ 2062 2063 sal_Bool SwDoc::IsNameInArray( const SvStringsDtor& rArr, const String& rName ) 2064 { 2065 #ifdef UNX 2066 for( sal_uInt16 i = 0; i < rArr.Count(); ++i ) 2067 if( rName == *rArr[ i ] ) 2068 return sal_True; 2069 #else 2070 const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore(); 2071 for( sal_uInt16 i = 0; i < rArr.Count(); ++i ) 2072 if( rSCmp.isEqual( rName, *rArr[ i] )) 2073 return sal_True; 2074 #endif 2075 return sal_False; 2076 } 2077 2078 void SwDoc::SetFixFields( bool bOnlyTimeDate, const DateTime* pNewDateTime ) 2079 { 2080 sal_Bool bIsModified = IsModified(); 2081 2082 sal_uLong nDate, nTime; 2083 if( pNewDateTime ) 2084 { 2085 nDate = pNewDateTime->GetDate(); 2086 nTime = pNewDateTime->GetTime(); 2087 } 2088 else 2089 { 2090 nDate = Date().GetDate(); 2091 nTime = Time().GetTime(); 2092 } 2093 2094 sal_uInt16 aTypes[5] = { 2095 /*0*/ RES_DOCINFOFLD, 2096 /*1*/ RES_AUTHORFLD, 2097 /*2*/ RES_EXTUSERFLD, 2098 /*3*/ RES_FILENAMEFLD, 2099 /*4*/ RES_DATETIMEFLD }; // MUSS am Ende stehen!! 2100 2101 sal_uInt16 nStt = bOnlyTimeDate ? 4 : 0; 2102 2103 for( ; nStt < 5; ++nStt ) 2104 { 2105 SwFieldType* pFldType = GetSysFldType( aTypes[ nStt ] ); 2106 SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType ); 2107 for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() ) 2108 { 2109 if( pFmtFld && pFmtFld->GetTxtFld() ) 2110 { 2111 sal_Bool bChgd = sal_False; 2112 switch( aTypes[ nStt ] ) 2113 { 2114 case RES_DOCINFOFLD: 2115 if( ((SwDocInfoField*)pFmtFld->GetField())->IsFixed() ) 2116 { 2117 bChgd = sal_True; 2118 SwDocInfoField* pDocInfFld = (SwDocInfoField*)pFmtFld->GetField(); 2119 pDocInfFld->SetExpansion( ((SwDocInfoFieldType*) 2120 pDocInfFld->GetTyp())->Expand( 2121 pDocInfFld->GetSubType(), 2122 pDocInfFld->GetFormat(), 2123 pDocInfFld->GetLanguage(), 2124 pDocInfFld->GetName() ) ); 2125 } 2126 break; 2127 2128 case RES_AUTHORFLD: 2129 if( ((SwAuthorField*)pFmtFld->GetField())->IsFixed() ) 2130 { 2131 bChgd = sal_True; 2132 SwAuthorField* pAuthorFld = (SwAuthorField*)pFmtFld->GetField(); 2133 pAuthorFld->SetExpansion( ((SwAuthorFieldType*) 2134 pAuthorFld->GetTyp())->Expand( 2135 pAuthorFld->GetFormat() ) ); 2136 } 2137 break; 2138 2139 case RES_EXTUSERFLD: 2140 if( ((SwExtUserField*)pFmtFld->GetField())->IsFixed() ) 2141 { 2142 bChgd = sal_True; 2143 SwExtUserField* pExtUserFld = (SwExtUserField*)pFmtFld->GetField(); 2144 pExtUserFld->SetExpansion( ((SwExtUserFieldType*) 2145 pExtUserFld->GetTyp())->Expand( 2146 pExtUserFld->GetSubType(), 2147 pExtUserFld->GetFormat())); 2148 } 2149 break; 2150 2151 case RES_DATETIMEFLD: 2152 if( ((SwDateTimeField*)pFmtFld->GetField())->IsFixed() ) 2153 { 2154 bChgd = sal_True; 2155 ((SwDateTimeField*)pFmtFld->GetField())->SetDateTime( 2156 DateTime(Date(nDate), Time(nTime)) ); 2157 } 2158 break; 2159 2160 case RES_FILENAMEFLD: 2161 if( ((SwFileNameField*)pFmtFld->GetField())->IsFixed() ) 2162 { 2163 bChgd = sal_True; 2164 SwFileNameField* pFileNameFld = 2165 (SwFileNameField*)pFmtFld->GetField(); 2166 pFileNameFld->SetExpansion( ((SwFileNameFieldType*) 2167 pFileNameFld->GetTyp())->Expand( 2168 pFileNameFld->GetFormat() ) ); 2169 } 2170 break; 2171 } 2172 2173 // Formatierung anstossen 2174 if( bChgd ) 2175 pFmtFld->ModifyNotification( 0, 0 ); 2176 } 2177 } 2178 } 2179 2180 if( !bIsModified ) 2181 ResetModified(); 2182 } 2183 2184 bool SwDoc::SetFieldsDirty( bool b, const SwNode* pChk, sal_uLong nLen ) 2185 { 2186 // teste ggfs. mal, ob die angegbenen Nodes ueberhaupt Felder beinhalten. 2187 // wenn nicht, braucht das Flag nicht veraendert werden. 2188 sal_Bool bFldsFnd = sal_False; 2189 if( b && pChk && !GetUpdtFlds().IsFieldsDirty() && !IsInDtor() 2190 // ?? was ist mit Undo, da will man es doch auch haben !! 2191 /*&& &pChk->GetNodes() == &GetNodes()*/ ) 2192 { 2193 b = sal_False; 2194 if( !nLen ) 2195 ++nLen; 2196 sal_uLong nStt = pChk->GetIndex(); 2197 const SwNodes& rNds = pChk->GetNodes(); 2198 while( nLen-- ) 2199 { 2200 const SwTxtNode* pTNd = rNds[ nStt++ ]->GetTxtNode(); 2201 if( pTNd ) 2202 { 2203 if( //pTNd->GetFmtColl() && //#outline level,zhaojianwei 2204 // MAXLEVEL > pTNd->GetTxtColl()->GetOutlineLevel() ) 2205 pTNd->GetAttrOutlineLevel() != 0 )//<-end,zhaojianwei 2206 // Kapitelfelder aktualisieren 2207 b = sal_True; 2208 else if( pTNd->GetpSwpHints() && pTNd->GetSwpHints().Count() ) 2209 for( sal_uInt16 n = 0, nEnd = pTNd->GetSwpHints().Count(); 2210 n < nEnd; ++n ) 2211 { 2212 const SwTxtAttr* pAttr = pTNd->GetSwpHints()[ n ]; 2213 if ( pAttr->Which() == RES_TXTATR_FIELD ) 2214 { 2215 b = sal_True; 2216 break; 2217 } 2218 } 2219 2220 if( b ) 2221 break; 2222 } 2223 } 2224 bFldsFnd = b; 2225 } 2226 GetUpdtFlds().SetFieldsDirty( b ); 2227 return bFldsFnd; 2228 } 2229 /* -----------------------------21.12.99 12:55-------------------------------- 2230 2231 ---------------------------------------------------------------------------*/ 2232 void SwDoc::ChangeAuthorityData( const SwAuthEntry* pNewData ) 2233 { 2234 const sal_uInt16 nSize = pFldTypes->Count(); 2235 2236 for( sal_uInt16 i = INIT_FLDTYPES; i < nSize; ++i ) 2237 { 2238 SwFieldType* pFldType = (*pFldTypes)[i]; 2239 if( RES_AUTHORITY == pFldType->Which() ) 2240 { 2241 SwAuthorityFieldType* pAuthType = (SwAuthorityFieldType*)pFldType; 2242 pAuthType->ChangeEntryContent(pNewData); 2243 break; 2244 } 2245 } 2246 2247 } 2248 /*-------------------------------------------------------------------- 2249 Beschreibung: 2250 --------------------------------------------------------------------*/ 2251 2252 void SwDocUpdtFld::InsDelFldInFldLst( sal_Bool bIns, const SwTxtFld& rFld ) 2253 { 2254 const sal_uInt16 nWhich = rFld.GetFmtFld().GetField()->GetTyp()->Which(); 2255 switch( nWhich ) 2256 { 2257 case RES_DBFLD: 2258 case RES_SETEXPFLD: 2259 case RES_HIDDENPARAFLD: 2260 case RES_HIDDENTXTFLD: 2261 case RES_DBNUMSETFLD: 2262 case RES_DBNEXTSETFLD: 2263 case RES_DBSETNUMBERFLD: 2264 case RES_GETEXPFLD: 2265 break; // diese muessen ein-/ausgetragen werden! 2266 2267 default: 2268 return; 2269 } 2270 2271 SetFieldsDirty( sal_True ); 2272 if( !pFldSortLst ) 2273 { 2274 if( !bIns ) // keine Liste vorhanden und loeschen 2275 return; // dann nichts tun 2276 pFldSortLst = new _SetGetExpFlds( 64, 16 ); 2277 } 2278 2279 if( bIns ) // neu einfuegen: 2280 GetBodyNode( rFld, nWhich ); 2281 else 2282 { 2283 // ueber den pTxtFld Pointer suchen. Ist zwar eine Sortierte 2284 // Liste, aber nach Node-Positionen sortiert. Bis dieser 2285 // bestimmt ist, ist das Suchen nach dem Pointer schon fertig 2286 for( sal_uInt16 n = 0; n < pFldSortLst->Count(); ++n ) 2287 if( &rFld == (*pFldSortLst)[ n ]->GetPointer() ) 2288 pFldSortLst->DeleteAndDestroy( n--, 1 ); 2289 // ein Feld kann mehrfach vorhanden sein! 2290 } 2291 } 2292 2293 void SwDocUpdtFld::MakeFldList( SwDoc& rDoc, int bAll, int eGetMode ) 2294 { 2295 if( !pFldSortLst || bAll || !( eGetMode & nFldLstGetMode ) || 2296 rDoc.GetNodes().Count() != nNodes ) 2297 _MakeFldList( rDoc, eGetMode ); 2298 } 2299 2300 void SwDocUpdtFld::_MakeFldList( SwDoc& rDoc, int eGetMode ) 2301 { 2302 // neue Version: gehe ueber alle Felder vom Attribut-Pool 2303 if( pFldSortLst ) 2304 delete pFldSortLst; 2305 pFldSortLst = new _SetGetExpFlds( 64, 16 ); 2306 2307 /// OD 09.08.2002 [#101207#,#101216#,#101778#] - consider and unhide sections 2308 /// with hide condition, only in mode GETFLD_ALL (<eGetMode == GETFLD_ALL>) 2309 /// notes by OD: 2310 /// eGetMode == GETFLD_CALC in call from methods SwDoc::FldsToCalc 2311 /// eGetMode == GETFLD_EXPAND in call from method SwDoc::FldsToExpand 2312 /// eGetMode == GETFLD_ALL in call from method SwDoc::UpdateExpFlds 2313 /// I figured out that hidden section only have to be shown, 2314 /// if fields have updated (call by SwDoc::UpdateExpFlds) and thus 2315 /// the hide conditions of section have to be updated. 2316 /// For correct updating the hide condition of a section, its position 2317 /// have to be known in order to insert the hide condition as a new 2318 /// expression field into the sorted field list (<pFldSortLst>). 2319 if ( eGetMode == GETFLD_ALL ) 2320 // zuerst die Bereiche einsammeln. Alle die ueber Bedingung 2321 // gehiddet sind, wieder mit Frames versorgen, damit die darin 2322 // enthaltenen Felder richtig einsortiert werden!!! 2323 { 2324 // damit die Frames richtig angelegt werden, muessen sie in der 2325 // Reihenfolgen von oben nach unten expandiert werden 2326 SvULongs aTmpArr; 2327 SwSectionFmts& rArr = rDoc.GetSections(); 2328 SwSectionNode* pSectNd; 2329 sal_uInt16 nArrStt = 0; 2330 sal_uLong nSttCntnt = rDoc.GetNodes().GetEndOfExtras().GetIndex(); 2331 2332 for (sal_uInt16 n = rArr.Count(); n; ) 2333 { 2334 SwSection* pSect = rArr[ --n ]->GetSection(); 2335 if( pSect && pSect->IsHidden() && pSect->GetCondition().Len() && 2336 0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() )) 2337 { 2338 sal_uLong nIdx = pSectNd->GetIndex(); 2339 sal_uInt16 i; 2340 2341 for( i = 0; i < aTmpArr.Count() && aTmpArr[ i ] < nIdx; ++i ) 2342 ; 2343 aTmpArr.Insert( nIdx, i ); 2344 if( nIdx < nSttCntnt ) 2345 ++nArrStt; 2346 } 2347 } 2348 2349 // erst alle anzeigen, damit die Frames vorhanden sind. Mit deren 2350 // Position wird das BodyAnchor ermittelt. 2351 // Dafuer erst den ContentBereich, dann die Sonderbereiche!!! 2352 for (sal_uInt16 n = nArrStt; n < aTmpArr.Count(); ++n) 2353 { 2354 pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode(); 2355 ASSERT( pSectNd, "Wo ist mein SectionNode" ); 2356 pSectNd->GetSection().SetCondHidden( sal_False ); 2357 } 2358 for (sal_uInt16 n = 0; n < nArrStt; ++n) 2359 { 2360 pSectNd = rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode(); 2361 ASSERT( pSectNd, "Wo ist mein SectionNode" ); 2362 pSectNd->GetSection().SetCondHidden( sal_False ); 2363 } 2364 2365 // so, erst jetzt alle sortiert in die Liste eintragen 2366 for (sal_uInt16 n = 0; n < aTmpArr.Count(); ++n) 2367 { 2368 GetBodyNode( *rDoc.GetNodes()[ aTmpArr[ n ] ]->GetSectionNode() ); 2369 } 2370 } 2371 2372 String sTrue( String::CreateFromAscii( 2373 RTL_CONSTASCII_STRINGPARAM( "sal_True" ))), 2374 sFalse( String::CreateFromAscii( 2375 RTL_CONSTASCII_STRINGPARAM( "sal_False" ))); 2376 2377 sal_Bool bIsDBMgr = 0 != rDoc.GetNewDBMgr(); 2378 sal_uInt16 nWhich, n; 2379 const String* pFormel = 0; 2380 const SfxPoolItem* pItem; 2381 sal_uInt32 nMaxItems = rDoc.GetAttrPool().GetItemCount2( RES_TXTATR_FIELD ); 2382 for( n = 0; n < nMaxItems; ++n ) 2383 { 2384 if( 0 == (pItem = rDoc.GetAttrPool().GetItem2( RES_TXTATR_FIELD, n )) ) 2385 continue; 2386 2387 const SwFmtFld* pFmtFld = (SwFmtFld*)pItem; 2388 const SwTxtFld* pTxtFld = pFmtFld->GetTxtFld(); 2389 if( !pTxtFld || !pTxtFld->GetTxtNode().GetNodes().IsDocNodes() ) 2390 continue; 2391 2392 const SwField* pFld = pFmtFld->GetField(); 2393 switch( nWhich = pFld->GetTyp()->Which() ) 2394 { 2395 case RES_DBSETNUMBERFLD: 2396 case RES_GETEXPFLD: 2397 if( GETFLD_ALL == eGetMode ) 2398 pFormel = &sTrue; 2399 break; 2400 2401 case RES_DBFLD: 2402 if( GETFLD_EXPAND & eGetMode ) 2403 pFormel = &sTrue; 2404 break; 2405 2406 case RES_SETEXPFLD: 2407 /// fields of subtype <string> have also been add 2408 /// for calculation (eGetMode == GETFLD_CALC). 2409 /// Thus, add fields of subtype <string> in all modes 2410 /// (eGetMode == GETFLD_EXPAND||GETFLD_CALC||GETFLD_ALL) 2411 /// and fields of other subtypes only in the modes 2412 /// (eGetMode == GETFLD_CALC||GETFLD_ALL) 2413 /* "old" if construct - not deleted for history and code review 2414 if( ( nsSwGetSetExpType::GSE_STRING & pFld->GetSubType() 2415 ? GETFLD_EXPAND : GETFLD_CALC ) 2416 & eGetMode ) 2417 */ 2418 if ( !(eGetMode == GETFLD_EXPAND) || 2419 (nsSwGetSetExpType::GSE_STRING & pFld->GetSubType()) ) 2420 { 2421 pFormel = &sTrue; 2422 } 2423 break; 2424 2425 case RES_HIDDENPARAFLD: 2426 if( GETFLD_ALL == eGetMode ) 2427 { 2428 pFormel = &pFld->GetPar1(); 2429 if( !pFormel->Len() || pFormel->Equals( sFalse )) 2430 ((SwHiddenParaField*)pFld)->SetHidden( sal_False ); 2431 else if( pFormel->Equals( sTrue )) 2432 ((SwHiddenParaField*)pFld)->SetHidden( sal_True ); 2433 else 2434 break; 2435 2436 pFormel = 0; 2437 // Formatierung anstossen 2438 ((SwFmtFld*)pFmtFld)->ModifyNotification( 0, 0 ); 2439 } 2440 break; 2441 2442 case RES_HIDDENTXTFLD: 2443 if( GETFLD_ALL == eGetMode ) 2444 { 2445 pFormel = &pFld->GetPar1(); 2446 if( !pFormel->Len() || pFormel->Equals( sFalse )) 2447 ((SwHiddenTxtField*)pFld)->SetValue( sal_True ); 2448 else if( pFormel->Equals( sTrue )) 2449 ((SwHiddenTxtField*)pFld)->SetValue( sal_False ); 2450 else 2451 break; 2452 2453 pFormel = 0; 2454 2455 // Feld Evaluieren 2456 ((SwHiddenTxtField*)pFld)->Evaluate(&rDoc); 2457 // Formatierung anstossen 2458 ((SwFmtFld*)pFmtFld)->ModifyNotification( 0, 0 ); 2459 } 2460 break; 2461 2462 case RES_DBNUMSETFLD: 2463 { 2464 SwDBData aDBData(((SwDBNumSetField*)pFld)->GetDBData(&rDoc)); 2465 2466 if ( 2467 (bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) && 2468 (GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNumSetField*)pFld)->IsCondValid())) 2469 ) 2470 { 2471 pFormel = &pFld->GetPar1(); 2472 } 2473 } 2474 break; 2475 case RES_DBNEXTSETFLD: 2476 { 2477 SwDBData aDBData(((SwDBNextSetField*)pFld)->GetDBData(&rDoc)); 2478 2479 if ( 2480 (bIsDBMgr && rDoc.GetNewDBMgr()->OpenDataSource(aDBData.sDataSource, aDBData.sCommand)) && 2481 (GETFLD_ALL == eGetMode || (GETFLD_CALC & eGetMode && ((SwDBNextSetField*)pFld)->IsCondValid())) 2482 ) 2483 { 2484 pFormel = &pFld->GetPar1(); 2485 } 2486 } 2487 break; 2488 } 2489 2490 if( pFormel && pFormel->Len() ) 2491 { 2492 GetBodyNode( *pTxtFld, nWhich ); 2493 pFormel = 0; 2494 } 2495 } 2496 nFldLstGetMode = static_cast<sal_uInt8>( eGetMode ); 2497 nNodes = rDoc.GetNodes().Count(); 2498 2499 #ifdef JP_DEBUG 2500 { 2501 SvFileStream sOut( "f:\\x.x", STREAM_STD_WRITE ); 2502 sOut.Seek( STREAM_SEEK_TO_END ); 2503 sOut << "------------------" << endl; 2504 const _SetGetExpFldPtr* pSortLst = pFldSortLst->GetData(); 2505 for( sal_uInt16 n = pFldSortLst->Count(); n; --n, ++pSortLst ) 2506 { 2507 String sStr( (*pSortLst)->GetNode() ); 2508 sStr += "\t, "; 2509 sStr += (*pSortLst)->GetCntnt(); 2510 sStr += "\tNode: "; 2511 sStr += (*pSortLst)->GetFld()->GetTxtNode().StartOfSectionIndex(); 2512 sStr += "\tPos: "; 2513 sStr += *(*pSortLst)->GetFld()->GetStart(); 2514 sStr += "\tType: "; 2515 sStr += (*pSortLst)->GetFld()->GetFld().GetFld()->GetTyp()->Which(); 2516 2517 sOut << sStr.GetStr() << endl; 2518 } 2519 } 2520 #endif 2521 // JP_DEBUG 2522 } 2523 2524 /*-------------------------------------------------------------------- 2525 Beschreibung: 2526 --------------------------------------------------------------------*/ 2527 2528 void SwDocUpdtFld::GetBodyNode( const SwTxtFld& rTFld, sal_uInt16 nFldWhich ) 2529 { 2530 const SwTxtNode& rTxtNd = rTFld.GetTxtNode(); 2531 const SwDoc& rDoc = *rTxtNd.GetDoc(); 2532 2533 // immer den ersten !! (in Tab-Headline, Kopf-/Fuss ) 2534 Point aPt; 2535 const SwCntntFrm* pFrm = rTxtNd.getLayoutFrm( rDoc.GetCurrentLayout(), &aPt, 0, sal_False ); 2536 2537 _SetGetExpFld* pNew = NULL; 2538 sal_Bool bIsInBody = sal_False; 2539 2540 if( !pFrm || pFrm->IsInDocBody() ) 2541 { 2542 // einen Index fuers bestimmen vom TextNode anlegen 2543 SwNodeIndex aIdx( rTxtNd ); 2544 bIsInBody = rDoc.GetNodes().GetEndOfExtras().GetIndex() < aIdx.GetIndex(); 2545 2546 // #104291# dvo: We don't want to update fields in redlines, or those 2547 // in frames whose anchor is in redline. However, we do want to update 2548 // fields in hidden sections. So: In order to be updated, a field 1) 2549 // must have a frame, or 2) it must be in the document body. 2550 if( (pFrm != NULL) || bIsInBody ) 2551 pNew = new _SetGetExpFld( aIdx, &rTFld ); 2552 } 2553 else 2554 { 2555 // einen Index fuers bestimmen vom TextNode anlegen 2556 SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() ); 2557 #ifdef DBG_UTIL 2558 ASSERT( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" ); 2559 #else 2560 GetBodyTxtNode( rDoc, aPos, *pFrm ); 2561 #endif 2562 pNew = new _SetGetExpFld( aPos.nNode, &rTFld, &aPos.nContent ); 2563 } 2564 2565 // bei GetExp.-/DB.-Felder immer das BodyTxtFlag setzen 2566 if( RES_GETEXPFLD == nFldWhich ) 2567 { 2568 SwGetExpField* pGetFld = (SwGetExpField*)rTFld.GetFmtFld().GetField(); 2569 pGetFld->ChgBodyTxtFlag( bIsInBody ); 2570 } 2571 else if( RES_DBFLD == nFldWhich ) 2572 { 2573 SwDBField* pDBFld = (SwDBField*)rTFld.GetFmtFld().GetField(); 2574 pDBFld->ChgBodyTxtFlag( bIsInBody ); 2575 } 2576 2577 if( pNew != NULL ) 2578 if( !pFldSortLst->Insert( pNew )) 2579 delete pNew; 2580 } 2581 2582 void SwDocUpdtFld::GetBodyNode( const SwSectionNode& rSectNd ) 2583 { 2584 const SwDoc& rDoc = *rSectNd.GetDoc(); 2585 _SetGetExpFld* pNew = 0; 2586 2587 if( rSectNd.GetIndex() < rDoc.GetNodes().GetEndOfExtras().GetIndex() ) 2588 { 2589 do { // middle check loop 2590 2591 // dann muessen wir uns mal den Anker besorgen! 2592 // einen Index fuers bestimmen vom TextNode anlegen 2593 SwPosition aPos( rSectNd ); 2594 SwCntntNode* pCNd = rDoc.GetNodes().GoNext( &aPos.nNode ); // zum naechsten ContentNode 2595 2596 if( !pCNd || !pCNd->IsTxtNode() ) 2597 break; 2598 2599 // immer den ersten !! (in Tab-Headline, Kopf-/Fuss ) 2600 Point aPt; 2601 const SwCntntFrm* pFrm = pCNd->getLayoutFrm( rDoc.GetCurrentLayout(), &aPt, 0, sal_False ); 2602 if( !pFrm ) 2603 break; 2604 2605 #ifdef DBG_UTIL 2606 ASSERT( GetBodyTxtNode( rDoc, aPos, *pFrm ), "wo steht das Feld" ); 2607 #else 2608 GetBodyTxtNode( rDoc, aPos, *pFrm ); 2609 #endif 2610 pNew = new _SetGetExpFld( rSectNd, &aPos ); 2611 2612 } while( sal_False ); 2613 } 2614 2615 if( !pNew ) 2616 pNew = new _SetGetExpFld( rSectNd ); 2617 2618 if( !pFldSortLst->Insert( pNew )) 2619 delete pNew; 2620 } 2621 2622 void SwDocUpdtFld::InsertFldType( const SwFieldType& rType ) 2623 { 2624 String sFldName; 2625 switch( rType.Which() ) 2626 { 2627 case RES_USERFLD : 2628 sFldName = ((SwUserFieldType&)rType).GetName(); 2629 break; 2630 case RES_SETEXPFLD: 2631 sFldName = ((SwSetExpFieldType&)rType).GetName(); 2632 break; 2633 default: 2634 ASSERT( !this, "kein gueltiger FeldTyp" ); 2635 } 2636 2637 if( sFldName.Len() ) 2638 { 2639 SetFieldsDirty( sal_True ); 2640 // suchen und aus der HashTabelle entfernen 2641 GetAppCharClass().toLower( sFldName ); 2642 sal_uInt16 n; 2643 2644 SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n ); 2645 2646 if( !pFnd ) 2647 { 2648 SwCalcFldType* pNew = new SwCalcFldType( sFldName, &rType ); 2649 pNew->pNext = aFldTypeTable[ n ]; 2650 aFldTypeTable[ n ] = pNew; 2651 } 2652 } 2653 } 2654 2655 void SwDocUpdtFld::RemoveFldType( const SwFieldType& rType ) 2656 { 2657 String sFldName; 2658 switch( rType.Which() ) 2659 { 2660 case RES_USERFLD : 2661 sFldName = ((SwUserFieldType&)rType).GetName(); 2662 break; 2663 case RES_SETEXPFLD: 2664 sFldName = ((SwSetExpFieldType&)rType).GetName(); 2665 break; 2666 } 2667 2668 if( sFldName.Len() ) 2669 { 2670 SetFieldsDirty( sal_True ); 2671 // suchen und aus der HashTabelle entfernen 2672 GetAppCharClass().toLower( sFldName ); 2673 sal_uInt16 n; 2674 2675 SwHash* pFnd = Find( sFldName, GetFldTypeTable(), TBLSZ, &n ); 2676 if( pFnd ) 2677 { 2678 if( aFldTypeTable[ n ] == pFnd ) 2679 aFldTypeTable[ n ] = (SwCalcFldType*)pFnd->pNext; 2680 else 2681 { 2682 SwHash* pPrev = aFldTypeTable[ n ]; 2683 while( pPrev->pNext != pFnd ) 2684 pPrev = pPrev->pNext; 2685 pPrev->pNext = pFnd->pNext; 2686 } 2687 pFnd->pNext = 0; 2688 delete pFnd; 2689 } 2690 } 2691 } 2692 2693 SwDocUpdtFld::SwDocUpdtFld() 2694 : pFldSortLst(0), nFldUpdtPos(LONG_MAX), nFldLstGetMode(0) 2695 { 2696 bInUpdateFlds = bFldsDirty = sal_False; 2697 memset( aFldTypeTable, 0, sizeof( aFldTypeTable ) ); 2698 } 2699 2700 SwDocUpdtFld::~SwDocUpdtFld() 2701 { 2702 delete pFldSortLst; 2703 2704 for( sal_uInt16 n = 0; n < TBLSZ; ++n ) 2705 delete aFldTypeTable[n]; 2706 } 2707 2708 // #111840# 2709 bool SwDoc::UpdateFld(SwTxtFld * pDstTxtFld, SwField & rSrcFld, 2710 SwMsgPoolItem * pMsgHnt, 2711 bool bUpdateFlds) 2712 { 2713 ASSERT(pDstTxtFld, "no field to update!"); 2714 2715 sal_Bool bTblSelBreak = sal_False; 2716 2717 SwFmtFld * pDstFmtFld = (SwFmtFld*)&pDstTxtFld->GetFmtFld(); 2718 SwField * pDstFld = pDstFmtFld->GetField(); 2719 sal_uInt16 nFldWhich = rSrcFld.GetTyp()->Which(); 2720 SwNodeIndex aTblNdIdx(pDstTxtFld->GetTxtNode()); 2721 2722 if (pDstFld->GetTyp()->Which() == 2723 rSrcFld.GetTyp()->Which()) 2724 { 2725 if (GetIDocumentUndoRedo().DoesUndo()) 2726 { 2727 SwPosition aPosition( pDstTxtFld->GetTxtNode() ); 2728 aPosition.nContent = *pDstTxtFld->GetStart(); 2729 2730 SwUndo *const pUndo( new SwUndoFieldFromDoc( aPosition, *pDstFld, rSrcFld, pMsgHnt, bUpdateFlds) ); 2731 GetIDocumentUndoRedo().AppendUndo(pUndo); 2732 } 2733 2734 SwField * pNewFld = rSrcFld.CopyField(); 2735 pDstFmtFld->SetField(pNewFld); 2736 2737 switch( nFldWhich ) 2738 { 2739 case RES_SETEXPFLD: 2740 case RES_GETEXPFLD: 2741 case RES_HIDDENTXTFLD: 2742 case RES_HIDDENPARAFLD: 2743 UpdateExpFlds( pDstTxtFld, true ); 2744 break; 2745 2746 case RES_TABLEFLD: 2747 { 2748 const SwTableNode* pTblNd = 2749 IsIdxInTbl(aTblNdIdx); 2750 if( pTblNd ) 2751 { 2752 SwTableFmlUpdate aTblUpdate( &pTblNd-> 2753 GetTable() ); 2754 if (bUpdateFlds) 2755 UpdateTblFlds( &aTblUpdate ); 2756 else 2757 pNewFld->GetTyp()->ModifyNotification(0, &aTblUpdate); 2758 2759 if (! bUpdateFlds) 2760 bTblSelBreak = sal_True; 2761 } 2762 } 2763 break; 2764 2765 case RES_MACROFLD: 2766 if( bUpdateFlds && pDstTxtFld->GetpTxtNode() ) 2767 (pDstTxtFld->GetpTxtNode())-> 2768 ModifyNotification( 0, pDstFmtFld ); 2769 break; 2770 2771 case RES_DBNAMEFLD: 2772 case RES_DBNEXTSETFLD: 2773 case RES_DBNUMSETFLD: 2774 case RES_DBSETNUMBERFLD: 2775 ChgDBData(((SwDBNameInfField*) pNewFld)->GetRealDBData()); 2776 pNewFld->GetTyp()->UpdateFlds(); 2777 2778 break; 2779 2780 case RES_DBFLD: 2781 { 2782 // JP 10.02.96: ChgValue aufrufen, damit 2783 //die Format- aenderung den ContentString 2784 //richtig setzt 2785 SwDBField* pDBFld = (SwDBField*)pNewFld; 2786 if (pDBFld->IsInitialized()) 2787 pDBFld->ChgValue( pDBFld->GetValue(), sal_True ); 2788 2789 pDBFld->ClearInitialized(); 2790 pDBFld->InitContent(); 2791 } 2792 // kein break; 2793 2794 default: 2795 pDstFmtFld->ModifyNotification( 0, pMsgHnt ); 2796 } 2797 2798 // Die Felder die wir berechnen koennen werden hier expli. 2799 // zum Update angestossen. 2800 if( nFldWhich == RES_USERFLD ) 2801 UpdateUsrFlds(); 2802 } 2803 2804 return bTblSelBreak; 2805 } 2806 2807 bool SwDoc::PutValueToField(const SwPosition & rPos, 2808 const Any& rVal, sal_uInt16 nWhich) 2809 { 2810 Any aOldVal; 2811 SwField * pField = GetFieldAtPos(rPos); 2812 2813 2814 if (GetIDocumentUndoRedo().DoesUndo() && 2815 pField->QueryValue(aOldVal, nWhich)) 2816 { 2817 SwUndo *const pUndo(new SwUndoFieldFromAPI(rPos, aOldVal, rVal, nWhich)); 2818 GetIDocumentUndoRedo().AppendUndo(pUndo); 2819 } 2820 2821 return pField->PutValue(rVal, nWhich); 2822 } 2823