From 1e5e7b9323c3321a380edf86097ccc2e3f0a7a7a Mon Sep 17 00:00:00 2001 From: Eike Rathke Date: Mon, 20 Jul 2015 19:13:06 +0200 Subject: Resolves: tdf#58838 do not use collation for Equal/NotEqual operators Unicode collation ignores control characters and other specific characters, see http://www.unicode.org/charts/collation/chart_Ignored.html and thus is not suitable to be used for Equal/NotEqual operators. Change-Id: Ib84713e1da59d92e07bc974d93b6def8217bb067 --- sc/inc/compare.hxx | 8 ++++++-- sc/source/core/inc/interpre.hxx | 2 +- sc/source/core/tool/compare.cxx | 22 ++++++++++++++++------ sc/source/core/tool/interpr1.cxx | 20 ++++++++++---------- sc/source/core/tool/scmatrix.cxx | 2 +- 5 files changed, 34 insertions(+), 20 deletions(-) diff --git a/sc/inc/compare.hxx b/sc/inc/compare.hxx index 69080a51a344..e04b5dbf60b8 100644 --- a/sc/inc/compare.hxx +++ b/sc/inc/compare.hxx @@ -61,9 +61,13 @@ private: }; /** @param pOptions - NULL means case sensitivity document option is to be used! + Used for comparing two strings, if given. + NULL means that for comparing two strings ScQueryOp rComp.meOp is + tested for SC_EQUAL and SC_NOT_EQUAL, else pOptions->aQueryEntry.eOp + Case sensitivity document option is always to be passed in + rComp.mbIgnoreCase. */ -double CompareFunc( const Compare::Cell& rCell1, const Compare::Cell& rCell2, bool bIgnoreCase, CompareOptions* pOptions = NULL ); +double CompareFunc( const Compare& rComp, CompareOptions* pOptions = NULL ); double CompareFunc( const Compare::Cell& rCell1, double fCell2, CompareOptions* pOptions = NULL ); double CompareFunc( double fCell1, double fCell2 ); diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index df87bda5cb10..14118da00d89 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -407,7 +407,7 @@ void ScChooseJump(); // Returns true if last jump was executed and result matrix pushed. bool JumpMatrix( short nStackLevel ); -double Compare(); +double Compare( ScQueryOp eOp ); /** @param pOptions NULL means case sensitivity document option is to be used! */ diff --git a/sc/source/core/tool/compare.cxx b/sc/source/core/tool/compare.cxx index 6395f2f31a01..b8836056a6aa 100644 --- a/sc/source/core/tool/compare.cxx +++ b/sc/source/core/tool/compare.cxx @@ -43,8 +43,11 @@ CompareOptions::CompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bo // struct if needed. } -double CompareFunc( const Compare::Cell& rCell1, const Compare::Cell& rCell2, bool bIgnoreCase, CompareOptions* pOptions ) +double CompareFunc( const Compare& rComp, CompareOptions* pOptions ) { + const Compare::Cell& rCell1 = rComp.maCells[0]; + const Compare::Cell& rCell2 = rComp.maCells[1]; + // Keep DoubleError if encountered // #i40539# if bEmpty is set, bVal/nVal are uninitialized if (!rCell1.mbEmpty && rCell1.mbValue && !rtl::math::isFinite(rCell1.mfValue)) @@ -134,7 +137,7 @@ double CompareFunc( const Compare::Cell& rCell1, const Compare::Cell& rCell2, bo sal_Int32 nStart = 0; sal_Int32 nStop = rCell1.maStr.getLength(); bool bMatch = rEntry.GetSearchTextPtr( - !bIgnoreCase)->SearchForward( + !rComp.mbIgnoreCase)->SearchForward( rCell1.maStr.getString(), &nStart, &nStop); if (bMatch && pOptions->bMatchWholeCell && (nStart != 0 || nStop != rCell1.maStr.getLength())) bMatch = false; // RegEx must match entire string. @@ -143,12 +146,12 @@ double CompareFunc( const Compare::Cell& rCell1, const Compare::Cell& rCell2, bo else if (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL) { ::utl::TransliterationWrapper* pTransliteration = - (bIgnoreCase ? ScGlobal::GetpTransliteration() : + (rComp.mbIgnoreCase ? ScGlobal::GetpTransliteration() : ScGlobal::GetCaseTransliteration()); bool bMatch = false; if (pOptions->bMatchWholeCell) { - if (bIgnoreCase) + if (rComp.mbIgnoreCase) bMatch = rCell1.maStr.getDataIgnoreCase() == rCell2.maStr.getDataIgnoreCase(); else bMatch = rCell1.maStr.getData() == rCell2.maStr.getData(); @@ -165,14 +168,21 @@ double CompareFunc( const Compare::Cell& rCell1, const Compare::Cell& rCell2, bo } fRes = (bMatch ? 0 : 1); } - else if (bIgnoreCase) + else if (rComp.mbIgnoreCase) fRes = (double) ScGlobal::GetCollator()->compareString( rCell1.maStr.getString(), rCell2.maStr.getString()); else fRes = (double) ScGlobal::GetCaseCollator()->compareString( rCell1.maStr.getString(), rCell2.maStr.getString()); } - else if (bIgnoreCase) + else if (rComp.meOp == SC_EQUAL || rComp.meOp == SC_NOT_EQUAL) + { + if (rComp.mbIgnoreCase) + fRes = (rCell1.maStr.getDataIgnoreCase() == rCell2.maStr.getDataIgnoreCase()) ? 0 : 1; + else + fRes = (rCell1.maStr.getData() == rCell2.maStr.getData()) ? 0 : 1; + } + else if (rComp.mbIgnoreCase) fRes = (double) ScGlobal::GetCollator()->compareString( rCell1.maStr.getString(), rCell2.maStr.getString()); else diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 78922695f522..b464da4e8716 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -801,9 +801,10 @@ bool ScInterpreter::JumpMatrix( short nStackLevel ) return false; } -double ScInterpreter::Compare() +double ScInterpreter::Compare( ScQueryOp eOp ) { sc::Compare aComp; + aComp.meOp = eOp; aComp.mbIgnoreCase = pDok->GetDocOptions().IsIgnoreCase(); for( short i = 1; i >= 0; i-- ) { @@ -888,7 +889,7 @@ double ScInterpreter::Compare() if( nGlobalError ) return 0; nCurFmtType = nFuncFmtType = css::util::NumberFormat::LOGICAL; - return sc::CompareFunc(aComp.maCells[0], aComp.maCells[1], aComp.mbIgnoreCase); + return sc::CompareFunc(aComp); } sc::RangeMatrix ScInterpreter::CompareMat( ScQueryOp eOp, sc::CompareOptions* pOptions ) @@ -997,8 +998,7 @@ sc::RangeMatrix ScInterpreter::CompareMat( ScQueryOp eOp, sc::CompareOptions* pO rCell.mbEmpty = false; } } - aRes.mpMat->PutDouble( - sc::CompareFunc(aComp.maCells[0], aComp.maCells[1], aComp.mbIgnoreCase, pOptions), j, k); + aRes.mpMat->PutDouble( sc::CompareFunc( aComp, pOptions), j, k); } else aRes.mpMat->PutError( errNoValue, j, k); @@ -1088,7 +1088,7 @@ void ScInterpreter::ScEqual() PushMatrix(aMat); } else - PushInt( int(Compare() == 0) ); + PushInt( int(Compare( SC_EQUAL) == 0) ); } void ScInterpreter::ScNotEqual() @@ -1105,7 +1105,7 @@ void ScInterpreter::ScNotEqual() PushMatrix(aMat); } else - PushInt( int(Compare() != 0) ); + PushInt( int(Compare( SC_NOT_EQUAL) != 0) ); } void ScInterpreter::ScLess() @@ -1122,7 +1122,7 @@ void ScInterpreter::ScLess() PushMatrix(aMat); } else - PushInt( int(Compare() < 0) ); + PushInt( int(Compare( SC_LESS) < 0) ); } void ScInterpreter::ScGreater() @@ -1139,7 +1139,7 @@ void ScInterpreter::ScGreater() PushMatrix(aMat); } else - PushInt( int(Compare() > 0) ); + PushInt( int(Compare( SC_GREATER) > 0) ); } void ScInterpreter::ScLessEqual() @@ -1156,7 +1156,7 @@ void ScInterpreter::ScLessEqual() PushMatrix(aMat); } else - PushInt( int(Compare() <= 0) ); + PushInt( int(Compare( SC_LESS_EQUAL) <= 0) ); } void ScInterpreter::ScGreaterEqual() @@ -1173,7 +1173,7 @@ void ScInterpreter::ScGreaterEqual() PushMatrix(aMat); } else - PushInt( int(Compare() >= 0) ); + PushInt( int(Compare( SC_GREATER_EQUAL) >= 0) ); } void ScInterpreter::ScAnd() diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx index fa099dd57ce1..5ef8378891d8 100644 --- a/sc/source/core/tool/scmatrix.cxx +++ b/sc/source/core/tool/scmatrix.cxx @@ -1380,7 +1380,7 @@ class CompareMatrixFunc : std::unary_function