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