]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/text/DecimalFormat.java
go
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / text / DecimalFormat.java
1 //##header J2SE15
2 /*
3  *******************************************************************************
4  * Copyright (C) 1996-2009, International Business Machines Corporation and    *
5  * others. All Rights Reserved.                                                *
6  *******************************************************************************
7  */
8 package com.ibm.icu.text;
9
10 import java.io.IOException;
11 import java.io.ObjectInputStream;
12 import java.math.BigInteger;
13 import java.text.ChoiceFormat;
14 import java.text.FieldPosition;
15 import java.text.ParsePosition;
16 import java.util.HashSet;
17 import java.util.Iterator;
18 import java.util.Set;
19
20 //#if defined(FOUNDATION10)
21 //#else
22 import java.io.ObjectOutputStream;
23 //#endif
24
25 //#if defined(FOUNDATION10) || defined(J2SE13)
26 //#else
27 import java.text.AttributedCharacterIterator;
28 import java.text.AttributedString;
29 import java.text.Format;
30 import java.util.ArrayList;
31 //#endif
32
33 import com.ibm.icu.impl.UCharacterProperty;
34 import com.ibm.icu.impl.Utility;
35 import com.ibm.icu.lang.UCharacter;
36 import com.ibm.icu.math.BigDecimal;
37 import com.ibm.icu.util.Currency;
38 import com.ibm.icu.util.CurrencyAmount;
39 import com.ibm.icu.util.ULocale;
40 import com.ibm.icu.math.MathContext;
41
42 //This is an enhanced version of DecimalFormat that is based on the standard version in the JDK. 
43 /**
44  * <code>DecimalFormat</code> is a concrete subclass of
45  * {@link NumberFormat} that formats decimal numbers. It has a variety of
46  * features designed to make it possible to parse and format numbers in any
47  * locale, including support for Western, Arabic, or Indic digits.  It also
48  * supports different flavors of numbers, including integers ("123"),
49  * fixed-point numbers ("123.4"), scientific notation ("1.23E4"), percentages
50  * ("12%"), and currency amounts ("$123.00", "USD123.00", "123.00 US dollars").
51  * All of these flavors can be easily localized.
52  *
53  * 
54  * <p>To obtain a {@link NumberFormat} for a specific locale (including the
55  * default locale) call one of <code>NumberFormat</code>'s factory methods such
56  * as {@link NumberFormat#getInstance}. Do not call the <code>DecimalFormat</code>
57  * constructors directly, unless you know what you are doing, since the
58  * {@link NumberFormat} factory methods may return subclasses other than
59  * <code>DecimalFormat</code>. If you need to customize the format object, do
60  * something like this:
61  *
62  * <blockquote><pre>
63  * NumberFormat f = NumberFormat.getInstance(loc);
64  * if (f instanceof DecimalFormat) {
65  *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
66  * }</pre></blockquote>
67  *
68  * <p><strong>Example Usage</strong>
69  *
70  * <blockquote><pre>
71  * <strong>// Print out a number using the localized number, currency,
72  * // and percent format for each locale</strong>
73  * Locale[] locales = NumberFormat.getAvailableLocales();
74  * double myNumber = -1234.56;
75  * NumberFormat format;
76  * for (int j=0; j<3; ++j) {
77  *     System.out.println("FORMAT");
78  *     for (int i = 0; i < locales.length; ++i) {
79  *         if (locales[i].getCountry().length() == 0) {
80  *            // Skip language-only locales
81  *            continue;
82  *         }
83  *         System.out.print(locales[i].getDisplayName());
84  *         switch (j) {
85  *         case 0:
86  *             format = NumberFormat.getInstance(locales[i]); break;
87  *         case 1:
88  *             format = NumberFormat.getCurrencyInstance(locales[i]); break;
89  *         default:
90  *             format = NumberFormat.getPercentInstance(locales[i]); break;
91  *         }
92  *         try {
93  *             // Assume format is a DecimalFormat
94  *             System.out.print(": " + ((DecimalFormat) format).toPattern()
95  *                              + " -> " + form.format(myNumber));
96  *         } catch (Exception e) {}
97  *         try {
98  *             System.out.println(" -> " + format.parse(form.format(myNumber)));
99  *         } catch (ParseException e) {}
100  *     }
101  * }</pre></blockquote>
102  *
103  * <P>
104  * Another example use getInstance(style)
105  * <P>
106  * <pre>
107  * <strong>// Print out a number using the localized number, currency,
108  * // percent, scientific, integer, iso currency, and plural currency
109  * // format for each locale</strong>
110  * ULocale locale = new ULocale("en_US");
111  * double myNumber = 1234.56;
112  * for (int j=NumberFormat.NUMBERSTYLE; j<=NumberFormat.PLURALCURRENCYSTYLE; ++j) {
113  *     NumberFormat format = NumberFormat.getInstance(locale, j);
114  *     try {
115  *         // Assume format is a DecimalFormat
116  *         System.out.print(": " + ((DecimalFormat) format).toPattern()
117  *                          + " -> " + form.format(myNumber));
118  *     } catch (Exception e) {}
119  *     try {
120  *         System.out.println(" -> " + format.parse(form.format(myNumber)));
121  *     } catch (ParseException e) {}
122  * }</pre></blockquote>
123  *
124  * <h4>Patterns</h4>
125  *
126  * <p>A <code>DecimalFormat</code> consists of a <em>pattern</em> and a set of
127  * <em>symbols</em>.  The pattern may be set directly using
128  * {@link #applyPattern}, or indirectly using other API methods which
129  * manipulate aspects of the pattern, such as the minimum number of integer
130  * digits.  The symbols are stored in a {@link DecimalFormatSymbols}
131  * object.  When using the {@link NumberFormat} factory methods, the
132  * pattern and symbols are read from ICU's locale data.
133  * 
134  * <h4>Special Pattern Characters</h4>
135  *
136  * <p>Many characters in a pattern are taken literally; they are matched during
137  * parsing and output unchanged during formatting.  Special characters, on the
138  * other hand, stand for other characters, strings, or classes of characters.
139  * For example, the '#' character is replaced by a localized digit.  Often the
140  * replacement character is the same as the pattern character; in the U.S. locale,
141  * the ',' grouping character is replaced by ','.  However, the replacement is
142  * still happening, and if the symbols are modified, the grouping character
143  * changes.  Some special characters affect the behavior of the formatter by
144  * their presence; for example, if the percent character is seen, then the
145  * value is multiplied by 100 before being displayed.
146  *
147  * <p>To insert a special character in a pattern as a literal, that is, without
148  * any special meaning, the character must be quoted.  There are some exceptions to
149  * this which are noted below.
150  *
151  * <p>The characters listed here are used in non-localized patterns.  Localized
152  * patterns use the corresponding characters taken from this formatter's
153  * {@link DecimalFormatSymbols} object instead, and these characters lose
154  * their special status.  Two exceptions are the currency sign and quote, which
155  * are not localized.
156  *
157  * <blockquote>
158  * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
159  *  location, localized, and meaning.">
160  *   <tr bgcolor="#ccccff">
161  *     <th align=left>Symbol
162  *     <th align=left>Location
163  *     <th align=left>Localized?
164  *     <th align=left>Meaning
165  *   <tr valign=top>
166  *     <td><code>0</code>
167  *     <td>Number
168  *     <td>Yes
169  *     <td>Digit
170  *   <tr valign=top bgcolor="#eeeeff">
171  *     <td><code>1-9</code>
172  *     <td>Number
173  *     <td>Yes
174  *     <td>'1' through '9' indicate rounding. 
175  *         
176  *   <tr valign=top>
177  *     <td><code>@</code>
178  *     <td>Number
179  *     <td>No
180  *     <td>Significant digit
181  *   <tr valign=top bgcolor="#eeeeff">
182  *     <td><code>#</code>
183  *     <td>Number
184  *     <td>Yes
185  *     <td>Digit, zero shows as absent
186  *   <tr valign=top>
187  *     <td><code>.</code>
188  *     <td>Number
189  *     <td>Yes
190  *     <td>Decimal separator or monetary decimal separator
191  *   <tr valign=top bgcolor="#eeeeff">
192  *     <td><code>-</code>
193  *     <td>Number
194  *     <td>Yes
195  *     <td>Minus sign
196  *   <tr valign=top>
197  *     <td><code>,</code>
198  *     <td>Number
199  *     <td>Yes
200  *     <td>Grouping separator
201  *   <tr valign=top bgcolor="#eeeeff">
202  *     <td><code>E</code>
203  *     <td>Number
204  *     <td>Yes
205  *     <td>Separates mantissa and exponent in scientific notation.
206  *         <em>Need not be quoted in prefix or suffix.</em>
207  *   <tr valign=top>
208  *     <td><code>+</code>
209  *     <td>Exponent
210  *     <td>Yes
211  *     <td>Prefix positive exponents with localized plus sign.
212  *         <em>Need not be quoted in prefix or suffix.</em>
213  *   <tr valign=top bgcolor="#eeeeff">
214  *     <td><code>;</code>
215  *     <td>Subpattern boundary
216  *     <td>Yes
217  *     <td>Separates positive and negative subpatterns
218  *   <tr valign=top>
219  *     <td><code>%</code>
220  *     <td>Prefix or suffix
221  *     <td>Yes
222  *     <td>Multiply by 100 and show as percentage
223  *   <tr valign=top bgcolor="#eeeeff">
224  *     <td><code>&#92;u2030</code>
225  *     <td>Prefix or suffix
226  *     <td>Yes
227  *     <td>Multiply by 1000 and show as per mille
228  *   <tr valign=top>
229  *     <td><code>&#164;</code> (<code>&#92;u00A4</code>)
230  *     <td>Prefix or suffix
231  *     <td>No
232  *     <td>Currency sign, replaced by currency symbol.  If
233  *         doubled, replaced by international currency symbol.
234  *         If tripled, replaced by currency plural names, for example,
235  *         "US dollar" or "US dollars" for America.
236  *         If present in a pattern, the monetary decimal separator
237  *         is used instead of the decimal separator.
238  *   <tr valign=top bgcolor="#eeeeff">
239  *     <td><code>'</code>
240  *     <td>Prefix or suffix
241  *     <td>No
242  *     <td>Used to quote special characters in a prefix or suffix,
243  *         for example, <code>"'#'#"</code> formats 123 to
244  *         <code>"#123"</code>.  To create a single quote
245  *         itself, use two in a row: <code>"# o''clock"</code>.
246  *   <tr valign=top>
247  *     <td><code>*</code>
248  *     <td>Prefix or suffix boundary
249  *     <td>Yes
250  *     <td>Pad escape, precedes pad character
251  * </table>
252  * </blockquote>
253  *
254  * <p>A <code>DecimalFormat</code> pattern contains a postive and negative
255  * subpattern, for example, "#,##0.00;(#,##0.00)".  Each subpattern has a
256  * prefix, a numeric part, and a suffix.  If there is no explicit negative
257  * subpattern, the negative subpattern is the localized minus sign prefixed to the
258  * positive subpattern. That is, "0.00" alone is equivalent to "0.00;-0.00".  If there
259  * is an explicit negative subpattern, it serves only to specify the negative
260  * prefix and suffix; the number of digits, minimal digits, and other
261  * characteristics are ignored in the negative subpattern. That means that
262  * "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)".
263  *
264  * <p>The prefixes, suffixes, and various symbols used for infinity, digits,
265  * thousands separators, decimal separators, etc. may be set to arbitrary
266  * values, and they will appear properly during formatting.  However, care must
267  * be taken that the symbols and strings do not conflict, or parsing will be
268  * unreliable.  For example, either the positive and negative prefixes or the
269  * suffixes must be distinct for {@link #parse} to be able
270  * to distinguish positive from negative values.  Another example is that the
271  * decimal separator and thousands separator should be distinct characters, or
272  * parsing will be impossible.
273  *
274  * <p>The <em>grouping separator</em> is a character that separates clusters of
275  * integer digits to make large numbers more legible.  It commonly used for
276  * thousands, but in some locales it separates ten-thousands.  The <em>grouping
277  * size</em> is the number of digits between the grouping separators, such as 3
278  * for "100,000,000" or 4 for "1 0000 0000". There are actually two different
279  * grouping sizes: One used for the least significant integer digits, the
280  * <em>primary grouping size</em>, and one used for all others, the
281  * <em>secondary grouping size</em>.  In most locales these are the same, but
282  * sometimes they are different. For example, if the primary grouping interval
283  * is 3, and the secondary is 2, then this corresponds to the pattern
284  * "#,##,##0", and the number 123456789 is formatted as "12,34,56,789".  If a
285  * pattern contains multiple grouping separators, the interval between the last
286  * one and the end of the integer defines the primary grouping size, and the
287  * interval between the last two defines the secondary grouping size. All others
288  * are ignored, so "#,##,###,####" == "###,###,####" == "##,#,###,####".
289  *
290  * <p>Illegal patterns, such as "#.#.#" or "#.###,###", will cause
291  * <code>DecimalFormat</code> to throw an {@link IllegalArgumentException}
292  * with a message that describes the problem.
293  *
294  * <h4>Pattern BNF</h4>
295  *
296  * <pre>
297  * pattern    := subpattern (';' subpattern)?
298  * subpattern := prefix? number exponent? suffix?
299  * number     := (integer ('.' fraction)?) | sigDigits
300  * prefix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
301  * suffix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
302  * integer    := '#'* '0'* '0'
303  * fraction   := '0'* '#'*
304  * sigDigits  := '#'* '@' '@'* '#'*
305  * exponent   := 'E' '+'? '0'* '0'
306  * padSpec    := '*' padChar
307  * padChar    := '&#92;u0000'..'&#92;uFFFD' - quote
308  * &#32;
309  * Notation:
310  *   X*       0 or more instances of X
311  *   X?       0 or 1 instances of X
312  *   X|Y      either X or Y
313  *   C..D     any character from C up to D, inclusive
314  *   S-T      characters in S, except those in T
315  * </pre>
316  * The first subpattern is for positive numbers. The second (optional)
317  * subpattern is for negative numbers.
318  * 
319  * <p>Not indicated in the BNF syntax above:
320  *
321  * <ul><li>The grouping separator ',' can occur inside the integer and
322  * sigDigits elements, between any two pattern characters of that
323  * element, as long as the integer or sigDigits element is not
324  * followed by the exponent element.
325  *
326  * <li>Two grouping intervals are recognized: That between the
327  *     decimal point and the first grouping symbol, and that
328  *     between the first and second grouping symbols. These
329  *     intervals are identical in most locales, but in some
330  *     locales they differ. For example, the pattern
331  *     &quot;#,##,###&quot; formats the number 123456789 as
332  *     &quot;12,34,56,789&quot;.</li>
333  * 
334  * <li>
335  * The pad specifier <code>padSpec</code> may appear before the prefix,
336  * after the prefix, before the suffix, after the suffix, or not at all.
337  *
338  * <li>
339  * In place of '0', the digits '1' through '9' may be used to
340  * indicate a rounding increment.
341  * </ul>
342  *
343  * <h4>Parsing</h4>
344  *
345  * <p><code>DecimalFormat</code> parses all Unicode characters that represent
346  * decimal digits, as defined by {@link UCharacter#digit}.  In addition,
347  * <code>DecimalFormat</code> also recognizes as digits the ten consecutive
348  * characters starting with the localized zero digit defined in the
349  * {@link DecimalFormatSymbols} object.  During formatting, the
350  * {@link DecimalFormatSymbols}-based digits are output.
351  *
352  * <p>During parsing, grouping separators are ignored.
353  *
354  * <p>For currency parsing, the formatter is able to parse every currency
355  * style formats no matter which style the formatter is constructed with.
356  * For example, a formatter instance gotten from 
357  * NumberFormat.getInstance(ULocale, NumberFormat.CURRENCYSTYLE) can parse
358  * formats such as "USD1.00" and "3.00 US dollars".
359  *
360  * <p>If {@link #parse(String, ParsePosition)} fails to parse
361  * a string, it returns <code>null</code> and leaves the parse position
362  * unchanged.  The convenience method {@link #parse(String)}
363  * indicates parse failure by throwing a {@link java.text.ParseException}.
364  *
365  * <h4>Formatting</h4>
366  *
367  * <p>Formatting is guided by several parameters, all of which can be
368  * specified either using a pattern or using the API.  The following
369  * description applies to formats that do not use <a href="#sci">scientific
370  * notation</a> or <a href="#sigdig">significant digits</a>.
371  *
372  * <ul><li>If the number of actual integer digits exceeds the
373  * <em>maximum integer digits</em>, then only the least significant
374  * digits are shown.  For example, 1997 is formatted as "97" if the
375  * maximum integer digits is set to 2.
376  *
377  * <li>If the number of actual integer digits is less than the
378  * <em>minimum integer digits</em>, then leading zeros are added.  For
379  * example, 1997 is formatted as "01997" if the minimum integer digits
380  * is set to 5.
381  *
382  * <li>If the number of actual fraction digits exceeds the <em>maximum
383  * fraction digits</em>, then half-even rounding it performed to the
384  * maximum fraction digits.  For example, 0.125 is formatted as "0.12"
385  * if the maximum fraction digits is 2.  This behavior can be changed
386  * by specifying a rounding increment and a rounding mode.
387  *
388  * <li>If the number of actual fraction digits is less than the
389  * <em>minimum fraction digits</em>, then trailing zeros are added.
390  * For example, 0.125 is formatted as "0.1250" if the mimimum fraction
391  * digits is set to 4.
392  *
393  * <li>Trailing fractional zeros are not displayed if they occur
394  * <em>j</em> positions after the decimal, where <em>j</em> is less
395  * than the maximum fraction digits. For example, 0.10004 is
396  * formatted as "0.1" if the maximum fraction digits is four or less.
397  * </ul>
398  * 
399  * <p><strong>Special Values</strong>
400  *
401  * <p><code>NaN</code> is represented as a single character, typically
402  * <code>&#92;uFFFD</code>.  This character is determined by the
403  * {@link DecimalFormatSymbols} object.  This is the only value for which
404  * the prefixes and suffixes are not used.
405  *
406  * <p>Infinity is represented as a single character, typically
407  * <code>&#92;u221E</code>, with the positive or negative prefixes and suffixes
408  * applied.  The infinity character is determined by the
409  * {@link DecimalFormatSymbols} object.
410  *
411  * <a name="sci"><h4>Scientific Notation</h4></a>
412  *
413  * <p>Numbers in scientific notation are expressed as the product of a mantissa
414  * and a power of ten, for example, 1234 can be expressed as 1.234 x 10<sup>3</sup>. The
415  * mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0),
416  * but it need not be.  <code>DecimalFormat</code> supports arbitrary mantissas.
417  * <code>DecimalFormat</code> can be instructed to use scientific
418  * notation through the API or through the pattern.  In a pattern, the exponent
419  * character immediately followed by one or more digit characters indicates
420  * scientific notation.  Example: "0.###E0" formats the number 1234 as
421  * "1.234E3".
422  *
423  * <ul>
424  * <li>The number of digit characters after the exponent character gives the
425  * minimum exponent digit count.  There is no maximum.  Negative exponents are
426  * formatted using the localized minus sign, <em>not</em> the prefix and suffix
427  * from the pattern.  This allows patterns such as "0.###E0 m/s".  To prefix
428  * positive exponents with a localized plus sign, specify '+' between the
429  * exponent and the digits: "0.###E+0" will produce formats "1E+1", "1E+0",
430  * "1E-1", etc.  (In localized patterns, use the localized plus sign rather than
431  * '+'.)
432  *
433  * <li>The minimum number of integer digits is achieved by adjusting the
434  * exponent.  Example: 0.00123 formatted with "00.###E0" yields "12.3E-4".  This
435  * only happens if there is no maximum number of integer digits.  If there is a
436  * maximum, then the minimum number of integer digits is fixed at one.
437  *
438  * <li>The maximum number of integer digits, if present, specifies the exponent
439  * grouping.  The most common use of this is to generate <em>engineering
440  * notation</em>, in which the exponent is a multiple of three, e.g.,
441  * "##0.###E0".  The number 12345 is formatted using "##0.####E0" as "12.345E3".
442  *
443  * <li>When using scientific notation, the formatter controls the
444  * digit counts using significant digits logic.  The maximum number of
445  * significant digits limits the total number of integer and fraction
446  * digits that will be shown in the mantissa; it does not affect
447  * parsing.  For example, 12345 formatted with "##0.##E0" is "12.3E3".
448  * See the section on significant digits for more details.
449  *
450  * <li>The number of significant digits shown is determined as
451  * follows: If areSignificantDigitsUsed() returns false, then the
452  * minimum number of significant digits shown is one, and the maximum
453  * number of significant digits shown is the sum of the <em>minimum
454  * integer</em> and <em>maximum fraction</em> digits, and is
455  * unaffected by the maximum integer digits.  If this sum is zero,
456  * then all significant digits are shown.  If
457  * areSignificantDigitsUsed() returns true, then the significant digit
458  * counts are specified by getMinimumSignificantDigits() and
459  * getMaximumSignificantDigits().  In this case, the number of
460  * integer digits is fixed at one, and there is no exponent grouping.
461  *
462  * <li>Exponential patterns may not contain grouping separators.
463  * </ul>
464  *
465  * <a name="sigdig"><h4>
466  * Significant Digits</h4></a>
467  *
468  * <code>DecimalFormat</code> has two ways of controlling how many
469  * digits are shows: (a) significant digits counts, or (b) integer and
470  * fraction digit counts.  Integer and fraction digit counts are
471  * described above.  When a formatter is using significant digits
472  * counts, the number of integer and fraction digits is not specified
473  * directly, and the formatter settings for these counts are ignored.
474  * Instead, the formatter uses however many integer and fraction
475  * digits are required to display the specified number of significant
476  * digits.  Examples:
477  *
478  * <blockquote>
479  * <table border=0 cellspacing=3 cellpadding=0>
480  *   <tr bgcolor="#ccccff">
481  *     <th align=left>Pattern
482  *     <th align=left>Minimum significant digits
483  *     <th align=left>Maximum significant digits
484  *     <th align=left>Number
485  *     <th align=left>Output of format()
486  *   <tr valign=top>
487  *     <td><code>@@@</code>
488  *     <td>3
489  *     <td>3
490  *     <td>12345
491  *     <td><code>12300</code>
492  *   <tr valign=top bgcolor="#eeeeff">
493  *     <td><code>@@@</code>
494  *     <td>3
495  *     <td>3
496  *     <td>0.12345
497  *     <td><code>0.123</code>
498  *   <tr valign=top>
499  *     <td><code>@@##</code>
500  *     <td>2
501  *     <td>4
502  *     <td>3.14159
503  *     <td><code>3.142</code>
504  *   <tr valign=top bgcolor="#eeeeff">
505  *     <td><code>@@##</code>
506  *     <td>2
507  *     <td>4
508  *     <td>1.23004
509  *     <td><code>1.23</code>
510  * </table>
511  * </blockquote>
512  *
513  * <ul>
514  * <li>Significant digit counts may be expressed using patterns that
515  * specify a minimum and maximum number of significant digits.  These
516  * are indicated by the <code>'@'</code> and <code>'#'</code>
517  * characters.  The minimum number of significant digits is the number
518  * of <code>'@'</code> characters.  The maximum number of significant
519  * digits is the number of <code>'@'</code> characters plus the number
520  * of <code>'#'</code> characters following on the right.  For
521  * example, the pattern <code>"@@@"</code> indicates exactly 3
522  * significant digits.  The pattern <code>"@##"</code> indicates from
523  * 1 to 3 significant digits.  Trailing zero digits to the right of
524  * the decimal separator are suppressed after the minimum number of
525  * significant digits have been shown.  For example, the pattern
526  * <code>"@##"</code> formats the number 0.1203 as
527  * <code>"0.12"</code>.
528  *
529  * <li>If a pattern uses significant digits, it may not contain a
530  * decimal separator, nor the <code>'0'</code> pattern character.
531  * Patterns such as <code>"@00"</code> or <code>"@.###"</code> are
532  * disallowed.
533  *
534  * <li>Any number of <code>'#'</code> characters may be prepended to
535  * the left of the leftmost <code>'@'</code> character.  These have no
536  * effect on the minimum and maximum significant digits counts, but
537  * may be used to position grouping separators.  For example,
538  * <code>"#,#@#"</code> indicates a minimum of one significant digits,
539  * a maximum of two significant digits, and a grouping size of three.
540  *
541  * <li>In order to enable significant digits formatting, use a pattern
542  * containing the <code>'@'</code> pattern character.  Alternatively,
543  * call {@link #setSignificantDigitsUsed setSignificantDigitsUsed(true)}.
544  *
545  * <li>In order to disable significant digits formatting, use a
546  * pattern that does not contain the <code>'@'</code> pattern
547  * character. Alternatively, call {@link #setSignificantDigitsUsed
548  * setSignificantDigitsUsed(false)}.
549  *
550  * <li>The number of significant digits has no effect on parsing.
551  *
552  * <li>Significant digits may be used together with exponential notation. Such
553  * patterns are equivalent to a normal exponential pattern with a minimum and
554  * maximum integer digit count of one, a minimum fraction digit count of
555  * <code>getMinimumSignificantDigits() - 1</code>, and a maximum fraction digit
556  * count of <code>getMaximumSignificantDigits() - 1</code>. For example, the
557  * pattern <code>"@@###E0"</code> is equivalent to <code>"0.0###E0"</code>.
558  *
559  * <li>If signficant digits are in use, then the integer and fraction
560  * digit counts, as set via the API, are ignored.  If significant
561  * digits are not in use, then the signficant digit counts, as set via
562  * the API, are ignored.
563  *
564  * </ul>
565  * 
566  * <h4>
567  * Padding</h4>
568  *
569  * <p><code>DecimalFormat</code> supports padding the result of
570  * {@link #format} to a specific width.  Padding may be specified either
571  * through the API or through the pattern syntax.  In a pattern the pad escape
572  * character, followed by a single pad character, causes padding to be parsed
573  * and formatted.  The pad escape character is '*' in unlocalized patterns, and
574  * can be localized using {@link DecimalFormatSymbols#setPadEscape}.  For
575  * example, <code>"$*x#,##0.00"</code> formats 123 to <code>"$xx123.00"</code>,
576  * and 1234 to <code>"$1,234.00"</code>.
577  *
578  * <ul>
579  * <li>When padding is in effect, the width of the positive subpattern,
580  * including prefix and suffix, determines the format width.  For example, in
581  * the pattern <code>"* #0 o''clock"</code>, the format width is 10.
582  *
583  * <li>The width is counted in 16-bit code units (Java <code>char</code>s).
584  *
585  * <li>Some parameters which usually do not matter have meaning when padding is
586  * used, because the pattern width is significant with padding.  In the pattern
587  * "* ##,##,#,##0.##", the format width is 14.  The initial characters "##,##,"
588  * do not affect the grouping size or maximum integer digits, but they do affect
589  * the format width.
590  *
591  * <li>Padding may be inserted at one of four locations: before the prefix,
592  * after the prefix, before the suffix, or after the suffix.  If padding is
593  * specified in any other location, {@link #applyPattern} throws an {@link
594  * IllegalArgumentException}.  If there is no prefix, before the
595  * prefix and after the prefix are equivalent, likewise for the suffix.
596  *
597  * <li>When specified in a pattern, the 16-bit <code>char</code> immediately
598  * following the pad escape is the pad character. This may be any character,
599  * including a special pattern character. That is, the pad escape
600  * <em>escapes</em> the following character. If there is no character after
601  * the pad escape, then the pattern is illegal.
602  *
603  * </ul>
604  *
605  * <p>
606  * <strong>Rounding</strong>
607  *
608  * <p><code>DecimalFormat</code> supports rounding to a specific increment.  For
609  * example, 1230 rounded to the nearest 50 is 1250.  1.234 rounded to the
610  * nearest 0.65 is 1.3.  The rounding increment may be specified through the API
611  * or in a pattern.  To specify a rounding increment in a pattern, include the
612  * increment in the pattern itself.  "#,#50" specifies a rounding increment of
613  * 50.  "#,##0.05" specifies a rounding increment of 0.05.
614  *
615  * <ul>
616  * <li>Rounding only affects the string produced by formatting.  It does
617  * not affect parsing or change any numerical values.
618  *
619  * <li>A <em>rounding mode</em> determines how values are rounded; see the
620  * {@link com.ibm.icu.math.BigDecimal} documentation for a description of the
621  * modes.  Rounding increments specified in patterns use the default mode,
622  * {@link com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN}.
623  *
624  * <li>Some locales use rounding in their currency formats to reflect the
625  * smallest currency denomination.
626  *
627  * <li>In a pattern, digits '1' through '9' specify rounding, but otherwise
628  * behave identically to digit '0'.
629  * </ul>
630  *
631  * <h4>Synchronization</h4>
632  *
633  * <p><code>DecimalFormat</code> objects are not synchronized.  Multiple
634  * threads should not access one formatter concurrently.
635  *
636  * @see          java.text.Format
637  * @see          NumberFormat
638  * @author       Mark Davis
639  * @author       Alan Liu
640  * @stable ICU 2.0
641  */
642 public class DecimalFormat extends NumberFormat {
643
644     /**
645      * Create a DecimalFormat using the default pattern and symbols
646      * for the default locale. This is a convenient way to obtain a
647      * DecimalFormat when internationalization is not the main concern.
648      * <p>
649      * To obtain standard formats for a given locale, use the factory methods
650      * on NumberFormat such as getNumberInstance. These factories will
651      * return the most appropriate sub-class of NumberFormat for a given
652      * locale.
653      * @see NumberFormat#getInstance
654      * @see NumberFormat#getNumberInstance
655      * @see NumberFormat#getCurrencyInstance
656      * @see NumberFormat#getPercentInstance
657      * @stable ICU 2.0
658      */
659     public DecimalFormat() {
660         // [NEW]
661         ULocale def = ULocale.getDefault();
662         String pattern = getPattern(def, 0);
663         // Always applyPattern after the symbols are set
664         this.symbols = new DecimalFormatSymbols(def);
665         setCurrency(Currency.getInstance(def));
666         applyPatternWithoutExpandAffix(pattern, false);
667         if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
668             currencyPluralInfo = new CurrencyPluralInfo(def);
669             // the exact pattern is not known until the plural count is known.
670             // so, no need to expand affix now.
671         } else {
672             expandAffixAdjustWidth(null);
673         }
674     }
675
676
677     /**
678      * Create a DecimalFormat from the given pattern and the symbols
679      * for the default locale. This is a convenient way to obtain a
680      * DecimalFormat when internationalization is not the main concern.
681      * <p>
682      * To obtain standard formats for a given locale, use the factory methods
683      * on NumberFormat such as getNumberInstance. These factories will
684      * return the most appropriate sub-class of NumberFormat for a given
685      * locale.
686      * @param pattern A non-localized pattern string.
687      * @exception IllegalArgumentException if the given pattern is invalid.
688      * @see NumberFormat#getInstance
689      * @see NumberFormat#getNumberInstance
690      * @see NumberFormat#getCurrencyInstance
691      * @see NumberFormat#getPercentInstance
692      * @stable ICU 2.0
693      */
694     public DecimalFormat(String pattern) {
695         // Always applyPattern after the symbols are set
696         ULocale def = ULocale.getDefault();
697         this.symbols = new DecimalFormatSymbols(def);
698         setCurrency(Currency.getInstance(def));
699         applyPatternWithoutExpandAffix( pattern, false );
700         if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
701             currencyPluralInfo = new CurrencyPluralInfo(def);
702         } else {
703             expandAffixAdjustWidth(null);
704         }
705     }
706
707
708     /**
709      * Create a DecimalFormat from the given pattern and symbols.
710      * Use this constructor when you need to completely customize the
711      * behavior of the format.
712      * <p>
713      * To obtain standard formats for a given
714      * locale, use the factory methods on NumberFormat such as
715      * getInstance or getCurrencyInstance. If you need only minor adjustments
716      * to a standard format, you can modify the format returned by
717      * a NumberFormat factory method.
718      * @param pattern a non-localized pattern string
719      * @param symbols the set of symbols to be used
720      * @exception IllegalArgumentException if the given pattern is invalid
721      * @see NumberFormat#getInstance
722      * @see NumberFormat#getNumberInstance
723      * @see NumberFormat#getCurrencyInstance
724      * @see NumberFormat#getPercentInstance
725      * @see DecimalFormatSymbols
726      * @stable ICU 2.0
727      */
728     public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {
729         createFromPatternAndSymbols(pattern, symbols);
730     }
731
732     private void createFromPatternAndSymbols(String pattern, DecimalFormatSymbols inputSymbols) {
733         // Always applyPattern after the symbols are set
734         symbols = (DecimalFormatSymbols) inputSymbols.clone();
735         setCurrencyForSymbols();
736         applyPatternWithoutExpandAffix(pattern, false);
737         if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
738             currencyPluralInfo = new CurrencyPluralInfo(symbols.getLocale());
739         } else {
740             expandAffixAdjustWidth(null);
741         }
742     }
743
744
745     /**
746      * Create a DecimalFormat from the given pattern, symbols,
747      * information used for currency plural format, and format style.
748      * Use this constructor when you need to completely customize the
749      * behavior of the format.
750      * <p>
751      * To obtain standard formats for a given
752      * locale, use the factory methods on NumberFormat such as
753      * getInstance or getCurrencyInstance. 
754      * <p>
755      * If you need only minor adjustments to a standard format, 
756      * you can modify the format returned by
757      * a NumberFormat factory method using the setters.
758      * <p>
759      * If you want to completely customize a decimal format,
760      * using your own DecimalFormatSymbols (such as group separators) and
761      * your own information for currency plural formatting (such as
762      * plural rule and currency plural patterns), you can use this constructor.
763      * <p> 
764      * @param pattern a non-localized pattern string
765      * @param symbols the set of symbols to be used
766      * @param infoInput the information used for currency plural format, 
767      *                  including currency plural patterns and plural rules.
768      * @param style the decimal formatting style, 
769      *              it is one of the following values:
770      *              NumberFormat.NUMBERSTYLE;
771      *              NumberFormat.CURRENCYSTYLE;
772      *              NumberFormat.PERCENTSTYLE;
773      *              NumberFormat.SCIENTIFICSTYLE;
774      *              NumberFormat.INTEGERSTYLE;
775      *              NumberFormat.ISOCURRENCYSTYLE;
776      *              NumberFormat.PLURALCURRENCYSTYLE;
777      * @draft ICU 4.2
778      * @provisional This API might change or be removed in a future release.
779      */
780     public DecimalFormat(String pattern, DecimalFormatSymbols symbols,
781                          CurrencyPluralInfo infoInput,
782                          int style) {
783         CurrencyPluralInfo info = infoInput;
784         if (style == NumberFormat.PLURALCURRENCYSTYLE) {
785             info = (CurrencyPluralInfo)infoInput.clone();
786         }
787         create(pattern, symbols, info, style);
788     }
789
790
791     private void create(String pattern, DecimalFormatSymbols inputSymbols,
792                         CurrencyPluralInfo info,
793                         int inputStyle) {
794         if (inputStyle != NumberFormat.PLURALCURRENCYSTYLE) {
795             createFromPatternAndSymbols(pattern, inputSymbols);
796         } else {
797             // Always applyPattern after the symbols are set
798             symbols = (DecimalFormatSymbols) inputSymbols.clone();
799             currencyPluralInfo = info;
800             // the pattern used in format is not fixed until formatting,
801             // in which, the number is known and 
802             // will be used to pick the right pattern based on plural count.
803             // Here, set the pattern as the pattern of plural count == "other".
804             // For most locale, the patterns are probably the same for all
805             // plural count. If not, the right pattern need to be re-applied
806             // during format.
807             String currencyPluralPatternForOther = currencyPluralInfo.getCurrencyPluralPattern("other");
808             applyPatternWithoutExpandAffix(currencyPluralPatternForOther,false);
809             setCurrencyForSymbols();
810         }
811         style = inputStyle;
812     }
813
814
815     /*
816      * Create a DecimalFormat for currency plural format 
817      * from the given pattern, symbols, and style.
818      */
819     DecimalFormat(String pattern, DecimalFormatSymbols inputSymbols, int style) {
820         CurrencyPluralInfo info = null;
821         if (style == NumberFormat.PLURALCURRENCYSTYLE) {
822             info = new CurrencyPluralInfo(inputSymbols.getLocale());
823         }
824         create(pattern, inputSymbols, info, style);
825     }
826
827     /**
828      * @stable ICU 2.0
829      */
830     public StringBuffer format(double number, StringBuffer result,
831             FieldPosition fieldPosition) {
832         return format(number, result, fieldPosition, false);
833     }
834     
835     // [Spark/CDL] The actual method to format number. If boolean value
836     // parseAttr == true, then attribute information will be recorded.
837     private StringBuffer format(double number, StringBuffer result,
838             FieldPosition fieldPosition, boolean parseAttr) 
839     {
840         fieldPosition.setBeginIndex(0);
841         fieldPosition.setEndIndex(0);
842
843         if (Double.isNaN(number))
844         {
845             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
846                 fieldPosition.setBeginIndex(result.length());
847             }
848 //#if defined(FOUNDATION10) || defined(J2SE13) 
849 //#else 
850             else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
851                 fieldPosition.setBeginIndex(result.length());
852             }
853 //#endif 
854
855             result.append(symbols.getNaN());
856             // [Spark/CDL] Add attribute for NaN here.
857             // result.append(symbols.getNaN());
858 //#if defined(FOUNDATION10) || defined(J2SE13)
859 //#else
860             if (parseAttr) {
861                 addAttribute(Field.INTEGER, result.length()
862                         - symbols.getNaN().length(), result.length());
863             }
864 //#endif
865             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
866                 fieldPosition.setEndIndex(result.length());
867             }
868 //#if defined(FOUNDATION10) || defined(J2SE13) 
869 //#else 
870             else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
871                 fieldPosition.setEndIndex(result.length());
872             }
873 //#endif 
874
875             addPadding(result, fieldPosition, 0, 0);
876             return result;
877         }
878
879         // Do this BEFORE checking to see if value is infinite or negative!
880         if (multiplier != 1) number *= multiplier;
881
882         /* Detecting whether a double is negative is easy with the exception of
883          * the value -0.0.  This is a double which has a zero mantissa (and
884          * exponent), but a negative sign bit.  It is semantically distinct from
885          * a zero with a positive sign bit, and this distinction is important
886          * to certain kinds of computations.  However, it's a little tricky to
887          * detect, since (-0.0 == 0.0) and !(-0.0 < 0.0).  How then, you may
888          * ask, does it behave distinctly from +0.0?  Well, 1/(-0.0) ==
889          * -Infinity.  Proper detection of -0.0 is needed to deal with the
890          * issues raised by bugs 4106658, 4106667, and 4147706.  Liu 7/6/98.
891          */
892         boolean isNegative = (number < 0.0) || (number == 0.0 && 1/number < 0.0);
893         if (isNegative) number = -number;
894
895         // Apply rounding after multiplier
896         if (roundingDouble > 0.0) {
897             // number = roundingDouble
898             //  * round(number / roundingDouble, roundingMode, isNegative);
899             double newNumber = round(number, roundingDouble, roundingDoubleReciprocal, roundingMode, isNegative);
900             if (newNumber == 0.0 && number != newNumber) isNegative = false; // if we touched it, then make zero be zero.
901             number = newNumber;
902         }
903
904         if (Double.isInfinite(number))
905         {
906             int prefixLen = appendAffix(result, isNegative, true, parseAttr);
907
908             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
909                 fieldPosition.setBeginIndex(result.length());
910             }
911 //#if defined(FOUNDATION10) || defined(J2SE13) 
912 //#else 
913             else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
914                 fieldPosition.setBeginIndex(result.length());
915             }
916 //#endif 
917
918             // [Spark/CDL] Add attribute for infinity here.
919             result.append(symbols.getInfinity());
920 //#if defined(FOUNDATION10) || defined(J2SE13)
921 //#else
922             if (parseAttr) {
923                 addAttribute(Field.INTEGER, result.length()
924                         - symbols.getInfinity().length(), result.length());
925             }
926 //#endif
927             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
928                 fieldPosition.setEndIndex(result.length());
929             }
930 //#if defined(FOUNDATION10) || defined(J2SE13) 
931 //#else 
932             else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
933                 fieldPosition.setEndIndex(result.length());
934             }
935 //#endif 
936
937             int suffixLen = appendAffix(result, isNegative, false, parseAttr);
938
939             addPadding(result, fieldPosition, prefixLen, suffixLen);
940             return result;
941         }
942
943         // At this point we are guaranteed a nonnegative finite
944         // number.
945         synchronized(digitList) {
946             digitList.set(number, precision(false),
947                           !useExponentialNotation && !areSignificantDigitsUsed());
948             return subformat(number, result, fieldPosition, isNegative, false,
949                     parseAttr);
950         }
951     }
952     
953     // [NEW]
954     /**
955      * Round a double value to the nearest multiple of the given
956      * rounding increment, according to the given mode.  This is
957      * equivalent to rounding value/roundingInc to the nearest
958      * integer, according to the given mode, and returning that
959      * integer * roundingInc.
960      * Note this is changed from the version in 2.4, since division of doubles
961      * have inaccuracies. jitterbug 1871.
962      * @param number the absolute value of the number to be rounded
963      * @param roundingInc the rounding increment
964      * @param roundingIncReciprocal if non-zero, is the 
965      * @param mode a BigDecimal rounding mode
966      * @param isNegative true if the number to be rounded is negative
967      * @return the absolute value of the rounded result
968      */
969     private static double round(double number, double roundingInc, 
970             double roundingIncReciprocal, int mode, boolean isNegative) {
971         
972         double div = roundingIncReciprocal == 0.0 
973             ? number / roundingInc
974             : number * roundingIncReciprocal;
975         
976         // do the absolute cases first
977         
978         switch (mode) {
979         case BigDecimal.ROUND_CEILING:
980             div = (isNegative ? Math.floor(div + epsilon) : Math.ceil(div - epsilon));
981             break;
982         case BigDecimal.ROUND_FLOOR:
983             div = (isNegative ? Math.ceil(div - epsilon) : Math.floor(div + epsilon));
984             break;
985         case BigDecimal.ROUND_DOWN:
986             div = (Math.floor(div + epsilon));
987             break;
988         case BigDecimal.ROUND_UP:
989             div = (Math.ceil(div - epsilon));
990             break;
991         case BigDecimal.ROUND_UNNECESSARY:
992             if (div != Math.floor(div)) {
993                 throw new ArithmeticException("Rounding necessary");
994             }
995             return number;
996         default:
997             
998             // Handle complex cases, where the choice depends on the closer value.
999             
1000             // We figure out the distances to the two possible values, ceiling and floor.
1001             // We then go for the diff that is smaller.
1002             // Only if they are equal does the mode matter.
1003
1004             double ceil = Math.ceil(div);
1005             double ceildiff = ceil - div; // (ceil * roundingInc) - number;
1006             double floor = Math.floor(div);
1007             double floordiff = div - floor; // number - (floor * roundingInc);
1008             
1009             // Note that the diff values were those mapped back to the "normal" space
1010             // by using the roundingInc. I don't have access to the original author of the code
1011             // but suspect that that was to produce better result in edge cases because of machine
1012             // precision, rather than simply using the difference between, say, ceil and div.
1013             // However, it didn't work in all cases. Am trying instead using an epsilon value.
1014             
1015             switch (mode) {
1016             case BigDecimal.ROUND_HALF_EVEN:
1017                 // We should be able to just return Math.rint(a), but this
1018                 // doesn't work in some VMs.
1019                 // if one is smaller than the other, take the corresponding side
1020                 if (floordiff + epsilon < ceildiff) {
1021                         div = floor;
1022                     } else if (ceildiff + epsilon < floordiff) {
1023                         div = ceil;
1024                 } else { // they are equal, so we want to round to whichever is even
1025                     double testFloor = floor / 2;
1026                     div = (testFloor == Math.floor(testFloor)) ? floor : ceil;
1027                 }
1028                 break;
1029             case BigDecimal.ROUND_HALF_DOWN:
1030                 div = ((floordiff <= ceildiff + epsilon) ? floor : ceil);
1031                 break;
1032             case BigDecimal.ROUND_HALF_UP:
1033                 div = ((ceildiff <= floordiff + epsilon) ? ceil : floor);
1034                 break;
1035             default:
1036                 throw new IllegalArgumentException("Invalid rounding mode: " + mode);
1037             }
1038         }
1039         number = roundingIncReciprocal == 0.0
1040             ? div * roundingInc
1041             : div / roundingIncReciprocal;
1042         return number;
1043     }
1044     private static double epsilon = 0.00000000001;
1045
1046     /**
1047      * @stable ICU 2.0
1048      */
1049     // [Spark/CDL] Delegate to format_long_StringBuffer_FieldPosition_boolean
1050     public StringBuffer format(long number, StringBuffer result,
1051             FieldPosition fieldPosition) {
1052         return format(number, result, fieldPosition, false);
1053     }
1054
1055     private StringBuffer format(long number, StringBuffer result,
1056             FieldPosition fieldPosition, boolean parseAttr) 
1057     {
1058         fieldPosition.setBeginIndex(0);
1059         fieldPosition.setEndIndex(0);
1060
1061         // If we are to do rounding, we need to move into the BigDecimal
1062         // domain in order to do divide/multiply correctly.
1063         // [NEW]
1064         if (roundingIncrementICU != null) {
1065             return format(BigDecimal.valueOf(number), result, fieldPosition);
1066         }
1067
1068         boolean isNegative = (number < 0);
1069         if (isNegative) number = -number;
1070
1071         // In general, long values always represent real finite numbers, so
1072         // we don't have to check for +/- Infinity or NaN.  However, there
1073         // is one case we have to be careful of:  The multiplier can push
1074         // a number near MIN_VALUE or MAX_VALUE outside the legal range.  We
1075         // check for this before multiplying, and if it happens we use BigInteger
1076         // instead.
1077         // [NEW]
1078         if (multiplier != 1) {
1079             boolean tooBig = false;
1080             if (number < 0) { // This can only happen if number == Long.MIN_VALUE
1081                 long cutoff = Long.MIN_VALUE / multiplier;
1082                 tooBig = (number <= cutoff); // number == cutoff can only happen if multiplier == -1
1083             } else {
1084                 long cutoff = Long.MAX_VALUE / multiplier;
1085                 tooBig = (number > cutoff);
1086             }
1087             if (tooBig) {
1088                 // [Spark/CDL] Use
1089                 // format_BigInteger_StringBuffer_FieldPosition_boolean instead
1090                 // parseAttr is used to judge whether to synthesize attributes.
1091                 return format(
1092                         BigInteger.valueOf(isNegative ? -number : number),
1093                         result, fieldPosition, parseAttr);
1094             }
1095         }
1096
1097         number *= multiplier;
1098         synchronized(digitList) {
1099             digitList.set(number, precision(true));
1100             return subformat(number, result, fieldPosition, isNegative, true, parseAttr);
1101         }
1102     }
1103
1104     // [NEW]
1105     /**
1106      * Format a BigInteger number.
1107      * 
1108      * @stable ICU 2.0
1109      */
1110     public StringBuffer format(BigInteger number, StringBuffer result,
1111             FieldPosition fieldPosition) {
1112         return format(number, result, fieldPosition, false);
1113     }
1114
1115     // [Spark/CDL] 
1116     private StringBuffer format(BigInteger number, StringBuffer result,
1117             FieldPosition fieldPosition, boolean parseAttr) {
1118         // If we are to do rounding, we need to move into the BigDecimal
1119         // domain in order to do divide/multiply correctly.
1120         if (roundingIncrementICU != null) {
1121             return format(new BigDecimal(number), result, fieldPosition);
1122         }
1123
1124         if (multiplier != 1) {
1125             number = number.multiply(BigInteger.valueOf(multiplier));
1126         }
1127
1128         // At this point we are guaranteed a nonnegative finite
1129         // number.
1130         synchronized(digitList) {
1131             digitList.set(number, precision(true));
1132             return subformat(number.intValue(), result, fieldPosition, number.signum() < 0, true, parseAttr);
1133         }
1134     }
1135
1136 //#if defined(FOUNDATION10)
1137 //#else
1138     // [NEW]
1139     /**
1140      * Format a BigDecimal number.
1141      * @stable ICU 2.0
1142      */
1143     public StringBuffer format(java.math.BigDecimal number, StringBuffer result,
1144                                FieldPosition fieldPosition) {
1145         return format(number, result, fieldPosition, false);
1146     }
1147     
1148     private StringBuffer format(java.math.BigDecimal number,
1149             StringBuffer result, FieldPosition fieldPosition, boolean parseAttr) {
1150         if (multiplier != 1) {
1151             number = number.multiply(java.math.BigDecimal.valueOf(multiplier));
1152         }
1153
1154         if (roundingIncrement != null) {
1155             number = number.divide(roundingIncrement, 0, roundingMode)
1156                     .multiply(roundingIncrement);
1157         }
1158
1159         synchronized(digitList) {
1160             digitList.set(number, precision(false),
1161                           !useExponentialNotation && !areSignificantDigitsUsed());
1162             return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0, false, parseAttr);
1163         }        
1164     }
1165 //#endif
1166     
1167     // [NEW]
1168     /**
1169      * Format a BigDecimal number.
1170      * @stable ICU 2.0
1171      */
1172     public StringBuffer format(BigDecimal number, StringBuffer result,
1173                                FieldPosition fieldPosition) {
1174         /* This method is just a copy of the corresponding java.math.BigDecimal
1175          * method for now.  It isn't very efficient since it must create a
1176          * conversion object to do math on the rounding increment.  In the
1177          * future we may try to clean this up, or even better, limit our support
1178          * to just one flavor of BigDecimal.
1179          */
1180         if (multiplier != 1) {
1181             number = number.multiply(BigDecimal.valueOf(multiplier), mathContext);
1182         }
1183
1184         if (roundingIncrementICU != null) {
1185             number = number.divide(roundingIncrementICU, 0, roundingMode)
1186                 .multiply(roundingIncrementICU, mathContext);
1187         }
1188
1189         synchronized(digitList) {
1190             digitList.set(number, precision(false),
1191                           !useExponentialNotation && !areSignificantDigitsUsed());
1192             return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0, false, false);
1193         }        
1194     }
1195
1196     /**
1197      * Return true if a grouping separator belongs at the given
1198      * position, based on whether grouping is in use and the values of
1199      * the primary and secondary grouping interval.
1200      * @param pos the number of integer digits to the right of
1201      * the current position.  Zero indicates the position after the
1202      * rightmost integer digit.
1203      * @return true if a grouping character belongs at the current
1204      * position.
1205      */
1206     private boolean isGroupingPosition(int pos) {
1207         boolean result = false;
1208         if (isGroupingUsed() && (pos > 0) && (groupingSize > 0)) {
1209             if ((groupingSize2 > 0) && (pos > groupingSize)) {
1210                 result = ((pos - groupingSize) % groupingSize2) == 0;
1211             } else {
1212                 result = pos % groupingSize == 0;
1213             }
1214         }
1215         return result;
1216     }
1217
1218     /**
1219      * Return the number of fraction digits to display, or the total
1220      * number of digits for significant digit formats and exponential
1221      * formats.
1222      */
1223     private int precision(boolean isIntegral) {
1224         if (areSignificantDigitsUsed()) {
1225             return getMaximumSignificantDigits();
1226         } else if (useExponentialNotation) {
1227             return getMinimumIntegerDigits() + getMaximumFractionDigits();
1228         } else {
1229             return isIntegral ? 0 : getMaximumFractionDigits();
1230         }
1231     }
1232
1233     private StringBuffer subformat(int number, StringBuffer result, 
1234                                    FieldPosition fieldPosition,
1235                                    boolean isNegative, boolean isInteger, 
1236                                    boolean parseAttr) {
1237         if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) { 
1238             return subformat(currencyPluralInfo.select(number), result, fieldPosition,
1239                              isNegative, isInteger, parseAttr);
1240         } else {
1241             return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
1242         }
1243     }
1244
1245     private StringBuffer subformat(double number, StringBuffer result, 
1246                                    FieldPosition fieldPosition,
1247                                    boolean isNegative, boolean isInteger,
1248                                    boolean parseAttr) {
1249         if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) { 
1250             return subformat(currencyPluralInfo.select(number), result, fieldPosition,
1251                              isNegative, isInteger, parseAttr);
1252         } else {
1253             return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
1254         }
1255     }
1256
1257     private StringBuffer subformat(String pluralCount, 
1258             StringBuffer result,
1259             FieldPosition fieldPosition, boolean isNegative, boolean isInteger,
1260             boolean parseAttr) 
1261     {
1262         // There are 2 ways to activate currency plural format:
1263         // by applying a pattern with 3 currency sign directly,
1264         // or by instantiate a decimal formatter using PLURALCURRENCYSTYLE.
1265         // For both cases, the number of currency sign in the pattern is 3.
1266         // Even if the number of currency sign in the pattern is 3, 
1267         // it does not mean we need to reset the pattern.
1268         // For 1st case, we do not need to reset pattern.
1269         // For 2nd case, we might need to reset pattern,
1270         // if the default pattern (corresponding to plural count 'other')
1271         // we use is different from the pattern based on 'pluralCount'.
1272         // 
1273         // style is only valid when decimal formatter is constructed through
1274         // DecimalFormat(pattern, symbol, style)
1275         if (style == NumberFormat.PLURALCURRENCYSTYLE) {
1276             // May need to reset pattern if the style is PLURALCURRENCYSTYLE.
1277             String currencyPluralPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount);
1278             if (formatPattern.equals(currencyPluralPattern) == false) {
1279                 applyPatternWithoutExpandAffix(currencyPluralPattern, false);
1280             }
1281         }
1282         // Expand the affix to the right name according to
1283         // the plural rule.
1284         // This is only used for currency plural formatting.
1285         // Currency plural name is not a fixed static one,
1286         // it is a dynamic name based on the currency plural count.
1287         // So, the affixes need to be expanded here.
1288         // For other cases, the affix is a static one based on pattern alone,
1289         // and it is already expanded during applying pattern,
1290         // or setDecimalFormatSymbols, or setCurrency.
1291         expandAffixAdjustWidth(pluralCount);
1292         return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
1293     }
1294
1295     /**
1296      * Complete the formatting of a finite number.  On entry, the digitList must
1297      * be filled in with the correct digits.
1298      */
1299     private StringBuffer subformat(StringBuffer result,
1300             FieldPosition fieldPosition, boolean isNegative, boolean isInteger,
1301             boolean parseAttr) 
1302     {
1303         // NOTE: This isn't required anymore because DigitList takes care of this.
1304         //
1305         //  // The negative of the exponent represents the number of leading
1306         //  // zeros between the decimal and the first non-zero digit, for
1307         //  // a value < 0.1 (e.g., for 0.00123, -fExponent == 2).  If this
1308         //  // is more than the maximum fraction digits, then we have an underflow
1309         //  // for the printed representation.  We recognize this here and set
1310         //  // the DigitList representation to zero in this situation.
1311         //
1312         //  if (-digitList.decimalAt >= getMaximumFractionDigits())
1313         //  {
1314         //      digitList.count = 0;
1315         //  }
1316
1317         int i;
1318         char zero = symbols.getZeroDigit();
1319         int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero
1320         char grouping = currencySignCount > 0 ?
1321                     symbols.getMonetaryGroupingSeparator() :
1322                     symbols.getGroupingSeparator();
1323         char decimal =  currencySignCount > 0 ?
1324             symbols.getMonetaryDecimalSeparator() :
1325             symbols.getDecimalSeparator();
1326         boolean useSigDig = areSignificantDigitsUsed();
1327         int maxIntDig = getMaximumIntegerDigits();
1328         int minIntDig = getMinimumIntegerDigits();
1329
1330         /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
1331          * format as zero.  This allows sensible computations and preserves
1332          * relations such as signum(1/x) = signum(x), where x is +Infinity or
1333          * -Infinity.  Prior to this fix, we always formatted zero values as if
1334          * they were positive.  Liu 7/6/98.
1335          */
1336         if (digitList.isZero())
1337         {
1338             digitList.decimalAt = 0; // Normalize
1339         }
1340
1341         int prefixLen = appendAffix(result, isNegative, true, parseAttr);
1342
1343         if (useExponentialNotation)
1344         {
1345             // Record field information for caller.
1346             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1347                 fieldPosition.setBeginIndex(result.length());
1348                 fieldPosition.setEndIndex(-1);
1349             } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1350                 fieldPosition.setBeginIndex(-1);
1351             }
1352 //#if defined(FOUNDATION10) || defined(J2SE13) 
1353 //#else 
1354             else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
1355                 fieldPosition.setBeginIndex(result.length());
1356                 fieldPosition.setEndIndex(-1);
1357             } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
1358                 fieldPosition.setBeginIndex(-1);
1359             } 
1360 //#endif 
1361
1362 //#if defined(FOUNDATION10) || defined(J2SE13)
1363 //#else
1364             // [Spark/CDL]
1365             // the begin index of integer part
1366             // the end index of integer part
1367             // the begin index of fractional part
1368             int intBegin = result.length();
1369             int intEnd = -1;
1370             int fracBegin = -1;
1371 //#endif
1372
1373             int minFracDig = 0;
1374             if (useSigDig) {
1375                 maxIntDig = minIntDig = 1;
1376                 minFracDig = getMinimumSignificantDigits() - 1;
1377             } else {
1378                 minFracDig = getMinimumFractionDigits();
1379                 if (maxIntDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
1380                     maxIntDig = 1;
1381                     if (maxIntDig < minIntDig) {
1382                         maxIntDig = minIntDig;
1383                     }
1384                 }
1385                 if (maxIntDig > minIntDig) {
1386                     minIntDig = 1;
1387                 }
1388             }            
1389
1390             // Minimum integer digits are handled in exponential format by
1391             // adjusting the exponent.  For example, 0.01234 with 3 minimum
1392             // integer digits is "123.4E-4".
1393
1394             // Maximum integer digits are interpreted as indicating the
1395             // repeating range.  This is useful for engineering notation, in
1396             // which the exponent is restricted to a multiple of 3.  For
1397             // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
1398             // If maximum integer digits are defined and are larger than
1399             // minimum integer digits, then minimum integer digits are
1400             // ignored.
1401
1402             int exponent = digitList.decimalAt;
1403             if (maxIntDig > 1 && maxIntDig != minIntDig) {
1404                 // A exponent increment is defined; adjust to it.
1405                 exponent = (exponent > 0) ? (exponent - 1) / maxIntDig
1406                                           : (exponent / maxIntDig) - 1;
1407                 exponent *= maxIntDig;
1408             } else {
1409                 // No exponent increment is defined; use minimum integer digits.
1410                 // If none is specified, as in "#E0", generate 1 integer digit.
1411                 exponent -= (minIntDig > 0 || minFracDig > 0)
1412                     ? minIntDig : 1;
1413             }
1414
1415             // We now output a minimum number of digits, and more if there
1416             // are more digits, up to the maximum number of digits.  We
1417             // place the decimal point after the "integer" digits, which
1418             // are the first (decimalAt - exponent) digits.
1419             int minimumDigits = minIntDig + minFracDig;
1420             // The number of integer digits is handled specially if the number
1421             // is zero, since then there may be no digits.
1422             int integerDigits = digitList.isZero() ? minIntDig :
1423                 digitList.decimalAt - exponent;
1424             int totalDigits = digitList.count;
1425             if (minimumDigits > totalDigits) totalDigits = minimumDigits;
1426             if (integerDigits > totalDigits) totalDigits = integerDigits;
1427
1428             for (i=0; i<totalDigits; ++i)
1429             {
1430                 if (i == integerDigits)
1431                 {
1432                     // Record field information for caller.
1433                     if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1434                         fieldPosition.setEndIndex(result.length());
1435                     }
1436 //#if defined(FOUNDATION10) || defined(J2SE13) 
1437 //#else 
1438                     else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
1439                         fieldPosition.setEndIndex(result.length());
1440                     }
1441 //#endif 
1442
1443 //#if defined(FOUNDATION10) || defined(J2SE13)
1444 //#else
1445                     // [Spark/CDL] Add attribute for integer part
1446                     if (parseAttr) {
1447                         intEnd = result.length();
1448                         addAttribute(Field.INTEGER, intBegin, result.length());
1449                     }
1450 //#endif
1451                     result.append(decimal);
1452 //#if defined(FOUNDATION10) || defined(J2SE13)
1453 //#else
1454                     // [Spark/CDL] Add attribute for decimal separator
1455                     if (parseAttr) {
1456                         // Length of decimal separator is 1.
1457                         int decimalSeparatorBegin = result.length() - 1;
1458                         addAttribute(Field.DECIMAL_SEPARATOR,
1459                                 decimalSeparatorBegin, result.length());
1460                             fracBegin = result.length();
1461                     }
1462 //#endif
1463                     // Record field information for caller.
1464                     if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1465                         fieldPosition.setBeginIndex(result.length());
1466                     }
1467 //#if defined(FOUNDATION10) || defined(J2SE13) 
1468 //#else 
1469                     else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
1470                         fieldPosition.setBeginIndex(result.length());
1471                     }
1472 //#endif 
1473
1474                 }
1475                 result.append((i < digitList.count) ?
1476                           (char)(digitList.digits[i] + zeroDelta) :
1477                           zero);
1478             }
1479             
1480             //For ICU compatibility and format 0 to 0E0 with pattern "#E0" [Richard/GCL]
1481             if (digitList.isZero() && (totalDigits ==0)) {
1482                 result.append(zero);
1483             }
1484
1485             // Record field information
1486             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1487                 if (fieldPosition.getEndIndex() < 0) {
1488                     fieldPosition.setEndIndex(result.length());
1489                 }
1490             } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1491                 if (fieldPosition.getBeginIndex() < 0) {
1492                     fieldPosition.setBeginIndex(result.length());
1493                 }
1494                 fieldPosition.setEndIndex(result.length());
1495             }
1496 //#if defined(FOUNDATION10) || defined(J2SE13) 
1497 //#else 
1498             else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
1499                 if (fieldPosition.getEndIndex() < 0) {
1500                     fieldPosition.setEndIndex(result.length());
1501                 }
1502             } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
1503                 if (fieldPosition.getBeginIndex() < 0) {
1504                     fieldPosition.setBeginIndex(result.length());
1505                 }
1506                 fieldPosition.setEndIndex(result.length());
1507             }
1508 //#endif 
1509
1510 //#if defined(FOUNDATION10) || defined(J2SE13)
1511 //#else
1512             // [Spark/CDL] Calcuate the end index of integer part and fractional
1513             // part if they are not properly processed yet.
1514             if (parseAttr) {
1515                 if (intEnd < 0) {
1516                     addAttribute(Field.INTEGER, intBegin, result.length());
1517                 }
1518                 if (fracBegin > 0) {
1519                     addAttribute(Field.FRACTION, fracBegin, result.length());
1520                 }
1521             }
1522 //#endif
1523
1524             // The exponent is output using the pattern-specified minimum
1525             // exponent digits.  There is no maximum limit to the exponent
1526             // digits, since truncating the exponent would result in an
1527             // unacceptable inaccuracy.
1528             result.append(symbols.getExponentSeparator());
1529 //#if defined(FOUNDATION10) || defined(J2SE13)
1530 //#else
1531             // [Spark/CDL] For exponent symbol, add an attribute.
1532             if (parseAttr) {
1533                 addAttribute(Field.EXPONENT_SYMBOL, result.length()
1534                         - symbols.getExponentSeparator().length(), result
1535                         .length());
1536             }
1537 //#endif
1538             // For zero values, we force the exponent to zero.  We
1539             // must do this here, and not earlier, because the value
1540             // is used to determine integer digit count above.
1541             if (digitList.isZero()) exponent = 0;
1542
1543             boolean negativeExponent = exponent < 0;
1544             if (negativeExponent) {
1545                 exponent = -exponent;
1546                 result.append(symbols.getMinusSign());
1547 //#if defined(FOUNDATION10) || defined(J2SE13)
1548 //#else
1549                 // [Spark/CDL] If exponent has sign, then add an exponent sign
1550                 // attribute.
1551                 if (parseAttr) {
1552                     // Length of exponent sign is 1.
1553                     addAttribute(Field.EXPONENT_SIGN, result.length() - 1,
1554                             result.length());
1555                 }
1556 //#endif
1557             } else if (exponentSignAlwaysShown) {
1558                 result.append(symbols.getPlusSign());
1559 //#if defined(FOUNDATION10) || defined(J2SE13)
1560 //#else
1561                 // [Spark/CDL] Add an plus sign attribute.
1562                 if (parseAttr) {
1563                     // Length of exponent sign is 1.
1564                     int expSignBegin = result.length() - 1;
1565                     addAttribute(Field.EXPONENT_SIGN, expSignBegin, result
1566                             .length());
1567                 }
1568 //#endif
1569             }
1570 //#if defined(FOUNDATION10) || defined(J2SE13)
1571 //#else
1572             int expBegin = result.length();
1573 //#endif
1574             digitList.set(exponent);
1575             {
1576                 int expDig = minExponentDigits;
1577                 if (useExponentialNotation && expDig < 1) {
1578                     expDig = 1;
1579                 }
1580                 for (i=digitList.decimalAt; i<expDig; ++i) result.append(zero);
1581             }
1582             for (i=0; i<digitList.decimalAt; ++i)
1583             {
1584                 result.append((i < digitList.count) ?
1585                           (char)(digitList.digits[i] + zeroDelta) : zero);
1586             }
1587 //#if defined(FOUNDATION10) || defined(J2SE13)
1588 //#else
1589             // [Spark/CDL] Add attribute for exponent part.
1590             if (parseAttr) {
1591                 addAttribute(Field.EXPONENT, expBegin, result.length());
1592             }
1593 //#endif
1594         }
1595         else
1596         {
1597 //#if defined(FOUNDATION10) || defined(J2SE13)
1598 //#else
1599             // [Spark/CDL] Record the integer start index.
1600             int intBegin = result.length();
1601 //#endif
1602             // Record field information for caller.
1603             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1604                 fieldPosition.setBeginIndex(result.length());
1605             }
1606 //#if defined(FOUNDATION10) || defined(J2SE13) 
1607 //#else 
1608             else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
1609                 fieldPosition.setBeginIndex(result.length());
1610             }
1611 //#endif 
1612
1613             int sigCount = 0;
1614             int minSigDig = getMinimumSignificantDigits();
1615             int maxSigDig = getMaximumSignificantDigits();
1616             if (!useSigDig) {
1617                 minSigDig = 0;
1618                 maxSigDig = Integer.MAX_VALUE;
1619             }
1620
1621             // Output the integer portion.  Here 'count' is the total
1622             // number of integer digits we will display, including both
1623             // leading zeros required to satisfy getMinimumIntegerDigits,
1624             // and actual digits present in the number.
1625             int count = useSigDig ?
1626                 Math.max(1, digitList.decimalAt) : minIntDig;
1627             if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
1628                 count = digitList.decimalAt;
1629             }
1630
1631             // Handle the case where getMaximumIntegerDigits() is smaller
1632             // than the real number of integer digits.  If this is so, we
1633             // output the least significant max integer digits.  For example,
1634             // the value 1997 printed with 2 max integer digits is just "97".
1635
1636             int digitIndex = 0; // Index into digitList.fDigits[]
1637             if (count > maxIntDig && maxIntDig >= 0) {
1638                 count = maxIntDig;
1639                 digitIndex = digitList.decimalAt - count;
1640             }
1641
1642             int sizeBeforeIntegerPart = result.length();
1643             for (i=count-1; i>=0; --i)
1644             {
1645                 if (i < digitList.decimalAt && digitIndex < digitList.count &&
1646                     sigCount < maxSigDig) {
1647                     // Output a real digit
1648                     byte d = digitList.digits[digitIndex++];
1649                     result.append((char)(d + zeroDelta));
1650                     ++sigCount;
1651                 }
1652                 else
1653                 {
1654                     // Output a zero (leading or trailing)
1655                     result.append(zero);
1656                     if (sigCount > 0) {
1657                         ++sigCount;
1658                     }
1659                 }
1660
1661                 // Output grouping separator if necessary.
1662                 if (isGroupingPosition(i)) {
1663                     result.append(grouping);
1664 //#if defined(FOUNDATION10) || defined(J2SE13)
1665 //#else
1666                     // [Spark/CDL] Add grouping separator attribute here.
1667                     if (parseAttr) {
1668                         // Length of grouping separator is 1.
1669                         addAttribute(Field.GROUPING_SEPARATOR,
1670                                 result.length() - 1, result.length());
1671                     }
1672 //#endif
1673                 }
1674             }
1675
1676             // Record field information for caller.
1677             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1678                 fieldPosition.setEndIndex(result.length());
1679             }
1680 //#if defined(FOUNDATION10) || defined(J2SE13) 
1681 //#else 
1682             else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
1683                 fieldPosition.setEndIndex(result.length());
1684             }
1685 //#endif 
1686
1687             // Determine whether or not there are any printable fractional
1688             // digits.  If we've used up the digits we know there aren't.
1689             boolean fractionPresent = (!isInteger && digitIndex < digitList.count) ||
1690                 (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0));
1691
1692             // If there is no fraction present, and we haven't printed any
1693             // integer digits, then print a zero.  Otherwise we won't print
1694             // _any_ digits, and we won't be able to parse this string.
1695             if (!fractionPresent && result.length() == sizeBeforeIntegerPart)
1696                 result.append(zero);
1697 //#if defined(FOUNDATION10) || defined(J2SE13)
1698 //#else
1699             // [Spark/CDL] Add attribute for integer part.
1700             if (parseAttr) {
1701                 addAttribute(Field.INTEGER, intBegin, result.length());
1702             }
1703 //#endif
1704             // Output the decimal separator if we always do so.
1705             if (decimalSeparatorAlwaysShown || fractionPresent)
1706             {
1707                 result.append(decimal);
1708 //#if defined(FOUNDATION10) || defined(J2SE13)
1709 //#else
1710                 // [Spark/CDL] Add attribute for decimal separator
1711                 if (parseAttr) {
1712                     addAttribute(Field.DECIMAL_SEPARATOR, result.length() - 1,
1713                             result.length());
1714                 }
1715 //#endif
1716             }
1717
1718             // Record field information for caller.
1719             if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1720                 fieldPosition.setBeginIndex(result.length());
1721             }
1722 //#if defined(FOUNDATION10) || defined(J2SE13) 
1723 //#else 
1724             else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
1725                 fieldPosition.setBeginIndex(result.length());
1726             }
1727 //#endif 
1728
1729 //#if defined(FOUNDATION10) || defined(J2SE13)
1730 //#else
1731             // [Spark/CDL] Record the begin index of fraction part.
1732             int fracBegin = result.length();
1733 //#endif
1734
1735             count = useSigDig ? Integer.MAX_VALUE : getMaximumFractionDigits();
1736             if (useSigDig && (sigCount == maxSigDig ||
1737                               (sigCount >= minSigDig && digitIndex == digitList.count))) {
1738                 count = 0;   
1739             }
1740             for (i=0; i < count; ++i) {
1741                 // Here is where we escape from the loop.  We escape
1742                 // if we've output the maximum fraction digits
1743                 // (specified in the for expression above).  We also
1744                 // stop when we've output the minimum digits and
1745                 // either: we have an integer, so there is no
1746                 // fractional stuff to display, or we're out of
1747                 // significant digits.
1748                 if (!useSigDig && i >= getMinimumFractionDigits() &&
1749                     (isInteger || digitIndex >= digitList.count)) {
1750                     break;
1751                 }
1752
1753                 // Output leading fractional zeros.  These are zeros
1754                 // that come after the decimal but before any
1755                 // significant digits.  These are only output if
1756                 // abs(number being formatted) < 1.0.
1757                 if (-1-i > (digitList.decimalAt-1)) {
1758                     result.append(zero);
1759                     continue;
1760                 }
1761
1762                 // Output a digit, if we have any precision left, or a
1763                 // zero if we don't.  We don't want to output noise digits.
1764                 if (!isInteger && digitIndex < digitList.count) {
1765                     result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
1766                 } else {
1767                     result.append(zero);
1768                 }
1769
1770                 // If we reach the maximum number of significant
1771                 // digits, or if we output all the real digits and
1772                 // reach the minimum, then we are done.
1773                 ++sigCount;
1774                 if (useSigDig &&
1775                     (sigCount == maxSigDig ||
1776                      (digitIndex == digitList.count && sigCount >= minSigDig))) {
1777                     break;
1778                 }
1779             }
1780
1781             // Record field information for caller.
1782             if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1783                 fieldPosition.setEndIndex(result.length());
1784             }
1785 //#if defined(FOUNDATION10) || defined(J2SE13) 
1786 //#else 
1787             else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
1788                 fieldPosition.setEndIndex(result.length());
1789             }
1790 //#endif 
1791
1792 //#if defined(FOUNDATION10) || defined(J2SE13)
1793 //#else
1794             // [Spark/CDL] Add attribute information if necessary.
1795             if (parseAttr && (decimalSeparatorAlwaysShown || fractionPresent)) {
1796                 addAttribute(Field.FRACTION, fracBegin, result.length());
1797             }
1798 //#endif
1799         }
1800
1801         int suffixLen = appendAffix(result, isNegative, false, parseAttr);
1802
1803         // [NEW]
1804         addPadding(result, fieldPosition, prefixLen, suffixLen);
1805         return result;
1806     }
1807
1808     // [NEW]
1809     private final void addPadding(StringBuffer result, FieldPosition fieldPosition,
1810                                   int prefixLen, int suffixLen) {
1811         if (formatWidth > 0) {
1812             int len = formatWidth - result.length();
1813             if (len > 0) {
1814                 char[] padding = new char[len];
1815                 for (int i=0; i<len; ++i) {
1816                     padding[i] = pad;
1817                 }
1818                 switch (padPosition) {
1819                 case PAD_AFTER_PREFIX:
1820                     result.insert(prefixLen, padding);
1821                     break;
1822                 case PAD_BEFORE_PREFIX:
1823                     result.insert(0, padding);
1824                     break;
1825                 case PAD_BEFORE_SUFFIX:
1826                     result.insert(result.length() - suffixLen, padding);
1827                     break;
1828                 case PAD_AFTER_SUFFIX:
1829                     result.append(padding);
1830                     break;
1831                 }
1832                 if (padPosition == PAD_BEFORE_PREFIX ||
1833                     padPosition == PAD_AFTER_PREFIX) {
1834                     fieldPosition.setBeginIndex(fieldPosition.getBeginIndex() + len);
1835                     fieldPosition.setEndIndex(fieldPosition.getEndIndex() + len);
1836                 }
1837             }
1838         }
1839     }
1840
1841     // [CHANGED]
1842     /**
1843      * Parse the given string, returning a <code>Number</code> object to
1844      * represent the parsed value.  <code>Double</code> objects are returned to
1845      * represent non-integral values which cannot be stored in a
1846      * <code>BigDecimal</code>.  These are <code>NaN</code>, infinity,
1847      * -infinity, and -0.0.  If {@link #isParseBigDecimal()} is false (the
1848      * default), all other values are returned as <code>Long</code>,
1849      * <code>BigInteger</code>, or <code>BigDecimal</code> values,
1850      * in that order of preference. If {@link #isParseBigDecimal()} is true,
1851      * all other values are returned as <code>BigDecimal</code> valuse.
1852      * If the parse fails, null is returned.
1853      * @param text the string to be parsed
1854      * @param parsePosition defines the position where parsing is to begin,
1855      * and upon return, the position where parsing left off.  If the position
1856      * has not changed upon return, then parsing failed.
1857      * @return a <code>Number</code> object with the parsed value or
1858      * <code>null</code> if the parse failed
1859      * @stable ICU 2.0
1860      */
1861     public Number parse(String text, ParsePosition parsePosition) {
1862        return (Number) parse(text, parsePosition, false);
1863     }
1864
1865     // [NEW]
1866     /**
1867      * Parses text from the given string as a CurrencyAmount.  Unlike
1868      * the parse() method, this method will attempt to parse a generic
1869      * currency name, searching for a match of this object's locale's
1870      * currency display names, or for a 3-letter ISO currency code.
1871      * This method will fail if this format is not a currency format,
1872      * that is, if it does not contain the currency pattern symbol
1873      * (U+00A4) in its prefix or suffix.
1874      *
1875      * @param text the string to parse
1876      * @param pos input-output position; on input, the position within
1877      * text to match; must have 0 <= pos.getIndex() < text.length();
1878      * on output, the position after the last matched character. If
1879      * the parse fails, the position in unchanged upon output.
1880      * @return a CurrencyAmount, or null upon failure
1881      * @internal
1882      * @deprecated This API is ICU internal only.
1883      */
1884     CurrencyAmount parseCurrency(String text, ParsePosition pos) {
1885         return (CurrencyAmount) parse(text, pos, true);
1886     }
1887
1888     /**
1889      * Parses the given text as either a Number or a CurrencyAmount.
1890      * @param text the string to parse
1891      * @param parsePosition input-output position; on input, the
1892      * position within text to match; must have 0 <= pos.getIndex() <
1893      * text.length(); on output, the position after the last matched
1894      * character. If the parse fails, the position in unchanged upon
1895      * output.
1896      * @param parseCurrency if true, a CurrencyAmount is parsed and
1897      * returned; otherwise a Number is parsed and returned
1898      * @return a Number or CurrencyAmount or null
1899      */
1900     private Object parse(String text, ParsePosition parsePosition, boolean parseCurrency) {
1901         int backup;
1902         int i = backup = parsePosition.getIndex();
1903
1904         // Handle NaN as a special case:
1905
1906         // Skip padding characters, if around prefix
1907         if (formatWidth > 0 && (padPosition == PAD_BEFORE_PREFIX ||
1908                                 padPosition == PAD_AFTER_PREFIX)) {
1909             i = skipPadding(text, i);
1910         }
1911         if (text.regionMatches(i, symbols.getNaN(),
1912                                0, symbols.getNaN().length())) {
1913             i += symbols.getNaN().length();
1914             // Skip padding characters, if around suffix
1915             if (formatWidth > 0 && (padPosition == PAD_BEFORE_SUFFIX ||
1916                                     padPosition == PAD_AFTER_SUFFIX)) {
1917                 i = skipPadding(text, i);
1918             }
1919             parsePosition.setIndex(i);
1920             return new Double(Double.NaN);
1921         }
1922
1923         // NaN parse failed; start over
1924         i = backup;
1925
1926         boolean[] status = new boolean[STATUS_LENGTH];
1927         Currency[] currency = parseCurrency ? new Currency[1] : null;
1928         if (currencySignCount > 0) {
1929             if (!parseForCurrency(text, parsePosition, parseCurrency, 
1930                                   currency, status)) {
1931                 return null;
1932             }
1933         } else {
1934             if (!subparse(text, parsePosition, digitList, false, status, 
1935                           currency, negPrefixPattern, negSuffixPattern,
1936                           posPrefixPattern, posSuffixPattern, Currency.SYMBOL_NAME)) {
1937                 parsePosition.setIndex(backup);
1938                 return null;
1939             }
1940         }
1941
1942         Number n = null;
1943
1944         // Handle infinity
1945         if (status[STATUS_INFINITE]) {
1946             n = new Double(status[STATUS_POSITIVE]
1947                            ? Double.POSITIVE_INFINITY
1948                            : Double.NEGATIVE_INFINITY);
1949         }
1950
1951         // Handle underflow
1952         else if (status[STATUS_UNDERFLOW]) {
1953             n = status[STATUS_POSITIVE] ? new Double("0.0") : new Double("-0.0");
1954         }
1955
1956         // Handle -0.0
1957         else if (!status[STATUS_POSITIVE] && digitList.isZero()) {
1958             n = new Double("-0.0");
1959         }
1960
1961         else {
1962             // Do as much of the multiplier conversion as possible without
1963             // losing accuracy.
1964             int mult = multiplier; // Don't modify this.multiplier
1965             while (mult % 10 == 0) {
1966                 --digitList.decimalAt;
1967                 mult /= 10;
1968             }
1969
1970             // Handle integral values
1971             if (!parseBigDecimal && mult == 1 && digitList.isIntegral()) {
1972                 // hack quick long
1973                 if (digitList.decimalAt < 12) { // quick check for long
1974                     long l = 0;
1975                     if (digitList.count > 0) {
1976                         int nx = 0;
1977                         while (nx < digitList.count) {
1978                             l = l * 10 + (char)digitList.digits[nx++] - '0';
1979                         }
1980                         while (nx++ < digitList.decimalAt) {
1981                             l *= 10;
1982                         }
1983                         if (!status[STATUS_POSITIVE]) {
1984                             l = -l;
1985                         }
1986                     }
1987                     n = new Long(l);
1988                 } else {
1989                     BigInteger big = digitList.getBigInteger(status[STATUS_POSITIVE]);
1990                     n = (big.bitLength() < 64) ?
1991                         (Number) new Long(big.longValue()) : (Number) big;
1992                 }
1993             }
1994             // Handle non-integral values or the case where parseBigDecimal is set
1995             else {
1996                 BigDecimal big = digitList.getBigDecimalICU(status[STATUS_POSITIVE]);
1997                 n = big;
1998                 if (mult != 1) {
1999                     n = big.divide(BigDecimal.valueOf(mult), mathContext);
2000                 }
2001             }
2002         }
2003
2004         // Assemble into CurrencyAmount if necessary
2005         return parseCurrency ? (Object) new CurrencyAmount(n, currency[0])
2006                              : (Object) n;
2007     }
2008
2009
2010     private boolean parseForCurrency(String text, ParsePosition parsePosition, 
2011                                      boolean parseCurrency, Currency[] currency,
2012                                      boolean[] status) {
2013         int origPos = parsePosition.getIndex();
2014         if (!isReadyForParsing) {
2015             int savedCurrencySignCount = currencySignCount;
2016             setupCurrencyAffixForAllPatterns();
2017             // reset pattern back
2018             if (savedCurrencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
2019                 applyPatternWithoutExpandAffix(formatPattern, false);
2020             } else {
2021                 applyPattern(formatPattern, false);
2022             }
2023             isReadyForParsing = true;
2024         }
2025         int maxPosIndex = origPos;
2026         int maxErrorPos = -1;
2027         boolean[] savedStatus = null;
2028         // First, parse against current pattern.
2029         // Since current pattern could be set by applyPattern(),
2030         // it could be an arbitrary pattern, and it may not be the one
2031         // defined in current locale.
2032         boolean[] tmpStatus = new boolean[STATUS_LENGTH];
2033         ParsePosition tmpPos = new ParsePosition(origPos);
2034         DigitList tmpDigitList = new DigitList();
2035         boolean found;
2036         if (style == NumberFormat.PLURALCURRENCYSTYLE) {
2037             found  = subparse(text, tmpPos, tmpDigitList, false, 
2038                   tmpStatus, currency, negPrefixPattern, negSuffixPattern,
2039                   posPrefixPattern, posSuffixPattern, Currency.LONG_NAME);
2040         } else {
2041             found  = subparse(text, tmpPos, tmpDigitList, false, 
2042                   tmpStatus, currency, negPrefixPattern, negSuffixPattern,
2043                   posPrefixPattern, posSuffixPattern, Currency.SYMBOL_NAME);
2044         }
2045         if (found) {
2046             if (tmpPos.getIndex() > maxPosIndex) {
2047                 maxPosIndex = tmpPos.getIndex();
2048                 savedStatus = tmpStatus;
2049                 digitList = tmpDigitList;
2050             }
2051         } else {
2052             maxErrorPos = tmpPos.getErrorIndex();
2053         }
2054         // Then, parse against affix patterns.
2055         // Those are currency patterns and currency plural patterns
2056         // defined in the locale.
2057         Iterator  iter = affixPatternsForCurrency.iterator();
2058         while (iter.hasNext()) {
2059             AffixForCurrency affix = (AffixForCurrency)iter.next();
2060
2061             tmpStatus = new boolean[STATUS_LENGTH];
2062             tmpPos = new ParsePosition(origPos); 
2063             tmpDigitList = new DigitList();
2064             boolean result = subparse(text, tmpPos, tmpDigitList, false, 
2065                                tmpStatus, currency, affix.getNegPrefix(),
2066                                affix.getNegSuffix(), affix.getPosPrefix(), 
2067                                affix.getPosSuffix(), affix.getPatternType());
2068             if (result) {
2069                 found = true;
2070                 if (tmpPos.getIndex() > maxPosIndex) {
2071                     maxPosIndex = tmpPos.getIndex();
2072                     savedStatus = tmpStatus;
2073                     digitList = tmpDigitList;
2074                 }
2075             } else {
2076                 maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ?
2077                               tmpPos.getErrorIndex() : maxErrorPos;
2078             }
2079         }
2080         // Finally, parse against simple affix to find the match.
2081         // For example, in TestMonster suite,
2082         // if the to-be-parsed text is "-\u00A40,00".
2083         // complexAffixCompare will not find match,
2084         // since there is no ISO code matches "\u00A4",
2085         // and the parse stops at "\u00A4".
2086         // We will just use simple affix comparison (look for exact match)
2087         // to pass it.
2088         tmpStatus = new boolean[STATUS_LENGTH];
2089         tmpPos = new ParsePosition(origPos); 
2090         tmpDigitList = new DigitList();
2091         int savedCurrencySignCount = currencySignCount;
2092         // set currencySignCount to 0 so that compareAffix function will
2093         // fall to compareSimpleAffix path, not compareComplexAffix path.
2094         currencySignCount = 0;
2095         boolean result = subparse(text, tmpPos, tmpDigitList, false, 
2096                   tmpStatus, currency, negativePrefix, negativeSuffix,
2097                   positivePrefix, positiveSuffix, Currency.SYMBOL_NAME);
2098         currencySignCount = savedCurrencySignCount;
2099         if (result) {
2100             if (tmpPos.getIndex() > maxPosIndex) {
2101                 maxPosIndex = tmpPos.getIndex();
2102                 savedStatus = tmpStatus;
2103                 digitList = tmpDigitList;
2104             }
2105             found = true;
2106         } else {
2107                 maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ?
2108                               tmpPos.getErrorIndex() : maxErrorPos;
2109         }
2110
2111         if (!found) {
2112             //parsePosition.setIndex(origPos);
2113             parsePosition.setErrorIndex(maxErrorPos);
2114         } else {
2115             parsePosition.setIndex(maxPosIndex);
2116             parsePosition.setErrorIndex(-1);
2117             for (int index = 0; index < STATUS_LENGTH; ++index) {
2118                 status[index] = savedStatus[index];
2119             }
2120         }
2121         return found;
2122     }
2123
2124
2125     // Get affix patterns used in locale's currency pattern
2126     // (NumberPatterns[1]) and currency plural pattern (CurrencyUnitPatterns).
2127     private void setupCurrencyAffixForAllPatterns() {
2128         if (currencyPluralInfo == null) {
2129             currencyPluralInfo = new CurrencyPluralInfo(symbols.getLocale());
2130         }
2131         affixPatternsForCurrency = new HashSet();
2132
2133         // save the current pattern, since it will be changed by
2134         // applyPatternWithoutExpandAffix
2135         String savedFormatPattern = formatPattern;
2136         
2137         // CURRENCYSTYLE and ISOCURRENCYSTYLE should have the same
2138         // prefix and suffix, so, only need to save one of them.
2139         // Here, chose onlyApplyPatternWithoutExpandAffix without
2140         // saving the actualy pattern in 'pattern' data member.
2141         // TODO: is it uloc?
2142         applyPatternWithoutExpandAffix(getPattern(symbols.getLocale(), NumberFormat.CURRENCYSTYLE), false);
2143         AffixForCurrency affixes = new AffixForCurrency(negPrefixPattern,
2144                                                         negSuffixPattern,
2145                                                         posPrefixPattern,
2146                                                         posSuffixPattern,
2147                                                         Currency.SYMBOL_NAME);
2148         affixPatternsForCurrency.add(affixes);
2149         
2150         // add plural pattern
2151         Iterator iter = currencyPluralInfo.pluralPatternIterator();
2152         Set currencyUnitPatternSet = new HashSet();
2153         while (iter.hasNext()) {
2154             String pluralCount = (String)iter.next();
2155             String currencyPattern = (String)currencyPluralInfo.getCurrencyPluralPattern(pluralCount);
2156             if (currencyPattern != null &&
2157                 currencyUnitPatternSet.contains(currencyPattern) == false) {
2158                 currencyUnitPatternSet.add(currencyPattern);
2159                 applyPatternWithoutExpandAffix(currencyPattern, false);
2160                 affixes = new AffixForCurrency(negPrefixPattern,
2161                                                negSuffixPattern,
2162                                                posPrefixPattern,
2163                                                posSuffixPattern,
2164                                                Currency.LONG_NAME);
2165                 affixPatternsForCurrency.add(affixes);
2166             }   
2167         }
2168         // reset pattern back
2169         formatPattern = savedFormatPattern;
2170     }
2171
2172     private static final int CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT = 1;
2173     private static final int CURRENCY_SIGN_COUNT_IN_ISO_FORMAT = 2;
2174     private static final int CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT = 3;
2175
2176     private static final int STATUS_INFINITE = 0;
2177     private static final int STATUS_POSITIVE = 1;
2178     private static final int STATUS_UNDERFLOW = 2;
2179     private static final int STATUS_LENGTH   = 3;
2180     private static final UnicodeSet dotEquivalents =(UnicodeSet) new UnicodeSet(
2181         "[.\u2024\u3002\uFE12\uFE52\uFF0E\uFF61]").freeze();
2182     private static final UnicodeSet commaEquivalents = (UnicodeSet) new UnicodeSet(
2183         "[,\u060C\u066B\u3001\uFE10\uFE11\uFE50\uFE51\uFF0C\uFF64]").freeze();
2184     private static final UnicodeSet otherGroupingSeparators = (UnicodeSet) new UnicodeSet(
2185         "[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]").freeze();
2186     
2187     private static final UnicodeSet strictDotEquivalents =(UnicodeSet) new UnicodeSet(
2188         "[.\u2024\uFE52\uFF0E\uFF61]").freeze();
2189     private static final UnicodeSet strictCommaEquivalents = (UnicodeSet) new UnicodeSet(
2190         "[,\u066B\uFE10\uFE50\uFF0C]").freeze();
2191     private static final UnicodeSet strictOtherGroupingSeparators = (UnicodeSet) new UnicodeSet(
2192         "[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]").freeze();
2193
2194     private static final UnicodeSet defaultGroupingSeparators = (UnicodeSet) new UnicodeSet(
2195         dotEquivalents).addAll(commaEquivalents).addAll(otherGroupingSeparators).freeze();
2196     private static final UnicodeSet strictDefaultGroupingSeparators = (UnicodeSet) new UnicodeSet(
2197             strictDotEquivalents).addAll(strictCommaEquivalents).addAll(strictOtherGroupingSeparators).freeze();
2198
2199     // When parsing a number with big exponential value, it requires to transform
2200     // the value into a string representation to construct BigInteger instance.
2201     // We want to set the maximum size because it can easily trigger OutOfMemoryException.
2202     // PARSE_MAX_EXPONENT is currently set to 1000, which is much bigger than
2203     // MAX_VALUE of Double (
2204     // See the problem reported by ticket#5698
2205     private static final int PARSE_MAX_EXPONENT = 1000;
2206
2207     /**
2208      * <strong><font face=helvetica color=red>CHANGED</font></strong>
2209      * Parse the given text into a number.  The text is parsed beginning at
2210      * parsePosition, until an unparseable character is seen.
2211      * @param text The string to parse.
2212      * @param parsePosition The position at which to being parsing.  Upon
2213      * return, the first unparseable character.
2214      * @param digits The DigitList to set to the parsed value.
2215      * @param isExponent If true, parse an exponent.  This means no
2216      * infinite values and integer only.
2217      * @param status Upon return contains boolean status flags indicating
2218      * whether the value was infinite and whether it was positive.
2219      * @param currency return value for parsed currency, for generic
2220      * currency parsing mode, or null for normal parsing. In generic
2221      * currency parsing mode, any currency is parsed, not just the
2222      * currency that this formatter is set to.
2223      * @param negPrefix negative prefix pattern
2224      * @param negSuffix negative suffix pattern
2225      * @param posPrefix positive prefix pattern
2226      * @param negSuffix negative suffix pattern
2227      * @param type type of currency to parse against, LONG_NAME only or not.
2228      */
2229     private final boolean subparse(String text, ParsePosition parsePosition,
2230                    DigitList digits, boolean isExponent,
2231                    boolean status[], Currency currency[],
2232                    String negPrefix, String negSuffix,
2233                    String posPrefix, String posSuffix,
2234                    int type)
2235     {
2236         int position = parsePosition.getIndex();
2237         int oldStart = parsePosition.getIndex();
2238
2239         // Match padding before prefix
2240         if (formatWidth > 0 && padPosition == PAD_BEFORE_PREFIX) {
2241             position = skipPadding(text, position);
2242         }
2243
2244         // Match positive and negative prefixes; prefer longest match.
2245         int posMatch = compareAffix(text, position, false, true, posPrefix, type, currency);
2246         int negMatch = compareAffix(text, position, true, true, negPrefix, type, currency);
2247         if (posMatch >= 0 && negMatch >= 0) {
2248             if (posMatch > negMatch) {
2249                 negMatch = -1;
2250             } else if (negMatch > posMatch) {
2251                 posMatch = -1;
2252             }  
2253         }
2254         if (posMatch >= 0) {
2255             position += posMatch;
2256         } else if (negMatch >= 0) {
2257             position += negMatch;
2258         } else {
2259             parsePosition.setErrorIndex(position);
2260             return false;
2261         }
2262
2263         // Match padding after prefix
2264         if (formatWidth > 0 && padPosition == PAD_AFTER_PREFIX) {
2265             position = skipPadding(text, position);
2266         }
2267
2268         // process digits or Inf, find decimal position
2269         status[STATUS_INFINITE] = false;
2270         if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0,
2271                           symbols.getInfinity().length()))
2272         {
2273             position += symbols.getInfinity().length();
2274             status[STATUS_INFINITE] = true;
2275         } else {
2276             // We now have a string of digits, possibly with grouping symbols,
2277             // and decimal points.  We want to process these into a DigitList.
2278             // We don't want to put a bunch of leading zeros into the DigitList
2279             // though, so we keep track of the location of the decimal point,
2280             // put only significant digits into the DigitList, and adjust the
2281             // exponent as needed.
2282
2283             digits.decimalAt = digits.count = 0;
2284             char zero = symbols.getZeroDigit();
2285             char decimal = currencySignCount > 0 ?
2286             symbols.getMonetaryDecimalSeparator() : symbols.getDecimalSeparator();
2287             char grouping = symbols.getGroupingSeparator();
2288                         
2289             String exponentSep = symbols.getExponentSeparator();
2290             boolean sawDecimal = false;
2291             boolean sawExponent = false;
2292             boolean sawDigit = false;
2293             long exponent = 0; // Set to the exponent value, if any
2294             int digit = 0;
2295
2296             // strict parsing
2297             boolean strictParse = isParseStrict();
2298             boolean strictFail = false; // did we exit with a strict parse failure?
2299             int lastGroup = -1; // where did we last see a grouping separator?
2300             int gs2 = groupingSize2 == 0 ? groupingSize : groupingSize2;
2301
2302             // Strict parsing leading zeroes.  If a leading zero would
2303             // be forced by the pattern, then don't fail strict parsing.
2304             boolean strictLeadingZero = false;
2305             int leadingZeroPos   = 0;
2306             int leadingZeroCount = 0;
2307             
2308             // equivalent grouping and decimal support
2309             
2310             // TODO markdavis Cache these if it makes a difference in performance.
2311             UnicodeSet decimalSet = new UnicodeSet(getSimilarDecimals(decimal, strictParse));
2312             UnicodeSet groupingSet = new UnicodeSet(strictParse ? strictDefaultGroupingSeparators : defaultGroupingSeparators)
2313                 .add(grouping).removeAll(decimalSet);
2314             
2315             // we are guaranteed that 
2316             // decimalSet contains the decimal, and 
2317             // groupingSet contains the groupingSeparator
2318             // (unless decimal and grouping are the same, which should never happen. But in that case, groupingSet will just be empty.)
2319
2320
2321             // We have to track digitCount ourselves, because digits.count will
2322             // pin when the maximum allowable digits is reached.
2323             int digitCount = 0;
2324             
2325             int backup = -1;
2326             for (; position < text.length(); ++position)
2327             {
2328                 char ch = text.charAt(position);
2329
2330                 /* We recognize all digit ranges, not only the Latin digit range
2331                  * '0'..'9'.  We do so by using the UCharacter.digit() method,
2332                  * which converts a valid Unicode digit to the range 0..9.
2333                  *
2334                  * The character 'ch' may be a digit.  If so, place its value
2335                  * from 0 to 9 in 'digit'.  First try using the locale digit,
2336                  * which may or MAY NOT be a standard Unicode digit range.  If
2337                  * this fails, try using the standard Unicode digit ranges by
2338                  * calling UCharacter.digit().  If this also fails, digit will
2339                  * have a value outside the range 0..9.
2340                  */
2341                 digit = ch - zero;
2342                 if (digit < 0 || digit > 9) digit = UCharacter.digit(ch, 10);
2343
2344                 if (digit == 0)
2345                 {
2346                     // Cancel out backup setting (see grouping handler below)
2347                     if (strictParse && backup != -1) {
2348                         // comma followed by digit, so group before comma is a 
2349                         // secondary group.  If there was a group separator
2350                         // before that, the group must == the secondary group
2351                         // length, else it can be <= the the secondary group
2352                         // length.
2353                         if ((lastGroup != -1 && backup - lastGroup - 1 != gs2) ||
2354                             (lastGroup == -1 && position - oldStart - 1 > gs2)) {
2355                             strictFail = true;
2356                             break;
2357                         }
2358                         lastGroup = backup;
2359                     }
2360                     backup = -1; // Do this BEFORE continue statement below!!!
2361                     sawDigit = true;
2362
2363                     // Handle leading zeros
2364                     if (digits.count == 0)
2365                     {
2366                         if (!sawDecimal) {
2367                             if (strictParse && !isExponent) {
2368                                 // Allow leading zeros in exponents
2369                                 // Count leading zeros for checking later
2370                                 if (!strictLeadingZero) leadingZeroPos = position + 1;
2371                                 strictLeadingZero = true;
2372                                 ++leadingZeroCount;                                
2373                             }
2374                             // Ignore leading zeros in integer part of number.
2375                             continue;
2376                         }
2377
2378                         // If we have seen the decimal, but no significant digits yet,
2379                         // then we account for leading zeros by decrementing the
2380                         // digits.decimalAt into negative values.
2381                         --digits.decimalAt;
2382                     }
2383                     else
2384                     {
2385                         ++digitCount;
2386                         digits.append((char)(digit + '0'));
2387                     }
2388                 }
2389                 else if (digit > 0 && digit <= 9) // [sic] digit==0 handled above
2390                 {
2391                     if (strictParse) {
2392                         if (backup != -1) {
2393                             if ((lastGroup != -1 && backup - lastGroup - 1 != gs2) ||
2394                                 (lastGroup == -1 && position - oldStart - 1 > gs2)) {
2395                                 strictFail = true;
2396                                 break;
2397                             }
2398                             lastGroup = backup;
2399                         }
2400                     }
2401
2402                     sawDigit = true;
2403                     ++digitCount;
2404                     digits.append((char)(digit + '0'));
2405
2406                     // Cancel out backup setting (see grouping handler below)
2407                     backup = -1;
2408                 }
2409                 else if (!isExponent && decimalSet.contains(ch))
2410                 {
2411                     if (strictParse) {
2412                         if (backup != -1 ||
2413                             (lastGroup != -1 && position - lastGroup != groupingSize + 1)) {
2414                             strictFail = true;
2415                             break;
2416                         }
2417                     }
2418                     // If we're only parsing integers, or if we ALREADY saw the
2419                     // decimal, then don't parse this one.
2420                     if (isParseIntegerOnly() || sawDecimal) break;
2421                     digits.decimalAt = digitCount; // Not digits.count!
2422                     sawDecimal = true;
2423                     
2424                     // Once we see a decimal character, we only accept that decimal character from then on.
2425                     decimalSet.set(ch,ch);
2426                 }
2427                 else if (!isExponent && isGroupingUsed() && groupingSet.contains(ch))
2428                 {
2429                     if (sawDecimal) {
2430                         break;
2431                     }
2432                     if (strictParse) {
2433                         if ((!sawDigit || backup != -1)) {
2434                             // leading group, or two group separators in a row
2435                             strictFail = true;
2436                             break;
2437                         }
2438                     }
2439                     // Once we see a grouping character, we only accept that grouping character from then on.
2440                     groupingSet.set(ch,ch);
2441                     
2442                     // Ignore grouping characters, if we are using them, but require
2443                     // that they be followed by a digit.  Otherwise we backup and
2444                     // reprocess them.
2445                     backup = position;
2446                 }
2447                 else if (!isExponent && !sawExponent &&
2448                          text.regionMatches(position, exponentSep,
2449                                             0, exponentSep.length()))
2450                 {
2451                     // Parse sign, if present
2452                     boolean negExp = false;
2453                     int pos = position + exponentSep.length();
2454                     if (pos < text.length()) {
2455                         ch = text.charAt(pos);
2456                         if (ch == symbols.getPlusSign()) {
2457                             ++pos;
2458                         } else if (ch == symbols.getMinusSign()) {
2459                             ++pos;
2460                             negExp = true;
2461                         }
2462                     }
2463
2464                     DigitList exponentDigits = new DigitList();
2465                     exponentDigits.count = 0;
2466                     while (pos < text.length()) {
2467                         digit = text.charAt(pos) - zero;
2468                         if (digit < 0 || digit > 9) {
2469                             /*
2470                               Can't parse "[1E0]" when pattern is "0.###E0;[0.###E0]"
2471                               Should update reassign the value of 'ch' in the
2472                               code:  digit = Character.digit(ch, 10);
2473                               [Richard/GCL]
2474                             */
2475                             digit = UCharacter.digit(text.charAt(pos), 10);
2476                         }
2477                         if (digit >= 0 && digit <= 9) {
2478                             exponentDigits.append((char)(digit + '0'));
2479                             ++pos;
2480                         } else {
2481                             break;
2482                         }
2483                     }
2484                     
2485                     if (exponentDigits.count > 0) {
2486                         // defer strict parse until we know we have a bona-fide exponent
2487                         if (strictParse) {
2488                             if (backup != -1 || lastGroup != -1) {
2489                                 strictFail = true;
2490                                 break;
2491                             }
2492                         }
2493
2494                         // Quick overflow check for exponential part.
2495                         // Actual limit check will be done later in this code.
2496                         if (exponentDigits.count > 10 /* maximum decimal digits for int */) {
2497                             if (negExp) {
2498                                 // set underflow flag
2499                                 status[STATUS_UNDERFLOW] = true;
2500                             } else {
2501                                 // set infinite flag
2502                                 status[STATUS_INFINITE] = true;
2503                             }
2504                         } else {
2505                             exponentDigits.decimalAt = exponentDigits.count;
2506                             exponent = exponentDigits.getLong();
2507                             if (negExp) {
2508                                 exponent = -exponent;
2509                             }
2510                         }
2511                         position = pos; // Advance past the exponent
2512                         sawExponent = true;
2513                     }
2514
2515                     break; // Whether we fail or succeed, we exit this loop
2516                 }
2517                 else break;
2518             }
2519
2520             if (backup != -1) position = backup;
2521
2522             // If there was no decimal point we have an integer
2523             if (!sawDecimal) digits.decimalAt = digitCount; // Not digits.count!            
2524             
2525             // check for strict parse errors
2526             if (strictParse && strictLeadingZero) {
2527                 if ((leadingZeroCount + digits.decimalAt) > this.getMinimumIntegerDigits()) {
2528                     parsePosition.setIndex(oldStart);
2529                     parsePosition.setErrorIndex(leadingZeroPos);
2530                     return false;
2531                 }
2532             }
2533             if (strictParse && !sawDecimal) {
2534                 if (lastGroup != -1 && position - lastGroup != groupingSize + 1) {
2535                     strictFail = true;
2536                 }
2537             }
2538             if (strictFail) {
2539                 // only set with strictParse and a leading zero error
2540                 // leading zeros are an error with strict parsing except
2541                 // immediately before nondigit (except group separator 
2542                 // followed by digit), or end of text.
2543                 
2544                 parsePosition.setIndex(oldStart);
2545                 parsePosition.setErrorIndex(position);
2546                 return false;
2547             }
2548
2549             // Adjust for exponent, if any
2550             exponent += digits.decimalAt;
2551             if (exponent < -PARSE_MAX_EXPONENT) {
2552                 status[STATUS_UNDERFLOW] = true;
2553             } else if (exponent > PARSE_MAX_EXPONENT) {
2554                 status[STATUS_INFINITE] = true;
2555             } else {
2556                 digits.decimalAt = (int)exponent;
2557             }
2558
2559             // If none of the text string was recognized.  For example, parse
2560             // "x" with pattern "#0.00" (return index and error index both 0)
2561             // parse "$" with pattern "$#0.00". (return index 0 and error index
2562             // 1).
2563             if (!sawDigit && digitCount == 0) {
2564                 parsePosition.setIndex(oldStart);
2565                 parsePosition.setErrorIndex(oldStart);
2566                 return false;
2567             }
2568         }
2569
2570         // Match padding before suffix
2571         if (formatWidth > 0 && padPosition == PAD_BEFORE_SUFFIX) {
2572             position = skipPadding(text, position);
2573         }
2574
2575         // Match positive and negative suffixes; prefer longest match.
2576         if (posMatch >= 0) {
2577             posMatch = compareAffix(text, position, false, false, posSuffix, type, currency);
2578         }
2579         if (negMatch >= 0) {
2580             negMatch = compareAffix(text, position, true, false, negSuffix, type, currency);
2581         }
2582         if (posMatch >= 0 && negMatch >= 0) {
2583             if (posMatch > negMatch) {
2584                 negMatch = -1;
2585             } else if (negMatch > posMatch) {
2586                 posMatch = -1;
2587             }  
2588         }
2589
2590         // Fail if neither or both
2591         if ((posMatch >= 0) == (negMatch >= 0)) {
2592             parsePosition.setErrorIndex(position);
2593             return false;
2594         }
2595
2596         position += (posMatch>=0 ? posMatch : negMatch);
2597
2598         // Match padding after suffix
2599         if (formatWidth > 0 && padPosition == PAD_AFTER_SUFFIX) {
2600             position = skipPadding(text, position);
2601         }
2602
2603         parsePosition.setIndex(position);
2604
2605         status[STATUS_POSITIVE] = (posMatch >= 0);
2606
2607         if (parsePosition.getIndex() == oldStart) {
2608             parsePosition.setErrorIndex(position);
2609             return false;
2610         }
2611         return true;
2612     }
2613
2614     /**
2615      * Return characters that are used where this decimal is used.
2616      * @param decimal
2617      * @param strictParse 
2618      * @return
2619      */
2620     private UnicodeSet getSimilarDecimals(char decimal, boolean strictParse) {
2621         if (dotEquivalents.contains(decimal)) {
2622             return strictParse ? strictDotEquivalents : dotEquivalents;
2623         }
2624         if (commaEquivalents.contains(decimal)) {
2625             return strictParse ? strictCommaEquivalents : commaEquivalents;
2626         }
2627         // if there is no match, return the character itself
2628         return new UnicodeSet().add(decimal);
2629     }
2630
2631     /**
2632      * Starting at position, advance past a run of pad characters, if any.
2633      * Return the index of the first character after position that is not a pad
2634      * character.  Result is >= position.
2635      */
2636     private final int skipPadding(String text, int position) {
2637         while (position < text.length() && text.charAt(position) == pad) {
2638             ++position;
2639         }
2640         return position;
2641     }
2642
2643     /*
2644      * Return the length matched by the given affix, or -1 if none.
2645      * Runs of white space in the affix, match runs of white space in
2646      * the input.  Pattern white space and input white space are
2647      * determined differently; see code.
2648      * @param text input text
2649      * @param pos offset into input at which to begin matching
2650      * @param isNegative
2651      * @param isPrefix
2652      * @param affixPat affix pattern used for currency affix comparison
2653      * @param type compare against currency type, LONG_NAME only or not.
2654      * @param currency return value for parsed currency, for generic
2655      * currency parsing mode, or null for normal parsing. In generic
2656      * currency parsing mode, any currency is parsed, not just the
2657      * currency that this formatter is set to.
2658      * @return length of input that matches, or -1 if match failure
2659      */
2660     private int compareAffix(String text, int pos, 
2661                              boolean isNegative, boolean isPrefix,
2662                              String affixPat,
2663                              int type,
2664                              Currency[] currency) {
2665         if (currency != null || currencyChoice != null ||
2666             currencySignCount > 0) {
2667                 return compareComplexAffix(affixPat, text, pos, type, currency);
2668         }
2669         if (isPrefix) {
2670             return compareSimpleAffix(isNegative ? negativePrefix : positivePrefix,
2671                                       text, pos);
2672         } else {
2673             return compareSimpleAffix(isNegative ? negativeSuffix : positiveSuffix,
2674                                       text, pos);
2675         }
2676
2677     }
2678
2679
2680
2681     /**
2682      * Return the length matched by the given affix, or -1 if none.
2683      * Runs of white space in the affix, match runs of white space in
2684      * the input.  Pattern white space and input white space are
2685      * determined differently; see code.
2686      * @param affix pattern string, taken as a literal
2687      * @param input input text
2688      * @param pos offset into input at which to begin matching
2689      * @return length of input that matches, or -1 if match failure
2690      */
2691     private static int compareSimpleAffix(String affix, String input, int pos) {
2692         int start = pos;
2693         for (int i=0; i<affix.length(); ) {
2694             int c = UTF16.charAt(affix, i);
2695             int len = UTF16.getCharCount(c);
2696             if (UCharacterProperty.isRuleWhiteSpace(c)) {
2697                 // We may have a pattern like: \u200F \u0020
2698                 //        and input text like: \u200F \u0020
2699                 // Note that U+200F and U+0020 are RuleWhiteSpace but only
2700                 // U+0020 is UWhiteSpace.  So we have to first do a direct
2701                 // match of the run of RULE whitespace in the pattern,
2702                 // then match any extra characters.
2703                 boolean literalMatch = false;
2704                 while (pos < input.length() &&
2705                        UTF16.charAt(input, pos) == c) {
2706                     literalMatch = true;
2707                     i += len;
2708                     pos += len;
2709                     if (i == affix.length()) {
2710                         break;
2711                     }
2712                     c = UTF16.charAt(affix, i);
2713                     len = UTF16.getCharCount(c);
2714                     if (!UCharacterProperty.isRuleWhiteSpace(c)) {
2715                         break;
2716                     }
2717                 }
2718                 
2719                 // Advance over run in affix
2720                 i = skipRuleWhiteSpace(affix, i);
2721                 
2722                 // Advance over run in input text
2723                 // Must see at least one white space char in input,
2724                 // unless we've already matched some characters literally.
2725                 int s = pos;
2726                 pos = skipUWhiteSpace(input, pos);
2727                 if (pos == s && !literalMatch) {
2728                     return -1;
2729                 }
2730                 // If we skip UWhiteSpace in the input text, we need to skip it in the pattern.
2731                 // Otherwise, the previous lines may have skipped over text (such as U+00A0) that
2732                 // is also in the affix.
2733                 i = skipUWhiteSpace(affix, i);
2734             } else {
2735                 if (pos < input.length() &&
2736                     UTF16.charAt(input, pos) == c) {
2737                     i += len;
2738                     pos += len;
2739                 } else {
2740                     return -1;
2741                 }
2742             }
2743         }
2744         return pos - start;
2745     }
2746
2747     /**
2748      * Skip over a run of zero or more isRuleWhiteSpace() characters at
2749      * pos in text.
2750      */
2751     private static int skipRuleWhiteSpace(String text, int pos) {
2752         while (pos < text.length()) {
2753             int c = UTF16.charAt(text, pos);
2754             if (!UCharacterProperty.isRuleWhiteSpace(c)) {
2755                 break;
2756             }
2757             pos += UTF16.getCharCount(c);
2758         }
2759         return pos;
2760     }
2761
2762     /**
2763      * Skip over a run of zero or more isUWhiteSpace() characters at pos
2764      * in text.
2765      */
2766     private static int skipUWhiteSpace(String text, int pos) {
2767         while (pos < text.length()) {
2768             int c = UTF16.charAt(text, pos);
2769             if (!UCharacter.isUWhiteSpace(c)) {
2770                 break;
2771             }
2772             pos += UTF16.getCharCount(c);
2773         }
2774         return pos;
2775     }
2776
2777     /*
2778      * Return the length matched by the given affix, or -1 if none.
2779      * @param affixPat pattern string
2780      * @param text input text
2781      * @param pos offset into input at which to begin matching
2782      * @param type parse against currency type, LONG_NAME only or not.
2783      * @param currency return value for parsed currency, for generic
2784      * currency parsing mode, or null for normal parsing. In generic
2785      * currency parsing mode, any currency is parsed, not just the
2786      * currency that this formatter is set to.
2787      * @return position after the matched text, or -1 if match failure
2788      */
2789     private int compareComplexAffix(String affixPat, String text, int pos,
2790                                     int type, Currency[] currency) {
2791         int start = pos;
2792         for (int i=0; 
2793              i < affixPat.length() && pos >= 0; ) {
2794             char c = affixPat.charAt(i++);
2795             if (c == QUOTE) {
2796                 for (;;) {
2797                     int j = affixPat.indexOf(QUOTE, i);
2798                     if (j == i) {
2799                         pos = match(text, pos, QUOTE);
2800                         i = j+1;
2801                         break;
2802                     } else if (j > i) {
2803                         pos = match(text, pos, affixPat.substring(i, j));
2804                         i = j+1;
2805                         if (i<affixPat.length() &&
2806                             affixPat.charAt(i)==QUOTE) {
2807                             pos = match(text, pos, QUOTE);
2808                             ++i;
2809                             // loop again
2810                         } else {
2811                             break;
2812                         }
2813                     } else {
2814                         // Unterminated quote; should be caught by apply
2815                         // pattern.
2816                         throw new RuntimeException();
2817                     }
2818                 }
2819                 continue;
2820             }
2821
2822             switch (c) {
2823             case CURRENCY_SIGN:
2824                 // since the currency names in choice format is saved
2825                 // the same way as other currency names, 
2826                 // do not need to do currency choice parsing here.
2827                 // the general currency parsing parse against all names,
2828                 // including names in choice format.
2829                 //assert(currency != null ||
2830                 //       (getCurrency() != null && currencyChoice != null));
2831                 boolean intl = i<affixPat.length() &&
2832                     affixPat.charAt(i) == CURRENCY_SIGN;
2833                 if (intl) {
2834                     ++i;
2835                 }
2836                 boolean plural = i<affixPat.length() &&
2837                     affixPat.charAt(i) == CURRENCY_SIGN;
2838                 if (plural) {
2839                     ++i;
2840                     intl = false;
2841                 }
2842                 // Parse generic currency -- anything for which we
2843                 // have a display name, or any 3-letter ISO code.
2844                 // Try to parse display name for our locale; first
2845                 // determine our locale.
2846                 // TODO: use locale in CurrencyPluralInfo
2847                 ULocale uloc = getLocale(ULocale.VALID_LOCALE);
2848                 if (uloc == null) {
2849                     // applyPattern has been called; use the symbols
2850                     uloc = symbols.getLocale(ULocale.VALID_LOCALE);
2851                 }
2852                 // Delegate parse of display name => ISO code to Currency
2853                 ParsePosition ppos = new ParsePosition(pos);
2854                 // using Currency.parse to handle mixed style parsing.
2855                 String iso = Currency.parse(uloc, text, type, ppos);
2856
2857                 // If parse succeeds, populate currency[0]
2858                 if (iso != null) {
2859                     if (currency != null) {
2860                         currency[0] = Currency.getInstance(iso);
2861                     }
2862                     pos = ppos.getIndex();
2863                 } else {
2864                     pos = -1;
2865                 }
2866                 continue;
2867             case PATTERN_PERCENT:
2868                 c = symbols.getPercent();
2869                 break;
2870             case PATTERN_PER_MILLE:
2871                 c = symbols.getPerMill();
2872                 break;
2873             case PATTERN_MINUS:
2874                 c = symbols.getMinusSign();
2875                 break;
2876             }
2877             pos = match(text, pos, c);
2878             if (UCharacterProperty.isRuleWhiteSpace(c)) {
2879                 i = skipRuleWhiteSpace(affixPat, i);
2880             }
2881         }
2882
2883         return pos - start;
2884     }
2885
2886     /**
2887      * Match a single character at text[pos] and return the index of the
2888      * next character upon success.  Return -1 on failure.  If
2889      * isRuleWhiteSpace(ch) then match a run of white space in text.
2890      */
2891     static final int match(String text, int pos, int ch) {
2892         if (pos >= text.length()) { 
2893             return -1; 
2894         } 
2895         if (UCharacterProperty.isRuleWhiteSpace(ch)) {
2896             // Advance over run of white space in input text
2897             // Must see at least one white space char in input
2898             int s = pos;
2899             pos = skipUWhiteSpace(text, pos);
2900             if (pos == s) {
2901                 return -1;
2902             }
2903             return pos;
2904         }
2905         return (pos >= 0 && UTF16.charAt(text, pos) == ch) ?
2906             (pos + UTF16.getCharCount(ch)) : -1;
2907     }
2908
2909     /**
2910      * Match a string at text[pos] and return the index of the next
2911      * character upon success.  Return -1 on failure.  Match a run of
2912      * white space in str with a run of white space in text.
2913      */
2914     static final int match(String text, int pos, String str) {
2915         for (int i=0; i<str.length() && pos >= 0; ) {
2916             int ch = UTF16.charAt(str, i);
2917             i += UTF16.getCharCount(ch);
2918             pos = match(text, pos, ch);
2919             if (UCharacterProperty.isRuleWhiteSpace(ch)) {
2920                 i = skipRuleWhiteSpace(str, i);
2921             }
2922         }
2923         return pos;
2924     }
2925
2926     /**
2927      * Returns a copy of the decimal format symbols used by this format.
2928      * @return desired DecimalFormatSymbols
2929      * @see DecimalFormatSymbols
2930      * @stable ICU 2.0
2931      */
2932     public DecimalFormatSymbols getDecimalFormatSymbols() {
2933         try {
2934             // don't allow multiple references
2935             return (DecimalFormatSymbols) symbols.clone();
2936         } catch (Exception foo) {
2937             return null; // should never happen
2938         }
2939     }
2940
2941
2942     /**
2943      * Sets the decimal format symbols used by this format.  The
2944      * format uses a copy of the provided symbols.
2945      * @param newSymbols desired DecimalFormatSymbols
2946      * @see DecimalFormatSymbols
2947      * @stable ICU 2.0
2948      */
2949     public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
2950         symbols = (DecimalFormatSymbols) newSymbols.clone();
2951         setCurrencyForSymbols();
2952         expandAffixes(null);
2953     }
2954
2955     /**
2956      * Update the currency object to match the symbols.  This method
2957      * is used only when the caller has passed in a symbols object
2958      * that may not be the default object for its locale.
2959      */
2960     private void setCurrencyForSymbols() {
2961         /*Bug 4212072
2962           Update the affix strings according to symbols in order to keep
2963           the affix strings up to date.
2964           [Richard/GCL]
2965         */
2966         
2967         // With the introduction of the Currency object, the currency
2968         // symbols in the DFS object are ignored.  For backward
2969         // compatibility, we check any explicitly set DFS object.  If it
2970         // is a default symbols object for its locale, we change the
2971         // currency object to one for that locale.  If it is custom,
2972         // we set the currency to null.
2973         DecimalFormatSymbols def =
2974             new DecimalFormatSymbols(symbols.getLocale());
2975         
2976         if (symbols.getCurrencySymbol().equals(
2977                 def.getCurrencySymbol()) &&
2978             symbols.getInternationalCurrencySymbol().equals(
2979                 def.getInternationalCurrencySymbol())) {
2980             setCurrency(Currency.getInstance(symbols.getLocale()));
2981         } else {
2982             setCurrency(null);
2983         }
2984     }
2985
2986     /**
2987      * Get the positive prefix.
2988      * <P>Examples: +123, $123, sFr123
2989      * @stable ICU 2.0
2990      */
2991     public String getPositivePrefix () {
2992         return positivePrefix;
2993     }
2994
2995     /**
2996      * Set the positive prefix.
2997      * <P>Examples: +123, $123, sFr123
2998      * @stable ICU 2.0
2999      */
3000     public void setPositivePrefix (String newValue) {
3001         positivePrefix = newValue;
3002         posPrefixPattern = null;
3003     }
3004
3005     /**
3006      * Get the negative prefix.
3007      * <P>Examples: -123, ($123) (with negative suffix), sFr-123
3008      * @stable ICU 2.0
3009      */
3010     public String getNegativePrefix () {
3011         return negativePrefix;
3012     }
3013
3014     /**
3015      * Set the negative prefix.
3016      * <P>Examples: -123, ($123) (with negative suffix), sFr-123
3017      * @stable ICU 2.0
3018      */
3019     public void setNegativePrefix (String newValue) {
3020         negativePrefix = newValue;
3021         negPrefixPattern = null;
3022     }
3023
3024     /**
3025      * Get the positive suffix.
3026      * <P>Example: 123%
3027      * @stable ICU 2.0
3028      */
3029     public String getPositiveSuffix () {
3030         return positiveSuffix;
3031     }
3032
3033     /**
3034      * Set the positive suffix.
3035      * <P>Example: 123%
3036      * @stable ICU 2.0
3037      */
3038     public void setPositiveSuffix (String newValue) {
3039         positiveSuffix = newValue;
3040         posSuffixPattern = null;
3041     }
3042
3043     /**
3044      * Get the negative suffix.
3045      * <P>Examples: -123%, ($123) (with positive suffixes)
3046      * @stable ICU 2.0
3047      */
3048     public String getNegativeSuffix () {
3049         return negativeSuffix;
3050     }
3051
3052     /**
3053      * Set the positive suffix.
3054      * <P>Examples: 123%
3055      * @stable ICU 2.0
3056      */
3057     public void setNegativeSuffix (String newValue) {
3058         negativeSuffix = newValue;
3059         negSuffixPattern = null;
3060     }
3061
3062     /**
3063      * Get the multiplier for use in percent, permill, etc.
3064      * For a percentage, set the suffixes to have "%" and the multiplier to be 100.
3065      * (For Arabic, use arabic percent symbol).
3066      * For a permill, set the suffixes to have "\u2031" and the multiplier to be 1000.
3067      * <P>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
3068      * @stable ICU 2.0
3069      */
3070     public int getMultiplier () {
3071         return multiplier;
3072     }
3073
3074     /**
3075      * Set the multiplier for use in percent, permill, etc.
3076      * For a percentage, set the suffixes to have "%" and the multiplier to be 100.
3077      * (For Arabic, use arabic percent symbol).
3078      * For a permill, set the suffixes to have "\u2031" and the multiplier to be 1000.
3079      * <P>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
3080      * @stable ICU 2.0
3081      */
3082     public void setMultiplier (int newValue) {
3083         if (newValue == 0) {
3084             throw new IllegalArgumentException("Bad multiplier: " + newValue);
3085         }
3086         multiplier = newValue;
3087     }
3088     
3089     // [NEW]
3090     /**
3091      * Get the rounding increment.
3092      * @return A positive rounding increment, or <code>null</code> if rounding
3093      * is not in effect.
3094      * @see #setRoundingIncrement
3095      * @see #getRoundingMode
3096      * @see #setRoundingMode
3097      * @stable ICU 2.0
3098      */
3099 //#if defined(FOUNDATION10) || defined(ECLIPSE_FRAGMENT)
3100 //##    public BigDecimal getRoundingIncrement() {
3101 //##        if (roundingIncrementICU == null) return null;
3102 //##        return new BigDecimal(roundingIncrementICU.toString());
3103 //##    }
3104 //#else
3105     public java.math.BigDecimal getRoundingIncrement() {
3106         if (roundingIncrementICU == null) return null;
3107         return roundingIncrementICU.toBigDecimal();
3108     }
3109 //#endif
3110     
3111 //#if defined(FOUNDATION10)
3112 //#else
3113     // [NEW]
3114     /**
3115      * Set the rounding increment.  This method also controls whether
3116      * rounding is enabled.
3117      * @param newValue A positive rounding increment, or <code>null</code> or
3118      * <code>BigDecimal(0.0)</code> to disable rounding.
3119      * @exception IllegalArgumentException if <code>newValue</code> is < 0.0
3120      * @see #getRoundingIncrement
3121      * @see #getRoundingMode
3122      * @see #setRoundingMode
3123      * @stable ICU 2.0
3124      */
3125     public void setRoundingIncrement(java.math.BigDecimal newValue) {
3126         if (newValue == null) {
3127             setRoundingIncrement((BigDecimal)null);
3128         } else {
3129             setRoundingIncrement(new BigDecimal(newValue));
3130         }
3131     }
3132 //#endif
3133     
3134     // [NEW]
3135     /**
3136      * Set the rounding increment.  This method also controls whether
3137      * rounding is enabled.
3138      * @param newValue A positive rounding increment, or <code>null</code> or
3139      * <code>BigDecimal(0.0)</code> to disable rounding.
3140      * @exception IllegalArgumentException if <code>newValue</code> is < 0.0
3141      * @see #getRoundingIncrement
3142      * @see #getRoundingMode
3143      * @see #setRoundingMode
3144      * @stable ICU 3.6
3145      */
3146     public void setRoundingIncrement(BigDecimal newValue) {
3147         int i = newValue == null
3148             ? 0 : newValue.compareTo(BigDecimal.ZERO);
3149         if (i < 0) {
3150             throw new IllegalArgumentException("Illegal rounding increment");
3151         }
3152         if (i == 0) {
3153             setInternalRoundingIncrement(null);
3154         } else {
3155             setInternalRoundingIncrement(newValue);
3156         }
3157         setRoundingDouble();
3158     }
3159
3160     // [NEW]
3161     /**
3162      * Set the rounding increment.  This method also controls whether
3163      * rounding is enabled.
3164      * @param newValue A positive rounding increment, or 0.0 to disable
3165      * rounding.
3166      * @exception IllegalArgumentException if <code>newValue</code> is < 0.0
3167      * @see #getRoundingIncrement
3168      * @see #getRoundingMode
3169      * @see #setRoundingMode
3170      * @stable ICU 2.0
3171      */
3172     public void setRoundingIncrement(double newValue) {
3173         if (newValue < 0.0) {
3174             throw new IllegalArgumentException("Illegal rounding increment");
3175         }
3176         roundingDouble = newValue;
3177         roundingDoubleReciprocal = 0.0d;
3178         if (newValue == 0.0d) {
3179             setRoundingIncrement((BigDecimal)null);
3180         } else {
3181             roundingDouble = newValue;
3182             if (roundingDouble < 1.0d) {
3183                 double rawRoundedReciprocal = 1.0d/roundingDouble;
3184                 setRoundingDoubleReciprocal(rawRoundedReciprocal);
3185             }
3186             setInternalRoundingIncrement(new BigDecimal(newValue));
3187         }
3188     }
3189
3190
3191     private void setRoundingDoubleReciprocal(double rawRoundedReciprocal) {
3192         roundingDoubleReciprocal = Math.rint(rawRoundedReciprocal);
3193         if (Math.abs(rawRoundedReciprocal - roundingDoubleReciprocal) > roundingIncrementEpsilon) {
3194             roundingDoubleReciprocal = 0.0d;
3195         }
3196     }
3197     
3198     static final double roundingIncrementEpsilon = 0.000000001;
3199     
3200     /**
3201      * Get the rounding mode.
3202      * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code>
3203      * and <code>BigDecimal.ROUND_UNNECESSARY</code>.
3204      * @see #setRoundingIncrement
3205      * @see #getRoundingIncrement
3206      * @see #setRoundingMode
3207      * @see java.math.BigDecimal
3208      * @stable ICU 2.0
3209      */
3210     public int getRoundingMode() {
3211         return roundingMode;
3212     }
3213
3214     /**
3215      * Set the rounding mode.  This has no effect unless the rounding
3216      * increment is greater than zero.
3217      * @param roundingMode A rounding mode, between
3218      * <code>BigDecimal.ROUND_UP</code> and
3219      * <code>BigDecimal.ROUND_UNNECESSARY</code>.
3220      * @exception IllegalArgumentException if <code>roundingMode</code>
3221      * is unrecognized.
3222      * @see #setRoundingIncrement
3223      * @see #getRoundingIncrement
3224      * @see #getRoundingMode
3225      * @see java.math.BigDecimal
3226      * @stable ICU 2.0
3227      */
3228     public void setRoundingMode(int roundingMode) {
3229         if (roundingMode < BigDecimal.ROUND_UP
3230             || roundingMode > BigDecimal.ROUND_UNNECESSARY) {
3231             throw new IllegalArgumentException("Invalid rounding mode: "
3232                                                + roundingMode);
3233         }
3234
3235         this.roundingMode = roundingMode;
3236
3237         if (getRoundingIncrement() == null) {
3238             setRoundingIncrement(Math.pow(10.0,(double)-getMaximumFractionDigits()));
3239         }
3240     }
3241
3242     // [NEW]
3243     /**
3244      * Get the width to which the output of <code>format()</code> is padded.
3245      * The width is counted in 16-bit code units.
3246      * @return the format width, or zero if no padding is in effect
3247      * @see #setFormatWidth
3248      * @see #getPadCharacter
3249      * @see #setPadCharacter
3250      * @see #getPadPosition
3251      * @see #setPadPosition
3252      * @stable ICU 2.0
3253      */
3254     public int getFormatWidth() {
3255         return formatWidth;
3256     }
3257
3258     // [NEW]
3259     /**
3260      * Set the width to which the output of <code>format()</code> is padded.
3261      * The width is counted in 16-bit code units.
3262      * This method also controls whether padding is enabled.
3263      * @param width the width to which to pad the result of
3264      * <code>format()</code>, or zero to disable padding
3265      * @exception IllegalArgumentException if <code>width</code> is < 0
3266      * @see #getFormatWidth
3267      * @see #getPadCharacter
3268      * @see #setPadCharacter
3269      * @see #getPadPosition
3270      * @see #setPadPosition
3271      * @stable ICU 2.0
3272      */
3273     public void setFormatWidth(int width) {
3274         if (width < 0) {
3275             throw new IllegalArgumentException("Illegal format width");
3276         }
3277         formatWidth = width;
3278     }
3279
3280     // [NEW]
3281     /**
3282      * Get the character used to pad to the format width.  The default is ' '.
3283      * @return the pad character
3284      * @see #setFormatWidth
3285      * @see #getFormatWidth
3286      * @see #setPadCharacter
3287      * @see #getPadPosition
3288      * @see #setPadPosition
3289      * @stable ICU 2.0
3290      */
3291     public char getPadCharacter() {
3292         return pad;
3293     }
3294
3295     // [NEW]
3296     /**
3297      * Set the character used to pad to the format width.  If padding
3298      * is not enabled, then this will take effect if padding is later
3299      * enabled.
3300      * @param padChar the pad character
3301      * @see #setFormatWidth
3302      * @see #getFormatWidth
3303      * @see #getPadCharacter
3304      * @see #getPadPosition
3305      * @see #setPadPosition
3306      * @stable ICU 2.0
3307      */
3308     public void setPadCharacter(char padChar) {
3309         pad = padChar;
3310     }
3311
3312     // [NEW]
3313     /**
3314      * Get the position at which padding will take place.  This is the location
3315      * at which padding will be inserted if the result of <code>format()</code>
3316      * is shorter than the format width.
3317      * @return the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
3318      * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
3319      * <code>PAD_AFTER_SUFFIX</code>.
3320      * @see #setFormatWidth
3321      * @see #getFormatWidth
3322      * @see #setPadCharacter
3323      * @see #getPadCharacter
3324      * @see #setPadPosition
3325      * @see #PAD_BEFORE_PREFIX
3326      * @see #PAD_AFTER_PREFIX
3327      * @see #PAD_BEFORE_SUFFIX
3328      * @see #PAD_AFTER_SUFFIX
3329      * @stable ICU 2.0
3330      */
3331     public int getPadPosition() {
3332         return padPosition;
3333     }
3334
3335     // [NEW]
3336     /**
3337      * Set the position at which padding will take place.  This is the location
3338      * at which padding will be inserted if the result of <code>format()</code>
3339      * is shorter than the format width.  This has no effect unless padding is
3340      * enabled.
3341      * @param padPos the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
3342      * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
3343      * <code>PAD_AFTER_SUFFIX</code>.
3344      * @exception IllegalArgumentException if the pad position in
3345      * unrecognized
3346      * @see #setFormatWidth
3347      * @see #getFormatWidth
3348      * @see #setPadCharacter
3349      * @see #getPadCharacter
3350      * @see #getPadPosition
3351      * @see #PAD_BEFORE_PREFIX
3352      * @see #PAD_AFTER_PREFIX
3353      * @see #PAD_BEFORE_SUFFIX
3354      * @see #PAD_AFTER_SUFFIX
3355      * @stable ICU 2.0
3356      */
3357     public void setPadPosition(int padPos) {
3358         if (padPos < PAD_BEFORE_PREFIX || padPos > PAD_AFTER_SUFFIX) {
3359             throw new IllegalArgumentException("Illegal pad position");
3360         }
3361         padPosition = padPos;
3362     }
3363
3364     // [NEW]
3365     /**
3366      * Return whether or not scientific notation is used.
3367      * @return true if this object formats and parses scientific notation
3368      * @see #setScientificNotation
3369      * @see #getMinimumExponentDigits
3370      * @see #setMinimumExponentDigits
3371      * @see #isExponentSignAlwaysShown
3372      * @see #setExponentSignAlwaysShown
3373      * @stable ICU 2.0
3374      */
3375     public boolean isScientificNotation() {
3376         return useExponentialNotation;
3377     }
3378
3379     // [NEW]
3380     /**
3381      * Set whether or not scientific notation is used.  When scientific notation
3382      * is used, the effective maximum number of integer digits is <= 8.  If the
3383      * maximum number of integer digits is set to more than 8, the effective
3384      * maximum will be 1.  This allows this call to generate a 'default' scientific
3385      * number format without additional changes.
3386      * @param useScientific true if this object formats and parses scientific
3387      * notation
3388      * @see #isScientificNotation
3389      * @see #getMinimumExponentDigits
3390      * @see #setMinimumExponentDigits
3391      * @see #isExponentSignAlwaysShown
3392      * @see #setExponentSignAlwaysShown
3393      * @stable ICU 2.0
3394      */
3395     public void setScientificNotation(boolean useScientific) {
3396         useExponentialNotation = useScientific;
3397     }
3398
3399     // [NEW]
3400     /**
3401      * Return the minimum exponent digits that will be shown.
3402      * @return the minimum exponent digits that will be shown
3403      * @see #setScientificNotation
3404      * @see #isScientificNotation
3405      * @see #setMinimumExponentDigits
3406      * @see #isExponentSignAlwaysShown
3407      * @see #setExponentSignAlwaysShown
3408      * @stable ICU 2.0
3409      */
3410     public byte getMinimumExponentDigits() {
3411         return minExponentDigits;
3412     }
3413     
3414     // [NEW]
3415     /**
3416      * Set the minimum exponent digits that will be shown.  This has no
3417      * effect unless scientific notation is in use.
3418      * @param minExpDig a value >= 1 indicating the fewest exponent digits
3419      * that will be shown
3420      * @exception IllegalArgumentException if <code>minExpDig</code> < 1
3421      * @see #setScientificNotation
3422      * @see #isScientificNotation
3423      * @see #getMinimumExponentDigits
3424      * @see #isExponentSignAlwaysShown
3425      * @see #setExponentSignAlwaysShown
3426      * @stable ICU 2.0
3427      */
3428     public void setMinimumExponentDigits(byte minExpDig) {
3429         if (minExpDig < 1) {
3430             throw new IllegalArgumentException("Exponent digits must be >= 1");
3431         }
3432         minExponentDigits = minExpDig;
3433     }
3434
3435     // [NEW]
3436     /**
3437      * Return whether the exponent sign is always shown.
3438      * @return true if the exponent is always prefixed with either the
3439      * localized minus sign or the localized plus sign, false if only negative
3440      * exponents are prefixed with the localized minus sign.
3441      * @see #setScientificNotation
3442      * @see #isScientificNotation
3443      * @see #setMinimumExponentDigits
3444      * @see #getMinimumExponentDigits
3445      * @see #setExponentSignAlwaysShown
3446      * @stable ICU 2.0
3447      */
3448     public boolean isExponentSignAlwaysShown() {
3449         return exponentSignAlwaysShown;
3450     }
3451
3452     // [NEW]
3453     /**
3454      * Set whether the exponent sign is always shown.  This has no effect
3455      * unless scientific notation is in use.
3456      * @param expSignAlways true if the exponent is always prefixed with either
3457      * the localized minus sign or the localized plus sign, false if only
3458      * negative exponents are prefixed with the localized minus sign.
3459      * @see #setScientificNotation
3460      * @see #isScientificNotation
3461      * @see #setMinimumExponentDigits
3462      * @see #getMinimumExponentDigits
3463      * @see #isExponentSignAlwaysShown
3464      * @stable ICU 2.0
3465      */
3466     public void setExponentSignAlwaysShown(boolean expSignAlways) {
3467         exponentSignAlwaysShown = expSignAlways;
3468     }
3469
3470     /**
3471      * Return the grouping size. Grouping size is the number of digits between
3472      * grouping separators in the integer portion of a number.  For example,
3473      * in the number "123,456.78", the grouping size is 3.
3474      * @see #setGroupingSize
3475      * @see NumberFormat#isGroupingUsed
3476      * @see DecimalFormatSymbols#getGroupingSeparator
3477      * @stable ICU 2.0
3478      */
3479     public int getGroupingSize () {
3480         return groupingSize;
3481     }
3482
3483     /**
3484      * Set the grouping size. Grouping size is the number of digits between
3485      * grouping separators in the integer portion of a number.  For example,
3486      * in the number "123,456.78", the grouping size is 3.
3487      * @see #getGroupingSize
3488      * @see NumberFormat#setGroupingUsed
3489      * @see DecimalFormatSymbols#setGroupingSeparator
3490      * @stable ICU 2.0
3491      */
3492     public void setGroupingSize (int newValue) {
3493         groupingSize = (byte)newValue;
3494     }
3495
3496     // [NEW]
3497     /**
3498      * Return the secondary grouping size. In some locales one
3499      * grouping interval is used for the least significant integer
3500      * digits (the primary grouping size), and another is used for all
3501      * others (the secondary grouping size).  A formatter supporting a
3502      * secondary grouping size will return a positive integer unequal
3503      * to the primary grouping size returned by
3504      * <code>getGroupingSize()</code>.  For example, if the primary
3505      * grouping size is 4, and the secondary grouping size is 2, then
3506      * the number 123456789 formats as "1,23,45,6789", and the pattern
3507      * appears as "#,##,###0".
3508      * @return the secondary grouping size, or a value less than
3509      * one if there is none
3510      * @see #setSecondaryGroupingSize
3511      * @see NumberFormat#isGroupingUsed
3512      * @see DecimalFormatSymbols#getGroupingSeparator
3513      * @stable ICU 2.0
3514      */
3515     public int getSecondaryGroupingSize () {
3516         return groupingSize2;
3517     }
3518
3519     // [NEW]
3520     /**
3521      * Set the secondary grouping size. If set to a value less than 1,
3522      * then secondary grouping is turned off, and the primary grouping
3523      * size is used for all intervals, not just the least significant.
3524      * @see #getSecondaryGroupingSize
3525      * @see NumberFormat#setGroupingUsed
3526      * @see DecimalFormatSymbols#setGroupingSeparator
3527      * @stable ICU 2.0
3528      */
3529     public void setSecondaryGroupingSize (int newValue) {
3530         groupingSize2 = (byte)newValue;
3531     }
3532
3533     // [NEW]
3534     /**
3535      * Returns the MathContext
3536      * used by this format. 
3537      * @return desired MathContext
3538      * @see #mathContext
3539      * @see #getMathContext
3540      * @draft ICU 4.2
3541      * @provisional This API might change or be removed in a future release.
3542      */
3543     public MathContext getMathContextICU() {
3544         return mathContext;
3545     }
3546
3547 //#if defined(FOUNDATION10) || defined(J2SE13) || defined(J2SE14) || defined(ECLIPSE_FRAGMENT)
3548 //#else
3549     // [NEW]
3550     /**
3551      * Returns the MathContext
3552      * used by this format. 
3553      * @return desired MathContext
3554      * @see #mathContext
3555      * @see #getMathContext
3556      * @draft ICU 4.2
3557      * @provisional This API might change or be removed in a future release.
3558      */
3559     public java.math.MathContext getMathContext()
3560     {
3561         try
3562         {
3563             // don't allow multiple references
3564             return mathContext == null ?
3565                    null :
3566                    new java.math.MathContext(mathContext.getDigits(),
3567                                              java.math.RoundingMode.valueOf(mathContext.getRoundingMode()));
3568         }
3569         catch (Exception foo)
3570         {
3571             return null; // should never happen
3572         }
3573     }
3574 //#endif
3575
3576     // [NEW]
3577     /**
3578      * Sets the MathContext used by this format.
3579      * @param newValue desired MathContext
3580      * @see #mathContext
3581      * @see #getMathContext
3582      * @draft ICU 4.2
3583      * @provisional This API might change or be removed in a future release.
3584      */
3585     public void setMathContextICU(MathContext newValue) {
3586         mathContext = newValue;
3587     }
3588
3589 //#if defined(FOUNDATION10) || defined(J2SE13) || defined(J2SE14) || defined(ECLIPSE_FRAGMENT)
3590 //#else
3591     // [NEW]
3592     /**
3593      * Sets the MathContext used by this format.
3594      * @param newValue desired MathContext
3595      * @see #mathContext
3596      * @see #getMathContext
3597      * @draft ICU 4.2
3598      * @provisional This API might change or be removed in a future release.
3599      */
3600     public void setMathContext(java.math.MathContext newValue)
3601     {
3602         mathContext = new MathContext(newValue.getPrecision(),
3603                                       MathContext.SCIENTIFIC,
3604                                       false,
3605                                       (newValue.getRoundingMode()).ordinal()
3606                                       );
3607     }
3608 //#endif
3609
3610     /**
3611      * Allows you to get the behavior of the decimal separator with integers.
3612      * (The decimal separator will always appear with decimals.)
3613      * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
3614      * @stable ICU 2.0
3615      */
3616     public boolean isDecimalSeparatorAlwaysShown() {
3617         return decimalSeparatorAlwaysShown;
3618     }
3619
3620     /**
3621      * Allows you to set the behavior of the decimal separator with integers.
3622      * (The decimal separator will always appear with decimals.)
3623      *
3624      * <p>This only affects formatting, and only where
3625      * there might be no digits after the decimal point, e.g.,
3626      * if true,  3456.00 -> "3,456."
3627      * if false, 3456.00 -> "3456"
3628      * This is independent of parsing.  If you want parsing to stop at the decimal
3629      * point, use setParseIntegerOnly.
3630      *
3631      * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
3632      * @stable ICU 2.0
3633      */
3634     public void setDecimalSeparatorAlwaysShown(boolean newValue) {
3635         decimalSeparatorAlwaysShown = newValue;
3636     }
3637
3638     /**
3639      * Returns a copy of the CurrencyPluralInfo 
3640      * used by this format. 
3641      * It might return null if the decimal format is not a plural type 
3642      * currency decimal format.
3643      * Plural type currency decimal format means either
3644      * the pattern in the decimal format contains 3 currency signs,
3645      * or the decimal format is initialized with PLURALCURRENCYSTYLE.
3646      * @return desired CurrencyPluralInfo
3647      * @see CurrencyPluralInfo
3648      * @draft ICU 4.2
3649      * @provisional This API might change or be removed in a future release.
3650      */
3651     public CurrencyPluralInfo getCurrencyPluralInfo() {
3652         try {
3653             // don't allow multiple references
3654             return currencyPluralInfo == null ? 
3655                    null :
3656                    (CurrencyPluralInfo) currencyPluralInfo.clone();
3657         } catch (Exception foo) {
3658             return null; // should never happen
3659         }
3660     }
3661
3662
3663     /**
3664      * Sets the CurrencyPluralInfo used by this format.  The
3665      * format uses a copy of the provided information.
3666      * @param newInfo desired CurrencyPluralInfo
3667      * @see CurrencyPluralInfo
3668      * @draft ICU 4.2
3669      * @provisional This API might change or be removed in a future release.
3670      */
3671     public void setCurrencyPluralInfo(CurrencyPluralInfo newInfo) {
3672         currencyPluralInfo = (CurrencyPluralInfo) newInfo.clone();
3673         isReadyForParsing = false;
3674     }
3675
3676     /**
3677      * Standard override; no change in semantics.
3678      * @stable ICU 2.0
3679      */
3680     public Object clone() {
3681         try {
3682             DecimalFormat other = (DecimalFormat) super.clone();
3683             other.symbols = (DecimalFormatSymbols) symbols.clone();
3684             other.digitList = new DigitList(); // fix for JB#5358
3685             if (currencyPluralInfo != null) {
3686                 other.currencyPluralInfo = (CurrencyPluralInfo)currencyPluralInfo.clone();
3687             }
3688             /*
3689              * TODO: We need to figure out whether we share a single copy
3690              * of DigitList by multiple cloned copies.  format/subformat
3691              * are designed to use a single instance, but parse/subparse
3692              * implementation is not. 
3693              */
3694             return other;
3695         } catch (Exception e) {
3696             throw new IllegalStateException();
3697         }
3698     }
3699
3700     /**
3701      * Overrides equals
3702      * @stable ICU 2.0
3703      */
3704     public boolean equals(Object obj)
3705     {
3706         if (obj == null) return false;
3707         if (!super.equals(obj)) return false; // super does class check
3708
3709         DecimalFormat other = (DecimalFormat) obj;
3710         /* Add the comparison of the four new added fields ,they are
3711          * posPrefixPattern, posSuffixPattern, negPrefixPattern, negSuffixPattern.
3712          * [Richard/GCL]
3713          */
3714         // following are added to accomodate changes for currency plural format.
3715         return currencySignCount == other.currencySignCount
3716             && (style != NumberFormat.PLURALCURRENCYSTYLE ||
3717                    equals(posPrefixPattern, other.posPrefixPattern)
3718                    && equals(posSuffixPattern, other.posSuffixPattern)
3719                    && equals(negPrefixPattern, other.negPrefixPattern)
3720                    && equals(negSuffixPattern, other.negSuffixPattern))
3721             && multiplier == other.multiplier
3722             && groupingSize == other.groupingSize
3723             && groupingSize2 == other.groupingSize2
3724             && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
3725             && useExponentialNotation == other.useExponentialNotation
3726             && (!useExponentialNotation ||
3727                 minExponentDigits == other.minExponentDigits)
3728             && useSignificantDigits == other.useSignificantDigits
3729             && (!useSignificantDigits ||
3730                 minSignificantDigits == other.minSignificantDigits &&
3731                 maxSignificantDigits == other.maxSignificantDigits)
3732             && symbols.equals(other.symbols) 
3733             && Utility.objectEquals(currencyPluralInfo, other.currencyPluralInfo);
3734     }
3735
3736     //method to unquote the strings and compare
3737     private boolean equals(String pat1, String pat2){
3738         if (pat1 == null || pat2 == null) {
3739             return (pat1 == null && pat2 == null);
3740         }
3741         //fast path
3742         if(pat1.equals(pat2)){
3743             return true;
3744         }
3745         return unquote(pat1).equals(unquote(pat2));
3746     }
3747     private String unquote(String pat){
3748         StringBuffer buf = new StringBuffer(pat.length());
3749         int i=0;
3750         while(i<pat.length()){
3751             char ch = pat.charAt(i++);
3752             if(ch!=QUOTE){
3753                 buf.append(ch);
3754             }
3755         }
3756         return buf.toString();
3757     }
3758 //      protected void handleToString(StringBuffer buf) {
3759 //          buf.append("\nposPrefixPattern: '" + posPrefixPattern + "'\n");
3760 //          buf.append("positivePrefix: '" + positivePrefix + "'\n");
3761 //          buf.append("posSuffixPattern: '" + posSuffixPattern + "'\n");
3762 //          buf.append("positiveSuffix: '" + positiveSuffix + "'\n");
3763 //          buf.append("negPrefixPattern: '" + com.ibm.icu.impl.Utility.format1ForSource(negPrefixPattern) + "'\n");
3764 //          buf.append("negativePrefix: '" + com.ibm.icu.impl.Utility.format1ForSource(negativePrefix) + "'\n");
3765 //          buf.append("negSuffixPattern: '" + negSuffixPattern + "'\n");
3766 //          buf.append("negativeSuffix: '" + negativeSuffix + "'\n");
3767 //          buf.append("multiplier: '" + multiplier + "'\n");
3768 //          buf.append("groupingSize: '" + groupingSize + "'\n");
3769 //          buf.append("groupingSize2: '" + groupingSize2 + "'\n");
3770 //          buf.append("decimalSeparatorAlwaysShown: '" + decimalSeparatorAlwaysShown + "'\n");
3771 //          buf.append("useExponentialNotation: '" + useExponentialNotation + "'\n");
3772 //          buf.append("minExponentDigits: '" + minExponentDigits + "'\n");
3773 //          buf.append("useSignificantDigits: '" + useSignificantDigits + "'\n");
3774 //          buf.append("minSignificantDigits: '" + minSignificantDigits + "'\n");
3775 //          buf.append("maxSignificantDigits: '" + maxSignificantDigits + "'\n");           
3776 //          buf.append("symbols: '" + symbols + "'");
3777 //      }
3778
3779     /**
3780      * Overrides hashCode
3781      * @stable ICU 2.0
3782      */
3783     public int hashCode() {
3784         return super.hashCode() * 37 + positivePrefix.hashCode();
3785         // just enough fields for a reasonable distribution
3786     }
3787
3788     /**
3789      * Synthesizes a pattern string that represents the current state
3790      * of this Format object.
3791      * @see #applyPattern
3792      * @stable ICU 2.0
3793      */
3794     public String toPattern() {
3795         if (style == NumberFormat.PLURALCURRENCYSTYLE) {
3796             // the prefix or suffix pattern might not be defined yet,
3797             // so they can not be synthesized,
3798             // instead, get them directly.
3799             // but it might not be the actual pattern used in formatting.
3800             // the actual pattern used in formatting depends on the 
3801             // formatted number's plural count.
3802             return formatPattern;
3803         }
3804         return toPattern( false );
3805     }
3806
3807     /**
3808      * Synthesizes a localized pattern string that represents the current
3809      * state of this Format object.
3810      * @see #applyPattern
3811      * @stable ICU 2.0
3812      */
3813     public String toLocalizedPattern() {
3814         if (style == NumberFormat.PLURALCURRENCYSTYLE) {
3815             return formatPattern;
3816         }
3817         return toPattern( true );
3818     }
3819
3820     /**
3821      * Expand the affix pattern strings into the expanded affix strings.  If any
3822      * affix pattern string is null, do not expand it.  This method should be
3823      * called any time the symbols or the affix patterns change in order to keep
3824      * the expanded affix strings up to date.
3825      * This method also will be called before formatting if format currency
3826      * plural names, since the plural name is not a static one, it is 
3827      * based on the currency plural count, the affix will be known only
3828      * after the currency plural count is know. 
3829      * In which case, the parameter
3830      * 'pluralCount' will be a non-null currency plural count.
3831      * In all other cases, the 'pluralCount' is null, which means 
3832      * it is not needed.
3833      */
3834     //Bug 4212072 [Richard/GCL]
3835     private void expandAffixes(String pluralCount) {
3836         // expandAffix() will set currencyChoice to a non-null value if
3837         // appropriate AND if it is null.
3838         currencyChoice = null;
3839
3840         // Reuse one StringBuffer for better performance
3841         StringBuffer buffer = new StringBuffer();
3842         if (posPrefixPattern != null) {
3843             expandAffix(posPrefixPattern, pluralCount, buffer, false);
3844             positivePrefix = buffer.toString();
3845         }
3846         if (posSuffixPattern != null) {
3847             expandAffix(posSuffixPattern, pluralCount, buffer, false);
3848             positiveSuffix = buffer.toString();
3849         }
3850         if (negPrefixPattern != null) {
3851             expandAffix(negPrefixPattern, pluralCount, buffer, false);
3852             negativePrefix = buffer.toString();
3853         }
3854         if (negSuffixPattern != null) {
3855             expandAffix(negSuffixPattern, pluralCount, buffer, false);
3856             negativeSuffix = buffer.toString();
3857         }
3858     }
3859
3860     /**
3861      * Expand an affix pattern into an affix string.  All characters in
3862      * the pattern are literal unless bracketed by QUOTEs.  The
3863      * following characters outside QUOTE are recognized:
3864      * PATTERN_PERCENT, PATTERN_PER_MILLE, PATTERN_MINUS, and
3865      * CURRENCY_SIGN.  If CURRENCY_SIGN is doubled, it is interpreted as
3866      * an international currency sign.  If CURRENCY_SIGN is tripled,
3867      * it is interpreted as currency plural long names, such as "US Dollars".
3868      * Any other character outside
3869      * QUOTE represents itself.  Quoted text must be well-formed.
3870      *
3871      * This method is used in two distinct ways.  First, it is used to expand
3872      * the stored affix patterns into actual affixes.  For this usage, doFormat
3873      * must be false.  Second, it is used to expand the stored affix patterns
3874      * given a specific number (doFormat == true), for those rare cases in
3875      * which a currency format references a ChoiceFormat (e.g., en_IN display
3876      * name for INR).  The number itself is taken from digitList.
3877      *
3878      * When used in the first way, this method has a side effect: It sets
3879      * currencyChoice to a ChoiceFormat object, if the currency's display name
3880      * in this locale is a ChoiceFormat pattern (very rare).  It only does this
3881      * if currencyChoice is null to start with.
3882      *
3883      * @param pattern the non-null, possibly empty pattern
3884      * @param pluralCount the plural count. It is only used for currency
3885      *                    plural format. In which case, it is the plural
3886      *                    count of the currency amount. For example,
3887      *                    in en_US, it is the singular "one", or the plural
3888      *                    "other". For all other cases, it is null, and
3889      *                    is not being used.
3890      * @param buffer a scratch StringBuffer; its contents will be lost
3891      * @param doFormat if false, then the pattern will be expanded, and if a
3892      * currency symbol is encountered that expands to a ChoiceFormat, the
3893      * currencyChoice member variable will be initialized if it is null.  If
3894      * doFormat is true, then it is assumed that the currencyChoice has been
3895      * created, and it will be used to format the value in digitList.
3896      * @return the expanded equivalent of pattern
3897      */
3898     //Bug 4212072 [Richard/GCL]
3899     private void expandAffix(String pattern, 
3900                              String pluralCount, 
3901                              StringBuffer buffer,
3902                              boolean doFormat) {
3903         buffer.setLength(0);
3904         for (int i=0; i<pattern.length(); ) {
3905             char c = pattern.charAt(i++);
3906             if (c == QUOTE) {
3907                 for (;;) {
3908                     int j = pattern.indexOf(QUOTE, i);
3909                     if (j == i) {
3910                         buffer.append(QUOTE);
3911                         i = j+1;
3912                         break;
3913                     } else if (j > i) {
3914                         buffer.append(pattern.substring(i, j));
3915                         i = j+1;
3916                         if (i<pattern.length() &&
3917                             pattern.charAt(i)==QUOTE) {
3918                             buffer.append(QUOTE);
3919                             ++i;
3920                             // loop again
3921                         } else {
3922                             break;
3923                         }
3924                     } else {
3925                         // Unterminated quote; should be caught by apply
3926                         // pattern.
3927                         throw new RuntimeException();
3928                     }
3929                 }
3930                 continue;
3931             }
3932
3933             switch (c) {
3934             case CURRENCY_SIGN:
3935                 // As of ICU 2.2 we use the currency object, and
3936                 // ignore the currency symbols in the DFS, unless
3937                 // we have a null currency object.  This occurs if
3938                 // resurrecting a pre-2.2 object or if the user
3939                 // sets a custom DFS.
3940                 boolean intl = i<pattern.length() &&
3941                     pattern.charAt(i) == CURRENCY_SIGN;
3942                 boolean plural = false;
3943                 if (intl) {
3944                     ++i;
3945                     if (i<pattern.length() &&
3946                         pattern.charAt(i) == CURRENCY_SIGN) {
3947                         plural = true;
3948                         intl = false;
3949                         ++i;
3950                     }
3951                 }
3952                 String s = null;
3953                 Currency currency = getCurrency();
3954                 if (currency != null) {
3955                     // plural name is only needed when pluralCount != null,
3956                     // which means when formatting currency plural names.
3957                     // For other cases, pluralCount == null,
3958                     // and plural names are not needed.
3959                     if (plural && pluralCount != null) {
3960                         boolean isChoiceFormat[] = new boolean[1];
3961                         s = currency.getName(symbols.getULocale(), 
3962                                              Currency.PLURAL_LONG_NAME, 
3963                                              pluralCount, 
3964                                              isChoiceFormat);
3965                     }
3966                     else if (!intl) {
3967                         boolean isChoiceFormat[] = new boolean[1];
3968                         s = currency.getName(symbols.getULocale(),
3969                                              Currency.SYMBOL_NAME,
3970                                              isChoiceFormat);
3971                         if (isChoiceFormat[0]) {
3972                             // Two modes here: If doFormat is false, we set up
3973                             // currencyChoice.  If doFormat is true, we use the
3974                             // previously created currencyChoice to format the
3975                             // value in digitList.
3976                             if (!doFormat) {
3977                                 // If the currency is handled by a ChoiceFormat,
3978                                 // then we're not going to use the expanded
3979                                 // patterns.  Instantiate the ChoiceFormat and
3980                                 // return.
3981                                 if (currencyChoice == null) {
3982                                     currencyChoice = new ChoiceFormat(s);
3983                                 }
3984                                 // We could almost return null or "" here, since the
3985                                 // expanded affixes are almost not used at all
3986                                 // in this situation.  However, one method --
3987                                 // toPattern() -- still does use the expanded
3988                                 // affixes, in order to set up a padding
3989                                 // pattern.  We use the CURRENCY_SIGN as a
3990                                 // placeholder.
3991                                 s = String.valueOf(CURRENCY_SIGN);
3992                             } else {
3993                                 FieldPosition pos = new FieldPosition(0); // ignored
3994                                 currencyChoice.format(digitList.getDouble(), buffer, pos);
3995                                 continue;
3996                             }
3997                         }
3998                     } else {
3999                         s = currency.getCurrencyCode();
4000                     }
4001                 } else {
4002                     s = intl ? symbols.getInternationalCurrencySymbol()
4003                         : symbols.getCurrencySymbol();
4004                 }
4005                 buffer.append(s);
4006                 continue;
4007             case PATTERN_PERCENT:
4008                 c = symbols.getPercent();
4009                 break;
4010             case PATTERN_PER_MILLE:
4011                 c = symbols.getPerMill();
4012                 break;
4013             case PATTERN_MINUS:
4014                 c = symbols.getMinusSign();
4015                 break;
4016             }
4017             buffer.append(c);
4018         }
4019     }
4020
4021     /**
4022      * Append an affix to the given StringBuffer.
4023      * @param buf buffer to append to
4024      * @param isNegative
4025      * @param isPrefix
4026      */
4027     private int appendAffix(StringBuffer buf, boolean isNegative,
4028             boolean isPrefix, boolean parseAttr) {
4029         if (currencyChoice != null) {
4030             String affixPat = null;
4031             if (isPrefix) {
4032                 affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
4033             } else {
4034                 affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
4035             }
4036             StringBuffer affixBuf = new StringBuffer();
4037             expandAffix(affixPat, null, affixBuf, true);
4038             buf.append(affixBuf.toString());
4039             return affixBuf.length();
4040         }
4041
4042         String affix = null;
4043         if (isPrefix) {
4044             affix = isNegative ? negativePrefix : positivePrefix;
4045         } else {
4046             affix = isNegative ? negativeSuffix : positiveSuffix;
4047         }
4048 //#if defined(FOUNDATION10) || defined(J2SE13)
4049 //#else
4050         // [Spark/CDL] Invoke formatAffix2Attribute to add attributes for affix
4051         if (parseAttr) {
4052             int offset = affix.indexOf(symbols.getCurrencySymbol());
4053             if (-1 == offset) {
4054                 offset = affix.indexOf(symbols.getPercent());
4055                 if(-1 == offset) {
4056                     offset = 0;
4057                 }
4058             }
4059             formatAffix2Attribute(affix, buf.length() + offset, buf.length()
4060                     + affix.length());
4061         }
4062 //#endif
4063         buf.append(affix);
4064         return affix.length();
4065     }
4066
4067 //#if defined(FOUNDATION10) || defined(J2SE13)
4068 //#else
4069     /*
4070      * [Spark/CDL] This is a newly added method, used to add attributes for
4071      * prefix and suffix.
4072      */
4073     private void formatAffix2Attribute(String affix, int begin, int end) {
4074         // [Spark/CDL] It is the invoker's responsibility to ensure that, before
4075         // the invocation of
4076         // this method, attributes is not null.
4077         // if( attributes == null ) return;
4078         if (affix.indexOf(symbols.getCurrencySymbol()) > -1) {
4079             addAttribute(Field.CURRENCY, begin, end);
4080         } else if (affix.indexOf(symbols.getMinusSign()) > -1) {
4081             addAttribute(Field.SIGN, begin, end);
4082         } else if (affix.indexOf(symbols.getPercent()) > -1) {
4083             addAttribute(Field.PERCENT, begin, end);
4084         } else if (affix.indexOf(symbols.getPerMill()) > -1) {
4085             addAttribute(Field.PERMILLE, begin, end);
4086         }
4087     }
4088 //#endif
4089
4090 //#if defined(FOUNDATION10) || defined(J2SE13)
4091 //#else
4092     /*
4093      * [Spark/CDL] Use this method to add attribute.
4094      */
4095     private void addAttribute(Field field, int begin, int end) {
4096         FieldPosition pos = new FieldPosition(field);
4097         pos.setBeginIndex(begin);
4098         pos.setEndIndex(end);
4099         attributes.add(pos);
4100     }
4101 //#endif
4102
4103 //#if defined(FOUNDATION10) || defined(J2SE13)
4104 //#else
4105     /**
4106      * Format the object to an attributed string, and return the corresponding iterator
4107      * Overrides superclass method.
4108      * @stable ICU 3.6
4109      */
4110     // [Spark/CDL] 
4111     public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
4112         if (!(obj instanceof Number))
4113             throw new IllegalArgumentException();
4114         Number number = (Number) obj;
4115         StringBuffer text = null;
4116         attributes.clear();
4117         if (obj instanceof BigInteger) {
4118             text = format((BigInteger) number, new StringBuffer(),
4119                     new FieldPosition(0), true);
4120         } else if (obj instanceof java.math.BigDecimal) {
4121             text = format((java.math.BigDecimal) number, new StringBuffer(),
4122                     new FieldPosition(0), true);
4123         } else if (obj instanceof Double) {
4124             text = format(number.doubleValue(), new StringBuffer(),
4125                     new FieldPosition(0), true);
4126         } else if (obj instanceof Integer || obj instanceof Long) {
4127             text = format(number.longValue(), new StringBuffer(),
4128                     new FieldPosition(0), true);
4129         }
4130
4131         AttributedString as = new AttributedString(text.toString());
4132
4133         // add NumberFormat field attributes to the AttributedString
4134         for (int i = 0; i < attributes.size(); i++) {
4135             FieldPosition pos = (FieldPosition) attributes.get(i);
4136             Format.Field attribute = pos.getFieldAttribute();
4137             as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos
4138                     .getEndIndex());
4139         }
4140
4141         // return the CharacterIterator from AttributedString
4142         return as.getIterator();
4143     }
4144 //#endif
4145     /**
4146      * Append an affix pattern to the given StringBuffer.  Localize unquoted
4147      * specials.
4148      */
4149     private void appendAffixPattern(StringBuffer buffer,
4150                                     boolean isNegative, boolean isPrefix,
4151                                     boolean localized) {
4152         String affixPat = null;
4153         if (isPrefix) {
4154             affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
4155         } else {
4156             affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
4157         }
4158
4159         // When there is a null affix pattern, we use the affix itself.
4160         if (affixPat == null) {
4161             String affix = null;
4162             if (isPrefix) {
4163                 affix = isNegative ? negativePrefix : positivePrefix;
4164             } else {
4165                 affix = isNegative ? negativeSuffix : positiveSuffix;
4166             }
4167             // Do this crudely for now:  Wrap everything in quotes.
4168             buffer.append(QUOTE);
4169             for (int i=0; i<affix.length(); ++i) {
4170                 char ch = affix.charAt(i);
4171                 if (ch == QUOTE) {
4172                     buffer.append(ch);
4173                 }
4174                 buffer.append(ch);
4175             }
4176             buffer.append(QUOTE);
4177             return;
4178         }
4179
4180         if (!localized) {
4181             buffer.append(affixPat);
4182         } else {
4183             int i, j;
4184             for (i=0; i<affixPat.length(); ++i) {
4185                 char ch = affixPat.charAt(i);
4186                 switch (ch) {
4187                 case QUOTE:
4188                     j = affixPat.indexOf(QUOTE, i+1);
4189                     if (j < 0) {
4190                         throw new IllegalArgumentException("Malformed affix pattern: " + affixPat);
4191                     }
4192                     buffer.append(affixPat.substring(i, j+1));
4193                     i = j;
4194                     continue;
4195                 case PATTERN_PER_MILLE:
4196                     ch = symbols.getPerMill();
4197                     break;
4198                 case PATTERN_PERCENT:
4199                     ch = symbols.getPercent();
4200                     break;
4201                 case PATTERN_MINUS:
4202                     ch = symbols.getMinusSign();
4203                     break;
4204                 }
4205                 //check if char is same as any other symbol
4206                 if(ch==symbols.getDecimalSeparator() ||
4207                    ch==symbols.getGroupingSeparator() ){
4208                     buffer.append(QUOTE);
4209                     buffer.append(ch);
4210                     buffer.append(QUOTE);
4211                 }else{
4212                     buffer.append(ch);
4213                 }
4214             }
4215         }
4216     }
4217
4218     /**
4219      * <strong><font face=helvetica color=red>CHANGED</font></strong>
4220      * Does the real work of generating a pattern.
4221      */
4222     private String toPattern(boolean localized) {
4223         StringBuffer result = new StringBuffer();
4224         char zero = localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT;
4225         char digit = localized ? symbols.getDigit() : PATTERN_DIGIT;
4226         char sigDigit = 0;
4227         boolean useSigDig = areSignificantDigitsUsed();
4228         if (useSigDig) {
4229             sigDigit = localized ? symbols.getSignificantDigit() : PATTERN_SIGNIFICANT_DIGIT;
4230         }
4231         char group = localized ? symbols.getGroupingSeparator()
4232                                : PATTERN_GROUPING_SEPARATOR;
4233         int i;
4234         int roundingDecimalPos = 0; // Pos of decimal in roundingDigits
4235         String roundingDigits = null;
4236         int padPos = (formatWidth > 0) ? padPosition : -1;
4237         String padSpec = (formatWidth > 0)
4238             ? new StringBuffer(2).
4239                 append(localized ? symbols.getPadEscape() : PATTERN_PAD_ESCAPE).
4240                 append(pad).toString()
4241             : null;
4242         if (roundingIncrementICU != null) {
4243             i = roundingIncrementICU.scale();
4244             roundingDigits = roundingIncrementICU.movePointRight(i).toString();
4245             roundingDecimalPos = roundingDigits.length() - i;
4246         }
4247         for (int part=0; part<2; ++part) {
4248             // variable not used int partStart = result.length();
4249             if (padPos == PAD_BEFORE_PREFIX) {
4250                 result.append(padSpec);
4251             }
4252             /* Use original symbols read from resources in pattern
4253              * eg. use "\u00A4" instead of "$" in Locale.US [Richard/GCL]
4254              */
4255             appendAffixPattern(result, part!=0, true, localized);
4256             if (padPos == PAD_AFTER_PREFIX) {
4257                 result.append(padSpec);
4258             }
4259             int sub0Start = result.length();
4260             int g = isGroupingUsed() ? Math.max(0, groupingSize) : 0;
4261             if (g > 0 && groupingSize2 > 0 && groupingSize2 != groupingSize) {
4262                 g += groupingSize2;
4263             }
4264             int maxDig = 0, minDig = 0, maxSigDig = 0;
4265             if (useSigDig) {
4266                 minDig = getMinimumSignificantDigits();
4267                 maxDig = maxSigDig = getMaximumSignificantDigits();
4268             } else {
4269                 minDig = getMinimumIntegerDigits();
4270                 maxDig = getMaximumIntegerDigits();
4271             }
4272             if (useExponentialNotation) {
4273                 if (maxDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
4274                     maxDig = 1;
4275                 }
4276             } else if (useSigDig) {
4277                 maxDig = Math.max(maxDig, g+1);
4278             } else {
4279                 maxDig = Math.max(Math.max(g, getMinimumIntegerDigits()),
4280                                   roundingDecimalPos) + 1;
4281             }
4282             for (i = maxDig; i > 0; --i) {
4283                 if (!useExponentialNotation && i<maxDig &&
4284                     isGroupingPosition(i)) {
4285                     result.append(group);
4286                 }
4287                 if (useSigDig) {
4288                     //  #@,@###   (maxSigDig == 5, minSigDig == 2)
4289                     //  65 4321   (1-based pos, count from the right)
4290                     // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig)
4291                     // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
4292                     result.append((maxSigDig >= i && i > (maxSigDig - minDig)) ? sigDigit : digit);
4293                 } else {
4294                     if (roundingDigits != null) {
4295                         int pos = roundingDecimalPos - i;
4296                         if (pos >= 0 && pos < roundingDigits.length()) {
4297                             result.append((char) (roundingDigits.charAt(pos) - '0' + zero));
4298                             continue;
4299                         }
4300                     }
4301                     result.append(i<=minDig ? zero : digit);
4302                 }
4303             }
4304             if (!useSigDig) {
4305                 if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) {
4306                     result.append(localized ? symbols.getDecimalSeparator() :
4307                                   PATTERN_DECIMAL_SEPARATOR);
4308                 }
4309                 int pos = roundingDecimalPos;
4310                 for (i = 0; i < getMaximumFractionDigits(); ++i) {
4311                     if (roundingDigits != null &&
4312                         pos < roundingDigits.length()) {
4313                         result.append(pos < 0 ? zero :
4314                                       (char) (roundingDigits.charAt(pos) - '0' + zero));
4315                         ++pos;
4316                         continue;
4317                     }
4318                     result.append(i<getMinimumFractionDigits() ? zero : digit);
4319                 }
4320             }
4321             if (useExponentialNotation) {
4322                 if(localized ){
4323                     result.append(symbols.getExponentSeparator() );
4324                 }else{
4325                     result.append(PATTERN_EXPONENT);
4326                 }
4327                 if (exponentSignAlwaysShown) {
4328                     result.append(localized ? symbols.getPlusSign() :
4329                                   PATTERN_PLUS_SIGN);
4330                 }
4331                 for (i=0; i<minExponentDigits; ++i) {
4332                     result.append(zero);
4333                 }
4334             }
4335             if (padSpec != null && !useExponentialNotation) {
4336                 int add = formatWidth - result.length() + sub0Start
4337                     - ((part == 0)
4338                        ? positivePrefix.length() + positiveSuffix.length()
4339                        : negativePrefix.length() + negativeSuffix.length());
4340                 while (add > 0) {
4341                     result.insert(sub0Start, digit);
4342                     ++maxDig;
4343                     --add;
4344                     // Only add a grouping separator if we have at least
4345                     // 2 additional characters to be added, so we don't
4346                     // end up with ",###".
4347                     if (add>1 && isGroupingPosition(maxDig)) {
4348                         result.insert(sub0Start, group);
4349                         --add;                        
4350                     }
4351                 }
4352             }
4353             if (padPos == PAD_BEFORE_SUFFIX) {
4354                 result.append(padSpec);
4355             }
4356             /* Use original symbols read from resources in pattern
4357              * eg. use "\u00A4" instead of "$" in Locale.US [Richard/GCL]
4358              */
4359             appendAffixPattern(result, part!=0, false, localized);
4360             if (padPos == PAD_AFTER_SUFFIX) {
4361                 result.append(padSpec);
4362             }
4363             if (part == 0) {
4364                 if (negativeSuffix.equals(positiveSuffix) &&
4365                     negativePrefix.equals( PATTERN_MINUS + positivePrefix)) {
4366                     break;
4367                 } else {
4368                     result.append(localized ? symbols.getPatternSeparator() :
4369                                   PATTERN_SEPARATOR);
4370                 }
4371             }
4372         }
4373         return result.toString();
4374     }
4375
4376     /**
4377      * Apply the given pattern to this Format object.  A pattern is a
4378      * short-hand specification for the various formatting properties.
4379      * These properties can also be changed individually through the
4380      * various setter methods.
4381      * <p>
4382      * There is no limit to integer digits are set
4383      * by this routine, since that is the typical end-user desire;
4384      * use setMaximumInteger if you want to set a real value.
4385      * For negative numbers, use a second pattern, separated by a semicolon
4386      * <P>Example "#,#00.0#" -> 1,234.56
4387      * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
4388      * a maximum of 2 fraction digits.
4389      * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parentheses.
4390      * <p>In negative patterns, the minimum and maximum counts are ignored;
4391      * these are presumed to be set in the positive pattern.
4392      * @stable ICU 2.0
4393      */
4394     public void applyPattern( String pattern ) {
4395         applyPattern( pattern, false );
4396     }
4397
4398     /**
4399      * Apply the given pattern to this Format object.  The pattern
4400      * is assumed to be in a localized notation. A pattern is a
4401      * short-hand specification for the various formatting properties.
4402      * These properties can also be changed individually through the
4403      * various setter methods.
4404      * <p>
4405      * There is no limit to integer digits are set
4406      * by this routine, since that is the typical end-user desire;
4407      * use setMaximumInteger if you want to set a real value.
4408      * For negative numbers, use a second pattern, separated by a semicolon
4409      * <P>Example "#,#00.0#" -> 1,234.56
4410      * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
4411      * a maximum of 2 fraction digits.
4412      * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses.
4413      * <p>In negative patterns, the minimum and maximum counts are ignored;
4414      * these are presumed to be set in the positive pattern.
4415      * @stable ICU 2.0
4416      */
4417     public void applyLocalizedPattern( String pattern ) {
4418         applyPattern( pattern, true );
4419     }
4420
4421    
4422     /**
4423      * <strong><font face=helvetica color=red>CHANGED</font></strong>
4424      * Does the real work of applying a pattern.
4425      */
4426     private void applyPattern(String pattern, boolean localized) {
4427         applyPatternWithoutExpandAffix(pattern, localized);
4428         expandAffixAdjustWidth(null);
4429     }
4430
4431     private void expandAffixAdjustWidth(String pluralCount) {
4432         /*Bug 4212072
4433           Update the affix strings according to symbols in order to keep
4434           the affix strings up to date.
4435           [Richard/GCL]
4436         */
4437         expandAffixes(pluralCount);
4438
4439         // Now that we have the actual prefix and suffix, fix up formatWidth
4440         if (formatWidth > 0) {
4441             formatWidth += positivePrefix.length() + positiveSuffix.length();
4442         }
4443     }
4444
4445     private void applyPatternWithoutExpandAffix(String pattern, boolean localized) {
4446         char zeroDigit         = PATTERN_ZERO_DIGIT; // '0'
4447         char sigDigit          = PATTERN_SIGNIFICANT_DIGIT; // '@'
4448         char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
4449         char decimalSeparator  = PATTERN_DECIMAL_SEPARATOR;
4450         char percent           = PATTERN_PERCENT;
4451         char perMill           = PATTERN_PER_MILLE;
4452         char digit             = PATTERN_DIGIT; // '#'
4453         char separator         = PATTERN_SEPARATOR;
4454         String exponent        = String.valueOf(PATTERN_EXPONENT);
4455         char plus              = PATTERN_PLUS_SIGN;
4456         char padEscape         = PATTERN_PAD_ESCAPE;
4457         char minus             = PATTERN_MINUS; //Bug 4212072 [Richard/GCL]
4458         if (localized) {
4459             zeroDigit         = symbols.getZeroDigit();
4460             sigDigit          = symbols.getSignificantDigit();
4461             groupingSeparator = symbols.getGroupingSeparator();
4462             decimalSeparator  = symbols.getDecimalSeparator();
4463             percent           = symbols.getPercent();
4464             perMill           = symbols.getPerMill();
4465             digit             = symbols.getDigit();
4466             separator         = symbols.getPatternSeparator();
4467             exponent          = symbols.getExponentSeparator();
4468             plus              = symbols.getPlusSign();
4469             padEscape         = symbols.getPadEscape();
4470             minus             = symbols.getMinusSign(); //Bug 4212072 [Richard/GCL]
4471         }
4472         char nineDigit = (char) (zeroDigit + 9);
4473
4474         boolean gotNegative = false;
4475
4476         int pos = 0;
4477         // Part 0 is the positive pattern.  Part 1, if present, is the negative
4478         // pattern.
4479         for (int part=0; part<2 && pos<pattern.length(); ++part) {
4480             // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix,
4481             // 2=suffix, 3=prefix in quote, 4=suffix in quote.  Subpart 0 is
4482             // between the prefix and suffix, and consists of pattern
4483             // characters.  In the prefix and suffix, percent, permille, and
4484             // currency symbols are recognized and translated.
4485             int subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;
4486
4487             // It's important that we don't change any fields of this object
4488             // prematurely.  We set the following variables for the multiplier,
4489             // grouping, etc., and then only change the actual object fields if
4490             // everything parses correctly.  This also lets us register
4491             // the data from part 0 and ignore the part 1, except for the
4492             // prefix and suffix.
4493             StringBuffer prefix = new StringBuffer();
4494             StringBuffer suffix = new StringBuffer();
4495             int decimalPos = -1;
4496             int multpl = 1;
4497             int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;
4498             byte groupingCount = -1;
4499             byte groupingCount2 = -1;
4500             int padPos = -1;
4501             char padChar = 0;
4502             int incrementPos = -1;
4503             long incrementVal = 0;
4504             byte expDigits = -1;
4505             boolean expSignAlways = false;
4506
4507             // The affix is either the prefix or the suffix.
4508             StringBuffer affix = prefix;
4509
4510             int start = pos;
4511
4512         PARTLOOP:
4513             for (; pos < pattern.length(); ++pos) {
4514                 char ch = pattern.charAt(pos);
4515                 switch (subpart) {
4516                 case 0: // Pattern proper subpart (between prefix & suffix)
4517                     // Process the digits, decimal, and grouping characters.  We
4518                     // record five pieces of information.  We expect the digits
4519                     // to occur in the pattern ####00.00####, and we record the
4520                     // number of left digits, zero (central) digits, and right
4521                     // digits.  The position of the last grouping character is
4522                     // recorded (should be somewhere within the first two blocks
4523                     // of characters), as is the position of the decimal point,
4524                     // if any (should be in the zero digits).  If there is no
4525                     // decimal point, then there should be no right digits.
4526                     if (ch == digit) {
4527                         if (zeroDigitCount > 0 || sigDigitCount > 0) {
4528                             ++digitRightCount;
4529                         } else {
4530                             ++digitLeftCount;
4531                         }
4532                         if (groupingCount >= 0 && decimalPos < 0) {
4533                             ++groupingCount;
4534                         }
4535                     } else if ((ch >= zeroDigit && ch <= nineDigit) ||
4536                                ch == sigDigit) {
4537                         if (digitRightCount > 0) {
4538                             patternError("Unexpected '" + ch + '\'', pattern);
4539                         }
4540                         if (ch == sigDigit) {
4541                             ++sigDigitCount;
4542                         } else {
4543                             ++zeroDigitCount;
4544                             if (ch != zeroDigit) {
4545                                 int p = digitLeftCount + zeroDigitCount
4546                                     + digitRightCount;
4547                                 if (incrementPos >= 0) {
4548                                     while (incrementPos < p) {
4549                                         incrementVal *= 10;
4550                                         ++incrementPos;
4551                                     }
4552                                 } else {
4553                                     incrementPos = p;
4554                                 }
4555                                 incrementVal += ch - zeroDigit;
4556                             }
4557                         }
4558                         if (groupingCount >= 0 && decimalPos < 0) {
4559                             ++groupingCount;
4560                         }
4561                     } else if (ch == groupingSeparator) {
4562                         /*Bug 4212072
4563                           process the Localized pattern like "'Fr. '#'##0.05;'Fr.-'#'##0.05"
4564                           (Locale="CH", groupingSeparator == QUOTE)                          
4565                           [Richard/GCL]
4566                         */
4567                         if (ch == QUOTE && (pos+1) < pattern.length()) {
4568                             char after = pattern.charAt(pos+1);
4569                             if (!(after == digit || (after >= zeroDigit && after <= nineDigit))) {
4570                                 // A quote outside quotes indicates either the opening
4571                                 // quote or two quotes, which is a quote literal.  That is,
4572                                 // we have the first quote in 'do' or o''clock.
4573                                 if (after == QUOTE) {
4574                                     ++pos;
4575                                     // Fall through to append(ch)
4576                                 } else {
4577                                     if (groupingCount < 0) {
4578                                         subpart = 3; // quoted prefix subpart
4579                                     } else {
4580                                       // Transition to suffix subpart
4581                                       subpart = 2; // suffix subpart
4582                                       affix = suffix;
4583                                       sub0Limit = pos--;
4584                                     }
4585                                     continue;
4586                                 }
4587                             }
4588                         }
4589                         
4590                         if (decimalPos >= 0) {
4591                             patternError("Grouping separator after decimal", pattern);
4592                         }
4593                         groupingCount2 = groupingCount;
4594                         groupingCount = 0;
4595                     } else if (ch == decimalSeparator) {
4596                         if (decimalPos >= 0) {
4597                             patternError("Multiple decimal separators", pattern);
4598                         }
4599                         // Intentionally incorporate the digitRightCount,
4600                         // even though it is illegal for this to be > 0
4601                         // at this point.  We check pattern syntax below.
4602                         decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
4603                     } else {
4604                         if (pattern.regionMatches(pos, exponent, 0, exponent.length())) {
4605                             if (expDigits >= 0) {
4606                                 patternError("Multiple exponential symbols", pattern);
4607                             }
4608                             if (groupingCount >= 0) {
4609                                 patternError("Grouping separator in exponential", pattern);
4610                             }
4611                             pos += exponent.length();
4612                             // Check for positive prefix
4613                             if (pos < pattern.length()
4614                                 && pattern.charAt(pos) == plus) {
4615                                 expSignAlways = true;
4616                                 ++pos;
4617                             }
4618                             // Use lookahead to parse out the exponential part of the
4619                             // pattern, then jump into suffix subpart.
4620                             expDigits = 0;
4621                             while (pos < pattern.length() &&
4622                                    pattern.charAt(pos) == zeroDigit) {
4623                                 ++expDigits;
4624                                 ++pos;
4625                             }
4626                             
4627                             // 1. Require at least one mantissa pattern digit
4628                             // 2. Disallow "#+ @" in mantissa
4629                             // 3. Require at least one exponent pattern digit
4630                             if (((digitLeftCount + zeroDigitCount) < 1 &&
4631                                  (sigDigitCount + digitRightCount) < 1) ||
4632                                 (sigDigitCount > 0 && digitLeftCount > 0) ||
4633                                 expDigits < 1) {
4634                                 patternError("Malformed exponential", pattern);
4635                             }
4636                         }
4637                         // Transition to suffix subpart
4638                         subpart = 2; // suffix subpart
4639                         affix = suffix;
4640                         sub0Limit = pos--; // backup: for() will increment
4641                         continue;
4642                     }
4643                     break;
4644                 case 1: // Prefix subpart
4645                 case 2: // Suffix subpart
4646                     // Process the prefix / suffix characters
4647                     // Process unquoted characters seen in prefix or suffix
4648                     // subpart.
4649                     
4650                     // Several syntax characters implicitly begins the
4651                     // next subpart if we are in the prefix; otherwise
4652                     // they are illegal if unquoted.
4653                     if (ch == digit ||
4654                         ch == groupingSeparator ||
4655                         ch == decimalSeparator ||
4656                         (ch >= zeroDigit && ch <= nineDigit) ||
4657                         ch == sigDigit) {
4658                         // Any of these characters implicitly begins the
4659                         // next subpart if we are in the prefix
4660                         if (subpart == 1) { // prefix subpart
4661                             subpart = 0; // pattern proper subpart
4662                             sub0Start = pos--; // Reprocess this character
4663                             continue;
4664                         } else if (ch == QUOTE) {
4665                             /*Bug 4212072
4666                               process the Localized pattern like "'Fr. '#'##0.05;'Fr.-'#'##0.05"
4667                               (Locale="CH", groupingSeparator == QUOTE)                          
4668                               [Richard/GCL]
4669                             */
4670                             // A quote outside quotes indicates either the opening
4671                             // quote or two quotes, which is a quote literal.  That is,
4672                             // we have the first quote in 'do' or o''clock.
4673                             if ((pos+1) < pattern.length() &&
4674                                 pattern.charAt(pos+1) == QUOTE) {
4675                                 ++pos;
4676                                 affix.append(ch);
4677                             } else {
4678                                 subpart += 2; // open quote
4679                             }
4680                             continue;
4681                         }
4682                         patternError("Unquoted special character '" + ch + '\'', pattern);
4683                     } else if (ch == CURRENCY_SIGN) {
4684                         // Use lookahead to determine if the currency sign is
4685                         // doubled or not.
4686                         boolean doubled = (pos + 1) < pattern.length() &&
4687                             pattern.charAt(pos + 1) == CURRENCY_SIGN;
4688                         /*Bug 4212072
4689                          To meet the need of expandAffix(String, StirngBuffer)
4690                          [Richard/GCL]
4691                         */
4692                         if (doubled) {
4693                             ++pos; // Skip over the doubled character
4694                             affix.append(ch); // append two: one here, one below
4695                             if ((pos + 1) < pattern.length() &&
4696                                 pattern.charAt(pos + 1) == CURRENCY_SIGN) {
4697                                 ++pos; // Skip over the tripled character
4698                                 affix.append(ch); // append again
4699                                 currencySignCount = CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT;
4700                             } else {
4701                                 currencySignCount = CURRENCY_SIGN_COUNT_IN_ISO_FORMAT;
4702                             } 
4703                         } else {
4704                             currencySignCount = CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT;
4705                         }
4706                         // Fall through to append(ch)
4707                     } else if (ch == QUOTE) {
4708                         // A quote outside quotes indicates either the opening
4709                         // quote or two quotes, which is a quote literal.  That is,
4710                         // we have the first quote in 'do' or o''clock.
4711                         if((pos+1) < pattern.length()&&
4712                             pattern.charAt(pos+1)==QUOTE){
4713                             ++pos;
4714                             affix.append(ch); // append two: one here, one below
4715                         }else{
4716                             subpart += 2; // open quote
4717                         }
4718                         // Fall through to append(ch)
4719                     } else if (ch == separator) {
4720                         // Don't allow separators in the prefix, and don't allow
4721                         // separators in the second pattern (part == 1).
4722                         if (subpart == 1 || part == 1) {
4723                             patternError("Unquoted special character '" + ch + '\'', pattern);
4724                         }
4725                         sub2Limit = pos++;
4726                         break PARTLOOP; // Go to next part
4727                     } else if (ch == percent || ch == perMill) {
4728                         // Next handle characters which are appended directly.
4729                         if (multpl != 1) {
4730                             patternError("Too many percent/permille characters", pattern);
4731                         }
4732                         multpl = (ch == percent) ? 100 : 1000;
4733                         // Convert to non-localized pattern
4734                         ch = (ch == percent) ? PATTERN_PERCENT : PATTERN_PER_MILLE;
4735                         // Fall through to append(ch)
4736                     } else if (ch == minus) {
4737                         // Convert to non-localized pattern
4738                         ch = PATTERN_MINUS;
4739                         // Fall through to append(ch)
4740                     } else if (ch == padEscape) {
4741                         if (padPos >= 0) {
4742                             patternError("Multiple pad specifiers", pattern);
4743                         }
4744                         if ((pos+1) == pattern.length()) {
4745                             patternError("Invalid pad specifier", pattern);
4746                         }
4747                         padPos = pos++; // Advance past pad char
4748                         padChar = pattern.charAt(pos);
4749                         continue;
4750                     }
4751                     affix.append(ch);
4752                     break;
4753                 case 3: // Prefix subpart, in quote
4754                 case 4: // Suffix subpart, in quote
4755                     // A quote within quotes indicates either the closing
4756                     // quote or two quotes, which is a quote literal.  That is,
4757                     // we have the second quote in 'do' or 'don''t'.
4758                     if (ch == QUOTE) {
4759                         if ((pos+1) < pattern.length() &&
4760                             pattern.charAt(pos+1) == QUOTE) {
4761                             ++pos; 
4762                             affix.append(ch);
4763                         } else {
4764                             subpart -= 2; // close quote
4765                         }
4766                         // Fall through to append(ch)
4767                     }
4768                     // NOTE: In ICU 2.2 there was code here to parse quoted
4769                     // percent and permille characters _within quotes_ and give
4770                     // them special meaning.  This is incorrect, since quoted
4771                     // characters are literals without special meaning.
4772                     affix.append(ch);
4773                     break;                    
4774                 }
4775             }
4776             
4777             if (subpart == 3 || subpart == 4) {
4778                 patternError("Unterminated quote", pattern);
4779             }
4780
4781             if (sub0Limit == 0) {
4782                 sub0Limit = pattern.length();
4783             }
4784
4785             if (sub2Limit == 0) {
4786                 sub2Limit = pattern.length();
4787             }
4788
4789             /* Handle patterns with no '0' pattern character.  These patterns
4790              * are legal, but must be recodified to make sense.  "##.###" ->
4791              * "#0.###".  ".###" -> ".0##".
4792              *
4793              * We allow patterns of the form "####" to produce a zeroDigitCount
4794              * of zero (got that?); although this seems like it might make it
4795              * possible for format() to produce empty strings, format() checks
4796              * for this condition and outputs a zero digit in this situation.
4797              * Having a zeroDigitCount of zero yields a minimum integer digits
4798              * of zero, which allows proper round-trip patterns.  We don't want
4799              * "#" to become "#0" when toPattern() is called (even though that's
4800              * what it really is, semantically).
4801              */
4802             if (zeroDigitCount == 0 && sigDigitCount == 0 &&
4803                 digitLeftCount > 0 && decimalPos >= 0) {
4804                 // Handle "###.###" and "###." and ".###"
4805                 int n = decimalPos;
4806                 if (n == 0) ++n; // Handle ".###"
4807                 digitRightCount = digitLeftCount - n;
4808                 digitLeftCount = n - 1;
4809                 zeroDigitCount = 1;
4810             }
4811
4812             // Do syntax checking on the digits, decimal points, and quotes.
4813             if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) ||
4814                 (decimalPos >= 0 &&
4815                  (sigDigitCount > 0 ||
4816                   decimalPos < digitLeftCount ||
4817                   decimalPos > (digitLeftCount + zeroDigitCount))) ||
4818                 groupingCount == 0 || groupingCount2 == 0 ||
4819                 (sigDigitCount > 0 && zeroDigitCount > 0) ||
4820                 subpart > 2) { // subpart > 2 == unmatched quote
4821                 patternError("Malformed pattern", pattern);
4822             }
4823
4824             // Make sure pad is at legal position before or after affix.
4825             if (padPos >= 0) {
4826                 if (padPos == start) {
4827                     padPos = PAD_BEFORE_PREFIX;
4828                 } else if (padPos+2 == sub0Start) {
4829                     padPos = PAD_AFTER_PREFIX;
4830                 } else if (padPos == sub0Limit) {
4831                     padPos = PAD_BEFORE_SUFFIX;
4832                 } else if (padPos+2 == sub2Limit) {
4833                     padPos = PAD_AFTER_SUFFIX;
4834                 } else {
4835                     patternError("Illegal pad position", pattern);
4836                 }
4837             }
4838
4839             if (part == 0) {
4840                 // Set negative affixes temporarily to match the positive
4841                 // affixes.  Fix this up later after processing both parts.
4842                 /*Bug 4212072
4843                   To meet the need of expandAffix(String, StirngBuffer)
4844                   [Richard/GCL]
4845                 */
4846                 posPrefixPattern = negPrefixPattern = prefix.toString();
4847                 posSuffixPattern = negSuffixPattern = suffix.toString();
4848
4849                 useExponentialNotation = (expDigits >= 0);
4850                 if (useExponentialNotation) {
4851                     minExponentDigits = expDigits;
4852                     exponentSignAlwaysShown = expSignAlways;
4853                 }
4854                 int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
4855                 // The effectiveDecimalPos is the position the decimal is at or
4856                 // would be at if there is no decimal.  Note that if
4857                 // decimalPos<0, then digitTotalCount == digitLeftCount +
4858                 // zeroDigitCount.
4859                 int effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;
4860                 boolean useSigDig = (sigDigitCount > 0);
4861                 setSignificantDigitsUsed(useSigDig);
4862                 if (useSigDig) {
4863                     setMinimumSignificantDigits(sigDigitCount);
4864                     setMaximumSignificantDigits(sigDigitCount + digitRightCount);
4865                 } else {
4866                     int minInt = effectiveDecimalPos - digitLeftCount;
4867                     setMinimumIntegerDigits(minInt);
4868                     /*Upper limit on integer and fraction digits for a Java double
4869                       [Richard/GCL]
4870                     */
4871                     setMaximumIntegerDigits(useExponentialNotation
4872                         ? digitLeftCount + minInt : DOUBLE_INTEGER_DIGITS);
4873                     setMaximumFractionDigits(decimalPos >= 0
4874                         ? (digitTotalCount - decimalPos) : 0);
4875                     setMinimumFractionDigits(decimalPos >= 0
4876                         ? (digitLeftCount + zeroDigitCount - decimalPos) : 0);
4877                 }
4878                 setGroupingUsed(groupingCount > 0);
4879                 this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
4880                 this.groupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount)
4881                     ? groupingCount2 : 0;
4882                 this.multiplier = multpl;
4883                 setDecimalSeparatorAlwaysShown(decimalPos == 0
4884                         || decimalPos == digitTotalCount);
4885                 if (padPos >= 0) {
4886                     padPosition = padPos;
4887                     formatWidth = sub0Limit - sub0Start; // to be fixed up below
4888                     pad = padChar;
4889                 } else {
4890                     formatWidth = 0;
4891                 }
4892                 if (incrementVal != 0) {
4893                     // BigDecimal scale cannot be negative (even though
4894                     // this makes perfect sense), so we need to handle this.
4895                     int scale = incrementPos - effectiveDecimalPos;
4896                     roundingIncrementICU =
4897                         BigDecimal.valueOf(incrementVal, scale > 0 ? scale : 0);
4898                     if (scale < 0) {
4899                         roundingIncrementICU =
4900                             roundingIncrementICU.movePointRight(-scale);
4901                     }
4902                     setRoundingDouble();
4903                     roundingMode = BigDecimal.ROUND_HALF_EVEN;
4904                 } else {
4905                     setRoundingIncrement((BigDecimal)null);
4906                 }
4907             } else {
4908                 /*Bug 4212072
4909                   To meet the need of expandAffix(String, StirngBuffer)
4910                   [Richard/GCL]
4911                 */
4912                 negPrefixPattern = prefix.toString();
4913                 negSuffixPattern = suffix.toString();
4914                 gotNegative = true;
4915             }
4916         }
4917
4918         /*Bug 4140009
4919           Process the empty pattern
4920           [Richard/GCL]
4921         */
4922         if (pattern.length() == 0) {
4923             posPrefixPattern = posSuffixPattern = "";
4924             setMinimumIntegerDigits(0);
4925             setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
4926             setMinimumFractionDigits(0);
4927             setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
4928         }
4929         
4930         // If there was no negative pattern, or if the negative pattern is
4931         // identical to the positive pattern, then prepend the minus sign to the
4932         // positive pattern to form the negative pattern.
4933         /*Bug 4212072
4934           To meet the need of expandAffix(String, StirngBuffer)
4935           [Richard/GCL]
4936         */
4937         if (!gotNegative ||
4938             (negPrefixPattern.equals(posPrefixPattern)
4939              && negSuffixPattern.equals(posSuffixPattern))) {
4940             negSuffixPattern = posSuffixPattern;
4941             negPrefixPattern = PATTERN_MINUS + posPrefixPattern;
4942         }
4943         setLocale(null, null);
4944         // save the pattern
4945         formatPattern = pattern;
4946         // initialize currencyPluralInfo if needed 
4947         if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT &&
4948             currencyPluralInfo == null) { 
4949             currencyPluralInfo = new CurrencyPluralInfo(symbols.getLocale());
4950         }
4951     }
4952
4953     /**
4954      * Centralizes the setting of the roundingDouble and roundingDoubleReciprocal.
4955      */
4956     private void setRoundingDouble() {
4957         if (roundingIncrementICU == null) {
4958             roundingDouble = 0.0d;
4959             roundingDoubleReciprocal = 0.0d;
4960         } else {
4961             roundingDouble = roundingIncrementICU.doubleValue();
4962             setRoundingDoubleReciprocal(BigDecimal.ONE.divide(roundingIncrementICU,BigDecimal.ROUND_HALF_EVEN).doubleValue());
4963         }
4964     }
4965
4966     private void patternError(String msg, String pattern) {
4967         throw new IllegalArgumentException(msg + " in pattern \"" + pattern + '"');
4968     }
4969
4970     /*Rewrite the following 4 "set" methods
4971       Upper limit on integer and fraction digits for a Java double 
4972       [Richard/GCL]
4973     */
4974     /**
4975      * Sets the maximum number of digits allowed in the integer portion of a
4976      * number. This override limits the integer digit count to 309.
4977      * @see NumberFormat#setMaximumIntegerDigits
4978      * @stable ICU 2.0
4979      */
4980     public void setMaximumIntegerDigits(int newValue) {
4981         super.setMaximumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
4982     }
4983
4984     /**
4985      * Sets the minimum number of digits allowed in the integer portion of a
4986      * number. This override limits the integer digit count to 309.
4987      * @see NumberFormat#setMinimumIntegerDigits
4988      * @stable ICU 2.0
4989      */
4990     public void setMinimumIntegerDigits(int newValue) {
4991         super.setMinimumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
4992     }
4993
4994     /**
4995      * Returns the minimum number of significant digits that will be
4996      * displayed. This value has no effect unless areSignificantDigitsUsed()
4997      * returns true.
4998      * @return the fewest significant digits that will be shown
4999      * @stable ICU 3.0
5000      */
5001     public int getMinimumSignificantDigits() {
5002         return minSignificantDigits;
5003     }
5004
5005     /**
5006      * Returns the maximum number of significant digits that will be
5007      * displayed. This value has no effect unless areSignificantDigitsUsed()
5008      * returns true.
5009      * @return the most significant digits that will be shown
5010      * @stable ICU 3.0
5011      */
5012     public int getMaximumSignificantDigits() {
5013         return maxSignificantDigits;
5014     }
5015
5016     /**
5017      * Sets the minimum number of significant digits that will be
5018      * displayed.  If <code>min</code> is less than one then it is set
5019      * to one.  If the maximum significant digits count is less than
5020      * <code>min</code>, then it is set to <code>min</code>. This
5021      * value has no effect unless areSignificantDigitsUsed() returns true.
5022      * @param min the fewest significant digits to be shown 
5023      * @stable ICU 3.0
5024      */
5025     public void setMinimumSignificantDigits(int min) {
5026         if (min < 1) {
5027             min = 1;   
5028         }
5029         // pin max sig dig to >= min
5030         int max = Math.max(maxSignificantDigits, min);
5031         minSignificantDigits = min;
5032         maxSignificantDigits = max;
5033     }
5034
5035     /**
5036      * Sets the maximum number of significant digits that will be
5037      * displayed.  If <code>max</code> is less than one then it is set
5038      * to one.  If the minimum significant digits count is greater
5039      * than <code>max</code>, then it is set to <code>max</code>. This
5040      * value has no effect unless areSignificantDigitsUsed() returns true.
5041      * @param max the most significant digits to be shown 
5042      * @stable ICU 3.0
5043      */
5044     public void setMaximumSignificantDigits(int max) {
5045         if (max < 1) {
5046             max = 1;
5047         }
5048         // pin min sig dig to 1..max
5049         int min = Math.min(minSignificantDigits, max);
5050         minSignificantDigits = min;
5051         maxSignificantDigits = max;
5052     }
5053
5054     /**
5055      * Returns true if significant digits are in use or false if
5056      * integer and fraction digit counts are in use.
5057      * @return true if significant digits are in use
5058      * @stable ICU 3.0
5059      */
5060     public boolean areSignificantDigitsUsed() {
5061         return useSignificantDigits;
5062     }
5063
5064     /**
5065      * Sets whether significant digits are in use, or integer and
5066      * fraction digit counts are in use.
5067      * @param useSignificantDigits true to use significant digits, or
5068      * false to use integer and fraction digit counts
5069      * @stable ICU 3.0
5070      */
5071     public void setSignificantDigitsUsed(boolean useSignificantDigits) {
5072         this.useSignificantDigits = useSignificantDigits;
5073     }
5074
5075     /**
5076      * Sets the <tt>Currency</tt> object used to display currency
5077      * amounts.  This takes effect immediately, if this format is a
5078      * currency format.  If this format is not a currency format, then
5079      * the currency object is used if and when this object becomes a
5080      * currency format through the application of a new pattern.
5081      * @param theCurrency new currency object to use.  Must not be
5082      * null.
5083      * @stable ICU 2.2
5084      */
5085     public void setCurrency(Currency theCurrency) {
5086         // If we are a currency format, then modify our affixes to
5087         // encode the currency symbol for the given currency in our
5088         // locale, and adjust the decimal digits and rounding for the
5089         // given currency.
5090
5091         super.setCurrency(theCurrency);
5092         if (theCurrency != null) {
5093             boolean[] isChoiceFormat = new boolean[1];
5094             String s = theCurrency.getName(symbols.getULocale(),
5095                     Currency.SYMBOL_NAME,
5096                     isChoiceFormat);
5097                 symbols.setCurrencySymbol(s);
5098                 symbols.setInternationalCurrencySymbol(theCurrency.getCurrencyCode());
5099         }
5100
5101         if (currencySignCount > 0) {
5102             if (theCurrency != null) {
5103                 setRoundingIncrement(theCurrency.getRoundingIncrement());
5104                 int d = theCurrency.getDefaultFractionDigits();
5105                 setMinimumFractionDigits(d);
5106                 setMaximumFractionDigits(d);
5107             }
5108             expandAffixes(null);
5109         }
5110     }
5111
5112     /**
5113      * Returns the currency in effect for this formatter.  Subclasses
5114      * should override this method as needed.  Unlike getCurrency(),
5115      * this method should never return null.
5116      * @internal
5117      * @deprecated This API is ICU internal only.
5118      */
5119     protected Currency getEffectiveCurrency() {
5120         Currency c = getCurrency();
5121         if (c == null) {
5122             c = Currency.getInstance(symbols.getInternationalCurrencySymbol());
5123         }
5124         return c;
5125     }
5126
5127     /**
5128      * Sets the maximum number of digits allowed in the fraction portion of a
5129      * number. This override limits the fraction digit count to 340.
5130      * @see NumberFormat#setMaximumFractionDigits
5131      * @stable ICU 2.0
5132      */
5133     public void setMaximumFractionDigits(int newValue) {
5134         super.setMaximumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
5135     }
5136
5137     /**
5138      * Sets the minimum number of digits allowed in the fraction portion of a
5139      * number. This override limits the fraction digit count to 340.
5140      * @see NumberFormat#setMinimumFractionDigits
5141      * @stable ICU 2.0
5142      */
5143     public void setMinimumFractionDigits(int newValue) {
5144         super.setMinimumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
5145     }
5146
5147     /**
5148      * Sets whether {@link #parse(String, ParsePosition)} method returns BigDecimal.
5149      * The default value is false.
5150      * @param value true if {@link #parse(String, ParsePosition)} method returns
5151      * BigDecimal.
5152      * @stable ICU 3.6
5153      */
5154     public void setParseBigDecimal(boolean value) {
5155         parseBigDecimal = value;
5156     }
5157
5158     /**
5159      * Returns whether {@link #parse(String, ParsePosition)} method returns BigDecimal.
5160      * @return true if {@link #parse(String, ParsePosition)} method returns BigDecimal.
5161      * @stable ICU 3.6
5162      */
5163     public boolean isParseBigDecimal() {
5164         return parseBigDecimal;
5165     }
5166
5167 //#if defined(FOUNDATION10) || defined(J2SE13)
5168 //#else
5169     private void writeObject(ObjectOutputStream stream) throws IOException {
5170 // Doug, do we need this anymore?
5171 //            if (roundingIncrementICU != null) {
5172 //                roundingIncrement = roundingIncrementICU.toBigDecimal();
5173 //            }
5174
5175         // Ticket#6449
5176         // Format.Field instances are not serializable.  When formatToCharacterIterator
5177         // is called, attributes (ArrayList) stores FieldPosition instances with
5178         // NumberFormat.Field.  Because NumberFormat.Field is not serializable, we need
5179         // to clear the contents of the list when writeObject is called.  We could remove
5180         // the field or make it transient, but it will break serialization compatibility.
5181         attributes.clear();
5182
5183         stream.defaultWriteObject();
5184     }
5185 //#endif
5186
5187     /**
5188      * First, read the default serializable fields from the stream.  Then
5189      * if <code>serialVersionOnStream</code> is less than 1, indicating that
5190      * the stream was written by JDK 1.1, initialize <code>useExponentialNotation</code>
5191      * to false, since it was not present in JDK 1.1.
5192      * Finally, set serialVersionOnStream back to the maximum allowed value so that
5193      * default serialization will work properly if this object is streamed out again.
5194      */
5195     private void readObject(ObjectInputStream stream)
5196          throws IOException, ClassNotFoundException
5197     {
5198         stream.defaultReadObject();
5199         /*Bug 4185761 validate fields
5200           [Richard/GCL]
5201         */
5202         // We only need to check the maximum counts because NumberFormat
5203         // .readObject has already ensured that the maximum is greater than the
5204         // minimum count.
5205         /*Commented for compatibility with previous version, and reserved for further use
5206         if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
5207             getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
5208             throw new InvalidObjectException("Digit count out of range");
5209         }*/
5210         /* Truncate the maximumIntegerDigits to DOUBLE_INTEGER_DIGITS and maximumFractionDigits
5211          * to DOUBLE_FRACTION_DIGITS
5212          */
5213         if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS) {
5214              setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
5215         }
5216         if (getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
5217             setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
5218         }
5219         if (serialVersionOnStream < 2) {
5220             exponentSignAlwaysShown = false;
5221             setInternalRoundingIncrement(null);
5222             setRoundingDouble();
5223             roundingMode = BigDecimal.ROUND_HALF_EVEN;
5224             formatWidth = 0;
5225             pad = ' ';
5226             padPosition = PAD_BEFORE_PREFIX;
5227             if (serialVersionOnStream < 1) {
5228                 // Didn't have exponential fields
5229                 useExponentialNotation = false;
5230             }
5231         }
5232         if (serialVersionOnStream < 3) {
5233             // Versions prior to 3 do not store a currency object.
5234             // Create one to match the DecimalFormatSymbols object.
5235             setCurrencyForSymbols();
5236         }
5237         serialVersionOnStream = currentSerialVersion;
5238         digitList = new DigitList();
5239
5240 //#if defined(FOUNDATION10)
5241 //#else
5242         if (roundingIncrement != null) {
5243             setInternalRoundingIncrement(new BigDecimal(roundingIncrement));
5244             setRoundingDouble();
5245         }   
5246 //#endif
5247     }
5248
5249
5250     private void setInternalRoundingIncrement(BigDecimal value) {
5251         roundingIncrementICU = value;
5252 //#if defined(FOUNDATION10)
5253 //#else
5254         roundingIncrement = value == null ? null : value.toBigDecimal();
5255 //#endif
5256     }
5257
5258     //----------------------------------------------------------------------
5259     // INSTANCE VARIABLES
5260     //----------------------------------------------------------------------
5261
5262     private transient DigitList digitList = new DigitList();
5263
5264     /**
5265      * The symbol used as a prefix when formatting positive numbers, e.g. "+".
5266      *
5267      * @serial
5268      * @see #getPositivePrefix
5269      */
5270     private String  positivePrefix = "";
5271
5272     /**
5273      * The symbol used as a suffix when formatting positive numbers.
5274      * This is often an empty string.
5275      *
5276      * @serial
5277      * @see #getPositiveSuffix
5278      */
5279     private String  positiveSuffix = "";
5280
5281     /**
5282      * The symbol used as a prefix when formatting negative numbers, e.g. "-".
5283      *
5284      * @serial
5285      * @see #getNegativePrefix
5286      */
5287     private String  negativePrefix = "-";
5288
5289     /**
5290      * The symbol used as a suffix when formatting negative numbers.
5291      * This is often an empty string.
5292      *
5293      * @serial
5294      * @see #getNegativeSuffix
5295      */
5296     private String  negativeSuffix = "";
5297     
5298     /**
5299      * The prefix pattern for non-negative numbers.  This variable corresponds
5300      * to <code>positivePrefix</code>.
5301      *
5302      * <p>This pattern is expanded by the method <code>expandAffix()</code> to
5303      * <code>positivePrefix</code> to update the latter to reflect changes in
5304      * <code>symbols</code>.  If this variable is <code>null</code> then
5305      * <code>positivePrefix</code> is taken as a literal value that does not
5306      * change when <code>symbols</code> changes.  This variable is always
5307      * <code>null</code> for <code>DecimalFormat</code> objects older than
5308      * stream version 2 restored from stream.
5309      *
5310      * @serial
5311      */
5312     //[Richard/GCL]
5313     private String posPrefixPattern;
5314
5315     /**
5316      * The suffix pattern for non-negative numbers.  This variable corresponds
5317      * to <code>positiveSuffix</code>.  This variable is analogous to
5318      * <code>posPrefixPattern</code>; see that variable for further
5319      * documentation.
5320      *
5321      * @serial
5322      */
5323     //[Richard/GCL]
5324     private String posSuffixPattern;
5325
5326     /**
5327      * The prefix pattern for negative numbers.  This variable corresponds
5328      * to <code>negativePrefix</code>.  This variable is analogous to
5329      * <code>posPrefixPattern</code>; see that variable for further
5330      * documentation.
5331      *
5332      * @serial
5333      */
5334     //[Richard/GCL]
5335     private String negPrefixPattern;
5336
5337     /**
5338      * The suffix pattern for negative numbers.  This variable corresponds
5339      * to <code>negativeSuffix</code>.  This variable is analogous to
5340      * <code>posPrefixPattern</code>; see that variable for further
5341      * documentation.
5342      *
5343      * @serial
5344      */
5345     //[Richard/GCL]
5346     private String negSuffixPattern;
5347
5348
5349
5350     /**
5351      * Formatter for ChoiceFormat-based currency names.  If this field
5352      * is not null, then delegate to it to format currency symbols.
5353      * @since ICU 2.6
5354      */
5355     private ChoiceFormat currencyChoice;
5356
5357     /**
5358      * The multiplier for use in percent, permill, etc.
5359      *
5360      * @serial
5361      * @see #getMultiplier
5362      */
5363     private int     multiplier = 1;
5364     
5365     /**
5366      * The number of digits between grouping separators in the integer
5367      * portion of a number.  Must be greater than 0 if
5368      * <code>NumberFormat.groupingUsed</code> is true.
5369      *
5370      * @serial
5371      * @see #getGroupingSize
5372      * @see NumberFormat#isGroupingUsed
5373      */
5374     private byte    groupingSize = 3;  // invariant, > 0 if useThousands
5375
5376     // [NEW]
5377     /**
5378      * The secondary grouping size.  This is only used for Hindi
5379      * numerals, which use a primary grouping of 3 and a secondary
5380      * grouping of 2, e.g., "12,34,567".  If this value is less than
5381      * 1, then secondary grouping is equal to the primary grouping.
5382      * 
5383      */
5384     private byte    groupingSize2 = 0;
5385     
5386     /**
5387      * If true, forces the decimal separator to always appear in a formatted
5388      * number, even if the fractional part of the number is zero.
5389      *
5390      * @serial
5391      * @see #isDecimalSeparatorAlwaysShown
5392      */
5393     private boolean decimalSeparatorAlwaysShown = false;
5394     
5395     
5396     /**
5397      * The <code>DecimalFormatSymbols</code> object used by this format.
5398      * It contains the symbols used to format numbers, e.g. the grouping separator,
5399      * decimal separator, and so on.
5400      *
5401      * @serial
5402      * @see #setDecimalFormatSymbols
5403      * @see DecimalFormatSymbols
5404      */
5405     private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();
5406
5407     /**
5408      * True to use significant digits rather than integer and fraction
5409      * digit counts.
5410      * @serial
5411      * @since ICU 3.0
5412      */
5413     private boolean useSignificantDigits = false;
5414
5415     /**
5416      * The minimum number of significant digits to show.  Must be >= 1
5417      * and <= maxSignificantDigits.  Ignored unless
5418      * useSignificantDigits == true.
5419      * @serial
5420      * @since ICU 3.0
5421      */
5422     private int minSignificantDigits = 1;
5423
5424     /**
5425      * The maximum number of significant digits to show.  Must be >=
5426      * minSignficantDigits.  Ignored unless useSignificantDigits ==
5427      * true.
5428      * @serial
5429      * @since ICU 3.0
5430      */
5431     private int maxSignificantDigits = 6;
5432
5433     /**
5434      * True to force the use of exponential (i.e. scientific) notation when formatting
5435      * numbers.
5436      * <p>
5437      * Note that the JDK 1.2 public API provides no way to set this field,
5438      * even though it is supported by the implementation and the stream format.
5439      * The intent is that this will be added to the API in the future.
5440      *
5441      * @serial
5442      */
5443     private boolean useExponentialNotation;  // Newly persistent in JDK 1.2
5444
5445     /**
5446      * The minimum number of digits used to display the exponent when a number is
5447      * formatted in exponential notation.  This field is ignored if
5448      * <code>useExponentialNotation</code> is not true.
5449      * <p>
5450      * Note that the JDK 1.2 public API provides no way to set this field,
5451      * even though it is supported by the implementation and the stream format.
5452      * The intent is that this will be added to the API in the future.
5453      *
5454      * @serial
5455      */
5456     private byte    minExponentDigits;       // Newly persistent in JDK 1.2
5457
5458     // [NEW]
5459     /**
5460      * If true, the exponent is always prefixed with either the plus
5461      * sign or the minus sign.  Otherwise, only negative exponents are
5462      * prefixed with the minus sign.  This has no effect unless
5463      * <code>useExponentialNotation</code> is true.
5464      * @serial
5465      * @since AlphaWorks NumberFormat
5466      */
5467     private boolean exponentSignAlwaysShown = false;
5468
5469 //#if defined(FOUNDATION10)
5470 //#else
5471     // [NEW]
5472     /**
5473      * The value to which numbers are rounded during formatting.  For example,
5474      * if the rounding increment is 0.05, then 13.371 would be formatted as
5475      * 13.350, assuming 3 fraction digits.  Has the value <code>null</code> if
5476      * rounding is not in effect, or a positive value if rounding is in effect.
5477      * Default value <code>null</code>.
5478      * @serial
5479      * @since AlphaWorks NumberFormat
5480      */
5481     // Note: this is kept in sync with roundingIncrementICU.
5482     // it is only kept around to avoid a conversion when formatting a java.math.BigDecimal
5483     private java.math.BigDecimal roundingIncrement = null;
5484 //#endif
5485
5486     // [NEW]
5487     /**
5488      * The value to which numbers are rounded during formatting.  For example,
5489      * if the rounding increment is 0.05, then 13.371 would be formatted as
5490      * 13.350, assuming 3 fraction digits.  Has the value <code>null</code> if
5491      * rounding is not in effect, or a positive value if rounding is in effect.
5492      * Default value <code>null</code>.
5493      * WARNING: the roundingIncrement value is the one serialized.
5494      * @serial
5495      * @since AlphaWorks NumberFormat
5496      */
5497     private transient BigDecimal roundingIncrementICU = null;
5498
5499     // [NEW]
5500     /**
5501      * The rounding increment as a double.  If this value is <= 0, then no
5502      * rounding is done.  This value is
5503      * <code>roundingIncrementICU.doubleValue()</code>.  Default value 0.0.
5504      */
5505     private transient double roundingDouble = 0.0;
5506
5507     // [NEW]
5508     /**
5509      * If the roundingDouble is the reciprocal of an integer (the most common case!),
5510      * this is set to be that integer. Otherwise it is 0.0.
5511      */
5512     private transient double roundingDoubleReciprocal = 0.0;
5513
5514     // [NEW]
5515     /**
5516      * The rounding mode.  This value controls any rounding operations which
5517      * occur when applying a rounding increment or when reducing the number of
5518      * fraction digits to satisfy a maximum fraction digits limit.  The value
5519      * may assume any of the <code>BigDecimal</code> rounding mode values.
5520      * Default value <code>BigDecimal.ROUND_HALF_EVEN</code>.
5521      * @serial
5522      * @since AlphaWorks NumberFormat
5523      */
5524     private int roundingMode = BigDecimal.ROUND_HALF_EVEN;
5525
5526     // [NEW]
5527     /**
5528      * Operations on <code>BigDecimal</code> numbers are controlled by a
5529      * {@link MathContext} object, which provides the context (precision and
5530      * other information) for the operation. The default <code>MathContext</code> 
5531      * settings are <code>digits=0, form=PLAIN, lostDigits=false, 
5532      * roundingMode=ROUND_HALF_UP</code>; these settings perform fixed point 
5533      * arithmetic with unlimited precision, as defined for the original BigDecimal 
5534      * class in Java 1.1 and Java 1.2
5535      */
5536     private MathContext mathContext = new MathContext(0, MathContext.PLAIN); // context for plain unlimited math
5537
5538     // [NEW]
5539     /**
5540      * The padded format width, or zero if there is no padding.  Must
5541      * be >= 0.  Default value zero.
5542      * @serial
5543      * @since AlphaWorks NumberFormat
5544      */
5545     private int formatWidth = 0;
5546
5547     // [NEW]
5548     /**
5549      * The character used to pad the result of format to
5550      * <code>formatWidth</code>, if padding is in effect.  Default value ' '.
5551      * @serial
5552      * @since AlphaWorks NumberFormat
5553      */
5554     private char pad = ' ';
5555
5556     // [NEW]
5557     /**
5558      * The position in the string at which the <code>pad</code> character
5559      * will be inserted, if padding is in effect.  Must have a value from
5560      * <code>PAD_BEFORE_PREFIX</code> to <code>PAD_AFTER_SUFFIX</code>.
5561      * Default value <code>PAD_BEFORE_PREFIX</code>.
5562      * @serial
5563      * @since AlphaWorks NumberFormat
5564      */
5565     private int padPosition = PAD_BEFORE_PREFIX;
5566
5567     /**
5568      * True if {@link #parse(String, ParsePosition)} to return BigDecimal
5569      * rather than Long, Double or BigDecimal except special values.
5570      * This property is introduced for J2SE 5 compatibility support.
5571      * @serial
5572      * @since ICU 3.6
5573      * @see #setParseBigDecimal(boolean)
5574      * @see #isParseBigDecimal()
5575      */
5576     private boolean parseBigDecimal = false;
5577
5578     //----------------------------------------------------------------------
5579
5580     static final int currentSerialVersion = 3;
5581
5582     /**
5583      * The internal serial version which says which version was written
5584      * Possible values are:
5585      * <ul>
5586      * <li><b>0</b> (default): versions before JDK 1.2
5587      * <li><b>1</b>: version from JDK 1.2 and later, which includes the two new fields
5588      *      <code>useExponentialNotation</code> and <code>minExponentDigits</code>.
5589      * <li><b>2</b>: version on AlphaWorks, which adds roundingMode, formatWidth,
5590      *      pad, padPosition, exponentSignAlwaysShown, roundingIncrement.
5591      * <li><b>3</b>: ICU 2.2.  Adds currency object.
5592      * </ul>
5593      * @serial */
5594     private int serialVersionOnStream = currentSerialVersion;
5595
5596     //----------------------------------------------------------------------
5597     // CONSTANTS
5598     //----------------------------------------------------------------------
5599
5600     // [NEW]
5601     /**
5602      * Constant for <code>getPadPosition()</code> and
5603      * <code>setPadPosition()</code> specifying pad characters inserted before
5604      * the prefix.
5605      * @see #setPadPosition
5606      * @see #getPadPosition
5607      * @see #PAD_AFTER_PREFIX
5608      * @see #PAD_BEFORE_SUFFIX
5609      * @see #PAD_AFTER_SUFFIX
5610      * @stable ICU 2.0
5611      */
5612     public static final int PAD_BEFORE_PREFIX = 0;
5613
5614     // [NEW]
5615     /**
5616      * Constant for <code>getPadPosition()</code> and
5617      * <code>setPadPosition()</code> specifying pad characters inserted after
5618      * the prefix.
5619      * @see #setPadPosition
5620      * @see #getPadPosition
5621      * @see #PAD_BEFORE_PREFIX
5622      * @see #PAD_BEFORE_SUFFIX
5623      * @see #PAD_AFTER_SUFFIX
5624      * @stable ICU 2.0
5625      */
5626     public static final int PAD_AFTER_PREFIX  = 1;
5627
5628     // [NEW]
5629     /**
5630      * Constant for <code>getPadPosition()</code> and
5631      * <code>setPadPosition()</code> specifying pad characters inserted before
5632      * the suffix.
5633      * @see #setPadPosition
5634      * @see #getPadPosition
5635      * @see #PAD_BEFORE_PREFIX
5636      * @see #PAD_AFTER_PREFIX
5637      * @see #PAD_AFTER_SUFFIX
5638      * @stable ICU 2.0
5639      */
5640     public static final int PAD_BEFORE_SUFFIX = 2;
5641
5642     // [NEW]
5643     /**
5644      * Constant for <code>getPadPosition()</code> and
5645      * <code>setPadPosition()</code> specifying pad characters inserted after
5646      * the suffix.
5647      * @see #setPadPosition
5648      * @see #getPadPosition
5649      * @see #PAD_BEFORE_PREFIX
5650      * @see #PAD_AFTER_PREFIX
5651      * @see #PAD_BEFORE_SUFFIX
5652      * @stable ICU 2.0
5653      */
5654     public static final int PAD_AFTER_SUFFIX  = 3;
5655
5656     // Constants for characters used in programmatic (unlocalized) patterns.
5657     private static final char       PATTERN_ZERO_DIGIT         = '0';
5658     private static final char       PATTERN_GROUPING_SEPARATOR = ',';
5659     private static final char       PATTERN_DECIMAL_SEPARATOR  = '.';
5660     private static final char       PATTERN_DIGIT              = '#';
5661             static final char       PATTERN_SIGNIFICANT_DIGIT  = '@';
5662             static final char       PATTERN_EXPONENT           = 'E'; // [NEW]
5663             static final char       PATTERN_PLUS_SIGN          = '+'; // [NEW]
5664
5665     // Affix
5666     private static final char       PATTERN_PER_MILLE          = '\u2030';
5667     private static final char       PATTERN_PERCENT            = '%';
5668             static final char       PATTERN_PAD_ESCAPE         = '*'; // [NEW]
5669     /*Bug 4212072
5670       To meet the need of expandAffix(String, StirngBuffer)
5671       [Richard/GCL]
5672     */
5673     private static final char       PATTERN_MINUS              = '-'; //[Richard/GCL]
5674
5675     // Other    
5676     private static final char       PATTERN_SEPARATOR          = ';';
5677
5678     // Pad escape is package private to allow access by DecimalFormatSymbols.
5679     // Also plus sign.  Also exponent.
5680
5681     /**
5682      * The CURRENCY_SIGN is the standard Unicode symbol for currency.  It
5683      * is used in patterns and substitued with either the currency symbol,
5684      * or if it is doubled, with the international currency symbol.  If the
5685      * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
5686      * replaced with the monetary decimal separator.
5687      *
5688      * The CURRENCY_SIGN is not localized.
5689      */
5690     private static final char       CURRENCY_SIGN = '\u00A4';
5691
5692     private static final char       QUOTE = '\'';
5693     
5694     /* Upper limit on integer and fraction digits for a Java double
5695        [Richard/GCL]
5696     */
5697     static final int DOUBLE_INTEGER_DIGITS  = 309;
5698     static final int DOUBLE_FRACTION_DIGITS = 340;
5699
5700     /**
5701      * When someone turns on scientific mode, we assume that more than this
5702      * number of digits is due to flipping from some other mode that didn't
5703      * restrict the maximum, and so we force 1 integer digit.  We don't bother
5704      * to track and see if someone is using exponential notation with more than
5705      * this number, it wouldn't make sense anyway, and this is just to make sure
5706      * that someone turning on scientific mode with default settings doesn't
5707      * end up with lots of zeroes.
5708      */
5709     static final int MAX_SCIENTIFIC_INTEGER_DIGITS = 8;
5710
5711 //#if defined(FOUNDATION10)
5712 //##    // we're not compatible with other versions, since we have no java.math.BigDecimal field
5713 //##    private static final long serialVersionUID = 2;
5714 //#else
5715     // Proclaim JDK 1.1 serial compatibility.
5716     private static final long serialVersionUID = 864413376551465018L;
5717 //#endif
5718
5719 //#if defined(FOUNDATION10) || defined(J2SE13)
5720 //#else
5721     private ArrayList attributes = new ArrayList();
5722 //#endif
5723
5724     /*
5725      * Following are used in currency format
5726      */
5727 /*
5728     // triple currency sign char array
5729     private static final char[] tripleCurrencySign = {0xA4, 0xA4, 0xA4};
5730     // triple currency sign string
5731     private static final String tripleCurrencyStr = new String(tripleCurrencySign);
5732
5733     // default currency plural pattern char array
5734     private static final char[] defaultCurrencyPluralPatternChar = {0, '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4};
5735     // default currency plural pattern string
5736     private static final String defaultCurrencyPluralPattern = new String(defaultCurrencyPluralPatternChar);
5737 */
5738
5739     // pattern used in this formatter
5740     private String formatPattern = "";
5741     // style is only valid when decimal formatter is constructed by
5742     // DecimalFormat(pattern, decimalFormatSymbol, style)
5743     private int style = NumberFormat.NUMBERSTYLE;
5744     /*
5745      * Represents whether this is a currency format, and which
5746      * currency format style.
5747      * 0: not currency format type;
5748      * 1: currency style -- symbol name, such as "$" for US dollar.
5749      * 2: currency style -- ISO name, such as USD for US dollar.
5750      * 3: currency style -- plural long name, such as "US Dollar" for
5751      *                      "1.00 US Dollar", or "US Dollars" for
5752      *                      "3.00 US Dollars".
5753      */
5754     private int currencySignCount = 0;
5755
5756
5757     /* For parsing purose,
5758      * Need to remember all prefix patterns and suffix patterns of 
5759      * every currency format pattern, 
5760      * including the pattern of default currecny style, ISO currency style,
5761      * and plural currency style. And the patterns are set through applyPattern.
5762      * Following are used to represent the affix patterns in currency plural
5763      * formats.
5764      */
5765     private static final class AffixForCurrency {
5766         // negative prefix pattern
5767         private String negPrefixPatternForCurrency = null; 
5768         // negative suffix pattern
5769         private String negSuffixPatternForCurrency = null; 
5770         // positive prefix pattern
5771         private String posPrefixPatternForCurrency = null; 
5772         // positive suffix pattern
5773         private String posSuffixPatternForCurrency = null; 
5774         private int patternType;
5775         
5776         public AffixForCurrency() { 
5777             patternType = Currency.SYMBOL_NAME; 
5778         }
5779
5780         public AffixForCurrency(String negPrefix, String negSuffix,
5781                                 String posPrefix, String posSuffix,
5782                                 int type) {
5783             negPrefixPatternForCurrency = negPrefix;
5784             negSuffixPatternForCurrency = negSuffix;
5785             posPrefixPatternForCurrency = posPrefix;
5786             posSuffixPatternForCurrency = posSuffix;
5787             patternType = type;
5788         }
5789
5790         public String getNegPrefix() {
5791             return negPrefixPatternForCurrency;
5792         }
5793
5794         public String getNegSuffix() {
5795             return negSuffixPatternForCurrency;
5796         }
5797
5798         public String getPosPrefix() {
5799             return posPrefixPatternForCurrency;
5800         }
5801
5802         public String getPosSuffix() {
5803             return posSuffixPatternForCurrency;
5804         }
5805
5806         public int getPatternType() {
5807             return patternType;
5808         }
5809     }
5810     // Affix patter set for currency.
5811     // It is a set of AffixForCurrency,
5812     // each element of the set saves the negative prefix,
5813     // negative suffix, positive prefix, and positive suffix of a pattern.
5814     private transient Set affixPatternsForCurrency = null;
5815
5816     // For currency parsing, since currency parsing need to parse
5817     // against all currency patterns, before the parsing, need to set up 
5818     // the affix patterns for currency.
5819     private transient boolean isReadyForParsing = false;
5820
5821     // Information needed for DecimalFormat to format/parse currency plural.
5822     private CurrencyPluralInfo currencyPluralInfo = null;
5823
5824 }
5825
5826 //eof