summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2012-04-13 16:47:38 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-04-13 16:47:38 -0700
commit2a07308ed27b7323377142c69975b019244e38d7 (patch)
tree5d3b5b2bf0b85fb2af963173fbdfcfb66aeeccca
parenta94afeb5b3c3c95c6d2cf0cd4d69587aba569cfb (diff)
parentacb69bb909d098cea284df47d794c17171d84c91 (diff)
downloadframeworks_base-2a07308ed27b7323377142c69975b019244e38d7.zip
frameworks_base-2a07308ed27b7323377142c69975b019244e38d7.tar.gz
frameworks_base-2a07308ed27b7323377142c69975b019244e38d7.tar.bz2
Merge "Add direct support for HTML formatted text in ClipData etc."
-rw-r--r--api/current.txt9
-rw-r--r--core/java/android/content/ClipData.java299
-rw-r--r--core/java/android/content/ClipDescription.java5
-rw-r--r--core/java/android/content/ContentResolver.java2
-rw-r--r--core/java/android/content/Intent.java36
-rw-r--r--core/java/android/text/Html.java11
-rw-r--r--core/java/android/widget/Editor.java2
-rw-r--r--core/java/android/widget/TextView.java2
8 files changed, 348 insertions, 18 deletions
diff --git a/api/current.txt b/api/current.txt
index eacce52..d0ab197 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4833,6 +4833,7 @@ package android.content {
method public android.content.ClipDescription getDescription();
method public android.content.ClipData.Item getItemAt(int);
method public int getItemCount();
+ method public static android.content.ClipData newHtmlText(java.lang.CharSequence, java.lang.CharSequence, java.lang.String);
method public static android.content.ClipData newIntent(java.lang.CharSequence, android.content.Intent);
method public static android.content.ClipData newPlainText(java.lang.CharSequence, java.lang.CharSequence);
method public static android.content.ClipData newRawUri(java.lang.CharSequence, android.net.Uri);
@@ -4843,10 +4844,15 @@ package android.content {
public static class ClipData.Item {
ctor public ClipData.Item(java.lang.CharSequence);
+ ctor public ClipData.Item(java.lang.CharSequence, java.lang.String);
ctor public ClipData.Item(android.content.Intent);
ctor public ClipData.Item(android.net.Uri);
ctor public ClipData.Item(java.lang.CharSequence, android.content.Intent, android.net.Uri);
+ ctor public ClipData.Item(java.lang.CharSequence, java.lang.String, android.content.Intent, android.net.Uri);
+ method public java.lang.String coerceToHtmlText(android.content.Context);
+ method public java.lang.CharSequence coerceToStyledText(android.content.Context);
method public java.lang.CharSequence coerceToText(android.content.Context);
+ method public java.lang.String getHtmlText();
method public android.content.Intent getIntent();
method public java.lang.CharSequence getText();
method public android.net.Uri getUri();
@@ -4864,6 +4870,7 @@ package android.content {
method public boolean hasMimeType(java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
+ field public static final java.lang.String MIMETYPE_TEXT_HTML = "text/html";
field public static final java.lang.String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent";
field public static final java.lang.String MIMETYPE_TEXT_PLAIN = "text/plain";
field public static final java.lang.String MIMETYPE_TEXT_URILIST = "text/uri-list";
@@ -5701,6 +5708,7 @@ package android.content {
field public static final int EXTRA_DOCK_STATE_UNDOCKED = 0; // 0x0
field public static final java.lang.String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP";
field public static final java.lang.String EXTRA_EMAIL = "android.intent.extra.EMAIL";
+ field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
field public static final java.lang.String EXTRA_INSTALLER_PACKAGE_NAME = "android.intent.extra.INSTALLER_PACKAGE_NAME";
field public static final java.lang.String EXTRA_INTENT = "android.intent.extra.INTENT";
@@ -20406,6 +20414,7 @@ package android.text {
}
public class Html {
+ method public static java.lang.String escapeHtml(java.lang.CharSequence);
method public static android.text.Spanned fromHtml(java.lang.String);
method public static android.text.Spanned fromHtml(java.lang.String, android.text.Html.ImageGetter, android.text.Html.TagHandler);
method public static java.lang.String toHtml(android.text.Spanned);
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index a655dd4..1866830 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -21,7 +21,12 @@ import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.Html;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
import android.text.TextUtils;
+import android.text.style.URLSpan;
import android.util.Log;
import java.io.FileInputStream;
@@ -144,6 +149,8 @@ import java.util.ArrayList;
public class ClipData implements Parcelable {
static final String[] MIMETYPES_TEXT_PLAIN = new String[] {
ClipDescription.MIMETYPE_TEXT_PLAIN };
+ static final String[] MIMETYPES_TEXT_HTML = new String[] {
+ ClipDescription.MIMETYPE_TEXT_HTML };
static final String[] MIMETYPES_TEXT_URILIST = new String[] {
ClipDescription.MIMETYPE_TEXT_URILIST };
static final String[] MIMETYPES_TEXT_INTENT = new String[] {
@@ -176,6 +183,7 @@ public class ClipData implements Parcelable {
*/
public static class Item {
final CharSequence mText;
+ final String mHtmlText;
final Intent mIntent;
final Uri mUri;
@@ -184,6 +192,20 @@ public class ClipData implements Parcelable {
*/
public Item(CharSequence text) {
mText = text;
+ mHtmlText = null;
+ mIntent = null;
+ mUri = null;
+ }
+
+ /**
+ * Create an Item consisting of a single block of (possibly styled) text,
+ * with an alternative HTML formatted representation. You <em>must</em>
+ * supply a plain text representation in addition to HTML text; coercion
+ * will not be done from HTML formated text into plain text.
+ */
+ public Item(CharSequence text, String htmlText) {
+ mText = text;
+ mHtmlText = htmlText;
mIntent = null;
mUri = null;
}
@@ -193,6 +215,7 @@ public class ClipData implements Parcelable {
*/
public Item(Intent intent) {
mText = null;
+ mHtmlText = null;
mIntent = intent;
mUri = null;
}
@@ -202,16 +225,35 @@ public class ClipData implements Parcelable {
*/
public Item(Uri uri) {
mText = null;
+ mHtmlText = null;
mIntent = null;
mUri = uri;
}
/**
* Create a complex Item, containing multiple representations of
- * text, intent, and/or URI.
+ * text, Intent, and/or URI.
*/
public Item(CharSequence text, Intent intent, Uri uri) {
mText = text;
+ mHtmlText = null;
+ mIntent = intent;
+ mUri = uri;
+ }
+
+ /**
+ * Create a complex Item, containing multiple representations of
+ * text, HTML text, Intent, and/or URI. If providing HTML text, you
+ * <em>must</em> supply a plain text representation as well; coercion
+ * will not be done from HTML formated text into plain text.
+ */
+ public Item(CharSequence text, String htmlText, Intent intent, Uri uri) {
+ if (htmlText != null && text == null) {
+ throw new IllegalArgumentException(
+ "Plain text must be supplied if HTML text is supplied");
+ }
+ mText = text;
+ mHtmlText = htmlText;
mIntent = intent;
mUri = uri;
}
@@ -224,6 +266,13 @@ public class ClipData implements Parcelable {
}
/**
+ * Retrieve the raw HTML text contained in this Item.
+ */
+ public String getHtmlText() {
+ return mHtmlText;
+ }
+
+ /**
* Retrieve the raw Intent contained in this Item.
*/
public Intent getIntent() {
@@ -250,7 +299,7 @@ public class ClipData implements Parcelable {
* the content provider does not supply a text representation, return
* the raw URI as a string.
* <li> If {@link #getIntent} is non-null, convert that to an intent:
- * URI and returnit.
+ * URI and return it.
* <li> Otherwise, return an empty string.
* </ul>
*
@@ -261,12 +310,14 @@ public class ClipData implements Parcelable {
//BEGIN_INCLUDE(coerceToText)
public CharSequence coerceToText(Context context) {
// If this Item has an explicit textual value, simply return that.
- if (mText != null) {
- return mText;
+ CharSequence text = getText();
+ if (text != null) {
+ return text;
}
// If this Item has a URI value, try using that.
- if (mUri != null) {
+ Uri uri = getUri();
+ if (uri != null) {
// First see if the URI can be opened as a plain text stream
// (of any sub-type). If so, this is the best textual
@@ -275,7 +326,7 @@ public class ClipData implements Parcelable {
try {
// Ask for a stream of the desired type.
AssetFileDescriptor descr = context.getContentResolver()
- .openTypedAssetFileDescriptor(mUri, "text/*", null);
+ .openTypedAssetFileDescriptor(uri, "text/*", null);
stream = descr.createInputStream();
InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
@@ -308,13 +359,14 @@ public class ClipData implements Parcelable {
// If we couldn't open the URI as a stream, then the URI itself
// probably serves fairly well as a textual representation.
- return mUri.toString();
+ return uri.toString();
}
// Finally, if all we have is an Intent, then we can just turn that
// into text. Not the most user-friendly thing, but it's something.
- if (mIntent != null) {
- return mIntent.toUri(Intent.URI_INTENT_SCHEME);
+ Intent intent = getIntent();
+ if (intent != null) {
+ return intent.toUri(Intent.URI_INTENT_SCHEME);
}
// Shouldn't get here, but just in case...
@@ -322,6 +374,210 @@ public class ClipData implements Parcelable {
}
//END_INCLUDE(coerceToText)
+ /**
+ * Like {@link #coerceToHtmlText(Context)}, but any text that would
+ * be returned as HTML formatting will be returned as text with
+ * style spans.
+ * @param context The caller's Context, from which its ContentResolver
+ * and other things can be retrieved.
+ * @return Returns the item's textual representation.
+ */
+ public CharSequence coerceToStyledText(Context context) {
+ CharSequence text = getText();
+ if (text instanceof Spanned) {
+ return text;
+ }
+ String htmlText = getHtmlText();
+ if (htmlText != null) {
+ try {
+ CharSequence newText = Html.fromHtml(htmlText);
+ if (newText != null) {
+ return newText;
+ }
+ } catch (RuntimeException e) {
+ // If anything bad happens, we'll fall back on the plain text.
+ }
+ }
+
+ if (text != null) {
+ return text;
+ }
+ return coerceToHtmlOrStyledText(context, true);
+ }
+
+ /**
+ * Turn this item into HTML text, regardless of the type of data it
+ * actually contains.
+ *
+ * <p>The algorithm for deciding what text to return is:
+ * <ul>
+ * <li> If {@link #getHtmlText} is non-null, return that.
+ * <li> If {@link #getText} is non-null, return that, converting to
+ * valid HTML text. If this text contains style spans,
+ * {@link Html#toHtml(Spanned) Html.toHtml(Spanned)} is used to
+ * convert them to HTML formatting.
+ * <li> If {@link #getUri} is non-null, try to retrieve its data
+ * as a text stream from its content provider. If the provider can
+ * supply text/html data, that will be preferred and returned as-is.
+ * Otherwise, any text/* data will be returned and escaped to HTML.
+ * If it is not a content: URI or the content provider does not supply
+ * a text representation, HTML text containing a link to the URI
+ * will be returned.
+ * <li> If {@link #getIntent} is non-null, convert that to an intent:
+ * URI and return as an HTML link.
+ * <li> Otherwise, return an empty string.
+ * </ul>
+ *
+ * @param context The caller's Context, from which its ContentResolver
+ * and other things can be retrieved.
+ * @return Returns the item's representation as HTML text.
+ */
+ public String coerceToHtmlText(Context context) {
+ // If the item has an explicit HTML value, simply return that.
+ String htmlText = getHtmlText();
+ if (htmlText != null) {
+ return htmlText;
+ }
+
+ // If this Item has a plain text value, return it as HTML.
+ CharSequence text = getText();
+ if (text != null) {
+ if (text instanceof Spanned) {
+ return Html.toHtml((Spanned)text);
+ }
+ return Html.escapeHtml(text);
+ }
+
+ text = coerceToHtmlOrStyledText(context, false);
+ return text != null ? text.toString() : null;
+ }
+
+ private CharSequence coerceToHtmlOrStyledText(Context context, boolean styled) {
+ // If this Item has a URI value, try using that.
+ if (mUri != null) {
+
+ // Check to see what data representations the content
+ // provider supports. We would like HTML text, but if that
+ // is not possible we'll live with plan text.
+ String[] types = context.getContentResolver().getStreamTypes(mUri, "text/*");
+ boolean hasHtml = false;
+ boolean hasText = false;
+ if (types != null) {
+ for (String type : types) {
+ if ("text/html".equals(type)) {
+ hasHtml = true;
+ } else if (type.startsWith("text/")) {
+ hasText = true;
+ }
+ }
+ }
+
+ // If the provider can serve data we can use, open and load it.
+ if (hasHtml || hasText) {
+ FileInputStream stream = null;
+ try {
+ // Ask for a stream of the desired type.
+ AssetFileDescriptor descr = context.getContentResolver()
+ .openTypedAssetFileDescriptor(mUri,
+ hasHtml ? "text/html" : "text/plain", null);
+ stream = descr.createInputStream();
+ InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
+
+ // Got it... copy the stream into a local string and return it.
+ StringBuilder builder = new StringBuilder(128);
+ char[] buffer = new char[8192];
+ int len;
+ while ((len=reader.read(buffer)) > 0) {
+ builder.append(buffer, 0, len);
+ }
+ String text = builder.toString();
+ if (hasHtml) {
+ if (styled) {
+ // We loaded HTML formatted text and the caller
+ // want styled text, convert it.
+ try {
+ CharSequence newText = Html.fromHtml(text);
+ return newText != null ? newText : text;
+ } catch (RuntimeException e) {
+ return text;
+ }
+ } else {
+ // We loaded HTML formatted text and that is what
+ // the caller wants, just return it.
+ return text.toString();
+ }
+ }
+ if (styled) {
+ // We loaded plain text and the caller wants styled
+ // text, that is all we have so return it.
+ return text;
+ } else {
+ // We loaded plain text and the caller wants HTML
+ // text, escape it for HTML.
+ return Html.escapeHtml(text);
+ }
+
+ } catch (FileNotFoundException e) {
+ // Unable to open content URI as text... not really an
+ // error, just something to ignore.
+
+ } catch (IOException e) {
+ // Something bad has happened.
+ Log.w("ClippedData", "Failure loading text", e);
+ return Html.escapeHtml(e.toString());
+
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ // If we couldn't open the URI as a stream, then we can build
+ // some HTML text with the URI itself.
+ // probably serves fairly well as a textual representation.
+ if (styled) {
+ return uriToStyledText(mUri.toString());
+ } else {
+ return uriToHtml(mUri.toString());
+ }
+ }
+
+ // Finally, if all we have is an Intent, then we can just turn that
+ // into text. Not the most user-friendly thing, but it's something.
+ if (mIntent != null) {
+ if (styled) {
+ return uriToStyledText(mIntent.toUri(Intent.URI_INTENT_SCHEME));
+ } else {
+ return uriToHtml(mIntent.toUri(Intent.URI_INTENT_SCHEME));
+ }
+ }
+
+ // Shouldn't get here, but just in case...
+ return "";
+ }
+
+ private String uriToHtml(String uri) {
+ StringBuilder builder = new StringBuilder(256);
+ builder.append("<a href=\"");
+ builder.append(uri);
+ builder.append("\">");
+ builder.append(Html.escapeHtml(uri));
+ builder.append("</a>");
+ return builder.toString();
+ }
+
+ private CharSequence uriToStyledText(String uri) {
+ SpannableStringBuilder builder = new SpannableStringBuilder();
+ builder.append(uri);
+ builder.setSpan(new URLSpan(uri), 0, builder.length(),
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ return builder;
+ }
+
@Override
public String toString() {
StringBuilder b = new StringBuilder(128);
@@ -335,7 +591,10 @@ public class ClipData implements Parcelable {
/** @hide */
public void toShortString(StringBuilder b) {
- if (mText != null) {
+ if (mHtmlText != null) {
+ b.append("H:");
+ b.append(mHtmlText);
+ } else if (mText != null) {
b.append("T:");
b.append(mText);
} else if (mUri != null) {
@@ -409,6 +668,22 @@ public class ClipData implements Parcelable {
}
/**
+ * Create a new ClipData holding data of the type
+ * {@link ClipDescription#MIMETYPE_TEXT_HTML}.
+ *
+ * @param label User-visible label for the clip data.
+ * @param text The text of clip as plain text, for receivers that don't
+ * handle HTML. This is required.
+ * @param htmlText The actual HTML text in the clip.
+ * @return Returns a new ClipData containing the specified data.
+ */
+ static public ClipData newHtmlText(CharSequence label, CharSequence text,
+ String htmlText) {
+ Item item = new Item(text, htmlText);
+ return new ClipData(label, MIMETYPES_TEXT_HTML, item);
+ }
+
+ /**
* Create a new ClipData holding an Intent with MIME type
* {@link ClipDescription#MIMETYPE_TEXT_INTENT}.
*
@@ -574,6 +849,7 @@ public class ClipData implements Parcelable {
for (int i=0; i<N; i++) {
Item item = mItems.get(i);
TextUtils.writeToParcel(item.mText, dest, flags);
+ dest.writeString(item.mHtmlText);
if (item.mIntent != null) {
dest.writeInt(1);
item.mIntent.writeToParcel(dest, flags);
@@ -600,9 +876,10 @@ public class ClipData implements Parcelable {
final int N = in.readInt();
for (int i=0; i<N; i++) {
CharSequence text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ String htmlText = in.readString();
Intent intent = in.readInt() != 0 ? Intent.CREATOR.createFromParcel(in) : null;
Uri uri = in.readInt() != 0 ? Uri.CREATOR.createFromParcel(in) : null;
- mItems.add(new Item(text, intent, uri));
+ mItems.add(new Item(text, htmlText, intent, uri));
}
}
diff --git a/core/java/android/content/ClipDescription.java b/core/java/android/content/ClipDescription.java
index c6b51ef..5cb6e77 100644
--- a/core/java/android/content/ClipDescription.java
+++ b/core/java/android/content/ClipDescription.java
@@ -41,6 +41,11 @@ public class ClipDescription implements Parcelable {
public static final String MIMETYPE_TEXT_PLAIN = "text/plain";
/**
+ * The MIME type for a clip holding HTML text.
+ */
+ public static final String MIMETYPE_TEXT_HTML = "text/html";
+
+ /**
* The MIME type for a clip holding one or more URIs. This should be
* used for URIs that are meaningful to a user (such as an http: URI).
* It should <em>not</em> be used for a content: URI that references some
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 2930998..722fdc6 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -248,7 +248,7 @@ public abstract class ContentResolver {
* @param mimeTypeFilter The desired MIME type. This may be a pattern,
* such as *\/*, to query for all available MIME types that match the
* pattern.
- * @return Returns an array of MIME type strings for all availablle
+ * @return Returns an array of MIME type strings for all available
* data streams that match the given mimeTypeFilter. If there are none,
* null is returned.
*/
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 18d682d..19e4372 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -954,7 +954,18 @@ public class Intent implements Parcelable, Cloneable {
* using EXTRA_TEXT, the MIME type should be "text/plain"; otherwise it
* should be the MIME type of the data in EXTRA_STREAM. Use {@literal *}/*
* if the MIME type is unknown (this will only allow senders that can
- * handle generic data streams).
+ * handle generic data streams). If using {@link #EXTRA_TEXT}, you can
+ * also optionally supply {@link #EXTRA_HTML_TEXT} for clients to retrieve
+ * your text with HTML formatting.
+ * <p>
+ * As of {@link android.os.Build.VERSION_CODES#JELLY_BEAN}, the data
+ * being sent can be supplied through {@link #setClipData(ClipData)}. This
+ * allows you to use {@link #FLAG_GRANT_READ_URI_PERMISSION} when sharing
+ * content: URIs and other advanced features of {@link ClipData}. If
+ * using this approach, you still must supply the same data through the
+ * {@link #EXTRA_TEXT} or {@link #EXTRA_STREAM} fields described below
+ * for compatibility with old applications. If you don't set a ClipData,
+ * it will be copied there for you when calling {@link Context#startActivity(Intent)}.
* <p>
* Optional standard extras, which may be interpreted by some recipients as
* appropriate, are: {@link #EXTRA_EMAIL}, {@link #EXTRA_CC},
@@ -967,11 +978,13 @@ public class Intent implements Parcelable, Cloneable {
/**
* Activity Action: Deliver multiple data to someone else.
* <p>
- * Like ACTION_SEND, except the data is multiple.
+ * Like {@link #ACTION_SEND}, except the data is multiple.
* <p>
* Input: {@link #getType} is the MIME type of the data being sent.
* get*ArrayListExtra can have either a {@link #EXTRA_TEXT} or {@link
- * #EXTRA_STREAM} field, containing the data to be sent.
+ * #EXTRA_STREAM} field, containing the data to be sent. If using
+ * {@link #EXTRA_TEXT}, you can also optionally supply {@link #EXTRA_HTML_TEXT}
+ * for clients to retrieve your text with HTML formatting.
* <p>
* Multiple types are supported, and receivers should handle mixed types
* whenever possible. The right way for the receiver to check them is to
@@ -983,6 +996,15 @@ public class Intent implements Parcelable, Cloneable {
* be image/jpg, but if you are sending image/jpg and image/png, then the
* intent's type should be image/*.
* <p>
+ * As of {@link android.os.Build.VERSION_CODES#JELLY_BEAN}, the data
+ * being sent can be supplied through {@link #setClipData(ClipData)}. This
+ * allows you to use {@link #FLAG_GRANT_READ_URI_PERMISSION} when sharing
+ * content: URIs and other advanced features of {@link ClipData}. If
+ * using this approach, you still must supply the same data through the
+ * {@link #EXTRA_TEXT} or {@link #EXTRA_STREAM} fields described below
+ * for compatibility with old applications. If you don't set a ClipData,
+ * it will be copied there for you when calling {@link Context#startActivity(Intent)}.
+ * <p>
* Optional standard extras, which may be interpreted by some recipients as
* appropriate, are: {@link #EXTRA_EMAIL}, {@link #EXTRA_CC},
* {@link #EXTRA_BCC}, {@link #EXTRA_SUBJECT}.
@@ -2501,6 +2523,14 @@ public class Intent implements Parcelable, Cloneable {
public static final String EXTRA_TEXT = "android.intent.extra.TEXT";
/**
+ * A constant String that is associated with the Intent, used with
+ * {@link #ACTION_SEND} to supply an alternative to {@link #EXTRA_TEXT}
+ * as HTML formatted text. Note that you <em>must</em> also supply
+ * {@link #EXTRA_TEXT}.
+ */
+ public static final String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
+
+ /**
* A content: URI holding a stream of data associated with the Intent,
* used with {@link #ACTION_SEND} to supply the data being sent.
*/
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index 8c97293..35e2e4a 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -147,6 +147,15 @@ public class Html {
return out.toString();
}
+ /**
+ * Returns an HTML escaped representation of the given plain text.
+ */
+ public static String escapeHtml(CharSequence text) {
+ StringBuilder out = new StringBuilder();
+ withinStyle(out, text, 0, text.length());
+ return out.toString();
+ }
+
private static void withinHtml(StringBuilder out, Spanned text) {
int len = text.length();
@@ -370,7 +379,7 @@ public class Html {
}
}
- private static void withinStyle(StringBuilder out, Spanned text,
+ private static void withinStyle(StringBuilder out, CharSequence text,
int start, int end) {
for (int i = start; i < end; i++) {
char c = text.charAt(i);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index cbff58c..040a385 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1681,7 +1681,7 @@ public class Editor {
final int itemCount = clipData.getItemCount();
for (int i=0; i < itemCount; i++) {
Item item = clipData.getItemAt(i);
- content.append(item.coerceToText(mTextView.getContext()));
+ content.append(item.coerceToStyledText(mTextView.getContext()));
}
final int offset = mTextView.getOffsetForPosition(event.getX(), event.getY());
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9867e47..3b0fb36 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -7710,7 +7710,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (clip != null) {
boolean didFirst = false;
for (int i=0; i<clip.getItemCount(); i++) {
- CharSequence paste = clip.getItemAt(i).coerceToText(getContext());
+ CharSequence paste = clip.getItemAt(i).coerceToStyledText(getContext());
if (paste != null) {
if (!didFirst) {
long minMax = prepareSpacesAroundPaste(min, max, paste);