status_t BTimeZone::SetTo(const char* zoneID, const BLanguage* language) { delete fICULocale; fICULocale = NULL; delete fICUTimeZone; fInitializedFields = 0; if (zoneID == NULL || zoneID[0] == '\0') fICUTimeZone = TimeZone::createDefault(); else fICUTimeZone = TimeZone::createTimeZone(zoneID); if (fICUTimeZone == NULL) { fInitStatus = B_NAME_NOT_FOUND; return fInitStatus; } if (language != NULL) { fICULocale = new Locale(language->Code()); if (fICULocale == NULL) { fInitStatus = B_NO_MEMORY; return fInitStatus; } } UnicodeString unicodeString; fICUTimeZone->getID(unicodeString); BStringByteSink sink(&fZoneID); unicodeString.toUTF8(sink); fInitStatus = B_OK; return fInitStatus; }
bool BCountry::MonGrouping(BString& grouping) const { UErrorCode err; NumberFormat* numberFormatter = NumberFormat::createCurrencyInstance(*fICULocale, err); assert(err == U_ZERO_ERROR); DecimalFormat* decimalFormatter = dynamic_cast<DecimalFormat*>(numberFormatter); assert(decimalFormatter != NULL); const DecimalFormatSymbols* syms = decimalFormatter->getDecimalFormatSymbols(); UnicodeString ICUString; ICUString = syms->getSymbol( DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol); BStringByteSink stringConverter(&grouping); ICUString.toUTF8(stringConverter); return true; }
status_t BLanguage::GetName(BString& name, const BLanguage* displayLanguage) const { status_t status = B_OK; BString appLanguage; if (displayLanguage == NULL) { BMessage preferredLanguage; status = BLocaleRoster::Default()->GetPreferredLanguages( &preferredLanguage); if (status == B_OK) status = preferredLanguage.FindString("language", 0, &appLanguage); } else { appLanguage = displayLanguage->Code(); } if (status == B_OK) { UnicodeString string; fICULocale->getDisplayName(Locale(appLanguage), string); name.Truncate(0); BStringByteSink converter(&name); string.toUTF8(converter); } return status; }
status_t BTimeUnitFormat::Format(BString& buffer, const int32 value, const time_unit_element unit) const { if (unit < 0 || unit > B_TIME_UNIT_LAST) return B_BAD_VALUE; if (fFormatter == NULL) return B_NO_INIT; UErrorCode icuStatus = U_ZERO_ERROR; TimeUnitAmount* timeUnitAmount = new TimeUnitAmount((double)value, skUnitMap[unit], icuStatus); if (timeUnitAmount == NULL) return B_NO_MEMORY; if (!U_SUCCESS(icuStatus)) return B_ERROR; Formattable formattable; formattable.adoptObject(timeUnitAmount); FieldPosition pos(FieldPosition::DONT_CARE); UnicodeString unicodeResult; fFormatter->format(formattable, unicodeResult, pos, icuStatus); if (!U_SUCCESS(icuStatus)) return B_ERROR; BStringByteSink byteSink(&buffer); unicodeResult.toUTF8(byteSink); return B_OK; }
status_t BLocale::FormatMonetary(BString* string, double value) const { if (string == NULL) return B_BAD_VALUE; BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; UErrorCode err = U_ZERO_ERROR; ObjectDeleter<NumberFormat> numberFormatter( NumberFormat::createCurrencyInstance( *BFormattingConventions::Private(&fConventions).ICULocale(), err)); if (numberFormatter.Get() == NULL) return B_NO_MEMORY; if (U_FAILURE(err)) return B_BAD_VALUE; UnicodeString icuString; numberFormatter->format(value, icuString); string->Truncate(0); BStringByteSink stringConverter(string); icuString.toUTF8(stringConverter); return B_OK; }
status_t BLocale::FormatTime(BString* string, time_t time, BString format, const BTimeZone* timeZone) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; if (format == NULL || format.CountChars() <= 0) return B_BAD_VALUE; ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(format)); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; if (timeZone != NULL) { ObjectDeleter<TimeZone> icuTimeZone( TimeZone::createTimeZone(timeZone->ID().String())); if (icuTimeZone.Get() == NULL) return B_NO_MEMORY; timeFormatter->setTimeZone(*icuTimeZone.Get()); } UnicodeString icuString; timeFormatter->format((UDate)time * 1000, icuString); string->Truncate(0); BStringByteSink stringConverter(string); icuString.toUTF8(stringConverter); return B_OK; }
ssize_t BLocale::FormatTime(char* string, size_t maxSize, time_t time, BString format) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; if (format == NULL || format.CountChars() <= 0) return B_BAD_VALUE; ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(format)); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; UnicodeString icuString; timeFormatter->format((UDate)time * 1000, icuString); CheckedArrayByteSink stringConverter(string, maxSize); icuString.toUTF8(stringConverter); if (stringConverter.Overflowed()) return B_BAD_VALUE; return stringConverter.NumberOfBytesWritten(); }
ssize_t BLocale::FormatDateTime(char* target, size_t maxSize, time_t time, BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; BString format; fConventions.GetDateFormat(dateStyle, format); ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format)); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; fConventions.GetTimeFormat(timeStyle, format); ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(format)); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; UnicodeString icuString; dateFormatter->format((UDate)time * 1000, icuString); icuString.append(UnicodeString::fromUTF8(", ")); timeFormatter->format((UDate)time * 1000, icuString); CheckedArrayByteSink stringConverter(target, maxSize); icuString.toUTF8(stringConverter); if (stringConverter.Overflowed()) return B_BAD_VALUE; return stringConverter.NumberOfBytesWritten(); }
status_t BFormattingConventions::GetDateFormat(BDateFormatStyle style, BString& outFormat) const { if (style < 0 || style >= B_DATE_FORMAT_STYLE_COUNT) return B_BAD_VALUE; outFormat = fExplicitDateFormats[style].Length() ? fExplicitDateFormats[style] : fCachedDateFormats[style]; if (outFormat.Length() > 0) return B_OK; ObjectDeleter<DateFormat> dateFormatter( DateFormat::createDateInstance((DateFormat::EStyle)style, *fICULocale)); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; SimpleDateFormat* dateFormatterImpl = static_cast<SimpleDateFormat*>(dateFormatter.Get()); UnicodeString icuString; dateFormatterImpl->toPattern(icuString); BStringByteSink stringConverter(&outFormat); icuString.toUTF8(stringConverter); fCachedDateFormats[style] = outFormat; return B_OK; }
status_t BLocale::FormatDate(BString *string, time_t time, BDateFormatStyle style, const BTimeZone* timeZone) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; BString format; fConventions.GetDateFormat(style, format); ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format)); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; if (timeZone != NULL) { ObjectDeleter<TimeZone> icuTimeZone( TimeZone::createTimeZone(timeZone->ID().String())); if (icuTimeZone.Get() == NULL) return B_NO_MEMORY; dateFormatter->setTimeZone(*icuTimeZone.Get()); } UnicodeString icuString; dateFormatter->format((UDate)time * 1000, icuString); string->Truncate(0); BStringByteSink stringConverter(string); icuString.toUTF8(stringConverter); return B_OK; }
bool BCountry::Name(BString& name) const { UnicodeString uString; fICULocale->getDisplayName(uString); BStringByteSink stringConverter(&name); uString.toUTF8(stringConverter); return true; }
status_t BLanguage::GetNativeName(BString& name) const { UnicodeString string; fICULocale->getDisplayName(*fICULocale, string); string.toTitle(NULL, *fICULocale); name.Truncate(0); BStringByteSink converter(&name); string.toUTF8(converter); return B_OK; }
void BCountry::FormatTime(BString* string, time_t time, bool longFormat) { // TODO: ICU allows for 4 different levels of expansion : // short, medium, long, and full. Our bool parameter is not enough... icu_4_2::DateFormat* timeFormatter; timeFormatter = longFormat ? fICULongTimeFormatter : fICUShortTimeFormatter; UnicodeString ICUString; ICUString = timeFormatter->format((UDate)time * 1000, ICUString); string->Truncate(0); BStringByteSink stringConverter(string); ICUString.toUTF8(stringConverter); }
status_t BFormattingConventions::GetTimeFormat(BTimeFormatStyle style, BString& outFormat) const { if (style < 0 || style >= B_TIME_FORMAT_STYLE_COUNT) return B_BAD_VALUE; outFormat = fExplicitTimeFormats[style].Length() ? fExplicitTimeFormats[style] : fCachedTimeFormats[style]; if (outFormat.Length() > 0) return B_OK; ObjectDeleter<DateFormat> timeFormatter( DateFormat::createTimeInstance((DateFormat::EStyle)style, *fICULocale)); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; SimpleDateFormat* timeFormatterImpl = static_cast<SimpleDateFormat*>(timeFormatter.Get()); UnicodeString icuString; timeFormatterImpl->toPattern(icuString); BStringByteSink stringConverter(&outFormat); icuString.toUTF8(stringConverter); int8 use24HourClock = fExplicitUse24HourClock != CLOCK_HOURS_UNSET ? fExplicitUse24HourClock : fCachedUse24HourClock; if (use24HourClock != CLOCK_HOURS_UNSET) { // adjust to 12/24-hour clock as requested bool localeUses24HourClock = !FormatUsesAmPm(outFormat); if (localeUses24HourClock) { if (use24HourClock == CLOCK_HOURS_12) CoerceFormatTo12HourClock(outFormat); } else { if (use24HourClock == CLOCK_HOURS_24) CoerceFormatTo24HourClock(outFormat); } } // use abbreviated timezone in short timezone format CoerceFormatToAbbreviatedTimezone(outFormat); fCachedTimeFormats[style] = outFormat; return B_OK; }
void BCountry::FormatNumber(BString* string, int32 value) { UErrorCode err; NumberFormat* numberFormatter = NumberFormat::createInstance(*fICULocale, err); assert(err == U_ZERO_ERROR); UnicodeString ICUString; ICUString = numberFormatter->format((int32_t)value, ICUString); string->Truncate(0); BStringByteSink stringConverter(string); ICUString.toUTF8(stringConverter); }
bool BCountry::TimeFormat(BString& format, bool longFormat) const { icu_4_2::DateFormat* dateFormatter; dateFormatter = longFormat ? fICULongTimeFormatter : fICUShortTimeFormatter; SimpleDateFormat* dateFormatterImpl = static_cast<SimpleDateFormat*>(dateFormatter); UnicodeString ICUString; ICUString = dateFormatterImpl->toPattern(ICUString); BStringByteSink stringConverter(&format); ICUString.toUTF8(stringConverter); return true; }
status_t BLocale::FormatDate(BString* string, int*& fieldPositions, int& fieldCount, time_t time, BDateFormatStyle style) const { BAutolock lock(fLock); if (!lock.IsLocked()) return B_ERROR; BString format; fConventions.GetDateFormat(style, format); ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format)); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; fieldPositions = NULL; UErrorCode error = U_ZERO_ERROR; icu::FieldPositionIterator positionIterator; UnicodeString icuString; dateFormatter->format((UDate)time * 1000, icuString, &positionIterator, error); if (error != U_ZERO_ERROR) return B_BAD_VALUE; icu::FieldPosition field; std::vector<int> fieldPosStorage; fieldCount = 0; while (positionIterator.next(field)) { fieldPosStorage.push_back(field.getBeginIndex()); fieldPosStorage.push_back(field.getEndIndex()); fieldCount += 2; } fieldPositions = (int*) malloc(fieldCount * sizeof(int)); for (int i = 0 ; i < fieldCount ; i++ ) fieldPositions[i] = fieldPosStorage[i]; string->Truncate(0); BStringByteSink stringConverter(string); icuString.toUTF8(stringConverter); return B_OK; }
const BString& BTimeZone::ShortDaylightSavingName() const { if ((fInitializedFields & skShortDaylightSavingNameField) == 0) { UnicodeString unicodeString; if (fICULocale != NULL) { fICUTimeZone->getDisplayName(true, TimeZone::SHORT, *fICULocale, unicodeString); } else { fICUTimeZone->getDisplayName(true, TimeZone::SHORT, unicodeString); } BStringByteSink sink(&fShortDaylightSavingName); unicodeString.toUTF8(sink); fInitializedFields |= skShortDaylightSavingNameField; } return fShortDaylightSavingName; }
const BString& BTimeZone::Name() const { if ((fInitializedFields & skNameField) == 0) { UnicodeString unicodeString; if (fICULocale != NULL) { fICUTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION, *fICULocale, unicodeString); } else { fICUTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION, unicodeString); } BStringByteSink sink(&fName); unicodeString.toUTF8(sink); fInitializedFields |= skNameField; } return fName; }
bool BCountry::TimeFormat(BString& format, bool longFormat) const { icu_4_2::DateFormat* dateFormatter; dateFormatter = DateFormat::createTimeInstance( longFormat ? DateFormat::FULL : DateFormat::SHORT, *fICULocale); SimpleDateFormat* dateFormatterImpl = static_cast<SimpleDateFormat*>(dateFormatter); UnicodeString ICUString; ICUString = dateFormatterImpl->toPattern(ICUString); BStringByteSink stringConverter(&format); ICUString.toUTF8(stringConverter); return true; }
status_t BFormattingConventions::GetDateTimeFormat(BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle, BString& outFormat) const { if (dateStyle < 0 || dateStyle >= B_DATE_FORMAT_STYLE_COUNT) return B_BAD_VALUE; if (timeStyle < 0 || timeStyle >= B_TIME_FORMAT_STYLE_COUNT) return B_BAD_VALUE; outFormat = fExplicitDateTimeFormats[dateStyle][timeStyle].Length() ? fExplicitDateTimeFormats[dateStyle][timeStyle] : fCachedDateTimeFormats[dateStyle][timeStyle]; if (outFormat.Length() > 0) return B_OK; ObjectDeleter<DateFormat> dateFormatter( DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle, (DateFormat::EStyle)timeStyle, *fICULocale)); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; SimpleDateFormat* dateFormatterImpl = static_cast<SimpleDateFormat*>(dateFormatter.Get()); UnicodeString icuString; dateFormatterImpl->toPattern(icuString); BStringByteSink stringConverter(&outFormat); icuString.toUTF8(stringConverter); CoerceFormatForClock(outFormat); if (dateStyle != B_FULL_DATE_FORMAT) { // use abbreviated timezone in short timezone format CoerceFormatToAbbreviatedTimezone(outFormat); } fCachedDateTimeFormats[dateStyle][timeStyle] = outFormat; return B_OK; }
status_t BCountry::FormatNumber(BString* string, double value) { UErrorCode err = U_ZERO_ERROR; NumberFormat* numberFormatter = NumberFormat::createInstance(*fICULocale, NumberFormat::kNumberStyle, err); // Warning: we're returning an ICU error here but the type is status_t. if (U_FAILURE(err)) return err; UnicodeString ICUString; ICUString = numberFormatter->format(value, ICUString); string->Truncate(0); BStringByteSink stringConverter(string); ICUString.toUTF8(stringConverter); return U_ZERO_ERROR; }
status_t BFormattingConventions::GetName(BString& name, const BLanguage* displayLanguage) const { BString displayLanguageID; if (displayLanguage == NULL) { BLanguage defaultLanguage; BLocale::Default()->GetLanguage(&defaultLanguage); displayLanguageID = defaultLanguage.Code(); } else { displayLanguageID = displayLanguage->Code(); } UnicodeString uString; fICULocale->getDisplayName(Locale(displayLanguageID.String()), uString); name.Truncate(0); BStringByteSink stringConverter(&name); uString.toUTF8(stringConverter); return B_OK; }
ssize_t BCountry::FormatMonetary(BString* string, double value) { if (string == NULL) return B_BAD_VALUE; UErrorCode err; NumberFormat* numberFormatter = NumberFormat::createCurrencyInstance(*fICULocale, err); assert(err == U_ZERO_ERROR); UnicodeString ICUString; ICUString = numberFormatter->format(value, ICUString); string->Truncate(0); BStringByteSink stringConverter(string); ICUString.toUTF8(stringConverter); return string->Length(); }
int compose(wchar_t* wcs, uint wcs_len, char* buf, uint buf_size) { // UCS4 to NFC auto str = UnicodeString::fromUTF32((UChar32*) wcs, wcs_len); auto status = U_ZERO_ERROR; UnicodeString result; Normalizer::normalize(str, UNORM_NFC, 0, result, status); if (U_FAILURE(status)) { cerr << "can't compose a UTF8 string, " << status << ": " << u_errorName(status) << endl; return -1; } string temp; StringByteSink<string> sink(&temp); result.toUTF8(sink); strcpy(buf, temp.c_str()); return 0; }
status_t BMessageFormat::Format(BString& output, const int32 arg) const { if (fInitStatus != B_OK) return fInitStatus; UnicodeString buffer; UErrorCode error = U_ZERO_ERROR; Formattable arguments[] = { (int32_t)arg }; FieldPosition pos; buffer = fFormatter->format(arguments, 1, buffer, pos, error); if (!U_SUCCESS(error)) return B_ERROR; BStringByteSink byteSink(&output); buffer.toUTF8(byteSink); return B_OK; }
bool BCountry::NegativeSign(BString& sign) const { UErrorCode err; NumberFormat* numberFormatter = NumberFormat::createInstance(*fICULocale, err); assert(err == U_ZERO_ERROR); DecimalFormat* decimalFormatter = dynamic_cast<DecimalFormat*>(numberFormatter); assert(decimalFormatter != NULL); const DecimalFormatSymbols* syms = decimalFormatter->getDecimalFormatSymbols(); UnicodeString ICUString; ICUString = syms->getSymbol(DecimalFormatSymbols::kMinusSignSymbol); BStringByteSink stringConverter(&sign); ICUString.toUTF8(stringConverter); return true; }
status_t ICUTimeConversion::TZSet(const char* timeZoneID, const char* tz) { bool offsetHasBeenSet = false; // The given TZ environment variable's content overrides the default // system timezone. if (tz != NULL) { // If the value given in the TZ env-var starts with a colon, that // value is implementation specific, we expect a full timezone ID. if (*tz == ':') { // nothing to do if the given name matches the current timezone if (strcasecmp(fTimeZoneID, tz + 1) == 0) return B_OK; strlcpy(fTimeZoneID, tz + 1, sizeof(fTimeZoneID)); } else { // note timezone name strlcpy(fTimeZoneID, tz, sizeof(fTimeZoneID)); // nothing to do if the given name matches the current timezone if (strcasecmp(fTimeZoneID, fDataBridge->addrOfTZName[0]) == 0) return B_OK; // parse TZ variable (only <std> and <offset> supported) const char* tzNameEnd = tz; while(isalpha(*tzNameEnd)) ++tzNameEnd; if (*tzNameEnd == '-' || *tzNameEnd == '+') { int hours = 0; int minutes = 0; int seconds = 0; sscanf(tzNameEnd + 1, "%2d:%2d:%2d", &hours, &minutes, &seconds); hours = min_c(24, max_c(0, hours)); minutes = min_c(59, max_c(0, minutes)); seconds = min_c(59, max_c(0, seconds)); *fDataBridge->addrOfTimezone = (*tzNameEnd == '-' ? -1 : 1) * (hours * 3600 + minutes * 60 + seconds); offsetHasBeenSet = true; } } } else { // nothing to do if the given name matches the current timezone if (strcasecmp(fTimeZoneID, timeZoneID) == 0) return B_OK; strlcpy(fTimeZoneID, timeZoneID, sizeof(fTimeZoneID)); } delete fTimeZone; fTimeZone = TimeZone::createTimeZone(fTimeZoneID); if (fTimeZone == NULL) return B_NO_MEMORY; if (offsetHasBeenSet) { fTimeZone->setRawOffset(*fDataBridge->addrOfTimezone * -1 * 1000); } else { int32_t rawOffset; int32_t dstOffset; UDate nowMillis = 1000 * (UDate)time(NULL); UErrorCode icuStatus = U_ZERO_ERROR; fTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, icuStatus); if (!U_SUCCESS(icuStatus)) { *fDataBridge->addrOfTimezone = 0; *fDataBridge->addrOfDaylight = false; strcpy(fDataBridge->addrOfTZName[0], "GMT"); strcpy(fDataBridge->addrOfTZName[1], "GMT"); return B_ERROR; } *fDataBridge->addrOfTimezone = -1 * (rawOffset + dstOffset) / 1000; // we want seconds, not the ms that ICU gives us } *fDataBridge->addrOfDaylight = fTimeZone->useDaylightTime(); for (int i = 0; i < 2; ++i) { if (tz != NULL && *tz != ':' && i == 0) { strcpy(fDataBridge->addrOfTZName[0], fTimeZoneID); } else { UnicodeString icuString; fTimeZone->getDisplayName(i == 1, TimeZone::SHORT, fTimeData.ICULocaleForStrings(), icuString); CheckedArrayByteSink byteSink(fDataBridge->addrOfTZName[i], sizeof(fTimeZoneID)); icuString.toUTF8(byteSink); // make sure to canonicalize "GMT+00:00" to just "GMT" if (strcmp(fDataBridge->addrOfTZName[i], "GMT+00:00") == 0) fDataBridge->addrOfTZName[i][3] = '\0'; } } return B_OK; }
LocaleWindow::LocaleWindow() : BWindow(BRect(0, 0, 0, 0), "Locale", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE | B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS) { BCountry* defaultCountry; be_locale_roster->GetDefaultCountry(&defaultCountry); SetLayout(new BGroupLayout(B_HORIZONTAL)); float spacing = be_control_look->DefaultItemSpacing(); BTabView* tabView = new BTabView("tabview"); BGroupView* languageTab = new BGroupView(B_TRANSLATE("Language"), B_HORIZONTAL, spacing); // first list: available languages fLanguageListView = new LanguageListView("available", B_MULTIPLE_SELECTION_LIST); BScrollView* scrollView = new BScrollView("scroller", fLanguageListView, B_WILL_DRAW | B_FRAME_EVENTS, false, true); fLanguageListView->SetInvocationMessage(new BMessage(kMsgLanguageInvoked)); fLanguageListView->SetDragMessage(new BMessage(kMsgLanguageDragged)); // Fill the language list from the LocaleRoster data BMessage installedLanguages; if (be_locale_roster->GetInstalledLanguages(&installedLanguages) == B_OK) { BString currentID; LanguageListItem* lastAddedCountryItem = NULL; for (int i = 0; installedLanguages.FindString("langs", i, ¤tID) == B_OK; i++) { // Now get an human-readable, localized name for each language BLanguage* currentLanguage; be_locale_roster->GetLanguage(currentID.String(), ¤tLanguage); BString name; currentLanguage->GetName(name); // TODO: as long as the app_server doesn't support font overlays, // use the translated name if problematic characters are used... const char* string = name.String(); while (uint32 code = BUnicodeChar::FromUTF8(&string)) { if (code > 1424) { currentLanguage->GetTranslatedName(name); break; } } LanguageListItem* item = new LanguageListItem(name, currentID.String(), currentLanguage->Code()); if (currentLanguage->IsCountrySpecific() && lastAddedCountryItem != NULL && lastAddedCountryItem->Code() == item->Code()) { fLanguageListView->AddUnder(item, lastAddedCountryItem); } else { // This is a language variant, add it at top-level fLanguageListView->AddItem(item); if (!currentLanguage->IsCountrySpecific()) { item->SetExpanded(false); lastAddedCountryItem = item; } } delete currentLanguage; } fLanguageListView->FullListSortItems(compare_typed_list_items); } else { BAlert* alert = new BAlert("Error", B_TRANSLATE("Unable to find the available languages! You can't " "use this preflet!"), B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_STOP_ALERT); alert->Go(); } // Second list: active languages fPreferredListView = new LanguageListView("preferred", B_MULTIPLE_SELECTION_LIST); BScrollView* scrollViewEnabled = new BScrollView("scroller", fPreferredListView, B_WILL_DRAW | B_FRAME_EVENTS, false, true); fPreferredListView->SetInvocationMessage( new BMessage(kMsgPreferredLanguageInvoked)); fPreferredListView->SetDeleteMessage( new BMessage(kMsgPreferredLanguageDeleted)); fPreferredListView->SetDragMessage( new BMessage(kMsgPreferredLanguageDragged)); BLayoutBuilder::Group<>(languageTab) .AddGroup(B_VERTICAL, spacing) .Add(new BStringView("", B_TRANSLATE("Available languages"))) .Add(scrollView) .End() .AddGroup(B_VERTICAL, spacing) .Add(new BStringView("", B_TRANSLATE("Preferred languages"))) .Add(scrollViewEnabled) .End() .SetInsets(spacing, spacing, spacing, spacing); BView* countryTab = new BView(B_TRANSLATE("Country"), B_WILL_DRAW); countryTab->SetLayout(new BGroupLayout(B_VERTICAL, 0)); BListView* listView = new BListView("country", B_SINGLE_SELECTION_LIST); scrollView = new BScrollView("scroller", listView, B_WILL_DRAW | B_FRAME_EVENTS, false, true); listView->SetSelectionMessage(new BMessage(kMsgCountrySelection)); // get all available countries from ICU // Use DateFormat::getAvailableLocale so we get only the one we can // use. Maybe check the NumberFormat one and see if there is more. int32_t localeCount; const Locale* currentLocale = Locale::getAvailableLocales(localeCount); for (int index = 0; index < localeCount; index++) { UnicodeString countryFullName; BString string; BStringByteSink sink(&string); currentLocale[index].getDisplayName(countryFullName); countryFullName.toUTF8(sink); LanguageListItem* item = new LanguageListItem(string, currentLocale[index].getName(), NULL); listView->AddItem(item); if (!strcmp(currentLocale[index].getName(), defaultCountry->Code())) listView->Select(listView->CountItems() - 1); } // TODO: find a real solution intead of this hack listView->SetExplicitMinSize( BSize(25 * be_plain_font->Size(), B_SIZE_UNSET)); fFormatView = new FormatView(defaultCountry); countryTab->AddChild(BLayoutBuilder::Group<>(B_HORIZONTAL, spacing) .AddGroup(B_VERTICAL, 3) .Add(scrollView) .End() .Add(fFormatView) .SetInsets(spacing, spacing, spacing, spacing)); listView->ScrollToSelection(); tabView->AddTab(languageTab); tabView->AddTab(countryTab); BButton* button = new BButton(B_TRANSLATE("Defaults"), new BMessage(kMsgDefaults)); fRevertButton = new BButton(B_TRANSLATE("Revert"), new BMessage(kMsgRevert)); fRevertButton->SetEnabled(false); BLayoutBuilder::Group<>(this, B_VERTICAL, spacing) .Add(tabView) .AddGroup(B_HORIZONTAL, spacing) .Add(button) .Add(fRevertButton) .AddGlue() .End() .SetInsets(spacing, spacing, spacing, spacing) .End(); _UpdatePreferredFromLocaleRoster(); SettingsReverted(); CenterOnScreen(); }