/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_i18npool.hxx" #include #include #include #include #include #include #include "LocaleNode.hxx" #include // 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) , xAttribs(new Attr(attr)) , parent(0) , children(0) , nChildren(0) , childArrSize(0) , nError(0) { } int LocaleNode::getError() const { int err = nError; for (sal_Int32 i=0;igetError(); 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;iprintR(); printf ("\t"); print(); } void LocaleNode::addChild ( LocaleNode * node) { if (childArrSize <= nChildren) { LocaleNode ** arrN = (LocaleNode **)malloc( sizeof (LocaleNode *)*(childArrSize+10) ) ; for (sal_Int32 i = 0; i 0 ) free(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 & attr) { if (name.equalsAscii("LC_INFO")) return new LCInfoNode (name,attr); if (name.equalsAscii("LC_CTYPE")) return new LCCTYPENode (name,attr); if (name.equalsAscii("LC_FORMAT")) return new LCFormatNode (name,attr); if (name.equalsAscii("LC_FORMAT_1")) return new LCFormatNode (name,attr); if (name.equalsAscii("LC_CALENDAR")) return new LCCalendarNode (name,attr); if (name.equalsAscii("LC_CURRENCY")) return new LCCurrencyNode (name,attr); if (name.equalsAscii("LC_TRANSLITERATION")) return new LCTransliterationNode (name,attr); if (name.equalsAscii("LC_COLLATION")) return new LCCollationNode (name,attr); if (name.equalsAscii("LC_INDEX")) return new LCIndexNode (name,attr); if (name.equalsAscii("LC_SEARCH")) return new LCSearchNode (name,attr); if (name.equalsAscii("LC_MISC")) return new LCMiscNode (name,attr); if (name.equalsAscii("LC_NumberingLevel")) return new LCNumberingLevelNode (name, attr); if (name.equalsAscii("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()) static void print_OUString( const OUString& s ) { printf( "%s", OSTR(s)); } static bool is_empty_string( const OUString& s ) { return (s.getLength()==0) || (s.getLength()==1 && s[0]=='\n'); } static void print_indent( int depth ) { for( int i=0; igetName() ); print_color(0); const Attr* q = p->getAttr(); if( q ) { for( sal_Int32 j=0; jgetLength(); 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; igetNumberOfChildren(); i++ ) { print_node( p->getChildAt(i), depth+1 ); } print_indent( depth ); printf("getName() ); printf(">"); printf("\n"); } void LocaleNode :: generateCode (const OFileWriter &of) const { ::rtl::OUString aDTD = getAttr()->getValueByName("versionDTD"); if (!aDTD.equalsAscii( 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; igenerateCode (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.equalsAscii( " ")) 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.equalsAscii( "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( pCollationOptions->getNumberOfChildren() ); for( sal_Int16 i=0; igetChildAt( 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 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; igetChildAt( i )->getValue(), sal::static_int_cast(i) ); } of.writeAsciiString("static const sal_Int16 nbOfSearchOptions = "); of.writeInt( sal::static_int_cast( nSearchOptions ) ); of.writeAsciiString(";\n\n"); of.writeAsciiString("static const sal_Unicode* searchOptions[] = {"); for( i=0; i(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 getValueByName("ref"); if (useLocale.getLength() > 0) { of.writeRefFunction("getAllCalendars_", useLocale); return; } sal_Int16 nbOfCalendars = sal::static_int_cast( 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.equalsAscii( "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::createFromAscii("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( 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.equalsAscii( "sun")) incError( "First day of a week of a Gregorian calendar must be sun"); 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::createFromAscii("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( 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.equalsAscii( "jan")) incError( "First month of a year of a Gregorian calendar must be jan"); 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::createFromAscii("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( 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.equalsAscii( "bc")) incError( "First era of a Gregorian calendar must be bc"); if (j == 1 && bGregorian && !eraID.equalsAscii( "ad")) incError( "Second era of a Gregorian calendar must be ad"); 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( " must be one of the , but is", str); } of.writeParameter("startDayOfWeek", str, i); str = calNode ->getChildAt(4)-> getValue(); sal_Int16 nDays = sal::static_int_cast( 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(sizeof(ReserveWord)/sizeof(ReserveWord[0])); 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; jgetValueByName( name ); of.writeParameter("continuous", name, value, sal::static_int_cast(i) ); } } // record number of styles and attributes. of.writeAsciiString("static const sal_Int16 continuousNbOfStyles = "); of.writeInt( sal::static_int_cast( 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(i) ); of.writeAsciiString("[] = {\n"); for( sal_Int32 j=0; j(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(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 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; jgetChildAt( j )->getAttr(); for( sal_Int32 k=0; kgetValueByName( name ); of.writeParameter("outline", name, value, sal::static_int_cast(i), sal::static_int_cast(j) ); } } } // verify that each style has the same number of levels. for( size_t i=0; i(i) ); of.writeAsciiString("Level"); of.writeInt( sal::static_int_cast(j) ); of.writeAsciiString("[] = { "); for( sal_Int32 k=0; k(i) ); of.writeInt( sal::static_int_cast(j) ); of.writeAsciiString(", "); } of.writeAsciiString("NULL };\n"); } } of.writeAsciiString("\n"); for( sal_Int32 i=0; i(i) ); of.writeAsciiString("[] = { "); for( sal_Int32 j=0; j(i) ); of.writeAsciiString("Level"); of.writeInt( sal::static_int_cast(j) ); of.writeAsciiString(", "); } of.writeAsciiString("NULL };\n"); } of.writeAsciiString("\n"); of.writeAsciiString("static const sal_Unicode*** LCOutlineNumberingLevelsArray[] = {\n" ); for( sal_Int32 i=0; i(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