001: /***
002: * jwma Java WebMail
003: * Copyright (c) 2000-2003 jwma team
004: *
005: * jwma is free software; you can distribute and use this source
006: * under the terms of the BSD-style license received along with
007: * the distribution.
008: ***/package dtw.webmail.util;
009:
010: import java.io.*;
011: import java.text.BreakIterator;
012:
013: import org.apache.log4j.Logger;
014: import net.wimpi.text.*;
015:
016: /**
017: * Implements a processor which wraps lines observing
018: * word boundaries.
019: *
020: * @author August Detlefsen (augustd at codemagi.com), Dieter Wimberger
021: */
022: public class LineWrapper extends AbstractProcessor {
023:
024: //logging
025: private static Logger log = Logger.getLogger(LineWrapper.class);
026:
027: public String getName() {
028: return "linewrapper";
029: }//getName
030:
031: public final String process(String str) {
032: return paragraphFormat(str, 80);
033: }//process
034:
035: /**
036: * Adds line breaks ('\n') to a paragraph of text
037: *
038: * @param paragraph the String to format.
039: * @param colWidth the suggested column width (actual width will
040: * be greater depending on word breaks).
041: * @return String The input text formatted with line breaks every colWidth
042: */
043: private final String paragraphFormat(String input, int colWidth) {
044:
045: //set up the break iterator
046: BreakIterator lines = BreakIterator.getLineInstance();
047: lines.setText(input);
048:
049: //setup the output buffer
050: StringBuffer output = new StringBuffer(input.length() + 100);
051:
052: int lastLineBreak = 0;
053: int lastBreak = 0;
054: int currentBreak = 0;
055:
056: StringBuffer currentWord = new StringBuffer();
057:
058: while (lines.next() != BreakIterator.DONE) {
059:
060: currentBreak = lines.current();
061:
062: //reset the currentWord buffer
063: currentWord.setLength(0);
064: currentWord
065: .append(input.substring(lastBreak, currentBreak));
066:
067: //FIXME: try to find :// once, problem is that
068: //the iterator takes : as boundary
069: if (currentWord.toString().indexOf("http:") != -1
070: || currentWord.toString().indexOf("ftp:") != -1) {
071:
072: try {
073: //don't chop URLs.
074: //Problem is that Break iterator sees '.' as a good place to break.
075: //Solution is to find the next space or line break
076: int nextLine = input.indexOf("\n", currentBreak);
077: int nextSpace = input.indexOf(" ", currentBreak);
078: int nextBreak = nextLine >= nextSpace ? nextSpace
079: : nextLine;
080:
081: if (nextBreak == -1) { //must be at end
082: nextBreak = input.length();
083: }
084:
085: //append everything up to the end of the url
086: currentWord.append(input.substring(currentBreak,
087: nextBreak));
088:
089: //set the break iterator forward
090: for (int i = currentBreak; i != BreakIterator.DONE
091: && i < nextBreak; i += 0) {
092: //keep getting next until ...
093: i = lines.next();
094: currentBreak = i;
095: }
096:
097: } catch (Exception e) {
098: e.printStackTrace();
099: }
100:
101: } else if (currentWord.toString().indexOf("\n") > -1) {
102: //if there is already a line break, update
103: lastLineBreak = currentBreak;
104:
105: } else if (currentBreak > lastLineBreak + colWidth) {
106: //if column is getting too wide, break it
107:
108: currentWord.append("\n");
109: //currentWord.append("!@!");
110: lastLineBreak = currentBreak;
111: }
112:
113: //append currentWord to the output buffer
114: output.append(currentWord);
115:
116: //reset the break
117: lastBreak = currentBreak;
118:
119: }
120:
121: return output.toString();
122: }//paragraphFormat
123:
124: public InputStream process(InputStream in) throws IOException {
125:
126: ByteArrayOutputStream bout = new ByteArrayOutputStream(in
127: .available());
128:
129: byte[] buffer = new byte[8192];
130: int amount = 0;
131: while ((amount = in.read(buffer)) >= 0) {
132: bout.write(buffer, 0, amount);
133: }
134: return new ByteArrayInputStream(process(bout.toString())
135: .getBytes());
136:
137: }//process
138:
139: }//class LineWrapper
|