KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencms > util > PrintfFormat


1 /*
2  * File : $Source: /usr/local/cvs/opencms/src/org/opencms/util/PrintfFormat.java,v $
3  * Date : $Date: 2005/06/23 11:11:24 $
4  * Version: $Revision: 1.9 $
5  *
6  * This library is part of OpenCms -
7  * the Open Source Content Mananagement System
8  *
9  * Copyright (c) 2005 Alkacon Software GmbH (http://www.alkacon.com)
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * For further information about Alkacon Software GmbH, please see the
22  * company website: http://www.alkacon.com
23  *
24  * For further information about OpenCms, please see the
25  * project website: http://www.opencms.org
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */

31
32 //
33
// (c) 2000 Sun Microsystems, Inc.
34
// ALL RIGHTS RESERVED
35
//
36
// License Grant-
37
//
38
//
39
// Permission to use, copy, modify, and distribute this Software and its
40
// documentation for NON-COMMERCIAL or COMMERCIAL purposes and without fee is
41
// hereby granted.
42
//
43
// This Software is provided "AS IS". All express warranties, including any
44
// implied warranty of merchantability, satisfactory quality, fitness for a
45
// particular purpose, or non-infringement, are disclaimed, except to the extent
46
// that such disclaimers are held to be legally invalid.
47
//
48
// You acknowledge that Software is not designed, licensed or intended for use in
49
// the design, construction, operation or maintenance of any nuclear facility
50
// ("High Risk Activities"). Sun disclaims any express or implied warranty of
51
// fitness for such uses.
52
//
53
// Please refer to the file http://www.sun.com/policies/trademarks/ for further
54
// important trademark information and to
55
// http://java.sun.com/nav/business/index.html for further important licensing
56
// information for the Java Technology.
57
//
58

59 package org.opencms.util;
60
61 import org.opencms.main.CmsIllegalArgumentException;
62
63 import java.text.DecimalFormatSymbols JavaDoc;
64 import java.util.Enumeration JavaDoc;
65 import java.util.Locale JavaDoc;
66 import java.util.Vector JavaDoc;
67
68 /**
69  * PrintfFormat allows the formatting of an array of
70  * objects embedded within a string. Primitive types
71  * must be passed using wrapper types. The formatting
72  * is controlled by a control string.
73  *<p>
74  * A control string is a Java string that contains a
75  * control specification. The control specification
76  * starts at the first percent sign (%) in the string,
77  * provided that this percent sign
78  *<ol>
79  *<li>is not escaped protected by a matching % or is
80  * not an escape % character,
81  *<li>is not at the end of the format string, and
82  *<li>precedes a sequence of characters that parses as
83  * a valid control specification.
84  *</ol>
85  *</p><p>
86  * A control specification usually takes the form:
87  *<pre> % ['-+ #0]* [0..9]* { . [0..9]* }+
88  * { [hlL] }+ [idfgGoxXeEcs]
89  *</pre>
90  * There are variants of this basic form that are
91  * discussed below.</p>
92  *<p>
93  * The format is composed of zero or more directives
94  * defined as follows:
95  *<ul>
96  *<li>ordinary characters, which are simply copied to
97  * the output stream;
98  *<li>escape sequences, which represent non-graphic
99  * characters; and
100  *<li>conversion specifications, each of which
101  * results in the fetching of zero or more arguments.
102  *</ul></p>
103  *<p>
104  * The results are undefined if there are insufficient
105  * arguments for the format. Usually an unchecked
106  * exception will be thrown. If the format is
107  * exhausted while arguments remain, the excess
108  * arguments are evaluated but are otherwise ignored.
109  * In format strings containing the % form of
110  * conversion specifications, each argument in the
111  * argument list is used exactly once.</p>
112  * <p>
113  * Conversions can be applied to the <code>n</code>th
114  * argument after the format in the argument list,
115  * rather than to the next unused argument. In this
116  * case, the conversion characer % is replaced by the
117  * sequence %<code>n</code>$, where <code>n</code> is
118  * a decimal integer giving the position of the
119  * argument in the argument list.</p>
120  * <p>
121  * In format strings containing the %<code>n</code>$
122  * form of conversion specifications, each argument
123  * in the argument list is used exactly once.</p>
124  *
125  *<h4>Escape Sequences</h4>
126  *<p>
127  * The following table lists escape sequences and
128  * associated actions on display devices capable of
129  * the action.
130  *<table>
131  *<tr><th align=left>Sequence</th>
132  * <th align=left>Name</th>
133  * <th align=left>Description</th></tr>
134  *<tr><td>\\</td><td>backlash</td><td>None.
135  *</td></tr>
136  *<tr><td>\a</td><td>alert</td><td>Attempts to alert
137  * the user through audible or visible
138  * notification.
139  *</td></tr>
140  *<tr><td>\b</td><td>backspace</td><td>Moves the
141  * printing position to one column before
142  * the current position, unless the
143  * current position is the start of a line.
144  *</td></tr>
145  *<tr><td>\f</td><td>form-feed</td><td>Moves the
146  * printing position to the initial
147  * printing position of the next logical
148  * page.
149  *</td></tr>
150  *<tr><td>\n</td><td>newline</td><td>Moves the
151  * printing position to the start of the
152  * next line.
153  *</td></tr>
154  *<tr><td>\r</td><td>carriage-return</td><td>Moves
155  * the printing position to the start of
156  * the current line.
157  *</td></tr>
158  *<tr><td>\t</td><td>tab</td><td>Moves the printing
159  * position to the next implementation-
160  * defined horizontal tab position.
161  *</td></tr>
162  *<tr><td>\v</td><td>vertical-tab</td><td>Moves the
163  * printing position to the start of the
164  * next implementation-defined vertical
165  * tab position.
166  *</td></tr>
167  *</table></p>
168  *<h4>Conversion Specifications</h4>
169  *<p>
170  * Each conversion specification is introduced by
171  * the percent sign character (%). After the character
172  * %, the following appear in sequence:</p>
173  *<p>
174  * Zero or more flags (in any order), which modify the
175  * meaning of the conversion specification.</p>
176  *<p>
177  * An optional minimum field width. If the converted
178  * value has fewer characters than the field width, it
179  * will be padded with spaces by default on the left;
180  * t will be padded on the right, if the left-
181  * adjustment flag (-), described below, is given to
182  * the field width. The field width takes the form
183  * of a decimal integer. If the conversion character
184  * is s, the field width is the the minimum number of
185  * characters to be printed.</p>
186  *<p>
187  * An optional precision that gives the minumum number
188  * of digits to appear for the d, i, o, x or X
189  * conversions (the field is padded with leading
190  * zeros); the number of digits to appear after the
191  * radix character for the e, E, and f conversions,
192  * the maximum number of significant digits for the g
193  * and G conversions; or the maximum number of
194  * characters to be written from a string is s and S
195  * conversions. The precision takes the form of an
196  * optional decimal digit string, where a null digit
197  * string is treated as 0. If a precision appears
198  * with a c conversion character the precision is
199  * ignored.
200  * </p>
201  *<p>
202  * An optional h specifies that a following d, i, o,
203  * x, or X conversion character applies to a type
204  * short argument (the argument will be promoted
205  * according to the integral promotions and its value
206  * converted to type short before printing).</p>
207  *<p>
208  * An optional l (ell) specifies that a following
209  * d, i, o, x, or X conversion character applies to a
210  * type long argument.</p>
211  *<p>
212  * A field width or precision may be indicated by an
213  * asterisk (*) instead of a digit string. In this
214  * case, an integer argument supplised the field width
215  * precision. The argument that is actually converted
216  * is not fetched until the conversion letter is seen,
217  * so the the arguments specifying field width or
218  * precision must appear before the argument (if any)
219  * to be converted. If the precision argument is
220  * negative, it will be changed to zero. A negative
221  * field width argument is taken as a - flag, followed
222  * by a positive field width.</p>
223  * <p>
224  * In format strings containing the %<code>n</code>$
225  * form of a conversion specification, a field width
226  * or precision may be indicated by the sequence
227  * *<code>m</code>$, where m is a decimal integer
228  * giving the position in the argument list (after the
229  * format argument) of an integer argument containing
230  * the field width or precision.</p>
231  * <p>
232  * The format can contain either numbered argument
233  * specifications (that is, %<code>n</code>$ and
234  * *<code>m</code>$), or unnumbered argument
235  * specifications (that is % and *), but normally not
236  * both. The only exception to this is that %% can
237  * be mixed with the %<code>n</code>$ form. The
238  * results of mixing numbered and unnumbered argument
239  * specifications in a format string are undefined.</p>
240  *
241  *<h4>Flag Characters</h4>
242  *<p>
243  * The flags and their meanings are:</p>
244  *<dl>
245  * <dt>'<dd> integer portion of the result of a
246  * decimal conversion (%i, %d, %f, %g, or %G) will
247  * be formatted with thousands' grouping
248  * characters. For other conversions the flag
249  * is ignored. The non-monetary grouping
250  * character is used.
251  * <dt>-<dd> result of the conversion is left-justified
252  * within the field. (It will be right-justified
253  * if this flag is not specified).
254  * <dt>+<dd> result of a signed conversion always
255  * begins with a sign (+ or -). (It will begin
256  * with a sign only when a negative value is
257  * converted if this flag is not specified.)
258  * <dt>&lt;space&gt;<dd> If the first character of a
259  * signed conversion is not a sign, a space
260  * character will be placed before the result.
261  * This means that if the space character and +
262  * flags both appear, the space flag will be
263  * ignored.
264  * <dt>#<dd> value is to be converted to an alternative
265  * form. For c, d, i, and s conversions, the flag
266  * has no effect. For o conversion, it increases
267  * the precision to force the first digit of the
268  * result to be a zero. For x or X conversion, a
269  * non-zero result has 0x or 0X prefixed to it,
270  * respectively. For e, E, f, g, and G
271  * conversions, the result always contains a radix
272  * character, even if no digits follow the radix
273  * character (normally, a decimal point appears in
274  * the result of these conversions only if a digit
275  * follows it). For g and G conversions, trailing
276  * zeros will not be removed from the result as
277  * they normally are.
278  * <dt>0<dd> d, i, o, x, X, e, E, f, g, and G
279  * conversions, leading zeros (following any
280  * indication of sign or base) are used to pad to
281  * the field width; no space padding is
282  * performed. If the 0 and - flags both appear,
283  * the 0 flag is ignored. For d, i, o, x, and X
284  * conversions, if a precision is specified, the
285  * 0 flag will be ignored. For c conversions,
286  * the flag is ignored.
287  *</dl>
288  *
289  *<h4>Conversion Characters</h4>
290  *<p>
291  * Each conversion character results in fetching zero
292  * or more arguments. The results are undefined if
293  * there are insufficient arguments for the format.
294  * Usually, an unchecked exception will be thrown.
295  * If the format is exhausted while arguments remain,
296  * the excess arguments are ignored.</p>
297  *
298  *<p>
299  * The conversion characters and their meanings are:
300  *</p>
301  *<dl>
302  * <dt>d,i<dd>The int argument is converted to a
303  * signed decimal in the style [-]dddd. The
304  * precision specifies the minimum number of
305  * digits to appear; if the value being
306  * converted can be represented in fewer
307  * digits, it will be expanded with leading
308  * zeros. The default precision is 1. The
309  * result of converting 0 with an explicit
310  * precision of 0 is no characters.
311  * <dt>o<dd> The int argument is converted to unsigned
312  * octal format in the style ddddd. The
313  * precision specifies the minimum number of
314  * digits to appear; if the value being
315  * converted can be represented in fewer
316  * digits, it will be expanded with leading
317  * zeros. The default precision is 1. The
318  * result of converting 0 with an explicit
319  * precision of 0 is no characters.
320  * <dt>x<dd> The int argument is converted to unsigned
321  * hexadecimal format in the style dddd; the
322  * letters abcdef are used. The precision
323  * specifies the minimum numberof digits to
324  * appear; if the value being converted can be
325  * represented in fewer digits, it will be
326  * expanded with leading zeros. The default
327  * precision is 1. The result of converting 0
328  * with an explicit precision of 0 is no
329  * characters.
330  * <dt>X<dd> Behaves the same as the x conversion
331  * character except that letters ABCDEF are
332  * used instead of abcdef.
333  * <dt>f<dd> The floating point number argument is
334  * written in decimal notation in the style
335  * [-]ddd.ddd, where the number of digits after
336  * the radix character (shown here as a decimal
337  * point) is equal to the precision
338  * specification. A Locale is used to determine
339  * the radix character to use in this format.
340  * If the precision is omitted from the
341  * argument, six digits are written after the
342  * radix character; if the precision is
343  * explicitly 0 and the # flag is not specified,
344  * no radix character appears. If a radix
345  * character appears, at least 1 digit appears
346  * before it. The value is rounded to the
347  * appropriate number of digits.
348  * <dt>e,E<dd>The floating point number argument is
349  * written in the style [-]d.ddde{+-}dd
350  * (the symbols {+-} indicate either a plus or
351  * minus sign), where there is one digit before
352  * the radix character (shown here as a decimal
353  * point) and the number of digits after it is
354  * equal to the precision. A Locale is used to
355  * determine the radix character to use in this
356  * format. When the precision is missing, six
357  * digits are written after the radix character;
358  * if the precision is 0 and the # flag is not
359  * specified, no radix character appears. The
360  * E conversion will produce a number with E
361  * instead of e introducing the exponent. The
362  * exponent always contains at least two digits.
363  * However, if the value to be written requires
364  * an exponent greater than two digits,
365  * additional exponent digits are written as
366  * necessary. The value is rounded to the
367  * appropriate number of digits.
368  * <dt>g,G<dd>The floating point number argument is
369  * written in style f or e (or in sytle E in the
370  * case of a G conversion character), with the
371  * precision specifying the number of
372  * significant digits. If the precision is
373  * zero, it is taken as one. The style used
374  * depends on the value converted: style e
375  * (or E) will be used only if the exponent
376  * resulting from the conversion is less than
377  * -4 or greater than or equal to the precision.
378  * Trailing zeros are removed from the result.
379  * A radix character appears only if it is
380  * followed by a digit.
381  * <dt>c,C<dd>The integer argument is converted to a
382  * char and the result is written.
383  *
384  * <dt>s,S<dd>The argument is taken to be a string and
385  * bytes from the string are written until the
386  * end of the string or the number of bytes
387  * indicated by the precision specification of
388  * the argument is reached. If the precision
389  * is omitted from the argument, it is taken to
390  * be infinite, so all characters up to the end
391  * of the string are written.
392  * <dt>%<dd>Write a % character; no argument is
393  * converted.
394  *</dl>
395  *<p>
396  * If a conversion specification does not match one of
397  * the above forms, an IllegalArgumentException is
398  * thrown and the instance of PrintfFormat is not
399  * created.</p>
400  *<p>
401  * If a floating point value is the internal
402  * representation for infinity, the output is
403  * [+]Infinity, where Infinity is either Infinity or
404  * Inf, depending on the desired output string length.
405  * Printing of the sign follows the rules described
406  * above.</p>
407  *<p>
408  * If a floating point value is the internal
409  * representation for "not-a-number," the output is
410  * [+]NaN. Printing of the sign follows the rules
411  * described above.</p>
412  *<p>
413  * In no case does a non-existent or small field width
414  * cause truncation of a field; if the result of a
415  * conversion is wider than the field width, the field
416  * is simply expanded to contain the conversion result.
417  *</p>
418  *<p>
419  * The behavior is like printf. One exception is that
420  * the minimum number of exponent digits is 3 instead
421  * of 2 for e and E formats when the optional L is used
422  * before the e, E, g, or G conversion character. The
423  * optional L does not imply conversion to a long long
424  * double. </p>
425  * <p>
426  * The biggest divergence from the C printf
427  * specification is in the use of 16 bit characters.
428  * This allows the handling of characters beyond the
429  * small ASCII character set and allows the utility to
430  * interoperate correctly with the rest of the Java
431  * runtime environment.</p>
432  *<p>
433  * Omissions from the C printf specification are
434  * numerous. All the known omissions are present
435  * because Java never uses bytes to represent
436  * characters and does not have pointers:</p>
437  *<ul>
438  * <li>%c is the same as %C.
439  * <li>%s is the same as %S.
440  * <li>u, p, and n conversion characters.
441  * <li>%ws format.
442  * <li>h modifier applied to an n conversion character.
443  * <li>l (ell) modifier applied to the c, n, or s
444  * conversion characters.
445  * <li>ll (ell ell) modifier to d, i, o, u, x, or X
446  * conversion characters.
447  * <li>ll (ell ell) modifier to an n conversion
448  * character.
449  * <li>c, C, d,i,o,u,x, and X conversion characters
450  * apply to Byte, Character, Short, Integer, Long
451  * types.
452  * <li>f, e, E, g, and G conversion characters apply
453  * to Float and Double types.
454  * <li>s and S conversion characters apply to String
455  * types.
456  * <li>All other reference types can be formatted
457  * using the s or S conversion characters only.
458  *</ul>
459  * <p>
460  * Most of this specification is quoted from the Unix
461  * man page for the sprintf utility.</p>
462  *
463  * @author Allan Jacobs
464  *
465  * @version $Revision: 1.9 $
466  *
467  * @since 6.0.0
468  */

469 public class PrintfFormat {
470
471     /**
472      *<p>
473      * ConversionSpecification allows the formatting of
474      * a single primitive or object embedded within a
475      * string. The formatting is controlled by a
476      * format string. Only one Java primitive or
477      * object can be formatted at a time.
478      *<p>
479      * A format string is a Java string that contains
480      * a control string. The control string starts at
481      * the first percent sign (%) in the string,
482      * provided that this percent sign
483      *<ol>
484      *<li>is not escaped protected by a matching % or
485      * is not an escape % character,
486      *<li>is not at the end of the format string, and
487      *<li>precedes a sequence of characters that parses
488      * as a valid control string.
489      *</ol>
490      *<p>
491      * A control string takes the form:
492      *<pre> % ['-+ #0]* [0..9]* { . [0..9]* }+
493      * { [hlL] }+ [idfgGoxXeEcs]
494      *</pre>
495      *<p>
496      * The behavior is like printf. One (hopefully the
497      * only) exception is that the minimum number of
498      * exponent digits is 3 instead of 2 for e and E
499      * formats when the optional L is used before the
500      * e, E, g, or G conversion character. The
501      * optional L does not imply conversion to a long
502      * long double.
503      */

504     private final class ConversionSpecification {
505
506         /** Default precision. */
507         private static final int DEFAULT_DIGITS = 6;
508
509         /**
510          * For an o conversion, increase the precision to
511          * force the first digit of the result to be a
512          * zero. For x (or X) conversions, a non-zero
513          * result will have 0x (or 0X) prepended to it.
514          * For e, E, f, g, or G conversions, the result
515          * will always contain a radix character, even if
516          * no digits follow the point. For g and G
517          * conversions, trailing zeros will not be removed
518          * from the result.
519          */

520         private boolean m_alternateForm;
521
522         /** Internal variable. */
523         private int m_argumentPosition;
524
525         /** Internal variable. */
526         private int m_argumentPositionForFieldWidth;
527
528         /** Internal variable. */
529         private int m_argumentPositionForPrecision;
530
531         /** Control string type. */
532         private char m_conversionCharacter;
533
534         /**
535          * If the converted value has fewer bytes than the
536          * field width, it will be padded with spaces or
537          * zeroes.
538          */

539         private int m_fieldWidth;
540
541         /**
542          * Flag indicating whether or not the field width
543          * has been set.
544          */

545         private boolean m_fieldWidthSet;
546
547         /** Literal or control format string. */
548         private String JavaDoc m_fmt;
549
550         /**
551          * The result of a signed conversion will always
552          * begin with a sign (+ or -).
553          */

554         private boolean m_leadingSign;
555
556         /**
557          * Flag indicating that left padding with spaces is
558          * specified.
559          */

560         private boolean m_leadingSpace;
561
562         /**
563          * Flag indicating that left padding with zeroes is
564          * specified.
565          */

566         private boolean m_leadingZeros;
567
568         /**
569          * The result of the conversion will be
570          * left-justified within the field.
571          */

572         private boolean m_leftJustify;
573
574         /**
575          * Flag specifying that a following d, i, o, u, x,
576          * or X conversion character applies to a type
577          * short int.
578          */

579         private boolean m_optionalh;
580
581         /**
582          * Flag specifying that a following d, i, o, u, x,
583          * or X conversion character applies to a type lont
584          * int argument.
585          */

586         private boolean m_optionall;
587
588         /**
589          * Flag specifying that a following e, E, f, g, or
590          * G conversion character applies to a type double
591          * argument. This is a noop in Java.
592          */

593         private boolean m_optionalL;
594
595         /**
596          * Position within the control string. Used by
597          * the constructor.
598          */

599         private int m_pos;
600
601         /** Internal variable. */
602         private boolean m_positionalFieldWidth;
603
604         /** Internal variable. */
605         private boolean m_positionalPrecision;
606
607         /** Internal variable. */
608         private boolean m_positionalSpecification;
609
610         /**
611          * The minimum number of digits to appear for the
612          * d, i, o, u, x, or X conversions. The number of
613          * digits to appear after the radix character for
614          * the e, E, and f conversions. The maximum number
615          * of significant digits for the g and G
616          * conversions. The maximum number of bytes to be
617          * printed from a string in s and S conversions.
618          */

619         private int m_precision;
620
621         /**
622          * Flag indicating whether or not the precision has
623          * been set.
624          */

625         private boolean m_precisionSet;
626
627         /**
628          * The integer portion of the result of a decimal
629          * conversion (i, d, u, f, g, or G) will be
630          * formatted with thousands' grouping characters.
631          * For other conversions the flag is ignored.
632          */

633         private boolean m_thousands;
634
635         /**
636          * Flag indicating that the field width is *.
637          */

638         private boolean m_variableFieldWidth;
639
640         /**
641          * Flag indicating that the precision is *.
642          */

643         private boolean m_variablePrecision;
644
645         /**
646          * Constructor. Used to prepare an instance
647          * to hold a literal, not a control string.
648          */

649         private ConversionSpecification() {
650
651             // empty
652
}
653
654         /**
655          * Constructor for a conversion specification.
656          * The argument must begin with a % and end
657          * with the conversion character for the
658          * conversion specification.
659          * @param fmtArg String specifying the
660          * conversion specification.
661          * @exception CmsIllegalArgumentException if the
662          * input string is null, zero length, or
663          * otherwise malformed.
664          */

665         private ConversionSpecification(String JavaDoc fmtArg)
666         throws CmsIllegalArgumentException {
667
668             if (fmtArg == null) {
669                 throw new NullPointerException JavaDoc();
670             }
671             if (fmtArg.length() == 0) {
672                 throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_CONTROL_STRING_LENGTH_0));
673             }
674             if (fmtArg.charAt(0) == '%') {
675                 m_fmt = fmtArg;
676                 m_pos = 1;
677                 setArgPosition();
678                 setFlagCharacters();
679                 setFieldWidth();
680                 setPrecision();
681                 setOptionalHL();
682                 if (setConversionCharacter()) {
683                     if (m_pos == fmtArg.length()) {
684                         if (m_leadingZeros && m_leftJustify) {
685                             m_leadingZeros = false;
686                         }
687                         if (m_precisionSet && m_leadingZeros) {
688                             if (m_conversionCharacter == 'd'
689                                 || m_conversionCharacter == 'i'
690                                 || m_conversionCharacter == 'o'
691                                 || m_conversionCharacter == 'x') {
692                                 m_leadingZeros = false;
693                             }
694                         }
695                     } else {
696                         throw new CmsIllegalArgumentException(Messages.get().container(
697                             Messages.ERR_INVALID_CONVERSION_SPEC_1,
698                             fmtArg));
699                     }
700                 } else {
701                     throw new CmsIllegalArgumentException(Messages.get().container(
702                         Messages.ERR_INVALID_CONVERSION_SPEC_1,
703                         fmtArg));
704                 }
705             } else {
706                 throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_CONTROL_STRING_START_0));
707             }
708         }
709
710         /**
711          * Internal helper.<p>
712          *
713          * @return the result
714          */

715         int getArgumentPosition() {
716
717             return m_argumentPosition;
718         }
719
720         /**
721          * Internal helper.<p>
722          *
723          * @return the result
724          */

725         int getArgumentPositionForFieldWidth() {
726
727             return m_argumentPositionForFieldWidth;
728         }
729
730         /**
731          * Internal helper.<p>
732          *
733          * @return the result
734          */

735         int getArgumentPositionForPrecision() {
736
737             return m_argumentPositionForPrecision;
738         }
739
740         /**
741          * Get the conversion character that tells what
742          * type of control character this instance has.
743          *
744          * @return the conversion character.
745          */

746         char getConversionCharacter() {
747
748             return m_conversionCharacter;
749         }
750
751         /**
752          * Get the String for this instance. Translate
753          * any escape sequences.
754          *
755          * @return s the stored String.
756          */

757         String JavaDoc getLiteral() {
758
759             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
760             int i = 0;
761             while (i < m_fmt.length()) {
762                 if (m_fmt.charAt(i) == '\\') {
763                     i++;
764                     if (i < m_fmt.length()) {
765                         char c = m_fmt.charAt(i);
766                         switch (c) {
767                             case 'a':
768                                 sb.append((char)0x07);
769                                 break;
770                             case 'b':
771                                 sb.append('\b');
772                                 break;
773                             case 'f':
774                                 sb.append('\f');
775                                 break;
776                             case 'n':
777                                 sb.append(System.getProperty("line.separator"));
778                                 break;
779                             case 'r':
780                                 sb.append('\r');
781                                 break;
782                             case 't':
783                                 sb.append('\t');
784                                 break;
785                             case 'v':
786                                 sb.append((char)0x0b);
787                                 break;
788                             case '\\':
789                                 sb.append('\\');
790                                 break;
791                             default:
792                         // noop
793
}
794                         i++;
795                     } else {
796                         sb.append('\\');
797                     }
798                 } else {
799                     i++;
800                 }
801             }
802             return m_fmt;
803         }
804
805         /**
806          * Format a double argument using this conversion
807          * specification.
808          * @param s the double to format.
809          * @return the formatted String.
810          * @exception CmsIllegalArgumentException if the
811          * conversion character is c, C, s, S, i, d,
812          * x, X, or o.
813          */

814         String JavaDoc internalsprintf(double s) throws CmsIllegalArgumentException {
815
816             String JavaDoc s2 = "";
817             switch (m_conversionCharacter) {
818                 case 'f':
819                     s2 = printFFormat(s);
820                     break;
821                 case 'E':
822                 case 'e':
823                     s2 = printEFormat(s);
824                     break;
825                 case 'G':
826                 case 'g':
827                     s2 = printGFormat(s);
828                     break;
829                 default:
830                     throw new CmsIllegalArgumentException(Messages.get().container(
831                         Messages.ERR_INVALID_DOUBLE_FMT_CHAR_2,
832                         "double",
833                         new Character JavaDoc(m_conversionCharacter)));
834             }
835             return s2;
836         }
837
838         /**
839          * Format an int argument using this conversion
840          * specification.
841          * @param s the int to format.
842          * @return the formatted String.
843          * @exception CmsIllegalArgumentException if the
844          * conversion character is f, e, E, g, or G.
845          */

846         String JavaDoc internalsprintf(int s) throws CmsIllegalArgumentException {
847
848             String JavaDoc s2 = "";
849             switch (m_conversionCharacter) {
850                 case 'd':
851                 case 'i':
852                     if (m_optionalh) {
853                         s2 = printDFormat((short)s);
854                     } else if (m_optionall) {
855                         s2 = printDFormat((long)s);
856                     } else {
857                         s2 = printDFormat(s);
858                     }
859                     break;
860                 case 'x':
861                 case 'X':
862                     if (m_optionalh) {
863                         s2 = printXFormat((short)s);
864                     } else if (m_optionall) {
865                         s2 = printXFormat((long)s);
866                     } else {
867                         s2 = printXFormat(s);
868                     }
869                     break;
870                 case 'o':
871                     if (m_optionalh) {
872                         s2 = printOFormat((short)s);
873                     } else if (m_optionall) {
874                         s2 = printOFormat((long)s);
875                     } else {
876                         s2 = printOFormat(s);
877                     }
878                     break;
879                 case 'c':
880                 case 'C':
881                     s2 = printCFormat((char)s);
882                     break;
883                 default:
884                     throw new CmsIllegalArgumentException(Messages.get().container(
885                         Messages.ERR_INVALID_DOUBLE_FMT_CHAR_2,
886                         "int",
887                         new Character JavaDoc(m_conversionCharacter)));
888             }
889             return s2;
890         }
891
892         /**
893          * Format a long argument using this conversion
894          * specification.
895          * @param s the long to format.
896          * @return the formatted String.
897          * @exception CmsIllegalArgumentException if the
898          * conversion character is f, e, E, g, or G.
899          */

900         String JavaDoc internalsprintf(long s) throws CmsIllegalArgumentException {
901
902             String JavaDoc s2 = "";
903             switch (m_conversionCharacter) {
904                 case 'd':
905                 case 'i':
906                     if (m_optionalh) {
907                         s2 = printDFormat((short)s);
908                     } else if (m_optionall) {
909                         s2 = printDFormat(s);
910                     } else {
911                         s2 = printDFormat((int)s);
912                     }
913                     break;
914                 case 'x':
915                 case 'X':
916                     if (m_optionalh) {
917                         s2 = printXFormat((short)s);
918                     } else if (m_optionall) {
919                         s2 = printXFormat(s);
920                     } else {
921                         s2 = printXFormat((int)s);
922                     }
923                     break;
924                 case 'o':
925                     if (m_optionalh) {
926                         s2 = printOFormat((short)s);
927                     } else if (m_optionall) {
928                         s2 = printOFormat(s);
929                     } else {
930                         s2 = printOFormat((int)s);
931                     }
932                     break;
933                 case 'c':
934                 case 'C':
935                     s2 = printCFormat((char)s);
936                     break;
937                 default:
938                     throw new CmsIllegalArgumentException(Messages.get().container(
939                         Messages.ERR_INVALID_DOUBLE_FMT_CHAR_2,
940                         "long",
941                         new Character JavaDoc(m_conversionCharacter)));
942             }
943             return s2;
944         }
945
946         /**
947          * Format an Object argument using this conversion
948          * specification.
949          * @param s the Object to format.
950          * @return the formatted String.
951          * @exception CmsIllegalArgumentException if the
952          * conversion character is neither s nor S.
953          */

954         String JavaDoc internalsprintf(Object JavaDoc s) throws CmsIllegalArgumentException {
955
956             String JavaDoc s2 = "";
957             if (m_conversionCharacter == 's' || m_conversionCharacter == 'S') {
958                 s2 = printSFormat(s.toString());
959             } else {
960                 throw new CmsIllegalArgumentException(Messages.get().container(
961                     Messages.ERR_INVALID_DOUBLE_FMT_CHAR_2,
962                     "String",
963                     new Character JavaDoc(m_conversionCharacter)));
964             }
965             return s2;
966         }
967
968         /**
969          * Format a String argument using this conversion
970          * specification.
971          * @param s the String to format.
972          * @return the formatted String.
973          * @exception CmsIllegalArgumentException if the
974          * conversion character is neither s nor S.
975          */

976         String JavaDoc internalsprintf(String JavaDoc s) throws CmsIllegalArgumentException {
977
978             String JavaDoc s2 = "";
979             if (m_conversionCharacter == 's' || m_conversionCharacter == 'S') {
980                 s2 = printSFormat(s);
981             } else {
982                 throw new CmsIllegalArgumentException(Messages.get().container(
983                     Messages.ERR_INVALID_DOUBLE_FMT_CHAR_2,
984                     "String",
985                     new Character JavaDoc(m_conversionCharacter)));
986             }
987             return s2;
988         }
989
990         /**
991          * Internal helper.<p>
992          *
993          * @return the result
994          */

995         boolean isPositionalFieldWidth() {
996
997             return m_positionalFieldWidth;
998         }
999
1000        /**
1001         * Internal helper.<p>
1002         *
1003         * @return the result
1004         */

1005        boolean isPositionalPrecision() {
1006
1007            return m_positionalPrecision;
1008        }
1009
1010        /**
1011         * Internal helper.<p>
1012         *
1013         * @return the result
1014         */

1015        boolean isPositionalSpecification() {
1016
1017            return m_positionalSpecification;
1018        }
1019
1020        /**
1021         * Check whether the specifier has a variable
1022         * field width that is going to be set by an
1023         * argument.
1024         * @return <code>true</code> if the conversion
1025         * uses an * field width; otherwise
1026         * <code>false</code>.
1027         */

1028        boolean isVariableFieldWidth() {
1029
1030            return m_variableFieldWidth;
1031        }
1032
1033        /**
1034         * Check whether the specifier has a variable
1035         * precision that is going to be set by an
1036         * argument.
1037         * @return <code>true</code> if the conversion
1038         * uses an * precision; otherwise
1039         * <code>false</code>.
1040         */

1041        boolean isVariablePrecision() {
1042
1043            return m_variablePrecision;
1044        }
1045
1046        /**
1047         * Set the field width with an argument. A
1048         * negative field width is taken as a - flag
1049         * followed by a positive field width.
1050         * @param fw the field width.
1051         */

1052        void setFieldWidthWithArg(int fw) {
1053
1054            if (fw < 0) {
1055                m_leftJustify = true;
1056            }
1057            m_fieldWidthSet = true;
1058            m_fieldWidth = Math.abs(fw);
1059        }
1060
1061        /**
1062         * Set the String for this instance.
1063         * @param s the String to store.
1064         */

1065        void setLiteral(String JavaDoc s) {
1066
1067            m_fmt = s;
1068        }
1069
1070        /**
1071         * Set the precision with an argument. A
1072         * negative precision will be changed to zero.
1073         * @param pr the precision.
1074         */

1075        void setPrecisionWithArg(int pr) {
1076
1077            m_precisionSet = true;
1078            m_precision = Math.max(pr, 0);
1079        }
1080
1081        /**
1082         * Apply zero or blank, left or right padding.
1083         * @param ca4 array of characters before padding is
1084         * finished
1085         * @param noDigits NaN or signed Inf
1086         * @return a padded array of characters
1087         */

1088        private char[] applyFloatPadding(char[] ca4, boolean noDigits) {
1089
1090            char[] ca5 = ca4;
1091            if (m_fieldWidthSet) {
1092                int i, j, nBlanks;
1093                if (m_leftJustify) {
1094                    nBlanks = m_fieldWidth - ca4.length;
1095                    if (nBlanks > 0) {
1096                        ca5 = new char[ca4.length + nBlanks];
1097                        for (i = 0; i < ca4.length; i++) {
1098                            ca5[i] = ca4[i];
1099                        }
1100                        for (j = 0; j < nBlanks; j++, i++) {
1101                            ca5[i] = ' ';
1102                        }
1103                    }
1104                } else if (!m_leadingZeros || noDigits) {
1105                    nBlanks = m_fieldWidth - ca4.length;
1106                    if (nBlanks > 0) {
1107                        ca5 = new char[ca4.length + nBlanks];
1108                        for (i = 0; i < nBlanks; i++) {
1109                            ca5[i] = ' ';
1110                        }
1111                        for (j = 0; j < ca4.length; i++, j++) {
1112                            ca5[i] = ca4[j];
1113                        }
1114                    }
1115                } else if (m_leadingZeros) {
1116                    nBlanks = m_fieldWidth - ca4.length;
1117                    if (nBlanks > 0) {
1118                        ca5 = new char[ca4.length + nBlanks];
1119                        i = 0;
1120                        j = 0;
1121                        if (ca4[0] == '-') {
1122                            ca5[0] = '-';
1123                            i++;
1124                            j++;
1125                        }
1126                        for (int k = 0; k < nBlanks; i++, k++) {
1127                            ca5[i] = '0';
1128                        }
1129                        for (; j < ca4.length; i++, j++) {
1130                            ca5[i] = ca4[j];
1131                        }
1132                    }
1133                }
1134            }
1135            return ca5;
1136        }
1137
1138        /**
1139         * Check to see if the digits that are going to
1140         * be truncated because of the precision should
1141         * force a round in the preceding digits.
1142         * @param ca1 the array of digits
1143         * @param icarry the index of the first digit that
1144         * is to be truncated from the print
1145         * @return <code>true</code> if the truncation forces
1146         * a round that will change the print
1147         */

1148        private boolean checkForCarry(char[] ca1, int icarry) {
1149
1150            boolean carry = false;
1151            if (icarry < ca1.length) {
1152                if (ca1[icarry] == '6' || ca1[icarry] == '7' || ca1[icarry] == '8' || ca1[icarry] == '9') {
1153                    carry = true;
1154                } else if (ca1[icarry] == '5') {
1155                    int ii = icarry + 1;
1156                    for (; ii < ca1.length; ii++) {
1157                        if (ca1[ii] != '0') {
1158                            break;
1159                        }
1160                    }
1161                    carry = ii < ca1.length;
1162                    if (!carry && icarry > 0) {
1163                        carry = (ca1[icarry - 1] == '1'
1164                            || ca1[icarry - 1] == '3'
1165                            || ca1[icarry - 1] == '5'
1166                            || ca1[icarry - 1] == '7' || ca1[icarry - 1] == '9');
1167                    }
1168                }
1169            }
1170            return carry;
1171        }
1172
1173        /**
1174         * For e format, the flag character '-', means that
1175         * the output should be left justified within the
1176         * field. The default is to pad with blanks on the
1177         * left. '+' character means that the conversion
1178         * will always begin with a sign (+ or -). The
1179         * blank flag character means that a non-negative
1180         * input will be preceded with a blank. If both a
1181         * '+' and a ' ' are specified, the blank flag is
1182         * ignored. The '0' flag character implies that
1183         * padding to the field width will be done with
1184         * zeros instead of blanks.
1185         *
1186         * The field width is treated as the minimum number
1187         * of characters to be printed. The default is to
1188         * add no padding. Padding is with blanks by
1189         * default.
1190         *
1191         * The precision, if set, is the minimum number of
1192         * digits to appear after the radix character.
1193         * Padding is with trailing 0s.
1194         *
1195         * The behavior is like printf. One (hopefully the
1196         * only) exception is that the minimum number of
1197         * exponent digits is 3 instead of 2 for e and E
1198         * formats when the optional L is used before the
1199         * e, E, g, or G conversion character. The optional
1200         * L does not imply conversion to a long long
1201         * double.
1202         *
1203         * @param x the x parameter
1204         * @param eChar the eChar parameter
1205         * @return the result
1206         */

1207        private char[] eFormatDigits(double x, char eChar) {
1208
1209            char[] ca1, ca2, ca3;
1210            // int defaultDigits=6;
1211
String JavaDoc sx;
1212            int i, j, k, p;
1213            int expon = 0;
1214            int ePos, rPos, eSize;
1215            boolean minusSign = false;
1216            if (x > 0.0) {
1217                sx = Double.toString(x);
1218            } else if (x < 0.0) {
1219                sx = Double.toString(-x);
1220                minusSign = true;
1221            } else {
1222                sx = Double.toString(x);
1223                if (sx.charAt(0) == '-') {
1224                    minusSign = true;
1225                    sx = sx.substring(1);
1226                }
1227            }
1228            ePos = sx.indexOf('E');
1229            if (ePos == -1) {
1230                ePos = sx.indexOf('e');
1231            }
1232            rPos = sx.indexOf('.');
1233            if (ePos != -1) {
1234                int ie = ePos + 1;
1235                expon = 0;
1236                if (sx.charAt(ie) == '-') {
1237                    for (++ie; ie < sx.length(); ie++) {
1238                        if (sx.charAt(ie) != '0') {
1239                            break;
1240                        }
1241                    }
1242                    if (ie < sx.length()) {
1243                        expon = -Integer.parseInt(sx.substring(ie));
1244                    }
1245                } else {
1246                    if (sx.charAt(ie) == '+') {
1247                        ++ie;
1248                    }
1249                    for (; ie < sx.length(); ie++) {
1250                        if (sx.charAt(ie) != '0') {
1251                            break;
1252                        }
1253                    }
1254                    if (ie < sx.length()) {
1255                        expon = Integer.parseInt(sx.substring(ie));
1256                    }
1257                }
1258            }
1259            if (rPos != -1) {
1260                expon += rPos - 1;
1261            }
1262            if (m_precisionSet) {
1263                p = m_precision;
1264            } else {
1265                p = DEFAULT_DIGITS - 1;
1266            }
1267            if (rPos != -1 && ePos != -1) {
1268                ca1 = (sx.substring(0, rPos) + sx.substring(rPos + 1, ePos)).toCharArray();
1269            } else if (rPos != -1) {
1270                ca1 = (sx.substring(0, rPos) + sx.substring(rPos + 1)).toCharArray();
1271            } else if (ePos != -1) {
1272                ca1 = sx.substring(0, ePos).toCharArray();
1273            } else {
1274                ca1 = sx.toCharArray();
1275            }
1276            boolean carry = false;
1277            int i0 = 0;
1278            if (ca1[0] != '0') {
1279                i0 = 0;
1280            } else {
1281                for (i0 = 0; i0 < ca1.length; i0++) {
1282                    if (ca1[i0] != '0') {
1283                        break;
1284                    }
1285                }
1286            }
1287            if (i0 + p < ca1.length - 1) {
1288                carry = checkForCarry(ca1, i0 + p + 1);
1289                if (carry) {
1290                    carry = startSymbolicCarry(ca1, i0 + p, i0);
1291                }
1292                if (carry) {
1293                    ca2 = new char[i0 + p + 1];
1294                    ca2[i0] = '1';
1295                    for (j = 0; j < i0; j++) {
1296                        ca2[j] = '0';
1297                    }
1298                    for (i = i0, j = i0 + 1; j < p + 1; i++, j++) {
1299                        ca2[j] = ca1[i];
1300                    }
1301                    expon++;
1302                    ca1 = ca2;
1303                }
1304            }
1305            if (Math.abs(expon) < 100 && !m_optionalL) {
1306                eSize = 4;
1307            } else {
1308                eSize = 5;
1309            }
1310            if (m_alternateForm || !m_precisionSet || m_precision != 0) {
1311                ca2 = new char[2 + p + eSize];
1312            } else {
1313                ca2 = new char[1 + eSize];
1314            }
1315            if (ca1[0] != '0') {
1316                ca2[0] = ca1[0];
1317                j = 1;
1318            } else {
1319                for (j = 1; j < (ePos == -1 ? ca1.length : ePos); j++) {
1320                    if (ca1[j] != '0') {
1321                        break;
1322                    }
1323                }
1324                if ((ePos != -1 && j < ePos) || (ePos == -1 && j < ca1.length)) {
1325                    ca2[0] = ca1[j];
1326                    expon -= j;
1327                    j++;
1328                } else {
1329                    ca2[0] = '0';
1330                    j = 2;
1331                }
1332            }
1333            if (m_alternateForm || !m_precisionSet || m_precision != 0) {
1334                ca2[1] = '.';
1335                i = 2;
1336            } else {
1337                i = 1;
1338            }
1339            for (k = 0; k < p && j < ca1.length; j++, i++, k++) {
1340                ca2[i] = ca1[j];
1341            }
1342            for (; i < ca2.length - eSize; i++) {
1343                ca2[i] = '0';
1344            }
1345            ca2[i++] = eChar;
1346            if (expon < 0) {
1347                ca2[i++] = '-';
1348            } else {
1349                ca2[i++] = '+';
1350            }
1351            expon = Math.abs(expon);
1352            if (expon >= 100) {
1353                switch (expon / 100) {
1354                    case 1:
1355                        ca2[i] = '1';
1356                        break;
1357                    case 2:
1358                        ca2[i] = '2';
1359                        break;
1360                    case 3:
1361                        ca2[i] = '3';
1362                        break;
1363                    case 4:
1364                        ca2[i] = '4';
1365                        break;
1366                    case 5:
1367                        ca2[i] = '5';
1368                        break;
1369                    case 6:
1370                        ca2[i] = '6';
1371                        break;
1372                    case 7:
1373                        ca2[i] = '7';
1374                        break;
1375                    case 8:
1376                        ca2[i] = '8';
1377                        break;
1378                    case 9:
1379                        ca2[i] = '9';
1380                        break;
1381                    default:
1382                // noop
1383
}
1384                i++;
1385            }
1386            switch ((expon % 100) / 10) {
1387                case 0:
1388                    ca2[i] = '0';
1389                    break;
1390                case 1:
1391                    ca2[i] = '1';
1392                    break;
1393                case 2:
1394                    ca2[i] = '2';
1395                    break;
1396                case 3:
1397                    ca2[i] = '3';
1398                    break;
1399                case 4:
1400                    ca2[i] = '4';
1401                    break;
1402                case 5:
1403                    ca2[i] = '5';
1404                    break;
1405                case 6:
1406                    ca2[i] = '6';
1407                    break;
1408                case 7:
1409                    ca2[i] = '7';
1410                    break;
1411                case 8:
1412                    ca2[i] = '8';
1413                    break;
1414                case 9:
1415                    ca2[i] = '9';
1416                    break;
1417                default:
1418            // noop
1419
}
1420            i++;
1421            switch (expon % 10) {
1422                case 0:
1423                    ca2[i] = '0';
1424                    break;
1425                case 1:
1426                    ca2[i] = '1';
1427                    break;
1428                case 2:
1429                    ca2[i] = '2';
1430                    break;
1431                case 3:
1432                    ca2[i] = '3';
1433                    break;
1434                case 4:
1435                    ca2[i] = '4';
1436                    break;
1437                case 5:
1438                    ca2[i] = '5';
1439                    break;
1440                case 6:
1441                    ca2[i] = '6';
1442                    break;
1443                case 7:
1444                    ca2[i] = '7';
1445                    break;
1446                case 8:
1447                    ca2[i] = '8';
1448                    break;
1449                case 9:
1450                    ca2[i] = '9';
1451                    break;
1452                default:
1453            // noop
1454
}
1455            int nZeros = 0;
1456            if (!m_leftJustify && m_leadingZeros) {
1457                int xThousands = 0;
1458                if (m_thousands) {
1459                    int xlead = 0;
1460                    if (ca2[0] == '+' || ca2[0] == '-' || ca2[0] == ' ') {
1461                        xlead = 1;
1462                    }
1463                    int xdp = xlead;
1464                    for (; xdp < ca2.length; xdp++) {
1465                        if (ca2[xdp] == '.') {
1466                            break;
1467                        }
1468                    }
1469                    xThousands = (xdp - xlead) / 3;
1470                }
1471                if (m_fieldWidthSet) {
1472                    nZeros = m_fieldWidth - ca2.length;
1473                }
1474                if ((!minusSign && (m_leadingSign || m_leadingSpace)) || minusSign) {
1475                    nZeros--;
1476                }
1477                nZeros -= xThousands;
1478                if (nZeros < 0) {
1479                    nZeros = 0;
1480                }
1481            }
1482            j = 0;
1483            if ((!minusSign && (m_leadingSign || m_leadingSpace)) || minusSign) {
1484                ca3 = new char[ca2.length + nZeros + 1];
1485                j++;
1486            } else {
1487                ca3 = new char[ca2.length + nZeros];
1488            }
1489            if (!minusSign) {
1490                if (m_leadingSign) {
1491                    ca3[0] = '+';
1492                }
1493                if (m_leadingSpace) {
1494                    ca3[0] = ' ';
1495                }
1496            } else {
1497                ca3[0] = '-';
1498            }
1499            for (k = 0; k < nZeros; j++, k++) {
1500                ca3[j] = '0';
1501            }
1502            for (i = 0; i < ca2.length && j < ca3.length; i++, j++) {
1503                ca3[j] = ca2[i];
1504            }
1505
1506            int lead = 0;
1507            if (ca3[0] == '+' || ca3[0] == '-' || ca3[0] == ' ') {
1508                lead = 1;
1509            }
1510            int dp = lead;
1511            for (; dp < ca3.length; dp++) {
1512                if (ca3[dp] == '.') {
1513                    break;
1514                }
1515            }
1516            int nThousands = dp / 3;
1517            // Localize the decimal point.
1518
if (dp < ca3.length) {
1519                ca3[dp] = m_dfs.getDecimalSeparator();
1520            }
1521            char[] ca4 = ca3;
1522            if (m_thousands && nThousands > 0) {
1523                ca4 = new char[ca3.length + nThousands + lead];
1524                ca4[0] = ca3[0];
1525                for (i = lead, k = lead; i < dp; i++) {
1526                    if (i > 0 && (dp - i) % 3 == 0) {
1527                        // ca4[k]=',';
1528
ca4[k] = m_dfs.getGroupingSeparator();
1529                        ca4[k + 1] = ca3[i];
1530                        k += 2;
1531                    } else {
1532                        ca4[k] = ca3[i];
1533                        k++;
1534                    }
1535                }
1536                for (; i < ca3.length; i++, k++) {
1537                    ca4[k] = ca3[i];
1538                }
1539            }
1540            return ca4;
1541        }
1542
1543        /**
1544         * An intermediate routine on the way to creating
1545         * an e format String. The method decides whether
1546         * the input double value is an infinity,
1547         * not-a-number, or a finite double and formats
1548         * each type of input appropriately.
1549         * @param x the double value to be formatted.
1550         * @param eChar an 'e' or 'E' to use in the
1551         * converted double value.
1552         * @return the converted double value.
1553         */

1554        private String JavaDoc eFormatString(double x, char eChar) {
1555
1556            char[] ca4, ca5;
1557            if (Double.isInfinite(x)) {
1558                if (x == Double.POSITIVE_INFINITY) {
1559                    if (m_leadingSign) {
1560                        ca4 = "+Inf".toCharArray();
1561                    } else if (m_leadingSpace) {
1562                        ca4 = " Inf".toCharArray();
1563                    } else {
1564                        ca4 = "Inf".toCharArray();
1565                    }
1566                } else {
1567                    ca4 = "-Inf".toCharArray();
1568                }
1569            } else if (Double.isNaN(x)) {
1570                if (m_leadingSign) {
1571                    ca4 = "+NaN".toCharArray();
1572                } else if (m_leadingSpace) {
1573                    ca4 = " NaN".toCharArray();
1574                } else {
1575                    ca4 = "NaN".toCharArray();
1576                }
1577            } else {
1578                ca4 = eFormatDigits(x, eChar);
1579            }
1580            ca5 = applyFloatPadding(ca4, false);
1581            return new String JavaDoc(ca5);
1582        }
1583
1584        /**
1585         * For f format, the flag character '-', means that
1586         * the output should be left justified within the
1587         * field. The default is to pad with blanks on the
1588         * left. '+' character means that the conversion
1589         * will always begin with a sign (+ or -). The
1590         * blank flag character means that a non-negative
1591         * input will be preceded with a blank. If both
1592         * a '+' and a ' ' are specified, the blank flag
1593         * is ignored. The '0' flag character implies that
1594         * padding to the field width will be done with
1595         * zeros instead of blanks.
1596         *
1597         * The field width is treated as the minimum number
1598         * of characters to be printed. The default is to
1599         * add no padding. Padding is with blanks by
1600         * default.
1601         *
1602         * The precision, if set, is the number of digits
1603         * to appear after the radix character. Padding is
1604         * with trailing 0s.
1605         *
1606         * @param x the paramater
1607         * @return the result
1608         */

1609        private char[] fFormatDigits(double x) {
1610
1611            // int defaultDigits=6;
1612
String JavaDoc sx;
1613            int i, j, k;
1614            int n1In, n2In;
1615            int expon = 0;
1616            boolean minusSign = false;
1617            if (x > 0.0) {
1618                sx = Double.toString(x);
1619            } else if (x < 0.0) {
1620                sx = Double.toString(-x);
1621                minusSign = true;
1622            } else {
1623                sx = Double.toString(x);
1624                if (sx.charAt(0) == '-') {
1625                    minusSign = true;
1626                    sx = sx.substring(1);
1627                }
1628            }
1629            int ePos = sx.indexOf('E');
1630            int rPos = sx.indexOf('.');
1631            if (rPos != -1) {
1632                n1In = rPos;
1633            } else if (ePos != -1) {
1634                n1In = ePos;
1635            } else {
1636                n1In = sx.length();
1637            }
1638            if (rPos != -1) {
1639                if (ePos != -1) {
1640                    n2In = ePos - rPos - 1;
1641                } else {
1642                    n2In = sx.length() - rPos - 1;
1643                }
1644            } else {
1645                n2In = 0;
1646            }
1647            if (ePos != -1) {
1648                int ie = ePos + 1;
1649                expon = 0;
1650                if (sx.charAt(ie) == '-') {
1651                    for (++ie; ie < sx.length(); ie++) {
1652                        if (sx.charAt(ie) != '0') {
1653                            break;
1654                        }
1655                    }
1656                    if (ie < sx.length()) {
1657                        expon = -Integer.parseInt(sx.substring(ie));
1658                    }
1659                } else {
1660                    if (sx.charAt(ie) == '+') {
1661                        ++ie;
1662                    }
1663                    for (; ie < sx.length(); ie++) {
1664                        if (sx.charAt(ie) != '0') {
1665                            break;
1666                        }
1667                    }
1668                    if (ie < sx.length()) {
1669                        expon = Integer.parseInt(sx.substring(ie));
1670                    }
1671                }
1672            }
1673            int p;
1674            if (m_precisionSet) {
1675                p = m_precision;
1676            } else {
1677                p = DEFAULT_DIGITS - 1;
1678            }
1679            char[] ca1 = sx.toCharArray();
1680            char[] ca2 = new char[n1In + n2In];
1681            char[] ca3, ca4, ca5;
1682            for (j = 0; j < n1In; j++) {
1683                ca2[j] = ca1[j];
1684            }
1685            i = j + 1;
1686            for (k = 0; k < n2In; j++, i++, k++) {
1687                ca2[j] = ca1[i];
1688            }
1689            if (n1In + expon <= 0) {
1690                ca3 = new char[-expon + n2In];
1691                for (j = 0, k = 0; k < (-n1In - expon); k++, j++) {
1692                    ca3[j] = '0';
1693                }
1694                for (i = 0; i < (n1In + n2In); i++, j++) {
1695                    ca3[j] = ca2[i];
1696                }
1697            } else {
1698                ca3 = ca2;
1699            }
1700            boolean carry = false;
1701            if (p < -expon + n2In) {
1702                if (expon < 0) {
1703                    i = p;
1704                } else {
1705                    i = p + n1In;
1706                }
1707                carry = checkForCarry(ca3, i);
1708                if (carry) {
1709                    carry = startSymbolicCarry(ca3, i - 1, 0);
1710                }
1711            }
1712            if (n1In + expon <= 0) {
1713                ca4 = new char[2 + p];
1714                if (!carry) {
1715                    ca4[0] = '0';
1716                } else {
1717                    ca4[0] = '1';
1718                }
1719                if (m_alternateForm || !m_precisionSet || m_precision != 0) {
1720                    ca4[1] = '.';
1721                    for (i = 0, j = 2; i < Math.min(p, ca3.length); i++, j++) {
1722                        ca4[j] = ca3[i];
1723                    }
1724                    for (; j < ca4.length; j++) {
1725                        ca4[j] = '0';
1726                    }
1727                }
1728            } else {
1729                if (!carry) {
1730                    if (m_alternateForm || !m_precisionSet || m_precision != 0) {
1731                        ca4 = new char[n1In + expon + p + 1];
1732                    } else {
1733                        ca4 = new char[n1In + expon];
1734                    }
1735                    j = 0;
1736                } else {
1737                    if (m_alternateForm || !m_precisionSet || m_precision != 0) {
1738                        ca4 = new char[n1In + expon + p + 2];
1739                    } else {
1740                        ca4 = new char[n1In + expon + 1];
1741                    }
1742                    ca4[0] = '1';
1743                    j = 1;
1744                }
1745                for (i = 0; i < Math.min(n1In + expon, ca3.length); i++, j++) {
1746                    ca4[j] = ca3[i];
1747                }
1748                for (; i < n1In + expon; i++, j++) {
1749                    ca4[j] = '0';
1750                }
1751                if (m_alternateForm || !m_precisionSet || m_precision != 0) {
1752                    ca4[j] = '.';
1753                    j++;
1754                    for (k = 0; i < ca3.length && k < p; i++, j++, k++) {
1755                        ca4[j] = ca3[i];
1756                    }
1757                    for (; j < ca4.length; j++) {
1758                        ca4[j] = '0';
1759                    }
1760                }
1761            }
1762            int nZeros = 0;
1763            if (!m_leftJustify && m_leadingZeros) {
1764                int xThousands = 0;
1765                if (m_thousands) {
1766                    int xlead = 0;
1767                    if (ca4[0] == '+' || ca4[0] == '-' || ca4[0] == ' ') {
1768                        xlead = 1;
1769                    }
1770                    int xdp = xlead;
1771                    for (; xdp < ca4.length; xdp++) {
1772                        if (ca4[xdp] == '.') {
1773                            break;
1774                        }
1775                    }
1776                    xThousands = (xdp - xlead) / 3;
1777                }
1778                if (m_fieldWidthSet) {
1779                    nZeros = m_fieldWidth - ca4.length;
1780                }
1781                if ((!minusSign && (m_leadingSign || m_leadingSpace)) || minusSign) {
1782                    nZeros--;
1783                }
1784                nZeros -= xThousands;
1785                if (nZeros < 0) {
1786                    nZeros = 0;
1787                }
1788            }
1789            j = 0;
1790            if ((!minusSign && (m_leadingSign || m_leadingSpace)) || minusSign) {
1791                ca5 = new char[ca4.length + nZeros + 1];
1792                j++;
1793            } else {
1794                ca5 = new char[ca4.length + nZeros];
1795            }
1796            if (!minusSign) {
1797                if (m_leadingSign) {
1798                    ca5[0] = '+';
1799                }
1800                if (m_leadingSpace) {
1801                    ca5[0] = ' ';
1802                }
1803            } else {
1804                ca5[0] = '-';
1805            }
1806            for (i = 0; i < nZeros; i++, j++) {
1807                ca5[j] = '0';
1808            }
1809            for (i = 0; i < ca4.length; i++, j++) {
1810                ca5[j] = ca4[i];
1811            }
1812            int lead = 0;
1813            if (ca5[0] == '+' || ca5[0] == '-' || ca5[0] == ' ') {
1814                lead = 1;
1815            }
1816            int dp = lead;
1817            for (; dp < ca5.length; dp++) {
1818                if (ca5[dp] == '.') {
1819                    break;
1820                }
1821            }
1822            int nThousands = (dp - lead) / 3;
1823            // Localize the decimal point.
1824
if (dp < ca5.length) {
1825                ca5[dp] = m_dfs.getDecimalSeparator();
1826            }
1827            char[] ca6 = ca5;
1828            if (m_thousands && nThousands > 0) {
1829                ca6 = new char[ca5.length + nThousands + lead];
1830                ca6[0] = ca5[0];
1831                for (i = lead, k = lead; i < dp; i++) {
1832                    if (i > 0 && (dp - i) % 3 == 0) {
1833                        // ca6[k]=',';
1834
ca6[k] = m_dfs.getGroupingSeparator();
1835                        ca6[k + 1] = ca5[i];
1836                        k += 2;
1837                    } else {
1838                        ca6[k] = ca5[i];
1839                        k++;
1840                    }
1841                }
1842                for (; i < ca5.length; i++, k++) {
1843                    ca6[k] = ca5[i];
1844                }
1845            }
1846            return ca6;
1847        }
1848
1849        /**
1850         * An intermediate routine on the way to creating
1851         * an f format String. The method decides whether
1852         * the input double value is an infinity,
1853         * not-a-number, or a finite double and formats
1854         * each type of input appropriately.
1855         * @param x the double value to be formatted.
1856         * @return the converted double value.
1857         */

1858        private String JavaDoc fFormatString(double x) {
1859
1860            char[] ca6, ca7;
1861            if (Double.isInfinite(x)) {
1862                if (x == Double.POSITIVE_INFINITY) {
1863                    if (m_leadingSign) {
1864                        ca6 = "+Inf".toCharArray();
1865                    } else if (m_leadingSpace) {
1866                        ca6 = " Inf".toCharArray();
1867                    } else {
1868                        ca6 = "Inf".toCharArray();
1869                    }
1870                } else {
1871                    ca6 = "-Inf".toCharArray();
1872                }
1873            } else if (Double.isNaN(x)) {
1874                if (m_leadingSign) {
1875                    ca6 = "+NaN".toCharArray();
1876                } else if (m_leadingSpace) {
1877                    ca6 = " NaN".toCharArray();
1878                } else {
1879                    ca6 = "NaN".toCharArray();
1880                }
1881            } else {
1882                ca6 = fFormatDigits(x);
1883            }
1884            ca7 = applyFloatPadding(ca6, false);
1885            return new String JavaDoc(ca7);
1886        }
1887
1888        /**
1889         * Format method for the c conversion character and
1890         * char argument.
1891         *
1892         * The only flag character that affects c format is
1893         * the '-', meaning that the output should be left
1894         * justified within the field. The default is to
1895         * pad with blanks on the left.
1896         *
1897         * The field width is treated as the minimum number
1898         * of characters to be printed. Padding is with
1899         * blanks by default. The default width is 1.
1900         *
1901         * The precision, if set, is ignored.
1902         * @param x the char to format.
1903         * @return the formatted String.
1904         */

1905        private String JavaDoc printCFormat(char x) {
1906
1907            int nPrint = 1;
1908            int width = m_fieldWidth;
1909            if (!m_fieldWidthSet) {
1910                width = nPrint;
1911            }
1912            char[] ca = new char[width];
1913            int i = 0;
1914            if (m_leftJustify) {
1915                ca[0] = x;
1916                for (i = 1; i <= width - nPrint; i++) {
1917                    ca[i] = ' ';
1918                }
1919            } else {
1920                for (i = 0; i < width - nPrint; i++) {
1921                    ca[i] = ' ';
1922                }
1923                ca[i] = x;
1924            }
1925            return new String JavaDoc(ca);
1926        }
1927
1928        /**
1929         * Format method for the d conversion character and
1930         * int argument.
1931         *
1932         * For d format, the flag character '-', means that
1933         * the output should be left justified within the
1934         * field. The default is to pad with blanks on the
1935         * left. A '+' character means that the conversion
1936         * will always begin with a sign (+ or -). The
1937         * blank flag character means that a non-negative
1938         * input will be preceded with a blank. If both a
1939         * '+' and a ' ' are specified, the blank flag is
1940         * ignored. The '0' flag character implies that
1941         * padding to the field width will be done with
1942         * zeros instead of blanks.
1943         *
1944         * The field width is treated as the minimum number
1945         * of characters to be printed. The default is to
1946         * add no padding. Padding is with blanks by
1947         * default.
1948         *
1949         * The precision, if set, is the minimum number of
1950         * digits to appear. Padding is with leading 0s.
1951         * @param x the int to format.
1952         * @return the formatted String.
1953         */

1954        private String JavaDoc printDFormat(int x) {
1955
1956            return printDFormat(Integer.toString(x));
1957        }
1958
1959        /**
1960         * Format method for the d conversion character and
1961         * long argument.
1962         *
1963         * For d format, the flag character '-', means that
1964         * the output should be left justified within the
1965         * field. The default is to pad with blanks on the
1966         * left. A '+' character means that the conversion
1967         * will always begin with a sign (+ or -). The
1968         * blank flag character means that a non-negative
1969         * input will be preceded with a blank. If both a
1970         * '+' and a ' ' are specified, the blank flag is
1971         * ignored. The '0' flag character implies that
1972         * padding to the field width will be done with
1973         * zeros instead of blanks.
1974         *
1975         * The field width is treated as the minimum number
1976         * of characters to be printed. The default is to
1977         * add no padding. Padding is with blanks by
1978         * default.
1979         *
1980         * The precision, if set, is the minimum number of
1981         * digits to appear. Padding is with leading 0s.
1982         * @param x the long to format.
1983         * @return the formatted String.
1984         */

1985        private String JavaDoc printDFormat(long x) {
1986
1987            return printDFormat(Long.toString(x));
1988        }
1989
1990        /**
1991         * Format method for the d conversion specifer and
1992         * short argument.
1993         *
1994         * For d format, the flag character '-', means that
1995         * the output should be left justified within the
1996         * field. The default is to pad with blanks on the
1997         * left. A '+' character means that the conversion
1998         * will always begin with a sign (+ or -). The
1999         * blank flag character means that a non-negative
2000         * input will be preceded with a blank. If both a
2001         * '+' and a ' ' are specified, the blank flag is
2002         * ignored. The '0' flag character implies that
2003         * padding to the field width will be done with
2004         * zeros instead of blanks.
2005         *
2006         * The field width is treated as the minimum number
2007         * of characters to be printed. The default is to
2008         * add no padding. Padding is with blanks by
2009         * default.
2010         *
2011         * The precision, if set, is the minimum number of
2012         * digits to appear. Padding is with leading 0s.
2013         * @param x the short to format.
2014         * @return the formatted String.
2015         */

2016        private String JavaDoc printDFormat(short x) {
2017
2018            return printDFormat(Short.toString(x));
2019        }
2020
2021        /**
2022         * Utility method for formatting using the d
2023         * conversion character.
2024         * @param sx the String to format, the result of
2025         * converting a short, int, or long to a
2026         * String.
2027         * @return the formatted String.
2028         */

2029        private String JavaDoc printDFormat(String JavaDoc sx) {
2030
2031            int nLeadingZeros = 0;
2032            int nBlanks = 0, n = 0;
2033            int i = 0, jFirst = 0;
2034            boolean neg = sx.charAt(0) == '-';
2035            if (sx.equals("0") && m_precisionSet && m_precision == 0) {
2036                sx = "";
2037            }
2038            if (!neg) {
2039                if (m_precisionSet && sx.length() < m_precision) {
2040                    nLeadingZeros = m_precision - sx.length();
2041                }
2042            } else {
2043                if (m_precisionSet && (sx.length() - 1) < m_precision) {
2044                    nLeadingZeros = m_precision - sx.length() + 1;
2045                }
2046            }
2047            if (nLeadingZeros < 0) {
2048                nLeadingZeros = 0;
2049            }
2050            if (m_fieldWidthSet) {
2051                nBlanks = m_fieldWidth - nLeadingZeros - sx.length();
2052                if (!neg && (m_leadingSign || m_leadingSpace)) {
2053                    nBlanks--;
2054                }
2055            }
2056            if (nBlanks < 0) {
2057                nBlanks = 0;
2058            }
2059            if (m_leadingSign) {
2060                n++;
2061            } else if (m_leadingSpace) {
2062                n++;
2063            }
2064            n += nBlanks;
2065            n += nLeadingZeros;
2066            n += sx.length();
2067            char[] ca = new char[n];
2068            if (m_leftJustify) {
2069                if (neg) {
2070                    ca[i++] = '-';
2071                } else if (m_leadingSign) {
2072                    ca[i++] = '+';
2073                } else if (m_leadingSpace) {
2074                    ca[i++] = ' ';
2075                }
2076                char[] csx = sx.toCharArray();
2077                jFirst = neg ? 1 : 0;
2078                for (int j = 0; j < nLeadingZeros; i++, j++) {
2079                    ca[i] = '0';
2080                }
2081                for (int j = jFirst; j < csx.length; j++, i++) {
2082                    ca[i] = csx[j];
2083                }
2084                for (int j = 0; j < nBlanks; i++, j++) {
2085                    ca[i] = ' ';
2086                }
2087            } else {
2088                if (!m_leadingZeros) {
2089                    for (i = 0; i < nBlanks; i++) {
2090                        ca[i] = ' ';
2091                    }
2092                    if (neg) {
2093                        ca[i++] = '-';
2094                    } else if (m_leadingSign) {
2095                        ca[i++] = '+';
2096                    } else if (m_leadingSpace) {
2097                        ca[i++] = ' ';
2098                    }
2099                } else {
2100                    if (neg) {
2101                        ca[i++] = '-';
2102                    } else if (m_leadingSign) {
2103                        ca[i++] = '+';
2104                    } else if (m_leadingSpace) {
2105                        ca[i++] = ' ';
2106                    }
2107                    for (int j = 0; j < nBlanks; j++, i++) {
2108                        ca[i] = '0';
2109                    }
2110                }
2111                for (int j = 0; j < nLeadingZeros; j++, i++) {
2112                    ca[i] = '0';
2113                }
2114                char[] csx = sx.toCharArray();
2115                jFirst = neg ? 1 : 0;
2116                for (int j = jFirst; j < csx.length; j++, i++) {
2117                    ca[i] = csx[j];
2118                }
2119            }
2120            return new String JavaDoc(ca);
2121        }
2122
2123        /**
2124         * Format method for the e or E conversion
2125         * character.
2126         * @param x the double to format.
2127         * @return the formatted String.
2128         */

2129        private String JavaDoc printEFormat(double x) {
2130
2131            if (m_conversionCharacter == 'e') {
2132                return eFormatString(x, 'e');
2133            } else {
2134                return eFormatString(x, 'E');
2135            }
2136        }
2137
2138        /**
2139         * Format method for the f conversion character.
2140         * @param x the double to format.
2141         * @return the formatted String.
2142         */

2143        private String JavaDoc printFFormat(double x) {
2144
2145            return fFormatString(x);
2146        }
2147
2148        /**
2149         * Format method for the g conversion character.
2150         *
2151         * For g format, the flag character '-', means that
2152         * the output should be left justified within the
2153         * field. The default is to pad with blanks on the
2154         * left. '+' character means that the conversion
2155         * will always begin with a sign (+ or -). The
2156         * blank flag character means that a non-negative
2157         * input will be preceded with a blank. If both a
2158         * '+' and a ' ' are specified, the blank flag is
2159         * ignored. The '0' flag character implies that
2160         * padding to the field width will be done with
2161         * zeros instead of blanks.
2162         *
2163         * The field width is treated as the minimum number
2164         * of characters to be printed. The default is to
2165         * add no padding. Padding is with blanks by
2166         * default.
2167         *
2168         * The precision, if set, is the minimum number of
2169         * digits to appear after the radix character.
2170         * Padding is with trailing 0s.
2171         * @param x the double to format.
2172         * @return the formatted String.
2173         */

2174        private String JavaDoc printGFormat(double x) {
2175
2176            String JavaDoc sx, sy, sz, ret;
2177            int savePrecision = m_precision;
2178            int i;
2179            char[] ca4, ca5;
2180            if (Double.isInfinite(x)) {
2181                if (x == Double.POSITIVE_INFINITY) {
2182                    if (m_leadingSign) {
2183                        ca4 = "+Inf".toCharArray();
2184                    } else if (m_leadingSpace) {
2185                        ca4 = " Inf".toCharArray();
2186                    } else {
2187                        ca4 = "Inf".toCharArray();
2188                    }
2189                } else {
2190                    ca4 = "-Inf".toCharArray();
2191                }
2192            } else if (Double.isNaN(x)) {
2193                if (m_leadingSign) {
2194                    ca4 = "+NaN".toCharArray();
2195                } else if (m_leadingSpace) {
2196                    ca4 = " NaN".toCharArray();
2197                } else {
2198                    ca4 = "NaN".toCharArray();
2199                }
2200            } else {
2201                if (!m_precisionSet) {
2202                    m_precision = DEFAULT_DIGITS;
2203                }
2204                if (m_precision == 0) {
2205                    m_precision = 1;
2206                }
2207                int ePos = -1;
2208                if (m_conversionCharacter == 'g') {
2209                    sx = eFormatString(x, 'e').trim();
2210                    ePos = sx.indexOf('e');
2211                } else {
2212                    sx = eFormatString(x, 'E').trim();
2213                    ePos = sx.indexOf('E');
2214                }
2215                i = ePos + 1;
2216                int expon = 0;
2217                if (sx.charAt(i) == '-') {
2218                    for (++i; i < sx.length(); i++) {
2219                        if (sx.charAt(i) != '0') {
2220                            break;
2221                        }
2222                    }
2223                    if (i < sx.length()) {
2224                        expon = -Integer.parseInt(sx.substring(i));
2225                    }
2226                } else {
2227                    if (sx.charAt(i) == '+') {
2228                        ++i;
2229                    }
2230                    for (; i < sx.length(); i++) {
2231                        if (sx.charAt(i) != '0') {
2232                            break;
2233                        }
2234                    }
2235                    if (i < sx.length()) {
2236                        expon = Integer.parseInt(sx.substring(i));
2237                    }
2238                }
2239                // Trim trailing zeros.
2240
// If the radix character is not followed by
2241
// a digit, trim it, too.
2242
if (!m_alternateForm) {
2243                    if (expon >= -4 && expon < m_precision) {
2244                        sy = fFormatString(x).trim();
2245                    } else {
2246                        sy = sx.substring(0, ePos);
2247                    }
2248                    i = sy.length() - 1;
2249                    for (; i >= 0; i--) {
2250                        if (sy.charAt(i) != '0') {
2251                            break;
2252                        }
2253                    }
2254                    if (i >= 0 && sy.charAt(i) == '.') {
2255                        i--;
2256                    }
2257                    if (i == -1) {
2258                        sz = "0";
2259                    } else if (!Character.isDigit(sy.charAt(i))) {
2260                        sz = sy.substring(0, i + 1) + "0";
2261                    } else {
2262                        sz = sy.substring(0, i + 1);
2263                    }
2264                    if (expon >= -4 && expon < m_precision) {
2265                        ret = sz;
2266                    } else {
2267                        ret = sz + sx.substring(ePos);
2268                    }
2269                } else {
2270                    if (expon >= -4 && expon < m_precision) {
2271                        ret = fFormatString(x).trim();
2272                    } else {
2273                        ret = sx;
2274                    }
2275                }
2276                // leading space was trimmed off during
2277
// construction
2278
if (m_leadingSpace) {
2279                    if (x >= 0) {
2280                        ret = " " + ret;
2281                    }
2282                }
2283                ca4 = ret.toCharArray();
2284            }
2285            // Pad with blanks or zeros.
2286
ca5 = applyFloatPadding(ca4, false);
2287            m_precision = savePrecision;
2288            return new String JavaDoc(ca5);
2289        }
2290
2291        /**
2292         * Format method for the o conversion character and
2293         * int argument.
2294         *
2295         * For o format, the flag character '-', means that
2296         * the output should be left justified within the
2297         * field. The default is to pad with blanks on the
2298         * left. The '#' flag character means that the
2299         * output begins with a leading 0 and the precision
2300         * is increased by 1.
2301         *
2302         * The field width is treated as the minimum number
2303         * of characters to be printed. The default is to
2304         * add no padding. Padding is with blanks by
2305         * default.
2306         *
2307         * The precision, if set, is the minimum number of
2308         * digits to appear. Padding is with leading 0s.
2309         * @param x the int to format.
2310         * @return the formatted String.
2311         */

2312        private String JavaDoc printOFormat(int x) {
2313
2314            String JavaDoc sx = null;
2315            if (x == Integer.MIN_VALUE) {
2316                sx = "20000000000";
2317            } else if (x < 0) {
2318                String JavaDoc t = Integer.toString((~(-x - 1)) ^ Integer.MIN_VALUE, 8);
2319                switch (t.length()) {
2320                    case 1:
2321                        sx = "2000000000" + t;
2322                        break;
2323                    case 2:
2324                        sx = "200000000" + t;
2325                        break;
2326                    case 3:
2327                        sx = "20000000" + t;
2328                        break;
2329                    case 4:
2330                        sx = "2000000" + t;
2331                        break;
2332                    case 5:
2333                        sx = "200000" + t;
2334                        break;
2335                    case 6:
2336                        sx = "20000" + t;
2337                        break;
2338                    case 7:
2339                        sx = "2000" + t;
2340                        break;
2341                    case 8:
2342                        sx = "200" + t;
2343                        break;
2344                    case 9:
2345                        sx = "20" + t;
2346                        break;
2347                    case 10:
2348                        sx = "2" + t;
2349                        break;
2350                    case 11:
2351                        sx = "3" + t.substring(1);
2352                        break;
2353                    default:
2354                // noop
2355
}
2356            } else {
2357                sx = Integer.toString(x, 8);
2358            }
2359            return printOFormat(sx);
2360        }
2361
2362        /**
2363         * Format method for the o conversion character and
2364         * long argument.
2365         *
2366         * For o format, the flag character '-', means that
2367         * the output should be left justified within the
2368         * field. The default is to pad with blanks on the
2369         * left. The '#' flag character means that the
2370         * output begins with a leading 0 and the precision
2371         * is increased by 1.
2372         *
2373         * The field width is treated as the minimum number
2374         * of characters to be printed. The default is to
2375         * add no padding. Padding is with blanks by
2376         * default.
2377         *
2378         * The precision, if set, is the minimum number of
2379         * digits to appear. Padding is with leading 0s.
2380         * @param x the long to format.
2381         * @return the formatted String.
2382         */

2383        private String JavaDoc printOFormat(long x) {
2384
2385            String JavaDoc sx = null;
2386            if (x == Long.MIN_VALUE) {
2387                sx = "1000000000000000000000";
2388            } else if (x < 0) {
2389                String JavaDoc t = Long.toString((~(-x - 1)) ^ Long.MIN_VALUE, 8);
2390                switch (t.length()) {
2391                    case 1:
2392                        sx = "100000000000000000000" + t;
2393                        break;
2394                    case 2:
2395                        sx = "10000000000000000000" + t;
2396                        break;
2397                    case 3:
2398                        sx = "1000000000000000000" + t;
2399                        break;
2400                    case 4:
2401                        sx = "100000000000000000" + t;
2402                        break;
2403                    case 5:
2404                        sx = "10000000000000000" + t;
2405                        break;
2406                    case 6:
2407                        sx = "1000000000000000" + t;
2408                        break;
2409                    case 7:
2410                        sx = "100000000000000" + t;
2411                        break;
2412                    case 8:
2413                        sx = "10000000000000" + t;
2414                        break;
2415                    case 9:
2416                        sx = "1000000000000" + t;
2417                        break;
2418                    case 10:
2419                        sx = "100000000000" + t;
2420                        break;
2421                    case 11:
2422                        sx = "10000000000" + t;
2423                        break;
2424                    case 12:
2425                        sx = "1000000000" + t;
2426                        break;
2427                    case 13:
2428                        sx = "100000000" + t;
2429                        break;
2430                    case 14:
2431                        sx = "10000000" + t;
2432                        break;
2433                    case 15:
2434                        sx = "1000000" + t;
2435                        break;
2436                    case 16:
2437                        sx = "100000" + t;
2438                        break;
2439                    case 17:
2440                        sx = "10000" + t;
2441                        break;
2442                    case 18:
2443                        sx = "1000" + t;
2444                        break;
2445                    case 19:
2446                        sx = "100" + t;
2447                        break;
2448                    case 20:
2449                        sx = "10" + t;
2450                        break;
2451                    case 21:
2452                        sx = "1" + t;
2453                        break;
2454                    default:
2455                // noop
2456
}
2457            } else {
2458                sx = Long.toString(x, 8);
2459            }
2460            return printOFormat(sx);
2461        }
2462
2463        /**
2464         * Format method for the o conversion character and
2465         * short argument.
2466         *
2467         * For o format, the flag character '-', means that
2468         * the output should be left justified within the
2469         * field. The default is to pad with blanks on the
2470         * left. The '#' flag character means that the
2471         * output begins with a leading 0 and the precision
2472         * is increased by 1.
2473         *
2474         * The field width is treated as the minimum number
2475         * of characters to be printed. The default is to
2476         * add no padding. Padding is with blanks by
2477         * default.
2478         *
2479         * The precision, if set, is the minimum number of
2480         * digits to appear. Padding is with leading 0s.
2481         * @param x the short to format.
2482         * @return the formatted String.
2483         */

2484        private String JavaDoc printOFormat(short x) {
2485
2486            String JavaDoc sx = null;
2487            if (x == Short.MIN_VALUE) {
2488                sx = "100000";
2489            } else if (x < 0) {
2490                String JavaDoc t = Integer.toString((~(-x - 1)) ^ Short.MIN_VALUE, 8);
2491                switch (t.length()) {
2492                    case 1:
2493                        sx = "10000" + t;
2494                        break;
2495                    case 2:
2496                        sx = "1000" + t;
2497                        break;
2498                    case 3:
2499                        sx = "100" + t;
2500                        break;
2501                    case 4:
2502                        sx = "10" + t;
2503                        break;
2504                    case 5:
2505                        sx = "1" + t;
2506                        break;
2507                    default:
2508                // noop
2509
}
2510            } else {
2511                sx = Integer.toString(x, 8);
2512            }
2513            return printOFormat(sx);
2514        }
2515
2516        /**
2517         * Utility method for formatting using the o
2518         * conversion character.
2519         * @param sx the String to format, the result of
2520         * converting a short, int, or long to a
2521         * String.
2522         * @return the formatted String.
2523         */

2524        private String JavaDoc printOFormat(String JavaDoc sx) {
2525
2526            int nLeadingZeros = 0;
2527            int nBlanks = 0;
2528            if (sx.equals("0") && m_precisionSet && m_precision == 0) {
2529                sx = "";
2530            }
2531            if (m_precisionSet) {
2532                nLeadingZeros = m_precision - sx.length();
2533            }
2534            if (m_alternateForm) {
2535                nLeadingZeros++;
2536            }
2537            if (nLeadingZeros < 0) {
2538                nLeadingZeros = 0;
2539            }
2540            if (m_fieldWidthSet) {
2541                nBlanks = m_fieldWidth - nLeadingZeros - sx.length();
2542            }
2543            if (nBlanks < 0) {
2544                nBlanks = 0;
2545            }
2546            int n = nLeadingZeros + sx.length() + nBlanks;
2547            char[] ca = new char[n];
2548            int i;
2549            if (m_leftJustify) {
2550                for (i = 0; i < nLeadingZeros; i++) {
2551                    ca[i] = '0';
2552                }
2553                char[] csx = sx.toCharArray();
2554                for (int j = 0; j < csx.length; j++, i++) {
2555                    ca[i] = csx[j];
2556                }
2557                for (int j = 0; j < nBlanks; j++, i++) {
2558                    ca[i] = ' ';
2559                }
2560            } else {
2561                if (m_leadingZeros) {
2562                    for (i = 0; i < nBlanks; i++) {
2563                        ca[i] = '0';
2564                    }
2565                } else {
2566                    for (i = 0; i < nBlanks; i++) {
2567                        ca[i] = ' ';
2568                    }
2569                }
2570                for (int j = 0; j < nLeadingZeros; j++, i++) {
2571                    ca[i] = '0';
2572                }
2573                char[] csx = sx.toCharArray();
2574                for (int j = 0; j < csx.length; j++, i++) {
2575                    ca[i] = csx[j];
2576                }
2577            }
2578            return new String JavaDoc(ca);
2579        }
2580
2581        /**
2582         * Format method for the s conversion character and
2583         * String argument.
2584         *
2585         * The only flag character that affects s format is
2586         * the '-', meaning that the output should be left
2587         * justified within the field. The default is to
2588         * pad with blanks on the left.
2589         *
2590         * The field width is treated as the minimum number
2591         * of characters to be printed. The default is the
2592         * smaller of the number of characters in the the
2593         * input and the precision. Padding is with blanks
2594         * by default.
2595         *
2596         * The precision, if set, specifies the maximum
2597         * number of characters to be printed from the
2598         * string. A null digit string is treated
2599         * as a 0. The default is not to set a maximum
2600         * number of characters to be printed.
2601         * @param x the String to format.
2602         * @return the formatted String.
2603         */

2604        private String JavaDoc printSFormat(String JavaDoc x) {
2605
2606            int nPrint = x.length();
2607            int width = m_fieldWidth;
2608            if (m_precisionSet && nPrint > m_precision) {
2609                nPrint = m_precision;
2610            }
2611            if (!m_fieldWidthSet) {
2612                width = nPrint;
2613            }
2614            int n = 0;
2615            if (width > nPrint) {
2616                n += width - nPrint;
2617            }
2618            if (nPrint >= x.length()) {
2619                n += x.length();
2620            } else {
2621                n += nPrint;
2622            }
2623            char[] ca = new char[n];
2624            int i = 0;
2625            if (m_leftJustify) {
2626                if (nPrint >= x.length()) {
2627                    char[] csx = x.toCharArray();
2628                    for (i = 0; i < x.length(); i++) {
2629                        ca[i] = csx[i];
2630                    }
2631                } else {
2632                    char[] csx = x.substring(0, nPrint).toCharArray();
2633                    for (i = 0; i < nPrint; i++) {
2634                        ca[i] = csx[i];
2635                    }
2636                }
2637                for (int j = 0; j < width - nPrint; j++, i++) {
2638                    ca[i] = ' ';
2639                }
2640            } else {
2641                for (i = 0; i < width - nPrint; i++) {
2642                    ca[i] = ' ';
2643                }
2644                if (nPrint >= x.length()) {
2645                    char[] csx = x.toCharArray();
2646                    for (int j = 0; j < x.length(); i++, j++) {
2647                        ca[i] = csx[j];
2648                    }
2649                } else {
2650                    char[] csx = x.substring(0, nPrint).toCharArray();
2651                    for (int j = 0; j < nPrint; i++, j++) {
2652                        ca[i] = csx[j];
2653                    }
2654                }
2655            }
2656            return new String JavaDoc(ca);
2657        }
2658
2659        /**
2660         * Format method for the x conversion character and
2661         * int argument.
2662         *
2663         * For x format, the flag character '-', means that
2664         * the output should be left justified within the
2665         * field. The default is to pad with blanks on the
2666         * left. The '#' flag character means to lead with
2667         * '0x'.
2668         *
2669         * The field width is treated as the minimum number
2670         * of characters to be printed. The default is to
2671         * add no padding. Padding is with blanks by
2672         * default.
2673         *
2674         * The precision, if set, is the minimum number of
2675         * digits to appear. Padding is with leading 0s.
2676         * @param x the int to format.
2677         * @return the formatted String.
2678         */

2679        private String JavaDoc printXFormat(int x) {
2680
2681            String JavaDoc sx = null;
2682            if (x == Integer.MIN_VALUE) {
2683                sx = "80000000";
2684            } else if (x < 0) {
2685                String JavaDoc t = Integer.toString((~(-x - 1)) ^ Integer.MIN_VALUE, 16);
2686                switch (t.length()) {
2687                    case 1:
2688                        sx = "8000000" + t;
2689                        break;
2690                    case 2:
2691                        sx = "800000" + t;
2692                        break;
2693                    case 3:
2694                        sx = "80000" + t;
2695                        break;
2696                    case 4:
2697                        sx = "8000" + t;
2698                        break;
2699                    case 5:
2700                        sx = "800" + t;
2701                        break;
2702                    case 6:
2703                        sx = "80" + t;
2704                        break;
2705                    case 7:
2706                        sx = "8" + t;
2707                        break;
2708                    case 8:
2709                        switch (t.charAt(0)) {
2710                            case '1':
2711                                sx = "9" + t.substring(1, 8);
2712                                break;
2713                            case '2':
2714                                sx = "a" + t.substring(1, 8);
2715                                break;
2716                            case '3':
2717                                sx = "b" + t.substring(1, 8);
2718                                break;
2719                            case '4':
2720                                sx = "c" + t.substring(1, 8);
2721                                break;
2722                            case '5':
2723                                sx = "d" + t.substring(1, 8);
2724                                break;
2725                            case '6':
2726                                sx = "e" + t.substring(1, 8);
2727                                break;
2728                            case '7':
2729                                sx = "f" + t.substring(1, 8);
2730                                break;
2731                            default:
2732                        // noop
2733
}
2734                        break;
2735                    default:
2736                // noop
2737
}
2738            } else {
2739                sx = Integer.toString(x, 16);
2740            }
2741            return printXFormat(sx);
2742        }
2743
2744        /**
2745         * Format method for the x conversion character and
2746         * long argument.
2747         *
2748         * For x format, the flag character '-', means that
2749         * the output should be left justified within the
2750         * field. The default is to pad with blanks on the
2751         * left. The '#' flag character means to lead with
2752         * '0x'.
2753         *
2754         * The field width is treated as the minimum number
2755         * of characters to be printed. The default is to
2756         * add no padding. Padding is with blanks by
2757         * default.
2758         *
2759         * The precision, if set, is the minimum number of
2760         * digits to appear. Padding is with leading 0s.
2761         * @param x the long to format.
2762         * @return the formatted String.
2763         */

2764        private String JavaDoc printXFormat(long x) {
2765
2766            String JavaDoc sx = null;
2767            if (x == Long.MIN_VALUE) {
2768                sx = "8000000000000000";
2769            } else if (x < 0) {
2770                String JavaDoc t = Long.toString((~(-x - 1)) ^ Long.MIN_VALUE, 16);
2771                switch (t.length()) {
2772                    case 1:
2773                        sx = "800000000000000" + t;
2774                        break;
2775                    case 2:
2776                        sx = "80000000000000" + t;
2777                        break;
2778                    case 3:
2779                        sx = "8000000000000" + t;
2780                        break;
2781                    case 4:
2782                        sx = "800000000000" + t;
2783                        break;
2784                    case 5:
2785                        sx = "80000000000" + t;
2786                        break;
2787                    case 6:
2788                        sx = "8000000000" + t;
2789                        break;
2790                    case 7:
2791                        sx = "800000000" + t;
2792                        break;
2793                    case 8:
2794                        sx = "80000000" + t;
2795                        break;
2796                    case 9:
2797                        sx = "8000000" + t;
2798                        break;
2799                    case 10:
2800                        sx = "800000" + t;
2801                        break;
2802                    case 11:
2803                        sx = "80000" + t;
2804                        break;
2805                    case 12:
2806                        sx = "8000" + t;
2807                        break;
2808                    case 13:
2809                        sx = "800" + t;
2810                        break;
2811                    case 14:
2812                        sx = "80" + t;
2813                        break;
2814                    case 15:
2815                        sx = "8" + t;
2816                        break;
2817                    case 16:
2818                        switch (t.charAt(0)) {
2819                            case '1':
2820                                sx = "9" + t.substring(1, 16);
2821                                break;
2822                            case '2':
2823                                sx = "a" + t.substring(1, 16);
2824                                break;
2825                            case '3':
2826                                sx = "b" + t.substring(1, 16);
2827                                break;
2828                            case '4':
2829                                sx = "c" + t.substring(1, 16);
2830                                break;
2831                            case '5':
2832                                sx = "d" + t.substring(1, 16);
2833                                break;
2834                            case '6':
2835                                sx = "e" + t.substring(1, 16);
2836                                break;
2837                            case '7':
2838                                sx = "f" + t.substring(1, 16);
2839                                break;
2840                            default:
2841                        // noop
2842
}
2843                        break;
2844                    default:
2845                // noop
2846
}
2847            } else {
2848                sx = Long.toString(x, 16);
2849            }
2850            return printXFormat(sx);
2851        }
2852
2853        /**
2854         * Format method for the x conversion character and
2855         * short argument.
2856         *
2857         * For x format, the flag character '-', means that
2858         * the output should be left justified within the
2859         * field. The default is to pad with blanks on the
2860         * left. The '#' flag character means to lead with
2861         * '0x'.
2862         *
2863         * The field width is treated as the minimum number
2864         * of characters to be printed. The default is to
2865         * add no padding. Padding is with blanks by
2866         * default.
2867         *
2868         * The precision, if set, is the minimum number of
2869         * digits to appear. Padding is with leading 0s.
2870         * @param x the short to format.
2871         * @return the formatted String.
2872         */

2873        private String JavaDoc printXFormat(short x) {
2874
2875            String JavaDoc sx = null;
2876            if (x == Short.MIN_VALUE) {
2877                sx = "8000";
2878            } else if (x < 0) {
2879                String JavaDoc t;
2880                if (x == Short.MIN_VALUE) {
2881                    t = "0";
2882                } else {
2883                    t = Integer.toString((~(-x - 1)) ^ Short.MIN_VALUE, 16);
2884                    if (t.charAt(0) == 'F' || t.charAt(0) == 'f') {
2885                        t = t.substring(16, 32);
2886                    }
2887                }
2888                switch (t.length()) {
2889                    case 1:
2890                        sx = "800" + t;
2891                        break;
2892                    case 2:
2893                        sx = "80" + t;
2894                        break;
2895                    case 3:
2896                        sx = "8" + t;
2897                        break;
2898                    case 4:
2899                        switch (t.charAt(0)) {
2900                            case '1':
2901                                sx = "9" + t.substring(1, 4);
2902                                break;
2903                            case '2':
2904                                sx = "a" + t.substring(1, 4);
2905                                break;
2906                            case '3':
2907                                sx = "b" + t.substring(1, 4);
2908                                break;
2909                            case '4':
2910                                sx = "c" + t.substring(1, 4);
2911                                break;
2912                            case '5':
2913                                sx = "d" + t.substring(1, 4);
2914                                break;
2915                            case '6':
2916                                sx = "e" + t.substring(1, 4);
2917                                break;
2918                            case '7':
2919                                sx = "f" + t.substring(1, 4);
2920                                break;
2921                            default:
2922                        // noop
2923
}
2924                        break;
2925                    default:
2926                // noop
2927
}
2928            } else {
2929                sx = Integer.toString(x, 16);
2930            }
2931            return printXFormat(sx);
2932        }
2933
2934        /**
2935         * Utility method for formatting using the x
2936         * conversion character.
2937         * @param sx the String to format, the result of
2938         * converting a short, int, or long to a
2939         * String.
2940         * @return the formatted String.
2941         */

2942        private String JavaDoc printXFormat(String JavaDoc sx) {
2943
2944            int nLeadingZeros = 0;
2945            int nBlanks = 0;
2946            if (sx.equals("0") && m_precisionSet && m_precision == 0) {
2947                sx = "";
2948            }
2949            if (m_precisionSet) {
2950                nLeadingZeros = m_precision - sx.length();
2951            }
2952            if (nLeadingZeros < 0) {
2953                nLeadingZeros = 0;
2954            }
2955            if (m_fieldWidthSet) {
2956                nBlanks = m_fieldWidth - nLeadingZeros - sx.length();
2957                if (m_alternateForm) {
2958                    nBlanks = nBlanks - 2;
2959                }
2960            }
2961            if (nBlanks < 0) {
2962                nBlanks = 0;
2963            }
2964            int n = 0;
2965            if (m_alternateForm) {
2966                n += 2;
2967            }
2968            n += nLeadingZeros;
2969            n += sx.length();
2970            n += nBlanks;
2971            char[] ca = new char[n];
2972            int i = 0;
2973            if (m_leftJustify) {
2974                if (m_alternateForm) {
2975                    ca[i++] = '0';
2976                    ca[i++] = 'x';
2977                }
2978                for (int j = 0; j < nLeadingZeros; j++, i++) {
2979                    ca[i] = '0';
2980                }
2981                char[] csx = sx.toCharArray();
2982                for (int j = 0; j < csx.length; j++, i++) {
2983                    ca[i] = csx[j];
2984                }
2985                for (int j = 0; j < nBlanks; j++, i++) {
2986                    ca[i] = ' ';
2987                }
2988            } else {
2989                if (!m_leadingZeros) {
2990                    for (int j = 0; j < nBlanks; j++, i++) {
2991                        ca[i] = ' ';
2992                    }
2993                }
2994                if (m_alternateForm) {
2995                    ca[i++] = '0';
2996                    ca[i++] = 'x';
2997                }
2998                if (m_leadingZeros) {
2999                    for (int j = 0; j < nBlanks; j++, i++) {
3000                        ca[i] = '0';
3001                    }
3002                }
3003                for (int j = 0; j < nLeadingZeros; j++, i++) {
3004                    ca[i] = '0';
3005                }
3006                char[] csx = sx.toCharArray();
3007                for (int j = 0; j < csx.length; j++, i++) {
3008                    ca[i] = csx[j];
3009                }
3010            }
3011            String JavaDoc caReturn = new String JavaDoc(ca);
3012            if (m_conversionCharacter == 'X') {
3013                caReturn = caReturn.toUpperCase();
3014            }
3015            return caReturn;
3016        }
3017
3018        /**
3019         * Store the digits <code>n</code> in %n$ forms.
3020         */

3021        private void setArgPosition() {
3022
3023            int xPos;
3024            for (xPos = m_pos; xPos < m_fmt.length(); xPos++) {
3025                if (!Character.isDigit(m_fmt.charAt(xPos))) {
3026                    break;
3027                }
3028            }
3029            if (xPos > m_pos && xPos < m_fmt.length()) {
3030                if (m_fmt.charAt(xPos) == '$') {
3031                    m_positionalSpecification = true;
3032                    m_argumentPosition = Integer.parseInt(m_fmt.substring(m_pos, xPos));
3033                    m_pos = xPos + 1;
3034                }
3035            }
3036        }
3037
3038        /**
3039         * Check for a conversion character. If it is
3040         * there, store it.
3041         * @return <code>true</code> if the conversion
3042         * character is there, and
3043         * <code>false</code> otherwise.
3044         */

3045        private boolean setConversionCharacter() {
3046
3047            /* idfgGoxXeEcs */
3048            boolean ret = false;
3049            m_conversionCharacter = '\0';
3050            if (m_pos < m_fmt.length()) {
3051                char c = m_fmt.charAt(m_pos);
3052                if (c == 'i'
3053                    || c == 'd'
3054                    || c == 'f'
3055                    || c == 'g'
3056                    || c == 'G'
3057                    || c == 'o'
3058                    || c == 'x'
3059                    || c == 'X'
3060                    || c == 'e'
3061                    || c == 'E'
3062                    || c == 'c'
3063                    || c == 's'
3064                    || c == '%') {
3065                    m_conversionCharacter = c;
3066                    m_pos++;
3067                    ret = true;
3068                }
3069            }
3070            return ret;
3071        }
3072
3073        /**
3074         * Set the field width.
3075         */

3076        private void setFieldWidth() {
3077
3078            int firstPos = m_pos;
3079            m_fieldWidth = 0;
3080            m_fieldWidthSet = false;
3081            if ((m_pos < m_fmt.length()) && (m_fmt.charAt(m_pos) == '*')) {
3082                m_pos++;
3083                if (!setFieldWidthArgPosition()) {
3084                    m_variableFieldWidth = true;
3085                    m_fieldWidthSet = true;
3086                }
3087            } else {
3088                while (m_pos < m_fmt.length()) {
3089                    char c = m_fmt.charAt(m_pos);
3090                    if (Character.isDigit(c)) {
3091                        m_pos++;
3092                    } else {
3093                        break;
3094                    }
3095                }
3096                if (firstPos < m_pos && firstPos < m_fmt.length()) {
3097                    String JavaDoc sz = m_fmt.substring(firstPos, m_pos);
3098                    m_fieldWidth = Integer.parseInt(sz);
3099                    m_fieldWidthSet = true;
3100                }
3101            }
3102        }
3103
3104        /**
3105         * Store the digits <code>n</code> in *n$ forms.
3106         *
3107         * @return the result
3108         */

3109        private boolean setFieldWidthArgPosition() {
3110
3111            boolean ret = false;
3112            int xPos;
3113            for (xPos = m_pos; xPos < m_fmt.length(); xPos++) {
3114                if (!Character.isDigit(m_fmt.charAt(xPos))) {
3115                    break;
3116                }
3117            }
3118            if (xPos > m_pos && xPos < m_fmt.length()) {
3119                if (m_fmt.charAt(xPos) == '$') {
3120                    m_positionalFieldWidth = true;
3121                    m_argumentPositionForFieldWidth = Integer.parseInt(m_fmt.substring(m_pos, xPos));
3122                    m_pos = xPos + 1;
3123                    ret = true;
3124                }
3125            }
3126            return ret;
3127        }
3128
3129        /**
3130         * Set flag characters, one of '-+#0 or a space.
3131         */

3132        private void setFlagCharacters() {
3133
3134            /* '-+ #0 */
3135            m_thousands = false;
3136            m_leftJustify = false;
3137            m_leadingSign = false;
3138            m_leadingSpace = false;
3139            m_alternateForm = false;
3140            m_leadingZeros = false;
3141            for (; m_pos < m_fmt.length(); m_pos++) {
3142                char c = m_fmt.charAt(m_pos);
3143                if (c == '\'') {
3144                    m_thousands = true;
3145                } else if (c == '-') {
3146                    m_leftJustify = true;
3147                    m_leadingZeros = false;
3148                } else if (c == '+') {
3149                    m_leadingSign = true;
3150                    m_leadingSpace = false;
3151                } else if (c == ' ') {
3152                    if (!m_leadingSign) {
3153                        m_leadingSpace = true;
3154                    }
3155                } else if (c == '#') {
3156                    m_alternateForm = true;
3157                } else if (c == '0') {
3158                    if (!m_leftJustify) {
3159                        m_leadingZeros = true;
3160                    }
3161                } else {
3162                    break;
3163                }
3164            }
3165        }
3166
3167        /**
3168         * Check for an h, l, or L in a format. An L is
3169         * used to control the minimum number of digits
3170         * in an exponent when using floating point
3171         * formats. An l or h is used to control
3172         * conversion of the input to a long or short,
3173         * respectively, before formatting. If any of
3174         * these is present, store them.
3175         */

3176        private void setOptionalHL() {
3177
3178            m_optionalh = false;
3179            m_optionall = false;
3180            m_optionalL = false;
3181            if (m_pos < m_fmt.length()) {
3182                char c = m_fmt.charAt(m_pos);
3183                if (c == 'h') {
3184                    m_optionalh = true;
3185                    m_pos++;
3186                } else if (c == 'l') {
3187                    m_optionall = true;
3188                    m_pos++;
3189                } else if (c == 'L') {
3190                    m_optionalL = true;
3191                    m_pos++;
3192                }
3193            }
3194        }
3195
3196        /**
3197         * Set the precision.
3198         */

3199        private void setPrecision() {
3200
3201            int firstPos = m_pos;
3202            m_precisionSet = false;
3203            if (m_pos < m_fmt.length() && m_fmt.charAt(m_pos) == '.') {
3204                m_pos++;
3205                if ((m_pos < m_fmt.length()) && (m_fmt.charAt(m_pos) == '*')) {
3206                    m_pos++;
3207                    if (!setPrecisionArgPosition()) {
3208                        m_variablePrecision = true;
3209                        m_precisionSet = true;
3210                    }
3211                    return;
3212                } else {
3213                    while (m_pos < m_fmt.length()) {
3214                        char c = m_fmt.charAt(m_pos);
3215                        if (Character.isDigit(c)) {
3216                            m_pos++;
3217                        } else {
3218                            break;
3219                        }
3220                    }
3221                    if (m_pos > firstPos + 1) {
3222                        String JavaDoc sz = m_fmt.substring(firstPos + 1, m_pos);
3223                        m_precision = Integer.parseInt(sz);
3224                        m_precisionSet = true;
3225                    }
3226                }
3227            }
3228        }
3229
3230        /**
3231         * Store the digits <code>n</code> in *n$ forms.
3232         *
3233         * @return the result
3234         */

3235        private boolean setPrecisionArgPosition() {
3236
3237            boolean ret = false;
3238            int xPos;
3239            for (xPos = m_pos; xPos < m_fmt.length(); xPos++) {
3240                if (!Character.isDigit(m_fmt.charAt(xPos))) {
3241                    break;
3242                }
3243            }
3244            if (xPos > m_pos && xPos < m_fmt.length()) {
3245                if (m_fmt.charAt(xPos) == '$') {
3246                    m_positionalPrecision = true;
3247                    m_argumentPositionForPrecision = Integer.parseInt(m_fmt.substring(m_pos, xPos));
3248                    m_pos = xPos + 1;
3249                    ret = true;
3250                }
3251            }
3252            return ret;
3253        }
3254
3255        /**
3256         * Start the symbolic carry process. The process
3257         * is not quite finished because the symbolic
3258         * carry may change the length of the string and
3259         * change the exponent (in e format).
3260         * @param cLast index of the last digit changed
3261         * by the round
3262         * @param cFirst index of the first digit allowed
3263         * to be changed by this phase of the round
3264         * @param ca the ca parameter
3265         * @return <code>true</code> if the carry forces
3266         * a round that will change the print still
3267         * more
3268         */

3269        private boolean startSymbolicCarry(char[] ca, int cLast, int cFirst) {
3270
3271            boolean carry = true;
3272            for (int i = cLast; carry && i >= cFirst; i--) {
3273                carry = false;
3274                switch (ca[i]) {
3275                    case '0':
3276                        ca[i] = '1';
3277                        break;
3278                    case '1':
3279                        ca[i] = '2';
3280                        break;
3281                    case '2':
3282                        ca[i] = '3';
3283                        break;
3284                    case '3':
3285                        ca[i] = '4';
3286                        break;
3287                    case '4':
3288                        ca[i] = '5';
3289                        break;
3290                    case '5':
3291                        ca[i] = '6';
3292                        break;
3293                    case '6':
3294                        ca[i] = '7';
3295                        break;
3296                    case '7':
3297                        ca[i] = '8';
3298                        break;
3299                    case '8':
3300                        ca[i] = '9';
3301                        break;
3302                    case '9':
3303                        ca[i] = '0';
3304                        carry = true;
3305                        break;
3306                    default:
3307                // noop
3308
}
3309            }
3310            return carry;
3311        }
3312    }
3313
3314    /** Character position. Used by the constructor. */
3315    DecimalFormatSymbols JavaDoc m_dfs;
3316
3317    /** Character position. Used by the constructor. */
3318    private int m_cPos;
3319
3320    /** Vector of control strings and format literals. */
3321    private Vector JavaDoc m_vFmt = new Vector JavaDoc();
3322
3323    /**
3324     * Constructs an array of control specifications
3325     * possibly preceded, separated, or followed by
3326     * ordinary strings. Control strings begin with
3327     * unpaired percent signs. A pair of successive
3328     * percent signs designates a single percent sign in
3329     * the format.
3330     * @param locale the locale
3331     * @param fmtArg Control string.
3332     * @exception CmsIllegalArgumentException if the control
3333     * string is null, zero length, or otherwise
3334     * malformed.
3335     */

3336    public PrintfFormat(Locale JavaDoc locale, String JavaDoc fmtArg)
3337    throws CmsIllegalArgumentException {
3338
3339        m_dfs = new DecimalFormatSymbols JavaDoc(locale);
3340        int ePos = 0;
3341        ConversionSpecification sFmt = null;
3342        String JavaDoc unCS = this.nonControl(fmtArg, 0);
3343        if (unCS != null) {
3344            sFmt = new ConversionSpecification();
3345            sFmt.setLiteral(unCS);
3346            m_vFmt.addElement(sFmt);
3347        }
3348        while (m_cPos != -1 && m_cPos < fmtArg.length()) {
3349            for (ePos = m_cPos + 1; ePos < fmtArg.length(); ePos++) {
3350                char c = 0;
3351                c = fmtArg.charAt(ePos);
3352                if (c == 'i') {
3353                    break;
3354                }
3355                if (c == 'd') {
3356                    break;
3357                }
3358                if (c == 'f') {
3359                    break;
3360                }
3361                if (c == 'g') {
3362                    break;
3363                }
3364                if (c == 'G') {
3365                    break;
3366                }
3367                if (c == 'o') {
3368                    break;
3369                }
3370                if (c == 'x') {
3371                    break;
3372                }
3373                if (c == 'X') {
3374                    break;
3375                }
3376                if (c == 'e') {
3377                    break;
3378                }
3379                if (c == 'E') {
3380                    break;
3381                }
3382                if (c == 'c') {
3383                    break;
3384                }
3385                if (c == 's') {
3386                    break;
3387                }
3388                if (c == '%') {
3389                    break;
3390                }
3391            }
3392            ePos = Math.min(ePos + 1, fmtArg.length());
3393            sFmt = new ConversionSpecification(fmtArg.substring(m_cPos, ePos));
3394            m_vFmt.addElement(sFmt);
3395            unCS = this.nonControl(fmtArg, ePos);
3396            if (unCS != null) {
3397                sFmt = new ConversionSpecification();
3398                sFmt.setLiteral(unCS);
3399                m_vFmt.addElement(sFmt);
3400            }
3401        }
3402    }
3403
3404    /**
3405     * Constructs an array of control specifications
3406     * possibly preceded, separated, or followed by
3407     * ordinary strings. Control strings begin with
3408     * unpaired percent signs. A pair of successive
3409     * percent signs designates a single percent sign in
3410     * the format.
3411     * @param fmtArg Control string.
3412     * @exception IllegalArgumentException if the control
3413     * string is null, zero length, or otherwise
3414     * malformed.
3415     */

3416    public PrintfFormat(String JavaDoc fmtArg)
3417    throws IllegalArgumentException JavaDoc {
3418
3419        this(Locale.getDefault(), fmtArg);
3420    }
3421
3422    /**
3423     * Format nothing. Just use the control string.
3424     * @return the formatted String.
3425     */

3426    public String JavaDoc sprintf() {
3427
3428        Enumeration JavaDoc e = m_vFmt.elements();
3429        ConversionSpecification cs = null;
3430        char c = 0;
3431        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
3432        while (e.hasMoreElements()) {
3433            cs = (ConversionSpecification)e.nextElement();
3434            c = cs.getConversionCharacter();
3435            if (c == '\0') {
3436                sb.append(cs.getLiteral());
3437            } else if (c == '%') {
3438                sb.append("%");
3439            }
3440        }
3441        return sb.toString();
3442    }
3443
3444    /**
3445     * Format a double.
3446     * @param x The double to format.
3447     * @return The formatted String.
3448     * @exception CmsIllegalArgumentException if the
3449     * conversion character is c, C, s, S,
3450     * d, d, x, X, or o.
3451     */

3452    public String JavaDoc sprintf(double x) throws CmsIllegalArgumentException {
3453
3454        Enumeration JavaDoc e = m_vFmt.elements();
3455        ConversionSpecification cs = null;
3456        char c = 0;
3457        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
3458        while (e.hasMoreElements()) {
3459            cs = (ConversionSpecification)e.nextElement();
3460            c = cs.getConversionCharacter();
3461            if (c == '\0') {
3462                sb.append(cs.getLiteral());
3463            } else if (c == '%') {
3464                sb.append("%");
3465            } else {
3466                sb.append(cs.internalsprintf(x));
3467            }
3468        }
3469        return sb.toString();
3470    }
3471
3472    /**
3473     * Format an int.
3474     * @param x The int to format.
3475     * @return The formatted String.
3476     * @exception CmsIllegalArgumentException if the
3477     * conversion character is f, e, E, g, G, s,
3478     * or S.
3479     */

3480    public String JavaDoc sprintf(int x) throws CmsIllegalArgumentException {
3481
3482        Enumeration JavaDoc e = m_vFmt.elements();
3483        ConversionSpecification cs = null;
3484        char c = 0;
3485        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
3486        while (e.hasMoreElements()) {
3487            cs = (ConversionSpecification)e.nextElement();
3488            c = cs.getConversionCharacter();
3489            if (c == '\0') {
3490                sb.append(cs.getLiteral());
3491            } else if (c == '%') {
3492                sb.append("%");
3493            } else {
3494                sb.append(cs.internalsprintf(x));
3495            }
3496        }
3497        return sb.toString();
3498    }
3499
3500    /**
3501     * Format an long.
3502     * @param x The long to format.
3503     * @return The formatted String.
3504     * @exception CmsIllegalArgumentException if the
3505     * conversion character is f, e, E, g, G, s,
3506     * or S.
3507     */

3508    public String JavaDoc sprintf(long x) throws CmsIllegalArgumentException {
3509
3510        Enumeration JavaDoc e = m_vFmt.elements();
3511        ConversionSpecification cs = null;
3512        char c = 0;
3513        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
3514        while (e.hasMoreElements()) {
3515            cs = (ConversionSpecification)e.nextElement();
3516            c = cs.getConversionCharacter();
3517            if (c == '\0') {
3518                sb.append(cs.getLiteral());
3519            } else if (c == '%') {
3520                sb.append("%");
3521            } else {
3522                sb.append(cs.internalsprintf(x));
3523            }
3524        }
3525        return sb.toString();
3526    }
3527
3528    /**
3529     * Format an Object. Convert wrapper types to
3530     * their primitive equivalents and call the
3531     * appropriate internal formatting method. Convert
3532     * Strings using an internal formatting method for
3533     * Strings. Otherwise use the default formatter
3534     * (use toString).
3535     * @param x the Object to format.
3536     * @return the formatted String.
3537     * @exception CmsIllegalArgumentException if the
3538     * conversion character is inappropriate for
3539     * formatting an unwrapped value.
3540     */

3541    public String JavaDoc sprintf(Object JavaDoc x) throws CmsIllegalArgumentException {
3542
3543        Enumeration JavaDoc e = m_vFmt.elements();
3544        ConversionSpecification cs = null;
3545        char c = 0;
3546        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
3547        while (e.hasMoreElements()) {
3548            cs = (ConversionSpecification)e.nextElement();
3549            c = cs.getConversionCharacter();
3550            if (c == '\0') {
3551                sb.append(cs.getLiteral());
3552            } else if (c == '%') {
3553                sb.append("%");
3554            } else {
3555                if (x instanceof Byte JavaDoc) {
3556                    sb.append(cs.internalsprintf(((Byte JavaDoc)x).byteValue()));
3557                } else if (x instanceof Short JavaDoc) {
3558                    sb.append(cs.internalsprintf(((Short JavaDoc)x).shortValue()));
3559                } else if (x instanceof Integer JavaDoc) {
3560                    sb.append(cs.internalsprintf(((Integer JavaDoc)x).intValue()));
3561                } else if (x instanceof Long JavaDoc) {
3562                    sb.append(cs.internalsprintf(((Long JavaDoc)x).longValue()));
3563                } else if (x instanceof Float JavaDoc) {
3564                    sb.append(cs.internalsprintf(((Float JavaDoc)x).floatValue()));
3565                } else if (x instanceof Double JavaDoc) {
3566                    sb.append(cs.internalsprintf(((Double JavaDoc)x).doubleValue()));
3567                } else if (x instanceof Character JavaDoc) {
3568                    sb.append(cs.internalsprintf(((Character JavaDoc)x).charValue()));
3569                } else if (x instanceof String JavaDoc) {
3570                    sb.append(cs.internalsprintf((String JavaDoc)x));
3571                } else {
3572                    sb.append(cs.internalsprintf(x));
3573                }
3574            }
3575        }
3576        return sb.toString();
3577    }
3578
3579    /**
3580     * Format an array of objects. Byte, Short,
3581     * Integer, Long, Float, Double, and Character
3582     * arguments are treated as wrappers for primitive
3583     * types.
3584     * @param o The array of objects to format.
3585     * @return The formatted String.
3586     */

3587    public String JavaDoc sprintf(Object JavaDoc[] o) {
3588
3589        Enumeration JavaDoc e = m_vFmt.elements();
3590        ConversionSpecification cs = null;
3591        char c = 0;
3592        int i = 0;
3593        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
3594        while (e.hasMoreElements()) {
3595            cs = (ConversionSpecification)e.nextElement();
3596            c = cs.getConversionCharacter();
3597            if (c == '\0') {
3598                sb.append(cs.getLiteral());
3599            } else if (c == '%') {
3600                sb.append("%");
3601            } else {
3602                if (cs.isPositionalSpecification()) {
3603                    i = cs.getArgumentPosition() - 1;
3604                    if (cs.isPositionalFieldWidth()) {
3605                        int ifw = cs.getArgumentPositionForFieldWidth() - 1;
3606                        cs.setFieldWidthWithArg(((Integer JavaDoc)o[ifw]).intValue());
3607                    }
3608                    if (cs.isPositionalPrecision()) {
3609                        int ipr = cs.getArgumentPositionForPrecision() - 1;
3610                        cs.setPrecisionWithArg(((Integer JavaDoc)o[ipr]).intValue());
3611                    }
3612                } else {
3613                    if (cs.isVariableFieldWidth()) {
3614                        cs.setFieldWidthWithArg(((Integer JavaDoc)o[i]).intValue());
3615                        i++;
3616                    }
3617                    if (cs.isVariablePrecision()) {
3618                        cs.setPrecisionWithArg(((Integer JavaDoc)o[i]).intValue());
3619                        i++;
3620                    }
3621                }
3622                if (o[i] instanceof Byte JavaDoc) {
3623                    sb.append(cs.internalsprintf(((Byte JavaDoc)o[i]).byteValue()));
3624                } else if (o[i] instanceof Short JavaDoc) {
3625                    sb.append(cs.internalsprintf(((Short JavaDoc)o[i]).shortValue()));
3626                } else if (o[i] instanceof Integer JavaDoc) {
3627                    sb.append(cs.internalsprintf(((Integer JavaDoc)o[i]).intValue()));
3628                } else if (o[i] instanceof Long JavaDoc) {
3629                    sb.append(cs.internalsprintf(((Long JavaDoc)o[i]).longValue()));
3630                } else if (o[i] instanceof Float JavaDoc) {
3631                    sb.append(cs.internalsprintf(((Float JavaDoc)o[i]).floatValue()));
3632                } else if (o[i] instanceof Double JavaDoc) {
3633                    sb.append(cs.internalsprintf(((Double JavaDoc)o[i]).doubleValue()));
3634                } else if (o[i] instanceof Character JavaDoc) {
3635                    sb.append(cs.internalsprintf(((Character JavaDoc)o[i]).charValue()));
3636                } else if (o[i] instanceof String JavaDoc) {
3637                    sb.append(cs.internalsprintf((String JavaDoc)o[i]));
3638                } else {
3639                    sb.append(cs.internalsprintf(o[i]));
3640                }
3641                if (!cs.isPositionalSpecification()) {
3642                    i++;
3643                }
3644            }
3645        }
3646        return sb.toString();
3647    }
3648
3649    /**
3650     * Format a String.
3651     * @param x The String to format.
3652     * @return The formatted String.
3653     * @exception CmsIllegalArgumentException if the
3654     * conversion character is neither s nor S.
3655     */

3656    public String JavaDoc sprintf(String JavaDoc x) throws CmsIllegalArgumentException {
3657
3658        Enumeration JavaDoc e = m_vFmt.elements();
3659        ConversionSpecification cs = null;
3660        char c = 0;
3661        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
3662        while (e.hasMoreElements()) {
3663            cs = (ConversionSpecification)e.nextElement();
3664            c = cs.getConversionCharacter();
3665            if (c == '\0') {
3666                sb.append(cs.getLiteral());
3667            } else if (c == '%') {
3668                sb.append("%");
3669            } else {
3670                sb.append(cs.internalsprintf(x));
3671            }
3672        }
3673        return sb.toString();
3674    }
3675
3676    /**
3677     * Return a substring starting at
3678     * <code>start</code> and ending at either the end
3679     * of the String <code>s</code>, the next unpaired
3680     * percent sign, or at the end of the String if the
3681     * last character is a percent sign.
3682     * @param s Control string.
3683     * @param start Position in the string
3684     * <code>s</code> to begin looking for the start
3685     * of a control string.
3686     * @return the substring from the start position
3687     * to the beginning of the control string.
3688     */

3689    private String JavaDoc nonControl(String JavaDoc s, int start) {
3690
3691        m_cPos = s.indexOf("%", start);
3692        if (m_cPos == -1) {
3693            m_cPos = s.length();
3694        }
3695        return s.substring(start, m_cPos);
3696    }
3697}
3698
Popular Tags