blob: cadf86785ee07ddad102262a4fb5ea892997567c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 The Regents of the University of California.
* This material was produced under U.S. Government contract W-7405-ENG-36
* for Los Alamos National Laboratory, which is operated by the University
* of California for the U.S. Department of Energy. The U.S. Government has
* rights to use, reproduce, and distribute this software. NEITHER THE
* GOVERNMENT NOR THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
* ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified
* to produce derivative works, such modified software should be clearly marked,
* so as not to confuse it with the version available from LANL.
*
* Additionally, this program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* LA-CC 04-115
*******************************************************************************/
package org.eclipse.ptp.internal.ui.hover;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.text.BreakIterator;
import org.eclipse.swt.graphics.GC;
/**
* @author Clement chu
*/
public class LineBreakingReader {
private BufferedReader fReader;
private GC fGC;
private int fMaxWidth;
private String fLine;
private int fOffset;
private int fLineLen;
private BreakIterator fLineBreakIterator;
/**
* Creates a reader that breaks an input text to fit in a given width.
*
* @param reader
* Reader of the input text
* @param gc
* The graphic context that defines the currently used font sizes
* @param maxLineWidth
* The max width (pixes) where the text has to fit in
*/
public LineBreakingReader(Reader reader, GC gc, int maxLineWidth) {
fReader = new BufferedReader(reader);
fGC = gc;
fMaxWidth = maxLineWidth;
fOffset = 0;
fLine = null;
fLineBreakIterator = BreakIterator.getLineInstance();
}
/**
* Is formatted line
*
* @return true if it is a formatted line
*/
public boolean isFormattedLine() {
return fLine != null;
}
/**
* Reads the next line. The lengths of the line will not exceed the gived maximum width
*
* @param indent
* @return
* @throws IOException
*/
public String readLine(String indent) throws IOException {
if (fLine == null) {
String line = fReader.readLine();
if (line == null)
return null;
int lineLen = fGC.textExtent(line).x;
if (fMaxWidth > -1 && lineLen < fMaxWidth) {
return line;
}
fLine = line;
fLineBreakIterator.setText(line);
fOffset = 0;
}
int breakOffset = findNextBreakOffset(fOffset, indent);
String res;
if (breakOffset != BreakIterator.DONE) {
res = fLine.substring(fOffset, breakOffset);
fOffset = findWordBegin(breakOffset);
if (fOffset == fLine.length()) {
fLine = null;
}
if (breakOffset == 1 && res.charAt(0) == '\t') {// added to prevent empty line
return "\t" + readLine(indent);
}
} else {
res = fLine.substring(fOffset);
fLine = null;
}
return res;
}
public String readLine() throws IOException {
if (fLine == null) {
String line = fReader.readLine();
if (line == null)
return null;
fLineLen = line.length();
if (fMaxWidth == -1 || fLineLen < fMaxWidth) {
return line;
}
fLine = line;
fOffset = 0;
}
int endLen = fOffset + fMaxWidth;
if (endLen > fLineLen)
endLen = fLineLen;
String res = fLine.substring(fOffset, endLen);
fOffset = endLen;
if (fOffset >= fLineLen) {
fLine = null;
fLineLen = 0;
}
if (res.charAt(0) == '\t') {// added to prevent empty line
return "\t" + res;
}
return res;
}
/**
* Find next breaj offset
*
* @param currOffset
* @param indent
* @return
*/
private int findNextBreakOffset(int currOffset, String indent) {
int currWidth = indent != null ? fGC.textExtent(indent).x : 0;
int nextOffset = fLineBreakIterator.following(currOffset);
while (nextOffset != BreakIterator.DONE) {
String word = fLine.substring(currOffset, nextOffset);
int wordWidth = fGC.textExtent(word).x;
int nextWidth = wordWidth + currWidth;
if (fMaxWidth > -1 && nextWidth > fMaxWidth) {
if (currWidth > 0) {
return currOffset;
} else {
return nextOffset;
}
}
currWidth = nextWidth;
currOffset = nextOffset;
nextOffset = fLineBreakIterator.next();
}
return nextOffset;
}
/**
* Find word begin index
*
* @param idx
* @return
*/
private int findWordBegin(int idx) {
while (idx < fLine.length() && Character.isWhitespace(fLine.charAt(idx))) {
idx++;
}
return idx;
}
}