summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid van Tonder <david.vantonder@gmail.com>2013-06-11 04:34:59 -0700
committerGerrit Code Review <gerrit@cyanogenmod.org>2013-06-11 04:34:59 -0700
commit3aca6c3137f968f4c4103e15f0fbbe0141dd518e (patch)
tree4efdc478f7892e28761f9a6b4adb6b099620561a
parentb020a3991446f495dd8eff515fec77c3ffc74eac (diff)
parentf756894579dc5e90bec286228d08da95b23b71ae (diff)
downloadpackages_apps_Mms-3aca6c3137f968f4c4103e15f0fbbe0141dd518e.zip
packages_apps_Mms-3aca6c3137f968f4c4103e15f0fbbe0141dd518e.tar.gz
packages_apps_Mms-3aca6c3137f968f4c4103e15f0fbbe0141dd518e.tar.bz2
Merge "Mms: Delay unicode stripping from a message" into cm-10.1
-rw-r--r--src/com/android/mms/quickmessage/QmTextWatcher.java10
-rw-r--r--src/com/android/mms/quickmessage/QuickMessagePopup.java140
-rw-r--r--src/com/android/mms/ui/ComposeMessageActivity.java141
-rw-r--r--src/com/android/mms/util/UnicodeFilter.java127
4 files changed, 168 insertions, 250 deletions
diff --git a/src/com/android/mms/quickmessage/QmTextWatcher.java b/src/com/android/mms/quickmessage/QmTextWatcher.java
index c56b0bf..fbc9b3e 100644
--- a/src/com/android/mms/quickmessage/QmTextWatcher.java
+++ b/src/com/android/mms/quickmessage/QmTextWatcher.java
@@ -25,21 +25,25 @@ import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
+import com.android.mms.util.UnicodeFilter;
+
public class QmTextWatcher implements TextWatcher {
private TextView mTextView;
private ImageButton mSendButton;
private ImageButton mTemplateButton;
private int mTemplateCount;
+ private UnicodeFilter mUnicodeFilter;
private Context mContext;
private static final int CHARS_REMAINING_BEFORE_COUNTER_SHOWN = 30;
public QmTextWatcher(Context context, TextView updateTextView, ImageButton sendButton,
- ImageButton templateButton, int templateCount) {
+ ImageButton templateButton, int templateCount, UnicodeFilter unicodeFilter) {
mContext = context;
mTextView = updateTextView;
mSendButton = sendButton;
mTemplateButton = templateButton;
mTemplateCount = templateCount;
+ mUnicodeFilter = unicodeFilter;
}
public QmTextWatcher(Context context, TextView updateTextView) {
@@ -58,6 +62,10 @@ public class QmTextWatcher implements TextWatcher {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
+ // strip unicode for message length counting
+ if (mUnicodeFilter != null) {
+ s = mUnicodeFilter.filter(s);
+ }
getQuickReplyCounterText(s, mTextView, mSendButton, mTemplateButton, mTemplateCount);
// For performance, we will only poke the wakelock on the 1st and every 20th keystroke
diff --git a/src/com/android/mms/quickmessage/QuickMessagePopup.java b/src/com/android/mms/quickmessage/QuickMessagePopup.java
index efe961c..8754360 100644
--- a/src/com/android/mms/quickmessage/QuickMessagePopup.java
+++ b/src/com/android/mms/quickmessage/QuickMessagePopup.java
@@ -89,6 +89,7 @@ import com.android.mms.ui.MessageUtils;
import com.android.mms.ui.MessagingPreferenceActivity;
import com.android.mms.util.EmojiParser;
import com.android.mms.util.SmileyParser;
+import com.android.mms.util.UnicodeFilter;
import com.google.android.mms.MmsException;
import java.nio.charset.Charset;
@@ -153,6 +154,7 @@ public class QuickMessagePopup extends Activity implements
private boolean mDarkTheme = false;
private boolean mFullTimestamp = false;
private int mUnicodeStripping = MessagingPreferenceActivity.UNICODE_STRIPPING_LEAVE_INTACT;
+ private UnicodeFilter mUnicodeFilter = null;
private boolean mEnableEmojis = false;
private int mInputMethod;
@@ -938,122 +940,6 @@ public class QuickMessagePopup extends Activity implements
//==========================================================
/**
- * Class copied from ComposeMessageActivity.java
- * InputFilter which attempts to substitute characters that cannot be
- * encoded in the limited GSM 03.38 character set. In many cases this will
- * prevent the keyboards auto-correction feature from inserting characters
- * that would switch the message from 7-bit GSM encoding (160 char limit)
- * to 16-bit Unicode encoding (70 char limit).
- */
- private static class StripUnicode implements InputFilter {
-
- private CharsetEncoder gsm =
- Charset.forName("gsm-03.38-2000").newEncoder();
-
- private Pattern diacritics =
- Pattern.compile("\\p{InCombiningDiacriticalMarks}");
-
- private boolean mStripNonDecodableOnly = false;
-
- StripUnicode(boolean stripping) {
- mStripNonDecodableOnly = stripping;
- }
-
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
-
- Boolean unfiltered = true;
- StringBuilder output = new StringBuilder(end - start);
-
- for (int i = start; i < end; i++) {
- char c = source.charAt(i);
-
- // Character is encodable by GSM, skip filtering
- if (mStripNonDecodableOnly && gsm.canEncode(c)) {
- output.append(c);
- }
- // Character requires Unicode, try to replace it
- else {
- unfiltered = false;
- String s = String.valueOf(c);
-
- // Try normalizing the character into Unicode NFKD form and
- // stripping out diacritic mark characters.
- s = Normalizer.normalize(s, Normalizer.Form.NFKD);
- s = diacritics.matcher(s).replaceAll("");
-
- // Special case characters that don't get stripped by the
- // above technique.
- s = s.replace("Œ", "OE");
- s = s.replace("œ", "oe");
- s = s.replace("Ł", "L");
- s = s.replace("ł", "l");
- s = s.replace("Đ", "DJ");
- s = s.replace("đ", "dj");
- s = s.replace("Α", "A");
- s = s.replace("Β", "B");
- s = s.replace("Ε", "E");
- s = s.replace("Ζ", "Z");
- s = s.replace("Η", "H");
- s = s.replace("Ι", "I");
- s = s.replace("Κ", "K");
- s = s.replace("Μ", "M");
- s = s.replace("Ν", "N");
- s = s.replace("Ο", "O");
- s = s.replace("Ρ", "P");
- s = s.replace("Τ", "T");
- s = s.replace("Υ", "Y");
- s = s.replace("Χ", "X");
- s = s.replace("α", "A");
- s = s.replace("β", "B");
- s = s.replace("γ", "Γ");
- s = s.replace("δ", "Δ");
- s = s.replace("ε", "E");
- s = s.replace("ζ", "Z");
- s = s.replace("η", "H");
- s = s.replace("θ", "Θ");
- s = s.replace("ι", "I");
- s = s.replace("κ", "K");
- s = s.replace("λ", "Λ");
- s = s.replace("μ", "M");
- s = s.replace("ν", "N");
- s = s.replace("ξ", "Ξ");
- s = s.replace("ο", "O");
- s = s.replace("π", "Π");
- s = s.replace("ρ", "P");
- s = s.replace("σ", "Σ");
- s = s.replace("τ", "T");
- s = s.replace("υ", "Y");
- s = s.replace("φ", "Φ");
- s = s.replace("χ", "X");
- s = s.replace("ψ", "Ψ");
- s = s.replace("ω", "Ω");
- s = s.replace("ς", "Σ");
-
- output.append(s);
- }
- }
-
- // No changes were attempted, so don't return anything
- if (unfiltered) {
- return null;
- }
- // Source is a spanned string, so copy the spans from it
- else if (source instanceof Spanned) {
- SpannableString spannedoutput = new SpannableString(output);
- TextUtils.copySpansFrom(
- (Spanned) source, start, end, null, spannedoutput, 0);
-
- return spannedoutput;
- }
- // Source is a vanilla charsequence, so return output as-is
- else {
- return output;
- }
- }
- }
-
- /**
* Message Pager class, used to display and navigate through the ViewPager pages
*/
private class MessagePagerAdapter extends PagerAdapter
@@ -1114,8 +1000,15 @@ public class QuickMessagePopup extends Activity implements
| InputType.TYPE_TEXT_FLAG_MULTI_LINE);
qmReplyText.setText(qm.getReplyText());
qmReplyText.setSelection(qm.getReplyText().length());
+
+ if (mUnicodeStripping != MessagingPreferenceActivity.UNICODE_STRIPPING_LEAVE_INTACT) {
+ boolean stripNonDecodableOnly =
+ mUnicodeStripping == MessagingPreferenceActivity.UNICODE_STRIPPING_NON_DECODABLE;
+ mUnicodeFilter = new UnicodeFilter(stripNonDecodableOnly);
+ }
+
qmReplyText.addTextChangedListener(new QmTextWatcher(mContext, qmTextCounter, qmSendButton,
- qmTemplatesButton, mNumTemplates));
+ qmTemplatesButton, mNumTemplates, mUnicodeFilter));
qmReplyText.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
@@ -1147,15 +1040,7 @@ public class QuickMessagePopup extends Activity implements
});
LengthFilter lengthFilter = new LengthFilter(MmsConfig.getMaxTextLimit());
-
- if (mUnicodeStripping != MessagingPreferenceActivity.UNICODE_STRIPPING_LEAVE_INTACT) {
- boolean stripNonDecodableOnly = mUnicodeStripping == MessagingPreferenceActivity
- .UNICODE_STRIPPING_NON_DECODABLE;
- qmReplyText.setFilters(new InputFilter[] { new StripUnicode(stripNonDecodableOnly),
- lengthFilter });
- } else {
- qmReplyText.setFilters(new InputFilter[] { lengthFilter });
- }
+ qmReplyText.setFilters(new InputFilter[] { lengthFilter });
QmTextWatcher.getQuickReplyCounterText(qmReplyText.getText().toString(),
qmTextCounter, qmSendButton, qmTemplatesButton, mNumTemplates);
@@ -1203,6 +1088,9 @@ public class QuickMessagePopup extends Activity implements
* @param qm - qm we are replying to (for sender details)
*/
private void sendMessageAndMoveOn(String message, QuickMessage qm) {
+ if (mUnicodeFilter != null) {
+ message = mUnicodeFilter.filter(message).toString();
+ }
sendQuickMessage(message, qm);
// Close the current QM and move on
int numMessages = mMessageList.size();
diff --git a/src/com/android/mms/ui/ComposeMessageActivity.java b/src/com/android/mms/ui/ComposeMessageActivity.java
index 9758ee7..901c227 100644
--- a/src/com/android/mms/ui/ComposeMessageActivity.java
+++ b/src/com/android/mms/ui/ComposeMessageActivity.java
@@ -157,6 +157,7 @@ import com.android.mms.util.EmojiParser;
import com.android.mms.util.PhoneNumberFormatter;
import com.android.mms.util.SendingProgressTokenManager;
import com.android.mms.util.SmileyParser;
+import com.android.mms.util.UnicodeFilter;
import com.android.mms.widget.MmsWidgetProvider;
import com.google.android.mms.ContentType;
import com.google.android.mms.MmsException;
@@ -394,6 +395,8 @@ public class ComposeMessageActivity extends Activity
// we should not load the draft.
private boolean mShouldLoadDraft;
+ private UnicodeFilter mUnicodeFilter = null;
+
private Handler mHandler = new Handler();
// keys for extras and icicles
@@ -411,123 +414,6 @@ public class ComposeMessageActivity extends Activity
Log.d(TAG, logMsg);
}
- //==========================================================
- // Inner classes
- //==========================================================
-
- // InputFilter which attempts to substitute characters that cannot be
- // encoded in the limited GSM 03.38 character set. In many cases this will
- // prevent the keyboards auto-correction feature from inserting characters
- // that would switch the message from 7-bit GSM encoding (160 char limit)
- // to 16-bit Unicode encoding (70 char limit).
-
- private static class StripUnicode implements InputFilter {
- private CharsetEncoder gsm =
- Charset.forName("gsm-03.38-2000").newEncoder();
-
- private Pattern diacritics =
- Pattern.compile("\\p{InCombiningDiacriticalMarks}");
-
- private boolean mStripNonDecodableOnly = false;
-
- StripUnicode(boolean stripping) {
- mStripNonDecodableOnly = stripping;
- }
-
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
-
- Boolean unfiltered = true;
- StringBuilder output = new StringBuilder(end - start);
-
- for (int i = start; i < end; i++) {
- char c = source.charAt(i);
-
- // Character is encodable by GSM, skip filtering
- if (mStripNonDecodableOnly && gsm.canEncode(c)) {
- output.append(c);
- }
- // Character requires Unicode, try to replace it
- else {
- unfiltered = false;
- String s = String.valueOf(c);
-
- // Try normalizing the character into Unicode NFKD form and
- // stripping out diacritic mark characters.
- s = Normalizer.normalize(s, Normalizer.Form.NFKD);
- s = diacritics.matcher(s).replaceAll("");
-
- // Special case characters that don't get stripped by the
- // above technique.
- s = s.replace("Œ", "OE");
- s = s.replace("œ", "oe");
- s = s.replace("Ł", "L");
- s = s.replace("ł", "l");
- s = s.replace("Đ", "DJ");
- s = s.replace("đ", "dj");
- s = s.replace("Α", "A");
- s = s.replace("Β", "B");
- s = s.replace("Ε", "E");
- s = s.replace("Ζ", "Z");
- s = s.replace("Η", "H");
- s = s.replace("Ι", "I");
- s = s.replace("Κ", "K");
- s = s.replace("Μ", "M");
- s = s.replace("Ν", "N");
- s = s.replace("Ο", "O");
- s = s.replace("Ρ", "P");
- s = s.replace("Τ", "T");
- s = s.replace("Υ", "Y");
- s = s.replace("Χ", "X");
- s = s.replace("α", "A");
- s = s.replace("β", "B");
- s = s.replace("γ", "Γ");
- s = s.replace("δ", "Δ");
- s = s.replace("ε", "E");
- s = s.replace("ζ", "Z");
- s = s.replace("η", "H");
- s = s.replace("θ", "Θ");
- s = s.replace("ι", "I");
- s = s.replace("κ", "K");
- s = s.replace("λ", "Λ");
- s = s.replace("μ", "M");
- s = s.replace("ν", "N");
- s = s.replace("ξ", "Ξ");
- s = s.replace("ο", "O");
- s = s.replace("π", "Π");
- s = s.replace("ρ", "P");
- s = s.replace("σ", "Σ");
- s = s.replace("τ", "T");
- s = s.replace("υ", "Y");
- s = s.replace("φ", "Φ");
- s = s.replace("χ", "X");
- s = s.replace("ψ", "Ψ");
- s = s.replace("ω", "Ω");
- s = s.replace("ς", "Σ");
-
- output.append(s);
- }
- }
-
- // No changes were attempted, so don't return anything
- if (unfiltered) {
- return null;
- }
- // Source is a spanned string, so copy the spans from it
- else if (source instanceof Spanned) {
- SpannableString spannedoutput = new SpannableString(output);
- TextUtils.copySpansFrom(
- (Spanned) source, start, end, null, spannedoutput, 0);
-
- return spannedoutput;
- }
- // Source is a vanilla charsequence, so return output as-is
- else {
- return output;
- }
- }
- }
-
private void editSlideshow() {
// The user wants to edit the slideshow. That requires us to persist the slideshow to
// disk as a PDU in saveAsMms. This code below does that persisting in a background
@@ -2084,14 +1970,12 @@ public class ComposeMessageActivity extends Activity
initResourceRefs();
LengthFilter lengthFilter = new LengthFilter(MmsConfig.getMaxTextLimit());
+ mTextEditor.setFilters(new InputFilter[] { lengthFilter });
if (unicodeStripping != MessagingPreferenceActivity.UNICODE_STRIPPING_LEAVE_INTACT) {
- boolean stripNonDecodableOnly = unicodeStripping == MessagingPreferenceActivity
- .UNICODE_STRIPPING_NON_DECODABLE;
- mTextEditor.setFilters(new InputFilter[] { new StripUnicode(stripNonDecodableOnly),
- lengthFilter });
- } else {
- mTextEditor.setFilters(new InputFilter[] { lengthFilter });
+ boolean stripNonDecodableOnly =
+ unicodeStripping == MessagingPreferenceActivity.UNICODE_STRIPPING_NON_DECODABLE;
+ mUnicodeFilter = new UnicodeFilter(stripNonDecodableOnly);
}
mContentResolver = getContentResolver();
@@ -3713,6 +3597,8 @@ public class ComposeMessageActivity extends Activity
updateSendButtonState();
+ // strip unicode for counting characters
+ s = stripUnicodeIfRequested(s);
updateCounter(s, start, before, count);
ensureCorrectButtonHeight();
@@ -4020,6 +3906,8 @@ public class ComposeMessageActivity extends Activity
// them back once the recipient list has settled.
removeRecipientsListeners();
+ // strip unicode chars before sending (if applicable)
+ mWorkingMessage.setText(stripUnicodeIfRequested(mWorkingMessage.getText()));
mWorkingMessage.send(mDebugRecipients);
mSentMessage = true;
@@ -4909,6 +4797,13 @@ public class ComposeMessageActivity extends Activity
getLoaderManager().restartLoader(LOAD_TEMPLATES, null, this);
}
+ private CharSequence stripUnicodeIfRequested(CharSequence text) {
+ if (mUnicodeFilter != null) {
+ text = mUnicodeFilter.filter(text);
+ }
+ return text;
+ }
+
@Override
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
ArrayList<Prediction> predictions = mLibrary.recognize(gesture);
diff --git a/src/com/android/mms/util/UnicodeFilter.java b/src/com/android/mms/util/UnicodeFilter.java
new file mode 100644
index 0000000..d29da73
--- /dev/null
+++ b/src/com/android/mms/util/UnicodeFilter.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2012-2013 The CyanogenMod 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.mms.util;
+
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.TextUtils;
+
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.text.Normalizer;
+import java.util.regex.Pattern;
+
+/**
+ * Attempts to substitute characters that cannot be encoded in the limited
+ * GSM 03.38 character set. In many cases this will prevent sending a message
+ * containing characters that would switch the message from 7-bit GSM
+ * encoding (160 char limit) to 16-bit Unicode encoding (70 char limit).
+ */
+public class UnicodeFilter {
+ private CharsetEncoder gsm =
+ Charset.forName("gsm-03.38-2000").newEncoder();
+
+ private Pattern diacritics =
+ Pattern.compile("\\p{InCombiningDiacriticalMarks}");
+
+ private boolean mStripNonDecodableOnly;
+
+ public UnicodeFilter(boolean stripNonDecodableOnly) {
+ mStripNonDecodableOnly = stripNonDecodableOnly;
+ }
+
+ public CharSequence filter(CharSequence source) {
+ StringBuilder output = new StringBuilder(source);
+ final int sourceLength = source.length();
+
+ for (int i = 0; i < sourceLength; i++) {
+ char c = source.charAt(i);
+
+ // Character requires Unicode, try to replace it
+ if (!mStripNonDecodableOnly || !gsm.canEncode(c)) {
+ String s = String.valueOf(c);
+
+ // Try normalizing the character into Unicode NFKD form and
+ // stripping out diacritic mark characters.
+ s = Normalizer.normalize(s, Normalizer.Form.NFKD);
+ s = diacritics.matcher(s).replaceAll("");
+
+ // Special case characters that don't get stripped by the
+ // above technique.
+ s = s.replace("Œ", "OE");
+ s = s.replace("œ", "oe");
+ s = s.replace("Ł", "L");
+ s = s.replace("ł", "l");
+ s = s.replace("Đ", "DJ");
+ s = s.replace("đ", "dj");
+ s = s.replace("Α", "A");
+ s = s.replace("Β", "B");
+ s = s.replace("Ε", "E");
+ s = s.replace("Ζ", "Z");
+ s = s.replace("Η", "H");
+ s = s.replace("Ι", "I");
+ s = s.replace("Κ", "K");
+ s = s.replace("Μ", "M");
+ s = s.replace("Ν", "N");
+ s = s.replace("Ο", "O");
+ s = s.replace("Ρ", "P");
+ s = s.replace("Τ", "T");
+ s = s.replace("Υ", "Y");
+ s = s.replace("Χ", "X");
+ s = s.replace("α", "A");
+ s = s.replace("β", "B");
+ s = s.replace("γ", "Γ");
+ s = s.replace("δ", "Δ");
+ s = s.replace("ε", "E");
+ s = s.replace("ζ", "Z");
+ s = s.replace("η", "H");
+ s = s.replace("θ", "Θ");
+ s = s.replace("ι", "I");
+ s = s.replace("κ", "K");
+ s = s.replace("λ", "Λ");
+ s = s.replace("μ", "M");
+ s = s.replace("ν", "N");
+ s = s.replace("ξ", "Ξ");
+ s = s.replace("ο", "O");
+ s = s.replace("π", "Π");
+ s = s.replace("ρ", "P");
+ s = s.replace("σ", "Σ");
+ s = s.replace("τ", "T");
+ s = s.replace("υ", "Y");
+ s = s.replace("φ", "Φ");
+ s = s.replace("χ", "X");
+ s = s.replace("ψ", "Ψ");
+ s = s.replace("ω", "Ω");
+ s = s.replace("ς", "Σ");
+
+ output.replace(i, i + 1, s);
+ }
+ }
+
+ // Source is a spanned string, so copy the spans from it
+ if (source instanceof Spanned) {
+ SpannableString spannedoutput = new SpannableString(output);
+ TextUtils.copySpansFrom(
+ (Spanned) source, 0, sourceLength, null, spannedoutput, 0);
+
+ return spannedoutput;
+ }
+
+ // Source is a vanilla charsequence, so return output as-is
+ return output.toString();
+ }
+}