1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
27 #include <rtl/ustrbuf.hxx>
28 #include <sal/macros.h>
30 #include "LocaleNode.hxx"
31 #include <i18npool/reservedconstants.hxx>
32 #include <com/sun/star/i18n/NumberFormatIndex.hpp>
33 #include <com/sun/star/xml/sax/XAttributeList.hpp>
35 // NOTE: MUST match the Locale versionDTD attribute defined in data/locale.dtd
36 #define LOCALE_VERSION_DTD "2.0.3"
38 typedef ::std::set
< OUString
> NameSet
;
39 typedef ::std::set
< sal_Int16
> ValueSet
;
41 namespace cssi
= ::com::sun::star::i18n
;
43 LocaleNode::LocaleNode (const OUString
& name
, const Reference
< XAttributeList
> & attr
)
51 int LocaleNode::getError() const
54 for (size_t i
=0;i
<children
.size();i
++)
55 err
+= children
[i
]->getError();
59 void LocaleNode::addChild ( LocaleNode
* node
) {
60 children
.emplace_back(node
);
64 const LocaleNode
* LocaleNode::getRoot() const
66 const LocaleNode
* pRoot
= nullptr;
67 const LocaleNode
* pParent
= this;
68 while ( (pParent
= pParent
->parent
) != nullptr )
73 const LocaleNode
* LocaleNode::findNode ( const sal_Char
*name
) const {
74 if (aName
.equalsAscii(name
))
76 for (size_t i
= 0; i
< children
.size(); i
++) {
77 const LocaleNode
*n
=children
[i
]->findNode(name
);
84 LocaleNode::~LocaleNode()
88 LocaleNode
* LocaleNode::createNode (const OUString
& name
, const Reference
< XAttributeList
> & attr
)
90 if ( name
== "LC_INFO" )
91 return new LCInfoNode (name
,attr
);
92 if ( name
== "LC_CTYPE" )
93 return new LCCTYPENode (name
,attr
);
94 if ( name
== "LC_FORMAT" )
95 return new LCFormatNode (name
,attr
);
96 if ( name
== "LC_FORMAT_1" )
97 return new LCFormatNode (name
,attr
);
98 if ( name
== "LC_CALENDAR" )
99 return new LCCalendarNode (name
,attr
);
100 if ( name
== "LC_CURRENCY" )
101 return new LCCurrencyNode (name
,attr
);
102 if ( name
== "LC_TRANSLITERATION" )
103 return new LCTransliterationNode (name
,attr
);
104 if ( name
== "LC_COLLATION" )
105 return new LCCollationNode (name
,attr
);
106 if ( name
== "LC_INDEX" )
107 return new LCIndexNode (name
,attr
);
108 if ( name
== "LC_SEARCH" )
109 return new LCSearchNode (name
,attr
);
110 if ( name
== "LC_MISC" )
111 return new LCMiscNode (name
,attr
);
112 if ( name
== "LC_NumberingLevel" )
113 return new LCNumberingLevelNode (name
, attr
);
114 if ( name
== "LC_OutLineNumberingLevel" )
115 return new LCOutlineNumberingLevelNode (name
, attr
);
117 return new LocaleNode(name
,attr
);
121 // printf(" name: '%s'\n", p->getName().pData->buffer );
122 // printf("value: '%s'\n", p->getValue().pData->buffer );
124 #define OSTR(s) (OUStringToOString( (s), RTL_TEXTENCODING_UTF8).getStr())
126 void LocaleNode::generateCode (const OFileWriter
&of
) const
128 OUString aDTD
= getAttr().getValueByName("versionDTD");
129 if ( aDTD
!= LOCALE_VERSION_DTD
)
132 fprintf( stderr
, "Error: Locale versionDTD is not %s, see comment in locale.dtd\n", LOCALE_VERSION_DTD
);
134 for (size_t i
=0; i
<children
.size(); i
++)
135 children
[i
]->generateCode (of
);
136 // print_node( this );
140 OUString
LocaleNode::writeParameterCheckLen( const OFileWriter
&of
,
141 const char* pParameterName
, const LocaleNode
* pNode
,
142 sal_Int32 nMinLen
, sal_Int32 nMaxLen
) const
146 aVal
= pNode
->getValue();
147 else if (nMinLen
>= 0) // -1: optional => empty, 0: must be present, empty
150 fprintf( stderr
, "Error: node NULL pointer for parameter %s.\n",
153 // write empty data if error
154 of
.writeParameter( pParameterName
, aVal
);
155 sal_Int32 nLen
= aVal
.getLength();
159 fprintf( stderr
, "Error: less than %ld character%s (%ld) in %s '%s'.\n",
160 sal::static_int_cast
< long >(nMinLen
), (nMinLen
> 1 ? "s" : ""),
161 sal::static_int_cast
< long >(nLen
),
162 (pNode
? OSTR( pNode
->getName()) : ""),
165 else if (nLen
> nMaxLen
&& nMaxLen
>= 0)
169 "Error: more than %ld character%s (%ld) in %s '%s' not supported by application.\n",
170 sal::static_int_cast
< long >(nMaxLen
), (nMaxLen
> 1 ? "s" : ""),
171 sal::static_int_cast
< long >(nLen
),
172 (pNode
? OSTR( pNode
->getName()) : ""),
179 OUString
LocaleNode::writeParameterCheckLen( const OFileWriter
&of
,
180 const char* pNodeName
, const char* pParameterName
,
181 sal_Int32 nMinLen
, sal_Int32 nMaxLen
) const
184 const LocaleNode
* pNode
= findNode( pNodeName
);
185 if (pNode
|| nMinLen
< 0)
186 aVal
= writeParameterCheckLen( of
, pParameterName
, pNode
, nMinLen
, nMaxLen
);
190 fprintf( stderr
, "Error: node %s not found.\n", pNodeName
);
191 // write empty data if error
192 of
.writeParameter( pParameterName
, aVal
);
197 void LocaleNode::incError( const char* pStr
) const
200 fprintf( stderr
, "Error: %s\n", pStr
);
203 void LocaleNode::incError( const OUString
& rStr
) const
205 incError( OSTR( rStr
));
208 void LocaleNode::incErrorInt( const char* pStr
, int nVal
) const
211 fprintf( stderr
, pStr
, nVal
);
214 void LocaleNode::incErrorStr( const char* pStr
, const OUString
& rVal
) const
217 fprintf( stderr
, pStr
, OSTR( rVal
));
220 void LocaleNode::incErrorStrStr( const char* pStr
, const OUString
& rVal1
, const OUString
& rVal2
) const
223 fprintf(stderr
, pStr
, OSTR(rVal1
), OSTR(rVal2
));
226 void LCInfoNode::generateCode (const OFileWriter
&of
) const
229 const LocaleNode
* languageNode
= findNode("Language");
230 const LocaleNode
* countryNode
= findNode("Country");
231 const LocaleNode
* variantNode
= findNode("Variant");
237 aLanguage
= languageNode
->getChildAt(0)->getValue();
238 if (!(aLanguage
.getLength() == 2 || aLanguage
.getLength() == 3))
239 incErrorStr( "Error: langID '%s' not 2-3 characters\n", aLanguage
);
240 of
.writeParameter("langID", aLanguage
);
241 of
.writeParameter("langDefaultName", languageNode
->getChildAt(1)->getValue());
244 incError( "No Language node.");
247 OUString
aCountry( countryNode
->getChildAt(0)->getValue());
248 if (!(aCountry
.isEmpty() || aCountry
.getLength() == 2))
249 incErrorStr( "Error: countryID '%s' not empty or more than 2 characters\n", aCountry
);
250 of
.writeParameter("countryID", aCountry
);
251 of
.writeParameter("countryDefaultName", countryNode
->getChildAt(1)->getValue());
254 incError( "No Country node.");
257 // If given Variant must be at least ll-Ssss and language must be 'qlt'
258 const OUString
& aVariant( variantNode
->getValue());
259 if (!(aVariant
.isEmpty() || (aVariant
.getLength() >= 7 && aVariant
.indexOf('-') >= 2)))
260 incErrorStr( "Error: invalid Variant '%s'\n", aVariant
);
261 if (!(aVariant
.isEmpty() || aLanguage
== "qlt"))
262 incErrorStrStr( "Error: Variant '%s' given but Language '%s' is not 'qlt'\n", aVariant
, aLanguage
);
263 of
.writeParameter("Variant", aVariant
);
266 of
.writeParameter("Variant", OUString());
267 of
.writeAsciiString("\nstatic const sal_Unicode* LCInfoArray[] = {\n");
268 of
.writeAsciiString("\tlangID,\n");
269 of
.writeAsciiString("\tlangDefaultName,\n");
270 of
.writeAsciiString("\tcountryID,\n");
271 of
.writeAsciiString("\tcountryDefaultName,\n");
272 of
.writeAsciiString("\tVariant\n");
273 of
.writeAsciiString("};\n\n");
274 of
.writeFunction("getLCInfo_", "SAL_N_ELEMENTS(LCInfoArray)", "LCInfoArray");
278 static OUString aDateSep
;
279 static OUString aDecSep
;
281 void LCCTYPENode::generateCode (const OFileWriter
&of
) const
283 const LocaleNode
* sepNode
= nullptr;
284 OUString useLocale
= getAttr().getValueByName("ref");
285 if (!useLocale
.isEmpty()) {
286 useLocale
= useLocale
.replace( '-', '_');
287 of
.writeRefFunction("getLocaleItem_", useLocale
);
290 OUString str
= getAttr().getValueByName("unoid");
291 of
.writeAsciiString("\n\n");
292 of
.writeParameter("LC_CTYPE_Unoid", str
);
295 writeParameterCheckLen( of
, "DateSeparator", "dateSeparator", 1, 1);
297 writeParameterCheckLen( of
, "ThousandSeparator", "thousandSeparator", 1, 1);
299 writeParameterCheckLen( of
, "DecimalSeparator", "decimalSeparator", 1, 1);
300 OUString aDecSepAlt
=
301 writeParameterCheckLen( of
, "DecimalSeparatorAlternative", "decimalSeparatorAlternative", -1, 1);
303 writeParameterCheckLen( of
, "TimeSeparator", "timeSeparator", 1, 1);
304 OUString aTime100Sep
=
305 writeParameterCheckLen( of
, "Time100SecSeparator", "time100SecSeparator", 1, 1);
307 writeParameterCheckLen( of
, "ListSeparator", "listSeparator", 1, 1);
311 sepNode
= findNode("LongDateDayOfWeekSeparator");
312 aLDS
= sepNode
->getValue();
313 of
.writeParameter("LongDateDayOfWeekSeparator", aLDS
);
315 fprintf( stderr
, "Warning: %s\n",
316 "LongDateDayOfWeekSeparator is only a comma not followed by a space. Usually this is not the case and may lead to concatenated display names like \"Wednesday,May 9, 2007\".");
318 sepNode
= findNode("LongDateDaySeparator");
319 aLDS
= sepNode
->getValue();
320 of
.writeParameter("LongDateDaySeparator", aLDS
);
321 if (aLDS
== "," || aLDS
== ".")
322 fprintf( stderr
, "Warning: %s\n",
323 "LongDateDaySeparator is only a comma or dot not followed by a space. Usually this is not the case and may lead to concatenated display names like \"Wednesday, May 9,2007\".");
325 sepNode
= findNode("LongDateMonthSeparator");
326 aLDS
= sepNode
->getValue();
327 of
.writeParameter("LongDateMonthSeparator", aLDS
);
329 fprintf( stderr
, "Warning: %s\n",
330 "LongDateMonthSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, May9, 2007\".");
332 sepNode
= findNode("LongDateYearSeparator");
333 aLDS
= sepNode
->getValue();
334 of
.writeParameter("LongDateYearSeparator", aLDS
);
336 fprintf( stderr
, "Warning: %s\n",
337 "LongDateYearSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, 2007May 9\".");
339 int nSavErr
= nError
;
341 if (aDateSep
== aTimeSep
)
342 incError( "DateSeparator equals TimeSeparator.");
343 if (aDecSep
== aThoSep
)
344 incError( "DecimalSeparator equals ThousandSeparator.");
345 if (aDecSepAlt
== aThoSep
)
346 incError( "DecimalSeparatorAlternative equals ThousandSeparator.");
347 if (aDecSepAlt
== aDecSep
)
348 incError( "DecimalSeparatorAlternative equals DecimalSeparator, it must not be specified then.");
349 if ( aThoSep
== " " )
350 incError( "ThousandSeparator is an ' ' ordinary space, this should be a non-breaking space U+00A0 instead.");
351 if (aListSep
== aDecSep
)
352 fprintf( stderr
, "Warning: %s\n",
353 "ListSeparator equals DecimalSeparator.");
354 if (aListSep
== aThoSep
)
355 fprintf( stderr
, "Warning: %s\n",
356 "ListSeparator equals ThousandSeparator.");
357 if (aListSep
.getLength() != 1 || aListSep
[0] != ';')
359 incError( "ListSeparator not ';' semicolon. Strongly recommended. Currently required.");
360 ++nSavErr
; // format codes not affected
362 if (aTimeSep
== aTime100Sep
)
365 fprintf( stderr
, "Warning: %s\n",
366 "Time100SecSeparator equals TimeSeparator, this is probably an error.");
368 if (aDecSep
!= aTime100Sep
)
371 fprintf( stderr
, "Warning: %s\n",
372 "Time100SecSeparator is different from DecimalSeparator, this may be correct or not. Intended?");
374 if (nSavErr
!= nError
|| nWarn
)
375 fprintf( stderr
, "Warning: %s\n",
376 "Don't forget to adapt corresponding FormatCode elements when changing separators.");
378 OUString aQuoteStart
=
379 writeParameterCheckLen( of
, "QuotationStart", "quotationStart", 1, 1);
381 writeParameterCheckLen( of
, "QuotationEnd", "quotationEnd", 1, 1);
382 OUString aDoubleQuoteStart
=
383 writeParameterCheckLen( of
, "DoubleQuotationStart", "doubleQuotationStart", 1, 1);
384 OUString aDoubleQuoteEnd
=
385 writeParameterCheckLen( of
, "DoubleQuotationEnd", "doubleQuotationEnd", 1, 1);
387 if (aQuoteStart
.toChar() <= 127 && aQuoteEnd
.toChar() > 127)
388 fprintf( stderr
, "Warning: %s\n",
389 "QuotationStart is an ASCII character but QuotationEnd is not.");
390 if (aQuoteEnd
.toChar() <= 127 && aQuoteStart
.toChar() > 127)
391 fprintf( stderr
, "Warning: %s\n",
392 "QuotationEnd is an ASCII character but QuotationStart is not.");
393 if (aDoubleQuoteStart
.toChar() <= 127 && aDoubleQuoteEnd
.toChar() > 127)
394 fprintf( stderr
, "Warning: %s\n",
395 "DoubleQuotationStart is an ASCII character but DoubleQuotationEnd is not.");
396 if (aDoubleQuoteEnd
.toChar() <= 127 && aDoubleQuoteStart
.toChar() > 127)
397 fprintf( stderr
, "Warning: %s\n",
398 "DoubleQuotationEnd is an ASCII character but DoubleQuotationStart is not.");
399 if (aQuoteStart
.toChar() <= 127 && aQuoteEnd
.toChar() <= 127)
400 fprintf( stderr
, "Warning: %s\n",
401 "QuotationStart and QuotationEnd are both ASCII characters. Not necessarily an issue, but unusual.");
402 if (aDoubleQuoteStart
.toChar() <= 127 && aDoubleQuoteEnd
.toChar() <= 127)
403 fprintf( stderr
, "Warning: %s\n",
404 "DoubleQuotationStart and DoubleQuotationEnd are both ASCII characters. Not necessarily an issue, but unusual.");
405 if (aQuoteStart
== aQuoteEnd
)
406 fprintf( stderr
, "Warning: %s\n",
407 "QuotationStart equals QuotationEnd. Not necessarily an issue, but unusual.");
408 if (aDoubleQuoteStart
== aDoubleQuoteEnd
)
409 fprintf( stderr
, "Warning: %s\n",
410 "DoubleQuotationStart equals DoubleQuotationEnd. Not necessarily an issue, but unusual.");
411 /* TODO: should equalness of single and double quotes be an error? Would
412 * need to adapt quite some locales' data. */
413 if (aQuoteStart
== aDoubleQuoteStart
)
414 fprintf( stderr
, "Warning: %s\n",
415 "QuotationStart equals DoubleQuotationStart. Not necessarily an issue, but unusual.");
416 if (aQuoteEnd
== aDoubleQuoteEnd
)
417 fprintf( stderr
, "Warning: %s\n",
418 "QuotationEnd equals DoubleQuotationEnd. Not necessarily an issue, but unusual.");
419 // Known good values, exclude ASCII single (U+0027, ') and double (U+0022, ") quotes.
420 switch (int ic
= aQuoteStart
.toChar())
422 case 0x2018: // LEFT SINGLE QUOTATION MARK
423 case 0x201a: // SINGLE LOW-9 QUOTATION MARK
424 case 0x201b: // SINGLE HIGH-REVERSED-9 QUOTATION MARK
425 case 0x2039: // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
426 case 0x203a: // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
427 case 0x300c: // LEFT CORNER BRACKET (Chinese)
431 fprintf( stderr
, "Warning: %s U+%04X %s\n",
432 "QuotationStart may be wrong:", ic
, OSTR( aQuoteStart
));
434 switch (int ic
= aQuoteEnd
.toChar())
436 case 0x2019: // RIGHT SINGLE QUOTATION MARK
437 case 0x201a: // SINGLE LOW-9 QUOTATION MARK
438 case 0x201b: // SINGLE HIGH-REVERSED-9 QUOTATION MARK
439 case 0x2039: // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
440 case 0x203a: // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
441 case 0x300d: // RIGHT CORNER BRACKET (Chinese)
445 fprintf( stderr
, "Warning: %s U+%04X %s\n",
446 "QuotationEnd may be wrong:", ic
, OSTR( aQuoteEnd
));
448 switch (int ic
= aDoubleQuoteStart
.toChar())
450 case 0x00ab: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
451 case 0x00bb: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
452 case 0x201c: // LEFT DOUBLE QUOTATION MARK
453 case 0x201e: // DOUBLE LOW-9 QUOTATION MARK
454 case 0x201f: // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
455 case 0x300e: // LEFT WHITE CORNER BRACKET (Chinese)
459 fprintf( stderr
, "Warning: %s U+%04X %s\n",
460 "DoubleQuotationStart may be wrong:", ic
, OSTR( aDoubleQuoteStart
));
462 switch (int ic
= aDoubleQuoteEnd
.toChar())
464 case 0x00ab: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
465 case 0x00bb: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
466 case 0x201d: // RIGHT DOUBLE QUOTATION MARK
467 case 0x201e: // DOUBLE LOW-9 QUOTATION MARK
468 case 0x201f: // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
469 case 0x300f: // RIGHT WHITE CORNER BRACKET (Chinese)
473 fprintf( stderr
, "Warning: %s U+%04X %s\n",
474 "DoubleQuotationEnd may be wrong:", ic
, OSTR( aDoubleQuoteEnd
));
477 writeParameterCheckLen( of
, "TimeAM", "timeAM", 1, -1);
478 writeParameterCheckLen( of
, "TimePM", "timePM", 1, -1);
479 sepNode
= findNode("MeasurementSystem");
480 of
.writeParameter("measurementSystem", sepNode
->getValue());
482 of
.writeAsciiString("\nstatic const sal_Unicode* LCType[] = {\n");
483 of
.writeAsciiString("\tLC_CTYPE_Unoid,\n");
484 of
.writeAsciiString("\tdateSeparator,\n");
485 of
.writeAsciiString("\tthousandSeparator,\n");
486 of
.writeAsciiString("\tdecimalSeparator,\n");
487 of
.writeAsciiString("\ttimeSeparator,\n");
488 of
.writeAsciiString("\ttime100SecSeparator,\n");
489 of
.writeAsciiString("\tlistSeparator,\n");
490 of
.writeAsciiString("\tquotationStart,\n");
491 of
.writeAsciiString("\tquotationEnd,\n");
492 of
.writeAsciiString("\tdoubleQuotationStart,\n");
493 of
.writeAsciiString("\tdoubleQuotationEnd,\n");
494 of
.writeAsciiString("\ttimeAM,\n");
495 of
.writeAsciiString("\ttimePM,\n");
496 of
.writeAsciiString("\tmeasurementSystem,\n");
497 of
.writeAsciiString("\tLongDateDayOfWeekSeparator,\n");
498 of
.writeAsciiString("\tLongDateDaySeparator,\n");
499 of
.writeAsciiString("\tLongDateMonthSeparator,\n");
500 of
.writeAsciiString("\tLongDateYearSeparator,\n");
501 of
.writeAsciiString("\tdecimalSeparatorAlternative\n");
502 of
.writeAsciiString("};\n\n");
503 of
.writeFunction("getLocaleItem_", "SAL_N_ELEMENTS(LCType)", "LCType");
507 static OUString sTheCurrencyReplaceTo
;
508 static OUString sTheCompatibleCurrency
;
509 static OUString sTheDateEditFormat
;
511 sal_Int16
LCFormatNode::mnSection
= 0;
512 sal_Int16
LCFormatNode::mnFormats
= 0;
514 void LCFormatNode::generateCode (const OFileWriter
&of
) const
517 incError("more than 2 LC_FORMAT sections");
519 ::std::vector
< OUString
> theDateAcceptancePatterns
;
521 OUString
useLocale(getAttr().getValueByName("ref"));
524 OUString
strFrom( getAttr().getValueByName("replaceFrom"));
525 if (useLocale
.isEmpty())
527 of
.writeParameter("replaceFrom", strFrom
, mnSection
);
529 str
= getAttr().getValueByName("replaceTo");
530 if (!strFrom
.isEmpty() && str
.isEmpty())
531 incErrorStr("replaceFrom=\"%s\" replaceTo=\"\" is empty replacement.\n", strFrom
);
532 // Locale data generator inserts FFFF for LangID, we need to adapt that.
533 if (str
.endsWithIgnoreAsciiCase( "-FFFF]"))
534 incErrorStr("replaceTo=\"%s\" needs FFFF to be adapted to the real LangID value.\n", str
);
535 of
.writeParameter("replaceTo", str
, mnSection
);
536 // Remember the replaceTo value for "[CURRENCY]" to check format codes.
537 if ( strFrom
== "[CURRENCY]" )
538 sTheCurrencyReplaceTo
= str
;
539 // Remember the currency symbol if present.
540 if (str
.startsWith( "[$" ))
542 sal_Int32 nHyphen
= str
.indexOf( '-');
545 sTheCompatibleCurrency
= str
.copy( 2, nHyphen
- 2);
549 if (!useLocale
.isEmpty())
551 if (!strFrom
.isEmpty() && strFrom
!= "[CURRENCY]") //???
554 "Error: non-empty replaceFrom=\"%s\" with non-empty ref=\"%s\".",
557 useLocale
= useLocale
.replace( '-', '_');
561 of
.writeRefFunction("getAllFormats0_", useLocale
, "replaceTo0");
564 of
.writeRefFunction("getAllFormats1_", useLocale
, "replaceTo1");
567 of
.writeRefFunction("getDateAcceptancePatterns_", useLocale
);
571 sal_Int16 formatCount
= mnFormats
;
573 ValueSet aFormatIndexSet
;
574 NameSet aDefaultsSet
;
575 bool bCtypeIsRef
= false;
576 bool bHaveEngineering
= false;
577 bool bShowNextFreeFormatIndex
= false;
579 for (sal_Int32 i
= 0; i
< getNumberOfChildren() ; i
++, formatCount
++)
581 LocaleNode
* currNode
= getChildAt (i
);
582 if ( currNode
->getName() == "DateAcceptancePattern" )
585 incError( "DateAcceptancePattern only handled in LC_FORMAT, not LC_FORMAT_1");
587 theDateAcceptancePatterns
.push_back( currNode
->getValue());
591 if ( currNode
->getName() != "FormatElement" )
593 incErrorStr( "Error: Undefined element '%s' in LC_FORMAT\n", currNode
->getName());
600 OUString aFormatIndex
;
601 // currNode -> print();
602 const Attr
&currNodeAttr
= currNode
->getAttr();
603 //printf ("getLen() = %d\n", currNode->getAttr().getLength());
605 str
= currNodeAttr
.getValueByName("msgid");
606 if (!aMsgIdSet
.insert( str
).second
)
607 incErrorStr( "Error: Duplicated msgid=\"%s\" in FormatElement.\n", str
);
608 of
.writeParameter("FormatKey", str
, formatCount
);
610 str
= currNodeAttr
.getValueByName("default");
611 bool bDefault
= str
== "true";
612 of
.writeDefaultParameter("FormatElement", str
, formatCount
);
614 aType
= currNodeAttr
.getValueByName("type");
615 of
.writeParameter("FormatType", aType
, formatCount
);
617 aUsage
= currNodeAttr
.getValueByName("usage");
618 of
.writeParameter("FormatUsage", aUsage
, formatCount
);
620 aFormatIndex
= currNodeAttr
.getValueByName("formatindex");
621 sal_Int16 formatindex
= static_cast<sal_Int16
>(aFormatIndex
.toInt32());
622 // Ensure the new reserved range is not used anymore, free usage start
623 // was up'ed from 50 to 60.
624 if (50 <= formatindex
&& formatindex
< i18npool::nFirstFreeFormatIndex
)
626 incErrorInt( "Error: Reserved formatindex=\"%d\" in FormatElement.\n", formatindex
);
627 bShowNextFreeFormatIndex
= true;
629 if (!aFormatIndexSet
.insert( formatindex
).second
)
631 incErrorInt( "Error: Duplicated formatindex=\"%d\" in FormatElement.\n", formatindex
);
632 bShowNextFreeFormatIndex
= true;
634 of
.writeIntParameter("Formatindex", formatCount
, formatindex
);
636 // Ensure only one default per usage and type.
639 OUString
aKey( aUsage
+ "," + aType
);
640 if (!aDefaultsSet
.insert( aKey
).second
)
642 OUString aStr
= "Duplicated default for usage=\"" + aUsage
+ "\" type=\"" + aType
+ "\": formatindex=\"" + aFormatIndex
+ "\".";
647 const LocaleNode
* n
= currNode
-> findNode("FormatCode");
650 of
.writeParameter("FormatCode", n
->getValue(), formatCount
);
651 // Check separator usage for some FormatCode elements.
652 const LocaleNode
* pCtype
= nullptr;
655 case cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
:
656 sTheDateEditFormat
= n
->getValue();
658 case cssi::NumberFormatIndex::NUMBER_1000DEC2
: // #,##0.00
659 case cssi::NumberFormatIndex::TIME_MMSS00
: // MM:SS.00
660 case cssi::NumberFormatIndex::TIME_HH_MMSS00
: // [HH]:MM:SS.00
662 const LocaleNode
* pRoot
= getRoot();
664 incError( "No root for FormatCode.");
667 pCtype
= pRoot
->findNode( "LC_CTYPE");
669 incError( "No LC_CTYPE found for FormatCode.");
672 OUString
aRef( pCtype
->getAttr().getValueByName("ref"));
675 aRef
= aRef
.replace( '-', '_');
678 "Warning: Can't check separators used in FormatCode due to LC_CTYPE ref=\"%s\".\n"
679 "If these two locales use identical format codes, you should consider to use the ref= mechanism also for the LC_FORMAT element, together with replaceFrom= and replaceTo= for the currency.\n",
688 case cssi::NumberFormatIndex::CURRENCY_1000DEC2
:
689 // Remember the currency symbol if present.
692 if (sTheCompatibleCurrency
.isEmpty() &&
693 ((nStart
= n
->getValue().indexOf("[$")) >= 0))
695 const OUString
& aCode( n
->getValue());
696 sal_Int32 nHyphen
= aCode
.indexOf( '-', nStart
);
697 if (nHyphen
>= nStart
+ 3)
698 sTheCompatibleCurrency
= aCode
.copy( nStart
+ 2, nHyphen
- nStart
- 2);
702 case cssi::NumberFormatIndex::CURRENCY_1000INT
:
703 case cssi::NumberFormatIndex::CURRENCY_1000INT_RED
:
704 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_RED
:
705 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_CCC
:
706 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_DASHED
:
707 // Currency formats should be something like [C]###0;-[C]###0
708 // and not parenthesized [C]###0;([C]###0) if not en_US.
709 if (strcmp( of
.getLocale(), "en_US") != 0)
711 const OUString
& aCode( n
->getValue());
712 OUString
const aPar1( "0)");
713 OUString
const aPar2( "-)" );
714 OUString
const aPar3( " )" );
715 OUString
const aPar4( "])" );
716 if (aCode
.indexOf( aPar1
) > 0 || aCode
.indexOf( aPar2
) > 0 ||
717 aCode
.indexOf( aPar3
) > 0 || aCode
.indexOf( aPar4
) > 0)
718 fprintf( stderr
, "Warning: FormatCode formatindex=\"%d\" for currency uses parentheses for negative amounts, which probably is not correct for locales not based on en_US.\n", formatindex
);
720 // Check if we have replaceTo for "[CURRENCY]" placeholder.
721 if (sTheCurrencyReplaceTo
.isEmpty())
723 const OUString
& aCode( n
->getValue());
724 if (aCode
.indexOf( "[CURRENCY]" ) >= 0)
725 incErrorInt( "Error: [CURRENCY] replaceTo not found for formatindex=\"%d\".\n", formatindex
);
729 if (aUsage
== "SCIENTIFIC_NUMBER")
731 // Check for presence of ##0.00E+00
732 const OUString
& aCode( n
->getValue());
733 // Simple check without decimal separator (assumed to
734 // be one UTF-16 character). May be prefixed with
735 // [NatNum1] or other tags.
736 sal_Int32 nInt
= aCode
.indexOf("##0");
737 sal_Int32 nDec
= (nInt
< 0 ? -1 : aCode
.indexOf("00E+00", nInt
));
738 if (nInt
>= 0 && nDec
== nInt
+4)
739 bHaveEngineering
= true;
745 int nSavErr
= nError
;
746 const OUString
& aCode( n
->getValue());
747 if (formatindex
== cssi::NumberFormatIndex::NUMBER_1000DEC2
)
751 const LocaleNode
* pSep
= pCtype
->findNode( "DecimalSeparator");
753 incError( "No DecimalSeparator found for FormatCode.");
756 nDec
= aCode
.indexOf( pSep
->getValue());
758 incErrorInt( "Error: DecimalSeparator not present in FormatCode formatindex=\"%d\".\n",
761 pSep
= pCtype
->findNode( "ThousandSeparator");
763 incError( "No ThousandSeparator found for FormatCode.");
766 nGrp
= aCode
.indexOf( pSep
->getValue());
768 incErrorInt( "Error: ThousandSeparator not present in FormatCode formatindex=\"%d\".\n",
771 if (nDec
>= 0 && nGrp
>= 0 && nDec
<= nGrp
)
772 incErrorInt( "Error: Ordering of ThousandSeparator and DecimalSeparator not correct in formatindex=\"%d\".\n",
775 if (formatindex
== cssi::NumberFormatIndex::TIME_MMSS00
||
776 formatindex
== cssi::NumberFormatIndex::TIME_HH_MMSS00
)
778 sal_Int32 nTime
= -1;
779 sal_Int32 n100s
= -1;
780 const LocaleNode
* pSep
= pCtype
->findNode( "TimeSeparator");
782 incError( "No TimeSeparator found for FormatCode.");
785 nTime
= aCode
.indexOf( pSep
->getValue());
787 incErrorInt( "Error: TimeSeparator not present in FormatCode formatindex=\"%d\".\n",
790 pSep
= pCtype
->findNode( "Time100SecSeparator");
792 incError( "No Time100SecSeparator found for FormatCode.");
795 n100s
= aCode
.indexOf( pSep
->getValue());
797 incErrorInt( "Error: Time100SecSeparator not present in FormatCode formatindex=\"%d\".\n",
799 n100s
= aCode
.indexOf( pSep
->getValue() + "00");
801 incErrorInt( "Error: Time100SecSeparator+00 not present in FormatCode formatindex=\"%d\".\n",
804 if (n100s
>= 0 && nTime
>= 0 && n100s
<= nTime
)
805 incErrorInt( "Error: Ordering of Time100SecSeparator and TimeSeparator not correct in formatindex=\"%d\".\n",
808 if (nSavErr
!= nError
)
810 "Warning: formatindex=\"%d\",\"%d\",\"%d\" are the only FormatCode elements checked for separator usage, there may be others that have errors.\n",
811 int(cssi::NumberFormatIndex::NUMBER_1000DEC2
),
812 int(cssi::NumberFormatIndex::TIME_MMSS00
),
813 int(cssi::NumberFormatIndex::TIME_HH_MMSS00
));
818 incError( "No FormatCode in FormatElement.");
819 n
= currNode
-> findNode("DefaultName");
821 of
.writeParameter("FormatDefaultName", n
->getValue(), formatCount
);
823 of
.writeParameter("FormatDefaultName", OUString(), formatCount
);
827 if (bShowNextFreeFormatIndex
)
829 sal_Int16 nNext
= i18npool::nFirstFreeFormatIndex
;
830 std::set
<sal_Int16
>::const_iterator
it( aFormatIndexSet
.find( nNext
));
831 if (it
!= aFormatIndexSet
.end())
833 // nFirstFreeFormatIndex already used, find next free including gaps.
838 while (++it
!= aFormatIndexSet
.end() && *it
== nNext
);
840 fprintf( stderr
, "Hint: Next free formatindex is %d.\n", static_cast<int>(nNext
));
843 // Check presence of all required format codes only in first section
844 // LC_FORMAT, not in optional LC_FORMAT_1
847 // At least one abbreviated date acceptance pattern must be present.
848 if (theDateAcceptancePatterns
.empty())
849 incError( "No DateAcceptancePattern present.\n");
852 bool bHaveAbbr
= false;
853 for (auto const& elem
: theDateAcceptancePatterns
)
855 if (elem
.indexOf('D') > -1 && elem
.indexOf('M') > -1 && elem
.indexOf('Y') <= -1)
862 incError( "No abbreviated DateAcceptancePattern present. For example M/D or D.M.\n");
865 // 0..47 MUST be present, 48,49 MUST NOT be present
866 ValueSet::const_iterator
aIter( aFormatIndexSet
.begin());
867 for (sal_Int16 nNext
= cssi::NumberFormatIndex::NUMBER_START
;
868 nNext
< cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES
; ++nNext
)
870 sal_Int16 nHere
= ::std::min( (aIter
!= aFormatIndexSet
.end() ? *aIter
:
871 cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES
),
872 cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES
);
873 if (aIter
!= aFormatIndexSet
.end()) ++aIter
;
874 for ( ; nNext
< nHere
; ++nNext
)
878 case cssi::NumberFormatIndex::FRACTION_1
:
879 case cssi::NumberFormatIndex::FRACTION_2
:
880 case cssi::NumberFormatIndex::BOOLEAN
:
881 case cssi::NumberFormatIndex::TEXT
:
882 // generated internally
885 incErrorInt( "Error: FormatElement formatindex=\"%d\" not present.\n", nNext
);
890 case cssi::NumberFormatIndex::BOOLEAN
:
891 incErrorInt( "Error: FormatElement formatindex=\"%d\" reserved for internal ``BOOLEAN''.\n", nNext
);
893 case cssi::NumberFormatIndex::TEXT
:
894 incErrorInt( "Error: FormatElement formatindex=\"%d\" reserved for internal ``@'' (TEXT).\n", nNext
);
901 if (!bHaveEngineering
)
902 incError("Engineering notation format not present, e.g. ##0.00E+00 or ##0,00E+00 for usage=\"SCIENTIFIC_NUMBER\"\n");
905 of
.writeAsciiString("\nstatic const sal_Int16 ");
906 of
.writeAsciiString("FormatElementsCount");
907 of
.writeInt(mnSection
);
908 of
.writeAsciiString(" = ");
909 of
.writeInt( formatCount
- mnFormats
);
910 of
.writeAsciiString(";\n");
911 of
.writeAsciiString("static const sal_Unicode* ");
912 of
.writeAsciiString("FormatElementsArray");
913 of
.writeInt(mnSection
);
914 of
.writeAsciiString("[] = {\n");
915 for(sal_Int16 i
= mnFormats
; i
< formatCount
; i
++) {
917 of
.writeAsciiString("\t");
918 of
.writeAsciiString("FormatCode");
920 of
.writeAsciiString(",\n");
922 of
.writeAsciiString("\t");
923 of
.writeAsciiString("FormatDefaultName");
925 of
.writeAsciiString(",\n");
927 of
.writeAsciiString("\t");
928 of
.writeAsciiString("FormatKey");
930 of
.writeAsciiString(",\n");
932 of
.writeAsciiString("\t");
933 of
.writeAsciiString("FormatType");
935 of
.writeAsciiString(",\n");
937 of
.writeAsciiString("\t");
938 of
.writeAsciiString("FormatUsage");
940 of
.writeAsciiString(",\n");
942 of
.writeAsciiString("\t");
943 of
.writeAsciiString("Formatindex");
945 of
.writeAsciiString(",\n");
948 of
.writeAsciiString("\tdefaultFormatElement");
950 of
.writeAsciiString(",\n");
952 of
.writeAsciiString("};\n\n");
957 of
.writeFunction("getAllFormats0_", "FormatElementsCount0", "FormatElementsArray0", "replaceFrom0", "replaceTo0");
960 of
.writeFunction("getAllFormats1_", "FormatElementsCount1", "FormatElementsArray1", "replaceFrom1", "replaceTo1");
964 mnFormats
= mnFormats
+ formatCount
;
968 // Extract and add date acceptance pattern for full date, so we provide
969 // at least one valid pattern, even if the number parser doesn't need
971 /* XXX NOTE: only simple [...] modifier and "..." quotes detected and
972 * ignored, not nested, no fancy stuff. */
973 sal_Int32 nIndex
= 0;
974 // aDateSep can be empty if LC_CTYPE was a ref=..., determine from
976 sal_uInt32 cDateSep
= (aDateSep
.isEmpty() ? 0 : aDateSep
.iterateCodePoints( &nIndex
));
977 sal_uInt32 cDateSep2
= cDateSep
;
979 OUStringBuffer
aPatternBuf(5);
980 OUStringBuffer
aPatternBuf2(5);
981 sal_uInt8 nDetected
= 0; // bits Y,M,D
982 bool bInModifier
= false;
983 bool bQuoted
= false;
984 while (nIndex
< sTheDateEditFormat
.getLength() && nDetected
< 7)
986 sal_uInt32 cChar
= sTheDateEditFormat
.iterateCodePoints( &nIndex
);
1003 if (!(nDetected
& 4))
1005 aPatternBuf
.append( 'Y');
1006 if (!aPatternBuf2
.isEmpty())
1007 aPatternBuf2
.append( 'Y');
1013 if (!(nDetected
& 2))
1015 aPatternBuf
.append( 'M');
1016 if (!aPatternBuf2
.isEmpty())
1017 aPatternBuf2
.append( 'M');
1023 if (!(nDetected
& 1))
1025 aPatternBuf
.append( 'D');
1026 if (!aPatternBuf2
.isEmpty())
1027 aPatternBuf2
.append( 'D');
1038 cChar
= sTheDateEditFormat
.iterateCodePoints( &nIndex
);
1043 // There are locales that use an ISO 8601 edit format
1044 // regardless of what the date separator or other formats
1045 // say, for example hu-HU. Generalize this for all cases
1046 // where the used separator differs and is one of the known
1047 // separators and generate a second pattern with the
1048 // format's separator at the current position.
1057 if (cDateSep
!= cDateSep2
&& aPatternBuf2
.isEmpty())
1058 aPatternBuf2
= aPatternBuf
;
1059 if (cChar
== cDateSep
|| cChar
== cDateSep2
)
1060 aPatternBuf
.append( OUString( &cDateSep
, 1)); // always the defined separator
1061 if (cChar
== cDateSep2
&& !aPatternBuf2
.isEmpty())
1062 aPatternBuf2
.append( OUString( &cDateSep2
, 1)); // always the format's separator
1064 // The localized legacy:
1066 if (((nDetected
& 7) == 3) || ((nDetected
& 7) == 0))
1072 aPatternBuf
.append( 'Y');
1073 if (!aPatternBuf2
.isEmpty())
1074 aPatternBuf2
.append( 'Y');
1079 if (((nDetected
& 7) == 0) || ((nDetected
& 7) == 6))
1083 aPatternBuf
.append( 'D');
1084 if (!aPatternBuf2
.isEmpty())
1085 aPatternBuf2
.append( 'D');
1088 else if ((nDetected
& 7) == 3)
1092 aPatternBuf
.append( 'Y');
1093 if (!aPatternBuf2
.isEmpty())
1094 aPatternBuf2
.append( 'Y');
1099 if ((nDetected
& 7) == 0)
1102 aPatternBuf
.append( 'D');
1103 if (!aPatternBuf2
.isEmpty())
1104 aPatternBuf2
.append( 'D');
1109 if ((nDetected
& 7) == 0)
1112 aPatternBuf
.append( 'D');
1113 if (!aPatternBuf2
.isEmpty())
1114 aPatternBuf2
.append( 'D');
1119 if ((nDetected
& 7) == 0)
1122 aPatternBuf
.append( 'D');
1123 if (!aPatternBuf2
.isEmpty())
1124 aPatternBuf2
.append( 'D');
1129 if ((nDetected
& 7) == 1)
1132 aPatternBuf
.append( 'M');
1133 if (!aPatternBuf2
.isEmpty())
1134 aPatternBuf2
.append( 'M');
1139 if ((nDetected
& 7) == 3)
1142 aPatternBuf
.append( 'Y');
1143 if (!aPatternBuf2
.isEmpty())
1144 aPatternBuf2
.append( 'Y');
1150 OUString
aPattern( aPatternBuf
.makeStringAndClear());
1151 if (((nDetected
& 7) != 7) || aPattern
.getLength() < 5)
1153 incErrorStr( "Error: failed to extract full date acceptance pattern: %s\n", aPattern
);
1154 fprintf( stderr
, " with DateSeparator '%s' from FormatCode '%s' (formatindex=\"%d\")\n",
1155 OSTR( OUString(&cDateSep
, 1)), OSTR( sTheDateEditFormat
),
1156 int(cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
));
1160 fprintf( stderr
, "Generated date acceptance pattern: '%s' from '%s' (formatindex=\"%d\" and defined DateSeparator '%s')\n",
1161 OSTR( aPattern
), OSTR( sTheDateEditFormat
),
1162 int(cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
),
1163 OSTR( OUString(&cDateSep
, 1)));
1164 // Insert at front so full date pattern is first in checks.
1165 theDateAcceptancePatterns
.insert( theDateAcceptancePatterns
.begin(), aPattern
);
1167 if (!aPatternBuf2
.isEmpty())
1169 OUString
aPattern2( aPatternBuf2
.makeStringAndClear());
1170 if (aPattern2
.getLength() < 5)
1172 incErrorStr( "Error: failed to extract 2nd date acceptance pattern: %s\n", aPattern2
);
1173 fprintf( stderr
, " with DateSeparator '%s' from FormatCode '%s' (formatindex=\"%d\")\n",
1174 OSTR( OUString(&cDateSep2
, 1)), OSTR( sTheDateEditFormat
),
1175 int(cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
));
1179 fprintf( stderr
, "Generated 2nd acceptance pattern: '%s' from '%s' (formatindex=\"%d\")\n",
1180 OSTR( aPattern2
), OSTR( sTheDateEditFormat
),
1181 int(cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
));
1182 theDateAcceptancePatterns
.insert( theDateAcceptancePatterns
.begin(), aPattern2
);
1186 // Rudimentary check if a pattern interferes with decimal number.
1187 // But only if not inherited in which case we don't have aDecSep here.
1188 if (!aDecSep
.isEmpty())
1191 sal_uInt32 cDecSep
= aDecSep
.iterateCodePoints( &nIndex
);
1192 for (auto const& elem
: theDateAcceptancePatterns
)
1194 if (elem
.getLength() == (cDecSep
<= 0xffff ? 3 : 4))
1197 if (elem
.iterateCodePoints( &nIndex
) == cDecSep
)
1200 fprintf( stderr
, "Error: Date acceptance pattern '%s' matches decimal number '#%s#'\n",
1201 OSTR(elem
), OSTR( aDecSep
));
1207 // Check for duplicates.
1208 for (vector
<OUString
>::const_iterator aIt
= theDateAcceptancePatterns
.begin();
1209 aIt
!= theDateAcceptancePatterns
.end(); ++aIt
)
1211 for (vector
<OUString
>::iterator aComp
= theDateAcceptancePatterns
.begin();
1212 aComp
!= theDateAcceptancePatterns
.end(); /*nop*/)
1214 if (aIt
!= aComp
&& *aIt
== *aComp
)
1216 incErrorStr( "Error: Duplicated DateAcceptancePattern: %s\n", *aComp
);
1217 aComp
= theDateAcceptancePatterns
.erase( aComp
);
1224 sal_Int16 nbOfDateAcceptancePatterns
= static_cast<sal_Int16
>(theDateAcceptancePatterns
.size());
1226 for (sal_Int16 i
= 0; i
< nbOfDateAcceptancePatterns
; ++i
)
1228 of
.writeParameter("DateAcceptancePattern", theDateAcceptancePatterns
[i
], i
);
1231 of
.writeAsciiString("static const sal_Int16 DateAcceptancePatternsCount = ");
1232 of
.writeInt( nbOfDateAcceptancePatterns
);
1233 of
.writeAsciiString(";\n");
1235 of
.writeAsciiString("static const sal_Unicode* DateAcceptancePatternsArray[] = {\n");
1236 for (sal_Int16 i
= 0; i
< nbOfDateAcceptancePatterns
; ++i
)
1238 of
.writeAsciiString("\t");
1239 of
.writeAsciiString("DateAcceptancePattern");
1241 of
.writeAsciiString(",\n");
1243 of
.writeAsciiString("};\n\n");
1245 of
.writeFunction("getDateAcceptancePatterns_", "DateAcceptancePatternsCount", "DateAcceptancePatternsArray");
1251 void LCCollationNode::generateCode (const OFileWriter
&of
) const
1253 OUString useLocale
= getAttr().getValueByName("ref");
1254 if (!useLocale
.isEmpty()) {
1255 useLocale
= useLocale
.replace( '-', '_');
1256 of
.writeRefFunction("getCollatorImplementation_", useLocale
);
1257 of
.writeRefFunction("getCollationOptions_", useLocale
);
1260 sal_Int16 nbOfCollations
= 0;
1261 sal_Int16 nbOfCollationOptions
= 0;
1263 for ( sal_Int32 j
= 0; j
< getNumberOfChildren(); j
++ ) {
1264 LocaleNode
* currNode
= getChildAt (j
);
1265 if( currNode
->getName() == "Collator" )
1268 str
= currNode
->getAttr().getValueByName("unoid");
1269 of
.writeParameter("CollatorID", str
, j
);
1270 str
= currNode
->getValue();
1271 of
.writeParameter("CollatorRule", str
, j
);
1272 str
= currNode
-> getAttr().getValueByName("default");
1273 of
.writeDefaultParameter("Collator", str
, j
);
1274 of
.writeAsciiString("\n");
1278 if( currNode
->getName() == "CollationOptions" )
1280 LocaleNode
* pCollationOptions
= currNode
;
1281 nbOfCollationOptions
= sal::static_int_cast
<sal_Int16
>( pCollationOptions
->getNumberOfChildren() );
1282 for( sal_Int16 i
=0; i
<nbOfCollationOptions
; i
++ )
1284 of
.writeParameter("collationOption", pCollationOptions
->getChildAt( i
)->getValue(), i
);
1287 of
.writeAsciiString("static const sal_Int16 nbOfCollationOptions = ");
1288 of
.writeInt( nbOfCollationOptions
);
1289 of
.writeAsciiString(";\n\n");
1292 of
.writeAsciiString("static const sal_Int16 nbOfCollations = ");
1293 of
.writeInt(nbOfCollations
);
1294 of
.writeAsciiString(";\n\n");
1296 of
.writeAsciiString("\nstatic const sal_Unicode* LCCollatorArray[] = {\n");
1297 for(sal_Int16 j
= 0; j
< nbOfCollations
; j
++) {
1298 of
.writeAsciiString("\tCollatorID");
1300 of
.writeAsciiString(",\n");
1302 of
.writeAsciiString("\tdefaultCollator");
1304 of
.writeAsciiString(",\n");
1306 of
.writeAsciiString("\tCollatorRule");
1308 of
.writeAsciiString(",\n");
1310 of
.writeAsciiString("};\n\n");
1312 of
.writeAsciiString("static const sal_Unicode* collationOptions[] = {");
1313 for( sal_Int16 j
=0; j
<nbOfCollationOptions
; j
++ )
1315 of
.writeAsciiString( "collationOption" );
1317 of
.writeAsciiString( ", " );
1319 of
.writeAsciiString("NULL };\n");
1320 of
.writeFunction("getCollatorImplementation_", "nbOfCollations", "LCCollatorArray");
1321 of
.writeFunction("getCollationOptions_", "nbOfCollationOptions", "collationOptions");
1324 void LCSearchNode::generateCode (const OFileWriter
&of
) const
1326 OUString useLocale
= getAttr().getValueByName("ref");
1327 if (!useLocale
.isEmpty()) {
1328 useLocale
= useLocale
.replace( '-', '_');
1329 of
.writeRefFunction("getSearchOptions_", useLocale
);
1333 if( getNumberOfChildren() != 1 )
1337 stderr
, "Error: LC_SEARCH: more than 1 child: %ld\n",
1338 sal::static_int_cast
< long >(getNumberOfChildren()));
1341 LocaleNode
* pSearchOptions
= getChildAt( 0 );
1342 sal_Int32 nSearchOptions
= pSearchOptions
->getNumberOfChildren();
1343 for( i
=0; i
<nSearchOptions
; i
++ )
1345 of
.writeParameter("searchOption", pSearchOptions
->getChildAt( i
)->getValue(), sal::static_int_cast
<sal_Int16
>(i
) );
1348 of
.writeAsciiString("static const sal_Int16 nbOfSearchOptions = ");
1349 of
.writeInt( sal::static_int_cast
<sal_Int16
>( nSearchOptions
) );
1350 of
.writeAsciiString(";\n\n");
1352 of
.writeAsciiString("static const sal_Unicode* searchOptions[] = {");
1353 for( i
=0; i
<nSearchOptions
; i
++ )
1355 of
.writeAsciiString( "searchOption" );
1356 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
1357 of
.writeAsciiString( ", " );
1359 of
.writeAsciiString("NULL };\n");
1360 of
.writeFunction("getSearchOptions_", "nbOfSearchOptions", "searchOptions");
1363 void LCIndexNode::generateCode (const OFileWriter
&of
) const
1365 OUString useLocale
= getAttr().getValueByName("ref");
1366 if (!useLocale
.isEmpty()) {
1367 useLocale
= useLocale
.replace( '-', '_');
1368 of
.writeRefFunction("getIndexAlgorithm_", useLocale
);
1369 of
.writeRefFunction("getUnicodeScripts_", useLocale
);
1370 of
.writeRefFunction("getFollowPageWords_", useLocale
);
1373 sal_Int16 nbOfIndexs
= 0;
1374 sal_Int16 nbOfUnicodeScripts
= 0;
1375 sal_Int16 nbOfPageWords
= 0;
1376 for (sal_Int32 i
= 0; i
< getNumberOfChildren();i
++) {
1377 LocaleNode
* currNode
= getChildAt (i
);
1378 if( currNode
->getName() == "IndexKey" )
1381 str
= currNode
->getAttr().getValueByName("unoid");
1382 of
.writeParameter("IndexID", str
, nbOfIndexs
);
1383 str
= currNode
->getAttr().getValueByName("module");
1384 of
.writeParameter("IndexModule", str
, nbOfIndexs
);
1385 str
= currNode
->getValue();
1386 of
.writeParameter("IndexKey", str
, nbOfIndexs
);
1387 str
= currNode
-> getAttr().getValueByName("default");
1388 of
.writeDefaultParameter("Index", str
, nbOfIndexs
);
1389 str
= currNode
-> getAttr().getValueByName("phonetic");
1390 of
.writeDefaultParameter("Phonetic", str
, nbOfIndexs
);
1391 of
.writeAsciiString("\n");
1395 if( currNode
->getName() == "UnicodeScript" )
1397 of
.writeParameter("unicodeScript", currNode
->getValue(), nbOfUnicodeScripts
);
1398 nbOfUnicodeScripts
++;
1401 if( currNode
->getName() == "FollowPageWord" )
1403 of
.writeParameter("followPageWord", currNode
->getValue(), nbOfPageWords
);
1407 of
.writeAsciiString("static const sal_Int16 nbOfIndexs = ");
1408 of
.writeInt(nbOfIndexs
);
1409 of
.writeAsciiString(";\n\n");
1411 of
.writeAsciiString("\nstatic const sal_Unicode* IndexArray[] = {\n");
1412 for(sal_Int16 i
= 0; i
< nbOfIndexs
; i
++) {
1413 of
.writeAsciiString("\tIndexID");
1415 of
.writeAsciiString(",\n");
1417 of
.writeAsciiString("\tIndexModule");
1419 of
.writeAsciiString(",\n");
1421 of
.writeAsciiString("\tIndexKey");
1423 of
.writeAsciiString(",\n");
1425 of
.writeAsciiString("\tdefaultIndex");
1427 of
.writeAsciiString(",\n");
1429 of
.writeAsciiString("\tdefaultPhonetic");
1431 of
.writeAsciiString(",\n");
1433 of
.writeAsciiString("};\n\n");
1435 of
.writeAsciiString("static const sal_Int16 nbOfUnicodeScripts = ");
1436 of
.writeInt( nbOfUnicodeScripts
);
1437 of
.writeAsciiString(";\n\n");
1439 of
.writeAsciiString("static const sal_Unicode* UnicodeScriptArray[] = {");
1440 for( sal_Int16 i
=0; i
<nbOfUnicodeScripts
; i
++ )
1442 of
.writeAsciiString( "unicodeScript" );
1444 of
.writeAsciiString( ", " );
1446 of
.writeAsciiString("NULL };\n\n");
1448 of
.writeAsciiString("static const sal_Int16 nbOfPageWords = ");
1449 of
.writeInt(nbOfPageWords
);
1450 of
.writeAsciiString(";\n\n");
1452 of
.writeAsciiString("static const sal_Unicode* FollowPageWordArray[] = {\n");
1453 for(sal_Int16 i
= 0; i
< nbOfPageWords
; i
++) {
1454 of
.writeAsciiString("\tfollowPageWord");
1456 of
.writeAsciiString(",\n");
1458 of
.writeAsciiString("\tNULL\n};\n\n");
1460 of
.writeFunction("getIndexAlgorithm_", "nbOfIndexs", "IndexArray");
1461 of
.writeFunction("getUnicodeScripts_", "nbOfUnicodeScripts", "UnicodeScriptArray");
1462 of
.writeFunction("getFollowPageWords_", "nbOfPageWords", "FollowPageWordArray");
1466 static void lcl_writeAbbrFullNarrNames( const OFileWriter
& of
, const LocaleNode
* currNode
,
1467 const sal_Char
* elementTag
, sal_Int16 i
, sal_Int16 j
)
1469 OUString aAbbrName
= currNode
->getChildAt(1)->getValue();
1470 OUString aFullName
= currNode
->getChildAt(2)->getValue();
1472 LocaleNode
* p
= (currNode
->getNumberOfChildren() > 3 ? currNode
->getChildAt(3) : nullptr);
1473 if ( p
&& p
->getName() == "DefaultNarrowName" )
1474 aNarrName
= p
->getValue();
1477 sal_Int32 nIndex
= 0;
1478 sal_uInt32 nChar
= aFullName
.iterateCodePoints( &nIndex
);
1479 aNarrName
= OUString( &nChar
, 1);
1481 of
.writeParameter( elementTag
, "DefaultAbbrvName", aAbbrName
, i
, j
);
1482 of
.writeParameter( elementTag
, "DefaultFullName", aFullName
, i
, j
);
1483 of
.writeParameter( elementTag
, "DefaultNarrowName", aNarrName
, i
, j
);
1486 static void lcl_writeTabTagString( const OFileWriter
& of
, const sal_Char
* pTag
, const sal_Char
* pStr
)
1488 of
.writeAsciiString("\t");
1489 of
.writeAsciiString( pTag
);
1490 of
.writeAsciiString( pStr
);
1493 static void lcl_writeTabTagStringNums( const OFileWriter
& of
,
1494 const sal_Char
* pTag
, const sal_Char
* pStr
, sal_Int16 i
, sal_Int16 j
)
1496 lcl_writeTabTagString( of
, pTag
, pStr
);
1497 of
.writeInt(i
); of
.writeInt(j
); of
.writeAsciiString(",\n");
1500 static void lcl_writeAbbrFullNarrArrays( const OFileWriter
& of
, sal_Int16 nCount
,
1501 const sal_Char
* elementTag
, sal_Int16 i
, bool bNarrow
)
1505 lcl_writeTabTagString( of
, elementTag
, "Ref");
1506 of
.writeInt(i
); of
.writeAsciiString(",\n");
1507 lcl_writeTabTagString( of
, elementTag
, "RefName");
1508 of
.writeInt(i
); of
.writeAsciiString(",\n");
1512 for (sal_Int16 j
= 0; j
< nCount
; j
++)
1514 lcl_writeTabTagStringNums( of
, elementTag
, "ID", i
, j
);
1515 lcl_writeTabTagStringNums( of
, elementTag
, "DefaultAbbrvName", i
, j
);
1516 lcl_writeTabTagStringNums( of
, elementTag
, "DefaultFullName", i
, j
);
1518 lcl_writeTabTagStringNums( of
, elementTag
, "DefaultNarrowName", i
, j
);
1523 void LCCalendarNode::generateCode (const OFileWriter
&of
) const
1525 OUString useLocale
= getAttr().getValueByName("ref");
1526 if (!useLocale
.isEmpty()) {
1527 useLocale
= useLocale
.replace( '-', '_');
1528 of
.writeRefFunction("getAllCalendars_", useLocale
);
1531 sal_Int16 nbOfCalendars
= sal::static_int_cast
<sal_Int16
>( getNumberOfChildren() );
1533 std::unique_ptr
<sal_Int16
[]> nbOfDays( new sal_Int16
[nbOfCalendars
] );
1534 std::unique_ptr
<sal_Int16
[]> nbOfMonths( new sal_Int16
[nbOfCalendars
] );
1535 std::unique_ptr
<sal_Int16
[]> nbOfGenitiveMonths( new sal_Int16
[nbOfCalendars
] );
1536 std::unique_ptr
<sal_Int16
[]> nbOfPartitiveMonths( new sal_Int16
[nbOfCalendars
] );
1537 std::unique_ptr
<sal_Int16
[]> nbOfEras( new sal_Int16
[nbOfCalendars
] );
1540 bool bHasGregorian
= false;
1543 for ( i
= 0; i
< nbOfCalendars
; i
++) {
1544 LocaleNode
* calNode
= getChildAt (i
);
1545 OUString calendarID
= calNode
-> getAttr().getValueByName("unoid");
1546 of
.writeParameter( "calendarID", calendarID
, i
);
1547 bool bGregorian
= calendarID
== "gregorian";
1549 bHasGregorian
= bGregorian
;
1550 str
= calNode
-> getAttr().getValueByName("default");
1551 of
.writeDefaultParameter("Calendar", str
, i
);
1553 sal_Int16 nChild
= 0;
1555 // Generate Days of Week
1556 const sal_Char
*elementTag
;
1557 LocaleNode
* daysNode
= nullptr;
1558 OUString ref_name
= calNode
->getChildAt(nChild
)->getAttr().getValueByName("ref");
1559 ref_name
= ref_name
.replace( '-', '_');
1560 if (!ref_name
.isEmpty() && i
> 0) {
1561 for (j
= 0; j
< i
; j
++) {
1562 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1563 if (str
== ref_name
)
1564 daysNode
= getChildAt(j
)->getChildAt(0);
1567 if (!ref_name
.isEmpty() && daysNode
== nullptr) {
1568 of
.writeParameter("dayRef", "ref", i
);
1569 of
.writeParameter("dayRefName", ref_name
, i
);
1572 if (daysNode
== nullptr)
1573 daysNode
= calNode
-> getChildAt(nChild
);
1574 nbOfDays
[i
] = sal::static_int_cast
<sal_Int16
>( daysNode
->getNumberOfChildren() );
1575 if (bGregorian
&& nbOfDays
[i
] != 7)
1576 incErrorInt( "Error: A Gregorian calendar must have 7 days per week, this one has %d\n", nbOfDays
[i
]);
1578 for (j
= 0; j
< nbOfDays
[i
]; j
++) {
1579 LocaleNode
*currNode
= daysNode
-> getChildAt(j
);
1580 OUString
dayID( currNode
->getChildAt(0)->getValue());
1581 of
.writeParameter("dayID", dayID
, i
, j
);
1582 if ( j
== 0 && bGregorian
&& dayID
!= "sun" )
1583 incError( "First day of a week of a Gregorian calendar must be <DayID>sun</DayID>");
1584 lcl_writeAbbrFullNarrNames( of
, currNode
, elementTag
, i
, j
);
1589 // Generate Months of Year
1590 LocaleNode
* monthsNode
= nullptr;
1591 ref_name
= calNode
->getChildAt(nChild
)->getAttr().getValueByName("ref");
1592 ref_name
= ref_name
.replace( '-', '_');
1593 if (!ref_name
.isEmpty() && i
> 0) {
1594 for (j
= 0; j
< i
; j
++) {
1595 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1596 if (str
== ref_name
)
1597 monthsNode
= getChildAt(j
)->getChildAt(1);
1600 if (!ref_name
.isEmpty() && monthsNode
== nullptr) {
1601 of
.writeParameter("monthRef", "ref", i
);
1602 of
.writeParameter("monthRefName", ref_name
, i
);
1605 if (monthsNode
== nullptr)
1606 monthsNode
= calNode
-> getChildAt(nChild
);
1607 nbOfMonths
[i
] = sal::static_int_cast
<sal_Int16
>( monthsNode
->getNumberOfChildren() );
1608 if (bGregorian
&& nbOfMonths
[i
] != 12)
1609 incErrorInt( "Error: A Gregorian calendar must have 12 months, this one has %d\n", nbOfMonths
[i
]);
1610 elementTag
= "month";
1611 for (j
= 0; j
< nbOfMonths
[i
]; j
++) {
1612 LocaleNode
*currNode
= monthsNode
-> getChildAt(j
);
1613 OUString
monthID( currNode
->getChildAt(0)->getValue());
1614 of
.writeParameter("monthID", monthID
, i
, j
);
1615 if ( j
== 0 && bGregorian
&& monthID
!= "jan" )
1616 incError( "First month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1617 lcl_writeAbbrFullNarrNames( of
, currNode
, elementTag
, i
, j
);
1622 // Generate genitive Months of Year
1623 // Optional, if not present fall back to month nouns.
1624 if ( calNode
->getChildAt(nChild
)->getName() != "GenitiveMonths" )
1626 LocaleNode
* genitiveMonthsNode
= nullptr;
1627 ref_name
= calNode
->getChildAt(nChild
)->getAttr().getValueByName("ref");
1628 ref_name
= ref_name
.replace( '-', '_');
1629 if (!ref_name
.isEmpty() && i
> 0) {
1630 for (j
= 0; j
< i
; j
++) {
1631 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1632 if (str
== ref_name
)
1633 genitiveMonthsNode
= getChildAt(j
)->getChildAt(1);
1636 if (!ref_name
.isEmpty() && genitiveMonthsNode
== nullptr) {
1637 of
.writeParameter("genitiveMonthRef", "ref", i
);
1638 of
.writeParameter("genitiveMonthRefName", ref_name
, i
);
1639 nbOfGenitiveMonths
[i
] = 0;
1641 if (genitiveMonthsNode
== nullptr)
1642 genitiveMonthsNode
= calNode
-> getChildAt(nChild
);
1643 nbOfGenitiveMonths
[i
] = sal::static_int_cast
<sal_Int16
>( genitiveMonthsNode
->getNumberOfChildren() );
1644 if (bGregorian
&& nbOfGenitiveMonths
[i
] != 12)
1645 incErrorInt( "Error: A Gregorian calendar must have 12 genitive months, this one has %d\n", nbOfGenitiveMonths
[i
]);
1646 elementTag
= "genitiveMonth";
1647 for (j
= 0; j
< nbOfGenitiveMonths
[i
]; j
++) {
1648 LocaleNode
*currNode
= genitiveMonthsNode
-> getChildAt(j
);
1649 OUString
genitiveMonthID( currNode
->getChildAt(0)->getValue());
1650 of
.writeParameter("genitiveMonthID", genitiveMonthID
, i
, j
);
1651 if ( j
== 0 && bGregorian
&& genitiveMonthID
!= "jan" )
1652 incError( "First genitive month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1653 lcl_writeAbbrFullNarrNames( of
, currNode
, elementTag
, i
, j
);
1658 // Generate partitive Months of Year
1659 // Optional, if not present fall back to genitive months, or nominative
1660 // months (nouns) if that isn't present either.
1661 if ( calNode
->getChildAt(nChild
)->getName() != "PartitiveMonths" )
1663 LocaleNode
* partitiveMonthsNode
= nullptr;
1664 ref_name
= calNode
->getChildAt(nChild
)->getAttr().getValueByName("ref");
1665 ref_name
= ref_name
.replace( '-', '_');
1666 if (!ref_name
.isEmpty() && i
> 0) {
1667 for (j
= 0; j
< i
; j
++) {
1668 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1669 if (str
== ref_name
)
1670 partitiveMonthsNode
= getChildAt(j
)->getChildAt(1);
1673 if (!ref_name
.isEmpty() && partitiveMonthsNode
== nullptr) {
1674 of
.writeParameter("partitiveMonthRef", "ref", i
);
1675 of
.writeParameter("partitiveMonthRefName", ref_name
, i
);
1676 nbOfPartitiveMonths
[i
] = 0;
1678 if (partitiveMonthsNode
== nullptr)
1679 partitiveMonthsNode
= calNode
-> getChildAt(nChild
);
1680 nbOfPartitiveMonths
[i
] = sal::static_int_cast
<sal_Int16
>( partitiveMonthsNode
->getNumberOfChildren() );
1681 if (bGregorian
&& nbOfPartitiveMonths
[i
] != 12)
1682 incErrorInt( "Error: A Gregorian calendar must have 12 partitive months, this one has %d\n", nbOfPartitiveMonths
[i
]);
1683 elementTag
= "partitiveMonth";
1684 for (j
= 0; j
< nbOfPartitiveMonths
[i
]; j
++) {
1685 LocaleNode
*currNode
= partitiveMonthsNode
-> getChildAt(j
);
1686 OUString
partitiveMonthID( currNode
->getChildAt(0)->getValue());
1687 of
.writeParameter("partitiveMonthID", partitiveMonthID
, i
, j
);
1688 if ( j
== 0 && bGregorian
&& partitiveMonthID
!= "jan" )
1689 incError( "First partitive month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1690 lcl_writeAbbrFullNarrNames( of
, currNode
, elementTag
, i
, j
);
1695 // Generate Era name
1696 LocaleNode
* erasNode
= nullptr;
1697 ref_name
= calNode
-> getChildAt(nChild
) ->getAttr().getValueByName("ref");
1698 ref_name
= ref_name
.replace( '-', '_');
1699 if (!ref_name
.isEmpty() && i
> 0) {
1700 for (j
= 0; j
< i
; j
++) {
1701 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1702 if (str
== ref_name
)
1703 erasNode
= getChildAt(j
)->getChildAt(2);
1706 if (!ref_name
.isEmpty() && erasNode
== nullptr) {
1707 of
.writeParameter("eraRef", "ref", i
);
1708 of
.writeParameter("eraRefName", ref_name
, i
);
1711 if (erasNode
== nullptr)
1712 erasNode
= calNode
-> getChildAt(nChild
);
1713 nbOfEras
[i
] = sal::static_int_cast
<sal_Int16
>( erasNode
->getNumberOfChildren() );
1714 if (bGregorian
&& nbOfEras
[i
] != 2)
1715 incErrorInt( "Error: A Gregorian calendar must have 2 eras, this one has %d\n", nbOfEras
[i
]);
1717 for (j
= 0; j
< nbOfEras
[i
]; j
++) {
1718 LocaleNode
*currNode
= erasNode
-> getChildAt(j
);
1719 OUString
eraID( currNode
->getChildAt(0)->getValue());
1720 of
.writeParameter("eraID", eraID
, i
, j
);
1721 if ( j
== 0 && bGregorian
&& eraID
!= "bc" )
1722 incError( "First era of a Gregorian calendar must be <EraID>bc</EraID>");
1723 if ( j
== 1 && bGregorian
&& eraID
!= "ad" )
1724 incError( "Second era of a Gregorian calendar must be <EraID>ad</EraID>");
1725 of
.writeAsciiString("\n");
1726 of
.writeParameter(elementTag
, "DefaultAbbrvName",currNode
->getChildAt(1)->getValue() ,i
, j
);
1727 of
.writeParameter(elementTag
, "DefaultFullName",currNode
->getChildAt(2)->getValue() , i
, j
);
1732 str
= calNode
->getChildAt(nChild
)->getChildAt(0)->getValue();
1735 for (j
= 0; j
< nbOfDays
[i
]; j
++)
1737 LocaleNode
*currNode
= daysNode
->getChildAt(j
);
1738 OUString
dayID( currNode
->getChildAt(0)->getValue());
1742 if (j
>= nbOfDays
[i
])
1743 incErrorStr( "Error: <StartDayOfWeek> <DayID> must be one of the <DaysOfWeek>, but is: %s\n", str
);
1745 of
.writeParameter("startDayOfWeek", str
, i
);
1748 str
= calNode
->getChildAt(nChild
)-> getValue();
1749 sal_Int16 nDays
= sal::static_int_cast
<sal_Int16
>( str
.toInt32() );
1750 if (nDays
< 1 || (0 < nbOfDays
[i
] && nbOfDays
[i
] < nDays
))
1751 incErrorInt( "Error: Bad value of MinimalDaysInFirstWeek: %d, must be 1 <= value <= days_in_week\n", nDays
);
1752 of
.writeIntParameter("minimalDaysInFirstWeek", i
, nDays
);
1755 fprintf( stderr
, "Warning: %s\n", "No Gregorian calendar defined, are you sure?");
1757 of
.writeAsciiString("static const sal_Int16 calendarsCount = ");
1758 of
.writeInt(nbOfCalendars
);
1759 of
.writeAsciiString(";\n\n");
1761 of
.writeAsciiString("static const sal_Unicode nbOfDays[] = {");
1762 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1763 of
.writeInt(nbOfDays
[i
]);
1764 of
.writeAsciiString(", ");
1766 of
.writeInt(nbOfDays
[i
]);
1767 of
.writeAsciiString("};\n");
1769 of
.writeAsciiString("static const sal_Unicode nbOfMonths[] = {");
1770 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1771 of
.writeInt(nbOfMonths
[i
]);
1772 of
.writeAsciiString(", ");
1774 of
.writeInt(nbOfMonths
[i
]);
1775 of
.writeAsciiString("};\n");
1777 of
.writeAsciiString("static const sal_Unicode nbOfGenitiveMonths[] = {");
1778 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1779 of
.writeInt(nbOfGenitiveMonths
[i
]);
1780 of
.writeAsciiString(", ");
1782 of
.writeInt(nbOfGenitiveMonths
[i
]);
1783 of
.writeAsciiString("};\n");
1785 of
.writeAsciiString("static const sal_Unicode nbOfPartitiveMonths[] = {");
1786 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1787 of
.writeInt(nbOfPartitiveMonths
[i
]);
1788 of
.writeAsciiString(", ");
1790 of
.writeInt(nbOfPartitiveMonths
[i
]);
1791 of
.writeAsciiString("};\n");
1793 of
.writeAsciiString("static const sal_Unicode nbOfEras[] = {");
1794 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1795 of
.writeInt(nbOfEras
[i
]);
1796 of
.writeAsciiString(", ");
1798 of
.writeInt(nbOfEras
[i
]);
1799 of
.writeAsciiString("};\n");
1802 of
.writeAsciiString("static const sal_Unicode* calendars[] = {\n");
1803 of
.writeAsciiString("\tnbOfDays,\n");
1804 of
.writeAsciiString("\tnbOfMonths,\n");
1805 of
.writeAsciiString("\tnbOfGenitiveMonths,\n");
1806 of
.writeAsciiString("\tnbOfPartitiveMonths,\n");
1807 of
.writeAsciiString("\tnbOfEras,\n");
1808 for(i
= 0; i
< nbOfCalendars
; i
++) {
1809 of
.writeAsciiString("\tcalendarID");
1811 of
.writeAsciiString(",\n");
1812 of
.writeAsciiString("\tdefaultCalendar");
1814 of
.writeAsciiString(",\n");
1815 lcl_writeAbbrFullNarrArrays( of
, nbOfDays
[i
], "day", i
, true);
1816 lcl_writeAbbrFullNarrArrays( of
, nbOfMonths
[i
], "month", i
, true);
1817 lcl_writeAbbrFullNarrArrays( of
, nbOfGenitiveMonths
[i
], "genitiveMonth", i
, true);
1818 lcl_writeAbbrFullNarrArrays( of
, nbOfPartitiveMonths
[i
], "partitiveMonth", i
, true);
1819 lcl_writeAbbrFullNarrArrays( of
, nbOfEras
[i
], "era", i
, false /*noNarrow*/);
1820 of
.writeAsciiString("\tstartDayOfWeek");of
.writeInt(i
); of
.writeAsciiString(",\n");
1821 of
.writeAsciiString("\tminimalDaysInFirstWeek");of
.writeInt(i
); of
.writeAsciiString(",\n");
1824 of
.writeAsciiString("};\n\n");
1825 of
.writeFunction("getAllCalendars_", "calendarsCount", "calendars");
1828 static bool isIso4217( const OUString
& rStr
)
1830 const sal_Unicode
* p
= rStr
.getStr();
1831 return rStr
.getLength() == 3
1832 && 'A' <= p
[0] && p
[0] <= 'Z'
1833 && 'A' <= p
[1] && p
[1] <= 'Z'
1834 && 'A' <= p
[2] && p
[2] <= 'Z'
1838 void LCCurrencyNode::generateCode (const OFileWriter
&of
) const
1840 OUString useLocale
= getAttr().getValueByName("ref");
1841 if (!useLocale
.isEmpty()) {
1842 useLocale
= useLocale
.replace( '-', '_');
1843 of
.writeRefFunction("getAllCurrencies_", useLocale
);
1846 sal_Int16 nbOfCurrencies
= 0;
1849 bool bTheDefault
= false;
1850 bool bTheCompatible
= false;
1851 for ( sal_Int32 i
= 0; i
< getNumberOfChildren(); i
++,nbOfCurrencies
++) {
1852 LocaleNode
* currencyNode
= getChildAt (i
);
1853 str
= currencyNode
->getAttr().getValueByName("default");
1854 bool bDefault
= of
.writeDefaultParameter("Currency", str
, nbOfCurrencies
);
1855 str
= currencyNode
->getAttr().getValueByName("usedInCompatibleFormatCodes");
1856 bool bCompatible
= of
.writeDefaultParameter("CurrencyUsedInCompatibleFormatCodes", str
, nbOfCurrencies
);
1857 str
= currencyNode
->getAttr().getValueByName("legacyOnly");
1858 bool bLegacy
= of
.writeDefaultParameter("CurrencyLegacyOnly", str
, nbOfCurrencies
);
1859 if (bLegacy
&& (bDefault
|| bCompatible
))
1860 incError( "Currency: if legacyOnly==true, both 'default' and 'usedInCompatibleFormatCodes' must be false.");
1864 incError( "Currency: more than one default currency.");
1870 incError( "Currency: more than one currency flagged as usedInCompatibleFormatCodes.");
1871 bTheCompatible
= true;
1873 str
= currencyNode
-> findNode ("CurrencyID") -> getValue();
1874 of
.writeParameter("currencyID", str
, nbOfCurrencies
);
1875 // CurrencyID MUST be ISO 4217.
1876 if (!bLegacy
&& !isIso4217(str
))
1877 incError( "CurrencyID is not ISO 4217");
1878 str
= currencyNode
-> findNode ("CurrencySymbol") -> getValue();
1879 of
.writeParameter("currencySymbol", str
, nbOfCurrencies
);
1880 // Check if this currency really is the one used in number format
1881 // codes. In case of ref=... mechanisms it may be that TheCurrency
1882 // couldn't had been determined from the current locale (i.e. is
1883 // empty), silently assume the referred locale has things right.
1884 if (bCompatible
&& !sTheCompatibleCurrency
.isEmpty() && sTheCompatibleCurrency
!= str
)
1885 incErrorStrStr( "Error: CurrencySymbol \"%s\" flagged as usedInCompatibleFormatCodes doesn't match \"%s\" determined from format codes.\n", str
, sTheCompatibleCurrency
);
1886 str
= currencyNode
-> findNode ("BankSymbol") -> getValue();
1887 of
.writeParameter("bankSymbol", str
, nbOfCurrencies
);
1888 // BankSymbol currently must be ISO 4217. May change later if
1889 // application always uses CurrencyID instead of BankSymbol.
1890 if (!bLegacy
&& !isIso4217(str
))
1891 incError( "BankSymbol is not ISO 4217");
1892 str
= currencyNode
-> findNode ("CurrencyName") -> getValue();
1893 of
.writeParameter("currencyName", str
, nbOfCurrencies
);
1894 str
= currencyNode
-> findNode ("DecimalPlaces") -> getValue();
1895 sal_Int16 nDecimalPlaces
= static_cast<sal_Int16
>(str
.toInt32());
1896 of
.writeIntParameter("currencyDecimalPlaces", nbOfCurrencies
, nDecimalPlaces
);
1897 of
.writeAsciiString("\n");
1901 incError( "Currency: no default currency.");
1902 if (!bTheCompatible
)
1903 incError( "Currency: no currency flagged as usedInCompatibleFormatCodes.");
1905 of
.writeAsciiString("static const sal_Int16 currencyCount = ");
1906 of
.writeInt(nbOfCurrencies
);
1907 of
.writeAsciiString(";\n\n");
1908 of
.writeAsciiString("static const sal_Unicode* currencies[] = {\n");
1909 for(sal_Int16 i
= 0; i
< nbOfCurrencies
; i
++) {
1910 of
.writeAsciiString("\tcurrencyID");
1912 of
.writeAsciiString(",\n");
1913 of
.writeAsciiString("\tcurrencySymbol");
1915 of
.writeAsciiString(",\n");
1916 of
.writeAsciiString("\tbankSymbol");
1918 of
.writeAsciiString(",\n");
1919 of
.writeAsciiString("\tcurrencyName");
1921 of
.writeAsciiString(",\n");
1922 of
.writeAsciiString("\tdefaultCurrency");
1924 of
.writeAsciiString(",\n");
1925 of
.writeAsciiString("\tdefaultCurrencyUsedInCompatibleFormatCodes");
1927 of
.writeAsciiString(",\n");
1928 of
.writeAsciiString("\tcurrencyDecimalPlaces");
1930 of
.writeAsciiString(",\n");
1931 of
.writeAsciiString("\tdefaultCurrencyLegacyOnly");
1933 of
.writeAsciiString(",\n");
1935 of
.writeAsciiString("};\n\n");
1936 of
.writeFunction("getAllCurrencies_", "currencyCount", "currencies");
1939 void LCTransliterationNode::generateCode (const OFileWriter
&of
) const
1941 OUString useLocale
= getAttr().getValueByName("ref");
1942 if (!useLocale
.isEmpty()) {
1943 useLocale
= useLocale
.replace( '-', '_');
1944 of
.writeRefFunction("getTransliterations_", useLocale
);
1947 sal_Int16 nbOfModules
= 0;
1950 for ( sal_Int32 i
= 0; i
< getNumberOfChildren(); i
++,nbOfModules
++) {
1951 LocaleNode
* transNode
= getChildAt (i
);
1952 str
= transNode
->getAttr().getValueByIndex(0);
1953 of
.writeParameter("Transliteration", str
, nbOfModules
);
1955 of
.writeAsciiString("static const sal_Int16 nbOfTransliterations = ");
1956 of
.writeInt(nbOfModules
);
1957 of
.writeAsciiString(";\n\n");
1959 of
.writeAsciiString("\nstatic const sal_Unicode* LCTransliterationsArray[] = {\n");
1960 for( sal_Int16 i
= 0; i
< nbOfModules
; i
++) {
1961 of
.writeAsciiString("\tTransliteration");
1963 of
.writeAsciiString(",\n");
1965 of
.writeAsciiString("};\n\n");
1966 of
.writeFunction("getTransliterations_", "nbOfTransliterations", "LCTransliterationsArray");
1969 struct NameValuePair
{
1970 const sal_Char
*name
;
1971 const sal_Char
*value
;
1973 static const NameValuePair ReserveWord
[] = {
1974 { "trueWord", "true" },
1975 { "falseWord", "false" },
1976 { "quarter1Word", "1st quarter" },
1977 { "quarter2Word", "2nd quarter" },
1978 { "quarter3Word", "3rd quarter" },
1979 { "quarter4Word", "4th quarter" },
1980 { "aboveWord", "above" },
1981 { "belowWord", "below" },
1982 { "quarter1Abbreviation", "Q1" },
1983 { "quarter2Abbreviation", "Q2" },
1984 { "quarter3Abbreviation", "Q3" },
1985 { "quarter4Abbreviation", "Q4" }
1988 void LCMiscNode::generateCode (const OFileWriter
&of
) const
1990 OUString useLocale
= getAttr().getValueByName("ref");
1991 if (!useLocale
.isEmpty()) {
1992 useLocale
= useLocale
.replace( '-', '_');
1993 of
.writeRefFunction("getForbiddenCharacters_", useLocale
);
1994 of
.writeRefFunction("getBreakIteratorRules_", useLocale
);
1995 of
.writeRefFunction("getReservedWords_", useLocale
);
1998 const LocaleNode
* reserveNode
= findNode("ReservedWords");
2000 incError( "No ReservedWords element."); // should not happen if validated...
2001 const LocaleNode
* forbidNode
= findNode("ForbiddenCharacters");
2002 const LocaleNode
* breakNode
= findNode("BreakIteratorRules");
2004 bool bEnglishLocale
= (strncmp( of
.getLocale(), "en_", 3) == 0);
2006 sal_Int16 nbOfWords
= 0;
2010 for ( i
= 0; i
< sal_Int16(SAL_N_ELEMENTS(ReserveWord
)); i
++,nbOfWords
++) {
2011 const LocaleNode
* curNode
= (reserveNode
? reserveNode
->findNode(
2012 ReserveWord
[i
].name
) : nullptr);
2015 "Warning: No %s in ReservedWords, using en_US default: \"%s\".\n",
2016 ReserveWord
[i
].name
, ReserveWord
[i
].value
);
2017 str
= curNode
? curNode
-> getValue() : OUString::createFromAscii(ReserveWord
[i
].value
);
2021 fprintf( stderr
, "Error: No content for ReservedWords %s.\n", ReserveWord
[i
].name
);
2023 of
.writeParameter("ReservedWord", str
, nbOfWords
);
2024 // "true", ..., "below" trigger untranslated warning.
2025 if (!bEnglishLocale
&& curNode
&& i
<= 7 &&
2026 str
.equalsIgnoreAsciiCaseAscii( ReserveWord
[i
].value
))
2029 "Warning: ReservedWord %s seems to be untranslated \"%s\".\n",
2030 ReserveWord
[i
].name
, ReserveWord
[i
].value
);
2033 of
.writeAsciiString("static const sal_Int16 nbOfReservedWords = ");
2034 of
.writeInt(nbOfWords
);
2035 of
.writeAsciiString(";\n\n");
2036 of
.writeAsciiString("\nstatic const sal_Unicode* LCReservedWordsArray[] = {\n");
2037 for( i
= 0; i
< nbOfWords
; i
++) {
2038 of
.writeAsciiString("\tReservedWord");
2040 of
.writeAsciiString(",\n");
2042 of
.writeAsciiString("};\n\n");
2043 of
.writeFunction("getReservedWords_", "nbOfReservedWords", "LCReservedWordsArray");
2046 of
.writeParameter( "forbiddenBegin", forbidNode
-> getChildAt(0)->getValue());
2047 of
.writeParameter( "forbiddenEnd", forbidNode
-> getChildAt(1)->getValue());
2048 of
.writeParameter( "hangingChars", forbidNode
-> getChildAt(2)->getValue());
2050 of
.writeParameter( "forbiddenBegin", OUString());
2051 of
.writeParameter( "forbiddenEnd", OUString());
2052 of
.writeParameter( "hangingChars", OUString());
2054 of
.writeAsciiString("\nstatic const sal_Unicode* LCForbiddenCharactersArray[] = {\n");
2055 of
.writeAsciiString("\tforbiddenBegin,\n");
2056 of
.writeAsciiString("\tforbiddenEnd,\n");
2057 of
.writeAsciiString("\thangingChars\n");
2058 of
.writeAsciiString("};\n\n");
2059 of
.writeFunction("getForbiddenCharacters_", "3", "LCForbiddenCharactersArray");
2062 of
.writeParameter( "EditMode", breakNode
-> getChildAt(0)->getValue());
2063 of
.writeParameter( "DictionaryMode", breakNode
-> getChildAt(1)->getValue());
2064 of
.writeParameter( "WordCountMode", breakNode
-> getChildAt(2)->getValue());
2065 of
.writeParameter( "CharacterMode", breakNode
-> getChildAt(3)->getValue());
2066 of
.writeParameter( "LineMode", breakNode
-> getChildAt(4)->getValue());
2068 of
.writeParameter( "EditMode", OUString());
2069 of
.writeParameter( "DictionaryMode", OUString());
2070 of
.writeParameter( "WordCountMode", OUString());
2071 of
.writeParameter( "CharacterMode", OUString());
2072 of
.writeParameter( "LineMode", OUString());
2074 of
.writeAsciiString("\nstatic const sal_Unicode* LCBreakIteratorRulesArray[] = {\n");
2075 of
.writeAsciiString("\tEditMode,\n");
2076 of
.writeAsciiString("\tDictionaryMode,\n");
2077 of
.writeAsciiString("\tWordCountMode,\n");
2078 of
.writeAsciiString("\tCharacterMode,\n");
2079 of
.writeAsciiString("\tLineMode\n");
2080 of
.writeAsciiString("};\n\n");
2081 of
.writeFunction("getBreakIteratorRules_", "5", "LCBreakIteratorRulesArray");
2085 void LCNumberingLevelNode::generateCode (const OFileWriter
&of
) const
2087 of
.writeAsciiString("// ---> ContinuousNumbering\n");
2088 OUString useLocale
= getAttr().getValueByName("ref");
2089 if (!useLocale
.isEmpty()) {
2090 useLocale
= useLocale
.replace( '-', '_');
2091 of
.writeRefFunction2("getContinuousNumberingLevels_", useLocale
);
2095 // hard code number of attributes per style.
2096 const int nAttributes
= 5;
2097 const char* attr
[ nAttributes
] = { "Prefix", "NumType", "Suffix", "Transliteration", "NatNum" };
2099 // record each attribute of each style in a static C++ variable.
2100 // determine number of styles on the fly.
2101 sal_Int32 nStyles
= getNumberOfChildren();
2104 for( i
= 0; i
< nStyles
; ++i
)
2106 const Attr
&q
= getChildAt( i
)->getAttr();
2107 for( sal_Int32 j
=0; j
<nAttributes
; ++j
)
2109 const char* name
= attr
[j
];
2110 OUString value
= q
.getValueByName( name
);
2111 of
.writeParameter("continuous", name
, value
, sal::static_int_cast
<sal_Int16
>(i
) );
2115 // record number of styles and attributes.
2116 of
.writeAsciiString("static const sal_Int16 continuousNbOfStyles = ");
2117 of
.writeInt( sal::static_int_cast
<sal_Int16
>( nStyles
) );
2118 of
.writeAsciiString(";\n\n");
2119 of
.writeAsciiString("static const sal_Int16 continuousNbOfAttributesPerStyle = ");
2120 of
.writeInt( nAttributes
);
2121 of
.writeAsciiString(";\n\n");
2123 // generate code. (intermediate arrays)
2124 for( i
=0; i
<nStyles
; i
++ )
2126 of
.writeAsciiString("\nstatic const sal_Unicode* continuousStyle" );
2127 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2128 of
.writeAsciiString("[] = {\n");
2129 for( sal_Int32 j
=0; j
<nAttributes
; j
++)
2131 of
.writeAsciiString("\t");
2132 of
.writeAsciiString( "continuous" );
2133 of
.writeAsciiString( attr
[j
] );
2134 of
.writeInt(sal::static_int_cast
<sal_Int16
>(i
));
2135 of
.writeAsciiString(",\n");
2137 of
.writeAsciiString("\t0\n};\n\n");
2140 // generate code. (top-level array)
2141 of
.writeAsciiString("\n");
2142 of
.writeAsciiString("static const sal_Unicode** LCContinuousNumberingLevelsArray[] = {\n" );
2143 for( i
=0; i
<nStyles
; i
++ )
2145 of
.writeAsciiString( "\t" );
2146 of
.writeAsciiString( "continuousStyle" );
2147 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2148 of
.writeAsciiString( ",\n");
2150 of
.writeAsciiString("\t0\n};\n\n");
2151 of
.writeFunction2("getContinuousNumberingLevels_", "continuousNbOfStyles",
2152 "continuousNbOfAttributesPerStyle", "LCContinuousNumberingLevelsArray");
2156 void LCOutlineNumberingLevelNode::generateCode (const OFileWriter
&of
) const
2158 of
.writeAsciiString("// ---> OutlineNumbering\n");
2159 OUString useLocale
= getAttr().getValueByName("ref");
2160 if (!useLocale
.isEmpty()) {
2161 useLocale
= useLocale
.replace( '-', '_');
2162 of
.writeRefFunction3("getOutlineNumberingLevels_", useLocale
);
2166 // hardcode number of attributes per level
2167 const int nAttributes
= 11;
2168 const char* attr
[ nAttributes
] =
2177 "SymbolTextDistance",
2183 // record each attribute of each level of each style in a static C++ variable.
2184 // determine number of styles and number of levels per style on the fly.
2185 sal_Int32 nStyles
= getNumberOfChildren();
2186 vector
<sal_Int32
> nLevels
; // may be different for each style?
2187 for( sal_Int32 i
= 0; i
< nStyles
; i
++ )
2189 LocaleNode
* p
= getChildAt( i
);
2190 nLevels
.push_back( p
->getNumberOfChildren() );
2191 for( sal_Int32 j
=0; j
<nLevels
.back(); j
++ )
2193 const Attr
& q
= p
->getChildAt( j
)->getAttr();
2194 for( sal_Int32 k
=0; k
<nAttributes
; ++k
)
2196 const char* name
= attr
[k
];
2197 OUString value
= q
.getValueByName( name
);
2198 of
.writeParameter("outline", name
, value
,
2199 sal::static_int_cast
<sal_Int16
>(i
),
2200 sal::static_int_cast
<sal_Int16
>(j
) );
2205 // verify that each style has the same number of levels.
2206 for( size_t i
=0; i
<nLevels
.size(); i
++ )
2208 if( nLevels
[0] != nLevels
[i
] )
2210 incError( "Numbering levels don't match.");
2214 // record number of attributes, levels, and styles.
2215 of
.writeAsciiString("static const sal_Int16 outlineNbOfStyles = ");
2216 of
.writeInt( sal::static_int_cast
<sal_Int16
>( nStyles
) );
2217 of
.writeAsciiString(";\n\n");
2218 of
.writeAsciiString("static const sal_Int16 outlineNbOfLevelsPerStyle = ");
2219 of
.writeInt( sal::static_int_cast
<sal_Int16
>( nLevels
.back() ) );
2220 of
.writeAsciiString(";\n\n");
2221 of
.writeAsciiString("static const sal_Int16 outlineNbOfAttributesPerLevel = ");
2222 of
.writeInt( nAttributes
);
2223 of
.writeAsciiString(";\n\n");
2225 // too complicated for now...
2226 // of.writeAsciiString("static const sal_Int16 nbOfOutlineNumberingLevels[] = { ");
2227 // for( sal_Int32 j=0; j<nStyles; j++ )
2229 // of.writeInt( nLevels[j] );
2230 // of.writeAsciiString(", ");
2232 // of.writeAsciiString("};\n\n");
2235 for( sal_Int32 i
=0; i
<nStyles
; i
++ )
2237 for( sal_Int32 j
=0; j
<nLevels
.back(); j
++ )
2239 of
.writeAsciiString("static const sal_Unicode* outline");
2240 of
.writeAsciiString("Style");
2241 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2242 of
.writeAsciiString("Level");
2243 of
.writeInt( sal::static_int_cast
<sal_Int16
>(j
) );
2244 of
.writeAsciiString("[] = { ");
2246 for( sal_Int32 k
=0; k
<nAttributes
; k
++ )
2248 of
.writeAsciiString( "outline" );
2249 of
.writeAsciiString( attr
[k
] );
2250 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2251 of
.writeInt( sal::static_int_cast
<sal_Int16
>(j
) );
2252 of
.writeAsciiString(", ");
2254 of
.writeAsciiString("NULL };\n");
2258 of
.writeAsciiString("\n");
2261 for( sal_Int32 i
=0; i
<nStyles
; i
++ )
2263 of
.writeAsciiString("static const sal_Unicode** outline");
2264 of
.writeAsciiString( "Style" );
2265 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2266 of
.writeAsciiString("[] = { ");
2268 for( sal_Int32 j
=0; j
<nLevels
.back(); j
++ )
2270 of
.writeAsciiString("outlineStyle");
2271 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2272 of
.writeAsciiString("Level");
2273 of
.writeInt( sal::static_int_cast
<sal_Int16
>(j
) );
2274 of
.writeAsciiString(", ");
2276 of
.writeAsciiString("NULL };\n");
2278 of
.writeAsciiString("\n");
2280 of
.writeAsciiString("static const sal_Unicode*** LCOutlineNumberingLevelsArray[] = {\n" );
2281 for( sal_Int32 i
=0; i
<nStyles
; i
++ )
2283 of
.writeAsciiString( "\t" );
2284 of
.writeAsciiString( "outlineStyle" );
2285 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2286 of
.writeAsciiString(",\n");
2288 of
.writeAsciiString("\tNULL\n};\n\n");
2289 of
.writeFunction3("getOutlineNumberingLevels_", "outlineNbOfStyles", "outlineNbOfLevelsPerStyle",
2290 "outlineNbOfAttributesPerLevel", "LCOutlineNumberingLevelsArray");
2293 Attr::Attr (const Reference
< XAttributeList
> & attr
) {
2294 sal_Int16 len
= attr
->getLength();
2296 value
.realloc (len
);
2297 for (sal_Int16 i
=0; i
< len
;i
++) {
2298 name
[i
] = attr
->getNameByIndex(i
);
2299 value
[i
] = attr
-> getValueByIndex(i
);
2303 OUString
Attr::getValueByName (const sal_Char
*str
) const {
2304 auto pName
= std::find_if(std::cbegin(name
), std::cend(name
),
2305 [&str
](const OUString
& rName
) { return rName
.equalsAscii(str
); });
2306 if (pName
!= std::cend(name
))
2308 auto i
= static_cast<sal_Int32
>(std::distance(std::cbegin(name
), pName
));
2314 const OUString
& Attr::getValueByIndex (sal_Int32 idx
) const
2319 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */