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