RichInputConnectionAndTextRangeTests.java revision 292deb632cbab232334190e68d29184094d6d51b
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.inputmethod.latin; 18 19import android.content.res.Resources; 20import android.inputmethodservice.InputMethodService; 21import android.os.Parcel; 22import android.test.AndroidTestCase; 23import android.test.MoreAsserts; 24import android.test.suitebuilder.annotation.SmallTest; 25import android.text.SpannableString; 26import android.text.TextUtils; 27import android.text.style.SuggestionSpan; 28import android.view.inputmethod.ExtractedText; 29import android.view.inputmethod.ExtractedTextRequest; 30import android.view.inputmethod.InputConnection; 31import android.view.inputmethod.InputConnectionWrapper; 32 33import com.android.inputmethod.latin.PrevWordsInfo.WordInfo; 34import com.android.inputmethod.latin.settings.SpacingAndPunctuations; 35import com.android.inputmethod.latin.utils.RunInLocale; 36import com.android.inputmethod.latin.utils.ScriptUtils; 37import com.android.inputmethod.latin.utils.StringUtils; 38import com.android.inputmethod.latin.utils.TextRange; 39 40import java.util.Locale; 41 42@SmallTest 43public class RichInputConnectionAndTextRangeTests extends AndroidTestCase { 44 45 // The following is meant to be a reasonable default for 46 // the "word_separators" resource. 47 private SpacingAndPunctuations mSpacingAndPunctuations; 48 49 @Override 50 protected void setUp() throws Exception { 51 super.setUp(); 52 final RunInLocale<SpacingAndPunctuations> job = new RunInLocale<SpacingAndPunctuations>() { 53 @Override 54 protected SpacingAndPunctuations job(final Resources res) { 55 return new SpacingAndPunctuations(res); 56 } 57 }; 58 final Resources res = getContext().getResources(); 59 mSpacingAndPunctuations = job.runInLocale(res, Locale.ENGLISH); 60 } 61 62 private class MockConnection extends InputConnectionWrapper { 63 final CharSequence mTextBefore; 64 final CharSequence mTextAfter; 65 final ExtractedText mExtractedText; 66 67 public MockConnection(final CharSequence text, final int cursorPosition) { 68 super(null, false); 69 // Interaction of spans with Parcels is completely non-trivial, but in the actual case 70 // the CharSequences do go through Parcels because they go through IPC. There 71 // are some significant differences between the behavior of Spanned objects that 72 // have and that have not gone through parceling, so it's much easier to simulate 73 // the environment with Parcels than try to emulate things by hand. 74 final Parcel p = Parcel.obtain(); 75 TextUtils.writeToParcel(text.subSequence(0, cursorPosition), p, 0 /* flags */); 76 TextUtils.writeToParcel(text.subSequence(cursorPosition, text.length()), p, 77 0 /* flags */); 78 final byte[] marshalled = p.marshall(); 79 p.unmarshall(marshalled, 0, marshalled.length); 80 p.setDataPosition(0); 81 mTextBefore = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p); 82 mTextAfter = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(p); 83 mExtractedText = null; 84 p.recycle(); 85 } 86 87 public MockConnection(String textBefore, String textAfter, ExtractedText extractedText) { 88 super(null, false); 89 mTextBefore = textBefore; 90 mTextAfter = textAfter; 91 mExtractedText = extractedText; 92 } 93 94 public int cursorPos() { 95 return mTextBefore.length(); 96 } 97 98 /* (non-Javadoc) 99 * @see android.view.inputmethod.InputConnectionWrapper#getTextBeforeCursor(int, int) 100 */ 101 @Override 102 public CharSequence getTextBeforeCursor(int n, int flags) { 103 return mTextBefore; 104 } 105 106 /* (non-Javadoc) 107 * @see android.view.inputmethod.InputConnectionWrapper#getTextAfterCursor(int, int) 108 */ 109 @Override 110 public CharSequence getTextAfterCursor(int n, int flags) { 111 return mTextAfter; 112 } 113 114 /* (non-Javadoc) 115 * @see android.view.inputmethod.InputConnectionWrapper#getExtractedText( 116 * ExtractedTextRequest, int) 117 */ 118 @Override 119 public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) { 120 return mExtractedText; 121 } 122 123 @Override 124 public boolean beginBatchEdit() { 125 return true; 126 } 127 128 @Override 129 public boolean endBatchEdit() { 130 return true; 131 } 132 133 @Override 134 public boolean finishComposingText() { 135 return true; 136 } 137 } 138 139 private class MockInputMethodService extends InputMethodService { 140 private MockConnection mMockConnection; 141 public void setInputConnection(final MockConnection mockConnection) { 142 mMockConnection = mockConnection; 143 } 144 public int cursorPos() { 145 return mMockConnection.cursorPos(); 146 } 147 @Override 148 public InputConnection getCurrentInputConnection() { 149 return mMockConnection; 150 } 151 } 152 153 /************************** Tests ************************/ 154 155 /** 156 * Test for getting previous word (for bigram suggestions) 157 */ 158 public void testGetPreviousWord() { 159 // If one of the following cases breaks, the bigram suggestions won't work. 160 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 161 "abc def", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mWord, "abc"); 162 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 163 "abc", mSpacingAndPunctuations, 2), PrevWordsInfo.BEGINNING_OF_SENTENCE); 164 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 165 "abc. def", mSpacingAndPunctuations, 2), PrevWordsInfo.BEGINNING_OF_SENTENCE); 166 167 assertFalse(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 168 "abc def", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mIsBeginningOfSentence); 169 assertTrue(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 170 "abc", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mIsBeginningOfSentence); 171 172 // For n-gram 173 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 174 "abc def", mSpacingAndPunctuations, 1).mPrevWordsInfo[0].mWord, "def"); 175 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 176 "abc def", mSpacingAndPunctuations, 1).mPrevWordsInfo[1].mWord, "abc"); 177 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 178 "abc def", mSpacingAndPunctuations, 2).mPrevWordsInfo[1], 179 WordInfo.BEGINNING_OF_SENTENCE); 180 181 // The following tests reflect the current behavior of the function 182 // RichInputConnection#getNthPreviousWord. 183 // TODO: However at this time, the code does never go 184 // into such a path, so it should be safe to change the behavior of 185 // this function if needed - especially since it does not seem very 186 // logical. These tests are just there to catch any unintentional 187 // changes in the behavior of the RichInputConnection#getPreviousWord method. 188 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 189 "abc def ", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mWord, "abc"); 190 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 191 "abc def.", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mWord, "abc"); 192 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 193 "abc def .", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mWord, "def"); 194 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 195 "abc ", mSpacingAndPunctuations, 2), PrevWordsInfo.BEGINNING_OF_SENTENCE); 196 197 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 198 "abc def", mSpacingAndPunctuations, 1).mPrevWordsInfo[0].mWord, "def"); 199 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 200 "abc def ", mSpacingAndPunctuations, 1).mPrevWordsInfo[0].mWord, "def"); 201 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 202 "abc 'def", mSpacingAndPunctuations, 1).mPrevWordsInfo[0].mWord, "'def"); 203 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 204 "abc def.", mSpacingAndPunctuations, 1), PrevWordsInfo.BEGINNING_OF_SENTENCE); 205 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 206 "abc def .", mSpacingAndPunctuations, 1), PrevWordsInfo.BEGINNING_OF_SENTENCE); 207 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 208 "abc, def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO); 209 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 210 "abc? def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO); 211 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 212 "abc! def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO); 213 assertEquals(RichInputConnection.getPrevWordsInfoFromNthPreviousWord( 214 "abc 'def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO); 215 } 216 217 /** 218 * Test logic in getting the word range at the cursor. 219 */ 220 private static final int[] SPACE = { Constants.CODE_SPACE }; 221 static final int[] TAB = { Constants.CODE_TAB }; 222 private static final int[] SPACE_TAB = StringUtils.toSortedCodePointArray(" \t"); 223 // A character that needs surrogate pair to represent its code point (U+2008A). 224 private static final String SUPPLEMENTARY_CHAR = "\uD840\uDC8A"; 225 private static final String HIRAGANA_WORD = "\u3042\u3044\u3046\u3048\u304A"; // あいうえお 226 private static final String GREEK_WORD = "\u03BA\u03B1\u03B9"; // και 227 228 public void testGetWordRangeAtCursor() { 229 ExtractedText et = new ExtractedText(); 230 final MockInputMethodService mockInputMethodService = new MockInputMethodService(); 231 final RichInputConnection ic = new RichInputConnection(mockInputMethodService); 232 mockInputMethodService.setInputConnection(new MockConnection("word wo", "rd", et)); 233 et.startOffset = 0; 234 et.selectionStart = 7; 235 TextRange r; 236 237 ic.beginBatchEdit(); 238 // basic case 239 r = ic.getWordRangeAtCursor(SPACE, ScriptUtils.SCRIPT_LATIN); 240 assertTrue(TextUtils.equals("word", r.mWord)); 241 242 // tab character instead of space 243 mockInputMethodService.setInputConnection(new MockConnection("one\tword\two", "rd", et)); 244 ic.beginBatchEdit(); 245 r = ic.getWordRangeAtCursor(TAB, ScriptUtils.SCRIPT_LATIN); 246 ic.endBatchEdit(); 247 assertTrue(TextUtils.equals("word", r.mWord)); 248 249 // splitting on supplementary character 250 mockInputMethodService.setInputConnection( 251 new MockConnection("one word" + SUPPLEMENTARY_CHAR + "wo", "rd", et)); 252 ic.beginBatchEdit(); 253 r = ic.getWordRangeAtCursor(StringUtils.toSortedCodePointArray(SUPPLEMENTARY_CHAR), 254 ScriptUtils.SCRIPT_LATIN); 255 ic.endBatchEdit(); 256 assertTrue(TextUtils.equals("word", r.mWord)); 257 258 // split on chars outside the specified script 259 mockInputMethodService.setInputConnection( 260 new MockConnection(HIRAGANA_WORD + "wo", "rd" + GREEK_WORD, et)); 261 ic.beginBatchEdit(); 262 r = ic.getWordRangeAtCursor(StringUtils.toSortedCodePointArray(SUPPLEMENTARY_CHAR), 263 ScriptUtils.SCRIPT_LATIN); 264 ic.endBatchEdit(); 265 assertTrue(TextUtils.equals("word", r.mWord)); 266 267 // likewise for greek 268 mockInputMethodService.setInputConnection( 269 new MockConnection("text" + GREEK_WORD, "text", et)); 270 ic.beginBatchEdit(); 271 r = ic.getWordRangeAtCursor(StringUtils.toSortedCodePointArray(SUPPLEMENTARY_CHAR), 272 ScriptUtils.SCRIPT_GREEK); 273 ic.endBatchEdit(); 274 assertTrue(TextUtils.equals(GREEK_WORD, r.mWord)); 275 } 276 277 /** 278 * Test logic in getting the word range at the cursor. 279 */ 280 public void testGetSuggestionSpansAtWord() { 281 helpTestGetSuggestionSpansAtWord(10); 282 helpTestGetSuggestionSpansAtWord(12); 283 helpTestGetSuggestionSpansAtWord(15); 284 helpTestGetSuggestionSpansAtWord(16); 285 } 286 287 private void helpTestGetSuggestionSpansAtWord(final int cursorPos) { 288 final MockInputMethodService mockInputMethodService = new MockInputMethodService(); 289 final RichInputConnection ic = new RichInputConnection(mockInputMethodService); 290 291 final String[] SUGGESTIONS1 = { "swing", "strong" }; 292 final String[] SUGGESTIONS2 = { "storing", "strung" }; 293 294 // Test the usual case. 295 SpannableString text = new SpannableString("This is a string for test"); 296 text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */), 297 10 /* start */, 16 /* end */, 0 /* flags */); 298 mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos)); 299 TextRange r; 300 SuggestionSpan[] suggestions; 301 302 r = ic.getWordRangeAtCursor(SPACE, ScriptUtils.SCRIPT_LATIN); 303 suggestions = r.getSuggestionSpansAtWord(); 304 assertEquals(suggestions.length, 1); 305 MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1); 306 307 // Test the case with 2 suggestion spans in the same place. 308 text = new SpannableString("This is a string for test"); 309 text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */), 310 10 /* start */, 16 /* end */, 0 /* flags */); 311 text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */), 312 10 /* start */, 16 /* end */, 0 /* flags */); 313 mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos)); 314 r = ic.getWordRangeAtCursor(SPACE, ScriptUtils.SCRIPT_LATIN); 315 suggestions = r.getSuggestionSpansAtWord(); 316 assertEquals(suggestions.length, 2); 317 MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1); 318 MoreAsserts.assertEquals(suggestions[1].getSuggestions(), SUGGESTIONS2); 319 320 // Test a case with overlapping spans, 2nd extending past the start of the word 321 text = new SpannableString("This is a string for test"); 322 text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */), 323 10 /* start */, 16 /* end */, 0 /* flags */); 324 text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */), 325 5 /* start */, 16 /* end */, 0 /* flags */); 326 mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos)); 327 r = ic.getWordRangeAtCursor(SPACE, ScriptUtils.SCRIPT_LATIN); 328 suggestions = r.getSuggestionSpansAtWord(); 329 assertEquals(suggestions.length, 1); 330 MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1); 331 332 // Test a case with overlapping spans, 2nd extending past the end of the word 333 text = new SpannableString("This is a string for test"); 334 text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */), 335 10 /* start */, 16 /* end */, 0 /* flags */); 336 text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */), 337 10 /* start */, 20 /* end */, 0 /* flags */); 338 mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos)); 339 r = ic.getWordRangeAtCursor(SPACE, ScriptUtils.SCRIPT_LATIN); 340 suggestions = r.getSuggestionSpansAtWord(); 341 assertEquals(suggestions.length, 1); 342 MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1); 343 344 // Test a case with overlapping spans, 2nd extending past both ends of the word 345 text = new SpannableString("This is a string for test"); 346 text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */), 347 10 /* start */, 16 /* end */, 0 /* flags */); 348 text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */), 349 5 /* start */, 20 /* end */, 0 /* flags */); 350 mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos)); 351 r = ic.getWordRangeAtCursor(SPACE, ScriptUtils.SCRIPT_LATIN); 352 suggestions = r.getSuggestionSpansAtWord(); 353 assertEquals(suggestions.length, 1); 354 MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1); 355 356 // Test a case with overlapping spans, none right on the word 357 text = new SpannableString("This is a string for test"); 358 text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS1, 0 /* flags */), 359 5 /* start */, 16 /* end */, 0 /* flags */); 360 text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */), 361 5 /* start */, 20 /* end */, 0 /* flags */); 362 mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos)); 363 r = ic.getWordRangeAtCursor(SPACE, ScriptUtils.SCRIPT_LATIN); 364 suggestions = r.getSuggestionSpansAtWord(); 365 assertEquals(suggestions.length, 0); 366 } 367 368 public void testCursorTouchingWord() { 369 final MockInputMethodService ims = new MockInputMethodService(); 370 final RichInputConnection ic = new RichInputConnection(ims); 371 final SpacingAndPunctuations sap = mSpacingAndPunctuations; 372 373 ims.setInputConnection(new MockConnection("users", 5)); 374 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 375 assertTrue(ic.isCursorTouchingWord(sap)); 376 377 ims.setInputConnection(new MockConnection("users'", 5)); 378 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 379 assertTrue(ic.isCursorTouchingWord(sap)); 380 381 ims.setInputConnection(new MockConnection("users'", 6)); 382 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 383 assertTrue(ic.isCursorTouchingWord(sap)); 384 385 ims.setInputConnection(new MockConnection("'users'", 6)); 386 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 387 assertTrue(ic.isCursorTouchingWord(sap)); 388 389 ims.setInputConnection(new MockConnection("'users'", 7)); 390 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 391 assertTrue(ic.isCursorTouchingWord(sap)); 392 393 ims.setInputConnection(new MockConnection("users '", 6)); 394 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 395 assertFalse(ic.isCursorTouchingWord(sap)); 396 397 ims.setInputConnection(new MockConnection("users '", 7)); 398 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 399 assertFalse(ic.isCursorTouchingWord(sap)); 400 401 ims.setInputConnection(new MockConnection("re-", 3)); 402 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 403 assertTrue(ic.isCursorTouchingWord(sap)); 404 405 ims.setInputConnection(new MockConnection("re--", 4)); 406 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 407 assertFalse(ic.isCursorTouchingWord(sap)); 408 409 ims.setInputConnection(new MockConnection("-", 1)); 410 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 411 assertFalse(ic.isCursorTouchingWord(sap)); 412 413 ims.setInputConnection(new MockConnection("--", 2)); 414 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 415 assertFalse(ic.isCursorTouchingWord(sap)); 416 417 ims.setInputConnection(new MockConnection(" -", 2)); 418 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 419 assertFalse(ic.isCursorTouchingWord(sap)); 420 421 ims.setInputConnection(new MockConnection(" --", 3)); 422 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 423 assertFalse(ic.isCursorTouchingWord(sap)); 424 425 ims.setInputConnection(new MockConnection(" users '", 1)); 426 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 427 assertTrue(ic.isCursorTouchingWord(sap)); 428 429 ims.setInputConnection(new MockConnection(" users '", 3)); 430 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 431 assertTrue(ic.isCursorTouchingWord(sap)); 432 433 ims.setInputConnection(new MockConnection(" users '", 7)); 434 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 435 assertFalse(ic.isCursorTouchingWord(sap)); 436 437 ims.setInputConnection(new MockConnection(" users are", 7)); 438 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 439 assertTrue(ic.isCursorTouchingWord(sap)); 440 441 ims.setInputConnection(new MockConnection(" users 'are", 7)); 442 ic.resetCachesUponCursorMoveAndReturnSuccess(ims.cursorPos(), ims.cursorPos(), true); 443 assertFalse(ic.isCursorTouchingWord(sap)); 444 } 445} 446