////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You 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 spark.components
{
    
    import flash.display.DisplayObject;
    import flash.display.DisplayObjectContainer;
    import flash.events.Event;
    import flash.events.FocusEvent;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.geom.Rectangle;
    import flash.system.IME;
    import flash.system.IMEConversionMode;
    import flash.text.engine.ElementFormat;
    import flash.text.engine.FontDescription;
    import flash.text.engine.FontLookup;
    import flash.text.engine.TextBlock;
    import flash.text.engine.TextElement;
    import flash.text.engine.TextLine;
    import flash.ui.Keyboard;
    
    import flashx.textLayout.compose.ISWFContext;
    import flashx.textLayout.container.TextContainerManager;
    import flashx.textLayout.conversion.ConversionType;
    import flashx.textLayout.conversion.ITextExporter;
    import flashx.textLayout.conversion.ITextImporter;
    import flashx.textLayout.conversion.TextConverter;
    import flashx.textLayout.edit.EditManager;
    import flashx.textLayout.edit.EditingMode;
    import flashx.textLayout.edit.IEditManager;
    import flashx.textLayout.edit.ISelectionManager;
    import flashx.textLayout.edit.SelectionState;
    import flashx.textLayout.edit.TextClipboard;
    import flashx.textLayout.elements.Configuration;
    import flashx.textLayout.elements.GlobalSettings;
    import flashx.textLayout.elements.InlineGraphicElement;
    import flashx.textLayout.elements.InlineGraphicElementStatus;
    import flashx.textLayout.elements.TextFlow;
    import flashx.textLayout.events.CompositionCompleteEvent;
    import flashx.textLayout.events.DamageEvent;
    import flashx.textLayout.events.FlowOperationEvent;
    import flashx.textLayout.events.SelectionEvent;
    import flashx.textLayout.events.StatusChangeEvent;
    import flashx.textLayout.factory.StringTextLineFactory;
    import flashx.textLayout.factory.TextFlowTextLineFactory;
    import flashx.textLayout.formats.BlockProgression;
    import flashx.textLayout.formats.Category;
    import flashx.textLayout.formats.ITextLayoutFormat;
    import flashx.textLayout.formats.TextLayoutFormat;
    import flashx.textLayout.operations.CopyOperation;
    import flashx.textLayout.operations.CutOperation;
    import flashx.textLayout.operations.DeleteTextOperation;
    import flashx.textLayout.operations.FlowOperation;
    import flashx.textLayout.operations.FlowTextOperation;
    import flashx.textLayout.operations.InsertTextOperation;
    import flashx.textLayout.operations.PasteOperation;
    import flashx.textLayout.tlf_internal;
    import flashx.undo.IUndoManager;
    
    import mx.core.FlexVersion;
    import mx.core.IFlexModuleFactory;
    import mx.core.IIMESupport;
    import mx.core.ISystemCursorClient;
    import mx.core.UIComponent;
	import mx.core.mx_internal;
    import mx.events.FlexEvent;
    import mx.managers.IFocusManager;
    import mx.managers.IFocusManagerComponent;
    import mx.utils.StringUtil;
    
    import spark.components.supportClasses.RichEditableTextContainerManager;
    import spark.core.CSSTextLayoutFormat;
    import spark.core.IEditableText;
    import spark.core.IViewport;
    import spark.core.NavigationUnit;
    import spark.events.TextOperationEvent;
    import spark.utils.TextUtil;
    
    use namespace mx_internal;
    use namespace tlf_internal;
    
    //--------------------------------------
    //  Events
    //--------------------------------------
    
    /**
     *  Dispached after the <code>selectionAnchorPosition</code> and/or
     *  <code>selectionActivePosition</code> properties have changed
     *  for any reason.
     *
     *  @eventType mx.events.FlexEvent.SELECTION_CHANGE
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    [Event(name="selectionChange", type="mx.events.FlexEvent")]
    
    /**
     *  Dispatched before a user editing operation occurs.
     *  You can alter the operation, or cancel the event
     *  to prevent the operation from being processed.
     *
     *  @eventType spark.events.TextOperationEvent.CHANGING
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    [Event(name="changing", type="spark.events.TextOperationEvent")]
    
    /**
     *  Dispatched after a user editing operation is complete.
     *
     *  @eventType spark.events.TextOperationEvent.CHANGE
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    [Event(name="change", type="spark.events.TextOperationEvent")]
    
    /**
     *  Dispatched when the user presses the Enter key,
     *  if the <code>multiline</code> property is false.
     *
     *  @eventType mx.events.FlexEvent.ENTER
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    [Event(name="enter", type="mx.events.FlexEvent")]
    
    //--------------------------------------
    //  Styles
    //--------------------------------------
    
    include "../styles/metadata/BasicInheritingTextStyles.as"
    include "../styles/metadata/BasicNonInheritingTextStyles.as"
    include "../styles/metadata/AdvancedInheritingTextStyles.as"
    include "../styles/metadata/AdvancedNonInheritingTextStyles.as"
    include "../styles/metadata/SelectionFormatTextStyles.as"
    
    /**
     *  The alpha level of the color defined by
     *  the <code>backgroundColor</code> style.
     *  Valid values range from 0.0 to 1.0.
     * 
     *  @default 1.0
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    [Style(name="backgroundAlpha", type="Number", inherit="no")]
    
    /**
     *  The color of the background of the entire
     *  bounding rectangle of this component.
     *  If this style is <code>undefined</code>,
     *  no background is drawn.
     *  Otherwise, this RGB color is drawn with an alpha level
     *  determined by the <code>backgroundAlpha</code> style.
     * 
     *  @default undefined
     *
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    [Style(name="backgroundColor", type="uint", format="Color", inherit="no")]
    
    //--------------------------------------
    //  Excluded APIs
    //--------------------------------------
    
    [Exclude(name="chromeColor", kind="style")]
    
    //--------------------------------------
    //  Other metadata
    //--------------------------------------
    
    [AccessibilityClass(implementation="spark.accessibility.RichEditableTextAccImpl")]
    
    [DefaultProperty("content")]
    
    [IconFile("RichEditableText.png")]
    
    [DefaultTriggerEvent("change")]
    
    [DiscouragedForProfile("mobileDevice")]
    
    /**
     *  RichEditableText is a low-level UIComponent for displaying,
     *  scrolling, selecting, and editing richly-formatted text.
     *
     *  <p>The rich text can contain clickable hyperlinks and inline graphics
     *  that are either embedded or loaded from URLs.</p>
     *
     *  <p>RichEditableText does not have scrollbars, but it implements
     *  the IViewport interface for programmatic scrolling so that it
     *  can be controlled by a Scroller, which does provide scrollbars.
     *  It also supports vertical scrolling with the mouse wheel.</p>
     *
     *  <p>It does not include any user interface for changing
     *  the formatting of the text.
     *  But it offers APIs which can do this programmatically;
     *  these make it possible, for example, for you to create 
     *  a Bold button that makes the selected text bold.</p>
     *
     *  <p>This class is used in the skins of the Spark versions
     *  of TextInput and TextArea.
     *  (TextInput does not expose its ability to handle rich text,
     *  but TextArea does.)
     *  By default, RichEditableText has a transparent background,
     *  and it does not support drawing a border.</p>
     *
     *  <p>RichEditableText uses the Text Layout Framework (TLF) library,
     *  which in turn builds on the Flash Text Engine (FTE)
     *  introduced in Flash Player 10. In combination, these layers provide text editing with
     *  high-quality international typography and layout.</p>
     *
     *  <p>The Spark architecture provides three text "primitives" -- 
     *  Label, RichText, and RichEditableText.
     *  Label is the fastest and most lightweight
     *  because it uses only FTE, not TLF,
     *  but it is limited in its capabilities: no rich text,
     *  no scrolling, no selection, and no editing.
     *  RichText adds the ability to display rich text
     *  with complex layout, but is still completely non-interactive.
     *  RichEditableText is the heaviest-weight,
     *  but offers most of what TLF can do.
     *  In general, use the fastest text primitive that meets your needs.</p>
     *
     *  <p>RichEditableText is similar to the UITextField class
     *  used in MX components. This class did not use FTE or TLF
     *  but rather extended the older TextField class.</p>
     *
     *  <p>The most important differences between UITextField and RichEditableText are:
     *  <ul>
     *    <li>RichEditableText offers better typography, better support
     *        for international languages, and better text layout.</li>
     *    <li>RichEditableText has an object-oriented model of rich text,
     *        while UITextField does not.</li>
     *    <li>RichEditableText has better support for displaying
     *        large amounts of text.</li>
     *    <li>RichEditableText requires that fonts be embedded
     *        differently than UITextField.
     *        Consult the documentation regarding how to use the
     *        <code>embedAsCFF</code> attribute when you embed a font.</li>
     *  </ul></p>
     *
     *  <p>RichEditableText uses TLF's object-oriented model of rich text,
     *  in which text layout elements such as divisions, paragraphs, spans,
     *  hyperlinks, and images are represented at runtime by ActionScript
     *  objects which can be programmatically accessed and manipulated.
     *  The central object in TLF for representing rich text is a
     *  TextFlow, so you specify rich text for a RichEditableText control to display
     *  by setting its <code>textFlow</code> property to a TextFlow instance.
     *  See the description of the <code>textFlow</code>
     *  property for information about how to create one,
     *  such as by importing TLF markup.
     *  If you don't need to display text that has multiple formats,
     *  you can use the <code>text</code> property to set a "plain text" String.
     *  See the description of the <code>text</code> and <code>textFlow</code>
     *  properties for information about how they interact;
     *  for example, you can set one and get the other.</p>
     *
     *  <p>At compile time, you can put TLF markup tags inside
     *  the RichEditableText tag, as the following example shows:
     *  <pre>
     *  &lt;s:RichEditableText&gt;Hello &lt;s:span fontWeight="bold"&gt;World!&lt;/s:span&gt;&lt;/s:RichEditableText&gt;
     *  </pre>
     *  In this case, the MXML compiler sets the <code>content</code>
     *  property, causing a TextFlow to be automatically created
     *  from the FlowElements that you specify.</p>
     *
     *  <p>The default text formatting is determined by CSS styles
     *  such as <code>fontFamily</code>, <code>fontSize</code>.
     *  Any formatting information in the TextFlow overrides
     *  the default formatting provided by the CSS styles.</p>
     *
     *  <p>You can control the spacing between lines with the
     *  <code>lineHeight</code> style and the spacing between
     *  paragraphs with the <code>paragraphSpaceBefore</code>
     *  and <code>paragraphSpaceAfter</code> styles.
     *  You can align or justify the text using the <code>textAlign</code>
     *  and <code>textAlignLast</code> styles.
     *  You can inset the text from the component's edges using the
     *  <code>paddingLeft</code>, <code>paddingTop</code>, 
     *  <code>paddingRight</code>, and <code>paddingBottom</code> styles.</p>
     *
     *  <p>By default, a RichEditableText "autosizes": it starts out very
     *  small if it has no text, and grows in width up to
     *  <code>maxWidth</code> as you type. It grows in height when you 
     *  press the Enter key to start a new line.</p>
     *
     *  <p>The <code>widthInChars</code> and <code>heightInLines</code>
     *  properties provide a convenient way to specify the width and height
     *  in a way that scales with the font size.
     *  You can use the <code>typicalText</code> property as well.
     *  Note that if you use <code>typicalText</code>, the
     *  <code>widthInChars</code> and <code>heightInLines</code>
     *  are ignored.
     *  You can also specify an explicit width or height in pixels,
     *  or use a percent width and height, or use constraints such as
     *  <code>left</code> and <code>right</code>
     *  or <code>top</code> and <code>bottom</code>.</p>
     *
     *  <p>When you specify some kind of width -- whether an explicit or
     *  percent width, a <code>maxWidth</code> or <code>left</code>
     *  and <code>right</code> constraints -- the text wraps at the right
     *  edge of the component and the text becomes vertically scrollable
     *  when there is more text than fits.
     *  If you set the <code>lineBreak</code> style to <code>explicit</code>,
     *  new lines will start only at explicit lines breaks, such as
     *  if you use CR (<code>\r</code>), LF (<code>\n</code>),
     *  or CR+LF (<code>\r\n</code>) in <code>text</code>
     *  or if you use <code>&lt;p&gt;</code> and <code>&lt;br/&gt;</code>
     *  in TLF markup.
     *  In that case, the text becomes horizontally scrollable
     *  if any lines are wider than the control.</p>
     *
     *  <p>You can use the <code>maxChars</code> property to limit the number
     *  of character that the user can enter, and the <code>restrict</code>
     *  to limit which characters the user can enter.</p>
     *
     *  <p>The <code>multiline</code> property determines what happens
     *  when you press the Enter key.
     *  If it is <code>true</code>, the Enter key starts a new paragraph.
     *  If it is <code>false</code>, it causes a <code>FlexEvent.ENTER</code>
     *  event to be dispatched.</p>
     *
     *  <p>If you don't want the text to be editable,
     *  set the <code>editable</code> property to <code>false</code>.
     *  If you don't even want the text to be selectable,
     *  set the <code>selectable</code> property to <code>false</code>.</p>
     *
     *  <p>Because RichEditableText uses TLF,
     *  it supports displaying left-to-right (LTR) text such as French,
     *  right-to-left (RTL) text such as Arabic, and bidirectional text
     *  such as a French phrase inside of an Arabic one.
     *  If the predominant text direction is right-to-left,
     *  set the <code>direction</code> style to <code>rtl</code>.
     *  The <code>textAlign</code> style defaults to <code>"start"</code>,
     *  which makes the text left-aligned when <code>direction</code>
     *  is <code>ltr</code> and right-aligned when <code>direction</code>
     *  is <code>rtl</code>.
     *  To get the opposite alignment, set <code>textAlign</code> to <code>end</code>.</p>
     *
     *  <p>As a result of using TLF, the RichEditableText supports
     *  unlimited undo/redo within one editing session.
     *  An editing session starts when the component gets keyboard focus
     *  and ends when it loses focus.</p>
     *
     *  <p>RichEditableText uses TLF's TextContainerManager class
     *  to handle its text display, scrolling, selection, editing and context menu.</p>
     *
     *  <p>To use this component in a list-based component, such as a List or DataGrid, 
     *  create an item renderer.
     *  For information about creating an item renderer, see 
     *  <a href="http://help.adobe.com/en_US/flex/using/WS4bebcd66a74275c3-fc6548e124e49b51c4-8000.html">
     *  Custom Spark item renderers</a>. </p>
     *
     *  @mxml
     *
     *  <p>The <code>&lt;s:RichEditableText&gt;</code> tag inherits all of the tag 
     *  attributes of its superclass and adds the following tag attributes:</p>
     *
     *  <pre>
     *  &lt;s:RichEditableText
     *    <strong>Properties</strong>
     *    clipAndEnableScrolling="false|true"
     *    contentHeight="<i>Calculated default</i>"
     *    contentWidth="<i>Calculated default</i>"
     *    displayAsPassword="false"
     *    editable="true"
     *    heightInLines="NaN"
     *    horizontalScrollPosition="0"
     *    imeMode="null"
     *    maxChars="0"
     *    multiline="true"
     *    restrict="null"
     *    selectable="true"
     *    selectionActivePosition="-1"
     *    selectionAnchorPosition="-1"
     *    selectionHighlighting="TextSelectionHighlighting.WHEN_FOCUSED"
     *    text=""
     *    textFlow="<i>TextFlow</i>"
     *    typicalText=null
     *    verticalScrollPosition="0"
     *    widthInChars="NaN"
     *  
     *    <strong>Events</strong>
     *    change="<i>No default</i>"
     *    changing="<i>No default</i>"
     *    enter="<i>No default</i>"
     *    selectionChange="<i>No default</i>"
     *  /&gt;
     *  </pre>
     *  
     *  @includeExample examples/RichEditableTextExample.mxml
     *  @includeExample examples/externalTextFlow.xml -noswf
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     *
     *  @see spark.components.Label
     *  @see spark.components.RichText
     *  @see spark.utils.TextFlowUtil
     *  @see flashx.textLayout.container.TextContainerManager
     */
    public class RichEditableText extends UIComponent
        implements IFocusManagerComponent, IIMESupport, ISystemCursorClient, 
                   IViewport, IEditableText
    {
        include "../core/Version.as";
        
        //--------------------------------------------------------------------------
        //
        //  Class mixins
        //
        //--------------------------------------------------------------------------
        
        /**
         *  @private
         *  Placeholder for mixin by RichEditableTextAccImpl.
         */
        mx_internal static var createAccessibilityImplementation:Function;
        
        //--------------------------------------------------------------------------
        //
        //  Class initialization
        //
        //--------------------------------------------------------------------------
        
        /**
         *  @private
         *  This method initializes the static vars of this class.
         *  Rather than calling it at static initialization time,
         *  we call it in the constructor to do the class initialization
         *  when the first instance is created.
         *  (It does an immediate return if it has already run.)
         *  By doing so, we avoid any static initialization issues
         *  related to whether this class or the TLF classes
         *  that it uses are initialized first.
         */
        private static function initClass():void
        {
            if (classInitialized)
                return;
            
            // Set the TLF hook used for localizing runtime error messages.
            // TLF itself has English-only messages,
            // but higher layers like Flex can provide localized versions.
            GlobalSettings.resourceStringFunction = TextUtil.getResourceString;
            
            // Set the TLF hook used to specify the callback used for changing 
            // the FontLookup based on SWFContext.  
            GlobalSettings.resolveFontLookupFunction = TextUtil.resolveFontLookup;
            
            // Pre-FP10.1, set default tab stops in TLF.  Without this, if there
            // is a tab and TLF is measuring width, the tab will
            // measure as the rest of the remaining width up to 10000.
            GlobalSettings.enableDefaultTabStops = 
                !Configuration.playerEnablesArgoFeatures;
            
            staticPlainTextImporter =
                TextConverter.getImporter(TextConverter.PLAIN_TEXT_FORMAT);
            
            // Throw import errors rather than return a null textFlow.
            // Alternatively, the error strings are in the Vector, importer.errors.
            staticPlainTextImporter.throwOnError = true;
            
            staticPlainTextExporter =
                TextConverter.getExporter(TextConverter.PLAIN_TEXT_FORMAT);
            
            classInitialized = true;
        } 
        
        //--------------------------------------------------------------------------
        //
        //  Class variables
        //
        //--------------------------------------------------------------------------
        
        /**
         *  @private
         */
        private static var classInitialized:Boolean = false;
                
        /**
         *  @private
         *  This TLF object composes TextLines from a text String.
         *  We use it when the 'typicalText' property is set to a String
         *  that doesn't contain linebreaks.
         */
        private static var staticStringFactory:StringTextLineFactory;
        
        /**
         *  @private
         *  This TLF object composes TextLines from a TextFlow.
         *  We use it when the 'typicalText is set to a String
         *  that contains linebreaks (and therefore is interpreted
         *  as multiple paragraphs).
         */
        private static var staticTextFlowFactory:TextFlowTextLineFactory;
        
        /**
         *  @private
         *  This TLF object is used to import a 'text' String
         *  containing linebreaks to create a multiparagraph TextFlow.
         */
        private static var staticPlainTextImporter:ITextImporter;
        
        /**
         *  @private
         *  This TLF object is used to export a TextFlow as plain 'text',
         *  by walking the leaf FlowElements in the TextFlow.
         */
        private static var staticPlainTextExporter:ITextExporter;
        
        /**
         *  @private
         *  Regular expression which matches all newlines in the text.  Used
         *  to strip newlines when pasting text when multiline is false.
         */
        private static const ALL_NEWLINES_REGEXP:RegExp = /[\n\r]/g;
        
        //--------------------------------------------------------------------------
        //
        //  Class methods
        //
        //--------------------------------------------------------------------------
        /**
         *  @private
         */
        public static function getNumberOrPercentOf(value:Object,
                                                    n:Number):Number
        {
            // If 'value' is a Number like 10.5, return it.
            if (value is Number)
                return Number(value);
            
            // If 'value' is a percentage String like "10.5%",
            // return that percentage of 'n'.
            if (value is String)
            {
                var len:int = String(value).length;
                if (len >= 1 && value.charAt(len - 1) == "%")
                {
                    var percent:Number = Number(value.substring(0, len - 1));
                    return percent / 100 * n;
                }
            }
            
            // Otherwise, return NaN.
            return NaN;
        }        
        
        /**
         *  @private
         */
        private static function splice(str:String, start:int, end:int,
                                       strToInsert:String):String
        {
            return str.substring(0, start) +
                strToInsert +
                str.substring(end, str.length);
        }

        //--------------------------------------------------------------------------
        //
        //  Constructor
        //
        //--------------------------------------------------------------------------
        
        /**
         *  Constructor. 
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function RichEditableText()
        {
            super();
            
            initClass();
            
            // Use the setter.
            text = "";
            
            // Create the TLF TextContainerManager, using this component
            // as the DisplayObjectContainer for its TextLines.
            // This TextContainerManager instance persists for the lifetime
            // of the component.
            _textContainerManager = createTextContainerManager();

            // Turn on TextField-like behavior which preserves the selection when text is set.
            // If the new text is shorter than the exisiting text, the selection may change.
            if (FlexVersion.compatibilityVersion > FlexVersion.VERSION_4_8) 
                _textContainerManager.preserveSelectionOnSetText = true;
            
            // Add event listeners on this component.
            addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);

            // The focusInHandler is called by the TCMContainer focusInHandler.
            // The focusOutHandler is called by the TCMContainer focusOutHandler.
            // The keyDownHandler is called by the TCMContainer keyDownHandler.
            
            // Add event listeners on its TextContainerManager.
            
            _textContainerManager.addEventListener(
                CompositionCompleteEvent.COMPOSITION_COMPLETE,
                textContainerManager_compositionCompleteHandler);
            
            _textContainerManager.addEventListener(
                DamageEvent.DAMAGE, textContainerManager_damageHandler);
            
            _textContainerManager.addEventListener(
                Event.SCROLL, textContainerManager_scrollHandler);
            
            _textContainerManager.addEventListener(
                SelectionEvent.SELECTION_CHANGE,
                textContainerManager_selectionChangeHandler);
            
            _textContainerManager.addEventListener(
                FlowOperationEvent.FLOW_OPERATION_BEGIN,
                textContainerManager_flowOperationBeginHandler);
            
            _textContainerManager.addEventListener(
                FlowOperationEvent.FLOW_OPERATION_END,
                textContainerManager_flowOperationEndHandler);
            
            _textContainerManager.addEventListener(
                FlowOperationEvent.FLOW_OPERATION_COMPLETE,
                textContainerManager_flowOperationCompleteHandler);
            
            _textContainerManager.addEventListener(
                StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE, 
                textContainerManager_inlineGraphicStatusChangeHandler);
        }
        
        //--------------------------------------------------------------------------
        //
        //  Variables
        //
        //--------------------------------------------------------------------------
        
        /**
         *  @private
         *  The composition bounds used when creating the TextLines.
         */
        mx_internal var unbounded:Rectangle = new Rectangle(0, 0, NaN, NaN);
        
        /**
         *  @private
         *  The hostFormat object in the _textContainerManager determines the 
         *  default text formatting used by this component, based on its CSS styles. 
         *  This flag is used by updateStylesIfChanged() determine when the object 
         *  must be reinitialized.  It is set in stylesInitialized() and 
         *  styleChanged(), and cleared in commitProperties().  After 
         *  initialization, the hostFormat object should never be null.
         */
        private var hostFormatChanged:Boolean;
        
        /**
         *  @private
         *  It is set to NaN by stylesInitialized() and styleChanged(),
         *  and recreated whenever necessary in calculateFontMetrics().
         */
        private var ascent:Number = NaN;
        
        /**
         *  @private
         *  It is set to NaN by stylesInitialized() and styleChanged(),
         *  and recreated whenever necessary in calculateFontMetrics().
         */
        private var descent:Number = NaN;
        
        /**
         *  @private
         *  Source of text: one of "text", "textFlow" or "content".
         */
        private var source:String = "text";
        
        /**
         *  @private
         *  Holds the last recorded value of the textFlow generation.  Used to
         *  determine whether to return immediately from damage event if there 
         *  have been no changes.
         */
        private var lastGeneration:uint = 0;    // 0 means not set
        
        /**
         *  @private
         *  The generation of the text flow that last reported its content
         *  bounds. 
         */
        private var lastContentBoundsGeneration:int = 0;  // 0 means not set
        
        /**
         *  @private
         *  True if TextOperationEvent.CHANGING and TextOperationEvent.CHANGE 
         *  events should be dispatched.
         */
        private var dispatchChangeAndChangingEvents:Boolean = true;
        
        /**
         *  @private
         */
        private var inMeasureMethod:Boolean = false;
        
        /**
         *  @private
         */
        private var inUpdateDLMethod:Boolean = false;
        
        /**
         *  @private
         */
        private var remeasuringText:Boolean = false;

        /**
         *  @private
         */
        mx_internal var passwordChar:String = "*";
        
        /**
         *  @private
         */
        mx_internal var undoManager:IUndoManager;
        
        /**
         *  @private
         */
        mx_internal var clearUndoOnFocusOut:Boolean = true;
        
        /**
         *  @private
         *  Holds the last recorded value of the module factory used to create the 
         *  font.
         */
        mx_internal var embeddedFontContext:IFlexModuleFactory;
        
        /**
         *  @private
         *  The TLF edit manager will batch all inserted text until the next
         *  enter frame event.  This includes text inserted via the GUI as well
         *  as api calls to EditManager.insertText().  Set this to false if you
         *  want every keystroke to be inserted into the text immediately which will
         *  result in a TextOperationEvent.CHANGE event for each character.  One
         *  place this is needed is for the type-ahead feature of the editable combo
         *  box.
         */
        mx_internal var batchTextInput:Boolean = true;
        
        /**
         *  @private
         *  True if we've seen a MOUSE_DOWN event and haven't seen the 
         *  corresponding MOUSE_UP event.
         */
        private var mouseDown:Boolean = false;
        
        /**
         *  @private
         *  Hold the previous editingMode while using a specific instance manager
         *  so that the editingMode can be restored when the instance manager is
         *  released.
         */
        private var priorEditingMode:String;
        
        /**
         *  @private
         *  Cache the width constraint as set by the layout in setLayoutBoundsSize()
         *  so that text reflow can be calculated during a subsequent measure pass.
         */
        private var widthConstraint:Number = NaN;
        
        /**
         *  @private
         *  Cache the height constraint as set by the layout in setLayoutBoundsSize()
         *  so that text reflow can be calculated during a subsequent measure pass.
         */
        private var heightConstraint:Number = NaN;
        
        /**
         *  @private
         *  If the selection was via the selectRange() or selectAll() api, remember
         *  that until the next selection is set, either interactively or via the
         *  API.
         */
        private var hasProgrammaticSelectionRange:Boolean = false;
        
        /**
         *  @private
         *  True if this component sizes itself based on its actual
         *  contents.
         */
        mx_internal var autoSize:Boolean = false;
        
        /**
         *  @private
         */
        private var lastMeasuredWidth:Number = NaN;
        
        /**
         *  @private
         */
        private var lastMeasuredHeight:Number = NaN;
        
        /**
         *  @private
         */
        private var lastUnscaledWidth:Number;
        /**
         *  @private
         */
        private var lastUnscaledHeight:Number;
        
        //--------------------------------------------------------------------------
        //
        //  Overridden properties: UIComponent
        //
        //--------------------------------------------------------------------------
        
        //----------------------------------
        //  baselinePosition
        //----------------------------------
        
        /**
         *  @private
         */
        override public function get baselinePosition():Number
        {
            return getStyle("paddingTop") + ascent;
        }
        
        //----------------------------------
        //  enabled
        //----------------------------------
        
        /**
         *  @private
         */
        private var enabledChanged:Boolean = false;
        
        /**
         *  @private
         */
        override public function set enabled(value:Boolean):void
        {
            if (value == super.enabled)
                return;
            
            super.enabled = value;
            enabledChanged = true;
            
            invalidateProperties();
            invalidateDisplayList();
        }
        
        //----------------------------------
        // explicitHeight
        //----------------------------------
        
        /**
         *  @private
         */
        override public function set explicitHeight(value:Number):void
        {
            super.explicitHeight = value;
            
            heightConstraint = NaN;
            
            // Because of autoSizing, the size and display might be impacted.
            invalidateSize();
            invalidateDisplayList();
        }
        
        //----------------------------------
        // explicitWidth
        //----------------------------------
        
        /**
         *  @private
         */
        override public function set explicitWidth(value:Number):void
        {
            super.explicitWidth = value;
            
            widthConstraint = NaN;
            
            // Because of autoSizing, the size and display might be impacted.
            invalidateSize();
            invalidateDisplayList();
        }
        
        //----------------------------------
        // isTruncated
        //----------------------------------
        
        /**
         *  @private
         */
        public function get isTruncated():Boolean
        {
            // This class does not support truncation
            return false;
        }
               
        //----------------------------------
        // percentHeight
        //----------------------------------
        
        /**
         *  @private
         */
        override public function set percentHeight(value:Number):void
        {
            super.percentHeight = value;
            
            heightConstraint = NaN;
            
            // If we were autoSizing and now we are not we need to remeasure.
            invalidateSize();
            invalidateDisplayList();
        }
        
        //----------------------------------
        // percentWidth
        //----------------------------------
        
        /**
         *  @private
         */
        override public function set percentWidth(value:Number):void
        {
            super.percentWidth = value;
            
            widthConstraint = NaN;
            
            // If we were autoSizing and now we are not we need to remeasure.
            invalidateSize();
            invalidateDisplayList();
        }
        
        //--------------------------------------------------------------------------
        //
        //  Properties: ISystemCursorClient
        //
        //--------------------------------------------------------------------------
        
        /**
         *  True if the system cursor should always be shown when the mouse 
         *  moves over the component.  If false, the custom cursor will be shown.
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get showSystemCursor():Boolean
        {
            return editable;        
        }
        
        //--------------------------------------------------------------------------
        //
        //  Properties: IViewport
        //
        //--------------------------------------------------------------------------
        
        //----------------------------------
        //  clipAndEnableScrolling
        //----------------------------------
        
        /**
         *  @private
         */
        private var _clipAndEnableScrolling:Boolean = false;
        
        /**
         *  @private
         */
        private var clipAndEnableScrollingChanged:Boolean = false;
        
        /**
         *  @copy spark.core.IViewport#clipAndEnableScrolling
         *
         *  @default false
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get clipAndEnableScrolling():Boolean 
        {
            return _clipAndEnableScrolling;
        }
        
        /**
         *  @private
         *  Set to true by a scroller when it installs this as a viewport.
         *  Set to false by a scroller when it uninstalls this as a viewport.
         */
        public function set clipAndEnableScrolling(value:Boolean):void 
        {
            if (value == _clipAndEnableScrolling) 
                return;
            
            _clipAndEnableScrolling = value;
            clipAndEnableScrollingChanged = true;
            
            invalidateProperties();
        }
        
        //----------------------------------
        //  contentHeight
        //----------------------------------
        
        /**
         *  @private
         */
        private var _contentHeight:Number = 0;
        
        [Bindable("propertyChange")]
        
        /**
         *  The height of the text.
         *
         *  <p>Due to the fact that the Text Layout Framework
         *  virtualizes TextLines for performance,
         *  this height will initially be an estimate
         *  if the component cannot display all of the text.
         *  If you scroll to the end of the text,
         *  all the TextLines will get composed
         *  and the <code>contentHeight</code> will be exact.</p>
         *
         *  <p>To scroll over the text vertically, vary the 
         *  <code>verticalScrollPosition</code> between 0 and
         *  <code>contentHeight - height</code>.</p>
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get contentHeight():Number
        {
            return _contentHeight;
        }
        
        //----------------------------------
        //  contentWidth
        //----------------------------------
        
        /**
         *  @private
         */
        private var _contentWidth:Number = 0;
        
        [Bindable("propertyChange")]
        
        /**
         *  The width of the text.
         *
         *  <p>Due to the fact that the Text Layout Framework
         *  virtualizes TextLines for performance,
         *  this width will initially be an estimate
         *  if the component cannot display all of the text.
         *  If you scroll to the end of the text,
         *  all the TextLines will get composed
         *  and the <code>contentWidth</code> will be exact.</p>
         *
         *  <p>To scroll over the text horizontally, vary the 
         *  <code>horizontalScrollPosition</code> between 0 and
         *  <code>contentWidth - width</code>.</p>  
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get contentWidth():Number
        {
            return _contentWidth;
        }
        
        //----------------------------------
        //  horizontalScrollPosition
        //----------------------------------

        /**
         *  @private
         */
        private var _horizontalScrollPosition:Number = 0;
        
        /**
         *  @private
         */
        private var horizontalScrollPositionChanged:Boolean = false;
        
        [Bindable("propertyChange")]
        [Inspectable(defaultValue="0", minValue="0.0")]
                
        /**
         *  The number of pixels by which the text is scrolled horizontally.
         *
         *  <p>To scroll over the text horizontally, vary the 
         *  <code>horizontalScrollPosition</code> between 0 and
         *  <code>contentWidth - width</code>.</p>
         *
         *  @default 0
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get horizontalScrollPosition():Number
        {
            return _horizontalScrollPosition;
        }
        
        /**
         *  @private
         */
        public function set horizontalScrollPosition(value:Number):void
        {
            // Convert NaN to 0 to keep TCM happy.
            if (isNaN(value))
                value = 0;
            
            if (value == _horizontalScrollPosition)
                return;
            
            _horizontalScrollPosition = value;
            horizontalScrollPositionChanged = true;
            
            invalidateProperties();
            
            // Note:  TLF takes care of updating the container when the scroll
            // position is set so there is no need for us to invalidate the 
            // display list.
        }
        
        //----------------------------------
        //  verticalScrollPosition
        //----------------------------------
        
        /**
         *  @private
         */
        private var _verticalScrollPosition:Number = 0;
        
        /**
         *  @private
         */
        private var verticalScrollPositionChanged:Boolean = false;
        
        [Bindable("propertyChange")]
        [Inspectable(defaultValue="0", minValue="0.0")]
                
        /**
         *  The number of pixels by which the text is scrolled vertically.
         *
         *  <p>To scroll over the text vertically, vary the 
         *  <code>verticalScrollPosition</code> between 0 and
         *  <code>contentHeight - height</code>.</p>
         *
         *  @default 0
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get verticalScrollPosition():Number
        {
            return _verticalScrollPosition;
        }
        
        /**
         *  @private
         */
        public function set verticalScrollPosition(value:Number):void
        {
            // Convert NaN to 0 to keep TCM happy.
            if (isNaN(value))
                value = 0;
            
            if (value == _verticalScrollPosition)
                return;
            
            _verticalScrollPosition = value;
            verticalScrollPositionChanged = true;
            
            invalidateProperties();
            
            // Note:  TLF takes care of updating the container when the scroll
            // position is set so there is no need for us to invalidate the 
            // display list.
        }
        
        //--------------------------------------------------------------------------
        //
        //  Properties
        //
        //--------------------------------------------------------------------------
        
        //----------------------------------
        //  content
        //----------------------------------
        
        /**
         *  @private
         */
        private var _content:Object;
        
        /**
         *  @private
         */
        private var contentChanged:Boolean = false;
        
        /**
         *  @private
         *  This metadata tells the MXML compiler to disable some of its default
         *  interpretation of the value specified for the 'content' property.
         *  Normally, for properties of type Object, it assumes that things
         *  looking like numbers are numbers and things looking like arrays
         *  are arrays. But <content>1</content> should generate code to set the
         *  content to  the String "1", not the int 1, and <content>[1]</content>
         *  should set it to the String "[1]", not the Array [ 1 ].
         *  However, {...} continues to be interpreted as a databinding
         *  expression, and @Resource(...), @Embed(...), etc.
         *  as compiler directives.
         *  Similar metadata on TLF classes causes the same rules to apply
         *  within <p>, <span>, etc.
         */
        [RichTextContent]
                
        /**
         *  This property is intended for use in MXML at compile time;
         *  to get or set rich text content at runtime,
         *  please use the <code>textFlow</code> property instead.
         *
         *  <p>The <code>content</code> property is the default property
         *  for RichEditableText, so that you can write MXML such as
         *  <pre>
         *  &lt;s:RichEditableText&gt;Hello &lt;s:span fontWeight="bold"/&gt;World&lt;/s:span&gt;&lt;/s:RichEditableText&gt;
         *  </pre>
         *  and have the String and SpanElement that you specify
         *  as the content be used to create a TextFlow.</p>
         *
         *  <p>This property is typed as Object because you can set it to
         *  to a String, a FlowElement, or an Array of Strings and FlowElements.
         *  In the example above, you are specifying the content
         *  to be a 2-element Array whose first element is the String
         *  "Hello" and whose second element is a SpanElement with the text
         *  "World" in boldface.</p>
         * 
         *  <p>No matter how you specify the content, it gets converted
         *  into a TextFlow, and when you get this property, you will get
         *  the resulting TextFlow.</p>
         * 
         *  <p>Adobe recommends using <code>textFlow</code> property
         *  to get and set rich text content at runtime,
         *  because it is strongly typed as a TextFlow
         *  rather than as an Object.
         *  A TextFlow is the canonical representation
         *  for rich text content in the Text Layout Framework.</p>
         * 
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get content():Object
        {
            return textFlow;
        }
        
        /**
         *  @private
         */   
        public function set content(value:Object):void
        {
            // Treat setting the 'content' to null
            // as if 'text' were being set to the empty String
            // (which is the default state).
            if (value == null)
            {
                text = "";
                return;
            }
            
            if (value == _content)
                return;
            
            _content = value;
            contentChanged = true;
            source = "content";
            
            // Of 'text', 'textFlow', and 'content', the last one set wins.
            textChanged = false;
            textFlowChanged = false;
            
            // The other two are now invalid and must be recalculated when needed.
            _text = null;
            _textFlow = null;
            
            invalidateProperties();
            invalidateSize();
            invalidateDisplayList();
            
            dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));                                   
        }
        
        //----------------------------------
        //  displayAsPassword
        //----------------------------------
        
        /**
         *  @private
         */
        private var _displayAsPassword:Boolean = false;
        
        /**
         *  @private
         */
        private var displayAsPasswordChanged:Boolean = false;
        
        [Inspectable(category="General", defaultValue="false")]
        
        /**
         *  @copy flash.text.TextField#displayAsPassword
         *
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get displayAsPassword():Boolean
        {
            return _displayAsPassword;
        }
        
        /**
         *  @private
         */
        public function set displayAsPassword(value:Boolean):void
        {
            if (value == _displayAsPassword)
                return;
            
            _displayAsPassword = value;
            displayAsPasswordChanged = true;
            
            invalidateProperties();
            invalidateSize();
            invalidateDisplayList();
        }
        
        //----------------------------------
        //  editable
        //----------------------------------
        
        /**
         *  @private
         */
        private var _editable:Boolean = true;
        
        /**
         *  @private
         */
        private var editableChanged:Boolean = false;
        
        [Inspectable(category="General", defaultValue="true")]
        
        /**
         *  A flag indicating whether the user is allowed
         *  to edit the text in this control.
         *
         *  <p>If <code>true</code>, the mouse cursor will change to an i-beam
         *  when over the bounds of this control.
         *  If <code>false</code>, the mouse cursor will remain an arrow.</p>
         *
         *  <p>If this property is <code>true</code>,
         *  the <code>selectable</code> property is ignored.</p>
         *
         *  @default true
         *
         *  @see spark.components.RichEditableText#selectable
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get editable():Boolean
        {
            return _editable;
        }
        
        /**
         *  @private
         */
        public function set editable(value:Boolean):void
        {
            if (value == _editable)
                return;
            
            _editable = value;
            editableChanged = true;
            
            invalidateProperties();
            invalidateDisplayList();
        }
        
        //----------------------------------
        //  editingMode
        //----------------------------------
        
        [Inspectable(category="General", defaultValue="readWrite", enumeration="readOnly,readWrite,readSelect")]

        /**
         *  @private
         *  The editingMode of this component's TextContainerManager.
         *  Note that this is not a public property
         *  and does not use the invalidation mechanism.
         */
        private function get editingMode():String
        {
            // Note: this could be called before all properties are committed.
            
            if (enabledChanged || editableChanged || selectableChanged)
            {
                updateEditingMode();
                
                enabledChanged = false;
                editableChanged = false;
                selectableChanged = false;
            }
            
            return _textContainerManager.editingMode;
        }
        
        /**
         *  @private
         */
        private function set editingMode(value:String):void
        {
            var lastEditingMode:String = _textContainerManager.editingMode;
            
            if (lastEditingMode == value)
                return;
            
            _textContainerManager.editingMode = value;
            
            // Make sure the selection manager selection is in sync with the
            // current selection.
            if (value != EditingMode.READ_ONLY && 
                _selectionAnchorPosition != -1 && _selectionActivePosition != -1)
            {
                var selectionManager:ISelectionManager = 
                    _textContainerManager.beginInteraction();
                
                selectionManager.selectRange(
                    _selectionAnchorPosition, _selectionActivePosition);
                
                _textContainerManager.endInteraction();
            }
        }
        
        //----------------------------------
        //  enableIME
        //----------------------------------
        
        /**
         *  A flag that indicates whether the IME should
         *  be enabled when the component receives focus.
         *
         *  @returns true if the component is editable and it is not displaying a password.
         * 
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get enableIME():Boolean
        {
            return editable && !displayAsPassword;
        }
        
        //----------------------------------
        //  heightInLines
        //----------------------------------
        
        /**
         *  @private
         */
        private var _heightInLines:Number = NaN;
        
        /**
         *  @private
         */
        private var heightInLinesChanged:Boolean = false;
        
        [Inspectable(category="General", minValue="0.0")]
        
        /**
         *  The default height of the control, measured in lines.
         *
         *  <p>The control's formatting styles, such as <code>fontSize</code>
         *  and <code>lineHeight</code>, are used to calculate the line height
         *  in pixels.</p>
         *
         *  <p>You would, for example, set this property to 5 if you want
         *  the height of the RichEditableText to be sufficient
         *  to display five lines of text.</p>
         *
         *  <p>If this property is <code>NaN</code> (the default),
         *  then the component's default height will be determined
         *  from the text to be displayed.</p>
         *  
         *  <p>This property will be ignored if you specify an explicit height,
         *  a percent height, or both <code>top</code> and <code>bottom</code>
         *  constraints.</p>
         *
         *  <p>This property will also be ignored if the <code>typicalText</code> 
         *  property is specified.</p>
         * 
         *  <p>RichEditableText's <code>measure()</code> method uses
         *  <code>widthInChars</code> and <code>heightInLines</code>
         *  to determine the <code>measuredWidth</code>
         *  and <code>measuredHeight</code>.
         *  These are similar to the <code>cols</code> and <code>rows</code>
         *  of an HTML TextArea.</p>
         *
         *  <p>Since both <code>widthInChars</code> and <code>heightInLines</code>
         *  default to <code>NaN</code>, RichTextEditable "autosizes" by default:
         *  it starts out very small if it has no text, grows in width as you
         *  type, and grows in height when you press Enter to start a new line.</p>
         *
         *  @default NaN
         *
         *  @see spark.components.RichEditableText#widthInChars
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get heightInLines():Number
        {
            return _heightInLines;
        }
        
        /**
         *  @private
         */
        public function set heightInLines(value:Number):void
        {
            if (value == _heightInLines)
                return;
            
            _heightInLines = value;
            heightInLinesChanged = true;
            
            heightConstraint = NaN;
            
            invalidateProperties();
            invalidateSize();
            invalidateDisplayList();
        }
        
        //----------------------------------
        //  imeMode
        //----------------------------------
        
        /**
         *  @private
         */
        private var _imeMode:String = null;
        
        /**
         *  Specifies the IME (input method editor) mode.
         *  The IME enables users to enter text in Chinese, Japanese, and Korean.
         *  Flex sets the specified IME mode when the control gets the focus,
         *  and sets it back to the previous value when the control loses the focus.
         *
         *  <p>The flash.system.IMEConversionMode class defines constants for the
         *  valid values for this property.
         *  You can also specify <code>null</code> to specify no IME.</p>
         *
         *  @default null
         * 
         *  @see flash.system.IMEConversionMode
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get imeMode():String
        {
            return _imeMode;
        }
        
        /**
         *  @private
         */
        public function set imeMode(value:String):void
        {
            _imeMode = value;
        }
        
        //----------------------------------
        //  lineBreak
        //----------------------------------
        
        [Inspectable(environment="none")]

        /**
         *  @private
         * 
         *  This property is only defined to implement the IEditableText
         *  interface. The lineBreak style should be used instead of this
         *  property.
         */
        public function get lineBreak():String
        {
            return getStyle("lineBreak");
        }
        
        /**
         *  @private
         */
        public function set lineBreak(value:String):void
        {
            setStyle("lineBreak", value);
        }
        
        //----------------------------------
        //  maxChars
        //----------------------------------
        
        /**
         *  @private
         */
        private var _maxChars:int = 0;
        
        [Inspectable(category="General", defaultValue="0")]
        
        /**
         *  @copy flash.text.TextField#maxChars
         * 
         *  @default 0
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get maxChars():int 
        {
            return _maxChars;
        }
        
        /**
         *  @private
         */
        public function set maxChars(value:int):void
        {
            _maxChars = value;
        }
        
        //----------------------------------
        //  multiline
        //----------------------------------
        
        /**
         *  @private
         */
        private var _multiline:Boolean = true;
        
        [Inspectable(category="General", defaultValue="true")]
        
        /**
         *  Determines whether the user can enter multiline text.
         *
         *  <p>If <code>true</code>, the Enter key starts a new paragraph.
         *  If <code>false</code>, the Enter key doesn't affect the text
         *  but causes the RichEditableText to dispatch an <code>"enter"</code> 
         *  event.  If you paste text into the RichEditableText with a multiline 
         *  value of <code>false</code>, newlines are stripped out of the text. </p>  
         * 
         *  @default true
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get multiline():Boolean 
        {
            return _multiline;
        }
        
        /**
         *  @private
         */
        public function set multiline(value:Boolean):void
        {
            _multiline = value;
        }
 
        //----------------------------------
        //  restrict
        //----------------------------------
        
        /**
         *  @private
         */
        private var _restrict:String = null;
        
        [Inspectable(category="General", defaultValue="null")]
        
        /**
         *  @copy flash.text.TextField#restrict
         * 
         *  @default null
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get restrict():String 
        {
            return _restrict;
        }
        
        /**
         *  @private
         */
        public function set restrict(value:String):void
        {
            _restrict = value;
        }
        
        //----------------------------------
        //  selectable
        //----------------------------------
        
        /**
         *  @private
         */
        private var _selectable:Boolean = true;
        
        /**
         *  @private
         */
        private var selectableChanged:Boolean = false;
        
        [Inspectable(category="General", defaultValue="true")]
        
        /**
         *  A flag indicating whether the content is selectable
         *  with the mouse, or with the keyboard when the control
         *  has the keyboard focus.
         *
         *  <p>Making the text selectable lets you copy text from the control.</p>
         *
         *  <p>This property is ignored if the <code>editable</code>
         *  property is <code>true</code>.</p>
         *
         *  @default true
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get selectable():Boolean
        {
            return _selectable;
        }
        
        /**
         *  @private
         */
        public function set selectable(value:Boolean):void
        {
            if (value == _selectable)
                return;
            
            _selectable = value;
            selectableChanged = true;
            
            invalidateProperties();
            invalidateDisplayList();
        }
        
        //----------------------------------
        //  selectionActivePosition
        //----------------------------------
        
        /**
         *  @private
         */
        private var _selectionActivePosition:int = -1;
        
        [Bindable("selectionChange")]
        [Inspectable(category="General", defaultValue="-1")]
        
        /**
         *  A character position, relative to the beginning of the
         *  <code>text</code> String, specifying the end of the selection
         *  that moves when the selection is extended with the arrow keys.
         *
         *  <p>The active position may be either the start
         *  or the end of the selection.</p>
         *
         *  <p>For example, if you drag-select from position 12 to position 8,
         *  then <code>selectionAnchorPosition</code> will be 12
         *  and <code>selectionActivePosition</code> will be 8,
         *  and when you press Left-Arrow <code>selectionActivePosition</code>
         *  will become 7.</p>
         *
         *  <p>A value of -1 indicates "not set".</p>
         *
         *  @default -1
         *
         *  @see spark.components.RichEditableText#selectionAnchorPosition
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get selectionActivePosition():int
        {
            return _selectionActivePosition;
        }
        
        //----------------------------------
        //  selectionAnchorPosition
        //----------------------------------
        
        /**
         *  @private
         */
        private var _selectionAnchorPosition:int = -1;
        
        [Bindable("selectionChange")]
        [Inspectable(category="General", defaultValue="-1")]
        
        /**
         *  A character position, relative to the beginning of the
         *  <code>text</code> String, specifying the end of the selection
         *  that stays fixed when the selection is extended with the arrow keys.
         *
         *  <p>The anchor position may be either the start
         *  or the end of the selection.</p>
         *
         *  <p>For example, if you drag-select from position 12 to position 8,
         *  then <code>selectionAnchorPosition</code> will be 12
         *  and <code>selectionActivePosition</code> will be 8,
         *  and when you press Left-Arrow <code>selectionActivePosition</code>
         *  will become 7.</p>
         *
         *  <p>A value of -1 indicates "not set".</p>
         *
         *  @default -1
         *
         *  @see spark.components.RichEditableText#selectionActivePosition
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get selectionAnchorPosition():int
        {
            return _selectionAnchorPosition;
        }
        
        //----------------------------------
        //  selectionHighlighting
        //----------------------------------
        
        /**
         *  @private
         */
        private var _selectionHighlighting:String =
            TextSelectionHighlighting.WHEN_FOCUSED;
        
        /**
         *  @private
         *  To indicate either selection highlighting or selection styles have
         *  changed.
         */
        private var selectionFormatsChanged:Boolean = false;
        
        [Inspectable(category="General", enumeration="always,whenActive,whenFocused", defaultValue="whenFocused")]
        
        /**
         *  Determines when the text selection is highlighted.
         *  
         *  <p>The allowed values are specified by the
         *  spark.components.TextSelectionHighlighting class.
         *  Possible values are <code>TextSelectionHighlighting.WHEN_FOCUSED</code>,
         *  <code>TextSelectionHighlighting.WHEN_ACTIVE</code>,
         *  and <code>TextSelectionHighlighting.ALWAYS</code>.</p>
         *
         *  <p><code>WHEN_FOCUSED</code> shows the text selection
         *  only when the component has keyboard focus.</p>
         *  
         *  <p><code>WHEN_ACTIVE</code> shows the text selection whenever
         *  the component's window is active, even if the component
         *  doesn't have the keyboard focus.</p>
         *
         *  <p><code>ALWAYS</code> shows the text selection,
         *  even if the component doesn't have the keyboard focus
         *  or if the component's window isn't the active window.</p>
         *  
         *  @default TextSelectionHighlighting.WHEN_FOCUSED
         *  
         *  @see spark.components.TextSelectionHighlighting
         * 
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get selectionHighlighting():String 
        {
            return _selectionHighlighting;
        }
        
        /**
         *  @private
         */
        public function set selectionHighlighting(value:String):void
        {
            if (value == _selectionHighlighting)
                return;
            
            _selectionHighlighting = value;
            selectionFormatsChanged = true;
            
            invalidateProperties();
            invalidateDisplayList();
        }
        
        //----------------------------------
        //  text
        //----------------------------------
        
        /**
         *  @private
         */
        private var _text:String = "";
        
        /**
         *  @private
         */
        private var textChanged:Boolean = false;
        
        [Bindable("change")]
        [Inspectable(category="General", defaultValue="")]
        
        /**
         *  The text String displayed by this component.
         *
         *  <p>Setting this property affects the <code>textFlow</code> property
         *  and vice versa.</p>
         *
         *  <p>If you set the <code>text</code> to a String such as
         *  <code>"Hello World"</code> and get the <code>textFlow</code>,
         *  it will be a TextFlow containing a single ParagraphElement
         *  with a single SpanElement.</p>
         *
         *  <p>If you set the <code>text</code> to null, it will be
         *  set to the default value which is an empty string.</p>
         * 
         *  <p>If the text contains explicit line breaks --
         *  CR ("\r"), LF ("\n"), or CR+LF ("\r\n") --
         *  then the content will be set to a TextFlow
         *  which contains multiple paragraphs, each with one span.</p>
         *
         *  <p>If you set the <code>textFlow</code> and get the <code>text</code>,
         *  the text in each paragraph will be separated by a single
         *  LF ("\n").</p>
         *
         *  <p>Setting this property also affects the properties
         *  specifying the control's scroll position and the text selection.
         *  It resets the <code>horizontalScrollPosition</code>
         *  and <code>verticalScrollPosition</code> to 0.
         *  Starting with Flex 4.6, the <code>selectionAnchorPosition</code> and 
         *  <code>selectionActivePosition</code> are preserved.
         *  Previously, the <code>selectionAnchorPosition</code>
         *  and <code>selectionActivePosition</code> were set
         *  to -1 to clear the selection.</p>
         *
         *  @default ""
         *
         *  @see spark.components.RichEditableText#textFlow
         *  @see spark.components.RichEditableText#horizontalScrollPosition
         *  @see spark.components.RichEditableText#verticalScrollPosition
         *  @see spark.components.RichEditableText#selectionAnchorPosition
         *  @see spark.components.RichEditableText#selectionActivePosition
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get text():String 
        {
            // Note: if displayAsPassword, _text will contain the actual text and the text flow will
            // contain the same number of passwordChars.
            
            // Go to the source if there isn't a pending change.  getText has its own buffering and 
            // only extracts the text from the TextFlow when it is damaged. 
            if (_textContainerManager && !textChanged && !textFlowChanged && !contentChanged && !displayAsPassword)
                return _textContainerManager.getText("\n");
            
            // Extracting the plaintext from a TextFlow is somewhat expensive,
            // as it involves iterating over the leaf FlowElements in the TextFlow.
            // Therefore we do this extraction only when necessary, namely when
            // you first set the 'content' or the 'textFlow'
            // (or mutate the TextFlow), and then get the 'text'.
            if (_text == null)
            {
                // If 'content' was last set,
                // we have to first turn that into a TextFlow.
                if (_content != null)
                    _textFlow = createTextFlowFromContent(_content);
                
                // Once we have a TextFlow, we can export its plain text.
                _text = staticPlainTextExporter.export(
                    _textFlow, ConversionType.STRING_TYPE) as String;
            }
            
            return _text;
        }
        
        /**
         *  @private
         *  This will create a TextFlow with a single paragraph with a single span 
         *  with exactly the text specified.  If there is whitespace and line 
         *  breaks in the text, they will remain, regardless of the settings of
         *  the lineBreak and whiteSpaceCollapse styles.
		 * 
		 *  Similiar to TextField, the selection is preserved when the text is set.
		 *  If the new text length is less than the existing text length, the selection 
		 *  may change.
         */
        public function set text(value:String):void
        {
            // Treat setting the 'text' to null
            // as if it were set to the empty String
            // (which is the default state).
            if (value == null)
                value = "";
            
            // If value is the same as _text, make sure if was not produced from
            // setting 'textFlow' or 'content'.  For example, if you set a TextFlow 
            // corresponding to "Hello <span color="OxFF0000">World</span>"
            // and then get the 'text', it will be the String "Hello World"
            // But if you then set the 'text' to "Hello World"
            // this represents a change: the "World" should no longer be red.
            //
            // Note: this is needed to stop two-binding from recursing.
            if (source == "text" && text == value)
                return;
            
            _text = value;
            textChanged = true;
            source = "text";
            
            // Of 'text', 'textFlow', and 'content', the last one set wins.
            textFlowChanged = false;
            contentChanged = false;
            
            // The other two are now invalid and must be recalculated when needed.
            _textFlow = null;
            _content = null;
            
            invalidateProperties();
            invalidateSize();
            invalidateDisplayList();
            
            dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));                                   
        }
        
        //----------------------------------
        //  textContainerManager
        //----------------------------------
        
        /**
         *  @private
         */
        private var _textContainerManager:RichEditableTextContainerManager;
        
        /**
         *  @private
         *  The TLF TextContainerManager instance that displays,
         *  scrolls, and edits the text in this component.
         */
        mx_internal function get textContainerManager():TextContainerManager
        {
            return _textContainerManager;
        }
        
        //----------------------------------
        //  textFlow
        //----------------------------------
        
        /**
         *  @private
         *  Storage for the textFlow property.
         */
        private var _textFlow:TextFlow;
        
        /**
         *  @private
         */
        private var textFlowChanged:Boolean = false;
        
        /**
         *  The TextFlow representing the rich text displayed by this component.
         * 
         *  <p>A TextFlow is the most important class
         *  in the Text Layout Framework (TLF).
         *  It is the root of a tree of FlowElements
         *  representing rich text content.</p>
         *
         *  <p>You normally create a TextFlow from TLF markup
         *  using the <code>TextFlowUtil.importFromString()</code>
         *  or <code>TextFlowUtil.importFromXML()</code> methods.
         *  Alternately, you can use TLF's TextConverter class
         *  (which can import a subset of HTML) or build a TextFlow
         *  using methods like <code>addChild()</code> on TextFlow.</p>
         *
         *  <p>Setting this property affects the <code>text</code> property
         *  and vice versa.</p>
         *
         *  <p>If you set the <code>textFlow</code> and get the <code>text</code>,
         *  the text in each paragraph will be separated by a single
         *  LF ("\n").</p>
         *
         *  <p>If you set the <code>text</code> to a String such as
         *  <code>"Hello World"</code> and get the <code>textFlow</code>,
         *  it will be a TextFlow containing a single ParagraphElement
         *  with a single SpanElement.</p>
         *
         *  <p>If the text contains explicit line breaks --
         *  CR ("\r"), LF ("\n"), or CR+LF ("\r\n") --
         *  then the content will be set to a TextFlow
         *  which contains multiple paragraphs, each with one span.</p>
         *
         *  <p>Setting this property also affects the properties
         *  specifying the control's scroll position and the text selection.
         *  It resets the <code>horizontalScrollPosition</code>
         *  and <code>verticalScrollPosition</code> to 0,
         *  and it sets the <code>selectionAnchorPosition</code>
         *  and <code>selectionActivePosition</code>
         *  to -1 to clear the selection.</p>
         *
         *  <p>To turn a TextFlow object into TLF markup,
         *  use the <code>TextFlowUtil.export()</code> markup.</p>
         *
         *  <p>A single TextFlow cannot be shared by multiple instances
         *  of RichEditableText.
         *  To display the same text in a second instance, you must create
         *  a second TextFlow, either by using <code>TextFlowUtil.export()</code>
         *  and <code>TextFlowUtil.importFromXML()</code> or by using
         *  the <code>deepCopy()</code> method on TextFlow.</p>
         *
         *  @see spark.utils.TextFlowUtil#importFromString()
         *  @see spark.utils.TextFlowUtil#importFromXML()
         *  @see spark.components.RichEditableText#text
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 2.5
         *  @productversion Flex 4.5
         */
        public function get textFlow():TextFlow
        {
            // Note: this could be called before all properties are committed.
            
            // We might not have a valid _textFlow for two reasons:
            // either because the 'text' was set (which is the state
            // after construction) or because the 'content' was set.
            if (!_textFlow)
            {
                if (_content != null)
                {
                    _textFlow = createTextFlowFromContent(_content);
                    _content = null;
                }
                else
                {
                    _textFlow = staticPlainTextImporter.importToFlow(_text);
                }
                textFlowChanged = true;
            }
            
            // Make sure the interactionManager and controller are added to this textFlow.           
            if (textChanged || contentChanged || textFlowChanged)
            {
                _textContainerManager.setTextFlow(_textFlow);
                textChanged = contentChanged = textFlowChanged = false;
            }
            
            // If not read-only, make sure the textFlow has a composer in
            // place so that it can be modified by the caller if desired.
            if (editingMode != EditingMode.READ_ONLY)
            {
                _textContainerManager.beginInteraction();
                _textContainerManager.endInteraction();
            }
            
            return _textFlow;
        }
        
        /**
         *  @private
         */
        public function set textFlow(value:TextFlow):void
        {
            // Treat setting the 'textFlow' to null
            // as if 'text' were being set to the empty String
            // (which is the default state).
            if (value == null)
            {
                text = "";
                return;
            }
            
            if (value == _textFlow)
                return;
            
            _textFlow = value;
            textFlowChanged = true;
            source = "textFlow";
            
            // Of 'text', 'textFlow', and 'content', the last one set wins.
            textChanged = false;
            contentChanged = false;
            
            // The other two are now invalid and must be recalculated when needed.
            _text = null
            _content = null;
            
            invalidateProperties();
            invalidateSize();
            invalidateDisplayList();
            
            dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));                                   
        }
        
        //----------------------------------
        //  typicalText
        //----------------------------------
        
        /**
         *  @private
         */
        private var typicalTextChanged:Boolean;
                
        /**
         *  @private
         */
        private var _typicalText:String;
        
        /**
         *  @private
         *  Used when _typicalText is multiline
         */
        private var _typicalTextFlow:TextFlow;
        
        [Inspectable(category="General", defaultValue="null")]

        /**
         *  Text that is used to determine
         *  the default width and height of the control, 
         *  without actually being displayed.
         *
         *  <p>This property will be ignored if you specify an explicit width,
         *  a percent width, or both <code>left</code> and <code>right</code>
         *  constraints.</p>
         *
         *  <p>Use of this property causes the <code>widthInChars</code> 
         *  and <code>heightInLines</code> properties to be ignored. </p>
         *
         *  @default null
         *
         *  @see spark.primitives.heightInLines
         *  @see spark.primitives.widthInChars
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.0
         *  @productversion Flex 4.5
         */
        public function get typicalText():String 
        {
            return _typicalText;
        }
        
        /**
         *  @private
         */
        public function set typicalText(value:String):void
        {
            if (value == _typicalText)
                return;
            
            _typicalText = value;
            
            typicalTextChanged = true;
            
            invalidateProperties();
            invalidateSize();
            invalidateDisplayList();
        }
        
        //----------------------------------
        //  widthInChars
        //----------------------------------
        
        /**
         *  @private
         *  These are measured in ems.
         */
        private var _widthInChars:Number = NaN;
        
        /**
         *  @private
         */
        private var widthInCharsChanged:Boolean = true;
        
        [Inspectable(category="General", minValue="0.0")]

        /**
         *  The default width of the control, measured in em units.
         *
         *  <p>An em is a unit of typographic measurement
         *  equal to the point size.
         *  It is not necessarily exactly the width of the "M" character,
         *  but in many fonts the "M" is about one em wide.
         *  The control's <code>fontSize</code> style is used,
         *  to calculate the em unit in pixels.</p>
         *
         *  <p>You would, for example, set this property to 20 if you want
         *  the width of the RichEditableText to be sufficient
         *  to display about 20 characters of text.</p>
         *
         *  <p>If this property is <code>NaN</code> (the default),
         *  then the component's default width will be determined
         *  from the text to be displayed.</p>
         *
         *  <p>This property will be ignored if you specify an explicit width,
         *  a percent width, or both <code>left</code> and <code>right</code>
         *  constraints.</p>
         *
         *  <p>This property will also be ignored if the <code>typicalText</code> 
         *  property is specified.</p>
         * 
         *  <p>RichEditableText's <code>measure()</code> method uses
         *  <code>widthInChars</code> and <code>heightInLines</code>
         *  to determine the <code>measuredWidth</code>
         *  and <code>measuredHeight</code>. 
         *  These are similar to the <code>cols</code> and <code>rows</code>
         *  of an HTML TextArea.</p>
         *
         *  <p>Since both <code>widthInChars</code> and <code>heightInLines</code>
         *  default to <code>NaN</code>, RichTextEditable "autosizes" by default:
         *  it starts out very small if it has no text, grows in width as you
         *  type, and grows in height when you press Enter to start a new line.</p>
         *
         *  @default NaN
         *
         *  @see spark.primitives.heightInLines
         *
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function get widthInChars():Number 
        {
            return _widthInChars;
        }
        
        /**
         *  @private
         */
        public function set widthInChars(value:Number):void
        {
            if (value == _widthInChars)
                return;
            
            _widthInChars = value;
            widthInCharsChanged = true;
            
            widthConstraint = NaN;
            
            invalidateProperties();
            invalidateSize();
            invalidateDisplayList();
        }
        
        //--------------------------------------------------------------------------
        //
        //  Overridden Methods: UIComponent
        //
        //--------------------------------------------------------------------------
        
        /**
         *  @private
         */
        override protected function initializeAccessibility():void
        {
            if (RichEditableText.createAccessibilityImplementation != null)
                RichEditableText.createAccessibilityImplementation(this);
        }
        
        /**
         *  @private
         */
        override public function parentChanged(p:DisplayObjectContainer):void
        {
            if (focusManager)
            {
                focusManager.removeEventListener(FlexEvent.FLEX_WINDOW_ACTIVATE, 
                    _textContainerManager.activateHandler)
                focusManager.removeEventListener(FlexEvent.FLEX_WINDOW_DEACTIVATE, 
                    _textContainerManager.deactivateHandler)
            }
            
            super.parentChanged(p);
            
            if (focusManager)
            {
                addActivateHandlers();
            }
            else
            {
                // if no focusmanager yet, add capture phase to detect when it
                // gets added
                if (systemManager)
                    systemManager.getSandboxRoot().addEventListener(FlexEvent.ADD_FOCUS_MANAGER, 
                        addFocusManagerHandler, true, 0, true)
                else
                    // no systemManager yet?  Check again when added to stage
                    addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
            }
            
        }
        
        /**
         *  @private
         */
        override public function removeChild(child:DisplayObject):DisplayObject
        {
            // not sure why this happens but it does if you just change
            // the embeddedFont context
            if (!child.parent)
                return child;
            
            if (child.parent == this)
                return super.removeChild(child);
            
            return child.parent.removeChild(child);
        }
        
        /**
         *  @private
         */
        override protected function commitProperties():void
        {
            super.commitProperties();
            
            updateStylesIfChanged();
            
            var oldAnchorPosition:int = _selectionAnchorPosition;
            var oldActivePosition:int = _selectionActivePosition;
            
            // EditingMode needs to be current before attempting to set a
            // selection below.
            if (enabledChanged || selectableChanged || editableChanged)
            {
                updateEditingMode();
                
                enabledChanged = false;
                editableChanged = false;
                selectableChanged = false;          
            }
            
            // Only one of textChanged, textFlowChanged, and contentChanged
            // will be true; the other two will be false because each setter
            // guarantees this.
            
            if (textChanged)
            {
                // If the text has linebreaks (CR, LF, or CF+LF)
                // create a multi-paragraph TextFlow from it
                // and use the TextFlowTextLineFactory to render it.
                // Otherwise the StringTextLineFactory will put
                // all of the lines into a single paragraph
                // and FTE performance will degrade on a large paragraph.
                if (_text.indexOf("\n") != -1 || _text.indexOf("\r") != -1)
                {
                    _textFlow = staticPlainTextImporter.importToFlow(_text);
                    _textContainerManager.setTextFlow(_textFlow);
                }
                else
                {
                    _textContainerManager.setText(_text);
                }                
            }
            else if (textFlowChanged)
            {
                _textContainerManager.setTextFlow(_textFlow);
            }
            else if (contentChanged)
            {
                _textFlow = createTextFlowFromContent(_content);
                _textContainerManager.setTextFlow(_textFlow);
                
                // Content converted to textFlow.
                _content = null;
            }                        
            
            if (textChanged || textFlowChanged || contentChanged)
            {
                lastGeneration = _textFlow ? _textFlow.generation : 0;
                lastContentBoundsGeneration = 0;
                
                // Handle the case where the initial text, textFlow or content 
                // is displayed as a password.
                if (displayAsPassword)
                    displayAsPasswordChanged = true;
                
                // New text so remove any leftover constraints.
                // Used if an item renderer is being recycled.
                widthConstraint = NaN;
                heightConstraint = NaN;
                
                textChanged = false;
                textFlowChanged = false;
                contentChanged = false;
                invalidateSize();
                invalidateDisplayList();
            }
            
            // If displayAsPassword changed, it only applies to the display, 
            // not the underlying text.
            if (displayAsPasswordChanged)
            {
                // If there is any text, convert it to the passwordChar.
                if (displayAsPassword)
                {
                    // Make sure _text is set with the actual text before we
                    // change the displayed text.
                    _text = _textContainerManager.getText("\n");
                    
                    // Paragraph terminators are lost during this substitution.
                    var textToDisplay:String = StringUtil.repeat(
                        passwordChar, _text.length);
                    
                    _textContainerManager.setText(textToDisplay);                            
                }
                else
                {
                    // Text was displayed as password.  Now display as plain text.
                    _textContainerManager.setText(_text);
                }
                
                // When TLF text is set above, TLF's textFlow is recreated so reset
                // our copy of the textFlow and the generation.
                _textFlow = null;
                lastGeneration = 0;
                lastContentBoundsGeneration = 0;
                
                displayAsPasswordChanged = false;
            }
            
            if (clipAndEnableScrollingChanged)
            {
                // The TLF code seems to check for !off.
                _textContainerManager.horizontalScrollPolicy = "auto";
                _textContainerManager.verticalScrollPolicy = "auto";
                
                clipAndEnableScrollingChanged = false;
            }
            
            if (horizontalScrollPositionChanged)
            {
                var oldHorizontalScrollPosition:Number = 
                    _textContainerManager.horizontalScrollPosition;
                
                _textContainerManager.horizontalScrollPosition =
                    _horizontalScrollPosition; 
                
                dispatchPropertyChangeEvent("horizontalScrollPosition",
                    oldHorizontalScrollPosition, _horizontalScrollPosition);
                
                horizontalScrollPositionChanged = false;            
            }
            
            if (verticalScrollPositionChanged)
            {
                var oldVerticalScrollPosition:Number = 
                    _textContainerManager.verticalScrollPosition;
                
                _textContainerManager.verticalScrollPosition =
                    _verticalScrollPosition;
                
                dispatchPropertyChangeEvent("verticalScrollPosition",
                    oldVerticalScrollPosition, _verticalScrollPosition);
                
                verticalScrollPositionChanged = false;            
            }
            
			// Updating the text programatically removes all child TextLine elements
			// before rebuilding the TextFlow, effectively removing all visual elements
			// from the display list. This causes any accessibilityImplementation that
			// was assigned to the component to be removed. The following line restores
			// the accessibilityImplementation if it no longer exists. 
			if (!accessibilityImplementation)
				initializeAccessibility();
        }
        
        /**
         *  @private
         */
        override protected function canSkipMeasurement():Boolean
        {
            autoSize = false;
            return super.canSkipMeasurement();
        }
        
        /**
         *  @private
         */
        override protected function measure():void 
        {
            var bounds:Rectangle;
            
            // If the damage handler is called while measuring text, this means
            // the text lines are damaged and the display needs to be updated. 
            // This flag tells the handler to invalidate just the display list.
            inMeasureMethod = true;
            
            lastMeasuredWidth = measuredWidth;
            lastMeasuredHeight = measuredHeight;
            
            super.measure();
            
            // Styles can be changed in event handlers while in the middle
            // of the component lifecycle.  Make sure they are not stale when
            // composing text.
            updateStylesIfChanged();
            
            // percentWidth and/or percentHeight will come back in as constraints
            // on the remeasure if we're autoSizing.
            
            // TODO:(cframpto) implement blockProgression rl for autoSize
            
            if (isMeasureFixed()) 
            {            
                autoSize = false;
                
                if (typicalText)
                {
                    if (typicalTextChanged)
                    {
                        // If the text has linebreaks (CR, LF, or CF+LF)
                        // create a multi-paragraph TextFlow from it
                        // and use the TextFlowTextLineFactory to render it.
                        // Otherwise the StringTextLineFactory will put
                        // all of the lines into a single paragraph
                        // and FTE performance will degrade on a large paragraph.
                        if (_typicalText.indexOf("\n") != -1 || _typicalText.indexOf("\r") != -1)
                        {
                            _typicalTextFlow = staticPlainTextImporter.importToFlow(_typicalText);
                            // this helped get the factory to generate the same bounds as the
                            // composer
                            _typicalTextFlow.hostFormat = _textContainerManager.hostFormat;
                        }
                        else
                            _typicalTextFlow = null;
                        typicalTextChanged = false;
                    }
                    // if multiline...
                    if (_typicalTextFlow)
                    {
                        // create the factory if needed
                        if (!staticTextFlowFactory)
                        {
                            staticTextFlowFactory = new TextFlowTextLineFactory();
                            // set bounds to natural bounds
                            staticTextFlowFactory.compositionBounds = unbounded;
                        }
                        if (_typicalTextFlow.flowComposer)
                        {
                            _typicalTextFlow.flowComposer.swfContext = 
                                ISWFContext(embeddedFontContext);
                        }                       
                        staticTextFlowFactory.swfContext = ISWFContext(embeddedFontContext);
                        // create the textlines
                        staticTextFlowFactory.createTextLines(tossTextLine, _typicalTextFlow);
                        // get the bounds
                        bounds = staticTextFlowFactory.getContentBounds();
                    }
                    else // single line
                    {
                        // create the factory if needed
                        if (!staticStringFactory)
                        {
                            staticStringFactory = new StringTextLineFactory();
                            // set bounds to natural bounds
                            staticStringFactory.compositionBounds = unbounded;
                        }
                        // create the textlines
                        staticStringFactory.text = _typicalText;
                        staticStringFactory.textFlowFormat = _textContainerManager.hostFormat;
                        staticStringFactory.swfContext = ISWFContext(embeddedFontContext);
                        staticStringFactory.createTextLines(tossTextLine);
                        // get the bounds
                        bounds = staticStringFactory.getContentBounds();
                    }           
                    
                    measuredWidth = Math.ceil(bounds.width);
                    measuredHeight = Math.ceil(bounds.height);                  
                }
                else
                {
                    // Go large.  For performance reasons, want to avoid a scrollRect 
                    // whenever possible in drawBackgroundAndSetScrollRect().  This is
                    // particularly true for 1 line TextInput components.
                    measuredWidth = !isNaN(explicitWidth) ? explicitWidth :
                        Math.ceil(calculateWidthInChars());
                    measuredHeight = !isNaN(explicitHeight) ? explicitHeight :
                        Math.ceil(calculateHeightInLines());
                }
            }
            else
            {
                var composeWidth:Number;
                var composeHeight:Number;
                
                // If we're here, then at one or both of the width and height can
                // grow to fit the text.  It is important to figure out whether
                // or not autoSize should be allowed to continue.  If in
                // updateDisplayList(), autoSize is true, then the 
                // compositionHeight is NaN to allow the text to grow.          
                autoSize = true;
                
                if (!isNaN(widthConstraint) || !isNaN(explicitWidth) || 
                    !isNaN(widthInChars))
                {
                    // width specified but no height
                    // if no text, start at one line high and grow
                    
                    if (!isNaN(widthConstraint))
                        composeWidth = widthConstraint;
                    else if (!isNaN(explicitWidth))                    
                        composeWidth = explicitWidth;
                    else
                        composeWidth = Math.ceil(calculateWidthInChars());
                    
                    // The composeWidth may be adjusted for minWidth/maxWidth
                    // except if we're using the explicitWidth.  
                    bounds = measureTextSize(composeWidth);
                    
                    // The measured width shouldn’t be pinned to the composeWidth if 
                    // the composeWidth is set by %, otherwise the measuredWidth 
                    // can keep stretching
                    if (!isNaN(explicitWidth) || !isNaN(widthInChars))
                        measuredWidth = textContainerManager.compositionWidth;
                    else
                        measuredWidth = Math.ceil(bounds.width); 
                    measuredHeight = Math.ceil(bounds.bottom);
                }
                else if (!isNaN(heightConstraint) || !isNaN(explicitHeight) || 
                    !isNaN(_heightInLines))
                {
                    // if no text, 1 char wide with specified height and grow
                    
                    if (!isNaN(heightConstraint))
                        composeHeight = heightConstraint;
                    else if (!isNaN(explicitHeight))
                        composeHeight = explicitHeight;
                    else
                        composeHeight = calculateHeightInLines();
                    
                    // The composeWidth may be adjusted for minWidth/maxWidth.
                    bounds = measureTextSize(NaN, composeHeight);
                    
                    measuredWidth = Math.ceil(bounds.right);               
                    measuredHeight = composeHeight;

                    // Have we already hit the limit with the existing text?  If we
                    // are beyond the composeHeight we can assume we've maxed out on
                    // the compose width as well (or the composeHeight isn't
                    // large enough for even one line of text).
                    if (bounds.bottom > composeHeight)
                        autoSize = false;
                }
                else
                {
                    // The composeWidth may be adjusted for minWidth/maxWidth.
                    bounds = measureTextSize(NaN);
                    
                    measuredWidth = Math.ceil(bounds.right);
                    measuredHeight = Math.ceil(bounds.bottom);
                }
                
                // Clamp the height, except if we're using the explicitHeight.
                if (isNaN(explicitHeight))
                {            
                    if (!isNaN(explicitMinHeight) && measuredHeight < explicitMinHeight)
                        measuredHeight = explicitMinHeight;
                    
                    // Reached max height so can't grow anymore.
                    if (!isNaN(explicitMaxHeight) && measuredHeight > explicitMaxHeight)
                    {
                        measuredHeight = explicitMaxHeight;
                        autoSize = false;
                    }
                }
                
                // Make sure we weren't previously scrolled. 
                if (autoSize && getStyle("lineBreak") == "toFit")
                {
                    _textContainerManager.horizontalScrollPosition = 0;
                    _textContainerManager.verticalScrollPosition = 0;                
                }               
                
                // If we remeasured, we composed and cleared the display.  We need to update the 
                // display if the size didn't change, since validateSize will not do it for us.  
                // This code path can be used by itemRenderer's since setLayoutBounds(), which is
                // where the constraints are set, is not always called.
                if (remeasuringText && 
                    lastMeasuredWidth == measuredWidth && lastMeasuredHeight == measuredHeight)
                {
                    _textContainerManager.updateContainer();
                }
            }
            
            remeasuringText = false;
            inMeasureMethod = false;
            
            //trace("measure", measuredWidth, measuredHeight, "autoSize", autoSize);
        }
        
        /**
         *  @private
         */
        override protected function updateDisplayList(unscaledWidth:Number,
                                                      unscaledHeight:Number):void 
        {
            inUpdateDLMethod = true;
            
            //trace("updateDisplayList", unscaledWidth, unscaledHeight, "autoSize", autoSize);
            
            // Styles can be changed in event handlers while in the middle
            // of the component lifecycle.  Make sure they are not stale when
            // composing text.
            updateStylesIfChanged();
            
            // Check if the auto-size text is constrained in some way and needs
            // to be remeasured.  If one of the dimension changes, the text may
            // compose differently and have a different size which the layout 
            // manager needs to know.
            // Don't exit early if we have changed size.  We may have to run 
            // drawBackgroundAndSetScrollRect 
            if (autoSize && 
                lastUnscaledHeight == unscaledHeight && lastUnscaledWidth == unscaledWidth && 
                remeasureText(unscaledWidth, unscaledHeight))
            {
                inUpdateDLMethod = false;
                return;
            }
            
            super.updateDisplayList(unscaledWidth, unscaledHeight);
            
            // If we're autoSizing we're telling the layout manager one set of
            // values and TLF another set of values so there is room for the text
            // to grow.
            
            // TODO:(cframpto) compositionWidth can be NaN when 
            // autoSize for blockProgression=="rl" is implemented
            if (!autoSize)
            {
                _textContainerManager.compositionWidth = unscaledWidth;
                _textContainerManager.compositionHeight = unscaledHeight;
            }
            
            // If scrolling, always compose with the composer so we get consistent
            // measurements.  The factory and the composer produce slightly 
            // different results which can confuse the scroller.  If there isn't a 
            // composer, this calls updateContainer so do it here now that the 
            // composition sizes are set so the results can be used.
            if (clipAndEnableScrolling && 
                _textContainerManager.composeState != 
                TextContainerManager.COMPOSE_COMPOSER)
            {
                _textContainerManager.convertToTextFlowWithComposer();
            }
            
            // The EditManager calls updateAllControllers() directly when there
            // is interactive input such as typing or cut/paste. This bypasses
            // our update cycle which matters if we are auto-sizing.
            // compositionWidth/Height are NaN and the background is drawn with
            // the old width/height because measureTextSize hasn't had a
            // chance to update the layout manager yet.  Once the layoutManager
            // has been updated, the compositionWidth/Height are still NaN
            // so TLF doesn't think there is anything to compose.  The text 
            // hasn't changed shape, but the background has.
            if (autoSize && !isNaN(lastUnscaledWidth) &&
                (lastUnscaledWidth != unscaledWidth || 
                    lastUnscaledHeight != unscaledHeight))
            {
                if (_textContainerManager.composeState == TextContainerManager.COMPOSE_COMPOSER)
                     _textContainerManager.getTextFlow().flowComposer.getControllerAt(0).shapesInvalid = true;
                else if (!_textContainerManager.isDamaged())
                    _textContainerManager.drawBackgroundAndSetScrollRect(0,0);
            }
               
            _textContainerManager.updateContainer();
            
            lastUnscaledWidth = unscaledWidth;
            lastUnscaledHeight = unscaledHeight;
            
            inUpdateDLMethod = false;
         }
        
        /**
         *  @private
         *  This is called by the layout manager the first time this
         *  component is measured, or later if its size changes. This
         *  is not always called before updateDisplayList().  For example,
         *  for recycled item renderers this is not called if the measured
         *  size doesn't change.
         * 
         *  width and height are NaN unless there are constraints on them.
         */
        override public function setLayoutBoundsSize(
                                    width:Number, height:Number,
                                    postLayoutTransform:Boolean = true):void
        {
            //trace("setLayoutBoundsSize", width, height);
            
            // Save these so when we are auto-sizing we know which dimensions
            // are constrained.  Without this it is not possible to differentiate 
            // between a measured width/height that is the same as the
            // constrained width/height to know whether that dimension can
            // be sized or must be fixed at the constrained value.                
            heightConstraint = height;

            super.setLayoutBoundsSize(width, height, postLayoutTransform);

            // Did we already constrain the width?
            if (widthConstraint == width)
                return;
            
            // No reflow for explicit lineBreak
            if (getStyle("lineBreak") == "explicit")
                return;
            
            // If we don't measure.
            // Call super so we don't call the override
            // and set autoSize to false;
            if (super.canSkipMeasurement())
                return;
            
            if (!isNaN(explicitHeight))
                return;
            
            // We support reflow only in the case of constrained width and
            // unconstrained height. Note that we compare with measuredWidth,
            // as for example the RichEditableText can be
            // constrained by the layout with "left" and "right", but the
            // container width itself may not be constrained and it would depend
            // on the element's measuredWidth.
            var constrainedWidth:Boolean = !isNaN(width) && (width != measuredWidth) && (width != 0); 
            if (!constrainedWidth)
                return;
            
            // We support reflow only when we don't have a transform.
            // We could add support for scale, but not skew or rotation.
            if (postLayoutTransform && hasComplexLayoutMatrix)
                return;
            
            widthConstraint = width;

            invalidateSize();
            
        }
        
        /**
         *  @inheritDoc
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        override public function stylesInitialized():void
        {
            super.stylesInitialized();
            
            ascent = NaN;
            descent = NaN;
            
            hostFormatChanged = true;
        }
        
        /**
         *  @inheritDoc
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        override public function styleChanged(styleProp:String):void
        {
            super.styleChanged(styleProp);
            
            // If null or "styleName" is passed it indicates that
            // multiple styles may have changed.  Otherwise it is a single style
            // so mark whether it is the selectionFormat that changed or the
            // hostFormat that changed.
            if (styleProp == null || styleProp == "styleName")
            {
                hostFormatChanged = true;
                selectionFormatsChanged = true;
                ascent = NaN;
                descent = NaN;
            }
            else if (styleProp == "focusedTextSelectionColor" || 
                styleProp == "unfocusedTextSelectionColor" ||
                styleProp == "inactiveTextSelectionColor")
            {
                selectionFormatsChanged = true;
            }
            else
            {
                hostFormatChanged = true;
                
                if (styleProp.indexOf("font") == 0 || styleProp == "cffHinting")
                {
                    // Regenerate font swfContext and metrics as well.
                    ascent = NaN;
                    descent = NaN;
                }
            }
            
            // Need to create new format(s).
            invalidateProperties();
        }
        
        /**
         *  @private
         */
        override public function setFocus():void
        {
            // We are about to set focus on this component.  If it is due to
            // a programmatic focus change we have to programatically do what the
            // mouseOverHandler and the mouseDownHandler do so that the user can 
            // type in this component without using the mouse first.  We need to
            // put a textFlow with a composer in place.
            if (editingMode != EditingMode.READ_ONLY &&
                _textContainerManager.composeState != 
                TextContainerManager.COMPOSE_COMPOSER)   
            {
                _textContainerManager.beginInteraction();
                _textContainerManager.endInteraction();
            }
            
            super.setFocus();
        }
        
        /**
         *  @private
         */
        override public function drawFocus(isFocused:Boolean):void
        {
            if (isFocused)
            {
                // For some composite components, the focused object may not
                // be "this". If so, we don't want to draw the focus.  This
                // replaces the parentDrawsFocus variable used in halo.
                var fm:IFocusManager = focusManager;
                if (fm && fm.getFocus() != this)
                    return;
            }
            
            super.drawFocus(isFocused);
        }
        
        //--------------------------------------------------------------------------
        //
        //  Methods: IViewport
        //
        //--------------------------------------------------------------------------
        
        //----------------------------------
        //  horizontalScrollPositionDelta
        //----------------------------------
        
        /**
         *  @inheritDoc
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function getHorizontalScrollPositionDelta(navigationUnit:uint):Number
        {
            var scrollR:Rectangle = scrollRect;
            if (!scrollR)
                return 0;
            
            // maxDelta is the horizontalScrollPosition delta required 
            // to scroll to the RIGHT and minDelta scrolls to LEFT. 
            var maxDelta:Number = contentWidth - scrollR.right;
            var minDelta:Number = -scrollR.left;
            
            // Scroll by a "character" which is 1 em (matches widthInChars()).
            var em:Number = getStyle("fontSize");
            
            switch (navigationUnit)
            {
                case NavigationUnit.LEFT:
                    return (scrollR.left <= 0) ? 0 : Math.max(minDelta, -em);
                    
                case NavigationUnit.RIGHT:
                    return (scrollR.right >= contentWidth) ? 0 : Math.min(maxDelta, em);
                    
                case NavigationUnit.PAGE_LEFT:
                    return Math.max(minDelta, -scrollR.width);
                    
                case NavigationUnit.PAGE_RIGHT:
                    return Math.min(maxDelta, scrollR.width);
                    
                case NavigationUnit.HOME: 
                    return minDelta;
                    
                case NavigationUnit.END: 
                    return maxDelta;
                    
                default:
                    return 0;
            }
        }
        
        //----------------------------------
        //  verticalScrollPositionDelta
        //----------------------------------
        
        /**
         *  @inheritDoc
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function getVerticalScrollPositionDelta(navigationUnit:uint):Number
        {
            var scrollR:Rectangle = scrollRect;
            if (!scrollR)
                return 0;
            
            // maxDelta is the horizontalScrollPosition delta required 
            // to scroll to the END and minDelta scrolls to HOME. 
            var maxDelta:Number = contentHeight - scrollR.bottom;
            var minDelta:Number = -scrollR.top;
            
            switch (navigationUnit)
            {
                case NavigationUnit.UP:
                    return _textContainerManager.getScrollDelta(-1);
                    
                case NavigationUnit.DOWN:
                    return _textContainerManager.getScrollDelta(1);
                    
                case NavigationUnit.PAGE_UP:
                    return Math.max(minDelta, -scrollR.height);
                    
                case NavigationUnit.PAGE_DOWN:
                    return Math.min(maxDelta, scrollR.height);
                    
                case NavigationUnit.HOME:
                    return minDelta;
                    
                case NavigationUnit.END:
                    return maxDelta;
                    
                default:
                    return 0;
            }       
        }
        
        //--------------------------------------------------------------------------
        //
        //  Methods
        //
        //--------------------------------------------------------------------------
        
        /**
         *  Inserts the specified text into the RichEditableText
         *  as if you had typed it.
         *
         *  <p>If a range was selected, the new text replaces the selected text.
         *  If there was an insertion point, the new text is inserted there.</p>
         *
         *  <p>An insertion point is then set after the new text.
         *  If necessary, the text will scroll to ensure
         *  that the insertion point is visible.</p>
         *
         *  @param text The text to be inserted.
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function insertText(text:String):void
        {      
            handleInsertText(text);  
        }
        
        /**
         *  Appends the specified text to the end of the RichEditableText,
         *  as if you had clicked at the end and typed.
         *
         *  <p>An insertion point is then set after the new text.
         *  If necessary, the text will scroll to ensure
         *  that the insertion point is visible.</p>
         *
         *  @param text The text to be appended.
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function appendText(text:String):void
        {
            handleInsertText(text, true);
        }
        
        /**
         *  @copy flashx.textLayout.container.ContainerController#scrollToRange() 
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function scrollToRange(anchorPosition:int, activePosition:int):void
        {
            // Make sure the properties are commited since the text could change.
            validateProperties();
            
            // Scrolls so that the text position is visible in the container. 
            textContainerManager.scrollToRange(anchorPosition, activePosition);       
        }
        
        /**
         *  Selects a specified range of characters.
         *
         *  <p>If either position is negative, it will deselect the text range.</p>
         *
         *  @param anchorPosition The character position specifying the end
         *  of the selection that stays fixed when the selection is extended.
         *
         *  @param activePosition The character position specifying the end
         *  of the selection that moves when the selection is extended.
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function selectRange(anchorPosition:int,
                                    activePosition:int):void
        {
            // Make sure the properties are commited since the text could change.
            validateProperties();
            
            if (editingMode == EditingMode.READ_ONLY)
            {
                var selectionState:SelectionState =
                    new SelectionState(textFlow, anchorPosition, activePosition);
                
                var selectionEvent:SelectionEvent = 
                    new SelectionEvent(SelectionEvent.SELECTION_CHANGE, 
                        false, false, selectionState);
                
                textContainerManager_selectionChangeHandler(selectionEvent);            
            }
            else
            {
                var im:ISelectionManager = _textContainerManager.beginInteraction();
                
                im.selectRange(anchorPosition, activePosition);        
                
                // Refresh the selection.  This does not cause a damage event.
                im.refreshSelection();
                
                _textContainerManager.endInteraction();
            }
            
            // Remember if the current selection is a range which was set
            // programatically.
            hasProgrammaticSelectionRange = (anchorPosition != activePosition);
        }
        
        /**
         *  Selects all of the text. This does not include the final paragraph
         *  terminator.
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function selectAll():void
        {
            selectRange(0, int.MAX_VALUE);
        }
       
        /**
         *  Returns a TextLayoutFormat object specifying the computed formats
         *  for the specified range of characters.
         *
         *  <p>If a format is not consistently set across the entire range,
         *  its value will be <code>undefined</code>.</p>
         *
         *  <p>You can specify a Vector of Strings containing the names of the
         *  formats that you care about; if you don't, all formats
         *  will be computed.</p>
         *  
         *  <p>If you don't specify a range, the selected range is used.</p>
         *
         *  @param requestedFormats A Vector of Strings specifying the names
         *  of the requested formats, or <code>null</code> to request all formats.
         *
         *  @param anchorPosition A character position specifying
         *  the fixed end of the selection.
         *
         *  @param activePosition A character position specifying
         *   the movable end of the selection.
         *
         *  @return A TextLayoutFormat object.
         *  
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function getFormatOfRange(requestedFormats:Vector.<String> = null,
                                         anchorPosition:int = -1,
                                         activePosition:int = -1):TextLayoutFormat
        {
            var format:TextLayoutFormat = new TextLayoutFormat();
            
            // Make sure all properties are committed.
            validateProperties();
            
            // This internal TLF object maps the names of format properties
            // to Property instances.
            // Each Property instance has a category property which tells
            // whether it is container-, paragraph-, or character-level.
            var description:Object = TextLayoutFormat.description;
            
            var p:String;
            var category:String;
            
            // Based on which formats have been requested, determine which
            // of the getCommonXXXFormat() methods we need to call.
            
            var needContainerFormat:Boolean = false;
            var needParagraphFormat:Boolean = false;
            var needCharacterFormat:Boolean = false;
            
            if (!requestedFormats)
            {
                requestedFormats = new Vector.<String>;
                for (p in description)
                    requestedFormats.push(p);
                
                needContainerFormat = true;
                needParagraphFormat = true;
                needCharacterFormat = true;
            }
            else
            {
                for each (p in requestedFormats)
                {
                    if (!(p in description))
                        continue;
                    
                    category = description[p].category;
                    
                    if (category == Category.CONTAINER)
                        needContainerFormat = true;
                    else if (category == Category.PARAGRAPH)
                        needParagraphFormat = true;
                    else if (category == Category.CHARACTER)
                        needCharacterFormat = true;
                }
            }
            
            // Get the common formats.
            
            var containerFormat:ITextLayoutFormat;
            var paragraphFormat:ITextLayoutFormat;
            var characterFormat:ITextLayoutFormat;
            
            if (anchorPosition == -1 && activePosition == -1)
            {
                anchorPosition = _selectionAnchorPosition;
                activePosition = _selectionActivePosition;
            }
            
            if (needContainerFormat)
            {
                containerFormat = 
                    _textContainerManager.getCommonContainerFormat();
            }
            
            if (needParagraphFormat)
            {
                paragraphFormat = 
                    _textContainerManager.getCommonParagraphFormat(
                        anchorPosition, activePosition);
            }
            
            if (needCharacterFormat)
            {
                characterFormat = 
                    _textContainerManager.getCommonCharacterFormat(
                        anchorPosition, activePosition);
            }
            
            // Extract the requested formats to return.
            for each (p in requestedFormats)
            {
                if (!(p in description))
                    continue;
                
                category = description[p].category;
                
                if (category == Category.CONTAINER && containerFormat)
                    format[p] = containerFormat[p];
                else if (category == Category.PARAGRAPH && paragraphFormat)
                    format[p] = paragraphFormat[p];
                else if (category == Category.CHARACTER && characterFormat)
                    format[p] = characterFormat[p];
            }
            
            return format;
        }
        
        /**
         *  Applies the specified formats to each element in the specified
         *  range that correspond to the given format.  
         *  It applies the character formats to the text in the specified range
         *  (no change is made if the specified range is a single point). 
         *  It applies the paragraph formats to any paragraphs at least 
         *  partially within the range (or a single paragraph if the range is a 
         *  single point).
         *  It applies the container formats to the container.
         * 
         *  <p>The supported formats are those in TextLayoutFormat.
         *  A value of <code>undefined</code> does not get applied.
         *  If you don't specify a range, the selected range is used.</p>
         *
         *  <p>The following example sets the <code>fontSize</code> and <code>color</code> of the selection:
         *  <pre>
         *  var textLayoutFormat:TextLayoutFormat = new TextLayoutFormat();
         *  textLayoutFormat.fontSize = 12;
         *  textLayoutFormat.color = 0xFF0000;
         *  myRET.setFormatOfRange(textLayoutFormat);
         *  </pre>
         *  </p>
         *  
         *  <p>If you use the results of <code>getFormatOfRange()</code> to
         *  specify the <code>format</code>, note that every format in the
         *  <code>TextLayoutFormat</code> has a
         *  computed value, which will be applied to each element that 
         *  corresponds to the given format.</p>
         * 
         *  <p>If you would like to specify a format to be applied to all the text
         *  it would be better to use <code>setStyle(format, value)</code>
         *  on the component itself.</p>
         * 
         *  <p>The following example sets the <code>fontSize</code> and <code>color</code> of all the text:
         *  <pre>
         *  myRET.setStyle("fontSize", 12);
         *  myRET.setStyle("color", 0xFF0000);
         *  </pre>
         *  </p>
         * 
         *  @param format The TextLayoutFormat to apply to the selection.
         * 
         *  @param anchorPosition A character position, relative to the beginning of the 
         *  text String, specifying the end of the selection that stays fixed when the 
         *  selection is extended with the arrow keys.
         * 
         *  @param activePosition A character position, relative to the beginning of the 
         *  text String, specifying the end of the selection that moves when the 
         *  selection is extended with the arrow keys. 
         * 
         *  @langversion 3.0
         *  @playerversion Flash 10
         *  @playerversion AIR 1.5
         *  @productversion Flex 4
         */
        public function setFormatOfRange(format:TextLayoutFormat,
                                         anchorPosition:int=-1,
                                         activePosition:int=-1):void
        {
            // Make sure all properties are committed.  The damage handler for the 
            // applyTextFormat op will cause the remeasure and display update.
            validateProperties();
            
            // Assign each specified attribute to one of three format objects,
            // depending on whether it is container-, paragraph-,
            // or character-level. Note that these can remain null.
            var containerFormat:TextLayoutFormat;
            var paragraphFormat:TextLayoutFormat;
            var characterFormat:TextLayoutFormat;
            
            // This internal TLF object maps the names of format properties
            // to Property instances.
            // Each Property instance has a category property which tells
            // whether it is container-, paragraph-, or character-level.
            var description:Object = TextLayoutFormat.description;
            
            for (var p:String in description) 
            {
                if (format[p] === undefined)
                    continue;
                
                var category:String = description[p].category;
                
                if (category == Category.CONTAINER)
                {
                    if (!containerFormat)
                        containerFormat =  new TextLayoutFormat();
                    containerFormat[p] = format[p];
                }
                else if (category == Category.PARAGRAPH)
                {
                    if (!paragraphFormat)
                        paragraphFormat =  new TextLayoutFormat();
                    paragraphFormat[p] = format[p];
                }
                else if (category == Category.CHARACTER)
                {
                    if (!characterFormat)
                        characterFormat =  new TextLayoutFormat();
                    characterFormat[p] = format[p];
                }
            }
            
            // If the selection isn't specified, use the current one.
            if (anchorPosition == -1 && activePosition == -1)
            {
                anchorPosition = _selectionAnchorPosition;
                activePosition = _selectionActivePosition;
            }
            
            // Apply the three format objects to the current selection if
            // selectionState is null, else the specified selection.
            _textContainerManager.applyFormatOperation(
                characterFormat, paragraphFormat, containerFormat, 
                anchorPosition, activePosition);
        }
        
        /**
         *  @private
         */
        mx_internal function createTextContainerManager():RichEditableTextContainerManager
        {
            return new RichEditableTextContainerManager(this);
        }
        
        /**
         *  @private
         */
        private function updateStylesIfChanged():void
        {
            
            if (hostFormatChanged)
            {
                // Side-effect is it marks the text as damaged.
                _textContainerManager.hostFormat = new CSSTextLayoutFormat(this);
                
                hostFormatChanged = false;
            }
            
            if (isNaN(ascent) || isNaN(descent))
            {
                // If the CSS styles for this component specify an embedded font,
                // embeddedFontContext will be set to the module factory that
                // should create TextLines (since they must be created in the
                // SWF where the embedded font is.)
                // Otherwise, this will be null.
                embeddedFontContext = getEmbeddedFontContext();
                
                _textContainerManager.swfContext =
                    ISWFContext(embeddedFontContext);                       
                
                // Note: CSSTextLayoutFormat has special processing
                // for the fontLookup style. If it is "auto",
                // the fontLookup format is set to either
                // "device" or "embedded" depending on whether
                // embeddedFontContext is null or non-null.
                
                // Recalcuate the ascent and descent.
                calculateFontMetrics();    
            }
            
            if (selectionFormatsChanged)
            {
                _textContainerManager.invalidateSelectionFormats();
                
                selectionFormatsChanged = false;
            }
        }
        
        /**
         *  @private
         *  Uses the component's CSS styles to determine the module factory
         *  that should creates its TextLines.
         */
        private function getEmbeddedFontContext():IFlexModuleFactory
        {
            var fontContext:IFlexModuleFactory;
            
            var fontLookup:String = getStyle("fontLookup");
            if (fontLookup != FontLookup.DEVICE)
            {
                var font:String = getStyle("fontFamily");
                var bold:Boolean = getStyle("fontWeight") == "bold";
                var italic:Boolean = getStyle("fontStyle") == "italic";
                
                fontContext = getFontContext(font, bold, italic, true);
            }
            
            return fontContext;
        }
        
        /**
         *  @private
         *  Return true if there is a width and height to use for the measure.
         */
        mx_internal function isMeasureFixed():Boolean
        {
            // This can be called from RET EditManager when hostFormat is null 
            // because a style changed and commitProperties hasn't run yet.
            if (!_textContainerManager.hostFormat)
                updateStylesIfChanged();            
            
            if (_textContainerManager.hostFormat.blockProgression != 
                BlockProgression.TB)
            {
                return true;
            }

            if (typicalText != null)
                return true;
            
            // Is there some sort of width and some sort of height?
            return  (!isNaN(explicitWidth) || !isNaN(_widthInChars) ||
                !isNaN(widthConstraint)) &&
                    (!isNaN(explicitHeight) || !isNaN(_heightInLines) ||
                        !isNaN(heightConstraint));
        }
        
        /**
         *  @private
         *  Returns the bounds of the measured text.  The initial composeWidth may
         *  be adjusted for minWidth or maxWidth.  The value used for the compose
         *  is in _textContainerManager.compositionWidth.
         */
        private function measureTextSize(composeWidth:Number, 
                                         composeHeight:Number=NaN):Rectangle
        {   
            // Adjust for explicit min/maxWidth so the measurement is accurate.
            // If no explicitWidth or widthInChars
            if (isNaN(explicitWidth) && isNaN(widthInChars))
            {
                // then if there is an explicit minWidth and
                // a specified composeWidth and the composeWidth
                // is less than the minWidth, use the minWidth
                if (!isNaN(explicitMinWidth) &&
                    !isNaN(composeWidth) && composeWidth < minWidth)
                {
                    composeWidth = minWidth;
                }
                // if composeWidth is NaN, just compose and see what happens
                // and fix up the measurements afterwards.  See final check
                // at the end of the method
                
                // On the other hand, if there is an explicit maxWidth and
                // no specified composeWidth then use maxWidth, 
                // or if there is a a specified composeWidth 
                // and the composeWidth is greater than maxWidth, use the maxWidth.
                if (!isNaN(explicitMaxWidth) &&
                    isNaN(composeWidth) || 
                    composeWidth > maxWidth)
                {
                    composeWidth = maxWidth;
                }
            }
            
            // If the width is NaN it can grow up to TextLine.MAX_LINE_WIDTH wide.
            // If the height is NaN it can grow to allow all the text to fit.
            _textContainerManager.compositionWidth = composeWidth;
            _textContainerManager.compositionHeight = composeHeight;
            
            // If scrolling, always compose with the composer so we get consistent
            // measurements.  The factory and the composer produce slightly 
            // different results which can confuse the scroller.  If there isn't a 
            // composer, this calls updateContainer so do it here now that the 
            // composition sizes are set so the results can be used.
            if (clipAndEnableScrolling && 
                _textContainerManager.composeState != 
                TextContainerManager.COMPOSE_COMPOSER)
            {
                _textContainerManager.convertToTextFlowWithComposer();
            }
                        
            // Compose only.  The display should not be updated.
            _textContainerManager.compose();
            
            // Adjust width and height for text alignment.
            var bounds:Rectangle = _textContainerManager.getContentBounds();
            
            // If it's an empty text flow, there is one line with one
            // character so the height is good for the line but we
            // need to give it some width other than optional padding.
            
            if (_textContainerManager.getText("\n").length == 0) 
            {
                // Empty text flow.  One Em wide so there
                // is a place to put the insertion cursor.
                bounds.width = bounds.width + getStyle("fontSize");
            }
            
            //trace("measureTextSize", composeWidth, "->", bounds.width, composeHeight, "->", bounds.height);
            
            // one final check:  If there is no explicitWidth...
            if (isNaN(explicitWidth) && isNaN(widthInChars))
            {
                // but there is a minWidth, and no specified composeWidth
                // and we measure out to be less than the minWidth
                // report the minWidth anyway.
                if (!isNaN(explicitMinWidth) &&
                    isNaN(composeWidth) &&
                    bounds.width < minWidth)
                {
                    bounds.width = minWidth;
                }
            }
            return bounds;
        }
        
        
        /**
         *  @private
         *  If auto-sizing text, it may need to be remeasured if it is 
         *  constrained in one dimension by the layout manager.  If it is
         *  constrained in both dimensions there is no need to remeasure.  
         *  Changing one dimension may change the size of the measured text 
         *  and the layout manager needs to know this.
         */
        private function remeasureText(width:Number, height:Number):Boolean
        {   
            // Neither dimensions changed.  If auto-sizing we're still auto-sizing.
            if (width == measuredWidth && height == measuredHeight)
                return false;
            
            // Either constraints are preventing auto-sizing or we need to
            // remeasure which will reset autoSize.
            autoSize = false;
            
            // If no width or height, there is nothing to remeasure since 
            // there is no room for text.
            if (width == 0 || height == 0) 
                return false;
            
            // If we're using typical text, no need to remeasure.
            if (typicalText != null)
                return false;
            
            // No reflow for explicit lineBreak
            if (_textContainerManager.hostFormat.lineBreak == "explicit")
                return false;
            
            if (!isNaN(widthConstraint))
            {
                // Do we have a constrained width and an explicit height?
                // If so, the sizes are set so no need to remeasure now.
                if (!isNaN(explicitHeight) || !isNaN(_heightInLines) ||
                    !isNaN(heightConstraint))
                {
                    return false;
                }
            } 
            
            if (!isNaN(heightConstraint))
            {        
                // Do we have a constrained height and an explicit width?
                // If so, the sizes are set so no need to remeasure now.
                if (!isNaN(explicitWidth) || !isNaN(_widthInChars))
                    return false;
            }                       
            
            // Width or height is different than what was measured.  Since we're
            // auto-sizing, need to remeasure, so the layout manager leaves the
            // correct amount of space for the component.
            invalidateSize();
            
            // Need to make sure the container is updated after the text is re-composed 
            // to measure it.
            remeasuringText = true;
            
            return true;            
        }
        
        /**
         *  @private
         *  This method is called when anything affecting the
         *  default font, size, weight, etc. changes.
         *  It calculates the 'ascent', 'descent', and
         *  instance variables, which are used in measure().
         */
        private function calculateFontMetrics():void
        {
            var fontDescription:FontDescription = new FontDescription();
            
            var s:String;
            
            s = getStyle("cffHinting");
            if (s != null)
                fontDescription.cffHinting = s;
            
            s = getStyle("fontFamily");
            if (s != null)
                fontDescription.fontName = s;
            
            s = getStyle("fontLookup");
            if (s != null)
            {
                // FTE understands only "device" and "embeddedCFF"
                // for fontLookup. But Flex allows this style to be
                // set to "auto", in which case we automatically
                // determine it based on whether the CSS styles
                // specify an embedded font.
                if (s != "device")
                {
                    s = TextUtil.resolveFontLookup(
                        _textContainerManager.swfContext, 
                        _textContainerManager.hostFormat);
                }
                fontDescription.fontLookup = s;
            }
            
            s = getStyle("fontStyle");
            if (s != null)
                fontDescription.fontPosture = s;
            
            s = getStyle("fontWeight");
            if (s != null)
                fontDescription.fontWeight = s;
            
            var elementFormat:ElementFormat = new ElementFormat();
            elementFormat.fontDescription = fontDescription;
            elementFormat.fontSize = getStyle("fontSize");
            
            var textElement:TextElement = new TextElement();
            textElement.elementFormat = elementFormat;
            textElement.text = "M";
            
            var textBlock:TextBlock = new TextBlock();
            textBlock.content = textElement;
            
            var swfContext:ISWFContext = ISWFContext(embeddedFontContext);
            
            var textLine:TextLine;
            if (swfContext)
            {
                textLine = swfContext.callInContext(
                    textBlock.createTextLine, textBlock,
                    [ null, 1000 ]);
            }
            else
                textLine = textBlock.createTextLine(null, 1000);
            
            ascent = textLine.ascent;
            descent = textLine.descent;
        }
        
        /**
         *  @private
         */
        private function calculateWidthInChars():Number
        {
            var em:Number = getStyle("fontSize");
            
            var effectiveWidthInChars:int;
            
            // If both height and width are NaN use 10 chars.  Otherwise if only 
            // width is NaN, use 1.                
            if (isNaN(_widthInChars))
                effectiveWidthInChars = isNaN(_heightInLines) ? 10 : 1;
            else
                effectiveWidthInChars = _widthInChars;
            
            // Without the explicit casts, if padding values are non-zero, the
            // returned width is a very large number.
            return getStyle("paddingLeft") +
                effectiveWidthInChars * em +
                getStyle("paddingRight");
        }
        
        /**
         *  @private
         *  Calculates the height needed for heightInLines lines using the default
         *  font.
         */
        private function calculateHeightInLines():Number
        {
            var height:Number = getStyle("paddingTop") + getStyle("paddingBottom");
            
            if (_heightInLines == 0)
                return height;
            
            var effectiveHeightInLines:int;
            
            // If both height and width are NaN use 10 lines.  Otherwise if 
            // only height is NaN, use 1.
            if (isNaN(_heightInLines))
                effectiveHeightInLines = isNaN(_widthInChars) ? 10 : 1;   
            else
                effectiveHeightInLines = _heightInLines;
            
            // Position of the baseline of first line in the container.
            value = getStyle("firstBaselineOffset");
            if (value == lineHeight)
                height += lineHeight;
            else if (value is Number)
                height += Number(value);
            else
                height += ascent;
            
            // Distance from baseline to baseline.  Can be +/- number or 
            // or +/- percent (in form "120%") or "undefined".  
            if (effectiveHeightInLines > 1)
            {
                var value:Object = getStyle("lineHeight");     
                var lineHeight:Number =
                    RichEditableText.getNumberOrPercentOf(value, getStyle("fontSize"));
                
                // Default is 120%
                if (isNaN(lineHeight))
                    lineHeight = getStyle("fontSize") * 1.2;
                
                height += (effectiveHeightInLines - 1) * lineHeight;
            }            
            
            // Add in descent of last line.
            height += descent;              
            
            return height;
        }
        
        /**
         *  @private
         */
        private function createTextFlowFromContent(content:Object):TextFlow
        {
            var textFlow:TextFlow ;
            
            if (content is TextFlow)
            {
                textFlow = content as TextFlow;
            }
            else if (content is Array)
            {
                textFlow = new TextFlow();
                textFlow.whiteSpaceCollapse = getStyle("whiteSpaceCollapse");
                textFlow.mxmlChildren = content as Array;
                textFlow.whiteSpaceCollapse = undefined;
            }
            else
            {
                textFlow = new TextFlow();
                textFlow.whiteSpaceCollapse = getStyle("whiteSpaceCollapse");
                textFlow.mxmlChildren = [ content ];
                textFlow.whiteSpaceCollapse = undefined;
            }
            
            return textFlow;
        }
        
        /**
         *  @private
         */
        private function updateEditingMode():void
        {
            var newEditingMode:String = EditingMode.READ_ONLY;
            
            if (enabled)
            {
                if (_editable)
                    newEditingMode = EditingMode.READ_WRITE;
                else if (_selectable)
                    newEditingMode = EditingMode.READ_SELECT;
            }
            
            editingMode = newEditingMode;
        }
        
        /**
         *  @private
         * 
         *  This is used when text is either inserted or appended via the API.
         */
        private function handleInsertText(newText:String, isAppend:Boolean=false):void
        {
            // Make sure all properties are committed.  The damage handler for the 
            // insert will cause the remeasure and display update.
            validateProperties();
            
            if (isAppend)
            {
                // Set insertion pt to the end of the current text.
                _selectionAnchorPosition = text.length;
                _selectionActivePosition = _selectionAnchorPosition;
            }
            else
            {
                // Insert requires a selection, or it is a noop.
                if (_selectionAnchorPosition == -1 || _selectionActivePosition == -1)
                    return;
            }
            
            // This will update the selection after the operation is done.
            var success:Boolean =
                _textContainerManager.insertTextOperation(
                    newText, _selectionAnchorPosition, _selectionActivePosition);
            
            if (success)
                dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));
        }
        
        /**
         *  @private
         */
        private function handlePasteOperation(op:PasteOperation):void
        {
            var hasConstraints:Boolean = 
                restrict || maxChars || displayAsPassword;
            
            // If there are no constraints and multiline text is allowed
            // there is nothing that needs to be done.
            if (!hasConstraints && multiline)
                return;
            
            // Make sure the clipboard has something to paste.
            if (op.textScrap == null || op.textScrap.textFlow == null)
                return;
            
            // If copied/cut from displayAsPassword field the pastedText
            // is '*' characters but this is correct.
            var pastedText:String = staticPlainTextExporter.export(
                op.textScrap.textFlow, ConversionType.STRING_TYPE) as String;
            
            // If there are no constraints and no newlines there is nothing
            // more to do.
            if (!hasConstraints && pastedText.search(ALL_NEWLINES_REGEXP) == -1)
                return;
            
            // Save this in case we modify the pasted text.  We need to know
            // how much text to delete.
            var textLength:int = pastedText.length;
            
            // Keep _text in sync with the text flow.  If there was a selection
            // for the paste, delete that text, then insert the pasted
            // text.
            if (_displayAsPassword)
            {
                _text = splice(_text, op.absoluteStart, op.absoluteEnd, "");
                _text = splice(_text, op.absoluteStart, op.absoluteStart, pastedText);
            }
            
            // If multiline is false, strip newlines out of pasted text
            // This will not strip newlines out of displayAsPassword fields
            // since the text is the passwordChar and newline won't be found.
            if (!multiline)
                pastedText = pastedText.replace(ALL_NEWLINES_REGEXP, "");
            
            // We know it's an EditManager or we wouldn't have gotten here.
            var editManager:IEditManager = 
                EditManager(_textContainerManager.beginInteraction());
            
            // Generate a CHANGING event for the PasteOperation but not for the
            // DeleteTextOperation or the InsertTextOperation which are also part
            // of the paste.
            dispatchChangeAndChangingEvents = false;
            
            // Replace the same text, the same place where the paste was done.
            // This will go thru the InsertPasteOperation and do the right
            // things with restrict, maxChars, displayAsPassword and _text.
            var selectionState:SelectionState = new SelectionState(
                  op.textFlow, op.absoluteStart, op.absoluteStart + textLength);
            editManager.insertText(pastedText, selectionState);        
            
            // All done with the edit manager.
            _textContainerManager.endInteraction();
            
            dispatchChangeAndChangingEvents = true;
        }
        
        //--------------------------------------------------------------------------
        //
        //  Event handlers
        //
        //--------------------------------------------------------------------------
        
        /**
         *  @private
         *  find the right time to listen to the focusmanager
         */
        private function addedToStageHandler(event:Event):void
        {
            if (event.target == this)
            {
                removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
                callLater(addActivateHandlers);
            }    
        }
        
        /**
         *  @private
         *  add listeners to focusManager
         */
        private function addActivateHandlers():void
        {
            if (!focusManager)
                return;
            
            focusManager.addEventListener(FlexEvent.FLEX_WINDOW_ACTIVATE, 
                _textContainerManager.activateHandler, false, 0, true)
            focusManager.addEventListener(FlexEvent.FLEX_WINDOW_DEACTIVATE, 
                _textContainerManager.deactivateHandler, false, 0, true)
        }
        
        /**
         *  @private
         *  Called when a FocusManager is added to an IFocusManagerContainer.
         *  We need to check that it belongs
         *  to us before listening to it.
         *  Because we listen to sandboxroot, you cannot assume the type of
         *  the event.
         */
        private function addFocusManagerHandler(event:Event):void
        {
            if (focusManager == event.target["focusManager"])
            {
                systemManager.getSandboxRoot().removeEventListener(FlexEvent.ADD_FOCUS_MANAGER, 
                    addFocusManagerHandler, true)
                addActivateHandlers();
            }
        }
        
        /**
         *  @private
         *  RichEditableTextContainerManager overrides focusInHandler and calls
         *  this before executing its own focusInHandler.
         */
        mx_internal function focusInHandler(event:FocusEvent):void
        {
            // When TCM is simulating a focusIn event, event will be null.
            // Ignore these and wait for the actual focus in event.
            if (event == null)
                return;
            
            //trace("focusIn handler");
            
            var fm:IFocusManager = focusManager;
            if (fm && editingMode == EditingMode.READ_WRITE)
                fm.showFocusIndicator = true;
            
            // showFocusIndicator must be set before this is called.
            super.focusInHandler(event);
            
            if (editingMode == EditingMode.READ_WRITE)
            {
                // If the focusIn was because of a mouseDown event, let TLF
                // handle the selection.  Otherwise it was because we tabbed in
                // or we programatically set the focus.
                if (!mouseDown)
                {
                    var selectionManager:ISelectionManager = 
                        _textContainerManager.beginInteraction();       
                    
                    if (multiline)
                    {
                        if (!selectionManager.hasSelection())
                            selectionManager.selectRange(0, 0);
                    } 
                    else if (!hasProgrammaticSelectionRange)
                    {
                        selectionManager.selectAll();
                    }
                    
                    selectionManager.refreshSelection();
                    
                    _textContainerManager.endInteraction();       
                }
                
                if (_imeMode != null)
                {
                    // When IME.conversionMode is unknown it cannot be
                    // set to anything other than unknown(English)      
                    try
                    {
                        if (IME.conversionMode != IMEConversionMode.UNKNOWN)
                        {
                            IME.conversionMode = _imeMode;
                        }
                    }
                    catch(e:Error)
                    {
                        // on Windows, setting a Japanese IME mode when in
                        // english throws an error (on Mac it doesn't)
                        // so ignore errors we get.
                    }
                }            
            }
            
            if (focusManager && multiline)
                focusManager.defaultButtonEnabled = false;
        }
        
        /**
         *  @private
         *  RichEditableTextContainerManager overrides focusOutHandler and calls
         *  this before executing its own focusOutHandler.
         */
        mx_internal function focusOutHandler(event:FocusEvent):void
        {
            //trace("focusOut handler");
            
            super.focusOutHandler(event);
            
            // By default, we clear the undo history when a RichEditableText loses 
            // focus.
            if (clearUndoOnFocusOut && undoManager)
                undoManager.clearAll();
            
            if (focusManager)
                focusManager.defaultButtonEnabled = true;
            
            
            dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));                           
        }
        
        /**
         *  @private
         *  RichEditableTextContainerManager overrides keyDownHandler and calls
         *  this before executing its own keyDownHandler.
         */ 
        mx_internal function keyDownHandler(event:KeyboardEvent):void
        {
            if (editingMode != EditingMode.READ_WRITE)
                return;
            
            // Handle the ENTER key here, if multiline text is not allowed or
            // if there isn't enough room for more characters to be added.
            if (event.keyCode == Keyboard.ENTER)
            {        
                if (!multiline)
                {
                    dispatchEvent(new FlexEvent(FlexEvent.ENTER));
                    event.preventDefault();
                    return;
                }
                
                // Multiline.  Make sure there is room before acting on it.
                if (_maxChars != 0 && text.length >= _maxChars)
                {
                    event.preventDefault();
                    return;
                }                

                // Let the TLF EditManager handle the ENTER key.  If editing
                // a list, depending on the position, it will either add a new
                // list item or close off the list.  Otherwise it will split
                // the paragraph.
            }
        }
        
        /**
         *  @private
         */
        mx_internal function mouseDownHandler(event:MouseEvent):void
        {
            mouseDown = true;
            
            // Need to get called even if mouse events are dispatched
            // outside of this component.  For example, when the user does
            // a mouse down in RET, drags the mouse outside of the 
            /// component, and then releases the mouse.
            systemManager.getSandboxRoot().addEventListener(
                MouseEvent.MOUSE_UP, 
                systemManager_mouseUpHandler, true /*useCapture*/);
        }
        
        /**
         *  @private
         */
        private function systemManager_mouseUpHandler(event:MouseEvent):void
        {
            mouseDown = false;
            
            systemManager.getSandboxRoot().removeEventListener(
                MouseEvent.MOUSE_UP, 
                         systemManager_mouseUpHandler, true /*useCapture*/);
        }
        
        /**
         *  @private
         *  call a TLF method so we don't leak
         */
        private function removedFromStageHandler(event:Event):void
        {
            if (event.target == this)
            {
                TextContainerManager.releaseReferences();
            }    
        }
        
        /**
         *  @private
         *  If the textFlow hasn't changed the generation remains the same.
         *  Changing the composition width and/or height does not change the
         *  generation.  The bounds can change as a result of different
         *  composition dimensions or as a result of more of the text flow
         *  being composed.  Only as much of the text flow as is displayed is
         *  composed.  If not all of the text flow is composed, its content height
         *  is estimated.  Until the entire text flow is composed its content
         *  height can increase or decrease while scrolling thru the flow.  
         *
         *  If the following conditions are met with the contentWidth and the
         *  contentHeight reported to the scroller, the scroller can avoid the 
         *  situation we've seen where it tries to add a scroll bar which causes the 
         *  text to reflow, which changes the content bounds, which causes the 
         *  scroller to react, and potentially loop indefinately.
         * 
         *       if width is reduced the height should grow or stay the same
         *       if height is reduced the width should grow or stay the same
         *       if width and height are reduced then either the width or height
         *           should grow or stay the same.
         *
         *  toFit
         *      width       height
         *      
         *      smaller     smaller     height pinned to old height
         *      smaller     larger      ok
         *      larger      larger      ok
         *      larger      smaller     ok
         *       
         *  explicit
         *      width       height
         *      smaller     smaller     width pinned to old width
         *      smaller     larger      width pinned to old width
         *      larger      larger      ok
         *      larger      smaller     ok
         */
        private function adjustContentBoundsForScroller(bounds:Rectangle):void
        {   
            // Already reported bounds at least once for this generation of
            // the text flow so we have to be careful to mantain consistency
            // for the scroller.
            if (_textFlow.generation == lastContentBoundsGeneration)
            {          
                if (bounds.width <= _contentWidth)
                {
                    if (_textContainerManager.hostFormat.lineBreak == "toFit")
                    {
                        if (bounds.height < _contentHeight)
                            bounds.height = _contentHeight;
                    }
                    else
                    {
                        // The width may get smaller if the compose height is 
                        // reduced and fewer lines are composed.  Use the old 
                        // content width which is more accurate.
                        bounds.width = _contentWidth;
                    }
                }
            }
            
            lastContentBoundsGeneration = _textFlow.generation;
        }
        
        /**
         *  @private
         *  Called when the TextContainerManager dispatches a 'compositionComplete'
         *  event when it has recomposed the text into TextLines.
         */
        private function textContainerManager_compositionCompleteHandler(
            event:CompositionCompleteEvent):void
        {
            //trace("compositionComplete");
            
            var oldContentWidth:Number = _contentWidth;
            var oldContentHeight:Number = _contentHeight;
            
            var newContentBounds:Rectangle = 
                _textContainerManager.getContentBounds();
            
            // If x and/or y are not 0, adjust for what is visible.  For example, if there is an 
            // image which is wider than the composeWidth and float="right", x will be negative
            // and the part of the image between x and 0 will not be visible so it should
            // not be included in the reported width.  This will avoid a scrollbar that does
            // nothing.
            newContentBounds.width += newContentBounds.x;
            newContentBounds.height += newContentBounds.y;
            
            // Try to prevent the scroller from getting into a loop while
            // adding/removing scroll bars.
            if (_textFlow && clipAndEnableScrolling)
                adjustContentBoundsForScroller(newContentBounds);
            
            var newContentWidth:Number = newContentBounds.width;        
            var newContentHeight:Number = newContentBounds.height;
            
            // TODO:(cframpto) handle blockProgression == RL
            
            if (newContentWidth != oldContentWidth)
            {
                _contentWidth = newContentWidth;
                
                //trace("composeWidth", _textContainerManager.compositionWidth, "contentWidth", oldContentWidth, newContentWidth);
                
                // If there is a scroller, this triggers the scroller layout.
                dispatchPropertyChangeEvent(
                    "contentWidth", oldContentWidth, newContentWidth);
            }
            
            if (newContentHeight != oldContentHeight)
            {
                _contentHeight = newContentHeight;
                
                //trace("composeHeight", _textContainerManager.compositionHeight, "contentHeight", oldContentHeight, newContentHeight);
                
                // If there is a scroller, this triggers the scroller layout.
                dispatchPropertyChangeEvent(
                    "contentHeight", oldContentHeight, newContentHeight);
            } 
        }
        
        /**
         *  @private
         *  Called when the TextContainerManager dispatches a 'damage' event.
         *  The TextFlow could have been modified interactively or programatically.
         */
        private function textContainerManager_damageHandler(event:DamageEvent):void
        {
            if (event.damageLength == 0)
                return;
            
            if (inUpdateDLMethod)
                return;
            
            // Text that is being measured is damaged so update the display.
            if (inMeasureMethod)
            {
                invalidateDisplayList();
                return;
            }
            
            //trace("damageHandler", "generation", _textFlow ? _textFlow.generation : -1, "lastGeneration", lastGeneration);
            
            // The following textContainerManager functions can trigger a damage
            // event:
            //    setText/setTextFlow
            //    set hostFormat
            //    set compositionWidth/compositionHeight
            //    set horizontalScrollPosition/veriticalScrollPosition
            //    set swfContext
            //    updateContainer or compose: always if TextFlowFactory, sometimes 
            //        if flowComposer
            // or the textFlow can be modified directly.
            
            // If no changes, don't recompose/update.  The TextFlowFactory 
            // createTextLines dispatches damage events every time the textFlow
            // is composed, even if there are no changes. 
            if (_textFlow && _textFlow.generation == lastGeneration)
                return;
            
            // If there are pending changes, don't wipe them out.  We have
            // not gotten to commitProperties() yet.
            if (textChanged || textFlowChanged || contentChanged)
                return;
            
            // In this case we always maintain _text with the underlying text and
            // display the appropriate number of passwordChars.  If there are any
            // interactive editing operations _text is updated during the operation.
            if (!displayAsPassword)
                _text = null;
            
            _content = null;        
            _textFlow = _textContainerManager.getTextFlow();
                        
            lastGeneration = _textFlow.generation;
            
            // We don't need to call invalidateProperties()
            // because the hostFormat and the _textFlow are still valid.
            
            // If the textFlow content is modified directly or if there is a style 
            // change by changing the textFlow directly the size could change.
            invalidateSize();
            
            invalidateDisplayList();
        }
        
        /**
         *  @private
         *  Called when the TextContainerManager dispatches a 'scroll' event
         *  as it autoscrolls.
         */
        private function textContainerManager_scrollHandler(event:Event):void
        {
            var oldHorizontalScrollPosition:Number = _horizontalScrollPosition;
            var newHorizontalScrollPosition:Number =
                _textContainerManager.horizontalScrollPosition;
            
            if (newHorizontalScrollPosition != oldHorizontalScrollPosition)
            {
                //trace("hsp scroll", oldHorizontalScrollPosition, "->", newHorizontalScrollPosition);
                
                _horizontalScrollPosition = newHorizontalScrollPosition;
                
                dispatchPropertyChangeEvent("horizontalScrollPosition",
                    oldHorizontalScrollPosition, newHorizontalScrollPosition);
            }
            
            var oldVerticalScrollPosition:Number = _verticalScrollPosition;
            var newVerticalScrollPosition:Number =
                _textContainerManager.verticalScrollPosition;
            
            if (newVerticalScrollPosition != oldVerticalScrollPosition)
            {
                //trace("vsp scroll", oldVerticalScrollPosition, "->", newVerticalScrollPosition);
                
                _verticalScrollPosition = newVerticalScrollPosition;
                
                dispatchPropertyChangeEvent("verticalScrollPosition",
                    oldVerticalScrollPosition, newVerticalScrollPosition);
            }
        }
        
        /**
         *  @private
         *  Called when the TextContainerManager dispatches a 'selectionChange' event.
         */
        private function textContainerManager_selectionChangeHandler(
            event:SelectionEvent):void
        {
            var oldAnchor:int = _selectionAnchorPosition;
            var oldActive:int = _selectionActivePosition;
            
            var selectionState:SelectionState = event.selectionState;
            
            if (selectionState)
            {
                _selectionAnchorPosition = selectionState.anchorPosition;
                _selectionActivePosition = selectionState.activePosition;
            }
            else
            {
                _selectionAnchorPosition = -1;
                _selectionActivePosition = -1;
            }
            
            // Selection changed so reset.
            hasProgrammaticSelectionRange = false;
            
            // Only dispatch the event if the selection has really changed.
            var changed:Boolean = oldAnchor != _selectionAnchorPosition ||
                oldActive != _selectionActivePosition;
                                   
            if (changed)
            { 
                //trace("selectionChangeHandler", _selectionAnchorPosition, _selectionActivePosition);
                dispatchEvent(new FlexEvent(FlexEvent.SELECTION_CHANGE));
            }
        }
        
        /**
         *  @private
         *  Called when the TextContainerManager dispatches an 'operationBegin'
         *  event before an editing operation.
         */     
        private function textContainerManager_flowOperationBeginHandler(
            event:FlowOperationEvent):void
        {
            //trace("flowOperationBegin", "level", event.level);
            
            var op:FlowOperation = event.operation;
            
            // The text flow's generation will be incremented if the text flow
            // is modified in any way by this operation.
            
            if (op is InsertTextOperation)
            {
                var insertTextOperation:InsertTextOperation =
                    InsertTextOperation(op);
                
                var textToInsert:String = insertTextOperation.text;
                
                // Note: Must process restrict first, then maxChars,
                // then displayAsPassword last.
                
                // The text deleted by this operation.  If we're doing our
                // own manipulation of the textFlow or thisis a result of a paste operation
                // we have to take the deleted text into account as well as the inserted text.
                var delSelOp:SelectionState = 
                    insertTextOperation.deleteSelectionState;
                
                var delLen:int = (delSelOp == null) ? 0 :
                    delSelOp.absoluteEnd - delSelOp.absoluteStart;
                
                if (_restrict != null)
                {
                    textToInsert = StringUtil.restrict(textToInsert, restrict);
                    // If restrict is the result of a paste the text has already been inserted
                    // into the buffer and has to be removed so don't short-circuit the operation.
                    if (textToInsert.length == 0 && delLen == 0)
                    {
                        event.preventDefault();
                        return;
                    }
                }
                
                if (maxChars != 0)
                {
                    var length1:int = text.length - delLen;
                    var length2:int = textToInsert.length;
                    if (length1 + length2 > maxChars)
                        textToInsert = textToInsert.substr(0, maxChars - length1);
                }
                
                if (_displayAsPassword)
                {
                    // Remove deleted text.
                    if (delLen > 0)
                    {
                        _text = splice(_text, delSelOp.absoluteStart, 
                                       delSelOp.absoluteEnd, "");                                    
                    }
                    
                    // Add in the inserted text.
                    if (textToInsert.length > 0)
                    {
                        _text = splice(_text, insertTextOperation.absoluteStart,
                            insertTextOperation.absoluteStart, textToInsert);
                        
                        // Display the passwordChar rather than the actual text.
                        textToInsert = StringUtil.repeat(passwordChar,
                            textToInsert.length);
                    }
                }
                
                insertTextOperation.text = textToInsert;
            }
            else if (op is CopyOperation)
            {
                if (_displayAsPassword)
                {
                    // For security, don't allow passwords to be copied.
                    event.preventDefault();
                    return;
                }
            }
            else if (op is PasteOperation)
            {
                // Paste is implemented in operationEnd.  The basic idea is to allow 
                // the paste to go through unchanged, but group it together with a 
                // second operation that modifies text as part of the same 
                // transaction. This is vastly simpler for TLF to manage.
                // But first, we do a multi-line check and remove newlines if not
                if (!multiline)
                {
                    var po:PasteOperation = PasteOperation(op);

                    // Make sure the clipboard has something to paste.
                    if (po.textScrap == null || po.textScrap.textFlow == null)
                        return;

                    // If copied/cut from displayAsPassword field the pastedText
                    // is '*' characters but this is correct.
                    var pastedText:String = staticPlainTextExporter.export(
                        po.textScrap.textFlow, ConversionType.STRING_TYPE) as String;
                    
                    // If there are no newlines there is nothing
                    // more to do.
                    if (pastedText.search(ALL_NEWLINES_REGEXP) != -1)
                    {
                        pastedText = pastedText.replace(ALL_NEWLINES_REGEXP, "");
                        po.textScrap = 
                            TextClipboard.importToScrap(pastedText, 
                                TextConverter.PLAIN_TEXT_FORMAT);
                    }
                    // don't do anything if nothing left on clipboard
                    if (pastedText.length == 0)
                        event.preventDefault();
                }
            }
            else if (op is DeleteTextOperation || op is CutOperation)
            {
                var flowTextOperation:FlowTextOperation =
                    FlowTextOperation(op);
                
                // Eat 0-length deletion.  This can happen when insertion point is 
                // at start of container when a backspace is entered
                // or when the insertion point is at the end of the
                // container and a delete key is entered.
                if (flowTextOperation.absoluteStart == 
                    flowTextOperation.absoluteEnd)
                {
                    event.preventDefault();
                    return;
                }           
                
                if (_displayAsPassword)
                {
                    if (op is DeleteTextOperation)
                    {
                        _text = splice(_text, flowTextOperation.absoluteStart,
                            flowTextOperation.absoluteEnd, "");
                    }
                    else
                    {
                        // For security, don't allow passwords to be cut.
                        event.preventDefault();
                        return;
                    }
                }
            }
            
            // Dispatch a 'changing' event from the RichEditableText
            // as notification that an editing operation is about to occur.
            // The level will be 0 for single operations, and at the start
            // of a composite operation.
            if (dispatchChangeAndChangingEvents && event.level == 0)
            {
                var newEvent:TextOperationEvent =
                    new TextOperationEvent(TextOperationEvent.CHANGING);
                newEvent.operation = op;
                dispatchEvent(newEvent);
                
                // If the event dispatched from this RichEditableText is canceled,
                // cancel the one from the EditManager, which will prevent
                // the editing operation from being processed.
                if (newEvent.isDefaultPrevented())
                    event.preventDefault();
            }
        }
        
        /**
         *  @private
         *  Called when the TextContainerManager dispatches an 'operationEnd' event
         *  after an editing operation.
         */
        private function textContainerManager_flowOperationEndHandler(
            event:FlowOperationEvent):void
        {
            //trace("flowOperationEnd", "level", event.level);
            
            // Paste is a special case.  Any mods have to be made to the text
            // which includes what was pasted.
            if (event.operation is PasteOperation)
                handlePasteOperation(PasteOperation(event.operation));
        }
        
        /**
         *  @private
         *  Called when the TextContainerManager dispatches an 'operationComplete' 
         *  event after an editing operation.
         */
        private function textContainerManager_flowOperationCompleteHandler(
            event:FlowOperationEvent):void
        {
            //trace("flowOperationComplete", "level", event.level);
            
            // Dispatch a 'change' event from the RichEditableText
            // as notification that an editing operation has occurred.
            // The flow is now in a state that it can be manipulated.
            // The level will be 0 for single operations, and at the end
            // of a composite operation.
            if (dispatchChangeAndChangingEvents && event.level == 0)
            {
                var newEvent:TextOperationEvent =
                    new TextOperationEvent(TextOperationEvent.CHANGE);
                newEvent.operation = event.operation;
                dispatchEvent(newEvent);
            }
        }
        
        /**
         *  @private
         *  Called when an InlineGraphicElement is asynchronously loaded.
         *  The event status could be "sizePending", "loaded" or "error". 
         *  Must call updateAllContainers() to cause transition to the next
         *  graphic status.
         */
        private function textContainerManager_inlineGraphicStatusChangeHandler (
            event:StatusChangeEvent):void
        {            
            if (event.status == InlineGraphicElementStatus.READY)
            {
                // Now that the actual size of the graphic is available need to
                // optionally remeasure and updateContainer.
                if (autoSize)
                    invalidateSize();                
            }

            // Call updateAllContainers().
            invalidateDisplayList();
        }    
        
        /**
         *  @private
         *  release the textline as it is temporary.
         */
        private function tossTextLine(textLine:DisplayObject):void
        {
            TextUtil.recycleTextLine(textLine as TextLine);
        }
    }

}
