////////////////////////////////////////////////////////////////////////////////
//
//  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.FocusEvent;
	import flash.events.IMEEvent;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.events.TextEvent;
	import flash.events.TimerEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	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.utils.Dictionary;
	import flash.utils.Timer;
	
	import flashx.textLayout.compose.FloatCompositionData;
	import flashx.textLayout.compose.FlowComposerBase;
	import flashx.textLayout.compose.FlowDamageType;
	import flashx.textLayout.compose.IFlowComposer;
	import flashx.textLayout.compose.TextFlowLine;
	import flashx.textLayout.compose.TextLineRecycler;
	import flashx.textLayout.debug.Debugging;
	import flashx.textLayout.debug.assert;
	import flashx.textLayout.edit.EditingMode;
	import flashx.textLayout.edit.IInteractionEventHandler;
	import flashx.textLayout.edit.ISelectionManager;
	import flashx.textLayout.edit.SelectionFormat;
	import flashx.textLayout.elements.BackgroundManager;
	import flashx.textLayout.elements.Configuration;
	import flashx.textLayout.elements.ContainerFormattedElement;
	import flashx.textLayout.elements.FlowElement;
	import flashx.textLayout.elements.FlowLeafElement;
	import flashx.textLayout.elements.FlowValueHolder;
	import flashx.textLayout.elements.InlineGraphicElement;
	import flashx.textLayout.elements.LinkElement;
	import flashx.textLayout.elements.ParagraphElement;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.events.FlowElementMouseEvent;
	import flashx.textLayout.events.FlowElementMouseEventManager;
	import flashx.textLayout.events.ModelChange;
	import flashx.textLayout.events.ScrollEvent;
	import flashx.textLayout.events.ScrollEventDirection;
	import flashx.textLayout.events.TextLayoutEvent;
	import flashx.textLayout.events.UpdateCompleteEvent;
	import flashx.textLayout.formats.BlockProgression;
	import flashx.textLayout.formats.Float;
	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.textLayout.utils.Twips;
	
	use namespace tlf_internal;
	
	/** 
	 * The ContainerController class defines the relationship between a TextFlow object and a container.
	 * A TextFlow may have one or more rectangular areas that can hold text; the text is said to be flowing
	 * through the containers. Each container is a Sprite that is the parent DisplayObject for the TextLines.
	 * Each container has a ContainerController that manages the container; the controller holds the target 
	 * width and height for the text area, populates the container with TextLines, and handles scrolling. A
	 * controller also has a format associated with it that allows some formatting attributes to be applied 
	 * to the text in the container. This allows, for instance, a TextFlow to have one container where the
	 * text appears in a single column, and a second container in the same TextFlow with two column text. Not
	 * all formatting attributes that can be applied to the container will affect the text; only the ones that
	 * affect container-level layout. The diagram below illustrates the relationship between the TextFlow,
	 * its flowComposer, and the display list.
	 *
	 * <p><img src="../../../images/textLayout_multiController.gif" alt="IContainerController"></img></p>
	 *
	 * @includeExample examples\ContainerControllerExample1.as -noswf
	 * @includeExample examples\ContainerControllerExample2.as -noswf
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 *
	 * @see flashx.textLayout.compose.IFlowComposer
	 * @see flashx.textLayout.elements.TextFlow
	 * @see flash.text.engine.TextLine
	 */
	public class ContainerController implements IInteractionEventHandler, ITextLayoutFormat, ISandboxSupport
	{		
		static tlf_internal var usesDiscretionaryHyphens:Boolean = true;
		static tlf_internal var startComposeFromBeginning:Boolean = false;
		
		private var _textFlowCache:TextFlow;
		private var _rootElement:ContainerFormattedElement;
		
		private var _absoluteStart:int;
		private var _textLength:int;
		
		private var _container:Sprite;
		private var _mouseEventManager:FlowElementMouseEventManager;
		
		// note must be protected - subclass sets or gets this variable but can't be public
		/** computed container attributes.  @private */
		protected var _computedFormat:TextLayoutFormat;
		
		// Generated column information
		// Generated column information
		private var _columnState:ColumnState;
		
		/** Container size to be composed */
		private var _compositionWidth:Number = 0;
		private var _compositionHeight:Number = 0;
		private var _measureWidth:Boolean; // true if we're measuring (isNaN(compositionWidth) optimization so we don't call isNaN too much
		private var _measureHeight:Boolean; // true if we're measuring (isNaN(compositionHeight) optimization so we don't call isNaN too much
		
		/* Text bounds after composition */
		private var _contentLeft:Number;
		private var _contentTop:Number;
		private var _contentWidth:Number;
		private var _contentHeight:Number;
		
		private var _uncomposedTextLength:int;	// 0 if composition was complete when contentHeight, etc registered, greater than one otherwise
		private var _finalParcelStart:int;
		
		// Scroll policy -- determines whether scrolling is enabled or not
		private var _horizontalScrollPolicy:String;
		private var _verticalScrollPolicy:String;
		
		// x, y location of the text in the container relative to the underlying scrollable area
		private var _xScroll:Number;
		private var _yScroll:Number;
		
		/** Are event listeners attached to the container */
		private var _minListenersAttached:Boolean = false;
		private var _allListenersAttached:Boolean = false;
		private var _selectListenersAttached:Boolean = false;
		tlf_internal var _mouseWheelListenerAttached:Boolean = false;
		
		/** @private */
		tlf_internal function get allListenersAttached():Boolean
		{ return _allListenersAttached; }
		
		/** Are the displayed shapes out of date? */
		private var _shapesInvalid:Boolean = false;
		
		private var _backgroundShape:Shape;
		
		private var _scrollTimer:Timer = null;
		
		/**
		 * @private use this boolean to determine if container.scrollRect is set.  Accessing scrollRect when null changes the rendering behavior of flash player.	
		 */
		protected var _hasScrollRect:Boolean;
		
		private var _linesInView:Array;	// lines that were in view according to the previous compose(). Empty if the lines have already been posted to the display list.
		private var _updateStart:int;
		
		private var _composedFloats:Array;  // floats that were composed into the controller -- array of FloatCompositionData
		private var _floatsInContainer:Array;  // floats are currently in view -- array of DisplayObject
		
		/** Interactive Objects **/
		private var _interactiveObjects:Dictionary = new Dictionary(true);
		private var _oldInteractiveObjects:Array = new Array();
		
		tlf_internal function get interactiveObjects():Dictionary
		{
			return _interactiveObjects ;
		}
		
		tlf_internal function get oldInteractiveObjects():Array
		{
			return _oldInteractiveObjects ;
		}
		
		/** 
		 * @private
		 * 
		 * <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.
		 */
		tlf_internal function get hasScrollRect():Boolean
		{ return _hasScrollRect; }
		
		CONFIG::debug
		{
			protected var id:String;
			private static var contCount:int = 0;
		}
		
		private var _shapeChildren:Array;
		
		private var _format:FlowValueHolder;
		
		private var _containerRoot:DisplayObject;
		
		/* Controller have a non-zero default width and height so that if you construct a text example with a container and don't
		* specify width and height you will still see some text so that you can then have a clue what to do to correct its appearance.
		*/
		
		/** 
		 * Constructor - creates a ContainerController instance. The ContainerController has a default <code>compositionWidth</code>
		 * and <code>compositionHeight</code> so that some text appears in the container if you don't specify its width
		 * height.
		 *
		 * @param container The DisplayObjectContainer in which to manage the text lines.
		 * @param compositionWidth The initial width for composing text in the container.
		 * @param compositionHeight The initial height for composing text in the container.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		public function ContainerController(container:Sprite,compositionWidth:Number=100,compositionHeight:Number=100)
		{
			initialize(container,compositionWidth,compositionHeight);
		}
		
		private function initialize(container:Sprite,compositionWidth:Number,compositionHeight:Number):void
		{
			_container = container;
			_containerRoot =  null;
			
			_textLength = 0;
			_absoluteStart = -1;
			
			_columnState = new ColumnState(null/*blockProgression*/, null/*columnDirection*/, null/*controller*/, 0/*compositionWidth*/, 0/*compositionHeight*/);
			//_visibleRect = new Rectangle();
			_xScroll = _yScroll = 0;
			_contentWidth = _contentHeight = 0;
			_uncomposedTextLength = 0;
			
			// We have to set the flag so that we will get double click events. This
			// is a change to the container we are given, but a minor one.
			_container.doubleClickEnabled = true;
			
			_horizontalScrollPolicy = _verticalScrollPolicy = String(ScrollPolicy.scrollPolicyPropertyDefinition.defaultValue);
			_hasScrollRect = false;
			
			CONFIG::debug { id = contCount.toString(); ++contCount; }
			
			_shapeChildren = [ ];
			_linesInView = [ ];
			
			setCompositionSize(compositionWidth, compositionHeight);
			format = _containerControllerInitialFormat;
		}
		
		/** @private */
		tlf_internal function get effectiveBlockProgression():String
		{
			return _rootElement ? _rootElement.computedFormat.blockProgression : BlockProgression.TB;
		}
		
		/** @private  Determine containerRoot in case the stage is not accessible. Normally the root is the stage. */
		tlf_internal function getContainerRoot():DisplayObject
		{
			// safe to test for stage existence
			if (_containerRoot == null && _container && _container.stage)
			{
				// if the stage is accessible lets use it.
				// trace("BEFORE COMPUTING CONTAINERROOT");
				try
				{
					var x:int = _container.stage.numChildren;
					_containerRoot = _container.stage;
				}
				catch(e:Error)
				{
					// TODO: some way to find the highest level accessible root???
					_containerRoot = _container.root;
				}
				// trace("AFTER COMPUTING CONTAINERROOT");
			}
			return _containerRoot;
		}
		
		/** 
		 * Returns the flow composer object that composes and highlights text into the container that this 
		 * controller manages. 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flashx.textLayout.compose.IFlowComposer
		 */
		
		public function get flowComposer():IFlowComposer
		{ return textFlow ? textFlow.flowComposer : null; }
		
		/** @private */
		tlf_internal function get shapesInvalid():Boolean
		{ return _shapesInvalid; }
		/** @private */
		tlf_internal function set shapesInvalid(val:Boolean):void
		{ _shapesInvalid = val;	}
		
		/** 
		 * Returns a ColumnState object, which describes the number and characteristics of columns in
		 * the container. These values are updated when the text is recomposed, either as a result
		 * of <code>IFlowComposer.compose()</code> or <code>IFlowComposer.updateAllControllers()</code>.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @see ColumnState
		 */
		
		public function get columnState():ColumnState
		{
			if (_rootElement == null)
				return null;
			
			if (_computedFormat == null)
				computedFormat;
			
			_columnState.computeColumns();
			
			return _columnState; 
		}
		
		/** 
		 * Returns the container display object that holds the text lines for this ContainerController instance. 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @see #ContainerController()
		 */
		
		public function get container():Sprite
		{ return _container; }
		
		/** 
		 * Returns the horizontal extent allowed for text inside the container. The value is specified in pixels.
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @see #setCompositionSize()
		 */
		
		public function get compositionWidth():Number
		{ return _compositionWidth; }
		
		/** 
		 * Returns the vertical extent allowed for text inside the container. The value is specified in pixels.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @see #setCompositionSize()
		 */
		
		public function get compositionHeight():Number
		{ return _compositionHeight; }
		
		/** @private */
		tlf_internal function get measureWidth():Boolean
		{ return _measureWidth; }
		
		/** @private */
		tlf_internal function get measureHeight():Boolean
		{ return _measureHeight; }
		
		/** 
		 * Sets the width and height allowed for text in the container. Width and height can be specified in pixels or <code>NaN</code> can be used for either value.  <code>NaN</code> indicates measure that value. 
		 * This can be used to find the widest line and/or the total height of all the content.  When NaN is specified as the width lines are broken with a maximum width of <code>TextLine.MAX_LINE_WIDTH</code>. 
		 * When <code>NaN</code> is specified as the height the container is assumed to have unlimited height.  The actual measured values can be ready back in <code>getContentBounds</code>.  
		 * When the computed <code>blockProgression</code> property of <code>TextFlow</code>
		 * is <code>BlockProgression.RL</code> the meanings of width and height are exchanged.
		 *
		 * @param w The width in pixels that's available for text in the container.  <code>NaN</code> indicates no specified width.  
		 * @param h The height in pixels that's available for text in the container.   <code>NaN</code> indicates no specified height.  
		 *
		 * @includeExample examples\ContainerController_setCompositionSizeExample.as -noswf
		 * 
		 * @see flash.text.engine.TextLine#MAX_LINE_WIDTH
		 * @see flashx.textLayout.formats.BlockProgression
		 * @see #getContentBounds()
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		public function setCompositionSize(w:Number,h:Number):void
		{
		//	trace("setCompositionSize(" + w + ", " + h + ")");
			
			// note: NaN == NaN is always false
			var widthChanged:Boolean  =  !(_compositionWidth == w || (isNaN(_compositionWidth) && isNaN(w)));
			var heightChanged:Boolean =  !(_compositionHeight == h || (isNaN(_compositionHeight) && isNaN(h)));
			
			if (widthChanged || heightChanged)
			{
				_compositionHeight = h;
				_measureHeight = isNaN(_compositionHeight);
				_compositionWidth = w;
				_measureWidth = isNaN(_compositionWidth);
				// otherwise the reset will happen when the cascade is done
				if (_computedFormat)
					resetColumnState();
				// Invalidate all the lines, forcing FTE rebuild if they changed in the logical width direction
				if (effectiveBlockProgression == BlockProgression.TB ? widthChanged : heightChanged)
				{
					if (textFlow && _textLength)
						textFlow.damage(absoluteStart, _textLength, TextLineValidity.INVALID, false);
				}
				else
					invalidateContents();		 // don't need to rebuild FTE lines, just reflow them
				attachTransparentBackgroundForHit(false);
			}
		}
		
		/** 
		 * Returns the TextFlow object whose content appears in the container. Either the <code>textFlow</code> and  
		 * <code>rootElement</code> values are the same, or this is the root element's TextFlow object. For example,
		 * if the container's root element is a DivElement, the value would be the TextFlow object to which the
		 * DivElement belongs.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 * 
	 	 * @see flashx.textLayout.elements.TextFlow TextFlow
	 	 */		 
		public function get textFlow():TextFlow
		{ 
			if (!_textFlowCache && _rootElement)
				_textFlowCache = _rootElement.getTextFlow();
			return _textFlowCache;
		}
		
		// Reserve possibility for future use as a ContainerFormattedElement within the TextFlow.
		
		/** 
		 * Returns the root element that appears in the container. The root element could be a DivElement or TextFlow
		 * instance, for example.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flashx.textLayout.elements.ContainerFormattedElement
		 * @see flashx.textLayout.elements.DivElement
		 * @see flashx.textLayout.elements.TextFlow
		 */
		
		public function get rootElement():ContainerFormattedElement
		{ return _rootElement; }
		
		/** Protected method used when updating the rootElement. 
		 * @param value new container to be controlled
		 * 
		 * @private
		 */
		tlf_internal function setRootElement(value:ContainerFormattedElement):void
		{
			if (_rootElement != value)
			{
				if (_mouseEventManager)
					_mouseEventManager.stopHitTests();
				if (!value)
					_mouseEventManager = null;
				else if (!_mouseEventManager)
				{
					// Currently, the manager listens to all events itself.
					// TODO: forward at least mouseOver and mouseDown events without
					// causing side effects
					_mouseEventManager = new FlowElementMouseEventManager(container, null);
					//				[MouseEvent.MOUSE_DOWN, MouseEvent.MOUSE_UP, MouseEvent.MOUSE_MOVE, MouseEvent.MOUSE_DOWN, MouseEvent.MOUSE_OUT,
					//				 KeyboardEvent.KEY_DOWN, KeyboardEvent.KEY_UP]);
				}

				clearCompositionResults();
				detachContainer();
				_rootElement = value;
				_textFlowCache = null;
				_textLength = 0;
				_absoluteStart = -1;
				attachContainer();
				if (_rootElement)
					formatChanged();

				if (_container && Configuration.playerEnablesSpicyFeatures)
					_container["needsSoftKeyboard"] = (interactionManager && interactionManager.editingMode == EditingMode.READ_WRITE);
			}
		}
		
		/** 
		 * @copy flashx.textLayout.elements.TextFlow#interactionManager
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flashx.textLayout.elements.TextFlow#interactionManager
		 */
		
		public function get interactionManager():ISelectionManager
		{
			return textFlow ? textFlow.interactionManager : null;
		}
		
		
		/** @private */
		tlf_internal function get uncomposedTextLength():int
		{ return _uncomposedTextLength; }

		/** @private */
		tlf_internal function get finalParcelStart():int
		{ return _finalParcelStart; }
		
		/** @private */
		tlf_internal function set finalParcelStart(val:int):void
		{ _finalParcelStart = val; }
		
		//--------------------------------------------------------------------------
		//
		//  Start and length
		//
		//--------------------------------------------------------------------------
		
		/** 
		 * Returns the first character in the container. If this is not the first container in the flow,
		 * this value is updated when the text is composed, that is when the IFlowComposer's <code>compose()</code> or 
		 * <code>updateAllControllers()</code> methods are called.
		 * 
		 * @see flashx.textLayout.compose.IFlowComposer
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		public function get absoluteStart():int
		{
			if (_absoluteStart != -1)
				return _absoluteStart;
			
			var rslt:int = 0;
			var composer:IFlowComposer = flowComposer;
			if (composer)
			{
				var stopIdx:int = composer.getControllerIndex(this);
				if (stopIdx != 0)
				{
					var prevController:ContainerController = composer.getControllerAt(stopIdx-1);
					rslt = prevController.absoluteStart + prevController.textLength;
				}
			}
			_absoluteStart = rslt;
			
			return rslt;
		}
		
		/** Returns the total number of characters in the container. This can include text that is not currently in view,
		 * if the container is scrollable. This value is updated when the text is composed (when the IFlowComposer's <code>compose()</code> 
		 * or <code>updateAllControllers()</code> methods are called).
		 * 
		 * @see flashx.textLayout.compose.IFlowComposer
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		public function get textLength():int
		{
			return _textLength;
		}
		/** @private */
		tlf_internal function setTextLengthOnly(numChars:int):void
		{ 
			if (_textLength != numChars)
			{
				_textLength = numChars; 
				_uncomposedTextLength = 0;
				// all following containers must have absoluteStart invalidated
				if (_absoluteStart != -1)
				{
					var composer:IFlowComposer = flowComposer;
					if (composer)
					{
						var idx:int = composer.getControllerIndex(this)+1;
						while (idx < flowComposer.numControllers)
						{
							var controller:ContainerController = composer.getControllerAt(idx++);
							if (controller._absoluteStart == -1)
								break;
							controller._absoluteStart = -1;
							controller._uncomposedTextLength = 0;
						}
					}
				}
			}
		}
		
		/** @private */
		tlf_internal function setTextLength(numChars:int):void
		{
			CONFIG::debug { assert(numChars >= 0,"bad set textLength"); }
			
			// If its a scrollable container, and it is the last one, then it gets all the characters even though we might not have composed them all
			var uncomposedTextLength:int = 0;
			if (textFlow)
			{
				var verticalText:Boolean = effectiveBlockProgression == BlockProgression.RL;
				var flowComposer:IFlowComposer = textFlow.flowComposer;
				if (numChars != 0 && flowComposer.getControllerIndex(this) == flowComposer.numControllers - 1 &&
					((!verticalText && _verticalScrollPolicy != ScrollPolicy.OFF)||
						(verticalText && _horizontalScrollPolicy != ScrollPolicy.OFF)))
				{
					var containerAbsoluteStart:int = absoluteStart;
					CONFIG::debug { assert(textFlow.textLength >= containerAbsoluteStart,"ContainerController.setTextLength bad absoluteStart"); }
					uncomposedTextLength = textFlow.textLength-(numChars+containerAbsoluteStart);
					// _composeCompleteRatio = (textFlow.textLength-containerAbsoluteStart) == numChars ? 1 : 1.1;
					// var scaledContentHeight:Number = _composeCompleteRatio * _contentHeight;
					// trace("composeCompleteRatio:",_composeCompleteRatio,"composedContentHeight",_contentHeight,"scaledContentHeight",scaledContentHeight,"textLength",textFlow.textLength,"numChars",numChars);
					// include all remaining characters in this container when scroll enabled
					numChars = textFlow.textLength - containerAbsoluteStart;
				}
			}
			
			// this call clears uncomposedTextLength - set it immediately afterwards
			setTextLengthOnly(numChars); 	
			_uncomposedTextLength = uncomposedTextLength;

			CONFIG::debug
			{
				if (Debugging.debugOn && textFlow)
					assert(Math.min(textFlow.textLength, absoluteStart)+_textLength <= textFlow.textLength, "container textLength may not extend past end of root element!");
			}			
		}
		
		/** 
		 * Determines whether the container has text that requires composing. 
		 *
		 * @return 	true if the container requires composing.
		 *
		 * @includeExample examples\ContainerController_isDamagedExample.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		public function isDamaged():Boolean
		{
			return flowComposer.isDamaged(absoluteStart + _textLength);
		}
		
		/** called whenever the container attributes are changed.  Mark computed attributes and columnstate as out of date. 
		 * @private
		 */
		tlf_internal function formatChanged():void
		{
			// The associated container, if there is one, inherits its container
			// attributes from here. So we need to tell it that these attributes
			// have changed.
			_computedFormat = null;
			invalidateContents();
		}
		
		/** This gets called when an element has changed its style selection related attributes. This may happen because an
		 * ancestor element changed it attributes.
		 * @private 
		 */		
		tlf_internal function styleSelectorChanged():void
		{
			modelChanged(ModelChange.STYLE_SELECTOR_CHANGED,this,0,this._textLength);
			_computedFormat = null;
		}
		
		/** @private */
		tlf_internal function modelChanged(changeType:String, element:ContainerController, changeStart:int, changeLen:int, needNormalize:Boolean = true, bumpGeneration:Boolean = true):void
		{
			var tf:TextFlow = _rootElement.getTextFlow();
			if (tf)
				tf.processModelChanged(changeType, element, absoluteStart+changeStart, changeLen, needNormalize, bumpGeneration);
		}
		
		/** @private */
		tlf_internal function gatherVisibleLines(wmode:String, createShape:Boolean):void
		{
			CONFIG::debug { assert(_linesInView.length == 0,"gatherVisibleLines: bad _linesInView"); }
			if (_textLength != 0)
			{
				// Similar computations also done in BaseCompose.getControllerVisibleBounds
				var width:Number = _measureWidth ? _contentWidth : _compositionWidth;
				var height:Number = _measureHeight ? _contentHeight : _compositionHeight;
				var adjustX:Number = (wmode == BlockProgression.RL) ? _xScroll - width : _xScroll;
				var adjustY:Number = _yScroll;
				var scrollAdjustXTW:int = Twips.roundTo(adjustX);
				var scrollAdjustYTW:int = Twips.roundTo(adjustY);
				var scrollAdjustWidthTW:int = Twips.to(width);
				var scrollAdjustHeightTW:int = Twips.to(height);
				
				var flowComposer:IFlowComposer = this.flowComposer;
	
				// Iterate over the lines in the container, setting the x and y positions and 
				// adding them to the list to go into the container. Keep track of the width 
				// and height of the actual text in the container.
				var firstLine:int = flowComposer.findLineIndexAtPosition(absoluteStart);
				var lastLine:int = flowComposer.findLineIndexAtPosition(absoluteStart + _textLength - 1);
				
				var curLine:TextFlowLine;
				var textLine:TextLine;
				var lineIndex:int;
				
				//Use binary search when there is one single column
				if(columnCount == 1)
				{
					// First just test the firstLine - normal unscrolled case
					curLine = flowComposer.getLineAt(firstLine);	
					textLine = testLineVisible(wmode, scrollAdjustXTW, scrollAdjustYTW, scrollAdjustWidthTW, scrollAdjustHeightTW, curLine, null) as TextLine;
					firstLine++;	// its been tested
					if (textLine)
					{
						if (createShape)
							curLine.createShape(wmode, textLine);
						_linesInView.push(textLine);
					}
					else
					{
						var hi:int = lastLine;
						while (firstLine <= hi)
						{
							var mid:int = (firstLine+hi)/2;
							CONFIG::debug { assert(mid != 0,"ContainerController:gatherVisibleLines: bad mid"); }
							curLine = flowComposer.getLineAt(mid);
							var testRslt:* = testLineVisible(wmode, scrollAdjustXTW, scrollAdjustYTW, scrollAdjustWidthTW, scrollAdjustHeightTW, curLine, null);
							textLine = testRslt as TextLine;
							if (textLine)
							{
								// note that we tested firstLine above so going to mid-1 is always valid
								var tempLine:TextFlowLine = flowComposer.getLineAt(mid-1);
								if (!(testLineVisible(wmode, scrollAdjustXTW, scrollAdjustYTW, scrollAdjustWidthTW, scrollAdjustHeightTW, tempLine, null) is TextLine))
								{
									// Got the start
									if (createShape)
										curLine.createShape(wmode, textLine);
									_linesInView.push(textLine);
									firstLine = mid+1;
									break;
								}
								testRslt = -1;	// past the start
							}
							if (testRslt < 0 || testRslt == 2)
								hi = mid-1;
							else
								firstLine = mid+1;
						}
					}
					
					for (lineIndex = firstLine; lineIndex <= lastLine; lineIndex++)
					{
						curLine = flowComposer.getLineAt(lineIndex);	
						textLine = testLineVisible(wmode, scrollAdjustXTW, scrollAdjustYTW, scrollAdjustWidthTW, scrollAdjustHeightTW, curLine, null) as TextLine;
						if (!textLine)
							break;
		
						if (createShape)
							curLine.createShape(wmode, textLine);
						_linesInView.push(textLine);
					}
				}
				else //multiple columns
				{
					for (lineIndex = firstLine; lineIndex <= lastLine; lineIndex++)
					{
						curLine = flowComposer.getLineAt(lineIndex);	
						if (curLine == null || curLine.controller != this)
							continue;
						
						textLine = oldTestLineVisible(wmode, scrollAdjustXTW, scrollAdjustYTW, scrollAdjustWidthTW, scrollAdjustHeightTW, curLine, null);
						if (textLine)
						{
							if (createShape)
								curLine.createShape(wmode, textLine);
							_linesInView.push(textLine);
						}
					}
				}
			}
			_updateStart = absoluteStart;	// we collected all lines from the start of the container
		}
		
		/** determines the shapechildren in the container and applies VJ. @private */
		tlf_internal function fillShapeChildren():void
		{ 
			if (_textLength == 0)
				return;	// none				
			
			var wmode:String = effectiveBlockProgression;
			
			if (_linesInView.length == 0)		// no preexisting concpetion of what lines are in view: recalculate
				gatherVisibleLines(wmode, true);
			
			// If scrolling is turned off, and flow is vertical, then we need to adjust the positions of all the lines. With
			// scrolling turned on, we don't need to do this because the adjustment is done in the Player when the scrollRect
			// is set up correctly. But with the scrollRect, we also get clipping, and if scrolling is turned off we want to
			// have the clipping turned off as well. So in this case we do the adjustment manually so the scrollRect can be null.
			// NOTE: similar adjustments are made in TextContainerManager
			var adjustLines:Boolean = (wmode == BlockProgression.RL) &&
				(_horizontalScrollPolicy == ScrollPolicy.OFF && 
					_verticalScrollPolicy == ScrollPolicy.OFF);
			
			if (adjustLines)
			{			
				var width:Number = _measureWidth ? _contentWidth : _compositionWidth;
				var height:Number = _measureHeight ? _contentHeight : _compositionHeight;
				var adjustX:Number = _xScroll - width;		// vertical text: blockProgression is rl
				var adjustY:Number = _yScroll;
				
				// Iterate over the lines in the container, setting the x and y positions. Keep track of the width 
				// and height of the actual text in the container.
				if (adjustX != 0 || adjustY != 0)
				{
					for each (var textLine:TextLine in _linesInView)
					{
						if (!textLine)
							continue;
						
						if (adjustLines)
						{
							textLine.x -= adjustX;
							textLine.y -= adjustY;
						}
					}
					_contentLeft -= adjustX;
					_contentTop  -= adjustY;
				}
			}
			
			
		}
		
		//--------------------------------------------------------------------------
		//
		//  Scrolling
		//
		//--------------------------------------------------------------------------
		
		/** 
		 * Specifies the horizontal scrolling policy, which you can set by assigning one of the constants of
		 * the ScrollPolicy class: ON, OFF, or AUTO.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see ScrollPolicy
		 */
		
		public function get horizontalScrollPolicy():String
		{
			return _horizontalScrollPolicy;
		}
		public function set horizontalScrollPolicy(scrollPolicy:String):void
		{
			var newScrollPolicy:String = ScrollPolicy.scrollPolicyPropertyDefinition.setHelper(_horizontalScrollPolicy, scrollPolicy) as String;
			
			if (newScrollPolicy != _horizontalScrollPolicy)
			{
				_horizontalScrollPolicy = newScrollPolicy;
				if (_horizontalScrollPolicy == ScrollPolicy.OFF)
					horizontalScrollPosition = 0;
				formatChanged();	// scroll policy affects composition
			}
		}
		
		/** @private */
		tlf_internal function checkScrollBounds():void
		{
			var newHeight:Number;
			var visibleHeight:Number;
			var measuring:Boolean;
			
			// If we've either grown the content past the composition bounds in the logical vertical direction, 
			// or shrunk it down under the composition bounds, signal a scrolling change
			// If we're measuring we never scroll.
			if (effectiveBlockProgression == BlockProgression.RL)
			{
				newHeight = _contentWidth;
				visibleHeight = compositionWidth;
				measuring = _measureWidth;
			}
			else
			{
				newHeight = _contentHeight;
				visibleHeight = compositionHeight;
				measuring = _measureHeight;
			}

			// Called when the bounds have changed and they now exceed the composition area, to see if we need to attach a mouse wheel listener for scrolling
			if (textFlow && _container && !_minListenersAttached)
			{
				var needToScroll:Boolean = !measuring && newHeight > visibleHeight;
				if (needToScroll != _mouseWheelListenerAttached)
				{
					if (_mouseWheelListenerAttached)
						removeMouseWheelListener();
					else
						addMouseWheelListener();
				}
			}
			
		}
		
		/** Specifies the vertical scrolling policy, which you can set by assigning one of the constants of the ScrollPolicy
		 * class: ON, OFF, or, AUTO.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @see ScrollPolicy
		 */
		
		public function get verticalScrollPolicy():String
		{
			return _verticalScrollPolicy;
		}
		public function set verticalScrollPolicy(scrollPolicy:String):void
		{
			var newScrollPolicy:String = ScrollPolicy.scrollPolicyPropertyDefinition.setHelper(_verticalScrollPolicy, scrollPolicy) as String;
			if (newScrollPolicy != _verticalScrollPolicy)
			{
				_verticalScrollPolicy = newScrollPolicy;
				if (_verticalScrollPolicy == ScrollPolicy.OFF)
					verticalScrollPosition = 0;
				formatChanged();	// scroll policy affects composition
			}
		}
		
		/** Specifies the current horizontal scroll location on the stage. The value specifies the number of
		 * pixels from the left.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		public function get horizontalScrollPosition():Number
		{
			return _xScroll;
		}
		
		public function set horizontalScrollPosition(x:Number):void
		{
			if (!_rootElement)
				return;
			
			if (_horizontalScrollPolicy == ScrollPolicy.OFF)
			{
				_xScroll = 0;
				return;
			}
			var oldScroll:Number = _xScroll;
			var newScroll:Number = computeHorizontalScrollPosition(x,true);
			
			if (newScroll != oldScroll)
			{	
				_shapesInvalid = true;
				_xScroll = newScroll;
				updateForScroll(ScrollEventDirection.HORIZONTAL, newScroll - oldScroll);
			}
		}
		
		static private function pinValue(value:Number, minimum:Number, maximum:Number):Number
		{
			return Math.min(Math.max(value, minimum), maximum);						
		}
		
		private function computeHorizontalScrollPosition(x:Number,okToCompose:Boolean):Number
		{
			var wmode:String = effectiveBlockProgression;
			var curEstimatedWidth:Number = contentWidth;
			var newScroll:Number = 0;
			
			if (curEstimatedWidth > _compositionWidth && !_measureWidth)
			{
				// Pin the lower and upper bounds of _x. If we're doing vertical text, then the right edge is 0 and the left edge is negative
				// We may not have composed all the way to the indicated position. If not, force composition so that we can be sure we're at
				// a legal position.
				if (wmode == BlockProgression.RL)
				{
					newScroll = pinValue(x, _contentLeft + _compositionWidth, _contentLeft + curEstimatedWidth);
					if (okToCompose && _uncomposedTextLength != 0 && newScroll != _xScroll)
					{
						// in order to compose have to set _xScroll
						_xScroll = x;
						if (_xScroll > _contentLeft + _contentWidth)
							_xScroll = _contentLeft + _contentWidth;
						flowComposer.composeToController(flowComposer.getControllerIndex(this));
						newScroll = pinValue(x, _contentLeft + _compositionWidth, _contentLeft + _contentWidth);
					}
				}
				else
					newScroll = pinValue(x, _contentLeft, (_contentLeft + curEstimatedWidth) - _compositionWidth);
			}
			return newScroll;
		}
		
		
		/** Specifies the current vertical scroll location on the stage. The value specifies the number of 
		 * pixels from the top.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		public function get verticalScrollPosition():Number
		{
			return _yScroll;
		}
		
		public function set verticalScrollPosition(y:Number):void
		{
			if (!_rootElement)
				return;
			
			if (_verticalScrollPolicy == ScrollPolicy.OFF)
			{
				_yScroll = 0;
				return;
			}
			
			var oldScroll:Number = _yScroll;
			var newScroll:Number = computeVerticalScrollPosition(y,true);
			
			if (newScroll != oldScroll)
			{			
				_shapesInvalid = true;
				_yScroll = newScroll;
				updateForScroll(ScrollEventDirection.VERTICAL, newScroll - oldScroll);
			}
		}	
		
		private function computeVerticalScrollPosition(y:Number,okToCompose:Boolean):Number
		{
			var newScroll:Number = 0;
			var curcontentHeight:Number = contentHeight;
			var wmode:String = effectiveBlockProgression;
			
			// Only try to scroll if the content height is greater than the composition height, then there is text that is not visible to scroll to
			if (curcontentHeight > _compositionHeight)
			{
				// new scroll value is somewhere between the topmost content, and the top of the last containerfull
				newScroll = pinValue(y, _contentTop, _contentTop + (curcontentHeight - _compositionHeight));
				
				// if we're not composed to the end, compose further so we can scroll to it. Sets the scroll position and then 
				// recomposes the container, which will compose through the end of the screenfull that starts at the requested position.
				if (okToCompose && _uncomposedTextLength != 0 && wmode == BlockProgression.TB)
				{
					_yScroll = y;
					if (_yScroll < _contentTop)
						_yScroll = _contentTop;
					flowComposer.composeToController(flowComposer.getControllerIndex(this));
					newScroll = pinValue(y, _contentTop, _contentTop + (curcontentHeight - _compositionHeight));
				}
			}
			return newScroll;
		}
		
		/** 
		 * Returns the area that the text occupies, as reflected by the last compose or update operation. 
		 * The width and the height might be estimated, if the container is scrollable and the text exceeds the 
		 * visible area.
		 * 
		 * @return describes the area that the text occupies.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @includeExample examples\ContainerController_getContentBoundsExample.as -noswf
		 *
		 * @see flash.geom.Rectangle Rectangle
		 */
		public function getContentBounds():Rectangle
		{
			return new Rectangle(_contentLeft, _contentTop, contentWidth, contentHeight);
		}
		
		/**
		 * @private
		 */
		
		tlf_internal function get contentLeft():Number
		{
			return _contentLeft;
		}
		
		/**
		 * @private
		 */
		
		tlf_internal function get contentTop():Number
		{
			return _contentTop;
		}
		
		/** @private */
		tlf_internal function computeScaledContentMeasure(measure:Number):Number
		{
			CONFIG::debug { assert(_finalParcelStart != -1 && _finalParcelStart >= this.absoluteStart && _finalParcelStart <= textFlow.textLength-_uncomposedTextLength,"computeScaledContentMeasure bad _finalParcelStart"); }
			var charsInFinalParcel:int = textFlow.textLength-_finalParcelStart;
			var composeCompleteRatio:Number = charsInFinalParcel / (charsInFinalParcel-_uncomposedTextLength);
			// trace(measure*composeCompleteRatio,charsInFinalParcel,_uncomposedTextLength,measure,composeCompleteRatio);
			return measure * composeCompleteRatio;
		}
		
		/** 
		 * @private
		 *
		 * Returns the vertical extent of the text. For horizontal text, it includes space taken for descenders on the last line. 
		 * If not all the text is composed, this returns an estimated value based on how much text is already composed; the
		 * more text that is composed, the more accurate s the estimate. To get a completely accurate value, recompose
		 * with the rootElement's flowComposer before accessing contentHeight.
		 * You can get the composed bounds of the text by getting the contentLeft, contentTop, contentWidth, contentHeight properties.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		tlf_internal function get contentHeight():Number
		{
			if (_uncomposedTextLength == 0 || effectiveBlockProgression != BlockProgression.TB)
				return _contentHeight;
			return computeScaledContentMeasure(_contentHeight);
		}
		
		/** 
		 * @private
		 *
		 * Returns the horizontal extent of the text. For vertical text, it includes space taken for descenders on the last line. 
		 * If not all the text is composed, this returns an estimated value based on how much text is already composed; the
		 * more text that is composed, the more accurate is the estimate. To get a completely accurate value, recompose
		 * with the rootElement's flowComposer before accessing contentWidth.
		 * You can get the composed bounds of the text by getting the contentLeft, contentTop, contentWidth, contentHeight properties.
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		tlf_internal function get contentWidth():Number
		{			
			if (_uncomposedTextLength == 0 || effectiveBlockProgression != BlockProgression.RL)
				return _contentWidth;
			return computeScaledContentMeasure(_contentWidth);
		}
		
		/** @private */
		tlf_internal function setContentBounds(contentLeft:Number, contentTop:Number, contentWidth:Number, contentHeight:Number):void
		{
			_contentWidth = contentWidth;
			_contentHeight = contentHeight;
			_contentLeft = contentLeft;
			_contentTop = contentTop;
			checkScrollBounds();
		}
		
		private function updateForScroll(direction:String, delta:Number):void
		{
			_linesInView.length = 0;		// zero out array of previously gathered up lines; its invalid because we've changed the visible area
			var flowComposer:IFlowComposer = textFlow.flowComposer;
			flowComposer.updateToController(flowComposer.getControllerIndex(this));
			
			attachTransparentBackgroundForHit(false);
			
			// notify client that we scrolled.
			if (textFlow.hasEventListener(TextLayoutEvent.SCROLL))
				textFlow.dispatchEvent(new ScrollEvent(TextLayoutEvent.SCROLL, false, false, direction, delta));
			
			//	trace("contentHeight", contentHeight, "contentWidth", contentWidth);
			//	trace("contentHeight", contentHeight, "contentWidth", contentWidth);
		}
		
		/** @private */
		CONFIG::debug tlf_internal function validateLines():void
		{
			if (!Debugging.containerLineValidation)
				return;
			
			// Optimally we would recalculate which lines are in view and make sure they are parented
			// to the container... but that causes side-effects (like creating TextLines) that affect
			// regular execution. So we don't try that.
			
			// Check all the children of the container. Verify that adornments go before or after lines, that lines are at the expected z-order position
			// And that extraneous lines are not parented to the container.
			var firstLineIndex:int = -1;
			var lastLineIndex:int = -1;
			var numChildren:int = _container.numChildren;
			for (var childIndex:int = 0; childIndex < numChildren; ++childIndex)
			{
				var child:DisplayObject = _container.getChildAt(childIndex);
				if (_shapeChildren.indexOf(child) < 0 && (!_floatsInContainer || _floatsInContainer.indexOf(child) < 0))
				{
					// the very last thing can be the selection sprite
					if (childIndex == numChildren - 1)
						assert(child == getSelectionSprite(false),"expected selectionsprite but not found");
					
					assert(firstLineIndex == -1 || lastLineIndex == childIndex - 1, "Found adornment in the middle of TextLine children");
					continue;		// it's an adornment: skip
				}
				else 
				{
					if (firstLineIndex == -1)
						firstLineIndex = childIndex;
					lastLineIndex = childIndex;
				}
				if (_floatsInContainer && _floatsInContainer.indexOf(child) >= 0)	// it's a float
					continue;
				assert(child is TextLine, "Expected child to be a TextLine");
				
				// Check that the line comes after previous lines, in z-order
				var lineIndex:int = _shapeChildren.indexOf(child);
				if (lineIndex > 0)
					assert(_container.getChildIndex(_shapeChildren[lineIndex - 1]) < childIndex, "Line is visible but not at expected z-order position: earlier line is later in z-order");
				else if (lineIndex < 0)
					assert(false, "Found line that should not be in the container (its not considered visible)");
			}
		}
		
		private function get containerScrollRectLeft():Number
		{
			var rslt:Number;
			if (horizontalScrollPolicy == ScrollPolicy.OFF && verticalScrollPolicy == ScrollPolicy.OFF)
				rslt = 0;
			else
				rslt= effectiveBlockProgression == BlockProgression.RL ? horizontalScrollPosition - compositionWidth : horizontalScrollPosition;
			//CONFIG::debug { assert(container.scrollRect == null && rslt == 0 || int(rslt) == container.scrollRect.left,"Bad containerScrollRectLeft"); }
			return rslt;
		}
		
		private function get containerScrollRectRight():Number
		{
			var rslt:Number = containerScrollRectLeft+compositionWidth;
			//CONFIG::debug { assert(container.scrollRect == null && rslt == compositionWidth || int(rslt) == container.scrollRect.right,"Bad containerScrollRectRight"); }
			return rslt;
		}
		
		private function get containerScrollRectTop():Number
		{
			var rslt:Number;
			if (horizontalScrollPolicy == ScrollPolicy.OFF && verticalScrollPolicy == ScrollPolicy.OFF)
				rslt = 0;
			else
				rslt = verticalScrollPosition;
			//CONFIG::debug { assert(container.scrollRect == null && rslt == 0 || int(rslt) == container.scrollRect.top,"Bad containerScrollRectTop"); }
			return rslt;
		}
		
		private function get containerScrollRectBottom():Number
		{
			var rslt:Number = containerScrollRectTop+compositionHeight;
			//CONFIG::debug { assert(container.scrollRect == null && rslt == compositionHeight || int(rslt) == container.scrollRect.bottom,"Bad containerScrollRectBottom"); }
			return rslt;
		}
		
		/** 
		 * Scrolls so that the text range is visible in the container.
		 *
		 * @param activePosition	The end of the selection that is changed when you extend the selection. It can be
		 * 	either the start or the end of the selection, expressed as an offset from the start of the text flow.
		 * @param anchorPosition   	The stable end of the selection when you extend the selection. It can be either 
		 * 	the start or the end of the selection.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		public function scrollToRange(activePosition:int,anchorPosition:int):void
		{
			
			// return if we're not scrolling, or if it's not the last controller
			if (!_hasScrollRect || !flowComposer || flowComposer.getControllerAt(flowComposer.numControllers-1) != this)
				return;
			
			// clamp values to range absoluteStart,absoluteStart+_textLength
			var controllerStart:int = absoluteStart;
			var lastPosition:int = Math.min(controllerStart+_textLength, textFlow.textLength - 1);
			activePosition = Math.max(controllerStart,Math.min(activePosition,lastPosition));
			anchorPosition = Math.max(controllerStart,Math.min(anchorPosition,lastPosition));
			
			var verticalText:Boolean = effectiveBlockProgression == BlockProgression.RL;
			var begPos:int = Math.min(activePosition,anchorPosition);
			var endPos:int = Math.max(activePosition,anchorPosition);
			
			// is part of the selection in view?
			var begLineIndex:int = flowComposer.findLineIndexAtPosition(begPos,(begPos == textFlow.textLength));
			var endLineIndex:int = flowComposer.findLineIndexAtPosition(endPos,(endPos == textFlow.textLength));
			
			// no scrolling if any part of the selection is in view			
			var scrollRectLeft:Number = containerScrollRectLeft;
			var scrollRectTop:Number  = containerScrollRectTop;
			var scrollRectRight:Number = containerScrollRectRight;
			var scrollRectBottom:Number = containerScrollRectBottom;
			
			if (flowComposer.damageAbsoluteStart <= endPos)
			{
				endPos = Math.min(begPos + 100, endPos + 1);
				flowComposer.composeToPosition(endPos);
				begLineIndex = flowComposer.findLineIndexAtPosition(begPos,(begPos == textFlow.textLength));
				endLineIndex = flowComposer.findLineIndexAtPosition(endPos,(endPos == textFlow.textLength));
			}
			var rect:Rectangle = rangeToRectangle(begPos, endPos, begLineIndex, endLineIndex);
			if (rect) 
			{
				var lastVisibleLine:TextFlowLine;
				var horizontalScrollOK:Boolean;
				var verticalScrollOK:Boolean;
				
				// vertical scroll
				if (verticalText) {					
					// horizontal scroll
					horizontalScrollOK = (rect.left < scrollRectLeft || rect.right > scrollRectLeft);
					if (horizontalScrollOK)
					{
						if (rect.left < scrollRectLeft)
							horizontalScrollPosition = rect.left + _compositionWidth;
						if (rect.right > scrollRectRight)
							horizontalScrollPosition = rect.right;
					}
					
					// If we're showing a blinking insertion point, we need to scroll far enough that
					// we can see the insertion point, and it comes just after the character.
					if (rect.top < scrollRectTop)
						verticalScrollPosition = rect.top;
					if (activePosition == anchorPosition)
						rect.bottom += 2;							
					// vertical scroll
					if (rect.bottom > scrollRectBottom)
						verticalScrollPosition = rect.bottom - _compositionHeight;
				}
				else 
				{
					// vertical scroll
					
					// Don't scroll if the range extends both above and below
					verticalScrollOK = (rect.top > scrollRectTop || rect.bottom < scrollRectBottom);
					
					// vertical scroll
					if (verticalScrollOK)
					{
						if (rect.top < scrollRectTop)
							verticalScrollPosition = rect.top;
	
						if (rect.bottom > scrollRectBottom)
							verticalScrollPosition = rect.bottom - _compositionHeight;
					}
					
					// horizontal scroll

					// If we're showing a blinking insertion point, we need to scroll far enough to see the
					// insertion point, and it comes up to the right
					if (activePosition == anchorPosition)
						rect.right += 2;

					// Don't scroll if range extends both to the left and right
					horizontalScrollOK = (rect.left > scrollRectLeft || rect.right < scrollRectRight);
					if (horizontalScrollOK && rect.left < scrollRectLeft)
						horizontalScrollPosition = rect.left - _compositionWidth / 2;
					if (horizontalScrollOK && rect.right > scrollRectRight)
						horizontalScrollPosition = rect.right - _compositionWidth / 2;
				}
			}
		}		
		
		private function rangeToRectangle(start:int, end:int, startLineIndex:int, endLineIndex:int):Rectangle
		{
			var bbox:Rectangle;
			var blockProgression:String = effectiveBlockProgression;		
			var flowComposer:IFlowComposer = textFlow.flowComposer;
			
			if (!container || !flowComposer)
				return null;
			
			if (startLineIndex == endLineIndex)
			{
				var line:TextFlowLine = flowComposer.getLineAt(startLineIndex); 
				if (line.isDamaged())
					return null;
				var textLine:TextLine = line.getTextLine(true);
				var paragraphStart:int = line.paragraph.getAbsoluteStart();
				
				var isTCY:Boolean = false;
				if (blockProgression == BlockProgression.RL)
				{
					var leafElement:FlowLeafElement = _rootElement.getTextFlow().findLeaf(start);
					isTCY =  leafElement.getParentByType(flashx.textLayout.elements.TCYElement) != null;
				}
				
				var minAtomIndex:int = textLine.atomCount;
				var maxAtomIndex:int = 0;
				if (start == end)
				{
					minAtomIndex = textLine.getAtomIndexAtCharIndex(start - paragraphStart);
					maxAtomIndex = minAtomIndex;
				}
				else
				{
					var atomIndex:int;
					var lastPosition:int = end - paragraphStart;
					for (var pos:int = start - paragraphStart; pos < lastPosition; ++pos)
					{
						atomIndex = textLine.getAtomIndexAtCharIndex(pos);
						if (atomIndex < minAtomIndex)
							minAtomIndex = atomIndex;
						if (atomIndex > maxAtomIndex)
							maxAtomIndex = atomIndex;
					}
				}
				bbox = atomToRectangle(minAtomIndex, line, textLine, blockProgression, isTCY);
				if (minAtomIndex != maxAtomIndex)
					bbox = bbox.union(atomToRectangle(maxAtomIndex, line, textLine, blockProgression, isTCY));
			}
			else
			{
				bbox = new Rectangle(_contentLeft, _contentTop, _contentWidth, _contentHeight);
				var startLine:TextFlowLine = flowComposer.getLineAt(startLineIndex); 
				var endLine:TextFlowLine = flowComposer.getLineAt(endLineIndex); 
				if (blockProgression == BlockProgression.TB)
				{
					bbox.top = startLine.y;
					bbox.bottom = endLine.y + endLine.textHeight;
				}
				else
				{
					bbox.right = startLine.x + startLine.textHeight;
					bbox.left = endLine.x;
				}
			}
			return bbox;
		}
		
		
		private function atomToRectangle(atomIdx:int, line:TextFlowLine, textLine:TextLine, blockProgression:String, isTCY:Boolean):Rectangle
		{
			var atomBounds:Rectangle;
			CONFIG::debug { assert(atomIdx > -1, "How'd we get here?"); }
			if (atomIdx > -1) 
				atomBounds = textLine.getAtomBounds(atomIdx);
			
			// special handling for TCY - no line height adjustments TCY is perpendicular to the height direction
			if (blockProgression == BlockProgression.RL)
			{
				if (isTCY)
					return new Rectangle(line.x+atomBounds.x,line.y+atomBounds.y,atomBounds.width,atomBounds.height);
				return new Rectangle(line.x, line.y + atomBounds.y, line.height, atomBounds.height);
			}
			return new Rectangle(line.x + atomBounds.x, line.y-line.height+line.ascent, atomBounds.width, line.height+textLine.descent);
		}
		
		/**
		 * @private
		 */
		
		tlf_internal function resetColumnState():void
		{
			if (_rootElement)
				_columnState.updateInputs(effectiveBlockProgression, _rootElement.computedFormat.direction, this, _compositionWidth, _compositionHeight);
		}
		
		/** 
		 * Marks all the text in this container as needing composing. 
		 *
		 * @includeExample examples\ContainerController_invalidateContentsExample.as -noswf
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 */
		
		public function invalidateContents():void
		{
			if (textFlow)
				textFlow.damage(absoluteStart, Math.min(_textLength, 1), FlowDamageType.GEOMETRY, false);
		}
		
		/** @private */
		private var _transparentBGX:Number;
		/** @private */
		private var _transparentBGY:Number;
		/** @private */
		private var _transparentBGWidth:Number;
		/** @private */
		private var _transparentBGHeight:Number;
		
		/** No mouse clicks or moves will be generated for the container unless it has a background covering its area.  Text Layout Framework
		 * wants those events so that clicking on a container will select the text in it.  This code
		 * adds or updates (on size change) that background for Sprite containers only. This may cause clients problems 
		 * - definitely no hits is a problem - add this code to explore the issues - expect feedback.  
		 * We may have to make this configurable. @private */
		
		
		tlf_internal function attachTransparentBackgroundForHit(justClear:Boolean):void
		{
			if ((_minListenersAttached || _mouseWheelListenerAttached) && attachTransparentBackground)
			{
				var s:Sprite = _container;
				if (s)
				{
					if (justClear)
					{
						s.graphics.clear();
						CONFIG::debug { Debugging.traceFTECall(null,s,"clearTransparentBackground()"); }
						_transparentBGX = _transparentBGY = _transparentBGWidth = _transparentBGHeight = NaN;
					}
					else
					{		
						var bgwidth:Number = _measureWidth ? _contentWidth : _compositionWidth;
						var bgheight:Number = _measureHeight ? _contentHeight : _compositionHeight;
						
						var adjustHorizontalScroll:Boolean = effectiveBlockProgression == BlockProgression.RL && _horizontalScrollPolicy != ScrollPolicy.OFF;
						var bgx:Number = adjustHorizontalScroll ? _xScroll - bgwidth : _xScroll;
						var bgy:Number = _yScroll;
						
						CONFIG::debug { assert(!isNaN(bgx) && !isNaN(bgy) && !isNaN(bgwidth) && ! isNaN(bgheight),"Bad background rectangle"); }
						
						if (bgx != _transparentBGX || bgy != _transparentBGY || bgwidth != _transparentBGWidth || bgheight != _transparentBGHeight)
						{
							s.graphics.clear();
							CONFIG::debug { Debugging.traceFTECall(null,s,"clearTransparentBackground()"); }
							if (bgwidth != 0 && bgheight != 0 )
							{
								s.graphics.beginFill(0, 0);
								s.graphics.drawRect(bgx, bgy, bgwidth, bgheight);
								s.graphics.endFill();
								CONFIG::debug { Debugging.traceFTECall(null,s,"drawTransparentBackground",bgx, bgy, bgwidth, bgheight); }
							}
							_transparentBGX = bgx;
							_transparentBGY = bgy;
							_transparentBGWidth = bgwidth;
							_transparentBGHeight = bgheight;
						}
					}
				}
			} 
		}
		
		/** @private */
		tlf_internal	function interactionManagerChanged(newInteractionManager:ISelectionManager):void
		{
			if (!newInteractionManager)
				detachContainer();
			attachContainer();
			checkScrollBounds();
			// Need to forward whether the Ctrl key is needed to have
			// hit-tested FlowElements emit events
			if (_mouseEventManager)
				_mouseEventManager.needsCtrlKey	= 
					(interactionManager != null && interactionManager.editingMode == EditingMode.READ_WRITE);

			// We have to tell the Player to bring up the soft keyboard on a
			// keyboard edit gesture. Note that needsSoftKeyboard is new with 10.2, so 
			// have to check for it. This is a change to the container, but unavoidable
			if (_container && Configuration.playerEnablesSpicyFeatures)
				_container["needsSoftKeyboard"] = (interactionManager && interactionManager.editingMode == EditingMode.READ_WRITE);
		}
		
		//--------------------------------------------------------------------------
		//  Event handlers for editing
		//  Listeners are attached on first compose
		//--------------------------------------------------------------------------
		
		/** @private */
		tlf_internal function attachContainer():void
		{
			if (!_minListenersAttached && textFlow && textFlow.interactionManager)
			{
				_minListenersAttached = true;
				
				if (_container)
				{
					_container.addEventListener(FocusEvent.FOCUS_IN, requiredFocusInHandler);
					_container.addEventListener(MouseEvent.MOUSE_OVER, requiredMouseOverHandler);

					attachTransparentBackgroundForHit(false);
					
					// If the container already has focus, we have to attach all listeners
					if (_container.stage && _container.stage.focus == _container)
						attachAllListeners();
					
				}
			}
		}
		
		/** @private */
		tlf_internal function attachInteractionHandlers():void
		{
			// the receiver is either this or another class that is going to handle the methods.
			var receiver:IInteractionEventHandler = getInteractionHandler();
			
			// the required handlers are implemented here and forwarded to the receiver
			_container.addEventListener(MouseEvent.MOUSE_DOWN, requiredMouseDownHandler);
			_container.addEventListener(FocusEvent.FOCUS_OUT, requiredFocusOutHandler);
			_container.addEventListener(MouseEvent.DOUBLE_CLICK, receiver.mouseDoubleClickHandler);
			_container.addEventListener(Event.ACTIVATE, receiver.activateHandler);
			_container.addEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, receiver.focusChangeHandler);
			_container.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, receiver.focusChangeHandler);
			_container.addEventListener(TextEvent.TEXT_INPUT, receiver.textInputHandler);
			_container.addEventListener(MouseEvent.MOUSE_OUT, receiver.mouseOutHandler);
			addMouseWheelListener();
			_container.addEventListener(Event.DEACTIVATE, receiver.deactivateHandler);
			// attach by literal event name to avoid Argo dependency
			// normally this would be IMEEvent.START_COMPOSITION
			_container.addEventListener("imeStartComposition", receiver.imeStartCompositionHandler);
			
			if (_container.contextMenu)
				_container.contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, receiver.menuSelectHandler);
			_container.addEventListener(Event.COPY, receiver.editHandler);
			_container.addEventListener(Event.SELECT_ALL, receiver.editHandler);
			_container.addEventListener(Event.CUT, receiver.editHandler);
			_container.addEventListener(Event.PASTE, receiver.editHandler);
			_container.addEventListener(Event.CLEAR, receiver.editHandler);
		}
		
		/** @private */
		tlf_internal function removeInteractionHandlers():void
		{
			var receiver:IInteractionEventHandler = getInteractionHandler();
			
			_container.removeEventListener(MouseEvent.MOUSE_DOWN, requiredMouseDownHandler);
			_container.removeEventListener(FocusEvent.FOCUS_OUT, requiredFocusOutHandler);
			_container.removeEventListener(MouseEvent.DOUBLE_CLICK, receiver.mouseDoubleClickHandler);
			_container.removeEventListener(Event.ACTIVATE, receiver.activateHandler);
			_container.removeEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, receiver.focusChangeHandler);
			_container.removeEventListener(FocusEvent.KEY_FOCUS_CHANGE, receiver.focusChangeHandler);
			_container.removeEventListener(TextEvent.TEXT_INPUT, receiver.textInputHandler);
			_container.removeEventListener(MouseEvent.MOUSE_OUT, receiver.mouseOutHandler);
			removeMouseWheelListener();
			_container.removeEventListener(Event.DEACTIVATE, receiver.deactivateHandler);
			//	_container.removeEventListener(IMEEvent.IME_START_COMPOSITION, receiver.imeStartCompositionHandler); 
			// attach by literal event name to avoid Argo dependency
			_container.removeEventListener("imeStartComposition", receiver.imeStartCompositionHandler); 
			
			if (_container.contextMenu) 
				_container.contextMenu.removeEventListener(ContextMenuEvent.MENU_SELECT, receiver.menuSelectHandler);
			_container.removeEventListener(Event.COPY, receiver.editHandler); 
			_container.removeEventListener(Event.SELECT_ALL, receiver.editHandler);
			_container.removeEventListener(Event.CUT, receiver.editHandler);
			_container.removeEventListener(Event.PASTE, receiver.editHandler);
			_container.removeEventListener(Event.CLEAR, receiver.editHandler);
			
			clearSelectHandlers();	
		}
		
		/** @private */
		private function detachContainer():void
		{
			if (_minListenersAttached)
			{
				if (_container)
				{
					_container.removeEventListener(FocusEvent.FOCUS_IN, requiredFocusInHandler);
					_container.removeEventListener(MouseEvent.MOUSE_OVER, requiredMouseOverHandler);
					
					if(_allListenersAttached)
					{
						removeInteractionHandlers();				
						removeContextMenu();
						
						attachTransparentBackgroundForHit(true);
						_allListenersAttached = false;
					}
				}
				_minListenersAttached = false;
			}
			removeMouseWheelListener();
		}
		
		
		private function attachAllListeners():void
		{	
			if (!_allListenersAttached && textFlow && textFlow.interactionManager)
			{
				CONFIG::debug { assert(_minListenersAttached,"Bad call to attachAllListeners - won't detach"); }
				_allListenersAttached = true;
				if (_container)
				{
					attachContextMenu();
					attachInteractionHandlers();
				}
			}
		}
		
		/** @private */
		tlf_internal function addMouseWheelListener():void
		{
			if (!_mouseWheelListenerAttached)
			{
				_container.addEventListener(MouseEvent.MOUSE_WHEEL, getInteractionHandler().mouseWheelHandler);
				_mouseWheelListenerAttached = true;
			}
		}
		
		/** @private */
		tlf_internal function removeMouseWheelListener():void
		{
			if (_mouseWheelListenerAttached)
			{
				_container.removeEventListener(MouseEvent.MOUSE_WHEEL, getInteractionHandler().mouseWheelHandler);
				_mouseWheelListenerAttached = false;
			}
		}
		
		/** @private */
		tlf_internal function attachContextMenu():void
		{ _container.contextMenu = createContextMenu(); }
		
		/** @private */
		tlf_internal function removeContextMenu():void
		{ _container.contextMenu = null; }

		
		/** @private  
		 *
		 * Shared so that TextContainerManager can create the same ContextMenu. 
		 */
		static tlf_internal function createDefaultContextMenu():ContextMenu
		{
			var contextMenu:ContextMenu = new ContextMenu();
			contextMenu.clipboardMenu = true;
			contextMenu.clipboardItems.clear = true;
			contextMenu.clipboardItems.copy = true;
			contextMenu.clipboardItems.cut = true;
			contextMenu.clipboardItems.paste = true;
			contextMenu.clipboardItems.selectAll = true;
			return contextMenu;
		}
		
		/** 
		 * Creates a context menu for the ContainerController. 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>
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @see flash.ui.ContextMenu ContextMenu
		 */
		protected function createContextMenu():ContextMenu
		{
			return createDefaultContextMenu();
		}
		
		/** @private */
		tlf_internal function scrollTimerHandler(event:Event):void
		{
			// trace("BEGIN scrollTimerHandler");
			if (!_scrollTimer)
				return;
			
			// shut it down if not in this container
			if (textFlow.interactionManager == null || textFlow.interactionManager.activePosition < absoluteStart || textFlow.interactionManager.activePosition > absoluteStart+textLength)
				event = null;
			
			
			// We're listening for MOUSE_UP so we can cancel autoscrolling
			if (event is MouseEvent)
			{
				_scrollTimer.stop();
				_scrollTimer.removeEventListener(TimerEvent.TIMER, scrollTimerHandler);
				CONFIG::debug { assert(_container.stage ==  null || getContainerRoot() == event.currentTarget,"scrollTimerHandler bad target"); }
				event.currentTarget.removeEventListener(MouseEvent.MOUSE_UP, scrollTimerHandler);
				_scrollTimer = null;
			}
			else if (!event)
			{
				_scrollTimer.stop();
				_scrollTimer.removeEventListener(TimerEvent.TIMER, scrollTimerHandler);
				if (getContainerRoot())
					getContainerRoot().removeEventListener(	MouseEvent.MOUSE_UP, scrollTimerHandler);	
				_scrollTimer = null;
			}
			else if (_container.stage)
			{
				var containerPoint:Point = new Point(_container.stage.mouseX, _container.stage.mouseY);
				containerPoint = _container.globalToLocal(containerPoint);
				var scrollChange:int = autoScrollIfNecessaryInternal(containerPoint);
				if (scrollChange != 0 && interactionManager)		// force selection update if we actually scrolled and we have a selection manager
				{
					var mouseEvent:MouseEvent = new PsuedoMouseEvent(MouseEvent.MOUSE_MOVE,false,false,_container.stage.mouseX, _container.stage.mouseY,_container.stage,false,false,false,true);
					var stashedScrollTimer:Timer = _scrollTimer;	
					try
					{
						_scrollTimer =  null;
						interactionManager.mouseMoveHandler(mouseEvent);
					}
					catch (e:Error)
					{
						throw(e);
					}
					finally
					{
						_scrollTimer = stashedScrollTimer;
					}
				}
			}
			// trace("AFTER scrollTimerHandler");
		}
		
		/** 
		 * Handle a scroll event during a "drag" selection. 
		 *
		 * @param mouseX	The horizontal position of the mouse cursor on the stage.
		 * @param mouseY	The vertical position of the mouse cursor  on the stage.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		public function autoScrollIfNecessary(mouseX:int, mouseY:int):void
		{ 			
			if (flowComposer.getControllerAt(flowComposer.numControllers-1) != this)
			{
				var verticalText:Boolean = (effectiveBlockProgression == BlockProgression.RL);
				var lastController:ContainerController = flowComposer.getControllerAt(flowComposer.numControllers - 1);
				if ((verticalText && _horizontalScrollPolicy == ScrollPolicy.OFF) ||
					(!verticalText && _verticalScrollPolicy == ScrollPolicy.OFF))
					return;
				var r:Rectangle = lastController.container.getBounds(_container.stage);
				if (verticalText)
				{
					if (mouseY >= r.top && mouseY <= r.bottom)
						lastController.autoScrollIfNecessary(mouseX, mouseY);
				}
				else
				{
					if (mouseX >= r.left && mouseX <= r.right)
						lastController.autoScrollIfNecessary(mouseX, mouseY);
				}
			}
			
			// even if not the last container - may scroll if there are explicit linebreaks
			if (!_hasScrollRect)
				return;
			var containerPoint:Point = new Point(mouseX, mouseY);
			containerPoint = _container.globalToLocal(containerPoint); 			
			autoScrollIfNecessaryInternal(containerPoint);
		}
		
		/** 
		 * Handle a scroll event during a "drag" selection. 
		 *
		 * @param mouseX	The horizontal position of the mouse cursor on the stage.
		 * @param mouseY	The vertical position of the mouse cursor  on the stage.
		 * @returns positive number if scroll went forward in reading order, negative number if it went backwards, and 0 if no scroll
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		private function autoScrollIfNecessaryInternal(extreme:Point):int
		{
			CONFIG::debug 
			{ 
				assert(_hasScrollRect, "internal scrolling function called on non-scrollable container");
			}
			
			
			var scrollDirection:int = 0;
			
			if (extreme.y - containerScrollRectBottom > 0) {
				verticalScrollPosition += textFlow.configuration.scrollDragPixels;
				scrollDirection = 1;
			}
			else if (extreme.y - containerScrollRectTop < 0) {
				verticalScrollPosition -= textFlow.configuration.scrollDragPixels;
				scrollDirection = -1;
			}
			
			if (extreme.x - containerScrollRectRight > 0) {
				horizontalScrollPosition += textFlow.configuration.scrollDragPixels;
				scrollDirection = -1;
			}
			else if (extreme.x - containerScrollRectLeft < 0) {
				horizontalScrollPosition -= textFlow.configuration.scrollDragPixels;
				scrollDirection = 1;
			}
			
			// we need a timer so that the mouse doesn't have to continue moving when the mouse is outside the content area
			if (scrollDirection != 0 && !_scrollTimer) 
			{
				_scrollTimer = new Timer(textFlow.configuration.scrollDragDelay);	// 35 ms is the default auto-repeat interval for ScrollBars.
				_scrollTimer.addEventListener(TimerEvent.TIMER, scrollTimerHandler, false, 0, true);
				if (getContainerRoot())
				{
					getContainerRoot().addEventListener(MouseEvent.MOUSE_UP, scrollTimerHandler, false, 0, true);
					beginMouseCapture(); // TELL CLIENTS WE WANT mouseUpSomewhere events
				}
				_scrollTimer.start();
			}
			
			return scrollDirection;
		}
		
		/** @private */ 
		tlf_internal function getFirstVisibleLine():TextFlowLine
		{ return _shapeChildren.length ? _shapeChildren[0].userData : null; }
		/** @private */
		tlf_internal function getLastVisibleLine():TextFlowLine
		{ return _shapeChildren.length ? _shapeChildren[_shapeChildren.length-1].userData : null; }
		
		/** 
		 * Figure out the scroll distance required to scroll up or down by the specified number of lines.
		 * Negative numbers scroll upward, bringing more of the top of the TextFlow into view. Positive numbers 
		 * scroll downward, bringing the next line from the bottom into full view.
		 * 
		 * <p>When scrolling up, for example, the method makes the next line fully visible. If the next line is partially
		 * obscured and the number of lines specified is 1, the partially obscured line becomes fully visible.</p>
		 *
		 * @param nLines	The number of lines to scroll.
		 *
		 * @return 	the delta amount of space to scroll
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		public function getScrollDelta(numLines:int):Number
		{
			var flowComposer:IFlowComposer = textFlow.flowComposer;
			
			if (flowComposer.numLines == 0)
				return 0;
			
			// Now we want to calculate the top & bottom lines within the scrollRect. It's ok if they're just partially
			// visible. Once we determine these lines, we figure out how much we need to scroll in order to bring the
			// lines completely into view.
			
			var firstVisibleLine:TextFlowLine = getFirstVisibleLine();
			if (!firstVisibleLine)
				return 0;

			var lastVisibleLine:TextFlowLine = getLastVisibleLine();
			CONFIG::debug { assert(lastVisibleLine != null,"Expect lastVisibleLine when there is a firstVisibleLine"); }
				
			// trace("    // findFirstAndLastVisibleLine ",flowComposer.findLineIndexAtPosition(firstVisibleLine.absoluteStart),flowComposer.findLineIndexAtPosition(lastVisibleLine.absoluteStart));
			
			var newLineIndex:int;
			var lineIndex:int;
			if (numLines > 0) 
			{
				lineIndex = flowComposer.findLineIndexAtPosition(lastVisibleLine.absoluteStart);
				// If the last visible line is only partly visible, don't count it as visible. But make sure it overlaps by
				// at least two pixels, otherwise it doesn't look like its clipped.

				var lastTextLine:TextLine = lastVisibleLine.getTextLine(true);
				if (effectiveBlockProgression == BlockProgression.TB)
				{
					if ((lastTextLine.y + lastTextLine.descent) - containerScrollRectBottom > 2)
						--lineIndex;
				}
				else if (containerScrollRectLeft - (lastTextLine.x - lastTextLine.descent)  > 2)
					--lineIndex;
				
				// if we hit the end, force composition so that we get more lines - I picked a random amount to scroll forward, if its not enough, it will keep going
				while (lineIndex + numLines > flowComposer.numLines - 1 && flowComposer.damageAbsoluteStart < textFlow.textLength)	
				{
					var previousDamageStart:int = flowComposer.damageAbsoluteStart;
					flowComposer.composeToPosition(flowComposer.damageAbsoluteStart + 1000);
					// if we've made no progress, abort
					if (flowComposer.damageAbsoluteStart == previousDamageStart)
						return 0;
				}
				newLineIndex = Math.min(flowComposer.numLines-1, lineIndex + numLines);
			}
			if (numLines < 0) 
			{
				lineIndex = flowComposer.findLineIndexAtPosition(firstVisibleLine.absoluteStart);
				
				// If the first visible line is only partly visible, don't count it as visible. But make sure it overlaps by
				// at least two pixels, otherwise it doesn't look like its clipped.
				if (effectiveBlockProgression == BlockProgression.TB)
				{
					if (firstVisibleLine.y + 2 < containerScrollRectTop)
						++lineIndex;
				}
				else if (firstVisibleLine.x + firstVisibleLine.ascent > containerScrollRectRight + 2)
					++lineIndex;
				
				newLineIndex = Math.max(0, lineIndex + numLines);
			}
			
			var line:TextFlowLine = flowComposer.getLineAt(newLineIndex);
			if (line.absoluteStart < absoluteStart)		// don't scroll past the start of this controller -- previous text is in previous controller
				return 0;
			if (line.validity != TextLineValidity.VALID)
			{
				var leaf:FlowLeafElement = textFlow.findLeaf(line.absoluteStart);
				var paragraph:ParagraphElement = leaf.getParagraph();
				textFlow.flowComposer.composeToPosition(paragraph.getAbsoluteStart() + paragraph.textLength);
				line = flowComposer.getLineAt(newLineIndex);
				CONFIG::debug { assert(line.validity == TextLineValidity.VALID, "expected valid line after recomposing"); }
			}
			
			var verticalText:Boolean = effectiveBlockProgression == BlockProgression.RL;
			
			var newScrollPosition:Number;
			if (verticalText)
			{
				
				newScrollPosition =  numLines < 0 ? line.x + line.textHeight : line.x - line.descent + _compositionWidth;
				return newScrollPosition - horizontalScrollPosition;
			}
			
			newScrollPosition = numLines < 0 ? line.y : line.y + line.textHeight - _compositionHeight;
			return newScrollPosition - verticalScrollPosition;
		}
		
		/** 
		 * Processes the <code>MouseEvent.MOUSE_OVER</code> event when the client manages events. 
		 *
		 * @param event The MouseEvent object.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @includeExample examples\ContainerController_mouseOverHandlerExample.as -noswf
		 *
		 * @see flash.events.MouseEvent#MOUSE_OVER MouseEvent.MOUSE_OVER
		 */
		
		public function mouseOverHandler(event:MouseEvent):void
		{
			if (interactionManager && !event.isDefaultPrevented())
				interactionManager.mouseOverHandler(event);
		}
		
		/** @private Does required mouseOver handling.  Calls mouseOverHandler.  @see #mouseOverHandler */
		tlf_internal function requiredMouseOverHandler(event:MouseEvent):void
		{
			attachAllListeners();
			getInteractionHandler().mouseOverHandler(event);
		}
		
		/** Processes the <code>MouseEvent.MOUSE_OUT</code> event when the client manages events.
		 *
		 * @param event The MouseEvent object.
		 *
		 * @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
		{
			if (interactionManager && !event.isDefaultPrevented())
				interactionManager.mouseOutHandler(event);
		}
		
		/** Processes the <code>MouseEvent.MOUSE_WHEEL</code> event when the client manages events.
		 *
		 * @param event The MouseEvent object.
		 *
		 * @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;
			
			// Do the scroll and call preventDefault only if the there is enough text to scroll. Otherwise
			// we let the event bubble up and cause scrolling at the next level up in the client's container hierarchy.
			var verticalText:Boolean = effectiveBlockProgression == BlockProgression.RL;
			if (verticalText)
			{
				if (contentWidth > _compositionWidth && !_measureWidth)
				{
					horizontalScrollPosition += event.delta * textFlow.configuration.scrollMouseWheelMultiplier;
					event.preventDefault();
				}
			}
			else if (contentHeight > _compositionHeight && !_measureHeight)
			{
				verticalScrollPosition -= event.delta * textFlow.configuration.scrollMouseWheelMultiplier;
				event.preventDefault();
			}
		}
		
		
		/** Processes the <code>MouseEvent.MOUSE_DOWN</code> event when the client manages events. 
		 *
		 * @param event The MouseEvent object.
		 *
		 * @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
		{
			if (interactionManager && !event.isDefaultPrevented())
			{
				interactionManager.mouseDownHandler(event);
				// grab the focus - alternative is to listen to keyevents on the Application
				// is this necessary?
				if ( interactionManager.hasSelection())
					setFocus();
			}
		}
		
		/** @private Does required mouseDown handling.  Calls mouseDownHandler.  @see #mouseDownHandler */
		tlf_internal function requiredMouseDownHandler(event:MouseEvent):void
		{
			if (!_selectListenersAttached)
			{
				var containerRoot:DisplayObject = getContainerRoot();
				if (containerRoot)
				{
					containerRoot.addEventListener(MouseEvent.MOUSE_MOVE, rootMouseMoveHandler, false, 0, true); 
					containerRoot.addEventListener(MouseEvent.MOUSE_UP,   rootMouseUpHandler, false, 0, true);
					
					beginMouseCapture(); // TELL CLIENTS THAT WE WANT moueUpSomewhere EVENTS
					
					
					_selectListenersAttached = true;
				}
			}
			getInteractionHandler().mouseDownHandler(event); 
		}
		
		/** 
		 * Processes the <code>MouseEvent.MOUSE_UP</code> event when the client manages events.
		 *
		 * @param event The MouseEvent object.
		 *
		 * @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 (interactionManager && event && !event.isDefaultPrevented())
			{
				interactionManager.mouseUpHandler(event);
			}
		}		
		
		/** @private */
		tlf_internal function rootMouseUpHandler(event:MouseEvent):void
		{
			clearSelectHandlers();
			getInteractionHandler().mouseUpHandler(event);
		}
		
		
		private function clearSelectHandlers():void
		{	
			if (_selectListenersAttached)
			{
				CONFIG::debug { assert(getContainerRoot() != null,"No container root"); }
				getContainerRoot().removeEventListener(MouseEvent.MOUSE_MOVE, rootMouseMoveHandler); 					
				getContainerRoot().removeEventListener(MouseEvent.MOUSE_UP,   rootMouseUpHandler);
				endMouseCapture(); // TELL CLIENTS WE NO LONGER WANT mouseUpSomewhere EVENTS
				_selectListenersAttached = false;
			}
		}
		
		/** 
		 * 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
		{
			// trace("BEGIN MOUSECAPTURE");
			var sandboxManager:ISandboxSupport = getInteractionHandler() as ISandboxSupport
			if (sandboxManager && sandboxManager != this)
				sandboxManager.beginMouseCapture();
		}
		/** 
		 * 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
		{
			// trace("END MOUSECAPTURE");
			var sandboxManager:ISandboxSupport = getInteractionHandler() as ISandboxSupport
			if (sandboxManager && sandboxManager != this)
				sandboxManager.endMouseCapture();
		}
		/** 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(event:Event):void
		{
			rootMouseUpHandler(null);
			scrollTimerHandler(null);
		}
		/** 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(event:Event):void
		{
			return;	// do nothing right now
		}
		
		// What'd I hit???
		private function hitOnMyFlowExceptLastContainer(event:MouseEvent):Boolean
		{
			if (event.target is TextLine)
			{
				var tfl:TextFlowLine = TextLine(event.target).userData as TextFlowLine;
				if (tfl)
				{
					var para:ParagraphElement = tfl.paragraph;
					if(para.getTextFlow() == textFlow)
						return true;
				}
			}
			else if (event.target is Sprite)
			{
				// skip the last container in the chain
				for (var idx:int = 0; idx < textFlow.flowComposer.numControllers-1; idx++)
					if (textFlow.flowComposer.getControllerAt(idx).container == event.target)
						return true;
			}
			return false;
		}
		/** 
		 * Processes the <code>MouseEvent.MOUSE_MOVE</code> event when the client manages events.
		 *
		 * @param event The MouseEvent object.
		 *
		 * @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 (interactionManager && !event.isDefaultPrevented())
			{
				// only autoscroll if we haven't hit something on the stage related to this particular TextFlow
				if (event.buttonDown && !hitOnMyFlowExceptLastContainer(event))
					autoScrollIfNecessary(event.stageX, event.stageY);
				interactionManager.mouseMoveHandler(event);
			}
		}
		
		/** @private */
		tlf_internal function rootMouseMoveHandler(event:MouseEvent):void
		{   
			getInteractionHandler().mouseMoveHandler(event); 
		}
		
		/** Processes the <code>MouseEvent.DOUBLE_CLICK</code> event when the client manages events.
		 *
		 * @param event The MouseEvent object.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @includeExample examples\ContainerController_mouseDoubleClickHandlerExample.as -noswf
		 *
		 * @see flash.events.MouseEvent#DOUBLE_CLICK MouseEvent.DOUBLE_CLICK
		 */
		public function mouseDoubleClickHandler(event:MouseEvent):void
		{
			if (interactionManager && !event.isDefaultPrevented())
			{
				interactionManager.mouseDoubleClickHandler(event);
				// grab the focus - alternative is to listen to keyevents on the Application
				// is this necessary?
				if ( interactionManager.hasSelection())
					setFocus();
			}
		}
		
		/** Give focus to the text container. @private */
		tlf_internal function setFocus():void
		{
			//trace("setFocus container", id);
			if (_container.stage)
				_container.stage.focus = _container; 
		}
		
		/** @private */
		tlf_internal function getContainerController(container:DisplayObject):ContainerController
		{
			try
			{
				while (container)
				{
					var flowComposer:IFlowComposer = flowComposer;
					for (var i:int = 0; i < flowComposer.numControllers; i++)
					{
						var controller:ContainerController = flowComposer.getControllerAt(i);
						if (controller.container == container)
							return controller;
					}
					container = container.parent;
				}
			}
			catch (e:Error)
			{ }
			return null;
		}
		
		/** 
		 * Processes the <code>FocusEvent.KEY_FOCUS_CHANGE</code> and <code>FocusEvent.MOUSE_FOCUS_CHANGE</code> events
		 * when the client manages events.
		 *
		 * @param event The FocusEvent object.
		 *
		 * @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
		{
			// Figure out which controllers, if any, correspond to the DisplayObjects passed in the event.
			// Disallow the focus change if it comes back to this controller again -- this prevents
			// a focusOut followed by a focusIn, which we would otherwise get after clicking in the 
			// container that already has focus.
			
			// This is the controller that currently has the focus
			var focusController:ContainerController = getContainerController(DisplayObject(event.target));
			
			// This is the controller that is about to get the focus
			var newFocusController:ContainerController = getContainerController(event.relatedObject);
			
			/*trace("focusChange from controller", 
			focusController is ContainerControllerBase ? ContainerControllerBase(focusController).id : "unknownType", 
			newFocusController is ContainerControllerBase ? ContainerControllerBase(newFocusController).id : "unknownType");
			*/
			if (newFocusController == focusController)
			{
				//	trace("prevent focus change");
				event.preventDefault();
			}
		}
		
		/** Processes the <code>FocusEvent.FOCUS_IN</code> event when the client manages events.
		 *
		 * @param event The FocusEvent object.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @includeExample examples\ContainerController_focusInHandlerExample.as -noswf
		 *
		 * @see flash.events.FocusEvent#FOCUS_IN FocusEvent.FOCUS_IN
		 */
		public function focusInHandler(event:FocusEvent):void
		{
			var blinkRate:int = 0;
			//	trace("container", id, "focusIn");
			if (interactionManager)
			{
				interactionManager.focusInHandler(event);
				
				if (interactionManager.editingMode == EditingMode.READ_WRITE)
					blinkRate = interactionManager.focusedSelectionFormat.pointBlinkRate;				
			} 
			setBlinkInterval(blinkRate);
		}
		
		/** @private - does whatever focusIn handling is required and cannot be overridden */
		tlf_internal function requiredFocusInHandler(event:FocusEvent):void
		{
			attachAllListeners();
			// trace("ContainerController requiredFocusInHandler adding key handlers");
			_container.addEventListener(KeyboardEvent.KEY_DOWN, getInteractionHandler().keyDownHandler);
			_container.addEventListener(KeyboardEvent.KEY_UP,   getInteractionHandler().keyUpHandler);		
			_container.addEventListener(FocusEvent.KEY_FOCUS_CHANGE,   getInteractionHandler().keyFocusChangeHandler);	
			if (Configuration.playerEnablesSpicyFeatures && Configuration.hasTouchScreen)
				_container.addEventListener("softKeyboardActivating", getInteractionHandler().softKeyboardActivatingHandler);
			getInteractionHandler().focusInHandler(event);
		}
		
		/** Processes the <code>FocusEvent.FOCUS_OUT</code> event when the client manages events.
		 *
		 * @param event The FocusEvent object.
		 *
		 * @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
		{
			if (interactionManager)
			{
				interactionManager.focusOutHandler(event);
				setBlinkInterval(interactionManager.unfocusedSelectionFormat.pointBlinkRate);
			}
			else
				setBlinkInterval(0);
		}
		
		/** @private Does required focusOut handling.  Calls focusOutHandler.  @see #focusOutHandler */
		tlf_internal function requiredFocusOutHandler(event:FocusEvent):void
		{
			// trace("ContainerController requiredFocusOutHandler removing key handlers");
			_container.removeEventListener(KeyboardEvent.KEY_DOWN, getInteractionHandler().keyDownHandler);
			_container.removeEventListener(KeyboardEvent.KEY_UP,   getInteractionHandler().keyUpHandler);   			
			_container.removeEventListener(FocusEvent.KEY_FOCUS_CHANGE,   getInteractionHandler().keyFocusChangeHandler);   			
			if (Configuration.playerEnablesSpicyFeatures && Configuration.hasTouchScreen)
				_container.removeEventListener("softKeyboardActivating", getInteractionHandler().softKeyboardActivatingHandler);
			getInteractionHandler().focusOutHandler(event);
		}
		
		/** Processes the <code>Event.ACTIVATE</code> event when the client manages events.
		 *
		 * @param event The Event object.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @includeExample examples\ContainerController_activateHandlerExample.as -noswf
		 *
		 * @see flash.events.Event#ACTIVATE Event.ACTIVATE
		 */						
		public function activateHandler(event:Event):void
		{
			if (interactionManager)
				interactionManager.activateHandler(event);
		}
		
		/** Processes the <code>Event.DEACTIVATE</code> event when the client manages events. 
		 *
		 * @param event The Event object.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flash.events.Event#DEACTIVATE Event.DEACTIVATE
		 */
		
		public function deactivateHandler(event:Event):void
		{
			if (interactionManager)
				interactionManager.deactivateHandler(event);
		}		
		
		/** Processes the <code>KeyboardEvent.KEY_DOWN</code> event when the client manages events.
		 *
		 * @param The KeyboardEvent object.
		 *
		 * @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 (interactionManager && !event.isDefaultPrevented())
				interactionManager.keyDownHandler(event);
		}
		
		/** Processes the <code>Keyboard.KEY_UP</code> event when the client manages events.
		 *
		 * @param event The KeyboardEvent object.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @includeExample examples\ContainerController_keyUpHandlerExample.as -noswf
		 *
		 * @see flash.events.KeyboardEvent#KEY_UP KeyboardEvent.KEY_UP
		 */
		
		public function keyUpHandler(event:KeyboardEvent):void
		{
			if (interactionManager && !event.isDefaultPrevented())
				interactionManager.keyUpHandler(event);
		}
		
		/** Processes the <code>FocusEvent.KEY_FOCUS_CHANGE</code> event when the client manages events.
		 *
		 * @param event The FocusEvent object.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @see flash.events.FocusEvent#KEY_FOCUS_CHANGE FocusEvent.KEY_FOCUS_CHANGE
		 */
		public function keyFocusChangeHandler(event:FocusEvent):void
		{
			if (interactionManager)
				interactionManager.keyFocusChangeHandler(event);
		}		
		/** Processes the <code>TextEvent.TEXT_INPUT</code> event when the client manages events.
		 *
		 * @param event  The TextEvent object.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @includeExample examples\ContainerController_textInputHandlerExample.as -noswf
		 *
		 * @see flash.events.TextEvent#TEXT_INPUT TextEvent.TEXT_INPUT
		 */
		
		public function textInputHandler(event:TextEvent):void
		{
			if (interactionManager && !event.isDefaultPrevented())
				interactionManager.textInputHandler(event);
		}
		
		/** Processes the <code>SoftKeyboardEvent.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 (interactionManager)
				interactionManager.softKeyboardActivatingHandler(event);
		}
		
		/** Processes the <code>IMEEvent.IME_START_COMPOSITION</code> event when the client manages events.
		 *
		 * @param event  The IMEEvent object.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flash.events.IMEEvent.IME_START_COMPOSITION
		 */
		
		public function imeStartCompositionHandler(event:IMEEvent):void
		{
			if (interactionManager)
				interactionManager.imeStartCompositionHandler(event);
		}
		
		
		/** 
		 * Processes the <code>ContextMenuEvent.MENU_SELECT</code> event when the client manages events.
		 * 
		 * @param The ContextMenuEvent object.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @includeExample examples\ContainerController_menuSelectHandlerExample.as -noswf
		 * 
		 * @see flash.events.ContextMenuEvent#MENU_SELECT ContextMenuEvent.MENU_SELECT
		 */						
		public function menuSelectHandler(event:ContextMenuEvent):void
		{			
			if (interactionManager)
			{
				interactionManager.menuSelectHandler(event);
			}
			else
			{
				var contextMenu:ContextMenu = _container.contextMenu;
				if (contextMenu)
				{
					var cbItems:ContextMenuClipboardItems = contextMenu.clipboardItems;
					cbItems.copy = false;
					cbItems.cut = false;
					cbItems.paste = false;
					cbItems.selectAll = false;
					cbItems.clear = false;
				}
			}
		}
		
		/**
		 * Processes an edit event (CUT, COPY, PASTE, SELECT_ALL) when the client manages events.
		 * 
		 * @param The Event object.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @includeExample examples\ContainerController_editHandlerExample.as -noswf
		 * 
		 * @see flash.events.Event Event
		 */	
		
		public function editHandler(event:Event):void
		{
			if (interactionManager && !event.isDefaultPrevented())
				interactionManager.editHandler(event);
			
			// re-enable context menu so following keyboard shortcuts will work
			var contextMenu:ContextMenu = _container.contextMenu;
			if (contextMenu)
			{
				contextMenu.clipboardItems.clear = true;
				contextMenu.clipboardItems.copy = true;
				contextMenu.clipboardItems.cut = true;
				contextMenu.clipboardItems.paste = true;
				contextMenu.clipboardItems.selectAll = true;
			}
		}
		
		/** 
		 * Sets the range of selected text in a component implementing ITextSupport.
		 * If either of the arguments is out of bounds the selection should not be changed.
		 * Components which wish to support inline IME should call into this method.
		 * 
		 * @param anchorIndex The zero-based index value of the character at the anchor end of the selection
		 *
		 * @param activeIndex The zero-based index value of the character at the active end of the selection.
		 * 
		 * @playerversion Flash 10.0
		 * @langversion 3.0
		 */
		public function selectRange(anchorIndex:int, activeIndex:int):void
		{
			if(interactionManager && interactionManager.editingMode != EditingMode.READ_ONLY)
			{
				interactionManager.selectRange(anchorIndex, activeIndex);
			}
		}
		
		//--------------------------------------------------------------------------
		//
		//  Cursor blinking code
		//
		//--------------------------------------------------------------------------
		
		// TODO Want to evaluate whether there's a cleaner way to do this
		
		private var blinkTimer:Timer;
		private var blinkObject:DisplayObject;
		
		/**
		 * Starts a DisplayObject cursor blinking by changing its alpha value
		 * over time.
		 * 
		 * @param obj The DisplayObject to use as the cursor.
		 * 
		 */
		private function startBlinkingCursor(obj:DisplayObject, blinkInterval:int):void
		{
			if (!blinkTimer)
				blinkTimer = new Timer(blinkInterval,0);
			blinkObject = obj;
			blinkTimer.addEventListener(TimerEvent.TIMER,blinkTimerHandler, false, 0, true);
			blinkTimer.start();
		}
		
		/**
		 * Stops cursor from blinking
		 * @private
		 */
		protected function stopBlinkingCursor():void
		{
			if (blinkTimer)
				blinkTimer.stop();
			blinkObject = null;
		}	
		
		private function blinkTimerHandler(event:TimerEvent):void
		{
			blinkObject.alpha = (blinkObject.alpha == 1.0) ? 0.0 : 1.0;
		}
		
		/** 
		 * Set the blink interval.
		 * 
		 * @param intervalMS - number of microseconds between blinks
		 * @private
		 */
		protected function setBlinkInterval(intervalMS:int):void
		{
			var blinkInterval:int = intervalMS;
			if (blinkInterval == 0)
			{
				// turn off the blinking
				if (blinkTimer)
					blinkTimer.stop();
				if (blinkObject)
					blinkObject.alpha = 1.0;
			}
			else if (blinkTimer)
			{
				blinkTimer.delay = blinkInterval;
				if (blinkObject)
					blinkTimer.start();
			}
		}
		
		/** Draw the caret for a selection 
		 * @param x	x-location where caret is drawn
		 * @param y y-location where caret is drawn
		 * @param w	width of caret
		 * @param h	height of caret
		 * @private
		 */
		tlf_internal function drawPointSelection(selFormat:SelectionFormat, x:Number,y:Number,w:Number,h:Number):void
		{
			var selObj:Shape = new Shape();
			
			// Oh, this is ugly. If we are in right aligned text, and there is no padding, and the scrollRect is set, 
			// then in an empty line (or if the point is at the right edge of the line), the blinking cursor is not
			// visible because it is clipped out. Move it in so we can see it. 
			if (_hasScrollRect)
			{
				if (effectiveBlockProgression == BlockProgression.TB)
				{
					if (x >= containerScrollRectRight)
						x -= w;
				} 
				else if (y >= containerScrollRectBottom)
					y -= h;
			}
			
			CONFIG::debug { assert(interactionManager.activePosition == interactionManager.anchorPosition,"bad call to drawPointSelection"); }
			selObj.graphics.beginFill(selFormat.pointColor);
			// pixel snap - works for unscaled text - scaled text will have to accept fuzzy cursors
			selObj.graphics.drawRect(int(x),int(y),w,h);
			selObj.graphics.endFill();
			
			// make it blink.  But we never blink unless the text is r/w
			if (selFormat.pointBlinkRate != 0 && interactionManager.editingMode == EditingMode.READ_WRITE)
				startBlinkingCursor(selObj, selFormat.pointBlinkRate);
			
			addSelectionChild(selObj);
		}
		
		/** Add selection shapes to the displaylist. @private */
		tlf_internal function addSelectionShapes(selFormat:SelectionFormat, selectionAbsoluteStart:int, selectionAbsoluteEnd:int): void
		{
			if (!interactionManager || _textLength == 0 || selectionAbsoluteStart == -1 || selectionAbsoluteEnd == -1)
				return;
			
			var prevLine:TextFlowLine;
			var nextLine:TextFlowLine;
			
			if (selectionAbsoluteStart != selectionAbsoluteEnd)
			{
				// adjust selectionAbsoluteStart and selectionAbsoluteEnd to be within this controller
				var absoluteControllerStart:int = this.absoluteStart;
				var absoluteControllerEnd:int = this.absoluteStart+this.textLength;
				
				if (selectionAbsoluteStart < absoluteControllerStart)
					selectionAbsoluteStart = absoluteControllerStart;
				else if (selectionAbsoluteStart >= absoluteControllerEnd)
					return;	// nothing to do
				
				// backup one so that 
				if (selectionAbsoluteEnd > absoluteControllerEnd)
					selectionAbsoluteEnd = absoluteControllerEnd;
				else if (selectionAbsoluteEnd < absoluteControllerStart)
					return;	// nothing to do
				
				CONFIG::debug { assert(selectionAbsoluteStart <= selectionAbsoluteEnd,"addSelectionShapes: bad range"); }
				CONFIG::debug { assert(selectionAbsoluteStart >= absoluteControllerStart,"addSelectionShapes: bad range"); }
				CONFIG::debug { assert(selectionAbsoluteEnd <= absoluteControllerEnd,"addSelectionShapes: bad range"); }
				
				var begLine:int = flowComposer.findLineIndexAtPosition(selectionAbsoluteStart);
				var endLine:int = selectionAbsoluteStart == selectionAbsoluteEnd ? begLine : flowComposer.findLineIndexAtPosition(selectionAbsoluteEnd);
				// watch for going past the end
				if (endLine >= flowComposer.numLines)
					endLine = flowComposer.numLines-1;
				
				var selObj:Shape = new Shape();
				prevLine = begLine ? flowComposer.getLineAt(begLine-1) : null;
				var line:TextFlowLine = flowComposer.getLineAt(begLine); 
				
				for (var idx:int = begLine; idx <= endLine; idx++)
				{
					nextLine = idx != flowComposer.numLines - 1 ? flowComposer.getLineAt(idx+1) : null;
					
					line.hiliteBlockSelection(selObj, selFormat, this._container,
						selectionAbsoluteStart < line.absoluteStart ? line.absoluteStart : selectionAbsoluteStart,
						selectionAbsoluteEnd > line.absoluteStart+line.textLength ? line.absoluteStart+line.textLength : selectionAbsoluteEnd, prevLine, nextLine);
					
					var temp:TextFlowLine = line;
					line = nextLine;
					prevLine = temp;
				}
				
				addSelectionChild(selObj);		
			}
			else
			{
				var lineIdx:int = flowComposer.findLineIndexAtPosition(selectionAbsoluteStart);
				// TODO: there is ambiguity - are we at the end of the currentLine or the beginning of the next one?
				// however must stick to the end of the last line
				if (lineIdx == flowComposer.numLines)
					lineIdx--;
				if (flowComposer.getLineAt(lineIdx).controller == this)
				{
					prevLine = lineIdx != 0 ? flowComposer.getLineAt(lineIdx-1) : null;
					nextLine = lineIdx != flowComposer.numLines-1 ? flowComposer.getLineAt(lineIdx+1) : null
					flowComposer.getLineAt(lineIdx).hilitePointSelection(selFormat, selectionAbsoluteStart, this._container, prevLine, nextLine);
				}
			}
		}
		
		/** Remove all selection shapes. @private */
		tlf_internal function clearSelectionShapes(): void
		{
			stopBlinkingCursor();
			
			var selectionSprite:DisplayObjectContainer = getSelectionSprite(false);
			if (selectionSprite != null)
			{
				if (selectionSprite.parent)
					removeSelectionContainer(selectionSprite);
				while (selectionSprite.numChildren > 0)
					selectionSprite.removeChildAt(0);
				return;
			}
		}
		
		/** Add a selection child. @private */
		tlf_internal function addSelectionChild(child:DisplayObject):void
		{
			// If there's no selectionSprite on this controller, we use the parent's.
			// That means we have to translate the coordinates.
			// TODO: this only supports one level of ntesting
			var selectionSprite:DisplayObjectContainer = getSelectionSprite(true);
			
			if (selectionSprite == null)
			{
				return;
			}
			
			var selFormat:SelectionFormat = interactionManager.currentSelectionFormat;
			var curBlendMode:String = (interactionManager.activePosition == interactionManager.anchorPosition) ? selFormat.pointBlendMode : selFormat.rangeBlendMode;
			var curAlpha:Number = (interactionManager.activePosition == interactionManager.anchorPosition) ? selFormat.pointAlpha : selFormat.rangeAlpha;
			if (selectionSprite.blendMode != curBlendMode)
				selectionSprite.blendMode = curBlendMode;
			
			if (selectionSprite.alpha != curAlpha)
				selectionSprite.alpha = curAlpha;
			
			if (selectionSprite.numChildren == 0)
				addSelectionContainer(selectionSprite);
			
			selectionSprite.addChild(child);
		}
		
		/** Test for a selection child. @private */
		tlf_internal function containsSelectionChild(child:DisplayObject):Boolean
		{ 
			var selectionSprite:DisplayObjectContainer = getSelectionSprite(false);
			if (selectionSprite == null)
			{
				return false;
			}
			return selectionSprite.contains(child); 
		}
		
		/** @private */
		tlf_internal function getBackgroundShape():Shape
		{
			if(!_backgroundShape)
			{
				_backgroundShape = new Shape();
				addBackgroundShape(_backgroundShape);
			}
			
			return _backgroundShape;
		}
		
	/*	CONFIG::debug private function containsFloats(textFlow:TextFlow):Boolean
		{
			if (textFlow)
				for (var leaf:FlowLeafElement = textFlow.getFirstLeaf(); leaf != null; leaf = leaf.getNextLeaf())
					if (leaf is InlineGraphicElement && InlineGraphicElement(leaf).float != Float.NONE)
						return true;
			return false;
		} */
		
		/** @private */
		tlf_internal function getEffectivePaddingLeft():Number
		{ return computedFormat.paddingLeft == FormatValue.AUTO ? computedFormat.borderLeftWidth + computedFormat.marginLeft : computedFormat.paddingLeft + computedFormat.borderLeftWidth + computedFormat.marginLeft; }
		/** @private */
		tlf_internal function getEffectivePaddingRight():Number
		{ return computedFormat.paddingRight == FormatValue.AUTO ? computedFormat.borderRightWidth + computedFormat.marginRight : computedFormat.paddingRight + computedFormat.borderRightWidth + computedFormat.marginRight; }
		/** @private */
		tlf_internal function getEffectivePaddingTop():Number
		{ return computedFormat.paddingTop == FormatValue.AUTO ? computedFormat.borderTopWidth + computedFormat.marginTop : computedFormat.paddingTop + computedFormat.borderTopWidth + computedFormat.marginTop; }
		/** @private */
		tlf_internal function getEffectivePaddingBottom():Number
		{ return computedFormat.paddingBottom == FormatValue.AUTO ? computedFormat.borderBottomWidth + computedFormat.marginBottom : computedFormat.paddingBottom + computedFormat.borderBottomWidth + computedFormat.marginBottom; }
		
		/** @private */
		tlf_internal function getTotalPaddingLeft():Number
		{ return getEffectivePaddingLeft() + (_rootElement ? _rootElement.getEffectivePaddingLeft() : 0); }
		/** @private */
		tlf_internal function getTotalPaddingRight():Number
		{ return getEffectivePaddingRight() + (_rootElement ? _rootElement.getEffectivePaddingRight() : 0); }
		/** @private */
		tlf_internal function getTotalPaddingTop():Number
		{ return getEffectivePaddingTop() + (_rootElement ? _rootElement.getEffectivePaddingTop() : 0); }
		/** @private */
		tlf_internal function getTotalPaddingBottom():Number
		{ return getEffectivePaddingBottom() + (_rootElement ? _rootElement.getEffectivePaddingBottom() : 0); }
		
		private var _selectionSprite:Sprite;
		
		/** @private */
		tlf_internal function getSelectionSprite(createForDrawing:Boolean):DisplayObjectContainer
		{
			if (createForDrawing)
			{
				if (_selectionSprite == null)
				{
					_selectionSprite = new Sprite();
					_selectionSprite.mouseEnabled = false;
					_selectionSprite.mouseChildren = false;
				}
			}
			return _selectionSprite;
		}
		
		static private function createContainerControllerInitialFormat():ITextLayoutFormat
		{
			var ccif:TextLayoutFormat = new TextLayoutFormat();
			ccif.columnCount = FormatValue.INHERIT;
			ccif.columnGap = FormatValue.INHERIT;
			ccif.columnWidth = FormatValue.INHERIT;
			ccif.verticalAlign = FormatValue.INHERIT;
			return ccif;
		}
		
		static private var _containerControllerInitialFormat:ITextLayoutFormat = createContainerControllerInitialFormat();
		
		/** 
		* @private
		* Specifies the initial format (ITextLayoutFormat instance) for a new ContainerController. The runtime
		* applies this to the format property of all new containers on creation.
		*
		* By default, sets the column format values to "inherit"; all other format values are inherited.
		*
		* @playerversion Flash 10
		* @playerversion AIR 1.5
		* @langversion 3.0
		*
		* @see flashx.textLayout.elements.TextFlow TextFlow
		*/
		
		static public function get containerControllerInitialFormat():ITextLayoutFormat
		{ return _containerControllerInitialFormat; }
		static public function set containerControllerInitialFormat(val:ITextLayoutFormat):void
		{ _containerControllerInitialFormat = val; }
		
		
		/** @private */
		protected function get attachTransparentBackground():Boolean
		{ return true; }
		
		/** @private */
		tlf_internal function clearCompositionResults():void
		{
			setTextLength(0); 
			
			for each (var textLine:TextLine in _shapeChildren)
			{
				removeTextLine(textLine);
				CONFIG::debug { Debugging.traceFTECall(null,_container,"removeTextLine",textLine); }
			}
			_shapeChildren.length = 0;
			_linesInView.length = 0;
			if (_floatsInContainer)
				_floatsInContainer.length = 0;
			if (_composedFloats)
				_composedFloats.length = 0;
		//	trace("clear composedFloats for container", flowComposer ? flowComposer.getControllerIndex(this) : 0);
		}
		
		private static var scratchRectangle:Rectangle = new Rectangle();
		
		/** Add DisplayObjects that were created by composition to the container. @private */
		tlf_internal function updateCompositionShapes():void
		{
			if(!shapesInvalid)
			{
				return;
			}			
			
			// reclamp vertical/horizontal scrollposition - addresses Watson 2380962
			var originalYScroll:Number = _yScroll;
			if (verticalScrollPolicy != ScrollPolicy.OFF && !_measureHeight)
				_yScroll = computeVerticalScrollPosition(_yScroll,false);
			var originalXScroll:Number = _xScroll;
			if (horizontalScrollPolicy != ScrollPolicy.OFF && !_measureWidth)
				_xScroll = computeHorizontalScrollPosition(_xScroll,false);
			var scrolled:Boolean = (originalYScroll != _yScroll || originalXScroll != _xScroll);	// true if scroll values were changed - we need to notify in this case
			
			// If we've scrolled, force all lines to be regathered since lines may now be in view that
			// previously were not.
			if (scrolled)
				_linesInView.length = 0;
			
			// Post all the new TextLines to the display list, and remove any old TextLines left from last time. Do this
			// in a non-destructive way so that lines that have not been changed are not touched. This reduces redraw time.
			fillShapeChildren();
			var newShapeChildren:Array = _linesInView;
			
			var childIdx:int = getFirstTextLineChildIndex(); // index where the first text line must appear at in its container  
			var newIdx:int = 0;		// offset into newShapeChildren
			var shapeChildrenStartIdx:int = 0;	// starting offset into shapeChildren

			// If we composed starting at the middle of the container, then _linesInView will contain only the lines that were
			// in view and changed. In that case, we want to skip the lines in the beginning that weren't changed, and start 
			// the iteration from the point where the new lines start. So we get the first new line, go back one, and find where
			// we are in the old list. If the line before the first new line was not displayed before, thenwe start from the 
			// beginning as usual. This can happen if we're scrolled forward, and then edit the first visible line.
			if (_updateStart > absoluteStart && newShapeChildren.length > 0)
			{
				var firstTextLine:TextLine = newShapeChildren[0];
				var firstLine:TextFlowLine = TextFlowLine(firstTextLine.userData);
				var prevLine:TextFlowLine = flowComposer.findLineAtPosition(firstLine.absoluteStart - 1);
				var prevTextLine:TextLine = prevLine.peekTextLine(); 
				shapeChildrenStartIdx = _shapeChildren.indexOf(prevTextLine);
				if (shapeChildrenStartIdx >= 0)
				{
					shapeChildrenStartIdx++;
					childIdx += shapeChildrenStartIdx;
				}
				else
					shapeChildrenStartIdx = 0;
			}
			var oldIdx:int = shapeChildrenStartIdx;		// offset into shapeChildren
			
			while (newIdx != newShapeChildren.length)
			{
				var newChild:TextLine = newShapeChildren[newIdx];
				if (newChild == _shapeChildren[oldIdx])
				{
					// Same shape is in both lists, no change necessary, advance to next item in each list
					CONFIG::debug { assert(newChild.parent == _container, "updateCompositionShapes expected line was already a child of the container"); }
					childIdx++;
					newIdx++;
					oldIdx++;
					continue;
				}
				
				var newChildIdx:int = _shapeChildren.indexOf(newChild);
				if (newChildIdx == -1)
				{
					// Shape is in the new list, but not in the old list, add it to the display list at the current location, and advance to next item
					addTextLine(newChild, childIdx++);
					CONFIG::debug { Debugging.traceFTECall(null,_container,"addTextLine",newChild); }
					newIdx++;
				}
				else
				{
						// The shape is on both lists, but there are several intervening "old" shapes in between. We'll remove the old shapes that
					// come before the new one we want to insert.
					removeAndRecycleTextLines (oldIdx, newChildIdx);
					oldIdx = newChildIdx;
				}
			}
			
			// remove any trailing children no longer displayed
			removeAndRecycleTextLines (oldIdx, _shapeChildren.length);
			
			// Update shapeChildren to reflect all these changes
			if (shapeChildrenStartIdx > 0)
			{
				// We only updated some of the lines. Remove the old versions off the end, and add in the new ones from _linesInView
				_shapeChildren.length = shapeChildrenStartIdx;		// truncate
				_shapeChildren = _shapeChildren.concat(_linesInView);	// append _linesInView to end of _shapeChildren
				_linesInView.length = 0;	// truncate
			}
			else
			{	// We updated all of the lines. 
				_linesInView = _shapeChildren;		// move the old array over to _linesInView, so we reuse its storage
				_linesInView.length = 0;
				_shapeChildren = newShapeChildren;
			}

			if ((_floatsInContainer && _floatsInContainer.length > 0) || (_composedFloats && _composedFloats.length > 0))
				updateGraphics(_updateStart);
			
			shapesInvalid = false;
			
			// _textFrame.updateVisibleRectangle(this._visibleRect);
			updateVisibleRectangle();
			
			var tf:TextFlow = this.textFlow;
			// Set the Ctrl key condition
			var needsCtrlKey:Boolean = (interactionManager != null && interactionManager.editingMode == EditingMode.READ_WRITE);
			// Generate the hit test area for the LinkElements of the visible lines
			var firstVisibleLine:TextFlowLine = getFirstVisibleLine();
			var lastVisibleLine:TextFlowLine = getLastVisibleLine();
			scratchRectangle.left = _contentLeft; 
			scratchRectangle.top = _contentTop; 
			scratchRectangle.width = _contentWidth; 
			scratchRectangle.height = _contentHeight; 
			_mouseEventManager.updateHitTests(effectiveBlockProgression == BlockProgression.RL && _hasScrollRect ? _contentWidth : 0, 
				scratchRectangle, tf, 
				firstVisibleLine ? firstVisibleLine.absoluteStart : _absoluteStart, 
				lastVisibleLine ? lastVisibleLine.absoluteStart + lastVisibleLine.textLength - 1 : _absoluteStart, 
				this,
				needsCtrlKey);
			
			_updateStart = _rootElement.textLength;

			// If we're measuring, then the measurement values may have changed since last time.
			// Force the transparent background to redraw, so that mouse events will work for the 
			// entire content area.
			if (_measureWidth || _measureHeight)
				attachTransparentBackgroundForHit(false);
			
			if (tf.backgroundManager)
			{
				tf.backgroundManager.onUpdateComplete(this);
			}
			
			// If we updated the scroll values, we need to send an event
			if (scrolled && tf.hasEventListener(TextLayoutEvent.SCROLL))
			{
				if (originalYScroll != _yScroll)
					tf.dispatchEvent(new ScrollEvent(TextLayoutEvent.SCROLL, false, false, ScrollEventDirection.VERTICAL, _yScroll - originalYScroll));
				if (originalXScroll != _xScroll)
					tf.dispatchEvent(new ScrollEvent(TextLayoutEvent.SCROLL, false, false, ScrollEventDirection.HORIZONTAL, _xScroll - originalXScroll));
			}
			
			if (tf.hasEventListener(UpdateCompleteEvent.UPDATE_COMPLETE))
			{
				tf.dispatchEvent(new UpdateCompleteEvent(UpdateCompleteEvent.UPDATE_COMPLETE,false,false,tf, this));
			}
			
		//	CONFIG::debug { validateLines(); }
		} 
		
		CONFIG::debug private function updateGraphicsCheck(previousGraphics:Array):void
		{
			var graphicDisplayObject:DisplayObject;
			var flowComposer:IFlowComposer = textFlow.flowComposer;
			
			// correctness check
			// iterate all graphics
			// for each one: is it visible?
			// if so, it should be a descendent of the container
			// if not, it should NOT be a descendent of the container

			// iterate all graphics previously visible
			// for each one: is it in the composedGraphics list?
			// if not, it should NOT be a descendent of the container
			for each (graphicDisplayObject in previousGraphics)
			{
				if (getIndexOfFloat(graphicDisplayObject) < 0)
					assert(!container.contains(graphicDisplayObject), "Previously visible graphic should have been removed from display list");
			}

			// Calculate the last possible anchor position for a visible float. The float can't be past the line *after* the last line.
			// In case that's an uncomposed line with the entire rest of the TextFlow in it, we cap what we'll look at to 2000 chars
			// past the last visible line end. This keeps us from iterating forever in a long text flow.
			//	var followingLineIndex:int = flowComposer.findLineIndexAtPosition(lastVisiblePosition) + 1;
			var firstLine:TextFlowLine = getFirstVisibleLine();
			var lastLine:TextFlowLine = getLastVisibleLine();
			var firstVisiblePosition:int = firstLine ? firstLine.absoluteStart : this.absoluteStart;
			var lastVisiblePosition:int = lastLine ? lastLine.absoluteStart + lastLine.textLength : this.absoluteStart + textLength;
			var followingLine:TextFlowLine = flowComposer.findLineAtPosition(lastVisiblePosition);
			var lastPossibleFloatPosition:int = followingLine ? followingLine.absoluteStart + followingLine.textLength : this.absoluteStart + textLength;
			lastPossibleFloatPosition = Math.min(lastPossibleFloatPosition, this.absoluteStart + textLength);
			lastPossibleFloatPosition = Math.min(lastPossibleFloatPosition, lastVisiblePosition + 2000);
			lastPossibleFloatPosition = Math.min(lastPossibleFloatPosition, flowComposer.damageAbsoluteStart);
			CONFIG::debug { assert(lastPossibleFloatPosition <= this.absoluteStart + textLength, "Expected lastPossibleFloatPosition to be before end of container"); }
			
			// Get visible area
			var wmode:String = effectiveBlockProgression;
			var width:Number = _measureWidth ? _contentWidth : _compositionWidth;
			var height:Number = _measureHeight ? _contentHeight : _compositionHeight;
			var adjustX:Number = (wmode == BlockProgression.RL) ? _xScroll - width : _xScroll;
			var adjustY:Number = _yScroll;
			
			var numGraphics:int = _composedFloats.length;
			for (var graphicIndex:int = 0; graphicIndex < numGraphics; ++graphicIndex)
			{
				var floatInfo:FloatCompositionData = _composedFloats[graphicIndex];
				graphicDisplayObject = floatInfo.graphic;
				
				var shouldDisplayGraphic:Boolean;
				if (!graphicDisplayObject)
					shouldDisplayGraphic = false;
				else 
				{
					if (floatInfo.floatType == Float.NONE)
						shouldDisplayGraphic = floatInfo.absolutePosition >= firstVisiblePosition && floatInfo.absolutePosition < lastVisiblePosition;
					else
						shouldDisplayGraphic = floatIsVisible(wmode, adjustX, adjustY, width, height, floatInfo) && floatInfo.absolutePosition < lastPossibleFloatPosition && floatInfo.absolutePosition >= this.absoluteStart;
				}
				
				if (shouldDisplayGraphic)
					assert(shouldDisplayGraphic == container.contains(graphicDisplayObject), 
						shouldDisplayGraphic ? "Graphic should be in view, but is not a descendent of the container" : "Graphic should not be in view, but is a descendent of the container");
			}
		}
		
		
		
		tlf_internal function updateGraphics(updateStart:int):void
		{
			var inlineHolder:DisplayObjectContainer;
			
			var visibleFloats:Array = [];
			
			// If we have new floats that have been composed into container, we add them here.
			// Also, we remove any that are no longer in the container. Only change those
			// floats that are within the area that was recomposed.
			
			var floatInfo:FloatCompositionData;
			var float:DisplayObject;
			var firstLine:TextFlowLine = getFirstVisibleLine();
			var lastLine:TextFlowLine = getLastVisibleLine();
			var firstVisiblePosition:int = firstLine ? firstLine.absoluteStart : this.absoluteStart;
			var lastVisiblePosition:int = lastLine ? lastLine.absoluteStart + lastLine.textLength : this.absoluteStart + textLength;

			// Calculate the last possible anchor position for a visible float. The float can't be past the line *after* the last line.
			// In case that's an uncomposed line with the entire rest of the TextFlow in it, we cap what we'll look at to 2000 chars
			// past the last visible line end. This keeps us from iterating forever in a long text flow.
		//	var followingLineIndex:int = flowComposer.findLineIndexAtPosition(lastVisiblePosition) + 1;
			var followingLine:TextFlowLine = flowComposer.findLineAtPosition(lastVisiblePosition);
			var lastPossibleFloatPosition:int = followingLine ? followingLine.absoluteStart + followingLine.textLength : this.absoluteStart + textLength;
			lastPossibleFloatPosition = Math.min(lastPossibleFloatPosition, this.absoluteStart + textLength);
			lastPossibleFloatPosition = Math.min(lastPossibleFloatPosition, lastVisiblePosition + 2000);
			lastPossibleFloatPosition = Math.min(lastPossibleFloatPosition, flowComposer.damageAbsoluteStart);
			CONFIG::debug { assert(lastPossibleFloatPosition <= this.absoluteStart + textLength, "Expected lastPossibleFloatPosition to be before end of container"); }
			
			// Get visible area
			var wmode:String = effectiveBlockProgression;
			var width:Number = _measureWidth ? _contentWidth : _compositionWidth;
			var height:Number = _measureHeight ? _contentHeight : _compositionHeight;
			var adjustX:Number = (wmode == BlockProgression.RL) ? _xScroll - width : _xScroll;
			var adjustY:Number = _yScroll;

			var floatIndex:int = findFloatIndexAtOrAfter(updateStart);
			var containerListIndex:int = 0;
			var childIdx:int = getFirstTextLineChildIndex(); // index where the first text line must appear at in its container  
			if (floatIndex > 0)		
			{
				// starting from the middle, need to skip over the initial entries already in the 
				// container list that are not being changed. Add them to the list of visible graphics, so they don't get dropped off.
				floatInfo = _composedFloats[floatIndex - 1];
				containerListIndex = _floatsInContainer.indexOf(floatInfo.graphic);
				while (containerListIndex == -1 && floatIndex > 0)
				{
					// Graphic anchor point appears earlier in the text, but the float isn't (or wasn't previously) visible
					--floatIndex;
					floatInfo = _composedFloats[floatIndex];
					containerListIndex = _floatsInContainer.indexOf(floatInfo.graphic);
				}
				containerListIndex++;
				CONFIG::debug { assert(containerListIndex >= 0, "Can't find previously visible float"); }
				for (var m:int = 0; m < floatIndex; ++m)
				{
					CONFIG::debug { assert(_composedFloats[m].absolutePosition >= this.absoluteStart, "Found float from previous container"); }
					if (_composedFloats[m].absolutePosition >= this.absoluteStart)
						visibleFloats.push(_composedFloats[m].graphic);
				}
			}
			var firstContainerListIndex:int = containerListIndex;
			if (!_floatsInContainer)
				_floatsInContainer = [];
			var numContainerList:int = _floatsInContainer.length;
			
			CONFIG::debug
			{
				var oldChanges:Array = [];
				var visibleAtEnd:Array = [];
				oldUpdateGraphics(_updateStart, oldChanges, visibleAtEnd);
				var changeIndex:int = 0;
				var originalAlgorithmChange:Array;
				var matrix:Matrix;
				var oldMatrix:Matrix;
				var changes:Array = [];
			}

			// Add in the floats from the last compose, at the composed location
			var numFloats:int = _composedFloats.length;
			for (; floatIndex < numFloats; )
			{
				floatInfo = _composedFloats[floatIndex];
				float = floatInfo.graphic;
				var parent:DisplayObjectContainer = floatInfo.parent;
				var shouldDisplayGraphic:Boolean;
				if (!float)
					shouldDisplayGraphic = false;
				else 
				{
					if (floatInfo.floatType == Float.NONE)
						shouldDisplayGraphic = floatInfo.absolutePosition >= firstVisiblePosition && floatInfo.absolutePosition < lastVisiblePosition;
					else
						shouldDisplayGraphic = floatIsVisible(wmode, adjustX, adjustY, width, height, floatInfo) && floatInfo.absolutePosition < lastPossibleFloatPosition && floatInfo.absolutePosition >= this.absoluteStart;
				}
				
				if (!shouldDisplayGraphic)		// skip to the next
				{
					// Float may be after the last visible line and still visible if it is anchored to the following line because it was too wide for the column,
					// so we don't stop iterating until we've gone at least one line past the last visible line.
					if (floatInfo.absolutePosition >= lastPossibleFloatPosition)
						break;
					++floatIndex;
					continue;
				}
				
				// If we had to remove some no-longer visible graphics, we might have already gone past this graphic before. Only add once.
				if (visibleFloats.indexOf(float) < 0)
					visibleFloats.push(float);
				
				// If it's an inline, the TextLine in the FloatCompositionData may have been replaced. Check for this and get a new line if necessary.
				if (floatInfo.floatType == Float.NONE)
				{
					// Check to see if the TextLine has changed
					var tl:TextLine = parent as TextLine;
					if (tl)
					{
						var tfl:TextFlowLine = tl.userData as TextFlowLine;
						if (!tfl || floatInfo.absolutePosition < tfl.absoluteStart || floatInfo.absolutePosition >= tfl.absoluteStart + tfl.textLength || tl.parent == null || tl.validity == TextLineValidity.INVALID)
						{
							// TextLine doesn't match TextFlowLine -- refetch the TextLine
							tfl = flowComposer.findLineAtPosition(floatInfo.absolutePosition);

							for (var i:int = 0; i < _shapeChildren.length; i++) 
								if ((_shapeChildren[i] as TextLine).userData == tfl)		// if this is coded into the loop condition we get a warning
									break;
							parent = (i < _shapeChildren.length) ? _shapeChildren[i] : null;
						}
					}
				}

				inlineHolder = float.parent;

				// Float is already visible in the right place in the z-order, leave it but update its position
				if (containerListIndex < numContainerList && floatInfo.parent == _container && inlineHolder && inlineHolder.parent == _container && float == _floatsInContainer[containerListIndex])
				{
					if (floatInfo.matrix)
						inlineHolder.transform.matrix = floatInfo.matrix;
					else
					{
						inlineHolder.x = 0;
						inlineHolder.y = 0;
					}
					inlineHolder.alpha = floatInfo.alpha;
					inlineHolder.x += floatInfo.x;
					inlineHolder.y += floatInfo.y;
					CONFIG::debug { assert(inlineHolder.contains(float), "expected float is already in display list"); }
					CONFIG::debug  { changes.push(["update", floatInfo.absolutePosition, inlineHolder.transform.matrix ? inlineHolder.transform.matrix.clone() : null, inlineHolder.alpha, inlineHolder.x, inlineHolder.y]);  }
					++floatIndex;
					++containerListIndex;
					continue;
				}
				var index:int = _floatsInContainer.indexOf(float);
				if (index > containerListIndex && parent == _container)		// it's in the existing list, but not yet, remove the old items from the container
				{
					var floatToRemove:DisplayObject = _floatsInContainer[containerListIndex++];
					if (floatToRemove.parent)
					{
						CONFIG::debug { changes.push(["remove", getIndexOfFloat(floatToRemove), floatToRemove, "going to add float", floatToRemove.parent.parent is TextLine ? "removing inline" : "removing float"]);  }
						removeInlineGraphicElement(floatInfo.parent, floatToRemove.parent);
					}
				}
				else					
				{
					if (containerListIndex < numContainerList &&  float == _floatsInContainer[containerListIndex])		// it was previously a Float.NONE; so we don't want to remove it later
						containerListIndex++;

					inlineHolder = new Sprite();
					if (floatInfo.matrix)
						inlineHolder.transform.matrix = floatInfo.matrix;
					inlineHolder.alpha = floatInfo.alpha;
					inlineHolder.x += floatInfo.x;
					inlineHolder.y += floatInfo.y;
					inlineHolder.addChild(float);
					CONFIG::debug { changes.push(["add", floatInfo.absolutePosition, parent, parent == _container ? childIdx : 0,  
						inlineHolder.transform.matrix ? inlineHolder.transform.matrix.clone() : null, inlineHolder.alpha, inlineHolder.x, inlineHolder.y]); }
					if (parent == _container)		// it's float - add to container
					{
						childIdx = Math.min(childIdx, _container.numChildren);
						addInlineGraphicElement(_container, inlineHolder, childIdx++);
					}
					else	// it's an inline - add to TextLine
						addInlineGraphicElement(parent, inlineHolder, 0);
					++floatIndex;
				}
			}
			while (containerListIndex < _floatsInContainer.length)		// remove trailing items
			{
				float = _floatsInContainer[containerListIndex++];
				if (float.parent && visibleFloats.indexOf(float) < 0)
				{
					CONFIG::debug { changes.push(["remove", getIndexOfFloat(float), float, "removeTrailing", float.parent is TextLine ? "removing inline" : "removing float"]);  }
					removeInlineGraphicElement(float.parent.parent, float.parent);
				}
			}
			
			CONFIG::debug { updateGraphicsCheck(_floatsInContainer); }
			
			// Update the container list
			_floatsInContainer = visibleFloats;

		//	CONFIG::debug { compareUpdateGraphicsResults(changes, oldChanges, _floatsInContainer, visibleAtEnd); }
		} 

		/*
		tlf_internal function updateGraphics(updateStart:int):void
		{
			var inlineHolder:DisplayObjectContainer;
			
			var visibleFloats:Array = [];
			
			// If we have new floats that have been composed into container, we add them here.
			// Also, we remove any that are no longer in the container. Only change those
			// floats that are within the area that was recomposed.
			
			var floatInfo:FloatCompositionData;
			var float:DisplayObject;
			var firstLine:TextFlowLine = getFirstVisibleLine();
			var lastLine:TextFlowLine = getLastVisibleLine();
			var firstVisiblePosition:int = firstLine ? firstLine.absoluteStart : this.absoluteStart;
			var lastVisiblePosition:int = lastLine ? lastLine.absoluteStart + lastLine.textLength : this.absoluteStart + textLength;
			
			// Calculate the last possible anchor position for a visible float. The float can't be past the line *after* the last line.
			// In case that's an uncomposed line with the entire rest of the TextFlow in it, we cap what we'll look at to 2000 chars
			// past the last visible line end. This keeps us from iterating forever in a long text flow.
			//	var followingLineIndex:int = flowComposer.findLineIndexAtPosition(lastVisiblePosition) + 1;
			var followingLine:TextFlowLine = flowComposer.findLineAtPosition(lastVisiblePosition);
			var lastPossibleFloatPosition:int = followingLine ? followingLine.absoluteStart + followingLine.textLength : this.absoluteStart + textLength;
			lastPossibleFloatPosition = Math.min(lastPossibleFloatPosition, this.absoluteStart + textLength);
			lastPossibleFloatPosition = Math.min(lastPossibleFloatPosition, lastVisiblePosition + 2000);
			lastPossibleFloatPosition = Math.min(lastPossibleFloatPosition, flowComposer.damageAbsoluteStart);
			CONFIG::debug { assert(lastPossibleFloatPosition <= this.absoluteStart + textLength, "Expected lastPossibleFloatPosition to be before end of container"); }
			
			// Get visible area
			var wmode:String = effectiveBlockProgression;
			var width:Number = _measureWidth ? _contentWidth : _compositionWidth;
			var height:Number = _measureHeight ? _contentHeight : _compositionHeight;
			var adjustX:Number = (wmode == BlockProgression.RL) ? _xScroll - width : _xScroll;
			var adjustY:Number = _yScroll;
			
			var floatIndex:int = findFloatIndexAtOrAfter(updateStart);
			var containerListIndex:int = 0;
			var childIdx:int = getFirstTextLineChildIndex(); // index where the first text line must appear at in its container  
			if (floatIndex > 0)		
			{
				// starting from the middle, need to skip over the initial entries already in the 
				// container list that are not being changed. Add them to the list of visible graphics, so they don't get dropped off.
				floatInfo = _composedFloats[floatIndex - 1];
				containerListIndex = _floatsInContainer.indexOf(floatInfo.graphic);
				while (containerListIndex == -1 && floatIndex > 0)
				{
					// Graphic anchor point appears earlier in the text, but the float isn't (or wasn't previously) visible
					floatIndex--;
					floatInfo = _composedFloats[floatIndex - 1];
					containerListIndex = _floatsInContainer.indexOf(floatInfo.graphic);
				}
				CONFIG::debug { assert(containerListIndex != -1, "Can't find previously visible float"); }
				containerListIndex++;
				for (var m:int = 0; m < floatIndex; ++m)
				{
					CONFIG::debug { assert(_composedFloats[m].absolutePosition >= this.absoluteStart, "Found float from previous container"); }
					if (_composedFloats[m].absolutePosition >= this.absoluteStart)
						visibleFloats.push(_composedFloats[m].graphic);
				}
			}
			var firstContainerListIndex:int = containerListIndex;
			if (!_floatsInContainer)
				_floatsInContainer = [];
			var numContainerList:int = _floatsInContainer.length;
			
			CONFIG::debug
			{
				var oldChanges:Array = [];
				var visibleAtEnd:Array = [];
				oldUpdateGraphics(_updateStart, oldChanges, visibleAtEnd);
				var changeIndex:int = 0;
				var originalAlgorithmChange:Array;
				var matrix:Matrix;
				var oldMatrix:Matrix;
				var changes:Array = [];
			}
			
			// Add in the floats from the last compose, at the composed location
			var numFloats:int = _composedFloats.length;
			for (; floatIndex < numFloats; )
			{
				floatInfo = _composedFloats[floatIndex];
				float = floatInfo.graphic;
				var parent:DisplayObjectContainer = floatInfo.parent;
				var shouldDisplayGraphic:Boolean;
				if (!float)
					shouldDisplayGraphic = false;
				else 
				{
					if (floatInfo.floatType == Float.NONE)
						shouldDisplayGraphic = floatInfo.absolutePosition >= firstVisiblePosition && floatInfo.absolutePosition < lastVisiblePosition;
					else
						shouldDisplayGraphic = floatIsVisible(wmode, adjustX, adjustY, width, height, floatInfo) && floatInfo.absolutePosition < lastPossibleFloatPosition && floatInfo.absolutePosition >= this.absoluteStart;
				}
				
				if (!shouldDisplayGraphic)		// skip to the next
				{
					// Float may be after the last visible line and still visible if it is anchored to the following line because it was too wide for the column,
					// so we don't stop iterating until we've gone at least one line past the last visible line.
					if (floatInfo.absolutePosition >= lastPossibleFloatPosition)
						break;
					++floatIndex;
					continue;
				}
				
				// If we had to remove some no-longer visible graphics, we might have already gone past this graphic before. Only add once.
				if (visibleFloats.indexOf(float) < 0)
					visibleFloats.push(float);
				
				// If it's an inline, the TextLine in the FloatCompositionData may have been replaced. Check for this and get a new line if necessary.
				if (floatInfo.floatType == Float.NONE)
				{
					// Check to see if the TextLine has changed
					var tl:TextLine = parent as TextLine;
					if (tl)
					{
						var tfl:TextFlowLine = tl.userData as TextFlowLine;
						if (!tfl || floatInfo.absolutePosition < tfl.absoluteStart || floatInfo.absolutePosition >= tfl.absoluteStart + tfl.textLength || tl.parent == null || tl.validity == TextLineValidity.INVALID)
						{
							// TextLine doesn't match TextFlowLine -- refetch the TextLine
							tfl = flowComposer.findLineAtPosition(floatInfo.absolutePosition);
							
							for (var i:int = 0; i < _shapeChildren.length; i++) 
								if ((_shapeChildren[i] as TextLine).userData == tfl)		// if this is coded into the loop condition we get a warning
									break;
							parent = (i < _shapeChildren.length) ? _shapeChildren[i] : null;
						}
					}
				}
				
				inlineHolder = float.parent;
				
				// Float is already visible in the right place in the z-order, leave it but update its position
				if (containerListIndex < numContainerList && floatInfo.parent == _container && inlineHolder && inlineHolder.parent == _container && float == _floatsInContainer[containerListIndex])
				{
					if (floatInfo.matrix)
						inlineHolder.transform.matrix = floatInfo.matrix;
					else
					{
						inlineHolder.x = 0;
						inlineHolder.y = 0;
					}
					inlineHolder.alpha = floatInfo.alpha;
					inlineHolder.x += floatInfo.x;
					inlineHolder.y += floatInfo.y;
					CONFIG::debug { assert(inlineHolder.contains(float), "expected float is already in display list"); }
					CONFIG::debug  { changes.push(["update", floatInfo.absolutePosition, inlineHolder.transform.matrix ? inlineHolder.transform.matrix.clone() : null, inlineHolder.alpha, inlineHolder.x, inlineHolder.y]);  }
					++floatIndex;
					++containerListIndex;
					continue;
				}
				var index:int = _floatsInContainer.indexOf(float);
				if (index > containerListIndex && parent == _container)		// it's in the existing list, but not yet, remove the old items from the container
				{
					var floatToRemove:DisplayObject = _floatsInContainer[containerListIndex++];
					if (floatToRemove.parent)
					{
						CONFIG::debug { changes.push(["remove", getIndexOfFloat(floatToRemove), floatToRemove, "going to add float", floatToRemove.parent.parent is TextLine ? "removing inline" : "removing float"]);  }
						removeInlineGraphicElement(_container, floatToRemove.parent);
					}
				}
				else					
				{
					if (containerListIndex < numContainerList &&  float == _floatsInContainer[containerListIndex])		// it was previously a Float.NONE; so we don't want to remove it later
						containerListIndex++;
					
					inlineHolder = new Sprite();
					if (floatInfo.matrix)
						inlineHolder.transform.matrix = floatInfo.matrix;
					inlineHolder.alpha = floatInfo.alpha;
					inlineHolder.x += floatInfo.x;
					inlineHolder.y += floatInfo.y;
					inlineHolder.addChild(float);
					CONFIG::debug { changes.push(["add", floatInfo.absolutePosition, parent, parent == _container ? childIdx : 0,  
						inlineHolder.transform.matrix ? inlineHolder.transform.matrix.clone() : null, inlineHolder.alpha, inlineHolder.x, inlineHolder.y]); }
					if (parent == _container)		// it's float - add to container
					{
						childIdx = Math.min(childIdx, _container.numChildren);
						addInlineGraphicElement(_container, inlineHolder, childIdx++);
					}
					else	// it's an inline - add to TextLine
						addInlineGraphicElement(parent, inlineHolder, 0);
					++floatIndex;
				}
			}
			while (containerListIndex < _floatsInContainer.length)		// remove trailing items
			{
				float = _floatsInContainer[containerListIndex++];
				if (float.parent)
				{
					CONFIG::debug { changes.push(["remove", getIndexOfFloat(float), float, "removeTrailing", float.parent is TextLine ? "removing inline" : "removing float"]);  }
					removeInlineGraphicElement(_container, float.parent);
				}
			}
			
			// Update the container list
			_floatsInContainer = visibleFloats;
			
			//	CONFIG::debug { compareUpdateGraphicsResults(changes, oldChanges, _floatsInContainer, visibleAtEnd); }
		} 
*/
		
		private function floatIsVisible(wmode:String, scrollX:Number, scrollY:Number, scrollWidth:Number, scrollHeight:Number, floatInfo:FloatCompositionData):Boolean
		{
			var inlineGraphicElement:InlineGraphicElement = textFlow.findLeaf(floatInfo.absolutePosition) as InlineGraphicElement;
			
			return (wmode == BlockProgression.TB) ?
				(floatInfo.y + inlineGraphicElement.elementHeight >= scrollY) && 
					(floatInfo.y <= scrollY + scrollHeight) :
				(floatInfo.x + inlineGraphicElement.elementWidth >= scrollX) && 
					(floatInfo.x <= scrollX + scrollWidth);
		} 
		
		CONFIG::debug private function processResults(changes:Array):Array
		{
			var newProcessedResults:Array = [];
			var newResults:Array;
			for each (newResults in changes)
			{
				var i:int;
				var result:Object = new Object();
				result.absolutePosition = newResults[1];
				result.state = newResults;
				for (i = 0; i < newProcessedResults.length; ++i)
					if (newProcessedResults[i].absolutePosition == newResults[1])
						break;
				if (i < newProcessedResults.length)
					newProcessedResults[i] = result;
				newProcessedResults.push(result);
			}
			return newProcessedResults;
		}
		
		CONFIG::debug private function compareUpdateGraphicsResults(newAlgorithmChanges:Array, originalAlgorithmChanges:Array, visibleFloats:Array, oldVisibleFloats:Array):void
		{
		//	var newResults:Array;
			var changeIndex:int = 0;
			var oldMatrix:Matrix;
			var matrix:Matrix;
			var result:Object;
			var newProcessedResults:Array = processResults(newAlgorithmChanges);
			var oldProcessedResults:Array = processResults(originalAlgorithmChanges);
			for each (result in newProcessedResults)
			{
				for (var i:int = 0; i < oldProcessedResults.length; ++i)
					if (oldProcessedResults[i].absolutePosition == result.absolutePosition)
						break;
				assert(i < oldProcessedResults.length, "Object at " + result.absolutePosition.toString() + "not changed by original algorithm is changed(" + result.state[0] + ") by new");
				if (i < oldProcessedResults.length)
				{
					var oldResult:Object = oldProcessedResults[i];
					var oldChanges:Array = oldResult.state;
					var newChanges:Array = result.state;
					assert (newChanges[0] == oldChanges[0], "New algorithm left object at " + newChanges[1].toString() + " in different state than old algorithm (now " + newChanges[0] + " was " + oldChanges[0]);
					if (newChanges[0] != oldChanges[0])
						continue;
					switch (newChanges[0])
					{
						case 'update':
							oldMatrix = oldChanges[2] as Matrix;
							matrix = newChanges[2] as Matrix;
							assert((matrix == null && oldMatrix == null) || 
								(matrix.a == oldMatrix.a && matrix.b == oldMatrix.b &&
									matrix.c == oldMatrix.c && matrix.d == oldMatrix.d &&
									matrix.tx == oldMatrix.tx && matrix.ty == oldMatrix.ty), "Expected matrix of new alogorithm to match matrix of old"); 
							assert(oldChanges[3] == newChanges[3], "Expected alpha of new alogirthm to match alpha of old"); 
							assert(oldChanges[4] == newChanges[4], "Expected X of new alogirthm to match X of old on update"); 
							assert(oldChanges[5] == newChanges[5], "Expected Y of new alogirthm to match Y of old on update"); 
							break;
						case 'add':
							assert(oldChanges[2] == newChanges[2], "After add new and old algorithm get different parent");
							assert(oldChanges[3] == newChanges[3], "After add new and old algorithm get different child index");
							matrix = oldChanges[4] as Matrix;
							oldMatrix = newChanges[4] as Matrix;
							assert((matrix == null && oldMatrix == null) ||
								(matrix.a == oldMatrix.a && matrix.b == oldMatrix.b &&
									matrix.c == oldMatrix.c && matrix.d == oldMatrix.d &&
									matrix.tx == oldMatrix.tx && matrix.ty == oldMatrix.ty), "After add new and old algorithm get different matrix"); 
							assert(oldChanges[5] == newChanges[5], "After add new and old algorithm get different alpha"); 
							assert(oldChanges[6] == newChanges[6], "After add new and old algorithm get different X"); 
							assert(oldChanges[7] == newChanges[7], "After add new and old algorithm get different Y"); 
							break;
						case 'remove':
							if (oldChanges[0] != "remove" && newChanges[3] == "going to add inline")
								return;
							if (oldChanges[2] != newChanges[2])
							{
								for (var j:int = 0; j < oldProcessedResults.length; ++j)
									if (oldProcessedResults[j].state[0] == "remove" && oldProcessedResults[j].state[2] == newChanges[2])
										break;
								assert(j < oldProcessedResults.length, "Float at " + newChanges[1].toString() + " removed by new algorithm " + oldChanges[0] + " by the old");
							}
							break;
					}
				}
			}
			var float:DisplayObject;
			var floatPosition:int = -1;
			for each (float in visibleFloats)
			{
				if (oldVisibleFloats.indexOf(float) < 0)
				{
					floatPosition = getIndexOfFloat(float);
					assert (false, "new algorithm _floatsInContainer has visible graphic at " + floatPosition.toString() + " not in old algorithm in container " + flowComposer.getControllerIndex(this).toString());
				}
			}
			for each (float in oldVisibleFloats)
			{
				if (visibleFloats.indexOf(float) < 0)
				{
					floatPosition = getIndexOfFloat(float);
					assert (false, "old algorithm _floatsInContainer has visible graphic at " + floatPosition.toString() + " not in new algorithm" + flowComposer.getControllerIndex(this).toString());
				}
			}
		} 
		
		CONFIG::debug private function getIndexOfFloat(float:DisplayObject):int
		{
			var floatPosition:int = -1;
			for (var m:int = 0; m < _composedFloats.length; m++)
			{
				if (_composedFloats[m].graphic == float)
				{
					floatPosition = _composedFloats[m].absolutePosition;
					break;
				}
			}
			return floatPosition;
		}
		
		// Add or remove graphis (floats or regular inlines) from the display list
		CONFIG::debug private function oldUpdateGraphics(updateStart:int, changes:Array, visibleAtEnd:Array):void
		{
			var inlineHolder:DisplayObjectContainer;
			
			// If we have new floats that have been composed into container, we add them here.
			// Also, we remove any that are no longer in the container. Only change those
			// floats that are within the area that was recomposed.
			
			var floatInfo:FloatCompositionData;
			var firstLine:TextFlowLine = getFirstVisibleLine();
			var lastLine:TextFlowLine = getLastVisibleLine();
			var firstVisiblePosition:int = firstLine ? firstLine.absoluteStart : this.absoluteStart;
			var lastVisiblePosition:int = lastLine ? lastLine.absoluteStart + lastLine.textLength : this.absoluteStart + textLength;

			var floatIndex:int = findFloatIndexAtOrAfter(updateStart);
			var lastFloatIndex:int = findFloatIndexAtOrAfter(lastVisiblePosition);
			var containerListIndex:int = 0;
			var childIdx:int = getFirstTextLineChildIndex(); // index where the first text line must appear at in its container  
			if (floatIndex > 0)		
			{
				// starting from the middle, need to skip over the initial entries already in the 
				// container list that are not being changed
				floatInfo = _composedFloats[floatIndex - 1];
				containerListIndex = _floatsInContainer.indexOf(floatInfo.graphic) + 1;
				CONFIG::debug { assert(containerListIndex >= 0, "Can't find pre-existing float in container list"); }
			}
			if (!_floatsInContainer)
				_floatsInContainer = [];
			var numContainerList:int = _floatsInContainer.length;

			// Add in the floats from the last compose, at the composed location
			for (; floatIndex < lastFloatIndex; )
			{
				floatInfo = _composedFloats[floatIndex];
				var float:DisplayObject = floatInfo.graphic;
				var parent:DisplayObjectContainer = floatInfo.parent;
				if (floatInfo.floatType == Float.NONE)	// If the parent line is not in view, don't display the ILG
				{
					// Check to see if the TextLine has changed
					var tl:TextLine = parent as TextLine;
					if (tl)
					{
						var tfl:TextFlowLine = tl.userData as TextFlowLine;
						if (!tfl || floatInfo.absolutePosition < tfl.absoluteStart || floatInfo.absolutePosition >= tfl.absoluteStart + tfl.textLength || tl.parent == null || tl.validity == TextLineValidity.INVALID)
						{
							// TextLine doesn't match TextFlowLine -- refetch the TextLine
							tfl = flowComposer.findLineAtPosition(floatInfo.absolutePosition);

							for (var i:int = 0; i < _shapeChildren.length; i++) 
								if ((_shapeChildren[i] as TextLine).userData == tfl)		// if this is coded into the loop condition we get a warning
									break;
							parent = (i < _shapeChildren.length) ? _shapeChildren[i] : null;
						}
					}
					if (!floatInfo.matrix || _shapeChildren.indexOf(parent) < 0)
					{
						++floatIndex;
						continue;
					}
				}
				if (floatInfo.floatType == Float.NONE && (!floatInfo.matrix || _shapeChildren.indexOf(parent) < 0))	// If the parent line is not in view, don't display the ILG
				{
					++floatIndex;
					continue;
				}
				if (float)
					inlineHolder = float.parent;
				if (containerListIndex < numContainerList && floatInfo.parent == _container && inlineHolder && inlineHolder.parent == _container && float == _floatsInContainer[containerListIndex])		// its in both lists, just skip over
				{
					var updateSprite:Sprite = new Sprite();
					updateSprite.transform.matrix = inlineHolder.transform.matrix;
					updateSprite.x = inlineHolder.x;
					updateSprite.y = inlineHolder.y;
					var updateAlpha:Number;
					
					// Update in place
					if (floatInfo.matrix)
						updateMatrix = floatInfo.matrix;
					else
					{
						updateSprite.x = 0;
						updateSprite.y = 0;
					}
					updateAlpha = floatInfo.alpha;
					updateSprite.x += floatInfo.x;
					updateSprite.y += floatInfo.y;
					var updateX:Number = updateSprite.x;
					var updateY:Number = updateSprite.y;
					var updateMatrix:Matrix = updateSprite.transform.matrix;
					updateMatrix = updateMatrix.clone();
					CONFIG::debug { assert(inlineHolder.contains(float), "expected float is already in display list"); }
					changes.push(["update", floatInfo.absolutePosition, updateMatrix, updateAlpha, updateX, updateY]);
					++floatIndex;
					++containerListIndex;
					continue;
				}
				var index:int = _floatsInContainer.indexOf(float);
				if (index > containerListIndex && parent == _container)		// it's in the existing list, but not yet, remove the old items from the container
				{
					var floatToRemove:DisplayObject = _floatsInContainer[containerListIndex++];
					if (floatToRemove.parent)
					//	removeInlineGraphicElement(_container, floatToRemove.parent);
						changes.push(["remove", getIndexOfFloat(floatToRemove), floatToRemove, parent == _container ? "going to add float" : "going to add inline"]);
				}
				else					
				{
					if (containerListIndex < numContainerList &&  float == _floatsInContainer[containerListIndex])		// it was previously a Float.NONE; so we don't want to remove it later
						containerListIndex++;

					var addSprite:Sprite = new Sprite();
					var addAlpha:Number = floatInfo.alpha;

					if (floatInfo.matrix)
						addSprite.transform.matrix = floatInfo.matrix;
					addSprite.x += floatInfo.x;	// addSprite x & y have values set up by matrix assignment - keep twip rounding same by assigning into Sprite
					addSprite.y += floatInfo.y;
					var addMatrix:Matrix = addSprite.transform.matrix;
					var addX:Number = addSprite.x;
					var addY:Number = addSprite.y;
					addMatrix = addMatrix ? addMatrix.clone() : null;
					if (parent == _container)		// it's float - add to container
						changes.push(["add", floatInfo.absolutePosition, _container, childIdx++, addMatrix, addAlpha, addX, addY]);
					//	addInlineGraphicElement(_container, inlineHolder, childIdx++);
					else	// it's an inline - add to TextLine
						changes.push(["add", floatInfo.absolutePosition, parent, 0, addMatrix, addAlpha, addX, addY]);
					//	addInlineGraphicElement(parent, inlineHolder, 0);
					++floatIndex;
				}
			}
			while (containerListIndex < _floatsInContainer.length)		// remove trailing items
			{
				float = _floatsInContainer[containerListIndex++];
				if (float.parent)
				{
					changes.push(["remove", getIndexOfFloat(float), float, "removeTrailing"]);
				//	removeInlineGraphicElement(_container, float.parent);
				}
			}

			// Update the container list
			visibleAtEnd.length = 0;
			for each (floatInfo in _composedFloats)
				if (floatInfo.absolutePosition >= firstVisiblePosition && floatInfo.absolutePosition < lastVisiblePosition)
					visibleAtEnd.push(floatInfo.graphic);
		}
			
		private function releaseLinesInBlock(textBlock:TextBlock):void
		{
			// run through the textBlock and if all lines are not in view,
			// release the lines from the TextBlock, and release the TextBlock itself.
			for (var textLine:TextLine = textBlock.firstLine; textLine && textLine.parent == null; textLine = textLine.nextLine)
			{	// do nothing 
			}
			if (!textLine && textBlock.firstLine)	// no lines in paragraph are in the view
			{
				var para:ParagraphElement;
				var line:TextFlowLine = textBlock.firstLine.userData as TextFlowLine;
				if (line)
					para = line.paragraph;
				textBlock.releaseLines(textBlock.firstLine, textBlock.lastLine);
				if (para)
					para.releaseTextBlock();
			}
		}
		
		private function removeAndRecycleTextLines (beginIndex:int, endIndex:int):void
		{
			var backgroundManager:BackgroundManager = textFlow.backgroundManager;
			
			var child:TextLine;
			var textBlock:TextBlock;
			for (var index:int = beginIndex; index < endIndex; index++)
			{
				child = _shapeChildren[index];					
				removeTextLine(child);
				CONFIG::debug { Debugging.traceFTECall(null,_container,"removeTextLine",child); }
				// when we've removed all the lines in the paragraph in shapeChildren, run through the textBlock and if all lines are not in view,
				// release the lines from the TextBlock, and release the TextBlock itself.
				if (child.textBlock != textBlock)		
				{
					if (textBlock)
						releaseLinesInBlock(textBlock);
					textBlock = child.textBlock;
				}
			}
			// To fix bug #2988783  -By Jin Huang
			// releaseLinesInBlock() can only be called here when
			// 1. the end of final container
			// 2. the end line of TextBlock is the end line of the container
			if (textBlock && (textBlock.lastLine == child || flowComposer.getControllerAt(flowComposer.numControllers - 1) == this))
				releaseLinesInBlock(textBlock);
			
			// Recycle lines not in view and not in the TextBlock
			if (TextLineRecycler.textLineRecyclerEnabled)
			{
				while (beginIndex < endIndex)
				{
					child = _shapeChildren[beginIndex++];
										
					// Recycle if its not displayed and not connected to the textblock
					if (!child.parent)
					{
						if (child.userData == null)
						{
							TextLineRecycler.addLineForReuse(child);
							if (backgroundManager)
								backgroundManager.removeLineFromCache(child);
						}
						else 
						{
							var tfl:TextFlowLine = child.userData as TextFlowLine;
							if (tfl && tfl.controller != this)		// don't release lines that belong to other containers
								continue;
							if (child.validity == TextLineValidity.INVALID || (child.nextLine == null && child.previousLine == null && (!child.textBlock || child.textBlock.firstLine != child)))
							{
								child.userData = null;
								TextLineRecycler.addLineForReuse(child);
								if (backgroundManager)
									backgroundManager.removeLineFromCache(child);
							}
						}
					}
				}
			}
		} 
		
		/**
		 * 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
		 */	
		protected 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;
		}
		
		/**
		 * 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
		 * 
		 */	
		protected function addTextLine(textLine:TextLine, index:int):void
		{ 
			if ( index > _container.numChildren )
				index = _container.numChildren;
			_container.addChildAt(textLine, index);
		}
		
		/**
		 * 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
		 * 
		 */	
		protected function removeTextLine(textLine:TextLine):void
		{
			if (_container.contains(textLine))
				_container.removeChild(textLine);
		}
		
		/**
		 * 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
		 * 
		 */
		protected function addBackgroundShape(shape:Shape):void	// No PMD
		{
			_container.addChildAt(_backgroundShape, getFirstTextLineChildIndex());
		}
		
		/**
		 * 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
		 * 
		 */
		protected function removeBackgroundShape(shape:Shape):void	
		{
			if (shape.parent)
				shape.parent.removeChild(shape);
		}
		
		/**
		 * 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
		 */
		protected 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);
		}
		
		/**
		 * 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
		 * 
		 */
		protected function removeSelectionContainer(selectionContainer:DisplayObjectContainer):void
		{	
			selectionContainer.parent.removeChild(selectionContainer);
		}
		
		/**
		 * 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
		 * 
		 */	
		protected function addInlineGraphicElement(parent:DisplayObjectContainer, inlineGraphicElement:DisplayObject, index:int):void
		{
			
			// We're adding the inline holder -- the float it owns should not be in the visible list
			CONFIG::debug { assert (parent != _container || !parent.contains(inlineGraphicElement), "Float already in container"); }
			if (parent)
				parent.addChildAt(inlineGraphicElement, index);
		}
		
		/**
		 * 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
		 * 
		 */	
		protected function removeInlineGraphicElement(parent:DisplayObjectContainer, inlineGraphicElement:DisplayObject):void
		{
			// We're removing the inline holder -- the float it owns should be in the visible list
			CONFIG::debug { assert (parent != _container || _floatsInContainer.indexOf(DisplayObjectContainer(inlineGraphicElement).getChildAt(0)) >= 0, "Float *not* already in container"); }
			if (null != parent && inlineGraphicElement.parent == parent)
				parent.removeChild(inlineGraphicElement);
		}
		
		/**
		 * @private
		 */
		tlf_internal function get textLines():Array
		{
			return _shapeChildren;
		}
		
		/** 
		 * If scrolling, sets the scroll rectangle to the container rectangle so that any lines that are 
		 * halfway in view are clipped to the scrollable region. If not scrolling, clear the
		 * scroll rectangle so that no clipping occurs.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		protected function updateVisibleRectangle() :void
		{
			if (horizontalScrollPolicy == ScrollPolicy.OFF && verticalScrollPolicy == ScrollPolicy.OFF)
			{
				if (_hasScrollRect)
				{
					_container.scrollRect = null;
					_hasScrollRect = false;
					
				}
			}
			else
			{
				var contentRight:Number = _contentLeft+contentWidth;
				var contentBottom:Number = _contentTop+contentHeight;
				var width:Number;
				var compositionRight:Number;
				if (_measureWidth)
				{
					width = contentWidth;
					compositionRight = _contentLeft + width
				}
				else
				{
					width = _compositionWidth;
					compositionRight = width;
				}
				var height:Number;
				var compositionBottom:Number;
				if (_measureHeight)
				{
					height = contentHeight;
					compositionBottom = _contentTop + height;
				}
				else
				{
					height = _compositionHeight;
					compositionBottom = height;
				}
				var xOrigin:Number = (effectiveBlockProgression == BlockProgression.RL) ? -width : 0;
				var xpos:int = horizontalScrollPosition + xOrigin;
				var ypos:int = verticalScrollPosition;
				//Fix bug 2869747 textFlow.flowComposer.getControllerAt(0)
				if(!_hasScrollRect)
				{
						_container.scrollRect = null;
						CONFIG::debug { Debugging.traceFTECall(null,_container,"clearContainerScrollRect()"); }
				}
				
				if (textLength == 0 || xpos == 0 && ypos == 0 && _contentLeft >= xOrigin && _contentTop >= 0 && contentRight <= compositionRight && contentBottom <= compositionBottom)
				{
					if(_hasScrollRect)
					{
						_container.scrollRect = null;
						CONFIG::debug { Debugging.traceFTECall(null,_container,"clearContainerScrollRect()"); }
						_hasScrollRect = false;
					}
				}
				else 
				{
					// don't look at hasScrollRect but do look at scrollRect - client may have messed with it; okay to touch it because about to set it
					var rect:Rectangle = _container.scrollRect;
					if (!rect || rect.x != xpos || rect.y != ypos || rect.width != width || rect.height != height)
					{
						_container.scrollRect = new Rectangle(xpos, ypos, width, height);
						CONFIG::debug { Debugging.traceFTECall(null,_container,"setContainerScrollRect",xpos, ypos, width, height); }
						_hasScrollRect = true;
					}
				}
			}
			
			//Fix for Watson 2347938 - re-add the transparent background as the dimension of the
			//container are altered by sutting down the scrolls in vertical text.
			this.attachTransparentBackgroundForHit(false);
		}
		
		include "../formats/TextLayoutFormatInc.as";
		
		/** Allows you to read and write user styles on a ContainerController object.  Note that reading this property
		 * makes a copy of the userStyles set in the format of this element. 
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 */
		public function get userStyles():Object
		{ return _format ? _format.userStyles : null; }
		public function set userStyles(styles:Object):void
		{
			var val:String;
			// clear the existing userstyles
			for (val in userStyles)
				this.setStyle(val,undefined);
			
			// set the new ones
			for (val in styles)
				this.setStyle(val,styles[val]);
		}
		
		/** Returns the <code>coreStyles</code> on this ContainerController.  Note that the getter makes a copy of the core 
		 * styles dictionary. The returned object includes the formats that are defined by TextLayoutFormat and are in TextLayoutFormat.description. The
		 * returned object consists of an array of <em>stylename-value</em> pairs.
		 * 
		 * @see flashx.textLayout.formats.TextLayoutFormat
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		public function get coreStyles():Object
		{ return _format ? _format.coreStyles : null; }
		
		/** Returns the styles on this ContainerController.  Note that the getter makes a copy of the  
		 * styles dictionary. The returned object includes all styles set in the format property including core and user styles. The
		 * returned object consists of an array of <em>stylename-value</em> pairs.
		 * 
		 * @see flashx.textLayout.formats.TextLayoutFormat
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public function get styles():Object
		{ return _format ? _format.styles : null; }

		/** 
		 * Stores the ITextLayoutFormat object that contains the attributes for this container. 
		 * The controller inherits the container properties from the TextFlow of which it is part. 
		 * This property allows different controllers in the same text flow to have, for example, 
		 * different column settings or padding.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @see flashx.textLayout.formats.ITextLayoutFormat
		 */
		public function get format():ITextLayoutFormat
		{ return _format; }
		public function set format(value:ITextLayoutFormat):void
		{
			if (value == _format)
				return;
			
			var oldStyleName:String = this.styleName;
			
			if (value == null)
				_format.clearStyles();
			else
				writableTextLayoutFormat().copy(value);

			formatChanged();
			if (oldStyleName != this.styleName)
				styleSelectorChanged();
		}
		
		private function writableTextLayoutFormat():FlowValueHolder
		{
			if (_format == null)
				_format = new FlowValueHolder();
			return _format;
		}
		
		/** Returns the value of the style specified by the <code>styleProp</code> parameter.
		 *
		 * @param styleProp The name of the style property whose value you want.
		 *
		 * @return	The current value for the specified style.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public function getStyle(styleProp:String):*
		{ 
			if (TextLayoutFormat.description.hasOwnProperty(styleProp))
				return computedFormat.getStyle(styleProp);
			
			var tf:TextFlow = _rootElement.getTextFlow();
			if (!tf || !tf.formatResolver)
				return computedFormat.getStyle(styleProp);
			
			return getUserStyleWorker(styleProp); 
		}
		
		/** @private worker function - any styleProp */
		tlf_internal function getUserStyleWorker(styleProp:String):*
		{
			CONFIG::debug { assert(TextLayoutFormat.description[styleProp] === undefined,"bad call to getUserStyleWorker"); }
			
			var userStyle:* = _format.getStyle(styleProp)
			if (userStyle !== undefined)
				return userStyle;
			
			var tf:TextFlow = _rootElement ? _rootElement.getTextFlow() : null;
			if (tf && tf.formatResolver)
			{
				userStyle = tf.formatResolver.resolveUserFormat(this,styleProp);
				if (userStyle !== undefined)
					return userStyle;
			}
			// or should it go to the container?
			return _rootElement ? _rootElement.getUserStyleWorker(styleProp) : undefined;
		}
		
		/** 
		 * Sets the value of the style specified by the <code>styleProp</code> parameter to the value
		 * specified by the <code>newValue</code> parameter.
		 *
		 * @param styleProp The name of the style property whose value you want to set.
		 * @param newValue The value that you want to assign to the style.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public function setStyle(styleProp:String,newValue:*):void
		{
			if (TextLayoutFormat.description[styleProp])
				this[styleProp] = newValue;
			else
			{
				writableTextLayoutFormat().setStyle(styleProp,newValue);
				formatChanged();
			}
		}
		
		/** Clears the style specified by <code>styleProp</code> from this FlowElement. Sets the value to
		 * <code>undefined</code>.
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public function clearStyle(styleProp:String):void
		{ setStyle(styleProp,undefined); }
		
		
		/** 
		 * Returns an ITextLayoutFormat instance with the attributes applied to this container, including the attributes inherited from its
		 * root element.
		 * 
		 * @return 	object that describes the container's attributes.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 *
		 * @see #rootElement
		 */
		public function get computedFormat():ITextLayoutFormat
		{
			if (!_computedFormat)
			{
				// TODO: revise cascade so it goes up through the container chain
				
				var parentPrototype:TextLayoutFormat = _rootElement ? TextLayoutFormat(_rootElement.computedFormat): null;
				_computedFormat =  FlowElement.createTextLayoutFormatPrototype(formatForCascade,parentPrototype);
				
				resetColumnState();
			}
			return _computedFormat;
		}
		
		/** @private */
		tlf_internal function get formatForCascade():ITextLayoutFormat
		{
			if (_rootElement)
			{
				var tf:TextFlow = _rootElement.getTextFlow();
				if (tf)
				{
					var elemStyle:TextLayoutFormat  = tf.getTextLayoutFormatStyle(this);
					if (elemStyle)
					{
						var localFormat:ITextLayoutFormat = _format;
						if (localFormat == null)
							return elemStyle;
						
						var rslt:TextLayoutFormat = new TextLayoutFormat(elemStyle);
						rslt.apply(localFormat);
						return rslt;
					}
				}
			}
			return _format;
		}
		
		/** @private 
		 * @returns -1 BEFORE visible, TextLine visible, 1 AFTER visible, 2 AFTER visible by auto-size image(bug #2988852)
		 * */
		tlf_internal function testLineVisible(wmode:String, scrollXTW:int, scrollYTW:int, scrollWidthTW:int, scrollHeightTW:int, textFlowLine:TextFlowLine, textLine:TextLine):*
		{
			// So this is another take on figuring out whether the line bounds intersects the visible area of the container. 
			// This code figures out the logical bounds of the line, and uses that for the intersection. There was a 
			// previous version of this code that uses the DisplayObject's getBounds function, which will include information
			// about the children, and also the bounds of visible glyphs. We decided that the logical bounds is close enough,
			// and is much faster to obtain. However, there may be some lines, that get a different result using the logical 
			// bounds than the getBounds. I've left the old code here for verification.
			CONFIG::debug { assert(textFlowLine != null,"testLineVisible"); }
			
			//Bug #2988852, scrolling in the application causes all text to disappear. When auto-size images make the line "after visible"
			//It's "after visible", but it cannot return 1. Because if it were 1, the binary-search in gatherVisibleLines() would make all the lines invisible.
			if(textFlowLine.controller == null)
			{
				var ilgs:Array = textFlow.getElementsByTypeName("img");
				var ilg:InlineGraphicElement;
				for(var idx:int = 0; idx < ilgs.length; idx++)
				{
					ilg = ilgs[idx] as InlineGraphicElement;
					if(ilg && ilg.getAbsoluteStart() < textFlowLine.absoluteStart)
					{
						if(wmode == BlockProgression.TB)
						{
							if(ilg.height == undefined || ilg.height == "auto")
								return 2; 
						}
						else
						{
							if(ilg.width == undefined || ilg.width == "auto")
								return 2;
						}
					}
					else 
						break;
				}
			}
			
			// assume the same textFlow and that it's composed.
			if (textFlowLine.controller != this)
				return textFlowLine.absoluteStart < this.absoluteStart ? -1 : 1;
			
			if (!textFlowLine.hasLineBounds())
			{
				if (!textLine)
					textLine = textFlowLine.getTextLine(true);
				textFlowLine.createShape(wmode, textLine);
				if (textLine.numChildren == 0)
				{
					// Get it the new way
					if (wmode == BlockProgression.TB)
						textFlowLine.cacheLineBounds(wmode, textLine.x, textLine.y - textLine.ascent, textLine.textWidth, textLine.textHeight);
					else
						textFlowLine.cacheLineBounds(wmode, textLine.x - textLine.descent, textLine.y, textLine.textHeight, textLine.textWidth);
				}
				else	// Phase this out after composition is updated to handle inline case correctly
				{
					var lineBounds:Rectangle = getPlacedTextLineBounds(textLine);
					if (textLine.hasGraphicElement)
						lineBounds = computeLineBoundsWithGraphics(textFlowLine, textLine, lineBounds);		
					textFlowLine.cacheLineBounds(wmode, lineBounds.x, lineBounds.y, lineBounds.width, lineBounds.height);
				}
			}
			var rslt:* = (wmode == BlockProgression.TB ? _measureHeight : _measureWidth) ? 0 : textFlowLine.testLineVisible(wmode, scrollXTW, scrollYTW, scrollWidthTW, scrollHeightTW)
			return (rslt == 0) ? (textLine ? textLine : textFlowLine.getTextLine(true)) : rslt;
		}
		
		/** @private 
		 * 	function testLineVisible that was used in old algorithm of gatherVisibleLines()
		 * */
		tlf_internal function oldTestLineVisible(wmode:String, scrollXTW:int, scrollYTW:int, scrollWidthTW:int, scrollHeightTW:int, textFlowLine:TextFlowLine, textLine:TextLine):TextLine
		{
			// So this is another take on figuring out whether the line bounds intersects the visible area of the container. 
			// This code figures out the logical bounds of the line, and uses that for the intersection. There was a 
			// previous version of this code that uses the DisplayObject's getBounds function, which will include information
			// about the children, and also the bounds of visible glyphs. We decided that the logical bounds is close enough,
			// and is much faster to obtain. However, there may be some lines, that get a different result using the logical 
			// bounds than the getBounds. I've left the old code here for verification.
			if (!textFlowLine.hasLineBounds())
			{
				if (!textLine)
					textLine = textFlowLine.getTextLine(true);
				textFlowLine.createShape(wmode, textLine);
				if (textLine.numChildren == 0)
				{
					// Get it the new way
					if (wmode == BlockProgression.TB)
						textFlowLine.cacheLineBounds(wmode, textLine.x, textLine.y - textLine.ascent, textLine.textWidth, textLine.textHeight);
					else
						textFlowLine.cacheLineBounds(wmode, textLine.x - textLine.descent, textLine.y, textLine.textHeight, textLine.textWidth);
				}
				else	// Phase this out after composition is updated to handle inline case correctly
				{
					var lineBounds:Rectangle = getPlacedTextLineBounds(textLine);
					if (textLine.hasGraphicElement)
						lineBounds = computeLineBoundsWithGraphics(textFlowLine, textLine, lineBounds);		
					textFlowLine.cacheLineBounds(wmode, lineBounds.x, lineBounds.y, lineBounds.width, lineBounds.height);
				}
			}
			if ((wmode == BlockProgression.TB ? _measureHeight : _measureWidth) || textFlowLine.oldTestLineVisible(wmode, scrollXTW, scrollYTW, scrollWidthTW, scrollHeightTW))		
				return textLine ? textLine : textFlowLine.getTextLine(true);
			return null;
		}
		
	/*	This code may turn out to be useful for iterating through the floats and doing some function,
		similar to applyFunctionToElements. 
		tlf_internal function applyFunctionToFloats(absoluteStart:int, absoluteEnd:int, func:Function):void
		{ 
			if (_composedFloats)
			{
				var floatIndex:int = findFloatIndexAtOrAfter(absoluteStart);
				var lastFloatIndex:int = findFloatIndexAtOrAfter(absoluteEnd);
				while (floatIndex < lastFloatIndex)
				{
					var floatInfo:FloatCompositionData = _composedFloats[floatIndex];
					if (!func(floatInfo))
						break;
					++floatIndex;
				}
			}
		} */

				
		private function computeLineBoundsWithGraphics(line:TextFlowLine, textLine:TextLine, boundsRect:Rectangle):Rectangle
		{
			if (_composedFloats)
			{
				var floatIndex:int = findFloatIndexAtOrAfter(line.absoluteStart);
				var lastFloatIndex:int = findFloatIndexAtOrAfter(line.absoluteStart + line.textLength);
				var inlineRect:Rectangle = new Rectangle();
				var topLeft:Point = new Point();
				while (floatIndex < lastFloatIndex)
				{
					var floatInfo:FloatCompositionData = _composedFloats[floatIndex];
					if (floatInfo.floatType == Float.NONE)
					{
						var inlineGraphicElement:InlineGraphicElement = textFlow.findLeaf(floatInfo.absolutePosition) as InlineGraphicElement;
						var inlineHolder:DisplayObject = inlineGraphicElement.placeholderGraphic.parent;
						if (inlineHolder)
						{
							inlineRect.x = textLine.x + inlineHolder.x;
							inlineRect.y = textLine.y + inlineHolder.y;
							inlineRect.width = inlineGraphicElement.elementWidth;
							inlineRect.height = inlineGraphicElement.elementHeight;
							boundsRect = boundsRect.union(inlineRect);
						}
					}
					++floatIndex;
				}
			}
			return boundsRect;
		}
		
		/** @private */
		tlf_internal function getPlacedTextLineBounds(textLine:TextLine):Rectangle
		{
			var curBounds:Rectangle;
			curBounds = textLine.getBounds(textLine);
			curBounds.x += textLine.x;
			curBounds.y += textLine.y;
			CONFIG::debug { verifyPlacedTextLineBounds(textLine,curBounds); }
			return curBounds;
		}
		
		CONFIG::debug
		{
			import flash.system.Capabilities;
			// OLD style calculation - lets make sure its the same.  
			static private var tempLineHolder:Sprite = new Sprite();
			
			/** @private */
			tlf_internal function verifyPlacedTextLineBounds(textLine:TextLine,newBounds:Rectangle):void
			{
				// But AIR has a bug so they don't match in AIR
				if (Capabilities.playerType == "Desktop")
					return;
				
				var curBounds:Rectangle;
				if (!textLine.parent)
				{
					// Has to be in the container to get the bounds
					/*addTextLine(textLine,0);
					curBounds = textLine.getBounds(_container);
					removeTextLine(textLine); */
					tempLineHolder.addChildAt(textLine,0);
					curBounds = textLine.getBounds(tempLineHolder);
					tempLineHolder.removeChildAt(0);
					CONFIG::debug { assert(textLine.parent == null,"Bad removeChild in getPlacedTextLineBounds"); }
				}
				else
				{
					// Note: Relative to its parent, which may not be _container
					// but in all reasonable cases, should share its origin with _container -- really???
					curBounds = textLine.getBounds(textLine.parent);
				}
				
				assert(Math.abs(newBounds.x-curBounds.x) <= .1 && Math.abs(newBounds.y-curBounds.y) <= .1 && Math.abs(newBounds.width-curBounds.width) <= .1 && Math.abs(newBounds.height-curBounds.height) <= .1,
					"verifyPlacedTextLineBounds: Bounds are different: "+curBounds.toString()+" : "+newBounds.toString());
			}
		}
		
		/** @private */
		tlf_internal function addComposedLine(textLine:TextLine):void
		{
			_linesInView.push(textLine);			
		}
		
		/** @private Return the array. Client code may add lines to the array. */
		tlf_internal function get composedLines():Array
		{
			if (!_linesInView)
				_linesInView = [];
			return _linesInView;
		}
		
		/** @private Empty out the linesInView, starting from the supplied text index. */
		tlf_internal function clearComposedLines(pos:int):void
		{
			var index:int = 0;
			for each (var textLine:TextLine in _linesInView)
			{
				var tfl:TextFlowLine = textLine.userData as TextFlowLine;
				if (tfl.absoluteStart >= pos)
					break;
				index++;
			}
			_linesInView.length = index;
			_updateStart = Math.min(_updateStart, pos);
		}
		
		/** @private */
		tlf_internal function get numFloats():int
		{
			return _composedFloats ? _composedFloats.length : 0;
		}
		
		/** @private */
		tlf_internal function getFloatAt(index:int):FloatCompositionData
		{
			return _composedFloats[index];
		}
		
		/** @private */
		tlf_internal function getFloatAtPosition(absolutePosition:int):FloatCompositionData
		{
			if (!_composedFloats)
				return null;
			
			var i:int = findFloatIndexAtOrAfter(absolutePosition);
			return (i < _composedFloats.length) ?  _composedFloats[i] : null;
			
		}
		
		/** Add new float info (called by composition when a float is composed into the container
		 * @private
		 */
		tlf_internal function addFloatAt(absolutePosition:int, float:DisplayObject, floatType:String, x:Number, y:Number, alpha:Number, matrix:Matrix, depth:Number, knockOutWidth:Number, columnIndex:int, parent:DisplayObjectContainer):void
		{
		//	trace("addFloatAt", absolutePosition,  "for container", flowComposer.getControllerIndex(this));
			if (!_composedFloats)
				_composedFloats = [];
			var floatInfo:FloatCompositionData = new FloatCompositionData(absolutePosition, float, floatType, x, y, alpha, matrix, depth, knockOutWidth, columnIndex, parent);
			if (_composedFloats.length > 0 && _composedFloats[_composedFloats.length - 1] < absolutePosition)
				_composedFloats.push(floatInfo);
			else
			{
				var index:int = findFloatIndexAtOrAfter(absolutePosition);
				_composedFloats.splice(index, 0, floatInfo);
			} 
			CONFIG::debug { verifyComposedFloats(); }
		}
		
		/** Remove float info for all floats after the given text position
		 * @private
		 */
		tlf_internal function clearFloatsAt(absolutePosition:int):void
		{
		//	trace("clearFloatsAt", absolutePosition,  "for container", flowComposer.getControllerIndex(this));
			if (_composedFloats)
				if (absolutePosition == this.absoluteStart)
					_composedFloats.length = 0;
				else
					_composedFloats.length = findFloatIndexAtOrAfter(absolutePosition);
		}
		
		/** @private */
		CONFIG::debug private function verifyComposedFloats():void
		{
			var previousPosition:int = -1;
			for ( var i:int = 0; i < _composedFloats.length; ++i)
			{
				var floatInfo:FloatCompositionData = _composedFloats[i];
				// Don't allow duplicate entries
				for ( var j:int = i + 1; j < _composedFloats.length && _composedFloats[j].absolutePosition != floatInfo.absolutePosition; ++j) {/* do nothing */}
				assert(j == _composedFloats.length, "Found duplicate entry in ContainerController _composedFloats list");
				// Entries should be ordered
				assert(floatInfo.absolutePosition > previousPosition, "Found out of order float in ContainerController _composedFloats list");
				previousPosition = floatInfo.absolutePosition;
				assert (floatInfo.floatType != Float.START && floatInfo.floatType != Float.END, "Unexpected float type in composed floats array");
			}
		}
		

		/** 
		 * @private
		 * Returns the index in the array of a knockOut at the specified location, or the first knockOut index past that location.
		 */	
		tlf_internal function findFloatIndexAfter(absolutePosition:int):int
		{	
			for (var i:int = 0; i < _composedFloats.length && _composedFloats[i].absolutePosition <= absolutePosition; ++i)
			{
				// do nothing
			}
			return i;
		} 
		
		/** 
		 * @private
		 * Returns the index in the array of a knockOut at the specified location, or the first knockOut index past that location.
		 */	
		tlf_internal function findFloatIndexAtOrAfter(absolutePosition:int):int
		{	
			for (var i:int = 0; i < _composedFloats.length && _composedFloats[i].absolutePosition < absolutePosition; ++i)
			{
				// do nothing
			}
			return i;
		} 
		/** @private */
		tlf_internal function getInteractionHandler():IInteractionEventHandler
		{ return this; }
	}
	
}
import flash.events.MouseEvent;
import flash.display.InteractiveObject;

class PsuedoMouseEvent extends MouseEvent
{
	public function PsuedoMouseEvent(type:String, bubbles:Boolean = true, cancelable:Boolean = false, localX:Number = NaN, localY:Number = NaN, relatedObject:InteractiveObject = null, ctrlKey:Boolean = false, altKey:Boolean = false, shiftKey:Boolean = false, buttonDown:Boolean = false)
	{
		super(type,bubbles,cancelable,localX,localY,relatedObject,ctrlKey,altKey,shiftKey,buttonDown);
	}
	public override function get currentTarget():Object
	{ return relatedObject; }
	public override function get target():Object
	{ return relatedObject; }
}

