[Libreoffice-commits] .: Branch 'libreoffice-3-4' - svl/inc svl/source

Caolán McNamara caolan at kemper.freedesktop.org
Fri Aug 5 04:18:59 PDT 2011


 svl/inc/svl/zforlist.hxx        |   18 ++++
 svl/inc/svl/zformat.hxx         |   16 ++++
 svl/source/numbers/zforlist.cxx |    2 
 svl/source/numbers/zformat.cxx  |  146 +++++++++++++++++++++++++++++++---------
 4 files changed, 147 insertions(+), 35 deletions(-)

New commits:
commit 14a83b892ead65acf16d566e2b69c2e8dd75d617
Author: Eike Rathke <ooo at erack.de>
Date:   Thu Aug 4 23:43:19 2011 +0200

    Fix fdo#38956 discarding bracketed prefixes in number formats, such as [RED]
    
    * Fixed discarding of prefixes.
    * Fixed the broken handling of Thai calendar and numerals speciality.
    * Added bits to actually display a format with embedded LCID in the dialog if
      the LCID doesn't match the currently viewed locale.
    (cherry picked from commit fbe916fd7dc7ba22b8652bc0c5b8a0d9cb15cc9d)
    
    Conflicts:
    
    	svl/inc/svl/zforlist.hxx
    	svl/source/numbers/zformat.cxx

diff --git a/svl/inc/svl/zforlist.hxx b/svl/inc/svl/zforlist.hxx
index eef1904..303b55e 100644
--- a/svl/inc/svl/zforlist.hxx
+++ b/svl/inc/svl/zforlist.hxx
@@ -42,6 +42,7 @@
 #include <svl/nfkeytab.hxx>
 
 #include <map>
+#include <set>
 
 class Date;
 class SvStream;
@@ -225,6 +226,8 @@ typedef Table SvNumberFormatterIndexTable;
 
 typedef ::std::map< sal_uInt32, sal_uInt32 > SvNumberFormatterMergeMap;
 
+typedef ::std::set< LanguageType > NfInstalledLocales;
+
 
 /** Language/country dependent currency entries
  */
@@ -343,6 +346,9 @@ public:
      */
     static const sal_uInt16 INPUTSTRING_PRECISION;
 
