1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_i18npool.hxx" 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <iostream> 34 #include <set> 35 36 #include <rtl/ustrbuf.hxx> 37 38 #include "LocaleNode.hxx" 39 #include <com/sun/star/i18n/NumberFormatIndex.hpp> 40 41 // NOTE: MUST match the Locale versionDTD attribute defined in data/locale.dtd 42 #define LOCALE_VERSION_DTD "2.0.3" 43 44 typedef ::std::set< ::rtl::OUString > NameSet; 45 typedef ::std::set< sal_Int16 > ValueSet; 46 47 namespace cssi = ::com::sun::star::i18n; 48 49 LocaleNode::LocaleNode (const OUString& name, const Reference< XAttributeList > & attr) 50 : aName(name) 51 , xAttribs(new Attr(attr)) 52 , parent(0) 53 , children(0) 54 , nChildren(0) 55 , childArrSize(0) 56 , nError(0) 57 { 58 } 59 60 int LocaleNode::getError() const 61 { 62 int err = nError; 63 for (sal_Int32 i=0;i<nChildren;i++) 64 err += children[i]->getError(); 65 return err; 66 } 67 68 void LocaleNode::print () const { 69 printf ("<"); 70 ::rtl::OUString str (aName); 71 for(sal_Int32 i = 0; i < str.getLength(); i++) 72 printf( "%c", str[i]); 73 printf (">\n"); 74 } 75 76 void LocaleNode::printR () const { 77 print(); 78 for (sal_Int32 i=0;i<nChildren;i++) 79 children[i]->printR(); 80 printf ("\t"); 81 print(); 82 } 83 84 void LocaleNode::addChild ( LocaleNode * node) { 85 if (childArrSize <= nChildren) { 86 LocaleNode ** arrN = (LocaleNode **)malloc( sizeof (LocaleNode *)*(childArrSize+10) ) ; 87 for (sal_Int32 i = 0; i<childArrSize ; i++) 88 arrN[i] = children[i]; 89 if ( childArrSize > 0 ) 90 free(children); 91 childArrSize += 10; 92 children = arrN; 93 } 94 children[nChildren++] = node; 95 node->setParent (this); 96 } 97 98 void LocaleNode::setParent ( LocaleNode * node) { 99 parent = node; 100 } 101 102 const LocaleNode* LocaleNode::getRoot() const 103 { 104 const LocaleNode* pRoot = 0; 105 const LocaleNode* pParent = this; 106 while ( (pParent = pParent->getParent()) != 0 ) 107 pRoot = pParent; 108 return pRoot; 109 } 110 111 const LocaleNode * LocaleNode::findNode ( const sal_Char *name) const { 112 if (aName.equalsAscii(name)) 113 return this; 114 for (sal_Int32 i = 0; i< nChildren; i++) { 115 const LocaleNode *n=children[i]->findNode(name); 116 if (n) 117 return n; 118 } 119 return 0; 120 } 121 122 LocaleNode::~LocaleNode() { 123 for (sal_Int32 i=0; i<nChildren;i++) 124 delete (children[i]); 125 } 126 127 LocaleNode* LocaleNode::createNode (const OUString& name, const Reference< XAttributeList > & attr) 128 { 129 if (name.equalsAscii("LC_INFO")) 130 return new LCInfoNode (name,attr); 131 if (name.equalsAscii("LC_CTYPE")) 132 return new LCCTYPENode (name,attr); 133 if (name.equalsAscii("LC_FORMAT")) 134 return new LCFormatNode (name,attr); 135 if (name.equalsAscii("LC_FORMAT_1")) 136 return new LCFormatNode (name,attr); 137 if (name.equalsAscii("LC_CALENDAR")) 138 return new LCCalendarNode (name,attr); 139 if (name.equalsAscii("LC_CURRENCY")) 140 return new LCCurrencyNode (name,attr); 141 if (name.equalsAscii("LC_TRANSLITERATION")) 142 return new LCTransliterationNode (name,attr); 143 if (name.equalsAscii("LC_COLLATION")) 144 return new LCCollationNode (name,attr); 145 if (name.equalsAscii("LC_INDEX")) 146 return new LCIndexNode (name,attr); 147 if (name.equalsAscii("LC_SEARCH")) 148 return new LCSearchNode (name,attr); 149 if (name.equalsAscii("LC_MISC")) 150 return new LCMiscNode (name,attr); 151 if (name.equalsAscii("LC_NumberingLevel")) 152 return new LCNumberingLevelNode (name, attr); 153 if (name.equalsAscii("LC_OutLineNumberingLevel")) 154 return new LCOutlineNumberingLevelNode (name, attr); 155 156 return new LocaleNode(name,attr); 157 } 158 159 160 // printf(" name: '%s'\n", p->getName().pData->buffer ); 161 // printf("value: '%s'\n", p->getValue().pData->buffer ); 162 163 #define OSTR(s) (OUStringToOString( (s), RTL_TEXTENCODING_UTF8).getStr()) 164 165 void print_OUString( const OUString& s ) 166 { 167 printf( "%s", OSTR(s)); 168 } 169 170 bool is_empty( const OUString& s ) 171 { 172 return (s.getLength()==0) || (s.getLength()==1 && s[0]=='\n'); 173 } 174 175 void print_indent( int depth ) 176 { 177 for( int i=0; i<depth; i++ ) printf(" "); 178 } 179 180 void print_color( int color ) 181 { 182 printf("\033[%dm", color); 183 } 184 185 void print_node( const LocaleNode* p, int depth=0 ) 186 { 187 if( !p ) return; 188 189 print_indent( depth ); 190 printf("<"); 191 print_color(36); 192 print_OUString( p->getName() ); 193 print_color(0); 194 const Attr* q = p->getAttr(); 195 if( q ) 196 { 197 for( sal_Int32 j=0; j<q->getLength(); j++ ) 198 { 199 printf(" "); 200 print_color(33); 201 print_OUString( q->getTypeByIndex(j) ); 202 print_color(0); 203 printf("="); 204 print_color(31); 205 printf("'"); 206 print_OUString( q->getValueByIndex(j) ); 207 printf("'"); 208 print_color(0); 209 } 210 } 211 printf(">"); 212 printf("\n"); 213 if( !is_empty( p->getValue() ) ) 214 { 215 print_indent( depth+1 ); 216 printf("value: "); 217 print_color(31); 218 printf("'"); 219 print_OUString( p->getValue() ); 220 printf("'"); 221 print_color(0); 222 printf("\n"); 223 } 224 for( sal_Int32 i=0; i<p->getNumberOfChildren(); i++ ) 225 { 226 print_node( p->getChildAt(i), depth+1 ); 227 } 228 print_indent( depth ); 229 printf("</"); 230 print_OUString( p->getName() ); 231 printf(">"); 232 printf("\n"); 233 } 234 235 void LocaleNode :: generateCode (const OFileWriter &of) const 236 { 237 ::rtl::OUString aDTD = getAttr()->getValueByName("versionDTD"); 238 if (!aDTD.equalsAscii( LOCALE_VERSION_DTD)) 239 { 240 ++nError; 241 fprintf( stderr, "Error: Locale versionDTD is not %s, see comment in locale.dtd\n", LOCALE_VERSION_DTD); 242 } 243 for (sal_Int32 i=0; i<nChildren;i++) 244 children[i]->generateCode (of); 245 // print_node( this ); 246 } 247 248 249 ::rtl::OUString LocaleNode::writeParameterCheckLen( const OFileWriter &of, 250 const char* pParameterName, const LocaleNode* pNode, 251 sal_Int32 nMinLen, sal_Int32 nMaxLen ) const 252 { 253 OUString aVal; 254 if (pNode) 255 aVal = pNode->getValue(); 256 else 257 { 258 ++nError; 259 fprintf( stderr, "Error: node NULL pointer for parameter %s.\n", 260 pParameterName); 261 } 262 // write empty data if error 263 of.writeParameter( pParameterName, aVal); 264 sal_Int32 nLen = aVal.getLength(); 265 if (nLen < nMinLen) 266 { 267 ++nError; 268 fprintf( stderr, "Error: less than %ld character%s (%ld) in %s '%s'.\n", 269 sal::static_int_cast< long >(nMinLen), (nMinLen > 1 ? "s" : ""), 270 sal::static_int_cast< long >(nLen), 271 (pNode ? OSTR( pNode->getName()) : ""), 272 OSTR( aVal)); 273 } 274 else if (nLen > nMaxLen && nMaxLen >= 0) 275 fprintf( stderr, 276 "Warning: more than %ld character%s (%ld) in %s %s not supported by application.\n", 277 sal::static_int_cast< long >(nMaxLen), (nMaxLen > 1 ? "s" : ""), 278 sal::static_int_cast< long >(nLen), 279 (pNode ? OSTR( pNode->getName()) : ""), 280 OSTR( aVal)); 281 return aVal; 282 } 283 284 285 ::rtl::OUString LocaleNode::writeParameterCheckLen( const OFileWriter &of, 286 const char* pNodeName, const char* pParameterName, 287 sal_Int32 nMinLen, sal_Int32 nMaxLen ) const 288 { 289 OUString aVal; 290 const LocaleNode * pNode = findNode( pNodeName); 291 if (pNode) 292 aVal = writeParameterCheckLen( of, pParameterName, pNode, nMinLen, nMaxLen); 293 else 294 { 295 ++nError; 296 fprintf( stderr, "Error: node %s not found.\n", pNodeName); 297 // write empty data if error 298 of.writeParameter( pParameterName, aVal); 299 } 300 return aVal; 301 } 302 303 void LocaleNode::incError( const char* pStr ) const 304 { 305 ++nError; 306 fprintf( stderr, "Error: %s\n", pStr); 307 } 308 309 void LocaleNode::incError( const ::rtl::OUString& rStr ) const 310 { 311 incError( OSTR( rStr)); 312 } 313 314 char* LocaleNode::prepareErrorFormat( const char* pFormat, const char* pDefaultConversion ) const 315 { 316 static char buf[2048]; 317 strcpy( buf, "Error: "); 318 strncat( buf, pFormat, 2000); 319 char* p = buf; 320 while (((p = strchr( p, '%')) != 0) && p[1] == '%') 321 p += 2; 322 if (!p) 323 strcat( buf, pDefaultConversion); 324 strcat( buf, "\n"); 325 return buf; 326 } 327 328 void LocaleNode::incErrorInt( const char* pStr, int nVal ) const 329 { 330 ++nError; 331 fprintf( stderr, prepareErrorFormat( pStr, ": %d"), nVal); 332 } 333 334 void LocaleNode::incErrorStr( const char* pStr, const ::rtl::OUString& rVal ) const 335 { 336 ++nError; 337 fprintf( stderr, prepareErrorFormat( pStr, ": %s"), OSTR( rVal)); 338 } 339 340 void LCInfoNode::generateCode (const OFileWriter &of) const 341 { 342 343 const LocaleNode * languageNode = findNode("Language"); 344 const LocaleNode * countryNode = findNode("Country"); 345 const LocaleNode * variantNode = findNode("Variant"); 346 347 if (languageNode) 348 { 349 writeParameterCheckLen( of, "langID", languageNode->getChildAt(0), 2, -1); 350 of.writeParameter("langDefaultName", languageNode->getChildAt(1)->getValue()); 351 } 352 else 353 incError( "No Language node."); 354 if (countryNode) 355 { 356 of.writeParameter("countryID", countryNode->getChildAt(0)->getValue()); 357 of.writeParameter("countryDefaultName", countryNode->getChildAt(1)->getValue()); 358 } 359 else 360 incError( "No Country node."); 361 if (variantNode) 362 { 363 of.writeParameter("Variant", variantNode->getValue()); 364 fprintf( stderr, "Warning: %s\n", 365 "Variants are not supported by application."); 366 } 367 else 368 of.writeParameter("Variant", ::rtl::OUString()); 369 of.writeAsciiString("\nstatic const sal_Unicode* LCInfoArray[] = {\n"); 370 of.writeAsciiString("\tlangID,\n"); 371 of.writeAsciiString("\tlangDefaultName,\n"); 372 of.writeAsciiString("\tcountryID,\n"); 373 of.writeAsciiString("\tcountryDefaultName,\n"); 374 of.writeAsciiString("\tVariant\n"); 375 of.writeAsciiString("};\n\n"); 376 of.writeFunction("getLCInfo_", "0", "LCInfoArray"); 377 } 378 379 void LCCTYPENode::generateCode (const OFileWriter &of) const 380 { 381 const LocaleNode * sepNode = 0; 382 ::rtl::OUString useLocale = getAttr() -> getValueByName("ref"); 383 if (useLocale.getLength() > 0) { 384 of.writeRefFunction("getLocaleItem_", useLocale); 385 return; 386 } 387 ::rtl::OUString str = getAttr() -> getValueByName("unoid"); 388 of.writeAsciiString("\n\n"); 389 of.writeParameter("LC_CTYPE_Unoid", str);; 390 391 OUString aDateSep = 392 writeParameterCheckLen( of, "DateSeparator", "dateSeparator", 1, 1); 393 OUString aThoSep = 394 writeParameterCheckLen( of, "ThousandSeparator", "thousandSeparator", 1, 1); 395 OUString aDecSep = 396 writeParameterCheckLen( of, "DecimalSeparator", "decimalSeparator", 1, 1); 397 OUString aTimeSep = 398 writeParameterCheckLen( of, "TimeSeparator", "timeSeparator", 1, 1); 399 OUString aTime100Sep = 400 writeParameterCheckLen( of, "Time100SecSeparator", "time100SecSeparator", 1, 1); 401 OUString aListSep = 402 writeParameterCheckLen( of, "ListSeparator", "listSeparator", 1, 1); 403 404 OUString aLDS; 405 406 sepNode = findNode("LongDateDayOfWeekSeparator"); 407 aLDS = sepNode->getValue(); 408 of.writeParameter("LongDateDayOfWeekSeparator", aLDS); 409 if (aLDS.getLength() == 1 && aLDS.getStr()[0] == ',') 410 fprintf( stderr, "Warning: %s\n", 411 "LongDateDayOfWeekSeparator is only a comma not followed by a space. Usually this is not the case and may lead to concatenated display names like \"Wednesday,May 9, 2007\"."); 412 413 sepNode = findNode("LongDateDaySeparator"); 414 aLDS = sepNode->getValue(); 415 of.writeParameter("LongDateDaySeparator", aLDS); 416 if (aLDS.getLength() == 1 && (aLDS.getStr()[0] == ',' || aLDS.getStr()[0] == '.')) 417 fprintf( stderr, "Warning: %s\n", 418 "LongDateDaySeparator is only a comma or dot not followed by a space. Usually this is not the case and may lead to concatenated display names like \"Wednesday, May 9,2007\"."); 419 420 sepNode = findNode("LongDateMonthSeparator"); 421 aLDS = sepNode->getValue(); 422 of.writeParameter("LongDateMonthSeparator", aLDS); 423 if (aLDS.getLength() == 0) 424 fprintf( stderr, "Warning: %s\n", 425 "LongDateMonthSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, May9, 2007\"."); 426 427 sepNode = findNode("LongDateYearSeparator"); 428 aLDS = sepNode->getValue(); 429 of.writeParameter("LongDateYearSeparator", aLDS); 430 if (aLDS.getLength() == 0) 431 fprintf( stderr, "Warning: %s\n", 432 "LongDateYearSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, 2007May 9\"."); 433 434 435 int nSavErr = nError; 436 int nWarn = 0; 437 if (aDateSep == aTimeSep) 438 incError( "DateSeparator equals TimeSeparator."); 439 if (aDecSep == aThoSep) 440 incError( "DecimalSeparator equals ThousandSeparator."); 441 if (aThoSep.equalsAscii( " ")) 442 incError( "ThousandSeparator is an ' ' ordinary space, this should be a non-breaking space U+00A0 instead."); 443 if (aListSep == aDecSep) 444 fprintf( stderr, "Warning: %s\n", 445 "ListSeparator equals DecimalSeparator."); 446 if (aListSep == aThoSep) 447 fprintf( stderr, "Warning: %s\n", 448 "ListSeparator equals ThousandSeparator."); 449 if (aListSep.getLength() != 1 || aListSep.getStr()[0] != ';') 450 { 451 incError( "ListSeparator not ';' semicolon. Strongly recommended. Currently required."); 452 ++nSavErr; // format codes not affected 453 } 454 if (aTimeSep == aTime100Sep) 455 ++nWarn, fprintf( stderr, "Warning: %s\n", 456 "Time100SecSeparator equals TimeSeparator, this is probably an error."); 457 if (aDecSep != aTime100Sep) 458 ++nWarn, fprintf( stderr, "Warning: %s\n", 459 "Time100SecSeparator is different from DecimalSeparator, this may be correct or not. Intended?"); 460 if (nSavErr != nError || nWarn) 461 fprintf( stderr, "Warning: %s\n", 462 "Don't forget to adapt corresponding FormatCode elements when changing separators."); 463 464 OUString aQuoteStart = 465 writeParameterCheckLen( of, "QuotationStart", "quotationStart", 1, 1); 466 OUString aQuoteEnd = 467 writeParameterCheckLen( of, "QuotationEnd", "quotationEnd", 1, 1); 468 OUString aDoubleQuoteStart = 469 writeParameterCheckLen( of, "DoubleQuotationStart", "doubleQuotationStart", 1, 1); 470 OUString aDoubleQuoteEnd = 471 writeParameterCheckLen( of, "DoubleQuotationEnd", "doubleQuotationEnd", 1, 1); 472 473 if (aQuoteStart.toChar() <= 127 && aQuoteEnd.toChar() > 127) 474 fprintf( stderr, "Warning: %s\n", 475 "QuotationStart is an ASCII character but QuotationEnd is not."); 476 if (aQuoteEnd.toChar() <= 127 && aQuoteStart.toChar() > 127) 477 fprintf( stderr, "Warning: %s\n", 478 "QuotationEnd is an ASCII character but QuotationStart is not."); 479 if (aDoubleQuoteStart.toChar() <= 127 && aDoubleQuoteEnd.toChar() > 127) 480 fprintf( stderr, "Warning: %s\n", 481 "DoubleQuotationStart is an ASCII character but DoubleQuotationEnd is not."); 482 if (aDoubleQuoteEnd.toChar() <= 127 && aDoubleQuoteStart.toChar() > 127) 483 fprintf( stderr, "Warning: %s\n", 484 "DoubleQuotationEnd is an ASCII character but DoubleQuotationStart is not."); 485 if (aQuoteStart.toChar() <= 127 && aQuoteEnd.toChar() <= 127) 486 fprintf( stderr, "Warning: %s\n", 487 "QuotationStart and QuotationEnd are both ASCII characters. Not necessarily an error, but unusual."); 488 if (aDoubleQuoteStart.toChar() <= 127 && aDoubleQuoteEnd.toChar() <= 127) 489 fprintf( stderr, "Warning: %s\n", 490 "DoubleQuotationStart and DoubleQuotationEnd are both ASCII characters. Not necessarily an error, but unusual."); 491 if (aQuoteStart == aQuoteEnd) 492 fprintf( stderr, "Warning: %s\n", 493 "QuotationStart equals QuotationEnd. Not necessarily an error, but unusual."); 494 if (aDoubleQuoteStart == aDoubleQuoteEnd) 495 fprintf( stderr, "Warning: %s\n", 496 "DoubleQuotationStart equals DoubleQuotationEnd. Not necessarily an error, but unusual."); 497 /* TODO: should equalness of single and double quotes be an error? Would 498 * need to adapt quite some locales' data. */ 499 if (aQuoteStart == aDoubleQuoteStart) 500 fprintf( stderr, "Warning: %s\n", 501 "QuotationStart equals DoubleQuotationStart. Not necessarily an error, but unusual."); 502 if (aQuoteEnd == aDoubleQuoteEnd) 503 fprintf( stderr, "Warning: %s\n", 504 "QuotationEnd equals DoubleQuotationEnd. Not necessarily an error, but unusual."); 505 // Known good values, exclude ASCII single (U+0027, ') and double (U+0022, ") quotes. 506 int ic; 507 switch (ic = aQuoteStart.toChar()) 508 { 509 case 0x2018: // LEFT SINGLE QUOTATION MARK 510 case 0x201a: // SINGLE LOW-9 QUOTATION MARK 511 case 0x201b: // SINGLE HIGH-REVERSED-9 QUOTATION MARK 512 case 0x2039: // SINGLE LEFT-POINTING ANGLE QUOTATION MARK 513 case 0x203a: // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK 514 case 0x300c: // LEFT CORNER BRACKET (Chinese) 515 ; 516 break; 517 default: 518 fprintf( stderr, "Warning: %s U+%04X %s\n", 519 "QuotationStart may be wrong:", ic, OSTR( aQuoteStart)); 520 } 521 switch (ic = aQuoteEnd.toChar()) 522 { 523 case 0x2019: // RIGHT SINGLE QUOTATION MARK 524 case 0x201a: // SINGLE LOW-9 QUOTATION MARK 525 case 0x201b: // SINGLE HIGH-REVERSED-9 QUOTATION MARK 526 case 0x2039: // SINGLE LEFT-POINTING ANGLE QUOTATION MARK 527 case 0x203a: // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK 528 case 0x300d: // RIGHT CORNER BRACKET (Chinese) 529 ; 530 break; 531 default: 532 fprintf( stderr, "Warning: %s U+%04X %s\n", 533 "QuotationEnd may be wrong:", ic, OSTR( aQuoteEnd)); 534 } 535 switch (ic = aDoubleQuoteStart.toChar()) 536 { 537 case 0x00ab: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 538 case 0x00bb: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 539 case 0x201c: // LEFT DOUBLE QUOTATION MARK 540 case 0x201e: // DOUBLE LOW-9 QUOTATION MARK 541 case 0x201f: // DOUBLE HIGH-REVERSED-9 QUOTATION MARK 542 case 0x300e: // LEFT WHITE CORNER BRACKET (Chinese) 543 ; 544 break; 545 default: 546 fprintf( stderr, "Warning: %s U+%04X %s\n", 547 "DoubleQuotationStart may be wrong:", ic, OSTR( aDoubleQuoteStart)); 548 } 549 switch (ic = aDoubleQuoteEnd.toChar()) 550 { 551 case 0x00ab: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 552 case 0x00bb: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 553 case 0x201d: // RIGHT DOUBLE QUOTATION MARK 554 case 0x201e: // DOUBLE LOW-9 QUOTATION MARK 555 case 0x201f: // DOUBLE HIGH-REVERSED-9 QUOTATION MARK 556 case 0x300f: // RIGHT WHITE CORNER BRACKET (Chinese) 557 ; 558 break; 559 default: 560 fprintf( stderr, "Warning: %s U+%04X %s\n", 561 "DoubleQuotationEnd may be wrong:", ic, OSTR( aDoubleQuoteEnd)); 562 } 563 564 writeParameterCheckLen( of, "TimeAM", "timeAM", 1, -1); 565 writeParameterCheckLen( of, "TimePM", "timePM", 1, -1); 566 sepNode = findNode("MeasurementSystem"); 567 of.writeParameter("measurementSystem", sepNode->getValue()); 568 569 of.writeAsciiString("\nstatic const sal_Unicode* LCType[] = {\n"); 570 of.writeAsciiString("\tLC_CTYPE_Unoid,\n"); 571 of.writeAsciiString("\tdateSeparator,\n"); 572 of.writeAsciiString("\tthousandSeparator,\n"); 573 of.writeAsciiString("\tdecimalSeparator,\n"); 574 of.writeAsciiString("\ttimeSeparator,\n"); 575 of.writeAsciiString("\ttime100SecSeparator,\n"); 576 of.writeAsciiString("\tlistSeparator,\n"); 577 of.writeAsciiString("\tquotationStart,\n"); 578 of.writeAsciiString("\tquotationEnd,\n"); 579 of.writeAsciiString("\tdoubleQuotationStart,\n"); 580 of.writeAsciiString("\tdoubleQuotationEnd,\n"); 581 of.writeAsciiString("\ttimeAM,\n"); 582 of.writeAsciiString("\ttimePM,\n"); 583 of.writeAsciiString("\tmeasurementSystem,\n"); 584 of.writeAsciiString("\tLongDateDayOfWeekSeparator,\n"); 585 of.writeAsciiString("\tLongDateDaySeparator,\n"); 586 of.writeAsciiString("\tLongDateMonthSeparator,\n"); 587 of.writeAsciiString("\tLongDateYearSeparator\n"); 588 of.writeAsciiString("};\n\n"); 589 of.writeFunction("getLocaleItem_", "0", "LCType"); 590 } 591 592 593 sal_Int16 LCFormatNode::mnSection = 0; 594 sal_Int16 LCFormatNode::mnFormats = 0; 595 596 void LCFormatNode::generateCode (const OFileWriter &of) const 597 { 598 OUString str; 599 if (mnSection >= 2) 600 incError("more than 2 LC_FORMAT sections"); 601 of.writeParameter("replaceFrom", getAttr() -> getValueByName("replaceFrom"), mnSection); 602 str = getAttr() -> getValueByName("replaceTo"); 603 // Locale data generator inserts FFFF for LangID, we need to adapt that. 604 if (str.endsWithIgnoreAsciiCaseAsciiL( "-FFFF]", 6)) 605 incErrorStr("replaceTo=\"%s\" needs FFFF to be adapted to the real LangID value.", str); 606 of.writeParameter("replaceTo", str, mnSection); 607 ::rtl::OUString useLocale = getAttr() -> getValueByName("ref"); 608 if (useLocale.getLength() > 0) { 609 switch (mnSection) 610 { 611 case 0: 612 of.writeRefFunction("getAllFormats0_", useLocale, "replaceTo0"); 613 break; 614 case 1: 615 of.writeRefFunction("getAllFormats1_", useLocale, "replaceTo1"); 616 break; 617 } 618 return; 619 } 620 sal_Int16 formatCount = mnFormats; 621 NameSet aMsgIdSet; 622 ValueSet aFormatIndexSet; 623 NameSet aDefaultsSet; 624 bool bCtypeIsRef = false; 625 626 for (sal_Int16 i = 0; i< getNumberOfChildren() ; i++,formatCount++) { 627 LocaleNode * currNode = getChildAt (i); 628 OUString aUsage; 629 OUString aType; 630 OUString aFormatIndex; 631 // currNode -> print(); 632 const Attr * currNodeAttr = currNode->getAttr(); 633 //printf ("getLen() = %d\n", currNode->getAttr()->getLength()); 634 635 str = currNodeAttr -> getValueByName("msgid"); 636 if (!aMsgIdSet.insert( str).second) 637 incErrorStr( "Duplicated msgid=\"%s\" in FormatElement.", str); 638 of.writeParameter("FormatKey", str, formatCount); 639 640 str = currNodeAttr -> getValueByName("default"); 641 bool bDefault = str.equalsAscii( "true"); 642 of.writeDefaultParameter("FormatElement", str, formatCount); 643 644 aType = currNodeAttr -> getValueByName("type"); 645 of.writeParameter("FormatType", aType, formatCount); 646 647 aUsage = currNodeAttr -> getValueByName("usage"); 648 of.writeParameter("FormatUsage", aUsage, formatCount); 649 650 aFormatIndex = currNodeAttr -> getValueByName("formatindex"); 651 sal_Int16 formatindex = (sal_Int16)aFormatIndex.toInt32(); 652 if (!aFormatIndexSet.insert( formatindex).second) 653 incErrorInt( "Duplicated formatindex=\"%d\" in FormatElement.", formatindex); 654 of.writeIntParameter("Formatindex", formatCount, formatindex); 655 656 // Ensure only one default per usage and type. 657 if (bDefault) 658 { 659 OUString aKey( aUsage + OUString( sal_Unicode(',')) + aType); 660 if (!aDefaultsSet.insert( aKey).second) 661 { 662 OUString aStr( RTL_CONSTASCII_USTRINGPARAM( "Duplicated default for usage=\"")); 663 aStr += aUsage; 664 aStr += OUString( RTL_CONSTASCII_USTRINGPARAM( "\" type=\"")); 665 aStr += aType; 666 aStr += OUString( RTL_CONSTASCII_USTRINGPARAM( "\": formatindex=\"")); 667 aStr += aFormatIndex; 668 aStr += OUString( RTL_CONSTASCII_USTRINGPARAM( "\".")); 669 incError( aStr); 670 } 671 } 672 673 const LocaleNode * n = currNode -> findNode("FormatCode"); 674 if (n) 675 { 676 of.writeParameter("FormatCode", n->getValue(), formatCount); 677 // Check separator usage for some FormatCode elements. 678 const LocaleNode* pCtype = 0; 679 switch (formatindex) 680 { 681 case cssi::NumberFormatIndex::NUMBER_1000DEC2 : // #,##0.00 682 case cssi::NumberFormatIndex::TIME_MMSS00 : // MM:SS.00 683 case cssi::NumberFormatIndex::TIME_HH_MMSS00 : // [HH]:MM:SS.00 684 { 685 const LocaleNode* pRoot = getRoot(); 686 if (!pRoot) 687 incError( "No root for FormatCode."); 688 else 689 { 690 pCtype = pRoot->findNode( "LC_CTYPE"); 691 if (!pCtype) 692 incError( "No LC_CTYPE found for FormatCode."); 693 else 694 { 695 OUString aRef( pCtype->getAttr()->getValueByName("ref")); 696 if (aRef.getLength() > 0) 697 { 698 if (!bCtypeIsRef) 699 fprintf( stderr, 700 "Warning: Can't check separators used in FormatCode due to LC_CTYPE ref=\"%s\".\n" 701 "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", 702 OSTR( aRef)); 703 bCtypeIsRef = true; 704 pCtype = 0; 705 } 706 } 707 } 708 } 709 break; 710 // Currency formats should be something like [C]###0;-[C]###0 711 // and not parenthesized [C]###0;([C]###0) if not en_US. 712 case cssi::NumberFormatIndex::CURRENCY_1000INT : 713 case cssi::NumberFormatIndex::CURRENCY_1000INT_RED : 714 case cssi::NumberFormatIndex::CURRENCY_1000DEC2 : 715 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_RED : 716 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_CCC : 717 case cssi::NumberFormatIndex::CURRENCY_1000DEC2_DASHED : 718 if (strcmp( of.getLocale(), "en_US") != 0) 719 { 720 OUString aCode( n->getValue()); 721 OUString aPar1( RTL_CONSTASCII_USTRINGPARAM( "0)" )); 722 OUString aPar2( RTL_CONSTASCII_USTRINGPARAM( "-)" )); 723 OUString aPar3( RTL_CONSTASCII_USTRINGPARAM( " )" )); 724 OUString aPar4( RTL_CONSTASCII_USTRINGPARAM( "])" )); 725 if (aCode.indexOf( aPar1 ) > 0 || aCode.indexOf( aPar2 ) > 0 || 726 aCode.indexOf( aPar3 ) > 0 || aCode.indexOf( aPar4 ) > 0) 727 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); 728 } 729 break; 730 } 731 if (pCtype) 732 { 733 int nSavErr = nError; 734 OUString aCode( n->getValue()); 735 if (formatindex == cssi::NumberFormatIndex::NUMBER_1000DEC2) 736 { 737 sal_Int32 nDec = -1; 738 sal_Int32 nGrp = -1; 739 const LocaleNode* pSep = pCtype->findNode( "DecimalSeparator"); 740 if (!pSep) 741 incError( "No DecimalSeparator found for FormatCode."); 742 else 743 { 744 nDec = aCode.indexOf( pSep->getValue()); 745 if (nDec < 0) 746 incErrorInt( "DecimalSeparator not present in FormatCode formatindex=\"%d\".", 747 formatindex); 748 } 749 pSep = pCtype->findNode( "ThousandSeparator"); 750 if (!pSep) 751 incError( "No ThousandSeparator found for FormatCode."); 752 else 753 { 754 nGrp = aCode.indexOf( pSep->getValue()); 755 if (nGrp < 0) 756 incErrorInt( "ThousandSeparator not present in FormatCode formatindex=\"%d\".", 757 formatindex); 758 } 759 if (nDec >= 0 && nGrp >= 0 && nDec <= nGrp) 760 incErrorInt( "Ordering of ThousandSeparator and DecimalSeparator not correct in formatindex=\"%d\".", 761 formatindex); 762 } 763 if (formatindex == cssi::NumberFormatIndex::TIME_MMSS00 || 764 formatindex == cssi::NumberFormatIndex::TIME_HH_MMSS00) 765 { 766 sal_Int32 nTime = -1; 767 sal_Int32 n100s = -1; 768 const LocaleNode* pSep = pCtype->findNode( "TimeSeparator"); 769 if (!pSep) 770 incError( "No TimeSeparator found for FormatCode."); 771 else 772 { 773 nTime = aCode.indexOf( pSep->getValue()); 774 if (nTime < 0) 775 incErrorInt( "TimeSeparator not present in FormatCode formatindex=\"%d\".", 776 formatindex); 777 } 778 pSep = pCtype->findNode( "Time100SecSeparator"); 779 if (!pSep) 780 incError( "No Time100SecSeparator found for FormatCode."); 781 else 782 { 783 n100s = aCode.indexOf( pSep->getValue()); 784 if (n100s < 0) 785 incErrorInt( "Time100SecSeparator not present in FormatCode formatindex=\"%d\".", 786 formatindex); 787 OUStringBuffer a100s( pSep->getValue()); 788 a100s.appendAscii( "00"); 789 n100s = aCode.indexOf( a100s.makeStringAndClear()); 790 if (n100s < 0) 791 incErrorInt( "Time100SecSeparator+00 not present in FormatCode formatindex=\"%d\".", 792 formatindex); 793 } 794 if (n100s >= 0 && nTime >= 0 && n100s <= nTime) 795 incErrorInt( "Ordering of Time100SecSeparator and TimeSeparator not correct in formatindex=\"%d\".", 796 formatindex); 797 } 798 if (nSavErr != nError) 799 fprintf( stderr, 800 "Warning: formatindex=\"%d\",\"%d\",\"%d\" are the only FormatCode elements checked for separator usage, there may be others that have errors.\n", 801 int(cssi::NumberFormatIndex::NUMBER_1000DEC2), 802 int(cssi::NumberFormatIndex::TIME_MMSS00), 803 int(cssi::NumberFormatIndex::TIME_HH_MMSS00)); 804 805 } 806 } 807 else 808 incError( "No FormatCode in FormatElement."); 809 n = currNode -> findNode("DefaultName"); 810 if (n) 811 of.writeParameter("FormatDefaultName", n->getValue(), formatCount); 812 else 813 of.writeParameter("FormatDefaultName", ::rtl::OUString(), formatCount); 814 815 } 816 817 // Check presence of all required format codes only in first section 818 // LC_FORMAT, not in optional LC_FORMAT_1 819 if (mnSection == 0) 820 { 821 // 0..47 MUST be present, 48,49 MUST NOT be present 822 ValueSet::const_iterator aIter( aFormatIndexSet.begin()); 823 for (sal_Int16 nNext = cssi::NumberFormatIndex::NUMBER_START; 824 nNext < cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES; ++nNext) 825 { 826 sal_Int16 nHere = ::std::min( ((aIter != aFormatIndexSet.end() ? *aIter : 827 cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES)), 828 cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES); 829 if (aIter != aFormatIndexSet.end()) ++aIter; 830 for ( ; nNext < nHere; ++nNext) 831 { 832 switch (nNext) 833 { 834 case cssi::NumberFormatIndex::FRACTION_1 : 835 case cssi::NumberFormatIndex::FRACTION_2 : 836 case cssi::NumberFormatIndex::BOOLEAN : 837 case cssi::NumberFormatIndex::TEXT : 838 // generated internally 839 break; 840 default: 841 incErrorInt( "FormatElement formatindex=\"%d\" not present.", nNext); 842 } 843 } 844 switch (nHere) 845 { 846 case cssi::NumberFormatIndex::BOOLEAN : 847 incErrorInt( "FormatElement formatindex=\"%d\" reserved for internal ``BOOLEAN''.", nNext); 848 break; 849 case cssi::NumberFormatIndex::TEXT : 850 incErrorInt( "FormatElement formatindex=\"%d\" reserved for internal ``@'' (TEXT).", nNext); 851 break; 852 default: 853 ; // nothing 854 } 855 } 856 } 857 858 of.writeAsciiString("\nstatic const sal_Int16 "); 859 of.writeAsciiString("FormatElementsCount"); 860 of.writeInt(mnSection); 861 of.writeAsciiString(" = "); 862 of.writeInt( formatCount - mnFormats); 863 of.writeAsciiString(";\n"); 864 of.writeAsciiString("static const sal_Unicode* "); 865 of.writeAsciiString("FormatElementsArray"); 866 of.writeInt(mnSection); 867 of.writeAsciiString("[] = {\n"); 868 for(sal_Int16 i = mnFormats; i < formatCount; i++) { 869 870 of.writeAsciiString("\t"); 871 of.writeAsciiString("FormatCode"); 872 of.writeInt(i); 873 of.writeAsciiString(",\n"); 874 875 of.writeAsciiString("\t"); 876 of.writeAsciiString("FormatDefaultName"); 877 of.writeInt(i); 878 of.writeAsciiString(",\n"); 879 880 of.writeAsciiString("\t"); 881 of.writeAsciiString("FormatKey"); 882 of.writeInt(i); 883 of.writeAsciiString(",\n"); 884 885 of.writeAsciiString("\t"); 886 of.writeAsciiString("FormatType"); 887 of.writeInt(i); 888 of.writeAsciiString(",\n"); 889 890 of.writeAsciiString("\t"); 891 of.writeAsciiString("FormatUsage"); 892 of.writeInt(i); 893 of.writeAsciiString(",\n"); 894 895 of.writeAsciiString("\t"); 896 of.writeAsciiString("Formatindex"); 897 of.writeInt(i); 898 of.writeAsciiString(",\n"); 899 900 901 of.writeAsciiString("\tdefaultFormatElement"); 902 of.writeInt(i); 903 of.writeAsciiString(",\n"); 904 } 905 of.writeAsciiString("};\n\n"); 906 907 switch (mnSection) 908 { 909 case 0: 910 of.writeFunction("getAllFormats0_", "FormatElementsCount0", "FormatElementsArray0", "replaceFrom0", "replaceTo0"); 911 break; 912 case 1: 913 of.writeFunction("getAllFormats1_", "FormatElementsCount1", "FormatElementsArray1", "replaceFrom1", "replaceTo1"); 914 break; 915 } 916 917 mnFormats = mnFormats + formatCount; 918 ++mnSection; 919 } 920 921 void LCCollationNode::generateCode (const OFileWriter &of) const 922 { 923 ::rtl::OUString useLocale = getAttr() -> getValueByName("ref"); 924 if (useLocale.getLength() > 0) { 925 of.writeRefFunction("getCollatorImplementation_", useLocale); 926 of.writeRefFunction("getCollationOptions_", useLocale); 927 return; 928 } 929 sal_Int16 nbOfCollations = 0; 930 sal_Int16 nbOfCollationOptions = 0; 931 sal_Int16 j; 932 933 for ( j = 0; j < getNumberOfChildren(); j++ ) { 934 LocaleNode * currNode = getChildAt (j); 935 if( currNode->getName().compareToAscii("Collator") == 0 ) 936 { 937 ::rtl::OUString str; 938 str = currNode->getAttr() -> getValueByName("unoid"); 939 of.writeParameter("CollatorID", str, j); 940 str = currNode->getValue(); 941 of.writeParameter("CollatorRule", str, j); 942 str = currNode -> getAttr() -> getValueByName("default"); 943 of.writeDefaultParameter("Collator", str, j); 944 of.writeAsciiString("\n"); 945 946 nbOfCollations++; 947 } 948 if( currNode->getName().compareToAscii("CollationOptions") == 0 ) 949 { 950 LocaleNode* pCollationOptions = currNode; 951 nbOfCollationOptions = sal::static_int_cast<sal_Int16>( pCollationOptions->getNumberOfChildren() ); 952 for( sal_Int16 i=0; i<nbOfCollationOptions; i++ ) 953 { 954 of.writeParameter("collationOption", pCollationOptions->getChildAt( i )->getValue(), i ); 955 } 956 957 of.writeAsciiString("static const sal_Int16 nbOfCollationOptions = "); 958 of.writeInt( nbOfCollationOptions ); 959 of.writeAsciiString(";\n\n"); 960 } 961 } 962 of.writeAsciiString("static const sal_Int16 nbOfCollations = "); 963 of.writeInt(nbOfCollations); 964 of.writeAsciiString(";\n\n"); 965 966 of.writeAsciiString("\nstatic const sal_Unicode* LCCollatorArray[] = {\n"); 967 for(j = 0; j < nbOfCollations; j++) { 968 of.writeAsciiString("\tCollatorID"); 969 of.writeInt(j); 970 of.writeAsciiString(",\n"); 971 972 of.writeAsciiString("\tdefaultCollator"); 973 of.writeInt(j); 974 of.writeAsciiString(",\n"); 975 976 of.writeAsciiString("\tCollatorRule"); 977 of.writeInt(j); 978 of.writeAsciiString(",\n"); 979 } 980 of.writeAsciiString("};\n\n"); 981 982 of.writeAsciiString("static const sal_Unicode* collationOptions[] = {"); 983 for( j=0; j<nbOfCollationOptions; j++ ) 984 { 985 of.writeAsciiString( "collationOption" ); 986 of.writeInt( j ); 987 of.writeAsciiString( ", " ); 988 } 989 of.writeAsciiString("NULL };\n"); 990 of.writeFunction("getCollatorImplementation_", "nbOfCollations", "LCCollatorArray"); 991 of.writeFunction("getCollationOptions_", "nbOfCollationOptions", "collationOptions"); 992 } 993 994 void LCSearchNode::generateCode (const OFileWriter &of) const 995 { 996 ::rtl::OUString useLocale = getAttr() -> getValueByName("ref"); 997 if (useLocale.getLength() > 0) { 998 of.writeRefFunction("getSearchOptions_", useLocale); 999 return; 1000 } 1001 1002 if( getNumberOfChildren() != 1 ) 1003 { 1004 ++nError; 1005 fprintf( 1006 stderr, "Error: LC_SEARCH: more than 1 child: %ld\n", 1007 sal::static_int_cast< long >(getNumberOfChildren())); 1008 } 1009 sal_Int32 i; 1010 LocaleNode* pSearchOptions = getChildAt( 0 ); 1011 sal_Int32 nSearchOptions = pSearchOptions->getNumberOfChildren(); 1012 for( i=0; i<nSearchOptions; i++ ) 1013 { 1014 of.writeParameter("searchOption", pSearchOptions->getChildAt( i )->getValue(), sal::static_int_cast<sal_Int16>(i) ); 1015 } 1016 1017 of.writeAsciiString("static const sal_Int16 nbOfSearchOptions = "); 1018 of.writeInt( sal::static_int_cast<sal_Int16>( nSearchOptions ) ); 1019 of.writeAsciiString(";\n\n"); 1020 1021 of.writeAsciiString("static const sal_Unicode* searchOptions[] = {"); 1022 for( i=0; i<nSearchOptions; i++ ) 1023 { 1024 of.writeAsciiString( "searchOption" ); 1025 of.writeInt( sal::static_int_cast<sal_Int16>(i) ); 1026 of.writeAsciiString( ", " ); 1027 } 1028 of.writeAsciiString("NULL };\n"); 1029 of.writeFunction("getSearchOptions_", "nbOfSearchOptions", "searchOptions"); 1030 } 1031 1032 void LCIndexNode::generateCode (const OFileWriter &of) const 1033 { 1034 ::rtl::OUString useLocale = getAttr() -> getValueByName("ref"); 1035 if (useLocale.getLength() > 0) { 1036 of.writeRefFunction("getIndexAlgorithm_", useLocale); 1037 of.writeRefFunction("getUnicodeScripts_", useLocale); 1038 of.writeRefFunction("getFollowPageWords_", useLocale); 1039 return; 1040 } 1041 sal_Int16 nbOfIndexs = 0; 1042 sal_Int16 nbOfUnicodeScripts = 0; 1043 sal_Int16 nbOfPageWords = 0; 1044 sal_Int16 i; 1045 for (i = 0; i< getNumberOfChildren();i++) { 1046 LocaleNode * currNode = getChildAt (i); 1047 if( currNode->getName().compareToAscii("IndexKey") == 0 ) 1048 { 1049 ::rtl::OUString str; 1050 str = currNode->getAttr() -> getValueByName("unoid"); 1051 of.writeParameter("IndexID", str, nbOfIndexs); 1052 str = currNode->getAttr() -> getValueByName("module"); 1053 of.writeParameter("IndexModule", str, nbOfIndexs); 1054 str = currNode->getValue(); 1055 of.writeParameter("IndexKey", str, nbOfIndexs); 1056 str = currNode -> getAttr() -> getValueByName("default"); 1057 of.writeDefaultParameter("Index", str, nbOfIndexs); 1058 str = currNode -> getAttr() -> getValueByName("phonetic"); 1059 of.writeDefaultParameter("Phonetic", str, nbOfIndexs); 1060 of.writeAsciiString("\n"); 1061 1062 nbOfIndexs++; 1063 } 1064 if( currNode->getName().compareToAscii("UnicodeScript") == 0 ) 1065 { 1066 of.writeParameter("unicodeScript", currNode->getValue(), nbOfUnicodeScripts ); 1067 nbOfUnicodeScripts++; 1068 1069 } 1070 if( currNode->getName().compareToAscii("FollowPageWord") == 0 ) 1071 { 1072 of.writeParameter("followPageWord", currNode->getValue(), nbOfPageWords); 1073 nbOfPageWords++; 1074 } 1075 } 1076 of.writeAsciiString("static const sal_Int16 nbOfIndexs = "); 1077 of.writeInt(nbOfIndexs); 1078 of.writeAsciiString(";\n\n"); 1079 1080 of.writeAsciiString("\nstatic const sal_Unicode* IndexArray[] = {\n"); 1081 for(i = 0; i < nbOfIndexs; i++) { 1082 of.writeAsciiString("\tIndexID"); 1083 of.writeInt(i); 1084 of.writeAsciiString(",\n"); 1085 1086 of.writeAsciiString("\tIndexModule"); 1087 of.writeInt(i); 1088 of.writeAsciiString(",\n"); 1089 1090 of.writeAsciiString("\tIndexKey"); 1091 of.writeInt(i); 1092 of.writeAsciiString(",\n"); 1093 1094 of.writeAsciiString("\tdefaultIndex"); 1095 of.writeInt(i); 1096 of.writeAsciiString(",\n"); 1097 1098 of.writeAsciiString("\tdefaultPhonetic"); 1099 of.writeInt(i); 1100 of.writeAsciiString(",\n"); 1101 } 1102 of.writeAsciiString("};\n\n"); 1103 1104 of.writeAsciiString("static const sal_Int16 nbOfUnicodeScripts = "); 1105 of.writeInt( nbOfUnicodeScripts ); 1106 of.writeAsciiString(";\n\n"); 1107 1108 of.writeAsciiString("static const sal_Unicode* UnicodeScriptArray[] = {"); 1109 for( i=0; i<nbOfUnicodeScripts; i++ ) 1110 { 1111 of.writeAsciiString( "unicodeScript" ); 1112 of.writeInt( i ); 1113 of.writeAsciiString( ", " ); 1114 } 1115 of.writeAsciiString("NULL };\n\n"); 1116 1117 of.writeAsciiString("static const sal_Int16 nbOfPageWords = "); 1118 of.writeInt(nbOfPageWords); 1119 of.writeAsciiString(";\n\n"); 1120 1121 of.writeAsciiString("static const sal_Unicode* FollowPageWordArray[] = {\n"); 1122 for(i = 0; i < nbOfPageWords; i++) { 1123 of.writeAsciiString("\tfollowPageWord"); 1124 of.writeInt(i); 1125 of.writeAsciiString(",\n"); 1126 } 1127 of.writeAsciiString("\tNULL\n};\n\n"); 1128 1129 of.writeFunction("getIndexAlgorithm_", "nbOfIndexs", "IndexArray"); 1130 of.writeFunction("getUnicodeScripts_", "nbOfUnicodeScripts", "UnicodeScriptArray"); 1131 of.writeFunction("getFollowPageWords_", "nbOfPageWords", "FollowPageWordArray"); 1132 } 1133 1134 void LCCalendarNode::generateCode (const OFileWriter &of) const 1135 { 1136 ::rtl::OUString useLocale = getAttr() -> getValueByName("ref"); 1137 if (useLocale.getLength() > 0) { 1138 of.writeRefFunction("getAllCalendars_", useLocale); 1139 return; 1140 } 1141 sal_Int16 nbOfCalendars = sal::static_int_cast<sal_Int16>( getNumberOfChildren() ); 1142 ::rtl::OUString str; 1143 sal_Int16 * nbOfDays = new sal_Int16[nbOfCalendars]; 1144 sal_Int16 * nbOfMonths = new sal_Int16[nbOfCalendars]; 1145 sal_Int16 * nbOfEras = new sal_Int16[nbOfCalendars]; 1146 sal_Int16 j; 1147 sal_Int16 i; 1148 bool bHasGregorian = false; 1149 1150 1151 for ( i = 0; i < nbOfCalendars; i++) { 1152 LocaleNode * calNode = getChildAt (i); 1153 OUString calendarID = calNode -> getAttr() -> getValueByName("unoid"); 1154 of.writeParameter( "calendarID", calendarID, i); 1155 bool bGregorian = calendarID.equalsAscii( "gregorian"); 1156 if (!bHasGregorian) 1157 bHasGregorian = bGregorian; 1158 str = calNode -> getAttr() -> getValueByName("default"); 1159 of.writeDefaultParameter("Calendar", str, i); 1160 1161 // Generate Days of Week 1162 const sal_Char *elementTag; 1163 LocaleNode * daysNode = NULL; 1164 ::rtl::OUString ref_name = calNode->getChildAt(0)->getAttr()->getValueByName("ref"); 1165 if (ref_name.getLength() > 0 && i > 0) { 1166 for (j = 0; j < i; j++) { 1167 str = getChildAt(j)->getAttr()->getValueByName("unoid"); 1168 if (str.equals(ref_name)) 1169 daysNode = getChildAt(j)->getChildAt(0); 1170 } 1171 } 1172 if (ref_name.getLength() > 0 && daysNode == NULL) { 1173 of.writeParameter("dayRef", OUString::createFromAscii("ref"), i); 1174 of.writeParameter("dayRefName", ref_name, i); 1175 nbOfDays[i] = 0; 1176 } else { 1177 if (daysNode == NULL) 1178 daysNode = calNode -> getChildAt(0); 1179 nbOfDays[i] = sal::static_int_cast<sal_Int16>( daysNode->getNumberOfChildren() ); 1180 if (bGregorian && nbOfDays[i] != 7) 1181 incErrorInt( "A Gregorian calendar must have 7 days per week, this one has %d", nbOfDays[i]); 1182 elementTag = "day"; 1183 for (j = 0; j < nbOfDays[i]; j++) { 1184 LocaleNode *currNode = daysNode -> getChildAt(j); 1185 OUString dayID( currNode->getChildAt(0)->getValue()); 1186 of.writeParameter("dayID", dayID, i, j); 1187 if (j == 0 && bGregorian && !dayID.equalsAscii( "sun")) 1188 incError( "First day of a week of a Gregorian calendar must be <DayID>sun</DayID>"); 1189 of.writeParameter(elementTag, "DefaultAbbrvName",currNode->getChildAt(1)->getValue() ,i, j); 1190 of.writeParameter(elementTag, "DefaultFullName",currNode->getChildAt(2)->getValue() , i, j); 1191 } 1192 } 1193 1194 // Generate Months of Year 1195 LocaleNode * monthsNode = NULL; 1196 ref_name = calNode->getChildAt(1)->getAttr()->getValueByName("ref"); 1197 if (ref_name.getLength() > 0 && i > 0) { 1198 for (j = 0; j < i; j++) { 1199 str = getChildAt(j)->getAttr()->getValueByName("unoid"); 1200 if (str.equals(ref_name)) 1201 monthsNode = getChildAt(j)->getChildAt(1); 1202 } 1203 } 1204 if (ref_name.getLength() > 0 && monthsNode == NULL) { 1205 of.writeParameter("monthRef", OUString::createFromAscii("ref"), i); 1206 of.writeParameter("monthRefName", ref_name, i); 1207 nbOfMonths[i] = 0; 1208 } else { 1209 if (monthsNode == NULL) 1210 monthsNode = calNode -> getChildAt(1); 1211 nbOfMonths[i] = sal::static_int_cast<sal_Int16>( monthsNode->getNumberOfChildren() ); 1212 if (bGregorian && nbOfMonths[i] != 12) 1213 incErrorInt( "A Gregorian calendar must have 12 months, this one has %d", nbOfMonths[i]); 1214 elementTag = "month"; 1215 for (j = 0; j < nbOfMonths[i]; j++) { 1216 LocaleNode *currNode = monthsNode -> getChildAt(j); 1217 OUString monthID( currNode->getChildAt(0)->getValue()); 1218 of.writeParameter("monthID", monthID, i, j); 1219 if (j == 0 && bGregorian && !monthID.equalsAscii( "jan")) 1220 incError( "First month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>"); 1221 of.writeParameter(elementTag, "DefaultAbbrvName",currNode->getChildAt(1)->getValue() ,i, j); 1222 of.writeParameter(elementTag, "DefaultFullName",currNode->getChildAt(2)->getValue() , i, j); 1223 } 1224 } 1225 1226 // Generate Era name 1227 LocaleNode * erasNode = NULL; 1228 ref_name = calNode -> getChildAt(2) ->getAttr()->getValueByName("ref"); 1229 if (ref_name.getLength() > 0 && i > 0) { 1230 for (j = 0; j < i; j++) { 1231 str = getChildAt(j)->getAttr()->getValueByName("unoid"); 1232 if (str.equals(ref_name)) 1233 erasNode = getChildAt(j)->getChildAt(2); 1234 } 1235 } 1236 if (ref_name.getLength() > 0 && erasNode == NULL) { 1237 of.writeParameter("eraRef", OUString::createFromAscii("ref"), i); 1238 of.writeParameter("eraRefName", ref_name, i); 1239 nbOfEras[i] = 0; 1240 } else { 1241 if (erasNode == NULL) 1242 erasNode = calNode -> getChildAt(2); 1243 nbOfEras[i] = sal::static_int_cast<sal_Int16>( erasNode->getNumberOfChildren() ); 1244 if (bGregorian && nbOfEras[i] != 2) 1245 incErrorInt( "A Gregorian calendar must have 2 eras, this one has %d", nbOfEras[i]); 1246 elementTag = "era"; 1247 for (j = 0; j < nbOfEras[i]; j++) { 1248 LocaleNode *currNode = erasNode -> getChildAt(j); 1249 OUString eraID( currNode->getChildAt(0)->getValue()); 1250 of.writeParameter("eraID", eraID, i, j); 1251 if (j == 0 && bGregorian && !eraID.equalsAscii( "bc")) 1252 incError( "First era of a Gregorian calendar must be <EraID>bc</EraID>"); 1253 if (j == 1 && bGregorian && !eraID.equalsAscii( "ad")) 1254 incError( "Second era of a Gregorian calendar must be <EraID>ad</EraID>"); 1255 of.writeAsciiString("\n"); 1256 of.writeParameter(elementTag, "DefaultAbbrvName",currNode->getChildAt(1)->getValue() ,i, j); 1257 of.writeParameter(elementTag, "DefaultFullName",currNode->getChildAt(2)->getValue() , i, j); 1258 } 1259 } 1260 str = calNode->getChildAt(3)->getChildAt(0)->getValue(); 1261 if (nbOfDays[i]) 1262 { 1263 for (j = 0; j < nbOfDays[i]; j++) 1264 { 1265 LocaleNode *currNode = daysNode->getChildAt(j); 1266 OUString dayID( currNode->getChildAt(0)->getValue()); 1267 if (str == dayID) 1268 break; // for 1269 } 1270 if (j >= nbOfDays[i]) 1271 incErrorStr( "<StartDayOfWeek> <DayID> must be one of the <DaysOfWeek>, but is", str); 1272 } 1273 of.writeParameter("startDayOfWeek", str, i); 1274 str = calNode ->getChildAt(4)-> getValue(); 1275 sal_Int16 nDays = sal::static_int_cast<sal_Int16>( str.toInt32() ); 1276 if (nDays < 1 || (0 < nbOfDays[i] && nbOfDays[i] < nDays)) 1277 incErrorInt( "Bad value of MinimalDaysInFirstWeek: %d, must be 1 <= value <= days_in_week", nDays); 1278 of.writeIntParameter("minimalDaysInFirstWeek", i, nDays); 1279 } 1280 if (!bHasGregorian) 1281 fprintf( stderr, "Warning: %s\n", "No Gregorian calendar defined, are you sure?"); 1282 1283 of.writeAsciiString("static const sal_Int16 calendarsCount = "); 1284 of.writeInt(nbOfCalendars); 1285 of.writeAsciiString(";\n\n"); 1286 1287 of.writeAsciiString("static const sal_Unicode nbOfDays[] = {"); 1288 for(i = 0; i < nbOfCalendars - 1; i++) { 1289 of.writeInt(nbOfDays[i]); 1290 of.writeAsciiString(", "); 1291 }; 1292 of.writeInt(nbOfDays[i]); 1293 of.writeAsciiString("};\n"); 1294 1295 of.writeAsciiString("static const sal_Unicode nbOfMonths[] = {"); 1296 for(i = 0; i < nbOfCalendars - 1; i++) { 1297 of.writeInt(nbOfMonths[i]); 1298 of.writeAsciiString(", "); 1299 }; 1300 of.writeInt(nbOfMonths[i]); 1301 of.writeAsciiString("};\n"); 1302 1303 of.writeAsciiString("static const sal_Unicode nbOfEras[] = {"); 1304 for(i = 0; i < nbOfCalendars - 1; i++) { 1305 of.writeInt(nbOfEras[i]); 1306 of.writeAsciiString(", "); 1307 }; 1308 of.writeInt(nbOfEras[i]); 1309 of.writeAsciiString("};\n"); 1310 1311 1312 of.writeAsciiString("static const sal_Unicode* calendars[] = {\n"); 1313 of.writeAsciiString("\tnbOfDays,\n"); 1314 of.writeAsciiString("\tnbOfMonths,\n"); 1315 of.writeAsciiString("\tnbOfEras,\n"); 1316 for(i = 0; i < nbOfCalendars; i++) { 1317 of.writeAsciiString("\tcalendarID"); 1318 of.writeInt(i); 1319 of.writeAsciiString(",\n"); 1320 of.writeAsciiString("\tdefaultCalendar"); 1321 of.writeInt(i); 1322 of.writeAsciiString(",\n"); 1323 if (nbOfDays[i] == 0) { 1324 of.writeAsciiString("\tdayRef"); 1325 of.writeInt(i); of.writeAsciiString(",\n"); 1326 of.writeAsciiString("\tdayRefName"); 1327 of.writeInt(i); of.writeAsciiString(",\n"); 1328 } else { 1329 for(j = 0; j < nbOfDays[i]; j++) { 1330 of.writeAsciiString("\tdayID"); 1331 of.writeInt(i); of.writeInt(j); of.writeAsciiString(",\n"); 1332 of.writeAsciiString("\tdayDefaultAbbrvName"); 1333 of.writeInt(i); of.writeInt(j); of.writeAsciiString(",\n"); 1334 of.writeAsciiString("\tdayDefaultFullName");of.writeInt(i); of.writeInt(j); of.writeAsciiString(",\n"); 1335 } 1336 } 1337 if (nbOfMonths[i] == 0) { 1338 of.writeAsciiString("\tmonthRef"); 1339 of.writeInt(i); of.writeAsciiString(",\n"); 1340 of.writeAsciiString("\tmonthRefName"); 1341 of.writeInt(i); of.writeAsciiString(",\n"); 1342 } else { 1343 for(j = 0; j < nbOfMonths[i]; j++) { 1344 of.writeAsciiString("\tmonthID");of.writeInt(i);of.writeInt(j);of.writeAsciiString(",\n"); 1345 of.writeAsciiString("\tmonthDefaultAbbrvName");of.writeInt(i);of.writeInt(j);of.writeAsciiString(",\n"); 1346 of.writeAsciiString("\tmonthDefaultFullName");of.writeInt(i);of.writeInt(j);of.writeAsciiString(",\n"); 1347 } 1348 } 1349 if (nbOfEras[i] == 0) { 1350 of.writeAsciiString("\teraRef"); 1351 of.writeInt(i); of.writeAsciiString(",\n"); 1352 of.writeAsciiString("\teraRefName"); 1353 of.writeInt(i); of.writeAsciiString(",\n"); 1354 } else { 1355 for(j = 0; j < nbOfEras[i]; j++) { 1356 of.writeAsciiString("\teraID"); of.writeInt(i); of.writeInt(j); of.writeAsciiString(",\n"); 1357 of.writeAsciiString("\teraDefaultAbbrvName");of.writeInt(i);of.writeInt(j);of.writeAsciiString(",\n"); 1358 of.writeAsciiString("\teraDefaultFullName");of.writeInt(i);of.writeInt(j);of.writeAsciiString(",\n"); 1359 } 1360 } 1361 of.writeAsciiString("\tstartDayOfWeek");of.writeInt(i); of.writeAsciiString(",\n"); 1362 of.writeAsciiString("\tminimalDaysInFirstWeek");of.writeInt(i); of.writeAsciiString(",\n"); 1363 } 1364 1365 of.writeAsciiString("};\n\n"); 1366 of.writeFunction("getAllCalendars_", "calendarsCount", "calendars"); 1367 1368 delete []nbOfDays; 1369 delete []nbOfMonths; 1370 delete []nbOfEras; 1371 } 1372 1373 bool isIso4217( const OUString& rStr ) 1374 { 1375 const sal_Unicode* p = rStr.getStr(); 1376 return rStr.getLength() == 3 1377 && 'A' <= p[0] && p[0] <= 'Z' 1378 && 'A' <= p[1] && p[1] <= 'Z' 1379 && 'A' <= p[2] && p[2] <= 'Z' 1380 ; 1381 } 1382 1383 void LCCurrencyNode :: generateCode (const OFileWriter &of) const 1384 { 1385 ::rtl::OUString useLocale = getAttr() -> getValueByName("ref"); 1386 if (useLocale.getLength() > 0) { 1387 of.writeRefFunction("getAllCurrencies_", useLocale); 1388 return; 1389 } 1390 sal_Int16 nbOfCurrencies = 0; 1391 ::rtl::OUString str; 1392 sal_Int16 i; 1393 1394 bool bTheDefault= false; 1395 bool bTheCompatible = false; 1396 for ( i = 0; i < getNumberOfChildren(); i++,nbOfCurrencies++) { 1397 LocaleNode * calNode = getChildAt (i); 1398 str = calNode->getAttr() -> getValueByName("default"); 1399 bool bDefault = of.writeDefaultParameter("Currency", str, nbOfCurrencies); 1400 str = calNode->getAttr() -> getValueByName("usedInCompatibleFormatCodes"); 1401 bool bCompatible = of.writeDefaultParameter("CurrencyUsedInCompatibleFormatCodes", str, nbOfCurrencies); 1402 str = calNode->getAttr() -> getValueByName("legacyOnly"); 1403 bool bLegacy = of.writeDefaultParameter("CurrencyLegacyOnly", str, nbOfCurrencies); 1404 if (bLegacy && (bDefault || bCompatible)) 1405 incError( "Currency: if legacyOnly==true, both 'default' and 'usedInCompatibleFormatCodes' must be false."); 1406 if (bDefault) 1407 { 1408 if (bTheDefault) 1409 incError( "Currency: more than one default currency."); 1410 bTheDefault = true; 1411 } 1412 if (bCompatible) 1413 { 1414 if (bTheCompatible) 1415 incError( "Currency: more than one currency flagged as usedInCompatibleFormatCodes."); 1416 bTheCompatible = true; 1417 } 1418 str = calNode -> findNode ("CurrencyID") -> getValue(); 1419 of.writeParameter("currencyID", str, nbOfCurrencies); 1420 // CurrencyID MUST be ISO 4217. 1421 if (!bLegacy && !isIso4217(str)) 1422 incError( "CurrencyID is not ISO 4217"); 1423 str = calNode -> findNode ("CurrencySymbol") -> getValue(); 1424 of.writeParameter("currencySymbol", str, nbOfCurrencies); 1425 str = calNode -> findNode ("BankSymbol") -> getValue(); 1426 of.writeParameter("bankSymbol", str, nbOfCurrencies); 1427 // BankSymbol currently must be ISO 4217. May change later if 1428 // application always uses CurrencyID instead of BankSymbol. 1429 if (!bLegacy && !isIso4217(str)) 1430 incError( "BankSymbol is not ISO 4217"); 1431 str = calNode -> findNode ("CurrencyName") -> getValue(); 1432 of.writeParameter("currencyName", str, nbOfCurrencies); 1433 str = calNode -> findNode ("DecimalPlaces") -> getValue(); 1434 sal_Int16 nDecimalPlaces = (sal_Int16)str.toInt32(); 1435 of.writeIntParameter("currencyDecimalPlaces", nbOfCurrencies, nDecimalPlaces); 1436 of.writeAsciiString("\n"); 1437 }; 1438 1439 if (!bTheDefault) 1440 incError( "Currency: no default currency."); 1441 if (!bTheCompatible) 1442 incError( "Currency: no currency flagged as usedInCompatibleFormatCodes."); 1443 1444 of.writeAsciiString("static const sal_Int16 currencyCount = "); 1445 of.writeInt(nbOfCurrencies); 1446 of.writeAsciiString(";\n\n"); 1447 of.writeAsciiString("static const sal_Unicode* currencies[] = {\n"); 1448 for(i = 0; i < nbOfCurrencies; i++) { 1449 of.writeAsciiString("\tcurrencyID"); 1450 of.writeInt(i); 1451 of.writeAsciiString(",\n"); 1452 of.writeAsciiString("\tcurrencySymbol"); 1453 of.writeInt(i); 1454 of.writeAsciiString(",\n"); 1455 of.writeAsciiString("\tbankSymbol"); 1456 of.writeInt(i); 1457 of.writeAsciiString(",\n"); 1458 of.writeAsciiString("\tcurrencyName"); 1459 of.writeInt(i); 1460 of.writeAsciiString(",\n"); 1461 of.writeAsciiString("\tdefaultCurrency"); 1462 of.writeInt(i); 1463 of.writeAsciiString(",\n"); 1464 of.writeAsciiString("\tdefaultCurrencyUsedInCompatibleFormatCodes"); 1465 of.writeInt(i); 1466 of.writeAsciiString(",\n"); 1467 of.writeAsciiString("\tcurrencyDecimalPlaces"); 1468 of.writeInt(i); 1469 of.writeAsciiString(",\n"); 1470 of.writeAsciiString("\tdefaultCurrencyLegacyOnly"); 1471 of.writeInt(i); 1472 of.writeAsciiString(",\n"); 1473 } 1474 of.writeAsciiString("};\n\n"); 1475 of.writeFunction("getAllCurrencies_", "currencyCount", "currencies"); 1476 } 1477 1478 void LCTransliterationNode::generateCode (const OFileWriter &of) const 1479 { 1480 ::rtl::OUString useLocale = getAttr() -> getValueByName("ref"); 1481 if (useLocale.getLength() > 0) { 1482 of.writeRefFunction("getTransliterations_", useLocale); 1483 return; 1484 } 1485 sal_Int16 nbOfModules = 0; 1486 ::rtl::OUString str; 1487 sal_Int16 i; 1488 1489 for ( i = 0; i < getNumberOfChildren(); i++,nbOfModules++) { 1490 LocaleNode * calNode = getChildAt (i); 1491 str = calNode->getAttr() -> getValueByIndex(0); 1492 of.writeParameter("Transliteration", str, nbOfModules); 1493 } 1494 of.writeAsciiString("static const sal_Int16 nbOfTransliterations = "); 1495 of.writeInt(nbOfModules); 1496 of.writeAsciiString(";\n\n"); 1497 1498 of.writeAsciiString("\nstatic const sal_Unicode* LCTransliterationsArray[] = {\n"); 1499 for( i = 0; i < nbOfModules; i++) { 1500 of.writeAsciiString("\tTransliteration"); 1501 of.writeInt(i); 1502 of.writeAsciiString(",\n"); 1503 } 1504 of.writeAsciiString("};\n\n"); 1505 of.writeFunction("getTransliterations_", "nbOfTransliterations", "LCTransliterationsArray"); 1506 } 1507 1508 struct NameValuePair { 1509 const sal_Char *name; 1510 const sal_Char *value; 1511 }; 1512 static NameValuePair ReserveWord[] = { 1513 { "trueWord", "true" }, 1514 { "falseWord", "false" }, 1515 { "quarter1Word", "1st quarter" }, 1516 { "quarter2Word", "2nd quarter" }, 1517 { "quarter3Word", "3rd quarter" }, 1518 { "quarter4Word", "4th quarter" }, 1519 { "aboveWord", "above" }, 1520 { "belowWord", "below" }, 1521 { "quarter1Abbreviation", "Q1" }, 1522 { "quarter2Abbreviation", "Q2" }, 1523 { "quarter3Abbreviation", "Q3" }, 1524 { "quarter4Abbreviation", "Q4" } 1525 }; 1526 1527 void LCMiscNode::generateCode (const OFileWriter &of) const 1528 { 1529 ::rtl::OUString useLocale = getAttr() -> getValueByName("ref"); 1530 if (useLocale.getLength() > 0) { 1531 of.writeRefFunction("getForbiddenCharacters_", useLocale); 1532 of.writeRefFunction("getBreakIteratorRules_", useLocale); 1533 of.writeRefFunction("getReservedWords_", useLocale); 1534 return; 1535 } 1536 const LocaleNode * reserveNode = findNode("ReservedWords"); 1537 if (!reserveNode) 1538 incError( "No ReservedWords element."); // should not happen if validated.. 1539 const LocaleNode * forbidNode = findNode("ForbiddenCharacters"); 1540 const LocaleNode * breakNode = findNode("BreakIteratorRules"); 1541 1542 bool bEnglishLocale = (strncmp( of.getLocale(), "en_", 3) == 0); 1543 1544 sal_Int16 nbOfWords = 0; 1545 ::rtl::OUString str; 1546 sal_Int16 i; 1547 1548 for ( i = 0; i < sal_Int16(sizeof(ReserveWord)/sizeof(ReserveWord[0])); i++,nbOfWords++) { 1549 const LocaleNode * curNode = (reserveNode ? reserveNode->findNode( 1550 ReserveWord[i].name) : 0); 1551 if (!curNode) 1552 fprintf( stderr, 1553 "Warning: No %s in ReservedWords, using en_US default: \"%s\".\n", 1554 ReserveWord[i].name, ReserveWord[i].value); 1555 str = curNode ? curNode -> getValue() : OUString::createFromAscii(ReserveWord[i].value); 1556 if (!str.getLength()) 1557 { 1558 ++nError; 1559 fprintf( stderr, "Error: No content for ReservedWords %s.\n", ReserveWord[i].name); 1560 } 1561 of.writeParameter("ReservedWord", str, nbOfWords); 1562 // "true", ..., "below" trigger untranslated warning. 1563 if (!bEnglishLocale && curNode && (0 <= i && i <= 7) && 1564 str.equalsIgnoreAsciiCaseAscii( ReserveWord[i].value)) 1565 { 1566 fprintf( stderr, 1567 "Warning: ReservedWord %s seems to be untranslated \"%s\".\n", 1568 ReserveWord[i].name, ReserveWord[i].value); 1569 } 1570 } 1571 of.writeAsciiString("static const sal_Int16 nbOfReservedWords = "); 1572 of.writeInt(nbOfWords); 1573 of.writeAsciiString(";\n\n"); 1574 of.writeAsciiString("\nstatic const sal_Unicode* LCReservedWordsArray[] = {\n"); 1575 for( i = 0; i < nbOfWords; i++) { 1576 of.writeAsciiString("\tReservedWord"); 1577 of.writeInt(i); 1578 of.writeAsciiString(",\n"); 1579 } 1580 of.writeAsciiString("};\n\n"); 1581 of.writeFunction("getReservedWords_", "nbOfReservedWords", "LCReservedWordsArray"); 1582 1583 if (forbidNode) { 1584 of.writeParameter( "forbiddenBegin", forbidNode -> getChildAt(0)->getValue()); 1585 of.writeParameter( "forbiddenEnd", forbidNode -> getChildAt(1)->getValue()); 1586 of.writeParameter( "hangingChars", forbidNode -> getChildAt(2)->getValue()); 1587 } else { 1588 of.writeParameter( "forbiddenBegin", ::rtl::OUString()); 1589 of.writeParameter( "forbiddenEnd", ::rtl::OUString()); 1590 of.writeParameter( "hangingChars", ::rtl::OUString()); 1591 } 1592 of.writeAsciiString("\nstatic const sal_Unicode* LCForbiddenCharactersArray[] = {\n"); 1593 of.writeAsciiString("\tforbiddenBegin,\n"); 1594 of.writeAsciiString("\tforbiddenEnd,\n"); 1595 of.writeAsciiString("\thangingChars\n"); 1596 of.writeAsciiString("};\n\n"); 1597 of.writeFunction("getForbiddenCharacters_", "3", "LCForbiddenCharactersArray"); 1598 1599 if (breakNode) { 1600 of.writeParameter( "EditMode", breakNode -> getChildAt(0)->getValue()); 1601 of.writeParameter( "DictionaryMode", breakNode -> getChildAt(1)->getValue()); 1602 of.writeParameter( "WordCountMode", breakNode -> getChildAt(2)->getValue()); 1603 of.writeParameter( "CharacterMode", breakNode -> getChildAt(3)->getValue()); 1604 of.writeParameter( "LineMode", breakNode -> getChildAt(4)->getValue()); 1605 } else { 1606 of.writeParameter( "EditMode", ::rtl::OUString()); 1607 of.writeParameter( "DictionaryMode", ::rtl::OUString()); 1608 of.writeParameter( "WordCountMode", ::rtl::OUString()); 1609 of.writeParameter( "CharacterMode", ::rtl::OUString()); 1610 of.writeParameter( "LineMode", ::rtl::OUString()); 1611 } 1612 of.writeAsciiString("\nstatic const sal_Unicode* LCBreakIteratorRulesArray[] = {\n"); 1613 of.writeAsciiString("\tEditMode,\n"); 1614 of.writeAsciiString("\tDictionaryMode,\n"); 1615 of.writeAsciiString("\tWordCountMode,\n"); 1616 of.writeAsciiString("\tCharacterMode,\n"); 1617 of.writeAsciiString("\tLineMode\n"); 1618 of.writeAsciiString("};\n\n"); 1619 of.writeFunction("getBreakIteratorRules_", "5", "LCBreakIteratorRulesArray"); 1620 1621 } 1622 1623 void LCNumberingLevelNode::generateCode (const OFileWriter &of) const 1624 { 1625 of.writeAsciiString("// ---> ContinuousNumbering\n"); 1626 ::rtl::OUString useLocale = getAttr() -> getValueByName("ref"); 1627 if (useLocale.getLength() > 0) { 1628 of.writeRefFunction2("getContinuousNumberingLevels_", useLocale); 1629 return; 1630 } 1631 1632 // hard code number of attributes per style. 1633 const int nAttributes = 5; 1634 const char* attr[ nAttributes ] = { "Prefix", "NumType", "Suffix", "Transliteration", "NatNum" }; 1635 1636 // record each attribute of each style in a static C++ variable. 1637 // determine number of styles on the fly. 1638 sal_Int32 nStyles = getNumberOfChildren(); 1639 sal_Int32 i; 1640 1641 for( i = 0; i < nStyles; i++ ) 1642 { 1643 const Attr* q = getChildAt( i )->getAttr(); 1644 for( sal_Int32 j=0; j<nAttributes; j++ ) 1645 { 1646 const char* name = attr[j]; 1647 OUString value = q->getValueByName( name ); 1648 of.writeParameter("continuous", name, value, sal::static_int_cast<sal_Int16>(i) ); 1649 } 1650 } 1651 1652 // record number of styles and attributes. 1653 of.writeAsciiString("static const sal_Int16 continuousNbOfStyles = "); 1654 of.writeInt( sal::static_int_cast<sal_Int16>( nStyles ) ); 1655 of.writeAsciiString(";\n\n"); 1656 of.writeAsciiString("static const sal_Int16 continuousNbOfAttributesPerStyle = "); 1657 of.writeInt( nAttributes ); 1658 of.writeAsciiString(";\n\n"); 1659 1660 // generate code. (intermediate arrays) 1661 for( i=0; i<nStyles; i++ ) 1662 { 1663 of.writeAsciiString("\nstatic const sal_Unicode* continuousStyle" ); 1664 of.writeInt( sal::static_int_cast<sal_Int16>(i) ); 1665 of.writeAsciiString("[] = {\n"); 1666 for( sal_Int32 j=0; j<nAttributes; j++) 1667 { 1668 of.writeAsciiString("\t"); 1669 of.writeAsciiString( "continuous" ); 1670 of.writeAsciiString( attr[j] ); 1671 of.writeInt(sal::static_int_cast<sal_Int16>(i)); 1672 of.writeAsciiString(",\n"); 1673 } 1674 of.writeAsciiString("\t0\n};\n\n"); 1675 } 1676 1677 // generate code. (top-level array) 1678 of.writeAsciiString("\n"); 1679 of.writeAsciiString("static const sal_Unicode** LCContinuousNumberingLevelsArray[] = {\n" ); 1680 for( i=0; i<nStyles; i++ ) 1681 { 1682 of.writeAsciiString( "\t" ); 1683 of.writeAsciiString( "continuousStyle" ); 1684 of.writeInt( sal::static_int_cast<sal_Int16>(i) ); 1685 of.writeAsciiString( ",\n"); 1686 } 1687 of.writeAsciiString("\t0\n};\n\n"); 1688 of.writeFunction2("getContinuousNumberingLevels_", "continuousNbOfStyles", 1689 "continuousNbOfAttributesPerStyle", "LCContinuousNumberingLevelsArray"); 1690 } 1691 1692 1693 void LCOutlineNumberingLevelNode::generateCode (const OFileWriter &of) const 1694 { 1695 of.writeAsciiString("// ---> OutlineNumbering\n"); 1696 ::rtl::OUString useLocale = getAttr() -> getValueByName("ref"); 1697 if (useLocale.getLength() > 0) { 1698 of.writeRefFunction3("getOutlineNumberingLevels_", useLocale); 1699 return; 1700 } 1701 1702 // hardcode number of attributes per level 1703 const int nAttributes = 11; 1704 const char* attr[ nAttributes ] = 1705 { 1706 "Prefix", 1707 "NumType", 1708 "Suffix", 1709 "BulletChar", 1710 "BulletFontName", 1711 "ParentNumbering", 1712 "LeftMargin", 1713 "SymbolTextDistance", 1714 "FirstLineOffset", 1715 "Transliteration", 1716 "NatNum", 1717 }; 1718 1719 // record each attribute of each level of each style in a static C++ variable. 1720 // determine number of styles and number of levels per style on the fly. 1721 sal_Int32 nStyles = getNumberOfChildren(); 1722 vector<sal_Int32> nLevels; // may be different for each style? 1723 for( sal_Int32 i = 0; i < nStyles; i++ ) 1724 { 1725 LocaleNode* p = getChildAt( i ); 1726 nLevels.push_back( p->getNumberOfChildren() ); 1727 for( sal_Int32 j=0; j<nLevels.back(); j++ ) 1728 { 1729 const Attr* q = p->getChildAt( j )->getAttr(); 1730 for( sal_Int32 k=0; k<nAttributes; k++ ) 1731 { 1732 const char* name = attr[k]; 1733 OUString value = q->getValueByName( name ); 1734 of.writeParameter("outline", name, value, 1735 sal::static_int_cast<sal_Int16>(i), 1736 sal::static_int_cast<sal_Int16>(j) ); 1737 } 1738 } 1739 } 1740 1741 // verify that each style has the same number of levels. 1742 for( size_t i=0; i<nLevels.size(); i++ ) 1743 { 1744 if( nLevels[0] != nLevels[i] ) 1745 { 1746 incError( "Numbering levels don't match."); 1747 } 1748 } 1749 1750 // record number of attributes, levels, and styles. 1751 of.writeAsciiString("static const sal_Int16 outlineNbOfStyles = "); 1752 of.writeInt( sal::static_int_cast<sal_Int16>( nStyles ) ); 1753 of.writeAsciiString(";\n\n"); 1754 of.writeAsciiString("static const sal_Int16 outlineNbOfLevelsPerStyle = "); 1755 of.writeInt( sal::static_int_cast<sal_Int16>( nLevels.back() ) ); 1756 of.writeAsciiString(";\n\n"); 1757 of.writeAsciiString("static const sal_Int16 outlineNbOfAttributesPerLevel = "); 1758 of.writeInt( nAttributes ); 1759 of.writeAsciiString(";\n\n"); 1760 1761 // too complicated for now... 1762 // of.writeAsciiString("static const sal_Int16 nbOfOutlineNumberingLevels[] = { "); 1763 // for( sal_Int32 j=0; j<nStyles; j++ ) 1764 // { 1765 // of.writeInt( nLevels[j] ); 1766 // of.writeAsciiString(", "); 1767 // } 1768 // of.writeAsciiString("};\n\n"); 1769 1770 1771 for( sal_Int32 i=0; i<nStyles; i++ ) 1772 { 1773 for( sal_Int32 j=0; j<nLevels.back(); j++ ) 1774 { 1775 of.writeAsciiString("static const sal_Unicode* outline"); 1776 of.writeAsciiString("Style"); 1777 of.writeInt( sal::static_int_cast<sal_Int16>(i) ); 1778 of.writeAsciiString("Level"); 1779 of.writeInt( sal::static_int_cast<sal_Int16>(j) ); 1780 of.writeAsciiString("[] = { "); 1781 1782 for( sal_Int32 k=0; k<nAttributes; k++ ) 1783 { 1784 of.writeAsciiString( "outline" ); 1785 of.writeAsciiString( attr[k] ); 1786 of.writeInt( sal::static_int_cast<sal_Int16>(i) ); 1787 of.writeInt( sal::static_int_cast<sal_Int16>(j) ); 1788 of.writeAsciiString(", "); 1789 } 1790 of.writeAsciiString("NULL };\n"); 1791 } 1792 } 1793 1794 of.writeAsciiString("\n"); 1795 1796 1797 for( sal_Int32 i=0; i<nStyles; i++ ) 1798 { 1799 of.writeAsciiString("static const sal_Unicode** outline"); 1800 of.writeAsciiString( "Style" ); 1801 of.writeInt( sal::static_int_cast<sal_Int16>(i) ); 1802 of.writeAsciiString("[] = { "); 1803 1804 for( sal_Int32 j=0; j<nLevels.back(); j++ ) 1805 { 1806 of.writeAsciiString("outlineStyle"); 1807 of.writeInt( sal::static_int_cast<sal_Int16>(i) ); 1808 of.writeAsciiString("Level"); 1809 of.writeInt( sal::static_int_cast<sal_Int16>(j) ); 1810 of.writeAsciiString(", "); 1811 } 1812 of.writeAsciiString("NULL };\n"); 1813 } 1814 of.writeAsciiString("\n"); 1815 1816 of.writeAsciiString("static const sal_Unicode*** LCOutlineNumberingLevelsArray[] = {\n" ); 1817 for( sal_Int32 i=0; i<nStyles; i++ ) 1818 { 1819 of.writeAsciiString( "\t" ); 1820 of.writeAsciiString( "outlineStyle" ); 1821 of.writeInt( sal::static_int_cast<sal_Int16>(i) ); 1822 of.writeAsciiString(",\n"); 1823 } 1824 of.writeAsciiString("\tNULL\n};\n\n"); 1825 of.writeFunction3("getOutlineNumberingLevels_", "outlineNbOfStyles", "outlineNbOfLevelsPerStyle", 1826 "outlineNbOfAttributesPerLevel", "LCOutlineNumberingLevelsArray"); 1827 } 1828 1829 Attr::Attr (const Reference< XAttributeList > & attr) { 1830 sal_Int16 len = attr->getLength(); 1831 name.realloc (len); 1832 value.realloc (len); 1833 for (sal_Int16 i =0; i< len;i++) { 1834 name[i] = attr->getNameByIndex(i); 1835 value[i] = attr -> getValueByIndex(i); 1836 } 1837 } 1838 1839 const OUString& Attr::getValueByName (const sal_Char *str) const { 1840 static OUString empty; 1841 sal_Int32 len = name.getLength(); 1842 for (sal_Int32 i = 0;i<len;i++) 1843 if (name[i].equalsAscii(str)) 1844 return value[i]; 1845 return empty; 1846 } 1847 1848 sal_Int32 Attr::getLength() const{ 1849 return name.getLength(); 1850 } 1851 1852 const OUString& Attr::getTypeByIndex (sal_Int32 idx) const { 1853 return name[idx]; 1854 } 1855 1856 const OUString& Attr::getValueByIndex (sal_Int32 idx) const 1857 { 1858 return value[idx]; 1859 } 1860