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
GetValue(SwTblCalcPara & rCalcPara) const75 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
SwTblCalcPara(SwCalc & rCalculator,const SwTable & rTable)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
~SwTblCalcPara()268 SwTblCalcPara::~SwTblCalcPara()
269 {
270 delete pBoxStk;
271 }
272
CalcWithStackOverflow()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
SwTableFormula(const String & rFormel)314 SwTableFormula::SwTableFormula( const String& rFormel )
315 : sFormel( rFormel )
316 {
317 eNmType = EXTRNL_NAME;
318 bValidValue = sal_False;
319 }
320
~SwTableFormula()321 SwTableFormula::~SwTableFormula()
322 {
323 }
324
_MakeFormel(const SwTable & rTbl,String & rNewStr,String & rFirstBox,String * pLastBox,void * pPara) const325 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
RelNmsToBoxNms(const SwTable & rTbl,String & rNewStr,String & rFirstBox,String * pLastBox,void * pPara) const390 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
RelBoxNmsToPtr(const SwTable & rTbl,String & rNewStr,String & rFirstBox,String * pLastBox,void * pPara) const420 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
BoxNmsToRelNm(const SwTable & rTbl,String & rNewStr,String & rFirstBox,String * pLastBox,void * pPara) const451 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
PtrToBoxNms(const SwTable & rTbl,String & rNewStr,String & rFirstBox,String * pLastBox,void *) const486 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
BoxNmsToPtr(const SwTable & rTbl,String & rNewStr,String & rFirstBox,String * pLastBox,void *) const518 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
PtrToBoxNm(const SwTable * pTbl)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
BoxNmToPtr(const SwTable * pTbl)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
ToRelBoxNm(const SwTable * pTbl)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
ScanString(FnScanFormel fnFormel,const SwTable & rTbl,void * pPara) const614 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
FindTable(SwDoc & rDoc,const String & rNm) const702 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
lcl_GetBoxFrm(const SwTableBox & rBox)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
lcl_GetLongBoxNum(String & rStr)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
lcl_RelToBox(const SwTable & rTbl,const SwTableBox * pRefBox,const String & rGetName)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
lcl_BoxNmToRel(const SwTable & rTbl,const SwTableNode & rTblNd,const String & rRefBoxNm,const String & rGetStr,sal_Bool bExtrnlNm)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
GetBoxesOfFormula(const SwTable & rTbl,SwSelBoxes & rBoxes)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
_GetFmlBoxes(const SwTable & rTbl,String &,String & rFirstBox,String * pLastBox,void * pPara) const894 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
GetBoxes(const SwTableBox & rSttBox,const SwTableBox & rEndBox,SwSelBoxes & rBoxes) const929 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?
_HasValidBoxes(const SwTable & rTbl,String &,String & rFirstBox,String * pLastBox,void * pPara) const985 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
HasValidBoxes() const1033 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
GetLnPosInTbl(const SwTable & rTbl,const SwTableBox * pBox)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
_SplitMergeBoxNm(const SwTable & rTbl,String & rNewStr,String & rFirstBox,String * pLastBox,void * pPara) const1057 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
ToSplitMergeBoxNm(SwTableFmlUpdate & rTblUpd)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