java.text.BreakIterator#last ( )源码实例Demo

下面列出了java.text.BreakIterator#last ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: TencentKona-8   文件: BreakIteratorTest.java
private Vector testLastAndPrevious(BreakIterator bi, String text) {
    int p = bi.last();
    int lastP = p;
    Vector<String> result = new Vector<String>();

    if (p != text.length())
        errln("last() returned " + p + " instead of " + text.length());
    while (p != BreakIterator.DONE) {
        p = bi.previous();
        if (p != BreakIterator.DONE) {
            if (p >= lastP)
                errln("previous() failed to move backward: previous() on position "
                                + lastP + " yielded " + p);

            result.insertElementAt(text.substring(p, lastP), 0);
        }
        else {
            if (lastP != 0)
                errln("previous() returned DONE prematurely: offset was "
                                + lastP + " instead of 0");
        }
        lastP = p;
    }
    return result;
}
 
源代码2 项目: openjdk-jdk8u   文件: BreakIteratorTest.java
private Vector testLastAndPrevious(BreakIterator bi, String text) {
    int p = bi.last();
    int lastP = p;
    Vector<String> result = new Vector<String>();

    if (p != text.length())
        errln("last() returned " + p + " instead of " + text.length());
    while (p != BreakIterator.DONE) {
        p = bi.previous();
        if (p != BreakIterator.DONE) {
            if (p >= lastP)
                errln("previous() failed to move backward: previous() on position "
                                + lastP + " yielded " + p);

            result.insertElementAt(text.substring(p, lastP), 0);
        }
        else {
            if (lastP != 0)
                errln("previous() returned DONE prematurely: offset was "
                                + lastP + " instead of 0");
        }
        lastP = p;
    }
    return result;
}
 
源代码3 项目: openjdk-jdk9   文件: BreakIteratorTest.java
private Vector testLastAndPrevious(BreakIterator bi, String text) {
    int p = bi.last();
    int lastP = p;
    Vector<String> result = new Vector<String>();

    if (p != text.length())
        errln("last() returned " + p + " instead of " + text.length());
    while (p != BreakIterator.DONE) {
        p = bi.previous();
        if (p != BreakIterator.DONE) {
            if (p >= lastP)
                errln("previous() failed to move backward: previous() on position "
                                + lastP + " yielded " + p);

            result.insertElementAt(text.substring(p, lastP), 0);
        }
        else {
            if (lastP != 0)
                errln("previous() returned DONE prematurely: offset was "
                                + lastP + " instead of 0");
        }
        lastP = p;
    }
    return result;
}
 
源代码4 项目: jdk8u_jdk   文件: BreakIteratorTest.java
private Vector testLastAndPrevious(BreakIterator bi, String text) {
    int p = bi.last();
    int lastP = p;
    Vector<String> result = new Vector<String>();

    if (p != text.length())
        errln("last() returned " + p + " instead of " + text.length());
    while (p != BreakIterator.DONE) {
        p = bi.previous();
        if (p != BreakIterator.DONE) {
            if (p >= lastP)
                errln("previous() failed to move backward: previous() on position "
                                + lastP + " yielded " + p);

            result.insertElementAt(text.substring(p, lastP), 0);
        }
        else {
            if (lastP != 0)
                errln("previous() returned DONE prematurely: offset was "
                                + lastP + " instead of 0");
        }
        lastP = p;
    }
    return result;
}
 
源代码5 项目: dragonwell8_jdk   文件: BreakIteratorTest.java
private void doMultipleSelectionTest(BreakIterator iterator, String testText)
{
    logln("Multiple selection test...");
    BreakIterator testIterator = (BreakIterator)iterator.clone();
    int offset = iterator.first();
    int testOffset;
    int count = 0;

    do {
        testOffset = testIterator.first();
        testOffset = testIterator.next(count);
        logln("next(" + count + ") -> " + testOffset);
        if (offset != testOffset)
            errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset);

        if (offset != BreakIterator.DONE) {
            count++;
            offset = iterator.next();
        }
    } while (offset != BreakIterator.DONE);

    // now do it backwards...
    offset = iterator.last();
    count = 0;

    do {
        testOffset = testIterator.last();
        testOffset = testIterator.next(count);
        logln("next(" + count + ") -> " + testOffset);
        if (offset != testOffset)
            errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset);

        if (offset != BreakIterator.DONE) {
            count--;
            offset = iterator.previous();
        }
    } while (offset != BreakIterator.DONE);
}
 
