init and compare opcode hashmap with uppercase symbols

This is necessary now there are TableRef items like #All that need to be
matched case insensitive but displayed preserving the case as coded /
translated.

As a side effect, OOXML functions with _xlfn. prefix are now matched in
case that prefix was uppercase.

Change-Id: Ie14700d13c40c3e39e6d6aff560bcdfe23707196
This commit is contained in:
Eike Rathke
2015-03-12 01:18:21 +01:00
parent 7b355da685
commit c6312364b6
3 changed files with 30 additions and 21 deletions

View File

@@ -151,7 +151,7 @@ public:
private: private:
bool getOpCodeString( OUString& rStr, sal_uInt16 nOp ); bool getOpCodeString( OUString& rStr, sal_uInt16 nOp );
void putDefaultOpCode( FormulaCompiler::NonConstOpCodeMapPtr xMap, sal_uInt16 nOp ); void putDefaultOpCode( FormulaCompiler::NonConstOpCodeMapPtr xMap, sal_uInt16 nOp, const CharClass* pCharClass );
private: private:
FormulaCompiler::SeparatorType meSepType; FormulaCompiler::SeparatorType meSepType;
@@ -162,11 +162,13 @@ OpCodeList::OpCodeList( sal_uInt16 nRID, FormulaCompiler::NonConstOpCodeMapPtr x
Resource( ResId( nRID, *ResourceManager::getResManager())) Resource( ResId( nRID, *ResourceManager::getResManager()))
, meSepType( eSepType) , meSepType( eSepType)
{ {
SvtSysLocale aSysLocale;
const CharClass* pCharClass = (xMap->isEnglish() ? NULL : aSysLocale.GetCharClassPtr());
if (meSepType == FormulaCompiler::RESOURCE_BASE) if (meSepType == FormulaCompiler::RESOURCE_BASE)
{ {
for (sal_uInt16 i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; ++i) for (sal_uInt16 i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; ++i)
{ {
putDefaultOpCode( xMap, i); putDefaultOpCode( xMap, i, pCharClass);
} }
} }
else else
@@ -175,9 +177,9 @@ OpCodeList::OpCodeList( sal_uInt16 nRID, FormulaCompiler::NonConstOpCodeMapPtr x
{ {
OUString aOpStr; OUString aOpStr;
if ( getOpCodeString( aOpStr, i) ) if ( getOpCodeString( aOpStr, i) )
xMap->putOpCode( aOpStr, OpCode(i)); xMap->putOpCode( aOpStr, OpCode(i), pCharClass);
else else
putDefaultOpCode( xMap, i); putDefaultOpCode( xMap, i, pCharClass);
} }
} }
@@ -235,12 +237,13 @@ bool OpCodeList::getOpCodeString( OUString& rStr, sal_uInt16 nOp )
return false; return false;
} }
void OpCodeList::putDefaultOpCode( FormulaCompiler::NonConstOpCodeMapPtr xMap, sal_uInt16 nOp ) void OpCodeList::putDefaultOpCode( FormulaCompiler::NonConstOpCodeMapPtr xMap, sal_uInt16 nOp,
const CharClass* pCharClass )
{ {
ResId aRes( nOp, *ResourceManager::getResManager()); ResId aRes( nOp, *ResourceManager::getResManager());
aRes.SetRT( RSC_STRING); aRes.SetRT( RSC_STRING);
if (IsAvailableRes( aRes)) if (IsAvailableRes( aRes))
xMap->putOpCode( aRes.toString(), OpCode( nOp)); xMap->putOpCode( aRes.toString(), OpCode( nOp), pCharClass);
} }
// static // static
@@ -508,7 +511,7 @@ uno::Sequence< sheet::FormulaOpCodeMapEntry > FormulaCompiler::OpCodeMap::create
} }
void FormulaCompiler::OpCodeMap::putOpCode( const OUString & rStr, const OpCode eOp ) void FormulaCompiler::OpCodeMap::putOpCode( const OUString & rStr, const OpCode eOp, const CharClass* pCharClass )
{ {
DBG_ASSERT( 0 < eOp && sal_uInt16(eOp) < mnSymbols, "OpCodeMap::putOpCode: OpCode out of range"); DBG_ASSERT( 0 < eOp && sal_uInt16(eOp) < mnSymbols, "OpCodeMap::putOpCode: OpCode out of range");
if (0 < eOp && sal_uInt16(eOp) < mnSymbols) if (0 < eOp && sal_uInt16(eOp) < mnSymbols)
@@ -519,8 +522,10 @@ void FormulaCompiler::OpCodeMap::putOpCode( const OUString & rStr, const OpCode
"OpCodeMap::putOpCode: reusing OpCode " << static_cast<sal_uInt16>(eOp) "OpCodeMap::putOpCode: reusing OpCode " << static_cast<sal_uInt16>(eOp)
<< ", replacing '" << mpTable[eOp] << "' with '" << rStr << "' in " << ", replacing '" << mpTable[eOp] << "' with '" << rStr << "' in "
<< (mbEnglish ? "" : "non-") << "English map 0x" << ::std::hex << meGrammar); << (mbEnglish ? "" : "non-") << "English map 0x" << ::std::hex << meGrammar);
// Case preserving opcode -> string, upper string -> opcode
mpTable[eOp] = rStr; mpTable[eOp] = rStr;
mpHashMap->insert( OpCodeHashMap::value_type( rStr, eOp)); OUString aUpper( pCharClass ? pCharClass->uppercase( rStr) : rStr.toAsciiUpperCase());
mpHashMap->insert( OpCodeHashMap::value_type( aUpper, eOp));
} }
} }
@@ -623,13 +628,15 @@ FormulaCompiler::OpCodeMapPtr FormulaCompiler::CreateOpCodeMap(
NonConstOpCodeMapPtr xMap( new OpCodeMap( SC_OPCODE_LAST_OPCODE_ID + 1, false, NonConstOpCodeMapPtr xMap( new OpCodeMap( SC_OPCODE_LAST_OPCODE_ID + 1, false,
FormulaGrammar::mergeToGrammar( FormulaGrammar::setEnglishBit( FormulaGrammar::mergeToGrammar( FormulaGrammar::setEnglishBit(
FormulaGrammar::GRAM_EXTERNAL, bEnglish), FormulaGrammar::CONV_UNSPECIFIED))); FormulaGrammar::GRAM_EXTERNAL, bEnglish), FormulaGrammar::CONV_UNSPECIFIED)));
SvtSysLocale aSysLocale;
const CharClass* pCharClass = (xMap->isEnglish() ? NULL : aSysLocale.GetCharClassPtr());
FormulaOpCodeMapEntry const * pArr2 = rMapping.getConstArray(); FormulaOpCodeMapEntry const * pArr2 = rMapping.getConstArray();
FormulaOpCodeMapEntry const * const pStop = pArr2 + rMapping.getLength(); FormulaOpCodeMapEntry const * const pStop = pArr2 + rMapping.getLength();
for ( ; pArr2 < pStop; ++pArr2) for ( ; pArr2 < pStop; ++pArr2)
{ {
OpCode eOp = OpCode(pArr2->Token.OpCode); OpCode eOp = OpCode(pArr2->Token.OpCode);
if (eOp != ocExternal) if (eOp != ocExternal)
xMap->putOpCode( pArr2->Name, eOp); xMap->putOpCode( pArr2->Name, eOp, pCharClass);
else else
{ {
OUString aExternalName; OUString aExternalName;
@@ -722,9 +729,9 @@ void FormulaCompiler::InitSymbolsEnglishXL() const
// TODO: For now, just replace the separators to the Excel English // TODO: For now, just replace the separators to the Excel English
// variants. Later, if we want to properly map Excel functions with Calc // variants. Later, if we want to properly map Excel functions with Calc
// functions, we'll need to do a little more work here. // functions, we'll need to do a little more work here.
mxSymbolsEnglishXL->putOpCode( OUString(','), ocSep); mxSymbolsEnglishXL->putOpCode( OUString(','), ocSep, NULL);
mxSymbolsEnglishXL->putOpCode( OUString(','), ocArrayColSep); mxSymbolsEnglishXL->putOpCode( OUString(','), ocArrayColSep, NULL);
mxSymbolsEnglishXL->putOpCode( OUString(';'), ocArrayRowSep); mxSymbolsEnglishXL->putOpCode( OUString(';'), ocArrayRowSep, NULL);
} }
void FormulaCompiler::InitSymbolsOOXML() const void FormulaCompiler::InitSymbolsOOXML() const
@@ -1947,9 +1954,9 @@ void FormulaCompiler::UpdateSeparatorsNative(
{ {
NonConstOpCodeMapPtr xSymbolsNative; NonConstOpCodeMapPtr xSymbolsNative;
lcl_fillNativeSymbols( xSymbolsNative); lcl_fillNativeSymbols( xSymbolsNative);
xSymbolsNative->putOpCode( rSep, ocSep); xSymbolsNative->putOpCode( rSep, ocSep, NULL);
xSymbolsNative->putOpCode( rArrayColSep, ocArrayColSep); xSymbolsNative->putOpCode( rArrayColSep, ocArrayColSep, NULL);
xSymbolsNative->putOpCode( rArrayRowSep, ocArrayRowSep); xSymbolsNative->putOpCode( rArrayRowSep, ocArrayRowSep, NULL);
} }
void FormulaCompiler::ResetNativeSymbols() void FormulaCompiler::ResetNativeSymbols()

View File

@@ -46,6 +46,7 @@ namespace com { namespace sun { namespace star {
} }
}}} }}}
class CharClass;
namespace formula namespace formula
{ {
@@ -159,7 +160,7 @@ public:
inline bool hasExternals() const { return !mpExternalHashMap->empty(); } inline bool hasExternals() const { return !mpExternalHashMap->empty(); }
/// Put entry of symbol String and OpCode pair. /// Put entry of symbol String and OpCode pair.
void putOpCode( const OUString & rStr, const OpCode eOp ); void putOpCode( const OUString & rStr, const OpCode eOp, const CharClass* pCharClass );
/// Put entry of symbol String and AddIn international String pair. /// Put entry of symbol String and AddIn international String pair.
void putExternal( const OUString & rSymbol, const OUString & rAddIn ); void putExternal( const OUString & rSymbol, const OUString & rAddIn );

View File

@@ -3582,26 +3582,27 @@ bool ScCompiler::NextNewToken( bool bInArray )
{ {
mbRewind = false; mbRewind = false;
const OUString aOrg( cSymbol ); const OUString aOrg( cSymbol );
aUpper.clear();
bool bAsciiUpper = false;
if (bAsciiNonAlnum) if (bAsciiNonAlnum)
{ {
bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar);
if (cSymbol[0] == '#') if (cSymbol[0] == '#')
{ {
// This can be only an error constant, if any. // This can be only an error constant, if any.
lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar);
if (IsErrorConstant( aUpper)) if (IsErrorConstant( aUpper))
return true; return true;
break; // do; create ocBad token or set error. break; // do; create ocBad token or set error.
} }
if (IsOpCode( aOrg, bInArray )) if (IsOpCode( aUpper, bInArray ))
return true; return true;
} }
aUpper.clear();
bool bAsciiUpper = false;
if (bMayBeFuncName) if (bMayBeFuncName)
{ {
bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar); if (aUpper.isEmpty())
bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar);
if (IsOpCode( aUpper, bInArray )) if (IsOpCode( aUpper, bInArray ))
return true; return true;
} }