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