源代码6 项目: TencentKona-8   文件: BreakIteratorTest.java
private void doMultipleSelectionTest(BreakIterator iterator, String testText)
{
    logln("Multiple selection test...");
    BreakIterator testIterator = (BreakIterator)iterator.clone();
    int offset = iterator.first();
    int testOffset;
    int count = 0;

    do {
        testOffset = testIterator.first();
        testOffset = testIterator.next(count);
        logln("next(" + count + ") -> " + testOffset);
        if (offset != testOffset)
            errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset);

        if (offset != BreakIterator.DONE) {
            count++;
            offset = iterator.next();
        }
    } while (offset != BreakIterator.DONE);

    // now do it backwards...
    offset = iterator.last();
    count = 0;

    do {
        testOffset = testIterator.last();
        testOffset = testIterator.next(count);
        logln("next(" + count + ") -> " + testOffset);
        if (offset != testOffset)
            errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset);

        if (offset != BreakIterator.DONE) {
            count--;
            offset = iterator.previous();
        }
    } while (offset != BreakIterator.DONE);
}
 
源代码7 项目: nebula   文件: DatePicker.java
/**
 * set / update the text of the displayLabels. these are the Week column
 * headers above the days on the Calendar part of the <code>CDateTime</code>
 * .
 */
private void updateDaysOfWeek() {
    if (dayPanel != null) {
        Calendar tmpcal = cdt.getCalendarInstance();
        tmpcal.set(Calendar.DAY_OF_WEEK, tmpcal.getFirstDayOfWeek());
        Locale locale = cdt.getLocale();
        boolean ltr = ComponentOrientation.getOrientation(locale)
                .isLeftToRight() && !locale.getLanguage().equals("zh"); //$NON-NLS-1$
        BreakIterator iterator = BreakIterator.getCharacterInstance(locale);
        for (VLabel dayLabel : dayLabels) {
            String str = getFormattedDate("E", tmpcal.getTime()); //$NON-NLS-1$
            if (dayLabel.getData(CDT.Key.Compact, Boolean.class)) {
                iterator.setText(str);
                int start, end;
                if (ltr) {
                    start = iterator.first();
                    end = iterator.next();
                } else {
                    end = iterator.last();
                    start = iterator.previous();
                }
                dayLabel.setText(str.substring(start, end));
            } else {
                dayLabel.setText(str);
            }
            tmpcal.add(Calendar.DAY_OF_WEEK, 1);
        }
    }
}
 
源代码8 项目: openjdk-jdk8u   文件: BreakIteratorTest.java
private void doMultipleSelectionTest(BreakIterator iterator, String testText)
{
    logln("Multiple selection test...");
    BreakIterator testIterator = (BreakIterator)iterator.clone();
    int offset = iterator.first();
    int testOffset;
    int count = 0;

    do {
        testOffset = testIterator.first();
        testOffset = testIterator.next(count);
        logln("next(" + count + ") -> " + testOffset);
        if (offset != testOffset)
            errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset);

        if (offset != BreakIterator.DONE) {
            count++;
            offset = iterator.next();
        }
    } while (offset != BreakIterator.DONE);

    // now do it backwards...
    offset = iterator.last();
    count = 0;

    do {
        testOffset = testIterator.last();
        testOffset = testIterator.next(count);
        logln("next(" + count + ") -> " + testOffset);
        if (offset != testOffset)
            errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset);

        if (offset != BreakIterator.DONE) {
            count--;
            offset = iterator.previous();
        }
    } while (offset != BreakIterator.DONE);
}
 
源代码9 项目: openjdk-jdk9   文件: BreakIteratorTest.java
private void doMultipleSelectionTest(BreakIterator iterator, String testText)
{
    logln("Multiple selection test...");
    BreakIterator testIterator = (BreakIterator)iterator.clone();
    int offset = iterator.first();
    int testOffset;
    int count = 0;

    do {
        testOffset = testIterator.first();
        testOffset = testIterator.next(count);
        logln("next(" + count + ") -> " + testOffset);
        if (offset != testOffset)
            errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset);

        if (offset != BreakIterator.DONE) {
            count++;
            offset = iterator.next();
        }
    } while (offset != BreakIterator.DONE);

    // now do it backwards...
    offset = iterator.last();
    count = 0;

    do {
        testOffset = testIterator.last();
        testOffset = testIterator.next(count);
        logln("next(" + count + ") -> " + testOffset);
        if (offset != testOffset)
            errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset);

        if (offset != BreakIterator.DONE) {
            count--;
            offset = iterator.previous();
        }
    } while (offset != BreakIterator.DONE);
}
 
源代码10 项目: lucene-solr   文件: TestSplittingBreakIterator.java
private void testFirstAndLast(BreakIterator bi, String text, String boundaries) {
  String message = "Text: " + text;
  int current = bi.current();
  assertEquals(message, boundaries.indexOf('^'), current);
  assertEquals(message, current, bi.first());
  assertEquals(message, current, bi.current());
  current = bi.last();
  assertEquals(boundaries.lastIndexOf('^'), current);
  assertEquals(message, current, bi.current());
}
 
源代码11 项目: lucene-solr   文件: TestSplittingBreakIterator.java
private void testPrevious(BreakIterator bi, String text, String boundaries) {
  String message = "Text: " + text;

  bi.setText(text);
  int idx = bi.last();//position at the end
  while (true) {
    idx = boundaries.lastIndexOf('^', idx - 1);
    if (idx == -1) {
      assertEquals(message, BreakIterator.DONE, bi.previous());
      break;
    }
    assertEquals(message, idx, bi.previous());
  }
  assertEquals(message, boundaries.indexOf('^'), bi.current());//finishes at first
}
 
源代码12 项目: Tehreer-Android   文件: BreakResolver.java
private static void fillBreaks(@NonNull String text, @NonNull byte[] breaks, byte type) {
    BreakIterator iterator;

    switch (type) {
    case CHARACTER:
        iterator = BreakIterator.getCharacterInstance();
        break;

    default:
        iterator = BreakIterator.getLineInstance();
        break;
    }

    iterator.setText(text);
    iterator.first();

    byte forwardType = typeMode(type, true);
    int charNext;

    while ((charNext = iterator.next()) != BreakIterator.DONE) {
        breaks[charNext - 1] |= forwardType;
    }

    iterator.last();
    byte backwardType = typeMode(type, false);
    int charIndex;

    while ((charIndex = iterator.previous()) != BreakIterator.DONE) {
        breaks[charIndex] |= backwardType;
    }
}
 
源代码13 项目: jdk8u_jdk   文件: BreakIteratorTest.java
private void doMultipleSelectionTest(BreakIterator iterator, String testText)
{
    logln("Multiple selection test...");
    BreakIterator testIterator = (BreakIterator)iterator.clone();
    int offset = iterator.first();
    int testOffset;
    int count = 0;

    do {
        testOffset = testIterator.first();
        testOffset = testIterator.next(count);
        logln("next(" + count + ") -> " + testOffset);
        if (offset != testOffset)
            errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset);

        if (offset != BreakIterator.DONE) {
            count++;
            offset = iterator.next();
        }
    } while (offset != BreakIterator.DONE);

    // now do it backwards...
    offset = iterator.last();
    count = 0;

    do {
        testOffset = testIterator.last();
        testOffset = testIterator.next(count);
        logln("next(" + count + ") -> " + testOffset);
        if (offset != testOffset)
            errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset);

        if (offset != BreakIterator.DONE) {
            count--;
            offset = iterator.previous();
        }
    } while (offset != BreakIterator.DONE);
}
 
源代码14 项目: java-swing-tips   文件: MainPanel.java
public static int getWordStart(JTextComponent c, int offs) throws BadLocationException {
  Element line = Optional.ofNullable(Utilities.getParagraphElement(c, offs))
      .orElseThrow(() -> new BadLocationException("No word at " + offs, offs));
  Document doc = c.getDocument();
  int lineStart = line.getStartOffset();
  int lineEnd = Math.min(line.getEndOffset(), doc.getLength());
  int offs2 = offs;
  Segment seg = SegmentCache.getSharedSegment();
  doc.getText(lineStart, lineEnd - lineStart, seg);
  if (seg.count > 0) {
    BreakIterator words = BreakIterator.getWordInstance(c.getLocale());
    words.setText(seg);
    int wordPosition = seg.offset + offs - lineStart;
    if (wordPosition >= words.last()) {
      wordPosition = words.last() - 1;
      words.following(wordPosition);
      offs2 = lineStart + words.previous() - seg.offset;
    } else {
      words.following(wordPosition);
      offs2 = lineStart + words.previous() - seg.offset;
      for (int i = offs; i > offs2; i--) {
        char ch = seg.charAt(i - seg.offset);
        if (ch == '_' || ch == '-') {
          offs2 = i + 1;
          break;
        }
      }
    }
  }
  SegmentCache.releaseSharedSegment(seg);
  return offs2;
}
 
