private int calculateLastVisibleChar(String line, int viewWidth, int firstChar, int lastChar) {
    if (firstChar == lastChar) return lastChar;
    if (firstChar > lastChar) throw new IllegalArgumentException("firstChar=" + firstChar + ", lastChar=" + lastChar);
    int totalWidth = getCurrFontMetrics().stringWidth(line.substring(firstChar, lastChar + 1));
    if (totalWidth == 0 || viewWidth > totalWidth) {
      return lastChar;
    }
    else {
      int newApprox = (lastChar - firstChar + 1) * viewWidth / totalWidth;
      int currChar = firstChar + Math.max(newApprox - 1, 0);
      int currWidth = getCurrFontMetrics().stringWidth(line.substring(firstChar, currChar + 1));
      while (true) {
        if (currWidth > viewWidth) {
          currChar--;
          if (currChar <= firstChar) {
            return firstChar;
          }
          currWidth -= getCurrFontMetrics().charWidth(line.charAt(currChar + 1));
          if (currWidth <= viewWidth) {
            return currChar;
          }
        }
        else {
          currChar++;
          if (currChar > lastChar) {
            return lastChar;
          }
          currWidth += getCurrFontMetrics().charWidth(line.charAt(currChar));
          if (currWidth >= viewWidth) {
            return currChar - 1;
          }
        }
      }
    }
  }
private int calculateLastVisibleChar(String line, int viewWidth, int firstChar, int lastChar)