summaryrefslogtreecommitdiff
path: root/i18npool/source/localedata/LocaleNode.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'i18npool/source/localedata/LocaleNode.cxx')
-rw-r--r--i18npool/source/localedata/LocaleNode.cxx1861
1 files changed, 1861 insertions, 0 deletions
diff --git a/i18npool/source/localedata/LocaleNode.cxx b/i18npool/source/localedata/LocaleNode.cxx
new file mode 100644
index 000000000000..05f6156489a6
--- /dev/null
+++ b/i18npool/source/localedata/LocaleNode.cxx
@@ -0,0 +1,1861 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_i18npool.hxx"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <set>
+
+#include <rtl/ustrbuf.hxx>
+#include <sal/macros.h>
+
+#include "LocaleNode.hxx"
+#include <com/sun/star/i18n/NumberFormatIndex.hpp>
+
+// NOTE: MUST match the Locale versionDTD attribute defined in data/locale.dtd
+#define LOCALE_VERSION_DTD "2.0.3"
+
+typedef ::std::set< ::rtl::OUString > NameSet;
+typedef ::std::set< sal_Int16 > ValueSet;
+
+namespace cssi = ::com::sun::star::i18n;
+
+LocaleNode::LocaleNode (const OUString& name, const Reference< XAttributeList > & attr)
+ : aName(name)
+ , aAttribs(attr)
+ , parent(0)
+ , children(0)
+ , nChildren(0)
+ , childArrSize(0)
+ , nError(0)
+{
+}
+
+int LocaleNode::getError() const
+{
+ int err = nError;
+ for (sal_Int32 i=0;i<nChildren;i++)
+ err += children[i]->getError();
+ return err;
+}
+
+void LocaleNode::print () const {
+ printf ("<");
+ ::rtl::OUString str (aName);
+ for(sal_Int32 i = 0; i < str.getLength(); i++)
+ printf( "%c", str[i]);
+ printf (">\n");
+}
+
+void LocaleNode::printR () const {
+ print();
+ for (sal_Int32 i=0;i<nChildren;i++)
+ children[i]->printR();
+ printf ("\t");
+ print();
+}
+
+void LocaleNode::addChild ( LocaleNode * node) {
+ if (childArrSize <= nChildren) {
+ LocaleNode ** arrN = new LocaleNode*[childArrSize+10];
+ for (sal_Int32 i = 0; i<childArrSize; ++i)
+ arrN[i] = children[i];
+ delete [] children;
+ childArrSize += 10;
+ children = arrN;
+ }
+ children[nChildren++] = node;
+ node->setParent (this);
+}
+
+void LocaleNode::setParent ( LocaleNode * node) {
+ parent = node;
+}
+
+const LocaleNode* LocaleNode::getRoot() const
+{
+ const LocaleNode* pRoot = 0;
+ const LocaleNode* pParent = this;
+ while ( (pParent = pParent->getParent()) != 0 )
+ pRoot = pParent;
+ return pRoot;
+}
+
+const LocaleNode * LocaleNode::findNode ( const sal_Char *name) const {
+ if (aName.equalsAscii(name))
+ return this;
+ for (sal_Int32 i = 0; i< nChildren; i++) {
+ const LocaleNode *n=children[i]->findNode(name);
+ if (n)
+ return n;
+ }
+ return 0;
+}
+
+LocaleNode::~LocaleNode()
+{
+ for (sal_Int32 i=0; i < nChildren; ++i)
+ delete children[i];
+ delete [] children;
+}
+
+LocaleNode* LocaleNode::createNode (const OUString& name, const Reference< XAttributeList > & attr)
+{
+ if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("LC_INFO")))
+ return new LCInfoNode (name,attr);
+ if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("LC_CTYPE")))
+ return new LCCTYPENode (name,attr);
+ if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("LC_FORMAT")))
+ return new LCFormatNode (name,attr);
+ if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("LC_FORMAT_1")))
+ return new LCFormatNode (name,attr);
+ if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("LC_CALENDAR")))
+ return new LCCalendarNode (name,attr);
+ if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("LC_CURRENCY")))
+ return new LCCurrencyNode (name,attr);
+ if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("LC_TRANSLITERATION")))
+ return new LCTransliterationNode (name,attr);
+ if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("LC_COLLATION")))
+ return new LCCollationNode (name,attr);
+ if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("LC_INDEX")))
+ return new LCIndexNode (name,attr);
+ if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("LC_SEARCH")))
+ return new LCSearchNode (name,attr);
+ if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("LC_MISC")))
+ return new LCMiscNode (name,attr);
+ if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("LC_NumberingLevel")))
+ return new LCNumberingLevelNode (name, attr);
+ if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("LC_OutLineNumberingLevel")))
+ return new LCOutlineNumberingLevelNode (name, attr);
+
+ return new LocaleNode(name,attr);
+}
+
+
+// printf(" name: '%s'\n", p->getName().pData->buffer );
+// printf("value: '%s'\n", p->getValue().pData->buffer );
+
+#define OSTR(s) (OUStringToOString( (s), RTL_TEXTENCODING_UTF8).getStr())
+
+void print_OUString( const OUString& s )
+{
+ printf( "%s", OSTR(s));
+}
+
+bool is_empty_string( const OUString& s )
+{
+ return (s.getLength()==0) || (s.getLength()==1 && s[0]=='\n');
+}
+
+void print_indent( int depth )
+{
+ for( int i=0; i<depth; i++ ) printf(" ");
+}
+
+void print_color( int color )
+{
+ printf("\033[%dm", color);
+}
+
+void print_node( const LocaleNode* p, int depth=0 )
+{
+ if( !p ) return;
+
+ print_indent( depth );
+ printf("<");
+ print_color(36);
+ print_OUString( p->getName() );
+ print_color(0);
+ const Attr& q = p->getAttr();
+ for( sal_Int32 j = 0; j < q.getLength(); ++j )
+ {
+ printf(" ");
+ print_color(33);
+ print_OUString( q.getTypeByIndex(j) );
+ print_color(0);
+ printf("=");
+ print_color(31);
+ printf("'");
+ print_OUString( q.getValueByIndex(j) );
+ printf("'");
+ print_color(0);
+ }
+ printf(">");
+ printf("\n");
+ if( !is_empty_string( p->getValue() ) )
+ {
+ print_indent( depth+1 );
+ printf("value: ");
+ print_color(31);
+ printf("'");
+ print_OUString( p->getValue() );
+ printf("'");
+ print_color(0);
+ printf("\n");
+ }
+ for( sal_Int32 i=0; i<p->getNumberOfChildren(); i++ )
+ {
+ print_node( p->getChildAt(i), depth+1 );
+ }
+ print_indent( depth );
+ printf("</");
+ print_OUString( p->getName() );
+ printf(">");
+ printf("\n");
+}
+
+void LocaleNode :: generateCode (const OFileWriter &of) const
+{
+ ::rtl::OUString aDTD = getAttr().getValueByName("versionDTD");
+ if (!aDTD.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(LOCALE_VERSION_DTD)))
+ {
+ ++nError;
+ fprintf( stderr, "Error: Locale versionDTD is not %s, see comment in locale.dtd\n", LOCALE_VERSION_DTD);
+ }
+ for (sal_Int32 i=0; i<nChildren;i++)
+ children[i]->generateCode (of);
+// print_node( this );
+}
+
+
+::rtl::OUString LocaleNode::writeParameterCheckLen( const OFileWriter &of,
+ const char* pParameterName, const LocaleNode* pNode,
+ sal_Int32 nMinLen, sal_Int32 nMaxLen ) const
+{
+ OUString aVal;
+ if (pNode)
+ aVal = pNode->getValue();
+ else
+ {
+ ++nError;
+ fprintf( stderr, "Error: node NULL pointer for parameter %s.\n",
+ pParameterName);
+ }
+ // write empty data if error
+ of.writeParameter( pParameterName, aVal);
+ sal_Int32 nLen = aVal.getLength();
+ if (nLen < nMinLen)
+ {
+ ++nError;
+ fprintf( stderr, "Error: less than %ld character%s (%ld) in %s '%s'.\n",
+ sal::static_int_cast< long >(nMinLen), (nMinLen > 1 ? "s" : ""),
+ sal::static_int_cast< long >(nLen),
+ (pNode ? OSTR( pNode->getName()) : ""),
+ OSTR( aVal));
+ }
+ else if (nLen > nMaxLen && nMaxLen >= 0)
+ fprintf( stderr,
+ "Warning: more than %ld character%s (%ld) in %s %s not supported by application.\n",
+ sal::static_int_cast< long >(nMaxLen), (nMaxLen > 1 ? "s" : ""),
+ sal::static_int_cast< long >(nLen),
+ (pNode ? OSTR( pNode->getName()) : ""),
+ OSTR( aVal));
+ return aVal;
+}
+
+
+::rtl::OUString LocaleNode::writeParameterCheckLen( const OFileWriter &of,
+ const char* pNodeName, const char* pParameterName,
+ sal_Int32 nMinLen, sal_Int32 nMaxLen ) const
+{
+ OUString aVal;
+ const LocaleNode * pNode = findNode( pNodeName);
+ if (pNode)
+ aVal = writeParameterCheckLen( of, pParameterName, pNode, nMinLen, nMaxLen);
+ else
+ {
+ ++nError;
+ fprintf( stderr, "Error: node %s not found.\n", pNodeName);
+ // write empty data if error
+ of.writeParameter( pParameterName, aVal);
+ }
+ return aVal;
+}
+
+void LocaleNode::incError( const char* pStr ) const
+{
+ ++nError;
+ fprintf( stderr, "Error: %s\n", pStr);
+}
+
+void LocaleNode::incError( const ::rtl::OUString& rStr ) const
+{
+ incError( OSTR( rStr));
+}
+
+char* LocaleNode::prepareErrorFormat( const char* pFormat, const char* pDefaultConversion ) const
+{
+ static char buf[2048];
+ strcpy( buf, "Error: ");
+ strncat( buf, pFormat, 2000);
+ char* p = buf;
+ while (((p = strchr( p, '%')) != 0) && p[1] == '%')
+ p += 2;
+ if (!p)
+ strcat( buf, pDefaultConversion);
+ strcat( buf, "\n");
+ return buf;
+}
+
+void LocaleNode::incErrorInt( const char* pStr, int nVal ) const
+{
+ ++nError;
+ fprintf( stderr, prepareErrorFormat( pStr, ": %d"), nVal);
+}
+
+void LocaleNode::incErrorStr( const char* pStr, const ::rtl::OUString& rVal ) const
+{
+ ++nError;
+ fprintf( stderr, prepareErrorFormat( pStr, ": %s"), OSTR( rVal));
+}
+
+void LCInfoNode::generateCode (const OFileWriter &of) const
+{
+
+ const LocaleNode * languageNode = findNode("Language");
+ const LocaleNode * countryNode = findNode("Country");
+ const LocaleNode * variantNode = findNode("Variant");
+
+ if (languageNode)
+ {
+ writeParameterCheckLen( of, "langID", languageNode->getChildAt(0), 2, -1);
+ of.writeParameter("langDefaultName", languageNode->getChildAt(1)->getValue());
+ }
+ else
+ incError( "No Language node.");
+ if (countryNode)
+ {
+ of.writeParameter("countryID", countryNode->getChildAt(0)->getValue());
+ of.writeParameter("countryDefaultName", countryNode->getChildAt(1)->getValue());
+ }
+ else
+ incError( "No Country node.");
+ if (variantNode)
+ {
+ of.writeParameter("Variant", variantNode->getValue());
+ fprintf( stderr, "Warning: %s\n",
+ "Variants are not supported by application.");
+ }
+ else
+ of.writeParameter("Variant", ::rtl::OUString());
+ of.writeAsciiString("\nstatic const sal_Unicode* LCInfoArray[] = {\n");
+ of.writeAsciiString("\tlangID,\n");
+ of.writeAsciiString("\tlangDefaultName,\n");
+ of.writeAsciiString("\tcountryID,\n");
+ of.writeAsciiString("\tcountryDefaultName,\n");
+ of.writeAsciiString("\tVariant\n");
+ of.writeAsciiString("};\n\n");
+ of.writeFunction("getLCInfo_", "0", "LCInfoArray");
+}
+
+void LCCTYPENode::generateCode (const OFileWriter &of) const
+{
+ const LocaleNode * sepNode = 0;
+ ::rtl::OUString useLocale = getAttr().getValueByName("ref");
+ if (useLocale.getLength() > 0) {
+ of.writeRefFunction("getLocaleItem_", useLocale);
+ return;
+ }
+ ::rtl::OUString str = getAttr().getValueByName("unoid");
+ of.writeAsciiString("\n\n");
+ of.writeParameter("LC_CTYPE_Unoid", str);;
+
+ OUString aDateSep =
+ writeParameterCheckLen( of, "DateSeparator", "dateSeparator", 1, 1);
+ OUString aThoSep =
+ writeParameterCheckLen( of, "ThousandSeparator", "thousandSeparator", 1, 1);
+ OUString aDecSep =
+ writeParameterCheckLen( of, "DecimalSeparator", "decimalSeparator", 1, 1);
+ OUString aTimeSep =
+ writeParameterCheckLen( of, "TimeSeparator", "timeSeparator", 1, 1);
+ OUString aTime100Sep =
+ writeParameterCheckLen( of, "Time100SecSeparator", "time100SecSeparator", 1, 1);
+ OUString aListSep =
+ writeParameterCheckLen( of, "ListSeparator", "listSeparator", 1, 1);
+
+ OUString aLDS;
+
+ sepNode = findNode("LongDateDayOfWeekSeparator");
+ aLDS = sepNode->getValue();
+ of.writeParameter("LongDateDayOfWeekSeparator", aLDS);
+ if (aLDS.getLength() == 1 && aLDS.getStr()[0] == ',')
+ fprintf( stderr, "Warning: %s\n",
+ "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\".");
+
+ sepNode = findNode("LongDateDaySeparator");
+ aLDS = sepNode->getValue();
+ of.writeParameter("LongDateDaySeparator", aLDS);
+ if (aLDS.getLength() == 1 && (aLDS.getStr()[0] == ',' || aLDS.getStr()[0] == '.'))
+ fprintf( stderr, "Warning: %s\n",
+ "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\".");
+
+ sepNode = findNode("LongDateMonthSeparator");
+ aLDS = sepNode->getValue();
+ of.writeParameter("LongDateMonthSeparator", aLDS);
+ if (aLDS.getLength() == 0)
+ fprintf( stderr, "Warning: %s\n",
+ "LongDateMonthSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, May9, 2007\".");
+
+ sepNode = findNode("LongDateYearSeparator");
+ aLDS = sepNode->getValue();
+ of.writeParameter("LongDateYearSeparator", aLDS);
+ if (aLDS.getLength() == 0)
+ fprintf( stderr, "Warning: %s\n",
+ "LongDateYearSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, 2007May 9\".");
+
+
+ int nSavErr = nError;
+ int nWarn = 0;
+ if (aDateSep == aTimeSep)
+ incError( "DateSeparator equals TimeSeparator.");
+ if (aDecSep == aThoSep)
+ incError( "DecimalSeparator equals ThousandSeparator.");
+ if (aThoSep.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( " ")))
+ incError( "ThousandSeparator is an ' ' ordinary space, this should be a non-breaking space U+00A0 instead.");
+ if (aListSep == aDecSep)
+ fprintf( stderr, "Warning: %s\n",
+ "ListSeparator equals DecimalSeparator.");
+ if (aListSep == aThoSep)
+ fprintf( stderr, "Warning: %s\n",
+ "ListSeparator equals ThousandSeparator.");
+ if (aListSep.getLength() != 1 || aListSep.getStr()[0] != ';')
+ {
+ incError( "ListSeparator not ';' semicolon. Strongly recommended. Currently required.");
+ ++nSavErr; // format codes not affected
+ }
+ if (aTimeSep == aTime100Sep)
+ ++nWarn, fprintf( stderr, "Warning: %s\n",
+ "Time100SecSeparator equals TimeSeparator, this is probably an error.");
+ if (aDecSep != aTime100Sep)
+ ++nWarn, fprintf( stderr, "Warning: %s\n",
+ "Time100SecSeparator is different from DecimalSeparator, this may be correct or not. Intended?");
+ if (nSavErr != nError || nWarn)
+ fprintf( stderr, "Warning: %s\n",
+ "Don't forget to adapt corresponding FormatCode elements when changing separators.");
+
+ OUString aQuoteStart =
+ writeParameterCheckLen( of, "QuotationStart", "quotationStart", 1, 1);
+ OUString aQuoteEnd =
+ writeParameterCheckLen( of, "QuotationEnd", "quotationEnd", 1, 1);
+ OUString aDoubleQuoteStart =
+ writeParameterCheckLen( of, "DoubleQuotationStart", "doubleQuotationStart", 1, 1);
+ OUString aDoubleQuoteEnd =
+ writeParameterCheckLen( of, "DoubleQuotationEnd", "doubleQuotationEnd", 1, 1);
+
+ if (aQuoteStart.toChar() <= 127 && aQuoteEnd.toChar() > 127)
+ fprintf( stderr, "Warning: %s\n",
+ "QuotationStart is an ASCII character but QuotationEnd is not.");
+ if (aQuoteEnd.toChar() <= 127 && aQuoteStart.toChar() > 127)
+ fprintf( stderr, "Warning: %s\n",
+ "QuotationEnd is an ASCII character but QuotationStart is not.");
+ if (aDoubleQuoteStart.toChar() <= 127 && aDoubleQuoteEnd.toChar() > 127)
+ fprintf( stderr, "Warning: %s\n",
+ "DoubleQuotationStart is an ASCII character but DoubleQuotationEnd is not.");
+ if (aDoubleQuoteEnd.toChar() <= 127 && aDoubleQuoteStart.toChar() > 127)
+ fprintf( stderr, "Warning: %s\n",
+ "DoubleQuotationEnd is an ASCII character but DoubleQuotationStart is not.");
+ if (aQuoteStart.toChar() <= 127 && aQuoteEnd.toChar() <= 127)
+ fprintf( stderr, "Warning: %s\n",
+ "QuotationStart and QuotationEnd are both ASCII characters. Not necessarily an error, but unusual.");
+ if (aDoubleQuoteStart.toChar() <= 127 && aDoubleQuoteEnd.toChar() <= 127)
+ fprintf( stderr, "Warning: %s\n",
+ "DoubleQuotationStart and DoubleQuotationEnd are both ASCII characters. Not necessarily an error, but unusual.");
+ if (aQuoteStart == aQuoteEnd)
+ fprintf( stderr, "Warning: %s\n",
+ "QuotationStart equals QuotationEnd. Not necessarily an error, but unusual.");
+ if (aDoubleQuoteStart == aDoubleQuoteEnd)
+ fprintf( stderr, "Warning: %s\n",
+ "DoubleQuotationStart equals DoubleQuotationEnd. Not necessarily an error, but unusual.");
+ /* TODO: should equalness of single and double quotes be an error? Would
+ * need to adapt quite some locales' data. */
+ if (aQuoteStart == aDoubleQuoteStart)
+ fprintf( stderr, "Warning: %s\n",
+ "QuotationStart equals DoubleQuotationStart. Not necessarily an error, but unusual.");
+ if (aQuoteEnd == aDoubleQuoteEnd)
+ fprintf( stderr, "Warning: %s\n",
+ "QuotationEnd equals DoubleQuotationEnd. Not necessarily an error, but unusual.");
+ // Known good values, exclude ASCII single (U+0027, ') and double (U+0022, ") quotes.
+ int ic;
+ switch (ic = aQuoteStart.toChar())
+ {
+ case 0x2018: // LEFT SINGLE QUOTATION MARK
+ case 0x201a: // SINGLE LOW-9 QUOTATION MARK
+ case 0x201b: // SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ case 0x2039: // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+ case 0x203a: // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+ case 0x300c: // LEFT CORNER BRACKET (Chinese)
+ ;
+ break;
+ default:
+ fprintf( stderr, "Warning: %s U+%04X %s\n",
+ "QuotationStart may be wrong:", ic, OSTR( aQuoteStart));
+ }
+ switch (ic = aQuoteEnd.toChar())
+ {
+ case 0x2019: // RIGHT SINGLE QUOTATION MARK
+ case 0x201a: // SINGLE LOW-9 QUOTATION MARK
+ case 0x201b: // SINGLE HIGH-REVERSED-9 QUOTATION MARK
+ case 0x2039: // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+ case 0x203a: // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+ case 0x300d: // RIGHT CORNER BRACKET (Chinese)
+ ;
+ break;
+ default:
+ fprintf( stderr, "Warning: %s U+%04X %s\n",
+ "QuotationEnd may be wrong:", ic, OSTR( aQuoteEnd));
+ }
+ switch (ic = aDoubleQuoteStart.toChar())
+ {
+ case 0x00ab: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ case 0x00bb: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+ case 0x201c: // LEFT DOUBLE QUOTATION MARK
+ case 0x201e: // DOUBLE LOW-9 QUOTATION MARK
+ case 0x201f: // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ case 0x300e: // LEFT WHITE CORNER BRACKET (Chinese)
+ ;
+ break;
+ default:
+ fprintf( stderr, "Warning: %s U+%04X %s\n",
+ "DoubleQuotationStart may be wrong:", ic, OSTR( aDoubleQuoteStart));
+ }
+ switch (ic = aDoubleQuoteEnd.toChar())
+ {
+ case 0x00ab: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ case 0x00bb: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+ case 0x201d: // RIGHT DOUBLE QUOTATION MARK
+ case 0x201e: // DOUBLE LOW-9 QUOTATION MARK
+ case 0x201f: // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+ case 0x300f: // RIGHT WHITE CORNER BRACKET (Chinese)
+ ;
+ break;
+ default:
+ fprintf( stderr, "Warning: %s U+%04X %s\n",
+ "DoubleQuotationEnd may be wrong:", ic, OSTR( aDoubleQuoteEnd));
+ }
+
+ writeParameterCheckLen( of, "TimeAM", "timeAM", 1, -1);
+ writeParameterCheckLen( of, "TimePM", "timePM", 1, -1);
+ sepNode = findNode("MeasurementSystem");
+ of.writeParameter("measurementSystem", sepNode->getValue());
+
+ of.writeAsciiString("\nstatic const sal_Unicode* LCType[] = {\n");
+ of.writeAsciiString("\tLC_CTYPE_Unoid,\n");
+ of.writeAsciiString("\tdateSeparator,\n");
+ of.writeAsciiString("\tthousandSeparator,\n");
+ of.writeAsciiString("\tdecimalSeparator,\n");
+ of.writeAsciiString("\ttimeSeparator,\n");
+ of.writeAsciiString("\ttime100SecSeparator,\n");
+ of.writeAsciiString("\tlistSeparator,\n");
+ of.writeAsciiString("\tquotationStart,\n");
+ of.writeAsciiString("\tquotationEnd,\n");
+ of.writeAsciiString("\tdoubleQuotationStart,\n");
+ of.writeAsciiString("\tdoubleQuotationEnd,\n");
+ of.writeAsciiString("\ttimeAM,\n");
+ of.writeAsciiString("\ttimePM,\n");
+ of.writeAsciiString("\tmeasurementSystem,\n");
+ of.writeAsciiString("\tLongDateDayOfWeekSeparator,\n");
+ of.writeAsciiString("\tLongDateDaySeparator,\n");
+ of.writeAsciiString("\tLongDateMonthSeparator,\n");
+ of.writeAsciiString("\tLongDateYearSeparator\n");
+ of.writeAsciiString("};\n\n");
+ of.writeFunction("getLocaleItem_", "0", "LCType");
+}
+
+
+sal_Int16 LCFormatNode::mnSection = 0;
+sal_Int16 LCFormatNode::mnFormats = 0;
+
+void LCFormatNode::generateCode (const OFileWriter &of) const
+{
+ OUString str;
+ if (mnSection >= 2)
+ incError("more than 2 LC_FORMAT sections");
+ of.writeParameter("replaceFrom", getAttr().getValueByName("replaceFrom"), mnSection);
+ str = getAttr().getValueByName("replaceTo");
+ // Locale data generator inserts FFFF for LangID, we need to adapt that.
+ if (str.endsWithIgnoreAsciiCaseAsciiL( "-FFFF]", 6))
+ incErrorStr("replaceTo=\"%s\" needs FFFF to be adapted to the real LangID value.", str);
+ of.writeParameter("replaceTo", str, mnSection);
+ ::rtl::OUString useLocale = getAttr().getValueByName("ref");
+ if (useLocale.getLength() > 0) {
+ switch (mnSection)
+ {
+ case 0:
+ of.writeRefFunction("getAllFormats0_", useLocale, "replaceTo0");
+ break;
+ case 1:
+ of.writeRefFunction("getAllFormats1_", useLocale, "replaceTo1");
+ break;
+ }
+ return;
+ }
+ sal_Int16 formatCount = mnFormats;
+ NameSet aMsgIdSet;
+ ValueSet aFormatIndexSet;
+ NameSet aDefaultsSet;
+ bool bCtypeIsRef = false;
+
+ for (sal_Int16 i = 0; i< getNumberOfChildren() ; i++,formatCount++) {
+ LocaleNode * currNode = getChildAt (i);
+ OUString aUsage;
+ OUString aType;
+ OUString aFormatIndex;
+ // currNode -> print();
+ const Attr &currNodeAttr = currNode->getAttr();
+ //printf ("getLen() = %d\n", currNode->getAttr().getLength());
+
+ str = currNodeAttr.getValueByName("msgid");
+ if (!aMsgIdSet.insert( str).second)
+ incErrorStr( "Duplicated msgid=\"%s\" in FormatElement.", str);
+ of.writeParameter("FormatKey", str, formatCount);
+
+ str = currNodeAttr.getValueByName("default");
+ bool bDefault = str.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "true"));
+ of.writeDefaultParameter("FormatElement", str, formatCount);
+
+ aType = currNodeAttr.getValueByName("type");
+ of.writeParameter("FormatType", aType, formatCount);
+
+ aUsage = currNodeAttr.getValueByName("usage");
+ of.writeParameter("FormatUsage", aUsage, formatCount);
+
+ aFormatIndex = currNodeAttr.getValueByName("formatindex");
+ sal_Int16 formatindex = (sal_Int16)aFormatIndex.toInt32();
+ if (!aFormatIndexSet.insert( formatindex).second)
+ incErrorInt( "Duplicated formatindex=\"%d\" in FormatElement.", formatindex);
+ of.writeIntParameter("Formatindex", formatCount, formatindex);
+
+ // Ensure only one default per usage and type.
+ if (bDefault)
+ {
+ OUString aKey( aUsage + OUString( sal_Unicode(',')) + aType);
+ if (!aDefaultsSet.insert( aKey).second)
+ {
+ OUString aStr( RTL_CONSTASCII_USTRINGPARAM( "Duplicated default for usage=\""));
+ aStr += aUsage;
+ aStr += OUString( RTL_CONSTASCII_USTRINGPARAM( "\" type=\""));
+ aStr += aType;
+ aStr += OUString( RTL_CONSTASCII_USTRINGPARAM( "\": formatindex=\""));
+ aStr += aFormatIndex;
+ aStr += OUString( RTL_CONSTASCII_USTRINGPARAM( "\"."));
+ incError( aStr);
+ }
+ }
+
+ const LocaleNode * n = currNode -> findNode("FormatCode");
+ if (n)
+ {
+ of.writeParameter("FormatCode", n->getValue(), formatCount);
+ // Check separator usage for some FormatCode elements.
+ const LocaleNode* pCtype = 0;
+ switch (formatindex)
+ {
+ case cssi::NumberFormatIndex::NUMBER_1000DEC2 : // #,##0.00
+ case cssi::NumberFormatIndex::TIME_MMSS00 : // MM:SS.00
+ case cssi::NumberFormatIndex::TIME_HH_MMSS00 : // [HH]:MM:SS.00
+ {
+ const LocaleNode* pRoot = getRoot();
+ if (!pRoot)
+ incError( "No root for FormatCode.");
+ else
+ {
+ pCtype = pRoot->findNode( "LC_CTYPE");
+ if (!pCtype)
+ incError( "No LC_CTYPE found for FormatCode.");
+ else
+ {
+ OUString aRef( pCtype->getAttr().getValueByName("ref"));
+ if (aRef.getLength() > 0)
+ {
+ if (!bCtypeIsRef)
+ fprintf( stderr,
+ "Warning: Can't check separators used in FormatCode due to LC_CTYPE ref=\"%s\".\n"
+ "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",
+ OSTR( aRef));
+ bCtypeIsRef = true;
+ pCtype = 0;
+ }
+ }
+ }
+ }
+ break;
+ // Currency formats should be something like [C]###0;-[C]###0
+ // and not parenthesized [C]###0;([C]###0) if not en_US.
+ case cssi::NumberFormatIndex::CURRENCY_1000INT :
+ case cssi::NumberFormatIndex::CURRENCY_1000INT_RED :
+ case cssi::NumberFormatIndex::CURRENCY_1000DEC2 :
+ case cssi::NumberFormatIndex::CURRENCY_1000DEC2_RED :
+ case cssi::NumberFormatIndex::CURRENCY_1000DEC2_CCC :
+ case cssi::NumberFormatIndex::CURRENCY_1000DEC2_DASHED :
+ if (strcmp( of.getLocale(), "en_US") != 0)
+ {
+ OUString aCode( n->getValue());
+ OUString aPar1( RTL_CONSTASCII_USTRINGPARAM( "0)" ));
+ OUString aPar2( RTL_CONSTASCII_USTRINGPARAM( "-)" ));
+ OUString aPar3( RTL_CONSTASCII_USTRINGPARAM( " )" ));
+ OUString aPar4( RTL_CONSTASCII_USTRINGPARAM( "])" ));
+ if (aCode.indexOf( aPar1 ) > 0 || aCode.indexOf( aPar2 ) > 0 ||
+ aCode.indexOf( aPar3 ) > 0 || aCode.indexOf( aPar4 ) > 0)
+ 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);
+ }
+ break;
+ }
+ if (pCtype)
+ {
+ int nSavErr = nError;
+ OUString aCode( n->getValue());
+ if (formatindex == cssi::NumberFormatIndex::NUMBER_1000DEC2)
+ {
+ sal_Int32 nDec = -1;
+ sal_Int32 nGrp = -1;
+ const LocaleNode* pSep = pCtype->findNode( "DecimalSeparator");
+ if (!pSep)
+ incError( "No DecimalSeparator found for FormatCode.");
+ else
+ {
+ nDec = aCode.indexOf( pSep->getValue());
+ if (nDec < 0)
+ incErrorInt( "DecimalSeparator not present in FormatCode formatindex=\"%d\".",
+ formatindex);
+ }
+ pSep = pCtype->findNode( "ThousandSeparator");
+ if (!pSep)
+ incError( "No ThousandSeparator found for FormatCode.");
+ else
+ {
+ nGrp = aCode.indexOf( pSep->getValue());
+ if (nGrp < 0)
+ incErrorInt( "ThousandSeparator not present in FormatCode formatindex=\"%d\".",
+ formatindex);
+ }
+ if (nDec >= 0 && nGrp >= 0 && nDec <= nGrp)
+ incErrorInt( "Ordering of ThousandSeparator and DecimalSeparator not correct in formatindex=\"%d\".",
+ formatindex);
+ }
+ if (formatindex == cssi::NumberFormatIndex::TIME_MMSS00 ||
+ formatindex == cssi::NumberFormatIndex::TIME_HH_MMSS00)
+ {
+ sal_Int32 nTime = -1;
+ sal_Int32 n100s = -1;
+ const LocaleNode* pSep = pCtype->findNode( "TimeSeparator");
+ if (!pSep)
+ incError( "No TimeSeparator found for FormatCode.");
+ else
+ {
+ nTime = aCode.indexOf( pSep->getValue());
+ if (nTime < 0)
+ incErrorInt( "TimeSeparator not present in FormatCode formatindex=\"%d\".",
+ formatindex);
+ }
+ pSep = pCtype->findNode( "Time100SecSeparator");
+ if (!pSep)
+ incError( "No Time100SecSeparator found for FormatCode.");
+ else
+ {
+ n100s = aCode.indexOf( pSep->getValue());
+ if (n100s < 0)
+ incErrorInt( "Time100SecSeparator not present in FormatCode formatindex=\"%d\".",
+ formatindex);
+ OUStringBuffer a100s( pSep->getValue());
+ a100s.appendAscii( "00");
+ n100s = aCode.indexOf( a100s.makeStringAndClear());
+ if (n100s < 0)
+ incErrorInt( "Time100SecSeparator+00 not present in FormatCode formatindex=\"%d\".",
+ formatindex);
+ }
+ if (n100s >= 0 && nTime >= 0 && n100s <= nTime)
+ incErrorInt( "Ordering of Time100SecSeparator and TimeSeparator not correct in formatindex=\"%d\".",
+ formatindex);
+ }
+ if (nSavErr != nError)
+ fprintf( stderr,
+ "Warning: formatindex=\"%d\",\"%d\",\"%d\" are the only FormatCode elements checked for separator usage, there may be others that have errors.\n",
+ int(cssi::NumberFormatIndex::NUMBER_1000DEC2),
+ int(cssi::NumberFormatIndex::TIME_MMSS00),
+ int(cssi::NumberFormatIndex::TIME_HH_MMSS00));
+
+ }
+ }
+ else
+ incError( "No FormatCode in FormatElement.");
+ n = currNode -> findNode("DefaultName");
+ if (n)
+ of.writeParameter("FormatDefaultName", n->getValue(), formatCount);
+ else
+ of.writeParameter("FormatDefaultName", ::rtl::OUString(), formatCount);
+
+ }
+
+ // Check presence of all required format codes only in first section
+ // LC_FORMAT, not in optional LC_FORMAT_1
+ if (mnSection == 0)
+ {
+ // 0..47 MUST be present, 48,49 MUST NOT be present
+ ValueSet::const_iterator aIter( aFormatIndexSet.begin());
+ for (sal_Int16 nNext = cssi::NumberFormatIndex::NUMBER_START;
+ nNext < cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES; ++nNext)
+ {
+ sal_Int16 nHere = ::std::min( ((aIter != aFormatIndexSet.end() ? *aIter :
+ cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES)),
+ cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES);
+ if (aIter != aFormatIndexSet.end()) ++aIter;
+ for ( ; nNext < nHere; ++nNext)
+ {
+ switch (nNext)
+ {
+ case cssi::NumberFormatIndex::FRACTION_1 :
+ case cssi::NumberFormatIndex::FRACTION_2 :
+ case cssi::NumberFormatIndex::BOOLEAN :
+ case cssi::NumberFormatIndex::TEXT :
+ // generated internally
+ break;
+ default:
+ incErrorInt( "FormatElement formatindex=\"%d\" not present.", nNext);
+ }
+ }
+ switch (nHere)
+ {
+ case cssi::NumberFormatIndex::BOOLEAN :
+ incErrorInt( "FormatElement formatindex=\"%d\" reserved for internal ``BOOLEAN''.", nNext);
+ break;
+ case cssi::NumberFormatIndex::TEXT :
+ incErrorInt( "FormatElement formatindex=\"%d\" reserved for internal ``@'' (TEXT).", nNext);
+ break;
+ default:
+ ; // nothing
+ }
+ }
+ }
+
+ of.writeAsciiString("\nstatic const sal_Int16 ");
+ of.writeAsciiString("FormatElementsCount");
+ of.writeInt(mnSection);
+ of.writeAsciiString(" = ");
+ of.writeInt( formatCount - mnFormats);
+ of.writeAsciiString(";\n");
+ of.writeAsciiString("static const sal_Unicode* ");
+ of.writeAsciiString("FormatElementsArray");
+ of.writeInt(mnSection);
+ of.writeAsciiString("[] = {\n");
+ for(sal_Int16 i = mnFormats; i < formatCount; i++) {
+
+ of.writeAsciiString("\t");
+ of.writeAsciiString("FormatCode");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+
+ of.writeAsciiString("\t");
+ of.writeAsciiString("FormatDefaultName");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+
+ of.writeAsciiString("\t");
+ of.writeAsciiString("FormatKey");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+
+ of.writeAsciiString("\t");
+ of.writeAsciiString("FormatType");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+
+ of.writeAsciiString("\t");
+ of.writeAsciiString("FormatUsage");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+
+ of.writeAsciiString("\t");
+ of.writeAsciiString("Formatindex");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+
+
+ of.writeAsciiString("\tdefaultFormatElement");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ }
+ of.writeAsciiString("};\n\n");
+
+ switch (mnSection)
+ {
+ case 0:
+ of.writeFunction("getAllFormats0_", "FormatElementsCount0", "FormatElementsArray0", "replaceFrom0", "replaceTo0");
+ break;
+ case 1:
+ of.writeFunction("getAllFormats1_", "FormatElementsCount1", "FormatElementsArray1", "replaceFrom1", "replaceTo1");
+ break;
+ }
+
+ mnFormats = mnFormats + formatCount;
+ ++mnSection;
+}
+
+void LCCollationNode::generateCode (const OFileWriter &of) const
+{
+ ::rtl::OUString useLocale = getAttr().getValueByName("ref");
+ if (useLocale.getLength() > 0) {
+ of.writeRefFunction("getCollatorImplementation_", useLocale);
+ of.writeRefFunction("getCollationOptions_", useLocale);
+ return;
+ }
+ sal_Int16 nbOfCollations = 0;
+ sal_Int16 nbOfCollationOptions = 0;
+ sal_Int16 j;
+
+ for ( j = 0; j < getNumberOfChildren(); j++ ) {
+ LocaleNode * currNode = getChildAt (j);
+ if( currNode->getName().compareToAscii("Collator") == 0 )
+ {
+ ::rtl::OUString str;
+ str = currNode->getAttr().getValueByName("unoid");
+ of.writeParameter("CollatorID", str, j);
+ str = currNode->getValue();
+ of.writeParameter("CollatorRule", str, j);
+ str = currNode -> getAttr().getValueByName("default");
+ of.writeDefaultParameter("Collator", str, j);
+ of.writeAsciiString("\n");
+
+ nbOfCollations++;
+ }
+ if( currNode->getName().compareToAscii("CollationOptions") == 0 )
+ {
+ LocaleNode* pCollationOptions = currNode;
+ nbOfCollationOptions = sal::static_int_cast<sal_Int16>( pCollationOptions->getNumberOfChildren() );
+ for( sal_Int16 i=0; i<nbOfCollationOptions; i++ )
+ {
+ of.writeParameter("collationOption", pCollationOptions->getChildAt( i )->getValue(), i );
+ }
+
+ of.writeAsciiString("static const sal_Int16 nbOfCollationOptions = ");
+ of.writeInt( nbOfCollationOptions );
+ of.writeAsciiString(";\n\n");
+ }
+ }
+ of.writeAsciiString("static const sal_Int16 nbOfCollations = ");
+ of.writeInt(nbOfCollations);
+ of.writeAsciiString(";\n\n");
+
+ of.writeAsciiString("\nstatic const sal_Unicode* LCCollatorArray[] = {\n");
+ for(j = 0; j < nbOfCollations; j++) {
+ of.writeAsciiString("\tCollatorID");
+ of.writeInt(j);
+ of.writeAsciiString(",\n");
+
+ of.writeAsciiString("\tdefaultCollator");
+ of.writeInt(j);
+ of.writeAsciiString(",\n");
+
+ of.writeAsciiString("\tCollatorRule");
+ of.writeInt(j);
+ of.writeAsciiString(",\n");
+ }
+ of.writeAsciiString("};\n\n");
+
+ of.writeAsciiString("static const sal_Unicode* collationOptions[] = {");
+ for( j=0; j<nbOfCollationOptions; j++ )
+ {
+ of.writeAsciiString( "collationOption" );
+ of.writeInt( j );
+ of.writeAsciiString( ", " );
+ }
+ of.writeAsciiString("NULL };\n");
+ of.writeFunction("getCollatorImplementation_", "nbOfCollations", "LCCollatorArray");
+ of.writeFunction("getCollationOptions_", "nbOfCollationOptions", "collationOptions");
+}
+
+void LCSearchNode::generateCode (const OFileWriter &of) const
+{
+ ::rtl::OUString useLocale = getAttr().getValueByName("ref");
+ if (useLocale.getLength() > 0) {
+ of.writeRefFunction("getSearchOptions_", useLocale);
+ return;
+ }
+
+ if( getNumberOfChildren() != 1 )
+ {
+ ++nError;
+ fprintf(
+ stderr, "Error: LC_SEARCH: more than 1 child: %ld\n",
+ sal::static_int_cast< long >(getNumberOfChildren()));
+ }
+ sal_Int32 i;
+ LocaleNode* pSearchOptions = getChildAt( 0 );
+ sal_Int32 nSearchOptions = pSearchOptions->getNumberOfChildren();
+ for( i=0; i<nSearchOptions; i++ )
+ {
+ of.writeParameter("searchOption", pSearchOptions->getChildAt( i )->getValue(), sal::static_int_cast<sal_Int16>(i) );
+ }
+
+ of.writeAsciiString("static const sal_Int16 nbOfSearchOptions = ");
+ of.writeInt( sal::static_int_cast<sal_Int16>( nSearchOptions ) );
+ of.writeAsciiString(";\n\n");
+
+ of.writeAsciiString("static const sal_Unicode* searchOptions[] = {");
+ for( i=0; i<nSearchOptions; i++ )
+ {
+ of.writeAsciiString( "searchOption" );
+ of.writeInt( sal::static_int_cast<sal_Int16>(i) );
+ of.writeAsciiString( ", " );
+ }
+ of.writeAsciiString("NULL };\n");
+ of.writeFunction("getSearchOptions_", "nbOfSearchOptions", "searchOptions");
+}
+
+void LCIndexNode::generateCode (const OFileWriter &of) const
+{
+ ::rtl::OUString useLocale = getAttr().getValueByName("ref");
+ if (useLocale.getLength() > 0) {
+ of.writeRefFunction("getIndexAlgorithm_", useLocale);
+ of.writeRefFunction("getUnicodeScripts_", useLocale);
+ of.writeRefFunction("getFollowPageWords_", useLocale);
+ return;
+ }
+ sal_Int16 nbOfIndexs = 0;
+ sal_Int16 nbOfUnicodeScripts = 0;
+ sal_Int16 nbOfPageWords = 0;
+ sal_Int16 i;
+ for (i = 0; i< getNumberOfChildren();i++) {
+ LocaleNode * currNode = getChildAt (i);
+ if( currNode->getName().compareToAscii("IndexKey") == 0 )
+ {
+ ::rtl::OUString str;
+ str = currNode->getAttr().getValueByName("unoid");
+ of.writeParameter("IndexID", str, nbOfIndexs);
+ str = currNode->getAttr().getValueByName("module");
+ of.writeParameter("IndexModule", str, nbOfIndexs);
+ str = currNode->getValue();
+ of.writeParameter("IndexKey", str, nbOfIndexs);
+ str = currNode -> getAttr().getValueByName("default");
+ of.writeDefaultParameter("Index", str, nbOfIndexs);
+ str = currNode -> getAttr().getValueByName("phonetic");
+ of.writeDefaultParameter("Phonetic", str, nbOfIndexs);
+ of.writeAsciiString("\n");
+
+ nbOfIndexs++;
+ }
+ if( currNode->getName().compareToAscii("UnicodeScript") == 0 )
+ {
+ of.writeParameter("unicodeScript", currNode->getValue(), nbOfUnicodeScripts );
+ nbOfUnicodeScripts++;
+
+ }
+ if( currNode->getName().compareToAscii("FollowPageWord") == 0 )
+ {
+ of.writeParameter("followPageWord", currNode->getValue(), nbOfPageWords);
+ nbOfPageWords++;
+ }
+ }
+ of.writeAsciiString("static const sal_Int16 nbOfIndexs = ");
+ of.writeInt(nbOfIndexs);
+ of.writeAsciiString(";\n\n");
+
+ of.writeAsciiString("\nstatic const sal_Unicode* IndexArray[] = {\n");
+ for(i = 0; i < nbOfIndexs; i++) {
+ of.writeAsciiString("\tIndexID");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+
+ of.writeAsciiString("\tIndexModule");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+
+ of.writeAsciiString("\tIndexKey");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+
+ of.writeAsciiString("\tdefaultIndex");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+
+ of.writeAsciiString("\tdefaultPhonetic");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ }
+ of.writeAsciiString("};\n\n");
+
+ of.writeAsciiString("static const sal_Int16 nbOfUnicodeScripts = ");
+ of.writeInt( nbOfUnicodeScripts );
+ of.writeAsciiString(";\n\n");
+
+ of.writeAsciiString("static const sal_Unicode* UnicodeScriptArray[] = {");
+ for( i=0; i<nbOfUnicodeScripts; i++ )
+ {
+ of.writeAsciiString( "unicodeScript" );
+ of.writeInt( i );
+ of.writeAsciiString( ", " );
+ }
+ of.writeAsciiString("NULL };\n\n");
+
+ of.writeAsciiString("static const sal_Int16 nbOfPageWords = ");
+ of.writeInt(nbOfPageWords);
+ of.writeAsciiString(";\n\n");
+
+ of.writeAsciiString("static const sal_Unicode* FollowPageWordArray[] = {\n");
+ for(i = 0; i < nbOfPageWords; i++) {
+ of.writeAsciiString("\tfollowPageWord");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ }
+ of.writeAsciiString("\tNULL\n};\n\n");
+
+ of.writeFunction("getIndexAlgorithm_", "nbOfIndexs", "IndexArray");
+ of.writeFunction("getUnicodeScripts_", "nbOfUnicodeScripts", "UnicodeScriptArray");
+ of.writeFunction("getFollowPageWords_", "nbOfPageWords", "FollowPageWordArray");
+}
+
+void LCCalendarNode::generateCode (const OFileWriter &of) const
+{
+ ::rtl::OUString useLocale = getAttr().getValueByName("ref");
+ if (useLocale.getLength() > 0) {
+ of.writeRefFunction("getAllCalendars_", useLocale);
+ return;
+ }
+ sal_Int16 nbOfCalendars = sal::static_int_cast<sal_Int16>( getNumberOfChildren() );
+ ::rtl::OUString str;
+ sal_Int16 * nbOfDays = new sal_Int16[nbOfCalendars];
+ sal_Int16 * nbOfMonths = new sal_Int16[nbOfCalendars];
+ sal_Int16 * nbOfEras = new sal_Int16[nbOfCalendars];
+ sal_Int16 j;
+ sal_Int16 i;
+ bool bHasGregorian = false;
+
+
+ for ( i = 0; i < nbOfCalendars; i++) {
+ LocaleNode * calNode = getChildAt (i);
+ OUString calendarID = calNode -> getAttr().getValueByName("unoid");
+ of.writeParameter( "calendarID", calendarID, i);
+ bool bGregorian = calendarID.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "gregorian"));
+ if (!bHasGregorian)
+ bHasGregorian = bGregorian;
+ str = calNode -> getAttr().getValueByName("default");
+ of.writeDefaultParameter("Calendar", str, i);
+
+ // Generate Days of Week
+ const sal_Char *elementTag;
+ LocaleNode * daysNode = NULL;
+ ::rtl::OUString ref_name = calNode->getChildAt(0)->getAttr().getValueByName("ref");
+ if (ref_name.getLength() > 0 && i > 0) {
+ for (j = 0; j < i; j++) {
+ str = getChildAt(j)->getAttr().getValueByName("unoid");
+ if (str.equals(ref_name))
+ daysNode = getChildAt(j)->getChildAt(0);
+ }
+ }
+ if (ref_name.getLength() > 0 && daysNode == NULL) {
+ of.writeParameter("dayRef", OUString(RTL_CONSTASCII_USTRINGPARAM("ref")), i);
+ of.writeParameter("dayRefName", ref_name, i);
+ nbOfDays[i] = 0;
+ } else {
+ if (daysNode == NULL)
+ daysNode = calNode -> getChildAt(0);
+ nbOfDays[i] = sal::static_int_cast<sal_Int16>( daysNode->getNumberOfChildren() );
+ if (bGregorian && nbOfDays[i] != 7)
+ incErrorInt( "A Gregorian calendar must have 7 days per week, this one has %d", nbOfDays[i]);
+ elementTag = "day";
+ for (j = 0; j < nbOfDays[i]; j++) {
+ LocaleNode *currNode = daysNode -> getChildAt(j);
+ OUString dayID( currNode->getChildAt(0)->getValue());
+ of.writeParameter("dayID", dayID, i, j);
+ if (j == 0 && bGregorian && !dayID.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "sun")))
+ incError( "First day of a week of a Gregorian calendar must be <DayID>sun</DayID>");
+ of.writeParameter(elementTag, "DefaultAbbrvName",currNode->getChildAt(1)->getValue() ,i, j);
+ of.writeParameter(elementTag, "DefaultFullName",currNode->getChildAt(2)->getValue() , i, j);
+ }
+ }
+
+ // Generate Months of Year
+ LocaleNode * monthsNode = NULL;
+ ref_name = calNode->getChildAt(1)->getAttr().getValueByName("ref");
+ if (ref_name.getLength() > 0 && i > 0) {
+ for (j = 0; j < i; j++) {
+ str = getChildAt(j)->getAttr().getValueByName("unoid");
+ if (str.equals(ref_name))
+ monthsNode = getChildAt(j)->getChildAt(1);
+ }
+ }
+ if (ref_name.getLength() > 0 && monthsNode == NULL) {
+ of.writeParameter("monthRef", OUString(RTL_CONSTASCII_USTRINGPARAM("ref")), i);
+ of.writeParameter("monthRefName", ref_name, i);
+ nbOfMonths[i] = 0;
+ } else {
+ if (monthsNode == NULL)
+ monthsNode = calNode -> getChildAt(1);
+ nbOfMonths[i] = sal::static_int_cast<sal_Int16>( monthsNode->getNumberOfChildren() );
+ if (bGregorian && nbOfMonths[i] != 12)
+ incErrorInt( "A Gregorian calendar must have 12 months, this one has %d", nbOfMonths[i]);
+ elementTag = "month";
+ for (j = 0; j < nbOfMonths[i]; j++) {
+ LocaleNode *currNode = monthsNode -> getChildAt(j);
+ OUString monthID( currNode->getChildAt(0)->getValue());
+ of.writeParameter("monthID", monthID, i, j);
+ if (j == 0 && bGregorian && !monthID.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "jan")))
+ incError( "First month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
+ of.writeParameter(elementTag, "DefaultAbbrvName",currNode->getChildAt(1)->getValue() ,i, j);
+ of.writeParameter(elementTag, "DefaultFullName",currNode->getChildAt(2)->getValue() , i, j);
+ }
+ }
+
+ // Generate Era name
+ LocaleNode * erasNode = NULL;
+ ref_name = calNode -> getChildAt(2) ->getAttr().getValueByName("ref");
+ if (ref_name.getLength() > 0 && i > 0) {
+ for (j = 0; j < i; j++) {
+ str = getChildAt(j)->getAttr().getValueByName("unoid");
+ if (str.equals(ref_name))
+ erasNode = getChildAt(j)->getChildAt(2);
+ }
+ }
+ if (ref_name.getLength() > 0 && erasNode == NULL) {
+ of.writeParameter("eraRef", OUString(RTL_CONSTASCII_USTRINGPARAM("ref")), i);
+ of.writeParameter("eraRefName", ref_name, i);
+ nbOfEras[i] = 0;
+ } else {
+ if (erasNode == NULL)
+ erasNode = calNode -> getChildAt(2);
+ nbOfEras[i] = sal::static_int_cast<sal_Int16>( erasNode->getNumberOfChildren() );
+ if (bGregorian && nbOfEras[i] != 2)
+ incErrorInt( "A Gregorian calendar must have 2 eras, this one has %d", nbOfEras[i]);
+ elementTag = "era";
+ for (j = 0; j < nbOfEras[i]; j++) {
+ LocaleNode *currNode = erasNode -> getChildAt(j);
+ OUString eraID( currNode->getChildAt(0)->getValue());
+ of.writeParameter("eraID", eraID, i, j);
+ if (j == 0 && bGregorian && !eraID.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "bc")))
+ incError( "First era of a Gregorian calendar must be <EraID>bc</EraID>");
+ if (j == 1 && bGregorian && !eraID.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "ad")))
+ incError( "Second era of a Gregorian calendar must be <EraID>ad</EraID>");
+ of.writeAsciiString("\n");
+ of.writeParameter(elementTag, "DefaultAbbrvName",currNode->getChildAt(1)->getValue() ,i, j);
+ of.writeParameter(elementTag, "DefaultFullName",currNode->getChildAt(2)->getValue() , i, j);
+ }
+ }
+ str = calNode->getChildAt(3)->getChildAt(0)->getValue();
+ if (nbOfDays[i])
+ {
+ for (j = 0; j < nbOfDays[i]; j++)
+ {
+ LocaleNode *currNode = daysNode->getChildAt(j);
+ OUString dayID( currNode->getChildAt(0)->getValue());
+ if (str == dayID)
+ break; // for
+ }
+ if (j >= nbOfDays[i])
+ incErrorStr( "<StartDayOfWeek> <DayID> must be one of the <DaysOfWeek>, but is", str);
+ }
+ of.writeParameter("startDayOfWeek", str, i);
+ str = calNode ->getChildAt(4)-> getValue();
+ sal_Int16 nDays = sal::static_int_cast<sal_Int16>( str.toInt32() );
+ if (nDays < 1 || (0 < nbOfDays[i] && nbOfDays[i] < nDays))
+ incErrorInt( "Bad value of MinimalDaysInFirstWeek: %d, must be 1 <= value <= days_in_week", nDays);
+ of.writeIntParameter("minimalDaysInFirstWeek", i, nDays);
+ }
+ if (!bHasGregorian)
+ fprintf( stderr, "Warning: %s\n", "No Gregorian calendar defined, are you sure?");
+
+ of.writeAsciiString("static const sal_Int16 calendarsCount = ");
+ of.writeInt(nbOfCalendars);
+ of.writeAsciiString(";\n\n");
+
+ of.writeAsciiString("static const sal_Unicode nbOfDays[] = {");
+ for(i = 0; i < nbOfCalendars - 1; i++) {
+ of.writeInt(nbOfDays[i]);
+ of.writeAsciiString(", ");
+ };
+ of.writeInt(nbOfDays[i]);
+ of.writeAsciiString("};\n");
+
+ of.writeAsciiString("static const sal_Unicode nbOfMonths[] = {");
+ for(i = 0; i < nbOfCalendars - 1; i++) {
+ of.writeInt(nbOfMonths[i]);
+ of.writeAsciiString(", ");
+ };
+ of.writeInt(nbOfMonths[i]);
+ of.writeAsciiString("};\n");
+
+ of.writeAsciiString("static const sal_Unicode nbOfEras[] = {");
+ for(i = 0; i < nbOfCalendars - 1; i++) {
+ of.writeInt(nbOfEras[i]);
+ of.writeAsciiString(", ");
+ };
+ of.writeInt(nbOfEras[i]);
+ of.writeAsciiString("};\n");
+
+
+ of.writeAsciiString("static const sal_Unicode* calendars[] = {\n");
+ of.writeAsciiString("\tnbOfDays,\n");
+ of.writeAsciiString("\tnbOfMonths,\n");
+ of.writeAsciiString("\tnbOfEras,\n");
+ for(i = 0; i < nbOfCalendars; i++) {
+ of.writeAsciiString("\tcalendarID");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ of.writeAsciiString("\tdefaultCalendar");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ if (nbOfDays[i] == 0) {
+ of.writeAsciiString("\tdayRef");
+ of.writeInt(i); of.writeAsciiString(",\n");
+ of.writeAsciiString("\tdayRefName");
+ of.writeInt(i); of.writeAsciiString(",\n");
+ } else {
+ for(j = 0; j < nbOfDays[i]; j++) {
+ of.writeAsciiString("\tdayID");
+ of.writeInt(i); of.writeInt(j); of.writeAsciiString(",\n");
+ of.writeAsciiString("\tdayDefaultAbbrvName");
+ of.writeInt(i); of.writeInt(j); of.writeAsciiString(",\n");
+ of.writeAsciiString("\tdayDefaultFullName");of.writeInt(i); of.writeInt(j); of.writeAsciiString(",\n");
+ }
+ }
+ if (nbOfMonths[i] == 0) {
+ of.writeAsciiString("\tmonthRef");
+ of.writeInt(i); of.writeAsciiString(",\n");
+ of.writeAsciiString("\tmonthRefName");
+ of.writeInt(i); of.writeAsciiString(",\n");
+ } else {
+ for(j = 0; j < nbOfMonths[i]; j++) {
+ of.writeAsciiString("\tmonthID");of.writeInt(i);of.writeInt(j);of.writeAsciiString(",\n");
+ of.writeAsciiString("\tmonthDefaultAbbrvName");of.writeInt(i);of.writeInt(j);of.writeAsciiString(",\n");
+ of.writeAsciiString("\tmonthDefaultFullName");of.writeInt(i);of.writeInt(j);of.writeAsciiString(",\n");
+ }
+ }
+ if (nbOfEras[i] == 0) {
+ of.writeAsciiString("\teraRef");
+ of.writeInt(i); of.writeAsciiString(",\n");
+ of.writeAsciiString("\teraRefName");
+ of.writeInt(i); of.writeAsciiString(",\n");
+ } else {
+ for(j = 0; j < nbOfEras[i]; j++) {
+ of.writeAsciiString("\teraID"); of.writeInt(i); of.writeInt(j); of.writeAsciiString(",\n");
+ of.writeAsciiString("\teraDefaultAbbrvName");of.writeInt(i);of.writeInt(j);of.writeAsciiString(",\n");
+ of.writeAsciiString("\teraDefaultFullName");of.writeInt(i);of.writeInt(j);of.writeAsciiString(",\n");
+ }
+ }
+ of.writeAsciiString("\tstartDayOfWeek");of.writeInt(i); of.writeAsciiString(",\n");
+ of.writeAsciiString("\tminimalDaysInFirstWeek");of.writeInt(i); of.writeAsciiString(",\n");
+ }
+
+ of.writeAsciiString("};\n\n");
+ of.writeFunction("getAllCalendars_", "calendarsCount", "calendars");
+
+ delete []nbOfDays;
+ delete []nbOfMonths;
+ delete []nbOfEras;
+}
+
+bool isIso4217( const OUString& rStr )
+{
+ const sal_Unicode* p = rStr.getStr();
+ return rStr.getLength() == 3
+ && 'A' <= p[0] && p[0] <= 'Z'
+ && 'A' <= p[1] && p[1] <= 'Z'
+ && 'A' <= p[2] && p[2] <= 'Z'
+ ;
+}
+
+void LCCurrencyNode :: generateCode (const OFileWriter &of) const
+{
+ ::rtl::OUString useLocale = getAttr().getValueByName("ref");
+ if (useLocale.getLength() > 0) {
+ of.writeRefFunction("getAllCurrencies_", useLocale);
+ return;
+ }
+ sal_Int16 nbOfCurrencies = 0;
+ ::rtl::OUString str;
+ sal_Int16 i;
+
+ bool bTheDefault= false;
+ bool bTheCompatible = false;
+ for ( i = 0; i < getNumberOfChildren(); i++,nbOfCurrencies++) {
+ LocaleNode * calNode = getChildAt (i);
+ str = calNode->getAttr().getValueByName("default");
+ bool bDefault = of.writeDefaultParameter("Currency", str, nbOfCurrencies);
+ str = calNode->getAttr().getValueByName("usedInCompatibleFormatCodes");
+ bool bCompatible = of.writeDefaultParameter("CurrencyUsedInCompatibleFormatCodes", str, nbOfCurrencies);
+ str = calNode->getAttr().getValueByName("legacyOnly");
+ bool bLegacy = of.writeDefaultParameter("CurrencyLegacyOnly", str, nbOfCurrencies);
+ if (bLegacy && (bDefault || bCompatible))
+ incError( "Currency: if legacyOnly==true, both 'default' and 'usedInCompatibleFormatCodes' must be false.");
+ if (bDefault)
+ {
+ if (bTheDefault)
+ incError( "Currency: more than one default currency.");
+ bTheDefault = true;
+ }
+ if (bCompatible)
+ {
+ if (bTheCompatible)
+ incError( "Currency: more than one currency flagged as usedInCompatibleFormatCodes.");
+ bTheCompatible = true;
+ }
+ str = calNode -> findNode ("CurrencyID") -> getValue();
+ of.writeParameter("currencyID", str, nbOfCurrencies);
+ // CurrencyID MUST be ISO 4217.
+ if (!bLegacy && !isIso4217(str))
+ incError( "CurrencyID is not ISO 4217");
+ str = calNode -> findNode ("CurrencySymbol") -> getValue();
+ of.writeParameter("currencySymbol", str, nbOfCurrencies);
+ str = calNode -> findNode ("BankSymbol") -> getValue();
+ of.writeParameter("bankSymbol", str, nbOfCurrencies);
+ // BankSymbol currently must be ISO 4217. May change later if
+ // application always uses CurrencyID instead of BankSymbol.
+ if (!bLegacy && !isIso4217(str))
+ incError( "BankSymbol is not ISO 4217");
+ str = calNode -> findNode ("CurrencyName") -> getValue();
+ of.writeParameter("currencyName", str, nbOfCurrencies);
+ str = calNode -> findNode ("DecimalPlaces") -> getValue();
+ sal_Int16 nDecimalPlaces = (sal_Int16)str.toInt32();
+ of.writeIntParameter("currencyDecimalPlaces", nbOfCurrencies, nDecimalPlaces);
+ of.writeAsciiString("\n");
+ };
+
+ if (!bTheDefault)
+ incError( "Currency: no default currency.");
+ if (!bTheCompatible)
+ incError( "Currency: no currency flagged as usedInCompatibleFormatCodes.");
+
+ of.writeAsciiString("static const sal_Int16 currencyCount = ");
+ of.writeInt(nbOfCurrencies);
+ of.writeAsciiString(";\n\n");
+ of.writeAsciiString("static const sal_Unicode* currencies[] = {\n");
+ for(i = 0; i < nbOfCurrencies; i++) {
+ of.writeAsciiString("\tcurrencyID");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ of.writeAsciiString("\tcurrencySymbol");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ of.writeAsciiString("\tbankSymbol");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ of.writeAsciiString("\tcurrencyName");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ of.writeAsciiString("\tdefaultCurrency");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ of.writeAsciiString("\tdefaultCurrencyUsedInCompatibleFormatCodes");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ of.writeAsciiString("\tcurrencyDecimalPlaces");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ of.writeAsciiString("\tdefaultCurrencyLegacyOnly");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ }
+ of.writeAsciiString("};\n\n");
+ of.writeFunction("getAllCurrencies_", "currencyCount", "currencies");
+}
+
+void LCTransliterationNode::generateCode (const OFileWriter &of) const
+{
+ ::rtl::OUString useLocale = getAttr().getValueByName("ref");
+ if (useLocale.getLength() > 0) {
+ of.writeRefFunction("getTransliterations_", useLocale);
+ return;
+ }
+ sal_Int16 nbOfModules = 0;
+ ::rtl::OUString str;
+ sal_Int16 i;
+
+ for ( i = 0; i < getNumberOfChildren(); i++,nbOfModules++) {
+ LocaleNode * calNode = getChildAt (i);
+ str = calNode->getAttr().getValueByIndex(0);
+ of.writeParameter("Transliteration", str, nbOfModules);
+ }
+ of.writeAsciiString("static const sal_Int16 nbOfTransliterations = ");
+ of.writeInt(nbOfModules);
+ of.writeAsciiString(";\n\n");
+
+ of.writeAsciiString("\nstatic const sal_Unicode* LCTransliterationsArray[] = {\n");
+ for( i = 0; i < nbOfModules; i++) {
+ of.writeAsciiString("\tTransliteration");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ }
+ of.writeAsciiString("};\n\n");
+ of.writeFunction("getTransliterations_", "nbOfTransliterations", "LCTransliterationsArray");
+}
+
+struct NameValuePair {
+ const sal_Char *name;
+ const sal_Char *value;
+};
+static NameValuePair ReserveWord[] = {
+ { "trueWord", "true" },
+ { "falseWord", "false" },
+ { "quarter1Word", "1st quarter" },
+ { "quarter2Word", "2nd quarter" },
+ { "quarter3Word", "3rd quarter" },
+ { "quarter4Word", "4th quarter" },
+ { "aboveWord", "above" },
+ { "belowWord", "below" },
+ { "quarter1Abbreviation", "Q1" },
+ { "quarter2Abbreviation", "Q2" },
+ { "quarter3Abbreviation", "Q3" },
+ { "quarter4Abbreviation", "Q4" }
+};
+
+void LCMiscNode::generateCode (const OFileWriter &of) const
+{
+ ::rtl::OUString useLocale = getAttr().getValueByName("ref");
+ if (useLocale.getLength() > 0) {
+ of.writeRefFunction("getForbiddenCharacters_", useLocale);
+ of.writeRefFunction("getBreakIteratorRules_", useLocale);
+ of.writeRefFunction("getReservedWords_", useLocale);
+ return;
+ }
+ const LocaleNode * reserveNode = findNode("ReservedWords");
+ if (!reserveNode)
+ incError( "No ReservedWords element."); // should not happen if validated..
+ const LocaleNode * forbidNode = findNode("ForbiddenCharacters");
+ const LocaleNode * breakNode = findNode("BreakIteratorRules");
+
+ bool bEnglishLocale = (strncmp( of.getLocale(), "en_", 3) == 0);
+
+ sal_Int16 nbOfWords = 0;
+ ::rtl::OUString str;
+ sal_Int16 i;
+
+ for ( i = 0; i < sal_Int16(SAL_N_ELEMENTS(ReserveWord)); i++,nbOfWords++) {
+ const LocaleNode * curNode = (reserveNode ? reserveNode->findNode(
+ ReserveWord[i].name) : 0);
+ if (!curNode)
+ fprintf( stderr,
+ "Warning: No %s in ReservedWords, using en_US default: \"%s\".\n",
+ ReserveWord[i].name, ReserveWord[i].value);
+ str = curNode ? curNode -> getValue() : OUString::createFromAscii(ReserveWord[i].value);
+ if (!str.getLength())
+ {
+ ++nError;
+ fprintf( stderr, "Error: No content for ReservedWords %s.\n", ReserveWord[i].name);
+ }
+ of.writeParameter("ReservedWord", str, nbOfWords);
+ // "true", ..., "below" trigger untranslated warning.
+ if (!bEnglishLocale && curNode && (0 <= i && i <= 7) &&
+ str.equalsIgnoreAsciiCaseAscii( ReserveWord[i].value))
+ {
+ fprintf( stderr,
+ "Warning: ReservedWord %s seems to be untranslated \"%s\".\n",
+ ReserveWord[i].name, ReserveWord[i].value);
+ }
+ }
+ of.writeAsciiString("static const sal_Int16 nbOfReservedWords = ");
+ of.writeInt(nbOfWords);
+ of.writeAsciiString(";\n\n");
+ of.writeAsciiString("\nstatic const sal_Unicode* LCReservedWordsArray[] = {\n");
+ for( i = 0; i < nbOfWords; i++) {
+ of.writeAsciiString("\tReservedWord");
+ of.writeInt(i);
+ of.writeAsciiString(",\n");
+ }
+ of.writeAsciiString("};\n\n");
+ of.writeFunction("getReservedWords_", "nbOfReservedWords", "LCReservedWordsArray");
+
+ if (forbidNode) {
+ of.writeParameter( "forbiddenBegin", forbidNode -> getChildAt(0)->getValue());
+ of.writeParameter( "forbiddenEnd", forbidNode -> getChildAt(1)->getValue());
+ of.writeParameter( "hangingChars", forbidNode -> getChildAt(2)->getValue());
+ } else {
+ of.writeParameter( "forbiddenBegin", ::rtl::OUString());
+ of.writeParameter( "forbiddenEnd", ::rtl::OUString());
+ of.writeParameter( "hangingChars", ::rtl::OUString());
+ }
+ of.writeAsciiString("\nstatic const sal_Unicode* LCForbiddenCharactersArray[] = {\n");
+ of.writeAsciiString("\tforbiddenBegin,\n");
+ of.writeAsciiString("\tforbiddenEnd,\n");
+ of.writeAsciiString("\thangingChars\n");
+ of.writeAsciiString("};\n\n");
+ of.writeFunction("getForbiddenCharacters_", "3", "LCForbiddenCharactersArray");
+
+ if (breakNode) {
+ of.writeParameter( "EditMode", breakNode -> getChildAt(0)->getValue());
+ of.writeParameter( "DictionaryMode", breakNode -> getChildAt(1)->getValue());
+ of.writeParameter( "WordCountMode", breakNode -> getChildAt(2)->getValue());
+ of.writeParameter( "CharacterMode", breakNode -> getChildAt(3)->getValue());
+ of.writeParameter( "LineMode", breakNode -> getChildAt(4)->getValue());
+ } else {
+ of.writeParameter( "EditMode", ::rtl::OUString());
+ of.writeParameter( "DictionaryMode", ::rtl::OUString());
+ of.writeParameter( "WordCountMode", ::rtl::OUString());
+ of.writeParameter( "CharacterMode", ::rtl::OUString());
+ of.writeParameter( "LineMode", ::rtl::OUString());
+ }
+ of.writeAsciiString("\nstatic const sal_Unicode* LCBreakIteratorRulesArray[] = {\n");
+ of.writeAsciiString("\tEditMode,\n");
+ of.writeAsciiString("\tDictionaryMode,\n");
+ of.writeAsciiString("\tWordCountMode,\n");
+ of.writeAsciiString("\tCharacterMode,\n");
+ of.writeAsciiString("\tLineMode\n");
+ of.writeAsciiString("};\n\n");
+ of.writeFunction("getBreakIteratorRules_", "5", "LCBreakIteratorRulesArray");
+
+}
+
+void LCNumberingLevelNode::generateCode (const OFileWriter &of) const
+{
+ of.writeAsciiString("// ---> ContinuousNumbering\n");
+ ::rtl::OUString useLocale = getAttr().getValueByName("ref");
+ if (useLocale.getLength() > 0) {
+ of.writeRefFunction2("getContinuousNumberingLevels_", useLocale);
+ return;
+ }
+
+ // hard code number of attributes per style.
+ const int nAttributes = 5;
+ const char* attr[ nAttributes ] = { "Prefix", "NumType", "Suffix", "Transliteration", "NatNum" };
+
+ // record each attribute of each style in a static C++ variable.
+ // determine number of styles on the fly.
+ sal_Int32 nStyles = getNumberOfChildren();
+ sal_Int32 i;
+
+ for( i = 0; i < nStyles; ++i )
+ {
+ const Attr &q = getChildAt( i )->getAttr();
+ for( sal_Int32 j=0; j<nAttributes; ++j )
+ {
+ const char* name = attr[j];
+ OUString value = q.getValueByName( name );
+ of.writeParameter("continuous", name, value, sal::static_int_cast<sal_Int16>(i) );
+ }
+ }
+
+ // record number of styles and attributes.
+ of.writeAsciiString("static const sal_Int16 continuousNbOfStyles = ");
+ of.writeInt( sal::static_int_cast<sal_Int16>( nStyles ) );
+ of.writeAsciiString(";\n\n");
+ of.writeAsciiString("static const sal_Int16 continuousNbOfAttributesPerStyle = ");
+ of.writeInt( nAttributes );
+ of.writeAsciiString(";\n\n");
+
+ // generate code. (intermediate arrays)
+ for( i=0; i<nStyles; i++ )
+ {
+ of.writeAsciiString("\nstatic const sal_Unicode* continuousStyle" );
+ of.writeInt( sal::static_int_cast<sal_Int16>(i) );
+ of.writeAsciiString("[] = {\n");
+ for( sal_Int32 j=0; j<nAttributes; j++)
+ {
+ of.writeAsciiString("\t");
+ of.writeAsciiString( "continuous" );
+ of.writeAsciiString( attr[j] );
+ of.writeInt(sal::static_int_cast<sal_Int16>(i));
+ of.writeAsciiString(",\n");
+ }
+ of.writeAsciiString("\t0\n};\n\n");
+ }
+
+ // generate code. (top-level array)
+ of.writeAsciiString("\n");
+ of.writeAsciiString("static const sal_Unicode** LCContinuousNumberingLevelsArray[] = {\n" );
+ for( i=0; i<nStyles; i++ )
+ {
+ of.writeAsciiString( "\t" );
+ of.writeAsciiString( "continuousStyle" );
+ of.writeInt( sal::static_int_cast<sal_Int16>(i) );
+ of.writeAsciiString( ",\n");
+ }
+ of.writeAsciiString("\t0\n};\n\n");
+ of.writeFunction2("getContinuousNumberingLevels_", "continuousNbOfStyles",
+ "continuousNbOfAttributesPerStyle", "LCContinuousNumberingLevelsArray");
+}
+
+
+void LCOutlineNumberingLevelNode::generateCode (const OFileWriter &of) const
+{
+ of.writeAsciiString("// ---> OutlineNumbering\n");
+ ::rtl::OUString useLocale = getAttr().getValueByName("ref");
+ if (useLocale.getLength() > 0) {
+ of.writeRefFunction3("getOutlineNumberingLevels_", useLocale);
+ return;
+ }
+
+ // hardcode number of attributes per level
+ const int nAttributes = 11;
+ const char* attr[ nAttributes ] =
+ {
+ "Prefix",
+ "NumType",
+ "Suffix",
+ "BulletChar",
+ "BulletFontName",
+ "ParentNumbering",
+ "LeftMargin",
+ "SymbolTextDistance",
+ "FirstLineOffset",
+ "Transliteration",
+ "NatNum",
+ };
+
+ // record each attribute of each level of each style in a static C++ variable.
+ // determine number of styles and number of levels per style on the fly.
+ sal_Int32 nStyles = getNumberOfChildren();
+ vector<sal_Int32> nLevels; // may be different for each style?
+ for( sal_Int32 i = 0; i < nStyles; i++ )
+ {
+ LocaleNode* p = getChildAt( i );
+ nLevels.push_back( p->getNumberOfChildren() );
+ for( sal_Int32 j=0; j<nLevels.back(); j++ )
+ {
+ const Attr& q = p->getChildAt( j )->getAttr();
+ for( sal_Int32 k=0; k<nAttributes; ++k )
+ {
+ const char* name = attr[k];
+ OUString value = q.getValueByName( name );
+ of.writeParameter("outline", name, value,
+ sal::static_int_cast<sal_Int16>(i),
+ sal::static_int_cast<sal_Int16>(j) );
+ }
+ }
+ }
+
+ // verify that each style has the same number of levels.
+ for( size_t i=0; i<nLevels.size(); i++ )
+ {
+ if( nLevels[0] != nLevels[i] )
+ {
+ incError( "Numbering levels don't match.");
+ }
+ }
+
+ // record number of attributes, levels, and styles.
+ of.writeAsciiString("static const sal_Int16 outlineNbOfStyles = ");
+ of.writeInt( sal::static_int_cast<sal_Int16>( nStyles ) );
+ of.writeAsciiString(";\n\n");
+ of.writeAsciiString("static const sal_Int16 outlineNbOfLevelsPerStyle = ");
+ of.writeInt( sal::static_int_cast<sal_Int16>( nLevels.back() ) );
+ of.writeAsciiString(";\n\n");
+ of.writeAsciiString("static const sal_Int16 outlineNbOfAttributesPerLevel = ");
+ of.writeInt( nAttributes );
+ of.writeAsciiString(";\n\n");
+
+ // too complicated for now...
+// of.writeAsciiString("static const sal_Int16 nbOfOutlineNumberingLevels[] = { ");
+// for( sal_Int32 j=0; j<nStyles; j++ )
+// {
+// of.writeInt( nLevels[j] );
+// of.writeAsciiString(", ");
+// }
+// of.writeAsciiString("};\n\n");
+
+
+ for( sal_Int32 i=0; i<nStyles; i++ )
+ {
+ for( sal_Int32 j=0; j<nLevels.back(); j++ )
+ {
+ of.writeAsciiString("static const sal_Unicode* outline");
+ of.writeAsciiString("Style");
+ of.writeInt( sal::static_int_cast<sal_Int16>(i) );
+ of.writeAsciiString("Level");
+ of.writeInt( sal::static_int_cast<sal_Int16>(j) );
+ of.writeAsciiString("[] = { ");
+
+ for( sal_Int32 k=0; k<nAttributes; k++ )
+ {
+ of.writeAsciiString( "outline" );
+ of.writeAsciiString( attr[k] );
+ of.writeInt( sal::static_int_cast<sal_Int16>(i) );
+ of.writeInt( sal::static_int_cast<sal_Int16>(j) );
+ of.writeAsciiString(", ");
+ }
+ of.writeAsciiString("NULL };\n");
+ }
+ }
+
+ of.writeAsciiString("\n");
+
+
+ for( sal_Int32 i=0; i<nStyles; i++ )
+ {
+ of.writeAsciiString("static const sal_Unicode** outline");
+ of.writeAsciiString( "Style" );
+ of.writeInt( sal::static_int_cast<sal_Int16>(i) );
+ of.writeAsciiString("[] = { ");
+
+ for( sal_Int32 j=0; j<nLevels.back(); j++ )
+ {
+ of.writeAsciiString("outlineStyle");
+ of.writeInt( sal::static_int_cast<sal_Int16>(i) );
+ of.writeAsciiString("Level");
+ of.writeInt( sal::static_int_cast<sal_Int16>(j) );
+ of.writeAsciiString(", ");
+ }
+ of.writeAsciiString("NULL };\n");
+ }
+ of.writeAsciiString("\n");
+
+ of.writeAsciiString("static const sal_Unicode*** LCOutlineNumberingLevelsArray[] = {\n" );
+ for( sal_Int32 i=0; i<nStyles; i++ )
+ {
+ of.writeAsciiString( "\t" );
+ of.writeAsciiString( "outlineStyle" );
+ of.writeInt( sal::static_int_cast<sal_Int16>(i) );
+ of.writeAsciiString(",\n");
+ }
+ of.writeAsciiString("\tNULL\n};\n\n");
+ of.writeFunction3("getOutlineNumberingLevels_", "outlineNbOfStyles", "outlineNbOfLevelsPerStyle",
+ "outlineNbOfAttributesPerLevel", "LCOutlineNumberingLevelsArray");
+}
+
+Attr::Attr (const Reference< XAttributeList > & attr) {
+ sal_Int16 len = attr->getLength();
+ name.realloc (len);
+ value.realloc (len);
+ for (sal_Int16 i =0; i< len;i++) {
+ name[i] = attr->getNameByIndex(i);
+ value[i] = attr -> getValueByIndex(i);
+ }
+}
+
+const OUString& Attr::getValueByName (const sal_Char *str) const {
+ static OUString empty;
+ sal_Int32 len = name.getLength();
+ for (sal_Int32 i = 0;i<len;i++)
+ if (name[i].equalsAscii(str))
+ return value[i];
+ return empty;
+}
+
+sal_Int32 Attr::getLength() const{
+ return name.getLength();
+}
+
+const OUString& Attr::getTypeByIndex (sal_Int32 idx) const {
+ return name[idx];
+}
+
+const OUString& Attr::getValueByIndex (sal_Int32 idx) const
+{
+ return value[idx];
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */