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