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