001: /*
002: * $RCSfile: MsgPrinter.java,v $
003: * $Revision: 1.1 $
004: * $Date: 2005/02/11 05:02:26 $
005: * $State: Exp $
006: *
007: * Class: MsgPrinter
008: *
009: * Description: Prints messages formatted for a specific
010: * line width.
011: *
012: *
013: *
014: * COPYRIGHT:
015: *
016: * This software module was originally developed by Raphaël Grosbois and
017: * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
018: * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
019: * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
020: * Centre France S.A) in the course of development of the JPEG2000
021: * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
022: * software module is an implementation of a part of the JPEG 2000
023: * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
024: * Systems AB and Canon Research Centre France S.A (collectively JJ2000
025: * Partners) agree not to assert against ISO/IEC and users of the JPEG
026: * 2000 Standard (Users) any of their rights under the copyright, not
027: * including other intellectual property rights, for this software module
028: * with respect to the usage by ISO/IEC and Users of this software module
029: * or modifications thereof for use in hardware or software products
030: * claiming conformance to the JPEG 2000 Standard. Those intending to use
031: * this software module in hardware or software products are advised that
032: * their use may infringe existing patents. The original developers of
033: * this software module, JJ2000 Partners and ISO/IEC assume no liability
034: * for use of this software module or modifications thereof. No license
035: * or right to this software module is granted for non JPEG 2000 Standard
036: * conforming products. JJ2000 Partners have full right to use this
037: * software module for his/her own purpose, assign or donate this
038: * software module to any third party and to inhibit third parties from
039: * using this software module for non JPEG 2000 Standard conforming
040: * products. This copyright notice must be included in all copies or
041: * derivative works of this software module.
042: *
043: * Copyright (c) 1999/2000 JJ2000 Partners.
044: *
045: *
046: *
047: */
048:
049: package jj2000.j2k.util;
050:
051: import java.io.*;
052:
053: /**
054: * This utility class formats messages to the specified line width, by
055: * inserting line-breaks between words, and printing the resulting
056: * lines.
057: * */
058: public class MsgPrinter {
059:
060: /** The line width to use */
061: public int lw;
062:
063: /** Signals that a newline was found */
064: private static final int IS_NEWLINE = -2;
065:
066: /** Signals that the end-of-string was reached */
067: private static final int IS_EOS = -1;
068:
069: /**
070: * Creates a new message printer with the specified line width and
071: * with the default locale.
072: *
073: * @param linewidth The line width for which to format (in
074: * characters)
075: *
076: *
077: * */
078: public MsgPrinter(int linewidth) {
079: lw = linewidth;
080: }
081:
082: /**
083: * Returns the line width that is used for formatting.
084: *
085: * @return The line width used for formatting
086: *
087: *
088: * */
089: public int getLineWidth() {
090: return lw;
091: }
092:
093: /**
094: * Sets the line width to the specified value. This new value will
095: * be used in subsequent calls to the print() message.
096: *
097: * @param linewidth The new line width to use (in cahracters)
098: *
099: *
100: * */
101: public void setLineWidth(int linewidth) {
102: if (linewidth < 1) {
103: throw new IllegalArgumentException();
104: }
105: lw = linewidth;
106: }
107:
108: /**
109: * Formats the message to print in the current line width, by
110: * breaking the message into lines between words. The number of
111: * spaces to indent the first line is specified by 'flind' and the
112: * number of spaces to indent each of the following lines is
113: * specified by 'ind'. Newlines in 'msg' are respected. A newline is
114: * always printed at the end.
115: *
116: * @param out Where to print the message.
117: *
118: * @param flind The indentation for the first line.
119: *
120: * @param ind The indentation for the other lines.
121: *
122: * @param msg The message to format and print.
123: *
124: *
125: * */
126: public void print(PrintWriter out, int flind, int ind, String msg) {
127: int start, end, pend, efflw, lind, i;
128:
129: start = 0;
130: end = 0;
131: pend = 0;
132: efflw = lw - flind;
133: lind = flind;
134: while ((end = nextLineEnd(msg, pend)) != IS_EOS) {
135: if (end == IS_NEWLINE) { // Forced line break
136: for (i = 0; i < lind; i++) {
137: out.print(" ");
138: }
139: out.println(msg.substring(start, pend));
140: if (nextWord(msg, pend) == msg.length()) {
141: // Traling newline => print it and done
142: out.println("");
143: start = pend;
144: break;
145: }
146: } else {
147: if (efflw > end - pend) { // Room left on current line
148: efflw -= end - pend;
149: pend = end;
150: continue;
151: } else { // Filled-up current line => print it
152: for (i = 0; i < lind; i++) {
153: out.print(" ");
154: }
155: if (start == pend) { // Word larger than line width
156: // Print anyways
157: out.println(msg.substring(start, end));
158: pend = end;
159: } else {
160: out.println(msg.substring(start, pend));
161: }
162: }
163: }
164: // Initialize for next line
165: lind = ind;
166: efflw = lw - ind;
167: start = nextWord(msg, pend);
168: pend = start;
169: if (start == IS_EOS) {
170: break; // Did all the string
171: }
172: }
173: if (pend != start) { // Part of a line left => print it
174: for (i = 0; i < lind; i++) {
175: out.print(" ");
176: }
177: out.println(msg.substring(start, pend));
178: }
179:
180: }
181:
182: /**
183: * Returns the index of the last character of the next word, plus 1, or
184: * IS_NEWLINE if a newline character is encountered before the next word,
185: * or IS_EOS if the end of the string is ecnounterd before the next
186: * word. The method first skips all whitespace characters at or after
187: * 'from', except newlines. If a newline is found IS_NEWLINE is
188: * returned. Then it skips all non-whitespace characters and returns the
189: * position of the last non-whitespace character, plus 1. The returned
190: * index may be greater than the last valid index in the tsring, but it is
191: * always suitable to be used in the String.substring() method.
192: *
193: * <P>Non-whitespace characters are defined as in the
194: * Character.isWhitespace method (that method is used).
195: *
196: * @param str The string to parse
197: *
198: * @param from The index of the first position to search from
199: *
200: * @return The index of the last character in the next word, plus 1,
201: * IS_NEWLINE, or IS_EOS if there are no more words.
202: *
203: *
204: * */
205: private int nextLineEnd(String str, int from) {
206: final int len = str.length();
207: char c = '\0';
208: // First skip all whitespace, except new line
209: while (from < len && (c = str.charAt(from)) != '\n'
210: && Character.isWhitespace(c)) {
211: from++;
212: }
213: if (c == '\n') {
214: return IS_NEWLINE;
215: }
216: if (from >= len) {
217: return IS_EOS;
218: }
219: // Now skip word characters
220: while (from < len && !Character.isWhitespace(str.charAt(from))) {
221: from++;
222: }
223: return from;
224: }
225:
226: /**
227: * Returns the position of the first character in the next word, starting
228: * from 'from', if a newline is encountered first then the index of the
229: * newline character plus 1 is returned. If the end of the string is
230: * encountered then IS_EOS is returned. Words are defined as any
231: * concatenation of 1 or more characters which are not
232: * whitespace. Whitespace characters are those for which
233: * Character.isWhitespace() returns true (that method is used).
234: *
235: * <P>Non-whitespace characters are defined as in the
236: * Character.isWhitespace method (that method is used).
237: *
238: * @param str The string to parse
239: *
240: * @param from The index where to start parsing
241: *
242: * @return The index of the first character of the next word, or the index
243: * of the newline plus 1, or IS_EOS.
244: *
245: *
246: * */
247: private int nextWord(String str, int from) {
248: final int len = str.length();
249: char c = '\0';
250: // First skip all whitespace, but new lines
251: while (from < len && (c = str.charAt(from)) != '\n'
252: && Character.isWhitespace(c)) {
253: from++;
254: }
255: if (from >= len) {
256: return IS_EOS;
257: } else if (c == '\n') {
258: return from + 1;
259: } else {
260: return from;
261: }
262: }
263: }
|