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