aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/EditingUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin/EditingUtils.java')
-rw-r--r--java/src/com/android/inputmethod/latin/EditingUtils.java147
1 files changed, 56 insertions, 91 deletions
diff --git a/java/src/com/android/inputmethod/latin/EditingUtils.java b/java/src/com/android/inputmethod/latin/EditingUtils.java
index 90c250dcb..e56aa695d 100644
--- a/java/src/com/android/inputmethod/latin/EditingUtils.java
+++ b/java/src/com/android/inputmethod/latin/EditingUtils.java
@@ -16,13 +16,13 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.compat.InputConnectionCompatUtils;
+
import android.text.TextUtils;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.util.regex.Pattern;
/**
@@ -34,11 +34,6 @@ public class EditingUtils {
*/
private static final int LOOKBACK_CHARACTER_NUM = 15;
- // Cache Method pointers
- private static boolean sMethodsInitialized;
- private static Method sMethodGetSelectedText;
- private static Method sMethodSetComposingRegion;
-
private EditingUtils() {
// Unintentional empty constructor for singleton.
}
@@ -78,7 +73,7 @@ public class EditingUtils {
/**
* @param connection connection to the current text field.
- * @param sep characters which may separate words
+ * @param separators characters which may separate words
* @return the word that surrounds the cursor, including up to one trailing
* separator. For example, if the field contains "he|llo world", where |
* represents the cursor, then "hello " will be returned.
@@ -166,23 +161,62 @@ public class EditingUtils {
private static final Pattern spaceRegex = Pattern.compile("\\s+");
+
public static CharSequence getPreviousWord(InputConnection connection,
String sentenceSeperators) {
//TODO: Should fix this. This could be slow!
CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
- if (prev == null) {
- return null;
- }
+ return getPreviousWord(prev, sentenceSeperators);
+ }
+
+ // Get the word before the whitespace preceding the non-whitespace preceding the cursor.
+ // Also, it won't return words that end in a separator.
+ // Example :
+ // "abc def|" -> abc
+ // "abc def |" -> abc
+ // "abc def. |" -> abc
+ // "abc def . |" -> def
+ // "abc|" -> null
+ // "abc |" -> null
+ // "abc. def|" -> null
+ public static CharSequence getPreviousWord(CharSequence prev, String sentenceSeperators) {
+ if (prev == null) return null;
String[] w = spaceRegex.split(prev);
- if (w.length >= 2 && w[w.length-2].length() > 0) {
- char lastChar = w[w.length-2].charAt(w[w.length-2].length() -1);
- if (sentenceSeperators.contains(String.valueOf(lastChar))) {
- return null;
- }
- return w[w.length-2];
- } else {
- return null;
- }
+
+ // If we can't find two words, or we found an empty word, return null.
+ if (w.length < 2 || w[w.length - 2].length() <= 0) return null;
+
+ // If ends in a separator, return null
+ char lastChar = w[w.length - 2].charAt(w[w.length - 2].length() - 1);
+ if (sentenceSeperators.contains(String.valueOf(lastChar))) return null;
+
+ return w[w.length - 2];
+ }
+
+ public static CharSequence getThisWord(InputConnection connection, String sentenceSeperators) {
+ final CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
+ return getThisWord(prev, sentenceSeperators);
+ }
+
+ // Get the word immediately before the cursor, even if there is whitespace between it and
+ // the cursor - but not if there is punctuation.
+ // Example :
+ // "abc def|" -> def
+ // "abc def |" -> def
+ // "abc def. |" -> null
+ // "abc def . |" -> null
+ public static CharSequence getThisWord(CharSequence prev, String sentenceSeperators) {
+ if (prev == null) return null;
+ String[] w = spaceRegex.split(prev);
+
+ // No word : return null
+ if (w.length < 1 || w[w.length - 1].length() <= 0) return null;
+
+ // If ends in a separator, return null
+ char lastChar = w[w.length - 1].charAt(w[w.length - 1].length() - 1);
+ if (sentenceSeperators.contains(String.valueOf(lastChar))) return null;
+
+ return w[w.length - 1];
}
public static class SelectedWord {
@@ -241,7 +275,8 @@ public class EditingUtils {
}
// Extract the selection alone
- CharSequence touching = getSelectedText(ic, selStart, selEnd);
+ CharSequence touching = InputConnectionCompatUtils.getSelectedText(
+ ic, selStart, selEnd);
if (TextUtils.isEmpty(touching)) return null;
// Is any part of the selection a separator? If so, return null.
final int length = touching.length();
@@ -255,74 +290,4 @@ public class EditingUtils {
}
return null;
}
-
- /**
- * Cache method pointers for performance
- */
- private static void initializeMethodsForReflection() {
- try {
- // These will either both exist or not, so no need for separate try/catch blocks.
- // If other methods are added later, use separate try/catch blocks.
- sMethodGetSelectedText = InputConnection.class.getMethod("getSelectedText", int.class);
- sMethodSetComposingRegion = InputConnection.class.getMethod("setComposingRegion",
- int.class, int.class);
- } catch (NoSuchMethodException exc) {
- // Ignore
- }
- sMethodsInitialized = true;
- }
-
- /**
- * Returns the selected text between the selStart and selEnd positions.
- */
- private static CharSequence getSelectedText(InputConnection ic, int selStart, int selEnd) {
- // Use reflection, for backward compatibility
- CharSequence result = null;
- if (!sMethodsInitialized) {
- initializeMethodsForReflection();
- }
- if (sMethodGetSelectedText != null) {
- try {
- result = (CharSequence) sMethodGetSelectedText.invoke(ic, 0);
- return result;
- } catch (InvocationTargetException exc) {
- // Ignore
- } catch (IllegalArgumentException e) {
- // Ignore
- } catch (IllegalAccessException e) {
- // Ignore
- }
- }
- // Reflection didn't work, try it the poor way, by moving the cursor to the start,
- // getting the text after the cursor and moving the text back to selected mode.
- // TODO: Verify that this works properly in conjunction with
- // LatinIME#onUpdateSelection
- ic.setSelection(selStart, selEnd);
- result = ic.getTextAfterCursor(selEnd - selStart, 0);
- ic.setSelection(selStart, selEnd);
- return result;
- }
-
- /**
- * Tries to set the text into composition mode if there is support for it in the framework.
- */
- public static void underlineWord(InputConnection ic, SelectedWord word) {
- // Use reflection, for backward compatibility
- // If method not found, there's nothing we can do. It still works but just wont underline
- // the word.
- if (!sMethodsInitialized) {
- initializeMethodsForReflection();
- }
- if (sMethodSetComposingRegion != null) {
- try {
- sMethodSetComposingRegion.invoke(ic, word.mStart, word.mEnd);
- } catch (InvocationTargetException exc) {
- // Ignore
- } catch (IllegalArgumentException e) {
- // Ignore
- } catch (IllegalAccessException e) {
- // Ignore
- }
- }
- }
}