Version 3.6.0.2, tag libreoffice-3.6.0.2
[LibreOffice.git] / i18npool / source / localedata / LocaleNode.cxx
blob2590e7e05702a9d102491c29888f11f24d5f6a83
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 ************************************************************************/
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <iostream>
33 #include <set>
34 #include <vector>
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)
51 : aName(name)
52 , aAttribs(attr)
53 , parent(0)
54 , children(0)
55 , nChildren(0)
56 , childArrSize(0)
57 , nError(0)
61 int LocaleNode::getError() const
63 int err = nError;
64 for (sal_Int32 i=0;i<nChildren;i++)
65 err += children[i]->getError();
66 return err;
69 void LocaleNode::print () const {
70 printf ("<");
71 ::rtl::OUString str (aName);
72 for(sal_Int32 i = 0; i < str.getLength(); i++)
73 printf( "%c", str[i]);
74 printf (">\n");
77 void LocaleNode::printR () const {
78 print();
79 for (sal_Int32 i=0;i<nChildren;i++)
80 children[i]->printR();
81 printf ("\t");
82 print();
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];
90 delete [] children;
91 childArrSize += 10;
92 children = arrN;
94 children[nChildren++] = node;
95 node->setParent (this);
98 void LocaleNode::setParent ( LocaleNode * node) {
99 parent = node;
102 const LocaleNode* LocaleNode::getRoot() const
104 const LocaleNode* pRoot = 0;
105 const LocaleNode* pParent = this;
106 while ( (pParent = pParent->getParent()) != 0 )
107 pRoot = pParent;
108 return pRoot;
111 const LocaleNode * LocaleNode::findNode ( const sal_Char *name) const {
112 if (aName.equalsAscii(name))
113 return this;
114 for (sal_Int32 i = 0; i< nChildren; i++) {
115 const LocaleNode *n=children[i]->findNode(name);
116 if (n)
117 return n;
119 return 0;
122 LocaleNode::~LocaleNode()
124 for (sal_Int32 i=0; i < nChildren; ++i)
125 delete children[i];
126 delete [] children;
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 )
189 if( !p ) return;
191 print_indent( depth );
192 printf("<");
193 print_color(36);
194 print_OUString( p->getName() );
195 print_color(0);
196 const Attr& q = p->getAttr();
197 for( sal_Int32 j = 0; j < q.getLength(); ++j )
199 printf(" ");
200 print_color(33);
201 print_OUString( q.getTypeByIndex(j) );
202 print_color(0);
203 printf("=");
204 print_color(31);
205 printf("'");
206 print_OUString( q.getValueByIndex(j) );
207 printf("'");
208 print_color(0);
210 printf(">");
211 printf("\n");
212 if( !is_empty_string( p->getValue() ) )
214 print_indent( depth+1 );
215 printf("value: ");
216 print_color(31);
217 printf("'");
218 print_OUString( p->getValue() );
219 printf("'");
220 print_color(0);
221 printf("\n");
223 for( sal_Int32 i=0; i<p->getNumberOfChildren(); i++ )
225 print_node( p->getChildAt(i), depth+1 );
227 print_indent( depth );
228 printf("</");
229 print_OUString( p->getName() );
230 printf(">");
231 printf("\n");
234 void LocaleNode :: generateCode (const OFileWriter &of) const
236 ::rtl::OUString aDTD = getAttr().getValueByName("versionDTD");
237 if ( aDTD != LOCALE_VERSION_DTD )
239 ++nError;
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
252 OUString aVal;
253 if (pNode)
254 aVal = pNode->getValue();
255 else
257 ++nError;
258 fprintf( stderr, "Error: node NULL pointer for parameter %s.\n",
259 pParameterName);
261 // write empty data if error
262 of.writeParameter( pParameterName, aVal);
263 sal_Int32 nLen = aVal.getLength();
264 if (nLen < nMinLen)
266 ++nError;
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()) : ""),
271 OSTR( aVal));
273 else if (nLen > nMaxLen && nMaxLen >= 0)
274 fprintf( stderr,
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()) : ""),
279 OSTR( aVal));
280 return aVal;
284 ::rtl::OUString LocaleNode::writeParameterCheckLen( const OFileWriter &of,
285 const char* pNodeName, const char* pParameterName,
286 sal_Int32 nMinLen, sal_Int32 nMaxLen ) const
288 OUString aVal;
289 const LocaleNode * pNode = findNode( pNodeName);
290 if (pNode)
291 aVal = writeParameterCheckLen( of, pParameterName, pNode, nMinLen, nMaxLen);
292 else
294 ++nError;
295 fprintf( stderr, "Error: node %s not found.\n", pNodeName);
296 // write empty data if error
297 of.writeParameter( pParameterName, aVal);
299 return aVal;
302 void LocaleNode::incError( const char* pStr ) const
304 ++nError;
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);
318 char* p = buf;
319 while (((p = strchr( p, '%')) != 0) && p[1] == '%')
320 p += 2;
321 if (!p)
322 strcat( buf, pDefaultConversion);
323 strcat( buf, "\n");
324 return buf;
327 void LocaleNode::incErrorInt( const char* pStr, int nVal ) const
329 ++nError;
330 fprintf( stderr, prepareErrorFormat( pStr, ": %d"), nVal);
333 void LocaleNode::incErrorStr( const char* pStr, const ::rtl::OUString& rVal ) const
335 ++nError;
336 fprintf( stderr, prepareErrorFormat( pStr, ": %s"), OSTR( rVal));
339 void LocaleNode::incErrorStrStr( const char* pStr, const ::rtl::OUString& rVal1, const ::rtl::OUString& rVal2 ) const
341 ++nError;
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");
352 if (languageNode)
354 writeParameterCheckLen( of, "langID", languageNode->getChildAt(0), 2, -1);
355 of.writeParameter("langDefaultName", languageNode->getChildAt(1)->getValue());
357 else
358 incError( "No Language node.");
359 if (countryNode)
361 of.writeParameter("countryID", countryNode->getChildAt(0)->getValue());
362 of.writeParameter("countryDefaultName", countryNode->getChildAt(1)->getValue());
364 else
365 incError( "No Country node.");
366 if (variantNode)
368 of.writeParameter("Variant", variantNode->getValue());
369 fprintf( stderr, "Warning: %s\n",
370 "Variants are not supported by application.");
372 else
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);
394 return;
396 ::rtl::OUString str = getAttr().getValueByName("unoid");
397 of.writeAsciiString("\n\n");
398 of.writeParameter("LC_CTYPE_Unoid", str);;
400 aDateSep =
401 writeParameterCheckLen( of, "DateSeparator", "dateSeparator", 1, 1);
402 OUString aThoSep =
403 writeParameterCheckLen( of, "ThousandSeparator", "thousandSeparator", 1, 1);
404 aDecSep =
405 writeParameterCheckLen( of, "DecimalSeparator", "decimalSeparator", 1, 1);
406 OUString aTimeSep =
407 writeParameterCheckLen( of, "TimeSeparator", "timeSeparator", 1, 1);
408 OUString aTime100Sep =
409 writeParameterCheckLen( of, "Time100SecSeparator", "time100SecSeparator", 1, 1);
410 OUString aListSep =
411 writeParameterCheckLen( of, "ListSeparator", "listSeparator", 1, 1);
413 OUString aLDS;
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);
432 if (aLDS.isEmpty())
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);
439 if (aLDS.isEmpty())
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;
445 int nWarn = 0;
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);
475 OUString aQuoteEnd =
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.
515 int ic;
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)
525 break;
526 default:
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)
539 break;
540 default:
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)
553 break;
554 default:
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)
567 break;
568 default:
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
611 if (mnSection >= 2)
612 incError("more than 2 LC_FORMAT sections");
614 ::std::vector< OUString > theDateAcceptancePatterns;
616 OUString str;
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( '-');
633 if (nHyphen >= 3)
635 sTheCompatibleCurrency = str.copy( 2, nHyphen - 2);
639 ::rtl::OUString useLocale = getAttr().getValueByName("ref");
640 if (!useLocale.isEmpty())
642 switch (mnSection)
644 case 0:
645 of.writeRefFunction("getAllFormats0_", useLocale, "replaceTo0");
646 break;
647 case 1:
648 of.writeRefFunction("getAllFormats1_", useLocale, "replaceTo1");
649 break;
651 of.writeRefFunction("getDateAcceptancePatterns_", useLocale);
652 return;
655 sal_Int16 formatCount = mnFormats;
656 NameSet aMsgIdSet;
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" )
666 if (mnSection > 0)
667 incError( "DateAcceptancePattern only handled in LC_FORMAT, not LC_FORMAT_1");
668 else
669 theDateAcceptancePatterns.push_back( currNode->getValue());
670 --formatCount;
671 continue; // for
673 if ( currNode->getName() != "FormatElement" )
675 incErrorStr( "Undefined element in LC_FORMAT", currNode->getName());
676 --formatCount;
677 continue; // for
680 OUString aUsage;
681 OUString aType;
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.
709 if (bDefault)
711 OUString aKey( aUsage + OUString( sal_Unicode(',')) + aType);
712 if (!aDefaultsSet.insert( aKey).second)
714 OUString aStr( "Duplicated default for usage=\"");
715 aStr += aUsage;
716 aStr += OUString( "\" type=\"");
717 aStr += aType;
718 aStr += OUString( "\": formatindex=\"");
719 aStr += aFormatIndex;
720 aStr += OUString( "\".");
721 incError( aStr);
725 const LocaleNode * n = currNode -> findNode("FormatCode");
726 if (n)
728 of.writeParameter("FormatCode", n->getValue(), formatCount);
729 // Check separator usage for some FormatCode elements.
730 const LocaleNode* pCtype = 0;
731 switch (formatindex)
733 case cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY :
734 sTheDateEditFormat = n->getValue();
735 break;
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();
741 if (!pRoot)
742 incError( "No root for FormatCode.");
743 else
745 pCtype = pRoot->findNode( "LC_CTYPE");
746 if (!pCtype)
747 incError( "No LC_CTYPE found for FormatCode.");
748 else
750 OUString aRef( pCtype->getAttr().getValueByName("ref"));
751 if (!aRef.isEmpty())
753 if (!bCtypeIsRef)
754 fprintf( stderr,
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",
757 OSTR( aRef));
758 bCtypeIsRef = true;
759 pCtype = 0;
764 break;
765 case cssi::NumberFormatIndex::CURRENCY_1000DEC2 :
766 // Remember the currency symbol if present.
768 sal_Int32 nStart;
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);
778 // fallthru
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);
804 break;
806 if (pCtype)
808 int nSavErr = nError;
809 OUString aCode( n->getValue());
810 if (formatindex == cssi::NumberFormatIndex::NUMBER_1000DEC2)
812 sal_Int32 nDec = -1;
813 sal_Int32 nGrp = -1;
814 const LocaleNode* pSep = pCtype->findNode( "DecimalSeparator");
815 if (!pSep)
816 incError( "No DecimalSeparator found for FormatCode.");
817 else
819 nDec = aCode.indexOf( pSep->getValue());
820 if (nDec < 0)
821 incErrorInt( "DecimalSeparator not present in FormatCode formatindex=\"%d\".",
822 formatindex);
824 pSep = pCtype->findNode( "ThousandSeparator");
825 if (!pSep)
826 incError( "No ThousandSeparator found for FormatCode.");
827 else
829 nGrp = aCode.indexOf( pSep->getValue());
830 if (nGrp < 0)
831 incErrorInt( "ThousandSeparator not present in FormatCode formatindex=\"%d\".",
832 formatindex);
834 if (nDec >= 0 && nGrp >= 0 && nDec <= nGrp)
835 incErrorInt( "Ordering of ThousandSeparator and DecimalSeparator not correct in formatindex=\"%d\".",
836 formatindex);
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");
844 if (!pSep)
845 incError( "No TimeSeparator found for FormatCode.");
846 else
848 nTime = aCode.indexOf( pSep->getValue());
849 if (nTime < 0)
850 incErrorInt( "TimeSeparator not present in FormatCode formatindex=\"%d\".",
851 formatindex);
853 pSep = pCtype->findNode( "Time100SecSeparator");
854 if (!pSep)
855 incError( "No Time100SecSeparator found for FormatCode.");
856 else
858 n100s = aCode.indexOf( pSep->getValue());
859 if (n100s < 0)
860 incErrorInt( "Time100SecSeparator not present in FormatCode formatindex=\"%d\".",
861 formatindex);
862 OUStringBuffer a100s( pSep->getValue());
863 a100s.appendAscii( "00");
864 n100s = aCode.indexOf( a100s.makeStringAndClear());
865 if (n100s < 0)
866 incErrorInt( "Time100SecSeparator+00 not present in FormatCode formatindex=\"%d\".",
867 formatindex);
869 if (n100s >= 0 && nTime >= 0 && n100s <= nTime)
870 incErrorInt( "Ordering of Time100SecSeparator and TimeSeparator not correct in formatindex=\"%d\".",
871 formatindex);
873 if (nSavErr != nError)
874 fprintf( stderr,
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));
882 else
883 incError( "No FormatCode in FormatElement.");
884 n = currNode -> findNode("DefaultName");
885 if (n)
886 of.writeParameter("FormatDefaultName", n->getValue(), formatCount);
887 else
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
894 if (mnSection == 0)
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)
907 switch (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
914 break;
915 default:
916 incErrorInt( "FormatElement formatindex=\"%d\" not present.", nNext);
919 switch (nHere)
921 case cssi::NumberFormatIndex::BOOLEAN :
922 incErrorInt( "FormatElement formatindex=\"%d\" reserved for internal ``BOOLEAN''.", nNext);
923 break;
924 case cssi::NumberFormatIndex::TEXT :
925 incErrorInt( "FormatElement formatindex=\"%d\" reserved for internal ``@'' (TEXT).", nNext);
926 break;
927 default:
928 ; // nothing
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");
947 of.writeInt(i);
948 of.writeAsciiString(",\n");
950 of.writeAsciiString("\t");
951 of.writeAsciiString("FormatDefaultName");
952 of.writeInt(i);
953 of.writeAsciiString(",\n");
955 of.writeAsciiString("\t");
956 of.writeAsciiString("FormatKey");
957 of.writeInt(i);
958 of.writeAsciiString(",\n");
960 of.writeAsciiString("\t");
961 of.writeAsciiString("FormatType");
962 of.writeInt(i);
963 of.writeAsciiString(",\n");
965 of.writeAsciiString("\t");
966 of.writeAsciiString("FormatUsage");
967 of.writeInt(i);
968 of.writeAsciiString(",\n");
970 of.writeAsciiString("\t");
971 of.writeAsciiString("Formatindex");
972 of.writeInt(i);
973 of.writeAsciiString(",\n");
976 of.writeAsciiString("\tdefaultFormatElement");
977 of.writeInt(i);
978 of.writeAsciiString(",\n");
980 of.writeAsciiString("};\n\n");
982 switch (mnSection)
984 case 0:
985 of.writeFunction("getAllFormats0_", "FormatElementsCount0", "FormatElementsArray0", "replaceFrom0", "replaceTo0");
986 break;
987 case 1:
988 of.writeFunction("getAllFormats1_", "FormatElementsCount1", "FormatElementsArray1", "replaceFrom1", "replaceTo1");
989 break;
992 mnFormats = mnFormats + formatCount;
994 if (mnSection == 0)
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
998 // that one.
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
1003 // FormatCode then.
1004 sal_uInt32 cDateSep = (aDateSep.isEmpty() ? 0 : aDateSep.iterateCodePoints( &nIndex));
1005 sal_uInt32 cDateSep2 = cDateSep;
1006 nIndex = 0;
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);
1015 if (bInModifier)
1017 if (cChar == ']')
1018 bInModifier = false;
1019 continue; // while
1021 if (bQuoted)
1023 if (cChar == '"')
1024 bQuoted = false;
1025 continue; // while
1027 switch (cChar)
1029 case 'Y':
1030 case 'y':
1031 if (!(nDetected & 4))
1033 aPatternBuf.append( 'Y');
1034 if (aPatternBuf2.getLength() > 0)
1035 aPatternBuf2.append( 'Y');
1036 nDetected |= 4;
1038 break;
1039 case 'M':
1040 case 'm':
1041 if (!(nDetected & 2))
1043 aPatternBuf.append( 'M');
1044 if (aPatternBuf2.getLength() > 0)
1045 aPatternBuf2.append( 'M');
1046 nDetected |= 2;
1048 break;
1049 case 'D':
1050 case 'd':
1051 if (!(nDetected & 1))
1053 aPatternBuf.append( 'D');
1054 if (aPatternBuf2.getLength() > 0)
1055 aPatternBuf2.append( 'D');
1056 nDetected |= 1;
1058 break;
1059 case '[':
1060 bInModifier = true;
1061 break;
1062 case '"':
1063 bQuoted = true;
1064 break;
1065 case '\\':
1066 cChar = sTheDateEditFormat.iterateCodePoints( &nIndex);
1067 break;
1068 case '-':
1069 case '.':
1070 case '/':
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.
1077 cDateSep2 = cChar;
1078 // fallthru
1079 default:
1080 if (!cDateSep)
1081 cDateSep = cChar;
1082 if (!cDateSep2)
1083 cDateSep2 = cChar;
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
1090 break;
1091 // The localized legacy:
1092 case 'A':
1093 if (((nDetected & 7) == 3) || ((nDetected & 7) == 0))
1095 // es DD/MM/AAAA
1096 // fr JJ.MM.AAAA
1097 // it GG/MM/AAAA
1098 // fr_CA AAAA-MM-JJ
1099 aPatternBuf.append( 'Y');
1100 if (aPatternBuf2.getLength() > 0)
1101 aPatternBuf2.append( 'Y');
1102 nDetected |= 4;
1104 break;
1105 case 'J':
1106 if (((nDetected & 7) == 0) || ((nDetected & 7) == 6))
1108 // fr JJ.MM.AAAA
1109 // fr_CA AAAA-MM-JJ
1110 aPatternBuf.append( 'D');
1111 if (aPatternBuf2.getLength() > 0)
1112 aPatternBuf2.append( 'D');
1113 nDetected |= 1;
1115 else if ((nDetected & 7) == 3)
1117 // nl DD-MM-JJJJ
1118 // de TT.MM.JJJJ
1119 aPatternBuf.append( 'Y');
1120 if (aPatternBuf2.getLength() > 0)
1121 aPatternBuf2.append( 'Y');
1122 nDetected |= 4;
1124 break;
1125 case 'T':
1126 if ((nDetected & 7) == 0)
1128 // de TT.MM.JJJJ
1129 aPatternBuf.append( 'D');
1130 if (aPatternBuf2.getLength() > 0)
1131 aPatternBuf2.append( 'D');
1132 nDetected |= 1;
1134 break;
1135 case 'G':
1136 if ((nDetected & 7) == 0)
1138 // it GG/MM/AAAA
1139 aPatternBuf.append( 'D');
1140 if (aPatternBuf2.getLength() > 0)
1141 aPatternBuf2.append( 'D');
1142 nDetected |= 1;
1144 break;
1145 case 'P':
1146 if ((nDetected & 7) == 0)
1148 // fi PP.KK.VVVV
1149 aPatternBuf.append( 'D');
1150 if (aPatternBuf2.getLength() > 0)
1151 aPatternBuf2.append( 'D');
1152 nDetected |= 1;
1154 break;
1155 case 'K':
1156 if ((nDetected & 7) == 1)
1158 // fi PP.KK.VVVV
1159 aPatternBuf.append( 'M');
1160 if (aPatternBuf2.getLength() > 0)
1161 aPatternBuf2.append( 'M');
1162 nDetected |= 2;
1164 break;
1165 case 'V':
1166 if ((nDetected & 7) == 3)
1168 // fi PP.KK.VVVV
1169 aPatternBuf.append( 'Y');
1170 if (aPatternBuf2.getLength() > 0)
1171 aPatternBuf2.append( 'Y');
1172 nDetected |= 4;
1174 break;
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);
1185 else
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);
1204 else
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.
1214 nIndex = 0;
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))
1221 nIndex = 1;
1222 if ((*aIt).iterateCodePoints( &nIndex) == cDecSep)
1224 ++nError;
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);
1243 else
1244 ++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");
1264 of.writeInt(i);
1265 of.writeAsciiString(",\n");
1267 of.writeAsciiString("};\n\n");
1269 of.writeFunction("getDateAcceptancePatterns_", "DateAcceptancePatternsCount", "DateAcceptancePatternsArray");
1272 ++mnSection;
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);
1281 return;
1283 sal_Int16 nbOfCollations = 0;
1284 sal_Int16 nbOfCollationOptions = 0;
1285 sal_Int16 j;
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");
1300 nbOfCollations++;
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");
1323 of.writeInt(j);
1324 of.writeAsciiString(",\n");
1326 of.writeAsciiString("\tdefaultCollator");
1327 of.writeInt(j);
1328 of.writeAsciiString(",\n");
1330 of.writeAsciiString("\tCollatorRule");
1331 of.writeInt(j);
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" );
1340 of.writeInt( j );
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);
1353 return;
1356 if( getNumberOfChildren() != 1 )
1358 ++nError;
1359 fprintf(
1360 stderr, "Error: LC_SEARCH: more than 1 child: %ld\n",
1361 sal::static_int_cast< long >(getNumberOfChildren()));
1363 sal_Int32 i;
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);
1393 return;
1395 sal_Int16 nbOfIndexs = 0;
1396 sal_Int16 nbOfUnicodeScripts = 0;
1397 sal_Int16 nbOfPageWords = 0;
1398 sal_Int16 i;
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");
1416 nbOfIndexs++;
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);
1427 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");
1437 of.writeInt(i);
1438 of.writeAsciiString(",\n");
1440 of.writeAsciiString("\tIndexModule");
1441 of.writeInt(i);
1442 of.writeAsciiString(",\n");
1444 of.writeAsciiString("\tIndexKey");
1445 of.writeInt(i);
1446 of.writeAsciiString(",\n");
1448 of.writeAsciiString("\tdefaultIndex");
1449 of.writeInt(i);
1450 of.writeAsciiString(",\n");
1452 of.writeAsciiString("\tdefaultPhonetic");
1453 of.writeInt(i);
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" );
1466 of.writeInt( i );
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");
1478 of.writeInt(i);
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();
1494 OUString aNarrName;
1495 LocaleNode* p = (currNode->getNumberOfChildren() > 3 ? currNode->getChildAt(3) : 0);
1496 if ( p && p->getName() == "DefaultNarrowName" )
1497 aNarrName = p->getValue();
1498 else
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 )
1526 if (nCount == 0)
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");
1533 else
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);
1540 if (bNarrow)
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);
1551 return;
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];
1560 sal_Int16 j;
1561 sal_Int16 i;
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";
1570 if (!bHasGregorian)
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);
1591 nbOfDays[i] = 0;
1592 } else {
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]);
1598 elementTag = "day";
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);
1608 ++nChild;
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);
1623 nbOfMonths[i] = 0;
1624 } else {
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);
1640 ++nChild;
1642 // Generate genitive Months of Year
1643 // Optional, if not present fall back to month nouns.
1644 if ( calNode->getChildAt(nChild)->getName() != "GenitiveMonths" )
1645 --nChild;
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;
1659 } else {
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);
1675 ++nChild;
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" )
1681 --nChild;
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;
1695 } else {
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);
1711 ++nChild;
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);
1726 nbOfEras[i] = 0;
1727 } else {
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]);
1733 elementTag = "era";
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);
1747 ++nChild;
1749 str = calNode->getChildAt(nChild)->getChildAt(0)->getValue();
1750 if (nbOfDays[i])
1752 for (j = 0; j < nbOfDays[i]; j++)
1754 LocaleNode *currNode = daysNode->getChildAt(j);
1755 OUString dayID( currNode->getChildAt(0)->getValue());
1756 if (str == dayID)
1757 break; // for
1759 if (j >= nbOfDays[i])
1760 incErrorStr( "<StartDayOfWeek> <DayID> must be one of the <DaysOfWeek>, but is", str);
1762 of.writeParameter("startDayOfWeek", str, i);
1763 ++nChild;
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);
1771 if (!bHasGregorian)
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");
1827 of.writeInt(i);
1828 of.writeAsciiString(",\n");
1829 of.writeAsciiString("\tdefaultCalendar");
1830 of.writeInt(i);
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");
1844 delete []nbOfDays;
1845 delete []nbOfMonths;
1846 delete []nbOfGenitiveMonths;
1847 delete []nbOfPartitiveMonths;
1848 delete []nbOfEras;
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);
1866 return;
1868 sal_Int16 nbOfCurrencies = 0;
1869 ::rtl::OUString str;
1870 sal_Int16 i;
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.");
1884 if (bDefault)
1886 if (bTheDefault)
1887 incError( "Currency: more than one default currency.");
1888 bTheDefault = true;
1890 if (bCompatible)
1892 if (bTheCompatible)
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");
1923 if (!bTheDefault)
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");
1934 of.writeInt(i);
1935 of.writeAsciiString(",\n");
1936 of.writeAsciiString("\tcurrencySymbol");
1937 of.writeInt(i);
1938 of.writeAsciiString(",\n");
1939 of.writeAsciiString("\tbankSymbol");
1940 of.writeInt(i);
1941 of.writeAsciiString(",\n");
1942 of.writeAsciiString("\tcurrencyName");
1943 of.writeInt(i);
1944 of.writeAsciiString(",\n");
1945 of.writeAsciiString("\tdefaultCurrency");
1946 of.writeInt(i);
1947 of.writeAsciiString(",\n");
1948 of.writeAsciiString("\tdefaultCurrencyUsedInCompatibleFormatCodes");
1949 of.writeInt(i);
1950 of.writeAsciiString(",\n");
1951 of.writeAsciiString("\tcurrencyDecimalPlaces");
1952 of.writeInt(i);
1953 of.writeAsciiString(",\n");
1954 of.writeAsciiString("\tdefaultCurrencyLegacyOnly");
1955 of.writeInt(i);
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);
1967 return;
1969 sal_Int16 nbOfModules = 0;
1970 ::rtl::OUString str;
1971 sal_Int16 i;
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");
1985 of.writeInt(i);
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);
2018 return;
2020 const LocaleNode * reserveNode = findNode("ReservedWords");
2021 if (!reserveNode)
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;
2030 sal_Int16 i;
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);
2035 if (!curNode)
2036 fprintf( stderr,
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);
2040 if (str.isEmpty())
2042 ++nError;
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))
2050 fprintf( stderr,
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");
2061 of.writeInt(i);
2062 of.writeAsciiString(",\n");
2064 of.writeAsciiString("};\n\n");
2065 of.writeFunction("getReservedWords_", "nbOfReservedWords", "LCReservedWordsArray");
2067 if (forbidNode) {
2068 of.writeParameter( "forbiddenBegin", forbidNode -> getChildAt(0)->getValue());
2069 of.writeParameter( "forbiddenEnd", forbidNode -> getChildAt(1)->getValue());
2070 of.writeParameter( "hangingChars", forbidNode -> getChildAt(2)->getValue());
2071 } else {
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");
2083 if (breakNode) {
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());
2089 } else {
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);
2113 return;
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();
2123 sal_Int32 i;
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);
2183 return;
2186 // hardcode number of attributes per level
2187 const int nAttributes = 11;
2188 const char* attr[ nAttributes ] =
2190 "Prefix",
2191 "NumType",
2192 "Suffix",
2193 "BulletChar",
2194 "BulletFontName",
2195 "ParentNumbering",
2196 "LeftMargin",
2197 "SymbolTextDistance",
2198 "FirstLineOffset",
2199 "Transliteration",
2200 "NatNum",
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++ )
2248 // {
2249 // of.writeInt( nLevels[j] );
2250 // of.writeAsciiString(", ");
2251 // }
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();
2315 name.realloc (len);
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))
2328 return value[i];
2329 return empty;
2332 sal_Int32 Attr::getLength() const{
2333 return name.getLength();
2336 const OUString& Attr::getTypeByIndex (sal_Int32 idx) const {
2337 return name[idx];
2340 const OUString& Attr::getValueByIndex (sal_Int32 idx) const
2342 return value[idx];
2345 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */