////////////////////////////////////////////////////////////////////////////////
//
//  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 flashx.textLayout.container
{
	import flash.display.BlendMode;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.InteractiveObject;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.ContextMenuEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.FocusEvent;
	import flash.events.IMEEvent;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.events.TextEvent;
	import flash.geom.Rectangle;
	import flash.text.engine.TextBlock;
	import flash.text.engine.TextLine;
	import flash.text.engine.TextLineValidity;
	import flash.ui.ContextMenu;
	import flash.ui.ContextMenuClipboardItems;
	import flash.ui.Mouse;
	import flash.ui.MouseCursor;
	import flash.utils.Dictionary;
	
	import flashx.textLayout.compose.BaseCompose;
	import flashx.textLayout.compose.ISWFContext;
	import flashx.textLayout.compose.SimpleCompose;
	import flashx.textLayout.compose.StandardFlowComposer;
	import flashx.textLayout.compose.TextFlowLine;
	import flashx.textLayout.compose.TextLineRecycler;
	import flashx.textLayout.debug.Debugging;
	import flashx.textLayout.debug.assert;
	import flashx.textLayout.edit.EditManager;
	import flashx.textLayout.edit.EditingMode;
	import flashx.textLayout.edit.IEditManager;
	import flashx.textLayout.edit.IInteractionEventHandler;
	import flashx.textLayout.edit.ISelectionManager;
	import flashx.textLayout.edit.SelectionFormat;
	import flashx.textLayout.edit.SelectionManager;
	import flashx.textLayout.edit.SelectionState;
	import flashx.textLayout.elements.Configuration;
	import flashx.textLayout.elements.FlowElement;
	import flashx.textLayout.elements.FlowLeafElement;
	import flashx.textLayout.elements.IConfiguration;
	import flashx.textLayout.elements.ParagraphElement;
	import flashx.textLayout.elements.SpanElement;
	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.events.TextLayoutEvent;
	import flashx.textLayout.events.UpdateCompleteEvent;
	import flashx.textLayout.factory.StringTextLineFactory;
	import flashx.textLayout.factory.TextFlowTextLineFactory;
	import flashx.textLayout.factory.TextLineFactoryBase;
	import flashx.textLayout.formats.BlockProgression;
	import flashx.textLayout.formats.FormatValue;
	import flashx.textLayout.formats.ITextLayoutFormat;
	import flashx.textLayout.formats.TextLayoutFormat;
	import flashx.textLayout.property.Property;
	import flashx.textLayout.tlf_internal;
	import flashx.undo.IUndoManager;
	import flashx.undo.UndoManager;

	use namespace tlf_internal;
	/**
	 *
	 *  @eventType flashx.textLayout.events.FlowOperationEvent.FLOW_OPERATION_BEGIN
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	 
	[Event(name="flowOperationBegin", type="flashx.textLayout.events.FlowOperationEvent")]
	
	/**
	 * 
	 * @eventType flashx.textLayout.events.FlowOperationEvent.FLOW_OPERATION_END
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	 
	[Event(name="flowOperationEnd", type="flashx.textLayout.events.FlowOperationEvent")]
	
	
	/**
	 * 
	 * @eventType flashx.textLayout.events.FlowOperationEvent.FLOW_OPERATION_COMPLETE
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	
	[Event(name="flowOperationComplete", type="flashx.textLayout.events.FlowOperationEvent")]
	
	/** Dispatched whenever the selection is changed.  Primarily used to update selection-dependent user interface. 
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	
	[Event(name="selectionChange", type="flashx.textLayout.events.SelectionEvent")]
	
	/** Dispatched after every recompose. 
	*
	* @playerversion Flash 10
	* @playerversion AIR 1.5
	* @langversion 3.0
	*/
	
	[Event(name="compositionComplete", type="flashx.textLayout.events.CompositionCompleteEvent")]
	
	/** Dispatched when the mouse is pressed down over any link. 
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	
	[Event(name="mouseDown", type="flashx.textLayout.events.FlowElementMouseEvent")]
	
	/** Dispatched when the mouse is released over any link. 
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	
	[Event(name="mouseUp", type="flashx.textLayout.events.FlowElementMouseEvent")]
	
	/** Dispatched when the mouse passes over any link. 
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	
	[Event(name="mouseMove", type="flashx.textLayout.events.FlowElementMouseEvent")]	
	
	/** Dispatched when the mouse first enters any link. 
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	
	[Event(name="rollOver", type="flashx.textLayout.events.FlowElementMouseEvent")]
	
	/** Dispatched when the mouse goes out of any link. 
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	
	[Event(name="rollOut", type="flashx.textLayout.events.FlowElementMouseEvent")]	
	
	/** Dispatched when any link is clicked. 
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	
	[Event(name="click", type="flashx.textLayout.events.FlowElementMouseEvent")]
	
	/** Dispatched when a InlineGraphicElement is resized due to having width or height as auto or percent 
	 * and the graphic has finished loading. 
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	
	[Event(name="inlineGraphicStatusChanged", type="flashx.textLayout.events.StatusChangeEvent")]
	
	/** Dispatched by a TextFlow object after text is scrolled within a controller container.  
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	
	[Event(name="scroll", type="flashx.textLayout.events.TextLayoutEvent")]
	
	/** Dispatched by a TextFlow object each time it is damaged 
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	
	[Event(name="damage", type="flashx.textLayout.events.DamageEvent")]

	/** Dispatched by a TextFlow object each time a container has had new DisplayObjects added or updated as a result of composition.
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 */
	
	[Event(name="updateComplete", type="flashx.textLayout.events.UpdateCompleteEvent")]
		
	[Exclude(name="getBaseSWFContext",kind="method")]
	
	[Exclude(name="callInContext",kind="method")]
	/** Manages text in a container. Assumes that it manages all children of the container. 
	 * Consider using TextContainerManager for better performance in cases where there is a 
	 * one container per TextFlow, and the TextFlow is not the main focus, is static text, or
	 * is infrequently selected. Good for text in form fields, for example.
	 * 
	 * @includeExample examples\TextContainerManager.as -noswf
	 *
 	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 * 
	 * @see ContainerController
	 */			
	public class TextContainerManager extends EventDispatcher implements ISWFContext, IInteractionEventHandler, ISandboxSupport
	{		
		// all events that are listened for need to be in this list.
		static private const eventList:Array = [ 
			FlowOperationEvent.FLOW_OPERATION_BEGIN,
			FlowOperationEvent.FLOW_OPERATION_END,
			FlowOperationEvent.FLOW_OPERATION_COMPLETE,
			SelectionEvent.SELECTION_CHANGE,
			CompositionCompleteEvent.COMPOSITION_COMPLETE,
			MouseEvent.CLICK,		//from FlowElementMouseEvent
			MouseEvent.MOUSE_DOWN,	//from FlowElementMouseEvent
			MouseEvent.MOUSE_OUT,	//from FlowElementMouseEvent
			MouseEvent.MOUSE_UP,	//from FlowElementMouseEvent
			MouseEvent.MOUSE_OVER,	//from FlowElementMouseEvent
			MouseEvent.MOUSE_OUT,	//from FlowElementMouseEvent
			StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE,
		 	TextLayoutEvent.SCROLL,
			DamageEvent.DAMAGE,
			UpdateCompleteEvent.UPDATE_COMPLETE
		];
		
		/** Configuration to be used by the TextContainerManager.  This can only be set once and before the inputmanager is used.  */
		static private var _defaultConfiguration:IConfiguration = null;

		/** The default configuration for this TextContainerManager. Column and padding attributes
		 * are set to <code>FormatValue.INHERIT</code>.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 * 
	 	 * @see flashx.textLayout.elements.IConfiguration IConfiguration
	 	 * @see flashx.textLayout.formats.FormatValue#INHERIT FormatValue.INHERIT
		 */
		static public function get defaultConfiguration():IConfiguration
		{
			if (_defaultConfiguration == null)
				_defaultConfiguration = customizeConfiguration(null);
			return _defaultConfiguration; 
		}
		
		/** @private Make a configuration acceptable to the TCM */
		static tlf_internal function customizeConfiguration(config:IConfiguration):IConfiguration
		{
			var newConfig:Configuration;
			if (config)
			{
				if (config.flowComposerClass == TextLineFactoryBase.getDefaultFlowComposerClass())
					return config;
				newConfig = (config as Configuration).clone();
			}
			else
				newConfig = new Configuration();
			newConfig.flowComposerClass = TextLineFactoryBase.getDefaultFlowComposerClass();
			return newConfig;
		}
		
		static private var _inputManagerTextFlowFactory:TCMTextFlowTextLineFactory;
		static private function inputManagerTextFlowFactory():TCMTextFlowTextLineFactory
		{
			if (!_inputManagerTextFlowFactory)
				_inputManagerTextFlowFactory  = new TCMTextFlowTextLineFactory();
			return _inputManagerTextFlowFactory;
		}

		// dictionary of stringfactories so that they can share a configuration
		static private var stringFactoryDictionary:Dictionary;
		static private function inputManagerStringFactory(config:IConfiguration):StringTextLineFactory
		{
			if (!stringFactoryDictionary)
				stringFactoryDictionary = new Dictionary(true);
			var factory:StringTextLineFactory = stringFactoryDictionary[config];
			if (factory == null)
			{
				factory = new StringTextLineFactory(config);
				stringFactoryDictionary[config] = factory;
			}
			return factory;
		}
		
		/** @private Method to release all references to factories so they can be gc'ed, for example when Flex unloads a module. */
		static tlf_internal function releaseReferences():void
		{
			stringFactoryDictionary = null;
			_inputManagerTextFlowFactory = null;
		}
		
		/** Shared definition of the scrollPolicy property. @private */
		static tlf_internal const editingModePropertyDefinition:Property = Property.NewEnumStringProperty("editingMode", EditingMode.READ_WRITE, false, null, 
			EditingMode.READ_WRITE, EditingMode.READ_ONLY, EditingMode.READ_SELECT);	
		
		private var _container:Sprite;
		private var _compositionWidth:Number;
		private var _compositionHeight:Number;
		
		private var _text:String;
		private var _textDamaged:Boolean;				// indicates the _text property needs updating when sourceState is SOURCE_TEXTFLOW
		private var _lastSeparator:String;
		
		private var _hostFormat:ITextLayoutFormat;
		// textFlow format to be used by a string factory - combination of config.initialTextLayoutFormat and hostFormat
		private var _stringFactoryTextFlowFormat:ITextLayoutFormat;
		
		private var _contentTop:Number;
		private var _contentLeft:Number;
		private var _contentHeight:Number;
		private var _contentWidth:Number;
		
		private var _horizontalScrollPolicy:String;
		private var _verticalScrollPolicy:String;
		
		private var _swfContext:ISWFContext;
		private var _config:IConfiguration;
		
		//Decide whether to preserve the selection state when calling setText() [bug #2931406 from Flex SDK]
		private var _preserveSelectionOnSetText:Boolean = false;
		
		/** @private */
		static tlf_internal const SOURCE_STRING:int = 0;
		/** @private */
		static tlf_internal const SOURCE_TEXTFLOW:int = 1;
		
		/** @private */
		static tlf_internal const COMPOSE_FACTORY:int = 0;
		/** @private */
		static tlf_internal const COMPOSE_COMPOSER:int = 1;
		
		/** @private */
		static tlf_internal const HANDLERS_NOTADDED:int  = 0;
		/** @private */
		static tlf_internal const HANDLERS_NONE:int      = 1;
		/** @private */
		static tlf_internal const HANDLERS_CREATION:int  = 2;
		/** @private */
		static tlf_internal const HANDLERS_ACTIVE:int    = 3;
		/** @private */
		static tlf_internal const HANDLERS_MOUSEWHEEL:int = 4;
		
		private var _sourceState:int;
		private var _composeState:int;
		private var _handlersState:int;
		// track hasFocus.  Depending on various factors focus and mouseDown can occur in different order
		private var _hasFocus:Boolean;
		private var _editingMode:String;
		private var _ibeamCursorSet:Boolean;
		private var _interactionCount:int;
		
		/** @private */
		tlf_internal function get sourceState():int
		{ return _sourceState; }
		/** @private */
		tlf_internal function get composeState():int
		{ return _composeState; }
		/** @private */
		tlf_internal function get handlersState():int
		{ return _handlersState; }
	
		// Tracks damage when sourceState is SOURCE_STRING. TODO - Might be worthwhile to always set and clear this
		private var _damaged:Boolean;			
		private var _textFlow:TextFlow;
		private var _needsRedraw:Boolean;
		
		/** Constructor function - creates a TextContainerManager instance.
		 *
		 * For best results:
		 * <ol>
		 *	<li>Start with TextContainerManager.defaultConfiguration and modify it</li>   
		 *	<li>Share the same Configuration among many InputManagers</li>
		 * </ol>
		 *
		 * @param container The DisplayObjectContainer in which to manage the text lines.
		 * @param config - The IConfiguration instance to use with this TextContainerManager instance. 
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0	 	
		 */
		public function TextContainerManager(container:Sprite,configuration:IConfiguration =  null)
		{
			_container = container;
			_compositionWidth = 100;
			_compositionHeight = 100;
			
			_config = configuration ? customizeConfiguration(configuration) : defaultConfiguration;				
			_config = (_config as Configuration).getImmutableClone();

			_horizontalScrollPolicy = _verticalScrollPolicy = String(ScrollPolicy.scrollPolicyPropertyDefinition.defaultValue);

			_damaged = true;
			_needsRedraw = false;
			_text = "";
			_textDamaged = false;
			
			_sourceState = SOURCE_STRING;
			_composeState = COMPOSE_FACTORY;
			_handlersState = HANDLERS_NOTADDED;
			_hasFocus = false;
			
			_editingMode = editingModePropertyDefinition.defaultValue as String;
			_ibeamCursorSet = false;
			_interactionCount = 0;
			
			if (_container is InteractiveObject)
			{
				_container.doubleClickEnabled = true;
				// so the textlines can be swapped on the first click and a double click still works
				_container.mouseChildren = false;
				_container.focusRect = false;
			}
		}

		/** Returns the container (DisplayObjectContainer) that holds the text that this TextContainerManager manages.
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
	 	 * @see ContainerController#container
	 	 */
	 	 
		public function get container():Sprite
		{ return _container; }
		
		/** Returns <code>true</code> if the content needs composing. 
		 * 
		 * @return	<code>true</code> if the content needs composing; <code>false</code> otherwise.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
		public function isDamaged():Boolean
		{ return _composeState == COMPOSE_FACTORY ? _damaged : _textFlow.flowComposer.isDamaged(_textFlow.textLength); }
		
		/** Editing mode of this TextContainerManager. Modes are reading only, reading and selection permitted, 
		 * and editing (reading, selection, and writing)  permitted. Use the constant values of the EditingMode
		 * class to set this property. 
		 * <p>Default value is READ_WRITE.</p>
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
		 * @see flashx.textLayout.edit.EditingMode EditingMode
		 */
		public function get editingMode():String
		{ return _editingMode; }
		public function set editingMode(val:String):void
		{
			var newMode:String = editingModePropertyDefinition.setHelper(_editingMode, val) as String;
			
			if (newMode != _editingMode)
			{
				if (composeState == COMPOSE_COMPOSER)
				{
					_editingMode = newMode;
					invalidateInteractionManager();
				}
				else
				{
					removeActivationEventListeners();
					_editingMode = newMode;
					// there is no way to turn it on here if going from READ_ONLY to editable and mouse is over the inputmanager field
					if (_editingMode == EditingMode.READ_ONLY)
						removeIBeamCursor();
					addActivationEventListeners();
				}
			}
		}
		
		/**
		 * Returns the current text using a separator between paragraphs.
		 * The separator can be specified with the <code>separator</code>
		 * argument. The default value of the <code>separator</code> argument
		 * is the Unicode character <code>'PARAGRAPH SEPARATOR' (U+2029)</code>.
		 *
		 * <p>Calling the setter discards any attached TextFlow. Any selection is lost.</p>
		 * 
		 * @param separator String to set between paragraphs.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
	 	 */
		public function getText(separator:String = '\u2029'):String
		{
			if (_sourceState == SOURCE_STRING)
				return _text;

			if (_textDamaged || _lastSeparator != separator)
			{
				_text = "";
				var firstLeaf:FlowLeafElement = _textFlow.getFirstLeaf();
				if (firstLeaf != null)
				{
					var para:ParagraphElement = firstLeaf.getParagraph();
					while (para)
					{
						var nextPara:ParagraphElement = para.getNextParagraph();
						_text += para.getText();
						_text += nextPara ? separator : "";
						para = nextPara;
					}
				}
				_textDamaged = false;
				_lastSeparator = separator;
			}
			return _text;
		}
		/**
		 * Sets the <code>text</code> property to the specified String.
		 *
		 * Discards any attached TextFlow. Any selection is lost.
		 * 
		 * @param str the String to set
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
	 	 */
		public function setText(text:String):void
		{
			var hadPreviousSelection:Boolean = false;
			var selectionChanged:Boolean = false;
			var selectionState:SelectionState = null;
            
            var oldAnchorPosition:int = -1;
            var oldActivePosition:int = -1;
            
			if (_sourceState == SOURCE_TEXTFLOW)
			{
				if (_textFlow.interactionManager && _textFlow.interactionManager.hasSelection()){
					hadPreviousSelection = true;
					
					//preserve the selection state [bug #2931406 from Flex SDK]
					if (_preserveSelectionOnSetText && text)
                    {
                        oldAnchorPosition = Math.min(_textFlow.interactionManager.anchorPosition, text.length);
                        oldActivePosition = Math.min(_textFlow.interactionManager.activePosition, text.length);
						if(oldAnchorPosition != _textFlow.interactionManager.anchorPosition || oldActivePosition != _textFlow.interactionManager.activePosition)
							selectionChanged = true;
					}
				}
				
				removeTextFlowListeners();
				if (_textFlow.flowComposer)
					_textFlow.flowComposer.removeAllControllers();
				_textFlow.unloadGraphics();
				_textFlow = null;
				_sourceState = SOURCE_STRING;
				_composeState = COMPOSE_FACTORY;
				if (_container is InteractiveObject)
					_container.mouseChildren = false;
				addActivationEventListeners();
			}
			_text = text ? text : ""; 
			_damaged = true;
			_textDamaged = false;
			
			// Generate a damage event 
			if (hasEventListener(DamageEvent.DAMAGE))
				dispatchEvent(new DamageEvent(DamageEvent.DAMAGE, false, false, null, 0, _text.length));
			
            // If the original tcm had selection, the selection needs to be preserved after setText.
            if (hadPreviousSelection)
            {
                if (_preserveSelectionOnSetText)
                {
					if (_composeState != COMPOSE_COMPOSER)
                    	convertToTextFlowWithComposer();
                    if (_textFlow.interactionManager)
					{
						_textFlow.interactionManager.setSelectionState(new SelectionState(_textFlow, oldAnchorPosition, oldActivePosition));
						if(selectionChanged)
							_textFlow.dispatchEvent(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, _textFlow.interactionManager.getSelectionState()));
					}
                }
                else if (hasEventListener(SelectionEvent.SELECTION_CHANGE))
                {
                    // generate a selection changed event.
                    dispatchEvent(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, null));
                }
            }    

			if (_hasFocus)
				requiredFocusInHandler(null);
		}
				
		/** Sets the format when display just a string.  If displaying a TextFlow this has no immediate effect.  The supplied ITextLayoutFormat is not copied.  Modifying it without calling this setter has indeterminate effects. */
		public function get hostFormat():ITextLayoutFormat
		{ return _hostFormat; }
		public function set hostFormat(val:ITextLayoutFormat):void
		{
			_hostFormat = val;
			_stringFactoryTextFlowFormat = null;
			
			if (_sourceState == SOURCE_TEXTFLOW)
				_textFlow.hostFormat = _hostFormat;
			if (_composeState == COMPOSE_FACTORY)
				_damaged = true;
		}
		
		/** Returns the horizontal extent allowed for text inside the container. The value is specified in pixels.
		 * 
		 * <p>After setting this property, the text in the container is damaged and requires composing.</p>
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0  
	 	 */
		public function get compositionWidth():Number
		{ return _compositionWidth; }
		public function set compositionWidth(val:Number):void
		{
			if (_compositionWidth == val || (isNaN(_compositionWidth) && isNaN(val)))
				return;
			_compositionWidth = val; 
			if (_composeState == COMPOSE_COMPOSER)
			{
				getController().setCompositionSize(_compositionWidth,_compositionHeight);
			}
			else
			{
				_damaged = true; 
			}
		}
	
		/** Returns the vertical extent allowed for text inside the container. The value is specified in pixels. 
		 * <p>After setting this property, the text in the container is damaged and requires composing.</p>
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
	 	 
		public function get compositionHeight():Number
		{ return _compositionHeight; }
		public function set compositionHeight(val:Number):void
		{
			if (_compositionHeight == val || (isNaN(_compositionHeight) && isNaN(val)))
				return;
			_compositionHeight = val; 
			if (_composeState == COMPOSE_COMPOSER)
			{
				getController().setCompositionSize(_compositionWidth,_compositionHeight);
			}
			else
			{
				_damaged = true; 
			}
		}
		
		/** The Configuration object for this TextContainerManager. 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
	 	 * @see flashx.textLayout.IConfiguration IConfiguration
	 	 */
		public function get configuration():IConfiguration
		{ return _config; }
			
		/** Creates a rectangle that shows where the last call to either the <code>compose()</code> 
		 * method or the <code>updateContainer()</code> method placed the text.
		 *
		 * @return  the bounds of the content
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
	 	 * @see #compose()
	 	 * @see #updateContainer()
		 */
		public function getContentBounds():Rectangle
		{
			if (_composeState == COMPOSE_FACTORY)
				return new Rectangle(_contentLeft, _contentTop, _contentWidth, _contentHeight);
			var controller:ContainerController = getController();
			return controller.getContentBounds();
		}	
		
		/** The current TextFlow. Converts this to a full TextFlow representation if it 
		 * isn't already one. 
		 *
		 * @return 	the current TextFlow object
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
		public function getTextFlow():TextFlow
		{
			if (_sourceState != SOURCE_TEXTFLOW)
			{
				var wasDamaged:Boolean = isDamaged();
				convertToTextFlow();
				if (!wasDamaged)
					updateContainer();
			}
			return _textFlow;
		}

		/** Sets a TextFlow into this TextContainerManager replacing any existing TextFlow and discarding the 
		 * current text. 
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
		public function setTextFlow(textFlow:TextFlow):void
		{
			if (textFlow == _textFlow)
				return;
			
			if (textFlow == null)
			{
				setText(null);
				return;
			}
						
			// Remove the old textFlow from its TextContainerManager, if it has one
			if (textFlow.flowComposer && textFlow.flowComposer.numControllers > 0 && textFlow.flowComposer.getControllerAt(0) is TMContainerController)
			{
				var controller:TMContainerController = textFlow.flowComposer.getControllerAt(0) as TMContainerController;
				if (controller.textContainerManager && controller.textContainerManager.getTextFlow() == textFlow)
					controller.textContainerManager.setTextFlow(null);
			}  

			if (_sourceState == SOURCE_TEXTFLOW)
			{
				removeTextFlowListeners();
				if (_textFlow.flowComposer)
					_textFlow.flowComposer.removeAllControllers();
				_textFlow.unloadGraphics();
				_textFlow = null;
			}
				
			_textFlow = textFlow;
			// damages the entire flow
			_textFlow.hostFormat = hostFormat;
			_sourceState = SOURCE_TEXTFLOW;
			_composeState = textFlow.interactionManager || textFlow.mustUseComposer() ? COMPOSE_COMPOSER : COMPOSE_FACTORY;
			_textDamaged = true;
			addTextFlowListeners();
			
			if (_composeState == COMPOSE_COMPOSER)
			{
				// Possible issue - this clear call could be delayed until updateToController
				_container.mouseChildren = true;
				clearContainerChildren(true);
				clearComposedLines();
				_textFlow.flowComposer = new StandardFlowComposer();
				_textFlow.flowComposer.swfContext = _swfContext;
				_textFlow.flowComposer.addController(new TMContainerController(_container,_compositionWidth,_compositionHeight,this));
				
				invalidateInteractionManager();
				
				// always start with an empty selection
				if (_textFlow.interactionManager)
					_textFlow.interactionManager.selectRange(-1,-1);
			}
			else
				_damaged = true;
			
			if (_hasFocus)
				requiredFocusInHandler(null);
			
			addActivationEventListeners();
		}
		
		/** 
		 * Controls whether the factory generates all text lines or stops when the container bounds are filled.
		 * 
		 * @copy flashx.textLayout.container.ContainerController#horizontalScrollPolicy 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
	 	 */
	 	public function get horizontalScrollPolicy():String
		{
			return _horizontalScrollPolicy;
		}
		public function set horizontalScrollPolicy(scrollPolicy:String):void
		{
			_horizontalScrollPolicy = ScrollPolicy.scrollPolicyPropertyDefinition.setHelper(_horizontalScrollPolicy, scrollPolicy) as String;
			if (_composeState == COMPOSE_COMPOSER)
				getController().horizontalScrollPolicy = _horizontalScrollPolicy;
			else
				_damaged = true;
		}
		
		/** 
		 * Controls whether the factory generates all text lines or stops when the container bounds are filled.
		 * 
		 * @copy flashx.textLayout.container.ContainerController#verticalScrollPolicy 
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
	 	 */
	 	 
		public function get verticalScrollPolicy():String
		{
			return _verticalScrollPolicy;
		}
		public function set verticalScrollPolicy(scrollPolicy:String):void
		{
			_verticalScrollPolicy = ScrollPolicy.scrollPolicyPropertyDefinition.setHelper(_verticalScrollPolicy, scrollPolicy) as String;
			if (_composeState == COMPOSE_COMPOSER)
				getController().verticalScrollPolicy = _verticalScrollPolicy;
			else
				_damaged = true;
		}
			
		/** 
		 * @copy flashx.textLayout.container.ContainerController#horizontalScrollPosition
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
	 	 */
		public function get horizontalScrollPosition():Number
		{ return _composeState == COMPOSE_COMPOSER ? getController().horizontalScrollPosition : 0; }
		public function set horizontalScrollPosition(val:Number):void
		{ 
			if (val == 0 && _composeState == COMPOSE_FACTORY)
				return;
			if (_composeState != COMPOSE_COMPOSER)
				convertToTextFlowWithComposer();
			getController().horizontalScrollPosition = val;
		}
		
		/** 
		 * @copy flashx.textLayout.container.ContainerController#verticalScrollPosition 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
	 	 */
		public function get verticalScrollPosition():Number
		{ return _composeState == COMPOSE_COMPOSER ? getController().verticalScrollPosition : 0; }
		public function set verticalScrollPosition(val:Number):void
		{
			if (val == 0 && _composeState == COMPOSE_FACTORY)
				return;
			if (_composeState != COMPOSE_COMPOSER)
				convertToTextFlowWithComposer();
			getController().verticalScrollPosition = val;
		}

		/** 
		* @copy flashx.textLayout.container.ContainerController#getScrollDelta() 
		*
		* @playerversion Flash 10
		* @playerversion AIR 1.5
		* @langversion 3.0
	 	*/
		public function getScrollDelta(numLines:int):Number
		{
			if (_composeState != COMPOSE_COMPOSER)
				convertToTextFlowWithComposer();
			return getController().getScrollDelta(numLines);
		}
		
		/** 
		* @copy flashx.textLayout.container.ContainerController#scrollToRange() 
		*
		* @playerversion Flash 10
		* @playerversion AIR 1.5
		* @langversion 3.0
	 	*/
	 	public function scrollToRange(activePosition:int,anchorPosition:int):void
	 	{
			if (_composeState != COMPOSE_COMPOSER)
				convertToTextFlowWithComposer();
			getController().scrollToRange(activePosition,anchorPosition);	 		
	 	}

		/** 
		* Optional ISWFContext instance used to make FTE calls as needed in the proper swf context. 
		*
		* 
		* @see flashx.textLayout.compose.ISWFContext
		* 
		* @playerversion Flash 10
		* @playerversion AIR 1.5
	 	* @langversion 3.0
	 	*/
 	
		public function get swfContext():ISWFContext
		{ return _swfContext; }
		public function set swfContext(context:ISWFContext):void
		{ 
			_swfContext = context;
			if (_composeState == COMPOSE_COMPOSER)
				_textFlow.flowComposer.swfContext = _swfContext;
			else
				_damaged = true;
		}
		
		/** @private - TextContainerManager wraps an underlying swfcontext - tell it to FlowComposerBase so it can avoid extra invalidation */
		public function getBaseSWFContext():ISWFContext
		{ return _swfContext; }
				
		/** @private - this is part of a performance optimziation for reusing existing TextLines in place iff recreateTextLine is available. */
	    public function callInContext(fn:Function, thisArg:Object, argsArray:Array, returns:Boolean=true):*
		{
			var textBlock:TextBlock = thisArg as TextBlock;
			if (textBlock && _expectedFactoryCompose == TextLineFactoryBase._factoryComposer)
			{
			 	if (fn == textBlock.createTextLine)
					return createTextLine(textBlock,argsArray);
				if (Configuration.playerEnablesArgoFeatures && fn == thisArg["recreateTextLine"])
					return recreateTextLine(textBlock,argsArray);
			}

			var swfContext:ISWFContext = _swfContext ? _swfContext : BaseCompose.globalSWFContext;
	        if (returns)
	            return swfContext.callInContext(fn,thisArg,argsArray,returns);
			swfContext.callInContext(fn,thisArg,argsArray,returns);
		}
		
		public function resetLine(textLine:TextLine):void
		{
			// this line is being reset
			if (textLine == _composedLines[_composeRecycledInPlaceLines-1])
				_composeRecycledInPlaceLines--;
		}
		
		/** 
		 * Uses the <code>textBlock</code> parameter, and calls the <code>TextBlock.createTextLine()</code> method on it 
		 * using the remaining parameters.
		 * WARNING: modifies argsArray
		 *  
		 * @copy flash.text.engine.TextBlock
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
		private function createTextLine(textBlock:TextBlock, argsArray:Array):TextLine
		{
			var swfContext:ISWFContext = _swfContext ? _swfContext : BaseCompose.globalSWFContext;
			CONFIG::debug { assert(Configuration.playerEnablesArgoFeatures,"Bad call to createTextLine"); }

			if (_composeRecycledInPlaceLines < _composedLines.length && _expectedFactoryCompose == TextLineFactoryBase._factoryComposer)
			{
				var textLine:TextLine = _composedLines[_composeRecycledInPlaceLines++];

				argsArray.splice(0,0,textLine);
				return swfContext.callInContext(textBlock["recreateTextLine"],textBlock,argsArray);
			}

			return swfContext.callInContext(textBlock.createTextLine,textBlock,argsArray);
		}

		/** 
		 * Uses the <code>textBlock</code> parameter, and calls the <code>FlowComposerBase.recreateTextLine()</code> method on it 
		 * using the remaining parameters.
		 *
		 * @param textBlock The TextBlock to which the TextLine belongs.
		 * @param textLine  The TextLine to be recreated.
		 * @param previousLine Specifies the previously broken line after 
		 *	which breaking is to commence. Can be null when breaking the first line.  
		 * @param width Specifies the desired width of the line in pixels. The 
		 * 	actual width may be less.  
		 * @param lineOffset An optional parameter which specifies the difference in 
		 *	pixels between the origin of the line and the origin of the tab stops. This can be used when lines are not aligned, 
		 * 	but it is desirable for their tabs to be so. 
		 * @param fitSomething An optional parameter that instructs the runtime to fit at least one 
		 * 	character into the text line, no matter what width has been specified (even if width is zero or negative, which 
		 * 	would otherwise result in an exception being thrown).  
		 * @return The recreated TextLine instance.
		 *  
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
		private function recreateTextLine(textBlock:TextBlock, argsArray:Array):TextLine
		{
			var swfContext:ISWFContext = _swfContext ? _swfContext : BaseCompose.globalSWFContext;
			CONFIG::debug { assert(Configuration.playerEnablesArgoFeatures,"Bad call to createTextLine"); }

			if (_composeRecycledInPlaceLines < _composedLines.length)
			{
				CONFIG::debug {assert(argsArray[0] != _composedLines[_composeRecycledInPlaceLines],"Bad args"); }
				TextLineRecycler.addLineForReuse(argsArray[0]);	// not going to use this one
				argsArray[0] = _composedLines[_composeRecycledInPlaceLines++];
			}
			return swfContext.callInContext(textBlock["recreateTextLine"],textBlock,argsArray);
		}

		
		/** Returns the current ISelectionManager instance. Converts to TextFlow instance and creates one if necessary. 
		 *
		 * @return  the interaction manager for this TextContainerManager instance.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
	 	 * @see flashx.textLayout.edit.ISelectionManager ISelectionManager
	 	 */
		public function beginInteraction():ISelectionManager
		{
			++_interactionCount;
			if (_composeState != COMPOSE_COMPOSER)
				convertToTextFlowWithComposer();
			return _textFlow.interactionManager;
		}
		
		/** Terminates interaction. 
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @see flashx.textLayout.edit.ISelectionManager ISelectionManager
	 	 */
		
		public function endInteraction():void
		{
			--_interactionCount;
		}
		
		/** Call this if you are editing, and want to reset the undo manager used for editing.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 */
		public function invalidateUndoManager():void
		{
			if (_editingMode == EditingMode.READ_WRITE)
				invalidateInteractionManager(true);
		}
		
		
		/** Call this if you change the selection formats (SelectionFormat) and want the interactionManager 
		 * to update. 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
	 	 */
		public function invalidateSelectionFormats():void
		{
			invalidateInteractionManager();
		}
		
		/** The interactionManager is invalid - update it. Clients should call this if they change the 
		 * selectionFormats.  Its called automatically if editingMode is changed. */
		private function invalidateInteractionManager(alwaysRecreateManager:Boolean = false):void
		{
			if (_composeState == COMPOSE_COMPOSER)
			{
				var interactionManager:ISelectionManager = _textFlow.interactionManager;
				var activePos:int = interactionManager ? interactionManager.activePosition : -1
				var anchorPos:int = interactionManager ? interactionManager.anchorPosition : -1;

				if (_editingMode == EditingMode.READ_ONLY)
				{
					if (interactionManager)
						_textFlow.interactionManager = null;
				}
				else if (_editingMode == EditingMode.READ_WRITE)
				{
					if (alwaysRecreateManager || interactionManager == null || interactionManager.editingMode == EditingMode.READ_SELECT)
					{
						_textFlow.interactionManager = createEditManager(getUndoManager());
						if (_textFlow.interactionManager is SelectionManager)
							SelectionManager(_textFlow.interactionManager).cloneSelectionFormatState(interactionManager);
					}
				}
				else if (_editingMode == EditingMode.READ_SELECT)
				{
					if (alwaysRecreateManager || interactionManager == null || interactionManager.editingMode == EditingMode.READ_WRITE)
					{
						_textFlow.interactionManager = createSelectionManager();
						if (_textFlow.interactionManager is SelectionManager)
							SelectionManager(_textFlow.interactionManager).cloneSelectionFormatState(interactionManager);
					}
				}
				
				interactionManager = _textFlow.interactionManager;
				if (interactionManager)
				{
					interactionManager.unfocusedSelectionFormat  = getUnfocusedSelectionFormat();
					interactionManager.focusedSelectionFormat    = getFocusedSelectionFormat();
					interactionManager.inactiveSelectionFormat = getInactiveSelectionFormat();
					interactionManager.selectRange(anchorPos,activePos);
				}				
			}
		}
		
		/**Create a selection manager to use for selection. Override this method if you have a custom SelectionManager that you
		 * want to use in place of the default.
		 *
		 * @return	a new SelectionManager instance.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
		 */
		protected function createSelectionManager():ISelectionManager
		{
			return new SelectionManager();
		}
		
		/**Create an edit manager to use for editing. Override this method if you have a custom EditManager that you
		 * want to use in place of the default.
		 *
		 * @param  an IUndoManager instance for the EditManager being created.
		 * @return	the editing manager for this TextContainerManager instance.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
		 */
		protected function createEditManager(undoManager:flashx.undo.IUndoManager):IEditManager
		{
			return new EditManager(undoManager);
		}
		
		private function getController():TMContainerController
		{ return _textFlow.flowComposer.getControllerAt(0) as TMContainerController; }

		/** @private */
		tlf_internal var _composedLines:Array = [];
		
		/** Return the TextLine at the index from array of composed lines.
		 *
		 * @param index	Finds the line at this index position in the text.
		 *
		 * @return 	the TextLine that occurs at the specified index.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
		 */
		public function getLineAt(index:int):TextLine
		{ 
			// note: this method is not reliable for damaged text
			if (_composeState == COMPOSE_FACTORY)
			{
				// watch out for the empty TCM optimization and make a TextLine
				if (_sourceState == SOURCE_STRING && _text.length == 0 && !_damaged && _composedLines.length == 0)
				{					
					if (_needsRedraw)
						compose();
					else
						updateContainer();
					CONFIG::debug { assert(_composeState == COMPOSE_FACTORY,"no longer a factory??"); }
				}
				return _composedLines[index];
			}
			var tfl:TextFlowLine = _textFlow.flowComposer.getLineAt(index);
			return tfl ? tfl.getTextLine(true) : null;
		}
		
		/** @copy flashx.textLayout.compose.IFlowComposer#numLines 
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
		public function get numLines():int
		{ 
			// note: this method is not reliable for damaged text
			if (_composeState == COMPOSE_COMPOSER)
				return _textFlow.flowComposer.numLines;
			// watch out for possibly optimized zero length text
			if (_sourceState == SOURCE_STRING && _text.length == 0)
				return 1;
			return _composedLines.length; 
		}
		
		/** @private 
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		tlf_internal function getActualNumLines():int
		{ 
			if (_composeState != COMPOSE_COMPOSER)
				convertToTextFlowWithComposer();
			// composes all lines
			_textFlow.flowComposer.composeToPosition();
			return _textFlow.flowComposer.numLines;
		}
		
		/** @private */
		tlf_internal function clearComposedLines():void
		{
			if (_composedLines)
				_composedLines.length = 0;
		}
		
		private function populateComposedLines(displayObject:DisplayObject):void
		{
			_composedLines.push(displayObject);
		}
		
		// TODO FOR ARGO - think about moving these variables into a separate helper class 
		private var _composeRecycledInPlaceLines:int;
		private var _composePushedLines:int;
		private function populateAndRecycleComposedLines(object:DisplayObject):void
		{
			var textLine:TextLine = object as TextLine;
			if (textLine)
			{
				CONFIG::debug { assert(_composePushedLines >= _composedLines.length || _composedLines[_composePushedLines] == textLine,"mismatched recycled textline"); }
				if (_composePushedLines >= _composedLines.length)
					_composedLines.push(textLine);
			}
			else	// this is the background color and goes at the head of the list
				_composedLines.splice(0,0,object);
			_composePushedLines++;
		}		
		
		static private var _expectedFactoryCompose:SimpleCompose;

		
		/** Composes the container text; calls either the factory or <code>updateAllControllers()</code>.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
		public function compose():void
		{
			if (_composeState == COMPOSE_COMPOSER)
				_textFlow.flowComposer.compose();
			else if (_damaged)
			{
				if (_sourceState == SOURCE_TEXTFLOW && _textFlow.mustUseComposer())
				{
					convertToTextFlowWithComposer(false);
					_textFlow.flowComposer.compose();
					return;
				}
				else
				{
					var callback:Function;
					if (Configuration.playerEnablesArgoFeatures)
					{
						// while the first thing in the array is not a TextLine its the background color OR its some floats OR something else from the last compose - remove it
						for (;;)
						{
							var firstObj:Object = _composedLines[0];
							if (firstObj == null || (firstObj is TextLine))
								break;
							_composedLines.splice(0,1);
						}
						_composeRecycledInPlaceLines = 0;
						_composePushedLines = 0;
						callback = populateAndRecycleComposedLines;
					}
					else
					{
						clearComposedLines();
						callback = populateComposedLines;
					}
					var inputManagerFactory:TextLineFactoryBase = (_sourceState == SOURCE_STRING) ? inputManagerStringFactory(_config) : inputManagerTextFlowFactory();
					inputManagerFactory.verticalScrollPolicy = _verticalScrollPolicy;
					inputManagerFactory.horizontalScrollPolicy = _horizontalScrollPolicy;
					inputManagerFactory.compositionBounds = new Rectangle(0,0,_compositionWidth,_compositionHeight);
					inputManagerFactory.swfContext = Configuration.playerEnablesArgoFeatures ? this : _swfContext;
					
					// compose can recurse for composing.  this sets up the swfContext so it doesn't recycle a line into a numberline
					_expectedFactoryCompose = TextLineFactoryBase.peekFactoryCompose();
					if (_sourceState == SOURCE_STRING)
					{
						var stringFactory:StringTextLineFactory = inputManagerFactory as StringTextLineFactory;
						if (!_stringFactoryTextFlowFormat)
						{
							if (_hostFormat == null)
								_stringFactoryTextFlowFormat = _config.textFlowInitialFormat;
							else
							{
								// mini cascade of initialFormat onto the hostFormat
								var format:TextLayoutFormat = new TextLayoutFormat(_hostFormat);
								TextLayoutFormat.resetModifiedNoninheritedStyles(format);
								var holderStyles:Object = (_config.textFlowInitialFormat as TextLayoutFormat).getStyles();
								for (var key:String in holderStyles)
								{
									var val:* = holderStyles[key];
									format[key] = (val !== FormatValue.INHERIT) ? val : _hostFormat[key];
								}
								_stringFactoryTextFlowFormat = format;
							}
						}
						if (!TextLayoutFormat.isEqual(stringFactory.textFlowFormat,_stringFactoryTextFlowFormat))
							stringFactory.textFlowFormat = _stringFactoryTextFlowFormat;
						stringFactory.text = _text;
						stringFactory.createTextLines(callback);
					}
					else
					{
						var factory:TCMTextFlowTextLineFactory = inputManagerFactory as TCMTextFlowTextLineFactory;
						factory.tcm = this;
						factory.createTextLines(callback,_textFlow);
						factory.tcm = null;
					}
					inputManagerFactory.swfContext = null;	// release any references to the swfContext
					_expectedFactoryCompose = null;
							
					if (Configuration.playerEnablesArgoFeatures)
						_composedLines.length = _composePushedLines;

					var bounds:Rectangle = inputManagerFactory.getContentBounds();
					
					_contentLeft   = bounds.x;
					_contentTop    = bounds.y;
					_contentWidth  = bounds.width;
					_contentHeight = bounds.height;
					_damaged = false;
					
					// generate a compositionComplete event.  Note that the last composed position isn't known
					if (hasEventListener(CompositionCompleteEvent.COMPOSITION_COMPLETE))
						dispatchEvent(new CompositionCompleteEvent(CompositionCompleteEvent.COMPOSITION_COMPLETE,false,false,_textFlow,0,-1));						
				}
				_needsRedraw = true;
			}

		}
		
		/** Updates the display; calls either the factory or updateAllControllers().
		 * 
		 * @return true if anything changed.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
		public function updateContainer():Boolean
		{
			if (_composeState == COMPOSE_COMPOSER)
				return _textFlow.flowComposer.updateAllControllers();
			
			compose();
			
			// depending on edits the Flow may now have a composer
			if (_composeState == COMPOSE_COMPOSER)
			{
				_textFlow.flowComposer.updateAllControllers();
				return true;
			}
				
			if (!_needsRedraw)
				return false;
			
			factoryUpdateContainerChildren();									
			drawBackgroundAndSetScrollRect(0,0);
					
			if (_handlersState == HANDLERS_NOTADDED)
				addActivationEventListeners();
	
			// generate a updateComplete event.  Note that the controller isn't known
			if (hasEventListener(UpdateCompleteEvent.UPDATE_COMPLETE))
				dispatchEvent(new UpdateCompleteEvent(UpdateCompleteEvent.UPDATE_COMPLETE,false,false,null));	
			
			_needsRedraw = false;
			return true;	// things changed
		}
		
		/** @private */
		tlf_internal function factoryUpdateContainerChildren():void
		{
			var textObject:DisplayObject; 	// scratch - TextLines and background shapes
			if (Configuration.playerEnablesArgoFeatures)
			{
				// while the first child in the container is a Shape - its the background color OR a Float OR something else - lose it
				while (_container.numChildren != 0)
				{
					textObject = _container.getChildAt(0);
					if (textObject is TextLine)
						break;
					_container.removeChildAt(0);
				}
				
				// add leading children _composedLines that are not TextLines into the Container
				for (var idx:int = 0; idx < _composedLines.length; idx++)
				{
					textObject = _composedLines[idx];
					if (textObject is TextLine)
						break;
					_container.addChildAt(textObject,idx);
				}
				
				// expect the leading lines are reused
				while (_container.numChildren < _composedLines.length)
					_container.addChild(_composedLines[_container.numChildren]);
				// recycle any trailing lines
				while (_container.numChildren > _composedLines.length)
				{
					var textLine:TextLine = _container.getChildAt(_composedLines.length) as TextLine;
					_container.removeChildAt(_composedLines.length);
					if (textLine)
					{
						// lines were rebroken but aren't being displayed
						if (textLine.validity == TextLineValidity.VALID)
							textLine.textBlock.releaseLines(textLine,textLine.textBlock.lastLine);
						textLine.userData = null;
						TextLineRecycler.addLineForReuse(textLine);
					}
				}
			}
			else
			{
				clearContainerChildren(false);
				
				for each (textObject in _composedLines)
					_container.addChild(textObject);
				
				clearComposedLines();
			}
		}
		
		private function addActivationEventListeners():void
		{	
			var newState:int =  HANDLERS_NONE;
			
			if (_composeState == COMPOSE_FACTORY)
			{
				if (_editingMode == EditingMode.READ_ONLY)
					newState = HANDLERS_MOUSEWHEEL;
				else
					newState = _handlersState == HANDLERS_NOTADDED ? HANDLERS_CREATION : HANDLERS_ACTIVE;
			}
			
			if (newState == _handlersState)
				return;
			
			removeActivationEventListeners();
				
			if (newState == HANDLERS_CREATION)
			{
				_container.addEventListener(FocusEvent.FOCUS_IN, requiredFocusInHandler);				
				_container.addEventListener(MouseEvent.MOUSE_OVER, requiredMouseOverHandler);
			}
			else if (newState == HANDLERS_ACTIVE)
			{
				_container.addEventListener(FocusEvent.FOCUS_IN, requiredFocusInHandler);				
				_container.addEventListener(MouseEvent.MOUSE_OVER, requiredMouseOverHandler);
				_container.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
				_container.addEventListener(MouseEvent.MOUSE_OUT,  mouseOutHandler);
				_container.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
			//	_container.addEventListener(IMEEvent.IME_START_COMPOSITION, imeStartCompositionHandler);
			// attach by literal event name to avoid Argo dependency
				_container.addEventListener("imeStartComposition", imeStartCompositionHandler);
				
				// If TCM's getContextMenu returns null assume client has control of the contextMenu
				if (getContextMenu() != null)
					_container.contextMenu = _contextMenu;
				if (_container.contextMenu)
					_container.contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, menuSelectHandler);
		            
		        _container.addEventListener(Event.SELECT_ALL, editHandler);
			}
			else if (newState == HANDLERS_MOUSEWHEEL)
				_container.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);				
			
			_handlersState = newState;
		}
		
		// The ContextMenu to be used.  The idea is that this is undefined until createContextMenu is called and then 
		// createContextMenu is only called once and the result is shared with the ContainerController when it gets created
		private var _contextMenu:*;
		
		/** @private  Returns the already created contextMenu.  If not created yet create it.  */
		tlf_internal function getContextMenu():ContextMenu
		{
			if (_contextMenu === undefined)
				_contextMenu = createContextMenu();
			return _contextMenu;
		}

		private function removeActivationEventListeners():void
		{
			if (_handlersState == HANDLERS_CREATION)
			{
				CONFIG::debug { assert(_composeState != COMPOSE_COMPOSER,"Bad call to removeActivationEventListeners"); }
				_container.removeEventListener(FocusEvent.FOCUS_IN, requiredFocusInHandler);				
				_container.removeEventListener(MouseEvent.MOUSE_OVER, requiredMouseOverHandler);
			}
			else if (_handlersState == HANDLERS_ACTIVE)
			{
				CONFIG::debug { assert(_composeState != COMPOSE_COMPOSER,"Bad call to removeActivationEventListeners"); }
				_container.removeEventListener(FocusEvent.FOCUS_IN, requiredFocusInHandler);				
				_container.removeEventListener(MouseEvent.MOUSE_OVER, requiredMouseOverHandler);
				_container.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
				_container.removeEventListener(MouseEvent.MOUSE_OUT,  mouseOutHandler);
				_container.removeEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
			//	_container.removeEventListener(IMEEvent.IME_START_COMPOSITION, imeStartCompositionHandler);
			// detach by literal event name to avoid Argo dependency
				_container.removeEventListener("imeStartComposition", imeStartCompositionHandler);
				// if _contextMenu is set then this TCM created the contextMenu and is manging it
				if (_container.contextMenu)
					_container.contextMenu.removeEventListener(ContextMenuEvent.MENU_SELECT, menuSelectHandler);
				// otherwise client is managing it
				if (_contextMenu)	
					_container.contextMenu = null;

		        _container.removeEventListener(Event.SELECT_ALL, editHandler);
			}
			else if (_handlersState == HANDLERS_MOUSEWHEEL)
			{
				CONFIG::debug { assert(_composeState != COMPOSE_COMPOSER,"Bad call to removeActivationEventListeners"); }
				_container.removeEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);		
			}

			_handlersState = HANDLERS_NOTADDED;
		}
		
		private function addTextFlowListeners():void
		{
			for each (var event:String in eventList)			
				_textFlow.addEventListener(event,dispatchEvent);
		}
		
		private function removeTextFlowListeners():void
		{
			for each (var event:String in eventList)			
				_textFlow.removeEventListener(event,dispatchEvent);
			_handlersState = HANDLERS_NONE;
		}
		
		/**
		 * @copy flash.events.IEventDispatcher#dispatchEvent()
		 * @private
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
 		 */
		public override function dispatchEvent(event:Event):Boolean
		{
			if (event.type == DamageEvent.DAMAGE)
			{
				_textDamaged = true;
				if (_composeState == COMPOSE_FACTORY)
					_damaged = true;
			}
			else if (event.type == FlowOperationEvent.FLOW_OPERATION_BEGIN)
			{
				if (_container.mouseChildren == false)
					_container.mouseChildren = true;
			}
			var result:Boolean = super.dispatchEvent(event);
			if (!result)
				event.preventDefault();
			return result;
		}
		
		/** @private */
		tlf_internal function clearContainerChildren(recycle:Boolean):void
		{
			while(_container.numChildren)
			{
				var textLine:TextLine = _container.getChildAt(0) as TextLine;
				_container.removeChildAt(0);
				if (textLine)
				{
					// releasing all textLines so release each still connected textBlock
					if (textLine.validity != TextLineValidity.INVALID && textLine.validity != TextLineValidity.STATIC)
					{
						var textBlock:TextBlock = textLine.textBlock;
						CONFIG::debug { Debugging.traceFTECall(null,textBlock,"releaseLines",textBlock.firstLine, textBlock.lastLine); }	
						textBlock.releaseLines(textBlock.firstLine,textBlock.lastLine);
					}					
					if (recycle)
					{
						textLine.userData = null;	// clear any userData
						TextLineRecycler.addLineForReuse(textLine);
					}
				}
			}
		}
		
		private function convertToTextFlow():void
		{
			CONFIG::debug { assert(_sourceState != SOURCE_TEXTFLOW,"bad call to convertToTextFlow"); }
									
			_textFlow = new TextFlow(_config);
			_textFlow.hostFormat = _hostFormat;
			if(_swfContext)
			{
				_textFlow.flowComposer.swfContext = _swfContext;
			}
	
			var p:ParagraphElement = new ParagraphElement();
			_textFlow.addChild(p)
			var s:SpanElement = new SpanElement();
			s.text = _text;
			p.addChild(s);
			_sourceState = SOURCE_TEXTFLOW;
			addTextFlowListeners();			
		}
				
		/** @private */
		tlf_internal function convertToTextFlowWithComposer(callUpdateContainer:Boolean = true):void
		{
			removeActivationEventListeners();
			
			if (_sourceState != SOURCE_TEXTFLOW)
				convertToTextFlow();
			
			if (_composeState != COMPOSE_COMPOSER)
			{
				clearContainerChildren(true);
				clearComposedLines();
				var controller:TMContainerController = new TMContainerController(_container,_compositionWidth,_compositionHeight,this);
				_textFlow.flowComposer = new StandardFlowComposer();
				_textFlow.flowComposer.addController(controller);
				_textFlow.flowComposer.swfContext = _swfContext;
				_composeState = COMPOSE_COMPOSER;
				
				invalidateInteractionManager();
				if (callUpdateContainer)
					updateContainer();
			}
		}
		
		private function get effectiveBlockProgression():String
		{
			if (_textFlow)
				return _textFlow.computedFormat.blockProgression;
			return _hostFormat && _hostFormat.blockProgression && _hostFormat.blockProgression != FormatValue.INHERIT ? _hostFormat.blockProgression : BlockProgression.TB;
		}
		
		/* CONFIG::debug private static function doTrace(msg:String):void
		{ trace(msg); } */
		
		private function removeIBeamCursor():void
		{
			if (_ibeamCursorSet)
			{
				Mouse.cursor = Configuration.getCursorString(configuration, MouseCursor.AUTO);
				_ibeamCursorSet = false;
			}
		}
		
		private var _hasScrollRect:Boolean = false;
		
		/** 
		 * Specifies whether this container has attached a ScrollRect object. Value is <code>true</code>
		 * or <code>false</code>. A display object is cropped to the size defined by the scroll rectangle, and 
		 * it scrolls within the rectangle when you change the x and y properties of the scrollRect object. 
		 *
		 * <p>This property enables a client to test for a ScrollRect object without accessing 
		 * the DisplayObject.scrollRect property, which can have side effects in some cases.</p> 
		 *
		 * @return true if the controller has attached a ScrollRect instance.
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 *
		 * @see #drawBackgroundAndSetScrollRect 
		 */
		private function get hasScrollRect():Boolean
		{ return _hasScrollRect; }
		private function set hasScrollRect(value:Boolean):void
		{ _hasScrollRect = value; }
		
		/**   
		 * Returns <code>true</code> if it has filled in the container's scrollRect property.  
		 * This method enables you to test whether <code>scrollRect</code> is set without actually accessing the <code>scrollRect</code> property 
		 * which can possibly create a  performance issue. 
		 * <p>Override this method to draw a background or a border.  Overriding this method can be tricky as the scrollRect <bold>must</bold> 
		 * be set as specified.</p>
		 * 
		 * @param scrollX The starting horizontal position of the scroll rectangle.
		 * @param scrollY The starting vertical position of the scroll rectangle.
		 * 
		 * @return 	<code>true</code> if it has created the <code>scrollRect</code> object.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
		public function drawBackgroundAndSetScrollRect(scrollX:Number,scrollY:Number):Boolean
		{
			var cont:Sprite = this.container;

 			var contentWidth:Number;
			var contentHeight:Number;
			if (_composeState == COMPOSE_FACTORY)
			{
				contentWidth = _contentWidth;
				contentHeight = _contentHeight;
			}
			else
			{
				var controller:ContainerController = getController();
				contentWidth = controller.contentWidth;
				contentHeight = controller.contentHeight;
			}
			var width:Number;
			if (isNaN(compositionWidth))
			{
				var contentLeft:Number = (_composeState == COMPOSE_FACTORY) ? _contentLeft : controller.contentLeft;
				width = contentLeft + contentWidth - scrollX;
			}
			else
				width = compositionWidth;
			var height:Number;
			if (isNaN(compositionHeight))
			{ 
				var contentTop:Number = (_composeState == COMPOSE_FACTORY) ? _contentTop : controller.contentTop;
				height = contentTop + contentHeight - scrollY;
			}
			else
				height = compositionHeight;
			
			if (scrollX == 0 && scrollY == 0 && contentWidth <= width && contentHeight <= height)
			{
				// skip the scrollRect
				if (_hasScrollRect)
				{
					cont.scrollRect = null;
					_hasScrollRect = false;					
				}
			}
			else
			{
				cont.scrollRect = new Rectangle(scrollX, scrollY, width, height);
				_hasScrollRect = true;
				
				// adjust to the values actually in the scrollRect
				scrollX = cont.scrollRect.x;
				scrollY = cont.scrollRect.y;
				width = cont.scrollRect.width;
				height = cont.scrollRect.height;
			}
			
	        // NOTE: must draw a background for interaction support - even it if is 100% transparent
	        var s:Sprite = cont as Sprite;
	        if (s)
	        {
				s.graphics.clear();
				s.graphics.beginFill(0, 0); 
		       	s.graphics.drawRect(scrollX,scrollY,width,height);
		        s.graphics.endFill();
		    }
	
	        return _hasScrollRect;
		}
		
		/** Returns the focusedSelectionFormat - by default get it from the configuration.
		 * This can be overridden in the subclass to supply a different SelectionFormat
		 */
		protected function getFocusedSelectionFormat():SelectionFormat
		{
			return _config.focusedSelectionFormat;
		}
		
		/** Returns the inactiveSelectionFormat - by default get it from the configuration 
		 * This can be overridden in the subclass to supply a different SelectionFormat
		 */
		protected function getInactiveSelectionFormat():SelectionFormat
		{
			return _config.inactiveSelectionFormat;
		}
		
		/** Returns the unfocusedSelectionFormat - by default get it from the configuration 
		 * You can override this method in the subclass to supply a different SelectionFormat.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		protected function getUnfocusedSelectionFormat():SelectionFormat
		{
			return _config.unfocusedSelectionFormat;
		}
		
		/** 
		 * Returns the undo manager to use. By default, creates a unique undo manager. 
		 * You can override this method in the subclass if you want to customize the undo manager
		 * (for example, to use a shared undo manager for multiple TextContainerManager instances).
		 *
		 * @return 	new IUndoManager instance.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
	 	 */
		 
		protected function getUndoManager():IUndoManager
		{
			return new UndoManager();
		}
						
		/** Creates a ContextMenu for the TextContainerManager. Use the methods of the ContextMenu 
		 *  class to add items to the menu. 
		 * <p>You can override this method to define a custom context menu.</p>
		 *
		 * @return 	the created context menu.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @see flash.ui.ContextMenu ContextMenu
		 */
		protected function createContextMenu():ContextMenu
		{
			return ContainerController.createDefaultContextMenu();
		}
		/** @copy flashx.textLayout.container.ContainerController#editHandler()
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 		 * @langversion 3.0
 		 *
 		 * @see flash.events.Event Event
		 */	
		public function editHandler(event:Event):void
		{
			if (_composeState == COMPOSE_FACTORY)
			{
				convertToTextFlowWithComposer();
				getController().editHandler(event);
				_textFlow.interactionManager.setFocus();
			}
			else
				getController().editHandler(event);
		}
		
		/** @copy flashx.textLayout.container.ContainerController#keyDownHandler() 
		*
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		* @see flash.events.KeyboardEvent#KEY_DOWN KeyboardEvent.KEY_DOWN
		*/	
		public function keyDownHandler(event:KeyboardEvent):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().keyDownHandler(event);
		}
		
		/** @copy flashx.textLayout.container.ContainerController#keyUpHandler().
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		* @see flash.events.KeyboardEvent#KEY_UP KeyboardEvent.KEY_UP
		*/	
		public function keyUpHandler(event:KeyboardEvent):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().keyUpHandler(event);
		}

		/** @copy flashx.textLayout.container.ContainerController#keyFocusChangeHandler().
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 * 	@param	event	the FocusChange event
		 */	
		public function keyFocusChangeHandler(event:FocusEvent):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().keyFocusChangeHandler(event);
		}
		
		/** @copy flashx.textLayout.container.ContainerController#textInputHandler()
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		* @see flash.events.TextEvent#TEXT_INPUT TextEvent.TEXT_INPUT
		*/
		public function textInputHandler(event:TextEvent):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().textInputHandler(event);
		}

		/** Processes the <code>IME_START_COMPOSITION</code> event when the client manages events.
		 *
		 * @param event  The IMEEvent object.
		 *
		 * @playerversion Flash 10.1
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 *
		 * @see flash.events.IMEEvent#IME_START_COMPOSITION IMEEvent.IME_START_COMPOSITION
		 */
		public function imeStartCompositionHandler(event:IMEEvent):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().imeStartCompositionHandler(event);
		}
		
		/** Processes the <code>SOFT_KEYBOARD_ACTIVATING</code> event when the client manages events.
		 *
		 * @param event  The SoftKeyboardEvent object.
		 *
		 * @playerversion Flash 10.2
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 *
		 * @see flash.events.SoftKeyboardEvent#SOFT_KEYBOARD_ACTIVATING SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATING
		 */
		public function softKeyboardActivatingHandler(event:Event):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().softKeyboardActivatingHandler(event);
		}
		
		/** @copy flashx.textLayout.container.ContainerController#mouseDownHandler()
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		* @see flash.events.MouseEvent#MOUSE_DOWN MouseEvent.MOUSE_DOWN
		*/	
		public function mouseDownHandler(event:MouseEvent):void
		{
			// doTrace("IM:mouseDownHandler");
			// before the mouseDown do a mouseOver
			if (_composeState == COMPOSE_FACTORY)
			{
				CONFIG::debug { assert(event.currentTarget == this.container,"TextContainerManager:mouseDownHandler - unexpected currentTarget"); }
				convertToTextFlowWithComposer();
				getController().requiredFocusInHandler(null);
				getController().requiredMouseOverHandler(event.target != container ? new RemappedMouseEvent(event) : event);
				if (_hasFocus)
					getController().requiredFocusInHandler(null);
				getController().requiredMouseDownHandler(event);
			}
			else
				getController().mouseDownHandler(event);
		}

		/** @copy flashx.textLayout.container.ContainerController#mouseMoveHandler()
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		* @see flash.events.MouseEvent#MOUSE_MOVE MouseEvent.MOUSE_MOVE
		*/	
		public function mouseMoveHandler(event:MouseEvent):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().mouseMoveHandler(event);
		}
		
		/** @copy flashx.textLayout.container.ContainerController#mouseUpHandler()
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		* @see flash.events.MouseEvent#MOUSE_UP MouseEvent.MOUSE_UP
		*/	
		public function mouseUpHandler(event:MouseEvent):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().mouseUpHandler(event);
		}
		
		/** @copy flashx.textLayout.container.ContainerController#mouseDoubleClickHandler()
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		* @see flash.events.MouseEvent#DOUBLE_CLICK MouseEvent.DOUBLE_CLICK
		*/	
		public function mouseDoubleClickHandler(event:MouseEvent):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().mouseDoubleClickHandler(event);
		}

		/** @private Process a mouseOver event.
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
		*/			
		tlf_internal final function requiredMouseOverHandler(event:MouseEvent):void
		{
			if (_composeState == COMPOSE_FACTORY)
				mouseOverHandler(event);
			if (_composeState == COMPOSE_COMPOSER)
				getController().requiredMouseOverHandler(event);
		}
		

		/** Process a mouseOver event.
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		* @see flash.events.MouseEvent#MOUSE_OVER MouseEvent.MOUSE_OVER
		*/			
		public function mouseOverHandler(event:MouseEvent):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().mouseOverHandler(event);
			else
			{
				// doTrace("IM:mouseOverHandler");
				if (effectiveBlockProgression != BlockProgression.RL)
				{
					Mouse.cursor = MouseCursor.IBEAM;
					_ibeamCursorSet = true;
				}	
				addActivationEventListeners();
			}
		}
		/** @copy flashx.textLayout.container.ContainerController#mouseOutHandler()
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		* @see flash.events.MouseEvent#MOUSE_OUT MouseEvent.MOUSE_OUT
		*/					
		public function mouseOutHandler(event:MouseEvent):void
		{
			// doTrace("IM:mouseOutHandler");
			if (_composeState == COMPOSE_FACTORY)
				removeIBeamCursor();
			else
				getController().mouseOutHandler(event);
		}		
		/** @copy flashx.textLayout.container.ContainerController#focusInHandler()
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		* @see flash.events.FocusEvent#FOCUS_IN FocusEvent.FOCUS_IN
		*/

		
		/** Process a focusIn event.
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
		*/
		public function focusInHandler(event:FocusEvent):void
		{
			_hasFocus = true;
			if (_composeState == COMPOSE_COMPOSER)
				getController().focusInHandler(event);
		}
		
		/** @private hook to get at requiredFocusOutHandler as needed */
		tlf_internal function requiredFocusOutHandler(event:FocusEvent):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().requiredFocusOutHandler(event);
		}
		/** @copy flashx.textLayout.container.ContainerController#focusOutHandler()
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		* @see flash.events.FocusEvent#FOCUS_OUT FocusEvent.FOCUS_OUT
		*/
		public function focusOutHandler(event:FocusEvent):void
		{
			_hasFocus = false;
			if (_composeState == COMPOSE_COMPOSER)
				getController().focusOutHandler(event);
		}

		/** @copy flashx.textLayout.container.ContainerController#activateHandler()
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		* @see flash.events.Event#ACTIVATE Event.ACTIVATE
		*/				
		public function activateHandler(event:Event):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().activateHandler(event);
		}		
		/** @copy flashx.textLayout.container.ContainerController#deactivateHandler()
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		* @see flash.events.Event#DEACTIVATE Event.DEACTIVATE
		*/				
		public function deactivateHandler(event:Event):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().deactivateHandler(event);
		}
		
		/** @copy flashx.textLayout.container.ContainerController#focusChangeHandler()
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		*
 		* @see flash.events.FocusEvent#KEY_FOCUS_CHANGE FocusEvent.KEY_FOCUS_CHANGE
		* @see flash.events.FocusEvent#MOUSE_FOCUS_CHANGE FocusEvent.MOUSE_FOCUS_CHANGE
		*/				
		public function focusChangeHandler(event:FocusEvent):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().focusChangeHandler(event);
		}
		
		/** @copy flashx.textLayout.container.ContainerController#menuSelectHandler()
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		*
 		* @see flash.events.ContextMenuEvent#MENU_SELECT ContextMenuEvent.MENU_SELECT
		*/				
		public function menuSelectHandler(event:ContextMenuEvent):void
		{
			if (_composeState == COMPOSE_FACTORY)
			{
				// there is no selection
				var contextMenu:ContextMenu = _container.contextMenu as ContextMenu;
				if (contextMenu)
				{
					var cbItems:ContextMenuClipboardItems = contextMenu.clipboardItems;
					cbItems.selectAll = _editingMode != EditingMode.READ_ONLY;
					cbItems.clear = false;
					cbItems.copy = false;
					cbItems.cut = false;
					cbItems.paste = false;
				}
			}
			else
				getController().menuSelectHandler(event);			
		}
		
		/** @copy flashx.textLayout.container.ContainerController#mouseWheelHandler()
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
 		*
 		* @see flash.events.MouseEvent#MOUSE_WHEEL MouseEvent.MOUSE_WHEEL
		*/				
		public function mouseWheelHandler(event:MouseEvent):void
		{
			if (event.isDefaultPrevented())
				return;

			if (_composeState == COMPOSE_FACTORY)
			{
				convertToTextFlowWithComposer();
				getController().requiredMouseOverHandler(event);
			}
			getController().mouseWheelHandler(event);
		}

		
		/** @private required FocusIn handler.  Clients override focusInHandler
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 		* @langversion 3.0
		*/
		tlf_internal final function requiredFocusInHandler(event:FocusEvent):void
		{			
			// doTrace("IM:focusInHandler");
			if (_composeState == COMPOSE_FACTORY)
			{
				addActivationEventListeners();
				focusInHandler(event);
			}			
			if (_composeState == COMPOSE_COMPOSER)
				getController().requiredFocusInHandler(event);
		}
		
		/** 
		 * Called to request clients to begin the forwarding of mouseup and mousemove events from outside a security sandbox.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 */
		public function beginMouseCapture():void
		{ }
		/** 
		 * Called to inform clients that the the forwarding of mouseup and mousemove events from outside a security sandbox is no longer needed.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 */
		public function endMouseCapture():void
		{ }
		/** Client call to forward a mouseUp event from outside a security sandbox.  Coordinates of the mouse up are not needed.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 */
		public function mouseUpSomewhere(e:Event):void
		{
			if (_composeState == COMPOSE_COMPOSER)
				getController().mouseUpSomewhere(e);
		}
		/** Client call to forward a mouseMove event from outside a security sandbox.  Coordinates of the mouse move are not needed.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 */		
		public function mouseMoveSomewhere(e:Event):void
		{ 
			if (_composeState == COMPOSE_COMPOSER)
				getController().mouseUpSomewhere(e);
		}
	
		/** @private
		 * Gets the index at which the first text line must appear in its parent.
		 * The default implementation of this method, which may be overriden, returns the child index 
		 * of the first <code>flash.text.engine.TextLine</code> child of <code>container</code>
		 * if one exists, and that of the last child of <code>container</code> otherwise. 
		 * 
		 * @return the index at which the first text line must appear in its parent.
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flash.text.engine.TextLine
		 * @see #container
		 */	
		tlf_internal function getFirstTextLineChildIndex():int
		{			
			// skip past any non-TextLine children below the text in the container,
			// This also means that in a container devoid of text, we will always
			// populate the text starting at index container.numChildren, which is intentional.
			var firstTextLine:int;
			for(firstTextLine = 0; firstTextLine<_container.numChildren; ++firstTextLine)
			{
				if(_container.getChildAt(firstTextLine) is TextLine)
				{
					break;
				}
			}
			return firstTextLine;
		}
		
		/** @private
		 * Adds a <code>flash.text.engine.TextLine</code> object as a descendant of <code>container</code>.
		 * The default implementation of this method, which may be overriden, adds the object
		 * as a direct child of <code>container</code> at the specified index.
		 * 
		 * @param textLine the <code>flash.text.engine.TextLine</code> object to add
		 * @param index insertion index of the text line in its parent 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flash.text.engine.TextLine
		 * @see #container
		 * 
		 */	
		tlf_internal function addTextLine(textLine:TextLine, index:int):void
		{ 
			_container.addChildAt(textLine, index);
		}
		
		/** @private
		 * Removes a <code>flash.text.engine.TextLine</code> object from its parent. 
		 * The default implementation of this method, which may be overriden, removes the object
		 * from <code>container</code> if it is a direct child of the latter.
		 * 
		 * This method may be called even if the object is not a descendant of <code>container</code>.
		 * Any implementation of this method must ensure that no action is taken in this case.
		 * 
		 * @param textLine the <code>flash.text.engine.TextLine</code> object to remove 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flash.text.engine.TextLine
		 * @see #container
		 * 
		 */	
		tlf_internal function removeTextLine(textLine:TextLine):void
		{
			if (_container.contains(textLine))
				_container.removeChild(textLine);
		}
		
		/** @private
		 * Adds a <code>flash.display.Shape</code> object on which background shapes (such as background color) are drawn.
		 * The default implementation of this method, which may be overriden, adds the object to <code>container</code>
		 * just before the first <code>flash.text.engine.TextLine</code> child, if one exists, and after the last exisiting
		 * child otherwise. 
		 * 
		 * @param shape <code>flash.display.Shape</code> object to add
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flash.display.Shape
		 * @see flash.text.engine.TextLine
		 * @see #container
		 * 
		 */
		tlf_internal function addBackgroundShape(shape:Shape):void	// No PMD
		{
			_container.addChildAt(shape, getFirstTextLineChildIndex());
		}
		
		/** @private
		 * Removes a <code>flash.display.Shape</code> object on which background shapes (such as background color) are drawn.
		 * The default implementation of this method, which may be overriden, removes the object from its <code>parent</code>.
		 * 
		 * @param shape <code>flash.display.Shape</code> object to remove
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flash.display.Shape
		 * @see flash.text.engine.TextLine
		 * @see #container
		 * 
		 */
		tlf_internal function removeBackgroundShape(shape:Shape):void	
		{
			if (shape.parent)
				shape.parent.removeChild(shape);
		}
		
		/** @private
		 * Adds a <code>flash.display.DisplayObjectContainer</code> object to which selection shapes (such as block selection highlight, cursor etc.) are added.
		 * The default implementation of this method, which may be overriden, has the following behavior:
		 * The object is added just before first <code>flash.text.engine.TextLine</code> child of <code>container</code> if one exists 
		 * and the object is opaque and has normal blend mode. 
		 * In all other cases, it is added as the last child of <code>container</code>.
		 * 
		 * @param selectionContainer <code>flash.display.DisplayObjectContainer</code> object to add
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flash.display.DisplayObjectContainer
		 * @see flash.text.engine.TextLine
		 * @see #container
		 */
		tlf_internal function addSelectionContainer(selectionContainer:DisplayObjectContainer):void
		{
			if (selectionContainer.blendMode == BlendMode.NORMAL && selectionContainer.alpha == 1)
			{
				// don't put selection behind background color or existing content in container, put it behind first text line
				_container.addChildAt(selectionContainer, getFirstTextLineChildIndex());
			}
			else
				_container.addChild(selectionContainer);
		}
		
		/** @private
		 * Removes the <code>flash.display.DisplayObjectContainer</code> object which contains selection shapes (such as block selection highlight, cursor etc.).
		 * The default implementation of this method, which may be overriden, removes the object from its parent if one exists.
		 * 
		 * @param selectionContainer <code>flash.display.DisplayObjectContainer</code> object to remove
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flash.display.DisplayObjectContainer
		 * @see #container
		 * 
		 */
		tlf_internal function removeSelectionContainer(selectionContainer:DisplayObjectContainer):void
		{	
			selectionContainer.parent.removeChild(selectionContainer);
		}
		
		/** @private
		 * Adds a <code>flash.display.DisplayObject</code> object as a descendant of <code>parent</code>.
		 * The default implementation of this method, which may be overriden, adds the object
		 * as a direct child of <code>parent</code> at the specified index. This is called to add 
		 * InlineGraphicElements to the TextLine or container.
		 * 
		 * @param parent the <code>flash.display.DisplayObjectContainer</code> object to add the inlineGraphicElement to
		 * @param inlineGraphicElement the <code>flash.display.DisplayObject</code> object to add
		 * @param index insertion index of the float in its parent 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 2.0
		 * @langversion 3.0
		 * 
		 * @see flash.display.DisplayObjectContainer
		 * @see flash.display.DisplayObject
		 * @see #container
		 * 
		 */	
		tlf_internal function addInlineGraphicElement(parent:DisplayObjectContainer, inlineGraphicElement:DisplayObject, index:int):void
		{
			if (parent)
				parent.addChildAt(inlineGraphicElement, index);
		}
		
		/** @private
		 * Removes a <code>flash.display.DisplayObject</code> object from its parent. 
		 * The default implementation of this method, which may be overriden, removes the object
		 * from <code>container</code> if it is a direct child of the latter.
		 * 
		 * This method may be called even if the object is not a descendant of <code>parent</code>.
		 * Any implementation of this method must ensure that no action is taken in this case.
		 * 
		 * @param float the <code>flash.display.DisplayObject</code> object to remove 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 2.0
		 * @langversion 3.0
		 * 
		 * @see flash.display.DisplayObjectContainer
		 * @see flash.display.DisplayObject
		 * @see #container
		 * 
		 */	
		tlf_internal function removeInlineGraphicElement(parent:DisplayObjectContainer, inlineGraphicElement:DisplayObject):void
		{
			if (parent && inlineGraphicElement.parent == parent)
				parent.removeChild(inlineGraphicElement);
		}

		/** @public
		 * It's <code>_preserveSelectionOnSetText</code> to decide whether or not TLF preserve selection state during setText().
		 * 
		 * The default value is false, which means <code>setText()</code> does not preserve original selection state, 
		 * <code>setText()</code> acts as what it was. If <code>_preserveSelectionOnSetText</code> is true, 
		 * the original selection state is preserved during <code>setText()</code>.  
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0  
		 */
		public function get preserveSelectionOnSetText():Boolean
		{
			return _preserveSelectionOnSetText;
		}
		public function set preserveSelectionOnSetText(value:Boolean):void
		{
			_preserveSelectionOnSetText = value;
		}

	}
	
}

import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.text.engine.TextLine;
import flash.ui.ContextMenu;

import flashx.textLayout.compose.IFlowComposer;
import flashx.textLayout.compose.SimpleCompose;
import flashx.textLayout.container.ContainerController;
import flashx.textLayout.container.ScrollPolicy;
import flashx.textLayout.container.TextContainerManager;
import flashx.textLayout.edit.IInteractionEventHandler;
import flashx.textLayout.elements.ContainerFormattedElement;
import flashx.textLayout.factory.FactoryDisplayComposer;
import flashx.textLayout.factory.TextFlowTextLineFactory;
import flashx.textLayout.factory.TextLineFactoryBase;
import flashx.textLayout.formats.BackgroundColor;
import flashx.textLayout.formats.BlockProgression;
import flashx.textLayout.tlf_internal;

use namespace tlf_internal;

class TMContainerController extends ContainerController
{
	private var _inputManager:TextContainerManager;
	
	public function TMContainerController(container:Sprite, compositionWidth:Number, compositionHeight:Number, tm:TextContainerManager)
	{
		super(container,compositionWidth,compositionHeight);
		_inputManager = tm;
		verticalScrollPolicy = tm.verticalScrollPolicy;
		horizontalScrollPolicy = tm.horizontalScrollPolicy;
	}

