diff --git a/common/java/com/android/ex/editstyledtext/EditStyledText.java b/common/java/com/android/ex/editstyledtext/EditStyledText.java
deleted file mode 100644
index 45bbf17..0000000
--- a/common/java/com/android/ex/editstyledtext/EditStyledText.java
+++ /dev/null
@@ -1,3355 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ex.editstyledtext;
-
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import com.android.ex.editstyledtext.EditStyledText.EditModeActions.EditModeActionBase;
-import com.android.ex.editstyledtext.EditStyledText.EditStyledTextSpans.HorizontalLineSpan;
-import com.android.ex.editstyledtext.EditStyledText.EditStyledTextSpans.MarqueeSpan;
-import com.android.ex.editstyledtext.EditStyledText.EditStyledTextSpans.RescalableImageSpan;
-
-import android.R;
-import android.app.AlertDialog;
-import android.app.AlertDialog.Builder;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.RectShape;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.ResultReceiver;
-import android.text.ClipboardManager;
-import android.text.Editable;
-import android.text.Html;
-import android.text.Layout;
-import android.text.NoCopySpan;
-import android.text.NoCopySpan.Concrete;
-import android.text.Selection;
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.TextPaint;
-import android.text.Html.ImageGetter;
-import android.text.Html.TagHandler;
-import android.text.method.ArrowKeyMovementMethod;
-import android.text.style.AbsoluteSizeSpan;
-import android.text.style.AlignmentSpan;
-import android.text.style.BackgroundColorSpan;
-import android.text.style.CharacterStyle;
-import android.text.style.DynamicDrawableSpan;
-import android.text.style.ForegroundColorSpan;
-import android.text.style.ImageSpan;
-import android.text.style.ParagraphStyle;
-import android.text.style.QuoteSpan;
-import android.text.style.UnderlineSpan;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.ContextMenu;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputConnectionWrapper;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-/**
- * EditStyledText extends EditText for managing the flow and status to edit the styled text. This
- * manages the states and flows of editing, supports inserting image, import/export HTML.
- */
-public class EditStyledText extends EditText {
-
-    private static final String TAG = "EditStyledText";
-    /**
-     * DBG should be false at checking in.
-     */
-    private static final boolean DBG = true;
-
-    /**
-     * Modes of editing actions.
-     */
-    /** The mode that no editing action is done. */
-    public static final int MODE_NOTHING = 0;
-    /** The mode of copy. */
-    public static final int MODE_COPY = 1;
-    /** The mode of paste. */
-    public static final int MODE_PASTE = 2;
-    /** The mode of changing size. */
-    public static final int MODE_SIZE = 3;
-    /** The mode of changing color. */
-    public static final int MODE_COLOR = 4;
-    /** The mode of selection. */
-    public static final int MODE_SELECT = 5;
-    /** The mode of changing alignment. */
-    public static final int MODE_ALIGN = 6;
-    /** The mode of changing cut. */
-    public static final int MODE_CUT = 7;
-    public static final int MODE_TELOP = 8;
-    public static final int MODE_SWING = 9;
-    public static final int MODE_MARQUEE = 10;
-    public static final int MODE_SELECTALL = 11;
-    public static final int MODE_HORIZONTALLINE = 12;
-    public static final int MODE_STOP_SELECT = 13;
-    public static final int MODE_CLEARSTYLES = 14;
-    public static final int MODE_IMAGE = 15;
-    public static final int MODE_BGCOLOR = 16;
-    public static final int MODE_PREVIEW = 17;
-    public static final int MODE_CANCEL = 18;
-    public static final int MODE_TEXTVIEWFUNCTION = 19;
-    public static final int MODE_START_EDIT = 20;
-    public static final int MODE_END_EDIT = 21;
-    public static final int MODE_RESET = 22;
-    public static final int MODE_SHOW_MENU = 23;
-
-    /**
-     * States of selection.
-     */
-    /** The state that selection isn't started. */
-    public static final int STATE_SELECT_OFF = 0;
-    /** The state that selection is started. */
-    public static final int STATE_SELECT_ON = 1;
-    /** The state that selection is done, but not fixed. */
-    public static final int STATE_SELECTED = 2;
-    /** The state that selection is done and not fixed. */
-    public static final int STATE_SELECT_FIX = 3;
-
-    /**
-     * Help message strings.
-     */
-    public static final int HINT_MSG_NULL = 0;
-    public static final int HINT_MSG_COPY_BUF_BLANK = 1;
-    public static final int HINT_MSG_SELECT_START = 2;
-    public static final int HINT_MSG_SELECT_END = 3;
-    public static final int HINT_MSG_PUSH_COMPETE = 4;
-    public static final int HINT_MSG_BIG_SIZE_ERROR = 5;
-    public static final int HINT_MSG_END_PREVIEW = 6;
-    public static final int HINT_MSG_END_COMPOSE = 7;
-
-    /**
-     * Fixed Values.
-     */
-    public static final int DEFAULT_TRANSPARENT_COLOR = 0x00FFFFFF;
-    public static final int DEFAULT_FOREGROUND_COLOR = 0xFF000000;
-    public static final char ZEROWIDTHCHAR = '\u2060';
-    public static final char IMAGECHAR = '\uFFFC';
-    private static final int ID_SELECT_ALL = android.R.id.selectAll;
-    private static final int ID_START_SELECTING_TEXT = android.R.id.startSelectingText;
-    private static final int ID_STOP_SELECTING_TEXT = android.R.id.stopSelectingText;
-    private static final int ID_PASTE = android.R.id.paste;
-    private static final int ID_COPY = android.R.id.copy;
-    private static final int ID_CUT = android.R.id.cut;
-    private static final int ID_HORIZONTALLINE = 0x00FFFF01;
-    private static final int ID_CLEARSTYLES = 0x00FFFF02;
-    private static final int ID_SHOWEDIT = 0x00FFFF03;
-    private static final int ID_HIDEEDIT = 0x00FFFF04;
-    private static final int MAXIMAGEWIDTHDIP = 300;
-
-    /**
-     * Strings for context menu. TODO: Extract the strings to strings.xml.
-     */
-    private static CharSequence STR_HORIZONTALLINE;
-    private static CharSequence STR_CLEARSTYLES;
-    private static CharSequence STR_PASTE;
-
-    private float mPaddingScale = 0;
-    private ArrayList<EditStyledTextNotifier> mESTNotifiers;
-    private Drawable mDefaultBackground;
-    // EditStyledTextEditorManager manages the flow and status of each function of StyledText.
-    private EditorManager mManager;
-    private InputConnection mInputConnection;
-    private StyledTextConverter mConverter;
-    private StyledTextDialog mDialog;
-
-    private static final Concrete SELECTING = new NoCopySpan.Concrete();
-    private static final int PRESSED = Spannable.SPAN_MARK_MARK | (1 << Spannable.SPAN_USER_SHIFT);
-
-    /**
-     * EditStyledText extends EditText for managing flow of each editing action.
-     */
-    public EditStyledText(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        init();
-    }
-
-    public EditStyledText(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init();
-    }
-
-    public EditStyledText(Context context) {
-        super(context);
-        init();
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        boolean superResult;
-        if (event.getAction() == MotionEvent.ACTION_UP) {
-            cancelLongPress();
-            boolean editting = isEditting();
-            // If View is touched but not in Edit Mode, starts Edit Mode.
-            if (!editting) {
-                onStartEdit();
-            }
-            int oldSelStart = Selection.getSelectionStart(getText());
-            int oldSelEnd = Selection.getSelectionEnd(getText());
-            superResult = super.onTouchEvent(event);
-            if (isFocused()) {
-                // If selection is started, don't open soft key by
-                // touching.
-                if (getSelectState() == STATE_SELECT_OFF) {
-                    if (editting) {
-                        mManager.showSoftKey(Selection.getSelectionStart(getText()),
-                                Selection.getSelectionEnd(getText()));
-                    } else {
-                        mManager.showSoftKey(oldSelStart, oldSelEnd);
-                    }
-                }
-            }
-            mManager.onCursorMoved();
-            mManager.unsetTextComposingMask();
-        } else {
-            superResult = super.onTouchEvent(event);
-        }
-        sendOnTouchEvent(event);
-        return superResult;
-    }
-
-    @Override
-    public Parcelable onSaveInstanceState() {
-        Parcelable superState = super.onSaveInstanceState();
-        SavedStyledTextState ss = new SavedStyledTextState(superState);
-        ss.mBackgroundColor = mManager.getBackgroundColor();
-        return ss;
-    }
-
-    @Override
-    public void onRestoreInstanceState(Parcelable state) {
-        if (!(state instanceof SavedStyledTextState)) {
-            super.onRestoreInstanceState(state);
-            return;
-        }
-        SavedStyledTextState ss = (SavedStyledTextState) state;
-        super.onRestoreInstanceState(ss.getSuperState());
-        setBackgroundColor(ss.mBackgroundColor);
-    }
-
-    @Override
-    protected void drawableStateChanged() {
-        super.drawableStateChanged();
-        if (mManager != null) {
-            mManager.onRefreshStyles();
-        }
-    }
-
-    @Override
-    public boolean onTextContextMenuItem(int id) {
-        boolean selection = getSelectionStart() != getSelectionEnd();
-        switch (id) {
-            case ID_SELECT_ALL:
-                onStartSelectAll();
-                return true;
-            case ID_START_SELECTING_TEXT:
-                onStartSelect();
-                mManager.blockSoftKey();
-                break;
-            case ID_STOP_SELECTING_TEXT:
-                onFixSelectedItem();
-                break;
-            case ID_PASTE:
-                onStartPaste();
-                return true;
-            case ID_COPY:
-                if (selection) {
-                    onStartCopy();
-                } else {
-                    mManager.onStartSelectAll(false);
-                    onStartCopy();
-                }
-                return true;
-            case ID_CUT:
-                if (selection) {
-                    onStartCut();
-                } else {
-                    mManager.onStartSelectAll(false);
-                    onStartCut();
-                }
-                return true;
-            case ID_HORIZONTALLINE:
-                onInsertHorizontalLine();
-                return true;
-            case ID_CLEARSTYLES:
-                onClearStyles();
-                return true;
-            case ID_SHOWEDIT:
-                onStartEdit();
-                return true;
-            case ID_HIDEEDIT:
-                onEndEdit();
-                return true;
-        }
-        return super.onTextContextMenuItem(id);
-    }
-
-    @Override
-    protected void onCreateContextMenu(ContextMenu menu) {
-        super.onCreateContextMenu(menu);
-        MenuHandler handler = new MenuHandler();
-        if (STR_HORIZONTALLINE != null) {
-            menu.add(0, ID_HORIZONTALLINE, 0, STR_HORIZONTALLINE).setOnMenuItemClickListener(
-                    handler);
-        }
-        if (isStyledText() && STR_CLEARSTYLES != null) {
-            menu.add(0, ID_CLEARSTYLES, 0, STR_CLEARSTYLES)
-                    .setOnMenuItemClickListener(handler);
-        }
-        if (mManager.canPaste()) {
-            menu.add(0, ID_PASTE, 0, STR_PASTE)
-                    .setOnMenuItemClickListener(handler).setAlphabeticShortcut('v');
-        }
-    }
-
-    @Override
-    protected void onTextChanged(CharSequence text, int start, int before, int after) {
-        // onTextChanged will be called super's constructor.
-        if (mManager != null) {
-            mManager.updateSpanNextToCursor(getText(), start, before, after);
-            mManager.updateSpanPreviousFromCursor(getText(), start, before, after);
-            if (after > before) {
-                mManager.setTextComposingMask(start, start + after);
-            } else if (before < after) {
-                mManager.unsetTextComposingMask();
-            }
-            if (mManager.isWaitInput()) {
-                if (after > before) {
-                    mManager.onCursorMoved();
-                    onFixSelectedItem();
-                } else if (after < before) {
-                    mManager.onAction(MODE_RESET);
-                }
-            }
-        }
-        super.onTextChanged(text, start, before, after);
-    }
-
-    @Override
-    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
-        mInputConnection =
-                new StyledTextInputConnection(super.onCreateInputConnection(outAttrs), this);
-        return mInputConnection;
-    }
-
-    @Override
-    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
-        super.onFocusChanged(focused, direction, previouslyFocusedRect);
-        if (focused) {
-            onStartEdit();
-        } else if (!isButtonsFocused()) {
-            onEndEdit();
-        }
-    }
-
-    /**
-     * Initialize members.
-     */
-    private void init() {
-        mConverter = new StyledTextConverter(this, new StyledTextHtmlStandard());
-        mDialog = new StyledTextDialog(this);
-        mManager = new EditorManager(this, mDialog);
-        setMovementMethod(new StyledTextArrowKeyMethod(mManager));
-        mDefaultBackground = getBackground();
-        requestFocus();
-    }
-
-    public interface StyledTextHtmlConverter {
-        public String toHtml(Spanned text);
-
-        public String toHtml(Spanned text, boolean escapeNonAsciiChar);
-
-        public String toHtml(Spanned text, boolean escapeNonAsciiChar, int width, float scale);
-
-        public Spanned fromHtml(String string);
-
-        public Spanned fromHtml(String source, ImageGetter imageGetter, TagHandler tagHandler);
-    }
-
-    public void setStyledTextHtmlConverter(StyledTextHtmlConverter html) {
-        mConverter.setStyledTextHtmlConverter(html);
-    }
-
-    /**
-     * EditStyledTextInterface provides functions for notifying messages to calling class.
-     */
-    public interface EditStyledTextNotifier {
-        public void sendHintMsg(int msgId);
-
-        public void onStateChanged(int mode, int state);
-
-        public boolean sendOnTouchEvent(MotionEvent event);
-
-        public boolean isButtonsFocused();
-
-        public boolean showPreview();
-
-        public void cancelViewManager();
-
-        public boolean showInsertImageSelectAlertDialog();
-
-        public boolean showMenuAlertDialog();
-    }
-
-    /**
-     * Add Notifier.
-     */
-    public void addEditStyledTextListener(EditStyledTextNotifier estInterface) {
-        if (mESTNotifiers == null) {
-            mESTNotifiers = new ArrayList<EditStyledTextNotifier>();
-        }
-        mESTNotifiers.add(estInterface);
-    }
-
-    /**
-     * Remove Notifier.
-     */
-    public void removeEditStyledTextListener(EditStyledTextNotifier estInterface) {
-        if (mESTNotifiers != null) {
-            int i = mESTNotifiers.indexOf(estInterface);
-
-            if (i > 0) {
-                mESTNotifiers.remove(i);
-            }
-        }
-    }
-
-    private void sendOnTouchEvent(MotionEvent event) {
-        if (mESTNotifiers != null) {
-            for (EditStyledTextNotifier notifier : mESTNotifiers) {
-                notifier.sendOnTouchEvent(event);
-            }
-        }
-    }
-
-    public boolean isButtonsFocused() {
-        boolean retval = false;
-        if (mESTNotifiers != null) {
-            for (EditStyledTextNotifier notifier : mESTNotifiers) {
-                retval |= notifier.isButtonsFocused();
-            }
-        }
-        return retval;
-    }
-
-    private void showPreview() {
-        if (mESTNotifiers != null) {
-            for (EditStyledTextNotifier notifier : mESTNotifiers) {
-                if (notifier.showPreview()) {
-                    break;
-                }
-            }
-        }
-    }
-
-    private void cancelViewManagers() {
-        if (mESTNotifiers != null) {
-            for (EditStyledTextNotifier notifier : mESTNotifiers) {
-                notifier.cancelViewManager();
-            }
-        }
-    }
-
-    private void showInsertImageSelectAlertDialog() {
-        if (mESTNotifiers != null) {
-            for (EditStyledTextNotifier notifier : mESTNotifiers) {
-                if (notifier.showInsertImageSelectAlertDialog()) {
-                    break;
-                }
-            }
-        }
-    }
-
-    private void showMenuAlertDialog() {
-        if (mESTNotifiers != null) {
-            for (EditStyledTextNotifier notifier : mESTNotifiers) {
-                if (notifier.showMenuAlertDialog()) {
-                    break;
-                }
-            }
-        }
-    }
-
-    /**
-     * Notify hint messages what action is expected to calling class.
-     *
-     * @param msgId Id of the hint message.
-     */
-    private void sendHintMessage(int msgId) {
-        if (mESTNotifiers != null) {
-            for (EditStyledTextNotifier notifier : mESTNotifiers) {
-                notifier.sendHintMsg(msgId);
-            }
-        }
-    }
-
-    /**
-     * Notify the event that the mode and state are changed.
-     *
-     * @param mode Mode of the editing action.
-     * @param state Mode of the selection state.
-     */
-    private void notifyStateChanged(int mode, int state) {
-        if (mESTNotifiers != null) {
-            for (EditStyledTextNotifier notifier : mESTNotifiers) {
-                notifier.onStateChanged(mode, state);
-            }
-        }
-    }
-
-    /** Start to edit styled text */
-    public void onStartEdit() {
-        mManager.onAction(MODE_START_EDIT);
-    }
-
-    /** End of editing styled text */
-    public void onEndEdit() {
-        mManager.onAction(MODE_END_EDIT);
-    }
-
-    public void onResetEdit() {
-        mManager.onAction(MODE_RESET);
-    }
-
-    /** Start to copy styled text */
-    public void onStartCopy() {
-        mManager.onAction(MODE_COPY);
-    }
-
-    /** Start to cut styled text */
-    public void onStartCut() {
-        mManager.onAction(MODE_CUT);
-    }
-
-    /** Start to paste styled text */
-    public void onStartPaste() {
-        mManager.onAction(MODE_PASTE);
-    }
-
-    /** Start to change size */
-    public void onStartSize() {
-        mManager.onAction(MODE_SIZE);
-    }
-
-    /** Start to change color */
-    public void onStartColor() {
-        mManager.onAction(MODE_COLOR);
-    }
-
-    /** Start to change background color */
-    public void onStartBackgroundColor() {
-        mManager.onAction(MODE_BGCOLOR);
-    }
-
-    /** Start to change Alignment */
-    public void onStartAlign() {
-        mManager.onAction(MODE_ALIGN);
-    }
-
-    public void onStartTelop() {
-        mManager.onAction(MODE_TELOP);
-    }
-
-    public void onStartSwing() {
-        mManager.onAction(MODE_SWING);
-    }
-
-    public void onStartMarquee() {
-        mManager.onAction(MODE_MARQUEE);
-    }
-
-    /** Start to select a text */
-    public void onStartSelect() {
-        mManager.onStartSelect(true);
-    }
-
-    /** Start to select all characters */
-    public void onStartSelectAll() {
-        mManager.onStartSelectAll(true);
-    }
-
-    public void onStartShowPreview() {
-        mManager.onAction(MODE_PREVIEW);
-    }
-
-    public void onStartShowMenuAlertDialog() {
-        mManager.onStartShowMenuAlertDialog();
-    }
-
-    public void onStartAction(int mode, boolean notifyStateChanged) {
-        mManager.onAction(mode, notifyStateChanged);
-    }
-
-    /** Fix selection */
-    public void onFixSelectedItem() {
-        mManager.onFixSelectedItem();
-    }
-
-    public void onInsertImage() {
-        mManager.onAction(MODE_IMAGE);
-    }
-
-    /**
-     * InsertImage to TextView by using URI
-     *
-     * @param uri URI of the iamge inserted to TextView.
-     */
-    public void onInsertImage(Uri uri) {
-        mManager.onInsertImage(uri);
-    }
-
-    /**
-     * InsertImage to TextView by using resource ID
-     *
-     * @param resId Resource ID of the iamge inserted to TextView.
-     */
-    public void onInsertImage(int resId) {
-        mManager.onInsertImage(resId);
-    }
-
-    public void onInsertHorizontalLine() {
-        mManager.onAction(MODE_HORIZONTALLINE);
-    }
-
-    public void onClearStyles() {
-        mManager.onClearStyles();
-    }
-
-    public void onBlockSoftKey() {
-        mManager.blockSoftKey();
-    }
-
-    public void onUnblockSoftKey() {
-        mManager.unblockSoftKey();
-    }
-
-    public void onCancelViewManagers() {
-        mManager.onCancelViewManagers();
-    }
-
-    private void onRefreshStyles() {
-        mManager.onRefreshStyles();
-    }
-
-    private void onRefreshZeoWidthChar() {
-        mManager.onRefreshZeoWidthChar();
-    }
-
-    /**
-     * Set Size of the Item.
-     *
-     * @param size The size of the Item.
-     */
-    public void setItemSize(int size) {
-        mManager.setItemSize(size, true);
-    }
-
-    /**
-     * Set Color of the Item.
-     *
-     * @param color The color of the Item.
-     */
-    public void setItemColor(int color) {
-        mManager.setItemColor(color, true);
-    }
-
-    /**
-     * Set Alignment of the Item.
-     *
-     * @param align The color of the Item.
-     */
-    public void setAlignment(Layout.Alignment align) {
-        mManager.setAlignment(align);
-    }
-
-    /**
-     * Set Background color of View.
-     *
-     * @param color The background color of view.
-     */
-    @Override
-    public void setBackgroundColor(int color) {
-        if (color != DEFAULT_TRANSPARENT_COLOR) {
-            super.setBackgroundColor(color);
-        } else {
-            setBackgroundDrawable(mDefaultBackground);
-        }
-        mManager.setBackgroundColor(color);
-        onRefreshStyles();
-    }
-
-    public void setMarquee(int marquee) {
-        mManager.setMarquee(marquee);
-    }
-
-    /**
-     * Set html to EditStyledText.
-     *
-     * @param html The html to be set.
-     */
-    public void setHtml(String html) {
-        mConverter.SetHtml(html);
-    }
-
-    /**
-     * Set Builder for AlertDialog.
-     *
-     * @param builder Builder for opening Alert Dialog.
-     */
-    public void setBuilder(Builder builder) {
-        mDialog.setBuilder(builder);
-    }
-
-    /**
-     * Set Parameters for ColorAlertDialog.
-     *
-     * @param colortitle Title for Alert Dialog.
-     * @param colornames List of name of selecting color.
-     * @param colorints List of int of color.
-     */
-    public void setColorAlertParams(CharSequence colortitle, CharSequence[] colornames,
-            CharSequence[] colorints, CharSequence transparent) {
-        mDialog.setColorAlertParams(colortitle, colornames, colorints, transparent);
-    }
-
-    /**
-     * Set Parameters for SizeAlertDialog.
-     *
-     * @param sizetitle Title for Alert Dialog.
-     * @param sizenames List of name of selecting size.
-     * @param sizedisplayints List of int of size displayed in TextView.
-     * @param sizesendints List of int of size exported to HTML.
-     */
-    public void setSizeAlertParams(CharSequence sizetitle, CharSequence[] sizenames,
-            CharSequence[] sizedisplayints, CharSequence[] sizesendints) {
-        mDialog.setSizeAlertParams(sizetitle, sizenames, sizedisplayints, sizesendints);
-    }
-
-    public void setAlignAlertParams(CharSequence aligntitle, CharSequence[] alignnames) {
-        mDialog.setAlignAlertParams(aligntitle, alignnames);
-    }
-
-    public void setMarqueeAlertParams(CharSequence marqueetitle, CharSequence[] marqueenames) {
-        mDialog.setMarqueeAlertParams(marqueetitle, marqueenames);
-    }
-
-    public void setContextMenuStrings(CharSequence horizontalline, CharSequence clearstyles,
-            CharSequence paste) {
-        STR_HORIZONTALLINE = horizontalline;
-        STR_CLEARSTYLES = clearstyles;
-        STR_PASTE = paste;
-    }
-
-    /**
-     * Check whether editing is started or not.
-     *
-     * @return Whether editing is started or not.
-     */
-    public boolean isEditting() {
-        return mManager.isEditting();
-    }
-
-    /**
-     * Check whether styled text or not.
-     *
-     * @return Whether styled text or not.
-     */
-    public boolean isStyledText() {
-        return mManager.isStyledText();
-    }
-
-    /**
-     * Check whether SoftKey is Blocked or not.
-     *
-     * @return whether SoftKey is Blocked or not.
-     */
-    public boolean isSoftKeyBlocked() {
-        return mManager.isSoftKeyBlocked();
-    }
-
-    /**
-     * Get the mode of the action.
-     *
-     * @return The mode of the action.
-     */
-    public int getEditMode() {
-        return mManager.getEditMode();
-    }
-
-    /**
-     * Get the state of the selection.
-     *
-     * @return The state of the selection.
-     */
-    public int getSelectState() {
-        return mManager.getSelectState();
-    }
-
-    /**
-     * Get the state of the selection.
-     *
-     * @return The state of the selection.
-     */
-    public String getHtml() {
-        return mConverter.getHtml(true);
-    }
-
-    public String getHtml(boolean escapeFlag) {
-        return mConverter.getHtml(escapeFlag);
-    }
-
-    /**
-     * Get the state of the selection.
-     *
-     * @param uris The array of used uris.
-     * @return The state of the selection.
-     */
-    public String getHtml(ArrayList<Uri> uris, boolean escapeFlag) {
-        mConverter.getUriArray(uris, getText());
-        return mConverter.getHtml(escapeFlag);
-    }
-
-    public String getPreviewHtml() {
-        return mConverter.getPreviewHtml();
-    }
-
-    /**
-     * Get Background color of View.
-     *
-     * @return The background color of View.
-     */
-    public int getBackgroundColor() {
-        return mManager.getBackgroundColor();
-    }
-
-    public EditorManager getEditStyledTextManager() {
-        return mManager;
-    }
-
-    /**
-     * Get Foreground color of View.
-     *
-     * @return The background color of View.
-     */
-    public int getForegroundColor(int pos) {
-        if (pos < 0 || pos > getText().length()) {
-            return DEFAULT_FOREGROUND_COLOR;
-        } else {
-            ForegroundColorSpan[] spans =
-                    getText().getSpans(pos, pos, ForegroundColorSpan.class);
-            if (spans.length > 0) {
-                return spans[0].getForegroundColor();
-            } else {
-                return DEFAULT_FOREGROUND_COLOR;
-            }
-        }
-    }
-
-    private void finishComposingText() {
-        if (mInputConnection != null && !mManager.mTextIsFinishedFlag) {
-            mInputConnection.finishComposingText();
-            mManager.mTextIsFinishedFlag = true;
-        }
-    }
-
-    private float getPaddingScale() {
-        if (mPaddingScale <= 0) {
-            mPaddingScale = getContext().getResources().getDisplayMetrics().density;
-        }
-        return mPaddingScale;
-    }
-
-    /** Convert pixcel to DIP */
-    private int dipToPx(int dip) {
-        if (mPaddingScale <= 0) {
-            mPaddingScale = getContext().getResources().getDisplayMetrics().density;
-        }
-        return (int) ((float) dip * getPaddingScale() + 0.5);
-    }
-
-    private int getMaxImageWidthDip() {
-        return MAXIMAGEWIDTHDIP;
-    }
-
-    private int getMaxImageWidthPx() {
-        return dipToPx(MAXIMAGEWIDTHDIP);
-    }
-
-    public void addAction(int mode, EditModeActionBase action) {
-        mManager.addAction(mode, action);
-    }
-
-    public void addInputExtra(boolean create, String extra) {
-        Bundle bundle = super.getInputExtras(create);
-        if (bundle != null) {
-            bundle.putBoolean(extra, true);
-        }
-    }
-
-    private static void startSelecting(View view, Spannable content) {
-        content.setSpan(SELECTING, 0, 0, PRESSED);
-    }
-
-    private static void stopSelecting(View view, Spannable content) {
-        content.removeSpan(SELECTING);
-    }
-
-    /**
-     * EditorManager manages the flow and status of editing actions.
-     */
-    private class EditorManager {
-
-        static final private String LOG_TAG = "EditStyledText.EditorManager";
-
-        private boolean mEditFlag = false;
-        private boolean mSoftKeyBlockFlag = false;
-        private boolean mKeepNonLineSpan = false;
-        private boolean mWaitInputFlag = false;
-        private boolean mTextIsFinishedFlag = false;
-        private int mMode = MODE_NOTHING;
-        private int mState = STATE_SELECT_OFF;
-        private int mCurStart = 0;
-        private int mCurEnd = 0;
-        private int mColorWaitInput = DEFAULT_TRANSPARENT_COLOR;
-        private int mSizeWaitInput = 0;
-        private int mBackgroundColor = DEFAULT_TRANSPARENT_COLOR;
-
-        private BackgroundColorSpan mComposingTextMask;
-        private EditStyledText mEST;
-        private EditModeActions mActions;
-        private SoftKeyReceiver mSkr;
-        private SpannableStringBuilder mCopyBuffer;
-
-        EditorManager(EditStyledText est, StyledTextDialog dialog) {
-            mEST = est;
-            mActions = new EditModeActions(mEST, this, dialog);
-            mSkr = new SoftKeyReceiver(mEST);
-        }
-
-        public void addAction(int mode, EditModeActionBase action) {
-            mActions.addAction(mode, action);
-        }
-
-        public void onAction(int mode) {
-            onAction(mode, true);
-        }
-
-        public void onAction(int mode, boolean notifyStateChanged) {
-            mActions.onAction(mode);
-            if (notifyStateChanged) {
-                mEST.notifyStateChanged(mMode, mState);
-            }
-        }
-
-        private void startEdit() {
-            resetEdit();
-            showSoftKey();
-        }
-
-        public void onStartSelect(boolean notifyStateChanged) {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- onClickSelect");
-            }
-            mMode = MODE_SELECT;
-            if (mState == STATE_SELECT_OFF) {
-                mActions.onSelectAction();
-            } else {
-                unsetSelect();
-                mActions.onSelectAction();
-            }
-            if (notifyStateChanged) {
-                mEST.notifyStateChanged(mMode, mState);
-            }
-        }
-
-        public void onCursorMoved() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- onClickView");
-            }
-            if (mState == STATE_SELECT_ON || mState == STATE_SELECTED) {
-                mActions.onSelectAction();
-                mEST.notifyStateChanged(mMode, mState);
-            }
-        }
-
-        public void onStartSelectAll(boolean notifyStateChanged) {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- onClickSelectAll");
-            }
-            handleSelectAll();
-            if (notifyStateChanged) {
-                mEST.notifyStateChanged(mMode, mState);
-            }
-        }
-
-        public void onStartShowMenuAlertDialog() {
-            mActions.onAction(MODE_SHOW_MENU);
-            // don't call notify state changed because it have to continue
-            // to the next action.
-            // mEST.notifyStateChanged(mMode, mState);
-        }
-
-        public void onFixSelectedItem() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- onFixSelectedItem");
-            }
-            fixSelectionAndDoNextAction();
-            mEST.notifyStateChanged(mMode, mState);
-        }
-
-        public void onInsertImage(Uri uri) {
-            mActions.onAction(MODE_IMAGE, uri);
-            mEST.notifyStateChanged(mMode, mState);
-        }
-
-        public void onInsertImage(int resId) {
-            mActions.onAction(MODE_IMAGE, resId);
-            mEST.notifyStateChanged(mMode, mState);
-        }
-
-        private void insertImageFromUri(Uri uri) {
-            insertImageSpan(new EditStyledTextSpans.RescalableImageSpan(mEST.getContext(),
-                    uri, mEST.getMaxImageWidthPx()), mEST.getSelectionStart());
-        }
-
-        private void insertImageFromResId(int resId) {
-            insertImageSpan(new EditStyledTextSpans.RescalableImageSpan(mEST.getContext(),
-                    resId, mEST.getMaxImageWidthDip()), mEST.getSelectionStart());
-        }
-
-        private void insertHorizontalLine() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- onInsertHorizontalLine:");
-            }
-            int curpos = mEST.getSelectionStart();
-            if (curpos > 0 && mEST.getText().charAt(curpos - 1) != '\n') {
-                mEST.getText().insert(curpos++, "\n");
-            }
-            insertImageSpan(
-                    new HorizontalLineSpan(0xFF000000, mEST.getWidth(), mEST.getText()),
-                    curpos++);
-            mEST.getText().insert(curpos++, "\n");
-            mEST.setSelection(curpos);
-            mEST.notifyStateChanged(mMode, mState);
-        }
-
-        private void clearStyles(CharSequence txt) {
-            if (DBG) {
-                Log.d("EditStyledText", "--- onClearStyles");
-            }
-            int len = txt.length();
-            if (txt instanceof Editable) {
-                Editable editable = (Editable) txt;
-                Object[] styles = editable.getSpans(0, len, Object.class);
-                for (Object style : styles) {
-                    if (style instanceof ParagraphStyle || style instanceof QuoteSpan
-                            || style instanceof CharacterStyle
-                            && !(style instanceof UnderlineSpan)) {
-                        if (style instanceof ImageSpan || style instanceof HorizontalLineSpan) {
-                            int start = editable.getSpanStart(style);
-                            int end = editable.getSpanEnd(style);
-                            editable.replace(start, end, "");
-                        }
-                        editable.removeSpan(style);
-                    }
-                }
-            }
-        }
-
-        public void onClearStyles() {
-            mActions.onAction(MODE_CLEARSTYLES);
-        }
-
-        public void onCancelViewManagers() {
-            mActions.onAction(MODE_CANCEL);
-        }
-
-        private void clearStyles() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- onClearStyles");
-            }
-            clearStyles(mEST.getText());
-            mEST.setBackgroundDrawable(mEST.mDefaultBackground);
-            mBackgroundColor = DEFAULT_TRANSPARENT_COLOR;
-            onRefreshZeoWidthChar();
-        }
-
-        public void onRefreshZeoWidthChar() {
-            Editable txt = mEST.getText();
-            for (int i = 0; i < txt.length(); i++) {
-                if (txt.charAt(i) == ZEROWIDTHCHAR) {
-                    txt.replace(i, i + 1, "");
-                    i--;
-                }
-            }
-        }
-
-        public void onRefreshStyles() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- onRefreshStyles");
-            }
-            Editable txt = mEST.getText();
-            int len = txt.length();
-            int width = mEST.getWidth();
-            HorizontalLineSpan[] lines = txt.getSpans(0, len, HorizontalLineSpan.class);
-            for (HorizontalLineSpan line : lines) {
-                line.resetWidth(width);
-            }
-            MarqueeSpan[] marquees = txt.getSpans(0, len, MarqueeSpan.class);
-            for (MarqueeSpan marquee : marquees) {
-                marquee.resetColor(mEST.getBackgroundColor());
-            }
-
-            if (lines.length > 0) {
-                // This is hack, bad needed for renewing View
-                // by inserting new line.
-                txt.replace(0, 1, "" + txt.charAt(0));
-            }
-        }
-
-        public void setBackgroundColor(int color) {
-            mBackgroundColor = color;
-        }
-
-        public void setItemSize(int size, boolean reset) {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- setItemSize");
-            }
-            if (isWaitingNextAction()) {
-                mSizeWaitInput = size;
-            } else if (mState == STATE_SELECTED || mState == STATE_SELECT_FIX) {
-                if (size > 0) {
-                    changeSizeSelectedText(size);
-                }
-                if (reset) {
-                    resetEdit();
-                }
-            }
-        }
-
-        public void setItemColor(int color, boolean reset) {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- setItemColor");
-            }
-            if (isWaitingNextAction()) {
-                mColorWaitInput = color;
-            } else if (mState == STATE_SELECTED || mState == STATE_SELECT_FIX) {
-                if (color != DEFAULT_TRANSPARENT_COLOR) {
-                    changeColorSelectedText(color);
-                }
-                if (reset) {
-                    resetEdit();
-                }
-            }
-        }
-
-        public void setAlignment(Layout.Alignment align) {
-            if (mState == STATE_SELECTED || mState == STATE_SELECT_FIX) {
-                changeAlign(align);
-                resetEdit();
-            }
-        }
-
-        public void setTelop() {
-            if (mState == STATE_SELECTED || mState == STATE_SELECT_FIX) {
-                addTelop();
-                resetEdit();
-            }
-        }
-
-        public void setSwing() {
-            if (mState == STATE_SELECTED || mState == STATE_SELECT_FIX) {
-                addSwing();
-                resetEdit();
-            }
-        }
-
-        public void setMarquee(int marquee) {
-            if (mState == STATE_SELECTED || mState == STATE_SELECT_FIX) {
-                addMarquee(marquee);
-                resetEdit();
-            }
-        }
-
-        public void setTextComposingMask(int start, int end) {
-            if (DBG) {
-                Log.d(TAG, "--- setTextComposingMask:" + start + "," + end);
-            }
-            int min = Math.min(start, end);
-            int max = Math.max(start, end);
-            int foregroundColor;
-            if (isWaitInput() && mColorWaitInput != DEFAULT_TRANSPARENT_COLOR) {
-                foregroundColor = mColorWaitInput;
-            } else {
-                foregroundColor = mEST.getForegroundColor(min);
-            }
-            int backgroundColor = mEST.getBackgroundColor();
-            if (DBG) {
-                Log.d(TAG,
-                        "--- fg:" + Integer.toHexString(foregroundColor) + ",bg:"
-                                + Integer.toHexString(backgroundColor) + "," + isWaitInput()
-                                + "," + "," + mMode);
-            }
-            if (foregroundColor == backgroundColor) {
-                int maskColor = 0x80000000 | ~(backgroundColor | 0xFF000000);
-                if (mComposingTextMask == null
-                        || mComposingTextMask.getBackgroundColor() != maskColor) {
-                    mComposingTextMask = new BackgroundColorSpan(maskColor);
-                }
-                mEST.getText().setSpan(mComposingTextMask, min, max,
-                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            }
-        }
-
-        private void setEditMode(int mode) {
-            mMode = mode;
-        }
-
-        private void setSelectState(int state) {
-            mState = state;
-        }
-
-        public void unsetTextComposingMask() {
-            if (DBG) {
-                Log.d(TAG, "--- unsetTextComposingMask");
-            }
-            if (mComposingTextMask != null) {
-                mEST.getText().removeSpan(mComposingTextMask);
-                mComposingTextMask = null;
-            }
-        }
-
-        public boolean isEditting() {
-            return mEditFlag;
-        }
-
-        /* If the style of the span is added, add check case for that style */
-        public boolean isStyledText() {
-            Editable txt = mEST.getText();
-            int len = txt.length();
-            if (txt.getSpans(0, len, ParagraphStyle.class).length > 0
-                    || txt.getSpans(0, len, QuoteSpan.class).length > 0
-                    || txt.getSpans(0, len, CharacterStyle.class).length > 0
-                    || mBackgroundColor != DEFAULT_TRANSPARENT_COLOR) {
-                return true;
-            }
-            return false;
-        }
-
-        public boolean isSoftKeyBlocked() {
-            return mSoftKeyBlockFlag;
-        }
-
-        public boolean isWaitInput() {
-            return mWaitInputFlag;
-        }
-
-        public int getBackgroundColor() {
-            return mBackgroundColor;
-        }
-
-        public int getEditMode() {
-            return mMode;
-        }
-
-        public int getSelectState() {
-            return mState;
-        }
-
-        public int getSelectionStart() {
-            return mCurStart;
-        }
-
-        public int getSelectionEnd() {
-            return mCurEnd;
-        }
-
-        public int getSizeWaitInput() {
-            return mSizeWaitInput;
-        }
-
-        public int getColorWaitInput() {
-            return mColorWaitInput;
-        }
-
-        private void setInternalSelection(int curStart, int curEnd) {
-            mCurStart = curStart;
-            mCurEnd = curEnd;
-        }
-
-        public void
-                updateSpanPreviousFromCursor(Editable txt, int start, int before, int after) {
-            if (DBG) {
-                Log.d(LOG_TAG, "updateSpanPrevious:" + start + "," + before + "," + after);
-            }
-            int end = start + after;
-            int min = Math.min(start, end);
-            int max = Math.max(start, end);
-            Object[] spansBefore = txt.getSpans(min, min, Object.class);
-            for (Object span : spansBefore) {
-                if (span instanceof ForegroundColorSpan || span instanceof AbsoluteSizeSpan
-                        || span instanceof MarqueeSpan || span instanceof AlignmentSpan) {
-                    int spanstart = txt.getSpanStart(span);
-                    int spanend = txt.getSpanEnd(span);
-                    if (DBG) {
-                        Log.d(LOG_TAG, "spantype:" + span.getClass() + "," + spanstart);
-                    }
-                    int tempmax = max;
-                    if (span instanceof MarqueeSpan || span instanceof AlignmentSpan) {
-                        // Line Span
-                        tempmax = findLineEnd(mEST.getText(), max);
-                    } else {
-                        if (mKeepNonLineSpan) {
-                            tempmax = spanend;
-                        }
-                    }
-                    if (spanend < tempmax) {
-                        if (DBG) {
-                            Log.d(LOG_TAG, "updateSpanPrevious: extend span");
-                        }
-                        txt.setSpan(span, spanstart, tempmax,
-                                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-                    }
-                } else if (span instanceof HorizontalLineSpan) {
-                    int spanstart = txt.getSpanStart(span);
-                    int spanend = txt.getSpanEnd(span);
-                    if (before > after) {
-                        // When text is deleted just after horizontalLineSpan, horizontalLineSpan
-                        // has to be deleted, because the charactor just after horizontalLineSpan
-                        // is '\n'.
-                        txt.replace(spanstart, spanend, "");
-                        txt.removeSpan(span);
-                    } else {
-                        // When text is added just after horizontalLineSpan add '\n' just after
-                        // horizontalLineSpan.
-                        if (spanend == end && end < txt.length()
-                                && mEST.getText().charAt(end) != '\n') {
-                            mEST.getText().insert(end, "\n");
-                        }
-                    }
-                }
-            }
-        }
-
-        public void updateSpanNextToCursor(Editable txt, int start, int before, int after) {
-            if (DBG) {
-                Log.d(LOG_TAG, "updateSpanNext:" + start + "," + before + "," + after);
-            }
-            int end = start + after;
-            int min = Math.min(start, end);
-            int max = Math.max(start, end);
-            Object[] spansAfter = txt.getSpans(max, max, Object.class);
-            for (Object span : spansAfter) {
-                if (span instanceof MarqueeSpan || span instanceof AlignmentSpan) {
-                    int spanstart = txt.getSpanStart(span);
-                    int spanend = txt.getSpanEnd(span);
-                    if (DBG) {
-                        Log.d(LOG_TAG, "spantype:" + span.getClass() + "," + spanend);
-                    }
-                    int tempmin = min;
-                    if (span instanceof MarqueeSpan || span instanceof AlignmentSpan) {
-                        tempmin = findLineStart(mEST.getText(), min);
-                    }
-                    if (tempmin < spanstart && before > after) {
-                        txt.removeSpan(span);
-                    } else if (spanstart > min) {
-                        txt.setSpan(span, min, spanend, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-                    }
-                } else if (span instanceof HorizontalLineSpan) {
-                    int spanstart = txt.getSpanStart(span);
-                    // Whene text is changed just before horizontalLineSpan and there is no '\n'
-                    // just before horizontalLineSpan add '\n'
-                    if (spanstart == end && end > 0 && mEST.getText().charAt(end - 1) != '\n') {
-                        mEST.getText().insert(end, "\n");
-                        mEST.setSelection(end);
-                    }
-                }
-            }
-        }
-
-        /** canPaste returns true only if ClipboardManager doen't contain text. */
-        public boolean canPaste() {
-            return (mCopyBuffer != null && mCopyBuffer.length() > 0 && removeImageChar(
-                    mCopyBuffer).length() == 0);
-        }
-
-        private void endEdit() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- handleCancel");
-            }
-            mMode = MODE_NOTHING;
-            mState = STATE_SELECT_OFF;
-            mEditFlag = false;
-            mColorWaitInput = DEFAULT_TRANSPARENT_COLOR;
-            mSizeWaitInput = 0;
-            mWaitInputFlag = false;
-            mSoftKeyBlockFlag = false;
-            mKeepNonLineSpan = false;
-            mTextIsFinishedFlag = false;
-            unsetSelect();
-            mEST.setOnClickListener(null);
-            unblockSoftKey();
-        }
-
-        private void fixSelectionAndDoNextAction() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- handleComplete:" + mCurStart + "," + mCurEnd);
-            }
-            if (!mEditFlag) {
-                return;
-            }
-            if (mCurStart == mCurEnd) {
-                if (DBG) {
-                    Log.d(LOG_TAG, "--- cancel handle complete:" + mCurStart);
-                }
-                resetEdit();
-                return;
-            }
-            if (mState == STATE_SELECTED) {
-                mState = STATE_SELECT_FIX;
-            }
-            // When the complete button is clicked, this should do action.
-            mActions.doNext(mMode);
-            //MetaKeyKeyListener.stopSelecting(mEST, mEST.getText());
-            stopSelecting(mEST, mEST.getText());
-        }
-
-        // Remove obj character for DynamicDrawableSpan from clipboard.
-        private SpannableStringBuilder removeImageChar(SpannableStringBuilder text) {
-            SpannableStringBuilder buf = new SpannableStringBuilder(text);
-            DynamicDrawableSpan[] styles =
-                    buf.getSpans(0, buf.length(), DynamicDrawableSpan.class);
-            for (DynamicDrawableSpan style : styles) {
-                if (style instanceof HorizontalLineSpan
-                        || style instanceof RescalableImageSpan) {
-                    int start = buf.getSpanStart(style);
-                    int end = buf.getSpanEnd(style);
-                    buf.replace(start, end, "");
-                }
-            }
-            return buf;
-        }
-
-        private void copyToClipBoard() {
-            int min = Math.min(getSelectionStart(), getSelectionEnd());
-            int max = Math.max(getSelectionStart(), getSelectionEnd());
-            mCopyBuffer = (SpannableStringBuilder) mEST.getText().subSequence(min, max);
-            SpannableStringBuilder clipboardtxt = removeImageChar(mCopyBuffer);
-            ClipboardManager clip =
-                    (ClipboardManager) getContext()
-                            .getSystemService(Context.CLIPBOARD_SERVICE);
-            clip.setText(clipboardtxt);
-            if (DBG) {
-                dumpSpannableString(clipboardtxt);
-                dumpSpannableString(mCopyBuffer);
-            }
-        }
-
-        private void cutToClipBoard() {
-            copyToClipBoard();
-            int min = Math.min(getSelectionStart(), getSelectionEnd());
-            int max = Math.max(getSelectionStart(), getSelectionEnd());
-            mEST.getText().delete(min, max);
-        }
-
-        private boolean isClipBoardChanged(CharSequence clipboardText) {
-            if (DBG) {
-                Log.d(TAG, "--- isClipBoardChanged:" + clipboardText);
-            }
-            if (mCopyBuffer == null) {
-                return true;
-            }
-            int len = clipboardText.length();
-            CharSequence removedClipBoard = removeImageChar(mCopyBuffer);
-            if (DBG) {
-                Log.d(TAG, "--- clipBoard:" + len + "," + removedClipBoard + clipboardText);
-            }
-            if (len != removedClipBoard.length()) {
-                return true;
-            }
-            for (int i = 0; i < len; ++i) {
-                if (clipboardText.charAt(i) != removedClipBoard.charAt(i)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private void pasteFromClipboard() {
-            int min = Math.min(mEST.getSelectionStart(), mEST.getSelectionEnd());
-            int max = Math.max(mEST.getSelectionStart(), mEST.getSelectionEnd());
-            // TODO: Find more smart way to set Span to Clipboard.
-            Selection.setSelection(mEST.getText(), max);
-            ClipboardManager clip =
-                    (ClipboardManager) getContext()
-                            .getSystemService(Context.CLIPBOARD_SERVICE);
-            mKeepNonLineSpan = true;
-            mEST.getText().replace(min, max, clip.getText());
-            if (!isClipBoardChanged(clip.getText())) {
-                if (DBG) {
-                    Log.d(TAG, "--- handlePaste: startPasteImage");
-                }
-                DynamicDrawableSpan[] styles =
-                        mCopyBuffer.getSpans(0, mCopyBuffer.length(),
-                                DynamicDrawableSpan.class);
-                for (DynamicDrawableSpan style : styles) {
-                    int start = mCopyBuffer.getSpanStart(style);
-                    if (style instanceof HorizontalLineSpan) {
-                        insertImageSpan(new HorizontalLineSpan(0xFF000000, mEST.getWidth(),
-                                mEST.getText()), min + start);
-                    } else if (style instanceof RescalableImageSpan) {
-                        insertImageSpan(
-                                new RescalableImageSpan(mEST.getContext(),
-                                        ((RescalableImageSpan) style).getContentUri(),
-                                        mEST.getMaxImageWidthPx()), min + start);
-                    }
-                }
-            }
-        }
-
-        private void handleSelectAll() {
-            if (!mEditFlag) {
-                return;
-            }
-            mActions.onAction(MODE_SELECTALL);
-        }
-
-        private void selectAll() {
-            Selection.selectAll(mEST.getText());
-            mCurStart = mEST.getSelectionStart();
-            mCurEnd = mEST.getSelectionEnd();
-            mMode = MODE_SELECT;
-            mState = STATE_SELECT_FIX;
-        }
-
-        private void resetEdit() {
-            endEdit();
-            mEditFlag = true;
-            mEST.notifyStateChanged(mMode, mState);
-        }
-
-        private void setSelection() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- onSelect:" + mCurStart + "," + mCurEnd);
-            }
-            if (mCurStart >= 0 && mCurStart <= mEST.getText().length() && mCurEnd >= 0
-                    && mCurEnd <= mEST.getText().length()) {
-                if (mCurStart < mCurEnd) {
-                    mEST.setSelection(mCurStart, mCurEnd);
-                    mState = STATE_SELECTED;
-                } else if (mCurStart > mCurEnd) {
-                    mEST.setSelection(mCurEnd, mCurStart);
-                    mState = STATE_SELECTED;
-                } else {
-                    mState = STATE_SELECT_ON;
-                }
-            } else {
-                Log.e(LOG_TAG, "Select is on, but cursor positions are illigal.:"
-                        + mEST.getText().length() + "," + mCurStart + "," + mCurEnd);
-            }
-        }
-
-        private void unsetSelect() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- offSelect");
-            }
-            //MetaKeyKeyListener.stopSelecting(mEST, mEST.getText());
-            stopSelecting(mEST, mEST.getText());
-            int currpos = mEST.getSelectionStart();
-            mEST.setSelection(currpos, currpos);
-            mState = STATE_SELECT_OFF;
-        }
-
-        private void setSelectStartPos() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- setSelectStartPos");
-            }
-            mCurStart = mEST.getSelectionStart();
-            mState = STATE_SELECT_ON;
-        }
-
-        private void setSelectEndPos() {
-            if (mEST.getSelectionEnd() == mCurStart) {
-                setEndPos(mEST.getSelectionStart());
-            } else {
-                setEndPos(mEST.getSelectionEnd());
-            }
-        }
-
-        public void setEndPos(int pos) {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- setSelectedEndPos:" + pos);
-            }
-            mCurEnd = pos;
-            setSelection();
-        }
-
-        private boolean isWaitingNextAction() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- waitingNext:" + mCurStart + "," + mCurEnd + "," + mState);
-            }
-            if (mCurStart == mCurEnd && mState == STATE_SELECT_FIX) {
-                waitSelection();
-                return true;
-            } else {
-                resumeSelection();
-                return false;
-            }
-        }
-
-        private void waitSelection() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- waitSelection");
-            }
-            mWaitInputFlag = true;
-            if (mCurStart == mCurEnd) {
-                mState = STATE_SELECT_ON;
-            } else {
-                mState = STATE_SELECTED;
-            }
-            //MetaKeyKeyListener.startSelecting(mEST, mEST.getText());
-            startSelecting(mEST, mEST.getText());
-        }
-
-        private void resumeSelection() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- resumeSelection");
-            }
-            mWaitInputFlag = false;
-            mState = STATE_SELECT_FIX;
-            //MetaKeyKeyListener.stopSelecting(mEST, mEST.getText());
-            stopSelecting(mEST, mEST.getText());
-        }
-
-        private boolean isTextSelected() {
-            return (mState == STATE_SELECTED || mState == STATE_SELECT_FIX);
-        }
-
-        private void setStyledTextSpan(Object span, int start, int end) {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- setStyledTextSpan:" + mMode + "," + start + "," + end);
-            }
-            int min = Math.min(start, end);
-            int max = Math.max(start, end);
-            mEST.getText().setSpan(span, min, max, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            Selection.setSelection(mEST.getText(), max);
-        }
-
-        private void setLineStyledTextSpan(Object span) {
-            int min = Math.min(mCurStart, mCurEnd);
-            int max = Math.max(mCurStart, mCurEnd);
-            int current = mEST.getSelectionStart();
-            int start = findLineStart(mEST.getText(), min);
-            int end = findLineEnd(mEST.getText(), max);
-            if (start == end) {
-                mEST.getText().insert(end, "\n");
-                setStyledTextSpan(span, start, end + 1);
-            } else {
-                setStyledTextSpan(span, start, end);
-            }
-            Selection.setSelection(mEST.getText(), current);
-        }
-
-        private void changeSizeSelectedText(int size) {
-            if (mCurStart != mCurEnd) {
-                setStyledTextSpan(new AbsoluteSizeSpan(size), mCurStart, mCurEnd);
-            } else {
-                Log.e(LOG_TAG, "---changeSize: Size of the span is zero");
-            }
-        }
-
-        private void changeColorSelectedText(int color) {
-            if (mCurStart != mCurEnd) {
-                setStyledTextSpan(new ForegroundColorSpan(color), mCurStart, mCurEnd);
-            } else {
-                Log.e(LOG_TAG, "---changeColor: Size of the span is zero");
-            }
-        }
-
-        private void changeAlign(Layout.Alignment align) {
-            setLineStyledTextSpan(new AlignmentSpan.Standard(align));
-        }
-
-        private void addTelop() {
-            addMarquee(MarqueeSpan.ALTERNATE);
-        }
-
-        private void addSwing() {
-            addMarquee(MarqueeSpan.SCROLL);
-        }
-
-        private void addMarquee(int marquee) {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- addMarquee:" + marquee);
-            }
-            setLineStyledTextSpan(new MarqueeSpan(marquee, mEST.getBackgroundColor()));
-        }
-
-        private void insertImageSpan(DynamicDrawableSpan span, int curpos) {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- insertImageSpan:");
-            }
-            if (span != null && span.getDrawable() != null) {
-                mEST.getText().insert(curpos, "" + IMAGECHAR);
-                mEST.getText().setSpan(span, curpos, curpos + 1,
-                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-                mEST.notifyStateChanged(mMode, mState);
-            } else {
-                Log.e(LOG_TAG, "--- insertImageSpan: null span was inserted");
-                mEST.sendHintMessage(HINT_MSG_BIG_SIZE_ERROR);
-            }
-        }
-
-        private int findLineStart(Editable text, int current) {
-            int pos = current;
-            for (; pos > 0; pos--) {
-                if (text.charAt(pos - 1) == '\n') {
-                    break;
-                }
-            }
-            if (DBG) {
-                Log.d(LOG_TAG, "--- findLineStart:" + current + "," + text.length() + ","
-                        + pos);
-            }
-            return pos;
-        }
-
-        private int findLineEnd(Editable text, int current) {
-            int pos = current;
-            for (; pos < text.length(); pos++) {
-                if (text.charAt(pos) == '\n') {
-                    pos++;
-                    break;
-                }
-            }
-            if (DBG) {
-                Log.d(LOG_TAG, "--- findLineEnd:" + current + "," + text.length() + "," + pos);
-            }
-            return pos;
-        }
-
-        // Only for debug.
-        private void dumpSpannableString(CharSequence txt) {
-            if (txt instanceof Spannable) {
-                Spannable spannable = (Spannable) txt;
-                int len = spannable.length();
-                if (DBG) {
-                    Log.d(TAG, "--- dumpSpannableString, txt:" + spannable + ", len:" + len);
-                }
-                Object[] styles = spannable.getSpans(0, len, Object.class);
-                for (Object style : styles) {
-                    if (DBG) {
-                        Log.d(TAG,
-                                "--- dumpSpannableString, class:" + style + ","
-                                        + spannable.getSpanStart(style) + ","
-                                        + spannable.getSpanEnd(style) + ","
-                                        + spannable.getSpanFlags(style));
-                    }
-                }
-            }
-        }
-
-        public void showSoftKey() {
-            showSoftKey(mEST.getSelectionStart(), mEST.getSelectionEnd());
-        }
-
-        public void showSoftKey(int oldSelStart, int oldSelEnd) {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- showsoftkey");
-            }
-            if (!mEST.isFocused() || isSoftKeyBlocked()) {
-                return;
-            }
-            mSkr.mNewStart = Selection.getSelectionStart(mEST.getText());
-            mSkr.mNewEnd = Selection.getSelectionEnd(mEST.getText());
-            InputMethodManager imm =
-                    (InputMethodManager) getContext().getSystemService(
-                            Context.INPUT_METHOD_SERVICE);
-            if (imm.showSoftInput(mEST, 0, mSkr) && mSkr != null) {
-                Selection.setSelection(getText(), oldSelStart, oldSelEnd);
-            }
-        }
-
-        public void hideSoftKey() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- hidesoftkey");
-            }
-            if (!mEST.isFocused()) {
-                return;
-            }
-            mSkr.mNewStart = Selection.getSelectionStart(mEST.getText());
-            mSkr.mNewEnd = Selection.getSelectionEnd(mEST.getText());
-            InputMethodManager imm =
-                    (InputMethodManager) mEST.getContext().getSystemService(
-                            Context.INPUT_METHOD_SERVICE);
-            imm.hideSoftInputFromWindow(mEST.getWindowToken(), 0, mSkr);
-        }
-
-        public void blockSoftKey() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- blockSoftKey:");
-            }
-            hideSoftKey();
-            mSoftKeyBlockFlag = true;
-        }
-
-        public void unblockSoftKey() {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- unblockSoftKey:");
-            }
-            mSoftKeyBlockFlag = false;
-        }
-    }
-
-    private class StyledTextHtmlStandard implements StyledTextHtmlConverter {
-        public String toHtml(Spanned text) {
-            return Html.toHtml(text);
-        }
-
-        public String toHtml(Spanned text, boolean escapeNonAsciiChar) {
-            return Html.toHtml(text);
-        }
-
-        public String toHtml(Spanned text, boolean escapeNonAsciiChar, int width, float scale) {
-            return Html.toHtml(text);
-        }
-
-        public Spanned fromHtml(String source) {
-            return Html.fromHtml(source);
-        }
-
-        public Spanned fromHtml(String source, ImageGetter imageGetter, TagHandler tagHandler) {
-            return Html.fromHtml(source, imageGetter, tagHandler);
-        }
-    }
-
-    private class StyledTextConverter {
-        private EditStyledText mEST;
-        private StyledTextHtmlConverter mHtml;
-
-        public StyledTextConverter(EditStyledText est, StyledTextHtmlConverter html) {
-            mEST = est;
-            mHtml = html;
-        }
-
-        public void setStyledTextHtmlConverter(StyledTextHtmlConverter html) {
-            mHtml = html;
-        }
-
-        public String getHtml(boolean escapeFlag) {
-            mEST.clearComposingText();
-            mEST.onRefreshZeoWidthChar();
-            String htmlBody = mHtml.toHtml(mEST.getText(), escapeFlag);
-            if (DBG) {
-                Log.d(TAG, "--- getHtml:" + htmlBody);
-            }
-            return htmlBody;
-        }
-
-        public String getPreviewHtml() {
-            mEST.clearComposingText();
-            mEST.onRefreshZeoWidthChar();
-            String html =
-                    mHtml.toHtml(mEST.getText(), true, getMaxImageWidthDip(),
-                            getPaddingScale());
-            int bgColor = mEST.getBackgroundColor();
-            html =
-                    String.format("<body bgcolor=\"#%02X%02X%02X\">%s</body>",
-                            Color.red(bgColor), Color.green(bgColor), Color.blue(bgColor),
-                            html);
-            if (DBG) {
-                Log.d(TAG, "--- getPreviewHtml:" + html + "," + mEST.getWidth());
-            }
-            return html;
-        }
-
-        public void getUriArray(ArrayList<Uri> uris, Editable text) {
-            uris.clear();
-            if (DBG) {
-                Log.d(TAG, "--- getUriArray:");
-            }
-            int len = text.length();
-            int next;
-            for (int i = 0; i < text.length(); i = next) {
-                next = text.nextSpanTransition(i, len, ImageSpan.class);
-                ImageSpan[] images = text.getSpans(i, next, ImageSpan.class);
-                for (int j = 0; j < images.length; j++) {
-                    if (DBG) {
-                        Log.d(TAG, "--- getUriArray: foundArray" + images[j].getSource());
-                    }
-                    uris.add(Uri.parse(images[j].getSource()));
-                }
-            }
-        }
-
-        public void SetHtml(String html) {
-            final Spanned spanned = mHtml.fromHtml(html, new Html.ImageGetter() {
-                public Drawable getDrawable(String src) {
-                    Log.d(TAG, "--- sethtml: src=" + src);
-                    if (src.startsWith("content://")) {
-                        Uri uri = Uri.parse(src);
-                        try {
-                            Drawable drawable = null;
-                            Bitmap bitmap = null;
-                            System.gc();
-                            InputStream is =
-                                    mEST.getContext().getContentResolver().openInputStream(uri);
-                            BitmapFactory.Options opt = new BitmapFactory.Options();
-                            opt.inJustDecodeBounds = true;
-                            BitmapFactory.decodeStream(is, null, opt);
-                            is.close();
-                            is =  mEST.getContext().getContentResolver().openInputStream(uri);
-                            int width, height;
-                            width = opt.outWidth;
-                            height = opt.outHeight;
-                            if (opt.outWidth > getMaxImageWidthPx()) {
-                                width = getMaxImageWidthPx();
-                                height = height * getMaxImageWidthPx() / opt.outWidth;
-                                Rect padding = new Rect(0, 0, width, height);
-                                bitmap = BitmapFactory.decodeStream(is, padding, null);
-                            } else {
-                                bitmap = BitmapFactory.decodeStream(is);
-                            }
-                            drawable = new BitmapDrawable(
-                                    mEST.getContext().getResources(), bitmap);
-                            drawable.setBounds(0, 0, width, height);
-                            is.close();
-                            return drawable;
-                        } catch (Exception e) {
-                            Log.e(TAG, "--- set html: Failed to loaded content " + uri, e);
-                            return null;
-                        } catch (OutOfMemoryError e) {
-                            Log.e(TAG, "OutOfMemoryError");
-                            mEST.setHint(HINT_MSG_BIG_SIZE_ERROR);
-
-                            return null;
-                        }
-                    }
-                    return null;
-                }
-            }, null);
-            mEST.setText(spanned);
-        }
-    }
-
-    private static class SoftKeyReceiver extends ResultReceiver {
-        int mNewStart;
-        int mNewEnd;
-        EditStyledText mEST;
-
-        SoftKeyReceiver(EditStyledText est) {
-            super(est.getHandler());
-            mEST = est;
-        }
-
-        @Override
-        protected void onReceiveResult(int resultCode, Bundle resultData) {
-            if (resultCode != InputMethodManager.RESULT_SHOWN) {
-                Selection.setSelection(mEST.getText(), mNewStart, mNewEnd);
-            }
-        }
-    }
-
-    public static class SavedStyledTextState extends BaseSavedState {
-        public int mBackgroundColor;
-
-        SavedStyledTextState(Parcelable superState) {
-            super(superState);
-        }
-
-        @Override
-        public void writeToParcel(Parcel out, int flags) {
-            super.writeToParcel(out, flags);
-            out.writeInt(mBackgroundColor);
-        }
-
-        @Override
-        public String toString() {
-            return "EditStyledText.SavedState{"
-                    + Integer.toHexString(System.identityHashCode(this)) + " bgcolor="
-                    + mBackgroundColor + "}";
-        }
-    }
-
-    private static class StyledTextDialog {
-        private static final int TYPE_FOREGROUND = 0;
-        private static final int TYPE_BACKGROUND = 1;
-        private Builder mBuilder;
-        private AlertDialog mAlertDialog;
-        private CharSequence mColorTitle;
-        private CharSequence mSizeTitle;
-        private CharSequence mAlignTitle;
-        private CharSequence mMarqueeTitle;
-        private CharSequence[] mColorNames;
-        private CharSequence[] mColorInts;
-        private CharSequence[] mSizeNames;
-        private CharSequence[] mSizeDisplayInts;
-        private CharSequence[] mSizeSendInts;
-        private CharSequence[] mAlignNames;
-        private CharSequence[] mMarqueeNames;
-        private CharSequence mColorDefaultMessage;
-        private EditStyledText mEST;
-
-        public StyledTextDialog(EditStyledText est) {
-            mEST = est;
-        }
-
-        public void setBuilder(Builder builder) {
-            mBuilder = builder;
-        }
-
-        public void setColorAlertParams(CharSequence colortitle, CharSequence[] colornames,
-                CharSequence[] colorInts, CharSequence defaultColorMessage) {
-            mColorTitle = colortitle;
-            mColorNames = colornames;
-            mColorInts = colorInts;
-            mColorDefaultMessage = defaultColorMessage;
-        }
-
-        public void setSizeAlertParams(CharSequence sizetitle, CharSequence[] sizenames,
-                CharSequence[] sizedisplayints, CharSequence[] sizesendints) {
-            mSizeTitle = sizetitle;
-            mSizeNames = sizenames;
-            mSizeDisplayInts = sizedisplayints;
-            mSizeSendInts = sizesendints;
-        }
-
-        public void setAlignAlertParams(CharSequence aligntitle, CharSequence[] alignnames) {
-            mAlignTitle = aligntitle;
-            mAlignNames = alignnames;
-        }
-
-        public void setMarqueeAlertParams(CharSequence marqueetitle,
-                CharSequence[] marqueenames) {
-            mMarqueeTitle = marqueetitle;
-            mMarqueeNames = marqueenames;
-        }
-
-        private boolean checkColorAlertParams() {
-            if (DBG) {
-                Log.d(TAG, "--- checkParams");
-            }
-            if (mBuilder == null) {
-                Log.e(TAG, "--- builder is null.");
-                return false;
-            } else if (mColorTitle == null || mColorNames == null || mColorInts == null) {
-                Log.e(TAG, "--- color alert params are null.");
-                return false;
-            } else if (mColorNames.length != mColorInts.length) {
-                Log.e(TAG, "--- the length of color alert params are " + "different.");
-                return false;
-            }
-            return true;
-        }
-
-        private boolean checkSizeAlertParams() {
-            if (DBG) {
-                Log.d(TAG, "--- checkParams");
-            }
-            if (mBuilder == null) {
-                Log.e(TAG, "--- builder is null.");
-                return false;
-            } else if (mSizeTitle == null || mSizeNames == null || mSizeDisplayInts == null
-                    || mSizeSendInts == null) {
-                Log.e(TAG, "--- size alert params are null.");
-                return false;
-            } else if (mSizeNames.length != mSizeDisplayInts.length
-                    && mSizeSendInts.length != mSizeDisplayInts.length) {
-                Log.e(TAG, "--- the length of size alert params are " + "different.");
-                return false;
-            }
-            return true;
-        }
-
-        private boolean checkAlignAlertParams() {
-            if (DBG) {
-                Log.d(TAG, "--- checkAlignAlertParams");
-            }
-            if (mBuilder == null) {
-                Log.e(TAG, "--- builder is null.");
-                return false;
-            } else if (mAlignTitle == null) {
-                Log.e(TAG, "--- align alert params are null.");
-                return false;
-            }
-            return true;
-        }
-
-        private boolean checkMarqueeAlertParams() {
-            if (DBG) {
-                Log.d(TAG, "--- checkMarqueeAlertParams");
-            }
-            if (mBuilder == null) {
-                Log.e(TAG, "--- builder is null.");
-                return false;
-            } else if (mMarqueeTitle == null) {
-                Log.e(TAG, "--- Marquee alert params are null.");
-                return false;
-            }
-            return true;
-        }
-
-        private void buildDialogue(CharSequence title, CharSequence[] names,
-                DialogInterface.OnClickListener l) {
-            mBuilder.setTitle(title);
-            mBuilder.setIcon(0);
-            mBuilder.setPositiveButton(null, null);
-            mBuilder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
-                public void onClick(DialogInterface dialog, int which) {
-                    mEST.onStartEdit();
-                }
-            });
-            mBuilder.setItems(names, l);
-            mBuilder.setView(null);
-            mBuilder.setCancelable(true);
-            mBuilder.setOnCancelListener(new OnCancelListener() {
-                public void onCancel(DialogInterface arg0) {
-                    if (DBG) {
-                        Log.d(TAG, "--- oncancel");
-                    }
-                    mEST.onStartEdit();
-                }
-            });
-            mBuilder.show();
-        }
-
-        private void buildAndShowColorDialogue(int type, CharSequence title, int[] colors) {
-            final int HORIZONTAL_ELEMENT_NUM = 5;
-            final int BUTTON_SIZE = mEST.dipToPx(50);
-            final int BUTTON_MERGIN = mEST.dipToPx(2);
-            final int BUTTON_PADDING = mEST.dipToPx(15);
-            mBuilder.setTitle(title);
-            mBuilder.setIcon(0);
-            mBuilder.setPositiveButton(null, null);
-            mBuilder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
-                public void onClick(DialogInterface dialog, int which) {
-                    mEST.onStartEdit();
-                }
-            });
-            mBuilder.setItems(null, null);
-            LinearLayout verticalLayout = new LinearLayout(mEST.getContext());
-            verticalLayout.setOrientation(LinearLayout.VERTICAL);
-            verticalLayout.setGravity(Gravity.CENTER_HORIZONTAL);
-            verticalLayout.setPadding(BUTTON_PADDING, BUTTON_PADDING, BUTTON_PADDING,
-                    BUTTON_PADDING);
-            LinearLayout horizontalLayout = null;
-            for (int i = 0; i < colors.length; i++) {
-                if (i % HORIZONTAL_ELEMENT_NUM == 0) {
-                    horizontalLayout = new LinearLayout(mEST.getContext());
-                    verticalLayout.addView(horizontalLayout);
-                }
-                Button button = new Button(mEST.getContext());
-                button.setHeight(BUTTON_SIZE);
-                button.setWidth(BUTTON_SIZE);
-                ColorPaletteDrawable cp =
-                        new ColorPaletteDrawable(colors[i], BUTTON_SIZE, BUTTON_SIZE,
-                                BUTTON_MERGIN);
-                button.setBackgroundDrawable(cp);
-                button.setDrawingCacheBackgroundColor(colors[i]);
-                if (type == TYPE_FOREGROUND) {
-                    button.setOnClickListener(new View.OnClickListener() {
-                        public void onClick(View view) {
-                            mEST.setItemColor(view.getDrawingCacheBackgroundColor());
-                            if (mAlertDialog != null) {
-                                mAlertDialog.setView(null);
-                                mAlertDialog.dismiss();
-                                mAlertDialog = null;
-                            } else {
-                                Log.e(TAG,
-                                        "--- buildAndShowColorDialogue: can't find alertDialog");
-                            }
-                        }
-                    });
-                } else if (type == TYPE_BACKGROUND) {
-                    button.setOnClickListener(new View.OnClickListener() {
-                        public void onClick(View view) {
-                            mEST.setBackgroundColor(view.getDrawingCacheBackgroundColor());
-                            if (mAlertDialog != null) {
-                                mAlertDialog.setView(null);
-                                mAlertDialog.dismiss();
-                                mAlertDialog = null;
-                            } else {
-                                Log.e(TAG,
-                                        "--- buildAndShowColorDialogue: can't find alertDialog");
-                            }
-                        }
-                    });
-                }
-                horizontalLayout.addView(button);
-            }
-
-            if (type == TYPE_BACKGROUND) {
-                mBuilder.setPositiveButton(mColorDefaultMessage,
-                        new DialogInterface.OnClickListener() {
-                            public void onClick(DialogInterface dialog, int which) {
-                                mEST.setBackgroundColor(DEFAULT_TRANSPARENT_COLOR);
-                            }
-                        });
-            } else if (type == TYPE_FOREGROUND) {
-                mBuilder.setPositiveButton(mColorDefaultMessage,
-                        new DialogInterface.OnClickListener() {
-                            public void onClick(DialogInterface dialog, int which) {
-                                mEST.setItemColor(DEFAULT_FOREGROUND_COLOR);
-                            }
-                        });
-            }
-
-            mBuilder.setView(verticalLayout);
-            mBuilder.setCancelable(true);
-            mBuilder.setOnCancelListener(new OnCancelListener() {
-                public void onCancel(DialogInterface arg0) {
-                    mEST.onStartEdit();
-                }
-            });
-            mAlertDialog = mBuilder.show();
-        }
-
-        private void onShowForegroundColorAlertDialog() {
-            if (DBG) {
-                Log.d(TAG, "--- onShowForegroundColorAlertDialog");
-            }
-            if (!checkColorAlertParams()) {
-                return;
-            }
-            int[] colorints = new int[mColorInts.length];
-            for (int i = 0; i < colorints.length; i++) {
-                colorints[i] = Integer.parseInt((String) mColorInts[i], 16) - 0x01000000;
-            }
-            buildAndShowColorDialogue(TYPE_FOREGROUND, mColorTitle, colorints);
-        }
-
-        private void onShowBackgroundColorAlertDialog() {
-            if (DBG) {
-                Log.d(TAG, "--- onShowBackgroundColorAlertDialog");
-            }
-            if (!checkColorAlertParams()) {
-                return;
-            }
-            int[] colorInts = new int[mColorInts.length];
-            for (int i = 0; i < colorInts.length; i++) {
-                colorInts[i] = Integer.parseInt((String) mColorInts[i], 16) - 0x01000000;
-            }
-            buildAndShowColorDialogue(TYPE_BACKGROUND, mColorTitle, colorInts);
-        }
-
-        private void onShowSizeAlertDialog() {
-            if (DBG) {
-                Log.d(TAG, "--- onShowSizeAlertDialog");
-            }
-            if (!checkSizeAlertParams()) {
-                return;
-            }
-            buildDialogue(mSizeTitle, mSizeNames, new DialogInterface.OnClickListener() {
-                public void onClick(DialogInterface dialog, int which) {
-                    Log.d(TAG, "mBuilder.onclick:" + which);
-                    int size =
-                            mEST.dipToPx(Integer.parseInt((String) mSizeDisplayInts[which]));
-                    mEST.setItemSize(size);
-                }
-            });
-        }
-
-        private void onShowAlignAlertDialog() {
-            if (DBG) {
-                Log.d(TAG, "--- onShowAlignAlertDialog");
-            }
-            if (!checkAlignAlertParams()) {
-                return;
-            }
-            buildDialogue(mAlignTitle, mAlignNames, new DialogInterface.OnClickListener() {
-                public void onClick(DialogInterface dialog, int which) {
-                    Layout.Alignment align = Layout.Alignment.ALIGN_NORMAL;
-                    switch (which) {
-                        case 0:
-                            align = Layout.Alignment.ALIGN_NORMAL;
-                            break;
-                        case 1:
-                            align = Layout.Alignment.ALIGN_CENTER;
-                            break;
-                        case 2:
-                            align = Layout.Alignment.ALIGN_OPPOSITE;
-                            break;
-                        default:
-                            Log.e(TAG, "--- onShowAlignAlertDialog: got illigal align.");
-                            break;
-                    }
-                    mEST.setAlignment(align);
-                }
-            });
-        }
-
-        private void onShowMarqueeAlertDialog() {
-            if (DBG) {
-                Log.d(TAG, "--- onShowMarqueeAlertDialog");
-            }
-            if (!checkMarqueeAlertParams()) {
-                return;
-            }
-            buildDialogue(mMarqueeTitle, mMarqueeNames, new DialogInterface.OnClickListener() {
-                public void onClick(DialogInterface dialog, int which) {
-                    if (DBG) {
-                        Log.d(TAG, "mBuilder.onclick:" + which);
-                    }
-                    mEST.setMarquee(which);
-                }
-            });
-        }
-    }
-
-    private class MenuHandler implements MenuItem.OnMenuItemClickListener {
-        public boolean onMenuItemClick(MenuItem item) {
-            return onTextContextMenuItem(item.getItemId());
-        }
-    }
-
-    private static class StyledTextArrowKeyMethod extends ArrowKeyMovementMethod {
-        EditorManager mManager;
-        String LOG_TAG = "StyledTextArrowKeyMethod";
-
-        StyledTextArrowKeyMethod(EditorManager manager) {
-            super();
-            mManager = manager;
-        }
-
-        @Override
-        public boolean
-                onKeyDown(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
-            if (DBG) {
-                Log.d(LOG_TAG, "---onkeydown:" + keyCode);
-            }
-            mManager.unsetTextComposingMask();
-            if (mManager.getSelectState() == STATE_SELECT_ON
-                    || mManager.getSelectState() == STATE_SELECTED) {
-                return executeDown(widget, buffer, keyCode);
-            } else {
-                return super.onKeyDown(widget, buffer, keyCode, event);
-            }
-        }
-
-        private int getEndPos(TextView widget) {
-            int end;
-            if (widget.getSelectionStart() == mManager.getSelectionStart()) {
-                end = widget.getSelectionEnd();
-            } else {
-                end = widget.getSelectionStart();
-            }
-            return end;
-        }
-
-        protected boolean up(TextView widget, Spannable buffer) {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- up:");
-            }
-            Layout layout = widget.getLayout();
-            int end = getEndPos(widget);
-            int line = layout.getLineForOffset(end);
-            if (line > 0) {
-                int to;
-                if (layout.getParagraphDirection(line) == layout
-                        .getParagraphDirection(line - 1)) {
-                    float h = layout.getPrimaryHorizontal(end);
-                    to = layout.getOffsetForHorizontal(line - 1, h);
-                } else {
-                    to = layout.getLineStart(line - 1);
-                }
-                mManager.setEndPos(to);
-                mManager.onCursorMoved();
-            }
-            return true;
-        }
-
-        protected boolean down(TextView widget, Spannable buffer) {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- down:");
-            }
-            Layout layout = widget.getLayout();
-            int end = getEndPos(widget);
-            int line = layout.getLineForOffset(end);
-            if (line < layout.getLineCount() - 1) {
-                int to;
-                if (layout.getParagraphDirection(line) == layout
-                        .getParagraphDirection(line + 1)) {
-                    float h = layout.getPrimaryHorizontal(end);
-                    to = layout.getOffsetForHorizontal(line + 1, h);
-                } else {
-                    to = layout.getLineStart(line + 1);
-                }
-                mManager.setEndPos(to);
-                mManager.onCursorMoved();
-            }
-            return true;
-        }
-
-        protected boolean left(TextView widget, Spannable buffer) {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- left:");
-            }
-            Layout layout = widget.getLayout();
-            int to = layout.getOffsetToLeftOf(getEndPos(widget));
-            mManager.setEndPos(to);
-            mManager.onCursorMoved();
-            return true;
-        }
-
-        protected boolean right(TextView widget, Spannable buffer) {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- right:");
-            }
-            Layout layout = widget.getLayout();
-            int to = layout.getOffsetToRightOf(getEndPos(widget));
-            mManager.setEndPos(to);
-            mManager.onCursorMoved();
-            return true;
-        }
-
-        private boolean executeDown(TextView widget, Spannable buffer, int keyCode) {
-            if (DBG) {
-                Log.d(LOG_TAG, "--- executeDown: " + 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:
-                    mManager.onFixSelectedItem();
-                    handled = true;
-                    break;
-            }
-            return handled;
-        }
-    }
-
-    public static class StyledTextInputConnection extends InputConnectionWrapper {
-        EditStyledText mEST;
-
-        public StyledTextInputConnection(InputConnection target, EditStyledText est) {
-            super(target, true);
-            mEST = est;
-        }
-
-        @Override
-        public boolean commitText(CharSequence text, int newCursorPosition) {
-            if (DBG) {
-                Log.d(TAG, "--- commitText:");
-            }
-            mEST.mManager.unsetTextComposingMask();
-            return super.commitText(text, newCursorPosition);
-        }
-
-        @Override
-        public boolean finishComposingText() {
-            if (DBG) {
-                Log.d(TAG, "--- finishcomposing:");
-            }
-            if (!mEST.isSoftKeyBlocked() && !mEST.isButtonsFocused() && !mEST.isEditting()) {
-                // TODO onEndEdit isn't called temporally .
-                mEST.onEndEdit();
-            }
-            return super.finishComposingText();
-        }
-    }
-
-    public static class EditStyledTextSpans {
-        private static final String LOG_TAG = "EditStyledTextSpan";
-
-        public static class HorizontalLineSpan extends DynamicDrawableSpan {
-            HorizontalLineDrawable mDrawable;
-
-            public HorizontalLineSpan(int color, int width, Spannable spannable) {
-                super(ALIGN_BOTTOM);
-                mDrawable = new HorizontalLineDrawable(color, width, spannable);
-            }
-
-            @Override
-            public Drawable getDrawable() {
-                return mDrawable;
-            }
-
-            public void resetWidth(int width) {
-                mDrawable.renewBounds(width);
-            }
-
-            public int getColor() {
-                return mDrawable.getPaint().getColor();
-            }
-        }
-
-        public static class MarqueeSpan extends CharacterStyle {
-            public static final int SCROLL = 0;
-            public static final int ALTERNATE = 1;
-            public static final int NOTHING = 2;
-            private int mType;
-            private int mMarqueeColor;
-
-            public MarqueeSpan(int type, int bgc) {
-                mType = type;
-                checkType(type);
-                mMarqueeColor = getMarqueeColor(type, bgc);
-            }
-
-            public MarqueeSpan(int type) {
-                this(type, EditStyledText.DEFAULT_TRANSPARENT_COLOR);
-            }
-
-            public int getType() {
-                return mType;
-            }
-
-            public void resetColor(int bgc) {
-                mMarqueeColor = getMarqueeColor(mType, bgc);
-            }
-
-            private int getMarqueeColor(int type, int bgc) {
-                int THRESHOLD = 128;
-                int a = Color.alpha(bgc);
-                int r = Color.red(bgc);
-                int g = Color.green(bgc);
-                int b = Color.blue(bgc);
-                if (a == 0) {
-                    a = 0x80;
-                }
-                switch (type) {
-                    case SCROLL:
-                        if (r > THRESHOLD) {
-                            r = r / 2;
-                        } else {
-                            r = (0XFF - r) / 2;
-                        }
-                        break;
-                    case ALTERNATE:
-                        if (g > THRESHOLD) {
-                            g = g / 2;
-                        } else {
-                            g = (0XFF - g) / 2;
-                        }
-                        break;
-                    case NOTHING:
-                        return DEFAULT_TRANSPARENT_COLOR;
-                    default:
-                        Log.e(TAG, "--- getMarqueeColor: got illigal marquee ID.");
-                        return DEFAULT_TRANSPARENT_COLOR;
-                }
-                return Color.argb(a, r, g, b);
-            }
-
-            private boolean checkType(int type) {
-                if (type == SCROLL || type == ALTERNATE) {
-                    return true;
-                } else {
-                    Log.e(LOG_TAG, "--- Invalid type of MarqueeSpan");
-                    return false;
-                }
-            }
-
-            @Override
-            public void updateDrawState(TextPaint tp) {
-                tp.bgColor = mMarqueeColor;
-            }
-        }
-
-        public static class RescalableImageSpan extends ImageSpan {
-            Uri mContentUri;
-            private Drawable mDrawable;
-            private Context mContext;
-            public int mIntrinsicWidth = -1;
-            public int mIntrinsicHeight = -1;
-            private final int MAXWIDTH;
-
-            public RescalableImageSpan(Context context, Uri uri, int maxwidth) {
-                super(context, uri);
-                mContext = context;
-                mContentUri = uri;
-                MAXWIDTH = maxwidth;
-            }
-
-            public RescalableImageSpan(Context context, int resourceId, int maxwidth) {
-                super(context, resourceId);
-                mContext = context;
-                MAXWIDTH = maxwidth;
-            }
-
-            @Override
-            public Drawable getDrawable() {
-                if (mDrawable != null) {
-                    return mDrawable;
-                } else if (mContentUri != null) {
-                    Bitmap bitmap = null;
-                    System.gc();
-                    try {
-                        InputStream is =
-                                mContext.getContentResolver().openInputStream(mContentUri);
-                        BitmapFactory.Options opt = new BitmapFactory.Options();
-                        opt.inJustDecodeBounds = true;
-                        BitmapFactory.decodeStream(is, null, opt);
-                        is.close();
-                        is = mContext.getContentResolver().openInputStream(mContentUri);
-                        int width, height;
-                        width = opt.outWidth;
-                        height = opt.outHeight;
-                        mIntrinsicWidth = width;
-                        mIntrinsicHeight = height;
-                        if (opt.outWidth > MAXWIDTH) {
-                            width = MAXWIDTH;
-                            height = height * MAXWIDTH / opt.outWidth;
-                            Rect padding = new Rect(0, 0, width, height);
-                            bitmap = BitmapFactory.decodeStream(is, padding, null);
-                        } else {
-                            bitmap = BitmapFactory.decodeStream(is);
-                        }
-                        mDrawable = new BitmapDrawable(mContext.getResources(), bitmap);
-                        mDrawable.setBounds(0, 0, width, height);
-                        is.close();
-                    } catch (Exception e) {
-                        Log.e(LOG_TAG, "Failed to loaded content " + mContentUri, e);
-                        return null;
-                    } catch (OutOfMemoryError e) {
-                        Log.e(LOG_TAG, "OutOfMemoryError");
-                        return null;
-                    }
-                } else {
-                    mDrawable = super.getDrawable();
-                    rescaleBigImage(mDrawable);
-                    mIntrinsicWidth = mDrawable.getIntrinsicWidth();
-                    mIntrinsicHeight = mDrawable.getIntrinsicHeight();
-                }
-                return mDrawable;
-            }
-
-            public boolean isOverSize() {
-                return (getDrawable().getIntrinsicWidth() > MAXWIDTH);
-            }
-
-            public Uri getContentUri() {
-                return mContentUri;
-            }
-
-            private void rescaleBigImage(Drawable image) {
-                if (DBG) {
-                    Log.d(LOG_TAG, "--- rescaleBigImage:");
-                }
-                if (MAXWIDTH < 0) {
-                    return;
-                }
-                int image_width = image.getIntrinsicWidth();
-                int image_height = image.getIntrinsicHeight();
-                if (DBG) {
-                    Log.d(LOG_TAG, "--- rescaleBigImage:" + image_width + "," + image_height
-                            + "," + MAXWIDTH);
-                }
-                if (image_width > MAXWIDTH) {
-                    image_width = MAXWIDTH;
-                    image_height = image_height * MAXWIDTH / image_width;
-                }
-                image.setBounds(0, 0, image_width, image_height);
-            }
-        }
-
-        public static class HorizontalLineDrawable extends ShapeDrawable {
-            private Spannable mSpannable;
-            private int mWidth;
-            private static boolean DBG_HL = false;
-
-            public HorizontalLineDrawable(int color, int width, Spannable spannable) {
-                super(new RectShape());
-                mSpannable = spannable;
-                mWidth = width;
-                renewColor(color);
-                renewBounds(width);
-            }
-
-            @Override
-            public void draw(Canvas canvas) {
-                renewColor();
-                Rect rect = new Rect(0, 9, mWidth, 11);
-                canvas.drawRect(rect, getPaint());
-            }
-
-            public void renewBounds(int width) {
-                int MARGIN = 20;
-                int HEIGHT = 20;
-                if (DBG_HL) {
-                    Log.d(LOG_TAG, "--- renewBounds:" + width);
-                }
-                if (width > MARGIN) {
-                    width -= MARGIN;
-                }
-                mWidth = width;
-                setBounds(0, 0, width, HEIGHT);
-            }
-
-            private void renewColor(int color) {
-                if (DBG_HL) {
-                    Log.d(LOG_TAG, "--- renewColor:" + color);
-                }
-                getPaint().setColor(color);
-            }
-
-            private void renewColor() {
-                HorizontalLineSpan parent = getParentSpan();
-                Spannable text = mSpannable;
-                int start = text.getSpanStart(parent);
-                int end = text.getSpanEnd(parent);
-                ForegroundColorSpan[] spans =
-                        text.getSpans(start, end, ForegroundColorSpan.class);
-                if (DBG_HL) {
-                    Log.d(LOG_TAG, "--- renewColor:" + spans.length);
-                }
-                if (spans.length > 0) {
-                    renewColor(spans[spans.length - 1].getForegroundColor());
-                }
-            }
-
-            private HorizontalLineSpan getParentSpan() {
-                Spannable text = mSpannable;
-                HorizontalLineSpan[] images =
-                        text.getSpans(0, text.length(), HorizontalLineSpan.class);
-                if (images.length > 0) {
-                    for (HorizontalLineSpan image : images) {
-                        if (image.getDrawable() == this) {
-                            return image;
-                        }
-                    }
-                }
-                Log.e(LOG_TAG, "---renewBounds: Couldn't find");
-                return null;
-            }
-        }
-    }
-
-    public static class ColorPaletteDrawable extends ShapeDrawable {
-        private Rect mRect;
-
-        public ColorPaletteDrawable(int color, int width, int height, int mergin) {
-            super(new RectShape());
-            mRect = new Rect(mergin, mergin, width - mergin, height - mergin);
-            getPaint().setColor(color);
-        }
-
-        @Override
-        public void draw(Canvas canvas) {
-            canvas.drawRect(mRect, getPaint());
-        }
-    }
-
-    public class EditModeActions {
-
-        private static final String TAG = "EditModeActions";
-        private static final boolean DBG = true;
-        private EditStyledText mEST;
-        private EditorManager mManager;
-        private StyledTextDialog mDialog;
-
-        private int mMode = EditStyledText.MODE_NOTHING;
-
-        private HashMap<Integer, EditModeActionBase> mActionMap =
-                new HashMap<Integer, EditModeActionBase>();
-
-        private NothingAction mNothingAction = new NothingAction();
-        private CopyAction mCopyAction = new CopyAction();
-        private PasteAction mPasteAction = new PasteAction();
-        private SelectAction mSelectAction = new SelectAction();
-        private CutAction mCutAction = new CutAction();
-        private SelectAllAction mSelectAllAction = new SelectAllAction();
-        private HorizontalLineAction mHorizontalLineAction = new HorizontalLineAction();
-        private StopSelectionAction mStopSelectionAction = new StopSelectionAction();
-        private ClearStylesAction mClearStylesAction = new ClearStylesAction();
-        private ImageAction mImageAction = new ImageAction();
-        private BackgroundColorAction mBackgroundColorAction = new BackgroundColorAction();
-        private PreviewAction mPreviewAction = new PreviewAction();
-        private CancelAction mCancelEditAction = new CancelAction();
-        private TextViewAction mTextViewAction = new TextViewAction();
-        private StartEditAction mStartEditAction = new StartEditAction();
-        private EndEditAction mEndEditAction = new EndEditAction();
-        private ResetAction mResetAction = new ResetAction();
-        private ShowMenuAction mShowMenuAction = new ShowMenuAction();
-        private AlignAction mAlignAction = new AlignAction();
-        private TelopAction mTelopAction = new TelopAction();
-        private SwingAction mSwingAction = new SwingAction();
-        private MarqueeDialogAction mMarqueeDialogAction = new MarqueeDialogAction();
-        private ColorAction mColorAction = new ColorAction();
-        private SizeAction mSizeAction = new SizeAction();
-
-        EditModeActions(EditStyledText est, EditorManager manager, StyledTextDialog dialog) {
-            mEST = est;
-            mManager = manager;
-            mDialog = dialog;
-            mActionMap.put(EditStyledText.MODE_NOTHING, mNothingAction);
-            mActionMap.put(EditStyledText.MODE_COPY, mCopyAction);
-            mActionMap.put(EditStyledText.MODE_PASTE, mPasteAction);
-            mActionMap.put(EditStyledText.MODE_SELECT, mSelectAction);
-            mActionMap.put(EditStyledText.MODE_CUT, mCutAction);
-            mActionMap.put(EditStyledText.MODE_SELECTALL, mSelectAllAction);
-            mActionMap.put(EditStyledText.MODE_HORIZONTALLINE, mHorizontalLineAction);
-            mActionMap.put(EditStyledText.MODE_STOP_SELECT, mStopSelectionAction);
-            mActionMap.put(EditStyledText.MODE_CLEARSTYLES, mClearStylesAction);
-            mActionMap.put(EditStyledText.MODE_IMAGE, mImageAction);
-            mActionMap.put(EditStyledText.MODE_BGCOLOR, mBackgroundColorAction);
-            mActionMap.put(EditStyledText.MODE_PREVIEW, mPreviewAction);
-            mActionMap.put(EditStyledText.MODE_CANCEL, mCancelEditAction);
-            mActionMap.put(EditStyledText.MODE_TEXTVIEWFUNCTION, mTextViewAction);
-            mActionMap.put(EditStyledText.MODE_START_EDIT, mStartEditAction);
-            mActionMap.put(EditStyledText.MODE_END_EDIT, mEndEditAction);
-            mActionMap.put(EditStyledText.MODE_RESET, mResetAction);
-            mActionMap.put(EditStyledText.MODE_SHOW_MENU, mShowMenuAction);
-            mActionMap.put(EditStyledText.MODE_ALIGN, mAlignAction);
-            mActionMap.put(EditStyledText.MODE_TELOP, mTelopAction);
-            mActionMap.put(EditStyledText.MODE_SWING, mSwingAction);
-            mActionMap.put(EditStyledText.MODE_MARQUEE, mMarqueeDialogAction);
-            mActionMap.put(EditStyledText.MODE_COLOR, mColorAction);
-            mActionMap.put(EditStyledText.MODE_SIZE, mSizeAction);
-        }
-
-        public void addAction(int modeId, EditModeActionBase action) {
-            mActionMap.put(modeId, action);
-        }
-
-        public void onAction(int newMode, Object[] params) {
-            getAction(newMode).addParams(params);
-            mMode = newMode;
-            doNext(newMode);
-        }
-
-        public void onAction(int newMode, Object param) {
-            onAction(newMode, new Object[] { param });
-        }
-
-        public void onAction(int newMode) {
-            onAction(newMode, null);
-        }
-
-        public void onSelectAction() {
-            doNext(EditStyledText.MODE_SELECT);
-        }
-
-        private EditModeActionBase getAction(int mode) {
-            if (mActionMap.containsKey(mode)) {
-                return mActionMap.get(mode);
-            }
-            return null;
-        }
-
-        public boolean doNext() {
-            return doNext(mMode);
-        }
-
-        public boolean doNext(int mode) {
-            if (DBG) {
-                Log.d(TAG, "--- do the next action: " + mode + "," + mManager.getSelectState());
-            }
-            EditModeActionBase action = getAction(mode);
-            if (action == null) {
-                Log.e(TAG, "--- invalid action error.");
-                return false;
-            }
-            switch (mManager.getSelectState()) {
-                case EditStyledText.STATE_SELECT_OFF:
-                    return action.doNotSelected();
-                case EditStyledText.STATE_SELECT_ON:
-                    return action.doStartPosIsSelected();
-                case EditStyledText.STATE_SELECTED:
-                    return action.doEndPosIsSelected();
-                case EditStyledText.STATE_SELECT_FIX:
-                    if (mManager.isWaitInput()) {
-                        return action.doSelectionIsFixedAndWaitingInput();
-                    } else {
-                        return action.doSelectionIsFixed();
-                    }
-                default:
-                    return false;
-            }
-        }
-
-        public class EditModeActionBase {
-            private Object[] mParams;
-
-            protected boolean canOverWrap() {
-                return false;
-            }
-
-            protected boolean canSelect() {
-                return false;
-            }
-
-            protected boolean canWaitInput() {
-                return false;
-            }
-
-            protected boolean needSelection() {
-                return false;
-            }
-
-            protected boolean isLine() {
-                return false;
-            }
-
-            protected boolean doNotSelected() {
-                return false;
-            }
-
-            protected boolean doStartPosIsSelected() {
-                return doNotSelected();
-            }
-
-            protected boolean doEndPosIsSelected() {
-                return doStartPosIsSelected();
-            }
-
-            protected boolean doSelectionIsFixed() {
-                return doEndPosIsSelected();
-            }
-
-            protected boolean doSelectionIsFixedAndWaitingInput() {
-                return doEndPosIsSelected();
-            }
-
-            protected boolean fixSelection() {
-                mEST.finishComposingText();
-                mManager.setSelectState(EditStyledText.STATE_SELECT_FIX);
-                return true;
-            }
-
-            protected void addParams(Object[] o) {
-                mParams = o;
-            }
-
-            protected Object getParam(int num) {
-                if (mParams == null || num > mParams.length) {
-                    if (DBG) {
-                        Log.d(TAG, "--- Number of the parameter is out of bound.");
-                    }
-                    return null;
-                } else {
-                    return mParams[num];
-                }
-            }
-        }
-
-        public class NothingAction extends EditModeActionBase {
-        }
-
-        public class TextViewActionBase extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                if (mManager.getEditMode() == EditStyledText.MODE_NOTHING
-                        || mManager.getEditMode() == EditStyledText.MODE_SELECT) {
-                    mManager.setEditMode(mMode);
-                    onSelectAction();
-                    return true;
-                }
-                return false;
-            }
-
-            @Override
-            protected boolean doEndPosIsSelected() {
-                if (mManager.getEditMode() == EditStyledText.MODE_NOTHING
-                        || mManager.getEditMode() == EditStyledText.MODE_SELECT) {
-                    mManager.setEditMode(mMode);
-                    fixSelection();
-                    doNext();
-                    return true;
-                } else if (mManager.getEditMode() != mMode) {
-                    mManager.resetEdit();
-                    mManager.setEditMode(mMode);
-                    doNext();
-                    return true;
-                }
-                return false;
-            }
-        }
-
-        public class TextViewAction extends TextViewActionBase {
-            @Override
-            protected boolean doEndPosIsSelected() {
-                if (super.doEndPosIsSelected()) {
-                    return true;
-                }
-                Object param = getParam(0);
-                if (param != null && param instanceof Integer) {
-                    mEST.onTextContextMenuItem((Integer) param);
-                }
-                mManager.resetEdit();
-                return true;
-            }
-        }
-
-        public class CopyAction extends TextViewActionBase {
-            @Override
-            protected boolean doEndPosIsSelected() {
-                if (super.doEndPosIsSelected()) {
-                    return true;
-                }
-                mManager.copyToClipBoard();
-                mManager.resetEdit();
-                return true;
-            }
-        }
-
-        public class CutAction extends TextViewActionBase {
-            @Override
-            protected boolean doEndPosIsSelected() {
-                if (super.doEndPosIsSelected()) {
-                    return true;
-                }
-                mManager.cutToClipBoard();
-                mManager.resetEdit();
-                return true;
-            }
-        }
-
-        public class SelectAction extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                if (mManager.isTextSelected()) {
-                    Log.e(TAG, "Selection is off, but selected");
-                }
-                mManager.setSelectStartPos();
-                mEST.sendHintMessage(EditStyledText.HINT_MSG_SELECT_END);
-                return true;
-            }
-
-            @Override
-            protected boolean doStartPosIsSelected() {
-                if (mManager.isTextSelected()) {
-                    Log.e(TAG, "Selection now start, but selected");
-                }
-                mManager.setSelectEndPos();
-                mEST.sendHintMessage(EditStyledText.HINT_MSG_PUSH_COMPETE);
-                if (mManager.getEditMode() != EditStyledText.MODE_SELECT) {
-                    doNext(mManager.getEditMode()); // doNextHandle needs edit mode in editor.
-                }
-                return true;
-            }
-
-            @Override
-            protected boolean doSelectionIsFixed() {
-                return false;
-            }
-        }
-
-        public class PasteAction extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                mManager.pasteFromClipboard();
-                mManager.resetEdit();
-                return true;
-            }
-        }
-
-        public class SelectAllAction extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                mManager.selectAll();
-                return true;
-            }
-        }
-
-        public class HorizontalLineAction extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                mManager.insertHorizontalLine();
-                return true;
-            }
-        }
-
-        public class ClearStylesAction extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                mManager.clearStyles();
-                return true;
-            }
-        }
-
-        public class StopSelectionAction extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                mManager.fixSelectionAndDoNextAction();
-                return true;
-            }
-        }
-
-        public class CancelAction extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                mEST.cancelViewManagers();
-                return true;
-            }
-        }
-
-        public class ImageAction extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                Object param = getParam(0);
-                if (param != null) {
-                    if (param instanceof Uri) {
-                        mManager.insertImageFromUri((Uri) param);
-                    } else if (param instanceof Integer) {
-                        mManager.insertImageFromResId((Integer) param);
-                    }
-                } else {
-                    mEST.showInsertImageSelectAlertDialog();
-                }
-                return true;
-            }
-        }
-
-        public class BackgroundColorAction extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                mDialog.onShowBackgroundColorAlertDialog();
-                return true;
-            }
-        }
-
-        public class PreviewAction extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                mEST.showPreview();
-                return true;
-            }
-        }
-
-        public class StartEditAction extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                mManager.startEdit();
-                return true;
-            }
-        }
-
-        public class EndEditAction extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                mManager.endEdit();
-                return true;
-            }
-        }
-
-        public class ResetAction extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                mManager.resetEdit();
-                return true;
-            }
-        }
-
-        public class ShowMenuAction extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                mEST.showMenuAlertDialog();
-                return true;
-            }
-        }
-
-        public class SetSpanActionBase extends EditModeActionBase {
-            @Override
-            protected boolean doNotSelected() {
-                if (mManager.getEditMode() == EditStyledText.MODE_NOTHING
-                        || mManager.getEditMode() == EditStyledText.MODE_SELECT) {
-                    mManager.setEditMode(mMode);
-                    mManager.setInternalSelection(mEST.getSelectionStart(),
-                            mEST.getSelectionEnd());
-                    fixSelection();
-                    doNext();
-                    return true;
-                } else if (mManager.getEditMode() != mMode) {
-                    Log.d(TAG, "--- setspanactionbase" + mManager.getEditMode() + "," + mMode);
-                    if (!mManager.isWaitInput()) {
-                        mManager.resetEdit();
-                        mManager.setEditMode(mMode);
-                    } else {
-                        mManager.setEditMode(EditStyledText.MODE_NOTHING);
-                        mManager.setSelectState(EditStyledText.STATE_SELECT_OFF);
-                    }
-                    doNext();
-                    return true;
-                }
-                return false;
-            }
-
-            @Override
-            protected boolean doStartPosIsSelected() {
-                if (mManager.getEditMode() == EditStyledText.MODE_NOTHING
-                        || mManager.getEditMode() == EditStyledText.MODE_SELECT) {
-                    mManager.setEditMode(mMode);
-                    onSelectAction();
-                    return true;
-                }
-                return doNotSelected();
-            }
-
-            @Override
-            protected boolean doEndPosIsSelected() {
-                if (mManager.getEditMode() == EditStyledText.MODE_NOTHING
-                        || mManager.getEditMode() == EditStyledText.MODE_SELECT) {
-                    mManager.setEditMode(mMode);
-                    fixSelection();
-                    doNext();
-                    return true;
-                }
-                return doStartPosIsSelected();
-            }
-
-            @Override
-            protected boolean doSelectionIsFixed() {
-                if (doEndPosIsSelected()) {
-                    return true;
-                }
-                mEST.sendHintMessage(EditStyledText.HINT_MSG_NULL);
-
-                return false;
-            }
-        }
-
-        public class AlignAction extends SetSpanActionBase {
-            @Override
-            protected boolean doSelectionIsFixed() {
-                if (super.doSelectionIsFixed()) {
-                    return true;
-                }
-                mDialog.onShowAlignAlertDialog();
-                return true;
-            }
-        }
-
-        public class TelopAction extends SetSpanActionBase {
-            @Override
-            protected boolean doSelectionIsFixed() {
-                if (super.doSelectionIsFixed()) {
-                    return true;
-                }
-                mManager.setTelop();
-                return true;
-            }
-        }
-
-        public class SwingAction extends SetSpanActionBase {
-            @Override
-            protected boolean doSelectionIsFixed() {
-                if (super.doSelectionIsFixed()) {
-                    return true;
-                }
-                mManager.setSwing();
-                return true;
-            }
-        }
-
-        public class MarqueeDialogAction extends SetSpanActionBase {
-            @Override
-            protected boolean doSelectionIsFixed() {
-                if (super.doSelectionIsFixed()) {
-                    return true;
-                }
-                mDialog.onShowMarqueeAlertDialog();
-                return true;
-            }
-        }
-
-        public class ColorAction extends SetSpanActionBase {
-            @Override
-            protected boolean doSelectionIsFixed() {
-                if (super.doSelectionIsFixed()) {
-                    return true;
-                }
-                mDialog.onShowForegroundColorAlertDialog();
-                return true;
-            }
-
-            @Override
-            protected boolean doSelectionIsFixedAndWaitingInput() {
-                if (super.doSelectionIsFixedAndWaitingInput()) {
-                    return true;
-                }
-                int size = mManager.getSizeWaitInput();
-                mManager.setItemColor(mManager.getColorWaitInput(), false);
-                // selection was resumed
-                if (!mManager.isWaitInput()) {
-                    mManager.setItemSize(size, false);
-                    mManager.resetEdit();
-                } else {
-                    fixSelection();
-                    mDialog.onShowForegroundColorAlertDialog();
-                }
-                return true;
-            }
-        }
-
-        public class SizeAction extends SetSpanActionBase {
-            @Override
-            protected boolean doSelectionIsFixed() {
-                if (super.doSelectionIsFixed()) {
-                    return true;
-                }
-                mDialog.onShowSizeAlertDialog();
-                return true;
-            }
-
-            @Override
-            protected boolean doSelectionIsFixedAndWaitingInput() {
-                if (super.doSelectionIsFixedAndWaitingInput()) {
-                    return true;
-                }
-                int color = mManager.getColorWaitInput();
-                mManager.setItemSize(mManager.getSizeWaitInput(), false);
-                if (!mManager.isWaitInput()) {
-                    mManager.setItemColor(color, false);
-                    mManager.resetEdit();
-                } else {
-                    fixSelection();
-                    mDialog.onShowSizeAlertDialog();
-                }
-                return true;
-            }
-        }
-    }
-}
