summaryrefslogtreecommitdiff
path: root/svl
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2014-05-17 02:33:42 +0200
committerAndras Timar <andras.timar@collabora.com>2014-05-18 22:15:14 +0200
commit715a73d35a4e1a31e49f2c0f5af6cf952340ce7d (patch)
tree779a3384fa18a32fba5a8a8286fbae158f32c733 /svl
parent6a8e4110580c4475e9e7e3813d533b85a6fc3dcc (diff)
resolved fdo#41166 match month and day name word instead of substring
(cherry picked from commit 8e71f81f47c20320c4de7a7aadb7d524f0d8ea76) (cherry picked from commit 3885b5d4b00ebb31adabc36c507abd642c03d0d4) Change-Id: I897dbcee47de574d91ba3e3b40a39a35b779fef8 Reviewed-on: https://gerrit.libreoffice.org/9387 Reviewed-by: Kohei Yoshida <libreoffice@kohei.us> Tested-by: Kohei Yoshida <libreoffice@kohei.us>
Diffstat (limited to 'svl')
-rw-r--r--svl/source/numbers/zforfind.cxx64
-rw-r--r--svl/source/numbers/zforfind.hxx7
2 files changed, 62 insertions, 9 deletions
diff --git a/svl/source/numbers/zforfind.cxx b/svl/source/numbers/zforfind.cxx
index 840af0c52a88..9c8bb1cd96f4 100644
--- a/svl/source/numbers/zforfind.cxx
+++ b/svl/source/numbers/zforfind.cxx
@@ -438,6 +438,52 @@ bool ImpSvNumberInputScan::StringPtrContainsImpl( const OUString& rWhat,
/**
+ * Whether rString contains word rWhat at nPos
+ */
+bool ImpSvNumberInputScan::StringContainsWord( const OUString& rWhat,
+ const OUString& rString, sal_Int32 nPos )
+{
+ if (rWhat.isEmpty() || rString.getLength() < nPos + rWhat.getLength())
+ return false;
+
+ if (StringPtrContainsImpl( rWhat, rString.getStr(), nPos))
+ {
+ nPos += rWhat.getLength();
+ if (nPos == rString.getLength())
+ return true; // word at end of string
+
+ /* TODO: we COULD invoke bells and whistles word break iterator to find
+ * the next boundary, but really ... this is called for date input, so
+ * how many languages do not separate the day and month names in some
+ * form? */
+
+ // Check simple ASCII first before invoking i18n or anything else.
+ if (rtl::isAsciiAlphanumeric( rString[nPos] ))
+ return false; // Alpha or numeric is not word gap.
+
+ sal_Int32 nIndex = nPos;
+ const sal_uInt32 c = rString.iterateCodePoints( &nIndex);
+ if (nPos+1 < nIndex)
+ return true; // Surrogate, assume these to be new words.
+ (void)c;
+
+ const sal_Int32 nType = pFormatter->GetCharClass()->getCharacterType( rString, nPos);
+ using namespace ::com::sun::star::i18n;
+
+ if ((nType & (KCharacterType::UPPER | KCharacterType::LOWER | KCharacterType::DIGIT)) != 0)
+ return false; // Alpha or numeric is not word gap.
+
+ if ((nType & (KCharacterType::LETTER)) != 0)
+ return true; // Letter other than alpha is new word. (Is it?)
+
+ return true; // Catch all remaining as gap until we know better.
+ }
+
+ return false;
+}
+
+
+/**
* Skips the supplied char
*/
inline bool ImpSvNumberInputScan::SkipChar( sal_Unicode c, const OUString& rString,
@@ -575,7 +621,7 @@ short ImpSvNumberInputScan::GetMonth( const OUString& rString, sal_Int32& nPos )
// if we stopped at the first match.
for ( sal_Int16 i = 0; i < nMonths; i++ )
{
- if ( bScanGenitiveMonths && StringContains( pUpperGenitiveMonthText[i], rString, nPos ) )
+ if ( bScanGenitiveMonths && StringContainsWord( pUpperGenitiveMonthText[i], rString, nPos ) )
{ // genitive full names first
const int nMonthLen = pUpperGenitiveMonthText[i].getLength();
if (nMonthLen > nMatchLen)
@@ -584,7 +630,7 @@ short ImpSvNumberInputScan::GetMonth( const OUString& rString, sal_Int32& nPos )
res = i + 1;
}
}
- else if ( bScanGenitiveMonths && StringContains( pUpperGenitiveAbbrevMonthText[i], rString, nPos ) )
+ else if ( bScanGenitiveMonths && StringContainsWord( pUpperGenitiveAbbrevMonthText[i], rString, nPos ) )
{ // genitive abbreviated
const int nMonthLen = pUpperGenitiveAbbrevMonthText[i].getLength();
if (nMonthLen > nMatchLen)
@@ -593,7 +639,7 @@ short ImpSvNumberInputScan::GetMonth( const OUString& rString, sal_Int32& nPos )
res = sal::static_int_cast< short >(-(i+1)); // negative
}
}
- else if ( bScanPartitiveMonths && StringContains( pUpperPartitiveMonthText[i], rString, nPos ) )
+ else if ( bScanPartitiveMonths && StringContainsWord( pUpperPartitiveMonthText[i], rString, nPos ) )
{ // partitive full names
const int nMonthLen = pUpperPartitiveMonthText[i].getLength();
if (nMonthLen > nMatchLen)
@@ -602,7 +648,7 @@ short ImpSvNumberInputScan::GetMonth( const OUString& rString, sal_Int32& nPos )
res = i+1;
}
}
- else if ( bScanPartitiveMonths && StringContains( pUpperPartitiveAbbrevMonthText[i], rString, nPos ) )
+ else if ( bScanPartitiveMonths && StringContainsWord( pUpperPartitiveAbbrevMonthText[i], rString, nPos ) )
{ // partitive abbreviated
const int nMonthLen = pUpperPartitiveAbbrevMonthText[i].getLength();
if (nMonthLen > nMatchLen)
@@ -611,7 +657,7 @@ short ImpSvNumberInputScan::GetMonth( const OUString& rString, sal_Int32& nPos )
res = sal::static_int_cast< short >(-(i+1)); // negative
}
}
- else if ( StringContains( pUpperMonthText[i], rString, nPos ) )
+ else if ( StringContainsWord( pUpperMonthText[i], rString, nPos ) )
{ // noun full names
const int nMonthLen = pUpperMonthText[i].getLength();
if (nMonthLen > nMatchLen)
@@ -620,7 +666,7 @@ short ImpSvNumberInputScan::GetMonth( const OUString& rString, sal_Int32& nPos )
res = i+1;
}
}
- else if ( StringContains( pUpperAbbrevMonthText[i], rString, nPos ) )
+ else if ( StringContainsWord( pUpperAbbrevMonthText[i], rString, nPos ) )
{ // noun abbreviated
const int nMonthLen = pUpperAbbrevMonthText[i].getLength();
if (nMonthLen > nMatchLen)
@@ -630,7 +676,7 @@ short ImpSvNumberInputScan::GetMonth( const OUString& rString, sal_Int32& nPos )
}
}
else if ( i == 8 && pUpperAbbrevMonthText[i] == aSeptCorrect &&
- StringContains( aSepShortened, rString, nPos ) )
+ StringContainsWord( aSepShortened, rString, nPos ) )
{ // #102136# SEPT/SEP
const int nMonthLen = aSepShortened.getLength();
if (nMonthLen > nMatchLen)
@@ -665,13 +711,13 @@ int ImpSvNumberInputScan::GetDayOfWeek( const OUString& rString, sal_Int32& nPos
sal_Int16 nDays = pFormatter->GetCalendar()->getNumberOfDaysInWeek();
for ( sal_Int16 i = 0; i < nDays; i++ )
{
- if ( StringContains( pUpperDayText[i], rString, nPos ) )
+ if ( StringContainsWord( pUpperDayText[i], rString, nPos ) )
{ // full names first
nPos = nPos + pUpperDayText[i].getLength();
res = i + 1;
break; // for
}
- if ( StringContains( pUpperAbbrevDayText[i], rString, nPos ) )
+ if ( StringContainsWord( pUpperAbbrevDayText[i], rString, nPos ) )
{ // abbreviated
nPos = nPos + pUpperAbbrevDayText[i].getLength();
res = -(i + 1); // negative
diff --git a/svl/source/numbers/zforfind.hxx b/svl/source/numbers/zforfind.hxx
index 6e24040faa4f..002db2453270 100644
--- a/svl/source/numbers/zforfind.hxx
+++ b/svl/source/numbers/zforfind.hxx
@@ -210,6 +210,13 @@ private:
void NumberStringDivision( const OUString& rString );
+ /** Whether rString contains word (!) rWhat at nPos.
+ rWhat will not be matched if it is a substring of a word.
+ */
+ bool StringContainsWord( const OUString& rWhat,
+ const OUString& rString,
+ sal_Int32 nPos );
+
// optimized substring versions
// Whether rString contains rWhat at nPos