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