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 .
28 #include <rtl/ustrbuf.hxx>
29 #include <sal/macros.h>
31 #include "LocaleNode.hxx"
32 #include <com/sun/star/i18n/NumberFormatIndex.hpp>
34 // NOTE: MUST match the Locale versionDTD attribute defined in data/locale.dtd
35 #define LOCALE_VERSION_DTD "2.0.3"
37 typedef ::std::set
< OUString
> NameSet
;
38 typedef ::std::set
< sal_Int16
> ValueSet
;
40 namespace cssi
= ::com::sun::star::i18n
;
42 LocaleNode::LocaleNode (const OUString
& name
, const Reference
< XAttributeList
> & attr
)
53 int LocaleNode::getError() const
56 for (sal_Int32 i
=0;i
<nChildren
;i
++)
57 err
+= children
[i
]->getError();
61 void LocaleNode::print () const {
64 for(sal_Int32 i
= 0; i
< str
.getLength(); i
++)
65 printf( "%c", str
[i
]);
69 void LocaleNode::printR () const {
71 for (sal_Int32 i
=0;i
<nChildren
;i
++)
72 children
[i
]->printR();
77 void LocaleNode::addChild ( LocaleNode
* node
) {
78 if (childArrSize
<= nChildren
) {
79 LocaleNode
** arrN
= new LocaleNode
*[childArrSize
+10];
80 for (sal_Int32 i
= 0; i
<childArrSize
; ++i
)
81 arrN
[i
] = children
[i
];
86 children
[nChildren
++] = node
;
87 node
->setParent (this);
90 void LocaleNode::setParent ( LocaleNode
* node
) {
94 const LocaleNode
* LocaleNode::getRoot() const
96 const LocaleNode
* pRoot
= nullptr;
97 const LocaleNode
* pParent
= this;
98 while ( (pParent
= pParent
->getParent()) != nullptr )
103 const LocaleNode
* LocaleNode::findNode ( const sal_Char
*name
) const {
104 if (aName
.equalsAscii(name
))
106 for (sal_Int32 i
= 0; i
< nChildren
; i
++) {
107 const LocaleNode
*n
=children
[i
]->findNode(name
);
114 LocaleNode::~LocaleNode()
116 for (sal_Int32 i
=0; i
< nChildren
; ++i
)
121 LocaleNode
* LocaleNode::createNode (const OUString
& name
, const Reference
< XAttributeList
> & attr
)
123 if ( name
== "LC_INFO" )
124 return new LCInfoNode (name
,attr
);
125 if ( name
== "LC_CTYPE" )
126 return new LCCTYPENode (name
,attr
);
127 if ( name
== "LC_FORMAT" )
128 return new LCFormatNode (name
,attr
);
129 if ( name
== "LC_FORMAT_1" )
130 return new LCFormatNode (name
,attr
);
131 if ( name
== "LC_CALENDAR" )
132 return new LCCalendarNode (name
,attr
);
133 if ( name
== "LC_CURRENCY" )
134 return new LCCurrencyNode (name
,attr
);
135 if ( name
== "LC_TRANSLITERATION" )
136 return new LCTransliterationNode (name
,attr
);
137 if ( name
== "LC_COLLATION" )
138 return new LCCollationNode (name
,attr
);
139 if ( name
== "LC_INDEX" )
140 return new LCIndexNode (name
,attr
);
141 if ( name
== "LC_SEARCH" )
142 return new LCSearchNode (name
,attr
);
143 if ( name
== "LC_MISC" )
144 return new LCMiscNode (name
,attr
);
145 if ( name
== "LC_NumberingLevel" )
146 return new LCNumberingLevelNode (name
, attr
);
147 if ( name
== "LC_OutLineNumberingLevel" )
148 return new LCOutlineNumberingLevelNode (name
, attr
);
150 return new LocaleNode(name
,attr
);
154 // printf(" name: '%s'\n", p->getName().pData->buffer );
155 // printf("value: '%s'\n", p->getValue().pData->buffer );
157 #define OSTR(s) (OUStringToOString( (s), RTL_TEXTENCODING_UTF8).getStr())
159 void print_OUString( const OUString
& s
)
161 printf( "%s", OSTR(s
));
164 bool is_empty_string( const OUString
& s
)
166 return s
.isEmpty() || s
== "\n";
169 void print_indent( int depth
)
171 for( int i
=0; i
<depth
; i
++ ) printf(" ");
174 void print_color( int color
)
176 printf("\033[%dm", color
);
179 void print_node( const LocaleNode
* p
, int depth
=0 )
183 print_indent( depth
);
186 print_OUString( p
->getName() );
188 const Attr
& q
= p
->getAttr();
189 for( sal_Int32 j
= 0; j
< q
.getLength(); ++j
)
193 print_OUString( q
.getTypeByIndex(j
) );
198 print_OUString( q
.getValueByIndex(j
) );
204 if( !is_empty_string( p
->getValue() ) )
206 print_indent( depth
+1 );
210 print_OUString( p
->getValue() );
215 for( sal_Int32 i
=0; i
<p
->getNumberOfChildren(); i
++ )
217 print_node( p
->getChildAt(i
), depth
+1 );
219 print_indent( depth
);
221 print_OUString( p
->getName() );
226 void LocaleNode::generateCode (const OFileWriter
&of
) const
228 OUString aDTD
= getAttr().getValueByName("versionDTD");
229 if ( aDTD
!= LOCALE_VERSION_DTD
)
232 fprintf( stderr
, "Error: Locale versionDTD is not %s, see comment in locale.dtd\n", LOCALE_VERSION_DTD
);
234 for (sal_Int32 i
=0; i
<nChildren
;i
++)
235 children
[i
]->generateCode (of
);
236 // print_node( this );
240 OUString
LocaleNode::writeParameterCheckLen( const OFileWriter
&of
,
241 const char* pParameterName
, const LocaleNode
* pNode
,
242 sal_Int32 nMinLen
, sal_Int32 nMaxLen
) const
246 aVal
= pNode
->getValue();
250 fprintf( stderr
, "Error: node NULL pointer for parameter %s.\n",
253 // write empty data if error
254 of
.writeParameter( pParameterName
, aVal
);
255 sal_Int32 nLen
= aVal
.getLength();
259 fprintf( stderr
, "Error: less than %ld character%s (%ld) in %s '%s'.\n",
260 sal::static_int_cast
< long >(nMinLen
), (nMinLen
> 1 ? "s" : ""),
261 sal::static_int_cast
< long >(nLen
),
262 (pNode
? OSTR( pNode
->getName()) : ""),
265 else if (nLen
> nMaxLen
&& nMaxLen
>= 0)
267 "Warning: more than %ld character%s (%ld) in %s %s not supported by application.\n",
268 sal::static_int_cast
< long >(nMaxLen
), (nMaxLen
> 1 ? "s" : ""),
269 sal::static_int_cast
< long >(nLen
),
270 (pNode
? OSTR( pNode
->getName()) : ""),
276 OUString
LocaleNode::writeParameterCheckLen( const OFileWriter
&of
,
277 const char* pNodeName
, const char* pParameterName
,
278 sal_Int32 nMinLen
, sal_Int32 nMaxLen
) const
281 const LocaleNode
* pNode
= findNode( pNodeName
);
283 aVal
= writeParameterCheckLen( of
, pParameterName
, pNode
, nMinLen
, nMaxLen
);
287 fprintf( stderr
, "Error: node %s not found.\n", pNodeName
);
288 // write empty data if error
289 of
.writeParameter( pParameterName
, aVal
);
294 void LocaleNode::incError( const char* pStr
) const
297 fprintf( stderr
, "Error: %s\n", pStr
);
300 void LocaleNode::incError( const OUString
& rStr
) const
302 incError( OSTR( rStr
));
305 void LocaleNode::incErrorInt( const char* pStr
, int nVal
) const
308 fprintf( stderr
, pStr
, nVal
);
311 void LocaleNode::incErrorStr( const char* pStr
, const OUString
& rVal
) const
314 fprintf( stderr
, pStr
, OSTR( rVal
));
317 void LocaleNode::incErrorStrStr( const char* pStr
, const OUString
& rVal1
, const OUString
& rVal2
) const
320 fprintf(stderr
, pStr
, OSTR(rVal1
), OSTR(rVal2
));
323 void LCInfoNode::generateCode (const OFileWriter
&of
) const
326 const LocaleNode
* languageNode
= findNode("Language");
327 const LocaleNode
* countryNode
= findNode("Country");
328 const LocaleNode
* variantNode
= findNode("Variant");
334 aLanguage
= languageNode
->getChildAt(0)->getValue();
335 if (!(aLanguage
.getLength() == 2 || aLanguage
.getLength() == 3))
336 incErrorStr( "Error: langID '%s' not 2-3 characters\n", aLanguage
);
337 of
.writeParameter("langID", aLanguage
);
338 of
.writeParameter("langDefaultName", languageNode
->getChildAt(1)->getValue());
341 incError( "No Language node.");
344 OUString
aCountry( countryNode
->getChildAt(0)->getValue());
345 if (!(aCountry
.isEmpty() || aCountry
.getLength() == 2))
346 incErrorStr( "Error: countryID '%s' not empty or more than 2 characters\n", aCountry
);
347 of
.writeParameter("countryID", aCountry
);
348 of
.writeParameter("countryDefaultName", countryNode
->getChildAt(1)->getValue());
351 incError( "No Country node.");
354 // If given Variant must be at least ll-Ssss and language must be 'qlt'
355 OUString
aVariant( variantNode
->getValue());
356 if (!(aVariant
.isEmpty() || (aVariant
.getLength() >= 7 && aVariant
.indexOf('-') >= 2)))
357 incErrorStr( "Error: invalid Variant '%s'\n", aVariant
);
358 if (!(aVariant
.isEmpty() || aLanguage
== "qlt"))
359 incErrorStrStr( "Error: Variant '%s' given but Language '%s' is not 'qlt'\n", aVariant
, aLanguage
);
360 of
.writeParameter("Variant", aVariant
);
363 of
.writeParameter("Variant", OUString());
364 of
.writeAsciiString("\nstatic const sal_Unicode* LCInfoArray[] = {\n");
365 of
.writeAsciiString("\tlangID,\n");
366 of
.writeAsciiString("\tlangDefaultName,\n");
367 of
.writeAsciiString("\tcountryID,\n");
368 of
.writeAsciiString("\tcountryDefaultName,\n");
369 of
.writeAsciiString("\tVariant\n");
370 of
.writeAsciiString("};\n\n");
371 of
.writeFunction("getLCInfo_", "0", "LCInfoArray");
375 static OUString aDateSep
;
376 static OUString aDecSep
;
378 void LCCTYPENode::generateCode (const OFileWriter
&of
) const
380 const LocaleNode
* sepNode
= nullptr;
381 OUString useLocale
= getAttr().getValueByName("ref");
382 if (!useLocale
.isEmpty()) {
383 useLocale
= useLocale
.replace( '-', '_');
384 of
.writeRefFunction("getLocaleItem_", useLocale
);
387 OUString str
= getAttr().getValueByName("unoid");
388 of
.writeAsciiString("\n\n");
389 of
.writeParameter("LC_CTYPE_Unoid", str
);
392 writeParameterCheckLen( of
, "DateSeparator", "dateSeparator", 1, 1);
394 writeParameterCheckLen( of
, "ThousandSeparator", "thousandSeparator", 1, 1);
396 writeParameterCheckLen( of
, "DecimalSeparator", "decimalSeparator", 1, 1);
398 writeParameterCheckLen( of
, "TimeSeparator", "timeSeparator", 1, 1);
399 OUString aTime100Sep
=
400 writeParameterCheckLen( of
, "Time100SecSeparator", "time100SecSeparator", 1, 1);
402 writeParameterCheckLen( of
, "ListSeparator", "listSeparator", 1, 1);
406 sepNode
= findNode("LongDateDayOfWeekSeparator");
407 aLDS
= sepNode
->getValue();
408 of
.writeParameter("LongDateDayOfWeekSeparator", aLDS
);
410 fprintf( stderr
, "Warning: %s\n",
411 "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\".");
413 sepNode
= findNode("LongDateDaySeparator");
414 aLDS
= sepNode
->getValue();
415 of
.writeParameter("LongDateDaySeparator", aLDS
);
416 if (aLDS
== "," || aLDS
== ".")
417 fprintf( stderr
, "Warning: %s\n",
418 "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\".");
420 sepNode
= findNode("LongDateMonthSeparator");
421 aLDS
= sepNode
->getValue();
422 of
.writeParameter("LongDateMonthSeparator", aLDS
);
424 fprintf( stderr
, "Warning: %s\n",
425 "LongDateMonthSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, May9, 2007\".");
427 sepNode
= findNode("LongDateYearSeparator");
428 aLDS
= sepNode
->getValue();
429 of
.writeParameter("LongDateYearSeparator", aLDS
);
431 fprintf( stderr
, "Warning: %s\n",
432 "LongDateYearSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, 2007May 9\".");
435 int nSavErr
= nError
;
437 if (aDateSep
== aTimeSep
)
438 incError( "DateSeparator equals TimeSeparator.");
439 if (aDecSep
== aThoSep
)
440 incError( "DecimalSeparator equals ThousandSeparator.");
441 if ( aThoSep
== " " )
442 incError( "ThousandSeparator is an ' ' ordinary space, this should be a non-breaking space U+00A0 instead.");
443 if (aListSep
== aDecSep
)
444 fprintf( stderr
, "Warning: %s\n",
445 "ListSeparator equals DecimalSeparator.");
446 if (aListSep
== aThoSep
)
447 fprintf( stderr
, "Warning: %s\n",
448 "ListSeparator equals ThousandSeparator.");
449 if (aListSep
.getLength() != 1 || aListSep
[0] != ';')
451 incError( "ListSeparator not ';' semicolon. Strongly recommended. Currently required.");
452 ++nSavErr
; // format codes not affected
454 if (aTimeSep
== aTime100Sep
)
457 fprintf( stderr
, "Warning: %s\n",
458 "Time100SecSeparator equals TimeSeparator, this is probably an error.");
460 if (aDecSep
!= aTime100Sep
)
463 fprintf( stderr
, "Warning: %s\n",
464 "Time100SecSeparator is different from DecimalSeparator, this may be correct or not. Intended?");
466 if (nSavErr
!= nError
|| nWarn
)
467 fprintf( stderr
, "Warning: %s\n",
468 "Don't forget to adapt corresponding FormatCode elements when changing separators.");
470 OUString aQuoteStart
=
471 writeParameterCheckLen( of
, "QuotationStart", "quotationStart", 1, 1);
473 writeParameterCheckLen( of
, "QuotationEnd", "quotationEnd", 1, 1);
474 OUString aDoubleQuoteStart
=
475 writeParameterCheckLen( of
, "DoubleQuotationStart", "doubleQuotationStart", 1, 1);
476 OUString aDoubleQuoteEnd
=
477 writeParameterCheckLen( of
, "DoubleQuotationEnd", "doubleQuotationEnd", 1, 1);
479 if (aQuoteStart
.toChar() <= 127 && aQuoteEnd
.toChar() > 127)
480 fprintf( stderr
, "Warning: %s\n",
481 "QuotationStart is an ASCII character but QuotationEnd is not.");
482 if (aQuoteEnd
.toChar() <= 127 && aQuoteStart
.toChar() > 127)
483 fprintf( stderr
, "Warning: %s\n",
484 "QuotationEnd is an ASCII character but QuotationStart is not.");
485 if (aDoubleQuoteStart
.toChar() <= 127 && aDoubleQuoteEnd
.toChar() > 127)
486 fprintf( stderr
, "Warning: %s\n",
487 "DoubleQuotationStart is an ASCII character but DoubleQuotationEnd is not.");
488 if (aDoubleQuoteEnd
.toChar() <= 127 && aDoubleQuoteStart
.toChar() > 127)
489 fprintf( stderr
, "Warning: %s\n",
490 "DoubleQuotationEnd is an ASCII character but DoubleQuotationStart is not.");
491 if (aQuoteStart
.toChar() <= 127 && aQuoteEnd
.toChar() <= 127)
492 fprintf( stderr
, "Warning: %s\n",
493 "QuotationStart and QuotationEnd are both ASCII characters. Not necessarily an issue, but unusual.");
494 if (aDoubleQuoteStart
.toChar() <= 127 && aDoubleQuoteEnd
.toChar() <= 127)
495 fprintf( stderr
, "Warning: %s\n",
496 "DoubleQuotationStart and DoubleQuotationEnd are both ASCII characters. Not necessarily an issue, but unusual.");
497 if (aQuoteStart
== aQuoteEnd
)
498 fprintf( stderr
, "Warning: %s\n",
499 "QuotationStart equals QuotationEnd. Not necessarily an issue, but unusual.");
500 if (aDoubleQuoteStart
== aDoubleQuoteEnd
)
501 fprintf( stderr
, "Warning: %s\n",
502 "DoubleQuotationStart equals DoubleQuotationEnd. Not necessarily an issue, but unusual.");
503 /* TODO: should equalness of single and double quotes be an error? Would
504 * need to adapt quite some locales' data. */
505 if (aQuoteStart
== aDoubleQuoteStart
)
506 fprintf( stderr
, "Warning: %s\n",
507 "QuotationStart equals DoubleQuotationStart. Not necessarily an issue, but unusual.");
508 if (aQuoteEnd
== aDoubleQuoteEnd
)
509 fprintf( stderr
, "Warning: %s\n",
510 "QuotationEnd equals DoubleQuotationEnd. Not necessarily an issue, but unusual.");
511 // Known good values, exclude ASCII single (U+0027, ') and double (U+0022, ") quotes.
512 switch (int ic
= aQuoteStart
.toChar())
514 case 0x2018: // LEFT SINGLE QUOTATION MARK
515 case 0x201a: // SINGLE LOW-9 QUOTATION MARK
516 case 0x201b: // SINGLE HIGH-REVERSED-9 QUOTATION MARK
517 case 0x2039: // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
518 case 0x203a: // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
519 case 0x300c: // LEFT CORNER BRACKET (Chinese)
523 fprintf( stderr
, "Warning: %s U+%04X %s\n",
524 "QuotationStart may be wrong:", ic
, OSTR( aQuoteStart
));
526 switch (int ic
= aQuoteEnd
.toChar())
528 case 0x2019: // RIGHT SINGLE QUOTATION MARK
529 case 0x201a: // SINGLE LOW-9 QUOTATION MARK
530 case 0x201b: // SINGLE HIGH-REVERSED-9 QUOTATION MARK
531 case 0x2039: // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
532 case 0x203a: // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
533 case 0x300d: // RIGHT CORNER BRACKET (Chinese)
537 fprintf( stderr
, "Warning: %s U+%04X %s\n",
538 "QuotationEnd may be wrong:", ic
, OSTR( aQuoteEnd
));
540 switch (int ic
= aDoubleQuoteStart
.toChar())
542 case 0x00ab: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
543 case 0x00bb: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
544 case 0x201c: // LEFT DOUBLE QUOTATION MARK
545 case 0x201e: // DOUBLE LOW-9 QUOTATION MARK
546 case 0x201f: // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
547 case 0x300e: // LEFT WHITE CORNER BRACKET (Chinese)
551 fprintf( stderr
, "Warning: %s U+%04X %s\n",
552 "DoubleQuotationStart may be wrong:", ic
, OSTR( aDoubleQuoteStart
));
554 switch (int ic
= aDoubleQuoteEnd
.toChar())
556 case 0x00ab: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
557 case 0x00bb: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
558 case 0x201d: // RIGHT DOUBLE QUOTATION MARK
559 case 0x201e: // DOUBLE LOW-9 QUOTATION MARK
560 case 0x201f: // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
561 case 0x300f: // RIGHT WHITE CORNER BRACKET (Chinese)
565 fprintf( stderr
, "Warning: %s U+%04X %s\n",
566 "DoubleQuotationEnd may be wrong:", ic
, OSTR( aDoubleQuoteEnd
));
569 writeParameterCheckLen( of
, "TimeAM", "timeAM", 1, -1);
570 writeParameterCheckLen( of
, "TimePM", "timePM", 1, -1);
571 sepNode
= findNode("MeasurementSystem");
572 of
.writeParameter("measurementSystem", sepNode
->getValue());
574 of
.writeAsciiString("\nstatic const sal_Unicode* LCType[] = {\n");
575 of
.writeAsciiString("\tLC_CTYPE_Unoid,\n");
576 of
.writeAsciiString("\tdateSeparator,\n");
577 of
.writeAsciiString("\tthousandSeparator,\n");
578 of
.writeAsciiString("\tdecimalSeparator,\n");
579 of
.writeAsciiString("\ttimeSeparator,\n");
580 of
.writeAsciiString("\ttime100SecSeparator,\n");
581 of
.writeAsciiString("\tlistSeparator,\n");
582 of
.writeAsciiString("\tquotationStart,\n");
583 of
.writeAsciiString("\tquotationEnd,\n");
584 of
.writeAsciiString("\tdoubleQuotationStart,\n");
585 of
.writeAsciiString("\tdoubleQuotationEnd,\n");
586 of
.writeAsciiString("\ttimeAM,\n");
587 of
.writeAsciiString("\ttimePM,\n");
588 of
.writeAsciiString("\tmeasurementSystem,\n");
589 of
.writeAsciiString("\tLongDateDayOfWeekSeparator,\n");
590 of
.writeAsciiString("\tLongDateDaySeparator,\n");
591 of
.writeAsciiString("\tLongDateMonthSeparator,\n");
592 of
.writeAsciiString("\tLongDateYearSeparator\n");
593 of
.writeAsciiString("};\n\n");
594 of
.writeFunction("getLocaleItem_", "0", "LCType");
598 static OUString sTheCurrencyReplaceTo
;
599 static OUString sTheCompatibleCurrency
;
600 static OUString sTheDateEditFormat
;
602 sal_Int16
LCFormatNode::mnSection
= 0;
603 sal_Int16
LCFormatNode::mnFormats
= 0;
605 void LCFormatNode::generateCode (const OFileWriter
&of
) const
608 incError("more than 2 LC_FORMAT sections");
610 ::std::vector
< OUString
> theDateAcceptancePatterns
;
612 OUString
useLocale(getAttr().getValueByName("ref"));
615 OUString
strFrom( getAttr().getValueByName("replaceFrom"));
616 if (useLocale
.isEmpty())
618 of
.writeParameter("replaceFrom", strFrom
, mnSection
);
620 str
= getAttr().getValueByName("replaceTo");
621 if (!strFrom
.isEmpty() && str
.isEmpty())
622 incErrorStr("replaceFrom=\"%s\" replaceTo=\"\" is empty replacement.\n", strFrom
);
623 // Locale data generator inserts FFFF for LangID, we need to adapt that.
624 if (str
.endsWithIgnoreAsciiCase( "-FFFF]"))
625 incErrorStr("replaceTo=\"%s\" needs FFFF to be adapted to the real LangID value.\n", str
);
626 of
.writeParameter("replaceTo", str
, mnSection
);
627 // Remember the replaceTo value for "[CURRENCY]" to check format codes.
628 if ( strFrom
== "[CURRENCY]" )
629 sTheCurrencyReplaceTo
= str
;
630 // Remember the currency symbol if present.
631 if (str
.startsWith( "[$" ))
633 sal_Int32 nHyphen
= str
.indexOf( '-');
636 sTheCompatibleCurrency
= str
.copy( 2, nHyphen
- 2);
640 if (!useLocale
.isEmpty())
642 if (!strFrom
.isEmpty() && strFrom
!= "[CURRENCY]") //???
645 "Error: non-empty replaceFrom=\"%s\" with non-empty ref=\"%s\".",
648 useLocale
= useLocale
.replace( '-', '_');
652 of
.writeRefFunction("getAllFormats0_", useLocale
, "replaceTo0");
655 of
.writeRefFunction("getAllFormats1_", useLocale
, "replaceTo1");
658 of
.writeRefFunction("getDateAcceptancePatterns_", useLocale
);
662 sal_Int16 formatCount
= mnFormats
;
664 ValueSet aFormatIndexSet
;
665 NameSet aDefaultsSet
;
666 bool bCtypeIsRef
= false;
667 bool bHaveEngineering
= false;
669 for (sal_Int32 i
= 0; i
< getNumberOfChildren() ; i
++, formatCount
++)
671 LocaleNode
* currNode
= getChildAt (i
);
672 if ( currNode
->getName() == "DateAcceptancePattern" )
675 incError( "DateAcceptancePattern only handled in LC_FORMAT, not LC_FORMAT_1");
677 theDateAcceptancePatterns
.push_back( currNode
->getValue());
681 if ( currNode
->getName() != "FormatElement" )
683 incErrorStr( "Error: Undefined element '%s' in LC_FORMAT\n", currNode
->getName());
690 OUString aFormatIndex
;
691 // currNode -> print();
692 const Attr
&currNodeAttr
= currNode
->getAttr();
693 //printf ("getLen() = %d\n", currNode->getAttr().getLength());
695 str
= currNodeAttr
.getValueByName("msgid");
696 if (!aMsgIdSet
.insert( str
).second
)
697 incErrorStr( "Error: Duplicated msgid=\"%s\" in FormatElement.\n", str
);
698 of
.writeParameter("FormatKey", str
, formatCount
);
700 str
= currNodeAttr
.getValueByName("default");
701 bool bDefault
= str
== "true";
702 of
.writeDefaultParameter("FormatElement", str
, formatCount
);
704 aType
= currNodeAttr
.getValueByName("type");
705 of
.writeParameter("FormatType", aType
, formatCount
);
707 aUsage
= currNodeAttr
.getValueByName("usage");
708 of
.writeParameter("FormatUsage", aUsage
, formatCount
);
710 aFormatIndex
= currNodeAttr
.getValueByName("formatindex");
711 sal_Int16 formatindex
= (sal_Int16
)aFormatIndex
.toInt32();
712 // Ensure the new reserved range is not used anymore, free usage start
713 // was up'ed from 50 to 60.
714 if (50 <= formatindex
&& formatindex
< 60)
715 incErrorInt( "Error: Reserved formatindex=\"%d\" in FormatElement, free usage starts at 60.\n", formatindex
);
716 if (!aFormatIndexSet
.insert( formatindex
).second
)
717 incErrorInt( "Error: Duplicated formatindex=\"%d\" in FormatElement.\n", formatindex
);
718 of
.writeIntParameter("Formatindex", formatCount
, formatindex
);
720 // Ensure only one default per usage and type.
723 OUString
aKey( aUsage
+ "," + aType
);
724 if (!aDefaultsSet
.insert( aKey
).second
)
726 OUString
aStr( "Duplicated default for usage=\"");
728 aStr
+= "\" type=\"";
730 aStr
+= "\": formatindex=\"";
731 aStr
+= aFormatIndex
;
737 const LocaleNode
* n
= currNode
-> findNode("FormatCode");
740 of
.writeParameter("FormatCode", n
->getValue(), formatCount
);
741 // Check separator usage for some FormatCode elements.
742 const LocaleNode
* pCtype
= nullptr;
745 case cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
:
746 sTheDateEditFormat
= n
->getValue();
748 case cssi::NumberFormatIndex::NUMBER_1000DEC2
: // #,##0.00
749 case cssi::NumberFormatIndex::TIME_MMSS00
: // MM:SS.00
750 case cssi::NumberFormatIndex::TIME_HH_MMSS00
: // [HH]:MM:SS.00
752 const LocaleNode
* pRoot
= getRoot();
754 incError( "No root for FormatCode.");
757 pCtype
= pRoot
->findNode( "LC_CTYPE");
759 incError( "No LC_CTYPE found for FormatCode.");
762 OUString
aRef( pCtype
->getAttr().getValueByName("ref"));
765 aRef
= aRef
.replace( '-', '_');
768 "Warning: Can't check separators used in FormatCode due to LC_CTYPE ref=\"%s\".\n"
769 "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",
778 case cssi::NumberFormatIndex::CURRENCY_1000DEC2
:
779 // Remember the currency symbol if present.
782 if (sTheCompatibleCurrency
.isEmpty() &&
783 ((nStart
= n
->getValue().indexOf("[$")) >= 0))
785 OUString
aCode( n
->getValue());
786 sal_Int32 nHyphen
= aCode
.indexOf( '-', nStart
);
787 if (nHyphen
>= nStart
+ 3)
788 sTheCompatibleCurrency
= aCode
.copy( nStart
+ 2, nHyphen
- nStart
- 2);
792 case cssi::NumberFormatIndex::CURRENCY_1000INT
:
793 case cssi::NumberFormatIndex::CURRENCY_1000INT_RED
:
794 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_RED
:
795 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_CCC
:
796 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_DASHED
:
797 // Currency formats should be something like [C]###0;-[C]###0
798 // and not parenthesized [C]###0;([C]###0) if not en_US.
799 if (strcmp( of
.getLocale(), "en_US") != 0)
801 OUString
aCode( n
->getValue());
802 OUString
aPar1( "0)");
803 OUString
aPar2( "-)" );
804 OUString
aPar3( " )" );
805 OUString
aPar4( "])" );
806 if (aCode
.indexOf( aPar1
) > 0 || aCode
.indexOf( aPar2
) > 0 ||
807 aCode
.indexOf( aPar3
) > 0 || aCode
.indexOf( aPar4
) > 0)
808 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
);
810 // Check if we have replaceTo for "[CURRENCY]" placeholder.
811 if (sTheCurrencyReplaceTo
.isEmpty())
813 OUString
aCode( n
->getValue());
814 if (aCode
.indexOf( "[CURRENCY]" ) >= 0)
815 incErrorInt( "Error: [CURRENCY] replaceTo not found for formatindex=\"%d\".\n", formatindex
);
819 if (aUsage
== "SCIENTIFIC_NUMBER")
821 // Check for presence of ##0.00E+00
822 OUString
aCode( n
->getValue());
823 // Simple check without decimal separator (assumed to
824 // be one UTF-16 character). May be prefixed with
825 // [NatNum1] or other tags.
826 sal_Int32 nInt
= aCode
.indexOf("##0");
827 sal_Int32 nDec
= (nInt
< 0 ? -1 : aCode
.indexOf("00E+00", nInt
));
828 if (nInt
>= 0 && nDec
== nInt
+4)
829 bHaveEngineering
= true;
835 int nSavErr
= nError
;
836 OUString
aCode( n
->getValue());
837 if (formatindex
== cssi::NumberFormatIndex::NUMBER_1000DEC2
)
841 const LocaleNode
* pSep
= pCtype
->findNode( "DecimalSeparator");
843 incError( "No DecimalSeparator found for FormatCode.");
846 nDec
= aCode
.indexOf( pSep
->getValue());
848 incErrorInt( "Error: DecimalSeparator not present in FormatCode formatindex=\"%d\".\n",
851 pSep
= pCtype
->findNode( "ThousandSeparator");
853 incError( "No ThousandSeparator found for FormatCode.");
856 nGrp
= aCode
.indexOf( pSep
->getValue());
858 incErrorInt( "Error: ThousandSeparator not present in FormatCode formatindex=\"%d\".\n",
861 if (nDec
>= 0 && nGrp
>= 0 && nDec
<= nGrp
)
862 incErrorInt( "Error: Ordering of ThousandSeparator and DecimalSeparator not correct in formatindex=\"%d\".\n",
865 if (formatindex
== cssi::NumberFormatIndex::TIME_MMSS00
||
866 formatindex
== cssi::NumberFormatIndex::TIME_HH_MMSS00
)
868 sal_Int32 nTime
= -1;
869 sal_Int32 n100s
= -1;
870 const LocaleNode
* pSep
= pCtype
->findNode( "TimeSeparator");
872 incError( "No TimeSeparator found for FormatCode.");
875 nTime
= aCode
.indexOf( pSep
->getValue());
877 incErrorInt( "Error: TimeSeparator not present in FormatCode formatindex=\"%d\".\n",
880 pSep
= pCtype
->findNode( "Time100SecSeparator");
882 incError( "No Time100SecSeparator found for FormatCode.");
885 n100s
= aCode
.indexOf( pSep
->getValue());
887 incErrorInt( "Error: Time100SecSeparator not present in FormatCode formatindex=\"%d\".\n",
889 OUStringBuffer
a100s( pSep
->getValue());
891 n100s
= aCode
.indexOf( a100s
.makeStringAndClear());
893 incErrorInt( "Error: Time100SecSeparator+00 not present in FormatCode formatindex=\"%d\".\n",
896 if (n100s
>= 0 && nTime
>= 0 && n100s
<= nTime
)
897 incErrorInt( "Error: Ordering of Time100SecSeparator and TimeSeparator not correct in formatindex=\"%d\".\n",
900 if (nSavErr
!= nError
)
902 "Warning: formatindex=\"%d\",\"%d\",\"%d\" are the only FormatCode elements checked for separator usage, there may be others that have errors.\n",
903 int(cssi::NumberFormatIndex::NUMBER_1000DEC2
),
904 int(cssi::NumberFormatIndex::TIME_MMSS00
),
905 int(cssi::NumberFormatIndex::TIME_HH_MMSS00
));
910 incError( "No FormatCode in FormatElement.");
911 n
= currNode
-> findNode("DefaultName");
913 of
.writeParameter("FormatDefaultName", n
->getValue(), formatCount
);
915 of
.writeParameter("FormatDefaultName", OUString(), formatCount
);
919 // Check presence of all required format codes only in first section
920 // LC_FORMAT, not in optional LC_FORMAT_1
923 // At least one abbreviated date acceptance pattern must be present.
924 if (theDateAcceptancePatterns
.empty())
925 incError( "No DateAcceptancePattern present.\n");
928 bool bHaveAbbr
= false;
929 for (::std::vector
< OUString
>::const_iterator
it( theDateAcceptancePatterns
.begin());
930 !bHaveAbbr
&& it
!= theDateAcceptancePatterns
.end(); ++it
)
932 if ((*it
).indexOf('D') > -1 && (*it
).indexOf('M') > -1 && (*it
).indexOf('Y') <= -1)
936 incError( "No abbreviated DateAcceptancePattern present. For example M/D or D.M.\n");
939 // 0..47 MUST be present, 48,49 MUST NOT be present
940 ValueSet::const_iterator
aIter( aFormatIndexSet
.begin());
941 for (sal_Int16 nNext
= cssi::NumberFormatIndex::NUMBER_START
;
942 nNext
< cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES
; ++nNext
)
944 sal_Int16 nHere
= ::std::min( ((aIter
!= aFormatIndexSet
.end() ? *aIter
:
945 cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES
)),
946 cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES
);
947 if (aIter
!= aFormatIndexSet
.end()) ++aIter
;
948 for ( ; nNext
< nHere
; ++nNext
)
952 case cssi::NumberFormatIndex::FRACTION_1
:
953 case cssi::NumberFormatIndex::FRACTION_2
:
954 case cssi::NumberFormatIndex::BOOLEAN
:
955 case cssi::NumberFormatIndex::TEXT
:
956 // generated internally
959 incErrorInt( "Error: FormatElement formatindex=\"%d\" not present.\n", nNext
);
964 case cssi::NumberFormatIndex::BOOLEAN
:
965 incErrorInt( "Error: FormatElement formatindex=\"%d\" reserved for internal ``BOOLEAN''.\n", nNext
);
967 case cssi::NumberFormatIndex::TEXT
:
968 incErrorInt( "Error: FormatElement formatindex=\"%d\" reserved for internal ``@'' (TEXT).\n", nNext
);
975 if (!bHaveEngineering
)
976 incError("Engineering notation format not present, e.g. ##0.00E+00 or ##0,00E+00 for usage=\"SCIENTIFIC_NUMBER\"\n");
979 of
.writeAsciiString("\nstatic const sal_Int16 ");
980 of
.writeAsciiString("FormatElementsCount");
981 of
.writeInt(mnSection
);
982 of
.writeAsciiString(" = ");
983 of
.writeInt( formatCount
- mnFormats
);
984 of
.writeAsciiString(";\n");
985 of
.writeAsciiString("static const sal_Unicode* ");
986 of
.writeAsciiString("FormatElementsArray");
987 of
.writeInt(mnSection
);
988 of
.writeAsciiString("[] = {\n");
989 for(sal_Int16 i
= mnFormats
; i
< formatCount
; i
++) {
991 of
.writeAsciiString("\t");
992 of
.writeAsciiString("FormatCode");
994 of
.writeAsciiString(",\n");
996 of
.writeAsciiString("\t");
997 of
.writeAsciiString("FormatDefaultName");
999 of
.writeAsciiString(",\n");
1001 of
.writeAsciiString("\t");
1002 of
.writeAsciiString("FormatKey");
1004 of
.writeAsciiString(",\n");
1006 of
.writeAsciiString("\t");
1007 of
.writeAsciiString("FormatType");
1009 of
.writeAsciiString(",\n");
1011 of
.writeAsciiString("\t");
1012 of
.writeAsciiString("FormatUsage");
1014 of
.writeAsciiString(",\n");
1016 of
.writeAsciiString("\t");
1017 of
.writeAsciiString("Formatindex");
1019 of
.writeAsciiString(",\n");
1022 of
.writeAsciiString("\tdefaultFormatElement");
1024 of
.writeAsciiString(",\n");
1026 of
.writeAsciiString("};\n\n");
1031 of
.writeFunction("getAllFormats0_", "FormatElementsCount0", "FormatElementsArray0", "replaceFrom0", "replaceTo0");
1034 of
.writeFunction("getAllFormats1_", "FormatElementsCount1", "FormatElementsArray1", "replaceFrom1", "replaceTo1");
1038 mnFormats
= mnFormats
+ formatCount
;
1042 // Extract and add date acceptance pattern for full date, so we provide
1043 // at least one valid pattern, even if the number parser doesn't need
1045 /* XXX NOTE: only simple [...] modifier and "..." quotes detected and
1046 * ignored, not nested, no fancy stuff. */
1047 sal_Int32 nIndex
= 0;
1048 // aDateSep can be empty if LC_CTYPE was a ref=..., determine from
1050 sal_uInt32 cDateSep
= (aDateSep
.isEmpty() ? 0 : aDateSep
.iterateCodePoints( &nIndex
));
1051 sal_uInt32 cDateSep2
= cDateSep
;
1053 OUStringBuffer
aPatternBuf(5);
1054 OUStringBuffer
aPatternBuf2(5);
1055 sal_uInt8 nDetected
= 0; // bits Y,M,D
1056 bool bInModifier
= false;
1057 bool bQuoted
= false;
1058 while (nIndex
< sTheDateEditFormat
.getLength() && nDetected
< 7)
1060 sal_uInt32 cChar
= sTheDateEditFormat
.iterateCodePoints( &nIndex
);
1064 bInModifier
= false;
1077 if (!(nDetected
& 4))
1079 aPatternBuf
.append( 'Y');
1080 if (!aPatternBuf2
.isEmpty())
1081 aPatternBuf2
.append( 'Y');
1087 if (!(nDetected
& 2))
1089 aPatternBuf
.append( 'M');
1090 if (!aPatternBuf2
.isEmpty())
1091 aPatternBuf2
.append( 'M');
1097 if (!(nDetected
& 1))
1099 aPatternBuf
.append( 'D');
1100 if (!aPatternBuf2
.isEmpty())
1101 aPatternBuf2
.append( 'D');
1112 cChar
= sTheDateEditFormat
.iterateCodePoints( &nIndex
);
1117 // There are locales that use an ISO 8601 edit format
1118 // regardless of what the date separator or other formats
1119 // say, for example hu-HU. Generalize this for all cases
1120 // where the used separator differs and is one of the known
1121 // separators and generate a second pattern with the
1122 // format's separator at the current position.
1131 if (cDateSep
!= cDateSep2
&& aPatternBuf2
.isEmpty())
1132 aPatternBuf2
= aPatternBuf
;
1133 if (cChar
== cDateSep
|| cChar
== cDateSep2
)
1134 aPatternBuf
.append( OUString( &cDateSep
, 1)); // always the defined separator
1135 if (cChar
== cDateSep2
&& !aPatternBuf2
.isEmpty())
1136 aPatternBuf2
.append( OUString( &cDateSep2
, 1)); // always the format's separator
1138 // The localized legacy:
1140 if (((nDetected
& 7) == 3) || ((nDetected
& 7) == 0))
1146 aPatternBuf
.append( 'Y');
1147 if (!aPatternBuf2
.isEmpty())
1148 aPatternBuf2
.append( 'Y');
1153 if (((nDetected
& 7) == 0) || ((nDetected
& 7) == 6))
1157 aPatternBuf
.append( 'D');
1158 if (!aPatternBuf2
.isEmpty())
1159 aPatternBuf2
.append( 'D');
1162 else if ((nDetected
& 7) == 3)
1166 aPatternBuf
.append( 'Y');
1167 if (!aPatternBuf2
.isEmpty())
1168 aPatternBuf2
.append( 'Y');
1173 if ((nDetected
& 7) == 0)
1176 aPatternBuf
.append( 'D');
1177 if (!aPatternBuf2
.isEmpty())
1178 aPatternBuf2
.append( 'D');
1183 if ((nDetected
& 7) == 0)
1186 aPatternBuf
.append( 'D');
1187 if (!aPatternBuf2
.isEmpty())
1188 aPatternBuf2
.append( 'D');
1193 if ((nDetected
& 7) == 0)
1196 aPatternBuf
.append( 'D');
1197 if (!aPatternBuf2
.isEmpty())
1198 aPatternBuf2
.append( 'D');
1203 if ((nDetected
& 7) == 1)
1206 aPatternBuf
.append( 'M');
1207 if (!aPatternBuf2
.isEmpty())
1208 aPatternBuf2
.append( 'M');
1213 if ((nDetected
& 7) == 3)
1216 aPatternBuf
.append( 'Y');
1217 if (!aPatternBuf2
.isEmpty())
1218 aPatternBuf2
.append( 'Y');
1224 OUString
aPattern( aPatternBuf
.makeStringAndClear());
1225 if (((nDetected
& 7) != 7) || aPattern
.getLength() < 5)
1227 incErrorStr( "Error: failed to extract full date acceptance pattern: %s\n", aPattern
);
1228 fprintf( stderr
, " with DateSeparator '%s' from FormatCode '%s' (formatindex=\"%d\")\n",
1229 OSTR( OUString(&cDateSep
, 1)), OSTR( sTheDateEditFormat
),
1230 (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
);
1234 fprintf( stderr
, "Generated date acceptance pattern: '%s' from '%s' (formatindex=\"%d\" and defined DateSeparator '%s')\n",
1235 OSTR( aPattern
), OSTR( sTheDateEditFormat
),
1236 (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
,
1237 OSTR( OUString(&cDateSep
, 1)));
1238 // Insert at front so full date pattern is first in checks.
1239 theDateAcceptancePatterns
.insert( theDateAcceptancePatterns
.begin(), aPattern
);
1241 if (!aPatternBuf2
.isEmpty())
1243 OUString
aPattern2( aPatternBuf2
.makeStringAndClear());
1244 if (aPattern2
.getLength() < 5)
1246 incErrorStr( "Error: failed to extract 2nd date acceptance pattern: %s\n", aPattern2
);
1247 fprintf( stderr
, " with DateSeparator '%s' from FormatCode '%s' (formatindex=\"%d\")\n",
1248 OSTR( OUString(&cDateSep2
, 1)), OSTR( sTheDateEditFormat
),
1249 (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
);
1253 fprintf( stderr
, "Generated 2nd acceptance pattern: '%s' from '%s' (formatindex=\"%d\")\n",
1254 OSTR( aPattern2
), OSTR( sTheDateEditFormat
),
1255 (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
);
1256 theDateAcceptancePatterns
.insert( theDateAcceptancePatterns
.begin(), aPattern2
);
1260 // Rudimentary check if a pattern interferes with decimal number.
1261 // But only if not inherited in which case we don't have aDecSep here.
1262 if (!aDecSep
.isEmpty())
1265 sal_uInt32 cDecSep
= aDecSep
.iterateCodePoints( &nIndex
);
1266 for (vector
<OUString
>::const_iterator aIt
= theDateAcceptancePatterns
.begin();
1267 aIt
!= theDateAcceptancePatterns
.end(); ++aIt
)
1269 if ((*aIt
).getLength() == (cDecSep
<= 0xffff ? 3 : 4))
1272 if ((*aIt
).iterateCodePoints( &nIndex
) == cDecSep
)
1275 fprintf( stderr
, "Error: Date acceptance pattern '%s' matches decimal number '#%s#'\n",
1276 OSTR( *aIt
), OSTR( aDecSep
));
1282 // Check for duplicates.
1283 for (vector
<OUString
>::const_iterator aIt
= theDateAcceptancePatterns
.begin();
1284 aIt
!= theDateAcceptancePatterns
.end(); ++aIt
)
1286 for (vector
<OUString
>::iterator aComp
= theDateAcceptancePatterns
.begin();
1287 aComp
!= theDateAcceptancePatterns
.end(); /*nop*/)
1289 if (aIt
!= aComp
&& *aIt
== *aComp
)
1291 incErrorStr( "Error: Duplicated DateAcceptancePattern: %s\n", *aComp
);
1292 aComp
= theDateAcceptancePatterns
.erase( aComp
);
1299 sal_Int16 nbOfDateAcceptancePatterns
= static_cast<sal_Int16
>(theDateAcceptancePatterns
.size());
1301 for (sal_Int16 i
= 0; i
< nbOfDateAcceptancePatterns
; ++i
)
1303 of
.writeParameter("DateAcceptancePattern", theDateAcceptancePatterns
[i
], i
);
1306 of
.writeAsciiString("static const sal_Int16 DateAcceptancePatternsCount = ");
1307 of
.writeInt( nbOfDateAcceptancePatterns
);
1308 of
.writeAsciiString(";\n");
1310 of
.writeAsciiString("static const sal_Unicode* DateAcceptancePatternsArray[] = {\n");
1311 for (sal_Int16 i
= 0; i
< nbOfDateAcceptancePatterns
; ++i
)
1313 of
.writeAsciiString("\t");
1314 of
.writeAsciiString("DateAcceptancePattern");
1316 of
.writeAsciiString(",\n");
1318 of
.writeAsciiString("};\n\n");
1320 of
.writeFunction("getDateAcceptancePatterns_", "DateAcceptancePatternsCount", "DateAcceptancePatternsArray");
1326 void LCCollationNode::generateCode (const OFileWriter
&of
) const
1328 OUString useLocale
= getAttr().getValueByName("ref");
1329 if (!useLocale
.isEmpty()) {
1330 useLocale
= useLocale
.replace( '-', '_');
1331 of
.writeRefFunction("getCollatorImplementation_", useLocale
);
1332 of
.writeRefFunction("getCollationOptions_", useLocale
);
1335 sal_Int16 nbOfCollations
= 0;
1336 sal_Int16 nbOfCollationOptions
= 0;
1339 for ( j
= 0; j
< getNumberOfChildren(); j
++ ) {
1340 LocaleNode
* currNode
= getChildAt (j
);
1341 if( currNode
->getName() == "Collator" )
1344 str
= currNode
->getAttr().getValueByName("unoid");
1345 of
.writeParameter("CollatorID", str
, j
);
1346 str
= currNode
->getValue();
1347 of
.writeParameter("CollatorRule", str
, j
);
1348 str
= currNode
-> getAttr().getValueByName("default");
1349 of
.writeDefaultParameter("Collator", str
, j
);
1350 of
.writeAsciiString("\n");
1354 if( currNode
->getName() == "CollationOptions" )
1356 LocaleNode
* pCollationOptions
= currNode
;
1357 nbOfCollationOptions
= sal::static_int_cast
<sal_Int16
>( pCollationOptions
->getNumberOfChildren() );
1358 for( sal_Int16 i
=0; i
<nbOfCollationOptions
; i
++ )
1360 of
.writeParameter("collationOption", pCollationOptions
->getChildAt( i
)->getValue(), i
);
1363 of
.writeAsciiString("static const sal_Int16 nbOfCollationOptions = ");
1364 of
.writeInt( nbOfCollationOptions
);
1365 of
.writeAsciiString(";\n\n");
1368 of
.writeAsciiString("static const sal_Int16 nbOfCollations = ");
1369 of
.writeInt(nbOfCollations
);
1370 of
.writeAsciiString(";\n\n");
1372 of
.writeAsciiString("\nstatic const sal_Unicode* LCCollatorArray[] = {\n");
1373 for(j
= 0; j
< nbOfCollations
; j
++) {
1374 of
.writeAsciiString("\tCollatorID");
1376 of
.writeAsciiString(",\n");
1378 of
.writeAsciiString("\tdefaultCollator");
1380 of
.writeAsciiString(",\n");
1382 of
.writeAsciiString("\tCollatorRule");
1384 of
.writeAsciiString(",\n");
1386 of
.writeAsciiString("};\n\n");
1388 of
.writeAsciiString("static const sal_Unicode* collationOptions[] = {");
1389 for( j
=0; j
<nbOfCollationOptions
; j
++ )
1391 of
.writeAsciiString( "collationOption" );
1393 of
.writeAsciiString( ", " );
1395 of
.writeAsciiString("NULL };\n");
1396 of
.writeFunction("getCollatorImplementation_", "nbOfCollations", "LCCollatorArray");
1397 of
.writeFunction("getCollationOptions_", "nbOfCollationOptions", "collationOptions");
1400 void LCSearchNode::generateCode (const OFileWriter
&of
) const
1402 OUString useLocale
= getAttr().getValueByName("ref");
1403 if (!useLocale
.isEmpty()) {
1404 useLocale
= useLocale
.replace( '-', '_');
1405 of
.writeRefFunction("getSearchOptions_", useLocale
);
1409 if( getNumberOfChildren() != 1 )
1413 stderr
, "Error: LC_SEARCH: more than 1 child: %ld\n",
1414 sal::static_int_cast
< long >(getNumberOfChildren()));
1417 LocaleNode
* pSearchOptions
= getChildAt( 0 );
1418 sal_Int32 nSearchOptions
= pSearchOptions
->getNumberOfChildren();
1419 for( i
=0; i
<nSearchOptions
; i
++ )
1421 of
.writeParameter("searchOption", pSearchOptions
->getChildAt( i
)->getValue(), sal::static_int_cast
<sal_Int16
>(i
) );
1424 of
.writeAsciiString("static const sal_Int16 nbOfSearchOptions = ");
1425 of
.writeInt( sal::static_int_cast
<sal_Int16
>( nSearchOptions
) );
1426 of
.writeAsciiString(";\n\n");
1428 of
.writeAsciiString("static const sal_Unicode* searchOptions[] = {");
1429 for( i
=0; i
<nSearchOptions
; i
++ )
1431 of
.writeAsciiString( "searchOption" );
1432 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
1433 of
.writeAsciiString( ", " );
1435 of
.writeAsciiString("NULL };\n");
1436 of
.writeFunction("getSearchOptions_", "nbOfSearchOptions", "searchOptions");
1439 void LCIndexNode::generateCode (const OFileWriter
&of
) const
1441 OUString useLocale
= getAttr().getValueByName("ref");
1442 if (!useLocale
.isEmpty()) {
1443 useLocale
= useLocale
.replace( '-', '_');
1444 of
.writeRefFunction("getIndexAlgorithm_", useLocale
);
1445 of
.writeRefFunction("getUnicodeScripts_", useLocale
);
1446 of
.writeRefFunction("getFollowPageWords_", useLocale
);
1449 sal_Int16 nbOfIndexs
= 0;
1450 sal_Int16 nbOfUnicodeScripts
= 0;
1451 sal_Int16 nbOfPageWords
= 0;
1453 for (i
= 0; i
< getNumberOfChildren();i
++) {
1454 LocaleNode
* currNode
= getChildAt (i
);
1455 if( currNode
->getName() == "IndexKey" )
1458 str
= currNode
->getAttr().getValueByName("unoid");
1459 of
.writeParameter("IndexID", str
, nbOfIndexs
);
1460 str
= currNode
->getAttr().getValueByName("module");
1461 of
.writeParameter("IndexModule", str
, nbOfIndexs
);
1462 str
= currNode
->getValue();
1463 of
.writeParameter("IndexKey", str
, nbOfIndexs
);
1464 str
= currNode
-> getAttr().getValueByName("default");
1465 of
.writeDefaultParameter("Index", str
, nbOfIndexs
);
1466 str
= currNode
-> getAttr().getValueByName("phonetic");
1467 of
.writeDefaultParameter("Phonetic", str
, nbOfIndexs
);
1468 of
.writeAsciiString("\n");
1472 if( currNode
->getName() == "UnicodeScript" )
1474 of
.writeParameter("unicodeScript", currNode
->getValue(), nbOfUnicodeScripts
);
1475 nbOfUnicodeScripts
++;
1478 if( currNode
->getName() == "FollowPageWord" )
1480 of
.writeParameter("followPageWord", currNode
->getValue(), nbOfPageWords
);
1484 of
.writeAsciiString("static const sal_Int16 nbOfIndexs = ");
1485 of
.writeInt(nbOfIndexs
);
1486 of
.writeAsciiString(";\n\n");
1488 of
.writeAsciiString("\nstatic const sal_Unicode* IndexArray[] = {\n");
1489 for(i
= 0; i
< nbOfIndexs
; i
++) {
1490 of
.writeAsciiString("\tIndexID");
1492 of
.writeAsciiString(",\n");
1494 of
.writeAsciiString("\tIndexModule");
1496 of
.writeAsciiString(",\n");
1498 of
.writeAsciiString("\tIndexKey");
1500 of
.writeAsciiString(",\n");
1502 of
.writeAsciiString("\tdefaultIndex");
1504 of
.writeAsciiString(",\n");
1506 of
.writeAsciiString("\tdefaultPhonetic");
1508 of
.writeAsciiString(",\n");
1510 of
.writeAsciiString("};\n\n");
1512 of
.writeAsciiString("static const sal_Int16 nbOfUnicodeScripts = ");
1513 of
.writeInt( nbOfUnicodeScripts
);
1514 of
.writeAsciiString(";\n\n");
1516 of
.writeAsciiString("static const sal_Unicode* UnicodeScriptArray[] = {");
1517 for( i
=0; i
<nbOfUnicodeScripts
; i
++ )
1519 of
.writeAsciiString( "unicodeScript" );
1521 of
.writeAsciiString( ", " );
1523 of
.writeAsciiString("NULL };\n\n");
1525 of
.writeAsciiString("static const sal_Int16 nbOfPageWords = ");
1526 of
.writeInt(nbOfPageWords
);
1527 of
.writeAsciiString(";\n\n");
1529 of
.writeAsciiString("static const sal_Unicode* FollowPageWordArray[] = {\n");
1530 for(i
= 0; i
< nbOfPageWords
; i
++) {
1531 of
.writeAsciiString("\tfollowPageWord");
1533 of
.writeAsciiString(",\n");
1535 of
.writeAsciiString("\tNULL\n};\n\n");
1537 of
.writeFunction("getIndexAlgorithm_", "nbOfIndexs", "IndexArray");
1538 of
.writeFunction("getUnicodeScripts_", "nbOfUnicodeScripts", "UnicodeScriptArray");
1539 of
.writeFunction("getFollowPageWords_", "nbOfPageWords", "FollowPageWordArray");
1543 static void lcl_writeAbbrFullNarrNames( const OFileWriter
& of
, const LocaleNode
* currNode
,
1544 const sal_Char
* elementTag
, sal_Int16 i
, sal_Int16 j
)
1546 OUString aAbbrName
= currNode
->getChildAt(1)->getValue();
1547 OUString aFullName
= currNode
->getChildAt(2)->getValue();
1549 LocaleNode
* p
= (currNode
->getNumberOfChildren() > 3 ? currNode
->getChildAt(3) : nullptr);
1550 if ( p
&& p
->getName() == "DefaultNarrowName" )
1551 aNarrName
= p
->getValue();
1554 sal_Int32 nIndex
= 0;
1555 sal_uInt32 nChar
= aFullName
.iterateCodePoints( &nIndex
);
1556 aNarrName
= OUString( &nChar
, 1);
1558 of
.writeParameter( elementTag
, "DefaultAbbrvName", aAbbrName
, i
, j
);
1559 of
.writeParameter( elementTag
, "DefaultFullName", aFullName
, i
, j
);
1560 of
.writeParameter( elementTag
, "DefaultNarrowName", aNarrName
, i
, j
);
1563 static void lcl_writeTabTagString( const OFileWriter
& of
, const sal_Char
* pTag
, const sal_Char
* pStr
)
1565 of
.writeAsciiString("\t");
1566 of
.writeAsciiString( pTag
);
1567 of
.writeAsciiString( pStr
);
1570 static void lcl_writeTabTagStringNums( const OFileWriter
& of
,
1571 const sal_Char
* pTag
, const sal_Char
* pStr
, sal_Int16 i
, sal_Int16 j
)
1573 lcl_writeTabTagString( of
, pTag
, pStr
);
1574 of
.writeInt(i
); of
.writeInt(j
); of
.writeAsciiString(",\n");
1577 static void lcl_writeAbbrFullNarrArrays( const OFileWriter
& of
, sal_Int16 nCount
,
1578 const sal_Char
* elementTag
, sal_Int16 i
, bool bNarrow
)
1582 lcl_writeTabTagString( of
, elementTag
, "Ref");
1583 of
.writeInt(i
); of
.writeAsciiString(",\n");
1584 lcl_writeTabTagString( of
, elementTag
, "RefName");
1585 of
.writeInt(i
); of
.writeAsciiString(",\n");
1589 for (sal_Int16 j
= 0; j
< nCount
; j
++)
1591 lcl_writeTabTagStringNums( of
, elementTag
, "ID", i
, j
);
1592 lcl_writeTabTagStringNums( of
, elementTag
, "DefaultAbbrvName", i
, j
);
1593 lcl_writeTabTagStringNums( of
, elementTag
, "DefaultFullName", i
, j
);
1595 lcl_writeTabTagStringNums( of
, elementTag
, "DefaultNarrowName", i
, j
);
1600 void LCCalendarNode::generateCode (const OFileWriter
&of
) const
1602 OUString useLocale
= getAttr().getValueByName("ref");
1603 if (!useLocale
.isEmpty()) {
1604 useLocale
= useLocale
.replace( '-', '_');
1605 of
.writeRefFunction("getAllCalendars_", useLocale
);
1608 sal_Int16 nbOfCalendars
= sal::static_int_cast
<sal_Int16
>( getNumberOfChildren() );
1610 sal_Int16
* nbOfDays
= new sal_Int16
[nbOfCalendars
];
1611 sal_Int16
* nbOfMonths
= new sal_Int16
[nbOfCalendars
];
1612 sal_Int16
* nbOfGenitiveMonths
= new sal_Int16
[nbOfCalendars
];
1613 sal_Int16
* nbOfPartitiveMonths
= new sal_Int16
[nbOfCalendars
];
1614 sal_Int16
* nbOfEras
= new sal_Int16
[nbOfCalendars
];
1617 bool bHasGregorian
= false;
1620 for ( i
= 0; i
< nbOfCalendars
; i
++) {
1621 LocaleNode
* calNode
= getChildAt (i
);
1622 OUString calendarID
= calNode
-> getAttr().getValueByName("unoid");
1623 of
.writeParameter( "calendarID", calendarID
, i
);
1624 bool bGregorian
= calendarID
== "gregorian";
1626 bHasGregorian
= bGregorian
;
1627 str
= calNode
-> getAttr().getValueByName("default");
1628 of
.writeDefaultParameter("Calendar", str
, i
);
1630 sal_Int16 nChild
= 0;
1632 // Generate Days of Week
1633 const sal_Char
*elementTag
;
1634 LocaleNode
* daysNode
= nullptr;
1635 OUString ref_name
= calNode
->getChildAt(nChild
)->getAttr().getValueByName("ref");
1636 ref_name
= ref_name
.replace( '-', '_');
1637 if (!ref_name
.isEmpty() && i
> 0) {
1638 for (j
= 0; j
< i
; j
++) {
1639 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1640 if (str
.equals(ref_name
))
1641 daysNode
= getChildAt(j
)->getChildAt(0);
1644 if (!ref_name
.isEmpty() && daysNode
== nullptr) {
1645 of
.writeParameter("dayRef", "ref", i
);
1646 of
.writeParameter("dayRefName", ref_name
, i
);
1649 if (daysNode
== nullptr)
1650 daysNode
= calNode
-> getChildAt(nChild
);
1651 nbOfDays
[i
] = sal::static_int_cast
<sal_Int16
>( daysNode
->getNumberOfChildren() );
1652 if (bGregorian
&& nbOfDays
[i
] != 7)
1653 incErrorInt( "Error: A Gregorian calendar must have 7 days per week, this one has %d\n", nbOfDays
[i
]);
1655 for (j
= 0; j
< nbOfDays
[i
]; j
++) {
1656 LocaleNode
*currNode
= daysNode
-> getChildAt(j
);
1657 OUString
dayID( currNode
->getChildAt(0)->getValue());
1658 of
.writeParameter("dayID", dayID
, i
, j
);
1659 if ( j
== 0 && bGregorian
&& dayID
!= "sun" )
1660 incError( "First day of a week of a Gregorian calendar must be <DayID>sun</DayID>");
1661 lcl_writeAbbrFullNarrNames( of
, currNode
, elementTag
, i
, j
);
1666 // Generate Months of Year
1667 LocaleNode
* monthsNode
= nullptr;
1668 ref_name
= calNode
->getChildAt(nChild
)->getAttr().getValueByName("ref");
1669 ref_name
= ref_name
.replace( '-', '_');
1670 if (!ref_name
.isEmpty() && i
> 0) {
1671 for (j
= 0; j
< i
; j
++) {
1672 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1673 if (str
.equals(ref_name
))
1674 monthsNode
= getChildAt(j
)->getChildAt(1);
1677 if (!ref_name
.isEmpty() && monthsNode
== nullptr) {
1678 of
.writeParameter("monthRef", "ref", i
);
1679 of
.writeParameter("monthRefName", ref_name
, i
);
1682 if (monthsNode
== nullptr)
1683 monthsNode
= calNode
-> getChildAt(nChild
);
1684 nbOfMonths
[i
] = sal::static_int_cast
<sal_Int16
>( monthsNode
->getNumberOfChildren() );
1685 if (bGregorian
&& nbOfMonths
[i
] != 12)
1686 incErrorInt( "Error: A Gregorian calendar must have 12 months, this one has %d\n", nbOfMonths
[i
]);
1687 elementTag
= "month";
1688 for (j
= 0; j
< nbOfMonths
[i
]; j
++) {
1689 LocaleNode
*currNode
= monthsNode
-> getChildAt(j
);
1690 OUString
monthID( currNode
->getChildAt(0)->getValue());
1691 of
.writeParameter("monthID", monthID
, i
, j
);
1692 if ( j
== 0 && bGregorian
&& monthID
!= "jan" )
1693 incError( "First month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1694 lcl_writeAbbrFullNarrNames( of
, currNode
, elementTag
, i
, j
);
1699 // Generate genitive Months of Year
1700 // Optional, if not present fall back to month nouns.
1701 if ( calNode
->getChildAt(nChild
)->getName() != "GenitiveMonths" )
1703 LocaleNode
* genitiveMonthsNode
= nullptr;
1704 ref_name
= calNode
->getChildAt(nChild
)->getAttr().getValueByName("ref");
1705 ref_name
= ref_name
.replace( '-', '_');
1706 if (!ref_name
.isEmpty() && i
> 0) {
1707 for (j
= 0; j
< i
; j
++) {
1708 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1709 if (str
.equals(ref_name
))
1710 genitiveMonthsNode
= getChildAt(j
)->getChildAt(1);
1713 if (!ref_name
.isEmpty() && genitiveMonthsNode
== nullptr) {
1714 of
.writeParameter("genitiveMonthRef", "ref", i
);
1715 of
.writeParameter("genitiveMonthRefName", ref_name
, i
);
1716 nbOfGenitiveMonths
[i
] = 0;
1718 if (genitiveMonthsNode
== nullptr)
1719 genitiveMonthsNode
= calNode
-> getChildAt(nChild
);
1720 nbOfGenitiveMonths
[i
] = sal::static_int_cast
<sal_Int16
>( genitiveMonthsNode
->getNumberOfChildren() );
1721 if (bGregorian
&& nbOfGenitiveMonths
[i
] != 12)
1722 incErrorInt( "Error: A Gregorian calendar must have 12 genitive months, this one has %d\n", nbOfGenitiveMonths
[i
]);
1723 elementTag
= "genitiveMonth";
1724 for (j
= 0; j
< nbOfGenitiveMonths
[i
]; j
++) {
1725 LocaleNode
*currNode
= genitiveMonthsNode
-> getChildAt(j
);
1726 OUString
genitiveMonthID( currNode
->getChildAt(0)->getValue());
1727 of
.writeParameter("genitiveMonthID", genitiveMonthID
, i
, j
);
1728 if ( j
== 0 && bGregorian
&& genitiveMonthID
!= "jan" )
1729 incError( "First genitive month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1730 lcl_writeAbbrFullNarrNames( of
, currNode
, elementTag
, i
, j
);
1735 // Generate partitive Months of Year
1736 // Optional, if not present fall back to genitive months, or nominative
1737 // months (nouns) if that isn't present either.
1738 if ( calNode
->getChildAt(nChild
)->getName() != "PartitiveMonths" )
1740 LocaleNode
* partitiveMonthsNode
= nullptr;
1741 ref_name
= calNode
->getChildAt(nChild
)->getAttr().getValueByName("ref");
1742 ref_name
= ref_name
.replace( '-', '_');
1743 if (!ref_name
.isEmpty() && i
> 0) {
1744 for (j
= 0; j
< i
; j
++) {
1745 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1746 if (str
.equals(ref_name
))
1747 partitiveMonthsNode
= getChildAt(j
)->getChildAt(1);
1750 if (!ref_name
.isEmpty() && partitiveMonthsNode
== nullptr) {
1751 of
.writeParameter("partitiveMonthRef", "ref", i
);
1752 of
.writeParameter("partitiveMonthRefName", ref_name
, i
);
1753 nbOfPartitiveMonths
[i
] = 0;
1755 if (partitiveMonthsNode
== nullptr)
1756 partitiveMonthsNode
= calNode
-> getChildAt(nChild
);
1757 nbOfPartitiveMonths
[i
] = sal::static_int_cast
<sal_Int16
>( partitiveMonthsNode
->getNumberOfChildren() );
1758 if (bGregorian
&& nbOfPartitiveMonths
[i
] != 12)
1759 incErrorInt( "Error: A Gregorian calendar must have 12 partitive months, this one has %d\n", nbOfPartitiveMonths
[i
]);
1760 elementTag
= "partitiveMonth";
1761 for (j
= 0; j
< nbOfPartitiveMonths
[i
]; j
++) {
1762 LocaleNode
*currNode
= partitiveMonthsNode
-> getChildAt(j
);
1763 OUString
partitiveMonthID( currNode
->getChildAt(0)->getValue());
1764 of
.writeParameter("partitiveMonthID", partitiveMonthID
, i
, j
);
1765 if ( j
== 0 && bGregorian
&& partitiveMonthID
!= "jan" )
1766 incError( "First partitive month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1767 lcl_writeAbbrFullNarrNames( of
, currNode
, elementTag
, i
, j
);
1772 // Generate Era name
1773 LocaleNode
* erasNode
= nullptr;
1774 ref_name
= calNode
-> getChildAt(nChild
) ->getAttr().getValueByName("ref");
1775 ref_name
= ref_name
.replace( '-', '_');
1776 if (!ref_name
.isEmpty() && i
> 0) {
1777 for (j
= 0; j
< i
; j
++) {
1778 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1779 if (str
.equals(ref_name
))
1780 erasNode
= getChildAt(j
)->getChildAt(2);
1783 if (!ref_name
.isEmpty() && erasNode
== nullptr) {
1784 of
.writeParameter("eraRef", "ref", i
);
1785 of
.writeParameter("eraRefName", ref_name
, i
);
1788 if (erasNode
== nullptr)
1789 erasNode
= calNode
-> getChildAt(nChild
);
1790 nbOfEras
[i
] = sal::static_int_cast
<sal_Int16
>( erasNode
->getNumberOfChildren() );
1791 if (bGregorian
&& nbOfEras
[i
] != 2)
1792 incErrorInt( "Error: A Gregorian calendar must have 2 eras, this one has %d\n", nbOfEras
[i
]);
1794 for (j
= 0; j
< nbOfEras
[i
]; j
++) {
1795 LocaleNode
*currNode
= erasNode
-> getChildAt(j
);
1796 OUString
eraID( currNode
->getChildAt(0)->getValue());
1797 of
.writeParameter("eraID", eraID
, i
, j
);
1798 if ( j
== 0 && bGregorian
&& eraID
!= "bc" )
1799 incError( "First era of a Gregorian calendar must be <EraID>bc</EraID>");
1800 if ( j
== 1 && bGregorian
&& eraID
!= "ad" )
1801 incError( "Second era of a Gregorian calendar must be <EraID>ad</EraID>");
1802 of
.writeAsciiString("\n");
1803 of
.writeParameter(elementTag
, "DefaultAbbrvName",currNode
->getChildAt(1)->getValue() ,i
, j
);
1804 of
.writeParameter(elementTag
, "DefaultFullName",currNode
->getChildAt(2)->getValue() , i
, j
);
1809 str
= calNode
->getChildAt(nChild
)->getChildAt(0)->getValue();
1812 for (j
= 0; j
< nbOfDays
[i
]; j
++)
1814 LocaleNode
*currNode
= daysNode
->getChildAt(j
);
1815 OUString
dayID( currNode
->getChildAt(0)->getValue());
1819 if (j
>= nbOfDays
[i
])
1820 incErrorStr( "Error: <StartDayOfWeek> <DayID> must be one of the <DaysOfWeek>, but is: %s\n", str
);
1822 of
.writeParameter("startDayOfWeek", str
, i
);
1825 str
= calNode
->getChildAt(nChild
)-> getValue();
1826 sal_Int16 nDays
= sal::static_int_cast
<sal_Int16
>( str
.toInt32() );
1827 if (nDays
< 1 || (0 < nbOfDays
[i
] && nbOfDays
[i
] < nDays
))
1828 incErrorInt( "Error: Bad value of MinimalDaysInFirstWeek: %d, must be 1 <= value <= days_in_week\n", nDays
);
1829 of
.writeIntParameter("minimalDaysInFirstWeek", i
, nDays
);
1832 fprintf( stderr
, "Warning: %s\n", "No Gregorian calendar defined, are you sure?");
1834 of
.writeAsciiString("static const sal_Int16 calendarsCount = ");
1835 of
.writeInt(nbOfCalendars
);
1836 of
.writeAsciiString(";\n\n");
1838 of
.writeAsciiString("static const sal_Unicode nbOfDays[] = {");
1839 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1840 of
.writeInt(nbOfDays
[i
]);
1841 of
.writeAsciiString(", ");
1843 of
.writeInt(nbOfDays
[i
]);
1844 of
.writeAsciiString("};\n");
1846 of
.writeAsciiString("static const sal_Unicode nbOfMonths[] = {");
1847 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1848 of
.writeInt(nbOfMonths
[i
]);
1849 of
.writeAsciiString(", ");
1851 of
.writeInt(nbOfMonths
[i
]);
1852 of
.writeAsciiString("};\n");
1854 of
.writeAsciiString("static const sal_Unicode nbOfGenitiveMonths[] = {");
1855 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1856 of
.writeInt(nbOfGenitiveMonths
[i
]);
1857 of
.writeAsciiString(", ");
1859 of
.writeInt(nbOfGenitiveMonths
[i
]);
1860 of
.writeAsciiString("};\n");
1862 of
.writeAsciiString("static const sal_Unicode nbOfPartitiveMonths[] = {");
1863 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1864 of
.writeInt(nbOfPartitiveMonths
[i
]);
1865 of
.writeAsciiString(", ");
1867 of
.writeInt(nbOfPartitiveMonths
[i
]);
1868 of
.writeAsciiString("};\n");
1870 of
.writeAsciiString("static const sal_Unicode nbOfEras[] = {");
1871 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1872 of
.writeInt(nbOfEras
[i
]);
1873 of
.writeAsciiString(", ");
1875 of
.writeInt(nbOfEras
[i
]);
1876 of
.writeAsciiString("};\n");
1879 of
.writeAsciiString("static const sal_Unicode* calendars[] = {\n");
1880 of
.writeAsciiString("\tnbOfDays,\n");
1881 of
.writeAsciiString("\tnbOfMonths,\n");
1882 of
.writeAsciiString("\tnbOfGenitiveMonths,\n");
1883 of
.writeAsciiString("\tnbOfPartitiveMonths,\n");
1884 of
.writeAsciiString("\tnbOfEras,\n");
1885 for(i
= 0; i
< nbOfCalendars
; i
++) {
1886 of
.writeAsciiString("\tcalendarID");
1888 of
.writeAsciiString(",\n");
1889 of
.writeAsciiString("\tdefaultCalendar");
1891 of
.writeAsciiString(",\n");
1892 lcl_writeAbbrFullNarrArrays( of
, nbOfDays
[i
], "day", i
, true);
1893 lcl_writeAbbrFullNarrArrays( of
, nbOfMonths
[i
], "month", i
, true);
1894 lcl_writeAbbrFullNarrArrays( of
, nbOfGenitiveMonths
[i
], "genitiveMonth", i
, true);
1895 lcl_writeAbbrFullNarrArrays( of
, nbOfPartitiveMonths
[i
], "partitiveMonth", i
, true);
1896 lcl_writeAbbrFullNarrArrays( of
, nbOfEras
[i
], "era", i
, false /*noNarrow*/);
1897 of
.writeAsciiString("\tstartDayOfWeek");of
.writeInt(i
); of
.writeAsciiString(",\n");
1898 of
.writeAsciiString("\tminimalDaysInFirstWeek");of
.writeInt(i
); of
.writeAsciiString(",\n");
1901 of
.writeAsciiString("};\n\n");
1902 of
.writeFunction("getAllCalendars_", "calendarsCount", "calendars");
1905 delete []nbOfMonths
;
1906 delete []nbOfGenitiveMonths
;
1907 delete []nbOfPartitiveMonths
;
1911 bool isIso4217( const OUString
& rStr
)
1913 const sal_Unicode
* p
= rStr
.getStr();
1914 return rStr
.getLength() == 3
1915 && 'A' <= p
[0] && p
[0] <= 'Z'
1916 && 'A' <= p
[1] && p
[1] <= 'Z'
1917 && 'A' <= p
[2] && p
[2] <= 'Z'
1921 void LCCurrencyNode::generateCode (const OFileWriter
&of
) const
1923 OUString useLocale
= getAttr().getValueByName("ref");
1924 if (!useLocale
.isEmpty()) {
1925 useLocale
= useLocale
.replace( '-', '_');
1926 of
.writeRefFunction("getAllCurrencies_", useLocale
);
1929 sal_Int16 nbOfCurrencies
= 0;
1933 bool bTheDefault
= false;
1934 bool bTheCompatible
= false;
1935 for ( i
= 0; i
< getNumberOfChildren(); i
++,nbOfCurrencies
++) {
1936 LocaleNode
* currencyNode
= getChildAt (i
);
1937 str
= currencyNode
->getAttr().getValueByName("default");
1938 bool bDefault
= of
.writeDefaultParameter("Currency", str
, nbOfCurrencies
);
1939 str
= currencyNode
->getAttr().getValueByName("usedInCompatibleFormatCodes");
1940 bool bCompatible
= of
.writeDefaultParameter("CurrencyUsedInCompatibleFormatCodes", str
, nbOfCurrencies
);
1941 str
= currencyNode
->getAttr().getValueByName("legacyOnly");
1942 bool bLegacy
= of
.writeDefaultParameter("CurrencyLegacyOnly", str
, nbOfCurrencies
);
1943 if (bLegacy
&& (bDefault
|| bCompatible
))
1944 incError( "Currency: if legacyOnly==true, both 'default' and 'usedInCompatibleFormatCodes' must be false.");
1948 incError( "Currency: more than one default currency.");
1954 incError( "Currency: more than one currency flagged as usedInCompatibleFormatCodes.");
1955 bTheCompatible
= true;
1957 str
= currencyNode
-> findNode ("CurrencyID") -> getValue();
1958 of
.writeParameter("currencyID", str
, nbOfCurrencies
);
1959 // CurrencyID MUST be ISO 4217.
1960 if (!bLegacy
&& !isIso4217(str
))
1961 incError( "CurrencyID is not ISO 4217");
1962 str
= currencyNode
-> findNode ("CurrencySymbol") -> getValue();
1963 of
.writeParameter("currencySymbol", str
, nbOfCurrencies
);
1964 // Check if this currency really is the one used in number format
1965 // codes. In case of ref=... mechanisms it may be that TheCurrency
1966 // couldn't had been determined from the current locale (i.e. is
1967 // empty), silently assume the referred locale has things right.
1968 if (bCompatible
&& !sTheCompatibleCurrency
.isEmpty() && sTheCompatibleCurrency
!= str
)
1969 incErrorStrStr( "Error: CurrencySymbol \"%s\" flagged as usedInCompatibleFormatCodes doesn't match \"%s\" determined from format codes.\n", str
, sTheCompatibleCurrency
);
1970 str
= currencyNode
-> findNode ("BankSymbol") -> getValue();
1971 of
.writeParameter("bankSymbol", str
, nbOfCurrencies
);
1972 // BankSymbol currently must be ISO 4217. May change later if
1973 // application always uses CurrencyID instead of BankSymbol.
1974 if (!bLegacy
&& !isIso4217(str
))
1975 incError( "BankSymbol is not ISO 4217");
1976 str
= currencyNode
-> findNode ("CurrencyName") -> getValue();
1977 of
.writeParameter("currencyName", str
, nbOfCurrencies
);
1978 str
= currencyNode
-> findNode ("DecimalPlaces") -> getValue();
1979 sal_Int16 nDecimalPlaces
= (sal_Int16
)str
.toInt32();
1980 of
.writeIntParameter("currencyDecimalPlaces", nbOfCurrencies
, nDecimalPlaces
);
1981 of
.writeAsciiString("\n");
1985 incError( "Currency: no default currency.");
1986 if (!bTheCompatible
)
1987 incError( "Currency: no currency flagged as usedInCompatibleFormatCodes.");
1989 of
.writeAsciiString("static const sal_Int16 currencyCount = ");
1990 of
.writeInt(nbOfCurrencies
);
1991 of
.writeAsciiString(";\n\n");
1992 of
.writeAsciiString("static const sal_Unicode* currencies[] = {\n");
1993 for(i
= 0; i
< nbOfCurrencies
; i
++) {
1994 of
.writeAsciiString("\tcurrencyID");
1996 of
.writeAsciiString(",\n");
1997 of
.writeAsciiString("\tcurrencySymbol");
1999 of
.writeAsciiString(",\n");
2000 of
.writeAsciiString("\tbankSymbol");
2002 of
.writeAsciiString(",\n");
2003 of
.writeAsciiString("\tcurrencyName");
2005 of
.writeAsciiString(",\n");
2006 of
.writeAsciiString("\tdefaultCurrency");
2008 of
.writeAsciiString(",\n");
2009 of
.writeAsciiString("\tdefaultCurrencyUsedInCompatibleFormatCodes");
2011 of
.writeAsciiString(",\n");
2012 of
.writeAsciiString("\tcurrencyDecimalPlaces");
2014 of
.writeAsciiString(",\n");
2015 of
.writeAsciiString("\tdefaultCurrencyLegacyOnly");
2017 of
.writeAsciiString(",\n");
2019 of
.writeAsciiString("};\n\n");
2020 of
.writeFunction("getAllCurrencies_", "currencyCount", "currencies");
2023 void LCTransliterationNode::generateCode (const OFileWriter
&of
) const
2025 OUString useLocale
= getAttr().getValueByName("ref");
2026 if (!useLocale
.isEmpty()) {
2027 useLocale
= useLocale
.replace( '-', '_');
2028 of
.writeRefFunction("getTransliterations_", useLocale
);
2031 sal_Int16 nbOfModules
= 0;
2035 for ( i
= 0; i
< getNumberOfChildren(); i
++,nbOfModules
++) {
2036 LocaleNode
* transNode
= getChildAt (i
);
2037 str
= transNode
->getAttr().getValueByIndex(0);
2038 of
.writeParameter("Transliteration", str
, nbOfModules
);
2040 of
.writeAsciiString("static const sal_Int16 nbOfTransliterations = ");
2041 of
.writeInt(nbOfModules
);
2042 of
.writeAsciiString(";\n\n");
2044 of
.writeAsciiString("\nstatic const sal_Unicode* LCTransliterationsArray[] = {\n");
2045 for( i
= 0; i
< nbOfModules
; i
++) {
2046 of
.writeAsciiString("\tTransliteration");
2048 of
.writeAsciiString(",\n");
2050 of
.writeAsciiString("};\n\n");
2051 of
.writeFunction("getTransliterations_", "nbOfTransliterations", "LCTransliterationsArray");
2054 struct NameValuePair
{
2055 const sal_Char
*name
;
2056 const sal_Char
*value
;
2058 static const NameValuePair ReserveWord
[] = {
2059 { "trueWord", "true" },
2060 { "falseWord", "false" },
2061 { "quarter1Word", "1st quarter" },
2062 { "quarter2Word", "2nd quarter" },
2063 { "quarter3Word", "3rd quarter" },
2064 { "quarter4Word", "4th quarter" },
2065 { "aboveWord", "above" },
2066 { "belowWord", "below" },
2067 { "quarter1Abbreviation", "Q1" },
2068 { "quarter2Abbreviation", "Q2" },
2069 { "quarter3Abbreviation", "Q3" },
2070 { "quarter4Abbreviation", "Q4" }
2073 void LCMiscNode::generateCode (const OFileWriter
&of
) const
2075 OUString useLocale
= getAttr().getValueByName("ref");
2076 if (!useLocale
.isEmpty()) {
2077 useLocale
= useLocale
.replace( '-', '_');
2078 of
.writeRefFunction("getForbiddenCharacters_", useLocale
);
2079 of
.writeRefFunction("getBreakIteratorRules_", useLocale
);
2080 of
.writeRefFunction("getReservedWords_", useLocale
);
2083 const LocaleNode
* reserveNode
= findNode("ReservedWords");
2085 incError( "No ReservedWords element."); // should not happen if validated..
2086 const LocaleNode
* forbidNode
= findNode("ForbiddenCharacters");
2087 const LocaleNode
* breakNode
= findNode("BreakIteratorRules");
2089 bool bEnglishLocale
= (strncmp( of
.getLocale(), "en_", 3) == 0);
2091 sal_Int16 nbOfWords
= 0;
2095 for ( i
= 0; i
< sal_Int16(SAL_N_ELEMENTS(ReserveWord
)); i
++,nbOfWords
++) {
2096 const LocaleNode
* curNode
= (reserveNode
? reserveNode
->findNode(
2097 ReserveWord
[i
].name
) : nullptr);
2100 "Warning: No %s in ReservedWords, using en_US default: \"%s\".\n",
2101 ReserveWord
[i
].name
, ReserveWord
[i
].value
);
2102 str
= curNode
? curNode
-> getValue() : OUString::createFromAscii(ReserveWord
[i
].value
);
2106 fprintf( stderr
, "Error: No content for ReservedWords %s.\n", ReserveWord
[i
].name
);
2108 of
.writeParameter("ReservedWord", str
, nbOfWords
);
2109 // "true", ..., "below" trigger untranslated warning.
2110 if (!bEnglishLocale
&& curNode
&& (0 <= i
&& i
<= 7) &&
2111 str
.equalsIgnoreAsciiCaseAscii( ReserveWord
[i
].value
))
2114 "Warning: ReservedWord %s seems to be untranslated \"%s\".\n",
2115 ReserveWord
[i
].name
, ReserveWord
[i
].value
);
2118 of
.writeAsciiString("static const sal_Int16 nbOfReservedWords = ");
2119 of
.writeInt(nbOfWords
);
2120 of
.writeAsciiString(";\n\n");
2121 of
.writeAsciiString("\nstatic const sal_Unicode* LCReservedWordsArray[] = {\n");
2122 for( i
= 0; i
< nbOfWords
; i
++) {
2123 of
.writeAsciiString("\tReservedWord");
2125 of
.writeAsciiString(",\n");
2127 of
.writeAsciiString("};\n\n");
2128 of
.writeFunction("getReservedWords_", "nbOfReservedWords", "LCReservedWordsArray");
2131 of
.writeParameter( "forbiddenBegin", forbidNode
-> getChildAt(0)->getValue());
2132 of
.writeParameter( "forbiddenEnd", forbidNode
-> getChildAt(1)->getValue());
2133 of
.writeParameter( "hangingChars", forbidNode
-> getChildAt(2)->getValue());
2135 of
.writeParameter( "forbiddenBegin", OUString());
2136 of
.writeParameter( "forbiddenEnd", OUString());
2137 of
.writeParameter( "hangingChars", OUString());
2139 of
.writeAsciiString("\nstatic const sal_Unicode* LCForbiddenCharactersArray[] = {\n");
2140 of
.writeAsciiString("\tforbiddenBegin,\n");
2141 of
.writeAsciiString("\tforbiddenEnd,\n");
2142 of
.writeAsciiString("\thangingChars\n");
2143 of
.writeAsciiString("};\n\n");
2144 of
.writeFunction("getForbiddenCharacters_", "3", "LCForbiddenCharactersArray");
2147 of
.writeParameter( "EditMode", breakNode
-> getChildAt(0)->getValue());
2148 of
.writeParameter( "DictionaryMode", breakNode
-> getChildAt(1)->getValue());
2149 of
.writeParameter( "WordCountMode", breakNode
-> getChildAt(2)->getValue());
2150 of
.writeParameter( "CharacterMode", breakNode
-> getChildAt(3)->getValue());
2151 of
.writeParameter( "LineMode", breakNode
-> getChildAt(4)->getValue());
2153 of
.writeParameter( "EditMode", OUString());
2154 of
.writeParameter( "DictionaryMode", OUString());
2155 of
.writeParameter( "WordCountMode", OUString());
2156 of
.writeParameter( "CharacterMode", OUString());
2157 of
.writeParameter( "LineMode", OUString());
2159 of
.writeAsciiString("\nstatic const sal_Unicode* LCBreakIteratorRulesArray[] = {\n");
2160 of
.writeAsciiString("\tEditMode,\n");
2161 of
.writeAsciiString("\tDictionaryMode,\n");
2162 of
.writeAsciiString("\tWordCountMode,\n");
2163 of
.writeAsciiString("\tCharacterMode,\n");
2164 of
.writeAsciiString("\tLineMode\n");
2165 of
.writeAsciiString("};\n\n");
2166 of
.writeFunction("getBreakIteratorRules_", "5", "LCBreakIteratorRulesArray");
2170 void LCNumberingLevelNode::generateCode (const OFileWriter
&of
) const
2172 of
.writeAsciiString("// ---> ContinuousNumbering\n");
2173 OUString useLocale
= getAttr().getValueByName("ref");
2174 if (!useLocale
.isEmpty()) {
2175 useLocale
= useLocale
.replace( '-', '_');
2176 of
.writeRefFunction2("getContinuousNumberingLevels_", useLocale
);
2180 // hard code number of attributes per style.
2181 const int nAttributes
= 5;
2182 const char* attr
[ nAttributes
] = { "Prefix", "NumType", "Suffix", "Transliteration", "NatNum" };
2184 // record each attribute of each style in a static C++ variable.
2185 // determine number of styles on the fly.
2186 sal_Int32 nStyles
= getNumberOfChildren();
2189 for( i
= 0; i
< nStyles
; ++i
)
2191 const Attr
&q
= getChildAt( i
)->getAttr();
2192 for( sal_Int32 j
=0; j
<nAttributes
; ++j
)
2194 const char* name
= attr
[j
];
2195 OUString value
= q
.getValueByName( name
);
2196 of
.writeParameter("continuous", name
, value
, sal::static_int_cast
<sal_Int16
>(i
) );
2200 // record number of styles and attributes.
2201 of
.writeAsciiString("static const sal_Int16 continuousNbOfStyles = ");
2202 of
.writeInt( sal::static_int_cast
<sal_Int16
>( nStyles
) );
2203 of
.writeAsciiString(";\n\n");
2204 of
.writeAsciiString("static const sal_Int16 continuousNbOfAttributesPerStyle = ");
2205 of
.writeInt( nAttributes
);
2206 of
.writeAsciiString(";\n\n");
2208 // generate code. (intermediate arrays)
2209 for( i
=0; i
<nStyles
; i
++ )
2211 of
.writeAsciiString("\nstatic const sal_Unicode* continuousStyle" );
2212 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2213 of
.writeAsciiString("[] = {\n");
2214 for( sal_Int32 j
=0; j
<nAttributes
; j
++)
2216 of
.writeAsciiString("\t");
2217 of
.writeAsciiString( "continuous" );
2218 of
.writeAsciiString( attr
[j
] );
2219 of
.writeInt(sal::static_int_cast
<sal_Int16
>(i
));
2220 of
.writeAsciiString(",\n");
2222 of
.writeAsciiString("\t0\n};\n\n");
2225 // generate code. (top-level array)
2226 of
.writeAsciiString("\n");
2227 of
.writeAsciiString("static const sal_Unicode** LCContinuousNumberingLevelsArray[] = {\n" );
2228 for( i
=0; i
<nStyles
; i
++ )
2230 of
.writeAsciiString( "\t" );
2231 of
.writeAsciiString( "continuousStyle" );
2232 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2233 of
.writeAsciiString( ",\n");
2235 of
.writeAsciiString("\t0\n};\n\n");
2236 of
.writeFunction2("getContinuousNumberingLevels_", "continuousNbOfStyles",
2237 "continuousNbOfAttributesPerStyle", "LCContinuousNumberingLevelsArray");
2241 void LCOutlineNumberingLevelNode::generateCode (const OFileWriter
&of
) const
2243 of
.writeAsciiString("// ---> OutlineNumbering\n");
2244 OUString useLocale
= getAttr().getValueByName("ref");
2245 if (!useLocale
.isEmpty()) {
2246 useLocale
= useLocale
.replace( '-', '_');
2247 of
.writeRefFunction3("getOutlineNumberingLevels_", useLocale
);
2251 // hardcode number of attributes per level
2252 const int nAttributes
= 11;
2253 const char* attr
[ nAttributes
] =
2262 "SymbolTextDistance",
2268 // record each attribute of each level of each style in a static C++ variable.
2269 // determine number of styles and number of levels per style on the fly.
2270 sal_Int32 nStyles
= getNumberOfChildren();
2271 vector
<sal_Int32
> nLevels
; // may be different for each style?
2272 for( sal_Int32 i
= 0; i
< nStyles
; i
++ )
2274 LocaleNode
* p
= getChildAt( i
);
2275 nLevels
.push_back( p
->getNumberOfChildren() );
2276 for( sal_Int32 j
=0; j
<nLevels
.back(); j
++ )
2278 const Attr
& q
= p
->getChildAt( j
)->getAttr();
2279 for( sal_Int32 k
=0; k
<nAttributes
; ++k
)
2281 const char* name
= attr
[k
];
2282 OUString value
= q
.getValueByName( name
);
2283 of
.writeParameter("outline", name
, value
,
2284 sal::static_int_cast
<sal_Int16
>(i
),
2285 sal::static_int_cast
<sal_Int16
>(j
) );
2290 // verify that each style has the same number of levels.
2291 for( size_t i
=0; i
<nLevels
.size(); i
++ )
2293 if( nLevels
[0] != nLevels
[i
] )
2295 incError( "Numbering levels don't match.");
2299 // record number of attributes, levels, and styles.
2300 of
.writeAsciiString("static const sal_Int16 outlineNbOfStyles = ");
2301 of
.writeInt( sal::static_int_cast
<sal_Int16
>( nStyles
) );
2302 of
.writeAsciiString(";\n\n");
2303 of
.writeAsciiString("static const sal_Int16 outlineNbOfLevelsPerStyle = ");
2304 of
.writeInt( sal::static_int_cast
<sal_Int16
>( nLevels
.back() ) );
2305 of
.writeAsciiString(";\n\n");
2306 of
.writeAsciiString("static const sal_Int16 outlineNbOfAttributesPerLevel = ");
2307 of
.writeInt( nAttributes
);
2308 of
.writeAsciiString(";\n\n");
2310 // too complicated for now...
2311 // of.writeAsciiString("static const sal_Int16 nbOfOutlineNumberingLevels[] = { ");
2312 // for( sal_Int32 j=0; j<nStyles; j++ )
2314 // of.writeInt( nLevels[j] );
2315 // of.writeAsciiString(", ");
2317 // of.writeAsciiString("};\n\n");
2320 for( sal_Int32 i
=0; i
<nStyles
; i
++ )
2322 for( sal_Int32 j
=0; j
<nLevels
.back(); j
++ )
2324 of
.writeAsciiString("static const sal_Unicode* outline");
2325 of
.writeAsciiString("Style");
2326 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2327 of
.writeAsciiString("Level");
2328 of
.writeInt( sal::static_int_cast
<sal_Int16
>(j
) );
2329 of
.writeAsciiString("[] = { ");
2331 for( sal_Int32 k
=0; k
<nAttributes
; k
++ )
2333 of
.writeAsciiString( "outline" );
2334 of
.writeAsciiString( attr
[k
] );
2335 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2336 of
.writeInt( sal::static_int_cast
<sal_Int16
>(j
) );
2337 of
.writeAsciiString(", ");
2339 of
.writeAsciiString("NULL };\n");
2343 of
.writeAsciiString("\n");
2346 for( sal_Int32 i
=0; i
<nStyles
; i
++ )
2348 of
.writeAsciiString("static const sal_Unicode** outline");
2349 of
.writeAsciiString( "Style" );
2350 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2351 of
.writeAsciiString("[] = { ");
2353 for( sal_Int32 j
=0; j
<nLevels
.back(); j
++ )
2355 of
.writeAsciiString("outlineStyle");
2356 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2357 of
.writeAsciiString("Level");
2358 of
.writeInt( sal::static_int_cast
<sal_Int16
>(j
) );
2359 of
.writeAsciiString(", ");
2361 of
.writeAsciiString("NULL };\n");
2363 of
.writeAsciiString("\n");
2365 of
.writeAsciiString("static const sal_Unicode*** LCOutlineNumberingLevelsArray[] = {\n" );
2366 for( sal_Int32 i
=0; i
<nStyles
; i
++ )
2368 of
.writeAsciiString( "\t" );
2369 of
.writeAsciiString( "outlineStyle" );
2370 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2371 of
.writeAsciiString(",\n");
2373 of
.writeAsciiString("\tNULL\n};\n\n");
2374 of
.writeFunction3("getOutlineNumberingLevels_", "outlineNbOfStyles", "outlineNbOfLevelsPerStyle",
2375 "outlineNbOfAttributesPerLevel", "LCOutlineNumberingLevelsArray");
2378 Attr::Attr (const Reference
< XAttributeList
> & attr
) {
2379 sal_Int16 len
= attr
->getLength();
2381 value
.realloc (len
);
2382 for (sal_Int16 i
=0; i
< len
;i
++) {
2383 name
[i
] = attr
->getNameByIndex(i
);
2384 value
[i
] = attr
-> getValueByIndex(i
);
2388 const OUString
& Attr::getValueByName (const sal_Char
*str
) const {
2389 static OUString empty
;
2390 sal_Int32 len
= name
.getLength();
2391 for (sal_Int32 i
= 0;i
<len
;i
++)
2392 if (name
[i
].equalsAscii(str
))
2397 sal_Int32
Attr::getLength() const{
2398 return name
.getLength();
2401 const OUString
& Attr::getTypeByIndex (sal_Int32 idx
) const {
2405 const OUString
& Attr::getValueByIndex (sal_Int32 idx
) const
2410 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */