*
* @author Kevin Lamonte [kevin.lamonte@gmail.com]
* @version 1
+ *
+ * I added some changes to integrate it here.
+ * @author Niki
*/
package be.nikiroo.utils;
*
* @return the list of justified lines
*/
- static List<String> left2(final String data, final int width) {
- List<String> result = new LinkedList<String>();
-
- return result;
- }
-
- /**
- * Left-justify a string into a list of lines.
- *
- * @param str
- * the string
- * @param n
- * the maximum number of characters in a line
- * @return the list of lines
- */
- static List<String> left(final String str, final int n) {
- List<String> result = new LinkedList<String>();
-
- /*
- * General procedure:
- *
- * 1. Split on '\n' into paragraphs.
- *
- * 2. Scan each line, noting the position of the last
- * beginning-of-a-word.
- *
- * 3. Chop at the last #2 if the next beginning-of-a-word exceeds n.
- *
- * 4. Return the lines.
- */
-
- String[] rawLines = str.split("\n");
- for (int i = 0; i < rawLines.length; i++) {
- StringBuilder line = new StringBuilder();
- StringBuilder word = new StringBuilder();
- boolean inWord = false;
- for (int j = 0; j < rawLines[i].length(); j++) {
- char ch = rawLines[i].charAt(j);
- if ((ch == ' ') || (ch == '\t')) {
- if (inWord == true) {
- // We have just transitioned from a word to
- // whitespace. See if we have enough space to add
- // the word to the line.
- if (word.length() + line.length() > n) {
- // This word will exceed the line length. Wrap
- // at it instead.
- result.add(line.toString());
- line = new StringBuilder();
- }
- if ((word.toString().startsWith(" "))
- && (line.length() == 0)) {
- line.append(word.substring(1));
- } else {
- line.append(word);
- }
- word = new StringBuilder();
- word.append(ch);
- inWord = false;
- } else {
- // We are in the whitespace before another word. Do
- // nothing.
- }
- } else {
- if (inWord == true) {
- // We are appending to a word.
- word.append(ch);
- } else {
- // We have transitioned from whitespace to a word.
- word.append(ch);
- inWord = true;
- }
- }
- } // next j
-
- if (word.length() + line.length() > n) {
- // This word will exceed the line length. Wrap at it
- // instead.
- result.add(line.toString());
- line = new StringBuilder();
- }
- if ((word.toString().startsWith(" ")) && (line.length() == 0)) {
- line.append(word.substring(1));
- } else {
- line.append(word);
- }
- result.add(line.toString());
- } // next i
-
- return result;
+ static List<String> left(final String data, final int width) {
+ return left(data, width, false);
}
/**
List<String> result = new LinkedList<String>();
/*
- * Same as left(), but insert spaces between words to make each line n
- * chars long. The "algorithm" here is pretty dumb: it performs a split
- * on space and then re-inserts multiples of n between words.
+ * Same as left(true), but insert spaces between words to make each line
+ * n chars long. The "algorithm" here is pretty dumb: it performs a
+ * split on space and then re-inserts multiples of n between words.
*/
- List<String> lines = left(str, n);
+ List<String> lines = left(str, n, true);
for (int lineI = 0; lineI < lines.size() - 1; lineI++) {
String line = lines.get(lineI);
String[] words = line.split(" ");
return result;
}
+
+ /**
+ * Process the given text into a list of left-justified lines of a given
+ * max-width.
+ *
+ * @param data
+ * the text to justify
+ * @param width
+ * the maximum width of a line
+ * @param minTwoWords
+ * use 2 words per line minimum if the text allows it
+ *
+ * @return the list of justified lines
+ */
+ static private List<String> left(final String data, final int width,
+ boolean minTwoWords) {
+ List<String> lines = new LinkedList<String>();
+
+ for (String dataLine : data.split("\n")) {
+ String line = rightTrim(dataLine.replace("\t", " "));
+
+ if (width > 0 && line.length() > width) {
+ while (line.length() > 0) {
+ int i = Math.min(line.length(), width - 1); // -1 for "-"
+
+ boolean needDash = true;
+ // find the best space if any and if needed
+ int prevSpace = 0;
+ if (i < line.length()) {
+ prevSpace = -1;
+ int space = line.indexOf(' ');
+ int numOfSpaces = 0;
+
+ while (space > -1 && space <= i) {
+ prevSpace = space;
+ space = line.indexOf(' ', space + 1);
+ numOfSpaces++;
+ }
+
+ if (prevSpace > 0 && (!minTwoWords || numOfSpaces >= 2)) {
+ i = prevSpace;
+ needDash = false;
+ }
+ }
+ //
+
+ // no dash before space/dash
+ if ((i + 1) < line.length()) {
+ char car = line.charAt(i);
+ char nextCar = line.charAt(i + 1);
+ if (car == ' ' || car == '-' || nextCar == ' ') {
+ needDash = false;
+ } else if (i > 0) {
+ char prevCar = line.charAt(i - 1);
+ if (prevCar == ' ' || prevCar == '-') {
+ needDash = false;
+ i--;
+ }
+ }
+ }
+
+ // if the space freed by the removed dash allows it, or if
+ // it is the last char, add the next char
+ if (!needDash || i >= line.length() - 1) {
+ int checkI = Math.min(i + 1, line.length());
+ if (checkI == i || checkI <= width) {
+ needDash = false;
+ i = checkI;
+ }
+ }
+
+ // no dash before parenthesis (but cannot add one more
+ // after)
+ if ((i + 1) < line.length()) {
+ char nextCar = line.charAt(i + 1);
+ if (nextCar == '(' || nextCar == ')') {
+ needDash = false;
+ }
+ }
+
+ if (needDash) {
+ lines.add(rightTrim(line.substring(0, i)) + "-");
+ } else {
+ lines.add(rightTrim(line.substring(0, i)));
+ }
+
+ // full trim (remove spaces when cutting)
+ line = line.substring(i).trim();
+ }
+ } else {
+ lines.add(line);
+ }
+ }
+
+ return lines;
+ }
+
+ /**
+ * Trim the given {@link String} on the right only.
+ *
+ * @param data
+ * the source {@link String}
+ * @return the right-trimmed String or Empty if it was NULL
+ */
+ static private String rightTrim(String data) {
+ if (data == null)
+ return "";
+
+ return ("|" + data).trim().substring(1);
+ }
}