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 050package jj2000.j2k.util; 051 052import java.io.*; 053 054/** 055 * This utility class formats messages to the specified line width, by 056 * inserting line-breaks between words, and printing the resulting 057 * lines. 058 * */ 059public class MsgPrinter { 060 061 /** The line width to use */ 062 public int lw; 063 064 /** Signals that a newline was found */ 065 private static final int IS_NEWLINE = -2; 066 067 /** Signals that the end-of-string was reached */ 068 private static final int IS_EOS = -1; 069 070 /** 071 * Creates a new message printer with the specified line width and 072 * with the default locale. 073 * 074 * @param linewidth The line width for which to format (in 075 * characters) 076 * 077 * 078 * */ 079 public MsgPrinter(int linewidth) { 080 lw = linewidth; 081 } 082 083 /** 084 * Returns the line width that is used for formatting. 085 * 086 * @return The line width used for formatting 087 * 088 * 089 * */ 090 public int getLineWidth() { 091 return lw; 092 } 093 094 /** 095 * Sets the line width to the specified value. This new value will 096 * be used in subsequent calls to the print() message. 097 * 098 * @param linewidth The new line width to use (in cahracters) 099 * 100 * 101 * */ 102 public void setLineWidth(int linewidth) { 103 if (linewidth <1) { 104 throw new IllegalArgumentException(); 105 } 106 lw = linewidth; 107 } 108 109 /** 110 * Formats the message to print in the current line width, by 111 * breaking the message into lines between words. The number of 112 * spaces to indent the first line is specified by 'flind' and the 113 * number of spaces to indent each of the following lines is 114 * specified by 'ind'. Newlines in 'msg' are respected. A newline is 115 * always printed at the end. 116 * 117 * @param out Where to print the message. 118 * 119 * @param flind The indentation for the first line. 120 * 121 * @param ind The indentation for the other lines. 122 * 123 * @param msg The message to format and print. 124 * 125 * 126 * */ 127 public void print(PrintWriter out, int flind, int ind, 128 String msg) { 129 int start,end,pend,efflw,lind,i; 130 131 start = 0; 132 end = 0; 133 pend = 0; 134 efflw = lw-flind; 135 lind = flind; 136 while ((end = nextLineEnd(msg,pend)) != IS_EOS) { 137 if (end == IS_NEWLINE) { // Forced line break 138 for (i=0; i<lind; i++) { 139 out.print(" "); 140 } 141 out.println(msg.substring(start,pend)); 142 if (nextWord(msg,pend) == msg.length()) { 143 // Traling newline => print it and done 144 out.println(""); 145 start = pend; 146 break; 147 } 148 } 149 else { 150 if (efflw > end-pend) { // Room left on current line 151 efflw -= end-pend; 152 pend = end; 153 continue; 154 } 155 else { // Filled-up current line => print it 156 for (i=0; i<lind; i++) { 157 out.print(" "); 158 } 159 if (start == pend) { // Word larger than line width 160 // Print anyways 161 out.println(msg.substring(start,end)); 162 pend = end; 163 } 164 else { 165 out.println(msg.substring(start,pend)); 166 } 167 } 168 } 169 // Initialize for next line 170 lind = ind; 171 efflw = lw-ind; 172 start = nextWord(msg,pend); 173 pend = start; 174 if (start == IS_EOS) { 175 break; // Did all the string 176 } 177 } 178 if (pend != start) { // Part of a line left => print it 179 for (i=0; i<lind; i++) { 180 out.print(" "); 181 } 182 out.println(msg.substring(start,pend)); 183 } 184 185 } 186 187 /** 188 * Returns the index of the last character of the next word, plus 1, or 189 * IS_NEWLINE if a newline character is encountered before the next word, 190 * or IS_EOS if the end of the string is ecnounterd before the next 191 * word. The method first skips all whitespace characters at or after 192 * 'from', except newlines. If a newline is found IS_NEWLINE is 193 * returned. Then it skips all non-whitespace characters and returns the 194 * position of the last non-whitespace character, plus 1. The returned 195 * index may be greater than the last valid index in the tsring, but it is 196 * always suitable to be used in the String.substring() method. 197 * 198 * <P>Non-whitespace characters are defined as in the 199 * Character.isWhitespace method (that method is used). 200 * 201 * @param str The string to parse 202 * 203 * @param from The index of the first position to search from 204 * 205 * @return The index of the last character in the next word, plus 1, 206 * IS_NEWLINE, or IS_EOS if there are no more words. 207 * 208 * 209 * */ 210 private int nextLineEnd(String str, int from) { 211 final int len = str.length(); 212 char c = '\0'; 213 // First skip all whitespace, except new line 214 while (from < len && (c = str.charAt(from)) != '\n' && 215 Character.isWhitespace(c)) { 216 from++; 217 } 218 if (c == '\n') { 219 return IS_NEWLINE; 220 } 221 if (from >= len) { 222 return IS_EOS; 223 } 224 // Now skip word characters 225 while (from < len && !Character.isWhitespace(str.charAt(from))) { 226 from++; 227 } 228 return from; 229 } 230 231 /** 232 * Returns the position of the first character in the next word, starting 233 * from 'from', if a newline is encountered first then the index of the 234 * newline character plus 1 is returned. If the end of the string is 235 * encountered then IS_EOS is returned. Words are defined as any 236 * concatenation of 1 or more characters which are not 237 * whitespace. Whitespace characters are those for which 238 * Character.isWhitespace() returns true (that method is used). 239 * 240 * <P>Non-whitespace characters are defined as in the 241 * Character.isWhitespace method (that method is used). 242 * 243 * @param str The string to parse 244 * 245 * @param from The index where to start parsing 246 * 247 * @return The index of the first character of the next word, or the index 248 * of the newline plus 1, or IS_EOS. 249 * 250 * 251 * */ 252 private int nextWord(String str, int from) { 253 final int len = str.length(); 254 char c = '\0'; 255 // First skip all whitespace, but new lines 256 while (from < len && (c = str.charAt(from)) != '\n' && 257 Character.isWhitespace(c)) { 258 from++; 259 } 260 if (from >= len) { 261 return IS_EOS; 262 } 263 else if (c == '\n') { 264 return from+1; 265 } 266 else { 267 return from; 268 } 269 } 270}