Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66ecd037 authored by emancebo's avatar emancebo
Browse files

Return match positions to enable highlighting for CN smart dial

Change-Id: I9255c582708c2fbfe22e7a2bf3ad971da692e2a9
parent fcffaad1
Loading
Loading
Loading
Loading
+49 −12
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@ import com.android.providers.contacts.HanziToPinyin;
import android.text.TextUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

public class ChineseSmartDialMap implements SmartDialMap {

@@ -439,28 +441,63 @@ public class ChineseSmartDialMap implements SmartDialMap {
    }

    /*
     * Since the dialpad is matching off the generated pinyin, the
     * Chinese characters can't be highlighted. Just return true if
     * there is a match without highlighting a character position.
     * Uses the default matching logic on the pinyin name and attempts to map the match positions
     * back to the original display name
     */
    @Override
    public boolean matchesCombination(SmartDialNameMatcher smartDialNameMatcher,
            String displayName, String query, ArrayList<SmartDialMatchPosition> matchList) {

        String pinyinName = tokenizeToPinyins(displayName);
        if (displayName.equals(pinyinName)) {
            return smartDialNameMatcher.matchesCombination(displayName, query, matchList);
        }
        final int nameLength = pinyinName.length();
        final int queryLength = query.length();

        if (nameLength < queryLength) {
        ArrayList<SmartDialMatchPosition> computedMatchList = new ArrayList<SmartDialMatchPosition>();
        boolean matches = smartDialNameMatcher.matchesCombination(pinyinName, query, computedMatchList);
        if (!matches)
            return false;

        // name was translated to pinyin before matching.  attempt to map the match positions
        // back to the original display string
        if (!displayName.equals(pinyinName)) {

            // construct an array that maps each character of the pinyin name back to the index of
            // the hanzi token from which it came
            // For example, if:
            //  displayName = 红霞李
            //  pinyinName =  "hong xia li"
            // then:
            //  pinyinMapping = 0,0,0,0,-1,1,1,1,-1,2,2
            int[] pinyinMapping = new int[pinyinName.length()];
            int curToken = 0;
            for (int i=0; i < pinyinName.length(); ++i) {
                char c = pinyinName.charAt(i);
                if (c == ' ') {
                    ++curToken;
                    pinyinMapping[i] = -1;
                }
                else {
                    pinyinMapping[i] = curToken;
                }
            }

        if (queryLength == 0) {
            return false;
            // calculate unique hanzi characters that are matched
            Set<Integer> positionsToHighlight = new HashSet<Integer>();
            for (SmartDialMatchPosition matchPosition : computedMatchList) {
                for (int pos = matchPosition.start; pos < matchPosition.end; ++pos) {
                    int mappedPos = pinyinMapping[pos];
                    if (mappedPos >= 0)
                        positionsToHighlight.add(mappedPos);
                }
            }

            // reset computed matches
            computedMatchList = new ArrayList<SmartDialMatchPosition>();
            for (int matchPos : positionsToHighlight) {
                // use one object per position for simplicity
                computedMatchList.add(new SmartDialMatchPosition(matchPos, matchPos+1));
            }
        }

        matchList.addAll(computedMatchList);
        return true;
    }

+6 −0
Original line number Diff line number Diff line
@@ -126,6 +126,12 @@ public class SmartDialPrefix {
        sNanpInitialized = true;
    }

    // for testing only
    @VisibleForTesting
    static void setSmartDialMap(SmartDialMap map) {
        mMap = map;
    }

    public static Locale getT9SearchInputLocale(Context context) {
        // Use system locale by default
        Locale locale = context.getResources().getConfiguration().locale;
+33 −2
Original line number Diff line number Diff line
@@ -33,6 +33,12 @@ import junit.framework.TestCase;
public class SmartDialNameMatcherTest extends TestCase {
    private static final String TAG = "SmartDialNameMatcherTest";

    @Override
    public void setUp() {
        SmartDialPrefix.setSmartDialMap(new LatinSmartDialMap());
        SmartDialPrefix.setUserInNanpRegion(true);
    }

    public void testMatches() {
        // Test to ensure that all alphabetic characters are covered
        checkMatches("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
@@ -162,6 +168,30 @@ public class SmartDialNameMatcherTest extends TestCase {
        fail("Cyrillic letters aren't supported yet.");
    }

    public void testMatches_chinese() {
        SmartDialPrefix.setSmartDialMap(new ChineseSmartDialMap());

        // basic cases
        checkMatches("红霞李", "46", true, 0, 1);
        checkMatches("红霞李", "46649", true, 0, 1, 1, 2);
        checkMatches("红霞李", "5", true, 2, 3);
        checkMatches("红霞李", "466494254", true, 0, 1, 1, 2, 2, 3);

        // test with spaces
        checkMatches("红霞 李", "466494254", true, 0, 1, 1, 2, 2, 3);
        checkMatches(" 红  霞    李", "466494254", true, 0, 1, 1, 2, 2, 3);

        // when character sets are mixed, match english only
        checkMatches("Hongxia 李", "46", true, 0, 2);
        checkMatches("Hongxia 李", "5", false);

        // make sure regular english cases still work
        checkMatches("Meow Face", "63", true, 0, 2);
        checkMatches("Meow Face", "32", true, 5, 7);
        checkMatches("Meow Face", "632", true, 0, 1, 5, 7);

        SmartDialPrefix.setSmartDialMap(new LatinSmartDialMap());
    }

    public void testMatches_NumberBasic() {
        // Simple basic examples that start the match from the start of the number
@@ -198,6 +228,7 @@ public class SmartDialNameMatcherTest extends TestCase {
    }

    public void testMatches_NumberNANP() {

        // An 11 digit number prefixed with 1 should be matched by the 10 digit number, as well as
        // the 7 digit number (without area code)
        checkMatchesNumber("1-510-333-7596", "5103337596", true, true, 2, 14);
@@ -252,8 +283,8 @@ public class SmartDialNameMatcherTest extends TestCase {
        final SmartDialNameMatcher matcher = new SmartDialNameMatcher(query);
        final ArrayList<SmartDialMatchPosition> matchPositions =
                new ArrayList<SmartDialMatchPosition>();
        final boolean matches = matcher.matchesCombination(
                displayName, query, matchPositions);
        final boolean matches =
                SmartDialPrefix.getMap().matchesCombination(matcher, displayName, query, matchPositions);
        Log.d(TAG, "query=" + query + "  text=" + displayName
                + "  nfd=" + Normalizer.normalize(displayName, Normalizer.Form.NFD)
                + "  nfc=" + Normalizer.normalize(displayName, Normalizer.Form.NFC)