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