源代码15 项目: java-swing-tips   文件: MainPanel.java
public static int getWordEnd(JTextComponent c, int offs) throws BadLocationException {
  Element line = Optional.ofNullable(Utilities.getParagraphElement(c, offs))
      .orElseThrow(() -> new BadLocationException("No word at " + offs, offs));
  Document doc = c.getDocument();
  int lineStart = line.getStartOffset();
  int lineEnd = Math.min(line.getEndOffset(), doc.getLength());
  int offs2 = offs;

  Segment seg = SegmentCache.getSharedSegment();
  doc.getText(lineStart, lineEnd - lineStart, seg);
  if (seg.count > 0) {
    BreakIterator words = BreakIterator.getWordInstance(c.getLocale());
    words.setText(seg);
    int wordPosition = offs - lineStart + seg.offset;
    if (wordPosition >= words.last()) {
      wordPosition = words.last() - 1;
    }
    offs2 = lineStart + words.following(wordPosition) - seg.offset;

    for (int i = offs; i < offs2; i++) {
      char ch = seg.charAt(i - seg.offset);
      if (ch == '_' || ch == '-') {
        offs2 = i;
        break;
      }
    }
  }
  SegmentCache.releaseSharedSegment(seg);
  return offs2;
}
 
源代码16 项目: openemm   文件: StringUtils.java
/**
 * Method converts single-line string to the word-wrapped multiline string with the given max-width
 * and max-line-number values (if the string is longer than that - the rest of the string will
 * be thrown out and "..." will be added to the end)
 *
 * @param input - the source string
 * @param width - the max width of one line of text
 * @param maxlines - the max number of lines that result string can contain
 * @param locale - the source string locale; is used to determine the possible places to make word-wraps in the source string
 * @return the string with word wrapping
 */
public static String wordWrap(String input, int width, int maxlines, Locale locale) {
    if (input == null) {
        return "";
    }
    if (width >= input.length()) {
        return input;
    }
    StringBuilder buf = new StringBuilder(input);
    boolean endOfLine = false;
    int lineStart = 0;
    for (int i = 0; i < buf.length(); i++) {
        if (buf.charAt(i) == '\n') {
            lineStart = i + 1;
            endOfLine = true;
        }
        // handle splitting at width character
        if (i > lineStart + width - 1) {
            if (!endOfLine) {
                int limit = i - lineStart - 1;
                BreakIterator breaks = BreakIterator.getLineInstance(locale);
                breaks.setText(buf.substring(lineStart, i));
                int end = breaks.last();
                // if the last character in the search string isn't a space,
                // we can't split on it. Search for a previous break character
                if (end == limit + 1) {
                    if (!Character.isWhitespace(buf.charAt(lineStart + end))) {
                        end = breaks.preceding(end - 1);
                    }
                }
                // if the last character is a space - replace it with \n
                if (end != BreakIterator.DONE && end == limit + 1) {
                    buf.replace(lineStart + end, lineStart + end + 1, "\n");
                    lineStart = lineStart + end;
                }
                // otherwise - just insert a \n
                else if (end != BreakIterator.DONE && end != 0) {
                    buf.insert(lineStart + end, '\n');
                    lineStart = lineStart + end + 1;
                }
                else {
                    buf.insert(i, '\n');
                    lineStart = i + 1;
                }
            }
            else {
                buf.insert(i, '\n');
                lineStart = i + 1;
                endOfLine = false;
            }
        }
    }
    // Throw out excess strings
    String result = buf.toString();
    StringBuilder builder = new StringBuilder();
    String[] lines = result.split("\n");
    if (lines != null && lines.length > maxlines) {
        String shortedStr = "...";
        if (lines[maxlines - 1].length() + shortedStr.length() <= width) {
            lines[maxlines - 1] = lines[maxlines - 1] + shortedStr;
        } else {
            lines[maxlines - 1] = lines[maxlines -1].substring(0, width - shortedStr.length()) + shortedStr;
        }
        for (int i = 0; i < maxlines; i++) {
            builder.append(lines[i]).append("\n");
        }
        result = builder.toString();
        result = result.substring(0, result.length() - 1);
    }
    return result;
}
 
源代码17 项目: Spark   文件: StringUtils.java
/**
    * Reformats a string where lines that are longer than <tt>width</tt>
    * <p/>
    * are split apart at the earliest wordbreak or at maxLength, whichever is
    * <p/>
    * sooner. If the width specified is less than 5 or greater than the input
    * <p/>
    * Strings length the string will be returned as is.
    * <p/>
    * <p/>
    * <p/>
    * Please note that this method can be lossy - trailing spaces on wrapped
    * <p/>
    * lines may be trimmed.
    * 
    * @param input
    *            the String to reformat.
    * @param width
    *            the maximum length of any one line.
    * @param locale
    *            of the string to be wrapped.
    * @return a new String with reformatted as needed.
    */
   public static String wordWrap(String input, int width, Locale locale) {
// protect ourselves
if (input == null) {
    return "";
} else if (width < 5) {
    return input;
} else if (width >= input.length()) {
    return input;
}

StringBuilder buf = new StringBuilder(input);
boolean endOfLine = false;
int lineStart = 0;

for (int i = 0; i < buf.length(); i++) {
    if (buf.charAt(i) == '\n') {
	lineStart = i + 1;
	endOfLine = true;
    }
    // handle splitting at width character
    if (i > lineStart + width - 1) {
	if (!endOfLine) {
	    int limit = i - lineStart - 1;
	    BreakIterator breaks = BreakIterator
		    .getLineInstance(locale);
	    breaks.setText(buf.substring(lineStart, i));
	    int end = breaks.last();
	    // if the last character in the search string isn't a space,
	    // we can't split on it (looks bad). Search for a previous
	    // break character
	    if (end == limit + 1) {
		if (!Character
			.isWhitespace(buf.charAt(lineStart + end))) {
		    end = breaks.preceding(end - 1);
		}
	    }
	    // if the last character is a space, replace it with a \n
	    if (end != BreakIterator.DONE && end == limit + 1) {
		buf.replace(lineStart + end, lineStart + end + 1, "\n");
		lineStart = lineStart + end;
	    }
	    // otherwise, just insert a \n
	    else if (end != BreakIterator.DONE && end != 0) {
		buf.insert(lineStart + end, '\n');
		lineStart = lineStart + end + 1;
	    } else {
		buf.insert(i, '\n');
		lineStart = i + 1;
	    }
	} else {
	    buf.insert(i, '\n');
	    lineStart = i + 1;
	    endOfLine = false;
	}
    }
}

return buf.toString();
   }
 
源代码18 项目: xyTalk-pc   文件: StringUtils.java
/**
    * Reformats a string where lines that are longer than <tt>width</tt>
    * <p/>
    * are split apart at the earliest wordbreak or at maxLength, whichever is
    * <p/>
    * sooner. If the width specified is less than 5 or greater than the input
    * <p/>
    * Strings length the string will be returned as is.
    * <p/>
    * <p/>
    * <p/>
    * Please note that this method can be lossy - trailing spaces on wrapped
    * <p/>
    * lines may be trimmed.
    * 
    * @param input
    *            the String to reformat.
    * @param width
    *            the maximum length of any one line.
    * @param locale
    *            of the string to be wrapped.
    * @return a new String with reformatted as needed.
    */
   public static String wordWrap(String input, int width, Locale locale) {
// protect ourselves
if (input == null) {
    return "";
} else if (width < 5) {
    return input;
} else if (width >= input.length()) {
    return input;
}

StringBuilder buf = new StringBuilder(input);
boolean endOfLine = false;
int lineStart = 0;

for (int i = 0; i < buf.length(); i++) {
    if (buf.charAt(i) == '\n') {
	lineStart = i + 1;
	endOfLine = true;
    }
    // handle splitting at width character
    if (i > lineStart + width - 1) {
	if (!endOfLine) {
	    int limit = i - lineStart - 1;
	    BreakIterator breaks = BreakIterator
		    .getLineInstance(locale);
	    breaks.setText(buf.substring(lineStart, i));
	    int end = breaks.last();
	    // if the last character in the search string isn't a space,
	    // we can't split on it (looks bad). Search for a previous
	    // break character
	    if (end == limit + 1) {
		if (!Character
			.isWhitespace(buf.charAt(lineStart + end))) {
		    end = breaks.preceding(end - 1);
		}
	    }
	    // if the last character is a space, replace it with a \n
	    if (end != BreakIterator.DONE && end == limit + 1) {
		buf.replace(lineStart + end, lineStart + end + 1, "\n");
		lineStart = lineStart + end;
	    }
	    // otherwise, just insert a \n
	    else if (end != BreakIterator.DONE && end != 0) {
		buf.insert(lineStart + end, '\n');
		lineStart = lineStart + end + 1;
	    } else {
		buf.insert(i, '\n');
		lineStart = i + 1;
	    }
	} else {
	    buf.insert(i, '\n');
	    lineStart = i + 1;
	    endOfLine = false;
	}
    }
}

return buf.toString();
   }
 
