public void callback(String word, int level) { if (word == null) return; int maxidx = word.length(); int lastStart = -1; int i = 0; while (i < maxidx) { char c = word.charAt(i); if (Character.isLetter(c) == true) { if (lastStart == -1) { lastStart = i; } } else { if (lastStart != -1 && i > lastStart) { backend.callback(word.substring(lastStart, i), level); lastStart = -1; } } ++i; } }
@Override public void getWords(final WordComposer codes, final WordCallback callback) { mWordCallback = callback; final int codesSize = codes.size(); // Wont deal with really long words. if (codesSize > MAX_WORD_LENGTH - 1) return; Arrays.fill(mInputCodes, -1); for (int i = 0; i < codesSize; i++) { final int[] alternatives = codes.getCodesAt(i); System.arraycopy( alternatives, 0, mInputCodes, i * MAX_ALTERNATIVES, Math.min(alternatives.length, MAX_ALTERNATIVES)); } Arrays.fill(mOutputChars, (char) 0); Arrays.fill(mFrequencies, 0); int count = getSuggestionsNative( mNativeDict, mInputCodes, codesSize, mOutputChars, mFrequencies, MAX_WORD_LENGTH, MAX_WORDS, MAX_ALTERNATIVES, -1); // If there aren't sufficient suggestions, search for words by allowing // wild cards at // the different character positions. This feature is not ready for // prime-time as we need // to figure out the best ranking for such words compared to proximity // corrections and // completions. if (ENABLE_MISSED_CHARACTERS && count < 5) { for (int skip = 0; skip < codesSize; skip++) { final int tempCount = getSuggestionsNative( mNativeDict, mInputCodes, codesSize, mOutputChars, mFrequencies, MAX_WORD_LENGTH, MAX_WORDS, MAX_ALTERNATIVES, skip); count = Math.max(count, tempCount); if (tempCount > 0) break; } } for (int j = 0; j < count; j++) { if (mFrequencies[j] < 1) break; final int start = j * MAX_WORD_LENGTH; int len = 0; while (mOutputChars[start + len] != 0) { len++; } if (len > 0) { callback.addWord(mOutputChars, start, len, mFrequencies[j]); } } }
/** * Recursively traverse the tree for words that match the input. Input consists of a list of * arrays. Each item in the list is one input character position. An input character is actually * an array of multiple possible candidates. This function is not optimized for speed, assuming * that the user dictionary will only be a few hundred words in size. * * @param roots node whose children have to be search for matches * @param codes the input character codes * @param word the word being composed as a possible match * @param depth the depth of traversal - the length of the word being composed thus far * @param completion whether the traversal is now in completion mode - meaning that we've * exhausted the input and we're looking for all possible suffixes. * @param snr current weight of the word being formed * @param inputIndex position in the input characters. This can be off from the depth in case we * skip over some punctuations such as apostrophe in the traversal. That is, if you type * "wouldve", it could be matching "would've", so the depth will be one more than the * inputIndex * @param callback the callback class for adding a word */ private void getWordsRec( NodeArray roots, final WordComposer codes, final char[] word, final int depth, boolean completion, float snr, int inputIndex, WordCallback callback) { final int count = roots.length; final int codeSize = mInputLength; // Optimization: Prune out words that are too long compared to how much was typed. if (depth > mMaxDepth) { return; } int[] currentChars = null; if (codeSize <= inputIndex) { completion = true; } else { currentChars = codes.getCodesAt(inputIndex); } for (int i = 0; i < count; i++) { final Node node = roots.data[i]; final char c = node.code; final char lowerC = toLowerCase(c); boolean terminal = node.terminal; NodeArray children = node.children; int freq = node.frequency; if (completion) { word[depth] = c; if (terminal) { if (!callback.addWord(word, 0, depth + 1, (int) (freq * snr))) { return; } } if (children != null) { getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex, callback); } } else if (c == QUOTE && currentChars[0] != QUOTE) { // Skip the ' and continue deeper word[depth] = QUOTE; if (children != null) { getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex, callback); } } else { for (int j = 0; j < currentChars.length; j++) { float addedAttenuation = (j > 0 ? 1f : 3f); if (currentChars[j] == -1) { break; } if (currentChars[j] == lowerC || currentChars[j] == c) { word[depth] = c; if (codes.size() == depth + 1) { if (terminal) { if (INCLUDE_TYPED_WORD_IF_VALID || !same(word, depth + 1, codes.getTypedWord())) { callback.addWord( word, 0, depth + 1, (int) (freq * snr * addedAttenuation * FULL_WORD_FREQ_MULTIPLIER)); } } if (children != null) { getWordsRec( children, codes, word, depth + 1, true, snr * addedAttenuation, inputIndex + 1, callback); } } else if (children != null) { getWordsRec( children, codes, word, depth + 1, false, snr * addedAttenuation, inputIndex + 1, callback); } } } } } }
public void pushLevel(int level) { backend.pushLevel(level); }
public void popLevel() { backend.popLevel(); }