Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <cstddef>
21 : #include <cstdio>
22 :
23 : #include <string.h>
24 : #include <tools/mempool.hxx>
25 : #include <osl/diagnose.h>
26 : #include <sfx2/docfile.hxx>
27 :
28 : #include "token.hxx"
29 : #include "tokenarray.hxx"
30 : #include "reftokenhelper.hxx"
31 : #include "clipparam.hxx"
32 : #include "compiler.hxx"
33 : #include <formula/compiler.hrc>
34 : #include "rechead.hxx"
35 : #include "parclass.hxx"
36 : #include "jumpmatrix.hxx"
37 : #include "rangeseq.hxx"
38 : #include "externalrefmgr.hxx"
39 : #include "document.hxx"
40 :
41 : using ::std::vector;
42 :
43 : #include <com/sun/star/sheet/ComplexReference.hpp>
44 : #include <com/sun/star/sheet/ExternalReference.hpp>
45 : #include <com/sun/star/sheet/ReferenceFlags.hpp>
46 : #include <com/sun/star/sheet/NameToken.hpp>
47 :
48 : using namespace formula;
49 : using namespace com::sun::star;
50 :
51 : namespace
52 : {
53 38 : void lcl_SingleRefToCalc( ScSingleRefData& rRef, const sheet::SingleReference& rAPI )
54 : {
55 38 : rRef.InitFlags();
56 :
57 38 : rRef.nCol = static_cast<SCsCOL>(rAPI.Column);
58 38 : rRef.nRow = static_cast<SCsROW>(rAPI.Row);
59 38 : rRef.nTab = static_cast<SCsTAB>(rAPI.Sheet);
60 38 : rRef.nRelCol = static_cast<SCsCOL>(rAPI.RelativeColumn);
61 38 : rRef.nRelRow = static_cast<SCsROW>(rAPI.RelativeRow);
62 38 : rRef.nRelTab = static_cast<SCsTAB>(rAPI.RelativeSheet);
63 :
64 38 : rRef.SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
65 38 : rRef.SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 );
66 38 : rRef.SetTabRel( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_RELATIVE ) != 0 );
67 38 : rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 );
68 38 : rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 );
69 38 : rRef.SetTabDeleted( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_DELETED ) != 0 );
70 38 : rRef.SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 );
71 38 : rRef.SetRelName( ( rAPI.Flags & sheet::ReferenceFlags::RELATIVE_NAME ) != 0 );
72 38 : }
73 :
74 0 : void lcl_ExternalRefToCalc( ScSingleRefData& rRef, const sheet::SingleReference& rAPI )
75 : {
76 0 : rRef.InitFlags();
77 :
78 0 : rRef.nCol = static_cast<SCsCOL>(rAPI.Column);
79 0 : rRef.nRow = static_cast<SCsROW>(rAPI.Row);
80 0 : rRef.nTab = 0;
81 0 : rRef.nRelCol = static_cast<SCsCOL>(rAPI.RelativeColumn);
82 0 : rRef.nRelRow = static_cast<SCsROW>(rAPI.RelativeRow);
83 0 : rRef.nRelTab = 0;
84 :
85 0 : rRef.SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
86 0 : rRef.SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 );
87 0 : rRef.SetTabRel( false ); // sheet index must be absolute for external refs
88 0 : rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 );
89 0 : rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 );
90 0 : rRef.SetTabDeleted( false ); // sheet must not be deleted for external refs
91 0 : rRef.SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 );
92 0 : rRef.SetRelName( false );
93 0 : }
94 : //
95 : } // namespace
96 :
97 : // Align MemPools on 4k boundaries - 64 bytes (4k is a MUST for OS/2)
98 :
99 : // Since RawTokens are temporary for the compiler, don't align on 4k and waste memory.
100 : // ScRawToken size is FixMembers + MAXSTRLEN + ~4 ~= 1036
101 5 : IMPL_FIXEDMEMPOOL_NEWDEL( ScRawToken )
102 : // Some ScDoubleRawToken, FixMembers + sizeof(double) ~= 16
103 5 : IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleRawToken )
104 :
105 : // Need a whole bunch of ScSingleRefToken
106 5 : IMPL_FIXEDMEMPOOL_NEWDEL( ScSingleRefToken )
107 : // Need quite a lot of ScDoubleRefToken
108 5 : IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleRefToken )
109 :
110 : // --- class ScRawToken -----------------------------------------------------
111 :
112 216 : xub_StrLen ScRawToken::GetStrLen( const sal_Unicode* pStr )
113 : {
114 216 : if ( !pStr )
115 0 : return 0;
116 216 : register const sal_Unicode* p = pStr;
117 1344 : while ( *p )
118 912 : p++;
119 216 : return sal::static_int_cast<xub_StrLen>( p - pStr );
120 : }
121 :
122 :
123 21169 : void ScRawToken::SetOpCode( OpCode e )
124 : {
125 21169 : eOp = e;
126 21169 : switch (eOp)
127 : {
128 : case ocIf:
129 20 : eType = svJump;
130 20 : nJump[ 0 ] = 3; // If, Else, Behind
131 20 : break;
132 : case ocChose:
133 0 : eType = svJump;
134 0 : nJump[ 0 ] = MAXJUMPCOUNT+1;
135 0 : break;
136 : case ocMissing:
137 0 : eType = svMissing;
138 0 : break;
139 : case ocSep:
140 : case ocOpen:
141 : case ocClose:
142 : case ocArrayRowSep:
143 : case ocArrayColSep:
144 : case ocArrayOpen:
145 : case ocArrayClose:
146 12332 : eType = svSep;
147 12332 : break;
148 : default:
149 8817 : eType = svByte;
150 8817 : sbyte.cByte = 0;
151 8817 : sbyte.bHasForceArray = ScParameterClassification::HasForceArray( eOp);
152 : }
153 21169 : nRefCnt = 0;
154 21169 : }
155 :
156 108 : void ScRawToken::SetString( const sal_Unicode* pStr )
157 : {
158 108 : eOp = ocPush;
159 108 : eType = svString;
160 108 : if ( pStr )
161 : {
162 108 : xub_StrLen nLen = GetStrLen( pStr ) + 1;
163 108 : if( nLen > MAXSTRLEN )
164 0 : nLen = MAXSTRLEN;
165 108 : memcpy( cStr, pStr, GetStrLenBytes( nLen ) );
166 108 : cStr[ nLen-1 ] = 0;
167 : }
168 : else
169 0 : cStr[0] = 0;
170 108 : nRefCnt = 0;
171 108 : }
172 :
173 377 : void ScRawToken::SetSingleReference( const ScSingleRefData& rRef )
174 : {
175 377 : eOp = ocPush;
176 377 : eType = svSingleRef;
177 : aRef.Ref1 =
178 377 : aRef.Ref2 = rRef;
179 377 : nRefCnt = 0;
180 377 : }
181 :
182 181 : void ScRawToken::SetDoubleReference( const ScComplexRefData& rRef )
183 : {
184 181 : eOp = ocPush;
185 181 : eType = svDoubleRef;
186 181 : aRef = rRef;
187 181 : nRefCnt = 0;
188 181 : }
189 :
190 435 : void ScRawToken::SetDouble(double rVal)
191 : {
192 435 : eOp = ocPush;
193 435 : eType = svDouble;
194 435 : nValue = rVal;
195 435 : nRefCnt = 0;
196 435 : }
197 :
198 0 : void ScRawToken::SetErrorConstant( sal_uInt16 nErr )
199 : {
200 0 : eOp = ocPush;
201 0 : eType = svError;
202 0 : nError = nErr;
203 0 : nRefCnt = 0;
204 0 : }
205 :
206 39 : void ScRawToken::SetName(bool bGlobal, sal_uInt16 nIndex)
207 : {
208 39 : eOp = ocName;
209 39 : eType = svIndex;
210 39 : nRefCnt = 0;
211 :
212 39 : name.bGlobal = bGlobal;
213 39 : name.nIndex = nIndex;
214 39 : }
215 :
216 23 : void ScRawToken::SetExternalSingleRef( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef )
217 : {
218 23 : eOp = ocPush;
219 23 : eType = svExternalSingleRef;
220 23 : nRefCnt = 0;
221 :
222 23 : extref.nFileId = nFileId;
223 : extref.aRef.Ref1 =
224 23 : extref.aRef.Ref2 = rRef;
225 :
226 23 : xub_StrLen n = rTabName.Len();
227 23 : memcpy(extref.cTabName, rTabName.GetBuffer(), n*sizeof(sal_Unicode));
228 23 : extref.cTabName[n] = 0;
229 23 : }
230 :
231 6 : void ScRawToken::SetExternalDoubleRef( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef )
232 : {
233 6 : eOp = ocPush;
234 6 : eType = svExternalDoubleRef;
235 6 : nRefCnt = 0;
236 :
237 6 : extref.nFileId = nFileId;
238 6 : extref.aRef = rRef;
239 :
240 6 : xub_StrLen n = rTabName.Len();
241 6 : memcpy(extref.cTabName, rTabName.GetBuffer(), n*sizeof(sal_Unicode));
242 6 : extref.cTabName[n] = 0;
243 6 : }
244 :
245 0 : void ScRawToken::SetExternalName( sal_uInt16 nFileId, const String& rName )
246 : {
247 0 : eOp = ocPush;
248 0 : eType = svExternalName;
249 0 : nRefCnt = 0;
250 :
251 0 : extname.nFileId = nFileId;
252 :
253 0 : xub_StrLen n = rName.Len();
254 0 : memcpy(extname.cName, rName.GetBuffer(), n*sizeof(sal_Unicode));
255 0 : extname.cName[n] = 0;
256 0 : }
257 :
258 :
259 :
260 0 : void ScRawToken::SetExternal( const sal_Unicode* pStr )
261 : {
262 0 : eOp = ocExternal;
263 0 : eType = svExternal;
264 0 : xub_StrLen nLen = GetStrLen( pStr ) + 1;
265 0 : if( nLen >= MAXSTRLEN )
266 0 : nLen = MAXSTRLEN-1;
267 : // Platz fuer Byte-Parameter lassen!
268 0 : memcpy( cStr+1, pStr, GetStrLenBytes( nLen ) );
269 0 : cStr[ nLen+1 ] = 0;
270 0 : nRefCnt = 0;
271 0 : }
272 :
273 :
274 446 : bool ScRawToken::IsValidReference() const
275 : {
276 446 : switch (eType)
277 : {
278 : case svSingleRef:
279 284 : return aRef.Ref1.Valid();
280 : case svDoubleRef:
281 133 : return aRef.Valid();
282 : case svExternalSingleRef:
283 : case svExternalDoubleRef:
284 29 : return true;
285 : default:
286 : ; // nothing
287 : }
288 0 : return false;
289 : }
290 :
291 :
292 3 : sal_uInt16 ScRawToken::sbyteOffset()
293 : {
294 : // offset of sbyte in ScRawToken
295 : // offsetof(ScRawToken, sbyte) gives a warning with gcc, because ScRawToken is no POD
296 :
297 3 : ScRawToken aToken;
298 3 : return static_cast<sal_uInt16>( reinterpret_cast<char*>(&aToken.sbyte) - reinterpret_cast<char*>(&aToken) );
299 : }
300 :
301 3291 : ScRawToken* ScRawToken::Clone() const
302 : {
303 : ScRawToken* p;
304 3291 : if ( eType == svDouble )
305 : {
306 435 : p = (ScRawToken*) new ScDoubleRawToken;
307 435 : p->eOp = eOp;
308 435 : p->eType = eType;
309 435 : p->nValue = nValue;
310 : }
311 : else
312 : {
313 2856 : static sal_uInt16 nOffset = sbyteOffset(); // offset of sbyte
314 2856 : sal_uInt16 n = nOffset;
315 :
316 2856 : switch( eType )
317 : {
318 1433 : case svSep: break;
319 670 : case svByte: n += sizeof(ScRawToken::sbyte); break;
320 0 : case svDouble: n += sizeof(double); break;
321 0 : case svError: n += sizeof(nError); break;
322 108 : case svString: n = sal::static_int_cast<sal_uInt16>( n + GetStrLenBytes( cStr ) + GetStrLenBytes( 1 ) ); break;
323 : case svSingleRef:
324 558 : case svDoubleRef: n += sizeof(aRef); break;
325 0 : case svMatrix: n += sizeof(ScMatrix*); break;
326 39 : case svIndex: n += sizeof(name); break;
327 19 : case svJump: n += nJump[ 0 ] * 2 + 2; break;
328 0 : case svExternal: n = sal::static_int_cast<sal_uInt16>( n + GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ) ); break;
329 :
330 : // external references
331 : case svExternalSingleRef:
332 29 : case svExternalDoubleRef: n += sizeof(extref); break;
333 0 : case svExternalName: n += sizeof(extname); break;
334 : default:
335 : {
336 : OSL_TRACE( "unknown ScRawToken::Clone() type %d", int(eType));
337 : }
338 : }
339 2856 : p = (ScRawToken*) new sal_uInt8[ n ];
340 2856 : memcpy( p, this, n * sizeof(sal_uInt8) );
341 : }
342 3291 : p->nRefCnt = 0;
343 3291 : p->bRaw = false;
344 3291 : return p;
345 : }
346 :
347 :
348 22338 : FormulaToken* ScRawToken::CreateToken() const
349 : {
350 : #if OSL_DEBUG_LEVEL > 1
351 : #define IF_NOT_OPCODE_ERROR(o,c) if (eOp!=o) OSL_TRACE( #c "::ctor: OpCode %d lost, converted to " #o "; maybe inherit from FormulaToken instead!", int(eOp))
352 : #else
353 : #define IF_NOT_OPCODE_ERROR(o,c)
354 : #endif
355 22338 : switch ( GetType() )
356 : {
357 : case svByte :
358 8817 : return new FormulaByteToken( eOp, sbyte.cByte, sbyte.bHasForceArray );
359 : case svDouble :
360 : IF_NOT_OPCODE_ERROR( ocPush, FormulaDoubleToken);
361 435 : return new FormulaDoubleToken( nValue );
362 : case svString :
363 108 : if (eOp == ocPush)
364 101 : return new FormulaStringToken( rtl::OUString( cStr ) );
365 : else
366 7 : return new FormulaStringOpToken( eOp, rtl::OUString( cStr ) );
367 : case svSingleRef :
368 377 : if (eOp == ocPush)
369 377 : return new ScSingleRefToken( aRef.Ref1 );
370 : else
371 0 : return new ScSingleRefToken( aRef.Ref1, eOp );
372 : case svDoubleRef :
373 181 : if (eOp == ocPush)
374 181 : return new ScDoubleRefToken( aRef );
375 : else
376 0 : return new ScDoubleRefToken( aRef, eOp );
377 : case svMatrix :
378 : IF_NOT_OPCODE_ERROR( ocPush, ScMatrixToken);
379 0 : return new ScMatrixToken( pMat );
380 : case svIndex :
381 39 : return new FormulaIndexToken( eOp, name.nIndex, name.bGlobal);
382 : case svExternalSingleRef:
383 : {
384 23 : rtl::OUString aTabName(extref.cTabName);
385 23 : return new ScExternalSingleRefToken(extref.nFileId, aTabName, extref.aRef.Ref1);
386 : }
387 : case svExternalDoubleRef:
388 : {
389 6 : rtl::OUString aTabName(extref.cTabName);
390 6 : return new ScExternalDoubleRefToken(extref.nFileId, aTabName, extref.aRef);
391 : }
392 : case svExternalName:
393 : {
394 0 : rtl::OUString aName(extname.cName);
395 0 : return new ScExternalNameToken( extname.nFileId, aName );
396 : }
397 : case svJump :
398 20 : return new FormulaJumpToken( eOp, (short*) nJump );
399 : case svExternal :
400 0 : return new FormulaExternalToken( eOp, sbyte.cByte, rtl::OUString( cStr+1 ) );
401 : case svFAP :
402 0 : return new FormulaFAPToken( eOp, sbyte.cByte, NULL );
403 : case svMissing :
404 : IF_NOT_OPCODE_ERROR( ocMissing, FormulaMissingToken);
405 0 : return new FormulaMissingToken;
406 : case svSep :
407 12332 : return new FormulaToken( svSep,eOp );
408 : case svError :
409 0 : return new FormulaErrorToken( nError );
410 : case svUnknown :
411 0 : return new FormulaUnknownToken( eOp );
412 : default:
413 : {
414 : OSL_TRACE( "unknown ScRawToken::CreateToken() type %d", int(GetType()));
415 0 : return new FormulaUnknownToken( ocBad );
416 : }
417 : }
418 : #undef IF_NOT_OPCODE_ERROR
419 : }
420 :
421 :
422 3291 : void ScRawToken::Delete()
423 : {
424 3291 : if ( bRaw )
425 0 : delete this; // FixedMemPool ScRawToken
426 : else
427 : { // created per Clone
428 3291 : switch ( eType )
429 : {
430 : case svDouble :
431 435 : delete (ScDoubleRawToken*) this; // FixedMemPool ScDoubleRawToken
432 435 : break;
433 : default:
434 2856 : delete [] (sal_uInt8*) this;
435 : }
436 : }
437 3291 : }
438 :
439 :
440 : // --- class ScToken --------------------------------------------------------
441 :
442 0 : static ScSingleRefData lcl_ScToken_InitSingleRef()
443 : {
444 : ScSingleRefData aRef;
445 0 : aRef.InitAddress( ScAddress() );
446 0 : return aRef;
447 : }
448 :
449 0 : static ScComplexRefData lcl_ScToken_InitDoubleRef()
450 : {
451 : ScComplexRefData aRef;
452 0 : aRef.Ref1 = lcl_ScToken_InitSingleRef();
453 0 : aRef.Ref2 = aRef.Ref1;
454 0 : return aRef;
455 : }
456 :
457 7820 : ScToken::~ScToken()
458 : {
459 7820 : }
460 :
461 : // TextEqual: if same formula entered (for optimization in sort)
462 0 : bool ScToken::TextEqual( const FormulaToken& _rToken ) const
463 : {
464 0 : if ( eType == svSingleRef || eType == svDoubleRef )
465 : {
466 : // in relative Refs only compare relative parts
467 :
468 0 : if ( eType != _rToken.GetType() || GetOpCode() != _rToken.GetOpCode() )
469 0 : return false;
470 :
471 0 : const ScToken& rToken = static_cast<const ScToken&>(_rToken);
472 : ScComplexRefData aTemp1;
473 0 : if ( eType == svSingleRef )
474 : {
475 0 : aTemp1.Ref1 = GetSingleRef();
476 0 : aTemp1.Ref2 = aTemp1.Ref1;
477 : }
478 : else
479 0 : aTemp1 = GetDoubleRef();
480 :
481 : ScComplexRefData aTemp2;
482 0 : if ( rToken.eType == svSingleRef )
483 : {
484 0 : aTemp2.Ref1 = rToken.GetSingleRef();
485 0 : aTemp2.Ref2 = aTemp2.Ref1;
486 : }
487 : else
488 0 : aTemp2 = rToken.GetDoubleRef();
489 :
490 0 : ScAddress aPos;
491 0 : aTemp1.SmartRelAbs(aPos);
492 0 : aTemp2.SmartRelAbs(aPos);
493 :
494 : // memcmp doesn't work because of the alignment byte after bFlags.
495 : // After SmartRelAbs only absolute parts have to be compared.
496 : return aTemp1.Ref1.nCol == aTemp2.Ref1.nCol &&
497 : aTemp1.Ref1.nRow == aTemp2.Ref1.nRow &&
498 : aTemp1.Ref1.nTab == aTemp2.Ref1.nTab &&
499 : aTemp1.Ref1.bFlags == aTemp2.Ref1.bFlags &&
500 : aTemp1.Ref2.nCol == aTemp2.Ref2.nCol &&
501 : aTemp1.Ref2.nRow == aTemp2.Ref2.nRow &&
502 : aTemp1.Ref2.nTab == aTemp2.Ref2.nTab &&
503 0 : aTemp1.Ref2.bFlags == aTemp2.Ref2.bFlags;
504 : }
505 : else
506 0 : return *this == _rToken; // else normal operator==
507 : }
508 :
509 :
510 0 : bool ScToken::Is3DRef() const
511 : {
512 0 : switch ( eType )
513 : {
514 : case svDoubleRef :
515 0 : if ( GetSingleRef2().IsFlag3D() )
516 0 : return true;
517 : //! fallthru
518 : case svSingleRef :
519 0 : if ( GetSingleRef().IsFlag3D() )
520 0 : return true;
521 0 : break;
522 : default:
523 : {
524 : // added to avoid warnings
525 : }
526 : }
527 0 : return false;
528 : }
529 :
530 0 : FormulaTokenRef ScToken::ExtendRangeReference( FormulaToken & rTok1, FormulaToken & rTok2,
531 : const ScAddress & rPos, bool bReuseDoubleRef )
532 : {
533 :
534 : StackVar sv1, sv2;
535 : // Doing a RangeOp with RefList is probably utter nonsense, but Xcl
536 : // supports it, so do we.
537 0 : if (((sv1 = rTok1.GetType()) != svSingleRef && sv1 != svDoubleRef && sv1 != svRefList &&
538 : sv1 != svExternalSingleRef && sv1 != svExternalDoubleRef ) ||
539 : ((sv2 = rTok2.GetType()) != svSingleRef && sv2 != svDoubleRef && sv2 != svRefList))
540 0 : return NULL;
541 :
542 0 : ScToken *p1 = static_cast<ScToken*>(&rTok1);
543 0 : ScToken *p2 = static_cast<ScToken*>(&rTok2);
544 :
545 0 : ScTokenRef xRes;
546 0 : bool bExternal = (sv1 == svExternalSingleRef);
547 0 : if ((sv1 == svSingleRef || bExternal) && sv2 == svSingleRef)
548 : {
549 : // Range references like Sheet1.A1:A2 are generalized and built by
550 : // first creating a DoubleRef from the first SingleRef, effectively
551 : // generating Sheet1.A1:A1, and then extending that with A2 as if
552 : // Sheet1.A1:A1:A2 was encountered, so the mechanisms to adjust the
553 : // references apply as well.
554 :
555 : /* Given the current structure of external references an external
556 : * reference can only be extended if the second reference does not
557 : * point to a different sheet. 'file'#Sheet1.A1:A2 is ok,
558 : * 'file'#Sheet1.A1:Sheet2.A2 is not. Since we can't determine from a
559 : * svSingleRef whether the sheet would be different from the one given
560 : * in the external reference, we have to bail out if there is any sheet
561 : * specified. NOTE: Xcl does handle external 3D references as in
562 : * '[file]Sheet1:Sheet2'!A1:A2
563 : *
564 : * FIXME: For OOo syntax be smart and remember an external singleref
565 : * encountered and if followed by ocRange and singleref, create an
566 : * external singleref for the second singleref. Both could then be
567 : * merged here. For Xcl syntax already parse an external range
568 : * reference entirely, cumbersome. */
569 :
570 0 : const ScSingleRefData& rRef2 = p2->GetSingleRef();
571 0 : if (bExternal && rRef2.IsFlag3D())
572 0 : return NULL;
573 :
574 : ScComplexRefData aRef;
575 0 : aRef.Ref1 = aRef.Ref2 = p1->GetSingleRef();
576 0 : aRef.Ref2.SetFlag3D( false);
577 0 : aRef.Extend( rRef2, rPos);
578 0 : if (bExternal)
579 0 : xRes = new ScExternalDoubleRefToken( p1->GetIndex(), p1->GetString(), aRef);
580 : else
581 0 : xRes = new ScDoubleRefToken( aRef);
582 : }
583 : else
584 : {
585 0 : bExternal |= (sv1 == svExternalDoubleRef);
586 0 : const ScRefList* pRefList = NULL;
587 0 : if (sv1 == svDoubleRef)
588 : {
589 0 : xRes = (bReuseDoubleRef && p1->GetRef() == 1 ? p1 : static_cast<ScToken*>(p1->Clone()));
590 0 : sv1 = svUnknown; // mark as handled
591 : }
592 0 : else if (sv2 == svDoubleRef)
593 : {
594 0 : xRes = (bReuseDoubleRef && p2->GetRef() == 1 ? p2 : static_cast<ScToken*>(p2->Clone()));
595 0 : sv2 = svUnknown; // mark as handled
596 : }
597 0 : else if (sv1 == svRefList)
598 0 : pRefList = p1->GetRefList();
599 0 : else if (sv2 == svRefList)
600 0 : pRefList = p2->GetRefList();
601 0 : if (pRefList)
602 : {
603 0 : if (!pRefList->size())
604 0 : return NULL;
605 0 : if (bExternal)
606 0 : return NULL; // external reference list not possible
607 0 : xRes = new ScDoubleRefToken( (*pRefList)[0] );
608 : }
609 0 : if (!xRes)
610 0 : return NULL; // shouldn't happen..
611 0 : StackVar sv[2] = { sv1, sv2 };
612 0 : ScToken* pt[2] = { p1, p2 };
613 0 : ScComplexRefData& rRef = xRes->GetDoubleRef();
614 0 : for (size_t i=0; i<2; ++i)
615 : {
616 0 : switch (sv[i])
617 : {
618 : case svSingleRef:
619 0 : rRef.Extend( pt[i]->GetSingleRef(), rPos);
620 0 : break;
621 : case svDoubleRef:
622 0 : rRef.Extend( pt[i]->GetDoubleRef(), rPos);
623 0 : break;
624 : case svRefList:
625 : {
626 0 : const ScRefList* p = pt[i]->GetRefList();
627 0 : if (!p->size())
628 0 : return NULL;
629 0 : ScRefList::const_iterator it( p->begin());
630 0 : ScRefList::const_iterator end( p->end());
631 0 : for ( ; it != end; ++it)
632 : {
633 0 : rRef.Extend( *it, rPos);
634 : }
635 : }
636 0 : break;
637 : case svExternalSingleRef:
638 0 : if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D())
639 0 : return NULL; // no other sheets with external refs
640 : else
641 0 : rRef.Extend( pt[i]->GetSingleRef(), rPos);
642 0 : break;
643 : case svExternalDoubleRef:
644 0 : if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D())
645 0 : return NULL; // no other sheets with external refs
646 : else
647 0 : rRef.Extend( pt[i]->GetDoubleRef(), rPos);
648 0 : break;
649 : default:
650 : ; // nothing, prevent compiler warning
651 : }
652 : }
653 : }
654 0 : return FormulaTokenRef(xRes.get());
655 : }
656 :
657 0 : const ScSingleRefData& ScToken::GetSingleRef() const
658 : {
659 : OSL_FAIL( "ScToken::GetSingleRef: virtual dummy called" );
660 0 : static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef();
661 0 : return aDummySingleRef;
662 : }
663 :
664 0 : ScSingleRefData& ScToken::GetSingleRef()
665 : {
666 : OSL_FAIL( "ScToken::GetSingleRef: virtual dummy called" );
667 0 : static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef();
668 0 : return aDummySingleRef;
669 : }
670 :
671 0 : const ScComplexRefData& ScToken::GetDoubleRef() const
672 : {
673 : OSL_FAIL( "ScToken::GetDoubleRef: virtual dummy called" );
674 0 : static ScComplexRefData aDummyDoubleRef = lcl_ScToken_InitDoubleRef();
675 0 : return aDummyDoubleRef;
676 : }
677 :
678 0 : ScComplexRefData& ScToken::GetDoubleRef()
679 : {
680 : OSL_FAIL( "ScToken::GetDoubleRef: virtual dummy called" );
681 0 : static ScComplexRefData aDummyDoubleRef = lcl_ScToken_InitDoubleRef();
682 0 : return aDummyDoubleRef;
683 : }
684 :
685 0 : const ScSingleRefData& ScToken::GetSingleRef2() const
686 : {
687 : OSL_FAIL( "ScToken::GetSingleRef2: virtual dummy called" );
688 0 : static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef();
689 0 : return aDummySingleRef;
690 : }
691 :
692 0 : ScSingleRefData& ScToken::GetSingleRef2()
693 : {
694 : OSL_FAIL( "ScToken::GetSingleRef2: virtual dummy called" );
695 0 : static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef();
696 0 : return aDummySingleRef;
697 : }
698 :
699 0 : void ScToken::CalcAbsIfRel( const ScAddress& /* rPos */ )
700 : {
701 : OSL_FAIL( "ScToken::CalcAbsIfRel: virtual dummy called" );
702 0 : }
703 :
704 0 : void ScToken::CalcRelFromAbs( const ScAddress& /* rPos */ )
705 : {
706 : OSL_FAIL( "ScToken::CalcRelFromAbs: virtual dummy called" );
707 0 : }
708 :
709 0 : const ScMatrix* ScToken::GetMatrix() const
710 : {
711 : OSL_FAIL( "ScToken::GetMatrix: virtual dummy called" );
712 0 : return NULL;
713 : }
714 :
715 0 : ScMatrix* ScToken::GetMatrix()
716 : {
717 : OSL_FAIL( "ScToken::GetMatrix: virtual dummy called" );
718 0 : return NULL;
719 : }
720 :
721 :
722 0 : ScJumpMatrix* ScToken::GetJumpMatrix() const
723 : {
724 : OSL_FAIL( "ScToken::GetJumpMatrix: virtual dummy called" );
725 0 : return NULL;
726 : }
727 0 : const ScRefList* ScToken::GetRefList() const
728 : {
729 : OSL_FAIL( "ScToken::GetRefList: virtual dummy called" );
730 0 : return NULL;
731 : }
732 :
733 0 : ScRefList* ScToken::GetRefList()
734 : {
735 : OSL_FAIL( "ScToken::GetRefList: virtual dummy called" );
736 0 : return NULL;
737 : }
738 : // ==========================================================================
739 : // real implementations of virtual functions
740 : // --------------------------------------------------------------------------
741 :
742 :
743 :
744 :
745 70 : const ScSingleRefData& ScSingleRefToken::GetSingleRef() const { return aSingleRef; }
746 11748 : ScSingleRefData& ScSingleRefToken::GetSingleRef() { return aSingleRef; }
747 37 : void ScSingleRefToken::CalcAbsIfRel( const ScAddress& rPos )
748 37 : { aSingleRef.CalcAbsIfRel( rPos ); }
749 62 : void ScSingleRefToken::CalcRelFromAbs( const ScAddress& rPos )
750 62 : { aSingleRef.CalcRelFromAbs( rPos ); }
751 2 : bool ScSingleRefToken::operator==( const FormulaToken& r ) const
752 : {
753 2 : return FormulaToken::operator==( r ) && aSingleRef == static_cast<const ScToken&>(r).GetSingleRef();
754 : }
755 :
756 :
757 14 : const ScSingleRefData& ScDoubleRefToken::GetSingleRef() const { return aDoubleRef.Ref1; }
758 2319 : ScSingleRefData& ScDoubleRefToken::GetSingleRef() { return aDoubleRef.Ref1; }
759 201 : const ScComplexRefData& ScDoubleRefToken::GetDoubleRef() const { return aDoubleRef; }
760 3431 : ScComplexRefData& ScDoubleRefToken::GetDoubleRef() { return aDoubleRef; }
761 14 : const ScSingleRefData& ScDoubleRefToken::GetSingleRef2() const { return aDoubleRef.Ref2; }
762 0 : ScSingleRefData& ScDoubleRefToken::GetSingleRef2() { return aDoubleRef.Ref2; }
763 2279 : void ScDoubleRefToken::CalcAbsIfRel( const ScAddress& rPos )
764 2279 : { aDoubleRef.CalcAbsIfRel( rPos ); }
765 0 : void ScDoubleRefToken::CalcRelFromAbs( const ScAddress& rPos )
766 0 : { aDoubleRef.CalcRelFromAbs( rPos ); }
767 0 : bool ScDoubleRefToken::operator==( const FormulaToken& r ) const
768 : {
769 0 : return FormulaToken::operator==( r ) && aDoubleRef == static_cast<const ScToken&>(r).GetDoubleRef();
770 : }
771 :
772 :
773 0 : const ScRefList* ScRefListToken::GetRefList() const { return &aRefList; }
774 0 : ScRefList* ScRefListToken::GetRefList() { return &aRefList; }
775 0 : void ScRefListToken::CalcAbsIfRel( const ScAddress& rPos )
776 : {
777 0 : for (ScRefList::iterator it( aRefList.begin()); it != aRefList.end(); ++it)
778 0 : (*it).CalcAbsIfRel( rPos);
779 0 : }
780 0 : void ScRefListToken::CalcRelFromAbs( const ScAddress& rPos )
781 : {
782 0 : for (ScRefList::iterator it( aRefList.begin()); it != aRefList.end(); ++it)
783 0 : (*it).CalcRelFromAbs( rPos);
784 0 : }
785 0 : bool ScRefListToken::operator==( const FormulaToken& r ) const
786 : {
787 0 : return FormulaToken::operator==( r ) && &aRefList == static_cast<const ScToken&>(r).GetRefList();
788 : }
789 :
790 :
791 2 : const ScMatrix* ScMatrixToken::GetMatrix() const { return pMatrix.get(); }
792 44 : ScMatrix* ScMatrixToken::GetMatrix() { return pMatrix.get(); }
793 0 : bool ScMatrixToken::operator==( const FormulaToken& r ) const
794 : {
795 0 : return FormulaToken::operator==( r ) && pMatrix == static_cast<const ScToken&>(r).GetMatrix();
796 : }
797 :
798 : // ============================================================================
799 :
800 26 : ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& r ) :
801 : ScToken( svExternalSingleRef, ocPush),
802 : mnFileId(nFileId),
803 : maTabName(rTabName),
804 26 : maSingleRef(r)
805 : {
806 26 : }
807 :
808 0 : ScExternalSingleRefToken::ScExternalSingleRefToken( const ScExternalSingleRefToken& r ) :
809 : ScToken(r),
810 : mnFileId(r.mnFileId),
811 : maTabName(r.maTabName),
812 0 : maSingleRef(r.maSingleRef)
813 : {
814 0 : }
815 :
816 0 : ScExternalSingleRefToken::~ScExternalSingleRefToken()
817 : {
818 0 : }
819 :
820 26 : sal_uInt16 ScExternalSingleRefToken::GetIndex() const
821 : {
822 26 : return mnFileId;
823 : }
824 :
825 26 : const String& ScExternalSingleRefToken::GetString() const
826 : {
827 26 : return maTabName;
828 : }
829 :
830 0 : const ScSingleRefData& ScExternalSingleRefToken::GetSingleRef() const
831 : {
832 0 : return maSingleRef;
833 : }
834 :
835 55 : ScSingleRefData& ScExternalSingleRefToken::GetSingleRef()
836 : {
837 55 : return maSingleRef;
838 : }
839 :
840 0 : void ScExternalSingleRefToken::CalcAbsIfRel( const ScAddress& rPos )
841 : {
842 0 : maSingleRef.CalcAbsIfRel( rPos );
843 0 : }
844 :
845 0 : void ScExternalSingleRefToken::CalcRelFromAbs( const ScAddress& rPos )
846 : {
847 0 : maSingleRef.CalcRelFromAbs( rPos );
848 0 : }
849 :
850 0 : bool ScExternalSingleRefToken::operator ==( const FormulaToken& r ) const
851 : {
852 0 : if (!FormulaToken::operator==(r))
853 0 : return false;
854 :
855 0 : if (mnFileId != r.GetIndex())
856 0 : return false;
857 :
858 0 : if (maTabName != r.GetString())
859 0 : return false;
860 :
861 0 : return maSingleRef == static_cast<const ScToken&>(r).GetSingleRef();
862 : }
863 :
864 : // ============================================================================
865 :
866 6 : ScExternalDoubleRefToken::ScExternalDoubleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& r ) :
867 : ScToken( svExternalDoubleRef, ocPush),
868 : mnFileId(nFileId),
869 : maTabName(rTabName),
870 6 : maDoubleRef(r)
871 : {
872 6 : }
873 :
874 0 : ScExternalDoubleRefToken::ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r ) :
875 : ScToken(r),
876 : mnFileId(r.mnFileId),
877 : maTabName(r.maTabName),
878 0 : maDoubleRef(r.maDoubleRef)
879 : {
880 0 : }
881 :
882 12 : ScExternalDoubleRefToken::~ScExternalDoubleRefToken()
883 : {
884 12 : }
885 :
886 6 : sal_uInt16 ScExternalDoubleRefToken::GetIndex() const
887 : {
888 6 : return mnFileId;
889 : }
890 :
891 6 : const String& ScExternalDoubleRefToken::GetString() const
892 : {
893 6 : return maTabName;
894 : }
895 :
896 0 : const ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef() const
897 : {
898 0 : return maDoubleRef.Ref1;
899 : }
900 :
901 12 : ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef()
902 : {
903 12 : return maDoubleRef.Ref1;
904 : }
905 :
906 0 : const ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef2() const
907 : {
908 0 : return maDoubleRef.Ref2;
909 : }
910 :
911 0 : ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef2()
912 : {
913 0 : return maDoubleRef.Ref2;
914 : }
915 :
916 0 : const ScComplexRefData& ScExternalDoubleRefToken::GetDoubleRef() const
917 : {
918 0 : return maDoubleRef;
919 : }
920 :
921 6 : ScComplexRefData& ScExternalDoubleRefToken::GetDoubleRef()
922 : {
923 6 : return maDoubleRef;
924 : }
925 :
926 0 : void ScExternalDoubleRefToken::CalcAbsIfRel( const ScAddress& rPos )
927 : {
928 0 : maDoubleRef.CalcAbsIfRel( rPos );
929 0 : }
930 :
931 0 : void ScExternalDoubleRefToken::CalcRelFromAbs( const ScAddress& rPos )
932 : {
933 0 : maDoubleRef.CalcRelFromAbs( rPos );
934 0 : }
935 :
936 0 : bool ScExternalDoubleRefToken::operator ==( const FormulaToken& r ) const
937 : {
938 0 : if (!ScToken::operator==(r))
939 0 : return false;
940 :
941 0 : if (mnFileId != r.GetIndex())
942 0 : return false;
943 :
944 0 : if (maTabName != r.GetString())
945 0 : return false;
946 :
947 0 : return maDoubleRef == static_cast<const ScToken&>(r).GetDoubleRef();
948 : }
949 :
950 : // ============================================================================
951 :
952 0 : ScExternalNameToken::ScExternalNameToken( sal_uInt16 nFileId, const String& rName ) :
953 : ScToken( svExternalName, ocPush),
954 : mnFileId(nFileId),
955 0 : maName(rName)
956 : {
957 0 : }
958 :
959 0 : ScExternalNameToken::ScExternalNameToken( const ScExternalNameToken& r ) :
960 : ScToken(r),
961 : mnFileId(r.mnFileId),
962 0 : maName(r.maName)
963 : {
964 0 : }
965 :
966 0 : ScExternalNameToken::~ScExternalNameToken() {}
967 :
968 0 : sal_uInt16 ScExternalNameToken::GetIndex() const
969 : {
970 0 : return mnFileId;
971 : }
972 :
973 0 : const String& ScExternalNameToken::GetString() const
974 : {
975 0 : return maName;
976 : }
977 :
978 0 : bool ScExternalNameToken::operator==( const FormulaToken& r ) const
979 : {
980 0 : if ( !FormulaToken::operator==(r) )
981 0 : return false;
982 :
983 0 : if (mnFileId != r.GetIndex())
984 0 : return false;
985 :
986 0 : xub_StrLen nLen = maName.Len();
987 0 : const String& rName = r.GetString();
988 0 : if (nLen != rName.Len())
989 0 : return false;
990 :
991 0 : const sal_Unicode* p1 = maName.GetBuffer();
992 0 : const sal_Unicode* p2 = rName.GetBuffer();
993 0 : for (xub_StrLen j = 0; j < nLen; ++j)
994 : {
995 0 : if (p1[j] != p2[j])
996 0 : return false;
997 : }
998 0 : return true;
999 : }
1000 :
1001 : // ============================================================================
1002 :
1003 0 : ScJumpMatrix* ScJumpMatrixToken::GetJumpMatrix() const { return pJumpMatrix; }
1004 0 : bool ScJumpMatrixToken::operator==( const FormulaToken& r ) const
1005 : {
1006 0 : return FormulaToken::operator==( r ) && pJumpMatrix == static_cast<const ScToken&>(r).GetJumpMatrix();
1007 : }
1008 0 : ScJumpMatrixToken::~ScJumpMatrixToken()
1009 : {
1010 0 : delete pJumpMatrix;
1011 0 : }
1012 :
1013 0 : double ScEmptyCellToken::GetDouble() const { return 0.0; }
1014 0 : const String & ScEmptyCellToken::GetString() const
1015 : {
1016 0 : static String aDummyString;
1017 0 : return aDummyString;
1018 : }
1019 0 : bool ScEmptyCellToken::operator==( const FormulaToken& r ) const
1020 : {
1021 0 : return FormulaToken::operator==( r ) &&
1022 0 : bInherited == static_cast< const ScEmptyCellToken & >(r).IsInherited() &&
1023 0 : bDisplayedAsString == static_cast< const ScEmptyCellToken & >(r).IsDisplayedAsString();
1024 : }
1025 :
1026 :
1027 0 : double ScMatrixCellResultToken::GetDouble() const { return xUpperLeft->GetDouble(); }
1028 0 : const String & ScMatrixCellResultToken::GetString() const { return xUpperLeft->GetString(); }
1029 90 : const ScMatrix* ScMatrixCellResultToken::GetMatrix() const { return xMatrix.get(); }
1030 : // Non-const GetMatrix() is private and unused but must be implemented to
1031 : // satisfy vtable linkage.
1032 0 : ScMatrix* ScMatrixCellResultToken::GetMatrix()
1033 : {
1034 0 : return const_cast<ScMatrix*>(xMatrix.get());
1035 : }
1036 0 : bool ScMatrixCellResultToken::operator==( const FormulaToken& r ) const
1037 : {
1038 0 : return FormulaToken::operator==( r ) &&
1039 0 : xUpperLeft == static_cast<const ScMatrixCellResultToken &>(r).xUpperLeft &&
1040 0 : xMatrix == static_cast<const ScMatrixCellResultToken &>(r).xMatrix;
1041 : }
1042 :
1043 :
1044 0 : bool ScMatrixFormulaCellToken::operator==( const FormulaToken& r ) const
1045 : {
1046 0 : const ScMatrixFormulaCellToken* p = dynamic_cast<const ScMatrixFormulaCellToken*>(&r);
1047 0 : return p && ScMatrixCellResultToken::operator==( r ) &&
1048 0 : nCols == p->nCols && nRows == p->nRows;
1049 : }
1050 2 : void ScMatrixFormulaCellToken::Assign( const formula::FormulaToken& r )
1051 : {
1052 2 : if (this == &r)
1053 2 : return;
1054 2 : const ScMatrixCellResultToken* p = dynamic_cast<const ScMatrixCellResultToken*>(&r);
1055 2 : if (p)
1056 0 : ScMatrixCellResultToken::Assign( *p);
1057 : else
1058 : {
1059 : OSL_ENSURE( r.GetType() != svMatrix, "ScMatrixFormulaCellToken::operator=: assigning ScMatrixToken to ScMatrixFormulaCellToken is not proper, use ScMatrixCellResultToken instead");
1060 2 : if (r.GetType() == svMatrix)
1061 : {
1062 0 : xUpperLeft = NULL;
1063 0 : xMatrix = static_cast<const ScToken&>(r).GetMatrix();
1064 : }
1065 : else
1066 : {
1067 2 : xUpperLeft = &r;
1068 2 : xMatrix = NULL;
1069 : }
1070 : }
1071 : }
1072 17 : void ScMatrixFormulaCellToken::SetUpperLeftDouble( double f )
1073 : {
1074 17 : switch (GetUpperLeftType())
1075 : {
1076 : case svDouble:
1077 0 : const_cast<FormulaToken*>(xUpperLeft.get())->GetDoubleAsReference() = f;
1078 0 : break;
1079 : case svUnknown:
1080 17 : if (!xUpperLeft)
1081 : {
1082 17 : xUpperLeft = new FormulaDoubleToken( f);
1083 17 : break;
1084 : }
1085 : // fall thru
1086 : default:
1087 : {
1088 : OSL_FAIL("ScMatrixFormulaCellToken::SetUpperLeftDouble: not modifying unhandled token type");
1089 : }
1090 : }
1091 17 : }
1092 :
1093 :
1094 0 : double ScHybridCellToken::GetDouble() const { return fDouble; }
1095 52 : const String & ScHybridCellToken::GetString() const { return aString; }
1096 0 : bool ScHybridCellToken::operator==( const FormulaToken& r ) const
1097 : {
1098 0 : return FormulaToken::operator==( r ) &&
1099 0 : fDouble == r.GetDouble() && aString == r.GetString() &&
1100 0 : aFormula == static_cast<const ScHybridCellToken &>(r).GetFormula();
1101 : }
1102 :
1103 :
1104 :
1105 :
1106 : //////////////////////////////////////////////////////////////////////////
1107 :
1108 125 : bool ScTokenArray::AddFormulaToken(const com::sun::star::sheet::FormulaToken& _aToken,formula::ExternalReferenceHelper* _pRef)
1109 : {
1110 125 : bool bError = FormulaTokenArray::AddFormulaToken(_aToken,_pRef);
1111 125 : if ( bError )
1112 : {
1113 45 : bError = false;
1114 45 : const OpCode eOpCode = static_cast<OpCode>(_aToken.OpCode); //! assuming equal values for the moment
1115 :
1116 45 : const uno::TypeClass eClass = _aToken.Data.getValueTypeClass();
1117 45 : switch ( eClass )
1118 : {
1119 : case uno::TypeClass_STRUCT:
1120 : {
1121 44 : uno::Type aType = _aToken.Data.getValueType();
1122 44 : if ( aType.equals( cppu::UnoType<sheet::SingleReference>::get() ) )
1123 : {
1124 : ScSingleRefData aSingleRef;
1125 16 : sheet::SingleReference aApiRef;
1126 16 : _aToken.Data >>= aApiRef;
1127 16 : lcl_SingleRefToCalc( aSingleRef, aApiRef );
1128 16 : if ( eOpCode == ocPush )
1129 16 : AddSingleReference( aSingleRef );
1130 0 : else if ( eOpCode == ocColRowName )
1131 0 : AddColRowName( aSingleRef );
1132 : else
1133 0 : bError = true;
1134 : }
1135 28 : else if ( aType.equals( cppu::UnoType<sheet::ComplexReference>::get() ) )
1136 : {
1137 : ScComplexRefData aComplRef;
1138 11 : sheet::ComplexReference aApiRef;
1139 11 : _aToken.Data >>= aApiRef;
1140 11 : lcl_SingleRefToCalc( aComplRef.Ref1, aApiRef.Reference1 );
1141 11 : lcl_SingleRefToCalc( aComplRef.Ref2, aApiRef.Reference2 );
1142 :
1143 11 : if ( eOpCode == ocPush )
1144 11 : AddDoubleReference( aComplRef );
1145 : else
1146 0 : bError = true;
1147 : }
1148 17 : else if ( aType.equals( cppu::UnoType<sheet::NameToken>::get() ) )
1149 : {
1150 17 : sheet::NameToken aTokenData;
1151 17 : _aToken.Data >>= aTokenData;
1152 17 : if ( eOpCode == ocName )
1153 17 : AddRangeName(aTokenData.Index, aTokenData.Global);
1154 0 : else if (eOpCode == ocDBArea)
1155 0 : AddDBRange(aTokenData.Index);
1156 : else
1157 0 : bError = true;
1158 : }
1159 0 : else if ( aType.equals( cppu::UnoType<sheet::ExternalReference>::get() ) )
1160 : {
1161 0 : sheet::ExternalReference aApiExtRef;
1162 0 : if( (eOpCode == ocPush) && (_aToken.Data >>= aApiExtRef) && (0 <= aApiExtRef.Index) && (aApiExtRef.Index <= SAL_MAX_UINT16) )
1163 : {
1164 0 : sal_uInt16 nFileId = static_cast< sal_uInt16 >( aApiExtRef.Index );
1165 0 : sheet::SingleReference aApiSRef;
1166 0 : sheet::ComplexReference aApiCRef;
1167 0 : ::rtl::OUString aName;
1168 0 : if( aApiExtRef.Reference >>= aApiSRef )
1169 : {
1170 : // try to resolve cache index to sheet name
1171 0 : size_t nCacheId = static_cast< size_t >( aApiSRef.Sheet );
1172 0 : String aTabName = _pRef->getCacheTableName( nFileId, nCacheId );
1173 0 : if( aTabName.Len() > 0 )
1174 : {
1175 : ScSingleRefData aSingleRef;
1176 : // convert column/row settings, set sheet index to absolute
1177 0 : lcl_ExternalRefToCalc( aSingleRef, aApiSRef );
1178 0 : AddExternalSingleReference( nFileId, aTabName, aSingleRef );
1179 : }
1180 : else
1181 0 : bError = true;
1182 : }
1183 0 : else if( aApiExtRef.Reference >>= aApiCRef )
1184 : {
1185 : // try to resolve cache index to sheet name.
1186 0 : size_t nCacheId = static_cast< size_t >( aApiCRef.Reference1.Sheet );
1187 0 : String aTabName = _pRef->getCacheTableName( nFileId, nCacheId );
1188 0 : if( aTabName.Len() > 0 )
1189 : {
1190 : ScComplexRefData aComplRef;
1191 : // convert column/row settings, set sheet index to absolute
1192 0 : lcl_ExternalRefToCalc( aComplRef.Ref1, aApiCRef.Reference1 );
1193 0 : lcl_ExternalRefToCalc( aComplRef.Ref2, aApiCRef.Reference2 );
1194 : // NOTE: This assumes that cached sheets are in consecutive order!
1195 0 : aComplRef.Ref2.nTab = aComplRef.Ref1.nTab + static_cast<SCsTAB>(aApiCRef.Reference2.Sheet - aApiCRef.Reference1.Sheet);
1196 0 : AddExternalDoubleReference( nFileId, aTabName, aComplRef );
1197 : }
1198 : else
1199 0 : bError = true;
1200 : }
1201 0 : else if( aApiExtRef.Reference >>= aName )
1202 : {
1203 0 : if( !aName.isEmpty() )
1204 0 : AddExternalName( nFileId, aName );
1205 : else
1206 0 : bError = true;
1207 : }
1208 : else
1209 0 : bError = true;
1210 : }
1211 : else
1212 0 : bError = true;
1213 : }
1214 : else
1215 0 : bError = true; // unknown struct
1216 : }
1217 44 : break;
1218 : case uno::TypeClass_SEQUENCE:
1219 : {
1220 1 : if ( eOpCode != ocPush )
1221 0 : bError = true; // not an inline array
1222 2 : else if (!_aToken.Data.getValueType().equals( getCppuType(
1223 2 : (uno::Sequence< uno::Sequence< uno::Any > > *)0)))
1224 0 : bError = true; // unexpected sequence type
1225 : else
1226 : {
1227 1 : ScMatrixRef xMat = ScSequenceToMatrix::CreateMixedMatrix( _aToken.Data);
1228 1 : if (xMat)
1229 1 : AddMatrix( xMat);
1230 : else
1231 0 : bError = true;
1232 : }
1233 : }
1234 1 : break;
1235 : default:
1236 0 : bError = true;
1237 : }
1238 : }
1239 125 : return bError;
1240 : }
1241 55 : bool ScTokenArray::ImplGetReference( ScRange& rRange, bool bValidOnly ) const
1242 : {
1243 55 : bool bIs = false;
1244 55 : if ( pCode && nLen == 1 )
1245 : {
1246 55 : const FormulaToken* pToken = pCode[0];
1247 55 : if ( pToken )
1248 : {
1249 55 : if ( pToken->GetType() == svSingleRef )
1250 : {
1251 5 : const ScSingleRefData& rRef = ((const ScSingleRefToken*)pToken)->GetSingleRef();
1252 5 : rRange.aStart = rRange.aEnd = ScAddress( rRef.nCol, rRef.nRow, rRef.nTab );
1253 5 : bIs = !bValidOnly || !rRef.IsDeleted();
1254 : }
1255 50 : else if ( pToken->GetType() == svDoubleRef )
1256 : {
1257 50 : const ScComplexRefData& rCompl = ((const ScDoubleRefToken*)pToken)->GetDoubleRef();
1258 50 : const ScSingleRefData& rRef1 = rCompl.Ref1;
1259 50 : const ScSingleRefData& rRef2 = rCompl.Ref2;
1260 50 : rRange.aStart = ScAddress( rRef1.nCol, rRef1.nRow, rRef1.nTab );
1261 50 : rRange.aEnd = ScAddress( rRef2.nCol, rRef2.nRow, rRef2.nTab );
1262 50 : bIs = !bValidOnly || (!rRef1.IsDeleted() && !rRef2.IsDeleted());
1263 : }
1264 : }
1265 : }
1266 55 : return bIs;
1267 : }
1268 :
1269 27 : bool ScTokenArray::IsReference( ScRange& rRange ) const
1270 : {
1271 27 : return ImplGetReference( rRange, false );
1272 : }
1273 :
1274 28 : bool ScTokenArray::IsValidReference( ScRange& rRange ) const
1275 : {
1276 28 : return ImplGetReference( rRange, true );
1277 : }
1278 :
1279 : ////////////////////////////////////////////////////////////////////////////
1280 :
1281 1742 : ScTokenArray::ScTokenArray()
1282 : {
1283 1742 : }
1284 :
1285 3797 : ScTokenArray::ScTokenArray( const ScTokenArray& rArr ) : FormulaTokenArray(rArr)
1286 : {
1287 3797 : }
1288 :
1289 9726 : ScTokenArray::~ScTokenArray()
1290 : {
1291 9726 : }
1292 :
1293 :
1294 :
1295 0 : ScTokenArray& ScTokenArray::operator=( const ScTokenArray& rArr )
1296 : {
1297 0 : Clear();
1298 0 : Assign( rArr );
1299 0 : return *this;
1300 : }
1301 :
1302 348 : ScTokenArray* ScTokenArray::Clone() const
1303 : {
1304 348 : ScTokenArray* p = new ScTokenArray();
1305 348 : p->nLen = nLen;
1306 348 : p->nRPN = nRPN;
1307 348 : p->nRefs = nRefs;
1308 348 : p->nMode = nMode;
1309 348 : p->nError = nError;
1310 348 : p->bHyperLink = bHyperLink;
1311 : FormulaToken** pp;
1312 348 : if( nLen )
1313 : {
1314 348 : pp = p->pCode = new FormulaToken*[ nLen ];
1315 348 : memcpy( pp, pCode, nLen * sizeof( ScToken* ) );
1316 1198 : for( sal_uInt16 i = 0; i < nLen; i++, pp++ )
1317 : {
1318 850 : *pp = (*pp)->Clone();
1319 850 : (*pp)->IncRef();
1320 : }
1321 : }
1322 348 : if( nRPN )
1323 : {
1324 42 : pp = p->pRPN = new FormulaToken*[ nRPN ];
1325 42 : memcpy( pp, pRPN, nRPN * sizeof( ScToken* ) );
1326 116 : for( sal_uInt16 i = 0; i < nRPN; i++, pp++ )
1327 : {
1328 74 : FormulaToken* t = *pp;
1329 74 : if( t->GetRef() > 1 )
1330 : {
1331 66 : FormulaToken** p2 = pCode;
1332 66 : sal_uInt16 nIdx = 0xFFFF;
1333 142 : for( sal_uInt16 j = 0; j < nLen; j++, p2++ )
1334 : {
1335 142 : if( *p2 == t )
1336 : {
1337 66 : nIdx = j; break;
1338 : }
1339 : }
1340 66 : if( nIdx == 0xFFFF )
1341 0 : *pp = t->Clone();
1342 : else
1343 66 : *pp = p->pCode[ nIdx ];
1344 : }
1345 : else
1346 8 : *pp = t->Clone();
1347 74 : (*pp)->IncRef();
1348 : }
1349 : }
1350 348 : return p;
1351 : }
1352 :
1353 19047 : FormulaToken* ScTokenArray::AddRawToken( const ScRawToken& r )
1354 : {
1355 19047 : return Add( r.CreateToken() );
1356 : }
1357 :
1358 : // Utility function to ensure that there is strict alternation of values and
1359 : // seperators.
1360 : static bool
1361 43 : checkArraySep( bool & bPrevWasSep, bool bNewVal )
1362 : {
1363 43 : bool bResult = (bPrevWasSep == bNewVal);
1364 43 : bPrevWasSep = bNewVal;
1365 43 : return bResult;
1366 : }
1367 :
1368 5 : FormulaToken* ScTokenArray::MergeArray( )
1369 : {
1370 5 : int nCol = -1, nRow = 0;
1371 5 : int i, nPrevRowSep = -1, nStart = 0;
1372 5 : bool bPrevWasSep = false; // top of stack is ocArrayClose
1373 : FormulaToken* t;
1374 5 : bool bNumeric = false; // numeric value encountered in current element
1375 :
1376 : // (1) Iterate from the end to the start to find matrix dims
1377 : // and do basic validation.
1378 53 : for ( i = nLen ; i-- > nStart ; )
1379 : {
1380 43 : t = pCode[i];
1381 43 : switch ( t->GetOpCode() )
1382 : {
1383 : case ocPush :
1384 19 : if( checkArraySep( bPrevWasSep, false ) )
1385 : {
1386 0 : return NULL;
1387 : }
1388 :
1389 : // no references or nested arrays
1390 19 : if ( t->GetType() != svDouble && t->GetType() != svString )
1391 : {
1392 0 : return NULL;
1393 : }
1394 19 : bNumeric = (t->GetType() == svDouble);
1395 19 : break;
1396 :
1397 : case ocMissing :
1398 : case ocTrue :
1399 : case ocFalse :
1400 0 : if( checkArraySep( bPrevWasSep, false ) )
1401 : {
1402 0 : return NULL;
1403 : }
1404 0 : bNumeric = false;
1405 0 : break;
1406 :
1407 : case ocArrayColSep :
1408 : case ocSep :
1409 12 : if( checkArraySep( bPrevWasSep, true ) )
1410 : {
1411 0 : return NULL;
1412 : }
1413 12 : bNumeric = false;
1414 12 : break;
1415 :
1416 : case ocArrayClose :
1417 : // not possible with the , but check just in case
1418 : // something changes in the future
1419 5 : if( i != (nLen-1))
1420 : {
1421 0 : return NULL;
1422 : }
1423 :
1424 5 : if( checkArraySep( bPrevWasSep, true ) )
1425 : {
1426 0 : return NULL;
1427 : }
1428 :
1429 5 : nPrevRowSep = i;
1430 5 : bNumeric = false;
1431 5 : break;
1432 :
1433 : case ocArrayOpen :
1434 5 : nStart = i; // stop iteration
1435 : // fall through to ArrayRowSep
1436 :
1437 : case ocArrayRowSep :
1438 7 : if( checkArraySep( bPrevWasSep, true ) )
1439 : {
1440 0 : return NULL;
1441 : }
1442 :
1443 7 : if( nPrevRowSep < 0 || // missing ocArrayClose
1444 : ((nPrevRowSep - i) % 2) == 1) // no complex elements
1445 : {
1446 0 : return NULL;
1447 : }
1448 :
1449 7 : if( nCol < 0 )
1450 : {
1451 5 : nCol = (nPrevRowSep - i) / 2;
1452 : }
1453 2 : else if( (nPrevRowSep - i)/2 != nCol) // irregular array
1454 : {
1455 0 : return NULL;
1456 : }
1457 :
1458 7 : nPrevRowSep = i;
1459 7 : nRow++;
1460 7 : bNumeric = false;
1461 7 : break;
1462 :
1463 : case ocNegSub :
1464 : case ocAdd :
1465 : // negation or unary plus must precede numeric value
1466 0 : if( !bNumeric )
1467 : {
1468 0 : return NULL;
1469 : }
1470 0 : --nPrevRowSep; // shorten this row by 1
1471 0 : bNumeric = false; // one level only, no --42
1472 0 : break;
1473 :
1474 : case ocSpaces :
1475 : // ignore spaces
1476 0 : --nPrevRowSep; // shorten this row by 1
1477 0 : break;
1478 :
1479 : default :
1480 : // no functions or operators
1481 0 : return NULL;
1482 : }
1483 : }
1484 5 : if( nCol <= 0 || nRow <= 0 )
1485 0 : return NULL;
1486 :
1487 5 : int nSign = 1;
1488 5 : ScMatrix* pArray = new ScMatrix(nCol, nRow, 0.0);
1489 48 : for ( i = nStart, nCol = 0, nRow = 0 ; i < nLen ; i++ )
1490 : {
1491 43 : t = pCode[i];
1492 :
1493 43 : switch ( t->GetOpCode() )
1494 : {
1495 : case ocPush :
1496 19 : if ( t->GetType() == svDouble )
1497 : {
1498 19 : pArray->PutDouble( t->GetDouble() * nSign, nCol, nRow );
1499 19 : nSign = 1;
1500 : }
1501 0 : else if ( t->GetType() == svString )
1502 : {
1503 0 : pArray->PutString( t->GetString(), nCol, nRow );
1504 : }
1505 19 : break;
1506 :
1507 : case ocMissing :
1508 0 : pArray->PutEmpty( nCol, nRow );
1509 0 : break;
1510 :
1511 : case ocTrue :
1512 0 : pArray->PutBoolean( true, nCol, nRow );
1513 0 : break;
1514 :
1515 : case ocFalse :
1516 0 : pArray->PutBoolean( false, nCol, nRow );
1517 0 : break;
1518 :
1519 : case ocArrayColSep :
1520 : case ocSep :
1521 12 : nCol++;
1522 12 : break;
1523 :
1524 : case ocArrayRowSep :
1525 2 : nRow++; nCol = 0;
1526 2 : break;
1527 :
1528 : case ocNegSub :
1529 0 : nSign = -nSign;
1530 0 : break;
1531 :
1532 : default :
1533 10 : break;
1534 : }
1535 43 : pCode[i] = NULL;
1536 43 : t->DecRef();
1537 : }
1538 5 : nLen = sal_uInt16( nStart );
1539 5 : return AddMatrix( pArray );
1540 : }
1541 :
1542 :
1543 0 : FormulaToken* ScTokenArray::MergeRangeReference( const ScAddress & rPos )
1544 : {
1545 0 : if (!pCode || !nLen)
1546 0 : return NULL;
1547 0 : sal_uInt16 nIdx = nLen;
1548 : FormulaToken *p1, *p2, *p3; // ref, ocRange, ref
1549 : // The actual types are checked in ExtendRangeReference().
1550 0 : if (((p3 = PeekPrev(nIdx)) != 0) &&
1551 0 : (((p2 = PeekPrev(nIdx)) != 0) && p2->GetOpCode() == ocRange) &&
1552 0 : ((p1 = PeekPrev(nIdx)) != 0))
1553 : {
1554 0 : FormulaTokenRef p = ScToken::ExtendRangeReference( *p1, *p3, rPos, true);
1555 0 : if (p)
1556 : {
1557 0 : p->IncRef();
1558 0 : p1->DecRef();
1559 0 : p2->DecRef();
1560 0 : p3->DecRef();
1561 0 : nLen -= 2;
1562 0 : pCode[ nLen-1 ] = p.get();
1563 0 : nRefs--;
1564 0 : }
1565 : }
1566 0 : return pCode[ nLen-1 ];
1567 : }
1568 :
1569 19013 : FormulaToken* ScTokenArray::AddOpCode( OpCode e )
1570 : {
1571 19013 : ScRawToken t;
1572 19013 : t.SetOpCode( e );
1573 19013 : return AddRawToken( t );
1574 : }
1575 :
1576 4439 : FormulaToken* ScTokenArray::AddSingleReference( const ScSingleRefData& rRef )
1577 : {
1578 4439 : return Add( new ScSingleRefToken( rRef ) );
1579 : }
1580 :
1581 28 : FormulaToken* ScTokenArray::AddMatrixSingleReference( const ScSingleRefData& rRef )
1582 : {
1583 28 : return Add( new ScSingleRefToken( rRef, ocMatRef ) );
1584 : }
1585 :
1586 2151 : FormulaToken* ScTokenArray::AddDoubleReference( const ScComplexRefData& rRef )
1587 : {
1588 2151 : return Add( new ScDoubleRefToken( rRef ) );
1589 : }
1590 :
1591 7 : FormulaToken* ScTokenArray::AddMatrix( const ScMatrixRef& p )
1592 : {
1593 7 : return Add( new ScMatrixToken( p ) );
1594 : }
1595 :
1596 111 : FormulaToken* ScTokenArray::AddRangeName( sal_uInt16 n, bool bGlobal )
1597 : {
1598 111 : return Add( new FormulaIndexToken( ocName, n, bGlobal));
1599 : }
1600 :
1601 0 : FormulaToken* ScTokenArray::AddDBRange( sal_uInt16 n )
1602 : {
1603 0 : return Add( new FormulaIndexToken( ocDBArea, n));
1604 : }
1605 :
1606 0 : FormulaToken* ScTokenArray::AddExternalName( sal_uInt16 nFileId, const String& rName )
1607 : {
1608 0 : return Add( new ScExternalNameToken(nFileId, rName) );
1609 : }
1610 :
1611 0 : FormulaToken* ScTokenArray::AddExternalSingleReference( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef )
1612 : {
1613 0 : return Add( new ScExternalSingleRefToken(nFileId, rTabName, rRef) );
1614 : }
1615 :
1616 0 : FormulaToken* ScTokenArray::AddExternalDoubleReference( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef )
1617 : {
1618 0 : return Add( new ScExternalDoubleRefToken(nFileId, rTabName, rRef) );
1619 : }
1620 :
1621 0 : FormulaToken* ScTokenArray::AddColRowName( const ScSingleRefData& rRef )
1622 : {
1623 0 : return Add( new ScSingleRefToken( rRef, ocColRowName ) );
1624 : }
1625 :
1626 0 : bool ScTokenArray::GetAdjacentExtendOfOuterFuncRefs( SCCOLROW& nExtend,
1627 : const ScAddress& rPos, ScDirection eDir )
1628 : {
1629 0 : SCCOL nCol = 0;
1630 0 : SCROW nRow = 0;
1631 0 : switch ( eDir )
1632 : {
1633 : case DIR_BOTTOM :
1634 0 : if ( rPos.Row() < MAXROW )
1635 0 : nRow = (nExtend = rPos.Row()) + 1;
1636 : else
1637 0 : return false;
1638 0 : break;
1639 : case DIR_RIGHT :
1640 0 : if ( rPos.Col() < MAXCOL )
1641 0 : nCol = static_cast<SCCOL>(nExtend = rPos.Col()) + 1;
1642 : else
1643 0 : return false;
1644 0 : break;
1645 : case DIR_TOP :
1646 0 : if ( rPos.Row() > 0 )
1647 0 : nRow = (nExtend = rPos.Row()) - 1;
1648 : else
1649 0 : return false;
1650 0 : break;
1651 : case DIR_LEFT :
1652 0 : if ( rPos.Col() > 0 )
1653 0 : nCol = static_cast<SCCOL>(nExtend = rPos.Col()) - 1;
1654 : else
1655 0 : return false;
1656 0 : break;
1657 : default:
1658 : OSL_FAIL( "unknown Direction" );
1659 0 : return false;
1660 : }
1661 0 : if ( pRPN && nRPN )
1662 : {
1663 0 : FormulaToken* t = pRPN[nRPN-1];
1664 0 : if ( t->GetType() == svByte )
1665 : {
1666 0 : sal_uInt8 nParamCount = t->GetByte();
1667 0 : if ( nParamCount && nRPN > nParamCount )
1668 : {
1669 0 : bool bRet = false;
1670 0 : sal_uInt16 nParam = nRPN - nParamCount - 1;
1671 0 : for ( ; nParam < nRPN-1; nParam++ )
1672 : {
1673 0 : FormulaToken* p = pRPN[nParam];
1674 0 : switch ( p->GetType() )
1675 : {
1676 : case svSingleRef :
1677 : {
1678 0 : ScSingleRefData& rRef = static_cast<ScToken*>(p)->GetSingleRef();
1679 0 : rRef.CalcAbsIfRel( rPos );
1680 0 : switch ( eDir )
1681 : {
1682 : case DIR_BOTTOM :
1683 0 : if ( rRef.nRow == nRow
1684 : && rRef.nRow > nExtend )
1685 : {
1686 0 : nExtend = rRef.nRow;
1687 0 : bRet = true;
1688 : }
1689 0 : break;
1690 : case DIR_RIGHT :
1691 0 : if ( rRef.nCol == nCol
1692 : && static_cast<SCCOLROW>(rRef.nCol)
1693 : > nExtend )
1694 : {
1695 0 : nExtend = rRef.nCol;
1696 0 : bRet = true;
1697 : }
1698 0 : break;
1699 : case DIR_TOP :
1700 0 : if ( rRef.nRow == nRow
1701 : && rRef.nRow < nExtend )
1702 : {
1703 0 : nExtend = rRef.nRow;
1704 0 : bRet = true;
1705 : }
1706 0 : break;
1707 : case DIR_LEFT :
1708 0 : if ( rRef.nCol == nCol
1709 : && static_cast<SCCOLROW>(rRef.nCol)
1710 : < nExtend )
1711 : {
1712 0 : nExtend = rRef.nCol;
1713 0 : bRet = true;
1714 : }
1715 0 : break;
1716 : }
1717 : }
1718 0 : break;
1719 : case svDoubleRef :
1720 : {
1721 0 : ScComplexRefData& rRef = static_cast<ScToken*>(p)->GetDoubleRef();
1722 0 : rRef.CalcAbsIfRel( rPos );
1723 0 : switch ( eDir )
1724 : {
1725 : case DIR_BOTTOM :
1726 0 : if ( rRef.Ref1.nRow == nRow
1727 : && rRef.Ref2.nRow > nExtend )
1728 : {
1729 0 : nExtend = rRef.Ref2.nRow;
1730 0 : bRet = true;
1731 : }
1732 0 : break;
1733 : case DIR_RIGHT :
1734 0 : if ( rRef.Ref1.nCol == nCol &&
1735 : static_cast<SCCOLROW>(rRef.Ref2.nCol)
1736 : > nExtend )
1737 : {
1738 0 : nExtend = rRef.Ref2.nCol;
1739 0 : bRet = true;
1740 : }
1741 0 : break;
1742 : case DIR_TOP :
1743 0 : if ( rRef.Ref2.nRow == nRow
1744 : && rRef.Ref1.nRow < nExtend )
1745 : {
1746 0 : nExtend = rRef.Ref1.nRow;
1747 0 : bRet = true;
1748 : }
1749 0 : break;
1750 : case DIR_LEFT :
1751 0 : if ( rRef.Ref2.nCol == nCol &&
1752 : static_cast<SCCOLROW>(rRef.Ref1.nCol)
1753 : < nExtend )
1754 : {
1755 0 : nExtend = rRef.Ref1.nCol;
1756 0 : bRet = true;
1757 : }
1758 0 : break;
1759 : }
1760 : }
1761 0 : break;
1762 : default:
1763 : {
1764 : // added to avoid warnings
1765 : }
1766 : } // switch
1767 : } // for
1768 0 : return bRet;
1769 : }
1770 : }
1771 : }
1772 0 : return false;
1773 : }
1774 :
1775 :
1776 0 : void ScTokenArray::ReadjustRelative3DReferences( const ScAddress& rOldPos,
1777 : const ScAddress& rNewPos )
1778 : {
1779 0 : for ( sal_uInt16 j=0; j<nLen; ++j )
1780 : {
1781 0 : switch ( pCode[j]->GetType() )
1782 : {
1783 : case svDoubleRef :
1784 : {
1785 0 : ScSingleRefData& rRef2 = static_cast<ScToken*>(pCode[j])->GetSingleRef2();
1786 : // Also adjust if the reference is of the form Sheet1.A2:A3
1787 0 : if ( rRef2.IsFlag3D() || static_cast<ScToken*>(pCode[j])->GetSingleRef().IsFlag3D() )
1788 : {
1789 0 : rRef2.CalcAbsIfRel( rOldPos );
1790 0 : rRef2.CalcRelFromAbs( rNewPos );
1791 : }
1792 : }
1793 : //! fallthru
1794 : case svSingleRef :
1795 : {
1796 0 : ScSingleRefData& rRef1 = static_cast<ScToken*>(pCode[j])->GetSingleRef();
1797 0 : if ( rRef1.IsFlag3D() )
1798 : {
1799 0 : rRef1.CalcAbsIfRel( rOldPos );
1800 0 : rRef1.CalcRelFromAbs( rNewPos );
1801 : }
1802 : }
1803 0 : break;
1804 : default:
1805 : {
1806 : // added to avoid warnings
1807 : }
1808 : }
1809 : }
1810 0 : }
1811 :
1812 : namespace {
1813 :
1814 3 : void GetExternalTableData(const ScDocument* pOldDoc, const ScDocument* pNewDoc, const SCTAB nTab, rtl::OUString& rTabName, sal_uInt16& rFileId)
1815 : {
1816 3 : rtl::OUString aFileName = pOldDoc->GetFileURL();;
1817 3 : rFileId = pNewDoc->GetExternalRefManager()->getExternalFileId(aFileName);
1818 3 : rTabName = pOldDoc->GetCopyTabName(nTab);
1819 3 : if (rTabName.isEmpty())
1820 0 : pOldDoc->GetName(nTab, rTabName);
1821 3 : }
1822 :
1823 11 : bool IsInCopyRange( const ScRange& rRange, const ScDocument* pClipDoc )
1824 : {
1825 11 : ScClipParam& rClipParam = const_cast<ScDocument*>(pClipDoc)->GetClipParam();
1826 11 : return rClipParam.maRanges.In(rRange);
1827 : }
1828 :
1829 20 : bool SkipReference(ScToken* pToken, const ScAddress& rPos, const ScDocument* pOldDoc, bool bRangeName, bool bCheckCopyArea)
1830 : {
1831 20 : ScRange aRange;
1832 :
1833 20 : pToken->CalcAbsIfRel(rPos);
1834 20 : if (!ScRefTokenHelper::getRangeFromToken(aRange, pToken))
1835 0 : return true;
1836 :
1837 20 : if (bRangeName && aRange.aStart.Tab() == rPos.Tab())
1838 : {
1839 0 : switch (pToken->GetType())
1840 : {
1841 : case svDoubleRef:
1842 : {
1843 0 : ScSingleRefData& rRef = pToken->GetSingleRef2();
1844 0 : if (rRef.IsColRel() || rRef.IsRowRel())
1845 0 : return true;
1846 : } // fall through
1847 : case svSingleRef:
1848 : {
1849 0 : ScSingleRefData& rRef = pToken->GetSingleRef();
1850 0 : if (rRef.IsColRel() || rRef.IsRowRel())
1851 0 : return true;
1852 : }
1853 0 : break;
1854 : default:
1855 0 : break;
1856 : }
1857 : }
1858 :
1859 20 : if (bCheckCopyArea && IsInCopyRange(aRange, pOldDoc))
1860 6 : return true;
1861 :
1862 14 : return false;
1863 : }
1864 :
1865 3 : void AdjustSingleRefData( ScSingleRefData& rRef, const ScAddress& rOldPos, const ScAddress& rNewPos)
1866 : {
1867 3 : SCsCOL nCols = rNewPos.Col() - rOldPos.Col();
1868 3 : SCsROW nRows = rNewPos.Row() - rOldPos.Row();
1869 3 : SCsTAB nTabs = rNewPos.Tab() - rOldPos.Tab();
1870 :
1871 3 : if (!rRef.IsColRel())
1872 3 : rRef.nCol += nCols;
1873 :
1874 3 : if (!rRef.IsRowRel())
1875 3 : rRef.nRow += nRows;
1876 :
1877 3 : if (!rRef.IsTabRel())
1878 1 : rRef.nTab += nTabs;
1879 3 : }
1880 :
1881 : }
1882 :
1883 6 : void ScTokenArray::ReadjustAbsolute3DReferences( const ScDocument* pOldDoc, const ScDocument* pNewDoc, const ScAddress& rPos, bool bRangeName )
1884 : {
1885 17 : for ( sal_uInt16 j=0; j<nLen; ++j )
1886 : {
1887 11 : switch ( pCode[j]->GetType() )
1888 : {
1889 : case svDoubleRef :
1890 : {
1891 0 : if (SkipReference(static_cast<ScToken*>(pCode[j]), rPos, pOldDoc, bRangeName, true))
1892 0 : continue;
1893 :
1894 0 : ScComplexRefData& rRef = static_cast<ScToken*>(pCode[j])->GetDoubleRef();
1895 0 : ScSingleRefData& rRef2 = rRef.Ref2;
1896 0 : ScSingleRefData& rRef1 = rRef.Ref1;
1897 :
1898 0 : if ( (rRef2.IsFlag3D() && !rRef2.IsTabRel()) || (rRef1.IsFlag3D() && !rRef1.IsTabRel()) )
1899 : {
1900 0 : rtl::OUString aTabName;
1901 : sal_uInt16 nFileId;
1902 0 : GetExternalTableData(pOldDoc, pNewDoc, rRef1.nTab, aTabName, nFileId);
1903 0 : pCode[j]->DecRef();
1904 0 : ScExternalDoubleRefToken* pToken = new ScExternalDoubleRefToken(nFileId, aTabName, rRef);
1905 0 : pToken->IncRef();
1906 0 : pCode[j] = pToken;
1907 : }
1908 : }
1909 0 : break;
1910 : case svSingleRef :
1911 : {
1912 7 : if (SkipReference(static_cast<ScToken*>(pCode[j]), rPos, pOldDoc, bRangeName, true))
1913 3 : continue;
1914 :
1915 4 : ScSingleRefData& rRef = static_cast<ScToken*>(pCode[j])->GetSingleRef();
1916 :
1917 4 : if ( rRef.IsFlag3D() && !rRef.IsTabRel() )
1918 : {
1919 3 : rtl::OUString aTabName;
1920 : sal_uInt16 nFileId;
1921 3 : GetExternalTableData(pOldDoc, pNewDoc, rRef.nTab, aTabName, nFileId);
1922 : //replace with ScExternalSingleRefToken and adjust references
1923 3 : pCode[j]->DecRef();
1924 3 : ScExternalSingleRefToken* pToken = new ScExternalSingleRefToken(nFileId, aTabName, rRef);
1925 3 : pToken->IncRef();
1926 3 : pCode[j] = pToken;
1927 : }
1928 : }
1929 4 : break;
1930 : default:
1931 : {
1932 : // added to avoid warnings
1933 : }
1934 : }
1935 : }
1936 6 : }
1937 :
1938 14 : void ScTokenArray::AdjustAbsoluteRefs( const ScDocument* pOldDoc, const ScAddress& rOldPos, const ScAddress& rNewPos, bool bRangeName, bool bCheckCopyRange)
1939 : {
1940 59 : for ( sal_uInt16 j=0; j<nLen; ++j )
1941 : {
1942 45 : switch ( pCode[j]->GetType() )
1943 : {
1944 : case svDoubleRef :
1945 : {
1946 3 : if (!SkipReference(static_cast<ScToken*>(pCode[j]), rOldPos, pOldDoc, false, bCheckCopyRange))
1947 3 : continue;
1948 :
1949 0 : ScComplexRefData& rRef = static_cast<ScToken*>(pCode[j])->GetDoubleRef();
1950 0 : ScSingleRefData& rRef2 = rRef.Ref2;
1951 0 : ScSingleRefData& rRef1 = rRef.Ref1;
1952 :
1953 : // for range names only adjust if all parts are absolute
1954 0 : if (!bRangeName || !(rRef1.IsColRel() || rRef1.IsRowRel() || rRef1.IsTabRel()))
1955 0 : AdjustSingleRefData( rRef1, rOldPos, rNewPos );
1956 0 : if (!bRangeName || !(rRef2.IsColRel() || rRef2.IsRowRel() || rRef2.IsTabRel()))
1957 0 : AdjustSingleRefData( rRef2, rOldPos, rNewPos );
1958 :
1959 : }
1960 0 : break;
1961 : case svSingleRef :
1962 : {
1963 10 : if (!SkipReference(static_cast<ScToken*>(pCode[j]), rOldPos, pOldDoc, false, bCheckCopyRange))
1964 7 : continue;
1965 :
1966 3 : ScSingleRefData& rRef = static_cast<ScToken*>(pCode[j])->GetSingleRef();
1967 :
1968 : // for range names only adjust if all parts are absolute
1969 3 : if (!bRangeName || !(rRef.IsColRel() || rRef.IsRowRel() || rRef.IsTabRel()))
1970 3 : AdjustSingleRefData( rRef, rOldPos, rNewPos );
1971 :
1972 :
1973 : }
1974 3 : break;
1975 : default:
1976 : {
1977 : // added to avoid warnings
1978 : }
1979 : }
1980 : }
1981 29 : }
1982 :
1983 :
1984 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|