	public function get textContainerManager():TextContainerManager { return _inputManager; }
	
	/** Reroute to the TextContainerManger's override.  Reuse the one that's already been created. */
	protected override function createContextMenu():ContextMenu
	{ return _inputManager.getContextMenu(); }

	/** @private */
	protected override function get attachTransparentBackground():Boolean
	{ return false; }
	
	/** @private */
	tlf_internal function doUpdateVisibleRectangle():void
	{ updateVisibleRectangle(); }
	
	/** @private. Override clones and enhances parent class functionality. */
	protected override function updateVisibleRectangle() :void
	{
		var xpos:Number;
		var ypos:Number;
		// see the adjustLines boolean in ContainerController.fillShapeChildren - this logic clones that and allows for skipping the scrollRect
		xpos = horizontalScrollPosition;
		if (effectiveBlockProgression == BlockProgression.RL && (verticalScrollPolicy != ScrollPolicy.OFF || horizontalScrollPolicy != ScrollPolicy.OFF))
			xpos -= !isNaN(compositionWidth) ? compositionWidth : contentWidth;

		ypos = verticalScrollPosition;
			
		_hasScrollRect = _inputManager.drawBackgroundAndSetScrollRect(xpos,ypos);
	}
		
	/** @private */
	tlf_internal override function getInteractionHandler():IInteractionEventHandler
	{ return _inputManager; }
	
	
	/** @private */
	tlf_internal override function attachContextMenu():void
	{ 
		if (_inputManager.getContextMenu() != null)
			super.attachContextMenu();
	}
	
