fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / unoobj / tokenuno.cxx
blob81cecbdaa3c2bcd11c6e3282c1f66bff75137fc6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "tokenuno.hxx"
22 #include <sal/macros.h>
24 #include <com/sun/star/sheet/ComplexReference.hpp>
25 #include <com/sun/star/sheet/ExternalReference.hpp>
26 #include <com/sun/star/sheet/ReferenceFlags.hpp>
27 #include <com/sun/star/sheet/AddressConvention.hpp>
28 #include <com/sun/star/sheet/NameToken.hpp>
29 #include <com/sun/star/table/CellAddress.hpp>
31 #include <svl/itemprop.hxx>
32 #include <vcl/svapp.hxx>
34 #include "miscuno.hxx"
35 #include "convuno.hxx"
36 #include "unonames.hxx"
37 #include "token.hxx"
38 #include "compiler.hxx"
39 #include "tokenarray.hxx"
40 #include "docsh.hxx"
41 #include "rangeseq.hxx"
42 #include "externalrefmgr.hxx"
44 using namespace ::formula;
45 using namespace ::com::sun::star;
47 static const SfxItemPropertyMapEntry* lcl_GetFormulaParserMap()
49 static const SfxItemPropertyMapEntry aFormulaParserMap_Impl[] =
51 {OUString(SC_UNO_COMPILEFAP), 0, cppu::UnoType<bool>::get(), 0, 0 },
52 {OUString(SC_UNO_COMPILEENGLISH), 0, cppu::UnoType<bool>::get(), 0, 0 },
53 {OUString(SC_UNO_IGNORELEADING), 0, cppu::UnoType<bool>::get(), 0, 0 },
54 {OUString(SC_UNO_FORMULACONVENTION), 0, cppu::UnoType<decltype(sheet::AddressConvention::UNSPECIFIED)>::get(), 0, 0 },
55 {OUString(SC_UNO_OPCODEMAP), 0, cppu::UnoType<uno::Sequence< sheet::FormulaOpCodeMapEntry >>::get(), 0, 0 },
56 { OUString(), 0, css::uno::Type(), 0, 0 }
58 return aFormulaParserMap_Impl;
61 SC_SIMPLE_SERVICE_INFO( ScFormulaParserObj, "ScFormulaParserObj", SC_SERVICENAME_FORMULAPARS )
63 ScFormulaParserObj::ScFormulaParserObj(ScDocShell* pDocSh) :
64 mpDocShell( pDocSh ),
65 mnConv( sheet::AddressConvention::UNSPECIFIED ),
66 mbEnglish( false ),
67 mbIgnoreSpaces( true ),
68 mbCompileFAP( false )
70 mpDocShell->GetDocument().AddUnoObject(*this);
73 ScFormulaParserObj::~ScFormulaParserObj()
75 SolarMutexGuard g;
77 if (mpDocShell)
78 mpDocShell->GetDocument().RemoveUnoObject(*this);
81 void ScFormulaParserObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
83 const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
84 if ( pSimpleHint && pSimpleHint->GetId() == SFX_HINT_DYING )
85 mpDocShell = NULL;
88 // XFormulaParser
90 void ScFormulaParserObj::SetCompilerFlags( ScCompiler& rCompiler ) const
92 static const formula::FormulaGrammar::AddressConvention aConvMap[] = {
93 formula::FormulaGrammar::CONV_OOO, // <- AddressConvention::OOO
94 formula::FormulaGrammar::CONV_XL_A1, // <- AddressConvention::XL_A1
95 formula::FormulaGrammar::CONV_XL_R1C1, // <- AddressConvention::XL_R1C1
96 formula::FormulaGrammar::CONV_XL_OOX, // <- AddressConvention::XL_OOX
97 formula::FormulaGrammar::CONV_LOTUS_A1 // <- AddressConvention::LOTUS_A1
99 static const sal_Int16 nConvMapCount = sizeof(aConvMap)/sizeof(aConvMap[0]);
101 // If mxOpCodeMap is not empty it overrides mbEnglish, and vice versa. We
102 // don't need to initialize things twice.
103 if (mxOpCodeMap.get())
104 rCompiler.SetFormulaLanguage( mxOpCodeMap );
105 else
107 sal_Int32 nFormulaLanguage = mbEnglish ?
108 sheet::FormulaLanguage::ENGLISH :
109 sheet::FormulaLanguage::NATIVE;
110 ScCompiler::OpCodeMapPtr xMap = rCompiler.GetOpCodeMap( nFormulaLanguage);
111 rCompiler.SetFormulaLanguage( xMap);
114 formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_UNSPECIFIED;
115 if (mnConv >= 0 && mnConv < nConvMapCount)
116 eConv = aConvMap[mnConv];
118 rCompiler.SetRefConvention( eConv );
119 rCompiler.EnableJumpCommandReorder(!mbCompileFAP);
120 rCompiler.EnableStopOnError(!mbCompileFAP);
122 rCompiler.SetExternalLinks( maExternalLinks);
125 uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula(
126 const OUString& aFormula, const table::CellAddress& rReferencePos )
127 throw (uno::RuntimeException, std::exception)
129 SolarMutexGuard aGuard;
130 uno::Sequence<sheet::FormulaToken> aRet;
132 if (mpDocShell)
134 ScDocument& rDoc = mpDocShell->GetDocument();
135 ScExternalRefManager::ApiGuard aExtRefGuard(&rDoc);
137 ScAddress aRefPos( ScAddress::UNINITIALIZED );
138 ScUnoConversion::FillScAddress( aRefPos, rReferencePos );
139 ScCompiler aCompiler( &rDoc, aRefPos);
140 aCompiler.SetGrammar(rDoc.GetGrammar());
141 SetCompilerFlags( aCompiler );
143 ScTokenArray* pCode = aCompiler.CompileString( aFormula );
144 (void)ScTokenConversion::ConvertToTokenSequence( rDoc, aRet, *pCode );
145 delete pCode;
148 return aRet;
151 OUString SAL_CALL ScFormulaParserObj::printFormula(
152 const uno::Sequence<sheet::FormulaToken>& aTokens, const table::CellAddress& rReferencePos )
153 throw (uno::RuntimeException, std::exception)
155 SolarMutexGuard aGuard;
156 OUString aRet;
158 if (mpDocShell)
160 ScDocument& rDoc = mpDocShell->GetDocument();
161 ScTokenArray aCode;
162 (void)ScTokenConversion::ConvertToTokenArray( rDoc, aCode, aTokens );
163 ScAddress aRefPos( ScAddress::UNINITIALIZED );
164 ScUnoConversion::FillScAddress( aRefPos, rReferencePos );
165 ScCompiler aCompiler( &rDoc, aRefPos, aCode);
166 aCompiler.SetGrammar(rDoc.GetGrammar());
167 SetCompilerFlags( aCompiler );
169 OUStringBuffer aBuffer;
170 aCompiler.CreateStringFromTokenArray( aBuffer );
171 aRet = aBuffer.makeStringAndClear();
174 return aRet;
177 // XPropertySet
179 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScFormulaParserObj::getPropertySetInfo()
180 throw(uno::RuntimeException, std::exception)
182 SolarMutexGuard aGuard;
183 static uno::Reference< beans::XPropertySetInfo > aRef(new SfxItemPropertySetInfo( lcl_GetFormulaParserMap() ));
184 return aRef;
187 void SAL_CALL ScFormulaParserObj::setPropertyValue(
188 const OUString& aPropertyName, const uno::Any& aValue )
189 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
190 lang::IllegalArgumentException, lang::WrappedTargetException,
191 uno::RuntimeException, std::exception)
193 SolarMutexGuard aGuard;
194 OUString aString(aPropertyName);
195 if ( aString == SC_UNO_COMPILEFAP )
197 aValue >>= mbCompileFAP;
199 else if ( aString == SC_UNO_COMPILEENGLISH )
201 bool bOldEnglish = mbEnglish;
202 if (aValue >>= mbEnglish)
204 // Need to recreate the symbol map to change English property
205 // because the map is const. So for performance reasons set
206 // CompileEnglish _before_ OpCodeMap!
207 if (mxOpCodeMap.get() && mbEnglish != bOldEnglish)
209 ScDocument& rDoc = mpDocShell->GetDocument();
210 ScCompiler aCompiler( &rDoc, ScAddress());
211 aCompiler.SetGrammar(rDoc.GetGrammar());
212 mxOpCodeMap = formula::FormulaCompiler::CreateOpCodeMap( maOpCodeMapping, mbEnglish);
215 else
216 throw lang::IllegalArgumentException();
218 else if ( aString == SC_UNO_FORMULACONVENTION )
220 aValue >>= mnConv;
222 else if ( aString == SC_UNO_IGNORELEADING )
224 aValue >>= mbIgnoreSpaces;
226 else if ( aString == SC_UNO_OPCODEMAP )
228 if (aValue >>= maOpCodeMapping)
230 ScDocument& rDoc = mpDocShell->GetDocument();
231 ScCompiler aCompiler( &rDoc, ScAddress());
232 aCompiler.SetGrammar(rDoc.GetGrammar());
233 mxOpCodeMap = formula::FormulaCompiler::CreateOpCodeMap( maOpCodeMapping, mbEnglish);
235 else
236 throw lang::IllegalArgumentException();
238 else if ( aString == SC_UNO_EXTERNALLINKS )
240 if (!(aValue >>= maExternalLinks))
241 throw lang::IllegalArgumentException();
243 else
244 throw beans::UnknownPropertyException();
247 uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const OUString& aPropertyName )
248 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
249 uno::RuntimeException, std::exception)
251 SolarMutexGuard aGuard;
252 uno::Any aRet;
253 OUString aString(aPropertyName);
254 if ( aString == SC_UNO_COMPILEFAP )
256 aRet <<= mbCompileFAP;
258 else if ( aString == SC_UNO_COMPILEENGLISH )
260 aRet <<= mbEnglish;
262 else if ( aString == SC_UNO_FORMULACONVENTION )
264 aRet <<= mnConv;
266 else if ( aString == SC_UNO_IGNORELEADING )
268 aRet <<= mbIgnoreSpaces;
270 else if ( aString == SC_UNO_OPCODEMAP )
272 aRet <<= maOpCodeMapping;
274 else if ( aString == SC_UNO_EXTERNALLINKS )
276 aRet <<= maExternalLinks;
278 else
279 throw beans::UnknownPropertyException();
280 return aRet;
283 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFormulaParserObj )
285 static void lcl_ExternalRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rRef )
287 rAPI.Column = 0;
288 rAPI.Row = 0;
289 rAPI.Sheet = 0;
290 rAPI.RelativeColumn = 0;
291 rAPI.RelativeRow = 0;
292 rAPI.RelativeSheet = 0;
294 sal_Int32 nFlags = 0;
295 if ( rRef.IsColRel() )
297 nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE;
298 rAPI.RelativeColumn = rRef.Col();
300 else
301 rAPI.Column = rRef.Col();
303 if ( rRef.IsRowRel() )
305 nFlags |= sheet::ReferenceFlags::ROW_RELATIVE;
306 rAPI.RelativeRow = rRef.Row();
308 else
309 rAPI.Row = rRef.Row();
311 if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED;
312 if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED;
313 if ( rRef.IsFlag3D() ) nFlags |= sheet::ReferenceFlags::SHEET_3D;
314 if ( rRef.IsRelName() ) nFlags |= sheet::ReferenceFlags::RELATIVE_NAME;
315 rAPI.Flags = nFlags;
318 static void lcl_SingleRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rRef )
320 sal_Int32 nFlags = 0;
321 if ( rRef.IsColRel() )
323 nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE;
324 rAPI.RelativeColumn = rRef.Col();
325 rAPI.Column = 0;
327 else
329 rAPI.RelativeColumn = 0;
330 rAPI.Column = rRef.Col();
333 if ( rRef.IsRowRel() )
335 nFlags |= sheet::ReferenceFlags::ROW_RELATIVE;
336 rAPI.RelativeRow = rRef.Row();
337 rAPI.Row = 0;
339 else
341 rAPI.RelativeRow = 0;
342 rAPI.Row = rRef.Row();
345 if ( rRef.IsTabRel() )
347 nFlags |= sheet::ReferenceFlags::SHEET_RELATIVE;
348 rAPI.RelativeSheet = rRef.Tab();
349 rAPI.Sheet = 0;
351 else
353 rAPI.RelativeSheet = 0;
354 rAPI.Sheet = rRef.Tab();
357 if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED;
358 if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED;
359 if ( rRef.IsTabDeleted() ) nFlags |= sheet::ReferenceFlags::SHEET_DELETED;
360 if ( rRef.IsFlag3D() ) nFlags |= sheet::ReferenceFlags::SHEET_3D;
361 if ( rRef.IsRelName() ) nFlags |= sheet::ReferenceFlags::RELATIVE_NAME;
362 rAPI.Flags = nFlags;
365 bool ScTokenConversion::ConvertToTokenArray( ScDocument& rDoc,
366 ScTokenArray& rTokenArray, const uno::Sequence<sheet::FormulaToken>& rSequence )
368 return !rTokenArray.Fill(rSequence, rDoc.GetSharedStringPool(), rDoc.GetExternalRefManager());
371 bool ScTokenConversion::ConvertToTokenSequence( const ScDocument& rDoc,
372 uno::Sequence<sheet::FormulaToken>& rSequence, const ScTokenArray& rTokenArray )
374 bool bError = false;
376 sal_Int32 nLen = static_cast<sal_Int32>(rTokenArray.GetLen());
377 formula::FormulaToken** pTokens = rTokenArray.GetArray();
378 if ( pTokens )
380 rSequence.realloc(nLen);
381 for (sal_Int32 nPos=0; nPos<nLen; nPos++)
383 const formula::FormulaToken& rToken = *pTokens[nPos];
384 sheet::FormulaToken& rAPI = rSequence[nPos];
386 OpCode eOpCode = rToken.GetOpCode();
387 // eOpCode may be changed in the following switch/case
388 switch ( rToken.GetType() )
390 case svByte:
391 // Only the count of spaces is stored as "long". Parameter count is ignored.
392 if ( eOpCode == ocSpaces )
393 rAPI.Data <<= (sal_Int32) rToken.GetByte();
394 else
395 rAPI.Data.clear(); // no data
396 break;
397 case formula::svDouble:
398 rAPI.Data <<= rToken.GetDouble();
399 break;
400 case formula::svString:
401 rAPI.Data <<= rToken.GetString().getString();
402 break;
403 case svExternal:
404 // Function name is stored as string.
405 // Byte (parameter count) is ignored.
406 rAPI.Data <<= OUString( rToken.GetExternal() );
407 break;
408 case svSingleRef:
410 sheet::SingleReference aSingleRef;
411 lcl_SingleRefToApi( aSingleRef, *rToken.GetSingleRef() );
412 rAPI.Data <<= aSingleRef;
414 break;
415 case formula::svDoubleRef:
417 sheet::ComplexReference aCompRef;
418 lcl_SingleRefToApi( aCompRef.Reference1, *rToken.GetSingleRef() );
419 lcl_SingleRefToApi( aCompRef.Reference2, *rToken.GetSingleRef2() );
420 rAPI.Data <<= aCompRef;
422 break;
423 case svIndex:
425 sheet::NameToken aNameToken;
426 aNameToken.Index = static_cast<sal_Int32>( rToken.GetIndex() );
427 aNameToken.Global = rToken.IsGlobal();
428 rAPI.Data <<= aNameToken;
430 break;
431 case svMatrix:
432 if (!ScRangeToSequence::FillMixedArray( rAPI.Data, rToken.GetMatrix(), true))
433 rAPI.Data.clear();
434 break;
435 case svExternalSingleRef:
437 sheet::SingleReference aSingleRef;
438 lcl_ExternalRefToApi( aSingleRef, *rToken.GetSingleRef() );
439 size_t nCacheId;
440 rDoc.GetExternalRefManager()->getCacheTable(
441 rToken.GetIndex(), rToken.GetString().getString(), false, &nCacheId);
442 aSingleRef.Sheet = static_cast< sal_Int32 >( nCacheId );
443 sheet::ExternalReference aExtRef;
444 aExtRef.Index = rToken.GetIndex();
445 aExtRef.Reference <<= aSingleRef;
446 rAPI.Data <<= aExtRef;
447 eOpCode = ocPush;
449 break;
450 case svExternalDoubleRef:
452 sheet::ComplexReference aComplRef;
453 lcl_ExternalRefToApi( aComplRef.Reference1, *rToken.GetSingleRef() );
454 lcl_ExternalRefToApi( aComplRef.Reference2, *rToken.GetSingleRef2() );
455 size_t nCacheId;
456 rDoc.GetExternalRefManager()->getCacheTable(
457 rToken.GetIndex(), rToken.GetString().getString(), false, &nCacheId);
458 aComplRef.Reference1.Sheet = static_cast< sal_Int32 >( nCacheId );
459 // NOTE: This assumes that cached sheets are in consecutive order!
460 aComplRef.Reference2.Sheet =
461 aComplRef.Reference1.Sheet +
462 (rToken.GetSingleRef2()->Tab() - rToken.GetSingleRef()->Tab());
463 sheet::ExternalReference aExtRef;
464 aExtRef.Index = rToken.GetIndex();
465 aExtRef.Reference <<= aComplRef;
466 rAPI.Data <<= aExtRef;
467 eOpCode = ocPush;
469 break;
470 case svExternalName:
472 sheet::ExternalReference aExtRef;
473 aExtRef.Index = rToken.GetIndex();
474 aExtRef.Reference <<= rToken.GetString().getString();
475 rAPI.Data <<= aExtRef;
476 eOpCode = ocPush;
478 break;
479 default:
480 OSL_TRACE( "ScTokenConversion::ConvertToTokenSequence: unhandled token type SvStackVar %d", rToken.GetType());
481 //fall-through
482 case svSep: // occurs with ocSep, ocOpen, ocClose, ocArray*
483 case svJump: // occurs with ocIf, ocChoose
484 case svMissing: // occurs with ocMissing
485 rAPI.Data.clear(); // no data
487 rAPI.OpCode = static_cast<sal_Int32>(eOpCode); //! assuming equal values for the moment
490 else
491 rSequence.realloc(0);
493 return !bError;
496 ScFormulaOpCodeMapperObj::ScFormulaOpCodeMapperObj(::std::unique_ptr<formula::FormulaCompiler> && _pCompiler)
497 : formula::FormulaOpCodeMapperObj(std::move(_pCompiler))
501 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */