Index: javax/swing/text/Utilities.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/text/Utilities.java,v retrieving revision 1.11 diff -u -r1.11 Utilities.java --- javax/swing/text/Utilities.java 22 Sep 2005 20:17:08 -0000 1.11 +++ javax/swing/text/Utilities.java 26 Sep 2005 20:31:45 -0000 @@ -394,4 +394,79 @@ wb.setText(text); return wb.following(offs); } + + /** + * Get the model position of the end of the row that contains the + * specified model position. Return null if the given JTextComponent + * does not have a size. + * @param c the JTextComponent + * @param offs the model position + * @return the model position of the end of the row containing the given + * offset + * @throws BadLocationException if the offset is invalid + */ + public static final int getRowEnd(JTextComponent c, int offs) + throws BadLocationException + { + Element root = c.getDocument().getDefaultRootElement(); + Element rowElement = root.getElement(root.getElementIndex(offs)); + String text = c.getText(rowElement.getStartOffset(), + rowElement.getEndOffset()); + if (text == null) + return -1; + + //Start at offs and iterate character by character until one of them + //is on the next line. This is poor performance, could be improved + //by calculating an approximate number of columns per row using + //the preferred size of the JTextComponent and the width of an + //arbitary character in whichever font is in use. Could increment i + //by (for example) half this value until incrementing it again would + //make the if statement true, then increment it by a smaller value + //until doing so would make the if statement true. Basically, use + //coarse increments until we need to fine tune to character by character. + for (int i = offs; i < text.length() - 1; i++) + { + if (c.modelToView(i).y != c.modelToView(offs).y) + return i - 1; + } + return text.length() - 1; + } + + /** + * Get the model position of the start of the row that contains the specified + * model position. Return null if the given JTextComponent does not have a + * size. + * + * @param c the JTextComponent + * @param offs the model position + * @return the model position of the start of the row containing the given + * offset + * @throws BadLocationException if the offset is invalid + */ + public static final int getRowStart(JTextComponent c, int offs) + throws BadLocationException + { + Element root = c.getDocument().getDefaultRootElement(); + Element rowElement = root.getElement(root.getElementIndex(offs)); + String text = c.getText(rowElement.getStartOffset(), + rowElement.getEndOffset()); + if (text == null) + return -1; + + //Start at offs and iterate character by character until one of them + //is on the previous line. This is poor performance, could be improved + //by calculating an approximate number of columns per row using + //the preferred size of the JTextComponent and the width of an + //arbitary character in whichever font is in use. Could increment i + //by (for example) half this value until incrementing it again would + //make the if statement true, then increment it by a smaller value + //until doing so would make the if statement true. Basically, use + //coarse increments until we need to fine tune to character by character. + for (int i = offs; i > 0; i--) + { + if (c.modelToView(i).y != c.modelToView(offs).y) + return i + 1; + } + return 0; + } }