	/** @private */
	tlf_internal override function removeContextMenu():void
	{ 				
		// otherwise client is managing it
		if (_inputManager.getContextMenu())	
			super.removeContextMenu();
	}
	
	// ////////////////////////////////////////////////////////////////////////////
	// push all these methods for manipulating the object list to the _inputmanager
	// ////////////////////////////////////////////////////////////////////////////
	protected override function getFirstTextLineChildIndex():int
	{ return _inputManager.getFirstTextLineChildIndex(); }
	protected override function addTextLine(textLine:TextLine, index:int):void
	{ _inputManager.addTextLine(textLine,index); }
	protected override function removeTextLine(textLine:TextLine):void
	{ _inputManager.removeTextLine(textLine); }
	protected override function addBackgroundShape(shape:Shape):void
	{ _inputManager.addBackgroundShape(shape); }
	protected override function removeBackgroundShape(shape:Shape):void
	{ _inputManager.removeBackgroundShape(shape); }
	protected override function addSelectionContainer(selectionContainer:DisplayObjectContainer):void
	{ _inputManager.addSelectionContainer(selectionContainer); }
	protected override function removeSelectionContainer(selectionContainer:DisplayObjectContainer):void
	{ _inputManager.removeSelectionContainer(selectionContainer); }
	protected override function addInlineGraphicElement(parent:DisplayObjectContainer, inlineGraphicElement:DisplayObject, index:int):void
	{ _inputManager.addInlineGraphicElement(parent,inlineGraphicElement,index); }
	protected override function removeInlineGraphicElement(parent:DisplayObjectContainer, inlineGraphicElement:DisplayObject):void
	{ _inputManager.removeInlineGraphicElement(parent,inlineGraphicElement); }
}

// remap the mouse event for processing inside TLF.  This is just the initial click.  Make it as if the event was on the container and not the textline
class RemappedMouseEvent extends MouseEvent
{
	private var _event:MouseEvent;
	
	public function RemappedMouseEvent(event:MouseEvent,cloning:Boolean = false)
	{
		var containerPoint:Point;
		if (!cloning)
		{
			containerPoint = DisplayObject(event.target).localToGlobal(new Point(event.localX, event.localY));
			containerPoint = DisplayObject(event.currentTarget).globalToLocal(containerPoint);
		}
		else
			containerPoint = new Point();

		/* event.commandKey,event.controlKey,event.clickCount are also supported in AIR.  IMHO they are a nonissue for the initial click */
		super(event.type,event.bubbles,event.cancelable,containerPoint.x,containerPoint.y,event.relatedObject,event.ctrlKey,event.altKey,event.shiftKey,event.buttonDown,event.delta);
		
		_event = event;
	}

	// override methods/getters for things we couldn't set in the base class	

	public override function get target():Object
	{ return _event.currentTarget; }
	
	public override function get currentTarget():Object
	{ return _event.currentTarget; }
	
	public override function get eventPhase():uint
	{ return _event.eventPhase; }
	
	public override function get isRelatedObjectInaccessible():Boolean
	{ return _event.isRelatedObjectInaccessible; }
	
