Program: 87397
Project: 87397
Buggy source:
/** 
 * Determine what caps mode should be in effect at the current offset in the text. Only the mode bits set in <var>reqModes</var> will be checked. Note that the caps mode flags here are explicitly defined to match those in   {@link InputType}. This code is a straight copy of TextUtils.getCapsMode (modulo namespace and formatting issues). This will change in the future as we simplify the code for our use and fix bugs.
 * @param cs The text that should be checked for caps modes.
 * @param reqModes The modes to be checked: may be any combination of{@link TextUtils#CAP_MODE_CHARACTERS},   {@link TextUtils#CAP_MODE_WORDS}, and  {@link TextUtils#CAP_MODE_SENTENCES}.
 * @param spacingAndPunctuations The current spacing and punctuations settings.
 * @param hasSpaceBefore Whether we should consider there is a space inserted at the end of cs
 * @return Returns the actual capitalization modes that can be in effectat the current position, which is any combination of {@link TextUtils#CAP_MODE_CHARACTERS},   {@link TextUtils#CAP_MODE_WORDS}, and  {@link TextUtils#CAP_MODE_SENTENCES}.
 */
public static int getCapsMode(final CharSequence cs,final int reqModes,final SpacingAndPunctuations spacingAndPunctuations,final boolean hasSpaceBefore){
  if ((reqModes & (TextUtils.CAP_MODE_WORDS | TextUtils.CAP_MODE_SENTENCES)) == 0) {
    return TextUtils.CAP_MODE_CHARACTERS & reqModes;
  }
  int i;
  if (hasSpaceBefore) {
    i=cs.length() + 1;
  }
 else {
    for (i=cs.length(); i > 0; i--) {
      final char c=cs.charAt(i - 1);
      if (c != Constants.CODE_DOUBLE_QUOTE && c != Constants.CODE_SINGLE_QUOTE && Character.getType(c) != Character.START_PUNCTUATION) {
        break;
      }
    }
  }
  int j=i;
  char prevChar=Constants.CODE_SPACE;
  if (hasSpaceBefore)   --j;
  while (j > 0) {
    prevChar=cs.charAt(j - 1);
    if (!Character.isSpaceChar(prevChar) && prevChar != Constants.CODE_TAB)     break;
    j--;
  }
  if (j <= 0 || Character.isWhitespace(prevChar)) {
    if (spacingAndPunctuations.mUsesGermanRules) {
      boolean hasNewLine=false;
      while (--j >= 0 && Character.isWhitespace(prevChar)) {
        if (Constants.CODE_ENTER == prevChar) {
          hasNewLine=true;
        }
        prevChar=cs.charAt(j);
      }
      if (Constants.CODE_COMMA == prevChar && hasNewLine) {
        return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes;
      }
    }
    return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS | TextUtils.CAP_MODE_SENTENCES) & reqModes;
  }
  if (i == j) {
    return TextUtils.CAP_MODE_CHARACTERS & reqModes;
  }
  if ((reqModes & TextUtils.CAP_MODE_SENTENCES) == 0) {
    return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes;
  }
  if (spacingAndPunctuations.mUsesAmericanTypography) {
    for (; j > 0; j--) {
      final char c=cs.charAt(j - 1);
      if (c != Constants.CODE_DOUBLE_QUOTE && c != Constants.CODE_SINGLE_QUOTE && Character.getType(c) != Character.END_PUNCTUATION) {
        break;
      }
    }
  }
  if (j <= 0)   return TextUtils.CAP_MODE_CHARACTERS & reqModes;
  char c=cs.charAt(--j);
  if (c == Constants.CODE_QUESTION_MARK || c == Constants.CODE_EXCLAMATION_MARK) {
    return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_SENTENCES) & reqModes;
  }
  if (!spacingAndPunctuations.isSentenceSeparator(c) || j <= 0) {
    return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes;
  }
  final int START=0;
  final int WORD=1;
  final int PERIOD=2;
  final int LETTER=3;
  final int caps=(TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS | TextUtils.CAP_MODE_SENTENCES) & reqModes;
  final int noCaps=(TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes;
  int state=START;
  while (j > 0) {
    c=cs.charAt(--j);
switch (state) {
case START:
      if (Character.isLetter(c)) {
        state=WORD;
      }
 else       if (Character.isWhitespace(c)) {
        return noCaps;
      }
 else {
        return caps;
      }
    break;
case WORD:
  if (Character.isLetter(c)) {
    state=WORD;
  }
 else   if (spacingAndPunctuations.isSentenceSeparator(c)) {
    state=PERIOD;
  }
 else {
    return caps;
  }
break;
case PERIOD:
if (Character.isLetter(c)) {
state=LETTER;
}
 else {
return caps;
}
break;
case LETTER:
if (Character.isLetter(c)) {
state=LETTER;
}
 else if (spacingAndPunctuations.isSentenceSeparator(c)) {
state=PERIOD;
}
 else {
return noCaps;
}
}
}
return (START == state || LETTER == state) ? noCaps : caps;
}

Fixed version (ground truth):
/** 
 * Determine what caps mode should be in effect at the current offset in the text. Only the mode bits set in <var>reqModes</var> will be checked. Note that the caps mode flags here are explicitly defined to match those in   {@link InputType}. This code is a straight copy of TextUtils.getCapsMode (modulo namespace and formatting issues). This will change in the future as we simplify the code for our use and fix bugs.
 * @param cs The text that should be checked for caps modes.
 * @param reqModes The modes to be checked: may be any combination of{@link TextUtils#CAP_MODE_CHARACTERS},   {@link TextUtils#CAP_MODE_WORDS}, and  {@link TextUtils#CAP_MODE_SENTENCES}.
 * @param spacingAndPunctuations The current spacing and punctuations settings.
 * @param hasSpaceBefore Whether we should consider there is a space inserted at the end of cs
 * @return Returns the actual capitalization modes that can be in effectat the current position, which is any combination of {@link TextUtils#CAP_MODE_CHARACTERS},   {@link TextUtils#CAP_MODE_WORDS}, and  {@link TextUtils#CAP_MODE_SENTENCES}.
 */
public static int getCapsMode(final CharSequence cs,final int reqModes,final SpacingAndPunctuations spacingAndPunctuations,final boolean hasSpaceBefore){
  if ((reqModes & (TextUtils.CAP_MODE_WORDS | TextUtils.CAP_MODE_SENTENCES)) == 0) {
    return TextUtils.CAP_MODE_CHARACTERS & reqModes;
  }
  int i;
  if (hasSpaceBefore) {
    i=cs.length() + 1;
  }
 else {
    for (i=cs.length(); i > 0; i--) {
      final char c=cs.charAt(i - 1);
      if (!isStartPunctuation(c)) {
        break;
      }
    }
  }
  int j=i;
  char prevChar=Constants.CODE_SPACE;
  if (hasSpaceBefore)   --j;
  while (j > 0) {
    prevChar=cs.charAt(j - 1);
    if (!Character.isSpaceChar(prevChar) && prevChar != Constants.CODE_TAB)     break;
    j--;
  }
  if (j <= 0 || Character.isWhitespace(prevChar)) {
    if (spacingAndPunctuations.mUsesGermanRules) {
      boolean hasNewLine=false;
      while (--j >= 0 && Character.isWhitespace(prevChar)) {
        if (Constants.CODE_ENTER == prevChar) {
          hasNewLine=true;
        }
        prevChar=cs.charAt(j);
      }
      if (Constants.CODE_COMMA == prevChar && hasNewLine) {
        return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes;
      }
    }
    return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS | TextUtils.CAP_MODE_SENTENCES) & reqModes;
  }
  if (i == j) {
    return TextUtils.CAP_MODE_CHARACTERS & reqModes;
  }
  if ((reqModes & TextUtils.CAP_MODE_SENTENCES) == 0) {
    return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes;
  }
  if (spacingAndPunctuations.mUsesAmericanTypography) {
    for (; j > 0; j--) {
      final char c=cs.charAt(j - 1);
      if (c != Constants.CODE_DOUBLE_QUOTE && c != Constants.CODE_SINGLE_QUOTE && Character.getType(c) != Character.END_PUNCTUATION) {
        break;
      }
    }
  }
  if (j <= 0)   return TextUtils.CAP_MODE_CHARACTERS & reqModes;
  char c=cs.charAt(--j);
  if (c == Constants.CODE_QUESTION_MARK || c == Constants.CODE_EXCLAMATION_MARK) {
    return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_SENTENCES) & reqModes;
  }
  if (!spacingAndPunctuations.isSentenceSeparator(c) || j <= 0) {
    return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes;
  }
  final int START=0;
  final int WORD=1;
  final int PERIOD=2;
  final int LETTER=3;
  final int NUMBER=4;
  final int caps=(TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS | TextUtils.CAP_MODE_SENTENCES) & reqModes;
  final int noCaps=(TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes;
  int state=START;
  while (j > 0) {
    c=cs.charAt(--j);
switch (state) {
case START:
      if (Character.isLetter(c)) {
        state=WORD;
      }
 else       if (Character.isWhitespace(c)) {
        return noCaps;
      }
 else       if (Character.isDigit(c) && spacingAndPunctuations.mUsesGermanRules) {
        state=NUMBER;
      }
 else {
        return caps;
      }
    break;
case WORD:
  if (Character.isLetter(c)) {
    state=WORD;
  }
 else   if (spacingAndPunctuations.isSentenceSeparator(c)) {
    state=PERIOD;
  }
 else {
    return caps;
  }
break;
case PERIOD:
if (Character.isLetter(c)) {
state=LETTER;
}
 else {
return caps;
}
break;
case LETTER:
if (Character.isLetter(c)) {
state=LETTER;
}
 else if (spacingAndPunctuations.isSentenceSeparator(c)) {
state=PERIOD;
}
 else {
return noCaps;
}
break;
case NUMBER:
if (Character.isLetter(c)) {
state=WORD;
}
 else if (Character.isDigit(c)) {
state=NUMBER;
}
 else {
return noCaps;
}
}
}
return (START == state || LETTER == state) ? noCaps : caps;
}