sync master with lastest vba changes
[ooovba.git] / sc / source / ui / unoobj / tokenuno.cxx
blob0c76cdb6aa0adb8fe985cac79b1d030e9993b978
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tokenuno.cxx,v $
10 * $Revision: 1.6.108.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 #include "tokenuno.hxx"
36 #include <com/sun/star/sheet/ComplexReference.hpp>
37 #include <com/sun/star/sheet/ExternalReference.hpp>
38 #include <com/sun/star/sheet/ReferenceFlags.hpp>
39 #include <com/sun/star/sheet/AddressConvention.hpp>
40 #include <com/sun/star/table/CellAddress.hpp>
42 #include <svtools/itemprop.hxx>
44 #include "miscuno.hxx"
45 #include "convuno.hxx"
46 #include "unonames.hxx"
47 #include "unoguard.hxx"
48 #include "token.hxx"
49 #include "compiler.hxx"
50 #include "tokenarray.hxx"
51 #include "docsh.hxx"
52 #include "rangeseq.hxx"
53 #include "externalrefmgr.hxx"
54 using namespace formula;
56 using namespace com::sun::star;
58 //------------------------------------------------------------------------
60 const SfxItemPropertyMap* lcl_GetFormulaParserMap()
62 static SfxItemPropertyMap aFormulaParserMap_Impl[] =
64 {MAP_CHAR_LEN(SC_UNO_REFERENCEPOS), 0, &getCppuType((table::CellAddress*)0), 0, 0 },
65 {MAP_CHAR_LEN(SC_UNO_COMPILEFAP), 0, &getBooleanCppuType(), 0, 0 },
66 {MAP_CHAR_LEN(SC_UNO_COMPILEENGLISH), 0, &getBooleanCppuType(), 0, 0 },
67 {MAP_CHAR_LEN(SC_UNO_IGNORELEADING), 0, &getBooleanCppuType(), 0, 0 },
68 {MAP_CHAR_LEN(SC_UNO_FORMULACONVENTION), 0, &getCppuType(&sheet::AddressConvention::UNSPECIFIED), 0, 0 },
69 {MAP_CHAR_LEN(SC_UNO_OPCODEMAP), 0, &getCppuType((uno::Sequence< sheet::FormulaOpCodeMapEntry >*)0), 0, 0 },
70 {0,0,0,0,0,0}
72 return aFormulaParserMap_Impl;
75 SC_SIMPLE_SERVICE_INFO( ScFormulaParserObj, "ScFormulaParserObj", SC_SERVICENAME_FORMULAPARS )
77 //------------------------------------------------------------------------
79 ScFormulaParserObj::ScFormulaParserObj(ScDocShell* pDocSh) :
80 mpDocShell( pDocSh ),
81 mnConv( sheet::AddressConvention::UNSPECIFIED ),
82 mbEnglish( false ),
83 mbIgnoreSpaces( true ),
84 mbCompileFAP( false )
86 mpDocShell->GetDocument()->AddUnoObject(*this);
89 ScFormulaParserObj::~ScFormulaParserObj()
91 if (mpDocShell)
92 mpDocShell->GetDocument()->RemoveUnoObject(*this);
95 void ScFormulaParserObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
97 if ( rHint.ISA( SfxSimpleHint ) && ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
98 mpDocShell = NULL;
101 // XFormulaParser
103 void ScFormulaParserObj::SetCompilerFlags( ScCompiler& rCompiler ) const
105 static const formula::FormulaGrammar::AddressConvention aConvMap[] = {
106 formula::FormulaGrammar::CONV_OOO, // <- AddressConvention::OOO
107 formula::FormulaGrammar::CONV_XL_A1, // <- AddressConvention::XL_A1
108 formula::FormulaGrammar::CONV_XL_R1C1, // <- AddressConvention::XL_R1C1
109 formula::FormulaGrammar::CONV_XL_OOX, // <- AddressConvention::XL_OOX
110 formula::FormulaGrammar::CONV_LOTUS_A1 // <- AddressConvention::LOTUS_A1
112 static const sal_Int16 nConvMapCount = sizeof(aConvMap)/sizeof(aConvMap[0]);
114 // If mxOpCodeMap is not empty it overrides mbEnglish, and vice versa. We
115 // don't need to initialize things twice.
116 if (mxOpCodeMap.get())
117 rCompiler.SetFormulaLanguage( mxOpCodeMap );
118 else
120 sal_Int32 nFormulaLanguage = mbEnglish ?
121 sheet::FormulaLanguage::ENGLISH :
122 sheet::FormulaLanguage::NATIVE;
123 ScCompiler::OpCodeMapPtr xMap = rCompiler.GetOpCodeMap( nFormulaLanguage);
124 rCompiler.SetFormulaLanguage( xMap);
127 formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_UNSPECIFIED;
128 if (mnConv >= 0 && mnConv < nConvMapCount)
129 eConv = aConvMap[mnConv];
131 rCompiler.SetRefConvention( eConv );
133 rCompiler.SetCompileForFAP(mbCompileFAP);
135 rCompiler.SetExternalLinks( maExternalLinks);
138 uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( const rtl::OUString& aFormula )
139 throw (uno::RuntimeException)
141 ScUnoGuard aGuard;
142 uno::Sequence<sheet::FormulaToken> aRet;
144 if (mpDocShell)
146 ScDocument* pDoc = mpDocShell->GetDocument();
147 ScCompiler aCompiler( pDoc, maRefPos);
148 aCompiler.SetGrammar(pDoc->GetGrammar());
149 SetCompilerFlags( aCompiler );
151 ScTokenArray* pCode = aCompiler.CompileString( aFormula );
152 (void)ScTokenConversion::ConvertToTokenSequence( *pDoc, aRet, *pCode );
153 delete pCode;
156 return aRet;
159 rtl::OUString SAL_CALL ScFormulaParserObj::printFormula( const uno::Sequence<sheet::FormulaToken>& aTokens )
160 throw (uno::RuntimeException)
162 ScUnoGuard aGuard;
163 rtl::OUString aRet;
165 if (mpDocShell)
167 ScDocument* pDoc = mpDocShell->GetDocument();
168 ScTokenArray aCode;
169 (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aCode, aTokens );
170 ScCompiler aCompiler( pDoc, maRefPos, aCode);
171 aCompiler.SetGrammar(pDoc->GetGrammar());
172 SetCompilerFlags( aCompiler );
174 rtl::OUStringBuffer aBuffer;
175 aCompiler.CreateStringFromTokenArray( aBuffer );
176 aRet = aBuffer.makeStringAndClear();
179 return aRet;
182 // XPropertySet
184 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScFormulaParserObj::getPropertySetInfo()
185 throw(uno::RuntimeException)
187 ScUnoGuard aGuard;
188 static uno::Reference< beans::XPropertySetInfo > aRef(new SfxItemPropertySetInfo( lcl_GetFormulaParserMap() ));
189 return aRef;
192 void SAL_CALL ScFormulaParserObj::setPropertyValue(
193 const rtl::OUString& aPropertyName, const uno::Any& aValue )
194 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
195 lang::IllegalArgumentException, lang::WrappedTargetException,
196 uno::RuntimeException)
198 ScUnoGuard aGuard;
199 String aString(aPropertyName);
200 if ( aString.EqualsAscii( SC_UNO_REFERENCEPOS ) )
202 table::CellAddress aAddress;
203 aValue >>= aAddress;
204 ScUnoConversion::FillScAddress( maRefPos, aAddress );
205 } // if ( aString.EqualsAscii( SC_UNO_REFERENCEPOS ) )
206 else if ( aString.EqualsAscii( SC_UNO_COMPILEFAP ) )
208 aValue >>= mbCompileFAP;
210 else if ( aString.EqualsAscii( SC_UNO_COMPILEENGLISH ) )
212 bool bOldEnglish = mbEnglish;
213 if (aValue >>= mbEnglish)
215 // Need to recreate the symbol map to change English property
216 // because the map is const. So for performance reasons set
217 // CompileEnglish _before_ OpCodeMap!
218 if (mxOpCodeMap.get() && mbEnglish != bOldEnglish)
220 ScDocument* pDoc = mpDocShell->GetDocument();
221 ScCompiler aCompiler( pDoc, maRefPos);
222 aCompiler.SetGrammar(pDoc->GetGrammar());
223 mxOpCodeMap = aCompiler.CreateOpCodeMap( maOpCodeMapping, mbEnglish);
226 else
227 throw lang::IllegalArgumentException();
229 else if ( aString.EqualsAscii( SC_UNO_FORMULACONVENTION ) )
231 aValue >>= mnConv;
233 else if ( aString.EqualsAscii( SC_UNO_IGNORELEADING ) )
235 aValue >>= mbIgnoreSpaces;
237 else if ( aString.EqualsAscii( SC_UNO_OPCODEMAP ) )
239 if (aValue >>= maOpCodeMapping)
241 ScDocument* pDoc = mpDocShell->GetDocument();
242 ScCompiler aCompiler( pDoc, maRefPos);
243 aCompiler.SetGrammar(pDoc->GetGrammar());
244 mxOpCodeMap = aCompiler.CreateOpCodeMap( maOpCodeMapping, mbEnglish);
246 else
247 throw lang::IllegalArgumentException();
249 else if ( aString.EqualsAscii( SC_UNO_EXTERNALLINKS ) )
251 if (!(aValue >>= maExternalLinks))
252 throw lang::IllegalArgumentException();
254 else
255 throw beans::UnknownPropertyException();
258 uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const rtl::OUString& aPropertyName )
259 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
260 uno::RuntimeException)
262 ScUnoGuard aGuard;
263 uno::Any aRet;
264 String aString(aPropertyName);
265 if ( aString.EqualsAscii( SC_UNO_REFERENCEPOS ) )
267 table::CellAddress aAddress;
268 ScUnoConversion::FillApiAddress( aAddress, maRefPos );
269 aRet <<= aAddress;
271 else if ( aString.EqualsAscii( SC_UNO_COMPILEFAP ) )
273 aRet <<= mbCompileFAP;
275 else if ( aString.EqualsAscii( SC_UNO_COMPILEENGLISH ) )
277 aRet <<= mbEnglish;
279 else if ( aString.EqualsAscii( SC_UNO_FORMULACONVENTION ) )
281 aRet <<= mnConv;
283 else if ( aString.EqualsAscii( SC_UNO_IGNORELEADING ) )
285 aRet <<= mbIgnoreSpaces;
287 else if ( aString.EqualsAscii( SC_UNO_OPCODEMAP ) )
289 aRet <<= maOpCodeMapping;
291 else if ( aString.EqualsAscii( SC_UNO_EXTERNALLINKS ) )
293 aRet <<= maExternalLinks;
295 else
296 throw beans::UnknownPropertyException();
297 return aRet;
300 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFormulaParserObj )
302 //------------------------------------------------------------------------
304 void lcl_ExternalRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rRef )
306 rAPI.Column = rRef.nCol;
307 rAPI.Row = rRef.nRow;
308 rAPI.Sheet = 0;
309 rAPI.RelativeColumn = rRef.nRelCol;
310 rAPI.RelativeRow = rRef.nRelRow;
311 rAPI.RelativeSheet = 0;
313 sal_Int32 nFlags = 0;
314 if ( rRef.IsColRel() ) nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE;
315 if ( rRef.IsRowRel() ) nFlags |= sheet::ReferenceFlags::ROW_RELATIVE;
316 if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED;
317 if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED;
318 if ( rRef.IsFlag3D() ) nFlags |= sheet::ReferenceFlags::SHEET_3D;
319 if ( rRef.IsRelName() ) nFlags |= sheet::ReferenceFlags::RELATIVE_NAME;
320 rAPI.Flags = nFlags;
323 void lcl_SingleRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rRef )
325 rAPI.Column = rRef.nCol;
326 rAPI.Row = rRef.nRow;
327 rAPI.Sheet = rRef.nTab;
328 rAPI.RelativeColumn = rRef.nRelCol;
329 rAPI.RelativeRow = rRef.nRelRow;
330 rAPI.RelativeSheet = rRef.nRelTab;
332 sal_Int32 nFlags = 0;
333 if ( rRef.IsColRel() ) nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE;
334 if ( rRef.IsRowRel() ) nFlags |= sheet::ReferenceFlags::ROW_RELATIVE;
335 if ( rRef.IsTabRel() ) nFlags |= sheet::ReferenceFlags::SHEET_RELATIVE;
336 if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED;
337 if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED;
338 if ( rRef.IsTabDeleted() ) nFlags |= sheet::ReferenceFlags::SHEET_DELETED;
339 if ( rRef.IsFlag3D() ) nFlags |= sheet::ReferenceFlags::SHEET_3D;
340 if ( rRef.IsRelName() ) nFlags |= sheet::ReferenceFlags::RELATIVE_NAME;
341 rAPI.Flags = nFlags;
344 // static
345 bool ScTokenConversion::ConvertToTokenArray( ScDocument& rDoc,
346 ScTokenArray& rTokenArray, const uno::Sequence<sheet::FormulaToken>& rSequence )
348 return !rTokenArray.Fill(rSequence,rDoc.GetExternalRefManager());
351 // static
352 bool ScTokenConversion::ConvertToTokenSequence( ScDocument& rDoc,
353 uno::Sequence<sheet::FormulaToken>& rSequence, const ScTokenArray& rTokenArray )
355 bool bError = false;
357 sal_Int32 nLen = static_cast<sal_Int32>(rTokenArray.GetLen());
358 formula::FormulaToken** pTokens = rTokenArray.GetArray();
359 if ( pTokens )
361 rSequence.realloc(nLen);
362 for (sal_Int32 nPos=0; nPos<nLen; nPos++)
364 const formula::FormulaToken& rToken = *pTokens[nPos];
365 sheet::FormulaToken& rAPI = rSequence[nPos];
367 OpCode eOpCode = rToken.GetOpCode();
368 // eOpCode may be changed in the following switch/case
369 switch ( rToken.GetType() )
371 case svByte:
372 // Only the count of spaces is stored as "long". Parameter count is ignored.
373 if ( eOpCode == ocSpaces )
374 rAPI.Data <<= (sal_Int32) rToken.GetByte();
375 else
376 rAPI.Data.clear(); // no data
377 break;
378 case formula::svDouble:
379 rAPI.Data <<= rToken.GetDouble();
380 break;
381 case formula::svString:
382 rAPI.Data <<= rtl::OUString( rToken.GetString() );
383 break;
384 case svExternal:
385 // Function name is stored as string.
386 // Byte (parameter count) is ignored.
387 rAPI.Data <<= rtl::OUString( rToken.GetExternal() );
388 break;
389 case svSingleRef:
391 sheet::SingleReference aSingleRef;
392 lcl_SingleRefToApi( aSingleRef, static_cast<const ScToken&>(rToken).GetSingleRef() );
393 rAPI.Data <<= aSingleRef;
395 break;
396 case formula::svDoubleRef:
398 sheet::ComplexReference aCompRef;
399 lcl_SingleRefToApi( aCompRef.Reference1, static_cast<const ScToken&>(rToken).GetSingleRef() );
400 lcl_SingleRefToApi( aCompRef.Reference2, static_cast<const ScToken&>(rToken).GetSingleRef2() );
401 rAPI.Data <<= aCompRef;
403 break;
404 case svIndex:
405 rAPI.Data <<= static_cast<sal_Int32>( rToken.GetIndex() );
406 break;
407 case svMatrix:
408 if (!ScRangeToSequence::FillMixedArray( rAPI.Data, static_cast<const ScToken&>(rToken).GetMatrix(), true))
409 rAPI.Data.clear();
410 break;
411 case svExternalSingleRef:
413 sheet::SingleReference aSingleRef;
414 lcl_ExternalRefToApi( aSingleRef, static_cast<const ScToken&>(rToken).GetSingleRef() );
415 size_t nCacheId;
416 rDoc.GetExternalRefManager()->getCacheTable( rToken.GetIndex(), rToken.GetString(), false, &nCacheId );
417 aSingleRef.Sheet = static_cast< sal_Int32 >( nCacheId );
418 sheet::ExternalReference aExtRef;
419 aExtRef.Index = rToken.GetIndex();
420 aExtRef.Reference <<= aSingleRef;
421 rAPI.Data <<= aExtRef;
422 eOpCode = ocPush;
424 break;
425 case svExternalDoubleRef:
427 sheet::ComplexReference aComplRef;
428 lcl_ExternalRefToApi( aComplRef.Reference1, static_cast<const ScToken&>(rToken).GetSingleRef() );
429 lcl_ExternalRefToApi( aComplRef.Reference2, static_cast<const ScToken&>(rToken).GetSingleRef2() );
430 size_t nCacheId;
431 rDoc.GetExternalRefManager()->getCacheTable( rToken.GetIndex(), rToken.GetString(), false, &nCacheId );
432 aComplRef.Reference1.Sheet = static_cast< sal_Int32 >( nCacheId );
433 // NOTE: This assumes that cached sheets are in consecutive order!
434 aComplRef.Reference2.Sheet = aComplRef.Reference1.Sheet + (static_cast<const ScToken&>(rToken).GetSingleRef2().nTab - static_cast<const ScToken&>(rToken).GetSingleRef().nTab);
435 sheet::ExternalReference aExtRef;
436 aExtRef.Index = rToken.GetIndex();
437 aExtRef.Reference <<= aComplRef;
438 rAPI.Data <<= aExtRef;
439 eOpCode = ocPush;
441 break;
442 case svExternalName:
444 sheet::ExternalReference aExtRef;
445 aExtRef.Index = rToken.GetIndex();
446 aExtRef.Reference <<= ::rtl::OUString( rToken.GetString() );
447 rAPI.Data <<= aExtRef;
448 eOpCode = ocPush;
450 break;
451 default:
452 DBG_ERROR1( "ScTokenConversion::ConvertToTokenSequence: unhandled token type SvStackVar %d", rToken.GetType());
453 case svSep: // occurs with ocSep, ocOpen, ocClose, ocArray*
454 case svJump: // occurs with ocIf, ocChose
455 case svMissing: // occurs with ocMissing
456 rAPI.Data.clear(); // no data
458 rAPI.OpCode = static_cast<sal_Int32>(eOpCode); //! assuming equal values for the moment
461 else
462 rSequence.realloc(0);
464 return !bError;
466 // -----------------------------------------------------------------------------
467 ScFormulaOpCodeMapperObj::ScFormulaOpCodeMapperObj(::std::auto_ptr<formula::FormulaCompiler> _pCompiler)
468 : formula::FormulaOpCodeMapperObj(_pCompiler)