	public override function get stageX():Number
	{ return _event.stageX; }
	
	public override function get stageY():Number
	{ return _event.stageY; }
	
	public override function clone():Event
	{ 
		var rslt:RemappedMouseEvent = new RemappedMouseEvent(_event,true); 
		rslt.localX = localX;
		rslt.localY = localY;
		return rslt;
	}
	
	public override function updateAfterEvent():void
	{ _event.updateAfterEvent(); }
	
	public override function isDefaultPrevented():Boolean
	{ return _event.isDefaultPrevented(); }
	
	public override function preventDefault():void
	{ _event.preventDefault(); }
	
	public override function stopImmediatePropagation():void
	{ _event.stopImmediatePropagation(); }
	
	public override function stopPropagation():void
	{ _event.stopPropagation(); }
}

class TCMTextFlowTextLineFactory extends TextFlowTextLineFactory
{
	private var _tcm:TextContainerManager;
	
	public function TCMTextFlowTextLineFactory()
	{ super(); }
	
	/** @private */
	tlf_internal override function createFlowComposer():IFlowComposer
	{ return new TCMFactoryDisplayComposer(_tcm); }
	
	public function get tcm():TextContainerManager
	{ return _tcm; }
	public function set tcm(val:TextContainerManager):void
	{ _tcm = val; }
}


class TCMFactoryDisplayComposer extends FactoryDisplayComposer
{
	tlf_internal var _tcm:TextContainerManager;
	public function TCMFactoryDisplayComposer(tcm:TextContainerManager)
	{ _tcm = tcm; }
	
	tlf_internal override function callTheComposer(absoluteEndPosition:int, controllerEndIndex:int):ContainerController
	{
		// always do a full compose
		clearCompositionResults();
		
		var state:SimpleCompose = TextLineFactoryBase._factoryComposer;
		state.resetLineHandler = _tcm.resetLine;
		state.composeTextFlow(textFlow, -1, -1);
		state.releaseAnyReferences()
		return getControllerAt(0);
	}
}