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