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
LocaleNode(const OUString & name,const Reference<XAttributeList> & attr)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
getError() const56 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
print() const64 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
printR() const72 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
addChild(LocaleNode * node)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
setParent(LocaleNode * node)94 void LocaleNode::setParent ( LocaleNode * node) {
95 parent = node;
96 }
97
getRoot() const98 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
findNode(const sal_Char * name) const107 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
~LocaleNode()118 LocaleNode::~LocaleNode() {
119 for (sal_Int32 i=0; i<nChildren;i++)
120 delete (children[i]);
121 }
122
createNode(const OUString & name,const Reference<XAttributeList> & attr)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
print_OUString(const OUString & s)161 static void print_OUString( const OUString& s )
162 {
163 printf( "%s", OSTR(s));
164 }
165
is_empty_string(const OUString & s)166 static bool is_empty_string( const OUString& s )
167 {
168 return (s.getLength()==0) || (s.getLength()==1 && s[0]=='\n');
169 }
170
print_indent(int depth)171 static void print_indent( int depth )
172 {
173 for( int i=0; i<depth; i++ ) printf(" ");
174 }
175
print_color(int color)176 static void print_color( int color )
177 {
178 printf("\033[%dm", color);
179 }
180
print_node(const LocaleNode * p,int depth=0)181 static 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_string( 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
generateCode(const OFileWriter & of) const231 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
writeParameterCheckLen(const OFileWriter & of,const char * pParameterName,const LocaleNode * pNode,sal_Int32 nMinLen,sal_Int32 nMaxLen) const245 ::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
writeParameterCheckLen(const OFileWriter & of,const char * pNodeName,const char * pParameterName,sal_Int32 nMinLen,sal_Int32 nMaxLen) const281 ::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
incError(const char * pStr) const299 void LocaleNode::incError( const char* pStr ) const
300 {
301 ++nError;
302 fprintf( stderr, "Error: %s\n", pStr);
303 }
304
incError(const::rtl::OUString & rStr) const305 void LocaleNode::incError( const ::rtl::OUString& rStr ) const
306 {
307 incError( OSTR( rStr));
308 }
309
prepareErrorFormat(const char * pFormat,const char * pDefaultConversion) const310 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
incErrorInt(const char * pStr,int nVal) const324 void LocaleNode::incErrorInt( const char* pStr, int nVal ) const
325 {
326 ++nError;
327 fprintf( stderr, prepareErrorFormat( pStr, ": %d"), nVal);
328 }
329
incErrorStr(const char * pStr,const::rtl::OUString & rVal) const330 void LocaleNode::incErrorStr( const char* pStr, const ::rtl::OUString& rVal ) const
331 {
332 ++nError;
333 fprintf( stderr, prepareErrorFormat( pStr, ": %s"), OSTR( rVal));
334 }
335
generateCode(const OFileWriter & of) const336 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
generateCode(const OFileWriter & of) const375 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
generateCode(const OFileWriter & of) const592 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
generateCode(const OFileWriter & of) const917 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
generateCode(const OFileWriter & of) const990 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
generateCode(const OFileWriter & of) const1028 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
generateCode(const OFileWriter & of) const1130 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
isIso4217(const OUString & rStr)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
generateCode(const OFileWriter & of) const1379 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
generateCode(const OFileWriter & of) const1474 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
generateCode(const OFileWriter & of) const1523 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
generateCode(const OFileWriter & of) const1619 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
generateCode(const OFileWriter & of) const1689 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
Attr(const Reference<XAttributeList> & attr)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
getValueByName(const sal_Char * str) const1835 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
getLength() const1844 sal_Int32 Attr::getLength() const{
1845 return name.getLength();
1846 }
1847
getTypeByIndex(sal_Int32 idx) const1848 const OUString& Attr::getTypeByIndex (sal_Int32 idx) const {
1849 return name[idx];
1850 }
1851
getValueByIndex(sal_Int32 idx) const1852 const OUString& Attr::getValueByIndex (sal_Int32 idx) const
1853 {
1854 return value[idx];
1855 }
1856