源代码19 项目: lucene-solr   文件: TestWholeBreakIterator.java
/** Asserts that two breakiterators break the text the same way */
public static void assertSameBreaks(CharacterIterator one, CharacterIterator two, BreakIterator expected, BreakIterator actual) {
  expected.setText(one);
  actual.setText(two);

  assertEquals(expected.current(), actual.current());

  // next()
  int v = expected.current();
  while (v != BreakIterator.DONE) {
    assertEquals(v = expected.next(), actual.next());
    assertEquals(expected.current(), actual.current());
  }
  
  // first()
  assertEquals(expected.first(), actual.first());
  assertEquals(expected.current(), actual.current());
  // last()
  assertEquals(expected.last(), actual.last());
  assertEquals(expected.current(), actual.current());
  
  // previous()
  v = expected.current();
  while (v != BreakIterator.DONE) {
    assertEquals(v = expected.previous(), actual.previous());
    assertEquals(expected.current(), actual.current());
  }
  
  // following()
  for (int i = one.getBeginIndex(); i <= one.getEndIndex(); i++) {
    expected.first();
    actual.first();
    assertEquals(expected.following(i), actual.following(i));
    assertEquals(expected.current(), actual.current());
  }
  
  // preceding()
  for (int i = one.getBeginIndex(); i <= one.getEndIndex(); i++) {
    expected.last();
    actual.last();
    assertEquals(expected.preceding(i), actual.preceding(i));
    assertEquals(expected.current(), actual.current());
  }
}
 
源代码20 项目: Openfire   文件: StringUtils.java
/**
 * Reformats a string where lines that are longer than {@code width}
 * are split apart at the earliest wordbreak or at maxLength, whichever is
 * sooner. If the width specified is less than 5 or greater than the input
 * Strings length the string will be returned as is.
 * <p>
 * Please note that this method can be lossy - trailing spaces on wrapped
 * lines may be trimmed.</p>
 *
 * @param input the String to reformat.
 * @param width the maximum length of any one line.
 * @param locale the local
 * @return a new String with reformatted as needed.
 */
public static String wordWrap(String input, int width, Locale locale) {
    // protect ourselves
    if (input == null) {
        return "";
    }
    else if (width < 5) {
        return input;
    }
    else if (width >= input.length()) {
        return input;
    }

    // default locale
    if (locale == null) {
        locale = JiveGlobals.getLocale();
    }

    StringBuilder buf = new StringBuilder(input);
    boolean endOfLine = false;
    int lineStart = 0;

    for (int i = 0; i < buf.length(); i++) {
        if (buf.charAt(i) == '\n') {
            lineStart = i + 1;
            endOfLine = true;
        }

        // handle splitting at width character
        if (i > lineStart + width - 1) {
            if (!endOfLine) {
                int limit = i - lineStart - 1;
                BreakIterator breaks = BreakIterator.getLineInstance(locale);
                breaks.setText(buf.substring(lineStart, i));
                int end = breaks.last();

                // if the last character in the search string isn't a space,
                // we can't split on it (looks bad). Search for a previous
                // break character
                if (end == limit + 1) {
                    if (!Character.isWhitespace(buf.charAt(lineStart + end))) {
                        end = breaks.preceding(end - 1);
                    }
                }

                // if the last character is a space, replace it with a \n
                if (end != BreakIterator.DONE && end == limit + 1) {
                    buf.replace(lineStart + end, lineStart + end + 1, "\n");
                    lineStart = lineStart + end;
                }
                // otherwise, just insert a \n
                else if (end != BreakIterator.DONE && end != 0) {
                    buf.insert(lineStart + end, '\n');
                    lineStart = lineStart + end + 1;
                }
                else {
                    buf.insert(i, '\n');
                    lineStart = i + 1;
                }
            }
            else {
                buf.insert(i, '\n');
                lineStart = i + 1;
                endOfLine = false;
            }
        }
    }

    return buf.toString();
}