Index: source/i18n/reldtfmt.cpp |
diff --git a/source/i18n/reldtfmt.cpp b/source/i18n/reldtfmt.cpp |
index 723b0c9a0e888dd9ead084667921f26f7944d306..81fb77749a594745c48d5daa863e6bad5705f899 100644 |
--- a/source/i18n/reldtfmt.cpp |
+++ b/source/i18n/reldtfmt.cpp |
@@ -1,6 +1,6 @@ |
/* |
******************************************************************************* |
-* Copyright (C) 2007-2013, International Business Machines Corporation and |
+* Copyright (C) 2007-2014, International Business Machines Corporation and |
* others. All Rights Reserved. |
******************************************************************************* |
*/ |
@@ -15,6 +15,9 @@ |
#include "unicode/datefmt.h" |
#include "unicode/smpdtfmt.h" |
#include "unicode/msgfmt.h" |
+#include "unicode/udisplaycontext.h" |
+#include "unicode/uchar.h" |
+#include "unicode/brkiter.h" |
#include "gregoimp.h" // for CalendarData |
#include "cmemory.h" |
@@ -42,7 +45,12 @@ RelativeDateFormat::RelativeDateFormat(const RelativeDateFormat& other) : |
fTimePattern(other.fTimePattern), fCombinedFormat(NULL), |
fDateStyle(other.fDateStyle), fLocale(other.fLocale), |
fDayMin(other.fDayMin), fDayMax(other.fDayMax), |
- fDatesLen(other.fDatesLen), fDates(NULL) |
+ fDatesLen(other.fDatesLen), fDates(NULL), |
+ fCombinedHasDateAtStart(other.fCombinedHasDateAtStart), |
+ fCapitalizationInfoSet(other.fCapitalizationInfoSet), |
+ fCapitalizationOfRelativeUnitsForUIListMenu(other.fCapitalizationOfRelativeUnitsForUIListMenu), |
+ fCapitalizationOfRelativeUnitsForStandAlone(other.fCapitalizationOfRelativeUnitsForStandAlone), |
+ fCapitalizationBrkIter(NULL) |
{ |
if(other.fDateTimeFormatter != NULL) { |
fDateTimeFormatter = (SimpleDateFormat*)other.fDateTimeFormatter->clone(); |
@@ -54,12 +62,20 @@ RelativeDateFormat::RelativeDateFormat(const RelativeDateFormat& other) : |
fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen); |
uprv_memcpy(fDates, other.fDates, sizeof(fDates[0])*fDatesLen); |
} |
+#if !UCONFIG_NO_BREAK_ITERATION |
+ if (other.fCapitalizationBrkIter != NULL) { |
+ fCapitalizationBrkIter = (other.fCapitalizationBrkIter)->clone(); |
+ } |
+#endif |
} |
RelativeDateFormat::RelativeDateFormat( UDateFormatStyle timeStyle, UDateFormatStyle dateStyle, |
const Locale& locale, UErrorCode& status) : |
DateFormat(), fDateTimeFormatter(NULL), fDatePattern(), fTimePattern(), fCombinedFormat(NULL), |
- fDateStyle(dateStyle), fLocale(locale), fDatesLen(0), fDates(NULL) |
+ fDateStyle(dateStyle), fLocale(locale), fDayMin(0), fDayMax(0), fDatesLen(0), fDates(NULL), |
+ fCombinedHasDateAtStart(FALSE), fCapitalizationInfoSet(FALSE), |
+ fCapitalizationOfRelativeUnitsForUIListMenu(FALSE), fCapitalizationOfRelativeUnitsForStandAlone(FALSE), |
+ fCapitalizationBrkIter(NULL) |
{ |
if(U_FAILURE(status) ) { |
return; |
@@ -110,6 +126,9 @@ RelativeDateFormat::~RelativeDateFormat() { |
delete fDateTimeFormatter; |
delete fCombinedFormat; |
uprv_free(fDates); |
+#if !UCONFIG_NO_BREAK_ITERATION |
+ delete fCapitalizationBrkIter; |
+#endif |
} |
@@ -119,12 +138,14 @@ Format* RelativeDateFormat::clone(void) const { |
UBool RelativeDateFormat::operator==(const Format& other) const { |
if(DateFormat::operator==(other)) { |
+ // The DateFormat::operator== check for fCapitalizationContext equality above |
+ // is sufficient to check equality of all derived context-related data. |
// DateFormat::operator== guarantees following cast is safe |
RelativeDateFormat* that = (RelativeDateFormat*)&other; |
return (fDateStyle==that->fDateStyle && |
fDatePattern==that->fDatePattern && |
fTimePattern==that->fTimePattern && |
- fLocale==that->fLocale); |
+ fLocale==that->fLocale ); |
} |
return FALSE; |
} |
@@ -137,6 +158,7 @@ UnicodeString& RelativeDateFormat::format( Calendar& cal, |
UErrorCode status = U_ZERO_ERROR; |
UnicodeString relativeDayString; |
+ UDisplayContext capitalizationContext = getContext(UDISPCTX_TYPE_CAPITALIZATION, status); |
// calculate the difference, in days, between 'cal' and now. |
int dayDiff = dayDifference(cal, status); |
@@ -148,7 +170,25 @@ UnicodeString& RelativeDateFormat::format( Calendar& cal, |
// found a relative string |
relativeDayString.setTo(theString, len); |
} |
- |
+ |
+ if ( relativeDayString.length() > 0 && !fDatePattern.isEmpty() && |
+ (fTimePattern.isEmpty() || fCombinedFormat == NULL || fCombinedHasDateAtStart)) { |
+#if !UCONFIG_NO_BREAK_ITERATION |
+ // capitalize relativeDayString according to context for relative, set formatter no context |
+ if ( u_islower(relativeDayString.char32At(0)) && fCapitalizationBrkIter!= NULL && |
+ ( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || |
+ (capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && fCapitalizationOfRelativeUnitsForUIListMenu) || |
+ (capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && fCapitalizationOfRelativeUnitsForStandAlone) ) ) { |
+ // titlecase first word of relativeDayString |
+ relativeDayString.toTitle(fCapitalizationBrkIter, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); |
+ } |
+#endif |
+ fDateTimeFormatter->setContext(UDISPCTX_CAPITALIZATION_NONE, status); |
+ } else { |
+ // set our context for the formatter |
+ fDateTimeFormatter->setContext(capitalizationContext, status); |
+ } |
+ |
if (fDatePattern.isEmpty()) { |
fDateTimeFormatter->applyPattern(fTimePattern); |
fDateTimeFormatter->format(cal,appendTo,pos); |
@@ -384,6 +424,57 @@ RelativeDateFormat::getDateFormatSymbols() const |
return fDateTimeFormatter->getDateFormatSymbols(); |
} |
+// override the DateFormat implementation in order to |
+// lazily initialize relevant items |
+void |
+RelativeDateFormat::setContext(UDisplayContext value, UErrorCode& status) |
+{ |
+ DateFormat::setContext(value, status); |
+ if (U_SUCCESS(status)) { |
+ if (!fCapitalizationInfoSet && |
+ (value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU || value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE)) { |
+ initCapitalizationContextInfo(fLocale); |
+ fCapitalizationInfoSet = TRUE; |
+ } |
+#if !UCONFIG_NO_BREAK_ITERATION |
+ if ( fCapitalizationBrkIter == NULL && (value==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || |
+ (value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && fCapitalizationOfRelativeUnitsForUIListMenu) || |
+ (value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && fCapitalizationOfRelativeUnitsForStandAlone)) ) { |
+ UErrorCode status = U_ZERO_ERROR; |
+ fCapitalizationBrkIter = BreakIterator::createSentenceInstance(fLocale, status); |
+ if (U_FAILURE(status)) { |
+ delete fCapitalizationBrkIter; |
+ fCapitalizationBrkIter = NULL; |
+ } |
+ } |
+#endif |
+ } |
+} |
+ |
+void |
+RelativeDateFormat::initCapitalizationContextInfo(const Locale& thelocale) |
+{ |
+#if !UCONFIG_NO_BREAK_ITERATION |
+ const char * localeID = (thelocale != NULL)? thelocale.getBaseName(): NULL; |
+ UErrorCode status = U_ZERO_ERROR; |
+ UResourceBundle *rb = ures_open(NULL, localeID, &status); |
+ rb = ures_getByKeyWithFallback(rb, "contextTransforms", rb, &status); |
+ rb = ures_getByKeyWithFallback(rb, "relative", rb, &status); |
+ if (U_SUCCESS(status) && rb != NULL) { |
+ int32_t len = 0; |
+ const int32_t * intVector = ures_getIntVector(rb, &len, &status); |
+ if (U_SUCCESS(status) && intVector != NULL && len >= 2) { |
+ fCapitalizationOfRelativeUnitsForUIListMenu = intVector[0]; |
+ fCapitalizationOfRelativeUnitsForStandAlone = intVector[1]; |
+ } |
+ } |
+ ures_close(rb); |
+#endif |
+} |
+ |
+static const UChar patItem1[] = {0x7B,0x31,0x7D}; // "{1}" |
+static const int32_t patItem1Len = 3; |
+ |
void RelativeDateFormat::loadDates(UErrorCode &status) { |
CalendarData calData(fLocale, "gregorian", status); |
@@ -420,26 +511,28 @@ void RelativeDateFormat::loadDates(UErrorCode &status) { |
} |
const UChar *resStr = ures_getStringByIndex(dateTimePatterns, glueIndex, &resStrLen, &tempStatus); |
+ if (U_SUCCESS(tempStatus) && resStrLen >= patItem1Len && u_strncmp(resStr,patItem1,patItem1Len)==0) { |
+ fCombinedHasDateAtStart = TRUE; |
+ } |
fCombinedFormat = new MessageFormat(UnicodeString(TRUE, resStr, resStrLen), fLocale, tempStatus); |
} |
} |
UResourceBundle *rb = ures_open(NULL, fLocale.getBaseName(), &status); |
- UResourceBundle *sb = ures_getByKeyWithFallback(rb, "fields", NULL, &status); |
- rb = ures_getByKeyWithFallback(sb, "day", rb, &status); |
- sb = ures_getByKeyWithFallback(rb, "relative", sb, &status); |
- ures_close(rb); |
+ rb = ures_getByKeyWithFallback(rb, "fields", rb, &status); |
+ rb = ures_getByKeyWithFallback(rb, "day", rb, &status); |
+ rb = ures_getByKeyWithFallback(rb, "relative", rb, &status); |
// set up min/max |
fDayMin=-1; |
fDayMax=1; |
if(U_FAILURE(status)) { |
fDatesLen=0; |
- ures_close(sb); |
+ ures_close(rb); |
return; |
} |
- fDatesLen = ures_getSize(sb); |
+ fDatesLen = ures_getSize(rb); |
fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen); |
// Load in each item into the array... |
@@ -447,8 +540,8 @@ void RelativeDateFormat::loadDates(UErrorCode &status) { |
UResourceBundle *subString = NULL; |
- while(ures_hasNext(sb) && U_SUCCESS(status)) { // iterate over items |
- subString = ures_getNextResource(sb, subString, &status); |
+ while(ures_hasNext(rb) && U_SUCCESS(status)) { // iterate over items |
+ subString = ures_getNextResource(rb, subString, &status); |
if(U_FAILURE(status) || (subString==NULL)) break; |
@@ -480,11 +573,12 @@ void RelativeDateFormat::loadDates(UErrorCode &status) { |
n++; |
} |
ures_close(subString); |
- ures_close(sb); |
+ ures_close(rb); |
// the fDates[] array could be sorted here, for direct access. |
} |
+//---------------------------------------------------------------------- |
// this should to be in DateFormat, instead it was copied from SimpleDateFormat. |