diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index b333e48738f75555144d9cc279d7c1e02a35823d..79441c557bde4ca98fdb7dbbdd034c1a46354e5a 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -75,7 +75,8 @@ class BinaryDictionaryGetter {
         // This assumes '%' is fully available as a non-separator, normal
         // character in a file name. This is probably true for all file systems.
         final StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < name.length(); ++i) {
+        final int nameLength = name.length();
+        for (int i = 0; i < nameLength; i = name.offsetByCodePoints(i, 1)) {
             final int codePoint = name.codePointAt(i);
             if (isFileNameCharacter(codePoint)) {
                 sb.appendCodePoint(codePoint);
@@ -92,7 +93,8 @@ class BinaryDictionaryGetter {
      */
     private static String getWordListIdFromFileName(final String fname) {
         final StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < fname.length(); ++i) {
+        final int fnameLength = fname.length();
+        for (int i = 0; i < fnameLength; i = fname.offsetByCodePoints(i, 1)) {
             final int codePoint = fname.codePointAt(i);
             if ('%' != codePoint) {
                 sb.appendCodePoint(codePoint);
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index 8e2f605c4f0d77d34dd7dbaa08fef6492e597733..589cb6f860f4b2611fca1d964494504ee56ed1fe 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -93,7 +93,8 @@ public class SettingsValues {
         mMagicSpaceStrippers = res.getString(R.string.magic_space_stripping_symbols);
         mMagicSpaceSwappers = res.getString(R.string.magic_space_swapping_symbols);
         if (LatinImeLogger.sDBG) {
-            for (int i = 0; i < mMagicSpaceStrippers.length(); ++i) {
+            final int length = mMagicSpaceStrippers.length();
+            for (int i = 0; i < length; i = mMagicSpaceStrippers.offsetByCodePoints(i, 1)) {
                 if (isMagicSpaceSwapper(mMagicSpaceStrippers.codePointAt(i))) {
                     throw new RuntimeException("Char code " + mMagicSpaceStrippers.codePointAt(i)
                             + " is both a magic space swapper and stripper.");
@@ -234,10 +235,12 @@ public class SettingsValues {
     }
 
     public boolean isMagicSpaceStripper(int code) {
+        // TODO: this does not work if the code does not fit in a char
         return mMagicSpaceStrippers.contains(String.valueOf((char)code));
     }
 
     public boolean isMagicSpaceSwapper(int code) {
+        // TODO: this does not work if the code does not fit in a char
         return mMagicSpaceSwappers.contains(String.valueOf((char)code));
     }
 
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index bd244b91333301b3eb160c5258dddc33f241c525..fa1b5ef6c87eefa3f6f2a882c6c8188411ca5307 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -221,7 +221,8 @@ public class WordComposer {
         if (mTrailingSingleQuotesCount > 0) {
             --mTrailingSingleQuotesCount;
         } else {
-            for (int i = mTypedWord.length() - 1; i >= 0; --i) {
+            for (int i = mTypedWord.offsetByCodePoints(mTypedWord.length(), -1);
+                    i >= 0; i = mTypedWord.offsetByCodePoints(i, -1)) {
                 if (Keyboard.CODE_SINGLE_QUOTE != mTypedWord.codePointAt(i)) break;
                 ++mTrailingSingleQuotesCount;
             }
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 88ac043ed0b3e7f28cb234a0b1bfc9c3755f63a5..8ac82ee5b0ed977f6efdd8187316179b499a16ce 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -431,9 +431,9 @@ public class AndroidSpellCheckerService extends SpellCheckerService
         // If the first char is not uppercase, then the word is either all lower case,
         // and in either case we return CAPITALIZE_NONE.
         if (!Character.isUpperCase(text.codePointAt(0))) return CAPITALIZE_NONE;
-        final int len = text.codePointCount(0, text.length());
+        final int len = text.length();
         int capsCount = 1;
-        for (int i = 1; i < len; ++i) {
+        for (int i = 1; i < len; i = text.offsetByCodePoints(i, 1)) {
             if (1 != capsCount && i != capsCount) break;
             if (Character.isUpperCase(text.codePointAt(i))) ++capsCount;
         }
@@ -522,13 +522,12 @@ public class AndroidSpellCheckerService extends SpellCheckerService
             // Filter contents
             final int length = text.length();
             int letterCount = 0;
-            for (int i = 0; i < length; ++i) {
+            for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) {
                 final int codePoint = text.codePointAt(i);
                 // Any word containing a '@' is probably an e-mail address
                 // Any word containing a '/' is probably either an ad-hoc combination of two
                 // words or a URI - in either case we don't want to spell check that
-                if ('@' == codePoint
-                        || '/' == codePoint) return true;
+                if ('@' == codePoint || '/' == codePoint) return true;
                 if (isLetterCheckableByLanguage(codePoint, script)) ++letterCount;
             }
             // Guestimate heuristic: perform spell checking if at least 3/4 of the characters
@@ -570,7 +569,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService
                         suggestionsLimit);
                 final WordComposer composer = new WordComposer();
                 final int length = text.length();
-                for (int i = 0; i < length; ++i) {
+                for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) {
                     final int character = text.codePointAt(i);
                     final int proximityIndex =
                             SpellCheckerProximityInfo.getIndexOfCodeForScript(character, mScript);
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
index 8c0ccd40bba3593077cd8531034c74b8288f7a88..af647b8ce1447ee80352debc1a5651faaa1bd5f6 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -133,7 +133,7 @@ public class InputLogicTests extends ServiceTestCase<LatinIME> {
     }
 
     private void type(final String stringToType) {
-        for (int i = 0; i < stringToType.length(); ++i) {
+        for (int i = 0; i < stringToType.length(); i = stringToType.offsetByCodePoints(i, 1)) {
             type(stringToType.codePointAt(i));
         }
     }
diff --git a/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java b/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java
index 918b1ca4bd8727a292fd7a7474467d5aff7611f9..08143d3eafb1611ae4768364a26ff356b7165ff0 100644
--- a/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java
+++ b/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java
@@ -164,7 +164,7 @@ public class FusionDictionary implements Iterable<Word> {
     static private int[] getCodePoints(String word) {
         final int wordLength = word.length();
         int[] array = new int[word.codePointCount(0, wordLength)];
-        for (int i = 0; i < wordLength; ++i) {
+        for (int i = 0; i < wordLength; i = word.offsetByCodePoints(i, 1)) {
             array[i] = word.codePointAt(i);
         }
         return array;