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

Generated by: LCOV version 1.10