summaryrefslogtreecommitdiff
path: root/i18npool/source/ordinalsuffix/ordinalsuffix.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'i18npool/source/ordinalsuffix/ordinalsuffix.cxx')
-rw-r--r--i18npool/source/ordinalsuffix/ordinalsuffix.cxx102
1 files changed, 69 insertions, 33 deletions
diff --git a/i18npool/source/ordinalsuffix/ordinalsuffix.cxx b/i18npool/source/ordinalsuffix/ordinalsuffix.cxx
index 4d75b0f2b46e..e74fa0306256 100644
--- a/i18npool/source/ordinalsuffix/ordinalsuffix.cxx
+++ b/i18npool/source/ordinalsuffix/ordinalsuffix.cxx
@@ -17,6 +17,7 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
+#include <boost/scoped_ptr.hpp>
#include <comphelper/processfactory.hxx>
#include <string.h>
#include "ordinalsuffix.hxx"
@@ -44,6 +45,23 @@ OrdinalSuffix::~OrdinalSuffix()
{
}
+namespace
+{
+ OUString mungeUnicodeStringToOUString(const icu::UnicodeString &rIn, UErrorCode &rCode)
+ {
+ // Apply NFKC normalization to get normal letters
+ icu::UnicodeString normalized;
+ icu::Normalizer::normalize(rIn, UNORM_NFKC, 0, normalized, rCode);
+ // Convert the normalized UnicodeString to OUString
+ OUString sRet = (U_SUCCESS(rCode))
+ ? OUString(reinterpret_cast<const sal_Unicode *>(normalized.getBuffer()), normalized.length())
+ : OUString();
+ // replace any minus signs with hyphen-minus so that negative numbers
+ // from the simple number formatter and heavy-duty pattern formatter
+ // agree as to their negative number sign
+ return sRet.replace(0x2212, '-');
+ }
+}
/*
* For this method to properly return the ordinal suffix for other locales
@@ -60,46 +78,64 @@ uno::Sequence< OUString > SAL_CALL OrdinalSuffix::getOrdinalSuffix( sal_Int32 nN
CSTR( aLocale.Language ),
CSTR( aLocale.Country ),
CSTR( aLocale.Variant ) );
- icu::RuleBasedNumberFormat formatter(
- icu::URBNF_ORDINAL, rIcuLocale, nCode );
- if ( U_SUCCESS( nCode ) )
+ icu::RuleBasedNumberFormat formatter(icu::URBNF_ORDINAL, rIcuLocale, nCode);
+ if (!U_SUCCESS(nCode))
+ return retValue;
+
+ boost::scoped_ptr<NumberFormat> xNumberFormat(icu::NumberFormat::createInstance(rIcuLocale, nCode));
+ if (!U_SUCCESS(nCode))
+ return retValue;
+
+ icu::UnicodeString sFormatWithNoOrdinal;
+ xNumberFormat->format((int32_t)nNumber, sFormatWithNoOrdinal, NULL, nCode);
+ if (!U_SUCCESS(nCode))
+ return retValue;
+
+ OUString sValueWithNoOrdinal = mungeUnicodeStringToOUString(sFormatWithNoOrdinal, nCode);
+ if (!U_SUCCESS(nCode))
+ return retValue;
+
+ int32_t nRuleSets = formatter.getNumberOfRuleSetNames( );
+ for (int32_t i = 0; i < nRuleSets; ++i)
{
- int32_t nRuleSets = formatter.getNumberOfRuleSetNames( );
- for ( int32_t i = 0; i < nRuleSets; i++ )
- {
- icu::UnicodeString ruleSet = formatter.getRuleSetName( i );
- // format the string
- icu::UnicodeString icuRet;
- icu::FieldPosition icuPos;
- formatter.format( (int32_t)nNumber, ruleSet, icuRet, icuPos, nCode );
-
- if ( U_SUCCESS( nCode ) )
- {
- // Apply NFKC normalization to get normal letters
- icu::UnicodeString normalized;
- nCode = U_ZERO_ERROR;
- icu::Normalizer::normalize( icuRet, UNORM_NFKC, 0, normalized, nCode );
- if ( U_SUCCESS( nCode ) )
- {
- // Convert the normalized UnicodeString to OUString
- OUString sValue( reinterpret_cast<const sal_Unicode *>( normalized.getBuffer( ) ), normalized.length() );
-
- // Remove the number to get the prefix
- sal_Int32 len = OUString::valueOf( nNumber ).getLength( );
-
- sal_Int32 newLength = retValue.getLength() + 1;
- retValue.realloc( newLength );
- retValue[ newLength - 1 ] = sValue.copy( len );
- }
- }
- }
+ icu::UnicodeString ruleSet = formatter.getRuleSetName(i);
+
+ // format the string
+ icu::UnicodeString sFormatWithOrdinal;
+ icu::FieldPosition icuPos;
+ formatter.format( (int32_t)nNumber, ruleSet, sFormatWithOrdinal, icuPos, nCode );
+
+ if (!U_SUCCESS(nCode))
+ continue;
+
+ OUString sValueWithOrdinal = mungeUnicodeStringToOUString(sFormatWithOrdinal, nCode);
+ if (!U_SUCCESS(nCode))
+ continue;
+
+ // fdo#54486 lets make sure that the ordinal format and the non-ordinal
+ // format match at the start, so that the expectation can be verified
+ // that there is some trailing "ordinal suffix" which can be extracted
+ bool bSimpleOrdinalSuffix = sValueWithOrdinal.match(sValueWithNoOrdinal);
+
+ SAL_WARN_IF(!bSimpleOrdinalSuffix, "i18npool", "ordinal " <<
+ sValueWithOrdinal << " didn't start with expected " <<
+ sValueWithNoOrdinal << " prefix");
+
+ if (!bSimpleOrdinalSuffix)
+ continue;
+
+ // Remove the number to get the prefix
+ sal_Int32 len = sValueWithNoOrdinal.getLength();
+
+ sal_Int32 newLength = retValue.getLength() + 1;
+ retValue.realloc( newLength );
+ retValue[ newLength - 1 ] = sValueWithOrdinal.copy( len );
}
return retValue;
}
-
const sal_Char cOrdinalSuffix[] = "com.sun.star.i18n.OrdinalSuffix";
OUString SAL_CALL OrdinalSuffix::getImplementationName(void) throw( RuntimeException )