Merge "Changing the default display order for Western names in CJK locales."
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index 5cc0254..f5ed2d7 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -1227,6 +1227,7 @@
                 return new AlertDialog.Builder(this)
                         .setTitle(R.string.confirm_share_visible_contacts_title)
                         .setMessage(getString(R.string.confirm_share_visible_contacts_message))
+                        .setNegativeButton(android.R.string.cancel, null)
                         .setPositiveButton(android.R.string.ok,
                                 new DialogInterface.OnClickListener() {
                             public void onClick(DialogInterface dialog, int which) {
diff --git a/src/com/android/contacts/ImportVCardActivity.java b/src/com/android/contacts/ImportVCardActivity.java
index 4f2749d..30b6cbf 100644
--- a/src/com/android/contacts/ImportVCardActivity.java
+++ b/src/com/android/contacts/ImportVCardActivity.java
@@ -22,6 +22,7 @@
 import android.app.Dialog;
 import android.app.ProgressDialog;
 import android.content.ContentResolver;
+import android.content.ContentUris;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -45,6 +46,7 @@
 import android.pim.vcard.exception.VCardNestedException;
 import android.pim.vcard.exception.VCardNotSupportedException;
 import android.pim.vcard.exception.VCardVersionException;
+import android.provider.ContactsContract.RawContacts;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.TextUtils;
@@ -189,6 +191,7 @@
         public void run() {
             boolean shouldCallFinish = true;
             mWakeLock.acquire();
+            Uri createdUri = null;
             // Some malicious vCard data may make this thread broken
             // (e.g. OutOfMemoryError).
             // Even in such cases, some should be done.
@@ -238,7 +241,7 @@
                     mProgressDialogForReadVCard.setIndeterminate(false);
                     mProgressDialogForReadVCard.setMax(counter.getCount());
                     String charset = detector.getEstimatedCharset();
-                    doActuallyReadOneVCard(mUri, null, charset, true, detector,
+                    createdUri = doActuallyReadOneVCard(mUri, null, charset, true, detector,
                             mErrorFileNameList);
                 } else {  // Read multiple files.
                     mProgressDialogForReadVCard.setProgressNumberFormat(
@@ -262,7 +265,7 @@
                             // Assume that VCardSourceDetector was able to detect the source.
                         }
                         String charset = detector.getEstimatedCharset();
-                        doActuallyReadOneVCard(uri, mAccount,
+                        createdUri = doActuallyReadOneVCard(uri, mAccount,
                                 charset, false, detector, mErrorFileNameList);
                         mProgressDialogForReadVCard.incrementProgressBy(1);
                     }
@@ -274,18 +277,18 @@
                 if (shouldCallFinish && !isFinishing()) {
                     if (mErrorFileNameList == null || mErrorFileNameList.isEmpty()) {
                         finish();
-                        // TODO: Send out ACTION_EDIT intent here to review the
-                        // incoming contact
                         if (mNeedReview) {
                             mNeedReview = false;
                             Log.v("importVCardActivity", "Prepare to review the imported contact");
-                            Uri uri = null; // TODO: need get the uri of the
-                                            // incoming contact
-                            Intent editIntent = new Intent(Intent.ACTION_EDIT, uri);
-                            if (editIntent != null) {
-                                //startActivity(editIntent);
-                            }
 
+                            // get contact_id of this raw_contact
+                            final long rawContactId = ContentUris.parseId(createdUri);
+                            Uri contactUri = RawContacts.getContactLookupUri(getContentResolver(),
+                                    ContentUris.withAppendedId(RawContacts.CONTENT_URI,
+                                            rawContactId));
+
+                            Intent viewIntent = new Intent(Intent.ACTION_VIEW, contactUri);
+                            startActivity(viewIntent);
                         }
                     } else {
                         StringBuilder builder = new StringBuilder();
@@ -298,7 +301,7 @@
                             }
                             builder.append(fileName);
                         }
-                        
+
                         mHandler.post(new DialogDisplayer(
                                 getString(R.string.fail_reason_failed_to_read_files,
                                         builder.toString())));
@@ -307,7 +310,7 @@
             }
         }
 
-        private boolean doActuallyReadOneVCard(Uri uri, Account account,
+        private Uri doActuallyReadOneVCard(Uri uri, Account account,
                 String charset, boolean showEntryParseProgress,
                 VCardSourceDetector detector, List<String> errorFileNameList) {
             final Context context = ImportVCardActivity.this;
@@ -321,7 +324,8 @@
                 charset = VCardConfig.DEFAULT_CHARSET;
                 builder = new VCardEntryConstructor(null, null, false, vcardType, mAccount);
             }
-            builder.addEntryHandler(new VCardEntryCommitter(mResolver));
+            VCardEntryCommitter committer = new VCardEntryCommitter(mResolver);
+            builder.addEntryHandler(committer);
             if (showEntryParseProgress) {
                 builder.addEntryHandler(new ProgressShower(mProgressDialogForReadVCard,
                         context.getString(R.string.reading_vcard_message),
@@ -331,12 +335,12 @@
 
             try {
                 if (!readOneVCardFile(uri, charset, builder, detector, false, null)) {
-                    return false;
+                    return null;
                 }
             } catch (VCardNestedException e) {
                 Log.e(LOG_TAG, "Never reach here.");
             }
-            return true;
+            return committer.getLastCreatedUri();
         }
 
         private boolean readOneVCardFile(Uri uri, String charset,
@@ -431,7 +435,7 @@
         public static final int IMPORT_MULTIPLE = 1;
         public static final int IMPORT_ALL = 2;
         public static final int IMPORT_TYPE_SIZE = 3;
-        
+
         private int mCurrentIndex;
 
         public void onClick(DialogInterface dialog, int which) {
@@ -454,7 +458,7 @@
             }
         }
     }
-    
+
     private class VCardSelectedListener implements
             DialogInterface.OnClickListener, DialogInterface.OnMultiChoiceClickListener {
         private int mCurrentIndex;
@@ -472,7 +476,7 @@
                 if (mSelectedIndexSet != null) {
                     List<VCardFile> selectedVCardFileList = new ArrayList<VCardFile>();
                     int size = mAllVCardFileList.size();
-                    // We'd like to sort the files by its index, so we do not use Set iterator. 
+                    // We'd like to sort the files by its index, so we do not use Set iterator.
                     for (int i = 0; i < size; i++) {
                         if (mSelectedIndexSet.contains(i)) {
                             selectedVCardFileList.add(mAllVCardFileList.get(i));
@@ -633,7 +637,7 @@
             mHandler.post(new DialogDisplayer(R.id.dialog_select_one_vcard));
         }
     }
-    
+
     private void importMultipleVCardFromSDCard(final List<VCardFile> selectedVCardFileList) {
         mHandler.post(new Runnable() {
             public void run() {
diff --git a/src/com/android/contacts/JapaneseContactListIndexer.java b/src/com/android/contacts/JapaneseContactListIndexer.java
deleted file mode 100644
index ca7ca33..0000000
--- a/src/com/android/contacts/JapaneseContactListIndexer.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts;
-
-import java.util.Map;
-
-import android.database.Cursor;
-import android.database.DataSetObserver;
-import android.util.Log;
-import android.util.SparseIntArray;
-import android.widget.SectionIndexer;
-
-/**
- * SectionIndexer which is for "phonetically sortable" String. This class heavily depends on the
- * algorithm of the SQL function "GET_PHONETICALLY_SORTABLE_STRING", whose implementation
- * is written in C++.
- */
-public final class JapaneseContactListIndexer extends DataSetObserver implements SectionIndexer {
-    private static String TAG = "JapaneseContactListIndexer";
-
-    private static final String[] sSections = {
-            " ", // Sections of SectionIndexer should start with " " (some components assume it).
-            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
-            "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
-            "\u3042", "\u304B", "\u3055", "\u305F", "\u306A", // a, ka, sa, ta, na 
-            "\u306F", "\u307E", "\u3084", "\u3089", "\u308F", // ha, ma, ya, ra, wa
-            "\uFF21", "\uFF22", "\uFF23", "\uFF24", "\uFF25", // full-width ABCDE
-            "\uFF26", "\uFF27", "\uFF28", "\uFF29", "\uFF2A", // full-width FGHIJ
-            "\uFF2B", "\uFF2C", "\uFF2D", "\uFF2E", "\uFF2F", // full-width KLMNO
-            "\uFF30", "\uFF31", "\uFF32", "\uFF33", "\uFF34", // full-width PQRST
-            "\uFF35", "\uFF36", "\uFF37", "\uFF38", "\uFF39", // full-width UVWXY
-            "\uFF40", // full-width Z
-            "\u6570", "\u8A18" // alphabets, numbers, symbols
-            };
-    private static final int sSectionsLength = sSections.length;
-
-    /**
-     * Converts given character into half-width ascii. If it is small ascii, it is translated
-     * into large ascii.
-     * This method is temporal huck until fixing the issue in which Ascii comes before Kana-s.
-     * Note that names starting from symbols corrupt the indexer.
-     *
-     * The current ICU mapping used in the locale ja merges full-width/half-width Asciis into
-     * one without caring its order. This mapping translates the unified characters into
-     * full-width capitalized ascii.
-     * TODO: Similar method should exist in public API. vCard code also has similar mapping.
-     */
-    private static int toHalfWidthCapitalizedAscii(int codePoint) {
-       if (0x61 <= codePoint && codePoint <= 0x7A) {
-           return codePoint - 0x20;  // half-width small ascii -> half-width capitalized ascii.
-       } else if ((0xFF01 <= codePoint && codePoint <= 0xFF40) ||
-               (0xFF5B <= codePoint && codePoint <= 0xFF5E)) {
-           return codePoint - (0xFF01 - 0x0020);
-       } else if (0xFF41 <= codePoint && codePoint <= 0xFF5A) {
-           return codePoint - (0xFF41 - 0x0041);
-       } else {
-           return codePoint;
-       }
-    }
-
-    private int mColumnIndex;
-    private Cursor mDataCursor;
-    private SparseIntArray mStringMap;
-    
-    public JapaneseContactListIndexer(Cursor cursor, int columnIndex) {
-        int len = sSections.length;
-        mColumnIndex = columnIndex;
-        mDataCursor = cursor;
-        mStringMap = new SparseIntArray(sSectionsLength);
-        if (cursor != null) {
-            cursor.registerDataSetObserver(this);
-        }
-    }
-    
-    public void setCursor(Cursor cursor) {
-        if (mDataCursor != null) {
-            mDataCursor.unregisterDataSetObserver(this);
-        }
-        mDataCursor = cursor;
-        if (cursor != null) {
-            mDataCursor.registerDataSetObserver(this);
-        }
-    }
-    
-    private int getSectionCodePoint(int index) {
-        if (index < sSections.length - 2) {
-            return sSections[index].codePointAt(0);
-        } else if (index == sSections.length - 2) {
-            return 0xFF66;  // Numbers are mapped from 0xFF66.
-        } else {  // index == mSections.length - 1
-            return 0xFF70;  // Symbols are mapped from 0xFF70.
-        }
-    }
-    
-    public int getPositionForSection(int sectionIndex) {
-        final SparseIntArray stringMap = mStringMap;
-        final Cursor cursor = mDataCursor;
-
-        if (cursor == null || sectionIndex <= 0) {
-            return 0;
-        }
-        
-        if (sectionIndex >= sSectionsLength) {
-            sectionIndex = sSectionsLength - 1;
-        }
-
-        int savedCursorPos = cursor.getPosition();
-
-        String targetLetter = sSections[sectionIndex];
-        int key = targetLetter.codePointAt(0);
-
-        // Check cache map
-        {
-            int tmp = stringMap.get(key, Integer.MIN_VALUE);
-            if (Integer.MIN_VALUE != tmp) {
-                return tmp;
-            }
-        }
-
-        int end = cursor.getCount();
-        int pos = 0;
-
-        {
-            // Note that sectionIndex > 0.
-            int prevLetter = sSections[sectionIndex - 1].codePointAt(0);
-            int prevLetterPos = stringMap.get(prevLetter, Integer.MIN_VALUE);
-            if (prevLetterPos != Integer.MIN_VALUE) {
-                pos = prevLetterPos;
-            }
-        }
-        
-        // Do rough binary search if there are a lot of entries.
-        while (end - pos > 100) {
-            int tmp = (end + pos) / 2;
-            cursor.moveToPosition(tmp);
-            String sort_name;
-            do {
-                sort_name = cursor.getString(mColumnIndex);
-                if (sort_name == null || sort_name.length() == 0) {
-                    // This should not happen, since sort_name field is created
-                    // automatically when syncing to a server, or creating/editing
-                    // the entry...
-                    Log.e(TAG, "sort_name is null or its length is 0. index: " + tmp);
-                    cursor.moveToNext();
-                    tmp++;
-                    continue;
-                }
-                break;
-            } while (tmp < end);
-            if (tmp == end) {
-                break;
-            }
-            int codePoint = sort_name.codePointAt(0);
-            if (codePoint < getSectionCodePoint(sectionIndex)) {
-                pos = tmp;
-            } else {
-                end = tmp;
-            }
-        }
-        
-        for (cursor.moveToPosition(pos); !cursor.isAfterLast(); ++pos, cursor.moveToNext()) {
-            String sort_name = cursor.getString(mColumnIndex);
-            if (sort_name == null || sort_name.length() == 0) {
-                // This should not happen, since sort_name field is created
-                // automatically when syncing to a server, or creating/editing
-                // the entry...
-                Log.e(TAG, "sort_name is null or its length is 0. index: " + pos);
-                continue;
-            }
-            int codePoint = toHalfWidthCapitalizedAscii(sort_name.codePointAt(0));
-            if (codePoint >= getSectionCodePoint(sectionIndex)) {
-                break;
-            }
-        }
-        
-        stringMap.put(key, pos);
-        cursor.moveToPosition(savedCursorPos);
-        return pos;
-    }
-    
-    public int getSectionForPosition(int position) {
-        // Not used in Contacts. Ignore for now.
-        return 0;
-    }
-
-    public Object[] getSections() {
-        return sSections;
-    }
-
-    @Override
-    public void onChanged() {
-        super.onChanged();
-        mStringMap.clear();
-    }
-
-    @Override
-    public void onInvalidated() {
-        super.onInvalidated();
-        mStringMap.clear();
-    }
-}