1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
36 #include <rtl/ustrbuf.hxx>
37 #include <sal/macros.h>
39 #include "LocaleNode.hxx"
40 #include <com/sun/star/i18n/NumberFormatIndex.hpp>
42 // NOTE: MUST match the Locale versionDTD attribute defined in data/locale.dtd
43 #define LOCALE_VERSION_DTD "2.0.3"
45 typedef ::std::set
< ::rtl::OUString
> NameSet
;
46 typedef ::std::set
< sal_Int16
> ValueSet
;
48 namespace cssi
= ::com::sun::star::i18n
;
50 LocaleNode::LocaleNode (const OUString
& name
, const Reference
< XAttributeList
> & attr
)
61 int LocaleNode::getError() const
64 for (sal_Int32 i
=0;i
<nChildren
;i
++)
65 err
+= children
[i
]->getError();
69 void LocaleNode::print () const {
71 ::rtl::OUString
str (aName
);
72 for(sal_Int32 i
= 0; i
< str
.getLength(); i
++)
73 printf( "%c", str
[i
]);
77 void LocaleNode::printR () const {
79 for (sal_Int32 i
=0;i
<nChildren
;i
++)
80 children
[i
]->printR();
85 void LocaleNode::addChild ( LocaleNode
* node
) {
86 if (childArrSize
<= nChildren
) {
87 LocaleNode
** arrN
= new LocaleNode
*[childArrSize
+10];
88 for (sal_Int32 i
= 0; i
<childArrSize
; ++i
)
89 arrN
[i
] = children
[i
];
94 children
[nChildren
++] = node
;
95 node
->setParent (this);
98 void LocaleNode::setParent ( LocaleNode
* node
) {
102 const LocaleNode
* LocaleNode::getRoot() const
104 const LocaleNode
* pRoot
= 0;
105 const LocaleNode
* pParent
= this;
106 while ( (pParent
= pParent
->getParent()) != 0 )
111 const LocaleNode
* LocaleNode::findNode ( const sal_Char
*name
) const {
112 if (aName
.equalsAscii(name
))
114 for (sal_Int32 i
= 0; i
< nChildren
; i
++) {
115 const LocaleNode
*n
=children
[i
]->findNode(name
);
122 LocaleNode::~LocaleNode()
124 for (sal_Int32 i
=0; i
< nChildren
; ++i
)
129 LocaleNode
* LocaleNode::createNode (const OUString
& name
, const Reference
< XAttributeList
> & attr
)
131 if ( name
== "LC_INFO" )
132 return new LCInfoNode (name
,attr
);
133 if ( name
== "LC_CTYPE" )
134 return new LCCTYPENode (name
,attr
);
135 if ( name
== "LC_FORMAT" )
136 return new LCFormatNode (name
,attr
);
137 if ( name
== "LC_FORMAT_1" )
138 return new LCFormatNode (name
,attr
);
139 if ( name
== "LC_CALENDAR" )
140 return new LCCalendarNode (name
,attr
);
141 if ( name
== "LC_CURRENCY" )
142 return new LCCurrencyNode (name
,attr
);
143 if ( name
== "LC_TRANSLITERATION" )
144 return new LCTransliterationNode (name
,attr
);
145 if ( name
== "LC_COLLATION" )
146 return new LCCollationNode (name
,attr
);
147 if ( name
== "LC_INDEX" )
148 return new LCIndexNode (name
,attr
);
149 if ( name
== "LC_SEARCH" )
150 return new LCSearchNode (name
,attr
);
151 if ( name
== "LC_MISC" )
152 return new LCMiscNode (name
,attr
);
153 if ( name
== "LC_NumberingLevel" )
154 return new LCNumberingLevelNode (name
, attr
);
155 if ( name
== "LC_OutLineNumberingLevel" )
156 return new LCOutlineNumberingLevelNode (name
, attr
);
158 return new LocaleNode(name
,attr
);
162 // printf(" name: '%s'\n", p->getName().pData->buffer );
163 // printf("value: '%s'\n", p->getValue().pData->buffer );
165 #define OSTR(s) (OUStringToOString( (s), RTL_TEXTENCODING_UTF8).getStr())
167 void print_OUString( const OUString
& s
)
169 printf( "%s", OSTR(s
));
172 bool is_empty_string( const OUString
& s
)
174 return s
.isEmpty() || (s
.getLength()==1 && s
[0]=='\n');
177 void print_indent( int depth
)
179 for( int i
=0; i
<depth
; i
++ ) printf(" ");
182 void print_color( int color
)
184 printf("\033[%dm", color
);
187 void print_node( const LocaleNode
* p
, int depth
=0 )
191 print_indent( depth
);
194 print_OUString( p
->getName() );
196 const Attr
& q
= p
->getAttr();
197 for( sal_Int32 j
= 0; j
< q
.getLength(); ++j
)
201 print_OUString( q
.getTypeByIndex(j
) );
206 print_OUString( q
.getValueByIndex(j
) );
212 if( !is_empty_string( p
->getValue() ) )
214 print_indent( depth
+1 );
218 print_OUString( p
->getValue() );
223 for( sal_Int32 i
=0; i
<p
->getNumberOfChildren(); i
++ )
225 print_node( p
->getChildAt(i
), depth
+1 );
227 print_indent( depth
);
229 print_OUString( p
->getName() );
234 void LocaleNode :: generateCode (const OFileWriter
&of
) const
236 ::rtl::OUString aDTD
= getAttr().getValueByName("versionDTD");
237 if ( aDTD
!= LOCALE_VERSION_DTD
)
240 fprintf( stderr
, "Error: Locale versionDTD is not %s, see comment in locale.dtd\n", LOCALE_VERSION_DTD
);
242 for (sal_Int32 i
=0; i
<nChildren
;i
++)
243 children
[i
]->generateCode (of
);
244 // print_node( this );
248 ::rtl::OUString
LocaleNode::writeParameterCheckLen( const OFileWriter
&of
,
249 const char* pParameterName
, const LocaleNode
* pNode
,
250 sal_Int32 nMinLen
, sal_Int32 nMaxLen
) const
254 aVal
= pNode
->getValue();
258 fprintf( stderr
, "Error: node NULL pointer for parameter %s.\n",
261 // write empty data if error
262 of
.writeParameter( pParameterName
, aVal
);
263 sal_Int32 nLen
= aVal
.getLength();
267 fprintf( stderr
, "Error: less than %ld character%s (%ld) in %s '%s'.\n",
268 sal::static_int_cast
< long >(nMinLen
), (nMinLen
> 1 ? "s" : ""),
269 sal::static_int_cast
< long >(nLen
),
270 (pNode
? OSTR( pNode
->getName()) : ""),
273 else if (nLen
> nMaxLen
&& nMaxLen
>= 0)
275 "Warning: more than %ld character%s (%ld) in %s %s not supported by application.\n",
276 sal::static_int_cast
< long >(nMaxLen
), (nMaxLen
> 1 ? "s" : ""),
277 sal::static_int_cast
< long >(nLen
),
278 (pNode
? OSTR( pNode
->getName()) : ""),
284 ::rtl::OUString
LocaleNode::writeParameterCheckLen( const OFileWriter
&of
,
285 const char* pNodeName
, const char* pParameterName
,
286 sal_Int32 nMinLen
, sal_Int32 nMaxLen
) const
289 const LocaleNode
* pNode
= findNode( pNodeName
);
291 aVal
= writeParameterCheckLen( of
, pParameterName
, pNode
, nMinLen
, nMaxLen
);
295 fprintf( stderr
, "Error: node %s not found.\n", pNodeName
);
296 // write empty data if error
297 of
.writeParameter( pParameterName
, aVal
);
302 void LocaleNode::incError( const char* pStr
) const
305 fprintf( stderr
, "Error: %s\n", pStr
);
308 void LocaleNode::incError( const ::rtl::OUString
& rStr
) const
310 incError( OSTR( rStr
));
313 char* LocaleNode::prepareErrorFormat( const char* pFormat
, const char* pDefaultConversion
) const
315 static char buf
[2048];
316 strcpy( buf
, "Error: ");
317 strncat( buf
, pFormat
, 2000);
319 while (((p
= strchr( p
, '%')) != 0) && p
[1] == '%')
322 strcat( buf
, pDefaultConversion
);
327 void LocaleNode::incErrorInt( const char* pStr
, int nVal
) const
330 fprintf( stderr
, prepareErrorFormat( pStr
, ": %d"), nVal
);
333 void LocaleNode::incErrorStr( const char* pStr
, const ::rtl::OUString
& rVal
) const
336 fprintf( stderr
, prepareErrorFormat( pStr
, ": %s"), OSTR( rVal
));
339 void LocaleNode::incErrorStrStr( const char* pStr
, const ::rtl::OUString
& rVal1
, const ::rtl::OUString
& rVal2
) const
342 fprintf( stderr
, prepareErrorFormat( pStr
, ": %s %s"), OSTR( rVal1
), OSTR( rVal2
));
345 void LCInfoNode::generateCode (const OFileWriter
&of
) const
348 const LocaleNode
* languageNode
= findNode("Language");
349 const LocaleNode
* countryNode
= findNode("Country");
350 const LocaleNode
* variantNode
= findNode("Variant");
354 writeParameterCheckLen( of
, "langID", languageNode
->getChildAt(0), 2, -1);
355 of
.writeParameter("langDefaultName", languageNode
->getChildAt(1)->getValue());
358 incError( "No Language node.");
361 of
.writeParameter("countryID", countryNode
->getChildAt(0)->getValue());
362 of
.writeParameter("countryDefaultName", countryNode
->getChildAt(1)->getValue());
365 incError( "No Country node.");
368 of
.writeParameter("Variant", variantNode
->getValue());
369 fprintf( stderr
, "Warning: %s\n",
370 "Variants are not supported by application.");
373 of
.writeParameter("Variant", ::rtl::OUString());
374 of
.writeAsciiString("\nstatic const sal_Unicode* LCInfoArray[] = {\n");
375 of
.writeAsciiString("\tlangID,\n");
376 of
.writeAsciiString("\tlangDefaultName,\n");
377 of
.writeAsciiString("\tcountryID,\n");
378 of
.writeAsciiString("\tcountryDefaultName,\n");
379 of
.writeAsciiString("\tVariant\n");
380 of
.writeAsciiString("};\n\n");
381 of
.writeFunction("getLCInfo_", "0", "LCInfoArray");
385 static OUString aDateSep
;
386 static OUString aDecSep
;
388 void LCCTYPENode::generateCode (const OFileWriter
&of
) const
390 const LocaleNode
* sepNode
= 0;
391 ::rtl::OUString useLocale
= getAttr().getValueByName("ref");
392 if (!useLocale
.isEmpty()) {
393 of
.writeRefFunction("getLocaleItem_", useLocale
);
396 ::rtl::OUString str
= getAttr().getValueByName("unoid");
397 of
.writeAsciiString("\n\n");
398 of
.writeParameter("LC_CTYPE_Unoid", str
);;
401 writeParameterCheckLen( of
, "DateSeparator", "dateSeparator", 1, 1);
403 writeParameterCheckLen( of
, "ThousandSeparator", "thousandSeparator", 1, 1);
405 writeParameterCheckLen( of
, "DecimalSeparator", "decimalSeparator", 1, 1);
407 writeParameterCheckLen( of
, "TimeSeparator", "timeSeparator", 1, 1);
408 OUString aTime100Sep
=
409 writeParameterCheckLen( of
, "Time100SecSeparator", "time100SecSeparator", 1, 1);
411 writeParameterCheckLen( of
, "ListSeparator", "listSeparator", 1, 1);
415 sepNode
= findNode("LongDateDayOfWeekSeparator");
416 aLDS
= sepNode
->getValue();
417 of
.writeParameter("LongDateDayOfWeekSeparator", aLDS
);
418 if (aLDS
.getLength() == 1 && aLDS
.getStr()[0] == ',')
419 fprintf( stderr
, "Warning: %s\n",
420 "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\".");
422 sepNode
= findNode("LongDateDaySeparator");
423 aLDS
= sepNode
->getValue();
424 of
.writeParameter("LongDateDaySeparator", aLDS
);
425 if (aLDS
.getLength() == 1 && (aLDS
.getStr()[0] == ',' || aLDS
.getStr()[0] == '.'))
426 fprintf( stderr
, "Warning: %s\n",
427 "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\".");
429 sepNode
= findNode("LongDateMonthSeparator");
430 aLDS
= sepNode
->getValue();
431 of
.writeParameter("LongDateMonthSeparator", aLDS
);
433 fprintf( stderr
, "Warning: %s\n",
434 "LongDateMonthSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, May9, 2007\".");
436 sepNode
= findNode("LongDateYearSeparator");
437 aLDS
= sepNode
->getValue();
438 of
.writeParameter("LongDateYearSeparator", aLDS
);
440 fprintf( stderr
, "Warning: %s\n",
441 "LongDateYearSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, 2007May 9\".");
444 int nSavErr
= nError
;
446 if (aDateSep
== aTimeSep
)
447 incError( "DateSeparator equals TimeSeparator.");
448 if (aDecSep
== aThoSep
)
449 incError( "DecimalSeparator equals ThousandSeparator.");
450 if ( aThoSep
== " " )
451 incError( "ThousandSeparator is an ' ' ordinary space, this should be a non-breaking space U+00A0 instead.");
452 if (aListSep
== aDecSep
)
453 fprintf( stderr
, "Warning: %s\n",
454 "ListSeparator equals DecimalSeparator.");
455 if (aListSep
== aThoSep
)
456 fprintf( stderr
, "Warning: %s\n",
457 "ListSeparator equals ThousandSeparator.");
458 if (aListSep
.getLength() != 1 || aListSep
.getStr()[0] != ';')
460 incError( "ListSeparator not ';' semicolon. Strongly recommended. Currently required.");
461 ++nSavErr
; // format codes not affected
463 if (aTimeSep
== aTime100Sep
)
464 ++nWarn
, fprintf( stderr
, "Warning: %s\n",
465 "Time100SecSeparator equals TimeSeparator, this is probably an error.");
466 if (aDecSep
!= aTime100Sep
)
467 ++nWarn
, fprintf( stderr
, "Warning: %s\n",
468 "Time100SecSeparator is different from DecimalSeparator, this may be correct or not. Intended?");
469 if (nSavErr
!= nError
|| nWarn
)
470 fprintf( stderr
, "Warning: %s\n",
471 "Don't forget to adapt corresponding FormatCode elements when changing separators.");
473 OUString aQuoteStart
=
474 writeParameterCheckLen( of
, "QuotationStart", "quotationStart", 1, 1);
476 writeParameterCheckLen( of
, "QuotationEnd", "quotationEnd", 1, 1);
477 OUString aDoubleQuoteStart
=
478 writeParameterCheckLen( of
, "DoubleQuotationStart", "doubleQuotationStart", 1, 1);
479 OUString aDoubleQuoteEnd
=
480 writeParameterCheckLen( of
, "DoubleQuotationEnd", "doubleQuotationEnd", 1, 1);
482 if (aQuoteStart
.toChar() <= 127 && aQuoteEnd
.toChar() > 127)
483 fprintf( stderr
, "Warning: %s\n",
484 "QuotationStart is an ASCII character but QuotationEnd is not.");
485 if (aQuoteEnd
.toChar() <= 127 && aQuoteStart
.toChar() > 127)
486 fprintf( stderr
, "Warning: %s\n",
487 "QuotationEnd is an ASCII character but QuotationStart is not.");
488 if (aDoubleQuoteStart
.toChar() <= 127 && aDoubleQuoteEnd
.toChar() > 127)
489 fprintf( stderr
, "Warning: %s\n",
490 "DoubleQuotationStart is an ASCII character but DoubleQuotationEnd is not.");
491 if (aDoubleQuoteEnd
.toChar() <= 127 && aDoubleQuoteStart
.toChar() > 127)
492 fprintf( stderr
, "Warning: %s\n",
493 "DoubleQuotationEnd is an ASCII character but DoubleQuotationStart is not.");
494 if (aQuoteStart
.toChar() <= 127 && aQuoteEnd
.toChar() <= 127)
495 fprintf( stderr
, "Warning: %s\n",
496 "QuotationStart and QuotationEnd are both ASCII characters. Not necessarily an issue, but unusual.");
497 if (aDoubleQuoteStart
.toChar() <= 127 && aDoubleQuoteEnd
.toChar() <= 127)
498 fprintf( stderr
, "Warning: %s\n",
499 "DoubleQuotationStart and DoubleQuotationEnd are both ASCII characters. Not necessarily an issue, but unusual.");
500 if (aQuoteStart
== aQuoteEnd
)
501 fprintf( stderr
, "Warning: %s\n",
502 "QuotationStart equals QuotationEnd. Not necessarily an issue, but unusual.");
503 if (aDoubleQuoteStart
== aDoubleQuoteEnd
)
504 fprintf( stderr
, "Warning: %s\n",
505 "DoubleQuotationStart equals DoubleQuotationEnd. Not necessarily an issue, but unusual.");
506 /* TODO: should equalness of single and double quotes be an error? Would
507 * need to adapt quite some locales' data. */
508 if (aQuoteStart
== aDoubleQuoteStart
)
509 fprintf( stderr
, "Warning: %s\n",
510 "QuotationStart equals DoubleQuotationStart. Not necessarily an isue, but unusual.");
511 if (aQuoteEnd
== aDoubleQuoteEnd
)
512 fprintf( stderr
, "Warning: %s\n",
513 "QuotationEnd equals DoubleQuotationEnd. Not necessarily an issue, but unusual.");
514 // Known good values, exclude ASCII single (U+0027, ') and double (U+0022, ") quotes.
516 switch (ic
= aQuoteStart
.toChar())
518 case 0x2018: // LEFT SINGLE QUOTATION MARK
519 case 0x201a: // SINGLE LOW-9 QUOTATION MARK
520 case 0x201b: // SINGLE HIGH-REVERSED-9 QUOTATION MARK
521 case 0x2039: // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
522 case 0x203a: // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
523 case 0x300c: // LEFT CORNER BRACKET (Chinese)
527 fprintf( stderr
, "Warning: %s U+%04X %s\n",
528 "QuotationStart may be wrong:", ic
, OSTR( aQuoteStart
));
530 switch (ic
= aQuoteEnd
.toChar())
532 case 0x2019: // RIGHT SINGLE QUOTATION MARK
533 case 0x201a: // SINGLE LOW-9 QUOTATION MARK
534 case 0x201b: // SINGLE HIGH-REVERSED-9 QUOTATION MARK
535 case 0x2039: // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
536 case 0x203a: // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
537 case 0x300d: // RIGHT CORNER BRACKET (Chinese)
541 fprintf( stderr
, "Warning: %s U+%04X %s\n",
542 "QuotationEnd may be wrong:", ic
, OSTR( aQuoteEnd
));
544 switch (ic
= aDoubleQuoteStart
.toChar())
546 case 0x00ab: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
547 case 0x00bb: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
548 case 0x201c: // LEFT DOUBLE QUOTATION MARK
549 case 0x201e: // DOUBLE LOW-9 QUOTATION MARK
550 case 0x201f: // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
551 case 0x300e: // LEFT WHITE CORNER BRACKET (Chinese)
555 fprintf( stderr
, "Warning: %s U+%04X %s\n",
556 "DoubleQuotationStart may be wrong:", ic
, OSTR( aDoubleQuoteStart
));
558 switch (ic
= aDoubleQuoteEnd
.toChar())
560 case 0x00ab: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
561 case 0x00bb: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
562 case 0x201d: // RIGHT DOUBLE QUOTATION MARK
563 case 0x201e: // DOUBLE LOW-9 QUOTATION MARK
564 case 0x201f: // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
565 case 0x300f: // RIGHT WHITE CORNER BRACKET (Chinese)
569 fprintf( stderr
, "Warning: %s U+%04X %s\n",
570 "DoubleQuotationEnd may be wrong:", ic
, OSTR( aDoubleQuoteEnd
));
573 writeParameterCheckLen( of
, "TimeAM", "timeAM", 1, -1);
574 writeParameterCheckLen( of
, "TimePM", "timePM", 1, -1);
575 sepNode
= findNode("MeasurementSystem");
576 of
.writeParameter("measurementSystem", sepNode
->getValue());
578 of
.writeAsciiString("\nstatic const sal_Unicode* LCType[] = {\n");
579 of
.writeAsciiString("\tLC_CTYPE_Unoid,\n");
580 of
.writeAsciiString("\tdateSeparator,\n");
581 of
.writeAsciiString("\tthousandSeparator,\n");
582 of
.writeAsciiString("\tdecimalSeparator,\n");
583 of
.writeAsciiString("\ttimeSeparator,\n");
584 of
.writeAsciiString("\ttime100SecSeparator,\n");
585 of
.writeAsciiString("\tlistSeparator,\n");
586 of
.writeAsciiString("\tquotationStart,\n");
587 of
.writeAsciiString("\tquotationEnd,\n");
588 of
.writeAsciiString("\tdoubleQuotationStart,\n");
589 of
.writeAsciiString("\tdoubleQuotationEnd,\n");
590 of
.writeAsciiString("\ttimeAM,\n");
591 of
.writeAsciiString("\ttimePM,\n");
592 of
.writeAsciiString("\tmeasurementSystem,\n");
593 of
.writeAsciiString("\tLongDateDayOfWeekSeparator,\n");
594 of
.writeAsciiString("\tLongDateDaySeparator,\n");
595 of
.writeAsciiString("\tLongDateMonthSeparator,\n");
596 of
.writeAsciiString("\tLongDateYearSeparator\n");
597 of
.writeAsciiString("};\n\n");
598 of
.writeFunction("getLocaleItem_", "0", "LCType");
602 static OUString sTheCurrencyReplaceTo
;
603 static OUString sTheCompatibleCurrency
;
604 static OUString sTheDateEditFormat
;
606 sal_Int16
LCFormatNode::mnSection
= 0;
607 sal_Int16
LCFormatNode::mnFormats
= 0;
609 void LCFormatNode::generateCode (const OFileWriter
&of
) const
612 incError("more than 2 LC_FORMAT sections");
614 ::std::vector
< OUString
> theDateAcceptancePatterns
;
617 OUString
strFrom( getAttr().getValueByName("replaceFrom"));
618 of
.writeParameter("replaceFrom", strFrom
, mnSection
);
619 str
= getAttr().getValueByName("replaceTo");
620 if (!strFrom
.isEmpty() && str
.isEmpty())
621 incErrorStr("replaceFrom=\"%s\" replaceTo=\"\" is empty replacement.", strFrom
);
622 // Locale data generator inserts FFFF for LangID, we need to adapt that.
623 if (str
.endsWithIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "-FFFF]")))
624 incErrorStr("replaceTo=\"%s\" needs FFFF to be adapted to the real LangID value.", str
);
625 of
.writeParameter("replaceTo", str
, mnSection
);
626 // Remember the replaceTo value for "[CURRENCY]" to check format codes.
627 if ( strFrom
== "[CURRENCY]" )
628 sTheCurrencyReplaceTo
= str
;
629 // Remember the currency symbol if present.
630 if (str
.indexOfAsciiL( "[$", 2) == 0)
632 sal_Int32 nHyphen
= str
.indexOf( '-');
635 sTheCompatibleCurrency
= str
.copy( 2, nHyphen
- 2);
639 ::rtl::OUString useLocale
= getAttr().getValueByName("ref");
640 if (!useLocale
.isEmpty())
645 of
.writeRefFunction("getAllFormats0_", useLocale
, "replaceTo0");
648 of
.writeRefFunction("getAllFormats1_", useLocale
, "replaceTo1");
651 of
.writeRefFunction("getDateAcceptancePatterns_", useLocale
);
655 sal_Int16 formatCount
= mnFormats
;
657 ValueSet aFormatIndexSet
;
658 NameSet aDefaultsSet
;
659 bool bCtypeIsRef
= false;
661 for (sal_Int16 i
= 0; i
< getNumberOfChildren() ; i
++, formatCount
++)
663 LocaleNode
* currNode
= getChildAt (i
);
664 if ( currNode
->getName() == "DateAcceptancePattern" )
667 incError( "DateAcceptancePattern only handled in LC_FORMAT, not LC_FORMAT_1");
669 theDateAcceptancePatterns
.push_back( currNode
->getValue());
673 if ( currNode
->getName() != "FormatElement" )
675 incErrorStr( "Undefined element in LC_FORMAT", currNode
->getName());
682 OUString aFormatIndex
;
683 // currNode -> print();
684 const Attr
&currNodeAttr
= currNode
->getAttr();
685 //printf ("getLen() = %d\n", currNode->getAttr().getLength());
687 str
= currNodeAttr
.getValueByName("msgid");
688 if (!aMsgIdSet
.insert( str
).second
)
689 incErrorStr( "Duplicated msgid=\"%s\" in FormatElement.", str
);
690 of
.writeParameter("FormatKey", str
, formatCount
);
692 str
= currNodeAttr
.getValueByName("default");
693 bool bDefault
= str
== "true";
694 of
.writeDefaultParameter("FormatElement", str
, formatCount
);
696 aType
= currNodeAttr
.getValueByName("type");
697 of
.writeParameter("FormatType", aType
, formatCount
);
699 aUsage
= currNodeAttr
.getValueByName("usage");
700 of
.writeParameter("FormatUsage", aUsage
, formatCount
);
702 aFormatIndex
= currNodeAttr
.getValueByName("formatindex");
703 sal_Int16 formatindex
= (sal_Int16
)aFormatIndex
.toInt32();
704 if (!aFormatIndexSet
.insert( formatindex
).second
)
705 incErrorInt( "Duplicated formatindex=\"%d\" in FormatElement.", formatindex
);
706 of
.writeIntParameter("Formatindex", formatCount
, formatindex
);
708 // Ensure only one default per usage and type.
711 OUString
aKey( aUsage
+ OUString( sal_Unicode(',')) + aType
);
712 if (!aDefaultsSet
.insert( aKey
).second
)
714 OUString
aStr( "Duplicated default for usage=\"");
716 aStr
+= OUString( "\" type=\"");
718 aStr
+= OUString( "\": formatindex=\"");
719 aStr
+= aFormatIndex
;
720 aStr
+= OUString( "\".");
725 const LocaleNode
* n
= currNode
-> findNode("FormatCode");
728 of
.writeParameter("FormatCode", n
->getValue(), formatCount
);
729 // Check separator usage for some FormatCode elements.
730 const LocaleNode
* pCtype
= 0;
733 case cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
:
734 sTheDateEditFormat
= n
->getValue();
736 case cssi::NumberFormatIndex::NUMBER_1000DEC2
: // #,##0.00
737 case cssi::NumberFormatIndex::TIME_MMSS00
: // MM:SS.00
738 case cssi::NumberFormatIndex::TIME_HH_MMSS00
: // [HH]:MM:SS.00
740 const LocaleNode
* pRoot
= getRoot();
742 incError( "No root for FormatCode.");
745 pCtype
= pRoot
->findNode( "LC_CTYPE");
747 incError( "No LC_CTYPE found for FormatCode.");
750 OUString
aRef( pCtype
->getAttr().getValueByName("ref"));
755 "Warning: Can't check separators used in FormatCode due to LC_CTYPE ref=\"%s\".\n"
756 "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",
765 case cssi::NumberFormatIndex::CURRENCY_1000DEC2
:
766 // Remember the currency symbol if present.
769 if (sTheCompatibleCurrency
.isEmpty() &&
770 ((nStart
= n
->getValue().indexOfAsciiL( "[$", 2)) >= 0))
772 OUString
aCode( n
->getValue());
773 sal_Int32 nHyphen
= aCode
.indexOf( '-', nStart
);
774 if (nHyphen
>= nStart
+ 3)
775 sTheCompatibleCurrency
= aCode
.copy( nStart
+ 2, nHyphen
- nStart
- 2);
779 case cssi::NumberFormatIndex::CURRENCY_1000INT
:
780 case cssi::NumberFormatIndex::CURRENCY_1000INT_RED
:
781 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_RED
:
782 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_CCC
:
783 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_DASHED
:
784 // Currency formats should be something like [C]###0;-[C]###0
785 // and not parenthesized [C]###0;([C]###0) if not en_US.
786 if (strcmp( of
.getLocale(), "en_US") != 0)
788 OUString
aCode( n
->getValue());
789 OUString
aPar1( "0)");
790 OUString
aPar2( "-)" );
791 OUString
aPar3( " )" );
792 OUString
aPar4( "])" );
793 if (aCode
.indexOf( aPar1
) > 0 || aCode
.indexOf( aPar2
) > 0 ||
794 aCode
.indexOf( aPar3
) > 0 || aCode
.indexOf( aPar4
) > 0)
795 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
);
797 // Check if we have replaceTo for "[CURRENCY]" placeholder.
798 if (sTheCurrencyReplaceTo
.isEmpty())
800 OUString
aCode( n
->getValue());
801 if (aCode
.indexOfAsciiL( RTL_CONSTASCII_STRINGPARAM( "[CURRENCY]")) >= 0)
802 incErrorInt( "[CURRENCY] replaceTo not found for formatindex=\"%d\".", formatindex
);
808 int nSavErr
= nError
;
809 OUString
aCode( n
->getValue());
810 if (formatindex
== cssi::NumberFormatIndex::NUMBER_1000DEC2
)
814 const LocaleNode
* pSep
= pCtype
->findNode( "DecimalSeparator");
816 incError( "No DecimalSeparator found for FormatCode.");
819 nDec
= aCode
.indexOf( pSep
->getValue());
821 incErrorInt( "DecimalSeparator not present in FormatCode formatindex=\"%d\".",
824 pSep
= pCtype
->findNode( "ThousandSeparator");
826 incError( "No ThousandSeparator found for FormatCode.");
829 nGrp
= aCode
.indexOf( pSep
->getValue());
831 incErrorInt( "ThousandSeparator not present in FormatCode formatindex=\"%d\".",
834 if (nDec
>= 0 && nGrp
>= 0 && nDec
<= nGrp
)
835 incErrorInt( "Ordering of ThousandSeparator and DecimalSeparator not correct in formatindex=\"%d\".",
838 if (formatindex
== cssi::NumberFormatIndex::TIME_MMSS00
||
839 formatindex
== cssi::NumberFormatIndex::TIME_HH_MMSS00
)
841 sal_Int32 nTime
= -1;
842 sal_Int32 n100s
= -1;
843 const LocaleNode
* pSep
= pCtype
->findNode( "TimeSeparator");
845 incError( "No TimeSeparator found for FormatCode.");
848 nTime
= aCode
.indexOf( pSep
->getValue());
850 incErrorInt( "TimeSeparator not present in FormatCode formatindex=\"%d\".",
853 pSep
= pCtype
->findNode( "Time100SecSeparator");
855 incError( "No Time100SecSeparator found for FormatCode.");
858 n100s
= aCode
.indexOf( pSep
->getValue());
860 incErrorInt( "Time100SecSeparator not present in FormatCode formatindex=\"%d\".",
862 OUStringBuffer
a100s( pSep
->getValue());
863 a100s
.appendAscii( "00");
864 n100s
= aCode
.indexOf( a100s
.makeStringAndClear());
866 incErrorInt( "Time100SecSeparator+00 not present in FormatCode formatindex=\"%d\".",
869 if (n100s
>= 0 && nTime
>= 0 && n100s
<= nTime
)
870 incErrorInt( "Ordering of Time100SecSeparator and TimeSeparator not correct in formatindex=\"%d\".",
873 if (nSavErr
!= nError
)
875 "Warning: formatindex=\"%d\",\"%d\",\"%d\" are the only FormatCode elements checked for separator usage, there may be others that have errors.\n",
876 int(cssi::NumberFormatIndex::NUMBER_1000DEC2
),
877 int(cssi::NumberFormatIndex::TIME_MMSS00
),
878 int(cssi::NumberFormatIndex::TIME_HH_MMSS00
));
883 incError( "No FormatCode in FormatElement.");
884 n
= currNode
-> findNode("DefaultName");
886 of
.writeParameter("FormatDefaultName", n
->getValue(), formatCount
);
888 of
.writeParameter("FormatDefaultName", ::rtl::OUString(), formatCount
);
892 // Check presence of all required format codes only in first section
893 // LC_FORMAT, not in optional LC_FORMAT_1
896 // 0..47 MUST be present, 48,49 MUST NOT be present
897 ValueSet::const_iterator
aIter( aFormatIndexSet
.begin());
898 for (sal_Int16 nNext
= cssi::NumberFormatIndex::NUMBER_START
;
899 nNext
< cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES
; ++nNext
)
901 sal_Int16 nHere
= ::std::min( ((aIter
!= aFormatIndexSet
.end() ? *aIter
:
902 cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES
)),
903 cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES
);
904 if (aIter
!= aFormatIndexSet
.end()) ++aIter
;
905 for ( ; nNext
< nHere
; ++nNext
)
909 case cssi::NumberFormatIndex::FRACTION_1
:
910 case cssi::NumberFormatIndex::FRACTION_2
:
911 case cssi::NumberFormatIndex::BOOLEAN
:
912 case cssi::NumberFormatIndex::TEXT
:
913 // generated internally
916 incErrorInt( "FormatElement formatindex=\"%d\" not present.", nNext
);
921 case cssi::NumberFormatIndex::BOOLEAN
:
922 incErrorInt( "FormatElement formatindex=\"%d\" reserved for internal ``BOOLEAN''.", nNext
);
924 case cssi::NumberFormatIndex::TEXT
:
925 incErrorInt( "FormatElement formatindex=\"%d\" reserved for internal ``@'' (TEXT).", nNext
);
933 of
.writeAsciiString("\nstatic const sal_Int16 ");
934 of
.writeAsciiString("FormatElementsCount");
935 of
.writeInt(mnSection
);
936 of
.writeAsciiString(" = ");
937 of
.writeInt( formatCount
- mnFormats
);
938 of
.writeAsciiString(";\n");
939 of
.writeAsciiString("static const sal_Unicode* ");
940 of
.writeAsciiString("FormatElementsArray");
941 of
.writeInt(mnSection
);
942 of
.writeAsciiString("[] = {\n");
943 for(sal_Int16 i
= mnFormats
; i
< formatCount
; i
++) {
945 of
.writeAsciiString("\t");
946 of
.writeAsciiString("FormatCode");
948 of
.writeAsciiString(",\n");
950 of
.writeAsciiString("\t");
951 of
.writeAsciiString("FormatDefaultName");
953 of
.writeAsciiString(",\n");
955 of
.writeAsciiString("\t");
956 of
.writeAsciiString("FormatKey");
958 of
.writeAsciiString(",\n");
960 of
.writeAsciiString("\t");
961 of
.writeAsciiString("FormatType");
963 of
.writeAsciiString(",\n");
965 of
.writeAsciiString("\t");
966 of
.writeAsciiString("FormatUsage");
968 of
.writeAsciiString(",\n");
970 of
.writeAsciiString("\t");
971 of
.writeAsciiString("Formatindex");
973 of
.writeAsciiString(",\n");
976 of
.writeAsciiString("\tdefaultFormatElement");
978 of
.writeAsciiString(",\n");
980 of
.writeAsciiString("};\n\n");
985 of
.writeFunction("getAllFormats0_", "FormatElementsCount0", "FormatElementsArray0", "replaceFrom0", "replaceTo0");
988 of
.writeFunction("getAllFormats1_", "FormatElementsCount1", "FormatElementsArray1", "replaceFrom1", "replaceTo1");
992 mnFormats
= mnFormats
+ formatCount
;
996 // Extract and add date acceptance pattern for full date, so we provide
997 // at least one valid pattern, even if the number parser doesn't need
999 /* XXX NOTE: only simple [...] modifier and "..." quotes detected and
1000 * ignored, not nested, no fancy stuff. */
1001 sal_Int32 nIndex
= 0;
1002 // aDateSep can be empty if LC_CTYPE was a ref=..., determine from
1004 sal_uInt32 cDateSep
= (aDateSep
.isEmpty() ? 0 : aDateSep
.iterateCodePoints( &nIndex
));
1005 sal_uInt32 cDateSep2
= cDateSep
;
1007 OUStringBuffer
aPatternBuf(5);
1008 OUStringBuffer
aPatternBuf2(5);
1009 sal_uInt8 nDetected
= 0; // bits Y,M,D
1010 bool bInModifier
= false;
1011 bool bQuoted
= false;
1012 while (nIndex
< sTheDateEditFormat
.getLength() && nDetected
< 7)
1014 sal_uInt32 cChar
= sTheDateEditFormat
.iterateCodePoints( &nIndex
);
1018 bInModifier
= false;
1031 if (!(nDetected
& 4))
1033 aPatternBuf
.append( 'Y');
1034 if (aPatternBuf2
.getLength() > 0)
1035 aPatternBuf2
.append( 'Y');
1041 if (!(nDetected
& 2))
1043 aPatternBuf
.append( 'M');
1044 if (aPatternBuf2
.getLength() > 0)
1045 aPatternBuf2
.append( 'M');
1051 if (!(nDetected
& 1))
1053 aPatternBuf
.append( 'D');
1054 if (aPatternBuf2
.getLength() > 0)
1055 aPatternBuf2
.append( 'D');
1066 cChar
= sTheDateEditFormat
.iterateCodePoints( &nIndex
);
1071 // There are locales that use an ISO 8601 edit format
1072 // regardless of what the date separator or other formats
1073 // say, for example hu-HU. Generalize this for all cases
1074 // where the used separator differs and is one of the known
1075 // separators and generate a second pattern with the
1076 // format's separator at the current position.
1084 if (cDateSep
!= cDateSep2
&& aPatternBuf2
.getLength() == 0)
1085 aPatternBuf2
= aPatternBuf
;
1086 if (cChar
== cDateSep
|| cChar
== cDateSep2
)
1087 aPatternBuf
.append( OUString( &cDateSep
, 1)); // always the defined separator
1088 if (cChar
== cDateSep2
&& aPatternBuf2
.getLength() > 0)
1089 aPatternBuf2
.append( OUString( &cDateSep2
, 1)); // always the format's separator
1091 // The localized legacy:
1093 if (((nDetected
& 7) == 3) || ((nDetected
& 7) == 0))
1099 aPatternBuf
.append( 'Y');
1100 if (aPatternBuf2
.getLength() > 0)
1101 aPatternBuf2
.append( 'Y');
1106 if (((nDetected
& 7) == 0) || ((nDetected
& 7) == 6))
1110 aPatternBuf
.append( 'D');
1111 if (aPatternBuf2
.getLength() > 0)
1112 aPatternBuf2
.append( 'D');
1115 else if ((nDetected
& 7) == 3)
1119 aPatternBuf
.append( 'Y');
1120 if (aPatternBuf2
.getLength() > 0)
1121 aPatternBuf2
.append( 'Y');
1126 if ((nDetected
& 7) == 0)
1129 aPatternBuf
.append( 'D');
1130 if (aPatternBuf2
.getLength() > 0)
1131 aPatternBuf2
.append( 'D');
1136 if ((nDetected
& 7) == 0)
1139 aPatternBuf
.append( 'D');
1140 if (aPatternBuf2
.getLength() > 0)
1141 aPatternBuf2
.append( 'D');
1146 if ((nDetected
& 7) == 0)
1149 aPatternBuf
.append( 'D');
1150 if (aPatternBuf2
.getLength() > 0)
1151 aPatternBuf2
.append( 'D');
1156 if ((nDetected
& 7) == 1)
1159 aPatternBuf
.append( 'M');
1160 if (aPatternBuf2
.getLength() > 0)
1161 aPatternBuf2
.append( 'M');
1166 if ((nDetected
& 7) == 3)
1169 aPatternBuf
.append( 'Y');
1170 if (aPatternBuf2
.getLength() > 0)
1171 aPatternBuf2
.append( 'Y');
1177 OUString
aPattern( aPatternBuf
.makeStringAndClear());
1178 if (((nDetected
& 7) != 7) || aPattern
.getLength() < 5)
1180 incErrorStr( "failed to extract full date acceptance pattern", aPattern
);
1181 fprintf( stderr
, " with DateSeparator '%s' from FormatCode '%s' (formatindex=\"%d\")\n",
1182 OSTR( OUString( cDateSep
)), OSTR( sTheDateEditFormat
),
1183 (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
);
1187 fprintf( stderr
, "Generated date acceptance pattern: '%s' from '%s' (formatindex=\"%d\" and defined DateSeparator '%s')\n",
1188 OSTR( aPattern
), OSTR( sTheDateEditFormat
),
1189 (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
,
1190 OSTR( OUString( cDateSep
)));
1191 // Insert at front so full date pattern is first in checks.
1192 theDateAcceptancePatterns
.insert( theDateAcceptancePatterns
.begin(), aPattern
);
1194 if (aPatternBuf2
.getLength() > 0)
1196 OUString
aPattern2( aPatternBuf2
.makeStringAndClear());
1197 if (aPattern2
.getLength() < 5)
1199 incErrorStr( "failed to extract 2nd date acceptance pattern", aPattern2
);
1200 fprintf( stderr
, " with DateSeparator '%s' from FormatCode '%s' (formatindex=\"%d\")\n",
1201 OSTR( OUString( cDateSep2
)), OSTR( sTheDateEditFormat
),
1202 (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
);
1206 fprintf( stderr
, "Generated 2nd acceptance pattern: '%s' from '%s' (formatindex=\"%d\")\n",
1207 OSTR( aPattern2
), OSTR( sTheDateEditFormat
),
1208 (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY
);
1209 theDateAcceptancePatterns
.insert( theDateAcceptancePatterns
.begin(), aPattern2
);
1213 // Rudimentary check if a pattern interferes with decimal number.
1215 sal_uInt32 cDecSep
= aDecSep
.iterateCodePoints( &nIndex
);
1216 for (vector
<OUString
>::const_iterator aIt
= theDateAcceptancePatterns
.begin();
1217 aIt
!= theDateAcceptancePatterns
.end(); ++aIt
)
1219 if ((*aIt
).getLength() == (cDecSep
<= 0xffff ? 3 : 4))
1222 if ((*aIt
).iterateCodePoints( &nIndex
) == cDecSep
)
1225 fprintf( stderr
, "Error: Date acceptance pattern '%s' matches decimal number '#%s#'\n",
1226 OSTR( *aIt
), OSTR( aDecSep
));
1231 // Check for duplicates.
1232 for (vector
<OUString
>::const_iterator aIt
= theDateAcceptancePatterns
.begin();
1233 aIt
!= theDateAcceptancePatterns
.end(); ++aIt
)
1235 for (vector
<OUString
>::iterator aComp
= theDateAcceptancePatterns
.begin();
1236 aComp
!= theDateAcceptancePatterns
.end(); /*nop*/)
1238 if (aIt
!= aComp
&& *aIt
== *aComp
)
1240 incErrorStr( "Duplicated DateAcceptancePattern", *aComp
);
1241 aComp
= theDateAcceptancePatterns
.erase( aComp
);
1248 sal_Int16 nbOfDateAcceptancePatterns
= static_cast<sal_Int16
>(theDateAcceptancePatterns
.size());
1250 for (sal_Int16 i
= 0; i
< nbOfDateAcceptancePatterns
; ++i
)
1252 of
.writeParameter("DateAcceptancePattern", theDateAcceptancePatterns
[i
], i
);
1255 of
.writeAsciiString("static const sal_Int16 DateAcceptancePatternsCount = ");
1256 of
.writeInt( nbOfDateAcceptancePatterns
);
1257 of
.writeAsciiString(";\n");
1259 of
.writeAsciiString("static const sal_Unicode* DateAcceptancePatternsArray[] = {\n");
1260 for (sal_Int16 i
= 0; i
< nbOfDateAcceptancePatterns
; ++i
)
1262 of
.writeAsciiString("\t");
1263 of
.writeAsciiString("DateAcceptancePattern");
1265 of
.writeAsciiString(",\n");
1267 of
.writeAsciiString("};\n\n");
1269 of
.writeFunction("getDateAcceptancePatterns_", "DateAcceptancePatternsCount", "DateAcceptancePatternsArray");
1275 void LCCollationNode::generateCode (const OFileWriter
&of
) const
1277 ::rtl::OUString useLocale
= getAttr().getValueByName("ref");
1278 if (!useLocale
.isEmpty()) {
1279 of
.writeRefFunction("getCollatorImplementation_", useLocale
);
1280 of
.writeRefFunction("getCollationOptions_", useLocale
);
1283 sal_Int16 nbOfCollations
= 0;
1284 sal_Int16 nbOfCollationOptions
= 0;
1287 for ( j
= 0; j
< getNumberOfChildren(); j
++ ) {
1288 LocaleNode
* currNode
= getChildAt (j
);
1289 if( currNode
->getName().compareToAscii("Collator") == 0 )
1291 ::rtl::OUString str
;
1292 str
= currNode
->getAttr().getValueByName("unoid");
1293 of
.writeParameter("CollatorID", str
, j
);
1294 str
= currNode
->getValue();
1295 of
.writeParameter("CollatorRule", str
, j
);
1296 str
= currNode
-> getAttr().getValueByName("default");
1297 of
.writeDefaultParameter("Collator", str
, j
);
1298 of
.writeAsciiString("\n");
1302 if( currNode
->getName().compareToAscii("CollationOptions") == 0 )
1304 LocaleNode
* pCollationOptions
= currNode
;
1305 nbOfCollationOptions
= sal::static_int_cast
<sal_Int16
>( pCollationOptions
->getNumberOfChildren() );
1306 for( sal_Int16 i
=0; i
<nbOfCollationOptions
; i
++ )
1308 of
.writeParameter("collationOption", pCollationOptions
->getChildAt( i
)->getValue(), i
);
1311 of
.writeAsciiString("static const sal_Int16 nbOfCollationOptions = ");
1312 of
.writeInt( nbOfCollationOptions
);
1313 of
.writeAsciiString(";\n\n");
1316 of
.writeAsciiString("static const sal_Int16 nbOfCollations = ");
1317 of
.writeInt(nbOfCollations
);
1318 of
.writeAsciiString(";\n\n");
1320 of
.writeAsciiString("\nstatic const sal_Unicode* LCCollatorArray[] = {\n");
1321 for(j
= 0; j
< nbOfCollations
; j
++) {
1322 of
.writeAsciiString("\tCollatorID");
1324 of
.writeAsciiString(",\n");
1326 of
.writeAsciiString("\tdefaultCollator");
1328 of
.writeAsciiString(",\n");
1330 of
.writeAsciiString("\tCollatorRule");
1332 of
.writeAsciiString(",\n");
1334 of
.writeAsciiString("};\n\n");
1336 of
.writeAsciiString("static const sal_Unicode* collationOptions[] = {");
1337 for( j
=0; j
<nbOfCollationOptions
; j
++ )
1339 of
.writeAsciiString( "collationOption" );
1341 of
.writeAsciiString( ", " );
1343 of
.writeAsciiString("NULL };\n");
1344 of
.writeFunction("getCollatorImplementation_", "nbOfCollations", "LCCollatorArray");
1345 of
.writeFunction("getCollationOptions_", "nbOfCollationOptions", "collationOptions");
1348 void LCSearchNode::generateCode (const OFileWriter
&of
) const
1350 ::rtl::OUString useLocale
= getAttr().getValueByName("ref");
1351 if (!useLocale
.isEmpty()) {
1352 of
.writeRefFunction("getSearchOptions_", useLocale
);
1356 if( getNumberOfChildren() != 1 )
1360 stderr
, "Error: LC_SEARCH: more than 1 child: %ld\n",
1361 sal::static_int_cast
< long >(getNumberOfChildren()));
1364 LocaleNode
* pSearchOptions
= getChildAt( 0 );
1365 sal_Int32 nSearchOptions
= pSearchOptions
->getNumberOfChildren();
1366 for( i
=0; i
<nSearchOptions
; i
++ )
1368 of
.writeParameter("searchOption", pSearchOptions
->getChildAt( i
)->getValue(), sal::static_int_cast
<sal_Int16
>(i
) );
1371 of
.writeAsciiString("static const sal_Int16 nbOfSearchOptions = ");
1372 of
.writeInt( sal::static_int_cast
<sal_Int16
>( nSearchOptions
) );
1373 of
.writeAsciiString(";\n\n");
1375 of
.writeAsciiString("static const sal_Unicode* searchOptions[] = {");
1376 for( i
=0; i
<nSearchOptions
; i
++ )
1378 of
.writeAsciiString( "searchOption" );
1379 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
1380 of
.writeAsciiString( ", " );
1382 of
.writeAsciiString("NULL };\n");
1383 of
.writeFunction("getSearchOptions_", "nbOfSearchOptions", "searchOptions");
1386 void LCIndexNode::generateCode (const OFileWriter
&of
) const
1388 ::rtl::OUString useLocale
= getAttr().getValueByName("ref");
1389 if (!useLocale
.isEmpty()) {
1390 of
.writeRefFunction("getIndexAlgorithm_", useLocale
);
1391 of
.writeRefFunction("getUnicodeScripts_", useLocale
);
1392 of
.writeRefFunction("getFollowPageWords_", useLocale
);
1395 sal_Int16 nbOfIndexs
= 0;
1396 sal_Int16 nbOfUnicodeScripts
= 0;
1397 sal_Int16 nbOfPageWords
= 0;
1399 for (i
= 0; i
< getNumberOfChildren();i
++) {
1400 LocaleNode
* currNode
= getChildAt (i
);
1401 if( currNode
->getName().compareToAscii("IndexKey") == 0 )
1403 ::rtl::OUString str
;
1404 str
= currNode
->getAttr().getValueByName("unoid");
1405 of
.writeParameter("IndexID", str
, nbOfIndexs
);
1406 str
= currNode
->getAttr().getValueByName("module");
1407 of
.writeParameter("IndexModule", str
, nbOfIndexs
);
1408 str
= currNode
->getValue();
1409 of
.writeParameter("IndexKey", str
, nbOfIndexs
);
1410 str
= currNode
-> getAttr().getValueByName("default");
1411 of
.writeDefaultParameter("Index", str
, nbOfIndexs
);
1412 str
= currNode
-> getAttr().getValueByName("phonetic");
1413 of
.writeDefaultParameter("Phonetic", str
, nbOfIndexs
);
1414 of
.writeAsciiString("\n");
1418 if( currNode
->getName().compareToAscii("UnicodeScript") == 0 )
1420 of
.writeParameter("unicodeScript", currNode
->getValue(), nbOfUnicodeScripts
);
1421 nbOfUnicodeScripts
++;
1424 if( currNode
->getName().compareToAscii("FollowPageWord") == 0 )
1426 of
.writeParameter("followPageWord", currNode
->getValue(), nbOfPageWords
);
1430 of
.writeAsciiString("static const sal_Int16 nbOfIndexs = ");
1431 of
.writeInt(nbOfIndexs
);
1432 of
.writeAsciiString(";\n\n");
1434 of
.writeAsciiString("\nstatic const sal_Unicode* IndexArray[] = {\n");
1435 for(i
= 0; i
< nbOfIndexs
; i
++) {
1436 of
.writeAsciiString("\tIndexID");
1438 of
.writeAsciiString(",\n");
1440 of
.writeAsciiString("\tIndexModule");
1442 of
.writeAsciiString(",\n");
1444 of
.writeAsciiString("\tIndexKey");
1446 of
.writeAsciiString(",\n");
1448 of
.writeAsciiString("\tdefaultIndex");
1450 of
.writeAsciiString(",\n");
1452 of
.writeAsciiString("\tdefaultPhonetic");
1454 of
.writeAsciiString(",\n");
1456 of
.writeAsciiString("};\n\n");
1458 of
.writeAsciiString("static const sal_Int16 nbOfUnicodeScripts = ");
1459 of
.writeInt( nbOfUnicodeScripts
);
1460 of
.writeAsciiString(";\n\n");
1462 of
.writeAsciiString("static const sal_Unicode* UnicodeScriptArray[] = {");
1463 for( i
=0; i
<nbOfUnicodeScripts
; i
++ )
1465 of
.writeAsciiString( "unicodeScript" );
1467 of
.writeAsciiString( ", " );
1469 of
.writeAsciiString("NULL };\n\n");
1471 of
.writeAsciiString("static const sal_Int16 nbOfPageWords = ");
1472 of
.writeInt(nbOfPageWords
);
1473 of
.writeAsciiString(";\n\n");
1475 of
.writeAsciiString("static const sal_Unicode* FollowPageWordArray[] = {\n");
1476 for(i
= 0; i
< nbOfPageWords
; i
++) {
1477 of
.writeAsciiString("\tfollowPageWord");
1479 of
.writeAsciiString(",\n");
1481 of
.writeAsciiString("\tNULL\n};\n\n");
1483 of
.writeFunction("getIndexAlgorithm_", "nbOfIndexs", "IndexArray");
1484 of
.writeFunction("getUnicodeScripts_", "nbOfUnicodeScripts", "UnicodeScriptArray");
1485 of
.writeFunction("getFollowPageWords_", "nbOfPageWords", "FollowPageWordArray");
1489 static void lcl_writeAbbrFullNarrNames( const OFileWriter
& of
, const LocaleNode
* currNode
,
1490 const sal_Char
* elementTag
, sal_Int16 i
, sal_Int16 j
)
1492 OUString aAbbrName
= currNode
->getChildAt(1)->getValue();
1493 OUString aFullName
= currNode
->getChildAt(2)->getValue();
1495 LocaleNode
* p
= (currNode
->getNumberOfChildren() > 3 ? currNode
->getChildAt(3) : 0);
1496 if ( p
&& p
->getName() == "DefaultNarrowName" )
1497 aNarrName
= p
->getValue();
1500 sal_Int32 nIndex
= 0;
1501 sal_uInt32 nChar
= aFullName
.iterateCodePoints( &nIndex
);
1502 aNarrName
= OUString( &nChar
, 1);
1504 of
.writeParameter( elementTag
, "DefaultAbbrvName", aAbbrName
, i
, j
);
1505 of
.writeParameter( elementTag
, "DefaultFullName", aFullName
, i
, j
);
1506 of
.writeParameter( elementTag
, "DefaultNarrowName", aNarrName
, i
, j
);
1509 static void lcl_writeTabTagString( const OFileWriter
& of
, const sal_Char
* pTag
, const sal_Char
* pStr
)
1511 of
.writeAsciiString("\t");
1512 of
.writeAsciiString( pTag
);
1513 of
.writeAsciiString( pStr
);
1516 static void lcl_writeTabTagStringNums( const OFileWriter
& of
,
1517 const sal_Char
* pTag
, const sal_Char
* pStr
, sal_Int16 i
, sal_Int16 j
)
1519 lcl_writeTabTagString( of
, pTag
, pStr
);
1520 of
.writeInt(i
); of
.writeInt(j
); of
.writeAsciiString(",\n");
1523 static void lcl_writeAbbrFullNarrArrays( const OFileWriter
& of
, sal_Int16 nCount
,
1524 const sal_Char
* elementTag
, sal_Int16 i
, bool bNarrow
)
1528 lcl_writeTabTagString( of
, elementTag
, "Ref");
1529 of
.writeInt(i
); of
.writeAsciiString(",\n");
1530 lcl_writeTabTagString( of
, elementTag
, "RefName");
1531 of
.writeInt(i
); of
.writeAsciiString(",\n");
1535 for (sal_Int16 j
= 0; j
< nCount
; j
++)
1537 lcl_writeTabTagStringNums( of
, elementTag
, "ID", i
, j
);
1538 lcl_writeTabTagStringNums( of
, elementTag
, "DefaultAbbrvName", i
, j
);
1539 lcl_writeTabTagStringNums( of
, elementTag
, "DefaultFullName", i
, j
);
1541 lcl_writeTabTagStringNums( of
, elementTag
, "DefaultNarrowName", i
, j
);
1546 void LCCalendarNode::generateCode (const OFileWriter
&of
) const
1548 ::rtl::OUString useLocale
= getAttr().getValueByName("ref");
1549 if (!useLocale
.isEmpty()) {
1550 of
.writeRefFunction("getAllCalendars_", useLocale
);
1553 sal_Int16 nbOfCalendars
= sal::static_int_cast
<sal_Int16
>( getNumberOfChildren() );
1554 ::rtl::OUString str
;
1555 sal_Int16
* nbOfDays
= new sal_Int16
[nbOfCalendars
];
1556 sal_Int16
* nbOfMonths
= new sal_Int16
[nbOfCalendars
];
1557 sal_Int16
* nbOfGenitiveMonths
= new sal_Int16
[nbOfCalendars
];
1558 sal_Int16
* nbOfPartitiveMonths
= new sal_Int16
[nbOfCalendars
];
1559 sal_Int16
* nbOfEras
= new sal_Int16
[nbOfCalendars
];
1562 bool bHasGregorian
= false;
1565 for ( i
= 0; i
< nbOfCalendars
; i
++) {
1566 LocaleNode
* calNode
= getChildAt (i
);
1567 OUString calendarID
= calNode
-> getAttr().getValueByName("unoid");
1568 of
.writeParameter( "calendarID", calendarID
, i
);
1569 bool bGregorian
= calendarID
== "gregorian";
1571 bHasGregorian
= bGregorian
;
1572 str
= calNode
-> getAttr().getValueByName("default");
1573 of
.writeDefaultParameter("Calendar", str
, i
);
1575 sal_Int16 nChild
= 0;
1577 // Generate Days of Week
1578 const sal_Char
*elementTag
;
1579 LocaleNode
* daysNode
= NULL
;
1580 ::rtl::OUString ref_name
= calNode
->getChildAt(nChild
)->getAttr().getValueByName("ref");
1581 if (!ref_name
.isEmpty() && i
> 0) {
1582 for (j
= 0; j
< i
; j
++) {
1583 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1584 if (str
.equals(ref_name
))
1585 daysNode
= getChildAt(j
)->getChildAt(0);
1588 if (!ref_name
.isEmpty() && daysNode
== NULL
) {
1589 of
.writeParameter("dayRef", OUString("ref"), i
);
1590 of
.writeParameter("dayRefName", ref_name
, i
);
1593 if (daysNode
== NULL
)
1594 daysNode
= calNode
-> getChildAt(nChild
);
1595 nbOfDays
[i
] = sal::static_int_cast
<sal_Int16
>( daysNode
->getNumberOfChildren() );
1596 if (bGregorian
&& nbOfDays
[i
] != 7)
1597 incErrorInt( "A Gregorian calendar must have 7 days per week, this one has %d", nbOfDays
[i
]);
1599 for (j
= 0; j
< nbOfDays
[i
]; j
++) {
1600 LocaleNode
*currNode
= daysNode
-> getChildAt(j
);
1601 OUString
dayID( currNode
->getChildAt(0)->getValue());
1602 of
.writeParameter("dayID", dayID
, i
, j
);
1603 if ( j
== 0 && bGregorian
&& dayID
!= "sun" )
1604 incError( "First day of a week of a Gregorian calendar must be <DayID>sun</DayID>");
1605 lcl_writeAbbrFullNarrNames( of
, currNode
, elementTag
, i
, j
);
1610 // Generate Months of Year
1611 LocaleNode
* monthsNode
= NULL
;
1612 ref_name
= calNode
->getChildAt(nChild
)->getAttr().getValueByName("ref");
1613 if (!ref_name
.isEmpty() && i
> 0) {
1614 for (j
= 0; j
< i
; j
++) {
1615 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1616 if (str
.equals(ref_name
))
1617 monthsNode
= getChildAt(j
)->getChildAt(1);
1620 if (!ref_name
.isEmpty() && monthsNode
== NULL
) {
1621 of
.writeParameter("monthRef", OUString("ref"), i
);
1622 of
.writeParameter("monthRefName", ref_name
, i
);
1625 if (monthsNode
== NULL
)
1626 monthsNode
= calNode
-> getChildAt(nChild
);
1627 nbOfMonths
[i
] = sal::static_int_cast
<sal_Int16
>( monthsNode
->getNumberOfChildren() );
1628 if (bGregorian
&& nbOfMonths
[i
] != 12)
1629 incErrorInt( "A Gregorian calendar must have 12 months, this one has %d", nbOfMonths
[i
]);
1630 elementTag
= "month";
1631 for (j
= 0; j
< nbOfMonths
[i
]; j
++) {
1632 LocaleNode
*currNode
= monthsNode
-> getChildAt(j
);
1633 OUString
monthID( currNode
->getChildAt(0)->getValue());
1634 of
.writeParameter("monthID", monthID
, i
, j
);
1635 if ( j
== 0 && bGregorian
&& monthID
!= "jan" )
1636 incError( "First month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1637 lcl_writeAbbrFullNarrNames( of
, currNode
, elementTag
, i
, j
);
1642 // Generate genitive Months of Year
1643 // Optional, if not present fall back to month nouns.
1644 if ( calNode
->getChildAt(nChild
)->getName() != "GenitiveMonths" )
1646 LocaleNode
* genitiveMonthsNode
= NULL
;
1647 ref_name
= calNode
->getChildAt(nChild
)->getAttr().getValueByName("ref");
1648 if (!ref_name
.isEmpty() && i
> 0) {
1649 for (j
= 0; j
< i
; j
++) {
1650 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1651 if (str
.equals(ref_name
))
1652 genitiveMonthsNode
= getChildAt(j
)->getChildAt(1);
1655 if (!ref_name
.isEmpty() && genitiveMonthsNode
== NULL
) {
1656 of
.writeParameter("genitiveMonthRef", OUString("ref"), i
);
1657 of
.writeParameter("genitiveMonthRefName", ref_name
, i
);
1658 nbOfGenitiveMonths
[i
] = 0;
1660 if (genitiveMonthsNode
== NULL
)
1661 genitiveMonthsNode
= calNode
-> getChildAt(nChild
);
1662 nbOfGenitiveMonths
[i
] = sal::static_int_cast
<sal_Int16
>( genitiveMonthsNode
->getNumberOfChildren() );
1663 if (bGregorian
&& nbOfGenitiveMonths
[i
] != 12)
1664 incErrorInt( "A Gregorian calendar must have 12 genitive months, this one has %d", nbOfGenitiveMonths
[i
]);
1665 elementTag
= "genitiveMonth";
1666 for (j
= 0; j
< nbOfGenitiveMonths
[i
]; j
++) {
1667 LocaleNode
*currNode
= genitiveMonthsNode
-> getChildAt(j
);
1668 OUString
genitiveMonthID( currNode
->getChildAt(0)->getValue());
1669 of
.writeParameter("genitiveMonthID", genitiveMonthID
, i
, j
);
1670 if ( j
== 0 && bGregorian
&& genitiveMonthID
!= "jan" )
1671 incError( "First genitive month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1672 lcl_writeAbbrFullNarrNames( of
, currNode
, elementTag
, i
, j
);
1677 // Generate partitive Months of Year
1678 // Optional, if not present fall back to genitive months, or nominative
1679 // months (nouns) if that isn't present either.
1680 if ( calNode
->getChildAt(nChild
)->getName() != "PartitiveMonths" )
1682 LocaleNode
* partitiveMonthsNode
= NULL
;
1683 ref_name
= calNode
->getChildAt(nChild
)->getAttr().getValueByName("ref");
1684 if (!ref_name
.isEmpty() && i
> 0) {
1685 for (j
= 0; j
< i
; j
++) {
1686 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1687 if (str
.equals(ref_name
))
1688 partitiveMonthsNode
= getChildAt(j
)->getChildAt(1);
1691 if (!ref_name
.isEmpty() && partitiveMonthsNode
== NULL
) {
1692 of
.writeParameter("partitiveMonthRef", OUString("ref"), i
);
1693 of
.writeParameter("partitiveMonthRefName", ref_name
, i
);
1694 nbOfPartitiveMonths
[i
] = 0;
1696 if (partitiveMonthsNode
== NULL
)
1697 partitiveMonthsNode
= calNode
-> getChildAt(nChild
);
1698 nbOfPartitiveMonths
[i
] = sal::static_int_cast
<sal_Int16
>( partitiveMonthsNode
->getNumberOfChildren() );
1699 if (bGregorian
&& nbOfPartitiveMonths
[i
] != 12)
1700 incErrorInt( "A Gregorian calendar must have 12 partitive months, this one has %d", nbOfPartitiveMonths
[i
]);
1701 elementTag
= "partitiveMonth";
1702 for (j
= 0; j
< nbOfPartitiveMonths
[i
]; j
++) {
1703 LocaleNode
*currNode
= partitiveMonthsNode
-> getChildAt(j
);
1704 OUString
partitiveMonthID( currNode
->getChildAt(0)->getValue());
1705 of
.writeParameter("partitiveMonthID", partitiveMonthID
, i
, j
);
1706 if ( j
== 0 && bGregorian
&& partitiveMonthID
!= "jan" )
1707 incError( "First partitive month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1708 lcl_writeAbbrFullNarrNames( of
, currNode
, elementTag
, i
, j
);
1713 // Generate Era name
1714 LocaleNode
* erasNode
= NULL
;
1715 ref_name
= calNode
-> getChildAt(nChild
) ->getAttr().getValueByName("ref");
1716 if (!ref_name
.isEmpty() && i
> 0) {
1717 for (j
= 0; j
< i
; j
++) {
1718 str
= getChildAt(j
)->getAttr().getValueByName("unoid");
1719 if (str
.equals(ref_name
))
1720 erasNode
= getChildAt(j
)->getChildAt(2);
1723 if (!ref_name
.isEmpty() && erasNode
== NULL
) {
1724 of
.writeParameter("eraRef", OUString("ref"), i
);
1725 of
.writeParameter("eraRefName", ref_name
, i
);
1728 if (erasNode
== NULL
)
1729 erasNode
= calNode
-> getChildAt(nChild
);
1730 nbOfEras
[i
] = sal::static_int_cast
<sal_Int16
>( erasNode
->getNumberOfChildren() );
1731 if (bGregorian
&& nbOfEras
[i
] != 2)
1732 incErrorInt( "A Gregorian calendar must have 2 eras, this one has %d", nbOfEras
[i
]);
1734 for (j
= 0; j
< nbOfEras
[i
]; j
++) {
1735 LocaleNode
*currNode
= erasNode
-> getChildAt(j
);
1736 OUString
eraID( currNode
->getChildAt(0)->getValue());
1737 of
.writeParameter("eraID", eraID
, i
, j
);
1738 if ( j
== 0 && bGregorian
&& eraID
!= "bc" )
1739 incError( "First era of a Gregorian calendar must be <EraID>bc</EraID>");
1740 if ( j
== 1 && bGregorian
&& eraID
!= "ad" )
1741 incError( "Second era of a Gregorian calendar must be <EraID>ad</EraID>");
1742 of
.writeAsciiString("\n");
1743 of
.writeParameter(elementTag
, "DefaultAbbrvName",currNode
->getChildAt(1)->getValue() ,i
, j
);
1744 of
.writeParameter(elementTag
, "DefaultFullName",currNode
->getChildAt(2)->getValue() , i
, j
);
1749 str
= calNode
->getChildAt(nChild
)->getChildAt(0)->getValue();
1752 for (j
= 0; j
< nbOfDays
[i
]; j
++)
1754 LocaleNode
*currNode
= daysNode
->getChildAt(j
);
1755 OUString
dayID( currNode
->getChildAt(0)->getValue());
1759 if (j
>= nbOfDays
[i
])
1760 incErrorStr( "<StartDayOfWeek> <DayID> must be one of the <DaysOfWeek>, but is", str
);
1762 of
.writeParameter("startDayOfWeek", str
, i
);
1765 str
= calNode
->getChildAt(nChild
)-> getValue();
1766 sal_Int16 nDays
= sal::static_int_cast
<sal_Int16
>( str
.toInt32() );
1767 if (nDays
< 1 || (0 < nbOfDays
[i
] && nbOfDays
[i
] < nDays
))
1768 incErrorInt( "Bad value of MinimalDaysInFirstWeek: %d, must be 1 <= value <= days_in_week", nDays
);
1769 of
.writeIntParameter("minimalDaysInFirstWeek", i
, nDays
);
1772 fprintf( stderr
, "Warning: %s\n", "No Gregorian calendar defined, are you sure?");
1774 of
.writeAsciiString("static const sal_Int16 calendarsCount = ");
1775 of
.writeInt(nbOfCalendars
);
1776 of
.writeAsciiString(";\n\n");
1778 of
.writeAsciiString("static const sal_Unicode nbOfDays[] = {");
1779 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1780 of
.writeInt(nbOfDays
[i
]);
1781 of
.writeAsciiString(", ");
1783 of
.writeInt(nbOfDays
[i
]);
1784 of
.writeAsciiString("};\n");
1786 of
.writeAsciiString("static const sal_Unicode nbOfMonths[] = {");
1787 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1788 of
.writeInt(nbOfMonths
[i
]);
1789 of
.writeAsciiString(", ");
1791 of
.writeInt(nbOfMonths
[i
]);
1792 of
.writeAsciiString("};\n");
1794 of
.writeAsciiString("static const sal_Unicode nbOfGenitiveMonths[] = {");
1795 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1796 of
.writeInt(nbOfGenitiveMonths
[i
]);
1797 of
.writeAsciiString(", ");
1799 of
.writeInt(nbOfGenitiveMonths
[i
]);
1800 of
.writeAsciiString("};\n");
1802 of
.writeAsciiString("static const sal_Unicode nbOfPartitiveMonths[] = {");
1803 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1804 of
.writeInt(nbOfPartitiveMonths
[i
]);
1805 of
.writeAsciiString(", ");
1807 of
.writeInt(nbOfPartitiveMonths
[i
]);
1808 of
.writeAsciiString("};\n");
1810 of
.writeAsciiString("static const sal_Unicode nbOfEras[] = {");
1811 for(i
= 0; i
< nbOfCalendars
- 1; i
++) {
1812 of
.writeInt(nbOfEras
[i
]);
1813 of
.writeAsciiString(", ");
1815 of
.writeInt(nbOfEras
[i
]);
1816 of
.writeAsciiString("};\n");
1819 of
.writeAsciiString("static const sal_Unicode* calendars[] = {\n");
1820 of
.writeAsciiString("\tnbOfDays,\n");
1821 of
.writeAsciiString("\tnbOfMonths,\n");
1822 of
.writeAsciiString("\tnbOfGenitiveMonths,\n");
1823 of
.writeAsciiString("\tnbOfPartitiveMonths,\n");
1824 of
.writeAsciiString("\tnbOfEras,\n");
1825 for(i
= 0; i
< nbOfCalendars
; i
++) {
1826 of
.writeAsciiString("\tcalendarID");
1828 of
.writeAsciiString(",\n");
1829 of
.writeAsciiString("\tdefaultCalendar");
1831 of
.writeAsciiString(",\n");
1832 lcl_writeAbbrFullNarrArrays( of
, nbOfDays
[i
], "day", i
, true);
1833 lcl_writeAbbrFullNarrArrays( of
, nbOfMonths
[i
], "month", i
, true);
1834 lcl_writeAbbrFullNarrArrays( of
, nbOfGenitiveMonths
[i
], "genitiveMonth", i
, true);
1835 lcl_writeAbbrFullNarrArrays( of
, nbOfPartitiveMonths
[i
], "partitiveMonth", i
, true);
1836 lcl_writeAbbrFullNarrArrays( of
, nbOfEras
[i
], "era", i
, false /*noNarrow*/);
1837 of
.writeAsciiString("\tstartDayOfWeek");of
.writeInt(i
); of
.writeAsciiString(",\n");
1838 of
.writeAsciiString("\tminimalDaysInFirstWeek");of
.writeInt(i
); of
.writeAsciiString(",\n");
1841 of
.writeAsciiString("};\n\n");
1842 of
.writeFunction("getAllCalendars_", "calendarsCount", "calendars");
1845 delete []nbOfMonths
;
1846 delete []nbOfGenitiveMonths
;
1847 delete []nbOfPartitiveMonths
;
1851 bool isIso4217( const OUString
& rStr
)
1853 const sal_Unicode
* p
= rStr
.getStr();
1854 return rStr
.getLength() == 3
1855 && 'A' <= p
[0] && p
[0] <= 'Z'
1856 && 'A' <= p
[1] && p
[1] <= 'Z'
1857 && 'A' <= p
[2] && p
[2] <= 'Z'
1861 void LCCurrencyNode :: generateCode (const OFileWriter
&of
) const
1863 ::rtl::OUString useLocale
= getAttr().getValueByName("ref");
1864 if (!useLocale
.isEmpty()) {
1865 of
.writeRefFunction("getAllCurrencies_", useLocale
);
1868 sal_Int16 nbOfCurrencies
= 0;
1869 ::rtl::OUString str
;
1872 bool bTheDefault
= false;
1873 bool bTheCompatible
= false;
1874 for ( i
= 0; i
< getNumberOfChildren(); i
++,nbOfCurrencies
++) {
1875 LocaleNode
* currencyNode
= getChildAt (i
);
1876 str
= currencyNode
->getAttr().getValueByName("default");
1877 bool bDefault
= of
.writeDefaultParameter("Currency", str
, nbOfCurrencies
);
1878 str
= currencyNode
->getAttr().getValueByName("usedInCompatibleFormatCodes");
1879 bool bCompatible
= of
.writeDefaultParameter("CurrencyUsedInCompatibleFormatCodes", str
, nbOfCurrencies
);
1880 str
= currencyNode
->getAttr().getValueByName("legacyOnly");
1881 bool bLegacy
= of
.writeDefaultParameter("CurrencyLegacyOnly", str
, nbOfCurrencies
);
1882 if (bLegacy
&& (bDefault
|| bCompatible
))
1883 incError( "Currency: if legacyOnly==true, both 'default' and 'usedInCompatibleFormatCodes' must be false.");
1887 incError( "Currency: more than one default currency.");
1893 incError( "Currency: more than one currency flagged as usedInCompatibleFormatCodes.");
1894 bTheCompatible
= true;
1896 str
= currencyNode
-> findNode ("CurrencyID") -> getValue();
1897 of
.writeParameter("currencyID", str
, nbOfCurrencies
);
1898 // CurrencyID MUST be ISO 4217.
1899 if (!bLegacy
&& !isIso4217(str
))
1900 incError( "CurrencyID is not ISO 4217");
1901 str
= currencyNode
-> findNode ("CurrencySymbol") -> getValue();
1902 of
.writeParameter("currencySymbol", str
, nbOfCurrencies
);
1903 // Check if this currency really is the one used in number format
1904 // codes. In case of ref=... mechanisms it may be that TheCurrency
1905 // couldn't had been determined from the current locale (i.e. is
1906 // empty), silently assume the referred locale has things right.
1907 if (bCompatible
&& !sTheCompatibleCurrency
.isEmpty() && sTheCompatibleCurrency
!= str
)
1908 incErrorStrStr( "CurrencySymbol \"%s\" flagged as usedInCompatibleFormatCodes doesn't match \"%s\" determined from format codes.", str
, sTheCompatibleCurrency
);
1909 str
= currencyNode
-> findNode ("BankSymbol") -> getValue();
1910 of
.writeParameter("bankSymbol", str
, nbOfCurrencies
);
1911 // BankSymbol currently must be ISO 4217. May change later if
1912 // application always uses CurrencyID instead of BankSymbol.
1913 if (!bLegacy
&& !isIso4217(str
))
1914 incError( "BankSymbol is not ISO 4217");
1915 str
= currencyNode
-> findNode ("CurrencyName") -> getValue();
1916 of
.writeParameter("currencyName", str
, nbOfCurrencies
);
1917 str
= currencyNode
-> findNode ("DecimalPlaces") -> getValue();
1918 sal_Int16 nDecimalPlaces
= (sal_Int16
)str
.toInt32();
1919 of
.writeIntParameter("currencyDecimalPlaces", nbOfCurrencies
, nDecimalPlaces
);
1920 of
.writeAsciiString("\n");
1924 incError( "Currency: no default currency.");
1925 if (!bTheCompatible
)
1926 incError( "Currency: no currency flagged as usedInCompatibleFormatCodes.");
1928 of
.writeAsciiString("static const sal_Int16 currencyCount = ");
1929 of
.writeInt(nbOfCurrencies
);
1930 of
.writeAsciiString(";\n\n");
1931 of
.writeAsciiString("static const sal_Unicode* currencies[] = {\n");
1932 for(i
= 0; i
< nbOfCurrencies
; i
++) {
1933 of
.writeAsciiString("\tcurrencyID");
1935 of
.writeAsciiString(",\n");
1936 of
.writeAsciiString("\tcurrencySymbol");
1938 of
.writeAsciiString(",\n");
1939 of
.writeAsciiString("\tbankSymbol");
1941 of
.writeAsciiString(",\n");
1942 of
.writeAsciiString("\tcurrencyName");
1944 of
.writeAsciiString(",\n");
1945 of
.writeAsciiString("\tdefaultCurrency");
1947 of
.writeAsciiString(",\n");
1948 of
.writeAsciiString("\tdefaultCurrencyUsedInCompatibleFormatCodes");
1950 of
.writeAsciiString(",\n");
1951 of
.writeAsciiString("\tcurrencyDecimalPlaces");
1953 of
.writeAsciiString(",\n");
1954 of
.writeAsciiString("\tdefaultCurrencyLegacyOnly");
1956 of
.writeAsciiString(",\n");
1958 of
.writeAsciiString("};\n\n");
1959 of
.writeFunction("getAllCurrencies_", "currencyCount", "currencies");
1962 void LCTransliterationNode::generateCode (const OFileWriter
&of
) const
1964 ::rtl::OUString useLocale
= getAttr().getValueByName("ref");
1965 if (!useLocale
.isEmpty()) {
1966 of
.writeRefFunction("getTransliterations_", useLocale
);
1969 sal_Int16 nbOfModules
= 0;
1970 ::rtl::OUString str
;
1973 for ( i
= 0; i
< getNumberOfChildren(); i
++,nbOfModules
++) {
1974 LocaleNode
* transNode
= getChildAt (i
);
1975 str
= transNode
->getAttr().getValueByIndex(0);
1976 of
.writeParameter("Transliteration", str
, nbOfModules
);
1978 of
.writeAsciiString("static const sal_Int16 nbOfTransliterations = ");
1979 of
.writeInt(nbOfModules
);
1980 of
.writeAsciiString(";\n\n");
1982 of
.writeAsciiString("\nstatic const sal_Unicode* LCTransliterationsArray[] = {\n");
1983 for( i
= 0; i
< nbOfModules
; i
++) {
1984 of
.writeAsciiString("\tTransliteration");
1986 of
.writeAsciiString(",\n");
1988 of
.writeAsciiString("};\n\n");
1989 of
.writeFunction("getTransliterations_", "nbOfTransliterations", "LCTransliterationsArray");
1992 struct NameValuePair
{
1993 const sal_Char
*name
;
1994 const sal_Char
*value
;
1996 static NameValuePair ReserveWord
[] = {
1997 { "trueWord", "true" },
1998 { "falseWord", "false" },
1999 { "quarter1Word", "1st quarter" },
2000 { "quarter2Word", "2nd quarter" },
2001 { "quarter3Word", "3rd quarter" },
2002 { "quarter4Word", "4th quarter" },
2003 { "aboveWord", "above" },
2004 { "belowWord", "below" },
2005 { "quarter1Abbreviation", "Q1" },
2006 { "quarter2Abbreviation", "Q2" },
2007 { "quarter3Abbreviation", "Q3" },
2008 { "quarter4Abbreviation", "Q4" }
2011 void LCMiscNode::generateCode (const OFileWriter
&of
) const
2013 ::rtl::OUString useLocale
= getAttr().getValueByName("ref");
2014 if (!useLocale
.isEmpty()) {
2015 of
.writeRefFunction("getForbiddenCharacters_", useLocale
);
2016 of
.writeRefFunction("getBreakIteratorRules_", useLocale
);
2017 of
.writeRefFunction("getReservedWords_", useLocale
);
2020 const LocaleNode
* reserveNode
= findNode("ReservedWords");
2022 incError( "No ReservedWords element."); // should not happen if validated..
2023 const LocaleNode
* forbidNode
= findNode("ForbiddenCharacters");
2024 const LocaleNode
* breakNode
= findNode("BreakIteratorRules");
2026 bool bEnglishLocale
= (strncmp( of
.getLocale(), "en_", 3) == 0);
2028 sal_Int16 nbOfWords
= 0;
2029 ::rtl::OUString str
;
2032 for ( i
= 0; i
< sal_Int16(SAL_N_ELEMENTS(ReserveWord
)); i
++,nbOfWords
++) {
2033 const LocaleNode
* curNode
= (reserveNode
? reserveNode
->findNode(
2034 ReserveWord
[i
].name
) : 0);
2037 "Warning: No %s in ReservedWords, using en_US default: \"%s\".\n",
2038 ReserveWord
[i
].name
, ReserveWord
[i
].value
);
2039 str
= curNode
? curNode
-> getValue() : OUString::createFromAscii(ReserveWord
[i
].value
);
2043 fprintf( stderr
, "Error: No content for ReservedWords %s.\n", ReserveWord
[i
].name
);
2045 of
.writeParameter("ReservedWord", str
, nbOfWords
);
2046 // "true", ..., "below" trigger untranslated warning.
2047 if (!bEnglishLocale
&& curNode
&& (0 <= i
&& i
<= 7) &&
2048 str
.equalsIgnoreAsciiCaseAscii( ReserveWord
[i
].value
))
2051 "Warning: ReservedWord %s seems to be untranslated \"%s\".\n",
2052 ReserveWord
[i
].name
, ReserveWord
[i
].value
);
2055 of
.writeAsciiString("static const sal_Int16 nbOfReservedWords = ");
2056 of
.writeInt(nbOfWords
);
2057 of
.writeAsciiString(";\n\n");
2058 of
.writeAsciiString("\nstatic const sal_Unicode* LCReservedWordsArray[] = {\n");
2059 for( i
= 0; i
< nbOfWords
; i
++) {
2060 of
.writeAsciiString("\tReservedWord");
2062 of
.writeAsciiString(",\n");
2064 of
.writeAsciiString("};\n\n");
2065 of
.writeFunction("getReservedWords_", "nbOfReservedWords", "LCReservedWordsArray");
2068 of
.writeParameter( "forbiddenBegin", forbidNode
-> getChildAt(0)->getValue());
2069 of
.writeParameter( "forbiddenEnd", forbidNode
-> getChildAt(1)->getValue());
2070 of
.writeParameter( "hangingChars", forbidNode
-> getChildAt(2)->getValue());
2072 of
.writeParameter( "forbiddenBegin", ::rtl::OUString());
2073 of
.writeParameter( "forbiddenEnd", ::rtl::OUString());
2074 of
.writeParameter( "hangingChars", ::rtl::OUString());
2076 of
.writeAsciiString("\nstatic const sal_Unicode* LCForbiddenCharactersArray[] = {\n");
2077 of
.writeAsciiString("\tforbiddenBegin,\n");
2078 of
.writeAsciiString("\tforbiddenEnd,\n");
2079 of
.writeAsciiString("\thangingChars\n");
2080 of
.writeAsciiString("};\n\n");
2081 of
.writeFunction("getForbiddenCharacters_", "3", "LCForbiddenCharactersArray");
2084 of
.writeParameter( "EditMode", breakNode
-> getChildAt(0)->getValue());
2085 of
.writeParameter( "DictionaryMode", breakNode
-> getChildAt(1)->getValue());
2086 of
.writeParameter( "WordCountMode", breakNode
-> getChildAt(2)->getValue());
2087 of
.writeParameter( "CharacterMode", breakNode
-> getChildAt(3)->getValue());
2088 of
.writeParameter( "LineMode", breakNode
-> getChildAt(4)->getValue());
2090 of
.writeParameter( "EditMode", ::rtl::OUString());
2091 of
.writeParameter( "DictionaryMode", ::rtl::OUString());
2092 of
.writeParameter( "WordCountMode", ::rtl::OUString());
2093 of
.writeParameter( "CharacterMode", ::rtl::OUString());
2094 of
.writeParameter( "LineMode", ::rtl::OUString());
2096 of
.writeAsciiString("\nstatic const sal_Unicode* LCBreakIteratorRulesArray[] = {\n");
2097 of
.writeAsciiString("\tEditMode,\n");
2098 of
.writeAsciiString("\tDictionaryMode,\n");
2099 of
.writeAsciiString("\tWordCountMode,\n");
2100 of
.writeAsciiString("\tCharacterMode,\n");
2101 of
.writeAsciiString("\tLineMode\n");
2102 of
.writeAsciiString("};\n\n");
2103 of
.writeFunction("getBreakIteratorRules_", "5", "LCBreakIteratorRulesArray");
2107 void LCNumberingLevelNode::generateCode (const OFileWriter
&of
) const
2109 of
.writeAsciiString("// ---> ContinuousNumbering\n");
2110 ::rtl::OUString useLocale
= getAttr().getValueByName("ref");
2111 if (!useLocale
.isEmpty()) {
2112 of
.writeRefFunction2("getContinuousNumberingLevels_", useLocale
);
2116 // hard code number of attributes per style.
2117 const int nAttributes
= 5;
2118 const char* attr
[ nAttributes
] = { "Prefix", "NumType", "Suffix", "Transliteration", "NatNum" };
2120 // record each attribute of each style in a static C++ variable.
2121 // determine number of styles on the fly.
2122 sal_Int32 nStyles
= getNumberOfChildren();
2125 for( i
= 0; i
< nStyles
; ++i
)
2127 const Attr
&q
= getChildAt( i
)->getAttr();
2128 for( sal_Int32 j
=0; j
<nAttributes
; ++j
)
2130 const char* name
= attr
[j
];
2131 OUString value
= q
.getValueByName( name
);
2132 of
.writeParameter("continuous", name
, value
, sal::static_int_cast
<sal_Int16
>(i
) );
2136 // record number of styles and attributes.
2137 of
.writeAsciiString("static const sal_Int16 continuousNbOfStyles = ");
2138 of
.writeInt( sal::static_int_cast
<sal_Int16
>( nStyles
) );
2139 of
.writeAsciiString(";\n\n");
2140 of
.writeAsciiString("static const sal_Int16 continuousNbOfAttributesPerStyle = ");
2141 of
.writeInt( nAttributes
);
2142 of
.writeAsciiString(";\n\n");
2144 // generate code. (intermediate arrays)
2145 for( i
=0; i
<nStyles
; i
++ )
2147 of
.writeAsciiString("\nstatic const sal_Unicode* continuousStyle" );
2148 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2149 of
.writeAsciiString("[] = {\n");
2150 for( sal_Int32 j
=0; j
<nAttributes
; j
++)
2152 of
.writeAsciiString("\t");
2153 of
.writeAsciiString( "continuous" );
2154 of
.writeAsciiString( attr
[j
] );
2155 of
.writeInt(sal::static_int_cast
<sal_Int16
>(i
));
2156 of
.writeAsciiString(",\n");
2158 of
.writeAsciiString("\t0\n};\n\n");
2161 // generate code. (top-level array)
2162 of
.writeAsciiString("\n");
2163 of
.writeAsciiString("static const sal_Unicode** LCContinuousNumberingLevelsArray[] = {\n" );
2164 for( i
=0; i
<nStyles
; i
++ )
2166 of
.writeAsciiString( "\t" );
2167 of
.writeAsciiString( "continuousStyle" );
2168 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2169 of
.writeAsciiString( ",\n");
2171 of
.writeAsciiString("\t0\n};\n\n");
2172 of
.writeFunction2("getContinuousNumberingLevels_", "continuousNbOfStyles",
2173 "continuousNbOfAttributesPerStyle", "LCContinuousNumberingLevelsArray");
2177 void LCOutlineNumberingLevelNode::generateCode (const OFileWriter
&of
) const
2179 of
.writeAsciiString("// ---> OutlineNumbering\n");
2180 ::rtl::OUString useLocale
= getAttr().getValueByName("ref");
2181 if (!useLocale
.isEmpty()) {
2182 of
.writeRefFunction3("getOutlineNumberingLevels_", useLocale
);
2186 // hardcode number of attributes per level
2187 const int nAttributes
= 11;
2188 const char* attr
[ nAttributes
] =
2197 "SymbolTextDistance",
2203 // record each attribute of each level of each style in a static C++ variable.
2204 // determine number of styles and number of levels per style on the fly.
2205 sal_Int32 nStyles
= getNumberOfChildren();
2206 vector
<sal_Int32
> nLevels
; // may be different for each style?
2207 for( sal_Int32 i
= 0; i
< nStyles
; i
++ )
2209 LocaleNode
* p
= getChildAt( i
);
2210 nLevels
.push_back( p
->getNumberOfChildren() );
2211 for( sal_Int32 j
=0; j
<nLevels
.back(); j
++ )
2213 const Attr
& q
= p
->getChildAt( j
)->getAttr();
2214 for( sal_Int32 k
=0; k
<nAttributes
; ++k
)
2216 const char* name
= attr
[k
];
2217 OUString value
= q
.getValueByName( name
);
2218 of
.writeParameter("outline", name
, value
,
2219 sal::static_int_cast
<sal_Int16
>(i
),
2220 sal::static_int_cast
<sal_Int16
>(j
) );
2225 // verify that each style has the same number of levels.
2226 for( size_t i
=0; i
<nLevels
.size(); i
++ )
2228 if( nLevels
[0] != nLevels
[i
] )
2230 incError( "Numbering levels don't match.");
2234 // record number of attributes, levels, and styles.
2235 of
.writeAsciiString("static const sal_Int16 outlineNbOfStyles = ");
2236 of
.writeInt( sal::static_int_cast
<sal_Int16
>( nStyles
) );
2237 of
.writeAsciiString(";\n\n");
2238 of
.writeAsciiString("static const sal_Int16 outlineNbOfLevelsPerStyle = ");
2239 of
.writeInt( sal::static_int_cast
<sal_Int16
>( nLevels
.back() ) );
2240 of
.writeAsciiString(";\n\n");
2241 of
.writeAsciiString("static const sal_Int16 outlineNbOfAttributesPerLevel = ");
2242 of
.writeInt( nAttributes
);
2243 of
.writeAsciiString(";\n\n");
2245 // too complicated for now...
2246 // of.writeAsciiString("static const sal_Int16 nbOfOutlineNumberingLevels[] = { ");
2247 // for( sal_Int32 j=0; j<nStyles; j++ )
2249 // of.writeInt( nLevels[j] );
2250 // of.writeAsciiString(", ");
2252 // of.writeAsciiString("};\n\n");
2255 for( sal_Int32 i
=0; i
<nStyles
; i
++ )
2257 for( sal_Int32 j
=0; j
<nLevels
.back(); j
++ )
2259 of
.writeAsciiString("static const sal_Unicode* outline");
2260 of
.writeAsciiString("Style");
2261 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2262 of
.writeAsciiString("Level");
2263 of
.writeInt( sal::static_int_cast
<sal_Int16
>(j
) );
2264 of
.writeAsciiString("[] = { ");
2266 for( sal_Int32 k
=0; k
<nAttributes
; k
++ )
2268 of
.writeAsciiString( "outline" );
2269 of
.writeAsciiString( attr
[k
] );
2270 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2271 of
.writeInt( sal::static_int_cast
<sal_Int16
>(j
) );
2272 of
.writeAsciiString(", ");
2274 of
.writeAsciiString("NULL };\n");
2278 of
.writeAsciiString("\n");
2281 for( sal_Int32 i
=0; i
<nStyles
; i
++ )
2283 of
.writeAsciiString("static const sal_Unicode** outline");
2284 of
.writeAsciiString( "Style" );
2285 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2286 of
.writeAsciiString("[] = { ");
2288 for( sal_Int32 j
=0; j
<nLevels
.back(); j
++ )
2290 of
.writeAsciiString("outlineStyle");
2291 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2292 of
.writeAsciiString("Level");
2293 of
.writeInt( sal::static_int_cast
<sal_Int16
>(j
) );
2294 of
.writeAsciiString(", ");
2296 of
.writeAsciiString("NULL };\n");
2298 of
.writeAsciiString("\n");
2300 of
.writeAsciiString("static const sal_Unicode*** LCOutlineNumberingLevelsArray[] = {\n" );
2301 for( sal_Int32 i
=0; i
<nStyles
; i
++ )
2303 of
.writeAsciiString( "\t" );
2304 of
.writeAsciiString( "outlineStyle" );
2305 of
.writeInt( sal::static_int_cast
<sal_Int16
>(i
) );
2306 of
.writeAsciiString(",\n");
2308 of
.writeAsciiString("\tNULL\n};\n\n");
2309 of
.writeFunction3("getOutlineNumberingLevels_", "outlineNbOfStyles", "outlineNbOfLevelsPerStyle",
2310 "outlineNbOfAttributesPerLevel", "LCOutlineNumberingLevelsArray");
2313 Attr::Attr (const Reference
< XAttributeList
> & attr
) {
2314 sal_Int16 len
= attr
->getLength();
2316 value
.realloc (len
);
2317 for (sal_Int16 i
=0; i
< len
;i
++) {
2318 name
[i
] = attr
->getNameByIndex(i
);
2319 value
[i
] = attr
-> getValueByIndex(i
);
2323 const OUString
& Attr::getValueByName (const sal_Char
*str
) const {
2324 static OUString empty
;
2325 sal_Int32 len
= name
.getLength();
2326 for (sal_Int32 i
= 0;i
<len
;i
++)
2327 if (name
[i
].equalsAscii(str
))
2332 sal_Int32
Attr::getLength() const{
2333 return name
.getLength();
2336 const OUString
& Attr::getTypeByIndex (sal_Int32 idx
) const {
2340 const OUString
& Attr::getValueByIndex (sal_Int32 idx
) const
2345 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */