[Libreoffice-commits] .: 15 commits - i18npool/inc i18npool/source offapi/com offapi/UnoApi_offapi.mk sc/qa svl/source unotools/inc unotools/source
Eike Rathke
erack at kemper.freedesktop.org
Wed Jan 11 04:19:24 PST 2012
i18npool/inc/localedata.hxx | 7
i18npool/source/localedata/LocaleNode.cxx | 227 ++++++++++++++++
i18npool/source/localedata/data/bg_BG.xml | 4
i18npool/source/localedata/data/de_DE.xml | 1
i18npool/source/localedata/data/en_US.xml | 1
i18npool/source/localedata/data/es_BO.xml | 2
i18npool/source/localedata/data/ko_KR.xml | 2
i18npool/source/localedata/data/ku_TR.xml | 2
i18npool/source/localedata/data/locale.dtd | 17 +
i18npool/source/localedata/data/sl_SI.xml | 1
i18npool/source/localedata/data/tr_TR.xml | 14 -
i18npool/source/localedata/localedata.cxx | 27 ++
offapi/UnoApi_offapi.mk | 1
offapi/com/sun/star/i18n/LocaleData.idl | 4
offapi/com/sun/star/i18n/XLocaleData4.idl | 66 ++++
sc/qa/unit/ucalc.cxx | 8
svl/source/numbers/zforfind.cxx | 376 +++++++++++++++++++++++++---
svl/source/numbers/zforfind.hxx | 84 ++++++
svl/source/numbers/zformat.cxx | 26 +
unotools/inc/unotools/localedatawrapper.hxx | 5
unotools/source/i18n/localedatawrapper.cxx | 25 +
21 files changed, 827 insertions(+), 73 deletions(-)
New commits:
commit 51a5998433641aa62c4ce94af0be11d3c6e81852
Author: Eike Rathke <erack at redhat.com>
Date: Wed Jan 11 12:32:46 2012 +0100
adapted test case cell input to new date acceptance reality
Cell input in testDataPilotLabels() like 1.2.3 was prefixed with single
quote / apostrophe to not form a date input but string instead. With the
new date acceptance, in en-US locale 1.2.3 isn't a date anymore and the
quote becomes part of the cell content, so the test checking for 1.2.3
failed because the result was '1.2.3
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 18fb569..d45ddb4 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -1390,14 +1390,14 @@ void Test::testDataPilotLabels()
DPFieldDef aFields[] = {
{ "Software", sheet::DataPilotFieldOrientation_ROW },
{ "Version", sheet::DataPilotFieldOrientation_COLUMN },
- { "'1.2.3", sheet::DataPilotFieldOrientation_DATA }
+ { "1.2.3", sheet::DataPilotFieldOrientation_DATA }
};
// Raw data
const char* aData[][3] = {
- { "LibreOffice", "'3.3.0", "30" },
- { "LibreOffice", "'3.3.1", "20" },
- { "LibreOffice", "'3.4.0", "45" },
+ { "LibreOffice", "3.3.0", "30" },
+ { "LibreOffice", "3.3.1", "20" },
+ { "LibreOffice", "3.4.0", "45" },
};
size_t nFieldCount = SAL_N_ELEMENTS(aFields);
commit cfec56f89f295002b2b2b9f68cd8f62dcca7c59c
Author: Eike Rathke <erack at redhat.com>
Date: Tue Jan 10 16:46:17 2012 +0100
fdo#44636 use date acceptance patterns in number scanner
Get rid of the lax "any 1-2 possible date separators used with 2-3 numbers
forms a date" date recognition. Use locale data's DateAcceptancePattern
elements to match against, or ISO 8601 yyyy-mm-dd, or an already applied date
format.
diff --git a/svl/source/numbers/zforfind.cxx b/svl/source/numbers/zforfind.cxx
index ba315fc..7d6f99e 100644
--- a/svl/source/numbers/zforfind.cxx
+++ b/svl/source/numbers/zforfind.cxx
@@ -146,6 +146,8 @@ void ImpSvNumberInputScan::Reset()
nMayBeIso8601 = 0;
nTimezonePos = 0;
nMayBeMonthDate = 0;
+ nAcceptedDatePattern = -2;
+ nDatePatternStart = 0;
}
@@ -1034,6 +1036,227 @@ bool ImpSvNumberInputScan::MayBeMonthDate()
}
//---------------------------------------------------------------------------
+
+bool ImpSvNumberInputScan::IsAcceptedDatePattern( sal_uInt16 nStartPatternAt )
+{
+ if (nAcceptedDatePattern >= -1)
+ return (nAcceptedDatePattern >= 0);
+
+ if (!nAnzNums)
+ nAcceptedDatePattern = -1;
+ else if (!sDateAcceptancePatterns.getLength())
+ {
+ sDateAcceptancePatterns = pFormatter->GetLocaleData()->getDateAcceptancePatterns();
+ SAL_WARN_IF( !sDateAcceptancePatterns.getLength(), "nf.date", "ImpSvNumberInputScan::IsAcceptedDatePattern: no date acceptance patterns");
+ nAcceptedDatePattern = (sDateAcceptancePatterns.getLength() ? -2 : -1);
+ }
+
+ if (nAcceptedDatePattern == -1)
+ return false;
+
+ nDatePatternStart = nStartPatternAt; // remember start particle
+
+ for (sal_Int32 nPattern=0; nPattern < sDateAcceptancePatterns.getLength(); ++nPattern)
+ {
+ sal_uInt16 nNext = nDatePatternStart;
+ bool bOk = true;
+ const rtl::OUString& rPat = sDateAcceptancePatterns[nPattern];
+ sal_Int32 nPat = 0;
+ for ( ; nPat < rPat.getLength() && bOk && nNext < nAnzStrings; ++nPat, ++nNext)
+ {
+ switch (rPat[nPat])
+ {
+ case 'Y':
+ case 'M':
+ case 'D':
+ bOk = IsNum[nNext];
+ break;
+ default:
+ bOk = !IsNum[nNext];
+ if (bOk)
+ {
+ const xub_StrLen nLen = sStrArray[nNext].Len();
+ bOk = (rPat.indexOf( sStrArray[nNext], nPat) == nPat);
+ if (bOk)
+ nPat += nLen - 1;
+ else if (nPat + nLen > rPat.getLength() && sStrArray[nNext].GetChar(nLen-1) == ' ')
+ {
+ // Trailing blanks in input.
+ String aStr( sStrArray[nNext]);
+ aStr.EraseTrailingChars(' ');
+ // Expand again in case of pattern "M. D. " and
+ // input "M. D. ", maybe fetched far, but..
+ aStr.Expand( rPat.getLength() - nPat, ' ');
+ bOk = (rPat.indexOf( aStr, nPat) == nPat);
+ if (bOk)
+ nPat += aStr.Len() - 1;
+ }
+ }
+ break;
+ }
+ }
+ if (bOk)
+ {
+ // Check for trailing characters mismatch.
+ if (nNext < nAnzStrings)
+ {
+ // Pattern end but not input end.
+ if (!IsNum[nNext])
+ {
+ // Trailing (or separating if time follows) blanks are ok.
+ xub_StrLen nPos = 0;
+ SkipBlanks( sStrArray[nNext], nPos);
+ if (nPos == sStrArray[nNext].Len())
+ {
+ nAcceptedDatePattern = nPattern;
+ return true;
+ }
+ }
+ }
+ else if (nPat == rPat.getLength())
+ {
+ // Input end and pattern end => match.
+ nAcceptedDatePattern = nPattern;
+ return true;
+ }
+ // else Input end but not pattern end, no match.
+ }
+ }
+ nAcceptedDatePattern = -1;
+ return false;
+}
+
+//---------------------------------------------------------------------------
+
+bool ImpSvNumberInputScan::SkipDatePatternSeparator( sal_uInt16 nParticle, xub_StrLen & rPos )
+{
+ // If not initialized yet start with first number, if any.
+ if (!IsAcceptedDatePattern( (nAnzNums ? nNums[0] : 0)))
+ return false;
+
+ if (nParticle < nDatePatternStart || nParticle >= nAnzStrings || IsNum[nParticle])
+ return false;
+
+ sal_uInt16 nNext = nDatePatternStart;
+ const rtl::OUString& rPat = sDateAcceptancePatterns[nAcceptedDatePattern];
+ for (sal_Int32 nPat = 0; nPat < rPat.getLength() && nNext < nAnzStrings; ++nPat, ++nNext)
+ {
+ switch (rPat[nPat])
+ {
+ case 'Y':
+ case 'M':
+ case 'D':
+ break;
+ default:
+ if (nNext == nParticle)
+ {
+ const xub_StrLen nLen = sStrArray[nNext].Len();
+ bool bOk = (rPat.indexOf( sStrArray[nNext], nPat) == nPat);
+ if (!bOk && (nPat + nLen > rPat.getLength() && sStrArray[nNext].GetChar(nLen-1) == ' '))
+ {
+ // The same ugly trailing blanks check as in
+ // IsAcceptedDatePattern().
+ String aStr( sStrArray[nNext]);
+ aStr.EraseTrailingChars(' ');
+ aStr.Expand( rPat.getLength() - nPat, ' ');
+ bOk = (rPat.indexOf( aStr, nPat) == nPat);
+ }
+ if (bOk)
+ {
+ rPos = nLen; // yes, set, not add!
+ return true;
+ }
+ else
+ return false;
+ }
+ nPat += sStrArray[nNext].Len() - 1;
+ break;
+ }
+ }
+ return false;
+}
+
+//---------------------------------------------------------------------------
+
+sal_uInt32 ImpSvNumberInputScan::GetDatePatternOrder()
+{
+ // If not initialized yet start with first number, if any.
+ if (!IsAcceptedDatePattern( (nAnzNums ? nNums[0] : 0)))
+ return 0;
+
+ sal_uInt32 nOrder = 0;
+ const rtl::OUString& rPat = sDateAcceptancePatterns[nAcceptedDatePattern];
+ for (sal_Int32 nPat = 0; nPat < rPat.getLength() && !(nOrder & 0xff0000); ++nPat)
+ {
+ switch (rPat[nPat])
+ {
+ case 'Y':
+ case 'M':
+ case 'D':
+ nOrder = (nOrder << 8) | rPat[nPat];
+ break;
+ }
+ }
+ return nOrder;
+}
+
+//---------------------------------------------------------------------------
+
+DateFormat ImpSvNumberInputScan::GetDateOrder()
+{
+ sal_uInt32 nOrder = GetDatePatternOrder();
+ if (!nOrder)
+ return pFormatter->GetLocaleData()->getDateFormat();
+ switch ((nOrder & 0xff0000) >> 16)
+ {
+ case 'Y':
+ if ((((nOrder & 0xff00) >> 8) == 'M') && ((nOrder & 0xff) == 'D'))
+ return YMD;
+ break;
+ case 'M':
+ if ((((nOrder & 0xff00) >> 8) == 'D') && ((nOrder & 0xff) == 'Y'))
+ return MDY;
+ break;
+ case 'D':
+ if ((((nOrder & 0xff00) >> 8) == 'M') && ((nOrder & 0xff) == 'Y'))
+ return DMY;
+ break;
+ default:
+ case 0:
+ switch ((nOrder & 0xff00) >> 8)
+ {
+ case 'Y':
+ switch ((nOrder & 0xff))
+ {
+ case 'M':
+ return YMD;
+ }
+ break;
+ case 'M':
+ switch ((nOrder & 0xff))
+ {
+ case 'Y':
+ return DMY;
+ case 'D':
+ return MDY;
+ }
+ break;
+ case 'D':
+ switch ((nOrder & 0xff))
+ {
+ case 'Y':
+ return MDY;
+ case 'M':
+ return DMY;
+ }
+ break;
+ }
+ }
+ SAL_WARN( "nf.date", "ImpSvNumberInputScan::GetDateOrder: undefined, falling back to locale's default");
+ return pFormatter->GetLocaleData()->getDateFormat();
+}
+
+//---------------------------------------------------------------------------
// GetDateRef
bool ImpSvNumberInputScan::GetDateRef( double& fDays, sal_uInt16& nCounter,
@@ -1077,7 +1300,7 @@ bool ImpSvNumberInputScan::GetDateRef( double& fDays, sal_uInt16& nCounter,
{
case NF_EVALDATEFORMAT_INTL :
bFormatTurn = false;
- DateFmt = pLoc->getDateFormat();
+ DateFmt = GetDateOrder();
break;
case NF_EVALDATEFORMAT_FORMAT :
bFormatTurn = true;
@@ -1087,7 +1310,7 @@ bool ImpSvNumberInputScan::GetDateRef( double& fDays, sal_uInt16& nCounter,
if ( nTryOrder == 1 )
{
bFormatTurn = false;
- DateFmt = pLoc->getDateFormat();
+ DateFmt = GetDateOrder();
}
else
{
@@ -1099,7 +1322,7 @@ bool ImpSvNumberInputScan::GetDateRef( double& fDays, sal_uInt16& nCounter,
if ( nTryOrder == 2 )
{
bFormatTurn = false;
- DateFmt = pLoc->getDateFormat();
+ DateFmt = GetDateOrder();
}
else
{
@@ -1175,7 +1398,8 @@ input for the following reasons:
switch (DateFmt)
{
case MDY:
- case YMD: {
+ case YMD:
+ {
sal_uInt16 nDay = ImplGetDay(0);
sal_uInt16 nYear = ImplGetYear(0);
if (nDay == 0 || nDay > 32) {
@@ -1221,8 +1445,11 @@ input for the following reasons:
case 0: // not found
{
bool bHadExact;
- sal_uInt32 nExactDateOrder = (bFormatTurn ? pFormat->GetExactDateOrder() : 0);
- if ( 0xff < nExactDateOrder && nExactDateOrder <= 0xffff )
+ sal_uInt32 nExactDateOrder = (bFormatTurn ?
+ pFormat->GetExactDateOrder() :
+ GetDatePatternOrder());
+ bool bIsExact = (0xff < nExactDateOrder && nExactDateOrder <= 0xffff);
+ if (bIsExact)
{ // formatted as date and exactly 2 parts
bHadExact = true;
switch ( (nExactDateOrder >> 8) & 0xff )
@@ -1253,10 +1480,14 @@ input for the following reasons:
default:
bHadExact = false;
}
+ SAL_WARN_IF( !bHadExact, "nf.date", "ImpSvNumberInputScan::GetDateRef: error in exact date order");
}
else
bHadExact = false;
- if ( !bHadExact || !pCal->isValid() )
+ // If input matched against a date acceptance pattern
+ // do not attempt to mess around with guessing the
+ // order, either it matches or it doesn't.
+ if ((bFormatTurn || !bIsExact) && (!bHadExact || !pCal->isValid()))
{
if ( !bHadExact && nExactDateOrder )
pCal->setGregorianDateTime( Date( Date::SYSTEM ) ); // reset today
@@ -1620,6 +1851,11 @@ bool ImpSvNumberInputScan::ScanStartString( const String& rString,
SkipBlanks(rString, nPos);
}
}
+ if (!nMonth)
+ {
+ // Determine and remember following date pattern, if any.
+ IsAcceptedDatePattern( 1);
+ }
}
}
}
@@ -1673,7 +1909,8 @@ bool ImpSvNumberInputScan::ScanMidString( const String& rString,
return MatchedReturn();
else if (nDecPos == 2) // . dup: 12.4.
{
- if (bDecSepInDateSeps) // . also date separator
+ if (bDecSepInDateSeps // . also date separator
+ || SkipDatePatternSeparator( nStringPos, nPos))
{
if ( eScannedType != NUMBERFORMAT_UNDEFINED &&
eScannedType != NUMBERFORMAT_DATE &&
@@ -1727,10 +1964,15 @@ bool ImpSvNumberInputScan::ScanMidString( const String& rString,
}
const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
- const String& rDate = pFormatter->GetDateSep();
- SkipBlanks(rString, nPos);
- if (SkipString( rDate, rString, nPos) // 10. 10- 10/
- || ((MayBeIso8601() || MayBeMonthDate())
+ bool bDate = SkipDatePatternSeparator( nStringPos, nPos); // 12/31 31.12. 12/31/1999 31.12.1999
+ if (!bDate)
+ {
+ const String& rDate = pFormatter->GetDateSep();
+ SkipBlanks(rString, nPos);
+ bDate = SkipString( rDate, rString, nPos); // 10. 10- 10/
+ }
+ if (bDate
+ || ((MayBeIso8601() || MayBeMonthDate()) // 1999-12-31 31-Dec-1999
&& SkipChar( '-', rString, nPos)))
{
if ( eScannedType != NUMBERFORMAT_UNDEFINED // already another type
@@ -1915,7 +2157,8 @@ bool ImpSvNumberInputScan::ScanEndString( const String& rString,
return MatchedReturn();
else if (nDecPos == 2) // . dup: 12.4.
{
- if (bDecSepInDateSeps) // . also date sep
+ if (bDecSepInDateSeps // . also date separator
+ || SkipDatePatternSeparator( nAnzStrings-1, nPos))
{
if ( eScannedType != NUMBERFORMAT_UNDEFINED &&
eScannedType != NUMBERFORMAT_DATE &&
@@ -2006,8 +2249,13 @@ bool ImpSvNumberInputScan::ScanEndString( const String& rString,
nTimePos = nAnzStrings;
}
- const String& rDate = pFormatter->GetDateSep();
- if (SkipString( rDate, rString, nPos) // 10. 10- 10/
+ bool bDate = SkipDatePatternSeparator( nAnzStrings-1, nPos); // 12/31 31.12. 12/31/1999 31.12.1999
+ if (!bDate)
+ {
+ const String& rDate = pFormatter->GetDateSep();
+ bDate = SkipString( rDate, rString, nPos); // 10. 10- 10/
+ }
+ if (bDate
|| ((MayBeIso8601() || MayBeMonthDate())
&& SkipChar( '-', rString, nPos)))
{
@@ -2575,6 +2823,8 @@ void ImpSvNumberInputScan::ChangeIntl()
cDecSep == pFormatter->GetDateSep().GetChar(0) );
bTextInitialized = false;
aUpperCurrSymbol.Erase();
+ if (sDateAcceptancePatterns.getLength())
+ sDateAcceptancePatterns = ::com::sun::star::uno::Sequence< ::rtl::OUString >();
}
@@ -2690,23 +2940,9 @@ bool ImpSvNumberInputScan::IsNumberFormat(
{
if (nAnzNums > 3)
res = false;
- else if (nAnzNums == 2)
- { // check locale dependent abbreviation
- /* FIXME: here go locale data acceptance patterns
- * instead */
- // Only one separator, 11/23 yes, 23/11 yes, 11/23/
- // no, 23/11/ no, 11-23 yes, 23-11 no?, 11-23- no,
- // 23-11- no, 23.11 no, 23.11. yes.
- sal_Unicode cDateSep = pFormatter->GetDateSep().GetChar(0);
- if (cDateSep == '.' && (nAnzStrings == 3 ||
- (nNums[1]+1 < nAnzStrings &&
- sStrArray[nNums[1]+1].GetChar(0) != cDateSep)))
- res = false;
- else if ((cDateSep == '/' || cDateSep == '-') &&
- (nNums[1]+1 < nAnzStrings &&
- sStrArray[nNums[1]+1].GetChar(0) == cDateSep))
- res = false;
- }
+ else
+ res = IsAcceptedDatePattern( nNums[0]) ||
+ MayBeIso8601() || nMatchedAllStrings;
}
break;
@@ -2749,6 +2985,9 @@ bool ImpSvNumberInputScan::IsNumberFormat(
if (nAnzNums > 6)
res = false;
}
+ if (res)
+ res = IsAcceptedDatePattern( nNums[0]) ||
+ MayBeIso8601() || nMatchedAllStrings;
}
break;
diff --git a/svl/source/numbers/zforfind.hxx b/svl/source/numbers/zforfind.hxx
index 5d6cb85..ce6d897 100644
--- a/svl/source/numbers/zforfind.hxx
+++ b/svl/source/numbers/zforfind.hxx
@@ -30,6 +30,8 @@
#define _ZFORFIND_HXX
#include <tools/string.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <rtl/ustring.hxx>
class Date;
class SvNumberformat;
@@ -163,6 +165,21 @@ private:
*/
sal_uInt8 nMayBeMonthDate;
+ /** Input matched this locale dependent date acceptance pattern.
+ -2 if not checked yet, -1 if no match, >=0 matched pattern.
+
+ @see IsAcceptedDatePattern()
+ */
+ sal_Int32 nAcceptedDatePattern;
+ com::sun::star::uno::Sequence< rtl::OUString > sDateAcceptancePatterns;
+
+ /** If input matched a date acceptance pattern that starts at input
+ particle sStrArray[nDatePatternStart].
+
+ @see IsAcceptedDatePattern()
+ */
+ sal_uInt16 nDatePatternStart;
+
#ifdef _ZFORFIND_CXX // methods private to implementation
void Reset(); // Reset all variables before start of analysis
@@ -319,6 +336,35 @@ private:
// native number transliteration if necessary
void TransformInput( String& rString );
+ /** Whether input matches locale dependent date acceptance pattern.
+
+ @param nStartPatternAt
+ The pattern matching starts at input particle
+ sStrArray[nStartPatternAt].
+
+ NOTE: once called the result is remembered, subsequent calls with
+ different parameters do not check for a match and do not lead to a
+ different result.
+ */
+ bool IsAcceptedDatePattern( sal_uInt16 nStartPatternAt );
+
+ /** Sets (not advances!) rPos to sStrArray[nParticle].Len() if string
+ matches separator in pattern at nParticle.
+
+ @returns TRUE if separator matched.
+ */
+ bool SkipDatePatternSeparator( sal_uInt16 nParticle, xub_StrLen & rPos );
+
+ /** Obtain order of accepted date pattern coded as, for example,
+ ('D'<<16)|('M'<<8)|'Y'
+ */
+ sal_uInt32 GetDatePatternOrder();
+
+ /** Obtain date format order, from accepted date pattern if available or
+ otherwise the locale's default order.
+ */
+ DateFormat GetDateOrder();
+
#endif // _ZFORFIND_CXX
};
commit ac32bcac33e3326149fe700b2de4d22542d6c82a
Author: Eike Rathke <erack at redhat.com>
Date: Tue Jan 10 16:45:26 2012 +0100
[bg-BG] special DateAcceptancePattern "D.M.Y г."
Special special.. upper and lower case letter GHE and space and non-breaking
space.
diff --git a/i18npool/source/localedata/data/bg_BG.xml b/i18npool/source/localedata/data/bg_BG.xml
index 2abd5cc..80e8827 100644
--- a/i18npool/source/localedata/data/bg_BG.xml
+++ b/i18npool/source/localedata/data/bg_BG.xml
@@ -35,6 +35,10 @@
<MeasurementSystem>metric</MeasurementSystem>
</LC_CTYPE>
<LC_FORMAT replaceFrom="[CURRENCY]" replaceTo="[$лв.-402]">
+ <DateAcceptancePattern>D.M.Y г.</DateAcceptancePattern>
+ <DateAcceptancePattern>D.M.Y г.</DateAcceptancePattern>
+ <DateAcceptancePattern>D.M.YÂ Ð.</DateAcceptancePattern>
+ <DateAcceptancePattern>D.M.Y Ð.</DateAcceptancePattern>
<FormatElement msgid="FixedFormatskey1" default="true" type="medium" usage="FIXED_NUMBER" formatindex="0">
<FormatCode>General</FormatCode>
</FormatElement>
commit ee3315bb22282d8725bef07c5fe2789e215309af
Author: Eike Rathke <erack at redhat.com>
Date: Tue Jan 10 16:45:25 2012 +0100
[sl-SI] special DateAcceptancePattern "D. M. Y"
diff --git a/i18npool/source/localedata/data/sl_SI.xml b/i18npool/source/localedata/data/sl_SI.xml
index e61ce24..21514d3 100644
--- a/i18npool/source/localedata/data/sl_SI.xml
+++ b/i18npool/source/localedata/data/sl_SI.xml
@@ -35,6 +35,7 @@
<MeasurementSystem>metric</MeasurementSystem>
</LC_CTYPE>
<LC_FORMAT replaceFrom="[CURRENCY]" replaceTo="[$SIT-424]">
+ <DateAcceptancePattern>D. M. Y</DateAcceptancePattern>
<FormatElement msgid="FixedFormatskey1" default="true" type="medium" usage="FIXED_NUMBER" formatindex="0">
<FormatCode>Standard</FormatCode>
</FormatElement>
commit a2685c5fd47396589e0767c5926a5bdb9f7b3390
Author: Eike Rathke <erack at redhat.com>
Date: Tue Jan 10 16:45:24 2012 +0100
bumped locale data wrapper to use XLocaleData4 and provide date acceptance patterns
diff --git a/unotools/inc/unotools/localedatawrapper.hxx b/unotools/inc/unotools/localedatawrapper.hxx
index 0bfaa97..2f4186f 100644
--- a/unotools/inc/unotools/localedatawrapper.hxx
+++ b/unotools/inc/unotools/localedatawrapper.hxx
@@ -30,7 +30,7 @@
#define _UNOTOOLS_LOCALEDATAWRAPPER_HXX
#include <tools/string.hxx>
-#include <com/sun/star/i18n/XLocaleData3.hpp>
+#include <com/sun/star/i18n/XLocaleData4.hpp>
#include <com/sun/star/i18n/LocaleItem.hpp>
#include <com/sun/star/i18n/reservedWords.hpp>
#include <unotools/readwritemutexguard.hxx>
@@ -67,7 +67,7 @@ class UNOTOOLS_DLLPUBLIC LocaleDataWrapper
static sal_uInt8 nLocaleDataChecking; // 0:=dontknow, 1:=yes, 2:=no
::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xSMgr;
- ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XLocaleData3 > xLD;
+ ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XLocaleData4 > xLD;
::com::sun::star::lang::Locale aLocale;
::boost::shared_ptr< ::com::sun::star::i18n::Calendar2 > xDefaultCalendar;
::com::sun::star::i18n::LocaleDataItem aLocaleDataItem;
@@ -163,6 +163,7 @@ public:
::com::sun::star::i18n::ForbiddenCharacters getForbiddenCharacters() const;
::com::sun::star::uno::Sequence< ::rtl::OUString > getReservedWord() const;
::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > getAllInstalledLocaleNames() const;
+ ::com::sun::star::uno::Sequence< ::rtl::OUString > getDateAcceptancePatterns() const;
/// same as the wrapper implementation but static
static ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > getInstalledLocaleNames();
diff --git a/unotools/source/i18n/localedatawrapper.cxx b/unotools/source/i18n/localedatawrapper.cxx
index f6248e9..704415d 100644
--- a/unotools/source/i18n/localedatawrapper.cxx
+++ b/unotools/source/i18n/localedatawrapper.cxx
@@ -82,7 +82,7 @@ LocaleDataWrapper::LocaleDataWrapper(
bReservedWordValid( sal_False )
{
setLocale( rLocale );
- xLD = Reference< XLocaleData3 > (
+ xLD = Reference< XLocaleData4 > (
intl_createInstance( xSMgr, "com.sun.star.i18n.LocaleData",
"LocaleDataWrapper" ), uno::UNO_QUERY );
}
@@ -1950,4 +1950,27 @@ void LocaleDataWrapper::evaluateLocaleDataChecking()
return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Calendar2 >(0);
}
+
+// --- XLocaleData4 ----------------------------------------------------------
+
+::com::sun::star::uno::Sequence< ::rtl::OUString > LocaleDataWrapper::getDateAcceptancePatterns() const
+{
+ try
+ {
+ if ( xLD.is() )
+ return xLD->getDateAcceptancePatterns( getLocale() );
+ }
+ catch ( Exception& e )
+ {
+#ifdef DBG_UTIL
+ rtl::OStringBuffer aMsg("getDateAcceptancePatterns: Exception caught\n");
+ aMsg.append(rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8));
+ DBG_ERRORFILE(aMsg.getStr());
+#else
+ (void)e;
+#endif
+ }
+ return ::com::sun::star::uno::Sequence< ::rtl::OUString >(0);
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit ee660ba9b7bf83e21a9fb9bdcb10318e152ab988
Author: Eike Rathke <erack at redhat.com>
Date: Tue Jan 10 16:45:23 2012 +0100
added DateAcceptancePattern element
diff --git a/i18npool/source/localedata/data/de_DE.xml b/i18npool/source/localedata/data/de_DE.xml
index a83b3db..2b72bfa 100644
--- a/i18npool/source/localedata/data/de_DE.xml
+++ b/i18npool/source/localedata/data/de_DE.xml
@@ -35,6 +35,7 @@
<MeasurementSystem>metric</MeasurementSystem>
</LC_CTYPE>
<LC_FORMAT>
+ <DateAcceptancePattern>D.M.</DateAcceptancePattern>
<FormatElement msgid="FixedFormatskey1" default="true" type="medium" usage="FIXED_NUMBER" formatindex="0">
<FormatCode>Standard</FormatCode>
</FormatElement>
diff --git a/i18npool/source/localedata/data/en_US.xml b/i18npool/source/localedata/data/en_US.xml
index f6b771b..90ceee4 100644
--- a/i18npool/source/localedata/data/en_US.xml
+++ b/i18npool/source/localedata/data/en_US.xml
@@ -35,6 +35,7 @@
<MeasurementSystem>US</MeasurementSystem>
</LC_CTYPE>
<LC_FORMAT replaceFrom="[CURRENCY]" replaceTo="[$$-409]">
+ <DateAcceptancePattern>M/D</DateAcceptancePattern>
<FormatElement msgid="FixedFormatskey1" default="true" type="medium" usage="FIXED_NUMBER" formatindex="0">
<FormatCode>General</FormatCode>
</FormatElement>
diff --git a/i18npool/source/localedata/data/locale.dtd b/i18npool/source/localedata/data/locale.dtd
index d22c16f..ae4cec5 100644
--- a/i18npool/source/localedata/data/locale.dtd
+++ b/i18npool/source/localedata/data/locale.dtd
@@ -132,7 +132,7 @@
that otherwise inherit the format codes.
-->
-<!ELEMENT LC_FORMAT (FormatElement*) >
+<!ELEMENT LC_FORMAT (DateAcceptancePattern*, FormatElement*) >
<!-- All FormatElement elements must be given if the RefLocale mechanism is not used! -->
<!ATTLIST LC_FORMAT %RefLocale;>
<!ATTLIST LC_FORMAT %replaceFrom;>
@@ -145,6 +145,21 @@
to be omitted. LCIDs are defined in i18npool/inc/i18npool/lang.h
-->
+<!ELEMENT DateAcceptancePattern (#PCDATA)>
+<!-- Pattern that defines an input sequence match to be accepted as
+ (abbreviated) date. For example, in en_US locale "M/D" accepts an input of
+ 11/23 as CurrentYear-November-23 whereas 11/23/ would not be a date. In
+ de_DE locale "D.M." accepts an input of 23.11. as CurrentYear-November-23
+ whereas 23.11 would not be a date.
+
+ For each locale one pattern that matches a full date is automatically
+ generated from FormatElement formatIndex="21" and does not need to be
+ defined, for example "M/D/Y" or "D.M.Y", so only if you want abbreviations
+ to be in effect add some patterns.
+
+ NOTE: use only single letter D,M,Y. Multiple patterns can be defined.
+-->
+
<!ELEMENT LC_FORMAT_1 (FormatElement*) >
<!ATTLIST LC_FORMAT_1 %RefLocale;>
<!ATTLIST LC_FORMAT_1 %replaceFrom;>
commit b75958473503f7eca096b8843e57a031bbabe0ab
Author: Eike Rathke <erack at redhat.com>
Date: Tue Jan 10 16:44:42 2012 +0100
implemented date acceptance patterns API
diff --git a/i18npool/inc/localedata.hxx b/i18npool/inc/localedata.hxx
index a28f104..2453aa4 100644
--- a/i18npool/inc/localedata.hxx
+++ b/i18npool/inc/localedata.hxx
@@ -32,7 +32,7 @@
#include <comphelper/processfactory.hxx>
-#include <com/sun/star/i18n/XLocaleData3.hpp>
+#include <com/sun/star/i18n/XLocaleData4.hpp>
#include <cppuhelper/implbase2.hxx> // helper for implementations
@@ -74,7 +74,7 @@ inline sal_Bool operator ==(const com::sun::star::lang::Locale& l1, const com::s
class LocaleData : public cppu::WeakImplHelper2
<
- com::sun::star::i18n::XLocaleData3,
+ com::sun::star::i18n::XLocaleData4,
com::sun::star::lang::XServiceInfo
>
{
@@ -105,6 +105,9 @@ public:
virtual com::sun::star::uno::Sequence< com::sun::star::uno::Sequence< beans::PropertyValue > > SAL_CALL getContinuousNumberingLevels( const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
virtual com::sun::star::uno::Sequence< com::sun::star::uno::Reference< container::XIndexAccess > > SAL_CALL getOutlineNumberingLevels( const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
+ // XLocaleData4
+ virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL getDateAcceptancePatterns( const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
+
// following methods are used by indexentry service
virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL getIndexAlgorithm( const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
virtual rtl::OUString SAL_CALL getDefaultIndexAlgorithm( const com::sun::star::lang::Locale& rLocale ) throw(com::sun::star::uno::RuntimeException);
diff --git a/i18npool/source/localedata/LocaleNode.cxx b/i18npool/source/localedata/LocaleNode.cxx
index a7b653c..f2e8c45 100644
--- a/i18npool/source/localedata/LocaleNode.cxx
+++ b/i18npool/source/localedata/LocaleNode.cxx
@@ -31,6 +31,7 @@
#include <string.h>
#include <iostream>
#include <set>
+#include <vector>
#include <rtl/ustrbuf.hxx>
#include <sal/macros.h>
@@ -380,6 +381,9 @@ void LCInfoNode::generateCode (const OFileWriter &of) const
of.writeFunction("getLCInfo_", "0", "LCInfoArray");
}
+
+OUString aDateSep;
+
void LCCTYPENode::generateCode (const OFileWriter &of) const
{
const LocaleNode * sepNode = 0;
@@ -392,7 +396,7 @@ void LCCTYPENode::generateCode (const OFileWriter &of) const
of.writeAsciiString("\n\n");
of.writeParameter("LC_CTYPE_Unoid", str);;
- OUString aDateSep =
+ aDateSep =
writeParameterCheckLen( of, "DateSeparator", "dateSeparator", 1, 1);
OUString aThoSep =
writeParameterCheckLen( of, "ThousandSeparator", "thousandSeparator", 1, 1);
@@ -596,20 +600,20 @@ void LCCTYPENode::generateCode (const OFileWriter &of) const
static OUString sTheCurrencyReplaceTo;
static OUString sTheCompatibleCurrency;
+static OUString sTheDateEditFormat;
+static ::std::vector< OUString > theDateAcceptancePatterns;
sal_Int16 LCFormatNode::mnSection = 0;
sal_Int16 LCFormatNode::mnFormats = 0;
void LCFormatNode::generateCode (const OFileWriter &of) const
{
- OUString str;
- if (mnSection == 0)
- {
- sTheCurrencyReplaceTo = OUString();
- sTheCompatibleCurrency = OUString();
- }
- else if (mnSection >= 2)
+ if (mnSection >= 2)
incError("more than 2 LC_FORMAT sections");
+
+ theDateAcceptancePatterns.clear();
+
+ OUString str;
OUString strFrom( getAttr().getValueByName("replaceFrom"));
of.writeParameter("replaceFrom", strFrom, mnSection);
str = getAttr().getValueByName("replaceTo");
@@ -631,8 +635,10 @@ void LCFormatNode::generateCode (const OFileWriter &of) const
sTheCompatibleCurrency = str.copy( 2, nHyphen - 2);
}
}
+
::rtl::OUString useLocale = getAttr().getValueByName("ref");
- if (!useLocale.isEmpty()) {
+ if (!useLocale.isEmpty())
+ {
switch (mnSection)
{
case 0:
@@ -642,16 +648,28 @@ void LCFormatNode::generateCode (const OFileWriter &of) const
of.writeRefFunction("getAllFormats1_", useLocale, "replaceTo1");
break;
}
+ of.writeRefFunction("getDateAcceptancePatterns_", useLocale);
return;
}
+
sal_Int16 formatCount = mnFormats;
NameSet aMsgIdSet;
ValueSet aFormatIndexSet;
NameSet aDefaultsSet;
bool bCtypeIsRef = false;
- for (sal_Int16 i = 0; i< getNumberOfChildren() ; i++,formatCount++) {
+ for (sal_Int16 i = 0; i< getNumberOfChildren() ; i++, formatCount++)
+ {
LocaleNode * currNode = getChildAt (i);
+ if (currNode->getName().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateAcceptancePattern")))
+ {
+ if (mnSection > 0)
+ incError( "DateAcceptancePattern only handled in LC_FORMAT, not LC_FORMAT_1");
+ else
+ theDateAcceptancePatterns.push_back( currNode->getValue());
+ --formatCount;
+ continue; // for
+ }
OUString aUsage;
OUString aType;
OUString aFormatIndex;
@@ -705,6 +723,9 @@ void LCFormatNode::generateCode (const OFileWriter &of) const
const LocaleNode* pCtype = 0;
switch (formatindex)
{
+ case cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY :
+ sTheDateEditFormat = n->getValue();
+ break;
case cssi::NumberFormatIndex::NUMBER_1000DEC2 : // #,##0.00
case cssi::NumberFormatIndex::TIME_MMSS00 : // MM:SS.00
case cssi::NumberFormatIndex::TIME_HH_MMSS00 : // [HH]:MM:SS.00
@@ -962,6 +983,192 @@ void LCFormatNode::generateCode (const OFileWriter &of) const
}
mnFormats = mnFormats + formatCount;
+
+ if (mnSection == 0)
+ {
+ // Extract and add date acceptance pattern for full date, so we provide
+ // at least one valid pattern, even if the number parser doesn't need
+ // that one.
+ /* XXX NOTE: only simple [...] modifier and "..." quotes detected and
+ * ignored, not nested, no fancy stuff. */
+ sal_Int32 nIndex = 0;
+ // aDateSep can be empty if LC_CTYPE was a ref=..., determine from
+ // FormatCode then.
+ sal_uInt32 cDateSep = (aDateSep.isEmpty() ? 0 : aDateSep.iterateCodePoints( &nIndex));
+ nIndex = 0;
+ OUStringBuffer aPatternBuf(5);
+ sal_uInt8 nDetected = 0; // bits Y,M,D
+ bool bInModifier = false;
+ bool bQuoted = false;
+ while (nIndex < sTheDateEditFormat.getLength() && nDetected < 7)
+ {
+ sal_uInt32 cChar = sTheDateEditFormat.iterateCodePoints( &nIndex);
+ if (bInModifier)
+ {
+ if (cChar == ']')
+ bInModifier = false;
+ continue; // while
+ }
+ if (bQuoted)
+ {
+ if (cChar == '"')
+ bQuoted = false;
+ continue; // while
+ }
+ switch (cChar)
+ {
+ case 'Y':
+ case 'y':
+ if (!(nDetected & 4))
+ {
+ aPatternBuf.append( 'Y');
+ nDetected |= 4;
+ }
+ break;
+ case 'M':
+ case 'm':
+ if (!(nDetected & 2))
+ {
+ aPatternBuf.append( 'M');
+ nDetected |= 2;
+ }
+ break;
+ case 'D':
+ case 'd':
+ if (!(nDetected & 1))
+ {
+ aPatternBuf.append( 'D');
+ nDetected |= 1;
+ }
+ break;
+ case '[':
+ bInModifier = true;
+ break;
+ case '"':
+ bQuoted = true;
+ break;
+ case '\\':
+ cChar = sTheDateEditFormat.iterateCodePoints( &nIndex);
+ break;
+ case '-':
+ // Assume a YYYY-MM-DD format or some such. There are
+ // locales that use an ISO 8601 edit format regardless of
+ // what the locale data and other formats say, for example
+ // hu_HU.
+ cDateSep = cChar;
+ // fallthru
+ default:
+ if (!cDateSep)
+ cDateSep = cChar;
+ if (cChar == cDateSep)
+ aPatternBuf.append( OUString( &cDateSep, 1));
+ break;
+ // The localized legacy:
+ case 'A':
+ if (((nDetected & 7) == 3) || ((nDetected & 7) == 0))
+ {
+ // es DD/MM/AAAA
+ // fr JJ.MM.AAAA
+ // it GG/MM/AAAA
+ // fr_CA AAAA-MM-JJ
+ aPatternBuf.append( 'Y');
+ nDetected |= 4;
+ }
+ break;
+ case 'J':
+ if (((nDetected & 7) == 0) || ((nDetected & 7) == 6))
+ {
+ // fr JJ.MM.AAAA
+ // fr_CA AAAA-MM-JJ
+ aPatternBuf.append( 'D');
+ nDetected |= 1;
+ }
+ else if ((nDetected & 7) == 3)
+ {
+ // nl DD-MM-JJJJ
+ // de TT.MM.JJJJ
+ aPatternBuf.append( 'Y');
+ nDetected |= 4;
+ }
+ break;
+ case 'T':
+ if ((nDetected & 7) == 0)
+ {
+ // de TT.MM.JJJJ
+ aPatternBuf.append( 'D');
+ nDetected |= 1;
+ }
+ break;
+ case 'G':
+ if ((nDetected & 7) == 0)
+ {
+ // it GG/MM/AAAA
+ aPatternBuf.append( 'D');
+ nDetected |= 1;
+ }
+ break;
+ case 'P':
+ if ((nDetected & 7) == 0)
+ {
+ // fi PP.KK.VVVV
+ aPatternBuf.append( 'D');
+ nDetected |= 1;
+ }
+ break;
+ case 'K':
+ if ((nDetected & 7) == 1)
+ {
+ // fi PP.KK.VVVV
+ aPatternBuf.append( 'M');
+ nDetected |= 2;
+ }
+ break;
+ case 'V':
+ if ((nDetected & 7) == 3)
+ {
+ // fi PP.KK.VVVV
+ aPatternBuf.append( 'Y');
+ nDetected |= 4;
+ }
+ break;
+ }
+ }
+ OUString aPattern( aPatternBuf.makeStringAndClear());
+ if (((nDetected & 7) != 7) || aPattern.getLength() < 5)
+ {
+ incErrorStr( "failed to extract full date acceptance pattern", aPattern);
+ fprintf( stderr, " with DateSeparator '%s' from FormatCode '%s'\n",
+ OSTR( OUString( cDateSep)), OSTR( sTheDateEditFormat));
+ }
+ else
+ fprintf( stderr, "Generated date acceptance pattern: '%s' from '%s'\n",
+ OSTR( aPattern), OSTR( sTheDateEditFormat));
+ theDateAcceptancePatterns.push_back( aPattern);
+
+ sal_Int16 nbOfDateAcceptancePatterns = static_cast<sal_Int16>(theDateAcceptancePatterns.size());
+
+ for (sal_Int16 i = 0; i < nbOfDateAcceptancePatterns; ++i)
+ {
+ of.writeParameter("DateAcceptancePattern", theDateAcceptancePatterns[i], i);
+ }
+
+ of.writeAsciiString("static const sal_Int16 DateAcceptancePatternsCount = ");
+ of.writeInt( nbOfDateAcceptancePatterns);
+ of.writeAsciiString(";\n");
+
+ of.writeAsciiString("static const sal_Unicode* DateAcceptancePatternsArray[] = {\n");
+ for (sal_Int16 i = 0; i < nbOfDateAcceptancePatterns; ++i)
+ {
+ of.writeAsciiString("\t");
+ of.writeAsciiString("DateAcceptancePattern");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ }
+ of.writeAsciiString("};\n\n");
+
+ of.writeFunction("getDateAcceptancePatterns_", "DateAcceptancePatternsCount", "DateAcceptancePatternsArray");
+ }
+
++mnSection;
}
diff --git a/i18npool/source/localedata/localedata.cxx b/i18npool/source/localedata/localedata.cxx
index 2750297..f26a8fc 100644
--- a/i18npool/source/localedata/localedata.cxx
+++ b/i18npool/source/localedata/localedata.cxx
@@ -793,6 +793,33 @@ LocaleData::getAllFormats( const Locale& rLocale ) throw(RuntimeException)
return seq;
}
+
+Sequence< OUString > SAL_CALL
+LocaleData::getDateAcceptancePatterns( const Locale& rLocale ) throw(RuntimeException)
+{
+ sal_Unicode **patternsArray = NULL;
+
+ MyFunc_Type func = (MyFunc_Type) getFunctionSymbol( rLocale, "getDateAcceptancePatterns" );
+
+ if (func)
+ {
+ sal_Int16 patternsCount = 0;
+ patternsArray = func( patternsCount );
+ Sequence< OUString > seq( patternsCount );
+ for (sal_Int16 i = 0; i < patternsCount; ++i)
+ {
+ seq[i] = OUString( patternsArray[i] );
+ }
+ return seq;
+ }
+ else
+ {
+ Sequence< OUString > seq(0);
+ return seq;
+ }
+}
+
+
#define COLLATOR_OFFSET_ALGO 0
#define COLLATOR_OFFSET_DEFAULT 1
#define COLLATOR_OFFSET_RULE 2
commit 67edfdce616c6dc56395e05a09e098a0460b9313
Author: Eike Rathke <erack at redhat.com>
Date: Tue Jan 10 16:42:07 2012 +0100
made [es-BO] DateSeparator the '/' that is used in FormatCode
diff --git a/i18npool/source/localedata/data/es_BO.xml b/i18npool/source/localedata/data/es_BO.xml
index de7a17f..d6c2eca 100644
--- a/i18npool/source/localedata/data/es_BO.xml
+++ b/i18npool/source/localedata/data/es_BO.xml
@@ -16,7 +16,7 @@
</LC_INFO>
<LC_CTYPE>
<Separators>
- <DateSeparator>-</DateSeparator>
+ <DateSeparator>/</DateSeparator>
<ThousandSeparator>.</ThousandSeparator>
<DecimalSeparator>,</DecimalSeparator>
<TimeSeparator>:</TimeSeparator>
commit 899fe10b72522c833b7dc03312284db470952a28
Author: Eike Rathke <erack at redhat.com>
Date: Tue Jan 10 16:42:06 2012 +0100
made [tr-TR] use the defined '.' DateSeparator in FormatCode
diff --git a/i18npool/source/localedata/data/tr_TR.xml b/i18npool/source/localedata/data/tr_TR.xml
index 6c032ac..e106ab7 100644
--- a/i18npool/source/localedata/data/tr_TR.xml
+++ b/i18npool/source/localedata/data/tr_TR.xml
@@ -87,13 +87,13 @@
<FormatCode>DD.MM.YY</FormatCode>
</FormatElement>
<FormatElement msgid="DateFormatskey9" default="true" type="long" usage="DATE" formatindex="19">
- <FormatCode>DD/MM/YY</FormatCode>
+ <FormatCode>DD.MM.YY</FormatCode>
</FormatElement>
<FormatElement msgid="DateFormatskey8" default="true" type="medium" usage="DATE" formatindex="20">
- <FormatCode>DD/MM/YY</FormatCode>
+ <FormatCode>DD.MM.YY</FormatCode>
</FormatElement>
<FormatElement msgid="DateFormatskey7" default="false" type="medium" usage="DATE" formatindex="21">
- <FormatCode>DD/MM/YYYY</FormatCode>
+ <FormatCode>DD.MM.YYYY</FormatCode>
</FormatElement>
<FormatElement msgid="DateFormatskey10" default="false" type="long" usage="DATE" formatindex="22">
<FormatCode>D.MMM.YY</FormatCode>
@@ -134,10 +134,10 @@
<DefaultName>ISO 8601</DefaultName>
</FormatElement>
<FormatElement msgid="DateFormatskey3" default="false" type="medium" usage="DATE" formatindex="34">
- <FormatCode>MM/YY</FormatCode>
+ <FormatCode>MM.YY</FormatCode>
</FormatElement>
<FormatElement msgid="DateFormatskey4" default="false" type="medium" usage="DATE" formatindex="35">
- <FormatCode>DD/MMM</FormatCode>
+ <FormatCode>DD.MMM</FormatCode>
</FormatElement>
<FormatElement msgid="DateFormatskey5" default="false" type="medium" usage="DATE" formatindex="36">
<FormatCode>MMMM</FormatCode>
@@ -170,10 +170,10 @@
<FormatCode>[HH]:MM:SS,00</FormatCode>
</FormatElement>
<FormatElement msgid="DateTimeFormatskey1" default="true" type="medium" usage="DATE_TIME" formatindex="46">
- <FormatCode>DD/MM/YY HH:MM</FormatCode>
+ <FormatCode>DD.MM.YY HH:MM</FormatCode>
</FormatElement>
<FormatElement msgid="DateTimeFormatskey2" default="false" type="medium" usage="DATE_TIME" formatindex="47">
- <FormatCode>DD/MM/YYYY HH:MM:SS</FormatCode>
+ <FormatCode>DD.MM.YYYY HH:MM:SS</FormatCode>
</FormatElement>
</LC_FORMAT>
<LC_COLLATION ref="en_US" />
commit ed5882352207f25bdc8aeeb515c8d5ed39211ac1
Author: Eike Rathke <erack at redhat.com>
Date: Tue Jan 10 16:42:05 2012 +0100
made [ko-KR] DateSeparator the '/' that is used in FormatCode
diff --git a/i18npool/source/localedata/data/ko_KR.xml b/i18npool/source/localedata/data/ko_KR.xml
index 3a3fbb0..7762c6d 100644
--- a/i18npool/source/localedata/data/ko_KR.xml
+++ b/i18npool/source/localedata/data/ko_KR.xml
@@ -13,7 +13,7 @@
</LC_INFO>
<LC_CTYPE>
<Separators>
- <DateSeparator>-</DateSeparator>
+ <DateSeparator>/</DateSeparator>
<ThousandSeparator>,</ThousandSeparator>
<DecimalSeparator>.</DecimalSeparator>
<TimeSeparator>:</TimeSeparator>
commit 5c81423cc06a907da34d6954732ac5b405ab8296
Author: Eike Rathke <erack at redhat.com>
Date: Tue Jan 10 16:42:04 2012 +0100
made [ku-TR] DateSeparator the '/' that is used in FormatCode
though I strongly doubt the entire US-centric approach ...
diff --git a/i18npool/source/localedata/data/ku_TR.xml b/i18npool/source/localedata/data/ku_TR.xml
index 0413353..641f482 100644
--- a/i18npool/source/localedata/data/ku_TR.xml
+++ b/i18npool/source/localedata/data/ku_TR.xml
@@ -13,7 +13,7 @@
</LC_INFO>
<LC_CTYPE>
<Separators>
- <DateSeparator>.</DateSeparator>
+ <DateSeparator>/</DateSeparator>
<ThousandSeparator>,</ThousandSeparator>
<DecimalSeparator>.</DecimalSeparator>
<TimeSeparator>:</TimeSeparator>
commit 8b7354217de215a972341414c8a693bdfbfd13af
Author: Eike Rathke <erack at redhat.com>
Date: Tue Jan 10 16:42:03 2012 +0100
added date acceptance patterns API
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index b6c4bd4..e8f623e 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -2673,6 +2673,7 @@ $(eval $(call gb_UnoApiTarget_add_idlfiles,offapi,offapi/com/sun/star/i18n,\
XLocaleData \
XLocaleData2 \
XLocaleData3 \
+ XLocaleData4 \
XNativeNumberSupplier \
XNumberFormatCode \
XOrdinalSuffix \
diff --git a/offapi/com/sun/star/i18n/LocaleData.idl b/offapi/com/sun/star/i18n/LocaleData.idl
index 5a32dcc..7885741 100644
--- a/offapi/com/sun/star/i18n/LocaleData.idl
+++ b/offapi/com/sun/star/i18n/LocaleData.idl
@@ -30,8 +30,7 @@
#define __com_sun_star_i18n_LocaleData_idl__
#include <com/sun/star/lang/XServiceInfo.idl>
-#include <com/sun/star/i18n/XLocaleData2.idl>
-#include <com/sun/star/i18n/XLocaleData3.idl>
+#include <com/sun/star/i18n/XLocaleData4.idl>
//============================================================================
@@ -47,6 +46,7 @@ published service LocaleData
[optional] interface com::sun::star::i18n::XLocaleData2;
[optional] interface com::sun::star::i18n::XLocaleData3;
+ [optional] interface com::sun::star::i18n::XLocaleData4;
};
//============================================================================
diff --git a/offapi/com/sun/star/i18n/XLocaleData4.idl b/offapi/com/sun/star/i18n/XLocaleData4.idl
new file mode 100644
index 0000000..154edfa
--- /dev/null
+++ b/offapi/com/sun/star/i18n/XLocaleData4.idl
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Major Contributor(s):
+ * Copyright (C) 2011 Red Hat, Inc., Eike Rathke <erack at redhat.com>
+ * (initial developer)
+ *
+ * All Rights Reserved.
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+
+#ifndef __com_sun_star_i18n_XLocaleData4_idl__
+#define __com_sun_star_i18n_XLocaleData4_idl__
+
+#include <com/sun/star/i18n/XLocaleData3.idl>
+
+//============================================================================
+
+module com { module sun { module star { module i18n {
+
+//============================================================================
+
+/**
+ Access locale specific data.
+
+ <p> Derived from <type scope="::com::sun::star::i18n">XLocaleData3</type>
+ this provides an additional method to return a sequence of date
+ acceptance patterns for a locale.
+
+ @since LibreOffice 3.6
+ */
+
+published interface XLocaleData4 : com::sun::star::i18n::XLocaleData3
+{
+ /** returns a sequence of date acceptance patterns for a locale
+
+ <p> Patterns with input combinations that are accepted as
+ incomplete date input, such as <b>M/D</b> or <b>D.M.</b>
+ */
+ sequence< string > getDateAcceptancePatterns(
+ [in] com::sun::star::lang::Locale aLocale );
+};
+
+//============================================================================
+}; }; }; };
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit f6c465e3555c8ac9d2902b3ac35f2d4784eed4c9
Author: Eike Rathke <erack at redhat.com>
Date: Tue Jan 10 16:42:02 2012 +0100
lower date acceptance with only two numbers
diff --git a/svl/source/numbers/zforfind.cxx b/svl/source/numbers/zforfind.cxx
index 3cf61e1..ba315fc 100644
--- a/svl/source/numbers/zforfind.cxx
+++ b/svl/source/numbers/zforfind.cxx
@@ -2690,6 +2690,23 @@ bool ImpSvNumberInputScan::IsNumberFormat(
{
if (nAnzNums > 3)
res = false;
+ else if (nAnzNums == 2)
+ { // check locale dependent abbreviation
+ /* FIXME: here go locale data acceptance patterns
+ * instead */
+ // Only one separator, 11/23 yes, 23/11 yes, 11/23/
+ // no, 23/11/ no, 11-23 yes, 23-11 no?, 11-23- no,
+ // 23-11- no, 23.11 no, 23.11. yes.
+ sal_Unicode cDateSep = pFormatter->GetDateSep().GetChar(0);
+ if (cDateSep == '.' && (nAnzStrings == 3 ||
+ (nNums[1]+1 < nAnzStrings &&
+ sStrArray[nNums[1]+1].GetChar(0) != cDateSep)))
+ res = false;
+ else if ((cDateSep == '/' || cDateSep == '-') &&
+ (nNums[1]+1 < nAnzStrings &&
+ sStrArray[nNums[1]+1].GetChar(0) == cDateSep))
+ res = false;
+ }
}
break;
commit 8298a4741d95034f65c648dddfae081f44cf9455
Author: Eike Rathke <erack at redhat.com>
Date: Tue Jan 10 16:42:01 2012 +0100
strict date recognition using locale's separator and ISO 8601
- Removed separators '-', '.' and '/' working in all combinations in all
locales forcing a date even for 23/12.99 (if locale has DMY order)
* Only the locale's date separator is accepted, plus '-' if the input may
represent an ISO 8601 date yyyy-mm-dd, check is lax though on minimum
digits, y-m-d is also accepted.
* Additionally, accept yy-month-dd or dd-month-yy with month name. Year must
be <1 or >31, 2-digit year magic for values 0,32..99 is applied, or has to
be prefixed with leading zero.
diff --git a/svl/source/numbers/zforfind.cxx b/svl/source/numbers/zforfind.cxx
index 3df9232..3cf61e1 100644
--- a/svl/source/numbers/zforfind.cxx
+++ b/svl/source/numbers/zforfind.cxx
@@ -145,6 +145,7 @@ void ImpSvNumberInputScan::Reset()
nMatchedAllStrings = nMatchedVirgin;
nMayBeIso8601 = 0;
nTimezonePos = 0;
+ nMayBeMonthDate = 0;
}
@@ -995,6 +996,44 @@ bool ImpSvNumberInputScan::MayBeIso8601()
}
//---------------------------------------------------------------------------
+
+bool ImpSvNumberInputScan::MayBeMonthDate()
+{
+ if (nMayBeMonthDate == 0)
+ {
+ nMayBeMonthDate = 1;
+ if (nAnzNums >= 2 && nNums[1] < nAnzStrings)
+ {
+ // "-Jan-"
+ const String& rM = sStrArray[nNums[0]+1];
+ if (rM.Len() >= 3 && rM.GetChar(0) == '-' && rM.GetChar( rM.Len()-1) == '-')
+ {
+ // Check year length assuming at least 3 digits (including
+ // leading zero). Two digit years 1..31 are out of luck here
+ // and may be taken as day of month.
+ bool bYear1 = (sStrArray[nNums[0]].Len() >= 3);
+ bool bYear2 = (sStrArray[nNums[1]].Len() >= 3);
+ sal_Int32 n;
+ bool bDay1 = (!bYear1 && (n = sStrArray[nNums[0]].ToInt32()) >= 1 && n <= 31);
+ bool bDay2 = (!bYear2 && (n = sStrArray[nNums[1]].ToInt32()) >= 1 && n <= 31);
+ if (bDay1 && !bDay2)
+ nMayBeMonthDate = 2; // dd-month-yy
+ else if (!bDay1 && bDay2)
+ nMayBeMonthDate = 3; // yy-month-dd
+ else if (bDay1 && bDay2)
+ {
+ if (bYear1 && !bYear2)
+ nMayBeMonthDate = 3; // yy-month-dd
+ else if (!bYear1 && bYear2)
+ nMayBeMonthDate = 2; // dd-month-yy
+ }
+ }
+ }
+ }
+ return nMayBeMonthDate > 1;
+}
+
+//---------------------------------------------------------------------------
// GetDateRef
bool ImpSvNumberInputScan::GetDateRef( double& fDays, sal_uInt16& nCounter,
@@ -1283,10 +1322,11 @@ input for the following reasons:
}
break;
case 2: // month in the middle (10 Jan 94)
+ {
pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
- switch (DateFmt)
+ DateFormat eDF = (MayBeMonthDate() ? (nMayBeMonthDate == 2 ? DMY : YMD) : DateFmt);
+ switch (eDF)
{
- case MDY: // yes, "10-Jan-94" is valid
case DMY:
pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
@@ -1299,7 +1339,8 @@ input for the following reasons:
res = false;
break;
}
- break;
+ }
+ break;
default: // else, e.g. month at the end (94 10 Jan)
res = false;
break;
@@ -1687,13 +1728,10 @@ bool ImpSvNumberInputScan::ScanMidString( const String& rString,
const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
const String& rDate = pFormatter->GetDateSep();
- const String& rTime = pLoc->getTimeSep();
- sal_Unicode cTime = rTime.GetChar(0);
SkipBlanks(rString, nPos);
- if ( SkipString(rDate, rString, nPos) // 10., 10-, 10/
- || ((cTime != '.') && SkipChar('.', rString, nPos)) // TRICKY:
- || ((cTime != '/') && SkipChar('/', rString, nPos)) // short boolean
- || ((cTime != '-') && SkipChar('-', rString, nPos)) ) // evaluation!
+ if (SkipString( rDate, rString, nPos) // 10. 10- 10/
+ || ((MayBeIso8601() || MayBeMonthDate())
+ && SkipChar( '-', rString, nPos)))
{
if ( eScannedType != NUMBERFORMAT_UNDEFINED // already another type
&& eScannedType != NUMBERFORMAT_DATE) // except date
@@ -1752,6 +1790,7 @@ bool ImpSvNumberInputScan::ScanMidString( const String& rString,
SkipBlanks(rString, nPos);
}
+ const String& rTime = pLoc->getTimeSep();
if ( SkipString(rTime, rString, nPos) ) // time separator?
{
if (nDecPos) // already . => maybe error
@@ -1945,7 +1984,6 @@ bool ImpSvNumberInputScan::ScanEndString( const String& rString,
}
const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
- const String& rDate = pFormatter->GetDateSep();
const String& rTime = pLoc->getTimeSep();
if ( SkipString(rTime, rString, nPos) ) // 10:
{
@@ -1968,11 +2006,10 @@ bool ImpSvNumberInputScan::ScanEndString( const String& rString,
nTimePos = nAnzStrings;
}
- sal_Unicode cTime = rTime.GetChar(0);
- if ( SkipString(rDate, rString, nPos) // 10., 10-, 10/
- || ((cTime != '.') && SkipChar('.', rString, nPos)) // TRICKY:
- || ((cTime != '/') && SkipChar('/', rString, nPos)) // short boolean
- || ((cTime != '-') && SkipChar('-', rString, nPos)) ) // evaluation!
+ const String& rDate = pFormatter->GetDateSep();
+ if (SkipString( rDate, rString, nPos) // 10. 10- 10/
+ || ((MayBeIso8601() || MayBeMonthDate())
+ && SkipChar( '-', rString, nPos)))
{
if (eScannedType != NUMBERFORMAT_UNDEFINED &&
eScannedType != NUMBERFORMAT_DATE) // already another type
@@ -2535,8 +2572,6 @@ void ImpSvNumberInputScan::ChangeIntl()
{
sal_Unicode cDecSep = pFormatter->GetNumDecimalSep().GetChar(0);
bDecSepInDateSeps = ( cDecSep == '-' ||
- cDecSep == '/' ||
- cDecSep == '.' ||
cDecSep == pFormatter->GetDateSep().GetChar(0) );
bTextInitialized = false;
aUpperCurrSymbol.Erase();
diff --git a/svl/source/numbers/zforfind.hxx b/svl/source/numbers/zforfind.hxx
index 02e08d4..5d6cb85 100644
--- a/svl/source/numbers/zforfind.hxx
+++ b/svl/source/numbers/zforfind.hxx
@@ -78,6 +78,11 @@ public:
*/
bool MayBeIso8601();
+ /** Whether input may be a dd-month-yy format, with month name, not
+ number.
+ */
+ bool MayBeMonthDate();
+
private:
SvNumberFormatter* pFormatter;
String* pUpperMonthText; // Array of month names, uppercase
@@ -136,14 +141,28 @@ private:
sal_uInt16 nTimezonePos; // Index of timezone separator (+1)
/** State of ISO 8601 detection.
+
0:= don't know yet
1:= no
2:= yes, <=2 digits in year
3:= yes, 3 digits in year
4:= yes, >=4 digits in year
+
+ @see MayBeIso8601()
*/
sal_uInt8 nMayBeIso8601;
+ /** State of dd-month-yy or yy-month-dd detection, with month name.
+
+ 0:= don't know yet
+ 1:= no
+ 2:= yes, dd-month-yy
+ 3:= yes, yy-month-dd
+
+ @see MayBeMonthDate()
+ */
+ sal_uInt8 nMayBeMonthDate;
+
#ifdef _ZFORFIND_CXX // methods private to implementation
void Reset(); // Reset all variables before start of analysis
commit 958cdbdcf5e35c04e259a69e972684060f1b3d12
Author: Eike Rathke <erack at redhat.com>
Date: Tue Jan 10 16:42:01 2012 +0100
accept and display years < 100
+ Years < 100 without being hit by the 2 digits year magic can be entered by
preceding them with a leading 0 if at least 3 digits are present, e.g.
099-1-1 is year 99, not 1999.
+ Years < 100 in an yyyy format are always displayed as 0099.
diff --git a/svl/source/numbers/zforfind.cxx b/svl/source/numbers/zforfind.cxx
index ef76fac..3df9232 100644
--- a/svl/source/numbers/zforfind.cxx
+++ b/svl/source/numbers/zforfind.cxx
@@ -957,10 +957,14 @@ sal_uInt16 ImpSvNumberInputScan::ImplGetYear( sal_uInt16 nIndex )
{
sal_uInt16 nYear = 0;
- if (sStrArray[nNums[nIndex]].Len() <= 4)
+ xub_StrLen nLen = sStrArray[nNums[nIndex]].Len();
+ if (nLen <= 4)
{
nYear = (sal_uInt16) sStrArray[nNums[nIndex]].ToInt32();
- nYear = SvNumberFormatter::ExpandTwoDigitYear( nYear, nYear2000 );
+ // A year < 100 entered with at least 3 digits with leading 0 is taken
+ // as is without expansion.
+ if (nYear < 100 && nLen < 3)
+ nYear = SvNumberFormatter::ExpandTwoDigitYear( nYear, nYear2000 );
}
return nYear;
@@ -972,13 +976,22 @@ bool ImpSvNumberInputScan::MayBeIso8601()
{
if (nMayBeIso8601 == 0)
{
- if (nAnzNums >= 3 && nNums[0] < nAnzStrings &&
- sStrArray[nNums[0]].ToInt32() > 31)
- nMayBeIso8601 = 1;
- else
- nMayBeIso8601 = 2;
+ nMayBeIso8601 = 1;
+ xub_StrLen nLen = ((nAnzNums >= 1 && nNums[0] < nAnzStrings) ? sStrArray[nNums[0]].Len() : 0);
+ if (nLen)
+ {
+ sal_Int32 n;
+ if (nAnzNums >= 3 && nNums[2] < nAnzStrings &&
+ sStrArray[nNums[0]+1] == '-' && // separator year-month
+ (n = sStrArray[nNums[1]].ToInt32()) >= 1 && n <= 12 && // month
+ sStrArray[nNums[1]+1] == '-' && // separator month-day
+ (n = sStrArray[nNums[2]].ToInt32()) >= 1 && n <= 31) // day
+ // Year (nNums[0]) value not checked, may be anything, but
+ // length (number of digits) is checked.
+ nMayBeIso8601 = (nLen >= 4 ? 4 : (nLen == 3 ? 3 : (nLen > 0 ? 2 : 0)));
+ }
}
- return nMayBeIso8601 == 1;
+ return nMayBeIso8601 > 1;
}
//---------------------------------------------------------------------------
diff --git a/svl/source/numbers/zforfind.hxx b/svl/source/numbers/zforfind.hxx
index 9c557b7..02e08d4 100644
--- a/svl/source/numbers/zforfind.hxx
+++ b/svl/source/numbers/zforfind.hxx
@@ -69,8 +69,13 @@ public:
/// get threshold of two-digit year input
sal_uInt16 GetYear2000() const { return nYear2000; }
- // Whether input may be a ISO 8601 date format, yyyy-mm-dd...
- // checks if at least 3 numbers and first number>31
+ /** Whether input may be an ISO 8601 date format, yyyy-mm-dd...
+
+ Checks if input has at least 3 numbers for yyyy-mm-dd and the separator
+ is '-', and 1<=mm<=12 and 1<=dd<=31.
+
+ @see nMayBeIso8601
+ */
bool MayBeIso8601();
private:
@@ -129,7 +134,15 @@ private:
// number <= nYear2000 => 20xx
// number > nYear2000 => 19xx
sal_uInt16 nTimezonePos; // Index of timezone separator (+1)
- sal_uInt8 nMayBeIso8601; // 0:=dontknowyet, 1:=yes, 2:=no
+
+ /** State of ISO 8601 detection.
+ 0:= don't know yet
+ 1:= no
+ 2:= yes, <=2 digits in year
+ 3:= yes, 3 digits in year
+ 4:= yes, >=4 digits in year
+ */
+ sal_uInt8 nMayBeIso8601;
#ifdef _ZFORFIND_CXX // methods private to implementation
void Reset(); // Reset all variables before start of analysis
diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx
index d796980..1976ec9 100644
--- a/svl/source/numbers/zformat.cxx
+++ b/svl/source/numbers/zformat.cxx
@@ -3387,8 +3387,19 @@ bool SvNumberformat::ImpGetDateOutput(double fNumber,
{
if ( bOtherCalendar )
SwitchToGregorianCalendar( aOrgCalendar, fOrgDateTime );
- OutString += rCal.getDisplayString(
+ String aYear = rCal.getDisplayString(
CalendarDisplayCode::LONG_YEAR, nNatNum );
+ if (aYear.Len() < 4)
+ {
+ // Ensure that year consists of at least 4 digits, so it
+ // can be distinguished from 2 digits display and edited
+ // without suddenly being hit by the 2-digit year magic.
+ String aZero;
+ aZero.Fill( 4 - aYear.Len(), sal_Unicode('0'));
+ ImpTransliterate( aZero, NumFor[nIx].GetNatNum());
+ aYear.Insert( aZero, 0);
+ }
+ OutString += aYear;
if ( bOtherCalendar )
SwitchToOtherCalendar( aOrgCalendar, fOrgDateTime );
}
@@ -3710,8 +3721,19 @@ bool SvNumberformat::ImpGetDateTimeOutput(double fNumber,
{
if ( bOtherCalendar )
SwitchToGregorianCalendar( aOrgCalendar, fOrgDateTime );
- OutString += rCal.getDisplayString(
+ String aYear = rCal.getDisplayString(
CalendarDisplayCode::LONG_YEAR, nNatNum );
+ if (aYear.Len() < 4)
+ {
+ // Ensure that year consists of at least 4 digits, so it
+ // can be distinguished from 2 digits display and edited
+ // without suddenly being hit by the 2-digit year magic.
+ String aZero;
+ aZero.Fill( 4 - aYear.Len(), sal_Unicode('0'));
+ ImpTransliterate( aZero, NumFor[nIx].GetNatNum());
+ aYear.Insert( aZero, 0);
+ }
+ OutString += aYear;
if ( bOtherCalendar )
SwitchToOtherCalendar( aOrgCalendar, fOrgDateTime );
}
More information about the Libreoffice-commits
mailing list