1 /* 2 ** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 ** Distributed under the terms of the OpenBeOS License. 4 */ 5 6 7 #include <AutoDeleter.h> 8 #include <CalendarView.h> 9 #include <Catalog.h> 10 #include <Locale.h> 11 #include <LocaleRoster.h> 12 #include <TimeZone.h> 13 14 #include <unicode/datefmt.h> 15 #include <unicode/dcfmtsym.h> 16 #include <unicode/decimfmt.h> 17 #include <unicode/dtfmtsym.h> 18 #include <unicode/numfmt.h> 19 #include <unicode/smpdtfmt.h> 20 #include <unicode/ustring.h> 21 #include <ICUWrapper.h> 22 23 #include <vector> 24 25 26 #define ICU_VERSION icu_44 27 28 29 using BPrivate::ObjectDeleter; 30 using BPrivate::B_WEEK_START_MONDAY; 31 using BPrivate::B_WEEK_START_SUNDAY; 32 33 34 static DateFormat* CreateDateFormat(bool longFormat, const Locale& locale, 35 const BString& format); 36 static DateFormat* CreateTimeFormat(bool longFormat, const Locale& locale, 37 const BString& format); 38 39 40 BLocale::BLocale(const char* languageAndCountryCode) 41 : 42 fCountry(languageAndCountryCode), 43 fLanguage(languageAndCountryCode), 44 fICULocale(new ICU_VERSION::Locale(languageAndCountryCode)) 45 { 46 } 47 48 49 BLocale::BLocale(const BLocale& other) 50 : 51 fCountry(other.fCountry), 52 fLanguage(other.fLanguage), 53 fICULocale(new ICU_VERSION::Locale(*other.fICULocale)), 54 fLongDateFormat(other.fLongDateFormat), 55 fShortDateFormat(other.fShortDateFormat), 56 fLongTimeFormat(other.fLongTimeFormat), 57 fShortTimeFormat(other.fShortTimeFormat) 58 { 59 } 60 61 62 BLocale& 63 BLocale::operator=(const BLocale& other) 64 { 65 if (this == &other) 66 return *this; 67 68 *fICULocale = *other.fICULocale; 69 70 fLongDateFormat = other.fLongDateFormat; 71 fShortDateFormat = other.fShortDateFormat; 72 fLongTimeFormat = other.fLongTimeFormat; 73 fShortTimeFormat = other.fShortTimeFormat; 74 75 fCountry = other.fCountry; 76 fLanguage = other.fLanguage; 77 78 return *this; 79 } 80 81 82 BLocale::~BLocale() 83 { 84 delete fICULocale; 85 } 86 87 88 const char * 89 BLocale::GetString(uint32 id) 90 { 91 // Note: this code assumes a certain order of the string bases 92 93 if (id >= B_OTHER_STRINGS_BASE) { 94 if (id == B_CODESET) 95 return "UTF-8"; 96 97 return ""; 98 } 99 return fLanguage.GetString(id); 100 } 101 102 103 void 104 BLocale::SetCountry(const BCountry& newCountry) 105 { 106 fCountry = newCountry; 107 } 108 109 110 void 111 BLocale::SetCollator(const BCollator& newCollator) 112 { 113 fCollator = newCollator; 114 } 115 116 117 void 118 BLocale::SetLanguage(const char* languageCode) 119 { 120 fLanguage.SetTo(languageCode); 121 } 122 123 124 const char* 125 BLocale::Code() const 126 { 127 return fICULocale->getName(); 128 } 129 130 131 bool 132 BLocale::GetName(BString& name) const 133 { 134 UnicodeString uString; 135 fICULocale->getDisplayName(uString); 136 BStringByteSink stringConverter(&name); 137 uString.toUTF8(stringConverter); 138 return true; 139 } 140 141 // #pragma mark - Date 142 143 144 status_t 145 BLocale::FormatDate(char* string, size_t maxSize, time_t time, bool longFormat) 146 { 147 ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, 148 *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); 149 if (dateFormatter.Get() == NULL) 150 return B_NO_MEMORY; 151 152 UnicodeString ICUString; 153 ICUString = dateFormatter->format((UDate)time * 1000, ICUString); 154 155 CheckedArrayByteSink stringConverter(string, maxSize); 156 157 ICUString.toUTF8(stringConverter); 158 159 if (stringConverter.Overflowed()) 160 return B_BAD_VALUE; 161 162 return B_OK; 163 } 164 165 166 status_t 167 BLocale::FormatDate(BString *string, time_t time, bool longFormat, 168 const BTimeZone* timeZone) 169 { 170 string->Truncate(0); 171 // We make the string empty, this way even in cases where ICU fail we at 172 // least return something sane 173 ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, 174 *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); 175 if (dateFormatter.Get() == NULL) 176 return B_NO_MEMORY; 177 178 if (timeZone != NULL) { 179 ObjectDeleter<TimeZone> icuTimeZone 180 = TimeZone::createTimeZone(timeZone->ID().String()); 181 if (icuTimeZone.Get() == NULL) 182 return B_NO_MEMORY; 183 dateFormatter->setTimeZone(*icuTimeZone.Get()); 184 } 185 186 UnicodeString ICUString; 187 ICUString = dateFormatter->format((UDate)time * 1000, ICUString); 188 189 BStringByteSink stringConverter(string); 190 ICUString.toUTF8(stringConverter); 191 192 return B_OK; 193 } 194 195 196 status_t 197 BLocale::FormatDate(BString* string, int*& fieldPositions, int& fieldCount, 198 time_t time, bool longFormat) 199 { 200 string->Truncate(0); 201 202 ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, 203 *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); 204 if (dateFormatter.Get() == NULL) 205 return B_NO_MEMORY; 206 207 fieldPositions = NULL; 208 UErrorCode error = U_ZERO_ERROR; 209 ICU_VERSION::FieldPositionIterator positionIterator; 210 UnicodeString ICUString; 211 ICUString = dateFormatter->format((UDate)time * 1000, ICUString, 212 &positionIterator, error); 213 214 if (error != U_ZERO_ERROR) 215 return B_ERROR; 216 217 ICU_VERSION::FieldPosition field; 218 std::vector<int> fieldPosStorage; 219 fieldCount = 0; 220 while (positionIterator.next(field)) { 221 fieldPosStorage.push_back(field.getBeginIndex()); 222 fieldPosStorage.push_back(field.getEndIndex()); 223 fieldCount += 2; 224 } 225 226 fieldPositions = (int*) malloc(fieldCount * sizeof(int)); 227 228 for (int i = 0 ; i < fieldCount ; i++ ) 229 fieldPositions[i] = fieldPosStorage[i]; 230 231 BStringByteSink stringConverter(string); 232 233 ICUString.toUTF8(stringConverter); 234 235 return B_OK; 236 } 237 238 239 status_t 240 BLocale::GetDateFormat(BString& format, bool longFormat) const 241 { 242 if (longFormat && fLongDateFormat.Length() > 0) 243 format = fLongDateFormat; 244 else if (!longFormat && fShortDateFormat.Length() > 0) 245 format = fShortDateFormat; 246 else { 247 format.Truncate(0); 248 249 ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, 250 *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); 251 if (dateFormatter.Get() == NULL) 252 return B_NO_MEMORY; 253 254 SimpleDateFormat* dateFormatterImpl 255 = static_cast<SimpleDateFormat*>(dateFormatter.Get()); 256 257 UnicodeString ICUString; 258 ICUString = dateFormatterImpl->toPattern(ICUString); 259 260 BStringByteSink stringConverter(&format); 261 262 ICUString.toUTF8(stringConverter); 263 } 264 265 return B_OK; 266 } 267 268 269 status_t 270 BLocale::SetDateFormat(const char* formatString, bool longFormat) 271 { 272 if (longFormat) 273 fLongDateFormat = formatString; 274 else 275 fShortDateFormat = formatString; 276 277 return B_OK; 278 } 279 280 281 status_t 282 BLocale::GetDateFields(BDateElement*& fields, int& fieldCount, 283 bool longFormat) const 284 { 285 ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, 286 *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); 287 if (dateFormatter.Get() == NULL) 288 return B_NO_MEMORY; 289 290 fields = NULL; 291 UErrorCode error = U_ZERO_ERROR; 292 ICU_VERSION::FieldPositionIterator positionIterator; 293 UnicodeString ICUString; 294 time_t now; 295 ICUString = dateFormatter->format((UDate)time(&now) * 1000, ICUString, 296 &positionIterator, error); 297 298 if (U_FAILURE(error)) 299 return B_ERROR; 300 301 ICU_VERSION::FieldPosition field; 302 std::vector<int> fieldPosStorage; 303 fieldCount = 0; 304 while (positionIterator.next(field)) { 305 fieldPosStorage.push_back(field.getField()); 306 fieldCount ++; 307 } 308 309 fields = (BDateElement*) malloc(fieldCount * sizeof(BDateElement)); 310 311 for (int i = 0 ; i < fieldCount ; i++ ) { 312 switch (fieldPosStorage[i]) { 313 case UDAT_YEAR_FIELD: 314 fields[i] = B_DATE_ELEMENT_YEAR; 315 break; 316 case UDAT_MONTH_FIELD: 317 fields[i] = B_DATE_ELEMENT_MONTH; 318 break; 319 case UDAT_DATE_FIELD: 320 fields[i] = B_DATE_ELEMENT_DAY; 321 break; 322 default: 323 fields[i] = B_DATE_ELEMENT_INVALID; 324 break; 325 } 326 } 327 328 return B_OK; 329 } 330 331 332 int 333 BLocale::StartOfWeek() const 334 { 335 UErrorCode err = U_ZERO_ERROR; 336 Calendar* c = Calendar::createInstance(*fICULocale, err); 337 338 if (err == U_ZERO_ERROR && c->getFirstDayOfWeek(err) == UCAL_SUNDAY) { 339 delete c; 340 return B_WEEK_START_SUNDAY; 341 } else { 342 delete c; 343 // Might be another day, but BeAPI will not handle it 344 return B_WEEK_START_MONDAY; 345 } 346 } 347 348 349 status_t 350 BLocale::FormatDateTime(char* target, size_t maxSize, time_t time, 351 bool longFormat) 352 { 353 ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, 354 *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); 355 if (dateFormatter.Get() == NULL) 356 return B_NO_MEMORY; 357 358 ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, 359 *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); 360 if (timeFormatter.Get() == NULL) 361 return B_NO_MEMORY; 362 363 UnicodeString ICUString; 364 ICUString = dateFormatter->format((UDate)time * 1000, ICUString); 365 366 ICUString.append(UnicodeString::fromUTF8(", ")); 367 368 ICUString = timeFormatter->format((UDate)time * 1000, ICUString); 369 370 CheckedArrayByteSink stringConverter(target, maxSize); 371 ICUString.toUTF8(stringConverter); 372 373 if (stringConverter.Overflowed()) 374 return B_BAD_VALUE; 375 376 return B_OK; 377 } 378 379 380 status_t 381 BLocale::FormatDateTime(BString* target, time_t time, bool longFormat, 382 const BTimeZone* timeZone) 383 { 384 ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, 385 *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); 386 if (dateFormatter.Get() == NULL) 387 return B_NO_MEMORY; 388 389 ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, 390 *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); 391 if (timeFormatter.Get() == NULL) 392 return B_NO_MEMORY; 393 394 if (timeZone != NULL) { 395 ObjectDeleter<TimeZone> icuTimeZone 396 = TimeZone::createTimeZone(timeZone->ID().String()); 397 if (icuTimeZone.Get() == NULL) 398 return B_NO_MEMORY; 399 timeFormatter->setTimeZone(*icuTimeZone.Get()); 400 } 401 402 UnicodeString ICUString; 403 ICUString = dateFormatter->format((UDate)time * 1000, ICUString); 404 405 ICUString.append(UnicodeString::fromUTF8(", ")); 406 407 ICUString = timeFormatter->format((UDate)time * 1000, ICUString); 408 409 BStringByteSink stringConverter(target); 410 ICUString.toUTF8(stringConverter); 411 412 return B_OK; 413 } 414 415 416 // #pragma mark - Time 417 418 419 status_t 420 BLocale::FormatTime(char* string, size_t maxSize, time_t time, bool longFormat) 421 { 422 ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, 423 *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); 424 if (timeFormatter.Get() == NULL) 425 return B_NO_MEMORY; 426 427 UnicodeString ICUString; 428 ICUString = timeFormatter->format((UDate)time * 1000, ICUString); 429 430 CheckedArrayByteSink stringConverter(string, maxSize); 431 432 ICUString.toUTF8(stringConverter); 433 434 if (stringConverter.Overflowed()) 435 return B_BAD_VALUE; 436 437 return B_OK; 438 } 439 440 441 status_t 442 BLocale::FormatTime(BString* string, time_t time, bool longFormat, 443 const BTimeZone* timeZone) 444 { 445 string->Truncate(0); 446 447 ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, 448 *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); 449 if (timeFormatter.Get() == NULL) 450 return B_NO_MEMORY; 451 452 if (timeZone != NULL) { 453 ObjectDeleter<TimeZone> icuTimeZone 454 = TimeZone::createTimeZone(timeZone->ID().String()); 455 if (icuTimeZone.Get() == NULL) 456 return B_NO_MEMORY; 457 timeFormatter->setTimeZone(*icuTimeZone.Get()); 458 } 459 460 UnicodeString ICUString; 461 ICUString = timeFormatter->format((UDate)time * 1000, ICUString); 462 463 BStringByteSink stringConverter(string); 464 465 ICUString.toUTF8(stringConverter); 466 467 return B_OK; 468 } 469 470 471 status_t 472 BLocale::FormatTime(BString* string, int*& fieldPositions, int& fieldCount, 473 time_t time, bool longFormat) 474 { 475 string->Truncate(0); 476 477 ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, 478 *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); 479 if (timeFormatter.Get() == NULL) 480 return B_NO_MEMORY; 481 482 fieldPositions = NULL; 483 UErrorCode error = U_ZERO_ERROR; 484 ICU_VERSION::FieldPositionIterator positionIterator; 485 UnicodeString ICUString; 486 ICUString = timeFormatter->format((UDate)time * 1000, ICUString, 487 &positionIterator, error); 488 489 if (error != U_ZERO_ERROR) 490 return B_ERROR; 491 492 ICU_VERSION::FieldPosition field; 493 std::vector<int> fieldPosStorage; 494 fieldCount = 0; 495 while (positionIterator.next(field)) { 496 fieldPosStorage.push_back(field.getBeginIndex()); 497 fieldPosStorage.push_back(field.getEndIndex()); 498 fieldCount += 2; 499 } 500 501 fieldPositions = (int*) malloc(fieldCount * sizeof(int)); 502 503 for (int i = 0 ; i < fieldCount ; i++ ) 504 fieldPositions[i] = fieldPosStorage[i]; 505 506 BStringByteSink stringConverter(string); 507 508 ICUString.toUTF8(stringConverter); 509 510 return B_OK; 511 } 512 513 514 status_t 515 BLocale::GetTimeFields(BDateElement*& fields, int& fieldCount, 516 bool longFormat) const 517 { 518 ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, 519 *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); 520 if (timeFormatter.Get() == NULL) 521 return B_NO_MEMORY; 522 523 fields = NULL; 524 UErrorCode error = U_ZERO_ERROR; 525 ICU_VERSION::FieldPositionIterator positionIterator; 526 UnicodeString ICUString; 527 time_t now; 528 ICUString = timeFormatter->format((UDate)time(&now) * 1000, ICUString, 529 &positionIterator, error); 530 531 if (error != U_ZERO_ERROR) 532 return B_ERROR; 533 534 ICU_VERSION::FieldPosition field; 535 std::vector<int> fieldPosStorage; 536 fieldCount = 0; 537 while (positionIterator.next(field)) { 538 fieldPosStorage.push_back(field.getField()); 539 fieldCount ++; 540 } 541 542 fields = (BDateElement*) malloc(fieldCount * sizeof(BDateElement)); 543 544 for (int i = 0 ; i < fieldCount ; i++ ) { 545 switch (fieldPosStorage[i]) { 546 case UDAT_HOUR_OF_DAY1_FIELD: 547 case UDAT_HOUR_OF_DAY0_FIELD: 548 case UDAT_HOUR1_FIELD: 549 case UDAT_HOUR0_FIELD: 550 fields[i] = B_DATE_ELEMENT_HOUR; 551 break; 552 case UDAT_MINUTE_FIELD: 553 fields[i] = B_DATE_ELEMENT_MINUTE; 554 break; 555 case UDAT_SECOND_FIELD: 556 fields[i] = B_DATE_ELEMENT_SECOND; 557 break; 558 case UDAT_AM_PM_FIELD: 559 fields[i] = B_DATE_ELEMENT_AM_PM; 560 break; 561 default: 562 fields[i] = B_DATE_ELEMENT_INVALID; 563 break; 564 } 565 } 566 567 return B_OK; 568 } 569 570 571 status_t 572 BLocale::SetTimeFormat(const char* formatString, bool longFormat) 573 { 574 if (longFormat) 575 fLongTimeFormat = formatString; 576 else 577 fShortTimeFormat = formatString; 578 579 return B_OK; 580 } 581 582 583 status_t 584 BLocale::GetTimeFormat(BString& format, bool longFormat) const 585 { 586 if (longFormat && fLongTimeFormat.Length() > 0) 587 format = fLongTimeFormat; 588 else if (!longFormat && fShortTimeFormat.Length() > 0) 589 format = fShortTimeFormat; 590 else { 591 format.Truncate(0); 592 593 ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, 594 *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); 595 if (timeFormatter.Get() == NULL) 596 return B_NO_MEMORY; 597 598 SimpleDateFormat* timeFormatterImpl 599 = static_cast<SimpleDateFormat*>(timeFormatter.Get()); 600 601 UnicodeString ICUString; 602 ICUString = timeFormatterImpl->toPattern(ICUString); 603 604 BStringByteSink stringConverter(&format); 605 ICUString.toUTF8(stringConverter); 606 } 607 608 return B_OK; 609 } 610 611 612 // #pragma mark - Numbers 613 614 615 status_t 616 BLocale::FormatNumber(char* string, size_t maxSize, double value) 617 { 618 BString fullString; 619 status_t status = FormatNumber(&fullString, value); 620 if (status == B_OK) 621 strlcpy(string, fullString.String(), maxSize); 622 623 return status; 624 } 625 626 627 status_t 628 BLocale::FormatNumber(BString* string, double value) 629 { 630 UErrorCode err = U_ZERO_ERROR; 631 ObjectDeleter<NumberFormat> numberFormatter = NumberFormat::createInstance( 632 *fICULocale, NumberFormat::kNumberStyle, err); 633 634 if (numberFormatter.Get() == NULL) 635 return B_NO_MEMORY; 636 if (U_FAILURE(err)) 637 return B_ERROR; 638 639 UnicodeString ICUString; 640 ICUString = numberFormatter->format(value, ICUString); 641 642 string->Truncate(0); 643 BStringByteSink stringConverter(string); 644 ICUString.toUTF8(stringConverter); 645 646 return B_OK; 647 } 648 649 650 status_t 651 BLocale::FormatNumber(char* string, size_t maxSize, int32 value) 652 { 653 BString fullString; 654 status_t status = FormatNumber(&fullString, value); 655 if (status == B_OK) 656 strlcpy(string, fullString.String(), maxSize); 657 658 return status; 659 } 660 661 662 status_t 663 BLocale::FormatNumber(BString* string, int32 value) 664 { 665 UErrorCode err = U_ZERO_ERROR; 666 ObjectDeleter<NumberFormat> numberFormatter = NumberFormat::createInstance( 667 *fICULocale, NumberFormat::kNumberStyle, err); 668 669 if (numberFormatter.Get() == NULL) 670 return B_NO_MEMORY; 671 if (U_FAILURE(err)) 672 return B_ERROR; 673 674 UnicodeString ICUString; 675 ICUString = numberFormatter->format((int32_t)value, ICUString); 676 677 string->Truncate(0); 678 BStringByteSink stringConverter(string); 679 ICUString.toUTF8(stringConverter); 680 681 return B_OK; 682 } 683 684 685 ssize_t 686 BLocale::FormatMonetary(char* string, size_t maxSize, double value) 687 { 688 BString fullString; 689 ssize_t written = FormatMonetary(&fullString, value); 690 if (written < 0) 691 return written; 692 693 return strlcpy(string, fullString.String(), maxSize); 694 } 695 696 697 ssize_t 698 BLocale::FormatMonetary(BString* string, double value) 699 { 700 if (string == NULL) 701 return B_BAD_VALUE; 702 703 UErrorCode err; 704 ObjectDeleter<NumberFormat> numberFormatter 705 = NumberFormat::createCurrencyInstance(*fICULocale, err); 706 707 if (numberFormatter.Get() == NULL) 708 return B_NO_MEMORY; 709 if (U_FAILURE(err)) 710 return B_ERROR; 711 712 UnicodeString ICUString; 713 ICUString = numberFormatter->format(value, ICUString); 714 715 string->Truncate(0); 716 BStringByteSink stringConverter(string); 717 ICUString.toUTF8(stringConverter); 718 719 return string->Length(); 720 } 721 722 723 status_t 724 BLocale::FormatMonetary(BString* string, int*& fieldPositions, 725 BNumberElement*& fieldTypes, int& fieldCount, double value) 726 { 727 UErrorCode err = U_ZERO_ERROR; 728 ObjectDeleter<NumberFormat> numberFormatter 729 = NumberFormat::createCurrencyInstance(*fICULocale, err); 730 if (U_FAILURE(err)) 731 return B_NO_MEMORY; 732 733 string->Truncate(0); 734 735 fieldPositions = NULL; 736 fieldTypes = NULL; 737 ICU_VERSION::FieldPositionIterator positionIterator; 738 UnicodeString ICUString; 739 ICUString = numberFormatter->format(value, ICUString, &positionIterator, 740 err); 741 742 if (err != U_ZERO_ERROR) 743 return B_ERROR; 744 745 ICU_VERSION::FieldPosition field; 746 std::vector<int> fieldPosStorage; 747 std::vector<int> fieldTypeStorage; 748 fieldCount = 0; 749 while (positionIterator.next(field)) { 750 fieldTypeStorage.push_back(field.getField()); 751 fieldPosStorage.push_back(field.getBeginIndex() | (field.getEndIndex() << 16)); 752 fieldCount ++; 753 754 } 755 756 fieldPositions = (int*) malloc(fieldCount * sizeof(int)); 757 fieldTypes = (BNumberElement*) malloc(fieldCount * sizeof(BNumberElement)); 758 759 for (int i = 0 ; i < fieldCount ; i++ ) { 760 fieldPositions[i] = fieldPosStorage[i]; 761 switch (fieldTypeStorage[i]) { 762 case NumberFormat::kCurrencyField: 763 fieldTypes[i] = B_NUMBER_ELEMENT_CURRENCY; 764 break; 765 case NumberFormat::kIntegerField: 766 fieldTypes[i] = B_NUMBER_ELEMENT_INTEGER; 767 break; 768 case NumberFormat::kFractionField: 769 fieldTypes[i] = B_NUMBER_ELEMENT_FRACTIONAL; 770 break; 771 default: 772 fieldTypes[i] = B_NUMBER_ELEMENT_INVALID; 773 break; 774 } 775 } 776 777 BStringByteSink stringConverter(string); 778 779 ICUString.toUTF8(stringConverter); 780 781 return B_OK; 782 } 783 784 785 status_t 786 BLocale::GetCurrencySymbol(BString& result) 787 { 788 UErrorCode error = U_ZERO_ERROR; 789 NumberFormat* format = NumberFormat::createCurrencyInstance(*fICULocale, 790 error); 791 792 if (U_FAILURE(error)) 793 return B_ERROR; 794 795 char* symbol = (char*)malloc(20); 796 u_strToUTF8(symbol, 20, NULL, format->getCurrency(), -1, &error); 797 if (U_FAILURE(error)) 798 return B_BAD_DATA; 799 result.Append(symbol); 800 delete format; 801 delete symbol; 802 return B_OK; 803 } 804 805 806 // #pragma mark - Helpers 807 808 809 static DateFormat* 810 CreateDateFormat(bool longFormat, const Locale& locale, 811 const BString& format) 812 { 813 DateFormat* dateFormatter = DateFormat::createDateInstance( 814 longFormat ? DateFormat::FULL : DateFormat::SHORT, locale); 815 816 if (format.Length() > 0) { 817 SimpleDateFormat* dateFormatterImpl 818 = static_cast<SimpleDateFormat*>(dateFormatter); 819 820 UnicodeString pattern(format.String()); 821 dateFormatterImpl->applyPattern(pattern); 822 } 823 824 return dateFormatter; 825 } 826 827 828 static DateFormat* 829 CreateTimeFormat(bool longFormat, const Locale& locale, 830 const BString& format) 831 { 832 DateFormat* timeFormatter = DateFormat::createTimeInstance( 833 longFormat ? DateFormat::MEDIUM : DateFormat::SHORT, locale); 834 835 if (format.Length() > 0) { 836 SimpleDateFormat* timeFormatterImpl 837 = static_cast<SimpleDateFormat*>(timeFormatter); 838 839 UnicodeString pattern(format.String()); 840 timeFormatterImpl->applyPattern(pattern); 841 } 842 843 return timeFormatter; 844 } 845