update dev300-m58
[ooovba.git] / sc / source / ui / unoobj / tokenuno.cxx
blobe6e194d7eb75c8922701a904ce84c31a9b5f92eb
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"
55 using namespace ::formula;
56 using namespace ::com::sun::star;
58 // ============================================================================
60 const SfxItemPropertyMapEntry* lcl_GetFormulaParserMap()
62 static SfxItemPropertyMapEntry aFormulaParserMap_Impl[] =
64 {MAP_CHAR_LEN(SC_UNO_COMPILEFAP), 0, &getBooleanCppuType(), 0, 0 },
65 {MAP_CHAR_LEN(SC_UNO_COMPILEENGLISH), 0, &getBooleanCppuType(), 0, 0 },
66 {MAP_CHAR_LEN(SC_UNO_IGNORELEADING), 0, &getBooleanCppuType(), 0, 0 },
67 {MAP_CHAR_LEN(SC_UNO_FORMULACONVENTION), 0, &getCppuType(&sheet::AddressConvention::UNSPECIFIED), 0, 0 },
68 {MAP_CHAR_LEN(SC_UNO_OPCODEMAP), 0, &getCppuType((uno::Sequence< sheet::FormulaOpCodeMapEntry >*)0), 0, 0 },
69 {0,0,0,0,0,0}
71 return aFormulaParserMap_Impl;
74 SC_SIMPLE_SERVICE_INFO( ScFormulaParserObj, "ScFormulaParserObj", SC_SERVICENAME_FORMULAPARS )
76 // ============================================================================
78 ScFormulaParserObj::ScFormulaParserObj(ScDocShell* pDocSh) :
79 mpDocShell( pDocSh ),
80 mnConv( sheet::AddressConvention::UNSPECIFIED ),
81 mbEnglish( false ),
82 mbIgnoreSpaces( true ),
83 mbCompileFAP( false )
85 mpDocShell->GetDocument()->AddUnoObject(*this);
88 ScFormulaParserObj::~ScFormulaParserObj()
90 if (mpDocShell)
91 mpDocShell->GetDocument()->RemoveUnoObject(*this);
94 void ScFormulaParserObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
96 if ( rHint.ISA( SfxSimpleHint ) && ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
97 mpDocShell = NULL;
100 // XFormulaParser
102 void ScFormulaParserObj::SetCompilerFlags( ScCompiler& rCompiler ) const
104 static const formula::FormulaGrammar::AddressConvention aConvMap[] = {
105 formula::FormulaGrammar::CONV_OOO, // <- AddressConvention::OOO
106 formula::FormulaGrammar::CONV_XL_A1, // <- AddressConvention::XL_A1
107 formula::FormulaGrammar::CONV_XL_R1C1, // <- AddressConvention::XL_R1C1
108 formula::FormulaGrammar::CONV_XL_OOX, // <- AddressConvention::XL_OOX
109 formula::FormulaGrammar::CONV_LOTUS_A1 // <- AddressConvention::LOTUS_A1
111 static const sal_Int16 nConvMapCount = sizeof(aConvMap)/sizeof(aConvMap[0]);
113 // If mxOpCodeMap is not empty it overrides mbEnglish, and vice versa. We
114 // don't need to initialize things twice.
115 if (mxOpCodeMap.get())
116 rCompiler.SetFormulaLanguage( mxOpCodeMap );
117 else
119 sal_Int32 nFormulaLanguage = mbEnglish ?
120 sheet::FormulaLanguage::ENGLISH :
121 sheet::FormulaLanguage::NATIVE;
122 ScCompiler::OpCodeMapPtr xMap = rCompiler.GetOpCodeMap( nFormulaLanguage);
123 rCompiler.SetFormulaLanguage( xMap);
126 formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_UNSPECIFIED;
127 if (mnConv >= 0 && mnConv < nConvMapCount)
128 eConv = aConvMap[mnConv];
130 rCompiler.SetRefConvention( eConv );
132 rCompiler.SetCompileForFAP(mbCompileFAP);
134 rCompiler.SetExternalLinks( maExternalLinks);
137 uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula(
138 const rtl::OUString& aFormula, const table::CellAddress& rReferencePos )
139 throw (uno::RuntimeException)
141 ScUnoGuard aGuard;
142 uno::Sequence<sheet::FormulaToken> aRet;
144 if (mpDocShell)
146 ScAddress aRefPos( ScAddress::UNINITIALIZED );
147 ScUnoConversion::FillScAddress( aRefPos, rReferencePos );
148 ScDocument* pDoc = mpDocShell->GetDocument();
149 ScCompiler aCompiler( pDoc, aRefPos);
150 aCompiler.SetGrammar(pDoc->GetGrammar());
151 SetCompilerFlags( aCompiler );
153 ScTokenArray* pCode = aCompiler.CompileString( aFormula );
154 (void)ScTokenConversion::ConvertToTokenSequence( *pDoc, aRet, *pCode );
155 delete pCode;
158 return aRet;
161 rtl::OUString SAL_CALL ScFormulaParserObj::printFormula(
162 const uno::Sequence<sheet::FormulaToken>& aTokens, const table::CellAddress& rReferencePos )
163 throw (uno::RuntimeException)
165 ScUnoGuard aGuard;
166 rtl::OUString aRet;
168 if (mpDocShell)
170 ScDocument* pDoc = mpDocShell->GetDocument();
171 ScTokenArray aCode;
172 (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aCode, aTokens );
173 ScAddress aRefPos( ScAddress::UNINITIALIZED );
174 ScUnoConversion::FillScAddress( aRefPos, rReferencePos );
175 ScCompiler aCompiler( pDoc, aRefPos, aCode);
176 aCompiler.SetGrammar(pDoc->GetGrammar());
177 SetCompilerFlags( aCompiler );
179 rtl::OUStringBuffer aBuffer;
180 aCompiler.CreateStringFromTokenArray( aBuffer );
181 aRet = aBuffer.makeStringAndClear();
184 return aRet;
187 // XPropertySet
189 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScFormulaParserObj::getPropertySetInfo()
190 throw(uno::RuntimeException)
192 ScUnoGuard aGuard;
193 static uno::Reference< beans::XPropertySetInfo > aRef(new SfxItemPropertySetInfo( lcl_GetFormulaParserMap() ));
194 return aRef;
197 void SAL_CALL ScFormulaParserObj::setPropertyValue(
198 const rtl::OUString& aPropertyName, const uno::Any& aValue )
199 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
200 lang::IllegalArgumentException, lang::WrappedTargetException,
201 uno::RuntimeException)
203 ScUnoGuard aGuard;
204 String aString(aPropertyName);
205 if ( aString.EqualsAscii( SC_UNO_COMPILEFAP ) )
207 aValue >>= mbCompileFAP;
209 else if ( aString.EqualsAscii( SC_UNO_COMPILEENGLISH ) )
211 bool bOldEnglish = mbEnglish;
212 if (aValue >>= mbEnglish)
214 // Need to recreate the symbol map to change English property
215 // because the map is const. So for performance reasons set
216 // CompileEnglish _before_ OpCodeMap!
217 if (mxOpCodeMap.get() && mbEnglish != bOldEnglish)
219 ScDocument* pDoc = mpDocShell->GetDocument();
220 ScCompiler aCompiler( pDoc, ScAddress());
221 aCompiler.SetGrammar(pDoc->GetGrammar());
222 mxOpCodeMap = aCompiler.CreateOpCodeMap( maOpCodeMapping, mbEnglish);
225 else
226 throw lang::IllegalArgumentException();
228 else if ( aString.EqualsAscii( SC_UNO_FORMULACONVENTION ) )
230 aValue >>= mnConv;
232 else if ( aString.EqualsAscii( SC_UNO_IGNORELEADING ) )
234 aValue >>= mbIgnoreSpaces;
236 else if ( aString.EqualsAscii( SC_UNO_OPCODEMAP ) )
238 if (aValue >>= maOpCodeMapping)
240 ScDocument* pDoc = mpDocShell->GetDocument();
241 ScCompiler aCompiler( pDoc, ScAddress());
242 aCompiler.SetGrammar(pDoc->GetGrammar());
243 mxOpCodeMap = aCompiler.CreateOpCodeMap( maOpCodeMapping, mbEnglish);
245 else
246 throw lang::IllegalArgumentException();
248 else if ( aString.EqualsAscii( SC_UNO_EXTERNALLINKS ) )
250 if (!(aValue >>= maExternalLinks))
251 throw lang::IllegalArgumentException();
253 else
254 throw beans::UnknownPropertyException();
257 uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const rtl::OUString& aPropertyName )
258 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
259 uno::RuntimeException)
261 ScUnoGuard aGuard;
262 uno::Any aRet;
263 String aString(aPropertyName);
264 if ( aString.EqualsAscii( SC_UNO_COMPILEFAP ) )
266 aRet <<= mbCompileFAP;
268 else if ( aString.EqualsAscii( SC_UNO_COMPILEENGLISH ) )
270 aRet <<= mbEnglish;
272 else if ( aString.EqualsAscii( SC_UNO_FORMULACONVENTION ) )
274 aRet <<= mnConv;
276 else if ( aString.EqualsAscii( SC_UNO_IGNORELEADING ) )
278 aRet <<= mbIgnoreSpaces;
280 else if ( aString.EqualsAscii( SC_UNO_OPCODEMAP ) )
282 aRet <<= maOpCodeMapping;
284 else if ( aString.EqualsAscii( SC_UNO_EXTERNALLINKS ) )
286 aRet <<= maExternalLinks;
288 else
289 throw beans::UnknownPropertyException();
290 return aRet;
293 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFormulaParserObj )
295 // ============================================================================
297 void lcl_ExternalRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rRef )
299 rAPI.Column = rRef.nCol;
300 rAPI.Row = rRef.nRow;
301 rAPI.Sheet = 0;
302 rAPI.RelativeColumn = rRef.nRelCol;
303 rAPI.RelativeRow = rRef.nRelRow;
304 rAPI.RelativeSheet = 0;
306 sal_Int32 nFlags = 0;
307 if ( rRef.IsColRel() ) nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE;
308 if ( rRef.IsRowRel() ) nFlags |= sheet::ReferenceFlags::ROW_RELATIVE;
309 if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED;
310 if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED;
311 if ( rRef.IsFlag3D() ) nFlags |= sheet::ReferenceFlags::SHEET_3D;
312 if ( rRef.IsRelName() ) nFlags |= sheet::ReferenceFlags::RELATIVE_NAME;
313 rAPI.Flags = nFlags;
316 void lcl_SingleRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rRef )
318 rAPI.Column = rRef.nCol;
319 rAPI.Row = rRef.nRow;
320 rAPI.Sheet = rRef.nTab;
321 rAPI.RelativeColumn = rRef.nRelCol;
322 rAPI.RelativeRow = rRef.nRelRow;
323 rAPI.RelativeSheet = rRef.nRelTab;
325 sal_Int32 nFlags = 0;
326 if ( rRef.IsColRel() ) nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE;
327 if ( rRef.IsRowRel() ) nFlags |= sheet::ReferenceFlags::ROW_RELATIVE;
328 if ( rRef.IsTabRel() ) nFlags |= sheet::ReferenceFlags::SHEET_RELATIVE;
329 if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED;
330 if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED;
331 if ( rRef.IsTabDeleted() ) nFlags |= sheet::ReferenceFlags::SHEET_DELETED;
332 if ( rRef.IsFlag3D() ) nFlags |= sheet::ReferenceFlags::SHEET_3D;
333 if ( rRef.IsRelName() ) nFlags |= sheet::ReferenceFlags::RELATIVE_NAME;
334 rAPI.Flags = nFlags;
337 // static
338 bool ScTokenConversion::ConvertToTokenArray( ScDocument& rDoc,
339 ScTokenArray& rTokenArray, const uno::Sequence<sheet::FormulaToken>& rSequence )
341 return !rTokenArray.Fill(rSequence,rDoc.GetExternalRefManager());
344 // static
345 bool ScTokenConversion::ConvertToTokenSequence( ScDocument& rDoc,
346 uno::Sequence<sheet::FormulaToken>& rSequence, const ScTokenArray& rTokenArray )
348 bool bError = false;
350 sal_Int32 nLen = static_cast<sal_Int32>(rTokenArray.GetLen());
351 formula::FormulaToken** pTokens = rTokenArray.GetArray();
352 if ( pTokens )
354 rSequence.realloc(nLen);
355 for (sal_Int32 nPos=0; nPos<nLen; nPos++)
357 const formula::FormulaToken& rToken = *pTokens[nPos];
358 sheet::FormulaToken& rAPI = rSequence[nPos];
360 OpCode eOpCode = rToken.GetOpCode();
361 // eOpCode may be changed in the following switch/case
362 switch ( rToken.GetType() )
364 case svByte:
365 // Only the count of spaces is stored as "long". Parameter count is ignored.
366 if ( eOpCode == ocSpaces )
367 rAPI.Data <<= (sal_Int32) rToken.GetByte();
368 else
369 rAPI.Data.clear(); // no data
370 break;
371 case formula::svDouble:
372 rAPI.Data <<= rToken.GetDouble();
373 break;
374 case formula::svString:
375 rAPI.Data <<= rtl::OUString( rToken.GetString() );
376 break;
377 case svExternal:
378 // Function name is stored as string.
379 // Byte (parameter count) is ignored.
380 rAPI.Data <<= rtl::OUString( rToken.GetExternal() );
381 break;
382 case svSingleRef:
384 sheet::SingleReference aSingleRef;
385 lcl_SingleRefToApi( aSingleRef, static_cast<const ScToken&>(rToken).GetSingleRef() );
386 rAPI.Data <<= aSingleRef;
388 break;
389 case formula::svDoubleRef:
391 sheet::ComplexReference aCompRef;
392 lcl_SingleRefToApi( aCompRef.Reference1, static_cast<const ScToken&>(rToken).GetSingleRef() );
393 lcl_SingleRefToApi( aCompRef.Reference2, static_cast<const ScToken&>(rToken).GetSingleRef2() );
394 rAPI.Data <<= aCompRef;
396 break;
397 case svIndex:
398 rAPI.Data <<= static_cast<sal_Int32>( rToken.GetIndex() );
399 break;
400 case svMatrix:
401 if (!ScRangeToSequence::FillMixedArray( rAPI.Data, static_cast<const ScToken&>(rToken).GetMatrix(), true))
402 rAPI.Data.clear();
403 break;
404 case svExternalSingleRef:
406 sheet::SingleReference aSingleRef;
407 lcl_ExternalRefToApi( aSingleRef, static_cast<const ScToken&>(rToken).GetSingleRef() );
408 size_t nCacheId;
409 rDoc.GetExternalRefManager()->getCacheTable( rToken.GetIndex(), rToken.GetString(), false, &nCacheId );
410 aSingleRef.Sheet = static_cast< sal_Int32 >( nCacheId );
411 sheet::ExternalReference aExtRef;
412 aExtRef.Index = rToken.GetIndex();
413 aExtRef.Reference <<= aSingleRef;
414 rAPI.Data <<= aExtRef;
415 eOpCode = ocPush;
417 break;
418 case svExternalDoubleRef:
420 sheet::ComplexReference aComplRef;
421 lcl_ExternalRefToApi( aComplRef.Reference1, static_cast<const ScToken&>(rToken).GetSingleRef() );
422 lcl_ExternalRefToApi( aComplRef.Reference2, static_cast<const ScToken&>(rToken).GetSingleRef2() );
423 size_t nCacheId;
424 rDoc.GetExternalRefManager()->getCacheTable( rToken.GetIndex(), rToken.GetString(), false, &nCacheId );
425 aComplRef.Reference1.Sheet = static_cast< sal_Int32 >( nCacheId );
426 // NOTE: This assumes that cached sheets are in consecutive order!
427 aComplRef.Reference2.Sheet = aComplRef.Reference1.Sheet + (static_cast<const ScToken&>(rToken).GetSingleRef2().nTab - static_cast<const ScToken&>(rToken).GetSingleRef().nTab);
428 sheet::ExternalReference aExtRef;
429 aExtRef.Index = rToken.GetIndex();
430 aExtRef.Reference <<= aComplRef;
431 rAPI.Data <<= aExtRef;
432 eOpCode = ocPush;
434 break;
435 case svExternalName:
437 sheet::ExternalReference aExtRef;
438 aExtRef.Index = rToken.GetIndex();
439 aExtRef.Reference <<= ::rtl::OUString( rToken.GetString() );
440 rAPI.Data <<= aExtRef;
441 eOpCode = ocPush;
443 break;
444 default:
445 DBG_ERROR1( "ScTokenConversion::ConvertToTokenSequence: unhandled token type SvStackVar %d", rToken.GetType());
446 case svSep: // occurs with ocSep, ocOpen, ocClose, ocArray*
447 case svJump: // occurs with ocIf, ocChose
448 case svMissing: // occurs with ocMissing
449 rAPI.Data.clear(); // no data
451 rAPI.OpCode = static_cast<sal_Int32>(eOpCode); //! assuming equal values for the moment
454 else
455 rSequence.realloc(0);
457 return !bError;
460 // ============================================================================
462 ScFormulaOpCodeMapperObj::ScFormulaOpCodeMapperObj(::std::auto_ptr<formula::FormulaCompiler> _pCompiler)
463 : formula::FormulaOpCodeMapperObj(_pCompiler)
467 // ============================================================================