/** Replaces the current word token */ public void replaceWord(String newWord) { if (currentWordPos != -1) { try { /* ORIGINAL document.remove(currentWordPos, currentWordEnd - currentWordPos); document.insertString(currentWordPos, newWord, null); */ // Howard's Version for Ekit Element element = ((javax.swing.text.html.HTMLDocument) document).getCharacterElement(currentWordPos); AttributeSet attribs = element.getAttributes(); document.remove(currentWordPos, currentWordEnd - currentWordPos); document.insertString(currentWordPos, newWord, attribs); // End Howard's Version // Need to reset the segment document.getText(0, document.getLength(), text); } catch (BadLocationException ex) { throw new RuntimeException(ex.getMessage()); } // Position after the newly replaced word(s) // Position after the newly replaced word(s) first = true; currentWordPos = getNextWordStart(text, currentWordPos + newWord.length()); if (currentWordPos != -1) { currentWordEnd = getNextWordEnd(text, currentWordPos); nextWordPos = getNextWordStart(text, currentWordEnd); sentanceIterator.setText(text); sentanceIterator.following(currentWordPos); } else moreTokens = false; } }
/** * Take the given filter text and break it down into words using a BreakIterator. * * @param text * @return an array of words */ private String[] getWords(String text) { List<String> words = new ArrayList<String>(); /* * Break the text up into words, separating based on whitespace and common * punctuation. Previously used String.split(..., "\\W"), where "\W" is a * regular expression (see the Javadoc for class Pattern). Need to avoid * both String.split and regular expressions, in order to compile against * JCL Foundation (bug 80053). Also need to do this in an NL-sensitive way. * The use of BreakIterator was suggested in bug 90579. */ BreakIterator iter = BreakIterator.getWordInstance(); iter.setText(text); int i = iter.first(); while (i != java.text.BreakIterator.DONE && i < text.length()) { int j = iter.following(i); if (j == java.text.BreakIterator.DONE) j = text.length(); /* match the word */ if (Character.isLetterOrDigit(text.charAt(i))) { String word = text.substring(i, j); words.add(word); } i = j; } return words.toArray(new String[words.size()]); }
private static void checkFollowingException(BreakIterator bi, int offset) { try { bi.following(offset); } catch (IllegalArgumentException e) { return; // OK } throw new RuntimeException(bi + ": following() doesn't throw an IAE with offset " + offset); }
/** * If <code>offset</code> is within a word, returns the index of the last character of that word * plus one, otherwise returns BreakIterator.DONE. * * <p>The offsets that are considered to be part of a word are the indexes of its characters, * <i>as well as</i> the index of its last character plus one. If offset is the index of a low * surrogate character, BreakIterator.DONE will be returned. * * <p>Valid range for offset is [0..textLength] (note the inclusive upper bound). The returned * value is within [offset..textLength] or BreakIterator.DONE. * * @throws IllegalArgumentException is offset is not valid. */ public int getEnd(int offset) { final int shiftedOffset = offset - mOffsetShift; checkOffsetIsValid(shiftedOffset); if (isAfterLetterOrDigit(shiftedOffset)) { if (mIterator.isBoundary(shiftedOffset)) { return shiftedOffset + mOffsetShift; } else { return mIterator.following(shiftedOffset) + mOffsetShift; } } else { if (isOnLetterOrDigit(shiftedOffset)) { return mIterator.following(shiftedOffset) + mOffsetShift; } } return BreakIterator.DONE; }
/** * Returns the position of next boundary after the given offset. Returns {@code DONE} if there is * no boundary after the given offset. * * @param offset the given start position to search from. * @return the position of the last boundary preceding the given offset. */ public int nextBoundary(int offset) { int shiftedOffset = offset - mOffsetShift; shiftedOffset = mIterator.following(shiftedOffset); if (shiftedOffset == BreakIterator.DONE) { return BreakIterator.DONE; } return shiftedOffset + mOffsetShift; }
// offsets on any line will go from start,true to end,false // excluding start,false and end,true public Selection point2Offset(Point p, Selection o) { if (p.y < yInset) { o.caret = 0; o.clickAfter = true; return o; } int line = (p.y - yInset) / lineHeight; if (line >= lineCount) { o.caret = contents.length(); o.clickAfter = false; return o; } int target = p.x - xInset; if (target <= 0) { o.caret = lineStarts[line]; o.clickAfter = true; return o; } int lowGuess = lineStarts[line]; int lowWidth = 0; int highGuess = lineStarts[line + 1]; int highWidth = fm.stringWidth(contents.substring(lineStarts[line], highGuess)); if (target >= highWidth) { o.caret = lineStarts[line + 1]; o.clickAfter = false; return o; } while (lowGuess < highGuess - 1) { int guess = (lowGuess + highGuess) / 2; int width = fm.stringWidth(contents.substring(lineStarts[line], guess)); if (width <= target) { lowGuess = guess; lowWidth = width; if (width == target) break; } else { highGuess = guess; highWidth = width; } } // at end, either lowWidth < target < width(low+1), or lowWidth = target int highBound = charBreaker.following(lowGuess); int lowBound = charBreaker.previous(); // we are now at character boundaries if (lowBound != lowGuess) lowWidth = fm.stringWidth(contents.substring(lineStarts[line], lowBound)); if (highBound != highGuess) highWidth = fm.stringWidth(contents.substring(lineStarts[line], highBound)); // we now have the right widths if (target - lowWidth < highWidth - target) { o.caret = lowBound; o.clickAfter = true; } else { o.caret = highBound; o.clickAfter = false; } // we now have the closest! return o; }
/** {@inheritDoc} */ public int following(int offset) { int shiftedOffset = offset - mOffsetShift; do { shiftedOffset = mIterator.following(shiftedOffset); if (shiftedOffset == BreakIterator.DONE) { return BreakIterator.DONE; } if (isAfterLetterOrDigit(shiftedOffset)) { return shiftedOffset + mOffsetShift; } } while (true); }
private void makeLayoutWindow(int localStart) { int compStart = localStart; int compLimit = fChars.length; // If we've already gone past the layout window, format to end of paragraph if (layoutCount > 0 && !haveLayoutWindow) { float avgLineLength = Math.max(layoutCharCount / layoutCount, 1); compLimit = Math.min(localStart + (int) (avgLineLength * EST_LINES), fChars.length); } if (localStart > 0 || compLimit < fChars.length) { if (charIter == null) { charIter = new CharArrayIterator(fChars); } else { charIter.reset(fChars); } if (fLineBreak == null) { fLineBreak = BreakIterator.getLineInstance(); } fLineBreak.setText(charIter); if (localStart > 0) { if (!fLineBreak.isBoundary(localStart)) { compStart = fLineBreak.preceding(localStart); } } if (compLimit < fChars.length) { if (!fLineBreak.isBoundary(compLimit)) { compLimit = fLineBreak.following(compLimit); } } } ensureComponents(compStart, compLimit); haveLayoutWindow = true; }
public static void main(String[] args) { BreakIterator bi = BreakIterator.getWordInstance(); bi.setText(text); MirroredBreakIterator mirror = new MirroredBreakIterator(bi); final int first = bi.first(); if (first != 0) { throw new RuntimeException("first != 0: " + first); } final int last = bi.last(); bi = BreakIterator.getWordInstance(); bi.setText(text); int length = text.length(); /* * following(int) */ for (int i = 0; i <= length; i++) { if (i == length) { check(bi.following(i), DONE); } check(bi.following(i), mirror.following(i)); check(bi.current(), mirror.current()); } for (int i = -length; i < 0; i++) { checkFollowingException(bi, i); checkFollowingException(mirror, i); check(bi.current(), mirror.current()); } for (int i = 1; i < length; i++) { checkFollowingException(bi, length + i); checkFollowingException(mirror, length + i); check(bi.current(), mirror.current()); } /* * preceding(int) */ for (int i = length; i >= 0; i--) { if (i == 0) { check(bi.preceding(i), DONE); } check(bi.preceding(i), mirror.preceding(i)); check(bi.current(), mirror.current()); } for (int i = -length; i < 0; i++) { checkPrecedingException(bi, i); checkPrecedingException(mirror, i); check(bi.current(), mirror.current()); } for (int i = 1; i < length; i++) { checkPrecedingException(bi, length + i); checkPrecedingException(mirror, length + i); check(bi.current(), mirror.current()); } /* * isBoundary(int) */ for (int i = 0; i <= length; i++) { check(bi.isBoundary(i), mirror.isBoundary(i)); check(bi.current(), mirror.current()); } for (int i = -length; i < 0; i++) { checkIsBoundaryException(bi, i); checkIsBoundaryException(mirror, i); } for (int i = 1; i < length; i++) { checkIsBoundaryException(bi, length + i); checkIsBoundaryException(mirror, length + i); } }