+    /** THE set of installed locales. */
+    static NfInstalledLocales theInstalledLocales;
+
     /// Preferred ctor with service manager and language/country enum
     SvNumberFormatter(
         const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xSMgr,
@@ -798,9 +804,15 @@ public:
         language/country, used in XML import */
     String GetStandardName( LanguageType eLnge );
 
-    /// Skip a NumberFormatter in stream, Chart needs this
-    static void SkipNumberFormatterInStream( SvStream& );
-
+    /** Check if a specific locale has supported locale data. */
+    static bool IsLocaleInstalled( LanguageType eLang )
+    {
+        // The set is initialized as a side effect of the currency table
+        // created, make sure that exists, which usually is the case unless a
+        // SvNumberFormatter was never instanciated.
+        GetTheCurrencyTable();
+        return theInstalledLocales.find( eLang) != theInstalledLocales.end();
+    }
 
 private:
     ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager;
diff --git a/svl/inc/svl/zformat.hxx b/svl/inc/svl/zformat.hxx
index bb43932..82a6046 100644
--- a/svl/inc/svl/zformat.hxx
+++ b/svl/inc/svl/zformat.hxx
@@ -529,6 +529,22 @@ private:
      */
     SVL_DLLPRIVATE static LocaleType ImpGetLocaleType( const String& rString, xub_StrLen& nPos );
 
+    /** Obtain calendar and numerals from a LocaleType that was parsed from a
+        LCID with ImpGetLocaleType().
+
+        Inserts a NatNum modifier to rString at nPos if needed as determined 
+        from the numeral code.
+
+        @ATTENTION: may modify <member>maLocale</member> to make it follow 
+        aTmpLocale, in which case also nLang is adapted.
+
+        @returns a string with the calendar if one was determined from the 
+        calendar code, else an empty string. The calendar string needs to be 
+        inserted at a proper positon to rString after all bracketed prefixes.
+     */
+    SVL_DLLPRIVATE String ImpObtainCalendarAndNumerals( String & rString,
+            xub_StrLen & nPos, LanguageType & nLang, const LocaleType & aTmpLocale );
+
     // standard number output
     SVL_DLLPRIVATE void ImpGetOutputStandard( double& fNumber, String& OutString );
     SVL_DLLPRIVATE void ImpGetOutputStdToPrecision( double& rNumber, String& rOutString, sal_uInt16 nPrecision ) const;
diff --git a/svl/source/numbers/zforlist.cxx b/svl/source/numbers/zforlist.cxx
index 2a62b2b..88e5008 100644
--- a/svl/source/numbers/zforlist.cxx
+++ b/svl/source/numbers/zforlist.cxx
@@ -181,6 +181,7 @@ SV_IMPL_PTRARR( NfWSStringsDtor, String* );
 
 const sal_uInt16 SvNumberFormatter::UNLIMITED_PRECISION   = ::std::numeric_limits<sal_uInt16>::max();
 const sal_uInt16 SvNumberFormatter::INPUTSTRING_PRECISION = ::std::numeric_limits<sal_uInt16>::max()-1;
+NfInstalledLocales SvNumberFormatter::theInstalledLocales;
 
 SvNumberFormatter::SvNumberFormatter(
             const Reference< XMultiServiceFactory >& xSMgr,
@@ -3678,6 +3679,7 @@ void SvNumberFormatter::ImpInitCurrencyTable()
     {
         LanguageType eLang = MsLangId::convertLocaleToLanguage(
                 pLocales[nLocale]);
+        theInstalledLocales.insert( eLang);
         pLocaleData->setLocale( pLocales[nLocale] );
         Sequence< Currency2 > aCurrSeq = pLocaleData->getAllCurrencies();
         sal_Int32 nCurrencyCount = aCurrSeq.getLength();
diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx
index eff1a1c..a0570ee 100644
--- a/svl/source/numbers/zformat.cxx
+++ b/svl/source/numbers/zformat.cxx
@@ -595,6 +595,46 @@ sal_Bool lcl_SvNumberformat_IsBracketedPrefix( short nSymbolType )
     return sal_False;
 }
 
+
+String SvNumberformat::ImpObtainCalendarAndNumerals( String & rString, 
+        xub_StrLen & nPos, LanguageType & nLang, const LocaleType & aTmpLocale )
+{
+    String sCalendar;
+    /* TODO: this could be enhanced to allow other possible locale dependent 
+     * calendars and numerals. BUT only if our locale data allows it! For LCID 
+     * numerals and calendars see 
+     * http://office.microsoft.com/en-us/excel/HA010346351033.aspx */
+    if (MsLangId::getRealLanguage( aTmpLocale.meLanguage) == LANGUAGE_THAI)
+    {
+        // Numeral shape code "D" = Thai digits.
+        if (aTmpLocale.mnNumeralShape == 0xD)
+            rString.InsertAscii( "[NatNum1]", nPos);
+
+        // Calendar type code "07" = Thai Buddhist calendar, insert this after 
+        // all prefixes have been consumed as it is actually a format modifier 
+        // and not a prefix.
+        if (aTmpLocale.mnCalendarType == 0x07)
+        {
+            // Currently calendars are tied to the locale of the entire number 
+            // format, e.g. [~buddhist] in en_US doesn't work.
+            // => Having different locales in sub formats does not work!
+            /* TODO: calendars could be tied to a sub format's NatNum info 
+             * instead, or even better be available for any locale. Needs a 
+             * different implementation of GetCal() and locale data calendars. 
+             * */
+            // If this is not Thai yet, make it so.
+            if (MsLangId::getRealLanguage( maLocale.meLanguage) != LANGUAGE_THAI)
+            {
+                maLocale = aTmpLocale;
+                nLang = maLocale.meLanguage = LANGUAGE_THAI;
+            }
+            sCalendar.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "[~buddhist]"));
+        }
+    }
+    return sCalendar;
+}
+
+
 SvNumberformat::SvNumberformat(String& rString,
                                ImpSvNumberformatScan* pSc,
                                ImpSvNumberInputScan* pISc,
@@ -650,6 +690,7 @@ SvNumberformat::SvNumberformat(String& rString,
         if (rScan.GetConvertMode())
             (rScan.GetNumberformatter())->ChangeIntl(rScan.GetTmpLnge());
 
+        String sInsertCalendar;     // a calendar resulting from parsing LCID
         String sStr;
         nPosOld = nPos;                         // Start position of substring
         // first get bracketed prefixes; e.g. conditions, color
@@ -709,6 +750,7 @@ SvNumberformat::SvNumberformat(String& rString,
             }
             else if ( lcl_SvNumberformat_IsBracketedPrefix( eSymbolType ) )
             {
+                String sSymbol( sStr);
                 switch ( eSymbolType )
                 {
                     case BRACKET_SYMBOLTYPE_COLOR :
@@ -793,7 +835,11 @@ SvNumberformat::SvNumberformat(String& rString,
                     break;
                     case BRACKET_SYMBOLTYPE_LOCALE :
                     {
-                        if ( NumFor[nIndex].GetNatNum().GetLang() != LANGUAGE_DONTKNOW )
+                        if ( NumFor[nIndex].GetNatNum().GetLang() != LANGUAGE_DONTKNOW ||
+                                rString.GetChar(nPos-1) != ']' )
+                                // Check also for ']' to avoid pulling in 
+                                // locale data for the preview string for not 
+                                // yet completed LCIDs in the dialog.
                         {
                             bCancel = sal_True;         // break for
                             nCheckPos = nPosOld;
@@ -801,17 +847,50 @@ SvNumberformat::SvNumberformat(String& rString,
                         else
                         {
                             xub_StrLen nTmp = 2;
-                            maLocale = ImpGetLocaleType( sStr, nTmp );
-                            if (maLocale.meLanguage == LANGUAGE_DONTKNOW)
+                            LocaleType aTmpLocale( ImpGetLocaleType( sStr, nTmp));
+                            if (aTmpLocale.meLanguage == LANGUAGE_DONTKNOW)
                             {
                                 bCancel = sal_True;         // break for
                                 nCheckPos = nPosOld;
                             }
-                            else if (maLocale.meLanguage != 0)
+                            else
                             {
+                                // Only the first sub format's locale will be 
+                                // used as the format's overall locale.
+                                // Sorts this also under the corresponding 
+                                // locale for the dialog.
+                                // If we don't support the locale this would 
+                                // result in an unknown (empty) language 
+                                // listbox entry and the user would never see 
+                                // this format.
+                                if (nIndex == 0 && (aTmpLocale.meLanguage == 0 || 
+                                            SvNumberFormatter::IsLocaleInstalled( aTmpLocale.meLanguage)))
+                                {
+                                    maLocale = aTmpLocale;
+                                    eLan = aTmpLocale.meLanguage;   // return to caller
+                                    /* TODO: fiddle with scanner to make this 
+                                     * known? A change in the locale may affect 
+                                     * separators and keywords. On the other 
+                                     * hand they may have been entered as used 
+                                     * in the originating locale, there's no 
+                                     * way to predict other than analyzing the 
+                                     * format code, we assume here the current 
+                                     * context is used, which is most likely 
+                                     * the case.
+                                     * */
+                                }
                                 sStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM("$-") );
-                                sStr = sStr + maLocale.generateCode();
-                                NumFor[nIndex].SetNatNumLang(maLocale.meLanguage);
+                                sStr += String( aTmpLocale.generateCode());
+                                NumFor[nIndex].SetNatNumLang( MsLangId::getRealLanguage( aTmpLocale.meLanguage));
+
+                                // "$-NNCCLLLL" Numerals and Calendar
+                                if (sSymbol.Len() > 6)
+                                    sInsertCalendar = ImpObtainCalendarAndNumerals( rString, nPos, eLan, aTmpLocale);
+                                    /* NOTE: there can be only one calendar 
+                                     * inserted so the last one wins, though 
+                                     * our own calendar modifiers support 
+                                     * multiple calendars within one sub format 
+                                     * code if at different positions. */
                             }
                         }
                     }
@@ -819,19 +898,24 @@ SvNumberformat::SvNumberformat(String& rString,
                 }
                 if ( !bCancel )
                 {
-                    rString.Erase(nPosOld,nPos-nPosOld);
-                    if (maLocale.meLanguage != 0)
-                    {
-                        rString.Insert(sStr,nPosOld);
-                        nPos = nPosOld + sStr.Len();
-                        rString.Insert(']', nPos);
-                        rString.Insert('[', nPosOld);
-                        nPos += 2;
-                        nPosOld = nPos;     // position before string
-                    }
+                    if (sStr == sSymbol)
+                        nPosOld = nPos;
                     else
                     {
-                        nPos = nPosOld;     // Excel LCID removed
+                        rString.Erase(nPosOld,nPos-nPosOld);
+                        if (sStr.Len())
+                        {
+                            rString.Insert(sStr,nPosOld);
+                            nPos = nPosOld + sStr.Len();
+                            rString.Insert(']', nPos);
+                            rString.Insert('[', nPosOld);
+                            nPos += 2;
+                            nPosOld = nPos;     // position before string
+                        }
+                        else
+                        {
+                            nPos = nPosOld;     // prefix removed for whatever reason
+                        }
                     }
                 }
             }
@@ -851,6 +935,9 @@ SvNumberformat::SvNumberformat(String& rString,
                 }
                 else
                 {
+                    if (sInsertCalendar.Len())
+                        sStr.Insert( sInsertCalendar, 0);
+
                     xub_StrLen nStrPos = pSc->ScanFormat( sStr, aComment );
                     sal_uInt16 nAnz = pSc->GetAnzResStrings();
                     if (nAnz == 0)              // error
@@ -1130,7 +1217,8 @@ OUString SvNumberformat::LocaleType::generateCode() const
         for (sal_uInt8 i = 0; i < 2; ++i)
         {
             sal_uInt8 n = (nVal & 0xF0) >> 4;
-            aBuf.append(toUniChar(n));
+            if (n || aBuf.getLength())
+                aBuf.append(toUniChar(n));
             nVal = nVal << 4;
         }
     }
@@ -1141,7 +1229,8 @@ OUString SvNumberformat::LocaleType::generateCode() const
         for (sal_uInt8 i = 0; i < 2; ++i)
         {
             sal_uInt8 n = (nVal & 0xF0) >> 4;
-            aBuf.append(toUniChar(n));
+            if (n || aBuf.getLength())
+                aBuf.append(toUniChar(n));
             nVal = nVal << 4;
         }
     }
@@ -1151,7 +1240,9 @@ OUString SvNumberformat::LocaleType::generateCode() const
     for (sal_uInt8 i = 0; i < 4; ++i)
     {
         sal_uInt8 n = static_cast<sal_uInt8>((n16 & 0xF000) >> 12);
-        aBuf.append(toUniChar(n));
+        // Omit leading zeros for consistency.
+        if (n || aBuf.getLength() || i == 3)
+            aBuf.append(toUniChar(n));
         n16 = n16 << 4;
     }
 
@@ -1183,8 +1274,9 @@ SvNumberformat::LocaleType SvNumberformat::ImpGetLocaleType(
 {
     sal_uInt32 nNum = 0;
     sal_Unicode cToken = 0;
+    xub_StrLen nStart = nPos;
     xub_StrLen nLen = rString.Len();
-    while ( nPos < nLen && ((cToken = rString.GetChar(nPos)) != ']') )
+    while ( nPos < nLen && (nPos - nStart < 8) && ((cToken = rString.GetChar(nPos)) != ']') )
     {
         if ( '0' <= cToken && cToken <= '9' )
         {
@@ -1206,7 +1298,7 @@ SvNumberformat::LocaleType SvNumberformat::ImpGetLocaleType(
         ++nPos;
     }
 
-    return (nNum && (cToken == ']' || nPos == nLen)) ? LocaleType(nNum) : LocaleType();
+    return (cToken == ']' || nPos == nLen) ? LocaleType(nNum) : LocaleType();
 }
 
 short SvNumberformat::ImpNextSymbol(String& rString,
@@ -1290,16 +1382,6 @@ short SvNumberformat::ImpNextSymbol(String& rString,
                     {
                         if ( rString.GetChar(nPos) == '-' )
                         {   // [$-xxx] locale
-                            if ( rString.GetChar(nPos+2) == '0' && rString.GetChar(nPos+3) == '7' ) // calendar type code "07" = Thai
-                            {
-                              rString.InsertAscii( "[~buddhist]", nPos+9 );
-                              nLen += 11;
-                            }
-                            if ( rString.GetChar(nPos+1) == 'D' ) // numeral shape code "D" = Thai digits
-                            {
-                              rString.InsertAscii( "[NatNum1]", nPos+9 );
-                              nLen += 9;
-                            }
                             sSymbol.EraseAllChars('[');
                             eSymbolType = BRACKET_SYMBOLTYPE_LOCALE;
                             eState = SsGetPrefix;


More information about the Libreoffice-commits mailing list