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