LCOV - code coverage report
Current view: top level - xmloff/source/style - xmlnumfi.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 693 879 78.8 %
Date: 2015-06-13 12:38:46 Functions: 60 76 78.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <comphelper/string.hxx>
      21             : #include <unotools/syslocale.hxx>
      22             : 
      23             : #include <svl/zforlist.hxx>
      24             : 
      25             : #include <svl/zformat.hxx>
      26             : #include <svl/numuno.hxx>
      27             : #include <rtl/math.hxx>
      28             : #include <i18nlangtag/languagetag.hxx>
      29             : #include <tools/color.hxx>
      30             : #include <tools/debug.hxx>
      31             : #include <osl/diagnose.h>
      32             : #include <rtl/ustrbuf.hxx>
      33             : 
      34             : #include <sax/tools/converter.hxx>
      35             : 
      36             : #include <xmloff/xmlnumfi.hxx>
      37             : #include <xmloff/xmltkmap.hxx>
      38             : #include <xmloff/xmlnmspe.hxx>
      39             : #include <xmloff/xmlictxt.hxx>
      40             : #include <xmloff/xmlimp.hxx>
      41             : #include <xmloff/xmluconv.hxx>
      42             : #include <xmloff/nmspmap.hxx>
      43             : #include <xmloff/families.hxx>
      44             : #include <xmloff/xmltoken.hxx>
      45             : #include <xmloff/languagetagodf.hxx>
      46             : 
      47             : #include <boost/ptr_container/ptr_vector.hpp>
      48             : #include <boost/ptr_container/ptr_set.hpp>
      49             : 
      50             : using namespace ::com::sun::star;
      51             : using namespace ::xmloff::token;
      52             : 
      53        1942 : struct SvXMLNumFmtEntry
      54             : {
      55             :     OUString   aName;
      56             :     sal_uInt32  nKey;
      57             :     bool        bRemoveAfterUse;
      58             : 
      59        1942 :     SvXMLNumFmtEntry( const OUString& rN, sal_uInt32 nK, bool bR ) :
      60        1942 :         aName(rN), nKey(nK), bRemoveAfterUse(bR) {}
      61             : };
      62             : 
      63             : typedef ::boost::ptr_vector<SvXMLNumFmtEntry> SvXMLNumFmtEntryArr;
      64             : 
      65           0 : struct SvXMLEmbeddedElement
      66             : {
      67             :     sal_Int32       nFormatPos;
      68             :     OUString   aText;
      69             : 
      70           0 :     SvXMLEmbeddedElement( sal_Int32 nFP, const OUString& rT ) :
      71           0 :         nFormatPos(nFP), aText(rT) {}
      72             : 
      73           0 :     bool operator < ( const SvXMLEmbeddedElement& r ) const { return nFormatPos <  r.nFormatPos; }
      74             : };
      75             : 
      76             : typedef boost::ptr_set<SvXMLEmbeddedElement> SvXMLEmbeddedElementArr;
      77             : 
      78             : class SvXMLNumImpData
      79             : {
      80             :     SvNumberFormatter*  pFormatter;
      81             :     SvXMLTokenMap*      pStylesElemTokenMap;
      82             :     SvXMLTokenMap*      pStyleElemTokenMap;
      83             :     SvXMLTokenMap*      pStyleAttrTokenMap;
      84             :     SvXMLTokenMap*      pStyleElemAttrTokenMap;
      85             :     LocaleDataWrapper*  pLocaleData;
      86             :     SvXMLNumFmtEntryArr aNameEntries;
      87             : 
      88             :     uno::Reference< uno::XComponentContext > m_xContext;
      89             : 
      90             : public:
      91             :     SvXMLNumImpData(
      92             :         SvNumberFormatter* pFmt,
      93             :         const uno::Reference<uno::XComponentContext>& rxContext );
      94             :     ~SvXMLNumImpData();
      95             : 
      96        5357 :     SvNumberFormatter*      GetNumberFormatter() const  { return pFormatter; }
      97             :     const SvXMLTokenMap&    GetStylesElemTokenMap();
      98             :     const SvXMLTokenMap&    GetStyleElemTokenMap();
      99             :     const SvXMLTokenMap&    GetStyleAttrTokenMap();
     100             :     const SvXMLTokenMap&    GetStyleElemAttrTokenMap();
     101             :     const LocaleDataWrapper&    GetLocaleData( LanguageType nLang );
     102             :     sal_uInt32              GetKeyForName( const OUString& rName );
     103             :     void                    AddKey( sal_uInt32 nKey, const OUString& rName, bool bRemoveAfterUse );
     104             :     void                    SetUsed( sal_uInt32 nKey );
     105             :     void                    RemoveVolatileFormats();
     106             : };
     107             : 
     108        5173 : struct SvXMLNumberInfo
     109             : {
     110             :     sal_Int32   nDecimals;
     111             :     sal_Int32   nInteger;
     112             :     sal_Int32   nExpDigits;
     113             :     sal_Int32   nExpInterval;
     114             :     sal_Int32   nNumerDigits;
     115             :     sal_Int32   nDenomDigits;
     116             :     sal_Int32   nFracDenominator;
     117             :     sal_Int32   nMinDecimalDigits;
     118             :     bool        bGrouping;
     119             :     bool        bDecReplace;
     120             :     bool        bExpSign;
     121             :     double      fDisplayFactor;
     122             :     SvXMLEmbeddedElementArr aEmbeddedElements;
     123             : 
     124        5173 :     SvXMLNumberInfo()
     125        5173 :     {
     126             :         nDecimals = nInteger = nExpDigits = nExpInterval = nNumerDigits = nDenomDigits =
     127        5173 :             nFracDenominator = nMinDecimalDigits = -1;
     128        5173 :         bGrouping = bDecReplace = false;
     129        5173 :         bExpSign = true;
     130        5173 :         fDisplayFactor = 1.0;
     131        5173 :     }
     132             : };
     133             : 
     134             : class SvXMLNumFmtElementContext : public SvXMLImportContext
     135             : {
     136             :     SvXMLNumFormatContext&  rParent;
     137             :     sal_uInt16              nType;
     138             :     OUStringBuffer          aContent;
     139             :     SvXMLNumberInfo         aNumInfo;
     140             :     LanguageType            nElementLang;
     141             :     bool                    bLong;
     142             :     bool                    bTextual;
     143             :     OUString                sCalendar;
     144             : 
     145             : public:
     146             :                 SvXMLNumFmtElementContext( SvXMLImport& rImport, sal_uInt16 nPrfx,
     147             :                                     const OUString& rLName,
     148             :                                     SvXMLNumFormatContext& rParentContext, sal_uInt16 nNewType,
     149             :                                     const ::com::sun::star::uno::Reference<
     150             :                                         ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
     151             :     virtual     ~SvXMLNumFmtElementContext();
     152             : 
     153             :     virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
     154             :                                     const OUString& rLocalName,
     155             :                                     const ::com::sun::star::uno::Reference<
     156             :                                           ::com::sun::star::xml::sax::XAttributeList>& xAttrList ) SAL_OVERRIDE;
     157             :     virtual void Characters( const OUString& rChars ) SAL_OVERRIDE;
     158             :     virtual void EndElement() SAL_OVERRIDE;
     159             : 
     160             :     void    AddEmbeddedElement( sal_Int32 nFormatPos, const OUString& rContent );
     161             : };
     162             : 
     163             : class SvXMLNumFmtEmbeddedTextContext : public SvXMLImportContext
     164             : {
     165             :     SvXMLNumFmtElementContext&  rParent;
     166             :     OUStringBuffer         aContent;
     167             :     sal_Int32                   nTextPosition;
     168             : 
     169             : public:
     170             :                 SvXMLNumFmtEmbeddedTextContext( SvXMLImport& rImport, sal_uInt16 nPrfx,
     171             :                                     const OUString& rLName,
     172             :                                     SvXMLNumFmtElementContext& rParentContext,
     173             :                                     const ::com::sun::star::uno::Reference<
     174             :                                         ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
     175             :     virtual     ~SvXMLNumFmtEmbeddedTextContext();
     176             : 
     177             :     virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
     178             :                                     const OUString& rLocalName,
     179             :                                     const ::com::sun::star::uno::Reference<
     180             :                                           ::com::sun::star::xml::sax::XAttributeList>& xAttrList ) SAL_OVERRIDE;
     181             :     virtual void Characters( const OUString& rChars ) SAL_OVERRIDE;
     182             :     virtual void EndElement() SAL_OVERRIDE;
     183             : };
     184             : 
     185             : class SvXMLNumFmtMapContext : public SvXMLImportContext
     186             : {
     187             :     SvXMLNumFormatContext&  rParent;
     188             :     OUString           sCondition;
     189             :     OUString           sName;
     190             : 
     191             : public:
     192             :                 SvXMLNumFmtMapContext( SvXMLImport& rImport, sal_uInt16 nPrfx,
     193             :                                     const OUString& rLName,
     194             :                                     SvXMLNumFormatContext& rParentContext,
     195             :                                     const ::com::sun::star::uno::Reference<
     196             :                                         ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
     197             :     virtual     ~SvXMLNumFmtMapContext();
     198             : 
     199             :     virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
     200             :                                     const OUString& rLocalName,
     201             :                                     const ::com::sun::star::uno::Reference<
     202             :                                           ::com::sun::star::xml::sax::XAttributeList>& xAttrList ) SAL_OVERRIDE;
     203             :     virtual void Characters( const OUString& rChars ) SAL_OVERRIDE;
     204             :     virtual void EndElement() SAL_OVERRIDE;
     205             : };
     206             : 
     207             : class SvXMLNumFmtPropContext : public SvXMLImportContext
     208             : {
     209             :     SvXMLNumFormatContext&  rParent;
     210             :     sal_Int32               m_nColor;
     211             :     bool                    bColSet;
     212             : 
     213             : public:
     214             :                 SvXMLNumFmtPropContext( SvXMLImport& rImport, sal_uInt16 nPrfx,
     215             :                                     const OUString& rLName,
     216             :                                     SvXMLNumFormatContext& rParentContext,
     217             :                                     const ::com::sun::star::uno::Reference<
     218             :                                         ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
     219             :     virtual     ~SvXMLNumFmtPropContext();
     220             : 
     221             :     virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
     222             :                                     const OUString& rLocalName,
     223             :                                     const ::com::sun::star::uno::Reference<
     224             :                                           ::com::sun::star::xml::sax::XAttributeList>& xAttrList ) SAL_OVERRIDE;
     225             :     virtual void Characters( const OUString& rChars ) SAL_OVERRIDE;
     226             :     virtual void EndElement() SAL_OVERRIDE;
     227             : };
     228             : 
     229             : enum SvXMLStyleTokens
     230             : {
     231             :     XML_TOK_STYLE_TEXT,
     232             :     XML_TOK_STYLE_FILL_CHARACTER,
     233             :     XML_TOK_STYLE_NUMBER,
     234             :     XML_TOK_STYLE_SCIENTIFIC_NUMBER,
     235             :     XML_TOK_STYLE_FRACTION,
     236             :     XML_TOK_STYLE_CURRENCY_SYMBOL,
     237             :     XML_TOK_STYLE_DAY,
     238             :     XML_TOK_STYLE_MONTH,
     239             :     XML_TOK_STYLE_YEAR,
     240             :     XML_TOK_STYLE_ERA,
     241             :     XML_TOK_STYLE_DAY_OF_WEEK,
     242             :     XML_TOK_STYLE_WEEK_OF_YEAR,
     243             :     XML_TOK_STYLE_QUARTER,
     244             :     XML_TOK_STYLE_HOURS,
     245             :     XML_TOK_STYLE_AM_PM,
     246             :     XML_TOK_STYLE_MINUTES,
     247             :     XML_TOK_STYLE_SECONDS,
     248             :     XML_TOK_STYLE_BOOLEAN,
     249             :     XML_TOK_STYLE_TEXT_CONTENT,
     250             :     XML_TOK_STYLE_PROPERTIES,
     251             :     XML_TOK_STYLE_MAP
     252             : };
     253             : 
     254             : enum SvXMLStyleAttrTokens
     255             : {
     256             :     XML_TOK_STYLE_ATTR_NAME,
     257             :     XML_TOK_STYLE_ATTR_RFC_LANGUAGE_TAG,
     258             :     XML_TOK_STYLE_ATTR_LANGUAGE,
     259             :     XML_TOK_STYLE_ATTR_SCRIPT,
     260             :     XML_TOK_STYLE_ATTR_COUNTRY,
     261             :     XML_TOK_STYLE_ATTR_TITLE,
     262             :     XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER,
     263             :     XML_TOK_STYLE_ATTR_FORMAT_SOURCE,
     264             :     XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW,
     265             :     XML_TOK_STYLE_ATTR_VOLATILE,
     266             :     XML_TOK_STYLE_ATTR_TRANSL_FORMAT,
     267             :     XML_TOK_STYLE_ATTR_TRANSL_RFC_LANGUAGE_TAG,
     268             :     XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE,
     269             :     XML_TOK_STYLE_ATTR_TRANSL_SCRIPT,
     270             :     XML_TOK_STYLE_ATTR_TRANSL_COUNTRY,
     271             :     XML_TOK_STYLE_ATTR_TRANSL_STYLE
     272             : };
     273             : 
     274             : enum SvXMLStyleElemAttrTokens
     275             : {
     276             :     XML_TOK_ELEM_ATTR_DECIMAL_PLACES,
     277             :     XML_TOK_ELEM_ATTR_MIN_DECIMAL_DIGITS,
     278             :     XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS,
     279             :     XML_TOK_ELEM_ATTR_GROUPING,
     280             :     XML_TOK_ELEM_ATTR_DISPLAY_FACTOR,
     281             :     XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT,
     282             :     XML_TOK_ELEM_ATTR_DENOMINATOR_VALUE,
     283             :     XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS,
     284             :     XML_TOK_ELEM_ATTR_EXPONENT_INTERVAL,
     285             :     XML_TOK_ELEM_ATTR_EXPONENT_SIGN,
     286             :     XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS,
     287             :     XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS,
     288             :     XML_TOK_ELEM_ATTR_RFC_LANGUAGE_TAG,
     289             :     XML_TOK_ELEM_ATTR_LANGUAGE,
     290             :     XML_TOK_ELEM_ATTR_SCRIPT,
     291             :     XML_TOK_ELEM_ATTR_COUNTRY,
     292             :     XML_TOK_ELEM_ATTR_STYLE,
     293             :     XML_TOK_ELEM_ATTR_TEXTUAL,
     294             :     XML_TOK_ELEM_ATTR_CALENDAR
     295             : };
     296             : 
     297             : 
     298             : //  standard colors
     299             : 
     300             : 
     301             : #define XML_NUMF_COLORCOUNT     10
     302             : 
     303             : static const ColorData aNumFmtStdColors[XML_NUMF_COLORCOUNT] =
     304             : {
     305             :     COL_BLACK,
     306             :     COL_LIGHTBLUE,
     307             :     COL_LIGHTGREEN,
     308             :     COL_LIGHTCYAN,
     309             :     COL_LIGHTRED,
     310             :     COL_LIGHTMAGENTA,
     311             :     COL_BROWN,
     312             :     COL_GRAY,
     313             :     COL_YELLOW,
     314             :     COL_WHITE
     315             : };
     316             : 
     317             : 
     318             : //  token maps
     319             : 
     320             : 
     321             : // maps for SvXMLUnitConverter::convertEnum
     322             : 
     323             : static const SvXMLEnumMapEntry aStyleValueMap[] =
     324             : {
     325             :     { XML_SHORT,            sal_uInt16(false) },
     326             :     { XML_LONG,             sal_uInt16(true) },
     327             :     { XML_TOKEN_INVALID,    0 }
     328             : };
     329             : 
     330             : static const SvXMLEnumMapEntry aFormatSourceMap[] =
     331             : {
     332             :     { XML_FIXED,            sal_uInt16(false) },
     333             :     { XML_LANGUAGE,         sal_uInt16(true) },
     334             :     { XML_TOKEN_INVALID,    0 }
     335             : };
     336             : 
     337             : struct SvXMLDefaultDateFormat
     338             : {
     339             :     NfIndexTableOffset          eFormat;
     340             :     SvXMLDateElementAttributes  eDOW;
     341             :     SvXMLDateElementAttributes  eDay;
     342             :     SvXMLDateElementAttributes  eMonth;
     343             :     SvXMLDateElementAttributes  eYear;
     344             :     SvXMLDateElementAttributes  eHours;
     345             :     SvXMLDateElementAttributes  eMins;
     346             :     SvXMLDateElementAttributes  eSecs;
     347             :     bool                        bSystem;
     348             : };
     349             : 
     350             : static const SvXMLDefaultDateFormat aDefaultDateFormats[] =
     351             : {
     352             :     // format                           day-of-week     day             month               year            hours           minutes         seconds         format-source
     353             : 
     354             :     { NF_DATE_SYSTEM_SHORT,             XML_DEA_NONE,   XML_DEA_ANY,    XML_DEA_ANY,        XML_DEA_ANY,    XML_DEA_NONE,   XML_DEA_NONE,   XML_DEA_NONE,   true },
     355             :     { NF_DATE_SYSTEM_LONG,              XML_DEA_ANY,    XML_DEA_ANY,    XML_DEA_ANY,        XML_DEA_ANY,    XML_DEA_NONE,   XML_DEA_NONE,   XML_DEA_NONE,   true },
     356             :     { NF_DATE_SYS_MMYY,                 XML_DEA_NONE,   XML_DEA_NONE,   XML_DEA_LONG,       XML_DEA_SHORT,  XML_DEA_NONE,   XML_DEA_NONE,   XML_DEA_NONE,   false },
     357             :     { NF_DATE_SYS_DDMMM,                XML_DEA_NONE,   XML_DEA_LONG,   XML_DEA_TEXTSHORT,  XML_DEA_NONE,   XML_DEA_NONE,   XML_DEA_NONE,   XML_DEA_NONE,   false },
     358             :     { NF_DATE_SYS_DDMMYYYY,             XML_DEA_NONE,   XML_DEA_LONG,   XML_DEA_LONG,       XML_DEA_LONG,   XML_DEA_NONE,   XML_DEA_NONE,   XML_DEA_NONE,   false },
     359             :     { NF_DATE_SYS_DDMMYY,               XML_DEA_NONE,   XML_DEA_LONG,   XML_DEA_LONG,       XML_DEA_SHORT,  XML_DEA_NONE,   XML_DEA_NONE,   XML_DEA_NONE,   false },
     360             :     { NF_DATE_SYS_DMMMYY,               XML_DEA_NONE,   XML_DEA_SHORT,  XML_DEA_TEXTSHORT,  XML_DEA_SHORT,  XML_DEA_NONE,   XML_DEA_NONE,   XML_DEA_NONE,   false },
     361             :     { NF_DATE_SYS_DMMMYYYY,             XML_DEA_NONE,   XML_DEA_SHORT,  XML_DEA_TEXTSHORT,  XML_DEA_LONG,   XML_DEA_NONE,   XML_DEA_NONE,   XML_DEA_NONE,   false },
     362             :     { NF_DATE_SYS_DMMMMYYYY,            XML_DEA_NONE,   XML_DEA_SHORT,  XML_DEA_TEXTLONG,   XML_DEA_LONG,   XML_DEA_NONE,   XML_DEA_NONE,   XML_DEA_NONE,   false },
     363             :     { NF_DATE_SYS_NNDMMMYY,             XML_DEA_SHORT,  XML_DEA_SHORT,  XML_DEA_TEXTSHORT,  XML_DEA_SHORT,  XML_DEA_NONE,   XML_DEA_NONE,   XML_DEA_NONE,   false },
     364             :     { NF_DATE_SYS_NNDMMMMYYYY,          XML_DEA_SHORT,  XML_DEA_SHORT,  XML_DEA_TEXTLONG,   XML_DEA_LONG,   XML_DEA_NONE,   XML_DEA_NONE,   XML_DEA_NONE,   false },
     365             :     { NF_DATE_SYS_NNNNDMMMMYYYY,        XML_DEA_LONG,   XML_DEA_SHORT,  XML_DEA_TEXTLONG,   XML_DEA_LONG,   XML_DEA_NONE,   XML_DEA_NONE,   XML_DEA_NONE,   false },
     366             :     { NF_DATETIME_SYSTEM_SHORT_HHMM,    XML_DEA_NONE,   XML_DEA_ANY,    XML_DEA_ANY,        XML_DEA_ANY,    XML_DEA_ANY,    XML_DEA_ANY,    XML_DEA_NONE,   true },
     367             :     { NF_DATETIME_SYS_DDMMYYYY_HHMMSS,  XML_DEA_NONE,   XML_DEA_ANY,    XML_DEA_ANY,        XML_DEA_ANY,    XML_DEA_ANY,    XML_DEA_ANY,    XML_DEA_ANY,    false }
     368             : };
     369             : 
     370             : 
     371             : //  SvXMLNumImpData
     372             : 
     373             : 
     374        1289 : SvXMLNumImpData::SvXMLNumImpData(
     375             :     SvNumberFormatter* pFmt,
     376             :     const uno::Reference<uno::XComponentContext>& rxContext )
     377             : :   pFormatter(pFmt),
     378             :     pStylesElemTokenMap(NULL),
     379             :     pStyleElemTokenMap(NULL),
     380             :     pStyleAttrTokenMap(NULL),
     381             :     pStyleElemAttrTokenMap(NULL),
     382             :     pLocaleData(NULL),
     383        1289 :     m_xContext(rxContext)
     384             : {
     385             :     DBG_ASSERT( rxContext.is(), "got no service manager" );
     386        1289 : }
     387             : 
     388        2578 : SvXMLNumImpData::~SvXMLNumImpData()
     389             : {
     390        1289 :     delete pStylesElemTokenMap;
     391        1289 :     delete pStyleElemTokenMap;
     392        1289 :     delete pStyleAttrTokenMap;
     393        1289 :     delete pStyleElemAttrTokenMap;
     394        1289 :     delete pLocaleData;
     395        1289 : }
     396             : 
     397         636 : sal_uInt32 SvXMLNumImpData::GetKeyForName( const OUString& rName )
     398             : {
     399         636 :     sal_uInt16 nCount = aNameEntries.size();
     400       42458 :     for (sal_uInt16 i=0; i<nCount; i++)
     401             :     {
     402       42458 :         const SvXMLNumFmtEntry* pObj = &aNameEntries[i];
     403       42458 :         if ( pObj->aName == rName )
     404         636 :             return pObj->nKey;              // found
     405             :     }
     406           0 :     return NUMBERFORMAT_ENTRY_NOT_FOUND;
     407             : }
     408             : 
     409        1942 : void SvXMLNumImpData::AddKey( sal_uInt32 nKey, const OUString& rName, bool bRemoveAfterUse )
     410             : {
     411        1942 :     if ( bRemoveAfterUse )
     412             :     {
     413             :         //  if there is already an entry for this key without the bRemoveAfterUse flag,
     414             :         //  clear the flag for this entry, too
     415             : 
     416         636 :         sal_uInt16 nCount = aNameEntries.size();
     417       40089 :         for (sal_uInt16 i=0; i<nCount; i++)
     418             :         {
     419       39482 :             SvXMLNumFmtEntry* pObj = &aNameEntries[i];
     420       39482 :             if ( pObj->nKey == nKey && !pObj->bRemoveAfterUse )
     421             :             {
     422          29 :                 bRemoveAfterUse = false;        // clear flag for new entry
     423          29 :                 break;
     424             :             }
     425             :         }
     426             :     }
     427             :     else
     428             :     {
     429             :         //  call SetUsed to clear the bRemoveAfterUse flag for other entries for this key
     430        1306 :         SetUsed( nKey );
     431             :     }
     432             : 
     433        1942 :     SvXMLNumFmtEntry* pObj = new SvXMLNumFmtEntry( rName, nKey, bRemoveAfterUse );
     434        1942 :     aNameEntries.push_back( pObj );
     435        1942 : }
     436             : 
     437        1306 : void SvXMLNumImpData::SetUsed( sal_uInt32 nKey )
     438             : {
     439        1306 :     sal_uInt16 nCount = aNameEntries.size();
     440       50033 :     for (sal_uInt16 i=0; i<nCount; i++)
     441             :     {
     442       48727 :         SvXMLNumFmtEntry* pObj = &aNameEntries[i];
     443       48727 :         if ( pObj->nKey == nKey )
     444             :         {
     445          12 :             pObj->bRemoveAfterUse = false;      // used -> don't remove
     446             : 
     447             :             //  continue searching - there may be several entries for the same key
     448             :             //  (with different names), the format must not be deleted if any one of
     449             :             //  them is used
     450             :         }
     451             :     }
     452        1306 : }
     453             : 
     454        1289 : void SvXMLNumImpData::RemoveVolatileFormats()
     455             : {
     456             :     //  remove temporary (volatile) formats from NumberFormatter
     457             :     //  called at the end of each import (styles and content), so volatile formats
     458             :     //  from styles can't be used in content
     459             : 
     460        1289 :     if ( !pFormatter )
     461        1289 :         return;
     462             : 
     463        1289 :     sal_uInt16 nCount = aNameEntries.size();
     464        3231 :     for (sal_uInt16 i=0; i<nCount; i++)
     465             :     {
     466        1942 :         const SvXMLNumFmtEntry* pObj = &aNameEntries[i];
     467        1942 :         if ( pObj->bRemoveAfterUse )
     468             :         {
     469         606 :             const SvNumberformat* pFormat = pFormatter->GetEntry(pObj->nKey);
     470         606 :             if (pFormat && (pFormat->GetType() & css::util::NumberFormat::DEFINED))
     471         492 :                 pFormatter->DeleteEntry( pObj->nKey );
     472             :         }
     473             :     }
     474             : }
     475             : 
     476       24769 : const SvXMLTokenMap& SvXMLNumImpData::GetStylesElemTokenMap()
     477             : {
     478       24769 :     if( !pStylesElemTokenMap )
     479             :     {
     480             :         static const SvXMLTokenMapEntry aStylesElemMap[] =
     481             :         {
     482             :             //  style elements
     483             :             { XML_NAMESPACE_NUMBER, XML_NUMBER_STYLE,      XML_TOK_STYLES_NUMBER_STYLE      },
     484             :             { XML_NAMESPACE_NUMBER, XML_CURRENCY_STYLE,    XML_TOK_STYLES_CURRENCY_STYLE    },
     485             :             { XML_NAMESPACE_NUMBER, XML_PERCENTAGE_STYLE,  XML_TOK_STYLES_PERCENTAGE_STYLE  },
     486             :             { XML_NAMESPACE_NUMBER, XML_DATE_STYLE,        XML_TOK_STYLES_DATE_STYLE        },
     487             :             { XML_NAMESPACE_NUMBER, XML_TIME_STYLE,        XML_TOK_STYLES_TIME_STYLE        },
     488             :             { XML_NAMESPACE_NUMBER, XML_BOOLEAN_STYLE,     XML_TOK_STYLES_BOOLEAN_STYLE     },
     489             :             { XML_NAMESPACE_NUMBER, XML_TEXT_STYLE,        XML_TOK_STYLES_TEXT_STYLE        },
     490             :             XML_TOKEN_MAP_END
     491             :         };
     492             : 
     493        1260 :         pStylesElemTokenMap = new SvXMLTokenMap( aStylesElemMap );
     494             :     }
     495       24769 :     return *pStylesElemTokenMap;
     496             : }
     497             : 
     498        6114 : const SvXMLTokenMap& SvXMLNumImpData::GetStyleElemTokenMap()
     499             : {
     500        6114 :     if( !pStyleElemTokenMap )
     501             :     {
     502             :         static const SvXMLTokenMapEntry aStyleElemMap[] =
     503             :         {
     504             :             //  elements in a style
     505             :             { XML_NAMESPACE_LO_EXT, XML_TEXT,               XML_TOK_STYLE_TEXT              },
     506             :             { XML_NAMESPACE_NUMBER, XML_TEXT,               XML_TOK_STYLE_TEXT              },
     507             :             { XML_NAMESPACE_LO_EXT, XML_FILL_CHARACTER,     XML_TOK_STYLE_FILL_CHARACTER    },
     508             :             { XML_NAMESPACE_NUMBER, XML_FILL_CHARACTER,     XML_TOK_STYLE_FILL_CHARACTER    },
     509             :             { XML_NAMESPACE_NUMBER, XML_NUMBER,             XML_TOK_STYLE_NUMBER            },
     510             :             { XML_NAMESPACE_NUMBER, XML_SCIENTIFIC_NUMBER,  XML_TOK_STYLE_SCIENTIFIC_NUMBER },
     511             :             { XML_NAMESPACE_NUMBER, XML_FRACTION,           XML_TOK_STYLE_FRACTION          },
     512             :             { XML_NAMESPACE_NUMBER, XML_CURRENCY_SYMBOL,    XML_TOK_STYLE_CURRENCY_SYMBOL   },
     513             :             { XML_NAMESPACE_NUMBER, XML_DAY,                XML_TOK_STYLE_DAY               },
     514             :             { XML_NAMESPACE_NUMBER, XML_MONTH,              XML_TOK_STYLE_MONTH             },
     515             :             { XML_NAMESPACE_NUMBER, XML_YEAR,               XML_TOK_STYLE_YEAR              },
     516             :             { XML_NAMESPACE_NUMBER, XML_ERA,                XML_TOK_STYLE_ERA               },
     517             :             { XML_NAMESPACE_NUMBER, XML_DAY_OF_WEEK,        XML_TOK_STYLE_DAY_OF_WEEK       },
     518             :             { XML_NAMESPACE_NUMBER, XML_WEEK_OF_YEAR,       XML_TOK_STYLE_WEEK_OF_YEAR      },
     519             :             { XML_NAMESPACE_NUMBER, XML_QUARTER,            XML_TOK_STYLE_QUARTER           },
     520             :             { XML_NAMESPACE_NUMBER, XML_HOURS,              XML_TOK_STYLE_HOURS             },
     521             :             { XML_NAMESPACE_NUMBER, XML_AM_PM,              XML_TOK_STYLE_AM_PM             },
     522             :             { XML_NAMESPACE_NUMBER, XML_MINUTES,            XML_TOK_STYLE_MINUTES           },
     523             :             { XML_NAMESPACE_NUMBER, XML_SECONDS,            XML_TOK_STYLE_SECONDS           },
     524             :             { XML_NAMESPACE_NUMBER, XML_BOOLEAN,            XML_TOK_STYLE_BOOLEAN           },
     525             :             { XML_NAMESPACE_NUMBER, XML_TEXT_CONTENT,       XML_TOK_STYLE_TEXT_CONTENT      },
     526             :             { XML_NAMESPACE_STYLE,  XML_TEXT_PROPERTIES,    XML_TOK_STYLE_PROPERTIES        },
     527             :             { XML_NAMESPACE_STYLE,  XML_MAP,                XML_TOK_STYLE_MAP               },
     528             :             XML_TOKEN_MAP_END
     529             :         };
     530             : 
     531         314 :         pStyleElemTokenMap = new SvXMLTokenMap( aStyleElemMap );
     532             :     }
     533        6114 :     return *pStyleElemTokenMap;
     534             : }
     535             : 
     536        3579 : const SvXMLTokenMap& SvXMLNumImpData::GetStyleAttrTokenMap()
     537             : {
     538        3579 :     if( !pStyleAttrTokenMap )
     539             :     {
     540             :         static const SvXMLTokenMapEntry aStyleAttrMap[] =
     541             :         {
     542             :             //  attributes for a style
     543             :             { XML_NAMESPACE_STYLE,  XML_NAME,                  XML_TOK_STYLE_ATTR_NAME                  },
     544             :             { XML_NAMESPACE_NUMBER, XML_RFC_LANGUAGE_TAG,      XML_TOK_STYLE_ATTR_RFC_LANGUAGE_TAG,     },
     545             :             { XML_NAMESPACE_NUMBER, XML_LANGUAGE,              XML_TOK_STYLE_ATTR_LANGUAGE              },
     546             :             { XML_NAMESPACE_NUMBER, XML_SCRIPT,                XML_TOK_STYLE_ATTR_SCRIPT                },
     547             :             { XML_NAMESPACE_NUMBER, XML_COUNTRY,               XML_TOK_STYLE_ATTR_COUNTRY               },
     548             :             { XML_NAMESPACE_NUMBER, XML_TITLE,                 XML_TOK_STYLE_ATTR_TITLE                 },
     549             :             { XML_NAMESPACE_NUMBER, XML_AUTOMATIC_ORDER,       XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER       },
     550             :             { XML_NAMESPACE_NUMBER, XML_FORMAT_SOURCE,         XML_TOK_STYLE_ATTR_FORMAT_SOURCE         },
     551             :             { XML_NAMESPACE_NUMBER, XML_TRUNCATE_ON_OVERFLOW,  XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW  },
     552             :             { XML_NAMESPACE_STYLE,  XML_VOLATILE,              XML_TOK_STYLE_ATTR_VOLATILE              },
     553             :             { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_FORMAT,     XML_TOK_STYLE_ATTR_TRANSL_FORMAT    },
     554             :             // not defined in ODF { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_RFC_LANGUAGE_TAG, XML_TOK_STYLE_ATTR_TRANSL_RFC_LANGUAGE_TAG   },
     555             :             { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_LANGUAGE,   XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE  },
     556             :             // not defined in ODF { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_SCRIPT,     XML_TOK_STYLE_ATTR_TRANSL_SCRIPT    },
     557             :             { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_COUNTRY,    XML_TOK_STYLE_ATTR_TRANSL_COUNTRY   },
     558             :             { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_STYLE,      XML_TOK_STYLE_ATTR_TRANSL_STYLE     },
     559             :             XML_TOKEN_MAP_END
     560             :         };
     561             : 
     562         314 :         pStyleAttrTokenMap = new SvXMLTokenMap( aStyleAttrMap );
     563             :     }
     564        3579 :     return *pStyleAttrTokenMap;
     565             : }
     566             : 
     567        5338 : const SvXMLTokenMap& SvXMLNumImpData::GetStyleElemAttrTokenMap()
     568             : {
     569        5338 :     if( !pStyleElemAttrTokenMap )
     570             :     {
     571             :         static const SvXMLTokenMapEntry aStyleElemAttrMap[] =
     572             :         {
     573             :             //  attributes for an element within a style
     574             :             { XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES,          XML_TOK_ELEM_ATTR_DECIMAL_PLACES       },
     575             :             { XML_NAMESPACE_LO_EXT, XML_MIN_DECIMAL_DIGITS,      XML_TOK_ELEM_ATTR_MIN_DECIMAL_DIGITS   },
     576             :             { XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS,      XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS   },
     577             :             { XML_NAMESPACE_NUMBER, XML_GROUPING,                XML_TOK_ELEM_ATTR_GROUPING             },
     578             :             { XML_NAMESPACE_NUMBER, XML_DISPLAY_FACTOR,          XML_TOK_ELEM_ATTR_DISPLAY_FACTOR       },
     579             :             { XML_NAMESPACE_NUMBER, XML_DECIMAL_REPLACEMENT,     XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT  },
     580             :             { XML_NAMESPACE_NUMBER, XML_DENOMINATOR_VALUE,       XML_TOK_ELEM_ATTR_DENOMINATOR_VALUE  },
     581             :             { XML_NAMESPACE_NUMBER, XML_MIN_EXPONENT_DIGITS,     XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS  },
     582             :             { XML_NAMESPACE_LO_EXT, XML_EXPONENT_INTERVAL,       XML_TOK_ELEM_ATTR_EXPONENT_INTERVAL    },
     583             :             { XML_NAMESPACE_NUMBER, XML_EXPONENT_INTERVAL,       XML_TOK_ELEM_ATTR_EXPONENT_INTERVAL    },
     584             :             { XML_NAMESPACE_LO_EXT, XML_EXPONENT_SIGN,           XML_TOK_ELEM_ATTR_EXPONENT_SIGN        },
     585             :             { XML_NAMESPACE_NUMBER, XML_MIN_NUMERATOR_DIGITS,    XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS },
     586             :             { XML_NAMESPACE_NUMBER, XML_MIN_DENOMINATOR_DIGITS,  XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS },
     587             :             { XML_NAMESPACE_NUMBER, XML_RFC_LANGUAGE_TAG,        XML_TOK_ELEM_ATTR_RFC_LANGUAGE_TAG     },
     588             :             { XML_NAMESPACE_NUMBER, XML_LANGUAGE,                XML_TOK_ELEM_ATTR_LANGUAGE             },
     589             :             { XML_NAMESPACE_NUMBER, XML_SCRIPT,                  XML_TOK_ELEM_ATTR_SCRIPT               },
     590             :             { XML_NAMESPACE_NUMBER, XML_COUNTRY,                 XML_TOK_ELEM_ATTR_COUNTRY              },
     591             :             { XML_NAMESPACE_NUMBER, XML_STYLE,                   XML_TOK_ELEM_ATTR_STYLE                },
     592             :             { XML_NAMESPACE_NUMBER, XML_TEXTUAL,                 XML_TOK_ELEM_ATTR_TEXTUAL              },
     593             :             { XML_NAMESPACE_NUMBER, XML_CALENDAR,                XML_TOK_ELEM_ATTR_CALENDAR             },
     594             :             XML_TOKEN_MAP_END
     595             :         };
     596             : 
     597         312 :         pStyleElemAttrTokenMap = new SvXMLTokenMap( aStyleElemAttrMap );
     598             :     }
     599        5338 :     return *pStyleElemAttrTokenMap;
     600             : }
     601             : 
     602        1187 : const LocaleDataWrapper& SvXMLNumImpData::GetLocaleData( LanguageType nLang )
     603             : {
     604        1187 :     if ( !pLocaleData )
     605             :         pLocaleData = new LocaleDataWrapper(
     606             :                pFormatter ? pFormatter->GetComponentContext() : m_xContext,
     607         204 :             LanguageTag( nLang ) );
     608             :     else
     609         983 :         pLocaleData->setLanguageTag( LanguageTag( nLang ) );
     610        1187 :     return *pLocaleData;
     611             : }
     612             : 
     613             : 
     614             : //  SvXMLNumFmtMapContext
     615             : 
     616             : 
     617         636 : SvXMLNumFmtMapContext::SvXMLNumFmtMapContext( SvXMLImport& rImport,
     618             :                                     sal_uInt16 nPrfx, const OUString& rLName,
     619             :                                     SvXMLNumFormatContext& rParentContext,
     620             :                                     const uno::Reference<xml::sax::XAttributeList>& xAttrList ) :
     621             :     SvXMLImportContext( rImport, nPrfx, rLName ),
     622         636 :     rParent( rParentContext )
     623             : {
     624         636 :     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
     625        1908 :     for( sal_Int16 i=0; i < nAttrCount; i++ )
     626             :     {
     627        1272 :         OUString sAttrName = xAttrList->getNameByIndex( i );
     628        2544 :         OUString sValue = xAttrList->getValueByIndex( i );
     629        2544 :         OUString aLocalName;
     630        1272 :         sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
     631        1272 :         if ( nPrefix == XML_NAMESPACE_STYLE )
     632             :         {
     633        1272 :             if ( IsXMLToken( aLocalName, XML_CONDITION) )
     634         636 :                 sCondition = sValue;
     635         636 :             else if ( IsXMLToken( aLocalName, XML_APPLY_STYLE_NAME) )
     636         636 :                 sName = sValue;
     637             :         }
     638        1272 :     }
     639         636 : }
     640             : 
     641        1272 : SvXMLNumFmtMapContext::~SvXMLNumFmtMapContext()
     642             : {
     643        1272 : }
     644             : 
     645           0 : SvXMLImportContext* SvXMLNumFmtMapContext::CreateChildContext(
     646             :                                     sal_uInt16 nPrfx, const OUString& rLName,
     647             :                                     const uno::Reference<xml::sax::XAttributeList>& )
     648             : {
     649             :     // no elements supported - use default context
     650           0 :     return new SvXMLImportContext( GetImport(), nPrfx, rLName );
     651             : }
     652             : 
     653           0 : void SvXMLNumFmtMapContext::Characters( const OUString& )
     654             : {
     655           0 : }
     656             : 
     657         636 : void SvXMLNumFmtMapContext::EndElement()
     658             : {
     659         636 :     rParent.AddCondition( sCondition, sName );
     660         636 : }
     661             : 
     662             : 
     663             : //  SvXMLNumFmtPropContext
     664             : 
     665             : 
     666         305 : SvXMLNumFmtPropContext::SvXMLNumFmtPropContext( SvXMLImport& rImport,
     667             :                                     sal_uInt16 nPrfx, const OUString& rLName,
     668             :                                     SvXMLNumFormatContext& rParentContext,
     669             :                                     const uno::Reference<xml::sax::XAttributeList>& xAttrList ) :
     670             :     SvXMLImportContext( rImport, nPrfx, rLName ),
     671             :     rParent( rParentContext ),
     672             :     m_nColor( 0 ),
     673         305 :     bColSet( false )
     674             : {
     675         305 :     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
     676         610 :     for( sal_Int16 i=0; i < nAttrCount; i++ )
     677             :     {
     678         305 :         OUString sAttrName = xAttrList->getNameByIndex( i );
     679         610 :         OUString sValue = xAttrList->getValueByIndex( i );
     680         610 :         OUString aLocalName;
     681         305 :         sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
     682         305 :         if ( nPrefix == XML_NAMESPACE_FO && IsXMLToken( aLocalName, XML_COLOR ) )
     683             :         {
     684         305 :             bColSet = ::sax::Converter::convertColor( m_nColor, sValue );
     685             :         }
     686         305 :     }
     687         305 : }
     688             : 
     689         610 : SvXMLNumFmtPropContext::~SvXMLNumFmtPropContext()
     690             : {
     691         610 : }
     692             : 
     693           0 : SvXMLImportContext* SvXMLNumFmtPropContext::CreateChildContext(
     694             :                                     sal_uInt16 nPrfx, const OUString& rLName,
     695             :                                     const uno::Reference<xml::sax::XAttributeList>& )
     696             : {
     697             :     // no elements supported - use default context
     698           0 :     return new SvXMLImportContext( GetImport(), nPrfx, rLName );
     699             : }
     700             : 
     701           0 : void SvXMLNumFmtPropContext::Characters( const OUString& )
     702             : {
     703           0 : }
     704             : 
     705         305 : void SvXMLNumFmtPropContext::EndElement()
     706             : {
     707         305 :     if (bColSet)
     708         305 :         rParent.AddColor( m_nColor );
     709         305 : }
     710             : 
     711             : 
     712             : //  SvXMLNumFmtEmbeddedTextContext
     713             : 
     714             : 
     715           0 : SvXMLNumFmtEmbeddedTextContext::SvXMLNumFmtEmbeddedTextContext( SvXMLImport& rImport,
     716             :                                     sal_uInt16 nPrfx, const OUString& rLName,
     717             :                                     SvXMLNumFmtElementContext& rParentContext,
     718             :                                     const uno::Reference<xml::sax::XAttributeList>& xAttrList ) :
     719             :     SvXMLImportContext( rImport, nPrfx, rLName ),
     720             :     rParent( rParentContext ),
     721           0 :     nTextPosition( 0 )
     722             : {
     723             :     sal_Int32 nAttrVal;
     724             : 
     725           0 :     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
     726           0 :     for( sal_Int16 i=0; i < nAttrCount; i++ )
     727             :     {
     728           0 :         OUString sAttrName = xAttrList->getNameByIndex( i );
     729           0 :         OUString sValue = xAttrList->getValueByIndex( i );
     730           0 :         OUString aLocalName;
     731           0 :         sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
     732           0 :         if ( nPrefix == XML_NAMESPACE_NUMBER && IsXMLToken( aLocalName, XML_POSITION ) )
     733             :         {
     734           0 :             if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
     735           0 :                 nTextPosition = nAttrVal;
     736             :         }
     737           0 :     }
     738           0 : }
     739             : 
     740           0 : SvXMLNumFmtEmbeddedTextContext::~SvXMLNumFmtEmbeddedTextContext()
     741             : {
     742           0 : }
     743             : 
     744           0 : SvXMLImportContext* SvXMLNumFmtEmbeddedTextContext::CreateChildContext(
     745             :                                     sal_uInt16 nPrfx, const OUString& rLName,
     746             :                                     const uno::Reference<xml::sax::XAttributeList>& )
     747             : {
     748             :     // no elements supported - use default context
     749           0 :     return new SvXMLImportContext( GetImport(), nPrfx, rLName );
     750             : }
     751             : 
     752           0 : void SvXMLNumFmtEmbeddedTextContext::Characters( const OUString& rChars )
     753             : {
     754           0 :     aContent.append( rChars );
     755           0 : }
     756             : 
     757           0 : void SvXMLNumFmtEmbeddedTextContext::EndElement()
     758             : {
     759           0 :     rParent.AddEmbeddedElement( nTextPosition, aContent.makeStringAndClear() );
     760           0 : }
     761             : 
     762        1823 : static bool lcl_ValidChar( sal_Unicode cChar, const SvXMLNumFormatContext& rParent )
     763             : {
     764        1823 :     sal_uInt16 nFormatType = rParent.GetType();
     765             : 
     766             :     // Treat space equal to non-breaking space separator.
     767        1823 :     const sal_Unicode cNBSP = 0x00A0;
     768             :     sal_Unicode cTS;
     769        3088 :     if ( ( nFormatType == XML_TOK_STYLES_NUMBER_STYLE ||
     770         712 :            nFormatType == XML_TOK_STYLES_CURRENCY_STYLE ||
     771        2993 :            nFormatType == XML_TOK_STYLES_PERCENTAGE_STYLE ) &&
     772        2306 :             (cChar == (cTS = rParent.GetLocaleData().getNumThousandSep()[0]) ||
     773         453 :              (cChar == ' ' && cTS == cNBSP)) )
     774             :     {
     775             :         //  #i22394# Extra occurrences of thousands separator must be quoted, so they
     776             :         //  aren't mis-interpreted as display-factor.
     777             :         //  This must be limited to the format types that can contain a number element,
     778             :         //  because the same character can be a date separator that should not be quoted
     779             :         //  in date formats.
     780             : 
     781          17 :         return false;   // force quotes
     782             :     }
     783             : 
     784             :     //  see ImpSvNumberformatScan::Next_Symbol
     785        1806 :     if ( cChar == ' ' ||
     786         732 :          cChar == '-' ||
     787         544 :          cChar == '/' ||
     788         520 :          cChar == '.' ||
     789         506 :          cChar == ',' ||
     790         315 :          cChar == ':' ||
     791             :          cChar == '\'' )
     792        1491 :         return true;    // for all format types
     793             : 
     794             :     //  percent sign must be used without quotes for percentage styles only
     795         315 :     if ( nFormatType == XML_TOK_STYLES_PERCENTAGE_STYLE && cChar == '%' )
     796          42 :         return true;
     797             : 
     798             :     //  don't put quotes around single parentheses (often used for negative numbers)
     799         273 :     if ( ( nFormatType == XML_TOK_STYLES_NUMBER_STYLE ||
     800          11 :            nFormatType == XML_TOK_STYLES_CURRENCY_STYLE ||
     801         262 :            nFormatType == XML_TOK_STYLES_PERCENTAGE_STYLE ) &&
     802         157 :          ( cChar == '(' || cChar == ')' ) )
     803         214 :         return true;
     804             : 
     805          59 :     return false;
     806             : }
     807             : 
     808        2031 : static void lcl_EnquoteIfNecessary( OUStringBuffer& rContent, const SvXMLNumFormatContext& rParent )
     809             : {
     810        2031 :     bool bQuote = true;
     811        2031 :     sal_Int32 nLength = rContent.getLength();
     812             : 
     813        3675 :     if ( ( nLength == 1 &&
     814        4100 :             lcl_ValidChar( rContent[0], rParent ) ) ||
     815         179 :          ( nLength == 2 &&
     816         328 :              lcl_ValidChar( rContent[0], rParent ) &&
     817         149 :              rContent[1] == ' ' ) )
     818             :     {
     819             :         //  don't quote single separator characters like space or percent,
     820             :         //  or separator characters followed by space (used in date formats)
     821        1636 :         bQuote = false;
     822             :     }
     823         395 :     else if ( rParent.GetType() == XML_TOK_STYLES_PERCENTAGE_STYLE && nLength > 1 )
     824             :     {
     825             :         //  the percent character in percentage styles must be left out of quoting
     826             :         //  (one occurrence is enough even if there are several percent characters in the string)
     827             : 
     828           0 :         OUString aString( rContent.getStr() );
     829           0 :         sal_Int32 nPos = aString.indexOf( '%' );
     830           0 :         if ( nPos >= 0 )
     831             :         {
     832           0 :             if ( nPos + 1 < nLength )
     833             :             {
     834           0 :                 if ( nPos + 2 == nLength && lcl_ValidChar( rContent[nPos + 1], rParent ) )
     835             :                 {
     836             :                     //  single character that doesn't need quoting
     837             :                 }
     838             :                 else
     839             :                 {
     840             :                     //  quote text behind percent character
     841           0 :                     rContent.insert( nPos + 1, '"' );
     842           0 :                     rContent.append( '"' );
     843             :                 }
     844             :             }
     845           0 :             if ( nPos > 0 )
     846             :             {
     847           0 :                 if ( nPos == 1 && lcl_ValidChar( rContent[0], rParent ) )
     848             :                 {
     849             :                     //  single character that doesn't need quoting
     850             :                 }
     851             :                 else
     852             :                 {
     853             :                     //  quote text before percent character
     854           0 :                     rContent.insert( nPos, '"' );
     855           0 :                     rContent.insert( 0, '"' );
     856             :                 }
     857             :             }
     858           0 :             bQuote = false;
     859           0 :         }
     860             :         // else: normal quoting (below)
     861             :     }
     862             : 
     863        2031 :     if ( bQuote )
     864             :     {
     865             :         // #i55469# quotes in the string itself have to be escaped
     866         395 :         bool bEscape = ( rContent.indexOf( '"' ) >= 0 );
     867         395 :         if ( bEscape )
     868             :         {
     869             :             // A quote is turned into "\"" - a quote to end quoted text, an escaped quote,
     870             :             // and a quote to resume quoting.
     871          44 :             OUString aInsert(  "\"\\\""  );
     872             : 
     873          44 :             sal_Int32 nPos = 0;
     874         244 :             while ( nPos < rContent.getLength() )
     875             :             {
     876         156 :                 if ( rContent[nPos] == '"' )
     877             :                 {
     878          44 :                     rContent.insert( nPos, aInsert );
     879          44 :                     nPos += aInsert.getLength();
     880             :                 }
     881         156 :                 ++nPos;
     882          44 :             }
     883             :         }
     884             : 
     885             :         //  quote string literals
     886         395 :         rContent.insert( 0, '"' );
     887         395 :         rContent.append( '"' );
     888             : 
     889             :         // remove redundant double quotes at start or end
     890         395 :         if ( bEscape )
     891             :         {
     892         132 :             if ( rContent.getLength() > 2 &&
     893          88 :                  rContent[0] == '"' &&
     894          44 :                  rContent[1] == '"' )
     895             :             {
     896           0 :                 rContent.remove(0, 2);
     897             :             }
     898             : 
     899          44 :             sal_Int32 nLen = rContent.getLength();
     900          88 :             if ( nLen > 2 &&
     901          88 :                  rContent[nLen - 1] == '"' &&
     902          44 :                  rContent[nLen - 2] == '"' )
     903             :             {
     904          44 :                 rContent.truncate(nLen - 2);
     905             :             }
     906             :         }
     907             :     }
     908        2031 : }
     909             : 
     910             : 
     911             : //  SvXMLNumFmtElementContext
     912             : 
     913             : 
     914             : const sal_Int32 MAX_SECOND_DIGITS = 20; // fdo#58539 & gnome#627420: limit number of digits during import
     915             : 
     916        5173 : SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport,
     917             :                                     sal_uInt16 nPrfx, const OUString& rLName,
     918             :                                     SvXMLNumFormatContext& rParentContext, sal_uInt16 nNewType,
     919             :                                     const uno::Reference<xml::sax::XAttributeList>& xAttrList ) :
     920             :     SvXMLImportContext( rImport, nPrfx, rLName ),
     921             :     rParent( rParentContext ),
     922             :     nType( nNewType ),
     923             :     nElementLang( LANGUAGE_SYSTEM ),
     924             :     bLong( false ),
     925        5173 :     bTextual( false )
     926             : {
     927        5173 :     LanguageTagODF aLanguageTagODF;
     928             :     sal_Int32 nAttrVal;
     929        5173 :     bool bAttrBool(false);
     930        5173 :     bool bVarDecimals = false;
     931             :     sal_uInt16 nAttrEnum;
     932             :     double fAttrDouble;
     933             : 
     934        5173 :     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
     935       10511 :     for( sal_Int16 i=0; i < nAttrCount; i++ )
     936             :     {
     937        5338 :         OUString sAttrName = xAttrList->getNameByIndex( i );
     938       10676 :         OUString sValue = xAttrList->getValueByIndex( i );
     939       10676 :         OUString aLocalName;
     940        5338 :         sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
     941             : 
     942        5338 :         const SvXMLTokenMap& rTokenMap = rParent.GetData()->GetStyleElemAttrTokenMap();
     943        5338 :         sal_uInt16 nToken = rTokenMap.Get( nPrefix, aLocalName );
     944             : 
     945        5338 :         switch (nToken)
     946             :         {
     947             :             case XML_TOK_ELEM_ATTR_DECIMAL_PLACES:
     948        1218 :                 if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
     949        1218 :                     aNumInfo.nDecimals = std::min<sal_Int32>(nAttrVal, MAX_SECOND_DIGITS);
     950        1218 :                 break;
     951             :             case XML_TOK_ELEM_ATTR_MIN_DECIMAL_DIGITS:
     952         121 :                 if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
     953         121 :                     aNumInfo.nMinDecimalDigits = nAttrVal;
     954         121 :                 break;
     955             :             case XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS:
     956        1488 :                 if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
     957        1488 :                     aNumInfo.nInteger = nAttrVal;
     958        1488 :                 break;
     959             :             case XML_TOK_ELEM_ATTR_GROUPING:
     960         959 :                 if (::sax::Converter::convertBool( bAttrBool, sValue ))
     961         959 :                     aNumInfo.bGrouping = bAttrBool;
     962         959 :                 break;
     963             :             case XML_TOK_ELEM_ATTR_DISPLAY_FACTOR:
     964          16 :                 if (::sax::Converter::convertDouble( fAttrDouble, sValue ))
     965          16 :                     aNumInfo.fDisplayFactor = fAttrDouble;
     966          16 :                 break;
     967             :             case XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT:
     968           3 :                 if ( !sValue.isEmpty() )
     969           2 :                     aNumInfo.bDecReplace = true;    // only a default string is supported
     970             :                 else
     971           1 :                     bVarDecimals = true;   // empty replacement string: variable decimals
     972           3 :                 break;
     973             :             case XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS:
     974          37 :                 if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
     975          37 :                     aNumInfo.nExpDigits = nAttrVal;
     976          37 :                 break;
     977             :             case XML_TOK_ELEM_ATTR_EXPONENT_INTERVAL:
     978           4 :                 if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
     979           4 :                     aNumInfo.nExpInterval = nAttrVal;
     980           4 :                 break;
     981             :             case XML_TOK_ELEM_ATTR_EXPONENT_SIGN:
     982           3 :                 if (::sax::Converter::convertBool( bAttrBool, sValue ))
     983           3 :                     aNumInfo.bExpSign = bAttrBool;
     984           3 :                 break;
     985             :             case XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS:
     986           7 :                 if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
     987           7 :                     aNumInfo.nNumerDigits = nAttrVal;
     988           7 :                 break;
     989             :             case XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS:
     990           7 :                 if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
     991           7 :                     aNumInfo.nDenomDigits = nAttrVal;
     992           7 :                 break;
     993             :             case XML_TOK_ELEM_ATTR_DENOMINATOR_VALUE:
     994           0 :                 if (::sax::Converter::convertNumber( nAttrVal, sValue, 0 ))
     995           0 :                     aNumInfo.nFracDenominator = nAttrVal;
     996           0 :                 break;
     997             :             case XML_TOK_ELEM_ATTR_RFC_LANGUAGE_TAG:
     998           0 :                 aLanguageTagODF.maRfcLanguageTag = sValue;
     999           0 :                 break;
    1000             :             case XML_TOK_ELEM_ATTR_LANGUAGE:
    1001         453 :                 aLanguageTagODF.maLanguage = sValue;
    1002         453 :                 break;
    1003             :             case XML_TOK_ELEM_ATTR_SCRIPT:
    1004           0 :                 aLanguageTagODF.maScript = sValue;
    1005           0 :                 break;
    1006             :             case XML_TOK_ELEM_ATTR_COUNTRY:
    1007         453 :                 aLanguageTagODF.maCountry = sValue;
    1008         453 :                 break;
    1009             :             case XML_TOK_ELEM_ATTR_STYLE:
    1010         487 :                 if ( SvXMLUnitConverter::convertEnum( nAttrEnum, sValue, aStyleValueMap ) )
    1011         487 :                     bLong = (bool) nAttrEnum;
    1012         487 :                 break;
    1013             :             case XML_TOK_ELEM_ATTR_TEXTUAL:
    1014          74 :                 if (::sax::Converter::convertBool( bAttrBool, sValue ))
    1015          74 :                     bTextual = bAttrBool;
    1016          74 :                 break;
    1017             :             case XML_TOK_ELEM_ATTR_CALENDAR:
    1018           8 :                 sCalendar = sValue;
    1019           8 :                 break;
    1020             :         }
    1021        5338 :     }
    1022        5173 :     if ( aNumInfo.nMinDecimalDigits == -1)
    1023             :     {
    1024        5052 :         if ( bVarDecimals )
    1025           1 :             aNumInfo.nMinDecimalDigits = 0;
    1026             :         else
    1027        5051 :             aNumInfo.nMinDecimalDigits = aNumInfo.nDecimals;
    1028             :     }
    1029             : 
    1030        5173 :     if ( !aLanguageTagODF.isEmpty() )
    1031             :     {
    1032         453 :         nElementLang = aLanguageTagODF.getLanguageTag().getLanguageType( false);
    1033         453 :         if ( nElementLang == LANGUAGE_DONTKNOW )
    1034           0 :             nElementLang = LANGUAGE_SYSTEM;         //! error handling for unknown locales?
    1035        5173 :     }
    1036        5173 : }
    1037             : 
    1038       10346 : SvXMLNumFmtElementContext::~SvXMLNumFmtElementContext()
    1039             : {
    1040       10346 : }
    1041             : 
    1042           0 : SvXMLImportContext* SvXMLNumFmtElementContext::CreateChildContext(
    1043             :                                     sal_uInt16 nPrfx, const OUString& rLName,
    1044             :                                     const uno::Reference<xml::sax::XAttributeList>& xAttrList )
    1045             : {
    1046             :     //  only number:number supports number:embedded-text child element
    1047             : 
    1048           0 :     if ( nType == XML_TOK_STYLE_NUMBER &&
    1049           0 :          nPrfx == XML_NAMESPACE_NUMBER && IsXMLToken( rLName, XML_EMBEDDED_TEXT ) )
    1050             :     {
    1051           0 :         return new SvXMLNumFmtEmbeddedTextContext( GetImport(), nPrfx, rLName, *this, xAttrList );
    1052             :     }
    1053             :     else
    1054           0 :         return new SvXMLImportContext( GetImport(), nPrfx, rLName );
    1055             : }
    1056             : 
    1057        2660 : void SvXMLNumFmtElementContext::Characters( const OUString& rChars )
    1058             : {
    1059        2660 :     aContent.append( rChars );
    1060        2660 : }
    1061             : 
    1062           0 : void SvXMLNumFmtElementContext::AddEmbeddedElement( sal_Int32 nFormatPos, const OUString& rContent )
    1063             : {
    1064           0 :     if ( !rContent.isEmpty() )
    1065             :     {
    1066           0 :         SvXMLEmbeddedElement* pObj = new SvXMLEmbeddedElement( nFormatPos, rContent );
    1067           0 :         if ( !aNumInfo.aEmbeddedElements.insert( pObj ).second )
    1068             :         {
    1069             :             //  there's already an element at this position - append text to existing element
    1070             : 
    1071           0 :             delete pObj;
    1072           0 :             for (SvXMLEmbeddedElementArr::iterator it = aNumInfo.aEmbeddedElements.begin();
    1073           0 :                  it != aNumInfo.aEmbeddedElements.end(); ++it)
    1074             :             {
    1075           0 :                 pObj = &*it;
    1076           0 :                 if ( pObj->nFormatPos == nFormatPos )
    1077             :                 {
    1078           0 :                     pObj->aText += rContent;
    1079           0 :                     break;
    1080             :                 }
    1081             :             }
    1082             :         }
    1083             :     }
    1084           0 : }
    1085             : 
    1086        5173 : void SvXMLNumFmtElementContext::EndElement()
    1087             : {
    1088        5173 :     bool bEffLong = bLong;
    1089        5173 :     switch (nType)
    1090             :     {
    1091             :         case XML_TOK_STYLE_TEXT:
    1092        6119 :             if ( rParent.HasLongDoW() &&
    1093        2053 :                  aContent.toString().equals(rParent.GetLocaleData().getLongDateDayOfWeekSep()) )
    1094             :             {
    1095             :                 //  skip separator constant after long day of week
    1096             :                 //  (NF_KEY_NNNN contains the separator)
    1097             : 
    1098           5 :                 if ( rParent.ReplaceNfKeyword( NF_KEY_NNN, NF_KEY_NNNN ) )
    1099             :                 {
    1100           5 :                     aContent = OUStringBuffer();
    1101             :                 }
    1102             : 
    1103           5 :                 rParent.SetHasLongDoW( false );     // only once
    1104             :             }
    1105        2038 :             if ( !aContent.isEmpty() )
    1106             :             {
    1107        2031 :                 lcl_EnquoteIfNecessary( aContent, rParent );
    1108        2031 :                 rParent.AddToCode( aContent.makeStringAndClear() );
    1109             :             }
    1110        2038 :             break;
    1111             : 
    1112             :         case XML_TOK_STYLE_NUMBER:
    1113        1444 :             rParent.AddNumber( aNumInfo );
    1114        1444 :             break;
    1115             : 
    1116             :         case XML_TOK_STYLE_CURRENCY_SYMBOL:
    1117         571 :             rParent.AddCurrency( aContent.makeStringAndClear(), nElementLang );
    1118         571 :             break;
    1119             : 
    1120             :         case XML_TOK_STYLE_TEXT_CONTENT:
    1121          74 :             rParent.AddToCode( '@');
    1122          74 :             break;
    1123             :         case XML_TOK_STYLE_FILL_CHARACTER:
    1124         111 :             if ( !aContent.isEmpty() )
    1125             :             {
    1126         111 :                 rParent.AddToCode( '*' );
    1127         111 :                 rParent.AddToCode( aContent[0] );
    1128             :             }
    1129         111 :             break;
    1130             :         case XML_TOK_STYLE_BOOLEAN:
    1131             :             // ignored - only default boolean format is supported
    1132          13 :             break;
    1133             : 
    1134             :         case XML_TOK_STYLE_DAY:
    1135         165 :             rParent.UpdateCalendar( sCalendar );
    1136             : //! I18N doesn't provide SYSTEM or extended date information yet
    1137             : 
    1138             :             rParent.AddNfKeyword(
    1139             :                 sal::static_int_cast< sal_uInt16 >(
    1140         165 :                     bEffLong ? NF_KEY_DD : NF_KEY_D ) );
    1141         165 :             break;
    1142             :         case XML_TOK_STYLE_MONTH:
    1143         186 :             rParent.UpdateCalendar( sCalendar );
    1144             : //! I18N doesn't provide SYSTEM or extended date information yet
    1145             : 
    1146             :             rParent.AddNfKeyword(
    1147             :                 sal::static_int_cast< sal_uInt16 >(
    1148             :                     bTextual
    1149             :                     ? ( bEffLong ? NF_KEY_MMMM : NF_KEY_MMM )
    1150         186 :                     : ( bEffLong ? NF_KEY_MM : NF_KEY_M ) ) );
    1151         186 :             break;
    1152             :         case XML_TOK_STYLE_YEAR:
    1153         158 :             rParent.UpdateCalendar( sCalendar );
    1154             : //! I18N doesn't provide SYSTEM or extended date information yet
    1155             :             // Y after G (era) is replaced by E
    1156         158 :             if ( rParent.HasEra() )
    1157             :                 rParent.AddNfKeyword(
    1158             :                     sal::static_int_cast< sal_uInt16 >(
    1159           2 :                         bEffLong ? NF_KEY_EEC : NF_KEY_EC ) );
    1160             :             else
    1161             :                 rParent.AddNfKeyword(
    1162             :                     sal::static_int_cast< sal_uInt16 >(
    1163         156 :                         bEffLong ? NF_KEY_YYYY : NF_KEY_YY ) );
    1164         158 :             break;
    1165             :         case XML_TOK_STYLE_ERA:
    1166           2 :             rParent.UpdateCalendar( sCalendar );
    1167             : //! I18N doesn't provide SYSTEM or extended date information yet
    1168             :             rParent.AddNfKeyword(
    1169             :                 sal::static_int_cast< sal_uInt16 >(
    1170           2 :                     bEffLong ? NF_KEY_GGG : NF_KEY_G ) );
    1171             :             //  HasEra flag is set
    1172           2 :             break;
    1173             :         case XML_TOK_STYLE_DAY_OF_WEEK:
    1174          12 :             rParent.UpdateCalendar( sCalendar );
    1175             : //! I18N doesn't provide SYSTEM or extended date information yet
    1176             :             rParent.AddNfKeyword(
    1177             :                 sal::static_int_cast< sal_uInt16 >(
    1178          12 :                     bEffLong ? NF_KEY_NNNN : NF_KEY_NN ) );
    1179          12 :             break;
    1180             :         case XML_TOK_STYLE_WEEK_OF_YEAR:
    1181           0 :             rParent.UpdateCalendar( sCalendar );
    1182           0 :             rParent.AddNfKeyword( NF_KEY_WW );
    1183           0 :             break;
    1184             :         case XML_TOK_STYLE_QUARTER:
    1185           0 :             rParent.UpdateCalendar( sCalendar );
    1186             :             rParent.AddNfKeyword(
    1187             :                 sal::static_int_cast< sal_uInt16 >(
    1188           0 :                     bEffLong ? NF_KEY_QQ : NF_KEY_Q ) );
    1189           0 :             break;
    1190             :         case XML_TOK_STYLE_HOURS:
    1191             :             rParent.AddNfKeyword(
    1192             :                 sal::static_int_cast< sal_uInt16 >(
    1193         108 :                     bEffLong ? NF_KEY_HH : NF_KEY_H ) );
    1194         108 :             break;
    1195             :         case XML_TOK_STYLE_AM_PM:
    1196             :             //! short/long?
    1197          36 :             rParent.AddNfKeyword( NF_KEY_AMPM );
    1198          36 :             break;
    1199             :         case XML_TOK_STYLE_MINUTES:
    1200             :             rParent.AddNfKeyword(
    1201             :                 sal::static_int_cast< sal_uInt16 >(
    1202         132 :                     bEffLong ? NF_KEY_MMI : NF_KEY_MI ) );
    1203         132 :             break;
    1204             :         case XML_TOK_STYLE_SECONDS:
    1205             :             rParent.AddNfKeyword(
    1206             :                 sal::static_int_cast< sal_uInt16 >(
    1207          79 :                     bEffLong ? NF_KEY_SS : NF_KEY_S ) );
    1208          79 :             if ( aNumInfo.nDecimals > 0 )
    1209             :             {
    1210             :                 //  manually add the decimal places
    1211          12 :                 rParent.AddToCode(rParent.GetLocaleData().getNumDecimalSep());
    1212          24 :                 for (sal_Int32 i=0; i<aNumInfo.nDecimals; i++)
    1213             :                 {
    1214          12 :                     rParent.AddToCode( '0');
    1215             :                 }
    1216             :             }
    1217          79 :             break;
    1218             : 
    1219             :         case XML_TOK_STYLE_FRACTION:
    1220             :             {
    1221           7 :                 if ( aNumInfo.nInteger >= 0 )
    1222             :                 {
    1223             :                     // add integer part only if min-integer-digits attribute is there
    1224           7 :                     aNumInfo.nDecimals = 0;
    1225           7 :                     rParent.AddNumber( aNumInfo );      // number without decimals
    1226           7 :                     rParent.AddToCode( ' ' );
    1227             :                 }
    1228             : 
    1229             :                 //! build string and add at once
    1230             : 
    1231             :                 sal_Int32 i;
    1232          17 :                 for (i=0; i<aNumInfo.nNumerDigits; i++)
    1233             :                 {
    1234          10 :                     rParent.AddToCode( '?' );
    1235             :                 }
    1236           7 :                 rParent.AddToCode( '/' );
    1237           7 :                 if ( aNumInfo.nFracDenominator > 0 )
    1238             :                 {
    1239           0 :                     rParent.AddToCode(  OUString::number( aNumInfo.nFracDenominator ) );
    1240             :                 }
    1241             :                 else
    1242             :                 {
    1243          17 :                     for (i=0; i<aNumInfo.nDenomDigits; i++)
    1244             :                     {
    1245          10 :                         rParent.AddToCode( '?');
    1246             :                     }
    1247             :                 }
    1248             :             }
    1249           7 :             break;
    1250             : 
    1251             :         case XML_TOK_STYLE_SCIENTIFIC_NUMBER:
    1252             :             {
    1253             :                 // exponential interval for engineering notation
    1254          37 :                 if( !aNumInfo.bGrouping && aNumInfo.nExpInterval > aNumInfo.nInteger )
    1255             :                 {
    1256           0 :                     for (sal_Int32 i=aNumInfo.nInteger; i<aNumInfo.nExpInterval; i++)
    1257             :                     {
    1258           0 :                         rParent.AddToCode( '#' );
    1259             :                     }
    1260             :                 }
    1261          37 :                 rParent.AddNumber( aNumInfo );      // simple number
    1262             : 
    1263          37 :                 if ( aNumInfo.bExpSign )
    1264          37 :                     rParent.AddToCode( OUString("E+") );
    1265             :                 else
    1266           0 :                     rParent.AddToCode( OUString("E") );
    1267         103 :                 for (sal_Int32 i=0; i<aNumInfo.nExpDigits; i++)
    1268             :                 {
    1269          66 :                     rParent.AddToCode( '0' );
    1270             :                 }
    1271             :             }
    1272          37 :             break;
    1273             : 
    1274             :         default:
    1275             :             OSL_FAIL("invalid element ID");
    1276             :     }
    1277        5173 : }
    1278             : 
    1279         293 : sal_uInt16 SvXMLNumFmtDefaults::GetDefaultDateFormat( SvXMLDateElementAttributes eDOW,
    1280             :                 SvXMLDateElementAttributes eDay, SvXMLDateElementAttributes eMonth,
    1281             :                 SvXMLDateElementAttributes eYear, SvXMLDateElementAttributes eHours,
    1282             :                 SvXMLDateElementAttributes eMins, SvXMLDateElementAttributes eSecs,
    1283             :                 bool bSystem )
    1284             : {
    1285             :     static const sal_uInt16 nCount = sizeof(aDefaultDateFormats) / sizeof(SvXMLDefaultDateFormat);
    1286        1888 :     for (sal_uInt16 nPos=0; nPos<nCount; nPos++)
    1287             :     {
    1288        1854 :         const SvXMLDefaultDateFormat& rEntry = aDefaultDateFormats[nPos];
    1289        3092 :         if ( bSystem == rEntry.bSystem &&
    1290        2476 :             ( eDOW   == rEntry.eDOW   || ( rEntry.eDOW   == XML_DEA_ANY && eDOW   != XML_DEA_NONE ) ) &&
    1291        2186 :             ( eDay   == rEntry.eDay   || ( rEntry.eDay   == XML_DEA_ANY && eDay   != XML_DEA_NONE ) ) &&
    1292        1318 :             ( eMonth == rEntry.eMonth || ( rEntry.eMonth == XML_DEA_ANY && eMonth != XML_DEA_NONE ) ) &&
    1293         646 :             ( eYear  == rEntry.eYear  || ( rEntry.eYear  == XML_DEA_ANY && eYear  != XML_DEA_NONE ) ) &&
    1294         570 :             ( eHours == rEntry.eHours || ( rEntry.eHours == XML_DEA_ANY && eHours != XML_DEA_NONE ) ) &&
    1295         518 :             ( eMins  == rEntry.eMins  || ( rEntry.eMins  == XML_DEA_ANY && eMins  != XML_DEA_NONE ) ) &&
    1296         259 :             ( eSecs  == rEntry.eSecs  || ( rEntry.eSecs  == XML_DEA_ANY && eSecs  != XML_DEA_NONE ) ) )
    1297             :         {
    1298         259 :             return sal::static_int_cast< sal_uInt16 >(rEntry.eFormat);
    1299             :         }
    1300             :     }
    1301             : 
    1302          34 :     return NF_INDEX_TABLE_ENTRIES;  // invalid
    1303             : }
    1304             : 
    1305             : 
    1306             : //  SvXMLNumFormatContext
    1307             : 
    1308             : 
    1309        1946 : SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport,
    1310             :                                     sal_uInt16 nPrfx, const OUString& rLName,
    1311             :                                     SvXMLNumImpData* pNewData, sal_uInt16 nNewType,
    1312             :                                     const uno::Reference<xml::sax::XAttributeList>& xAttrList,
    1313             :                                     SvXMLStylesContext& rStyles ) :
    1314             :     SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList ),
    1315             :     pData( pNewData ),
    1316             :     pStyles( &rStyles ),
    1317             :     aMyConditions(),
    1318             :     nType( nNewType ),
    1319             :     nKey(-1),
    1320             :     nFormatLang( LANGUAGE_SYSTEM ),
    1321             :     bAutoOrder( false ),
    1322             :     bFromSystem( false ),
    1323             :     bTruncate( true ),
    1324             :     bAutoDec( false ),
    1325             :     bAutoInt( false ),
    1326             :     bHasExtraText( false ),
    1327             :     bHasLongDoW( false ),
    1328             :     bHasEra( false ),
    1329             :     bHasDateTime( false ),
    1330             :     bRemoveAfterUse( false ),
    1331             :     eDateDOW( XML_DEA_NONE ),
    1332             :     eDateDay( XML_DEA_NONE ),
    1333             :     eDateMonth( XML_DEA_NONE ),
    1334             :     eDateYear( XML_DEA_NONE ),
    1335             :     eDateHours( XML_DEA_NONE ),
    1336             :     eDateMins( XML_DEA_NONE ),
    1337             :     eDateSecs( XML_DEA_NONE ),
    1338        1946 :     bDateNoDefault( false )
    1339             : {
    1340        1946 :     LanguageTagODF aLanguageTagODF;
    1341        3892 :     OUString sNatNumAttrScript, sNatNumAttrRfcLanguageTag;
    1342        3892 :     ::com::sun::star::i18n::NativeNumberXmlAttributes aNatNumAttr;
    1343        1946 :     bool bAttrBool(false);
    1344             :     sal_uInt16 nAttrEnum;
    1345             : 
    1346        1946 :     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    1347        5525 :     for( sal_Int16 i=0; i < nAttrCount; i++ )
    1348             :     {
    1349        3579 :         OUString sAttrName = xAttrList->getNameByIndex( i );
    1350        7158 :         OUString sValue = xAttrList->getValueByIndex( i );
    1351        7158 :         OUString aLocalName;
    1352        3579 :         sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
    1353             : 
    1354        3579 :         const SvXMLTokenMap& rTokenMap = pData->GetStyleAttrTokenMap();
    1355        3579 :         sal_uInt16 nToken = rTokenMap.Get( nPrefix, aLocalName );
    1356        3579 :         switch (nToken)
    1357             :         {
    1358             :             case XML_TOK_STYLE_ATTR_NAME:
    1359        1946 :                 break;
    1360             :             case XML_TOK_STYLE_ATTR_RFC_LANGUAGE_TAG:
    1361           0 :                 aLanguageTagODF.maRfcLanguageTag = sValue;
    1362           0 :                 break;
    1363             :             case XML_TOK_STYLE_ATTR_LANGUAGE:
    1364         428 :                 aLanguageTagODF.maLanguage = sValue;
    1365         428 :                 break;
    1366             :             case XML_TOK_STYLE_ATTR_SCRIPT:
    1367           0 :                 aLanguageTagODF.maScript = sValue;
    1368           0 :                 break;
    1369             :             case XML_TOK_STYLE_ATTR_COUNTRY:
    1370         428 :                 aLanguageTagODF.maCountry = sValue;
    1371         428 :                 break;
    1372             :             case XML_TOK_STYLE_ATTR_TITLE:
    1373           0 :                 sFormatTitle = sValue;
    1374           0 :                 break;
    1375             :             case XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER:
    1376         104 :                 if (::sax::Converter::convertBool( bAttrBool, sValue ))
    1377         104 :                     bAutoOrder = bAttrBool;
    1378         104 :                 break;
    1379             :             case XML_TOK_STYLE_ATTR_FORMAT_SOURCE:
    1380           2 :                 if ( SvXMLUnitConverter::convertEnum( nAttrEnum, sValue, aFormatSourceMap ) )
    1381           2 :                     bFromSystem = (bool) nAttrEnum;
    1382           2 :                 break;
    1383             :             case XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW:
    1384          12 :                 if (::sax::Converter::convertBool( bAttrBool, sValue ))
    1385          12 :                     bTruncate = bAttrBool;
    1386          12 :                 break;
    1387             :             case XML_TOK_STYLE_ATTR_VOLATILE:
    1388             :                 //  volatile formats can be removed after importing
    1389             :                 //  if not used in other styles
    1390         636 :                 if (::sax::Converter::convertBool( bAttrBool, sValue ))
    1391         636 :                     bRemoveAfterUse = bAttrBool;
    1392         636 :                 break;
    1393             :             case XML_TOK_STYLE_ATTR_TRANSL_FORMAT:
    1394           1 :                 aNatNumAttr.Format = sValue;
    1395           1 :                 break;
    1396             :             case XML_TOK_STYLE_ATTR_TRANSL_RFC_LANGUAGE_TAG:
    1397           0 :                 sNatNumAttrRfcLanguageTag = sValue;
    1398           0 :                 break;
    1399             :             case XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE:
    1400           1 :                 aNatNumAttr.Locale.Language = sValue;
    1401           1 :                 break;
    1402             :             case XML_TOK_STYLE_ATTR_TRANSL_SCRIPT:
    1403           0 :                 sNatNumAttrScript = sValue;
    1404           0 :                 break;
    1405             :             case XML_TOK_STYLE_ATTR_TRANSL_COUNTRY:
    1406           1 :                 aNatNumAttr.Locale.Country = sValue;
    1407           1 :                 break;
    1408             :             case XML_TOK_STYLE_ATTR_TRANSL_STYLE:
    1409           1 :                 aNatNumAttr.Style = sValue;
    1410           1 :                 break;
    1411             :         }
    1412        3579 :     }
    1413             : 
    1414        1946 :     if (!aLanguageTagODF.isEmpty())
    1415             :     {
    1416         428 :         nFormatLang = aLanguageTagODF.getLanguageTag().getLanguageType( false);
    1417         428 :         if ( nFormatLang == LANGUAGE_DONTKNOW )
    1418           0 :             nFormatLang = LANGUAGE_SYSTEM;          //! error handling for unknown locales?
    1419             :     }
    1420             : 
    1421        1946 :     if ( !aNatNumAttr.Format.isEmpty() )
    1422             :     {
    1423           1 :         SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
    1424           1 :         if ( pFormatter )
    1425             :         {
    1426             :             LanguageTag aLanguageTag( sNatNumAttrRfcLanguageTag, aNatNumAttr.Locale.Language,
    1427           1 :                     sNatNumAttrScript, aNatNumAttr.Locale.Country);
    1428           1 :             aNatNumAttr.Locale = aLanguageTag.getLocale( false);
    1429             : 
    1430           1 :             sal_Int32 nNatNum = pFormatter->GetNatNum()->convertFromXmlAttributes( aNatNumAttr );
    1431           1 :             aFormatCode.append( "[NatNum" );
    1432           1 :             aFormatCode.append( nNatNum, 10 );
    1433             : 
    1434           1 :             LanguageType eLang = aLanguageTag.getLanguageType( false);
    1435           1 :             if ( eLang == LANGUAGE_DONTKNOW )
    1436           0 :                 eLang = LANGUAGE_SYSTEM;            //! error handling for unknown locales?
    1437           1 :             if ( eLang != nFormatLang && eLang != LANGUAGE_SYSTEM )
    1438             :             {
    1439           0 :                 aFormatCode.append( "][$-" );
    1440             :                 // language code in upper hex:
    1441           0 :                 aFormatCode.append(OUString::number(eLang, 16).toAsciiUpperCase());
    1442             :             }
    1443           1 :             aFormatCode.append( ']' );
    1444             :         }
    1445        1946 :     }
    1446        1946 : }
    1447             : 
    1448         901 : SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport,
    1449             :                                     sal_uInt16 nPrfx, const OUString& rLName,
    1450             :                                     const uno::Reference<xml::sax::XAttributeList>& xAttrList,
    1451             :                                     const sal_Int32 nTempKey,
    1452             :                                     SvXMLStylesContext& rStyles ) :
    1453             :     SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList, XML_STYLE_FAMILY_DATA_STYLE ),
    1454             :     pData( NULL ),
    1455             :     pStyles( &rStyles ),
    1456             :     aMyConditions(),
    1457             :     nType( 0 ),
    1458             :     nKey(nTempKey),
    1459             :     nFormatLang( LANGUAGE_SYSTEM ),
    1460             :     bAutoOrder( false ),
    1461             :     bFromSystem( false ),
    1462             :     bTruncate( true ),
    1463             :     bAutoDec( false ),
    1464             :     bAutoInt( false ),
    1465             :     bHasExtraText( false ),
    1466             :     bHasLongDoW( false ),
    1467             :     bHasEra( false ),
    1468             :     bHasDateTime( false ),
    1469             :     bRemoveAfterUse( false ),
    1470             :     eDateDOW( XML_DEA_NONE ),
    1471             :     eDateDay( XML_DEA_NONE ),
    1472             :     eDateMonth( XML_DEA_NONE ),
    1473             :     eDateYear( XML_DEA_NONE ),
    1474             :     eDateHours( XML_DEA_NONE ),
    1475             :     eDateMins( XML_DEA_NONE ),
    1476             :     eDateSecs( XML_DEA_NONE ),
    1477         901 :     bDateNoDefault( false )
    1478             : {
    1479         901 :     SetAttribute(XML_NAMESPACE_STYLE, GetXMLToken(XML_NAME), rLName);
    1480         901 : }
    1481             : 
    1482        5692 : SvXMLNumFormatContext::~SvXMLNumFormatContext()
    1483             : {
    1484        5692 : }
    1485             : 
    1486        6114 : SvXMLImportContext* SvXMLNumFormatContext::CreateChildContext(
    1487             :                                     sal_uInt16 nPrfx, const OUString& rLName,
    1488             :                                     const uno::Reference<xml::sax::XAttributeList>& xAttrList )
    1489             : {
    1490        6114 :     SvXMLImportContext* pContext = NULL;
    1491             : 
    1492        6114 :     const SvXMLTokenMap& rTokenMap = pData->GetStyleElemTokenMap();
    1493        6114 :     sal_uInt16 nToken = rTokenMap.Get( nPrfx, rLName );
    1494        6114 :     switch (nToken)
    1495             :     {
    1496             :         case XML_TOK_STYLE_TEXT:
    1497             :         case XML_TOK_STYLE_FILL_CHARACTER:
    1498             :         case XML_TOK_STYLE_NUMBER:
    1499             :         case XML_TOK_STYLE_SCIENTIFIC_NUMBER:
    1500             :         case XML_TOK_STYLE_FRACTION:
    1501             :         case XML_TOK_STYLE_CURRENCY_SYMBOL:
    1502             :         case XML_TOK_STYLE_DAY:
    1503             :         case XML_TOK_STYLE_MONTH:
    1504             :         case XML_TOK_STYLE_YEAR:
    1505             :         case XML_TOK_STYLE_ERA:
    1506             :         case XML_TOK_STYLE_DAY_OF_WEEK:
    1507             :         case XML_TOK_STYLE_WEEK_OF_YEAR:
    1508             :         case XML_TOK_STYLE_QUARTER:
    1509             :         case XML_TOK_STYLE_HOURS:
    1510             :         case XML_TOK_STYLE_AM_PM:
    1511             :         case XML_TOK_STYLE_MINUTES:
    1512             :         case XML_TOK_STYLE_SECONDS:
    1513             :         case XML_TOK_STYLE_BOOLEAN:
    1514             :         case XML_TOK_STYLE_TEXT_CONTENT:
    1515        5173 :             pContext = new SvXMLNumFmtElementContext( GetImport(), nPrfx, rLName,
    1516        5173 :                                                         *this, nToken, xAttrList );
    1517        5173 :             break;
    1518             : 
    1519             :         case XML_TOK_STYLE_PROPERTIES:
    1520         305 :             pContext = new SvXMLNumFmtPropContext( GetImport(), nPrfx, rLName,
    1521         305 :                                                         *this, xAttrList );
    1522         305 :             break;
    1523             :         case XML_TOK_STYLE_MAP:
    1524             :             {
    1525             :                 //  SvXMLNumFmtMapContext::EndElement adds to aMyConditions,
    1526             :                 //  so there's no need for an extra flag
    1527         636 :                 pContext = new SvXMLNumFmtMapContext( GetImport(), nPrfx, rLName,
    1528         636 :                                                             *this, xAttrList );
    1529             :             }
    1530         636 :             break;
    1531             :     }
    1532             : 
    1533        6114 :     if( !pContext )
    1534           0 :         pContext = new SvXMLImportContext( GetImport(), nPrfx, rLName );
    1535        6114 :     return pContext;
    1536             : }
    1537             : 
    1538         985 : sal_Int32 SvXMLNumFormatContext::GetKey()
    1539             : {
    1540         985 :     if (nKey > -1)
    1541             :     {
    1542         580 :         if (bRemoveAfterUse)
    1543             :         {
    1544             :             //  format is used -> don't remove
    1545           0 :             bRemoveAfterUse = false;
    1546           0 :             if (pData)
    1547           0 :                 pData->SetUsed(nKey);
    1548             : 
    1549             :             //  Add to import's list of keys now - CreateAndInsert didn't add
    1550             :             //  the style if bRemoveAfterUse was set.
    1551           0 :             GetImport().AddNumberStyle( nKey, GetName() );
    1552             :         }
    1553         580 :         return nKey;
    1554             :     }
    1555             :     else
    1556             :     {
    1557             :         // reset bRemoveAfterUse before CreateAndInsert, so AddKey is called without bRemoveAfterUse set
    1558         405 :         bRemoveAfterUse = false;
    1559         405 :         CreateAndInsert(true);
    1560         405 :         return nKey;
    1561             :     }
    1562             : }
    1563             : 
    1564         636 : sal_Int32 SvXMLNumFormatContext::PrivateGetKey()
    1565             : {
    1566             :     //  used for map elements in CreateAndInsert - don't reset bRemoveAfterUse flag
    1567             : 
    1568         636 :     if (nKey > -1)
    1569         622 :         return nKey;
    1570             :     else
    1571             :     {
    1572          14 :         CreateAndInsert(true);
    1573          14 :         return nKey;
    1574             :     }
    1575             : }
    1576             : 
    1577           0 : sal_Int32 SvXMLNumFormatContext::CreateAndInsert( com::sun::star::uno::Reference< com::sun::star::util::XNumberFormatsSupplier >& xFormatsSupplier )
    1578             : {
    1579           0 :     if (nKey <= -1)
    1580             :     {
    1581           0 :         SvNumberFormatter* pFormatter = NULL;
    1582             :         SvNumberFormatsSupplierObj* pObj =
    1583           0 :                         SvNumberFormatsSupplierObj::getImplementation( xFormatsSupplier );
    1584           0 :         if (pObj)
    1585           0 :             pFormatter = pObj->GetNumberFormatter();
    1586             : 
    1587           0 :         if ( pFormatter )
    1588           0 :             return CreateAndInsert( pFormatter );
    1589             :         else
    1590           0 :             return -1;
    1591             :     }
    1592             :     else
    1593           0 :         return nKey;
    1594             : }
    1595             : 
    1596        1942 : void SvXMLNumFormatContext::CreateAndInsert(bool /*bOverwrite*/)
    1597             : {
    1598        1942 :     if (!(nKey > -1))
    1599        1942 :         CreateAndInsert(pData->GetNumberFormatter());
    1600        1942 : }
    1601             : 
    1602        1942 : sal_Int32 SvXMLNumFormatContext::CreateAndInsert(SvNumberFormatter* pFormatter)
    1603             : {
    1604        1942 :     if (!pFormatter)
    1605             :     {
    1606             :         OSL_FAIL("no number formatter");
    1607           0 :         return -1;
    1608             :     }
    1609             : 
    1610        1942 :     sal_uInt32 nIndex = NUMBERFORMAT_ENTRY_NOT_FOUND;
    1611             : 
    1612        2578 :     for (size_t i = 0; i < aMyConditions.size(); i++)
    1613             :     {
    1614             :         SvXMLNumFormatContext* pStyle = const_cast<SvXMLNumFormatContext*>( static_cast<const SvXMLNumFormatContext *>(pStyles->FindStyleChildContext(
    1615         636 :             XML_STYLE_FAMILY_DATA_STYLE, aMyConditions[i].sMapName, false)));
    1616         636 :         if (pStyle)
    1617             :         {
    1618         636 :             if ((pStyle->PrivateGetKey() > -1))     // don't reset pStyle's bRemoveAfterUse flag
    1619         636 :                 AddCondition(i);
    1620             :         }
    1621             :     }
    1622             : 
    1623        1942 :     if ( aFormatCode.isEmpty() )
    1624             :     {
    1625             :         //  insert empty format as empty string (with quotes)
    1626             :         //  #93901# this check has to be done before inserting the conditions
    1627          13 :         aFormatCode.appendAscii("\"\"");    // ""
    1628             :     }
    1629             : 
    1630        1942 :     aFormatCode.insert( 0, aConditions.makeStringAndClear() );
    1631        1942 :     OUString sFormat = aFormatCode.makeStringAndClear();
    1632             : 
    1633             :     //  test special cases
    1634             : 
    1635        1942 :     if ( bAutoDec )         // automatic decimal places
    1636             :     {
    1637             :         //  #99391# adjust only if the format contains no text elements, no conditions
    1638             :         //  and no color definition (detected by the '[' at the start)
    1639             : 
    1640        1091 :         if ( nType == XML_TOK_STYLES_NUMBER_STYLE && !bHasExtraText &&
    1641         813 :                 aMyConditions.empty() && sFormat.toChar() != '[' )
    1642         269 :             nIndex = pFormatter->GetStandardIndex( nFormatLang );
    1643             :     }
    1644        1942 :     if ( bAutoInt )         // automatic integer digits
    1645             :     {
    1646             :         //! only if two decimal places was set?
    1647             : 
    1648           0 :         if ( nType == XML_TOK_STYLES_NUMBER_STYLE && !bHasExtraText &&
    1649           0 :                 aMyConditions.empty() && sFormat.toChar() != '[' )
    1650           0 :             nIndex = pFormatter->GetFormatIndex( NF_NUMBER_SYSTEM, nFormatLang );
    1651             :     }
    1652             : 
    1653             :     //  boolean is always the builtin boolean format
    1654             :     //  (no other boolean formats are implemented)
    1655        1942 :     if ( nType == XML_TOK_STYLES_BOOLEAN_STYLE )
    1656          13 :         nIndex = pFormatter->GetFormatIndex( NF_BOOLEAN, nFormatLang );
    1657             : 
    1658             :     //  check for default date formats
    1659        1942 :     if ( nType == XML_TOK_STYLES_DATE_STYLE && bAutoOrder && !bDateNoDefault )
    1660             :     {
    1661             :         NfIndexTableOffset eFormat = (NfIndexTableOffset) SvXMLNumFmtDefaults::GetDefaultDateFormat(
    1662             :             eDateDOW, eDateDay, eDateMonth, eDateYear,
    1663         102 :             eDateHours, eDateMins, eDateSecs, bFromSystem );
    1664         102 :         if ( eFormat < NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS )
    1665             :         {
    1666             :             //  #109651# if a date format has the automatic-order attribute and
    1667             :             //  contains exactly the elements of one of the default date formats,
    1668             :             //  use that default format, with the element order and separators
    1669             :             //  from the current locale settings
    1670             : 
    1671          68 :             nIndex = pFormatter->GetFormatIndex( eFormat, nFormatLang );
    1672             :         }
    1673             :     }
    1674             : 
    1675        1942 :     if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND && !sFormat.isEmpty() )
    1676             :     {
    1677             :         //  insert by format string
    1678             : 
    1679        1592 :         OUString aFormatStr( sFormat );
    1680        1592 :         nIndex = pFormatter->GetEntryKey( aFormatStr, nFormatLang );
    1681        1592 :         if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND )
    1682             :         {
    1683        1163 :             sal_Int32  nErrPos = 0;
    1684        1163 :             short       l_nType = 0;
    1685        1163 :             bool bOk = pFormatter->PutEntry( aFormatStr, nErrPos, l_nType, nIndex, nFormatLang );
    1686        1163 :             if ( !bOk && nErrPos == 0 && aFormatStr != sFormat )
    1687             :             {
    1688             :                 //  if the string was modified by PutEntry, look for an existing format
    1689             :                 //  with the modified string
    1690           1 :                 nIndex = pFormatter->GetEntryKey( aFormatStr, nFormatLang );
    1691           1 :                 if ( nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND )
    1692           1 :                     bOk = true;
    1693             :             }
    1694        1163 :             if (!bOk)
    1695           2 :                 nIndex = NUMBERFORMAT_ENTRY_NOT_FOUND;
    1696        1592 :         }
    1697             :     }
    1698             : 
    1699             : //! I18N doesn't provide SYSTEM or extended date information yet
    1700        1942 :     if ( nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND && !bAutoOrder )
    1701             :     {
    1702             :         //  use fixed-order formats instead of SYS... if bAutoOrder is false
    1703             :         //  (only if the format strings are equal for the locale)
    1704             : 
    1705        1838 :         NfIndexTableOffset eOffset = pFormatter->GetIndexTableOffset( nIndex );
    1706        1838 :         if ( eOffset == NF_DATE_SYS_DMMMYYYY )
    1707             :         {
    1708           0 :             sal_uInt32 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_DIN_DMMMYYYY, nFormatLang );
    1709           0 :             const SvNumberformat* pOldEntry = pFormatter->GetEntry( nIndex );
    1710           0 :             const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewIndex );
    1711           0 :             if ( pOldEntry && pNewEntry && pOldEntry->GetFormatstring() == pNewEntry->GetFormatstring() )
    1712           0 :                 nIndex = nNewIndex;
    1713             :         }
    1714        1838 :         else if ( eOffset == NF_DATE_SYS_DMMMMYYYY )
    1715             :         {
    1716           0 :             sal_uInt32 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_DIN_DMMMMYYYY, nFormatLang );
    1717           0 :             const SvNumberformat* pOldEntry = pFormatter->GetEntry( nIndex );
    1718           0 :             const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewIndex );
    1719           0 :             if ( pOldEntry && pNewEntry && pOldEntry->GetFormatstring() == pNewEntry->GetFormatstring() )
    1720           0 :                 nIndex = nNewIndex;
    1721             :         }
    1722             :     }
    1723             : 
    1724        1942 :     if ((nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND) && !sFormatTitle.isEmpty())
    1725             :     {
    1726           0 :         SvNumberformat* pFormat = const_cast<SvNumberformat*>(pFormatter->GetEntry( nIndex ));
    1727           0 :         if (pFormat)
    1728             :         {
    1729           0 :             pFormat->SetComment(sFormatTitle);
    1730             :         }
    1731             :     }
    1732             : 
    1733        1942 :     if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND )
    1734             :     {
    1735             :         OSL_FAIL("invalid number format");
    1736           2 :         nIndex = pFormatter->GetStandardIndex( nFormatLang );
    1737             :     }
    1738             : 
    1739        1942 :     pData->AddKey( nIndex, GetName(), bRemoveAfterUse );
    1740        1942 :     nKey = nIndex;
    1741             : 
    1742             :     //  Add to import's list of keys (shared between styles and content import)
    1743             :     //  only if not volatile - formats are removed from NumberFormatter at the
    1744             :     //  end of each import (in SvXMLNumFmtHelper dtor).
    1745             :     //  If bRemoveAfterUse is reset later in GetKey, AddNumberStyle is called there.
    1746             : 
    1747        1942 :     if (!bRemoveAfterUse)
    1748        1306 :         GetImport().AddNumberStyle( nKey, GetName() );
    1749             : 
    1750        1942 :     return nKey;
    1751             : }
    1752             : 
    1753        1525 : void SvXMLNumFormatContext::Finish( bool bOverwrite )
    1754             : {
    1755        1525 :     SvXMLStyleContext::Finish( bOverwrite );
    1756        1525 : }
    1757             : 
    1758        1170 : const LocaleDataWrapper& SvXMLNumFormatContext::GetLocaleData() const
    1759             : {
    1760        1170 :     return pData->GetLocaleData( nFormatLang );
    1761             : }
    1762             : 
    1763         408 : void SvXMLNumFormatContext::AddToCode( sal_Unicode c )
    1764             : {
    1765         408 :     aFormatCode.append( c );
    1766         408 :     bHasExtraText = true;
    1767         408 : }
    1768             : 
    1769        2080 : void SvXMLNumFormatContext::AddToCode( const OUString& rString )
    1770             : {
    1771        2080 :     aFormatCode.append( rString );
    1772        2080 :     bHasExtraText = true;
    1773        2080 : }
    1774             : 
    1775        1488 : void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo& rInfo )
    1776             : {
    1777        1488 :     SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
    1778        1488 :     if (!pFormatter)
    1779         275 :         return;
    1780             : 
    1781             :     //  store special conditions
    1782        1488 :     bAutoDec = ( rInfo.nDecimals < 0 );
    1783        1488 :     bAutoInt = ( rInfo.nInteger < 0 );
    1784             : 
    1785        1488 :     sal_uInt16 nPrec = 0;
    1786        1488 :     sal_uInt16 nLeading = 0;
    1787        1488 :     if ( rInfo.nDecimals >= 0 )                     //  < 0 : Default
    1788        1213 :         nPrec = (sal_uInt16) rInfo.nDecimals;
    1789        1488 :     if ( rInfo.nInteger >= 0 )                      //  < 0 : Default
    1790        1488 :         nLeading = (sal_uInt16) rInfo.nInteger;
    1791             : 
    1792        1488 :     if ( bAutoDec )
    1793             :     {
    1794         275 :         if ( nType == XML_TOK_STYLES_CURRENCY_STYLE )
    1795             :         {
    1796             :             //  for currency formats, "automatic decimals" is used for the automatic
    1797             :             //  currency format with (fixed) decimals from the locale settings
    1798             : 
    1799           0 :             const LocaleDataWrapper& rLoc = pData->GetLocaleData( nFormatLang );
    1800           0 :             nPrec = rLoc.getCurrDigits();
    1801             :         }
    1802             :         else
    1803             :         {
    1804             :             //  for other types, "automatic decimals" means dynamic determination of
    1805             :             //  decimals, as achieved with the "general" keyword
    1806             : 
    1807         275 :             aFormatCode.append( pFormatter->GetStandardName( nFormatLang ) );
    1808         275 :             return;
    1809             :         }
    1810             :     }
    1811        1213 :     if ( bAutoInt )
    1812             :     {
    1813             :         //!...
    1814             :     }
    1815             : 
    1816        1213 :     sal_uInt16 nGenPrec = nPrec;
    1817        1213 :     if ( rInfo.nMinDecimalDigits >= 0 )
    1818        1206 :         nGenPrec = rInfo.nMinDecimalDigits;
    1819        1213 :     if ( rInfo.bDecReplace )
    1820           2 :         nGenPrec = 0;               // generate format without decimals...
    1821             : 
    1822        1213 :     bool bGrouping = rInfo.bGrouping;
    1823        1213 :     sal_uInt16 nEmbeddedCount = rInfo.aEmbeddedElements.size();
    1824        1213 :     if ( nEmbeddedCount )
    1825           0 :         bGrouping = false;      // grouping and embedded characters can't be used together
    1826             : 
    1827        1213 :     sal_uInt32 nStdIndex = pFormatter->GetStandardIndex( nFormatLang );
    1828             :     OUStringBuffer aNumStr = pFormatter->GenerateFormat( nStdIndex, nFormatLang,
    1829        1213 :                                                          bGrouping, false, nGenPrec, nLeading );
    1830             : 
    1831        1213 :     if ( rInfo.nExpDigits >= 0 && nLeading == 0 && !bGrouping && nEmbeddedCount == 0 )
    1832             :     {
    1833             :         // #i43959# For scientific numbers, "#" in the integer part forces a digit,
    1834             :         // so it has to be removed if nLeading is 0 (".00E+0", not "#.00E+0").
    1835             : 
    1836           0 :         aNumStr.stripStart('#');
    1837             :     }
    1838             : 
    1839        1213 :     if ( bGrouping && rInfo.nExpInterval > rInfo.nInteger )
    1840             :     {
    1841           0 :         sal_Int32 nIndex = 0;
    1842           0 :         sal_Int32 nDigits = rInfo.nInteger;
    1843           0 :         sal_Int32 nIntegerEnd = aNumStr.indexOf( pFormatter->GetNumDecimalSep() );
    1844           0 :         if ( nIntegerEnd < 0 )
    1845           0 :             nIntegerEnd = aNumStr.getLength();
    1846           0 :         while ( nIndex >= 0 && nIndex < nIntegerEnd )
    1847             :         {
    1848           0 :             if ( ( nIndex = aNumStr.indexOf( '#', nIndex ) ) >= 0 )
    1849             :             {
    1850           0 :                 nDigits ++;
    1851           0 :                 nIndex ++;
    1852             :             }
    1853             :             else
    1854           0 :                 nIndex = -1;
    1855             :         }
    1856           0 :         while ( rInfo.nExpInterval > nDigits )
    1857             :         {
    1858           0 :             nDigits++;
    1859           0 :             aNumStr.insert( 0, '#' );
    1860             :         }
    1861             :     }
    1862             : 
    1863        1213 :     if ( nEmbeddedCount )
    1864             :     {
    1865             :         //  insert embedded strings into number string
    1866             :         //  only the integer part is supported
    1867             :         //  nZeroPos is the string position where format position 0 is inserted
    1868             : 
    1869           0 :         sal_Int32 nZeroPos = aNumStr.indexOf( pData->GetLocaleData( nFormatLang ).getNumDecimalSep() );
    1870           0 :         if ( nZeroPos < 0 )
    1871             :         {
    1872           0 :             nZeroPos = aNumStr.getLength();
    1873             :         }
    1874             : 
    1875             :         //  aEmbeddedElements is sorted - last entry has the largest position (leftmost)
    1876           0 :         const SvXMLEmbeddedElement* pLastObj = &*rInfo.aEmbeddedElements.rbegin();
    1877           0 :         sal_Int32 nLastFormatPos = pLastObj->nFormatPos;
    1878           0 :         if ( nLastFormatPos >= nZeroPos )
    1879             :         {
    1880             :             //  add '#' characters so all embedded texts are really embedded in digits
    1881             :             //  (there always has to be a digit before the leftmost embedded text)
    1882             : 
    1883           0 :             sal_Int32 nAddCount = nLastFormatPos + 1 - nZeroPos;
    1884           0 :             for(sal_Int32 index = 0; index < nAddCount; ++index)
    1885             :             {
    1886           0 :                 aNumStr.insert(0, '#');
    1887             :             }
    1888           0 :             nZeroPos = nZeroPos + nAddCount;
    1889             :         }
    1890             : 
    1891             :         //  aEmbeddedElements is sorted with ascending positions - loop is from right to left
    1892           0 :         for (SvXMLEmbeddedElementArr::const_iterator it = rInfo.aEmbeddedElements.begin();
    1893           0 :              it != rInfo.aEmbeddedElements.end(); ++it)
    1894             :         {
    1895           0 :             const SvXMLEmbeddedElement* pObj = &*it;
    1896           0 :             sal_Int32 nFormatPos = pObj->nFormatPos;
    1897           0 :             sal_Int32 nInsertPos = nZeroPos - nFormatPos;
    1898           0 :             if ( nFormatPos >= 0 && nInsertPos >= 0 )
    1899             :             {
    1900             :                 //  #107805# always quote embedded strings - even space would otherwise
    1901             :                 //  be recognized as thousands separator in French.
    1902             : 
    1903           0 :                 aNumStr.insert(nInsertPos, '"');
    1904           0 :                 aNumStr.insert(nInsertPos, pObj->aText);
    1905           0 :                 aNumStr.insert(nInsertPos, '"');
    1906             :             }
    1907             :         }
    1908             :     }
    1909             : 
    1910        1213 :     aFormatCode.append( aNumStr.makeStringAndClear() );
    1911             : 
    1912        1213 :     if ( ( rInfo.bDecReplace || rInfo.nMinDecimalDigits < rInfo.nDecimals ) && nPrec )     // add decimal replacement (dashes)
    1913             :     {
    1914             :         //  add dashes for explicit decimal replacement, # for variable decimals
    1915           3 :         sal_Unicode cAdd = rInfo.bDecReplace ? '-' : '#';
    1916             : 
    1917           3 :         if ( rInfo.nMinDecimalDigits == 0 )
    1918           1 :             aFormatCode.append( pData->GetLocaleData( nFormatLang ).getNumDecimalSep() );
    1919           5 :         for ( sal_uInt16 i=rInfo.nMinDecimalDigits; i<nPrec; i++)
    1920           2 :             aFormatCode.append( cAdd );
    1921             :     }
    1922             : 
    1923             :     //  add extra thousands separators for display factor
    1924             : 
    1925        1213 :     if ( rInfo.fDisplayFactor != 1.0 && rInfo.fDisplayFactor > 0.0 )
    1926             :     {
    1927             :         //  test for 1.0 is just for optimization - nSepCount would be 0
    1928             : 
    1929             :         //  one separator for each factor of 1000
    1930          16 :         sal_Int32 nSepCount = (sal_Int32) ::rtl::math::round( log10(rInfo.fDisplayFactor) / 3.0 );
    1931          16 :         if ( nSepCount > 0 )
    1932             :         {
    1933          16 :             OUString aSep = pData->GetLocaleData( nFormatLang ).getNumThousandSep();
    1934          32 :             for ( sal_Int32 i=0; i<nSepCount; i++ )
    1935          32 :                 aFormatCode.append( aSep );
    1936             :         }
    1937        1213 :     }
    1938             : }
    1939             : 
    1940         571 : void SvXMLNumFormatContext::AddCurrency( const OUString& rContent, LanguageType nLang )
    1941             : {
    1942         571 :     bool bAutomatic = false;
    1943         571 :     OUString aSymbol = rContent;
    1944         571 :     if ( aSymbol.isEmpty())
    1945             :     {
    1946         102 :         SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
    1947         102 :         if ( pFormatter )
    1948             :         {
    1949         102 :             pFormatter->ChangeIntl( nFormatLang );
    1950         204 :             OUString sCurString, sDummy;
    1951         102 :             pFormatter->GetCompatibilityCurrency( sCurString, sDummy );
    1952         102 :             aSymbol = sCurString;
    1953             : 
    1954         204 :             bAutomatic = true;
    1955             :         }
    1956             :     }
    1957         469 :     else if ( nLang == LANGUAGE_SYSTEM && aSymbol == "CCC" )
    1958             :     {
    1959             :         //  "CCC" is used for automatic long symbol
    1960           0 :         bAutomatic = true;
    1961             :     }
    1962             : 
    1963         571 :     if ( bAutomatic )
    1964             :     {
    1965             :         //  remove unnecessary quotes before automatic symbol (formats like "-(0DM)")
    1966             :         //  otherwise the currency symbol isn't recognized (#94048#)
    1967             : 
    1968         102 :         sal_Int32 nLength = aFormatCode.getLength();
    1969         102 :         if ( nLength > 1 && aFormatCode[nLength - 1] == '"' )
    1970             :         {
    1971             :             //  find start of quoted string
    1972             :             //  When SvXMLNumFmtElementContext::EndElement creates escaped quotes,
    1973             :             //  they must be handled here, too.
    1974             : 
    1975           0 :             sal_Int32 nFirst = nLength - 2;
    1976           0 :             while ( nFirst >= 0 && aFormatCode[nFirst] != '"' )
    1977           0 :                 --nFirst;
    1978           0 :             if ( nFirst >= 0 )
    1979             :             {
    1980             :                 //  remove both quotes from aFormatCode
    1981           0 :                 OUString aOld = aFormatCode.makeStringAndClear();
    1982           0 :                 if ( nFirst > 0 )
    1983           0 :                     aFormatCode.append( aOld.copy( 0, nFirst ) );
    1984           0 :                 if ( nLength > nFirst + 2 )
    1985           0 :                     aFormatCode.append( aOld.copy( nFirst + 1, nLength - nFirst - 2 ) );
    1986             :             }
    1987             :         }
    1988             :     }
    1989             : 
    1990         571 :     if (!bAutomatic)
    1991         469 :         aFormatCode.appendAscii( "[$" );            // intro for "new" currency symbols
    1992             : 
    1993         571 :     aFormatCode.append( aSymbol );
    1994             : 
    1995         571 :     if (!bAutomatic)
    1996             :     {
    1997         469 :         if ( nLang != LANGUAGE_SYSTEM )
    1998             :         {
    1999             :             //  '-' sign and language code in hex:
    2000         453 :             aFormatCode.append("-" + OUString::number(sal_Int32(nLang), 16).toAsciiUpperCase());
    2001             :         }
    2002             : 
    2003         469 :         aFormatCode.append( ']' );    // end of "new" currency symbol
    2004         571 :     }
    2005         571 : }
    2006             : 
    2007         878 : void SvXMLNumFormatContext::AddNfKeyword( sal_uInt16 nIndex )
    2008             : {
    2009         878 :     SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
    2010         878 :     if (!pFormatter)
    2011         878 :         return;
    2012             : 
    2013         878 :     if ( nIndex == NF_KEY_G || nIndex == NF_KEY_GG || nIndex == NF_KEY_GGG )
    2014           2 :         bHasEra = true;
    2015             : 
    2016         878 :     if ( nIndex == NF_KEY_NNNN )
    2017             :     {
    2018           5 :         nIndex = NF_KEY_NNN;
    2019           5 :         bHasLongDoW = true;         // to remove string constant with separator
    2020             :     }
    2021             : 
    2022         878 :     OUString sKeyword = pFormatter->GetKeyword( nFormatLang, nIndex );
    2023             : 
    2024         878 :     if ( nIndex == NF_KEY_H  || nIndex == NF_KEY_HH  ||
    2025         770 :          nIndex == NF_KEY_MI || nIndex == NF_KEY_MMI ||
    2026         638 :          nIndex == NF_KEY_S  || nIndex == NF_KEY_SS )
    2027             :     {
    2028         319 :         if ( !bTruncate && !bHasDateTime )
    2029             :         {
    2030             :             //  with truncate-on-overflow = false, add "[]" to first time part
    2031          12 :             aFormatCode.append("[" + sKeyword + "]");
    2032             :         }
    2033             :         else
    2034             :         {
    2035         307 :             aFormatCode.append( sKeyword );
    2036             :         }
    2037         319 :         bHasDateTime = true;
    2038             :     }
    2039             :     else
    2040             :     {
    2041         559 :         aFormatCode.append( sKeyword );
    2042             :     }
    2043             :     //  collect the date elements that the format contains, to recognize default date formats
    2044         878 :     switch ( nIndex )
    2045             :     {
    2046           7 :         case NF_KEY_NN:     eDateDOW = XML_DEA_SHORT;       break;
    2047             :         case NF_KEY_NNN:
    2048           5 :         case NF_KEY_NNNN:   eDateDOW = XML_DEA_LONG;        break;
    2049          97 :         case NF_KEY_D:      eDateDay = XML_DEA_SHORT;       break;
    2050          68 :         case NF_KEY_DD:     eDateDay = XML_DEA_LONG;        break;
    2051          52 :         case NF_KEY_M:      eDateMonth = XML_DEA_SHORT;     break;
    2052          60 :         case NF_KEY_MM:     eDateMonth = XML_DEA_LONG;      break;
    2053          60 :         case NF_KEY_MMM:    eDateMonth = XML_DEA_TEXTSHORT; break;
    2054          14 :         case NF_KEY_MMMM:   eDateMonth = XML_DEA_TEXTLONG;  break;
    2055          59 :         case NF_KEY_YY:     eDateYear = XML_DEA_SHORT;      break;
    2056          97 :         case NF_KEY_YYYY:   eDateYear = XML_DEA_LONG;       break;
    2057          77 :         case NF_KEY_H:      eDateHours = XML_DEA_SHORT;     break;
    2058          31 :         case NF_KEY_HH:     eDateHours = XML_DEA_LONG;      break;
    2059           0 :         case NF_KEY_MI:     eDateMins = XML_DEA_SHORT;      break;
    2060         132 :         case NF_KEY_MMI:    eDateMins = XML_DEA_LONG;       break;
    2061           0 :         case NF_KEY_S:      eDateSecs = XML_DEA_SHORT;      break;
    2062          79 :         case NF_KEY_SS:     eDateSecs = XML_DEA_LONG;       break;
    2063             :         case NF_KEY_AP:
    2064          36 :         case NF_KEY_AMPM:   break;          // AM/PM may or may not be in date/time formats -> ignore by itself
    2065             :         default:
    2066           4 :             bDateNoDefault = true;      // any other element -> no default format
    2067         878 :     }
    2068             : }
    2069             : 
    2070           5 : static bool lcl_IsAtEnd( OUStringBuffer& rBuffer, const OUString& rToken )
    2071             : {
    2072           5 :     sal_Int32 nBufLen = rBuffer.getLength();
    2073           5 :     sal_Int32 nTokLen = rToken.getLength();
    2074             : 
    2075           5 :     if ( nTokLen > nBufLen )
    2076           0 :         return false;
    2077             : 
    2078           5 :     sal_Int32 nStartPos = nBufLen - nTokLen;
    2079          20 :     for ( sal_Int32 nTokPos = 0; nTokPos < nTokLen; nTokPos++ )
    2080          15 :         if ( rToken[ nTokPos ] != rBuffer[nStartPos + nTokPos] )
    2081           0 :             return false;
    2082             : 
    2083           5 :     return true;
    2084             : }
    2085             : 
    2086           5 : bool SvXMLNumFormatContext::ReplaceNfKeyword( sal_uInt16 nOld, sal_uInt16 nNew )
    2087             : {
    2088             :     //  replaces one keyword with another if it is found at the end of the code
    2089             : 
    2090           5 :     SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
    2091           5 :     if (!pFormatter)
    2092           0 :         return false;
    2093             : 
    2094           5 :     OUString sOldStr = pFormatter->GetKeyword( nFormatLang, nOld );
    2095           5 :     if ( lcl_IsAtEnd( aFormatCode, sOldStr ) )
    2096             :     {
    2097             :         // remove old keyword
    2098           5 :         aFormatCode.setLength( aFormatCode.getLength() - sOldStr.getLength() );
    2099             : 
    2100             :         // add new keyword
    2101           5 :         OUString sNewStr = pFormatter->GetKeyword( nFormatLang, nNew );
    2102           5 :         aFormatCode.append( sNewStr );
    2103             : 
    2104           5 :         return true;    // changed
    2105             :     }
    2106           0 :     return false;       // not found
    2107             : }
    2108             : 
    2109         636 : void SvXMLNumFormatContext::AddCondition( const sal_Int32 nIndex )
    2110             : {
    2111         636 :     OUString rApplyName = aMyConditions[nIndex].sMapName;
    2112        1272 :     OUString rCondition = aMyConditions[nIndex].sCondition;
    2113         636 :     SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
    2114         636 :     sal_uInt32 l_nKey = pData->GetKeyForName( rApplyName );
    2115        1272 :     OUString sValue("value()");        //! define constant
    2116         636 :     sal_Int32 nValLen = sValue.getLength();
    2117             : 
    2118        2544 :     if ( pFormatter && l_nKey != NUMBERFORMAT_ENTRY_NOT_FOUND &&
    2119        2544 :             rCondition.copy( 0, nValLen ) == sValue )
    2120             :     {
    2121             :         //! test for valid conditions
    2122             :         //! test for default conditions
    2123             : 
    2124         636 :         OUString sRealCond = rCondition.copy( nValLen, rCondition.getLength() - nValLen );
    2125         636 :         bool bDefaultCond = false;
    2126             : 
    2127             :         //! collect all conditions first and adjust default to >=0, >0 or <0 depending on count
    2128             :         //! allow blanks in conditions
    2129         636 :         if ( aConditions.isEmpty() && aMyConditions.size() == 1 && sRealCond == ">=0" )
    2130         381 :             bDefaultCond = true;
    2131             : 
    2132         636 :         if ( nType == XML_TOK_STYLES_TEXT_STYLE && nIndex == 2 )
    2133             :         {
    2134             :             //  The third condition in a number format with a text part can only be
    2135             :             //  "all other numbers", the condition string must be empty.
    2136          67 :             bDefaultCond = true;
    2137             :         }
    2138             : 
    2139         636 :         if (!bDefaultCond)
    2140             :         {
    2141             :             // Convert != to <>
    2142         188 :             sal_Int32 nPos = sRealCond.indexOf( "!=" );
    2143         188 :             if ( nPos >= 0 )
    2144             :             {
    2145           2 :                 sRealCond = sRealCond.replaceAt( nPos, 2, "<>" );
    2146             :             }
    2147             : 
    2148         188 :             nPos = sRealCond.indexOf( '.' );
    2149         188 :             if ( nPos >= 0 )
    2150             :             {
    2151             :                 // #i8026# #103991# localize decimal separator
    2152           0 :                 const OUString& rDecSep = GetLocaleData().getNumDecimalSep();
    2153           0 :                 if ( rDecSep.getLength() > 1 || rDecSep[0] != '.' )
    2154             :                 {
    2155           0 :                     sRealCond = sRealCond.replaceAt( nPos, 1, rDecSep );
    2156             :                 }
    2157             :             }
    2158         188 :             aConditions.append("[" + sRealCond + "]");
    2159             :         }
    2160             : 
    2161         636 :         const SvNumberformat* pFormat = pFormatter->GetEntry(l_nKey);
    2162         636 :         if ( pFormat )
    2163         636 :             aConditions.append( OUString( pFormat->GetFormatstring() ) );
    2164             : 
    2165         636 :         aConditions.append( ';' );
    2166         636 :     }
    2167         636 : }
    2168             : 
    2169         636 : void SvXMLNumFormatContext::AddCondition( const OUString& rCondition, const OUString& rApplyName )
    2170             : {
    2171         636 :     MyCondition aCondition;
    2172         636 :     aCondition.sCondition = rCondition;
    2173         636 :     aCondition.sMapName = rApplyName;
    2174         636 :     aMyConditions.push_back(aCondition);
    2175         636 : }
    2176             : 
    2177         305 : void SvXMLNumFormatContext::AddColor( sal_uInt32 const nColor )
    2178             : {
    2179         305 :     SvNumberFormatter* pFormatter = pData->GetNumberFormatter();
    2180         305 :     if (!pFormatter)
    2181         305 :         return;
    2182             : 
    2183         305 :     OUStringBuffer aColName;
    2184        1469 :     for ( sal_uInt16 i=0; i<XML_NUMF_COLORCOUNT; i++ )
    2185        1469 :         if (nColor == aNumFmtStdColors[i])
    2186             :         {
    2187         305 :             aColName = OUString( pFormatter->GetKeyword( nFormatLang, sal::static_int_cast< sal_uInt16 >(NF_KEY_FIRSTCOLOR + i) ) );
    2188         305 :             break;
    2189             :         }
    2190             : 
    2191         305 :     if ( !aColName.isEmpty() )
    2192             :     {
    2193         305 :         aColName.insert( 0, '[' );
    2194         305 :         aColName.append( ']' );
    2195         305 :         aFormatCode.insert( 0, aColName.makeStringAndClear() );
    2196         305 :     }
    2197             : }
    2198             : 
    2199         523 : void SvXMLNumFormatContext::UpdateCalendar( const OUString& rNewCalendar )
    2200             : {
    2201         523 :     if ( rNewCalendar != sCalendar )
    2202             :     {
    2203           2 :         sCalendar = rNewCalendar;
    2204           2 :         if ( !sCalendar.isEmpty() )
    2205             :         {
    2206           2 :             aFormatCode.appendAscii( "[~" );            // intro for calendar code
    2207           2 :             aFormatCode.append( sCalendar );
    2208           2 :             aFormatCode.append( ']' );    // end of "new" currency symbolcalendar code
    2209             :         }
    2210             :     }
    2211         523 : }
    2212             : 
    2213          16 : bool SvXMLNumFormatContext::IsSystemLanguage()
    2214             : {
    2215          16 :     return nFormatLang == LANGUAGE_SYSTEM;
    2216             : }
    2217             : 
    2218             : 
    2219             : //  SvXMLNumFmtHelper
    2220             : 
    2221             : 
    2222        1067 : SvXMLNumFmtHelper::SvXMLNumFmtHelper(
    2223             :     const uno::Reference<util::XNumberFormatsSupplier>& rSupp,
    2224             :     const uno::Reference<uno::XComponentContext>& rxContext )
    2225             : {
    2226             :     DBG_ASSERT( rxContext.is(), "got no service manager" );
    2227             : 
    2228        1067 :     SvNumberFormatter* pFormatter = NULL;
    2229             :     SvNumberFormatsSupplierObj* pObj =
    2230        1067 :                     SvNumberFormatsSupplierObj::getImplementation( rSupp );
    2231        1067 :     if (pObj)
    2232        1067 :         pFormatter = pObj->GetNumberFormatter();
    2233             : 
    2234        1067 :     pData = new SvXMLNumImpData( pFormatter, rxContext );
    2235        1067 : }
    2236             : 
    2237         222 : SvXMLNumFmtHelper::SvXMLNumFmtHelper(
    2238             :     SvNumberFormatter* pNumberFormatter,
    2239             :     const uno::Reference<uno::XComponentContext>& rxContext )
    2240             : {
    2241             :     DBG_ASSERT( rxContext.is(), "got no service manager" );
    2242             : 
    2243         222 :     pData = new SvXMLNumImpData( pNumberFormatter, rxContext );
    2244         222 : }
    2245             : 
    2246        1289 : SvXMLNumFmtHelper::~SvXMLNumFmtHelper()
    2247             : {
    2248             :     //  remove temporary (volatile) formats from NumberFormatter
    2249        1289 :     pData->RemoveVolatileFormats();
    2250             : 
    2251        1289 :     delete pData;
    2252        1289 : }
    2253             : 
    2254       21802 : SvXMLStyleContext*  SvXMLNumFmtHelper::CreateChildContext( SvXMLImport& rImport,
    2255             :                 sal_uInt16 nPrefix, const OUString& rLocalName,
    2256             :                 const uno::Reference<xml::sax::XAttributeList>& xAttrList,
    2257             :                 SvXMLStylesContext& rStyles )
    2258             : {
    2259       21802 :     SvXMLStyleContext* pContext = NULL;
    2260             : 
    2261       21802 :     const SvXMLTokenMap& rTokenMap = pData->GetStylesElemTokenMap();
    2262       21802 :     sal_uInt16 nToken = rTokenMap.Get( nPrefix, rLocalName );
    2263       21802 :     switch (nToken)
    2264             :     {
    2265             :         case XML_TOK_STYLES_NUMBER_STYLE:
    2266             :         case XML_TOK_STYLES_CURRENCY_STYLE:
    2267             :         case XML_TOK_STYLES_PERCENTAGE_STYLE:
    2268             :         case XML_TOK_STYLES_DATE_STYLE:
    2269             :         case XML_TOK_STYLES_TIME_STYLE:
    2270             :         case XML_TOK_STYLES_BOOLEAN_STYLE:
    2271             :         case XML_TOK_STYLES_TEXT_STYLE:
    2272             :             pContext = new SvXMLNumFormatContext( rImport, nPrefix, rLocalName,
    2273        1944 :                                                     pData, nToken, xAttrList, rStyles );
    2274        1944 :             break;
    2275             :     }
    2276             : 
    2277             :     // return NULL if not a data style, caller must handle other elements
    2278       21802 :     return pContext;
    2279             : }
    2280             : 
    2281        2967 : const SvXMLTokenMap& SvXMLNumFmtHelper::GetStylesElemTokenMap()
    2282             : {
    2283        2967 :     return pData->GetStylesElemTokenMap();
    2284             : }
    2285             : 
    2286             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11