summaryrefslogtreecommitdiffstats
path: root/core/java/android/text
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:45 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:45 -0800
commitd83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/java/android/text
parent076357b8567458d4b6dfdcf839ef751634cd2bfb (diff)
downloadframeworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip
frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz
frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/java/android/text')
-rw-r--r--core/java/android/text/AlteredCharSequence.java127
-rw-r--r--core/java/android/text/AndroidCharacter.java45
-rw-r--r--core/java/android/text/Annotation.java60
-rw-r--r--core/java/android/text/AutoText.java246
-rw-r--r--core/java/android/text/BoringLayout.java388
-rw-r--r--core/java/android/text/ClipboardManager.java88
-rw-r--r--core/java/android/text/DynamicLayout.java503
-rw-r--r--core/java/android/text/Editable.java142
-rw-r--r--core/java/android/text/GetChars.java33
-rw-r--r--core/java/android/text/GraphicsOperations.java46
-rw-r--r--core/java/android/text/Html.java784
-rw-r--r--core/java/android/text/IClipboard.aidl42
-rw-r--r--core/java/android/text/InputFilter.java97
-rw-r--r--core/java/android/text/InputType.java254
-rw-r--r--core/java/android/text/Layout.java1747
-rw-r--r--core/java/android/text/LoginFilter.java219
-rw-r--r--core/java/android/text/NoCopySpan.java31
-rw-r--r--core/java/android/text/PackedIntVector.java368
-rw-r--r--core/java/android/text/PackedObjectVector.java188
-rw-r--r--core/java/android/text/ParcelableSpan.java31
-rw-r--r--core/java/android/text/Selection.java429
-rw-r--r--core/java/android/text/SpanWatcher.java42
-rw-r--r--core/java/android/text/Spannable.java70
-rw-r--r--core/java/android/text/SpannableString.java56
-rw-r--r--core/java/android/text/SpannableStringBuilder.java1140
-rw-r--r--core/java/android/text/SpannableStringInternal.java372
-rw-r--r--core/java/android/text/Spanned.java182
-rw-r--r--core/java/android/text/SpannedString.java48
-rw-r--r--core/java/android/text/StaticLayout.java1195
-rw-r--r--core/java/android/text/Styled.java298
-rw-r--r--core/java/android/text/TextPaint.java55
-rw-r--r--core/java/android/text/TextUtils.java1620
-rw-r--r--core/java/android/text/TextWatcher.java57
-rw-r--r--core/java/android/text/format/DateFormat.java585
-rw-r--r--core/java/android/text/format/DateUtils.java1581
-rw-r--r--core/java/android/text/format/Formatter.java83
-rw-r--r--core/java/android/text/format/Time.java757
-rw-r--r--core/java/android/text/method/ArrowKeyMovementMethod.java286
-rw-r--r--core/java/android/text/method/BaseKeyListener.java160
-rw-r--r--core/java/android/text/method/CharacterPickerDialog.java134
-rw-r--r--core/java/android/text/method/DateKeyListener.java58
-rw-r--r--core/java/android/text/method/DateTimeKeyListener.java58
-rw-r--r--core/java/android/text/method/DialerKeyListener.java113
-rw-r--r--core/java/android/text/method/DigitsKeyListener.java218
-rw-r--r--core/java/android/text/method/HideReturnsTransformationMethod.java59
-rw-r--r--core/java/android/text/method/KeyListener.java79
-rw-r--r--core/java/android/text/method/LinkMovementMethod.java256
-rw-r--r--core/java/android/text/method/MetaKeyKeyListener.java485
-rw-r--r--core/java/android/text/method/MovementMethod.java51
-rw-r--r--core/java/android/text/method/MultiTapKeyListener.java286
-rw-r--r--core/java/android/text/method/NumberKeyListener.java131
-rw-r--r--core/java/android/text/method/PasswordTransformationMethod.java264
-rw-r--r--core/java/android/text/method/QwertyKeyListener.java451
-rw-r--r--core/java/android/text/method/ReplacementTransformationMethod.java205
-rw-r--r--core/java/android/text/method/ScrollingMovementMethod.java240
-rw-r--r--core/java/android/text/method/SingleLineTransformationMethod.java62
-rw-r--r--core/java/android/text/method/TextKeyListener.java297
-rw-r--r--core/java/android/text/method/TimeKeyListener.java58
-rw-r--r--core/java/android/text/method/Touch.java156
-rw-r--r--core/java/android/text/method/TransformationMethod.java46
-rw-r--r--core/java/android/text/method/package.html21
-rw-r--r--core/java/android/text/package.html13
-rw-r--r--core/java/android/text/style/AbsoluteSizeSpan.java61
-rw-r--r--core/java/android/text/style/AlignmentSpan.java55
-rw-r--r--core/java/android/text/style/BackgroundColorSpan.java57
-rw-r--r--core/java/android/text/style/BulletSpan.java102
-rw-r--r--core/java/android/text/style/CharacterStyle.java87
-rw-r--r--core/java/android/text/style/ClickableSpan.java43
-rw-r--r--core/java/android/text/style/DrawableMarginSpan.java79
-rw-r--r--core/java/android/text/style/DynamicDrawableSpan.java128
-rw-r--r--core/java/android/text/style/ForegroundColorSpan.java57
-rw-r--r--core/java/android/text/style/IconMarginSpan.java73
-rw-r--r--core/java/android/text/style/ImageSpan.java144
-rw-r--r--core/java/android/text/style/LeadingMarginSpan.java78
-rw-r--r--core/java/android/text/style/LineBackgroundSpan.java30
-rw-r--r--core/java/android/text/style/LineHeightSpan.java29
-rw-r--r--core/java/android/text/style/MaskFilterSpan.java38
-rw-r--r--core/java/android/text/style/MetricAffectingSpan.java85
-rw-r--r--core/java/android/text/style/ParagraphStyle.java26
-rw-r--r--core/java/android/text/style/QuoteSpan.java81
-rw-r--r--core/java/android/text/style/RasterizerSpan.java38
-rw-r--r--core/java/android/text/style/RelativeSizeSpan.java61
-rw-r--r--core/java/android/text/style/ReplacementSpan.java43
-rw-r--r--core/java/android/text/style/ScaleXSpan.java61
-rw-r--r--core/java/android/text/style/StrikethroughSpan.java47
-rw-r--r--core/java/android/text/style/StyleSpan.java112
-rw-r--r--core/java/android/text/style/SubscriptSpan.java51
-rw-r--r--core/java/android/text/style/SuperscriptSpan.java51
-rw-r--r--core/java/android/text/style/TabStopSpan.java37
-rw-r--r--core/java/android/text/style/TextAppearanceSpan.java250
-rw-r--r--core/java/android/text/style/TypefaceSpan.java96
-rw-r--r--core/java/android/text/style/URLSpan.java61
-rw-r--r--core/java/android/text/style/UnderlineSpan.java47
-rw-r--r--core/java/android/text/style/UpdateAppearance.java10
-rw-r--r--core/java/android/text/style/UpdateLayout.java25
-rw-r--r--core/java/android/text/style/WrapTogetherSpan.java23
-rw-r--r--core/java/android/text/style/package.html10
-rw-r--r--core/java/android/text/util/Linkify.java541
-rw-r--r--core/java/android/text/util/Regex.java204
-rw-r--r--core/java/android/text/util/Rfc822Token.java172
-rw-r--r--core/java/android/text/util/Rfc822Tokenizer.java292
-rw-r--r--core/java/android/text/util/Rfc822Validator.java132
-rw-r--r--core/java/android/text/util/package.html6
103 files changed, 0 insertions, 21819 deletions
diff --git a/core/java/android/text/AlteredCharSequence.java b/core/java/android/text/AlteredCharSequence.java
deleted file mode 100644
index 4cc71fd..0000000
--- a/core/java/android/text/AlteredCharSequence.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-// XXX should this really be in the public API at all?
-/**
- * An AlteredCharSequence is a CharSequence that is largely mirrored from
- * another CharSequence, except that a specified range of characters are
- * mirrored from a different char array instead.
- */
-public class AlteredCharSequence
-implements CharSequence, GetChars
-{
- /**
- * Create an AlteredCharSequence whose text (and possibly spans)
- * are mirrored from <code>source</code>, except that the range of
- * offsets <code>substart</code> inclusive to <code>subend</code> exclusive
- * are mirrored instead from <code>sub</code>, beginning at offset 0.
- */
- public static AlteredCharSequence make(CharSequence source, char[] sub,
- int substart, int subend) {
- if (source instanceof Spanned)
- return new AlteredSpanned(source, sub, substart, subend);
- else
- return new AlteredCharSequence(source, sub, substart, subend);
- }
-
- private AlteredCharSequence(CharSequence source, char[] sub,
- int substart, int subend) {
- mSource = source;
- mChars = sub;
- mStart = substart;
- mEnd = subend;
- }
-
- /* package */ void update(char[] sub, int substart, int subend) {
- mChars = sub;
- mStart = substart;
- mEnd = subend;
- }
-
- private static class AlteredSpanned
- extends AlteredCharSequence
- implements Spanned
- {
- private AlteredSpanned(CharSequence source, char[] sub,
- int substart, int subend) {
- super(source, sub, substart, subend);
- mSpanned = (Spanned) source;
- }
-
- public <T> T[] getSpans(int start, int end, Class<T> kind) {
- return mSpanned.getSpans(start, end, kind);
- }
-
- public int getSpanStart(Object span) {
- return mSpanned.getSpanStart(span);
- }
-
- public int getSpanEnd(Object span) {
- return mSpanned.getSpanEnd(span);
- }
-
- public int getSpanFlags(Object span) {
- return mSpanned.getSpanFlags(span);
- }
-
- public int nextSpanTransition(int start, int end, Class kind) {
- return mSpanned.nextSpanTransition(start, end, kind);
- }
-
- private Spanned mSpanned;
- }
-
- public char charAt(int off) {
- if (off >= mStart && off < mEnd)
- return mChars[off - mStart];
- else
- return mSource.charAt(off);
- }
-
- public int length() {
- return mSource.length();
- }
-
- public CharSequence subSequence(int start, int end) {
- return AlteredCharSequence.make(mSource.subSequence(start, end),
- mChars, mStart - start, mEnd - start);
- }
-
- public void getChars(int start, int end, char[] dest, int off) {
- TextUtils.getChars(mSource, start, end, dest, off);
-
- start = Math.max(mStart, start);
- end = Math.min(mEnd, end);
-
- if (start > end)
- System.arraycopy(mChars, start - mStart, dest, off, end - start);
- }
-
- public String toString() {
- int len = length();
-
- char[] ret = new char[len];
- getChars(0, len, ret, 0);
- return String.valueOf(ret);
- }
-
- private int mStart;
- private int mEnd;
- private char[] mChars;
- private CharSequence mSource;
-}
diff --git a/core/java/android/text/AndroidCharacter.java b/core/java/android/text/AndroidCharacter.java
deleted file mode 100644
index 6dfd64d..0000000
--- a/core/java/android/text/AndroidCharacter.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-/**
- * AndroidCharacter exposes some character properties that are not
- * easily accessed from java.lang.Character.
- */
-public class AndroidCharacter
-{
- /**
- * Fill in the first <code>count</code> bytes of <code>dest</code> with the
- * directionalities from the first <code>count</code> chars of <code>src</code>.
- * This is just like Character.getDirectionality() except it is a
- * batch operation.
- */
- public native static void getDirectionalities(char[] src, byte[] dest,
- int count);
- /**
- * Replace the specified slice of <code>text</code> with the chars'
- * right-to-left mirrors (if any), returning true if any
- * replacements were made.
- */
- public native static boolean mirror(char[] text, int start, int count);
-
- /**
- * Return the right-to-left mirror (or the original char if none)
- * of the specified char.
- */
- public native static char getMirror(char ch);
-}
diff --git a/core/java/android/text/Annotation.java b/core/java/android/text/Annotation.java
deleted file mode 100644
index dbc290b..0000000
--- a/core/java/android/text/Annotation.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.text;
-
-import android.os.Parcel;
-
-/**
- * Annotations are simple key-value pairs that are preserved across
- * TextView save/restore cycles and can be used to keep application-specific
- * data that needs to be maintained for regions of text.
- */
-public class Annotation implements ParcelableSpan {
- private final String mKey;
- private final String mValue;
-
- public Annotation(String key, String value) {
- mKey = key;
- mValue = value;
- }
-
- public Annotation(Parcel src) {
- mKey = src.readString();
- mValue = src.readString();
- }
-
- public int getSpanTypeId() {
- return TextUtils.ANNOTATION;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mKey);
- dest.writeString(mValue);
- }
-
- public String getKey() {
- return mKey;
- }
-
- public String getValue() {
- return mValue;
- }
-}
diff --git a/core/java/android/text/AutoText.java b/core/java/android/text/AutoText.java
deleted file mode 100644
index 508d740..0000000
--- a/core/java/android/text/AutoText.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.text;
-
-import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
-import com.android.internal.util.XmlUtils;
-import android.view.View;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.Locale;
-
-/**
- * This class accesses a dictionary of corrections to frequent misspellings.
- */
-public class AutoText {
- // struct trie {
- // char c;
- // int off;
- // struct trie *child;
- // struct trie *next;
- // };
-
- private static final int TRIE_C = 0;
- private static final int TRIE_OFF = 1;
- private static final int TRIE_CHILD = 2;
- private static final int TRIE_NEXT = 3;
-
- private static final int TRIE_SIZEOF = 4;
- private static final char TRIE_NULL = (char) -1;
- private static final int TRIE_ROOT = 0;
-
- private static final int INCREMENT = 1024;
-
- private static final int DEFAULT = 14337; // Size of the Trie 13 Aug 2007
-
- private static final int RIGHT = 9300; // Size of 'right' 13 Aug 2007
-
- private static AutoText sInstance = new AutoText(Resources.getSystem());
- private static Object sLock = new Object();
-
- // TODO:
- //
- // Note the assumption that the destination strings total less than
- // 64K characters and that the trie for the source side totals less
- // than 64K chars/offsets/child pointers/next pointers.
- //
- // This seems very safe for English (currently 7K of destination,
- // 14K of trie) but may need to be revisited.
-
- private char[] mTrie;
- private char mTrieUsed;
- private String mText;
- private Locale mLocale;
-
- private AutoText(Resources resources) {
- mLocale = resources.getConfiguration().locale;
- init(resources);
- }
-
- /**
- * Retrieves a possible spelling correction for the specified range
- * of text. Returns null if no correction can be found.
- * The View is used to get the current Locale and Resources.
- */
- public static String get(CharSequence src, final int start, final int end,
- View view) {
- Resources res = view.getContext().getResources();
- Locale locale = res.getConfiguration().locale;
- AutoText instance;
-
- synchronized (sLock) {
- instance = sInstance;
-
- if (!locale.equals(instance.mLocale)) {
- instance = new AutoText(res);
- sInstance = instance;
- }
- }
-
- return instance.lookup(src, start, end);
- }
-
- private String lookup(CharSequence src, final int start, final int end) {
- int here = mTrie[TRIE_ROOT];
-
- for (int i = start; i < end; i++) {
- char c = src.charAt(i);
-
- for (; here != TRIE_NULL; here = mTrie[here + TRIE_NEXT]) {
- if (c == mTrie[here + TRIE_C]) {
- if ((i == end - 1)
- && (mTrie[here + TRIE_OFF] != TRIE_NULL)) {
- int off = mTrie[here + TRIE_OFF];
- int len = mText.charAt(off);
-
- return mText.substring(off + 1, off + 1 + len);
- }
-
- here = mTrie[here + TRIE_CHILD];
- break;
- }
- }
-
- if (here == TRIE_NULL) {
- return null;
- }
- }
-
- return null;
- }
-
- private void init(Resources r) {
- XmlResourceParser parser = r.getXml(com.android.internal.R.xml.autotext);
-
- StringBuilder right = new StringBuilder(RIGHT);
- mTrie = new char[DEFAULT];
- mTrie[TRIE_ROOT] = TRIE_NULL;
- mTrieUsed = TRIE_ROOT + 1;
-
- try {
- XmlUtils.beginDocument(parser, "words");
- String odest = "";
- char ooff = 0;
-
- while (true) {
- XmlUtils.nextElement(parser);
-
- String element = parser.getName();
- if (element == null || !(element.equals("word"))) {
- break;
- }
-
- String src = parser.getAttributeValue(null, "src");
- if (parser.next() == XmlPullParser.TEXT) {
- String dest = parser.getText();
- char off;
-
- if (dest.equals(odest)) {
- off = ooff;
- } else {
- off = (char) right.length();
- right.append((char) dest.length());
- right.append(dest);
- }
-
- add(src, off);
- }
- }
-
- // Don't let Resources cache a copy of all these strings.
- r.flushLayoutCache();
- } catch (XmlPullParserException e) {
- throw new RuntimeException(e);
- } catch (IOException e) {
- throw new RuntimeException(e);
- } finally {
- parser.close();
- }
-
- mText = right.toString();
- }
-
- private void add(String src, char off) {
- int slen = src.length();
- int herep = TRIE_ROOT;
-
- for (int i = 0; i < slen; i++) {
- char c = src.charAt(i);
- boolean found = false;
-
- for (; mTrie[herep] != TRIE_NULL;
- herep = mTrie[herep] + TRIE_NEXT) {
- if (c == mTrie[mTrie[herep] + TRIE_C]) {
- // There is a node for this letter, and this is the
- // end, so fill in the right hand side fields.
-
- if (i == slen - 1) {
- mTrie[mTrie[herep] + TRIE_OFF] = off;
- return;
- }
-
- // There is a node for this letter, and we need
- // to go deeper into it to fill in the rest.
-
- herep = mTrie[herep] + TRIE_CHILD;
- found = true;
- break;
- }
- }
-
- if (!found) {
- // No node for this letter yet. Make one.
-
- char node = newTrieNode();
- mTrie[herep] = node;
-
- mTrie[mTrie[herep] + TRIE_C] = c;
- mTrie[mTrie[herep] + TRIE_OFF] = TRIE_NULL;
- mTrie[mTrie[herep] + TRIE_NEXT] = TRIE_NULL;
- mTrie[mTrie[herep] + TRIE_CHILD] = TRIE_NULL;
-
- // If this is the end of the word, fill in the offset.
-
- if (i == slen - 1) {
- mTrie[mTrie[herep] + TRIE_OFF] = off;
- return;
- }
-
- // Otherwise, step in deeper and go to the next letter.
-
- herep = mTrie[herep] + TRIE_CHILD;
- }
- }
- }
-
- private char newTrieNode() {
- if (mTrieUsed + TRIE_SIZEOF > mTrie.length) {
- char[] copy = new char[mTrie.length + INCREMENT];
- System.arraycopy(mTrie, 0, copy, 0, mTrie.length);
- mTrie = copy;
- }
-
- char ret = mTrieUsed;
- mTrieUsed += TRIE_SIZEOF;
-
- return ret;
- }
-}
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
deleted file mode 100644
index 843754b..0000000
--- a/core/java/android/text/BoringLayout.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.util.FloatMath;
-
-/**
- * A BoringLayout is a very simple Layout implementation for text that
- * fits on a single line and is all left-to-right characters.
- * You will probably never want to make one of these yourself;
- * if you do, be sure to call {@link #isBoring} first to make sure
- * the text meets the criteria.
- * <p>This class is used by widgets to control text layout. You should not need
- * to use this class directly unless you are implementing your own widget
- * or custom display object, in which case
- * you are encouraged to use a Layout instead of calling
- * {@link android.graphics.Canvas#drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint)
- * Canvas.drawText()} directly.</p>
- */
-public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback {
- public static BoringLayout make(CharSequence source,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- BoringLayout.Metrics metrics, boolean includepad) {
- return new BoringLayout(source, paint, outerwidth, align,
- spacingmult, spacingadd, metrics,
- includepad);
- }
-
- public static BoringLayout make(CharSequence source,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- BoringLayout.Metrics metrics, boolean includepad,
- TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
- return new BoringLayout(source, paint, outerwidth, align,
- spacingmult, spacingadd, metrics,
- includepad, ellipsize, ellipsizedWidth);
- }
-
- /**
- * Returns a BoringLayout for the specified text, potentially reusing
- * this one if it is already suitable. The caller must make sure that
- * no one is still using this Layout.
- */
- public BoringLayout replaceOrMake(CharSequence source, TextPaint paint,
- int outerwidth, Alignment align,
- float spacingmult, float spacingadd,
- BoringLayout.Metrics metrics,
- boolean includepad) {
- replaceWith(source, paint, outerwidth, align, spacingmult,
- spacingadd);
-
- mEllipsizedWidth = outerwidth;
- mEllipsizedStart = 0;
- mEllipsizedCount = 0;
-
- init(source, paint, outerwidth, align, spacingmult, spacingadd,
- metrics, includepad, true);
- return this;
- }
-
- /**
- * Returns a BoringLayout for the specified text, potentially reusing
- * this one if it is already suitable. The caller must make sure that
- * no one is still using this Layout.
- */
- public BoringLayout replaceOrMake(CharSequence source, TextPaint paint,
- int outerwidth, Alignment align,
- float spacingmult, float spacingadd,
- BoringLayout.Metrics metrics,
- boolean includepad,
- TextUtils.TruncateAt ellipsize,
- int ellipsizedWidth) {
- boolean trust;
-
- if (ellipsize == null || ellipsize == TextUtils.TruncateAt.MARQUEE) {
- replaceWith(source, paint, outerwidth, align, spacingmult,
- spacingadd);
-
- mEllipsizedWidth = outerwidth;
- mEllipsizedStart = 0;
- mEllipsizedCount = 0;
- trust = true;
- } else {
- replaceWith(TextUtils.ellipsize(source, paint, ellipsizedWidth,
- ellipsize, true, this),
- paint, outerwidth, align, spacingmult,
- spacingadd);
-
- mEllipsizedWidth = ellipsizedWidth;
- trust = false;
- }
-
- init(getText(), paint, outerwidth, align, spacingmult, spacingadd,
- metrics, includepad, trust);
- return this;
- }
-
- public BoringLayout(CharSequence source,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- BoringLayout.Metrics metrics, boolean includepad) {
- super(source, paint, outerwidth, align, spacingmult, spacingadd);
-
- mEllipsizedWidth = outerwidth;
- mEllipsizedStart = 0;
- mEllipsizedCount = 0;
-
- init(source, paint, outerwidth, align, spacingmult, spacingadd,
- metrics, includepad, true);
- }
-
- public BoringLayout(CharSequence source,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- BoringLayout.Metrics metrics, boolean includepad,
- TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
- /*
- * It is silly to have to call super() and then replaceWith(),
- * but we can't use "this" for the callback until the call to
- * super() finishes.
- */
- super(source, paint, outerwidth, align, spacingmult, spacingadd);
-
- boolean trust;
-
- if (ellipsize == null || ellipsize == TextUtils.TruncateAt.MARQUEE) {
- mEllipsizedWidth = outerwidth;
- mEllipsizedStart = 0;
- mEllipsizedCount = 0;
- trust = true;
- } else {
- replaceWith(TextUtils.ellipsize(source, paint, ellipsizedWidth,
- ellipsize, true, this),
- paint, outerwidth, align, spacingmult,
- spacingadd);
-
-
- mEllipsizedWidth = ellipsizedWidth;
- trust = false;
- }
-
- init(getText(), paint, outerwidth, align, spacingmult, spacingadd,
- metrics, includepad, trust);
- }
-
- /* package */ void init(CharSequence source,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- BoringLayout.Metrics metrics, boolean includepad,
- boolean trustWidth) {
- int spacing;
-
- if (source instanceof String && align == Layout.Alignment.ALIGN_NORMAL) {
- mDirect = source.toString();
- } else {
- mDirect = null;
- }
-
- mPaint = paint;
-
- if (includepad) {
- spacing = metrics.bottom - metrics.top;
- } else {
- spacing = metrics.descent - metrics.ascent;
- }
-
- if (spacingmult != 1 || spacingadd != 0) {
- spacing = (int)(spacing * spacingmult + spacingadd + 0.5f);
- }
-
- mBottom = spacing;
-
- if (includepad) {
- mDesc = spacing + metrics.top;
- } else {
- mDesc = spacing + metrics.ascent;
- }
-
- if (trustWidth) {
- mMax = metrics.width;
- } else {
- /*
- * If we have ellipsized, we have to actually calculate the
- * width because the width that was passed in was for the
- * full text, not the ellipsized form.
- */
- synchronized (sTemp) {
- mMax = (int) (FloatMath.ceil(Styled.measureText(paint, sTemp,
- source, 0, source.length(),
- null)));
- }
- }
-
- if (includepad) {
- mTopPadding = metrics.top - metrics.ascent;
- mBottomPadding = metrics.bottom - metrics.descent;
- }
- }
-
- /**
- * Returns null if not boring; the width, ascent, and descent if boring.
- */
- public static Metrics isBoring(CharSequence text,
- TextPaint paint) {
- return isBoring(text, paint, null);
- }
-
- /**
- * Returns null if not boring; the width, ascent, and descent in the
- * provided Metrics object (or a new one if the provided one was null)
- * if boring.
- */
- public static Metrics isBoring(CharSequence text, TextPaint paint,
- Metrics metrics) {
- char[] temp = TextUtils.obtain(500);
- int len = text.length();
- boolean boring = true;
-
- outer:
- for (int i = 0; i < len; i += 500) {
- int j = i + 500;
-
- if (j > len)
- j = len;
-
- TextUtils.getChars(text, i, j, temp, 0);
-
- int n = j - i;
-
- for (int a = 0; a < n; a++) {
- char c = temp[a];
-
- if (c == '\n' || c == '\t' || c >= FIRST_RIGHT_TO_LEFT) {
- boring = false;
- break outer;
- }
- }
- }
-
- TextUtils.recycle(temp);
-
- if (boring) {
- Metrics fm = metrics;
- if (fm == null) {
- fm = new Metrics();
- }
-
- int wid;
-
- synchronized (sTemp) {
- wid = (int) (FloatMath.ceil(Styled.measureText(paint, sTemp,
- text, 0, text.length(), fm)));
- }
- fm.width = wid;
- return fm;
- } else {
- return null;
- }
- }
-
- @Override public int getHeight() {
- return mBottom;
- }
-
- @Override public int getLineCount() {
- return 1;
- }
-
- @Override public int getLineTop(int line) {
- if (line == 0)
- return 0;
- else
- return mBottom;
- }
-
- @Override public int getLineDescent(int line) {
- return mDesc;
- }
-
- @Override public int getLineStart(int line) {
- if (line == 0)
- return 0;
- else
- return getText().length();
- }
-
- @Override public int getParagraphDirection(int line) {
- return DIR_LEFT_TO_RIGHT;
- }
-
- @Override public boolean getLineContainsTab(int line) {
- return false;
- }
-
- @Override public float getLineMax(int line) {
- return mMax;
- }
-
- @Override public final Directions getLineDirections(int line) {
- return Layout.DIRS_ALL_LEFT_TO_RIGHT;
- }
-
- public int getTopPadding() {
- return mTopPadding;
- }
-
- public int getBottomPadding() {
- return mBottomPadding;
- }
-
- @Override
- public int getEllipsisCount(int line) {
- return mEllipsizedCount;
- }
-
- @Override
- public int getEllipsisStart(int line) {
- return mEllipsizedStart;
- }
-
- @Override
- public int getEllipsizedWidth() {
- return mEllipsizedWidth;
- }
-
- // Override draw so it will be faster.
- @Override
- public void draw(Canvas c, Path highlight, Paint highlightpaint,
- int cursorOffset) {
- if (mDirect != null && highlight == null) {
- c.drawText(mDirect, 0, mBottom - mDesc, mPaint);
- } else {
- super.draw(c, highlight, highlightpaint, cursorOffset);
- }
- }
-
- /**
- * Callback for the ellipsizer to report what region it ellipsized.
- */
- public void ellipsized(int start, int end) {
- mEllipsizedStart = start;
- mEllipsizedCount = end - start;
- }
-
- private static final char FIRST_RIGHT_TO_LEFT = '\u0590';
-
- private String mDirect;
- private Paint mPaint;
-
- /* package */ int mBottom, mDesc; // for Direct
- private int mTopPadding, mBottomPadding;
- private float mMax;
- private int mEllipsizedWidth, mEllipsizedStart, mEllipsizedCount;
-
- private static final TextPaint sTemp =
- new TextPaint();
-
- public static class Metrics extends Paint.FontMetricsInt {
- public int width;
-
- @Override public String toString() {
- return super.toString() + " width=" + width;
- }
- }
-}
diff --git a/core/java/android/text/ClipboardManager.java b/core/java/android/text/ClipboardManager.java
deleted file mode 100644
index 52039af..0000000
--- a/core/java/android/text/ClipboardManager.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.text;
-
-import android.content.Context;
-import android.os.RemoteException;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.ServiceManager;
-import android.util.Log;
-
-/**
- * Interface to the clipboard service, for placing and retrieving text in
- * the global clipboard.
- *
- * <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
- *
- * @see android.content.Context#getSystemService
- */
-public class ClipboardManager {
- private static IClipboard sService;
-
- private Context mContext;
-
- static private IClipboard getService() {
- if (sService != null) {
- return sService;
- }
- IBinder b = ServiceManager.getService("clipboard");
- sService = IClipboard.Stub.asInterface(b);
- return sService;
- }
-
- /** {@hide} */
- public ClipboardManager(Context context, Handler handler) {
- mContext = context;
- }
-
- /**
- * Returns the text on the clipboard. It will eventually be possible
- * to store types other than text too, in which case this will return
- * null if the type cannot be coerced to text.
- */
- public CharSequence getText() {
- try {
- return getService().getClipboardText();
- } catch (RemoteException e) {
- return null;
- }
- }
-
- /**
- * Sets the contents of the clipboard to the specified text.
- */
- public void setText(CharSequence text) {
- try {
- getService().setClipboardText(text);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Returns true if the clipboard contains text; false otherwise.
- */
- public boolean hasText() {
- try {
- return getService().hasClipboardText();
- } catch (RemoteException e) {
- return false;
- }
- }
-}
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
deleted file mode 100644
index 14e5655..0000000
--- a/core/java/android/text/DynamicLayout.java
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-import android.graphics.Paint;
-import android.text.style.UpdateLayout;
-import android.text.style.WrapTogetherSpan;
-
-import java.lang.ref.WeakReference;
-
-/**
- * DynamicLayout is a text layout that updates itself as the text is edited.
- * <p>This is used by widgets to control text layout. You should not need
- * to use this class directly unless you are implementing your own widget
- * or custom display object, or need to call
- * {@link android.graphics.Canvas#drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint)
- * Canvas.drawText()} directly.</p>
- */
-public class DynamicLayout
-extends Layout
-{
- private static final int PRIORITY = 128;
-
- /**
- * Make a layout for the specified text that will be updated as
- * the text is changed.
- */
- public DynamicLayout(CharSequence base,
- TextPaint paint,
- int width, Alignment align,
- float spacingmult, float spacingadd,
- boolean includepad) {
- this(base, base, paint, width, align, spacingmult, spacingadd,
- includepad);
- }
-
- /**
- * Make a layout for the transformed text (password transformation
- * being the primary example of a transformation)
- * that will be updated as the base text is changed.
- */
- public DynamicLayout(CharSequence base, CharSequence display,
- TextPaint paint,
- int width, Alignment align,
- float spacingmult, float spacingadd,
- boolean includepad) {
- this(base, display, paint, width, align, spacingmult, spacingadd,
- includepad, null, 0);
- }
-
- /**
- * Make a layout for the transformed text (password transformation
- * being the primary example of a transformation)
- * that will be updated as the base text is changed.
- * If ellipsize is non-null, the Layout will ellipsize the text
- * down to ellipsizedWidth.
- */
- public DynamicLayout(CharSequence base, CharSequence display,
- TextPaint paint,
- int width, Alignment align,
- float spacingmult, float spacingadd,
- boolean includepad,
- TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
- super((ellipsize == null)
- ? display
- : (display instanceof Spanned)
- ? new SpannedEllipsizer(display)
- : new Ellipsizer(display),
- paint, width, align, spacingmult, spacingadd);
-
- mBase = base;
- mDisplay = display;
-
- if (ellipsize != null) {
- mInts = new PackedIntVector(COLUMNS_ELLIPSIZE);
- mEllipsizedWidth = ellipsizedWidth;
- mEllipsizeAt = ellipsize;
- } else {
- mInts = new PackedIntVector(COLUMNS_NORMAL);
- mEllipsizedWidth = width;
- mEllipsizeAt = ellipsize;
- }
-
- mObjects = new PackedObjectVector<Directions>(1);
-
- mIncludePad = includepad;
-
- /*
- * This is annoying, but we can't refer to the layout until
- * superclass construction is finished, and the superclass
- * constructor wants the reference to the display text.
- *
- * This will break if the superclass constructor ever actually
- * cares about the content instead of just holding the reference.
- */
- if (ellipsize != null) {
- Ellipsizer e = (Ellipsizer) getText();
-
- e.mLayout = this;
- e.mWidth = ellipsizedWidth;
- e.mMethod = ellipsize;
- mEllipsize = true;
- }
-
- // Initial state is a single line with 0 characters (0 to 0),
- // with top at 0 and bottom at whatever is natural, and
- // undefined ellipsis.
-
- int[] start;
-
- if (ellipsize != null) {
- start = new int[COLUMNS_ELLIPSIZE];
- start[ELLIPSIS_START] = ELLIPSIS_UNDEFINED;
- } else {
- start = new int[COLUMNS_NORMAL];
- }
-
- Directions[] dirs = new Directions[] { DIRS_ALL_LEFT_TO_RIGHT };
-
- Paint.FontMetricsInt fm = paint.getFontMetricsInt();
- int asc = fm.ascent;
- int desc = fm.descent;
-
- start[DIR] = DIR_LEFT_TO_RIGHT << DIR_SHIFT;
- start[TOP] = 0;
- start[DESCENT] = desc;
- mInts.insertAt(0, start);
-
- start[TOP] = desc - asc;
- mInts.insertAt(1, start);
-
- mObjects.insertAt(0, dirs);
-
- // Update from 0 characters to whatever the real text is
-
- reflow(base, 0, 0, base.length());
-
- if (base instanceof Spannable) {
- if (mWatcher == null)
- mWatcher = new ChangeWatcher(this);
-
- // Strip out any watchers for other DynamicLayouts.
- Spannable sp = (Spannable) base;
- ChangeWatcher[] spans = sp.getSpans(0, sp.length(), ChangeWatcher.class);
- for (int i = 0; i < spans.length; i++)
- sp.removeSpan(spans[i]);
-
- sp.setSpan(mWatcher, 0, base.length(),
- Spannable.SPAN_INCLUSIVE_INCLUSIVE |
- (PRIORITY << Spannable.SPAN_PRIORITY_SHIFT));
- }
- }
-
- private void reflow(CharSequence s, int where, int before, int after) {
- if (s != mBase)
- return;
-
- CharSequence text = mDisplay;
- int len = text.length();
-
- // seek back to the start of the paragraph
-
- int find = TextUtils.lastIndexOf(text, '\n', where - 1);
- if (find < 0)
- find = 0;
- else
- find = find + 1;
-
- {
- int diff = where - find;
- before += diff;
- after += diff;
- where -= diff;
- }
-
- // seek forward to the end of the paragraph
-
- int look = TextUtils.indexOf(text, '\n', where + after);
- if (look < 0)
- look = len;
- else
- look++; // we want the index after the \n
-
- int change = look - (where + after);
- before += change;
- after += change;
-
- // seek further out to cover anything that is forced to wrap together
-
- if (text instanceof Spanned) {
- Spanned sp = (Spanned) text;
- boolean again;
-
- do {
- again = false;
-
- Object[] force = sp.getSpans(where, where + after,
- WrapTogetherSpan.class);
-
- for (int i = 0; i < force.length; i++) {
- int st = sp.getSpanStart(force[i]);
- int en = sp.getSpanEnd(force[i]);
-
- if (st < where) {
- again = true;
-
- int diff = where - st;
- before += diff;
- after += diff;
- where -= diff;
- }
-
- if (en > where + after) {
- again = true;
-
- int diff = en - (where + after);
- before += diff;
- after += diff;
- }
- }
- } while (again);
- }
-
- // find affected region of old layout
-
- int startline = getLineForOffset(where);
- int startv = getLineTop(startline);
-
- int endline = getLineForOffset(where + before);
- if (where + after == len)
- endline = getLineCount();
- int endv = getLineTop(endline);
- boolean islast = (endline == getLineCount());
-
- // generate new layout for affected text
-
- StaticLayout reflowed;
-
- synchronized (sLock) {
- reflowed = sStaticLayout;
- sStaticLayout = null;
- }
-
- if (reflowed == null)
- reflowed = new StaticLayout(true);
-
- reflowed.generate(text, where, where + after,
- getPaint(), getWidth(), getAlignment(),
- getSpacingMultiplier(), getSpacingAdd(),
- false, true, mEllipsize,
- mEllipsizedWidth, mEllipsizeAt);
- int n = reflowed.getLineCount();
-
- // If the new layout has a blank line at the end, but it is not
- // the very end of the buffer, then we already have a line that
- // starts there, so disregard the blank line.
-
- if (where + after != len &&
- reflowed.getLineStart(n - 1) == where + after)
- n--;
-
- // remove affected lines from old layout
-
- mInts.deleteAt(startline, endline - startline);
- mObjects.deleteAt(startline, endline - startline);
-
- // adjust offsets in layout for new height and offsets
-
- int ht = reflowed.getLineTop(n);
- int toppad = 0, botpad = 0;
-
- if (mIncludePad && startline == 0) {
- toppad = reflowed.getTopPadding();
- mTopPadding = toppad;
- ht -= toppad;
- }
- if (mIncludePad && islast) {
- botpad = reflowed.getBottomPadding();
- mBottomPadding = botpad;
- ht += botpad;
- }
-
- mInts.adjustValuesBelow(startline, START, after - before);
- mInts.adjustValuesBelow(startline, TOP, startv - endv + ht);
-
- // insert new layout
-
- int[] ints;
-
- if (mEllipsize) {
- ints = new int[COLUMNS_ELLIPSIZE];
- ints[ELLIPSIS_START] = ELLIPSIS_UNDEFINED;
- } else {
- ints = new int[COLUMNS_NORMAL];
- }
-
- Directions[] objects = new Directions[1];
-
-
- for (int i = 0; i < n; i++) {
- ints[START] = reflowed.getLineStart(i) |
- (reflowed.getParagraphDirection(i) << DIR_SHIFT) |
- (reflowed.getLineContainsTab(i) ? TAB_MASK : 0);
-
- int top = reflowed.getLineTop(i) + startv;
- if (i > 0)
- top -= toppad;
- ints[TOP] = top;
-
- int desc = reflowed.getLineDescent(i);
- if (i == n - 1)
- desc += botpad;
-
- ints[DESCENT] = desc;
- objects[0] = reflowed.getLineDirections(i);
-
- if (mEllipsize) {
- ints[ELLIPSIS_START] = reflowed.getEllipsisStart(i);
- ints[ELLIPSIS_COUNT] = reflowed.getEllipsisCount(i);
- }
-
- mInts.insertAt(startline + i, ints);
- mObjects.insertAt(startline + i, objects);
- }
-
- synchronized (sLock) {
- sStaticLayout = reflowed;
- }
- }
-
- private void dump(boolean show) {
- int n = getLineCount();
-
- for (int i = 0; i < n; i++) {
- System.out.print("line " + i + ": " + getLineStart(i) + " to " + getLineEnd(i) + " ");
-
- if (show) {
- System.out.print(getText().subSequence(getLineStart(i),
- getLineEnd(i)));
- }
-
- System.out.println("");
- }
-
- System.out.println("");
- }
-
- public int getLineCount() {
- return mInts.size() - 1;
- }
-
- public int getLineTop(int line) {
- return mInts.getValue(line, TOP);
- }
-
- public int getLineDescent(int line) {
- return mInts.getValue(line, DESCENT);
- }
-
- public int getLineStart(int line) {
- return mInts.getValue(line, START) & START_MASK;
- }
-
- public boolean getLineContainsTab(int line) {
- return (mInts.getValue(line, TAB) & TAB_MASK) != 0;
- }
-
- public int getParagraphDirection(int line) {
- return mInts.getValue(line, DIR) >> DIR_SHIFT;
- }
-
- public final Directions getLineDirections(int line) {
- return mObjects.getValue(line, 0);
- }
-
- public int getTopPadding() {
- return mTopPadding;
- }
-
- public int getBottomPadding() {
- return mBottomPadding;
- }
-
- @Override
- public int getEllipsizedWidth() {
- return mEllipsizedWidth;
- }
-
- private static class ChangeWatcher
- implements TextWatcher, SpanWatcher
- {
- public ChangeWatcher(DynamicLayout layout) {
- mLayout = new WeakReference(layout);
- }
-
- private void reflow(CharSequence s, int where, int before, int after) {
- DynamicLayout ml = (DynamicLayout) mLayout.get();
-
- if (ml != null)
- ml.reflow(s, where, before, after);
- else if (s instanceof Spannable)
- ((Spannable) s).removeSpan(this);
- }
-
- public void beforeTextChanged(CharSequence s,
- int where, int before, int after) {
- ;
- }
-
- public void onTextChanged(CharSequence s,
- int where, int before, int after) {
- reflow(s, where, before, after);
- }
-
- public void afterTextChanged(Editable s) {
- ;
- }
-
- public void onSpanAdded(Spannable s, Object o, int start, int end) {
- if (o instanceof UpdateLayout)
- reflow(s, start, end - start, end - start);
- }
-
- public void onSpanRemoved(Spannable s, Object o, int start, int end) {
- if (o instanceof UpdateLayout)
- reflow(s, start, end - start, end - start);
- }
-
- public void onSpanChanged(Spannable s, Object o, int start, int end,
- int nstart, int nend) {
- if (o instanceof UpdateLayout) {
- reflow(s, start, end - start, end - start);
- reflow(s, nstart, nend - nstart, nend - nstart);
- }
- }
-
- private WeakReference mLayout;
- }
-
- public int getEllipsisStart(int line) {
- if (mEllipsizeAt == null) {
- return 0;
- }
-
- return mInts.getValue(line, ELLIPSIS_START);
- }
-
- public int getEllipsisCount(int line) {
- if (mEllipsizeAt == null) {
- return 0;
- }
-
- return mInts.getValue(line, ELLIPSIS_COUNT);
- }
-
- private CharSequence mBase;
- private CharSequence mDisplay;
- private ChangeWatcher mWatcher;
- private boolean mIncludePad;
- private boolean mEllipsize;
- private int mEllipsizedWidth;
- private TextUtils.TruncateAt mEllipsizeAt;
-
- private PackedIntVector mInts;
- private PackedObjectVector<Directions> mObjects;
-
- private int mTopPadding, mBottomPadding;
-
- private static StaticLayout sStaticLayout = new StaticLayout(true);
- private static Object sLock = new Object();
-
- private static final int START = 0;
- private static final int DIR = START;
- private static final int TAB = START;
- private static final int TOP = 1;
- private static final int DESCENT = 2;
- private static final int COLUMNS_NORMAL = 3;
-
- private static final int ELLIPSIS_START = 3;
- private static final int ELLIPSIS_COUNT = 4;
- private static final int COLUMNS_ELLIPSIZE = 5;
-
- private static final int START_MASK = 0x1FFFFFFF;
- private static final int DIR_MASK = 0xC0000000;
- private static final int DIR_SHIFT = 30;
- private static final int TAB_MASK = 0x20000000;
-
- private static final int ELLIPSIS_UNDEFINED = 0x80000000;
-}
diff --git a/core/java/android/text/Editable.java b/core/java/android/text/Editable.java
deleted file mode 100644
index a284a00..0000000
--- a/core/java/android/text/Editable.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-/**
- * This is the interface for text whose content and markup
- * can be changed (as opposed
- * to immutable text like Strings). If you make a {@link DynamicLayout}
- * of an Editable, the layout will be reflowed as the text is changed.
- */
-public interface Editable
-extends CharSequence, GetChars, Spannable, Appendable
-{
- /**
- * Replaces the specified range (<code>st&hellip;en</code>) of text in this
- * Editable with a copy of the slice <code>start&hellip;end</code> from
- * <code>source</code>. The destination slice may be empty, in which case
- * the operation is an insertion, or the source slice may be empty,
- * in which case the operation is a deletion.
- * <p>
- * Before the change is committed, each filter that was set with
- * {@link #setFilters} is given the opportunity to modify the
- * <code>source</code> text.
- * <p>
- * If <code>source</code>
- * is Spanned, the spans from it are preserved into the Editable.
- * Existing spans within the Editable that entirely cover the replaced
- * range are retained, but any that were strictly within the range
- * that was replaced are removed. As a special case, the cursor
- * position is preserved even when the entire range where it is
- * located is replaced.
- * @return a reference to this object.
- */
- public Editable replace(int st, int en, CharSequence source, int start, int end);
-
- /**
- * Convenience for replace(st, en, text, 0, text.length())
- * @see #replace(int, int, CharSequence, int, int)
- */
- public Editable replace(int st, int en, CharSequence text);
-
- /**
- * Convenience for replace(where, where, text, start, end)
- * @see #replace(int, int, CharSequence, int, int)
- */
- public Editable insert(int where, CharSequence text, int start, int end);
-
- /**
- * Convenience for replace(where, where, text, 0, text.length());
- * @see #replace(int, int, CharSequence, int, int)
- */
- public Editable insert(int where, CharSequence text);
-
- /**
- * Convenience for replace(st, en, "", 0, 0)
- * @see #replace(int, int, CharSequence, int, int)
- */
- public Editable delete(int st, int en);
-
- /**
- * Convenience for replace(length(), length(), text, 0, text.length())
- * @see #replace(int, int, CharSequence, int, int)
- */
- public Editable append(CharSequence text);
-
- /**
- * Convenience for replace(length(), length(), text, start, end)
- * @see #replace(int, int, CharSequence, int, int)
- */
- public Editable append(CharSequence text, int start, int end);
-
- /**
- * Convenience for append(String.valueOf(text)).
- * @see #replace(int, int, CharSequence, int, int)
- */
- public Editable append(char text);
-
- /**
- * Convenience for replace(0, length(), "", 0, 0)
- * @see #replace(int, int, CharSequence, int, int)
- * Note that this clears the text, not the spans;
- * use {@link #clearSpans} if you need that.
- */
- public void clear();
-
- /**
- * Removes all spans from the Editable, as if by calling
- * {@link #removeSpan} on each of them.
- */
- public void clearSpans();
-
- /**
- * Sets the series of filters that will be called in succession
- * whenever the text of this Editable is changed, each of which has
- * the opportunity to limit or transform the text that is being inserted.
- */
- public void setFilters(InputFilter[] filters);
-
- /**
- * Returns the array of input filters that are currently applied
- * to changes to this Editable.
- */
- public InputFilter[] getFilters();
-
- /**
- * Factory used by TextView to create new Editables. You can subclass
- * it to provide something other than SpannableStringBuilder.
- */
- public static class Factory {
- private static Editable.Factory sInstance = new Editable.Factory();
-
- /**
- * Returns the standard Editable Factory.
- */
- public static Editable.Factory getInstance() {
- return sInstance;
- }
-
- /**
- * Returns a new SpannedStringBuilder from the specified
- * CharSequence. You can override this to provide
- * a different kind of Spanned.
- */
- public Editable newEditable(CharSequence source) {
- return new SpannableStringBuilder(source);
- }
- }
-}
diff --git a/core/java/android/text/GetChars.java b/core/java/android/text/GetChars.java
deleted file mode 100644
index 348a911..0000000
--- a/core/java/android/text/GetChars.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-/**
- * Please implement this interface if your CharSequence has a
- * getChars() method like the one in String that is faster than
- * calling charAt() multiple times.
- */
-public interface GetChars
-extends CharSequence
-{
- /**
- * Exactly like String.getChars(): copy chars <code>start</code>
- * through <code>end - 1</code> from this CharSequence into <code>dest</code>
- * beginning at offset <code>destoff</code>.
- */
- public void getChars(int start, int end, char[] dest, int destoff);
-}
diff --git a/core/java/android/text/GraphicsOperations.java b/core/java/android/text/GraphicsOperations.java
deleted file mode 100644
index c3bd0ae..0000000
--- a/core/java/android/text/GraphicsOperations.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.text;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-
-/**
- * Please implement this interface if your CharSequence can do quick
- * draw/measure/widths calculations from an internal array.
- * {@hide}
- */
-public interface GraphicsOperations
-extends CharSequence
-{
- /**
- * Just like {@link Canvas#drawText}.
- */
- void drawText(Canvas c, int start, int end,
- float x, float y, Paint p);
-
- /**
- * Just like {@link Paint#measureText}.
- */
- float measureText(int start, int end, Paint p);
-
-
- /**
- * Just like {@link Paint#getTextWidths}.
- */
- public int getTextWidths(int start, int end, float[] widths, Paint p);
-}
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
deleted file mode 100644
index 8495714..0000000
--- a/core/java/android/text/Html.java
+++ /dev/null
@@ -1,784 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.text;
-
-import org.ccil.cowan.tagsoup.HTMLSchema;
-import org.ccil.cowan.tagsoup.Parser;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-
-import android.content.res.Resources;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.text.style.CharacterStyle;
-import android.text.style.ForegroundColorSpan;
-import android.text.style.ImageSpan;
-import android.text.style.ParagraphStyle;
-import android.text.style.QuoteSpan;
-import android.text.style.RelativeSizeSpan;
-import android.text.style.StrikethroughSpan;
-import android.text.style.StyleSpan;
-import android.text.style.SubscriptSpan;
-import android.text.style.SuperscriptSpan;
-import android.text.style.TypefaceSpan;
-import android.text.style.URLSpan;
-import android.text.style.UnderlineSpan;
-import com.android.internal.util.XmlUtils;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.nio.CharBuffer;
-
-/**
- * This class processes HTML strings into displayable styled text.
- * Not all HTML tags are supported.
- */
-public class Html {
- /**
- * Retrieves images for HTML &lt;img&gt; tags.
- */
- public static interface ImageGetter {
- /**
- * This methos is called when the HTML parser encounters an
- * &lt;img&gt; tag. The <code>source</code> argument is the
- * string from the "src" attribute; the return value should be
- * a Drawable representation of the image or <code>null</code>
- * for a generic replacement image. Make sure you call
- * setBounds() on your Drawable if it doesn't already have
- * its bounds set.
- */
- public Drawable getDrawable(String source);
- }
-
- /**
- * Is notified when HTML tags are encountered that the parser does
- * not know how to interpret.
- */
- public static interface TagHandler {
- /**
- * This method will be called whenn the HTML parser encounters
- * a tag that it does not know how to interpret.
- */
- public void handleTag(boolean opening, String tag,
- Editable output, XMLReader xmlReader);
- }
-
- private Html() { }
-
- /**
- * Returns displayable styled text from the provided HTML string.
- * Any &lt;img&gt; tags in the HTML will display as a generic
- * replacement image which your program can then go through and
- * replace with real images.
- *
- * <p>This uses TagSoup to handle real HTML, including all of the brokenness found in the wild.
- */
- public static Spanned fromHtml(String source) {
- return fromHtml(source, null, null);
- }
-
- /**
- * Lazy initialization holder for HTML parser. This class will
- * a) be preloaded by the zygote, or b) not loaded until absolutely
- * necessary.
- */
- private static class HtmlParser {
- private static final HTMLSchema schema = new HTMLSchema();
- }
-
- /**
- * Returns displayable styled text from the provided HTML string.
- * Any &lt;img&gt; tags in the HTML will use the specified ImageGetter
- * to request a representation of the image (use null if you don't
- * want this) and the specified TagHandler to handle unknown tags
- * (specify null if you don't want this).
- *
- * <p>This uses TagSoup to handle real HTML, including all of the brokenness found in the wild.
- */
- public static Spanned fromHtml(String source, ImageGetter imageGetter,
- TagHandler tagHandler) {
- Parser parser = new Parser();
- try {
- parser.setProperty(Parser.schemaProperty, HtmlParser.schema);
- } catch (org.xml.sax.SAXNotRecognizedException e) {
- // Should not happen.
- throw new RuntimeException(e);
- } catch (org.xml.sax.SAXNotSupportedException e) {
- // Should not happen.
- throw new RuntimeException(e);
- }
-
- HtmlToSpannedConverter converter =
- new HtmlToSpannedConverter(source, imageGetter, tagHandler,
- parser);
- return converter.convert();
- }
-
- /**
- * Returns an HTML representation of the provided Spanned text.
- */
- public static String toHtml(Spanned text) {
- StringBuilder out = new StringBuilder();
- int len = text.length();
-
- int next;
- for (int i = 0; i < text.length(); i = next) {
- next = text.nextSpanTransition(i, len, QuoteSpan.class);
- QuoteSpan[] quotes = text.getSpans(i, next, QuoteSpan.class);
-
- for (QuoteSpan quote: quotes) {
- out.append("<blockquote>");
- }
-
- withinBlockquote(out, text, i, next);
-
- for (QuoteSpan quote: quotes) {
- out.append("</blockquote>\n");
- }
- }
-
- return out.toString();
- }
-
- private static void withinBlockquote(StringBuilder out, Spanned text,
- int start, int end) {
- out.append("<p>");
-
- int next;
- for (int i = start; i < end; i = next) {
- next = TextUtils.indexOf(text, '\n', i, end);
- if (next < 0) {
- next = end;
- }
-
- int nl = 0;
-
- while (next < end && text.charAt(next) == '\n') {
- nl++;
- next++;
- }
-
- withinParagraph(out, text, i, next - nl, nl, next == end);
- }
-
- out.append("</p>\n");
- }
-
- private static void withinParagraph(StringBuilder out, Spanned text,
- int start, int end, int nl,
- boolean last) {
- int next;
- for (int i = start; i < end; i = next) {
- next = text.nextSpanTransition(i, end, CharacterStyle.class);
- CharacterStyle[] style = text.getSpans(i, next,
- CharacterStyle.class);
-
- for (int j = 0; j < style.length; j++) {
- if (style[j] instanceof StyleSpan) {
- int s = ((StyleSpan) style[j]).getStyle();
-
- if ((s & Typeface.BOLD) != 0) {
- out.append("<b>");
- }
- if ((s & Typeface.ITALIC) != 0) {
- out.append("<i>");
- }
- }
- if (style[j] instanceof TypefaceSpan) {
- String s = ((TypefaceSpan) style[j]).getFamily();
-
- if (s.equals("monospace")) {
- out.append("<tt>");
- }
- }
- if (style[j] instanceof SuperscriptSpan) {
- out.append("<sup>");
- }
- if (style[j] instanceof SubscriptSpan) {
- out.append("<sub>");
- }
- if (style[j] instanceof UnderlineSpan) {
- out.append("<u>");
- }
- if (style[j] instanceof StrikethroughSpan) {
- out.append("<strike>");
- }
- if (style[j] instanceof URLSpan) {
- out.append("<a href=\"");
- out.append(((URLSpan) style[j]).getURL());
- out.append("\">");
- }
- if (style[j] instanceof ImageSpan) {
- out.append("<img src=\"");
- out.append(((ImageSpan) style[j]).getSource());
- out.append("\">");
-
- // Don't output the dummy character underlying the image.
- i = next;
- }
- }
-
- withinStyle(out, text, i, next);
-
- for (int j = style.length - 1; j >= 0; j--) {
- if (style[j] instanceof URLSpan) {
- out.append("</a>");
- }
- if (style[j] instanceof StrikethroughSpan) {
- out.append("</strike>");
- }
- if (style[j] instanceof UnderlineSpan) {
- out.append("</u>");
- }
- if (style[j] instanceof SubscriptSpan) {
- out.append("</sub>");
- }
- if (style[j] instanceof SuperscriptSpan) {
- out.append("</sup>");
- }
- if (style[j] instanceof TypefaceSpan) {
- String s = ((TypefaceSpan) style[j]).getFamily();
-
- if (s.equals("monospace")) {
- out.append("</tt>");
- }
- }
- if (style[j] instanceof StyleSpan) {
- int s = ((StyleSpan) style[j]).getStyle();
-
- if ((s & Typeface.BOLD) != 0) {
- out.append("</b>");
- }
- if ((s & Typeface.ITALIC) != 0) {
- out.append("</i>");
- }
- }
- }
- }
-
- String p = last ? "" : "</p>\n<p>";
-
- if (nl == 1) {
- out.append("<br>\n");
- } else if (nl == 2) {
- out.append(p);
- } else {
- for (int i = 2; i < nl; i++) {
- out.append("<br>");
- }
-
- out.append(p);
- }
- }
-
- private static void withinStyle(StringBuilder out, Spanned text,
- int start, int end) {
- for (int i = start; i < end; i++) {
- char c = text.charAt(i);
-
- if (c == '<') {
- out.append("&lt;");
- } else if (c == '>') {
- out.append("&gt;");
- } else if (c == '&') {
- out.append("&amp;");
- } else if (c > 0x7E || c < ' ') {
- out.append("&#" + ((int) c) + ";");
- } else if (c == ' ') {
- while (i + 1 < end && text.charAt(i + 1) == ' ') {
- out.append("&nbsp;");
- i++;
- }
-
- out.append(' ');
- } else {
- out.append(c);
- }
- }
- }
-}
-
-class HtmlToSpannedConverter implements ContentHandler {
-
- private static final float[] HEADER_SIZES = {
- 1.5f, 1.4f, 1.3f, 1.2f, 1.1f, 1f,
- };
-
- private String mSource;
- private XMLReader mReader;
- private SpannableStringBuilder mSpannableStringBuilder;
- private Html.ImageGetter mImageGetter;
- private Html.TagHandler mTagHandler;
-
- public HtmlToSpannedConverter(
- String source, Html.ImageGetter imageGetter, Html.TagHandler tagHandler,
- Parser parser) {
- mSource = source;
- mSpannableStringBuilder = new SpannableStringBuilder();
- mImageGetter = imageGetter;
- mTagHandler = tagHandler;
- mReader = parser;
- }
-
- public Spanned convert() {
-
- mReader.setContentHandler(this);
- try {
- mReader.parse(new InputSource(new StringReader(mSource)));
- } catch (IOException e) {
- // We are reading from a string. There should not be IO problems.
- throw new RuntimeException(e);
- } catch (SAXException e) {
- // TagSoup doesn't throw parse exceptions.
- throw new RuntimeException(e);
- }
-
- // Fix flags and range for paragraph-type markup.
- Object[] obj = mSpannableStringBuilder.getSpans(0, mSpannableStringBuilder.length(), ParagraphStyle.class);
- for (int i = 0; i < obj.length; i++) {
- int start = mSpannableStringBuilder.getSpanStart(obj[i]);
- int end = mSpannableStringBuilder.getSpanEnd(obj[i]);
-
- // If the last line of the range is blank, back off by one.
- if (end - 2 >= 0) {
- if (mSpannableStringBuilder.charAt(end - 1) == '\n' &&
- mSpannableStringBuilder.charAt(end - 2) == '\n') {
- end--;
- }
- }
-
- if (end == start) {
- mSpannableStringBuilder.removeSpan(obj[i]);
- } else {
- mSpannableStringBuilder.setSpan(obj[i], start, end, Spannable.SPAN_PARAGRAPH);
- }
- }
-
- return mSpannableStringBuilder;
- }
-
- private void handleStartTag(String tag, Attributes attributes) {
- if (tag.equalsIgnoreCase("br")) {
- // We don't need to handle this. TagSoup will ensure that there's a </br> for each <br>
- // so we can safely emite the linebreaks when we handle the close tag.
- } else if (tag.equalsIgnoreCase("p")) {
- handleP(mSpannableStringBuilder);
- } else if (tag.equalsIgnoreCase("div")) {
- handleP(mSpannableStringBuilder);
- } else if (tag.equalsIgnoreCase("em")) {
- start(mSpannableStringBuilder, new Bold());
- } else if (tag.equalsIgnoreCase("b")) {
- start(mSpannableStringBuilder, new Bold());
- } else if (tag.equalsIgnoreCase("strong")) {
- start(mSpannableStringBuilder, new Italic());
- } else if (tag.equalsIgnoreCase("cite")) {
- start(mSpannableStringBuilder, new Italic());
- } else if (tag.equalsIgnoreCase("dfn")) {
- start(mSpannableStringBuilder, new Italic());
- } else if (tag.equalsIgnoreCase("i")) {
- start(mSpannableStringBuilder, new Italic());
- } else if (tag.equalsIgnoreCase("big")) {
- start(mSpannableStringBuilder, new Big());
- } else if (tag.equalsIgnoreCase("small")) {
- start(mSpannableStringBuilder, new Small());
- } else if (tag.equalsIgnoreCase("font")) {
- startFont(mSpannableStringBuilder, attributes);
- } else if (tag.equalsIgnoreCase("blockquote")) {
- handleP(mSpannableStringBuilder);
- start(mSpannableStringBuilder, new Blockquote());
- } else if (tag.equalsIgnoreCase("tt")) {
- start(mSpannableStringBuilder, new Monospace());
- } else if (tag.equalsIgnoreCase("a")) {
- startA(mSpannableStringBuilder, attributes);
- } else if (tag.equalsIgnoreCase("u")) {
- start(mSpannableStringBuilder, new Underline());
- } else if (tag.equalsIgnoreCase("sup")) {
- start(mSpannableStringBuilder, new Super());
- } else if (tag.equalsIgnoreCase("sub")) {
- start(mSpannableStringBuilder, new Sub());
- } else if (tag.length() == 2 &&
- Character.toLowerCase(tag.charAt(0)) == 'h' &&
- tag.charAt(1) >= '1' && tag.charAt(1) <= '6') {
- handleP(mSpannableStringBuilder);
- start(mSpannableStringBuilder, new Header(tag.charAt(1) - '1'));
- } else if (tag.equalsIgnoreCase("img")) {
- startImg(mSpannableStringBuilder, attributes, mImageGetter);
- } else if (mTagHandler != null) {
- mTagHandler.handleTag(true, tag, mSpannableStringBuilder, mReader);
- }
- }
-
- private void handleEndTag(String tag) {
- if (tag.equalsIgnoreCase("br")) {
- handleBr(mSpannableStringBuilder);
- } else if (tag.equalsIgnoreCase("p")) {
- handleP(mSpannableStringBuilder);
- } else if (tag.equalsIgnoreCase("div")) {
- handleP(mSpannableStringBuilder);
- } else if (tag.equalsIgnoreCase("em")) {
- end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD));
- } else if (tag.equalsIgnoreCase("b")) {
- end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD));
- } else if (tag.equalsIgnoreCase("strong")) {
- end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC));
- } else if (tag.equalsIgnoreCase("cite")) {
- end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC));
- } else if (tag.equalsIgnoreCase("dfn")) {
- end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC));
- } else if (tag.equalsIgnoreCase("i")) {
- end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC));
- } else if (tag.equalsIgnoreCase("big")) {
- end(mSpannableStringBuilder, Big.class, new RelativeSizeSpan(1.25f));
- } else if (tag.equalsIgnoreCase("small")) {
- end(mSpannableStringBuilder, Small.class, new RelativeSizeSpan(0.8f));
- } else if (tag.equalsIgnoreCase("font")) {
- endFont(mSpannableStringBuilder);
- } else if (tag.equalsIgnoreCase("blockquote")) {
- handleP(mSpannableStringBuilder);
- end(mSpannableStringBuilder, Blockquote.class, new QuoteSpan());
- } else if (tag.equalsIgnoreCase("tt")) {
- end(mSpannableStringBuilder, Monospace.class,
- new TypefaceSpan("monospace"));
- } else if (tag.equalsIgnoreCase("a")) {
- endA(mSpannableStringBuilder);
- } else if (tag.equalsIgnoreCase("u")) {
- end(mSpannableStringBuilder, Underline.class, new UnderlineSpan());
- } else if (tag.equalsIgnoreCase("sup")) {
- end(mSpannableStringBuilder, Super.class, new SuperscriptSpan());
- } else if (tag.equalsIgnoreCase("sub")) {
- end(mSpannableStringBuilder, Sub.class, new SubscriptSpan());
- } else if (tag.length() == 2 &&
- Character.toLowerCase(tag.charAt(0)) == 'h' &&
- tag.charAt(1) >= '1' && tag.charAt(1) <= '6') {
- handleP(mSpannableStringBuilder);
- endHeader(mSpannableStringBuilder);
- } else if (mTagHandler != null) {
- mTagHandler.handleTag(false, tag, mSpannableStringBuilder, mReader);
- }
- }
-
- private static void handleP(SpannableStringBuilder text) {
- int len = text.length();
-
- if (len >= 1 && text.charAt(len - 1) == '\n') {
- if (len >= 2 && text.charAt(len - 2) == '\n') {
- return;
- }
-
- text.append("\n");
- return;
- }
-
- if (len != 0) {
- text.append("\n\n");
- }
- }
-
- private static void handleBr(SpannableStringBuilder text) {
- text.append("\n");
- }
-
- private static Object getLast(Spanned text, Class kind) {
- /*
- * This knows that the last returned object from getSpans()
- * will be the most recently added.
- */
- Object[] objs = text.getSpans(0, text.length(), kind);
-
- if (objs.length == 0) {
- return null;
- } else {
- return objs[objs.length - 1];
- }
- }
-
- private static void start(SpannableStringBuilder text, Object mark) {
- int len = text.length();
- text.setSpan(mark, len, len, Spannable.SPAN_MARK_MARK);
- }
-
- private static void end(SpannableStringBuilder text, Class kind,
- Object repl) {
- int len = text.length();
- Object obj = getLast(text, kind);
- int where = text.getSpanStart(obj);
-
- text.removeSpan(obj);
-
- if (where != len) {
- text.setSpan(repl, where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- return;
- }
-
- private static void startImg(SpannableStringBuilder text,
- Attributes attributes, Html.ImageGetter img) {
- String src = attributes.getValue("", "src");
- Drawable d = null;
-
- if (img != null) {
- d = img.getDrawable(src);
- }
-
- if (d == null) {
- d = Resources.getSystem().
- getDrawable(com.android.internal.R.drawable.unknown_image);
- d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
- }
-
- int len = text.length();
- text.append("\uFFFC");
-
- text.setSpan(new ImageSpan(d, src), len, text.length(),
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- private static void startFont(SpannableStringBuilder text,
- Attributes attributes) {
- String color = attributes.getValue("", "color");
- String face = attributes.getValue("", "face");
-
- int len = text.length();
- text.setSpan(new Font(color, face), len, len, Spannable.SPAN_MARK_MARK);
- }
-
- private static void endFont(SpannableStringBuilder text) {
- int len = text.length();
- Object obj = getLast(text, Font.class);
- int where = text.getSpanStart(obj);
-
- text.removeSpan(obj);
-
- if (where != len) {
- Font f = (Font) obj;
-
- if (f.mColor != null) {
- int c = -1;
-
- if (f.mColor.equalsIgnoreCase("aqua")) {
- c = 0x00FFFF;
- } else if (f.mColor.equalsIgnoreCase("black")) {
- c = 0x000000;
- } else if (f.mColor.equalsIgnoreCase("blue")) {
- c = 0x0000FF;
- } else if (f.mColor.equalsIgnoreCase("fuchsia")) {
- c = 0xFF00FF;
- } else if (f.mColor.equalsIgnoreCase("green")) {
- c = 0x008000;
- } else if (f.mColor.equalsIgnoreCase("grey")) {
- c = 0x808080;
- } else if (f.mColor.equalsIgnoreCase("lime")) {
- c = 0x00FF00;
- } else if (f.mColor.equalsIgnoreCase("maroon")) {
- c = 0x800000;
- } else if (f.mColor.equalsIgnoreCase("navy")) {
- c = 0x000080;
- } else if (f.mColor.equalsIgnoreCase("olive")) {
- c = 0x808000;
- } else if (f.mColor.equalsIgnoreCase("purple")) {
- c = 0x800080;
- } else if (f.mColor.equalsIgnoreCase("red")) {
- c = 0xFF0000;
- } else if (f.mColor.equalsIgnoreCase("silver")) {
- c = 0xC0C0C0;
- } else if (f.mColor.equalsIgnoreCase("teal")) {
- c = 0x008080;
- } else if (f.mColor.equalsIgnoreCase("white")) {
- c = 0xFFFFFF;
- } else if (f.mColor.equalsIgnoreCase("yellow")) {
- c = 0xFFFF00;
- } else {
- try {
- c = XmlUtils.convertValueToInt(f.mColor, -1);
- } catch (NumberFormatException nfe) {
- // Can't understand the color, so just drop it.
- }
- }
-
- if (c != -1) {
- text.setSpan(new ForegroundColorSpan(c | 0xFF000000),
- where, len,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
-
- if (f.mFace != null) {
- text.setSpan(new TypefaceSpan(f.mFace), where, len,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- }
-
- private static void startA(SpannableStringBuilder text, Attributes attributes) {
- String href = attributes.getValue("", "href");
-
- int len = text.length();
- text.setSpan(new Href(href), len, len, Spannable.SPAN_MARK_MARK);
- }
-
- private static void endA(SpannableStringBuilder text) {
- int len = text.length();
- Object obj = getLast(text, Href.class);
- int where = text.getSpanStart(obj);
-
- text.removeSpan(obj);
-
- if (where != len) {
- Href h = (Href) obj;
-
- if (h.mHref != null) {
- text.setSpan(new URLSpan(h.mHref), where, len,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- }
-
- private static void endHeader(SpannableStringBuilder text) {
- int len = text.length();
- Object obj = getLast(text, Header.class);
-
- int where = text.getSpanStart(obj);
-
- text.removeSpan(obj);
-
- // Back off not to change only the text, not the blank line.
- while (len > where && text.charAt(len - 1) == '\n') {
- len--;
- }
-
- if (where != len) {
- Header h = (Header) obj;
-
- text.setSpan(new RelativeSizeSpan(HEADER_SIZES[h.mLevel]),
- where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- text.setSpan(new StyleSpan(Typeface.BOLD),
- where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
-
- public void setDocumentLocator(Locator locator) {
- }
-
- public void startDocument() throws SAXException {
- }
-
- public void endDocument() throws SAXException {
- }
-
- public void startPrefixMapping(String prefix, String uri) throws SAXException {
- }
-
- public void endPrefixMapping(String prefix) throws SAXException {
- }
-
- public void startElement(String uri, String localName, String qName, Attributes attributes)
- throws SAXException {
- handleStartTag(localName, attributes);
- }
-
- public void endElement(String uri, String localName, String qName) throws SAXException {
- handleEndTag(localName);
- }
-
- public void characters(char ch[], int start, int length) throws SAXException {
- StringBuilder sb = new StringBuilder();
-
- /*
- * Ignore whitespace that immediately follows other whitespace;
- * newlines count as spaces.
- */
-
- for (int i = 0; i < length; i++) {
- char c = ch[i + start];
-
- if (c == ' ' || c == '\n') {
- char pred;
- int len = sb.length();
-
- if (len == 0) {
- len = mSpannableStringBuilder.length();
-
- if (len == 0) {
- pred = '\n';
- } else {
- pred = mSpannableStringBuilder.charAt(len - 1);
- }
- } else {
- pred = sb.charAt(len - 1);
- }
-
- if (pred != ' ' && pred != '\n') {
- sb.append(' ');
- }
- } else {
- sb.append(c);
- }
- }
-
- mSpannableStringBuilder.append(sb);
- }
-
- public void ignorableWhitespace(char ch[], int start, int length) throws SAXException {
- }
-
- public void processingInstruction(String target, String data) throws SAXException {
- }
-
- public void skippedEntity(String name) throws SAXException {
- }
-
- private static class Bold { }
- private static class Italic { }
- private static class Underline { }
- private static class Big { }
- private static class Small { }
- private static class Monospace { }
- private static class Blockquote { }
- private static class Super { }
- private static class Sub { }
-
- private static class Font {
- public String mColor;
- public String mFace;
-
- public Font(String color, String face) {
- mColor = color;
- mFace = face;
- }
- }
-
- private static class Href {
- public String mHref;
-
- public Href(String href) {
- mHref = href;
- }
- }
-
- private static class Header {
- private int mLevel;
-
- public Header(int level) {
- mLevel = level;
- }
- }
-}
diff --git a/core/java/android/text/IClipboard.aidl b/core/java/android/text/IClipboard.aidl
deleted file mode 100644
index 4deb5c8..0000000
--- a/core/java/android/text/IClipboard.aidl
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Copyright (c) 2008, 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 android.text;
-
-/**
- * Programming interface to the clipboard, which allows copying and pasting
- * between applications.
- * {@hide}
- */
-interface IClipboard {
- /**
- * Returns the text on the clipboard. It will eventually be possible
- * to store types other than text too, in which case this will return
- * null if the type cannot be coerced to text.
- */
- CharSequence getClipboardText();
-
- /**
- * Sets the contents of the clipboard to the specified text.
- */
- void setClipboardText(CharSequence text);
-
- /**
- * Returns true if the clipboard contains text; false otherwise.
- */
- boolean hasClipboardText();
-}
-
diff --git a/core/java/android/text/InputFilter.java b/core/java/android/text/InputFilter.java
deleted file mode 100644
index 2f55677..0000000
--- a/core/java/android/text/InputFilter.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-/**
- * InputFilters can be attached to {@link Editable}s to constrain the
- * changes that can be made to them.
- */
-public interface InputFilter
-{
- /**
- * This method is called when the buffer is going to replace the
- * range <code>dstart &hellip; dend</code> of <code>dest</code>
- * with the new text from the range <code>start &hellip; end</code>
- * of <code>source</code>. Return the CharSequence that you would
- * like to have placed there instead, including an empty string
- * if appropriate, or <code>null</code> to accept the original
- * replacement. Be careful to not to reject 0-length replacements,
- * as this is what happens when you delete text. Also beware that
- * you should not attempt to make any changes to <code>dest</code>
- * from this method; you may only examine it for context.
- *
- * Note: If <var>source</var> is an instance of {@link Spanned} or
- * {@link Spannable}, the span objects in the <var>source</var> should be
- * copied into the filtered result (i.e. the non-null return value).
- * {@link TextUtils#copySpansFrom} can be used for convenience.
- */
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend);
-
- /**
- * This filter will capitalize all the lower case letters that are added
- * through edits.
- */
- public static class AllCaps implements InputFilter {
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
- for (int i = start; i < end; i++) {
- if (Character.isLowerCase(source.charAt(i))) {
- char[] v = new char[end - start];
- TextUtils.getChars(source, start, end, v, 0);
- String s = new String(v).toUpperCase();
-
- if (source instanceof Spanned) {
- SpannableString sp = new SpannableString(s);
- TextUtils.copySpansFrom((Spanned) source,
- start, end, null, sp, 0);
- return sp;
- } else {
- return s;
- }
- }
- }
-
- return null; // keep original
- }
- }
-
- /**
- * This filter will constrain edits not to make the length of the text
- * greater than the specified length.
- */
- public static class LengthFilter implements InputFilter {
- public LengthFilter(int max) {
- mMax = max;
- }
-
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
- int keep = mMax - (dest.length() - (dend - dstart));
-
- if (keep <= 0) {
- return "";
- } else if (keep >= end - start) {
- return null; // keep original
- } else {
- return source.subSequence(start, start + keep);
- }
- }
-
- private int mMax;
- }
-}
diff --git a/core/java/android/text/InputType.java b/core/java/android/text/InputType.java
deleted file mode 100644
index a073cf4..0000000
--- a/core/java/android/text/InputType.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.text;
-
-import android.text.TextUtils;
-
-/**
- * Bit definitions for an integer defining the basic content type of text
- * held in an {@link Editable} object.
- */
-public interface InputType {
- /**
- * Mask of bits that determine the overall class
- * of text being given. Currently supported classes are:
- * {@link #TYPE_CLASS_TEXT}, {@link #TYPE_CLASS_NUMBER},
- * {@link #TYPE_CLASS_PHONE}, {@link #TYPE_CLASS_DATETIME}.
- * If the class is not one you
- * understand, assume {@link #TYPE_CLASS_TEXT} with NO variation
- * or flags.
- */
- public static final int TYPE_MASK_CLASS = 0x0000000f;
-
- /**
- * Mask of bits that determine the variation of
- * the base content class.
- */
- public static final int TYPE_MASK_VARIATION = 0x00000ff0;
-
- /**
- * Mask of bits that provide addition bit flags
- * of options.
- */
- public static final int TYPE_MASK_FLAGS = 0x00fff000;
-
- /**
- * Special content type for when no explicit type has been specified.
- * This should be interpreted to mean that the target input connection
- * is not rich, it can not process and show things like candidate text nor
- * retrieve the current text, so the input method will need to run in a
- * limited "generate key events" mode.
- */
- public static final int TYPE_NULL = 0x00000000;
-
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
-
- /**
- * Class for normal text. This class supports the following flags (only
- * one of which should be set):
- * {@link #TYPE_TEXT_FLAG_CAP_CHARACTERS},
- * {@link #TYPE_TEXT_FLAG_CAP_WORDS}, and.
- * {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}. It also supports the
- * following variations:
- * {@link #TYPE_TEXT_VARIATION_NORMAL}, and
- * {@link #TYPE_TEXT_VARIATION_URI}. If you do not recognize the
- * variation, normal should be assumed.
- */
- public static final int TYPE_CLASS_TEXT = 0x00000001;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: capitalize all characters. Overrides
- * {@link #TYPE_TEXT_FLAG_CAP_WORDS} and
- * {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}. This value is explicitly defined
- * to be the same as {@link TextUtils#CAP_MODE_CHARACTERS}.
- */
- public static final int TYPE_TEXT_FLAG_CAP_CHARACTERS = 0x00001000;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: capitalize first character of
- * all words. Overrides {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}. This
- * value is explicitly defined
- * to be the same as {@link TextUtils#CAP_MODE_WORDS}.
- */
- public static final int TYPE_TEXT_FLAG_CAP_WORDS = 0x00002000;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: capitalize first character of
- * each sentence. This value is explicitly defined
- * to be the same as {@link TextUtils#CAP_MODE_SENTENCES}.
- */
- public static final int TYPE_TEXT_FLAG_CAP_SENTENCES = 0x00004000;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: the user is entering free-form
- * text that should have auto-correction applied to it.
- */
- public static final int TYPE_TEXT_FLAG_AUTO_CORRECT = 0x00008000;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: the text editor is performing
- * auto-completion of the text being entered based on its own semantics,
- * which it will present to the user as they type. This generally means
- * that the input method should not be showing candidates itself, but can
- * expect for the editor to supply its own completions/candidates from
- * {@link android.view.inputmethod.InputMethodSession#displayCompletions
- * InputMethodSession.displayCompletions()} as a result of the editor calling
- * {@link android.view.inputmethod.InputMethodManager#displayCompletions
- * InputMethodManager.displayCompletions()}.
- */
- public static final int TYPE_TEXT_FLAG_AUTO_COMPLETE = 0x00010000;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: multiple lines of text can be
- * entered into the field. If this flag is not set, the text field
- * will be constrained to a single line.
- */
- public static final int TYPE_TEXT_FLAG_MULTI_LINE = 0x00020000;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: the regular text view associated
- * with this should not be multi-line, but when a fullscreen input method
- * is providing text it should use multiple lines if it can.
- */
- public static final int TYPE_TEXT_FLAG_IME_MULTI_LINE = 0x00040000;
-
- /**
- * Flag for {@link #TYPE_CLASS_TEXT}: flags any text being used as a search string
- */
- public static final int TYPE_TEXT_FLAG_SEARCH = 0x00080000;
-
- // ----------------------------------------------------------------------
-
- /**
- * Default variation of {@link #TYPE_CLASS_TEXT}: plain old normal text.
- */
- public static final int TYPE_TEXT_VARIATION_NORMAL = 0x00000000;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering a URI.
- */
- public static final int TYPE_TEXT_VARIATION_URI = 0x00000010;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering an e-mail address.
- */
- public static final int TYPE_TEXT_VARIATION_EMAIL_ADDRESS = 0x00000020;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering the subject line of
- * an e-mail.
- */
- public static final int TYPE_TEXT_VARIATION_EMAIL_SUBJECT = 0x00000030;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering a short, possibly informal
- * message such as an instant message or a text message.
- */
- public static final int TYPE_TEXT_VARIATION_SHORT_MESSAGE = 0x00000040;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering the content of a long, possibly
- * formal message such as the body of an e-mail.
- */
- public static final int TYPE_TEXT_VARIATION_LONG_MESSAGE = 0x00000050;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering the name of a person.
- */
- public static final int TYPE_TEXT_VARIATION_PERSON_NAME = 0x00000060;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering a postal mailing address.
- */
- public static final int TYPE_TEXT_VARIATION_POSTAL_ADDRESS = 0x00000070;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering a password.
- */
- public static final int TYPE_TEXT_VARIATION_PASSWORD = 0x00000080;
-
- /**
- * Variation of {@link #TYPE_CLASS_TEXT}: entering text inside of a web form.
- */
- public static final int TYPE_TEXT_VARIATION_WEB_EDIT_TEXT = 0x00000090;
-
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
-
- /**
- * Class for numeric text. This class supports the following flag:
- * {@link #TYPE_NUMBER_FLAG_SIGNED} and
- * {@link #TYPE_NUMBER_FLAG_DECIMAL}.
- */
- public static final int TYPE_CLASS_NUMBER = 0x00000002;
-
- /**
- * Flag of {@link #TYPE_CLASS_NUMBER}: the number is signed, allowing
- * a positive or negative sign at the start.
- */
- public static final int TYPE_NUMBER_FLAG_SIGNED = 0x00001000;
-
- /**
- * Flag of {@link #TYPE_CLASS_NUMBER}: the number is decimal, allowing
- * a decimal point to provide fractional values.
- */
- public static final int TYPE_NUMBER_FLAG_DECIMAL = 0x00002000;
-
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
-
- /**
- * Class for a phone number. This class currently supports no variations
- * or flags.
- */
- public static final int TYPE_CLASS_PHONE = 0x00000003;
-
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
- // ----------------------------------------------------------------------
-
- /**
- * Class for dates and times. It supports the
- * following variations:
- * {@link #TYPE_DATETIME_VARIATION_NORMAL}
- * {@link #TYPE_DATETIME_VARIATION_DATE}, and
- * {@link #TYPE_DATETIME_VARIATION_TIME},.
- */
- public static final int TYPE_CLASS_DATETIME = 0x00000004;
-
- /**
- * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering
- * both a date and time.
- */
- public static final int TYPE_DATETIME_VARIATION_NORMAL = 0x00000000;
-
- /**
- * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering
- * only a date.
- */
- public static final int TYPE_DATETIME_VARIATION_DATE = 0x00000010;
-
- /**
- * Default variation of {@link #TYPE_CLASS_DATETIME}: allows entering
- * only a time.
- */
- public static final int TYPE_DATETIME_VARIATION_TIME = 0x00000020;
-}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
deleted file mode 100644
index 95acf9d..0000000
--- a/core/java/android/text/Layout.java
+++ /dev/null
@@ -1,1747 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Path;
-import com.android.internal.util.ArrayUtils;
-import android.util.Config;
-
-import junit.framework.Assert;
-import android.text.style.*;
-import android.text.method.TextKeyListener;
-import android.view.KeyEvent;
-
-/**
- * A base class that manages text layout in visual elements on
- * the screen.
- * <p>For text that will be edited, use a {@link DynamicLayout},
- * which will be updated as the text changes.
- * For text that will not change, use a {@link StaticLayout}.
- */
-public abstract class Layout {
- /**
- * Return how wide a layout would be necessary to display the
- * specified text with one line per paragraph.
- */
- public static float getDesiredWidth(CharSequence source,
- TextPaint paint) {
- return getDesiredWidth(source, 0, source.length(), paint);
- }
-
- /**
- * Return how wide a layout would be necessary to display the
- * specified text slice with one line per paragraph.
- */
- public static float getDesiredWidth(CharSequence source,
- int start, int end,
- TextPaint paint) {
- float need = 0;
- TextPaint workPaint = new TextPaint();
-
- int next;
- for (int i = start; i <= end; i = next) {
- next = TextUtils.indexOf(source, '\n', i, end);
-
- if (next < 0)
- next = end;
-
- float w = measureText(paint, workPaint,
- source, i, next, null, true, null);
-
- if (w > need)
- need = w;
-
- next++;
- }
-
- return need;
- }
-
- /**
- * Subclasses of Layout use this constructor to set the display text,
- * width, and other standard properties.
- */
- protected Layout(CharSequence text, TextPaint paint,
- int width, Alignment align,
- float spacingmult, float spacingadd) {
- if (width < 0)
- throw new IllegalArgumentException("Layout: " + width + " < 0");
-
- mText = text;
- mPaint = paint;
- mWorkPaint = new TextPaint();
- mWidth = width;
- mAlignment = align;
- mSpacingMult = spacingmult;
- mSpacingAdd = spacingadd;
- mSpannedText = text instanceof Spanned;
- }
-
- /**
- * Replace constructor properties of this Layout with new ones. Be careful.
- */
- /* package */ void replaceWith(CharSequence text, TextPaint paint,
- int width, Alignment align,
- float spacingmult, float spacingadd) {
- if (width < 0) {
- throw new IllegalArgumentException("Layout: " + width + " < 0");
- }
-
- mText = text;
- mPaint = paint;
- mWidth = width;
- mAlignment = align;
- mSpacingMult = spacingmult;
- mSpacingAdd = spacingadd;
- mSpannedText = text instanceof Spanned;
- }
-
- /**
- * Draw this Layout on the specified Canvas.
- */
- public void draw(Canvas c) {
- draw(c, null, null, 0);
- }
-
- /**
- * Draw the specified rectangle from this Layout on the specified Canvas,
- * with the specified path drawn between the background and the text.
- */
- public void draw(Canvas c, Path highlight, Paint highlightpaint,
- int cursorOffsetVertical) {
- int dtop, dbottom;
-
- synchronized (sTempRect) {
- if (!c.getClipBounds(sTempRect)) {
- return;
- }
-
- dtop = sTempRect.top;
- dbottom = sTempRect.bottom;
- }
-
- TextPaint paint = mPaint;
-
- int top = 0;
- // getLineBottom(getLineCount() -1) just calls getLineTop(getLineCount)
- int bottom = getLineTop(getLineCount());
-
-
- if (dtop > top) {
- top = dtop;
- }
- if (dbottom < bottom) {
- bottom = dbottom;
- }
-
- int first = getLineForVertical(top);
- int last = getLineForVertical(bottom);
-
- int previousLineBottom = getLineTop(first);
- int previousLineEnd = getLineStart(first);
-
- CharSequence buf = mText;
-
- ParagraphStyle[] nospans = ArrayUtils.emptyArray(ParagraphStyle.class);
- ParagraphStyle[] spans = nospans;
- int spanend = 0;
- int textLength = 0;
- boolean spannedText = mSpannedText;
-
- if (spannedText) {
- spanend = 0;
- textLength = buf.length();
- for (int i = first; i <= last; i++) {
- int start = previousLineEnd;
- int end = getLineStart(i+1);
- previousLineEnd = end;
-
- int ltop = previousLineBottom;
- int lbottom = getLineTop(i+1);
- previousLineBottom = lbottom;
- int lbaseline = lbottom - getLineDescent(i);
-
- if (start >= spanend) {
- Spanned sp = (Spanned) buf;
- spanend = sp.nextSpanTransition(start, textLength,
- LineBackgroundSpan.class);
- spans = sp.getSpans(start, spanend,
- LineBackgroundSpan.class);
- }
-
- for (int n = 0; n < spans.length; n++) {
- LineBackgroundSpan back = (LineBackgroundSpan) spans[n];
-
- back.drawBackground(c, paint, 0, mWidth,
- ltop, lbaseline, lbottom,
- buf, start, end,
- i);
- }
- }
- // reset to their original values
- spanend = 0;
- previousLineBottom = getLineTop(first);
- previousLineEnd = getLineStart(first);
- spans = nospans;
- }
-
- // There can be a highlight even without spans if we are drawing
- // a non-spanned transformation of a spanned editing buffer.
- if (highlight != null) {
- if (cursorOffsetVertical != 0) {
- c.translate(0, cursorOffsetVertical);
- }
-
- c.drawPath(highlight, highlightpaint);
-
- if (cursorOffsetVertical != 0) {
- c.translate(0, -cursorOffsetVertical);
- }
- }
-
- Alignment align = mAlignment;
-
- for (int i = first; i <= last; i++) {
- int start = previousLineEnd;
-
- previousLineEnd = getLineStart(i+1);
- int end = getLineVisibleEnd(i, start, previousLineEnd);
-
- int ltop = previousLineBottom;
- int lbottom = getLineTop(i+1);
- previousLineBottom = lbottom;
- int lbaseline = lbottom - getLineDescent(i);
-
- boolean par = false;
- if (spannedText) {
- if (start == 0 || buf.charAt(start - 1) == '\n') {
- par = true;
- }
- if (start >= spanend) {
-
- Spanned sp = (Spanned) buf;
-
- spanend = sp.nextSpanTransition(start, textLength,
- ParagraphStyle.class);
- spans = sp.getSpans(start, spanend, ParagraphStyle.class);
-
- align = mAlignment;
-
- for (int n = spans.length-1; n >= 0; n--) {
- if (spans[n] instanceof AlignmentSpan) {
- align = ((AlignmentSpan) spans[n]).getAlignment();
- break;
- }
- }
- }
- }
-
- int dir = getParagraphDirection(i);
- int left = 0;
- int right = mWidth;
-
- if (spannedText) {
- final int length = spans.length;
- for (int n = 0; n < length; n++) {
- if (spans[n] instanceof LeadingMarginSpan) {
- LeadingMarginSpan margin = (LeadingMarginSpan) spans[n];
-
- if (dir == DIR_RIGHT_TO_LEFT) {
- margin.drawLeadingMargin(c, paint, right, dir, ltop,
- lbaseline, lbottom, buf,
- start, end, par, this);
-
- right -= margin.getLeadingMargin(par);
- } else {
- margin.drawLeadingMargin(c, paint, left, dir, ltop,
- lbaseline, lbottom, buf,
- start, end, par, this);
-
- left += margin.getLeadingMargin(par);
- }
- }
- }
- }
-
- int x;
- if (align == Alignment.ALIGN_NORMAL) {
- if (dir == DIR_LEFT_TO_RIGHT) {
- x = left;
- } else {
- x = right;
- }
- } else {
- int max = (int)getLineMax(i, spans, false);
- if (align == Alignment.ALIGN_OPPOSITE) {
- if (dir == DIR_RIGHT_TO_LEFT) {
- x = left + max;
- } else {
- x = right - max;
- }
- } else {
- // Alignment.ALIGN_CENTER
- max = max & ~1;
- int half = (right - left - max) >> 1;
- if (dir == DIR_RIGHT_TO_LEFT) {
- x = right - half;
- } else {
- x = left + half;
- }
- }
- }
-
- Directions directions = getLineDirections(i);
- boolean hasTab = getLineContainsTab(i);
- if (directions == DIRS_ALL_LEFT_TO_RIGHT &&
- !spannedText && !hasTab) {
- if (Config.DEBUG) {
- Assert.assertTrue(dir == DIR_LEFT_TO_RIGHT);
- Assert.assertNotNull(c);
- }
- c.drawText(buf, start, end, x, lbaseline, paint);
- } else {
- drawText(c, buf, start, end, dir, directions,
- x, ltop, lbaseline, lbottom, paint, mWorkPaint,
- hasTab, spans);
- }
- }
- }
-
- /**
- * Return the text that is displayed by this Layout.
- */
- public final CharSequence getText() {
- return mText;
- }
-
- /**
- * Return the base Paint properties for this layout.
- * Do NOT change the paint, which may result in funny
- * drawing for this layout.
- */
- public final TextPaint getPaint() {
- return mPaint;
- }
-
- /**
- * Return the width of this layout.
- */
- public final int getWidth() {
- return mWidth;
- }
-
- /**
- * Return the width to which this Layout is ellipsizing, or
- * {@link #getWidth} if it is not doing anything special.
- */
- public int getEllipsizedWidth() {
- return mWidth;
- }
-
- /**
- * Increase the width of this layout to the specified width.
- * Be careful to use this only when you know it is appropriate --
- * it does not cause the text to reflow to use the full new width.
- */
- public final void increaseWidthTo(int wid) {
- if (wid < mWidth) {
- throw new RuntimeException("attempted to reduce Layout width");
- }
-
- mWidth = wid;
- }
-
- /**
- * Return the total height of this layout.
- */
- public int getHeight() {
- return getLineTop(getLineCount()); // same as getLineBottom(getLineCount() - 1);
- }
-
- /**
- * Return the base alignment of this layout.
- */
- public final Alignment getAlignment() {
- return mAlignment;
- }
-
- /**
- * Return what the text height is multiplied by to get the line height.
- */
- public final float getSpacingMultiplier() {
- return mSpacingMult;
- }
-
- /**
- * Return the number of units of leading that are added to each line.
- */
- public final float getSpacingAdd() {
- return mSpacingAdd;
- }
-
- /**
- * Return the number of lines of text in this layout.
- */
- public abstract int getLineCount();
-
- /**
- * Return the baseline for the specified line (0&hellip;getLineCount() - 1)
- * If bounds is not null, return the top, left, right, bottom extents
- * of the specified line in it.
- * @param line which line to examine (0..getLineCount() - 1)
- * @param bounds Optional. If not null, it returns the extent of the line
- * @return the Y-coordinate of the baseline
- */
- public int getLineBounds(int line, Rect bounds) {
- if (bounds != null) {
- bounds.left = 0; // ???
- bounds.top = getLineTop(line);
- bounds.right = mWidth; // ???
- bounds.bottom = getLineBottom(line);
- }
- return getLineBaseline(line);
- }
-
- /**
- * Return the vertical position of the top of the specified line.
- * If the specified line is one beyond the last line, returns the
- * bottom of the last line.
- */
- public abstract int getLineTop(int line);
-
- /**
- * Return the descent of the specified line.
- */
- public abstract int getLineDescent(int line);
-
- /**
- * Return the text offset of the beginning of the specified line.
- * If the specified line is one beyond the last line, returns the
- * end of the last line.
- */
- public abstract int getLineStart(int line);
-
- /**
- * Returns the primary directionality of the paragraph containing
- * the specified line.
- */
- public abstract int getParagraphDirection(int line);
-
- /**
- * Returns whether the specified line contains one or more tabs.
- */
- public abstract boolean getLineContainsTab(int line);
-
- /**
- * Returns an array of directionalities for the specified line.
- * The array alternates counts of characters in left-to-right
- * and right-to-left segments of the line.
- */
- public abstract Directions getLineDirections(int line);
-
- /**
- * Returns the (negative) number of extra pixels of ascent padding in the
- * top line of the Layout.
- */
- public abstract int getTopPadding();
-
- /**
- * Returns the number of extra pixels of descent padding in the
- * bottom line of the Layout.
- */
- public abstract int getBottomPadding();
-
- /**
- * Get the primary horizontal position for the specified text offset.
- * This is the location where a new character would be inserted in
- * the paragraph's primary direction.
- */
- public float getPrimaryHorizontal(int offset) {
- return getHorizontal(offset, false, true);
- }
-
- /**
- * Get the secondary horizontal position for the specified text offset.
- * This is the location where a new character would be inserted in
- * the direction other than the paragraph's primary direction.
- */
- public float getSecondaryHorizontal(int offset) {
- return getHorizontal(offset, true, true);
- }
-
- private float getHorizontal(int offset, boolean trailing, boolean alt) {
- int line = getLineForOffset(offset);
-
- return getHorizontal(offset, trailing, alt, line);
- }
-
- private float getHorizontal(int offset, boolean trailing, boolean alt,
- int line) {
- int start = getLineStart(line);
- int end = getLineVisibleEnd(line);
- int dir = getParagraphDirection(line);
- boolean tab = getLineContainsTab(line);
- Directions directions = getLineDirections(line);
-
- TabStopSpan[] tabs = null;
- if (tab && mText instanceof Spanned) {
- tabs = ((Spanned) mText).getSpans(start, end, TabStopSpan.class);
- }
-
- float wid = measureText(mPaint, mWorkPaint, mText, start, offset, end,
- dir, directions, trailing, alt, tab, tabs);
-
- if (offset > end) {
- if (dir == DIR_RIGHT_TO_LEFT)
- wid -= measureText(mPaint, mWorkPaint,
- mText, end, offset, null, tab, tabs);
- else
- wid += measureText(mPaint, mWorkPaint,
- mText, end, offset, null, tab, tabs);
- }
-
- Alignment align = getParagraphAlignment(line);
- int left = getParagraphLeft(line);
- int right = getParagraphRight(line);
-
- if (align == Alignment.ALIGN_NORMAL) {
- if (dir == DIR_RIGHT_TO_LEFT)
- return right + wid;
- else
- return left + wid;
- }
-
- float max = getLineMax(line);
-
- if (align == Alignment.ALIGN_OPPOSITE) {
- if (dir == DIR_RIGHT_TO_LEFT)
- return left + max + wid;
- else
- return right - max + wid;
- } else { /* align == Alignment.ALIGN_CENTER */
- int imax = ((int) max) & ~1;
-
- if (dir == DIR_RIGHT_TO_LEFT)
- return right - (((right - left) - imax) / 2) + wid;
- else
- return left + ((right - left) - imax) / 2 + wid;
- }
- }
-
- /**
- * Get the leftmost position that should be exposed for horizontal
- * scrolling on the specified line.
- */
- public float getLineLeft(int line) {
- int dir = getParagraphDirection(line);
- Alignment align = getParagraphAlignment(line);
-
- if (align == Alignment.ALIGN_NORMAL) {
- if (dir == DIR_RIGHT_TO_LEFT)
- return getParagraphRight(line) - getLineMax(line);
- else
- return 0;
- } else if (align == Alignment.ALIGN_OPPOSITE) {
- if (dir == DIR_RIGHT_TO_LEFT)
- return 0;
- else
- return mWidth - getLineMax(line);
- } else { /* align == Alignment.ALIGN_CENTER */
- int left = getParagraphLeft(line);
- int right = getParagraphRight(line);
- int max = ((int) getLineMax(line)) & ~1;
-
- return left + ((right - left) - max) / 2;
- }
- }
-
- /**
- * Get the rightmost position that should be exposed for horizontal
- * scrolling on the specified line.
- */
- public float getLineRight(int line) {
- int dir = getParagraphDirection(line);
- Alignment align = getParagraphAlignment(line);
-
- if (align == Alignment.ALIGN_NORMAL) {
- if (dir == DIR_RIGHT_TO_LEFT)
- return mWidth;
- else
- return getParagraphLeft(line) + getLineMax(line);
- } else if (align == Alignment.ALIGN_OPPOSITE) {
- if (dir == DIR_RIGHT_TO_LEFT)
- return getLineMax(line);
- else
- return mWidth;
- } else { /* align == Alignment.ALIGN_CENTER */
- int left = getParagraphLeft(line);
- int right = getParagraphRight(line);
- int max = ((int) getLineMax(line)) & ~1;
-
- return right - ((right - left) - max) / 2;
- }
- }
-
- /**
- * Gets the horizontal extent of the specified line, excluding
- * trailing whitespace.
- */
- public float getLineMax(int line) {
- return getLineMax(line, null, false);
- }
-
- /**
- * Gets the horizontal extent of the specified line, including
- * trailing whitespace.
- */
- public float getLineWidth(int line) {
- return getLineMax(line, null, true);
- }
-
- private float getLineMax(int line, Object[] tabs, boolean full) {
- int start = getLineStart(line);
- int end;
-
- if (full) {
- end = getLineEnd(line);
- } else {
- end = getLineVisibleEnd(line);
- }
- boolean tab = getLineContainsTab(line);
-
- if (tabs == null && tab && mText instanceof Spanned) {
- tabs = ((Spanned) mText).getSpans(start, end, TabStopSpan.class);
- }
-
- return measureText(mPaint, mWorkPaint,
- mText, start, end, null, tab, tabs);
- }
-
- /**
- * Get the line number corresponding to the specified vertical position.
- * If you ask for a position above 0, you get 0; if you ask for a position
- * below the bottom of the text, you get the last line.
- */
- // FIXME: It may be faster to do a linear search for layouts without many lines.
- public int getLineForVertical(int vertical) {
- int high = getLineCount(), low = -1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
-
- if (getLineTop(guess) > vertical)
- high = guess;
- else
- low = guess;
- }
-
- if (low < 0)
- return 0;
- else
- return low;
- }
-
- /**
- * Get the line number on which the specified text offset appears.
- * If you ask for a position before 0, you get 0; if you ask for a position
- * beyond the end of the text, you get the last line.
- */
- public int getLineForOffset(int offset) {
- int high = getLineCount(), low = -1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
-
- if (getLineStart(guess) > offset)
- high = guess;
- else
- low = guess;
- }
-
- if (low < 0)
- return 0;
- else
- return low;
- }
-
- /**
- * Get the character offset on the specfied line whose position is
- * closest to the specified horizontal position.
- */
- public int getOffsetForHorizontal(int line, float horiz) {
- int max = getLineEnd(line) - 1;
- int min = getLineStart(line);
- Directions dirs = getLineDirections(line);
-
- if (line == getLineCount() - 1)
- max++;
-
- int best = min;
- float bestdist = Math.abs(getPrimaryHorizontal(best) - horiz);
-
- int here = min;
- for (int i = 0; i < dirs.mDirections.length; i++) {
- int there = here + dirs.mDirections[i];
- int swap = ((i & 1) == 0) ? 1 : -1;
-
- if (there > max)
- there = max;
-
- int high = there - 1 + 1, low = here + 1 - 1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
- int adguess = getOffsetAtStartOf(guess);
-
- if (getPrimaryHorizontal(adguess) * swap >= horiz * swap)
- high = guess;
- else
- low = guess;
- }
-
- if (low < here + 1)
- low = here + 1;
-
- if (low < there) {
- low = getOffsetAtStartOf(low);
-
- float dist = Math.abs(getPrimaryHorizontal(low) - horiz);
-
- int aft = TextUtils.getOffsetAfter(mText, low);
- if (aft < there) {
- float other = Math.abs(getPrimaryHorizontal(aft) - horiz);
-
- if (other < dist) {
- dist = other;
- low = aft;
- }
- }
-
- if (dist < bestdist) {
- bestdist = dist;
- best = low;
- }
- }
-
- float dist = Math.abs(getPrimaryHorizontal(here) - horiz);
-
- if (dist < bestdist) {
- bestdist = dist;
- best = here;
- }
-
- here = there;
- }
-
- float dist = Math.abs(getPrimaryHorizontal(max) - horiz);
-
- if (dist < bestdist) {
- bestdist = dist;
- best = max;
- }
-
- return best;
- }
-
- /**
- * Return the text offset after the last character on the specified line.
- */
- public final int getLineEnd(int line) {
- return getLineStart(line + 1);
- }
-
- /**
- * Return the text offset after the last visible character (so whitespace
- * is not counted) on the specified line.
- */
- public int getLineVisibleEnd(int line) {
- return getLineVisibleEnd(line, getLineStart(line), getLineStart(line+1));
- }
-
- private int getLineVisibleEnd(int line, int start, int end) {
- if (Config.DEBUG) {
- Assert.assertTrue(getLineStart(line) == start && getLineStart(line+1) == end);
- }
-
- CharSequence text = mText;
- char ch;
- if (line == getLineCount() - 1) {
- return end;
- }
-
- for (; end > start; end--) {
- ch = text.charAt(end - 1);
-
- if (ch == '\n') {
- return end - 1;
- }
-
- if (ch != ' ' && ch != '\t') {
- break;
- }
-
- }
-
- return end;
- }
-
- /**
- * Return the vertical position of the bottom of the specified line.
- */
- public final int getLineBottom(int line) {
- return getLineTop(line + 1);
- }
-
- /**
- * Return the vertical position of the baseline of the specified line.
- */
- public final int getLineBaseline(int line) {
- // getLineTop(line+1) == getLineTop(line)
- return getLineTop(line+1) - getLineDescent(line);
- }
-
- /**
- * Get the ascent of the text on the specified line.
- * The return value is negative to match the Paint.ascent() convention.
- */
- public final int getLineAscent(int line) {
- // getLineTop(line+1) - getLineDescent(line) == getLineBaseLine(line)
- return getLineTop(line) - (getLineTop(line+1) - getLineDescent(line));
- }
-
- /**
- * Return the text offset that would be reached by moving left
- * (possibly onto another line) from the specified offset.
- */
- public int getOffsetToLeftOf(int offset) {
- int line = getLineForOffset(offset);
- int start = getLineStart(line);
- int end = getLineEnd(line);
- Directions dirs = getLineDirections(line);
-
- if (line != getLineCount() - 1)
- end--;
-
- float horiz = getPrimaryHorizontal(offset);
-
- int best = offset;
- float besth = Integer.MIN_VALUE;
- int candidate;
-
- candidate = TextUtils.getOffsetBefore(mText, offset);
- if (candidate >= start && candidate <= end) {
- float h = getPrimaryHorizontal(candidate);
-
- if (h < horiz && h > besth) {
- best = candidate;
- besth = h;
- }
- }
-
- candidate = TextUtils.getOffsetAfter(mText, offset);
- if (candidate >= start && candidate <= end) {
- float h = getPrimaryHorizontal(candidate);
-
- if (h < horiz && h > besth) {
- best = candidate;
- besth = h;
- }
- }
-
- int here = start;
- for (int i = 0; i < dirs.mDirections.length; i++) {
- int there = here + dirs.mDirections[i];
- if (there > end)
- there = end;
-
- float h = getPrimaryHorizontal(here);
-
- if (h < horiz && h > besth) {
- best = here;
- besth = h;
- }
-
- candidate = TextUtils.getOffsetAfter(mText, here);
- if (candidate >= start && candidate <= end) {
- h = getPrimaryHorizontal(candidate);
-
- if (h < horiz && h > besth) {
- best = candidate;
- besth = h;
- }
- }
-
- candidate = TextUtils.getOffsetBefore(mText, there);
- if (candidate >= start && candidate <= end) {
- h = getPrimaryHorizontal(candidate);
-
- if (h < horiz && h > besth) {
- best = candidate;
- besth = h;
- }
- }
-
- here = there;
- }
-
- float h = getPrimaryHorizontal(end);
-
- if (h < horiz && h > besth) {
- best = end;
- besth = h;
- }
-
- if (best != offset)
- return best;
-
- int dir = getParagraphDirection(line);
-
- if (dir > 0) {
- if (line == 0)
- return best;
- else
- return getOffsetForHorizontal(line - 1, 10000);
- } else {
- if (line == getLineCount() - 1)
- return best;
- else
- return getOffsetForHorizontal(line + 1, 10000);
- }
- }
-
- /**
- * Return the text offset that would be reached by moving right
- * (possibly onto another line) from the specified offset.
- */
- public int getOffsetToRightOf(int offset) {
- int line = getLineForOffset(offset);
- int start = getLineStart(line);
- int end = getLineEnd(line);
- Directions dirs = getLineDirections(line);
-
- if (line != getLineCount() - 1)
- end--;
-
- float horiz = getPrimaryHorizontal(offset);
-
- int best = offset;
- float besth = Integer.MAX_VALUE;
- int candidate;
-
- candidate = TextUtils.getOffsetBefore(mText, offset);
- if (candidate >= start && candidate <= end) {
- float h = getPrimaryHorizontal(candidate);
-
- if (h > horiz && h < besth) {
- best = candidate;
- besth = h;
- }
- }
-
- candidate = TextUtils.getOffsetAfter(mText, offset);
- if (candidate >= start && candidate <= end) {
- float h = getPrimaryHorizontal(candidate);
-
- if (h > horiz && h < besth) {
- best = candidate;
- besth = h;
- }
- }
-
- int here = start;
- for (int i = 0; i < dirs.mDirections.length; i++) {
- int there = here + dirs.mDirections[i];
- if (there > end)
- there = end;
-
- float h = getPrimaryHorizontal(here);
-
- if (h > horiz && h < besth) {
- best = here;
- besth = h;
- }
-
- candidate = TextUtils.getOffsetAfter(mText, here);
- if (candidate >= start && candidate <= end) {
- h = getPrimaryHorizontal(candidate);
-
- if (h > horiz && h < besth) {
- best = candidate;
- besth = h;
- }
- }
-
- candidate = TextUtils.getOffsetBefore(mText, there);
- if (candidate >= start && candidate <= end) {
- h = getPrimaryHorizontal(candidate);
-
- if (h > horiz && h < besth) {
- best = candidate;
- besth = h;
- }
- }
-
- here = there;
- }
-
- float h = getPrimaryHorizontal(end);
-
- if (h > horiz && h < besth) {
- best = end;
- besth = h;
- }
-
- if (best != offset)
- return best;
-
- int dir = getParagraphDirection(line);
-
- if (dir > 0) {
- if (line == getLineCount() - 1)
- return best;
- else
- return getOffsetForHorizontal(line + 1, -10000);
- } else {
- if (line == 0)
- return best;
- else
- return getOffsetForHorizontal(line - 1, -10000);
- }
- }
-
- private int getOffsetAtStartOf(int offset) {
- if (offset == 0)
- return 0;
-
- CharSequence text = mText;
- char c = text.charAt(offset);
-
- if (c >= '\uDC00' && c <= '\uDFFF') {
- char c1 = text.charAt(offset - 1);
-
- if (c1 >= '\uD800' && c1 <= '\uDBFF')
- offset -= 1;
- }
-
- if (mSpannedText) {
- ReplacementSpan[] spans = ((Spanned) text).getSpans(offset, offset,
- ReplacementSpan.class);
-
- for (int i = 0; i < spans.length; i++) {
- int start = ((Spanned) text).getSpanStart(spans[i]);
- int end = ((Spanned) text).getSpanEnd(spans[i]);
-
- if (start < offset && end > offset)
- offset = start;
- }
- }
-
- return offset;
- }
-
- /**
- * Fills in the specified Path with a representation of a cursor
- * at the specified offset. This will often be a vertical line
- * but can be multiple discontinous lines in text with multiple
- * directionalities.
- */
- public void getCursorPath(int point, Path dest,
- CharSequence editingBuffer) {
- dest.reset();
-
- int line = getLineForOffset(point);
- int top = getLineTop(line);
- int bottom = getLineTop(line+1);
-
- float h1 = getPrimaryHorizontal(point) - 0.5f;
- float h2 = getSecondaryHorizontal(point) - 0.5f;
-
- int caps = TextKeyListener.getMetaState(editingBuffer,
- KeyEvent.META_SHIFT_ON) |
- TextKeyListener.getMetaState(editingBuffer,
- TextKeyListener.META_SELECTING);
- int fn = TextKeyListener.getMetaState(editingBuffer,
- KeyEvent.META_ALT_ON);
- int dist = 0;
-
- if (caps != 0 || fn != 0) {
- dist = (bottom - top) >> 2;
-
- if (fn != 0)
- top += dist;
- if (caps != 0)
- bottom -= dist;
- }
-
- if (h1 < 0.5f)
- h1 = 0.5f;
- if (h2 < 0.5f)
- h2 = 0.5f;
-
- if (h1 == h2) {
- dest.moveTo(h1, top);
- dest.lineTo(h1, bottom);
- } else {
- dest.moveTo(h1, top);
- dest.lineTo(h1, (top + bottom) >> 1);
-
- dest.moveTo(h2, (top + bottom) >> 1);
- dest.lineTo(h2, bottom);
- }
-
- if (caps == 2) {
- dest.moveTo(h2, bottom);
- dest.lineTo(h2 - dist, bottom + dist);
- dest.lineTo(h2, bottom);
- dest.lineTo(h2 + dist, bottom + dist);
- } else if (caps == 1) {
- dest.moveTo(h2, bottom);
- dest.lineTo(h2 - dist, bottom + dist);
-
- dest.moveTo(h2 - dist, bottom + dist - 0.5f);
- dest.lineTo(h2 + dist, bottom + dist - 0.5f);
-
- dest.moveTo(h2 + dist, bottom + dist);
- dest.lineTo(h2, bottom);
- }
-
- if (fn == 2) {
- dest.moveTo(h1, top);
- dest.lineTo(h1 - dist, top - dist);
- dest.lineTo(h1, top);
- dest.lineTo(h1 + dist, top - dist);
- } else if (fn == 1) {
- dest.moveTo(h1, top);
- dest.lineTo(h1 - dist, top - dist);
-
- dest.moveTo(h1 - dist, top - dist + 0.5f);
- dest.lineTo(h1 + dist, top - dist + 0.5f);
-
- dest.moveTo(h1 + dist, top - dist);
- dest.lineTo(h1, top);
- }
- }
-
- private void addSelection(int line, int start, int end,
- int top, int bottom, Path dest) {
- int linestart = getLineStart(line);
- int lineend = getLineEnd(line);
- Directions dirs = getLineDirections(line);
-
- if (lineend > linestart && mText.charAt(lineend - 1) == '\n')
- lineend--;
-
- int here = linestart;
- for (int i = 0; i < dirs.mDirections.length; i++) {
- int there = here + dirs.mDirections[i];
- if (there > lineend)
- there = lineend;
-
- if (start <= there && end >= here) {
- int st = Math.max(start, here);
- int en = Math.min(end, there);
-
- if (st != en) {
- float h1 = getHorizontal(st, false, false, line);
- float h2 = getHorizontal(en, true, false, line);
-
- dest.addRect(h1, top, h2, bottom, Path.Direction.CW);
- }
- }
-
- here = there;
- }
- }
-
- /**
- * Fills in the specified Path with a representation of a highlight
- * between the specified offsets. This will often be a rectangle
- * or a potentially discontinuous set of rectangles. If the start
- * and end are the same, the returned path is empty.
- */
- public void getSelectionPath(int start, int end, Path dest) {
- dest.reset();
-
- if (start == end)
- return;
-
- if (end < start) {
- int temp = end;
- end = start;
- start = temp;
- }
-
- int startline = getLineForOffset(start);
- int endline = getLineForOffset(end);
-
- int top = getLineTop(startline);
- int bottom = getLineBottom(endline);
-
- if (startline == endline) {
- addSelection(startline, start, end, top, bottom, dest);
- } else {
- final float width = mWidth;
-
- addSelection(startline, start, getLineEnd(startline),
- top, getLineBottom(startline), dest);
-
- if (getParagraphDirection(startline) == DIR_RIGHT_TO_LEFT)
- dest.addRect(getLineLeft(startline), top,
- 0, getLineBottom(startline), Path.Direction.CW);
- else
- dest.addRect(getLineRight(startline), top,
- width, getLineBottom(startline), Path.Direction.CW);
-
- for (int i = startline + 1; i < endline; i++) {
- top = getLineTop(i);
- bottom = getLineBottom(i);
- dest.addRect(0, top, width, bottom, Path.Direction.CW);
- }
-
- top = getLineTop(endline);
- bottom = getLineBottom(endline);
-
- addSelection(endline, getLineStart(endline), end,
- top, bottom, dest);
-
- if (getParagraphDirection(endline) == DIR_RIGHT_TO_LEFT)
- dest.addRect(width, top, getLineRight(endline), bottom, Path.Direction.CW);
- else
- dest.addRect(0, top, getLineLeft(endline), bottom, Path.Direction.CW);
- }
- }
-
- /**
- * Get the alignment of the specified paragraph, taking into account
- * markup attached to it.
- */
- public final Alignment getParagraphAlignment(int line) {
- Alignment align = mAlignment;
-
- if (mSpannedText) {
- Spanned sp = (Spanned) mText;
- AlignmentSpan[] spans = sp.getSpans(getLineStart(line),
- getLineEnd(line),
- AlignmentSpan.class);
-
- int spanLength = spans.length;
- if (spanLength > 0) {
- align = spans[spanLength-1].getAlignment();
- }
- }
-
- return align;
- }
-
- /**
- * Get the left edge of the specified paragraph, inset by left margins.
- */
- public final int getParagraphLeft(int line) {
- int dir = getParagraphDirection(line);
-
- int left = 0;
-
- boolean par = false;
- int off = getLineStart(line);
- if (off == 0 || mText.charAt(off - 1) == '\n')
- par = true;
-
- if (dir == DIR_LEFT_TO_RIGHT) {
- if (mSpannedText) {
- Spanned sp = (Spanned) mText;
- LeadingMarginSpan[] spans = sp.getSpans(getLineStart(line),
- getLineEnd(line),
- LeadingMarginSpan.class);
-
- for (int i = 0; i < spans.length; i++) {
- left += spans[i].getLeadingMargin(par);
- }
- }
- }
-
- return left;
- }
-
- /**
- * Get the right edge of the specified paragraph, inset by right margins.
- */
- public final int getParagraphRight(int line) {
- int dir = getParagraphDirection(line);
-
- int right = mWidth;
-
- boolean par = false;
- int off = getLineStart(line);
- if (off == 0 || mText.charAt(off - 1) == '\n')
- par = true;
-
-
- if (dir == DIR_RIGHT_TO_LEFT) {
- if (mSpannedText) {
- Spanned sp = (Spanned) mText;
- LeadingMarginSpan[] spans = sp.getSpans(getLineStart(line),
- getLineEnd(line),
- LeadingMarginSpan.class);
-
- for (int i = 0; i < spans.length; i++) {
- right -= spans[i].getLeadingMargin(par);
- }
- }
- }
-
- return right;
- }
-
- private static void drawText(Canvas canvas,
- CharSequence text, int start, int end,
- int dir, Directions directions,
- float x, int top, int y, int bottom,
- TextPaint paint,
- TextPaint workPaint,
- boolean hasTabs, Object[] parspans) {
- char[] buf;
- if (!hasTabs) {
- if (directions == DIRS_ALL_LEFT_TO_RIGHT) {
- if (Config.DEBUG) {
- Assert.assertTrue(DIR_LEFT_TO_RIGHT == dir);
- }
- Styled.drawText(canvas, text, start, end, dir, false, x, top, y, bottom, paint, workPaint, false);
- return;
- }
- buf = null;
- } else {
- buf = TextUtils.obtain(end - start);
- TextUtils.getChars(text, start, end, buf, 0);
- }
-
- float h = 0;
-
- int here = 0;
- for (int i = 0; i < directions.mDirections.length; i++) {
- int there = here + directions.mDirections[i];
- if (there > end - start)
- there = end - start;
-
- int segstart = here;
- for (int j = hasTabs ? here : there; j <= there; j++) {
- if (j == there || buf[j] == '\t') {
- h += Styled.drawText(canvas, text,
- start + segstart, start + j,
- dir, (i & 1) != 0, x + h,
- top, y, bottom, paint, workPaint,
- start + j != end);
-
- if (j != there && buf[j] == '\t')
- h = dir * nextTab(text, start, end, h * dir, parspans);
-
- segstart = j + 1;
- }
- }
-
- here = there;
- }
-
- if (hasTabs)
- TextUtils.recycle(buf);
- }
-
- private static float measureText(TextPaint paint,
- TextPaint workPaint,
- CharSequence text,
- int start, int offset, int end,
- int dir, Directions directions,
- boolean trailing, boolean alt,
- boolean hasTabs, Object[] tabs) {
- char[] buf = null;
-
- if (hasTabs) {
- buf = TextUtils.obtain(end - start);
- TextUtils.getChars(text, start, end, buf, 0);
- }
-
- float h = 0;
-
- if (alt) {
- if (dir == DIR_RIGHT_TO_LEFT)
- trailing = !trailing;
- }
-
- int here = 0;
- for (int i = 0; i < directions.mDirections.length; i++) {
- if (alt)
- trailing = !trailing;
-
- int there = here + directions.mDirections[i];
- if (there > end - start)
- there = end - start;
-
- int segstart = here;
- for (int j = hasTabs ? here : there; j <= there; j++) {
- if (j == there || buf[j] == '\t') {
- float segw;
-
- if (offset < start + j ||
- (trailing && offset <= start + j)) {
- if (dir == DIR_LEFT_TO_RIGHT && (i & 1) == 0) {
- h += Styled.measureText(paint, workPaint, text,
- start + segstart, offset,
- null);
- return h;
- }
-
- if (dir == DIR_RIGHT_TO_LEFT && (i & 1) != 0) {
- h -= Styled.measureText(paint, workPaint, text,
- start + segstart, offset,
- null);
- return h;
- }
- }
-
- segw = Styled.measureText(paint, workPaint, text,
- start + segstart, start + j,
- null);
-
- if (offset < start + j ||
- (trailing && offset <= start + j)) {
- if (dir == DIR_LEFT_TO_RIGHT) {
- h += segw - Styled.measureText(paint, workPaint,
- text,
- start + segstart,
- offset, null);
- return h;
- }
-
- if (dir == DIR_RIGHT_TO_LEFT) {
- h -= segw - Styled.measureText(paint, workPaint,
- text,
- start + segstart,
- offset, null);
- return h;
- }
- }
-
- if (dir == DIR_RIGHT_TO_LEFT)
- h -= segw;
- else
- h += segw;
-
- if (j != there && buf[j] == '\t') {
- if (offset == start + j)
- return h;
-
- h = dir * nextTab(text, start, end, h * dir, tabs);
- }
-
- segstart = j + 1;
- }
- }
-
- here = there;
- }
-
- if (hasTabs)
- TextUtils.recycle(buf);
-
- return h;
- }
-
- /* package */ static float measureText(TextPaint paint,
- TextPaint workPaint,
- CharSequence text,
- int start, int end,
- Paint.FontMetricsInt fm,
- boolean hasTabs, Object[] tabs) {
- char[] buf = null;
-
- if (hasTabs) {
- buf = TextUtils.obtain(end - start);
- TextUtils.getChars(text, start, end, buf, 0);
- }
-
- int len = end - start;
-
- int here = 0;
- float h = 0;
- int ab = 0, be = 0;
- int top = 0, bot = 0;
-
- if (fm != null) {
- fm.ascent = 0;
- fm.descent = 0;
- }
-
- for (int i = hasTabs ? 0 : len; i <= len; i++) {
- if (i == len || buf[i] == '\t') {
- workPaint.baselineShift = 0;
-
- h += Styled.measureText(paint, workPaint, text,
- start + here, start + i,
- fm);
-
- if (fm != null) {
- if (workPaint.baselineShift < 0) {
- fm.ascent += workPaint.baselineShift;
- fm.top += workPaint.baselineShift;
- } else {
- fm.descent += workPaint.baselineShift;
- fm.bottom += workPaint.baselineShift;
- }
- }
-
- if (i != len)
- h = nextTab(text, start, end, h, tabs);
-
- if (fm != null) {
- if (fm.ascent < ab) {
- ab = fm.ascent;
- }
- if (fm.descent > be) {
- be = fm.descent;
- }
-
- if (fm.top < top) {
- top = fm.top;
- }
- if (fm.bottom > bot) {
- bot = fm.bottom;
- }
- }
-
- here = i + 1;
- }
- }
-
- if (fm != null) {
- fm.ascent = ab;
- fm.descent = be;
- fm.top = top;
- fm.bottom = bot;
- }
-
- if (hasTabs)
- TextUtils.recycle(buf);
-
- return h;
- }
-
- /* package */ static float nextTab(CharSequence text, int start, int end,
- float h, Object[] tabs) {
- float nh = Float.MAX_VALUE;
- boolean alltabs = false;
-
- if (text instanceof Spanned) {
- if (tabs == null) {
- tabs = ((Spanned) text).getSpans(start, end, TabStopSpan.class);
- alltabs = true;
- }
-
- for (int i = 0; i < tabs.length; i++) {
- if (!alltabs) {
- if (!(tabs[i] instanceof TabStopSpan))
- continue;
- }
-
- int where = ((TabStopSpan) tabs[i]).getTabStop();
-
- if (where < nh && where > h)
- nh = where;
- }
-
- if (nh != Float.MAX_VALUE)
- return nh;
- }
-
- return ((int) ((h + TAB_INCREMENT) / TAB_INCREMENT)) * TAB_INCREMENT;
- }
-
- protected final boolean isSpanned() {
- return mSpannedText;
- }
-
- private void ellipsize(int start, int end, int line,
- char[] dest, int destoff) {
- int ellipsisCount = getEllipsisCount(line);
-
- if (ellipsisCount == 0) {
- return;
- }
-
- int ellipsisStart = getEllipsisStart(line);
- int linestart = getLineStart(line);
-
- for (int i = ellipsisStart; i < ellipsisStart + ellipsisCount; i++) {
- char c;
-
- if (i == ellipsisStart) {
- c = '\u2026'; // ellipsis
- } else {
- c = '\uFEFF'; // 0-width space
- }
-
- int a = i + linestart;
-
- if (a >= start && a < end) {
- dest[destoff + a - start] = c;
- }
- }
- }
-
- /**
- * Stores information about bidirectional (left-to-right or right-to-left)
- * text within the layout of a line. TODO: This work is not complete
- * or correct and will be fleshed out in a later revision.
- */
- public static class Directions {
- private short[] mDirections;
-
- /* package */ Directions(short[] dirs) {
- mDirections = dirs;
- }
- }
-
- /**
- * Return the offset of the first character to be ellipsized away,
- * relative to the start of the line. (So 0 if the beginning of the
- * line is ellipsized, not getLineStart().)
- */
- public abstract int getEllipsisStart(int line);
- /**
- * Returns the number of characters to be ellipsized away, or 0 if
- * no ellipsis is to take place.
- */
- public abstract int getEllipsisCount(int line);
-
- /* package */ static class Ellipsizer implements CharSequence, GetChars {
- /* package */ CharSequence mText;
- /* package */ Layout mLayout;
- /* package */ int mWidth;
- /* package */ TextUtils.TruncateAt mMethod;
-
- public Ellipsizer(CharSequence s) {
- mText = s;
- }
-
- public char charAt(int off) {
- char[] buf = TextUtils.obtain(1);
- getChars(off, off + 1, buf, 0);
- char ret = buf[0];
-
- TextUtils.recycle(buf);
- return ret;
- }
-
- public void getChars(int start, int end, char[] dest, int destoff) {
- int line1 = mLayout.getLineForOffset(start);
- int line2 = mLayout.getLineForOffset(end);
-
- TextUtils.getChars(mText, start, end, dest, destoff);
-
- for (int i = line1; i <= line2; i++) {
- mLayout.ellipsize(start, end, i, dest, destoff);
- }
- }
-
- public int length() {
- return mText.length();
- }
-
- public CharSequence subSequence(int start, int end) {
- char[] s = new char[end - start];
- getChars(start, end, s, 0);
- return new String(s);
- }
-
- public String toString() {
- char[] s = new char[length()];
- getChars(0, length(), s, 0);
- return new String(s);
- }
-
- }
-
- /* package */ static class SpannedEllipsizer
- extends Ellipsizer implements Spanned {
- private Spanned mSpanned;
-
- public SpannedEllipsizer(CharSequence display) {
- super(display);
- mSpanned = (Spanned) display;
- }
-
- public <T> T[] getSpans(int start, int end, Class<T> type) {
- return mSpanned.getSpans(start, end, type);
- }
-
- public int getSpanStart(Object tag) {
- return mSpanned.getSpanStart(tag);
- }
-
- public int getSpanEnd(Object tag) {
- return mSpanned.getSpanEnd(tag);
- }
-
- public int getSpanFlags(Object tag) {
- return mSpanned.getSpanFlags(tag);
- }
-
- public int nextSpanTransition(int start, int limit, Class type) {
- return mSpanned.nextSpanTransition(start, limit, type);
- }
-
- public CharSequence subSequence(int start, int end) {
- char[] s = new char[end - start];
- getChars(start, end, s, 0);
-
- SpannableString ss = new SpannableString(new String(s));
- TextUtils.copySpansFrom(mSpanned, start, end, Object.class, ss, 0);
- return ss;
- }
- }
-
- private CharSequence mText;
- private TextPaint mPaint;
- /* package */ TextPaint mWorkPaint;
- private int mWidth;
- private Alignment mAlignment = Alignment.ALIGN_NORMAL;
- private float mSpacingMult;
- private float mSpacingAdd;
- private static Rect sTempRect = new Rect();
- private boolean mSpannedText;
-
- public static final int DIR_LEFT_TO_RIGHT = 1;
- public static final int DIR_RIGHT_TO_LEFT = -1;
-
- public enum Alignment {
- ALIGN_NORMAL,
- ALIGN_OPPOSITE,
- ALIGN_CENTER,
- // XXX ALIGN_LEFT,
- // XXX ALIGN_RIGHT,
- }
-
- private static final int TAB_INCREMENT = 20;
-
- /* package */ static final Directions DIRS_ALL_LEFT_TO_RIGHT =
- new Directions(new short[] { 32767 });
- /* package */ static final Directions DIRS_ALL_RIGHT_TO_LEFT =
- new Directions(new short[] { 0, 32767 });
-
-}
-
diff --git a/core/java/android/text/LoginFilter.java b/core/java/android/text/LoginFilter.java
deleted file mode 100644
index 27c703f..0000000
--- a/core/java/android/text/LoginFilter.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-/**
- * Abstract class for filtering login-related text (user names and passwords)
- *
- */
-public abstract class LoginFilter implements InputFilter {
- private boolean mAppendInvalid; // whether to append or ignore invalid characters
- /**
- * Base constructor for LoginFilter
- * @param appendInvalid whether or not to append invalid characters.
- */
- LoginFilter(boolean appendInvalid) {
- mAppendInvalid = appendInvalid;
- }
-
- /**
- * Default constructor for LoginFilter doesn't append invalid characters.
- */
- LoginFilter() {
- mAppendInvalid = false;
- }
-
- /**
- * This method is called when the buffer is going to replace the
- * range <code>dstart &hellip; dend</code> of <code>dest</code>
- * with the new text from the range <code>start &hellip; end</code>
- * of <code>source</code>. Returns the CharSequence that we want
- * placed there instead, including an empty string
- * if appropriate, or <code>null</code> to accept the original
- * replacement. Be careful to not to reject 0-length replacements,
- * as this is what happens when you delete text.
- */
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
- char[] out = new char[end - start]; // reserve enough space for whole string
- int outidx = 0;
- boolean changed = false;
-
- onStart();
-
- // Scan through beginning characters in dest, calling onInvalidCharacter()
- // for each invalid character.
- for (int i = 0; i < dstart; i++) {
- char c = dest.charAt(i);
- if (!isAllowed(c)) onInvalidCharacter(c);
- }
-
- // Scan through changed characters rejecting disallowed chars
- for (int i = start; i < end; i++) {
- char c = source.charAt(i);
- if (isAllowed(c)) {
- // Character allowed. Add it to the sequence.
- out[outidx++] = c;
- } else {
- if (mAppendInvalid) out[outidx++] = c;
- else changed = true; // we changed the original string
- onInvalidCharacter(c);
- }
- }
-
- // Scan through remaining characters in dest, calling onInvalidCharacter()
- // for each invalid character.
- for (int i = dend; i < dest.length(); i++) {
- char c = dest.charAt(i);
- if (!isAllowed(c)) onInvalidCharacter(c);
- }
-
- onStop();
-
- if (!changed) {
- return null;
- }
-
- String s = new String(out, 0, outidx);
-
- if (source instanceof Spanned) {
- SpannableString sp = new SpannableString(s);
- TextUtils.copySpansFrom((Spanned) source,
- start, end, null, sp, 0);
- return sp;
- } else {
- return s;
- }
- }
-
- /**
- * Called when we start processing filter.
- */
- public void onStart() {
-
- }
-
- /**
- * Called whenever we encounter an invalid character.
- * @param c the invalid character
- */
- public void onInvalidCharacter(char c) {
-
- }
-
- /**
- * Called when we're done processing filter
- */
- public void onStop() {
-
- }
-
- /**
- * Returns whether or not we allow character c.
- * Subclasses must override this method.
- */
- public abstract boolean isAllowed(char c);
-
- /**
- * This filter rejects characters in the user name that are not compatible with GMail
- * account creation. It prevents the user from entering user names with characters other than
- * [a-zA-Z0-9.].
- *
- */
- public static class UsernameFilterGMail extends LoginFilter {
-
- public UsernameFilterGMail() {
- super(false);
- }
-
- public UsernameFilterGMail(boolean appendInvalid) {
- super(appendInvalid);
- }
-
- @Override
- public boolean isAllowed(char c) {
- // Allow [a-zA-Z0-9@.]
- if ('0' <= c && c <= '9')
- return true;
- if ('a' <= c && c <= 'z')
- return true;
- if ('A' <= c && c <= 'Z')
- return true;
- if ('.' == c)
- return true;
- return false;
- }
- }
-
- /**
- * This filter rejects characters in the user name that are not compatible with Google login.
- * It is slightly less restrictive than the above filter in that it allows [a-zA-Z0-9._-].
- *
- */
- public static class UsernameFilterGeneric extends LoginFilter {
- private static final String mAllowed = "@_-."; // Additional characters
-
- public UsernameFilterGeneric() {
- super(false);
- }
-
- public UsernameFilterGeneric(boolean appendInvalid) {
- super(appendInvalid);
- }
-
- @Override
- public boolean isAllowed(char c) {
- // Allow [a-zA-Z0-9@.]
- if ('0' <= c && c <= '9')
- return true;
- if ('a' <= c && c <= 'z')
- return true;
- if ('A' <= c && c <= 'Z')
- return true;
- if (mAllowed.indexOf(c) != -1)
- return true;
- return false;
- }
- }
-
- /**
- * This filter is compatible with GMail passwords which restricts characters to
- * the Latin-1 (ISO8859-1) char set.
- *
- */
- public static class PasswordFilterGMail extends LoginFilter {
-
- public PasswordFilterGMail() {
- super(false);
- }
-
- public PasswordFilterGMail(boolean appendInvalid) {
- super(appendInvalid);
- }
-
- // We should reject anything not in the Latin-1 (ISO8859-1) charset
- @Override
- public boolean isAllowed(char c) {
- if (32 <= c && c <= 127)
- return true; // standard charset
- // if (128 <= c && c <= 159) return true; // nonstandard (Windows(TM)(R)) charset
- if (160 <= c && c <= 255)
- return true; // extended charset
- return false;
- }
- }
-}
diff --git a/core/java/android/text/NoCopySpan.java b/core/java/android/text/NoCopySpan.java
deleted file mode 100644
index 0855c0b..0000000
--- a/core/java/android/text/NoCopySpan.java
+++ /dev/null
@@ -1,31 +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 android.text;
-
-/**
- * This interface should be added to a span object that should not be copied
- * into a new Spenned when performing a slice or copy operation on the original
- * Spanned it was placed in.
- */
-public interface NoCopySpan {
- /**
- * Convenience equivalent for when you would just want a new Object() for
- * a span but want it to be no-copy. Use this instead.
- */
- public class Concrete implements NoCopySpan {
- }
-}
diff --git a/core/java/android/text/PackedIntVector.java b/core/java/android/text/PackedIntVector.java
deleted file mode 100644
index d87f600..0000000
--- a/core/java/android/text/PackedIntVector.java
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.text;
-
-import com.android.internal.util.ArrayUtils;
-
-
-/**
- * PackedIntVector stores a two-dimensional array of integers,
- * optimized for inserting and deleting rows and for
- * offsetting the values in segments of a given column.
- */
-class PackedIntVector {
- private final int mColumns;
- private int mRows;
-
- private int mRowGapStart;
- private int mRowGapLength;
-
- private int[] mValues;
- private int[] mValueGap; // starts, followed by lengths
-
- /**
- * Creates a new PackedIntVector with the specified width and
- * a height of 0.
- *
- * @param columns the width of the PackedIntVector.
- */
- public PackedIntVector(int columns) {
- mColumns = columns;
- mRows = 0;
-
- mRowGapStart = 0;
- mRowGapLength = mRows;
-
- mValues = null;
- mValueGap = new int[2 * columns];
- }
-
- /**
- * Returns the value at the specified row and column.
- *
- * @param row the index of the row to return.
- * @param column the index of the column to return.
- *
- * @return the value stored at the specified position.
- *
- * @throws IndexOutOfBoundsException if the row is out of range
- * (row &lt; 0 || row >= size()) or the column is out of range
- * (column &lt; 0 || column >= width()).
- */
- public int getValue(int row, int column) {
- final int columns = mColumns;
-
- if (((row | column) < 0) || (row >= size()) || (column >= columns)) {
- throw new IndexOutOfBoundsException(row + ", " + column);
- }
-
- if (row >= mRowGapStart) {
- row += mRowGapLength;
- }
-
- int value = mValues[row * columns + column];
-
- int[] valuegap = mValueGap;
- if (row >= valuegap[column]) {
- value += valuegap[column + columns];
- }
-
- return value;
- }
-
- /**
- * Sets the value at the specified row and column.
- *
- * @param row the index of the row to set.
- * @param column the index of the column to set.
- *
- * @throws IndexOutOfBoundsException if the row is out of range
- * (row &lt; 0 || row >= size()) or the column is out of range
- * (column &lt; 0 || column >= width()).
- */
- public void setValue(int row, int column, int value) {
- if (((row | column) < 0) || (row >= size()) || (column >= mColumns)) {
- throw new IndexOutOfBoundsException(row + ", " + column);
- }
-
- if (row >= mRowGapStart) {
- row += mRowGapLength;
- }
-
- int[] valuegap = mValueGap;
- if (row >= valuegap[column]) {
- value -= valuegap[column + mColumns];
- }
-
- mValues[row * mColumns + column] = value;
- }
-
- /**
- * Sets the value at the specified row and column.
- * Private internal version: does not check args.
- *
- * @param row the index of the row to set.
- * @param column the index of the column to set.
- *
- */
- private void setValueInternal(int row, int column, int value) {
- if (row >= mRowGapStart) {
- row += mRowGapLength;
- }
-
- int[] valuegap = mValueGap;
- if (row >= valuegap[column]) {
- value -= valuegap[column + mColumns];
- }
-
- mValues[row * mColumns + column] = value;
- }
-
-
- /**
- * Increments all values in the specified column whose row >= the
- * specified row by the specified delta.
- *
- * @param startRow the row at which to begin incrementing.
- * This may be == size(), which case there is no effect.
- * @param column the index of the column to set.
- *
- * @throws IndexOutOfBoundsException if the row is out of range
- * (startRow &lt; 0 || startRow > size()) or the column
- * is out of range (column &lt; 0 || column >= width()).
- */
- public void adjustValuesBelow(int startRow, int column, int delta) {
- if (((startRow | column) < 0) || (startRow > size()) ||
- (column >= width())) {
- throw new IndexOutOfBoundsException(startRow + ", " + column);
- }
-
- if (startRow >= mRowGapStart) {
- startRow += mRowGapLength;
- }
-
- moveValueGapTo(column, startRow);
- mValueGap[column + mColumns] += delta;
- }
-
- /**
- * Inserts a new row of values at the specified row offset.
- *
- * @param row the row above which to insert the new row.
- * This may be == size(), which case the new row is added
- * at the end.
- * @param values the new values to be added. If this is null,
- * a row of zeroes is added.
- *
- * @throws IndexOutOfBoundsException if the row is out of range
- * (row &lt; 0 || row > size()) or if the length of the
- * values array is too small (values.length < width()).
- */
- public void insertAt(int row, int[] values) {
- if ((row < 0) || (row > size())) {
- throw new IndexOutOfBoundsException("row " + row);
- }
-
- if ((values != null) && (values.length < width())) {
- throw new IndexOutOfBoundsException("value count " + values.length);
- }
-
- moveRowGapTo(row);
-
- if (mRowGapLength == 0) {
- growBuffer();
- }
-
- mRowGapStart++;
- mRowGapLength--;
-
- if (values == null) {
- for (int i = mColumns - 1; i >= 0; i--) {
- setValueInternal(row, i, 0);
- }
- } else {
- for (int i = mColumns - 1; i >= 0; i--) {
- setValueInternal(row, i, values[i]);
- }
- }
- }
-
- /**
- * Deletes the specified number of rows starting with the specified
- * row.
- *
- * @param row the index of the first row to be deleted.
- * @param count the number of rows to delete.
- *
- * @throws IndexOutOfBoundsException if any of the rows to be deleted
- * are out of range (row &lt; 0 || count &lt; 0 ||
- * row + count > size()).
- */
- public void deleteAt(int row, int count) {
- if (((row | count) < 0) || (row + count > size())) {
- throw new IndexOutOfBoundsException(row + ", " + count);
- }
-
- moveRowGapTo(row + count);
-
- mRowGapStart -= count;
- mRowGapLength += count;
-
- // TODO: Reclaim memory when the new height is much smaller
- // than the allocated size.
- }
-
- /**
- * Returns the number of rows in the PackedIntVector. This number
- * will change as rows are inserted and deleted.
- *
- * @return the number of rows.
- */
- public int size() {
- return mRows - mRowGapLength;
- }
-
- /**
- * Returns the width of the PackedIntVector. This number is set
- * at construction and will not change.
- *
- * @return the number of columns.
- */
- public int width() {
- return mColumns;
- }
-
- /**
- * Grows the value and gap arrays to be large enough to store at least
- * one more than the current number of rows.
- */
- private final void growBuffer() {
- final int columns = mColumns;
- int newsize = size() + 1;
- newsize = ArrayUtils.idealIntArraySize(newsize * columns) / columns;
- int[] newvalues = new int[newsize * columns];
-
- final int[] valuegap = mValueGap;
- final int rowgapstart = mRowGapStart;
-
- int after = mRows - (rowgapstart + mRowGapLength);
-
- if (mValues != null) {
- System.arraycopy(mValues, 0, newvalues, 0, columns * rowgapstart);
- System.arraycopy(mValues, (mRows - after) * columns,
- newvalues, (newsize - after) * columns,
- after * columns);
- }
-
- for (int i = 0; i < columns; i++) {
- if (valuegap[i] >= rowgapstart) {
- valuegap[i] += newsize - mRows;
-
- if (valuegap[i] < rowgapstart) {
- valuegap[i] = rowgapstart;
- }
- }
- }
-
- mRowGapLength += newsize - mRows;
- mRows = newsize;
- mValues = newvalues;
- }
-
- /**
- * Moves the gap in the values of the specified column to begin at
- * the specified row.
- */
- private final void moveValueGapTo(int column, int where) {
- final int[] valuegap = mValueGap;
- final int[] values = mValues;
- final int columns = mColumns;
-
- if (where == valuegap[column]) {
- return;
- } else if (where > valuegap[column]) {
- for (int i = valuegap[column]; i < where; i++) {
- values[i * columns + column] += valuegap[column + columns];
- }
- } else /* where < valuegap[column] */ {
- for (int i = where; i < valuegap[column]; i++) {
- values[i * columns + column] -= valuegap[column + columns];
- }
- }
-
- valuegap[column] = where;
- }
-
- /**
- * Moves the gap in the row indices to begin at the specified row.
- */
- private final void moveRowGapTo(int where) {
- if (where == mRowGapStart) {
- return;
- } else if (where > mRowGapStart) {
- int moving = where + mRowGapLength - (mRowGapStart + mRowGapLength);
- final int columns = mColumns;
- final int[] valuegap = mValueGap;
- final int[] values = mValues;
- final int gapend = mRowGapStart + mRowGapLength;
-
- for (int i = gapend; i < gapend + moving; i++) {
- int destrow = i - gapend + mRowGapStart;
-
- for (int j = 0; j < columns; j++) {
- int val = values[i * columns+ j];
-
- if (i >= valuegap[j]) {
- val += valuegap[j + columns];
- }
-
- if (destrow >= valuegap[j]) {
- val -= valuegap[j + columns];
- }
-
- values[destrow * columns + j] = val;
- }
- }
- } else /* where < mRowGapStart */ {
- int moving = mRowGapStart - where;
- final int columns = mColumns;
- final int[] valuegap = mValueGap;
- final int[] values = mValues;
- final int gapend = mRowGapStart + mRowGapLength;
-
- for (int i = where + moving - 1; i >= where; i--) {
- int destrow = i - where + gapend - moving;
-
- for (int j = 0; j < columns; j++) {
- int val = values[i * columns+ j];
-
- if (i >= valuegap[j]) {
- val += valuegap[j + columns];
- }
-
- if (destrow >= valuegap[j]) {
- val -= valuegap[j + columns];
- }
-
- values[destrow * columns + j] = val;
- }
- }
- }
-
- mRowGapStart = where;
- }
-}
diff --git a/core/java/android/text/PackedObjectVector.java b/core/java/android/text/PackedObjectVector.java
deleted file mode 100644
index a29df09..0000000
--- a/core/java/android/text/PackedObjectVector.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-import com.android.internal.util.ArrayUtils;
-
-class PackedObjectVector<E>
-{
- private int mColumns;
- private int mRows;
-
- private int mRowGapStart;
- private int mRowGapLength;
-
- private Object[] mValues;
-
- public
- PackedObjectVector(int columns)
- {
- mColumns = columns;
- mRows = ArrayUtils.idealIntArraySize(0) / mColumns;
-
- mRowGapStart = 0;
- mRowGapLength = mRows;
-
- mValues = new Object[mRows * mColumns];
- }
-
- public E
- getValue(int row, int column)
- {
- if (row >= mRowGapStart)
- row += mRowGapLength;
-
- Object value = mValues[row * mColumns + column];
-
- return (E) value;
- }
-
- public void
- setValue(int row, int column, E value)
- {
- if (row >= mRowGapStart)
- row += mRowGapLength;
-
- mValues[row * mColumns + column] = value;
- }
-
- public void
- insertAt(int row, E[] values)
- {
- moveRowGapTo(row);
-
- if (mRowGapLength == 0)
- growBuffer();
-
- mRowGapStart++;
- mRowGapLength--;
-
- if (values == null)
- for (int i = 0; i < mColumns; i++)
- setValue(row, i, null);
- else
- for (int i = 0; i < mColumns; i++)
- setValue(row, i, values[i]);
- }
-
- public void
- deleteAt(int row, int count)
- {
- moveRowGapTo(row + count);
-
- mRowGapStart -= count;
- mRowGapLength += count;
-
- if (mRowGapLength > size() * 2)
- {
- // dump();
- // growBuffer();
- }
- }
-
- public int
- size()
- {
- return mRows - mRowGapLength;
- }
-
- public int
- width()
- {
- return mColumns;
- }
-
- private void
- growBuffer()
- {
- int newsize = size() + 1;
- newsize = ArrayUtils.idealIntArraySize(newsize * mColumns) / mColumns;
- Object[] newvalues = new Object[newsize * mColumns];
-
- int after = mRows - (mRowGapStart + mRowGapLength);
-
- System.arraycopy(mValues, 0, newvalues, 0, mColumns * mRowGapStart);
- System.arraycopy(mValues, (mRows - after) * mColumns, newvalues, (newsize - after) * mColumns, after * mColumns);
-
- mRowGapLength += newsize - mRows;
- mRows = newsize;
- mValues = newvalues;
- }
-
- private void
- moveRowGapTo(int where)
- {
- if (where == mRowGapStart)
- return;
-
- if (where > mRowGapStart)
- {
- int moving = where + mRowGapLength - (mRowGapStart + mRowGapLength);
-
- for (int i = mRowGapStart + mRowGapLength; i < mRowGapStart + mRowGapLength + moving; i++)
- {
- int destrow = i - (mRowGapStart + mRowGapLength) + mRowGapStart;
-
- for (int j = 0; j < mColumns; j++)
- {
- Object val = mValues[i * mColumns + j];
-
- mValues[destrow * mColumns + j] = val;
- }
- }
- }
- else /* where < mRowGapStart */
- {
- int moving = mRowGapStart - where;
-
- for (int i = where + moving - 1; i >= where; i--)
- {
- int destrow = i - where + mRowGapStart + mRowGapLength - moving;
-
- for (int j = 0; j < mColumns; j++)
- {
- Object val = mValues[i * mColumns + j];
-
- mValues[destrow * mColumns + j] = val;
- }
- }
- }
-
- mRowGapStart = where;
- }
-
- public void // XXX
- dump()
- {
- for (int i = 0; i < mRows; i++)
- {
- for (int j = 0; j < mColumns; j++)
- {
- Object val = mValues[i * mColumns + j];
-
- if (i < mRowGapStart || i >= mRowGapStart + mRowGapLength)
- System.out.print(val + " ");
- else
- System.out.print("(" + val + ") ");
- }
-
- System.out.print(" << \n");
- }
-
- System.out.print("-----\n\n");
- }
-}
diff --git a/core/java/android/text/ParcelableSpan.java b/core/java/android/text/ParcelableSpan.java
deleted file mode 100644
index 224511a..0000000
--- a/core/java/android/text/ParcelableSpan.java
+++ /dev/null
@@ -1,31 +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 android.text;
-
-import android.os.Parcelable;
-
-/**
- * A special kind of Parcelable for objects that will serve as text spans.
- * This can only be used by code in the framework; it is not intended for
- * applications to implement their own Parcelable spans.
- */
-public interface ParcelableSpan extends Parcelable {
- /**
- * Return a special type identifier for this span class.
- */
- public abstract int getSpanTypeId();
-}
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
deleted file mode 100644
index bb98bce..0000000
--- a/core/java/android/text/Selection.java
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-
-/**
- * Utility class for manipulating cursors and selections in CharSequences.
- * A cursor is a selection where the start and end are at the same offset.
- */
-public class Selection {
- private Selection() { /* cannot be instantiated */ }
-
- /*
- * Retrieving the selection
- */
-
- /**
- * Return the offset of the selection anchor or cursor, or -1 if
- * there is no selection or cursor.
- */
- public static final int getSelectionStart(CharSequence text) {
- if (text instanceof Spanned)
- return ((Spanned) text).getSpanStart(SELECTION_START);
- else
- return -1;
- }
-
- /**
- * Return the offset of the selection edge or cursor, or -1 if
- * there is no selection or cursor.
- */
- public static final int getSelectionEnd(CharSequence text) {
- if (text instanceof Spanned)
- return ((Spanned) text).getSpanStart(SELECTION_END);
- else
- return -1;
- }
-
- /*
- * Setting the selection
- */
-
- // private static int pin(int value, int min, int max) {
- // return value < min ? 0 : (value > max ? max : value);
- // }
-
- /**
- * Set the selection anchor to <code>start</code> and the selection edge
- * to <code>stop</code>.
- */
- public static void setSelection(Spannable text, int start, int stop) {
- // int len = text.length();
- // start = pin(start, 0, len); XXX remove unless we really need it
- // stop = pin(stop, 0, len);
-
- int ostart = getSelectionStart(text);
- int oend = getSelectionEnd(text);
-
- if (ostart != start || oend != stop) {
- text.setSpan(SELECTION_START, start, start,
- Spanned.SPAN_POINT_POINT|Spanned.SPAN_INTERMEDIATE);
- text.setSpan(SELECTION_END, stop, stop,
- Spanned.SPAN_POINT_POINT);
- }
- }
-
- /**
- * Move the cursor to offset <code>index</code>.
- */
- public static final void setSelection(Spannable text, int index) {
- setSelection(text, index, index);
- }
-
- /**
- * Select the entire text.
- */
- public static final void selectAll(Spannable text) {
- setSelection(text, 0, text.length());
- }
-
- /**
- * Move the selection edge to offset <code>index</code>.
- */
- public static final void extendSelection(Spannable text, int index) {
- if (text.getSpanStart(SELECTION_END) != index)
- text.setSpan(SELECTION_END, index, index, Spanned.SPAN_POINT_POINT);
- }
-
- /**
- * Remove the selection or cursor, if any, from the text.
- */
- public static final void removeSelection(Spannable text) {
- text.removeSpan(SELECTION_START);
- text.removeSpan(SELECTION_END);
- }
-
- /*
- * Moving the selection within the layout
- */
-
- /**
- * Move the cursor to the buffer offset physically above the current
- * offset, or return false if the cursor is already on the top line.
- */
- public static boolean moveUp(Spannable text, Layout layout) {
- int start = getSelectionStart(text);
- int end = getSelectionEnd(text);
-
- if (start != end) {
- int min = Math.min(start, end);
- int max = Math.max(start, end);
-
- setSelection(text, min);
-
- if (min == 0 && max == text.length()) {
- return false;
- }
-
- return true;
- } else {
- int line = layout.getLineForOffset(end);
-
- if (line > 0) {
- int move;
-
- if (layout.getParagraphDirection(line) ==
- layout.getParagraphDirection(line - 1)) {
- float h = layout.getPrimaryHorizontal(end);
- move = layout.getOffsetForHorizontal(line - 1, h);
- } else {
- move = layout.getLineStart(line - 1);
- }
-
- setSelection(text, move);
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Move the cursor to the buffer offset physically below the current
- * offset, or return false if the cursor is already on the bottom line.
- */
- public static boolean moveDown(Spannable text, Layout layout) {
- int start = getSelectionStart(text);
- int end = getSelectionEnd(text);
-
- if (start != end) {
- int min = Math.min(start, end);
- int max = Math.max(start, end);
-
- setSelection(text, max);
-
- if (min == 0 && max == text.length()) {
- return false;
- }
-
- return true;
- } else {
- int line = layout.getLineForOffset(end);
-
- if (line < layout.getLineCount() - 1) {
- int move;
-
- if (layout.getParagraphDirection(line) ==
- layout.getParagraphDirection(line + 1)) {
- float h = layout.getPrimaryHorizontal(end);
- move = layout.getOffsetForHorizontal(line + 1, h);
- } else {
- move = layout.getLineStart(line + 1);
- }
-
- setSelection(text, move);
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Move the cursor to the buffer offset physically to the left of
- * the current offset, or return false if the cursor is already
- * at the left edge of the line and there is not another line to move it to.
- */
- public static boolean moveLeft(Spannable text, Layout layout) {
- int start = getSelectionStart(text);
- int end = getSelectionEnd(text);
-
- if (start != end) {
- setSelection(text, chooseHorizontal(layout, -1, start, end));
- return true;
- } else {
- int to = layout.getOffsetToLeftOf(end);
-
- if (to != end) {
- setSelection(text, to);
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Move the cursor to the buffer offset physically to the right of
- * the current offset, or return false if the cursor is already at
- * at the right edge of the line and there is not another line
- * to move it to.
- */
- public static boolean moveRight(Spannable text, Layout layout) {
- int start = getSelectionStart(text);
- int end = getSelectionEnd(text);
-
- if (start != end) {
- setSelection(text, chooseHorizontal(layout, 1, start, end));
- return true;
- } else {
- int to = layout.getOffsetToRightOf(end);
-
- if (to != end) {
- setSelection(text, to);
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Move the selection end to the buffer offset physically above
- * the current selection end.
- */
- public static boolean extendUp(Spannable text, Layout layout) {
- int end = getSelectionEnd(text);
- int line = layout.getLineForOffset(end);
-
- if (line > 0) {
- int move;
-
- if (layout.getParagraphDirection(line) ==
- layout.getParagraphDirection(line - 1)) {
- float h = layout.getPrimaryHorizontal(end);
- move = layout.getOffsetForHorizontal(line - 1, h);
- } else {
- move = layout.getLineStart(line - 1);
- }
-
- extendSelection(text, move);
- return true;
- } else if (end != 0) {
- extendSelection(text, 0);
- return true;
- }
-
- return true;
- }
-
- /**
- * Move the selection end to the buffer offset physically below
- * the current selection end.
- */
- public static boolean extendDown(Spannable text, Layout layout) {
- int end = getSelectionEnd(text);
- int line = layout.getLineForOffset(end);
-
- if (line < layout.getLineCount() - 1) {
- int move;
-
- if (layout.getParagraphDirection(line) ==
- layout.getParagraphDirection(line + 1)) {
- float h = layout.getPrimaryHorizontal(end);
- move = layout.getOffsetForHorizontal(line + 1, h);
- } else {
- move = layout.getLineStart(line + 1);
- }
-
- extendSelection(text, move);
- return true;
- } else if (end != text.length()) {
- extendSelection(text, text.length());
- return true;
- }
-
- return true;
- }
-
- /**
- * Move the selection end to the buffer offset physically to the left of
- * the current selection end.
- */
- public static boolean extendLeft(Spannable text, Layout layout) {
- int end = getSelectionEnd(text);
- int to = layout.getOffsetToLeftOf(end);
-
- if (to != end) {
- extendSelection(text, to);
- return true;
- }
-
- return true;
- }
-
- /**
- * Move the selection end to the buffer offset physically to the right of
- * the current selection end.
- */
- public static boolean extendRight(Spannable text, Layout layout) {
- int end = getSelectionEnd(text);
- int to = layout.getOffsetToRightOf(end);
-
- if (to != end) {
- extendSelection(text, to);
- return true;
- }
-
- return true;
- }
-
- public static boolean extendToLeftEdge(Spannable text, Layout layout) {
- int where = findEdge(text, layout, -1);
- extendSelection(text, where);
- return true;
- }
-
- public static boolean extendToRightEdge(Spannable text, Layout layout) {
- int where = findEdge(text, layout, 1);
- extendSelection(text, where);
- return true;
- }
-
- public static boolean moveToLeftEdge(Spannable text, Layout layout) {
- int where = findEdge(text, layout, -1);
- setSelection(text, where);
- return true;
- }
-
- public static boolean moveToRightEdge(Spannable text, Layout layout) {
- int where = findEdge(text, layout, 1);
- setSelection(text, where);
- return true;
- }
-
- private static int findEdge(Spannable text, Layout layout, int dir) {
- int pt = getSelectionEnd(text);
- int line = layout.getLineForOffset(pt);
- int pdir = layout.getParagraphDirection(line);
-
- if (dir * pdir < 0) {
- return layout.getLineStart(line);
- } else {
- int end = layout.getLineEnd(line);
-
- if (line == layout.getLineCount() - 1)
- return end;
- else
- return end - 1;
- }
- }
-
- private static int chooseHorizontal(Layout layout, int direction,
- int off1, int off2) {
- int line1 = layout.getLineForOffset(off1);
- int line2 = layout.getLineForOffset(off2);
-
- if (line1 == line2) {
- // same line, so it goes by pure physical direction
-
- float h1 = layout.getPrimaryHorizontal(off1);
- float h2 = layout.getPrimaryHorizontal(off2);
-
- if (direction < 0) {
- // to left
-
- if (h1 < h2)
- return off1;
- else
- return off2;
- } else {
- // to right
-
- if (h1 > h2)
- return off1;
- else
- return off2;
- }
- } else {
- // different line, so which line is "left" and which is "right"
- // depends upon the directionality of the text
-
- // This only checks at one end, but it's not clear what the
- // right thing to do is if the ends don't agree. Even if it
- // is wrong it should still not be too bad.
- int line = layout.getLineForOffset(off1);
- int textdir = layout.getParagraphDirection(line);
-
- if (textdir == direction)
- return Math.max(off1, off2);
- else
- return Math.min(off1, off2);
- }
- }
-
- private static final class START implements NoCopySpan { };
- private static final class END implements NoCopySpan { };
-
- /*
- * Public constants
- */
-
- public static final Object SELECTION_START = new START();
- public static final Object SELECTION_END = new END();
-}
diff --git a/core/java/android/text/SpanWatcher.java b/core/java/android/text/SpanWatcher.java
deleted file mode 100644
index 01e82c8..0000000
--- a/core/java/android/text/SpanWatcher.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-/**
- * When an object of this type is attached to a Spannable, its methods
- * will be called to notify it that other markup objects have been
- * added, changed, or removed.
- */
-public interface SpanWatcher extends NoCopySpan {
- /**
- * This method is called to notify you that the specified object
- * has been attached to the specified range of the text.
- */
- public void onSpanAdded(Spannable text, Object what, int start, int end);
- /**
- * This method is called to notify you that the specified object
- * has been detached from the specified range of the text.
- */
- public void onSpanRemoved(Spannable text, Object what, int start, int end);
- /**
- * This method is called to notify you that the specified object
- * has been relocated from the range <code>ostart&hellip;oend</code>
- * to the new range <code>nstart&hellip;nend</code> of the text.
- */
- public void onSpanChanged(Spannable text, Object what, int ostart, int oend,
- int nstart, int nend);
-}
diff --git a/core/java/android/text/Spannable.java b/core/java/android/text/Spannable.java
deleted file mode 100644
index ae5d356..0000000
--- a/core/java/android/text/Spannable.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-/**
- * This is the interface for text to which markup objects can be
- * attached and detached. Not all Spannable classes have mutable text;
- * see {@link Editable} for that.
- */
-public interface Spannable
-extends Spanned
-{
- /**
- * Attach the specified markup object to the range <code>start&hellip;end</code>
- * of the text, or move the object to that range if it was already
- * attached elsewhere. See {@link Spanned} for an explanation of
- * what the flags mean. The object can be one that has meaning only
- * within your application, or it can be one that the text system will
- * use to affect text display or behavior. Some noteworthy ones are
- * the subclasses of {@link android.text.style.CharacterStyle} and
- * {@link android.text.style.ParagraphStyle}, and
- * {@link android.text.TextWatcher} and
- * {@link android.text.SpanWatcher}.
- */
- public void setSpan(Object what, int start, int end, int flags);
-
- /**
- * Remove the specified object from the range of text to which it
- * was attached, if any. It is OK to remove an object that was never
- * attached in the first place.
- */
- public void removeSpan(Object what);
-
- /**
- * Factory used by TextView to create new Spannables. You can subclass
- * it to provide something other than SpannableString.
- */
- public static class Factory {
- private static Spannable.Factory sInstance = new Spannable.Factory();
-
- /**
- * Returns the standard Spannable Factory.
- */
- public static Spannable.Factory getInstance() {
- return sInstance;
- }
-
- /**
- * Returns a new SpannableString from the specified CharSequence.
- * You can override this to provide a different kind of Spannable.
- */
- public Spannable newSpannable(CharSequence source) {
- return new SpannableString(source);
- }
- }
-}
diff --git a/core/java/android/text/SpannableString.java b/core/java/android/text/SpannableString.java
deleted file mode 100644
index 56d0946..0000000
--- a/core/java/android/text/SpannableString.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-
-/**
- * This is the class for text whose content is immutable but to which
- * markup objects can be attached and detached.
- * For mutable text, see {@link SpannableStringBuilder}.
- */
-public class SpannableString
-extends SpannableStringInternal
-implements CharSequence, GetChars, Spannable
-{
- public SpannableString(CharSequence source) {
- super(source, 0, source.length());
- }
-
- private SpannableString(CharSequence source, int start, int end) {
- super(source, start, end);
- }
-
- public static SpannableString valueOf(CharSequence source) {
- if (source instanceof SpannableString) {
- return (SpannableString) source;
- } else {
- return new SpannableString(source);
- }
- }
-
- public void setSpan(Object what, int start, int end, int flags) {
- super.setSpan(what, start, end, flags);
- }
-
- public void removeSpan(Object what) {
- super.removeSpan(what);
- }
-
- public final CharSequence subSequence(int start, int end) {
- return new SpannableString(this, start, end);
- }
-}
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
deleted file mode 100644
index caaafa1..0000000
--- a/core/java/android/text/SpannableStringBuilder.java
+++ /dev/null
@@ -1,1140 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-import com.android.internal.util.ArrayUtils;
-import android.graphics.Paint;
-import android.graphics.Canvas;
-
-import java.lang.reflect.Array;
-
-/**
- * This is the class for text whose content and markup can both be changed.
- */
-public class SpannableStringBuilder
-implements CharSequence, GetChars, Spannable, Editable, Appendable,
- GraphicsOperations
-{
- /**
- * Create a new SpannableStringBuilder with empty contents
- */
- public SpannableStringBuilder() {
- this("");
- }
-
- /**
- * Create a new SpannableStringBuilder containing a copy of the
- * specified text, including its spans if any.
- */
- public SpannableStringBuilder(CharSequence text) {
- this(text, 0, text.length());
- }
-
- /**
- * Create a new SpannableStringBuilder containing a copy of the
- * specified slice of the specified text, including its spans if any.
- */
- public SpannableStringBuilder(CharSequence text, int start, int end) {
- int srclen = end - start;
-
- int len = ArrayUtils.idealCharArraySize(srclen + 1);
- mText = new char[len];
- mGapStart = srclen;
- mGapLength = len - srclen;
-
- TextUtils.getChars(text, start, end, mText, 0);
-
- mSpanCount = 0;
- int alloc = ArrayUtils.idealIntArraySize(0);
- mSpans = new Object[alloc];
- mSpanStarts = new int[alloc];
- mSpanEnds = new int[alloc];
- mSpanFlags = new int[alloc];
-
- if (text instanceof Spanned) {
- Spanned sp = (Spanned) text;
- Object[] spans = sp.getSpans(start, end, Object.class);
-
- for (int i = 0; i < spans.length; i++) {
- if (spans[i] instanceof NoCopySpan) {
- continue;
- }
-
- int st = sp.getSpanStart(spans[i]) - start;
- int en = sp.getSpanEnd(spans[i]) - start;
- int fl = sp.getSpanFlags(spans[i]);
-
- if (st < 0)
- st = 0;
- if (st > end - start)
- st = end - start;
-
- if (en < 0)
- en = 0;
- if (en > end - start)
- en = end - start;
-
- setSpan(spans[i], st, en, fl);
- }
- }
- }
-
- public static SpannableStringBuilder valueOf(CharSequence source) {
- if (source instanceof SpannableStringBuilder) {
- return (SpannableStringBuilder) source;
- } else {
- return new SpannableStringBuilder(source);
- }
- }
-
- /**
- * Return the char at the specified offset within the buffer.
- */
- public char charAt(int where) {
- int len = length();
- if (where < 0) {
- throw new IndexOutOfBoundsException("charAt: " + where + " < 0");
- } else if (where >= len) {
- throw new IndexOutOfBoundsException("charAt: " + where +
- " >= length " + len);
- }
-
- if (where >= mGapStart)
- return mText[where + mGapLength];
- else
- return mText[where];
- }
-
- /**
- * Return the number of chars in the buffer.
- */
- public int length() {
- return mText.length - mGapLength;
- }
-
- private void resizeFor(int size) {
- int newlen = ArrayUtils.idealCharArraySize(size + 1);
- char[] newtext = new char[newlen];
-
- int after = mText.length - (mGapStart + mGapLength);
-
- System.arraycopy(mText, 0, newtext, 0, mGapStart);
- System.arraycopy(mText, mText.length - after,
- newtext, newlen - after, after);
-
- for (int i = 0; i < mSpanCount; i++) {
- if (mSpanStarts[i] > mGapStart)
- mSpanStarts[i] += newlen - mText.length;
- if (mSpanEnds[i] > mGapStart)
- mSpanEnds[i] += newlen - mText.length;
- }
-
- int oldlen = mText.length;
- mText = newtext;
- mGapLength += mText.length - oldlen;
-
- if (mGapLength < 1)
- new Exception("mGapLength < 1").printStackTrace();
- }
-
- private void moveGapTo(int where) {
- if (where == mGapStart)
- return;
-
- boolean atend = (where == length());
-
- if (where < mGapStart) {
- int overlap = mGapStart - where;
-
- System.arraycopy(mText, where,
- mText, mGapStart + mGapLength - overlap, overlap);
- } else /* where > mGapStart */ {
- int overlap = where - mGapStart;
-
- System.arraycopy(mText, where + mGapLength - overlap,
- mText, mGapStart, overlap);
- }
-
- // XXX be more clever
- for (int i = 0; i < mSpanCount; i++) {
- int start = mSpanStarts[i];
- int end = mSpanEnds[i];
-
- if (start > mGapStart)
- start -= mGapLength;
- if (start > where)
- start += mGapLength;
- else if (start == where) {
- int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;
-
- if (flag == POINT || (atend && flag == PARAGRAPH))
- start += mGapLength;
- }
-
- if (end > mGapStart)
- end -= mGapLength;
- if (end > where)
- end += mGapLength;
- else if (end == where) {
- int flag = (mSpanFlags[i] & END_MASK);
-
- if (flag == POINT || (atend && flag == PARAGRAPH))
- end += mGapLength;
- }
-
- mSpanStarts[i] = start;
- mSpanEnds[i] = end;
- }
-
- mGapStart = where;
- }
-
- // Documentation from interface
- public SpannableStringBuilder insert(int where, CharSequence tb, int start, int end) {
- return replace(where, where, tb, start, end);
- }
-
- // Documentation from interface
- public SpannableStringBuilder insert(int where, CharSequence tb) {
- return replace(where, where, tb, 0, tb.length());
- }
-
- // Documentation from interface
- public SpannableStringBuilder delete(int start, int end) {
- SpannableStringBuilder ret = replace(start, end, "", 0, 0);
-
- if (mGapLength > 2 * length())
- resizeFor(length());
-
- return ret; // == this
- }
-
- // Documentation from interface
- public void clear() {
- replace(0, length(), "", 0, 0);
- }
-
- // Documentation from interface
- public void clearSpans() {
- for (int i = mSpanCount - 1; i >= 0; i--) {
- Object what = mSpans[i];
- int ostart = mSpanStarts[i];
- int oend = mSpanEnds[i];
-
- if (ostart > mGapStart)
- ostart -= mGapLength;
- if (oend > mGapStart)
- oend -= mGapLength;
-
- mSpanCount = i;
- mSpans[i] = null;
-
- sendSpanRemoved(what, ostart, oend);
- }
- }
-
- // Documentation from interface
- public SpannableStringBuilder append(CharSequence text) {
- int length = length();
- return replace(length, length, text, 0, text.length());
- }
-
- // Documentation from interface
- public SpannableStringBuilder append(CharSequence text, int start, int end) {
- int length = length();
- return replace(length, length, text, start, end);
- }
-
- // Documentation from interface
- public SpannableStringBuilder append(char text) {
- return append(String.valueOf(text));
- }
-
- private int change(int start, int end,
- CharSequence tb, int tbstart, int tbend) {
- return change(true, start, end, tb, tbstart, tbend);
- }
-
- private int change(boolean notify, int start, int end,
- CharSequence tb, int tbstart, int tbend) {
- checkRange("replace", start, end);
- int ret = tbend - tbstart;
- TextWatcher[] recipients = null;
-
- if (notify)
- recipients = sendTextWillChange(start, end - start,
- tbend - tbstart);
-
- for (int i = mSpanCount - 1; i >= 0; i--) {
- if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) {
- int st = mSpanStarts[i];
- if (st > mGapStart)
- st -= mGapLength;
-
- int en = mSpanEnds[i];
- if (en > mGapStart)
- en -= mGapLength;
-
- int ost = st;
- int oen = en;
- int clen = length();
-
- if (st > start && st <= end) {
- for (st = end; st < clen; st++)
- if (st > end && charAt(st - 1) == '\n')
- break;
- }
-
- if (en > start && en <= end) {
- for (en = end; en < clen; en++)
- if (en > end && charAt(en - 1) == '\n')
- break;
- }
-
- if (st != ost || en != oen)
- setSpan(mSpans[i], st, en, mSpanFlags[i]);
- }
- }
-
- moveGapTo(end);
-
- if (tbend - tbstart >= mGapLength + (end - start))
- resizeFor(mText.length - mGapLength +
- tbend - tbstart - (end - start));
-
- mGapStart += tbend - tbstart - (end - start);
- mGapLength -= tbend - tbstart - (end - start);
-
- if (mGapLength < 1)
- new Exception("mGapLength < 1").printStackTrace();
-
- TextUtils.getChars(tb, tbstart, tbend, mText, start);
-
- if (tb instanceof Spanned) {
- Spanned sp = (Spanned) tb;
- Object[] spans = sp.getSpans(tbstart, tbend, Object.class);
-
- for (int i = 0; i < spans.length; i++) {
- int st = sp.getSpanStart(spans[i]);
- int en = sp.getSpanEnd(spans[i]);
-
- if (st < tbstart)
- st = tbstart;
- if (en > tbend)
- en = tbend;
-
- if (getSpanStart(spans[i]) < 0) {
- setSpan(false, spans[i],
- st - tbstart + start,
- en - tbstart + start,
- sp.getSpanFlags(spans[i]));
- }
- }
- }
-
- // no need for span fixup on pure insertion
- if (tbend > tbstart && end - start == 0) {
- if (notify) {
- sendTextChange(recipients, start, end - start, tbend - tbstart);
- sendTextHasChanged(recipients);
- }
-
- return ret;
- }
-
- boolean atend = (mGapStart + mGapLength == mText.length);
-
- for (int i = mSpanCount - 1; i >= 0; i--) {
- if (mSpanStarts[i] >= start &&
- mSpanStarts[i] < mGapStart + mGapLength) {
- int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;
-
- if (flag == POINT || (flag == PARAGRAPH && atend))
- mSpanStarts[i] = mGapStart + mGapLength;
- else
- mSpanStarts[i] = start;
- }
-
- if (mSpanEnds[i] >= start &&
- mSpanEnds[i] < mGapStart + mGapLength) {
- int flag = (mSpanFlags[i] & END_MASK);
-
- if (flag == POINT || (flag == PARAGRAPH && atend))
- mSpanEnds[i] = mGapStart + mGapLength;
- else
- mSpanEnds[i] = start;
- }
-
- // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE
- // XXX send notification on removal
-
- if (mSpanEnds[i] < mSpanStarts[i]) {
- System.arraycopy(mSpans, i + 1,
- mSpans, i, mSpanCount - (i + 1));
- System.arraycopy(mSpanStarts, i + 1,
- mSpanStarts, i, mSpanCount - (i + 1));
- System.arraycopy(mSpanEnds, i + 1,
- mSpanEnds, i, mSpanCount - (i + 1));
- System.arraycopy(mSpanFlags, i + 1,
- mSpanFlags, i, mSpanCount - (i + 1));
-
- mSpanCount--;
- }
- }
-
- if (notify) {
- sendTextChange(recipients, start, end - start, tbend - tbstart);
- sendTextHasChanged(recipients);
- }
-
- return ret;
- }
-
- // Documentation from interface
- public SpannableStringBuilder replace(int start, int end, CharSequence tb) {
- return replace(start, end, tb, 0, tb.length());
- }
-
- // Documentation from interface
- public SpannableStringBuilder replace(final int start, final int end,
- CharSequence tb, int tbstart, int tbend) {
- int filtercount = mFilters.length;
- for (int i = 0; i < filtercount; i++) {
- CharSequence repl = mFilters[i].filter(tb, tbstart, tbend,
- this, start, end);
-
- if (repl != null) {
- tb = repl;
- tbstart = 0;
- tbend = repl.length();
- }
- }
-
- if (end == start && tbstart == tbend) {
- return this;
- }
-
- if (end == start || tbstart == tbend) {
- change(start, end, tb, tbstart, tbend);
- } else {
- int selstart = Selection.getSelectionStart(this);
- int selend = Selection.getSelectionEnd(this);
-
- // XXX just make the span fixups in change() do the right thing
- // instead of this madness!
-
- checkRange("replace", start, end);
- moveGapTo(end);
- TextWatcher[] recipients;
-
- recipients = sendTextWillChange(start, end - start,
- tbend - tbstart);
-
- int origlen = end - start;
-
- if (mGapLength < 2)
- resizeFor(length() + 1);
-
- for (int i = mSpanCount - 1; i >= 0; i--) {
- if (mSpanStarts[i] == mGapStart)
- mSpanStarts[i]++;
-
- if (mSpanEnds[i] == mGapStart)
- mSpanEnds[i]++;
- }
-
- mText[mGapStart] = ' ';
- mGapStart++;
- mGapLength--;
-
- if (mGapLength < 1)
- new Exception("mGapLength < 1").printStackTrace();
-
- int oldlen = (end + 1) - start;
-
- int inserted = change(false, start + 1, start + 1,
- tb, tbstart, tbend);
- change(false, start, start + 1, "", 0, 0);
- change(false, start + inserted, start + inserted + oldlen - 1,
- "", 0, 0);
-
- /*
- * Special case to keep the cursor in the same position
- * if it was somewhere in the middle of the replaced region.
- * If it was at the start or the end or crossing the whole
- * replacement, it should already be where it belongs.
- * TODO: Is there some more general mechanism that could
- * accomplish this?
- */
- if (selstart > start && selstart < end) {
- long off = selstart - start;
-
- off = off * inserted / (end - start);
- selstart = (int) off + start;
-
- setSpan(false, Selection.SELECTION_START, selstart, selstart,
- Spanned.SPAN_POINT_POINT);
- }
- if (selend > start && selend < end) {
- long off = selend - start;
-
- off = off * inserted / (end - start);
- selend = (int) off + start;
-
- setSpan(false, Selection.SELECTION_END, selend, selend,
- Spanned.SPAN_POINT_POINT);
- }
-
- sendTextChange(recipients, start, origlen, inserted);
- sendTextHasChanged(recipients);
- }
- return this;
- }
-
- /**
- * Mark the specified range of text with the specified object.
- * The flags determine how the span will behave when text is
- * inserted at the start or end of the span's range.
- */
- public void setSpan(Object what, int start, int end, int flags) {
- setSpan(true, what, start, end, flags);
- }
-
- private void setSpan(boolean send,
- Object what, int start, int end, int flags) {
- int nstart = start;
- int nend = end;
-
- checkRange("setSpan", start, end);
-
- if ((flags & START_MASK) == (PARAGRAPH << START_SHIFT)) {
- if (start != 0 && start != length()) {
- char c = charAt(start - 1);
-
- if (c != '\n')
- throw new RuntimeException(
- "PARAGRAPH span must start at paragraph boundary");
- }
- }
-
- if ((flags & END_MASK) == PARAGRAPH) {
- if (end != 0 && end != length()) {
- char c = charAt(end - 1);
-
- if (c != '\n')
- throw new RuntimeException(
- "PARAGRAPH span must end at paragraph boundary");
- }
- }
-
- if (start > mGapStart)
- start += mGapLength;
- else if (start == mGapStart) {
- int flag = (flags & START_MASK) >> START_SHIFT;
-
- if (flag == POINT || (flag == PARAGRAPH && start == length()))
- start += mGapLength;
- }
-
- if (end > mGapStart)
- end += mGapLength;
- else if (end == mGapStart) {
- int flag = (flags & END_MASK);
-
- if (flag == POINT || (flag == PARAGRAPH && end == length()))
- end += mGapLength;
- }
-
- int count = mSpanCount;
- Object[] spans = mSpans;
-
- for (int i = 0; i < count; i++) {
- if (spans[i] == what) {
- int ostart = mSpanStarts[i];
- int oend = mSpanEnds[i];
-
- if (ostart > mGapStart)
- ostart -= mGapLength;
- if (oend > mGapStart)
- oend -= mGapLength;
-
- mSpanStarts[i] = start;
- mSpanEnds[i] = end;
- mSpanFlags[i] = flags;
-
- if (send)
- sendSpanChanged(what, ostart, oend, nstart, nend);
-
- return;
- }
- }
-
- if (mSpanCount + 1 >= mSpans.length) {
- int newsize = ArrayUtils.idealIntArraySize(mSpanCount + 1);
- Object[] newspans = new Object[newsize];
- int[] newspanstarts = new int[newsize];
- int[] newspanends = new int[newsize];
- int[] newspanflags = new int[newsize];
-
- System.arraycopy(mSpans, 0, newspans, 0, mSpanCount);
- System.arraycopy(mSpanStarts, 0, newspanstarts, 0, mSpanCount);
- System.arraycopy(mSpanEnds, 0, newspanends, 0, mSpanCount);
- System.arraycopy(mSpanFlags, 0, newspanflags, 0, mSpanCount);
-
- mSpans = newspans;
- mSpanStarts = newspanstarts;
- mSpanEnds = newspanends;
- mSpanFlags = newspanflags;
- }
-
- mSpans[mSpanCount] = what;
- mSpanStarts[mSpanCount] = start;
- mSpanEnds[mSpanCount] = end;
- mSpanFlags[mSpanCount] = flags;
- mSpanCount++;
-
- if (send)
- sendSpanAdded(what, nstart, nend);
- }
-
- /**
- * Remove the specified markup object from the buffer.
- */
- public void removeSpan(Object what) {
- for (int i = mSpanCount - 1; i >= 0; i--) {
- if (mSpans[i] == what) {
- int ostart = mSpanStarts[i];
- int oend = mSpanEnds[i];
-
- if (ostart > mGapStart)
- ostart -= mGapLength;
- if (oend > mGapStart)
- oend -= mGapLength;
-
- int count = mSpanCount - (i + 1);
-
- System.arraycopy(mSpans, i + 1, mSpans, i, count);
- System.arraycopy(mSpanStarts, i + 1, mSpanStarts, i, count);
- System.arraycopy(mSpanEnds, i + 1, mSpanEnds, i, count);
- System.arraycopy(mSpanFlags, i + 1, mSpanFlags, i, count);
-
- mSpanCount--;
- mSpans[mSpanCount] = null;
-
- sendSpanRemoved(what, ostart, oend);
- return;
- }
- }
- }
-
- /**
- * Return the buffer offset of the beginning of the specified
- * markup object, or -1 if it is not attached to this buffer.
- */
- public int getSpanStart(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- int where = mSpanStarts[i];
-
- if (where > mGapStart)
- where -= mGapLength;
-
- return where;
- }
- }
-
- return -1;
- }
-
- /**
- * Return the buffer offset of the end of the specified
- * markup object, or -1 if it is not attached to this buffer.
- */
- public int getSpanEnd(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- int where = mSpanEnds[i];
-
- if (where > mGapStart)
- where -= mGapLength;
-
- return where;
- }
- }
-
- return -1;
- }
-
- /**
- * Return the flags of the end of the specified
- * markup object, or 0 if it is not attached to this buffer.
- */
- public int getSpanFlags(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- return mSpanFlags[i];
- }
- }
-
- return 0;
- }
-
- /**
- * Return an array of the spans of the specified type that overlap
- * the specified range of the buffer. The kind may be Object.class to get
- * a list of all the spans regardless of type.
- */
- public <T> T[] getSpans(int queryStart, int queryEnd, Class<T> kind) {
- int spanCount = mSpanCount;
- Object[] spans = mSpans;
- int[] starts = mSpanStarts;
- int[] ends = mSpanEnds;
- int[] flags = mSpanFlags;
- int gapstart = mGapStart;
- int gaplen = mGapLength;
-
- int count = 0;
- Object[] ret = null;
- Object ret1 = null;
-
- for (int i = 0; i < spanCount; i++) {
- int spanStart = starts[i];
- int spanEnd = ends[i];
-
- if (spanStart > gapstart) {
- spanStart -= gaplen;
- }
- if (spanEnd > gapstart) {
- spanEnd -= gaplen;
- }
-
- if (spanStart > queryEnd) {
- continue;
- }
- if (spanEnd < queryStart) {
- continue;
- }
-
- if (spanStart != spanEnd && queryStart != queryEnd) {
- if (spanStart == queryEnd)
- continue;
- if (spanEnd == queryStart)
- continue;
- }
-
- if (kind != null && !kind.isInstance(spans[i])) {
- continue;
- }
-
- if (count == 0) {
- ret1 = spans[i];
- count++;
- } else {
- if (count == 1) {
- ret = (Object[]) Array.newInstance(kind, spanCount - i + 1);
- ret[0] = ret1;
- }
-
- int prio = flags[i] & SPAN_PRIORITY;
- if (prio != 0) {
- int j;
-
- for (j = 0; j < count; j++) {
- int p = getSpanFlags(ret[j]) & SPAN_PRIORITY;
-
- if (prio > p) {
- break;
- }
- }
-
- System.arraycopy(ret, j, ret, j + 1, count - j);
- ret[j] = spans[i];
- count++;
- } else {
- ret[count++] = spans[i];
- }
- }
- }
-
- if (count == 0) {
- return (T[]) ArrayUtils.emptyArray(kind);
- }
- if (count == 1) {
- ret = (Object[]) Array.newInstance(kind, 1);
- ret[0] = ret1;
- return (T[]) ret;
- }
- if (count == ret.length) {
- return (T[]) ret;
- }
-
- Object[] nret = (Object[]) Array.newInstance(kind, count);
- System.arraycopy(ret, 0, nret, 0, count);
- return (T[]) nret;
- }
-
- /**
- * Return the next offset after <code>start</code> but less than or
- * equal to <code>limit</code> where a span of the specified type
- * begins or ends.
- */
- public int nextSpanTransition(int start, int limit, Class kind) {
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] starts = mSpanStarts;
- int[] ends = mSpanEnds;
- int gapstart = mGapStart;
- int gaplen = mGapLength;
-
- if (kind == null) {
- kind = Object.class;
- }
-
- for (int i = 0; i < count; i++) {
- int st = starts[i];
- int en = ends[i];
-
- if (st > gapstart)
- st -= gaplen;
- if (en > gapstart)
- en -= gaplen;
-
- if (st > start && st < limit && kind.isInstance(spans[i]))
- limit = st;
- if (en > start && en < limit && kind.isInstance(spans[i]))
- limit = en;
- }
-
- return limit;
- }
-
- /**
- * Return a new CharSequence containing a copy of the specified
- * range of this buffer, including the overlapping spans.
- */
- public CharSequence subSequence(int start, int end) {
- return new SpannableStringBuilder(this, start, end);
- }
-
- /**
- * Copy the specified range of chars from this buffer into the
- * specified array, beginning at the specified offset.
- */
- public void getChars(int start, int end, char[] dest, int destoff) {
- checkRange("getChars", start, end);
-
- if (end <= mGapStart) {
- System.arraycopy(mText, start, dest, destoff, end - start);
- } else if (start >= mGapStart) {
- System.arraycopy(mText, start + mGapLength,
- dest, destoff, end - start);
- } else {
- System.arraycopy(mText, start, dest, destoff, mGapStart - start);
- System.arraycopy(mText, mGapStart + mGapLength,
- dest, destoff + (mGapStart - start),
- end - mGapStart);
- }
- }
-
- /**
- * Return a String containing a copy of the chars in this buffer.
- */
- public String toString() {
- int len = length();
- char[] buf = new char[len];
-
- getChars(0, len, buf, 0);
- return new String(buf);
- }
-
- private TextWatcher[] sendTextWillChange(int start, int before, int after) {
- TextWatcher[] recip = getSpans(start, start + before, TextWatcher.class);
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].beforeTextChanged(this, start, before, after);
- }
-
- return recip;
- }
-
- private void sendTextChange(TextWatcher[] recip, int start, int before,
- int after) {
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].onTextChanged(this, start, before, after);
- }
- }
-
- private void sendTextHasChanged(TextWatcher[] recip) {
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].afterTextChanged(this);
- }
- }
-
- private void sendSpanAdded(Object what, int start, int end) {
- SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class);
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].onSpanAdded(this, what, start, end);
- }
- }
-
- private void sendSpanRemoved(Object what, int start, int end) {
- SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class);
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].onSpanRemoved(this, what, start, end);
- }
- }
-
- private void sendSpanChanged(Object what, int s, int e, int st, int en) {
- SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en),
- SpanWatcher.class);
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].onSpanChanged(this, what, s, e, st, en);
- }
- }
-
- private static String region(int start, int end) {
- return "(" + start + " ... " + end + ")";
- }
-
- private void checkRange(final String operation, int start, int end) {
- if (end < start) {
- throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " has end before start");
- }
-
- int len = length();
-
- if (start > len || end > len) {
- throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " ends beyond length " + len);
- }
-
- if (start < 0 || end < 0) {
- throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " starts before 0");
- }
- }
-
- private boolean isprint(char c) { // XXX
- if (c >= ' ' && c <= '~')
- return true;
- else
- return false;
- }
-
-/*
- private static final int startFlag(int flag) {
- return (flag >> 4) & 0x0F;
- }
-
- private static final int endFlag(int flag) {
- return flag & 0x0F;
- }
-
- public void dump() { // XXX
- for (int i = 0; i < mGapStart; i++) {
- System.out.print('|');
- System.out.print(' ');
- System.out.print(isprint(mText[i]) ? mText[i] : '.');
- System.out.print(' ');
- }
-
- for (int i = mGapStart; i < mGapStart + mGapLength; i++) {
- System.out.print('|');
- System.out.print('(');
- System.out.print(isprint(mText[i]) ? mText[i] : '.');
- System.out.print(')');
- }
-
- for (int i = mGapStart + mGapLength; i < mText.length; i++) {
- System.out.print('|');
- System.out.print(' ');
- System.out.print(isprint(mText[i]) ? mText[i] : '.');
- System.out.print(' ');
- }
-
- System.out.print('\n');
-
- for (int i = 0; i < mText.length + 1; i++) {
- int found = 0;
- int wfound = 0;
-
- for (int j = 0; j < mSpanCount; j++) {
- if (mSpanStarts[j] == i) {
- found = 1;
- wfound = j;
- break;
- }
-
- if (mSpanEnds[j] == i) {
- found = 2;
- wfound = j;
- break;
- }
- }
-
- if (found == 1) {
- if (startFlag(mSpanFlags[wfound]) == MARK)
- System.out.print("( ");
- if (startFlag(mSpanFlags[wfound]) == PARAGRAPH)
- System.out.print("< ");
- else
- System.out.print("[ ");
- } else if (found == 2) {
- if (endFlag(mSpanFlags[wfound]) == POINT)
- System.out.print(") ");
- if (endFlag(mSpanFlags[wfound]) == PARAGRAPH)
- System.out.print("> ");
- else
- System.out.print("] ");
- } else {
- System.out.print(" ");
- }
- }
-
- System.out.print("\n");
- }
-*/
-
- /**
- * Don't call this yourself -- exists for Canvas to use internally.
- * {@hide}
- */
- public void drawText(Canvas c, int start, int end,
- float x, float y, Paint p) {
- checkRange("drawText", start, end);
-
- if (end <= mGapStart) {
- c.drawText(mText, start, end - start, x, y, p);
- } else if (start >= mGapStart) {
- c.drawText(mText, start + mGapLength, end - start, x, y, p);
- } else {
- char[] buf = TextUtils.obtain(end - start);
-
- getChars(start, end, buf, 0);
- c.drawText(buf, 0, end - start, x, y, p);
- TextUtils.recycle(buf);
- }
- }
-
- /**
- * Don't call this yourself -- exists for Paint to use internally.
- * {@hide}
- */
- public float measureText(int start, int end, Paint p) {
- checkRange("measureText", start, end);
-
- float ret;
-
- if (end <= mGapStart) {
- ret = p.measureText(mText, start, end - start);
- } else if (start >= mGapStart) {
- ret = p.measureText(mText, start + mGapLength, end - start);
- } else {
- char[] buf = TextUtils.obtain(end - start);
-
- getChars(start, end, buf, 0);
- ret = p.measureText(buf, 0, end - start);
- TextUtils.recycle(buf);
- }
-
- return ret;
- }
-
- /**
- * Don't call this yourself -- exists for Paint to use internally.
- * {@hide}
- */
- public int getTextWidths(int start, int end, float[] widths, Paint p) {
- checkRange("getTextWidths", start, end);
-
- int ret;
-
- if (end <= mGapStart) {
- ret = p.getTextWidths(mText, start, end - start, widths);
- } else if (start >= mGapStart) {
- ret = p.getTextWidths(mText, start + mGapLength, end - start,
- widths);
- } else {
- char[] buf = TextUtils.obtain(end - start);
-
- getChars(start, end, buf, 0);
- ret = p.getTextWidths(buf, 0, end - start, widths);
- TextUtils.recycle(buf);
- }
-
- return ret;
- }
-
- // Documentation from interface
- public void setFilters(InputFilter[] filters) {
- if (filters == null) {
- throw new IllegalArgumentException();
- }
-
- mFilters = filters;
- }
-
- // Documentation from interface
- public InputFilter[] getFilters() {
- return mFilters;
- }
-
- private static final InputFilter[] NO_FILTERS = new InputFilter[0];
- private InputFilter[] mFilters = NO_FILTERS;
-
- private char[] mText;
- private int mGapStart;
- private int mGapLength;
-
- private Object[] mSpans;
- private int[] mSpanStarts;
- private int[] mSpanEnds;
- private int[] mSpanFlags;
- private int mSpanCount;
-
- private static final int MARK = 1;
- private static final int POINT = 2;
- private static final int PARAGRAPH = 3;
-
- private static final int START_MASK = 0xF0;
- private static final int END_MASK = 0x0F;
- private static final int START_SHIFT = 4;
-}
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
deleted file mode 100644
index 0412285..0000000
--- a/core/java/android/text/SpannableStringInternal.java
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-import com.android.internal.util.ArrayUtils;
-
-import java.lang.reflect.Array;
-
-/* package */ abstract class SpannableStringInternal
-{
- /* package */ SpannableStringInternal(CharSequence source,
- int start, int end) {
- if (start == 0 && end == source.length())
- mText = source.toString();
- else
- mText = source.toString().substring(start, end);
-
- int initial = ArrayUtils.idealIntArraySize(0);
- mSpans = new Object[initial];
- mSpanData = new int[initial * 3];
-
- if (source instanceof Spanned) {
- Spanned sp = (Spanned) source;
- Object[] spans = sp.getSpans(start, end, Object.class);
-
- for (int i = 0; i < spans.length; i++) {
- int st = sp.getSpanStart(spans[i]);
- int en = sp.getSpanEnd(spans[i]);
- int fl = sp.getSpanFlags(spans[i]);
-
- if (st < start)
- st = start;
- if (en > end)
- en = end;
-
- setSpan(spans[i], st - start, en - start, fl);
- }
- }
- }
-
- public final int length() {
- return mText.length();
- }
-
- public final char charAt(int i) {
- return mText.charAt(i);
- }
-
- public final String toString() {
- return mText;
- }
-
- /* subclasses must do subSequence() to preserve type */
-
- public final void getChars(int start, int end, char[] dest, int off) {
- mText.getChars(start, end, dest, off);
- }
-
- /* package */ void setSpan(Object what, int start, int end, int flags) {
- int nstart = start;
- int nend = end;
-
- checkRange("setSpan", start, end);
-
- if ((flags & Spannable.SPAN_PARAGRAPH) == Spannable.SPAN_PARAGRAPH) {
- if (start != 0 && start != length()) {
- char c = charAt(start - 1);
-
- if (c != '\n')
- throw new RuntimeException(
- "PARAGRAPH span must start at paragraph boundary" +
- " (" + start + " follows " + c + ")");
- }
-
- if (end != 0 && end != length()) {
- char c = charAt(end - 1);
-
- if (c != '\n')
- throw new RuntimeException(
- "PARAGRAPH span must end at paragraph boundary" +
- " (" + end + " follows " + c + ")");
- }
- }
-
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] data = mSpanData;
-
- for (int i = 0; i < count; i++) {
- if (spans[i] == what) {
- int ostart = data[i * COLUMNS + START];
- int oend = data[i * COLUMNS + END];
-
- data[i * COLUMNS + START] = start;
- data[i * COLUMNS + END] = end;
- data[i * COLUMNS + FLAGS] = flags;
-
- sendSpanChanged(what, ostart, oend, nstart, nend);
- return;
- }
- }
-
- if (mSpanCount + 1 >= mSpans.length) {
- int newsize = ArrayUtils.idealIntArraySize(mSpanCount + 1);
- Object[] newtags = new Object[newsize];
- int[] newdata = new int[newsize * 3];
-
- System.arraycopy(mSpans, 0, newtags, 0, mSpanCount);
- System.arraycopy(mSpanData, 0, newdata, 0, mSpanCount * 3);
-
- mSpans = newtags;
- mSpanData = newdata;
- }
-
- mSpans[mSpanCount] = what;
- mSpanData[mSpanCount * COLUMNS + START] = start;
- mSpanData[mSpanCount * COLUMNS + END] = end;
- mSpanData[mSpanCount * COLUMNS + FLAGS] = flags;
- mSpanCount++;
-
- if (this instanceof Spannable)
- sendSpanAdded(what, nstart, nend);
- }
-
- /* package */ void removeSpan(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] data = mSpanData;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- int ostart = data[i * COLUMNS + START];
- int oend = data[i * COLUMNS + END];
-
- int c = count - (i + 1);
-
- System.arraycopy(spans, i + 1, spans, i, c);
- System.arraycopy(data, (i + 1) * COLUMNS,
- data, i * COLUMNS, c * COLUMNS);
-
- mSpanCount--;
-
- sendSpanRemoved(what, ostart, oend);
- return;
- }
- }
- }
-
- public int getSpanStart(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] data = mSpanData;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- return data[i * COLUMNS + START];
- }
- }
-
- return -1;
- }
-
- public int getSpanEnd(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] data = mSpanData;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- return data[i * COLUMNS + END];
- }
- }
-
- return -1;
- }
-
- public int getSpanFlags(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] data = mSpanData;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- return data[i * COLUMNS + FLAGS];
- }
- }
-
- return 0;
- }
-
- public <T> T[] getSpans(int queryStart, int queryEnd, Class<T> kind) {
- int count = 0;
-
- int spanCount = mSpanCount;
- Object[] spans = mSpans;
- int[] data = mSpanData;
- Object[] ret = null;
- Object ret1 = null;
-
- for (int i = 0; i < spanCount; i++) {
- int spanStart = data[i * COLUMNS + START];
- int spanEnd = data[i * COLUMNS + END];
-
- if (spanStart > queryEnd) {
- continue;
- }
- if (spanEnd < queryStart) {
- continue;
- }
-
- if (spanStart != spanEnd && queryStart != queryEnd) {
- if (spanStart == queryEnd) {
- continue;
- }
- if (spanEnd == queryStart) {
- continue;
- }
- }
-
- if (kind != null && !kind.isInstance(spans[i])) {
- continue;
- }
-
- if (count == 0) {
- ret1 = spans[i];
- count++;
- } else {
- if (count == 1) {
- ret = (Object[]) Array.newInstance(kind, spanCount - i + 1);
- ret[0] = ret1;
- }
-
- int prio = data[i * COLUMNS + FLAGS] & Spanned.SPAN_PRIORITY;
- if (prio != 0) {
- int j;
-
- for (j = 0; j < count; j++) {
- int p = getSpanFlags(ret[j]) & Spanned.SPAN_PRIORITY;
-
- if (prio > p) {
- break;
- }
- }
-
- System.arraycopy(ret, j, ret, j + 1, count - j);
- ret[j] = spans[i];
- count++;
- } else {
- ret[count++] = spans[i];
- }
- }
- }
-
- if (count == 0) {
- return (T[]) ArrayUtils.emptyArray(kind);
- }
- if (count == 1) {
- ret = (Object[]) Array.newInstance(kind, 1);
- ret[0] = ret1;
- return (T[]) ret;
- }
- if (count == ret.length) {
- return (T[]) ret;
- }
-
- Object[] nret = (Object[]) Array.newInstance(kind, count);
- System.arraycopy(ret, 0, nret, 0, count);
- return (T[]) nret;
- }
-
- public int nextSpanTransition(int start, int limit, Class kind) {
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] data = mSpanData;
-
- if (kind == null) {
- kind = Object.class;
- }
-
- for (int i = 0; i < count; i++) {
- int st = data[i * COLUMNS + START];
- int en = data[i * COLUMNS + END];
-
- if (st > start && st < limit && kind.isInstance(spans[i]))
- limit = st;
- if (en > start && en < limit && kind.isInstance(spans[i]))
- limit = en;
- }
-
- return limit;
- }
-
- private void sendSpanAdded(Object what, int start, int end) {
- SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class);
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].onSpanAdded((Spannable) this, what, start, end);
- }
- }
-
- private void sendSpanRemoved(Object what, int start, int end) {
- SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class);
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].onSpanRemoved((Spannable) this, what, start, end);
- }
- }
-
- private void sendSpanChanged(Object what, int s, int e, int st, int en) {
- SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en),
- SpanWatcher.class);
- int n = recip.length;
-
- for (int i = 0; i < n; i++) {
- recip[i].onSpanChanged((Spannable) this, what, s, e, st, en);
- }
- }
-
- private static String region(int start, int end) {
- return "(" + start + " ... " + end + ")";
- }
-
- private void checkRange(final String operation, int start, int end) {
- if (end < start) {
- throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " has end before start");
- }
-
- int len = length();
-
- if (start > len || end > len) {
- throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " ends beyond length " + len);
- }
-
- if (start < 0 || end < 0) {
- throw new IndexOutOfBoundsException(operation + " " +
- region(start, end) +
- " starts before 0");
- }
- }
-
- private String mText;
- private Object[] mSpans;
- private int[] mSpanData;
- private int mSpanCount;
-
- /* package */ static final Object[] EMPTY = new Object[0];
-
- private static final int START = 0;
- private static final int END = 1;
- private static final int FLAGS = 2;
- private static final int COLUMNS = 3;
-}
diff --git a/core/java/android/text/Spanned.java b/core/java/android/text/Spanned.java
deleted file mode 100644
index 154497d..0000000
--- a/core/java/android/text/Spanned.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-/**
- * This is the interface for text that has markup objects attached to
- * ranges of it. Not all text classes have mutable markup or text;
- * see {@link Spannable} for mutable markup and {@link Editable} for
- * mutable text.
- */
-public interface Spanned
-extends CharSequence
-{
- /**
- * Bitmask of bits that are relevent for controlling point/mark behavior
- * of spans.
- */
- public static final int SPAN_POINT_MARK_MASK = 0x33;
-
- /**
- * 0-length spans with type SPAN_MARK_MARK behave like text marks:
- * they remain at their original offset when text is inserted
- * at that offset.
- */
- public static final int SPAN_MARK_MARK = 0x11;
- /**
- * SPAN_MARK_POINT is a synonym for {@link #SPAN_INCLUSIVE_INCLUSIVE}.
- */
- public static final int SPAN_MARK_POINT = 0x12;
- /**
- * SPAN_POINT_MARK is a synonym for {@link #SPAN_EXCLUSIVE_EXCLUSIVE}.
- */
- public static final int SPAN_POINT_MARK = 0x21;
-
- /**
- * 0-length spans with type SPAN_POINT_POINT behave like cursors:
- * they are pushed forward by the length of the insertion when text
- * is inserted at their offset.
- */
- public static final int SPAN_POINT_POINT = 0x22;
-
- /**
- * SPAN_PARAGRAPH behaves like SPAN_INCLUSIVE_EXCLUSIVE
- * (SPAN_MARK_MARK), except that if either end of the span is
- * at the end of the buffer, that end behaves like _POINT
- * instead (so SPAN_INCLUSIVE_INCLUSIVE if it starts in the
- * middle and ends at the end, or SPAN_EXCLUSIVE_INCLUSIVE
- * if it both starts and ends at the end).
- * <p>
- * Its endpoints must be the start or end of the buffer or
- * immediately after a \n character, and if the \n
- * that anchors it is deleted, the endpoint is pulled to the
- * next \n that follows in the buffer (or to the end of
- * the buffer).
- */
- public static final int SPAN_PARAGRAPH = 0x33;
-
- /**
- * Non-0-length spans of type SPAN_INCLUSIVE_EXCLUSIVE expand
- * to include text inserted at their starting point but not at their
- * ending point. When 0-length, they behave like marks.
- */
- public static final int SPAN_INCLUSIVE_EXCLUSIVE = SPAN_MARK_MARK;
-
- /**
- * Spans of type SPAN_INCLUSIVE_INCLUSIVE expand
- * to include text inserted at either their starting or ending point.
- */
- public static final int SPAN_INCLUSIVE_INCLUSIVE = SPAN_MARK_POINT;
-
- /**
- * Spans of type SPAN_EXCLUSIVE_EXCLUSIVE do not expand
- * to include text inserted at either their starting or ending point.
- * They can never have a length of 0 and are automatically removed
- * from the buffer if all the text they cover is removed.
- */
- public static final int SPAN_EXCLUSIVE_EXCLUSIVE = SPAN_POINT_MARK;
-
- /**
- * Non-0-length spans of type SPAN_INCLUSIVE_EXCLUSIVE expand
- * to include text inserted at their ending point but not at their
- * starting point. When 0-length, they behave like points.
- */
- public static final int SPAN_EXCLUSIVE_INCLUSIVE = SPAN_POINT_POINT;
-
- /**
- * This flag is set on spans that are being used to apply temporary
- * styling information on the composing text of an input method, so that
- * they can be found and removed when the composing text is being
- * replaced.
- */
- public static final int SPAN_COMPOSING = 0x100;
-
- /**
- * This flag will be set for intermediate span changes, meaning there
- * is guaranteed to be another change following it. Typically it is
- * used for {@link Selection} which automatically uses this with the first
- * offset it sets when updating the selection.
- */
- public static final int SPAN_INTERMEDIATE = 0x200;
-
- /**
- * The bits numbered SPAN_USER_SHIFT and above are available
- * for callers to use to store scalar data associated with their
- * span object.
- */
- public static final int SPAN_USER_SHIFT = 24;
- /**
- * The bits specified by the SPAN_USER bitfield are available
- * for callers to use to store scalar data associated with their
- * span object.
- */
- public static final int SPAN_USER = 0xFFFFFFFF << SPAN_USER_SHIFT;
-
- /**
- * The bits numbered just above SPAN_PRIORITY_SHIFT determine the order
- * of change notifications -- higher numbers go first. You probably
- * don't need to set this; it is used so that when text changes, the
- * text layout gets the chance to update itself before any other
- * callbacks can inquire about the layout of the text.
- */
- public static final int SPAN_PRIORITY_SHIFT = 16;
- /**
- * The bits specified by the SPAN_PRIORITY bitmap determine the order
- * of change notifications -- higher numbers go first. You probably
- * don't need to set this; it is used so that when text changes, the
- * text layout gets the chance to update itself before any other
- * callbacks can inquire about the layout of the text.
- */
- public static final int SPAN_PRIORITY = 0xFF << SPAN_PRIORITY_SHIFT;
-
- /**
- * Return an array of the markup objects attached to the specified
- * slice of this CharSequence and whose type is the specified type
- * or a subclass of it. Specify Object.class for the type if you
- * want all the objects regardless of type.
- */
- public <T> T[] getSpans(int start, int end, Class<T> type);
-
- /**
- * Return the beginning of the range of text to which the specified
- * markup object is attached, or -1 if the object is not attached.
- */
- public int getSpanStart(Object tag);
-
- /**
- * Return the end of the range of text to which the specified
- * markup object is attached, or -1 if the object is not attached.
- */
- public int getSpanEnd(Object tag);
-
- /**
- * Return the flags that were specified when {@link Spannable#setSpan} was
- * used to attach the specified markup object, or 0 if the specified
- * object has not been attached.
- */
- public int getSpanFlags(Object tag);
-
- /**
- * Return the first offset greater than or equal to <code>start</code>
- * where a markup object of class <code>type</code> begins or ends,
- * or <code>limit</code> if there are no starts or ends greater than or
- * equal to <code>start</code> but less than <code>limit</code>. Specify
- * <code>null</code> or Object.class for the type if you want every
- * transition regardless of type.
- */
- public int nextSpanTransition(int start, int limit, Class type);
-}
diff --git a/core/java/android/text/SpannedString.java b/core/java/android/text/SpannedString.java
deleted file mode 100644
index afed221..0000000
--- a/core/java/android/text/SpannedString.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-
-/**
- * This is the class for text whose content and markup are immutable.
- * For mutable markup, see {@link SpannableString}; for mutable text,
- * see {@link SpannableStringBuilder}.
- */
-public final class SpannedString
-extends SpannableStringInternal
-implements CharSequence, GetChars, Spanned
-{
- public SpannedString(CharSequence source) {
- super(source, 0, source.length());
- }
-
- private SpannedString(CharSequence source, int start, int end) {
- super(source, start, end);
- }
-
- public CharSequence subSequence(int start, int end) {
- return new SpannedString(this, start, end);
- }
-
- public static SpannedString valueOf(CharSequence source) {
- if (source instanceof SpannedString) {
- return (SpannedString) source;
- } else {
- return new SpannedString(source);
- }
- }
-}
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
deleted file mode 100644
index 0fef40b..0000000
--- a/core/java/android/text/StaticLayout.java
+++ /dev/null
@@ -1,1195 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-import android.graphics.Paint;
-import com.android.internal.util.ArrayUtils;
-import android.util.Log;
-import android.text.style.LeadingMarginSpan;
-import android.text.style.LineHeightSpan;
-import android.text.style.MetricAffectingSpan;
-import android.text.style.ReplacementSpan;
-
-/**
- * StaticLayout is a Layout for text that will not be edited after it
- * is laid out. Use {@link DynamicLayout} for text that may change.
- * <p>This is used by widgets to control text layout. You should not need
- * to use this class directly unless you are implementing your own widget
- * or custom display object, or would be tempted to call
- * {@link android.graphics.Canvas#drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint)
- * Canvas.drawText()} directly.</p>
- */
-public class
-StaticLayout
-extends Layout
-{
- public StaticLayout(CharSequence source, TextPaint paint,
- int width,
- Alignment align, float spacingmult, float spacingadd,
- boolean includepad) {
- this(source, 0, source.length(), paint, width, align,
- spacingmult, spacingadd, includepad);
- }
-
- public StaticLayout(CharSequence source, int bufstart, int bufend,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- boolean includepad) {
- this(source, bufstart, bufend, paint, outerwidth, align,
- spacingmult, spacingadd, includepad, null, 0);
- }
-
- public StaticLayout(CharSequence source, int bufstart, int bufend,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- boolean includepad,
- TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
- super((ellipsize == null)
- ? source
- : (source instanceof Spanned)
- ? new SpannedEllipsizer(source)
- : new Ellipsizer(source),
- paint, outerwidth, align, spacingmult, spacingadd);
-
- /*
- * This is annoying, but we can't refer to the layout until
- * superclass construction is finished, and the superclass
- * constructor wants the reference to the display text.
- *
- * This will break if the superclass constructor ever actually
- * cares about the content instead of just holding the reference.
- */
- if (ellipsize != null) {
- Ellipsizer e = (Ellipsizer) getText();
-
- e.mLayout = this;
- e.mWidth = ellipsizedWidth;
- e.mMethod = ellipsize;
- mEllipsizedWidth = ellipsizedWidth;
-
- mColumns = COLUMNS_ELLIPSIZE;
- } else {
- mColumns = COLUMNS_NORMAL;
- mEllipsizedWidth = outerwidth;
- }
-
- mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)];
- mLineDirections = new Directions[
- ArrayUtils.idealIntArraySize(2 * mColumns)];
-
- generate(source, bufstart, bufend, paint, outerwidth, align,
- spacingmult, spacingadd, includepad, includepad,
- ellipsize != null, ellipsizedWidth, ellipsize);
-
- mChdirs = null;
- mChs = null;
- mWidths = null;
- mFontMetricsInt = null;
- }
-
- /* package */ StaticLayout(boolean ellipsize) {
- super(null, null, 0, null, 0, 0);
-
- mColumns = COLUMNS_ELLIPSIZE;
- mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)];
- mLineDirections = new Directions[
- ArrayUtils.idealIntArraySize(2 * mColumns)];
- }
-
- /* package */ void generate(CharSequence source, int bufstart, int bufend,
- TextPaint paint, int outerwidth,
- Alignment align,
- float spacingmult, float spacingadd,
- boolean includepad, boolean trackpad,
- boolean breakOnlyAtSpaces,
- float ellipsizedWidth, TextUtils.TruncateAt where) {
- mLineCount = 0;
-
- int v = 0;
- boolean needMultiply = (spacingmult != 1 || spacingadd != 0);
-
- Paint.FontMetricsInt fm = mFontMetricsInt;
- int[] choosehtv = null;
-
- int end = TextUtils.indexOf(source, '\n', bufstart, bufend);
- int bufsiz = end >= 0 ? end - bufstart : bufend - bufstart;
- boolean first = true;
-
- if (mChdirs == null) {
- mChdirs = new byte[ArrayUtils.idealByteArraySize(bufsiz + 1)];
- mChs = new char[ArrayUtils.idealCharArraySize(bufsiz + 1)];
- mWidths = new float[ArrayUtils.idealIntArraySize((bufsiz + 1) * 2)];
- }
-
- byte[] chdirs = mChdirs;
- char[] chs = mChs;
- float[] widths = mWidths;
-
- AlteredCharSequence alter = null;
- Spanned spanned = null;
-
- if (source instanceof Spanned)
- spanned = (Spanned) source;
-
- int DEFAULT_DIR = DIR_LEFT_TO_RIGHT; // XXX
-
- for (int start = bufstart; start <= bufend; start = end) {
- if (first)
- first = false;
- else
- end = TextUtils.indexOf(source, '\n', start, bufend);
-
- if (end < 0)
- end = bufend;
- else
- end++;
-
- int firstwidth = outerwidth;
- int restwidth = outerwidth;
-
- LineHeightSpan[] chooseht = null;
-
- if (spanned != null) {
- LeadingMarginSpan[] sp;
-
- sp = spanned.getSpans(start, end, LeadingMarginSpan.class);
- for (int i = 0; i < sp.length; i++) {
- firstwidth -= sp[i].getLeadingMargin(true);
- restwidth -= sp[i].getLeadingMargin(false);
- }
-
- chooseht = spanned.getSpans(start, end, LineHeightSpan.class);
-
- if (chooseht.length != 0) {
- if (choosehtv == null ||
- choosehtv.length < chooseht.length) {
- choosehtv = new int[ArrayUtils.idealIntArraySize(
- chooseht.length)];
- }
-
- for (int i = 0; i < chooseht.length; i++) {
- int o = spanned.getSpanStart(chooseht[i]);
-
- if (o < start) {
- // starts in this layout, before the
- // current paragraph
-
- choosehtv[i] = getLineTop(getLineForOffset(o));
- } else {
- // starts in this paragraph
-
- choosehtv[i] = v;
- }
- }
- }
- }
-
- if (end - start > chdirs.length) {
- chdirs = new byte[ArrayUtils.idealByteArraySize(end - start)];
- mChdirs = chdirs;
- }
- if (end - start > chs.length) {
- chs = new char[ArrayUtils.idealCharArraySize(end - start)];
- mChs = chs;
- }
- if ((end - start) * 2 > widths.length) {
- widths = new float[ArrayUtils.idealIntArraySize((end - start) * 2)];
- mWidths = widths;
- }
-
- TextUtils.getChars(source, start, end, chs, 0);
- final int n = end - start;
-
- boolean easy = true;
- boolean altered = false;
- int dir = DEFAULT_DIR; // XXX
-
- for (int i = 0; i < n; i++) {
- if (chs[i] >= FIRST_RIGHT_TO_LEFT) {
- easy = false;
- break;
- }
- }
-
- if (!easy) {
- AndroidCharacter.getDirectionalities(chs, chdirs, end - start);
-
- /*
- * Determine primary paragraph direction
- */
-
- for (int j = start; j < end; j++) {
- int d = chdirs[j - start];
-
- if (d == Character.DIRECTIONALITY_LEFT_TO_RIGHT) {
- dir = DIR_LEFT_TO_RIGHT;
- break;
- }
- if (d == Character.DIRECTIONALITY_RIGHT_TO_LEFT) {
- dir = DIR_RIGHT_TO_LEFT;
- break;
- }
- }
-
- /*
- * XXX Explicit overrides should go here
- */
-
- /*
- * Weak type resolution
- */
-
- final byte SOR = dir == DIR_LEFT_TO_RIGHT ?
- Character.DIRECTIONALITY_LEFT_TO_RIGHT :
- Character.DIRECTIONALITY_RIGHT_TO_LEFT;
-
- // dump(chdirs, n, "initial");
-
- // W1 non spacing marks
- for (int j = 0; j < n; j++) {
- if (chdirs[j] == Character.NON_SPACING_MARK) {
- if (j == 0)
- chdirs[j] = SOR;
- else
- chdirs[j] = chdirs[j - 1];
- }
- }
-
- // dump(chdirs, n, "W1");
-
- // W2 european numbers
- byte cur = SOR;
- for (int j = 0; j < n; j++) {
- byte d = chdirs[j];
-
- if (d == Character.DIRECTIONALITY_LEFT_TO_RIGHT ||
- d == Character.DIRECTIONALITY_RIGHT_TO_LEFT ||
- d == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC)
- cur = d;
- else if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER) {
- if (cur ==
- Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC)
- chdirs[j] = Character.DIRECTIONALITY_ARABIC_NUMBER;
- }
- }
-
- // dump(chdirs, n, "W2");
-
- // W3 arabic letters
- for (int j = 0; j < n; j++) {
- if (chdirs[j] == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC)
- chdirs[j] = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
- }
-
- // dump(chdirs, n, "W3");
-
- // W4 single separator between numbers
- for (int j = 1; j < n - 1; j++) {
- byte d = chdirs[j];
- byte prev = chdirs[j - 1];
- byte next = chdirs[j + 1];
-
- if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR) {
- if (prev == Character.DIRECTIONALITY_EUROPEAN_NUMBER &&
- next == Character.DIRECTIONALITY_EUROPEAN_NUMBER)
- chdirs[j] = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
- } else if (d == Character.DIRECTIONALITY_COMMON_NUMBER_SEPARATOR) {
- if (prev == Character.DIRECTIONALITY_EUROPEAN_NUMBER &&
- next == Character.DIRECTIONALITY_EUROPEAN_NUMBER)
- chdirs[j] = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
- if (prev == Character.DIRECTIONALITY_ARABIC_NUMBER &&
- next == Character.DIRECTIONALITY_ARABIC_NUMBER)
- chdirs[j] = Character.DIRECTIONALITY_ARABIC_NUMBER;
- }
- }
-
- // dump(chdirs, n, "W4");
-
- // W5 european number terminators
- boolean adjacent = false;
- for (int j = 0; j < n; j++) {
- byte d = chdirs[j];
-
- if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER)
- adjacent = true;
- else if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR && adjacent)
- chdirs[j] = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
- else
- adjacent = false;
- }
-
- //dump(chdirs, n, "W5");
-
- // W5 european number terminators part 2,
- // W6 separators and terminators
- adjacent = false;
- for (int j = n - 1; j >= 0; j--) {
- byte d = chdirs[j];
-
- if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER)
- adjacent = true;
- else if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR) {
- if (adjacent)
- chdirs[j] = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
- else
- chdirs[j] = Character.DIRECTIONALITY_OTHER_NEUTRALS;
- }
- else {
- adjacent = false;
-
- if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR ||
- d == Character.DIRECTIONALITY_COMMON_NUMBER_SEPARATOR ||
- d == Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR ||
- d == Character.DIRECTIONALITY_SEGMENT_SEPARATOR)
- chdirs[j] = Character.DIRECTIONALITY_OTHER_NEUTRALS;
- }
- }
-
- // dump(chdirs, n, "W6");
-
- // W7 strong direction of european numbers
- cur = SOR;
- for (int j = 0; j < n; j++) {
- byte d = chdirs[j];
-
- if (d == SOR ||
- d == Character.DIRECTIONALITY_LEFT_TO_RIGHT ||
- d == Character.DIRECTIONALITY_RIGHT_TO_LEFT)
- cur = d;
-
- if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER)
- chdirs[j] = cur;
- }
-
- // dump(chdirs, n, "W7");
-
- // N1, N2 neutrals
- cur = SOR;
- for (int j = 0; j < n; j++) {
- byte d = chdirs[j];
-
- if (d == Character.DIRECTIONALITY_LEFT_TO_RIGHT ||
- d == Character.DIRECTIONALITY_RIGHT_TO_LEFT) {
- cur = d;
- } else if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER ||
- d == Character.DIRECTIONALITY_ARABIC_NUMBER) {
- cur = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
- } else {
- byte dd = SOR;
- int k;
-
- for (k = j + 1; k < n; k++) {
- dd = chdirs[k];
-
- if (dd == Character.DIRECTIONALITY_LEFT_TO_RIGHT ||
- dd == Character.DIRECTIONALITY_RIGHT_TO_LEFT) {
- break;
- }
- if (dd == Character.DIRECTIONALITY_EUROPEAN_NUMBER ||
- dd == Character.DIRECTIONALITY_ARABIC_NUMBER) {
- dd = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
- break;
- }
- }
-
- for (int y = j; y < k; y++) {
- if (dd == cur)
- chdirs[y] = cur;
- else
- chdirs[y] = SOR;
- }
-
- j = k - 1;
- }
- }
-
- // dump(chdirs, n, "final");
-
- // extra: enforce that all tabs go the primary direction
-
- for (int j = 0; j < n; j++) {
- if (chs[j] == '\t')
- chdirs[j] = SOR;
- }
-
- // extra: enforce that object replacements go to the
- // primary direction
- // and that none of the underlying characters are treated
- // as viable breakpoints
-
- if (source instanceof Spanned) {
- Spanned sp = (Spanned) source;
- ReplacementSpan[] spans = sp.getSpans(start, end, ReplacementSpan.class);
-
- for (int y = 0; y < spans.length; y++) {
- int a = sp.getSpanStart(spans[y]);
- int b = sp.getSpanEnd(spans[y]);
-
- for (int x = a; x < b; x++) {
- chdirs[x - start] = SOR;
- chs[x - start] = '\uFFFC';
- }
- }
- }
-
- // Do mirroring for right-to-left segments
-
- for (int i = 0; i < n; i++) {
- if (chdirs[i] == Character.DIRECTIONALITY_RIGHT_TO_LEFT) {
- int j;
-
- for (j = i; j < n; j++) {
- if (chdirs[j] !=
- Character.DIRECTIONALITY_RIGHT_TO_LEFT)
- break;
- }
-
- if (AndroidCharacter.mirror(chs, i, j - i))
- altered = true;
-
- i = j - 1;
- }
- }
- }
-
- CharSequence sub;
-
- if (altered) {
- if (alter == null)
- alter = AlteredCharSequence.make(source, chs, start, end);
- else
- alter.update(chs, start, end);
-
- sub = alter;
- } else {
- sub = source;
- }
-
- int width = firstwidth;
-
- float w = 0;
- int here = start;
-
- int ok = start;
- float okwidth = w;
- int okascent = 0, okdescent = 0, oktop = 0, okbottom = 0;
-
- int fit = start;
- float fitwidth = w;
- int fitascent = 0, fitdescent = 0, fittop = 0, fitbottom = 0;
-
- boolean tab = false;
-
- int next;
- for (int i = start; i < end; i = next) {
- if (spanned == null)
- next = end;
- else
- next = spanned.nextSpanTransition(i, end,
- MetricAffectingSpan.
- class);
-
- if (spanned == null) {
- paint.getTextWidths(sub, i, next, widths);
- System.arraycopy(widths, 0, widths,
- end - start + (i - start), next - i);
-
- paint.getFontMetricsInt(fm);
- } else {
- mWorkPaint.baselineShift = 0;
-
- Styled.getTextWidths(paint, mWorkPaint,
- spanned, i, next,
- widths, fm);
- System.arraycopy(widths, 0, widths,
- end - start + (i - start), next - i);
-
- if (mWorkPaint.baselineShift < 0) {
- fm.ascent += mWorkPaint.baselineShift;
- fm.top += mWorkPaint.baselineShift;
- } else {
- fm.descent += mWorkPaint.baselineShift;
- fm.bottom += mWorkPaint.baselineShift;
- }
- }
-
- int fmtop = fm.top;
- int fmbottom = fm.bottom;
- int fmascent = fm.ascent;
- int fmdescent = fm.descent;
-
- if (false) {
- StringBuilder sb = new StringBuilder();
- for (int j = i; j < next; j++) {
- sb.append(widths[j - start + (end - start)]);
- sb.append(' ');
- }
-
- Log.e("text", sb.toString());
- }
-
- for (int j = i; j < next; j++) {
- char c = chs[j - start];
- float before = w;
-
- switch (c) {
- case '\n':
- break;
-
- case '\t':
- w = Layout.nextTab(sub, start, end, w, null);
- tab = true;
- break;
-
- default:
- w += widths[j - start + (end - start)];
- }
-
- // Log.e("text", "was " + before + " now " + w + " after " + c + " within " + width);
-
- if (w <= width) {
- fitwidth = w;
- fit = j + 1;
-
- if (fmtop < fittop)
- fittop = fmtop;
- if (fmascent < fitascent)
- fitascent = fmascent;
- if (fmdescent > fitdescent)
- fitdescent = fmdescent;
- if (fmbottom > fitbottom)
- fitbottom = fmbottom;
-
- /*
- * From the Unicode Line Breaking Algorithm:
- * (at least approximately)
- *
- * .,:; are class IS: breakpoints
- * except when adjacent to digits
- * / is class SY: a breakpoint
- * except when followed by a digit.
- * - is class HY: a breakpoint
- * except when followed by a digit.
- *
- * Ideographs are class ID: breakpoints when adjacent.
- */
-
- if (c == ' ' || c == '\t' ||
- ((c == '.' || c == ',' || c == ':' || c == ';') &&
- (j - 1 < here || !Character.isDigit(chs[j - 1 - start])) &&
- (j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) ||
- ((c == '/' || c == '-') &&
- (j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) ||
- (c >= FIRST_CJK && isIdeographic(c) &&
- j + 1 < next && isIdeographic(chs[j + 1 - start]))) {
- okwidth = w;
- ok = j + 1;
-
- if (fittop < oktop)
- oktop = fittop;
- if (fitascent < okascent)
- okascent = fitascent;
- if (fitdescent > okdescent)
- okdescent = fitdescent;
- if (fitbottom > okbottom)
- okbottom = fitbottom;
- }
- } else if (breakOnlyAtSpaces) {
- if (ok != here) {
- // Log.e("text", "output ok " + here + " to " +ok);
-
- while (ok < next && chs[ok - start] == ' ') {
- ok++;
- }
-
- v = out(source,
- here, ok,
- okascent, okdescent, oktop, okbottom,
- v,
- spacingmult, spacingadd, chooseht,
- choosehtv, fm, tab,
- needMultiply, start, chdirs, dir, easy,
- ok == bufend, includepad, trackpad,
- widths, start, end - start,
- where, ellipsizedWidth, okwidth,
- paint);
-
- here = ok;
- } else {
- // Act like it fit even though it didn't.
-
- fitwidth = w;
- fit = j + 1;
-
- if (fmtop < fittop)
- fittop = fmtop;
- if (fmascent < fitascent)
- fitascent = fmascent;
- if (fmdescent > fitdescent)
- fitdescent = fmdescent;
- if (fmbottom > fitbottom)
- fitbottom = fmbottom;
- }
- } else {
- if (ok != here) {
- // Log.e("text", "output ok " + here + " to " +ok);
-
- while (ok < next && chs[ok - start] == ' ') {
- ok++;
- }
-
- v = out(source,
- here, ok,
- okascent, okdescent, oktop, okbottom,
- v,
- spacingmult, spacingadd, chooseht,
- choosehtv, fm, tab,
- needMultiply, start, chdirs, dir, easy,
- ok == bufend, includepad, trackpad,
- widths, start, end - start,
- where, ellipsizedWidth, okwidth,
- paint);
-
- here = ok;
- } else if (fit != here) {
- // Log.e("text", "output fit " + here + " to " +fit);
- v = out(source,
- here, fit,
- fitascent, fitdescent,
- fittop, fitbottom,
- v,
- spacingmult, spacingadd, chooseht,
- choosehtv, fm, tab,
- needMultiply, start, chdirs, dir, easy,
- fit == bufend, includepad, trackpad,
- widths, start, end - start,
- where, ellipsizedWidth, fitwidth,
- paint);
-
- here = fit;
- } else {
- // Log.e("text", "output one " + here + " to " +(here + 1));
- measureText(paint, mWorkPaint,
- source, here, here + 1, fm, tab,
- null);
-
- v = out(source,
- here, here+1,
- fm.ascent, fm.descent,
- fm.top, fm.bottom,
- v,
- spacingmult, spacingadd, chooseht,
- choosehtv, fm, tab,
- needMultiply, start, chdirs, dir, easy,
- here + 1 == bufend, includepad,
- trackpad,
- widths, start, end - start,
- where, ellipsizedWidth,
- widths[here - start], paint);
-
- here = here + 1;
- }
-
- if (here < i) {
- j = next = here; // must remeasure
- } else {
- j = here - 1; // continue looping
- }
-
- ok = fit = here;
- w = 0;
- fitascent = fitdescent = fittop = fitbottom = 0;
- okascent = okdescent = oktop = okbottom = 0;
-
- width = restwidth;
- }
- }
- }
-
- if (end != here) {
- if ((fittop | fitbottom | fitdescent | fitascent) == 0) {
- paint.getFontMetricsInt(fm);
-
- fittop = fm.top;
- fitbottom = fm.bottom;
- fitascent = fm.ascent;
- fitdescent = fm.descent;
- }
-
- // Log.e("text", "output rest " + here + " to " + end);
-
- v = out(source,
- here, end, fitascent, fitdescent,
- fittop, fitbottom,
- v,
- spacingmult, spacingadd, chooseht,
- choosehtv, fm, tab,
- needMultiply, start, chdirs, dir, easy,
- end == bufend, includepad, trackpad,
- widths, start, end - start,
- where, ellipsizedWidth, w, paint);
- }
-
- start = end;
-
- if (end == bufend)
- break;
- }
-
- if (bufend == bufstart || source.charAt(bufend - 1) == '\n') {
- // Log.e("text", "output last " + bufend);
-
- paint.getFontMetricsInt(fm);
-
- v = out(source,
- bufend, bufend, fm.ascent, fm.descent,
- fm.top, fm.bottom,
- v,
- spacingmult, spacingadd, null,
- null, fm, false,
- needMultiply, bufend, chdirs, DEFAULT_DIR, true,
- true, includepad, trackpad,
- widths, bufstart, 0,
- where, ellipsizedWidth, 0, paint);
- }
- }
-
- private static final char FIRST_CJK = '\u2E80';
- /**
- * Returns true if the specified character is one of those specified
- * as being Ideographic (class ID) by the Unicode Line Breaking Algorithm
- * (http://www.unicode.org/unicode/reports/tr14/), and is therefore OK
- * to break between a pair of.
- */
- private static final boolean isIdeographic(char c) {
- if (c >= '\u2E80' && c <= '\u2FFF') {
- return true; // CJK, KANGXI RADICALS, DESCRIPTION SYMBOLS
- }
- if (c == '\u3000') {
- return true; // IDEOGRAPHIC SPACE
- }
- if (c >= '\u3040' && c <= '\u309F') {
- return true; // Hiragana (except small characters)
- }
- if (c >= '\u30A0' && c <= '\u30FF') {
- return true; // Katakana (except small characters)
- }
- if (c >= '\u3400' && c <= '\u4DB5') {
- return true; // CJK UNIFIED IDEOGRAPHS EXTENSION A
- }
- if (c >= '\u4E00' && c <= '\u9FBB') {
- return true; // CJK UNIFIED IDEOGRAPHS
- }
- if (c >= '\uF900' && c <= '\uFAD9') {
- return true; // CJK COMPATIBILITY IDEOGRAPHS
- }
- if (c >= '\uA000' && c <= '\uA48F') {
- return true; // YI SYLLABLES
- }
- if (c >= '\uA490' && c <= '\uA4CF') {
- return true; // YI RADICALS
- }
- if (c >= '\uFE62' && c <= '\uFE66') {
- return true; // SMALL PLUS SIGN to SMALL EQUALS SIGN
- }
- if (c >= '\uFF10' && c <= '\uFF19') {
- return true; // WIDE DIGITS
- }
-
- return false;
- }
-
-/*
- private static void dump(byte[] data, int count, String label) {
- if (false) {
- System.out.print(label);
-
- for (int i = 0; i < count; i++)
- System.out.print(" " + data[i]);
-
- System.out.println();
- }
- }
-*/
-
- private static int getFit(TextPaint paint,
- TextPaint workPaint,
- CharSequence text, int start, int end,
- float wid) {
- int high = end + 1, low = start - 1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
-
- if (measureText(paint, workPaint,
- text, start, guess, null, true, null) > wid)
- high = guess;
- else
- low = guess;
- }
-
- if (low < start)
- return start;
- else
- return low;
- }
-
- private int out(CharSequence text, int start, int end,
- int above, int below, int top, int bottom, int v,
- float spacingmult, float spacingadd,
- LineHeightSpan[] chooseht, int[] choosehtv,
- Paint.FontMetricsInt fm, boolean tab,
- boolean needMultiply, int pstart, byte[] chdirs,
- int dir, boolean easy, boolean last,
- boolean includepad, boolean trackpad,
- float[] widths, int widstart, int widoff,
- TextUtils.TruncateAt ellipsize, float ellipsiswidth,
- float textwidth, TextPaint paint) {
- int j = mLineCount;
- int off = j * mColumns;
- int want = off + mColumns + TOP;
- int[] lines = mLines;
-
- // Log.e("text", "line " + start + " to " + end + (last ? "===" : ""));
-
- if (want >= lines.length) {
- int nlen = ArrayUtils.idealIntArraySize(want + 1);
- int[] grow = new int[nlen];
- System.arraycopy(lines, 0, grow, 0, lines.length);
- mLines = grow;
- lines = grow;
-
- Directions[] grow2 = new Directions[nlen];
- System.arraycopy(mLineDirections, 0, grow2, 0,
- mLineDirections.length);
- mLineDirections = grow2;
- }
-
- if (chooseht != null) {
- fm.ascent = above;
- fm.descent = below;
- fm.top = top;
- fm.bottom = bottom;
-
- for (int i = 0; i < chooseht.length; i++) {
- chooseht[i].chooseHeight(text, start, end, choosehtv[i], v, fm);
- }
-
- above = fm.ascent;
- below = fm.descent;
- top = fm.top;
- bottom = fm.bottom;
- }
-
- if (j == 0) {
- if (trackpad) {
- mTopPadding = top - above;
- }
-
- if (includepad) {
- above = top;
- }
- }
- if (last) {
- if (trackpad) {
- mBottomPadding = bottom - below;
- }
-
- if (includepad) {
- below = bottom;
- }
- }
-
- int extra;
-
- if (needMultiply) {
- extra = (int) ((below - above) * (spacingmult - 1)
- + spacingadd + 0.5);
- } else {
- extra = 0;
- }
-
- lines[off + START] = start;
- lines[off + TOP] = v;
- lines[off + DESCENT] = below + extra;
-
- v += (below - above) + extra;
- lines[off + mColumns + START] = end;
- lines[off + mColumns + TOP] = v;
-
- if (tab)
- lines[off + TAB] |= TAB_MASK;
-
- {
- lines[off + DIR] |= dir << DIR_SHIFT;
-
- int cur = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
- int count = 0;
-
- if (!easy) {
- for (int k = start; k < end; k++) {
- if (chdirs[k - pstart] != cur) {
- count++;
- cur = chdirs[k - pstart];
- }
- }
- }
-
- Directions linedirs;
-
- if (count == 0) {
- linedirs = DIRS_ALL_LEFT_TO_RIGHT;
- } else {
- short[] ld = new short[count + 1];
-
- cur = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
- count = 0;
- int here = start;
-
- for (int k = start; k < end; k++) {
- if (chdirs[k - pstart] != cur) {
- // XXX check to make sure we don't
- // overflow short
- ld[count++] = (short) (k - here);
- cur = chdirs[k - pstart];
- here = k;
- }
- }
-
- ld[count] = (short) (end - here);
-
- if (count == 1 && ld[0] == 0) {
- linedirs = DIRS_ALL_RIGHT_TO_LEFT;
- } else {
- linedirs = new Directions(ld);
- }
- }
-
- mLineDirections[j] = linedirs;
-
- // If ellipsize is in marquee mode, do not apply ellipsis on the first line
- if (ellipsize != null && (ellipsize != TextUtils.TruncateAt.MARQUEE || j != 0)) {
- calculateEllipsis(start, end, widths, widstart, widoff,
- ellipsiswidth, ellipsize, j,
- textwidth, paint);
- }
- }
-
- mLineCount++;
- return v;
- }
-
- private void calculateEllipsis(int linestart, int lineend,
- float[] widths, int widstart, int widoff,
- float avail, TextUtils.TruncateAt where,
- int line, float textwidth, TextPaint paint) {
- int len = lineend - linestart;
-
- if (textwidth <= avail) {
- // Everything fits!
- mLines[mColumns * line + ELLIPSIS_START] = 0;
- mLines[mColumns * line + ELLIPSIS_COUNT] = 0;
- return;
- }
-
- float ellipsiswid = paint.measureText("\u2026");
- int ellipsisStart, ellipsisCount;
-
- if (where == TextUtils.TruncateAt.START) {
- float sum = 0;
- int i;
-
- for (i = len; i >= 0; i--) {
- float w = widths[i - 1 + linestart - widstart + widoff];
-
- if (w + sum + ellipsiswid > avail) {
- break;
- }
-
- sum += w;
- }
-
- ellipsisStart = 0;
- ellipsisCount = i;
- } else if (where == TextUtils.TruncateAt.END || where == TextUtils.TruncateAt.MARQUEE) {
- float sum = 0;
- int i;
-
- for (i = 0; i < len; i++) {
- float w = widths[i + linestart - widstart + widoff];
-
- if (w + sum + ellipsiswid > avail) {
- break;
- }
-
- sum += w;
- }
-
- ellipsisStart = i;
- ellipsisCount = len - i;
- } else /* where = TextUtils.TruncateAt.MIDDLE */ {
- float lsum = 0, rsum = 0;
- int left = 0, right = len;
-
- float ravail = (avail - ellipsiswid) / 2;
- for (right = len; right >= 0; right--) {
- float w = widths[right - 1 + linestart - widstart + widoff];
-
- if (w + rsum > ravail) {
- break;
- }
-
- rsum += w;
- }
-
- float lavail = avail - ellipsiswid - rsum;
- for (left = 0; left < right; left++) {
- float w = widths[left + linestart - widstart + widoff];
-
- if (w + lsum > lavail) {
- break;
- }
-
- lsum += w;
- }
-
- ellipsisStart = left;
- ellipsisCount = right - left;
- }
-
- mLines[mColumns * line + ELLIPSIS_START] = ellipsisStart;
- mLines[mColumns * line + ELLIPSIS_COUNT] = ellipsisCount;
- }
-
- // Override the baseclass so we can directly access our members,
- // rather than relying on member functions.
- // The logic mirrors that of Layout.getLineForVertical
- // FIXME: It may be faster to do a linear search for layouts without many lines.
- public int getLineForVertical(int vertical) {
- int high = mLineCount;
- int low = -1;
- int guess;
- int[] lines = mLines;
- while (high - low > 1) {
- guess = (high + low) >> 1;
- if (lines[mColumns * guess + TOP] > vertical){
- high = guess;
- } else {
- low = guess;
- }
- }
- if (low < 0) {
- return 0;
- } else {
- return low;
- }
- }
-
- public int getLineCount() {
- return mLineCount;
- }
-
- public int getLineTop(int line) {
- return mLines[mColumns * line + TOP];
- }
-
- public int getLineDescent(int line) {
- return mLines[mColumns * line + DESCENT];
- }
-
- public int getLineStart(int line) {
- return mLines[mColumns * line + START] & START_MASK;
- }
-
- public int getParagraphDirection(int line) {
- return mLines[mColumns * line + DIR] >> DIR_SHIFT;
- }
-
- public boolean getLineContainsTab(int line) {
- return (mLines[mColumns * line + TAB] & TAB_MASK) != 0;
- }
-
- public final Directions getLineDirections(int line) {
- return mLineDirections[line];
- }
-
- public int getTopPadding() {
- return mTopPadding;
- }
-
- public int getBottomPadding() {
- return mBottomPadding;
- }
-
- @Override
- public int getEllipsisCount(int line) {
- if (mColumns < COLUMNS_ELLIPSIZE) {
- return 0;
- }
-
- return mLines[mColumns * line + ELLIPSIS_COUNT];
- }
-
- @Override
- public int getEllipsisStart(int line) {
- if (mColumns < COLUMNS_ELLIPSIZE) {
- return 0;
- }
-
- return mLines[mColumns * line + ELLIPSIS_START];
- }
-
- @Override
- public int getEllipsizedWidth() {
- return mEllipsizedWidth;
- }
-
- private int mLineCount;
- private int mTopPadding, mBottomPadding;
- private int mColumns;
- private int mEllipsizedWidth;
-
- private static final int COLUMNS_NORMAL = 3;
- private static final int COLUMNS_ELLIPSIZE = 5;
- private static final int START = 0;
- private static final int DIR = START;
- private static final int TAB = START;
- private static final int TOP = 1;
- private static final int DESCENT = 2;
- private static final int ELLIPSIS_START = 3;
- private static final int ELLIPSIS_COUNT = 4;
-
- private int[] mLines;
- private Directions[] mLineDirections;
-
- private static final int START_MASK = 0x1FFFFFFF;
- private static final int DIR_MASK = 0xC0000000;
- private static final int DIR_SHIFT = 30;
- private static final int TAB_MASK = 0x20000000;
-
- private static final char FIRST_RIGHT_TO_LEFT = '\u0590';
-
- /*
- * These are reused across calls to generate()
- */
- private byte[] mChdirs;
- private char[] mChs;
- private float[] mWidths;
- private Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
-}
diff --git a/core/java/android/text/Styled.java b/core/java/android/text/Styled.java
deleted file mode 100644
index 05c27ea..0000000
--- a/core/java/android/text/Styled.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.graphics.Path;
-import android.graphics.RectF;
-import android.graphics.Typeface;
-import android.graphics.MaskFilter;
-import android.graphics.Rasterizer;
-import android.graphics.LayerRasterizer;
-import android.text.style.*;
-
-/* package */ class Styled
-{
- private static float each(Canvas canvas,
- Spanned text, int start, int end,
- int dir, boolean reverse,
- float x, int top, int y, int bottom,
- Paint.FontMetricsInt fm,
- TextPaint realPaint,
- TextPaint paint,
- boolean needwid) {
-
- boolean havewid = false;
- float ret = 0;
- CharacterStyle[] spans = text.getSpans(start, end, CharacterStyle.class);
-
- ReplacementSpan replacement = null;
-
- realPaint.bgColor = 0;
- realPaint.baselineShift = 0;
- paint.set(realPaint);
-
- if (spans.length > 0) {
- for (int i = 0; i < spans.length; i++) {
- CharacterStyle span = spans[i];
-
- if (span instanceof ReplacementSpan) {
- replacement = (ReplacementSpan)span;
- }
- else {
- span.updateDrawState(paint);
- }
- }
- }
-
- if (replacement == null) {
- CharSequence tmp;
- int tmpstart, tmpend;
-
- if (reverse) {
- tmp = TextUtils.getReverse(text, start, end);
- tmpstart = 0;
- tmpend = end - start;
- } else {
- tmp = text;
- tmpstart = start;
- tmpend = end;
- }
-
- if (fm != null) {
- paint.getFontMetricsInt(fm);
- }
-
- if (canvas != null) {
- if (paint.bgColor != 0) {
- int c = paint.getColor();
- Paint.Style s = paint.getStyle();
- paint.setColor(paint.bgColor);
- paint.setStyle(Paint.Style.FILL);
-
- if (!havewid) {
- ret = paint.measureText(tmp, tmpstart, tmpend);
- havewid = true;
- }
-
- if (dir == Layout.DIR_RIGHT_TO_LEFT)
- canvas.drawRect(x - ret, top, x, bottom, paint);
- else
- canvas.drawRect(x, top, x + ret, bottom, paint);
-
- paint.setStyle(s);
- paint.setColor(c);
- }
-
- if (dir == Layout.DIR_RIGHT_TO_LEFT) {
- if (!havewid) {
- ret = paint.measureText(tmp, tmpstart, tmpend);
- havewid = true;
- }
-
- canvas.drawText(tmp, tmpstart, tmpend,
- x - ret, y + paint.baselineShift, paint);
- } else {
- if (needwid) {
- if (!havewid) {
- ret = paint.measureText(tmp, tmpstart, tmpend);
- havewid = true;
- }
- }
-
- canvas.drawText(tmp, tmpstart, tmpend,
- x, y + paint.baselineShift, paint);
- }
- } else {
- if (needwid && !havewid) {
- ret = paint.measureText(tmp, tmpstart, tmpend);
- havewid = true;
- }
- }
- } else {
- ret = replacement.getSize(paint, text, start, end, fm);
-
- if (canvas != null) {
- if (dir == Layout.DIR_RIGHT_TO_LEFT)
- replacement.draw(canvas, text, start, end,
- x - ret, top, y, bottom, paint);
- else
- replacement.draw(canvas, text, start, end,
- x, top, y, bottom, paint);
- }
- }
-
- if (dir == Layout.DIR_RIGHT_TO_LEFT)
- return -ret;
- else
- return ret;
- }
-
- public static int getTextWidths(TextPaint realPaint,
- TextPaint paint,
- Spanned text, int start, int end,
- float[] widths, Paint.FontMetricsInt fm) {
-
- MetricAffectingSpan[] spans = text.getSpans(start, end, MetricAffectingSpan.class);
-
- ReplacementSpan replacement = null;
- paint.set(realPaint);
-
- for (int i = 0; i < spans.length; i++) {
- MetricAffectingSpan span = spans[i];
- if (span instanceof ReplacementSpan) {
- replacement = (ReplacementSpan)span;
- }
- else {
- span.updateMeasureState(paint);
- }
- }
-
- if (replacement == null) {
- paint.getFontMetricsInt(fm);
- paint.getTextWidths(text, start, end, widths);
- } else {
- int wid = replacement.getSize(paint, text, start, end, fm);
-
- if (end > start) {
- widths[0] = wid;
-
- for (int i = start + 1; i < end; i++)
- widths[i - start] = 0;
- }
- }
- return end - start;
- }
-
- private static float foreach(Canvas canvas,
- CharSequence text, int start, int end,
- int dir, boolean reverse,
- float x, int top, int y, int bottom,
- Paint.FontMetricsInt fm,
- TextPaint paint,
- TextPaint workPaint,
- boolean needwid) {
- if (! (text instanceof Spanned)) {
- float ret = 0;
-
- if (reverse) {
- CharSequence tmp = TextUtils.getReverse(text, start, end);
- int tmpend = end - start;
-
- if (canvas != null || needwid)
- ret = paint.measureText(tmp, 0, tmpend);
-
- if (canvas != null)
- canvas.drawText(tmp, 0, tmpend,
- x - ret, y, paint);
- } else {
- if (needwid)
- ret = paint.measureText(text, start, end);
-
- if (canvas != null)
- canvas.drawText(text, start, end, x, y, paint);
- }
-
- if (fm != null) {
- paint.getFontMetricsInt(fm);
- }
-
- return ret * dir; //Layout.DIR_RIGHT_TO_LEFT == -1
- }
-
- float ox = x;
- int asc = 0, desc = 0;
- int ftop = 0, fbot = 0;
-
- Spanned sp = (Spanned) text;
- Class division;
-
- if (canvas == null)
- division = MetricAffectingSpan.class;
- else
- division = CharacterStyle.class;
-
- int next;
- for (int i = start; i < end; i = next) {
- next = sp.nextSpanTransition(i, end, division);
-
- x += each(canvas, sp, i, next, dir, reverse,
- x, top, y, bottom, fm, paint, workPaint,
- needwid || next != end);
-
- if (fm != null) {
- if (fm.ascent < asc)
- asc = fm.ascent;
- if (fm.descent > desc)
- desc = fm.descent;
-
- if (fm.top < ftop)
- ftop = fm.top;
- if (fm.bottom > fbot)
- fbot = fm.bottom;
- }
- }
-
- if (fm != null) {
- if (start == end) {
- paint.getFontMetricsInt(fm);
- } else {
- fm.ascent = asc;
- fm.descent = desc;
- fm.top = ftop;
- fm.bottom = fbot;
- }
- }
-
- return x - ox;
- }
-
- public static float drawText(Canvas canvas,
- CharSequence text, int start, int end,
- int dir, boolean reverse,
- float x, int top, int y, int bottom,
- TextPaint paint,
- TextPaint workPaint,
- boolean needwid) {
- if ((dir == Layout.DIR_RIGHT_TO_LEFT && !reverse)||(reverse && dir == Layout.DIR_LEFT_TO_RIGHT)) {
- float ch = foreach(null, text, start, end, Layout.DIR_LEFT_TO_RIGHT,
- false, 0, 0, 0, 0, null, paint, workPaint,
- true);
-
- ch *= dir; // DIR_RIGHT_TO_LEFT == -1
- foreach(canvas, text, start, end, -dir,
- reverse, x + ch, top, y, bottom, null, paint,
- workPaint, true);
-
- return ch;
- }
-
- return foreach(canvas, text, start, end, dir, reverse,
- x, top, y, bottom, null, paint, workPaint,
- needwid);
- }
-
- public static float measureText(TextPaint paint,
- TextPaint workPaint,
- CharSequence text, int start, int end,
- Paint.FontMetricsInt fm) {
- return foreach(null, text, start, end,
- Layout.DIR_LEFT_TO_RIGHT, false,
- 0, 0, 0, 0, fm, paint, workPaint, true);
- }
-}
diff --git a/core/java/android/text/TextPaint.java b/core/java/android/text/TextPaint.java
deleted file mode 100644
index f13820d..0000000
--- a/core/java/android/text/TextPaint.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-import android.graphics.Paint;
-
-/**
- * TextPaint is an extension of Paint that leaves room for some extra
- * data used during text measuring and drawing.
- */
-public class TextPaint extends Paint {
- public int bgColor;
- public int baselineShift;
- public int linkColor;
- public int[] drawableState;
-
- public TextPaint() {
- super();
- }
-
- public TextPaint(int flags) {
- super(flags);
- }
-
- public TextPaint(Paint p) {
- super(p);
- }
-
- /**
- * Copy the fields from tp into this TextPaint, including the
- * fields inherited from Paint.
- */
- public void set(TextPaint tp) {
- super.set(tp);
-
- bgColor = tp.bgColor;
- baselineShift = tp.baselineShift;
- linkColor = tp.linkColor;
- drawableState = tp.drawableState;
- }
-}
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
deleted file mode 100644
index 5b4c380..0000000
--- a/core/java/android/text/TextUtils.java
+++ /dev/null
@@ -1,1620 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-import com.android.internal.R;
-
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.method.TextKeyListener.Capitalize;
-import android.text.style.AbsoluteSizeSpan;
-import android.text.style.AlignmentSpan;
-import android.text.style.BackgroundColorSpan;
-import android.text.style.BulletSpan;
-import android.text.style.CharacterStyle;
-import android.text.style.ForegroundColorSpan;
-import android.text.style.LeadingMarginSpan;
-import android.text.style.MetricAffectingSpan;
-import android.text.style.QuoteSpan;
-import android.text.style.RelativeSizeSpan;
-import android.text.style.ReplacementSpan;
-import android.text.style.ScaleXSpan;
-import android.text.style.StrikethroughSpan;
-import android.text.style.StyleSpan;
-import android.text.style.SubscriptSpan;
-import android.text.style.SuperscriptSpan;
-import android.text.style.TextAppearanceSpan;
-import android.text.style.TypefaceSpan;
-import android.text.style.URLSpan;
-import android.text.style.UnderlineSpan;
-import android.util.Printer;
-
-import com.android.internal.util.ArrayUtils;
-
-import java.util.regex.Pattern;
-import java.util.Iterator;
-
-public class TextUtils {
- private TextUtils() { /* cannot be instantiated */ }
-
- private static String[] EMPTY_STRING_ARRAY = new String[]{};
-
- public static void getChars(CharSequence s, int start, int end,
- char[] dest, int destoff) {
- Class c = s.getClass();
-
- if (c == String.class)
- ((String) s).getChars(start, end, dest, destoff);
- else if (c == StringBuffer.class)
- ((StringBuffer) s).getChars(start, end, dest, destoff);
- else if (c == StringBuilder.class)
- ((StringBuilder) s).getChars(start, end, dest, destoff);
- else if (s instanceof GetChars)
- ((GetChars) s).getChars(start, end, dest, destoff);
- else {
- for (int i = start; i < end; i++)
- dest[destoff++] = s.charAt(i);
- }
- }
-
- public static int indexOf(CharSequence s, char ch) {
- return indexOf(s, ch, 0);
- }
-
- public static int indexOf(CharSequence s, char ch, int start) {
- Class c = s.getClass();
-
- if (c == String.class)
- return ((String) s).indexOf(ch, start);
-
- return indexOf(s, ch, start, s.length());
- }
-
- public static int indexOf(CharSequence s, char ch, int start, int end) {
- Class c = s.getClass();
-
- if (s instanceof GetChars || c == StringBuffer.class ||
- c == StringBuilder.class || c == String.class) {
- final int INDEX_INCREMENT = 500;
- char[] temp = obtain(INDEX_INCREMENT);
-
- while (start < end) {
- int segend = start + INDEX_INCREMENT;
- if (segend > end)
- segend = end;
-
- getChars(s, start, segend, temp, 0);
-
- int count = segend - start;
- for (int i = 0; i < count; i++) {
- if (temp[i] == ch) {
- recycle(temp);
- return i + start;
- }
- }
-
- start = segend;
- }
-
- recycle(temp);
- return -1;
- }
-
- for (int i = start; i < end; i++)
- if (s.charAt(i) == ch)
- return i;
-
- return -1;
- }
-
- public static int lastIndexOf(CharSequence s, char ch) {
- return lastIndexOf(s, ch, s.length() - 1);
- }
-
- public static int lastIndexOf(CharSequence s, char ch, int last) {
- Class c = s.getClass();
-
- if (c == String.class)
- return ((String) s).lastIndexOf(ch, last);
-
- return lastIndexOf(s, ch, 0, last);
- }
-
- public static int lastIndexOf(CharSequence s, char ch,
- int start, int last) {
- if (last < 0)
- return -1;
- if (last >= s.length())
- last = s.length() - 1;
-
- int end = last + 1;
-
- Class c = s.getClass();
-
- if (s instanceof GetChars || c == StringBuffer.class ||
- c == StringBuilder.class || c == String.class) {
- final int INDEX_INCREMENT = 500;
- char[] temp = obtain(INDEX_INCREMENT);
-
- while (start < end) {
- int segstart = end - INDEX_INCREMENT;
- if (segstart < start)
- segstart = start;
-
- getChars(s, segstart, end, temp, 0);
-
- int count = end - segstart;
- for (int i = count - 1; i >= 0; i--) {
- if (temp[i] == ch) {
- recycle(temp);
- return i + segstart;
- }
- }
-
- end = segstart;
- }
-
- recycle(temp);
- return -1;
- }
-
- for (int i = end - 1; i >= start; i--)
- if (s.charAt(i) == ch)
- return i;
-
- return -1;
- }
-
- public static int indexOf(CharSequence s, CharSequence needle) {
- return indexOf(s, needle, 0, s.length());
- }
-
- public static int indexOf(CharSequence s, CharSequence needle, int start) {
- return indexOf(s, needle, start, s.length());
- }
-
- public static int indexOf(CharSequence s, CharSequence needle,
- int start, int end) {
- int nlen = needle.length();
- if (nlen == 0)
- return start;
-
- char c = needle.charAt(0);
-
- for (;;) {
- start = indexOf(s, c, start);
- if (start > end - nlen) {
- break;
- }
-
- if (start < 0) {
- return -1;
- }
-
- if (regionMatches(s, start, needle, 0, nlen)) {
- return start;
- }
-
- start++;
- }
- return -1;
- }
-
- public static boolean regionMatches(CharSequence one, int toffset,
- CharSequence two, int ooffset,
- int len) {
- char[] temp = obtain(2 * len);
-
- getChars(one, toffset, toffset + len, temp, 0);
- getChars(two, ooffset, ooffset + len, temp, len);
-
- boolean match = true;
- for (int i = 0; i < len; i++) {
- if (temp[i] != temp[i + len]) {
- match = false;
- break;
- }
- }
-
- recycle(temp);
- return match;
- }
-
- /**
- * Create a new String object containing the given range of characters
- * from the source string. This is different than simply calling
- * {@link CharSequence#subSequence(int, int) CharSequence.subSequence}
- * in that it does not preserve any style runs in the source sequence,
- * allowing a more efficient implementation.
- */
- public static String substring(CharSequence source, int start, int end) {
- if (source instanceof String)
- return ((String) source).substring(start, end);
- if (source instanceof StringBuilder)
- return ((StringBuilder) source).substring(start, end);
- if (source instanceof StringBuffer)
- return ((StringBuffer) source).substring(start, end);
-
- char[] temp = obtain(end - start);
- getChars(source, start, end, temp, 0);
- String ret = new String(temp, 0, end - start);
- recycle(temp);
-
- return ret;
- }
-
- /**
- * Returns a string containing the tokens joined by delimiters.
- * @param tokens an array objects to be joined. Strings will be formed from
- * the objects by calling object.toString().
- */
- public static String join(CharSequence delimiter, Object[] tokens) {
- StringBuilder sb = new StringBuilder();
- boolean firstTime = true;
- for (Object token: tokens) {
- if (firstTime) {
- firstTime = false;
- } else {
- sb.append(delimiter);
- }
- sb.append(token);
- }
- return sb.toString();
- }
-
- /**
- * Returns a string containing the tokens joined by delimiters.
- * @param tokens an array objects to be joined. Strings will be formed from
- * the objects by calling object.toString().
- */
- public static String join(CharSequence delimiter, Iterable tokens) {
- StringBuilder sb = new StringBuilder();
- boolean firstTime = true;
- for (Object token: tokens) {
- if (firstTime) {
- firstTime = false;
- } else {
- sb.append(delimiter);
- }
- sb.append(token);
- }
- return sb.toString();
- }
-
- /**
- * String.split() returns [''] when the string to be split is empty. This returns []. This does
- * not remove any empty strings from the result. For example split("a,", "," ) returns {"a", ""}.
- *
- * @param text the string to split
- * @param expression the regular expression to match
- * @return an array of strings. The array will be empty if text is empty
- *
- * @throws NullPointerException if expression or text is null
- */
- public static String[] split(String text, String expression) {
- if (text.length() == 0) {
- return EMPTY_STRING_ARRAY;
- } else {
- return text.split(expression, -1);
- }
- }
-
- /**
- * Splits a string on a pattern. String.split() returns [''] when the string to be
- * split is empty. This returns []. This does not remove any empty strings from the result.
- * @param text the string to split
- * @param pattern the regular expression to match
- * @return an array of strings. The array will be empty if text is empty
- *
- * @throws NullPointerException if expression or text is null
- */
- public static String[] split(String text, Pattern pattern) {
- if (text.length() == 0) {
- return EMPTY_STRING_ARRAY;
- } else {
- return pattern.split(text, -1);
- }
- }
-
- /**
- * An interface for splitting strings according to rules that are opaque to the user of this
- * interface. This also has less overhead than split, which uses regular expressions and
- * allocates an array to hold the results.
- *
- * <p>The most efficient way to use this class is:
- *
- * <pre>
- * // Once
- * TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(delimiter);
- *
- * // Once per string to split
- * splitter.setString(string);
- * for (String s : splitter) {
- * ...
- * }
- * </pre>
- */
- public interface StringSplitter extends Iterable<String> {
- public void setString(String string);
- }
-
- /**
- * A simple string splitter.
- *
- * <p>If the final character in the string to split is the delimiter then no empty string will
- * be returned for the empty string after that delimeter. That is, splitting <tt>"a,b,"</tt> on
- * comma will return <tt>"a", "b"</tt>, not <tt>"a", "b", ""</tt>.
- */
- public static class SimpleStringSplitter implements StringSplitter, Iterator<String> {
- private String mString;
- private char mDelimiter;
- private int mPosition;
- private int mLength;
-
- /**
- * Initializes the splitter. setString may be called later.
- * @param delimiter the delimeter on which to split
- */
- public SimpleStringSplitter(char delimiter) {
- mDelimiter = delimiter;
- }
-
- /**
- * Sets the string to split
- * @param string the string to split
- */
- public void setString(String string) {
- mString = string;
- mPosition = 0;
- mLength = mString.length();
- }
-
- public Iterator<String> iterator() {
- return this;
- }
-
- public boolean hasNext() {
- return mPosition < mLength;
- }
-
- public String next() {
- int end = mString.indexOf(mDelimiter, mPosition);
- if (end == -1) {
- end = mLength;
- }
- String nextString = mString.substring(mPosition, end);
- mPosition = end + 1; // Skip the delimiter.
- return nextString;
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-
- public static CharSequence stringOrSpannedString(CharSequence source) {
- if (source == null)
- return null;
- if (source instanceof SpannedString)
- return source;
- if (source instanceof Spanned)
- return new SpannedString(source);
-
- return source.toString();
- }
-
- /**
- * Returns true if the string is null or 0-length.
- * @param str the string to be examined
- * @return true if str is null or zero length
- */
- public static boolean isEmpty(CharSequence str) {
- if (str == null || str.length() == 0)
- return true;
- else
- return false;
- }
-
- /**
- * Returns the length that the specified CharSequence would have if
- * spaces and control characters were trimmed from the start and end,
- * as by {@link String#trim}.
- */
- public static int getTrimmedLength(CharSequence s) {
- int len = s.length();
-
- int start = 0;
- while (start < len && s.charAt(start) <= ' ') {
- start++;
- }
-
- int end = len;
- while (end > start && s.charAt(end - 1) <= ' ') {
- end--;
- }
-
- return end - start;
- }
-
- /**
- * Returns true if a and b are equal, including if they are both null.
- * <p><i>Note: In platform versions 1.1 and earlier, this method only worked well if
- * both the arguments were instances of String.</i></p>
- * @param a first CharSequence to check
- * @param b second CharSequence to check
- * @return true if a and b are equal
- */
- public static boolean equals(CharSequence a, CharSequence b) {
- if (a == b) return true;
- int length;
- if (a != null && b != null && (length = a.length()) == b.length()) {
- if (a instanceof String && b instanceof String) {
- return a.equals(b);
- } else {
- for (int i = 0; i < length; i++) {
- if (a.charAt(i) != b.charAt(i)) return false;
- }
- return true;
- }
- }
- return false;
- }
-
- // XXX currently this only reverses chars, not spans
- public static CharSequence getReverse(CharSequence source,
- int start, int end) {
- return new Reverser(source, start, end);
- }
-
- private static class Reverser
- implements CharSequence, GetChars
- {
- public Reverser(CharSequence source, int start, int end) {
- mSource = source;
- mStart = start;
- mEnd = end;
- }
-
- public int length() {
- return mEnd - mStart;
- }
-
- public CharSequence subSequence(int start, int end) {
- char[] buf = new char[end - start];
-
- getChars(start, end, buf, 0);
- return new String(buf);
- }
-
- public String toString() {
- return subSequence(0, length()).toString();
- }
-
- public char charAt(int off) {
- return AndroidCharacter.getMirror(mSource.charAt(mEnd - 1 - off));
- }
-
- public void getChars(int start, int end, char[] dest, int destoff) {
- TextUtils.getChars(mSource, start + mStart, end + mStart,
- dest, destoff);
- AndroidCharacter.mirror(dest, 0, end - start);
-
- int len = end - start;
- int n = (end - start) / 2;
- for (int i = 0; i < n; i++) {
- char tmp = dest[destoff + i];
-
- dest[destoff + i] = dest[destoff + len - i - 1];
- dest[destoff + len - i - 1] = tmp;
- }
- }
-
- private CharSequence mSource;
- private int mStart;
- private int mEnd;
- }
-
- /** @hide */
- public static final int ALIGNMENT_SPAN = 1;
- /** @hide */
- public static final int FOREGROUND_COLOR_SPAN = 2;
- /** @hide */
- public static final int RELATIVE_SIZE_SPAN = 3;
- /** @hide */
- public static final int SCALE_X_SPAN = 4;
- /** @hide */
- public static final int STRIKETHROUGH_SPAN = 5;
- /** @hide */
- public static final int UNDERLINE_SPAN = 6;
- /** @hide */
- public static final int STYLE_SPAN = 7;
- /** @hide */
- public static final int BULLET_SPAN = 8;
- /** @hide */
- public static final int QUOTE_SPAN = 9;
- /** @hide */
- public static final int LEADING_MARGIN_SPAN = 10;
- /** @hide */
- public static final int URL_SPAN = 11;
- /** @hide */
- public static final int BACKGROUND_COLOR_SPAN = 12;
- /** @hide */
- public static final int TYPEFACE_SPAN = 13;
- /** @hide */
- public static final int SUPERSCRIPT_SPAN = 14;
- /** @hide */
- public static final int SUBSCRIPT_SPAN = 15;
- /** @hide */
- public static final int ABSOLUTE_SIZE_SPAN = 16;
- /** @hide */
- public static final int TEXT_APPEARANCE_SPAN = 17;
- /** @hide */
- public static final int ANNOTATION = 18;
-
- /**
- * Flatten a CharSequence and whatever styles can be copied across processes
- * into the parcel.
- */
- public static void writeToParcel(CharSequence cs, Parcel p,
- int parcelableFlags) {
- if (cs instanceof Spanned) {
- p.writeInt(0);
- p.writeString(cs.toString());
-
- Spanned sp = (Spanned) cs;
- Object[] os = sp.getSpans(0, cs.length(), Object.class);
-
- // note to people adding to this: check more specific types
- // before more generic types. also notice that it uses
- // "if" instead of "else if" where there are interfaces
- // so one object can be several.
-
- for (int i = 0; i < os.length; i++) {
- Object o = os[i];
- Object prop = os[i];
-
- if (prop instanceof CharacterStyle) {
- prop = ((CharacterStyle) prop).getUnderlying();
- }
-
- if (prop instanceof ParcelableSpan) {
- ParcelableSpan ps = (ParcelableSpan)prop;
- p.writeInt(ps.getSpanTypeId());
- ps.writeToParcel(p, parcelableFlags);
- writeWhere(p, sp, o);
- }
- }
-
- p.writeInt(0);
- } else {
- p.writeInt(1);
- if (cs != null) {
- p.writeString(cs.toString());
- } else {
- p.writeString(null);
- }
- }
- }
-
- private static void writeWhere(Parcel p, Spanned sp, Object o) {
- p.writeInt(sp.getSpanStart(o));
- p.writeInt(sp.getSpanEnd(o));
- p.writeInt(sp.getSpanFlags(o));
- }
-
- public static final Parcelable.Creator<CharSequence> CHAR_SEQUENCE_CREATOR
- = new Parcelable.Creator<CharSequence>() {
- /**
- * Read and return a new CharSequence, possibly with styles,
- * from the parcel.
- */
- public CharSequence createFromParcel(Parcel p) {
- int kind = p.readInt();
-
- if (kind == 1)
- return p.readString();
-
- SpannableString sp = new SpannableString(p.readString());
-
- while (true) {
- kind = p.readInt();
-
- if (kind == 0)
- break;
-
- switch (kind) {
- case ALIGNMENT_SPAN:
- readSpan(p, sp, new AlignmentSpan.Standard(p));
- break;
-
- case FOREGROUND_COLOR_SPAN:
- readSpan(p, sp, new ForegroundColorSpan(p));
- break;
-
- case RELATIVE_SIZE_SPAN:
- readSpan(p, sp, new RelativeSizeSpan(p));
- break;
-
- case SCALE_X_SPAN:
- readSpan(p, sp, new ScaleXSpan(p));
- break;
-
- case STRIKETHROUGH_SPAN:
- readSpan(p, sp, new StrikethroughSpan(p));
- break;
-
- case UNDERLINE_SPAN:
- readSpan(p, sp, new UnderlineSpan(p));
- break;
-
- case STYLE_SPAN:
- readSpan(p, sp, new StyleSpan(p));
- break;
-
- case BULLET_SPAN:
- readSpan(p, sp, new BulletSpan(p));
- break;
-
- case QUOTE_SPAN:
- readSpan(p, sp, new QuoteSpan(p));
- break;
-
- case LEADING_MARGIN_SPAN:
- readSpan(p, sp, new LeadingMarginSpan.Standard(p));
- break;
-
- case URL_SPAN:
- readSpan(p, sp, new URLSpan(p));
- break;
-
- case BACKGROUND_COLOR_SPAN:
- readSpan(p, sp, new BackgroundColorSpan(p));
- break;
-
- case TYPEFACE_SPAN:
- readSpan(p, sp, new TypefaceSpan(p));
- break;
-
- case SUPERSCRIPT_SPAN:
- readSpan(p, sp, new SuperscriptSpan(p));
- break;
-
- case SUBSCRIPT_SPAN:
- readSpan(p, sp, new SubscriptSpan(p));
- break;
-
- case ABSOLUTE_SIZE_SPAN:
- readSpan(p, sp, new AbsoluteSizeSpan(p));
- break;
-
- case TEXT_APPEARANCE_SPAN:
- readSpan(p, sp, new TextAppearanceSpan(p));
- break;
-
- case ANNOTATION:
- readSpan(p, sp, new Annotation(p));
- break;
-
- default:
- throw new RuntimeException("bogus span encoding " + kind);
- }
- }
-
- return sp;
- }
-
- public CharSequence[] newArray(int size)
- {
- return new CharSequence[size];
- }
- };
-
- /**
- * Debugging tool to print the spans in a CharSequence. The output will
- * be printed one span per line. If the CharSequence is not a Spanned,
- * then the entire string will be printed on a single line.
- */
- public static void dumpSpans(CharSequence cs, Printer printer, String prefix) {
- if (cs instanceof Spanned) {
- Spanned sp = (Spanned) cs;
- Object[] os = sp.getSpans(0, cs.length(), Object.class);
-
- for (int i = 0; i < os.length; i++) {
- Object o = os[i];
- printer.println(prefix + cs.subSequence(sp.getSpanStart(o),
- sp.getSpanEnd(o)) + ": "
- + Integer.toHexString(System.identityHashCode(o))
- + " " + o.getClass().getCanonicalName()
- + " (" + sp.getSpanStart(o) + "-" + sp.getSpanEnd(o)
- + ") fl=#" + sp.getSpanFlags(o));
- }
- } else {
- printer.println(prefix + cs + ": (no spans)");
- }
- }
-
- /**
- * Return a new CharSequence in which each of the source strings is
- * replaced by the corresponding element of the destinations.
- */
- public static CharSequence replace(CharSequence template,
- String[] sources,
- CharSequence[] destinations) {
- SpannableStringBuilder tb = new SpannableStringBuilder(template);
-
- for (int i = 0; i < sources.length; i++) {
- int where = indexOf(tb, sources[i]);
-
- if (where >= 0)
- tb.setSpan(sources[i], where, where + sources[i].length(),
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- for (int i = 0; i < sources.length; i++) {
- int start = tb.getSpanStart(sources[i]);
- int end = tb.getSpanEnd(sources[i]);
-
- if (start >= 0) {
- tb.replace(start, end, destinations[i]);
- }
- }
-
- return tb;
- }
-
- /**
- * Replace instances of "^1", "^2", etc. in the
- * <code>template</code> CharSequence with the corresponding
- * <code>values</code>. "^^" is used to produce a single caret in
- * the output. Only up to 9 replacement values are supported,
- * "^10" will be produce the first replacement value followed by a
- * '0'.
- *
- * @param template the input text containing "^1"-style
- * placeholder values. This object is not modified; a copy is
- * returned.
- *
- * @param values CharSequences substituted into the template. The
- * first is substituted for "^1", the second for "^2", and so on.
- *
- * @return the new CharSequence produced by doing the replacement
- *
- * @throws IllegalArgumentException if the template requests a
- * value that was not provided, or if more than 9 values are
- * provided.
- */
- public static CharSequence expandTemplate(CharSequence template,
- CharSequence... values) {
- if (values.length > 9) {
- throw new IllegalArgumentException("max of 9 values are supported");
- }
-
- SpannableStringBuilder ssb = new SpannableStringBuilder(template);
-
- try {
- int i = 0;
- while (i < ssb.length()) {
- if (ssb.charAt(i) == '^') {
- char next = ssb.charAt(i+1);
- if (next == '^') {
- ssb.delete(i+1, i+2);
- ++i;
- continue;
- } else if (Character.isDigit(next)) {
- int which = Character.getNumericValue(next) - 1;
- if (which < 0) {
- throw new IllegalArgumentException(
- "template requests value ^" + (which+1));
- }
- if (which >= values.length) {
- throw new IllegalArgumentException(
- "template requests value ^" + (which+1) +
- "; only " + values.length + " provided");
- }
- ssb.replace(i, i+2, values[which]);
- i += values[which].length();
- continue;
- }
- }
- ++i;
- }
- } catch (IndexOutOfBoundsException ignore) {
- // happens when ^ is the last character in the string.
- }
- return ssb;
- }
-
- public static int getOffsetBefore(CharSequence text, int offset) {
- if (offset == 0)
- return 0;
- if (offset == 1)
- return 0;
-
- char c = text.charAt(offset - 1);
-
- if (c >= '\uDC00' && c <= '\uDFFF') {
- char c1 = text.charAt(offset - 2);
-
- if (c1 >= '\uD800' && c1 <= '\uDBFF')
- offset -= 2;
- else
- offset -= 1;
- } else {
- offset -= 1;
- }
-
- if (text instanceof Spanned) {
- ReplacementSpan[] spans = ((Spanned) text).getSpans(offset, offset,
- ReplacementSpan.class);
-
- for (int i = 0; i < spans.length; i++) {
- int start = ((Spanned) text).getSpanStart(spans[i]);
- int end = ((Spanned) text).getSpanEnd(spans[i]);
-
- if (start < offset && end > offset)
- offset = start;
- }
- }
-
- return offset;
- }
-
- public static int getOffsetAfter(CharSequence text, int offset) {
- int len = text.length();
-
- if (offset == len)
- return len;
- if (offset == len - 1)
- return len;
-
- char c = text.charAt(offset);
-
- if (c >= '\uD800' && c <= '\uDBFF') {
- char c1 = text.charAt(offset + 1);
-
- if (c1 >= '\uDC00' && c1 <= '\uDFFF')
- offset += 2;
- else
- offset += 1;
- } else {
- offset += 1;
- }
-
- if (text instanceof Spanned) {
- ReplacementSpan[] spans = ((Spanned) text).getSpans(offset, offset,
- ReplacementSpan.class);
-
- for (int i = 0; i < spans.length; i++) {
- int start = ((Spanned) text).getSpanStart(spans[i]);
- int end = ((Spanned) text).getSpanEnd(spans[i]);
-
- if (start < offset && end > offset)
- offset = end;
- }
- }
-
- return offset;
- }
-
- private static void readSpan(Parcel p, Spannable sp, Object o) {
- sp.setSpan(o, p.readInt(), p.readInt(), p.readInt());
- }
-
- public static void copySpansFrom(Spanned source, int start, int end,
- Class kind,
- Spannable dest, int destoff) {
- if (kind == null) {
- kind = Object.class;
- }
-
- Object[] spans = source.getSpans(start, end, kind);
-
- for (int i = 0; i < spans.length; i++) {
- int st = source.getSpanStart(spans[i]);
- int en = source.getSpanEnd(spans[i]);
- int fl = source.getSpanFlags(spans[i]);
-
- if (st < start)
- st = start;
- if (en > end)
- en = end;
-
- dest.setSpan(spans[i], st - start + destoff, en - start + destoff,
- fl);
- }
- }
-
- public enum TruncateAt {
- START,
- MIDDLE,
- END,
- MARQUEE,
- }
-
- public interface EllipsizeCallback {
- /**
- * This method is called to report that the specified region of
- * text was ellipsized away by a call to {@link #ellipsize}.
- */
- public void ellipsized(int start, int end);
- }
-
- private static String sEllipsis = null;
-
- /**
- * Returns the original text if it fits in the specified width
- * given the properties of the specified Paint,
- * or, if it does not fit, a truncated
- * copy with ellipsis character added at the specified edge or center.
- */
- public static CharSequence ellipsize(CharSequence text,
- TextPaint p,
- float avail, TruncateAt where) {
- return ellipsize(text, p, avail, where, false, null);
- }
-
- /**
- * Returns the original text if it fits in the specified width
- * given the properties of the specified Paint,
- * or, if it does not fit, a copy with ellipsis character added
- * at the specified edge or center.
- * If <code>preserveLength</code> is specified, the returned copy
- * will be padded with zero-width spaces to preserve the original
- * length and offsets instead of truncating.
- * If <code>callback</code> is non-null, it will be called to
- * report the start and end of the ellipsized range.
- */
- public static CharSequence ellipsize(CharSequence text,
- TextPaint p,
- float avail, TruncateAt where,
- boolean preserveLength,
- EllipsizeCallback callback) {
- if (sEllipsis == null) {
- Resources r = Resources.getSystem();
- sEllipsis = r.getString(R.string.ellipsis);
- }
-
- int len = text.length();
-
- // Use Paint.breakText() for the non-Spanned case to avoid having
- // to allocate memory and accumulate the character widths ourselves.
-
- if (!(text instanceof Spanned)) {
- float wid = p.measureText(text, 0, len);
-
- if (wid <= avail) {
- if (callback != null) {
- callback.ellipsized(0, 0);
- }
-
- return text;
- }
-
- float ellipsiswid = p.measureText(sEllipsis);
-
- if (ellipsiswid > avail) {
- if (callback != null) {
- callback.ellipsized(0, len);
- }
-
- if (preserveLength) {
- char[] buf = obtain(len);
- for (int i = 0; i < len; i++) {
- buf[i] = '\uFEFF';
- }
- String ret = new String(buf, 0, len);
- recycle(buf);
- return ret;
- } else {
- return "";
- }
- }
-
- if (where == TruncateAt.START) {
- int fit = p.breakText(text, 0, len, false,
- avail - ellipsiswid, null);
-
- if (callback != null) {
- callback.ellipsized(0, len - fit);
- }
-
- if (preserveLength) {
- return blank(text, 0, len - fit);
- } else {
- return sEllipsis + text.toString().substring(len - fit, len);
- }
- } else if (where == TruncateAt.END) {
- int fit = p.breakText(text, 0, len, true,
- avail - ellipsiswid, null);
-
- if (callback != null) {
- callback.ellipsized(fit, len);
- }
-
- if (preserveLength) {
- return blank(text, fit, len);
- } else {
- return text.toString().substring(0, fit) + sEllipsis;
- }
- } else /* where == TruncateAt.MIDDLE */ {
- int right = p.breakText(text, 0, len, false,
- (avail - ellipsiswid) / 2, null);
- float used = p.measureText(text, len - right, len);
- int left = p.breakText(text, 0, len - right, true,
- avail - ellipsiswid - used, null);
-
- if (callback != null) {
- callback.ellipsized(left, len - right);
- }
-
- if (preserveLength) {
- return blank(text, left, len - right);
- } else {
- String s = text.toString();
- return s.substring(0, left) + sEllipsis +
- s.substring(len - right, len);
- }
- }
- }
-
- // But do the Spanned cases by hand, because it's such a pain
- // to iterate the span transitions backwards and getTextWidths()
- // will give us the information we need.
-
- // getTextWidths() always writes into the start of the array,
- // so measure each span into the first half and then copy the
- // results into the second half to use later.
-
- float[] wid = new float[len * 2];
- TextPaint temppaint = new TextPaint();
- Spanned sp = (Spanned) text;
-
- int next;
- for (int i = 0; i < len; i = next) {
- next = sp.nextSpanTransition(i, len, MetricAffectingSpan.class);
-
- Styled.getTextWidths(p, temppaint, sp, i, next, wid, null);
- System.arraycopy(wid, 0, wid, len + i, next - i);
- }
-
- float sum = 0;
- for (int i = 0; i < len; i++) {
- sum += wid[len + i];
- }
-
- if (sum <= avail) {
- if (callback != null) {
- callback.ellipsized(0, 0);
- }
-
- return text;
- }
-
- float ellipsiswid = p.measureText(sEllipsis);
-
- if (ellipsiswid > avail) {
- if (callback != null) {
- callback.ellipsized(0, len);
- }
-
- if (preserveLength) {
- char[] buf = obtain(len);
- for (int i = 0; i < len; i++) {
- buf[i] = '\uFEFF';
- }
- SpannableString ss = new SpannableString(new String(buf, 0, len));
- recycle(buf);
- copySpansFrom(sp, 0, len, Object.class, ss, 0);
- return ss;
- } else {
- return "";
- }
- }
-
- if (where == TruncateAt.START) {
- sum = 0;
- int i;
-
- for (i = len; i >= 0; i--) {
- float w = wid[len + i - 1];
-
- if (w + sum + ellipsiswid > avail) {
- break;
- }
-
- sum += w;
- }
-
- if (callback != null) {
- callback.ellipsized(0, i);
- }
-
- if (preserveLength) {
- SpannableString ss = new SpannableString(blank(text, 0, i));
- copySpansFrom(sp, 0, len, Object.class, ss, 0);
- return ss;
- } else {
- SpannableStringBuilder out = new SpannableStringBuilder(sEllipsis);
- out.insert(1, text, i, len);
-
- return out;
- }
- } else if (where == TruncateAt.END) {
- sum = 0;
- int i;
-
- for (i = 0; i < len; i++) {
- float w = wid[len + i];
-
- if (w + sum + ellipsiswid > avail) {
- break;
- }
-
- sum += w;
- }
-
- if (callback != null) {
- callback.ellipsized(i, len);
- }
-
- if (preserveLength) {
- SpannableString ss = new SpannableString(blank(text, i, len));
- copySpansFrom(sp, 0, len, Object.class, ss, 0);
- return ss;
- } else {
- SpannableStringBuilder out = new SpannableStringBuilder(sEllipsis);
- out.insert(0, text, 0, i);
-
- return out;
- }
- } else /* where = TruncateAt.MIDDLE */ {
- float lsum = 0, rsum = 0;
- int left = 0, right = len;
-
- float ravail = (avail - ellipsiswid) / 2;
- for (right = len; right >= 0; right--) {
- float w = wid[len + right - 1];
-
- if (w + rsum > ravail) {
- break;
- }
-
- rsum += w;
- }
-
- float lavail = avail - ellipsiswid - rsum;
- for (left = 0; left < right; left++) {
- float w = wid[len + left];
-
- if (w + lsum > lavail) {
- break;
- }
-
- lsum += w;
- }
-
- if (callback != null) {
- callback.ellipsized(left, right);
- }
-
- if (preserveLength) {
- SpannableString ss = new SpannableString(blank(text, left, right));
- copySpansFrom(sp, 0, len, Object.class, ss, 0);
- return ss;
- } else {
- SpannableStringBuilder out = new SpannableStringBuilder(sEllipsis);
- out.insert(0, text, 0, left);
- out.insert(out.length(), text, right, len);
-
- return out;
- }
- }
- }
-
- private static String blank(CharSequence source, int start, int end) {
- int len = source.length();
- char[] buf = obtain(len);
-
- if (start != 0) {
- getChars(source, 0, start, buf, 0);
- }
- if (end != len) {
- getChars(source, end, len, buf, end);
- }
-
- if (start != end) {
- buf[start] = '\u2026';
-
- for (int i = start + 1; i < end; i++) {
- buf[i] = '\uFEFF';
- }
- }
-
- String ret = new String(buf, 0, len);
- recycle(buf);
-
- return ret;
- }
-
- /**
- * Converts a CharSequence of the comma-separated form "Andy, Bob,
- * Charles, David" that is too wide to fit into the specified width
- * into one like "Andy, Bob, 2 more".
- *
- * @param text the text to truncate
- * @param p the Paint with which to measure the text
- * @param avail the horizontal width available for the text
- * @param oneMore the string for "1 more" in the current locale
- * @param more the string for "%d more" in the current locale
- */
- public static CharSequence commaEllipsize(CharSequence text,
- TextPaint p, float avail,
- String oneMore,
- String more) {
- int len = text.length();
- char[] buf = new char[len];
- TextUtils.getChars(text, 0, len, buf, 0);
-
- int commaCount = 0;
- for (int i = 0; i < len; i++) {
- if (buf[i] == ',') {
- commaCount++;
- }
- }
-
- float[] wid;
-
- if (text instanceof Spanned) {
- Spanned sp = (Spanned) text;
- TextPaint temppaint = new TextPaint();
- wid = new float[len * 2];
-
- int next;
- for (int i = 0; i < len; i = next) {
- next = sp.nextSpanTransition(i, len, MetricAffectingSpan.class);
-
- Styled.getTextWidths(p, temppaint, sp, i, next, wid, null);
- System.arraycopy(wid, 0, wid, len + i, next - i);
- }
-
- System.arraycopy(wid, len, wid, 0, len);
- } else {
- wid = new float[len];
- p.getTextWidths(text, 0, len, wid);
- }
-
- int ok = 0;
- int okRemaining = commaCount + 1;
- String okFormat = "";
-
- int w = 0;
- int count = 0;
-
- for (int i = 0; i < len; i++) {
- w += wid[i];
-
- if (buf[i] == ',') {
- count++;
-
- int remaining = commaCount - count + 1;
- float moreWid;
- String format;
-
- if (remaining == 1) {
- format = " " + oneMore;
- } else {
- format = " " + String.format(more, remaining);
- }
-
- moreWid = p.measureText(format);
-
- if (w + moreWid <= avail) {
- ok = i + 1;
- okRemaining = remaining;
- okFormat = format;
- }
- }
- }
-
- if (w <= avail) {
- return text;
- } else {
- SpannableStringBuilder out = new SpannableStringBuilder(okFormat);
- out.insert(0, text, 0, ok);
- return out;
- }
- }
-
- /* package */ static char[] obtain(int len) {
- char[] buf;
-
- synchronized (sLock) {
- buf = sTemp;
- sTemp = null;
- }
-
- if (buf == null || buf.length < len)
- buf = new char[ArrayUtils.idealCharArraySize(len)];
-
- return buf;
- }
-
- /* package */ static void recycle(char[] temp) {
- if (temp.length > 1000)
- return;
-
- synchronized (sLock) {
- sTemp = temp;
- }
- }
-
- /**
- * Html-encode the string.
- * @param s the string to be encoded
- * @return the encoded string
- */
- public static String htmlEncode(String s) {
- StringBuilder sb = new StringBuilder();
- char c;
- for (int i = 0; i < s.length(); i++) {
- c = s.charAt(i);
- switch (c) {
- case '<':
- sb.append("&lt;"); //$NON-NLS-1$
- break;
- case '>':
- sb.append("&gt;"); //$NON-NLS-1$
- break;
- case '&':
- sb.append("&amp;"); //$NON-NLS-1$
- break;
- case '\'':
- sb.append("&apos;"); //$NON-NLS-1$
- break;
- case '"':
- sb.append("&quot;"); //$NON-NLS-1$
- break;
- default:
- sb.append(c);
- }
- }
- return sb.toString();
- }
-
- /**
- * Returns a CharSequence concatenating the specified CharSequences,
- * retaining their spans if any.
- */
- public static CharSequence concat(CharSequence... text) {
- if (text.length == 0) {
- return "";
- }
-
- if (text.length == 1) {
- return text[0];
- }
-
- boolean spanned = false;
- for (int i = 0; i < text.length; i++) {
- if (text[i] instanceof Spanned) {
- spanned = true;
- break;
- }
- }
-
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < text.length; i++) {
- sb.append(text[i]);
- }
-
- if (!spanned) {
- return sb.toString();
- }
-
- SpannableString ss = new SpannableString(sb);
- int off = 0;
- for (int i = 0; i < text.length; i++) {
- int len = text[i].length();
-
- if (text[i] instanceof Spanned) {
- copySpansFrom((Spanned) text[i], 0, len, Object.class, ss, off);
- }
-
- off += len;
- }
-
- return new SpannedString(ss);
- }
-
- /**
- * Returns whether the given CharSequence contains any printable characters.
- */
- public static boolean isGraphic(CharSequence str) {
- final int len = str.length();
- for (int i=0; i<len; i++) {
- int gc = Character.getType(str.charAt(i));
- if (gc != Character.CONTROL
- && gc != Character.FORMAT
- && gc != Character.SURROGATE
- && gc != Character.UNASSIGNED
- && gc != Character.LINE_SEPARATOR
- && gc != Character.PARAGRAPH_SEPARATOR
- && gc != Character.SPACE_SEPARATOR) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns whether this character is a printable character.
- */
- public static boolean isGraphic(char c) {
- int gc = Character.getType(c);
- return gc != Character.CONTROL
- && gc != Character.FORMAT
- && gc != Character.SURROGATE
- && gc != Character.UNASSIGNED
- && gc != Character.LINE_SEPARATOR
- && gc != Character.PARAGRAPH_SEPARATOR
- && gc != Character.SPACE_SEPARATOR;
- }
-
- /**
- * Returns whether the given CharSequence contains only digits.
- */
- public static boolean isDigitsOnly(CharSequence str) {
- final int len = str.length();
- for (int i = 0; i < len; i++) {
- if (!Character.isDigit(str.charAt(i))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Capitalization mode for {@link #getCapsMode}: capitalize all
- * characters. This value is explicitly defined to be the same as
- * {@link InputType#TYPE_TEXT_FLAG_CAP_CHARACTERS}.
- */
- public static final int CAP_MODE_CHARACTERS
- = InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
-
- /**
- * Capitalization mode for {@link #getCapsMode}: capitalize the first
- * character of all words. This value is explicitly defined to be the same as
- * {@link InputType#TYPE_TEXT_FLAG_CAP_WORDS}.
- */
- public static final int CAP_MODE_WORDS
- = InputType.TYPE_TEXT_FLAG_CAP_WORDS;
-
- /**
- * Capitalization mode for {@link #getCapsMode}: capitalize the first
- * character of each sentence. This value is explicitly defined to be the same as
- * {@link InputType#TYPE_TEXT_FLAG_CAP_SENTENCES}.
- */
- public static final int CAP_MODE_SENTENCES
- = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
-
- /**
- * Determine what caps mode should be in effect at the current offset in
- * the text. Only the mode bits set in <var>reqModes</var> will be
- * checked. Note that the caps mode flags here are explicitly defined
- * to match those in {@link InputType}.
- *
- * @param cs The text that should be checked for caps modes.
- * @param off Location in the text at which to check.
- * @param reqModes The modes to be checked: may be any combination of
- * {@link #CAP_MODE_CHARACTERS}, {@link #CAP_MODE_WORDS}, and
- * {@link #CAP_MODE_SENTENCES}.
- *
- * @return Returns the actual capitalization modes that can be in effect
- * at the current position, which is any combination of
- * {@link #CAP_MODE_CHARACTERS}, {@link #CAP_MODE_WORDS}, and
- * {@link #CAP_MODE_SENTENCES}.
- */
- public static int getCapsMode(CharSequence cs, int off, int reqModes) {
- int i;
- char c;
- int mode = 0;
-
- if ((reqModes&CAP_MODE_CHARACTERS) != 0) {
- mode |= CAP_MODE_CHARACTERS;
- }
- if ((reqModes&(CAP_MODE_WORDS|CAP_MODE_SENTENCES)) == 0) {
- return mode;
- }
-
- // Back over allowed opening punctuation.
-
- for (i = off; i > 0; i--) {
- c = cs.charAt(i - 1);
-
- if (c != '"' && c != '\'' &&
- Character.getType(c) != Character.START_PUNCTUATION) {
- break;
- }
- }
-
- // Start of paragraph, with optional whitespace.
-
- int j = i;
- while (j > 0 && ((c = cs.charAt(j - 1)) == ' ' || c == '\t')) {
- j--;
- }
- if (j == 0 || cs.charAt(j - 1) == '\n') {
- return mode | CAP_MODE_WORDS;
- }
-
- // Or start of word if we are that style.
-
- if ((reqModes&CAP_MODE_SENTENCES) == 0) {
- if (i != j) mode |= CAP_MODE_WORDS;
- return mode;
- }
-
- // There must be a space if not the start of paragraph.
-
- if (i == j) {
- return mode;
- }
-
- // Back over allowed closing punctuation.
-
- for (; j > 0; j--) {
- c = cs.charAt(j - 1);
-
- if (c != '"' && c != '\'' &&
- Character.getType(c) != Character.END_PUNCTUATION) {
- break;
- }
- }
-
- if (j > 0) {
- c = cs.charAt(j - 1);
-
- if (c == '.' || c == '?' || c == '!') {
- // Do not capitalize if the word ends with a period but
- // also contains a period, in which case it is an abbreviation.
-
- if (c == '.') {
- for (int k = j - 2; k >= 0; k--) {
- c = cs.charAt(k);
-
- if (c == '.') {
- return mode;
- }
-
- if (!Character.isLetter(c)) {
- break;
- }
- }
- }
-
- return mode | CAP_MODE_SENTENCES;
- }
- }
-
- return mode;
- }
-
- private static Object sLock = new Object();
- private static char[] sTemp = null;
-}
diff --git a/core/java/android/text/TextWatcher.java b/core/java/android/text/TextWatcher.java
deleted file mode 100644
index bad09f2..0000000
--- a/core/java/android/text/TextWatcher.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text;
-
-/**
- * When an object of a type is attached to an Editable, its methods will
- * be called when the text is changed.
- */
-public interface TextWatcher extends NoCopySpan {
- /**
- * This method is called to notify you that, within <code>s</code>,
- * the <code>count</code> characters beginning at <code>start</code>
- * are about to be replaced by new text with length <code>after</code>.
- * It is an error to attempt to make changes to <code>s</code> from
- * this callback.
- */
- public void beforeTextChanged(CharSequence s, int start,
- int count, int after);
- /**
- * This method is called to notify you that, within <code>s</code>,
- * the <code>count</code> characters beginning at <code>start</code>
- * have just replaced old text that had length <code>before</code>.
- * It is an error to attempt to make changes to <code>s</code> from
- * this callback.
- */
- public void onTextChanged(CharSequence s, int start, int before, int count);
-
- /**
- * This method is called to notify you that, somewhere within
- * <code>s</code>, the text has been changed.
- * It is legitimate to make further changes to <code>s</code> from
- * this callback, but be careful not to get yourself into an infinite
- * loop, because any changes you make will cause this method to be
- * called again recursively.
- * (You are not told where the change took place because other
- * afterTextChanged() methods may already have made other changes
- * and invalidated the offsets. But if you need to know here,
- * you can use {@link Spannable#setSpan} in {@link #onTextChanged}
- * to mark your place and then look up from here where the span
- * ended up.
- */
- public void afterTextChanged(Editable s);
-}
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
deleted file mode 100644
index 0dc96c3..0000000
--- a/core/java/android/text/format/DateFormat.java
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.format;
-
-import android.content.Context;
-import android.provider.Settings;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.SpannedString;
-
-import com.android.internal.R;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
-import java.text.SimpleDateFormat;
-
-/**
- Utility class for producing strings with formatted date/time.
-
- <p>
- This class takes as inputs a format string and a representation of a date/time.
- The format string controls how the output is generated.
- </p>
- <p>
- Formatting characters may be repeated in order to get more detailed representations
- of that field. For instance, the format character &apos;M&apos; is used to
- represent the month. Depending on how many times that character is repeated
- you get a different representation.
- </p>
- <p>
- For the month of September:<br/>
- M -&gt; 9<br/>
- MM -&gt; 09<br/>
- MMM -&gt; Sep<br/>
- MMMM -&gt; September
- </p>
- <p>
- The effects of the duplication vary depending on the nature of the field.
- See the notes on the individual field formatters for details. For purely numeric
- fields such as <code>HOUR</code> adding more copies of the designator will
- zero-pad the value to that number of characters.
- </p>
- <p>
- For 7 minutes past the hour:<br/>
- m -&gt; 7<br/>
- mm -&gt; 07<br/>
- mmm -&gt; 007<br/>
- mmmm -&gt; 0007
- </p>
- <p>
- Examples for April 6, 1970 at 3:23am:<br/>
- &quot;MM/dd/yy h:mmaa&quot; -&gt; &quot;04/06/70 3:23am&quot<br/>
- &quot;MMM dd, yyyy h:mmaa&quot; -&gt; &quot;Apr 6, 1970 3:23am&quot<br/>
- &quot;MMMM dd, yyyy h:mmaa&quot; -&gt; &quot;April 6, 1970 3:23am&quot<br/>
- &quot;E, MMMM dd, yyyy h:mmaa&quot; -&gt; &quot;Mon, April 6, 1970 3:23am&<br/>
- &quot;EEEE, MMMM dd, yyyy h:mmaa&quot; -&gt; &quot;Monday, April 6, 1970 3:23am&quot;<br/>
- &quot;&apos;Noteworthy day: &apos;M/d/yy&quot; -&gt; &quot;Noteworthy day: 4/6/70&quot;
- */
-
-public class DateFormat {
- /**
- Text in the format string that should be copied verbatim rather that
- interpreted as formatting codes must be surrounded by the <code>QUOTE</code>
- character. If you need to embed a literal <code>QUOTE</code> character in
- the output text then use two in a row.
- */
- public static final char QUOTE = '\'';
-
- /**
- This designator indicates whether the <code>HOUR</code> field is before
- or after noon. The output is lower-case.
-
- Examples:
- a -> a or p
- aa -> am or pm
- */
- public static final char AM_PM = 'a';
-
- /**
- This designator indicates whether the <code>HOUR</code> field is before
- or after noon. The output is capitalized.
-
- Examples:
- A -> A or P
- AA -> AM or PM
- */
- public static final char CAPITAL_AM_PM = 'A';
-
- /**
- This designator indicates the day of the month.
-
- Examples for the 9th of the month:
- d -> 9
- dd -> 09
- */
- public static final char DATE = 'd';
-
- /**
- This designator indicates the name of the day of the week.
-
- Examples for Sunday:
- E -> Sun
- EEEE -> Sunday
- */
- public static final char DAY = 'E';
-
- /**
- This designator indicates the hour of the day in 12 hour format.
-
- Examples for 3pm:
- h -> 3
- hh -> 03
- */
- public static final char HOUR = 'h';
-
- /**
- This designator indicates the hour of the day in 24 hour format.
-
- Example for 3pm:
- k -> 15
-
- Examples for midnight:
- k -> 0
- kk -> 00
- */
- public static final char HOUR_OF_DAY = 'k';
-
- /**
- This designator indicates the minute of the hour.
-
- Examples for 7 minutes past the hour:
- m -> 7
- mm -> 07
- */
- public static final char MINUTE = 'm';
-
- /**
- This designator indicates the month of the year
-
- Examples for September:
- M -> 9
- MM -> 09
- MMM -> Sep
- MMMM -> September
- */
- public static final char MONTH = 'M';
-
- /**
- This designator indicates the seconds of the minute.
-
- Examples for 7 seconds past the minute:
- s -> 7
- ss -> 07
- */
- public static final char SECONDS = 's';
-
- /**
- This designator indicates the offset of the timezone from GMT.
-
- Example for US/Pacific timezone:
- z -> -0800
- zz -> PST
- */
- public static final char TIME_ZONE = 'z';
-
- /**
- This designator indicates the year.
-
- Examples for 2006
- y -> 06
- yyyy -> 2006
- */
- public static final char YEAR = 'y';
-
-
- private static final Object sLocaleLock = new Object();
- private static Locale sIs24HourLocale;
- private static boolean sIs24Hour;
-
-
- /**
- * Returns true if user preference is set to 24-hour format.
- * @param context the context to use for the content resolver
- * @return true if 24 hour time format is selected, false otherwise.
- */
- public static boolean is24HourFormat(Context context) {
- String value = Settings.System.getString(context.getContentResolver(),
- Settings.System.TIME_12_24);
-
- if (value == null) {
- Locale locale = context.getResources().getConfiguration().locale;
-
- synchronized (sLocaleLock) {
- if (sIs24HourLocale != null && sIs24HourLocale.equals(locale)) {
- return sIs24Hour;
- }
- }
-
- java.text.DateFormat natural =
- java.text.DateFormat.getTimeInstance(
- java.text.DateFormat.LONG, locale);
-
- if (natural instanceof SimpleDateFormat) {
- SimpleDateFormat sdf = (SimpleDateFormat) natural;
- String pattern = sdf.toPattern();
-
- if (pattern.indexOf('H') >= 0) {
- value = "24";
- } else {
- value = "12";
- }
- } else {
- value = "12";
- }
-
- synchronized (sLocaleLock) {
- sIs24HourLocale = locale;
- sIs24Hour = !value.equals("12");
- }
- }
-
- boolean b24 = !(value == null || value.equals("12"));
- return b24;
- }
-
- /**
- * Returns a {@link java.text.DateFormat} object that can format the time according
- * to the current user preference.
- * @param context the application context
- * @return the {@link java.text.DateFormat} object that properly formats the time.
- */
- public static final java.text.DateFormat getTimeFormat(Context context) {
- boolean b24 = is24HourFormat(context);
- int res;
-
- if (b24) {
- res = R.string.twenty_four_hour_time_format;
- } else {
- res = R.string.twelve_hour_time_format;
- }
-
- return new java.text.SimpleDateFormat(context.getString(res));
- }
-
- /**
- * Returns a {@link java.text.DateFormat} object that can format the date according
- * to the current user preference.
- * @param context the application context
- * @return the {@link java.text.DateFormat} object that properly formats the date.
- */
- public static final java.text.DateFormat getDateFormat(Context context) {
- String value = getDateFormatString(context);
- return new java.text.SimpleDateFormat(value);
- }
-
- /**
- * Returns a {@link java.text.DateFormat} object that can format the date
- * in long form (such as December 31, 1999) based on user preference.
- * @param context the application context
- * @return the {@link java.text.DateFormat} object that formats the date in long form.
- */
- public static final java.text.DateFormat getLongDateFormat(Context context) {
- String value = getDateFormatString(context);
- if (value.indexOf('M') < value.indexOf('d')) {
- value = context.getString(R.string.full_date_month_first);
- } else {
- value = context.getString(R.string.full_date_day_first);
- }
- return new java.text.SimpleDateFormat(value);
- }
-
- /**
- * Returns a {@link java.text.DateFormat} object that can format the date
- * in medium form (such as Dec. 31, 1999) based on user preference.
- * @param context the application context
- * @return the {@link java.text.DateFormat} object that formats the date in long form.
- */
- public static final java.text.DateFormat getMediumDateFormat(Context context) {
- String value = getDateFormatString(context);
- if (value.indexOf('M') < value.indexOf('d')) {
- value = context.getString(R.string.medium_date_month_first);
- } else {
- value = context.getString(R.string.medium_date_day_first);
- }
- return new java.text.SimpleDateFormat(value);
- }
-
- /**
- * Gets the current date format stored as a char array. The array will contain
- * 3 elements ({@link #DATE}, {@link #MONTH}, and {@link #YEAR}) in the order
- * preferred by the user.
- */
- public static final char[] getDateFormatOrder(Context context) {
- char[] order = new char[] {DATE, MONTH, YEAR};
- String value = getDateFormatString(context);
- int index = 0;
- boolean foundDate = false;
- boolean foundMonth = false;
- boolean foundYear = false;
-
- for (char c : value.toCharArray()) {
- if (!foundDate && (c == DATE)) {
- foundDate = true;
- order[index] = DATE;
- index++;
- }
-
- if (!foundMonth && (c == MONTH)) {
- foundMonth = true;
- order[index] = MONTH;
- index++;
- }
-
- if (!foundYear && (c == YEAR)) {
- foundYear = true;
- order[index] = YEAR;
- index++;
- }
- }
- return order;
- }
-
- private static String getDateFormatString(Context context) {
- String value = Settings.System.getString(context.getContentResolver(),
- Settings.System.DATE_FORMAT);
- if (value == null || value.length() < 6) {
- /*
- * No need to localize -- this is an emergency fallback in case
- * the setting is missing, but it should always be set.
- */
- value = "MM-dd-yyyy";
- }
- return value;
- }
-
- /**
- * Given a format string and a time in milliseconds since Jan 1, 1970 GMT, returns a
- * CharSequence containing the requested date.
- * @param inFormat the format string, as described in {@link android.text.format.DateFormat}
- * @param inTimeInMillis in milliseconds since Jan 1, 1970 GMT
- * @return a {@link CharSequence} containing the requested text
- */
- public static final CharSequence format(CharSequence inFormat, long inTimeInMillis) {
- return format(inFormat, new Date(inTimeInMillis));
- }
-
- /**
- * Given a format string and a {@link java.util.Date} object, returns a CharSequence containing
- * the requested date.
- * @param inFormat the format string, as described in {@link android.text.format.DateFormat}
- * @param inDate the date to format
- * @return a {@link CharSequence} containing the requested text
- */
- public static final CharSequence format(CharSequence inFormat, Date inDate) {
- Calendar c = new GregorianCalendar();
-
- c.setTime(inDate);
-
- return format(inFormat, c);
- }
-
- /**
- * Given a format string and a {@link java.util.Calendar} object, returns a CharSequence
- * containing the requested date.
- * @param inFormat the format string, as described in {@link android.text.format.DateFormat}
- * @param inDate the date to format
- * @return a {@link CharSequence} containing the requested text
- */
- public static final CharSequence format(CharSequence inFormat, Calendar inDate) {
- SpannableStringBuilder s = new SpannableStringBuilder(inFormat);
- int c;
- int count;
-
- int len = inFormat.length();
-
- for (int i = 0; i < len; i += count) {
- int temp;
-
- count = 1;
- c = s.charAt(i);
-
- if (c == QUOTE) {
- count = appendQuotedText(s, i, len);
- len = s.length();
- continue;
- }
-
- while ((i + count < len) && (s.charAt(i + count) == c)) {
- count++;
- }
-
- String replacement;
-
- switch (c) {
- case AM_PM:
- replacement = DateUtils.getAMPMString(inDate.get(Calendar.AM_PM));
- break;
-
- case CAPITAL_AM_PM:
- //FIXME: this is the same as AM_PM? no capital?
- replacement = DateUtils.getAMPMString(inDate.get(Calendar.AM_PM));
- break;
-
- case DATE:
- replacement = zeroPad(inDate.get(Calendar.DATE), count);
- break;
-
- case DAY:
- temp = inDate.get(Calendar.DAY_OF_WEEK);
- replacement = DateUtils.getDayOfWeekString(temp,
- count < 4 ?
- DateUtils.LENGTH_MEDIUM :
- DateUtils.LENGTH_LONG);
- break;
-
- case HOUR:
- temp = inDate.get(Calendar.HOUR);
-
- if (0 == temp)
- temp = 12;
-
- replacement = zeroPad(temp, count);
- break;
-
- case HOUR_OF_DAY:
- replacement = zeroPad(inDate.get(Calendar.HOUR_OF_DAY), count);
- break;
-
- case MINUTE:
- replacement = zeroPad(inDate.get(Calendar.MINUTE), count);
- break;
-
- case MONTH:
- replacement = getMonthString(inDate, count);
- break;
-
- case SECONDS:
- replacement = zeroPad(inDate.get(Calendar.SECOND), count);
- break;
-
- case TIME_ZONE:
- replacement = getTimeZoneString(inDate, count);
- break;
-
- case YEAR:
- replacement = getYearString(inDate, count);
- break;
-
- default:
- replacement = null;
- break;
- }
-
- if (replacement != null) {
- s.replace(i, i + count, replacement);
- count = replacement.length(); // CARE: count is used in the for loop above
- len = s.length();
- }
- }
-
- if (inFormat instanceof Spanned)
- return new SpannedString(s);
- else
- return s.toString();
- }
-
- private static final String getMonthString(Calendar inDate, int count) {
- int month = inDate.get(Calendar.MONTH);
-
- if (count >= 4)
- return DateUtils.getMonthString(month, DateUtils.LENGTH_LONG);
- else if (count == 3)
- return DateUtils.getMonthString(month, DateUtils.LENGTH_MEDIUM);
- else {
- // Calendar.JANUARY == 0, so add 1 to month.
- return zeroPad(month+1, count);
- }
- }
-
- private static final String getTimeZoneString(Calendar inDate, int count) {
- TimeZone tz = inDate.getTimeZone();
-
- if (count < 2) { // FIXME: shouldn't this be <= 2 ?
- return formatZoneOffset(inDate.get(Calendar.DST_OFFSET) +
- inDate.get(Calendar.ZONE_OFFSET),
- count);
- } else {
- boolean dst = inDate.get(Calendar.DST_OFFSET) != 0;
- return tz.getDisplayName(dst, TimeZone.SHORT);
- }
- }
-
- private static final String formatZoneOffset(int offset, int count) {
- offset /= 1000; // milliseconds to seconds
- StringBuilder tb = new StringBuilder();
-
- if (offset < 0) {
- tb.insert(0, "-");
- offset = -offset;
- } else {
- tb.insert(0, "+");
- }
-
- int hours = offset / 3600;
- int minutes = (offset % 3600) / 60;
-
- tb.append(zeroPad(hours, 2));
- tb.append(zeroPad(minutes, 2));
- return tb.toString();
- }
-
- private static final String getYearString(Calendar inDate, int count) {
- int year = inDate.get(Calendar.YEAR);
- return (count <= 2) ? zeroPad(year % 100, 2) : String.valueOf(year);
- }
-
- private static final int appendQuotedText(SpannableStringBuilder s, int i, int len) {
- if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
- s.delete(i, i + 1);
- return 1;
- }
-
- int count = 0;
-
- // delete leading quote
- s.delete(i, i + 1);
- len--;
-
- while (i < len) {
- char c = s.charAt(i);
-
- if (c == QUOTE) {
- // QUOTEQUOTE -> QUOTE
- if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
-
- s.delete(i, i + 1);
- len--;
- count++;
- i++;
- } else {
- // Closing QUOTE ends quoted text copying
- s.delete(i, i + 1);
- break;
- }
- } else {
- i++;
- count++;
- }
- }
-
- return count;
- }
-
- private static final String zeroPad(int inValue, int inMinDigits) {
- String val = String.valueOf(inValue);
-
- if (val.length() < inMinDigits) {
- char[] buf = new char[inMinDigits];
-
- for (int i = 0; i < inMinDigits; i++)
- buf[i] = '0';
-
- val.getChars(0, val.length(), buf, inMinDigits - val.length());
- val = new String(buf);
- }
- return val;
- }
-}
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
deleted file mode 100644
index feae6cf..0000000
--- a/core/java/android/text/format/DateUtils.java
+++ /dev/null
@@ -1,1581 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.format;
-
-import com.android.internal.R;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.pim.DateException;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.TimeZone;
-
-/**
- * This class contains various date-related utilities for creating text for things like
- * elapsed time and date ranges, strings for days of the week and months, and AM/PM text etc.
- */
-public class DateUtils
-{
- private static final Object sLock = new Object();
- private static final int[] sDaysLong = new int[] {
- com.android.internal.R.string.day_of_week_long_sunday,
- com.android.internal.R.string.day_of_week_long_monday,
- com.android.internal.R.string.day_of_week_long_tuesday,
- com.android.internal.R.string.day_of_week_long_wednesday,
- com.android.internal.R.string.day_of_week_long_thursday,
- com.android.internal.R.string.day_of_week_long_friday,
- com.android.internal.R.string.day_of_week_long_saturday,
- };
- private static final int[] sDaysMedium = new int[] {
- com.android.internal.R.string.day_of_week_medium_sunday,
- com.android.internal.R.string.day_of_week_medium_monday,
- com.android.internal.R.string.day_of_week_medium_tuesday,
- com.android.internal.R.string.day_of_week_medium_wednesday,
- com.android.internal.R.string.day_of_week_medium_thursday,
- com.android.internal.R.string.day_of_week_medium_friday,
- com.android.internal.R.string.day_of_week_medium_saturday,
- };
- private static final int[] sDaysShort = new int[] {
- com.android.internal.R.string.day_of_week_short_sunday,
- com.android.internal.R.string.day_of_week_short_monday,
- com.android.internal.R.string.day_of_week_short_tuesday,
- com.android.internal.R.string.day_of_week_short_wednesday,
- com.android.internal.R.string.day_of_week_short_thursday,
- com.android.internal.R.string.day_of_week_short_friday,
- com.android.internal.R.string.day_of_week_short_saturday,
- };
- private static final int[] sDaysShorter = new int[] {
- com.android.internal.R.string.day_of_week_shorter_sunday,
- com.android.internal.R.string.day_of_week_shorter_monday,
- com.android.internal.R.string.day_of_week_shorter_tuesday,
- com.android.internal.R.string.day_of_week_shorter_wednesday,
- com.android.internal.R.string.day_of_week_shorter_thursday,
- com.android.internal.R.string.day_of_week_shorter_friday,
- com.android.internal.R.string.day_of_week_shorter_saturday,
- };
- private static final int[] sDaysShortest = new int[] {
- com.android.internal.R.string.day_of_week_shortest_sunday,
- com.android.internal.R.string.day_of_week_shortest_monday,
- com.android.internal.R.string.day_of_week_shortest_tuesday,
- com.android.internal.R.string.day_of_week_shortest_wednesday,
- com.android.internal.R.string.day_of_week_shortest_thursday,
- com.android.internal.R.string.day_of_week_shortest_friday,
- com.android.internal.R.string.day_of_week_shortest_saturday,
- };
- private static final int[] sMonthsLong = new int [] {
- com.android.internal.R.string.month_long_january,
- com.android.internal.R.string.month_long_february,
- com.android.internal.R.string.month_long_march,
- com.android.internal.R.string.month_long_april,
- com.android.internal.R.string.month_long_may,
- com.android.internal.R.string.month_long_june,
- com.android.internal.R.string.month_long_july,
- com.android.internal.R.string.month_long_august,
- com.android.internal.R.string.month_long_september,
- com.android.internal.R.string.month_long_october,
- com.android.internal.R.string.month_long_november,
- com.android.internal.R.string.month_long_december,
- };
- private static final int[] sMonthsMedium = new int [] {
- com.android.internal.R.string.month_medium_january,
- com.android.internal.R.string.month_medium_february,
- com.android.internal.R.string.month_medium_march,
- com.android.internal.R.string.month_medium_april,
- com.android.internal.R.string.month_medium_may,
- com.android.internal.R.string.month_medium_june,
- com.android.internal.R.string.month_medium_july,
- com.android.internal.R.string.month_medium_august,
- com.android.internal.R.string.month_medium_september,
- com.android.internal.R.string.month_medium_october,
- com.android.internal.R.string.month_medium_november,
- com.android.internal.R.string.month_medium_december,
- };
- private static final int[] sMonthsShortest = new int [] {
- com.android.internal.R.string.month_shortest_january,
- com.android.internal.R.string.month_shortest_february,
- com.android.internal.R.string.month_shortest_march,
- com.android.internal.R.string.month_shortest_april,
- com.android.internal.R.string.month_shortest_may,
- com.android.internal.R.string.month_shortest_june,
- com.android.internal.R.string.month_shortest_july,
- com.android.internal.R.string.month_shortest_august,
- com.android.internal.R.string.month_shortest_september,
- com.android.internal.R.string.month_shortest_october,
- com.android.internal.R.string.month_shortest_november,
- com.android.internal.R.string.month_shortest_december,
- };
- private static final int[] sAmPm = new int[] {
- com.android.internal.R.string.am,
- com.android.internal.R.string.pm,
- };
- private static Configuration sLastConfig;
- private static String sStatusTimeFormat;
- private static String sElapsedFormatMMSS;
- private static String sElapsedFormatHMMSS;
-
- private static final String FAST_FORMAT_HMMSS = "%1$d:%2$02d:%3$02d";
- private static final String FAST_FORMAT_MMSS = "%1$02d:%2$02d";
- private static final char TIME_PADDING = '0';
- private static final char TIME_SEPARATOR = ':';
-
-
- public static final long SECOND_IN_MILLIS = 1000;
- public static final long MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60;
- public static final long HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60;
- public static final long DAY_IN_MILLIS = HOUR_IN_MILLIS * 24;
- public static final long WEEK_IN_MILLIS = DAY_IN_MILLIS * 7;
- public static final long YEAR_IN_MILLIS = WEEK_IN_MILLIS * 52;
-
- // The following FORMAT_* symbols are used for specifying the format of
- // dates and times in the formatDateRange method.
- public static final int FORMAT_SHOW_TIME = 0x00001;
- public static final int FORMAT_SHOW_WEEKDAY = 0x00002;
- public static final int FORMAT_SHOW_YEAR = 0x00004;
- public static final int FORMAT_NO_YEAR = 0x00008;
- public static final int FORMAT_SHOW_DATE = 0x00010;
- public static final int FORMAT_NO_MONTH_DAY = 0x00020;
- public static final int FORMAT_12HOUR = 0x00040;
- public static final int FORMAT_24HOUR = 0x00080;
- public static final int FORMAT_CAP_AMPM = 0x00100;
- public static final int FORMAT_NO_NOON = 0x00200;
- public static final int FORMAT_CAP_NOON = 0x00400;
- public static final int FORMAT_NO_MIDNIGHT = 0x00800;
- public static final int FORMAT_CAP_MIDNIGHT = 0x01000;
- public static final int FORMAT_UTC = 0x02000;
- public static final int FORMAT_ABBREV_TIME = 0x04000;
- public static final int FORMAT_ABBREV_WEEKDAY = 0x08000;
- public static final int FORMAT_ABBREV_MONTH = 0x10000;
- public static final int FORMAT_NUMERIC_DATE = 0x20000;
- public static final int FORMAT_ABBREV_RELATIVE = 0x40000;
- public static final int FORMAT_ABBREV_ALL = 0x80000;
- public static final int FORMAT_CAP_NOON_MIDNIGHT = (FORMAT_CAP_NOON | FORMAT_CAP_MIDNIGHT);
- public static final int FORMAT_NO_NOON_MIDNIGHT = (FORMAT_NO_NOON | FORMAT_NO_MIDNIGHT);
-
- // Date and time format strings that are constant and don't need to be
- // translated.
- public static final String HOUR_MINUTE_24 = "%H:%M";
- public static final String MONTH_FORMAT = "%B";
- public static final String ABBREV_MONTH_FORMAT = "%b";
- public static final String NUMERIC_MONTH_FORMAT = "%m";
- public static final String MONTH_DAY_FORMAT = "%-d";
- public static final String YEAR_FORMAT = "%Y";
- public static final String YEAR_FORMAT_TWO_DIGITS = "%g";
- public static final String WEEKDAY_FORMAT = "%A";
- public static final String ABBREV_WEEKDAY_FORMAT = "%a";
-
- // This table is used to lookup the resource string id of a format string
- // used for formatting a start and end date that fall in the same year.
- // The index is constructed from a bit-wise OR of the boolean values:
- // {showTime, showYear, showWeekDay}. For example, if showYear and
- // showWeekDay are both true, then the index would be 3.
- public static final int sameYearTable[] = {
- com.android.internal.R.string.same_year_md1_md2,
- com.android.internal.R.string.same_year_wday1_md1_wday2_md2,
- com.android.internal.R.string.same_year_mdy1_mdy2,
- com.android.internal.R.string.same_year_wday1_mdy1_wday2_mdy2,
- com.android.internal.R.string.same_year_md1_time1_md2_time2,
- com.android.internal.R.string.same_year_wday1_md1_time1_wday2_md2_time2,
- com.android.internal.R.string.same_year_mdy1_time1_mdy2_time2,
- com.android.internal.R.string.same_year_wday1_mdy1_time1_wday2_mdy2_time2,
-
- // Numeric date strings
- com.android.internal.R.string.numeric_md1_md2,
- com.android.internal.R.string.numeric_wday1_md1_wday2_md2,
- com.android.internal.R.string.numeric_mdy1_mdy2,
- com.android.internal.R.string.numeric_wday1_mdy1_wday2_mdy2,
- com.android.internal.R.string.numeric_md1_time1_md2_time2,
- com.android.internal.R.string.numeric_wday1_md1_time1_wday2_md2_time2,
- com.android.internal.R.string.numeric_mdy1_time1_mdy2_time2,
- com.android.internal.R.string.numeric_wday1_mdy1_time1_wday2_mdy2_time2,
- };
-
- // This table is used to lookup the resource string id of a format string
- // used for formatting a start and end date that fall in the same month.
- // The index is constructed from a bit-wise OR of the boolean values:
- // {showTime, showYear, showWeekDay}. For example, if showYear and
- // showWeekDay are both true, then the index would be 3.
- public static final int sameMonthTable[] = {
- com.android.internal.R.string.same_month_md1_md2,
- com.android.internal.R.string.same_month_wday1_md1_wday2_md2,
- com.android.internal.R.string.same_month_mdy1_mdy2,
- com.android.internal.R.string.same_month_wday1_mdy1_wday2_mdy2,
- com.android.internal.R.string.same_month_md1_time1_md2_time2,
- com.android.internal.R.string.same_month_wday1_md1_time1_wday2_md2_time2,
- com.android.internal.R.string.same_month_mdy1_time1_mdy2_time2,
- com.android.internal.R.string.same_month_wday1_mdy1_time1_wday2_mdy2_time2,
-
- com.android.internal.R.string.numeric_md1_md2,
- com.android.internal.R.string.numeric_wday1_md1_wday2_md2,
- com.android.internal.R.string.numeric_mdy1_mdy2,
- com.android.internal.R.string.numeric_wday1_mdy1_wday2_mdy2,
- com.android.internal.R.string.numeric_md1_time1_md2_time2,
- com.android.internal.R.string.numeric_wday1_md1_time1_wday2_md2_time2,
- com.android.internal.R.string.numeric_mdy1_time1_mdy2_time2,
- com.android.internal.R.string.numeric_wday1_mdy1_time1_wday2_mdy2_time2,
- };
-
- /**
- * Request the full spelled-out name. For use with the 'abbrev' parameter of
- * {@link #getDayOfWeekString} and {@link #getMonthString}.
- *
- * @more <p>
- * e.g. "Sunday" or "January"
- */
- public static final int LENGTH_LONG = 10;
-
- /**
- * Request an abbreviated version of the name. For use with the 'abbrev'
- * parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
- *
- * @more <p>
- * e.g. "Sun" or "Jan"
- */
- public static final int LENGTH_MEDIUM = 20;
-
- /**
- * Request a shorter abbreviated version of the name.
- * For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
- * @more
- * <p>e.g. "Su" or "Jan"
- * <p>In some languages, the results returned for LENGTH_SHORT may be the same as
- * return for {@link #LENGTH_MEDIUM}.
- */
- public static final int LENGTH_SHORT = 30;
-
- /**
- * Request an even shorter abbreviated version of the name.
- * For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
- * @more
- * <p>e.g. "M", "Tu", "Th" or "J"
- * <p>In some languages, the results returned for LENGTH_SHORTEST may be the same as
- * return for {@link #LENGTH_SHORTER}.
- */
- public static final int LENGTH_SHORTER = 40;
-
- /**
- * Request an even shorter abbreviated version of the name.
- * For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
- * @more
- * <p>e.g. "S", "T", "T" or "J"
- * <p>In some languages, the results returned for LENGTH_SHORTEST may be the same as
- * return for {@link #LENGTH_SHORTER}.
- */
- public static final int LENGTH_SHORTEST = 50;
-
- /**
- * Return a string for the day of the week.
- * @param dayOfWeek One of {@link Calendar#SUNDAY Calendar.SUNDAY},
- * {@link Calendar#MONDAY Calendar.MONDAY}, etc.
- * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_SHORT}, {@link #LENGTH_SHORTER}
- * or {@link #LENGTH_SHORTEST}. For forward compatibility, anything else
- * will return the same as {#LENGTH_MEDIUM}.
- * @throws IndexOutOfBoundsException if the dayOfWeek is out of bounds.
- */
- public static String getDayOfWeekString(int dayOfWeek, int abbrev) {
- int[] list;
- switch (abbrev) {
- case LENGTH_LONG: list = sDaysLong; break;
- case LENGTH_MEDIUM: list = sDaysMedium; break;
- case LENGTH_SHORT: list = sDaysShort; break;
- case LENGTH_SHORTER: list = sDaysShorter; break;
- case LENGTH_SHORTEST: list = sDaysShortest; break;
- default: list = sDaysMedium; break;
- }
-
- Resources r = Resources.getSystem();
- return r.getString(list[dayOfWeek - Calendar.SUNDAY]);
- }
-
- /**
- * Return a localized string for AM or PM.
- * @param ampm Either {@link Calendar#AM Calendar.AM} or {@link Calendar#PM Calendar.PM}.
- * @throws IndexOutOfBoundsException if the ampm is out of bounds.
- * @return Localized version of "AM" or "PM".
- */
- public static String getAMPMString(int ampm) {
- Resources r = Resources.getSystem();
- return r.getString(sAmPm[ampm - Calendar.AM]);
- }
-
- /**
- * Return a localized string for the day of the week.
- * @param month One of {@link Calendar#JANUARY Calendar.JANUARY},
- * {@link Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
- * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_SHORT}, {@link #LENGTH_SHORTER}
- * or {@link #LENGTH_SHORTEST}. For forward compatibility, anything else
- * will return the same as {#LENGTH_MEDIUM}.
- * @return Localized day of the week.
- */
- public static String getMonthString(int month, int abbrev) {
- // Note that here we use sMonthsMedium for MEDIUM, SHORT and SHORTER.
- // This is a shortcut to not spam the translators with too many variations
- // of the same string. If we find that in a language the distinction
- // is necessary, we can can add more without changing this API.
- int[] list;
- switch (abbrev) {
- case LENGTH_LONG: list = sMonthsLong; break;
- case LENGTH_MEDIUM: list = sMonthsMedium; break;
- case LENGTH_SHORT: list = sMonthsMedium; break;
- case LENGTH_SHORTER: list = sMonthsMedium; break;
- case LENGTH_SHORTEST: list = sMonthsShortest; break;
- default: list = sMonthsMedium; break;
- }
-
- Resources r = Resources.getSystem();
- return r.getString(list[month - Calendar.JANUARY]);
- }
-
- /**
- * Returns a string describing the elapsed time since startTime.
- * @param startTime some time in the past.
- * @return a String object containing the elapsed time.
- * @see #getRelativeTimeSpanString(long, long, long)
- */
- public static CharSequence getRelativeTimeSpanString(long startTime) {
- return getRelativeTimeSpanString(startTime, System.currentTimeMillis(), MINUTE_IN_MILLIS);
- }
-
- /**
- * Returns a string describing 'time' as a time relative to 'now'.
- * <p>
- * Time spans in the past are formatted like "42 minutes ago".
- * Time spans in the future are formatted like "in 42 minutes".
- *
- * @param time the time to describe, in milliseconds
- * @param now the current time in milliseconds
- * @param minResolution the minimum timespan to report. For example, a time 3 seconds in the
- * past will be reported as "0 minutes ago" if this is set to MINUTE_IN_MILLIS. Pass one of
- * 0, MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS, WEEK_IN_MILLIS
- */
- public static CharSequence getRelativeTimeSpanString(long time, long now, long minResolution) {
- int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR | FORMAT_ABBREV_MONTH;
- return getRelativeTimeSpanString(time, now, minResolution, flags);
- }
-
- /**
- * Returns a string describing 'time' as a time relative to 'now'.
- * <p>
- * Time spans in the past are formatted like "42 minutes ago". Time spans in
- * the future are formatted like "in 42 minutes".
- * <p>
- * Can use {@link #FORMAT_ABBREV_RELATIVE} flag to use abbreviated relative
- * times, like "42 mins ago".
- *
- * @param time the time to describe, in milliseconds
- * @param now the current time in milliseconds
- * @param minResolution the minimum timespan to report. For example, a time
- * 3 seconds in the past will be reported as "0 minutes ago" if
- * this is set to MINUTE_IN_MILLIS. Pass one of 0,
- * MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS,
- * WEEK_IN_MILLIS
- * @param flags a bit mask of formatting options, such as
- * {@link #FORMAT_NUMERIC_DATE} or
- * {@link #FORMAT_ABBREV_RELATIVE}
- */
- public static CharSequence getRelativeTimeSpanString(long time, long now, long minResolution,
- int flags) {
- Resources r = Resources.getSystem();
- boolean abbrevRelative = (flags & (FORMAT_ABBREV_RELATIVE | FORMAT_ABBREV_ALL)) != 0;
-
- boolean past = (now >= time);
- long duration = Math.abs(now - time);
-
- int resId;
- long count;
- if (duration < MINUTE_IN_MILLIS && minResolution < MINUTE_IN_MILLIS) {
- count = duration / SECOND_IN_MILLIS;
- if (past) {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_num_seconds_ago;
- } else {
- resId = com.android.internal.R.plurals.num_seconds_ago;
- }
- } else {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_in_num_seconds;
- } else {
- resId = com.android.internal.R.plurals.in_num_seconds;
- }
- }
- } else if (duration < HOUR_IN_MILLIS && minResolution < HOUR_IN_MILLIS) {
- count = duration / MINUTE_IN_MILLIS;
- if (past) {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_num_minutes_ago;
- } else {
- resId = com.android.internal.R.plurals.num_minutes_ago;
- }
- } else {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_in_num_minutes;
- } else {
- resId = com.android.internal.R.plurals.in_num_minutes;
- }
- }
- } else if (duration < DAY_IN_MILLIS && minResolution < DAY_IN_MILLIS) {
- count = duration / HOUR_IN_MILLIS;
- if (past) {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_num_hours_ago;
- } else {
- resId = com.android.internal.R.plurals.num_hours_ago;
- }
- } else {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_in_num_hours;
- } else {
- resId = com.android.internal.R.plurals.in_num_hours;
- }
- }
- } else if (duration < WEEK_IN_MILLIS && minResolution < WEEK_IN_MILLIS) {
- count = duration / DAY_IN_MILLIS;
- if (past) {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_num_days_ago;
- } else {
- resId = com.android.internal.R.plurals.num_days_ago;
- }
- } else {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_in_num_days;
- } else {
- resId = com.android.internal.R.plurals.in_num_days;
- }
- }
- } else {
- // We know that we won't be showing the time, so it is safe to pass
- // in a null context.
- return formatDateRange(null, time, time, flags);
- }
-
- String format = r.getQuantityString(resId, (int) count);
- return String.format(format, count);
- }
-
- /**
- * Return string describing the elapsed time since startTime formatted like
- * "[relative time/date], [time]".
- * <p>
- * Example output strings for the US date format.
- * <ul>
- * <li>3 mins ago, 10:15 AM</li>
- * <li>yesterday, 12:20 PM</li>
- * <li>Dec 12, 4:12 AM</li>
- * <li>11/14/2007, 8:20 AM</li>
- * </ul>
- *
- * @param time some time in the past.
- * @param minResolution the minimum elapsed time (in milliseconds) to report
- * when showing relative times. For example, a time 3 seconds in
- * the past will be reported as "0 minutes ago" if this is set to
- * {@link #MINUTE_IN_MILLIS}.
- * @param transitionResolution the elapsed time (in milliseconds) at which
- * to stop reporting relative measurements. Elapsed times greater
- * than this resolution will default to normal date formatting.
- * For example, will transition from "6 days ago" to "Dec 12"
- * when using {@link #WEEK_IN_MILLIS}.
- */
- public static CharSequence getRelativeDateTimeString(Context c, long time, long minResolution,
- long transitionResolution, int flags) {
- Resources r = Resources.getSystem();
-
- long now = System.currentTimeMillis();
- long duration = Math.abs(now - time);
-
- // getRelativeTimeSpanString() doesn't correctly format relative dates
- // above a week or exact dates below a day, so clamp
- // transitionResolution as needed.
- if (transitionResolution > WEEK_IN_MILLIS) {
- transitionResolution = WEEK_IN_MILLIS;
- } else if (transitionResolution < DAY_IN_MILLIS) {
- transitionResolution = DAY_IN_MILLIS;
- }
-
- CharSequence timeClause = formatDateRange(c, time, time, FORMAT_SHOW_TIME);
-
- String result;
- if (duration < transitionResolution) {
- CharSequence relativeClause = getRelativeTimeSpanString(time, now, minResolution, flags);
- result = r.getString(com.android.internal.R.string.relative_time, relativeClause, timeClause);
- } else {
- CharSequence dateClause = getRelativeTimeSpanString(c, time, false);
- result = r.getString(com.android.internal.R.string.date_time, dateClause, timeClause);
- }
-
- return result;
- }
-
- /**
- * Returns a string describing a day relative to the current day. For example if the day is
- * today this function returns "Today", if the day was a week ago it returns "7 days ago", and
- * if the day is in 2 weeks it returns "in 14 days".
- *
- * @param r the resources to get the strings from
- * @param day the relative day to describe in UTC milliseconds
- * @param today the current time in UTC milliseconds
- * @return a formatting string
- */
- private static final String getRelativeDayString(Resources r, long day, long today) {
- Time startTime = new Time();
- startTime.set(day);
- Time currentTime = new Time();
- currentTime.set(today);
-
- int startDay = Time.getJulianDay(day, startTime.gmtoff);
- int currentDay = Time.getJulianDay(today, currentTime.gmtoff);
-
- int days = Math.abs(currentDay - startDay);
- boolean past = (today > day);
-
- if (days == 1) {
- if (past) {
- return r.getString(com.android.internal.R.string.yesterday);
- } else {
- return r.getString(com.android.internal.R.string.tomorrow);
- }
- } else if (days == 0) {
- return r.getString(com.android.internal.R.string.today);
- }
-
- int resId;
- if (past) {
- resId = com.android.internal.R.plurals.num_days_ago;
- } else {
- resId = com.android.internal.R.plurals.in_num_days;
- }
-
- String format = r.getQuantityString(resId, days);
- return String.format(format, days);
- }
-
- private static void initFormatStrings() {
- synchronized (sLock) {
- Resources r = Resources.getSystem();
- Configuration cfg = r.getConfiguration();
- if (sLastConfig == null || !sLastConfig.equals(cfg)) {
- sLastConfig = cfg;
- sStatusTimeFormat = r.getString(com.android.internal.R.string.status_bar_time_format);
- sElapsedFormatMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_mm_ss);
- sElapsedFormatHMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_h_mm_ss);
- }
- }
- }
-
- /**
- * Format a time so it appears like it would in the status bar clock.
- * @deprecated use {@link #DateFormat.getTimeFormat(Context)} instead.
- * @hide
- */
- public static final CharSequence timeString(long millis) {
- initFormatStrings();
- return DateFormat.format(sStatusTimeFormat, millis);
- }
-
- /**
- * Formats an elapsed time in the form "MM:SS" or "H:MM:SS"
- * for display on the call-in-progress screen.
- * @param elapsedSeconds the elapsed time in seconds.
- */
- public static String formatElapsedTime(long elapsedSeconds) {
- initFormatStrings();
-
- long hours = 0;
- long minutes = 0;
- long seconds = 0;
-
- if (elapsedSeconds >= 3600) {
- hours = elapsedSeconds / 3600;
- elapsedSeconds -= hours * 3600;
- }
- if (elapsedSeconds >= 60) {
- minutes = elapsedSeconds / 60;
- elapsedSeconds -= minutes * 60;
- }
- seconds = elapsedSeconds;
-
- String result;
- if (hours > 0) {
- return formatElapsedTime(sElapsedFormatHMMSS, hours, minutes, seconds);
- } else {
- return formatElapsedTime(sElapsedFormatMMSS, minutes, seconds);
- }
- }
-
- /**
- * Fast formatting of h:mm:ss
- */
- private static String formatElapsedTime(String format, long hours, long minutes, long seconds) {
- if (FAST_FORMAT_HMMSS.equals(format)) {
- StringBuffer sb = new StringBuffer(16);
- sb.append(hours);
- sb.append(TIME_SEPARATOR);
- if (minutes < 10) {
- sb.append(TIME_PADDING);
- } else {
- sb.append(toDigitChar(minutes / 10));
- }
- sb.append(toDigitChar(minutes % 10));
- sb.append(TIME_SEPARATOR);
- if (seconds < 10) {
- sb.append(TIME_PADDING);
- } else {
- sb.append(toDigitChar(seconds / 10));
- }
- sb.append(toDigitChar(seconds % 10));
- return sb.toString();
- } else {
- return String.format(format, hours, minutes, seconds);
- }
- }
-
- /**
- * Fast formatting of m:ss
- */
- private static String formatElapsedTime(String format, long minutes, long seconds) {
- if (FAST_FORMAT_MMSS.equals(format)) {
- StringBuffer sb = new StringBuffer(16);
- if (minutes < 10) {
- sb.append(TIME_PADDING);
- } else {
- sb.append(toDigitChar(minutes / 10));
- }
- sb.append(toDigitChar(minutes % 10));
- sb.append(TIME_SEPARATOR);
- if (seconds < 10) {
- sb.append(TIME_PADDING);
- } else {
- sb.append(toDigitChar(seconds / 10));
- }
- sb.append(toDigitChar(seconds % 10));
- return sb.toString();
- } else {
- return String.format(format, minutes, seconds);
- }
- }
-
- private static char toDigitChar(long digit) {
- return (char) (digit + '0');
- }
-
- /**
- * Format a date / time such that if the then is on the same day as now, it shows
- * just the time and if it's a different day, it shows just the date.
- *
- * <p>The parameters dateFormat and timeFormat should each be one of
- * {@link java.text.DateFormat#DEFAULT},
- * {@link java.text.DateFormat#FULL},
- * {@link java.text.DateFormat#LONG},
- * {@link java.text.DateFormat#MEDIUM}
- * or
- * {@link java.text.DateFormat#SHORT}
- *
- * @param then the date to format
- * @param now the base time
- * @param dateStyle how to format the date portion.
- * @param timeStyle how to format the time portion.
- */
- public static final CharSequence formatSameDayTime(long then, long now,
- int dateStyle, int timeStyle) {
- Calendar thenCal = new GregorianCalendar();
- thenCal.setTimeInMillis(then);
- Date thenDate = thenCal.getTime();
- Calendar nowCal = new GregorianCalendar();
- nowCal.setTimeInMillis(now);
-
- java.text.DateFormat f;
-
- if (thenCal.get(Calendar.YEAR) == nowCal.get(Calendar.YEAR)
- && thenCal.get(Calendar.MONTH) == nowCal.get(Calendar.MONTH)
- && thenCal.get(Calendar.DAY_OF_MONTH) == nowCal.get(Calendar.DAY_OF_MONTH)) {
- f = java.text.DateFormat.getTimeInstance(timeStyle);
- } else {
- f = java.text.DateFormat.getDateInstance(dateStyle);
- }
- return f.format(thenDate);
- }
-
- /**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static Calendar newCalendar(boolean zulu)
- {
- if (zulu)
- return Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-
- return Calendar.getInstance();
- }
-
- /**
- * @return true if the supplied when is today else false
- */
- public static boolean isToday(long when) {
- Time time = new Time();
- time.set(when);
-
- int thenYear = time.year;
- int thenMonth = time.month;
- int thenMonthDay = time.monthDay;
-
- time.set(System.currentTimeMillis());
- return (thenYear == time.year)
- && (thenMonth == time.month)
- && (thenMonthDay == time.monthDay);
- }
-
- /**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- private static final int ctoi(String str, int index)
- throws DateException
- {
- char c = str.charAt(index);
- if (c >= '0' && c <= '9') {
- return (int)(c - '0');
- }
- throw new DateException("Expected numeric character. Got '" +
- c + "'");
- }
-
- /**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- private static final int check(int lowerBound, int upperBound, int value)
- throws DateException
- {
- if (value >= lowerBound && value <= upperBound) {
- return value;
- }
- throw new DateException("field out of bounds. max=" + upperBound
- + " value=" + value);
- }
-
- /**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- * Return true if this date string is local time
- */
- public static boolean isUTC(String s)
- {
- if (s.length() == 16 && s.charAt(15) == 'Z') {
- return true;
- }
- if (s.length() == 9 && s.charAt(8) == 'Z') {
- // XXX not sure if this case possible/valid
- return true;
- }
- return false;
- }
-
-
- // note that month in Calendar is 0 based and in all other human
- // representations, it's 1 based.
- // Returns if the Z was present, meaning that the time is in UTC
- /**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static boolean parseDateTime(String str, Calendar cal)
- throws DateException
- {
- int len = str.length();
- boolean dateTime = (len == 15 || len == 16) && str.charAt(8) == 'T';
- boolean justDate = len == 8;
- if (dateTime || justDate) {
- cal.clear();
- cal.set(Calendar.YEAR,
- ctoi(str, 0)*1000 + ctoi(str, 1)*100
- + ctoi(str, 2)*10 + ctoi(str, 3));
- cal.set(Calendar.MONTH,
- check(0, 11, ctoi(str, 4)*10 + ctoi(str, 5) - 1));
- cal.set(Calendar.DAY_OF_MONTH,
- check(1, 31, ctoi(str, 6)*10 + ctoi(str, 7)));
- if (dateTime) {
- cal.set(Calendar.HOUR_OF_DAY,
- check(0, 23, ctoi(str, 9)*10 + ctoi(str, 10)));
- cal.set(Calendar.MINUTE,
- check(0, 59, ctoi(str, 11)*10 + ctoi(str, 12)));
- cal.set(Calendar.SECOND,
- check(0, 59, ctoi(str, 13)*10 + ctoi(str, 14)));
- }
- if (justDate) {
- cal.set(Calendar.HOUR_OF_DAY, 0);
- cal.set(Calendar.MINUTE, 0);
- cal.set(Calendar.SECOND, 0);
- return true;
- }
- if (len == 15) {
- return false;
- }
- if (str.charAt(15) == 'Z') {
- return true;
- }
- }
- throw new DateException("Invalid time (expected "
- + "YYYYMMDDThhmmssZ? got '" + str + "').");
- }
-
- /**
- * Given a timezone string which can be null, and a dateTime string,
- * set that time into a calendar.
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static void parseDateTime(String tz, String dateTime, Calendar out)
- throws DateException
- {
- TimeZone timezone;
- if (DateUtils.isUTC(dateTime)) {
- timezone = TimeZone.getTimeZone("UTC");
- }
- else if (tz == null) {
- timezone = TimeZone.getDefault();
- }
- else {
- timezone = TimeZone.getTimeZone(tz);
- }
-
- Calendar local = new GregorianCalendar(timezone);
- DateUtils.parseDateTime(dateTime, local);
-
- out.setTimeInMillis(local.getTimeInMillis());
- }
-
-
- /**
- * Return a string containing the date and time in RFC2445 format.
- * Ensures that the time is written in UTC. The Calendar class doesn't
- * really help out with this, so this is slower than it ought to be.
- *
- * @param cal the date and time to write
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static String writeDateTime(Calendar cal)
- {
- TimeZone tz = TimeZone.getTimeZone("GMT");
- GregorianCalendar c = new GregorianCalendar(tz);
- c.setTimeInMillis(cal.getTimeInMillis());
- return writeDateTime(c, true);
- }
-
- /**
- * Return a string containing the date and time in RFC2445 format.
- *
- * @param cal the date and time to write
- * @param zulu If the calendar is in UTC, pass true, and a Z will
- * be written at the end as per RFC2445. Otherwise, the time is
- * considered in localtime.
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static String writeDateTime(Calendar cal, boolean zulu)
- {
- StringBuilder sb = new StringBuilder();
- sb.ensureCapacity(16);
- if (zulu) {
- sb.setLength(16);
- sb.setCharAt(15, 'Z');
- } else {
- sb.setLength(15);
- }
- return writeDateTime(cal, sb);
- }
-
- /**
- * Return a string containing the date and time in RFC2445 format.
- *
- * @param cal the date and time to write
- * @param sb a StringBuilder to use. It is assumed that setLength
- * has already been called on sb to the appropriate length
- * which is sb.setLength(zulu ? 16 : 15)
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static String writeDateTime(Calendar cal, StringBuilder sb)
- {
- int n;
-
- n = cal.get(Calendar.YEAR);
- sb.setCharAt(3, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(2, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(1, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(0, (char)('0'+n%10));
-
- n = cal.get(Calendar.MONTH) + 1;
- sb.setCharAt(5, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(4, (char)('0'+n%10));
-
- n = cal.get(Calendar.DAY_OF_MONTH);
- sb.setCharAt(7, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(6, (char)('0'+n%10));
-
- sb.setCharAt(8, 'T');
-
- n = cal.get(Calendar.HOUR_OF_DAY);
- sb.setCharAt(10, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(9, (char)('0'+n%10));
-
- n = cal.get(Calendar.MINUTE);
- sb.setCharAt(12, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(11, (char)('0'+n%10));
-
- n = cal.get(Calendar.SECOND);
- sb.setCharAt(14, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(13, (char)('0'+n%10));
-
- return sb.toString();
- }
-
- /**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static void assign(Calendar lval, Calendar rval)
- {
- // there should be a faster way.
- lval.clear();
- lval.setTimeInMillis(rval.getTimeInMillis());
- }
-
- /**
- * Formats a date or a time range according to the local conventions.
- *
- * <p>
- * Example output strings (date formats in these examples are shown using
- * the US date format convention but that may change depending on the
- * local settings):
- * <ul>
- * <li>10:15am</li>
- * <li>3:00pm - 4:00pm</li>
- * <li>3pm - 4pm</li>
- * <li>3PM - 4PM</li>
- * <li>08:00 - 17:00</li>
- * <li>Oct 9</li>
- * <li>Tue, Oct 9</li>
- * <li>October 9, 2007</li>
- * <li>Oct 9 - 10</li>
- * <li>Oct 9 - 10, 2007</li>
- * <li>Oct 28 - Nov 3, 2007</li>
- * <li>Dec 31, 2007 - Jan 1, 2008</li>
- * <li>Oct 9, 8:00am - Oct 10, 5:00pm</li>
- * <li>12/31/2007 - 01/01/2008</li>
- * </ul>
- *
- * <p>
- * The flags argument is a bitmask of options from the following list:
- *
- * <ul>
- * <li>FORMAT_SHOW_TIME</li>
- * <li>FORMAT_SHOW_WEEKDAY</li>
- * <li>FORMAT_SHOW_YEAR</li>
- * <li>FORMAT_NO_YEAR</li>
- * <li>FORMAT_SHOW_DATE</li>
- * <li>FORMAT_NO_MONTH_DAY</li>
- * <li>FORMAT_12HOUR</li>
- * <li>FORMAT_24HOUR</li>
- * <li>FORMAT_CAP_AMPM</li>
- * <li>FORMAT_NO_NOON</li>
- * <li>FORMAT_CAP_NOON</li>
- * <li>FORMAT_NO_MIDNIGHT</li>
- * <li>FORMAT_CAP_MIDNIGHT</li>
- * <li>FORMAT_UTC</li>
- * <li>FORMAT_ABBREV_TIME</li>
- * <li>FORMAT_ABBREV_WEEKDAY</li>
- * <li>FORMAT_ABBREV_MONTH</li>
- * <li>FORMAT_ABBREV_ALL</li>
- * <li>FORMAT_NUMERIC_DATE</li>
- * </ul>
- *
- * <p>
- * If FORMAT_SHOW_TIME is set, the time is shown as part of the date range.
- * If the start and end time are the same, then just the start time is
- * shown.
- *
- * <p>
- * If FORMAT_SHOW_WEEKDAY is set, then the weekday is shown.
- *
- * <p>
- * If FORMAT_SHOW_YEAR is set, then the year is always shown.
- * If FORMAT_NO_YEAR is set, then the year is not shown.
- * If neither FORMAT_SHOW_YEAR nor FORMAT_NO_YEAR are set, then the year
- * is shown only if it is different from the current year, or if the start
- * and end dates fall on different years.
- *
- * <p>
- * Normally the date is shown unless the start and end day are the same.
- * If FORMAT_SHOW_DATE is set, then the date is always shown, even for
- * same day ranges.
- *
- * <p>
- * If FORMAT_NO_MONTH_DAY is set, then if the date is shown, just the
- * month name will be shown, not the day of the month. For example,
- * "January, 2008" instead of "January 6 - 12, 2008".
- *
- * <p>
- * If FORMAT_CAP_AMPM is set and 12-hour time is used, then the "AM"
- * and "PM" are capitalized.
- *
- * <p>
- * If FORMAT_NO_NOON is set and 12-hour time is used, then "12pm" is
- * shown instead of "noon".
- *
- * <p>
- * If FORMAT_CAP_NOON is set and 12-hour time is used, then "Noon" is
- * shown instead of "noon".
- *
- * <p>
- * If FORMAT_NO_MIDNIGHT is set and 12-hour time is used, then "12am" is
- * shown instead of "midnight".
- *
- * <p>
- * If FORMAT_CAP_NOON is set and 12-hour time is used, then "Midnight" is
- * shown instead of "midnight".
- *
- * <p>
- * If FORMAT_12HOUR is set and the time is shown, then the time is
- * shown in the 12-hour time format. You should not normally set this.
- * Instead, let the time format be chosen automatically according to the
- * system settings. If both FORMAT_12HOUR and FORMAT_24HOUR are set, then
- * FORMAT_24HOUR takes precedence.
- *
- * <p>
- * If FORMAT_24HOUR is set and the time is shown, then the time is
- * shown in the 24-hour time format. You should not normally set this.
- * Instead, let the time format be chosen automatically according to the
- * system settings. If both FORMAT_12HOUR and FORMAT_24HOUR are set, then
- * FORMAT_24HOUR takes precedence.
- *
- * <p>
- * If FORMAT_UTC is set, then the UTC timezone is used for the start
- * and end milliseconds.
- *
- * <p>
- * If FORMAT_ABBREV_TIME is set and 12-hour time format is used, then the
- * start and end times (if shown) are abbreviated by not showing the minutes
- * if they are zero. For example, instead of "3:00pm" the time would be
- * abbreviated to "3pm".
- *
- * <p>
- * If FORMAT_ABBREV_WEEKDAY is set, then the weekday (if shown) is
- * abbreviated to a 3-letter string.
- *
- * <p>
- * If FORMAT_ABBREV_MONTH is set, then the month (if shown) is abbreviated
- * to a 3-letter string.
- *
- * <p>
- * If FORMAT_ABBREV_ALL is set, then the weekday and the month (if shown)
- * are abbreviated to 3-letter strings.
- *
- * <p>
- * If FORMAT_NUMERIC_DATE is set, then the date is shown in numeric format
- * instead of using the name of the month. For example, "12/31/2008"
- * instead of "December 31, 2008".
- *
- * @param context the context is required only if the time is shown
- * @param startMillis the start time in UTC milliseconds
- * @param endMillis the end time in UTC milliseconds
- * @param flags a bit mask of options
- *
- * @return a string containing the formatted date/time range.
- */
- public static String formatDateRange(Context context, long startMillis,
- long endMillis, int flags) {
- Resources res = Resources.getSystem();
- boolean showTime = (flags & FORMAT_SHOW_TIME) != 0;
- boolean showWeekDay = (flags & FORMAT_SHOW_WEEKDAY) != 0;
- boolean showYear = (flags & FORMAT_SHOW_YEAR) != 0;
- boolean noYear = (flags & FORMAT_NO_YEAR) != 0;
- boolean useUTC = (flags & FORMAT_UTC) != 0;
- boolean abbrevWeekDay = (flags & (FORMAT_ABBREV_WEEKDAY | FORMAT_ABBREV_ALL)) != 0;
- boolean abbrevMonth = (flags & (FORMAT_ABBREV_MONTH | FORMAT_ABBREV_ALL)) != 0;
- boolean noMonthDay = (flags & FORMAT_NO_MONTH_DAY) != 0;
- boolean numericDate = (flags & FORMAT_NUMERIC_DATE) != 0;
-
- Time startDate;
- Time endDate;
-
- if (useUTC) {
- startDate = new Time(Time.TIMEZONE_UTC);
- endDate = new Time(Time.TIMEZONE_UTC);
- } else {
- startDate = new Time();
- endDate = new Time();
- }
-
- startDate.set(startMillis);
- endDate.set(endMillis);
- int startJulianDay = Time.getJulianDay(startMillis, startDate.gmtoff);
- int endJulianDay = Time.getJulianDay(endMillis, endDate.gmtoff);
- int dayDistance = endJulianDay - startJulianDay;
-
- // If the end date ends at 12am at the beginning of a day,
- // then modify it to make it look like it ends at midnight on
- // the previous day. This will allow us to display "8pm - midnight",
- // for example, instead of "Nov 10, 8pm - Nov 11, 12am". But we only do
- // this if it is midnight of the same day as the start date because
- // for multiple-day events, an end time of "midnight on Nov 11" is
- // ambiguous and confusing (is that midnight the start of Nov 11, or
- // the end of Nov 11?).
- // If we are not showing the time then also adjust the end date
- // for multiple-day events. This is to allow us to display, for
- // example, "Nov 10 -11" for an event with a start date of Nov 10
- // and an end date of Nov 12 at 00:00.
- // If the start and end time are the same, then skip this and don't
- // adjust the date.
- if ((endDate.hour | endDate.minute | endDate.second) == 0
- && (!showTime || dayDistance <= 1) && (startMillis != endMillis)) {
- endDate.monthDay -= 1;
- endDate.normalize(true /* ignore isDst */);
- }
-
- int startDay = startDate.monthDay;
- int startMonthNum = startDate.month;
- int startYear = startDate.year;
-
- int endDay = endDate.monthDay;
- int endMonthNum = endDate.month;
- int endYear = endDate.year;
-
- String startWeekDayString = "";
- String endWeekDayString = "";
- if (showWeekDay) {
- String weekDayFormat = "";
- if (abbrevWeekDay) {
- weekDayFormat = ABBREV_WEEKDAY_FORMAT;
- } else {
- weekDayFormat = WEEKDAY_FORMAT;
- }
- startWeekDayString = startDate.format(weekDayFormat);
- endWeekDayString = endDate.format(weekDayFormat);
- }
-
- String startTimeString = "";
- String endTimeString = "";
- if (showTime) {
- String startTimeFormat = "";
- String endTimeFormat = "";
- boolean force24Hour = (flags & FORMAT_24HOUR) != 0;
- boolean force12Hour = (flags & FORMAT_12HOUR) != 0;
- boolean use24Hour;
- if (force24Hour) {
- use24Hour = true;
- } else if (force12Hour) {
- use24Hour = false;
- } else {
- use24Hour = DateFormat.is24HourFormat(context);
- }
- if (use24Hour) {
- startTimeFormat = HOUR_MINUTE_24;
- endTimeFormat = HOUR_MINUTE_24;
- } else {
- boolean abbrevTime = (flags & (FORMAT_ABBREV_TIME | FORMAT_ABBREV_ALL)) != 0;
- boolean capAMPM = (flags & FORMAT_CAP_AMPM) != 0;
- boolean noNoon = (flags & FORMAT_NO_NOON) != 0;
- boolean capNoon = (flags & FORMAT_CAP_NOON) != 0;
- boolean noMidnight = (flags & FORMAT_NO_MIDNIGHT) != 0;
- boolean capMidnight = (flags & FORMAT_CAP_MIDNIGHT) != 0;
-
- boolean startOnTheHour = startDate.minute == 0 && startDate.second == 0;
- boolean endOnTheHour = endDate.minute == 0 && endDate.second == 0;
- if (abbrevTime && startOnTheHour) {
- if (capAMPM) {
- startTimeFormat = res.getString(com.android.internal.R.string.hour_cap_ampm);
- } else {
- startTimeFormat = res.getString(com.android.internal.R.string.hour_ampm);
- }
- } else {
- if (capAMPM) {
- startTimeFormat = res.getString(com.android.internal.R.string.hour_minute_cap_ampm);
- } else {
- startTimeFormat = res.getString(com.android.internal.R.string.hour_minute_ampm);
- }
- }
- if (abbrevTime && endOnTheHour) {
- if (capAMPM) {
- endTimeFormat = res.getString(com.android.internal.R.string.hour_cap_ampm);
- } else {
- endTimeFormat = res.getString(com.android.internal.R.string.hour_ampm);
- }
- } else {
- if (capAMPM) {
- endTimeFormat = res.getString(com.android.internal.R.string.hour_minute_cap_ampm);
- } else {
- endTimeFormat = res.getString(com.android.internal.R.string.hour_minute_ampm);
- }
- }
-
- if (startDate.hour == 12 && startOnTheHour && !noNoon) {
- if (capNoon) {
- startTimeFormat = res.getString(com.android.internal.R.string.Noon);
- } else {
- startTimeFormat = res.getString(com.android.internal.R.string.noon);
- }
- // Don't show the start time starting at midnight. Show
- // 12am instead.
- }
-
- if (endDate.hour == 12 && endOnTheHour && !noNoon) {
- if (capNoon) {
- endTimeFormat = res.getString(com.android.internal.R.string.Noon);
- } else {
- endTimeFormat = res.getString(com.android.internal.R.string.noon);
- }
- } else if (endDate.hour == 0 && endOnTheHour && !noMidnight) {
- if (capMidnight) {
- endTimeFormat = res.getString(com.android.internal.R.string.Midnight);
- } else {
- endTimeFormat = res.getString(com.android.internal.R.string.midnight);
- }
- }
- }
- startTimeString = startDate.format(startTimeFormat);
- endTimeString = endDate.format(endTimeFormat);
- }
-
- // Get the current year
- long millis = System.currentTimeMillis();
- Time time = new Time();
- time.set(millis);
- int currentYear = time.year;
-
- // Show the year if the user specified FORMAT_SHOW_YEAR or if
- // the starting and end years are different from each other
- // or from the current year. But don't show the year if the
- // user specified FORMAT_NO_YEAR;
- showYear = showYear || (!noYear && (startYear != endYear || startYear != currentYear));
-
- String defaultDateFormat, fullFormat, dateRange;
- if (numericDate) {
- defaultDateFormat = res.getString(com.android.internal.R.string.numeric_date);
- } else if (showYear) {
- if (abbrevMonth) {
- if (noMonthDay) {
- defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month_year);
- } else {
- defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month_day_year);
- }
- } else {
- if (noMonthDay) {
- defaultDateFormat = res.getString(com.android.internal.R.string.month_year);
- } else {
- defaultDateFormat = res.getString(com.android.internal.R.string.month_day_year);
- }
- }
- } else {
- if (abbrevMonth) {
- if (noMonthDay) {
- defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month);
- } else {
- defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month_day);
- }
- } else {
- if (noMonthDay) {
- defaultDateFormat = res.getString(com.android.internal.R.string.month);
- } else {
- defaultDateFormat = res.getString(com.android.internal.R.string.month_day);
- }
- }
- }
-
- if (showWeekDay) {
- if (showTime) {
- fullFormat = res.getString(com.android.internal.R.string.wday1_date1_time1_wday2_date2_time2);
- } else {
- fullFormat = res.getString(com.android.internal.R.string.wday1_date1_wday2_date2);
- }
- } else {
- if (showTime) {
- fullFormat = res.getString(com.android.internal.R.string.date1_time1_date2_time2);
- } else {
- fullFormat = res.getString(com.android.internal.R.string.date1_date2);
- }
- }
-
- if (noMonthDay && startMonthNum == endMonthNum) {
- // Example: "January, 2008"
- String startDateString = startDate.format(defaultDateFormat);
- return startDateString;
- }
-
- if (startYear != endYear || noMonthDay) {
- // Different year or we are not showing the month day number.
- // Example: "December 31, 2007 - January 1, 2008"
- // Or: "January - February, 2008"
- String startDateString = startDate.format(defaultDateFormat);
- String endDateString = endDate.format(defaultDateFormat);
-
- // The values that are used in a fullFormat string are specified
- // by position.
- dateRange = String.format(fullFormat,
- startWeekDayString, startDateString, startTimeString,
- endWeekDayString, endDateString, endTimeString);
- return dateRange;
- }
-
- // Get the month, day, and year strings for the start and end dates
- String monthFormat;
- if (numericDate) {
- monthFormat = NUMERIC_MONTH_FORMAT;
- } else if (abbrevMonth) {
- monthFormat = ABBREV_MONTH_FORMAT;
- } else {
- monthFormat = MONTH_FORMAT;
- }
- String startMonthString = startDate.format(monthFormat);
- String startMonthDayString = startDate.format(MONTH_DAY_FORMAT);
- String startYearString = startDate.format(YEAR_FORMAT);
- String endMonthString = endDate.format(monthFormat);
- String endMonthDayString = endDate.format(MONTH_DAY_FORMAT);
- String endYearString = endDate.format(YEAR_FORMAT);
-
- if (startMonthNum != endMonthNum) {
- // Same year, different month.
- // Example: "October 28 - November 3"
- // or: "Wed, Oct 31 - Sat, Nov 3, 2007"
- // or: "Oct 31, 8am - Sat, Nov 3, 2007, 5pm"
-
- int index = 0;
- if (showWeekDay) index = 1;
- if (showYear) index += 2;
- if (showTime) index += 4;
- if (numericDate) index += 8;
- int resId = sameYearTable[index];
- fullFormat = res.getString(resId);
-
- // The values that are used in a fullFormat string are specified
- // by position.
- dateRange = String.format(fullFormat,
- startWeekDayString, startMonthString, startMonthDayString,
- startYearString, startTimeString,
- endWeekDayString, endMonthString, endMonthDayString,
- endYearString, endTimeString);
- return dateRange;
- }
-
- if (startDay != endDay) {
- // Same month, different day.
- int index = 0;
- if (showWeekDay) index = 1;
- if (showYear) index += 2;
- if (showTime) index += 4;
- if (numericDate) index += 8;
- int resId = sameMonthTable[index];
- fullFormat = res.getString(resId);
-
- // The values that are used in a fullFormat string are specified
- // by position.
- dateRange = String.format(fullFormat,
- startWeekDayString, startMonthString, startMonthDayString,
- startYearString, startTimeString,
- endWeekDayString, endMonthString, endMonthDayString,
- endYearString, endTimeString);
- return dateRange;
- }
-
- // Same start and end day
- boolean showDate = (flags & FORMAT_SHOW_DATE) != 0;
-
- // If nothing was specified, then show the date.
- if (!showTime && !showDate && !showWeekDay) showDate = true;
-
- // Compute the time string (example: "10:00 - 11:00 am")
- String timeString = "";
- if (showTime) {
- // If the start and end time are the same, then just show the
- // start time.
- if (startMillis == endMillis) {
- // Same start and end time.
- // Example: "10:15 AM"
- timeString = startTimeString;
- } else {
- // Example: "10:00 - 11:00 am"
- String timeFormat = res.getString(com.android.internal.R.string.time1_time2);
- timeString = String.format(timeFormat, startTimeString, endTimeString);
- }
- }
-
- // Figure out which full format to use.
- fullFormat = "";
- String dateString = "";
- if (showDate) {
- dateString = startDate.format(defaultDateFormat);
- if (showWeekDay) {
- if (showTime) {
- // Example: "10:00 - 11:00 am, Tue, Oct 9"
- fullFormat = res.getString(com.android.internal.R.string.time_wday_date);
- } else {
- // Example: "Tue, Oct 9"
- fullFormat = res.getString(com.android.internal.R.string.wday_date);
- }
- } else {
- if (showTime) {
- // Example: "10:00 - 11:00 am, Oct 9"
- fullFormat = res.getString(com.android.internal.R.string.time_date);
- } else {
- // Example: "Oct 9"
- return dateString;
- }
- }
- } else if (showWeekDay) {
- if (showTime) {
- // Example: "10:00 - 11:00 am, Tue"
- fullFormat = res.getString(com.android.internal.R.string.time_wday);
- } else {
- // Example: "Tue"
- return startWeekDayString;
- }
- } else if (showTime) {
- return timeString;
- }
-
- // The values that are used in a fullFormat string are specified
- // by position.
- dateRange = String.format(fullFormat, timeString, startWeekDayString, dateString);
- return dateRange;
- }
-
- /**
- * Formats a date or a time according to the local conventions. There are
- * lots of options that allow the caller to control, for example, if the
- * time is shown, if the day of the week is shown, if the month name is
- * abbreviated, if noon is shown instead of 12pm, and so on. For the
- * complete list of options, see the documentation for
- * {@link #formatDateRange}.
- * <p>
- * Example output strings (date formats in these examples are shown using
- * the US date format convention but that may change depending on the
- * local settings):
- * <ul>
- * <li>10:15am</li>
- * <li>3:00pm</li>
- * <li>3pm</li>
- * <li>3PM</li>
- * <li>08:00</li>
- * <li>17:00</li>
- * <li>noon</li>
- * <li>Noon</li>
- * <li>midnight</li>
- * <li>Midnight</li>
- * <li>Oct 31</li>
- * <li>Oct 31, 2007</li>
- * <li>October 31, 2007</li>
- * <li>10am, Oct 31</li>
- * <li>17:00, Oct 31</li>
- * <li>Wed</li>
- * <li>Wednesday</li>
- * <li>10am, Wed, Oct 31</li>
- * <li>Wed, Oct 31</li>
- * <li>Wednesday, Oct 31</li>
- * <li>Wed, Oct 31, 2007</li>
- * <li>Wed, October 31</li>
- * <li>10/31/2007</li>
- * </ul>
- *
- * @param context the context is required only if the time is shown
- * @param millis a point in time in UTC milliseconds
- * @param flags a bit mask of formatting options
- * @return a string containing the formatted date/time.
- */
- public static String formatDateTime(Context context, long millis, int flags) {
- return formatDateRange(context, millis, millis, flags);
- }
-
- /**
- * @return a relative time string to display the time expressed by millis. Times
- * are counted starting at midnight, which means that assuming that the current
- * time is March 31st, 0:30:
- * <ul>
- * <li>"millis=0:10 today" will be displayed as "0:10"</li>
- * <li>"millis=11:30pm the day before" will be displayed as "Mar 30"</li>
- * </ul>
- * If the given millis is in a different year, then the full date is
- * returned in numeric format (e.g., "10/12/2008").
- *
- * @param withPreposition If true, the string returned will include the correct
- * preposition ("at 9:20am", "on 10/12/2008" or "on May 29").
- */
- public static CharSequence getRelativeTimeSpanString(Context c, long millis,
- boolean withPreposition) {
-
- long now = System.currentTimeMillis();
- long span = now - millis;
-
- if (sNowTime == null) {
- sNowTime = new Time();
- sThenTime = new Time();
- }
-
- sNowTime.set(now);
- sThenTime.set(millis);
-
- String result;
- int prepositionId;
- if (span < DAY_IN_MILLIS && sNowTime.weekDay == sThenTime.weekDay) {
- // Same day
- int flags = FORMAT_SHOW_TIME;
- result = formatDateRange(c, millis, millis, flags);
- prepositionId = R.string.preposition_for_time;
- } else if (sNowTime.year != sThenTime.year) {
- // Different years
- int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE;
- result = formatDateRange(c, millis, millis, flags);
-
- // This is a date (like "10/31/2008" so use the date preposition)
- prepositionId = R.string.preposition_for_date;
- } else {
- // Default
- int flags = FORMAT_SHOW_DATE | FORMAT_ABBREV_MONTH;
- result = formatDateRange(c, millis, millis, flags);
- prepositionId = R.string.preposition_for_date;
- }
- if (withPreposition) {
- Resources res = c.getResources();
- result = res.getString(prepositionId, result);
- }
- return result;
- }
-
- /**
- * Convenience function to return relative time string without preposition.
- * @param c context for resources
- * @param millis time in milliseconds
- * @return {@link CharSequence} containing relative time.
- * @see #getRelativeTimeSpanString(Context, long, boolean)
- */
- public static CharSequence getRelativeTimeSpanString(Context c, long millis) {
- return getRelativeTimeSpanString(c, millis, false /* no preposition */);
- }
-
- private static Time sNowTime;
- private static Time sThenTime;
-}
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
deleted file mode 100644
index 1b30aa0..0000000
--- a/core/java/android/text/format/Formatter.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.format;
-
-import android.content.Context;
-
-/**
- * Utility class to aid in formatting common values that are not covered
- * by the standard java.util.Formatter.
- */
-public final class Formatter {
-
- /**
- * Formats a content size to be in the form of bytes, kilobytes, megabytes, etc
- *
- * @param context Context to use to load the localized units
- * @param number size value to be formated
- * @return formated string with the number
- */
- public static String formatFileSize(Context context, long number) {
- if (context == null) {
- return "";
- }
-
- float result = number;
- int suffix = com.android.internal.R.string.byteShort;
- if (result > 900) {
- suffix = com.android.internal.R.string.kilobyteShort;
- result = result / 1024;
- }
- if (result > 900) {
- suffix = com.android.internal.R.string.megabyteShort;
- result = result / 1024;
- }
- if (result > 900) {
- suffix = com.android.internal.R.string.gigabyteShort;
- result = result / 1024;
- }
- if (result > 900) {
- suffix = com.android.internal.R.string.terabyteShort;
- result = result / 1024;
- }
- if (result > 900) {
- suffix = com.android.internal.R.string.petabyteShort;
- result = result / 1024;
- }
- if (result < 100) {
- return String.format("%.2f%s", result, context.getText(suffix).toString());
- }
- return String.format("%.0f%s", result, context.getText(suffix).toString());
- }
-
- /**
- * Returns a string in the canonical IP format ###.###.###.### from a packed integer containing
- * the IP address. The IP address is expected to be in little-endian format (LSB first). That
- * is, 0x01020304 will return "4.3.2.1".
- *
- * @param addr the IP address as a packed integer with LSB first.
- * @return string with canonical IP address format.
- */
- public static String formatIpAddress(int addr) {
- StringBuffer buf = new StringBuffer();
- buf.append(addr & 0xff).append('.').
- append((addr >>>= 8) & 0xff).append('.').
- append((addr >>>= 8) & 0xff).append('.').
- append((addr >>>= 8) & 0xff);
- return buf.toString();
- }
-}
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
deleted file mode 100644
index daa99c2..0000000
--- a/core/java/android/text/format/Time.java
+++ /dev/null
@@ -1,757 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.format;
-
-import android.content.res.Resources;
-
-import java.util.Locale;
-import java.util.TimeZone;
-
-/**
- * The Time class is a faster replacement for the java.util.Calendar and
- * java.util.GregorianCalendar classes. An instance of the Time class represents
- * a moment in time, specified with second precision. It is modelled after
- * struct tm, and in fact, uses struct tm to implement most of the
- * functionality.
- */
-public class Time {
- private static final String Y_M_D_T_H_M_S_000 = "%Y-%m-%dT%H:%M:%S.000";
- private static final String Y_M_D_T_H_M_S_000_Z = "%Y-%m-%dT%H:%M:%S.000Z";
- private static final String Y_M_D = "%Y-%m-%d";
-
- public static final String TIMEZONE_UTC = "UTC";
-
- /**
- * The Julian day of the epoch, that is, January 1, 1970 on the Gregorian
- * calendar.
- */
- public static final int EPOCH_JULIAN_DAY = 2440588;
-
- /**
- * True if this is an allDay event. The hour, minute, second fields are
- * all zero, and the date is displayed the same in all time zones.
- */
- public boolean allDay;
-
- /**
- * Seconds [0-61] (2 leap seconds allowed)
- */
- public int second;
-
- /**
- * Minute [0-59]
- */
- public int minute;
-
- /**
- * Hour of day [0-23]
- */
- public int hour;
-
- /**
- * Day of month [1-31]
- */
- public int monthDay;
-
- /**
- * Month [0-11]
- */
- public int month;
-
- /**
- * Year. TBD. Is this years since 1900 like in struct tm?
- */
- public int year;
-
- /**
- * Day of week [0-6]
- */
- public int weekDay;
-
- /**
- * Day of year [0-365]
- */
- public int yearDay;
-
- /**
- * This time is in daylight savings time. One of:
- * <ul>
- * <li><b>positive</b> - in dst</li>
- * <li><b>0</b> - not in dst</li>
- * <li><b>negative</b> - unknown</li>
- * </ul>
- */
- public int isDst;
-
- /**
- * Offset from UTC (in seconds).
- */
- public long gmtoff;
-
- /**
- * The timezone for this Time. Should not be null.
- */
- public String timezone;
-
- /*
- * Define symbolic constants for accessing the fields in this class. Used in
- * getActualMaximum().
- */
- public static final int SECOND = 1;
- public static final int MINUTE = 2;
- public static final int HOUR = 3;
- public static final int MONTH_DAY = 4;
- public static final int MONTH = 5;
- public static final int YEAR = 6;
- public static final int WEEK_DAY = 7;
- public static final int YEAR_DAY = 8;
- public static final int WEEK_NUM = 9;
-
- public static final int SUNDAY = 0;
- public static final int MONDAY = 1;
- public static final int TUESDAY = 2;
- public static final int WEDNESDAY = 3;
- public static final int THURSDAY = 4;
- public static final int FRIDAY = 5;
- public static final int SATURDAY = 6;
-
- /*
- * The Locale for which date formatting strings have been loaded.
- */
- private static Locale sLocale;
- private static String[] sShortMonths;
- private static String[] sLongMonths;
- private static String[] sShortWeekdays;
- private static String[] sLongWeekdays;
- private static String sTimeOnlyFormat;
- private static String sDateOnlyFormat;
- private static String sDateTimeFormat;
- private static String sAm;
- private static String sPm;
- private static String sDateCommand = "%a %b %e %H:%M:%S %Z %Y";
-
- /**
- * Construct a Time object in the timezone named by the string
- * argument "timezone". The time is initialized to Jan 1, 1970.
- * @param timezone string containing the timezone to use.
- * @see TimeZone
- */
- public Time(String timezone) {
- if (timezone == null) {
- throw new NullPointerException("timezone is null!");
- }
- this.timezone = timezone;
- this.year = 1970;
- this.monthDay = 1;
- // Set the daylight-saving indicator to the unknown value -1 so that
- // it will be recomputed.
- this.isDst = -1;
- }
-
- /**
- * Construct a Time object in the default timezone. The time is initialized to
- * Jan 1, 1970.
- */
- public Time() {
- this(TimeZone.getDefault().getID());
- }
-
- /**
- * A copy constructor. Construct a Time object by copying the given
- * Time object. No normalization occurs.
- *
- * @param other
- */
- public Time(Time other) {
- set(other);
- }
-
- /**
- * Ensures the values in each field are in range. For example if the
- * current value of this calendar is March 32, normalize() will convert it
- * to April 1. It also fills in weekDay, yearDay, isDst and gmtoff.
- *
- * <p>
- * If "ignoreDst" is true, then this method sets the "isDst" field to -1
- * (the "unknown" value) before normalizing. It then computes the
- * correct value for "isDst".
- *
- * <p>
- * See {@link #toMillis(boolean)} for more information about when to
- * use <tt>true</tt> or <tt>false</tt> for "ignoreDst".
- *
- * @return the UTC milliseconds since the epoch
- */
- native public long normalize(boolean ignoreDst);
-
- /**
- * Convert this time object so the time represented remains the same, but is
- * instead located in a different timezone. This method automatically calls
- * normalize() in some cases
- */
- native public void switchTimezone(String timezone);
-
- private static final int[] DAYS_PER_MONTH = { 31, 28, 31, 30, 31, 30, 31,
- 31, 30, 31, 30, 31 };
-
- /**
- * Return the maximum possible value for the given field given the value of
- * the other fields. Requires that it be normalized for MONTH_DAY and
- * YEAR_DAY.
- * @param field one of the constants for HOUR, MINUTE, SECOND, etc.
- * @return the maximum value for the field.
- */
- public int getActualMaximum(int field) {
- switch (field) {
- case SECOND:
- return 59; // leap seconds, bah humbug
- case MINUTE:
- return 59;
- case HOUR:
- return 23;
- case MONTH_DAY: {
- int n = DAYS_PER_MONTH[this.month];
- if (n != 28) {
- return n;
- } else {
- int y = this.year;
- return ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0)) ? 29 : 28;
- }
- }
- case MONTH:
- return 11;
- case YEAR:
- return 2037;
- case WEEK_DAY:
- return 6;
- case YEAR_DAY: {
- int y = this.year;
- // Year days are numbered from 0, so the last one is usually 364.
- return ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0)) ? 365 : 364;
- }
- case WEEK_NUM:
- throw new RuntimeException("WEEK_NUM not implemented");
- default:
- throw new RuntimeException("bad field=" + field);
- }
- }
-
- /**
- * Clears all values, setting the timezone to the given timezone. Sets isDst
- * to a negative value to mean "unknown".
- * @param timezone the timezone to use.
- */
- public void clear(String timezone) {
- if (timezone == null) {
- throw new NullPointerException("timezone is null!");
- }
- this.timezone = timezone;
- this.allDay = false;
- this.second = 0;
- this.minute = 0;
- this.hour = 0;
- this.monthDay = 0;
- this.month = 0;
- this.year = 0;
- this.weekDay = 0;
- this.yearDay = 0;
- this.gmtoff = 0;
- this.isDst = -1;
- }
-
- /**
- * return a negative number if a is less than b, a positive number if a is
- * greater than b, and 0 if they are equal.
- */
- native public static int compare(Time a, Time b);
-
- /**
- * Print the current value given the format string provided. See man
- * strftime for what means what. The final string must be less than 256
- * characters.
- * @param format a string containing the desired format.
- * @return a String containing the current time expressed in the current locale.
- */
- public String format(String format) {
- synchronized (Time.class) {
- Locale locale = Locale.getDefault();
-
- if (sLocale == null || locale == null || !(locale.equals(sLocale))) {
- Resources r = Resources.getSystem();
-
- sShortMonths = new String[] {
- r.getString(com.android.internal.R.string.month_medium_january),
- r.getString(com.android.internal.R.string.month_medium_february),
- r.getString(com.android.internal.R.string.month_medium_march),
- r.getString(com.android.internal.R.string.month_medium_april),
- r.getString(com.android.internal.R.string.month_medium_may),
- r.getString(com.android.internal.R.string.month_medium_june),
- r.getString(com.android.internal.R.string.month_medium_july),
- r.getString(com.android.internal.R.string.month_medium_august),
- r.getString(com.android.internal.R.string.month_medium_september),
- r.getString(com.android.internal.R.string.month_medium_october),
- r.getString(com.android.internal.R.string.month_medium_november),
- r.getString(com.android.internal.R.string.month_medium_december),
- };
- sLongMonths = new String[] {
- r.getString(com.android.internal.R.string.month_long_january),
- r.getString(com.android.internal.R.string.month_long_february),
- r.getString(com.android.internal.R.string.month_long_march),
- r.getString(com.android.internal.R.string.month_long_april),
- r.getString(com.android.internal.R.string.month_long_may),
- r.getString(com.android.internal.R.string.month_long_june),
- r.getString(com.android.internal.R.string.month_long_july),
- r.getString(com.android.internal.R.string.month_long_august),
- r.getString(com.android.internal.R.string.month_long_september),
- r.getString(com.android.internal.R.string.month_long_october),
- r.getString(com.android.internal.R.string.month_long_november),
- r.getString(com.android.internal.R.string.month_long_december),
- };
- sShortWeekdays = new String[] {
- r.getString(com.android.internal.R.string.day_of_week_medium_sunday),
- r.getString(com.android.internal.R.string.day_of_week_medium_monday),
- r.getString(com.android.internal.R.string.day_of_week_medium_tuesday),
- r.getString(com.android.internal.R.string.day_of_week_medium_wednesday),
- r.getString(com.android.internal.R.string.day_of_week_medium_thursday),
- r.getString(com.android.internal.R.string.day_of_week_medium_friday),
- r.getString(com.android.internal.R.string.day_of_week_medium_saturday),
- };
- sLongWeekdays = new String[] {
- r.getString(com.android.internal.R.string.day_of_week_long_sunday),
- r.getString(com.android.internal.R.string.day_of_week_long_monday),
- r.getString(com.android.internal.R.string.day_of_week_long_tuesday),
- r.getString(com.android.internal.R.string.day_of_week_long_wednesday),
- r.getString(com.android.internal.R.string.day_of_week_long_thursday),
- r.getString(com.android.internal.R.string.day_of_week_long_friday),
- r.getString(com.android.internal.R.string.day_of_week_long_saturday),
- };
- sTimeOnlyFormat = r.getString(com.android.internal.R.string.time_of_day);
- sDateOnlyFormat = r.getString(com.android.internal.R.string.month_day_year);
- sDateTimeFormat = r.getString(com.android.internal.R.string.date_and_time);
- sAm = r.getString(com.android.internal.R.string.am);
- sPm = r.getString(com.android.internal.R.string.pm);
-
- sLocale = locale;
- }
-
- return format1(format);
- }
- }
-
- native private String format1(String format);
-
- /**
- * Return the current time in YYYYMMDDTHHMMSS<tz> format
- */
- @Override
- native public String toString();
-
- /**
- * Parses a date-time string in either the RFC 2445 format or an abbreviated
- * format that does not include the "time" field. For example, all of the
- * following strings are valid:
- *
- * <ul>
- * <li>"20081013T160000Z"</li>
- * <li>"20081013T160000"</li>
- * <li>"20081013"</li>
- * </ul>
- *
- * Returns whether or not the time is in UTC (ends with Z). If the string
- * ends with "Z" then the timezone is set to UTC. If the date-time string
- * included only a date and no time field, then the <code>allDay</code>
- * field of this Time class is set to true and the <code>hour</code>,
- * <code>minute</code>, and <code>second</code> fields are set to zero;
- * otherwise (a time field was included in the date-time string)
- * <code>allDay</code> is set to false. The fields <code>weekDay</code>,
- * <code>yearDay</code>, and <code>gmtoff</code> are always set to zero,
- * and the field <code>isDst</code> is set to -1 (unknown). To set those
- * fields, call {@link #normalize(boolean)} after parsing.
- *
- * To parse a date-time string and convert it to UTC milliseconds, do
- * something like this:
- *
- * <pre>
- * Time time = new Time();
- * String date = "20081013T160000Z";
- * time.parse(date);
- * long millis = time.normalize(false);
- * </pre>
- *
- * @param s the string to parse
- * @return true if the resulting time value is in UTC time
- * @throws android.util.TimeFormatException if s cannot be parsed.
- */
- public boolean parse(String s) {
- if (nativeParse(s)) {
- timezone = TIMEZONE_UTC;
- return true;
- }
- return false;
- }
-
- /**
- * Parse a time in the current zone in YYYYMMDDTHHMMSS format.
- */
- native private boolean nativeParse(String s);
-
- /**
- * Parse a time in RFC 3339 format. This method also parses simple dates
- * (that is, strings that contain no time or time offset). For example,
- * all of the following strings are valid:
- *
- * <ul>
- * <li>"2008-10-13T16:00:00.000Z"</li>
- * <li>"2008-10-13T16:00:00.000+07:00"</li>
- * <li>"2008-10-13T16:00:00.000-07:00"</li>
- * <li>"2008-10-13"</li>
- * </ul>
- *
- * <p>
- * If the string contains a time and time offset, then the time offset will
- * be used to convert the time value to UTC.
- * </p>
- *
- * <p>
- * If the given string contains just a date (with no time field), then
- * the {@link #allDay} field is set to true and the {@link #hour},
- * {@link #minute}, and {@link #second} fields are set to zero.
- * </p>
- *
- * <p>
- * Returns true if the resulting time value is in UTC time.
- * </p>
- *
- * @param s the string to parse
- * @return true if the resulting time value is in UTC time
- */
- public boolean parse3339(String s) {
- if (nativeParse3339(s)) {
- timezone = TIMEZONE_UTC;
- return true;
- }
- return false;
- }
-
- native private boolean nativeParse3339(String s);
-
- /**
- * Returns the timezone string that is currently set for the device.
- */
- public static String getCurrentTimezone() {
- return TimeZone.getDefault().getID();
- }
-
- /**
- * Sets the time of the given Time object to the current time.
- */
- native public void setToNow();
-
- /**
- * Converts this time to milliseconds. Suitable for interacting with the
- * standard java libraries. The time is in UTC milliseconds since the epoch.
- * This does an implicit normalization to compute the milliseconds but does
- * <em>not</em> change any of the fields in this Time object. If you want
- * to normalize the fields in this Time object and also get the milliseconds
- * then use {@link #normalize(boolean)}.
- *
- * <p>
- * If "ignoreDst" is false, then this method uses the current setting of the
- * "isDst" field and will adjust the returned time if the "isDst" field is
- * wrong for the given time. See the sample code below for an example of
- * this.
- *
- * <p>
- * If "ignoreDst" is true, then this method ignores the current setting of
- * the "isDst" field in this Time object and will instead figure out the
- * correct value of "isDst" (as best it can) from the fields in this
- * Time object. The only case where this method cannot figure out the
- * correct value of the "isDst" field is when the time is inherently
- * ambiguous because it falls in the hour that is repeated when switching
- * from Daylight-Saving Time to Standard Time.
- *
- * <p>
- * Here is an example where <tt>toMillis(true)</tt> adjusts the time,
- * assuming that DST changes at 2am on Sunday, Nov 4, 2007.
- *
- * <pre>
- * Time time = new Time();
- * time.set(2007, 10, 4); // set the date to Nov 4, 2007, 12am
- * time.normalize(); // this sets isDst = 1
- * time.monthDay += 1; // changes the date to Nov 5, 2007, 12am
- * millis = time.toMillis(false); // millis is Nov 4, 2007, 11pm
- * millis = time.toMillis(true); // millis is Nov 5, 2007, 12am
- * </pre>
- *
- * <p>
- * To avoid this problem, use <tt>toMillis(true)</tt>
- * after adding or subtracting days or explicitly setting the "monthDay"
- * field. On the other hand, if you are adding
- * or subtracting hours or minutes, then you should use
- * <tt>toMillis(false)</tt>.
- *
- * <p>
- * You should also use <tt>toMillis(false)</tt> if you want
- * to read back the same milliseconds that you set with {@link #set(long)}
- * or {@link #set(Time)} or after parsing a date string.
- */
- native public long toMillis(boolean ignoreDst);
-
- /**
- * Sets the fields in this Time object given the UTC milliseconds. After
- * this method returns, all the fields are normalized.
- * This also sets the "isDst" field to the correct value.
- *
- * @param millis the time in UTC milliseconds since the epoch.
- */
- native public void set(long millis);
-
- /**
- * Format according to RFC 2445 DATETIME type.
- *
- * <p>
- * The same as format("%Y%m%dT%H%M%S").
- */
- native public String format2445();
-
- /**
- * Copy the value of that to this Time object. No normalization happens.
- */
- public void set(Time that) {
- this.timezone = that.timezone;
- this.allDay = that.allDay;
- this.second = that.second;
- this.minute = that.minute;
- this.hour = that.hour;
- this.monthDay = that.monthDay;
- this.month = that.month;
- this.year = that.year;
- this.weekDay = that.weekDay;
- this.yearDay = that.yearDay;
- this.isDst = that.isDst;
- this.gmtoff = that.gmtoff;
- }
-
- /**
- * Sets the fields. Sets weekDay, yearDay and gmtoff to 0, and isDst to -1.
- * Call {@link #normalize(boolean)} if you need those.
- */
- public void set(int second, int minute, int hour, int monthDay, int month, int year) {
- this.allDay = false;
- this.second = second;
- this.minute = minute;
- this.hour = hour;
- this.monthDay = monthDay;
- this.month = month;
- this.year = year;
- this.weekDay = 0;
- this.yearDay = 0;
- this.isDst = -1;
- this.gmtoff = 0;
- }
-
- /**
- * Sets the date from the given fields. Also sets allDay to true.
- * Sets weekDay, yearDay and gmtoff to 0, and isDst to -1.
- * Call {@link #normalize(boolean)} if you need those.
- *
- * @param monthDay the day of the month (in the range [1,31])
- * @param month the zero-based month number (in the range [0,11])
- * @param year the year
- */
- public void set(int monthDay, int month, int year) {
- this.allDay = true;
- this.second = 0;
- this.minute = 0;
- this.hour = 0;
- this.monthDay = monthDay;
- this.month = month;
- this.year = year;
- this.weekDay = 0;
- this.yearDay = 0;
- this.isDst = -1;
- this.gmtoff = 0;
- }
-
- /**
- * Returns true if the time represented by this Time object occurs before
- * the given time.
- *
- * @param that a given Time object to compare against
- * @return true if this time is less than the given time
- */
- public boolean before(Time that) {
- return Time.compare(this, that) < 0;
- }
-
-
- /**
- * Returns true if the time represented by this Time object occurs after
- * the given time.
- *
- * @param that a given Time object to compare against
- * @return true if this time is greater than the given time
- */
- public boolean after(Time that) {
- return Time.compare(this, that) > 0;
- }
-
- /**
- * This array is indexed by the weekDay field (SUNDAY=0, MONDAY=1, etc.)
- * and gives a number that can be added to the yearDay to give the
- * closest Thursday yearDay.
- */
- private static final int[] sThursdayOffset = { -3, 3, 2, 1, 0, -1, -2 };
-
- /**
- * Computes the week number according to ISO 8601. The current Time
- * object must already be normalized because this method uses the
- * yearDay and weekDay fields.
- *
- * <p>
- * In IS0 8601, weeks start on Monday.
- * The first week of the year (week 1) is defined by ISO 8601 as the
- * first week with four or more of its days in the starting year.
- * Or equivalently, the week containing January 4. Or equivalently,
- * the week with the year's first Thursday in it.
- * </p>
- *
- * <p>
- * The week number can be calculated by counting Thursdays. Week N
- * contains the Nth Thursday of the year.
- * </p>
- *
- * @return the ISO week number.
- */
- public int getWeekNumber() {
- // Get the year day for the closest Thursday
- int closestThursday = yearDay + sThursdayOffset[weekDay];
-
- // Year days start at 0
- if (closestThursday >= 0 && closestThursday <= 364) {
- return closestThursday / 7 + 1;
- }
-
- // The week crosses a year boundary.
- Time temp = new Time(this);
- temp.monthDay += sThursdayOffset[weekDay];
- temp.normalize(true /* ignore isDst */);
- return temp.yearDay / 7 + 1;
- }
-
- /**
- * Return a string in the RFC 3339 format.
- * <p>
- * If allDay is true, expresses the time as Y-M-D</p>
- * <p>
- * Otherwise, if the timezone is UTC, expresses the time as Y-M-D-T-H-M-S UTC</p>
- * <p>
- * Otherwise the time is expressed the time as Y-M-D-T-H-M-S +- GMT</p>
- * @param allDay
- * @return string in the RFC 3339 format.
- */
- public String format3339(boolean allDay) {
- if (allDay) {
- return format(Y_M_D);
- } else if (TIMEZONE_UTC.equals(timezone)) {
- return format(Y_M_D_T_H_M_S_000_Z);
- } else {
- String base = format(Y_M_D_T_H_M_S_000);
- String sign = (gmtoff < 0) ? "-" : "+";
- int offset = (int)Math.abs(gmtoff);
- int minutes = (offset % 3600) / 60;
- int hours = offset / 3600;
-
- return String.format("%s%s%02d:%02d", base, sign, hours, minutes);
- }
- }
-
- /**
- * Returns true if the day of the given time is the epoch on the Julian Calendar
- * (January 1, 1970 on the Gregorian calendar).
- *
- * @param time the time to test
- * @return true if epoch.
- */
- public static boolean isEpoch(Time time) {
- long millis = time.toMillis(true);
- return getJulianDay(millis, 0) == EPOCH_JULIAN_DAY;
- }
-
- /**
- * Computes the Julian day number, given the UTC milliseconds
- * and the offset (in seconds) from UTC. The Julian day for a given
- * date will be the same for every timezone. For example, the Julian
- * day for July 1, 2008 is 2454649. This is the same value no matter
- * what timezone is being used. The Julian day is useful for testing
- * if two events occur on the same day and for determining the relative
- * time of an event from the present ("yesterday", "3 days ago", etc.).
- *
- * <p>
- * Use {@link #toMillis(boolean)} to get the milliseconds.
- *
- * @param millis the time in UTC milliseconds
- * @param gmtoff the offset from UTC in seconds
- * @return the Julian day
- */
- public static int getJulianDay(long millis, long gmtoff) {
- long offsetMillis = gmtoff * 1000;
- long julianDay = (millis + offsetMillis) / DateUtils.DAY_IN_MILLIS;
- return (int) julianDay + EPOCH_JULIAN_DAY;
- }
-
- /**
- * <p>Sets the time from the given Julian day number, which must be based on
- * the same timezone that is set in this Time object. The "gmtoff" field
- * need not be initialized because the given Julian day may have a different
- * GMT offset than whatever is currently stored in this Time object anyway.
- * After this method returns all the fields will be normalized and the time
- * will be set to 12am at the beginning of the given Julian day.
- * </p>
- *
- * <p>
- * The only exception to this is if 12am does not exist for that day because
- * of daylight saving time. For example, Cairo, Eqypt moves time ahead one
- * hour at 12am on April 25, 2008 and there are a few other places that
- * also change daylight saving time at 12am. In those cases, the time
- * will be set to 1am.
- * </p>
- *
- * @param julianDay the Julian day in the timezone for this Time object
- * @return the UTC milliseconds for the beginning of the Julian day
- */
- public long setJulianDay(int julianDay) {
- // Don't bother with the GMT offset since we don't know the correct
- // value for the given Julian day. Just get close and then adjust
- // the day.
- long millis = (julianDay - EPOCH_JULIAN_DAY) * DateUtils.DAY_IN_MILLIS;
- set(millis);
-
- // Figure out how close we are to the requested Julian day.
- // We can't be off by more than a day.
- int approximateDay = getJulianDay(millis, gmtoff);
- int diff = julianDay - approximateDay;
- monthDay += diff;
-
- // Set the time to 12am and re-normalize.
- hour = 0;
- minute = 0;
- second = 0;
- millis = normalize(true);
- return millis;
- }
-}
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
deleted file mode 100644
index 6df0b35..0000000
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.util.Log;
-import android.view.KeyEvent;
-import android.text.*;
-import android.widget.TextView;
-import android.view.View;
-import android.view.MotionEvent;
-
-// XXX this doesn't extend MetaKeyKeyListener because the signatures
-// don't match. Need to figure that out. Meanwhile the meta keys
-// won't work in fields that don't take input.
-
-public class
-ArrowKeyMovementMethod
-implements MovementMethod
-{
- private boolean up(TextView widget, Spannable buffer) {
- boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_SHIFT_ON) == 1) ||
- (MetaKeyKeyListener.getMetaState(buffer,
- MetaKeyKeyListener.META_SELECTING) != 0);
- boolean alt = MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_ALT_ON) == 1;
- Layout layout = widget.getLayout();
-
- if (cap) {
- if (alt) {
- Selection.extendSelection(buffer, 0);
- return true;
- } else {
- return Selection.extendUp(buffer, layout);
- }
- } else {
- if (alt) {
- Selection.setSelection(buffer, 0);
- return true;
- } else {
- return Selection.moveUp(buffer, layout);
- }
- }
- }
-
- private boolean down(TextView widget, Spannable buffer) {
- boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_SHIFT_ON) == 1) ||
- (MetaKeyKeyListener.getMetaState(buffer,
- MetaKeyKeyListener.META_SELECTING) != 0);
- boolean alt = MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_ALT_ON) == 1;
- Layout layout = widget.getLayout();
-
- if (cap) {
- if (alt) {
- Selection.extendSelection(buffer, buffer.length());
- return true;
- } else {
- return Selection.extendDown(buffer, layout);
- }
- } else {
- if (alt) {
- Selection.setSelection(buffer, buffer.length());
- return true;
- } else {
- return Selection.moveDown(buffer, layout);
- }
- }
- }
-
- private boolean left(TextView widget, Spannable buffer) {
- boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_SHIFT_ON) == 1) ||
- (MetaKeyKeyListener.getMetaState(buffer,
- MetaKeyKeyListener.META_SELECTING) != 0);
- boolean alt = MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_ALT_ON) == 1;
- Layout layout = widget.getLayout();
-
- if (cap) {
- if (alt) {
- return Selection.extendToLeftEdge(buffer, layout);
- } else {
- return Selection.extendLeft(buffer, layout);
- }
- } else {
- if (alt) {
- return Selection.moveToLeftEdge(buffer, layout);
- } else {
- return Selection.moveLeft(buffer, layout);
- }
- }
- }
-
- private boolean right(TextView widget, Spannable buffer) {
- boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_SHIFT_ON) == 1) ||
- (MetaKeyKeyListener.getMetaState(buffer,
- MetaKeyKeyListener.META_SELECTING) != 0);
- boolean alt = MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_ALT_ON) == 1;
- Layout layout = widget.getLayout();
-
- if (cap) {
- if (alt) {
- return Selection.extendToRightEdge(buffer, layout);
- } else {
- return Selection.extendRight(buffer, layout);
- }
- } else {
- if (alt) {
- return Selection.moveToRightEdge(buffer, layout);
- } else {
- return Selection.moveRight(buffer, layout);
- }
- }
- }
-
- public boolean onKeyDown(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
- if (executeDown(widget, buffer, keyCode)) {
- MetaKeyKeyListener.adjustMetaAfterKeypress(buffer);
- MetaKeyKeyListener.resetLockedMeta(buffer);
- return true;
- }
-
- return false;
- }
-
- private boolean executeDown(TextView widget, Spannable buffer, int keyCode) {
- boolean handled = false;
-
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_UP:
- handled |= up(widget, buffer);
- break;
-
- case KeyEvent.KEYCODE_DPAD_DOWN:
- handled |= down(widget, buffer);
- break;
-
- case KeyEvent.KEYCODE_DPAD_LEFT:
- handled |= left(widget, buffer);
- break;
-
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- handled |= right(widget, buffer);
- break;
-
- case KeyEvent.KEYCODE_DPAD_CENTER:
- if (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0) {
- if (widget.showContextMenu()) {
- handled = true;
- }
- }
- }
-
- if (handled) {
- MetaKeyKeyListener.adjustMetaAfterKeypress(buffer);
- MetaKeyKeyListener.resetLockedMeta(buffer);
- }
-
- return handled;
- }
-
- public boolean onKeyUp(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
- return false;
- }
-
- public boolean onKeyOther(TextView view, Spannable text, KeyEvent event) {
- int code = event.getKeyCode();
- if (code != KeyEvent.KEYCODE_UNKNOWN
- && event.getAction() == KeyEvent.ACTION_MULTIPLE) {
- int repeat = event.getRepeatCount();
- boolean handled = false;
- while ((--repeat) > 0) {
- handled |= executeDown(view, text, code);
- }
- return handled;
- }
- return false;
- }
-
- public boolean onTrackballEvent(TextView widget, Spannable text,
- MotionEvent event) {
- return false;
- }
-
- public boolean onTouchEvent(TextView widget, Spannable buffer,
- MotionEvent event) {
- boolean handled = Touch.onTouchEvent(widget, buffer, event);
-
- if (widget.isFocused()) {
- if (event.getAction() == MotionEvent.ACTION_UP) {
- int x = (int) event.getX();
- int y = (int) event.getY();
-
- x -= widget.getTotalPaddingLeft();
- y -= widget.getTotalPaddingTop();
-
- x += widget.getScrollX();
- y += widget.getScrollY();
-
- Layout layout = widget.getLayout();
- int line = layout.getLineForVertical(y);
- int off = layout.getOffsetForHorizontal(line, x);
-
- boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
- KeyEvent.META_SHIFT_ON) == 1) ||
- (MetaKeyKeyListener.getMetaState(buffer,
- MetaKeyKeyListener.META_SELECTING) != 0);
-
- if (cap) {
- Selection.extendSelection(buffer, off);
- } else {
- Selection.setSelection(buffer, off);
- }
-
- MetaKeyKeyListener.adjustMetaAfterKeypress(buffer);
- MetaKeyKeyListener.resetLockedMeta(buffer);
-
- return true;
- }
- }
-
- return handled;
- }
-
- public boolean canSelectArbitrarily() {
- return true;
- }
-
- public void initialize(TextView widget, Spannable text) {
- Selection.setSelection(text, 0);
- }
-
- public void onTakeFocus(TextView view, Spannable text, int dir) {
- if ((dir & (View.FOCUS_FORWARD | View.FOCUS_DOWN)) != 0) {
- Layout layout = view.getLayout();
-
- if (layout == null) {
- /*
- * This shouldn't be null, but do something sensible if it is.
- */
- Selection.setSelection(text, text.length());
- } else {
- /*
- * Put the cursor at the end of the first line, which is
- * either the last offset if there is only one line, or the
- * offset before the first character of the second line
- * if there is more than one line.
- */
- if (layout.getLineCount() == 1) {
- Selection.setSelection(text, text.length());
- } else {
- Selection.setSelection(text, layout.getLineStart(1) - 1);
- }
- }
- } else {
- Selection.setSelection(text, text.length());
- }
- }
-
- public static MovementMethod getInstance() {
- if (sInstance == null)
- sInstance = new ArrowKeyMovementMethod();
-
- return sInstance;
- }
-
- private static ArrowKeyMovementMethod sInstance;
-}
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
deleted file mode 100644
index 6df6a3a..0000000
--- a/core/java/android/text/method/BaseKeyListener.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.view.KeyEvent;
-import android.view.View;
-import android.text.*;
-import android.text.method.TextKeyListener.Capitalize;
-import android.widget.TextView;
-
-public abstract class BaseKeyListener
-extends MetaKeyKeyListener
-implements KeyListener {
- /* package */ static final Object OLD_SEL_START = new NoCopySpan.Concrete();
-
- /**
- * Performs the action that happens when you press the DEL key in
- * a TextView. If there is a selection, deletes the selection;
- * otherwise, DEL alone deletes the character before the cursor,
- * if any;
- * ALT+DEL deletes everything on the line the cursor is on.
- *
- * @return true if anything was deleted; false otherwise.
- */
- public boolean backspace(View view, Editable content, int keyCode,
- KeyEvent event) {
- int selStart, selEnd;
- boolean result = true;
-
- {
- int a = Selection.getSelectionStart(content);
- int b = Selection.getSelectionEnd(content);
-
- selStart = Math.min(a, b);
- selEnd = Math.max(a, b);
- }
-
- if (selStart != selEnd) {
- content.delete(selStart, selEnd);
- } else if (altBackspace(view, content, keyCode, event)) {
- result = true;
- } else {
- int to = TextUtils.getOffsetBefore(content, selEnd);
-
- if (to != selEnd) {
- content.delete(Math.min(to, selEnd), Math.max(to, selEnd));
- }
- else {
- result = false;
- }
- }
-
- if (result)
- adjustMetaAfterKeypress(content);
-
- return result;
- }
-
- private boolean altBackspace(View view, Editable content, int keyCode,
- KeyEvent event) {
- if (getMetaState(content, META_ALT_ON) != 1) {
- return false;
- }
-
- if (!(view instanceof TextView)) {
- return false;
- }
-
- Layout layout = ((TextView) view).getLayout();
-
- if (layout == null) {
- return false;
- }
-
- int l = layout.getLineForOffset(Selection.getSelectionStart(content));
- int start = layout.getLineStart(l);
- int end = layout.getLineEnd(l);
-
- if (end == start) {
- return false;
- }
-
- content.delete(start, end);
- return true;
- }
-
- static int makeTextContentType(Capitalize caps, boolean autoText) {
- int contentType = InputType.TYPE_CLASS_TEXT;
- switch (caps) {
- case CHARACTERS:
- contentType |= InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
- break;
- case WORDS:
- contentType |= InputType.TYPE_TEXT_FLAG_CAP_WORDS;
- break;
- case SENTENCES:
- contentType |= InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
- break;
- }
- if (autoText) {
- contentType |= InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
- }
- return contentType;
- }
-
- public boolean onKeyDown(View view, Editable content,
- int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_DEL) {
- backspace(view, content, keyCode, event);
- return true;
- }
-
- return super.onKeyDown(view, content, keyCode, event);
- }
-
- /**
- * Base implementation handles ACTION_MULTIPLE KEYCODE_UNKNOWN by inserting
- * the event's text into the content.
- */
- public boolean onKeyOther(View view, Editable content, KeyEvent event) {
- if (event.getAction() != KeyEvent.ACTION_MULTIPLE
- || event.getKeyCode() != KeyEvent.KEYCODE_UNKNOWN) {
- // Not something we are interested in.
- return false;
- }
-
- int selStart, selEnd;
-
- {
- int a = Selection.getSelectionStart(content);
- int b = Selection.getSelectionEnd(content);
-
- selStart = Math.min(a, b);
- selEnd = Math.max(a, b);
- }
-
- CharSequence text = event.getCharacters();
- if (text == null) {
- return false;
- }
-
- content.replace(selStart, selEnd, text);
- return true;
- }
-}
-
diff --git a/core/java/android/text/method/CharacterPickerDialog.java b/core/java/android/text/method/CharacterPickerDialog.java
deleted file mode 100644
index 3c406751..0000000
--- a/core/java/android/text/method/CharacterPickerDialog.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.text.method;
-
-import com.android.internal.R;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.os.Bundle;
-import android.text.*;
-import android.view.LayoutInflater;
-import android.view.View.OnClickListener;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.Button;
-import android.widget.GridView;
-import android.widget.TextView;
-
-/**
- * Dialog for choosing accented characters related to a base character.
- */
-public class CharacterPickerDialog extends Dialog
- implements OnItemClickListener, OnClickListener {
- private View mView;
- private Editable mText;
- private String mOptions;
- private boolean mInsert;
- private LayoutInflater mInflater;
-
- /**
- * Creates a new CharacterPickerDialog that presents the specified
- * <code>options</code> for insertion or replacement (depending on
- * the sense of <code>insert</code>) into <code>text</code>.
- */
- public CharacterPickerDialog(Context context, View view,
- Editable text, String options,
- boolean insert) {
- super(context);
-
- mView = view;
- mText = text;
- mOptions = options;
- mInsert = insert;
- mInflater = LayoutInflater.from(context);
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- WindowManager.LayoutParams params = getWindow().getAttributes();
- params.token = mView.getApplicationWindowToken();
- params.type = params.TYPE_APPLICATION_ATTACHED_DIALOG;
-
- setTitle(R.string.select_character);
- setContentView(R.layout.character_picker);
-
- GridView grid = (GridView) findViewById(R.id.characterPicker);
- grid.setAdapter(new OptionsAdapter(getContext()));
- grid.setOnItemClickListener(this);
-
- findViewById(R.id.cancel).setOnClickListener(this);
- }
-
- /**
- * Handles clicks on the character buttons.
- */
- public void onItemClick(AdapterView parent, View view, int position, long id) {
- int selEnd = Selection.getSelectionEnd(mText);
- String result = String.valueOf(mOptions.charAt(position));
-
- if (mInsert || selEnd == 0) {
- mText.insert(selEnd, result);
- } else {
- mText.replace(selEnd - 1, selEnd, result);
- }
-
- dismiss();
- }
-
- /**
- * Handles clicks on the Cancel button.
- */
- public void onClick(View v) {
- dismiss();
- }
-
- private class OptionsAdapter extends BaseAdapter {
- private Context mContext;
-
- public OptionsAdapter(Context context) {
- super();
- mContext = context;
- }
-
- public View getView(int position, View convertView, ViewGroup parent) {
- Button b = (Button)
- mInflater.inflate(R.layout.character_picker_button, null);
- b.setText(String.valueOf(mOptions.charAt(position)));
- return b;
- }
-
- public final int getCount() {
- return mOptions.length();
- }
-
- public final Object getItem(int position) {
- return String.valueOf(mOptions.charAt(position));
- }
-
- public final long getItemId(int position) {
- return position;
- }
- }
-}
diff --git a/core/java/android/text/method/DateKeyListener.java b/core/java/android/text/method/DateKeyListener.java
deleted file mode 100644
index 7c11434..0000000
--- a/core/java/android/text/method/DateKeyListener.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.view.KeyEvent;
-import android.text.InputType;
-
-/**
- * For entering dates in a text field.
- */
-public class DateKeyListener extends NumberKeyListener
-{
- public int getInputType() {
- return InputType.TYPE_CLASS_DATETIME
- | InputType.TYPE_DATETIME_VARIATION_DATE;
- }
-
- @Override
- protected char[] getAcceptedChars()
- {
- return CHARACTERS;
- }
-
- public static DateKeyListener getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new DateKeyListener();
- return sInstance;
- }
-
- /**
- * The characters that are used.
- *
- * @see KeyEvent#getMatch
- * @see #getAcceptedChars
- */
- public static final char[] CHARACTERS = new char[] {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '/', '-', '.'
- };
-
- private static DateKeyListener sInstance;
-}
diff --git a/core/java/android/text/method/DateTimeKeyListener.java b/core/java/android/text/method/DateTimeKeyListener.java
deleted file mode 100644
index f8ebc40..0000000
--- a/core/java/android/text/method/DateTimeKeyListener.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.text.InputType;
-import android.view.KeyEvent;
-
-/**
- * For entering dates and times in the same text field.
- */
-public class DateTimeKeyListener extends NumberKeyListener
-{
- public int getInputType() {
- return InputType.TYPE_CLASS_DATETIME
- | InputType.TYPE_DATETIME_VARIATION_NORMAL;
- }
-
- @Override
- protected char[] getAcceptedChars()
- {
- return CHARACTERS;
- }
-
- public static DateTimeKeyListener getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new DateTimeKeyListener();
- return sInstance;
- }
-
- /**
- * The characters that are used.
- *
- * @see KeyEvent#getMatch
- * @see #getAcceptedChars
- */
- public static final char[] CHARACTERS = new char[] {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'm',
- 'p', ':', '/', '-', ' '
- };
-
- private static DateTimeKeyListener sInstance;
-}
diff --git a/core/java/android/text/method/DialerKeyListener.java b/core/java/android/text/method/DialerKeyListener.java
deleted file mode 100644
index b121e60..0000000
--- a/core/java/android/text/method/DialerKeyListener.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.view.KeyEvent;
-import android.view.KeyCharacterMap.KeyData;
-import android.text.InputType;
-import android.text.Spannable;
-
-/**
- * For dialing-only text entry
- */
-public class DialerKeyListener extends NumberKeyListener
-{
- @Override
- protected char[] getAcceptedChars()
- {
- return CHARACTERS;
- }
-
- public static DialerKeyListener getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new DialerKeyListener();
- return sInstance;
- }
-
- public int getInputType() {
- return InputType.TYPE_CLASS_PHONE;
- }
-
- /**
- * Overrides the superclass's lookup method to prefer the number field
- * from the KeyEvent.
- */
- protected int lookup(KeyEvent event, Spannable content) {
- int meta = getMetaState(content);
- int number = event.getNumber();
-
- /*
- * Prefer number if no meta key is active, or if it produces something
- * valid and the meta lookup does not.
- */
- if ((meta & (KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON)) == 0) {
- if (number != 0) {
- return number;
- }
- }
-
- int match = super.lookup(event, content);
-
- if (match != 0) {
- return match;
- } else {
- /*
- * If a meta key is active but the lookup with the meta key
- * did not produce anything, try some other meta keys, because
- * the user might have pressed SHIFT when they meant ALT,
- * or vice versa.
- */
-
- if (meta != 0) {
- KeyData kd = new KeyData();
- char[] accepted = getAcceptedChars();
-
- if (event.getKeyData(kd)) {
- for (int i = 1; i < kd.meta.length; i++) {
- if (ok(accepted, kd.meta[i])) {
- return kd.meta[i];
- }
- }
- }
- }
-
- /*
- * Otherwise, use the number associated with the key, since
- * whatever they wanted to do with the meta key does not
- * seem to be valid here.
- */
-
- return number;
- }
- }
-
-
- /**
- * The characters that are used.
- *
- * @see KeyEvent#getMatch
- * @see #getAcceptedChars
- */
- public static final char[] CHARACTERS = new char[] {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '*',
- '+', '-', '(', ')', ',', '/', 'N', '.', ' '
- };
-
- private static DialerKeyListener sInstance;
-}
diff --git a/core/java/android/text/method/DigitsKeyListener.java b/core/java/android/text/method/DigitsKeyListener.java
deleted file mode 100644
index f0f072c..0000000
--- a/core/java/android/text/method/DigitsKeyListener.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.text.InputType;
-import android.text.Spanned;
-import android.text.SpannableStringBuilder;
-import android.view.KeyEvent;
-
-
-/**
- * For digits-only text entry
- */
-public class DigitsKeyListener extends NumberKeyListener
-{
- private char[] mAccepted;
- private boolean mSign;
- private boolean mDecimal;
-
- private static final int SIGN = 1;
- private static final int DECIMAL = 2;
-
- @Override
- protected char[] getAcceptedChars() {
- return mAccepted;
- }
-
- /**
- * The characters that are used.
- *
- * @see KeyEvent#getMatch
- * @see #getAcceptedChars
- */
- private static final char[][] CHARACTERS = new char[][] {
- new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' },
- new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' },
- new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.' },
- new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '.' },
- };
-
- /**
- * Allocates a DigitsKeyListener that accepts the digits 0 through 9.
- */
- public DigitsKeyListener() {
- this(false, false);
- }
-
- /**
- * Allocates a DigitsKeyListener that accepts the digits 0 through 9,
- * plus the minus sign (only at the beginning) and/or decimal point
- * (only one per field) if specified.
- */
- public DigitsKeyListener(boolean sign, boolean decimal) {
- mSign = sign;
- mDecimal = decimal;
-
- int kind = (sign ? SIGN : 0) | (decimal ? DECIMAL : 0);
- mAccepted = CHARACTERS[kind];
- }
-
- /**
- * Returns a DigitsKeyListener that accepts the digits 0 through 9.
- */
- public static DigitsKeyListener getInstance() {
- return getInstance(false, false);
- }
-
- /**
- * Returns a DigitsKeyListener that accepts the digits 0 through 9,
- * plus the minus sign (only at the beginning) and/or decimal point
- * (only one per field) if specified.
- */
- public static DigitsKeyListener getInstance(boolean sign, boolean decimal) {
- int kind = (sign ? SIGN : 0) | (decimal ? DECIMAL : 0);
-
- if (sInstance[kind] != null)
- return sInstance[kind];
-
- sInstance[kind] = new DigitsKeyListener(sign, decimal);
- return sInstance[kind];
- }
-
- /**
- * Returns a DigitsKeyListener that accepts only the characters
- * that appear in the specified String. Note that not all characters
- * may be available on every keyboard.
- */
- public static DigitsKeyListener getInstance(String accepted) {
- // TODO: do we need a cache of these to avoid allocating?
-
- DigitsKeyListener dim = new DigitsKeyListener();
-
- dim.mAccepted = new char[accepted.length()];
- accepted.getChars(0, accepted.length(), dim.mAccepted, 0);
-
- return dim;
- }
-
- public int getInputType() {
- int contentType = InputType.TYPE_CLASS_NUMBER;
- if (mSign) {
- contentType |= InputType.TYPE_NUMBER_FLAG_SIGNED;
- }
- if (mDecimal) {
- contentType |= InputType.TYPE_NUMBER_FLAG_DECIMAL;
- }
- return contentType;
- }
-
- @Override
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
- CharSequence out = super.filter(source, start, end, dest, dstart, dend);
-
- if (mSign == false && mDecimal == false) {
- return out;
- }
-
- if (out != null) {
- source = out;
- start = 0;
- end = out.length();
- }
-
- int sign = -1;
- int decimal = -1;
- int dlen = dest.length();
-
- /*
- * Find out if the existing text has '-' or '.' characters.
- */
-
- for (int i = 0; i < dstart; i++) {
- char c = dest.charAt(i);
-
- if (c == '-') {
- sign = i;
- } else if (c == '.') {
- decimal = i;
- }
- }
- for (int i = dend; i < dlen; i++) {
- char c = dest.charAt(i);
-
- if (c == '-') {
- return ""; // Nothing can be inserted in front of a '-'.
- } else if (c == '.') {
- decimal = i;
- }
- }
-
- /*
- * If it does, we must strip them out from the source.
- * In addition, '-' must be the very first character,
- * and nothing can be inserted before an existing '-'.
- * Go in reverse order so the offsets are stable.
- */
-
- SpannableStringBuilder stripped = null;
-
- for (int i = end - 1; i >= start; i--) {
- char c = source.charAt(i);
- boolean strip = false;
-
- if (c == '-') {
- if (i != start || dstart != 0) {
- strip = true;
- } else if (sign >= 0) {
- strip = true;
- } else {
- sign = i;
- }
- } else if (c == '.') {
- if (decimal >= 0) {
- strip = true;
- } else {
- decimal = i;
- }
- }
-
- if (strip) {
- if (end == start + 1) {
- return ""; // Only one character, and it was stripped.
- }
-
- if (stripped == null) {
- stripped = new SpannableStringBuilder(source, start, end);
- }
-
- stripped.delete(i - start, i + 1 - start);
- }
- }
-
- if (stripped != null) {
- return stripped;
- } else if (out != null) {
- return out;
- } else {
- return null;
- }
- }
-
- private static DigitsKeyListener[] sInstance = new DigitsKeyListener[4];
-}
diff --git a/core/java/android/text/method/HideReturnsTransformationMethod.java b/core/java/android/text/method/HideReturnsTransformationMethod.java
deleted file mode 100644
index ce18692..0000000
--- a/core/java/android/text/method/HideReturnsTransformationMethod.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.graphics.Rect;
-import android.text.GetChars;
-import android.text.Spanned;
-import android.text.SpannedString;
-import android.text.TextUtils;
-import android.view.View;
-
-/**
- * This transformation method causes any carriage return characters (\r)
- * to be hidden by displaying them as zero-width non-breaking space
- * characters (\uFEFF).
- */
-public class HideReturnsTransformationMethod
-extends ReplacementTransformationMethod {
- private static char[] ORIGINAL = new char[] { '\r' };
- private static char[] REPLACEMENT = new char[] { '\uFEFF' };
-
- /**
- * The character to be replaced is \r.
- */
- protected char[] getOriginal() {
- return ORIGINAL;
- }
-
- /**
- * The character that \r is replaced with is \uFEFF.
- */
- protected char[] getReplacement() {
- return REPLACEMENT;
- }
-
- public static HideReturnsTransformationMethod getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new HideReturnsTransformationMethod();
- return sInstance;
- }
-
- private static HideReturnsTransformationMethod sInstance;
-}
diff --git a/core/java/android/text/method/KeyListener.java b/core/java/android/text/method/KeyListener.java
deleted file mode 100644
index 8594852..0000000
--- a/core/java/android/text/method/KeyListener.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.text.Editable;
-import android.view.KeyEvent;
-import android.view.View;
-
-/**
- * Interface for converting text key events into edit operations on an
- * Editable class. Note that for must cases this interface has been
- * superceded by general soft input methods as defined by
- * {@link android.view.inputmethod.InputMethod}; it should only be used
- * for cases where an application has its own on-screen keypad and also wants
- * to process hard keyboard events to match it.
- */
-public interface KeyListener {
- /**
- * Return the type of text that this key listener is manipulating,
- * as per {@link android.text.InputType}. This is used to
- * determine the mode of the soft keyboard that is shown for the editor.
- *
- * <p>If you return
- * {@link android.text.InputType#TYPE_NULL}
- * then <em>no</em> soft keyboard will provided. In other words, you
- * must be providing your own key pad for on-screen input and the key
- * listener will be used to handle input from a hard keyboard.
- *
- * <p>If you
- * return any other value, a soft input method will be created when the
- * user puts focus in the editor, which will provide a keypad and also
- * consume hard key events. This means that the key listener will generally
- * not be used, instead the soft input method will take care of managing
- * key input as per the content type returned here.
- */
- public int getInputType();
-
- /**
- * If the key listener wants to handle this key, return true,
- * otherwise return false and the caller (i.e. the widget host)
- * will handle the key.
- */
- public boolean onKeyDown(View view, Editable text,
- int keyCode, KeyEvent event);
-
- /**
- * If the key listener wants to handle this key release, return true,
- * otherwise return false and the caller (i.e. the widget host)
- * will handle the key.
- */
- public boolean onKeyUp(View view, Editable text,
- int keyCode, KeyEvent event);
-
- /**
- * If the key listener wants to other kinds of key events, return true,
- * otherwise return false and the caller (i.e. the widget host)
- * will handle the key.
- */
- public boolean onKeyOther(View view, Editable text, KeyEvent event);
-
- /**
- * Remove the given shift states from the edited text.
- */
- public void clearMetaKeyState(View view, Editable content, int states);
-}
diff --git a/core/java/android/text/method/LinkMovementMethod.java b/core/java/android/text/method/LinkMovementMethod.java
deleted file mode 100644
index 22e9cc6..0000000
--- a/core/java/android/text/method/LinkMovementMethod.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.text.*;
-import android.text.style.*;
-import android.view.View;
-import android.widget.TextView;
-
-public class
-LinkMovementMethod
-extends ScrollingMovementMethod
-{
- private static final int CLICK = 1;
- private static final int UP = 2;
- private static final int DOWN = 3;
-
- @Override
- public boolean onKeyDown(TextView widget, Spannable buffer,
- int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_ENTER:
- if (event.getRepeatCount() == 0) {
- if (action(CLICK, widget, buffer)) {
- return true;
- }
- }
- }
-
- return super.onKeyDown(widget, buffer, keyCode, event);
- }
-
- @Override
- protected boolean up(TextView widget, Spannable buffer) {
- if (action(UP, widget, buffer)) {
- return true;
- }
-
- return super.up(widget, buffer);
- }
-
- @Override
- protected boolean down(TextView widget, Spannable buffer) {
- if (action(DOWN, widget, buffer)) {
- return true;
- }
-
- return super.down(widget, buffer);
- }
-
- @Override
- protected boolean left(TextView widget, Spannable buffer) {
- if (action(UP, widget, buffer)) {
- return true;
- }
-
- return super.left(widget, buffer);
- }
-
- @Override
- protected boolean right(TextView widget, Spannable buffer) {
- if (action(DOWN, widget, buffer)) {
- return true;
- }
-
- return super.right(widget, buffer);
- }
-
- private boolean action(int what, TextView widget, Spannable buffer) {
- boolean handled = false;
-
- Layout layout = widget.getLayout();
-
- int padding = widget.getTotalPaddingTop() +
- widget.getTotalPaddingBottom();
- int areatop = widget.getScrollY();
- int areabot = areatop + widget.getHeight() - padding;
-
- int linetop = layout.getLineForVertical(areatop);
- int linebot = layout.getLineForVertical(areabot);
-
- int first = layout.getLineStart(linetop);
- int last = layout.getLineEnd(linebot);
-
- ClickableSpan[] candidates = buffer.getSpans(first, last, ClickableSpan.class);
-
- int a = Selection.getSelectionStart(buffer);
- int b = Selection.getSelectionEnd(buffer);
-
- int selStart = Math.min(a, b);
- int selEnd = Math.max(a, b);
-
- if (selStart < 0) {
- if (buffer.getSpanStart(FROM_BELOW) >= 0) {
- selStart = selEnd = buffer.length();
- }
- }
-
- if (selStart > last)
- selStart = selEnd = Integer.MAX_VALUE;
- if (selEnd < first)
- selStart = selEnd = -1;
-
- switch (what) {
- case CLICK:
- if (selStart == selEnd) {
- return false;
- }
-
- ClickableSpan[] link = buffer.getSpans(selStart, selEnd, ClickableSpan.class);
-
- if (link.length != 1)
- return false;
-
- link[0].onClick(widget);
- break;
-
- case UP:
- int beststart, bestend;
-
- beststart = -1;
- bestend = -1;
-
- for (int i = 0; i < candidates.length; i++) {
- int end = buffer.getSpanEnd(candidates[i]);
-
- if (end < selEnd || selStart == selEnd) {
- if (end > bestend) {
- beststart = buffer.getSpanStart(candidates[i]);
- bestend = end;
- }
- }
- }
-
- if (beststart >= 0) {
- Selection.setSelection(buffer, bestend, beststart);
- return true;
- }
-
- break;
-
- case DOWN:
- beststart = Integer.MAX_VALUE;
- bestend = Integer.MAX_VALUE;
-
- for (int i = 0; i < candidates.length; i++) {
- int start = buffer.getSpanStart(candidates[i]);
-
- if (start > selStart || selStart == selEnd) {
- if (start < beststart) {
- beststart = start;
- bestend = buffer.getSpanEnd(candidates[i]);
- }
- }
- }
-
- if (bestend < Integer.MAX_VALUE) {
- Selection.setSelection(buffer, beststart, bestend);
- return true;
- }
-
- break;
- }
-
- return false;
- }
-
- public boolean onKeyUp(TextView widget, Spannable buffer,
- int keyCode, KeyEvent event) {
- return false;
- }
-
- @Override
- public boolean onTouchEvent(TextView widget, Spannable buffer,
- MotionEvent event) {
- int action = event.getAction();
-
- if (action == MotionEvent.ACTION_UP ||
- action == MotionEvent.ACTION_DOWN) {
- int x = (int) event.getX();
- int y = (int) event.getY();
-
- x -= widget.getTotalPaddingLeft();
- y -= widget.getTotalPaddingTop();
-
- x += widget.getScrollX();
- y += widget.getScrollY();
-
- Layout layout = widget.getLayout();
- int line = layout.getLineForVertical(y);
- int off = layout.getOffsetForHorizontal(line, x);
-
- ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
-
- if (link.length != 0) {
- if (action == MotionEvent.ACTION_UP) {
- link[0].onClick(widget);
- } else if (action == MotionEvent.ACTION_DOWN) {
- Selection.setSelection(buffer,
- buffer.getSpanStart(link[0]),
- buffer.getSpanEnd(link[0]));
- }
-
- return true;
- } else {
- Selection.removeSelection(buffer);
- }
- }
-
- return super.onTouchEvent(widget, buffer, event);
- }
-
- public void initialize(TextView widget, Spannable text) {
- Selection.removeSelection(text);
- text.removeSpan(FROM_BELOW);
- }
-
- public void onTakeFocus(TextView view, Spannable text, int dir) {
- Selection.removeSelection(text);
-
- if ((dir & View.FOCUS_BACKWARD) != 0) {
- text.setSpan(FROM_BELOW, 0, 0, Spannable.SPAN_POINT_POINT);
- } else {
- text.removeSpan(FROM_BELOW);
- }
- }
-
- public static MovementMethod getInstance() {
- if (sInstance == null)
- sInstance = new LinkMovementMethod();
-
- return sInstance;
- }
-
- private static LinkMovementMethod sInstance;
- private static Object FROM_BELOW = new NoCopySpan.Concrete();
-}
diff --git a/core/java/android/text/method/MetaKeyKeyListener.java b/core/java/android/text/method/MetaKeyKeyListener.java
deleted file mode 100644
index 39ad976..0000000
--- a/core/java/android/text/method/MetaKeyKeyListener.java
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.view.KeyEvent;
-import android.view.View;
-import android.text.*;
-
-/**
- * This base class encapsulates the behavior for handling the meta keys
- * (shift and alt) and the pseudo-meta state of selecting text.
- * Key listeners that care about meta state should
- * inherit from it; you should not instantiate this class directly in a client.
- */
-
-public abstract class MetaKeyKeyListener {
- public static final int META_SHIFT_ON = KeyEvent.META_SHIFT_ON;
- public static final int META_ALT_ON = KeyEvent.META_ALT_ON;
- public static final int META_SYM_ON = KeyEvent.META_SYM_ON;
-
- private static final int LOCKED_SHIFT = 8;
-
- public static final int META_CAP_LOCKED = KeyEvent.META_SHIFT_ON << LOCKED_SHIFT;
- public static final int META_ALT_LOCKED = KeyEvent.META_ALT_ON << LOCKED_SHIFT;
- public static final int META_SYM_LOCKED = KeyEvent.META_SYM_ON << LOCKED_SHIFT;
-
- /**
- * @hide pending API review
- */
- public static final int META_SELECTING = 1 << 16;
-
- private static final int USED_SHIFT = 24;
-
- private static final long META_CAP_USED = ((long)KeyEvent.META_SHIFT_ON) << USED_SHIFT;
- private static final long META_ALT_USED = ((long)KeyEvent.META_ALT_ON) << USED_SHIFT;
- private static final long META_SYM_USED = ((long)KeyEvent.META_SYM_ON) << USED_SHIFT;
-
- private static final int PRESSED_SHIFT = 32;
-
- private static final long META_CAP_PRESSED = ((long)KeyEvent.META_SHIFT_ON) << PRESSED_SHIFT;
- private static final long META_ALT_PRESSED = ((long)KeyEvent.META_ALT_ON) << PRESSED_SHIFT;
- private static final long META_SYM_PRESSED = ((long)KeyEvent.META_SYM_ON) << PRESSED_SHIFT;
-
- private static final int RELEASED_SHIFT = 40;
-
- private static final long META_CAP_RELEASED = ((long)KeyEvent.META_SHIFT_ON) << RELEASED_SHIFT;
- private static final long META_ALT_RELEASED = ((long)KeyEvent.META_ALT_ON) << RELEASED_SHIFT;
- private static final long META_SYM_RELEASED = ((long)KeyEvent.META_SYM_ON) << RELEASED_SHIFT;
-
- private static final long META_SHIFT_MASK = META_SHIFT_ON
- | META_CAP_LOCKED | META_CAP_USED
- | META_CAP_PRESSED | META_CAP_RELEASED;
- private static final long META_ALT_MASK = META_ALT_ON
- | META_ALT_LOCKED | META_ALT_USED
- | META_ALT_PRESSED | META_ALT_RELEASED;
- private static final long META_SYM_MASK = META_SYM_ON
- | META_SYM_LOCKED | META_SYM_USED
- | META_SYM_PRESSED | META_SYM_RELEASED;
-
- private static final Object CAP = new NoCopySpan.Concrete();
- private static final Object ALT = new NoCopySpan.Concrete();
- private static final Object SYM = new NoCopySpan.Concrete();
- private static final Object SELECTING = new NoCopySpan.Concrete();
-
- /**
- * Resets all meta state to inactive.
- */
- public static void resetMetaState(Spannable text) {
- text.removeSpan(CAP);
- text.removeSpan(ALT);
- text.removeSpan(SYM);
- text.removeSpan(SELECTING);
- }
-
- /**
- * Gets the state of the meta keys.
- *
- * @param text the buffer in which the meta key would have been pressed.
- *
- * @return an integer in which each bit set to one represents a pressed
- * or locked meta key.
- */
- public static final int getMetaState(CharSequence text) {
- return getActive(text, CAP, META_SHIFT_ON, META_CAP_LOCKED) |
- getActive(text, ALT, META_ALT_ON, META_ALT_LOCKED) |
- getActive(text, SYM, META_SYM_ON, META_SYM_LOCKED) |
- getActive(text, SELECTING, META_SELECTING, META_SELECTING);
- }
-
- /**
- * Gets the state of a particular meta key.
- *
- * @param meta META_SHIFT_ON, META_ALT_ON, META_SYM_ON, or META_SELECTING
- * @param text the buffer in which the meta key would have been pressed.
- *
- * @return 0 if inactive, 1 if active, 2 if locked.
- */
- public static final int getMetaState(CharSequence text, int meta) {
- switch (meta) {
- case META_SHIFT_ON:
- return getActive(text, CAP, 1, 2);
-
- case META_ALT_ON:
- return getActive(text, ALT, 1, 2);
-
- case META_SYM_ON:
- return getActive(text, SYM, 1, 2);
-
- case META_SELECTING:
- return getActive(text, SELECTING, 1, 2);
-
- default:
- return 0;
- }
- }
-
- private static int getActive(CharSequence text, Object meta,
- int on, int lock) {
- if (!(text instanceof Spanned)) {
- return 0;
- }
-
- Spanned sp = (Spanned) text;
- int flag = sp.getSpanFlags(meta);
-
- if (flag == LOCKED) {
- return lock;
- } else if (flag != 0) {
- return on;
- } else {
- return 0;
- }
- }
-
- /**
- * Call this method after you handle a keypress so that the meta
- * state will be reset to unshifted (if it is not still down)
- * or primed to be reset to unshifted (once it is released).
- */
- public static void adjustMetaAfterKeypress(Spannable content) {
- adjust(content, CAP);
- adjust(content, ALT);
- adjust(content, SYM);
- }
-
- /**
- * Returns true if this object is one that this class would use to
- * keep track of meta state in the specified text.
- */
- public static boolean isMetaTracker(CharSequence text, Object what) {
- return what == CAP || what == ALT || what == SYM ||
- what == SELECTING;
- }
-
- private static void adjust(Spannable content, Object what) {
- int current = content.getSpanFlags(what);
-
- if (current == PRESSED)
- content.setSpan(what, 0, 0, USED);
- else if (current == RELEASED)
- content.removeSpan(what);
- }
-
- /**
- * Call this if you are a method that ignores the locked meta state
- * (arrow keys, for example) and you handle a key.
- */
- protected static void resetLockedMeta(Spannable content) {
- resetLock(content, CAP);
- resetLock(content, ALT);
- resetLock(content, SYM);
- resetLock(content, SELECTING);
- }
-
- private static void resetLock(Spannable content, Object what) {
- int current = content.getSpanFlags(what);
-
- if (current == LOCKED)
- content.removeSpan(what);
- }
-
- /**
- * Handles presses of the meta keys.
- */
- public boolean onKeyDown(View view, Editable content,
- int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
- press(content, CAP);
- return true;
- }
-
- if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT
- || keyCode == KeyEvent.KEYCODE_NUM) {
- press(content, ALT);
- return true;
- }
-
- if (keyCode == KeyEvent.KEYCODE_SYM) {
- press(content, SYM);
- return true;
- }
-
- return false; // no super to call through to
- }
-
- private void press(Editable content, Object what) {
- int state = content.getSpanFlags(what);
-
- if (state == PRESSED)
- ; // repeat before use
- else if (state == RELEASED)
- content.setSpan(what, 0, 0, LOCKED);
- else if (state == USED)
- ; // repeat after use
- else if (state == LOCKED)
- content.removeSpan(what);
- else
- content.setSpan(what, 0, 0, PRESSED);
- }
-
- /**
- * Start selecting text.
- * @hide pending API review
- */
- public static void startSelecting(View view, Spannable content) {
- content.setSpan(SELECTING, 0, 0, PRESSED);
- }
-
- /**
- * Stop selecting text. This does not actually collapse the selection;
- * call {@link android.text.Selection#setSelection} too.
- * @hide pending API review
- */
- public static void stopSelecting(View view, Spannable content) {
- content.removeSpan(SELECTING);
- }
-
- /**
- * Handles release of the meta keys.
- */
- public boolean onKeyUp(View view, Editable content, int keyCode,
- KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
- release(content, CAP);
- return true;
- }
-
- if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT
- || keyCode == KeyEvent.KEYCODE_NUM) {
- release(content, ALT);
- return true;
- }
-
- if (keyCode == KeyEvent.KEYCODE_SYM) {
- release(content, SYM);
- return true;
- }
-
- return false; // no super to call through to
- }
-
- private void release(Editable content, Object what) {
- int current = content.getSpanFlags(what);
-
- if (current == USED)
- content.removeSpan(what);
- else if (current == PRESSED)
- content.setSpan(what, 0, 0, RELEASED);
- }
-
- public void clearMetaKeyState(View view, Editable content, int states) {
- clearMetaKeyState(content, states);
- }
-
- public static void clearMetaKeyState(Editable content, int states) {
- if ((states&META_SHIFT_ON) != 0) content.removeSpan(CAP);
- if ((states&META_ALT_ON) != 0) content.removeSpan(ALT);
- if ((states&META_SYM_ON) != 0) content.removeSpan(SYM);
- if ((states&META_SELECTING) != 0) content.removeSpan(SELECTING);
- }
-
- /**
- * Call this if you are a method that ignores the locked meta state
- * (arrow keys, for example) and you handle a key.
- */
- public static long resetLockedMeta(long state) {
- state = resetLock(state, META_SHIFT_ON, META_SHIFT_MASK);
- state = resetLock(state, META_ALT_ON, META_ALT_MASK);
- state = resetLock(state, META_SYM_ON, META_SYM_MASK);
- return state;
- }
-
- private static long resetLock(long state, int what, long mask) {
- if ((state&(((long)what)<<LOCKED_SHIFT)) != 0) {
- state &= ~mask;
- }
- return state;
- }
-
- // ---------------------------------------------------------------------
- // Version of API that operates on a state bit mask
- // ---------------------------------------------------------------------
-
- /**
- * Gets the state of the meta keys.
- *
- * @param state the current meta state bits.
- *
- * @return an integer in which each bit set to one represents a pressed
- * or locked meta key.
- */
- public static final int getMetaState(long state) {
- return getActive(state, META_SHIFT_ON, META_SHIFT_ON, META_CAP_LOCKED) |
- getActive(state, META_ALT_ON, META_ALT_ON, META_ALT_LOCKED) |
- getActive(state, META_SYM_ON, META_SYM_ON, META_SYM_LOCKED);
- }
-
- /**
- * Gets the state of a particular meta key.
- *
- * @param state the current state bits.
- * @param meta META_SHIFT_ON, META_ALT_ON, or META_SYM_ON
- *
- * @return 0 if inactive, 1 if active, 2 if locked.
- */
- public static final int getMetaState(long state, int meta) {
- switch (meta) {
- case META_SHIFT_ON:
- return getActive(state, meta, 1, 2);
-
- case META_ALT_ON:
- return getActive(state, meta, 1, 2);
-
- case META_SYM_ON:
- return getActive(state, meta, 1, 2);
-
- default:
- return 0;
- }
- }
-
- private static int getActive(long state, int meta, int on, int lock) {
- if ((state&(meta<<LOCKED_SHIFT)) != 0) {
- return lock;
- } else if ((state&meta) != 0) {
- return on;
- } else {
- return 0;
- }
- }
-
- /**
- * Call this method after you handle a keypress so that the meta
- * state will be reset to unshifted (if it is not still down)
- * or primed to be reset to unshifted (once it is released). Takes
- * the current state, returns the new state.
- */
- public static long adjustMetaAfterKeypress(long state) {
- state = adjust(state, META_SHIFT_ON, META_SHIFT_MASK);
- state = adjust(state, META_ALT_ON, META_ALT_MASK);
- state = adjust(state, META_SYM_ON, META_SYM_MASK);
- return state;
- }
-
- private static long adjust(long state, int what, long mask) {
- if ((state&(((long)what)<<PRESSED_SHIFT)) != 0)
- return (state&~mask) | what | ((long)what)<<USED_SHIFT;
- else if ((state&(((long)what)<<RELEASED_SHIFT)) != 0)
- return state & ~mask;
- return state;
- }
-
- /**
- * Handles presses of the meta keys.
- */
- public static long handleKeyDown(long state, int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
- return press(state, META_SHIFT_ON, META_SHIFT_MASK);
- }
-
- if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT
- || keyCode == KeyEvent.KEYCODE_NUM) {
- return press(state, META_ALT_ON, META_ALT_MASK);
- }
-
- if (keyCode == KeyEvent.KEYCODE_SYM) {
- return press(state, META_SYM_ON, META_SYM_MASK);
- }
-
- return state;
- }
-
- private static long press(long state, int what, long mask) {
- if ((state&(((long)what)<<PRESSED_SHIFT)) != 0)
- ; // repeat before use
- else if ((state&(((long)what)<<RELEASED_SHIFT)) != 0)
- state = (state&~mask) | what | (((long)what) << LOCKED_SHIFT);
- else if ((state&(((long)what)<<USED_SHIFT)) != 0)
- ; // repeat after use
- else if ((state&(((long)what)<<LOCKED_SHIFT)) != 0)
- state = state&~mask;
- else
- state = state | what | (((long)what)<<PRESSED_SHIFT);
- return state;
- }
-
- /**
- * Handles release of the meta keys.
- */
- public static long handleKeyUp(long state, int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
- return release(state, META_SHIFT_ON, META_SHIFT_MASK);
- }
-
- if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT
- || keyCode == KeyEvent.KEYCODE_NUM) {
- return release(state, META_ALT_ON, META_ALT_MASK);
- }
-
- if (keyCode == KeyEvent.KEYCODE_SYM) {
- return release(state, META_SYM_ON, META_SYM_MASK);
- }
-
- return state;
- }
-
- private static long release(long state, int what, long mask) {
- if ((state&(((long)what)<<USED_SHIFT)) != 0)
- state = state&~mask;
- else if ((state&(((long)what)<<PRESSED_SHIFT)) != 0)
- state = state | what | (((long)what)<<RELEASED_SHIFT);
- return state;
- }
-
- public long clearMetaKeyState(long state, int which) {
- if ((which&META_SHIFT_ON) != 0)
- state = resetLock(state, META_SHIFT_ON, META_SHIFT_MASK);
- if ((which&META_ALT_ON) != 0)
- state = resetLock(state, META_ALT_ON, META_ALT_MASK);
- if ((which&META_SYM_ON) != 0)
- state = resetLock(state, META_SYM_ON, META_SYM_MASK);
- return state;
- }
-
- /**
- * The meta key has been pressed but has not yet been used.
- */
- private static final int PRESSED =
- Spannable.SPAN_MARK_MARK | (1 << Spannable.SPAN_USER_SHIFT);
-
- /**
- * The meta key has been pressed and released but has still
- * not yet been used.
- */
- private static final int RELEASED =
- Spannable.SPAN_MARK_MARK | (2 << Spannable.SPAN_USER_SHIFT);
-
- /**
- * The meta key has been pressed and used but has not yet been released.
- */
- private static final int USED =
- Spannable.SPAN_MARK_MARK | (3 << Spannable.SPAN_USER_SHIFT);
-
- /**
- * The meta key has been pressed and released without use, and then
- * pressed again; it may also have been released again.
- */
- private static final int LOCKED =
- Spannable.SPAN_MARK_MARK | (4 << Spannable.SPAN_USER_SHIFT);
-}
-
diff --git a/core/java/android/text/method/MovementMethod.java b/core/java/android/text/method/MovementMethod.java
deleted file mode 100644
index 29f67a1..0000000
--- a/core/java/android/text/method/MovementMethod.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.widget.TextView;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.text.*;
-
-public interface MovementMethod
-{
- public void initialize(TextView widget, Spannable text);
- public boolean onKeyDown(TextView widget, Spannable text, int keyCode, KeyEvent event);
- public boolean onKeyUp(TextView widget, Spannable text, int keyCode, KeyEvent event);
-
- /**
- * If the key listener wants to other kinds of key events, return true,
- * otherwise return false and the caller (i.e. the widget host)
- * will handle the key.
- */
- public boolean onKeyOther(TextView view, Spannable text, KeyEvent event);
-
- public void onTakeFocus(TextView widget, Spannable text, int direction);
- public boolean onTrackballEvent(TextView widget, Spannable text,
- MotionEvent event);
- public boolean onTouchEvent(TextView widget, Spannable text,
- MotionEvent event);
-
- /**
- * Returns true if this movement method allows arbitrary selection
- * of any text; false if it has no selection (like a movement method
- * that only scrolls) or a constrained selection (for example
- * limited to links. The "Select All" menu item is disabled
- * if arbitrary selection is not allowed.
- */
- public boolean canSelectArbitrarily();
-}
diff --git a/core/java/android/text/method/MultiTapKeyListener.java b/core/java/android/text/method/MultiTapKeyListener.java
deleted file mode 100644
index 6d94788..0000000
--- a/core/java/android/text/method/MultiTapKeyListener.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.view.KeyEvent;
-import android.view.View;
-import android.os.Handler;
-import android.os.SystemClock;
-import android.text.*;
-import android.text.method.TextKeyListener.Capitalize;
-import android.util.SparseArray;
-
-/**
- * This is the standard key listener for alphabetic input on 12-key
- * keyboards. You should generally not need to instantiate this yourself;
- * TextKeyListener will do it for you.
- */
-public class MultiTapKeyListener extends BaseKeyListener
- implements SpanWatcher {
- private static MultiTapKeyListener[] sInstance =
- new MultiTapKeyListener[Capitalize.values().length * 2];
-
- private static final SparseArray<String> sRecs = new SparseArray<String>();
-
- private Capitalize mCapitalize;
- private boolean mAutoText;
-
- static {
- sRecs.put(KeyEvent.KEYCODE_1, ".,1!@#$%^&*:/?'=()");
- sRecs.put(KeyEvent.KEYCODE_2, "abc2ABC");
- sRecs.put(KeyEvent.KEYCODE_3, "def3DEF");
- sRecs.put(KeyEvent.KEYCODE_4, "ghi4GHI");
- sRecs.put(KeyEvent.KEYCODE_5, "jkl5JKL");
- sRecs.put(KeyEvent.KEYCODE_6, "mno6MNO");
- sRecs.put(KeyEvent.KEYCODE_7, "pqrs7PQRS");
- sRecs.put(KeyEvent.KEYCODE_8, "tuv8TUV");
- sRecs.put(KeyEvent.KEYCODE_9, "wxyz9WXYZ");
- sRecs.put(KeyEvent.KEYCODE_0, "0+");
- sRecs.put(KeyEvent.KEYCODE_POUND, " ");
- };
-
- public MultiTapKeyListener(Capitalize cap,
- boolean autotext) {
- mCapitalize = cap;
- mAutoText = autotext;
- }
-
- /**
- * Returns a new or existing instance with the specified capitalization
- * and correction properties.
- */
- public static MultiTapKeyListener getInstance(boolean autotext,
- Capitalize cap) {
- int off = cap.ordinal() * 2 + (autotext ? 1 : 0);
-
- if (sInstance[off] == null) {
- sInstance[off] = new MultiTapKeyListener(cap, autotext);
- }
-
- return sInstance[off];
- }
-
- public int getInputType() {
- return makeTextContentType(mCapitalize, mAutoText);
- }
-
- public boolean onKeyDown(View view, Editable content,
- int keyCode, KeyEvent event) {
- int selStart, selEnd;
- int pref = 0;
-
- if (view != null) {
- pref = TextKeyListener.getInstance().getPrefs(view.getContext());
- }
-
- {
- int a = Selection.getSelectionStart(content);
- int b = Selection.getSelectionEnd(content);
-
- selStart = Math.min(a, b);
- selEnd = Math.max(a, b);
- }
-
- int activeStart = content.getSpanStart(TextKeyListener.ACTIVE);
- int activeEnd = content.getSpanEnd(TextKeyListener.ACTIVE);
-
- // now for the multitap cases...
-
- // Try to increment the character we were working on before
- // if we have one and it's still the same key.
-
- int rec = (content.getSpanFlags(TextKeyListener.ACTIVE)
- & Spannable.SPAN_USER) >>> Spannable.SPAN_USER_SHIFT;
-
- if (activeStart == selStart && activeEnd == selEnd &&
- selEnd - selStart == 1 &&
- rec >= 0 && rec < sRecs.size()) {
- if (keyCode == KeyEvent.KEYCODE_STAR) {
- char current = content.charAt(selStart);
-
- if (Character.isLowerCase(current)) {
- content.replace(selStart, selEnd,
- String.valueOf(current).toUpperCase());
- removeTimeouts(content);
- Timeout t = new Timeout(content);
-
- return true;
- }
- if (Character.isUpperCase(current)) {
- content.replace(selStart, selEnd,
- String.valueOf(current).toLowerCase());
- removeTimeouts(content);
- Timeout t = new Timeout(content);
-
- return true;
- }
- }
-
- if (sRecs.indexOfKey(keyCode) == rec) {
- String val = sRecs.valueAt(rec);
- char ch = content.charAt(selStart);
- int ix = val.indexOf(ch);
-
- if (ix >= 0) {
- ix = (ix + 1) % (val.length());
-
- content.replace(selStart, selEnd, val, ix, ix + 1);
- removeTimeouts(content);
- Timeout t = new Timeout(content);
-
- return true;
- }
- }
-
- // Is this key one we know about at all? If so, acknowledge
- // that the selection is our fault but the key has changed
- // or the text no longer matches, so move the selection over
- // so that it inserts instead of replaces.
-
- rec = sRecs.indexOfKey(keyCode);
-
- if (rec >= 0) {
- Selection.setSelection(content, selEnd, selEnd);
- selStart = selEnd;
- }
- } else {
- rec = sRecs.indexOfKey(keyCode);
- }
-
- if (rec >= 0) {
- // We have a valid key. Replace the selection or insertion point
- // with the first character for that key, and remember what
- // record it came from for next time.
-
- String val = sRecs.valueAt(rec);
-
- int off = 0;
- if ((pref & TextKeyListener.AUTO_CAP) != 0 &&
- TextKeyListener.shouldCap(mCapitalize, content, selStart)) {
- for (int i = 0; i < val.length(); i++) {
- if (Character.isUpperCase(val.charAt(i))) {
- off = i;
- break;
- }
- }
- }
-
- if (selStart != selEnd) {
- Selection.setSelection(content, selEnd);
- }
-
- content.setSpan(OLD_SEL_START, selStart, selStart,
- Spannable.SPAN_MARK_MARK);
-
- content.replace(selStart, selEnd, val, off, off + 1);
-
- int oldStart = content.getSpanStart(OLD_SEL_START);
- selEnd = Selection.getSelectionEnd(content);
-
- if (selEnd != oldStart) {
- Selection.setSelection(content, oldStart, selEnd);
-
- content.setSpan(TextKeyListener.LAST_TYPED,
- oldStart, selEnd,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-
- content.setSpan(TextKeyListener.ACTIVE,
- oldStart, selEnd,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE |
- (rec << Spannable.SPAN_USER_SHIFT));
-
- }
-
- removeTimeouts(content);
- Timeout t = new Timeout(content);
-
- // Set up the callback so we can remove the timeout if the
- // cursor moves.
-
- if (content.getSpanStart(this) < 0) {
- KeyListener[] methods = content.getSpans(0, content.length(),
- KeyListener.class);
- for (Object method : methods) {
- content.removeSpan(method);
- }
- content.setSpan(this, 0, content.length(),
- Spannable.SPAN_INCLUSIVE_INCLUSIVE);
- }
-
- return true;
- }
-
- return super.onKeyDown(view, content, keyCode, event);
- }
-
- public void onSpanChanged(Spannable buf,
- Object what, int s, int e, int start, int stop) {
- if (what == Selection.SELECTION_END) {
- buf.removeSpan(TextKeyListener.ACTIVE);
- removeTimeouts(buf);
- }
- }
-
- private static void removeTimeouts(Spannable buf) {
- Timeout[] timeout = buf.getSpans(0, buf.length(), Timeout.class);
-
- for (int i = 0; i < timeout.length; i++) {
- Timeout t = timeout[i];
-
- t.removeCallbacks(t);
- t.mBuffer = null;
- buf.removeSpan(t);
- }
- }
-
- private class Timeout
- extends Handler
- implements Runnable
- {
- public Timeout(Editable buffer) {
- mBuffer = buffer;
- mBuffer.setSpan(Timeout.this, 0, mBuffer.length(),
- Spannable.SPAN_INCLUSIVE_INCLUSIVE);
-
- postAtTime(this, SystemClock.uptimeMillis() + 2000);
- }
-
- public void run() {
- Spannable buf = mBuffer;
-
- if (buf != null) {
- int st = Selection.getSelectionStart(buf);
- int en = Selection.getSelectionEnd(buf);
-
- int start = buf.getSpanStart(TextKeyListener.ACTIVE);
- int end = buf.getSpanEnd(TextKeyListener.ACTIVE);
-
- if (st == start && en == end) {
- Selection.setSelection(buf, Selection.getSelectionEnd(buf));
- }
-
- buf.removeSpan(Timeout.this);
- }
- }
-
- private Editable mBuffer;
- }
-
- public void onSpanAdded(Spannable s, Object what, int start, int end) { }
- public void onSpanRemoved(Spannable s, Object what, int start, int end) { }
-}
-
diff --git a/core/java/android/text/method/NumberKeyListener.java b/core/java/android/text/method/NumberKeyListener.java
deleted file mode 100644
index e500fae..0000000
--- a/core/java/android/text/method/NumberKeyListener.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.view.KeyEvent;
-import android.view.View;
-import android.text.Editable;
-import android.text.InputFilter;
-import android.text.Selection;
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-
-/**
- * For numeric text entry
- */
-public abstract class NumberKeyListener extends BaseKeyListener
- implements InputFilter
-{
- /**
- * You can say which characters you can accept.
- */
- protected abstract char[] getAcceptedChars();
-
- protected int lookup(KeyEvent event, Spannable content) {
- return event.getMatch(getAcceptedChars(), getMetaState(content));
- }
-
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
- char[] accept = getAcceptedChars();
- boolean filter = false;
-
- int i;
- for (i = start; i < end; i++) {
- if (!ok(accept, source.charAt(i))) {
- break;
- }
- }
-
- if (i == end) {
- // It was all OK.
- return null;
- }
-
- if (end - start == 1) {
- // It was not OK, and there is only one char, so nothing remains.
- return "";
- }
-
- SpannableStringBuilder filtered =
- new SpannableStringBuilder(source, start, end);
- i -= start;
- end -= start;
-
- int len = end - start;
- // Only count down to i because the chars before that were all OK.
- for (int j = end - 1; j >= i; j--) {
- if (!ok(accept, source.charAt(j))) {
- filtered.delete(j, j + 1);
- }
- }
-
- return filtered;
- }
-
- protected static boolean ok(char[] accept, char c) {
- for (int i = accept.length - 1; i >= 0; i--) {
- if (accept[i] == c) {
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public boolean onKeyDown(View view, Editable content,
- int keyCode, KeyEvent event) {
- int selStart, selEnd;
-
- {
- int a = Selection.getSelectionStart(content);
- int b = Selection.getSelectionEnd(content);
-
- selStart = Math.min(a, b);
- selEnd = Math.max(a, b);
- }
-
- int i = event != null ? lookup(event, content) : 0;
- int repeatCount = event != null ? event.getRepeatCount() : 0;
- if (repeatCount == 0) {
- if (i != 0) {
- if (selStart != selEnd) {
- Selection.setSelection(content, selEnd);
- }
-
- content.replace(selStart, selEnd, String.valueOf((char) i));
-
- adjustMetaAfterKeypress(content);
- return true;
- }
- } else if (i == '0' && repeatCount == 1) {
- // Pretty hackish, it replaces the 0 with the +
-
- if (selStart == selEnd && selEnd > 0 &&
- content.charAt(selStart - 1) == '0') {
- content.replace(selStart - 1, selEnd, String.valueOf('+'));
- adjustMetaAfterKeypress(content);
- return true;
- }
- }
-
- adjustMetaAfterKeypress(content);
- return super.onKeyDown(view, content, keyCode, event);
- }
-}
diff --git a/core/java/android/text/method/PasswordTransformationMethod.java b/core/java/android/text/method/PasswordTransformationMethod.java
deleted file mode 100644
index fad4f64..0000000
--- a/core/java/android/text/method/PasswordTransformationMethod.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.os.Handler;
-import android.os.SystemClock;
-import android.graphics.Rect;
-import android.view.View;
-import android.text.Editable;
-import android.text.GetChars;
-import android.text.NoCopySpan;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.text.Selection;
-import android.text.Spanned;
-import android.text.Spannable;
-import android.text.style.UpdateLayout;
-
-import java.lang.ref.WeakReference;
-
-public class PasswordTransformationMethod
-implements TransformationMethod, TextWatcher
-{
- public CharSequence getTransformation(CharSequence source, View view) {
- if (source instanceof Spannable) {
- Spannable sp = (Spannable) source;
-
- /*
- * Remove any references to other views that may still be
- * attached. This will happen when you flip the screen
- * while a password field is showing; there will still
- * be references to the old EditText in the text.
- */
- ViewReference[] vr = sp.getSpans(0, sp.length(),
- ViewReference.class);
- for (int i = 0; i < vr.length; i++) {
- sp.removeSpan(vr[i]);
- }
-
- sp.setSpan(new ViewReference(view), 0, 0,
- Spannable.SPAN_POINT_POINT);
- }
-
- return new PasswordCharSequence(source);
- }
-
- public static PasswordTransformationMethod getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new PasswordTransformationMethod();
- return sInstance;
- }
-
- public void beforeTextChanged(CharSequence s, int start,
- int count, int after) {
- // This callback isn't used.
- }
-
- public void onTextChanged(CharSequence s, int start,
- int before, int count) {
- if (s instanceof Spannable) {
- Spannable sp = (Spannable) s;
- ViewReference[] vr = sp.getSpans(0, s.length(),
- ViewReference.class);
- if (vr.length == 0) {
- return;
- }
-
- /*
- * There should generally only be one ViewReference in the text,
- * but make sure to look through all of them if necessary in case
- * something strange is going on. (We might still end up with
- * multiple ViewReferences if someone moves text from one password
- * field to another.)
- */
- View v = null;
- for (int i = 0; v == null && i < vr.length; i++) {
- v = vr[i].get();
- }
-
- if (v == null) {
- return;
- }
-
- int pref = TextKeyListener.getInstance().getPrefs(v.getContext());
- if ((pref & TextKeyListener.SHOW_PASSWORD) != 0) {
- if (count > 0) {
- Visible[] old = sp.getSpans(0, sp.length(), Visible.class);
- for (int i = 0; i < old.length; i++) {
- sp.removeSpan(old[i]);
- }
-
- if (count == 1) {
- sp.setSpan(new Visible(sp, this), start, start + count,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- }
- }
- }
-
- public void afterTextChanged(Editable s) {
- // This callback isn't used.
- }
-
- public void onFocusChanged(View view, CharSequence sourceText,
- boolean focused, int direction,
- Rect previouslyFocusedRect) {
- if (!focused) {
- if (sourceText instanceof Spannable) {
- Spannable sp = (Spannable) sourceText;
-
- Visible[] old = sp.getSpans(0, sp.length(), Visible.class);
- for (int i = 0; i < old.length; i++) {
- sp.removeSpan(old[i]);
- }
- }
- }
- }
-
- private static class PasswordCharSequence
- implements CharSequence, GetChars
- {
- public PasswordCharSequence(CharSequence source) {
- mSource = source;
- }
-
- public int length() {
- return mSource.length();
- }
-
- public char charAt(int i) {
- if (mSource instanceof Spanned) {
- Spanned sp = (Spanned) mSource;
-
- int st = sp.getSpanStart(TextKeyListener.ACTIVE);
- int en = sp.getSpanEnd(TextKeyListener.ACTIVE);
-
- if (i >= st && i < en) {
- return mSource.charAt(i);
- }
-
- Visible[] visible = sp.getSpans(0, sp.length(), Visible.class);
-
- for (int a = 0; a < visible.length; a++) {
- if (sp.getSpanStart(visible[a].mTransformer) >= 0) {
- st = sp.getSpanStart(visible[a]);
- en = sp.getSpanEnd(visible[a]);
-
- if (i >= st && i < en) {
- return mSource.charAt(i);
- }
- }
- }
- }
-
- return DOT;
- }
-
- public CharSequence subSequence(int start, int end) {
- char[] buf = new char[end - start];
-
- getChars(start, end, buf, 0);
- return new String(buf);
- }
-
- public String toString() {
- return subSequence(0, length()).toString();
- }
-
- public void getChars(int start, int end, char[] dest, int off) {
- TextUtils.getChars(mSource, start, end, dest, off);
-
- int st = -1, en = -1;
- int nvisible = 0;
- int[] starts = null, ends = null;
-
- if (mSource instanceof Spanned) {
- Spanned sp = (Spanned) mSource;
-
- st = sp.getSpanStart(TextKeyListener.ACTIVE);
- en = sp.getSpanEnd(TextKeyListener.ACTIVE);
-
- Visible[] visible = sp.getSpans(0, sp.length(), Visible.class);
- nvisible = visible.length;
- starts = new int[nvisible];
- ends = new int[nvisible];
-
- for (int i = 0; i < nvisible; i++) {
- if (sp.getSpanStart(visible[i].mTransformer) >= 0) {
- starts[i] = sp.getSpanStart(visible[i]);
- ends[i] = sp.getSpanEnd(visible[i]);
- }
- }
- }
-
- for (int i = start; i < end; i++) {
- if (! (i >= st && i < en)) {
- boolean visible = false;
-
- for (int a = 0; a < nvisible; a++) {
- if (i >= starts[a] && i < ends[a]) {
- visible = true;
- break;
- }
- }
-
- if (!visible) {
- dest[i - start + off] = DOT;
- }
- }
- }
- }
-
- private CharSequence mSource;
- }
-
- private static class Visible
- extends Handler
- implements UpdateLayout, Runnable
- {
- public Visible(Spannable sp, PasswordTransformationMethod ptm) {
- mText = sp;
- mTransformer = ptm;
- postAtTime(this, SystemClock.uptimeMillis() + 1500);
- }
-
- public void run() {
- mText.removeSpan(this);
- }
-
- private Spannable mText;
- private PasswordTransformationMethod mTransformer;
- }
-
- /**
- * Used to stash a reference back to the View in the Editable so we
- * can use it to check the settings.
- */
- private static class ViewReference extends WeakReference<View>
- implements NoCopySpan {
- public ViewReference(View v) {
- super(v);
- }
- }
-
- private static PasswordTransformationMethod sInstance;
- private static char DOT = '\u2022';
-}
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
deleted file mode 100644
index 0b39517..0000000
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.text.*;
-import android.text.method.TextKeyListener.Capitalize;
-import android.util.SparseArray;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.View;
-
-/**
- * This is the standard key listener for alphabetic input on qwerty
- * keyboards. You should generally not need to instantiate this yourself;
- * TextKeyListener will do it for you.
- */
-public class QwertyKeyListener extends BaseKeyListener {
- private static QwertyKeyListener[] sInstance =
- new QwertyKeyListener[Capitalize.values().length * 2];
-
- public QwertyKeyListener(Capitalize cap, boolean autotext) {
- mAutoCap = cap;
- mAutoText = autotext;
- }
-
- /**
- * Returns a new or existing instance with the specified capitalization
- * and correction properties.
- */
- public static QwertyKeyListener getInstance(boolean autotext,
- Capitalize cap) {
- int off = cap.ordinal() * 2 + (autotext ? 1 : 0);
-
- if (sInstance[off] == null) {
- sInstance[off] = new QwertyKeyListener(cap, autotext);
- }
-
- return sInstance[off];
- }
-
- public int getInputType() {
- return makeTextContentType(mAutoCap, mAutoText);
- }
-
- public boolean onKeyDown(View view, Editable content,
- int keyCode, KeyEvent event) {
- int selStart, selEnd;
- int pref = 0;
-
- if (view != null) {
- pref = TextKeyListener.getInstance().getPrefs(view.getContext());
- }
-
- {
- int a = Selection.getSelectionStart(content);
- int b = Selection.getSelectionEnd(content);
-
- selStart = Math.min(a, b);
- selEnd = Math.max(a, b);
-
- if (selStart < 0 || selEnd < 0) {
- selStart = selEnd = 0;
- Selection.setSelection(content, 0, 0);
- }
- }
-
- int activeStart = content.getSpanStart(TextKeyListener.ACTIVE);
- int activeEnd = content.getSpanEnd(TextKeyListener.ACTIVE);
-
- // QWERTY keyboard normal case
-
- int i = event.getUnicodeChar(getMetaState(content));
-
- int count = event.getRepeatCount();
- if (count > 0 && selStart == selEnd && selStart > 0) {
- char c = content.charAt(selStart - 1);
-
- if (c == i || c == Character.toUpperCase(i) && view != null) {
- if (showCharacterPicker(view, content, c, false, count)) {
- resetMetaState(content);
- return true;
- }
- }
- }
-
- if (i == KeyCharacterMap.PICKER_DIALOG_INPUT) {
- if (view != null) {
- showCharacterPicker(view, content,
- KeyCharacterMap.PICKER_DIALOG_INPUT, true, 1);
- }
- resetMetaState(content);
- return true;
- }
-
- if (i == KeyCharacterMap.HEX_INPUT) {
- int start;
-
- if (selStart == selEnd) {
- start = selEnd;
-
- while (start > 0 && selEnd - start < 4 &&
- Character.digit(content.charAt(start - 1), 16) >= 0) {
- start--;
- }
- } else {
- start = selStart;
- }
-
- int ch = -1;
- try {
- String hex = TextUtils.substring(content, start, selEnd);
- ch = Integer.parseInt(hex, 16);
- } catch (NumberFormatException nfe) { }
-
- if (ch >= 0) {
- selStart = start;
- Selection.setSelection(content, selStart, selEnd);
- i = ch;
- } else {
- i = 0;
- }
- }
-
- if (i != 0) {
- boolean dead = false;
-
- if ((i & KeyCharacterMap.COMBINING_ACCENT) != 0) {
- dead = true;
- i = i & KeyCharacterMap.COMBINING_ACCENT_MASK;
- }
-
- if (activeStart == selStart && activeEnd == selEnd) {
- boolean replace = false;
-
- if (selEnd - selStart - 1 == 0) {
- char accent = content.charAt(selStart);
- int composed = event.getDeadChar(accent, i);
-
- if (composed != 0) {
- i = composed;
- replace = true;
- }
- }
-
- if (!replace) {
- Selection.setSelection(content, selEnd);
- content.removeSpan(TextKeyListener.ACTIVE);
- selStart = selEnd;
- }
- }
-
- if ((pref & TextKeyListener.AUTO_CAP) != 0 &&
- Character.isLowerCase(i) &&
- TextKeyListener.shouldCap(mAutoCap, content, selStart)) {
- int where = content.getSpanEnd(TextKeyListener.CAPPED);
- int flags = content.getSpanFlags(TextKeyListener.CAPPED);
-
- if (where == selStart && (((flags >> 16) & 0xFFFF) == i)) {
- content.removeSpan(TextKeyListener.CAPPED);
- } else {
- flags = i << 16;
- i = Character.toUpperCase(i);
-
- if (selStart == 0)
- content.setSpan(TextKeyListener.CAPPED, 0, 0,
- Spannable.SPAN_MARK_MARK | flags);
- else
- content.setSpan(TextKeyListener.CAPPED,
- selStart - 1, selStart,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE |
- flags);
- }
- }
-
- if (selStart != selEnd) {
- Selection.setSelection(content, selEnd);
- }
- content.setSpan(OLD_SEL_START, selStart, selStart,
- Spannable.SPAN_MARK_MARK);
-
- content.replace(selStart, selEnd, String.valueOf((char) i));
-
- int oldStart = content.getSpanStart(OLD_SEL_START);
- selEnd = Selection.getSelectionEnd(content);
-
- if (oldStart < selEnd) {
- content.setSpan(TextKeyListener.LAST_TYPED,
- oldStart, selEnd,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-
- if (dead) {
- Selection.setSelection(content, oldStart, selEnd);
- content.setSpan(TextKeyListener.ACTIVE, oldStart, selEnd,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
-
- adjustMetaAfterKeypress(content);
-
- // potentially do autotext replacement if the character
- // that was typed was an autotext terminator
-
- if ((pref & TextKeyListener.AUTO_TEXT) != 0 && mAutoText &&
- (i == ' ' || i == '\t' || i == '\n' ||
- i == ',' || i == '.' || i == '!' || i == '?' ||
- i == '"' || Character.getType(i) == Character.END_PUNCTUATION) &&
- content.getSpanEnd(TextKeyListener.INHIBIT_REPLACEMENT)
- != oldStart) {
- int x;
-
- for (x = oldStart; x > 0; x--) {
- char c = content.charAt(x - 1);
- if (c != '\'' && !Character.isLetter(c)) {
- break;
- }
- }
-
- String rep = getReplacement(content, x, oldStart, view);
-
- if (rep != null) {
- Replaced[] repl = content.getSpans(0, content.length(),
- Replaced.class);
- for (int a = 0; a < repl.length; a++)
- content.removeSpan(repl[a]);
-
- char[] orig = new char[oldStart - x];
- TextUtils.getChars(content, x, oldStart, orig, 0);
-
- content.setSpan(new Replaced(orig), x, oldStart,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- content.replace(x, oldStart, rep);
- }
- }
-
- // Replace two spaces by a period and a space.
-
- if ((pref & TextKeyListener.AUTO_PERIOD) != 0 && mAutoText) {
- selEnd = Selection.getSelectionEnd(content);
- if (selEnd - 3 >= 0) {
- if (content.charAt(selEnd - 1) == ' ' &&
- content.charAt(selEnd - 2) == ' ') {
- char c = content.charAt(selEnd - 3);
-
- for (int j = selEnd - 3; j > 0; j--) {
- if (c == '"' ||
- Character.getType(c) == Character.END_PUNCTUATION) {
- c = content.charAt(j - 1);
- } else {
- break;
- }
- }
-
- if (Character.isLetter(c) || Character.isDigit(c)) {
- content.replace(selEnd - 2, selEnd - 1, ".");
- }
- }
- }
- }
-
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_DEL && selStart == selEnd) {
- // special backspace case for undoing autotext
-
- int consider = 1;
-
- // if backspacing over the last typed character,
- // it undoes the autotext prior to that character
- // (unless the character typed was newline, in which
- // case this behavior would be confusing)
-
- if (content.getSpanEnd(TextKeyListener.LAST_TYPED) == selStart) {
- if (content.charAt(selStart - 1) != '\n')
- consider = 2;
- }
-
- Replaced[] repl = content.getSpans(selStart - consider, selStart,
- Replaced.class);
-
- if (repl.length > 0) {
- int st = content.getSpanStart(repl[0]);
- int en = content.getSpanEnd(repl[0]);
- String old = new String(repl[0].mText);
-
- content.removeSpan(repl[0]);
- content.setSpan(TextKeyListener.INHIBIT_REPLACEMENT,
- en, en, Spannable.SPAN_POINT_POINT);
- content.replace(st, en, old);
-
- en = content.getSpanStart(TextKeyListener.INHIBIT_REPLACEMENT);
- if (en - 1 >= 0) {
- content.setSpan(TextKeyListener.INHIBIT_REPLACEMENT,
- en - 1, en,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- } else {
- content.removeSpan(TextKeyListener.INHIBIT_REPLACEMENT);
- }
-
- adjustMetaAfterKeypress(content);
-
- return true;
- }
- }
-
- return super.onKeyDown(view, content, keyCode, event);
- }
-
- private String getReplacement(CharSequence src, int start, int end,
- View view) {
- int len = end - start;
- boolean changecase = false;
-
- String replacement = AutoText.get(src, start, end, view);
-
- if (replacement == null) {
- String key = TextUtils.substring(src, start, end).toLowerCase();
- replacement = AutoText.get(key, 0, end - start, view);
- changecase = true;
-
- if (replacement == null)
- return null;
- }
-
- int caps = 0;
-
- if (changecase) {
- for (int j = start; j < end; j++) {
- if (Character.isUpperCase(src.charAt(j)))
- caps++;
- }
- }
-
- String out;
-
- if (caps == 0)
- out = replacement;
- else if (caps == 1)
- out = toTitleCase(replacement);
- else if (caps == len)
- out = replacement.toUpperCase();
- else
- out = toTitleCase(replacement);
-
- if (out.length() == len &&
- TextUtils.regionMatches(src, start, out, 0, len))
- return null;
-
- return out;
- }
-
- /**
- * Marks the specified region of <code>content</code> as having
- * contained <code>original</code> prior to AutoText replacement.
- * Call this method when you have done or are about to do an
- * AutoText-style replacement on a region of text and want to let
- * the same mechanism (the user pressing DEL immediately after the
- * change) undo the replacement.
- *
- * @param content the Editable text where the replacement was made
- * @param start the start of the replaced region
- * @param end the end of the replaced region; the location of the cursor
- * @param original the text to be restored if the user presses DEL
- */
- public static void markAsReplaced(Spannable content, int start, int end,
- String original) {
- Replaced[] repl = content.getSpans(0, content.length(), Replaced.class);
- for (int a = 0; a < repl.length; a++) {
- content.removeSpan(repl[a]);
- }
-
- int len = original.length();
- char[] orig = new char[len];
- original.getChars(0, len, orig, 0);
-
- content.setSpan(new Replaced(orig), start, end,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- private static SparseArray<String> PICKER_SETS =
- new SparseArray<String>();
- static {
- PICKER_SETS.put('!', "\u00A1");
- PICKER_SETS.put('<', "\u00AB");
- PICKER_SETS.put('>', "\u00BB");
- PICKER_SETS.put('?', "\u00BF");
- PICKER_SETS.put('A', "\u00C0\u00C1\u00C2\u00C4\u00C6\u00C3\u00C5");
- PICKER_SETS.put('C', "\u00C7");
- PICKER_SETS.put('E', "\u00C8\u00C9\u00CA\u00CB");
- PICKER_SETS.put('I', "\u00CC\u00CD\u00CE\u00CF");
- PICKER_SETS.put('N', "\u00D1");
- PICKER_SETS.put('O', "\u00D8\u0152\u00D5\u00D2\u00D3\u00D4\u00D6");
- PICKER_SETS.put('U', "\u00D9\u00DA\u00DB\u00DC");
- PICKER_SETS.put('Y', "\u00DD\u0178");
- PICKER_SETS.put('a', "\u00E0\u00E1\u00E2\u00E4\u00E6\u00E3\u00E5");
- PICKER_SETS.put('c', "\u00E7");
- PICKER_SETS.put('e', "\u00E8\u00E9\u00EA\u00EB");
- PICKER_SETS.put('i', "\u00EC\u00ED\u00EE\u00EF");
- PICKER_SETS.put('n', "\u00F1");
- PICKER_SETS.put('o', "\u00F8\u0153\u00F5\u00F2\u00F3\u00F4\u00F6");
- PICKER_SETS.put('s', "\u00A7\u00DF");
- PICKER_SETS.put('u', "\u00F9\u00FA\u00FB\u00FC");
- PICKER_SETS.put('y', "\u00FD\u00FF");
- PICKER_SETS.put(KeyCharacterMap.PICKER_DIALOG_INPUT,
- "\u2026\u00A5\u2022\u00AE\u00A9\u00B1");
- };
-
- private boolean showCharacterPicker(View view, Editable content, char c,
- boolean insert, int count) {
- String set = PICKER_SETS.get(c);
- if (set == null) {
- return false;
- }
-
- if (count == 1) {
- new CharacterPickerDialog(view.getContext(),
- view, content, set, insert).show();
- }
-
- return true;
- }
-
- private static String toTitleCase(String src) {
- return Character.toUpperCase(src.charAt(0)) + src.substring(1);
- }
-
- /* package */ static class Replaced implements NoCopySpan
- {
- public Replaced(char[] text) {
- mText = text;
- }
-
- private char[] mText;
- }
-
- private Capitalize mAutoCap;
- private boolean mAutoText;
-}
-
diff --git a/core/java/android/text/method/ReplacementTransformationMethod.java b/core/java/android/text/method/ReplacementTransformationMethod.java
deleted file mode 100644
index d6f879a..0000000
--- a/core/java/android/text/method/ReplacementTransformationMethod.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.graphics.Rect;
-import android.text.Editable;
-import android.text.GetChars;
-import android.text.Spannable;
-import android.text.Spanned;
-import android.text.SpannedString;
-import android.text.TextUtils;
-import android.view.View;
-
-/**
- * This transformation method causes the characters in the {@link #getOriginal}
- * array to be replaced by the corresponding characters in the
- * {@link #getReplacement} array.
- */
-public abstract class ReplacementTransformationMethod
-implements TransformationMethod
-{
- /**
- * Returns the list of characters that are to be replaced by other
- * characters when displayed.
- */
- protected abstract char[] getOriginal();
- /**
- * Returns a parallel array of replacement characters for the ones
- * that are to be replaced.
- */
- protected abstract char[] getReplacement();
-
- /**
- * Returns a CharSequence that will mirror the contents of the
- * source CharSequence but with the characters in {@link #getOriginal}
- * replaced by ones from {@link #getReplacement}.
- */
- public CharSequence getTransformation(CharSequence source, View v) {
- char[] original = getOriginal();
- char[] replacement = getReplacement();
-
- /*
- * Short circuit for faster display if the text will never change.
- */
- if (!(source instanceof Editable)) {
- /*
- * Check whether the text does not contain any of the
- * source characters so can be used unchanged.
- */
- boolean doNothing = true;
- int n = original.length;
- for (int i = 0; i < n; i++) {
- if (TextUtils.indexOf(source, original[i]) >= 0) {
- doNothing = false;
- break;
- }
- }
- if (doNothing) {
- return source;
- }
-
- if (!(source instanceof Spannable)) {
- /*
- * The text contains some of the source characters,
- * but they can be flattened out now instead of
- * at display time.
- */
- if (source instanceof Spanned) {
- return new SpannedString(new SpannedReplacementCharSequence(
- (Spanned) source,
- original, replacement));
- } else {
- return new ReplacementCharSequence(source,
- original,
- replacement).toString();
- }
- }
- }
-
- if (source instanceof Spanned) {
- return new SpannedReplacementCharSequence((Spanned) source,
- original, replacement);
- } else {
- return new ReplacementCharSequence(source, original, replacement);
- }
- }
-
- public void onFocusChanged(View view, CharSequence sourceText,
- boolean focused, int direction,
- Rect previouslyFocusedRect) {
- // This callback isn't used.
- }
-
- private static class ReplacementCharSequence
- implements CharSequence, GetChars {
- private char[] mOriginal, mReplacement;
-
- public ReplacementCharSequence(CharSequence source, char[] original,
- char[] replacement) {
- mSource = source;
- mOriginal = original;
- mReplacement = replacement;
- }
-
- public int length() {
- return mSource.length();
- }
-
- public char charAt(int i) {
- char c = mSource.charAt(i);
-
- int n = mOriginal.length;
- for (int j = 0; j < n; j++) {
- if (c == mOriginal[j]) {
- c = mReplacement[j];
- }
- }
-
- return c;
- }
-
- public CharSequence subSequence(int start, int end) {
- char[] c = new char[end - start];
-
- getChars(start, end, c, 0);
- return new String(c);
- }
-
- public String toString() {
- char[] c = new char[length()];
-
- getChars(0, length(), c, 0);
- return new String(c);
- }
-
- public void getChars(int start, int end, char[] dest, int off) {
- TextUtils.getChars(mSource, start, end, dest, off);
- int offend = end - start + off;
- int n = mOriginal.length;
-
- for (int i = off; i < offend; i++) {
- char c = dest[i];
-
- for (int j = 0; j < n; j++) {
- if (c == mOriginal[j]) {
- dest[i] = mReplacement[j];
- }
- }
- }
- }
-
- private CharSequence mSource;
- }
-
- private static class SpannedReplacementCharSequence
- extends ReplacementCharSequence
- implements Spanned
- {
- public SpannedReplacementCharSequence(Spanned source, char[] original,
- char[] replacement) {
- super(source, original, replacement);
- mSpanned = source;
- }
-
- public CharSequence subSequence(int start, int end) {
- return new SpannedString(this).subSequence(start, end);
- }
-
- public <T> T[] getSpans(int start, int end, Class<T> type) {
- return mSpanned.getSpans(start, end, type);
- }
-
- public int getSpanStart(Object tag) {
- return mSpanned.getSpanStart(tag);
- }
-
- public int getSpanEnd(Object tag) {
- return mSpanned.getSpanEnd(tag);
- }
-
- public int getSpanFlags(Object tag) {
- return mSpanned.getSpanFlags(tag);
- }
-
- public int nextSpanTransition(int start, int end, Class type) {
- return mSpanned.nextSpanTransition(start, end, type);
- }
-
- private Spanned mSpanned;
- }
-}
diff --git a/core/java/android/text/method/ScrollingMovementMethod.java b/core/java/android/text/method/ScrollingMovementMethod.java
deleted file mode 100644
index 563ceed..0000000
--- a/core/java/android/text/method/ScrollingMovementMethod.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.text.*;
-import android.widget.TextView;
-import android.view.View;
-
-public class
-ScrollingMovementMethod
-implements MovementMethod
-{
- /**
- * Scrolls the text to the left if possible.
- */
- protected boolean left(TextView widget, Spannable buffer) {
- Layout layout = widget.getLayout();
-
- int scrolly = widget.getScrollY();
- int scr = widget.getScrollX();
- int em = Math.round(layout.getPaint().getFontSpacing());
-
- int padding = widget.getTotalPaddingTop() +
- widget.getTotalPaddingBottom();
- int top = layout.getLineForVertical(scrolly);
- int bottom = layout.getLineForVertical(scrolly + widget.getHeight() -
- padding);
- int left = Integer.MAX_VALUE;
-
- for (int i = top; i <= bottom; i++) {
- left = (int) Math.min(left, layout.getLineLeft(i));
- }
-
- if (scr > left) {
- int s = Math.max(scr - em, left);
- widget.scrollTo(s, widget.getScrollY());
- return true;
- }
-
- return false;
- }
-
- /**
- * Scrolls the text to the right if possible.
- */
- protected boolean right(TextView widget, Spannable buffer) {
- Layout layout = widget.getLayout();
-
- int scrolly = widget.getScrollY();
- int scr = widget.getScrollX();
- int em = Math.round(layout.getPaint().getFontSpacing());
-
- int padding = widget.getTotalPaddingTop() +
- widget.getTotalPaddingBottom();
- int top = layout.getLineForVertical(scrolly);
- int bottom = layout.getLineForVertical(scrolly + widget.getHeight() -
- padding);
- int right = 0;
-
- for (int i = top; i <= bottom; i++) {
- right = (int) Math.max(right, layout.getLineRight(i));
- }
-
- padding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight();
- if (scr < right - (widget.getWidth() - padding)) {
- int s = Math.min(scr + em, right - (widget.getWidth() - padding));
- widget.scrollTo(s, widget.getScrollY());
- return true;
- }
-
- return false;
- }
-
- /**
- * Scrolls the text up if possible.
- */
- protected boolean up(TextView widget, Spannable buffer) {
- Layout layout = widget.getLayout();
-
- int areatop = widget.getScrollY();
- int line = layout.getLineForVertical(areatop);
- int linetop = layout.getLineTop(line);
-
- // If the top line is partially visible, bring it all the way
- // into view; otherwise, bring the previous line into view.
- if (areatop == linetop)
- line--;
-
- if (line >= 0) {
- Touch.scrollTo(widget, layout,
- widget.getScrollX(), layout.getLineTop(line));
- return true;
- }
-
- return false;
- }
-
- /**
- * Scrolls the text down if possible.
- */
- protected boolean down(TextView widget, Spannable buffer) {
- Layout layout = widget.getLayout();
-
- int padding = widget.getTotalPaddingTop() +
- widget.getTotalPaddingBottom();
-
- int areabot = widget.getScrollY() + widget.getHeight() - padding;
- int line = layout.getLineForVertical(areabot);
-
- if (layout.getLineTop(line+1) < areabot + 1) {
- // Less than a pixel of this line is out of view,
- // so we must have tried to make it entirely in view
- // and now want the next line to be in view instead.
-
- line++;
- }
-
- if (line <= layout.getLineCount() - 1) {
- widget.scrollTo(widget.getScrollX(), layout.getLineTop(line+1) -
- (widget.getHeight() - padding));
- Touch.scrollTo(widget, layout,
- widget.getScrollX(), widget.getScrollY());
- return true;
- }
-
- return false;
- }
-
- public boolean onKeyDown(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
- return executeDown(widget, buffer, keyCode);
- }
-
- private boolean executeDown(TextView widget, Spannable buffer, int keyCode) {
- boolean handled = false;
-
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- handled |= left(widget, buffer);
- break;
-
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- handled |= right(widget, buffer);
- break;
-
- case KeyEvent.KEYCODE_DPAD_UP:
- handled |= up(widget, buffer);
- break;
-
- case KeyEvent.KEYCODE_DPAD_DOWN:
- handled |= down(widget, buffer);
- break;
- }
-
- return handled;
- }
-
- public boolean onKeyUp(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
- return false;
- }
-
- public boolean onKeyOther(TextView view, Spannable text, KeyEvent event) {
- int code = event.getKeyCode();
- if (code != KeyEvent.KEYCODE_UNKNOWN
- && event.getAction() == KeyEvent.ACTION_MULTIPLE) {
- int repeat = event.getRepeatCount();
- boolean first = true;
- boolean handled = false;
- while ((--repeat) > 0) {
- if (first && executeDown(view, text, code)) {
- handled = true;
- MetaKeyKeyListener.adjustMetaAfterKeypress(text);
- MetaKeyKeyListener.resetLockedMeta(text);
- }
- first = false;
- }
- return handled;
- }
- return false;
- }
-
- public boolean onTrackballEvent(TextView widget, Spannable text,
- MotionEvent event) {
- return false;
- }
-
- public boolean onTouchEvent(TextView widget, Spannable buffer,
- MotionEvent event) {
- return Touch.onTouchEvent(widget, buffer, event);
- }
-
- public void initialize(TextView widget, Spannable text) { }
-
- public boolean canSelectArbitrarily() {
- return false;
- }
-
- public void onTakeFocus(TextView widget, Spannable text, int dir) {
- Layout layout = widget.getLayout();
-
- if (layout != null && (dir & View.FOCUS_FORWARD) != 0) {
- widget.scrollTo(widget.getScrollX(),
- layout.getLineTop(0));
- }
- if (layout != null && (dir & View.FOCUS_BACKWARD) != 0) {
- int padding = widget.getTotalPaddingTop() +
- widget.getTotalPaddingBottom();
- int line = layout.getLineCount() - 1;
-
- widget.scrollTo(widget.getScrollX(),
- layout.getLineTop(line+1) -
- (widget.getHeight() - padding));
- }
- }
-
- public static MovementMethod getInstance() {
- if (sInstance == null)
- sInstance = new ScrollingMovementMethod();
-
- return sInstance;
- }
-
- private static ScrollingMovementMethod sInstance;
-}
diff --git a/core/java/android/text/method/SingleLineTransformationMethod.java b/core/java/android/text/method/SingleLineTransformationMethod.java
deleted file mode 100644
index 6a05fe4..0000000
--- a/core/java/android/text/method/SingleLineTransformationMethod.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.graphics.Rect;
-import android.text.Editable;
-import android.text.GetChars;
-import android.text.Spannable;
-import android.text.Spanned;
-import android.text.SpannedString;
-import android.text.TextUtils;
-import android.view.View;
-
-/**
- * This transformation method causes any newline characters (\n) to be
- * displayed as spaces instead of causing line breaks, and causes
- * carriage return characters (\r) to have no appearance.
- */
-public class SingleLineTransformationMethod
-extends ReplacementTransformationMethod {
- private static char[] ORIGINAL = new char[] { '\n', '\r' };
- private static char[] REPLACEMENT = new char[] { ' ', '\uFEFF' };
-
- /**
- * The characters to be replaced are \n and \r.
- */
- protected char[] getOriginal() {
- return ORIGINAL;
- }
-
- /**
- * The character \n is replaced with is space;
- * the character \r is replaced with is FEFF (zero width space).
- */
- protected char[] getReplacement() {
- return REPLACEMENT;
- }
-
- public static SingleLineTransformationMethod getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new SingleLineTransformationMethod();
- return sInstance;
- }
-
- private static SingleLineTransformationMethod sInstance;
-}
diff --git a/core/java/android/text/method/TextKeyListener.java b/core/java/android/text/method/TextKeyListener.java
deleted file mode 100644
index 5be2a48..0000000
--- a/core/java/android/text/method/TextKeyListener.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.text.method;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.provider.Settings;
-import android.provider.Settings.System;
-import android.text.*;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.View;
-import android.text.InputType;
-
-import java.lang.ref.WeakReference;
-
-/**
- * This is the key listener for typing normal text. It delegates to
- * other key listeners appropriate to the current keyboard and language.
- */
-public class TextKeyListener extends BaseKeyListener implements SpanWatcher {
- private static TextKeyListener[] sInstance =
- new TextKeyListener[Capitalize.values().length * 2];
-
- /* package */ static final Object ACTIVE = new NoCopySpan.Concrete();
- /* package */ static final Object CAPPED = new NoCopySpan.Concrete();
- /* package */ static final Object INHIBIT_REPLACEMENT = new NoCopySpan.Concrete();
- /* package */ static final Object LAST_TYPED = new NoCopySpan.Concrete();
-
- private Capitalize mAutoCap;
- private boolean mAutoText;
-
- private int mPrefs;
- private boolean mPrefsInited;
-
- /* package */ static final int AUTO_CAP = 1;
- /* package */ static final int AUTO_TEXT = 2;
- /* package */ static final int AUTO_PERIOD = 4;
- /* package */ static final int SHOW_PASSWORD = 8;
- private WeakReference<ContentResolver> mResolver;
- private TextKeyListener.SettingsObserver mObserver;
-
- /**
- * Creates a new TextKeyListener with the specified capitalization
- * and correction properties.
- *
- * @param cap when, if ever, to automatically capitalize.
- * @param autotext whether to automatically do spelling corrections.
- */
- public TextKeyListener(Capitalize cap, boolean autotext) {
- mAutoCap = cap;
- mAutoText = autotext;
- }
-
- /**
- * Returns a new or existing instance with the specified capitalization
- * and correction properties.
- *
- * @param cap when, if ever, to automatically capitalize.
- * @param autotext whether to automatically do spelling corrections.
- */
- public static TextKeyListener getInstance(boolean autotext,
- Capitalize cap) {
- int off = cap.ordinal() * 2 + (autotext ? 1 : 0);
-
- if (sInstance[off] == null) {
- sInstance[off] = new TextKeyListener(cap, autotext);
- }
-
- return sInstance[off];
- }
-
- /**
- * Returns a new or existing instance with no automatic capitalization
- * or correction.
- */
- public static TextKeyListener getInstance() {
- return getInstance(false, Capitalize.NONE);
- }
-
- /**
- * Returns whether it makes sense to automatically capitalize at the
- * specified position in the specified text, with the specified rules.
- *
- * @param cap the capitalization rules to consider.
- * @param cs the text in which an insertion is being made.
- * @param off the offset into that text where the insertion is being made.
- *
- * @return whether the character being inserted should be capitalized.
- */
- public static boolean shouldCap(Capitalize cap, CharSequence cs, int off) {
- int i;
- char c;
-
- if (cap == Capitalize.NONE) {
- return false;
- }
- if (cap == Capitalize.CHARACTERS) {
- return true;
- }
-
- return TextUtils.getCapsMode(cs, off, cap == Capitalize.WORDS
- ? TextUtils.CAP_MODE_WORDS : TextUtils.CAP_MODE_SENTENCES)
- != 0;
- }
-
- public int getInputType() {
- return makeTextContentType(mAutoCap, mAutoText);
- }
-
- @Override
- public boolean onKeyDown(View view, Editable content,
- int keyCode, KeyEvent event) {
- KeyListener im = getKeyListener(event);
-
- return im.onKeyDown(view, content, keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(View view, Editable content,
- int keyCode, KeyEvent event) {
- KeyListener im = getKeyListener(event);
-
- return im.onKeyUp(view, content, keyCode, event);
- }
-
- @Override
- public boolean onKeyOther(View view, Editable content, KeyEvent event) {
- KeyListener im = getKeyListener(event);
-
- return im.onKeyOther(view, content, event);
- }
-
- /**
- * Clear all the input state (autotext, autocap, multitap, undo)
- * from the specified Editable, going beyond Editable.clear(), which
- * just clears the text but not the input state.
- *
- * @param e the buffer whose text and state are to be cleared.
- */
- public static void clear(Editable e) {
- e.clear();
- e.removeSpan(ACTIVE);
- e.removeSpan(CAPPED);
- e.removeSpan(INHIBIT_REPLACEMENT);
- e.removeSpan(LAST_TYPED);
-
- QwertyKeyListener.Replaced[] repl = e.getSpans(0, e.length(),
- QwertyKeyListener.Replaced.class);
- final int count = repl.length;
- for (int i = 0; i < count; i++) {
- e.removeSpan(repl[i]);
- }
- }
-
- public void onSpanAdded(Spannable s, Object what, int start, int end) { }
- public void onSpanRemoved(Spannable s, Object what, int start, int end) { }
-
- public void onSpanChanged(Spannable s, Object what, int start, int end,
- int st, int en) {
- if (what == Selection.SELECTION_END) {
- s.removeSpan(ACTIVE);
- }
- }
-
- private KeyListener getKeyListener(KeyEvent event) {
- KeyCharacterMap kmap = KeyCharacterMap.load(event.getKeyboardDevice());
- int kind = kmap.getKeyboardType();
-
- if (kind == KeyCharacterMap.ALPHA) {
- return QwertyKeyListener.getInstance(mAutoText, mAutoCap);
- } else if (kind == KeyCharacterMap.NUMERIC) {
- return MultiTapKeyListener.getInstance(mAutoText, mAutoCap);
- }
-
- return NullKeyListener.getInstance();
- }
-
- public enum Capitalize {
- NONE, SENTENCES, WORDS, CHARACTERS,
- }
-
- private static class NullKeyListener implements KeyListener
- {
- public int getInputType() {
- return InputType.TYPE_NULL;
- }
-
- public boolean onKeyDown(View view, Editable content,
- int keyCode, KeyEvent event) {
- return false;
- }
-
- public boolean onKeyUp(View view, Editable content, int keyCode,
- KeyEvent event) {
- return false;
- }
-
- public boolean onKeyOther(View view, Editable content, KeyEvent event) {
- return false;
- }
-
- public void clearMetaKeyState(View view, Editable content, int states) {
- }
-
- public static NullKeyListener getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new NullKeyListener();
- return sInstance;
- }
-
- private static NullKeyListener sInstance;
- }
-
- public void release() {
- if (mResolver != null) {
- final ContentResolver contentResolver = mResolver.get();
- if (contentResolver != null) {
- contentResolver.unregisterContentObserver(mObserver);
- mResolver.clear();
- }
- mObserver = null;
- mResolver = null;
- mPrefsInited = false;
- }
- }
-
- private void initPrefs(Context context) {
- final ContentResolver contentResolver = context.getContentResolver();
- mResolver = new WeakReference<ContentResolver>(contentResolver);
- mObserver = new SettingsObserver();
- contentResolver.registerContentObserver(Settings.System.CONTENT_URI, true, mObserver);
-
- updatePrefs(contentResolver);
- mPrefsInited = true;
- }
-
- private class SettingsObserver extends ContentObserver {
- public SettingsObserver() {
- super(new Handler());
- }
-
- @Override
- public void onChange(boolean selfChange) {
- if (mResolver != null) {
- final ContentResolver contentResolver = mResolver.get();
- if (contentResolver == null) {
- mPrefsInited = false;
- } else {
- updatePrefs(contentResolver);
- }
- } else {
- mPrefsInited = false;
- }
- }
- }
-
- private void updatePrefs(ContentResolver resolver) {
- boolean cap = System.getInt(resolver, System.TEXT_AUTO_CAPS, 1) > 0;
- boolean text = System.getInt(resolver, System.TEXT_AUTO_REPLACE, 1) > 0;
- boolean period = System.getInt(resolver, System.TEXT_AUTO_PUNCTUATE, 1) > 0;
- boolean pw = System.getInt(resolver, System.TEXT_SHOW_PASSWORD, 1) > 0;
-
- mPrefs = (cap ? AUTO_CAP : 0) |
- (text ? AUTO_TEXT : 0) |
- (period ? AUTO_PERIOD : 0) |
- (pw ? SHOW_PASSWORD : 0);
- }
-
- /* package */ int getPrefs(Context context) {
- synchronized (this) {
- if (!mPrefsInited || mResolver.get() == null) {
- initPrefs(context);
- }
- }
-
- return mPrefs;
- }
-}
diff --git a/core/java/android/text/method/TimeKeyListener.java b/core/java/android/text/method/TimeKeyListener.java
deleted file mode 100644
index 3fbfd8c..0000000
--- a/core/java/android/text/method/TimeKeyListener.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.view.KeyEvent;
-import android.text.InputType;
-
-/**
- * For entering times in a text field.
- */
-public class TimeKeyListener extends NumberKeyListener
-{
- public int getInputType() {
- return InputType.TYPE_CLASS_DATETIME
- | InputType.TYPE_DATETIME_VARIATION_TIME;
- }
-
- @Override
- protected char[] getAcceptedChars()
- {
- return CHARACTERS;
- }
-
- public static TimeKeyListener getInstance() {
- if (sInstance != null)
- return sInstance;
-
- sInstance = new TimeKeyListener();
- return sInstance;
- }
-
- /**
- * The characters that are used.
- *
- * @see KeyEvent#getMatch
- * @see #getAcceptedChars
- */
- public static final char[] CHARACTERS = new char[] {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'm',
- 'p', ':'
- };
-
- private static TimeKeyListener sInstance;
-}
diff --git a/core/java/android/text/method/Touch.java b/core/java/android/text/method/Touch.java
deleted file mode 100644
index 65036ad..0000000
--- a/core/java/android/text/method/Touch.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.text.method;
-
-import android.text.Layout;
-import android.text.NoCopySpan;
-import android.text.Layout.Alignment;
-import android.text.Spannable;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.widget.TextView;
-
-public class Touch {
- private Touch() { }
-
- /**
- * Scrolls the specified widget to the specified coordinates, except
- * constrains the X scrolling position to the horizontal regions of
- * the text that will be visible after scrolling to the specified
- * Y position.
- */
- public static void scrollTo(TextView widget, Layout layout, int x, int y) {
- int padding = widget.getTotalPaddingTop() +
- widget.getTotalPaddingBottom();
- int top = layout.getLineForVertical(y);
- int bottom = layout.getLineForVertical(y + widget.getHeight() -
- padding);
-
- int left = Integer.MAX_VALUE;
- int right = 0;
- Alignment a = null;
-
- for (int i = top; i <= bottom; i++) {
- left = (int) Math.min(left, layout.getLineLeft(i));
- right = (int) Math.max(right, layout.getLineRight(i));
-
- if (a == null) {
- a = layout.getParagraphAlignment(i);
- }
- }
-
- padding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight();
- int width = widget.getWidth();
- int diff = 0;
-
- if (right - left < width - padding) {
- if (a == Alignment.ALIGN_CENTER) {
- diff = (width - padding - (right - left)) / 2;
- } else if (a == Alignment.ALIGN_OPPOSITE) {
- diff = width - padding - (right - left);
- }
- }
-
- x = Math.min(x, right - (width - padding) - diff);
- x = Math.max(x, left - diff);
-
- widget.scrollTo(x, y);
- }
-
- /**
- * Handles touch events for dragging. You may want to do other actions
- * like moving the cursor on touch as well.
- */
- public static boolean onTouchEvent(TextView widget, Spannable buffer,
- MotionEvent event) {
- DragState[] ds;
-
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- buffer.setSpan(new DragState(event.getX(), event.getY()),
- 0, 0, Spannable.SPAN_MARK_MARK);
- return true;
-
- case MotionEvent.ACTION_UP:
- ds = buffer.getSpans(0, buffer.length(), DragState.class);
-
- for (int i = 0; i < ds.length; i++) {
- buffer.removeSpan(ds[i]);
- }
-
- if (ds.length > 0 && ds[0].mUsed) {
- return true;
- } else {
- return false;
- }
-
- case MotionEvent.ACTION_MOVE:
- ds = buffer.getSpans(0, buffer.length(), DragState.class);
-
- if (ds.length > 0) {
- if (ds[0].mFarEnough == false) {
- int slop = ViewConfiguration.get(widget.getContext()).getScaledTouchSlop();
-
- if (Math.abs(event.getX() - ds[0].mX) >= slop ||
- Math.abs(event.getY() - ds[0].mY) >= slop) {
- ds[0].mFarEnough = true;
- }
- }
-
- if (ds[0].mFarEnough) {
- ds[0].mUsed = true;
-
- float dx = ds[0].mX - event.getX();
- float dy = ds[0].mY - event.getY();
-
- ds[0].mX = event.getX();
- ds[0].mY = event.getY();
-
- int nx = widget.getScrollX() + (int) dx;
- int ny = widget.getScrollY() + (int) dy;
-
- int padding = widget.getTotalPaddingTop() +
- widget.getTotalPaddingBottom();
- Layout layout = widget.getLayout();
-
- ny = Math.min(ny, layout.getHeight() - (widget.getHeight() -
- padding));
- ny = Math.max(ny, 0);
-
- scrollTo(widget, layout, nx, ny);
- widget.cancelLongPress();
- return true;
- }
- }
- }
-
- return false;
- }
-
- private static class DragState implements NoCopySpan {
- public float mX;
- public float mY;
- public boolean mFarEnough;
- public boolean mUsed;
-
- public DragState(float x, float y) {
- mX = x;
- mY = y;
- }
- }
-}
diff --git a/core/java/android/text/method/TransformationMethod.java b/core/java/android/text/method/TransformationMethod.java
deleted file mode 100644
index 9f51c2a..0000000
--- a/core/java/android/text/method/TransformationMethod.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.method;
-
-import android.graphics.Rect;
-import android.view.View;
-import android.widget.TextView;
-
-/**
- * TextView uses TransformationMethods to do things like replacing the
- * characters of passwords with dots, or keeping the newline characters
- * from causing line breaks in single-line text fields.
- */
-public interface TransformationMethod
-{
- /**
- * Returns a CharSequence that is a transformation of the source text --
- * for example, replacing each character with a dot in a password field.
- * Beware that the returned text must be exactly the same length as
- * the source text, and that if the source text is Editable, the returned
- * text must mirror it dynamically instead of doing a one-time copy.
- */
- public CharSequence getTransformation(CharSequence source, View view);
-
- /**
- * This method is called when the TextView that uses this
- * TransformationMethod gains or loses focus.
- */
- public void onFocusChanged(View view, CharSequence sourceText,
- boolean focused, int direction,
- Rect previouslyFocusedRect);
-}
diff --git a/core/java/android/text/method/package.html b/core/java/android/text/method/package.html
deleted file mode 100644
index 93698b8..0000000
--- a/core/java/android/text/method/package.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html>
-<body>
-
-<p>Provides classes that monitor or modify keypad input.</p>
-<p>You can use these classes to modify the type of keypad entry
-for your application, or decipher the keypresses entered for your specific
-entry method. For example:</p>
-<pre>
-// Set the text to password display style:
-EditText txtView = (EditText)findViewById(R.id.text);
-txtView.setTransformationMethod(PasswordTransformationMethod.getInstance());
-
-//Set the input style to numbers, rather than qwerty keyboard style.
-txtView.setInputMethod(DigitsInputMethod.getInstance());
-
-// Find out whether the caps lock is on.
-// 0 is no, 1 is yes, 2 is caps lock on.
-int active = MultiTapInputMethod.getCapsActive(txtView.getText());
-</pre>
-</body>
-</html>
diff --git a/core/java/android/text/package.html b/core/java/android/text/package.html
deleted file mode 100644
index 162dcd8..0000000
--- a/core/java/android/text/package.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<html>
-<body>
-
-<p>Provides classes used to render or track text and text spans on the screen.</p>
-<p>You can use these classes to design your own widgets that manage text,
-to handle arbitrary text spans for changes, or to handle drawing yourself
-for an existing widget.</p>
-<p>The Span&hellip; interfaces and classes are used to create or manage spans of
-text in a View item. You can use these to style the text or background, or to
-listen for changes. If creating your own widget, extend DynamicLayout, to manages
-the actual wrapping and drawing of your text.
-</body>
-</html>
diff --git a/core/java/android/text/style/AbsoluteSizeSpan.java b/core/java/android/text/style/AbsoluteSizeSpan.java
deleted file mode 100644
index 484f8ce..0000000
--- a/core/java/android/text/style/AbsoluteSizeSpan.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class AbsoluteSizeSpan extends MetricAffectingSpan implements ParcelableSpan {
-
- private final int mSize;
-
- public AbsoluteSizeSpan(int size) {
- mSize = size;
- }
-
- public AbsoluteSizeSpan(Parcel src) {
- mSize = src.readInt();
- }
-
- public int getSpanTypeId() {
- return TextUtils.ABSOLUTE_SIZE_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mSize);
- }
-
- public int getSize() {
- return mSize;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setTextSize(mSize);
- }
-
- @Override
- public void updateMeasureState(TextPaint ds) {
- ds.setTextSize(mSize);
- }
-}
diff --git a/core/java/android/text/style/AlignmentSpan.java b/core/java/android/text/style/AlignmentSpan.java
deleted file mode 100644
index b8a37da..0000000
--- a/core/java/android/text/style/AlignmentSpan.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.os.Parcel;
-import android.text.Layout;
-import android.text.ParcelableSpan;
-import android.text.TextUtils;
-
-public interface AlignmentSpan extends ParagraphStyle {
- public Layout.Alignment getAlignment();
-
- public static class Standard
- implements AlignmentSpan, ParcelableSpan {
- public Standard(Layout.Alignment align) {
- mAlignment = align;
- }
-
- public Standard(Parcel src) {
- mAlignment = Layout.Alignment.valueOf(src.readString());
- }
-
- public int getSpanTypeId() {
- return TextUtils.ALIGNMENT_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mAlignment.name());
- }
-
- public Layout.Alignment getAlignment() {
- return mAlignment;
- }
-
- private final Layout.Alignment mAlignment;
- }
-}
diff --git a/core/java/android/text/style/BackgroundColorSpan.java b/core/java/android/text/style/BackgroundColorSpan.java
deleted file mode 100644
index 580a369..0000000
--- a/core/java/android/text/style/BackgroundColorSpan.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class BackgroundColorSpan extends CharacterStyle
- implements UpdateAppearance, ParcelableSpan {
-
- private final int mColor;
-
- public BackgroundColorSpan(int color) {
- mColor = color;
- }
-
- public BackgroundColorSpan(Parcel src) {
- mColor = src.readInt();
- }
-
- public int getSpanTypeId() {
- return TextUtils.BACKGROUND_COLOR_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mColor);
- }
-
- public int getBackgroundColor() {
- return mColor;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.bgColor = mColor;
- }
-}
diff --git a/core/java/android/text/style/BulletSpan.java b/core/java/android/text/style/BulletSpan.java
deleted file mode 100644
index 655bd81..0000000
--- a/core/java/android/text/style/BulletSpan.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.os.Parcel;
-import android.text.Layout;
-import android.text.ParcelableSpan;
-import android.text.Spanned;
-import android.text.TextUtils;
-
-public class BulletSpan implements LeadingMarginSpan, ParcelableSpan {
- private final int mGapWidth;
- private final boolean mWantColor;
- private final int mColor;
-
- private static final int BULLET_RADIUS = 3;
- public static final int STANDARD_GAP_WIDTH = 2;
-
- public BulletSpan() {
- mGapWidth = STANDARD_GAP_WIDTH;
- mWantColor = false;
- mColor = 0;
- }
-
- public BulletSpan(int gapWidth) {
- mGapWidth = gapWidth;
- mWantColor = false;
- mColor = 0;
- }
-
- public BulletSpan(int gapWidth, int color) {
- mGapWidth = gapWidth;
- mWantColor = true;
- mColor = color;
- }
-
- public BulletSpan(Parcel src) {
- mGapWidth = src.readInt();
- mWantColor = src.readInt() != 0;
- mColor = src.readInt();
- }
-
- public int getSpanTypeId() {
- return TextUtils.BULLET_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mGapWidth);
- dest.writeInt(mWantColor ? 1 : 0);
- dest.writeInt(mColor);
- }
-
- public int getLeadingMargin(boolean first) {
- return 2 * BULLET_RADIUS + mGapWidth;
- }
-
- public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- boolean first, Layout l) {
- if (((Spanned) text).getSpanStart(this) == start) {
- Paint.Style style = p.getStyle();
- int oldcolor = 0;
-
- if (mWantColor) {
- oldcolor = p.getColor();
- p.setColor(mColor);
- }
-
- p.setStyle(Paint.Style.FILL);
-
- c.drawCircle(x + dir * BULLET_RADIUS, (top + bottom) / 2.0f,
- BULLET_RADIUS, p);
-
- if (mWantColor) {
- p.setColor(oldcolor);
- }
-
- p.setStyle(style);
- }
- }
-}
diff --git a/core/java/android/text/style/CharacterStyle.java b/core/java/android/text/style/CharacterStyle.java
deleted file mode 100644
index 14dfddd..0000000
--- a/core/java/android/text/style/CharacterStyle.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.text.TextPaint;
-
-/**
- * The classes that affect character-level text formatting extend this
- * class. Most extend its subclass {@link MetricAffectingSpan}, but simple
- * ones may just implement {@link UpdateAppearance}.
- */
-public abstract class CharacterStyle {
- public abstract void updateDrawState(TextPaint tp);
-
- /**
- * A given CharacterStyle can only applied to a single region of a given
- * Spanned. If you need to attach the same CharacterStyle to multiple
- * regions, you can use this method to wrap it with a new object that
- * will have the same effect but be a distinct object so that it can
- * also be attached without conflict.
- */
- public static CharacterStyle wrap(CharacterStyle cs) {
- if (cs instanceof MetricAffectingSpan) {
- return new MetricAffectingSpan.Passthrough((MetricAffectingSpan) cs);
- } else {
- return new Passthrough(cs);
- }
- }
-
- /**
- * Returns "this" for most CharacterStyles, but for CharacterStyles
- * that were generated by {@link #wrap}, returns the underlying
- * CharacterStyle.
- */
- public CharacterStyle getUnderlying() {
- return this;
- }
-
- /**
- * A Passthrough CharacterStyle is one that
- * passes {@link #updateDrawState} calls through to the
- * specified CharacterStyle while still being a distinct object,
- * and is therefore able to be attached to the same Spannable
- * to which the specified CharacterStyle is already attached.
- */
- private static class Passthrough extends CharacterStyle {
- private CharacterStyle mStyle;
-
- /**
- * Creates a new Passthrough of the specfied CharacterStyle.
- */
- public Passthrough(CharacterStyle cs) {
- mStyle = cs;
- }
-
- /**
- * Passes updateDrawState through to the underlying CharacterStyle.
- */
- @Override
- public void updateDrawState(TextPaint tp) {
- mStyle.updateDrawState(tp);
- }
-
- /**
- * Returns the CharacterStyle underlying this one, or the one
- * underlying it if it too is a Passthrough.
- */
- @Override
- public CharacterStyle getUnderlying() {
- return mStyle.getUnderlying();
- }
- }
-}
diff --git a/core/java/android/text/style/ClickableSpan.java b/core/java/android/text/style/ClickableSpan.java
deleted file mode 100644
index 989ef54..0000000
--- a/core/java/android/text/style/ClickableSpan.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.text.style;
-
-import android.text.TextPaint;
-import android.view.View;
-
-/**
- * If an object of this type is attached to the text of a TextView
- * with a movement method of LinkMovementMethod, the affected spans of
- * text can be selected. If clicked, the {@link #onClick} method will
- * be called.
- */
-public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance {
-
- /**
- * Performs the click action associated with this span.
- */
- public abstract void onClick(View widget);
-
- /**
- * Makes the text underlined and in the link color.
- */
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setColor(ds.linkColor);
- ds.setUnderlineText(true);
- }
-}
diff --git a/core/java/android/text/style/DrawableMarginSpan.java b/core/java/android/text/style/DrawableMarginSpan.java
deleted file mode 100644
index 3c471a5..0000000
--- a/core/java/android/text/style/DrawableMarginSpan.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.graphics.drawable.Drawable;
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.graphics.RectF;
-import android.text.Spanned;
-import android.text.Layout;
-
-public class DrawableMarginSpan
-implements LeadingMarginSpan, LineHeightSpan
-{
- public DrawableMarginSpan(Drawable b) {
- mDrawable = b;
- }
-
- public DrawableMarginSpan(Drawable b, int pad) {
- mDrawable = b;
- mPad = pad;
- }
-
- public int getLeadingMargin(boolean first) {
- return mDrawable.getIntrinsicWidth() + mPad;
- }
-
- public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- boolean first, Layout layout) {
- int st = ((Spanned) text).getSpanStart(this);
- int ix = (int)x;
- int itop = (int)layout.getLineTop(layout.getLineForOffset(st));
-
- int dw = mDrawable.getIntrinsicWidth();
- int dh = mDrawable.getIntrinsicHeight();
-
- if (dir < 0)
- x -= dw;
-
- // XXX What to do about Paint?
- mDrawable.setBounds(ix, itop, ix+dw, itop+dh);
- mDrawable.draw(c);
- }
-
- public void chooseHeight(CharSequence text, int start, int end,
- int istartv, int v,
- Paint.FontMetricsInt fm) {
- if (end == ((Spanned) text).getSpanEnd(this)) {
- int ht = mDrawable.getIntrinsicHeight();
-
- int need = ht - (v + fm.descent - fm.ascent - istartv);
- if (need > 0)
- fm.descent += need;
-
- need = ht - (v + fm.bottom - fm.top - istartv);
- if (need > 0)
- fm.bottom += need;
- }
- }
-
- private Drawable mDrawable;
- private int mPad;
-}
diff --git a/core/java/android/text/style/DynamicDrawableSpan.java b/core/java/android/text/style/DynamicDrawableSpan.java
deleted file mode 100644
index 89dc45b..0000000
--- a/core/java/android/text/style/DynamicDrawableSpan.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Paint.Style;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
-
-import java.lang.ref.WeakReference;
-
-/**
- *
- */
-public abstract class DynamicDrawableSpan extends ReplacementSpan {
- private static final String TAG = "DynamicDrawableSpan";
-
- /**
- * A constant indicating that the bottom of this span should be aligned
- * with the bottom of the surrounding text, i.e., at the same level as the
- * lowest descender in the text.
- */
- public static final int ALIGN_BOTTOM = 0;
-
- /**
- * A constant indicating that the bottom of this span should be aligned
- * with the baseline of the surrounding text.
- */
- public static final int ALIGN_BASELINE = 1;
-
- protected final int mVerticalAlignment;
-
- public DynamicDrawableSpan() {
- mVerticalAlignment = ALIGN_BOTTOM;
- }
-
- /**
- * @param verticalAlignment one of {@link #ALIGN_BOTTOM} or {@link #ALIGN_BASELINE}.
- */
- protected DynamicDrawableSpan(int verticalAlignment) {
- mVerticalAlignment = verticalAlignment;
- }
-
- /**
- * Returns the vertical alignment of this span, one of {@link #ALIGN_BOTTOM} or
- * {@link #ALIGN_BASELINE}.
- */
- public int getVerticalAlignment() {
- return mVerticalAlignment;
- }
-
- /**
- * Your subclass must implement this method to provide the bitmap
- * to be drawn. The dimensions of the bitmap must be the same
- * from each call to the next.
- */
- public abstract Drawable getDrawable();
-
- @Override
- public int getSize(Paint paint, CharSequence text,
- int start, int end,
- Paint.FontMetricsInt fm) {
- Drawable d = getCachedDrawable();
- Rect rect = d.getBounds();
-
- if (fm != null) {
- fm.ascent = -rect.bottom;
- fm.descent = 0;
-
- fm.top = fm.ascent;
- fm.bottom = 0;
- }
-
- return rect.right;
- }
-
- @Override
- public void draw(Canvas canvas, CharSequence text,
- int start, int end, float x,
- int top, int y, int bottom, Paint paint) {
- Drawable b = getCachedDrawable();
- canvas.save();
-
- int transY = bottom - b.getBounds().bottom;
- if (mVerticalAlignment == ALIGN_BASELINE) {
- transY -= paint.getFontMetricsInt().descent;
- }
-
- canvas.translate(x, transY);
- b.draw(canvas);
- canvas.restore();
- }
-
- private Drawable getCachedDrawable() {
- WeakReference<Drawable> wr = mDrawableRef;
- Drawable d = null;
-
- if (wr != null)
- d = wr.get();
-
- if (d == null) {
- d = getDrawable();
- mDrawableRef = new WeakReference<Drawable>(d);
- }
-
- return d;
- }
-
- private WeakReference<Drawable> mDrawableRef;
-}
-
diff --git a/core/java/android/text/style/ForegroundColorSpan.java b/core/java/android/text/style/ForegroundColorSpan.java
deleted file mode 100644
index 476124d..0000000
--- a/core/java/android/text/style/ForegroundColorSpan.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class ForegroundColorSpan extends CharacterStyle
- implements UpdateAppearance, ParcelableSpan {
-
- private final int mColor;
-
- public ForegroundColorSpan(int color) {
- mColor = color;
- }
-
- public ForegroundColorSpan(Parcel src) {
- mColor = src.readInt();
- }
-
- public int getSpanTypeId() {
- return TextUtils.FOREGROUND_COLOR_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mColor);
- }
-
- public int getForegroundColor() {
- return mColor;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setColor(mColor);
- }
-}
diff --git a/core/java/android/text/style/IconMarginSpan.java b/core/java/android/text/style/IconMarginSpan.java
deleted file mode 100644
index c786a17..0000000
--- a/core/java/android/text/style/IconMarginSpan.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.RectF;
-import android.text.Spanned;
-import android.text.Layout;
-
-public class IconMarginSpan
-implements LeadingMarginSpan, LineHeightSpan
-{
- public IconMarginSpan(Bitmap b) {
- mBitmap = b;
- }
-
- public IconMarginSpan(Bitmap b, int pad) {
- mBitmap = b;
- mPad = pad;
- }
-
- public int getLeadingMargin(boolean first) {
- return mBitmap.getWidth() + mPad;
- }
-
- public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- boolean first, Layout layout) {
- int st = ((Spanned) text).getSpanStart(this);
- int itop = layout.getLineTop(layout.getLineForOffset(st));
-
- if (dir < 0)
- x -= mBitmap.getWidth();
-
- c.drawBitmap(mBitmap, x, itop, p);
- }
-
- public void chooseHeight(CharSequence text, int start, int end,
- int istartv, int v,
- Paint.FontMetricsInt fm) {
- if (end == ((Spanned) text).getSpanEnd(this)) {
- int ht = mBitmap.getHeight();
-
- int need = ht - (v + fm.descent - fm.ascent - istartv);
- if (need > 0)
- fm.descent += need;
-
- need = ht - (v + fm.bottom - fm.top - istartv);
- if (need > 0)
- fm.bottom += need;
- }
- }
-
- private Bitmap mBitmap;
- private int mPad;
-}
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
deleted file mode 100644
index efb88a0..0000000
--- a/core/java/android/text/style/ImageSpan.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.util.Log;
-
-import java.io.InputStream;
-
-public class ImageSpan extends DynamicDrawableSpan {
- private Drawable mDrawable;
- private Uri mContentUri;
- private int mResourceId;
- private Context mContext;
- private String mSource;
-
- public ImageSpan(Bitmap b) {
- this(b, ALIGN_BOTTOM);
- }
-
- /**
- * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
- * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
- */
- public ImageSpan(Bitmap b, int verticalAlignment) {
- super(verticalAlignment);
- mDrawable = new BitmapDrawable(b);
- int width = mDrawable.getIntrinsicWidth();
- int height = mDrawable.getIntrinsicHeight();
- mDrawable.setBounds(0, 0, width > 0 ? width : 0, height > 0 ? height : 0);
- }
-
- public ImageSpan(Drawable d) {
- this(d, ALIGN_BOTTOM);
- }
-
- /**
- * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
- * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
- */
- public ImageSpan(Drawable d, int verticalAlignment) {
- super(verticalAlignment);
- mDrawable = d;
- }
-
- public ImageSpan(Drawable d, String source) {
- this(d, source, ALIGN_BOTTOM);
- }
-
- /**
- * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
- * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
- */
- public ImageSpan(Drawable d, String source, int verticalAlignment) {
- super(verticalAlignment);
- mDrawable = d;
- mSource = source;
- }
-
- public ImageSpan(Context context, Uri uri) {
- this(context, uri, ALIGN_BOTTOM);
- }
-
- /**
- * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
- * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
- */
- public ImageSpan(Context context, Uri uri, int verticalAlignment) {
- super(verticalAlignment);
- mContext = context;
- mContentUri = uri;
- }
-
- public ImageSpan(Context context, int resourceId) {
- this(context, resourceId, ALIGN_BOTTOM);
- }
-
- /**
- * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
- * {@link DynamicDrawableSpan#ALIGN_BASELINE}.
- */
- public ImageSpan(Context context, int resourceId, int verticalAlignment) {
- super(verticalAlignment);
- mContext = context;
- mResourceId = resourceId;
- }
-
- @Override
- public Drawable getDrawable() {
- Drawable drawable = null;
-
- if (mDrawable != null) {
- drawable = mDrawable;
- } else if (mContentUri != null) {
- Bitmap bitmap = null;
- try {
- InputStream is = mContext.getContentResolver().openInputStream(
- mContentUri);
- bitmap = BitmapFactory.decodeStream(is);
- drawable = new BitmapDrawable(bitmap);
- is.close();
- } catch (Exception e) {
- Log.e("sms", "Failed to loaded content " + mContentUri, e);
- }
- } else {
- try {
- drawable = mContext.getResources().getDrawable(mResourceId);
- drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
- drawable.getIntrinsicHeight());
- } catch (Exception e) {
- Log.e("sms", "Unable to find resource: " + mResourceId);
- }
- }
-
- return drawable;
- }
-
- /**
- * Returns the source string that was saved during construction.
- */
- public String getSource() {
- return mSource;
- }
-
-}
diff --git a/core/java/android/text/style/LeadingMarginSpan.java b/core/java/android/text/style/LeadingMarginSpan.java
deleted file mode 100644
index 8e212e3..0000000
--- a/core/java/android/text/style/LeadingMarginSpan.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.os.Parcel;
-import android.text.Layout;
-import android.text.ParcelableSpan;
-import android.text.TextUtils;
-
-public interface LeadingMarginSpan
-extends ParagraphStyle
-{
- public int getLeadingMargin(boolean first);
- public void drawLeadingMargin(Canvas c, Paint p,
- int x, int dir,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- boolean first, Layout layout);
-
- public static class Standard implements LeadingMarginSpan, ParcelableSpan {
- private final int mFirst, mRest;
-
- public Standard(int first, int rest) {
- mFirst = first;
- mRest = rest;
- }
-
- public Standard(int every) {
- this(every, every);
- }
-
- public Standard(Parcel src) {
- mFirst = src.readInt();
- mRest = src.readInt();
- }
-
- public int getSpanTypeId() {
- return TextUtils.LEADING_MARGIN_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mFirst);
- dest.writeInt(mRest);
- }
-
- public int getLeadingMargin(boolean first) {
- return first ? mFirst : mRest;
- }
-
- public void drawLeadingMargin(Canvas c, Paint p,
- int x, int dir,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- boolean first, Layout layout) {
- ;
- }
- }
-}
diff --git a/core/java/android/text/style/LineBackgroundSpan.java b/core/java/android/text/style/LineBackgroundSpan.java
deleted file mode 100644
index 854aeaf..0000000
--- a/core/java/android/text/style/LineBackgroundSpan.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Canvas;
-
-public interface LineBackgroundSpan
-extends ParagraphStyle
-{
- public void drawBackground(Canvas c, Paint p,
- int left, int right,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- int lnum);
-}
diff --git a/core/java/android/text/style/LineHeightSpan.java b/core/java/android/text/style/LineHeightSpan.java
deleted file mode 100644
index c0ef97c..0000000
--- a/core/java/android/text/style/LineHeightSpan.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.text.Layout;
-
-public interface LineHeightSpan
-extends ParagraphStyle, WrapTogetherSpan
-{
- public void chooseHeight(CharSequence text, int start, int end,
- int spanstartv, int v,
- Paint.FontMetricsInt fm);
-}
diff --git a/core/java/android/text/style/MaskFilterSpan.java b/core/java/android/text/style/MaskFilterSpan.java
deleted file mode 100644
index 64ab0d8..0000000
--- a/core/java/android/text/style/MaskFilterSpan.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.graphics.MaskFilter;
-import android.text.TextPaint;
-
-public class MaskFilterSpan extends CharacterStyle implements UpdateAppearance {
-
- private MaskFilter mFilter;
-
- public MaskFilterSpan(MaskFilter filter) {
- mFilter = filter;
- }
-
- public MaskFilter getMaskFilter() {
- return mFilter;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setMaskFilter(mFilter);
- }
-}
diff --git a/core/java/android/text/style/MetricAffectingSpan.java b/core/java/android/text/style/MetricAffectingSpan.java
deleted file mode 100644
index 92558eb..0000000
--- a/core/java/android/text/style/MetricAffectingSpan.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.graphics.Paint;
-import android.text.TextPaint;
-
-/**
- * The classes that affect character-level text formatting in a way that
- * changes the width or height of characters extend this class.
- */
-public abstract class MetricAffectingSpan
-extends CharacterStyle
-implements UpdateLayout {
-
- public abstract void updateMeasureState(TextPaint p);
-
- /**
- * Returns "this" for most MetricAffectingSpans, but for
- * MetricAffectingSpans that were generated by {@link #wrap},
- * returns the underlying MetricAffectingSpan.
- */
- @Override
- public MetricAffectingSpan getUnderlying() {
- return this;
- }
-
- /**
- * A Passthrough MetricAffectingSpan is one that
- * passes {@link #updateDrawState} and {@link #updateMeasureState}
- * calls through to the specified MetricAffectingSpan
- * while still being a distinct object,
- * and is therefore able to be attached to the same Spannable
- * to which the specified MetricAffectingSpan is already attached.
- */
- /* package */ static class Passthrough extends MetricAffectingSpan {
- private MetricAffectingSpan mStyle;
-
- /**
- * Creates a new Passthrough of the specfied MetricAffectingSpan.
- */
- public Passthrough(MetricAffectingSpan cs) {
- mStyle = cs;
- }
-
- /**
- * Passes updateDrawState through to the underlying MetricAffectingSpan.
- */
- @Override
- public void updateDrawState(TextPaint tp) {
- mStyle.updateDrawState(tp);
- }
-
- /**
- * Passes updateMeasureState through to the underlying MetricAffectingSpan.
- */
- @Override
- public void updateMeasureState(TextPaint tp) {
- mStyle.updateMeasureState(tp);
- }
-
- /**
- * Returns the MetricAffectingSpan underlying this one, or the one
- * underlying it if it too is a Passthrough.
- */
- @Override
- public MetricAffectingSpan getUnderlying() {
- return mStyle.getUnderlying();
- }
- }
-}
diff --git a/core/java/android/text/style/ParagraphStyle.java b/core/java/android/text/style/ParagraphStyle.java
deleted file mode 100644
index 423156e..0000000
--- a/core/java/android/text/style/ParagraphStyle.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-/**
- * The classes that affect paragraph-level text formatting implement
- * this interface.
- */
-public interface ParagraphStyle
-{
-
-}
diff --git a/core/java/android/text/style/QuoteSpan.java b/core/java/android/text/style/QuoteSpan.java
deleted file mode 100644
index 29dd273..0000000
--- a/core/java/android/text/style/QuoteSpan.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.os.Parcel;
-import android.text.Layout;
-import android.text.ParcelableSpan;
-import android.text.TextUtils;
-
-public class QuoteSpan implements LeadingMarginSpan, ParcelableSpan {
- private static final int STRIPE_WIDTH = 2;
- private static final int GAP_WIDTH = 2;
-
- private final int mColor;
-
- public QuoteSpan() {
- super();
- mColor = 0xff0000ff;
- }
-
- public QuoteSpan(int color) {
- super();
- mColor = color;
- }
-
- public QuoteSpan(Parcel src) {
- mColor = src.readInt();
- }
-
- public int getSpanTypeId() {
- return TextUtils.QUOTE_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mColor);
- }
-
- public int getColor() {
- return mColor;
- }
-
- public int getLeadingMargin(boolean first) {
- return STRIPE_WIDTH + GAP_WIDTH;
- }
-
- public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
- int top, int baseline, int bottom,
- CharSequence text, int start, int end,
- boolean first, Layout layout) {
- Paint.Style style = p.getStyle();
- int color = p.getColor();
-
- p.setStyle(Paint.Style.FILL);
- p.setColor(mColor);
-
- c.drawRect(x, top, x + dir * STRIPE_WIDTH, bottom, p);
-
- p.setStyle(style);
- p.setColor(color);
- }
-}
diff --git a/core/java/android/text/style/RasterizerSpan.java b/core/java/android/text/style/RasterizerSpan.java
deleted file mode 100644
index 75b5bcc..0000000
--- a/core/java/android/text/style/RasterizerSpan.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.text.style;
-
-import android.graphics.Rasterizer;
-import android.text.TextPaint;
-
-public class RasterizerSpan extends CharacterStyle implements UpdateAppearance {
-
- private Rasterizer mRasterizer;
-
- public RasterizerSpan(Rasterizer r) {
- mRasterizer = r;
- }
-
- public Rasterizer getRasterizer() {
- return mRasterizer;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setRasterizer(mRasterizer);
- }
-}
diff --git a/core/java/android/text/style/RelativeSizeSpan.java b/core/java/android/text/style/RelativeSizeSpan.java
deleted file mode 100644
index 9717362..0000000
--- a/core/java/android/text/style/RelativeSizeSpan.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class RelativeSizeSpan extends MetricAffectingSpan implements ParcelableSpan {
-
- private final float mProportion;
-
- public RelativeSizeSpan(float proportion) {
- mProportion = proportion;
- }
-
- public RelativeSizeSpan(Parcel src) {
- mProportion = src.readFloat();
- }
-
- public int getSpanTypeId() {
- return TextUtils.RELATIVE_SIZE_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeFloat(mProportion);
- }
-
- public float getSizeChange() {
- return mProportion;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setTextSize(ds.getTextSize() * mProportion);
- }
-
- @Override
- public void updateMeasureState(TextPaint ds) {
- ds.setTextSize(ds.getTextSize() * mProportion);
- }
-}
diff --git a/core/java/android/text/style/ReplacementSpan.java b/core/java/android/text/style/ReplacementSpan.java
deleted file mode 100644
index 26c725f..0000000
--- a/core/java/android/text/style/ReplacementSpan.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.text.TextPaint;
-
-public abstract class ReplacementSpan extends MetricAffectingSpan {
-
- public abstract int getSize(Paint paint, CharSequence text,
- int start, int end,
- Paint.FontMetricsInt fm);
- public abstract void draw(Canvas canvas, CharSequence text,
- int start, int end, float x,
- int top, int y, int bottom, Paint paint);
-
- /**
- * This method does nothing, since ReplacementSpans are measured
- * explicitly instead of affecting Paint properties.
- */
- public void updateMeasureState(TextPaint p) { }
-
- /**
- * This method does nothing, since ReplacementSpans are drawn
- * explicitly instead of affecting Paint properties.
- */
- public void updateDrawState(TextPaint ds) { }
-}
diff --git a/core/java/android/text/style/ScaleXSpan.java b/core/java/android/text/style/ScaleXSpan.java
deleted file mode 100644
index 655064b..0000000
--- a/core/java/android/text/style/ScaleXSpan.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class ScaleXSpan extends MetricAffectingSpan implements ParcelableSpan {
-
- private final float mProportion;
-
- public ScaleXSpan(float proportion) {
- mProportion = proportion;
- }
-
- public ScaleXSpan(Parcel src) {
- mProportion = src.readFloat();
- }
-
- public int getSpanTypeId() {
- return TextUtils.SCALE_X_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeFloat(mProportion);
- }
-
- public float getScaleX() {
- return mProportion;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setTextScaleX(ds.getTextScaleX() * mProportion);
- }
-
- @Override
- public void updateMeasureState(TextPaint ds) {
- ds.setTextScaleX(ds.getTextScaleX() * mProportion);
- }
-}
diff --git a/core/java/android/text/style/StrikethroughSpan.java b/core/java/android/text/style/StrikethroughSpan.java
deleted file mode 100644
index b51363a..0000000
--- a/core/java/android/text/style/StrikethroughSpan.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class StrikethroughSpan extends CharacterStyle
- implements UpdateAppearance, ParcelableSpan {
- public StrikethroughSpan() {
- }
-
- public StrikethroughSpan(Parcel src) {
- }
-
- public int getSpanTypeId() {
- return TextUtils.STRIKETHROUGH_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setStrikeThruText(true);
- }
-}
diff --git a/core/java/android/text/style/StyleSpan.java b/core/java/android/text/style/StyleSpan.java
deleted file mode 100644
index 8e6147c..0000000
--- a/core/java/android/text/style/StyleSpan.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Typeface;
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-/**
- *
- * Describes a style in a span.
- * Note that styles are cumulative -- if both bold and italic are set in
- * separate spans, or if the base style is bold and a span calls for italic,
- * you get bold italic. You can't turn off a style from the base style.
- *
- */
-public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan {
-
- private final int mStyle;
-
- /**
- *
- * @param style An integer constant describing the style for this span. Examples
- * include bold, italic, and normal. Values are constants defined
- * in {@link android.graphics.Typeface}.
- */
- public StyleSpan(int style) {
- mStyle = style;
- }
-
- public StyleSpan(Parcel src) {
- mStyle = src.readInt();
- }
-
- public int getSpanTypeId() {
- return TextUtils.STYLE_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mStyle);
- }
-
- /**
- * Returns the style constant defined in {@link android.graphics.Typeface}.
- */
- public int getStyle() {
- return mStyle;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- apply(ds, mStyle);
- }
-
- @Override
- public void updateMeasureState(TextPaint paint) {
- apply(paint, mStyle);
- }
-
- private static void apply(Paint paint, int style) {
- int oldStyle;
-
- Typeface old = paint.getTypeface();
- if (old == null) {
- oldStyle = 0;
- } else {
- oldStyle = old.getStyle();
- }
-
- int want = oldStyle | style;
-
- Typeface tf;
- if (old == null) {
- tf = Typeface.defaultFromStyle(want);
- } else {
- tf = Typeface.create(old, want);
- }
-
- int fake = want & ~tf.getStyle();
-
- if ((fake & Typeface.BOLD) != 0) {
- paint.setFakeBoldText(true);
- }
-
- if ((fake & Typeface.ITALIC) != 0) {
- paint.setTextSkewX(-0.25f);
- }
-
- paint.setTypeface(tf);
- }
-}
diff --git a/core/java/android/text/style/SubscriptSpan.java b/core/java/android/text/style/SubscriptSpan.java
deleted file mode 100644
index de1d8b2..0000000
--- a/core/java/android/text/style/SubscriptSpan.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class SubscriptSpan extends MetricAffectingSpan implements ParcelableSpan {
- public SubscriptSpan() {
- }
-
- public SubscriptSpan(Parcel src) {
- }
-
- public int getSpanTypeId() {
- return TextUtils.SUBSCRIPT_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- }
-
- @Override
- public void updateDrawState(TextPaint tp) {
- tp.baselineShift -= (int) (tp.ascent() / 2);
- }
-
- @Override
- public void updateMeasureState(TextPaint tp) {
- tp.baselineShift -= (int) (tp.ascent() / 2);
- }
-}
diff --git a/core/java/android/text/style/SuperscriptSpan.java b/core/java/android/text/style/SuperscriptSpan.java
deleted file mode 100644
index 285fe84..0000000
--- a/core/java/android/text/style/SuperscriptSpan.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class SuperscriptSpan extends MetricAffectingSpan implements ParcelableSpan {
- public SuperscriptSpan() {
- }
-
- public SuperscriptSpan(Parcel src) {
- }
-
- public int getSpanTypeId() {
- return TextUtils.SUPERSCRIPT_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- }
-
- @Override
- public void updateDrawState(TextPaint tp) {
- tp.baselineShift += (int) (tp.ascent() / 2);
- }
-
- @Override
- public void updateMeasureState(TextPaint tp) {
- tp.baselineShift += (int) (tp.ascent() / 2);
- }
-}
diff --git a/core/java/android/text/style/TabStopSpan.java b/core/java/android/text/style/TabStopSpan.java
deleted file mode 100644
index e5b7644..0000000
--- a/core/java/android/text/style/TabStopSpan.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-public interface TabStopSpan
-extends ParagraphStyle
-{
- public int getTabStop();
-
- public static class Standard
- implements TabStopSpan
- {
- public Standard(int where) {
- mTab = where;
- }
-
- public int getTabStop() {
- return mTab;
- }
-
- private int mTab;
- }
-}
diff --git a/core/java/android/text/style/TextAppearanceSpan.java b/core/java/android/text/style/TextAppearanceSpan.java
deleted file mode 100644
index de929e3..0000000
--- a/core/java/android/text/style/TextAppearanceSpan.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.text.style;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.TypedArray;
-import android.graphics.Typeface;
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-/**
- * Sets the text color, size, style, and typeface to match a TextAppearance
- * resource.
- */
-public class TextAppearanceSpan extends MetricAffectingSpan implements ParcelableSpan {
- private final String mTypeface;
- private final int mStyle;
- private final int mTextSize;
- private final ColorStateList mTextColor;
- private final ColorStateList mTextColorLink;
-
- /**
- * Uses the specified TextAppearance resource to determine the
- * text appearance. The <code>appearance</code> should be, for example,
- * <code>android.R.style.TextAppearance_Small</code>.
- */
- public TextAppearanceSpan(Context context, int appearance) {
- this(context, appearance, -1);
- }
-
- /**
- * Uses the specified TextAppearance resource to determine the
- * text appearance, and the specified text color resource
- * to determine the color. The <code>appearance</code> should be,
- * for example, <code>android.R.style.TextAppearance_Small</code>,
- * and the <code>colorList</code> should be, for example,
- * <code>android.R.styleable.Theme_textColorDim</code>.
- */
- public TextAppearanceSpan(Context context, int appearance,
- int colorList) {
- ColorStateList textColor;
-
- TypedArray a =
- context.obtainStyledAttributes(appearance,
- com.android.internal.R.styleable.TextAppearance);
-
- textColor = a.getColorStateList(com.android.internal.R.styleable.
- TextAppearance_textColor);
- mTextColorLink = a.getColorStateList(com.android.internal.R.styleable.
- TextAppearance_textColorLink);
- mTextSize = a.getDimensionPixelSize(com.android.internal.R.styleable.
- TextAppearance_textSize, -1);
-
- mStyle = a.getInt(com.android.internal.R.styleable.TextAppearance_textStyle, 0);
- int tf = a.getInt(com.android.internal.R.styleable.TextAppearance_typeface, 0);
-
- switch (tf) {
- case 1:
- mTypeface = "sans";
- break;
-
- case 2:
- mTypeface = "serif";
- break;
-
- case 3:
- mTypeface = "monospace";
- break;
-
- default:
- mTypeface = null;
- break;
- }
-
- a.recycle();
-
- if (colorList >= 0) {
- a = context.obtainStyledAttributes(com.android.internal.R.style.Theme,
- com.android.internal.R.styleable.Theme);
-
- textColor = a.getColorStateList(colorList);
- a.recycle();
- }
-
- mTextColor = textColor;
- }
-
- /**
- * Makes text be drawn with the specified typeface, size, style,
- * and colors.
- */
- public TextAppearanceSpan(String family, int style, int size,
- ColorStateList color, ColorStateList linkColor) {
- mTypeface = family;
- mStyle = style;
- mTextSize = size;
- mTextColor = color;
- mTextColorLink = linkColor;
- }
-
- public TextAppearanceSpan(Parcel src) {
- mTypeface = src.readString();
- mStyle = src.readInt();
- mTextSize = src.readInt();
- if (src.readInt() != 0) {
- mTextColor = ColorStateList.CREATOR.createFromParcel(src);
- } else {
- mTextColor = null;
- }
- if (src.readInt() != 0) {
- mTextColorLink = ColorStateList.CREATOR.createFromParcel(src);
- } else {
- mTextColorLink = null;
- }
- }
-
- public int getSpanTypeId() {
- return TextUtils.TEXT_APPEARANCE_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mTypeface);
- dest.writeInt(mStyle);
- dest.writeInt(mTextSize);
- if (mTextColor != null) {
- dest.writeInt(1);
- mTextColor.writeToParcel(dest, flags);
- } else {
- dest.writeInt(0);
- }
- if (mTextColorLink != null) {
- dest.writeInt(1);
- mTextColorLink.writeToParcel(dest, flags);
- } else {
- dest.writeInt(0);
- }
- }
-
- /**
- * Returns the typeface family specified by this span, or <code>null</code>
- * if it does not specify one.
- */
- public String getFamily() {
- return mTypeface;
- }
-
- /**
- * Returns the text color specified by this span, or <code>null</code>
- * if it does not specify one.
- */
- public ColorStateList getTextColor() {
- return mTextColor;
- }
-
- /**
- * Returns the link color specified by this span, or <code>null</code>
- * if it does not specify one.
- */
- public ColorStateList getLinkTextColor() {
- return mTextColorLink;
- }
-
- /**
- * Returns the text size specified by this span, or <code>-1</code>
- * if it does not specify one.
- */
- public int getTextSize() {
- return mTextSize;
- }
-
- /**
- * Returns the text style specified by this span, or <code>0</code>
- * if it does not specify one.
- */
- public int getTextStyle() {
- return mStyle;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- updateMeasureState(ds);
-
- if (mTextColor != null) {
- ds.setColor(mTextColor.getColorForState(ds.drawableState, 0));
- }
-
- if (mTextColorLink != null) {
- ds.linkColor = mTextColor.getColorForState(ds.drawableState, 0);
- }
- }
-
- @Override
- public void updateMeasureState(TextPaint ds) {
- if (mTypeface != null || mStyle != 0) {
- Typeface tf = ds.getTypeface();
- int style = 0;
-
- if (tf != null) {
- style = tf.getStyle();
- }
-
- style |= mStyle;
-
- if (mTypeface != null) {
- tf = Typeface.create(mTypeface, style);
- } else if (tf == null) {
- tf = Typeface.defaultFromStyle(style);
- } else {
- tf = Typeface.create(tf, style);
- }
-
- int fake = style & ~tf.getStyle();
-
- if ((fake & Typeface.BOLD) != 0) {
- ds.setFakeBoldText(true);
- }
-
- if ((fake & Typeface.ITALIC) != 0) {
- ds.setTextSkewX(-0.25f);
- }
-
- ds.setTypeface(tf);
- }
-
- if (mTextSize > 0) {
- ds.setTextSize(mTextSize);
- }
- }
-}
diff --git a/core/java/android/text/style/TypefaceSpan.java b/core/java/android/text/style/TypefaceSpan.java
deleted file mode 100644
index f194060..0000000
--- a/core/java/android/text/style/TypefaceSpan.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.graphics.Paint;
-import android.graphics.Typeface;
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-/**
- * Changes the typeface family of the text to which the span is attached.
- */
-public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan {
- private final String mFamily;
-
- /**
- * @param family The font family for this typeface. Examples include
- * "monospace", "serif", and "sans-serif".
- */
- public TypefaceSpan(String family) {
- mFamily = family;
- }
-
- public TypefaceSpan(Parcel src) {
- mFamily = src.readString();
- }
-
- public int getSpanTypeId() {
- return TextUtils.TYPEFACE_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mFamily);
- }
-
- /**
- * Returns the font family name.
- */
- public String getFamily() {
- return mFamily;
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- apply(ds, mFamily);
- }
-
- @Override
- public void updateMeasureState(TextPaint paint) {
- apply(paint, mFamily);
- }
-
- private static void apply(Paint paint, String family) {
- int oldStyle;
-
- Typeface old = paint.getTypeface();
- if (old == null) {
- oldStyle = 0;
- } else {
- oldStyle = old.getStyle();
- }
-
- Typeface tf = Typeface.create(family, oldStyle);
- int fake = oldStyle & ~tf.getStyle();
-
- if ((fake & Typeface.BOLD) != 0) {
- paint.setFakeBoldText(true);
- }
-
- if ((fake & Typeface.ITALIC) != 0) {
- paint.setTextSkewX(-0.25f);
- }
-
- paint.setTypeface(tf);
- }
-}
diff --git a/core/java/android/text/style/URLSpan.java b/core/java/android/text/style/URLSpan.java
deleted file mode 100644
index f458611..0000000
--- a/core/java/android/text/style/URLSpan.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextUtils;
-import android.view.View;
-
-public class URLSpan extends ClickableSpan implements ParcelableSpan {
-
- private final String mURL;
-
- public URLSpan(String url) {
- mURL = url;
- }
-
- public URLSpan(Parcel src) {
- mURL = src.readString();
- }
-
- public int getSpanTypeId() {
- return TextUtils.URL_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mURL);
- }
-
- public String getURL() {
- return mURL;
- }
-
- @Override
- public void onClick(View widget) {
- Uri uri = Uri.parse(getURL());
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- intent.addCategory(Intent.CATEGORY_BROWSABLE);
- widget.getContext().startActivity(intent);
- }
-}
diff --git a/core/java/android/text/style/UnderlineSpan.java b/core/java/android/text/style/UnderlineSpan.java
deleted file mode 100644
index b0cb0e8..0000000
--- a/core/java/android/text/style/UnderlineSpan.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-import android.os.Parcel;
-import android.text.ParcelableSpan;
-import android.text.TextPaint;
-import android.text.TextUtils;
-
-public class UnderlineSpan extends CharacterStyle
- implements UpdateAppearance, ParcelableSpan {
- public UnderlineSpan() {
- }
-
- public UnderlineSpan(Parcel src) {
- }
-
- public int getSpanTypeId() {
- return TextUtils.UNDERLINE_SPAN;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- }
-
- @Override
- public void updateDrawState(TextPaint ds) {
- ds.setUnderlineText(true);
- }
-}
diff --git a/core/java/android/text/style/UpdateAppearance.java b/core/java/android/text/style/UpdateAppearance.java
deleted file mode 100644
index 198e4fa..0000000
--- a/core/java/android/text/style/UpdateAppearance.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package android.text.style;
-
-/**
- * The classes that affect character-level text in a way that modifies their
- * appearance when one is added or removed must implement this interface. Note
- * that if the class also impacts size or other metrics, it should instead
- * implement {@link UpdateLayout}.
- */
-public interface UpdateAppearance {
-}
diff --git a/core/java/android/text/style/UpdateLayout.java b/core/java/android/text/style/UpdateLayout.java
deleted file mode 100644
index 591075e..0000000
--- a/core/java/android/text/style/UpdateLayout.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-/**
- * The classes that affect character-level text formatting in a way that
- * triggers a text layout update when one is added or removed must implement
- * this interface. This interface also includes {@link UpdateAppearance}
- * since such a change implicitly also impacts the appearance.
- */
-public interface UpdateLayout extends UpdateAppearance { }
diff --git a/core/java/android/text/style/WrapTogetherSpan.java b/core/java/android/text/style/WrapTogetherSpan.java
deleted file mode 100644
index 11721a8..0000000
--- a/core/java/android/text/style/WrapTogetherSpan.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.text.style;
-
-public interface WrapTogetherSpan
-extends ParagraphStyle
-{
-
-}
diff --git a/core/java/android/text/style/package.html b/core/java/android/text/style/package.html
deleted file mode 100644
index 0a8520c..0000000
--- a/core/java/android/text/style/package.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<html>
-<body>
-
-<p>Provides classes used to view or change the style of a span of text in a View object.
-The classes with a subclass Standard are passed in to {@link android.text.SpannableString#setSpan(java.lang.Object, int, int, int)
-SpannableString.setSpan()} or {@link android.text.SpannableStringBuilder#setSpan(java.lang.Object, int, int, int)
-SpannableStringBuilder.setSpan()} to add a new styled span to a string in a View object.
-
-</body>
-</html>
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
deleted file mode 100644
index d61e888..0000000
--- a/core/java/android/text/util/Linkify.java
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.text.util;
-
-import android.text.method.LinkMovementMethod;
-import android.text.method.MovementMethod;
-import android.text.style.URLSpan;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.Spanned;
-import android.webkit.WebView;
-import android.widget.TextView;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Linkify take a piece of text and a regular expression and turns all of the
- * regex matches in the text into clickable links. This is particularly
- * useful for matching things like email addresses, web urls, etc. and making
- * them actionable.
- *
- * Alone with the pattern that is to be matched, a url scheme prefix is also
- * required. Any pattern match that does not begin with the supplied scheme
- * will have the scheme prepended to the matched text when the clickable url
- * is created. For instance, if you are matching web urls you would supply
- * the scheme <code>http://</code>. If the pattern matches example.com, which
- * does not have a url scheme prefix, the supplied scheme will be prepended to
- * create <code>http://example.com</code> when the clickable url link is
- * created.
- */
-
-public class Linkify {
- /**
- * Bit field indicating that web URLs should be matched in methods that
- * take an options mask
- */
- public static final int WEB_URLS = 0x01;
-
- /**
- * Bit field indicating that email addresses should be matched in methods
- * that take an options mask
- */
- public static final int EMAIL_ADDRESSES = 0x02;
-
- /**
- * Bit field indicating that phone numbers should be matched in methods that
- * take an options mask
- */
- public static final int PHONE_NUMBERS = 0x04;
-
- /**
- * Bit field indicating that street addresses should be matched in methods that
- * take an options mask
- */
- public static final int MAP_ADDRESSES = 0x08;
-
- /**
- * Bit mask indicating that all available patterns should be matched in
- * methods that take an options mask
- */
- public static final int ALL = WEB_URLS | EMAIL_ADDRESSES | PHONE_NUMBERS | MAP_ADDRESSES;
-
- /**
- * Don't treat anything with fewer than this many digits as a
- * phone number.
- */
- private static final int PHONE_NUMBER_MINIMUM_DIGITS = 5;
-
- /**
- * Filters out web URL matches that occur after an at-sign (@). This is
- * to prevent turning the domain name in an email address into a web link.
- */
- public static final MatchFilter sUrlMatchFilter = new MatchFilter() {
- public final boolean acceptMatch(CharSequence s, int start, int end) {
- if (start == 0) {
- return true;
- }
-
- if (s.charAt(start - 1) == '@') {
- return false;
- }
-
- return true;
- }
- };
-
- /**
- * Filters out URL matches that don't have enough digits to be a
- * phone number.
- */
- public static final MatchFilter sPhoneNumberMatchFilter = new MatchFilter() {
- public final boolean acceptMatch(CharSequence s, int start, int end) {
- int digitCount = 0;
-
- for (int i = start; i < end; i++) {
- if (Character.isDigit(s.charAt(i))) {
- digitCount++;
- if (digitCount >= PHONE_NUMBER_MINIMUM_DIGITS) {
- return true;
- }
- }
- }
- return false;
- }
- };
-
- /**
- * Transforms matched phone number text into something suitable
- * to be used in a tel: URL. It does this by removing everything
- * but the digits and plus signs. For instance:
- * &apos;+1 (919) 555-1212&apos;
- * becomes &apos;+19195551212&apos;
- */
- public static final TransformFilter sPhoneNumberTransformFilter = new TransformFilter() {
- public final String transformUrl(final Matcher match, String url) {
- return Regex.digitsAndPlusOnly(match);
- }
- };
-
- /**
- * MatchFilter enables client code to have more control over
- * what is allowed to match and become a link, and what is not.
- *
- * For example: when matching web urls you would like things like
- * http://www.example.com to match, as well as just example.com itelf.
- * However, you would not want to match against the domain in
- * support@example.com. So, when matching against a web url pattern you
- * might also include a MatchFilter that disallows the match if it is
- * immediately preceded by an at-sign (@).
- */
- public interface MatchFilter {
- /**
- * Examines the character span matched by the pattern and determines
- * if the match should be turned into an actionable link.
- *
- * @param s The body of text against which the pattern
- * was matched
- * @param start The index of the first character in s that was
- * matched by the pattern - inclusive
- * @param end The index of the last character in s that was
- * matched - exclusive
- *
- * @return Whether this match should be turned into a link
- */
- boolean acceptMatch(CharSequence s, int start, int end);
- }
-
- /**
- * TransformFilter enables client code to have more control over
- * how matched patterns are represented as URLs.
- *
- * For example: when converting a phone number such as (919) 555-1212
- * into a tel: URL the parentheses, white space, and hyphen need to be
- * removed to produce tel:9195551212.
- */
- public interface TransformFilter {
- /**
- * Examines the matched text and either passes it through or uses the
- * data in the Matcher state to produce a replacement.
- *
- * @param match The regex matcher state that found this URL text
- * @param url The text that was matched
- *
- * @return The transformed form of the URL
- */
- String transformUrl(final Matcher match, String url);
- }
-
- /**
- * Scans the text of the provided Spannable and turns all occurrences
- * of the link types indicated in the mask into clickable links.
- * If the mask is nonzero, it also removes any existing URLSpans
- * attached to the Spannable, to avoid problems if you call it
- * repeatedly on the same text.
- */
- public static final boolean addLinks(Spannable text, int mask) {
- if (mask == 0) {
- return false;
- }
-
- URLSpan[] old = text.getSpans(0, text.length(), URLSpan.class);
-
- for (int i = old.length - 1; i >= 0; i--) {
- text.removeSpan(old[i]);
- }
-
- ArrayList<LinkSpec> links = new ArrayList<LinkSpec>();
-
- if ((mask & WEB_URLS) != 0) {
- gatherLinks(links, text, Regex.WEB_URL_PATTERN,
- new String[] { "http://", "https://" },
- sUrlMatchFilter, null);
- }
-
- if ((mask & EMAIL_ADDRESSES) != 0) {
- gatherLinks(links, text, Regex.EMAIL_ADDRESS_PATTERN,
- new String[] { "mailto:" },
- null, null);
- }
-
- if ((mask & PHONE_NUMBERS) != 0) {
- gatherLinks(links, text, Regex.PHONE_PATTERN,
- new String[] { "tel:" },
- sPhoneNumberMatchFilter, sPhoneNumberTransformFilter);
- }
-
- if ((mask & MAP_ADDRESSES) != 0) {
- gatherMapLinks(links, text);
- }
-
- pruneOverlaps(links);
-
- if (links.size() == 0) {
- return false;
- }
-
- for (LinkSpec link: links) {
- applyLink(link.url, link.start, link.end, text);
- }
-
- return true;
- }
-
- /**
- * Scans the text of the provided TextView and turns all occurrences of
- * the link types indicated in the mask into clickable links. If matches
- * are found the movement method for the TextView is set to
- * LinkMovementMethod.
- */
- public static final boolean addLinks(TextView text, int mask) {
- if (mask == 0) {
- return false;
- }
-
- CharSequence t = text.getText();
-
- if (t instanceof Spannable) {
- if (addLinks((Spannable) t, mask)) {
- addLinkMovementMethod(text);
- return true;
- }
-
- return false;
- } else {
- SpannableString s = SpannableString.valueOf(t);
-
- if (addLinks(s, mask)) {
- addLinkMovementMethod(text);
- text.setText(s);
-
- return true;
- }
-
- return false;
- }
- }
-
- private static final void addLinkMovementMethod(TextView t) {
- MovementMethod m = t.getMovementMethod();
-
- if ((m == null) || !(m instanceof LinkMovementMethod)) {
- if (t.getLinksClickable()) {
- t.setMovementMethod(LinkMovementMethod.getInstance());
- }
- }
- }
-
- /**
- * Applies a regex to the text of a TextView turning the matches into
- * links. If links are found then UrlSpans are applied to the link
- * text match areas, and the movement method for the text is changed
- * to LinkMovementMethod.
- *
- * @param text TextView whose text is to be marked-up with links
- * @param pattern Regex pattern to be used for finding links
- * @param scheme Url scheme string (eg <code>http://</code> to be
- * prepended to the url of links that do not have
- * a scheme specified in the link text
- */
- public static final void addLinks(TextView text, Pattern pattern, String scheme) {
- addLinks(text, pattern, scheme, null, null);
- }
-
- /**
- * Applies a regex to the text of a TextView turning the matches into
- * links. If links are found then UrlSpans are applied to the link
- * text match areas, and the movement method for the text is changed
- * to LinkMovementMethod.
- *
- * @param text TextView whose text is to be marked-up with links
- * @param p Regex pattern to be used for finding links
- * @param scheme Url scheme string (eg <code>http://</code> to be
- * prepended to the url of links that do not have
- * a scheme specified in the link text
- * @param matchFilter The filter that is used to allow the client code
- * additional control over which pattern matches are
- * to be converted into links.
- */
- public static final void addLinks(TextView text, Pattern p, String scheme,
- MatchFilter matchFilter, TransformFilter transformFilter) {
- SpannableString s = SpannableString.valueOf(text.getText());
-
- if (addLinks(s, p, scheme, matchFilter, transformFilter)) {
- text.setText(s);
- addLinkMovementMethod(text);
- }
- }
-
- /**
- * Applies a regex to a Spannable turning the matches into
- * links.
- *
- * @param text Spannable whose text is to be marked-up with
- * links
- * @param pattern Regex pattern to be used for finding links
- * @param scheme Url scheme string (eg <code>http://</code> to be
- * prepended to the url of links that do not have
- * a scheme specified in the link text
- */
- public static final boolean addLinks(Spannable text, Pattern pattern, String scheme) {
- return addLinks(text, pattern, scheme, null, null);
- }
-
- /**
- * Applies a regex to a Spannable turning the matches into
- * links.
- *
- * @param s Spannable whose text is to be marked-up with
- * links
- * @param p Regex pattern to be used for finding links
- * @param scheme Url scheme string (eg <code>http://</code> to be
- * prepended to the url of links that do not have
- * a scheme specified in the link text
- * @param matchFilter The filter that is used to allow the client code
- * additional control over which pattern matches are
- * to be converted into links.
- */
- public static final boolean addLinks(Spannable s, Pattern p,
- String scheme, MatchFilter matchFilter,
- TransformFilter transformFilter) {
- boolean hasMatches = false;
- String prefix = (scheme == null) ? "" : scheme.toLowerCase();
- Matcher m = p.matcher(s);
-
- while (m.find()) {
- int start = m.start();
- int end = m.end();
- boolean allowed = true;
-
- if (matchFilter != null) {
- allowed = matchFilter.acceptMatch(s, start, end);
- }
-
- if (allowed) {
- String url = makeUrl(m.group(0), new String[] { prefix },
- m, transformFilter);
-
- applyLink(url, start, end, s);
- hasMatches = true;
- }
- }
-
- return hasMatches;
- }
-
- private static final void applyLink(String url, int start, int end, Spannable text) {
- URLSpan span = new URLSpan(url);
-
- text.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- private static final String makeUrl(String url, String[] prefixes,
- Matcher m, TransformFilter filter) {
- if (filter != null) {
- url = filter.transformUrl(m, url);
- }
-
- boolean hasPrefix = false;
-
- for (int i = 0; i < prefixes.length; i++) {
- if (url.regionMatches(true, 0, prefixes[i], 0,
- prefixes[i].length())) {
- hasPrefix = true;
-
- // Fix capitalization if necessary
- if (!url.regionMatches(false, 0, prefixes[i], 0,
- prefixes[i].length())) {
- url = prefixes[i] + url.substring(prefixes[i].length());
- }
-
- break;
- }
- }
-
- if (!hasPrefix) {
- url = prefixes[0] + url;
- }
-
- return url;
- }
-
- private static final void gatherLinks(ArrayList<LinkSpec> links,
- Spannable s, Pattern pattern, String[] schemes,
- MatchFilter matchFilter, TransformFilter transformFilter) {
- Matcher m = pattern.matcher(s);
-
- while (m.find()) {
- int start = m.start();
- int end = m.end();
-
- if (matchFilter == null || matchFilter.acceptMatch(s, start, end)) {
- LinkSpec spec = new LinkSpec();
- String url = makeUrl(m.group(0), schemes, m, transformFilter);
-
- spec.url = url;
- spec.start = start;
- spec.end = end;
-
- links.add(spec);
- }
- }
- }
-
- private static final void gatherMapLinks(ArrayList<LinkSpec> links, Spannable s) {
- String string = s.toString();
- String address;
- int base = 0;
-
- while ((address = WebView.findAddress(string)) != null) {
- int start = string.indexOf(address);
-
- if (start < 0) {
- break;
- }
-
- LinkSpec spec = new LinkSpec();
- int length = address.length();
- int end = start + length;
-
- spec.start = base + start;
- spec.end = base + end;
- string = string.substring(end);
- base += end;
-
- String encodedAddress = null;
-
- try {
- encodedAddress = URLEncoder.encode(address,"UTF-8");
- } catch (UnsupportedEncodingException e) {
- continue;
- }
-
- spec.url = "geo:0,0?q=" + encodedAddress;
- links.add(spec);
- }
- }
-
- private static final void pruneOverlaps(ArrayList<LinkSpec> links) {
- Comparator<LinkSpec> c = new Comparator<LinkSpec>() {
- public final int compare(LinkSpec a, LinkSpec b) {
- if (a.start < b.start) {
- return -1;
- }
-
- if (a.start > b.start) {
- return 1;
- }
-
- if (a.end < b.end) {
- return 1;
- }
-
- if (a.end > b.end) {
- return -1;
- }
-
- return 0;
- }
-
- public final boolean equals(Object o) {
- return false;
- }
- };
-
- Collections.sort(links, c);
-
- int len = links.size();
- int i = 0;
-
- while (i < len - 1) {
- LinkSpec a = links.get(i);
- LinkSpec b = links.get(i + 1);
- int remove = -1;
-
- if ((a.start <= b.start) && (a.end > b.start)) {
- if (b.end <= a.end) {
- remove = i + 1;
- } else if ((a.end - a.start) > (b.end - b.start)) {
- remove = i + 1;
- } else if ((a.end - a.start) < (b.end - b.start)) {
- remove = i;
- }
-
- if (remove != -1) {
- links.remove(remove);
- len--;
- continue;
- }
-
- }
-
- i++;
- }
- }
-}
-
-class LinkSpec {
- String url;
- int start;
- int end;
-}
diff --git a/core/java/android/text/util/Regex.java b/core/java/android/text/util/Regex.java
deleted file mode 100644
index 4c128ad..0000000
--- a/core/java/android/text/util/Regex.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.text.util;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * @hide
- */
-public class Regex {
- /**
- * Regular expression pattern to match all IANA top-level domains.
- * List accurate as of 2007/06/15. List taken from:
- * http://data.iana.org/TLD/tlds-alpha-by-domain.txt
- * This pattern is auto-generated by //device/tools/make-iana-tld-pattern.py
- */
- public static final Pattern TOP_LEVEL_DOMAIN_PATTERN
- = Pattern.compile(
- "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
- + "|(biz|b[abdefghijmnorstvwyz])"
- + "|(cat|com|coop|c[acdfghiklmnoruvxyz])"
- + "|d[ejkmoz]"
- + "|(edu|e[cegrstu])"
- + "|f[ijkmor]"
- + "|(gov|g[abdefghilmnpqrstuwy])"
- + "|h[kmnrtu]"
- + "|(info|int|i[delmnoqrst])"
- + "|(jobs|j[emop])"
- + "|k[eghimnrwyz]"
- + "|l[abcikrstuvy]"
- + "|(mil|mobi|museum|m[acdghklmnopqrstuvwxyz])"
- + "|(name|net|n[acefgilopruz])"
- + "|(org|om)"
- + "|(pro|p[aefghklmnrstwy])"
- + "|qa"
- + "|r[eouw]"
- + "|s[abcdeghijklmnortuvyz]"
- + "|(tel|travel|t[cdfghjklmnoprtvwz])"
- + "|u[agkmsyz]"
- + "|v[aceginu]"
- + "|w[fs]"
- + "|y[etu]"
- + "|z[amw])");
-
- /**
- * Regular expression pattern to match RFC 1738 URLs
- * List accurate as of 2007/06/15. List taken from:
- * http://data.iana.org/TLD/tlds-alpha-by-domain.txt
- * This pattern is auto-generated by //device/tools/make-iana-tld-pattern.py
- */
- public static final Pattern WEB_URL_PATTERN
- = Pattern.compile(
- "((?:(http|https|Http|Https):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
- + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2}))+(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
- + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2}))+)?\\@)?)?"
- + "((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]*\\.)+" // named host
- + "(?:" // plus top level domain
- + "(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
- + "|(?:biz|b[abdefghijmnorstvwyz])"
- + "|(?:cat|com|coop|c[acdfghiklmnoruvxyz])"
- + "|d[ejkmoz]"
- + "|(?:edu|e[cegrstu])"
- + "|f[ijkmor]"
- + "|(?:gov|g[abdefghilmnpqrstuwy])"
- + "|h[kmnrtu]"
- + "|(?:info|int|i[delmnoqrst])"
- + "|(?:jobs|j[emop])"
- + "|k[eghimnrwyz]"
- + "|l[abcikrstuvy]"
- + "|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])"
- + "|(?:name|net|n[acefgilopruz])"
- + "|(?:org|om)"
- + "|(?:pro|p[aefghklmnrstwy])"
- + "|qa"
- + "|r[eouw]"
- + "|s[abcdeghijklmnortuvyz]"
- + "|(?:tel|travel|t[cdfghjklmnoprtvwz])"
- + "|u[agkmsyz]"
- + "|v[aceginu]"
- + "|w[fs]"
- + "|y[etu]"
- + "|z[amw]))"
- + "|(?:(?:25[0-5]|2[0-4]" // or ip address
- + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]"
- + "|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1]"
- + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
- + "|[1-9][0-9]|[0-9])))"
- + "(?:\\:\\d{1,5})?)" // plus option port number
- + "(\\/(?:(?:[a-zA-Z0-9\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params
- + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
- + "(?:\\b|$)"); // and finally, a word boundary or end of
- // input. This is to stop foo.sure from
- // matching as foo.su
-
- public static final Pattern IP_ADDRESS_PATTERN
- = Pattern.compile(
- "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
- + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
- + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
- + "|[1-9][0-9]|[0-9]))");
-
- public static final Pattern DOMAIN_NAME_PATTERN
- = Pattern.compile(
- "(((([a-zA-Z0-9][a-zA-Z0-9\\-]*)*[a-zA-Z0-9]\\.)+"
- + TOP_LEVEL_DOMAIN_PATTERN + ")|"
- + IP_ADDRESS_PATTERN + ")");
-
- public static final Pattern EMAIL_ADDRESS_PATTERN
- = Pattern.compile(
- "[a-zA-Z0-9\\+\\.\\_\\%\\-]+" +
- "\\@" +
- "[a-zA-Z0-9][a-zA-Z0-9\\-]*" +
- "(" +
- "\\." +
- "[a-zA-Z0-9][a-zA-Z0-9\\-]*" +
- ")+"
- );
-
- /**
- * This pattern is intended for searching for things that look like they
- * might be phone numbers in arbitrary text, not for validating whether
- * something is in fact a phone number. It will miss many things that
- * are legitimate phone numbers.
- *
- * <p> The pattern matches the following:
- * <ul>
- * <li>Optionally, a + sign followed immediately by one or more digits. Spaces, dots, or dashes
- * may follow.
- * <li>Optionally, sets of digits in parentheses, separated by spaces, dots, or dashes.
- * <li>A string starting and ending with a digit, containing digits, spaces, dots, and/or dashes.
- * </ul>
- */
- public static final Pattern PHONE_PATTERN
- = Pattern.compile( // sdd = space, dot, or dash
- "(\\+[0-9]+[\\- \\.]*)?" // +<digits><sdd>*
- + "(\\([0-9]+\\)[\\- \\.]*)?" // (<digits>)<sdd>*
- + "([0-9][0-9\\- \\.][0-9\\- \\.]+[0-9])"); // <digit><digit|sdd>+<digit>
-
- /**
- * Convenience method to take all of the non-null matching groups in a
- * regex Matcher and return them as a concatenated string.
- *
- * @param matcher The Matcher object from which grouped text will
- * be extracted
- *
- * @return A String comprising all of the non-null matched
- * groups concatenated together
- */
- public static final String concatGroups(Matcher matcher) {
- StringBuilder b = new StringBuilder();
- final int numGroups = matcher.groupCount();
-
- for (int i = 1; i <= numGroups; i++) {
- String s = matcher.group(i);
-
- System.err.println("Group(" + i + ") : " + s);
-
- if (s != null) {
- b.append(s);
- }
- }
-
- return b.toString();
- }
-
- /**
- * Convenience method to return only the digits and plus signs
- * in the matching string.
- *
- * @param matcher The Matcher object from which digits and plus will
- * be extracted
- *
- * @return A String comprising all of the digits and plus in
- * the match
- */
- public static final String digitsAndPlusOnly(Matcher matcher) {
- StringBuilder buffer = new StringBuilder();
- String matchingRegion = matcher.group();
-
- for (int i = 0, size = matchingRegion.length(); i < size; i++) {
- char character = matchingRegion.charAt(i);
-
- if (character == '+' || Character.isDigit(character)) {
- buffer.append(character);
- }
- }
- return buffer.toString();
- }
-}
diff --git a/core/java/android/text/util/Rfc822Token.java b/core/java/android/text/util/Rfc822Token.java
deleted file mode 100644
index e6472df..0000000
--- a/core/java/android/text/util/Rfc822Token.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.text.util;
-
-/**
- * This class stores an RFC 822-like name, address, and comment,
- * and provides methods to convert them to quoted strings.
- */
-public class Rfc822Token {
- private String mName, mAddress, mComment;
-
- /**
- * Creates a new Rfc822Token with the specified name, address,
- * and comment.
- */
- public Rfc822Token(String name, String address, String comment) {
- mName = name;
- mAddress = address;
- mComment = comment;
- }
-
- /**
- * Returns the name part.
- */
- public String getName() {
- return mName;
- }
-
- /**
- * Returns the address part.
- */
- public String getAddress() {
- return mAddress;
- }
-
- /**
- * Returns the comment part.
- */
- public String getComment() {
- return mComment;
- }
-
- /**
- * Changes the name to the specified name.
- */
- public void setName(String name) {
- mName = name;
- }
-
- /**
- * Changes the address to the specified address.
- */
- public void setAddress(String address) {
- mAddress = address;
- }
-
- /**
- * Changes the comment to the specified comment.
- */
- public void setComment(String comment) {
- mComment = comment;
- }
-
- /**
- * Returns the name (with quoting added if necessary),
- * the comment (in parentheses), and the address (in angle brackets).
- * This should be suitable for inclusion in an RFC 822 address list.
- */
- public String toString() {
- StringBuilder sb = new StringBuilder();
-
- if (mName != null && mName.length() != 0) {
- sb.append(quoteNameIfNecessary(mName));
- sb.append(' ');
- }
-
- if (mComment != null && mComment.length() != 0) {
- sb.append('(');
- sb.append(quoteComment(mComment));
- sb.append(") ");
- }
-
- if (mAddress != null && mAddress.length() != 0) {
- sb.append('<');
- sb.append(mAddress);
- sb.append('>');
- }
-
- return sb.toString();
- }
-
- /**
- * Returns the name, conservatively quoting it if there are any
- * characters that are likely to cause trouble outside of a
- * quoted string, or returning it literally if it seems safe.
- */
- public static String quoteNameIfNecessary(String name) {
- int len = name.length();
-
- for (int i = 0; i < len; i++) {
- char c = name.charAt(i);
-
- if (! ((c >= 'A' && i <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- (c == ' ') ||
- (c >= '0' && c <= '9'))) {
- return '"' + quoteName(name) + '"';
- }
- }
-
- return name;
- }
-
- /**
- * Returns the name, with internal backslashes and quotation marks
- * preceded by backslashes. The outer quote marks themselves are not
- * added by this method.
- */
- public static String quoteName(String name) {
- StringBuilder sb = new StringBuilder();
-
- int len = name.length();
- for (int i = 0; i < len; i++) {
- char c = name.charAt(i);
-
- if (c == '\\' || c == '"') {
- sb.append('\\');
- }
-
- sb.append(c);
- }
-
- return sb.toString();
- }
-
- /**
- * Returns the comment, with internal backslashes and parentheses
- * preceded by backslashes. The outer parentheses themselves are
- * not added by this method.
- */
- public static String quoteComment(String comment) {
- int len = comment.length();
- StringBuilder sb = new StringBuilder();
-
- for (int i = 0; i < len; i++) {
- char c = comment.charAt(i);
-
- if (c == '(' || c == ')' || c == '\\') {
- sb.append('\\');
- }
-
- sb.append(c);
- }
-
- return sb.toString();
- }
-}
-
diff --git a/core/java/android/text/util/Rfc822Tokenizer.java b/core/java/android/text/util/Rfc822Tokenizer.java
deleted file mode 100644
index d4e78b0..0000000
--- a/core/java/android/text/util/Rfc822Tokenizer.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.text.util;
-
-import android.widget.MultiAutoCompleteTextView;
-
-import java.util.ArrayList;
-
-/**
- * This class works as a Tokenizer for MultiAutoCompleteTextView for
- * address list fields, and also provides a method for converting
- * a string of addresses (such as might be typed into such a field)
- * into a series of Rfc822Tokens.
- */
-public class Rfc822Tokenizer implements MultiAutoCompleteTextView.Tokenizer {
- /**
- * This constructor will try to take a string like
- * "Foo Bar (something) &lt;foo\@google.com&gt;,
- * blah\@google.com (something)"
- * and convert it into one or more Rfc822Tokens.
- * It does *not* decode MIME encoded-words; charset conversion
- * must already have taken place if necessary.
- * It will try to be tolerant of broken syntax instead of
- * returning an error.
- */
- public static Rfc822Token[] tokenize(CharSequence text) {
- ArrayList<Rfc822Token> out = new ArrayList<Rfc822Token>();
- StringBuilder name = new StringBuilder();
- StringBuilder address = new StringBuilder();
- StringBuilder comment = new StringBuilder();
-
- int i = 0;
- int cursor = text.length();
-
- while (i < cursor) {
- char c = text.charAt(i);
-
- if (c == ',' || c == ';') {
- i++;
-
- while (i < cursor && text.charAt(i) == ' ') {
- i++;
- }
-
- crunch(name);
-
- if (address.length() > 0) {
- out.add(new Rfc822Token(name.toString(),
- address.toString(),
- comment.toString()));
- } else if (name.length() > 0) {
- out.add(new Rfc822Token(null,
- name.toString(),
- comment.toString()));
- }
-
- name.setLength(0);
- address.setLength(0);
- address.setLength(0);
- } else if (c == '"') {
- i++;
-
- while (i < cursor) {
- c = text.charAt(i);
-
- if (c == '"') {
- i++;
- break;
- } else if (c == '\\') {
- name.append(text.charAt(i + 1));
- i += 2;
- } else {
- name.append(c);
- i++;
- }
- }
- } else if (c == '(') {
- int level = 1;
- i++;
-
- while (i < cursor && level > 0) {
- c = text.charAt(i);
-
- if (c == ')') {
- if (level > 1) {
- comment.append(c);
- }
-
- level--;
- i++;
- } else if (c == '(') {
- comment.append(c);
- level++;
- i++;
- } else if (c == '\\') {
- comment.append(text.charAt(i + 1));
- i += 2;
- } else {
- comment.append(c);
- i++;
- }
- }
- } else if (c == '<') {
- i++;
-
- while (i < cursor) {
- c = text.charAt(i);
-
- if (c == '>') {
- i++;
- break;
- } else {
- address.append(c);
- i++;
- }
- }
- } else if (c == ' ') {
- name.append('\0');
- i++;
- } else {
- name.append(c);
- i++;
- }
- }
-
- crunch(name);
-
- if (address.length() > 0) {
- out.add(new Rfc822Token(name.toString(),
- address.toString(),
- comment.toString()));
- } else if (name.length() > 0) {
- out.add(new Rfc822Token(null,
- name.toString(),
- comment.toString()));
- }
-
- return out.toArray(new Rfc822Token[out.size()]);
- }
-
- private static void crunch(StringBuilder sb) {
- int i = 0;
- int len = sb.length();
-
- while (i < len) {
- char c = sb.charAt(i);
-
- if (c == '\0') {
- if (i == 0 || i == len - 1 ||
- sb.charAt(i - 1) == ' ' ||
- sb.charAt(i - 1) == '\0' ||
- sb.charAt(i + 1) == ' ' ||
- sb.charAt(i + 1) == '\0') {
- sb.deleteCharAt(i);
- len--;
- } else {
- i++;
- }
- } else {
- i++;
- }
- }
-
- for (i = 0; i < len; i++) {
- if (sb.charAt(i) == '\0') {
- sb.setCharAt(i, ' ');
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public int findTokenStart(CharSequence text, int cursor) {
- /*
- * It's hard to search backward, so search forward until
- * we reach the cursor.
- */
-
- int best = 0;
- int i = 0;
-
- while (i < cursor) {
- i = findTokenEnd(text, i);
-
- if (i < cursor) {
- i++; // Skip terminating punctuation
-
- while (i < cursor && text.charAt(i) == ' ') {
- i++;
- }
-
- if (i < cursor) {
- best = i;
- }
- }
- }
-
- return best;
- }
-
- /**
- * {@inheritDoc}
- */
- public int findTokenEnd(CharSequence text, int cursor) {
- int len = text.length();
- int i = cursor;
-
- while (i < len) {
- char c = text.charAt(i);
-
- if (c == ',' || c == ';') {
- return i;
- } else if (c == '"') {
- i++;
-
- while (i < len) {
- c = text.charAt(i);
-
- if (c == '"') {
- i++;
- break;
- } else if (c == '\\') {
- i += 2;
- } else {
- i++;
- }
- }
- } else if (c == '(') {
- int level = 1;
- i++;
-
- while (i < len && level > 0) {
- c = text.charAt(i);
-
- if (c == ')') {
- level--;
- i++;
- } else if (c == '(') {
- level++;
- i++;
- } else if (c == '\\') {
- i += 2;
- } else {
- i++;
- }
- }
- } else if (c == '<') {
- i++;
-
- while (i < len) {
- c = text.charAt(i);
-
- if (c == '>') {
- i++;
- break;
- } else {
- i++;
- }
- }
- } else {
- i++;
- }
- }
-
- return i;
- }
-
- /**
- * Terminates the specified address with a comma and space.
- * This assumes that the specified text already has valid syntax.
- * The Adapter subclass's convertToString() method must make that
- * guarantee.
- */
- public CharSequence terminateToken(CharSequence text) {
- return text + ", ";
- }
-}
diff --git a/core/java/android/text/util/Rfc822Validator.java b/core/java/android/text/util/Rfc822Validator.java
deleted file mode 100644
index 6a6bf69..0000000
--- a/core/java/android/text/util/Rfc822Validator.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2008 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 android.text.util;
-
-import android.text.TextUtils;
-import android.widget.AutoCompleteTextView;
-
-import java.util.regex.Pattern;
-
-/**
- * This class works as a Validator for AutoCompleteTextView for
- * email addresses. If a token does not appear to be a valid address,
- * it is trimmed of characters that cannot legitimately appear in one
- * and has the specified domain name added. It is meant for use with
- * {@link Rfc822Token} and {@link Rfc822Tokenizer}.
- *
- * @deprecated In the future make sure we don't quietly alter the user's
- * text in ways they did not intend. Meanwhile, hide this
- * class from the public API because it does not even have
- * a full understanding of the syntax it claims to correct.
- * @hide
- */
-public class Rfc822Validator implements AutoCompleteTextView.Validator {
- /*
- * Regex.EMAIL_ADDRESS_PATTERN hardcodes the TLD that we accept, but we
- * want to make sure we will keep accepting email addresses with TLD's
- * that don't exist at the time of this writing, so this regexp relaxes
- * that constraint by accepting any kind of top level domain, not just
- * ".com", ".fr", etc...
- */
- private static final Pattern EMAIL_ADDRESS_PATTERN =
- Pattern.compile("[^\\s@]+@[^\\s@]+\\.[a-zA-z][a-zA-Z][a-zA-Z]*");
-
- private String mDomain;
-
- /**
- * Constructs a new validator that uses the specified domain name as
- * the default when none is specified.
- */
- public Rfc822Validator(String domain) {
- mDomain = domain;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean isValid(CharSequence text) {
- Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(text);
-
- return tokens.length == 1 &&
- EMAIL_ADDRESS_PATTERN.
- matcher(tokens[0].getAddress()).matches();
- }
-
- /**
- * @return a string in which all the characters that are illegal for the username
- * or the domain name part of the email address have been removed.
- */
- private String removeIllegalCharacters(String s) {
- StringBuilder result = new StringBuilder();
- int length = s.length();
- for (int i = 0; i < length; i++) {
- char c = s.charAt(i);
-
- /*
- * An RFC822 atom can contain any ASCII printing character
- * except for periods and any of the following punctuation.
- * A local-part can contain multiple atoms, concatenated by
- * periods, so do allow periods here.
- */
-
- if (c <= ' ' || c > '~') {
- continue;
- }
-
- if (c == '(' || c == ')' || c == '<' || c == '>' ||
- c == '@' || c == ',' || c == ';' || c == ':' ||
- c == '\\' || c == '"' || c == '[' || c == ']') {
- continue;
- }
-
- result.append(c);
- }
- return result.toString();
- }
-
- /**
- * {@inheritDoc}
- */
- public CharSequence fixText(CharSequence cs) {
- // Return an empty string if the email address only contains spaces, \n or \t
- if (TextUtils.getTrimmedLength(cs) == 0) return "";
-
- Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(cs);
- StringBuilder sb = new StringBuilder();
-
- for (int i = 0; i < tokens.length; i++) {
- String text = tokens[i].getAddress();
- int index = text.indexOf('@');
- if (index < 0) {
- // If there is no @, just append the domain of the account
- tokens[i].setAddress(removeIllegalCharacters(text) + "@" + mDomain);
- } else {
- // Otherwise, remove the illegal characters on both sides of the '@'
- String fix = removeIllegalCharacters(text.substring(0, index));
- String domain = removeIllegalCharacters(text.substring(index + 1));
- tokens[i].setAddress(fix + "@" + (domain.length() != 0 ? domain : mDomain));
- }
-
- sb.append(tokens[i].toString());
- if (i + 1 < tokens.length) {
- sb.append(", ");
- }
- }
-
- return sb;
- }
-}
diff --git a/core/java/android/text/util/package.html b/core/java/android/text/util/package.html
deleted file mode 100644
index d9312aa2..0000000
--- a/core/java/android/text/util/package.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<HTML>
-<BODY>
-Utilities for converting identifiable text strings into clickable links
-and creating RFC 822-type message (SMTP) tokens.
-</BODY>
-</HTML> \ No newline at end of file