Handle quotes in wxTranslateFromUnicodeFormat.
When parsing Unicode date formats text inside single quotes should not be escaped and instead treated as literal text. In addition two single quotes (either inside or outside quoted text) should be interpreted as a single quote. Fixes #16118.
This commit is contained in:
@@ -1135,6 +1135,22 @@ wxString wxLocale::GetHeaderValue(const wxString& header,
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
bool IsAtTwoSingleQuotes(const wxString& fmt, wxString::const_iterator p)
|
||||||
|
{
|
||||||
|
if ( p != fmt.end() && *p == '\'')
|
||||||
|
{
|
||||||
|
++p;
|
||||||
|
if ( p != fmt.end() && *p == '\'')
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
// This function translates from Unicode date formats described at
|
// This function translates from Unicode date formats described at
|
||||||
//
|
//
|
||||||
// http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns
|
// http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns
|
||||||
@@ -1142,7 +1158,7 @@ namespace
|
|||||||
// to strftime()-like syntax. This translation is not lossless but we try to do
|
// to strftime()-like syntax. This translation is not lossless but we try to do
|
||||||
// our best.
|
// our best.
|
||||||
|
|
||||||
static wxString TranslateFromUnicodeFormat(const wxString& fmt)
|
wxString wxTranslateFromUnicodeFormat(const wxString& fmt)
|
||||||
{
|
{
|
||||||
wxString fmtWX;
|
wxString fmtWX;
|
||||||
fmtWX.reserve(fmt.length());
|
fmtWX.reserve(fmt.length());
|
||||||
@@ -1385,6 +1401,49 @@ static wxString TranslateFromUnicodeFormat(const wxString& fmt)
|
|||||||
if ( p == fmt.end() )
|
if ( p == fmt.end() )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Handle single quotes:
|
||||||
|
"Two single quotes represents [sic] a literal single quote, either
|
||||||
|
inside or outside single quotes. Text within single quotes is not
|
||||||
|
interpreted in any way (except for two adjacent single quotes)."
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( IsAtTwoSingleQuotes(fmt, p) )
|
||||||
|
{
|
||||||
|
fmtWX += '\'';
|
||||||
|
++p; // the 2nd single quote is skipped by the for loop's increment
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEndQuote = false;
|
||||||
|
if ( *p == '\'' )
|
||||||
|
{
|
||||||
|
++p;
|
||||||
|
while ( p != fmt.end() )
|
||||||
|
{
|
||||||
|
if ( IsAtTwoSingleQuotes(fmt, p) )
|
||||||
|
{
|
||||||
|
fmtWX += '\'';
|
||||||
|
p += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( *p == '\'' )
|
||||||
|
{
|
||||||
|
isEndQuote = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fmtWX += *p;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( p == fmt.end() )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ( !isEndQuote )
|
||||||
|
{
|
||||||
// not a special character so must be just a separator, treat as is
|
// not a special character so must be just a separator, treat as is
|
||||||
if ( *p == wxT('%') )
|
if ( *p == wxT('%') )
|
||||||
{
|
{
|
||||||
@@ -1394,11 +1453,11 @@ static wxString TranslateFromUnicodeFormat(const wxString& fmt)
|
|||||||
|
|
||||||
fmtWX += *p;
|
fmtWX += *p;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return fmtWX;
|
return fmtWX;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
#endif // __WINDOWS__ || __WXOSX__
|
#endif // __WINDOWS__ || __WXOSX__
|
||||||
|
|
||||||
@@ -1476,7 +1535,7 @@ GetInfoFromLCID(LCID lcid,
|
|||||||
if ( ::GetLocaleInfo(lcid, GetLCTYPEFormatFromLocalInfo(index),
|
if ( ::GetLocaleInfo(lcid, GetLCTYPEFormatFromLocalInfo(index),
|
||||||
buf, WXSIZEOF(buf)) )
|
buf, WXSIZEOF(buf)) )
|
||||||
{
|
{
|
||||||
return TranslateFromUnicodeFormat(buf);
|
return wxTranslateFromUnicodeFormat(buf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1630,7 +1689,7 @@ wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat))
|
|||||||
wxCFRef<CFDateFormatterRef> dateFormatter( CFDateFormatterCreate
|
wxCFRef<CFDateFormatterRef> dateFormatter( CFDateFormatterCreate
|
||||||
(NULL, userLocaleRef, dateStyle, timeStyle));
|
(NULL, userLocaleRef, dateStyle, timeStyle));
|
||||||
wxCFStringRef cfs = wxCFRetain( CFDateFormatterGetFormat(dateFormatter ));
|
wxCFStringRef cfs = wxCFRetain( CFDateFormatterGetFormat(dateFormatter ));
|
||||||
wxString format = TranslateFromUnicodeFormat(cfs.AsString());
|
wxString format = wxTranslateFromUnicodeFormat(cfs.AsString());
|
||||||
// we always want full years
|
// we always want full years
|
||||||
format.Replace("%y","%Y");
|
format.Replace("%y","%Y");
|
||||||
return format;
|
return format;
|
||||||
|
@@ -232,6 +232,7 @@ private:
|
|||||||
CPPUNIT_TEST( TestTimeArithmetics );
|
CPPUNIT_TEST( TestTimeArithmetics );
|
||||||
CPPUNIT_TEST( TestDSTBug );
|
CPPUNIT_TEST( TestDSTBug );
|
||||||
CPPUNIT_TEST( TestDateOnly );
|
CPPUNIT_TEST( TestDateOnly );
|
||||||
|
CPPUNIT_TEST( TestTranslateFromUnicodeFormat );
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
void TestLeapYears();
|
void TestLeapYears();
|
||||||
@@ -252,6 +253,7 @@ private:
|
|||||||
void TestTimeArithmetics();
|
void TestTimeArithmetics();
|
||||||
void TestDSTBug();
|
void TestDSTBug();
|
||||||
void TestDateOnly();
|
void TestDateOnly();
|
||||||
|
void TestTranslateFromUnicodeFormat();
|
||||||
|
|
||||||
DECLARE_NO_COPY_CLASS(DateTimeTestCase)
|
DECLARE_NO_COPY_CLASS(DateTimeTestCase)
|
||||||
};
|
};
|
||||||
@@ -1447,4 +1449,37 @@ void DateTimeTestCase::TestDateOnly()
|
|||||||
CPPUNIT_ASSERT_EQUAL( wxDateTime::Today(), wxDateTime::Now().GetDateOnly() );
|
CPPUNIT_ASSERT_EQUAL( wxDateTime::Today(), wxDateTime::Now().GetDateOnly() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Forward declaration
|
||||||
|
wxString wxTranslateFromUnicodeFormat(const wxString& fmt);
|
||||||
|
|
||||||
|
void DateTimeTestCase::TestTranslateFromUnicodeFormat()
|
||||||
|
{
|
||||||
|
// Test single quote handling...
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL("", wxTranslateFromUnicodeFormat("'"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("%H", wxTranslateFromUnicodeFormat("H'"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("H", wxTranslateFromUnicodeFormat("'H"));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL("'", wxTranslateFromUnicodeFormat("''"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("%H'", wxTranslateFromUnicodeFormat("H''"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("H", wxTranslateFromUnicodeFormat("'H'"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("'%H", wxTranslateFromUnicodeFormat("''H"));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL("'", wxTranslateFromUnicodeFormat("'''"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("%H'", wxTranslateFromUnicodeFormat("H'''"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("H'", wxTranslateFromUnicodeFormat("'H''"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("'%H", wxTranslateFromUnicodeFormat("''H'"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("'H", wxTranslateFromUnicodeFormat("'''H"));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL("''", wxTranslateFromUnicodeFormat("''''"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("%H''", wxTranslateFromUnicodeFormat("H''''"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("H'", wxTranslateFromUnicodeFormat("'H'''"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("'%H'", wxTranslateFromUnicodeFormat("''H''"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("'H", wxTranslateFromUnicodeFormat("'''H'"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL("''%H", wxTranslateFromUnicodeFormat("''''H"));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL("'%H o'clock: It's about time'",
|
||||||
|
wxTranslateFromUnicodeFormat("''H 'o''clock: It''s about time'''"));
|
||||||
|
}
|
||||||
|
|
||||||
#endif // wxUSE_DATETIME
|
#endif // wxUSE_DATETIME
|
||||||
|
Reference in New Issue
Block a user