bump product version to 4.2.0.1
[LibreOffice.git] / i18npool / source / localedata / LocaleNode.cxx
blob2e1043ac49e039f420fb72ef62dd088bdca53f97
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <iostream>
24 #include <set>
25 #include <vector>
27 #include <rtl/ustrbuf.hxx>
28 #include <sal/macros.h>
30 #include "LocaleNode.hxx"
31 #include <com/sun/star/i18n/NumberFormatIndex.hpp>
33 // NOTE: MUST match the Locale versionDTD attribute defined in data/locale.dtd
34 #define LOCALE_VERSION_DTD "2.0.3"
36 typedef ::std::set< OUString > NameSet;
37 typedef ::std::set< sal_Int16 > ValueSet;
39 namespace cssi = ::com::sun::star::i18n;
41 LocaleNode::LocaleNode (const OUString& name, const Reference< XAttributeList > & attr)
42 : aName(name)
43 , aAttribs(attr)
44 , parent(0)
45 , children(0)
46 , nChildren(0)
47 , childArrSize(0)
48 , nError(0)
52 int LocaleNode::getError() const
54 int err = nError;
55 for (sal_Int32 i=0;i<nChildren;i++)
56 err += children[i]->getError();
57 return err;
60 void LocaleNode::print () const {
61 printf ("<");
62 OUString str (aName);
63 for(sal_Int32 i = 0; i < str.getLength(); i++)
64 printf( "%c", str[i]);
65 printf (">\n");
68 void LocaleNode::printR () const {
69 print();
70 for (sal_Int32 i=0;i<nChildren;i++)
71 children[i]->printR();
72 printf ("\t");
73 print();
76 void LocaleNode::addChild ( LocaleNode * node) {
77 if (childArrSize <= nChildren) {
78 LocaleNode ** arrN = new LocaleNode*[childArrSize+10];
79 for (sal_Int32 i = 0; i<childArrSize; ++i)
80 arrN[i] = children[i];
81 delete [] children;
82 childArrSize += 10;
83 children = arrN;
85 children[nChildren++] = node;
86 node->setParent (this);
89 void LocaleNode::setParent ( LocaleNode * node) {
90 parent = node;
93 const LocaleNode* LocaleNode::getRoot() const
95 const LocaleNode* pRoot = 0;
96 const LocaleNode* pParent = this;
97 while ( (pParent = pParent->getParent()) != 0 )
98 pRoot = pParent;
99 return pRoot;
102 const LocaleNode * LocaleNode::findNode ( const sal_Char *name) const {
103 if (aName.equalsAscii(name))
104 return this;
105 for (sal_Int32 i = 0; i< nChildren; i++) {
106 const LocaleNode *n=children[i]->findNode(name);
107 if (n)
108 return n;
110 return 0;
113 LocaleNode::~LocaleNode()
115 for (sal_Int32 i=0; i < nChildren; ++i)
116 delete children[i];
117 delete [] children;
120 LocaleNode* LocaleNode::createNode (const OUString& name, const Reference< XAttributeList > & attr)
122 if ( name == "LC_INFO" )
123 return new LCInfoNode (name,attr);
124 if ( name == "LC_CTYPE" )
125 return new LCCTYPENode (name,attr);
126 if ( name == "LC_FORMAT" )
127 return new LCFormatNode (name,attr);
128 if ( name == "LC_FORMAT_1" )
129 return new LCFormatNode (name,attr);
130 if ( name == "LC_CALENDAR" )
131 return new LCCalendarNode (name,attr);
132 if ( name == "LC_CURRENCY" )
133 return new LCCurrencyNode (name,attr);
134 if ( name == "LC_TRANSLITERATION" )
135 return new LCTransliterationNode (name,attr);
136 if ( name == "LC_COLLATION" )
137 return new LCCollationNode (name,attr);
138 if ( name == "LC_INDEX" )
139 return new LCIndexNode (name,attr);
140 if ( name == "LC_SEARCH" )
141 return new LCSearchNode (name,attr);
142 if ( name == "LC_MISC" )
143 return new LCMiscNode (name,attr);
144 if ( name == "LC_NumberingLevel" )
145 return new LCNumberingLevelNode (name, attr);
146 if ( name == "LC_OutLineNumberingLevel" )
147 return new LCOutlineNumberingLevelNode (name, attr);
149 return new LocaleNode(name,attr);
153 // printf(" name: '%s'\n", p->getName().pData->buffer );
154 // printf("value: '%s'\n", p->getValue().pData->buffer );
156 #define OSTR(s) (OUStringToOString( (s), RTL_TEXTENCODING_UTF8).getStr())
158 void print_OUString( const OUString& s )
160 printf( "%s", OSTR(s));
163 bool is_empty_string( const OUString& s )
165 return s.isEmpty() || (s.getLength()==1 && s[0]=='\n');
168 void print_indent( int depth )
170 for( int i=0; i<depth; i++ ) printf(" ");
173 void print_color( int color )
175 printf("\033[%dm", color);
178 void print_node( const LocaleNode* p, int depth=0 )
180 if( !p ) return;
182 print_indent( depth );
183 printf("<");
184 print_color(36);
185 print_OUString( p->getName() );
186 print_color(0);
187 const Attr& q = p->getAttr();
188 for( sal_Int32 j = 0; j < q.getLength(); ++j )
190 printf(" ");
191 print_color(33);
192 print_OUString( q.getTypeByIndex(j) );
193 print_color(0);
194 printf("=");
195 print_color(31);
196 printf("'");
197 print_OUString( q.getValueByIndex(j) );
198 printf("'");
199 print_color(0);
201 printf(">");
202 printf("\n");
203 if( !is_empty_string( p->getValue() ) )
205 print_indent( depth+1 );
206 printf("value: ");
207 print_color(31);
208 printf("'");
209 print_OUString( p->getValue() );
210 printf("'");
211 print_color(0);
212 printf("\n");
214 for( sal_Int32 i=0; i<p->getNumberOfChildren(); i++ )
216 print_node( p->getChildAt(i), depth+1 );
218 print_indent( depth );
219 printf("</");
220 print_OUString( p->getName() );
221 printf(">");
222 printf("\n");
225 void LocaleNode :: generateCode (const OFileWriter &of) const
227 OUString aDTD = getAttr().getValueByName("versionDTD");
228 if ( aDTD != LOCALE_VERSION_DTD )
230 ++nError;
231 fprintf( stderr, "Error: Locale versionDTD is not %s, see comment in locale.dtd\n", LOCALE_VERSION_DTD);
233 for (sal_Int32 i=0; i<nChildren;i++)
234 children[i]->generateCode (of);
235 // print_node( this );
239 OUString LocaleNode::writeParameterCheckLen( const OFileWriter &of,
240 const char* pParameterName, const LocaleNode* pNode,
241 sal_Int32 nMinLen, sal_Int32 nMaxLen ) const
243 OUString aVal;
244 if (pNode)
245 aVal = pNode->getValue();
246 else
248 ++nError;
249 fprintf( stderr, "Error: node NULL pointer for parameter %s.\n",
250 pParameterName);
252 // write empty data if error
253 of.writeParameter( pParameterName, aVal);
254 sal_Int32 nLen = aVal.getLength();
255 if (nLen < nMinLen)
257 ++nError;
258 fprintf( stderr, "Error: less than %ld character%s (%ld) in %s '%s'.\n",
259 sal::static_int_cast< long >(nMinLen), (nMinLen > 1 ? "s" : ""),
260 sal::static_int_cast< long >(nLen),
261 (pNode ? OSTR( pNode->getName()) : ""),
262 OSTR( aVal));
264 else if (nLen > nMaxLen && nMaxLen >= 0)
265 fprintf( stderr,
266 "Warning: more than %ld character%s (%ld) in %s %s not supported by application.\n",
267 sal::static_int_cast< long >(nMaxLen), (nMaxLen > 1 ? "s" : ""),
268 sal::static_int_cast< long >(nLen),
269 (pNode ? OSTR( pNode->getName()) : ""),
270 OSTR( aVal));
271 return aVal;
275 OUString LocaleNode::writeParameterCheckLen( const OFileWriter &of,
276 const char* pNodeName, const char* pParameterName,
277 sal_Int32 nMinLen, sal_Int32 nMaxLen ) const
279 OUString aVal;
280 const LocaleNode * pNode = findNode( pNodeName);
281 if (pNode)
282 aVal = writeParameterCheckLen( of, pParameterName, pNode, nMinLen, nMaxLen);
283 else
285 ++nError;
286 fprintf( stderr, "Error: node %s not found.\n", pNodeName);
287 // write empty data if error
288 of.writeParameter( pParameterName, aVal);
290 return aVal;
293 void LocaleNode::incError( const char* pStr ) const
295 ++nError;
296 fprintf( stderr, "Error: %s\n", pStr);
299 void LocaleNode::incError( const OUString& rStr ) const
301 incError( OSTR( rStr));
304 char* LocaleNode::prepareErrorFormat( const char* pFormat, const char* pDefaultConversion ) const
306 static char buf[2048];
307 strcpy( buf, "Error: ");
308 strncat( buf, pFormat, 2000);
309 char* p = buf;
310 while (((p = strchr( p, '%')) != 0) && p[1] == '%')
311 p += 2;
312 if (!p)
313 strcat( buf, pDefaultConversion);
314 strcat( buf, "\n");
315 return buf;
318 void LocaleNode::incErrorInt( const char* pStr, int nVal ) const
320 ++nError;
321 fprintf( stderr, prepareErrorFormat( pStr, ": %d"), nVal);
324 void LocaleNode::incErrorStr( const char* pStr, const OUString& rVal ) const
326 ++nError;
327 fprintf( stderr, prepareErrorFormat( pStr, ": %s"), OSTR( rVal));
330 void LocaleNode::incErrorStrStr( const char* pStr, const OUString& rVal1, const OUString& rVal2 ) const
332 ++nError;
333 fprintf( stderr, prepareErrorFormat( pStr, ": %s %s"), OSTR( rVal1), OSTR( rVal2));
336 void LCInfoNode::generateCode (const OFileWriter &of) const
339 const LocaleNode * languageNode = findNode("Language");
340 const LocaleNode * countryNode = findNode("Country");
341 const LocaleNode * variantNode = findNode("Variant");
343 OUString aLanguage;
345 if (languageNode)
347 aLanguage = languageNode->getChildAt(0)->getValue();
348 if (!(aLanguage.getLength() == 2 || aLanguage.getLength() == 3))
349 incErrorStr( "langID not 2-3 characters", aLanguage);
350 of.writeParameter("langID", aLanguage);
351 of.writeParameter("langDefaultName", languageNode->getChildAt(1)->getValue());
353 else
354 incError( "No Language node.");
355 if (countryNode)
357 OUString aCountry( countryNode->getChildAt(0)->getValue());
358 if (!(aCountry.isEmpty() || aCountry.getLength() == 2))
359 incErrorStr( "countryID not empty or more than 2 characters", aCountry);
360 of.writeParameter("countryID", aCountry);
361 of.writeParameter("countryDefaultName", countryNode->getChildAt(1)->getValue());
363 else
364 incError( "No Country node.");
365 if (variantNode)
367 // If given Variant must be at least ll-Ssss and language must be 'qlt'
368 OUString aVariant( variantNode->getValue());
369 if (!(aVariant.isEmpty() || (aVariant.getLength() >= 7 && aVariant.indexOf('-') >= 2)))
370 incErrorStr( "invalid Variant", aVariant);
371 if (!(aVariant.isEmpty() || aLanguage == "qlt"))
372 incErrorStrStr( "Variant '%s' given but Language '%s' is not 'qlt'", aVariant, aLanguage);
373 of.writeParameter("Variant", aVariant);
375 else
376 of.writeParameter("Variant", OUString());
377 of.writeAsciiString("\nstatic const sal_Unicode* LCInfoArray[] = {\n");
378 of.writeAsciiString("\tlangID,\n");
379 of.writeAsciiString("\tlangDefaultName,\n");
380 of.writeAsciiString("\tcountryID,\n");
381 of.writeAsciiString("\tcountryDefaultName,\n");
382 of.writeAsciiString("\tVariant\n");
383 of.writeAsciiString("};\n\n");
384 of.writeFunction("getLCInfo_", "0", "LCInfoArray");
388 static OUString aDateSep;
389 static OUString aDecSep;
391 void LCCTYPENode::generateCode (const OFileWriter &of) const
393 const LocaleNode * sepNode = 0;
394 OUString useLocale = getAttr().getValueByName("ref");
395 if (!useLocale.isEmpty()) {
396 useLocale = useLocale.replace( '-', '_');
397 of.writeRefFunction("getLocaleItem_", useLocale);
398 return;
400 OUString str = getAttr().getValueByName("unoid");
401 of.writeAsciiString("\n\n");
402 of.writeParameter("LC_CTYPE_Unoid", str);;
404 aDateSep =
405 writeParameterCheckLen( of, "DateSeparator", "dateSeparator", 1, 1);
406 OUString aThoSep =
407 writeParameterCheckLen( of, "ThousandSeparator", "thousandSeparator", 1, 1);
408 aDecSep =
409 writeParameterCheckLen( of, "DecimalSeparator", "decimalSeparator", 1, 1);
410 OUString aTimeSep =
411 writeParameterCheckLen( of, "TimeSeparator", "timeSeparator", 1, 1);
412 OUString aTime100Sep =
413 writeParameterCheckLen( of, "Time100SecSeparator", "time100SecSeparator", 1, 1);
414 OUString aListSep =
415 writeParameterCheckLen( of, "ListSeparator", "listSeparator", 1, 1);
417 OUString aLDS;
419 sepNode = findNode("LongDateDayOfWeekSeparator");
420 aLDS = sepNode->getValue();
421 of.writeParameter("LongDateDayOfWeekSeparator", aLDS);
422 if (aLDS == ",")
423 fprintf( stderr, "Warning: %s\n",
424 "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\".");
426 sepNode = findNode("LongDateDaySeparator");
427 aLDS = sepNode->getValue();
428 of.writeParameter("LongDateDaySeparator", aLDS);
429 if (aLDS == "," || aLDS == ".")
430 fprintf( stderr, "Warning: %s\n",
431 "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\".");
433 sepNode = findNode("LongDateMonthSeparator");
434 aLDS = sepNode->getValue();
435 of.writeParameter("LongDateMonthSeparator", aLDS);
436 if (aLDS.isEmpty())
437 fprintf( stderr, "Warning: %s\n",
438 "LongDateMonthSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, May9, 2007\".");
440 sepNode = findNode("LongDateYearSeparator");
441 aLDS = sepNode->getValue();
442 of.writeParameter("LongDateYearSeparator", aLDS);
443 if (aLDS.isEmpty())
444 fprintf( stderr, "Warning: %s\n",
445 "LongDateYearSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, 2007May 9\".");
448 int nSavErr = nError;
449 int nWarn = 0;
450 if (aDateSep == aTimeSep)
451 incError( "DateSeparator equals TimeSeparator.");
452 if (aDecSep == aThoSep)
453 incError( "DecimalSeparator equals ThousandSeparator.");
454 if ( aThoSep == " " )
455 incError( "ThousandSeparator is an ' ' ordinary space, this should be a non-breaking space U+00A0 instead.");
456 if (aListSep == aDecSep)
457 fprintf( stderr, "Warning: %s\n",
458 "ListSeparator equals DecimalSeparator.");
459 if (aListSep == aThoSep)
460 fprintf( stderr, "Warning: %s\n",
461 "ListSeparator equals ThousandSeparator.");
462 if (aListSep.getLength() != 1 || aListSep[0] != ';')
464 incError( "ListSeparator not ';' semicolon. Strongly recommended. Currently required.");
465 ++nSavErr; // format codes not affected
467 if (aTimeSep == aTime100Sep)
468 ++nWarn, fprintf( stderr, "Warning: %s\n",
469 "Time100SecSeparator equals TimeSeparator, this is probably an error.");
470 if (aDecSep != aTime100Sep)
471 ++nWarn, fprintf( stderr, "Warning: %s\n",
472 "Time100SecSeparator is different from DecimalSeparator, this may be correct or not. Intended?");
473 if (nSavErr != nError || nWarn)
474 fprintf( stderr, "Warning: %s\n",
475 "Don't forget to adapt corresponding FormatCode elements when changing separators.");
477 OUString aQuoteStart =
478 writeParameterCheckLen( of, "QuotationStart", "quotationStart", 1, 1);
479 OUString aQuoteEnd =
480 writeParameterCheckLen( of, "QuotationEnd", "quotationEnd", 1, 1);
481 OUString aDoubleQuoteStart =
482 writeParameterCheckLen( of, "DoubleQuotationStart", "doubleQuotationStart", 1, 1);
483 OUString aDoubleQuoteEnd =
484 writeParameterCheckLen( of, "DoubleQuotationEnd", "doubleQuotationEnd", 1, 1);
486 if (aQuoteStart.toChar() <= 127 && aQuoteEnd.toChar() > 127)
487 fprintf( stderr, "Warning: %s\n",
488 "QuotationStart is an ASCII character but QuotationEnd is not.");
489 if (aQuoteEnd.toChar() <= 127 && aQuoteStart.toChar() > 127)
490 fprintf( stderr, "Warning: %s\n",
491 "QuotationEnd is an ASCII character but QuotationStart is not.");
492 if (aDoubleQuoteStart.toChar() <= 127 && aDoubleQuoteEnd.toChar() > 127)
493 fprintf( stderr, "Warning: %s\n",
494 "DoubleQuotationStart is an ASCII character but DoubleQuotationEnd is not.");
495 if (aDoubleQuoteEnd.toChar() <= 127 && aDoubleQuoteStart.toChar() > 127)
496 fprintf( stderr, "Warning: %s\n",
497 "DoubleQuotationEnd is an ASCII character but DoubleQuotationStart is not.");
498 if (aQuoteStart.toChar() <= 127 && aQuoteEnd.toChar() <= 127)
499 fprintf( stderr, "Warning: %s\n",
500 "QuotationStart and QuotationEnd are both ASCII characters. Not necessarily an issue, but unusual.");
501 if (aDoubleQuoteStart.toChar() <= 127 && aDoubleQuoteEnd.toChar() <= 127)
502 fprintf( stderr, "Warning: %s\n",
503 "DoubleQuotationStart and DoubleQuotationEnd are both ASCII characters. Not necessarily an issue, but unusual.");
504 if (aQuoteStart == aQuoteEnd)
505 fprintf( stderr, "Warning: %s\n",
506 "QuotationStart equals QuotationEnd. Not necessarily an issue, but unusual.");
507 if (aDoubleQuoteStart == aDoubleQuoteEnd)
508 fprintf( stderr, "Warning: %s\n",
509 "DoubleQuotationStart equals DoubleQuotationEnd. Not necessarily an issue, but unusual.");
510 /* TODO: should equalness of single and double quotes be an error? Would
511 * need to adapt quite some locales' data. */
512 if (aQuoteStart == aDoubleQuoteStart)
513 fprintf( stderr, "Warning: %s\n",
514 "QuotationStart equals DoubleQuotationStart. Not necessarily an isue, but unusual.");
515 if (aQuoteEnd == aDoubleQuoteEnd)
516 fprintf( stderr, "Warning: %s\n",
517 "QuotationEnd equals DoubleQuotationEnd. Not necessarily an issue, but unusual.");
518 // Known good values, exclude ASCII single (U+0027, ') and double (U+0022, ") quotes.
519 int ic;
520 switch (ic = aQuoteStart.toChar())
522 case 0x2018: // LEFT SINGLE QUOTATION MARK
523 case 0x201a: // SINGLE LOW-9 QUOTATION MARK
524 case 0x201b: // SINGLE HIGH-REVERSED-9 QUOTATION MARK
525 case 0x2039: // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
526 case 0x203a: // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
527 case 0x300c: // LEFT CORNER BRACKET (Chinese)
529 break;
530 default:
531 fprintf( stderr, "Warning: %s U+%04X %s\n",
532 "QuotationStart may be wrong:", ic, OSTR( aQuoteStart));
534 switch (ic = aQuoteEnd.toChar())
536 case 0x2019: // RIGHT SINGLE QUOTATION MARK
537 case 0x201a: // SINGLE LOW-9 QUOTATION MARK
538 case 0x201b: // SINGLE HIGH-REVERSED-9 QUOTATION MARK
539 case 0x2039: // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
540 case 0x203a: // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
541 case 0x300d: // RIGHT CORNER BRACKET (Chinese)
543 break;
544 default:
545 fprintf( stderr, "Warning: %s U+%04X %s\n",
546 "QuotationEnd may be wrong:", ic, OSTR( aQuoteEnd));
548 switch (ic = aDoubleQuoteStart.toChar())
550 case 0x00ab: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
551 case 0x00bb: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
552 case 0x201c: // LEFT DOUBLE QUOTATION MARK
553 case 0x201e: // DOUBLE LOW-9 QUOTATION MARK
554 case 0x201f: // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
555 case 0x300e: // LEFT WHITE CORNER BRACKET (Chinese)
557 break;
558 default:
559 fprintf( stderr, "Warning: %s U+%04X %s\n",
560 "DoubleQuotationStart may be wrong:", ic, OSTR( aDoubleQuoteStart));
562 switch (ic = aDoubleQuoteEnd.toChar())
564 case 0x00ab: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
565 case 0x00bb: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
566 case 0x201d: // RIGHT DOUBLE QUOTATION MARK
567 case 0x201e: // DOUBLE LOW-9 QUOTATION MARK
568 case 0x201f: // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
569 case 0x300f: // RIGHT WHITE CORNER BRACKET (Chinese)
571 break;
572 default:
573 fprintf( stderr, "Warning: %s U+%04X %s\n",
574 "DoubleQuotationEnd may be wrong:", ic, OSTR( aDoubleQuoteEnd));
577 writeParameterCheckLen( of, "TimeAM", "timeAM", 1, -1);
578 writeParameterCheckLen( of, "TimePM", "timePM", 1, -1);
579 sepNode = findNode("MeasurementSystem");
580 of.writeParameter("measurementSystem", sepNode->getValue());
582 of.writeAsciiString("\nstatic const sal_Unicode* LCType[] = {\n");
583 of.writeAsciiString("\tLC_CTYPE_Unoid,\n");
584 of.writeAsciiString("\tdateSeparator,\n");
585 of.writeAsciiString("\tthousandSeparator,\n");
586 of.writeAsciiString("\tdecimalSeparator,\n");
587 of.writeAsciiString("\ttimeSeparator,\n");
588 of.writeAsciiString("\ttime100SecSeparator,\n");
589 of.writeAsciiString("\tlistSeparator,\n");
590 of.writeAsciiString("\tquotationStart,\n");
591 of.writeAsciiString("\tquotationEnd,\n");
592 of.writeAsciiString("\tdoubleQuotationStart,\n");
593 of.writeAsciiString("\tdoubleQuotationEnd,\n");
594 of.writeAsciiString("\ttimeAM,\n");
595 of.writeAsciiString("\ttimePM,\n");
596 of.writeAsciiString("\tmeasurementSystem,\n");
597 of.writeAsciiString("\tLongDateDayOfWeekSeparator,\n");
598 of.writeAsciiString("\tLongDateDaySeparator,\n");
599 of.writeAsciiString("\tLongDateMonthSeparator,\n");
600 of.writeAsciiString("\tLongDateYearSeparator\n");
601 of.writeAsciiString("};\n\n");
602 of.writeFunction("getLocaleItem_", "0", "LCType");
606 static OUString sTheCurrencyReplaceTo;
607 static OUString sTheCompatibleCurrency;
608 static OUString sTheDateEditFormat;
610 sal_Int16 LCFormatNode::mnSection = 0;
611 sal_Int16 LCFormatNode::mnFormats = 0;
613 void LCFormatNode::generateCode (const OFileWriter &of) const
615 if (mnSection >= 2)
616 incError("more than 2 LC_FORMAT sections");
618 ::std::vector< OUString > theDateAcceptancePatterns;
620 OUString str;
621 OUString strFrom( getAttr().getValueByName("replaceFrom"));
622 of.writeParameter("replaceFrom", strFrom, mnSection);
623 str = getAttr().getValueByName("replaceTo");
624 if (!strFrom.isEmpty() && str.isEmpty())
625 incErrorStr("replaceFrom=\"%s\" replaceTo=\"\" is empty replacement.", strFrom);
626 // Locale data generator inserts FFFF for LangID, we need to adapt that.
627 if (str.endsWithIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "-FFFF]")))
628 incErrorStr("replaceTo=\"%s\" needs FFFF to be adapted to the real LangID value.", str);
629 of.writeParameter("replaceTo", str, mnSection);
630 // Remember the replaceTo value for "[CURRENCY]" to check format codes.
631 if ( strFrom == "[CURRENCY]" )
632 sTheCurrencyReplaceTo = str;
633 // Remember the currency symbol if present.
634 if (str.startsWith( "[$" ))
636 sal_Int32 nHyphen = str.indexOf( '-');
637 if (nHyphen >= 3)
639 sTheCompatibleCurrency = str.copy( 2, nHyphen - 2);
643 OUString useLocale = getAttr().getValueByName("ref");
644 if (!useLocale.isEmpty())
646 useLocale = useLocale.replace( '-', '_');
647 switch (mnSection)
649 case 0:
650 of.writeRefFunction("getAllFormats0_", useLocale, "replaceTo0");
651 break;
652 case 1:
653 of.writeRefFunction("getAllFormats1_", useLocale, "replaceTo1");
654 break;
656 of.writeRefFunction("getDateAcceptancePatterns_", useLocale);
657 return;
660 sal_Int16 formatCount = mnFormats;
661 NameSet aMsgIdSet;
662 ValueSet aFormatIndexSet;
663 NameSet aDefaultsSet;
664 bool bCtypeIsRef = false;
666 for (sal_Int16 i = 0; i< getNumberOfChildren() ; i++, formatCount++)
668 LocaleNode * currNode = getChildAt (i);
669 if ( currNode->getName() == "DateAcceptancePattern" )
671 if (mnSection > 0)
672 incError( "DateAcceptancePattern only handled in LC_FORMAT, not LC_FORMAT_1");
673 else
674 theDateAcceptancePatterns.push_back( currNode->getValue());
675 --formatCount;
676 continue; // for
678 if ( currNode->getName() != "FormatElement" )
680 incErrorStr( "Undefined element in LC_FORMAT", currNode->getName());
681 --formatCount;
682 continue; // for
685 OUString aUsage;
686 OUString aType;
687 OUString aFormatIndex;
688 // currNode -> print();
689 const Attr &currNodeAttr = currNode->getAttr();
690 //printf ("getLen() = %d\n", currNode->getAttr().getLength());
692 str = currNodeAttr.getValueByName("msgid");
693 if (!aMsgIdSet.insert( str).second)
694 incErrorStr( "Duplicated msgid=\"%s\" in FormatElement.", str);
695 of.writeParameter("FormatKey", str, formatCount);
697 str = currNodeAttr.getValueByName("default");
698 bool bDefault = str == "true";
699 of.writeDefaultParameter("FormatElement", str, formatCount);
701 aType = currNodeAttr.getValueByName("type");
702 of.writeParameter("FormatType", aType, formatCount);
704 aUsage = currNodeAttr.getValueByName("usage");
705 of.writeParameter("FormatUsage", aUsage, formatCount);
707 aFormatIndex = currNodeAttr.getValueByName("formatindex");
708 sal_Int16 formatindex = (sal_Int16)aFormatIndex.toInt32();
709 if (!aFormatIndexSet.insert( formatindex).second)
710 incErrorInt( "Duplicated formatindex=\"%d\" in FormatElement.", formatindex);
711 of.writeIntParameter("Formatindex", formatCount, formatindex);
713 // Ensure only one default per usage and type.
714 if (bDefault)
716 OUString aKey( aUsage + OUString( ',') + aType);
717 if (!aDefaultsSet.insert( aKey).second)
719 OUString aStr( "Duplicated default for usage=\"");
720 aStr += aUsage;
721 aStr += "\" type=\"";
722 aStr += aType;
723 aStr += "\": formatindex=\"";
724 aStr += aFormatIndex;
725 aStr += "\".";
726 incError( aStr);
730 const LocaleNode * n = currNode -> findNode("FormatCode");
731 if (n)
733 of.writeParameter("FormatCode", n->getValue(), formatCount);
734 // Check separator usage for some FormatCode elements.
735 const LocaleNode* pCtype = 0;
736 switch (formatindex)
738 case cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY :
739 sTheDateEditFormat = n->getValue();
740 break;
741 case cssi::NumberFormatIndex::NUMBER_1000DEC2 : // #,##0.00
742 case cssi::NumberFormatIndex::TIME_MMSS00 : // MM:SS.00
743 case cssi::NumberFormatIndex::TIME_HH_MMSS00 : // [HH]:MM:SS.00
745 const LocaleNode* pRoot = getRoot();
746 if (!pRoot)
747 incError( "No root for FormatCode.");
748 else
750 pCtype = pRoot->findNode( "LC_CTYPE");
751 if (!pCtype)
752 incError( "No LC_CTYPE found for FormatCode.");
753 else
755 OUString aRef( pCtype->getAttr().getValueByName("ref"));
756 if (!aRef.isEmpty())
758 aRef = aRef.replace( '-', '_');
759 if (!bCtypeIsRef)
760 fprintf( stderr,
761 "Warning: Can't check separators used in FormatCode due to LC_CTYPE ref=\"%s\".\n"
762 "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",
763 OSTR( aRef));
764 bCtypeIsRef = true;
765 pCtype = 0;
770 break;
771 case cssi::NumberFormatIndex::CURRENCY_1000DEC2 :
772 // Remember the currency symbol if present.
774 sal_Int32 nStart;
775 if (sTheCompatibleCurrency.isEmpty() &&
776 ((nStart = n->getValue().indexOfAsciiL( "[$", 2)) >= 0))
778 OUString aCode( n->getValue());
779 sal_Int32 nHyphen = aCode.indexOf( '-', nStart);
780 if (nHyphen >= nStart + 3)
781 sTheCompatibleCurrency = aCode.copy( nStart + 2, nHyphen - nStart - 2);
784 // fallthru
785 case cssi::NumberFormatIndex::CURRENCY_1000INT :
786 case cssi::NumberFormatIndex::CURRENCY_1000INT_RED :
787 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_RED :
788 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_CCC :
789 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_DASHED :
790 // Currency formats should be something like [C]###0;-[C]###0
791 // and not parenthesized [C]###0;([C]###0) if not en_US.
792 if (strcmp( of.getLocale(), "en_US") != 0)
794 OUString aCode( n->getValue());
795 OUString aPar1( "0)");
796 OUString aPar2( "-)" );
797 OUString aPar3( " )" );
798 OUString aPar4( "])" );
799 if (aCode.indexOf( aPar1 ) > 0 || aCode.indexOf( aPar2 ) > 0 ||
800 aCode.indexOf( aPar3 ) > 0 || aCode.indexOf( aPar4 ) > 0)
801 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);
803 // Check if we have replaceTo for "[CURRENCY]" placeholder.
804 if (sTheCurrencyReplaceTo.isEmpty())
806 OUString aCode( n->getValue());
807 if (aCode.indexOfAsciiL( RTL_CONSTASCII_STRINGPARAM( "[CURRENCY]")) >= 0)
808 incErrorInt( "[CURRENCY] replaceTo not found for formatindex=\"%d\".", formatindex);
810 break;
812 if (pCtype)
814 int nSavErr = nError;
815 OUString aCode( n->getValue());
816 if (formatindex == cssi::NumberFormatIndex::NUMBER_1000DEC2)
818 sal_Int32 nDec = -1;
819 sal_Int32 nGrp = -1;
820 const LocaleNode* pSep = pCtype->findNode( "DecimalSeparator");
821 if (!pSep)
822 incError( "No DecimalSeparator found for FormatCode.");
823 else
825 nDec = aCode.indexOf( pSep->getValue());
826 if (nDec < 0)
827 incErrorInt( "DecimalSeparator not present in FormatCode formatindex=\"%d\".",
828 formatindex);
830 pSep = pCtype->findNode( "ThousandSeparator");
831 if (!pSep)
832 incError( "No ThousandSeparator found for FormatCode.");
833 else
835 nGrp = aCode.indexOf( pSep->getValue());
836 if (nGrp < 0)
837 incErrorInt( "ThousandSeparator not present in FormatCode formatindex=\"%d\".",
838 formatindex);
840 if (nDec >= 0 && nGrp >= 0 && nDec <= nGrp)
841 incErrorInt( "Ordering of ThousandSeparator and DecimalSeparator not correct in formatindex=\"%d\".",
842 formatindex);
844 if (formatindex == cssi::NumberFormatIndex::TIME_MMSS00 ||
845 formatindex == cssi::NumberFormatIndex::TIME_HH_MMSS00)
847 sal_Int32 nTime = -1;
848 sal_Int32 n100s = -1;
849 const LocaleNode* pSep = pCtype->findNode( "TimeSeparator");
850 if (!pSep)
851 incError( "No TimeSeparator found for FormatCode.");
852 else
854 nTime = aCode.indexOf( pSep->getValue());
855 if (nTime < 0)
856 incErrorInt( "TimeSeparator not present in FormatCode formatindex=\"%d\".",
857 formatindex);
859 pSep = pCtype->findNode( "Time100SecSeparator");
860 if (!pSep)
861 incError( "No Time100SecSeparator found for FormatCode.");
862 else
864 n100s = aCode.indexOf( pSep->getValue());
865 if (n100s < 0)
866 incErrorInt( "Time100SecSeparator not present in FormatCode formatindex=\"%d\".",
867 formatindex);
868 OUStringBuffer a100s( pSep->getValue());
869 a100s.appendAscii( "00");
870 n100s = aCode.indexOf( a100s.makeStringAndClear());
871 if (n100s < 0)
872 incErrorInt( "Time100SecSeparator+00 not present in FormatCode formatindex=\"%d\".",
873 formatindex);
875 if (n100s >= 0 && nTime >= 0 && n100s <= nTime)
876 incErrorInt( "Ordering of Time100SecSeparator and TimeSeparator not correct in formatindex=\"%d\".",
877 formatindex);
879 if (nSavErr != nError)
880 fprintf( stderr,
881 "Warning: formatindex=\"%d\",\"%d\",\"%d\" are the only FormatCode elements checked for separator usage, there may be others that have errors.\n",
882 int(cssi::NumberFormatIndex::NUMBER_1000DEC2),
883 int(cssi::NumberFormatIndex::TIME_MMSS00),
884 int(cssi::NumberFormatIndex::TIME_HH_MMSS00));
888 else
889 incError( "No FormatCode in FormatElement.");
890 n = currNode -> findNode("DefaultName");
891 if (n)
892 of.writeParameter("FormatDefaultName", n->getValue(), formatCount);
893 else
894 of.writeParameter("FormatDefaultName", OUString(), formatCount);
898 // Check presence of all required format codes only in first section
899 // LC_FORMAT, not in optional LC_FORMAT_1
900 if (mnSection == 0)
902 // 0..47 MUST be present, 48,49 MUST NOT be present
903 ValueSet::const_iterator aIter( aFormatIndexSet.begin());
904 for (sal_Int16 nNext = cssi::NumberFormatIndex::NUMBER_START;
905 nNext < cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES; ++nNext)
907 sal_Int16 nHere = ::std::min( ((aIter != aFormatIndexSet.end() ? *aIter :
908 cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES)),
909 cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES);
910 if (aIter != aFormatIndexSet.end()) ++aIter;
911 for ( ; nNext < nHere; ++nNext)
913 switch (nNext)
915 case cssi::NumberFormatIndex::FRACTION_1 :
916 case cssi::NumberFormatIndex::FRACTION_2 :
917 case cssi::NumberFormatIndex::BOOLEAN :
918 case cssi::NumberFormatIndex::TEXT :
919 // generated internally
920 break;
921 default:
922 incErrorInt( "FormatElement formatindex=\"%d\" not present.", nNext);
925 switch (nHere)
927 case cssi::NumberFormatIndex::BOOLEAN :
928 incErrorInt( "FormatElement formatindex=\"%d\" reserved for internal ``BOOLEAN''.", nNext);
929 break;
930 case cssi::NumberFormatIndex::TEXT :
931 incErrorInt( "FormatElement formatindex=\"%d\" reserved for internal ``@'' (TEXT).", nNext);
932 break;
933 default:
934 ; // nothing
939 of.writeAsciiString("\nstatic const sal_Int16 ");
940 of.writeAsciiString("FormatElementsCount");
941 of.writeInt(mnSection);
942 of.writeAsciiString(" = ");
943 of.writeInt( formatCount - mnFormats);
944 of.writeAsciiString(";\n");
945 of.writeAsciiString("static const sal_Unicode* ");
946 of.writeAsciiString("FormatElementsArray");
947 of.writeInt(mnSection);
948 of.writeAsciiString("[] = {\n");
949 for(sal_Int16 i = mnFormats; i < formatCount; i++) {
951 of.writeAsciiString("\t");
952 of.writeAsciiString("FormatCode");
953 of.writeInt(i);
954 of.writeAsciiString(",\n");
956 of.writeAsciiString("\t");
957 of.writeAsciiString("FormatDefaultName");
958 of.writeInt(i);
959 of.writeAsciiString(",\n");
961 of.writeAsciiString("\t");
962 of.writeAsciiString("FormatKey");
963 of.writeInt(i);
964 of.writeAsciiString(",\n");
966 of.writeAsciiString("\t");
967 of.writeAsciiString("FormatType");
968 of.writeInt(i);
969 of.writeAsciiString(",\n");
971 of.writeAsciiString("\t");
972 of.writeAsciiString("FormatUsage");
973 of.writeInt(i);
974 of.writeAsciiString(",\n");
976 of.writeAsciiString("\t");
977 of.writeAsciiString("Formatindex");
978 of.writeInt(i);
979 of.writeAsciiString(",\n");
982 of.writeAsciiString("\tdefaultFormatElement");
983 of.writeInt(i);
984 of.writeAsciiString(",\n");
986 of.writeAsciiString("};\n\n");
988 switch (mnSection)
990 case 0:
991 of.writeFunction("getAllFormats0_", "FormatElementsCount0", "FormatElementsArray0", "replaceFrom0", "replaceTo0");
992 break;
993 case 1:
994 of.writeFunction("getAllFormats1_", "FormatElementsCount1", "FormatElementsArray1", "replaceFrom1", "replaceTo1");
995 break;
998 mnFormats = mnFormats + formatCount;
1000 if (mnSection == 0)
1002 // Extract and add date acceptance pattern for full date, so we provide
1003 // at least one valid pattern, even if the number parser doesn't need
1004 // that one.
1005 /* XXX NOTE: only simple [...] modifier and "..." quotes detected and
1006 * ignored, not nested, no fancy stuff. */
1007 sal_Int32 nIndex = 0;
1008 // aDateSep can be empty if LC_CTYPE was a ref=..., determine from
1009 // FormatCode then.
1010 sal_uInt32 cDateSep = (aDateSep.isEmpty() ? 0 : aDateSep.iterateCodePoints( &nIndex));
1011 sal_uInt32 cDateSep2 = cDateSep;
1012 nIndex = 0;
1013 OUStringBuffer aPatternBuf(5);
1014 OUStringBuffer aPatternBuf2(5);
1015 sal_uInt8 nDetected = 0; // bits Y,M,D
1016 bool bInModifier = false;
1017 bool bQuoted = false;
1018 while (nIndex < sTheDateEditFormat.getLength() && nDetected < 7)
1020 sal_uInt32 cChar = sTheDateEditFormat.iterateCodePoints( &nIndex);
1021 if (bInModifier)
1023 if (cChar == ']')
1024 bInModifier = false;
1025 continue; // while
1027 if (bQuoted)
1029 if (cChar == '"')
1030 bQuoted = false;
1031 continue; // while
1033 switch (cChar)
1035 case 'Y':
1036 case 'y':
1037 if (!(nDetected & 4))
1039 aPatternBuf.append( 'Y');
1040 if (!aPatternBuf2.isEmpty())
1041 aPatternBuf2.append( 'Y');
1042 nDetected |= 4;
1044 break;
1045 case 'M':
1046 case 'm':
1047 if (!(nDetected & 2))
1049 aPatternBuf.append( 'M');
1050 if (!aPatternBuf2.isEmpty())
1051 aPatternBuf2.append( 'M');
1052 nDetected |= 2;
1054 break;
1055 case 'D':
1056 case 'd':
1057 if (!(nDetected & 1))
1059 aPatternBuf.append( 'D');
1060 if (!aPatternBuf2.isEmpty())
1061 aPatternBuf2.append( 'D');
1062 nDetected |= 1;
1064 break;
1065 case '[':
1066 bInModifier = true;
1067 break;
1068 case '"':
1069 bQuoted = true;
1070 break;
1071 case '\\':
1072 cChar = sTheDateEditFormat.iterateCodePoints( &nIndex);
1073 break;
1074 case '-':
1075 case '.':
1076 case '/':
1077 // There are locales that use an ISO 8601 edit format
1078 // regardless of what the date separator or other formats
1079 // say, for example hu-HU. Generalize this for all cases
1080 // where the used separator differs and is one of the known
1081 // separators and generate a second pattern with the
1082 // format's separator at the current position.
1083 cDateSep2 = cChar;
1084 // fallthru
1085 default:
1086 if (!cDateSep)
1087 cDateSep = cChar;
1088 if (!cDateSep2)
1089 cDateSep2 = cChar;
1090 if (cDateSep != cDateSep2 && aPatternBuf2.isEmpty())
1091 aPatternBuf2 = aPatternBuf;
1092 if (cChar == cDateSep || cChar == cDateSep2)
1093 aPatternBuf.append( OUString( &cDateSep, 1)); // always the defined separator
1094 if (cChar == cDateSep2 && !aPatternBuf2.isEmpty())
1095 aPatternBuf2.append( OUString( &cDateSep2, 1)); // always the format's separator
1096 break;
1097 // The localized legacy:
1098 case 'A':
1099 if (((nDetected & 7) == 3) || ((nDetected & 7) == 0))
1101 // es DD/MM/AAAA
1102 // fr JJ.MM.AAAA
1103 // it GG/MM/AAAA
1104 // fr_CA AAAA-MM-JJ
1105 aPatternBuf.append( 'Y');
1106 if (!aPatternBuf2.isEmpty())
1107 aPatternBuf2.append( 'Y');
1108 nDetected |= 4;
1110 break;
1111 case 'J':
1112 if (((nDetected & 7) == 0) || ((nDetected & 7) == 6))
1114 // fr JJ.MM.AAAA
1115 // fr_CA AAAA-MM-JJ
1116 aPatternBuf.append( 'D');
1117 if (!aPatternBuf2.isEmpty())
1118 aPatternBuf2.append( 'D');
1119 nDetected |= 1;
1121 else if ((nDetected & 7) == 3)
1123 // nl DD-MM-JJJJ
1124 // de TT.MM.JJJJ
1125 aPatternBuf.append( 'Y');
1126 if (!aPatternBuf2.isEmpty())
1127 aPatternBuf2.append( 'Y');
1128 nDetected |= 4;
1130 break;
1131 case 'T':
1132 if ((nDetected & 7) == 0)
1134 // de TT.MM.JJJJ
1135 aPatternBuf.append( 'D');
1136 if (!aPatternBuf2.isEmpty())
1137 aPatternBuf2.append( 'D');
1138 nDetected |= 1;
1140 break;
1141 case 'G':
1142 if ((nDetected & 7) == 0)
1144 // it GG/MM/AAAA
1145 aPatternBuf.append( 'D');
1146 if (!aPatternBuf2.isEmpty())
1147 aPatternBuf2.append( 'D');
1148 nDetected |= 1;
1150 break;
1151 case 'P':
1152 if ((nDetected & 7) == 0)
1154 // fi PP.KK.VVVV
1155 aPatternBuf.append( 'D');
1156 if (!aPatternBuf2.isEmpty())
1157 aPatternBuf2.append( 'D');
1158 nDetected |= 1;
1160 break;
1161 case 'K':
1162 if ((nDetected & 7) == 1)
1164 // fi PP.KK.VVVV
1165 aPatternBuf.append( 'M');
1166 if (!aPatternBuf2.isEmpty())
1167 aPatternBuf2.append( 'M');
1168 nDetected |= 2;
1170 break;
1171 case 'V':
1172 if ((nDetected & 7) == 3)
1174 // fi PP.KK.VVVV
1175 aPatternBuf.append( 'Y');
1176 if (!aPatternBuf2.isEmpty())
1177 aPatternBuf2.append( 'Y');
1178 nDetected |= 4;
1180 break;
1183 OUString aPattern( aPatternBuf.makeStringAndClear());
1184 if (((nDetected & 7) != 7) || aPattern.getLength() < 5)
1186 incErrorStr( "failed to extract full date acceptance pattern", aPattern);
1187 fprintf( stderr, " with DateSeparator '%s' from FormatCode '%s' (formatindex=\"%d\")\n",
1188 OSTR( OUString( cDateSep)), OSTR( sTheDateEditFormat),
1189 (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY);
1191 else
1193 fprintf( stderr, "Generated date acceptance pattern: '%s' from '%s' (formatindex=\"%d\" and defined DateSeparator '%s')\n",
1194 OSTR( aPattern), OSTR( sTheDateEditFormat),
1195 (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY,
1196 OSTR( OUString( cDateSep)));
1197 // Insert at front so full date pattern is first in checks.
1198 theDateAcceptancePatterns.insert( theDateAcceptancePatterns.begin(), aPattern);
1200 if (!aPatternBuf2.isEmpty())
1202 OUString aPattern2( aPatternBuf2.makeStringAndClear());
1203 if (aPattern2.getLength() < 5)
1205 incErrorStr( "failed to extract 2nd date acceptance pattern", aPattern2);
1206 fprintf( stderr, " with DateSeparator '%s' from FormatCode '%s' (formatindex=\"%d\")\n",
1207 OSTR( OUString( cDateSep2)), OSTR( sTheDateEditFormat),
1208 (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY);
1210 else
1212 fprintf( stderr, "Generated 2nd acceptance pattern: '%s' from '%s' (formatindex=\"%d\")\n",
1213 OSTR( aPattern2), OSTR( sTheDateEditFormat),
1214 (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY);
1215 theDateAcceptancePatterns.insert( theDateAcceptancePatterns.begin(), aPattern2);
1219 // Rudimentary check if a pattern interferes with decimal number.
1220 // But only if not inherited in which case we don't have aDecSep here.
1221 if (!aDecSep.isEmpty())
1223 nIndex = 0;
1224 sal_uInt32 cDecSep = aDecSep.iterateCodePoints( &nIndex);
1225 for (vector<OUString>::const_iterator aIt = theDateAcceptancePatterns.begin();
1226 aIt != theDateAcceptancePatterns.end(); ++aIt)
1228 if ((*aIt).getLength() == (cDecSep <= 0xffff ? 3 : 4))
1230 nIndex = 1;
1231 if ((*aIt).iterateCodePoints( &nIndex) == cDecSep)
1233 ++nError;
1234 fprintf( stderr, "Error: Date acceptance pattern '%s' matches decimal number '#%s#'\n",
1235 OSTR( *aIt), OSTR( aDecSep));
1241 // Check for duplicates.
1242 for (vector<OUString>::const_iterator aIt = theDateAcceptancePatterns.begin();
1243 aIt != theDateAcceptancePatterns.end(); ++aIt)
1245 for (vector<OUString>::iterator aComp = theDateAcceptancePatterns.begin();
1246 aComp != theDateAcceptancePatterns.end(); /*nop*/)
1248 if (aIt != aComp && *aIt == *aComp)
1250 incErrorStr( "Duplicated DateAcceptancePattern", *aComp);
1251 aComp = theDateAcceptancePatterns.erase( aComp);
1253 else
1254 ++aComp;
1258 sal_Int16 nbOfDateAcceptancePatterns = static_cast<sal_Int16>(theDateAcceptancePatterns.size());
1260 for (sal_Int16 i = 0; i < nbOfDateAcceptancePatterns; ++i)
1262 of.writeParameter("DateAcceptancePattern", theDateAcceptancePatterns[i], i);
1265 of.writeAsciiString("static const sal_Int16 DateAcceptancePatternsCount = ");
1266 of.writeInt( nbOfDateAcceptancePatterns);
1267 of.writeAsciiString(";\n");
1269 of.writeAsciiString("static const sal_Unicode* DateAcceptancePatternsArray[] = {\n");
1270 for (sal_Int16 i = 0; i < nbOfDateAcceptancePatterns; ++i)
1272 of.writeAsciiString("\t");
1273 of.writeAsciiString("DateAcceptancePattern");
1274 of.writeInt(i);
1275 of.writeAsciiString(",\n");
1277 of.writeAsciiString("};\n\n");
1279 of.writeFunction("getDateAcceptancePatterns_", "DateAcceptancePatternsCount", "DateAcceptancePatternsArray");
1282 ++mnSection;
1285 void LCCollationNode::generateCode (const OFileWriter &of) const
1287 OUString useLocale = getAttr().getValueByName("ref");
1288 if (!useLocale.isEmpty()) {
1289 useLocale = useLocale.replace( '-', '_');
1290 of.writeRefFunction("getCollatorImplementation_", useLocale);
1291 of.writeRefFunction("getCollationOptions_", useLocale);
1292 return;
1294 sal_Int16 nbOfCollations = 0;
1295 sal_Int16 nbOfCollationOptions = 0;
1296 sal_Int16 j;
1298 for ( j = 0; j < getNumberOfChildren(); j++ ) {
1299 LocaleNode * currNode = getChildAt (j);
1300 if( currNode->getName().equalsAscii("Collator") )
1302 OUString str;
1303 str = currNode->getAttr().getValueByName("unoid");
1304 of.writeParameter("CollatorID", str, j);
1305 str = currNode->getValue();
1306 of.writeParameter("CollatorRule", str, j);
1307 str = currNode -> getAttr().getValueByName("default");
1308 of.writeDefaultParameter("Collator", str, j);
1309 of.writeAsciiString("\n");
1311 nbOfCollations++;
1313 if( currNode->getName().equalsAscii("CollationOptions") )
1315 LocaleNode* pCollationOptions = currNode;
1316 nbOfCollationOptions = sal::static_int_cast<sal_Int16>( pCollationOptions->getNumberOfChildren() );
1317 for( sal_Int16 i=0; i<nbOfCollationOptions; i++ )
1319 of.writeParameter("collationOption", pCollationOptions->getChildAt( i )->getValue(), i );
1322 of.writeAsciiString("static const sal_Int16 nbOfCollationOptions = ");
1323 of.writeInt( nbOfCollationOptions );
1324 of.writeAsciiString(";\n\n");
1327 of.writeAsciiString("static const sal_Int16 nbOfCollations = ");
1328 of.writeInt(nbOfCollations);
1329 of.writeAsciiString(";\n\n");
1331 of.writeAsciiString("\nstatic const sal_Unicode* LCCollatorArray[] = {\n");
1332 for(j = 0; j < nbOfCollations; j++) {
1333 of.writeAsciiString("\tCollatorID");
1334 of.writeInt(j);
1335 of.writeAsciiString(",\n");
1337 of.writeAsciiString("\tdefaultCollator");
1338 of.writeInt(j);
1339 of.writeAsciiString(",\n");
1341 of.writeAsciiString("\tCollatorRule");
1342 of.writeInt(j);
1343 of.writeAsciiString(",\n");
1345 of.writeAsciiString("};\n\n");
1347 of.writeAsciiString("static const sal_Unicode* collationOptions[] = {");
1348 for( j=0; j<nbOfCollationOptions; j++ )
1350 of.writeAsciiString( "collationOption" );
1351 of.writeInt( j );
1352 of.writeAsciiString( ", " );
1354 of.writeAsciiString("NULL };\n");
1355 of.writeFunction("getCollatorImplementation_", "nbOfCollations", "LCCollatorArray");
1356 of.writeFunction("getCollationOptions_", "nbOfCollationOptions", "collationOptions");
1359 void LCSearchNode::generateCode (const OFileWriter &of) const
1361 OUString useLocale = getAttr().getValueByName("ref");
1362 if (!useLocale.isEmpty()) {
1363 useLocale = useLocale.replace( '-', '_');
1364 of.writeRefFunction("getSearchOptions_", useLocale);
1365 return;
1368 if( getNumberOfChildren() != 1 )
1370 ++nError;
1371 fprintf(
1372 stderr, "Error: LC_SEARCH: more than 1 child: %ld\n",
1373 sal::static_int_cast< long >(getNumberOfChildren()));
1375 sal_Int32 i;
1376 LocaleNode* pSearchOptions = getChildAt( 0 );
1377 sal_Int32 nSearchOptions = pSearchOptions->getNumberOfChildren();
1378 for( i=0; i<nSearchOptions; i++ )
1380 of.writeParameter("searchOption", pSearchOptions->getChildAt( i )->getValue(), sal::static_int_cast<sal_Int16>(i) );
1383 of.writeAsciiString("static const sal_Int16 nbOfSearchOptions = ");
1384 of.writeInt( sal::static_int_cast<sal_Int16>( nSearchOptions ) );
1385 of.writeAsciiString(";\n\n");
1387 of.writeAsciiString("static const sal_Unicode* searchOptions[] = {");
1388 for( i=0; i<nSearchOptions; i++ )
1390 of.writeAsciiString( "searchOption" );
1391 of.writeInt( sal::static_int_cast<sal_Int16>(i) );
1392 of.writeAsciiString( ", " );
1394 of.writeAsciiString("NULL };\n");
1395 of.writeFunction("getSearchOptions_", "nbOfSearchOptions", "searchOptions");
1398 void LCIndexNode::generateCode (const OFileWriter &of) const
1400 OUString useLocale = getAttr().getValueByName("ref");
1401 if (!useLocale.isEmpty()) {
1402 useLocale = useLocale.replace( '-', '_');
1403 of.writeRefFunction("getIndexAlgorithm_", useLocale);
1404 of.writeRefFunction("getUnicodeScripts_", useLocale);
1405 of.writeRefFunction("getFollowPageWords_", useLocale);
1406 return;
1408 sal_Int16 nbOfIndexs = 0;
1409 sal_Int16 nbOfUnicodeScripts = 0;
1410 sal_Int16 nbOfPageWords = 0;
1411 sal_Int16 i;
1412 for (i = 0; i< getNumberOfChildren();i++) {
1413 LocaleNode * currNode = getChildAt (i);
1414 if( currNode->getName().equalsAscii("IndexKey") )
1416 OUString str;
1417 str = currNode->getAttr().getValueByName("unoid");
1418 of.writeParameter("IndexID", str, nbOfIndexs);
1419 str = currNode->getAttr().getValueByName("module");
1420 of.writeParameter("IndexModule", str, nbOfIndexs);
1421 str = currNode->getValue();
1422 of.writeParameter("IndexKey", str, nbOfIndexs);
1423 str = currNode -> getAttr().getValueByName("default");
1424 of.writeDefaultParameter("Index", str, nbOfIndexs);
1425 str = currNode -> getAttr().getValueByName("phonetic");
1426 of.writeDefaultParameter("Phonetic", str, nbOfIndexs);
1427 of.writeAsciiString("\n");
1429 nbOfIndexs++;
1431 if( currNode->getName().equalsAscii("UnicodeScript") )
1433 of.writeParameter("unicodeScript", currNode->getValue(), nbOfUnicodeScripts );
1434 nbOfUnicodeScripts++;
1437 if( currNode->getName().equalsAscii("FollowPageWord") )
1439 of.writeParameter("followPageWord", currNode->getValue(), nbOfPageWords);
1440 nbOfPageWords++;
1443 of.writeAsciiString("static const sal_Int16 nbOfIndexs = ");
1444 of.writeInt(nbOfIndexs);
1445 of.writeAsciiString(";\n\n");
1447 of.writeAsciiString("\nstatic const sal_Unicode* IndexArray[] = {\n");
1448 for(i = 0; i < nbOfIndexs; i++) {
1449 of.writeAsciiString("\tIndexID");
1450 of.writeInt(i);
1451 of.writeAsciiString(",\n");
1453 of.writeAsciiString("\tIndexModule");
1454 of.writeInt(i);
1455 of.writeAsciiString(",\n");
1457 of.writeAsciiString("\tIndexKey");
1458 of.writeInt(i);
1459 of.writeAsciiString(",\n");
1461 of.writeAsciiString("\tdefaultIndex");
1462 of.writeInt(i);
1463 of.writeAsciiString(",\n");
1465 of.writeAsciiString("\tdefaultPhonetic");
1466 of.writeInt(i);
1467 of.writeAsciiString(",\n");
1469 of.writeAsciiString("};\n\n");
1471 of.writeAsciiString("static const sal_Int16 nbOfUnicodeScripts = ");
1472 of.writeInt( nbOfUnicodeScripts );
1473 of.writeAsciiString(";\n\n");
1475 of.writeAsciiString("static const sal_Unicode* UnicodeScriptArray[] = {");
1476 for( i=0; i<nbOfUnicodeScripts; i++ )
1478 of.writeAsciiString( "unicodeScript" );
1479 of.writeInt( i );
1480 of.writeAsciiString( ", " );
1482 of.writeAsciiString("NULL };\n\n");
1484 of.writeAsciiString("static const sal_Int16 nbOfPageWords = ");
1485 of.writeInt(nbOfPageWords);
1486 of.writeAsciiString(";\n\n");
1488 of.writeAsciiString("static const sal_Unicode* FollowPageWordArray[] = {\n");
1489 for(i = 0; i < nbOfPageWords; i++) {
1490 of.writeAsciiString("\tfollowPageWord");
1491 of.writeInt(i);
1492 of.writeAsciiString(",\n");
1494 of.writeAsciiString("\tNULL\n};\n\n");
1496 of.writeFunction("getIndexAlgorithm_", "nbOfIndexs", "IndexArray");
1497 of.writeFunction("getUnicodeScripts_", "nbOfUnicodeScripts", "UnicodeScriptArray");
1498 of.writeFunction("getFollowPageWords_", "nbOfPageWords", "FollowPageWordArray");
1502 static void lcl_writeAbbrFullNarrNames( const OFileWriter & of, const LocaleNode* currNode,
1503 const sal_Char* elementTag, sal_Int16 i, sal_Int16 j )
1505 OUString aAbbrName = currNode->getChildAt(1)->getValue();
1506 OUString aFullName = currNode->getChildAt(2)->getValue();
1507 OUString aNarrName;
1508 LocaleNode* p = (currNode->getNumberOfChildren() > 3 ? currNode->getChildAt(3) : 0);
1509 if ( p && p->getName() == "DefaultNarrowName" )
1510 aNarrName = p->getValue();
1511 else
1513 sal_Int32 nIndex = 0;
1514 sal_uInt32 nChar = aFullName.iterateCodePoints( &nIndex);
1515 aNarrName = OUString( &nChar, 1);
1517 of.writeParameter( elementTag, "DefaultAbbrvName", aAbbrName, i, j);
1518 of.writeParameter( elementTag, "DefaultFullName", aFullName, i, j);
1519 of.writeParameter( elementTag, "DefaultNarrowName", aNarrName, i, j);
1522 static void lcl_writeTabTagString( const OFileWriter & of, const sal_Char* pTag, const sal_Char* pStr )
1524 of.writeAsciiString("\t");
1525 of.writeAsciiString( pTag);
1526 of.writeAsciiString( pStr);
1529 static void lcl_writeTabTagStringNums( const OFileWriter & of,
1530 const sal_Char* pTag, const sal_Char* pStr, sal_Int16 i, sal_Int16 j )
1532 lcl_writeTabTagString( of, pTag, pStr);
1533 of.writeInt(i); of.writeInt(j); of.writeAsciiString(",\n");
1536 static void lcl_writeAbbrFullNarrArrays( const OFileWriter & of, sal_Int16 nCount,
1537 const sal_Char* elementTag, sal_Int16 i, bool bNarrow )
1539 if (nCount == 0)
1541 lcl_writeTabTagString( of, elementTag, "Ref");
1542 of.writeInt(i); of.writeAsciiString(",\n");
1543 lcl_writeTabTagString( of, elementTag, "RefName");
1544 of.writeInt(i); of.writeAsciiString(",\n");
1546 else
1548 for (sal_Int16 j = 0; j < nCount; j++)
1550 lcl_writeTabTagStringNums( of, elementTag, "ID", i, j);
1551 lcl_writeTabTagStringNums( of, elementTag, "DefaultAbbrvName", i, j);
1552 lcl_writeTabTagStringNums( of, elementTag, "DefaultFullName", i, j);
1553 if (bNarrow)
1554 lcl_writeTabTagStringNums( of, elementTag, "DefaultNarrowName", i, j);
1559 void LCCalendarNode::generateCode (const OFileWriter &of) const
1561 OUString useLocale = getAttr().getValueByName("ref");
1562 if (!useLocale.isEmpty()) {
1563 useLocale = useLocale.replace( '-', '_');
1564 of.writeRefFunction("getAllCalendars_", useLocale);
1565 return;
1567 sal_Int16 nbOfCalendars = sal::static_int_cast<sal_Int16>( getNumberOfChildren() );
1568 OUString str;
1569 sal_Int16 * nbOfDays = new sal_Int16[nbOfCalendars];
1570 sal_Int16 * nbOfMonths = new sal_Int16[nbOfCalendars];
1571 sal_Int16 * nbOfGenitiveMonths = new sal_Int16[nbOfCalendars];
1572 sal_Int16 * nbOfPartitiveMonths = new sal_Int16[nbOfCalendars];
1573 sal_Int16 * nbOfEras = new sal_Int16[nbOfCalendars];
1574 sal_Int16 j;
1575 sal_Int16 i;
1576 bool bHasGregorian = false;
1579 for ( i = 0; i < nbOfCalendars; i++) {
1580 LocaleNode * calNode = getChildAt (i);
1581 OUString calendarID = calNode -> getAttr().getValueByName("unoid");
1582 of.writeParameter( "calendarID", calendarID, i);
1583 bool bGregorian = calendarID == "gregorian";
1584 if (!bHasGregorian)
1585 bHasGregorian = bGregorian;
1586 str = calNode -> getAttr().getValueByName("default");
1587 of.writeDefaultParameter("Calendar", str, i);
1589 sal_Int16 nChild = 0;
1591 // Generate Days of Week
1592 const sal_Char *elementTag;
1593 LocaleNode * daysNode = NULL;
1594 OUString ref_name = calNode->getChildAt(nChild)->getAttr().getValueByName("ref");
1595 ref_name = ref_name.replace( '-', '_');
1596 if (!ref_name.isEmpty() && i > 0) {
1597 for (j = 0; j < i; j++) {
1598 str = getChildAt(j)->getAttr().getValueByName("unoid");
1599 if (str.equals(ref_name))
1600 daysNode = getChildAt(j)->getChildAt(0);
1603 if (!ref_name.isEmpty() && daysNode == NULL) {
1604 of.writeParameter("dayRef", OUString("ref"), i);
1605 of.writeParameter("dayRefName", ref_name, i);
1606 nbOfDays[i] = 0;
1607 } else {
1608 if (daysNode == NULL)
1609 daysNode = calNode -> getChildAt(nChild);
1610 nbOfDays[i] = sal::static_int_cast<sal_Int16>( daysNode->getNumberOfChildren() );
1611 if (bGregorian && nbOfDays[i] != 7)
1612 incErrorInt( "A Gregorian calendar must have 7 days per week, this one has %d", nbOfDays[i]);
1613 elementTag = "day";
1614 for (j = 0; j < nbOfDays[i]; j++) {
1615 LocaleNode *currNode = daysNode -> getChildAt(j);
1616 OUString dayID( currNode->getChildAt(0)->getValue());
1617 of.writeParameter("dayID", dayID, i, j);
1618 if ( j == 0 && bGregorian && dayID != "sun" )
1619 incError( "First day of a week of a Gregorian calendar must be <DayID>sun</DayID>");
1620 lcl_writeAbbrFullNarrNames( of, currNode, elementTag, i, j);
1623 ++nChild;
1625 // Generate Months of Year
1626 LocaleNode * monthsNode = NULL;
1627 ref_name = calNode->getChildAt(nChild)->getAttr().getValueByName("ref");
1628 ref_name = ref_name.replace( '-', '_');
1629 if (!ref_name.isEmpty() && i > 0) {
1630 for (j = 0; j < i; j++) {
1631 str = getChildAt(j)->getAttr().getValueByName("unoid");
1632 if (str.equals(ref_name))
1633 monthsNode = getChildAt(j)->getChildAt(1);
1636 if (!ref_name.isEmpty() && monthsNode == NULL) {
1637 of.writeParameter("monthRef", OUString("ref"), i);
1638 of.writeParameter("monthRefName", ref_name, i);
1639 nbOfMonths[i] = 0;
1640 } else {
1641 if (monthsNode == NULL)
1642 monthsNode = calNode -> getChildAt(nChild);
1643 nbOfMonths[i] = sal::static_int_cast<sal_Int16>( monthsNode->getNumberOfChildren() );
1644 if (bGregorian && nbOfMonths[i] != 12)
1645 incErrorInt( "A Gregorian calendar must have 12 months, this one has %d", nbOfMonths[i]);
1646 elementTag = "month";
1647 for (j = 0; j < nbOfMonths[i]; j++) {
1648 LocaleNode *currNode = monthsNode -> getChildAt(j);
1649 OUString monthID( currNode->getChildAt(0)->getValue());
1650 of.writeParameter("monthID", monthID, i, j);
1651 if ( j == 0 && bGregorian && monthID != "jan" )
1652 incError( "First month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1653 lcl_writeAbbrFullNarrNames( of, currNode, elementTag, i, j);
1656 ++nChild;
1658 // Generate genitive Months of Year
1659 // Optional, if not present fall back to month nouns.
1660 if ( calNode->getChildAt(nChild)->getName() != "GenitiveMonths" )
1661 --nChild;
1662 LocaleNode * genitiveMonthsNode = NULL;
1663 ref_name = calNode->getChildAt(nChild)->getAttr().getValueByName("ref");
1664 ref_name = ref_name.replace( '-', '_');
1665 if (!ref_name.isEmpty() && i > 0) {
1666 for (j = 0; j < i; j++) {
1667 str = getChildAt(j)->getAttr().getValueByName("unoid");
1668 if (str.equals(ref_name))
1669 genitiveMonthsNode = getChildAt(j)->getChildAt(1);
1672 if (!ref_name.isEmpty() && genitiveMonthsNode == NULL) {
1673 of.writeParameter("genitiveMonthRef", OUString("ref"), i);
1674 of.writeParameter("genitiveMonthRefName", ref_name, i);
1675 nbOfGenitiveMonths[i] = 0;
1676 } else {
1677 if (genitiveMonthsNode == NULL)
1678 genitiveMonthsNode = calNode -> getChildAt(nChild);
1679 nbOfGenitiveMonths[i] = sal::static_int_cast<sal_Int16>( genitiveMonthsNode->getNumberOfChildren() );
1680 if (bGregorian && nbOfGenitiveMonths[i] != 12)
1681 incErrorInt( "A Gregorian calendar must have 12 genitive months, this one has %d", nbOfGenitiveMonths[i]);
1682 elementTag = "genitiveMonth";
1683 for (j = 0; j < nbOfGenitiveMonths[i]; j++) {
1684 LocaleNode *currNode = genitiveMonthsNode -> getChildAt(j);
1685 OUString genitiveMonthID( currNode->getChildAt(0)->getValue());
1686 of.writeParameter("genitiveMonthID", genitiveMonthID, i, j);
1687 if ( j == 0 && bGregorian && genitiveMonthID != "jan" )
1688 incError( "First genitive month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1689 lcl_writeAbbrFullNarrNames( of, currNode, elementTag, i, j);
1692 ++nChild;
1694 // Generate partitive Months of Year
1695 // Optional, if not present fall back to genitive months, or nominative
1696 // months (nouns) if that isn't present either.
1697 if ( calNode->getChildAt(nChild)->getName() != "PartitiveMonths" )
1698 --nChild;
1699 LocaleNode * partitiveMonthsNode = NULL;
1700 ref_name = calNode->getChildAt(nChild)->getAttr().getValueByName("ref");
1701 ref_name = ref_name.replace( '-', '_');
1702 if (!ref_name.isEmpty() && i > 0) {
1703 for (j = 0; j < i; j++) {
1704 str = getChildAt(j)->getAttr().getValueByName("unoid");
1705 if (str.equals(ref_name))
1706 partitiveMonthsNode = getChildAt(j)->getChildAt(1);
1709 if (!ref_name.isEmpty() && partitiveMonthsNode == NULL) {
1710 of.writeParameter("partitiveMonthRef", OUString("ref"), i);
1711 of.writeParameter("partitiveMonthRefName", ref_name, i);
1712 nbOfPartitiveMonths[i] = 0;
1713 } else {
1714 if (partitiveMonthsNode == NULL)
1715 partitiveMonthsNode = calNode -> getChildAt(nChild);
1716 nbOfPartitiveMonths[i] = sal::static_int_cast<sal_Int16>( partitiveMonthsNode->getNumberOfChildren() );
1717 if (bGregorian && nbOfPartitiveMonths[i] != 12)
1718 incErrorInt( "A Gregorian calendar must have 12 partitive months, this one has %d", nbOfPartitiveMonths[i]);
1719 elementTag = "partitiveMonth";
1720 for (j = 0; j < nbOfPartitiveMonths[i]; j++) {
1721 LocaleNode *currNode = partitiveMonthsNode -> getChildAt(j);
1722 OUString partitiveMonthID( currNode->getChildAt(0)->getValue());
1723 of.writeParameter("partitiveMonthID", partitiveMonthID, i, j);
1724 if ( j == 0 && bGregorian && partitiveMonthID != "jan" )
1725 incError( "First partitive month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1726 lcl_writeAbbrFullNarrNames( of, currNode, elementTag, i, j);
1729 ++nChild;
1731 // Generate Era name
1732 LocaleNode * erasNode = NULL;
1733 ref_name = calNode -> getChildAt(nChild) ->getAttr().getValueByName("ref");
1734 ref_name = ref_name.replace( '-', '_');
1735 if (!ref_name.isEmpty() && i > 0) {
1736 for (j = 0; j < i; j++) {
1737 str = getChildAt(j)->getAttr().getValueByName("unoid");
1738 if (str.equals(ref_name))
1739 erasNode = getChildAt(j)->getChildAt(2);
1742 if (!ref_name.isEmpty() && erasNode == NULL) {
1743 of.writeParameter("eraRef", OUString("ref"), i);
1744 of.writeParameter("eraRefName", ref_name, i);
1745 nbOfEras[i] = 0;
1746 } else {
1747 if (erasNode == NULL)
1748 erasNode = calNode -> getChildAt(nChild);
1749 nbOfEras[i] = sal::static_int_cast<sal_Int16>( erasNode->getNumberOfChildren() );
1750 if (bGregorian && nbOfEras[i] != 2)
1751 incErrorInt( "A Gregorian calendar must have 2 eras, this one has %d", nbOfEras[i]);
1752 elementTag = "era";
1753 for (j = 0; j < nbOfEras[i]; j++) {
1754 LocaleNode *currNode = erasNode -> getChildAt(j);
1755 OUString eraID( currNode->getChildAt(0)->getValue());
1756 of.writeParameter("eraID", eraID, i, j);
1757 if ( j == 0 && bGregorian && eraID != "bc" )
1758 incError( "First era of a Gregorian calendar must be <EraID>bc</EraID>");
1759 if ( j == 1 && bGregorian && eraID != "ad" )
1760 incError( "Second era of a Gregorian calendar must be <EraID>ad</EraID>");
1761 of.writeAsciiString("\n");
1762 of.writeParameter(elementTag, "DefaultAbbrvName",currNode->getChildAt(1)->getValue() ,i, j);
1763 of.writeParameter(elementTag, "DefaultFullName",currNode->getChildAt(2)->getValue() , i, j);
1766 ++nChild;
1768 str = calNode->getChildAt(nChild)->getChildAt(0)->getValue();
1769 if (nbOfDays[i])
1771 for (j = 0; j < nbOfDays[i]; j++)
1773 LocaleNode *currNode = daysNode->getChildAt(j);
1774 OUString dayID( currNode->getChildAt(0)->getValue());
1775 if (str == dayID)
1776 break; // for
1778 if (j >= nbOfDays[i])
1779 incErrorStr( "<StartDayOfWeek> <DayID> must be one of the <DaysOfWeek>, but is", str);
1781 of.writeParameter("startDayOfWeek", str, i);
1782 ++nChild;
1784 str = calNode ->getChildAt(nChild)-> getValue();
1785 sal_Int16 nDays = sal::static_int_cast<sal_Int16>( str.toInt32() );
1786 if (nDays < 1 || (0 < nbOfDays[i] && nbOfDays[i] < nDays))
1787 incErrorInt( "Bad value of MinimalDaysInFirstWeek: %d, must be 1 <= value <= days_in_week", nDays);
1788 of.writeIntParameter("minimalDaysInFirstWeek", i, nDays);
1790 if (!bHasGregorian)
1791 fprintf( stderr, "Warning: %s\n", "No Gregorian calendar defined, are you sure?");
1793 of.writeAsciiString("static const sal_Int16 calendarsCount = ");
1794 of.writeInt(nbOfCalendars);
1795 of.writeAsciiString(";\n\n");
1797 of.writeAsciiString("static const sal_Unicode nbOfDays[] = {");
1798 for(i = 0; i < nbOfCalendars - 1; i++) {
1799 of.writeInt(nbOfDays[i]);
1800 of.writeAsciiString(", ");
1802 of.writeInt(nbOfDays[i]);
1803 of.writeAsciiString("};\n");
1805 of.writeAsciiString("static const sal_Unicode nbOfMonths[] = {");
1806 for(i = 0; i < nbOfCalendars - 1; i++) {
1807 of.writeInt(nbOfMonths[i]);
1808 of.writeAsciiString(", ");
1810 of.writeInt(nbOfMonths[i]);
1811 of.writeAsciiString("};\n");
1813 of.writeAsciiString("static const sal_Unicode nbOfGenitiveMonths[] = {");
1814 for(i = 0; i < nbOfCalendars - 1; i++) {
1815 of.writeInt(nbOfGenitiveMonths[i]);
1816 of.writeAsciiString(", ");
1818 of.writeInt(nbOfGenitiveMonths[i]);
1819 of.writeAsciiString("};\n");
1821 of.writeAsciiString("static const sal_Unicode nbOfPartitiveMonths[] = {");
1822 for(i = 0; i < nbOfCalendars - 1; i++) {
1823 of.writeInt(nbOfPartitiveMonths[i]);
1824 of.writeAsciiString(", ");
1826 of.writeInt(nbOfPartitiveMonths[i]);
1827 of.writeAsciiString("};\n");
1829 of.writeAsciiString("static const sal_Unicode nbOfEras[] = {");
1830 for(i = 0; i < nbOfCalendars - 1; i++) {
1831 of.writeInt(nbOfEras[i]);
1832 of.writeAsciiString(", ");
1834 of.writeInt(nbOfEras[i]);
1835 of.writeAsciiString("};\n");
1838 of.writeAsciiString("static const sal_Unicode* calendars[] = {\n");
1839 of.writeAsciiString("\tnbOfDays,\n");
1840 of.writeAsciiString("\tnbOfMonths,\n");
1841 of.writeAsciiString("\tnbOfGenitiveMonths,\n");
1842 of.writeAsciiString("\tnbOfPartitiveMonths,\n");
1843 of.writeAsciiString("\tnbOfEras,\n");
1844 for(i = 0; i < nbOfCalendars; i++) {
1845 of.writeAsciiString("\tcalendarID");
1846 of.writeInt(i);
1847 of.writeAsciiString(",\n");
1848 of.writeAsciiString("\tdefaultCalendar");
1849 of.writeInt(i);
1850 of.writeAsciiString(",\n");
1851 lcl_writeAbbrFullNarrArrays( of, nbOfDays[i], "day", i, true);
1852 lcl_writeAbbrFullNarrArrays( of, nbOfMonths[i], "month", i, true);
1853 lcl_writeAbbrFullNarrArrays( of, nbOfGenitiveMonths[i], "genitiveMonth", i, true);
1854 lcl_writeAbbrFullNarrArrays( of, nbOfPartitiveMonths[i], "partitiveMonth", i, true);
1855 lcl_writeAbbrFullNarrArrays( of, nbOfEras[i], "era", i, false /*noNarrow*/);
1856 of.writeAsciiString("\tstartDayOfWeek");of.writeInt(i); of.writeAsciiString(",\n");
1857 of.writeAsciiString("\tminimalDaysInFirstWeek");of.writeInt(i); of.writeAsciiString(",\n");
1860 of.writeAsciiString("};\n\n");
1861 of.writeFunction("getAllCalendars_", "calendarsCount", "calendars");
1863 delete []nbOfDays;
1864 delete []nbOfMonths;
1865 delete []nbOfGenitiveMonths;
1866 delete []nbOfPartitiveMonths;
1867 delete []nbOfEras;
1870 bool isIso4217( const OUString& rStr )
1872 const sal_Unicode* p = rStr.getStr();
1873 return rStr.getLength() == 3
1874 && 'A' <= p[0] && p[0] <= 'Z'
1875 && 'A' <= p[1] && p[1] <= 'Z'
1876 && 'A' <= p[2] && p[2] <= 'Z'
1880 void LCCurrencyNode :: generateCode (const OFileWriter &of) const
1882 OUString useLocale = getAttr().getValueByName("ref");
1883 if (!useLocale.isEmpty()) {
1884 useLocale = useLocale.replace( '-', '_');
1885 of.writeRefFunction("getAllCurrencies_", useLocale);
1886 return;
1888 sal_Int16 nbOfCurrencies = 0;
1889 OUString str;
1890 sal_Int16 i;
1892 bool bTheDefault= false;
1893 bool bTheCompatible = false;
1894 for ( i = 0; i < getNumberOfChildren(); i++,nbOfCurrencies++) {
1895 LocaleNode * currencyNode = getChildAt (i);
1896 str = currencyNode->getAttr().getValueByName("default");
1897 bool bDefault = of.writeDefaultParameter("Currency", str, nbOfCurrencies);
1898 str = currencyNode->getAttr().getValueByName("usedInCompatibleFormatCodes");
1899 bool bCompatible = of.writeDefaultParameter("CurrencyUsedInCompatibleFormatCodes", str, nbOfCurrencies);
1900 str = currencyNode->getAttr().getValueByName("legacyOnly");
1901 bool bLegacy = of.writeDefaultParameter("CurrencyLegacyOnly", str, nbOfCurrencies);
1902 if (bLegacy && (bDefault || bCompatible))
1903 incError( "Currency: if legacyOnly==true, both 'default' and 'usedInCompatibleFormatCodes' must be false.");
1904 if (bDefault)
1906 if (bTheDefault)
1907 incError( "Currency: more than one default currency.");
1908 bTheDefault = true;
1910 if (bCompatible)
1912 if (bTheCompatible)
1913 incError( "Currency: more than one currency flagged as usedInCompatibleFormatCodes.");
1914 bTheCompatible = true;
1916 str = currencyNode -> findNode ("CurrencyID") -> getValue();
1917 of.writeParameter("currencyID", str, nbOfCurrencies);
1918 // CurrencyID MUST be ISO 4217.
1919 if (!bLegacy && !isIso4217(str))
1920 incError( "CurrencyID is not ISO 4217");
1921 str = currencyNode -> findNode ("CurrencySymbol") -> getValue();
1922 of.writeParameter("currencySymbol", str, nbOfCurrencies);
1923 // Check if this currency really is the one used in number format
1924 // codes. In case of ref=... mechanisms it may be that TheCurrency
1925 // couldn't had been determined from the current locale (i.e. is
1926 // empty), silently assume the referred locale has things right.
1927 if (bCompatible && !sTheCompatibleCurrency.isEmpty() && sTheCompatibleCurrency != str)
1928 incErrorStrStr( "CurrencySymbol \"%s\" flagged as usedInCompatibleFormatCodes doesn't match \"%s\" determined from format codes.", str, sTheCompatibleCurrency);
1929 str = currencyNode -> findNode ("BankSymbol") -> getValue();
1930 of.writeParameter("bankSymbol", str, nbOfCurrencies);
1931 // BankSymbol currently must be ISO 4217. May change later if
1932 // application always uses CurrencyID instead of BankSymbol.
1933 if (!bLegacy && !isIso4217(str))
1934 incError( "BankSymbol is not ISO 4217");
1935 str = currencyNode -> findNode ("CurrencyName") -> getValue();
1936 of.writeParameter("currencyName", str, nbOfCurrencies);
1937 str = currencyNode -> findNode ("DecimalPlaces") -> getValue();
1938 sal_Int16 nDecimalPlaces = (sal_Int16)str.toInt32();
1939 of.writeIntParameter("currencyDecimalPlaces", nbOfCurrencies, nDecimalPlaces);
1940 of.writeAsciiString("\n");
1943 if (!bTheDefault)
1944 incError( "Currency: no default currency.");
1945 if (!bTheCompatible)
1946 incError( "Currency: no currency flagged as usedInCompatibleFormatCodes.");
1948 of.writeAsciiString("static const sal_Int16 currencyCount = ");
1949 of.writeInt(nbOfCurrencies);
1950 of.writeAsciiString(";\n\n");
1951 of.writeAsciiString("static const sal_Unicode* currencies[] = {\n");
1952 for(i = 0; i < nbOfCurrencies; i++) {
1953 of.writeAsciiString("\tcurrencyID");
1954 of.writeInt(i);
1955 of.writeAsciiString(",\n");
1956 of.writeAsciiString("\tcurrencySymbol");
1957 of.writeInt(i);
1958 of.writeAsciiString(",\n");
1959 of.writeAsciiString("\tbankSymbol");
1960 of.writeInt(i);
1961 of.writeAsciiString(",\n");
1962 of.writeAsciiString("\tcurrencyName");
1963 of.writeInt(i);
1964 of.writeAsciiString(",\n");
1965 of.writeAsciiString("\tdefaultCurrency");
1966 of.writeInt(i);
1967 of.writeAsciiString(",\n");
1968 of.writeAsciiString("\tdefaultCurrencyUsedInCompatibleFormatCodes");
1969 of.writeInt(i);
1970 of.writeAsciiString(",\n");
1971 of.writeAsciiString("\tcurrencyDecimalPlaces");
1972 of.writeInt(i);
1973 of.writeAsciiString(",\n");
1974 of.writeAsciiString("\tdefaultCurrencyLegacyOnly");
1975 of.writeInt(i);
1976 of.writeAsciiString(",\n");
1978 of.writeAsciiString("};\n\n");
1979 of.writeFunction("getAllCurrencies_", "currencyCount", "currencies");
1982 void LCTransliterationNode::generateCode (const OFileWriter &of) const
1984 OUString useLocale = getAttr().getValueByName("ref");
1985 if (!useLocale.isEmpty()) {
1986 useLocale = useLocale.replace( '-', '_');
1987 of.writeRefFunction("getTransliterations_", useLocale);
1988 return;
1990 sal_Int16 nbOfModules = 0;
1991 OUString str;
1992 sal_Int16 i;
1994 for ( i = 0; i < getNumberOfChildren(); i++,nbOfModules++) {
1995 LocaleNode * transNode = getChildAt (i);
1996 str = transNode->getAttr().getValueByIndex(0);
1997 of.writeParameter("Transliteration", str, nbOfModules);
1999 of.writeAsciiString("static const sal_Int16 nbOfTransliterations = ");
2000 of.writeInt(nbOfModules);
2001 of.writeAsciiString(";\n\n");
2003 of.writeAsciiString("\nstatic const sal_Unicode* LCTransliterationsArray[] = {\n");
2004 for( i = 0; i < nbOfModules; i++) {
2005 of.writeAsciiString("\tTransliteration");
2006 of.writeInt(i);
2007 of.writeAsciiString(",\n");
2009 of.writeAsciiString("};\n\n");
2010 of.writeFunction("getTransliterations_", "nbOfTransliterations", "LCTransliterationsArray");
2013 struct NameValuePair {
2014 const sal_Char *name;
2015 const sal_Char *value;
2017 static const NameValuePair ReserveWord[] = {
2018 { "trueWord", "true" },
2019 { "falseWord", "false" },
2020 { "quarter1Word", "1st quarter" },
2021 { "quarter2Word", "2nd quarter" },
2022 { "quarter3Word", "3rd quarter" },
2023 { "quarter4Word", "4th quarter" },
2024 { "aboveWord", "above" },
2025 { "belowWord", "below" },
2026 { "quarter1Abbreviation", "Q1" },
2027 { "quarter2Abbreviation", "Q2" },
2028 { "quarter3Abbreviation", "Q3" },
2029 { "quarter4Abbreviation", "Q4" }
2032 void LCMiscNode::generateCode (const OFileWriter &of) const
2034 OUString useLocale = getAttr().getValueByName("ref");
2035 if (!useLocale.isEmpty()) {
2036 useLocale = useLocale.replace( '-', '_');
2037 of.writeRefFunction("getForbiddenCharacters_", useLocale);
2038 of.writeRefFunction("getBreakIteratorRules_", useLocale);
2039 of.writeRefFunction("getReservedWords_", useLocale);
2040 return;
2042 const LocaleNode * reserveNode = findNode("ReservedWords");
2043 if (!reserveNode)
2044 incError( "No ReservedWords element."); // should not happen if validated..
2045 const LocaleNode * forbidNode = findNode("ForbiddenCharacters");
2046 const LocaleNode * breakNode = findNode("BreakIteratorRules");
2048 bool bEnglishLocale = (strncmp( of.getLocale(), "en_", 3) == 0);
2050 sal_Int16 nbOfWords = 0;
2051 OUString str;
2052 sal_Int16 i;
2054 for ( i = 0; i < sal_Int16(SAL_N_ELEMENTS(ReserveWord)); i++,nbOfWords++) {
2055 const LocaleNode * curNode = (reserveNode ? reserveNode->findNode(
2056 ReserveWord[i].name) : 0);
2057 if (!curNode)
2058 fprintf( stderr,
2059 "Warning: No %s in ReservedWords, using en_US default: \"%s\".\n",
2060 ReserveWord[i].name, ReserveWord[i].value);
2061 str = curNode ? curNode -> getValue() : OUString::createFromAscii(ReserveWord[i].value);
2062 if (str.isEmpty())
2064 ++nError;
2065 fprintf( stderr, "Error: No content for ReservedWords %s.\n", ReserveWord[i].name);
2067 of.writeParameter("ReservedWord", str, nbOfWords);
2068 // "true", ..., "below" trigger untranslated warning.
2069 if (!bEnglishLocale && curNode && (0 <= i && i <= 7) &&
2070 str.equalsIgnoreAsciiCaseAscii( ReserveWord[i].value))
2072 fprintf( stderr,
2073 "Warning: ReservedWord %s seems to be untranslated \"%s\".\n",
2074 ReserveWord[i].name, ReserveWord[i].value);
2077 of.writeAsciiString("static const sal_Int16 nbOfReservedWords = ");
2078 of.writeInt(nbOfWords);
2079 of.writeAsciiString(";\n\n");
2080 of.writeAsciiString("\nstatic const sal_Unicode* LCReservedWordsArray[] = {\n");
2081 for( i = 0; i < nbOfWords; i++) {
2082 of.writeAsciiString("\tReservedWord");
2083 of.writeInt(i);
2084 of.writeAsciiString(",\n");
2086 of.writeAsciiString("};\n\n");
2087 of.writeFunction("getReservedWords_", "nbOfReservedWords", "LCReservedWordsArray");
2089 if (forbidNode) {
2090 of.writeParameter( "forbiddenBegin", forbidNode -> getChildAt(0)->getValue());
2091 of.writeParameter( "forbiddenEnd", forbidNode -> getChildAt(1)->getValue());
2092 of.writeParameter( "hangingChars", forbidNode -> getChildAt(2)->getValue());
2093 } else {
2094 of.writeParameter( "forbiddenBegin", OUString());
2095 of.writeParameter( "forbiddenEnd", OUString());
2096 of.writeParameter( "hangingChars", OUString());
2098 of.writeAsciiString("\nstatic const sal_Unicode* LCForbiddenCharactersArray[] = {\n");
2099 of.writeAsciiString("\tforbiddenBegin,\n");
2100 of.writeAsciiString("\tforbiddenEnd,\n");
2101 of.writeAsciiString("\thangingChars\n");
2102 of.writeAsciiString("};\n\n");
2103 of.writeFunction("getForbiddenCharacters_", "3", "LCForbiddenCharactersArray");
2105 if (breakNode) {
2106 of.writeParameter( "EditMode", breakNode -> getChildAt(0)->getValue());
2107 of.writeParameter( "DictionaryMode", breakNode -> getChildAt(1)->getValue());
2108 of.writeParameter( "WordCountMode", breakNode -> getChildAt(2)->getValue());
2109 of.writeParameter( "CharacterMode", breakNode -> getChildAt(3)->getValue());
2110 of.writeParameter( "LineMode", breakNode -> getChildAt(4)->getValue());
2111 } else {
2112 of.writeParameter( "EditMode", OUString());
2113 of.writeParameter( "DictionaryMode", OUString());
2114 of.writeParameter( "WordCountMode", OUString());
2115 of.writeParameter( "CharacterMode", OUString());
2116 of.writeParameter( "LineMode", OUString());
2118 of.writeAsciiString("\nstatic const sal_Unicode* LCBreakIteratorRulesArray[] = {\n");
2119 of.writeAsciiString("\tEditMode,\n");
2120 of.writeAsciiString("\tDictionaryMode,\n");
2121 of.writeAsciiString("\tWordCountMode,\n");
2122 of.writeAsciiString("\tCharacterMode,\n");
2123 of.writeAsciiString("\tLineMode\n");
2124 of.writeAsciiString("};\n\n");
2125 of.writeFunction("getBreakIteratorRules_", "5", "LCBreakIteratorRulesArray");
2129 void LCNumberingLevelNode::generateCode (const OFileWriter &of) const
2131 of.writeAsciiString("// ---> ContinuousNumbering\n");
2132 OUString useLocale = getAttr().getValueByName("ref");
2133 if (!useLocale.isEmpty()) {
2134 useLocale = useLocale.replace( '-', '_');
2135 of.writeRefFunction2("getContinuousNumberingLevels_", useLocale);
2136 return;
2139 // hard code number of attributes per style.
2140 const int nAttributes = 5;
2141 const char* attr[ nAttributes ] = { "Prefix", "NumType", "Suffix", "Transliteration", "NatNum" };
2143 // record each attribute of each style in a static C++ variable.
2144 // determine number of styles on the fly.
2145 sal_Int32 nStyles = getNumberOfChildren();
2146 sal_Int32 i;
2148 for( i = 0; i < nStyles; ++i )
2150 const Attr &q = getChildAt( i )->getAttr();
2151 for( sal_Int32 j=0; j<nAttributes; ++j )
2153 const char* name = attr[j];
2154 OUString value = q.getValueByName( name );
2155 of.writeParameter("continuous", name, value, sal::static_int_cast<sal_Int16>(i) );
2159 // record number of styles and attributes.
2160 of.writeAsciiString("static const sal_Int16 continuousNbOfStyles = ");
2161 of.writeInt( sal::static_int_cast<sal_Int16>( nStyles ) );
2162 of.writeAsciiString(";\n\n");
2163 of.writeAsciiString("static const sal_Int16 continuousNbOfAttributesPerStyle = ");
2164 of.writeInt( nAttributes );
2165 of.writeAsciiString(";\n\n");
2167 // generate code. (intermediate arrays)
2168 for( i=0; i<nStyles; i++ )
2170 of.writeAsciiString("\nstatic const sal_Unicode* continuousStyle" );
2171 of.writeInt( sal::static_int_cast<sal_Int16>(i) );
2172 of.writeAsciiString("[] = {\n");
2173 for( sal_Int32 j=0; j<nAttributes; j++)
2175 of.writeAsciiString("\t");
2176 of.writeAsciiString( "continuous" );
2177 of.writeAsciiString( attr[j] );
2178 of.writeInt(sal::static_int_cast<sal_Int16>(i));
2179 of.writeAsciiString(",\n");
2181 of.writeAsciiString("\t0\n};\n\n");
2184 // generate code. (top-level array)
2185 of.writeAsciiString("\n");
2186 of.writeAsciiString("static const sal_Unicode** LCContinuousNumberingLevelsArray[] = {\n" );
2187 for( i=0; i<nStyles; i++ )
2189 of.writeAsciiString( "\t" );
2190 of.writeAsciiString( "continuousStyle" );
2191 of.writeInt( sal::static_int_cast<sal_Int16>(i) );
2192 of.writeAsciiString( ",\n");
2194 of.writeAsciiString("\t0\n};\n\n");
2195 of.writeFunction2("getContinuousNumberingLevels_", "continuousNbOfStyles",
2196 "continuousNbOfAttributesPerStyle", "LCContinuousNumberingLevelsArray");
2200 void LCOutlineNumberingLevelNode::generateCode (const OFileWriter &of) const
2202 of.writeAsciiString("// ---> OutlineNumbering\n");
2203 OUString useLocale = getAttr().getValueByName("ref");
2204 if (!useLocale.isEmpty()) {
2205 useLocale = useLocale.replace( '-', '_');
2206 of.writeRefFunction3("getOutlineNumberingLevels_", useLocale);
2207 return;
2210 // hardcode number of attributes per level
2211 const int nAttributes = 11;
2212 const char* attr[ nAttributes ] =
2214 "Prefix",
2215 "NumType",
2216 "Suffix",
2217 "BulletChar",
2218 "BulletFontName",
2219 "ParentNumbering",
2220 "LeftMargin",
2221 "SymbolTextDistance",
2222 "FirstLineOffset",
2223 "Transliteration",
2224 "NatNum",
2227 // record each attribute of each level of each style in a static C++ variable.
2228 // determine number of styles and number of levels per style on the fly.
2229 sal_Int32 nStyles = getNumberOfChildren();
2230 vector<sal_Int32> nLevels; // may be different for each style?
2231 for( sal_Int32 i = 0; i < nStyles; i++ )
2233 LocaleNode* p = getChildAt( i );
2234 nLevels.push_back( p->getNumberOfChildren() );
2235 for( sal_Int32 j=0; j<nLevels.back(); j++ )
2237 const Attr& q = p->getChildAt( j )->getAttr();
2238 for( sal_Int32 k=0; k<nAttributes; ++k )
2240 const char* name = attr[k];
2241 OUString value = q.getValueByName( name );
2242 of.writeParameter("outline", name, value,
2243 sal::static_int_cast<sal_Int16>(i),
2244 sal::static_int_cast<sal_Int16>(j) );
2249 // verify that each style has the same number of levels.
2250 for( size_t i=0; i<nLevels.size(); i++ )
2252 if( nLevels[0] != nLevels[i] )
2254 incError( "Numbering levels don't match.");
2258 // record number of attributes, levels, and styles.
2259 of.writeAsciiString("static const sal_Int16 outlineNbOfStyles = ");
2260 of.writeInt( sal::static_int_cast<sal_Int16>( nStyles ) );
2261 of.writeAsciiString(";\n\n");
2262 of.writeAsciiString("static const sal_Int16 outlineNbOfLevelsPerStyle = ");
2263 of.writeInt( sal::static_int_cast<sal_Int16>( nLevels.back() ) );
2264 of.writeAsciiString(";\n\n");
2265 of.writeAsciiString("static const sal_Int16 outlineNbOfAttributesPerLevel = ");
2266 of.writeInt( nAttributes );
2267 of.writeAsciiString(";\n\n");
2269 // too complicated for now...
2270 // of.writeAsciiString("static const sal_Int16 nbOfOutlineNumberingLevels[] = { ");
2271 // for( sal_Int32 j=0; j<nStyles; j++ )
2272 // {
2273 // of.writeInt( nLevels[j] );
2274 // of.writeAsciiString(", ");
2275 // }
2276 // of.writeAsciiString("};\n\n");
2279 for( sal_Int32 i=0; i<nStyles; i++ )
2281 for( sal_Int32 j=0; j<nLevels.back(); j++ )
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("Level");
2287 of.writeInt( sal::static_int_cast<sal_Int16>(j) );
2288 of.writeAsciiString("[] = { ");
2290 for( sal_Int32 k=0; k<nAttributes; k++ )
2292 of.writeAsciiString( "outline" );
2293 of.writeAsciiString( attr[k] );
2294 of.writeInt( sal::static_int_cast<sal_Int16>(i) );
2295 of.writeInt( sal::static_int_cast<sal_Int16>(j) );
2296 of.writeAsciiString(", ");
2298 of.writeAsciiString("NULL };\n");
2302 of.writeAsciiString("\n");
2305 for( sal_Int32 i=0; i<nStyles; i++ )
2307 of.writeAsciiString("static const sal_Unicode** outline");
2308 of.writeAsciiString( "Style" );
2309 of.writeInt( sal::static_int_cast<sal_Int16>(i) );
2310 of.writeAsciiString("[] = { ");
2312 for( sal_Int32 j=0; j<nLevels.back(); j++ )
2314 of.writeAsciiString("outlineStyle");
2315 of.writeInt( sal::static_int_cast<sal_Int16>(i) );
2316 of.writeAsciiString("Level");
2317 of.writeInt( sal::static_int_cast<sal_Int16>(j) );
2318 of.writeAsciiString(", ");
2320 of.writeAsciiString("NULL };\n");
2322 of.writeAsciiString("\n");
2324 of.writeAsciiString("static const sal_Unicode*** LCOutlineNumberingLevelsArray[] = {\n" );
2325 for( sal_Int32 i=0; i<nStyles; i++ )
2327 of.writeAsciiString( "\t" );
2328 of.writeAsciiString( "outlineStyle" );
2329 of.writeInt( sal::static_int_cast<sal_Int16>(i) );
2330 of.writeAsciiString(",\n");
2332 of.writeAsciiString("\tNULL\n};\n\n");
2333 of.writeFunction3("getOutlineNumberingLevels_", "outlineNbOfStyles", "outlineNbOfLevelsPerStyle",
2334 "outlineNbOfAttributesPerLevel", "LCOutlineNumberingLevelsArray");
2337 Attr::Attr (const Reference< XAttributeList > & attr) {
2338 sal_Int16 len = attr->getLength();
2339 name.realloc (len);
2340 value.realloc (len);
2341 for (sal_Int16 i =0; i< len;i++) {
2342 name[i] = attr->getNameByIndex(i);
2343 value[i] = attr -> getValueByIndex(i);
2347 const OUString& Attr::getValueByName (const sal_Char *str) const {
2348 static OUString empty;
2349 sal_Int32 len = name.getLength();
2350 for (sal_Int32 i = 0;i<len;i++)
2351 if (name[i].equalsAscii(str))
2352 return value[i];
2353 return empty;
2356 sal_Int32 Attr::getLength() const{
2357 return name.getLength();
2360 const OUString& Attr::getTypeByIndex (sal_Int32 idx) const {
2361 return name[idx];
2364 const OUString& Attr::getValueByIndex (sal_Int32 idx) const
2366 return value[idx];
2369 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */