KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ibm > icu > text > DecimalFormat


1 //##header 1189099963000 FOUNDATION
2
/*
3  *******************************************************************************
4  * Copyright (C) 1996-2007, International Business Machines Corporation and *
5  * others. All Rights Reserved. *
6  *******************************************************************************
7  */

8 package com.ibm.icu.text;
9
10 import java.io.IOException JavaDoc;
11 import java.io.ObjectInputStream JavaDoc;
12 import java.io.ObjectOutputStream JavaDoc;
13 import java.math.BigInteger JavaDoc;
14 import java.text.AttributedCharacterIterator JavaDoc;
15 import java.text.AttributedString JavaDoc;
16 import java.text.ChoiceFormat JavaDoc;
17 import java.text.FieldPosition JavaDoc;
18 import java.text.Format JavaDoc;
19 import java.text.ParsePosition JavaDoc;
20 import java.util.ArrayList JavaDoc;
21
22 import com.ibm.icu.impl.UCharacterProperty;
23 import com.ibm.icu.lang.UCharacter;
24 import com.ibm.icu.math.BigDecimal;
25 import com.ibm.icu.util.Currency;
26 import com.ibm.icu.util.CurrencyAmount;
27 import com.ibm.icu.util.ULocale;
28
29 /**
30  * <code>DecimalFormat</code> is a concrete subclass of
31  * {@link NumberFormat} that formats decimal numbers. It has a variety of
32  * features designed to make it possible to parse and format numbers in any
33  * locale, including support for Western, Arabic, or Indic digits. It also
34  * supports different flavors of numbers, including integers ("123"),
35  * fixed-point numbers ("123.4"), scientific notation ("1.23E4"), percentages
36  * ("12%"), and currency amounts ("$123"). All of these flavors can be easily
37  * localized.
38  *
39  * <p><strong>This is an enhanced version of <code>DecimalFormat</code> that
40  * is based on the standard version in the JDK. New or changed functionality
41  * is labeled
42  * <strong><font face=helvetica color=red>NEW</font></strong> or
43  * <strong><font face=helvetica color=red>CHANGED</font></strong>.</strong>
44  *
45  * <p>To obtain a {@link NumberFormat} for a specific locale (including the
46  * default locale) call one of <code>NumberFormat</code>'s factory methods such
47  * as {@link NumberFormat#getInstance}. Do not call the <code>DecimalFormat</code>
48  * constructors directly, unless you know what you are doing, since the
49  * {@link NumberFormat} factory methods may return subclasses other than
50  * <code>DecimalFormat</code>. If you need to customize the format object, do
51  * something like this:
52  *
53  * <blockquote><pre>
54  * NumberFormat f = NumberFormat.getInstance(loc);
55  * if (f instanceof DecimalFormat) {
56  * ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
57  * }</pre></blockquote>
58  *
59  * <p><strong>Example Usage</strong>
60  *
61  * <blockquote><pre>
62  * <strong>// Print out a number using the localized number, currency,
63  * // and percent format for each locale</strong>
64  * Locale[] locales = NumberFormat.getAvailableLocales();
65  * double myNumber = -1234.56;
66  * NumberFormat format;
67  * for (int j=0; j<3; ++j) {
68  * System.out.println("FORMAT");
69  * for (int i = 0; i < locales.length; ++i) {
70  * if (locales[i].getCountry().length() == 0) {
71  * // Skip language-only locales
72  * continue;
73  * }
74  * System.out.print(locales[i].getDisplayName());
75  * switch (j) {
76  * case 0:
77  * format = NumberFormat.getInstance(locales[i]); break;
78  * case 1:
79  * format = NumberFormat.getCurrencyInstance(locales[i]); break;
80  * default:
81  * format = NumberFormat.getPercentInstance(locales[i]); break;
82  * }
83  * try {
84  * // Assume format is a DecimalFormat
85  * System.out.print(": " + ((DecimalFormat) format).toPattern()
86  * + " -> " + form.format(myNumber));
87  * } catch (Exception e) {}
88  * try {
89  * System.out.println(" -> " + format.parse(form.format(myNumber)));
90  * } catch (ParseException e) {}
91  * }
92  * }</pre></blockquote>
93  *
94  * <h4>Patterns</h4>
95  *
96  * <p>A <code>DecimalFormat</code> consists of a <em>pattern</em> and a set of
97  * <em>symbols</em>. The pattern may be set directly using
98  * {@link #applyPattern}, or indirectly using other API methods which
99  * manipulate aspects of the pattern, such as the minimum number of integer
100  * digits. The symbols are stored in a {@link DecimalFormatSymbols}
101  * object. When using the {@link NumberFormat} factory methods, the
102  * pattern and symbols are read from ICU's locale data.
103  *
104  * <h4>Special Pattern Characters</h4>
105  *
106  * <p>Many characters in a pattern are taken literally; they are matched during
107  * parsing and output unchanged during formatting. Special characters, on the
108  * other hand, stand for other characters, strings, or classes of characters.
109  * For example, the '#' character is replaced by a localized digit. Often the
110  * replacement character is the same as the pattern character; in the U.S. locale,
111  * the ',' grouping character is replaced by ','. However, the replacement is
112  * still happening, and if the symbols are modified, the grouping character
113  * changes. Some special characters affect the behavior of the formatter by
114  * their presence; for example, if the percent character is seen, then the
115  * value is multiplied by 100 before being displayed.
116  *
117  * <p>To insert a special character in a pattern as a literal, that is, without
118  * any special meaning, the character must be quoted. There are some exceptions to
119  * this which are noted below.
120  *
121  * <p>The characters listed here are used in non-localized patterns. Localized
122  * patterns use the corresponding characters taken from this formatter's
123  * {@link DecimalFormatSymbols} object instead, and these characters lose
124  * their special status. Two exceptions are the currency sign and quote, which
125  * are not localized.
126  *
127  * <blockquote>
128  * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
129  * location, localized, and meaning.">
130  * <tr bgcolor="#ccccff">
131  * <th align=left>Symbol
132  * <th align=left>Location
133  * <th align=left>Localized?
134  * <th align=left>Meaning
135  * <tr valign=top>
136  * <td><code>0</code>
137  * <td>Number
138  * <td>Yes
139  * <td>Digit
140  * <tr valign=top bgcolor="#eeeeff">
141  * <td><code>1-9</code>
142  * <td>Number
143  * <td>Yes
144  * <td><strong><font face=helvetica color=red>NEW</font></strong>
145  * '1' through '9' indicate rounding.
146  * <tr valign=top>
147  * <td><code>@</code>
148  * <td>Number
149  * <td>No
150  * <td><strong><font face=helvetica color=red>NEW</font></strong>
151  * Significant digit
152  * <tr valign=top bgcolor="#eeeeff">
153  * <td><code>#</code>
154  * <td>Number
155  * <td>Yes
156  * <td>Digit, zero shows as absent
157  * <tr valign=top>
158  * <td><code>.</code>
159  * <td>Number
160  * <td>Yes
161  * <td>Decimal separator or monetary decimal separator
162  * <tr valign=top bgcolor="#eeeeff">
163  * <td><code>-</code>
164  * <td>Number
165  * <td>Yes
166  * <td>Minus sign
167  * <tr valign=top>
168  * <td><code>,</code>
169  * <td>Number
170  * <td>Yes
171  * <td>Grouping separator
172  * <tr valign=top bgcolor="#eeeeff">
173  * <td><code>E</code>
174  * <td>Number
175  * <td>Yes
176  * <td>Separates mantissa and exponent in scientific notation.
177  * <em>Need not be quoted in prefix or suffix.</em>
178  * <tr valign=top>
179  * <td><code>+</code>
180  * <td>Exponent
181  * <td>Yes
182  * <td><strong><font face=helvetica color=red>NEW</font></strong>
183  * Prefix positive exponents with localized plus sign.
184  * <em>Need not be quoted in prefix or suffix.</em>
185  * <tr valign=top bgcolor="#eeeeff">
186  * <td><code>;</code>
187  * <td>Subpattern boundary
188  * <td>Yes
189  * <td>Separates positive and negative subpatterns
190  * <tr valign=top>
191  * <td><code>%</code>
192  * <td>Prefix or suffix
193  * <td>Yes
194  * <td>Multiply by 100 and show as percentage
195  * <tr valign=top bgcolor="#eeeeff">
196  * <td><code>&#92;u2030</code>
197  * <td>Prefix or suffix
198  * <td>Yes
199  * <td>Multiply by 1000 and show as per mille
200  * <tr valign=top>
201  * <td><code>&#164;</code> (<code>&#92;u00A4</code>)
202  * <td>Prefix or suffix
203  * <td>No
204  * <td>Currency sign, replaced by currency symbol. If
205  * doubled, replaced by international currency symbol.
206  * If present in a pattern, the monetary decimal separator
207  * is used instead of the decimal separator.
208  * <tr valign=top bgcolor="#eeeeff">
209  * <td><code>'</code>
210  * <td>Prefix or suffix
211  * <td>No
212  * <td>Used to quote special characters in a prefix or suffix,
213  * for example, <code>"'#'#"</code> formats 123 to
214  * <code>"#123"</code>. To create a single quote
215  * itself, use two in a row: <code>"# o''clock"</code>.
216  * <tr valign=top>
217  * <td><code>*</code>
218  * <td>Prefix or suffix boundary
219  * <td>Yes
220  * <td><strong><font face=helvetica color=red>NEW</font></strong>
221  * Pad escape, precedes pad character
222  * </table>
223  * </blockquote>
224  *
225  * <p>A <code>DecimalFormat</code> pattern contains a postive and negative
226  * subpattern, for example, "#,##0.00;(#,##0.00)". Each subpattern has a
227  * prefix, a numeric part, and a suffix. If there is no explicit negative
228  * subpattern, the negative subpattern is the localized minus sign prefixed to the
229  * positive subpattern. That is, "0.00" alone is equivalent to "0.00;-0.00". If there
230  * is an explicit negative subpattern, it serves only to specify the negative
231  * prefix and suffix; the number of digits, minimal digits, and other
232  * characteristics are ignored in the negative subpattern. That means that
233  * "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)".
234  *
235  * <p>The prefixes, suffixes, and various symbols used for infinity, digits,
236  * thousands separators, decimal separators, etc. may be set to arbitrary
237  * values, and they will appear properly during formatting. However, care must
238  * be taken that the symbols and strings do not conflict, or parsing will be
239  * unreliable. For example, either the positive and negative prefixes or the
240  * suffixes must be distinct for {@link #parse} to be able
241  * to distinguish positive from negative values. Another example is that the
242  * decimal separator and thousands separator should be distinct characters, or
243  * parsing will be impossible.
244  *
245  * <p>The <em>grouping separator</em> is a character that separates clusters of
246  * integer digits to make large numbers more legible. It commonly used for
247  * thousands, but in some locales it separates ten-thousands. The <em>grouping
248  * size</em> is the number of digits between the grouping separators, such as 3
249  * for "100,000,000" or 4 for "1 0000 0000". There are actually two different
250  * grouping sizes: One used for the least significant integer digits, the
251  * <em>primary grouping size</em>, and one used for all others, the
252  * <em>secondary grouping size</em>. In most locales these are the same, but
253  * sometimes they are different. For example, if the primary grouping interval
254  * is 3, and the secondary is 2, then this corresponds to the pattern
255  * "#,##,##0", and the number 123456789 is formatted as "12,34,56,789". If a
256  * pattern contains multiple grouping separators, the interval between the last
257  * one and the end of the integer defines the primary grouping size, and the
258  * interval between the last two defines the secondary grouping size. All others
259  * are ignored, so "#,##,###,####" == "###,###,####" == "##,#,###,####".
260  *
261  * <p>Illegal patterns, such as "#.#.#" or "#.###,###", will cause
262  * <code>DecimalFormat</code> to throw an {@link IllegalArgumentException}
263  * with a message that describes the problem.
264  *
265  * <h4>Pattern BNF</h4>
266  *
267  * <pre>
268  * pattern := subpattern (';' subpattern)?
269  * subpattern := prefix? number exponent? suffix?
270  * number := (integer ('.' fraction)?) | sigDigits
271  * prefix := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
272  * suffix := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
273  * integer := '#'* '0'* '0'
274  * fraction := '0'* '#'*
275  * sigDigits := '#'* '@' '@'* '#'*
276  * exponent := 'E' '+'? '0'* '0'
277  * padSpec := '*' padChar
278  * padChar := '&#92;u0000'..'&#92;uFFFD' - quote
279  * &#32;
280  * Notation:
281  * X* 0 or more instances of X
282  * X? 0 or 1 instances of X
283  * X|Y either X or Y
284  * C..D any character from C up to D, inclusive
285  * S-T characters in S, except those in T
286  * </pre>
287  * The first subpattern is for positive numbers. The second (optional)
288  * subpattern is for negative numbers.
289  *
290  * <p>Not indicated in the BNF syntax above:
291  *
292  * <ul><li>The grouping separator ',' can occur inside the integer and
293  * sigDigits elements, between any two pattern characters of that
294  * element, as long as the integer or sigDigits element is not
295  * followed by the exponent element.
296  *
297  * <li><font color=red face=helvetica><strong>NEW</strong></font>
298  * Two grouping intervals are recognized: That between the
299  * decimal point and the first grouping symbol, and that
300  * between the first and second grouping symbols. These
301  * intervals are identical in most locales, but in some
302  * locales they differ. For example, the pattern
303  * &quot;#,##,###&quot; formats the number 123456789 as
304  * &quot;12,34,56,789&quot;.</li>
305  *
306  * <li>
307  * <strong><font face=helvetica color=red>NEW</font></strong>
308  * The pad specifier <code>padSpec</code> may appear before the prefix,
309  * after the prefix, before the suffix, after the suffix, or not at all.
310  *
311  * <li>
312  * <strong><font face=helvetica color=red>NEW</font></strong>
313  * In place of '0', the digits '1' through '9' may be used to
314  * indicate a rounding increment.
315  * </ul>
316  *
317  * <h4>Parsing</h4>
318  *
319  * <p><code>DecimalFormat</code> parses all Unicode characters that represent
320  * decimal digits, as defined by {@link UCharacter#digit}. In addition,
321  * <code>DecimalFormat</code> also recognizes as digits the ten consecutive
322  * characters starting with the localized zero digit defined in the
323  * {@link DecimalFormatSymbols} object. During formatting, the
324  * {@link DecimalFormatSymbols}-based digits are output.
325  *
326  * <p>During parsing, grouping separators are ignored.
327  *
328  * <p>If {@link #parse(String, ParsePosition)} fails to parse
329  * a string, it returns <code>null</code> and leaves the parse position
330  * unchanged. The convenience method {@link #parse(String)}
331  * indicates parse failure by throwing a {@link java.text.ParseException}.
332  *
333  * <h4>Formatting</h4>
334  *
335  * <p>Formatting is guided by several parameters, all of which can be
336  * specified either using a pattern or using the API. The following
337  * description applies to formats that do not use <a HREF="#sci">scientific
338  * notation</a> or <a HREF="#sigdig">significant digits</a>.
339  *
340  * <ul><li>If the number of actual integer digits exceeds the
341  * <em>maximum integer digits</em>, then only the least significant
342  * digits are shown. For example, 1997 is formatted as "97" if the
343  * maximum integer digits is set to 2.
344  *
345  * <li>If the number of actual integer digits is less than the
346  * <em>minimum integer digits</em>, then leading zeros are added. For
347  * example, 1997 is formatted as "01997" if the minimum integer digits
348  * is set to 5.
349  *
350  * <li>If the number of actual fraction digits exceeds the <em>maximum
351  * fraction digits</em>, then half-even rounding it performed to the
352  * maximum fraction digits. For example, 0.125 is formatted as "0.12"
353  * if the maximum fraction digits is 2. This behavior can be changed
354  * by specifying a rounding increment and a rounding mode.
355  *
356  * <li>If the number of actual fraction digits is less than the
357  * <em>minimum fraction digits</em>, then trailing zeros are added.
358  * For example, 0.125 is formatted as "0.1250" if the mimimum fraction
359  * digits is set to 4.
360  *
361  * <li>Trailing fractional zeros are not displayed if they occur
362  * <em>j</em> positions after the decimal, where <em>j</em> is less
363  * than the maximum fraction digits. For example, 0.10004 is
364  * formatted as "0.1" if the maximum fraction digits is four or less.
365  * </ul>
366  *
367  * <p><strong>Special Values</strong>
368  *
369  * <p><code>NaN</code> is represented as a single character, typically
370  * <code>&#92;uFFFD</code>. This character is determined by the
371  * {@link DecimalFormatSymbols} object. This is the only value for which
372  * the prefixes and suffixes are not used.
373  *
374  * <p>Infinity is represented as a single character, typically
375  * <code>&#92;u221E</code>, with the positive or negative prefixes and suffixes
376  * applied. The infinity character is determined by the
377  * {@link DecimalFormatSymbols} object.
378  *
379  * <a name="sci"><h4>Scientific Notation</h4></a>
380  *
381  * <p>Numbers in scientific notation are expressed as the product of a mantissa
382  * and a power of ten, for example, 1234 can be expressed as 1.234 x 10<sup>3</sup>. The
383  * mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0),
384  * but it need not be. <code>DecimalFormat</code> supports arbitrary mantissas.
385  * <code>DecimalFormat</code> can be instructed to use scientific
386  * notation through the API or through the pattern. In a pattern, the exponent
387  * character immediately followed by one or more digit characters indicates
388  * scientific notation. Example: "0.###E0" formats the number 1234 as
389  * "1.234E3".
390  *
391  * <ul>
392  * <li>The number of digit characters after the exponent character gives the
393  * minimum exponent digit count. There is no maximum. Negative exponents are
394  * formatted using the localized minus sign, <em>not</em> the prefix and suffix
395  * from the pattern. This allows patterns such as "0.###E0 m/s". To prefix
396  * positive exponents with a localized plus sign, specify '+' between the
397  * exponent and the digits: "0.###E+0" will produce formats "1E+1", "1E+0",
398  * "1E-1", etc. (In localized patterns, use the localized plus sign rather than
399  * '+'.)
400  *
401  * <li>The minimum number of integer digits is achieved by adjusting the
402  * exponent. Example: 0.00123 formatted with "00.###E0" yields "12.3E-4". This
403  * only happens if there is no maximum number of integer digits. If there is a
404  * maximum, then the minimum number of integer digits is fixed at one.
405  *
406  * <li>The maximum number of integer digits, if present, specifies the exponent
407  * grouping. The most common use of this is to generate <em>engineering
408  * notation</em>, in which the exponent is a multiple of three, e.g.,
409  * "##0.###E0". The number 12345 is formatted using "##0.####E0" as "12.345E3".
410  *
411  * <li>When using scientific notation, the formatter controls the
412  * digit counts using significant digits logic. The maximum number of
413  * significant digits limits the total number of integer and fraction
414  * digits that will be shown in the mantissa; it does not affect
415  * parsing. For example, 12345 formatted with "##0.##E0" is "12.3E3".
416  * See the section on significant digits for more details.
417  *
418  * <li>The number of significant digits shown is determined as
419  * follows: If areSignificantDigitsUsed() returns false, then the
420  * minimum number of significant digits shown is one, and the maximum
421  * number of significant digits shown is the sum of the <em>minimum
422  * integer</em> and <em>maximum fraction</em> digits, and is
423  * unaffected by the maximum integer digits. If this sum is zero,
424  * then all significant digits are shown. If
425  * areSignificantDigitsUsed() returns true, then the significant digit
426  * counts are specified by getMinimumSignificantDigits() and
427  * getMaximumSignificantDigits(). In this case, the number of
428  * integer digits is fixed at one, and there is no exponent grouping.
429  *
430  * <li>Exponential patterns may not contain grouping separators.
431  * </ul>
432  *
433  * <a name="sigdig"><h4>
434  * <strong><font face=helvetica color=red>NEW</font></strong>
435  * Significant Digits</h4></a>
436  *
437  * <code>DecimalFormat</code> has two ways of controlling how many
438  * digits are shows: (a) significant digits counts, or (b) integer and
439  * fraction digit counts. Integer and fraction digit counts are
440  * described above. When a formatter is using significant digits
441  * counts, the number of integer and fraction digits is not specified
442  * directly, and the formatter settings for these counts are ignored.
443  * Instead, the formatter uses however many integer and fraction
444  * digits are required to display the specified number of significant
445  * digits. Examples:
446  *
447  * <blockquote>
448  * <table border=0 cellspacing=3 cellpadding=0>
449  * <tr bgcolor="#ccccff">
450  * <th align=left>Pattern
451  * <th align=left>Minimum significant digits
452  * <th align=left>Maximum significant digits
453  * <th align=left>Number
454  * <th align=left>Output of format()
455  * <tr valign=top>
456  * <td><code>@@@</code>
457  * <td>3
458  * <td>3
459  * <td>12345
460  * <td><code>12300</code>
461  * <tr valign=top bgcolor="#eeeeff">
462  * <td><code>@@@</code>
463  * <td>3
464  * <td>3
465  * <td>0.12345
466  * <td><code>0.123</code>
467  * <tr valign=top>
468  * <td><code>@@##</code>
469  * <td>2
470  * <td>4
471  * <td>3.14159
472  * <td><code>3.142</code>
473  * <tr valign=top bgcolor="#eeeeff">
474  * <td><code>@@##</code>
475  * <td>2
476  * <td>4
477  * <td>1.23004
478  * <td><code>1.23</code>
479  * </table>
480  * </blockquote>
481  *
482  * <ul>
483  * <li>Significant digit counts may be expressed using patterns that
484  * specify a minimum and maximum number of significant digits. These
485  * are indicated by the <code>'@'</code> and <code>'#'</code>
486  * characters. The minimum number of significant digits is the number
487  * of <code>'@'</code> characters. The maximum number of significant
488  * digits is the number of <code>'@'</code> characters plus the number
489  * of <code>'#'</code> characters following on the right. For
490  * example, the pattern <code>"@@@"</code> indicates exactly 3
491  * significant digits. The pattern <code>"@##"</code> indicates from
492  * 1 to 3 significant digits. Trailing zero digits to the right of
493  * the decimal separator are suppressed after the minimum number of
494  * significant digits have been shown. For example, the pattern
495  * <code>"@##"</code> formats the number 0.1203 as
496  * <code>"0.12"</code>.
497  *
498  * <li>If a pattern uses significant digits, it may not contain a
499  * decimal separator, nor the <code>'0'</code> pattern character.
500  * Patterns such as <code>"@00"</code> or <code>"@.###"</code> are
501  * disallowed.
502  *
503  * <li>Any number of <code>'#'</code> characters may be prepended to
504  * the left of the leftmost <code>'@'</code> character. These have no
505  * effect on the minimum and maximum significant digits counts, but
506  * may be used to position grouping separators. For example,
507  * <code>"#,#@#"</code> indicates a minimum of one significant digits,
508  * a maximum of two significant digits, and a grouping size of three.
509  *
510  * <li>In order to enable significant digits formatting, use a pattern
511  * containing the <code>'@'</code> pattern character. Alternatively,
512  * call {@link #setSignificantDigitsUsed setSignificantDigitsUsed(true)}.
513  *
514  * <li>In order to disable significant digits formatting, use a
515  * pattern that does not contain the <code>'@'</code> pattern
516  * character. Alternatively, call {@link #setSignificantDigitsUsed
517  * setSignificantDigitsUsed(false)}.
518  *
519  * <li>The number of significant digits has no effect on parsing.
520  *
521  * <li>Significant digits may be used together with exponential notation. Such
522  * patterns are equivalent to a normal exponential pattern with a minimum and
523  * maximum integer digit count of one, a minimum fraction digit count of
524  * <code>getMinimumSignificantDigits() - 1</code>, and a maximum fraction digit
525  * count of <code>getMaximumSignificantDigits() - 1</code>. For example, the
526  * pattern <code>"@@###E0"</code> is equivalent to <code>"0.0###E0"</code>.
527  *
528  * <li>If signficant digits are in use, then the integer and fraction
529  * digit counts, as set via the API, are ignored. If significant
530  * digits are not in use, then the signficant digit counts, as set via
531  * the API, are ignored.
532  *
533  * </ul>
534  *
535  * <h4>
536  * <strong><font face=helvetica color=red>NEW</font></strong>
537  * Padding</h4>
538  *
539  * <p><code>DecimalFormat</code> supports padding the result of
540  * {@link #format} to a specific width. Padding may be specified either
541  * through the API or through the pattern syntax. In a pattern the pad escape
542  * character, followed by a single pad character, causes padding to be parsed
543  * and formatted. The pad escape character is '*' in unlocalized patterns, and
544  * can be localized using {@link DecimalFormatSymbols#setPadEscape}. For
545  * example, <code>"$*x#,##0.00"</code> formats 123 to <code>"$xx123.00"</code>,
546  * and 1234 to <code>"$1,234.00"</code>.
547  *
548  * <ul>
549  * <li>When padding is in effect, the width of the positive subpattern,
550  * including prefix and suffix, determines the format width. For example, in
551  * the pattern <code>"* #0 o''clock"</code>, the format width is 10.
552  *
553  * <li>The width is counted in 16-bit code units (Java <code>char</code>s).
554  *
555  * <li>Some parameters which usually do not matter have meaning when padding is
556  * used, because the pattern width is significant with padding. In the pattern
557  * "* ##,##,#,##0.##", the format width is 14. The initial characters "##,##,"
558  * do not affect the grouping size or maximum integer digits, but they do affect
559  * the format width.
560  *
561  * <li>Padding may be inserted at one of four locations: before the prefix,
562  * after the prefix, before the suffix, or after the suffix. If padding is
563  * specified in any other location, {@link #applyPattern} throws an {@link
564  * IllegalArgumentException}. If there is no prefix, before the
565  * prefix and after the prefix are equivalent, likewise for the suffix.
566  *
567  * <li>When specified in a pattern, the 16-bit <code>char</code> immediately
568  * following the pad escape is the pad character. This may be any character,
569  * including a special pattern character. That is, the pad escape
570  * <em>escapes</em> the following character. If there is no character after
571  * the pad escape, then the pattern is illegal.
572  *
573  * </ul>
574  *
575  * <p>
576  * <strong><font face=helvetica color=red>NEW</font></strong>
577  * <strong>Rounding</strong>
578  *
579  * <p><code>DecimalFormat</code> supports rounding to a specific increment. For
580  * example, 1230 rounded to the nearest 50 is 1250. 1.234 rounded to the
581  * nearest 0.65 is 1.3. The rounding increment may be specified through the API
582  * or in a pattern. To specify a rounding increment in a pattern, include the
583  * increment in the pattern itself. "#,#50" specifies a rounding increment of
584  * 50. "#,##0.05" specifies a rounding increment of 0.05.
585  *
586  * <ul>
587  * <li>Rounding only affects the string produced by formatting. It does
588  * not affect parsing or change any numerical values.
589  *
590  * <li>A <em>rounding mode</em> determines how values are rounded; see the
591  * {@link com.ibm.icu.math.BigDecimal} documentation for a description of the
592  * modes. Rounding increments specified in patterns use the default mode,
593  * {@link com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN}.
594  *
595  * <li>Some locales use rounding in their currency formats to reflect the
596  * smallest currency denomination.
597  *
598  * <li>In a pattern, digits '1' through '9' specify rounding, but otherwise
599  * behave identically to digit '0'.
600  * </ul>
601  *
602  * <h4>Synchronization</h4>
603  *
604  * <p><code>DecimalFormat</code> objects are not synchronized. Multiple
605  * threads should not access one formatter concurrently.
606  *
607  * @see java.text.Format
608  * @see NumberFormat
609  * @author Mark Davis
610  * @author Alan Liu
611  * @stable ICU 2.0
612  */

613 public class DecimalFormat extends NumberFormat {
614
615     /**
616      * Create a DecimalFormat using the default pattern and symbols
617      * for the default locale. This is a convenient way to obtain a
618      * DecimalFormat when internationalization is not the main concern.
619      * <p>
620      * To obtain standard formats for a given locale, use the factory methods
621      * on NumberFormat such as getNumberInstance. These factories will
622      * return the most appropriate sub-class of NumberFormat for a given
623      * locale.
624      * @see NumberFormat#getInstance
625      * @see NumberFormat#getNumberInstance
626      * @see NumberFormat#getCurrencyInstance
627      * @see NumberFormat#getPercentInstance
628      * @stable ICU 2.0
629      */

630     public DecimalFormat() {
631         // [NEW]
632
ULocale def = ULocale.getDefault();
633         String JavaDoc pattern = getPattern(def, 0);
634         // Always applyPattern after the symbols are set
635
this.symbols = new DecimalFormatSymbols(def);
636         setCurrency(Currency.getInstance(def));
637         applyPattern(pattern, false);
638     }
639
640
641     /**
642      * Create a DecimalFormat from the given pattern and the symbols
643      * for the default locale. This is a convenient way to obtain a
644      * DecimalFormat when internationalization is not the main concern.
645      * <p>
646      * To obtain standard formats for a given locale, use the factory methods
647      * on NumberFormat such as getNumberInstance. These factories will
648      * return the most appropriate sub-class of NumberFormat for a given
649      * locale.
650      * @param pattern A non-localized pattern string.
651      * @exception IllegalArgumentException if the given pattern is invalid.
652      * @see NumberFormat#getInstance
653      * @see NumberFormat#getNumberInstance
654      * @see NumberFormat#getCurrencyInstance
655      * @see NumberFormat#getPercentInstance
656      * @stable ICU 2.0
657      */

658     public DecimalFormat(String JavaDoc pattern) {
659         // Always applyPattern after the symbols are set
660
ULocale def = ULocale.getDefault();
661         this.symbols = new DecimalFormatSymbols(def);
662         setCurrency(Currency.getInstance(def));
663         applyPattern( pattern, false );
664     }
665
666
667     /**
668      * Create a DecimalFormat from the given pattern and symbols.
669      * Use this constructor when you need to completely customize the
670      * behavior of the format.
671      * <p>
672      * To obtain standard formats for a given
673      * locale, use the factory methods on NumberFormat such as
674      * getInstance or getCurrencyInstance. If you need only minor adjustments
675      * to a standard format, you can modify the format returned by
676      * a NumberFormat factory method.
677      * @param pattern a non-localized pattern string
678      * @param symbols the set of symbols to be used
679      * @exception IllegalArgumentException if the given pattern is invalid
680      * @see NumberFormat#getInstance
681      * @see NumberFormat#getNumberInstance
682      * @see NumberFormat#getCurrencyInstance
683      * @see NumberFormat#getPercentInstance
684      * @see DecimalFormatSymbols
685      * @stable ICU 2.0
686      */

687     public DecimalFormat(String JavaDoc pattern, DecimalFormatSymbols symbols) {
688         // Always applyPattern after the symbols are set
689
this.symbols = (DecimalFormatSymbols) symbols.clone();
690         setCurrencyForSymbols();
691         applyPattern( pattern, false );
692     }
693
694     /**
695      * @stable ICU 2.0
696      */

697     public StringBuffer JavaDoc format(double number, StringBuffer JavaDoc result,
698             FieldPosition JavaDoc fieldPosition) {
699         return format(number, result, fieldPosition, false);
700     }
701     
702     // [Spark/CDL] The actual method to format number. If boolean value
703
// parseAttr == true, then attribute information will be recorded.
704
private StringBuffer JavaDoc format(double number, StringBuffer JavaDoc result,
705             FieldPosition JavaDoc fieldPosition, boolean parseAttr)
706     {
707         fieldPosition.setBeginIndex(0);
708         fieldPosition.setEndIndex(0);
709
710         if (Double.isNaN(number))
711         {
712             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
713                 fieldPosition.setBeginIndex(result.length());
714             }
715
716             result.append(symbols.getNaN());
717             // [Spark/CDL] Add attribute for NaN here.
718
// result.append(symbols.getNaN());
719
//#ifndef FOUNDATION
720
//## if (parseAttr) {
721
//## addAttribute(Field.INTEGER, result.length()
722
//## - symbols.getNaN().length(), result.length());
723
//## }
724
//#endif
725
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
726                 fieldPosition.setEndIndex(result.length());
727             }
728
729             addPadding(result, fieldPosition, 0, 0);
730             return result;
731         }
732
733         /* Detecting whether a double is negative is easy with the exception of
734          * the value -0.0. This is a double which has a zero mantissa (and
735          * exponent), but a negative sign bit. It is semantically distinct from
736          * a zero with a positive sign bit, and this distinction is important
737          * to certain kinds of computations. However, it's a little tricky to
738          * detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you may
739          * ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==
740          * -Infinity. Proper detection of -0.0 is needed to deal with the
741          * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
742          */

743         boolean isNegative = (number < 0.0) || (number == 0.0 && 1/number < 0.0);
744         if (isNegative) number = -number;
745
746         // Do this BEFORE checking to see if value is infinite!
747
if (multiplier != 1) number *= multiplier;
748
749         // Apply rounding after multiplier
750
if (roundingDouble > 0.0) {
751             // number = roundingDouble
752
// * round(number / roundingDouble, roundingMode, isNegative);
753
double newNumber = round(number, roundingDouble, roundingDoubleReciprocal, roundingMode, isNegative);
754             if (newNumber == 0.0 && number != newNumber) isNegative = false; // if we touched it, then make zero be zero.
755
number = newNumber;
756         }
757
758         if (Double.isInfinite(number))
759         {
760             int prefixLen = appendAffix(result, isNegative, true, parseAttr);
761
762             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
763                 fieldPosition.setBeginIndex(result.length());
764             }
765
766             // [Spark/CDL] Add attribute for infinity here.
767
result.append(symbols.getInfinity());
768 //#ifndef FOUNDATION
769
//## if (parseAttr) {
770
//## addAttribute(Field.INTEGER, result.length()
771
//## - symbols.getInfinity().length(), result.length());
772
//## }
773
//#endif
774
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
775                 fieldPosition.setEndIndex(result.length());
776             }
777
778             int suffixLen = appendAffix(result, isNegative, false, parseAttr);
779
780             addPadding(result, fieldPosition, prefixLen, suffixLen);
781             return result;
782         }
783
784         // At this point we are guaranteed a nonnegative finite
785
// number.
786
synchronized(digitList) {
787             digitList.set(number, precision(false),
788                           !useExponentialNotation && !areSignificantDigitsUsed());
789             return subformat(result, fieldPosition, isNegative, false,
790                     parseAttr);
791         }
792     }
793     
794     /**
795      * <strong><font face=helvetica color=red>NEW</font></strong>
796      * Round a double value to the nearest multiple of the given
797      * rounding increment, according to the given mode. This is
798      * equivalent to rounding value/roundingInc to the nearest
799      * integer, according to the given mode, and returning that
800      * integer * roundingInc.
801      * Note this is changed from the version in 2.4, since division of doubles
802      * have inaccuracies. jitterbug 1871.
803      * @param number the absolute value of the number to be rounded
804      * @param roundingInc the rounding increment
805      * @param roundingIncReciprocal if non-zero, is the
806      * @param mode a BigDecimal rounding mode
807      * @param isNegative true if the number to be rounded is negative
808      * @return the absolute value of the rounded result
809      */

810     private static double round(double number, double roundingInc,
811             double roundingIncReciprocal, int mode, boolean isNegative) {
812         
813         double div = roundingIncReciprocal == 0.0
814             ? number / roundingInc
815             : number * roundingIncReciprocal;
816         
817         // do the absolute cases first
818

819         switch (mode) {
820         case BigDecimal.ROUND_CEILING:
821             div = (isNegative ? Math.floor(div + epsilon) : Math.ceil(div - epsilon));
822             break;
823         case BigDecimal.ROUND_FLOOR:
824             div = (isNegative ? Math.ceil(div - epsilon) : Math.floor(div + epsilon));
825             break;
826         case BigDecimal.ROUND_DOWN:
827             div = (Math.floor(div + epsilon));
828             break;
829         case BigDecimal.ROUND_UP:
830             div = (Math.ceil(div - epsilon));
831             break;
832         case BigDecimal.ROUND_UNNECESSARY:
833             if (div != Math.floor(div)) {
834                 throw new ArithmeticException JavaDoc("Rounding necessary");
835             }
836             return number;
837         default:
838             
839             // Handle complex cases, where the choice depends on the closer value.
840

841             // We figure out the distances to the two possible values, ceiling and floor.
842
// We then go for the diff that is smaller.
843
// Only if they are equal does the mode matter.
844

845             double ceil = Math.ceil(div);
846             double ceildiff = ceil - div; // (ceil * roundingInc) - number;
847
double floor = Math.floor(div);
848             double floordiff = div - floor; // number - (floor * roundingInc);
849

850             // Note that the diff values were those mapped back to the "normal" space
851
// by using the roundingInc. I don't have access to the original author of the code
852
// but suspect that that was to produce better result in edge cases because of machine
853
// precision, rather than simply using the difference between, say, ceil and div.
854
// However, it didn't work in all cases. Am trying instead using an epsilon value.
855

856             switch (mode) {
857             case BigDecimal.ROUND_HALF_EVEN:
858                 // We should be able to just return Math.rint(a), but this
859
// doesn't work in some VMs.
860
// if one is smaller than the other, take the corresponding side
861
if (floordiff + epsilon < ceildiff) {
862                     div = floor;
863                 } else if (ceildiff + epsilon < floordiff) {
864                     div = ceil;
865                 } else { // they are equal, so we want to round to whichever is even
866
double testFloor = floor / 2;
867                     div = (testFloor == Math.floor(testFloor)) ? floor : ceil;
868                 }
869                 break;
870             case BigDecimal.ROUND_HALF_DOWN:
871                 div = ((floordiff <= ceildiff + epsilon) ? floor : ceil);
872                 break;
873             case BigDecimal.ROUND_HALF_UP:
874                 div = ((ceildiff <= floordiff + epsilon) ? ceil : floor);
875                 break;
876             default:
877                 throw new IllegalArgumentException JavaDoc("Invalid rounding mode: " + mode);
878             }
879         }
880         number = roundingIncReciprocal == 0.0
881             ? div * roundingInc
882             : div / roundingIncReciprocal;
883         return number;
884     }
885     private static double epsilon = 0.00000000001;
886
887     /**
888      * @stable ICU 2.0
889      */

890     // [Spark/CDL] Delegate to format_long_StringBuffer_FieldPosition_boolean
891
public StringBuffer JavaDoc format(long number, StringBuffer JavaDoc result,
892             FieldPosition JavaDoc fieldPosition) {
893         return format(number, result, fieldPosition, false);
894     }
895
896     private StringBuffer JavaDoc format(long number, StringBuffer JavaDoc result,
897             FieldPosition JavaDoc fieldPosition, boolean parseAttr)
898     {
899         fieldPosition.setBeginIndex(0);
900         fieldPosition.setEndIndex(0);
901
902         // If we are to do rounding, we need to move into the BigDecimal
903
// domain in order to do divide/multiply correctly.
904
// [NEW]
905
if (roundingIncrementICU != null) {
906             return format(BigDecimal.valueOf(number), result, fieldPosition);
907         }
908
909         boolean isNegative = (number < 0);
910         if (isNegative) number = -number;
911
912         // In general, long values always represent real finite numbers, so
913
// we don't have to check for +/- Infinity or NaN. However, there
914
// is one case we have to be careful of: The multiplier can push
915
// a number near MIN_VALUE or MAX_VALUE outside the legal range. We
916
// check for this before multiplying, and if it happens we use BigInteger
917
// instead.
918
// [NEW]
919
if (multiplier != 1) {
920             boolean tooBig = false;
921             if (number < 0) { // This can only happen if number == Long.MIN_VALUE
922
long cutoff = Long.MIN_VALUE / multiplier;
923                 tooBig = (number < cutoff);
924             } else {
925                 long cutoff = Long.MAX_VALUE / multiplier;
926                 tooBig = (number > cutoff);
927             }
928             if (tooBig) {
929                 // [Spark/CDL] Use
930
// format_BigInteger_StringBuffer_FieldPosition_boolean instead
931
// parseAttr is used to judge whether to synthesize attributes.
932
return format(
933                         BigInteger.valueOf(isNegative ? -number : number),
934                         result, fieldPosition, parseAttr);
935             }
936         }
937
938         number *= multiplier;
939         synchronized(digitList) {
940             digitList.set(number, precision(true));
941             return subformat(result, fieldPosition, isNegative, true, parseAttr);
942         }
943     }
944
945     /**
946      * <strong><font face=helvetica color=red>NEW</font></strong> Format a
947      * BigInteger number.
948      *
949      * @stable ICU 2.0
950      */

951     public StringBuffer JavaDoc format(BigInteger JavaDoc number, StringBuffer JavaDoc result,
952             FieldPosition JavaDoc fieldPosition) {
953         return format(number, result, fieldPosition, false);
954     }
955
956     // [Spark/CDL]
957
private StringBuffer JavaDoc format(BigInteger JavaDoc number, StringBuffer JavaDoc result,
958             FieldPosition JavaDoc fieldPosition, boolean parseAttr) {
959         // If we are to do rounding, we need to move into the BigDecimal
960
// domain in order to do divide/multiply correctly.
961
if (roundingIncrementICU != null) {
962             return format(new BigDecimal(number), result, fieldPosition);
963         }
964
965         if (multiplier != 1) {
966             number = number.multiply(BigInteger.valueOf(multiplier));
967         }
968
969         // At this point we are guaranteed a nonnegative finite
970
// number.
971
synchronized(digitList) {
972             digitList.set(number, precision(true));
973             return subformat(result, fieldPosition, number.signum() < 0, false, parseAttr);
974         }
975     }
976
977 //#ifndef FOUNDATION
978
//## /**
979
//## * <strong><font face=helvetica color=red>NEW</font></strong>
980
//## * Format a BigDecimal number.
981
//## * @stable ICU 2.0
982
//## */
983
//## public StringBuffer format(java.math.BigDecimal number, StringBuffer result,
984
//## FieldPosition fieldPosition) {
985
//## return format(number, result, fieldPosition, false);
986
//## }
987
//##
988
//## private StringBuffer format(java.math.BigDecimal number,
989
//## StringBuffer result, FieldPosition fieldPosition, boolean parseAttr) {
990
//## if (multiplier != 1) {
991
//## number = number.multiply(java.math.BigDecimal.valueOf(multiplier));
992
//## }
993
//##
994
//## if (roundingIncrement != null) {
995
//## number = number.divide(roundingIncrement, 0, roundingMode)
996
//## .multiply(roundingIncrement);
997
//## }
998
//##
999
//## synchronized(digitList) {
1000
//## digitList.set(number, precision(false),
1001
//## !useExponentialNotation && !areSignificantDigitsUsed());
1002
//## return subformat(result, fieldPosition, number.signum() < 0, false, parseAttr);
1003
//## }
1004
//## }
1005
//#endif
1006

1007    /**
1008     * <strong><font face=helvetica color=red>NEW</font></strong>
1009     * Format a BigDecimal number.
1010     * @stable ICU 2.0
1011     */

1012    public StringBuffer JavaDoc format(BigDecimal number, StringBuffer JavaDoc result,
1013                               FieldPosition JavaDoc fieldPosition) {
1014        /* This method is just a copy of the corresponding java.math.BigDecimal
1015         * method for now. It isn't very efficient since it must create a
1016         * conversion object to do math on the rounding increment. In the
1017         * future we may try to clean this up, or even better, limit our support
1018         * to just one flavor of BigDecimal.
1019         */

1020        if (multiplier != 1) {
1021            number = number.multiply(BigDecimal.valueOf(multiplier));
1022        }
1023
1024        if (roundingIncrementICU != null) {
1025            number = number.divide(roundingIncrementICU, 0, roundingMode)
1026                    .multiply(roundingIncrementICU);
1027        }
1028
1029        synchronized(digitList) {
1030            digitList.set(number, precision(false),
1031                          !useExponentialNotation && !areSignificantDigitsUsed());
1032            return subformat(result, fieldPosition, number.signum() < 0, false);
1033        }
1034    }
1035
1036    /**
1037     * Return true if a grouping separator belongs at the given
1038     * position, based on whether grouping is in use and the values of
1039     * the primary and secondary grouping interval.
1040     * @param pos the number of integer digits to the right of
1041     * the current position. Zero indicates the position after the
1042     * rightmost integer digit.
1043     * @return true if a grouping character belongs at the current
1044     * position.
1045     */

1046    private boolean isGroupingPosition(int pos) {
1047        boolean result = false;
1048        if (isGroupingUsed() && (pos > 0) && (groupingSize > 0)) {
1049            if ((groupingSize2 > 0) && (pos > groupingSize)) {
1050                result = ((pos - groupingSize) % groupingSize2) == 0;
1051            } else {
1052                result = pos % groupingSize == 0;
1053            }
1054        }
1055        return result;
1056    }
1057
1058    /**
1059     * Return the number of fraction digits to display, or the total
1060     * number of digits for significant digit formats and exponential
1061     * formats.
1062     */

1063    private int precision(boolean isIntegral) {
1064        if (areSignificantDigitsUsed()) {
1065            return getMaximumSignificantDigits();
1066        } else if (useExponentialNotation) {
1067            return getMinimumIntegerDigits() + getMaximumFractionDigits();
1068        } else {
1069            return isIntegral ? 0 : getMaximumFractionDigits();
1070        }
1071    }
1072
1073    /**
1074     * Complete the formatting of a finite number. On entry, the digitList must
1075     * be filled in with the correct digits.
1076     */

1077    private StringBuffer JavaDoc subformat(StringBuffer JavaDoc result, FieldPosition JavaDoc fieldPosition,
1078                                   boolean isNegative, boolean isInteger){
1079        return subformat(result, fieldPosition, isNegative, isInteger, false);
1080    }
1081
1082    private StringBuffer JavaDoc subformat(StringBuffer JavaDoc result,
1083            FieldPosition JavaDoc fieldPosition, boolean isNegative, boolean isInteger,
1084            boolean parseAttr)
1085    {
1086        // NOTE: This isn't required anymore because DigitList takes care of this.
1087
//
1088
// // The negative of the exponent represents the number of leading
1089
// // zeros between the decimal and the first non-zero digit, for
1090
// // a value < 0.1 (e.g., for 0.00123, -fExponent == 2). If this
1091
// // is more than the maximum fraction digits, then we have an underflow
1092
// // for the printed representation. We recognize this here and set
1093
// // the DigitList representation to zero in this situation.
1094
//
1095
// if (-digitList.decimalAt >= getMaximumFractionDigits())
1096
// {
1097
// digitList.count = 0;
1098
// }
1099

1100        int i;
1101        char zero = symbols.getZeroDigit();
1102        int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero
1103
char grouping = isCurrencyFormat ?
1104                    symbols.getMonetaryGroupingSeparator() :
1105                    symbols.getGroupingSeparator();
1106        char decimal = isCurrencyFormat ?
1107            symbols.getMonetaryDecimalSeparator() :
1108            symbols.getDecimalSeparator();
1109        boolean useSigDig = areSignificantDigitsUsed();
1110        int maxIntDig = getMaximumIntegerDigits();
1111        int minIntDig = getMinimumIntegerDigits();
1112
1113        /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
1114         * format as zero. This allows sensible computations and preserves
1115         * relations such as signum(1/x) = signum(x), where x is +Infinity or
1116         * -Infinity. Prior to this fix, we always formatted zero values as if
1117         * they were positive. Liu 7/6/98.
1118         */

1119        if (digitList.isZero())
1120        {
1121            digitList.decimalAt = 0; // Normalize
1122
}
1123
1124        int prefixLen = appendAffix(result, isNegative, true, parseAttr);
1125
1126        if (useExponentialNotation)
1127        {
1128            // Record field information for caller.
1129
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1130                fieldPosition.setBeginIndex(result.length());
1131                fieldPosition.setEndIndex(-1);
1132            } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1133                fieldPosition.setBeginIndex(-1);
1134            }
1135
1136            // [Spark/CDL]
1137
// the begin index of integer part
1138
// the end index of integer part
1139
// the begin index of fractional part
1140
int intBegin = result.length();
1141            int intEnd = -1;
1142            int fracBegin = -1;
1143
1144            int minFracDig = 0;
1145            if (useSigDig) {
1146                maxIntDig = minIntDig = 1;
1147                minFracDig = getMinimumSignificantDigits() - 1;
1148            } else {
1149                minFracDig = getMinimumFractionDigits();
1150                if (maxIntDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
1151                    maxIntDig = 1;
1152                    if (maxIntDig < minIntDig) {
1153                        maxIntDig = minIntDig;
1154                    }
1155                }
1156                if (maxIntDig > minIntDig) {
1157                    minIntDig = 1;
1158                }
1159            }
1160
1161            // Minimum integer digits are handled in exponential format by
1162
// adjusting the exponent. For example, 0.01234 with 3 minimum
1163
// integer digits is "123.4E-4".
1164

1165            // Maximum integer digits are interpreted as indicating the
1166
// repeating range. This is useful for engineering notation, in
1167
// which the exponent is restricted to a multiple of 3. For
1168
// example, 0.01234 with 3 maximum integer digits is "12.34e-3".
1169
// If maximum integer digits are defined and are larger than
1170
// minimum integer digits, then minimum integer digits are
1171
// ignored.
1172

1173            int exponent = digitList.decimalAt;
1174            if (maxIntDig > 1 && maxIntDig != minIntDig) {
1175                // A exponent increment is defined; adjust to it.
1176
exponent = (exponent > 0) ? (exponent - 1) / maxIntDig
1177                                          : (exponent / maxIntDig) - 1;
1178                exponent *= maxIntDig;
1179            } else {
1180                // No exponent increment is defined; use minimum integer digits.
1181
// If none is specified, as in "#E0", generate 1 integer digit.
1182
exponent -= (minIntDig > 0 || minFracDig > 0)
1183                    ? minIntDig : 1;
1184            }
1185
1186            // We now output a minimum number of digits, and more if there
1187
// are more digits, up to the maximum number of digits. We
1188
// place the decimal point after the "integer" digits, which
1189
// are the first (decimalAt - exponent) digits.
1190
int minimumDigits = minIntDig + minFracDig;
1191            // The number of integer digits is handled specially if the number
1192
// is zero, since then there may be no digits.
1193
int integerDigits = digitList.isZero() ? minIntDig :
1194                digitList.decimalAt - exponent;
1195            int totalDigits = digitList.count;
1196            if (minimumDigits > totalDigits) totalDigits = minimumDigits;
1197            if (integerDigits > totalDigits) totalDigits = integerDigits;
1198
1199            for (i=0; i<totalDigits; ++i)
1200            {
1201                if (i == integerDigits)
1202                {
1203                    // Record field information for caller.
1204
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1205                        fieldPosition.setEndIndex(result.length());
1206                    }
1207//#ifndef FOUNDATION
1208
//## // [Spark/CDL] Add attribute for integer part
1209
//## if (parseAttr) {
1210
//## intEnd = result.length();
1211
//## addAttribute(Field.INTEGER, intBegin, result.length());
1212
//## }
1213
//#endif
1214
result.append(decimal);
1215//#ifndef FOUNDATION
1216
//## // [Spark/CDL] Add attribute for decimal separator
1217
//## if (parseAttr) {
1218
//## // Length of decimal separator is 1.
1219
//## int decimalSeparatorBegin = result.length() - 1;
1220
//## addAttribute(Field.DECIMAL_SEPARATOR,
1221
//## decimalSeparatorBegin, result.length());
1222
//## fracBegin = result.length();
1223
//## }
1224
//#endif
1225
// Record field information for caller.
1226
if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1227                        fieldPosition.setBeginIndex(result.length());
1228                    }
1229                }
1230                result.append((i < digitList.count) ?
1231                          (char)(digitList.digits[i] + zeroDelta) :
1232                          zero);
1233            }
1234            
1235            //For ICU compatibility and format 0 to 0E0 with pattern "#E0" [Richard/GCL]
1236
if (digitList.isZero() && (totalDigits ==0)) {
1237                result.append(zero);
1238            }
1239
1240            // Record field information
1241
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1242                if (fieldPosition.getEndIndex() < 0) {
1243                    fieldPosition.setEndIndex(result.length());
1244                }
1245            } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1246                if (fieldPosition.getBeginIndex() < 0) {
1247                    fieldPosition.setBeginIndex(result.length());
1248                }
1249                fieldPosition.setEndIndex(result.length());
1250            }
1251//#ifndef FOUNDATION
1252
//## // [Spark/CDL] Calcuate the end index of integer part and fractional
1253
//## // part if they are not properly processed yet.
1254
//## if (parseAttr) {
1255
//## if (intEnd < 0) {
1256
//## addAttribute(Field.INTEGER, intBegin, result.length());
1257
//## }
1258
//## if (fracBegin > 0) {
1259
//## addAttribute(Field.FRACTION, fracBegin, result.length());
1260
//## }
1261
//## }
1262
//#endif
1263

1264            // The exponent is output using the pattern-specified minimum
1265
// exponent digits. There is no maximum limit to the exponent
1266
// digits, since truncating the exponent would result in an
1267
// unacceptable inaccuracy.
1268
result.append(symbols.getExponentSeparator());
1269//#ifndef FOUNDATION
1270
//## // [Spark/CDL] For exponent symbol, add an attribute.
1271
//## if (parseAttr) {
1272
//## addAttribute(Field.EXPONENT_SYMBOL, result.length()
1273
//## - symbols.getExponentSeparator().length(), result
1274
//## .length());
1275
//## }
1276
//#endif
1277
// For zero values, we force the exponent to zero. We
1278
// must do this here, and not earlier, because the value
1279
// is used to determine integer digit count above.
1280
if (digitList.isZero()) exponent = 0;
1281
1282            boolean negativeExponent = exponent < 0;
1283            if (negativeExponent) {
1284                exponent = -exponent;
1285                result.append(symbols.getMinusSign());
1286//#ifndef FOUNDATION
1287
//## // [Spark/CDL] If exponent has sign, then add an exponent sign
1288
//## // attribute.
1289
//## if (parseAttr) {
1290
//## // Length of exponent sign is 1.
1291
//## addAttribute(Field.EXPONENT_SIGN, result.length() - 1,
1292
//## result.length());
1293
//## }
1294
//#endif
1295
} else if (exponentSignAlwaysShown) {
1296                result.append(symbols.getPlusSign());
1297//#ifndef FOUNDATION
1298
//## // [Spark/CDL] Add an plus sign attribute.
1299
//## if (parseAttr) {
1300
//## // Length of exponent sign is 1.
1301
//## int expSignBegin = result.length() - 1;
1302
//## addAttribute(Field.EXPONENT_SIGN, expSignBegin, result
1303
//## .length());
1304
//## }
1305
//#endif
1306
}
1307            int expBegin = result.length();
1308            digitList.set(exponent);
1309            {
1310                int expDig = minExponentDigits;
1311                if (useExponentialNotation && expDig < 1) {
1312                    expDig = 1;
1313                }
1314                for (i=digitList.decimalAt; i<expDig; ++i) result.append(zero);
1315            }
1316            for (i=0; i<digitList.decimalAt; ++i)
1317            {
1318                result.append((i < digitList.count) ?
1319                          (char)(digitList.digits[i] + zeroDelta) : zero);
1320            }
1321//#ifndef FOUNDATION
1322
//## // [Spark/CDL] Add attribute for exponent part.
1323
//## if (parseAttr) {
1324
//## addAttribute(Field.EXPONENT, expBegin, result.length());
1325
//## }
1326
//#endif
1327
}
1328        else
1329        {
1330            // [Spark/CDL] Record the integer start index.
1331
int intBegin = result.length();
1332            // Record field information for caller.
1333
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1334                fieldPosition.setBeginIndex(result.length());
1335            }
1336
1337            int sigCount = 0;
1338            int minSigDig = getMinimumSignificantDigits();
1339            int maxSigDig = getMaximumSignificantDigits();
1340            if (!useSigDig) {
1341                minSigDig = 0;
1342                maxSigDig = Integer.MAX_VALUE;
1343            }
1344
1345            // Output the integer portion. Here 'count' is the total
1346
// number of integer digits we will display, including both
1347
// leading zeros required to satisfy getMinimumIntegerDigits,
1348
// and actual digits present in the number.
1349
int count = useSigDig ?
1350                Math.max(1, digitList.decimalAt) : minIntDig;
1351            if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
1352                count = digitList.decimalAt;
1353            }
1354
1355            // Handle the case where getMaximumIntegerDigits() is smaller
1356
// than the real number of integer digits. If this is so, we
1357
// output the least significant max integer digits. For example,
1358
// the value 1997 printed with 2 max integer digits is just "97".
1359

1360            int digitIndex = 0; // Index into digitList.fDigits[]
1361
if (count > maxIntDig && maxIntDig >= 0) {
1362                count = maxIntDig;
1363                digitIndex = digitList.decimalAt - count;
1364            }
1365
1366            int sizeBeforeIntegerPart = result.length();
1367            for (i=count-1; i>=0; --i)
1368            {
1369                if (i < digitList.decimalAt && digitIndex < digitList.count &&
1370                    sigCount < maxSigDig) {
1371                    // Output a real digit
1372
byte d = digitList.digits[digitIndex++];
1373                    result.append((char)(d + zeroDelta));
1374                    ++sigCount;
1375                }
1376                else
1377                {
1378                    // Output a zero (leading or trailing)
1379
result.append(zero);
1380                    if (sigCount > 0) {
1381                        ++sigCount;
1382                    }
1383                }
1384
1385                // Output grouping separator if necessary.
1386
if (isGroupingPosition(i)) {
1387                    result.append(grouping);
1388//#ifndef FOUNDATION
1389
//## // [Spark/CDL] Add grouping separator attribute here.
1390
//## if (parseAttr) {
1391
//## // Length of grouping separator is 1.
1392
//## addAttribute(Field.GROUPING_SEPARATOR,
1393
//## result.length() - 1, result.length());
1394
//## }
1395
//#endif
1396
}
1397            }
1398
1399            // Record field information for caller.
1400
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1401                fieldPosition.setEndIndex(result.length());
1402            }
1403
1404            // Determine whether or not there are any printable fractional
1405
// digits. If we've used up the digits we know there aren't.
1406
boolean fractionPresent = (!isInteger && digitIndex < digitList.count) ||
1407                (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0));
1408
1409            // If there is no fraction present, and we haven't printed any
1410
// integer digits, then print a zero. Otherwise we won't print
1411
// _any_ digits, and we won't be able to parse this string.
1412
if (!fractionPresent && result.length() == sizeBeforeIntegerPart)
1413                result.append(zero);
1414//#ifndef FOUNDATION
1415
//## // [Spark/CDL] Add attribute for integer part.
1416
//## if (parseAttr) {
1417
//## addAttribute(Field.INTEGER, intBegin, result.length());
1418
//## }
1419
//#endif
1420
// Output the decimal separator if we always do so.
1421
if (decimalSeparatorAlwaysShown || fractionPresent)
1422            {
1423                result.append(decimal);
1424//#ifndef FOUNDATION
1425
//## // [Spark/CDL] Add attribute for decimal separator
1426
//## if (parseAttr) {
1427
//## addAttribute(Field.DECIMAL_SEPARATOR, result.length() - 1,
1428
//## result.length());
1429
//## }
1430
//#endif
1431
}
1432
1433            // Record field information for caller.
1434
if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1435                fieldPosition.setBeginIndex(result.length());
1436            }
1437
1438            // [Spark/CDL] Record the begin index of fraction part.
1439
int fracBegin = result.length();
1440
1441            count = useSigDig ? Integer.MAX_VALUE : getMaximumFractionDigits();
1442            if (useSigDig && (sigCount == maxSigDig ||
1443                              (sigCount >= minSigDig && digitIndex == digitList.count))) {
1444                count = 0;
1445            }
1446            for (i=0; i < count; ++i) {
1447                // Here is where we escape from the loop. We escape
1448
// if we've output the maximum fraction digits
1449
// (specified in the for expression above). We also
1450
// stop when we've output the minimum digits and
1451
// either: we have an integer, so there is no
1452
// fractional stuff to display, or we're out of
1453
// significant digits.
1454
if (!useSigDig && i >= getMinimumFractionDigits() &&
1455                    (isInteger || digitIndex >= digitList.count)) {
1456                    break;
1457                }
1458
1459                // Output leading fractional zeros. These are zeros
1460
// that come after the decimal but before any
1461
// significant digits. These are only output if
1462
// abs(number being formatted) < 1.0.
1463
if (-1-i > (digitList.decimalAt-1)) {
1464                    result.append(zero);
1465                    continue;
1466                }
1467
1468                // Output a digit, if we have any precision left, or a
1469
// zero if we don't. We don't want to output noise digits.
1470
if (!isInteger && digitIndex < digitList.count) {
1471                    result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
1472                } else {
1473                    result.append(zero);
1474                }
1475
1476                // If we reach the maximum number of significant
1477
// digits, or if we output all the real digits and
1478
// reach the minimum, then we are done.
1479
++sigCount;
1480                if (useSigDig &&
1481                    (sigCount == maxSigDig ||
1482                     (digitIndex == digitList.count && sigCount >= minSigDig))) {
1483                    break;
1484                }
1485            }
1486
1487            // Record field information for caller.
1488
if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1489                fieldPosition.setEndIndex(result.length());
1490            }
1491//#ifndef FOUNDATION
1492
//## // [Spark/CDL] Add attribute information if necessary.
1493
//## if (parseAttr && (decimalSeparatorAlwaysShown || fractionPresent)) {
1494
//## addAttribute(Field.FRACTION, fracBegin, result.length());
1495
//## }
1496
//#endif
1497
}
1498
1499        int suffixLen = appendAffix(result, isNegative, false, parseAttr);
1500
1501        // [NEW]
1502
addPadding(result, fieldPosition, prefixLen, suffixLen);
1503        return result;
1504    }
1505
1506    // [NEW]
1507
private final void addPadding(StringBuffer JavaDoc result, FieldPosition JavaDoc fieldPosition,
1508                                  int prefixLen, int suffixLen) {
1509        if (formatWidth > 0) {
1510            int len = formatWidth - result.length();
1511            if (len > 0) {
1512                char[] padding = new char[len];
1513                for (int i=0; i<len; ++i) {
1514                    padding[i] = pad;
1515                }
1516                switch (padPosition) {
1517                case PAD_AFTER_PREFIX:
1518                    result.insert(prefixLen, padding);
1519                    break;
1520                case PAD_BEFORE_PREFIX:
1521                    result.insert(0, padding);
1522                    break;
1523                case PAD_BEFORE_SUFFIX:
1524                    result.insert(result.length() - suffixLen, padding);
1525                    break;
1526                case PAD_AFTER_SUFFIX:
1527                    result.append(padding);
1528                    break;
1529                }
1530                if (padPosition == PAD_BEFORE_PREFIX ||
1531                    padPosition == PAD_AFTER_PREFIX) {
1532                    fieldPosition.setBeginIndex(fieldPosition.getBeginIndex() + len);
1533                    fieldPosition.setEndIndex(fieldPosition.getEndIndex() + len);
1534                }
1535            }
1536        }
1537    }
1538
1539    /**
1540     * <strong><font face=helvetica color=red>CHANGED</font></strong>
1541     * Parse the given string, returning a <code>Number</code> object to
1542     * represent the parsed value. <code>Double</code> objects are returned to
1543     * represent non-integral values which cannot be stored in a
1544     * <code>BigDecimal</code>. These are <code>NaN</code>, infinity,
1545     * -infinity, and -0.0. If {@link #isParseBigDecimal()} is false (the
1546     * default), all other values are returned as <code>Long</code>,
1547     * <code>BigInteger</code>, or <code>BigDecimal</code> values,
1548     * in that order of preference. If {@link #isParseBigDecimal()} is true,
1549     * all other values are returned as <code>BigDecimal</code> valuse.
1550     * If the parse fails, null is returned.
1551     * @param text the string to be parsed
1552     * @param parsePosition defines the position where parsing is to begin,
1553     * and upon return, the position where parsing left off. If the position
1554     * has not changed upon return, then parsing failed.
1555     * @return a <code>Number</code> object with the parsed value or
1556     * <code>null</code> if the parse failed
1557     * @stable ICU 2.0
1558     */

1559    public Number JavaDoc parse(String JavaDoc text, ParsePosition JavaDoc parsePosition) {
1560       return (Number JavaDoc) parse(text, parsePosition, false);
1561    }
1562
1563    /**
1564     * <strong><font face=helvetica color=red>NEW</font></strong>
1565     * Parses text from the given string as a CurrencyAmount. Unlike
1566     * the parse() method, this method will attempt to parse a generic
1567     * currency name, searching for a match of this object's locale's
1568     * currency display names, or for a 3-letter ISO currency code.
1569     * This method will fail if this format is not a currency format,
1570     * that is, if it does not contain the currency pattern symbol
1571     * (U+00A4) in its prefix or suffix.
1572     *
1573     * @param text the string to parse
1574     * @param pos input-output position; on input, the position within
1575     * text to match; must have 0 <= pos.getIndex() < text.length();
1576     * on output, the position after the last matched character. If
1577     * the parse fails, the position in unchanged upon output.
1578     * @return a CurrencyAmount, or null upon failure
1579     * @internal
1580     * @deprecated This API is ICU internal only.
1581     */

1582    CurrencyAmount parseCurrency(String JavaDoc text, ParsePosition JavaDoc pos) {
1583        return (CurrencyAmount) parse(text, pos, true);
1584    }
1585
1586    /**
1587     * Parses the given text as either a Number or a CurrencyAmount.
1588     * @param text the string to parse
1589     * @param parsePosition input-output position; on input, the
1590     * position within text to match; must have 0 <= pos.getIndex() <
1591     * text.length(); on output, the position after the last matched
1592     * character. If the parse fails, the position in unchanged upon
1593     * output.
1594     * @param parseCurrency if true, a CurrencyAmount is parsed and
1595     * returned; otherwise a Number is parsed and returned
1596     * @return a Number or CurrencyAmount or null
1597     */

1598    private Object JavaDoc parse(String JavaDoc text, ParsePosition JavaDoc parsePosition, boolean parseCurrency) {
1599        int backup;
1600        int i = backup = parsePosition.getIndex();
1601
1602        // Handle NaN as a special case:
1603

1604        // Skip padding characters, if around prefix
1605
if (formatWidth > 0 && (padPosition == PAD_BEFORE_PREFIX ||
1606                                padPosition == PAD_AFTER_PREFIX)) {
1607            i = skipPadding(text, i);
1608        }
1609        if (text.regionMatches(i, symbols.getNaN(),
1610                               0, symbols.getNaN().length())) {
1611            i += symbols.getNaN().length();
1612            // Skip padding characters, if around suffix
1613
if (formatWidth > 0 && (padPosition == PAD_BEFORE_SUFFIX ||
1614                                    padPosition == PAD_AFTER_SUFFIX)) {
1615                i = skipPadding(text, i);
1616            }
1617            parsePosition.setIndex(i);
1618            return new Double JavaDoc(Double.NaN);
1619        }
1620
1621        // NaN parse failed; start over
1622
i = backup;
1623
1624        boolean[] status = new boolean[STATUS_LENGTH];
1625        Currency[] currency = parseCurrency ? new Currency[1] : null;
1626        if (!subparse(text, parsePosition, digitList, false, status, currency)) {
1627            parsePosition.setIndex(backup);
1628            return null;
1629        }
1630
1631        Number JavaDoc n = null;
1632
1633        // Handle infinity
1634
if (status[STATUS_INFINITE]) {
1635            n = new Double JavaDoc(status[STATUS_POSITIVE]
1636                           ? Double.POSITIVE_INFINITY
1637                           : Double.NEGATIVE_INFINITY);
1638        }
1639
1640        // Handle -0.0
1641
else if (!status[STATUS_POSITIVE] && digitList.isZero()) {
1642            n = new Double JavaDoc(-0.0);
1643        }
1644
1645        else {
1646            // Do as much of the multiplier conversion as possible without
1647
// losing accuracy.
1648
int mult = multiplier; // Don't modify this.multiplier
1649
while (mult % 10 == 0) {
1650                --digitList.decimalAt;
1651                mult /= 10;
1652            }
1653
1654            // Handle integral values
1655
if (!parseBigDecimal && mult == 1 && digitList.isIntegral()) {
1656                // hack quick long
1657
if (digitList.decimalAt < 12) { // quick check for long
1658
long l = 0;
1659                    if (digitList.count > 0) {
1660                        int nx = 0;
1661                        while (nx < digitList.count) {
1662                            l = l * 10 + (char)digitList.digits[nx++] - '0';
1663                        }
1664                        while (nx++ < digitList.decimalAt) {
1665                            l *= 10;
1666                        }
1667                        if (!status[STATUS_POSITIVE]) {
1668                            l = -l;
1669                        }
1670                    }
1671                    n = new Long JavaDoc(l);
1672                } else {
1673                    BigInteger JavaDoc big = digitList.getBigInteger(status[STATUS_POSITIVE]);
1674                    n = (big.bitLength() < 64) ?
1675                        (Number JavaDoc) new Long JavaDoc(big.longValue()) : (Number JavaDoc) big;
1676                }
1677            }
1678
1679            // Handle non-integral values or the case where parseBigDecimal is set
1680
else {
1681                BigDecimal big = digitList.getBigDecimalICU(status[STATUS_POSITIVE]);
1682                n = big;
1683                if (mult != 1) {
1684                    n = big.divide(BigDecimal.valueOf(mult),
1685                            BigDecimal.ROUND_HALF_EVEN);
1686                }
1687            }
1688        }
1689
1690        // Assemble into CurrencyAmount if necessary
1691
return parseCurrency ? (Object JavaDoc) new CurrencyAmount(n, currency[0])
1692                             : (Object JavaDoc) n;
1693    }
1694
1695    private static final int STATUS_INFINITE = 0;
1696    private static final int STATUS_POSITIVE = 1;
1697    private static final int STATUS_LENGTH = 2;
1698
1699    /**
1700     * <strong><font face=helvetica color=red>CHANGED</font></strong>
1701     * Parse the given text into a number. The text is parsed beginning at
1702     * parsePosition, until an unparseable character is seen.
1703     * @param text The string to parse.
1704     * @param parsePosition The position at which to being parsing. Upon
1705     * return, the first unparseable character.
1706     * @param digits The DigitList to set to the parsed value.
1707     * @param isExponent If true, parse an exponent. This means no
1708     * infinite values and integer only.
1709     * @param status Upon return contains boolean status flags indicating
1710     * whether the value was infinite and whether it was positive.
1711     * @param currency return value for parsed currency, for generic
1712     * currency parsing mode, or null for normal parsing. In generic
1713     * currency parsing mode, any currency is parsed, not just the
1714     * currency that this formatter is set to.
1715     */

1716    private final boolean subparse(String JavaDoc text, ParsePosition JavaDoc parsePosition,
1717                   DigitList digits, boolean isExponent,
1718                   boolean status[], Currency currency[])
1719    {
1720        int position = parsePosition.getIndex();
1721        int oldStart = parsePosition.getIndex();
1722
1723        // Match padding before prefix
1724
if (formatWidth > 0 && padPosition == PAD_BEFORE_PREFIX) {
1725            position = skipPadding(text, position);
1726        }
1727
1728        // Match positive and negative prefixes; prefer longest match.
1729
int posMatch = compareAffix(text, position, false, true, currency);
1730        int negMatch = compareAffix(text, position, true, true, currency);
1731        if (posMatch >= 0 && negMatch >= 0) {
1732            if (posMatch > negMatch) {
1733                negMatch = -1;
1734            } else if (negMatch > posMatch) {
1735                posMatch = -1;
1736            }
1737        }
1738        if (posMatch >= 0) {
1739            position += posMatch;
1740        } else if (negMatch >= 0) {
1741            position += negMatch;
1742        } else {
1743            parsePosition.setErrorIndex(position);
1744            return false;
1745        }
1746
1747        // Match padding after prefix
1748
if (formatWidth > 0 && padPosition == PAD_AFTER_PREFIX) {
1749            position = skipPadding(text, position);
1750        }
1751
1752        // process digits or Inf, find decimal position
1753
status[STATUS_INFINITE] = false;
1754        if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0,
1755                          symbols.getInfinity().length()))
1756        {
1757            position += symbols.getInfinity().length();
1758            status[STATUS_INFINITE] = true;
1759        } else {
1760            // We now have a string of digits, possibly with grouping symbols,
1761
// and decimal points. We want to process these into a DigitList.
1762
// We don't want to put a bunch of leading zeros into the DigitList
1763
// though, so we keep track of the location of the decimal point,
1764
// put only significant digits into the DigitList, and adjust the
1765
// exponent as needed.
1766

1767            digits.decimalAt = digits.count = 0;
1768            char zero = symbols.getZeroDigit();
1769            char decimal = isCurrencyFormat ?
1770            symbols.getMonetaryDecimalSeparator() : symbols.getDecimalSeparator();
1771            char grouping = symbols.getGroupingSeparator();
1772            String JavaDoc exponentSep = symbols.getExponentSeparator();
1773            boolean sawDecimal = false;
1774            boolean sawExponent = false;
1775            boolean sawDigit = false;
1776            int exponent = 0; // Set to the exponent value, if any
1777
int digit = 0;
1778
1779            // strict parsing
1780
boolean strictParse = isParseStrict();
1781            boolean strictFail = false; // did we exit with a strict parse failure?
1782
boolean leadingZero = false; // did we see a leading zero?
1783
int lastGroup = -1; // where did we last see a grouping separator?
1784
int prevGroup = -1; // where did we see the grouping separator before that?
1785
int gs2 = groupingSize2 == 0 ? groupingSize : groupingSize2;
1786
1787            // We have to track digitCount ourselves, because digits.count will
1788
// pin when the maximum allowable digits is reached.
1789
int digitCount = 0;
1790            
1791            int backup = -1;
1792            for (; position < text.length(); ++position)
1793            {
1794                char ch = text.charAt(position);
1795
1796                /* We recognize all digit ranges, not only the Latin digit range
1797                 * '0'..'9'. We do so by using the UCharacter.digit() method,
1798                 * which converts a valid Unicode digit to the range 0..9.
1799                 *
1800                 * The character 'ch' may be a digit. If so, place its value
1801                 * from 0 to 9 in 'digit'. First try using the locale digit,
1802                 * which may or MAY NOT be a standard Unicode digit range. If
1803                 * this fails, try using the standard Unicode digit ranges by
1804                 * calling UCharacter.digit(). If this also fails, digit will
1805                 * have a value outside the range 0..9.
1806                 */

1807                digit = ch - zero;
1808                if (digit < 0 || digit > 9) digit = UCharacter.digit(ch, 10);
1809
1810                if (digit == 0)
1811                {
1812                    // Cancel out backup setting (see grouping handler below)
1813
if (strictParse && backup != -1) {
1814                        // comma followed by digit, so group before comma is a
1815
// secondary group. If there was a group separator
1816
// before that, the group must == the secondary group
1817
// length, else it can be <= the the secondary group
1818
// length.
1819
if ((lastGroup != -1 && backup - lastGroup - 1 != gs2) ||
1820                            (lastGroup == -1 && position - oldStart - 1 > gs2)) {
1821                            strictFail = true;
1822                            break;
1823                        }
1824                        prevGroup = lastGroup;
1825                        lastGroup = backup;
1826                    }
1827                    backup = -1; // Do this BEFORE continue statement below!!!
1828
sawDigit = true;
1829
1830                    // Handle leading zeros
1831
if (digits.count == 0)
1832                    {
1833                        if (!sawDecimal) {
1834                            if (strictParse && !isExponent) {
1835                                // Allow leading zeros in exponents
1836
if (leadingZero) {
1837                                    strictFail = true;
1838                                    break;
1839                                }
1840                                leadingZero = true;
1841                            }
1842                            // Ignore leading zeros in integer part of number.
1843
continue;
1844                        }
1845
1846                        // If we have seen the decimal, but no significant digits yet,
1847
// then we account for leading zeros by decrementing the
1848
// digits.decimalAt into negative values.
1849
--digits.decimalAt;
1850                    }
1851                    else
1852                    {
1853                        ++digitCount;
1854                        digits.append((char)(digit + '0'));
1855                    }
1856                }
1857                else if (digit > 0 && digit <= 9) // [sic] digit==0 handled above
1858
{
1859                    if (strictParse) {
1860                        if (leadingZero) {
1861                            // a leading zero before a digit is an error with strict parsing
1862
strictFail = true;
1863                            break;
1864                        }
1865                        if (backup != -1) {
1866                            if ((lastGroup != -1 && backup - lastGroup - 1 != gs2) ||
1867                                (lastGroup == -1 && position - oldStart - 1 > gs2)) {
1868                                strictFail = true;
1869                                break;
1870                            }
1871                            prevGroup = lastGroup;
1872                            lastGroup = backup;
1873                        }
1874                    }
1875
1876                    sawDigit = true;
1877                    ++digitCount;
1878                    digits.append((char)(digit + '0'));
1879
1880                    // Cancel out backup setting (see grouping handler below)
1881
backup = -1;
1882                }
1883                else if (!isExponent && ch == decimal)
1884                {
1885                    if (strictParse) {
1886                        if (backup != -1 ||
1887                            (lastGroup != -1 && position - lastGroup != groupingSize - 1)) {
1888                            strictFail = true;
1889                            break;
1890                        }
1891                    }
1892                    // If we're only parsing integers, or if we ALREADY saw the
1893
// decimal, then don't parse this one.
1894
if (isParseIntegerOnly() || sawDecimal) break;
1895                    digits.decimalAt = digitCount; // Not digits.count!
1896
sawDecimal = true;
1897                    leadingZero = false; // a single leading zero before a decimal is ok
1898
}
1899                else if (!isExponent && ch == grouping && isGroupingUsed())
1900                {
1901                    if (sawDecimal) {
1902                        break;
1903                    }
1904                    if (strictParse) {
1905                        if ((!sawDigit || backup != -1)) {
1906                            // leading group, or two group separators in a row
1907
strictFail = true;
1908                            break;
1909                        }
1910                    }
1911                    // Ignore grouping characters, if we are using them, but require
1912
// that they be followed by a digit. Otherwise we backup and
1913
// reprocess them.
1914
backup = position;
1915                }
1916                else if (!isExponent && !sawExponent &&
1917                         text.regionMatches(position, exponentSep,
1918                                            0, exponentSep.length()))
1919                {
1920                    // Parse sign, if present
1921
boolean negExp = false;
1922                    int pos = position + exponentSep.length();
1923                    if (pos < text.length()) {
1924                        ch = text.charAt(pos);
1925                        if (ch == symbols.getPlusSign()) {
1926                            ++pos;
1927                        } else if (ch == symbols.getMinusSign()) {
1928                            ++pos;
1929                            negExp = true;
1930                        }
1931                    }
1932
1933                    DigitList exponentDigits = new DigitList();
1934                    exponentDigits.count = 0;
1935                    while (pos < text.length()) {
1936                        digit = text.charAt(pos) - zero;
1937                        if (digit < 0 || digit > 9) {
1938                            /*
1939                              Can't parse "[1E0]" when pattern is "0.###E0;[0.###E0]"
1940                              Should update reassign the value of 'ch' in the
1941                              code: digit = Character.digit(ch, 10);
1942                              [Richard/GCL]
1943                            */

1944                            digit = UCharacter.digit(text.charAt(pos), 10);
1945                        }
1946                        if (digit >= 0 && digit <= 9) {
1947                            exponentDigits.append((char)(digit + '0'));
1948                            ++pos;
1949                        } else {
1950                            break;
1951                        }
1952                    }
1953                    
1954                    if (exponentDigits.count > 0) {
1955                        // defer strict parse until we know we have a bona-fide exponent
1956
if (strictParse) {
1957                            if (backup != -1 || lastGroup != -1) {
1958                                strictFail = true;
1959                                break;
1960                            }
1961                        }
1962
1963                        exponentDigits.decimalAt = exponentDigits.count;
1964                        exponent = (int) exponentDigits.getLong();
1965                        if (negExp) {
1966                            exponent = -exponent;
1967                        }
1968                        position = pos; // Advance past the exponent
1969
sawExponent = true;
1970                    }
1971
1972                    break; // Whether we fail or succeed, we exit this loop
1973
}
1974                else break;
1975            }
1976
1977            if (backup != -1) position = backup;
1978
1979            if (strictParse && !sawDecimal) {
1980                if (lastGroup != -1 && position - lastGroup != groupingSize + 1) {
1981                    strictFail = true;
1982                }
1983            }
1984            if (strictFail) {
1985                // only set with strictParse and a leading zero error
1986
// leading zeros are an error with strict parsing except
1987
// immediately before nondigit (except group separator
1988
// followed by digit), or end of text.
1989

1990                parsePosition.setIndex(oldStart);
1991                parsePosition.setErrorIndex(position);
1992                return false;
1993            }
1994
1995            // If there was no decimal point we have an integer
1996
if (!sawDecimal) digits.decimalAt = digitCount; // Not digits.count!
1997

1998            // Adjust for exponent, if any
1999
digits.decimalAt += exponent;
2000
2001            // If none of the text string was recognized. For example, parse
2002
// "x" with pattern "#0.00" (return index and error index both 0)
2003
// parse "$" with pattern "$#0.00". (return index 0 and error index
2004
// 1).
2005
if (!sawDigit && digitCount == 0) {
2006                parsePosition.setIndex(oldStart);
2007                parsePosition.setErrorIndex(oldStart);
2008                return false;
2009            }
2010        }
2011
2012        // Match padding before suffix
2013
if (formatWidth > 0 && padPosition == PAD_BEFORE_SUFFIX) {
2014            position = skipPadding(text, position);
2015        }
2016
2017        // Match positive and negative suffixes; prefer longest match.
2018
if (posMatch >= 0) {
2019            posMatch = compareAffix(text, position, false, false, currency);
2020        }
2021        if (negMatch >= 0) {
2022            negMatch = compareAffix(text, position, true, false, currency);
2023        }
2024        if (posMatch >= 0 && negMatch >= 0) {
2025            if (posMatch > negMatch) {
2026                negMatch = -1;
2027            } else if (negMatch > posMatch) {
2028                posMatch = -1;
2029            }
2030        }
2031
2032        // Fail if neither or both
2033
if ((posMatch >= 0) == (negMatch >= 0)) {
2034            parsePosition.setErrorIndex(position);
2035            return false;
2036        }
2037
2038        position += (posMatch>=0 ? posMatch : negMatch);
2039
2040        // Match padding after suffix
2041
if (formatWidth > 0 && padPosition == PAD_AFTER_SUFFIX) {
2042            position = skipPadding(text, position);
2043        }
2044
2045        parsePosition.setIndex(position);
2046
2047        status[STATUS_POSITIVE] = (posMatch >= 0);
2048
2049        if (parsePosition.getIndex() == oldStart) {
2050            parsePosition.setErrorIndex(position);
2051            return false;
2052        }
2053        return true;
2054    }
2055
2056    /**
2057     * Starting at position, advance past a run of pad characters, if any.
2058     * Return the index of the first character after position that is not a pad
2059     * character. Result is >= position.
2060     */

2061    private final int skipPadding(String JavaDoc text, int position) {
2062        while (position < text.length() && text.charAt(position) == pad) {
2063            ++position;
2064        }
2065        return position;
2066    }
2067
2068    /**
2069     * Return the length matched by the given affix, or -1 if none.
2070     * Runs of white space in the affix, match runs of white space in
2071     * the input. Pattern white space and input white space are
2072     * determined differently; see code.
2073     * @param text input text
2074     * @param pos offset into input at which to begin matching
2075     * @param isNegative
2076     * @param isPrefix
2077     * @param currency return value for parsed currency, for generic
2078     * currency parsing mode, or null for normal parsing. In generic
2079     * currency parsing mode, any currency is parsed, not just the
2080     * currency that this formatter is set to.
2081     * @return length of input that matches, or -1 if match failure
2082     */

2083    private int compareAffix(String JavaDoc text, int pos, boolean isNegative,
2084                             boolean isPrefix, Currency[] currency) {
2085        if (currency != null || currencyChoice != null) {
2086            if (isPrefix) {
2087                return compareComplexAffix(isNegative ? negPrefixPattern : posPrefixPattern,
2088                                           text, pos, currency);
2089            } else {
2090                return compareComplexAffix(isNegative ? negSuffixPattern : posSuffixPattern,
2091                                           text, pos, currency);
2092            }
2093        }
2094
2095        if (isPrefix) {
2096            return compareSimpleAffix(isNegative ? negativePrefix : positivePrefix,
2097                                      text, pos);
2098        } else {
2099            return compareSimpleAffix(isNegative ? negativeSuffix : positiveSuffix,
2100                                      text, pos);
2101        }
2102    }
2103
2104    /**
2105     * Return the length matched by the given affix, or -1 if none.
2106     * Runs of white space in the affix, match runs of white space in
2107     * the input. Pattern white space and input white space are
2108     * determined differently; see code.
2109     * @param affix pattern string, taken as a literal
2110     * @param input input text
2111     * @param pos offset into input at which to begin matching
2112     * @return length of input that matches, or -1 if match failure
2113     */

2114    private static int compareSimpleAffix(String JavaDoc affix, String JavaDoc input, int pos) {
2115        int start = pos;
2116        for (int i=0; i<affix.length(); ) {
2117            int c = UTF16.charAt(affix, i);
2118            int len = UTF16.getCharCount(c);
2119            if (UCharacterProperty.isRuleWhiteSpace(c)) {
2120                // We may have a pattern like: \u200F \u0020
2121
// and input text like: \u200F \u0020
2122
// Note that U+200F and U+0020 are RuleWhiteSpace but only
2123
// U+0020 is UWhiteSpace. So we have to first do a direct
2124
// match of the run of RULE whitespace in the pattern,
2125
// then match any extra characters.
2126
boolean literalMatch = false;
2127                while (pos < input.length() &&
2128                       UTF16.charAt(input, pos) == c) {
2129                    literalMatch = true;
2130                    i += len;
2131                    pos += len;
2132                    if (i == affix.length()) {
2133                        break;
2134                    }
2135                    c = UTF16.charAt(affix, i);
2136                    len = UTF16.getCharCount(c);
2137                    if (!UCharacterProperty.isRuleWhiteSpace(c)) {
2138                        break;
2139                    }
2140                }
2141                
2142                // Advance over run in affix
2143
i = skipRuleWhiteSpace(affix, i);
2144                
2145                // Advance over run in input text
2146
// Must see at least one white space char in input,
2147
// unless we've already matched some characters literally.
2148
int s = pos;
2149                pos = skipUWhiteSpace(input, pos);
2150                if (pos == s && !literalMatch) {
2151                    return -1;
2152                }
2153            } else {
2154                if (pos < input.length() &&
2155                    UTF16.charAt(input, pos) == c) {
2156                    i += len;
2157                    pos += len;
2158                } else {
2159                    return -1;
2160                }
2161            }
2162        }
2163        return pos - start;
2164    }
2165
2166    /**
2167     * Skip over a run of zero or more isRuleWhiteSpace() characters at
2168     * pos in text.
2169     */

2170    private static int skipRuleWhiteSpace(String JavaDoc text, int pos) {
2171        while (pos < text.length()) {
2172            int c = UTF16.charAt(text, pos);
2173            if (!UCharacterProperty.isRuleWhiteSpace(c)) {
2174                break;
2175            }
2176            pos += UTF16.getCharCount(c);
2177        }
2178        return pos;
2179    }
2180
2181    /**
2182     * Skip over a run of zero or more isUWhiteSpace() characters at pos
2183     * in text.
2184     */

2185    private static int skipUWhiteSpace(String JavaDoc text, int pos) {
2186        while (pos < text.length()) {
2187            int c = UTF16.charAt(text, pos);
2188            if (!UCharacter.isUWhiteSpace(c)) {
2189                break;
2190            }
2191            pos += UTF16.getCharCount(c);
2192        }
2193        return pos;
2194    }
2195
2196    /**
2197     * Return the length matched by the given affix, or -1 if none.
2198     * @param affixPat pattern string
2199     * @param text input text
2200     * @param pos offset into input at which to begin matching
2201     * @param currency return value for parsed currency, for generic
2202     * currency parsing mode, or null for normal parsing. In generic
2203     * currency parsing mode, any currency is parsed, not just the
2204     * currency that this formatter is set to.
2205     * @return length of input that matches, or -1 if match failure
2206     */

2207    private int compareComplexAffix(String JavaDoc affixPat, String JavaDoc text, int pos,
2208                                    Currency[] currency) {
2209
2210        for (int i=0; i<affixPat.length() && pos >= 0; ) {
2211            char c = affixPat.charAt(i++);
2212            if (c == QUOTE) {
2213                for (;;) {
2214                    int j = affixPat.indexOf(QUOTE, i);
2215                    if (j == i) {
2216                        pos = match(text, pos, QUOTE);
2217                        i = j+1;
2218                        break;
2219                    } else if (j > i) {
2220                        pos = match(text, pos, affixPat.substring(i, j));
2221                        i = j+1;
2222                        if (i<affixPat.length() &&
2223                            affixPat.charAt(i)==QUOTE) {
2224                            pos = match(text, pos, QUOTE);
2225                            ++i;
2226                            // loop again
2227
} else {
2228                            break;
2229                        }
2230                    } else {
2231                        // Unterminated quote; should be caught by apply
2232
// pattern.
2233
throw new RuntimeException JavaDoc();
2234                    }
2235                }
2236                continue;
2237            }
2238
2239            switch (c) {
2240            case CURRENCY_SIGN:
2241                // If currency != null, then perform generic currency matching.
2242
// Otherwise, do currency choice parsing.
2243
//assert(currency != null ||
2244
// (getCurrency() != null && currencyChoice != null));
2245
boolean intl = i<affixPat.length() &&
2246                    affixPat.charAt(i) == CURRENCY_SIGN;
2247
2248                // Parse generic currency -- anything for which we
2249
// have a display name, or any 3-letter ISO code.
2250
if (currency != null) {
2251                    // Try to parse display name for our locale; first
2252
// determine our locale.
2253
ULocale uloc = getLocale(ULocale.VALID_LOCALE);
2254                    if (uloc == null) {
2255                        // applyPattern has been called; use the symbols
2256
uloc = symbols.getLocale(ULocale.VALID_LOCALE);
2257                    }
2258                    // Delegate parse of display name => ISO code to Currency
2259
ParsePosition JavaDoc ppos = new ParsePosition JavaDoc(pos);
2260                    String JavaDoc iso = Currency.parse(uloc, text, ppos);
2261
2262                    // If parse succeeds, populate currency[0]
2263
if (iso != null) {
2264                        currency[0] = Currency.getInstance(iso);
2265                        pos = ppos.getIndex();
2266                    } else {
2267                        pos = -1;
2268                    }
2269                } else {
2270                    if (intl) {
2271                        ++i;
2272                        pos = match(text, pos, getCurrency().getCurrencyCode());
2273                    } else {
2274                        ParsePosition JavaDoc ppos = new ParsePosition JavaDoc(pos);
2275                        /* Number n = */currencyChoice.parse(text, ppos);
2276                        pos = (ppos.getIndex() == pos) ? -1 : ppos.getIndex();
2277                    }
2278                }
2279                continue;
2280            case PATTERN_PERCENT:
2281                c = symbols.getPercent();
2282                break;
2283            case PATTERN_PER_MILLE:
2284                c = symbols.getPerMill();
2285                break;
2286            case PATTERN_MINUS:
2287                c = symbols.getMinusSign();
2288                break;
2289            }
2290            pos = match(text, pos, c);
2291            if (UCharacterProperty.isRuleWhiteSpace(c)) {
2292                i = skipRuleWhiteSpace(affixPat, i);
2293            }
2294        }
2295
2296        return pos;
2297    }
2298
2299    /**
2300     * Match a single character at text[pos] and return the index of the
2301     * next character upon success. Return -1 on failure. If
2302     * isRuleWhiteSpace(ch) then match a run of white space in text.
2303     */

2304    static final int match(String JavaDoc text, int pos, int ch) {
2305        if (UCharacterProperty.isRuleWhiteSpace(ch)) {
2306            // Advance over run of white space in input text
2307
// Must see at least one white space char in input
2308
int s = pos;
2309            pos = skipUWhiteSpace(text, pos);
2310            if (pos == s) {
2311                return -1;
2312            }
2313            return pos;
2314        }
2315        return (pos >= 0 && UTF16.charAt(text, pos) == ch) ?
2316            (pos + UTF16.getCharCount(ch)) : -1;
2317    }
2318
2319    /**
2320     * Match a string at text[pos] and return the index of the next
2321     * character upon success. Return -1 on failure. Match a run of
2322     * white space in str with a run of white space in text.
2323     */

2324    static final int match(String JavaDoc text, int pos, String JavaDoc str) {
2325        for (int i=0; i<str.length() && pos >= 0; ) {
2326            int ch = UTF16.charAt(str, i);
2327            i += UTF16.getCharCount(ch);
2328            pos = match(text, pos, ch);
2329            if (UCharacterProperty.isRuleWhiteSpace(ch)) {
2330                i = skipRuleWhiteSpace(str, i);
2331            }
2332        }
2333        return pos;
2334    }
2335
2336    /**
2337     * Returns a copy of the decimal format symbols used by this format.
2338     * @return desired DecimalFormatSymbols
2339     * @see DecimalFormatSymbols
2340     * @stable ICU 2.0
2341     */

2342    public DecimalFormatSymbols getDecimalFormatSymbols() {
2343        try {
2344            // don't allow multiple references
2345
return (DecimalFormatSymbols) symbols.clone();
2346        } catch (Exception JavaDoc foo) {
2347            return null; // should never happen
2348
}
2349    }
2350
2351
2352    /**
2353     * Sets the decimal format symbols used by this format. The
2354     * format uses a copy of the provided symbols.
2355     * @param newSymbols desired DecimalFormatSymbols
2356     * @see DecimalFormatSymbols
2357     * @stable ICU 2.0
2358     */

2359    public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
2360        symbols = (DecimalFormatSymbols) newSymbols.clone();
2361        setCurrencyForSymbols();
2362        expandAffixes();
2363    }
2364
2365    /**
2366     * Update the currency object to match the symbols. This method
2367     * is used only when the caller has passed in a symbols object
2368     * that may not be the default object for its locale.
2369     */

2370    private void setCurrencyForSymbols() {
2371        /*Bug 4212072
2372          Update the affix strings accroding to symbols in order to keep
2373          the affix strings up to date.
2374          [Richard/GCL]
2375        */

2376        
2377        // With the introduction of the Currency object, the currency
2378
// symbols in the DFS object are ignored. For backward
2379
// compatibility, we check any explicitly set DFS object. If it
2380
// is a default symbols object for its locale, we change the
2381
// currency object to one for that locale. If it is custom,
2382
// we set the currency to null.
2383
DecimalFormatSymbols def =
2384            new DecimalFormatSymbols(symbols.getLocale());
2385        
2386        if (symbols.getCurrencySymbol().equals(
2387                def.getCurrencySymbol()) &&
2388            symbols.getInternationalCurrencySymbol().equals(
2389                def.getInternationalCurrencySymbol())) {
2390            setCurrency(Currency.getInstance(symbols.getLocale()));
2391        } else {
2392            setCurrency(null);
2393        }
2394    }
2395
2396    /**
2397     * Get the positive prefix.
2398     * <P>Examples: +123, $123, sFr123
2399     * @stable ICU 2.0
2400     */

2401    public String JavaDoc getPositivePrefix () {
2402        return positivePrefix;
2403    }
2404
2405    /**
2406     * Set the positive prefix.
2407     * <P>Examples: +123, $123, sFr123
2408     * @stable ICU 2.0
2409     */

2410    public void setPositivePrefix (String JavaDoc newValue) {
2411        positivePrefix = newValue;
2412        posPrefixPattern = null;
2413    }
2414
2415    /**
2416     * Get the negative prefix.
2417     * <P>Examples: -123, ($123) (with negative suffix), sFr-123
2418     * @stable ICU 2.0
2419     */

2420    public String JavaDoc getNegativePrefix () {
2421        return negativePrefix;
2422    }
2423
2424    /**
2425     * Set the negative prefix.
2426     * <P>Examples: -123, ($123) (with negative suffix), sFr-123
2427     * @stable ICU 2.0
2428     */

2429    public void setNegativePrefix (String JavaDoc newValue) {
2430        negativePrefix = newValue;
2431        negPrefixPattern = null;
2432    }
2433
2434    /**
2435     * Get the positive suffix.
2436     * <P>Example: 123%
2437     * @stable ICU 2.0
2438     */

2439    public String JavaDoc getPositiveSuffix () {
2440        return positiveSuffix;
2441    }
2442
2443    /**
2444     * Set the positive suffix.
2445     * <P>Example: 123%
2446     * @stable ICU 2.0
2447     */

2448    public void setPositiveSuffix (String JavaDoc newValue) {
2449        positiveSuffix = newValue;
2450        posSuffixPattern = null;
2451    }
2452
2453    /**
2454     * Get the negative suffix.
2455     * <P>Examples: -123%, ($123) (with positive suffixes)
2456     * @stable ICU 2.0
2457     */

2458    public String JavaDoc getNegativeSuffix () {
2459        return negativeSuffix;
2460    }
2461
2462    /**
2463     * Set the positive suffix.
2464     * <P>Examples: 123%
2465     * @stable ICU 2.0
2466     */

2467    public void setNegativeSuffix (String JavaDoc newValue) {
2468        negativeSuffix = newValue;
2469        negSuffixPattern = null;
2470    }
2471
2472    /**
2473     * Get the multiplier for use in percent, permill, etc.
2474     * For a percentage, set the suffixes to have "%" and the multiplier to be 100.
2475     * (For Arabic, use arabic percent symbol).
2476     * For a permill, set the suffixes to have "?" and the multiplier to be 1000.
2477     * <P>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
2478     * @stable ICU 2.0
2479     */

2480    public int getMultiplier () {
2481        return multiplier;
2482    }
2483
2484    /**
2485     * Set the multiplier for use in percent, permill, etc.
2486     * For a percentage, set the suffixes to have "%" and the multiplier to be 100.
2487     * (For Arabic, use arabic percent symbol).
2488     * For a permill, set the suffixes to have "?" and the multiplier to be 1000.
2489     * <P>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
2490     * @stable ICU 2.0
2491     */

2492    public void setMultiplier (int newValue) {
2493        if (newValue <= 0) {
2494            throw new IllegalArgumentException JavaDoc("Bad multiplier: " + newValue);
2495        }
2496        multiplier = newValue;
2497    }
2498
2499    /**
2500     * <strong><font face=helvetica color=red>NEW</font></strong>
2501     * Get the rounding increment.
2502     * @return A positive rounding increment, or <code>null</code> if rounding
2503     * is not in effect.
2504     * @see #setRoundingIncrement
2505     * @see #getRoundingMode
2506     * @see #setRoundingMode
2507     * @stable ICU 2.0
2508     */

2509//#ifdef FOUNDATION
2510
public BigDecimal getRoundingIncrement() {
2511        if (roundingIncrementICU == null) return null;
2512        return new BigDecimal(roundingIncrementICU.toString());
2513    }
2514//#else
2515
//#ifdef ECLIPSE_FRAGMENT
2516
//## public BigDecimal getRoundingIncrement() {
2517
//## if (roundingIncrementICU == null) return null;
2518
//## return new BigDecimal(roundingIncrementICU.toString());
2519
//## }
2520
//#else
2521
//## public java.math.BigDecimal getRoundingIncrement() {
2522
//## if (roundingIncrementICU == null) return null;
2523
//## return roundingIncrementICU.toBigDecimal();
2524
//## }
2525
//#endif
2526
//#endif
2527

2528//#ifndef FOUNDATION
2529
//## /**
2530
//## * <strong><font face=helvetica color=red>NEW</font></strong>
2531
//## * Set the rounding increment. This method also controls whether
2532
//## * rounding is enabled.
2533
//## * @param newValue A positive rounding increment, or <code>null</code> or
2534
//## * <code>BigDecimal(0.0)</code> to disable rounding.
2535
//## * @exception IllegalArgumentException if <code>newValue</code> is < 0.0
2536
//## * @see #getRoundingIncrement
2537
//## * @see #getRoundingMode
2538
//## * @see #setRoundingMode
2539
//## * @stable ICU 2.0
2540
//## */
2541
//## public void setRoundingIncrement(java.math.BigDecimal newValue) {
2542
//## if (newValue == null) {
2543
//## setRoundingIncrement((BigDecimal)null);
2544
//## } else {
2545
//## setRoundingIncrement(new BigDecimal(newValue));
2546
//## }
2547
//## }
2548
//#endif
2549

2550    /**
2551     * <strong><font face=helvetica color=red>NEW</font></strong>
2552     * Set the rounding increment. This method also controls whether
2553     * rounding is enabled.
2554     * @param newValue A positive rounding increment, or <code>null</code> or
2555     * <code>BigDecimal(0.0)</code> to disable rounding.
2556     * @exception IllegalArgumentException if <code>newValue</code> is < 0.0
2557     * @see #getRoundingIncrement
2558     * @see #getRoundingMode
2559     * @see #setRoundingMode
2560     * @draft ICU 3.4.2
2561     * @provisional This API might change or be removed in a future release.
2562     */

2563    public void setRoundingIncrement(BigDecimal newValue) {
2564        int i = newValue == null
2565            ? 0 : newValue.compareTo(BigDecimal.ZERO);
2566        if (i < 0) {
2567            throw new IllegalArgumentException JavaDoc("Illegal rounding increment");
2568        }
2569        if (i == 0) {
2570            setInternalRoundingIncrement(null);
2571        } else {
2572            setInternalRoundingIncrement(newValue);
2573        }
2574        setRoundingDouble();
2575    }
2576
2577
2578    /**
2579     * <strong><font face=helvetica color=red>NEW</font></strong>
2580     * Set the rounding increment. This method also controls whether
2581     * rounding is enabled.
2582     * @param newValue A positive rounding increment, or 0.0 to disable
2583     * rounding.
2584     * @exception IllegalArgumentException if <code>newValue</code> is < 0.0
2585     * @see #getRoundingIncrement
2586     * @see #getRoundingMode
2587     * @see #setRoundingMode
2588     * @stable ICU 2.0
2589     */

2590    public void setRoundingIncrement(double newValue) {
2591        if (newValue < 0.0) {
2592            throw new IllegalArgumentException JavaDoc("Illegal rounding increment");
2593        }
2594        roundingDouble = newValue;
2595        roundingDoubleReciprocal = 0.0d;
2596        if (newValue == 0.0d) {
2597            setRoundingIncrement((BigDecimal)null);
2598        } else {
2599            roundingDouble = newValue;
2600            if (roundingDouble < 1.0d) {
2601                double rawRoundedReciprocal = 1.0d/roundingDouble;
2602                setRoundingDoubleReciprocal(rawRoundedReciprocal);
2603            }
2604            setInternalRoundingIncrement(new BigDecimal(newValue));
2605        }
2606    }
2607
2608
2609    private void setRoundingDoubleReciprocal(double rawRoundedReciprocal) {
2610        roundingDoubleReciprocal = Math.rint(rawRoundedReciprocal);
2611        if (Math.abs(rawRoundedReciprocal - roundingDoubleReciprocal) > roundingIncrementEpsilon) {
2612            roundingDoubleReciprocal = 0.0d;
2613        }
2614    }
2615    
2616    static final double roundingIncrementEpsilon = 0.000000001;
2617    
2618    /**
2619     * <strong><font face=helvetica color=red>NEW</font></strong>
2620     * Get the rounding mode.
2621     * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code>
2622     * and <code>BigDecimal.ROUND_UNNECESSARY</code>.
2623     * @see #setRoundingIncrement
2624     * @see #getRoundingIncrement
2625     * @see #setRoundingMode
2626     * @see java.math.BigDecimal
2627     * @stable ICU 2.0
2628     */

2629    public int getRoundingMode() {
2630        return roundingMode;
2631    }
2632
2633    /**
2634     * <strong><font face=helvetica color=red>NEW</font></strong>
2635     * Set the rounding mode. This has no effect unless the rounding
2636     * increment is greater than zero.
2637     * @param roundingMode A rounding mode, between
2638     * <code>BigDecimal.ROUND_UP</code> and
2639     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
2640     * @exception IllegalArgumentException if <code>roundingMode</code>
2641     * is unrecognized.
2642     * @see #setRoundingIncrement
2643     * @see #getRoundingIncrement
2644     * @see #getRoundingMode
2645     * @see java.math.BigDecimal
2646     * @stable ICU 2.0
2647     */

2648    public void setRoundingMode(int roundingMode) {
2649        if (roundingMode < BigDecimal.ROUND_UP
2650            || roundingMode > BigDecimal.ROUND_UNNECESSARY) {
2651            throw new IllegalArgumentException JavaDoc("Invalid rounding mode: "
2652                                               + roundingMode);
2653        }
2654        this.roundingMode = roundingMode;
2655    }
2656
2657    /**
2658     * <strong><font face=helvetica color=red>NEW</font></strong>
2659     * Get the width to which the output of <code>format()</code> is padded.
2660     * The width is counted in 16-bit code units.
2661     * @return the format width, or zero if no padding is in effect
2662     * @see #setFormatWidth
2663     * @see #getPadCharacter
2664     * @see #setPadCharacter
2665     * @see #getPadPosition
2666     * @see #setPadPosition
2667     * @stable ICU 2.0
2668     */

2669    public int getFormatWidth() {
2670        return formatWidth;
2671    }
2672
2673    /**
2674     * <strong><font face=helvetica color=red>NEW</font></strong>
2675     * Set the width to which the output of <code>format()</code> is padded.
2676     * The width is counted in 16-bit code units.
2677     * This method also controls whether padding is enabled.
2678     * @param width the width to which to pad the result of
2679     * <code>format()</code>, or zero to disable padding
2680     * @exception IllegalArgumentException if <code>width</code> is < 0
2681     * @see #getFormatWidth
2682     * @see #getPadCharacter
2683     * @see #setPadCharacter
2684     * @see #getPadPosition
2685     * @see #setPadPosition
2686     * @stable ICU 2.0
2687     */

2688    public void setFormatWidth(int width) {
2689        if (width < 0) {
2690            throw new IllegalArgumentException JavaDoc("Illegal format width");
2691        }
2692        formatWidth = width;
2693    }
2694
2695    /**
2696     * <strong><font face=helvetica color=red>NEW</font></strong>
2697     * Get the character used to pad to the format width. The default is ' '.
2698     * @return the pad character
2699     * @see #setFormatWidth
2700     * @see #getFormatWidth
2701     * @see #setPadCharacter
2702     * @see #getPadPosition
2703     * @see #setPadPosition
2704     * @stable ICU 2.0
2705     */

2706    public char getPadCharacter() {
2707        return pad;
2708    }
2709
2710    /**
2711     * <strong><font face=helvetica color=red>NEW</font></strong>
2712     * Set the character used to pad to the format width. If padding
2713     * is not enabled, then this will take effect if padding is later
2714     * enabled.
2715     * @param padChar the pad character
2716     * @see #setFormatWidth
2717     * @see #getFormatWidth
2718     * @see #getPadCharacter
2719     * @see #getPadPosition
2720     * @see #setPadPosition
2721     * @stable ICU 2.0
2722     */

2723    public void setPadCharacter(char padChar) {
2724        pad = padChar;
2725    }
2726
2727    /**
2728     * <strong><font face=helvetica color=red>NEW</font></strong>
2729     * Get the position at which padding will take place. This is the location
2730     * at which padding will be inserted if the result of <code>format()</code>
2731     * is shorter than the format width.
2732     * @return the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
2733     * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
2734     * <code>PAD_AFTER_SUFFIX</code>.
2735     * @see #setFormatWidth
2736     * @see #getFormatWidth
2737     * @see #setPadCharacter
2738     * @see #getPadCharacter
2739     * @see #setPadPosition
2740     * @see #PAD_BEFORE_PREFIX
2741     * @see #PAD_AFTER_PREFIX
2742     * @see #PAD_BEFORE_SUFFIX
2743     * @see #PAD_AFTER_SUFFIX
2744     * @stable ICU 2.0
2745     */

2746    public int getPadPosition() {
2747        return padPosition;
2748    }
2749
2750    /**
2751     * <strong><font face=helvetica color=red>NEW</font></strong>
2752     * Set the position at which padding will take place. This is the location
2753     * at which padding will be inserted if the result of <code>format()</code>
2754     * is shorter than the format width. This has no effect unless padding is
2755     * enabled.
2756     * @param padPos the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
2757     * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
2758     * <code>PAD_AFTER_SUFFIX</code>.
2759     * @exception IllegalArgumentException if the pad position in
2760     * unrecognized
2761     * @see #setFormatWidth
2762     * @see #getFormatWidth
2763     * @see #setPadCharacter
2764     * @see #getPadCharacter
2765     * @see #getPadPosition
2766     * @see #PAD_BEFORE_PREFIX
2767     * @see #PAD_AFTER_PREFIX
2768     * @see #PAD_BEFORE_SUFFIX
2769     * @see #PAD_AFTER_SUFFIX
2770     * @stable ICU 2.0
2771     */

2772    public void setPadPosition(int padPos) {
2773        if (padPos < PAD_BEFORE_PREFIX || padPos > PAD_AFTER_SUFFIX) {
2774            throw new IllegalArgumentException JavaDoc("Illegal pad position");
2775        }
2776        padPosition = padPos;
2777    }
2778
2779    /**
2780     * <strong><font face=helvetica color=red>NEW</font></strong>
2781     * Return whether or not scientific notation is used.
2782     * @return true if this object formats and parses scientific notation
2783     * @see #setScientificNotation
2784     * @see #getMinimumExponentDigits
2785     * @see #setMinimumExponentDigits
2786     * @see #isExponentSignAlwaysShown
2787     * @see #setExponentSignAlwaysShown
2788     * @stable ICU 2.0
2789     */

2790    public boolean isScientificNotation() {
2791        return useExponentialNotation;
2792    }
2793
2794    /**
2795     * <strong><font face=helvetica color=red>NEW</font></strong>
2796     * Set whether or not scientific notation is used. When scientific notation
2797     * is used, the effective maximum number of integer digits is <= 8. If the
2798     * maximum number of integer digits is set to more than 8, the effective
2799     * maximum will be 1. This allows this call to generate a 'default' scientific
2800     * number format without additional changes.
2801     * @param useScientific true if this object formats and parses scientific
2802     * notation
2803     * @see #isScientificNotation
2804     * @see #getMinimumExponentDigits
2805     * @see #setMinimumExponentDigits
2806     * @see #isExponentSignAlwaysShown
2807     * @see #setExponentSignAlwaysShown
2808     * @stable ICU 2.0
2809     */

2810    public void setScientificNotation(boolean useScientific) {
2811        useExponentialNotation = useScientific;
2812    }
2813
2814    /**
2815     * <strong><font face=helvetica color=red>NEW</font></strong>
2816     * Return the minimum exponent digits that will be shown.
2817     * @return the minimum exponent digits that will be shown
2818     * @see #setScientificNotation
2819     * @see #isScientificNotation
2820     * @see #setMinimumExponentDigits
2821     * @see #isExponentSignAlwaysShown
2822     * @see #setExponentSignAlwaysShown
2823     * @stable ICU 2.0
2824     */

2825    public byte getMinimumExponentDigits() {
2826        return minExponentDigits;
2827    }
2828    
2829    /**
2830     * <strong><font face=helvetica color=red>NEW</font></strong>
2831     * Set the minimum exponent digits that will be shown. This has no
2832     * effect unless scientific notation is in use.
2833     * @param minExpDig a value >= 1 indicating the fewest exponent digits
2834     * that will be shown
2835     * @exception IllegalArgumentException if <code>minExpDig</code> < 1
2836     * @see #setScientificNotation
2837     * @see #isScientificNotation
2838     * @see #getMinimumExponentDigits
2839     * @see #isExponentSignAlwaysShown
2840     * @see #setExponentSignAlwaysShown
2841     * @stable ICU 2.0
2842     */

2843    public void setMinimumExponentDigits(byte minExpDig) {
2844        if (minExpDig < 1) {
2845            throw new IllegalArgumentException JavaDoc("Exponent digits must be >= 1");
2846        }
2847        minExponentDigits = minExpDig;
2848    }
2849
2850    /**
2851     * <strong><font face=helvetica color=red>NEW</font></strong>
2852     * Return whether the exponent sign is always shown.
2853     * @return true if the exponent is always prefixed with either the
2854     * localized minus sign or the localized plus sign, false if only negative
2855     * exponents are prefixed with the localized minus sign.
2856     * @see #setScientificNotation
2857     * @see #isScientificNotation
2858     * @see #setMinimumExponentDigits
2859     * @see #getMinimumExponentDigits
2860     * @see #setExponentSignAlwaysShown
2861     * @stable ICU 2.0
2862     */

2863    public boolean isExponentSignAlwaysShown() {
2864        return exponentSignAlwaysShown;
2865    }
2866
2867    /**
2868     * <strong><font face=helvetica color=red>NEW</font></strong>
2869     * Set whether the exponent sign is always shown. This has no effect
2870     * unless scientific notation is in use.
2871     * @param expSignAlways true if the exponent is always prefixed with either
2872     * the localized minus sign or the localized plus sign, false if only
2873     * negative exponents are prefixed with the localized minus sign.
2874     * @see #setScientificNotation
2875     * @see #isScientificNotation
2876     * @see #setMinimumExponentDigits
2877     * @see #getMinimumExponentDigits
2878     * @see #isExponentSignAlwaysShown
2879     * @stable ICU 2.0
2880     */

2881    public void setExponentSignAlwaysShown(boolean expSignAlways) {
2882        exponentSignAlwaysShown = expSignAlways;
2883    }
2884
2885    /**
2886     * Return the grouping size. Grouping size is the number of digits between
2887     * grouping separators in the integer portion of a number. For example,
2888     * in the number "123,456.78", the grouping size is 3.
2889     * @see #setGroupingSize
2890     * @see NumberFormat#isGroupingUsed
2891     * @see DecimalFormatSymbols#getGroupingSeparator
2892     * @stable ICU 2.0
2893     */

2894    public int getGroupingSize () {
2895        return groupingSize;
2896    }
2897
2898    /**
2899     * Set the grouping size. Grouping size is the number of digits between
2900     * grouping separators in the integer portion of a number. For example,
2901     * in the number "123,456.78", the grouping size is 3.
2902     * @see #getGroupingSize
2903     * @see NumberFormat#setGroupingUsed
2904     * @see DecimalFormatSymbols#setGroupingSeparator
2905     * @stable ICU 2.0
2906     */

2907    public void setGroupingSize (int newValue) {
2908        groupingSize = (byte)newValue;
2909    }
2910
2911    /**
2912     * Return the secondary grouping size. In some locales one
2913     * grouping interval is used for the least significant integer
2914     * digits (the primary grouping size), and another is used for all
2915     * others (the secondary grouping size). A formatter supporting a
2916     * secondary grouping size will return a positive integer unequal
2917     * to the primary grouping size returned by
2918     * <code>getGroupingSize()</code>. For example, if the primary
2919     * grouping size is 4, and the secondary grouping size is 2, then
2920     * the number 123456789 formats as "1,23,45,6789", and the pattern
2921     * appears as "#,##,###0".
2922     * [NEW]
2923     * @return the secondary grouping size, or a value less than
2924     * one if there is none
2925     * @see #setSecondaryGroupingSize
2926     * @see NumberFormat#isGroupingUsed
2927     * @see DecimalFormatSymbols#getGroupingSeparator
2928     * @stable ICU 2.0
2929     */

2930    public int getSecondaryGroupingSize () {
2931        return groupingSize2;
2932    }
2933
2934    /**
2935     * Set the secondary grouping size. If set to a value less than 1,
2936     * then secondary grouping is turned off, and the primary grouping
2937     * size is used for all intervals, not just the least significant.
2938     * [NEW]
2939     * @see #getSecondaryGroupingSize
2940     * @see NumberFormat#setGroupingUsed
2941     * @see DecimalFormatSymbols#setGroupingSeparator
2942     * @stable ICU 2.0
2943     */

2944    public void setSecondaryGroupingSize (int newValue) {
2945        groupingSize2 = (byte)newValue;
2946    }
2947
2948    /**
2949     * Allows you to get the behavior of the decimal separator with integers.
2950     * (The decimal separator will always appear with decimals.)
2951     * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
2952     * @stable ICU 2.0
2953     */

2954    public boolean isDecimalSeparatorAlwaysShown() {
2955        return decimalSeparatorAlwaysShown;
2956    }
2957
2958    /**
2959     * Allows you to set the behavior of the decimal separator with integers.
2960     * (The decimal separator will always appear with decimals.)
2961     *
2962     * <p>This only affects formatting, and only where
2963     * there might be no digits after the decimal point, e.g.,
2964     * if true, 3456.00 -> "3,456."
2965     * if false, 3456.00 -> "3456"
2966     * This is independent of parsing. If you want parsing to stop at the decimal
2967     * point, use setParseIntegerOnly.
2968     *
2969     * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
2970     * @stable ICU 2.0
2971     */

2972    public void setDecimalSeparatorAlwaysShown(boolean newValue) {
2973        decimalSeparatorAlwaysShown = newValue;
2974    }
2975
2976    /**
2977     * Standard override; no change in semantics.
2978     * @stable ICU 2.0
2979     */

2980    public Object JavaDoc clone() {
2981        try {
2982            DecimalFormat other = (DecimalFormat) super.clone();
2983            other.symbols = (DecimalFormatSymbols) symbols.clone();
2984            other.digitList = new DigitList(); // fix for JB#5358
2985
/*
2986             * TODO: We need to figure out whether we share a single copy
2987             * of DigitList by multiple cloned copies. format/subformat
2988             * are designed to use a single instance, but parse/subparse
2989             * implementation is not.
2990             */

2991            return other;
2992        } catch (Exception JavaDoc e) {
2993            throw new IllegalStateException JavaDoc();
2994        }
2995    }
2996
2997    /**
2998     * Overrides equals
2999     * @stable ICU 2.0
3000     */

3001    public boolean equals(Object JavaDoc obj)
3002    {
3003        if (obj == null) return false;
3004        if (!super.equals(obj)) return false; // super does class check
3005

3006        DecimalFormat other = (DecimalFormat) obj;
3007        /* Add the comparison of the four new added fields ,they are
3008         * posPrefixPattern, posSuffixPattern, negPrefixPattern, negSuffixPattern.
3009         * [Richard/GCL]
3010         */

3011        return (posPrefixPattern != null &&
3012                    equals(posPrefixPattern, other.posPrefixPattern))
3013            && (posSuffixPattern != null &&
3014                    equals(posSuffixPattern, other.posSuffixPattern))
3015            && (negPrefixPattern != null &&
3016                    equals(negPrefixPattern, other.negPrefixPattern))
3017            && (negSuffixPattern != null &&
3018                    equals(negSuffixPattern, other.negSuffixPattern))
3019            && multiplier == other.multiplier
3020            && groupingSize == other.groupingSize
3021            && groupingSize2 == other.groupingSize2
3022            && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
3023            && useExponentialNotation == other.useExponentialNotation
3024            && (!useExponentialNotation ||
3025                minExponentDigits == other.minExponentDigits)
3026            && useSignificantDigits == other.useSignificantDigits
3027            && (!useSignificantDigits ||
3028                minSignificantDigits == other.minSignificantDigits &&
3029                maxSignificantDigits == other.maxSignificantDigits)
3030            && symbols.equals(other.symbols);
3031    }
3032    //method to unquote the strings and compare
3033
private boolean equals(String JavaDoc pat1, String JavaDoc pat2){
3034        //fast path
3035
if(pat1.equals(pat2)){
3036            return true;
3037        }
3038        return unquote(pat1).equals(unquote(pat2));
3039    }
3040    private String JavaDoc unquote(String JavaDoc pat){
3041        StringBuffer JavaDoc buf = new StringBuffer JavaDoc(pat.length());
3042        int i=0;
3043        while(i<pat.length()){
3044            char ch = pat.charAt(i++);
3045            if(ch!=QUOTE){
3046                buf.append(ch);
3047            }
3048        }
3049        return buf.toString();
3050    }
3051// protected void handleToString(StringBuffer buf) {
3052
// buf.append("\nposPrefixPattern: '" + posPrefixPattern + "'\n");
3053
// buf.append("positivePrefix: '" + positivePrefix + "'\n");
3054
// buf.append("posSuffixPattern: '" + posSuffixPattern + "'\n");
3055
// buf.append("positiveSuffix: '" + positiveSuffix + "'\n");
3056
// buf.append("negPrefixPattern: '" + com.ibm.icu.impl.Utility.format1ForSource(negPrefixPattern) + "'\n");
3057
// buf.append("negativePrefix: '" + com.ibm.icu.impl.Utility.format1ForSource(negativePrefix) + "'\n");
3058
// buf.append("negSuffixPattern: '" + negSuffixPattern + "'\n");
3059
// buf.append("negativeSuffix: '" + negativeSuffix + "'\n");
3060
// buf.append("multiplier: '" + multiplier + "'\n");
3061
// buf.append("groupingSize: '" + groupingSize + "'\n");
3062
// buf.append("groupingSize2: '" + groupingSize2 + "'\n");
3063
// buf.append("decimalSeparatorAlwaysShown: '" + decimalSeparatorAlwaysShown + "'\n");
3064
// buf.append("useExponentialNotation: '" + useExponentialNotation + "'\n");
3065
// buf.append("minExponentDigits: '" + minExponentDigits + "'\n");
3066
// buf.append("useSignificantDigits: '" + useSignificantDigits + "'\n");
3067
// buf.append("minSignificantDigits: '" + minSignificantDigits + "'\n");
3068
// buf.append("maxSignificantDigits: '" + maxSignificantDigits + "'\n");
3069
// buf.append("symbols: '" + symbols + "'");
3070
// }
3071

3072    /**
3073     * Overrides hashCode
3074     * @stable ICU 2.0
3075     */

3076    public int hashCode() {
3077        return super.hashCode() * 37 + positivePrefix.hashCode();
3078        // just enough fields for a reasonable distribution
3079
}
3080
3081    /**
3082     * Synthesizes a pattern string that represents the current state
3083     * of this Format object.
3084     * @see #applyPattern
3085     * @stable ICU 2.0
3086     */

3087    public String JavaDoc toPattern() {
3088        return toPattern( false );
3089    }
3090
3091    /**
3092     * Synthesizes a localized pattern string that represents the current
3093     * state of this Format object.
3094     * @see #applyPattern
3095     * @stable ICU 2.0
3096     */

3097    public String JavaDoc toLocalizedPattern() {
3098        return toPattern( true );
3099    }
3100
3101    /**
3102     * Expand the affix pattern strings into the expanded affix strings. If any
3103     * affix pattern string is null, do not expand it. This method should be
3104     * called any time the symbols or the affix patterns change in order to keep
3105     * the expanded affix strings up to date.
3106     */

3107    //Bug 4212072 [Richard/GCL]
3108
private void expandAffixes() {
3109        // expandAffix() will set currencyChoice to a non-null value if
3110
// appropriate AND if it is null.
3111
currencyChoice = null;
3112
3113        // Reuse one StringBuffer for better performance
3114
StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
3115        if (posPrefixPattern != null) {
3116            expandAffix(posPrefixPattern, buffer, false);
3117            positivePrefix = buffer.toString();
3118        }
3119        if (posSuffixPattern != null) {
3120            expandAffix(posSuffixPattern, buffer, false);
3121            positiveSuffix = buffer.toString();
3122        }
3123        if (negPrefixPattern != null) {
3124            expandAffix(negPrefixPattern, buffer, false);
3125            negativePrefix = buffer.toString();
3126        }
3127        if (negSuffixPattern != null) {
3128            expandAffix(negSuffixPattern, buffer, false);
3129            negativeSuffix = buffer.toString();
3130        }
3131    }
3132
3133    /**
3134     * Expand an affix pattern into an affix string. All characters in
3135     * the pattern are literal unless bracketed by QUOTEs. The
3136     * following characters outside QUOTE are recognized:
3137     * PATTERN_PERCENT, PATTERN_PER_MILLE, PATTERN_MINUS, and
3138     * CURRENCY_SIGN. If CURRENCY_SIGN is doubled, it is interpreted as
3139     * an international currency sign. Any other character outside
3140     * QUOTE represents itself. Quoted text must be well-formed.
3141     *
3142     * This method is used in two distinct ways. First, it is used to expand
3143     * the stored affix patterns into actual affixes. For this usage, doFormat
3144     * must be false. Second, it is used to expand the stored affix patterns
3145     * given a specific number (doFormat == true), for those rare cases in
3146     * which a currency format references a ChoiceFormat (e.g., en_IN display
3147     * name for INR). The number itself is taken from digitList.
3148     *
3149     * When used in the first way, this method has a side effect: It sets
3150     * currencyChoice to a ChoiceFormat object, if the currency's display name
3151     * in this locale is a ChoiceFormat pattern (very rare). It only does this
3152     * if currencyChoice is null to start with.
3153     *
3154     * @param pattern the non-null, possibly empty pattern
3155     * @param buffer a scratch StringBuffer; its contents will be lost
3156     * @param doFormat if false, then the pattern will be expanded, and if a
3157     * currency symbol is encountered that expands to a ChoiceFormat, the
3158     * currencyChoice member variable will be initialized if it is null. If
3159     * doFormat is true, then it is assumed that the currencyChoice has been
3160     * created, and it will be used to format the value in digitList.
3161     * @return the expanded equivalent of pattern
3162     */

3163    //Bug 4212072 [Richard/GCL]
3164
private void expandAffix(String JavaDoc pattern, StringBuffer JavaDoc buffer,
3165                             boolean doFormat) {
3166        buffer.setLength(0);
3167        for (int i=0; i<pattern.length(); ) {
3168            char c = pattern.charAt(i++);
3169            if (c == QUOTE) {
3170                for (;;) {
3171                    int j = pattern.indexOf(QUOTE, i);
3172                    if (j == i) {
3173                        buffer.append(QUOTE);
3174                        i = j+1;
3175                        break;
3176                    } else if (j > i) {
3177                        buffer.append(pattern.substring(i, j));
3178                        i = j+1;
3179                        if (i<pattern.length() &&
3180                            pattern.charAt(i)==QUOTE) {
3181                            buffer.append(QUOTE);
3182                            ++i;
3183                            // loop again
3184
} else {
3185                            break;
3186                        }
3187                    } else {
3188                        // Unterminated quote; should be caught by apply
3189
// pattern.
3190
throw new RuntimeException JavaDoc();
3191                    }
3192                }
3193                continue;
3194            }
3195
3196            switch (c) {
3197            case CURRENCY_SIGN:
3198                // As of ICU 2.2 we use the currency object, and
3199
// ignore the currency symbols in the DFS, unless
3200
// we have a null currency object. This occurs if
3201
// resurrecting a pre-2.2 object or if the user
3202
// sets a custom DFS.
3203
boolean intl = i<pattern.length() &&
3204                    pattern.charAt(i) == CURRENCY_SIGN;
3205                if (intl) {
3206                    ++i;
3207                }
3208                String JavaDoc s = null;
3209                Currency currency = getCurrency();
3210                if (currency != null) {
3211                    if (!intl) {
3212                        boolean isChoiceFormat[] = new boolean[1];
3213                        s = currency.getName(symbols.getULocale(),
3214                                             Currency.SYMBOL_NAME,
3215                                             isChoiceFormat);
3216                        if (isChoiceFormat[0]) {
3217                            // Two modes here: If doFormat is false, we set up
3218
// currencyChoice. If doFormat is true, we use the
3219
// previously created currencyChoice to format the
3220
// value in digitList.
3221
if (!doFormat) {
3222                                // If the currency is handled by a ChoiceFormat,
3223
// then we're not going to use the expanded
3224
// patterns. Instantiate the ChoiceFormat and
3225
// return.
3226
if (currencyChoice == null) {
3227                                    currencyChoice = new ChoiceFormat JavaDoc(s);
3228                                }
3229                                // We could almost return null or "" here, since the
3230
// expanded affixes are almost not used at all
3231
// in this situation. However, one method --
3232
// toPattern() -- still does use the expanded
3233
// affixes, in order to set up a padding
3234
// pattern. We use the CURRENCY_SIGN as a
3235
// placeholder.
3236
s = String.valueOf(CURRENCY_SIGN);
3237                            } else {
3238                                FieldPosition JavaDoc pos = new FieldPosition JavaDoc(0); // ignored
3239
currencyChoice.format(digitList.getDouble(), buffer, pos);
3240                                continue;
3241                            }
3242                        }
3243                    } else {
3244                        s = currency.getCurrencyCode();
3245                    }
3246                } else {
3247                    s = intl ? symbols.getInternationalCurrencySymbol()
3248                        : symbols.getCurrencySymbol();
3249                }
3250                buffer.append(s);
3251                continue;
3252            case PATTERN_PERCENT:
3253                c = symbols.getPercent();
3254                break;
3255            case PATTERN_PER_MILLE:
3256                c = symbols.getPerMill();
3257                break;
3258            case PATTERN_MINUS:
3259                c = symbols.getMinusSign();
3260                break;
3261            }
3262            buffer.append(c);
3263        }
3264    }
3265
3266    /**
3267     * Append an affix to the given StringBuffer.
3268     * @param buf buffer to append to
3269     * @param isNegative
3270     * @param isPrefix
3271     */

3272    private int appendAffix(StringBuffer JavaDoc buf, boolean isNegative,
3273            boolean isPrefix, boolean parseAttr) {
3274        if (currencyChoice != null) {
3275            String JavaDoc affixPat = null;
3276            if (isPrefix) {
3277                affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
3278            } else {
3279                affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
3280            }
3281            StringBuffer JavaDoc affixBuf = new StringBuffer JavaDoc();
3282            expandAffix(affixPat, affixBuf, true);
3283            buf.append(affixBuf.toString());
3284            return affixBuf.length();
3285        }
3286
3287        String JavaDoc affix = null;
3288        if (isPrefix) {
3289            affix = isNegative ? negativePrefix : positivePrefix;
3290        } else {
3291            affix = isNegative ? negativeSuffix : positiveSuffix;
3292        }
3293//#ifndef FOUNDATION
3294
//## // [Spark/CDL] Invoke formatAffix2Attribute to add attributes for affix
3295
//## if (parseAttr) {
3296
//## int offset = affix.indexOf(symbols.getCurrencySymbol());
3297
//## if (-1 == offset) {
3298
//## offset = affix.indexOf(symbols.getPercent());
3299
//## if(-1 == offset) {
3300
//## offset = 0;
3301
//## }
3302
//## }
3303
//## formatAffix2Attribute(affix, buf.length() + offset, buf.length()
3304
//## + affix.length());
3305
//## }
3306
//#endif
3307
buf.append(affix);
3308        return affix.length();
3309    }
3310
3311//#ifndef FOUNDATION
3312
//## /*
3313
//## * [Spark/CDL] This is a newly added method, used to add attributes for
3314
//## * prefix and suffix.
3315
//## */
3316
//## private void formatAffix2Attribute(String affix, int begin, int end) {
3317
//## // [Spark/CDL] It is the invoker's responsibility to ensure that, before
3318
//## // the invocation of
3319
//## // this method, attributes is not null.
3320
//## // if( attributes == null ) return;
3321
//## if (affix.indexOf(symbols.getCurrencySymbol()) > -1) {
3322
//## addAttribute(Field.CURRENCY, begin, end);
3323
//## } else if (affix.indexOf(symbols.getMinusSign()) > -1) {
3324
//## addAttribute(Field.SIGN, begin, end);
3325
//## } else if (affix.indexOf(symbols.getPercent()) > -1) {
3326
//## addAttribute(Field.PERCENT, begin, end);
3327
//## } else if (affix.indexOf(symbols.getPerMill()) > -1) {
3328
//## addAttribute(Field.PERMILLE, begin, end);
3329
//## }
3330
//## }
3331
//#endif
3332

3333//#ifndef FOUNDATION
3334
//## /*
3335
//## * [Spark/CDL] Use this method to add attribute.
3336
//## */
3337
//## private void addAttribute(Field field, int begin, int end) {
3338
//## FieldPosition pos = new FieldPosition(field);
3339
//## pos.setBeginIndex(begin);
3340
//## pos.setEndIndex(end);
3341
//## attributes.add(pos);
3342
//## }
3343
//#endif
3344

3345//#ifndef FOUNDATION
3346
//## /**
3347
//## * Format the object to an attributed string, and return the corresponding iterator
3348
//## * Overrides superclass method.
3349
//## * @stable ICU 3.6
3350
//## */
3351
//## // [Spark/CDL]
3352
//## public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
3353
//## if (!(obj instanceof Number))
3354
//## throw new IllegalArgumentException();
3355
//## Number number = (Number) obj;
3356
//## StringBuffer text = null;
3357
//## attributes.clear();
3358
//## if (obj instanceof BigInteger) {
3359
//## text = format((BigInteger) number, new StringBuffer(),
3360
//## new FieldPosition(0), true);
3361
//## } else if (obj instanceof java.math.BigDecimal) {
3362
//## text = format((java.math.BigDecimal) number, new StringBuffer(),
3363
//## new FieldPosition(0), true);
3364
//## } else if (obj instanceof Double) {
3365
//## text = format(number.doubleValue(), new StringBuffer(),
3366
//## new FieldPosition(0), true);
3367
//## } else if (obj instanceof Integer || obj instanceof Long) {
3368
//## text = format(number.longValue(), new StringBuffer(),
3369
//## new FieldPosition(0), true);
3370
//## }
3371
//##
3372
//## AttributedString as = new AttributedString(text.toString());
3373
//##
3374
//## // add NumberFormat field attributes to the AttributedString
3375
//## for (int i = 0; i < attributes.size(); i++) {
3376
//## FieldPosition pos = (FieldPosition) attributes.get(i);
3377
//## Format.Field attribute = pos.getFieldAttribute();
3378
//## as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos
3379
//## .getEndIndex());
3380
//## }
3381
//##
3382
//## // return the CharacterIterator from AttributedString
3383
//## return as.getIterator();
3384
//## }
3385
//#endif
3386
/**
3387     * Append an affix pattern to the given StringBuffer. Localize unquoted
3388     * specials.
3389     */

3390    private void appendAffixPattern(StringBuffer JavaDoc buffer,
3391                                    boolean isNegative, boolean isPrefix,
3392                                    boolean localized) {
3393        String JavaDoc affixPat = null;
3394        if (isPrefix) {
3395            affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
3396        } else {
3397            affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
3398        }
3399
3400        // When there is a null affix pattern, we use the affix itself.
3401
if (affixPat == null) {
3402            String JavaDoc affix = null;
3403            if (isPrefix) {
3404                affix = isNegative ? negativePrefix : positivePrefix;
3405            } else {
3406                affix = isNegative ? negativeSuffix : positiveSuffix;
3407            }
3408            // Do this crudely for now: Wrap everything in quotes.
3409
buffer.append(QUOTE);
3410            for (int i=0; i<affix.length(); ++i) {
3411                char ch = affix.charAt(i);
3412                if (ch == QUOTE) {
3413                    buffer.append(ch);
3414                }
3415                buffer.append(ch);
3416            }
3417            buffer.append(QUOTE);
3418            return;
3419        }
3420
3421        if (!localized) {
3422            buffer.append(affixPat);
3423        } else {
3424            int i, j;
3425            for (i=0; i<affixPat.length(); ++i) {
3426                char ch = affixPat.charAt(i);
3427                switch (ch) {
3428                case QUOTE:
3429                    j = affixPat.indexOf(QUOTE, i+1);
3430                    if (j < 0) {
3431                        throw new IllegalArgumentException JavaDoc("Malformed affix pattern: " + affixPat);
3432                    }
3433                    buffer.append(affixPat.substring(i, j+1));
3434                    i = j;
3435                    continue;
3436                case PATTERN_PER_MILLE:
3437                    ch = symbols.getPerMill();
3438                    break;
3439                case PATTERN_PERCENT:
3440                    ch = symbols.getPercent();
3441                    break;
3442                case PATTERN_MINUS:
3443                    ch = symbols.getMinusSign();
3444                    break;
3445                }
3446                //check if char is same as any other symbol
3447
if(ch==symbols.getDecimalSeparator() ||
3448                   ch==symbols.getGroupingSeparator() ){
3449                    buffer.append(QUOTE);
3450                    buffer.append(ch);
3451                    buffer.append(QUOTE);
3452                }else{
3453                    buffer.append(ch);
3454                }
3455            }
3456        }
3457    }
3458
3459    /**
3460     * <strong><font face=helvetica color=red>CHANGED</font></strong>
3461     * Does the real work of generating a pattern.
3462     */

3463    private String JavaDoc toPattern(boolean localized) {
3464        StringBuffer JavaDoc result = new StringBuffer JavaDoc();
3465        char zero = localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT;
3466        char digit = localized ? symbols.getDigit() : PATTERN_DIGIT;
3467        char sigDigit = 0;
3468        boolean useSigDig = areSignificantDigitsUsed();
3469        if (useSigDig) {
3470            sigDigit = localized ? symbols.getSignificantDigit() : PATTERN_SIGNIFICANT_DIGIT;
3471        }
3472        char group = localized ? symbols.getGroupingSeparator()
3473                               : PATTERN_GROUPING_SEPARATOR;
3474        int i;
3475        int roundingDecimalPos = 0; // Pos of decimal in roundingDigits
3476
String JavaDoc roundingDigits = null;
3477        int padPos = (formatWidth > 0) ? padPosition : -1;
3478        String JavaDoc padSpec = (formatWidth > 0)
3479            ? new StringBuffer JavaDoc(2).
3480                append(localized ? symbols.getPadEscape() : PATTERN_PAD_ESCAPE).
3481                append(pad).toString()
3482            : null;
3483        if (roundingIncrementICU != null) {
3484            i = roundingIncrementICU.scale();
3485            roundingDigits = roundingIncrementICU.movePointRight(i).toString();
3486            roundingDecimalPos = roundingDigits.length() - i;
3487        }
3488        for (int part=0; part<2; ++part) {
3489            // variable not used int partStart = result.length();
3490
if (padPos == PAD_BEFORE_PREFIX) {
3491                result.append(padSpec);
3492            }
3493            /* Use original symbols read from resources in pattern
3494             * eg. use "" instead of "$" in Locale.US [Richard/GCL]
3495             */

3496            appendAffixPattern(result, part!=0, true, localized);
3497            if (padPos == PAD_AFTER_PREFIX) {
3498                result.append(padSpec);
3499            }
3500            int sub0Start = result.length();
3501            int g = isGroupingUsed() ? Math.max(0, groupingSize) : 0;
3502            if (g > 0 && groupingSize2 > 0 && groupingSize2 != groupingSize) {
3503                g += groupingSize2;
3504            }
3505            int maxDig = 0, minDig = 0, maxSigDig = 0;
3506            if (useSigDig) {
3507                minDig = getMinimumSignificantDigits();
3508                maxDig = maxSigDig = getMaximumSignificantDigits();
3509            } else {
3510                minDig = getMinimumIntegerDigits();
3511                maxDig = getMaximumIntegerDigits();
3512            }
3513            if (useExponentialNotation) {
3514                if (maxDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
3515                    maxDig = 1;
3516                }
3517            } else if (useSigDig) {
3518                maxDig = Math.max(maxDig, g+1);
3519            } else {
3520                maxDig = Math.max(Math.max(g, getMinimumIntegerDigits()),
3521                                  roundingDecimalPos) + 1;
3522            }
3523            for (i = maxDig; i > 0; --i) {
3524                if (!useExponentialNotation && i<maxDig &&
3525                    isGroupingPosition(i)) {
3526                    result.append(group);
3527                }
3528                if (useSigDig) {
3529                    // #@,@### (maxSigDig == 5, minSigDig == 2)
3530
// 65 4321 (1-based pos, count from the right)
3531
// Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig)
3532
// Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
3533
result.append((maxSigDig >= i && i > (maxSigDig - minDig)) ? sigDigit : digit);
3534                } else {
3535                    if (roundingDigits != null) {
3536                        int pos = roundingDecimalPos - i;
3537                        if (pos >= 0 && pos < roundingDigits.length()) {
3538                            result.append((char) (roundingDigits.charAt(pos) - '0' + zero));
3539                            continue;
3540                        }
3541                    }
3542                    result.append(i<=minDig ? zero : digit);
3543                }
3544            }
3545            if (!useSigDig) {
3546                if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) {
3547                    result.append(localized ? symbols.getDecimalSeparator() :
3548                                  PATTERN_DECIMAL_SEPARATOR);
3549                }
3550                int pos = roundingDecimalPos;
3551                for (i = 0; i < getMaximumFractionDigits(); ++i) {
3552                    if (roundingDigits != null &&
3553                        pos < roundingDigits.length()) {
3554                        result.append(pos < 0 ? zero :
3555                                      (char) (roundingDigits.charAt(pos) - '0' + zero));
3556                        ++pos;
3557                        continue;
3558                    }
3559                    result.append(i<getMinimumFractionDigits() ? zero : digit);
3560                }
3561            }
3562            if (useExponentialNotation) {
3563                if(localized ){
3564                    result.append(symbols.getExponentSeparator() );
3565                }else{
3566                    result.append(PATTERN_EXPONENT);
3567                }
3568                if (exponentSignAlwaysShown) {
3569                    result.append(localized ? symbols.getPlusSign() :
3570                                  PATTERN_PLUS_SIGN);
3571                }
3572                for (i=0; i<minExponentDigits; ++i) {
3573                    result.append(zero);
3574                }
3575            }
3576            if (padSpec != null && !useExponentialNotation) {
3577                int add = formatWidth - result.length() + sub0Start
3578                    - ((part == 0)
3579                       ? positivePrefix.length() + positiveSuffix.length()
3580                       : negativePrefix.length() + negativeSuffix.length());
3581                while (add > 0) {
3582                    result.insert(sub0Start, digit);
3583                    ++maxDig;
3584                    --add;
3585                    // Only add a grouping separator if we have at least
3586
// 2 additional characters to be added, so we don't
3587
// end up with ",###".
3588
if (add>1 && isGroupingPosition(maxDig)) {
3589                        result.insert(sub0Start, group);
3590                        --add;
3591                    }
3592                }
3593            }
3594            if (padPos == PAD_BEFORE_SUFFIX) {
3595                result.append(padSpec);
3596            }
3597            /* Use original symbols read from resources in pattern
3598             * eg. use "" instead of "$" in Locale.US [Richard/GCL]
3599             */

3600            appendAffixPattern(result, part!=0, false, localized);
3601            if (padPos == PAD_AFTER_SUFFIX) {
3602                result.append(padSpec);
3603            }
3604            if (part == 0) {
3605                if (negativeSuffix.equals(positiveSuffix) &&
3606                    negativePrefix.equals( PATTERN_MINUS + positivePrefix)) {
3607                    break;
3608                } else {
3609                    result.append(localized ? symbols.getPatternSeparator() :
3610                                  PATTERN_SEPARATOR);
3611                }
3612            }
3613        }
3614        return result.toString();
3615    }
3616
3617    /**
3618     * Apply the given pattern to this Format object. A pattern is a
3619     * short-hand specification for the various formatting properties.
3620     * These properties can also be changed individually through the
3621     * various setter methods.
3622     * <p>
3623     * There is no limit to integer digits are set
3624     * by this routine, since that is the typical end-user desire;
3625     * use setMaximumInteger if you want to set a real value.
3626     * For negative numbers, use a second pattern, separated by a semicolon
3627     * <P>Example "#,#00.0#" -> 1,234.56
3628     * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
3629     * a maximum of 2 fraction digits.
3630     * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parentheses.
3631     * <p>In negative patterns, the minimum and maximum counts are ignored;
3632     * these are presumed to be set in the positive pattern.
3633     * @stable ICU 2.0
3634     */

3635    public void applyPattern( String JavaDoc pattern ) {
3636        applyPattern( pattern, false );
3637    }
3638
3639    /**
3640     * Apply the given pattern to this Format object. The pattern
3641     * is assumed to be in a localized notation. A pattern is a
3642     * short-hand specification for the various formatting properties.
3643     * These properties can also be changed individually through the
3644     * various setter methods.
3645     * <p>
3646     * There is no limit to integer digits are set
3647     * by this routine, since that is the typical end-user desire;
3648     * use setMaximumInteger if you want to set a real value.
3649     * For negative numbers, use a second pattern, separated by a semicolon
3650     * <P>Example "#,#00.0#" -> 1,234.56
3651     * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
3652     * a maximum of 2 fraction digits.
3653     * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses.
3654     * <p>In negative patterns, the minimum and maximum counts are ignored;
3655     * these are presumed to be set in the positive pattern.
3656     * @stable ICU 2.0
3657     */

3658    public void applyLocalizedPattern( String JavaDoc pattern ) {
3659        applyPattern( pattern, true );
3660    }
3661
3662    /**
3663     * <strong><font face=helvetica color=red>CHANGED</font></strong>
3664     * Does the real work of applying a pattern.
3665     */

3666    private void applyPattern(String JavaDoc pattern, boolean localized) {
3667        char zeroDigit = PATTERN_ZERO_DIGIT; // '0'
3668
char sigDigit = PATTERN_SIGNIFICANT_DIGIT; // '@'
3669
char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
3670        char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;
3671        char percent = PATTERN_PERCENT;
3672        char perMill = PATTERN_PER_MILLE;
3673        char digit = PATTERN_DIGIT; // '#'
3674
char separator = PATTERN_SEPARATOR;
3675        String JavaDoc exponent = String.valueOf(PATTERN_EXPONENT);
3676        char plus = PATTERN_PLUS_SIGN;
3677        char padEscape = PATTERN_PAD_ESCAPE;
3678        char minus = PATTERN_MINUS; //Bug 4212072 [Richard/GCL]
3679
if (localized) {
3680            zeroDigit = symbols.getZeroDigit();
3681            sigDigit = symbols.getSignificantDigit();
3682            groupingSeparator = symbols.getGroupingSeparator();
3683            decimalSeparator = symbols.getDecimalSeparator();
3684            percent = symbols.getPercent();
3685            perMill = symbols.getPerMill();
3686            digit = symbols.getDigit();
3687            separator = symbols.getPatternSeparator();
3688            exponent = symbols.getExponentSeparator();
3689            plus = symbols.getPlusSign();
3690            padEscape = symbols.getPadEscape();
3691            minus = symbols.getMinusSign(); //Bug 4212072 [Richard/GCL]
3692
}
3693        char nineDigit = (char) (zeroDigit + 9);
3694
3695        boolean gotNegative = false;
3696
3697        int pos = 0;
3698        // Part 0 is the positive pattern. Part 1, if present, is the negative
3699
// pattern.
3700
for (int part=0; part<2 && pos<pattern.length(); ++part) {
3701            // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix,
3702
// 2=suffix, 3=prefix in quote, 4=suffix in quote. Subpart 0 is
3703
// between the prefix and suffix, and consists of pattern
3704
// characters. In the prefix and suffix, percent, permille, and
3705
// currency symbols are recognized and translated.
3706
int subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;
3707
3708            // It's important that we don't change any fields of this object
3709
// prematurely. We set the following variables for the multiplier,
3710
// grouping, etc., and then only change the actual object fields if
3711
// everything parses correctly. This also lets us register
3712
// the data from part 0 and ignore the part 1, except for the
3713
// prefix and suffix.
3714
StringBuffer JavaDoc prefix = new StringBuffer JavaDoc();
3715            StringBuffer JavaDoc suffix = new StringBuffer JavaDoc();
3716            int decimalPos = -1;
3717            int multiplier = 1;
3718            int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;
3719            byte groupingCount = -1;
3720            byte groupingCount2 = -1;
3721            int padPos = -1;
3722            char padChar = 0;
3723            int incrementPos = -1;
3724            long incrementVal = 0;
3725            byte expDigits = -1;
3726            boolean expSignAlways = false;
3727            boolean isCurrency = false;
3728
3729            // The affix is either the prefix or the suffix.
3730
StringBuffer JavaDoc affix = prefix;
3731
3732            int start = pos;
3733
3734        PARTLOOP:
3735            for (; pos < pattern.length(); ++pos) {
3736                char ch = pattern.charAt(pos);
3737                switch (subpart) {
3738                case 0: // Pattern proper subpart (between prefix & suffix)
3739
// Process the digits, decimal, and grouping characters. We
3740
// record five pieces of information. We expect the digits
3741
// to occur in the pattern ####00.00####, and we record the
3742
// number of left digits, zero (central) digits, and right
3743
// digits. The position of the last grouping character is
3744
// recorded (should be somewhere within the first two blocks
3745
// of characters), as is the position of the decimal point,
3746
// if any (should be in the zero digits). If there is no
3747
// decimal point, then there should be no right digits.
3748
if (ch == digit) {
3749                        if (zeroDigitCount > 0 || sigDigitCount > 0) {
3750                            ++digitRightCount;
3751                        } else {
3752                            ++digitLeftCount;
3753                        }
3754                        if (groupingCount >= 0 && decimalPos < 0) {
3755                            ++groupingCount;
3756                        }
3757                    } else if ((ch >= zeroDigit && ch <= nineDigit) ||
3758                               ch == sigDigit) {
3759                        if (digitRightCount > 0) {
3760                            patternError("Unexpected '" + ch + '\'', pattern);
3761                        }
3762                        if (ch == sigDigit) {
3763                            ++sigDigitCount;
3764                        } else {
3765                            ++zeroDigitCount;
3766                            if (ch != zeroDigit) {
3767                                int p = digitLeftCount + zeroDigitCount
3768                                    + digitRightCount;
3769                                if (incrementPos >= 0) {
3770                                    while (incrementPos < p) {
3771                                        incrementVal *= 10;
3772                                        ++incrementPos;
3773                                    }
3774                                } else {
3775                                    incrementPos = p;
3776                                }
3777                                incrementVal += ch - zeroDigit;
3778                            }
3779                        }
3780                        if (groupingCount >= 0 && decimalPos < 0) {
3781                            ++groupingCount;
3782                        }
3783                    } else if (ch == groupingSeparator) {
3784                        /*Bug 4212072
3785                          process the Localized pattern like "'Fr. '#'##0.05;'Fr.-'#'##0.05"
3786                          (Locale="CH", groupingSeparator == QUOTE)
3787                          [Richard/GCL]
3788                        */

3789                        if (ch == QUOTE && (pos+1) < pattern.length()) {
3790                            char after = pattern.charAt(pos+1);
3791                            if (!(after == digit || (after >= zeroDigit && after <= nineDigit))) {
3792                                // A quote outside quotes indicates either the opening
3793
// quote or two quotes, which is a quote literal. That is,
3794
// we have the first quote in 'do' or o''clock.
3795
if (after == QUOTE) {
3796                                    ++pos;
3797                                    // Fall through to append(ch)
3798
} else {
3799                                    if (groupingCount < 0) {
3800                                        subpart = 3; // quoted prefix subpart
3801
} else {
3802                                      // Transition to suffix subpart
3803
subpart = 2; // suffix subpart
3804
affix = suffix;
3805                                      sub0Limit = pos--;
3806                                    }
3807                                    continue;
3808                                }
3809                            }
3810                        }
3811                        
3812                        if (decimalPos >= 0) {
3813                            patternError("Grouping separator after decimal", pattern);
3814                        }
3815                        groupingCount2 = groupingCount;
3816                        groupingCount = 0;
3817                    } else if (ch == decimalSeparator) {
3818                        if (decimalPos >= 0) {
3819                            patternError("Multiple decimal separators", pattern);
3820                        }
3821                        // Intentionally incorporate the digitRightCount,
3822
// even though it is illegal for this to be > 0
3823
// at this point. We check pattern syntax below.
3824
decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
3825                    } else {
3826                        if (pattern.regionMatches(pos, exponent, 0, exponent.length())) {
3827                            if (expDigits >= 0) {
3828                                patternError("Multiple exponential symbols", pattern);
3829                            }
3830                            if (groupingCount >= 0) {
3831                                patternError("Grouping separator in exponential", pattern);
3832                            }
3833                            pos += exponent.length();
3834                            // Check for positive prefix
3835
if (pos < pattern.length()
3836                                && pattern.charAt(pos) == plus) {
3837                                expSignAlways = true;
3838                                ++pos;
3839                            }
3840                            // Use lookahead to parse out the exponential part of the
3841
// pattern, then jump into suffix subpart.
3842
expDigits = 0;
3843                            while (pos < pattern.length() &&
3844                                   pattern.charAt(pos) == zeroDigit) {
3845                                ++expDigits;
3846                                ++pos;
3847                            }
3848                            
3849                            // 1. Require at least one mantissa pattern digit
3850
// 2. Disallow "#+ @" in mantissa
3851
// 3. Require at least one exponent pattern digit
3852
if (((digitLeftCount + zeroDigitCount) < 1 &&
3853                                 (sigDigitCount + digitRightCount) < 1) ||
3854                                (sigDigitCount > 0 && digitLeftCount > 0) ||
3855                                expDigits < 1) {
3856                                patternError("Malformed exponential", pattern);
3857                            }
3858                        }
3859                        // Transition to suffix subpart
3860
subpart = 2; // suffix subpart
3861
affix = suffix;
3862                        sub0Limit = pos--; // backup: for() will increment
3863
continue;
3864                    }
3865                    break;
3866                case 1: // Prefix subpart
3867
case 2: // Suffix subpart
3868
// Process the prefix / suffix characters
3869
// Process unquoted characters seen in prefix or suffix
3870
// subpart.
3871

3872                    // Several syntax characters implicitly begins the
3873
// next subpart if we are in the prefix; otherwise
3874
// they are illegal if unquoted.
3875
if (ch == digit ||
3876                        ch == groupingSeparator ||
3877                        ch == decimalSeparator ||
3878                        (ch >= zeroDigit && ch <= nineDigit) ||
3879                        ch == sigDigit) {
3880                        // Any of these characters implicitly begins the
3881
// next subpart if we are in the prefix
3882
if (subpart == 1) { // prefix subpart
3883
subpart = 0; // pattern proper subpart
3884
sub0Start = pos--; // Reprocess this character
3885
continue;
3886                        } else if (ch == QUOTE) {
3887                            /*Bug 4212072
3888                              process the Localized pattern like "'Fr. '#'##0.05;'Fr.-'#'##0.05"
3889                              (Locale="CH", groupingSeparator == QUOTE)
3890                              [Richard/GCL]
3891                            */

3892                            // A quote outside quotes indicates either the opening
3893
// quote or two quotes, which is a quote literal. That is,
3894
// we have the first quote in 'do' or o''clock.
3895
if ((pos+1) < pattern.length() &&
3896                                pattern.charAt(pos+1) == QUOTE) {
3897                                ++pos;
3898                                affix.append(ch);
3899                            } else {
3900                                subpart += 2; // open quote
3901
}
3902                            continue;
3903                        }
3904                        patternError("Unquoted special character '" + ch + '\'', pattern);
3905                    } else if (ch == CURRENCY_SIGN) {
3906                        // Use lookahead to determine if the currency sign is
3907
// doubled or not.
3908
boolean doubled = (pos + 1) < pattern.length() &&
3909                            pattern.charAt(pos + 1) == CURRENCY_SIGN;
3910                        /*Bug 4212072
3911                         To meet the need of expandAffix(String, StirngBuffer)
3912                         [Richard/GCL]
3913                        */

3914                        if (doubled) {
3915                            ++pos; // Skip over the doubled character
3916
affix.append(ch); // append two: one here, one below
3917
}
3918                        isCurrency = true;
3919                        // Fall through to append(ch)
3920
} else if (ch == QUOTE) {
3921                        // A quote outside quotes indicates either the opening
3922
// quote or two quotes, which is a quote literal. That is,
3923
// we have the first quote in 'do' or o''clock.
3924
if((pos+1) < pattern.length()&&
3925                            pattern.charAt(pos+1)==QUOTE){
3926                            ++pos;
3927                            affix.append(ch); // append two: one here, one below
3928
}else{
3929                            subpart += 2; // open quote
3930
}
3931                        // Fall through to append(ch)
3932
} else if (ch == separator) {
3933                        // Don't allow separators in the prefix, and don't allow
3934
// separators in the second pattern (part == 1).
3935
if (subpart == 1 || part == 1) {
3936                            patternError("Unquoted special character '" + ch + '\'', pattern);
3937                        }
3938                        sub2Limit = pos++;
3939                        break PARTLOOP; // Go to next part
3940
} else if (ch == percent || ch == perMill) {
3941                        // Next handle characters which are appended directly.
3942
if (multiplier != 1) {
3943                            patternError("Too many percent/permille characters", pattern);
3944                        }
3945                        multiplier = (ch == percent) ? 100 : 1000;
3946                        // Convert to non-localized pattern
3947
ch = (ch == percent) ? PATTERN_PERCENT : PATTERN_PER_MILLE;
3948                        // Fall through to append(ch)
3949
} else if (ch == minus) {
3950                        // Convert to non-localized pattern
3951
ch = PATTERN_MINUS;
3952                        // Fall through to append(ch)
3953
} else if (ch == padEscape) {
3954                        if (padPos >= 0) {
3955                            patternError("Multiple pad specifiers", pattern);
3956                        }
3957                        if ((pos+1) == pattern.length()) {
3958                            patternError("Invalid pad specifier", pattern);
3959                        }
3960                        padPos = pos++; // Advance past pad char
3961
padChar = pattern.charAt(pos);
3962                        continue;
3963                    }
3964                    affix.append(ch);
3965                    break;
3966                case 3: // Prefix subpart, in quote
3967
case 4: // Suffix subpart, in quote
3968
// A quote within quotes indicates either the closing
3969
// quote or two quotes, which is a quote literal. That is,
3970
// we have the second quote in 'do' or 'don''t'.
3971
if (ch == QUOTE) {
3972                        if ((pos+1) < pattern.length() &&
3973                            pattern.charAt(pos+1) == QUOTE) {
3974                            ++pos;
3975                            affix.append(ch);
3976                        } else {
3977                            subpart -= 2; // close quote
3978
}
3979                        // Fall through to append(ch)
3980
}
3981                    // NOTE: In ICU 2.2 there was code here to parse quoted
3982
// percent and permille characters _within quotes_ and give
3983
// them special meaning. This is incorrect, since quoted
3984
// characters are literals without special meaning.
3985
affix.append(ch);
3986                    break;
3987                }
3988            }
3989            
3990            if (subpart == 3 || subpart == 4) {
3991                patternError("Unterminated quote", pattern);
3992            }
3993
3994            if (sub0Limit == 0) {
3995                sub0Limit = pattern.length();
3996            }
3997
3998            if (sub2Limit == 0) {
3999                sub2Limit = pattern.length();
4000            }
4001
4002            /* Handle patterns with no '0' pattern character. These patterns
4003             * are legal, but must be recodified to make sense. "##.###" ->
4004             * "#0.###". ".###" -> ".0##".
4005             *
4006             * We allow patterns of the form "####" to produce a zeroDigitCount
4007             * of zero (got that?); although this seems like it might make it
4008             * possible for format() to produce empty strings, format() checks
4009             * for this condition and outputs a zero digit in this situation.
4010             * Having a zeroDigitCount of zero yields a minimum integer digits
4011             * of zero, which allows proper round-trip patterns. We don't want
4012             * "#" to become "#0" when toPattern() is called (even though that's
4013             * what it really is, semantically).
4014             */

4015            if (zeroDigitCount == 0 && sigDigitCount == 0 &&
4016                digitLeftCount > 0 && decimalPos >= 0) {
4017                // Handle "###.###" and "###." and ".###"
4018
int n = decimalPos;
4019                if (n == 0) ++n; // Handle ".###"
4020
digitRightCount = digitLeftCount - n;
4021                digitLeftCount = n - 1;
4022                zeroDigitCount = 1;
4023            }
4024
4025            // Do syntax checking on the digits, decimal points, and quotes.
4026
if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) ||
4027                (decimalPos >= 0 &&
4028                 (sigDigitCount > 0 ||
4029                  decimalPos < digitLeftCount ||
4030                  decimalPos > (digitLeftCount + zeroDigitCount))) ||
4031                groupingCount == 0 || groupingCount2 == 0 ||
4032                (sigDigitCount > 0 && zeroDigitCount > 0) ||
4033                subpart > 2) { // subpart > 2 == unmatched quote
4034
patternError("Malformed pattern", pattern);
4035            }
4036
4037            // Make sure pad is at legal position before or after affix.
4038
if (padPos >= 0) {
4039                if (padPos == start) {
4040                    padPos = PAD_BEFORE_PREFIX;
4041                } else if (padPos+2 == sub0Start) {
4042                    padPos = PAD_AFTER_PREFIX;
4043                } else if (padPos == sub0Limit) {
4044                    padPos = PAD_BEFORE_SUFFIX;
4045                } else if (padPos+2 == sub2Limit) {
4046                    padPos = PAD_AFTER_SUFFIX;
4047                } else {
4048                    patternError("Illegal pad position", pattern);
4049                }
4050            }
4051
4052            if (part == 0) {
4053                // Set negative affixes temporarily to match the positive
4054
// affixes. Fix this up later after processing both parts.
4055
/*Bug 4212072
4056                  To meet the need of expandAffix(String, StirngBuffer)
4057                  [Richard/GCL]
4058                */

4059                posPrefixPattern = negPrefixPattern = prefix.toString();
4060                posSuffixPattern = negSuffixPattern = suffix.toString();
4061
4062                useExponentialNotation = (expDigits >= 0);
4063                if (useExponentialNotation) {
4064                    minExponentDigits = expDigits;
4065                    exponentSignAlwaysShown = expSignAlways;
4066                }
4067                isCurrencyFormat = isCurrency;
4068                int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
4069                // The effectiveDecimalPos is the position the decimal is at or
4070
// would be at if there is no decimal. Note that if
4071
// decimalPos<0, then digitTotalCount == digitLeftCount +
4072
// zeroDigitCount.
4073
int effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;
4074                boolean useSigDig = (sigDigitCount > 0);
4075                setSignificantDigitsUsed(useSigDig);
4076                if (useSigDig) {
4077                    setMinimumSignificantDigits(sigDigitCount);
4078                    setMaximumSignificantDigits(sigDigitCount + digitRightCount);
4079                } else {
4080                    int minInt = effectiveDecimalPos - digitLeftCount;
4081                    setMinimumIntegerDigits(minInt);
4082                    /*Upper limit on integer and fraction digits for a Java double
4083                      [Richard/GCL]
4084                    */

4085                    setMaximumIntegerDigits(useExponentialNotation
4086                        ? digitLeftCount + minInt : DOUBLE_INTEGER_DIGITS);
4087                    setMaximumFractionDigits(decimalPos >= 0
4088                        ? (digitTotalCount - decimalPos) : 0);
4089                    setMinimumFractionDigits(decimalPos >= 0
4090                        ? (digitLeftCount + zeroDigitCount - decimalPos) : 0);
4091                }
4092                setGroupingUsed(groupingCount > 0);
4093                this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
4094                this.groupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount)
4095                    ? groupingCount2 : 0;
4096                this.multiplier = multiplier;
4097                setDecimalSeparatorAlwaysShown(decimalPos == 0
4098                        || decimalPos == digitTotalCount);
4099                if (padPos >= 0) {
4100                    padPosition = padPos;
4101                    formatWidth = sub0Limit - sub0Start; // to be fixed up below
4102
pad = padChar;
4103                } else {
4104                    formatWidth = 0;
4105                }
4106                if (incrementVal != 0) {
4107                    // BigDecimal scale cannot be negative (even though
4108
// this makes perfect sense), so we need to handle this.
4109
int scale = incrementPos - effectiveDecimalPos;
4110                    roundingIncrementICU =
4111                        BigDecimal.valueOf(incrementVal, scale > 0 ? scale : 0);
4112                    if (scale < 0) {
4113                        roundingIncrementICU =
4114                            roundingIncrementICU.movePointRight(-scale);
4115                    }
4116                    setRoundingDouble();
4117                    roundingMode = BigDecimal.ROUND_HALF_EVEN;
4118                } else {
4119                    setRoundingIncrement((BigDecimal)null);
4120                }
4121            } else {
4122                /*Bug 4212072
4123                  To meet the need of expandAffix(String, StirngBuffer)
4124                  [Richard/GCL]
4125                */

4126                negPrefixPattern = prefix.toString();
4127                negSuffixPattern = suffix.toString();
4128                gotNegative = true;
4129            }
4130        }
4131
4132        /*Bug 4140009
4133          Process the empty pattern
4134          [Richard/GCL]
4135        */

4136        if (pattern.length() == 0) {
4137            posPrefixPattern = posSuffixPattern = "";
4138            setMinimumIntegerDigits(0);
4139            setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
4140            setMinimumFractionDigits(0);
4141            setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
4142        }
4143        
4144        // If there was no negative pattern, or if the negative pattern is
4145
// identical to the positive pattern, then prepend the minus sign to the
4146
// positive pattern to form the negative pattern.
4147
/*Bug 4212072
4148          To meet the need of expandAffix(String, StirngBuffer)
4149          [Richard/GCL]
4150        */

4151        if (!gotNegative ||
4152            (negPrefixPattern.equals(posPrefixPattern)
4153             && negSuffixPattern.equals(posSuffixPattern))) {
4154            negSuffixPattern = posSuffixPattern;
4155            negPrefixPattern = PATTERN_MINUS + posPrefixPattern;
4156        }
4157        /*Bug 4212072
4158          Update the affix strings accroding to symbols in order to keep
4159          the affix strings up to date.
4160          [Richard/GCL]
4161        */

4162        expandAffixes();
4163
4164        // Now that we have the actual prefix and suffix, fix up formatWidth
4165
if (formatWidth > 0) {
4166            formatWidth += positivePrefix.length() + positiveSuffix.length();
4167        }
4168        
4169        setLocale(null, null);
4170    }
4171
4172    /**
4173     * Centralizes the setting of the roundingDouble and roundingDoubleReciprocal.
4174     */

4175    private void setRoundingDouble() {
4176        if (roundingIncrementICU == null) {
4177            roundingDouble = 0.0d;
4178            roundingDoubleReciprocal = 0.0d;
4179        } else {
4180            roundingDouble = roundingIncrementICU.doubleValue();
4181            setRoundingDoubleReciprocal(BigDecimal.ONE.divide(roundingIncrementICU,BigDecimal.ROUND_HALF_EVEN).doubleValue());
4182        }
4183    }
4184
4185    private void patternError(String JavaDoc msg, String JavaDoc pattern) {
4186        throw new IllegalArgumentException JavaDoc(msg + " in pattern \"" + pattern + '"');
4187    }
4188
4189    /*Rewrite the following 4 "set" methods
4190      Upper limit on integer and fraction digits for a Java double
4191      [Richard/GCL]
4192    */

4193    /**
4194     * Sets the maximum number of digits allowed in the integer portion of a
4195     * number. This override limits the integer digit count to 309.
4196     * @see NumberFormat#setMaximumIntegerDigits
4197     * @stable ICU 2.0
4198     */

4199    public void setMaximumIntegerDigits(int newValue) {
4200        super.setMaximumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
4201    }
4202
4203    /**
4204     * Sets the minimum number of digits allowed in the integer portion of a
4205     * number. This override limits the integer digit count to 309.
4206     * @see NumberFormat#setMinimumIntegerDigits
4207     * @stable ICU 2.0
4208     */

4209    public void setMinimumIntegerDigits(int newValue) {
4210        super.setMinimumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
4211    }
4212
4213    /**
4214     * Returns the minimum number of significant digits that will be
4215     * displayed. This value has no effect unless areSignificantDigitsUsed()
4216     * returns true.
4217     * @return the fewest significant digits that will be shown
4218     * @stable ICU 3.0
4219     */

4220    public int getMinimumSignificantDigits() {
4221        return minSignificantDigits;
4222    }
4223
4224    /**
4225     * Returns the maximum number of significant digits that will be
4226     * displayed. This value has no effect unless areSignificantDigitsUsed()
4227     * returns true.
4228     * @return the most significant digits that will be shown
4229     * @stable ICU 3.0
4230     */

4231    public int getMaximumSignificantDigits() {
4232        return maxSignificantDigits;
4233    }
4234
4235    /**
4236     * Sets the minimum number of significant digits that will be
4237     * displayed. If <code>min</code> is less than one then it is set
4238     * to one. If the maximum significant digits count is less than
4239     * <code>min</code>, then it is set to <code>min</code>. This
4240     * value has no effect unless areSignificantDigitsUsed() returns true.
4241     * @param min the fewest significant digits to be shown
4242     * @stable ICU 3.0
4243     */

4244    public void setMinimumSignificantDigits(int min) {
4245        if (min < 1) {
4246            min = 1;
4247        }
4248        // pin max sig dig to >= min
4249
int max = Math.max(maxSignificantDigits, min);
4250        minSignificantDigits = min;
4251        maxSignificantDigits = max;
4252    }
4253
4254    /**
4255     * Sets the maximum number of significant digits that will be
4256     * displayed. If <code>max</code> is less than one then it is set
4257     * to one. If the minimum significant digits count is greater
4258     * than <code>max</code>, then it is set to <code>max</code>. This
4259     * value has no effect unless areSignificantDigitsUsed() returns true.
4260     * @param max the most significant digits to be shown
4261     * @stable ICU 3.0
4262     */

4263    public void setMaximumSignificantDigits(int max) {
4264        if (max < 1) {
4265            max = 1;
4266        }
4267        // pin min sig dig to 1..max
4268
int min = Math.min(minSignificantDigits, max);
4269        minSignificantDigits = min;
4270        maxSignificantDigits = max;
4271    }
4272
4273    /**
4274     * Returns true if significant digits are in use or false if
4275     * integer and fraction digit counts are in use.
4276     * @return true if significant digits are in use
4277     * @stable ICU 3.0
4278     */

4279    public boolean areSignificantDigitsUsed() {
4280        return useSignificantDigits;
4281    }
4282
4283    /**
4284     * Sets whether significant digits are in use, or integer and
4285     * fraction digit counts are in use.
4286     * @param useSignificantDigits true to use significant digits, or
4287     * false to use integer and fraction digit counts
4288     * @stable ICU 3.0
4289     */

4290    public void setSignificantDigitsUsed(boolean useSignificantDigits) {
4291        this.useSignificantDigits = useSignificantDigits;
4292    }
4293
4294    /**
4295     * Sets the <tt>Currency</tt> object used to display currency
4296     * amounts. This takes effect immediately, if this format is a
4297     * currency format. If this format is not a currency format, then
4298     * the currency object is used if and when this object becomes a
4299     * currency format through the application of a new pattern.
4300     * @param theCurrency new currency object to use. Must not be
4301     * null.
4302     * @stable ICU 2.2
4303     */

4304    public void setCurrency(Currency theCurrency) {
4305        // If we are a currency format, then modify our affixes to
4306
// encode the currency symbol for the given currency in our
4307
// locale, and adjust the decimal digits and rounding for the
4308
// given currency.
4309

4310        super.setCurrency(theCurrency);
4311        if (theCurrency != null) {
4312            boolean[] isChoiceFormat = new boolean[1];
4313            String JavaDoc s = theCurrency.getName(symbols.getULocale(),
4314                    Currency.SYMBOL_NAME,
4315                    isChoiceFormat);
4316                symbols.setCurrencySymbol(s);
4317                symbols.setInternationalCurrencySymbol(theCurrency.getCurrencyCode());
4318        }
4319
4320        if (isCurrencyFormat) {
4321            if (theCurrency != null) {
4322                setRoundingIncrement(theCurrency.getRoundingIncrement());
4323                
4324                int d = theCurrency.getDefaultFractionDigits();
4325                setMinimumFractionDigits(d);
4326                setMaximumFractionDigits(d);
4327            }
4328            expandAffixes();
4329        }
4330    }
4331
4332    /**
4333     * Returns the currency in effect for this formatter. Subclasses
4334     * should override this method as needed. Unlike getCurrency(),
4335     * this method should never return null.
4336     * @internal
4337     * @deprecated This API is ICU internal only.
4338     */

4339    protected Currency getEffectiveCurrency() {
4340        Currency c = getCurrency();
4341        if (c == null) {
4342            c = Currency.getInstance(symbols.getInternationalCurrencySymbol());
4343        }
4344        return c;
4345    }
4346
4347    /**
4348     * Sets the maximum number of digits allowed in the fraction portion of a
4349     * number. This override limits the fraction digit count to 340.
4350     * @see NumberFormat#setMaximumFractionDigits
4351     * @stable ICU 2.0
4352     */

4353    public void setMaximumFractionDigits(int newValue) {
4354        super.setMaximumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
4355    }
4356
4357    /**
4358     * Sets the minimum number of digits allowed in the fraction portion of a
4359     * number. This override limits the fraction digit count to 340.
4360     * @see NumberFormat#setMinimumFractionDigits
4361     * @stable ICU 2.0
4362     */

4363    public void setMinimumFractionDigits(int newValue) {
4364        super.setMinimumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
4365    }
4366
4367    /**
4368     * Sets whether {@link #parse(String, ParsePosition)} method returns BigDecimal.
4369     * The default value is false.
4370     * @param value true if {@link #parse(String, ParsePosition)} method returns
4371     * BigDecimal.
4372     * @stable ICU 3.6
4373     */

4374    public void setParseBigDecimal(boolean value) {
4375        parseBigDecimal = value;
4376    }
4377
4378    /**
4379     * Returns whether {@link #parse(String, ParsePosition)} method returns BigDecimal.
4380     * @return true if {@link #parse(String, ParsePosition)} method returns BigDecimal.
4381     * @stable ICU 3.6
4382     */

4383    public boolean isParseBigDecimal() {
4384        return parseBigDecimal;
4385    }
4386
4387//#ifndef FOUNDATION
4388
//## private void writeObject(ObjectOutputStream stream) throws IOException, ClassNotFoundException {
4389
//##// Doug, do we need this anymore?
4390
//##// if (roundingIncrementICU != null) {
4391
//##// roundingIncrement = roundingIncrementICU.toBigDecimal();
4392
//##// }
4393
//##
4394
//## stream.defaultWriteObject();
4395
//## }
4396
//#endif
4397

4398    /**
4399     * First, read the default serializable fields from the stream. Then
4400     * if <code>serialVersionOnStream</code> is less than 1, indicating that
4401     * the stream was written by JDK 1.1, initialize <code>useExponentialNotation</code>
4402     * to false, since it was not present in JDK 1.1.
4403     * Finally, set serialVersionOnStream back to the maximum allowed value so that
4404     * default serialization will work properly if this object is streamed out again.
4405     */

4406    private void readObject(ObjectInputStream JavaDoc stream)
4407         throws IOException JavaDoc, ClassNotFoundException JavaDoc
4408    {
4409        stream.defaultReadObject();
4410        /*Bug 4185761 validate fields
4411          [Richard/GCL]
4412        */

4413        // We only need to check the maximum counts because NumberFormat
4414
// .readObject has already ensured that the maximum is greater than the
4415
// minimum count.
4416
/*Commented for compatibility with previous version, and reserved for further use
4417        if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
4418            getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
4419            throw new InvalidObjectException("Digit count out of range");
4420        }*/

4421        /* Truncate the maximumIntegerDigits to DOUBLE_INTEGER_DIGITS and maximumFractionDigits
4422         * to DOUBLE_FRACTION_DIGITS
4423         */

4424        if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS) {
4425             setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
4426        }
4427        if (getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
4428            setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
4429        }
4430        if (serialVersionOnStream < 2) {
4431            exponentSignAlwaysShown = false;
4432            setInternalRoundingIncrement(null);
4433            setRoundingDouble();
4434            roundingMode = BigDecimal.ROUND_HALF_EVEN;
4435            formatWidth = 0;
4436            pad = ' ';
4437            padPosition = PAD_BEFORE_PREFIX;
4438            if (serialVersionOnStream < 1) {
4439                // Didn't have exponential fields
4440
useExponentialNotation = false;
4441            }
4442        }
4443        if (serialVersionOnStream < 3) {
4444            // Versions prior to 3 do not store a currency object.
4445
// Create one to match the DecimalFormatSymbols object.
4446
setCurrencyForSymbols();
4447        }
4448        serialVersionOnStream = currentSerialVersion;
4449        digitList = new DigitList();
4450
4451//#ifndef FOUNDATION
4452
//## if (roundingIncrement != null) {
4453
//## setInternalRoundingIncrement(new BigDecimal(roundingIncrement));
4454
//## setRoundingDouble();
4455
//## }
4456
//#endif
4457
}
4458
4459
4460    private void setInternalRoundingIncrement(BigDecimal value) {
4461        roundingIncrementICU = value;
4462//#ifndef FOUNDATION
4463
//## roundingIncrement = value == null ? null : value.toBigDecimal();
4464
//#endif
4465
}
4466
4467    //----------------------------------------------------------------------
4468
// INSTANCE VARIABLES
4469
//----------------------------------------------------------------------
4470

4471    private transient DigitList digitList = new DigitList();
4472
4473    /**
4474     * The symbol used as a prefix when formatting positive numbers, e.g. "+".
4475     *
4476     * @serial
4477     * @see #getPositivePrefix
4478     */

4479    private String JavaDoc positivePrefix = "";
4480
4481    /**
4482     * The symbol used as a suffix when formatting positive numbers.
4483     * This is often an empty string.
4484     *
4485     * @serial
4486     * @see #getPositiveSuffix
4487     */

4488    private String JavaDoc positiveSuffix = "";
4489
4490    /**
4491     * The symbol used as a prefix when formatting negative numbers, e.g. "-".
4492     *
4493     * @serial
4494     * @see #getNegativePrefix
4495     */

4496    private String JavaDoc negativePrefix = "-";
4497
4498    /**
4499     * The symbol used as a suffix when formatting negative numbers.
4500     * This is often an empty string.
4501     *
4502     * @serial
4503     * @see #getNegativeSuffix
4504     */

4505    private String JavaDoc negativeSuffix = "";
4506    
4507    /**
4508     * The prefix pattern for non-negative numbers. This variable corresponds
4509     * to <code>positivePrefix</code>.
4510     *
4511     * <p>This pattern is expanded by the method <code>expandAffix()</code> to
4512     * <code>positivePrefix</code> to update the latter to reflect changes in
4513     * <code>symbols</code>. If this variable is <code>null</code> then
4514     * <code>positivePrefix</code> is taken as a literal value that does not
4515     * change when <code>symbols</code> changes. This variable is always
4516     * <code>null</code> for <code>DecimalFormat</code> objects older than
4517     * stream version 2 restored from stream.
4518     *
4519     * @serial
4520     */

4521    //[Richard/GCL]
4522
private String JavaDoc posPrefixPattern;
4523
4524    /**
4525     * The suffix pattern for non-negative numbers. This variable corresponds
4526     * to <code>positiveSuffix</code>. This variable is analogous to
4527     * <code>posPrefixPattern</code>; see that variable for further
4528     * documentation.
4529     *
4530     * @serial
4531     */

4532    //[Richard/GCL]
4533
private String JavaDoc posSuffixPattern;
4534
4535    /**
4536     * The prefix pattern for negative numbers. This variable corresponds
4537     * to <code>negativePrefix</code>. This variable is analogous to
4538     * <code>posPrefixPattern</code>; see that variable for further
4539     * documentation.
4540     *
4541     * @serial
4542     */

4543    //[Richard/GCL]
4544
private String JavaDoc negPrefixPattern;
4545
4546    /**
4547     * The suffix pattern for negative numbers. This variable corresponds
4548     * to <code>negativeSuffix</code>. This variable is analogous to
4549     * <code>posPrefixPattern</code>; see that variable for further
4550     * documentation.
4551     *
4552     * @serial
4553     */

4554    //[Richard/GCL]
4555
private String JavaDoc negSuffixPattern;
4556
4557    /**
4558     * Formatter for ChoiceFormat-based currency names. If this field
4559     * is not null, then delegate to it to format currency symbols.
4560     * @since ICU 2.6
4561     */

4562    private ChoiceFormat JavaDoc currencyChoice;
4563
4564    /**
4565     * The multiplier for use in percent, permill, etc.
4566     *
4567     * @serial
4568     * @see #getMultiplier
4569     */

4570    private int multiplier = 1;
4571    
4572    /**
4573     * The number of digits between grouping separators in the integer
4574     * portion of a number. Must be greater than 0 if
4575     * <code>NumberFormat.groupingUsed</code> is true.
4576     *
4577     * @serial
4578     * @see #getGroupingSize
4579     * @see NumberFormat#isGroupingUsed
4580     */

4581    private byte groupingSize = 3; // invariant, > 0 if useThousands
4582

4583    /**
4584     * The secondary grouping size. This is only used for Hindi
4585     * numerals, which use a primary grouping of 3 and a secondary
4586     * grouping of 2, e.g., "12,34,567". If this value is less than
4587     * 1, then secondary grouping is equal to the primary grouping.
4588     * [NEW]
4589     */

4590    private byte groupingSize2 = 0;
4591    
4592    /**
4593     * If true, forces the decimal separator to always appear in a formatted
4594     * number, even if the fractional part of the number is zero.
4595     *
4596     * @serial
4597     * @see #isDecimalSeparatorAlwaysShown
4598     */

4599    private boolean decimalSeparatorAlwaysShown = false;
4600    
4601    /**
4602     * True if this object represents a currency format. This determines
4603     * whether the monetary decimal separator is used instead of the normal one.
4604     */

4605    private transient boolean isCurrencyFormat = false;
4606    
4607    /**
4608     * The <code>DecimalFormatSymbols</code> object used by this format.
4609     * It contains the symbols used to format numbers, e.g. the grouping separator,
4610     * decimal separator, and so on.
4611     *
4612     * @serial
4613     * @see #setDecimalFormatSymbols
4614     * @see DecimalFormatSymbols
4615     */

4616    private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();
4617

4618    /**
4619     * True to use significant digits rather than integer and fraction
4620     * digit counts.
4621     * @serial
4622     * @since ICU 3.0
4623     */

4624    private boolean useSignificantDigits = false;
4625
4626    /**
4627     * The minimum number of significant digits to show. Must be >= 1
4628     * and <= maxSignificantDigits. Ignored unless
4629     * useSignificantDigits == true.
4630     * @serial
4631     * @since ICU 3.0
4632     */

4633    private int minSignificantDigits = 1;
4634
4635    /**
4636     * The maximum number of significant digits to show. Must be >=
4637     * minSignficantDigits. Ignored unless useSignificantDigits ==
4638     * true.
4639     * @serial
4640     * @since ICU 3.0
4641     */

4642    private int maxSignificantDigits = 6;
4643
4644    /**
4645     * True to force the use of exponential (i.e. scientific) notation when formatting
4646     * numbers.
4647     * <p>
4648     * Note that the JDK 1.2 public API provides no way to set this field,
4649     * even though it is supported by the implementation and the stream format.
4650     * The intent is that this will be added to the API in the future.
4651     *
4652     * @serial
4653     */

4654    private boolean useExponentialNotation; // Newly persistent in JDK 1.2
4655

4656    /**
4657     * The minimum number of digits used to display the exponent when a number is
4658     * formatted in exponential notation. This field is ignored if
4659     * <code>useExponentialNotation</code> is not true.
4660     * <p>
4661     * Note that the JDK 1.2 public API provides no way to set this field,
4662     * even though it is supported by the implementation and the stream format.
4663     * The intent is that this will be added to the API in the future.
4664     *
4665     * @serial
4666     */

4667    private byte minExponentDigits; // Newly persistent in JDK 1.2
4668

4669    /**
4670     * <strong><font face=helvetica color=red>NEW</font></strong>
4671     * If true, the exponent is always prefixed with either the plus
4672     * sign or the minus sign. Otherwise, only negative exponents are
4673     * prefixed with the minus sign. This has no effect unless
4674     * <code>useExponentialNotation</code> is true.
4675     * @serial
4676     * @since AlphaWorks NumberFormat
4677     */

4678    private boolean exponentSignAlwaysShown = false;
4679
4680//#ifndef FOUNDATION
4681
//## /**
4682
//## * <strong><font face=helvetica color=red>NEW</font></strong>
4683
//## * The value to which numbers are rounded during formatting. For example,
4684
//## * if the rounding increment is 0.05, then 13.371 would be formatted as
4685
//## * 13.350, assuming 3 fraction digits. Has the value <code>null</code> if
4686
//## * rounding is not in effect, or a positive value if rounding is in effect.
4687
//## * Default value <code>null</code>.
4688
//## * @serial
4689
//## * @since AlphaWorks NumberFormat
4690
//## */
4691
//## // Note: this is kept in sync with roundingIncrementICU.
4692
//## // it is only kept around to avoid a conversion when formatting a java.math.BigDecimal
4693
//## private java.math.BigDecimal roundingIncrement = null;
4694
//#endif
4695

4696    /**
4697     * <strong><font face=helvetica color=red>NEW</font></strong>
4698     * The value to which numbers are rounded during formatting. For example,
4699     * if the rounding increment is 0.05, then 13.371 would be formatted as
4700     * 13.350, assuming 3 fraction digits. Has the value <code>null</code> if
4701     * rounding is not in effect, or a positive value if rounding is in effect.
4702     * Default value <code>null</code>.
4703     * WARNING: the roundingIncrement value is the one serialized.
4704     * @serial
4705     * @since AlphaWorks NumberFormat
4706     */

4707    private transient BigDecimal roundingIncrementICU = null;
4708
4709    /**
4710     * <strong><font face=helvetica color=red>NEW</font></strong>
4711     * The rounding increment as a double. If this value is <= 0, then no
4712     * rounding is done. This value is
4713     * <code>roundingIncrementICU.doubleValue()</code>. Default value 0.0.
4714     */

4715    private transient double roundingDouble = 0.0;
4716
4717    /**
4718     * <strong><font face=helvetica color=red>NEW</font></strong>
4719     * If the roundingDouble is the reciprocal of an integer (the most common case!),
4720     * this is set to be that integer. Otherwise it is 0.0.
4721     */

4722    private transient double roundingDoubleReciprocal = 0.0;
4723
4724    /**
4725     * <strong><font face=helvetica color=red>NEW</font></strong>
4726     * The rounding mode. This value controls any rounding operations which
4727     * occur when applying a rounding increment or when reducing the number of
4728     * fraction digits to satisfy a maximum fraction digits limit. The value
4729     * may assume any of the <code>BigDecimal</code> rounding mode values.
4730     * Default value <code>BigDecimal.ROUND_HALF_EVEN</code>.
4731     * @serial
4732     * @since AlphaWorks NumberFormat
4733     */

4734    private int roundingMode = BigDecimal.ROUND_HALF_EVEN;
4735
4736    /**
4737     * <strong><font face=helvetica color=red>NEW</font></strong>
4738     * The padded format width, or zero if there is no padding. Must
4739     * be >= 0. Default value zero.
4740     * @serial
4741     * @since AlphaWorks NumberFormat
4742     */

4743    private int formatWidth = 0;
4744
4745    /**
4746     * <strong><font face=helvetica color=red>NEW</font></strong>
4747     * The character used to pad the result of format to
4748     * <code>formatWidth</code>, if padding is in effect. Default value ' '.
4749     * @serial
4750     * @since AlphaWorks NumberFormat
4751     */

4752    private char pad = ' ';
4753
4754    /**
4755     * <strong><font face=helvetica color=red>NEW</font></strong>
4756     * The position in the string at which the <code>pad</code> character
4757     * will be inserted, if padding is in effect. Must have a value from
4758     * <code>PAD_BEFORE_PREFIX</code> to <code>PAD_AFTER_SUFFIX</code>.
4759     * Default value <code>PAD_BEFORE_PREFIX</code>.
4760     * @serial
4761     * @since AlphaWorks NumberFormat
4762     */

4763    private int padPosition = PAD_BEFORE_PREFIX;
4764
4765    /**
4766     * True if {@link #parse(String, ParsePosition)} to return BigDecimal
4767     * rather than Long, Double or BigDecimal except special values.
4768     * This property is introduced for J2SE 5 compatibility support.
4769     * @serial
4770     * @since ICU 3.6
4771     * @see #setParseBigDecimal(boolean)
4772     * @see #isParseBigDecimal()
4773     */

4774    private boolean parseBigDecimal = false;
4775
4776    //----------------------------------------------------------------------
4777

4778    static final int currentSerialVersion = 3;
4779
4780    /**
4781     * The internal serial version which says which version was written
4782     * Possible values are:
4783     * <ul>
4784     * <li><b>0</b> (default): versions before JDK 1.2
4785     * <li><b>1</b>: version from JDK 1.2 and later, which includes the two new fields
4786     * <code>useExponentialNotation</code> and <code>minExponentDigits</code>.
4787     * <li><b>2</b>: version on AlphaWorks, which adds roundingMode, formatWidth,
4788     * pad, padPosition, exponentSignAlwaysShown, roundingIncrement.
4789     * <li><b>3</b>: ICU 2.2. Adds currency object.
4790     * </ul>
4791     * @serial */

4792    private int serialVersionOnStream = currentSerialVersion;
4793
4794    //----------------------------------------------------------------------
4795
// CONSTANTS
4796
//----------------------------------------------------------------------
4797

4798    /**
4799     * <strong><font face=helvetica color=red>NEW</font></strong>
4800     * Constant for <code>getPadPosition()</code> and
4801     * <code>setPadPosition()</code> specifying pad characters inserted before
4802     * the prefix.
4803     * @see #setPadPosition
4804     * @see #getPadPosition
4805     * @see #PAD_AFTER_PREFIX
4806     * @see #PAD_BEFORE_SUFFIX
4807     * @see #PAD_AFTER_SUFFIX
4808     * @stable ICU 2.0
4809     */

4810    public static final int PAD_BEFORE_PREFIX = 0;
4811
4812    /**
4813     * <strong><font face=helvetica color=red>NEW</font></strong>
4814     * Constant for <code>getPadPosition()</code> and
4815     * <code>setPadPosition()</code> specifying pad characters inserted after
4816     * the prefix.
4817     * @see #setPadPosition
4818     * @see #getPadPosition
4819     * @see #PAD_BEFORE_PREFIX
4820     * @see #PAD_BEFORE_SUFFIX
4821     * @see #PAD_AFTER_SUFFIX
4822     * @stable ICU 2.0
4823     */

4824    public static final int PAD_AFTER_PREFIX = 1;
4825
4826    /**
4827     * <strong><font face=helvetica color=red>NEW</font></strong>
4828     * Constant for <code>getPadPosition()</code> and
4829     * <code>setPadPosition()</code> specifying pad characters inserted before
4830     * the suffix.
4831     * @see #setPadPosition
4832     * @see #getPadPosition
4833     * @see #PAD_BEFORE_PREFIX
4834     * @see #PAD_AFTER_PREFIX
4835     * @see #PAD_AFTER_SUFFIX
4836     * @stable ICU 2.0
4837     */

4838    public static final int PAD_BEFORE_SUFFIX = 2;
4839
4840    /**
4841     * <strong><font face=helvetica color=red>NEW</font></strong>
4842     * Constant for <code>getPadPosition()</code> and
4843     * <code>setPadPosition()</code> specifying pad characters inserted after
4844     * the suffix.
4845     * @see #setPadPosition
4846     * @see #getPadPosition
4847     * @see #PAD_BEFORE_PREFIX
4848     * @see #PAD_AFTER_PREFIX
4849     * @see #PAD_BEFORE_SUFFIX
4850     * @stable ICU 2.0
4851     */

4852    public static final int PAD_AFTER_SUFFIX = 3;
4853
4854    // Constants for characters used in programmatic (unlocalized) patterns.
4855
private static final char PATTERN_ZERO_DIGIT = '0';
4856    private static final char PATTERN_GROUPING_SEPARATOR = ',';
4857    private static final char PATTERN_DECIMAL_SEPARATOR = '.';
4858    private static final char PATTERN_DIGIT = '#';
4859            static final char PATTERN_SIGNIFICANT_DIGIT = '@';
4860            static final char PATTERN_EXPONENT = 'E'; // [NEW]
4861
static final char PATTERN_PLUS_SIGN = '+'; // [NEW]
4862

4863    // Affix
4864
private static final char PATTERN_PER_MILLE = '\u2030';
4865    private static final char PATTERN_PERCENT = '%';
4866            static final char PATTERN_PAD_ESCAPE = '*'; // [NEW]
4867
/*Bug 4212072
4868      To meet the need of expandAffix(String, StirngBuffer)
4869      [Richard/GCL]
4870    */

4871    private static final char PATTERN_MINUS = '-'; //[Richard/GCL]
4872

4873    // Other
4874
private static final char PATTERN_SEPARATOR = ';';
4875
4876    // Pad escape is package private to allow access by DecimalFormatSymbols.
4877
// Also plus sign. Also exponent.
4878

4879    /**
4880     * The CURRENCY_SIGN is the standard Unicode symbol for currency. It
4881     * is used in patterns and substitued with either the currency symbol,
4882     * or if it is doubled, with the international currency symbol. If the
4883     * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
4884     * replaced with the monetary decimal separator.
4885     *
4886     * The CURRENCY_SIGN is not localized.
4887     */

4888    private static final char CURRENCY_SIGN = '\u00A4';
4889
4890    private static final char QUOTE = '\'';
4891    
4892    /* Upper limit on integer and fraction digits for a Java double
4893       [Richard/GCL]
4894    */

4895    static final int DOUBLE_INTEGER_DIGITS = 309;
4896    static final int DOUBLE_FRACTION_DIGITS = 340;
4897
4898    /**
4899     * When someone turns on scientific mode, we assume that more than this
4900     * number of digits is due to flipping from some other mode that didn't
4901     * restrict the maximum, and so we force 1 integer digit. We don't bother
4902     * to track and see if someone is using exponential notation with more than
4903     * this number, it wouldn't make sense anyway, and this is just to make sure
4904     * that someone turning on scientific mode with default settings doesn't
4905     * end up with lots of zeroes.
4906     */

4907    static final int MAX_SCIENTIFIC_INTEGER_DIGITS = 8;
4908
4909//#ifdef FOUNDATION
4910
// we're not compatible with other versions, since we have no java.math.BigDecimal field
4911
private static final long serialVersionUID = 2;
4912//#else
4913
//## // Proclaim JDK 1.1 serial compatibility.
4914
//## private static final long serialVersionUID = 864413376551465018L;
4915
//#endif
4916
private ArrayList JavaDoc attributes = new ArrayList JavaDoc();
4917}
4918
4919//eof
4920
Popular Tags