Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <stdio.h>
21 : #include <stdlib.h>
22 : #include <string.h>
23 : #include <iostream>
24 : #include <set>
25 : #include <vector>
26 :
27 : #include <rtl/ustrbuf.hxx>
28 : #include <sal/macros.h>
29 :
30 : #include "LocaleNode.hxx"
31 : #include <com/sun/star/i18n/NumberFormatIndex.hpp>
32 :
33 : // NOTE: MUST match the Locale versionDTD attribute defined in data/locale.dtd
34 : #define LOCALE_VERSION_DTD "2.0.3"
35 :
36 : typedef ::std::set< OUString > NameSet;
37 : typedef ::std::set< sal_Int16 > ValueSet;
38 :
39 : namespace cssi = ::com::sun::star::i18n;
40 :
41 49509 : LocaleNode::LocaleNode (const OUString& name, const Reference< XAttributeList > & attr)
42 : : aName(name)
43 : , aAttribs(attr)
44 : , parent(0)
45 : , children(0)
46 : , nChildren(0)
47 : , childArrSize(0)
48 49509 : , nError(0)
49 : {
50 49509 : }
51 :
52 49509 : int LocaleNode::getError() const
53 : {
54 49509 : int err = nError;
55 98787 : for (sal_Int32 i=0;i<nChildren;i++)
56 49278 : err += children[i]->getError();
57 49509 : return err;
58 : }
59 :
60 0 : void LocaleNode::print () const {
61 0 : printf ("<");
62 0 : OUString str (aName);
63 0 : for(sal_Int32 i = 0; i < str.getLength(); i++)
64 0 : printf( "%c", str[i]);
65 0 : printf (">\n");
66 0 : }
67 :
68 0 : void LocaleNode::printR () const {
69 0 : print();
70 0 : for (sal_Int32 i=0;i<nChildren;i++)
71 0 : children[i]->printR();
72 0 : printf ("\t");
73 0 : print();
74 0 : }
75 :
76 49278 : void LocaleNode::addChild ( LocaleNode * node) {
77 49278 : if (childArrSize <= nChildren) {
78 17626 : LocaleNode ** arrN = new LocaleNode*[childArrSize+10];
79 41416 : for (sal_Int32 i = 0; i<childArrSize; ++i)
80 23790 : arrN[i] = children[i];
81 17626 : delete [] children;
82 17626 : childArrSize += 10;
83 17626 : children = arrN;
84 : }
85 49278 : children[nChildren++] = node;
86 49278 : node->setParent (this);
87 49278 : }
88 :
89 49278 : void LocaleNode::setParent ( LocaleNode * node) {
90 49278 : parent = node;
91 49278 : }
92 :
93 468 : const LocaleNode* LocaleNode::getRoot() const
94 : {
95 468 : const LocaleNode* pRoot = 0;
96 468 : const LocaleNode* pParent = this;
97 1404 : while ( (pParent = pParent->getParent()) != 0 )
98 468 : pRoot = pParent;
99 468 : return pRoot;
100 : }
101 :
102 104662 : const LocaleNode * LocaleNode::findNode ( const sal_Char *name) const {
103 104662 : if (aName.equalsAscii(name))
104 16247 : return this;
105 149218 : for (sal_Int32 i = 0; i< nChildren; i++) {
106 80608 : const LocaleNode *n=children[i]->findNode(name);
107 80608 : if (n)
108 19805 : return n;
109 : }
110 68610 : return 0;
111 : }
112 :
113 145754 : LocaleNode::~LocaleNode()
114 : {
115 98787 : for (sal_Int32 i=0; i < nChildren; ++i)
116 49278 : delete children[i];
117 49509 : delete [] children;
118 96245 : }
119 :
120 49509 : LocaleNode* LocaleNode::createNode (const OUString& name, const Reference< XAttributeList > & attr)
121 : {
122 49509 : if ( name == "LC_INFO" )
123 231 : return new LCInfoNode (name,attr);
124 49278 : if ( name == "LC_CTYPE" )
125 231 : return new LCCTYPENode (name,attr);
126 49047 : if ( name == "LC_FORMAT" )
127 231 : return new LCFormatNode (name,attr);
128 48816 : if ( name == "LC_FORMAT_1" )
129 1 : return new LCFormatNode (name,attr);
130 48815 : if ( name == "LC_CALENDAR" )
131 231 : return new LCCalendarNode (name,attr);
132 48584 : if ( name == "LC_CURRENCY" )
133 231 : return new LCCurrencyNode (name,attr);
134 48353 : if ( name == "LC_TRANSLITERATION" )
135 231 : return new LCTransliterationNode (name,attr);
136 48122 : if ( name == "LC_COLLATION" )
137 231 : return new LCCollationNode (name,attr);
138 47891 : if ( name == "LC_INDEX" )
139 231 : return new LCIndexNode (name,attr);
140 47660 : if ( name == "LC_SEARCH" )
141 231 : return new LCSearchNode (name,attr);
142 47429 : if ( name == "LC_MISC" )
143 231 : return new LCMiscNode (name,attr);
144 47198 : if ( name == "LC_NumberingLevel" )
145 231 : return new LCNumberingLevelNode (name, attr);
146 46967 : if ( name == "LC_OutLineNumberingLevel" )
147 231 : return new LCOutlineNumberingLevelNode (name, attr);
148 :
149 46736 : return new LocaleNode(name,attr);
150 : }
151 :
152 :
153 : // printf(" name: '%s'\n", p->getName().pData->buffer );
154 : // printf("value: '%s'\n", p->getValue().pData->buffer );
155 :
156 : #define OSTR(s) (OUStringToOString( (s), RTL_TEXTENCODING_UTF8).getStr())
157 :
158 0 : void print_OUString( const OUString& s )
159 : {
160 0 : printf( "%s", OSTR(s));
161 0 : }
162 :
163 0 : bool is_empty_string( const OUString& s )
164 : {
165 0 : return s.isEmpty() || s == "\n";
166 : }
167 :
168 0 : void print_indent( int depth )
169 : {
170 0 : for( int i=0; i<depth; i++ ) printf(" ");
171 0 : }
172 :
173 0 : void print_color( int color )
174 : {
175 0 : printf("\033[%dm", color);
176 0 : }
177 :
178 0 : void print_node( const LocaleNode* p, int depth=0 )
179 : {
180 0 : if( !p ) return;
181 :
182 0 : print_indent( depth );
183 0 : printf("<");
184 0 : print_color(36);
185 0 : print_OUString( p->getName() );
186 0 : print_color(0);
187 0 : const Attr& q = p->getAttr();
188 0 : for( sal_Int32 j = 0; j < q.getLength(); ++j )
189 : {
190 0 : printf(" ");
191 0 : print_color(33);
192 0 : print_OUString( q.getTypeByIndex(j) );
193 0 : print_color(0);
194 0 : printf("=");
195 0 : print_color(31);
196 0 : printf("'");
197 0 : print_OUString( q.getValueByIndex(j) );
198 0 : printf("'");
199 0 : print_color(0);
200 : }
201 0 : printf(">");
202 0 : printf("\n");
203 0 : if( !is_empty_string( p->getValue() ) )
204 : {
205 0 : print_indent( depth+1 );
206 0 : printf("value: ");
207 0 : print_color(31);
208 0 : printf("'");
209 0 : print_OUString( p->getValue() );
210 0 : printf("'");
211 0 : print_color(0);
212 0 : printf("\n");
213 : }
214 0 : for( sal_Int32 i=0; i<p->getNumberOfChildren(); i++ )
215 : {
216 0 : print_node( p->getChildAt(i), depth+1 );
217 : }
218 0 : print_indent( depth );
219 0 : printf("</");
220 0 : print_OUString( p->getName() );
221 0 : printf(">");
222 0 : printf("\n");
223 : }
224 :
225 231 : void LocaleNode :: generateCode (const OFileWriter &of) const
226 : {
227 231 : OUString aDTD = getAttr().getValueByName("versionDTD");
228 231 : if ( aDTD != LOCALE_VERSION_DTD )
229 : {
230 0 : ++nError;
231 0 : fprintf( stderr, "Error: Locale versionDTD is not %s, see comment in locale.dtd\n", LOCALE_VERSION_DTD);
232 : }
233 3004 : for (sal_Int32 i=0; i<nChildren;i++)
234 3004 : children[i]->generateCode (of);
235 : // print_node( this );
236 231 : }
237 :
238 :
239 2268 : OUString LocaleNode::writeParameterCheckLen( const OFileWriter &of,
240 : const char* pParameterName, const LocaleNode* pNode,
241 : sal_Int32 nMinLen, sal_Int32 nMaxLen ) const
242 : {
243 2268 : OUString aVal;
244 2268 : if (pNode)
245 2268 : aVal = pNode->getValue();
246 : else
247 : {
248 0 : ++nError;
249 : fprintf( stderr, "Error: node NULL pointer for parameter %s.\n",
250 0 : pParameterName);
251 : }
252 : // write empty data if error
253 2268 : of.writeParameter( pParameterName, aVal);
254 2268 : sal_Int32 nLen = aVal.getLength();
255 2268 : if (nLen < nMinLen)
256 : {
257 0 : ++nError;
258 : fprintf( stderr, "Error: less than %ld character%s (%ld) in %s '%s'.\n",
259 : sal::static_int_cast< long >(nMinLen), (nMinLen > 1 ? "s" : ""),
260 : sal::static_int_cast< long >(nLen),
261 0 : (pNode ? OSTR( pNode->getName()) : ""),
262 0 : OSTR( aVal));
263 : }
264 2268 : else if (nLen > nMaxLen && nMaxLen >= 0)
265 : fprintf( stderr,
266 : "Warning: more than %ld character%s (%ld) in %s %s not supported by application.\n",
267 : sal::static_int_cast< long >(nMaxLen), (nMaxLen > 1 ? "s" : ""),
268 : sal::static_int_cast< long >(nLen),
269 0 : (pNode ? OSTR( pNode->getName()) : ""),
270 0 : OSTR( aVal));
271 2268 : return aVal;
272 : }
273 :
274 :
275 2268 : OUString LocaleNode::writeParameterCheckLen( const OFileWriter &of,
276 : const char* pNodeName, const char* pParameterName,
277 : sal_Int32 nMinLen, sal_Int32 nMaxLen ) const
278 : {
279 2268 : OUString aVal;
280 2268 : const LocaleNode * pNode = findNode( pNodeName);
281 2268 : if (pNode)
282 2268 : aVal = writeParameterCheckLen( of, pParameterName, pNode, nMinLen, nMaxLen);
283 : else
284 : {
285 0 : ++nError;
286 0 : fprintf( stderr, "Error: node %s not found.\n", pNodeName);
287 : // write empty data if error
288 0 : of.writeParameter( pParameterName, aVal);
289 : }
290 2268 : return aVal;
291 : }
292 :
293 0 : void LocaleNode::incError( const char* pStr ) const
294 : {
295 0 : ++nError;
296 0 : fprintf( stderr, "Error: %s\n", pStr);
297 0 : }
298 :
299 0 : void LocaleNode::incError( const OUString& rStr ) const
300 : {
301 0 : incError( OSTR( rStr));
302 0 : }
303 :
304 0 : char* LocaleNode::prepareErrorFormat( const char* pFormat, const char* pDefaultConversion ) const
305 : {
306 : static char buf[2048];
307 0 : strcpy( buf, "Error: ");
308 0 : strncat( buf, pFormat, 2000);
309 0 : char* p = buf;
310 0 : while (((p = strchr( p, '%')) != 0) && p[1] == '%')
311 0 : p += 2;
312 0 : if (!p)
313 0 : strcat( buf, pDefaultConversion);
314 0 : strcat( buf, "\n");
315 0 : return buf;
316 : }
317 :
318 0 : void LocaleNode::incErrorInt( const char* pStr, int nVal ) const
319 : {
320 0 : ++nError;
321 0 : fprintf( stderr, prepareErrorFormat( pStr, ": %d"), nVal);
322 0 : }
323 :
324 0 : void LocaleNode::incErrorStr( const char* pStr, const OUString& rVal ) const
325 : {
326 0 : ++nError;
327 0 : fprintf( stderr, prepareErrorFormat( pStr, ": %s"), OSTR( rVal));
328 0 : }
329 :
330 0 : void LocaleNode::incErrorStrStr( const char* pStr, const OUString& rVal1, const OUString& rVal2 ) const
331 : {
332 0 : ++nError;
333 0 : fprintf( stderr, prepareErrorFormat( pStr, ": %s %s"), OSTR( rVal1), OSTR( rVal2));
334 0 : }
335 :
336 231 : void LCInfoNode::generateCode (const OFileWriter &of) const
337 : {
338 :
339 231 : const LocaleNode * languageNode = findNode("Language");
340 231 : const LocaleNode * countryNode = findNode("Country");
341 231 : const LocaleNode * variantNode = findNode("Variant");
342 :
343 231 : OUString aLanguage;
344 :
345 231 : if (languageNode)
346 : {
347 231 : aLanguage = languageNode->getChildAt(0)->getValue();
348 231 : if (!(aLanguage.getLength() == 2 || aLanguage.getLength() == 3))
349 0 : incErrorStr( "langID not 2-3 characters", aLanguage);
350 231 : of.writeParameter("langID", aLanguage);
351 231 : of.writeParameter("langDefaultName", languageNode->getChildAt(1)->getValue());
352 : }
353 : else
354 0 : incError( "No Language node.");
355 231 : if (countryNode)
356 : {
357 231 : OUString aCountry( countryNode->getChildAt(0)->getValue());
358 231 : if (!(aCountry.isEmpty() || aCountry.getLength() == 2))
359 0 : incErrorStr( "countryID not empty or more than 2 characters", aCountry);
360 231 : of.writeParameter("countryID", aCountry);
361 231 : of.writeParameter("countryDefaultName", countryNode->getChildAt(1)->getValue());
362 : }
363 : else
364 0 : incError( "No Country node.");
365 231 : if (variantNode)
366 : {
367 : // If given Variant must be at least ll-Ssss and language must be 'qlt'
368 6 : OUString aVariant( variantNode->getValue());
369 6 : if (!(aVariant.isEmpty() || (aVariant.getLength() >= 7 && aVariant.indexOf('-') >= 2)))
370 0 : incErrorStr( "invalid Variant", aVariant);
371 6 : if (!(aVariant.isEmpty() || aLanguage == "qlt"))
372 0 : incErrorStrStr( "Variant '%s' given but Language '%s' is not 'qlt'", aVariant, aLanguage);
373 6 : of.writeParameter("Variant", aVariant);
374 : }
375 : else
376 225 : of.writeParameter("Variant", OUString());
377 231 : of.writeAsciiString("\nstatic const sal_Unicode* LCInfoArray[] = {\n");
378 231 : of.writeAsciiString("\tlangID,\n");
379 231 : of.writeAsciiString("\tlangDefaultName,\n");
380 231 : of.writeAsciiString("\tcountryID,\n");
381 231 : of.writeAsciiString("\tcountryDefaultName,\n");
382 231 : of.writeAsciiString("\tVariant\n");
383 231 : of.writeAsciiString("};\n\n");
384 231 : of.writeFunction("getLCInfo_", "0", "LCInfoArray");
385 231 : }
386 :
387 :
388 231 : static OUString aDateSep;
389 231 : static OUString aDecSep;
390 :
391 231 : void LCCTYPENode::generateCode (const OFileWriter &of) const
392 : {
393 231 : const LocaleNode * sepNode = 0;
394 231 : OUString useLocale = getAttr().getValueByName("ref");
395 231 : if (!useLocale.isEmpty()) {
396 42 : useLocale = useLocale.replace( '-', '_');
397 42 : of.writeRefFunction("getLocaleItem_", useLocale);
398 273 : return;
399 : }
400 378 : OUString str = getAttr().getValueByName("unoid");
401 189 : of.writeAsciiString("\n\n");
402 189 : of.writeParameter("LC_CTYPE_Unoid", str);;
403 :
404 378 : aDateSep =
405 189 : writeParameterCheckLen( of, "DateSeparator", "dateSeparator", 1, 1);
406 : OUString aThoSep =
407 378 : writeParameterCheckLen( of, "ThousandSeparator", "thousandSeparator", 1, 1);
408 378 : aDecSep =
409 189 : writeParameterCheckLen( of, "DecimalSeparator", "decimalSeparator", 1, 1);
410 : OUString aTimeSep =
411 378 : writeParameterCheckLen( of, "TimeSeparator", "timeSeparator", 1, 1);
412 : OUString aTime100Sep =
413 378 : writeParameterCheckLen( of, "Time100SecSeparator", "time100SecSeparator", 1, 1);
414 : OUString aListSep =
415 378 : writeParameterCheckLen( of, "ListSeparator", "listSeparator", 1, 1);
416 :
417 378 : OUString aLDS;
418 :
419 189 : sepNode = findNode("LongDateDayOfWeekSeparator");
420 189 : aLDS = sepNode->getValue();
421 189 : of.writeParameter("LongDateDayOfWeekSeparator", aLDS);
422 189 : if (aLDS == ",")
423 : fprintf( stderr, "Warning: %s\n",
424 0 : "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\".");
425 :
426 189 : sepNode = findNode("LongDateDaySeparator");
427 189 : aLDS = sepNode->getValue();
428 189 : of.writeParameter("LongDateDaySeparator", aLDS);
429 189 : if (aLDS == "," || aLDS == ".")
430 : fprintf( stderr, "Warning: %s\n",
431 9 : "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\".");
432 :
433 189 : sepNode = findNode("LongDateMonthSeparator");
434 189 : aLDS = sepNode->getValue();
435 189 : of.writeParameter("LongDateMonthSeparator", aLDS);
436 189 : if (aLDS.isEmpty())
437 : fprintf( stderr, "Warning: %s\n",
438 0 : "LongDateMonthSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, May9, 2007\".");
439 :
440 189 : sepNode = findNode("LongDateYearSeparator");
441 189 : aLDS = sepNode->getValue();
442 189 : of.writeParameter("LongDateYearSeparator", aLDS);
443 189 : if (aLDS.isEmpty())
444 : fprintf( stderr, "Warning: %s\n",
445 2 : "LongDateYearSeparator is empty. Usually this is not the case and may lead to concatenated display names like \"Wednesday, 2007May 9\".");
446 :
447 :
448 189 : int nSavErr = nError;
449 189 : int nWarn = 0;
450 189 : if (aDateSep == aTimeSep)
451 0 : incError( "DateSeparator equals TimeSeparator.");
452 189 : if (aDecSep == aThoSep)
453 0 : incError( "DecimalSeparator equals ThousandSeparator.");
454 189 : if ( aThoSep == " " )
455 0 : incError( "ThousandSeparator is an ' ' ordinary space, this should be a non-breaking space U+00A0 instead.");
456 189 : if (aListSep == aDecSep)
457 : fprintf( stderr, "Warning: %s\n",
458 0 : "ListSeparator equals DecimalSeparator.");
459 189 : if (aListSep == aThoSep)
460 : fprintf( stderr, "Warning: %s\n",
461 0 : "ListSeparator equals ThousandSeparator.");
462 189 : if (aListSep.getLength() != 1 || aListSep[0] != ';')
463 : {
464 0 : incError( "ListSeparator not ';' semicolon. Strongly recommended. Currently required.");
465 0 : ++nSavErr; // format codes not affected
466 : }
467 189 : if (aTimeSep == aTime100Sep)
468 : ++nWarn, fprintf( stderr, "Warning: %s\n",
469 0 : "Time100SecSeparator equals TimeSeparator, this is probably an error.");
470 189 : if (aDecSep != aTime100Sep)
471 : ++nWarn, fprintf( stderr, "Warning: %s\n",
472 7 : "Time100SecSeparator is different from DecimalSeparator, this may be correct or not. Intended?");
473 189 : if (nSavErr != nError || nWarn)
474 : fprintf( stderr, "Warning: %s\n",
475 7 : "Don't forget to adapt corresponding FormatCode elements when changing separators.");
476 :
477 : OUString aQuoteStart =
478 378 : writeParameterCheckLen( of, "QuotationStart", "quotationStart", 1, 1);
479 : OUString aQuoteEnd =
480 378 : writeParameterCheckLen( of, "QuotationEnd", "quotationEnd", 1, 1);
481 : OUString aDoubleQuoteStart =
482 378 : writeParameterCheckLen( of, "DoubleQuotationStart", "doubleQuotationStart", 1, 1);
483 : OUString aDoubleQuoteEnd =
484 378 : writeParameterCheckLen( of, "DoubleQuotationEnd", "doubleQuotationEnd", 1, 1);
485 :
486 189 : if (aQuoteStart.toChar() <= 127 && aQuoteEnd.toChar() > 127)
487 : fprintf( stderr, "Warning: %s\n",
488 0 : "QuotationStart is an ASCII character but QuotationEnd is not.");
489 189 : if (aQuoteEnd.toChar() <= 127 && aQuoteStart.toChar() > 127)
490 : fprintf( stderr, "Warning: %s\n",
491 0 : "QuotationEnd is an ASCII character but QuotationStart is not.");
492 189 : if (aDoubleQuoteStart.toChar() <= 127 && aDoubleQuoteEnd.toChar() > 127)
493 : fprintf( stderr, "Warning: %s\n",
494 2 : "DoubleQuotationStart is an ASCII character but DoubleQuotationEnd is not.");
495 189 : if (aDoubleQuoteEnd.toChar() <= 127 && aDoubleQuoteStart.toChar() > 127)
496 : fprintf( stderr, "Warning: %s\n",
497 0 : "DoubleQuotationEnd is an ASCII character but DoubleQuotationStart is not.");
498 189 : if (aQuoteStart.toChar() <= 127 && aQuoteEnd.toChar() <= 127)
499 : fprintf( stderr, "Warning: %s\n",
500 11 : "QuotationStart and QuotationEnd are both ASCII characters. Not necessarily an issue, but unusual.");
501 189 : if (aDoubleQuoteStart.toChar() <= 127 && aDoubleQuoteEnd.toChar() <= 127)
502 : fprintf( stderr, "Warning: %s\n",
503 17 : "DoubleQuotationStart and DoubleQuotationEnd are both ASCII characters. Not necessarily an issue, but unusual.");
504 189 : if (aQuoteStart == aQuoteEnd)
505 : fprintf( stderr, "Warning: %s\n",
506 20 : "QuotationStart equals QuotationEnd. Not necessarily an issue, but unusual.");
507 189 : if (aDoubleQuoteStart == aDoubleQuoteEnd)
508 : fprintf( stderr, "Warning: %s\n",
509 23 : "DoubleQuotationStart equals DoubleQuotationEnd. Not necessarily an issue, but unusual.");
510 : /* TODO: should equalness of single and double quotes be an error? Would
511 : * need to adapt quite some locales' data. */
512 189 : if (aQuoteStart == aDoubleQuoteStart)
513 : fprintf( stderr, "Warning: %s\n",
514 1 : "QuotationStart equals DoubleQuotationStart. Not necessarily an isue, but unusual.");
515 189 : if (aQuoteEnd == aDoubleQuoteEnd)
516 : fprintf( stderr, "Warning: %s\n",
517 1 : "QuotationEnd equals DoubleQuotationEnd. Not necessarily an issue, but unusual.");
518 : // Known good values, exclude ASCII single (U+0027, ') and double (U+0022, ") quotes.
519 : int ic;
520 189 : switch (ic = aQuoteStart.toChar())
521 : {
522 : case 0x2018: // LEFT SINGLE QUOTATION MARK
523 : case 0x201a: // SINGLE LOW-9 QUOTATION MARK
524 : case 0x201b: // SINGLE HIGH-REVERSED-9 QUOTATION MARK
525 : case 0x2039: // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
526 : case 0x203a: // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
527 : case 0x300c: // LEFT CORNER BRACKET (Chinese)
528 : ;
529 142 : break;
530 : default:
531 : fprintf( stderr, "Warning: %s U+%04X %s\n",
532 47 : "QuotationStart may be wrong:", ic, OSTR( aQuoteStart));
533 : }
534 189 : switch (ic = aQuoteEnd.toChar())
535 : {
536 : case 0x2019: // RIGHT SINGLE QUOTATION MARK
537 : case 0x201a: // SINGLE LOW-9 QUOTATION MARK
538 : case 0x201b: // SINGLE HIGH-REVERSED-9 QUOTATION MARK
539 : case 0x2039: // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
540 : case 0x203a: // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
541 : case 0x300d: // RIGHT CORNER BRACKET (Chinese)
542 : ;
543 137 : break;
544 : default:
545 : fprintf( stderr, "Warning: %s U+%04X %s\n",
546 52 : "QuotationEnd may be wrong:", ic, OSTR( aQuoteEnd));
547 : }
548 189 : switch (ic = aDoubleQuoteStart.toChar())
549 : {
550 : case 0x00ab: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
551 : case 0x00bb: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
552 : case 0x201c: // LEFT DOUBLE QUOTATION MARK
553 : case 0x201e: // DOUBLE LOW-9 QUOTATION MARK
554 : case 0x201f: // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
555 : case 0x300e: // LEFT WHITE CORNER BRACKET (Chinese)
556 : ;
557 154 : break;
558 : default:
559 : fprintf( stderr, "Warning: %s U+%04X %s\n",
560 35 : "DoubleQuotationStart may be wrong:", ic, OSTR( aDoubleQuoteStart));
561 : }
562 189 : switch (ic = aDoubleQuoteEnd.toChar())
563 : {
564 : case 0x00ab: // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
565 : case 0x00bb: // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
566 : case 0x201d: // RIGHT DOUBLE QUOTATION MARK
567 : case 0x201e: // DOUBLE LOW-9 QUOTATION MARK
568 : case 0x201f: // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
569 : case 0x300f: // RIGHT WHITE CORNER BRACKET (Chinese)
570 : ;
571 144 : break;
572 : default:
573 : fprintf( stderr, "Warning: %s U+%04X %s\n",
574 45 : "DoubleQuotationEnd may be wrong:", ic, OSTR( aDoubleQuoteEnd));
575 : }
576 :
577 189 : writeParameterCheckLen( of, "TimeAM", "timeAM", 1, -1);
578 189 : writeParameterCheckLen( of, "TimePM", "timePM", 1, -1);
579 189 : sepNode = findNode("MeasurementSystem");
580 189 : of.writeParameter("measurementSystem", sepNode->getValue());
581 :
582 189 : of.writeAsciiString("\nstatic const sal_Unicode* LCType[] = {\n");
583 189 : of.writeAsciiString("\tLC_CTYPE_Unoid,\n");
584 189 : of.writeAsciiString("\tdateSeparator,\n");
585 189 : of.writeAsciiString("\tthousandSeparator,\n");
586 189 : of.writeAsciiString("\tdecimalSeparator,\n");
587 189 : of.writeAsciiString("\ttimeSeparator,\n");
588 189 : of.writeAsciiString("\ttime100SecSeparator,\n");
589 189 : of.writeAsciiString("\tlistSeparator,\n");
590 189 : of.writeAsciiString("\tquotationStart,\n");
591 189 : of.writeAsciiString("\tquotationEnd,\n");
592 189 : of.writeAsciiString("\tdoubleQuotationStart,\n");
593 189 : of.writeAsciiString("\tdoubleQuotationEnd,\n");
594 189 : of.writeAsciiString("\ttimeAM,\n");
595 189 : of.writeAsciiString("\ttimePM,\n");
596 189 : of.writeAsciiString("\tmeasurementSystem,\n");
597 189 : of.writeAsciiString("\tLongDateDayOfWeekSeparator,\n");
598 189 : of.writeAsciiString("\tLongDateDaySeparator,\n");
599 189 : of.writeAsciiString("\tLongDateMonthSeparator,\n");
600 189 : of.writeAsciiString("\tLongDateYearSeparator\n");
601 189 : of.writeAsciiString("};\n\n");
602 378 : of.writeFunction("getLocaleItem_", "0", "LCType");
603 : }
604 :
605 :
606 231 : static OUString sTheCurrencyReplaceTo;
607 231 : static OUString sTheCompatibleCurrency;
608 231 : static OUString sTheDateEditFormat;
609 :
610 : sal_Int16 LCFormatNode::mnSection = 0;
611 : sal_Int16 LCFormatNode::mnFormats = 0;
612 :
613 232 : void LCFormatNode::generateCode (const OFileWriter &of) const
614 : {
615 232 : if (mnSection >= 2)
616 0 : incError("more than 2 LC_FORMAT sections");
617 :
618 232 : ::std::vector< OUString > theDateAcceptancePatterns;
619 :
620 389 : OUString useLocale(getAttr().getValueByName("ref"));
621 :
622 389 : OUString str;
623 389 : OUString strFrom( getAttr().getValueByName("replaceFrom"));
624 232 : if (useLocale.isEmpty())
625 : {
626 157 : of.writeParameter("replaceFrom", strFrom, mnSection);
627 : }
628 232 : str = getAttr().getValueByName("replaceTo");
629 232 : if (!strFrom.isEmpty() && str.isEmpty())
630 0 : incErrorStr("replaceFrom=\"%s\" replaceTo=\"\" is empty replacement.", strFrom);
631 : // Locale data generator inserts FFFF for LangID, we need to adapt that.
632 232 : if (str.endsWithIgnoreAsciiCase( "-FFFF]"))
633 0 : incErrorStr("replaceTo=\"%s\" needs FFFF to be adapted to the real LangID value.", str);
634 232 : of.writeParameter("replaceTo", str, mnSection);
635 : // Remember the replaceTo value for "[CURRENCY]" to check format codes.
636 232 : if ( strFrom == "[CURRENCY]" )
637 131 : sTheCurrencyReplaceTo = str;
638 : // Remember the currency symbol if present.
639 232 : if (str.startsWith( "[$" ))
640 : {
641 174 : sal_Int32 nHyphen = str.indexOf( '-');
642 174 : if (nHyphen >= 3)
643 : {
644 174 : sTheCompatibleCurrency = str.copy( 2, nHyphen - 2);
645 : }
646 : }
647 :
648 232 : if (!useLocale.isEmpty())
649 : {
650 75 : if (!strFrom.isEmpty() && strFrom != "[CURRENCY]") //???
651 : {
652 : incErrorStrStr(
653 : "non-empty replaceFrom=\"%s\" with non-empty ref=\"%s\".",
654 0 : strFrom, useLocale);
655 : }
656 75 : useLocale = useLocale.replace( '-', '_');
657 75 : switch (mnSection)
658 : {
659 : case 0:
660 75 : of.writeRefFunction("getAllFormats0_", useLocale, "replaceTo0");
661 75 : break;
662 : case 1:
663 0 : of.writeRefFunction("getAllFormats1_", useLocale, "replaceTo1");
664 0 : break;
665 : }
666 75 : of.writeRefFunction("getDateAcceptancePatterns_", useLocale);
667 307 : return;
668 : }
669 :
670 157 : sal_Int16 formatCount = mnFormats;
671 157 : NameSet aMsgIdSet;
672 314 : ValueSet aFormatIndexSet;
673 314 : NameSet aDefaultsSet;
674 157 : bool bCtypeIsRef = false;
675 :
676 7830 : for (sal_Int16 i = 0; i< getNumberOfChildren() ; i++, formatCount++)
677 : {
678 7673 : LocaleNode * currNode = getChildAt (i);
679 7673 : if ( currNode->getName() == "DateAcceptancePattern" )
680 : {
681 224 : if (mnSection > 0)
682 0 : incError( "DateAcceptancePattern only handled in LC_FORMAT, not LC_FORMAT_1");
683 : else
684 224 : theDateAcceptancePatterns.push_back( currNode->getValue());
685 224 : --formatCount;
686 448 : continue; // for
687 : }
688 7449 : if ( currNode->getName() != "FormatElement" )
689 : {
690 0 : incErrorStr( "Undefined element in LC_FORMAT", currNode->getName());
691 0 : --formatCount;
692 0 : continue; // for
693 : }
694 :
695 7449 : OUString aUsage;
696 14898 : OUString aType;
697 14898 : OUString aFormatIndex;
698 : // currNode -> print();
699 7449 : const Attr &currNodeAttr = currNode->getAttr();
700 : //printf ("getLen() = %d\n", currNode->getAttr().getLength());
701 :
702 7449 : str = currNodeAttr.getValueByName("msgid");
703 7449 : if (!aMsgIdSet.insert( str).second)
704 0 : incErrorStr( "Duplicated msgid=\"%s\" in FormatElement.", str);
705 7449 : of.writeParameter("FormatKey", str, formatCount);
706 :
707 7449 : str = currNodeAttr.getValueByName("default");
708 7449 : bool bDefault = str == "true";
709 7449 : of.writeDefaultParameter("FormatElement", str, formatCount);
710 :
711 7449 : aType = currNodeAttr.getValueByName("type");
712 7449 : of.writeParameter("FormatType", aType, formatCount);
713 :
714 7449 : aUsage = currNodeAttr.getValueByName("usage");
715 7449 : of.writeParameter("FormatUsage", aUsage, formatCount);
716 :
717 7449 : aFormatIndex = currNodeAttr.getValueByName("formatindex");
718 7449 : sal_Int16 formatindex = (sal_Int16)aFormatIndex.toInt32();
719 7449 : if (!aFormatIndexSet.insert( formatindex).second)
720 0 : incErrorInt( "Duplicated formatindex=\"%d\" in FormatElement.", formatindex);
721 7449 : of.writeIntParameter("Formatindex", formatCount, formatindex);
722 :
723 : // Ensure only one default per usage and type.
724 7449 : if (bDefault)
725 : {
726 2030 : OUString aKey( aUsage + OUString( ',') + aType);
727 2030 : if (!aDefaultsSet.insert( aKey).second)
728 : {
729 0 : OUString aStr( "Duplicated default for usage=\"");
730 0 : aStr += aUsage;
731 0 : aStr += "\" type=\"";
732 0 : aStr += aType;
733 0 : aStr += "\": formatindex=\"";
734 0 : aStr += aFormatIndex;
735 0 : aStr += "\".";
736 0 : incError( aStr);
737 2030 : }
738 : }
739 :
740 7449 : const LocaleNode * n = currNode -> findNode("FormatCode");
741 7449 : if (n)
742 : {
743 7449 : of.writeParameter("FormatCode", n->getValue(), formatCount);
744 : // Check separator usage for some FormatCode elements.
745 7449 : const LocaleNode* pCtype = 0;
746 7449 : switch (formatindex)
747 : {
748 : case cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY :
749 156 : sTheDateEditFormat = n->getValue();
750 156 : break;
751 : case cssi::NumberFormatIndex::NUMBER_1000DEC2 : // #,##0.00
752 : case cssi::NumberFormatIndex::TIME_MMSS00 : // MM:SS.00
753 : case cssi::NumberFormatIndex::TIME_HH_MMSS00 : // [HH]:MM:SS.00
754 : {
755 468 : const LocaleNode* pRoot = getRoot();
756 468 : if (!pRoot)
757 0 : incError( "No root for FormatCode.");
758 : else
759 : {
760 468 : pCtype = pRoot->findNode( "LC_CTYPE");
761 468 : if (!pCtype)
762 0 : incError( "No LC_CTYPE found for FormatCode.");
763 : else
764 : {
765 468 : OUString aRef( pCtype->getAttr().getValueByName("ref"));
766 468 : if (!aRef.isEmpty())
767 : {
768 12 : aRef = aRef.replace( '-', '_');
769 12 : if (!bCtypeIsRef)
770 : fprintf( stderr,
771 : "Warning: Can't check separators used in FormatCode due to LC_CTYPE ref=\"%s\".\n"
772 : "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",
773 4 : OSTR( aRef));
774 12 : bCtypeIsRef = true;
775 12 : pCtype = 0;
776 468 : }
777 : }
778 : }
779 : }
780 468 : break;
781 : case cssi::NumberFormatIndex::CURRENCY_1000DEC2 :
782 : // Remember the currency symbol if present.
783 : {
784 : sal_Int32 nStart;
785 213 : if (sTheCompatibleCurrency.isEmpty() &&
786 57 : ((nStart = n->getValue().indexOfAsciiL( "[$", 2)) >= 0))
787 : {
788 57 : OUString aCode( n->getValue());
789 57 : sal_Int32 nHyphen = aCode.indexOf( '-', nStart);
790 57 : if (nHyphen >= nStart + 3)
791 57 : sTheCompatibleCurrency = aCode.copy( nStart + 2, nHyphen - nStart - 2);
792 : }
793 : }
794 : // fallthru
795 : case cssi::NumberFormatIndex::CURRENCY_1000INT :
796 : case cssi::NumberFormatIndex::CURRENCY_1000INT_RED :
797 : case cssi::NumberFormatIndex::CURRENCY_1000DEC2_RED :
798 : case cssi::NumberFormatIndex::CURRENCY_1000DEC2_CCC :
799 : case cssi::NumberFormatIndex::CURRENCY_1000DEC2_DASHED :
800 : // Currency formats should be something like [C]###0;-[C]###0
801 : // and not parenthesized [C]###0;([C]###0) if not en_US.
802 936 : if (strcmp( of.getLocale(), "en_US") != 0)
803 : {
804 930 : OUString aCode( n->getValue());
805 1860 : OUString aPar1( "0)");
806 1860 : OUString aPar2( "-)" );
807 1860 : OUString aPar3( " )" );
808 1860 : OUString aPar4( "])" );
809 3638 : if (aCode.indexOf( aPar1 ) > 0 || aCode.indexOf( aPar2 ) > 0 ||
810 2700 : aCode.indexOf( aPar3 ) > 0 || aCode.indexOf( aPar4 ) > 0)
811 975 : 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);
812 : }
813 : // Check if we have replaceTo for "[CURRENCY]" placeholder.
814 936 : if (sTheCurrencyReplaceTo.isEmpty())
815 : {
816 342 : OUString aCode( n->getValue());
817 342 : if (aCode.indexOf( "[CURRENCY]" ) >= 0)
818 0 : incErrorInt( "[CURRENCY] replaceTo not found for formatindex=\"%d\".", formatindex);
819 : }
820 936 : break;
821 : }
822 7449 : if (pCtype)
823 : {
824 456 : int nSavErr = nError;
825 456 : OUString aCode( n->getValue());
826 456 : if (formatindex == cssi::NumberFormatIndex::NUMBER_1000DEC2)
827 : {
828 152 : sal_Int32 nDec = -1;
829 152 : sal_Int32 nGrp = -1;
830 152 : const LocaleNode* pSep = pCtype->findNode( "DecimalSeparator");
831 152 : if (!pSep)
832 0 : incError( "No DecimalSeparator found for FormatCode.");
833 : else
834 : {
835 152 : nDec = aCode.indexOf( pSep->getValue());
836 152 : if (nDec < 0)
837 : incErrorInt( "DecimalSeparator not present in FormatCode formatindex=\"%d\".",
838 0 : formatindex);
839 : }
840 152 : pSep = pCtype->findNode( "ThousandSeparator");
841 152 : if (!pSep)
842 0 : incError( "No ThousandSeparator found for FormatCode.");
843 : else
844 : {
845 152 : nGrp = aCode.indexOf( pSep->getValue());
846 152 : if (nGrp < 0)
847 : incErrorInt( "ThousandSeparator not present in FormatCode formatindex=\"%d\".",
848 0 : formatindex);
849 : }
850 152 : if (nDec >= 0 && nGrp >= 0 && nDec <= nGrp)
851 : incErrorInt( "Ordering of ThousandSeparator and DecimalSeparator not correct in formatindex=\"%d\".",
852 0 : formatindex);
853 : }
854 760 : if (formatindex == cssi::NumberFormatIndex::TIME_MMSS00 ||
855 304 : formatindex == cssi::NumberFormatIndex::TIME_HH_MMSS00)
856 : {
857 304 : sal_Int32 nTime = -1;
858 304 : sal_Int32 n100s = -1;
859 304 : const LocaleNode* pSep = pCtype->findNode( "TimeSeparator");
860 304 : if (!pSep)
861 0 : incError( "No TimeSeparator found for FormatCode.");
862 : else
863 : {
864 304 : nTime = aCode.indexOf( pSep->getValue());
865 304 : if (nTime < 0)
866 : incErrorInt( "TimeSeparator not present in FormatCode formatindex=\"%d\".",
867 0 : formatindex);
868 : }
869 304 : pSep = pCtype->findNode( "Time100SecSeparator");
870 304 : if (!pSep)
871 0 : incError( "No Time100SecSeparator found for FormatCode.");
872 : else
873 : {
874 304 : n100s = aCode.indexOf( pSep->getValue());
875 304 : if (n100s < 0)
876 : incErrorInt( "Time100SecSeparator not present in FormatCode formatindex=\"%d\".",
877 0 : formatindex);
878 304 : OUStringBuffer a100s( pSep->getValue());
879 304 : a100s.appendAscii( "00");
880 304 : n100s = aCode.indexOf( a100s.makeStringAndClear());
881 304 : if (n100s < 0)
882 : incErrorInt( "Time100SecSeparator+00 not present in FormatCode formatindex=\"%d\".",
883 0 : formatindex);
884 : }
885 304 : if (n100s >= 0 && nTime >= 0 && n100s <= nTime)
886 : incErrorInt( "Ordering of Time100SecSeparator and TimeSeparator not correct in formatindex=\"%d\".",
887 0 : formatindex);
888 : }
889 456 : if (nSavErr != nError)
890 : fprintf( stderr,
891 : "Warning: formatindex=\"%d\",\"%d\",\"%d\" are the only FormatCode elements checked for separator usage, there may be others that have errors.\n",
892 : int(cssi::NumberFormatIndex::NUMBER_1000DEC2),
893 : int(cssi::NumberFormatIndex::TIME_MMSS00),
894 0 : int(cssi::NumberFormatIndex::TIME_HH_MMSS00));
895 :
896 : }
897 : }
898 : else
899 0 : incError( "No FormatCode in FormatElement.");
900 7449 : n = currNode -> findNode("DefaultName");
901 7449 : if (n)
902 175 : of.writeParameter("FormatDefaultName", n->getValue(), formatCount);
903 : else
904 7274 : of.writeParameter("FormatDefaultName", OUString(), formatCount);
905 :
906 7449 : }
907 :
908 : // Check presence of all required format codes only in first section
909 : // LC_FORMAT, not in optional LC_FORMAT_1
910 157 : if (mnSection == 0)
911 : {
912 : // 0..47 MUST be present, 48,49 MUST NOT be present
913 156 : ValueSet::const_iterator aIter( aFormatIndexSet.begin());
914 7488 : for (sal_Int16 nNext = cssi::NumberFormatIndex::NUMBER_START;
915 : nNext < cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES; ++nNext)
916 : {
917 14664 : sal_Int16 nHere = ::std::min( ((aIter != aFormatIndexSet.end() ? *aIter :
918 : cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES)),
919 7332 : cssi::NumberFormatIndex::INDEX_TABLE_ENTRIES);
920 7332 : if (aIter != aFormatIndexSet.end()) ++aIter;
921 7956 : for ( ; nNext < nHere; ++nNext)
922 : {
923 624 : switch (nNext)
924 : {
925 : case cssi::NumberFormatIndex::FRACTION_1 :
926 : case cssi::NumberFormatIndex::FRACTION_2 :
927 : case cssi::NumberFormatIndex::BOOLEAN :
928 : case cssi::NumberFormatIndex::TEXT :
929 : // generated internally
930 624 : break;
931 : default:
932 0 : incErrorInt( "FormatElement formatindex=\"%d\" not present.", nNext);
933 : }
934 : }
935 7332 : switch (nHere)
936 : {
937 : case cssi::NumberFormatIndex::BOOLEAN :
938 0 : incErrorInt( "FormatElement formatindex=\"%d\" reserved for internal ``BOOLEAN''.", nNext);
939 0 : break;
940 : case cssi::NumberFormatIndex::TEXT :
941 0 : incErrorInt( "FormatElement formatindex=\"%d\" reserved for internal ``@'' (TEXT).", nNext);
942 0 : break;
943 : default:
944 : ; // nothing
945 : }
946 : }
947 : }
948 :
949 157 : of.writeAsciiString("\nstatic const sal_Int16 ");
950 157 : of.writeAsciiString("FormatElementsCount");
951 157 : of.writeInt(mnSection);
952 157 : of.writeAsciiString(" = ");
953 157 : of.writeInt( formatCount - mnFormats);
954 157 : of.writeAsciiString(";\n");
955 157 : of.writeAsciiString("static const sal_Unicode* ");
956 157 : of.writeAsciiString("FormatElementsArray");
957 157 : of.writeInt(mnSection);
958 157 : of.writeAsciiString("[] = {\n");
959 7606 : for(sal_Int16 i = mnFormats; i < formatCount; i++) {
960 :
961 7449 : of.writeAsciiString("\t");
962 7449 : of.writeAsciiString("FormatCode");
963 7449 : of.writeInt(i);
964 7449 : of.writeAsciiString(",\n");
965 :
966 7449 : of.writeAsciiString("\t");
967 7449 : of.writeAsciiString("FormatDefaultName");
968 7449 : of.writeInt(i);
969 7449 : of.writeAsciiString(",\n");
970 :
971 7449 : of.writeAsciiString("\t");
972 7449 : of.writeAsciiString("FormatKey");
973 7449 : of.writeInt(i);
974 7449 : of.writeAsciiString(",\n");
975 :
976 7449 : of.writeAsciiString("\t");
977 7449 : of.writeAsciiString("FormatType");
978 7449 : of.writeInt(i);
979 7449 : of.writeAsciiString(",\n");
980 :
981 7449 : of.writeAsciiString("\t");
982 7449 : of.writeAsciiString("FormatUsage");
983 7449 : of.writeInt(i);
984 7449 : of.writeAsciiString(",\n");
985 :
986 7449 : of.writeAsciiString("\t");
987 7449 : of.writeAsciiString("Formatindex");
988 7449 : of.writeInt(i);
989 7449 : of.writeAsciiString(",\n");
990 :
991 :
992 7449 : of.writeAsciiString("\tdefaultFormatElement");
993 7449 : of.writeInt(i);
994 7449 : of.writeAsciiString(",\n");
995 : }
996 157 : of.writeAsciiString("};\n\n");
997 :
998 157 : switch (mnSection)
999 : {
1000 : case 0:
1001 156 : of.writeFunction("getAllFormats0_", "FormatElementsCount0", "FormatElementsArray0", "replaceFrom0", "replaceTo0");
1002 156 : break;
1003 : case 1:
1004 1 : of.writeFunction("getAllFormats1_", "FormatElementsCount1", "FormatElementsArray1", "replaceFrom1", "replaceTo1");
1005 1 : break;
1006 : }
1007 :
1008 157 : mnFormats = mnFormats + formatCount;
1009 :
1010 157 : if (mnSection == 0)
1011 : {
1012 : // Extract and add date acceptance pattern for full date, so we provide
1013 : // at least one valid pattern, even if the number parser doesn't need
1014 : // that one.
1015 : /* XXX NOTE: only simple [...] modifier and "..." quotes detected and
1016 : * ignored, not nested, no fancy stuff. */
1017 156 : sal_Int32 nIndex = 0;
1018 : // aDateSep can be empty if LC_CTYPE was a ref=..., determine from
1019 : // FormatCode then.
1020 156 : sal_uInt32 cDateSep = (aDateSep.isEmpty() ? 0 : aDateSep.iterateCodePoints( &nIndex));
1021 156 : sal_uInt32 cDateSep2 = cDateSep;
1022 156 : nIndex = 0;
1023 156 : OUStringBuffer aPatternBuf(5);
1024 312 : OUStringBuffer aPatternBuf2(5);
1025 156 : sal_uInt8 nDetected = 0; // bits Y,M,D
1026 156 : bool bInModifier = false;
1027 156 : bool bQuoted = false;
1028 1511 : while (nIndex < sTheDateEditFormat.getLength() && nDetected < 7)
1029 : {
1030 1199 : sal_uInt32 cChar = sTheDateEditFormat.iterateCodePoints( &nIndex);
1031 1199 : if (bInModifier)
1032 : {
1033 49 : if (cChar == ']')
1034 6 : bInModifier = false;
1035 49 : continue; // while
1036 : }
1037 1150 : if (bQuoted)
1038 : {
1039 0 : if (cChar == '"')
1040 0 : bQuoted = false;
1041 0 : continue; // while
1042 : }
1043 1150 : switch (cChar)
1044 : {
1045 : case 'Y':
1046 : case 'y':
1047 215 : if (!(nDetected & 4))
1048 : {
1049 128 : aPatternBuf.append( 'Y');
1050 128 : if (!aPatternBuf2.isEmpty())
1051 0 : aPatternBuf2.append( 'Y');
1052 128 : nDetected |= 4;
1053 : }
1054 215 : break;
1055 : case 'M':
1056 : case 'm':
1057 304 : if (!(nDetected & 2))
1058 : {
1059 155 : aPatternBuf.append( 'M');
1060 155 : if (!aPatternBuf2.isEmpty())
1061 1 : aPatternBuf2.append( 'M');
1062 155 : nDetected |= 2;
1063 : }
1064 304 : break;
1065 : case 'D':
1066 : case 'd':
1067 253 : if (!(nDetected & 1))
1068 : {
1069 143 : aPatternBuf.append( 'D');
1070 143 : if (!aPatternBuf2.isEmpty())
1071 1 : aPatternBuf2.append( 'D');
1072 143 : nDetected |= 1;
1073 : }
1074 253 : break;
1075 : case '[':
1076 6 : bInModifier = true;
1077 6 : break;
1078 : case '"':
1079 0 : bQuoted = true;
1080 0 : break;
1081 : case '\\':
1082 0 : cChar = sTheDateEditFormat.iterateCodePoints( &nIndex);
1083 0 : break;
1084 : case '-':
1085 : case '.':
1086 : case '/':
1087 : // There are locales that use an ISO 8601 edit format
1088 : // regardless of what the date separator or other formats
1089 : // say, for example hu-HU. Generalize this for all cases
1090 : // where the used separator differs and is one of the known
1091 : // separators and generate a second pattern with the
1092 : // format's separator at the current position.
1093 310 : cDateSep2 = cChar;
1094 : // fallthru
1095 : default:
1096 314 : if (!cDateSep)
1097 4 : cDateSep = cChar;
1098 314 : if (!cDateSep2)
1099 0 : cDateSep2 = cChar;
1100 314 : if (cDateSep != cDateSep2 && aPatternBuf2.isEmpty())
1101 1 : aPatternBuf2 = aPatternBuf;
1102 314 : if (cChar == cDateSep || cChar == cDateSep2)
1103 312 : aPatternBuf.append( OUString( &cDateSep, 1)); // always the defined separator
1104 314 : if (cChar == cDateSep2 && !aPatternBuf2.isEmpty())
1105 2 : aPatternBuf2.append( OUString( &cDateSep2, 1)); // always the format's separator
1106 314 : break;
1107 : // The localized legacy:
1108 : case 'A':
1109 23 : if (((nDetected & 7) == 3) || ((nDetected & 7) == 0))
1110 : {
1111 : // es DD/MM/AAAA
1112 : // fr JJ.MM.AAAA
1113 : // it GG/MM/AAAA
1114 : // fr_CA AAAA-MM-JJ
1115 20 : aPatternBuf.append( 'Y');
1116 20 : if (!aPatternBuf2.isEmpty())
1117 0 : aPatternBuf2.append( 'Y');
1118 20 : nDetected |= 4;
1119 : }
1120 23 : break;
1121 : case 'J':
1122 16 : if (((nDetected & 7) == 0) || ((nDetected & 7) == 6))
1123 : {
1124 : // fr JJ.MM.AAAA
1125 : // fr_CA AAAA-MM-JJ
1126 5 : aPatternBuf.append( 'D');
1127 5 : if (!aPatternBuf2.isEmpty())
1128 0 : aPatternBuf2.append( 'D');
1129 5 : nDetected |= 1;
1130 : }
1131 11 : else if ((nDetected & 7) == 3)
1132 : {
1133 : // nl DD-MM-JJJJ
1134 : // de TT.MM.JJJJ
1135 7 : aPatternBuf.append( 'Y');
1136 7 : if (!aPatternBuf2.isEmpty())
1137 0 : aPatternBuf2.append( 'Y');
1138 7 : nDetected |= 4;
1139 : }
1140 16 : break;
1141 : case 'T':
1142 10 : if ((nDetected & 7) == 0)
1143 : {
1144 : // de TT.MM.JJJJ
1145 5 : aPatternBuf.append( 'D');
1146 5 : if (!aPatternBuf2.isEmpty())
1147 0 : aPatternBuf2.append( 'D');
1148 5 : nDetected |= 1;
1149 : }
1150 10 : break;
1151 : case 'G':
1152 4 : if ((nDetected & 7) == 0)
1153 : {
1154 : // it GG/MM/AAAA
1155 2 : aPatternBuf.append( 'D');
1156 2 : if (!aPatternBuf2.isEmpty())
1157 0 : aPatternBuf2.append( 'D');
1158 2 : nDetected |= 1;
1159 : }
1160 4 : break;
1161 : case 'P':
1162 2 : if ((nDetected & 7) == 0)
1163 : {
1164 : // fi PP.KK.VVVV
1165 1 : aPatternBuf.append( 'D');
1166 1 : if (!aPatternBuf2.isEmpty())
1167 0 : aPatternBuf2.append( 'D');
1168 1 : nDetected |= 1;
1169 : }
1170 2 : break;
1171 : case 'K':
1172 2 : if ((nDetected & 7) == 1)
1173 : {
1174 : // fi PP.KK.VVVV
1175 1 : aPatternBuf.append( 'M');
1176 1 : if (!aPatternBuf2.isEmpty())
1177 0 : aPatternBuf2.append( 'M');
1178 1 : nDetected |= 2;
1179 : }
1180 2 : break;
1181 : case 'V':
1182 1 : if ((nDetected & 7) == 3)
1183 : {
1184 : // fi PP.KK.VVVV
1185 1 : aPatternBuf.append( 'Y');
1186 1 : if (!aPatternBuf2.isEmpty())
1187 0 : aPatternBuf2.append( 'Y');
1188 1 : nDetected |= 4;
1189 : }
1190 1 : break;
1191 : }
1192 : }
1193 156 : OUString aPattern( aPatternBuf.makeStringAndClear());
1194 156 : if (((nDetected & 7) != 7) || aPattern.getLength() < 5)
1195 : {
1196 0 : incErrorStr( "failed to extract full date acceptance pattern", aPattern);
1197 : fprintf( stderr, " with DateSeparator '%s' from FormatCode '%s' (formatindex=\"%d\")\n",
1198 : OSTR( OUString( cDateSep)), OSTR( sTheDateEditFormat),
1199 0 : (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY);
1200 : }
1201 : else
1202 : {
1203 : fprintf( stderr, "Generated date acceptance pattern: '%s' from '%s' (formatindex=\"%d\" and defined DateSeparator '%s')\n",
1204 : OSTR( aPattern), OSTR( sTheDateEditFormat),
1205 : (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY,
1206 156 : OSTR( OUString( cDateSep)));
1207 : // Insert at front so full date pattern is first in checks.
1208 156 : theDateAcceptancePatterns.insert( theDateAcceptancePatterns.begin(), aPattern);
1209 : }
1210 156 : if (!aPatternBuf2.isEmpty())
1211 : {
1212 1 : OUString aPattern2( aPatternBuf2.makeStringAndClear());
1213 1 : if (aPattern2.getLength() < 5)
1214 : {
1215 0 : incErrorStr( "failed to extract 2nd date acceptance pattern", aPattern2);
1216 : fprintf( stderr, " with DateSeparator '%s' from FormatCode '%s' (formatindex=\"%d\")\n",
1217 : OSTR( OUString( cDateSep2)), OSTR( sTheDateEditFormat),
1218 0 : (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY);
1219 : }
1220 : else
1221 : {
1222 : fprintf( stderr, "Generated 2nd acceptance pattern: '%s' from '%s' (formatindex=\"%d\")\n",
1223 : OSTR( aPattern2), OSTR( sTheDateEditFormat),
1224 1 : (int)cssi::NumberFormatIndex::DATE_SYS_DDMMYYYY);
1225 1 : theDateAcceptancePatterns.insert( theDateAcceptancePatterns.begin(), aPattern2);
1226 1 : }
1227 : }
1228 :
1229 : // Rudimentary check if a pattern interferes with decimal number.
1230 : // But only if not inherited in which case we don't have aDecSep here.
1231 156 : if (!aDecSep.isEmpty())
1232 : {
1233 152 : nIndex = 0;
1234 152 : sal_uInt32 cDecSep = aDecSep.iterateCodePoints( &nIndex);
1235 1575 : for (vector<OUString>::const_iterator aIt = theDateAcceptancePatterns.begin();
1236 1050 : aIt != theDateAcceptancePatterns.end(); ++aIt)
1237 : {
1238 373 : if ((*aIt).getLength() == (cDecSep <= 0xffff ? 3 : 4))
1239 : {
1240 149 : nIndex = 1;
1241 149 : if ((*aIt).iterateCodePoints( &nIndex) == cDecSep)
1242 : {
1243 0 : ++nError;
1244 : fprintf( stderr, "Error: Date acceptance pattern '%s' matches decimal number '#%s#'\n",
1245 0 : OSTR( *aIt), OSTR( aDecSep));
1246 : }
1247 : }
1248 : }
1249 : }
1250 :
1251 : // Check for duplicates.
1252 1611 : for (vector<OUString>::const_iterator aIt = theDateAcceptancePatterns.begin();
1253 1074 : aIt != theDateAcceptancePatterns.end(); ++aIt)
1254 : {
1255 3397 : for (vector<OUString>::iterator aComp = theDateAcceptancePatterns.begin();
1256 3016 : aComp != theDateAcceptancePatterns.end(); /*nop*/)
1257 : {
1258 1127 : if (aIt != aComp && *aIt == *aComp)
1259 : {
1260 0 : incErrorStr( "Duplicated DateAcceptancePattern", *aComp);
1261 0 : aComp = theDateAcceptancePatterns.erase( aComp);
1262 : }
1263 : else
1264 1127 : ++aComp;
1265 : }
1266 : }
1267 :
1268 156 : sal_Int16 nbOfDateAcceptancePatterns = static_cast<sal_Int16>(theDateAcceptancePatterns.size());
1269 :
1270 537 : for (sal_Int16 i = 0; i < nbOfDateAcceptancePatterns; ++i)
1271 : {
1272 381 : of.writeParameter("DateAcceptancePattern", theDateAcceptancePatterns[i], i);
1273 : }
1274 :
1275 156 : of.writeAsciiString("static const sal_Int16 DateAcceptancePatternsCount = ");
1276 156 : of.writeInt( nbOfDateAcceptancePatterns);
1277 156 : of.writeAsciiString(";\n");
1278 :
1279 156 : of.writeAsciiString("static const sal_Unicode* DateAcceptancePatternsArray[] = {\n");
1280 537 : for (sal_Int16 i = 0; i < nbOfDateAcceptancePatterns; ++i)
1281 : {
1282 381 : of.writeAsciiString("\t");
1283 381 : of.writeAsciiString("DateAcceptancePattern");
1284 381 : of.writeInt(i);
1285 381 : of.writeAsciiString(",\n");
1286 : }
1287 156 : of.writeAsciiString("};\n\n");
1288 :
1289 312 : of.writeFunction("getDateAcceptancePatterns_", "DateAcceptancePatternsCount", "DateAcceptancePatternsArray");
1290 : }
1291 :
1292 471 : ++mnSection;
1293 : }
1294 :
1295 231 : void LCCollationNode::generateCode (const OFileWriter &of) const
1296 : {
1297 231 : OUString useLocale = getAttr().getValueByName("ref");
1298 231 : if (!useLocale.isEmpty()) {
1299 122 : useLocale = useLocale.replace( '-', '_');
1300 122 : of.writeRefFunction("getCollatorImplementation_", useLocale);
1301 122 : of.writeRefFunction("getCollationOptions_", useLocale);
1302 353 : return;
1303 : }
1304 109 : sal_Int16 nbOfCollations = 0;
1305 109 : sal_Int16 nbOfCollationOptions = 0;
1306 : sal_Int16 j;
1307 :
1308 340 : for ( j = 0; j < getNumberOfChildren(); j++ ) {
1309 231 : LocaleNode * currNode = getChildAt (j);
1310 231 : if( currNode->getName().equalsAscii("Collator") )
1311 : {
1312 122 : OUString str;
1313 122 : str = currNode->getAttr().getValueByName("unoid");
1314 122 : of.writeParameter("CollatorID", str, j);
1315 122 : str = currNode->getValue();
1316 122 : of.writeParameter("CollatorRule", str, j);
1317 122 : str = currNode -> getAttr().getValueByName("default");
1318 122 : of.writeDefaultParameter("Collator", str, j);
1319 122 : of.writeAsciiString("\n");
1320 :
1321 122 : nbOfCollations++;
1322 : }
1323 231 : if( currNode->getName().equalsAscii("CollationOptions") )
1324 : {
1325 109 : LocaleNode* pCollationOptions = currNode;
1326 109 : nbOfCollationOptions = sal::static_int_cast<sal_Int16>( pCollationOptions->getNumberOfChildren() );
1327 218 : for( sal_Int16 i=0; i<nbOfCollationOptions; i++ )
1328 : {
1329 109 : of.writeParameter("collationOption", pCollationOptions->getChildAt( i )->getValue(), i );
1330 : }
1331 :
1332 109 : of.writeAsciiString("static const sal_Int16 nbOfCollationOptions = ");
1333 109 : of.writeInt( nbOfCollationOptions );
1334 109 : of.writeAsciiString(";\n\n");
1335 : }
1336 : }
1337 109 : of.writeAsciiString("static const sal_Int16 nbOfCollations = ");
1338 109 : of.writeInt(nbOfCollations);
1339 109 : of.writeAsciiString(";\n\n");
1340 :
1341 109 : of.writeAsciiString("\nstatic const sal_Unicode* LCCollatorArray[] = {\n");
1342 231 : for(j = 0; j < nbOfCollations; j++) {
1343 122 : of.writeAsciiString("\tCollatorID");
1344 122 : of.writeInt(j);
1345 122 : of.writeAsciiString(",\n");
1346 :
1347 122 : of.writeAsciiString("\tdefaultCollator");
1348 122 : of.writeInt(j);
1349 122 : of.writeAsciiString(",\n");
1350 :
1351 122 : of.writeAsciiString("\tCollatorRule");
1352 122 : of.writeInt(j);
1353 122 : of.writeAsciiString(",\n");
1354 : }
1355 109 : of.writeAsciiString("};\n\n");
1356 :
1357 109 : of.writeAsciiString("static const sal_Unicode* collationOptions[] = {");
1358 218 : for( j=0; j<nbOfCollationOptions; j++ )
1359 : {
1360 109 : of.writeAsciiString( "collationOption" );
1361 109 : of.writeInt( j );
1362 109 : of.writeAsciiString( ", " );
1363 : }
1364 109 : of.writeAsciiString("NULL };\n");
1365 109 : of.writeFunction("getCollatorImplementation_", "nbOfCollations", "LCCollatorArray");
1366 109 : of.writeFunction("getCollationOptions_", "nbOfCollationOptions", "collationOptions");
1367 : }
1368 :
1369 231 : void LCSearchNode::generateCode (const OFileWriter &of) const
1370 : {
1371 231 : OUString useLocale = getAttr().getValueByName("ref");
1372 231 : if (!useLocale.isEmpty()) {
1373 137 : useLocale = useLocale.replace( '-', '_');
1374 137 : of.writeRefFunction("getSearchOptions_", useLocale);
1375 368 : return;
1376 : }
1377 :
1378 94 : if( getNumberOfChildren() != 1 )
1379 : {
1380 0 : ++nError;
1381 : fprintf(
1382 : stderr, "Error: LC_SEARCH: more than 1 child: %ld\n",
1383 0 : sal::static_int_cast< long >(getNumberOfChildren()));
1384 : }
1385 : sal_Int32 i;
1386 94 : LocaleNode* pSearchOptions = getChildAt( 0 );
1387 94 : sal_Int32 nSearchOptions = pSearchOptions->getNumberOfChildren();
1388 190 : for( i=0; i<nSearchOptions; i++ )
1389 : {
1390 96 : of.writeParameter("searchOption", pSearchOptions->getChildAt( i )->getValue(), sal::static_int_cast<sal_Int16>(i) );
1391 : }
1392 :
1393 94 : of.writeAsciiString("static const sal_Int16 nbOfSearchOptions = ");
1394 94 : of.writeInt( sal::static_int_cast<sal_Int16>( nSearchOptions ) );
1395 94 : of.writeAsciiString(";\n\n");
1396 :
1397 94 : of.writeAsciiString("static const sal_Unicode* searchOptions[] = {");
1398 190 : for( i=0; i<nSearchOptions; i++ )
1399 : {
1400 96 : of.writeAsciiString( "searchOption" );
1401 96 : of.writeInt( sal::static_int_cast<sal_Int16>(i) );
1402 96 : of.writeAsciiString( ", " );
1403 : }
1404 94 : of.writeAsciiString("NULL };\n");
1405 94 : of.writeFunction("getSearchOptions_", "nbOfSearchOptions", "searchOptions");
1406 : }
1407 :
1408 231 : void LCIndexNode::generateCode (const OFileWriter &of) const
1409 : {
1410 231 : OUString useLocale = getAttr().getValueByName("ref");
1411 231 : if (!useLocale.isEmpty()) {
1412 82 : useLocale = useLocale.replace( '-', '_');
1413 82 : of.writeRefFunction("getIndexAlgorithm_", useLocale);
1414 82 : of.writeRefFunction("getUnicodeScripts_", useLocale);
1415 82 : of.writeRefFunction("getFollowPageWords_", useLocale);
1416 313 : return;
1417 : }
1418 149 : sal_Int16 nbOfIndexs = 0;
1419 149 : sal_Int16 nbOfUnicodeScripts = 0;
1420 149 : sal_Int16 nbOfPageWords = 0;
1421 : sal_Int16 i;
1422 900 : for (i = 0; i< getNumberOfChildren();i++) {
1423 751 : LocaleNode * currNode = getChildAt (i);
1424 751 : if( currNode->getName().equalsAscii("IndexKey") )
1425 : {
1426 157 : OUString str;
1427 157 : str = currNode->getAttr().getValueByName("unoid");
1428 157 : of.writeParameter("IndexID", str, nbOfIndexs);
1429 157 : str = currNode->getAttr().getValueByName("module");
1430 157 : of.writeParameter("IndexModule", str, nbOfIndexs);
1431 157 : str = currNode->getValue();
1432 157 : of.writeParameter("IndexKey", str, nbOfIndexs);
1433 157 : str = currNode -> getAttr().getValueByName("default");
1434 157 : of.writeDefaultParameter("Index", str, nbOfIndexs);
1435 157 : str = currNode -> getAttr().getValueByName("phonetic");
1436 157 : of.writeDefaultParameter("Phonetic", str, nbOfIndexs);
1437 157 : of.writeAsciiString("\n");
1438 :
1439 157 : nbOfIndexs++;
1440 : }
1441 751 : if( currNode->getName().equalsAscii("UnicodeScript") )
1442 : {
1443 300 : of.writeParameter("unicodeScript", currNode->getValue(), nbOfUnicodeScripts );
1444 300 : nbOfUnicodeScripts++;
1445 :
1446 : }
1447 751 : if( currNode->getName().equalsAscii("FollowPageWord") )
1448 : {
1449 294 : of.writeParameter("followPageWord", currNode->getValue(), nbOfPageWords);
1450 294 : nbOfPageWords++;
1451 : }
1452 : }
1453 149 : of.writeAsciiString("static const sal_Int16 nbOfIndexs = ");
1454 149 : of.writeInt(nbOfIndexs);
1455 149 : of.writeAsciiString(";\n\n");
1456 :
1457 149 : of.writeAsciiString("\nstatic const sal_Unicode* IndexArray[] = {\n");
1458 306 : for(i = 0; i < nbOfIndexs; i++) {
1459 157 : of.writeAsciiString("\tIndexID");
1460 157 : of.writeInt(i);
1461 157 : of.writeAsciiString(",\n");
1462 :
1463 157 : of.writeAsciiString("\tIndexModule");
1464 157 : of.writeInt(i);
1465 157 : of.writeAsciiString(",\n");
1466 :
1467 157 : of.writeAsciiString("\tIndexKey");
1468 157 : of.writeInt(i);
1469 157 : of.writeAsciiString(",\n");
1470 :
1471 157 : of.writeAsciiString("\tdefaultIndex");
1472 157 : of.writeInt(i);
1473 157 : of.writeAsciiString(",\n");
1474 :
1475 157 : of.writeAsciiString("\tdefaultPhonetic");
1476 157 : of.writeInt(i);
1477 157 : of.writeAsciiString(",\n");
1478 : }
1479 149 : of.writeAsciiString("};\n\n");
1480 :
1481 149 : of.writeAsciiString("static const sal_Int16 nbOfUnicodeScripts = ");
1482 149 : of.writeInt( nbOfUnicodeScripts );
1483 149 : of.writeAsciiString(";\n\n");
1484 :
1485 149 : of.writeAsciiString("static const sal_Unicode* UnicodeScriptArray[] = {");
1486 449 : for( i=0; i<nbOfUnicodeScripts; i++ )
1487 : {
1488 300 : of.writeAsciiString( "unicodeScript" );
1489 300 : of.writeInt( i );
1490 300 : of.writeAsciiString( ", " );
1491 : }
1492 149 : of.writeAsciiString("NULL };\n\n");
1493 :
1494 149 : of.writeAsciiString("static const sal_Int16 nbOfPageWords = ");
1495 149 : of.writeInt(nbOfPageWords);
1496 149 : of.writeAsciiString(";\n\n");
1497 :
1498 149 : of.writeAsciiString("static const sal_Unicode* FollowPageWordArray[] = {\n");
1499 443 : for(i = 0; i < nbOfPageWords; i++) {
1500 294 : of.writeAsciiString("\tfollowPageWord");
1501 294 : of.writeInt(i);
1502 294 : of.writeAsciiString(",\n");
1503 : }
1504 149 : of.writeAsciiString("\tNULL\n};\n\n");
1505 :
1506 149 : of.writeFunction("getIndexAlgorithm_", "nbOfIndexs", "IndexArray");
1507 149 : of.writeFunction("getUnicodeScripts_", "nbOfUnicodeScripts", "UnicodeScriptArray");
1508 149 : of.writeFunction("getFollowPageWords_", "nbOfPageWords", "FollowPageWordArray");
1509 : }
1510 :
1511 :
1512 8427 : static void lcl_writeAbbrFullNarrNames( const OFileWriter & of, const LocaleNode* currNode,
1513 : const sal_Char* elementTag, sal_Int16 i, sal_Int16 j )
1514 : {
1515 8427 : OUString aAbbrName = currNode->getChildAt(1)->getValue();
1516 16854 : OUString aFullName = currNode->getChildAt(2)->getValue();
1517 16854 : OUString aNarrName;
1518 8427 : LocaleNode* p = (currNode->getNumberOfChildren() > 3 ? currNode->getChildAt(3) : 0);
1519 8427 : if ( p && p->getName() == "DefaultNarrowName" )
1520 0 : aNarrName = p->getValue();
1521 : else
1522 : {
1523 8427 : sal_Int32 nIndex = 0;
1524 8427 : sal_uInt32 nChar = aFullName.iterateCodePoints( &nIndex);
1525 8427 : aNarrName = OUString( &nChar, 1);
1526 : }
1527 8427 : of.writeParameter( elementTag, "DefaultAbbrvName", aAbbrName, i, j);
1528 8427 : of.writeParameter( elementTag, "DefaultFullName", aFullName, i, j);
1529 16854 : of.writeParameter( elementTag, "DefaultNarrowName", aNarrName, i, j);
1530 8427 : }
1531 :
1532 34975 : static void lcl_writeTabTagString( const OFileWriter & of, const sal_Char* pTag, const sal_Char* pStr )
1533 : {
1534 34975 : of.writeAsciiString("\t");
1535 34975 : of.writeAsciiString( pTag);
1536 34975 : of.writeAsciiString( pStr);
1537 34975 : }
1538 :
1539 34893 : static void lcl_writeTabTagStringNums( const OFileWriter & of,
1540 : const sal_Char* pTag, const sal_Char* pStr, sal_Int16 i, sal_Int16 j )
1541 : {
1542 34893 : lcl_writeTabTagString( of, pTag, pStr);
1543 34893 : of.writeInt(i); of.writeInt(j); of.writeAsciiString(",\n");
1544 34893 : }
1545 :
1546 1020 : static void lcl_writeAbbrFullNarrArrays( const OFileWriter & of, sal_Int16 nCount,
1547 : const sal_Char* elementTag, sal_Int16 i, bool bNarrow )
1548 : {
1549 1020 : if (nCount == 0)
1550 : {
1551 41 : lcl_writeTabTagString( of, elementTag, "Ref");
1552 41 : of.writeInt(i); of.writeAsciiString(",\n");
1553 41 : lcl_writeTabTagString( of, elementTag, "RefName");
1554 41 : of.writeInt(i); of.writeAsciiString(",\n");
1555 : }
1556 : else
1557 : {
1558 9801 : for (sal_Int16 j = 0; j < nCount; j++)
1559 : {
1560 8822 : lcl_writeTabTagStringNums( of, elementTag, "ID", i, j);
1561 8822 : lcl_writeTabTagStringNums( of, elementTag, "DefaultAbbrvName", i, j);
1562 8822 : lcl_writeTabTagStringNums( of, elementTag, "DefaultFullName", i, j);
1563 8822 : if (bNarrow)
1564 8427 : lcl_writeTabTagStringNums( of, elementTag, "DefaultNarrowName", i, j);
1565 : }
1566 : }
1567 1020 : }
1568 :
1569 231 : void LCCalendarNode::generateCode (const OFileWriter &of) const
1570 : {
1571 231 : OUString useLocale = getAttr().getValueByName("ref");
1572 231 : if (!useLocale.isEmpty()) {
1573 41 : useLocale = useLocale.replace( '-', '_');
1574 41 : of.writeRefFunction("getAllCalendars_", useLocale);
1575 272 : return;
1576 : }
1577 190 : sal_Int16 nbOfCalendars = sal::static_int_cast<sal_Int16>( getNumberOfChildren() );
1578 380 : OUString str;
1579 190 : sal_Int16 * nbOfDays = new sal_Int16[nbOfCalendars];
1580 190 : sal_Int16 * nbOfMonths = new sal_Int16[nbOfCalendars];
1581 190 : sal_Int16 * nbOfGenitiveMonths = new sal_Int16[nbOfCalendars];
1582 190 : sal_Int16 * nbOfPartitiveMonths = new sal_Int16[nbOfCalendars];
1583 190 : sal_Int16 * nbOfEras = new sal_Int16[nbOfCalendars];
1584 : sal_Int16 j;
1585 : sal_Int16 i;
1586 190 : bool bHasGregorian = false;
1587 :
1588 :
1589 394 : for ( i = 0; i < nbOfCalendars; i++) {
1590 204 : LocaleNode * calNode = getChildAt (i);
1591 204 : OUString calendarID = calNode -> getAttr().getValueByName("unoid");
1592 204 : of.writeParameter( "calendarID", calendarID, i);
1593 204 : bool bGregorian = calendarID == "gregorian";
1594 204 : if (!bHasGregorian)
1595 192 : bHasGregorian = bGregorian;
1596 204 : str = calNode -> getAttr().getValueByName("default");
1597 204 : of.writeDefaultParameter("Calendar", str, i);
1598 :
1599 204 : sal_Int16 nChild = 0;
1600 :
1601 : // Generate Days of Week
1602 : const sal_Char *elementTag;
1603 204 : LocaleNode * daysNode = NULL;
1604 408 : OUString ref_name = calNode->getChildAt(nChild)->getAttr().getValueByName("ref");
1605 204 : ref_name = ref_name.replace( '-', '_');
1606 204 : if (!ref_name.isEmpty() && i > 0) {
1607 6 : for (j = 0; j < i; j++) {
1608 3 : str = getChildAt(j)->getAttr().getValueByName("unoid");
1609 3 : if (str.equals(ref_name))
1610 2 : daysNode = getChildAt(j)->getChildAt(0);
1611 : }
1612 : }
1613 204 : if (!ref_name.isEmpty() && daysNode == NULL) {
1614 9 : of.writeParameter("dayRef", OUString("ref"), i);
1615 9 : of.writeParameter("dayRefName", ref_name, i);
1616 9 : nbOfDays[i] = 0;
1617 : } else {
1618 195 : if (daysNode == NULL)
1619 193 : daysNode = calNode -> getChildAt(nChild);
1620 195 : nbOfDays[i] = sal::static_int_cast<sal_Int16>( daysNode->getNumberOfChildren() );
1621 195 : if (bGregorian && nbOfDays[i] != 7)
1622 0 : incErrorInt( "A Gregorian calendar must have 7 days per week, this one has %d", nbOfDays[i]);
1623 195 : elementTag = "day";
1624 1560 : for (j = 0; j < nbOfDays[i]; j++) {
1625 1365 : LocaleNode *currNode = daysNode -> getChildAt(j);
1626 1365 : OUString dayID( currNode->getChildAt(0)->getValue());
1627 1365 : of.writeParameter("dayID", dayID, i, j);
1628 1365 : if ( j == 0 && bGregorian && dayID != "sun" )
1629 0 : incError( "First day of a week of a Gregorian calendar must be <DayID>sun</DayID>");
1630 1365 : lcl_writeAbbrFullNarrNames( of, currNode, elementTag, i, j);
1631 1365 : }
1632 : }
1633 204 : ++nChild;
1634 :
1635 : // Generate Months of Year
1636 204 : LocaleNode * monthsNode = NULL;
1637 204 : ref_name = calNode->getChildAt(nChild)->getAttr().getValueByName("ref");
1638 204 : ref_name = ref_name.replace( '-', '_');
1639 204 : if (!ref_name.isEmpty() && i > 0) {
1640 2 : for (j = 0; j < i; j++) {
1641 1 : str = getChildAt(j)->getAttr().getValueByName("unoid");
1642 1 : if (str.equals(ref_name))
1643 1 : monthsNode = getChildAt(j)->getChildAt(1);
1644 : }
1645 : }
1646 204 : if (!ref_name.isEmpty() && monthsNode == NULL) {
1647 8 : of.writeParameter("monthRef", OUString("ref"), i);
1648 8 : of.writeParameter("monthRefName", ref_name, i);
1649 8 : nbOfMonths[i] = 0;
1650 : } else {
1651 196 : if (monthsNode == NULL)
1652 195 : monthsNode = calNode -> getChildAt(nChild);
1653 196 : nbOfMonths[i] = sal::static_int_cast<sal_Int16>( monthsNode->getNumberOfChildren() );
1654 196 : if (bGregorian && nbOfMonths[i] != 12)
1655 0 : incErrorInt( "A Gregorian calendar must have 12 months, this one has %d", nbOfMonths[i]);
1656 196 : elementTag = "month";
1657 2550 : for (j = 0; j < nbOfMonths[i]; j++) {
1658 2354 : LocaleNode *currNode = monthsNode -> getChildAt(j);
1659 2354 : OUString monthID( currNode->getChildAt(0)->getValue());
1660 2354 : of.writeParameter("monthID", monthID, i, j);
1661 2354 : if ( j == 0 && bGregorian && monthID != "jan" )
1662 0 : incError( "First month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1663 2354 : lcl_writeAbbrFullNarrNames( of, currNode, elementTag, i, j);
1664 2354 : }
1665 : }
1666 204 : ++nChild;
1667 :
1668 : // Generate genitive Months of Year
1669 : // Optional, if not present fall back to month nouns.
1670 204 : if ( calNode->getChildAt(nChild)->getName() != "GenitiveMonths" )
1671 195 : --nChild;
1672 204 : LocaleNode * genitiveMonthsNode = NULL;
1673 204 : ref_name = calNode->getChildAt(nChild)->getAttr().getValueByName("ref");
1674 204 : ref_name = ref_name.replace( '-', '_');
1675 204 : if (!ref_name.isEmpty() && i > 0) {
1676 2 : for (j = 0; j < i; j++) {
1677 1 : str = getChildAt(j)->getAttr().getValueByName("unoid");
1678 1 : if (str.equals(ref_name))
1679 1 : genitiveMonthsNode = getChildAt(j)->getChildAt(1);
1680 : }
1681 : }
1682 204 : if (!ref_name.isEmpty() && genitiveMonthsNode == NULL) {
1683 8 : of.writeParameter("genitiveMonthRef", OUString("ref"), i);
1684 8 : of.writeParameter("genitiveMonthRefName", ref_name, i);
1685 8 : nbOfGenitiveMonths[i] = 0;
1686 : } else {
1687 196 : if (genitiveMonthsNode == NULL)
1688 195 : genitiveMonthsNode = calNode -> getChildAt(nChild);
1689 196 : nbOfGenitiveMonths[i] = sal::static_int_cast<sal_Int16>( genitiveMonthsNode->getNumberOfChildren() );
1690 196 : if (bGregorian && nbOfGenitiveMonths[i] != 12)
1691 0 : incErrorInt( "A Gregorian calendar must have 12 genitive months, this one has %d", nbOfGenitiveMonths[i]);
1692 196 : elementTag = "genitiveMonth";
1693 2550 : for (j = 0; j < nbOfGenitiveMonths[i]; j++) {
1694 2354 : LocaleNode *currNode = genitiveMonthsNode -> getChildAt(j);
1695 2354 : OUString genitiveMonthID( currNode->getChildAt(0)->getValue());
1696 2354 : of.writeParameter("genitiveMonthID", genitiveMonthID, i, j);
1697 2354 : if ( j == 0 && bGregorian && genitiveMonthID != "jan" )
1698 0 : incError( "First genitive month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1699 2354 : lcl_writeAbbrFullNarrNames( of, currNode, elementTag, i, j);
1700 2354 : }
1701 : }
1702 204 : ++nChild;
1703 :
1704 : // Generate partitive Months of Year
1705 : // Optional, if not present fall back to genitive months, or nominative
1706 : // months (nouns) if that isn't present either.
1707 204 : if ( calNode->getChildAt(nChild)->getName() != "PartitiveMonths" )
1708 200 : --nChild;
1709 204 : LocaleNode * partitiveMonthsNode = NULL;
1710 204 : ref_name = calNode->getChildAt(nChild)->getAttr().getValueByName("ref");
1711 204 : ref_name = ref_name.replace( '-', '_');
1712 204 : if (!ref_name.isEmpty() && i > 0) {
1713 2 : for (j = 0; j < i; j++) {
1714 1 : str = getChildAt(j)->getAttr().getValueByName("unoid");
1715 1 : if (str.equals(ref_name))
1716 1 : partitiveMonthsNode = getChildAt(j)->getChildAt(1);
1717 : }
1718 : }
1719 204 : if (!ref_name.isEmpty() && partitiveMonthsNode == NULL) {
1720 8 : of.writeParameter("partitiveMonthRef", OUString("ref"), i);
1721 8 : of.writeParameter("partitiveMonthRefName", ref_name, i);
1722 8 : nbOfPartitiveMonths[i] = 0;
1723 : } else {
1724 196 : if (partitiveMonthsNode == NULL)
1725 195 : partitiveMonthsNode = calNode -> getChildAt(nChild);
1726 196 : nbOfPartitiveMonths[i] = sal::static_int_cast<sal_Int16>( partitiveMonthsNode->getNumberOfChildren() );
1727 196 : if (bGregorian && nbOfPartitiveMonths[i] != 12)
1728 0 : incErrorInt( "A Gregorian calendar must have 12 partitive months, this one has %d", nbOfPartitiveMonths[i]);
1729 196 : elementTag = "partitiveMonth";
1730 2550 : for (j = 0; j < nbOfPartitiveMonths[i]; j++) {
1731 2354 : LocaleNode *currNode = partitiveMonthsNode -> getChildAt(j);
1732 2354 : OUString partitiveMonthID( currNode->getChildAt(0)->getValue());
1733 2354 : of.writeParameter("partitiveMonthID", partitiveMonthID, i, j);
1734 2354 : if ( j == 0 && bGregorian && partitiveMonthID != "jan" )
1735 0 : incError( "First partitive month of a year of a Gregorian calendar must be <MonthID>jan</MonthID>");
1736 2354 : lcl_writeAbbrFullNarrNames( of, currNode, elementTag, i, j);
1737 2354 : }
1738 : }
1739 204 : ++nChild;
1740 :
1741 : // Generate Era name
1742 204 : LocaleNode * erasNode = NULL;
1743 204 : ref_name = calNode -> getChildAt(nChild) ->getAttr().getValueByName("ref");
1744 204 : ref_name = ref_name.replace( '-', '_');
1745 204 : if (!ref_name.isEmpty() && i > 0) {
1746 0 : for (j = 0; j < i; j++) {
1747 0 : str = getChildAt(j)->getAttr().getValueByName("unoid");
1748 0 : if (str.equals(ref_name))
1749 0 : erasNode = getChildAt(j)->getChildAt(2);
1750 : }
1751 : }
1752 204 : if (!ref_name.isEmpty() && erasNode == NULL) {
1753 8 : of.writeParameter("eraRef", OUString("ref"), i);
1754 8 : of.writeParameter("eraRefName", ref_name, i);
1755 8 : nbOfEras[i] = 0;
1756 : } else {
1757 196 : if (erasNode == NULL)
1758 196 : erasNode = calNode -> getChildAt(nChild);
1759 196 : nbOfEras[i] = sal::static_int_cast<sal_Int16>( erasNode->getNumberOfChildren() );
1760 196 : if (bGregorian && nbOfEras[i] != 2)
1761 0 : incErrorInt( "A Gregorian calendar must have 2 eras, this one has %d", nbOfEras[i]);
1762 196 : elementTag = "era";
1763 591 : for (j = 0; j < nbOfEras[i]; j++) {
1764 395 : LocaleNode *currNode = erasNode -> getChildAt(j);
1765 395 : OUString eraID( currNode->getChildAt(0)->getValue());
1766 395 : of.writeParameter("eraID", eraID, i, j);
1767 395 : if ( j == 0 && bGregorian && eraID != "bc" )
1768 0 : incError( "First era of a Gregorian calendar must be <EraID>bc</EraID>");
1769 395 : if ( j == 1 && bGregorian && eraID != "ad" )
1770 0 : incError( "Second era of a Gregorian calendar must be <EraID>ad</EraID>");
1771 395 : of.writeAsciiString("\n");
1772 395 : of.writeParameter(elementTag, "DefaultAbbrvName",currNode->getChildAt(1)->getValue() ,i, j);
1773 395 : of.writeParameter(elementTag, "DefaultFullName",currNode->getChildAt(2)->getValue() , i, j);
1774 395 : }
1775 : }
1776 204 : ++nChild;
1777 :
1778 204 : str = calNode->getChildAt(nChild)->getChildAt(0)->getValue();
1779 204 : if (nbOfDays[i])
1780 : {
1781 425 : for (j = 0; j < nbOfDays[i]; j++)
1782 : {
1783 425 : LocaleNode *currNode = daysNode->getChildAt(j);
1784 425 : OUString dayID( currNode->getChildAt(0)->getValue());
1785 425 : if (str == dayID)
1786 195 : break; // for
1787 230 : }
1788 195 : if (j >= nbOfDays[i])
1789 0 : incErrorStr( "<StartDayOfWeek> <DayID> must be one of the <DaysOfWeek>, but is", str);
1790 : }
1791 204 : of.writeParameter("startDayOfWeek", str, i);
1792 204 : ++nChild;
1793 :
1794 204 : str = calNode ->getChildAt(nChild)-> getValue();
1795 204 : sal_Int16 nDays = sal::static_int_cast<sal_Int16>( str.toInt32() );
1796 204 : if (nDays < 1 || (0 < nbOfDays[i] && nbOfDays[i] < nDays))
1797 0 : incErrorInt( "Bad value of MinimalDaysInFirstWeek: %d, must be 1 <= value <= days_in_week", nDays);
1798 204 : of.writeIntParameter("minimalDaysInFirstWeek", i, nDays);
1799 204 : }
1800 190 : if (!bHasGregorian)
1801 0 : fprintf( stderr, "Warning: %s\n", "No Gregorian calendar defined, are you sure?");
1802 :
1803 190 : of.writeAsciiString("static const sal_Int16 calendarsCount = ");
1804 190 : of.writeInt(nbOfCalendars);
1805 190 : of.writeAsciiString(";\n\n");
1806 :
1807 190 : of.writeAsciiString("static const sal_Unicode nbOfDays[] = {");
1808 204 : for(i = 0; i < nbOfCalendars - 1; i++) {
1809 14 : of.writeInt(nbOfDays[i]);
1810 14 : of.writeAsciiString(", ");
1811 : };
1812 190 : of.writeInt(nbOfDays[i]);
1813 190 : of.writeAsciiString("};\n");
1814 :
1815 190 : of.writeAsciiString("static const sal_Unicode nbOfMonths[] = {");
1816 204 : for(i = 0; i < nbOfCalendars - 1; i++) {
1817 14 : of.writeInt(nbOfMonths[i]);
1818 14 : of.writeAsciiString(", ");
1819 : };
1820 190 : of.writeInt(nbOfMonths[i]);
1821 190 : of.writeAsciiString("};\n");
1822 :
1823 190 : of.writeAsciiString("static const sal_Unicode nbOfGenitiveMonths[] = {");
1824 204 : for(i = 0; i < nbOfCalendars - 1; i++) {
1825 14 : of.writeInt(nbOfGenitiveMonths[i]);
1826 14 : of.writeAsciiString(", ");
1827 : };
1828 190 : of.writeInt(nbOfGenitiveMonths[i]);
1829 190 : of.writeAsciiString("};\n");
1830 :
1831 190 : of.writeAsciiString("static const sal_Unicode nbOfPartitiveMonths[] = {");
1832 204 : for(i = 0; i < nbOfCalendars - 1; i++) {
1833 14 : of.writeInt(nbOfPartitiveMonths[i]);
1834 14 : of.writeAsciiString(", ");
1835 : };
1836 190 : of.writeInt(nbOfPartitiveMonths[i]);
1837 190 : of.writeAsciiString("};\n");
1838 :
1839 190 : of.writeAsciiString("static const sal_Unicode nbOfEras[] = {");
1840 204 : for(i = 0; i < nbOfCalendars - 1; i++) {
1841 14 : of.writeInt(nbOfEras[i]);
1842 14 : of.writeAsciiString(", ");
1843 : };
1844 190 : of.writeInt(nbOfEras[i]);
1845 190 : of.writeAsciiString("};\n");
1846 :
1847 :
1848 190 : of.writeAsciiString("static const sal_Unicode* calendars[] = {\n");
1849 190 : of.writeAsciiString("\tnbOfDays,\n");
1850 190 : of.writeAsciiString("\tnbOfMonths,\n");
1851 190 : of.writeAsciiString("\tnbOfGenitiveMonths,\n");
1852 190 : of.writeAsciiString("\tnbOfPartitiveMonths,\n");
1853 190 : of.writeAsciiString("\tnbOfEras,\n");
1854 394 : for(i = 0; i < nbOfCalendars; i++) {
1855 204 : of.writeAsciiString("\tcalendarID");
1856 204 : of.writeInt(i);
1857 204 : of.writeAsciiString(",\n");
1858 204 : of.writeAsciiString("\tdefaultCalendar");
1859 204 : of.writeInt(i);
1860 204 : of.writeAsciiString(",\n");
1861 204 : lcl_writeAbbrFullNarrArrays( of, nbOfDays[i], "day", i, true);
1862 204 : lcl_writeAbbrFullNarrArrays( of, nbOfMonths[i], "month", i, true);
1863 204 : lcl_writeAbbrFullNarrArrays( of, nbOfGenitiveMonths[i], "genitiveMonth", i, true);
1864 204 : lcl_writeAbbrFullNarrArrays( of, nbOfPartitiveMonths[i], "partitiveMonth", i, true);
1865 204 : lcl_writeAbbrFullNarrArrays( of, nbOfEras[i], "era", i, false /*noNarrow*/);
1866 204 : of.writeAsciiString("\tstartDayOfWeek");of.writeInt(i); of.writeAsciiString(",\n");
1867 204 : of.writeAsciiString("\tminimalDaysInFirstWeek");of.writeInt(i); of.writeAsciiString(",\n");
1868 : }
1869 :
1870 190 : of.writeAsciiString("};\n\n");
1871 190 : of.writeFunction("getAllCalendars_", "calendarsCount", "calendars");
1872 :
1873 190 : delete []nbOfDays;
1874 190 : delete []nbOfMonths;
1875 190 : delete []nbOfGenitiveMonths;
1876 190 : delete []nbOfPartitiveMonths;
1877 380 : delete []nbOfEras;
1878 : }
1879 :
1880 494 : bool isIso4217( const OUString& rStr )
1881 : {
1882 494 : const sal_Unicode* p = rStr.getStr();
1883 494 : return rStr.getLength() == 3
1884 494 : && 'A' <= p[0] && p[0] <= 'Z'
1885 494 : && 'A' <= p[1] && p[1] <= 'Z'
1886 988 : && 'A' <= p[2] && p[2] <= 'Z'
1887 : ;
1888 : }
1889 :
1890 231 : void LCCurrencyNode :: generateCode (const OFileWriter &of) const
1891 : {
1892 231 : OUString useLocale = getAttr().getValueByName("ref");
1893 231 : if (!useLocale.isEmpty()) {
1894 39 : useLocale = useLocale.replace( '-', '_');
1895 39 : of.writeRefFunction("getAllCurrencies_", useLocale);
1896 270 : return;
1897 : }
1898 192 : sal_Int16 nbOfCurrencies = 0;
1899 384 : OUString str;
1900 : sal_Int16 i;
1901 :
1902 192 : bool bTheDefault= false;
1903 192 : bool bTheCompatible = false;
1904 477 : for ( i = 0; i < getNumberOfChildren(); i++,nbOfCurrencies++) {
1905 285 : LocaleNode * currencyNode = getChildAt (i);
1906 285 : str = currencyNode->getAttr().getValueByName("default");
1907 285 : bool bDefault = of.writeDefaultParameter("Currency", str, nbOfCurrencies);
1908 285 : str = currencyNode->getAttr().getValueByName("usedInCompatibleFormatCodes");
1909 285 : bool bCompatible = of.writeDefaultParameter("CurrencyUsedInCompatibleFormatCodes", str, nbOfCurrencies);
1910 285 : str = currencyNode->getAttr().getValueByName("legacyOnly");
1911 285 : bool bLegacy = of.writeDefaultParameter("CurrencyLegacyOnly", str, nbOfCurrencies);
1912 285 : if (bLegacy && (bDefault || bCompatible))
1913 0 : incError( "Currency: if legacyOnly==true, both 'default' and 'usedInCompatibleFormatCodes' must be false.");
1914 285 : if (bDefault)
1915 : {
1916 192 : if (bTheDefault)
1917 0 : incError( "Currency: more than one default currency.");
1918 192 : bTheDefault = true;
1919 : }
1920 285 : if (bCompatible)
1921 : {
1922 192 : if (bTheCompatible)
1923 0 : incError( "Currency: more than one currency flagged as usedInCompatibleFormatCodes.");
1924 192 : bTheCompatible = true;
1925 : }
1926 285 : str = currencyNode -> findNode ("CurrencyID") -> getValue();
1927 285 : of.writeParameter("currencyID", str, nbOfCurrencies);
1928 : // CurrencyID MUST be ISO 4217.
1929 285 : if (!bLegacy && !isIso4217(str))
1930 0 : incError( "CurrencyID is not ISO 4217");
1931 285 : str = currencyNode -> findNode ("CurrencySymbol") -> getValue();
1932 285 : of.writeParameter("currencySymbol", str, nbOfCurrencies);
1933 : // Check if this currency really is the one used in number format
1934 : // codes. In case of ref=... mechanisms it may be that TheCurrency
1935 : // couldn't had been determined from the current locale (i.e. is
1936 : // empty), silently assume the referred locale has things right.
1937 285 : if (bCompatible && !sTheCompatibleCurrency.isEmpty() && sTheCompatibleCurrency != str)
1938 0 : incErrorStrStr( "CurrencySymbol \"%s\" flagged as usedInCompatibleFormatCodes doesn't match \"%s\" determined from format codes.", str, sTheCompatibleCurrency);
1939 285 : str = currencyNode -> findNode ("BankSymbol") -> getValue();
1940 285 : of.writeParameter("bankSymbol", str, nbOfCurrencies);
1941 : // BankSymbol currently must be ISO 4217. May change later if
1942 : // application always uses CurrencyID instead of BankSymbol.
1943 285 : if (!bLegacy && !isIso4217(str))
1944 0 : incError( "BankSymbol is not ISO 4217");
1945 285 : str = currencyNode -> findNode ("CurrencyName") -> getValue();
1946 285 : of.writeParameter("currencyName", str, nbOfCurrencies);
1947 285 : str = currencyNode -> findNode ("DecimalPlaces") -> getValue();
1948 285 : sal_Int16 nDecimalPlaces = (sal_Int16)str.toInt32();
1949 285 : of.writeIntParameter("currencyDecimalPlaces", nbOfCurrencies, nDecimalPlaces);
1950 285 : of.writeAsciiString("\n");
1951 : };
1952 :
1953 192 : if (!bTheDefault)
1954 0 : incError( "Currency: no default currency.");
1955 192 : if (!bTheCompatible)
1956 0 : incError( "Currency: no currency flagged as usedInCompatibleFormatCodes.");
1957 :
1958 192 : of.writeAsciiString("static const sal_Int16 currencyCount = ");
1959 192 : of.writeInt(nbOfCurrencies);
1960 192 : of.writeAsciiString(";\n\n");
1961 192 : of.writeAsciiString("static const sal_Unicode* currencies[] = {\n");
1962 477 : for(i = 0; i < nbOfCurrencies; i++) {
1963 285 : of.writeAsciiString("\tcurrencyID");
1964 285 : of.writeInt(i);
1965 285 : of.writeAsciiString(",\n");
1966 285 : of.writeAsciiString("\tcurrencySymbol");
1967 285 : of.writeInt(i);
1968 285 : of.writeAsciiString(",\n");
1969 285 : of.writeAsciiString("\tbankSymbol");
1970 285 : of.writeInt(i);
1971 285 : of.writeAsciiString(",\n");
1972 285 : of.writeAsciiString("\tcurrencyName");
1973 285 : of.writeInt(i);
1974 285 : of.writeAsciiString(",\n");
1975 285 : of.writeAsciiString("\tdefaultCurrency");
1976 285 : of.writeInt(i);
1977 285 : of.writeAsciiString(",\n");
1978 285 : of.writeAsciiString("\tdefaultCurrencyUsedInCompatibleFormatCodes");
1979 285 : of.writeInt(i);
1980 285 : of.writeAsciiString(",\n");
1981 285 : of.writeAsciiString("\tcurrencyDecimalPlaces");
1982 285 : of.writeInt(i);
1983 285 : of.writeAsciiString(",\n");
1984 285 : of.writeAsciiString("\tdefaultCurrencyLegacyOnly");
1985 285 : of.writeInt(i);
1986 285 : of.writeAsciiString(",\n");
1987 : }
1988 192 : of.writeAsciiString("};\n\n");
1989 384 : of.writeFunction("getAllCurrencies_", "currencyCount", "currencies");
1990 : }
1991 :
1992 231 : void LCTransliterationNode::generateCode (const OFileWriter &of) const
1993 : {
1994 231 : OUString useLocale = getAttr().getValueByName("ref");
1995 231 : if (!useLocale.isEmpty()) {
1996 132 : useLocale = useLocale.replace( '-', '_');
1997 132 : of.writeRefFunction("getTransliterations_", useLocale);
1998 363 : return;
1999 : }
2000 99 : sal_Int16 nbOfModules = 0;
2001 198 : OUString str;
2002 : sal_Int16 i;
2003 :
2004 647 : for ( i = 0; i < getNumberOfChildren(); i++,nbOfModules++) {
2005 548 : LocaleNode * transNode = getChildAt (i);
2006 548 : str = transNode->getAttr().getValueByIndex(0);
2007 548 : of.writeParameter("Transliteration", str, nbOfModules);
2008 : }
2009 99 : of.writeAsciiString("static const sal_Int16 nbOfTransliterations = ");
2010 99 : of.writeInt(nbOfModules);
2011 99 : of.writeAsciiString(";\n\n");
2012 :
2013 99 : of.writeAsciiString("\nstatic const sal_Unicode* LCTransliterationsArray[] = {\n");
2014 647 : for( i = 0; i < nbOfModules; i++) {
2015 548 : of.writeAsciiString("\tTransliteration");
2016 548 : of.writeInt(i);
2017 548 : of.writeAsciiString(",\n");
2018 : }
2019 99 : of.writeAsciiString("};\n\n");
2020 198 : of.writeFunction("getTransliterations_", "nbOfTransliterations", "LCTransliterationsArray");
2021 : }
2022 :
2023 : struct NameValuePair {
2024 : const sal_Char *name;
2025 : const sal_Char *value;
2026 : };
2027 : static const NameValuePair ReserveWord[] = {
2028 : { "trueWord", "true" },
2029 : { "falseWord", "false" },
2030 : { "quarter1Word", "1st quarter" },
2031 : { "quarter2Word", "2nd quarter" },
2032 : { "quarter3Word", "3rd quarter" },
2033 : { "quarter4Word", "4th quarter" },
2034 : { "aboveWord", "above" },
2035 : { "belowWord", "below" },
2036 : { "quarter1Abbreviation", "Q1" },
2037 : { "quarter2Abbreviation", "Q2" },
2038 : { "quarter3Abbreviation", "Q3" },
2039 : { "quarter4Abbreviation", "Q4" }
2040 : };
2041 :
2042 231 : void LCMiscNode::generateCode (const OFileWriter &of) const
2043 : {
2044 231 : OUString useLocale = getAttr().getValueByName("ref");
2045 231 : if (!useLocale.isEmpty()) {
2046 68 : useLocale = useLocale.replace( '-', '_');
2047 68 : of.writeRefFunction("getForbiddenCharacters_", useLocale);
2048 68 : of.writeRefFunction("getBreakIteratorRules_", useLocale);
2049 68 : of.writeRefFunction("getReservedWords_", useLocale);
2050 299 : return;
2051 : }
2052 163 : const LocaleNode * reserveNode = findNode("ReservedWords");
2053 163 : if (!reserveNode)
2054 0 : incError( "No ReservedWords element."); // should not happen if validated..
2055 163 : const LocaleNode * forbidNode = findNode("ForbiddenCharacters");
2056 163 : const LocaleNode * breakNode = findNode("BreakIteratorRules");
2057 :
2058 163 : bool bEnglishLocale = (strncmp( of.getLocale(), "en_", 3) == 0);
2059 :
2060 163 : sal_Int16 nbOfWords = 0;
2061 326 : OUString str;
2062 : sal_Int16 i;
2063 :
2064 2119 : for ( i = 0; i < sal_Int16(SAL_N_ELEMENTS(ReserveWord)); i++,nbOfWords++) {
2065 : const LocaleNode * curNode = (reserveNode ? reserveNode->findNode(
2066 1956 : ReserveWord[i].name) : 0);
2067 1956 : if (!curNode)
2068 : fprintf( stderr,
2069 : "Warning: No %s in ReservedWords, using en_US default: \"%s\".\n",
2070 0 : ReserveWord[i].name, ReserveWord[i].value);
2071 1956 : str = curNode ? curNode -> getValue() : OUString::createFromAscii(ReserveWord[i].value);
2072 1956 : if (str.isEmpty())
2073 : {
2074 0 : ++nError;
2075 0 : fprintf( stderr, "Error: No content for ReservedWords %s.\n", ReserveWord[i].name);
2076 : }
2077 1956 : of.writeParameter("ReservedWord", str, nbOfWords);
2078 : // "true", ..., "below" trigger untranslated warning.
2079 3244 : if (!bEnglishLocale && curNode && (0 <= i && i <= 7) &&
2080 1288 : str.equalsIgnoreAsciiCaseAscii( ReserveWord[i].value))
2081 : {
2082 : fprintf( stderr,
2083 : "Warning: ReservedWord %s seems to be untranslated \"%s\".\n",
2084 35 : ReserveWord[i].name, ReserveWord[i].value);
2085 : }
2086 : }
2087 163 : of.writeAsciiString("static const sal_Int16 nbOfReservedWords = ");
2088 163 : of.writeInt(nbOfWords);
2089 163 : of.writeAsciiString(";\n\n");
2090 163 : of.writeAsciiString("\nstatic const sal_Unicode* LCReservedWordsArray[] = {\n");
2091 2119 : for( i = 0; i < nbOfWords; i++) {
2092 1956 : of.writeAsciiString("\tReservedWord");
2093 1956 : of.writeInt(i);
2094 1956 : of.writeAsciiString(",\n");
2095 : }
2096 163 : of.writeAsciiString("};\n\n");
2097 163 : of.writeFunction("getReservedWords_", "nbOfReservedWords", "LCReservedWordsArray");
2098 :
2099 163 : if (forbidNode) {
2100 4 : of.writeParameter( "forbiddenBegin", forbidNode -> getChildAt(0)->getValue());
2101 4 : of.writeParameter( "forbiddenEnd", forbidNode -> getChildAt(1)->getValue());
2102 4 : of.writeParameter( "hangingChars", forbidNode -> getChildAt(2)->getValue());
2103 : } else {
2104 159 : of.writeParameter( "forbiddenBegin", OUString());
2105 159 : of.writeParameter( "forbiddenEnd", OUString());
2106 159 : of.writeParameter( "hangingChars", OUString());
2107 : }
2108 163 : of.writeAsciiString("\nstatic const sal_Unicode* LCForbiddenCharactersArray[] = {\n");
2109 163 : of.writeAsciiString("\tforbiddenBegin,\n");
2110 163 : of.writeAsciiString("\tforbiddenEnd,\n");
2111 163 : of.writeAsciiString("\thangingChars\n");
2112 163 : of.writeAsciiString("};\n\n");
2113 163 : of.writeFunction("getForbiddenCharacters_", "3", "LCForbiddenCharactersArray");
2114 :
2115 163 : if (breakNode) {
2116 14 : of.writeParameter( "EditMode", breakNode -> getChildAt(0)->getValue());
2117 14 : of.writeParameter( "DictionaryMode", breakNode -> getChildAt(1)->getValue());
2118 14 : of.writeParameter( "WordCountMode", breakNode -> getChildAt(2)->getValue());
2119 14 : of.writeParameter( "CharacterMode", breakNode -> getChildAt(3)->getValue());
2120 14 : of.writeParameter( "LineMode", breakNode -> getChildAt(4)->getValue());
2121 : } else {
2122 149 : of.writeParameter( "EditMode", OUString());
2123 149 : of.writeParameter( "DictionaryMode", OUString());
2124 149 : of.writeParameter( "WordCountMode", OUString());
2125 149 : of.writeParameter( "CharacterMode", OUString());
2126 149 : of.writeParameter( "LineMode", OUString());
2127 : }
2128 163 : of.writeAsciiString("\nstatic const sal_Unicode* LCBreakIteratorRulesArray[] = {\n");
2129 163 : of.writeAsciiString("\tEditMode,\n");
2130 163 : of.writeAsciiString("\tDictionaryMode,\n");
2131 163 : of.writeAsciiString("\tWordCountMode,\n");
2132 163 : of.writeAsciiString("\tCharacterMode,\n");
2133 163 : of.writeAsciiString("\tLineMode\n");
2134 163 : of.writeAsciiString("};\n\n");
2135 326 : of.writeFunction("getBreakIteratorRules_", "5", "LCBreakIteratorRulesArray");
2136 :
2137 : }
2138 :
2139 231 : void LCNumberingLevelNode::generateCode (const OFileWriter &of) const
2140 : {
2141 231 : of.writeAsciiString("// ---> ContinuousNumbering\n");
2142 231 : OUString useLocale = getAttr().getValueByName("ref");
2143 231 : if (!useLocale.isEmpty()) {
2144 156 : useLocale = useLocale.replace( '-', '_');
2145 156 : of.writeRefFunction2("getContinuousNumberingLevels_", useLocale);
2146 387 : return;
2147 : }
2148 :
2149 : // hard code number of attributes per style.
2150 75 : const int nAttributes = 5;
2151 75 : const char* attr[ nAttributes ] = { "Prefix", "NumType", "Suffix", "Transliteration", "NatNum" };
2152 :
2153 : // record each attribute of each style in a static C++ variable.
2154 : // determine number of styles on the fly.
2155 75 : sal_Int32 nStyles = getNumberOfChildren();
2156 : sal_Int32 i;
2157 :
2158 685 : for( i = 0; i < nStyles; ++i )
2159 : {
2160 610 : const Attr &q = getChildAt( i )->getAttr();
2161 3660 : for( sal_Int32 j=0; j<nAttributes; ++j )
2162 : {
2163 3050 : const char* name = attr[j];
2164 3050 : OUString value = q.getValueByName( name );
2165 3050 : of.writeParameter("continuous", name, value, sal::static_int_cast<sal_Int16>(i) );
2166 3050 : }
2167 : }
2168 :
2169 : // record number of styles and attributes.
2170 75 : of.writeAsciiString("static const sal_Int16 continuousNbOfStyles = ");
2171 75 : of.writeInt( sal::static_int_cast<sal_Int16>( nStyles ) );
2172 75 : of.writeAsciiString(";\n\n");
2173 75 : of.writeAsciiString("static const sal_Int16 continuousNbOfAttributesPerStyle = ");
2174 75 : of.writeInt( nAttributes );
2175 75 : of.writeAsciiString(";\n\n");
2176 :
2177 : // generate code. (intermediate arrays)
2178 685 : for( i=0; i<nStyles; i++ )
2179 : {
2180 610 : of.writeAsciiString("\nstatic const sal_Unicode* continuousStyle" );
2181 610 : of.writeInt( sal::static_int_cast<sal_Int16>(i) );
2182 610 : of.writeAsciiString("[] = {\n");
2183 3660 : for( sal_Int32 j=0; j<nAttributes; j++)
2184 : {
2185 3050 : of.writeAsciiString("\t");
2186 3050 : of.writeAsciiString( "continuous" );
2187 3050 : of.writeAsciiString( attr[j] );
2188 3050 : of.writeInt(sal::static_int_cast<sal_Int16>(i));
2189 3050 : of.writeAsciiString(",\n");
2190 : }
2191 610 : of.writeAsciiString("\t0\n};\n\n");
2192 : }
2193 :
2194 : // generate code. (top-level array)
2195 75 : of.writeAsciiString("\n");
2196 75 : of.writeAsciiString("static const sal_Unicode** LCContinuousNumberingLevelsArray[] = {\n" );
2197 685 : for( i=0; i<nStyles; i++ )
2198 : {
2199 610 : of.writeAsciiString( "\t" );
2200 610 : of.writeAsciiString( "continuousStyle" );
2201 610 : of.writeInt( sal::static_int_cast<sal_Int16>(i) );
2202 610 : of.writeAsciiString( ",\n");
2203 : }
2204 75 : of.writeAsciiString("\t0\n};\n\n");
2205 : of.writeFunction2("getContinuousNumberingLevels_", "continuousNbOfStyles",
2206 75 : "continuousNbOfAttributesPerStyle", "LCContinuousNumberingLevelsArray");
2207 : }
2208 :
2209 :
2210 231 : void LCOutlineNumberingLevelNode::generateCode (const OFileWriter &of) const
2211 : {
2212 231 : of.writeAsciiString("// ---> OutlineNumbering\n");
2213 231 : OUString useLocale = getAttr().getValueByName("ref");
2214 231 : if (!useLocale.isEmpty()) {
2215 202 : useLocale = useLocale.replace( '-', '_');
2216 202 : of.writeRefFunction3("getOutlineNumberingLevels_", useLocale);
2217 433 : return;
2218 : }
2219 :
2220 : // hardcode number of attributes per level
2221 29 : const int nAttributes = 11;
2222 : const char* attr[ nAttributes ] =
2223 : {
2224 : "Prefix",
2225 : "NumType",
2226 : "Suffix",
2227 : "BulletChar",
2228 : "BulletFontName",
2229 : "ParentNumbering",
2230 : "LeftMargin",
2231 : "SymbolTextDistance",
2232 : "FirstLineOffset",
2233 : "Transliteration",
2234 : "NatNum",
2235 29 : };
2236 :
2237 : // record each attribute of each level of each style in a static C++ variable.
2238 : // determine number of styles and number of levels per style on the fly.
2239 29 : sal_Int32 nStyles = getNumberOfChildren();
2240 58 : vector<sal_Int32> nLevels; // may be different for each style?
2241 269 : for( sal_Int32 i = 0; i < nStyles; i++ )
2242 : {
2243 240 : LocaleNode* p = getChildAt( i );
2244 240 : nLevels.push_back( p->getNumberOfChildren() );
2245 1440 : for( sal_Int32 j=0; j<nLevels.back(); j++ )
2246 : {
2247 1200 : const Attr& q = p->getChildAt( j )->getAttr();
2248 14400 : for( sal_Int32 k=0; k<nAttributes; ++k )
2249 : {
2250 13200 : const char* name = attr[k];
2251 13200 : OUString value = q.getValueByName( name );
2252 : of.writeParameter("outline", name, value,
2253 13200 : sal::static_int_cast<sal_Int16>(i),
2254 26400 : sal::static_int_cast<sal_Int16>(j) );
2255 13200 : }
2256 : }
2257 : }
2258 :
2259 : // verify that each style has the same number of levels.
2260 269 : for( size_t i=0; i<nLevels.size(); i++ )
2261 : {
2262 240 : if( nLevels[0] != nLevels[i] )
2263 : {
2264 0 : incError( "Numbering levels don't match.");
2265 : }
2266 : }
2267 :
2268 : // record number of attributes, levels, and styles.
2269 29 : of.writeAsciiString("static const sal_Int16 outlineNbOfStyles = ");
2270 29 : of.writeInt( sal::static_int_cast<sal_Int16>( nStyles ) );
2271 29 : of.writeAsciiString(";\n\n");
2272 29 : of.writeAsciiString("static const sal_Int16 outlineNbOfLevelsPerStyle = ");
2273 29 : of.writeInt( sal::static_int_cast<sal_Int16>( nLevels.back() ) );
2274 29 : of.writeAsciiString(";\n\n");
2275 29 : of.writeAsciiString("static const sal_Int16 outlineNbOfAttributesPerLevel = ");
2276 29 : of.writeInt( nAttributes );
2277 29 : of.writeAsciiString(";\n\n");
2278 :
2279 : // too complicated for now...
2280 : // of.writeAsciiString("static const sal_Int16 nbOfOutlineNumberingLevels[] = { ");
2281 : // for( sal_Int32 j=0; j<nStyles; j++ )
2282 : // {
2283 : // of.writeInt( nLevels[j] );
2284 : // of.writeAsciiString(", ");
2285 : // }
2286 : // of.writeAsciiString("};\n\n");
2287 :
2288 :
2289 269 : for( sal_Int32 i=0; i<nStyles; i++ )
2290 : {
2291 1440 : for( sal_Int32 j=0; j<nLevels.back(); j++ )
2292 : {
2293 1200 : of.writeAsciiString("static const sal_Unicode* outline");
2294 1200 : of.writeAsciiString("Style");
2295 1200 : of.writeInt( sal::static_int_cast<sal_Int16>(i) );
2296 1200 : of.writeAsciiString("Level");
2297 1200 : of.writeInt( sal::static_int_cast<sal_Int16>(j) );
2298 1200 : of.writeAsciiString("[] = { ");
2299 :
2300 14400 : for( sal_Int32 k=0; k<nAttributes; k++ )
2301 : {
2302 13200 : of.writeAsciiString( "outline" );
2303 13200 : of.writeAsciiString( attr[k] );
2304 13200 : of.writeInt( sal::static_int_cast<sal_Int16>(i) );
2305 13200 : of.writeInt( sal::static_int_cast<sal_Int16>(j) );
2306 13200 : of.writeAsciiString(", ");
2307 : }
2308 1200 : of.writeAsciiString("NULL };\n");
2309 : }
2310 : }
2311 :
2312 29 : of.writeAsciiString("\n");
2313 :
2314 :
2315 269 : for( sal_Int32 i=0; i<nStyles; i++ )
2316 : {
2317 240 : of.writeAsciiString("static const sal_Unicode** outline");
2318 240 : of.writeAsciiString( "Style" );
2319 240 : of.writeInt( sal::static_int_cast<sal_Int16>(i) );
2320 240 : of.writeAsciiString("[] = { ");
2321 :
2322 1440 : for( sal_Int32 j=0; j<nLevels.back(); j++ )
2323 : {
2324 1200 : of.writeAsciiString("outlineStyle");
2325 1200 : of.writeInt( sal::static_int_cast<sal_Int16>(i) );
2326 1200 : of.writeAsciiString("Level");
2327 1200 : of.writeInt( sal::static_int_cast<sal_Int16>(j) );
2328 1200 : of.writeAsciiString(", ");
2329 : }
2330 240 : of.writeAsciiString("NULL };\n");
2331 : }
2332 29 : of.writeAsciiString("\n");
2333 :
2334 29 : of.writeAsciiString("static const sal_Unicode*** LCOutlineNumberingLevelsArray[] = {\n" );
2335 269 : for( sal_Int32 i=0; i<nStyles; i++ )
2336 : {
2337 240 : of.writeAsciiString( "\t" );
2338 240 : of.writeAsciiString( "outlineStyle" );
2339 240 : of.writeInt( sal::static_int_cast<sal_Int16>(i) );
2340 240 : of.writeAsciiString(",\n");
2341 : }
2342 29 : of.writeAsciiString("\tNULL\n};\n\n");
2343 : of.writeFunction3("getOutlineNumberingLevels_", "outlineNbOfStyles", "outlineNbOfLevelsPerStyle",
2344 58 : "outlineNbOfAttributesPerLevel", "LCOutlineNumberingLevelsArray");
2345 : }
2346 :
2347 49509 : Attr::Attr (const Reference< XAttributeList > & attr) {
2348 49509 : sal_Int16 len = attr->getLength();
2349 49509 : name.realloc (len);
2350 49509 : value.realloc (len);
2351 103892 : for (sal_Int16 i =0; i< len;i++) {
2352 54383 : name[i] = attr->getNameByIndex(i);
2353 54383 : value[i] = attr -> getValueByIndex(i);
2354 : }
2355 49509 : }
2356 :
2357 60550 : const OUString& Attr::getValueByName (const sal_Char *str) const {
2358 60550 : static OUString empty;
2359 60550 : sal_Int32 len = name.getLength();
2360 208293 : for (sal_Int32 i = 0;i<len;i++)
2361 201152 : if (name[i].equalsAscii(str))
2362 53409 : return value[i];
2363 7141 : return empty;
2364 : }
2365 :
2366 0 : sal_Int32 Attr::getLength() const{
2367 0 : return name.getLength();
2368 : }
2369 :
2370 0 : const OUString& Attr::getTypeByIndex (sal_Int32 idx) const {
2371 0 : return name[idx];
2372 : }
2373 :
2374 548 : const OUString& Attr::getValueByIndex (sal_Int32 idx) const
2375 : {
2376 548 : return value[idx];
2377 693 : }
2378 :
2379 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|