Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <comphelper/string.hxx>
30 : : #include <svl/zforlist.hxx>
31 : : #include <svl/zformat.hxx>
32 : : #include <svl/numuno.hxx>
33 : : #include <i18npool/mslangid.hxx>
34 : : #include <tools/debug.hxx>
35 : : #include <rtl/math.hxx>
36 : : #include <unotools/calendarwrapper.hxx>
37 : : #include <unotools/charclass.hxx>
38 : : #include <com/sun/star/lang/Locale.hpp>
39 : : #include <rtl/ustrbuf.hxx>
40 : : #include <tools/color.hxx>
41 : : #include <sax/tools/converter.hxx>
42 : :
43 : : #include <com/sun/star/i18n/NativeNumberXmlAttributes.hpp>
44 : :
45 : : #include <xmloff/xmlnumfe.hxx>
46 : : #include "xmloff/xmlnmspe.hxx"
47 : : #include <xmloff/attrlist.hxx>
48 : : #include <xmloff/nmspmap.hxx>
49 : : #include <xmloff/families.hxx>
50 : : #include <xmloff/xmlnumfi.hxx> // SvXMLNumFmtDefaults
51 : :
52 : : #include <svl/nfsymbol.hxx>
53 : : #include <xmloff/xmltoken.hxx>
54 : : #include <xmloff/xmlexp.hxx>
55 : :
56 : : #include <set>
57 : : #include <boost/ptr_container/ptr_vector.hpp>
58 : :
59 : : using ::rtl::OUString;
60 : : using ::rtl::OUStringBuffer;
61 : :
62 : : using namespace ::com::sun::star;
63 : : using namespace ::xmloff::token;
64 : : using namespace ::svt;
65 : :
66 : : //-------------------------------------------------------------------------
67 : :
68 : : #define XMLNUM_MAX_PARTS 3
69 : :
70 : : //-------------------------------------------------------------------------
71 : :
72 : : struct LessuInt32
73 : : {
74 : 498 : sal_Bool operator() (const sal_uInt32 rValue1, const sal_uInt32 rValue2) const
75 : : {
76 : 498 : return rValue1 < rValue2;
77 : : }
78 : : };
79 : :
80 : : typedef std::set< sal_uInt32, LessuInt32 > SvXMLuInt32Set;
81 : :
82 : : class SvXMLNumUsedList_Impl
83 : : {
84 : : SvXMLuInt32Set aUsed;
85 : : SvXMLuInt32Set aWasUsed;
86 : : SvXMLuInt32Set::iterator aCurrentUsedPos;
87 : : sal_uInt32 nUsedCount;
88 : : sal_uInt32 nWasUsedCount;
89 : :
90 : : public:
91 : : SvXMLNumUsedList_Impl();
92 : : ~SvXMLNumUsedList_Impl();
93 : :
94 : : void SetUsed( sal_uInt32 nKey );
95 : : sal_Bool IsUsed( sal_uInt32 nKey ) const;
96 : : sal_Bool IsWasUsed( sal_uInt32 nKey ) const;
97 : : void Export();
98 : :
99 : : sal_Bool GetFirstUsed(sal_uInt32& nKey);
100 : : sal_Bool GetNextUsed(sal_uInt32& nKey);
101 : :
102 : : void GetWasUsed(uno::Sequence<sal_Int32>& rWasUsed);
103 : : void SetWasUsed(const uno::Sequence<sal_Int32>& rWasUsed);
104 : : };
105 : :
106 : : //-------------------------------------------------------------------------
107 : :
108 : 0 : struct SvXMLEmbeddedTextEntry
109 : : {
110 : : sal_uInt16 nSourcePos; // position in NumberFormat (to skip later)
111 : : sal_Int32 nFormatPos; // resulting position in embedded-text element
112 : : rtl::OUString aText;
113 : :
114 : 0 : SvXMLEmbeddedTextEntry( sal_uInt16 nSP, sal_Int32 nFP, const rtl::OUString& rT ) :
115 : 0 : nSourcePos(nSP), nFormatPos(nFP), aText(rT) {}
116 : : };
117 : :
118 : 66 : class SvXMLEmbeddedTextEntryArr : public boost::ptr_vector<SvXMLEmbeddedTextEntry> {};
119 : :
120 : : //-------------------------------------------------------------------------
121 : :
122 : : //
123 : : //! SvXMLNumUsedList_Impl should be optimized!
124 : : //
125 : :
126 : 489 : SvXMLNumUsedList_Impl::SvXMLNumUsedList_Impl() :
127 : : nUsedCount(0),
128 [ + - ][ + - ]: 489 : nWasUsedCount(0)
129 : : {
130 : 489 : }
131 : :
132 : 489 : SvXMLNumUsedList_Impl::~SvXMLNumUsedList_Impl()
133 : : {
134 : 489 : }
135 : :
136 : 138 : void SvXMLNumUsedList_Impl::SetUsed( sal_uInt32 nKey )
137 : : {
138 [ + + ]: 138 : if ( !IsWasUsed(nKey) )
139 : : {
140 [ + - ]: 83 : std::pair<SvXMLuInt32Set::iterator, bool> aPair = aUsed.insert( nKey );
141 [ + + ]: 83 : if (aPair.second)
142 : 83 : nUsedCount++;
143 : : }
144 : 138 : }
145 : :
146 : 67 : sal_Bool SvXMLNumUsedList_Impl::IsUsed( sal_uInt32 nKey ) const
147 : : {
148 [ + - ]: 67 : SvXMLuInt32Set::const_iterator aItr = aUsed.find(nKey);
149 [ + - ]: 67 : return (aItr != aUsed.end());
150 : : }
151 : :
152 : 201 : sal_Bool SvXMLNumUsedList_Impl::IsWasUsed( sal_uInt32 nKey ) const
153 : : {
154 [ + - ]: 201 : SvXMLuInt32Set::const_iterator aItr = aWasUsed.find(nKey);
155 [ + - ]: 201 : return (aItr != aWasUsed.end());
156 : : }
157 : :
158 : 233 : void SvXMLNumUsedList_Impl::Export()
159 : : {
160 : 233 : SvXMLuInt32Set::const_iterator aItr = aUsed.begin();
161 [ + - ][ + + ]: 262 : while (aItr != aUsed.end())
162 : : {
163 [ + - ][ + - ]: 29 : std::pair<SvXMLuInt32Set::const_iterator, bool> aPair = aWasUsed.insert( *aItr );
164 [ + - ]: 29 : if (aPair.second)
165 : 29 : nWasUsedCount++;
166 [ + - ]: 29 : ++aItr;
167 : : }
168 : 233 : aUsed.clear();
169 : 233 : nUsedCount = 0;
170 : 233 : }
171 : :
172 : 233 : sal_Bool SvXMLNumUsedList_Impl::GetFirstUsed(sal_uInt32& nKey)
173 : : {
174 : 233 : sal_Bool bRet(sal_False);
175 : 233 : aCurrentUsedPos = aUsed.begin();
176 [ + + ]: 233 : if(nUsedCount)
177 : : {
178 : : DBG_ASSERT(aCurrentUsedPos != aUsed.end(), "something went wrong");
179 : 15 : nKey = *aCurrentUsedPos;
180 : 15 : bRet = sal_True;
181 : : }
182 : 233 : return bRet;
183 : : }
184 : :
185 : 29 : sal_Bool SvXMLNumUsedList_Impl::GetNextUsed(sal_uInt32& nKey)
186 : : {
187 : 29 : sal_Bool bRet(sal_False);
188 [ + - ][ + - ]: 29 : if (aCurrentUsedPos != aUsed.end())
189 : : {
190 : 29 : ++aCurrentUsedPos;
191 [ + + ][ + - ]: 29 : if (aCurrentUsedPos != aUsed.end())
192 : : {
193 : 14 : nKey = *aCurrentUsedPos;
194 : 14 : bRet = sal_True;
195 : : }
196 : : }
197 : 29 : return bRet;
198 : : }
199 : :
200 : 50 : void SvXMLNumUsedList_Impl::GetWasUsed(uno::Sequence<sal_Int32>& rWasUsed)
201 : : {
202 : 50 : rWasUsed.realloc(nWasUsedCount);
203 : 50 : sal_Int32* pWasUsed = rWasUsed.getArray();
204 [ + - ]: 50 : if (pWasUsed)
205 : : {
206 : 50 : SvXMLuInt32Set::const_iterator aItr = aWasUsed.begin();
207 [ + - ][ + + ]: 70 : while (aItr != aWasUsed.end())
208 : : {
209 [ + - ]: 20 : *pWasUsed = *aItr;
210 [ + - ]: 20 : ++aItr;
211 : 20 : ++pWasUsed;
212 : : }
213 : : }
214 : 50 : }
215 : :
216 : 25 : void SvXMLNumUsedList_Impl::SetWasUsed(const uno::Sequence<sal_Int32>& rWasUsed)
217 : : {
218 : : DBG_ASSERT(nWasUsedCount == 0, "WasUsed should be empty");
219 : 25 : sal_Int32 nCount(rWasUsed.getLength());
220 : 25 : const sal_Int32* pWasUsed = rWasUsed.getConstArray();
221 [ + + ]: 33 : for (sal_uInt16 i = 0; i < nCount; i++, pWasUsed++)
222 : : {
223 [ + - ]: 8 : std::pair<SvXMLuInt32Set::const_iterator, bool> aPair = aWasUsed.insert( *pWasUsed );
224 [ + - ]: 8 : if (aPair.second)
225 : 8 : nWasUsedCount++;
226 : : }
227 : 25 : }
228 : :
229 : : //-------------------------------------------------------------------------
230 : :
231 : 489 : SvXMLNumFmtExport::SvXMLNumFmtExport(
232 : : SvXMLExport& rExp,
233 : : const uno::Reference< util::XNumberFormatsSupplier >& rSupp ) :
234 : : rExport( rExp ),
235 : : sPrefix( OUString("N") ),
236 : : pFormatter( NULL ),
237 : : pCharClass( NULL ),
238 : 489 : pLocaleData( NULL )
239 : : {
240 : : // supplier must be SvNumberFormatsSupplierObj
241 : : SvNumberFormatsSupplierObj* pObj =
242 [ + - ]: 489 : SvNumberFormatsSupplierObj::getImplementation( rSupp );
243 [ + - ]: 489 : if (pObj)
244 [ + - ]: 489 : pFormatter = pObj->GetNumberFormatter();
245 : :
246 [ + - ]: 489 : if ( pFormatter )
247 : : {
248 : : pCharClass = new CharClass( pFormatter->GetServiceManager(),
249 [ + - ][ + - ]: 489 : pFormatter->GetLocale() );
[ + - ]
250 : : pLocaleData = new LocaleDataWrapper( pFormatter->GetServiceManager(),
251 [ + - ][ + - ]: 489 : pFormatter->GetLocale() );
[ + - ]
252 : : }
253 : : else
254 : : {
255 [ # # ][ # # ]: 0 : lang::Locale aLocale( MsLangId::convertLanguageToLocale( MsLangId::getSystemLanguage() ) );
256 : :
257 [ # # ][ # # ]: 0 : pCharClass = new CharClass( rExport.getServiceFactory(), aLocale );
[ # # ]
258 [ # # ][ # # ]: 0 : pLocaleData = new LocaleDataWrapper( rExport.getServiceFactory(), aLocale );
[ # # ]
259 : : }
260 : :
261 [ + - ][ + - ]: 489 : pUsedList = new SvXMLNumUsedList_Impl;
262 : 489 : }
263 : :
264 : 0 : SvXMLNumFmtExport::SvXMLNumFmtExport(
265 : : SvXMLExport& rExp,
266 : : const ::com::sun::star::uno::Reference<
267 : : ::com::sun::star::util::XNumberFormatsSupplier >& rSupp,
268 : : const rtl::OUString& rPrefix ) :
269 : : rExport( rExp ),
270 : : sPrefix( rPrefix ),
271 : : pFormatter( NULL ),
272 : : pCharClass( NULL ),
273 : 0 : pLocaleData( NULL )
274 : : {
275 : : // supplier must be SvNumberFormatsSupplierObj
276 : : SvNumberFormatsSupplierObj* pObj =
277 [ # # ]: 0 : SvNumberFormatsSupplierObj::getImplementation( rSupp );
278 [ # # ]: 0 : if (pObj)
279 [ # # ]: 0 : pFormatter = pObj->GetNumberFormatter();
280 : :
281 [ # # ]: 0 : if ( pFormatter )
282 : : {
283 : : pCharClass = new CharClass( pFormatter->GetServiceManager(),
284 [ # # ][ # # ]: 0 : pFormatter->GetLocale() );
[ # # ]
285 : : pLocaleData = new LocaleDataWrapper( pFormatter->GetServiceManager(),
286 [ # # ][ # # ]: 0 : pFormatter->GetLocale() );
[ # # ]
287 : : }
288 : : else
289 : : {
290 [ # # ][ # # ]: 0 : lang::Locale aLocale( MsLangId::convertLanguageToLocale( MsLangId::getSystemLanguage() ) );
291 : :
292 [ # # ][ # # ]: 0 : pCharClass = new CharClass( rExport.getServiceFactory(), aLocale );
[ # # ]
293 [ # # ][ # # ]: 0 : pLocaleData = new LocaleDataWrapper( rExport.getServiceFactory(), aLocale );
[ # # ]
294 : : }
295 : :
296 [ # # ][ # # ]: 0 : pUsedList = new SvXMLNumUsedList_Impl;
297 : 0 : }
298 : :
299 : 489 : SvXMLNumFmtExport::~SvXMLNumFmtExport()
300 : : {
301 [ + - ]: 489 : delete pUsedList;
302 [ + - ][ + - ]: 489 : delete pLocaleData;
303 [ + - ][ + - ]: 489 : delete pCharClass;
304 [ - + ]: 978 : }
305 : :
306 : : //-------------------------------------------------------------------------
307 : :
308 : : //
309 : : // helper methods
310 : : //
311 : :
312 : 104 : OUString lcl_CreateStyleName( sal_Int32 nKey, sal_Int32 nPart, sal_Bool bDefPart, const rtl::OUString& rPrefix )
313 : : {
314 : 104 : OUStringBuffer aFmtName( 10L );
315 [ + - ]: 104 : aFmtName.append( rPrefix );
316 [ + - ]: 104 : aFmtName.append( nKey );
317 [ + + ]: 104 : if (!bDefPart)
318 : : {
319 [ + - ]: 8 : aFmtName.append( (sal_Unicode)'P' );
320 [ + - ]: 8 : aFmtName.append( nPart );
321 : : }
322 [ + - ]: 104 : return aFmtName.makeStringAndClear();
323 : : }
324 : :
325 : 26 : void SvXMLNumFmtExport::AddCalendarAttr_Impl( const OUString& rCalendar )
326 : : {
327 [ - + ]: 26 : if ( !rCalendar.isEmpty() )
328 : : {
329 : 0 : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_CALENDAR, rCalendar );
330 : : }
331 : 26 : }
332 : :
333 : 10 : void SvXMLNumFmtExport::AddTextualAttr_Impl( sal_Bool bText )
334 : : {
335 [ + + ]: 10 : if ( bText ) // non-textual
336 : : {
337 : 2 : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TEXTUAL, XML_TRUE );
338 : : }
339 : 10 : }
340 : :
341 : 26 : void SvXMLNumFmtExport::AddStyleAttr_Impl( sal_Bool bLong )
342 : : {
343 [ + - ]: 26 : if ( bLong ) // short is default
344 : : {
345 : 26 : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_STYLE, XML_LONG );
346 : : }
347 : 26 : }
348 : :
349 : 41 : void SvXMLNumFmtExport::AddLanguageAttr_Impl( sal_Int32 nLang )
350 : : {
351 [ + + ]: 41 : if ( nLang != LANGUAGE_SYSTEM )
352 : : {
353 : 18 : OUString aLangStr, aCountryStr;
354 [ + - ]: 18 : MsLangId::convertLanguageToIsoNames( (LanguageType)nLang, aLangStr, aCountryStr );
355 : :
356 [ + - ]: 18 : if (!aLangStr.isEmpty())
357 [ + - ]: 18 : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_LANGUAGE, aLangStr );
358 [ + - ]: 18 : if (!aCountryStr.isEmpty())
359 [ + - ]: 18 : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_COUNTRY, aCountryStr );
360 : : }
361 : 41 : }
362 : :
363 : : //-------------------------------------------------------------------------
364 : :
365 : : //
366 : : // methods to write individual elements within a format
367 : : //
368 : :
369 : 20 : void SvXMLNumFmtExport::AddToTextElement_Impl( const OUString& rString )
370 : : {
371 : : // append to sTextContent, write element in FinishTextElement_Impl
372 : : // to avoid several text elements following each other
373 : :
374 : 20 : sTextContent.append( rString );
375 : 20 : }
376 : :
377 : 152 : void SvXMLNumFmtExport::FinishTextElement_Impl()
378 : : {
379 [ + + ]: 152 : if ( sTextContent.getLength() )
380 : : {
381 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_TEXT,
382 [ + - ]: 20 : sal_True, sal_False );
383 [ + - ][ + - ]: 20 : rExport.Characters( sTextContent.makeStringAndClear() );
[ + - ]
384 : : }
385 : 152 : }
386 : :
387 : 4 : void SvXMLNumFmtExport::WriteColorElement_Impl( const Color& rColor )
388 : : {
389 [ + - ]: 4 : FinishTextElement_Impl();
390 : :
391 : 4 : OUStringBuffer aColStr( 7 );
392 [ + - ]: 4 : ::sax::Converter::convertColor( aColStr, rColor.GetColor() );
393 : : rExport.AddAttribute( XML_NAMESPACE_FO, XML_COLOR,
394 [ + - ][ + - ]: 4 : aColStr.makeStringAndClear() );
395 : :
396 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE, XML_TEXT_PROPERTIES,
397 [ + - ][ + - ]: 4 : sal_True, sal_False );
398 : 4 : }
399 : :
400 : 8 : void SvXMLNumFmtExport::WriteCurrencyElement_Impl( const OUString& rString,
401 : : const OUString& rExt )
402 : : {
403 [ + - ]: 8 : FinishTextElement_Impl();
404 : :
405 [ + - ]: 8 : if ( !rExt.isEmpty() )
406 : : {
407 : 8 : sal_Int32 nLang = rExt.toInt32(16); // hex
408 [ + - ]: 8 : if ( nLang < 0 ) // extension string may contain "-" separator
409 : 8 : nLang = -nLang;
410 [ + - ]: 8 : AddLanguageAttr_Impl( nLang ); // adds to pAttrList
411 : : }
412 : :
413 : : SvXMLElementExport aElem( rExport,
414 : : XML_NAMESPACE_NUMBER, XML_CURRENCY_SYMBOL,
415 [ + - ]: 8 : sal_True, sal_False );
416 [ + - ][ + - ]: 8 : rExport.Characters( rString );
417 : 8 : }
418 : :
419 : 0 : void SvXMLNumFmtExport::WriteBooleanElement_Impl()
420 : : {
421 [ # # ]: 0 : FinishTextElement_Impl();
422 : :
423 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_BOOLEAN,
424 [ # # ][ # # ]: 0 : sal_True, sal_False );
425 : 0 : }
426 : :
427 : 0 : void SvXMLNumFmtExport::WriteTextContentElement_Impl()
428 : : {
429 [ # # ]: 0 : FinishTextElement_Impl();
430 : :
431 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_TEXT_CONTENT,
432 [ # # ][ # # ]: 0 : sal_True, sal_False );
433 : 0 : }
434 : :
435 : : // date elements
436 : :
437 : 8 : void SvXMLNumFmtExport::WriteDayElement_Impl( const OUString& rCalendar, sal_Bool bLong )
438 : : {
439 [ + - ]: 8 : FinishTextElement_Impl();
440 : :
441 [ + - ]: 8 : AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
442 [ + - ]: 8 : AddStyleAttr_Impl( bLong ); // adds to pAttrList
443 : :
444 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_DAY,
445 [ + - ][ + - ]: 8 : sal_True, sal_False );
446 : 8 : }
447 : :
448 : 10 : void SvXMLNumFmtExport::WriteMonthElement_Impl( const OUString& rCalendar, sal_Bool bLong, sal_Bool bText )
449 : : {
450 [ + - ]: 10 : FinishTextElement_Impl();
451 : :
452 [ + - ]: 10 : AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
453 [ + - ]: 10 : AddStyleAttr_Impl( bLong ); // adds to pAttrList
454 [ + - ]: 10 : AddTextualAttr_Impl( bText ); // adds to pAttrList
455 : :
456 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_MONTH,
457 [ + - ][ + - ]: 10 : sal_True, sal_False );
458 : 10 : }
459 : :
460 : 8 : void SvXMLNumFmtExport::WriteYearElement_Impl( const OUString& rCalendar, sal_Bool bLong )
461 : : {
462 [ + - ]: 8 : FinishTextElement_Impl();
463 : :
464 [ + - ]: 8 : AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
465 [ + - ]: 8 : AddStyleAttr_Impl( bLong ); // adds to pAttrList
466 : :
467 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_YEAR,
468 [ + - ][ + - ]: 8 : sal_True, sal_False );
469 : 8 : }
470 : :
471 : 0 : void SvXMLNumFmtExport::WriteEraElement_Impl( const OUString& rCalendar, sal_Bool bLong )
472 : : {
473 [ # # ]: 0 : FinishTextElement_Impl();
474 : :
475 [ # # ]: 0 : AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
476 [ # # ]: 0 : AddStyleAttr_Impl( bLong ); // adds to pAttrList
477 : :
478 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_ERA,
479 [ # # ][ # # ]: 0 : sal_True, sal_False );
480 : 0 : }
481 : :
482 : 0 : void SvXMLNumFmtExport::WriteDayOfWeekElement_Impl( const OUString& rCalendar, sal_Bool bLong )
483 : : {
484 [ # # ]: 0 : FinishTextElement_Impl();
485 : :
486 [ # # ]: 0 : AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
487 [ # # ]: 0 : AddStyleAttr_Impl( bLong ); // adds to pAttrList
488 : :
489 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_DAY_OF_WEEK,
490 [ # # ][ # # ]: 0 : sal_True, sal_False );
491 : 0 : }
492 : :
493 : 0 : void SvXMLNumFmtExport::WriteWeekElement_Impl( const OUString& rCalendar )
494 : : {
495 [ # # ]: 0 : FinishTextElement_Impl();
496 : :
497 [ # # ]: 0 : AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
498 : :
499 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_WEEK_OF_YEAR,
500 [ # # ][ # # ]: 0 : sal_True, sal_False );
501 : 0 : }
502 : :
503 : 0 : void SvXMLNumFmtExport::WriteQuarterElement_Impl( const OUString& rCalendar, sal_Bool bLong )
504 : : {
505 [ # # ]: 0 : FinishTextElement_Impl();
506 : :
507 [ # # ]: 0 : AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList
508 [ # # ]: 0 : AddStyleAttr_Impl( bLong ); // adds to pAttrList
509 : :
510 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_QUARTER,
511 [ # # ][ # # ]: 0 : sal_True, sal_False );
512 : 0 : }
513 : :
514 : : // time elements
515 : :
516 : 0 : void SvXMLNumFmtExport::WriteHoursElement_Impl( sal_Bool bLong )
517 : : {
518 [ # # ]: 0 : FinishTextElement_Impl();
519 : :
520 [ # # ]: 0 : AddStyleAttr_Impl( bLong ); // adds to pAttrList
521 : :
522 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_HOURS,
523 [ # # ][ # # ]: 0 : sal_True, sal_False );
524 : 0 : }
525 : :
526 : 0 : void SvXMLNumFmtExport::WriteMinutesElement_Impl( sal_Bool bLong )
527 : : {
528 [ # # ]: 0 : FinishTextElement_Impl();
529 : :
530 [ # # ]: 0 : AddStyleAttr_Impl( bLong ); // adds to pAttrList
531 : :
532 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_MINUTES,
533 [ # # ][ # # ]: 0 : sal_True, sal_False );
534 : 0 : }
535 : :
536 : 0 : void SvXMLNumFmtExport::WriteRepeatedElement_Impl( sal_Unicode nChar )
537 : : {
538 [ # # ]: 0 : FinishTextElement_Impl();
539 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_FILL_CHARACTER,
540 [ # # ]: 0 : sal_True, sal_False );
541 [ # # ][ # # ]: 0 : rExport.Characters( OUString::valueOf( nChar ) );
542 : 0 : }
543 : :
544 : 0 : void SvXMLNumFmtExport::WriteSecondsElement_Impl( sal_Bool bLong, sal_uInt16 nDecimals )
545 : : {
546 [ # # ]: 0 : FinishTextElement_Impl();
547 : :
548 [ # # ]: 0 : AddStyleAttr_Impl( bLong ); // adds to pAttrList
549 [ # # ]: 0 : if ( nDecimals > 0 )
550 : : {
551 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES,
552 [ # # ]: 0 : OUString::valueOf( (sal_Int32) nDecimals ) );
553 : : }
554 : :
555 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_SECONDS,
556 [ # # ][ # # ]: 0 : sal_True, sal_False );
557 : 0 : }
558 : :
559 : 0 : void SvXMLNumFmtExport::WriteAMPMElement_Impl()
560 : : {
561 [ # # ]: 0 : FinishTextElement_Impl();
562 : :
563 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_AM_PM,
564 [ # # ][ # # ]: 0 : sal_True, sal_False );
565 : 0 : }
566 : :
567 : : // numbers
568 : :
569 : 23 : void SvXMLNumFmtExport::WriteNumberElement_Impl(
570 : : sal_Int32 nDecimals, sal_Int32 nInteger,
571 : : const OUString& rDashStr, sal_Bool bVarDecimals,
572 : : sal_Bool bGrouping, sal_Int32 nTrailingThousands,
573 : : const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries )
574 : : {
575 [ + - ]: 23 : FinishTextElement_Impl();
576 : :
577 : : // decimals
578 [ + + ]: 23 : if ( nDecimals >= 0 ) // negative = automatic
579 : : {
580 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES,
581 [ + - ]: 10 : OUString::valueOf( nDecimals ) );
582 : : }
583 : :
584 : : // integer digits
585 [ + - ]: 23 : if ( nInteger >= 0 ) // negative = automatic
586 : : {
587 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS,
588 [ + - ]: 23 : OUString::valueOf( nInteger ) );
589 : : }
590 : :
591 : : // decimal replacement (dashes) or variable decimals (#)
592 [ + - ][ - + ]: 23 : if ( !rDashStr.isEmpty() || bVarDecimals )
[ - + ]
593 : : {
594 : : // variable decimals means an empty replacement string
595 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_REPLACEMENT,
596 [ # # ]: 0 : rDashStr );
597 : : }
598 : :
599 : : // (automatic) grouping separator
600 [ + + ]: 23 : if ( bGrouping )
601 : : {
602 [ + - ]: 10 : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TRUE );
603 : : }
604 : :
605 : : // display-factor if there are trailing thousands separators
606 [ - + ]: 23 : if ( nTrailingThousands )
607 : : {
608 : : // each separator character removes three digits
609 : 0 : double fFactor = ::rtl::math::pow10Exp( 1.0, 3 * nTrailingThousands );
610 : :
611 : 0 : OUStringBuffer aFactStr;
612 [ # # ]: 0 : ::sax::Converter::convertDouble( aFactStr, fFactor );
613 [ # # ][ # # ]: 0 : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DISPLAY_FACTOR, aFactStr.makeStringAndClear() );
614 : : }
615 : :
616 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_NUMBER,
617 [ + - ]: 23 : sal_True, sal_True );
618 : :
619 : : // number:embedded-text as child elements
620 : :
621 : 23 : sal_uInt16 nEntryCount = rEmbeddedEntries.size();
622 [ - + ]: 23 : for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++)
623 : : {
624 [ # # ]: 0 : const SvXMLEmbeddedTextEntry* pObj = &rEmbeddedEntries[nEntry];
625 : :
626 : : // position attribute
627 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_POSITION,
628 [ # # ]: 0 : OUString::valueOf( pObj->nFormatPos ) );
629 : : SvXMLElementExport aChildElem( rExport, XML_NAMESPACE_NUMBER, XML_EMBEDDED_TEXT,
630 [ # # ]: 0 : sal_True, sal_False );
631 : :
632 : : // text as element content
633 : 0 : rtl::OUString aContent( pObj->aText );
634 [ # # ][ # # ]: 0 : while ( nEntry+1 < nEntryCount && rEmbeddedEntries[nEntry+1].nFormatPos == pObj->nFormatPos )
[ # # ][ # # ]
635 : : {
636 : : // The array can contain several elements for the same position in the number
637 : : // (for example, literal text and space from underscores). They must be merged
638 : : // into a single embedded-text element.
639 [ # # ]: 0 : aContent += rEmbeddedEntries[nEntry+1].aText;
640 : 0 : ++nEntry;
641 : : }
642 [ # # ]: 0 : rExport.Characters( aContent );
643 [ # # ][ + - ]: 23 : }
644 : 23 : }
645 : :
646 : 0 : void SvXMLNumFmtExport::WriteScientificElement_Impl(
647 : : sal_Int32 nDecimals, sal_Int32 nInteger,
648 : : sal_Bool bGrouping, sal_Int32 nExp )
649 : : {
650 [ # # ]: 0 : FinishTextElement_Impl();
651 : :
652 : : // decimals
653 [ # # ]: 0 : if ( nDecimals >= 0 ) // negative = automatic
654 : : {
655 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES,
656 [ # # ]: 0 : OUString::valueOf( nDecimals ) );
657 : : }
658 : :
659 : : // integer digits
660 [ # # ]: 0 : if ( nInteger >= 0 ) // negative = automatic
661 : : {
662 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS,
663 [ # # ]: 0 : OUString::valueOf( nInteger ) );
664 : : }
665 : :
666 : : // (automatic) grouping separator
667 [ # # ]: 0 : if ( bGrouping )
668 : : {
669 [ # # ]: 0 : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TRUE );
670 : : }
671 : :
672 : : // exponent digits
673 [ # # ]: 0 : if ( nExp >= 0 )
674 : : {
675 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_EXPONENT_DIGITS,
676 [ # # ]: 0 : OUString::valueOf( nExp ) );
677 : : }
678 : :
679 : : SvXMLElementExport aElem( rExport,
680 : : XML_NAMESPACE_NUMBER, XML_SCIENTIFIC_NUMBER,
681 [ # # ][ # # ]: 0 : sal_True, sal_False );
682 : 0 : }
683 : :
684 : 0 : void SvXMLNumFmtExport::WriteFractionElement_Impl(
685 : : sal_Int32 nInteger, sal_Bool bGrouping,
686 : : sal_Int32 nNumerator, sal_Int32 nDenominator )
687 : : {
688 [ # # ]: 0 : FinishTextElement_Impl();
689 : :
690 : : // integer digits
691 [ # # ]: 0 : if ( nInteger >= 0 ) // negative = default (no integer part)
692 : : {
693 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS,
694 [ # # ]: 0 : OUString::valueOf( nInteger ) );
695 : : }
696 : :
697 : : // (automatic) grouping separator
698 [ # # ]: 0 : if ( bGrouping )
699 : : {
700 [ # # ]: 0 : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TRUE );
701 : : }
702 : :
703 : : // numerator digits
704 [ # # ]: 0 : if ( nNumerator >= 0 )
705 : : {
706 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_NUMERATOR_DIGITS,
707 [ # # ]: 0 : OUString::valueOf( nNumerator ) );
708 : : }
709 : :
710 : : // denominator digits
711 [ # # ]: 0 : if ( nDenominator >= 0 )
712 : : {
713 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_DENOMINATOR_DIGITS,
714 [ # # ]: 0 : OUString::valueOf( nDenominator ) );
715 : : }
716 : :
717 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_FRACTION,
718 [ # # ][ # # ]: 0 : sal_True, sal_False );
719 : 0 : }
720 : :
721 : : // mapping (condition)
722 : :
723 : 58 : void SvXMLNumFmtExport::WriteMapElement_Impl( sal_Int32 nOp, double fLimit,
724 : : sal_Int32 nKey, sal_Int32 nPart )
725 : : {
726 : 58 : FinishTextElement_Impl();
727 : :
728 [ + + ]: 58 : if ( nOp != NUMBERFORMAT_OP_NO )
729 : : {
730 : : // style namespace
731 : :
732 : 4 : OUStringBuffer aCondStr( 20L );
733 [ + - ]: 4 : aCondStr.appendAscii( "value()" ); //! define constant
734 [ - - - - : 4 : switch ( nOp )
- + - ]
735 : : {
736 [ # # ]: 0 : case NUMBERFORMAT_OP_EQ: aCondStr.append( (sal_Unicode) '=' ); break;
737 [ # # ]: 0 : case NUMBERFORMAT_OP_NE: aCondStr.appendAscii( "<>" ); break;
738 [ # # ]: 0 : case NUMBERFORMAT_OP_LT: aCondStr.append( (sal_Unicode) '<' ); break;
739 [ # # ]: 0 : case NUMBERFORMAT_OP_LE: aCondStr.appendAscii( "<=" ); break;
740 [ # # ]: 0 : case NUMBERFORMAT_OP_GT: aCondStr.append( (sal_Unicode) '>' ); break;
741 [ + - ]: 4 : case NUMBERFORMAT_OP_GE: aCondStr.appendAscii( ">=" ); break;
742 : : default:
743 : : OSL_FAIL("unknown operator");
744 : : }
745 : : ::rtl::math::doubleToUStringBuffer( aCondStr, fLimit,
746 : : rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
747 : 4 : '.', true );
748 : :
749 : : rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_CONDITION,
750 [ + - ][ + - ]: 4 : aCondStr.makeStringAndClear() );
751 : :
752 : : rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_APPLY_STYLE_NAME,
753 : : rExport.EncodeStyleName( lcl_CreateStyleName( nKey, nPart, sal_False,
754 [ + - ][ + - ]: 4 : sPrefix ) ) );
[ + - ]
755 : :
756 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE, XML_MAP,
757 [ + - ][ + - ]: 4 : sal_True, sal_False );
758 : : }
759 : 58 : }
760 : :
761 : : //-------------------------------------------------------------------------
762 : : // for old (automatic) currency formats: parse currency symbol from text
763 : :
764 : 0 : xub_StrLen lcl_FindSymbol( const String& sUpperStr, const String& sCurString )
765 : : {
766 : : // search for currency symbol
767 : : // Quoting as in ImpSvNumberformatScan::Symbol_Division
768 : :
769 : 0 : xub_StrLen nCPos = 0;
770 [ # # ]: 0 : while (nCPos != STRING_NOTFOUND)
771 : : {
772 : 0 : nCPos = sUpperStr.Search( sCurString, nCPos );
773 [ # # ]: 0 : if (nCPos != STRING_NOTFOUND)
774 : : {
775 : : // in Quotes?
776 : 0 : xub_StrLen nQ = SvNumberformat::GetQuoteEnd( sUpperStr, nCPos );
777 [ # # ]: 0 : if ( nQ == STRING_NOTFOUND )
778 : : {
779 : : // dm can be escaped as "dm or \d
780 : : sal_Unicode c;
781 [ # # ][ # # ]: 0 : if ( nCPos == 0 ||
[ # # ][ # # ]
782 : 0 : ((c = sUpperStr.GetChar(xub_StrLen(nCPos-1))) != '"'
783 : : && c != '\\') )
784 : : {
785 : 0 : return nCPos; // found
786 : : }
787 : : else
788 : 0 : nCPos++; // continue
789 : : }
790 : : else
791 : 0 : nCPos = nQ + 1; // continue after quote end
792 : : }
793 : : }
794 : 0 : return STRING_NOTFOUND; // not found
795 : : }
796 : :
797 : 0 : sal_Bool SvXMLNumFmtExport::WriteTextWithCurrency_Impl( const OUString& rString,
798 : : const ::com::sun::star::lang::Locale& rLocale )
799 : : {
800 : : // returns sal_True if currency element was written
801 : :
802 : 0 : sal_Bool bRet = sal_False;
803 : :
804 [ # # ]: 0 : LanguageType nLang = MsLangId::convertLocaleToLanguage( rLocale );
805 [ # # ]: 0 : pFormatter->ChangeIntl( nLang );
806 [ # # ][ # # ]: 0 : String sCurString, sDummy;
807 [ # # ]: 0 : pFormatter->GetCompatibilityCurrency( sCurString, sDummy );
808 : :
809 [ # # ]: 0 : pCharClass->setLocale( rLocale );
810 [ # # ][ # # ]: 0 : String sUpperStr = pCharClass->uppercase(rString);
811 [ # # ]: 0 : xub_StrLen nPos = lcl_FindSymbol( sUpperStr, sCurString );
812 [ # # ]: 0 : if ( nPos != STRING_NOTFOUND )
813 : : {
814 : 0 : sal_Int32 nLength = rString.getLength();
815 : 0 : sal_Int32 nCurLen = sCurString.Len();
816 : 0 : sal_Int32 nCont = nPos + nCurLen;
817 : :
818 : : // text before currency symbol
819 [ # # ]: 0 : if ( nPos > 0 )
820 [ # # ]: 0 : AddToTextElement_Impl( rString.copy( 0, nPos ) );
821 : :
822 : : // currency symbol (empty string -> default)
823 : 0 : OUString sEmpty;
824 [ # # ]: 0 : WriteCurrencyElement_Impl( sEmpty, sEmpty );
825 : 0 : bRet = sal_True;
826 : :
827 : : // text after currency symbol
828 [ # # ]: 0 : if ( nCont < nLength )
829 [ # # ]: 0 : AddToTextElement_Impl( rString.copy( nCont, nLength-nCont ) );
830 : : }
831 : : else
832 [ # # ]: 0 : AddToTextElement_Impl( rString ); // simple text
833 : :
834 [ # # ][ # # ]: 0 : return bRet; // sal_True: currency element written
[ # # ]
835 : : }
836 : :
837 : : //-------------------------------------------------------------------------
838 : :
839 : 0 : OUString lcl_GetDefaultCalendar( SvNumberFormatter* pFormatter, LanguageType nLang )
840 : : {
841 : : // get name of first non-gregorian calendar for the language
842 : :
843 : 0 : OUString aCalendar;
844 [ # # ]: 0 : CalendarWrapper* pCalendar = pFormatter->GetCalendar();
845 [ # # ]: 0 : if (pCalendar)
846 : : {
847 [ # # ]: 0 : lang::Locale aLocale( MsLangId::convertLanguageToLocale( nLang ) );
848 : :
849 [ # # ]: 0 : uno::Sequence<OUString> aCals = pCalendar->getAllCalendars( aLocale );
850 : 0 : sal_Int32 nCnt = aCals.getLength();
851 : 0 : sal_Bool bFound = sal_False;
852 [ # # ][ # # ]: 0 : for ( sal_Int32 j=0; j < nCnt && !bFound; j++ )
[ # # ]
853 : : {
854 [ # # ][ # # ]: 0 : if ( aCals[j] != "gregorian" )
855 : : {
856 [ # # ]: 0 : aCalendar = aCals[j];
857 : 0 : bFound = sal_True;
858 : : }
859 [ # # ]: 0 : }
860 : : }
861 : 0 : return aCalendar;
862 : : }
863 : :
864 : : //-------------------------------------------------------------------------
865 : :
866 : 20 : sal_Bool lcl_IsInEmbedded( const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries, sal_uInt16 nPos )
867 : : {
868 : 20 : sal_uInt16 nCount = rEmbeddedEntries.size();
869 [ - + ]: 20 : for (sal_uInt16 i=0; i<nCount; i++)
870 [ # # ]: 0 : if ( rEmbeddedEntries[i].nSourcePos == nPos )
871 : 0 : return sal_True;
872 : :
873 : 20 : return sal_False; // not found
874 : : }
875 : :
876 : 8 : sal_Bool lcl_IsDefaultDateFormat( const SvNumberformat& rFormat, sal_Bool bSystemDate, NfIndexTableOffset eBuiltIn )
877 : : {
878 : : // make an extra loop to collect date elements, to check if it is a default format
879 : : // before adding the automatic-order attribute
880 : :
881 : 8 : SvXMLDateElementAttributes eDateDOW = XML_DEA_NONE;
882 : 8 : SvXMLDateElementAttributes eDateDay = XML_DEA_NONE;
883 : 8 : SvXMLDateElementAttributes eDateMonth = XML_DEA_NONE;
884 : 8 : SvXMLDateElementAttributes eDateYear = XML_DEA_NONE;
885 : 8 : SvXMLDateElementAttributes eDateHours = XML_DEA_NONE;
886 : 8 : SvXMLDateElementAttributes eDateMins = XML_DEA_NONE;
887 : 8 : SvXMLDateElementAttributes eDateSecs = XML_DEA_NONE;
888 : 8 : sal_Bool bDateNoDefault = sal_False;
889 : :
890 : 8 : sal_uInt16 nPos = 0;
891 : 8 : sal_Bool bEnd = sal_False;
892 : 8 : short nLastType = 0;
893 [ + + ]: 56 : while (!bEnd)
894 : : {
895 : 48 : short nElemType = rFormat.GetNumForType( 0, nPos, sal_False );
896 [ + + - - : 48 : switch ( nElemType )
- + - + -
- - + - -
- - - - -
- ]
897 : : {
898 : : case 0:
899 [ - + ]: 8 : if ( nLastType == NF_SYMBOLTYPE_STRING )
900 : 0 : bDateNoDefault = sal_True; // text at the end -> no default date format
901 : 8 : bEnd = sal_True; // end of format reached
902 : 8 : break;
903 : : case NF_SYMBOLTYPE_STRING:
904 : : case NF_SYMBOLTYPE_DATESEP:
905 : : case NF_SYMBOLTYPE_TIMESEP:
906 : : case NF_SYMBOLTYPE_TIME100SECSEP:
907 : : // text is ignored, except at the end
908 : 16 : break;
909 : : // same mapping as in SvXMLNumFormatContext::AddNfKeyword:
910 : 0 : case NF_KEY_NN: eDateDOW = XML_DEA_SHORT; break;
911 : : case NF_KEY_NNN:
912 : 0 : case NF_KEY_NNNN: eDateDOW = XML_DEA_LONG; break;
913 : 0 : case NF_KEY_D: eDateDay = XML_DEA_SHORT; break;
914 : 8 : case NF_KEY_DD: eDateDay = XML_DEA_LONG; break;
915 : 0 : case NF_KEY_M: eDateMonth = XML_DEA_SHORT; break;
916 : 8 : case NF_KEY_MM: eDateMonth = XML_DEA_LONG; break;
917 : 0 : case NF_KEY_MMM: eDateMonth = XML_DEA_TEXTSHORT; break;
918 : 0 : case NF_KEY_MMMM: eDateMonth = XML_DEA_TEXTLONG; break;
919 : 0 : case NF_KEY_YY: eDateYear = XML_DEA_SHORT; break;
920 : 8 : case NF_KEY_YYYY: eDateYear = XML_DEA_LONG; break;
921 : 0 : case NF_KEY_H: eDateHours = XML_DEA_SHORT; break;
922 : 0 : case NF_KEY_HH: eDateHours = XML_DEA_LONG; break;
923 : 0 : case NF_KEY_MI: eDateMins = XML_DEA_SHORT; break;
924 : 0 : case NF_KEY_MMI: eDateMins = XML_DEA_LONG; break;
925 : 0 : case NF_KEY_S: eDateSecs = XML_DEA_SHORT; break;
926 : 0 : case NF_KEY_SS: eDateSecs = XML_DEA_LONG; break;
927 : : case NF_KEY_AP:
928 : 0 : case NF_KEY_AMPM: break; // AM/PM may or may not be in date/time formats -> ignore by itself
929 : : default:
930 : 0 : bDateNoDefault = sal_True; // any other element -> no default format
931 : : }
932 : 48 : nLastType = nElemType;
933 : 48 : ++nPos;
934 : : }
935 : :
936 [ - + ]: 8 : if ( bDateNoDefault )
937 : 0 : return sal_False; // additional elements
938 : : else
939 : : {
940 : : NfIndexTableOffset eFound = (NfIndexTableOffset) SvXMLNumFmtDefaults::GetDefaultDateFormat(
941 : 8 : eDateDOW, eDateDay, eDateMonth, eDateYear, eDateHours, eDateMins, eDateSecs, bSystemDate );
942 : :
943 : 8 : return ( eFound == eBuiltIn );
944 : : }
945 : : }
946 : :
947 : : //
948 : : // export one part (condition)
949 : : //
950 : :
951 : 33 : void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey,
952 : : sal_uInt16 nPart, sal_Bool bDefPart )
953 : : {
954 : : //! for the default part, pass the coditions from the other parts!
955 : :
956 : : //
957 : : // element name
958 : : //
959 : :
960 [ + - ]: 33 : NfIndexTableOffset eBuiltIn = pFormatter->GetIndexTableOffset( nKey );
961 : :
962 : 33 : short nFmtType = 0;
963 : 33 : bool bThousand = false;
964 : 33 : sal_uInt16 nPrecision = 0;
965 : 33 : sal_uInt16 nLeading = 0;
966 [ + - ]: 33 : rFormat.GetNumForInfo( nPart, nFmtType, bThousand, nPrecision, nLeading);
967 : 33 : nFmtType &= ~NUMBERFORMAT_DEFINED;
968 : :
969 : : // special treatment of builtin formats that aren't detected by normal parsing
970 : : // (the same formats that get the type set in SvNumberFormatter::ImpGenerateFormats)
971 [ + + ]: 33 : if ( eBuiltIn == NF_NUMBER_STANDARD )
972 : 13 : nFmtType = NUMBERFORMAT_NUMBER;
973 [ - + ]: 20 : else if ( eBuiltIn == NF_BOOLEAN )
974 : 0 : nFmtType = NUMBERFORMAT_LOGICAL;
975 [ - + ]: 20 : else if ( eBuiltIn == NF_TEXT )
976 : 0 : nFmtType = NUMBERFORMAT_TEXT;
977 : :
978 : : // #101606# An empty subformat is a valid number-style resulting in an
979 : : // empty display string for the condition of the subformat.
980 [ - + ][ # # ]: 33 : if ( nFmtType == NUMBERFORMAT_UNDEFINED && rFormat.GetNumForType( nPart,
[ - + ]
981 [ # # ]: 0 : 0, sal_False ) == 0 )
982 : 0 : nFmtType = 0;
983 : :
984 : 33 : XMLTokenEnum eType = XML_TOKEN_INVALID;
985 [ + - + + : 33 : switch ( nFmtType )
- - - - ]
986 : : {
987 : : // type is 0 if a format contains no recognized elements
988 : : // (like text only) - this is handled as a number-style.
989 : : case 0:
990 : : case NUMBERFORMAT_NUMBER:
991 : : case NUMBERFORMAT_SCIENTIFIC:
992 : : case NUMBERFORMAT_FRACTION:
993 : 15 : eType = XML_NUMBER_STYLE;
994 : 15 : break;
995 : : case NUMBERFORMAT_PERCENT:
996 : 0 : eType = XML_PERCENTAGE_STYLE;
997 : 0 : break;
998 : : case NUMBERFORMAT_CURRENCY:
999 : 8 : eType = XML_CURRENCY_STYLE;
1000 : 8 : break;
1001 : : case NUMBERFORMAT_DATE:
1002 : : case NUMBERFORMAT_DATETIME:
1003 : 10 : eType = XML_DATE_STYLE;
1004 : 10 : break;
1005 : : case NUMBERFORMAT_TIME:
1006 : 0 : eType = XML_TIME_STYLE;
1007 : 0 : break;
1008 : : case NUMBERFORMAT_TEXT:
1009 : 0 : eType = XML_TEXT_STYLE;
1010 : 0 : break;
1011 : : case NUMBERFORMAT_LOGICAL:
1012 : 0 : eType = XML_BOOLEAN_STYLE;
1013 : 0 : break;
1014 : : }
1015 : : DBG_ASSERT( eType != XML_TOKEN_INVALID, "unknown format type" );
1016 : :
1017 : 33 : OUString sAttrValue;
1018 : 33 : sal_Bool bUserDef = ( ( rFormat.GetType() & NUMBERFORMAT_DEFINED ) != 0 );
1019 : :
1020 : : //
1021 : : // common attributes for format
1022 : : //
1023 : :
1024 : : // format name (generated from key) - style namespace
1025 : : rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_NAME,
1026 [ + - ][ + - ]: 33 : lcl_CreateStyleName( nKey, nPart, bDefPart, sPrefix ) );
1027 : :
1028 : : // "volatile" attribute for styles used only in maps
1029 [ + + ]: 33 : if ( !bDefPart )
1030 [ + - ]: 4 : rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_VOLATILE, XML_TRUE );
1031 : :
1032 : : // language / country
1033 : 33 : LanguageType nLang = rFormat.GetLanguage();
1034 [ + - ]: 33 : AddLanguageAttr_Impl( nLang ); // adds to pAttrList
1035 : :
1036 : : // title (comment)
1037 : : // titles for builtin formats are not written
1038 [ + - ]: 33 : sAttrValue = rFormat.GetComment();
1039 [ # # ][ # # ]: 33 : if ( !sAttrValue.isEmpty() && bUserDef && bDefPart )
[ - + ][ - + ]
1040 : : {
1041 [ # # ]: 0 : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TITLE, sAttrValue );
1042 : : }
1043 : :
1044 : : // automatic ordering for currency and date formats
1045 : : // only used for some built-in formats
1046 : : sal_Bool bAutoOrder = ( eBuiltIn == NF_CURRENCY_1000INT || eBuiltIn == NF_CURRENCY_1000DEC2 ||
1047 : : eBuiltIn == NF_CURRENCY_1000INT_RED || eBuiltIn == NF_CURRENCY_1000DEC2_RED ||
1048 : : eBuiltIn == NF_CURRENCY_1000DEC2_DASHED ||
1049 : : eBuiltIn == NF_DATE_SYSTEM_SHORT || eBuiltIn == NF_DATE_SYSTEM_LONG ||
1050 : : eBuiltIn == NF_DATE_SYS_MMYY || eBuiltIn == NF_DATE_SYS_DDMMM ||
1051 : : eBuiltIn == NF_DATE_SYS_DDMMYYYY || eBuiltIn == NF_DATE_SYS_DDMMYY ||
1052 : : eBuiltIn == NF_DATE_SYS_DMMMYY || eBuiltIn == NF_DATE_SYS_DMMMYYYY ||
1053 : : eBuiltIn == NF_DATE_SYS_DMMMMYYYY || eBuiltIn == NF_DATE_SYS_NNDMMMYY ||
1054 : : eBuiltIn == NF_DATE_SYS_NNDMMMMYYYY || eBuiltIn == NF_DATE_SYS_NNNNDMMMMYYYY ||
1055 [ + - ][ + - ]: 33 : eBuiltIn == NF_DATETIME_SYSTEM_SHORT_HHMM || eBuiltIn == NF_DATETIME_SYS_DDMMYYYY_HHMMSS );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ]
1056 : :
1057 : : // format source (for date and time formats)
1058 : : // only used for some built-in formats
1059 : : sal_Bool bSystemDate = ( eBuiltIn == NF_DATE_SYSTEM_SHORT ||
1060 : : eBuiltIn == NF_DATE_SYSTEM_LONG ||
1061 [ + - ][ + - ]: 33 : eBuiltIn == NF_DATETIME_SYSTEM_SHORT_HHMM );
[ - + ]
1062 : 33 : sal_Bool bLongSysDate = ( eBuiltIn == NF_DATE_SYSTEM_LONG );
1063 : :
1064 : : // check if the format definition matches the key
1065 [ + + ][ - + ]: 41 : if ( bAutoOrder && ( nFmtType == NUMBERFORMAT_DATE || nFmtType == NUMBERFORMAT_DATETIME ) &&
[ # # ][ - + ]
[ - + ]
1066 [ + - ]: 8 : !lcl_IsDefaultDateFormat( rFormat, bSystemDate, eBuiltIn ) )
1067 : : {
1068 : 0 : bAutoOrder = bSystemDate = bLongSysDate = sal_False; // don't write automatic-order attribute then
1069 : : }
1070 : :
1071 [ + + ][ + - ]: 33 : if ( bAutoOrder &&
[ - + ][ # # ]
1072 : : ( nFmtType == NUMBERFORMAT_CURRENCY || nFmtType == NUMBERFORMAT_DATE || nFmtType == NUMBERFORMAT_DATETIME ) )
1073 : : {
1074 : : // #85109# format type must be checked to avoid dtd errors if
1075 : : // locale data contains other format types at the built-in positions
1076 : :
1077 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_AUTOMATIC_ORDER,
1078 [ + - ]: 8 : XML_TRUE );
1079 : : }
1080 : :
1081 [ - + ][ # # ]: 33 : if ( bSystemDate && bAutoOrder &&
[ # # ][ # # ]
1082 : : ( nFmtType == NUMBERFORMAT_DATE || nFmtType == NUMBERFORMAT_DATETIME ) )
1083 : : {
1084 : : // #85109# format type must be checked to avoid dtd errors if
1085 : : // locale data contains other format types at the built-in positions
1086 : :
1087 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_FORMAT_SOURCE,
1088 [ # # ]: 0 : XML_LANGUAGE );
1089 : : }
1090 : :
1091 : : // overflow for time formats as in [hh]:mm
1092 : : // controlled by bThousand from number format info
1093 : : // default for truncate-on-overflow is true
1094 [ - + ][ # # ]: 33 : if ( nFmtType == NUMBERFORMAT_TIME && bThousand )
1095 : : {
1096 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRUNCATE_ON_OVERFLOW,
1097 [ # # ]: 0 : XML_FALSE );
1098 : : }
1099 : :
1100 : : //
1101 : : // Native number transliteration
1102 : : //
1103 : 33 : ::com::sun::star::i18n::NativeNumberXmlAttributes aAttr;
1104 [ + - ]: 33 : rFormat.GetNatNumXml( aAttr, nPart );
1105 [ - + ]: 33 : if ( !aAttr.Format.isEmpty() )
1106 : : {
1107 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_FORMAT,
1108 [ # # ]: 0 : aAttr.Format );
1109 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_LANGUAGE,
1110 [ # # ]: 0 : aAttr.Locale.Language );
1111 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_COUNTRY,
1112 [ # # ]: 0 : aAttr.Locale.Country );
1113 : : rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_STYLE,
1114 [ # # ]: 0 : aAttr.Style );
1115 : : }
1116 : :
1117 : : //
1118 : : // The element
1119 : : //
1120 : : SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, eType,
1121 [ + - ]: 33 : sal_True, sal_True );
1122 : :
1123 : : //
1124 : : // color (properties element)
1125 : : //
1126 : :
1127 [ + - ]: 33 : const Color* pCol = rFormat.GetColor( nPart );
1128 [ + + ]: 33 : if (pCol)
1129 [ + - ]: 4 : WriteColorElement_Impl(*pCol);
1130 : :
1131 : :
1132 : : // detect if there is "real" content, excluding color and maps
1133 : : //! move to implementation of Write... methods?
1134 : 33 : sal_Bool bAnyContent = sal_False;
1135 : :
1136 : : //
1137 : : // format elements
1138 : : //
1139 : :
1140 [ + - ]: 33 : SvXMLEmbeddedTextEntryArr aEmbeddedEntries;
1141 [ + + ]: 33 : if ( eBuiltIn == NF_NUMBER_STANDARD )
1142 : : {
1143 : : // default number format contains just one number element
1144 [ + - ]: 13 : WriteNumberElement_Impl( -1, 1, OUString(), sal_False, sal_False, 0, aEmbeddedEntries );
1145 : 13 : bAnyContent = sal_True;
1146 : : }
1147 [ - + ]: 20 : else if ( eBuiltIn == NF_BOOLEAN )
1148 : : {
1149 : : // boolean format contains just one boolean element
1150 [ # # ]: 0 : WriteBooleanElement_Impl();
1151 : 0 : bAnyContent = sal_True;
1152 : : }
1153 : : else
1154 : : {
1155 : : // first loop to collect attributes
1156 : :
1157 : 20 : sal_Bool bDecDashes = sal_False;
1158 : 20 : sal_Bool bVarDecimals = sal_False;
1159 : 20 : sal_Bool bExpFound = sal_False;
1160 : 20 : sal_Bool bCurrFound = sal_False;
1161 : 20 : sal_Bool bInInteger = sal_True;
1162 : 20 : sal_Int32 nExpDigits = 0;
1163 : 20 : sal_Int32 nIntegerSymbols = 0; // for embedded-text, including "#"
1164 : 20 : sal_Int32 nTrailingThousands = 0; // thousands-separators after all digits
1165 : 20 : OUString sCurrExt;
1166 : 20 : OUString aCalendar;
1167 : 20 : sal_uInt16 nPos = 0;
1168 : 20 : sal_Bool bEnd = sal_False;
1169 [ + + ]: 168 : while (!bEnd)
1170 : : {
1171 [ + - ]: 148 : short nElemType = rFormat.GetNumForType( nPart, nPos, sal_False );
1172 [ + - ]: 148 : const XubString* pElemStr = rFormat.GetNumForString( nPart, nPos, sal_False );
1173 : :
1174 [ + + + + : 148 : switch ( nElemType )
- + + -
+ ]
1175 : : {
1176 : : case 0:
1177 : 20 : bEnd = sal_True; // end of format reached
1178 : 20 : break;
1179 : : case NF_SYMBOLTYPE_DIGIT:
1180 [ - + ][ # # ]: 30 : if ( bExpFound && pElemStr )
1181 : 0 : nExpDigits += pElemStr->Len();
1182 [ + - ][ + - ]: 30 : else if ( !bDecDashes && pElemStr && pElemStr->GetChar(0) == '-' )
[ - + ][ - + ]
1183 : 0 : bDecDashes = sal_True;
1184 [ + - ][ + + ]: 30 : else if ( !bVarDecimals && !bInInteger && pElemStr && pElemStr->GetChar(0) == '#' )
[ + - ][ - + ]
[ - + ]
1185 : : {
1186 : : // If the decimal digits string starts with a '#', variable
1187 : : // decimals is assumed (for 0.###, but not 0.0##).
1188 : 0 : bVarDecimals = sal_True;
1189 : : }
1190 [ + + ][ + - ]: 30 : if ( bInInteger && pElemStr )
1191 : 20 : nIntegerSymbols += pElemStr->Len();
1192 : 30 : nTrailingThousands = 0;
1193 : 30 : break;
1194 : : case NF_SYMBOLTYPE_DECSEP:
1195 : 10 : bInInteger = sal_False;
1196 : 10 : break;
1197 : : case NF_SYMBOLTYPE_THSEP:
1198 [ + - ]: 10 : if (pElemStr)
1199 : 10 : nTrailingThousands += pElemStr->Len(); // is reset to 0 if digits follow
1200 : 10 : break;
1201 : : case NF_SYMBOLTYPE_EXP:
1202 : 0 : bExpFound = sal_True; // following digits are exponent digits
1203 : 0 : bInInteger = sal_False;
1204 : 0 : break;
1205 : : case NF_SYMBOLTYPE_CURRENCY:
1206 : 8 : bCurrFound = sal_True;
1207 : 8 : break;
1208 : : case NF_SYMBOLTYPE_CURREXT:
1209 [ + - ]: 8 : if (pElemStr)
1210 [ + - ]: 8 : sCurrExt = *pElemStr;
1211 : 8 : break;
1212 : :
1213 : : // E, EE, R, RR: select non-gregorian calendar
1214 : : // AAA, AAAA: calendar is switched at the position of the element
1215 : : case NF_KEY_EC:
1216 : : case NF_KEY_EEC:
1217 : : case NF_KEY_R:
1218 : : case NF_KEY_RR:
1219 [ # # ]: 0 : if (aCalendar.isEmpty())
1220 [ # # ]: 0 : aCalendar = lcl_GetDefaultCalendar( pFormatter, nLang );
1221 : 0 : break;
1222 : : }
1223 : 148 : ++nPos;
1224 : : }
1225 : :
1226 : : // collect strings for embedded-text (must be known before number element is written)
1227 : :
1228 : : sal_Bool bAllowEmbedded = ( nFmtType == 0 || nFmtType == NUMBERFORMAT_NUMBER ||
1229 : : nFmtType == NUMBERFORMAT_CURRENCY ||
1230 [ + - ][ + + ]: 20 : nFmtType == NUMBERFORMAT_PERCENT );
[ + + ][ - + ]
1231 [ + + ]: 20 : if ( bAllowEmbedded )
1232 : : {
1233 : 10 : sal_Int32 nDigitsPassed = 0;
1234 : 10 : nPos = 0;
1235 : 10 : bEnd = sal_False;
1236 [ + + ]: 106 : while (!bEnd)
1237 : : {
1238 [ + - ]: 96 : short nElemType = rFormat.GetNumForType( nPart, nPos, sal_False );
1239 [ + - ]: 96 : const XubString* pElemStr = rFormat.GetNumForString( nPart, nPos, sal_False );
1240 : :
1241 [ + + + + ]: 96 : switch ( nElemType )
1242 : : {
1243 : : case 0:
1244 : 10 : bEnd = sal_True; // end of format reached
1245 : 10 : break;
1246 : : case NF_SYMBOLTYPE_DIGIT:
1247 [ + - ]: 30 : if ( pElemStr )
1248 : 30 : nDigitsPassed += pElemStr->Len();
1249 : 30 : break;
1250 : : case NF_SYMBOLTYPE_STRING:
1251 : : case NF_SYMBOLTYPE_BLANK:
1252 : : case NF_SYMBOLTYPE_PERCENT:
1253 [ - + ][ # # ]: 4 : if ( nDigitsPassed > 0 && nDigitsPassed < nIntegerSymbols && pElemStr )
[ # # ]
1254 : : {
1255 : : // text (literal or underscore) within the integer part of a number:number element
1256 : :
1257 [ # # ]: 0 : String aEmbeddedStr;
1258 [ # # ][ # # ]: 0 : if ( nElemType == NF_SYMBOLTYPE_STRING || nElemType == NF_SYMBOLTYPE_PERCENT )
1259 [ # # ]: 0 : aEmbeddedStr = *pElemStr;
1260 : : else
1261 [ # # ]: 0 : SvNumberformat::InsertBlanks( aEmbeddedStr, 0, pElemStr->GetChar(1) );
1262 : :
1263 : 0 : sal_Int32 nEmbedPos = nIntegerSymbols - nDigitsPassed;
1264 : :
1265 [ # # ][ # # ]: 0 : SvXMLEmbeddedTextEntry* pObj = new SvXMLEmbeddedTextEntry( nPos, nEmbedPos, aEmbeddedStr );
1266 [ # # ][ # # ]: 0 : aEmbeddedEntries.push_back( pObj );
1267 : : }
1268 : 4 : break;
1269 : : }
1270 : 96 : ++nPos;
1271 : : }
1272 : : }
1273 : :
1274 : : // final loop to write elements
1275 : :
1276 : 20 : sal_Bool bNumWritten = sal_False;
1277 : 20 : sal_Bool bCurrencyWritten = sal_False;
1278 : 20 : short nPrevType = 0;
1279 : 20 : nPos = 0;
1280 : 20 : bEnd = sal_False;
1281 [ + + ]: 168 : while (!bEnd)
1282 : : {
1283 [ + - ]: 148 : short nElemType = rFormat.GetNumForType( nPart, nPos, sal_False );
1284 [ + - ]: 148 : const XubString* pElemStr = rFormat.GetNumForString( nPart, nPos, sal_False );
1285 : :
1286 [ + + - - : 148 : switch ( nElemType )
- + + + -
- + - + +
- - - - -
- - - + ]
1287 : : {
1288 : : case 0:
1289 : 20 : bEnd = sal_True; // end of format reached
1290 : 20 : break;
1291 : : case NF_SYMBOLTYPE_STRING:
1292 : : case NF_SYMBOLTYPE_DATESEP:
1293 : : case NF_SYMBOLTYPE_TIMESEP:
1294 : : case NF_SYMBOLTYPE_TIME100SECSEP:
1295 : : case NF_SYMBOLTYPE_PERCENT:
1296 [ + - ]: 20 : if (pElemStr)
1297 : : {
1298 [ + - ][ - + ]: 20 : if ( ( nPrevType == NF_KEY_S || nPrevType == NF_KEY_SS ) &&
[ # # ][ # # ]
1299 : : ( nElemType == NF_SYMBOLTYPE_TIME100SECSEP ) &&
1300 : : nPrecision > 0 )
1301 : : {
1302 : : // decimal separator after seconds is implied by
1303 : : // "decimal-places" attribute and must not be written
1304 : : // as text element
1305 : : //! difference between '.' and ',' is lost here
1306 : : }
1307 [ + - ][ + - ]: 20 : else if ( lcl_IsInEmbedded( aEmbeddedEntries, nPos ) )
1308 : : {
1309 : : // text is written as embedded-text child of the number,
1310 : : // don't create a text element
1311 : : }
1312 [ + + ][ - + ]: 20 : else if ( nFmtType == NUMBERFORMAT_CURRENCY && !bCurrFound && !bCurrencyWritten )
[ # # ]
1313 : : {
1314 : : // automatic currency symbol is implemented as part of
1315 : : // normal text -> search for the symbol
1316 : : bCurrencyWritten = WriteTextWithCurrency_Impl( *pElemStr,
1317 [ # # ][ # # ]: 0 : MsLangId::convertLanguageToLocale( nLang ) );
[ # # ]
1318 : 0 : bAnyContent = sal_True;
1319 : : }
1320 : : else
1321 [ + - ][ + - ]: 20 : AddToTextElement_Impl( *pElemStr );
1322 : : }
1323 : 20 : break;
1324 : : case NF_SYMBOLTYPE_BLANK:
1325 [ # # ][ # # ]: 0 : if ( pElemStr && !lcl_IsInEmbedded( aEmbeddedEntries, nPos ) )
[ # # ][ # # ]
1326 : : {
1327 : : // turn "_x" into the number of spaces used for x in InsertBlanks in the NumberFormat
1328 : : // (#i20396# the spaces may also be in embedded-text elements)
1329 : :
1330 [ # # ]: 0 : String aBlanks;
1331 [ # # ]: 0 : SvNumberformat::InsertBlanks( aBlanks, 0, pElemStr->GetChar(1) );
1332 [ # # ][ # # ]: 0 : AddToTextElement_Impl( aBlanks );
[ # # ]
1333 : : }
1334 : 0 : break;
1335 : : case NF_KEY_GENERAL :
1336 [ # # ]: 0 : WriteNumberElement_Impl( -1, 1, OUString(), sal_False, sal_False, 0, aEmbeddedEntries );
1337 : 0 : break;
1338 : : case NF_KEY_CCC:
1339 [ # # ]: 0 : if (pElemStr)
1340 : : {
1341 [ # # ]: 0 : if ( bCurrencyWritten )
1342 [ # # ][ # # ]: 0 : AddToTextElement_Impl( *pElemStr ); // never more than one currency element
1343 : : else
1344 : : {
1345 : : //! must be different from short automatic format
1346 : : //! but should still be empty (meaning automatic)
1347 : : // pElemStr is "CCC"
1348 : :
1349 [ # # ][ # # ]: 0 : WriteCurrencyElement_Impl( *pElemStr, OUString() );
1350 : 0 : bAnyContent = sal_True;
1351 : 0 : bCurrencyWritten = sal_True;
1352 : : }
1353 : : }
1354 : 0 : break;
1355 : : case NF_SYMBOLTYPE_CURRENCY:
1356 [ + - ]: 8 : if (pElemStr)
1357 : : {
1358 [ - + ]: 8 : if ( bCurrencyWritten )
1359 [ # # ][ # # ]: 0 : AddToTextElement_Impl( *pElemStr ); // never more than one currency element
1360 : : else
1361 : : {
1362 [ + - ][ + - ]: 8 : WriteCurrencyElement_Impl( *pElemStr, sCurrExt );
1363 : 8 : bAnyContent = sal_True;
1364 : 8 : bCurrencyWritten = sal_True;
1365 : : }
1366 : : }
1367 : 8 : break;
1368 : : case NF_SYMBOLTYPE_DIGIT:
1369 [ + + ]: 30 : if (!bNumWritten) // write number part
1370 : : {
1371 [ + - - - ]: 10 : switch ( nFmtType )
1372 : : {
1373 : : // for type 0 (not recognized as a special type),
1374 : : // write a "normal" number
1375 : : case 0:
1376 : : case NUMBERFORMAT_NUMBER:
1377 : : case NUMBERFORMAT_CURRENCY:
1378 : : case NUMBERFORMAT_PERCENT:
1379 : : {
1380 : : // decimals
1381 : : // only some built-in formats have automatic decimals
1382 : 10 : sal_Int32 nDecimals = nPrecision; // from GetFormatSpecialInfo
1383 [ + - ][ + - ]: 10 : if ( eBuiltIn == NF_NUMBER_STANDARD ||
[ + - ][ + - ]
[ - + ]
1384 : : eBuiltIn == NF_CURRENCY_1000DEC2 ||
1385 : : eBuiltIn == NF_CURRENCY_1000DEC2_RED ||
1386 : : eBuiltIn == NF_CURRENCY_1000DEC2_CCC ||
1387 : : eBuiltIn == NF_CURRENCY_1000DEC2_DASHED )
1388 : 0 : nDecimals = -1;
1389 : :
1390 : : // integer digits
1391 : : // only one built-in format has automatic integer digits
1392 : 10 : sal_Int32 nInteger = nLeading;
1393 [ - + ]: 10 : if ( eBuiltIn == NF_NUMBER_SYSTEM )
1394 : 0 : nInteger = -1;
1395 : :
1396 : : // string for decimal replacement
1397 : : // has to be taken from nPrecision
1398 : : // (positive number even for automatic decimals)
1399 [ + - ]: 10 : String sDashStr;
1400 [ - + ][ # # ]: 10 : if ( bDecDashes && nPrecision > 0 )
1401 [ # # ]: 0 : sDashStr.Fill( nPrecision, '-' );
1402 : :
1403 : : WriteNumberElement_Impl( nDecimals, nInteger, sDashStr, bVarDecimals,
1404 [ + - ][ + - ]: 10 : bThousand, nTrailingThousands, aEmbeddedEntries );
1405 [ + - ]: 10 : bAnyContent = sal_True;
1406 : : }
1407 : 10 : break;
1408 : : case NUMBERFORMAT_SCIENTIFIC:
1409 : : // #i43959# for scientific numbers, count all integer symbols ("0" and "#")
1410 : : // as integer digits: use nIntegerSymbols instead of nLeading
1411 : : // (use of '#' to select multiples in exponent might be added later)
1412 [ # # ]: 0 : WriteScientificElement_Impl( nPrecision, nIntegerSymbols, bThousand, nExpDigits );
1413 : 0 : bAnyContent = sal_True;
1414 : 0 : break;
1415 : : case NUMBERFORMAT_FRACTION:
1416 : : {
1417 : 0 : sal_Int32 nInteger = nLeading;
1418 [ # # ][ # # ]: 0 : if ( pElemStr && pElemStr->GetChar(0) == '?' )
[ # # ]
1419 : : {
1420 : : // If the first digit character is a question mark,
1421 : : // the fraction doesn't have an integer part, and no
1422 : : // min-integer-digits attribute must be written.
1423 : 0 : nInteger = -1;
1424 : : }
1425 [ # # ]: 0 : WriteFractionElement_Impl( nInteger, bThousand, nPrecision, nPrecision );
1426 : 0 : bAnyContent = sal_True;
1427 : : }
1428 : 0 : break;
1429 : : }
1430 : :
1431 : 10 : bNumWritten = sal_True;
1432 : : }
1433 : 30 : break;
1434 : : case NF_SYMBOLTYPE_DECSEP:
1435 [ + - ][ - + ]: 10 : if ( pElemStr && nPrecision == 0 )
1436 : : {
1437 : : // A decimal separator after the number, without following decimal digits,
1438 : : // isn't modelled as part of the number element, so it's written as text
1439 : : // (the distinction between a quoted and non-quoted, locale-dependent
1440 : : // character is lost here).
1441 : :
1442 [ # # ][ # # ]: 0 : AddToTextElement_Impl( *pElemStr );
1443 : : }
1444 : 10 : break;
1445 : : case NF_SYMBOLTYPE_DEL:
1446 [ # # ][ # # ]: 0 : if ( pElemStr && comphelper::string::equals(*pElemStr, '@') )
[ # # ][ # # ]
[ # # # # ]
1447 : : {
1448 [ # # ]: 0 : WriteTextContentElement_Impl();
1449 : 0 : bAnyContent = sal_True;
1450 : : }
1451 : 0 : break;
1452 : :
1453 : : case NF_SYMBOLTYPE_CALENDAR:
1454 [ # # ]: 0 : if ( pElemStr )
1455 [ # # ]: 0 : aCalendar = *pElemStr;
1456 : 0 : break;
1457 : :
1458 : : // date elements:
1459 : :
1460 : : case NF_KEY_D:
1461 : : case NF_KEY_DD:
1462 : : {
1463 : 8 : sal_Bool bLong = ( nElemType == NF_KEY_DD );
1464 [ - + ][ + - ]: 8 : WriteDayElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) );
1465 : 8 : bAnyContent = sal_True;
1466 : : }
1467 : 8 : break;
1468 : : case NF_KEY_DDD:
1469 : : case NF_KEY_DDDD:
1470 : : case NF_KEY_NN:
1471 : : case NF_KEY_NNN:
1472 : : case NF_KEY_NNNN:
1473 : : case NF_KEY_AAA:
1474 : : case NF_KEY_AAAA:
1475 : : {
1476 : 0 : OUString aCalAttr = aCalendar;
1477 [ # # ][ # # ]: 0 : if ( nElemType == NF_KEY_AAA || nElemType == NF_KEY_AAAA )
1478 : : {
1479 : : // calendar attribute for AAA and AAAA is switched only for this element
1480 [ # # ]: 0 : if (aCalAttr.isEmpty())
1481 [ # # ]: 0 : aCalAttr = lcl_GetDefaultCalendar( pFormatter, nLang );
1482 : : }
1483 : :
1484 : : sal_Bool bLong = ( nElemType == NF_KEY_NNN || nElemType == NF_KEY_NNNN ||
1485 [ # # ][ # # ]: 0 : nElemType == NF_KEY_DDDD || nElemType == NF_KEY_AAAA );
[ # # ][ # # ]
1486 [ # # ][ # # ]: 0 : WriteDayOfWeekElement_Impl( aCalAttr, ( bSystemDate ? bLongSysDate : bLong ) );
1487 : 0 : bAnyContent = sal_True;
1488 [ # # ]: 0 : if ( nElemType == NF_KEY_NNNN )
1489 : : {
1490 : : // write additional text element for separator
1491 [ # # ][ # # ]: 0 : pLocaleData->setLocale( MsLangId::convertLanguageToLocale( nLang ) );
1492 [ # # ][ # # ]: 0 : AddToTextElement_Impl( pLocaleData->getLongDateDayOfWeekSep() );
1493 : 0 : }
1494 : : }
1495 : 0 : break;
1496 : : case NF_KEY_M:
1497 : : case NF_KEY_MM:
1498 : : case NF_KEY_MMM:
1499 : : case NF_KEY_MMMM:
1500 : : case NF_KEY_MMMMM: //! first letter of month name, no attribute available
1501 : : {
1502 [ + + ][ + - ]: 10 : sal_Bool bLong = ( nElemType == NF_KEY_MM || nElemType == NF_KEY_MMMM );
1503 : : sal_Bool bText = ( nElemType == NF_KEY_MMM || nElemType == NF_KEY_MMMM ||
1504 [ + - ][ + + ]: 10 : nElemType == NF_KEY_MMMMM );
[ - + ]
1505 [ - + ][ + - ]: 10 : WriteMonthElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ), bText );
1506 : 10 : bAnyContent = sal_True;
1507 : : }
1508 : 10 : break;
1509 : : case NF_KEY_YY:
1510 : : case NF_KEY_YYYY:
1511 : : case NF_KEY_EC:
1512 : : case NF_KEY_EEC:
1513 : : case NF_KEY_R: //! R acts as EE, no attribute available
1514 : : {
1515 : : //! distinguish EE and R
1516 : : // calendar attribute for E and EE and R is set in first loop
1517 : : sal_Bool bLong = ( nElemType == NF_KEY_YYYY || nElemType == NF_KEY_EEC ||
1518 [ - + ][ # # ]: 8 : nElemType == NF_KEY_R );
[ # # ]
1519 [ - + ][ + - ]: 8 : WriteYearElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) );
1520 : 8 : bAnyContent = sal_True;
1521 : : }
1522 : 8 : break;
1523 : : case NF_KEY_G:
1524 : : case NF_KEY_GG:
1525 : : case NF_KEY_GGG:
1526 : : case NF_KEY_RR: //! RR acts as GGGEE, no attribute available
1527 : : {
1528 : : //! distinguish GG and GGG and RR
1529 [ # # ][ # # ]: 0 : sal_Bool bLong = ( nElemType == NF_KEY_GGG || nElemType == NF_KEY_RR );
1530 [ # # ][ # # ]: 0 : WriteEraElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) );
1531 : 0 : bAnyContent = sal_True;
1532 [ # # ]: 0 : if ( nElemType == NF_KEY_RR )
1533 : : {
1534 : : // calendar attribute for RR is set in first loop
1535 [ # # ][ # # ]: 0 : WriteYearElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : sal_True ) );
1536 : : }
1537 : : }
1538 : 0 : break;
1539 : : case NF_KEY_Q:
1540 : : case NF_KEY_QQ:
1541 : : {
1542 : 0 : sal_Bool bLong = ( nElemType == NF_KEY_QQ );
1543 [ # # ][ # # ]: 0 : WriteQuarterElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) );
1544 : 0 : bAnyContent = sal_True;
1545 : : }
1546 : 0 : break;
1547 : : case NF_KEY_WW:
1548 [ # # ]: 0 : WriteWeekElement_Impl( aCalendar );
1549 : 0 : bAnyContent = sal_True;
1550 : 0 : break;
1551 : :
1552 : : // time elements (bSystemDate is not used):
1553 : :
1554 : : case NF_KEY_H:
1555 : : case NF_KEY_HH:
1556 [ # # ]: 0 : WriteHoursElement_Impl( nElemType == NF_KEY_HH );
1557 : 0 : bAnyContent = sal_True;
1558 : 0 : break;
1559 : : case NF_KEY_MI:
1560 : : case NF_KEY_MMI:
1561 [ # # ]: 0 : WriteMinutesElement_Impl( nElemType == NF_KEY_MMI );
1562 : 0 : bAnyContent = sal_True;
1563 : 0 : break;
1564 : : case NF_KEY_S:
1565 : : case NF_KEY_SS:
1566 [ # # ]: 0 : WriteSecondsElement_Impl( ( nElemType == NF_KEY_SS ), nPrecision );
1567 : 0 : bAnyContent = sal_True;
1568 : 0 : break;
1569 : : case NF_KEY_AMPM:
1570 : : case NF_KEY_AP:
1571 [ # # ]: 0 : WriteAMPMElement_Impl(); // short/long?
1572 : 0 : bAnyContent = sal_True;
1573 : 0 : break;
1574 : : case NF_SYMBOLTYPE_STAR :
1575 : : // export only if ODF 1.2 extensions are enabled
1576 [ # # ][ # # ]: 0 : if( SvtSaveOptions().GetODFDefaultVersion() > SvtSaveOptions::ODFVER_012 )
[ # # ][ # # ]
1577 : : {
1578 [ # # ][ # # ]: 0 : if ( pElemStr && pElemStr->Len() > 1 )
[ # # ]
1579 [ # # ]: 0 : WriteRepeatedElement_Impl( pElemStr->GetChar( 1 ) );
1580 : : }
1581 : 0 : break;
1582 : : }
1583 : 148 : nPrevType = nElemType;
1584 : 148 : ++nPos;
1585 : 20 : }
1586 : : }
1587 : :
1588 [ - + ]: 33 : if ( sTextContent.getLength() )
1589 : 0 : bAnyContent = sal_True; // element written in FinishTextElement_Impl
1590 : :
1591 [ + - ]: 33 : FinishTextElement_Impl(); // final text element - before maps
1592 : :
1593 [ - + ]: 33 : if ( !bAnyContent )
1594 : : {
1595 : : // for an empty format, write an empty text element
1596 : : SvXMLElementExport aTElem( rExport, XML_NAMESPACE_NUMBER, XML_TEXT,
1597 [ # # ][ # # ]: 0 : sal_True, sal_False );
1598 : : }
1599 : :
1600 : : //
1601 : : // mapping (conditions) must be last elements
1602 : : //
1603 : :
1604 [ + + ]: 33 : if (bDefPart)
1605 : : {
1606 : : SvNumberformatLimitOps eOp1, eOp2;
1607 : : double fLimit1, fLimit2;
1608 [ + - ]: 29 : rFormat.GetConditions( eOp1, fLimit1, eOp2, fLimit2 );
1609 : :
1610 [ + - ]: 29 : WriteMapElement_Impl( eOp1, fLimit1, nKey, 0 );
1611 [ + - ]: 29 : WriteMapElement_Impl( eOp2, fLimit2, nKey, 1 );
1612 : :
1613 [ - + ]: 29 : if ( rFormat.HasTextFormat() )
1614 : : {
1615 : : // 4th part is for text -> make an "all other numbers" condition for the 3rd part
1616 : : // by reversing the 2nd condition
1617 : :
1618 : 0 : SvNumberformatLimitOps eOp3 = NUMBERFORMAT_OP_NO;
1619 : 0 : double fLimit3 = fLimit2;
1620 [ # # # # : 0 : switch ( eOp2 )
# # # ]
1621 : : {
1622 : 0 : case NUMBERFORMAT_OP_EQ: eOp3 = NUMBERFORMAT_OP_NE; break;
1623 : 0 : case NUMBERFORMAT_OP_NE: eOp3 = NUMBERFORMAT_OP_EQ; break;
1624 : 0 : case NUMBERFORMAT_OP_LT: eOp3 = NUMBERFORMAT_OP_GE; break;
1625 : 0 : case NUMBERFORMAT_OP_LE: eOp3 = NUMBERFORMAT_OP_GT; break;
1626 : 0 : case NUMBERFORMAT_OP_GT: eOp3 = NUMBERFORMAT_OP_LE; break;
1627 : 0 : case NUMBERFORMAT_OP_GE: eOp3 = NUMBERFORMAT_OP_LT; break;
1628 : : default:
1629 : 0 : break;
1630 : : }
1631 : :
1632 [ # # ][ # # ]: 0 : if ( fLimit1 == fLimit2 &&
[ # # ][ # # ]
[ # # ]
1633 : : ( ( eOp1 == NUMBERFORMAT_OP_LT && eOp2 == NUMBERFORMAT_OP_GT ) ||
1634 : : ( eOp1 == NUMBERFORMAT_OP_GT && eOp2 == NUMBERFORMAT_OP_LT ) ) )
1635 : : {
1636 : : // For <x and >x, add =x as last condition
1637 : : // (just for readability, <=x would be valid, too)
1638 : :
1639 : 0 : eOp3 = NUMBERFORMAT_OP_EQ;
1640 : : }
1641 : :
1642 [ # # ]: 29 : WriteMapElement_Impl( eOp3, fLimit3, nKey, 2 );
1643 : : }
1644 [ + - ][ + - ]: 33 : }
1645 : 33 : }
1646 : :
1647 : : //-------------------------------------------------------------------------
1648 : :
1649 : : //
1650 : : // export one format
1651 : : //
1652 : :
1653 : 29 : void SvXMLNumFmtExport::ExportFormat_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey )
1654 : : {
1655 : 29 : sal_uInt16 nUsedParts = 0;
1656 : : sal_uInt16 nPart;
1657 [ + + ]: 116 : for (nPart=0; nPart<XMLNUM_MAX_PARTS; nPart++)
1658 [ + - ][ + + ]: 87 : if (rFormat.GetNumForType( nPart, 0, sal_False ) != 0)
1659 : 33 : nUsedParts = nPart+1;
1660 : :
1661 : : SvNumberformatLimitOps eOp1, eOp2;
1662 : : double fLimit1, fLimit2;
1663 [ + - ]: 29 : rFormat.GetConditions( eOp1, fLimit1, eOp2, fLimit2 );
1664 : :
1665 : : // if conditions are set, even empty formats must be written
1666 : :
1667 [ + + ][ - + ]: 29 : if ( eOp1 != NUMBERFORMAT_OP_NO && nUsedParts < 2 )
1668 : 0 : nUsedParts = 2;
1669 [ - + ][ # # ]: 29 : if ( eOp2 != NUMBERFORMAT_OP_NO && nUsedParts < 3 )
1670 : 0 : nUsedParts = 3;
1671 [ - + ][ # # ]: 29 : if ( rFormat.HasTextFormat() && nUsedParts < 4 )
[ - + ]
1672 : 0 : nUsedParts = 4;
1673 : :
1674 [ + + ]: 62 : for (nPart=0; nPart<nUsedParts; nPart++)
1675 : : {
1676 : 33 : sal_Bool bDefault = ( nPart+1 == nUsedParts ); // last = default
1677 [ + - ]: 33 : ExportPart_Impl( rFormat, nKey, nPart, bDefault );
1678 : : }
1679 : 29 : }
1680 : :
1681 : : //-------------------------------------------------------------------------
1682 : :
1683 : : //
1684 : : // export method called by application
1685 : : //
1686 : :
1687 : 233 : void SvXMLNumFmtExport::Export( sal_Bool bIsAutoStyle )
1688 : : {
1689 [ + - ]: 233 : if ( !pFormatter )
1690 : 233 : return; // no formatter -> no entries
1691 : :
1692 : : sal_uInt32 nKey;
1693 : 233 : const SvNumberformat* pFormat = NULL;
1694 [ + - ]: 233 : sal_Bool bNext(pUsedList->GetFirstUsed(nKey));
1695 [ + + ]: 262 : while(bNext)
1696 : : {
1697 [ + - ]: 29 : pFormat = pFormatter->GetEntry(nKey);
1698 [ + - ]: 29 : if(pFormat)
1699 [ + - ]: 29 : ExportFormat_Impl( *pFormat, nKey );
1700 [ + - ]: 29 : bNext = pUsedList->GetNextUsed(nKey);
1701 : : }
1702 [ + + ]: 233 : if (!bIsAutoStyle)
1703 : : {
1704 [ + - ]: 178 : std::vector<sal_uInt16> aLanguages;
1705 [ + - ]: 178 : pFormatter->GetUsedLanguages( aLanguages );
1706 [ + - ][ + - ]: 356 : for (std::vector<sal_uInt16>::const_iterator it(aLanguages.begin()); it != aLanguages.end(); ++it)
[ + - ][ + + ]
1707 : : {
1708 [ + - ]: 178 : LanguageType nLang = *it;
1709 : :
1710 : 178 : sal_uInt32 nDefaultIndex = 0;
1711 : : SvNumberFormatTable& rTable = pFormatter->GetEntryTable(
1712 [ + - ]: 178 : NUMBERFORMAT_DEFINED, nDefaultIndex, nLang );
1713 : 178 : SvNumberFormatTable::iterator it2 = rTable.begin();
1714 [ + - ][ - + ]: 178 : while (it2 != rTable.end())
1715 : : {
1716 [ # # ]: 0 : nKey = it2->first;
1717 [ # # ]: 0 : pFormat = it2->second;
1718 [ # # ][ # # ]: 0 : if (!pUsedList->IsUsed(nKey))
1719 : : {
1720 : : DBG_ASSERT((pFormat->GetType() & NUMBERFORMAT_DEFINED) != 0, "a not user defined numberformat found");
1721 : : // user-defined and used formats are exported
1722 [ # # ]: 0 : ExportFormat_Impl( *pFormat, nKey );
1723 : : // if it is a user-defined Format it will be added else nothing will hapen
1724 [ # # ]: 0 : pUsedList->SetUsed(nKey);
1725 : : }
1726 : :
1727 [ # # ]: 0 : ++it2;
1728 : : }
1729 : 178 : }
1730 : : }
1731 [ + - ]: 233 : pUsedList->Export();
1732 : : }
1733 : :
1734 : 67 : OUString SvXMLNumFmtExport::GetStyleName( sal_uInt32 nKey )
1735 : : {
1736 [ + + ][ + - ]: 67 : if(pUsedList->IsUsed(nKey) || pUsedList->IsWasUsed(nKey))
[ + - ]
1737 : 67 : return lcl_CreateStyleName( nKey, 0, sal_True, sPrefix );
1738 : : else
1739 : : {
1740 : : OSL_FAIL("There is no written Data-Style");
1741 : 67 : return rtl::OUString();
1742 : : }
1743 : : }
1744 : :
1745 : 138 : void SvXMLNumFmtExport::SetUsed( sal_uInt32 nKey )
1746 : : {
1747 : : DBG_ASSERT( pFormatter != NULL, "missing formatter" );
1748 [ - + ]: 138 : if( !pFormatter )
1749 : 138 : return;
1750 : :
1751 [ + - ]: 138 : if (pFormatter->GetEntry(nKey))
1752 : 138 : pUsedList->SetUsed( nKey );
1753 : : else {
1754 : : OSL_FAIL("no existing Numberformat found with this key");
1755 : : }
1756 : : }
1757 : :
1758 : 50 : void SvXMLNumFmtExport::GetWasUsed(uno::Sequence<sal_Int32>& rWasUsed)
1759 : : {
1760 [ + - ]: 50 : if (pUsedList)
1761 : 50 : pUsedList->GetWasUsed(rWasUsed);
1762 : 50 : }
1763 : :
1764 : 25 : void SvXMLNumFmtExport::SetWasUsed(const uno::Sequence<sal_Int32>& rWasUsed)
1765 : : {
1766 [ + - ]: 25 : if (pUsedList)
1767 : 25 : pUsedList->SetWasUsed(rWasUsed);
1768 : 25 : }
1769 : :
1770 : :
1771 : :
1772 : 10 : const SvNumberformat* lcl_GetFormat( SvNumberFormatter* pFormatter,
1773 : : sal_uInt32 nKey )
1774 : : {
1775 [ + - ]: 10 : return ( pFormatter != NULL ) ? pFormatter->GetEntry( nKey ) : NULL;
1776 : : }
1777 : :
1778 : 10 : sal_uInt32 SvXMLNumFmtExport::ForceSystemLanguage( sal_uInt32 nKey )
1779 : : {
1780 : 10 : sal_uInt32 nRet = nKey;
1781 : :
1782 : 10 : const SvNumberformat* pFormat = lcl_GetFormat( pFormatter, nKey );
1783 [ + - ]: 10 : if( pFormat != NULL )
1784 : : {
1785 : : DBG_ASSERT( pFormatter != NULL, "format without formatter?" );
1786 : :
1787 : : xub_StrLen nErrorPos;
1788 : 10 : short nType = pFormat->GetType();
1789 : :
1790 : : sal_uInt32 nNewKey = pFormatter->GetFormatForLanguageIfBuiltIn(
1791 [ + - ]: 10 : nKey, LANGUAGE_SYSTEM );
1792 : :
1793 [ - + ]: 10 : if( nNewKey != nKey )
1794 : : {
1795 : 0 : nRet = nNewKey;
1796 : : }
1797 : : else
1798 : : {
1799 [ + - ]: 10 : String aFormatString( pFormat->GetFormatstring() );
1800 : : pFormatter->PutandConvertEntry(
1801 : : aFormatString,
1802 : : nErrorPos, nType, nNewKey,
1803 [ + - ]: 10 : pFormat->GetLanguage(), LANGUAGE_SYSTEM );
1804 : :
1805 : : // success? Then use new key.
1806 [ + - ]: 10 : if( nErrorPos == 0 )
1807 [ + - ]: 10 : nRet = nNewKey;
1808 : : }
1809 : : }
1810 : :
1811 : 10 : return nRet;
1812 : : }
1813 : :
1814 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|