#include "unicode/locdspnm.h"
#include "unicode/msgfmt.h"
#include "unicode/ures.h"
+#include "unicode/udisplaycontext.h"
#include "unicode/brkiter.h"
#include "cmemory.h"
MessageFormat *format;
MessageFormat *keyTypeFormat;
UDisplayContext capitalizationContext;
+ BreakIterator* capitalizationBrkIter;
UnicodeString formatOpenParen;
UnicodeString formatReplaceOpenParen;
UnicodeString formatCloseParen;
kCapContextUsageKeyValue,
kCapContextUsageCount
};
- // Capitalization transforms. For each usage type, the first array element indicates
- // whether to titlecase for uiListOrMenu context, the second indicates whether to
- // titlecase for stand-alone context.
- UBool fCapitalization[kCapContextUsageCount][2];
+ // Capitalization transforms. For each usage type, indicates whether to titlecase for
+ // the context specified in capitalizationContext (which we know at construction time)
+ UBool fCapitalization[kCapContextUsageCount];
public:
// constructor
, format(NULL)
, keyTypeFormat(NULL)
, capitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
+ , capitalizationBrkIter(NULL)
{
initialize();
}
, format(NULL)
, keyTypeFormat(NULL)
, capitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
+ , capitalizationBrkIter(NULL)
{
while (length-- > 0) {
UDisplayContext value = *contexts++;
{ "variant", kCapContextUsageVariant },
{ NULL, (CapContextUsage)0 },
};
- int32_t len = 0;
- UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &status);
- if (U_SUCCESS(status)) {
- UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, "contextTransforms", NULL, &status);
+ // Only get the context data if we need it! This is a const object so we know now...
+ // Also check whether we will need a break iterator (depends on the data)
+ UBool needBrkIter = FALSE;
+ if (capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU || capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_STANDALONE) {
+ int32_t len = 0;
+ UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &status);
if (U_SUCCESS(status)) {
- UResourceBundle *contextTransformUsage;
- while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &status)) != NULL ) {
- const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
- if (U_SUCCESS(status) && intVector != NULL && len >= 2) {
- const char* usageKey = ures_getKey(contextTransformUsage);
- if (usageKey != NULL) {
- const ContextUsageNameToEnum * typeMapPtr = contextUsageTypeMap;
- int32_t compResult = 0;
- // linear search; list is short and we cannot be sure that bsearch is available
- while ( typeMapPtr->usageName != NULL && (compResult = uprv_strcmp(usageKey, typeMapPtr->usageName)) > 0 ) {
- ++typeMapPtr;
- }
- if (typeMapPtr->usageName != NULL && compResult == 0) {
- fCapitalization[typeMapPtr->usageEnum][0] = intVector[0];
- fCapitalization[typeMapPtr->usageEnum][1] = intVector[1];
+ UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, "contextTransforms", NULL, &status);
+ if (U_SUCCESS(status)) {
+ UResourceBundle *contextTransformUsage;
+ while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &status)) != NULL ) {
+ const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
+ if (U_SUCCESS(status) && intVector != NULL && len >= 2) {
+ const char* usageKey = ures_getKey(contextTransformUsage);
+ if (usageKey != NULL) {
+ const ContextUsageNameToEnum * typeMapPtr = contextUsageTypeMap;
+ int32_t compResult = 0;
+ // linear search; list is short and we cannot be sure that bsearch is available
+ while ( typeMapPtr->usageName != NULL && (compResult = uprv_strcmp(usageKey, typeMapPtr->usageName)) > 0 ) {
+ ++typeMapPtr;
+ }
+ if (typeMapPtr->usageName != NULL && compResult == 0) {
+ int32_t titlecaseInt = (capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU)? intVector[0]: intVector[1];
+ if (titlecaseInt != 0) {
+ fCapitalization[typeMapPtr->usageEnum] = TRUE;;
+ needBrkIter = TRUE;
+ }
+ }
}
}
+ status = U_ZERO_ERROR;
+ ures_close(contextTransformUsage);
}
- status = U_ZERO_ERROR;
- ures_close(contextTransformUsage);
+ ures_close(contextTransforms);
}
- ures_close(contextTransforms);
+ ures_close(localeBundle);
+ }
+ }
+ // Get a sentence break iterator if we will need it
+ if (needBrkIter || capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE) {
+ status = U_ZERO_ERROR;
+ capitalizationBrkIter = BreakIterator::createSentenceInstance(locale, status);
+ if (U_FAILURE(status)) {
+ delete capitalizationBrkIter;
+ capitalizationBrkIter = NULL;
}
- ures_close(localeBundle);
}
#endif
}
delete separatorFormat;
delete format;
delete keyTypeFormat;
+ delete capitalizationBrkIter;
}
const Locale&
UnicodeString& result) const {
#if !UCONFIG_NO_BREAK_ITERATION
// check to see whether we need to titlecase result
- UBool titlecase = FALSE;
- switch (capitalizationContext) {
- case UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE:
- titlecase = TRUE;
- break;
- case UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU:
- titlecase = fCapitalization[usage][0];
- break;
- case UDISPCTX_CAPITALIZATION_FOR_STANDALONE:
- titlecase = fCapitalization[usage][1];
- break;
- default:
- // titlecase = FALSE;
- break;
- }
- if (titlecase) {
- // TODO: Fix this titlecase hack when we figure out something better to do.
- // We don't want to titlecase the whole text, only something like the first word,
- // of the first segment long enough to have a complete cluster, whichever is
- // shorter. We could have keep a word break iterator around, but I am not sure
- // that will do the ight thing for the purposes here. For now we assume that in
- // languages for which titlecasing makes a difference, we can stop at non-letter
- // characters in 0x0000-0x00FF and only titlecase up to the first occurrence of
- // any of those, or to a small number of chars, whichever comes first.
- int32_t stopPos, stopPosLimit = 8, len = result.length();
- if ( stopPosLimit > len ) {
- stopPosLimit = len;
- }
- for ( stopPos = 0; stopPos < stopPosLimit; stopPos++ ) {
- UChar32 ch = result.char32At(stopPos);
- if ( (ch < 0x41) || (ch > 0x5A && ch < 0x61) || (ch > 0x7A && ch < 0xC0) ) {
- break;
- }
- if (ch >= 0x10000) {
- stopPos++;
- }
- }
- if ( stopPos > 0 && stopPos < len ) {
- UnicodeString firstWord(result, 0, stopPos);
- firstWord.toTitle(NULL, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
- result.replaceBetween(0, stopPos, firstWord);
- } else {
- // no stopPos, titlecase the whole text
- result.toTitle(NULL, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
- }
+ if ( result.length() > 0 && u_islower(result.char32At(0)) && capitalizationBrkIter!= NULL &&
+ ( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || fCapitalization[usage] ) ) {
+ // note fCapitalization[usage] won't be set unless capitalizationContext is UI_LIST_OR_MENU or STANDALONE
+ result.toTitle(capitalizationBrkIter, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
}
#endif
return result;
(value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && capitalizationForStandAlone)) ) {
UErrorCode status = U_ZERO_ERROR;
capitalizationBrkIter = BreakIterator::createSentenceInstance(locale, status);
+ if (U_FAILURE(status)) {
+ delete capitalizationBrkIter;
+ capitalizationBrkIter = NULL;
+ }
}
#endif
}
#include "unicode/msgfmt.h"
#include "unicode/udisplaycontext.h"
#include "unicode/uchar.h"
+#include "unicode/brkiter.h"
#include "gregoimp.h" // for CalendarData
#include "cmemory.h"
fDateStyle(other.fDateStyle), fLocale(other.fLocale),
fDayMin(other.fDayMin), fDayMax(other.fDayMax),
fDatesLen(other.fDatesLen), fDates(NULL),
- fCombinedHasDateAtStart(other.fCombinedHasDateAtStart)
+ fCombinedHasDateAtStart(other.fCombinedHasDateAtStart),
+ fCapitalizationInfoSet(other.fCapitalizationInfoSet),
+ fCapitalizationOfRelativeUnitsForUIListMenu(other.fCapitalizationOfRelativeUnitsForUIListMenu),
+ fCapitalizationOfRelativeUnitsForStandAlone(other.fCapitalizationOfRelativeUnitsForStandAlone),
+ fCapitalizationBrkIter(NULL)
{
if(other.fDateTimeFormatter != NULL) {
fDateTimeFormatter = (SimpleDateFormat*)other.fDateTimeFormatter->clone();
fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen);
uprv_memcpy(fDates, other.fDates, sizeof(fDates[0])*fDatesLen);
}
- fCapitalizationForRelativeUnits[0] = other.fCapitalizationForRelativeUnits[0];
- fCapitalizationForRelativeUnits[1] = other.fCapitalizationForRelativeUnits[1];
+ if (other.fCapitalizationBrkIter != NULL) {
+ fCapitalizationBrkIter = (other.fCapitalizationBrkIter)->clone();
+ }
}
RelativeDateFormat::RelativeDateFormat( UDateFormatStyle timeStyle, UDateFormatStyle dateStyle,
const Locale& locale, UErrorCode& status) :
DateFormat(), fDateTimeFormatter(NULL), fDatePattern(), fTimePattern(), fCombinedFormat(NULL),
fDateStyle(dateStyle), fLocale(locale), fDayMin(0), fDayMax(0), fDatesLen(0), fDates(NULL),
- fCombinedHasDateAtStart(FALSE)
+ fCombinedHasDateAtStart(FALSE), fCapitalizationInfoSet(FALSE),
+ fCapitalizationOfRelativeUnitsForUIListMenu(FALSE), fCapitalizationOfRelativeUnitsForStandAlone(FALSE),
+ fCapitalizationBrkIter(NULL)
{
if(U_FAILURE(status) ) {
return;
delete fDateTimeFormatter;
delete fCombinedFormat;
uprv_free(fDates);
+ delete fCapitalizationBrkIter;
}
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 &&
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 ( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
- (capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && fCapitalizationForRelativeUnits[0]) ||
- (capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && fCapitalizationForRelativeUnits[1]) ) {
- // titlecase first word of relativeDayString, do like LocaleDisplayNamesImpl::adjustForUsageAndContext
- int32_t stopPos, stopPosLimit = 8;
- if ( stopPosLimit > len ) {
- stopPosLimit = len;
- }
- for ( stopPos = 0; stopPos < stopPosLimit; stopPos++ ) {
- UChar32 ch = relativeDayString.char32At(stopPos);
- int32_t wb = u_getIntPropertyValue(ch, UCHAR_WORD_BREAK);
- if (!(u_islower(ch) || wb==U_WB_EXTEND || wb==U_WB_SINGLE_QUOTE || wb==U_WB_MIDNUMLET || wb==U_WB_MIDLETTER)) {
- break;
- }
- if (ch >= 0x10000) {
- stopPos++;
- }
- }
- if ( stopPos > 0 && stopPos < len ) {
- UnicodeString firstWord(relativeDayString, 0, stopPos);
- firstWord.toTitle(NULL, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
- relativeDayString.replaceBetween(0, stopPos, firstWord);
- } else {
- // no stopPos, titlecase the whole text
- relativeDayString.toTitle(NULL, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
- }
+ 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
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;
}
}
- fCapitalizationForRelativeUnits[0] = fCapitalizationForRelativeUnits[1] = FALSE;
- UResourceBundle *lb = ures_open(NULL, fLocale.getBaseName(), &status);
- tempStatus = status;
- UResourceBundle *rb = ures_getByKeyWithFallback(lb, "contextTransforms", NULL, &tempStatus);
- UResourceBundle *sb = ures_getByKeyWithFallback(rb, "relative", NULL, &tempStatus);
- if (U_SUCCESS(tempStatus) && sb != NULL) {
- int32_t len = 0;
- const int32_t * intVector = ures_getIntVector(sb, &len, &tempStatus);
- if (U_SUCCESS(tempStatus) && intVector != NULL && len >= 2) {
- fCapitalizationForRelativeUnits[0] = intVector[0];
- fCapitalizationForRelativeUnits[1] = intVector[1];
- }
- }
- sb = ures_getByKeyWithFallback(lb, "fields", sb, &status);
- rb = ures_getByKeyWithFallback(sb, "day", rb, &status);
- sb = ures_getByKeyWithFallback(rb, "relative", sb, &status);
- ures_close(rb);
- ures_close(lb);
+ UResourceBundle *rb = ures_open(NULL, fLocale.getBaseName(), &status);
+ 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...
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;
n++;
}
ures_close(subString);
- ures_close(sb);
+ ures_close(rb);
// the fDates[] array could be sorted here, for direct access.
}
#include "unicode/datefmt.h"
#include "unicode/smpdtfmt.h"
+#include "unicode/brkiter.h"
U_NAMESPACE_BEGIN
*/
virtual const DateFormatSymbols* getDateFormatSymbols(void) const;
+ /* Cannot use #ifndef U_HIDE_DRAFT_API for the following draft method since it is virtual */
+ /**
+ * Set a particular UDisplayContext value in the formatter, such as
+ * UDISPCTX_CAPITALIZATION_FOR_STANDALONE. Note: For getContext, see
+ * DateFormat.
+ * @param value The UDisplayContext value to set.
+ * @param status Input/output status. If at entry this indicates a failure
+ * status, the function will do nothing; otherwise this will be
+ * updated with any new status from the function.
+ * @internal ICU 53
+ */
+ virtual void setContext(UDisplayContext value, UErrorCode& status);
+
private:
SimpleDateFormat *fDateTimeFormatter;
UnicodeString fDatePattern;
int32_t fDatesLen; // Length of array
URelativeString *fDates; // array of strings
- UBool fCapitalizationForRelativeUnits[2];
UBool fCombinedHasDateAtStart;
+ UBool fCapitalizationInfoSet;
+ UBool fCapitalizationOfRelativeUnitsForUIListMenu;
+ UBool fCapitalizationOfRelativeUnitsForStandAlone;
+ BreakIterator* fCapitalizationBrkIter;
/**
* Get the string at a specific offset.
*/
void loadDates(UErrorCode &status);
+ /**
+ * Set fCapitalizationOfRelativeUnitsForUIListMenu, fCapitalizationOfRelativeUnitsForStandAlone
+ */
+ void initCapitalizationContextInfo(const Locale& thelocale);
+
/**
* @return the number of days in "until-now"
*/
#include "unicode/utf16.h"
#include "unicode/vtzone.h"
#include "unicode/udisplaycontext.h"
+#include "unicode/brkiter.h"
#include "olsontz.h"
#include "patternprops.h"
#include "fphdlimp.h"
delete cur->nf;
uprv_free(cur);
}
+
+ delete fCapitalizationBrkIter;
}
//----------------------------------------------------------------------
fSymbols(NULL),
fTimeZoneFormat(NULL),
fNumberFormatters(NULL),
- fOverrideList(NULL)
+ fOverrideList(NULL),
+ fCapitalizationBrkIter(NULL)
{
initializeBooleanAttributes();
construct(kShort, (EStyle) (kShort + kDateOffset), fLocale, status);
fSymbols(NULL),
fTimeZoneFormat(NULL),
fNumberFormatters(NULL),
- fOverrideList(NULL)
+ fOverrideList(NULL),
+ fCapitalizationBrkIter(NULL)
{
fDateOverride.setToBogus();
fTimeOverride.setToBogus();
fSymbols(NULL),
fTimeZoneFormat(NULL),
fNumberFormatters(NULL),
- fOverrideList(NULL)
+ fOverrideList(NULL),
+ fCapitalizationBrkIter(NULL)
{
fDateOverride.setTo(override);
fTimeOverride.setToBogus();
fLocale(locale),
fTimeZoneFormat(NULL),
fNumberFormatters(NULL),
- fOverrideList(NULL)
+ fOverrideList(NULL),
+ fCapitalizationBrkIter(NULL)
{
fDateOverride.setToBogus();
fLocale(locale),
fTimeZoneFormat(NULL),
fNumberFormatters(NULL),
- fOverrideList(NULL)
+ fOverrideList(NULL),
+ fCapitalizationBrkIter(NULL)
{
fDateOverride.setTo(override);
fSymbols(symbolsToAdopt),
fTimeZoneFormat(NULL),
fNumberFormatters(NULL),
- fOverrideList(NULL)
+ fOverrideList(NULL),
+ fCapitalizationBrkIter(NULL)
{
fDateOverride.setToBogus();
fSymbols(new DateFormatSymbols(symbols)),
fTimeZoneFormat(NULL),
fNumberFormatters(NULL),
- fOverrideList(NULL)
+ fOverrideList(NULL),
+ fCapitalizationBrkIter(NULL)
{
fDateOverride.setToBogus();
fSymbols(NULL),
fTimeZoneFormat(NULL),
fNumberFormatters(NULL),
- fOverrideList(NULL)
+ fOverrideList(NULL),
+ fCapitalizationBrkIter(NULL)
{
initializeBooleanAttributes();
construct(timeStyle, dateStyle, fLocale, status);
fSymbols(NULL),
fTimeZoneFormat(NULL),
fNumberFormatters(NULL),
- fOverrideList(NULL)
+ fOverrideList(NULL),
+ fCapitalizationBrkIter(NULL)
{
if (U_FAILURE(status)) return;
initializeBooleanAttributes();
fSymbols(NULL),
fTimeZoneFormat(NULL),
fNumberFormatters(NULL),
- fOverrideList(NULL)
+ fOverrideList(NULL),
+ fCapitalizationBrkIter(NULL)
{
initializeBooleanAttributes();
*this = other;
fTimeZoneFormat = NULL; // forces lazy instantiation with the other locale
fLocale = other.fLocale;
}
+
+ if (other.fCapitalizationBrkIter != NULL) {
+ fCapitalizationBrkIter = (other.fCapitalizationBrkIter)->clone();
+ }
return *this;
}
SimpleDateFormat::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
SimpleDateFormat* that = (SimpleDateFormat*)&other;
return (fPattern == that->fPattern &&
break;
}
#if !UCONFIG_NO_BREAK_ITERATION
- if (fieldNum == 0) {
- // first field, check to see whether we need to titlecase it
+ // if first field, check to see whether we need to and are able to titlecase it
+ if (fieldNum == 0 && u_islower(appendTo.char32At(beginOffset)) && fCapitalizationBrkIter != NULL) {
UBool titlecase = FALSE;
switch (capitalizationContext) {
case UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE:
}
if (titlecase) {
UnicodeString firstField(appendTo, beginOffset);
- firstField.toTitle(NULL, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
+ firstField.toTitle(fCapitalizationBrkIter, fLocale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
appendTo.replaceBetween(beginOffset, appendTo.length(), firstField);
}
}
//----------------------------------------------------------------------
+// override the DateFormat implementation in order to
+// lazily initialize fCapitalizationBrkIter
+void
+SimpleDateFormat::setContext(UDisplayContext value, UErrorCode& status)
+{
+ DateFormat::setContext(value, status);
+#if !UCONFIG_NO_BREAK_ITERATION
+ if (U_SUCCESS(status)) {
+ if ( fCapitalizationBrkIter == NULL && (value==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
+ value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU || value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE) ) {
+ UErrorCode status = U_ZERO_ERROR;
+ fCapitalizationBrkIter = BreakIterator::createSentenceInstance(fLocale, status);
+ if (U_FAILURE(status)) {
+ delete fCapitalizationBrkIter;
+ fCapitalizationBrkIter = NULL;
+ }
+ }
+ }
+#endif
+}
+
+
+//----------------------------------------------------------------------
+
+
UBool
SimpleDateFormat::isFieldUnitIgnored(UCalendarDateFields field) const {
return isFieldUnitIgnored(fPattern, field);
UBool capitalizationInfoSet;
UBool capitalizationForUIListMenu;
UBool capitalizationForStandAlone;
-#if !UCONFIG_NO_BREAK_ITERATION
BreakIterator* capitalizationBrkIter;
-#else
- void* capitalizationBrkIter;
-#endif
};
// ---------------
#include "unicode/datefmt.h"
#include "unicode/udisplaycontext.h"
#include "unicode/tzfmt.h" /* for UTimeZoneFormatTimeType */
+#include "unicode/brkiter.h"
U_NAMESPACE_BEGIN
*/
virtual const TimeZoneFormat* getTimeZoneFormat(void) const;
+ /* Cannot use #ifndef U_HIDE_DRAFT_API for the following draft method since it is virtual */
+ /**
+ * Set a particular UDisplayContext value in the formatter, such as
+ * UDISPCTX_CAPITALIZATION_FOR_STANDALONE. Note: For getContext, see
+ * DateFormat.
+ * @param value The UDisplayContext value to set.
+ * @param status Input/output status. If at entry this indicates a failure
+ * status, the function will do nothing; otherwise this will be
+ * updated with any new status from the function.
+ * @draft ICU 53
+ */
+ virtual void setContext(UDisplayContext value, UErrorCode& status);
+
#ifndef U_HIDE_INTERNAL_API
/**
* This is for ICU internal use only. Please do not use.
NSOverride *fOverrideList;
UBool fHaveDefaultCentury;
+
+ BreakIterator* fCapitalizationBrkIter;
};
inline UDate
/*********************************************************************
* COPYRIGHT:
- * Copyright (c) 2010-2013, International Business Machines Corporation and
+ * Copyright (c) 2010-2014, International Business Machines Corporation and
* others. All Rights Reserved.
*********************************************************************/
{ "da", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, en_US, daFor_en_US_DT },
{ "es", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, en, esFor_en_T },
{ "es", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, en_US, esFor_en_US_T },
- { "es", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, en_US, esFor_en_US_DT },
+ { "es", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, en_US, esFor_en_US_DT },
{ "da", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, en, daFor_en_T },
{ "da", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, en_US, daFor_en_US_T },
{ "da", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, en_US, daFor_en_US_DT },
{ "es", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, en, esFor_en_T },
{ "es", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, en_US, esFor_en_US_T },
- { "es", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, en_US, esFor_en_US_DT },
+ { "es", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, en_US, esFor_en_US_DT },
+
+ { "da", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, en, daFor_en },
+ { "da", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, en_US, daFor_en_US },
+ { "da", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, en_US, daFor_en_US_D },
+ { "es", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, en, esFor_en_T },
+ { "es", UDISPCTX_STANDARD_NAMES, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, en_US, esFor_en_US_T },
+ { "es", UDISPCTX_DIALECT_NAMES, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, en_US, esFor_en_US_DT },
#endif /* #if !UCONFIG_NO_BREAK_ITERATION */
{ NULL, (UDisplayContext)0, (UDisplayContext)0, NULL, NULL }
};