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 <float.h> 33 #include <hintids.hxx> 34 #include <hints.hxx> 35 #include <fmtfld.hxx> 36 #include <txtfld.hxx> 37 #include <frmfmt.hxx> 38 #include <layfrm.hxx> 39 #include <cntfrm.hxx> 40 #include <tabfrm.hxx> 41 #include <doc.hxx> 42 #include <docary.hxx> 43 #include <ndtxt.hxx> 44 #include <swtable.hxx> 45 #include <tblsel.hxx> 46 #include <cellfml.hxx> 47 #include <calc.hxx> 48 #include <expfld.hxx> 49 #include <usrfld.hxx> 50 #include <flddat.hxx> 51 #include <cellatr.hxx> 52 #include <ndindex.hxx> 53 54 const sal_Unicode cRelTrenner = ','; 55 const sal_Unicode cRelKennung = ''; // CTRL-R 56 57 const sal_uInt16 cMAXSTACKSIZE = 50; 58 59 const SwFrm* lcl_GetBoxFrm( const SwTableBox& rBox ); 60 long lcl_GetLongBoxNum( String& rStr ); 61 const SwTableBox* lcl_RelToBox( const SwTable&, const SwTableBox*, const String& ); 62 String lcl_BoxNmToRel( const SwTable&, const SwTableNode&, 63 const String& , const String& , sal_Bool ); 64 65 66 /************************************************************************* 67 |* 68 |* double SwTableBox::GetValue() const 69 |* gebe den Wert dieser Box zurueck. Der Wert ergibt sich aus dem 1. 70 |* TextNode. Beginnt dieser mit einer Zahl/Formel, so berechne diese; 71 |* oder mit einem Feld, dann hole den Wert. 72 |* Alle anderen Bedingungen returnen einen Fehler (oder 0 ?) 73 |* 74 |* Ersterstellung JP 30. Jun. 93 75 |* Letzte Aenderung JP 30. Jun. 93 76 |* 77 |*************************************************************************/ 78 79 double SwTableBox::GetValue( SwTblCalcPara& rCalcPara ) const 80 { 81 double nRet = 0; 82 83 if( rCalcPara.rCalc.IsCalcError() ) 84 return nRet; // schon ein Fehler in der Berechnung 85 86 rCalcPara.rCalc.SetCalcError( CALC_SYNTAX ); // default immer Fehler 87 88 // keine Content Box ? 89 if( !pSttNd ) 90 return nRet; 91 92 if( rCalcPara.IncStackCnt() ) 93 return nRet; 94 95 rCalcPara.SetLastTblBox( this ); 96 97 // wird eine Rekursion erzeugt ? 98 SwTableBox* pBox = (SwTableBox*)this; 99 if( rCalcPara.pBoxStk->Seek_Entry( pBox )) 100 return nRet; // steht schon auf dem Stack: FEHLER 101 102 // bei dieser Box nochmal aufsetzen 103 rCalcPara.SetLastTblBox( this ); 104 105 rCalcPara.pBoxStk->Insert( pBox ); // eintragen 106 do { // Middle-Check-Loop, damit aus dieser gesprungen werden kann 107 // hier aufgespannt, damit am Ende der Box-Pointer aus dem 108 // Stack ausgetragen wird 109 SwDoc* pDoc = GetFrmFmt()->GetDoc(); 110 111 const SfxPoolItem* pItem; 112 if( SFX_ITEM_SET == GetFrmFmt()->GetItemState( 113 RES_BOXATR_FORMULA, sal_False, &pItem ) ) 114 { 115 rCalcPara.rCalc.SetCalcError( CALC_NOERR ); // wieder zuruecksetzen 116 if( !((SwTblBoxFormula*)pItem)->IsValid() ) 117 { 118 // dann berechnen 119 const SwTable* pTmp = rCalcPara.pTbl; 120 rCalcPara.pTbl = &pBox->GetSttNd()->FindTableNode()->GetTable(); 121 ((SwTblBoxFormula*)pItem)->Calc( rCalcPara, nRet ); 122 123 if( !rCalcPara.IsStackOverFlow() ) 124 { 125 SwFrmFmt* pFmt = pBox->ClaimFrmFmt(); 126 SfxItemSet aTmp( pDoc->GetAttrPool(), 127 RES_BOXATR_BEGIN,RES_BOXATR_END-1 ); 128 aTmp.Put( SwTblBoxValue( nRet ) ); 129 if( SFX_ITEM_SET != pFmt->GetItemState( RES_BOXATR_FORMAT )) 130 aTmp.Put( SwTblBoxNumFormat( 0 )); 131 pFmt->SetFmtAttr( aTmp ); 132 } 133 rCalcPara.pTbl = pTmp; 134 } 135 else 136 nRet = GetFrmFmt()->GetTblBoxValue().GetValue(); 137 break; 138 } 139 else if( SFX_ITEM_SET == pBox->GetFrmFmt()->GetItemState( 140 RES_BOXATR_VALUE, sal_False, &pItem ) ) 141 { 142 rCalcPara.rCalc.SetCalcError( CALC_NOERR ); // wieder zuruecksetzen 143 nRet = ((SwTblBoxValue*)pItem)->GetValue(); 144 break; 145 } 146 147 SwTxtNode* pTxtNd = pDoc->GetNodes()[ pSttNd->GetIndex() + 1 ]->GetTxtNode(); 148 if( !pTxtNd ) 149 break; 150 151 xub_StrLen nSttPos = 0; 152 const String& rTxt = pTxtNd->GetTxt(); 153 while( nSttPos < rTxt.Len() && 154 ( ' ' == rTxt.GetChar( nSttPos ) || '\t' == rTxt.GetChar( nSttPos ) ) ) 155 ++nSttPos; 156 157 // beginnt an erster Position ein "RechenFeld", dann erfrage den Wert 158 // von diesem 159 sal_Unicode const Char = rTxt.GetChar(nSttPos); 160 if ( nSttPos < rTxt.Len() && 161 ( CH_TXTATR_BREAKWORD == Char || CH_TXTATR_INWORD == Char ) ) 162 { 163 SwIndex aIdx( pTxtNd, nSttPos ); 164 SwTxtFld * const pTxtFld = static_cast<SwTxtFld*>( 165 pTxtNd->GetTxtAttrForCharAt(aIdx.GetIndex(), RES_TXTATR_FIELD)); 166 if( !pTxtFld ) 167 break; 168 169 rCalcPara.rCalc.SetCalcError( CALC_NOERR ); // wieder zuruecksetzen 170 171 const SwField* pFld = pTxtFld->GetFld().GetFld(); 172 switch( pFld->GetTyp()->Which() ) 173 { 174 case RES_SETEXPFLD: 175 nRet = ((SwSetExpField*)pFld)->GetValue(); 176 break; 177 case RES_USERFLD: 178 nRet = ((SwUserFieldType*)pFld)->GetValue(); 179 break; 180 case RES_TABLEFLD: 181 { 182 SwTblField* pTblFld = (SwTblField*)pFld; 183 if( !pTblFld->IsValid() ) // ist der Wert gueltig ?? 184 { 185 // die richtige Tabelle mitgeben! 186 const SwTable* pTmp = rCalcPara.pTbl; 187 rCalcPara.pTbl = &pTxtNd->FindTableNode()->GetTable(); 188 pTblFld->CalcField( rCalcPara ); 189 rCalcPara.pTbl = pTmp; 190 } 191 nRet = pTblFld->GetValue(); 192 } 193 break; 194 195 case RES_DATETIMEFLD: 196 nRet = ((SwDateTimeField*)pFld)->GetValue(); 197 break; 198 199 case RES_JUMPEDITFLD: 200 //JP 14.09.98: Bug 56112 - der Platzhalter kann nie einen 201 // gueltigen Inhalt haben! 202 nRet = 0; 203 break; 204 205 default: 206 String const value(pFld->ExpandField(true)); 207 nRet = rCalcPara.rCalc.Calculate(value).GetDouble(); 208 } 209 } 210 else 211 { 212 // Ergebnis ist 0 und kein Fehler! 213 rCalcPara.rCalc.SetCalcError( CALC_NOERR ); // wieder zuruecksetzen 214 215 double aNum; 216 String sTxt( rTxt.Copy( nSttPos ) ); 217 sal_uInt32 nFmtIndex = GetFrmFmt()->GetTblBoxNumFmt().GetValue(); 218 219 SvNumberFormatter* pNumFmtr = pDoc->GetNumberFormatter(); 220 221 if( NUMBERFORMAT_TEXT == nFmtIndex ) 222 nFmtIndex = 0; 223 // JP 22.04.98: Bug 49659 - Sonderbehandlung fuer Prozent 224 else if( sTxt.Len() && 225 NUMBERFORMAT_PERCENT == pNumFmtr->GetType( nFmtIndex )) 226 { 227 sal_uInt32 nTmpFmt = 0; 228 if( pNumFmtr->IsNumberFormat( sTxt, nTmpFmt, aNum ) && 229 NUMBERFORMAT_NUMBER == pNumFmtr->GetType( nTmpFmt )) 230 sTxt += '%'; 231 } 232 233 if( pNumFmtr->IsNumberFormat( sTxt, nFmtIndex, aNum )) 234 nRet = aNum; 235 } 236 237 // ?? sonst ist das ein Fehler 238 } while( sal_False ); 239 240 if( !rCalcPara.IsStackOverFlow() ) 241 { 242 rCalcPara.pBoxStk->Remove( pBox ); // raus aus dem Stack 243 rCalcPara.DecStackCnt(); 244 } 245 246 //JP 12.01.99: mit Fehlererkennung, Bug 60794 247 if( DBL_MAX == nRet ) 248 rCalcPara.rCalc.SetCalcError( CALC_SYNTAX ); // Fehler setzen 249 250 return nRet; 251 } 252 253 /* */ 254 255 // Struktur, die zum TabelleRechnen benoetigt wird 256 257 SwTblCalcPara::SwTblCalcPara( SwCalc& rCalculator, const SwTable& rTable ) 258 : pLastTblBox( 0 ), nStackCnt( 0 ), nMaxSize( cMAXSTACKSIZE ), 259 rCalc( rCalculator ), pTbl( &rTable ) 260 { 261 pBoxStk = new SwTableSortBoxes; 262 } 263 264 SwTblCalcPara::~SwTblCalcPara() 265 { 266 delete pBoxStk; 267 } 268 269 sal_Bool SwTblCalcPara::CalcWithStackOverflow() 270 { 271 // falls ein StackUeberlauf erkannt wurde, sollte mit 272 // der letzten Box noch mal aufgesetzt werden. Irgend 273 // ein Weg sollte dann 274 sal_uInt16 nSaveMaxSize = nMaxSize; 275 276 nMaxSize = cMAXSTACKSIZE - 5; 277 sal_uInt16 nCnt = 0; 278 SwTableBoxes aStackOverFlows; 279 do { 280 SwTableBox* pBox = (SwTableBox*)pLastTblBox; 281 nStackCnt = 0; 282 rCalc.SetCalcError( CALC_NOERR ); 283 aStackOverFlows.C40_INSERT( SwTableBox, pBox, nCnt++ ); 284 285 pBoxStk->Remove( pBox ); 286 pBox->GetValue( *this ); 287 } while( IsStackOverFlow() ); 288 289 nMaxSize = cMAXSTACKSIZE - 3; // es muss mind. 1 Stufe tiefer gehen! 290 291 // falls Rekursionen erkannt wurden 292 nStackCnt = 0; 293 rCalc.SetCalcError( CALC_NOERR ); 294 pBoxStk->Remove( sal_uInt16(0), pBoxStk->Count() ); 295 296 while( !rCalc.IsCalcError() && nCnt ) 297 { 298 aStackOverFlows[ --nCnt ]->GetValue( *this ); 299 if( IsStackOverFlow() && !CalcWithStackOverflow() ) 300 break; 301 } 302 303 nMaxSize = nSaveMaxSize; 304 aStackOverFlows.Remove( 0, aStackOverFlows.Count() ); 305 return !rCalc.IsCalcError(); 306 } 307 308 /* */ 309 310 SwTableFormula::SwTableFormula( const String& rFormel ) 311 : sFormel( rFormel ) 312 { 313 eNmType = EXTRNL_NAME; 314 bValidValue = sal_False; 315 } 316 317 SwTableFormula::~SwTableFormula() 318 { 319 } 320 321 void SwTableFormula::_MakeFormel( const SwTable& rTbl, String& rNewStr, 322 String& rFirstBox, String* pLastBox, void* pPara ) const 323 { 324 SwTblCalcPara* pCalcPara = (SwTblCalcPara*)pPara; 325 if( pCalcPara->rCalc.IsCalcError() ) // ist schon Fehler gesetzt ? 326 return; 327 328 SwTableBox* pSttBox, *pEndBox = 0; 329 330 rFirstBox.Erase(0,1); // Kennung fuer Box loeschen 331 // ein Bereich in dieser Klammer ? 332 if( pLastBox ) 333 { 334 pEndBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->ToInt64())); 335 336 // ist das ueberhaupt ein gueltiger Pointer ?? 337 if( !rTbl.GetTabSortBoxes().Seek_Entry( pEndBox )) 338 pEndBox = 0; 339 rFirstBox.Erase( 0, pLastBox->Len()+1 ); 340 } 341 pSttBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(rFirstBox.ToInt64())); 342 // ist das ueberhaupt ein gueltiger Pointer ?? 343 if( !rTbl.GetTabSortBoxes().Seek_Entry( pSttBox )) 344 pSttBox = 0; 345 346 rNewStr += ' '; 347 if( pEndBox && pSttBox ) // Bereich ? 348 { 349 // hole ueber das Layout alle "selectierten" Boxen und berechne 350 // deren Werte 351 SwSelBoxes aBoxes; 352 GetBoxes( *pSttBox, *pEndBox, aBoxes ); 353 354 rNewStr += '('; 355 bool bDelim = false; 356 for( sal_uInt16 n = 0; n < aBoxes.Count() && 357 !pCalcPara->rCalc.IsCalcError(); ++n ) 358 { 359 const SwTableBox* pTblBox = aBoxes[n]; 360 if ( pTblBox->getRowSpan() >= 1 ) 361 { 362 if( bDelim ) 363 rNewStr += cListDelim; 364 bDelim = true; 365 rNewStr += pCalcPara->rCalc.GetStrResult( 366 pTblBox->GetValue( *pCalcPara ), sal_False ); 367 } 368 } 369 rNewStr += ')'; 370 } 371 else if( pSttBox && !pLastBox ) // nur die StartBox ? 372 { 373 //JP 12.01.99: und keine EndBox in der Formel! 374 // Berechne den Wert der Box 375 if ( pSttBox->getRowSpan() >= 1 ) 376 { 377 rNewStr += pCalcPara->rCalc.GetStrResult( 378 pSttBox->GetValue( *pCalcPara ), sal_False ); 379 } 380 } 381 else 382 pCalcPara->rCalc.SetCalcError( CALC_SYNTAX ); // Fehler setzen 383 rNewStr += ' '; 384 } 385 386 void SwTableFormula::RelNmsToBoxNms( const SwTable& rTbl, String& rNewStr, 387 String& rFirstBox, String* pLastBox, void* pPara ) const 388 { 389 // relativen Namen zu Box-Namen (externe Darstellung) 390 SwNode* pNd = (SwNode*)pPara; 391 ASSERT( pNd, "Feld steht in keinem TextNode" ); 392 const SwTableBox *pRelBox, *pBox = (SwTableBox *)rTbl.GetTblBox( 393 pNd->FindTableBoxStartNode()->GetIndex() ); 394 395 rNewStr += rFirstBox.Copy(0,1); // Kennung fuer Box erhalten 396 rFirstBox.Erase(0,1); 397 if( pLastBox ) 398 { 399 if( 0 != ( pRelBox = lcl_RelToBox( rTbl, pBox, *pLastBox )) ) 400 rNewStr += pRelBox->GetName(); 401 else 402 rNewStr.AppendAscii("A1"); 403 rNewStr += ':'; 404 rFirstBox.Erase( 0, pLastBox->Len()+1 ); 405 } 406 407 if( 0 != ( pRelBox = lcl_RelToBox( rTbl, pBox, rFirstBox )) ) 408 rNewStr += pRelBox->GetName(); 409 else 410 rNewStr.AppendAscii("A1"); 411 412 // Kennung fuer Box erhalten 413 rNewStr += rFirstBox.GetChar( rFirstBox.Len() - 1 ); 414 } 415 416 void SwTableFormula::RelBoxNmsToPtr( const SwTable& rTbl, String& rNewStr, 417 String& rFirstBox, String* pLastBox, void* pPara ) const 418 { 419 // relativen Namen zu Box-Pointern (interne Darstellung) 420 SwNode* pNd = (SwNode*)pPara; 421 ASSERT( pNd, "Feld steht in keinem Node" ); 422 const SwTableBox *pRelBox, *pBox = (SwTableBox*)rTbl.GetTblBox( 423 pNd->FindTableBoxStartNode()->GetIndex() ); 424 425 rNewStr += rFirstBox.Copy(0,1); // Kennung fuer Box erhalten 426 rFirstBox.Erase(0,1); 427 if( pLastBox ) 428 { 429 if( 0 != ( pRelBox = lcl_RelToBox( rTbl, pBox, *pLastBox )) ) 430 rNewStr += String::CreateFromInt64( (sal_PtrDiff)pRelBox ); 431 else 432 rNewStr += '0'; 433 rNewStr += ':'; 434 rFirstBox.Erase( 0, pLastBox->Len()+1 ); 435 } 436 437 if( 0 != ( pRelBox = lcl_RelToBox( rTbl, pBox, rFirstBox )) ) 438 rNewStr += String::CreateFromInt64( (sal_PtrDiff)pRelBox ); 439 else 440 rNewStr += '0'; 441 442 // Kennung fuer Box erhalten 443 rNewStr += rFirstBox.GetChar( rFirstBox.Len() - 1 ); 444 } 445 446 447 void SwTableFormula::BoxNmsToRelNm( const SwTable& rTbl, String& rNewStr, 448 String& rFirstBox, String* pLastBox, void* pPara ) const 449 { 450 // Box-Namen (externe Darstellung) zu relativen Namen 451 SwNode* pNd = (SwNode*)pPara; 452 ASSERT( pNd, "Feld steht in keinem Node" ); 453 const SwTableNode* pTblNd = pNd->FindTableNode(); 454 455 String sRefBoxNm; 456 if( &pTblNd->GetTable() == &rTbl ) 457 { 458 const SwTableBox *pBox = rTbl.GetTblBox( 459 pNd->FindTableBoxStartNode()->GetIndex() ); 460 ASSERT( pBox, "Feld steht in keiner Tabelle" ); 461 sRefBoxNm = pBox->GetName(); 462 } 463 464 rNewStr += rFirstBox.Copy(0,1); // Kennung fuer Box erhalten 465 rFirstBox.Erase(0,1); 466 if( pLastBox ) 467 { 468 rNewStr += lcl_BoxNmToRel( rTbl, *pTblNd, sRefBoxNm, *pLastBox, 469 eNmType == EXTRNL_NAME ); 470 rNewStr += ':'; 471 rFirstBox.Erase( 0, pLastBox->Len()+1 ); 472 } 473 474 rNewStr += lcl_BoxNmToRel( rTbl, *pTblNd, sRefBoxNm, rFirstBox, 475 eNmType == EXTRNL_NAME ); 476 477 // Kennung fuer Box erhalten 478 rNewStr += rFirstBox.GetChar( rFirstBox.Len() - 1 ); 479 } 480 481 482 void SwTableFormula::PtrToBoxNms( const SwTable& rTbl, String& rNewStr, 483 String& rFirstBox, String* pLastBox, void* ) const 484 { 485 // ein Bereich in dieser Klammer ? 486 SwTableBox* pBox; 487 488 rNewStr += rFirstBox.Copy(0,1); // Kennung fuer Box erhalten 489 rFirstBox.Erase(0,1); 490 if( pLastBox ) 491 { 492 pBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->ToInt64())); 493 494 // ist das ueberhaupt ein gueltiger Pointer ?? 495 if( rTbl.GetTabSortBoxes().Seek_Entry( pBox )) 496 rNewStr += pBox->GetName(); 497 else 498 rNewStr += '?'; 499 rNewStr += ':'; 500 rFirstBox.Erase( 0, pLastBox->Len()+1 ); 501 } 502 503 pBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(rFirstBox.ToInt64())); 504 // ist das ueberhaupt ein gueltiger Pointer ?? 505 if( rTbl.GetTabSortBoxes().Seek_Entry( pBox )) 506 rNewStr += pBox->GetName(); 507 else 508 rNewStr += '?'; 509 510 // Kennung fuer Box erhalten 511 rNewStr += rFirstBox.GetChar( rFirstBox.Len() - 1 ); 512 } 513 514 void SwTableFormula::BoxNmsToPtr( const SwTable& rTbl, String& rNewStr, 515 String& rFirstBox, String* pLastBox, void* ) const 516 { 517 // ein Bereich in dieser Klammer ? 518 const SwTableBox* pBox; 519 520 rNewStr += rFirstBox.Copy(0,1); // Kennung fuer Box erhalten 521 rFirstBox.Erase(0,1); 522 if( pLastBox ) 523 { 524 pBox = rTbl.GetTblBox( *pLastBox ); 525 rNewStr += String::CreateFromInt64( (sal_PtrDiff)pBox ); 526 rNewStr += ':'; 527 rFirstBox.Erase( 0, pLastBox->Len()+1 ); 528 } 529 530 pBox = rTbl.GetTblBox( rFirstBox ); 531 rNewStr += String::CreateFromInt64( (sal_PtrDiff)pBox ); 532 533 // Kennung fuer Box erhalten 534 rNewStr += rFirstBox.GetChar( rFirstBox.Len() - 1 ); 535 } 536 537 // erzeuge die externe (fuer UI) Formel 538 void SwTableFormula::PtrToBoxNm( const SwTable* pTbl ) 539 { 540 const SwNode* pNd = 0; 541 FnScanFormel fnFormel = 0; 542 switch( eNmType) 543 { 544 case INTRNL_NAME: 545 if( pTbl ) 546 fnFormel = &SwTableFormula::PtrToBoxNms; 547 break; 548 case REL_NAME: 549 if( pTbl ) 550 { 551 fnFormel = &SwTableFormula::RelNmsToBoxNms; 552 pNd = GetNodeOfFormula(); 553 } 554 break; 555 case EXTRNL_NAME: 556 return; 557 } 558 sFormel = ScanString( fnFormel, *pTbl, (void*)pNd ); 559 eNmType = EXTRNL_NAME; 560 } 561 562 // erzeuge die interne (in CORE) Formel 563 void SwTableFormula::BoxNmToPtr( const SwTable* pTbl ) 564 { 565 const SwNode* pNd = 0; 566 FnScanFormel fnFormel = 0; 567 switch( eNmType) 568 { 569 case EXTRNL_NAME: 570 if( pTbl ) 571 fnFormel = &SwTableFormula::BoxNmsToPtr; 572 break; 573 case REL_NAME: 574 if( pTbl ) 575 { 576 fnFormel = &SwTableFormula::RelBoxNmsToPtr; 577 pNd = GetNodeOfFormula(); 578 } 579 break; 580 case INTRNL_NAME: 581 return; 582 } 583 sFormel = ScanString( fnFormel, *pTbl, (void*)pNd ); 584 eNmType = INTRNL_NAME; 585 } 586 587 // erzeuge die relative (fuers Kopieren) Formel 588 void SwTableFormula::ToRelBoxNm( const SwTable* pTbl ) 589 { 590 const SwNode* pNd = 0; 591 FnScanFormel fnFormel = 0; 592 switch( eNmType) 593 { 594 case INTRNL_NAME: 595 case EXTRNL_NAME: 596 if( pTbl ) 597 { 598 fnFormel = &SwTableFormula::BoxNmsToRelNm; 599 pNd = GetNodeOfFormula(); 600 } 601 break; 602 case REL_NAME: 603 return; 604 } 605 sFormel = ScanString( fnFormel, *pTbl, (void*)pNd ); 606 eNmType = REL_NAME; 607 } 608 609 610 String SwTableFormula::ScanString( FnScanFormel fnFormel, const SwTable& rTbl, 611 void* pPara ) const 612 { 613 String aStr; 614 sal_uInt16 nFml = 0, nStt = 0, nEnd = 0, nTrenner; 615 616 do { 617 // falls der Formel ein Name vorangestellt ist, diese Tabelle 618 // benutzen !! 619 const SwTable* pTbl = &rTbl; 620 621 nStt = sFormel.Search( '<', nFml ); 622 if( STRING_NOTFOUND != nStt ) 623 { 624 while( STRING_NOTFOUND != nStt && 625 ( ' ' == sFormel.GetChar( nStt + 1 ) || 626 '=' == sFormel.GetChar( nStt + 1 ) ) ) 627 nStt = sFormel.Search( '<', nStt + 1 ); 628 629 if( STRING_NOTFOUND != nStt ) 630 nEnd = sFormel.Search( '>', nStt+1 ); 631 } 632 if( STRING_NOTFOUND == nStt || STRING_NOTFOUND == nEnd ) 633 { 634 // den Rest setzen und beenden 635 aStr.Insert( sFormel, nFml, sFormel.Len() - nFml ); 636 break; 637 } 638 aStr.Insert( sFormel, nFml, nStt - nFml ); // Anfang schreiben 639 640 if( fnFormel != NULL ) 641 { 642 // ist ein TabellenName vorangestellt ?? 643 // JP 16.02.99: SplitMergeBoxNm behandeln den Namen selbst 644 // JP 22.02.99: der CAST muss fuer den Linux-Compiler sein 645 // JP 28.06.99: rel. BoxName have no preceding tablename! 646 if( fnFormel != (FnScanFormel)&SwTableFormula::_SplitMergeBoxNm && 647 1 < sFormel.Len() && cRelKennung != sFormel.GetChar( 1 ) && 648 STRING_NOTFOUND != ( nTrenner = sFormel.Search( '.', nStt )) 649 && nTrenner < nEnd ) 650 { 651 String sTblNm( sFormel.Copy( nStt, nEnd - nStt )); 652 653 // falls im Namen schon die Punkte enthalten sind, 654 // treten diese immer paarig auf!!! (A1.1.1 !!) 655 if( (sTblNm.GetTokenCount( '.' ) - 1 ) & 1 ) 656 { 657 sTblNm.Erase( nTrenner - nStt ); 658 659 // beim Bauen der Formel ist der TabellenName unerwuenscht 660 //JP 22.02.99: der CAST muss fuer den Linux-Compiler sein 661 if( fnFormel != (FnScanFormel)&SwTableFormula::_MakeFormel ) 662 aStr += sTblNm; 663 nStt = nTrenner; 664 665 sTblNm.Erase( 0, 1 ); // Trenner loeschen 666 if( sTblNm != rTbl.GetFrmFmt()->GetName() ) 667 { 668 // dann suchen wir uns mal unsere Tabelle: 669 const SwTable* pFnd = FindTable( 670 *rTbl.GetFrmFmt()->GetDoc(), 671 sTblNm ); 672 if( pFnd ) 673 pTbl = pFnd; 674 // ?? 675 ASSERT( pFnd, "Tabelle nicht gefunden, was nun?" ); 676 } 677 } 678 } 679 680 String sBox( sFormel.Copy( nStt, nEnd - nStt + 1 )); 681 // ein Bereich in dieser Klammer ? 682 if( STRING_NOTFOUND != ( nTrenner = sFormel.Search( ':', nStt )) 683 && nTrenner < nEnd ) 684 { 685 // ohne die Anfangsklammer 686 String aFirstBox( sFormel.Copy( nStt+1, nTrenner - nStt - 1 )); 687 (this->*fnFormel)( *pTbl, aStr, sBox, &aFirstBox, pPara ); 688 } 689 else 690 (this->*fnFormel)( *pTbl, aStr, sBox, 0, pPara ); 691 } 692 693 nFml = nEnd+1; 694 } while( sal_True ); 695 return aStr; 696 } 697 698 const SwTable* SwTableFormula::FindTable( SwDoc& rDoc, const String& rNm ) const 699 { 700 const SwFrmFmts& rTblFmts = *rDoc.GetTblFrmFmts(); 701 const SwTable* pTmpTbl, *pRet = 0; 702 for( sal_uInt16 nFmtCnt = rTblFmts.Count(); nFmtCnt; ) 703 { 704 SwFrmFmt* pFmt = rTblFmts[ --nFmtCnt ]; 705 // falls wir von Sw3Writer gerufen werden, dann ist dem 706 // FormatNamen eine Nummer anhaengig 707 SwTableBox* pFBox; 708 if( COMPARE_EQUAL == rNm.CompareTo( pFmt->GetName(), 709 pFmt->GetName().Search( 0x0a ) ) && 710 0 != ( pTmpTbl = SwTable::FindTable( pFmt ) ) && 711 0 != (pFBox = pTmpTbl->GetTabSortBoxes()[0] ) && 712 pFBox->GetSttNd() && 713 pFBox->GetSttNd()->GetNodes().IsDocNodes() ) 714 { 715 // eine Tabelle im normalen NodesArr 716 pRet = pTmpTbl; 717 break; 718 } 719 } 720 return pRet; 721 } 722 723 const SwFrm* lcl_GetBoxFrm( const SwTableBox& rBox ) 724 { 725 SwNodeIndex aIdx( *rBox.GetSttNd() ); 726 SwCntntNode* pCNd = aIdx.GetNodes().GoNext( &aIdx ); 727 ASSERT( pCNd, "Box hat keinen TextNode" ); 728 Point aPt; // den im Layout 1. Frame returnen - Tab.Kopfzeile !! 729 return pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aPt, NULL, sal_False ); 730 } 731 732 long lcl_GetLongBoxNum( String& rStr ) 733 { 734 sal_uInt16 nPos; 735 long nRet; 736 if( STRING_NOTFOUND == ( nPos = rStr.Search( cRelTrenner ) )) 737 { 738 nRet = rStr.ToInt32(); 739 rStr.Erase(); 740 } 741 else 742 { 743 nRet = rStr.Copy( 0, nPos ).ToInt32(); 744 rStr.Erase( 0, nPos+1 ); 745 } 746 return nRet; 747 } 748 749 const SwTableBox* lcl_RelToBox( const SwTable& rTbl, 750 const SwTableBox* pRefBox, 751 const String& rGetName ) 752 { 753 // hole die Line 754 const SwTableBox* pBox = 0; 755 String sGetName( rGetName ); 756 757 // ist es denn wirklich eine relative Angabe?? 758 if( cRelKennung == sGetName.GetChar(0) ) // ja, ... 759 { 760 if( !pRefBox ) 761 return 0; 762 763 sGetName.Erase( 0, 1 ); 764 765 const SwTableLines* pLines = (SwTableLines*)&rTbl.GetTabLines(); 766 const SwTableBoxes* pBoxes; 767 const SwTableLine* pLine; 768 769 // bestimme erst mal die Start-Werte der Box: 770 pBox = (SwTableBox*)pRefBox; 771 pLine = pBox->GetUpper(); 772 while( pLine->GetUpper() ) 773 { 774 pBox = pLine->GetUpper(); 775 pLine = pBox->GetUpper(); 776 } 777 sal_uInt16 nSttBox = pLine->GetTabBoxes().GetPos( pBox ); 778 sal_uInt16 nSttLine = rTbl.GetTabLines().GetPos( pLine ); 779 780 long nBoxOffset = lcl_GetLongBoxNum( sGetName ) + nSttBox; 781 long nLineOffset = lcl_GetLongBoxNum( sGetName ) + nSttLine; 782 783 if( nBoxOffset < 0 || nBoxOffset >= USHRT_MAX || 784 nLineOffset < 0 || nLineOffset >= USHRT_MAX ) 785 return 0; 786 787 if( nLineOffset >= long(pLines->Count()) ) 788 return 0; 789 790 pLine = (*pLines)[ sal_uInt16(nLineOffset) ]; 791 792 // dann suche die Box 793 pBoxes = &pLine->GetTabBoxes(); 794 if( nBoxOffset >= long(pBoxes->Count()) ) 795 return 0; 796 pBox = (*pBoxes)[ sal_uInt16(nBoxOffset) ]; 797 798 while( sGetName.Len() ) 799 { 800 nSttBox = SwTable::_GetBoxNum( sGetName ); 801 pLines = &pBox->GetTabLines(); 802 if( nSttBox ) 803 --nSttBox; 804 805 nSttLine = SwTable::_GetBoxNum( sGetName ); 806 807 // bestimme die Line 808 if( !nSttLine || nSttLine > pLines->Count() ) 809 break; 810 pLine = (*pLines)[ nSttLine-1 ]; 811 812 // bestimme die Box 813 pBoxes = &pLine->GetTabBoxes(); 814 if( nSttBox >= pBoxes->Count() ) 815 break; 816 pBox = (*pBoxes)[ nSttBox ]; 817 } 818 819 if( pBox ) 820 { 821 if( !pBox->GetSttNd() ) 822 // "herunterfallen lassen" bis zur ersten Box 823 while( pBox->GetTabLines().Count() ) 824 pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0]; 825 } 826 } 827 else 828 { 829 // sonst ist es eine absolute externe Darstellung: 830 pBox = rTbl.GetTblBox( sGetName ); 831 } 832 return pBox; 833 } 834 835 String lcl_BoxNmToRel( const SwTable& rTbl, const SwTableNode& rTblNd, 836 const String& rRefBoxNm, const String& rGetStr, 837 sal_Bool bExtrnlNm ) 838 { 839 String sCpy( rRefBoxNm ); 840 String sTmp( rGetStr ); 841 if( !bExtrnlNm ) 842 { 843 // in die Externe Darstellung umwandeln. 844 SwTableBox* pBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(sTmp.ToInt64())); 845 if( !rTbl.GetTabSortBoxes().Seek_Entry( pBox )) 846 return '?'; 847 sTmp = pBox->GetName(); 848 } 849 850 // sollte die es eine Tabellen uebergreifende Formel sein, dann behalte 851 // die externe Darstellung bei: 852 if( &rTbl == &rTblNd.GetTable() ) 853 { 854 long nBox = SwTable::_GetBoxNum( sTmp, sal_True ); 855 nBox -= SwTable::_GetBoxNum( sCpy, sal_True ); 856 long nLine = SwTable::_GetBoxNum( sTmp ); 857 nLine -= SwTable::_GetBoxNum( sCpy ); 858 859 sCpy = sTmp; //JP 01.11.95: den Rest aus dem BoxNamen anhaengen 860 861 sTmp = cRelKennung; 862 sTmp += String::CreateFromInt32( nBox ); 863 sTmp += cRelTrenner; 864 sTmp += String::CreateFromInt32( nLine ); 865 866 if( sCpy.Len() ) 867 { 868 sTmp += cRelTrenner; 869 sTmp += sCpy; 870 } 871 } 872 873 if( sTmp.Len() && '>' == sTmp.GetChar( sTmp.Len() - 1 )) 874 sTmp.Erase( sTmp.Len()-1 ); 875 876 return sTmp; 877 } 878 879 sal_uInt16 SwTableFormula::GetBoxesOfFormula( const SwTable& rTbl, 880 SwSelBoxes& rBoxes ) 881 { 882 if( rBoxes.Count() ) 883 rBoxes.Remove( sal_uInt16(0), rBoxes.Count() ); 884 885 BoxNmToPtr( &rTbl ); 886 ScanString( &SwTableFormula::_GetFmlBoxes, rTbl, &rBoxes ); 887 return rBoxes.Count(); 888 } 889 890 void SwTableFormula::_GetFmlBoxes( const SwTable& rTbl, String& , 891 String& rFirstBox, String* pLastBox, void* pPara ) const 892 { 893 SwSelBoxes* pBoxes = (SwSelBoxes*)pPara; 894 SwTableBox* pSttBox, *pEndBox = 0; 895 896 rFirstBox.Erase(0,1); // Kennung fuer Box loeschen 897 // ein Bereich in dieser Klammer ? 898 if( pLastBox ) 899 { 900 pEndBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->ToInt64())); 901 902 // ist das ueberhaupt ein gueltiger Pointer ?? 903 if( !rTbl.GetTabSortBoxes().Seek_Entry( pEndBox )) 904 pEndBox = 0; 905 rFirstBox.Erase( 0, pLastBox->Len()+1 ); 906 } 907 908 pSttBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(rFirstBox.ToInt64())); 909 // ist das ueberhaupt ein gueltiger Pointer ?? 910 if( !rTbl.GetTabSortBoxes().Seek_Entry( pSttBox )) 911 pSttBox = 0; 912 913 if( pEndBox && pSttBox ) // Bereich ? 914 { 915 // ueber das Layout alle "selectierten" Boxen und berechne 916 // deren Werte 917 SwSelBoxes aBoxes; 918 GetBoxes( *pSttBox, *pEndBox, aBoxes ); 919 pBoxes->Insert( &aBoxes ); 920 } 921 else if( pSttBox ) // nur die StartBox ? 922 pBoxes->Insert( pSttBox ); 923 } 924 925 void SwTableFormula::GetBoxes( const SwTableBox& rSttBox, 926 const SwTableBox& rEndBox, 927 SwSelBoxes& rBoxes ) const 928 { 929 // hole ueber das Layout alle "selektierten" Boxen 930 const SwLayoutFrm *pStt, *pEnd; 931 const SwFrm* pFrm = lcl_GetBoxFrm( rSttBox ); 932 pStt = pFrm ? pFrm->GetUpper() : 0; 933 pEnd = ( 0 != (pFrm = lcl_GetBoxFrm( rEndBox ))) ? pFrm->GetUpper() : 0; 934 if( !pStt || !pEnd ) 935 return ; // no valid selection 936 937 GetTblSel( pStt, pEnd, rBoxes, 0 ); 938 939 const SwTable* pTbl = pStt->FindTabFrm()->GetTable(); 940 941 // filter die Kopfzeilen-Boxen heraus: 942 if( pTbl->GetRowsToRepeat() > 0 ) 943 { 944 do { // middle-check loop 945 const SwTableLine* pLine = rSttBox.GetUpper(); 946 while( pLine->GetUpper() ) 947 pLine = pLine->GetUpper()->GetUpper(); 948 949 if( pTbl->IsHeadline( *pLine ) ) 950 break; // Headline mit im Bereich ! 951 952 // vielleicht ist ja Start und Ende vertauscht 953 pLine = rEndBox.GetUpper(); 954 while ( pLine->GetUpper() ) 955 pLine = pLine->GetUpper()->GetUpper(); 956 957 if( pTbl->IsHeadline( *pLine ) ) 958 break; // Headline mit im Bereich ! 959 960 const SwTabFrm *pTable = pStt->FindTabFrm(); 961 const SwTabFrm *pEndTable = pEnd->FindTabFrm(); 962 963 if( pTable == pEndTable ) // keine gespl. Tabelle 964 break; 965 966 // dann mal die Tabellenkoepfe raus: 967 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 968 { 969 pLine = rBoxes[n]->GetUpper(); 970 while( pLine->GetUpper() ) 971 pLine = pLine->GetUpper()->GetUpper(); 972 973 if( pTbl->IsHeadline( *pLine ) ) 974 rBoxes.Remove( n--, 1 ); 975 } 976 } while( sal_False ); 977 } 978 } 979 980 // sind alle Boxen gueltig, auf die sich die Formel bezieht? 981 void SwTableFormula::_HasValidBoxes( const SwTable& rTbl, String& , 982 String& rFirstBox, String* pLastBox, void* pPara ) const 983 { 984 sal_Bool* pBValid = (sal_Bool*)pPara; 985 if( *pBValid ) // einmal falsch, immer falsch 986 { 987 SwTableBox* pSttBox = 0, *pEndBox = 0; 988 rFirstBox.Erase(0,1); // Kennung fuer Box loeschen 989 990 // ein Bereich in dieser Klammer ? 991 if( pLastBox ) 992 rFirstBox.Erase( 0, pLastBox->Len()+1 ); 993 994 switch( eNmType) 995 { 996 case INTRNL_NAME: 997 if( pLastBox ) 998 pEndBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->ToInt64())); 999 pSttBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(rFirstBox.ToInt64())); 1000 break; 1001 1002 case REL_NAME: 1003 { 1004 const SwNode* pNd = GetNodeOfFormula(); 1005 const SwTableBox* pBox = !pNd ? 0 1006 : (SwTableBox *)rTbl.GetTblBox( 1007 pNd->FindTableBoxStartNode()->GetIndex() ); 1008 if( pLastBox ) 1009 pEndBox = (SwTableBox*)lcl_RelToBox( rTbl, pBox, *pLastBox ); 1010 pSttBox = (SwTableBox*)lcl_RelToBox( rTbl, pBox, rFirstBox ); 1011 } 1012 break; 1013 1014 case EXTRNL_NAME: 1015 if( pLastBox ) 1016 pEndBox = (SwTableBox*)rTbl.GetTblBox( *pLastBox ); 1017 pSttBox = (SwTableBox*)rTbl.GetTblBox( rFirstBox ); 1018 break; 1019 } 1020 1021 // sind das gueltige Pointer ? 1022 if( ( pLastBox && 1023 ( !pEndBox || !rTbl.GetTabSortBoxes().Seek_Entry( pEndBox ) ) ) || 1024 ( !pSttBox || !rTbl.GetTabSortBoxes().Seek_Entry( pSttBox ) ) ) 1025 *pBValid = sal_False; 1026 } 1027 } 1028 1029 sal_Bool SwTableFormula::HasValidBoxes() const 1030 { 1031 sal_Bool bRet = sal_True; 1032 const SwNode* pNd = GetNodeOfFormula(); 1033 if( pNd && 0 != ( pNd = pNd->FindTableNode() ) ) 1034 ScanString( &SwTableFormula::_HasValidBoxes, 1035 ((SwTableNode*)pNd)->GetTable(), &bRet ); 1036 return bRet; 1037 } 1038 1039 1040 sal_uInt16 SwTableFormula::GetLnPosInTbl( const SwTable& rTbl, const SwTableBox* pBox ) 1041 { 1042 sal_uInt16 nRet = USHRT_MAX; 1043 if( pBox ) 1044 { 1045 const SwTableLine* pLn = pBox->GetUpper(); 1046 while( pLn->GetUpper() ) 1047 pLn = pLn->GetUpper()->GetUpper(); 1048 nRet = rTbl.GetTabLines().GetPos( pLn ); 1049 } 1050 return nRet; 1051 } 1052 1053 void SwTableFormula::_SplitMergeBoxNm( const SwTable& rTbl, String& rNewStr, 1054 String& rFirstBox, String* pLastBox, void* pPara ) const 1055 { 1056 SwTableFmlUpdate& rTblUpd = *(SwTableFmlUpdate*)pPara; 1057 1058 rNewStr += rFirstBox.Copy(0,1); // Kennung fuer Box erhalten 1059 rFirstBox.Erase(0,1); 1060 1061 String sTblNm; 1062 const SwTable* pTbl = &rTbl; 1063 1064 String* pTblNmBox = pLastBox ? pLastBox : &rFirstBox; 1065 1066 sal_uInt16 nLastBoxLen = pTblNmBox->Len(); 1067 sal_uInt16 nTrenner = pTblNmBox->Search( '.' ); 1068 if( STRING_NOTFOUND != nTrenner && 1069 // falls im Namen schon die Punkte enthalten sind, 1070 // treten diese immer paarig auf!!! (A1.1.1 !!) 1071 (pTblNmBox->GetTokenCount( '.' ) - 1 ) & 1 ) 1072 { 1073 sTblNm = pTblNmBox->Copy( 0, nTrenner ); 1074 pTblNmBox->Erase( 0, nTrenner + 1);// den Punkt entfernen 1075 const SwTable* pFnd = FindTable( *rTbl.GetFrmFmt()->GetDoc(), sTblNm ); 1076 if( pFnd ) 1077 pTbl = pFnd; 1078 1079 if( TBL_MERGETBL == rTblUpd.eFlags ) 1080 { 1081 if( pFnd ) 1082 { 1083 if( pFnd == rTblUpd.DATA.pDelTbl ) 1084 { 1085 if( rTblUpd.pTbl != &rTbl ) // es ist nicht die akt. 1086 (rNewStr += rTblUpd.pTbl->GetFrmFmt()->GetName() ) 1087 += '.'; // den neuen Tabellen Namen setzen 1088 rTblUpd.bModified = sal_True; 1089 } 1090 else if( pFnd != rTblUpd.pTbl || 1091 ( rTblUpd.pTbl != &rTbl && &rTbl != rTblUpd.DATA.pDelTbl)) 1092 (rNewStr += sTblNm ) += '.'; // den Tabellen Namen behalten 1093 else 1094 rTblUpd.bModified = sal_True; 1095 } 1096 else 1097 (rNewStr += sTblNm ) += '.'; // den Tabellen Namen behalten 1098 1099 } 1100 } 1101 if( pTblNmBox == pLastBox ) 1102 rFirstBox.Erase( 0, nLastBoxLen + 1 ); 1103 1104 SwTableBox* pSttBox = 0, *pEndBox = 0; 1105 switch( eNmType ) 1106 { 1107 case INTRNL_NAME: 1108 if( pLastBox ) 1109 pEndBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(pLastBox->ToInt64())); 1110 pSttBox = reinterpret_cast<SwTableBox*>(sal::static_int_cast<sal_IntPtr>(rFirstBox.ToInt64())); 1111 break; 1112 1113 case REL_NAME: 1114 { 1115 const SwNode* pNd = GetNodeOfFormula(); 1116 const SwTableBox* pBox = pNd ? pTbl->GetTblBox( 1117 pNd->FindTableBoxStartNode()->GetIndex() ) : 0; 1118 if( pLastBox ) 1119 pEndBox = (SwTableBox*)lcl_RelToBox( *pTbl, pBox, *pLastBox ); 1120 pSttBox = (SwTableBox*)lcl_RelToBox( *pTbl, pBox, rFirstBox ); 1121 } 1122 break; 1123 1124 case EXTRNL_NAME: 1125 if( pLastBox ) 1126 pEndBox = (SwTableBox*)pTbl->GetTblBox( *pLastBox ); 1127 pSttBox = (SwTableBox*)pTbl->GetTblBox( rFirstBox ); 1128 break; 1129 } 1130 1131 if( pLastBox && !pTbl->GetTabSortBoxes().Seek_Entry( pEndBox )) 1132 pEndBox = 0; 1133 if( !pTbl->GetTabSortBoxes().Seek_Entry( pSttBox )) 1134 pSttBox = 0; 1135 1136 if( TBL_SPLITTBL == rTblUpd.eFlags ) 1137 { 1138 // wo liegen die Boxen, in der "alten" oder in der neuen Tabelle? 1139 sal_Bool bInNewTbl = sal_False; 1140 if( pLastBox ) 1141 { 1142 // das ist die "erste" Box in der Selektion. Die bestimmt ob die 1143 // Formel in der alten oder neuen Tabelle steht. 1144 sal_uInt16 nEndLnPos = SwTableFormula::GetLnPosInTbl( *pTbl, pEndBox ), 1145 nSttLnPos = SwTableFormula::GetLnPosInTbl( *pTbl, pSttBox ); 1146 1147 if( USHRT_MAX != nSttLnPos && USHRT_MAX != nEndLnPos && 1148 ((rTblUpd.nSplitLine <= nSttLnPos) == 1149 (rTblUpd.nSplitLine <= nEndLnPos)) ) 1150 { 1151 // bleiben in der gleichen Tabelle 1152 bInNewTbl = rTblUpd.nSplitLine <= nEndLnPos && 1153 pTbl == rTblUpd.pTbl; 1154 } 1155 else 1156 { 1157 // das ist aufjedenfall eine ungueltige Formel, also fuers 1158 // Undo auf Modified setzen 1159 rTblUpd.bModified = sal_True; 1160 if( pEndBox ) 1161 bInNewTbl = USHRT_MAX != nEndLnPos && 1162 rTblUpd.nSplitLine <= nEndLnPos && 1163 pTbl == rTblUpd.pTbl; 1164 } 1165 } 1166 else 1167 { 1168 sal_uInt16 nSttLnPos = SwTableFormula::GetLnPosInTbl( *pTbl, pSttBox ); 1169 // dann landet das Teil in der neuen Tabelle? 1170 bInNewTbl = USHRT_MAX != nSttLnPos && 1171 rTblUpd.nSplitLine <= nSttLnPos && 1172 pTbl == rTblUpd.pTbl; 1173 } 1174 1175 // wenn die Formel selbst in der neuen Tabellen landet 1176 if( rTblUpd.bBehindSplitLine ) 1177 { 1178 if( !bInNewTbl ) 1179 { 1180 rTblUpd.bModified = sal_True; 1181 ( rNewStr += rTblUpd.pTbl->GetFrmFmt()->GetName() ) += '.'; 1182 } 1183 else if( sTblNm.Len() ) 1184 ( rNewStr += sTblNm ) += '.'; 1185 } 1186 else if( bInNewTbl ) 1187 { 1188 rTblUpd.bModified = sal_True; 1189 ( rNewStr += *rTblUpd.DATA.pNewTblNm ) += '.'; 1190 } 1191 else if( sTblNm.Len() ) 1192 ( rNewStr += sTblNm ) += '.'; 1193 } 1194 1195 if( pLastBox ) 1196 ( rNewStr += String::CreateFromInt64((sal_PtrDiff)pEndBox)) += ':'; 1197 ( rNewStr += String::CreateFromInt64((sal_PtrDiff)pSttBox)) 1198 += rFirstBox.GetChar( rFirstBox.Len() - 1 ); 1199 } 1200 1201 // erzeuge die externe Formel, beachte aber das die Formel 1202 // in einer gesplitteten/gemergten Tabelle landet 1203 void SwTableFormula::ToSplitMergeBoxNm( SwTableFmlUpdate& rTblUpd ) 1204 { 1205 const SwTable* pTbl; 1206 const SwNode* pNd = GetNodeOfFormula(); 1207 if( pNd && 0 != ( pNd = pNd->FindTableNode() )) 1208 pTbl = &((SwTableNode*)pNd)->GetTable(); 1209 else 1210 pTbl = rTblUpd.pTbl; 1211 1212 sFormel = ScanString( &SwTableFormula::_SplitMergeBoxNm, *pTbl, (void*)&rTblUpd ); 1213 eNmType = INTRNL_NAME; 1214 } 1215 1216 1217