xref: /AOO41X/main/sw/source/core/fields/cellfml.cxx (revision 24c91d8626b8cded94cd29838d7c44d17cf7b1da)
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