LCOV - code coverage report
Current view: top level - i18npool/source/localedata - LocaleNode.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1278 1497 85.4 %
Date: 2015-06-13 12:38:46 Functions: 34 48 70.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include <stdio.h>
      21             : #include <stdlib.h>
      22             : #include <string.h>
      23             : #include <algorithm>
      24             : #include <iostream>
      25             : #include <set>
      26             : #include <vector>
      27             : 
      28             : #include <rtl/ustrbuf.hxx>
      29             : #include <sal/macros.h>
      30             : 
      31             : #include "LocaleNode.hxx"
      32             : #include <com/sun/star/i18n/NumberFormatIndex.hpp>
      33             : 
      34             : // NOTE: MUST match the Locale versionDTD attribute defined in data/locale.dtd
      35             : #define LOCALE_VERSION_DTD "2.0.3"
      36             : 
      37             : typedef ::std::set< OUString > NameSet;
      38             : typedef ::std::set< sal_Int16 > ValueSet;
      39             : 
      40             : namespace cssi = ::com::sun::star::i18n;
      41             : 
      42       51550 : LocaleNode::LocaleNode (const OUString& name, const Reference< XAttributeList > & attr)
      43             :     : aName(name)
      44             :     , aAttribs(attr)
      45             :     , parent(0)
      46             :     , children(0)
      47             :     , nChildren(0)
      48             :     , childArrSize(0)
      49       51550 :     , nError(0)
      50             : {
      51       51550 : }
      52             : 
      53       51550 : int LocaleNode::getError() const
      54             : {
      55       51550 :     int err = nError;
      56      102855 :     for (sal_Int32 i=0;i<nChildren;i++)
      57       51305 :         err += children[i]->getError();
      58       51550 :     return err;
      59             : }
      60             : 
      61           0 : void LocaleNode::print () const {
      62           0 :     printf ("<");
      63           0 :     OUString str (aName);
      64           0 :     for(sal_Int32 i = 0; i < str.getLength(); i++)
      65           0 :         printf( "%c", str[i]);
      66           0 :     printf (">\n");
      67           0 : }
      68             : 
      69           0 : void LocaleNode::printR () const {
      70           0 :     print();
      71           0 :     for (sal_Int32 i=0;i<nChildren;i++)
      72           0 :         children[i]->printR();
      73           0 :     printf ("\t");
      74           0 :     print();
      75           0 : }
      76             : 
      77       51305 : void LocaleNode::addChild ( LocaleNode * node) {
      78       51305 :     if (childArrSize <= nChildren) {
      79       18397 :         LocaleNode ** arrN = new LocaleNode*[childArrSize+10];
      80       43327 :         for (sal_Int32 i = 0; i<childArrSize; ++i)
      81       24930 :             arrN[i] = children[i];
      82       18397 :         delete [] children;
      83       18397 :         childArrSize += 10;
      84       18397 :         children = arrN;
      85             :     }
      86       51305 :     children[nChildren++] = node;
      87       51305 :     node->setParent (this);
      88       51305 : }
      89             : 
      90       51305 : void LocaleNode::setParent ( LocaleNode * node) {
      91       51305 :     parent = node;
      92       51305 : }
      93             : 
      94         483 : const LocaleNode* LocaleNode::getRoot() const
      95             : {
      96         483 :     const LocaleNode* pRoot = 0;
      97         483 :     const LocaleNode* pParent = this;
      98        1449 :     while ( (pParent = pParent->getParent()) != 0 )
      99         483 :         pRoot = pParent;
     100         483 :     return pRoot;
     101             : }
     102             : 
     103      108918 : const LocaleNode * LocaleNode::findNode ( const sal_Char *name) const {
     104      108918 :     if (aName.equalsAscii(name))
     105       16972 :         return this;
     106      155020 :     for (sal_Int32 i = 0; i< nChildren; i++)  {
     107       83724 :         const LocaleNode *n=children[i]->findNode(name);
     108       83724 :         if (n)
     109       20650 :             return n;
     110             :         }
     111       71296 :     return 0;
     112             : }
     113             : 
     114      151709 : LocaleNode::~LocaleNode()
     115             : {
     116      102855 :     for (sal_Int32 i=0; i < nChildren; ++i)
     117       51305 :         delete children[i];
     118       51550 :     delete [] children;
     119      100159 : }
     120             : 
     121       51550 : LocaleNode* LocaleNode::createNode (const OUString& name, const Reference< XAttributeList > & attr)
     122             : {
     123       51550 :     if ( name == "LC_INFO" )
     124         245 :         return new LCInfoNode (name,attr);
     125       51305 :     if ( name == "LC_CTYPE" )
     126         245 :         return new LCCTYPENode (name,attr);
     127       51060 :     if ( name == "LC_FORMAT" )
     128         245 :         return new LCFormatNode (name,attr);
     129       50815 :     if ( name == "LC_FORMAT_1" )
     130           1 :         return new LCFormatNode (name,attr);
     131       50814 :     if ( name == "LC_CALENDAR" )
     132         245 :         return new LCCalendarNode (name,attr);
     133       50569 :     if ( name == "LC_CURRENCY" )
     134         245 :         return new LCCurrencyNode (name,attr);
     135       50324 :     if ( name == "LC_TRANSLITERATION" )
     136         245 :         return new LCTransliterationNode (name,attr);
     137       50079 :     if ( name == "LC_COLLATION" )
     138         245 :         return new LCCollationNode (name,attr);
     139       49834 :     if ( name == "LC_INDEX" )
     140         245 :         return new LCIndexNode (name,attr);
     141       49589 :     if ( name == "LC_SEARCH" )
     142         245 :         return new LCSearchNode (name,attr);
     143       49344 :     if ( name == "LC_MISC" )
     144         245 :         return new LCMiscNode (name,attr);
     145       49099 :       if ( name == "LC_NumberingLevel" )
     146         245 :                 return new LCNumberingLevelNode (name, attr);
     147       48854 :       if ( name == "LC_OutLineNumberingLevel" )
     148         245 :                 return new LCOutlineNumberingLevelNode (name, attr);
     149             : 
     150       48609 :     return new LocaleNode(name,attr);
     151             : }
     152             : 
     153             : 
     154             : //   printf(" name: '%s'\n", p->getName().pData->buffer );
     155             : //   printf("value: '%s'\n", p->getValue().pData->buffer );
     156             : 
     157             : #define OSTR(s) (OUStringToOString( (s), RTL_TEXTENCODING_UTF8).getStr())
     158             : 
     159           0 : void print_OUString( const OUString& s )
     160             : {
     161           0 :     printf( "%s", OSTR(s));
     162           0 : }
     163             : 
     164           0 : bool is_empty_string( const OUString& s )
     165             : {
     166           0 :      return s.isEmpty() || s == "\n";
     167             : }
     168             : 
     169           0 : void print_indent( int depth )
     170             : {
     171           0 :      for( int i=0; i<depth; i++ ) printf("    ");
     172           0 : }
     173             : 
     174           0 : void print_color( int color )
     175             : {
     176           0 :      printf("\033[%dm", color);
     177           0 : }
     178             : 
     179           0 : void print_node( const LocaleNode* p, int depth=0 )
     180             : {
     181           0 :      if( !p ) return;
     182             : 
     183           0 :      print_indent( depth );
     184           0 :      printf("<");
     185           0 :      print_color(36);
     186           0 :      print_OUString( p->getName()  );
     187           0 :      print_color(0);
     188           0 :      const Attr& q = p->getAttr();
     189           0 :      for( sal_Int32 j = 0; j < q.getLength(); ++j )
     190             :      {
     191           0 :           printf(" ");
     192           0 :           print_color(33);
     193           0 :           print_OUString( q.getTypeByIndex(j) );
     194           0 :           print_color(0);
     195           0 :           printf("=");
     196           0 :           print_color(31);
     197           0 :           printf("'");
     198           0 :           print_OUString( q.getValueByIndex(j) );
     199           0 :           printf("'");
     200           0 :           print_color(0);
     201             :      }
     202           0 :      printf(">");
     203           0 :      printf("\n");
     204           0 :      if( !is_empty_string( p->getValue() ) )
     205             :      {
     206           0 :           print_indent( depth+1 );
     207           0 :           printf("value: ");
     208           0 :           print_color(31);
     209           0 :           printf("'");
     210           0 :           print_OUString( p->getValue() );
     211           0 :           printf("'");
     212           0 :           print_color(0);
     213           0 :           printf("\n");
     214             :      }
     215           0 :      for( sal_Int32 i=0; i<p->getNumberOfChildren(); i++ )
     216             :      {
     217           0 :           print_node( p->getChildAt(i), depth+1 );
     218             :      }
     219           0 :      print_indent( depth );
     220           0 :      printf("</");
     221           0 :      print_OUString( p->getName()  );
     222           0 :      printf(">");
     223           0 :      printf("\n");
     224             : }
     225             : 
     226         245 : void LocaleNode :: generateCode (const OFileWriter &of) const
     227             : {
     228         245 :     OUString aDTD = getAttr().getValueByName("versionDTD");
     229         245 :     if ( aDTD != LOCALE_VERSION_DTD )
     230             :     {
     231           0 :         ++nError;
     232           0 :         fprintf( stderr, "Error: Locale versionDTD is not %s, see comment in locale.dtd\n", LOCALE_VERSION_DTD);
     233             :     }
     234        3186 :     for (sal_Int32 i=0; i<nChildren;i++)
     235        3186 :         children[i]->generateCode (of);
     236             : //      print_node( this );
     237         245 : }
     238             : 
     239             : 
     240        2340 : OUString LocaleNode::writeParameterCheckLen( const OFileWriter &of,
     241             :         const char* pParameterName, const LocaleNode* pNode,
     242             :         sal_Int32 nMinLen, sal_Int32 nMaxLen ) const
     243             : {
     244        2340 :     OUString aVal;
     245        2340 :     if (pNode)
     246        2340 :         aVal = pNode->getValue();
     247             :     else
     248             :     {
     249           0 :         ++nError;
     250             :         fprintf( stderr, "Error: node NULL pointer for parameter %s.\n",
     251           0 :                 pParameterName);
     252             :     }
     253             :     // write empty data if error
     254        2340 :     of.writeParameter( pParameterName, aVal);
     255        2340 :     sal_Int32 nLen = aVal.getLength();
     256        2340 :     if (nLen < nMinLen)
     257             :     {
     258           0 :         ++nError;
     259             :         fprintf( stderr, "Error: less than %ld character%s (%ld) in %s '%s'.\n",
     260             :                 sal::static_int_cast< long >(nMinLen), (nMinLen > 1 ? "s" : ""),
     261             :                 sal::static_int_cast< long >(nLen),
     262           0 :                 (pNode ? OSTR( pNode->getName()) : ""),
     263           0 :                 OSTR( aVal));
     264             :     }
     265        2340 :     else if (nLen > nMaxLen && nMaxLen >= 0)
     266             :         fprintf( stderr,
     267             :                 "Warning: more than %ld character%s (%ld) in %s %s not supported by application.\n",
     268             :                 sal::static_int_cast< long >(nMaxLen), (nMaxLen > 1 ? "s" : ""),
     269             :                 sal::static_int_cast< long >(nLen),
     270           0 :                 (pNode ? OSTR( pNode->getName()) : ""),
     271           0 :                 OSTR( aVal));
     272        2340 :     return aVal;
     273             : }
     274             : 
     275             : 
     276        2340 : OUString LocaleNode::writeParameterCheckLen( const OFileWriter &of,
     277             :         const char* pNodeName, const char* pParameterName,
     278             :         sal_Int32 nMinLen, sal_Int32 nMaxLen ) const
     279             : {
     280        2340 :     OUString aVal;
     281        2340 :     const LocaleNode * pNode = findNode( pNodeName);
     282        2340 :     if (pNode)
     283        2340 :         aVal = writeParameterCheckLen( of, pParameterName, pNode, nMinLen, nMaxLen);
     284             :     else
     285             :     {
     286           0 :         ++nError;
     287           0 :         fprintf( stderr, "Error: node %s not found.\n", pNodeName);
     288             :         // write empty data if error
     289           0 :         of.writeParameter( pParameterName, aVal);
     290             :     }
     291        2340 :     return aVal;
     292             : }
     293             : 
     294           0 : void LocaleNode::incError( const char* pStr ) const
     295             : {
     296           0 :     ++nError;
     297           0 :     fprintf( stderr, "Error: %s\n", pStr);
     298           0 : }
     299             : 
     300           0 : void LocaleNode::incError( const OUString& rStr ) const
     301             : {
     302           0 :     incError( OSTR( rStr));
     303           0 : }
     304             : 
     305           0 : void LocaleNode::incErrorInt( const char* pStr, int nVal ) const
     306             : {
     307           0 :     ++nError;
     308           0 :     fprintf( stderr, pStr, nVal);
     309           0 : }
     310             : 
     311           0 : void LocaleNode::incErrorStr( const char* pStr, const OUString& rVal ) const
     312             : {
     313           0 :     ++nError;
     314           0 :     fprintf( stderr, pStr, OSTR( rVal));
     315           0 : }
     316             : 
     317           0 : void LocaleNode::incErrorStrStr( const char* pStr, const OUString& rVal1, const OUString& rVal2 ) const
     318             : {
     319           0 :     ++nError;
     320           0 :     fprintf(stderr, pStr, OSTR(rVal1), OSTR(rVal2));
     321           0 : }
     322             : 
     323         245 : void LCInfoNode::generateCode (const OFileWriter &of) const
     324             : {
     325             : 
     326         245 :     const LocaleNode * languageNode = findNode("Language");
     327         245 :     const LocaleNode * countryNode = findNode("Country");
     328         245 :     const LocaleNode * variantNode = findNode("Variant");
     329             : 
     330         245 :     OUString aLanguage;
     331             : 
     332         245 :     if (languageNode)
     333             :     {
     334         245 :         aLanguage = languageNode->getChildAt(0)->getValue();
     335         245 :         if (!(aLanguage.getLength() == 2 || aLanguage.getLength() == 3))
     336           0 :             incErrorStr( "Error: langID '%s' not 2-3 characters\n", aLanguage);
     337         245 :         of.writeParameter("langID", aLanguage);
     338         245 :         of.writeParameter("langDefaultName", languageNode->getChildAt(1)->getValue());
     339             :     }
     340             :     else
     341           0 :         incError( "No Language node.");
     342         245 :     if (countryNode)
     343             :     {
     344         245 :         OUString aCountry( countryNode->getChildAt(0)->getValue());
     345         245 :         if (!(aCountry.isEmpty() || aCountry.getLength() == 2))
     346           0 :             incErrorStr( "Error: countryID '%s' not empty or more than 2 characters\n", aCountry);
     347         245 :         of.writeParameter("countryID", aCountry);
     348         245 :         of.writeParameter("countryDefaultName", countryNode->getChildAt(1)->getValue());
     349             :     }
     350             :     else
     351           0 :         incError( "No Country node.");
     352         245 :     if (variantNode)
     353             :     {
     354             :         // If given Variant must be at least ll-Ssss and language must be 'qlt'
     355           7 :         OUString aVariant( variantNode->getValue());
     356           7 :         if (!(aVariant.isEmpty() || (aVariant.getLength() >= 7 && aVariant.indexOf('-') >= 2)))
     357           0 :             incErrorStr( "Error: invalid Variant '%s'\n", aVariant);
     358           7 :         if (!(aVariant.isEmpty() || aLanguage == "qlt"))
     359           0 :             incErrorStrStr( "Error: Variant '%s' given but Language '%s' is not 'qlt'\n", aVariant, aLanguage);
     360           7 :         of.writeParameter("Variant", aVariant);
     361             :     }
     362             :     else
     363         238 :         of.writeParameter("Variant", OUString());
     364         245 :     of.writeAsciiString("\nstatic const sal_Unicode* LCInfoArray[] = {\n");
     365         245 :     of.writeAsciiString("\tlangID,\n");
     366         245 :     of.writeAsciiString("\tlangDefaultName,\n");
     367         245 :     of.writeAsciiString("\tcountryID,\n");
     368         245 :     of.writeAsciiString("\tcountryDefaultName,\n");
     369         245 :     of.writeAsciiString("\tVariant\n");
     370         245 :     of.writeAsciiString("};\n\n");
     371         245 :     of.writeFunction("getLCInfo_", "0", "LCInfoArray");
     372         245 : }
     373             : 
     374             : 
     375         245 : static OUString aDateSep;
     376         245 : static OUString aDecSep;
     377             : 
     378         245 : void LCCTYPENode::generateCode (const OFileWriter &of) const
     379             : {
     380         245 :     const LocaleNode * sepNode = 0;
     381         245 :     OUString useLocale =   getAttr().getValueByName("ref");
     382         245 :     if (!useLocale.isEmpty()) {
     383          50 :         useLocale = useLocale.replace( '-', '_');
     384          50 :         of.writeRefFunction("getLocaleItem_", useLocale);
     385         295 :         return;
     386             :     }
     387         390 :     OUString str =   getAttr().getValueByName("unoid");
     388         195 :     of.writeAsciiString("\n\n");
     389         195 :     of.writeParameter("LC_CTYPE_Unoid", str);
     390             : 
     391         390 :     aDateSep =
     392         195 :         writeParameterCheckLen( of, "DateSeparator", "dateSeparator", 1, 1);
     393             :     OUString aThoSep =
     394         390 :         writeParameterCheckLen( of, "ThousandSeparator", "thousandSeparator", 1, 1);
     395         390 :     aDecSep =
     396         195 :         writeParameterCheckLen( of, "DecimalSeparator", "decimalSeparator", 1, 1);
     397             :     OUString aTimeSep =
     398         390 :         writeParameterCheckLen( of, "TimeSeparator", "timeSeparator", 1, 1);
     399             :     OUString aTime100Sep =
     400         390 :         writeParameterCheckLen( of, "Time100SecSeparator", "time100SecSeparator", 1, 1);
     401             :     OUString aListSep =
     402         390 :         writeParameterCheckLen( of, "ListSeparator", "listSeparator", 1, 1);
     403             : 
     404         390 :     OUString aLDS;
     405             : 
     406         195 :     sepNode = findNode("LongDateDayOfWeekSeparator");
     407         195 :     aLDS = sepNode->getValue();
     408         195 :     of.writeParameter("LongDateDayOfWeekSeparator", aLDS);
     409         195 :     if (aLDS == ",")
     410             :         fprintf( stderr, "Warning: %s\n",
     411           0 :                 "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\".");
     412             : 
     413         195 :     sepNode = findNode("LongDateDaySeparator");
     414         195 :     aLDS = sepNode->getValue();
     415         195 :     of.writeParameter("LongDateDaySeparator", aLDS);
     416         195 :     if (aLDS == "," || aLDS == ".")
     417             :         fprintf( stderr, "Warning: %s\n",
     418           9 :                 "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\".");
     419             : 
     420         195 :     sepNode = findNode("LongDateMonthSeparator");
     421         195 :     aLDS = sepNode->getValue();
     422         195 :     of.writeParameter("LongDateMonthSeparator", aLDS);
     423         195 :     if (aLDS.isEmpty())
     424             :         fprintf( stderr, "Warning: %s\n",
     425           0 :                 "LongDateMonthSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, May9, 2007\".");
     426             : 
     427         195 :     sepNode = findNode("LongDateYearSeparator");
     428         195 :     aLDS = sepNode->getValue();
     429         195 :     of.writeParameter("LongDateYearSeparator", aLDS);
     430         195 :     if (aLDS.isEmpty())
     431             :         fprintf( stderr, "Warning: %s\n",
     432           2 :                 "LongDateYearSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, 2007May 9\".");
     433             : 
     434             : 
     435         195 :     int nSavErr = nError;
     436         195 :     int nWarn = 0;
     437         195 :     if (aDateSep == aTimeSep)
     438           0 :         incError( "DateSeparator equals TimeSeparator.");
     439         195 :     if (aDecSep == aThoSep)
     440           0 :         incError( "DecimalSeparator equals ThousandSeparator.");
     441         195 :     if ( aThoSep == " " )
     442           0 :         incError( "ThousandSeparator is an ' ' ordinary space, this should be a non-breaking space U+00A0 instead.");
     443         195 :     if (aListSep == aDecSep)
     444             :         fprintf( stderr, "Warning: %s\n",
     445           0 :                 "ListSeparator equals DecimalSeparator.");
     446         195 :     if (aListSep == aThoSep)
     447             :         fprintf( stderr, "Warning: %s\n",
     448           0 :                 "ListSeparator equals ThousandSeparator.");
     449         195 :     if (aListSep.getLength() != 1 || aListSep[0] != ';')
     450             :     {
     451           0 :         incError( "ListSeparator not ';' semicolon. Strongly recommended. Currently required.");
     452           0 :         ++nSavErr;  // format codes not affected
     453             :     }
     454         195 :     if (aTimeSep == aTime100Sep)
     455             :         ++nWarn, fprintf( stderr, "Warning: %s\n",
     456           0 :                 "Time100SecSeparator equals TimeSeparator, this is probably an error.");
     457         195 :     if (aDecSep != aTime100Sep)
     458             :         ++nWarn, fprintf( stderr, "Warning: %s\n",
     459           7 :                 "Time100SecSeparator is different from DecimalSeparator, this may be correct or not. Intended?");
     460         195 :     if (nSavErr != nError || nWarn)
     461             :         fprintf( stderr, "Warning: %s\n",
     462           7 :                 "Don't forget to adapt corresponding FormatCode elements when changing separators.");
     463             : 
     464             :     OUString aQuoteStart =
     465         390 :         writeParameterCheckLen( of, "QuotationStart", "quotationStart", 1, 1);
     466             :     OUString aQuoteEnd =
     467         390 :         writeParameterCheckLen( of, "QuotationEnd", "quotationEnd", 1, 1);
     468             :     OUString aDoubleQuoteStart =
     469         390 :         writeParameterCheckLen( of, "DoubleQuotationStart", "doubleQuotationStart", 1, 1);
     470             :     OUString aDoubleQuoteEnd =
     471         390 :         writeParameterCheckLen( of, "DoubleQuotationEnd", "doubleQuotationEnd", 1, 1);
     472             : 
     473         195 :     if (aQuoteStart.toChar() <= 127 && aQuoteEnd.toChar() > 127)
     474             :         fprintf( stderr, "Warning: %s\n",
     475           0 :                 "QuotationStart is an ASCII character but QuotationEnd is not.");
     476         195 :     if (aQuoteEnd.toChar() <= 127 && aQuoteStart.toChar() > 127)
     477             :         fprintf( stderr, "Warning: %s\n",
     478           0 :                 "QuotationEnd is an ASCII character but QuotationStart is not.");
     479         195 :     if (aDoubleQuoteStart.toChar() <= 127 && aDoubleQuoteEnd.toChar() > 127)
     480             :         fprintf( stderr, "Warning: %s\n",
     481           2 :                 "DoubleQuotationStart is an ASCII character but DoubleQuotationEnd is not.");
     482         195 :     if (aDoubleQuoteEnd.toChar() <= 127 && aDoubleQuoteStart.toChar() > 127)
     483             :         fprintf( stderr, "Warning: %s\n",
     484           0 :                 "DoubleQuotationEnd is an ASCII character but DoubleQuotationStart is not.");
     485         195 :     if (aQuoteStart.toChar() <= 127 && aQuoteEnd.toChar() <= 127)
     486             :         fprintf( stderr, "Warning: %s\n",
     487          13 :                 "QuotationStart and QuotationEnd are both ASCII characters. Not necessarily an issue, but unusual.");
     488         195 :     if (aDoubleQuoteStart.toChar() <= 127 && aDoubleQuoteEnd.toChar() <= 127)
     489             :         fprintf( stderr, "Warning: %s\n",
     490          19 :                 "DoubleQuotationStart and DoubleQuotationEnd are both ASCII characters. Not necessarily an issue, but unusual.");
     491         195 :     if (aQuoteStart == aQuoteEnd)
     492             :         fprintf( stderr, "Warning: %s\n",
     493          22 :                 "QuotationStart equals QuotationEnd. Not necessarily an issue, but unusual.");
     494         195 :     if (aDoubleQuoteStart == aDoubleQuoteEnd)
     495             :         fprintf( stderr, "Warning: %s\n",
     496          25 :                 "DoubleQuotationStart equals DoubleQuotationEnd. Not necessarily an issue, but unusual.");
     497             :     /* TODO: should equalness of single and double quotes be an error? Would
     498             :      * need to adapt quite some locales' data. */
     499         195 :     if (aQuoteStart == aDoubleQuoteStart)
     500             :         fprintf( stderr, "Warning: %s\n",
     501           1 :                 "QuotationStart equals DoubleQuotationStart. Not necessarily an isue, but unusual.");
     502         195 :     if (aQuoteEnd == aDoubleQuoteEnd)
     503             :         fprintf( stderr, "Warning: %s\n",
     504           1 :                 "QuotationEnd equals DoubleQuotationEnd. Not necessarily an issue, but unusual.");
     505             :     // Known good values, exclude ASCII single (U+0027, ') and double (U+0022, ") quotes.
     506             :     int ic;
     507         195 :     switch (ic = aQuoteStart.toChar())
     508             :     {
     509             :         case 0x2018:    // LEFT SINGLE QUOTATION MARK
     510             :         case 0x201a:    // SINGLE LOW-9 QUOTATION MARK
     511             :         case 0x201b:    // SINGLE HIGH-REVERSED-9 QUOTATION MARK
     512             :         case 0x2039:    // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
     513             :         case 0x203a:    // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
     514             :         case 0x300c:    // LEFT CORNER BRACKET (Chinese)
     515             :             ;
     516         145 :             break;
     517             :         default:
     518             :             fprintf( stderr, "Warning: %s U+%04X %s\n",
     519          50 :                     "QuotationStart may be wrong:", ic, OSTR( aQuoteStart));
     520             :     }
     521         195 :     switch (ic = aQuoteEnd.toChar())
     522             :     {
     523             :         case 0x2019:    // RIGHT SINGLE QUOTATION MARK
     524             :         case 0x201a:    // SINGLE LOW-9 QUOTATION MARK
     525             :         case 0x201b:    // SINGLE HIGH-REVERSED-9 QUOTATION MARK
     526             :         case 0x2039:    // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
     527             :         case 0x203a:    // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
     528             :         case 0x300d:    // RIGHT CORNER BRACKET (Chinese)
     529             :             ;
     530         140 :             break;
     531             :         default:
     532             :             fprintf( stderr, "Warning: %s U+%04X %s\n",
     533          55 :                     "QuotationEnd may be wrong:", ic, OSTR( aQuoteEnd));
     534             :     }
     535         195 :     switch (ic = aDoubleQuoteStart.toChar())
     536             :     {
     537             :         case 0x00ab:    // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
     538             :         case 0x00bb:    // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
     539             :         case 0x201c:    // LEFT DOUBLE QUOTATION MARK
     540             :         case 0x201e:    // DOUBLE LOW-9 QUOTATION MARK
     541             :         case 0x201f:    // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
     542             :         case 0x300e:    // LEFT WHITE CORNER BRACKET (Chinese)
     543             :             ;
     544         158 :             break;
     545             :         default:
     546             :             fprintf( stderr, "Warning: %s U+%04X %s\n",
     547          37 :                     "DoubleQuotationStart may be wrong:", ic, OSTR( aDoubleQuoteStart));
     548             :     }
     549         195 :     switch (ic = aDoubleQuoteEnd.toChar())
     550             :     {
     551             :         case 0x00ab:    // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
     552             :         case 0x00bb:    // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
     553             :         case 0x201d:    // RIGHT DOUBLE QUOTATION MARK
     554             :         case 0x201e:    // DOUBLE LOW-9 QUOTATION MARK
     555             :         case 0x201f:    // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
     556             :         case 0x300f:    // RIGHT WHITE CORNER BRACKET (Chinese)
     557             :             ;
     558         148 :             break;
     559             :         default:
     560             :             fprintf( stderr, "Warning: %s U+%04X %s\n",
     561          47 :                     "DoubleQuotationEnd may be wrong:", ic, OSTR( aDoubleQuoteEnd));
     562             :     }
     563             : 
     564         195 :     writeParameterCheckLen( of, "TimeAM", "timeAM", 1, -1);
     565         195 :     writeParameterCheckLen( of, "TimePM", "timePM", 1, -1);
     566         195 :     sepNode = findNode("MeasurementSystem");
     567         195 :     of.writeParameter("measurementSystem", sepNode->getValue());
     568             : 
     569         195 :     of.writeAsciiString("\nstatic const sal_Unicode* LCType[] = {\n");
     570         195 :     of.writeAsciiString("\tLC_CTYPE_Unoid,\n");
     571         195 :     of.writeAsciiString("\tdateSeparator,\n");
     572         195 :     of.writeAsciiString("\tthousandSeparator,\n");
     573         195 :     of.writeAsciiString("\tdecimalSeparator,\n");
     574         195 :     of.writeAsciiString("\ttimeSeparator,\n");
     575         195 :     of.writeAsciiString("\ttime100SecSeparator,\n");
     576         195 :     of.writeAsciiString("\tlistSeparator,\n");
     577         195 :     of.writeAsciiString("\tquotationStart,\n");
     578         195 :     of.writeAsciiString("\tquotationEnd,\n");
     579         195 :     of.writeAsciiString("\tdoubleQuotationStart,\n");
     580         195 :     of.writeAsciiString("\tdoubleQuotationEnd,\n");
     581         195 :     of.writeAsciiString("\ttimeAM,\n");
     582         195 :     of.writeAsciiString("\ttimePM,\n");
     583         195 :     of.writeAsciiString("\tmeasurementSystem,\n");
     584         195 :     of.writeAsciiString("\tLongDateDayOfWeekSeparator,\n");
     585         195 :     of.writeAsciiString("\tLongDateDaySeparator,\n");
     586         195 :     of.writeAsciiString("\tLongDateMonthSeparator,\n");
     587         195 :     of.writeAsciiString("\tLongDateYearSeparator\n");
     588         195 :     of.writeAsciiString("};\n\n");
     589         390 :     of.writeFunction("getLocaleItem_", "0", "LCType");
     590             : }
     591             : 
     592             : 
     593         245 : static OUString sTheCurrencyReplaceTo;
     594         245 : static OUString sTheCompatibleCurrency;
     595         245 : static OUString sTheDateEditFormat;
     596             : 
     597             : sal_Int16 LCFormatNode::mnSection = 0;
     598             : sal_Int16 LCFormatNode::mnFormats = 0;
     599             : 
     600         246 : void LCFormatNode::generateCode (const OFileWriter &of) const
     601             : {
     602         246 :     if (mnSection >= 2)
     603           0 :         incError("more than 2 LC_FORMAT sections");
     604             : 
     605         246 :     ::std::vector< OUString > theDateAcceptancePatterns;
     606             : 
     607         408 :     OUString useLocale(getAttr().getValueByName("ref"));
     608             : 
     609         408 :     OUString str;
     610         408 :     OUString strFrom( getAttr().getValueByName("replaceFrom"));
     611         246 :     if (useLocale.isEmpty())
     612             :     {
     613         162 :         of.writeParameter("replaceFrom", strFrom, mnSection);
     614             :     }
     615         246 :     str = getAttr().getValueByName("replaceTo");
     616         246 :     if (!strFrom.isEmpty() && str.isEmpty())
     617           0 :         incErrorStr("replaceFrom=\"%s\" replaceTo=\"\" is empty replacement.\n", strFrom);
     618             :     // Locale data generator inserts FFFF for LangID, we need to adapt that.
     619         246 :     if (str.endsWithIgnoreAsciiCase( "-FFFF]"))
     620           0 :         incErrorStr("replaceTo=\"%s\" needs FFFF to be adapted to the real LangID value.\n", str);
     621         246 :     of.writeParameter("replaceTo", str, mnSection);
     622             :     // Remember the replaceTo value for "[CURRENCY]" to check format codes.
     623         246 :     if ( strFrom == "[CURRENCY]" )
     624         145 :         sTheCurrencyReplaceTo = str;
     625             :     // Remember the currency symbol if present.
     626         246 :     if (str.startsWith( "[$" ))
     627             :     {
     628         188 :         sal_Int32 nHyphen = str.indexOf( '-');
     629         188 :         if (nHyphen >= 3)
     630             :         {
     631         188 :             sTheCompatibleCurrency = str.copy( 2, nHyphen - 2);
     632             :         }
     633             :     }
     634             : 
     635         246 :     if (!useLocale.isEmpty())
     636             :     {
     637          84 :         if (!strFrom.isEmpty() && strFrom != "[CURRENCY]") //???
     638             :         {
     639             :             incErrorStrStr(
     640             :                 "Error: non-empty replaceFrom=\"%s\" with non-empty ref=\"%s\".",
     641           0 :                 strFrom, useLocale);
     642             :         }
     643          84 :         useLocale = useLocale.replace( '-', '_');
     644          84 :         switch (mnSection)
     645             :         {
     646             :             case 0:
     647          84 :                 of.writeRefFunction("getAllFormats0_", useLocale, "replaceTo0");
     648          84 :                 break;
     649             :             case 1:
     650           0 :                 of.writeRefFunction("getAllFormats1_", useLocale, "replaceTo1");
     651           0 :                 break;
     652             :         }
     653          84 :         of.writeRefFunction("getDateAcceptancePatterns_", useLocale);
     654         330 :         return;
     655             :     }
     656             : 
     657         162 :     sal_Int16 formatCount = mnFormats;
     658         162 :     NameSet  aMsgIdSet;
     659         324 :     ValueSet aFormatIndexSet;
     660         324 :     NameSet  aDefaultsSet;
     661         162 :     bool bCtypeIsRef = false;
     662         162 :     bool bHaveEngineering = false;
     663             : 
     664        8241 :     for (sal_Int32 i = 0; i< getNumberOfChildren() ; i++, formatCount++)
     665             :     {
     666        8079 :         LocaleNode * currNode = getChildAt (i);
     667        8079 :         if ( currNode->getName() == "DateAcceptancePattern" )
     668             :         {
     669         230 :             if (mnSection > 0)
     670           0 :                 incError( "DateAcceptancePattern only handled in LC_FORMAT, not LC_FORMAT_1");
     671             :             else
     672         230 :                 theDateAcceptancePatterns.push_back( currNode->getValue());
     673         230 :             --formatCount;
     674         460 :             continue;   // for
     675             :         }
     676        7849 :         if ( currNode->getName() != "FormatElement" )
     677             :         {
     678           0 :             incErrorStr( "Error: Undefined element '%s' in LC_FORMAT\n", currNode->getName());
     679           0 :             --formatCount;
     680           0 :             continue;   // for
     681             :         }
     682             : 
     683        7849 :         OUString aUsage;
     684       15698 :         OUString aType;
     685       15698 :         OUString aFormatIndex;
     686             :         //      currNode -> print();
     687        7849 :         const Attr &currNodeAttr = currNode->getAttr();
     688             :         //printf ("getLen() = %d\n", currNode->getAttr().getLength());
     689             : 
     690        7849 :         str = currNodeAttr.getValueByName("msgid");
     691        7849 :         if (!aMsgIdSet.insert( str).second)
     692           0 :             incErrorStr( "Error: Duplicated msgid=\"%s\" in FormatElement.\n", str);
     693        7849 :         of.writeParameter("FormatKey", str, formatCount);
     694             : 
     695        7849 :         str = currNodeAttr.getValueByName("default");
     696        7849 :         bool bDefault = str == "true";
     697        7849 :         of.writeDefaultParameter("FormatElement", str, formatCount);
     698             : 
     699        7849 :         aType = currNodeAttr.getValueByName("type");
     700        7849 :         of.writeParameter("FormatType", aType, formatCount);
     701             : 
     702        7849 :         aUsage = currNodeAttr.getValueByName("usage");
     703        7849 :         of.writeParameter("FormatUsage", aUsage, formatCount);
     704             : 
     705        7849 :         aFormatIndex = currNodeAttr.getValueByName("formatindex");
     706        7849 :         sal_Int16 formatindex = (sal_Int16)aFormatIndex.toInt32();
     707        7849 :         if (!aFormatIndexSet.insert( formatindex).second)
     708           0 :             incErrorInt( "Error: Duplicated formatindex=\"%d\" in FormatElement.\n", formatindex);
     709        7849 :         of.writeIntParameter("Formatindex", formatCount, formatindex);
     710             : 
     711             :         // Ensure only one default per usage and type.
     712        7849 :         if (bDefault)
     713             :         {
     714        2093 :             OUString aKey( aUsage + "," + aType);
     715        2093 :             if (!aDefaultsSet.insert( aKey).second)
     716             :             {
     717           0 :                 OUString aStr(  "Duplicated default for usage=\"");
     718           0 :                 aStr += aUsage;
     719           0 :                 aStr += "\" type=\"";
     720           0 :                 aStr += aType;
     721           0 :                 aStr += "\": formatindex=\"";
     722           0 :                 aStr += aFormatIndex;
     723           0 :                 aStr += "\".";
     724           0 :                 incError( aStr);
     725        2093 :             }
     726             :         }
     727             : 
     728        7849 :         const LocaleNode * n = currNode -> findNode("FormatCode");
     729        7849 :         if (n)
     730             :         {
     731        7849 :             of.writeParameter("FormatCode", n->getValue(), formatCount);
     732             :             // Check separator usage for some FormatCode elements.
     733        7849 :             const LocaleNode* pCtype = 0;
     734        7849 :             switch (formatindex)
     735             :             {
     736             :                 case cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY :
     737         161 :                     sTheDateEditFormat = n->getValue();
     738         161 :                     break;
     739             :                 case cssi::NumberFormatIndex::NUMBER_1000DEC2 : // #,##0.00
     740             :                 case cssi::NumberFormatIndex::TIME_MMSS00 :     // MM:SS.00
     741             :                 case cssi::NumberFormatIndex::TIME_HH_MMSS00 :  // [HH]:MM:SS.00
     742             :                     {
     743         483 :                         const LocaleNode* pRoot = getRoot();
     744         483 :                         if (!pRoot)
     745           0 :                             incError( "No root for FormatCode.");
     746             :                         else
     747             :                         {
     748         483 :                             pCtype = pRoot->findNode( "LC_CTYPE");
     749         483 :                             if (!pCtype)
     750           0 :                                 incError( "No LC_CTYPE found for FormatCode.");
     751             :                             else
     752             :                             {
     753         483 :                                 OUString aRef( pCtype->getAttr().getValueByName("ref"));
     754         483 :                                 if (!aRef.isEmpty())
     755             :                                 {
     756           9 :                                     aRef = aRef.replace( '-', '_');
     757           9 :                                     if (!bCtypeIsRef)
     758             :                                         fprintf( stderr,
     759             :                                                 "Warning: Can't check separators used in FormatCode due to LC_CTYPE ref=\"%s\".\n"
     760             :                                                 "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",
     761           3 :                                                 OSTR( aRef));
     762           9 :                                     bCtypeIsRef = true;
     763           9 :                                     pCtype = 0;
     764         483 :                                 }
     765             :                             }
     766             :                         }
     767             :                     }
     768         483 :                     break;
     769             :                 case cssi::NumberFormatIndex::CURRENCY_1000DEC2 :
     770             :                     // Remember the currency symbol if present.
     771             :                     {
     772             :                         sal_Int32 nStart;
     773         218 :                         if (sTheCompatibleCurrency.isEmpty() &&
     774          57 :                                 ((nStart = n->getValue().indexOf("[$")) >= 0))
     775             :                         {
     776          57 :                             OUString aCode( n->getValue());
     777          57 :                             sal_Int32 nHyphen = aCode.indexOf( '-', nStart);
     778          57 :                             if (nHyphen >= nStart + 3)
     779          57 :                                 sTheCompatibleCurrency = aCode.copy( nStart + 2, nHyphen - nStart - 2);
     780             :                         }
     781             :                     }
     782             :                     // fallthru
     783             :                 case cssi::NumberFormatIndex::CURRENCY_1000INT :
     784             :                 case cssi::NumberFormatIndex::CURRENCY_1000INT_RED :
     785             :                 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_RED :
     786             :                 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_CCC :
     787             :                 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_DASHED :
     788             :                     // Currency formats should be something like [C]###0;-[C]###0
     789             :                     // and not parenthesized [C]###0;([C]###0) if not en_US.
     790         966 :                     if (strcmp( of.getLocale(), "en_US") != 0)
     791             :                     {
     792         960 :                         OUString aCode( n->getValue());
     793        1920 :                         OUString aPar1( "0)");
     794        1920 :                         OUString aPar2( "-)" );
     795        1920 :                         OUString aPar3( " )" );
     796        1920 :                         OUString aPar4( "])" );
     797        3758 :                         if (aCode.indexOf( aPar1 ) > 0 || aCode.indexOf( aPar2 ) > 0 ||
     798        2790 :                                 aCode.indexOf( aPar3 ) > 0 || aCode.indexOf( aPar4 ) > 0)
     799        1005 :                             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);
     800             :                     }
     801             :                     // Check if we have replaceTo for "[CURRENCY]" placeholder.
     802         966 :                     if (sTheCurrencyReplaceTo.isEmpty())
     803             :                     {
     804         342 :                         OUString aCode( n->getValue());
     805         342 :                         if (aCode.indexOf( "[CURRENCY]" ) >= 0)
     806           0 :                             incErrorInt( "Error: [CURRENCY] replaceTo not found for formatindex=\"%d\".\n", formatindex);
     807             :                     }
     808         966 :                     break;
     809             :                 default:
     810        6239 :                     if (aUsage == "SCIENTIFIC_NUMBER")
     811             :                     {
     812             :                         // Check for presence of  ##0.00E+00
     813         486 :                         OUString aCode( n->getValue());
     814             :                         // Simple check without decimal separator (assumed to
     815             :                         // be one UTF-16 character). May be prefixed with
     816             :                         // [NatNum1] or other tags.
     817         486 :                         sal_Int32 nInt = aCode.indexOf("##0");
     818         486 :                         sal_Int32 nDec = (nInt < 0 ? -1 : aCode.indexOf("00E+00", nInt));
     819         486 :                         if (nInt >= 0 && nDec == nInt+4)
     820         161 :                             bHaveEngineering = true;
     821             :                     }
     822        6239 :                     break;
     823             :             }
     824        7849 :             if (pCtype)
     825             :             {
     826         474 :                 int nSavErr = nError;
     827         474 :                 OUString aCode( n->getValue());
     828         474 :                 if (formatindex == cssi::NumberFormatIndex::NUMBER_1000DEC2)
     829             :                 {
     830         158 :                     sal_Int32 nDec = -1;
     831         158 :                     sal_Int32 nGrp = -1;
     832         158 :                     const LocaleNode* pSep = pCtype->findNode( "DecimalSeparator");
     833         158 :                     if (!pSep)
     834           0 :                         incError( "No DecimalSeparator found for FormatCode.");
     835             :                     else
     836             :                     {
     837         158 :                         nDec = aCode.indexOf( pSep->getValue());
     838         158 :                         if (nDec < 0)
     839             :                             incErrorInt( "Error: DecimalSeparator not present in FormatCode formatindex=\"%d\".\n",
     840           0 :                                     formatindex);
     841             :                     }
     842         158 :                     pSep = pCtype->findNode( "ThousandSeparator");
     843         158 :                     if (!pSep)
     844           0 :                         incError( "No ThousandSeparator found for FormatCode.");
     845             :                     else
     846             :                     {
     847         158 :                         nGrp = aCode.indexOf( pSep->getValue());
     848         158 :                         if (nGrp < 0)
     849             :                             incErrorInt( "Error: ThousandSeparator not present in FormatCode formatindex=\"%d\".\n",
     850           0 :                                     formatindex);
     851             :                     }
     852         158 :                     if (nDec >= 0 && nGrp >= 0 && nDec <= nGrp)
     853             :                         incErrorInt( "Error: Ordering of ThousandSeparator and DecimalSeparator not correct in formatindex=\"%d\".\n",
     854           0 :                                 formatindex);
     855             :                 }
     856         790 :                 if (formatindex == cssi::NumberFormatIndex::TIME_MMSS00 ||
     857         316 :                         formatindex == cssi::NumberFormatIndex::TIME_HH_MMSS00)
     858             :                 {
     859         316 :                     sal_Int32 nTime = -1;
     860         316 :                     sal_Int32 n100s = -1;
     861         316 :                     const LocaleNode* pSep = pCtype->findNode( "TimeSeparator");
     862         316 :                     if (!pSep)
     863           0 :                         incError( "No TimeSeparator found for FormatCode.");
     864             :                     else
     865             :                     {
     866         316 :                         nTime = aCode.indexOf( pSep->getValue());
     867         316 :                         if (nTime < 0)
     868             :                             incErrorInt( "Error: TimeSeparator not present in FormatCode formatindex=\"%d\".\n",
     869           0 :                                     formatindex);
     870             :                     }
     871         316 :                     pSep = pCtype->findNode( "Time100SecSeparator");
     872         316 :                     if (!pSep)
     873           0 :                         incError( "No Time100SecSeparator found for FormatCode.");
     874             :                     else
     875             :                     {
     876         316 :                         n100s = aCode.indexOf( pSep->getValue());
     877         316 :                         if (n100s < 0)
     878             :                             incErrorInt( "Error: Time100SecSeparator not present in FormatCode formatindex=\"%d\".\n",
     879           0 :                                     formatindex);
     880         316 :                         OUStringBuffer a100s( pSep->getValue());
     881         316 :                         a100s.appendAscii( "00");
     882         316 :                         n100s = aCode.indexOf( a100s.makeStringAndClear());
     883         316 :                         if (n100s < 0)
     884             :                             incErrorInt( "Error: Time100SecSeparator+00 not present in FormatCode formatindex=\"%d\".\n",
     885           0 :                                     formatindex);
     886             :                     }
     887         316 :                     if (n100s >= 0 && nTime >= 0 && n100s <= nTime)
     888             :                         incErrorInt( "Error: Ordering of Time100SecSeparator and TimeSeparator not correct in formatindex=\"%d\".\n",
     889           0 :                                 formatindex);
     890             :                 }
     891         474 :                 if (nSavErr != nError)
     892             :                     fprintf( stderr,
     893             :                             "Warning: formatindex=\"%d\",\"%d\",\"%d\" are the only FormatCode elements checked for separator usage, there may be others that have errors.\n",
     894             :                             int(cssi::NumberFormatIndex::NUMBER_1000DEC2),
     895             :                             int(cssi::NumberFormatIndex::TIME_MMSS00),
     896           0 :                             int(cssi::NumberFormatIndex::TIME_HH_MMSS00));
     897             : 
     898             :             }
     899             :         }
     900             :         else
     901           0 :             incError( "No FormatCode in FormatElement.");
     902        7849 :         n = currNode -> findNode("DefaultName");
     903        7849 :         if (n)
     904         185 :             of.writeParameter("FormatDefaultName", n->getValue(), formatCount);
     905             :         else
     906        7664 :             of.writeParameter("FormatDefaultName", OUString(), formatCount);
     907             : 
     908        7849 :     }
     909             : 
     910             :     // Check presence of all required format codes only in first section
     911             :     // LC_FORMAT, not in optional LC_FORMAT_1
     912         162 :     if (mnSection == 0)
     913             :     {
     914             :         // At least one abbreviated date acceptance pattern must be present.
     915         161 :         if (theDateAcceptancePatterns.empty())
     916           0 :             incError( "No DateAcceptancePattern present.\n");
     917             :         else
     918             :         {
     919         161 :             bool bHaveAbbr = false;
     920        1142 :             for (::std::vector< OUString >::const_iterator it( theDateAcceptancePatterns.begin());
     921         820 :                     !bHaveAbbr && it != theDateAcceptancePatterns.end(); ++it)
     922             :             {
     923         166 :                 if ((*it).indexOf('D') > -1 && (*it).indexOf('M') > -1 && (*it).indexOf('Y') <= -1)
     924         161 :                     bHaveAbbr = true;
     925             :             }
     926         161 :             if (!bHaveAbbr)
     927           0 :                 incError( "No abbreviated DateAcceptancePattern present. For example M/D or D.M.\n");
     928             :         }
     929             : 
     930             :         // 0..47 MUST be present, 48,49 MUST NOT be present
     931         161 :         ValueSet::const_iterator aIter( aFormatIndexSet.begin());
     932        7728 :         for (sal_Int16 nNext = cssi::NumberFormatIndex::NUMBER_START;
     933             :                 nNext < cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES; ++nNext)
     934             :         {
     935       15134 :             sal_Int16 nHere = ::std::min( ((aIter != aFormatIndexSet.end() ? *aIter :
     936             :                     cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES)),
     937        7567 :                     cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES);
     938        7567 :             if (aIter != aFormatIndexSet.end()) ++aIter;
     939        8211 :             for ( ; nNext < nHere; ++nNext)
     940             :             {
     941         644 :                 switch (nNext)
     942             :                 {
     943             :                     case cssi::NumberFormatIndex::FRACTION_1 :
     944             :                     case cssi::NumberFormatIndex::FRACTION_2 :
     945             :                     case cssi::NumberFormatIndex::BOOLEAN :
     946             :                     case cssi::NumberFormatIndex::TEXT :
     947             :                         // generated internally
     948         644 :                         break;
     949             :                     default:
     950           0 :                         incErrorInt( "Error: FormatElement formatindex=\"%d\" not present.\n", nNext);
     951             :                 }
     952             :             }
     953        7567 :             switch (nHere)
     954             :             {
     955             :                 case cssi::NumberFormatIndex::BOOLEAN :
     956           0 :                     incErrorInt( "Error: FormatElement formatindex=\"%d\" reserved for internal ``BOOLEAN''.\n", nNext);
     957           0 :                     break;
     958             :                 case cssi::NumberFormatIndex::TEXT :
     959           0 :                     incErrorInt( "Error: FormatElement formatindex=\"%d\" reserved for internal ``@'' (TEXT).\n", nNext);
     960           0 :                     break;
     961             :                 default:
     962             :                     ;   // nothing
     963             :             }
     964             :         }
     965             : 
     966         161 :         if (!bHaveEngineering)
     967           0 :             incError("Engineering notation format not present, e.g. ##0.00E+00 or ##0,00E+00 for usage=\"SCIENTIFIC_NUMBER\"\n");
     968             :     }
     969             : 
     970         162 :     of.writeAsciiString("\nstatic const sal_Int16 ");
     971         162 :     of.writeAsciiString("FormatElementsCount");
     972         162 :     of.writeInt(mnSection);
     973         162 :     of.writeAsciiString(" = ");
     974         162 :     of.writeInt( formatCount - mnFormats);
     975         162 :     of.writeAsciiString(";\n");
     976         162 :     of.writeAsciiString("static const sal_Unicode* ");
     977         162 :     of.writeAsciiString("FormatElementsArray");
     978         162 :     of.writeInt(mnSection);
     979         162 :     of.writeAsciiString("[] = {\n");
     980        8011 :     for(sal_Int16 i = mnFormats; i < formatCount; i++) {
     981             : 
     982        7849 :         of.writeAsciiString("\t");
     983        7849 :         of.writeAsciiString("FormatCode");
     984        7849 :         of.writeInt(i);
     985        7849 :         of.writeAsciiString(",\n");
     986             : 
     987        7849 :         of.writeAsciiString("\t");
     988        7849 :         of.writeAsciiString("FormatDefaultName");
     989        7849 :         of.writeInt(i);
     990        7849 :         of.writeAsciiString(",\n");
     991             : 
     992        7849 :         of.writeAsciiString("\t");
     993        7849 :         of.writeAsciiString("FormatKey");
     994        7849 :         of.writeInt(i);
     995        7849 :         of.writeAsciiString(",\n");
     996             : 
     997        7849 :         of.writeAsciiString("\t");
     998        7849 :         of.writeAsciiString("FormatType");
     999        7849 :         of.writeInt(i);
    1000        7849 :         of.writeAsciiString(",\n");
    1001             : 
    1002        7849 :         of.writeAsciiString("\t");
    1003        7849 :         of.writeAsciiString("FormatUsage");
    1004        7849 :         of.writeInt(i);
    1005        7849 :         of.writeAsciiString(",\n");
    1006             : 
    1007        7849 :         of.writeAsciiString("\t");
    1008        7849 :         of.writeAsciiString("Formatindex");
    1009        7849 :         of.writeInt(i);
    1010        7849 :         of.writeAsciiString(",\n");
    1011             : 
    1012             : 
    1013        7849 :         of.writeAsciiString("\tdefaultFormatElement");
    1014        7849 :         of.writeInt(i);
    1015        7849 :         of.writeAsciiString(",\n");
    1016             :     }
    1017         162 :     of.writeAsciiString("};\n\n");
    1018             : 
    1019         162 :     switch (mnSection)
    1020             :     {
    1021             :         case 0:
    1022         161 :             of.writeFunction("getAllFormats0_", "FormatElementsCount0", "FormatElementsArray0", "replaceFrom0", "replaceTo0");
    1023         161 :             break;
    1024             :         case 1:
    1025           1 :             of.writeFunction("getAllFormats1_", "FormatElementsCount1", "FormatElementsArray1", "replaceFrom1", "replaceTo1");
    1026           1 :             break;
    1027             :     }
    1028             : 
    1029         162 :     mnFormats = mnFormats + formatCount;
    1030             : 
    1031         162 :     if (mnSection == 0)
    1032             :     {
    1033             :         // Extract and add date acceptance pattern for full date, so we provide
    1034             :         // at least one valid pattern, even if the number parser doesn't need
    1035             :         // that one.
    1036             :         /* XXX NOTE: only simple [...] modifier and "..." quotes detected and
    1037             :          * ignored, not nested, no fancy stuff. */
    1038         161 :         sal_Int32 nIndex = 0;
    1039             :         // aDateSep can be empty if LC_CTYPE was a ref=..., determine from
    1040             :         // FormatCode then.
    1041         161 :         sal_uInt32 cDateSep = (aDateSep.isEmpty() ? 0 : aDateSep.iterateCodePoints( &nIndex));
    1042         161 :         sal_uInt32 cDateSep2 = cDateSep;
    1043         161 :         nIndex = 0;
    1044         161 :         OUStringBuffer aPatternBuf(5);
    1045         322 :         OUStringBuffer aPatternBuf2(5);
    1046         161 :         sal_uInt8 nDetected = 0;    // bits Y,M,D
    1047         161 :         bool bInModifier = false;
    1048         161 :         bool bQuoted = false;
    1049        1560 :         while (nIndex < sTheDateEditFormat.getLength() && nDetected < 7)
    1050             :         {
    1051        1238 :             sal_uInt32 cChar = sTheDateEditFormat.iterateCodePoints( &nIndex);
    1052        1238 :             if (bInModifier)
    1053             :             {
    1054          49 :                 if (cChar == ']')
    1055           6 :                     bInModifier = false;
    1056          49 :                 continue;   // while
    1057             :             }
    1058        1189 :             if (bQuoted)
    1059             :             {
    1060           0 :                 if (cChar == '"')
    1061           0 :                     bQuoted = false;
    1062           0 :                 continue;   // while
    1063             :             }
    1064        1189 :             switch (cChar)
    1065             :             {
    1066             :                 case 'Y':
    1067             :                 case 'y':
    1068         226 :                     if (!(nDetected & 4))
    1069             :                     {
    1070         133 :                         aPatternBuf.append( 'Y');
    1071         133 :                         if (!aPatternBuf2.isEmpty())
    1072           0 :                             aPatternBuf2.append( 'Y');
    1073         133 :                         nDetected |= 4;
    1074             :                     }
    1075         226 :                     break;
    1076             :                 case 'M':
    1077             :                 case 'm':
    1078         314 :                     if (!(nDetected & 2))
    1079             :                     {
    1080         160 :                         aPatternBuf.append( 'M');
    1081         160 :                         if (!aPatternBuf2.isEmpty())
    1082           1 :                             aPatternBuf2.append( 'M');
    1083         160 :                         nDetected |= 2;
    1084             :                     }
    1085         314 :                     break;
    1086             :                 case 'D':
    1087             :                 case 'd':
    1088         261 :                     if (!(nDetected & 1))
    1089             :                     {
    1090         148 :                         aPatternBuf.append( 'D');
    1091         148 :                         if (!aPatternBuf2.isEmpty())
    1092           1 :                             aPatternBuf2.append( 'D');
    1093         148 :                         nDetected |= 1;
    1094             :                     }
    1095         261 :                     break;
    1096             :                 case '[':
    1097           6 :                     bInModifier = true;
    1098           6 :                     break;
    1099             :                 case '"':
    1100           0 :                     bQuoted = true;
    1101           0 :                     break;
    1102             :                 case '\\':
    1103           0 :                     cChar = sTheDateEditFormat.iterateCodePoints( &nIndex);
    1104           0 :                     break;
    1105             :                 case '-':
    1106             :                 case '.':
    1107             :                 case '/':
    1108             :                     // There are locales that use an ISO 8601 edit format
    1109             :                     // regardless of what the date separator or other formats
    1110             :                     // say, for example hu-HU. Generalize this for all cases
    1111             :                     // where the used separator differs and is one of the known
    1112             :                     // separators and generate a second pattern with the
    1113             :                     // format's separator at the current position.
    1114         322 :                     cDateSep2 = cChar;
    1115             :                     // fallthru
    1116             :                 default:
    1117         324 :                     if (!cDateSep)
    1118           3 :                         cDateSep = cChar;
    1119         324 :                     if (!cDateSep2)
    1120           0 :                         cDateSep2 = cChar;
    1121         324 :                     if (cDateSep != cDateSep2 && aPatternBuf2.isEmpty())
    1122           1 :                         aPatternBuf2 = aPatternBuf;
    1123         324 :                     if (cChar == cDateSep || cChar == cDateSep2)
    1124         322 :                         aPatternBuf.append( OUString( &cDateSep, 1));   // always the defined separator
    1125         324 :                     if (cChar == cDateSep2 && !aPatternBuf2.isEmpty())
    1126           2 :                         aPatternBuf2.append( OUString( &cDateSep2, 1)); // always the format's separator
    1127         324 :                     break;
    1128             :                 // The localized legacy:
    1129             :                 case 'A':
    1130          23 :                     if (((nDetected & 7) == 3) || ((nDetected & 7) == 0))
    1131             :                     {
    1132             :                         // es DD/MM/AAAA
    1133             :                         // fr JJ.MM.AAAA
    1134             :                         // it GG/MM/AAAA
    1135             :                         // fr_CA AAAA-MM-JJ
    1136          20 :                         aPatternBuf.append( 'Y');
    1137          20 :                         if (!aPatternBuf2.isEmpty())
    1138           0 :                             aPatternBuf2.append( 'Y');
    1139          20 :                         nDetected |= 4;
    1140             :                     }
    1141          23 :                     break;
    1142             :                 case 'J':
    1143          16 :                     if (((nDetected & 7) == 0) || ((nDetected & 7) == 6))
    1144             :                     {
    1145             :                         // fr JJ.MM.AAAA
    1146             :                         // fr_CA AAAA-MM-JJ
    1147           5 :                         aPatternBuf.append( 'D');
    1148           5 :                         if (!aPatternBuf2.isEmpty())
    1149           0 :                             aPatternBuf2.append( 'D');
    1150           5 :                         nDetected |= 1;
    1151             :                     }
    1152          11 :                     else if ((nDetected & 7) == 3)
    1153             :                     {
    1154             :                         // nl DD-MM-JJJJ
    1155             :                         // de TT.MM.JJJJ
    1156           7 :                         aPatternBuf.append( 'Y');
    1157           7 :                         if (!aPatternBuf2.isEmpty())
    1158           0 :                             aPatternBuf2.append( 'Y');
    1159           7 :                         nDetected |= 4;
    1160             :                     }
    1161          16 :                     break;
    1162             :                 case 'T':
    1163          10 :                     if ((nDetected & 7) == 0)
    1164             :                     {
    1165             :                         // de TT.MM.JJJJ
    1166           5 :                         aPatternBuf.append( 'D');
    1167           5 :                         if (!aPatternBuf2.isEmpty())
    1168           0 :                             aPatternBuf2.append( 'D');
    1169           5 :                         nDetected |= 1;
    1170             :                     }
    1171          10 :                     break;
    1172             :                 case 'G':
    1173           4 :                     if ((nDetected & 7) == 0)
    1174             :                     {
    1175             :                         // it GG/MM/AAAA
    1176           2 :                         aPatternBuf.append( 'D');
    1177           2 :                         if (!aPatternBuf2.isEmpty())
    1178           0 :                             aPatternBuf2.append( 'D');
    1179           2 :                         nDetected |= 1;
    1180             :                     }
    1181           4 :                     break;
    1182             :                 case 'P':
    1183           2 :                     if ((nDetected & 7) == 0)
    1184             :                     {
    1185             :                         // fi PP.KK.VVVV
    1186           1 :                         aPatternBuf.append( 'D');
    1187           1 :                         if (!aPatternBuf2.isEmpty())
    1188           0 :                             aPatternBuf2.append( 'D');
    1189           1 :                         nDetected |= 1;
    1190             :                     }
    1191           2 :                     break;
    1192             :                 case 'K':
    1193           2 :                     if ((nDetected & 7) == 1)
    1194             :                     {
    1195             :                         // fi PP.KK.VVVV
    1196           1 :                         aPatternBuf.append( 'M');
    1197           1 :                         if (!aPatternBuf2.isEmpty())
    1198           0 :                             aPatternBuf2.append( 'M');
    1199           1 :                         nDetected |= 2;
    1200             :                     }
    1201           2 :                     break;
    1202             :                 case 'V':
    1203           1 :                     if ((nDetected & 7) == 3)
    1204             :                     {
    1205             :                         // fi PP.KK.VVVV
    1206           1 :                         aPatternBuf.append( 'Y');
    1207           1 :                         if (!aPatternBuf2.isEmpty())
    1208           0 :                             aPatternBuf2.append( 'Y');
    1209           1 :                         nDetected |= 4;
    1210             :                     }
    1211           1 :                     break;
    1212             :             }
    1213             :         }
    1214         161 :         OUString aPattern( aPatternBuf.makeStringAndClear());
    1215         161 :         if (((nDetected & 7) != 7) || aPattern.getLength() < 5)
    1216             :         {
    1217           0 :             incErrorStr( "Error: failed to extract full date acceptance pattern: %s\n", aPattern);
    1218             :             fprintf( stderr, "       with DateSeparator '%s' from FormatCode '%s' (formatindex=\"%d\")\n",
    1219             :                     OSTR( OUString( cDateSep)), OSTR( sTheDateEditFormat),
    1220           0 :                     (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY);
    1221             :         }
    1222             :         else
    1223             :         {
    1224             :             fprintf( stderr, "Generated date acceptance pattern: '%s' from '%s' (formatindex=\"%d\" and defined DateSeparator '%s')\n",
    1225             :                     OSTR( aPattern), OSTR( sTheDateEditFormat),
    1226             :                     (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY,
    1227         161 :                     OSTR( OUString( cDateSep)));
    1228             :             // Insert at front so full date pattern is first in checks.
    1229         161 :             theDateAcceptancePatterns.insert( theDateAcceptancePatterns.begin(), aPattern);
    1230             :         }
    1231         161 :         if (!aPatternBuf2.isEmpty())
    1232             :         {
    1233           1 :             OUString aPattern2( aPatternBuf2.makeStringAndClear());
    1234           1 :             if (aPattern2.getLength() < 5)
    1235             :             {
    1236           0 :                 incErrorStr( "Error: failed to extract 2nd date acceptance pattern: %s\n", aPattern2);
    1237             :                 fprintf( stderr, "       with DateSeparator '%s' from FormatCode '%s' (formatindex=\"%d\")\n",
    1238             :                         OSTR( OUString( cDateSep2)), OSTR( sTheDateEditFormat),
    1239           0 :                         (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY);
    1240             :             }
    1241             :             else
    1242             :             {
    1243             :                 fprintf( stderr, "Generated  2nd acceptance pattern: '%s' from '%s' (formatindex=\"%d\")\n",
    1244             :                         OSTR( aPattern2), OSTR( sTheDateEditFormat),
    1245           1 :                         (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY);
    1246           1 :                 theDateAcceptancePatterns.insert( theDateAcceptancePatterns.begin(), aPattern2);
    1247           1 :             }
    1248             :         }
    1249             : 
    1250             :         // Rudimentary check if a pattern interferes with decimal number.
    1251             :         // But only if not inherited in which case we don't have aDecSep here.
    1252         161 :         if (!aDecSep.isEmpty())
    1253             :         {
    1254         158 :             nIndex = 0;
    1255         158 :             sal_uInt32 cDecSep = aDecSep.iterateCodePoints( &nIndex);
    1256        1632 :             for (vector<OUString>::const_iterator aIt = theDateAcceptancePatterns.begin();
    1257        1088 :                     aIt != theDateAcceptancePatterns.end(); ++aIt)
    1258             :             {
    1259         386 :                 if ((*aIt).getLength() == (cDecSep <= 0xffff ? 3 : 4))
    1260             :                 {
    1261         154 :                     nIndex = 1;
    1262         154 :                     if ((*aIt).iterateCodePoints( &nIndex) == cDecSep)
    1263             :                     {
    1264           0 :                         ++nError;
    1265             :                         fprintf( stderr, "Error: Date acceptance pattern '%s' matches decimal number '#%s#'\n",
    1266           0 :                                 OSTR( *aIt), OSTR( aDecSep));
    1267             :                     }
    1268             :                 }
    1269             :             }
    1270             :         }
    1271             : 
    1272             :         // Check for duplicates.
    1273        1659 :         for (vector<OUString>::const_iterator aIt = theDateAcceptancePatterns.begin();
    1274        1106 :                 aIt != theDateAcceptancePatterns.end(); ++aIt)
    1275             :         {
    1276        3492 :             for (vector<OUString>::iterator aComp = theDateAcceptancePatterns.begin();
    1277        3100 :                     aComp != theDateAcceptancePatterns.end(); /*nop*/)
    1278             :             {
    1279        1158 :                 if (aIt != aComp && *aIt == *aComp)
    1280             :                 {
    1281           0 :                     incErrorStr( "Error: Duplicated DateAcceptancePattern: %s\n", *aComp);
    1282           0 :                     aComp = theDateAcceptancePatterns.erase( aComp);
    1283             :                 }
    1284             :                 else
    1285        1158 :                     ++aComp;
    1286             :             }
    1287             :         }
    1288             : 
    1289         161 :         sal_Int16 nbOfDateAcceptancePatterns = static_cast<sal_Int16>(theDateAcceptancePatterns.size());
    1290             : 
    1291         553 :         for (sal_Int16 i = 0; i < nbOfDateAcceptancePatterns; ++i)
    1292             :         {
    1293         392 :             of.writeParameter("DateAcceptancePattern", theDateAcceptancePatterns[i], i);
    1294             :         }
    1295             : 
    1296         161 :         of.writeAsciiString("static const sal_Int16 DateAcceptancePatternsCount = ");
    1297         161 :         of.writeInt( nbOfDateAcceptancePatterns);
    1298         161 :         of.writeAsciiString(";\n");
    1299             : 
    1300         161 :         of.writeAsciiString("static const sal_Unicode* DateAcceptancePatternsArray[] = {\n");
    1301         553 :         for (sal_Int16 i = 0; i < nbOfDateAcceptancePatterns; ++i)
    1302             :         {
    1303         392 :             of.writeAsciiString("\t");
    1304         392 :             of.writeAsciiString("DateAcceptancePattern");
    1305         392 :             of.writeInt(i);
    1306         392 :             of.writeAsciiString(",\n");
    1307             :         }
    1308         161 :         of.writeAsciiString("};\n\n");
    1309             : 
    1310         322 :         of.writeFunction("getDateAcceptancePatterns_", "DateAcceptancePatternsCount", "DateAcceptancePatternsArray");
    1311             :     }
    1312             : 
    1313         486 :     ++mnSection;
    1314             : }
    1315             : 
    1316         245 : void LCCollationNode::generateCode (const OFileWriter &of) const
    1317             : {
    1318         245 :     OUString useLocale =   getAttr().getValueByName("ref");
    1319         245 :     if (!useLocale.isEmpty()) {
    1320         131 :         useLocale = useLocale.replace( '-', '_');
    1321         131 :         of.writeRefFunction("getCollatorImplementation_", useLocale);
    1322         131 :         of.writeRefFunction("getCollationOptions_", useLocale);
    1323         376 :         return;
    1324             :     }
    1325         114 :     sal_Int16 nbOfCollations = 0;
    1326         114 :     sal_Int16 nbOfCollationOptions = 0;
    1327             :     sal_Int16 j;
    1328             : 
    1329         355 :     for ( j = 0; j < getNumberOfChildren(); j++ ) {
    1330         241 :         LocaleNode * currNode = getChildAt (j);
    1331         241 :         if( currNode->getName() == "Collator" )
    1332             :         {
    1333         127 :             OUString str;
    1334         127 :             str = currNode->getAttr().getValueByName("unoid");
    1335         127 :             of.writeParameter("CollatorID", str, j);
    1336         127 :             str = currNode->getValue();
    1337         127 :             of.writeParameter("CollatorRule", str, j);
    1338         127 :             str = currNode -> getAttr().getValueByName("default");
    1339         127 :             of.writeDefaultParameter("Collator", str, j);
    1340         127 :             of.writeAsciiString("\n");
    1341             : 
    1342         127 :             nbOfCollations++;
    1343             :         }
    1344         241 :         if( currNode->getName() == "CollationOptions" )
    1345             :         {
    1346         114 :             LocaleNode* pCollationOptions = currNode;
    1347         114 :             nbOfCollationOptions = sal::static_int_cast<sal_Int16>( pCollationOptions->getNumberOfChildren() );
    1348         228 :             for( sal_Int16 i=0; i<nbOfCollationOptions; i++ )
    1349             :             {
    1350         114 :                 of.writeParameter("collationOption", pCollationOptions->getChildAt( i )->getValue(), i );
    1351             :             }
    1352             : 
    1353         114 :             of.writeAsciiString("static const sal_Int16 nbOfCollationOptions = ");
    1354         114 :             of.writeInt( nbOfCollationOptions );
    1355         114 :             of.writeAsciiString(";\n\n");
    1356             :         }
    1357             :     }
    1358         114 :     of.writeAsciiString("static const sal_Int16 nbOfCollations = ");
    1359         114 :     of.writeInt(nbOfCollations);
    1360         114 :     of.writeAsciiString(";\n\n");
    1361             : 
    1362         114 :     of.writeAsciiString("\nstatic const sal_Unicode* LCCollatorArray[] = {\n");
    1363         241 :     for(j = 0; j < nbOfCollations; j++) {
    1364         127 :         of.writeAsciiString("\tCollatorID");
    1365         127 :         of.writeInt(j);
    1366         127 :         of.writeAsciiString(",\n");
    1367             : 
    1368         127 :         of.writeAsciiString("\tdefaultCollator");
    1369         127 :         of.writeInt(j);
    1370         127 :         of.writeAsciiString(",\n");
    1371             : 
    1372         127 :         of.writeAsciiString("\tCollatorRule");
    1373         127 :         of.writeInt(j);
    1374         127 :         of.writeAsciiString(",\n");
    1375             :     }
    1376         114 :     of.writeAsciiString("};\n\n");
    1377             : 
    1378         114 :     of.writeAsciiString("static const sal_Unicode* collationOptions[] = {");
    1379         228 :     for( j=0; j<nbOfCollationOptions; j++ )
    1380             :     {
    1381         114 :         of.writeAsciiString( "collationOption" );
    1382         114 :         of.writeInt( j );
    1383         114 :         of.writeAsciiString( ", " );
    1384             :     }
    1385         114 :     of.writeAsciiString("NULL };\n");
    1386         114 :     of.writeFunction("getCollatorImplementation_", "nbOfCollations", "LCCollatorArray");
    1387         114 :     of.writeFunction("getCollationOptions_", "nbOfCollationOptions", "collationOptions");
    1388             : }
    1389             : 
    1390         245 : void LCSearchNode::generateCode (const OFileWriter &of) const
    1391             : {
    1392         245 :     OUString useLocale =   getAttr().getValueByName("ref");
    1393         245 :     if (!useLocale.isEmpty()) {
    1394         147 :         useLocale = useLocale.replace( '-', '_');
    1395         147 :         of.writeRefFunction("getSearchOptions_", useLocale);
    1396         392 :         return;
    1397             :     }
    1398             : 
    1399          98 :     if( getNumberOfChildren() != 1 )
    1400             :     {
    1401           0 :         ++nError;
    1402             :         fprintf(
    1403             :             stderr, "Error: LC_SEARCH: more than 1 child: %ld\n",
    1404           0 :             sal::static_int_cast< long >(getNumberOfChildren()));
    1405             :     }
    1406             :     sal_Int32 i;
    1407          98 :     LocaleNode* pSearchOptions = getChildAt( 0 );
    1408          98 :     sal_Int32   nSearchOptions = pSearchOptions->getNumberOfChildren();
    1409         198 :     for( i=0; i<nSearchOptions; i++ )
    1410             :     {
    1411         100 :         of.writeParameter("searchOption", pSearchOptions->getChildAt( i )->getValue(), sal::static_int_cast<sal_Int16>(i) );
    1412             :     }
    1413             : 
    1414          98 :     of.writeAsciiString("static const sal_Int16 nbOfSearchOptions = ");
    1415          98 :     of.writeInt( sal::static_int_cast<sal_Int16>( nSearchOptions ) );
    1416          98 :     of.writeAsciiString(";\n\n");
    1417             : 
    1418          98 :     of.writeAsciiString("static const sal_Unicode* searchOptions[] = {");
    1419         198 :     for( i=0; i<nSearchOptions; i++ )
    1420             :     {
    1421         100 :         of.writeAsciiString( "searchOption" );
    1422         100 :         of.writeInt( sal::static_int_cast<sal_Int16>(i) );
    1423         100 :         of.writeAsciiString( ", " );
    1424             :     }
    1425          98 :     of.writeAsciiString("NULL };\n");
    1426          98 :     of.writeFunction("getSearchOptions_", "nbOfSearchOptions", "searchOptions");
    1427             : }
    1428             : 
    1429         245 : void LCIndexNode::generateCode (const OFileWriter &of) const
    1430             : {
    1431         245 :     OUString useLocale =   getAttr().getValueByName("ref");
    1432         245 :     if (!useLocale.isEmpty()) {
    1433          90 :         useLocale = useLocale.replace( '-', '_');
    1434          90 :         of.writeRefFunction("getIndexAlgorithm_", useLocale);
    1435          90 :         of.writeRefFunction("getUnicodeScripts_", useLocale);
    1436          90 :         of.writeRefFunction("getFollowPageWords_", useLocale);
    1437         335 :         return;
    1438             :     }
    1439         155 :     sal_Int16 nbOfIndexs = 0;
    1440         155 :     sal_Int16 nbOfUnicodeScripts = 0;
    1441         155 :     sal_Int16 nbOfPageWords = 0;
    1442             :     sal_Int16 i;
    1443         937 :     for (i = 0; i< getNumberOfChildren();i++) {
    1444         782 :         LocaleNode * currNode = getChildAt (i);
    1445         782 :         if( currNode->getName() == "IndexKey" )
    1446             :         {
    1447         163 :             OUString str;
    1448         163 :             str = currNode->getAttr().getValueByName("unoid");
    1449         163 :             of.writeParameter("IndexID", str, nbOfIndexs);
    1450         163 :             str = currNode->getAttr().getValueByName("module");
    1451         163 :             of.writeParameter("IndexModule", str, nbOfIndexs);
    1452         163 :             str = currNode->getValue();
    1453         163 :             of.writeParameter("IndexKey", str, nbOfIndexs);
    1454         163 :             str = currNode -> getAttr().getValueByName("default");
    1455         163 :             of.writeDefaultParameter("Index", str, nbOfIndexs);
    1456         163 :             str = currNode -> getAttr().getValueByName("phonetic");
    1457         163 :             of.writeDefaultParameter("Phonetic", str, nbOfIndexs);
    1458         163 :             of.writeAsciiString("\n");
    1459             : 
    1460         163 :             nbOfIndexs++;
    1461             :         }
    1462         782 :         if( currNode->getName() == "UnicodeScript" )
    1463             :         {
    1464         313 :             of.writeParameter("unicodeScript", currNode->getValue(), nbOfUnicodeScripts );
    1465         313 :             nbOfUnicodeScripts++;
    1466             : 
    1467             :         }
    1468         782 :         if( currNode->getName() == "FollowPageWord" )
    1469             :         {
    1470         306 :             of.writeParameter("followPageWord", currNode->getValue(), nbOfPageWords);
    1471         306 :             nbOfPageWords++;
    1472             :         }
    1473             :     }
    1474         155 :     of.writeAsciiString("static const sal_Int16 nbOfIndexs = ");
    1475         155 :     of.writeInt(nbOfIndexs);
    1476         155 :     of.writeAsciiString(";\n\n");
    1477             : 
    1478         155 :     of.writeAsciiString("\nstatic const sal_Unicode* IndexArray[] = {\n");
    1479         318 :     for(i = 0; i < nbOfIndexs; i++) {
    1480         163 :         of.writeAsciiString("\tIndexID");
    1481         163 :         of.writeInt(i);
    1482         163 :         of.writeAsciiString(",\n");
    1483             : 
    1484         163 :         of.writeAsciiString("\tIndexModule");
    1485         163 :         of.writeInt(i);
    1486         163 :         of.writeAsciiString(",\n");
    1487             : 
    1488         163 :         of.writeAsciiString("\tIndexKey");
    1489         163 :         of.writeInt(i);
    1490         163 :         of.writeAsciiString(",\n");
    1491             : 
    1492         163 :         of.writeAsciiString("\tdefaultIndex");
    1493         163 :         of.writeInt(i);
    1494         163 :         of.writeAsciiString(",\n");
    1495             : 
    1496         163 :         of.writeAsciiString("\tdefaultPhonetic");
    1497         163 :         of.writeInt(i);
    1498         163 :         of.writeAsciiString(",\n");
    1499             :     }
    1500         155 :     of.writeAsciiString("};\n\n");
    1501             : 
    1502         155 :     of.writeAsciiString("static const sal_Int16 nbOfUnicodeScripts = ");
    1503         155 :     of.writeInt( nbOfUnicodeScripts );
    1504         155 :     of.writeAsciiString(";\n\n");
    1505             : 
    1506         155 :     of.writeAsciiString("static const sal_Unicode* UnicodeScriptArray[] = {");
    1507         468 :     for( i=0; i<nbOfUnicodeScripts; i++ )
    1508             :     {
    1509         313 :         of.writeAsciiString( "unicodeScript" );
    1510         313 :         of.writeInt( i );
    1511         313 :         of.writeAsciiString( ", " );
    1512             :     }
    1513         155 :     of.writeAsciiString("NULL };\n\n");
    1514             : 
    1515         155 :     of.writeAsciiString("static const sal_Int16 nbOfPageWords = ");
    1516         155 :     of.writeInt(nbOfPageWords);
    1517         155 :     of.writeAsciiString(";\n\n");
    1518             : 
    1519         155 :     of.writeAsciiString("static const sal_Unicode* FollowPageWordArray[] = {\n");
    1520         461 :     for(i = 0; i < nbOfPageWords; i++) {
    1521         306 :         of.writeAsciiString("\tfollowPageWord");
    1522         306 :         of.writeInt(i);
    1523         306 :         of.writeAsciiString(",\n");
    1524             :     }
    1525         155 :     of.writeAsciiString("\tNULL\n};\n\n");
    1526             : 
    1527         155 :     of.writeFunction("getIndexAlgorithm_", "nbOfIndexs", "IndexArray");
    1528         155 :     of.writeFunction("getUnicodeScripts_", "nbOfUnicodeScripts", "UnicodeScriptArray");
    1529         155 :     of.writeFunction("getFollowPageWords_", "nbOfPageWords", "FollowPageWordArray");
    1530             : }
    1531             : 
    1532             : 
    1533        8685 : static void lcl_writeAbbrFullNarrNames( const OFileWriter & of, const LocaleNode* currNode,
    1534             :         const sal_Char* elementTag, sal_Int16 i, sal_Int16 j )
    1535             : {
    1536        8685 :     OUString aAbbrName = currNode->getChildAt(1)->getValue();
    1537       17370 :     OUString aFullName = currNode->getChildAt(2)->getValue();
    1538       17370 :     OUString aNarrName;
    1539        8685 :     LocaleNode* p = (currNode->getNumberOfChildren() > 3 ? currNode->getChildAt(3) : 0);
    1540        8685 :     if ( p && p->getName() == "DefaultNarrowName" )
    1541           0 :         aNarrName = p->getValue();
    1542             :     else
    1543             :     {
    1544        8685 :         sal_Int32 nIndex = 0;
    1545        8685 :         sal_uInt32 nChar = aFullName.iterateCodePoints( &nIndex);
    1546        8685 :         aNarrName = OUString( &nChar, 1);
    1547             :     }
    1548        8685 :     of.writeParameter( elementTag, "DefaultAbbrvName",  aAbbrName, i, j);
    1549        8685 :     of.writeParameter( elementTag, "DefaultFullName",   aFullName, i, j);
    1550       17370 :     of.writeParameter( elementTag, "DefaultNarrowName", aNarrName, i, j);
    1551        8685 : }
    1552             : 
    1553       36043 : static void lcl_writeTabTagString( const OFileWriter & of, const sal_Char* pTag, const sal_Char* pStr )
    1554             : {
    1555       36043 :     of.writeAsciiString("\t");
    1556       36043 :     of.writeAsciiString( pTag);
    1557       36043 :     of.writeAsciiString( pStr);
    1558       36043 : }
    1559             : 
    1560       35961 : static void lcl_writeTabTagStringNums( const OFileWriter & of,
    1561             :         const sal_Char* pTag, const sal_Char* pStr, sal_Int16 i, sal_Int16 j )
    1562             : {
    1563       35961 :     lcl_writeTabTagString( of, pTag, pStr);
    1564       35961 :     of.writeInt(i); of.writeInt(j); of.writeAsciiString(",\n");
    1565       35961 : }
    1566             : 
    1567        1050 : static void lcl_writeAbbrFullNarrArrays( const OFileWriter & of, sal_Int16 nCount,
    1568             :         const sal_Char* elementTag, sal_Int16 i, bool bNarrow )
    1569             : {
    1570        1050 :     if (nCount == 0)
    1571             :     {
    1572          41 :         lcl_writeTabTagString( of, elementTag, "Ref");
    1573          41 :         of.writeInt(i); of.writeAsciiString(",\n");
    1574          41 :         lcl_writeTabTagString( of, elementTag, "RefName");
    1575          41 :         of.writeInt(i); of.writeAsciiString(",\n");
    1576             :     }
    1577             :     else
    1578             :     {
    1579       10101 :         for (sal_Int16 j = 0; j < nCount; j++)
    1580             :         {
    1581        9092 :             lcl_writeTabTagStringNums( of, elementTag, "ID", i, j);
    1582        9092 :             lcl_writeTabTagStringNums( of, elementTag, "DefaultAbbrvName",  i, j);
    1583        9092 :             lcl_writeTabTagStringNums( of, elementTag, "DefaultFullName",   i, j);
    1584        9092 :             if (bNarrow)
    1585        8685 :                 lcl_writeTabTagStringNums( of, elementTag, "DefaultNarrowName", i, j);
    1586             :         }
    1587             :     }
    1588        1050 : }
    1589             : 
    1590         245 : void LCCalendarNode::generateCode (const OFileWriter &of) const
    1591             : {
    1592         245 :     OUString useLocale =   getAttr().getValueByName("ref");
    1593         245 :     if (!useLocale.isEmpty()) {
    1594          49 :         useLocale = useLocale.replace( '-', '_');
    1595          49 :         of.writeRefFunction("getAllCalendars_", useLocale);
    1596         294 :         return;
    1597             :     }
    1598         196 :     sal_Int16 nbOfCalendars = sal::static_int_cast<sal_Int16>( getNumberOfChildren() );
    1599         392 :     OUString str;
    1600         196 :     sal_Int16 * nbOfDays = new sal_Int16[nbOfCalendars];
    1601         196 :     sal_Int16 * nbOfMonths = new sal_Int16[nbOfCalendars];
    1602         196 :     sal_Int16 * nbOfGenitiveMonths = new sal_Int16[nbOfCalendars];
    1603         196 :     sal_Int16 * nbOfPartitiveMonths = new sal_Int16[nbOfCalendars];
    1604         196 :     sal_Int16 * nbOfEras = new sal_Int16[nbOfCalendars];
    1605             :     sal_Int16 j;
    1606             :     sal_Int16 i;
    1607         196 :     bool bHasGregorian = false;
    1608             : 
    1609             : 
    1610         406 :     for ( i = 0; i < nbOfCalendars; i++) {
    1611         210 :         LocaleNode * calNode = getChildAt (i);
    1612         210 :         OUString calendarID = calNode -> getAttr().getValueByName("unoid");
    1613         210 :         of.writeParameter( "calendarID", calendarID, i);
    1614         210 :         bool bGregorian = calendarID == "gregorian";
    1615         210 :         if (!bHasGregorian)
    1616         198 :             bHasGregorian = bGregorian;
    1617         210 :         str = calNode -> getAttr().getValueByName("default");
    1618         210 :         of.writeDefaultParameter("Calendar", str, i);
    1619             : 
    1620         210 :         sal_Int16 nChild = 0;
    1621             : 
    1622             :         // Generate Days of Week
    1623             :         const sal_Char *elementTag;
    1624         210 :         LocaleNode * daysNode = NULL;
    1625         420 :         OUString ref_name = calNode->getChildAt(nChild)->getAttr().getValueByName("ref");
    1626         210 :         ref_name = ref_name.replace( '-', '_');
    1627         210 :         if (!ref_name.isEmpty() && i > 0) {
    1628           6 :             for (j = 0; j < i; j++) {
    1629           3 :                 str = getChildAt(j)->getAttr().getValueByName("unoid");
    1630           3 :                 if (str.equals(ref_name))
    1631           2 :                     daysNode = getChildAt(j)->getChildAt(0);
    1632             :             }
    1633             :         }
    1634         210 :         if (!ref_name.isEmpty() && daysNode == NULL) {
    1635           9 :             of.writeParameter("dayRef", OUString("ref"), i);
    1636           9 :             of.writeParameter("dayRefName", ref_name, i);
    1637           9 :             nbOfDays[i] = 0;
    1638             :         } else {
    1639         201 :             if (daysNode == NULL)
    1640         199 :                 daysNode = calNode -> getChildAt(nChild);
    1641         201 :             nbOfDays[i] = sal::static_int_cast<sal_Int16>( daysNode->getNumberOfChildren() );
    1642         201 :             if (bGregorian && nbOfDays[i] != 7)
    1643           0 :                 incErrorInt( "Error: A Gregorian calendar must have 7 days per week, this one has %d\n", nbOfDays[i]);
    1644         201 :             elementTag = "day";
    1645        1608 :             for (j = 0; j < nbOfDays[i]; j++) {
    1646        1407 :                 LocaleNode *currNode = daysNode -> getChildAt(j);
    1647        1407 :                 OUString dayID( currNode->getChildAt(0)->getValue());
    1648        1407 :                 of.writeParameter("dayID", dayID, i, j);
    1649        1407 :                 if ( j == 0 && bGregorian && dayID != "sun" )
    1650           0 :                     incError( "First day of a week of a Gregorian calendar must be <DayID>sun</DayID>");
    1651        1407 :                 lcl_writeAbbrFullNarrNames( of, currNode, elementTag, i, j);
    1652        1407 :             }
    1653             :         }
    1654         210 :         ++nChild;
    1655             : 
    1656             :         // Generate Months of Year
    1657         210 :         LocaleNode * monthsNode = NULL;
    1658         210 :         ref_name = calNode->getChildAt(nChild)->getAttr().getValueByName("ref");
    1659         210 :         ref_name = ref_name.replace( '-', '_');
    1660         210 :         if (!ref_name.isEmpty() && i > 0) {
    1661           2 :             for (j = 0; j < i; j++) {
    1662           1 :                 str = getChildAt(j)->getAttr().getValueByName("unoid");
    1663           1 :                 if (str.equals(ref_name))
    1664           1 :                     monthsNode = getChildAt(j)->getChildAt(1);
    1665             :             }
    1666             :         }
    1667         210 :         if (!ref_name.isEmpty() && monthsNode == NULL) {
    1668           8 :             of.writeParameter("monthRef", OUString("ref"), i);
    1669           8 :             of.writeParameter("monthRefName", ref_name, i);
    1670           8 :             nbOfMonths[i] = 0;
    1671             :         } else {
    1672         202 :             if (monthsNode == NULL)
    1673         201 :                 monthsNode = calNode -> getChildAt(nChild);
    1674         202 :             nbOfMonths[i] = sal::static_int_cast<sal_Int16>( monthsNode->getNumberOfChildren() );
    1675         202 :             if (bGregorian && nbOfMonths[i] != 12)
    1676           0 :                 incErrorInt( "Error: A Gregorian calendar must have 12 months, this one has %d\n", nbOfMonths[i]);
    1677         202 :             elementTag = "month";
    1678        2628 :             for (j = 0; j < nbOfMonths[i]; j++) {
    1679        2426 :                 LocaleNode *currNode = monthsNode -> getChildAt(j);
    1680        2426 :                 OUString monthID( currNode->getChildAt(0)->getValue());
    1681        2426 :                 of.writeParameter("monthID", monthID, i, j);
    1682        2426 :                 if ( j == 0 && bGregorian && monthID != "jan" )
    1683           0 :                     incError( "First month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
    1684        2426 :                 lcl_writeAbbrFullNarrNames( of, currNode, elementTag, i, j);
    1685        2426 :             }
    1686             :         }
    1687         210 :         ++nChild;
    1688             : 
    1689             :         // Generate genitive Months of Year
    1690             :         // Optional, if not present fall back to month nouns.
    1691         210 :         if ( calNode->getChildAt(nChild)->getName() != "GenitiveMonths" )
    1692         200 :             --nChild;
    1693         210 :         LocaleNode * genitiveMonthsNode = NULL;
    1694         210 :         ref_name = calNode->getChildAt(nChild)->getAttr().getValueByName("ref");
    1695         210 :         ref_name = ref_name.replace( '-', '_');
    1696         210 :         if (!ref_name.isEmpty() && i > 0) {
    1697           2 :             for (j = 0; j < i; j++) {
    1698           1 :                 str = getChildAt(j)->getAttr().getValueByName("unoid");
    1699           1 :                 if (str.equals(ref_name))
    1700           1 :                     genitiveMonthsNode = getChildAt(j)->getChildAt(1);
    1701             :             }
    1702             :         }
    1703         210 :         if (!ref_name.isEmpty() && genitiveMonthsNode == NULL) {
    1704           8 :             of.writeParameter("genitiveMonthRef", OUString("ref"), i);
    1705           8 :             of.writeParameter("genitiveMonthRefName", ref_name, i);
    1706           8 :             nbOfGenitiveMonths[i] = 0;
    1707             :         } else {
    1708         202 :             if (genitiveMonthsNode == NULL)
    1709         201 :                 genitiveMonthsNode = calNode -> getChildAt(nChild);
    1710         202 :             nbOfGenitiveMonths[i] = sal::static_int_cast<sal_Int16>( genitiveMonthsNode->getNumberOfChildren() );
    1711         202 :             if (bGregorian && nbOfGenitiveMonths[i] != 12)
    1712           0 :                 incErrorInt( "Error: A Gregorian calendar must have 12 genitive months, this one has %d\n", nbOfGenitiveMonths[i]);
    1713         202 :             elementTag = "genitiveMonth";
    1714        2628 :             for (j = 0; j < nbOfGenitiveMonths[i]; j++) {
    1715        2426 :                 LocaleNode *currNode = genitiveMonthsNode -> getChildAt(j);
    1716        2426 :                 OUString genitiveMonthID( currNode->getChildAt(0)->getValue());
    1717        2426 :                 of.writeParameter("genitiveMonthID", genitiveMonthID, i, j);
    1718        2426 :                 if ( j == 0 && bGregorian && genitiveMonthID != "jan" )
    1719           0 :                     incError( "First genitive month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
    1720        2426 :                 lcl_writeAbbrFullNarrNames( of, currNode, elementTag, i, j);
    1721        2426 :             }
    1722             :         }
    1723         210 :         ++nChild;
    1724             : 
    1725             :         // Generate partitive Months of Year
    1726             :         // Optional, if not present fall back to genitive months, or nominative
    1727             :         // months (nouns) if that isn't present either.
    1728         210 :         if ( calNode->getChildAt(nChild)->getName() != "PartitiveMonths" )
    1729         206 :             --nChild;
    1730         210 :         LocaleNode * partitiveMonthsNode = NULL;
    1731         210 :         ref_name = calNode->getChildAt(nChild)->getAttr().getValueByName("ref");
    1732         210 :         ref_name = ref_name.replace( '-', '_');
    1733         210 :         if (!ref_name.isEmpty() && i > 0) {
    1734           2 :             for (j = 0; j < i; j++) {
    1735           1 :                 str = getChildAt(j)->getAttr().getValueByName("unoid");
    1736           1 :                 if (str.equals(ref_name))
    1737           1 :                     partitiveMonthsNode = getChildAt(j)->getChildAt(1);
    1738             :             }
    1739             :         }
    1740         210 :         if (!ref_name.isEmpty() && partitiveMonthsNode == NULL) {
    1741           8 :             of.writeParameter("partitiveMonthRef", OUString("ref"), i);
    1742           8 :             of.writeParameter("partitiveMonthRefName", ref_name, i);
    1743           8 :             nbOfPartitiveMonths[i] = 0;
    1744             :         } else {
    1745         202 :             if (partitiveMonthsNode == NULL)
    1746         201 :                 partitiveMonthsNode = calNode -> getChildAt(nChild);
    1747         202 :             nbOfPartitiveMonths[i] = sal::static_int_cast<sal_Int16>( partitiveMonthsNode->getNumberOfChildren() );
    1748         202 :             if (bGregorian && nbOfPartitiveMonths[i] != 12)
    1749           0 :                 incErrorInt( "Error: A Gregorian calendar must have 12 partitive months, this one has %d\n", nbOfPartitiveMonths[i]);
    1750         202 :             elementTag = "partitiveMonth";
    1751        2628 :             for (j = 0; j < nbOfPartitiveMonths[i]; j++) {
    1752        2426 :                 LocaleNode *currNode = partitiveMonthsNode -> getChildAt(j);
    1753        2426 :                 OUString partitiveMonthID( currNode->getChildAt(0)->getValue());
    1754        2426 :                 of.writeParameter("partitiveMonthID", partitiveMonthID, i, j);
    1755        2426 :                 if ( j == 0 && bGregorian && partitiveMonthID != "jan" )
    1756           0 :                     incError( "First partitive month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
    1757        2426 :                 lcl_writeAbbrFullNarrNames( of, currNode, elementTag, i, j);
    1758        2426 :             }
    1759             :         }
    1760         210 :         ++nChild;
    1761             : 
    1762             :         // Generate Era name
    1763         210 :         LocaleNode * erasNode = NULL;
    1764         210 :         ref_name =   calNode -> getChildAt(nChild) ->getAttr().getValueByName("ref");
    1765         210 :         ref_name = ref_name.replace( '-', '_');
    1766         210 :         if (!ref_name.isEmpty() && i > 0) {
    1767           0 :             for (j = 0; j < i; j++) {
    1768           0 :                 str = getChildAt(j)->getAttr().getValueByName("unoid");
    1769           0 :                 if (str.equals(ref_name))
    1770           0 :                     erasNode = getChildAt(j)->getChildAt(2);
    1771             :             }
    1772             :         }
    1773         210 :         if (!ref_name.isEmpty() && erasNode == NULL) {
    1774           8 :             of.writeParameter("eraRef", OUString("ref"), i);
    1775           8 :             of.writeParameter("eraRefName", ref_name, i);
    1776           8 :             nbOfEras[i] = 0;
    1777             :         } else {
    1778         202 :             if (erasNode == NULL)
    1779         202 :                 erasNode = calNode -> getChildAt(nChild);
    1780         202 :             nbOfEras[i] = sal::static_int_cast<sal_Int16>( erasNode->getNumberOfChildren() );
    1781         202 :             if (bGregorian && nbOfEras[i] != 2)
    1782           0 :                 incErrorInt( "Error: A Gregorian calendar must have 2 eras, this one has %d\n", nbOfEras[i]);
    1783         202 :             elementTag = "era";
    1784         609 :             for (j = 0; j < nbOfEras[i]; j++) {
    1785         407 :                 LocaleNode *currNode = erasNode -> getChildAt(j);
    1786         407 :                 OUString eraID( currNode->getChildAt(0)->getValue());
    1787         407 :                 of.writeParameter("eraID", eraID, i, j);
    1788         407 :                 if ( j == 0 && bGregorian && eraID != "bc" )
    1789           0 :                     incError( "First era of a Gregorian calendar must be <EraID>bc</EraID>");
    1790         407 :                 if ( j == 1 && bGregorian && eraID != "ad" )
    1791           0 :                     incError( "Second era of a Gregorian calendar must be <EraID>ad</EraID>");
    1792         407 :                 of.writeAsciiString("\n");
    1793         407 :                 of.writeParameter(elementTag, "DefaultAbbrvName",currNode->getChildAt(1)->getValue() ,i, j);
    1794         407 :                 of.writeParameter(elementTag, "DefaultFullName",currNode->getChildAt(2)->getValue() , i, j);
    1795         407 :             }
    1796             :         }
    1797         210 :         ++nChild;
    1798             : 
    1799         210 :         str = calNode->getChildAt(nChild)->getChildAt(0)->getValue();
    1800         210 :         if (nbOfDays[i])
    1801             :         {
    1802         434 :             for (j = 0; j < nbOfDays[i]; j++)
    1803             :             {
    1804         434 :                 LocaleNode *currNode = daysNode->getChildAt(j);
    1805         434 :                 OUString dayID( currNode->getChildAt(0)->getValue());
    1806         434 :                 if (str == dayID)
    1807         201 :                     break;  // for
    1808         233 :             }
    1809         201 :             if (j >= nbOfDays[i])
    1810           0 :                 incErrorStr( "Error: <StartDayOfWeek> <DayID> must be one of the <DaysOfWeek>, but is: %s\n", str);
    1811             :         }
    1812         210 :         of.writeParameter("startDayOfWeek", str, i);
    1813         210 :         ++nChild;
    1814             : 
    1815         210 :         str = calNode ->getChildAt(nChild)-> getValue();
    1816         210 :         sal_Int16 nDays = sal::static_int_cast<sal_Int16>( str.toInt32() );
    1817         210 :         if (nDays < 1 || (0 < nbOfDays[i] && nbOfDays[i] < nDays))
    1818           0 :             incErrorInt( "Error: Bad value of MinimalDaysInFirstWeek: %d, must be 1 <= value <= days_in_week\n",  nDays);
    1819         210 :         of.writeIntParameter("minimalDaysInFirstWeek", i, nDays);
    1820         210 :     }
    1821         196 :     if (!bHasGregorian)
    1822           0 :         fprintf( stderr, "Warning: %s\n", "No Gregorian calendar defined, are you sure?");
    1823             : 
    1824         196 :     of.writeAsciiString("static const sal_Int16 calendarsCount = ");
    1825         196 :     of.writeInt(nbOfCalendars);
    1826         196 :     of.writeAsciiString(";\n\n");
    1827             : 
    1828         196 :     of.writeAsciiString("static const sal_Unicode nbOfDays[] = {");
    1829         210 :     for(i = 0; i < nbOfCalendars - 1; i++) {
    1830          14 :         of.writeInt(nbOfDays[i]);
    1831          14 :         of.writeAsciiString(", ");
    1832             :     }
    1833         196 :     of.writeInt(nbOfDays[i]);
    1834         196 :     of.writeAsciiString("};\n");
    1835             : 
    1836         196 :     of.writeAsciiString("static const sal_Unicode nbOfMonths[] = {");
    1837         210 :     for(i = 0; i < nbOfCalendars - 1; i++) {
    1838          14 :         of.writeInt(nbOfMonths[i]);
    1839          14 :         of.writeAsciiString(", ");
    1840             :     }
    1841         196 :     of.writeInt(nbOfMonths[i]);
    1842         196 :     of.writeAsciiString("};\n");
    1843             : 
    1844         196 :     of.writeAsciiString("static const sal_Unicode nbOfGenitiveMonths[] = {");
    1845         210 :     for(i = 0; i < nbOfCalendars - 1; i++) {
    1846          14 :         of.writeInt(nbOfGenitiveMonths[i]);
    1847          14 :         of.writeAsciiString(", ");
    1848             :     }
    1849         196 :     of.writeInt(nbOfGenitiveMonths[i]);
    1850         196 :     of.writeAsciiString("};\n");
    1851             : 
    1852         196 :     of.writeAsciiString("static const sal_Unicode nbOfPartitiveMonths[] = {");
    1853         210 :     for(i = 0; i < nbOfCalendars - 1; i++) {
    1854          14 :         of.writeInt(nbOfPartitiveMonths[i]);
    1855          14 :         of.writeAsciiString(", ");
    1856             :     }
    1857         196 :     of.writeInt(nbOfPartitiveMonths[i]);
    1858         196 :     of.writeAsciiString("};\n");
    1859             : 
    1860         196 :     of.writeAsciiString("static const sal_Unicode nbOfEras[] = {");
    1861         210 :     for(i = 0; i < nbOfCalendars - 1; i++) {
    1862          14 :         of.writeInt(nbOfEras[i]);
    1863          14 :         of.writeAsciiString(", ");
    1864             :     }
    1865         196 :     of.writeInt(nbOfEras[i]);
    1866         196 :     of.writeAsciiString("};\n");
    1867             : 
    1868             : 
    1869         196 :     of.writeAsciiString("static const sal_Unicode* calendars[] = {\n");
    1870         196 :     of.writeAsciiString("\tnbOfDays,\n");
    1871         196 :     of.writeAsciiString("\tnbOfMonths,\n");
    1872         196 :     of.writeAsciiString("\tnbOfGenitiveMonths,\n");
    1873         196 :     of.writeAsciiString("\tnbOfPartitiveMonths,\n");
    1874         196 :     of.writeAsciiString("\tnbOfEras,\n");
    1875         406 :     for(i = 0; i < nbOfCalendars; i++) {
    1876         210 :         of.writeAsciiString("\tcalendarID");
    1877         210 :         of.writeInt(i);
    1878         210 :         of.writeAsciiString(",\n");
    1879         210 :         of.writeAsciiString("\tdefaultCalendar");
    1880         210 :         of.writeInt(i);
    1881         210 :         of.writeAsciiString(",\n");
    1882         210 :         lcl_writeAbbrFullNarrArrays( of, nbOfDays[i], "day", i, true);
    1883         210 :         lcl_writeAbbrFullNarrArrays( of, nbOfMonths[i], "month", i, true);
    1884         210 :         lcl_writeAbbrFullNarrArrays( of, nbOfGenitiveMonths[i], "genitiveMonth", i, true);
    1885         210 :         lcl_writeAbbrFullNarrArrays( of, nbOfPartitiveMonths[i], "partitiveMonth", i, true);
    1886         210 :         lcl_writeAbbrFullNarrArrays( of, nbOfEras[i], "era", i, false /*noNarrow*/);
    1887         210 :         of.writeAsciiString("\tstartDayOfWeek");of.writeInt(i); of.writeAsciiString(",\n");
    1888         210 :         of.writeAsciiString("\tminimalDaysInFirstWeek");of.writeInt(i); of.writeAsciiString(",\n");
    1889             :     }
    1890             : 
    1891         196 :     of.writeAsciiString("};\n\n");
    1892         196 :     of.writeFunction("getAllCalendars_", "calendarsCount", "calendars");
    1893             : 
    1894         196 :     delete []nbOfDays;
    1895         196 :     delete []nbOfMonths;
    1896         196 :     delete []nbOfGenitiveMonths;
    1897         196 :     delete []nbOfPartitiveMonths;
    1898         392 :     delete []nbOfEras;
    1899             : }
    1900             : 
    1901         514 : bool isIso4217( const OUString& rStr )
    1902             : {
    1903         514 :     const sal_Unicode* p = rStr.getStr();
    1904         514 :     return rStr.getLength() == 3
    1905         514 :         && 'A' <= p[0] && p[0] <= 'Z'
    1906         514 :         && 'A' <= p[1] && p[1] <= 'Z'
    1907        1028 :         && 'A' <= p[2] && p[2] <= 'Z'
    1908             :         ;
    1909             : }
    1910             : 
    1911         245 : void LCCurrencyNode :: generateCode (const OFileWriter &of) const
    1912             : {
    1913         245 :     OUString useLocale =   getAttr().getValueByName("ref");
    1914         245 :     if (!useLocale.isEmpty()) {
    1915          46 :         useLocale = useLocale.replace( '-', '_');
    1916          46 :         of.writeRefFunction("getAllCurrencies_", useLocale);
    1917         291 :         return;
    1918             :     }
    1919         199 :     sal_Int16 nbOfCurrencies = 0;
    1920         398 :     OUString str;
    1921             :     sal_Int16 i;
    1922             : 
    1923         199 :     bool bTheDefault= false;
    1924         199 :     bool bTheCompatible = false;
    1925         495 :     for ( i = 0; i < getNumberOfChildren(); i++,nbOfCurrencies++) {
    1926         296 :         LocaleNode * currencyNode = getChildAt (i);
    1927         296 :         str = currencyNode->getAttr().getValueByName("default");
    1928         296 :         bool bDefault = of.writeDefaultParameter("Currency", str, nbOfCurrencies);
    1929         296 :         str = currencyNode->getAttr().getValueByName("usedInCompatibleFormatCodes");
    1930         296 :         bool bCompatible = of.writeDefaultParameter("CurrencyUsedInCompatibleFormatCodes", str, nbOfCurrencies);
    1931         296 :         str = currencyNode->getAttr().getValueByName("legacyOnly");
    1932         296 :         bool bLegacy = of.writeDefaultParameter("CurrencyLegacyOnly", str, nbOfCurrencies);
    1933         296 :         if (bLegacy && (bDefault || bCompatible))
    1934           0 :             incError( "Currency: if legacyOnly==true, both 'default' and 'usedInCompatibleFormatCodes' must be false.");
    1935         296 :         if (bDefault)
    1936             :         {
    1937         199 :             if (bTheDefault)
    1938           0 :                 incError( "Currency: more than one default currency.");
    1939         199 :             bTheDefault = true;
    1940             :         }
    1941         296 :         if (bCompatible)
    1942             :         {
    1943         199 :             if (bTheCompatible)
    1944           0 :                 incError( "Currency: more than one currency flagged as usedInCompatibleFormatCodes.");
    1945         199 :             bTheCompatible = true;
    1946             :         }
    1947         296 :         str = currencyNode -> findNode ("CurrencyID") -> getValue();
    1948         296 :         of.writeParameter("currencyID", str, nbOfCurrencies);
    1949             :         // CurrencyID MUST be ISO 4217.
    1950         296 :         if (!bLegacy && !isIso4217(str))
    1951           0 :             incError( "CurrencyID is not ISO 4217");
    1952         296 :         str = currencyNode -> findNode ("CurrencySymbol") -> getValue();
    1953         296 :         of.writeParameter("currencySymbol", str, nbOfCurrencies);
    1954             :         // Check if this currency really is the one used in number format
    1955             :         // codes. In case of ref=... mechanisms it may be that TheCurrency
    1956             :         // couldn't had been determined from the current locale (i.e. is
    1957             :         // empty), silently assume the referred locale has things right.
    1958         296 :         if (bCompatible && !sTheCompatibleCurrency.isEmpty() && sTheCompatibleCurrency != str)
    1959           0 :             incErrorStrStr( "Error: CurrencySymbol \"%s\" flagged as usedInCompatibleFormatCodes doesn't match \"%s\" determined from format codes.\n", str, sTheCompatibleCurrency);
    1960         296 :         str = currencyNode -> findNode ("BankSymbol") -> getValue();
    1961         296 :         of.writeParameter("bankSymbol", str, nbOfCurrencies);
    1962             :         // BankSymbol currently must be ISO 4217. May change later if
    1963             :         // application always uses CurrencyID instead of BankSymbol.
    1964         296 :         if (!bLegacy && !isIso4217(str))
    1965           0 :             incError( "BankSymbol is not ISO 4217");
    1966         296 :         str = currencyNode -> findNode ("CurrencyName") -> getValue();
    1967         296 :         of.writeParameter("currencyName", str, nbOfCurrencies);
    1968         296 :         str = currencyNode -> findNode ("DecimalPlaces") -> getValue();
    1969         296 :         sal_Int16 nDecimalPlaces = (sal_Int16)str.toInt32();
    1970         296 :         of.writeIntParameter("currencyDecimalPlaces", nbOfCurrencies, nDecimalPlaces);
    1971         296 :         of.writeAsciiString("\n");
    1972             :     };
    1973             : 
    1974         199 :     if (!bTheDefault)
    1975           0 :         incError( "Currency: no default currency.");
    1976         199 :     if (!bTheCompatible)
    1977           0 :         incError( "Currency: no currency flagged as usedInCompatibleFormatCodes.");
    1978             : 
    1979         199 :     of.writeAsciiString("static const sal_Int16 currencyCount = ");
    1980         199 :     of.writeInt(nbOfCurrencies);
    1981         199 :     of.writeAsciiString(";\n\n");
    1982         199 :     of.writeAsciiString("static const sal_Unicode* currencies[] = {\n");
    1983         495 :     for(i = 0; i < nbOfCurrencies; i++) {
    1984         296 :         of.writeAsciiString("\tcurrencyID");
    1985         296 :         of.writeInt(i);
    1986         296 :         of.writeAsciiString(",\n");
    1987         296 :         of.writeAsciiString("\tcurrencySymbol");
    1988         296 :         of.writeInt(i);
    1989         296 :         of.writeAsciiString(",\n");
    1990         296 :         of.writeAsciiString("\tbankSymbol");
    1991         296 :         of.writeInt(i);
    1992         296 :         of.writeAsciiString(",\n");
    1993         296 :         of.writeAsciiString("\tcurrencyName");
    1994         296 :         of.writeInt(i);
    1995         296 :         of.writeAsciiString(",\n");
    1996         296 :         of.writeAsciiString("\tdefaultCurrency");
    1997         296 :         of.writeInt(i);
    1998         296 :         of.writeAsciiString(",\n");
    1999         296 :         of.writeAsciiString("\tdefaultCurrencyUsedInCompatibleFormatCodes");
    2000         296 :         of.writeInt(i);
    2001         296 :         of.writeAsciiString(",\n");
    2002         296 :         of.writeAsciiString("\tcurrencyDecimalPlaces");
    2003         296 :         of.writeInt(i);
    2004         296 :         of.writeAsciiString(",\n");
    2005         296 :         of.writeAsciiString("\tdefaultCurrencyLegacyOnly");
    2006         296 :         of.writeInt(i);
    2007         296 :         of.writeAsciiString(",\n");
    2008             :     }
    2009         199 :     of.writeAsciiString("};\n\n");
    2010         398 :     of.writeFunction("getAllCurrencies_", "currencyCount", "currencies");
    2011             : }
    2012             : 
    2013         245 : void LCTransliterationNode::generateCode (const OFileWriter &of) const
    2014             : {
    2015         245 :     OUString useLocale =   getAttr().getValueByName("ref");
    2016         245 :     if (!useLocale.isEmpty()) {
    2017         142 :         useLocale = useLocale.replace( '-', '_');
    2018         142 :         of.writeRefFunction("getTransliterations_", useLocale);
    2019         387 :         return;
    2020             :     }
    2021         103 :     sal_Int16 nbOfModules = 0;
    2022         206 :     OUString str;
    2023             :     sal_Int16 i;
    2024             : 
    2025         663 :     for ( i = 0; i < getNumberOfChildren(); i++,nbOfModules++) {
    2026         560 :         LocaleNode * transNode = getChildAt (i);
    2027         560 :         str = transNode->getAttr().getValueByIndex(0);
    2028         560 :         of.writeParameter("Transliteration", str, nbOfModules);
    2029             :     }
    2030         103 :     of.writeAsciiString("static const sal_Int16 nbOfTransliterations = ");
    2031         103 :     of.writeInt(nbOfModules);
    2032         103 :     of.writeAsciiString(";\n\n");
    2033             : 
    2034         103 :     of.writeAsciiString("\nstatic const sal_Unicode* LCTransliterationsArray[] = {\n");
    2035         663 :     for( i = 0; i < nbOfModules; i++) {
    2036         560 :         of.writeAsciiString("\tTransliteration");
    2037         560 :         of.writeInt(i);
    2038         560 :         of.writeAsciiString(",\n");
    2039             :     }
    2040         103 :     of.writeAsciiString("};\n\n");
    2041         206 :     of.writeFunction("getTransliterations_", "nbOfTransliterations", "LCTransliterationsArray");
    2042             : }
    2043             : 
    2044             : struct NameValuePair {
    2045             :     const sal_Char *name;
    2046             :     const sal_Char *value;
    2047             : };
    2048             : static const NameValuePair ReserveWord[] = {
    2049             :     { "trueWord", "true" },
    2050             :     { "falseWord", "false" },
    2051             :     { "quarter1Word", "1st quarter" },
    2052             :     { "quarter2Word", "2nd quarter" },
    2053             :     { "quarter3Word", "3rd quarter" },
    2054             :     { "quarter4Word", "4th quarter" },
    2055             :     { "aboveWord", "above" },
    2056             :     { "belowWord", "below" },
    2057             :     { "quarter1Abbreviation", "Q1" },
    2058             :     { "quarter2Abbreviation", "Q2" },
    2059             :     { "quarter3Abbreviation", "Q3" },
    2060             :     { "quarter4Abbreviation", "Q4" }
    2061             : };
    2062             : 
    2063         245 : void LCMiscNode::generateCode (const OFileWriter &of) const
    2064             : {
    2065         245 :     OUString useLocale =   getAttr().getValueByName("ref");
    2066         245 :     if (!useLocale.isEmpty()) {
    2067          76 :         useLocale = useLocale.replace( '-', '_');
    2068          76 :         of.writeRefFunction("getForbiddenCharacters_", useLocale);
    2069          76 :         of.writeRefFunction("getBreakIteratorRules_", useLocale);
    2070          76 :         of.writeRefFunction("getReservedWords_", useLocale);
    2071         321 :         return;
    2072             :     }
    2073         169 :     const LocaleNode * reserveNode = findNode("ReservedWords");
    2074         169 :     if (!reserveNode)
    2075           0 :         incError( "No ReservedWords element."); // should not happen if validated..
    2076         169 :     const LocaleNode * forbidNode = findNode("ForbiddenCharacters");
    2077         169 :     const LocaleNode * breakNode = findNode("BreakIteratorRules");
    2078             : 
    2079         169 :     bool bEnglishLocale = (strncmp( of.getLocale(), "en_", 3) == 0);
    2080             : 
    2081         169 :     sal_Int16 nbOfWords = 0;
    2082         338 :     OUString str;
    2083             :     sal_Int16 i;
    2084             : 
    2085        2197 :     for ( i = 0; i < sal_Int16(SAL_N_ELEMENTS(ReserveWord)); i++,nbOfWords++) {
    2086             :         const LocaleNode * curNode = (reserveNode ? reserveNode->findNode(
    2087        2028 :                     ReserveWord[i].name) : 0);
    2088        2028 :         if (!curNode)
    2089             :             fprintf( stderr,
    2090             :                     "Warning: No %s in ReservedWords, using en_US default: \"%s\".\n",
    2091           0 :                     ReserveWord[i].name, ReserveWord[i].value);
    2092        2028 :         str = curNode ? curNode -> getValue() : OUString::createFromAscii(ReserveWord[i].value);
    2093        2028 :         if (str.isEmpty())
    2094             :         {
    2095           0 :             ++nError;
    2096           0 :             fprintf( stderr, "Error: No content for ReservedWords %s.\n", ReserveWord[i].name);
    2097             :         }
    2098        2028 :         of.writeParameter("ReservedWord", str, nbOfWords);
    2099             :         // "true", ..., "below" trigger untranslated warning.
    2100        3364 :         if (!bEnglishLocale && curNode && (0 <= i && i <= 7) &&
    2101        1336 :                 str.equalsIgnoreAsciiCaseAscii( ReserveWord[i].value))
    2102             :         {
    2103             :             fprintf( stderr,
    2104             :                     "Warning: ReservedWord %s seems to be untranslated \"%s\".\n",
    2105          37 :                     ReserveWord[i].name, ReserveWord[i].value);
    2106             :         }
    2107             :     }
    2108         169 :     of.writeAsciiString("static const sal_Int16 nbOfReservedWords = ");
    2109         169 :     of.writeInt(nbOfWords);
    2110         169 :     of.writeAsciiString(";\n\n");
    2111         169 :     of.writeAsciiString("\nstatic const sal_Unicode* LCReservedWordsArray[] = {\n");
    2112        2197 :     for( i = 0; i < nbOfWords; i++) {
    2113        2028 :         of.writeAsciiString("\tReservedWord");
    2114        2028 :         of.writeInt(i);
    2115        2028 :         of.writeAsciiString(",\n");
    2116             :     }
    2117         169 :     of.writeAsciiString("};\n\n");
    2118         169 :     of.writeFunction("getReservedWords_", "nbOfReservedWords", "LCReservedWordsArray");
    2119             : 
    2120         169 :     if (forbidNode)    {
    2121           4 :          of.writeParameter( "forbiddenBegin", forbidNode -> getChildAt(0)->getValue());
    2122           4 :          of.writeParameter( "forbiddenEnd", forbidNode -> getChildAt(1)->getValue());
    2123           4 :          of.writeParameter( "hangingChars", forbidNode -> getChildAt(2)->getValue());
    2124             :     } else {
    2125         165 :          of.writeParameter( "forbiddenBegin", OUString());
    2126         165 :          of.writeParameter( "forbiddenEnd", OUString());
    2127         165 :          of.writeParameter( "hangingChars", OUString());
    2128             :     }
    2129         169 :     of.writeAsciiString("\nstatic const sal_Unicode* LCForbiddenCharactersArray[] = {\n");
    2130         169 :     of.writeAsciiString("\tforbiddenBegin,\n");
    2131         169 :     of.writeAsciiString("\tforbiddenEnd,\n");
    2132         169 :     of.writeAsciiString("\thangingChars\n");
    2133         169 :     of.writeAsciiString("};\n\n");
    2134         169 :     of.writeFunction("getForbiddenCharacters_", "3", "LCForbiddenCharactersArray");
    2135             : 
    2136         169 :     if (breakNode) {
    2137          14 :          of.writeParameter( "EditMode", breakNode -> getChildAt(0)->getValue());
    2138          14 :          of.writeParameter( "DictionaryMode", breakNode -> getChildAt(1)->getValue());
    2139          14 :          of.writeParameter( "WordCountMode", breakNode -> getChildAt(2)->getValue());
    2140          14 :          of.writeParameter( "CharacterMode", breakNode -> getChildAt(3)->getValue());
    2141          14 :          of.writeParameter( "LineMode", breakNode -> getChildAt(4)->getValue());
    2142             :     } else {
    2143         155 :          of.writeParameter( "EditMode", OUString());
    2144         155 :          of.writeParameter( "DictionaryMode", OUString());
    2145         155 :          of.writeParameter( "WordCountMode", OUString());
    2146         155 :          of.writeParameter( "CharacterMode", OUString());
    2147         155 :          of.writeParameter( "LineMode", OUString());
    2148             :     }
    2149         169 :     of.writeAsciiString("\nstatic const sal_Unicode* LCBreakIteratorRulesArray[] = {\n");
    2150         169 :     of.writeAsciiString("\tEditMode,\n");
    2151         169 :     of.writeAsciiString("\tDictionaryMode,\n");
    2152         169 :     of.writeAsciiString("\tWordCountMode,\n");
    2153         169 :     of.writeAsciiString("\tCharacterMode,\n");
    2154         169 :     of.writeAsciiString("\tLineMode\n");
    2155         169 :     of.writeAsciiString("};\n\n");
    2156         338 :     of.writeFunction("getBreakIteratorRules_", "5", "LCBreakIteratorRulesArray");
    2157             : 
    2158             : }
    2159             : 
    2160         245 : void LCNumberingLevelNode::generateCode (const OFileWriter &of) const
    2161             : {
    2162         245 :     of.writeAsciiString("// ---> ContinuousNumbering\n");
    2163         245 :     OUString useLocale =   getAttr().getValueByName("ref");
    2164         245 :     if (!useLocale.isEmpty()) {
    2165         166 :         useLocale = useLocale.replace( '-', '_');
    2166         166 :         of.writeRefFunction2("getContinuousNumberingLevels_", useLocale);
    2167         411 :         return;
    2168             :     }
    2169             : 
    2170             :     // hard code number of attributes per style.
    2171          79 :     const int   nAttributes = 5;
    2172          79 :     const char* attr[ nAttributes ] = { "Prefix", "NumType", "Suffix", "Transliteration", "NatNum" };
    2173             : 
    2174             :     // record each attribute of each style in a static C++ variable.
    2175             :     // determine number of styles on the fly.
    2176          79 :     sal_Int32 nStyles = getNumberOfChildren();
    2177             :     sal_Int32 i;
    2178             : 
    2179         728 :     for( i = 0; i < nStyles; ++i )
    2180             :     {
    2181         649 :         const Attr &q = getChildAt( i )->getAttr();
    2182        3894 :         for( sal_Int32 j=0; j<nAttributes; ++j )
    2183             :         {
    2184        3245 :             const char* name = attr[j];
    2185        3245 :             OUString   value = q.getValueByName( name );
    2186        3245 :             of.writeParameter("continuous", name, value, sal::static_int_cast<sal_Int16>(i) );
    2187        3245 :         }
    2188             :     }
    2189             : 
    2190             :     // record number of styles and attributes.
    2191          79 :     of.writeAsciiString("static const sal_Int16 continuousNbOfStyles = ");
    2192          79 :     of.writeInt( sal::static_int_cast<sal_Int16>( nStyles ) );
    2193          79 :     of.writeAsciiString(";\n\n");
    2194          79 :     of.writeAsciiString("static const sal_Int16 continuousNbOfAttributesPerStyle = ");
    2195          79 :     of.writeInt( nAttributes );
    2196          79 :     of.writeAsciiString(";\n\n");
    2197             : 
    2198             :     // generate code. (intermediate arrays)
    2199         728 :     for( i=0; i<nStyles; i++ )
    2200             :     {
    2201         649 :         of.writeAsciiString("\nstatic const sal_Unicode* continuousStyle" );
    2202         649 :         of.writeInt( sal::static_int_cast<sal_Int16>(i) );
    2203         649 :         of.writeAsciiString("[] = {\n");
    2204        3894 :         for( sal_Int32 j=0; j<nAttributes; j++)
    2205             :         {
    2206        3245 :             of.writeAsciiString("\t");
    2207        3245 :             of.writeAsciiString( "continuous" );
    2208        3245 :             of.writeAsciiString( attr[j] );
    2209        3245 :             of.writeInt(sal::static_int_cast<sal_Int16>(i));
    2210        3245 :             of.writeAsciiString(",\n");
    2211             :         }
    2212         649 :         of.writeAsciiString("\t0\n};\n\n");
    2213             :     }
    2214             : 
    2215             :     // generate code. (top-level array)
    2216          79 :     of.writeAsciiString("\n");
    2217          79 :     of.writeAsciiString("static const sal_Unicode** LCContinuousNumberingLevelsArray[] = {\n" );
    2218         728 :     for( i=0; i<nStyles; i++ )
    2219             :     {
    2220         649 :         of.writeAsciiString( "\t" );
    2221         649 :         of.writeAsciiString( "continuousStyle" );
    2222         649 :         of.writeInt( sal::static_int_cast<sal_Int16>(i) );
    2223         649 :         of.writeAsciiString( ",\n");
    2224             :     }
    2225          79 :     of.writeAsciiString("\t0\n};\n\n");
    2226             :     of.writeFunction2("getContinuousNumberingLevels_", "continuousNbOfStyles",
    2227          79 :             "continuousNbOfAttributesPerStyle", "LCContinuousNumberingLevelsArray");
    2228             : }
    2229             : 
    2230             : 
    2231         245 : void LCOutlineNumberingLevelNode::generateCode (const OFileWriter &of) const
    2232             : {
    2233         245 :     of.writeAsciiString("// ---> OutlineNumbering\n");
    2234         245 :     OUString useLocale =   getAttr().getValueByName("ref");
    2235         245 :     if (!useLocale.isEmpty()) {
    2236         216 :         useLocale = useLocale.replace( '-', '_');
    2237         216 :         of.writeRefFunction3("getOutlineNumberingLevels_", useLocale);
    2238         461 :         return;
    2239             :     }
    2240             : 
    2241             :     // hardcode number of attributes per level
    2242          29 :     const int   nAttributes = 11;
    2243             :     const char* attr[ nAttributes ] =
    2244             :     {
    2245             :         "Prefix",
    2246             :         "NumType",
    2247             :         "Suffix",
    2248             :         "BulletChar",
    2249             :         "BulletFontName",
    2250             :         "ParentNumbering",
    2251             :         "LeftMargin",
    2252             :         "SymbolTextDistance",
    2253             :         "FirstLineOffset",
    2254             :         "Transliteration",
    2255             :         "NatNum",
    2256          29 :     };
    2257             : 
    2258             :     // record each attribute of each level of each style in a static C++ variable.
    2259             :     // determine number of styles and number of levels per style on the fly.
    2260          29 :     sal_Int32 nStyles = getNumberOfChildren();
    2261          58 :     vector<sal_Int32> nLevels; // may be different for each style?
    2262         269 :     for( sal_Int32 i = 0; i < nStyles; i++ )
    2263             :     {
    2264         240 :         LocaleNode* p = getChildAt( i );
    2265         240 :         nLevels.push_back( p->getNumberOfChildren() );
    2266        1440 :         for( sal_Int32 j=0; j<nLevels.back(); j++ )
    2267             :         {
    2268        1200 :             const Attr& q = p->getChildAt( j )->getAttr();
    2269       14400 :             for( sal_Int32 k=0; k<nAttributes; ++k )
    2270             :             {
    2271       13200 :                 const char* name = attr[k];
    2272       13200 :                 OUString   value = q.getValueByName( name );
    2273             :                 of.writeParameter("outline", name, value,
    2274       13200 :                         sal::static_int_cast<sal_Int16>(i),
    2275       26400 :                         sal::static_int_cast<sal_Int16>(j) );
    2276       13200 :             }
    2277             :         }
    2278             :     }
    2279             : 
    2280             :     // verify that each style has the same number of levels.
    2281         269 :     for( size_t i=0; i<nLevels.size(); i++ )
    2282             :     {
    2283         240 :         if( nLevels[0] != nLevels[i] )
    2284             :         {
    2285           0 :             incError( "Numbering levels don't match.");
    2286             :         }
    2287             :     }
    2288             : 
    2289             :     // record number of attributes, levels, and styles.
    2290          29 :     of.writeAsciiString("static const sal_Int16 outlineNbOfStyles = ");
    2291          29 :     of.writeInt( sal::static_int_cast<sal_Int16>( nStyles ) );
    2292          29 :     of.writeAsciiString(";\n\n");
    2293          29 :     of.writeAsciiString("static const sal_Int16 outlineNbOfLevelsPerStyle = ");
    2294          29 :     of.writeInt( sal::static_int_cast<sal_Int16>( nLevels.back() ) );
    2295          29 :     of.writeAsciiString(";\n\n");
    2296          29 :     of.writeAsciiString("static const sal_Int16 outlineNbOfAttributesPerLevel = ");
    2297          29 :     of.writeInt( nAttributes );
    2298          29 :     of.writeAsciiString(";\n\n");
    2299             : 
    2300             :     // too complicated for now...
    2301             :     //     of.writeAsciiString("static const sal_Int16 nbOfOutlineNumberingLevels[] = { ");
    2302             :     //     for( sal_Int32 j=0; j<nStyles; j++ )
    2303             :     //     {
    2304             :     //          of.writeInt( nLevels[j] );
    2305             :     //          of.writeAsciiString(", ");
    2306             :     //     }
    2307             :     //     of.writeAsciiString("};\n\n");
    2308             : 
    2309             : 
    2310         269 :     for( sal_Int32 i=0; i<nStyles; i++ )
    2311             :     {
    2312        1440 :         for( sal_Int32 j=0; j<nLevels.back(); j++ )
    2313             :         {
    2314        1200 :             of.writeAsciiString("static const sal_Unicode* outline");
    2315        1200 :             of.writeAsciiString("Style");
    2316        1200 :             of.writeInt( sal::static_int_cast<sal_Int16>(i) );
    2317        1200 :             of.writeAsciiString("Level");
    2318        1200 :             of.writeInt( sal::static_int_cast<sal_Int16>(j) );
    2319        1200 :             of.writeAsciiString("[] = { ");
    2320             : 
    2321       14400 :             for( sal_Int32 k=0; k<nAttributes; k++ )
    2322             :             {
    2323       13200 :                 of.writeAsciiString( "outline" );
    2324       13200 :                 of.writeAsciiString( attr[k] );
    2325       13200 :                 of.writeInt( sal::static_int_cast<sal_Int16>(i) );
    2326       13200 :                 of.writeInt( sal::static_int_cast<sal_Int16>(j) );
    2327       13200 :                 of.writeAsciiString(", ");
    2328             :             }
    2329        1200 :             of.writeAsciiString("NULL };\n");
    2330             :         }
    2331             :     }
    2332             : 
    2333          29 :     of.writeAsciiString("\n");
    2334             : 
    2335             : 
    2336         269 :     for( sal_Int32 i=0; i<nStyles; i++ )
    2337             :     {
    2338         240 :         of.writeAsciiString("static const sal_Unicode** outline");
    2339         240 :         of.writeAsciiString( "Style" );
    2340         240 :         of.writeInt( sal::static_int_cast<sal_Int16>(i) );
    2341         240 :         of.writeAsciiString("[] = { ");
    2342             : 
    2343        1440 :         for( sal_Int32 j=0; j<nLevels.back(); j++ )
    2344             :         {
    2345        1200 :             of.writeAsciiString("outlineStyle");
    2346        1200 :             of.writeInt( sal::static_int_cast<sal_Int16>(i) );
    2347        1200 :             of.writeAsciiString("Level");
    2348        1200 :             of.writeInt( sal::static_int_cast<sal_Int16>(j) );
    2349        1200 :             of.writeAsciiString(", ");
    2350             :         }
    2351         240 :         of.writeAsciiString("NULL };\n");
    2352             :     }
    2353          29 :     of.writeAsciiString("\n");
    2354             : 
    2355          29 :     of.writeAsciiString("static const sal_Unicode*** LCOutlineNumberingLevelsArray[] = {\n" );
    2356         269 :     for( sal_Int32 i=0; i<nStyles; i++ )
    2357             :     {
    2358         240 :         of.writeAsciiString( "\t" );
    2359         240 :         of.writeAsciiString( "outlineStyle" );
    2360         240 :         of.writeInt( sal::static_int_cast<sal_Int16>(i) );
    2361         240 :         of.writeAsciiString(",\n");
    2362             :     }
    2363          29 :     of.writeAsciiString("\tNULL\n};\n\n");
    2364             :     of.writeFunction3("getOutlineNumberingLevels_", "outlineNbOfStyles", "outlineNbOfLevelsPerStyle",
    2365          58 :             "outlineNbOfAttributesPerLevel", "LCOutlineNumberingLevelsArray");
    2366             : }
    2367             : 
    2368       51550 : Attr::Attr (const Reference< XAttributeList > & attr) {
    2369       51550 :     sal_Int16 len = attr->getLength();
    2370       51550 :     name.realloc (len);
    2371       51550 :     value.realloc (len);
    2372      108305 :     for (sal_Int16 i =0; i< len;i++) {
    2373       56755 :         name[i] = attr->getNameByIndex(i);
    2374       56755 :         value[i] = attr -> getValueByIndex(i);
    2375             :     }
    2376       51550 : }
    2377             : 
    2378       63071 : const OUString& Attr::getValueByName (const sal_Char *str) const {
    2379       63071 :     static OUString empty;
    2380       63071 :     sal_Int32 len = name.getLength();
    2381      215305 :     for (sal_Int32 i = 0;i<len;i++)
    2382      207965 :         if (name[i].equalsAscii(str))
    2383       55731 :             return value[i];
    2384        7340 :     return empty;
    2385             : }
    2386             : 
    2387           0 : sal_Int32 Attr::getLength() const{
    2388           0 :     return name.getLength();
    2389             : }
    2390             : 
    2391           0 : const OUString& Attr::getTypeByIndex (sal_Int32 idx) const {
    2392           0 :     return name[idx];
    2393             : }
    2394             : 
    2395         560 : const OUString& Attr::getValueByIndex (sal_Int32 idx) const
    2396             : {
    2397         560 :     return value[idx];
    2398         735 : }
    2399             : 
    2400             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11